summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/2geom/CMakeLists.txt4
-rw-r--r--src/2geom/crossing.cpp20
-rw-r--r--src/2geom/crossing.h1
-rw-r--r--src/2geom/ellipse.cpp7
-rw-r--r--src/2geom/math-utils.h4
-rw-r--r--src/2geom/numeric/symmetric-matrix-fs-operation.h2
-rw-r--r--src/2geom/numeric/symmetric-matrix-fs-trace.h2
-rw-r--r--src/2geom/path-intersection.cpp33
-rw-r--r--src/2geom/path.cpp6
-rw-r--r--src/2geom/svg-path-parser.cpp37
-rw-r--r--src/2geom/toposweep.cpp1
-rw-r--r--src/CMakeLists.txt37
-rw-r--r--src/Makefile.am12
-rw-r--r--src/Makefile_insert28
-rw-r--r--src/attribute-rel-css.cpp1
-rw-r--r--src/attribute-rel-svg.cpp1
-rw-r--r--src/attribute-rel-util.h2
-rw-r--r--src/attributes.cpp34
-rw-r--r--src/attributes.h42
-rw-r--r--src/axis-manip.cpp15
-rw-r--r--src/axis-manip.h37
-rw-r--r--src/box3d-side.cpp9
-rw-r--r--src/box3d-side.h12
-rw-r--r--src/box3d.cpp91
-rw-r--r--src/box3d.h23
-rw-r--r--src/cms-color-types.h5
-rw-r--r--src/cms-system.h8
-rw-r--r--src/color-profile.cpp13
-rw-r--r--src/color-profile.h21
-rw-r--r--src/color-rgba.h5
-rw-r--r--src/color.cpp46
-rw-r--r--src/color.h7
-rw-r--r--src/conn-avoid-ref.h2
-rw-r--r--src/connection-pool.h84
-rw-r--r--src/context-fns.cpp13
-rw-r--r--src/context-fns.h15
-rw-r--r--src/debug/gdk-event-latency-tracker.cpp2
-rw-r--r--src/debug/gdk-event-latency-tracker.h2
-rw-r--r--src/debug/log-display-config.cpp6
-rw-r--r--src/desktop-events.cpp67
-rw-r--r--src/desktop-events.h8
-rw-r--r--src/desktop-style.cpp323
-rw-r--r--src/desktop-style.h11
-rw-r--r--src/desktop.cpp18
-rw-r--r--src/desktop.h37
-rw-r--r--src/dialogs/CMakeLists.txt11
-rw-r--r--src/dialogs/Makefile_insert5
-rw-r--r--src/dialogs/makefile.in17
-rw-r--r--src/dir-util.h6
-rw-r--r--src/display/CMakeLists.txt2
-rw-r--r--src/display/Makefile_insert2
-rw-r--r--src/display/cairo-templates.h3
-rw-r--r--src/display/cairo-utils.cpp97
-rw-r--r--src/display/cairo-utils.h9
-rw-r--r--src/display/canvas-arena.cpp37
-rw-r--r--src/display/canvas-arena.h8
-rw-r--r--src/display/canvas-axonomgrid.cpp3
-rw-r--r--src/display/canvas-axonomgrid.h8
-rw-r--r--src/display/canvas-bpath.cpp37
-rw-r--r--src/display/canvas-grid.cpp36
-rw-r--r--src/display/canvas-grid.h10
-rw-r--r--src/display/canvas-temporary-item-list.cpp5
-rw-r--r--src/display/canvas-temporary-item-list.h5
-rw-r--r--src/display/canvas-temporary-item.cpp8
-rw-r--r--src/display/canvas-temporary-item.h11
-rw-r--r--src/display/canvas-text.cpp39
-rw-r--r--src/display/curve.cpp36
-rw-r--r--src/display/curve.h38
-rw-r--r--src/display/drawing-context.h7
-rw-r--r--src/display/drawing-group.cpp3
-rw-r--r--src/display/drawing-group.h2
-rw-r--r--src/display/drawing-image.cpp11
-rw-r--r--src/display/drawing-item.cpp78
-rw-r--r--src/display/drawing-item.h21
-rw-r--r--src/display/drawing-pattern.cpp194
-rw-r--r--src/display/drawing-pattern.h87
-rw-r--r--src/display/drawing-shape.cpp17
-rw-r--r--src/display/drawing-shape.h4
-rw-r--r--src/display/drawing-surface.h7
-rw-r--r--src/display/drawing-text.cpp506
-rw-r--r--src/display/drawing-text.h6
-rw-r--r--src/display/drawing.h12
-rw-r--r--src/display/gnome-canvas-acetate.cpp29
-rw-r--r--src/display/gnome-canvas-acetate.h8
-rw-r--r--src/display/grayscale.cpp4
-rw-r--r--src/display/grayscale.h6
-rw-r--r--src/display/guideline.cpp34
-rw-r--r--src/display/nr-3dutils.h11
-rw-r--r--src/display/nr-filter-blend.cpp10
-rw-r--r--src/display/nr-filter-blend.h6
-rw-r--r--src/display/nr-filter-colormatrix.h15
-rw-r--r--src/display/nr-filter-component-transfer.h6
-rw-r--r--src/display/nr-filter-composite.h4
-rw-r--r--src/display/nr-filter-convolve-matrix.h8
-rw-r--r--src/display/nr-filter-diffuselighting.h10
-rw-r--r--src/display/nr-filter-displacement-map.h4
-rw-r--r--src/display/nr-filter-flood.h5
-rw-r--r--src/display/nr-filter-gaussian.h4
-rw-r--r--src/display/nr-filter-image.h8
-rw-r--r--src/display/nr-filter-merge.h4
-rw-r--r--src/display/nr-filter-morphology.h4
-rw-r--r--src/display/nr-filter-offset.h4
-rw-r--r--src/display/nr-filter-primitive.h5
-rw-r--r--src/display/nr-filter-skeleton.h4
-rw-r--r--src/display/nr-filter-slot.h10
-rw-r--r--src/display/nr-filter-specularlighting.h12
-rw-r--r--src/display/nr-filter-tile.h4
-rw-r--r--src/display/nr-filter-turbulence.h5
-rw-r--r--src/display/nr-filter-types.h4
-rw-r--r--src/display/nr-filter-units.h4
-rw-r--r--src/display/nr-filter-utils.h7
-rw-r--r--src/display/nr-filter.cpp2
-rw-r--r--src/display/nr-filter.h4
-rw-r--r--src/display/nr-light-types.h4
-rw-r--r--src/display/nr-light.cpp8
-rw-r--r--src/display/nr-light.h34
-rw-r--r--src/display/nr-style.cpp205
-rw-r--r--src/display/nr-style.h20
-rw-r--r--src/display/nr-svgfonts.cpp132
-rw-r--r--src/display/nr-svgfonts.h55
-rw-r--r--src/display/snap-indicator.cpp8
-rw-r--r--src/display/sodipodi-ctrl.cpp37
-rw-r--r--src/display/sodipodi-ctrlrect.cpp38
-rw-r--r--src/display/sodipodi-ctrlrect.h4
-rw-r--r--src/display/sp-canvas-item.h12
-rw-r--r--src/display/sp-canvas-util.h6
-rw-r--r--src/display/sp-canvas.cpp114
-rw-r--r--src/display/sp-canvas.h10
-rw-r--r--src/display/sp-ctrlcurve.cpp41
-rw-r--r--src/display/sp-ctrlcurve.h9
-rw-r--r--src/display/sp-ctrlline.cpp40
-rw-r--r--src/display/sp-ctrlline.h6
-rw-r--r--src/display/sp-ctrlpoint.cpp35
-rw-r--r--src/display/sp-ctrlquadr.cpp34
-rw-r--r--src/document-private.h1
-rw-r--r--src/document-undo.cpp16
-rw-r--r--src/document-undo.h5
-rw-r--r--src/document.cpp159
-rw-r--r--src/document.h56
-rw-r--r--src/ege-color-prof-tracker.cpp9
-rw-r--r--src/event-log.h8
-rw-r--r--src/extension/CMakeLists.txt3
-rw-r--r--src/extension/dbus/Makefile_insert2
-rw-r--r--src/extension/dbus/document-interface.cpp2
-rw-r--r--src/extension/dependency.cpp20
-rw-r--r--src/extension/extension.cpp20
-rw-r--r--src/extension/implementation/implementation.h2
-rw-r--r--src/extension/implementation/script.cpp144
-rw-r--r--src/extension/implementation/script.h80
-rw-r--r--src/extension/implementation/xslt.cpp40
-rw-r--r--src/extension/init.cpp8
-rw-r--r--src/extension/input.h5
-rw-r--r--src/extension/internal/Makefile_insert2
-rw-r--r--src/extension/internal/bitmap/crop.cpp2
-rw-r--r--src/extension/internal/bitmap/opacity.cpp2
-rw-r--r--src/extension/internal/cairo-ps-out.cpp6
-rw-r--r--src/extension/internal/cairo-ps-out.h2
-rw-r--r--src/extension/internal/cairo-render-context.cpp123
-rw-r--r--src/extension/internal/cairo-render-context.h4
-rw-r--r--src/extension/internal/cairo-renderer-pdf-out.cpp2
-rw-r--r--src/extension/internal/cairo-renderer.cpp196
-rw-r--r--src/extension/internal/cairo-renderer.h2
-rw-r--r--src/extension/internal/cdr-input.cpp44
-rw-r--r--src/extension/internal/emf-inout.cpp618
-rw-r--r--src/extension/internal/emf-inout.h92
-rw-r--r--src/extension/internal/emf-print.cpp191
-rw-r--r--src/extension/internal/emf-print.h6
-rw-r--r--src/extension/internal/gdkpixbuf-input.cpp21
-rw-r--r--src/extension/internal/gdkpixbuf-input.h2
-rw-r--r--src/extension/internal/image-resolution.cpp24
-rw-r--r--src/extension/internal/latex-text-renderer.cpp100
-rw-r--r--src/extension/internal/latex-text-renderer.h12
-rw-r--r--src/extension/internal/metafile-inout.cpp90
-rw-r--r--src/extension/internal/metafile-inout.h2
-rw-r--r--src/extension/internal/metafile-print.h2
-rw-r--r--src/extension/internal/pdf-input-cairo.cpp680
-rw-r--r--src/extension/internal/pdf-input-cairo.h157
-rw-r--r--src/extension/internal/pdfinput/pdf-input.cpp259
-rw-r--r--src/extension/internal/pdfinput/pdf-input.h4
-rw-r--r--src/extension/internal/pdfinput/pdf-parser.cpp236
-rw-r--r--src/extension/internal/pdfinput/pdf-parser.h30
-rw-r--r--src/extension/internal/pdfinput/svg-builder.cpp11
-rw-r--r--src/extension/internal/svg.cpp55
-rw-r--r--src/extension/internal/text_reassemble.c20
-rw-r--r--src/extension/internal/vsd-input.cpp45
-rw-r--r--src/extension/internal/wmf-inout.cpp573
-rw-r--r--src/extension/internal/wmf-inout.h79
-rw-r--r--src/extension/internal/wmf-print.cpp6
-rw-r--r--src/extension/internal/wmf-print.h2
-rw-r--r--src/extension/internal/wpg-input.cpp57
-rw-r--r--src/extension/output.h1
-rw-r--r--src/extension/param/color.cpp12
-rw-r--r--src/extension/param/enum.cpp55
-rw-r--r--src/extension/param/notebook.cpp2
-rw-r--r--src/extension/param/radiobutton.cpp2
-rw-r--r--src/extension/prefdialog.cpp9
-rw-r--r--src/extension/system.cpp5
-rw-r--r--src/extract-uri.h4
-rw-r--r--src/factory.h2
-rw-r--r--src/file.cpp28
-rw-r--r--src/file.h8
-rw-r--r--src/filter-chemistry.cpp7
-rw-r--r--src/filter-chemistry.h9
-rw-r--r--src/filter-enums.cpp11
-rw-r--r--src/filters/blend.cpp34
-rw-r--r--src/filters/composite.cpp26
-rw-r--r--src/filters/displacementmap.cpp25
-rw-r--r--src/filters/distantlight.h12
-rw-r--r--src/filters/pointlight.h16
-rw-r--r--src/filters/spotlight.h36
-rw-r--r--src/gc-anchored.h1
-rw-r--r--src/gc-core.h1
-rw-r--r--src/gradient-chemistry.cpp12
-rw-r--r--src/gradient-chemistry.h21
-rw-r--r--src/gradient-drag.cpp11
-rw-r--r--src/graphlayout.cpp4
-rw-r--r--src/graphlayout.h13
-rw-r--r--src/guide-snapper.cpp2
-rw-r--r--src/help.cpp19
-rw-r--r--src/help.h20
-rw-r--r--src/helper-fns.h30
-rw-r--r--src/helper/action.h6
-rw-r--r--src/helper/geom.cpp53
-rw-r--r--src/helper/gnome-utils.cpp148
-rw-r--r--src/helper/gnome-utils.h14
-rw-r--r--src/helper/pixbuf-ops.cpp17
-rw-r--r--src/helper/png-write.cpp2
-rw-r--r--src/helper/stock-items.cpp2
-rw-r--r--src/helper/window.cpp62
-rw-r--r--src/helper/window.h19
-rw-r--r--src/icon-size.h2
-rw-r--r--src/id-clash.cpp134
-rw-r--r--src/inkscape-manifest-x64.xml10
-rw-r--r--src/inkscape-version.h2
-rw-r--r--src/inkscape-x64.rc30
-rw-r--r--src/inkscape.cpp131
-rw-r--r--src/inkscape.h15
-rw-r--r--src/inkscape.rc10
-rw-r--r--src/inkview-manifest-x64.xml10
-rw-r--r--src/inkview-x64.rc29
-rw-r--r--src/inkview.cpp14
-rw-r--r--src/inkview.rc10
-rw-r--r--src/isinf.h2
-rw-r--r--src/isnormal.h19
-rw-r--r--src/knot-holder-entity.cpp34
-rw-r--r--src/knot-holder-entity.h40
-rw-r--r--src/knot-ptr.cpp25
-rw-r--r--src/knot-ptr.h8
-rw-r--r--src/knot.cpp19
-rw-r--r--src/knot.h64
-rw-r--r--src/knotholder.cpp118
-rw-r--r--src/knotholder.h18
-rw-r--r--src/layer-manager.h11
-rw-r--r--src/layer-model.h6
-rw-r--r--src/libavoid/connector.cpp23
-rw-r--r--src/libcroco/cr-rgb.c1
-rw-r--r--src/libcroco/cr-sel-eng.c6
-rw-r--r--src/libdepixelize/CMakeLists.txt4
-rw-r--r--src/libdepixelize/kopftracer2011.cpp2
-rw-r--r--src/libdepixelize/kopftracer2011.h1
-rw-r--r--src/libnrtype/CMakeLists.txt4
-rw-r--r--src/libnrtype/FontFactory.cpp936
-rw-r--r--src/libnrtype/FontFactory.h70
-rw-r--r--src/libnrtype/FontInstance.cpp145
-rw-r--r--src/libnrtype/Layout-TNG-Compute.cpp55
-rw-r--r--src/libnrtype/Layout-TNG-Input.cpp5
-rw-r--r--src/libnrtype/Layout-TNG-Output.cpp3
-rw-r--r--src/libnrtype/Layout-TNG.h3
-rw-r--r--src/libnrtype/Makefile_insert4
-rw-r--r--src/libnrtype/font-instance.h6
-rw-r--r--src/libnrtype/font-lister.cpp1671
-rw-r--r--src/libnrtype/font-lister.h549
-rw-r--r--src/libnrtype/font-style-to-pos.cpp120
-rw-r--r--src/libnrtype/font-style-to-pos.h21
-rw-r--r--src/libnrtype/nr-type-pos-def.cpp268
-rw-r--r--src/libnrtype/nr-type-pos-def.h102
-rw-r--r--src/libnrtype/nr-type-primitives.cpp151
-rw-r--r--src/libnrtype/nr-type-primitives.h21
-rw-r--r--src/libuemf/uemf.c6
-rw-r--r--src/libuemf/uemf.h5
-rw-r--r--src/libuemf/uwmf.c6
-rw-r--r--src/line-geometry.h5
-rw-r--r--src/line-snapper.cpp5
-rw-r--r--src/line-snapper.h5
-rw-r--r--src/livarot/Path.h2
-rw-r--r--src/livarot/PathStroke.cpp18
-rw-r--r--src/live_effects/CMakeLists.txt29
-rw-r--r--src/live_effects/Makefile_insert34
-rw-r--r--src/live_effects/effect-enum.h15
-rw-r--r--src/live_effects/effect.cpp161
-rw-r--r--src/live_effects/effect.h18
-rw-r--r--src/live_effects/lpe-attach-path.cpp198
-rw-r--r--src/live_effects/lpe-attach-path.h52
-rw-r--r--src/live_effects/lpe-bendpath.cpp3
-rw-r--r--src/live_effects/lpe-bounding-box.cpp67
-rw-r--r--src/live_effects/lpe-bounding-box.h37
-rw-r--r--src/live_effects/lpe-bspline.cpp537
-rw-r--r--src/live_effects/lpe-bspline.h54
-rw-r--r--src/live_effects/lpe-copy_rotate.cpp60
-rw-r--r--src/live_effects/lpe-copy_rotate.h5
-rw-r--r--src/live_effects/lpe-ellipse_5pts.cpp214
-rw-r--r--src/live_effects/lpe-ellipse_5pts.h50
-rw-r--r--src/live_effects/lpe-envelope.cpp5
-rw-r--r--src/live_effects/lpe-fill-between-many.cpp78
-rw-r--r--src/live_effects/lpe-fill-between-many.h36
-rw-r--r--src/live_effects/lpe-fill-between-strokes.cpp116
-rw-r--r--src/live_effects/lpe-fill-between-strokes.h38
-rw-r--r--src/live_effects/lpe-fillet-chamfer.cpp660
-rw-r--r--src/live_effects/lpe-fillet-chamfer.h102
-rw-r--r--src/live_effects/lpe-interpolate_points.cpp94
-rw-r--r--src/live_effects/lpe-interpolate_points.h51
-rw-r--r--src/live_effects/lpe-jointype.cpp190
-rw-r--r--src/live_effects/lpe-jointype.h57
-rw-r--r--src/live_effects/lpe-knot.cpp29
-rw-r--r--src/live_effects/lpe-knot.h4
-rw-r--r--src/live_effects/lpe-lattice.cpp3
-rw-r--r--src/live_effects/lpe-lattice.h1
-rw-r--r--src/live_effects/lpe-lattice2.cpp499
-rw-r--r--src/live_effects/lpe-lattice2.h92
-rw-r--r--src/live_effects/lpe-mirror_symmetry.cpp8
-rw-r--r--src/live_effects/lpe-mirror_symmetry.h2
-rw-r--r--src/live_effects/lpe-offset.cpp8
-rw-r--r--src/live_effects/lpe-offset.h2
-rw-r--r--src/live_effects/lpe-perspective-envelope.cpp387
-rw-r--r--src/live_effects/lpe-perspective-envelope.h70
-rw-r--r--src/live_effects/lpe-perspective_path.cpp127
-rw-r--r--src/live_effects/lpe-perspective_path.h6
-rw-r--r--src/live_effects/lpe-powerstroke-interpolators.h127
-rw-r--r--src/live_effects/lpe-powerstroke.cpp124
-rw-r--r--src/live_effects/lpe-powerstroke.h2
-rw-r--r--src/live_effects/lpe-roughen.cpp358
-rw-r--r--src/live_effects/lpe-roughen.h65
-rw-r--r--src/live_effects/lpe-ruler.cpp2
-rw-r--r--src/live_effects/lpe-show_handles.cpp211
-rw-r--r--src/live_effects/lpe-show_handles.h61
-rw-r--r--src/live_effects/lpe-simplify.cpp292
-rw-r--r--src/live_effects/lpe-simplify.h59
-rw-r--r--src/live_effects/lpe-tangent_to_curve.cpp19
-rw-r--r--src/live_effects/lpe-tangent_to_curve.h1
-rw-r--r--src/live_effects/lpe-taperstroke.cpp632
-rw-r--r--src/live_effects/lpe-taperstroke.h72
-rw-r--r--src/live_effects/lpe-vonkoch.cpp12
-rw-r--r--src/live_effects/lpeobject-reference.h6
-rw-r--r--src/live_effects/lpeobject.h4
-rw-r--r--src/live_effects/parameter/Makefile_insert10
-rw-r--r--src/live_effects/parameter/bool.h2
-rw-r--r--src/live_effects/parameter/filletchamferpointarray.cpp881
-rw-r--r--src/live_effects/parameter/filletchamferpointarray.h127
-rw-r--r--src/live_effects/parameter/originalpatharray.cpp487
-rw-r--r--src/live_effects/parameter/originalpatharray.h122
-rw-r--r--src/live_effects/parameter/parameter.cpp37
-rw-r--r--src/live_effects/parameter/parameter.h2
-rw-r--r--src/live_effects/parameter/path.cpp13
-rw-r--r--src/live_effects/parameter/pointreseteable.cpp210
-rw-r--r--src/live_effects/parameter/pointreseteable.h74
-rw-r--r--src/live_effects/parameter/powerstrokepointarray.cpp96
-rw-r--r--src/live_effects/parameter/powerstrokepointarray.h25
-rw-r--r--src/live_effects/parameter/text.cpp2
-rw-r--r--src/live_effects/parameter/togglebutton.cpp172
-rw-r--r--src/live_effects/parameter/togglebutton.h77
-rw-r--r--src/live_effects/parameter/transformedpoint.cpp182
-rw-r--r--src/live_effects/parameter/transformedpoint.h82
-rw-r--r--src/live_effects/pathoutlineprovider.cpp803
-rw-r--r--src/live_effects/pathoutlineprovider.h55
-rw-r--r--src/macros.h11
-rw-r--r--src/main-cmdlineact.h6
-rw-r--r--src/main.cpp39
-rw-r--r--src/menus-skeleton.h3
-rw-r--r--src/message-context.h15
-rw-r--r--src/message-stack.h31
-rw-r--r--src/number-opt-number.h30
-rw-r--r--src/object-hierarchy.cpp23
-rw-r--r--src/object-hierarchy.h3
-rw-r--r--src/object-snapper.cpp55
-rw-r--r--src/object-test.h233
-rw-r--r--src/path-chemistry.cpp65
-rw-r--r--src/path-chemistry.h5
-rw-r--r--src/path-prefix.h50
-rw-r--r--src/persp3d-reference.h7
-rw-r--r--src/persp3d.h15
-rw-r--r--src/perspective-line.cpp6
-rw-r--r--src/perspective-line.h1
-rw-r--r--src/preferences-skeleton.h6
-rw-r--r--src/preferences.cpp4
-rw-r--r--src/preferences.h6
-rw-r--r--src/prefix.cpp5
-rw-r--r--src/prefix.h2
-rw-r--r--src/print.h8
-rw-r--r--src/profile-manager.h5
-rw-r--r--src/proj_pt.cpp20
-rw-r--r--src/proj_pt.h28
-rw-r--r--src/rdf.h39
-rw-r--r--src/removeoverlap.h2
-rw-r--r--src/rubberband.h10
-rw-r--r--src/satisfied-guide-cns.h2
-rw-r--r--src/selcue.h8
-rw-r--r--src/selection-chemistry.cpp833
-rw-r--r--src/selection-chemistry.h33
-rw-r--r--src/selection-describer.cpp93
-rw-r--r--src/selection-describer.h6
-rw-r--r--src/selection.h21
-rw-r--r--src/seltrans-handles.h14
-rw-r--r--src/seltrans.cpp144
-rw-r--r--src/seltrans.h67
-rw-r--r--src/shape-editor.cpp255
-rw-r--r--src/shape-editor.h95
-rw-r--r--src/shortcuts.h11
-rw-r--r--src/snap-candidate.h5
-rw-r--r--src/snap-preferences.h18
-rw-r--r--src/snap.cpp99
-rw-r--r--src/snap.h1
-rw-r--r--src/snapped-curve.h6
-rw-r--r--src/snapped-point.h7
-rw-r--r--src/snapper.h13
-rw-r--r--src/sp-anchor.h14
-rw-r--r--src/sp-clippath.h21
-rw-r--r--src/sp-conn-end-pair.h18
-rw-r--r--src/sp-conn-end.h13
-rw-r--r--src/sp-cursor.cpp9
-rw-r--r--src/sp-cursor.h9
-rw-r--r--src/sp-defs.h2
-rw-r--r--src/sp-desc.h6
-rw-r--r--src/sp-ellipse.cpp112
-rw-r--r--src/sp-ellipse.h22
-rw-r--r--src/sp-filter-primitive.cpp5
-rw-r--r--src/sp-filter-primitive.h12
-rw-r--r--src/sp-filter.cpp9
-rw-r--r--src/sp-filter.h17
-rw-r--r--src/sp-flowdiv.h26
-rw-r--r--src/sp-flowregion.cpp65
-rw-r--r--src/sp-flowregion.h8
-rw-r--r--src/sp-flowtext.cpp182
-rw-r--r--src/sp-flowtext.h18
-rw-r--r--src/sp-font-face.h12
-rw-r--r--src/sp-font.h8
-rw-r--r--src/sp-glyph-kerning.cpp133
-rw-r--r--src/sp-glyph-kerning.h73
-rw-r--r--src/sp-glyph.cpp162
-rw-r--r--src/sp-glyph.h48
-rw-r--r--src/sp-gradient-vector.h5
-rw-r--r--src/sp-gradient.cpp100
-rw-r--r--src/sp-gradient.h48
-rw-r--r--src/sp-guide-constraint.h2
-rw-r--r--src/sp-guide.cpp336
-rw-r--r--src/sp-guide.h78
-rw-r--r--src/sp-hatch-path.cpp361
-rw-r--r--src/sp-hatch-path.h95
-rw-r--r--src/sp-hatch.cpp756
-rw-r--r--src/sp-hatch.h186
-rw-r--r--src/sp-image.cpp1
-rw-r--r--src/sp-image.h13
-rw-r--r--src/sp-item-group.cpp332
-rw-r--r--src/sp-item-group.h27
-rw-r--r--src/sp-item-notify-moveto.cpp11
-rw-r--r--src/sp-item-transform.cpp2
-rw-r--r--src/sp-item-transform.h9
-rw-r--r--src/sp-item.cpp456
-rw-r--r--src/sp-item.h203
-rw-r--r--src/sp-line.h6
-rw-r--r--src/sp-linear-gradient.cpp2
-rw-r--r--src/sp-linear-gradient.h4
-rw-r--r--src/sp-lpe-item.cpp286
-rw-r--r--src/sp-lpe-item.h15
-rw-r--r--src/sp-marker.cpp (renamed from src/marker.cpp)43
-rw-r--r--src/sp-marker.h (renamed from src/marker.h)18
-rw-r--r--src/sp-mask.h16
-rw-r--r--src/sp-mesh-array.cpp16
-rw-r--r--src/sp-mesh-array.h64
-rw-r--r--src/sp-mesh-gradient.cpp6
-rw-r--r--src/sp-mesh-gradient.h4
-rw-r--r--src/sp-mesh-patch.h6
-rw-r--r--src/sp-mesh-row.h5
-rw-r--r--src/sp-metadata.h9
-rw-r--r--src/sp-missing-glyph.h12
-rw-r--r--src/sp-namedview.cpp23
-rw-r--r--src/sp-namedview.h31
-rw-r--r--src/sp-object-group.h2
-rw-r--r--src/sp-object.cpp37
-rw-r--r--src/sp-object.h91
-rw-r--r--src/sp-offset.cpp5
-rw-r--r--src/sp-offset.h18
-rw-r--r--src/sp-paint-server-reference.h3
-rw-r--r--src/sp-paint-server.cpp23
-rw-r--r--src/sp-paint-server.h58
-rw-r--r--src/sp-path.cpp17
-rw-r--r--src/sp-path.h10
-rw-r--r--src/sp-pattern.cpp21
-rw-r--r--src/sp-pattern.h39
-rw-r--r--src/sp-polygon.h13
-rw-r--r--src/sp-polyline.h6
-rw-r--r--src/sp-radial-gradient.cpp2
-rw-r--r--src/sp-radial-gradient.h8
-rw-r--r--src/sp-rect.h32
-rw-r--r--src/sp-root.h8
-rw-r--r--src/sp-script.h14
-rw-r--r--src/sp-shape.cpp152
-rw-r--r--src/sp-shape.h19
-rw-r--r--src/sp-solid-color.cpp99
-rw-r--r--src/sp-solid-color.h48
-rw-r--r--src/sp-spiral.h16
-rw-r--r--src/sp-star.cpp3
-rw-r--r--src/sp-star.h18
-rw-r--r--src/sp-stop.h13
-rw-r--r--src/sp-string.cpp120
-rw-r--r--src/sp-string.h4
-rw-r--r--src/sp-style-elem.cpp54
-rw-r--r--src/sp-style-elem.h7
-rw-r--r--src/sp-switch.h10
-rw-r--r--src/sp-symbol.h18
-rw-r--r--src/sp-tag-use-reference.cpp156
-rw-r--r--src/sp-tag-use-reference.h78
-rw-r--r--src/sp-tag-use.cpp206
-rw-r--r--src/sp-tag-use.h55
-rw-r--r--src/sp-tag.cpp154
-rw-r--r--src/sp-tag.h57
-rw-r--r--src/sp-text.cpp57
-rw-r--r--src/sp-text.h24
-rw-r--r--src/sp-textpath.h7
-rw-r--r--src/sp-title.h6
-rw-r--r--src/sp-tref-reference.h8
-rw-r--r--src/sp-tref.cpp7
-rw-r--r--src/sp-tref.h6
-rw-r--r--src/sp-tspan.cpp5
-rw-r--r--src/sp-tspan.h7
-rw-r--r--src/sp-use-reference.h8
-rw-r--r--src/sp-use.cpp106
-rw-r--r--src/sp-use.h20
-rw-r--r--src/splivarot.cpp33
-rw-r--r--src/splivarot.h7
-rw-r--r--src/streq.h1
-rw-r--r--src/style-enums.h282
-rw-r--r--src/style-internal.cpp2648
-rw-r--r--src/style-internal.h1162
-rw-r--r--src/style-test.h336
-rw-r--r--src/style.cpp5384
-rw-r--r--src/style.h237
-rw-r--r--src/svg-view-widget.cpp64
-rw-r--r--src/svg-view-widget.h2
-rw-r--r--src/svg-view.h13
-rw-r--r--src/svg/CMakeLists.txt2
-rw-r--r--src/svg/Makefile_insert2
-rw-r--r--src/svg/css-ostringstream.h5
-rw-r--r--src/svg/path-string.h4
-rw-r--r--src/svg/stringstream-test.h6
-rw-r--r--src/svg/stringstream.h5
-rw-r--r--src/svg/svg-affine-test.h14
-rw-r--r--src/svg/svg-affine.cpp157
-rw-r--r--src/svg/svg-angle.cpp140
-rw-r--r--src/svg/svg-angle.h69
-rw-r--r--src/svg/svg-color.cpp58
-rw-r--r--src/svg/svg-color.h13
-rw-r--r--src/svg/svg-length-test.h14
-rw-r--r--src/svg/svg-length.cpp13
-rw-r--r--src/svg/svg-length.h24
-rw-r--r--src/svg/svg-path.cpp51
-rw-r--r--src/svg/svg.h24
-rw-r--r--src/text-chemistry.h2
-rw-r--r--src/text-editing.cpp4
-rw-r--r--src/text-editing.h29
-rw-r--r--src/transf_mat_3x4.cpp8
-rw-r--r--src/transf_mat_3x4.h4
-rw-r--r--src/ui/CMakeLists.txt19
-rw-r--r--src/ui/Makefile_insert13
-rw-r--r--src/ui/clipboard.cpp150
-rw-r--r--src/ui/dialog-events.cpp (renamed from src/dialogs/dialog-events.cpp)4
-rw-r--r--src/ui/dialog-events.h (renamed from src/dialogs/dialog-events.h)6
-rw-r--r--src/ui/dialog/Makefile_insert8
-rw-r--r--src/ui/dialog/aboutbox.cpp40
-rw-r--r--src/ui/dialog/aboutbox.h6
-rw-r--r--src/ui/dialog/align-and-distribute.cpp8
-rw-r--r--src/ui/dialog/calligraphic-profile-rename.h2
-rw-r--r--src/ui/dialog/clonetiler.cpp51
-rw-r--r--src/ui/dialog/clonetiler.h5
-rw-r--r--src/ui/dialog/color-item.cpp2
-rw-r--r--src/ui/dialog/desktop-tracker.cpp2
-rw-r--r--src/ui/dialog/desktop-tracker.h5
-rw-r--r--src/ui/dialog/dialog-manager.cpp25
-rw-r--r--src/ui/dialog/dialog.cpp20
-rw-r--r--src/ui/dialog/dialog.h4
-rw-r--r--src/ui/dialog/dock-behavior.cpp4
-rw-r--r--src/ui/dialog/document-metadata.cpp4
-rw-r--r--src/ui/dialog/document-metadata.h4
-rw-r--r--src/ui/dialog/document-properties.cpp65
-rw-r--r--src/ui/dialog/document-properties.h4
-rw-r--r--src/ui/dialog/export.cpp6
-rw-r--r--src/ui/dialog/export.h9
-rw-r--r--src/ui/dialog/extension-editor.cpp2
-rw-r--r--src/ui/dialog/filedialog.cpp2
-rw-r--r--src/ui/dialog/filedialog.h1
-rw-r--r--src/ui/dialog/filedialogimpl-gtkmm.cpp47
-rw-r--r--src/ui/dialog/filedialogimpl-win32.cpp14
-rw-r--r--src/ui/dialog/filedialogimpl-win32.h11
-rw-r--r--src/ui/dialog/fill-and-stroke.h2
-rw-r--r--src/ui/dialog/filter-effects-dialog.cpp2
-rw-r--r--src/ui/dialog/find.cpp97
-rw-r--r--src/ui/dialog/floating-behavior.cpp4
-rw-r--r--src/ui/dialog/font-substitution.cpp20
-rw-r--r--src/ui/dialog/grid-arrange-tab.cpp4
-rw-r--r--src/ui/dialog/grid-arrange-tab.h8
-rw-r--r--src/ui/dialog/guides.cpp23
-rw-r--r--src/ui/dialog/inkscape-preferences.cpp42
-rw-r--r--src/ui/dialog/inkscape-preferences.h6
-rw-r--r--src/ui/dialog/input.cpp2
-rw-r--r--src/ui/dialog/layers.cpp12
-rw-r--r--src/ui/dialog/livepatheffect-add.cpp14
-rw-r--r--src/ui/dialog/livepatheffect-add.h4
-rw-r--r--src/ui/dialog/livepatheffect-editor.cpp127
-rw-r--r--src/ui/dialog/lpe-fillet-chamfer-properties.cpp301
-rw-r--r--src/ui/dialog/lpe-fillet-chamfer-properties.h115
-rw-r--r--src/ui/dialog/lpe-powerstroke-properties.cpp211
-rw-r--r--src/ui/dialog/lpe-powerstroke-properties.h99
-rw-r--r--src/ui/dialog/new-from-template.cpp15
-rw-r--r--src/ui/dialog/objects.cpp2144
-rw-r--r--src/ui/dialog/objects.h263
-rw-r--r--src/ui/dialog/ocaldialogs.cpp4
-rw-r--r--src/ui/dialog/ocaldialogs.h3
-rw-r--r--src/ui/dialog/panel-dialog.h12
-rw-r--r--src/ui/dialog/pixelartdialog.cpp4
-rw-r--r--src/ui/dialog/polar-arrange-tab.cpp32
-rw-r--r--src/ui/dialog/polar-arrange-tab.h19
-rw-r--r--src/ui/dialog/print.cpp12
-rw-r--r--src/ui/dialog/spellcheck.cpp78
-rw-r--r--src/ui/dialog/swatches.cpp103
-rw-r--r--src/ui/dialog/swatches.h2
-rw-r--r--src/ui/dialog/symbols.cpp121
-rw-r--r--src/ui/dialog/symbols.h9
-rw-r--r--src/ui/dialog/tags.cpp1166
-rw-r--r--src/ui/dialog/tags.h181
-rw-r--r--src/ui/dialog/template-load-tab.cpp2
-rw-r--r--src/ui/dialog/template-widget.cpp8
-rw-r--r--src/ui/dialog/text-edit.cpp17
-rw-r--r--src/ui/dialog/transformation.cpp4
-rw-r--r--src/ui/dialog/xml-tree.cpp5
-rw-r--r--src/ui/draw-anchor.cpp (renamed from src/draw-anchor.cpp)6
-rw-r--r--src/ui/draw-anchor.h (renamed from src/draw-anchor.h)9
-rw-r--r--src/ui/interface.cpp (renamed from src/interface.cpp)17
-rw-r--r--src/ui/interface.h (renamed from src/interface.h)19
-rw-r--r--src/ui/object-edit.cpp (renamed from src/object-edit.cpp)359
-rw-r--r--src/ui/object-edit.h (renamed from src/object-edit.h)5
-rw-r--r--src/ui/shape-editor.cpp177
-rw-r--r--src/ui/shape-editor.h71
-rw-r--r--src/ui/tool-factory.h (renamed from src/tool-factory.h)0
-rw-r--r--src/ui/tool/control-point-selection.cpp49
-rw-r--r--src/ui/tool/control-point-selection.h13
-rw-r--r--src/ui/tool/curve-drag-point.cpp17
-rw-r--r--src/ui/tool/multi-path-manipulator.cpp21
-rw-r--r--src/ui/tool/multi-path-manipulator.h5
-rw-r--r--src/ui/tool/node.cpp248
-rw-r--r--src/ui/tool/node.h15
-rw-r--r--src/ui/tool/path-manipulator.cpp170
-rw-r--r--src/ui/tool/path-manipulator.h12
-rw-r--r--src/ui/tool/selectable-control-point.h1
-rw-r--r--src/ui/tools-switch.cpp (renamed from src/tools-switch.cpp)80
-rw-r--r--src/ui/tools-switch.h (renamed from src/tools-switch.h)0
-rw-r--r--src/ui/tools/arc-tool.cpp10
-rw-r--r--src/ui/tools/arc-tool.h2
-rw-r--r--src/ui/tools/box3d-tool.cpp10
-rw-r--r--src/ui/tools/calligraphic-tool.cpp2
-rw-r--r--src/ui/tools/connector-tool.cpp2
-rw-r--r--src/ui/tools/dropper-tool.cpp2
-rw-r--r--src/ui/tools/eraser-tool.cpp2
-rw-r--r--src/ui/tools/flood-tool.cpp10
-rw-r--r--src/ui/tools/flood-tool.h4
-rw-r--r--src/ui/tools/freehand-base.cpp232
-rw-r--r--src/ui/tools/freehand-base.h6
-rw-r--r--src/ui/tools/gradient-tool.cpp19
-rw-r--r--src/ui/tools/lpe-tool.cpp11
-rw-r--r--src/ui/tools/measure-tool.cpp61
-rw-r--r--src/ui/tools/mesh-tool.cpp2
-rw-r--r--src/ui/tools/node-tool.cpp74
-rw-r--r--src/ui/tools/node-tool.h5
-rw-r--r--src/ui/tools/pen-tool.cpp1034
-rw-r--r--src/ui/tools/pen-tool.h31
-rw-r--r--src/ui/tools/pencil-tool.cpp48
-rw-r--r--src/ui/tools/rect-tool.cpp10
-rw-r--r--src/ui/tools/rect-tool.h4
-rw-r--r--src/ui/tools/select-tool.cpp82
-rw-r--r--src/ui/tools/select-tool.h1
-rw-r--r--src/ui/tools/spiral-tool.cpp10
-rw-r--r--src/ui/tools/spiral-tool.h8
-rw-r--r--src/ui/tools/spray-tool.cpp36
-rw-r--r--src/ui/tools/star-tool.cpp10
-rw-r--r--src/ui/tools/text-tool.cpp10
-rw-r--r--src/ui/tools/text-tool.h7
-rw-r--r--src/ui/tools/tool-base.cpp20
-rw-r--r--src/ui/tools/tool-base.h4
-rw-r--r--src/ui/tools/tweak-tool.cpp88
-rw-r--r--src/ui/tools/zoom-tool.cpp2
-rw-r--r--src/ui/view/view-widget.cpp31
-rw-r--r--src/ui/widget/Makefile_insert13
-rw-r--r--src/ui/widget/addtoicon.cpp156
-rw-r--r--src/ui/widget/addtoicon.h98
-rw-r--r--src/ui/widget/anchor-selector.cpp16
-rw-r--r--src/ui/widget/anchor-selector.h20
-rw-r--r--src/ui/widget/button.cpp6
-rw-r--r--src/ui/widget/button.h6
-rw-r--r--src/ui/widget/clipmaskicon.cpp183
-rw-r--r--src/ui/widget/clipmaskicon.h102
-rw-r--r--src/ui/widget/color-picker.cpp2
-rw-r--r--src/ui/widget/entity-entry.cpp4
-rw-r--r--src/ui/widget/entity-entry.h4
-rw-r--r--src/ui/widget/filter-effect-chooser.cpp15
-rw-r--r--src/ui/widget/filter-effect-chooser.h4
-rw-r--r--src/ui/widget/highlight-picker.cpp206
-rw-r--r--src/ui/widget/highlight-picker.h90
-rw-r--r--src/ui/widget/insertordericon.cpp164
-rw-r--r--src/ui/widget/insertordericon.h100
-rw-r--r--src/ui/widget/layertypeicon.cpp174
-rw-r--r--src/ui/widget/layertypeicon.h108
-rw-r--r--src/ui/widget/licensor.cpp4
-rw-r--r--src/ui/widget/licensor.h4
-rw-r--r--src/ui/widget/notebook-page.cpp6
-rw-r--r--src/ui/widget/notebook-page.h6
-rw-r--r--src/ui/widget/object-composite-settings.cpp4
-rw-r--r--src/ui/widget/object-composite-settings.h6
-rw-r--r--src/ui/widget/page-sizer.cpp8
-rw-r--r--src/ui/widget/page-sizer.h4
-rw-r--r--src/ui/widget/panel.cpp4
-rw-r--r--src/ui/widget/panel.h12
-rw-r--r--src/ui/widget/preferences-widget.cpp8
-rw-r--r--src/ui/widget/preferences-widget.h4
-rw-r--r--src/ui/widget/registered-widget.cpp57
-rw-r--r--src/ui/widget/registered-widget.h29
-rw-r--r--src/ui/widget/registry.cpp4
-rw-r--r--src/ui/widget/registry.h4
-rw-r--r--src/ui/widget/rendering-options.cpp18
-rw-r--r--src/ui/widget/rotateable.cpp6
-rw-r--r--src/ui/widget/rotateable.h4
-rw-r--r--src/ui/widget/selected-style.cpp35
-rw-r--r--src/ui/widget/selected-style.h17
-rw-r--r--src/ui/widget/spin-scale.cpp6
-rw-r--r--src/ui/widget/spin-scale.h6
-rw-r--r--src/ui/widget/spin-slider.cpp6
-rw-r--r--src/ui/widget/spin-slider.h6
-rw-r--r--src/ui/widget/spinbutton.cpp6
-rw-r--r--src/ui/widget/spinbutton.h6
-rw-r--r--src/ui/widget/style-subject.h2
-rw-r--r--src/ui/widget/style-swatch.cpp6
-rw-r--r--src/ui/widget/style-swatch.h8
-rw-r--r--src/ui/widget/tolerance-slider.cpp4
-rw-r--r--src/ui/widget/tolerance-slider.h4
-rw-r--r--src/ui/widget/unit-menu.cpp6
-rw-r--r--src/ui/widget/unit-menu.h4
-rw-r--r--src/ui/widget/unit-tracker.cpp2
-rw-r--r--src/ui/widget/unit-tracker.h7
-rw-r--r--src/unclump.cpp1
-rw-r--r--src/unclump.h2
-rw-r--r--src/unicoderange.h14
-rw-r--r--src/uri-references.cpp6
-rw-r--r--src/uri-references.h14
-rw-r--r--src/uri.h35
-rw-r--r--src/util/CMakeLists.txt3
-rw-r--r--src/util/Makefile_insert1
-rw-r--r--src/util/units.cpp7
-rw-r--r--src/vanishing-point.cpp54
-rw-r--r--src/vanishing-point.h12
-rw-r--r--src/verbs.cpp133
-rw-r--r--src/verbs.h56
-rw-r--r--src/version.cpp22
-rw-r--r--src/version.h12
-rw-r--r--src/viewbox.cpp21
-rw-r--r--src/widgets/CMakeLists.txt10
-rw-r--r--src/widgets/Makefile_insert10
-rw-r--r--src/widgets/arc-toolbar.cpp28
-rw-r--r--src/widgets/box3d-toolbar.cpp28
-rw-r--r--src/widgets/button.cpp381
-rw-r--r--src/widgets/button.h31
-rw-r--r--src/widgets/calligraphy-toolbar.cpp6
-rw-r--r--src/widgets/connector-toolbar.cpp4
-rw-r--r--src/widgets/dash-selector.cpp2
-rw-r--r--src/widgets/desktop-widget.cpp9
-rw-r--r--src/widgets/dropper-toolbar.cpp4
-rw-r--r--src/widgets/eek-preview.h1
-rw-r--r--src/widgets/ege-adjustment-action.cpp (renamed from src/ege-adjustment-action.cpp)2
-rw-r--r--src/widgets/ege-adjustment-action.h (renamed from src/ege-adjustment-action.h)2
-rw-r--r--src/widgets/ege-output-action.cpp (renamed from src/ege-output-action.cpp)2
-rw-r--r--src/widgets/ege-output-action.h (renamed from src/ege-output-action.h)2
-rw-r--r--src/widgets/ege-paint-def.cpp1
-rw-r--r--src/widgets/ege-select-one-action.cpp (renamed from src/ege-select-one-action.cpp)2
-rw-r--r--src/widgets/ege-select-one-action.h (renamed from src/ege-select-one-action.h)2
-rw-r--r--src/widgets/eraser-toolbar.cpp6
-rw-r--r--src/widgets/font-selector.cpp89
-rw-r--r--src/widgets/font-selector.h4
-rw-r--r--src/widgets/gradient-image.cpp56
-rw-r--r--src/widgets/gradient-image.h30
-rw-r--r--src/widgets/gradient-selector.cpp54
-rw-r--r--src/widgets/gradient-selector.h31
-rw-r--r--src/widgets/gradient-toolbar.cpp83
-rw-r--r--src/widgets/gradient-vector.cpp72
-rw-r--r--src/widgets/gradient-vector.h16
-rw-r--r--src/widgets/icon.cpp5
-rw-r--r--src/widgets/icon.h8
-rw-r--r--src/widgets/ink-action.cpp (renamed from src/ink-action.cpp)2
-rw-r--r--src/widgets/ink-action.h (renamed from src/ink-action.h)2
-rw-r--r--src/widgets/ink-comboboxentry-action.cpp (renamed from src/ink-comboboxentry-action.cpp)48
-rw-r--r--src/widgets/ink-comboboxentry-action.h (renamed from src/ink-comboboxentry-action.h)4
-rw-r--r--src/widgets/lpe-toolbar.cpp41
-rw-r--r--src/widgets/mappings.xml1
-rw-r--r--src/widgets/measure-toolbar.cpp4
-rw-r--r--src/widgets/mesh-toolbar.cpp88
-rw-r--r--src/widgets/node-toolbar.cpp53
-rw-r--r--src/widgets/paint-selector.cpp101
-rw-r--r--src/widgets/paint-selector.h20
-rw-r--r--src/widgets/paintbucket-toolbar.cpp6
-rw-r--r--src/widgets/pencil-toolbar.cpp17
-rw-r--r--src/widgets/rect-toolbar.cpp31
-rw-r--r--src/widgets/ruler.cpp2
-rw-r--r--src/widgets/select-toolbar.cpp6
-rw-r--r--src/widgets/sp-color-icc-selector.cpp45
-rw-r--r--src/widgets/sp-color-icc-selector.h2
-rw-r--r--src/widgets/sp-color-notebook.cpp50
-rw-r--r--src/widgets/sp-color-notebook.h4
-rw-r--r--src/widgets/sp-color-scales.cpp54
-rw-r--r--src/widgets/sp-color-scales.h5
-rw-r--r--src/widgets/sp-color-selector.cpp42
-rw-r--r--src/widgets/sp-color-selector.h12
-rw-r--r--src/widgets/sp-color-slider.cpp30
-rw-r--r--src/widgets/sp-color-slider.h7
-rw-r--r--src/widgets/sp-color-wheel-selector.cpp54
-rw-r--r--src/widgets/sp-color-wheel-selector.h5
-rw-r--r--src/widgets/sp-widget.cpp79
-rw-r--r--src/widgets/sp-widget.h18
-rw-r--r--src/widgets/sp-xmlview-attr-list.cpp34
-rw-r--r--src/widgets/sp-xmlview-attr-list.h3
-rw-r--r--src/widgets/sp-xmlview-content.cpp34
-rw-r--r--src/widgets/sp-xmlview-content.h3
-rw-r--r--src/widgets/sp-xmlview-tree.cpp42
-rw-r--r--src/widgets/sp-xmlview-tree.h17
-rw-r--r--src/widgets/spinbutton-events.h4
-rw-r--r--src/widgets/spiral-toolbar.cpp6
-rw-r--r--src/widgets/spray-toolbar.cpp6
-rw-r--r--src/widgets/spw-utilities.cpp11
-rw-r--r--src/widgets/star-toolbar.cpp31
-rw-r--r--src/widgets/stroke-marker-selector.cpp6
-rw-r--r--src/widgets/stroke-style.cpp21
-rw-r--r--src/widgets/stroke-style.h6
-rw-r--r--src/widgets/text-toolbar.cpp94
-rw-r--r--src/widgets/toolbox.cpp21
-rw-r--r--src/widgets/toolbox.h6
-rw-r--r--src/widgets/tweak-toolbar.cpp8
-rw-r--r--src/xml/event.h2
-rw-r--r--src/xml/helper-observer.cpp13
-rw-r--r--src/xml/helper-observer.h69
-rw-r--r--src/xml/node-event-vector.h42
-rw-r--r--src/xml/node-observer.h6
-rw-r--r--src/xml/node.h15
-rw-r--r--src/xml/pi-node.h1
-rw-r--r--src/xml/quote.h2
-rw-r--r--src/xml/rebase-hrefs.h9
-rw-r--r--src/xml/repr-css.cpp43
-rw-r--r--src/xml/repr-io.cpp1
-rw-r--r--src/xml/repr.h85
-rw-r--r--src/xml/simple-node.h18
853 files changed, 39325 insertions, 17614 deletions
diff --git a/src/2geom/CMakeLists.txt b/src/2geom/CMakeLists.txt
index b1c30f678..eeaecaa39 100644
--- a/src/2geom/CMakeLists.txt
+++ b/src/2geom/CMakeLists.txt
@@ -21,6 +21,7 @@ set(2geom_SRC
nearest-point.cpp
numeric/matrix.cpp
path-intersection.cpp
+ path-sink.cpp
path.cpp
pathvector.cpp
piecewise.cpp
@@ -43,7 +44,6 @@ set(2geom_SRC
solve-bezier-parametric.cpp
svg-elliptical-arc.cpp
svg-path-parser.cpp
- svg-path.cpp
sweep.cpp
toposweep.cpp
transforms.cpp
@@ -94,6 +94,7 @@ set(2geom_SRC
nearest-point.h
ord.h
path-intersection.h
+ path-sink.h
path.h
pathvector.h
piecewise.h
@@ -115,7 +116,6 @@ set(2geom_SRC
solver.h
svg-elliptical-arc.h
svg-path-parser.h
- svg-path.h
sweep.h
toposweep.h
transforms.h
diff --git a/src/2geom/crossing.cpp b/src/2geom/crossing.cpp
index 13affa8e9..513327271 100644
--- a/src/2geom/crossing.cpp
+++ b/src/2geom/crossing.cpp
@@ -154,7 +154,6 @@ Crossings reverse_tb(Crossings const &cr, unsigned split, std::vector<double> ma
Crossings ret;
for(Crossings::const_iterator i = cr.begin(); i != cr.end(); ++i) {
double mx = max[i->b - split];
- std::cout << i->b << "\n";
ret.push_back(Crossing(i->ta, i->tb > mx+0.01 ? (1 - (i->tb - mx) + mx) : mx - i->tb,
!i->dir));
}
@@ -181,6 +180,25 @@ CrossingSet reverse_tb(CrossingSet const &cr, unsigned split, std::vector<double
return ret;
}
+// Delete any duplicates in a vector of crossings
+// A crossing is considered to be a duplicate when it has both t_a and t_b near to another crossing's t_a and t_b
+// For example, duplicates will be found when calculating the intersections of a linesegment with a polygon, if the
+// endpoint of that line coincides with a cusp node of the polygon. In that case, an intersection will be found of
+// the linesegment with each of the polygon's linesegments extending from the cusp node (i.e. two intersections)
+void delete_duplicates(Crossings &crs) {
+ Crossings::reverse_iterator rit = crs.rbegin();
+
+ for (rit = crs.rbegin(); rit!= crs.rend(); ++rit) {
+ Crossings::reverse_iterator rit2 = rit;
+ while (++rit2 != crs.rend()) {
+ if (Geom::are_near((*rit).ta, (*rit2).ta) && Geom::are_near((*rit).tb, (*rit2).tb)) {
+ crs.erase((rit + 1).base()); // This +1 and .base() construction is needed to convert to a regular iterator
+ break; // out of while loop, and continue with next iteration of for loop
+ }
+ }
+ }
+}
+
void clean(Crossings &/*cr_a*/, Crossings &/*cr_b*/) {
/* if(cr_a.empty()) return;
diff --git a/src/2geom/crossing.h b/src/2geom/crossing.h
index 75c75fc24..d5012ae2b 100644
--- a/src/2geom/crossing.h
+++ b/src/2geom/crossing.h
@@ -183,6 +183,7 @@ CrossingSet reverse_ta(CrossingSet const &cr, unsigned split, std::vector<double
CrossingSet reverse_tb(CrossingSet const &cr, unsigned split, std::vector<double> max);
void clean(Crossings &cr_a, Crossings &cr_b);
+void delete_duplicates(Crossings &crs);
}
diff --git a/src/2geom/ellipse.cpp b/src/2geom/ellipse.cpp
index bea99e5dd..2686844b2 100644
--- a/src/2geom/ellipse.cpp
+++ b/src/2geom/ellipse.cpp
@@ -36,6 +36,7 @@
#include <2geom/numeric/fitting-tool.h>
#include <2geom/numeric/fitting-model.h>
+using std::swap;
namespace Geom
{
@@ -102,7 +103,7 @@ void Ellipse::set(double A, double B, double C, double D, double E, double F)
// the solution is not unique so we choose always the ellipse
// with a rotation angle between 0 and PI/2
- if ( swap_axes ) std::swap(rx, ry);
+ if ( swap_axes ) swap(rx, ry);
if ( are_near(rot, M_PI/2)
|| are_near(rot, -M_PI/2)
|| are_near(rx, ry) )
@@ -233,7 +234,7 @@ Ellipse Ellipse::transformed(Affine const& m) const
Point new_center = center() * m;
Affine M = m.withoutTranslation();
Affine AM = A * M;
- if ( are_near(AM.det(), 0) )
+ if ( are_near(std::sqrt(fabs(AM.det())), 0) )
{
double angle;
if (AM[0] != 0)
@@ -262,7 +263,7 @@ Ellipse Ellipse::transformed(Affine const& m) const
Affine invm = M.inverse();
Q = invm * Q ;
- std::swap( invm[1], invm[2] );
+ swap( invm[1], invm[2] );
Q *= invm;
Ellipse e(Q[0], 2*Q[1], Q[3], 0, 0, -1);
e.m_centre = new_center;
diff --git a/src/2geom/math-utils.h b/src/2geom/math-utils.h
index 83c7b4f5e..0d5d3667b 100644
--- a/src/2geom/math-utils.h
+++ b/src/2geom/math-utils.h
@@ -111,7 +111,7 @@ inline void sincos(double angle, double &sin_, double &cos_) {
# define IS_NAN(_a) (_isnan(_a)) /* Win32 definition */
#elif defined(isnan) || defined(__FreeBSD__) || defined(__osf__)
# define IS_NAN(_a) (isnan(_a)) /* GNU definition */
-#elif defined (SOLARIS_2_8) && __GNUC__ == 3 && __GNUC_MINOR__ == 2
+#elif defined (SOLARIS)
# define IS_NAN(_a) (isnan(_a)) /* GNU definition */
#else
# define IS_NAN(_a) (boost::math::isnan(_a))
@@ -129,7 +129,7 @@ inline void sincos(double angle, double &sin_, double &cos_) {
# define IS_FINITE(_a) (isfinite(_a))
#elif defined(__osf__)
# define IS_FINITE(_a) (finite(_a) && !IS_NAN(_a))
-#elif defined (SOLARIS_2_8) && __GNUC__ == 3 && __GNUC_MINOR__ == 2
+#elif defined (SOLARIS)
#include <ieeefp.h>
#define IS_FINITE(_a) (finite(_a) && !IS_NAN(_a))
#else
diff --git a/src/2geom/numeric/symmetric-matrix-fs-operation.h b/src/2geom/numeric/symmetric-matrix-fs-operation.h
index 5222d2734..37ece56ae 100644
--- a/src/2geom/numeric/symmetric-matrix-fs-operation.h
+++ b/src/2geom/numeric/symmetric-matrix-fs-operation.h
@@ -44,7 +44,7 @@ namespace Geom { namespace NL {
template <size_t N>
inline
-SymmetricMatrix<N> adj(const ConstBaseSymmetricMatrix<N> & S)
+SymmetricMatrix<N> adj(const ConstBaseSymmetricMatrix<N> & /*S*/)
{
THROW_NOTIMPLEMENTED();
return SymmetricMatrix<N>();
diff --git a/src/2geom/numeric/symmetric-matrix-fs-trace.h b/src/2geom/numeric/symmetric-matrix-fs-trace.h
index 099c834a8..dbabecf6e 100644
--- a/src/2geom/numeric/symmetric-matrix-fs-trace.h
+++ b/src/2geom/numeric/symmetric-matrix-fs-trace.h
@@ -74,7 +74,7 @@ template <size_t K, size_t N>
struct trace
{
static
- double evaluate (const ConstBaseSymmetricMatrix<N> & S)
+ double evaluate (const ConstBaseSymmetricMatrix<N> & /*S*/)
{
THROW_NOTIMPLEMENTED();
return K;
diff --git a/src/2geom/path-intersection.cpp b/src/2geom/path-intersection.cpp
index ff24b92eb..63a29423d 100644
--- a/src/2geom/path-intersection.cpp
+++ b/src/2geom/path-intersection.cpp
@@ -164,20 +164,35 @@ void append(T &a, T const &b) {
bool
linear_intersect(Point A0, Point A1, Point B0, Point B1,
double &tA, double &tB, double &det) {
- // kramers rule as cross products
+ bool both_lines_non_zero = (!are_near(A0, A1)) && (!are_near(B0, B1));
+
+ // Cramer's rule as cross products
Point Ad = A1 - A0,
Bd = B1 - B0,
d = B0 - A0;
det = cross(Ad, Bd);
- if( 1.0 + det == 1.0 )
- return false;
- else
- {
- double detinv = 1.0 / det;
- tA = cross(d, Bd) * detinv;
- tB = cross(d, Ad) * detinv;
- return tA >= 0. && tA <= 1. && tB >= 0. && tB <= 1.;
+
+ double det_rel = det; // Calculate the determinant of the normalized vectors
+ if (both_lines_non_zero) {
+ det_rel /= Ad.length();
+ det_rel /= Bd.length();
}
+
+ if( fabs(det_rel) < 1e-12 ) { // If the cross product is NEARLY zero,
+ // Then one of the linesegments might have length zero
+ if (both_lines_non_zero) {
+ // If that's not the case, then we must have either:
+ // - parallel lines, with no intersections, or
+ // - coincident lines, with an infinite number of intersections
+ // Either is quite useless, so we'll just bail out
+ return false;
+ } // Else, one of the linesegments is zero, and we might still be able to calculate a single intersection point
+ } // Else we haven't bailed out, and we'll try to calculate the intersections
+
+ double detinv = 1.0 / det;
+ tA = cross(d, Bd) * detinv;
+ tB = cross(d, Ad) * detinv;
+ return (tA >= 0.) && (tA <= 1.) && (tB >= 0.) && (tB <= 1.);
}
diff --git a/src/2geom/path.cpp b/src/2geom/path.cpp
index 5797f475c..3558af3b3 100644
--- a/src/2geom/path.cpp
+++ b/src/2geom/path.cpp
@@ -104,12 +104,14 @@ Path &Path::operator*=(Affine const &m) {
}
Path &Path::operator*=(Translate const &m) {
+/* Somehow there is something wrong here, LPE Construct grid fails with this code
unshare();
Sequence::iterator last = get_curves().end() - 1;
Sequence::iterator it;
Point prev;
for (it = get_curves().begin() ; it != last ; ++it) {
- *(const_cast<Curve*>(&**it)) *= m;
+ // *(const_cast<Curve*>(&**it)) *= m;
+ const_cast<Curve*>(it->get())->operator*=(m);
if ( it != get_curves().begin() && (*it)->initialPoint() != prev ) {
THROW_CONTINUITYERROR();
}
@@ -124,6 +126,8 @@ Path &Path::operator*=(Translate const &m) {
}
}
return *this;
+*/
+ return this->operator*=(static_cast<Affine>(m));
}
std::vector<double>
diff --git a/src/2geom/svg-path-parser.cpp b/src/2geom/svg-path-parser.cpp
index ccc383920..932f95829 100644
--- a/src/2geom/svg-path-parser.cpp
+++ b/src/2geom/svg-path-parser.cpp
@@ -1,5 +1,3 @@
-
-#line 1 "/home/tweenk/src/lib2geom/src/2geom/svg-path-parser.rl"
/**
* \file
* \brief parse SVG path specifications
@@ -130,6 +128,9 @@ private:
void _arcTo(double rx, double ry, double angle,
bool large_arc, bool sweep, Point p)
{
+ if (are_near(_current, p)) {
+ return;
+ }
_quad_tangent = _cubic_tangent = _current = p;
_sink.arcTo(rx, ry, angle, large_arc, sweep, p);
}
@@ -141,7 +142,6 @@ private:
};
-#line 145 "/home/tweenk/src/lib2geom/src/2geom/svg-path-parser.cpp"
static const char _svg_path_actions[] = {
0, 1, 0, 1, 1, 1, 2, 1,
3, 1, 4, 1, 5, 1, 15, 1,
@@ -1147,9 +1147,6 @@ static const int svg_path_first_final = 270;
//static const int svg_path_en_main = 1;
-#line 144 "/home/tweenk/src/lib2geom/src/2geom/svg-path-parser.rl"
-
-
void Parser::parse(char const *str)
throw(SVGPathParseError)
{
@@ -1159,13 +1156,11 @@ throw(SVGPathParseError)
_reset();
-
-#line 1164 "/home/tweenk/src/lib2geom/src/2geom/svg-path-parser.cpp"
{
cs = svg_path_start;
}
-#line 1169 "/home/tweenk/src/lib2geom/src/2geom/svg-path-parser.cpp"
+
{
int _klen;
unsigned int _trans;
@@ -1238,13 +1233,12 @@ _match:
switch ( *_acts++ )
{
case 0:
-#line 156 "/home/tweenk/src/lib2geom/src/2geom/svg-path-parser.rl"
{
start = p;
}
break;
case 1:
-#line 160 "/home/tweenk/src/lib2geom/src/2geom/svg-path-parser.rl"
+
{
char const *end=p;
std::string buf(start, end);
@@ -1253,55 +1247,49 @@ _match:
}
break;
case 2:
-#line 167 "/home/tweenk/src/lib2geom/src/2geom/svg-path-parser.rl"
+
{
_push(1.0);
}
break;
case 3:
-#line 171 "/home/tweenk/src/lib2geom/src/2geom/svg-path-parser.rl"
+
{
_push(0.0);
}
break;
case 4:
-#line 175 "/home/tweenk/src/lib2geom/src/2geom/svg-path-parser.rl"
+
{
_absolute = true;
}
break;
case 5:
-#line 179 "/home/tweenk/src/lib2geom/src/2geom/svg-path-parser.rl"
{
_absolute = false;
}
break;
case 6:
-#line 183 "/home/tweenk/src/lib2geom/src/2geom/svg-path-parser.rl"
{
_moveTo(_pop_point());
}
break;
case 7:
-#line 187 "/home/tweenk/src/lib2geom/src/2geom/svg-path-parser.rl"
{
_lineTo(_pop_point());
}
break;
case 8:
-#line 191 "/home/tweenk/src/lib2geom/src/2geom/svg-path-parser.rl"
{
_hlineTo(Point(_pop_coord(X), _current[Y]));
}
break;
case 9:
-#line 195 "/home/tweenk/src/lib2geom/src/2geom/svg-path-parser.rl"
{
_vlineTo(Point(_current[X], _pop_coord(Y)));
}
break;
case 10:
-#line 199 "/home/tweenk/src/lib2geom/src/2geom/svg-path-parser.rl"
{
Point p = _pop_point();
Point c1 = _pop_point();
@@ -1310,7 +1298,6 @@ _match:
}
break;
case 11:
-#line 206 "/home/tweenk/src/lib2geom/src/2geom/svg-path-parser.rl"
{
Point p = _pop_point();
Point c1 = _pop_point();
@@ -1318,7 +1305,6 @@ _match:
}
break;
case 12:
-#line 212 "/home/tweenk/src/lib2geom/src/2geom/svg-path-parser.rl"
{
Point p = _pop_point();
Point c = _pop_point();
@@ -1326,14 +1312,12 @@ _match:
}
break;
case 13:
-#line 218 "/home/tweenk/src/lib2geom/src/2geom/svg-path-parser.rl"
{
Point p = _pop_point();
_quadTo(_quad_tangent, p);
}
break;
case 14:
-#line 223 "/home/tweenk/src/lib2geom/src/2geom/svg-path-parser.rl"
{
Point point = _pop_point();
bool sweep = _pop_flag();
@@ -1346,16 +1330,13 @@ _match:
}
break;
case 15:
-#line 234 "/home/tweenk/src/lib2geom/src/2geom/svg-path-parser.rl"
{
_closePath();
}
break;
case 16:
-#line 370 "/home/tweenk/src/lib2geom/src/2geom/svg-path-parser.rl"
{{p++; goto _out; }}
break;
-#line 1359 "/home/tweenk/src/lib2geom/src/2geom/svg-path-parser.cpp"
}
}
@@ -1367,8 +1348,6 @@ _again:
_out: {}
}
-#line 380 "/home/tweenk/src/lib2geom/src/2geom/svg-path-parser.rl"
-
if ( cs < svg_path_first_final ) {
throw SVGPathParseError();
diff --git a/src/2geom/toposweep.cpp b/src/2geom/toposweep.cpp
index cfb91857c..4da3f6922 100644
--- a/src/2geom/toposweep.cpp
+++ b/src/2geom/toposweep.cpp
@@ -53,6 +53,7 @@ TopoGraph::Edge TopoGraph::remove_edge(unsigned ix, unsigned jx) {
}
}
assert(0);
+ return v[0]; // if assert is disabled, return first Edge.
}
void TopoGraph::cannonize() {
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index e1e0afa79..a1f5fc3dd 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -32,6 +32,8 @@ set(sp_SRC
sp-gradient-reference.cpp
sp-gradient.cpp
sp-guide.cpp
+ sp-hatch.cpp
+ sp-hatch-path.cpp
sp-image.cpp
sp-item-group.cpp
sp-item-notify-moveto.cpp
@@ -42,6 +44,7 @@ set(sp_SRC
sp-line.cpp
sp-linear-gradient.cpp
sp-lpe-item.cpp
+ sp-marker.cpp
sp-mask.cpp
sp-mesh-array.cpp
sp-mesh-gradient.cpp
@@ -63,6 +66,7 @@ set(sp_SRC
sp-root.cpp
sp-script.cpp
sp-shape.cpp
+ sp-solid-color.cpp
sp-spiral.cpp
sp-star.cpp
sp-stop.cpp
@@ -114,6 +118,8 @@ set(sp_SRC
sp-guide-attachment.h
sp-guide-constraint.h
sp-guide.h
+ sp-hatch.h
+ sp-hatch-path.h
sp-image.h
sp-item-group.h
sp-item-notify-moveto.h
@@ -124,6 +130,7 @@ set(sp_SRC
sp-line.h
sp-linear-gradient.h
sp-lpe-item.h
+ sp-marker.h
sp-marker-loc.h
sp-mask.h
sp-mesh-array.h
@@ -147,6 +154,7 @@ set(sp_SRC
sp-root.h
sp-script.h
sp-shape.h
+ sp-solid-color.h
sp-spiral.h
sp-star.h
sp-stop.h
@@ -188,11 +196,7 @@ set(inkscape_SRC
document-undo.cpp
document.cpp
doxygen-main.cpp
- draw-anchor.cpp
- ege-adjustment-action.cpp
ege-color-prof-tracker.cpp
- ege-output-action.cpp
- ege-select-one-action.cpp
event-log.cpp
extract-uri.cpp
file.cpp
@@ -208,26 +212,23 @@ set(inkscape_SRC
help.cpp
id-clash.cpp
# ige-mac-menu.c
- ink-action.cpp
- ink-comboboxentry-action.cpp
inkscape.cpp
inkscape.rc
interface.cpp
knot-holder-entity.cpp
knot.cpp
knotholder.cpp
+ knot-ptr.cpp
layer-fns.cpp
layer-manager.cpp
layer-model.cpp
line-geometry.cpp
line-snapper.cpp
main-cmdlineact.cpp
- marker.cpp
media.cpp
message-context.cpp
message-stack.cpp
mod360.cpp
- object-edit.cpp
object-hierarchy.cpp
object-snapper.cpp
path-chemistry.cpp
@@ -250,7 +251,6 @@ set(inkscape_SRC
selection.cpp
seltrans-handles.cpp
seltrans.cpp
- shape-editor.cpp
shortcuts.cpp
snap-preferences.cpp
snap.cpp
@@ -259,11 +259,11 @@ set(inkscape_SRC
snapped-point.cpp
snapper.cpp
style.cpp
+ style-internal.cpp
svg-view-widget.cpp
svg-view.cpp
text-chemistry.cpp
text-editing.cpp
- tools-switch.cpp
transf_mat_3x4.cpp
unclump.cpp
unicoderange.cpp
@@ -295,7 +295,6 @@ set(inkscape_SRC
composite-undo-stack-observer.h
conditions.h
conn-avoid-ref.h
- connection-pool.h
console-output-undo-observer.h
context-fns.h
decimal-round.h
@@ -310,11 +309,7 @@ set(inkscape_SRC
document-subset.h
document-undo.h
document.h
- draw-anchor.h
- ege-adjustment-action.h
ege-color-prof-tracker.h
- ege-output-action.h
- ege-select-one-action.h
enums.h
event-log.h
event.h
@@ -341,18 +336,16 @@ set(inkscape_SRC
icon-size.h
id-clash.h
# ige-mac-menu.h
- ink-action.h
- ink-comboboxentry-action.h
inkscape-private.h
inkscape-version.h
inkscape.h
interface.h
isinf.h
- isnormal.h
knot-enums.h
knot-holder-entity.h
knot.h
knotholder.h
+ knot-ptr.h
layer-fns.h
layer-manager.h
layer-model.h
@@ -370,9 +363,9 @@ set(inkscape_SRC
mod360-test.h
mod360.h
number-opt-number.h
- object-edit.h
object-hierarchy.h
object-snapper.h
+ object-test.h
path-chemistry.h
path-prefix.h
persp3d-reference.h
@@ -401,7 +394,6 @@ set(inkscape_SRC
selection.h
seltrans-handles.h
seltrans.h
- shape-editor.h
shortcuts.h
snap-candidate.h
snap-enums.h
@@ -426,13 +418,12 @@ set(inkscape_SRC
text-chemistry.h
text-editing.h
text-tag-attributes.h
- tool-factory.h
- tools-switch.h
transf_mat_3x4.h
unclump.h
undo-stack-observer.h
unicoderange.h
uri-references.h
+ uri-test.h
uri.h
vanishing-point.h
verbs-test.h
@@ -485,7 +476,6 @@ list(APPEND inkscape_SRC
add_subdirectory(debug)
add_subdirectory(dialogs)
add_subdirectory(display)
-add_subdirectory(dom)
add_subdirectory(extension)
add_subdirectory(filters)
add_subdirectory(helper)
@@ -539,7 +529,6 @@ target_link_libraries(inkscape
#sp_LIB # annoying, we need both!
nrtype_LIB # annoying, we need both!
- dom_LIB
croco_LIB
avoid_LIB
gdl_LIB
diff --git a/src/Makefile.am b/src/Makefile.am
index d3f8794ee..8fb7e23ef 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -64,6 +64,8 @@ BUILT_SOURCES =
EXTRA_DIST =
AM_CPPFLAGS = \
+ -I$(top_srcdir)/cxxtest \
+ -I$(builddir)/extension/dbus \
$(EXIF_CFLAGS) \
$(FREETYPE_CFLAGS) \
$(GNOME_PRINT_CFLAGS) \
@@ -80,9 +82,7 @@ AM_CPPFLAGS = \
$(POPPLER_GLIB_CFLAGS) \
-DPOTRACE=\"potrace\" \
$(INKSCAPE_CFLAGS) \
- -I$(top_srcdir)/cxxtest \
$(WIN32_CFLAGS) \
- -I$(builddir)/extension/dbus \
$(X11_CFLAGS)
CXXTEST_TEMPLATE = $(srcdir)/cxxtest-template.tpl
@@ -105,7 +105,6 @@ endif
# Include all partial makefiles from subdirectories
include Makefile_insert
-include dialogs/Makefile_insert
include display/Makefile_insert
include extension/Makefile_insert
include extension/dbus/Makefile_insert
@@ -144,7 +143,6 @@ include libdepixelize/Makefile_insert
EXTRA_DIST += \
2geom/makefile.in \
debug/makefile.in \
- dialogs/makefile.in \
display/makefile.in \
extension/implementation/makefile.in \
extension/internal/makefile.in \
@@ -220,7 +218,7 @@ endif
# someone updates the BZR working directory.
inkscape-version.cpp: $(inkscape_version_deps)
VER_PREFIX="$(VERSION)";\
- VER_BZRREV=" r`bzr revno --tree`"; \
+ VER_BZRREV=" r`bzr revno --tree $(top_srcdir)`"; \
if test ! -z "`bzr status -S -V $(srcdir)`"; then \
VER_CUSTOM=" custom"; \
fi; \
@@ -250,7 +248,9 @@ check_PROGRAMS = cxxtests
# "make distcheck".
# List of all tests to be run.
-TESTS = $(check_PROGRAMS) ../share/extensions/test/run-all-extension-tests
+TESTS = $(check_PROGRAMS)
+check-local:
+ $(top_srcdir)/share/extensions/test/run-all-extension-tests
# FIXME: Currently, a number of cxxtest tests fail. These should be fixed and
# the XFAIL_TESTS build target should be removed.
diff --git a/src/Makefile_insert b/src/Makefile_insert
index 8872b045d..107acdf31 100644
--- a/src/Makefile_insert
+++ b/src/Makefile_insert
@@ -24,7 +24,6 @@ ink_common_sources += \
composite-undo-stack-observer.h \
conditions.cpp conditions.h \
conn-avoid-ref.cpp conn-avoid-ref.h \
- connection-pool.h \
console-output-undo-observer.h console-output-undo-observer.cpp \
context-fns.cpp context-fns.h \
decimal-round.h \
@@ -38,11 +37,7 @@ ink_common_sources += \
document-subset.cpp document-subset.h \
document-undo.cpp document-undo.h \
doxygen-main.cpp \
- draw-anchor.cpp draw-anchor.h \
- ege-adjustment-action.cpp ege-adjustment-action.h \
ege-color-prof-tracker.cpp ege-color-prof-tracker.h \
- ege-output-action.cpp ege-output-action.h \
- ege-select-one-action.cpp ege-select-one-action.h \
enums.h \
event-log.cpp event-log.h event.h \
extract-uri.cpp extract-uri.h \
@@ -68,18 +63,13 @@ ink_common_sources += \
helper/pixbuf-ops.h \
icon-size.h \
id-clash.cpp id-clash.h \
- ink-action.cpp \
- ink-action.h \
- ink-comboboxentry-action.cpp \
- ink-comboboxentry-action.h \
inkscape.cpp inkscape.h inkscape-private.h \
- interface.cpp interface.h \
isinf.h \
- isnormal.h \
knot.cpp knot.h \
knot-enums.h \
knotholder.cpp knotholder.h \
knot-holder-entity.h knot-holder-entity.cpp \
+ knot-ptr.h knot-ptr.cpp \
layer-fns.cpp layer-fns.h \
layer-manager.cpp layer-manager.h \
layer-model.cpp layer-model.h \
@@ -87,14 +77,12 @@ ink_common_sources += \
line-snapper.cpp line-snapper.h \
macros.h \
main-cmdlineact.cpp main-cmdlineact.h \
- marker.cpp marker.h \
media.cpp media.h \
menus-skeleton.h \
message-context.cpp message-context.h \
message.h \
message-stack.cpp message-stack.h \
mod360.cpp mod360.h \
- object-edit.cpp object-edit.h \
object-hierarchy.cpp object-hierarchy.h \
object-snapper.cpp object-snapper.h \
path-chemistry.cpp path-chemistry.h \
@@ -121,7 +109,6 @@ ink_common_sources += \
selection-describer.cpp selection-describer.h \
seltrans.cpp seltrans.h \
seltrans-handles.cpp seltrans-handles.h \
- shape-editor.cpp shape-editor.h \
shortcuts.cpp shortcuts.h \
snap.cpp snap.h \
snap-enums.h snap-candidate.h \
@@ -158,6 +145,8 @@ ink_common_sources += \
sp-guide-attachment.h \
sp-guide-constraint.h \
sp-guide.cpp sp-guide.h \
+ sp-hatch.cpp sp-hatch.h \
+ sp-hatch-path.cpp sp-hatch-path.h \
sp-image.cpp sp-image.h \
sp-item.cpp sp-item.h \
sp-item-group.cpp sp-item-group.h \
@@ -169,6 +158,7 @@ ink_common_sources += \
sp-line.cpp sp-line.h \
splivarot.cpp splivarot.h \
sp-lpe-item.cpp sp-lpe-item.h \
+ sp-marker.cpp sp-marker.h \
sp-marker-loc.h \
sp-mask.cpp sp-mask.h \
sp-metadata.cpp sp-metadata.h \
@@ -192,6 +182,7 @@ ink_common_sources += \
sp-root.cpp sp-root.h \
sp-script.cpp sp-script.h \
sp-shape.cpp sp-shape.h \
+ sp-solid-color.cpp sp-solid-color.h \
sp-spiral.cpp sp-spiral.h \
sp-star.cpp sp-star.h \
sp-stop.cpp sp-stop.h \
@@ -199,6 +190,9 @@ ink_common_sources += \
sp-style-elem.cpp sp-style-elem.h \
sp-switch.cpp sp-switch.h \
sp-symbol.cpp sp-symbol.h \
+ sp-tag.cpp sp-tag.h \
+ sp-tag-use.cpp sp-tag-use.h \
+ sp-tag-use-reference.cpp sp-tag-use-reference.h \
sp-text.cpp sp-text.h \
sp-textpath.h \
sp-title.cpp sp-title.h \
@@ -210,7 +204,8 @@ ink_common_sources += \
streq.h \
strneq.h \
style.cpp style.h \
- style-enums.h style-internal.h \
+ style-enums.h \
+ style-internal.cpp style-internal.h \
svg-profile.h \
svg-view.cpp svg-view.h \
svg-view-widget.cpp svg-view-widget.h \
@@ -218,8 +213,6 @@ ink_common_sources += \
text-chemistry.cpp text-chemistry.h \
text-editing.cpp text-editing.h \
text-tag-attributes.h \
- tool-factory.h \
- tools-switch.cpp tools-switch.h \
transf_mat_3x4.cpp transf_mat_3x4.h \
unclump.cpp unclump.h \
undo-stack-observer.h \
@@ -254,6 +247,7 @@ CXXTEST_TESTSUITES += \
$(srcdir)/extract-uri-test.h \
$(srcdir)/marker-test.h \
$(srcdir)/mod360-test.h \
+ $(srcdir)/object-test.h \
$(srcdir)/preferences-test.h \
$(srcdir)/round-test.h \
$(srcdir)/sp-gradient-test.h \
diff --git a/src/attribute-rel-css.cpp b/src/attribute-rel-css.cpp
index 89678edb5..b904cd5f4 100644
--- a/src/attribute-rel-css.cpp
+++ b/src/attribute-rel-css.cpp
@@ -60,6 +60,7 @@ bool SPAttributeRelCSS::findIfValid(Glib::ustring property, Glib::ustring elemen
|| property.substr(0,4) == "rdf:"
|| property.substr(0,3) == "cc:"
|| property.substr(0,4) == "ns1:" // JessyInk
+ || property.substr(0,4) == "osb:" // Open Swatch Book
|| (SPAttributeRelCSS::instance->propertiesOfElements[temp].find(property)
!= SPAttributeRelCSS::instance->propertiesOfElements[temp].end()) ) {
return true;
diff --git a/src/attribute-rel-svg.cpp b/src/attribute-rel-svg.cpp
index 49c97ae64..0064f4c62 100644
--- a/src/attribute-rel-svg.cpp
+++ b/src/attribute-rel-svg.cpp
@@ -56,6 +56,7 @@ bool SPAttributeRelSVG::findIfValid(Glib::ustring attribute, Glib::ustring eleme
|| attribute.substr(0,4) == "rdf:"
|| attribute.substr(0,3) == "cc:"
|| attribute.substr(0,4) == "ns1:" // JessyInk
+ || attribute.substr(0,4) == "osb:" // Open Swatch Book
|| (SPAttributeRelSVG::instance->attributesOfElements[temp].find(attribute)
!= SPAttributeRelSVG::instance->attributesOfElements[temp].end()) ) {
return true;
diff --git a/src/attribute-rel-util.h b/src/attribute-rel-util.h
index 3a6661965..604987779 100644
--- a/src/attribute-rel-util.h
+++ b/src/attribute-rel-util.h
@@ -8,7 +8,7 @@
* Author: tavmjong
*/
-#include "glibmm/ustring.h"
+#include <glibmm/ustring.h>
#include "xml/sp-css-attr.h"
using Inkscape::XML::Node;
diff --git a/src/attributes.cpp b/src/attributes.cpp
index ee2a80fd3..d142d1a06 100644
--- a/src/attributes.cpp
+++ b/src/attributes.cpp
@@ -1,9 +1,4 @@
-#define __SP_ATTRIBUTES_C__
-
-/** \file
- * Lookup dictionary for attributes/properties.
- */
-/*
+/**
* Author:
* Lauris Kaplinski <lauris@kaplinski.com>
*
@@ -25,6 +20,10 @@ typedef struct {
gchar const *name;
} SPStyleProp;
+/**
+ * Lookup dictionary for attributes/properties.
+ */
+
static SPStyleProp const props[] = {
{SP_ATTR_INVALID, NULL},
/* SPObject */
@@ -41,6 +40,7 @@ static SPStyleProp const props[] = {
{SP_ATTR_TRANSFORM_CENTER_X, "inkscape:transform-center-x"},
{SP_ATTR_TRANSFORM_CENTER_Y, "inkscape:transform-center-y"},
{SP_ATTR_INKSCAPE_PATH_EFFECT, "inkscape:path-effect"},
+ {SP_ATTR_INKSCAPE_HIGHLIGHT_COLOR, "inkscape:highlight-color"},
/* SPAnchor */
{SP_ATTR_XLINK_HREF, "xlink:href"},
{SP_ATTR_XLINK_TYPE, "xlink:type"},
@@ -51,6 +51,7 @@ static SPStyleProp const props[] = {
{SP_ATTR_XLINK_ACTUATE, "xlink:actuate"},
{SP_ATTR_TARGET, "target"},
{SP_ATTR_INKSCAPE_GROUPMODE, "inkscape:groupmode"},
+ {SP_ATTR_INKSCAPE_EXPANDED, "inkscape:expanded"},
/* SPRoot */
{SP_ATTR_VERSION, "version"},
{SP_ATTR_WIDTH, "width"},
@@ -292,6 +293,11 @@ static SPStyleProp const props[] = {
{SP_ATTR_PATTERNUNITS, "patternUnits"},
{SP_ATTR_PATTERNCONTENTUNITS, "patternContentUnits"},
{SP_ATTR_PATTERNTRANSFORM, "patternTransform"},
+ /* SPHatch */
+ {SP_ATTR_HATCHUNITS, "hatchUnits"},
+ {SP_ATTR_HATCHCONTENTUNITS, "hatchContentUnits"},
+ {SP_ATTR_HATCHTRANSFORM, "hatchTransform"},
+ {SP_ATTR_PITCH, "pitch"},
/* SPClipPath */
{SP_ATTR_CLIPPATHUNITS, "clipPathUnits"},
/* SPMask */
@@ -413,10 +419,6 @@ static SPStyleProp const props[] = {
/* Text */
{SP_PROP_TEXT_INDENT, "text-indent"},
{SP_PROP_TEXT_ALIGN, "text-align"},
- {SP_PROP_TEXT_DECORATION, "text-decoration"},
- {SP_PROP_TEXT_DECORATION_LINE, "text-decoration-line"},
- {SP_PROP_TEXT_DECORATION_STYLE,"text-decoration-style"},
- {SP_PROP_TEXT_DECORATION_COLOR,"text-decoration-color"},
{SP_PROP_LINE_HEIGHT, "line-height"},
{SP_PROP_LETTER_SPACING, "letter-spacing"},
{SP_PROP_WORD_SPACING, "word-spacing"},
@@ -433,6 +435,12 @@ static SPStyleProp const props[] = {
{SP_PROP_GLYPH_ORIENTATION_VERTICAL, "glyph-orientation-vertical"},
{SP_PROP_KERNING, "kerning"},
{SP_PROP_TEXT_ANCHOR, "text-anchor"},
+ {SP_PROP_WHITE_SPACE, "white-space"},
+ /* Text Decoration */
+ {SP_PROP_TEXT_DECORATION, "text-decoration"},
+ {SP_PROP_TEXT_DECORATION_LINE, "text-decoration-line"},
+ {SP_PROP_TEXT_DECORATION_STYLE,"text-decoration-style"},
+ {SP_PROP_TEXT_DECORATION_COLOR,"text-decoration-color"},
/* Misc */
{SP_PROP_CLIP, "clip"},
{SP_PROP_COLOR, "color"},
@@ -440,7 +448,7 @@ static SPStyleProp const props[] = {
{SP_PROP_DISPLAY, "display"},
{SP_PROP_OVERFLOW, "overflow"},
{SP_PROP_VISIBILITY, "visibility"},
- {SP_PROP_BLEND_MODE, "mix-blend-mode"}, // CSS Blending and Compositing
+ {SP_PROP_MIX_BLEND_MODE, "mix-blend-mode"}, // CSS Blending and Compositing
{SP_PROP_ISOLATION, "isolation"},
/* SVG */
/* Clip/Mask */
@@ -475,6 +483,8 @@ static SPStyleProp const props[] = {
{SP_PROP_MARKER_START, "marker-start"},
{SP_PROP_PAINT_ORDER, "paint-order" },
{SP_PROP_SHAPE_RENDERING, "shape-rendering"},
+ {SP_PROP_SOLID_COLOR, "solid-color"},
+ {SP_PROP_SOLID_OPACITY, "solid-opacity"},
{SP_PROP_STROKE, "stroke"},
{SP_PROP_STROKE_DASHARRAY, "stroke-dasharray"},
{SP_PROP_STROKE_DASHOFFSET, "stroke-dashoffset"},
@@ -535,4 +545,4 @@ sp_attribute_name(unsigned int id)
fill-column:99
End:
*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8 :
diff --git a/src/attributes.h b/src/attributes.h
index b8843fcb7..8e091df71 100644
--- a/src/attributes.h
+++ b/src/attributes.h
@@ -40,6 +40,7 @@ enum SPAttributeEnum {
SP_ATTR_TRANSFORM_CENTER_X,
SP_ATTR_TRANSFORM_CENTER_Y,
SP_ATTR_INKSCAPE_PATH_EFFECT,
+ SP_ATTR_INKSCAPE_HIGHLIGHT_COLOR,
/* SPAnchor */
SP_ATTR_XLINK_HREF,
SP_ATTR_XLINK_TYPE,
@@ -51,6 +52,7 @@ enum SPAttributeEnum {
SP_ATTR_TARGET,
/* SPGroup */
SP_ATTR_INKSCAPE_GROUPMODE,
+ SP_ATTR_INKSCAPE_EXPANDED,
/* SPRoot */
SP_ATTR_VERSION,
SP_ATTR_WIDTH,
@@ -293,6 +295,11 @@ enum SPAttributeEnum {
SP_ATTR_PATTERNUNITS,
SP_ATTR_PATTERNCONTENTUNITS,
SP_ATTR_PATTERNTRANSFORM,
+ /* SPHatch */
+ SP_ATTR_HATCHUNITS,
+ SP_ATTR_HATCHCONTENTUNITS,
+ SP_ATTR_HATCHTRANSFORM,
+ SP_ATTR_PITCH,
/* SPClipPath */
SP_ATTR_CLIPPATHUNITS,
/* SPMask */
@@ -399,9 +406,11 @@ enum SPAttributeEnum {
SP_ATTR_TEXT_EXCLUDE,
SP_ATTR_LAYOUT_OPTIONS,
- /* CSS2 */
- /* Custom full font name because Font stuff below is inadequate */
+ /* CSS & SVG Properties */
+
+ /* Custom full font name because Font stuff below is inadequate REMOVE ME */
SP_PROP_INKSCAPE_FONT_SPEC,
+
/* Font */
SP_PROP_FONT,
SP_PROP_FONT_FAMILY,
@@ -411,18 +420,16 @@ enum SPAttributeEnum {
SP_PROP_FONT_STYLE,
SP_PROP_FONT_VARIANT,
SP_PROP_FONT_WEIGHT,
- /* Text */
+
+ /* Text Layout */
SP_PROP_TEXT_INDENT,
SP_PROP_TEXT_ALIGN,
- SP_PROP_TEXT_DECORATION, /* SVG 1 underline etc.( no color or style) OR SVG2 with _LINE, _STYLE, _COLOR values */
- SP_PROP_TEXT_DECORATION_LINE, /* SVG 2 underline etc. */
- SP_PROP_TEXT_DECORATION_STYLE, /* SVG 2 proposed solid [SVG 1], dotted, etc.)*/
- SP_PROP_TEXT_DECORATION_COLOR, /* SVG 2 proposed same as text [SVG 1], specified*/
+
SP_PROP_LINE_HEIGHT,
SP_PROP_LETTER_SPACING,
SP_PROP_WORD_SPACING,
SP_PROP_TEXT_TRANSFORM,
- /* text (css3) */
+
SP_PROP_DIRECTION,
SP_PROP_BLOCK_PROGRESSION,
SP_PROP_WRITING_MODE,
@@ -434,6 +441,14 @@ enum SPAttributeEnum {
SP_PROP_GLYPH_ORIENTATION_VERTICAL,
SP_PROP_KERNING,
SP_PROP_TEXT_ANCHOR,
+ SP_PROP_WHITE_SPACE,
+
+ /* Text Decoration */
+ SP_PROP_TEXT_DECORATION, /* SVG 1 underline etc.( no color or style) OR SVG2 with _LINE, _STYLE, _COLOR values */
+ SP_PROP_TEXT_DECORATION_LINE, /* SVG 2 underline etc. */
+ SP_PROP_TEXT_DECORATION_STYLE, /* SVG 2 proposed solid [SVG 1], dotted, etc.)*/
+ SP_PROP_TEXT_DECORATION_COLOR, /* SVG 2 proposed same as text [SVG 1], specified*/
+
/* Misc */
SP_PROP_CLIP,
SP_PROP_COLOR,
@@ -441,26 +456,31 @@ enum SPAttributeEnum {
SP_PROP_DISPLAY,
SP_PROP_OVERFLOW,
SP_PROP_VISIBILITY,
- SP_PROP_BLEND_MODE,
+ SP_PROP_MIX_BLEND_MODE,
SP_PROP_ISOLATION,
+
/* SVG */
/* Clip/Mask */
SP_PROP_CLIP_PATH,
SP_PROP_CLIP_RULE,
SP_PROP_MASK,
SP_PROP_OPACITY,
+
/* Filter */
SP_PROP_ENABLE_BACKGROUND,
SP_PROP_FILTER,
SP_PROP_FLOOD_COLOR,
SP_PROP_FLOOD_OPACITY,
SP_PROP_LIGHTING_COLOR,
+
/* Gradient */
SP_PROP_STOP_COLOR,
SP_PROP_STOP_OPACITY,
SP_PROP_STOP_PATH,
+
/* Interactivity */
SP_PROP_POINTER_EVENTS,
+
/* Paint */
SP_PROP_COLOR_INTERPOLATION,
SP_PROP_COLOR_INTERPOLATION_FILTERS,
@@ -476,6 +496,8 @@ enum SPAttributeEnum {
SP_PROP_MARKER_START,
SP_PROP_PAINT_ORDER, /* SVG2 */
SP_PROP_SHAPE_RENDERING,
+ SP_PROP_SOLID_COLOR,
+ SP_PROP_SOLID_OPACITY,
SP_PROP_STROKE,
SP_PROP_STROKE_DASHARRAY,
SP_PROP_STROKE_DASHOFFSET,
@@ -485,10 +507,12 @@ enum SPAttributeEnum {
SP_PROP_STROKE_OPACITY,
SP_PROP_STROKE_WIDTH,
SP_PROP_TEXT_RENDERING,
+
/* Conditional */
SP_PROP_SYSTEM_LANGUAGE,
SP_PROP_REQUIRED_FEATURES,
SP_PROP_REQUIRED_EXTENSIONS,
+
/* LivePathEffect */
SP_PROP_PATH_EFFECT,
};
diff --git a/src/axis-manip.cpp b/src/axis-manip.cpp
index 1dfa0e6bf..8955202c8 100644
--- a/src/axis-manip.cpp
+++ b/src/axis-manip.cpp
@@ -1,6 +1,4 @@
-#define __AXIS_MANIP_C__
-
-/*
+/**
* Generic auxiliary routines for 3D axes
*
* Authors:
@@ -11,6 +9,7 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
+#include <glib.h>
#include "axis-manip.h"
namespace Proj {
@@ -33,6 +32,14 @@ get_remaining_axes (Axis axis) {
return std::make_pair (extract_first_axis_direction (plane), extract_second_axis_direction (plane));
}
+char * string_from_axes (Box3D::Axis axis) {
+ GString *pstring = g_string_new("");
+ if (axis & Box3D::X) g_string_append_printf (pstring, "X");
+ if (axis & Box3D::Y) g_string_append_printf (pstring, "Y");
+ if (axis & Box3D::Z) g_string_append_printf (pstring, "Z");
+ return pstring->str;
+}
+
} // namespace Box3D
/*
@@ -44,4 +51,4 @@ get_remaining_axes (Axis axis) {
fill-column:99
End:
*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8 :
diff --git a/src/axis-manip.h b/src/axis-manip.h
index 9392e2ddd..5e245939e 100644
--- a/src/axis-manip.h
+++ b/src/axis-manip.h
@@ -12,8 +12,9 @@
#ifndef SEEN_AXIS_MANIP_H
#define SEEN_AXIS_MANIP_H
+#include <cassert>
+#include <string>
#include <utility>
-#include <gtk/gtk.h>
namespace Proj {
@@ -34,7 +35,7 @@ enum Axis {
extern Axis axes[4];
-inline gchar const *
+inline char const*
string_from_axis(Proj::Axis axis) {
switch (axis) {
case X: return "X"; break;
@@ -77,18 +78,15 @@ inline int axis_to_int(Box3D::Axis axis) {
switch (axis) {
case Box3D::X:
return 0;
- break;
case Box3D::Y:
return 1;
- break;
case Box3D::Z:
return 2;
- break;
case Box3D::NONE:
return -1;
- break;
default:
- g_assert_not_reached();
+ assert(false);
+ return -1; // help compiler's flow analysis (-Werror=return-value)
}
}
@@ -103,7 +101,8 @@ inline Proj::Axis toProj(Box3D::Axis axis) {
case Box3D::NONE:
return Proj::NONE;
default:
- g_assert_not_reached();
+ assert(false);
+ return Proj::NONE; // help compiler's flow analysis (-Werror=return-value)
}
}
@@ -126,7 +125,8 @@ inline Box3D::Axis toAffine(Proj::Axis axis) {
case Proj::NONE:
return Box3D::NONE;
default:
- g_assert_not_reached();
+ assert(false);
+ return Box3D::NONE; // help compiler's flow analysis (-Werror=return-value)
}
}
@@ -144,7 +144,7 @@ namespace Box3D {
// (which is normally used to index an array). Return -1 if the bit sequence
// does not specify a face. A face can either be given by its plane (e.g, XY)
// or by the axis that is orthogonal to it (e.g., Z).
-inline gint face_to_int (guint face_id) {
+inline int face_to_int (unsigned int face_id) {
switch (face_id) {
case 1: return 0;
case 2: return 1;
@@ -164,7 +164,7 @@ inline gint face_to_int (guint face_id) {
}
}
-inline gint int_to_face (guint id) {
+inline int int_to_face (unsigned id) {
switch (id) {
case 0: return Box3D::YZ ^ Box3D::FRONT;
case 1: return Box3D::XZ ^ Box3D::FRONT;
@@ -176,7 +176,7 @@ inline gint int_to_face (guint id) {
return Box3D::NONE; // should not be reached
}
-inline bool is_face_id (guint face_id) {
+inline bool is_face_id (unsigned int face_id) {
return !((face_id & 0x7) == 0x7);
}
@@ -186,8 +186,8 @@ inline gint opposite_face (guint face_id) {
}
**/
-inline guint number_of_axis_directions (Box3D::Axis axis) {
- guint num = 0;
+inline unsigned int number_of_axis_directions (Box3D::Axis axis) {
+ unsigned int num = 0;
if (axis & Box3D::X) num++;
if (axis & Box3D::Y) num++;
if (axis & Box3D::Z) num++;
@@ -238,14 +238,7 @@ inline Box3D::Axis get_perpendicular_axis_direction (Box3D::Axis dirs) {
return Box3D::NONE;
}
-inline gchar * string_from_axes (Box3D::Axis axis) {
- GString *pstring = g_string_new("");
- if (axis & Box3D::X) g_string_append_printf (pstring, "X");
- if (axis & Box3D::Y) g_string_append_printf (pstring, "Y");
- if (axis & Box3D::Z) g_string_append_printf (pstring, "Z");
- return pstring->str;
-}
-
+char * string_from_axes (Box3D::Axis axis);
std::pair <Axis, Axis> get_remaining_axes (Axis axis);
} // namespace Box3D
diff --git a/src/box3d-side.cpp b/src/box3d-side.cpp
index dfccb63bf..3058eab2d 100644
--- a/src/box3d-side.cpp
+++ b/src/box3d-side.cpp
@@ -4,6 +4,7 @@
* Authors:
* Maximilian Albert <Anhalter42@gmx.de>
* Abhishek Sharma
+ * Jon A. Cruz <jon@joncruz.org>
*
* Copyright (C) 2007 Authors
*
@@ -166,13 +167,12 @@ void Box3DSide::set_shape() {
SPObject *parent = this->parent;
- if (!SP_IS_BOX3D(parent)) {
+ SPBox3D *box = dynamic_cast<SPBox3D *>(parent);
+ if (!box) {
g_warning("Parent of 3D box side is not a 3D box.\n");
return;
}
- SPBox3D *box = SP_BOX3D(parent);
-
Persp3D *persp = box3d_side_perspective(this);
if (!persp) {
@@ -259,7 +259,8 @@ box3d_side_compute_corner_ids(Box3DSide *side, unsigned int corners[4]) {
Persp3D *
box3d_side_perspective(Box3DSide *side) {
- return SP_BOX3D(side->parent)->persp_ref->getObject();
+ SPBox3D *box = side ? dynamic_cast<SPBox3D *>(side->parent) : NULL;
+ return box ? box->persp_ref->getObject() : NULL;
}
Inkscape::XML::Node *box3d_side_convert_to_path(Box3DSide *side) {
diff --git a/src/box3d-side.h b/src/box3d-side.h
index 04bd196c2..4783a5f24 100644
--- a/src/box3d-side.h
+++ b/src/box3d-side.h
@@ -7,6 +7,7 @@
* Authors:
* Maximilian Albert <Anhalter42@gmx.de>
* Abhishek Sharma
+ * Jon A. Cruz <jon@joncruz.org>
*
* Copyright (C) 2007 Authors
*
@@ -17,9 +18,6 @@
#include "axis-manip.h"
-#define SP_BOX3D_SIDE(obj) (dynamic_cast<Box3DSide*>((SPObject*)obj))
-#define SP_IS_BOX3D_SIDE(obj) (dynamic_cast<const Box3DSide*>((SPObject*)obj) != NULL)
-
class SPBox3D;
class Persp3D;
@@ -36,16 +34,16 @@ public:
static Box3DSide * createBox3DSide(SPBox3D *box);
virtual void build(SPDocument* doc, Inkscape::XML::Node* repr);
- virtual void set(unsigned int key, gchar const* value);
- virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags);
- virtual void update(SPCtx *ctx, guint flags);
+ virtual void set(unsigned int key, char const* value);
+ virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags);
+ virtual void update(SPCtx *ctx, unsigned int flags);
virtual void set_shape();
};
void box3d_side_position_set (Box3DSide *side); // FIXME: Replace this by box3d_side_set_shape??
-gchar *box3d_side_axes_string(Box3DSide *side);
+char *box3d_side_axes_string(Box3DSide *side);
Persp3D *box3d_side_perspective(Box3DSide *side);
diff --git a/src/box3d.cpp b/src/box3d.cpp
index 13a8d0e3e..3c0cbb675 100644
--- a/src/box3d.cpp
+++ b/src/box3d.cpp
@@ -6,6 +6,7 @@
* Lauris Kaplinski <lauris@kaplinski.com>
* bulia byak <buliabyak@users.sf.net>
* Abhishek Sharma
+ * Jon A. Cruz <jon@joncruz.org>
*
* Copyright (C) 2007 Authors
* Copyright (C) 1999-2002 Lauris Kaplinski
@@ -65,27 +66,23 @@ SPBox3D::~SPBox3D() {
}
void SPBox3D::build(SPDocument *document, Inkscape::XML::Node *repr) {
- SPBox3D* object = this;
-
SPGroup::build(document, repr);
- SPBox3D *box = SP_BOX3D (object);
- box->my_counter = counter++;
+ my_counter = counter++;
/* we initialize the z-orders to zero so that they are updated during dragging */
for (int i = 0; i < 6; ++i) {
- box->z_orders[i] = 0;
+ z_orders[i] = 0;
}
// TODO: Create/link to the correct perspective
- SPDocument *doc = box->document;
- if ( doc ) {
- box->persp_ref->changedSignal().connect(sigc::bind(sigc::ptr_fun(box3d_ref_changed), box));
+ if ( document ) {
+ persp_ref->changedSignal().connect(sigc::bind(sigc::ptr_fun(box3d_ref_changed), this));
- object->readAttr( "inkscape:perspectiveID" );
- object->readAttr( "inkscape:corner0" );
- object->readAttr( "inkscape:corner7" );
+ readAttr( "inkscape:perspectiveID" );
+ readAttr( "inkscape:corner0" );
+ readAttr( "inkscape:corner7" );
}
}
@@ -187,11 +184,15 @@ box3d_ref_changed(SPObject *old_ref, SPObject *ref, SPBox3D *box)
{
if (old_ref) {
sp_signal_disconnect_by_data(old_ref, box);
- persp3d_remove_box (SP_PERSP3D(old_ref), box);
+ Persp3D *oldPersp = dynamic_cast<Persp3D *>(old_ref);
+ if (oldPersp) {
+ persp3d_remove_box(oldPersp, box);
+ }
}
- if ( SP_IS_PERSP3D(ref) && ref != box ) // FIXME: Comparisons sane?
+ Persp3D *persp = dynamic_cast<Persp3D *>(ref);
+ if ( persp && (ref != box) ) // FIXME: Comparisons sane?
{
- persp3d_add_box (SP_PERSP3D(ref), box);
+ persp3d_add_box(persp, box);
}
}
@@ -263,17 +264,15 @@ void box3d_position_set(SPBox3D *box)
{
/* This draws the curve and calls requestDisplayUpdate() for each side (the latter is done in
box3d_side_position_set() to avoid update conflicts with the parent box) */
- for ( SPObject *child = box->firstChild(); child; child = child->getNext() ) {
- if (SP_IS_BOX3D_SIDE(child)) {
- box3d_side_position_set(SP_BOX3D_SIDE(child));
+ for ( SPObject *obj = box->firstChild(); obj; obj = obj->getNext() ) {
+ Box3DSide *side = dynamic_cast<Box3DSide *>(obj);
+ if (side) {
+ box3d_side_position_set(side);
}
}
}
Geom::Affine SPBox3D::set_transform(Geom::Affine const &xform) {
- SPBox3D* item = this;
- SPBox3D *box = item;
-
// We don't apply the transform to the box directly but instead to its perspective (which is
// done in sp_selection_apply_affine). Here we only adjust strokes, patterns, etc.
@@ -281,10 +280,9 @@ Geom::Affine SPBox3D::set_transform(Geom::Affine const &xform) {
gdouble const sw = hypot(ret[0], ret[1]);
gdouble const sh = hypot(ret[2], ret[3]);
- for ( SPObject *child = box->firstChild(); child; child = child->getNext() ) {
- if (SP_IS_ITEM(child)) {
- SPItem *childitem = SP_ITEM(child);
-
+ for ( SPObject *child = firstChild(); child; child = child->getNext() ) {
+ SPItem *childitem = dynamic_cast<SPItem *>(child);
+ if (childitem) {
// Adjust stroke width
childitem->adjust_stroke(sqrt(fabs(sw * sh)));
@@ -672,15 +670,6 @@ box3d_aux_set_z_orders (int z_orders[6], int a, int b, int c, int d, int e, int
z_orders[5] = f;
}
-static inline void
-box3d_swap_z_orders (int z_orders[6]) {
- int tmp;
- for (int i = 0; i < 3; ++i) {
- tmp = z_orders[i];
- z_orders[i] = z_orders[5-i];
- z_orders[5-i] = tmp;
- }
-}
/*
* In standard perspective we have:
@@ -695,11 +684,6 @@ box3d_swap_z_orders (int z_orders[6]) {
/* All VPs infinite */
static void
box3d_set_new_z_orders_case0 (SPBox3D *box, int z_orders[6], Box3D::Axis central_axis) {
- Persp3D *persp = box3d_get_perspective(box);
- Geom::Point xdir(persp3d_get_infinite_dir(persp, Proj::X));
- Geom::Point ydir(persp3d_get_infinite_dir(persp, Proj::Y));
- Geom::Point zdir(persp3d_get_infinite_dir(persp, Proj::Z));
-
bool swapped = box3d_XY_axes_are_swapped(box);
switch(central_axis) {
@@ -811,12 +795,7 @@ box3d_set_new_z_orders_case1 (SPBox3D *box, int z_orders[6], Box3D::Axis central
/* Precisely 2 finite VPs */
static void
box3d_set_new_z_orders_case2 (SPBox3D *box, int z_orders[6], Box3D::Axis central_axis, Box3D::Axis /*infinite_axis*/) {
- Persp3D *persp = box3d_get_perspective(box);
-
Geom::Point c3(box3d_get_corner_screen(box, 3, false));
- Geom::Point xdir(persp3d_get_PL_dir_from_pt(persp, c3, Proj::X));
- Geom::Point ydir(persp3d_get_PL_dir_from_pt(persp, c3, Proj::Y));
- Geom::Point zdir(persp3d_get_PL_dir_from_pt(persp, c3, Proj::Z));
bool swapped = box3d_XY_axes_are_swapped(box);
@@ -1098,10 +1077,10 @@ box3d_recompute_z_orders (SPBox3D *box) {
static std::map<int, Box3DSide *> box3d_get_sides(SPBox3D *box)
{
std::map<int, Box3DSide *> sides;
- for ( SPObject *side = box->firstChild(); side; side = side->getNext() ) {
- if (SP_IS_BOX3D_SIDE(side)){
- Box3DSide *bside = SP_BOX3D_SIDE(side);
- sides[Box3D::face_to_int(bside->getFaceId())] = bside;
+ for ( SPObject *obj = box->firstChild(); obj; obj = obj->getNext() ) {
+ Box3DSide *side = dynamic_cast<Box3DSide *>(obj);
+ if (side) {
+ sides[Box3D::face_to_int(side->getFaceId())] = side;
}
}
sides.erase(-1);
@@ -1237,9 +1216,10 @@ box3d_check_for_swapped_coords(SPBox3D *box) {
}
static void box3d_extract_boxes_rec(SPObject *obj, std::list<SPBox3D *> &boxes) {
- if (SP_IS_BOX3D(obj)) {
- boxes.push_back(SP_BOX3D(obj));
- } else if (SP_IS_GROUP(obj)) {
+ SPBox3D *box = dynamic_cast<SPBox3D *>(obj);
+ if (box) {
+ boxes.push_back(box);
+ } else if (dynamic_cast<SPGroup *>(obj)) {
for ( SPObject *child = obj->firstChild(); child; child = child->getNext() ) {
box3d_extract_boxes_rec(child, boxes);
}
@@ -1299,9 +1279,10 @@ SPGroup *box3d_convert_to_group(SPBox3D *box)
// create a new group and add the sides (converted to ordinary paths) as its children
Inkscape::XML::Node *grepr = xml_doc->createElement("svg:g");
- for ( SPObject *child = box->firstChild(); child; child = child->getNext() ) {
- if (SP_IS_BOX3D_SIDE(child)) {
- Inkscape::XML::Node *repr = box3d_side_convert_to_path(SP_BOX3D_SIDE(child));
+ for ( SPObject *obj = box->firstChild(); obj; obj = obj->getNext() ) {
+ Box3DSide *side = dynamic_cast<Box3DSide *>(obj);
+ if (side) {
+ Inkscape::XML::Node *repr = box3d_side_convert_to_path(side);
grepr->appendChild(repr);
} else {
g_warning("Non-side item encountered as child of a 3D box.");
@@ -1322,7 +1303,9 @@ SPGroup *box3d_convert_to_group(SPBox3D *box)
grepr->setAttribute("id", id);
- return SP_GROUP(doc->getObjectByRepr(grepr));
+ SPGroup *group = dynamic_cast<SPGroup *>(doc->getObjectByRepr(grepr));
+ g_assert(group != NULL);
+ return group;
}
const char *SPBox3D::displayName() const {
diff --git a/src/box3d.h b/src/box3d.h
index 4107d2452..85f481e5b 100644
--- a/src/box3d.h
+++ b/src/box3d.h
@@ -8,6 +8,7 @@
* Lauris Kaplinski <lauris@kaplinski.com>
* Maximilian Albert <Anhalter42@gmx.de>
* Abhishek Sharma
+ * Jon A. Cruz <jon@joncruz.org.
*
* Copyright (C) 2007 Authors
* Copyright (C) 1999-2002 Lauris Kaplinski
@@ -21,8 +22,6 @@
#include "axis-manip.h"
#define SP_TYPE_BOX3D (box3d_get_type ())
-#define SP_BOX3D(obj) (dynamic_cast<SPBox3D*>((SPObject*)obj))
-#define SP_IS_BOX3D(obj) (dynamic_cast<const SPBox3D*>((SPObject*)obj) != NULL)
class Persp3D;
class Persp3DReference;
@@ -32,9 +31,9 @@ public:
SPBox3D();
virtual ~SPBox3D();
- gint z_orders[6]; // z_orders[i] holds the ID of the face at position #i in the group (from top to bottom)
+ int z_orders[6]; // z_orders[i] holds the ID of the face at position #i in the group (from top to bottom)
- gchar *persp_href;
+ char *persp_href;
Persp3DReference *persp_ref;
Proj::Pt3 orig_corner0;
@@ -45,7 +44,7 @@ public:
Box3D::Axis swapped; // to indicate which coordinates are swapped during dragging
- gint my_counter; // for debugging only
+ int my_counter; // for debugging only
/**
* Create a SPBox3D and append it to the parent.
@@ -54,24 +53,24 @@ public:
virtual void build(SPDocument *document, Inkscape::XML::Node *repr);
virtual void release();
- virtual void set(unsigned int key, gchar const* value);
- virtual void update(SPCtx *ctx, guint flags);
- virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags);
+ virtual void set(unsigned int key, char const* value);
+ virtual void update(SPCtx *ctx, unsigned int flags);
+ virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags);
virtual const char* display_name();
virtual Geom::Affine set_transform(Geom::Affine const &transform);
virtual void convert_to_guides() const;
virtual const char* displayName() const;
- virtual gchar *description() const;
+ virtual char *description() const;
};
void box3d_position_set (SPBox3D *box);
-Proj::Pt3 box3d_get_proj_corner (SPBox3D const *box, guint id);
-Geom::Point box3d_get_corner_screen (SPBox3D const *box, guint id, bool item_coords = true);
+Proj::Pt3 box3d_get_proj_corner (SPBox3D const *box, unsigned int id);
+Geom::Point box3d_get_corner_screen (SPBox3D const *box, unsigned int id, bool item_coords = true);
Proj::Pt3 box3d_get_proj_center (SPBox3D *box);
Geom::Point box3d_get_center_screen (SPBox3D *box);
-void box3d_set_corner (SPBox3D *box, guint id, Geom::Point const &new_pos, Box3D::Axis movement, bool constrained);
+void box3d_set_corner (SPBox3D *box, unsigned int id, Geom::Point const &new_pos, Box3D::Axis movement, bool constrained);
void box3d_set_center (SPBox3D *box, Geom::Point const &new_pos, Geom::Point const &old_pos, Box3D::Axis movement, bool constrained);
void box3d_corners_for_PLs (const SPBox3D * box, Proj::Axis axis, Geom::Point &corner1, Geom::Point &corner2, Geom::Point &corner3, Geom::Point &corner4);
bool box3d_recompute_z_orders (SPBox3D *box);
diff --git a/src/cms-color-types.h b/src/cms-color-types.h
index 47157c243..b94c96029 100644
--- a/src/cms-color-types.h
+++ b/src/cms-color-types.h
@@ -10,15 +10,14 @@
# include "config.h"
#endif // HAVE_CONFIG_H
-#include <glib.h>
-
#if HAVE_LIBLCMS1
# include <icc34.h>
#endif
#if HAVE_STDINT_H
-# include <stdint.h>
+# include <stdint.h> // uint8_t, etc
#endif
+typedef unsigned int guint32;
typedef void * cmsHPROFILE;
typedef void * cmsHTRANSFORM;
diff --git a/src/cms-system.h b/src/cms-system.h
index c528deb94..73d1a89c4 100644
--- a/src/cms-system.h
+++ b/src/cms-system.h
@@ -5,8 +5,6 @@
* Macros and fn declarations related to linear gradients.
*/
-#include <glib-object.h>
-#include <glib.h>
#include <vector>
#include <glibmm/ustring.h>
#include "cms-color-types.h"
@@ -19,13 +17,13 @@ class ColorProfile;
class CMSSystem {
public:
- static cmsHPROFILE getHandle( SPDocument* document, guint* intent, gchar const* name );
+ static cmsHPROFILE getHandle( SPDocument* document, unsigned int* intent, char const* name );
static cmsHTRANSFORM getDisplayTransform();
static Glib::ustring getDisplayId( int screen, int monitor );
- static Glib::ustring setDisplayPer( gpointer buf, guint bufLen, int screen, int monitor );
+ static Glib::ustring setDisplayPer( void* buf, unsigned int bufLen, int screen, int monitor );
static cmsHTRANSFORM getDisplayPer( Glib::ustring const& id );
@@ -39,7 +37,7 @@ public:
static bool isPrintColorSpace(ColorProfile const *profile);
- static gint getChannelCount(ColorProfile const *profile);
+ static int getChannelCount(ColorProfile const *profile);
};
diff --git a/src/color-profile.cpp b/src/color-profile.cpp
index ed4b9029e..28550b75d 100644
--- a/src/color-profile.cpp
+++ b/src/color-profile.cpp
@@ -19,6 +19,7 @@
#include <gtk/gtk.h>
#endif // DEBUG_LCMS
+#include <unistd.h>
#include <cstring>
#include <string>
#include <io/sys.h>
@@ -322,17 +323,15 @@ void ColorProfile::set(unsigned key, gchar const *value) {
}
//# 1. Get complete URI of document
gchar const *docbase = doc->getURI();
- if (!docbase)
- {
- // Normal for files that have not yet been saved.
- docbase = "";
- }
gchar* escaped = g_uri_escape_string(this->href, "!*'();:@=+$,/?#[]", TRUE);
//g_message("docbase:%s\n", docbase);
//org::w3c::dom::URI docUri(docbase);
- Inkscape::URI docUri(docbase);
+ Inkscape::URI docUri("");
+ if (docbase) { // The file has already been saved
+ docUri = Inkscape::URI::from_native_filename(docbase);
+ }
//# 2. Get href of icc file. we don't care if it's rel or abs
//org::w3c::dom::URI hrefUri(escaped);
@@ -912,7 +911,7 @@ Glib::ustring getNameFromProfile(cmsHPROFILE profile)
if ( name && !g_utf8_validate(name, -1, NULL) ) {
name = _("(invalid UTF-8 string)");
}
- nameStr = (name) ? name : _("None");
+ nameStr = (name) ? name : C_("Profile name", "None");
#elif HAVE_LIBLCMS2
cmsUInt32Number byteLen = cmsGetProfileInfo(profile, cmsInfoDescription, "en", "US", NULL, 0);
if (byteLen > 0) {
diff --git a/src/color-profile.h b/src/color-profile.h
index 2da757b91..cb6b25945 100644
--- a/src/color-profile.h
+++ b/src/color-profile.h
@@ -2,7 +2,6 @@
#define SEEN_COLOR_PROFILE_H
#include <vector>
-#include <glib.h>
#include <sp-object.h>
#include <glibmm/ustring.h>
#include "cms-color-types.h"
@@ -31,7 +30,7 @@ public:
ColorProfile();
virtual ~ColorProfile();
- friend cmsHPROFILE colorprofile_get_handle( SPDocument*, guint*, gchar const* );
+ friend cmsHPROFILE colorprofile_get_handle( SPDocument*, unsigned int*, char const* );
friend class CMSSystem;
static std::vector<Glib::ustring> getBaseProfileDirs();
@@ -49,21 +48,21 @@ public:
#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
- gchar* href;
- gchar* local;
- gchar* name;
- gchar* intentStr;
- guint rendering_intent;
+ char* href;
+ char* local;
+ char* name;
+ char* intentStr;
+ unsigned int rendering_intent; // FIXME: type the enum and hold that instead
protected:
ColorProfileImpl *impl;
- virtual void build(SPDocument* doc, Inkscape::XML::Node* repr);
- virtual void release();
+ virtual void build(SPDocument* doc, Inkscape::XML::Node* repr);
+ virtual void release();
- virtual void set(unsigned int key, const gchar* value);
+ virtual void set(unsigned int key, char const* value);
- virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, guint flags);
+ virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, unsigned int flags);
};
} // namespace Inkscape
diff --git a/src/color-rgba.h b/src/color-rgba.h
index ef7d9aee1..55cf68877 100644
--- a/src/color-rgba.h
+++ b/src/color-rgba.h
@@ -9,8 +9,9 @@
#ifndef SEEN_COLOR_RGBA_H
#define SEEN_COLOR_RGBA_H
-#include <glib.h> // g_assert()
+#include <cassert>
#include "decimal-round.h"
+typedef unsigned int guint32;
/**
* A class to contain a floating point RGBA color as one unit.
@@ -96,7 +97,7 @@ public:
* @return The requested value.
*/
float operator[](unsigned int const i) const {
- g_assert( unsigned(i) < 4 );
+ assert( unsigned(i) < 4 );
return _c[i];
}
diff --git a/src/color.cpp b/src/color.cpp
index dccd603b0..d7e8d25dd 100644
--- a/src/color.cpp
+++ b/src/color.cpp
@@ -12,13 +12,21 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include <math.h>
+#include <cmath>
+#include <cstdio>
+
+#define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
+#define MAX(X,Y) ((X) > (Y) ? (X) : (Y))
+
#include "color.h"
#include "svg/svg-icc-color.h"
#include "svg/svg-color.h"
#include "svg/css-ostringstream.h"
+#define return_if_fail(x) if (!(x)) { printf("assertion failed: " #x); return; }
+#define return_val_if_fail(x, val) if (!(x)) { printf("assertion failed: " #x); return val; }
+
using Inkscape::CSSOStringStream;
using std::vector;
@@ -118,7 +126,7 @@ static bool profileMatches( SVGICCColor const* first, SVGICCColor const* second
&& (first->colorProfile == second->colorProfile)
&& (first->colors.size() == second->colors.size());
if ( match ) {
- for ( guint i = 0; i < first->colors.size(); i++ ) {
+ for ( unsigned i = 0; i < first->colors.size(); i++ ) {
match &= (fabs(first->colors[i] - second->colors[i]) < PROFILE_EPSILON);
}
}
@@ -132,12 +140,12 @@ static bool profileMatches( SVGICCColor const* first, SVGICCColor const* second
*/
void SPColor::set( float r, float g, float b )
{
- g_return_if_fail(r >= 0.0);
- g_return_if_fail(r <= 1.0);
- g_return_if_fail(g >= 0.0);
- g_return_if_fail(g <= 1.0);
- g_return_if_fail(b >= 0.0);
- g_return_if_fail(b <= 1.0);
+ return_if_fail(r >= 0.0);
+ return_if_fail(r <= 1.0);
+ return_if_fail(g >= 0.0);
+ return_if_fail(g <= 1.0);
+ return_if_fail(b >= 0.0);
+ return_if_fail(b <= 1.0);
// TODO clear icc if set?
v.c[0] = r;
@@ -160,9 +168,9 @@ void SPColor::set( guint32 value )
* Convert SPColor with integer alpha value to 32bit RGBA value.
* \pre alpha < 256
*/
-guint32 SPColor::toRGBA32( gint alpha ) const
+guint32 SPColor::toRGBA32( int alpha ) const
{
- g_return_val_if_fail (alpha <= 0xff, 0x0);
+ return_val_if_fail (alpha <= 0xff, 0x0);
guint32 rgba = SP_RGBA32_U_COMPOSE( SP_COLOR_F_TO_U(v.c[0]),
SP_COLOR_F_TO_U(v.c[1]),
@@ -175,12 +183,12 @@ guint32 SPColor::toRGBA32( gint alpha ) const
* Convert SPColor with float alpha value to 32bit RGBA value.
* \pre color != NULL && 0 <= alpha <= 1
*/
-guint32 SPColor::toRGBA32( gdouble alpha ) const
+guint32 SPColor::toRGBA32( double alpha ) const
{
- g_return_val_if_fail(alpha >= 0.0, 0x0);
- g_return_val_if_fail(alpha <= 1.0, 0x0);
+ return_val_if_fail(alpha >= 0.0, 0x0);
+ return_val_if_fail(alpha <= 1.0, 0x0);
- return toRGBA32( static_cast<gint>(SP_COLOR_F_TO_U(alpha)) );
+ return toRGBA32( static_cast<int>(SP_COLOR_F_TO_U(alpha)) );
}
std::string SPColor::toString() const
@@ -215,8 +223,8 @@ std::string SPColor::toString() const
void
sp_color_get_rgb_floatv(SPColor const *color, float *rgb)
{
- g_return_if_fail (color != NULL);
- g_return_if_fail (rgb != NULL);
+ return_if_fail (color != NULL);
+ return_if_fail (rgb != NULL);
rgb[0] = color->v.c[0];
rgb[1] = color->v.c[1];
@@ -230,8 +238,8 @@ sp_color_get_rgb_floatv(SPColor const *color, float *rgb)
void
sp_color_get_cmyk_floatv(SPColor const *color, float *cmyk)
{
- g_return_if_fail (color != NULL);
- g_return_if_fail (cmyk != NULL);
+ return_if_fail (color != NULL);
+ return_if_fail (cmyk != NULL);
sp_color_rgb_to_cmyk_floatv( cmyk,
color->v.c[0],
@@ -284,7 +292,7 @@ sp_color_rgb_to_hsv_floatv (float *hsv, float r, float g, float b)
void
sp_color_hsv_to_rgb_floatv (float *rgb, float h, float s, float v)
{
- gdouble f, w, q, t, d;
+ double f, w, q, t, d;
d = h * 5.99999999;
f = d - floor (d);
diff --git a/src/color.h b/src/color.h
index 746ecebbf..887daf66b 100644
--- a/src/color.h
+++ b/src/color.h
@@ -13,8 +13,8 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include <gdk/gdk.h>
#include <string>
+typedef unsigned int guint32; // uint is guaranteed to hold up to 2^32 − 1
/* Useful composition macros */
@@ -46,13 +46,14 @@ struct SPColor {
SPColor& operator= (SPColor const& other);
bool operator == ( SPColor const& other ) const;
+ bool operator != ( SPColor const& other ) const { return !(*this == other); };
bool isClose( SPColor const& other, float epsilon ) const;
void set( float r, float g, float b );
void set( guint32 value );
- guint32 toRGBA32( gint alpha ) const;
- guint32 toRGBA32( gdouble alpha ) const;
+ guint32 toRGBA32( int alpha ) const;
+ guint32 toRGBA32( double alpha ) const;
std::string toString() const;
diff --git a/src/conn-avoid-ref.h b/src/conn-avoid-ref.h
index ce364abf1..e9e12118f 100644
--- a/src/conn-avoid-ref.h
+++ b/src/conn-avoid-ref.h
@@ -14,13 +14,13 @@
*/
#include <2geom/point.h>
-#include <glib.h>
#include <stddef.h>
#include <sigc++/connection.h>
class SPDesktop;
class SPObject;
class SPItem;
+typedef struct _GSList GSList;
namespace Avoid { class ShapeRef; }
class SPAvoidRef {
diff --git a/src/connection-pool.h b/src/connection-pool.h
deleted file mode 100644
index b1ac6f07a..000000000
--- a/src/connection-pool.h
+++ /dev/null
@@ -1,84 +0,0 @@
-#ifndef CONNECTION_POOL_H
-#define CONNECTION_POOL_H
-
-#include <map>
-#include <glib-object.h>
-#include <stddef.h>
-#include <string>
-#include <sigc++/sigc++.h>
-
-namespace Inkscape
-{
-class ConnectionPool
-{
- public:
-
- enum Exception
- {
- NAME_EXISTS,
- NAME_DOES_NOT_EXIST
- };
-
- typedef std::map<std::string, sigc::connection*> ConnectionMap;
-
- virtual ~ConnectionPool ()
- {
- for (ConnectionMap::iterator iter = map.begin (), end = map.end (); iter != end; ++iter) {
- sigc::connection* connection = (*iter).second;
- connection->disconnect ();
- delete connection;
- }
- }
-
- void
- add_connection (std::string name, sigc::connection* connection)
- {
- if (map.find (name) != map.end ()) throw NAME_EXISTS;
- map.insert (std::make_pair (name, connection));
- }
-
- void
- del_connection (std::string name)
- {
- ConnectionMap::iterator iter = map.find (name);
- if (iter == map.end ()) throw NAME_DOES_NOT_EXIST;
- sigc::connection* connection = (*iter).second;
- connection->disconnect ();
- delete connection;
- }
-
-
- static Inkscape::ConnectionPool*
- new_connection_pool (std::string name)
- {
- return new ConnectionPool (name);
- }
-
- static void
- del_connection_pool (Inkscape::ConnectionPool* pool)
- {
- delete pool;
- }
-
- static void
- connect_destroy (GObject *obj, Inkscape::ConnectionPool *pool)
- {
- g_object_connect (obj, "swapped-signal::destroy", G_CALLBACK (del_connection_pool), pool, NULL);
- }
-
- operator std::string ()
- {
- return name;
- }
-
- private:
-
- ConnectionPool (std::string name) : name (name)
- {}
-
- ConnectionMap map;
- std::string name;
-};
-}
-
-#endif
diff --git a/src/context-fns.cpp b/src/context-fns.cpp
index 1e30e51de..e1df53d98 100644
--- a/src/context-fns.cpp
+++ b/src/context-fns.cpp
@@ -1,17 +1,14 @@
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
#include <glibmm/i18n.h>
-#include "sp-item.h"
+
+#include "context-fns.h"
#include "desktop.h"
+#include "display/snap-indicator.h"
#include "message-context.h"
#include "message-stack.h"
-#include "context-fns.h"
#include "snap.h"
-#include "ui/tools/tool-base.h"
+#include "sp-item.h"
#include "sp-namedview.h"
-#include "display/snap-indicator.h"
+#include "ui/tools/tool-base.h"
static const double midpt_1_goldenratio = (1 + goldenratio) / 2;
static const double midpt_goldenratio_2 = (goldenratio + 2) / 2;
diff --git a/src/context-fns.h b/src/context-fns.h
index bd48e5fb8..82554a6c9 100644
--- a/src/context-fns.h
+++ b/src/context-fns.h
@@ -2,7 +2,6 @@
#define SEEN_CONTEXT_FNS_H
/*
- * <description>
*
* Authors:
*
@@ -11,11 +10,13 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include <gdk/gdk.h>
#include <2geom/forward.h>
-class SPDesktop;
-class SPItem;
+class SPDesktop;
+class SPItem;
+typedef union _GdkEvent GdkEvent;
+
+const double goldenratio = 1.61803398874989484820; // golden ratio
namespace Inkscape {
namespace UI {
@@ -25,12 +26,6 @@ class ToolBase;
}
}
-}
-
-const double goldenratio = 1.61803398874989484820; // golden ratio
-
-namespace Inkscape
-{
class MessageContext;
class MessageStack;
diff --git a/src/debug/gdk-event-latency-tracker.cpp b/src/debug/gdk-event-latency-tracker.cpp
index b21675f53..4679f05f1 100644
--- a/src/debug/gdk-event-latency-tracker.cpp
+++ b/src/debug/gdk-event-latency-tracker.cpp
@@ -9,6 +9,8 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
+#include <gdk/gdk.h>
+
#include "debug/gdk-event-latency-tracker.h"
#include "preferences.h"
diff --git a/src/debug/gdk-event-latency-tracker.h b/src/debug/gdk-event-latency-tracker.h
index c3624e74f..0fdb18790 100644
--- a/src/debug/gdk-event-latency-tracker.h
+++ b/src/debug/gdk-event-latency-tracker.h
@@ -12,7 +12,7 @@
#ifndef SEEN_INKSCAPE_DEBUG_GDK_EVENT_LATENCY_TRACKER_H
#define SEEN_INKSCAPE_DEBUG_GDK_EVENT_LATENCY_TRACKER_H
-#include <gdk/gdk.h>
+typedef union _GdkEvent GdkEvent;
#include <glibmm/timer.h>
#include <boost/optional.hpp>
diff --git a/src/debug/log-display-config.cpp b/src/debug/log-display-config.cpp
index 07380b3ad..ecc05b7b7 100644
--- a/src/debug/log-display-config.cpp
+++ b/src/debug/log-display-config.cpp
@@ -10,6 +10,7 @@
*/
#include <iostream>
+#include <gtk/gtk.h>
#include <gdk/gdk.h>
#include "debug/event-tracker.h"
#include "debug/logger.h"
@@ -58,11 +59,16 @@ public:
Display() : ConfigurationEvent("display") {}
void generateChildEvents() const {
GdkDisplay *display=gdk_display_get_default();
+#if GTK_CHECK_VERSION(3,10,0)
+ GdkScreen *screen = gdk_display_get_screen(display, 0);
+ Logger::write<Screen>(screen);
+#else
gint n_screens = gdk_display_get_n_screens(display);
for ( gint i = 0 ; i < n_screens ; i++ ) {
GdkScreen *screen = gdk_display_get_screen(display, i);
Logger::write<Screen>(screen);
}
+#endif
}
};
diff --git a/src/desktop-events.cpp b/src/desktop-events.cpp
index 0129a382d..5d8ea8b9f 100644
--- a/src/desktop-events.cpp
+++ b/src/desktop-events.cpp
@@ -25,7 +25,7 @@
#include "desktop.h"
#include "desktop-events.h"
#include "desktop-handles.h"
-#include "dialogs/dialog-events.h"
+#include "ui/dialog-events.h"
#include "display/canvas-axonomgrid.h"
#include "display/canvas-grid.h"
#include "display/guideline.h"
@@ -40,7 +40,7 @@
#include "display/sp-canvas.h"
#include "sp-guide.h"
#include "sp-namedview.h"
-#include "tools-switch.h"
+#include "ui/tools-switch.h"
#include "verbs.h"
#include "widgets/desktop-widget.h"
#include "xml/repr.h"
@@ -295,7 +295,7 @@ gint sp_dt_guide_event(SPCanvasItem *item, GdkEvent *event, gpointer data)
// here must be exactly on the guide line though, otherwise
// small errors will occur once we snap, see
// https://bugs.launchpad.net/inkscape/+bug/333762
- drag_origin = Geom::projection(event_dt, Geom::Line(guide->point_on_line, guide->angle()));
+ drag_origin = Geom::projection(event_dt, Geom::Line(guide->getPoint(), guide->angle()));
if (event->button.state & GDK_SHIFT_MASK) {
// with shift we rotate the guide
@@ -336,7 +336,7 @@ gint sp_dt_guide_event(SPCanvasItem *item, GdkEvent *event, gpointer data)
// be forced to be on the guide. If we don't snap however, then
// the origin should still be constrained to the guide. So let's do
// that explicitly first:
- Geom::Line line(guide->point_on_line, guide->angle());
+ Geom::Line line(guide->getPoint(), guide->angle());
Geom::Coord t = line.nearestPoint(motion_dt);
motion_dt = line.pointAt(t);
if (!(event->motion.state & GDK_SHIFT_MASK)) {
@@ -344,10 +344,15 @@ gint sp_dt_guide_event(SPCanvasItem *item, GdkEvent *event, gpointer data)
}
} else if (!((drag_type == SP_DRAG_ROTATE) && (event->motion.state & GDK_CONTROL_MASK))) {
// cannot use shift here to disable snapping, because we already use it for rotating the guide
+ Geom::Point temp;
if (drag_type == SP_DRAG_ROTATE) {
- m.guideFreeSnap(motion_dt, guide->point_on_line, true, false);
+ temp = guide->getPoint();
+ m.guideFreeSnap(motion_dt, temp, true, false);
+ guide->moveto(temp, false);
} else {
- m.guideFreeSnap(motion_dt, guide->normal_to_line, false, true);
+ temp = guide->getNormal();
+ m.guideFreeSnap(motion_dt, temp, false, true);
+ guide->set_normal(temp, false);
}
}
m.unSetup();
@@ -355,20 +360,20 @@ gint sp_dt_guide_event(SPCanvasItem *item, GdkEvent *event, gpointer data)
switch (drag_type) {
case SP_DRAG_TRANSLATE:
{
- sp_guide_moveto(*guide, motion_dt, false);
+ guide->moveto(motion_dt, false);
break;
}
case SP_DRAG_ROTATE:
{
- Geom::Point pt = motion_dt - guide->point_on_line;
+ Geom::Point pt = motion_dt - guide->getPoint();
Geom::Angle angle(pt);
if (event->motion.state & GDK_CONTROL_MASK) {
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
unsigned const snaps = abs(prefs->getInt("/options/rotationsnapsperpi/value", 12));
- bool const relative_snaps = abs(prefs->getBool("/options/relativeguiderotationsnap/value", false));
+ bool const relative_snaps = prefs->getBool("/options/relativeguiderotationsnap/value", false);
if (snaps) {
if (relative_snaps) {
- Geom::Angle orig_angle(guide->normal_to_line);
+ Geom::Angle orig_angle(guide->getNormal());
Geom::Angle snap_angle = angle - orig_angle;
double sections = floor(snap_angle.radians0() * snaps / M_PI + .5);
angle = (M_PI / snaps) * sections + orig_angle.radians0();
@@ -378,16 +383,16 @@ gint sp_dt_guide_event(SPCanvasItem *item, GdkEvent *event, gpointer data)
}
}
}
- sp_guide_set_normal(*guide, Geom::Point::polar(angle).cw(), false);
+ guide->set_normal(Geom::Point::polar(angle).cw(), false);
break;
}
case SP_DRAG_MOVE_ORIGIN:
{
- sp_guide_moveto(*guide, motion_dt, false);
+ guide->moveto(motion_dt, false);
break;
}
case SP_DRAG_NONE:
- g_assert_not_reached();
+ assert(false);
break;
}
moved = true;
@@ -412,7 +417,7 @@ gint sp_dt_guide_event(SPCanvasItem *item, GdkEvent *event, gpointer data)
// be forced to be on the guide. If we don't snap however, then
// the origin should still be constrained to the guide. So let's
// do that explicitly first:
- Geom::Line line(guide->point_on_line, guide->angle());
+ Geom::Line line(guide->getPoint(), guide->angle());
Geom::Coord t = line.nearestPoint(event_dt);
event_dt = line.pointAt(t);
if (!(event->button.state & GDK_SHIFT_MASK)) {
@@ -420,10 +425,15 @@ gint sp_dt_guide_event(SPCanvasItem *item, GdkEvent *event, gpointer data)
}
} else if (!((drag_type == SP_DRAG_ROTATE) && (event->motion.state & GDK_CONTROL_MASK))) {
// cannot use shift here to disable snapping, because we already use it for rotating the guide
+ Geom::Point temp;
if (drag_type == SP_DRAG_ROTATE) {
- m.guideFreeSnap(event_dt, guide->point_on_line, true, false);
+ temp = guide->getPoint();
+ m.guideFreeSnap(event_dt, temp, true, false);
+ guide->moveto(temp, false);
} else {
- m.guideFreeSnap(event_dt, guide->normal_to_line, false, true);
+ temp = guide->getNormal();
+ m.guideFreeSnap(event_dt, temp, false, true);
+ guide->set_normal(temp, false);
}
}
m.unSetup();
@@ -432,20 +442,20 @@ gint sp_dt_guide_event(SPCanvasItem *item, GdkEvent *event, gpointer data)
switch (drag_type) {
case SP_DRAG_TRANSLATE:
{
- sp_guide_moveto(*guide, event_dt, true);
+ guide->moveto(event_dt, true);
break;
}
case SP_DRAG_ROTATE:
{
- Geom::Point pt = event_dt - guide->point_on_line;
+ Geom::Point pt = event_dt - guide->getPoint();
Geom::Angle angle(pt);
if (event->motion.state & GDK_CONTROL_MASK) {
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
unsigned const snaps = abs(prefs->getInt("/options/rotationsnapsperpi/value", 12));
- bool const relative_snaps = abs(prefs->getBool("/options/relativeguiderotationsnap/value", false));
+ bool const relative_snaps = prefs->getBool("/options/relativeguiderotationsnap/value", false);
if (snaps) {
if (relative_snaps) {
- Geom::Angle orig_angle(guide->normal_to_line);
+ Geom::Angle orig_angle(guide->getNormal());
Geom::Angle snap_angle = angle - orig_angle;
double sections = floor(snap_angle.radians0() * snaps / M_PI + .5);
angle = (M_PI / snaps) * sections + orig_angle.radians0();
@@ -455,24 +465,24 @@ gint sp_dt_guide_event(SPCanvasItem *item, GdkEvent *event, gpointer data)
}
}
}
- sp_guide_set_normal(*guide, Geom::Point::polar(angle).cw(), true);
+ guide->set_normal(Geom::Point::polar(angle).cw(), true);
break;
}
case SP_DRAG_MOVE_ORIGIN:
{
- sp_guide_moveto(*guide, event_dt, true);
+ guide->moveto(event_dt, true);
break;
}
case SP_DRAG_NONE:
- g_assert_not_reached();
+ assert(false);
break;
}
DocumentUndo::done(sp_desktop_document(desktop), SP_VERB_NONE,
_("Move guide"));
} else {
/* Undo movement of any attached shapes. */
- sp_guide_moveto(*guide, guide->point_on_line, false);
- sp_guide_set_normal(*guide, guide->normal_to_line, false);
+ guide->moveto(guide->getPoint(), false);
+ guide->set_normal(guide->getNormal(), false);
sp_guide_remove(guide);
DocumentUndo::done(sp_desktop_document(desktop), SP_VERB_NONE,
_("Delete guide"));
@@ -487,11 +497,10 @@ gint sp_dt_guide_event(SPCanvasItem *item, GdkEvent *event, gpointer data)
break;
case GDK_ENTER_NOTIFY:
{
- sp_guideline_set_color(SP_GUIDELINE(item), guide->hicolor);
+ sp_guideline_set_color(SP_GUIDELINE(item), guide->getHiColor());
// set move or rotate cursor
Geom::Point const event_w(event->crossing.x, event->crossing.y);
- Geom::Point const event_dt(desktop->w2d(event_w));
if ((event->crossing.state & GDK_SHIFT_MASK) && (drag_type != SP_DRAG_MOVE_ORIGIN)) {
GdkCursor *guide_cursor;
@@ -513,13 +522,13 @@ gint sp_dt_guide_event(SPCanvasItem *item, GdkEvent *event, gpointer data)
#endif
}
- char *guide_description = sp_guide_description(guide);
+ char *guide_description = guide->description();
desktop->guidesMessageContext()->setF(Inkscape::NORMAL_MESSAGE, _("<b>Guideline</b>: %s"), guide_description);
g_free(guide_description);
break;
}
case GDK_LEAVE_NOTIFY:
- sp_guideline_set_color(SP_GUIDELINE(item), guide->color);
+ sp_guideline_set_color(SP_GUIDELINE(item), guide->getColor());
// restore event context's cursor
gdk_window_set_cursor(gtk_widget_get_window (GTK_WIDGET(sp_desktop_canvas(desktop))), desktop->event_context->cursor);
diff --git a/src/desktop-events.h b/src/desktop-events.h
index 7123ce91b..dc85e563b 100644
--- a/src/desktop-events.h
+++ b/src/desktop-events.h
@@ -13,13 +13,15 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include <gdk/gdk.h>
-#include <gtk/gtk.h>
-
class SPDesktop;
struct SPDesktopWidget;
struct SPCanvasItem;
+typedef union _GdkEvent GdkEvent;
+typedef struct _GdkEventCrossing GdkEventCrossing;
+typedef struct _GdkEventMotion GdkEventMotion;
+typedef struct _GtkWidget GtkWidget;
+
/* Item handlers */
int sp_desktop_root_handler (SPCanvasItem *item, GdkEvent *event, SPDesktop *desktop);
diff --git a/src/desktop-style.cpp b/src/desktop-style.cpp
index bab9635a9..30869d87d 100644
--- a/src/desktop-style.cpp
+++ b/src/desktop-style.cpp
@@ -14,6 +14,7 @@
#include <string>
#include <cstring>
+#include <glibmm.h>
#include "desktop.h"
#include "color-rgba.h"
@@ -40,7 +41,6 @@
#include "sp-tspan.h"
#include "xml/repr.h"
#include "xml/sp-css-attr.h"
-#include "libnrtype/font-style-to-pos.h"
#include "sp-path.h"
#include "ui/tools/tool-base.h"
@@ -49,6 +49,24 @@
#include "box3d-side.h"
#include <2geom/math-utils.h>
+namespace {
+
+bool isTextualItem(SPObject const *obj)
+{
+ bool isTextual = dynamic_cast<SPText const *>(obj) //
+ || dynamic_cast<SPFlowtext const *>(obj) //
+ || dynamic_cast<SPTSpan const *>(obj) //
+ || dynamic_cast<SPTRef const *>(obj) //
+ || dynamic_cast<SPTextPath const *>(obj) //
+ || dynamic_cast<SPFlowdiv const *>(obj) //
+ || dynamic_cast<SPFlowpara const *>(obj) //
+ || dynamic_cast<SPFlowtspan const *>(obj);
+
+ return isTextual;
+}
+
+} // namespace
+
/**
* Set color on selection on desktop.
*/
@@ -89,8 +107,10 @@ void
sp_desktop_apply_css_recursive(SPObject *o, SPCSSAttr *css, bool skip_lines)
{
// non-items should not have style
- if (!SP_IS_ITEM(o))
+ SPItem *item = dynamic_cast<SPItem *>(o);
+ if (!item) {
return;
+ }
// 1. tspans with role=line are not regular objects in that they are not supposed to have style of their own,
// but must always inherit from the parent text. Same for textPath.
@@ -100,22 +120,24 @@ sp_desktop_apply_css_recursive(SPObject *o, SPCSSAttr *css, bool skip_lines)
// it, be it clone or not; it's just styleless shape (because that's how Inkscape does
// flowtext).
+ SPTSpan *tspan = dynamic_cast<SPTSpan *>(o);
+
if (!(skip_lines
- && ((SP_IS_TSPAN(o) && SP_TSPAN(o)->role == SP_TSPAN_ROLE_LINE)
- || SP_IS_FLOWDIV(o)
- || SP_IS_FLOWPARA(o)
- || SP_IS_TEXTPATH(o))
+ && ((tspan && tspan->role == SP_TSPAN_ROLE_LINE)
+ || dynamic_cast<SPFlowdiv *>(o)
+ || dynamic_cast<SPFlowpara *>(o)
+ || dynamic_cast<SPTextPath *>(o))
&& !o->getAttribute("style"))
&&
- !(SP_IS_FLOWREGION(o) ||
- SP_IS_FLOWREGIONEXCLUDE(o) ||
- (SP_IS_USE(o) &&
+ !(dynamic_cast<SPFlowregionbreak *>(o) ||
+ dynamic_cast<SPFlowregionExclude *>(o) ||
+ (dynamic_cast<SPUse *>(o) &&
o->parent &&
- (SP_IS_FLOWREGION(o->parent) ||
- SP_IS_FLOWREGIONEXCLUDE(o->parent)
- )
- )
- )
+ (dynamic_cast<SPFlowregion *>(o->parent) ||
+ dynamic_cast<SPFlowregionExclude *>(o->parent)
+ )
+ )
+ )
) {
SPCSSAttr *css_set = sp_repr_css_attr_new();
@@ -123,7 +145,7 @@ sp_desktop_apply_css_recursive(SPObject *o, SPCSSAttr *css, bool skip_lines)
// Scale the style by the inverse of the accumulated parent transform in the paste context.
{
- Geom::Affine const local(SP_ITEM(o)->i2doc_affine());
+ Geom::Affine const local(item->i2doc_affine());
double const ex(local.descrim());
if ( ( ex != 0. )
&& ( ex != 1. ) ) {
@@ -137,8 +159,9 @@ sp_desktop_apply_css_recursive(SPObject *o, SPCSSAttr *css, bool skip_lines)
}
// setting style on child of clone spills into the clone original (via shared repr), don't do it!
- if (SP_IS_USE(o))
+ if (dynamic_cast<SPUse *>(o)) {
return;
+ }
for ( SPObject *child = o->firstChild() ; child ; child = child->getNext() ) {
if (sp_repr_css_property(css, "opacity", NULL) != NULL) {
@@ -174,8 +197,10 @@ sp_desktop_set_style(SPDesktop *desktop, SPCSSAttr *css, bool change, bool write
for (const GSList *i = desktop->selection->itemList(); i != NULL; i = i->next) {
/* last used styles for 3D box faces are stored separately */
- if (SP_IS_BOX3D_SIDE (i->data)) {
- const char * descr = box3d_side_axes_string(SP_BOX3D_SIDE(i->data));
+ SPObject *obj = reinterpret_cast<SPObject *>(i->data); // TODO unsafe until Selection is refactored.
+ Box3DSide *side = dynamic_cast<Box3DSide *>(obj);
+ if (side) {
+ const char * descr = box3d_side_axes_string(side);
if (descr != NULL) {
prefs->mergeStyle(Glib::ustring("/desktop/") + descr + "/style", css_write);
}
@@ -210,17 +235,22 @@ sp_desktop_set_style(SPDesktop *desktop, SPCSSAttr *css, bool change, bool write
css_no_text = sp_css_attr_unset_text(css_no_text);
for (GSList const *i = desktop->selection->itemList(); i != NULL; i = i->next) {
+ SPItem *item = reinterpret_cast<SPItem *>(i->data);
+
+ // If not text, don't apply text attributes (can a group have text attributes? Yes! FIXME)
+ if (isTextualItem(item)) {
- // If not text, don't apply text attributes (can a group have text attributes?)
- if ( SP_IS_TEXT(i->data) || SP_IS_FLOWTEXT(i->data)
- || SP_IS_TSPAN(i->data) || SP_IS_TREF(i->data) || SP_IS_TEXTPATH(i->data)
- || SP_IS_FLOWDIV(i->data) || SP_IS_FLOWPARA(i->data) || SP_IS_FLOWTSPAN(i->data)) {
+ // If any font property has changed, then we have written out the font
+ // properties in longhand and we need to remove the 'font' shorthand.
+ if( !sp_repr_css_property_is_unset(css, "font-family") ) {
+ sp_repr_css_unset_property(css, "font");
+ }
- sp_desktop_apply_css_recursive(SP_OBJECT(i->data), css, true);
+ sp_desktop_apply_css_recursive(item, css, true);
} else {
- sp_desktop_apply_css_recursive(SP_OBJECT(i->data), css_no_text, true);
+ sp_desktop_apply_css_recursive(item, css_no_text, true);
}
}
@@ -419,16 +449,17 @@ stroke_average_width (GSList const *objects)
int n_notstroked = 0;
for (GSList const *l = objects; l != NULL; l = l->next) {
- if (!SP_IS_ITEM (l->data))
+ SPObject *obj = reinterpret_cast<SPObject *>(l->data);
+ SPItem *item = dynamic_cast<SPItem *>(obj);
+ if (!item) {
continue;
+ }
- Geom::Affine i2dt = SP_ITEM(l->data)->i2dt_affine();
-
- SPObject *object = SP_OBJECT(l->data);
+ Geom::Affine i2dt = item->i2dt_affine();
- double width = object->style->stroke_width.computed * i2dt.descrim();
+ double width = item->style->stroke_width.computed * i2dt.descrim();
- if ( object->style->stroke.isNone() || IS_NAN(width)) {
+ if ( item->style->stroke.isNone() || IS_NAN(width)) {
++n_notstroked; // do not count nonstroked objects
continue;
} else {
@@ -485,7 +516,10 @@ objects_query_fillstroke (GSList *objects, SPStyle *style_res, bool const isfill
bool same_color = true;
for (GSList const *i = objects; i != NULL; i = i->next) {
- SPObject *obj = SP_OBJECT (i->data);
+ SPObject *obj = reinterpret_cast<SPObject *>(i->data);
+ if (!obj) {
+ continue;
+ }
SPStyle *style = obj->style;
if (!style) {
continue;
@@ -496,9 +530,9 @@ objects_query_fillstroke (GSList *objects, SPStyle *style_res, bool const isfill
// We consider paint "effectively set" for anything within text hierarchy
SPObject *parent = obj->parent;
bool paint_effectively_set =
- paint->set || (SP_IS_TEXT(parent) || SP_IS_TEXTPATH(parent) || SP_IS_TSPAN(parent)
- || SP_IS_FLOWTEXT(parent) || SP_IS_FLOWDIV(parent) || SP_IS_FLOWPARA(parent)
- || SP_IS_FLOWTSPAN(parent) || SP_IS_FLOWLINE(parent));
+ paint->set || (dynamic_cast<SPText *>(parent) || dynamic_cast<SPTextPath *>(parent) || dynamic_cast<SPTSpan *>(parent)
+ || dynamic_cast<SPFlowtext *>(parent) || dynamic_cast<SPFlowdiv *>(parent) || dynamic_cast<SPFlowpara *>(parent)
+ || dynamic_cast<SPFlowtspan *>(parent) || dynamic_cast<SPFlowline*>(parent));
// 1. Bail out with QUERY_STYLE_MULTIPLE_DIFFERENT if necessary
@@ -510,38 +544,45 @@ objects_query_fillstroke (GSList *objects, SPStyle *style_res, bool const isfill
if (paint_res->set && paint->set && paint_res->isPaintserver()) {
// both previous paint and this paint were a server, see if the servers are compatible
- SPPaintServer *server_res = isfill? SP_STYLE_FILL_SERVER (style_res) : SP_STYLE_STROKE_SERVER (style_res);
- SPPaintServer *server = isfill? SP_STYLE_FILL_SERVER (style) : SP_STYLE_STROKE_SERVER (style);
+ SPPaintServer *server_res = isfill ? style_res->getFillPaintServer() : style_res->getStrokePaintServer();
+ SPPaintServer *server = isfill ? style->getFillPaintServer() : style->getStrokePaintServer();
- if (SP_IS_LINEARGRADIENT (server_res)) {
-
- if (!SP_IS_LINEARGRADIENT(server))
+ SPLinearGradient *linear_res = dynamic_cast<SPLinearGradient *>(server_res);
+ SPRadialGradient *radial_res = linear_res ? NULL : dynamic_cast<SPRadialGradient *>(server_res);
+ SPPattern *pattern_res = (linear_res || radial_res) ? NULL : dynamic_cast<SPPattern *>(server_res);
+ if (linear_res) {
+ SPLinearGradient *linear = dynamic_cast<SPLinearGradient *>(server);
+ if (!linear) {
return QUERY_STYLE_MULTIPLE_DIFFERENT; // different kind of server
+ }
- SPGradient *vector = SP_GRADIENT(server)->getVector();
- SPGradient *vector_res = SP_GRADIENT(server_res)->getVector();
- if (vector_res != vector)
+ SPGradient *vector = linear->getVector();
+ SPGradient *vector_res = linear_res->getVector();
+ if (vector_res != vector) {
return QUERY_STYLE_MULTIPLE_DIFFERENT; // different gradient vectors
-
- } else if (SP_IS_RADIALGRADIENT (server_res)) {
-
- if (!SP_IS_RADIALGRADIENT(server))
+ }
+ } else if (radial_res) {
+ SPRadialGradient *radial = dynamic_cast<SPRadialGradient *>(server);
+ if (!radial) {
return QUERY_STYLE_MULTIPLE_DIFFERENT; // different kind of server
+ }
- SPGradient *vector = SP_GRADIENT(server)->getVector();
- SPGradient *vector_res = SP_GRADIENT(server_res)->getVector();
- if (vector_res != vector)
+ SPGradient *vector = radial->getVector();
+ SPGradient *vector_res = radial_res->getVector();
+ if (vector_res != vector) {
return QUERY_STYLE_MULTIPLE_DIFFERENT; // different gradient vectors
-
- } else if (SP_IS_PATTERN (server_res)) {
-
- if (!SP_IS_PATTERN(server))
+ }
+ } else if (pattern_res) {
+ SPPattern *pattern = dynamic_cast<SPPattern *>(server);
+ if (!pattern) {
return QUERY_STYLE_MULTIPLE_DIFFERENT; // different kind of server
+ }
- SPPattern *pat = pattern_getroot (SP_PATTERN (server));
- SPPattern *pat_res = pattern_getroot (SP_PATTERN (server_res));
- if (pat_res != pat)
+ SPPattern *pat = pattern_getroot (pattern);
+ SPPattern *pat_res = pattern_getroot (pattern_res);
+ if (pat_res != pat) {
return QUERY_STYLE_MULTIPLE_DIFFERENT; // different pattern roots
+ }
}
}
@@ -659,7 +700,10 @@ objects_query_opacity (GSList *objects, SPStyle *style_res)
for (GSList const *i = objects; i != NULL; i = i->next) {
- SPObject *obj = SP_OBJECT (i->data);
+ SPObject *obj = reinterpret_cast<SPObject *>(i->data);
+ if (!obj) {
+ continue;
+ }
SPStyle *style = obj->style;
if (!style) {
continue;
@@ -712,8 +756,12 @@ objects_query_strokewidth (GSList *objects, SPStyle *style_res)
int n_stroked = 0;
for (GSList const *i = objects; i != NULL; i = i->next) {
- SPObject *obj = SP_OBJECT (i->data);
- if (!SP_IS_ITEM(obj)) {
+ SPObject *obj = reinterpret_cast<SPObject *>(i->data);
+ if (!obj) {
+ continue;
+ }
+ SPItem *item = dynamic_cast<SPItem *>(obj);
+ if (!item) {
continue;
}
SPStyle *style = obj->style;
@@ -722,17 +770,17 @@ objects_query_strokewidth (GSList *objects, SPStyle *style_res)
}
if ( style->stroke.isNone() && !(
- style->marker[SP_MARKER_LOC].set || // stroke width affects markers, so if there's no stroke but only markers then we should
- style->marker[SP_MARKER_LOC_START].set || // still calculate the stroke width
- style->marker[SP_MARKER_LOC_MID].set ||
- style->marker[SP_MARKER_LOC_END].set))
+ style->marker.set || // stroke width affects markers, so if there's no
+ style->marker_start.set || // stroke but only markers then we should
+ style->marker_mid.set || // still calculate the stroke width
+ style->marker_end.set))
{
continue;
}
noneSet &= style->stroke.isNone();
- Geom::Affine i2d = SP_ITEM(obj)->i2dt_affine();
+ Geom::Affine i2d = item->i2dt_affine();
double sw = style->stroke_width.computed * i2d.descrim();
if (!IS_NAN(sw)) {
@@ -782,8 +830,8 @@ objects_query_miterlimit (GSList *objects, SPStyle *style_res)
bool same_ml = true;
for (GSList const *i = objects; i != NULL; i = i->next) {
- SPObject *obj = SP_OBJECT (i->data);
- if (!SP_IS_ITEM(obj)) {
+ SPObject *obj = reinterpret_cast<SPObject *>(i->data);
+ if (!dynamic_cast<SPItem *>(obj)) {
continue;
}
SPStyle *style = obj->style;
@@ -841,8 +889,8 @@ objects_query_strokecap (GSList *objects, SPStyle *style_res)
int n_stroked = 0;
for (GSList const *i = objects; i != NULL; i = i->next) {
- SPObject *obj = SP_OBJECT (i->data);
- if (!SP_IS_ITEM(obj)) {
+ SPObject *obj = reinterpret_cast<SPObject *>(i->data);
+ if (!dynamic_cast<SPItem *>(obj)) {
continue;
}
SPStyle *style = obj->style;
@@ -895,8 +943,8 @@ objects_query_strokejoin (GSList *objects, SPStyle *style_res)
int n_stroked = 0;
for (GSList const *i = objects; i != NULL; i = i->next) {
- SPObject *obj = SP_OBJECT (i->data);
- if (!SP_IS_ITEM(obj)) {
+ SPObject *obj = reinterpret_cast<SPObject *>(i->data);
+ if (!dynamic_cast<SPItem *>(obj)) {
continue;
}
SPStyle *style = obj->style;
@@ -958,11 +1006,9 @@ objects_query_fontnumbers (GSList *objects, SPStyle *style_res)
int no_size = 0;
for (GSList const *i = objects; i != NULL; i = i->next) {
- SPObject *obj = SP_OBJECT (i->data);
+ SPObject *obj = reinterpret_cast<SPObject *>(i->data);
- if (!SP_IS_TEXT(obj) && !SP_IS_FLOWTEXT(obj)
- && !SP_IS_TSPAN(obj) && !SP_IS_TREF(obj) && !SP_IS_TEXTPATH(obj)
- && !SP_IS_FLOWDIV(obj) && !SP_IS_FLOWPARA(obj) && !SP_IS_FLOWTSPAN(obj)) {
+ if (!isTextualItem(obj)) {
continue;
}
@@ -972,7 +1018,9 @@ objects_query_fontnumbers (GSList *objects, SPStyle *style_res)
}
texts ++;
- double dummy = style->font_size.computed * Geom::Affine(SP_ITEM(obj)->i2dt_affine()).descrim();
+ SPItem *item = dynamic_cast<SPItem *>(obj);
+ g_assert(item != NULL);
+ double dummy = style->font_size.computed * Geom::Affine(item->i2dt_affine()).descrim();
if (!IS_NAN(dummy)) {
size += dummy; /// \todo FIXME: we assume non-% units here
} else {
@@ -1005,8 +1053,8 @@ objects_query_fontnumbers (GSList *objects, SPStyle *style_res)
} else if (style->line_height.unit == SP_CSS_UNIT_PERCENT || style->font_size.computed == 0) {
linespacing_current = style->line_height.value;
linespacing_normal = false;
- } else { // we need % here
- linespacing_current = style->line_height.computed / style->font_size.computed;
+ } else {
+ linespacing_current = style->line_height.computed;
linespacing_normal = false;
}
linespacing += linespacing_current;
@@ -1077,12 +1125,11 @@ objects_query_fontstyle (GSList *objects, SPStyle *style_res)
int texts = 0;
for (GSList const *i = objects; i != NULL; i = i->next) {
- SPObject *obj = SP_OBJECT (i->data);
+ SPObject *obj = reinterpret_cast<SPObject *>(i->data);
- if (!SP_IS_TEXT(obj) && !SP_IS_FLOWTEXT(obj)
- && !SP_IS_TSPAN(obj) && !SP_IS_TREF(obj) && !SP_IS_TEXTPATH(obj)
- && !SP_IS_FLOWDIV(obj) && !SP_IS_FLOWPARA(obj) && !SP_IS_FLOWTSPAN(obj))
+ if (!isTextualItem(obj)) {
continue;
+ }
SPStyle *style = obj->style;
if (!style) {
@@ -1092,7 +1139,10 @@ objects_query_fontstyle (GSList *objects, SPStyle *style_res)
texts ++;
if (set &&
- font_style_to_pos(*style_res).signature() != font_style_to_pos(*style).signature() ) {
+ ( ( style_res->font_weight.computed != style->font_weight.computed ) ||
+ ( style_res->font_style.computed != style->font_style.computed ) ||
+ ( style_res->font_stretch.computed != style->font_stretch.computed ) ||
+ ( style_res->font_variant.computed != style->font_variant.computed ) ) ) {
different = true; // different styles
}
@@ -1144,11 +1194,9 @@ objects_query_baselines (GSList *objects, SPStyle *style_res)
int texts = 0;
for (GSList const *i = objects; i != NULL; i = i->next) {
- SPObject *obj = SP_OBJECT (i->data);
+ SPObject *obj = reinterpret_cast<SPObject *>(i->data);
- if (!SP_IS_TEXT(obj) && !SP_IS_FLOWTEXT(obj)
- && !SP_IS_TSPAN(obj) && !SP_IS_TREF(obj) && !SP_IS_TEXTPATH(obj)
- && !SP_IS_FLOWDIV(obj) && !SP_IS_FLOWPARA(obj) && !SP_IS_FLOWTSPAN(obj)) {
+ if (!isTextualItem(obj)) {
continue;
}
@@ -1227,19 +1275,17 @@ objects_query_fontfamily (GSList *objects, SPStyle *style_res)
bool different = false;
int texts = 0;
- if (style_res->text->font_family.value) {
- g_free(style_res->text->font_family.value);
- style_res->text->font_family.value = NULL;
+ if (style_res->font_family.value) {
+ g_free(style_res->font_family.value);
+ style_res->font_family.value = NULL;
}
- style_res->text->font_family.set = FALSE;
+ style_res->font_family.set = FALSE;
for (GSList const *i = objects; i != NULL; i = i->next) {
- SPObject *obj = SP_OBJECT (i->data);
+ SPObject *obj = reinterpret_cast<SPObject *>(i->data);
// std::cout << " " << reinterpret_cast<SPObject*>(i->data)->getId() << std::endl;
- if (!SP_IS_TEXT(obj) && !SP_IS_FLOWTEXT(obj)
- && !SP_IS_TSPAN(obj) && !SP_IS_TREF(obj) && !SP_IS_TEXTPATH(obj)
- && !SP_IS_FLOWDIV(obj) && !SP_IS_FLOWPARA(obj) && !SP_IS_FLOWTSPAN(obj)) {
+ if (!isTextualItem(obj)) {
continue;
}
@@ -1250,21 +1296,21 @@ objects_query_fontfamily (GSList *objects, SPStyle *style_res)
texts ++;
- if (style_res->text->font_family.value && style->text->font_family.value &&
- strcmp (style_res->text->font_family.value, style->text->font_family.value)) {
+ if (style_res->font_family.value && style->font_family.value &&
+ strcmp (style_res->font_family.value, style->font_family.value)) {
different = true; // different fonts
}
- if (style_res->text->font_family.value) {
- g_free(style_res->text->font_family.value);
- style_res->text->font_family.value = NULL;
+ if (style_res->font_family.value) {
+ g_free(style_res->font_family.value);
+ style_res->font_family.value = NULL;
}
- style_res->text->font_family.set = TRUE;
- style_res->text->font_family.value = g_strdup(style->text->font_family.value);
+ style_res->font_family.set = TRUE;
+ style_res->font_family.value = g_strdup(style->font_family.value);
}
- if (texts == 0 || !style_res->text->font_family.set) {
+ if (texts == 0 || !style_res->font_family.set) {
return QUERY_STYLE_NOTHING;
}
@@ -1285,19 +1331,17 @@ objects_query_fontspecification (GSList *objects, SPStyle *style_res)
bool different = false;
int texts = 0;
- if (style_res->text->font_specification.value) {
- g_free(style_res->text->font_specification.value);
- style_res->text->font_specification.value = NULL;
+ if (style_res->font_specification.value) {
+ g_free(style_res->font_specification.value);
+ style_res->font_specification.value = NULL;
}
- style_res->text->font_specification.set = FALSE;
+ style_res->font_specification.set = FALSE;
for (GSList const *i = objects; i != NULL; i = i->next) {
- SPObject *obj = SP_OBJECT (i->data);
+ SPObject *obj = reinterpret_cast<SPObject *>(i->data);
// std::cout << " " << reinterpret_cast<SPObject*>(i->data)->getId() << std::endl;
- if (!SP_IS_TEXT(obj) && !SP_IS_FLOWTEXT(obj)
- && !SP_IS_TSPAN(obj) && !SP_IS_TREF(obj) && !SP_IS_TEXTPATH(obj)
- && !SP_IS_FLOWDIV(obj) && !SP_IS_FLOWPARA(obj) && !SP_IS_FLOWTSPAN(obj)) {
+ if (!isTextualItem(obj)) {
continue;
}
@@ -1308,21 +1352,21 @@ objects_query_fontspecification (GSList *objects, SPStyle *style_res)
texts ++;
- if (style_res->text->font_specification.value && style_res->text->font_specification.set &&
- style->text->font_specification.value && style->text->font_specification.set &&
- strcmp (style_res->text->font_specification.value, style->text->font_specification.value)) {
+ if (style_res->font_specification.value && style_res->font_specification.set &&
+ style->font_specification.value && style->font_specification.set &&
+ strcmp (style_res->font_specification.value, style->font_specification.value)) {
different = true; // different fonts
}
- if (style->text->font_specification.set) {
+ if (style->font_specification.set) {
- if (style_res->text->font_specification.value) {
- g_free(style_res->text->font_specification.value);
- style_res->text->font_specification.value = NULL;
+ if (style_res->font_specification.value) {
+ g_free(style_res->font_specification.value);
+ style_res->font_specification.value = NULL;
}
- style_res->text->font_specification.set = TRUE;
- style_res->text->font_specification.value = g_strdup(style->text->font_specification.value);
+ style_res->font_specification.set = TRUE;
+ style_res->font_specification.value = g_strdup(style->font_specification.value);
}
}
@@ -1352,9 +1396,12 @@ objects_query_blend (GSList *objects, SPStyle *style_res)
guint items = 0;
for (GSList const *i = objects; i != NULL; i = i->next) {
- SPObject *obj = SP_OBJECT (i->data);
+ SPObject *obj = reinterpret_cast<SPObject *>(i->data);
+ if (!obj) {
+ continue;
+ }
SPStyle *style = obj->style;
- if (!style || !SP_IS_ITEM(obj)) {
+ if (!style || !dynamic_cast<SPItem *>(obj)) {
continue;
}
@@ -1367,14 +1414,14 @@ objects_query_blend (GSList *objects, SPStyle *style_res)
// determine whether filter is simple (blend and/or blur) or complex
for(SPObject *primitive_obj = style->getFilter()->children;
- primitive_obj && SP_IS_FILTER_PRIMITIVE(primitive_obj);
+ primitive_obj && dynamic_cast<SPFilterPrimitive *>(primitive_obj);
primitive_obj = primitive_obj->next) {
- SPFilterPrimitive *primitive = SP_FILTER_PRIMITIVE(primitive_obj);
- if(SP_IS_FEBLEND(primitive))
+ SPFilterPrimitive *primitive = dynamic_cast<SPFilterPrimitive *>(primitive_obj);
+ if (dynamic_cast<SPFeBlend *>(primitive)) {
++blendcount;
- else if(SP_IS_GAUSSIANBLUR(primitive))
+ } else if (dynamic_cast<SPGaussianBlur *>(primitive)) {
++blurcount;
- else {
+ } else {
blurcount = complex_filter;
break;
}
@@ -1383,10 +1430,10 @@ objects_query_blend (GSList *objects, SPStyle *style_res)
// simple filter
if(blurcount == 1 || blendcount == 1) {
for(SPObject *primitive_obj = style->getFilter()->children;
- primitive_obj && SP_IS_FILTER_PRIMITIVE(primitive_obj);
+ primitive_obj && dynamic_cast<SPFilterPrimitive *>(primitive_obj);
primitive_obj = primitive_obj->next) {
- if(SP_IS_FEBLEND(primitive_obj)) {
- SPFeBlend *spblend = SP_FEBLEND(primitive_obj);
+ SPFeBlend *spblend = dynamic_cast<SPFeBlend *>(primitive_obj);
+ if (spblend) {
blend = spblend->blend_mode;
}
}
@@ -1439,16 +1486,20 @@ objects_query_blur (GSList *objects, SPStyle *style_res)
guint items = 0;
for (GSList const *i = objects; i != NULL; i = i->next) {
- SPObject *obj = SP_OBJECT (i->data);
+ SPObject *obj = reinterpret_cast<SPObject *>(i->data);
+ if (!obj) {
+ continue;
+ }
SPStyle *style = obj->style;
if (!style) {
continue;
}
- if (!SP_IS_ITEM(obj)) {
+ SPItem *item = dynamic_cast<SPItem *>(obj);
+ if (!item) {
continue;
}
- Geom::Affine i2d = SP_ITEM(obj)->i2dt_affine();
+ Geom::Affine i2d = item->i2dt_affine();
items ++;
@@ -1457,12 +1508,12 @@ objects_query_blur (GSList *objects, SPStyle *style_res)
//cycle through filter primitives
SPObject *primitive_obj = style->getFilter()->children;
while (primitive_obj) {
- if (SP_IS_FILTER_PRIMITIVE(primitive_obj)) {
- SPFilterPrimitive *primitive = SP_FILTER_PRIMITIVE(primitive_obj);
+ SPFilterPrimitive *primitive = dynamic_cast<SPFilterPrimitive *>(primitive_obj);
+ if (primitive) {
//if primitive is gaussianblur
- if(SP_IS_GAUSSIANBLUR(primitive)) {
- SPGaussianBlur * spblur = SP_GAUSSIANBLUR(primitive);
+ SPGaussianBlur * spblur = dynamic_cast<SPGaussianBlur *>(primitive);
+ if (spblur) {
float num = spblur->stdDeviation.getNumber();
float dummy = num * i2d.descrim();
if (!IS_NAN(dummy)) {
diff --git a/src/desktop-style.h b/src/desktop-style.h
index 47575de75..40ca27e9e 100644
--- a/src/desktop-style.h
+++ b/src/desktop-style.h
@@ -13,13 +13,12 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include <glib.h>
-
class ColorRGBA;
-class SPCSSAttr;
-class SPDesktop;
-class SPObject;
-struct SPStyle;
+class SPCSSAttr;
+class SPDesktop;
+class SPObject;
+class SPStyle;
+typedef struct _GSList GSList;
namespace Inkscape {
namespace XML {
class Node;
diff --git a/src/desktop.cpp b/src/desktop.cpp
index 22c00d4f1..74dea3ca1 100644
--- a/src/desktop.cpp
+++ b/src/desktop.cpp
@@ -55,7 +55,7 @@
#include "document-undo.h"
#include "event-log.h"
#include "helper/action-context.h"
-#include "interface.h"
+#include "ui/interface.h"
#include "inkscape-private.h"
#include "layer-fns.h"
#include "layer-manager.h"
@@ -72,7 +72,7 @@
#include "sp-namedview.h"
#include "sp-root.h"
#include "sp-defs.h"
-#include "tool-factory.h"
+#include "ui/tool-factory.h"
#include "widgets/desktop-widget.h"
#include "xml/repr.h"
#include "helper/action.h" //sp_action_perform
@@ -138,6 +138,7 @@ SPDesktop::SPDesktop() :
_w2d(),
_d2w(),
_doc2dt( Geom::Scale(1, -1) ),
+ _image_render_observer(this, "/options/rendering/imageinoutlinemode"),
grids_visible( false )
{
_d2w.setIdentity();
@@ -499,11 +500,15 @@ SPDesktop::remove_temporary_canvasitem (Inkscape::Display::TemporaryItem * tempi
}
}
+void SPDesktop::redrawDesktop() {
+ sp_canvas_item_affine_absolute (SP_CANVAS_ITEM (main), _d2w); // redraw
+}
+
void SPDesktop::_setDisplayMode(Inkscape::RenderMode mode) {
SP_CANVAS_ARENA (drawing)->drawing.setRenderMode(mode);
canvas->rendermode = mode;
_display_mode = mode;
- sp_canvas_item_affine_absolute (SP_CANVAS_ITEM (main), _d2w); // redraw
+ redrawDesktop();
_widget->setTitle( sp_desktop_document(this)->getName() );
}
void SPDesktop::_setDisplayColorMode(Inkscape::ColorMode mode) {
@@ -524,7 +529,7 @@ void SPDesktop::_setDisplayColorMode(Inkscape::ColorMode mode) {
SP_CANVAS_ARENA (drawing)->drawing.setColorMode(mode);
canvas->colorrendermode = mode;
_display_color_mode = mode;
- sp_canvas_item_affine_absolute (SP_CANVAS_ITEM (main), _d2w); // redraw
+ redrawDesktop();
_widget->setTitle( sp_desktop_document(this)->getName() );
}
@@ -819,7 +824,7 @@ SPDesktop::set_display_area (double x0, double y0, double x1, double y1, double
// zoom changed - set new zoom factors
_d2w = Geom::Scale(newscale, -newscale);
_w2d = Geom::Scale(1/newscale, 1/-newscale);
- sp_canvas_item_affine_absolute(SP_CANVAS_ITEM(main), _d2w);
+ redrawDesktop();
clear = TRUE;
zoomChanged = true;
}
@@ -1699,7 +1704,6 @@ _layer_hierarchy_changed(SPObject */*top*/, SPObject *bottom,
/// Called when document is starting to be rebuilt.
static void _reconstruction_start(SPDesktop * desktop)
{
- g_debug("Desktop, starting reconstruction\n");
desktop->_reconstruction_old_layer_id = desktop->currentLayer()->getId() ? desktop->currentLayer()->getId() : "";
desktop->layers->reset();
@@ -1710,8 +1714,6 @@ static void _reconstruction_start(SPDesktop * desktop)
}
*/
desktop->selection->clear();
-
- g_debug("Desktop, starting reconstruction end\n");
}
/// Called when document rebuild is finished.
diff --git a/src/desktop.h b/src/desktop.h
index 2f47dc2dd..509f8a396 100644
--- a/src/desktop.h
+++ b/src/desktop.h
@@ -35,12 +35,14 @@
#include "display/rendermode.h"
#include <glibmm/ustring.h>
+#include "preferences.h"
#include "sp-gradient.h" // TODO refactor enums out to their own .h file
class SPCSSAttr;
struct SPCanvas;
struct SPCanvasItem;
struct SPCanvasGroup;
+struct DesktopPrefObserver;
namespace Inkscape {
namespace UI {
@@ -52,10 +54,10 @@ class ToolBase;
}
}
-class SPItem;
+class SPItem;
class SPNamedView;
-class SPObject;
-struct SPStyle;
+class SPObject;
+class SPStyle;
typedef struct _DocumentInterface DocumentInterface;//struct DocumentInterface;
namespace Gtk
@@ -70,8 +72,9 @@ typedef struct _GdkEventAny GdkEventAny;
struct _GdkEventWindowState;
typedef struct _GdkEventWindowState GdkEventWindowState;
+struct InkscapeApplication;
+
namespace Inkscape {
- struct Application;
class LayerModel;
class MessageContext;
class Selection;
@@ -206,7 +209,7 @@ public:
/// Emitted when the zoom factor changes (not emitted when scrolling).
/// The parameter is the new zoom factor
sigc::signal<void, double> signal_zoom_changed;
-
+
sigc::connection connectDestroy(const sigc::slot<void, SPDesktop*> &slot)
{
return _destroy_signal.connect(slot);
@@ -256,6 +259,8 @@ public:
Inkscape::Display::TemporaryItem * add_temporary_canvasitem (SPCanvasItem *item, guint lifetime, bool move_to_bottom = true);
void remove_temporary_canvasitem (Inkscape::Display::TemporaryItem * tempitem);
+ void redrawDesktop();
+
void _setDisplayMode(Inkscape::RenderMode mode);
void setDisplayModeNormal() {
_setDisplayMode(Inkscape::RENDERMODE_NORMAL);
@@ -419,13 +424,33 @@ public:
private:
Inkscape::UI::View::EditWidgetInterface *_widget;
- Inkscape::Application *_inkscape;
+ InkscapeApplication *_inkscape;
Inkscape::MessageContext *_guides_message_context;
bool _active;
Geom::Affine _w2d;
Geom::Affine _d2w;
Geom::Affine _doc2dt;
+ /*
+ * Allow redrawing or refreshing if preferences change
+ */
+ class DesktopPrefObserver : public Inkscape::Preferences::Observer {
+ public:
+ DesktopPrefObserver(SPDesktop *desktop, Glib::ustring const &path)
+ : Inkscape::Preferences::Observer(path)
+ , _desktop(desktop) {
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ prefs->addObserver(*this);
+ }
+ private:
+ void notify(Inkscape::Preferences::Entry const &) {
+ _desktop->redrawDesktop();
+ }
+ SPDesktop *_desktop;
+ };
+
+ DesktopPrefObserver _image_render_observer;
+
bool grids_visible; /* don't set this variable directly, use the method below */
void set_grids_visible(bool visible);
diff --git a/src/dialogs/CMakeLists.txt b/src/dialogs/CMakeLists.txt
deleted file mode 100644
index ca19c0b72..000000000
--- a/src/dialogs/CMakeLists.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-
-set(dialogs_SRC
- dialog-events.cpp
-
- # -------
- # Headers
- dialog-events.h
-)
-
-# add_inkscape_lib(dialogs_LIB "${dialogs_SRC}")
-add_inkscape_source("${dialogs_SRC}")
diff --git a/src/dialogs/Makefile_insert b/src/dialogs/Makefile_insert
deleted file mode 100644
index f1ed89314..000000000
--- a/src/dialogs/Makefile_insert
+++ /dev/null
@@ -1,5 +0,0 @@
-## Makefile.am fragment sourced by src/Makefile.am.
-
-ink_common_sources += \
- dialogs/dialog-events.cpp \
- dialogs/dialog-events.h
diff --git a/src/dialogs/makefile.in b/src/dialogs/makefile.in
deleted file mode 100644
index 9acaf79a0..000000000
--- a/src/dialogs/makefile.in
+++ /dev/null
@@ -1,17 +0,0 @@
-# Convenience stub makefile to call the real Makefile.
-
-@SET_MAKE@
-
-OBJEXT = @OBJEXT@
-
-# Explicit so that it's the default rule.
-all:
- cd .. && $(MAKE) dialogs/all
-
-clean %.a %.$(OBJEXT):
- cd .. && $(MAKE) dialogs/$@
-
-.PHONY: all clean
-
-.SUFFIXES:
-.SUFFIXES: .a .$(OBJEXT)
diff --git a/src/dir-util.h b/src/dir-util.h
index 17261af41..e78cad6a6 100644
--- a/src/dir-util.h
+++ b/src/dir-util.h
@@ -9,8 +9,8 @@
*
*/
-#include <stdlib.h>
-#include <glib.h>
+#include <cstdlib>
+#include <string>
/**
* Returns a form of \a path relative to \a base if that is easy to construct (eg if \a path
@@ -49,7 +49,7 @@ char *inkscape_rel2abs(char const *path, char const *base, char *result, size_t
char *inkscape_abs2rel(char const *path, char const *base, char *result, size_t const size);
-gchar *prepend_current_dir_if_relative(gchar const *filename);
+gchar *prepend_current_dir_if_relative(char const *filename);
#endif // !SEEN_DIR_UTIL_H
diff --git a/src/display/CMakeLists.txt b/src/display/CMakeLists.txt
index 20424c845..800c4d0d4 100644
--- a/src/display/CMakeLists.txt
+++ b/src/display/CMakeLists.txt
@@ -13,6 +13,7 @@ set(display_SRC
drawing-group.cpp
drawing-image.cpp
drawing-item.cpp
+ drawing-pattern.cpp
drawing-shape.cpp
drawing-surface.cpp
drawing-text.cpp
@@ -75,6 +76,7 @@ set(display_SRC
drawing-group.h
drawing-image.h
drawing-item.h
+ drawing-pattern.h
drawing-shape.h
drawing-surface.h
drawing-text.h
diff --git a/src/display/Makefile_insert b/src/display/Makefile_insert
index abbd89a68..2355c3653 100644
--- a/src/display/Makefile_insert
+++ b/src/display/Makefile_insert
@@ -33,6 +33,8 @@ ink_common_sources += \
display/drawing-image.h \
display/drawing-item.cpp \
display/drawing-item.h \
+ display/drawing-pattern.cpp \
+ display/drawing-pattern.h \
display/drawing-shape.cpp \
display/drawing-shape.h \
display/drawing-surface.cpp \
diff --git a/src/display/cairo-templates.h b/src/display/cairo-templates.h
index 57ec98f81..a49f925c3 100644
--- a/src/display/cairo-templates.h
+++ b/src/display/cairo-templates.h
@@ -16,6 +16,8 @@
#include "config.h"
#endif
+#include <glib.h>
+
#ifdef HAVE_OPENMP
#include <omp.h>
#include "preferences.h"
@@ -25,7 +27,6 @@ static const int OPENMP_THRESHOLD = 2048;
#include <algorithm>
#include <cairo.h>
-#include <glib.h>
#include <math.h>
#include "display/nr-3dutils.h"
#include "display/cairo-utils.h"
diff --git a/src/display/cairo-utils.cpp b/src/display/cairo-utils.cpp
index 5b358ade7..e1f12b04b 100644
--- a/src/display/cairo-utils.cpp
+++ b/src/display/cairo-utils.cpp
@@ -19,19 +19,20 @@
#include <glibmm/fileutils.h>
#include <2geom/pathvector.h>
#include <2geom/bezier-curve.h>
+#include <2geom/elliptical-arc.h>
#include <2geom/hvlinesegment.h>
#include <2geom/affine.h>
#include <2geom/point.h>
#include <2geom/path.h>
#include <2geom/transforms.h>
#include <2geom/sbasis-to-bezier.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+
#include "color.h"
#include "style.h"
#include "helper/geom-curves.h"
#include "display/cairo-templates.h"
-static void ink_cairo_pixbuf_cleanup(guchar *, void *);
-
/**
* Key for cairo_surface_t to keep track of current color interpolation value
* Only the address of the structure is used, it is never initialized. See:
@@ -502,7 +503,17 @@ void Pixbuf::ensurePixelFormat(PixelFormat fmt)
static void
feed_curve_to_cairo(cairo_t *cr, Geom::Curve const &c, Geom::Affine const & trans, Geom::Rect view, bool optimize_stroke)
{
- if( is_straight_curve(c) )
+ using Geom::X;
+ using Geom::Y;
+
+ unsigned order = 0;
+ if (Geom::BezierCurve const* b = dynamic_cast<Geom::BezierCurve const*>(&c)) {
+ order = b->order();
+ }
+
+ // handle the three typical curve cases
+ switch (order) {
+ case 1:
{
Geom::Point end_tr = c.finalPoint() * trans;
if (!optimize_stroke) {
@@ -516,57 +527,97 @@ feed_curve_to_cairo(cairo_t *cr, Geom::Curve const &c, Geom::Affine const & tran
}
}
}
- else if(Geom::QuadraticBezier const *quadratic_bezier = dynamic_cast<Geom::QuadraticBezier const*>(&c)) {
+ break;
+ case 2:
+ {
+ Geom::QuadraticBezier const *quadratic_bezier = static_cast<Geom::QuadraticBezier const*>(&c);
std::vector<Geom::Point> points = quadratic_bezier->points();
points[0] *= trans;
points[1] *= trans;
points[2] *= trans;
+ // degree-elevate to cubic Bezier, since Cairo doesn't do quadratic Beziers
Geom::Point b1 = points[0] + (2./3) * (points[1] - points[0]);
Geom::Point b2 = b1 + (1./3) * (points[2] - points[0]);
if (!optimize_stroke) {
- cairo_curve_to(cr, b1[0], b1[1], b2[0], b2[1], points[2][0], points[2][1]);
+ cairo_curve_to(cr, b1[X], b1[Y], b2[X], b2[Y], points[2][X], points[2][Y]);
} else {
Geom::Rect swept(points[0], points[2]);
swept.expandTo(points[1]);
if (swept.intersects(view)) {
- cairo_curve_to(cr, b1[0], b1[1], b2[0], b2[1], points[2][0], points[2][1]);
+ cairo_curve_to(cr, b1[X], b1[Y], b2[X], b2[Y], points[2][X], points[2][Y]);
} else {
- cairo_move_to(cr, points[2][0], points[2][1]);
+ cairo_move_to(cr, points[2][X], points[2][Y]);
}
}
}
- else if(Geom::CubicBezier const *cubic_bezier = dynamic_cast<Geom::CubicBezier const*>(&c)) {
+ break;
+ case 3:
+ {
+ Geom::CubicBezier const *cubic_bezier = static_cast<Geom::CubicBezier const*>(&c);
std::vector<Geom::Point> points = cubic_bezier->points();
//points[0] *= trans; // don't do this one here for fun: it is only needed for optimized strokes
points[1] *= trans;
points[2] *= trans;
points[3] *= trans;
if (!optimize_stroke) {
- cairo_curve_to(cr, points[1][0], points[1][1], points[2][0], points[2][1], points[3][0], points[3][1]);
+ cairo_curve_to(cr, points[1][X], points[1][Y], points[2][X], points[2][Y], points[3][X], points[3][Y]);
} else {
points[0] *= trans; // didn't transform this point yet
Geom::Rect swept(points[0], points[3]);
swept.expandTo(points[1]);
swept.expandTo(points[2]);
if (swept.intersects(view)) {
- cairo_curve_to(cr, points[1][0], points[1][1], points[2][0], points[2][1], points[3][0], points[3][1]);
+ cairo_curve_to(cr, points[1][X], points[1][Y], points[2][X], points[2][Y], points[3][X], points[3][Y]);
} else {
- cairo_move_to(cr, points[3][0], points[3][1]);
+ cairo_move_to(cr, points[3][X], points[3][Y]);
}
}
}
-// else if(Geom::SVGEllipticalArc const *svg_elliptical_arc = dynamic_cast<Geom::SVGEllipticalArc *>(c)) {
-// //TODO: get at the innards and spit them out to cairo
-// }
- else {
- //this case handles sbasis as well as all other curve types
- Geom::Path sbasis_path = Geom::cubicbezierpath_from_sbasis(c.toSBasis(), 0.1);
-
- //recurse to convert the new path resulting from the sbasis to svgd
- for(Geom::Path::iterator iter = sbasis_path.begin(); iter != sbasis_path.end(); ++iter) {
- feed_curve_to_cairo(cr, *iter, trans, view, optimize_stroke);
+ break;
+ default:
+ {
+ if (Geom::EllipticalArc const *a = dynamic_cast<Geom::EllipticalArc const*>(&c)) {
+ //if (!optimize_stroke || a->boundsFast().intersects(view)) {
+ Geom::Affine xform = a->unitCircleTransform() * trans;
+ Geom::Point ang(a->initialAngle().radians(), a->finalAngle().radians());
+
+ // Apply the transformation to the current context
+ cairo_matrix_t cm;
+ cm.xx = xform[0];
+ cm.xy = xform[2];
+ cm.x0 = xform[4];
+ cm.yx = xform[1];
+ cm.yy = xform[3];
+ cm.y0 = xform[5];
+
+ cairo_save(cr);
+ cairo_transform(cr, &cm);
+
+ // Draw the circle
+ if (a->sweep()) {
+ cairo_arc(cr, 0, 0, 1, ang[0], ang[1]);
+ } else {
+ cairo_arc_negative(cr, 0, 0, 1, ang[0], ang[1]);
+ }
+ // Revert the current context
+ cairo_restore(cr);
+ //} else {
+ // Geom::Point f = a->finalPoint() * trans;
+ // cairo_move_to(cr, f[X], f[Y]);
+ //}
+ } else {
+ // handles sbasis as well as all other curve types
+ // this is very slow
+ Geom::Path sbasis_path = Geom::cubicbezierpath_from_sbasis(c.toSBasis(), 0.1);
+
+ // recurse to convert the new path resulting from the sbasis to svgd
+ for (Geom::Path::iterator iter = sbasis_path.begin(); iter != sbasis_path.end(); ++iter) {
+ feed_curve_to_cairo(cr, *iter, trans, view, optimize_stroke);
+ }
}
}
+ break;
+ }
}
@@ -579,7 +630,7 @@ feed_path_to_cairo (cairo_t *ct, Geom::Path const &path)
cairo_move_to(ct, path.initialPoint()[0], path.initialPoint()[1] );
- for(Geom::Path::const_iterator cit = path.begin(); cit != path.end_open(); ++cit) {
+ for (Geom::Path::const_iterator cit = path.begin(); cit != path.end_open(); ++cit) {
feed_curve_to_cairo(ct, *cit, Geom::identity(), Geom::Rect(), false); // optimize_stroke is false, so the view rect is not used
}
@@ -1119,7 +1170,7 @@ GdkPixbuf *ink_pixbuf_create_from_cairo_surface(cairo_surface_t *s)
* to gdk_pixbuf_new_from_data when creating a GdkPixbuf backed by
* a Cairo surface.
*/
-static void ink_cairo_pixbuf_cleanup(guchar * /*pixels*/, void *data)
+void ink_cairo_pixbuf_cleanup(guchar * /*pixels*/, void *data)
{
cairo_surface_t *surface = static_cast<cairo_surface_t*>(data);
cairo_surface_destroy(surface);
diff --git a/src/display/cairo-utils.h b/src/display/cairo-utils.h
index 505e2ca77..2a7e460e8 100644
--- a/src/display/cairo-utils.h
+++ b/src/display/cairo-utils.h
@@ -12,15 +12,16 @@
#ifndef SEEN_INKSCAPE_DISPLAY_CAIRO_UTILS_H
#define SEEN_INKSCAPE_DISPLAY_CAIRO_UTILS_H
+#include <2geom/forward.h>
#include <boost/noncopyable.hpp>
-//#include <glibmm/threads.h> // workaround
-#include <glib.h>
#include <cairomm/cairomm.h>
-//#include <gdkmm/pixbuf.h>
-#include <2geom/forward.h>
#include "style.h"
struct SPColor;
+typedef struct _GdkPixbuf GdkPixbuf;
+
+void ink_cairo_pixbuf_cleanup(unsigned char *, void *);
+void convert_pixbuf_argb32_to_normal(GdkPixbuf *pb);
namespace Inkscape {
diff --git a/src/display/canvas-arena.cpp b/src/display/canvas-arena.cpp
index 404a94828..8738b93e4 100644
--- a/src/display/canvas-arena.cpp
+++ b/src/display/canvas-arena.cpp
@@ -11,7 +11,7 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include <gtk/gtk.h>
+#include <gtkmm.h>
#include "display/sp-canvas-util.h"
#include "helper/sp-marshal.h"
@@ -30,8 +30,6 @@ enum {
LAST_SIGNAL
};
-static void sp_canvas_arena_class_init(SPCanvasArenaClass *klass);
-static void sp_canvas_arena_init(SPCanvasArena *group);
static void sp_canvas_arena_destroy(SPCanvasItem *object);
static void sp_canvas_arena_item_deleted(SPCanvasArena *arena, Inkscape::DrawingItem *item);
@@ -46,7 +44,6 @@ static gint sp_canvas_arena_send_event (SPCanvasArena *arena, GdkEvent *event);
static void sp_canvas_arena_request_update (SPCanvasArena *ca, DrawingItem *item);
static void sp_canvas_arena_request_render (SPCanvasArena *ca, Geom::IntRect const &area);
-static SPCanvasItemClass *parent_class;
static guint signals[LAST_SIGNAL] = {0};
struct CachePrefObserver : public Inkscape::Preferences::Observer {
@@ -70,33 +67,13 @@ struct CachePrefObserver : public Inkscape::Preferences::Observer {
SPCanvasArena *_arena;
};
-GType
-sp_canvas_arena_get_type (void)
-{
- static GType type = 0;
- if (!type) {
- GTypeInfo info = {
- sizeof (SPCanvasArenaClass),
- NULL, NULL,
- (GClassInitFunc) sp_canvas_arena_class_init,
- NULL, NULL,
- sizeof (SPCanvasArena),
- 0,
- (GInstanceInitFunc) sp_canvas_arena_init,
- NULL
- };
- type = g_type_register_static (SP_TYPE_CANVAS_ITEM, "SPCanvasArena", &info, (GTypeFlags)0);
- }
- return type;
-}
+G_DEFINE_TYPE(SPCanvasArena, sp_canvas_arena, SP_TYPE_CANVAS_ITEM);
static void
sp_canvas_arena_class_init (SPCanvasArenaClass *klass)
{
SPCanvasItemClass *item_class = (SPCanvasItemClass *) klass;
- parent_class = (SPCanvasItemClass*)g_type_class_peek_parent (klass);
-
signals[ARENA_EVENT] = g_signal_new ("arena_event",
G_TYPE_FROM_CLASS(item_class),
G_SIGNAL_RUN_LAST,
@@ -149,8 +126,8 @@ static void sp_canvas_arena_destroy(SPCanvasItem *object)
delete arena->observer;
arena->drawing.~Drawing();
- if (SP_CANVAS_ITEM_CLASS(parent_class)->destroy)
- (* SP_CANVAS_ITEM_CLASS(parent_class)->destroy) (object);
+ if (SP_CANVAS_ITEM_CLASS(sp_canvas_arena_parent_class)->destroy)
+ SP_CANVAS_ITEM_CLASS(sp_canvas_arena_parent_class)->destroy(object);
}
static void
@@ -158,8 +135,8 @@ sp_canvas_arena_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned
{
SPCanvasArena *arena = SP_CANVAS_ARENA (item);
- if (((SPCanvasItemClass *) parent_class)->update)
- (* ((SPCanvasItemClass *) parent_class)->update) (item, affine, flags);
+ if (SP_CANVAS_ITEM_CLASS(sp_canvas_arena_parent_class)->update)
+ SP_CANVAS_ITEM_CLASS(sp_canvas_arena_parent_class)->update(item, affine, flags);
arena->ctx.ctm = affine;
@@ -227,7 +204,7 @@ sp_canvas_arena_point (SPCanvasItem *item, Geom::Point p, SPCanvasItem **actual_
{
SPCanvasArena *arena = SP_CANVAS_ARENA (item);
- arena->drawing.update(Geom::IntRect::infinite(), arena->ctx, DrawingItem::STATE_PICK);
+ arena->drawing.update(Geom::IntRect::infinite(), arena->ctx, DrawingItem::STATE_PICK | DrawingItem::STATE_BBOX);
DrawingItem *picked = arena->drawing.pick(p, arena->drawing.delta, arena->sticky);
arena->picked = picked;
diff --git a/src/display/canvas-arena.h b/src/display/canvas-arena.h
index 26f19732d..15bbc2ee0 100644
--- a/src/display/canvas-arena.h
+++ b/src/display/canvas-arena.h
@@ -13,15 +13,13 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include <cairo.h>
#include <2geom/rect.h>
+
#include "display/drawing.h"
#include "display/drawing-item.h"
#include "display/sp-canvas.h"
#include "display/sp-canvas-item.h"
-G_BEGIN_DECLS
-
#define SP_TYPE_CANVAS_ARENA (sp_canvas_arena_get_type ())
#define SP_CANVAS_ARENA(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SP_TYPE_CANVAS_ARENA, SPCanvasArena))
#define SP_CANVAS_ARENA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SP_TYPE_CANVAS_ARENA, SPCanvasArenaClass))
@@ -30,6 +28,7 @@ G_BEGIN_DECLS
typedef struct _SPCanvasArena SPCanvasArena;
typedef struct _SPCanvasArenaClass SPCanvasArenaClass;
+typedef struct _cairo_surface cairo_surface_t;
struct CachePrefObserver;
namespace Inkscape {
@@ -39,7 +38,6 @@ class DrawingItem;
} // namespace Inkscape
-
struct _SPCanvasArena {
SPCanvasItem item;
@@ -70,6 +68,4 @@ void sp_canvas_arena_set_sticky (SPCanvasArena *ca, gboolean sticky);
void sp_canvas_arena_render_surface (SPCanvasArena *ca, cairo_surface_t *surface, Geom::IntRect const &area);
-G_END_DECLS
-
#endif // SEEN_SP_CANVAS_ARENA_H
diff --git a/src/display/canvas-axonomgrid.cpp b/src/display/canvas-axonomgrid.cpp
index 312a8d655..592c962a6 100644
--- a/src/display/canvas-axonomgrid.cpp
+++ b/src/display/canvas-axonomgrid.cpp
@@ -387,6 +387,9 @@ _wr.setUpdating (false);
_rcp_gmcol->setRgba32 (empcolor);
_rsi->setValue (empspacing);
+ _rsu_ox->setProgrammatically = false;
+ _rsu_oy->setProgrammatically = false;
+
return table;
}
diff --git a/src/display/canvas-axonomgrid.h b/src/display/canvas-axonomgrid.h
index 3888a3dc4..92cdb4c50 100644
--- a/src/display/canvas-axonomgrid.h
+++ b/src/display/canvas-axonomgrid.h
@@ -26,11 +26,11 @@ public:
CanvasAxonomGrid(SPNamedView * nv, Inkscape::XML::Node * in_repr, SPDocument * in_doc);
virtual ~CanvasAxonomGrid();
- void Update (Geom::Affine const &affine, unsigned int flags);
- void Render (SPCanvasBuf *buf);
+ virtual void Update (Geom::Affine const &affine, unsigned int flags);
+ virtual void Render (SPCanvasBuf *buf);
- void readRepr();
- void onReprAttrChanged (Inkscape::XML::Node * repr, const gchar *key, const gchar *oldval, const gchar *newval, bool is_interactive);
+ virtual void readRepr();
+ virtual void onReprAttrChanged (Inkscape::XML::Node * repr, char const *key, char const *oldval, char const *newval, bool is_interactive);
double lengthy; /**< The lengths of the primary y-axis */
double angle_deg[3]; /**< Angle of each axis (note that angle[2] == 0) */
diff --git a/src/display/canvas-bpath.cpp b/src/display/canvas-bpath.cpp
index ee9e14f10..46b59d25a 100644
--- a/src/display/canvas-bpath.cpp
+++ b/src/display/canvas-bpath.cpp
@@ -11,9 +11,6 @@
*
*/
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
#include <sstream>
#include <string.h>
#include "desktop.h"
@@ -27,42 +24,18 @@
#include "helper/geom.h"
#include "display/sp-canvas.h"
-static void sp_canvas_bpath_class_init (SPCanvasBPathClass *klass);
-static void sp_canvas_bpath_init (SPCanvasBPath *path);
static void sp_canvas_bpath_destroy(SPCanvasItem *object);
static void sp_canvas_bpath_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags);
static void sp_canvas_bpath_render (SPCanvasItem *item, SPCanvasBuf *buf);
static double sp_canvas_bpath_point (SPCanvasItem *item, Geom::Point p, SPCanvasItem **actual_item);
-static SPCanvasItemClass *parent_class;
-
-GType
-sp_canvas_bpath_get_type (void)
-{
- static GType type = 0;
- if (!type) {
- GTypeInfo info = {
- sizeof (SPCanvasBPathClass),
- NULL, NULL,
- (GClassInitFunc) sp_canvas_bpath_class_init,
- NULL, NULL,
- sizeof (SPCanvasBPath),
- 0,
- (GInstanceInitFunc) sp_canvas_bpath_init,
- NULL
- };
- type = g_type_register_static (SP_TYPE_CANVAS_ITEM, "SPCanvasBPath", &info, (GTypeFlags)0);
- }
- return type;
-}
+G_DEFINE_TYPE(SPCanvasBPath, sp_canvas_bpath, SP_TYPE_CANVAS_ITEM);
static void sp_canvas_bpath_class_init(SPCanvasBPathClass *klass)
{
SPCanvasItemClass *item_class = (SPCanvasItemClass *) klass;
- parent_class = (SPCanvasItemClass*)g_type_class_peek_parent (klass);
-
item_class->destroy = sp_canvas_bpath_destroy;
item_class->update = sp_canvas_bpath_update;
item_class->render = sp_canvas_bpath_render;
@@ -90,8 +63,8 @@ static void sp_canvas_bpath_destroy(SPCanvasItem *object)
cbp->curve = cbp->curve->unref();
}
- if (SP_CANVAS_ITEM_CLASS(parent_class)->destroy)
- (* SP_CANVAS_ITEM_CLASS(parent_class)->destroy) (object);
+ if (SP_CANVAS_ITEM_CLASS(sp_canvas_bpath_parent_class)->destroy)
+ (* SP_CANVAS_ITEM_CLASS(sp_canvas_bpath_parent_class)->destroy) (object);
}
static void sp_canvas_bpath_update(SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags)
@@ -100,8 +73,8 @@ static void sp_canvas_bpath_update(SPCanvasItem *item, Geom::Affine const &affin
item->canvas->requestRedraw((int)item->x1, (int)item->y1, (int)item->x2, (int)item->y2);
- if (reinterpret_cast<SPCanvasItemClass *>(parent_class)->update) {
- reinterpret_cast<SPCanvasItemClass *>(parent_class)->update(item, affine, flags);
+ if (reinterpret_cast<SPCanvasItemClass *>(sp_canvas_bpath_parent_class)->update) {
+ reinterpret_cast<SPCanvasItemClass *>(sp_canvas_bpath_parent_class)->update(item, affine, flags);
}
sp_canvas_item_reset_bounds (item);
diff --git a/src/display/canvas-grid.cpp b/src/display/canvas-grid.cpp
index 4b1dbd1ed..2eeaa7006 100644
--- a/src/display/canvas-grid.cpp
+++ b/src/display/canvas-grid.cpp
@@ -71,42 +71,16 @@ static gchar const *const grid_svgname[] = {
// ##########################################################
// Grid CanvasItem
-static void grid_canvasitem_class_init (GridCanvasItemClass *klass);
-static void grid_canvasitem_init (GridCanvasItem *grid);
static void grid_canvasitem_destroy(SPCanvasItem *object);
static void grid_canvasitem_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags);
static void grid_canvasitem_render (SPCanvasItem *item, SPCanvasBuf *buf);
-static SPCanvasItemClass * parent_class;
-
-GType
-grid_canvasitem_get_type (void)
-{
- static GType grid_canvasitem_type = 0;
-
- if (!grid_canvasitem_type) {
- GTypeInfo grid_canvasitem_info = {
- sizeof (GridCanvasItemClass),
- NULL, NULL,
- (GClassInitFunc) grid_canvasitem_class_init,
- NULL, NULL,
- sizeof (GridCanvasItem),
- 0,
- (GInstanceInitFunc) grid_canvasitem_init,
- NULL
- };
-
- grid_canvasitem_type = g_type_register_static(SPCanvasItem::getType(), "GridCanvasItem", &grid_canvasitem_info, GTypeFlags(0));
- }
- return grid_canvasitem_type;
-}
+G_DEFINE_TYPE(GridCanvasItem, grid_canvasitem, SP_TYPE_CANVAS_ITEM);
static void grid_canvasitem_class_init(GridCanvasItemClass *klass)
{
SPCanvasItemClass *item_class = (SPCanvasItemClass *) klass;
- parent_class = (SPCanvasItemClass*)g_type_class_peek_parent (klass);
-
item_class->destroy = grid_canvasitem_destroy;
item_class->update = grid_canvasitem_update;
item_class->render = grid_canvasitem_render;
@@ -123,8 +97,8 @@ static void grid_canvasitem_destroy(SPCanvasItem *object)
g_return_if_fail (object != NULL);
g_return_if_fail (INKSCAPE_IS_GRID_CANVASITEM (object));
- if (SP_CANVAS_ITEM_CLASS(parent_class)->destroy)
- (* SP_CANVAS_ITEM_CLASS(parent_class)->destroy) (object);
+ if (SP_CANVAS_ITEM_CLASS(grid_canvasitem_parent_class)->destroy)
+ (* SP_CANVAS_ITEM_CLASS(grid_canvasitem_parent_class)->destroy) (object);
}
/**
@@ -145,8 +119,8 @@ grid_canvasitem_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned
{
GridCanvasItem *gridcanvasitem = INKSCAPE_GRID_CANVASITEM (item);
- if (parent_class->update)
- (* parent_class->update) (item, affine, flags);
+ if (SP_CANVAS_ITEM_CLASS(grid_canvasitem_parent_class)->update)
+ SP_CANVAS_ITEM_CLASS(grid_canvasitem_parent_class)->update(item, affine, flags);
if (gridcanvasitem->grid) {
gridcanvasitem->grid->Update(affine, flags);
diff --git a/src/display/canvas-grid.h b/src/display/canvas-grid.h
index 5a23dee52..557bd6dab 100644
--- a/src/display/canvas-grid.h
+++ b/src/display/canvas-grid.h
@@ -82,7 +82,7 @@ public:
virtual void Render (SPCanvasBuf *buf) = 0;
virtual void readRepr() = 0;
- virtual void onReprAttrChanged (Inkscape::XML::Node * /*repr*/, const gchar */*key*/, const gchar */*oldval*/, const gchar */*newval*/, bool /*is_interactive*/) = 0;
+ virtual void onReprAttrChanged (Inkscape::XML::Node * /*repr*/, char const */*key*/, char const */*oldval*/, char const */*newval*/, bool /*is_interactive*/) = 0;
Gtk::Widget * newWidget();
@@ -129,11 +129,11 @@ public:
CanvasXYGrid(SPNamedView * nv, Inkscape::XML::Node * in_repr, SPDocument * in_doc);
virtual ~CanvasXYGrid();
- void Update (Geom::Affine const &affine, unsigned int flags);
- void Render (SPCanvasBuf *buf);
+ virtual void Update (Geom::Affine const &affine, unsigned int flags);
+ virtual void Render (SPCanvasBuf *buf);
- void readRepr();
- void onReprAttrChanged (Inkscape::XML::Node * repr, const gchar *key, const gchar *oldval, const gchar *newval, bool is_interactive);
+ virtual void readRepr();
+ virtual void onReprAttrChanged (Inkscape::XML::Node * repr, char const *key, char const *oldval, char const *newval, bool is_interactive);
Geom::Point spacing; /**< Spacing between elements of the grid */
bool scaled[2]; /**< Whether the grid is in scaled mode, which can
diff --git a/src/display/canvas-temporary-item-list.cpp b/src/display/canvas-temporary-item-list.cpp
index b0fec98b5..60ead11ce 100644
--- a/src/display/canvas-temporary-item-list.cpp
+++ b/src/display/canvas-temporary-item-list.cpp
@@ -10,9 +10,8 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include "display/canvas-temporary-item-list.h"
-
#include "display/canvas-temporary-item.h"
+#include "display/canvas-temporary-item-list.h"
namespace Inkscape {
namespace Display {
@@ -35,7 +34,7 @@ TemporaryItemList::~TemporaryItemList()
/* Note that TemporaryItem or TemporaryItemList is responsible for deletion and such, so this return pointer can safely be ignored. */
TemporaryItem *
-TemporaryItemList::add_item(SPCanvasItem *item, guint lifetime)
+TemporaryItemList::add_item(SPCanvasItem *item, unsigned int lifetime)
{
// beware of strange things happening due to very short timeouts
TemporaryItem * tempitem = new TemporaryItem(item, lifetime);
diff --git a/src/display/canvas-temporary-item-list.h b/src/display/canvas-temporary-item-list.h
index d204c692f..471bb99b9 100644
--- a/src/display/canvas-temporary-item-list.h
+++ b/src/display/canvas-temporary-item-list.h
@@ -11,7 +11,6 @@
*/
#include <list>
-#include <glib.h>
struct SPCanvasItem;
class SPDesktop;
@@ -22,14 +21,14 @@ namespace Display {
class TemporaryItem;
/**
- * Provides a class that can contain active TemporaryItem's on a desktop.
+ * Provides a class that can contain active TemporaryItem[s] on a desktop.
*/
class TemporaryItemList {
public:
TemporaryItemList(SPDesktop *desktop);
virtual ~TemporaryItemList();
- TemporaryItem* add_item (SPCanvasItem *item, guint lifetime);
+ TemporaryItem* add_item (SPCanvasItem *item, unsigned int lifetime);
void delete_item (TemporaryItem * tempitem);
protected:
diff --git a/src/display/canvas-temporary-item.cpp b/src/display/canvas-temporary-item.cpp
index 551ea1536..f55c8bf4e 100644
--- a/src/display/canvas-temporary-item.cpp
+++ b/src/display/canvas-temporary-item.cpp
@@ -16,7 +16,7 @@
#include "display/canvas-temporary-item.h"
-#include <gtk/gtk.h>
+#include <glib.h>
#include "display/sp-canvas-item.h"
namespace Inkscape {
@@ -54,9 +54,9 @@ TemporaryItem::~TemporaryItem()
}
}
-/* static method*/
-gboolean TemporaryItem::_timeout(gpointer data) {
- TemporaryItem *tempitem = reinterpret_cast<TemporaryItem *>(data);
+/* static method */
+int TemporaryItem::_timeout(void* data) {
+ TemporaryItem *tempitem = static_cast<TemporaryItem *>(data);
tempitem->timeout_id = 0;
tempitem->signal_timeout.emit(tempitem);
delete tempitem;
diff --git a/src/display/canvas-temporary-item.h b/src/display/canvas-temporary-item.h
index 09d243fa1..39ca2fc65 100644
--- a/src/display/canvas-temporary-item.h
+++ b/src/display/canvas-temporary-item.h
@@ -11,9 +11,8 @@
*/
-#include <stddef.h>
-#include <sigc++/sigc++.h>
-#include <glib.h>
+#include <cstddef>
+#include <sigc++/signal.h>
struct SPCanvasItem;
@@ -25,7 +24,7 @@ namespace Display {
*/
class TemporaryItem {
public:
- TemporaryItem(SPCanvasItem *item, guint lifetime, bool destroy_on_deselect = false);
+ TemporaryItem(SPCanvasItem *item, unsigned int lifetime, bool destroy_on_deselect = false);
virtual ~TemporaryItem();
sigc::signal<void, TemporaryItem *> signal_timeout;
@@ -34,10 +33,10 @@ protected:
friend class TemporaryItemList;
SPCanvasItem * canvasitem; /** The item we are holding on to */
- guint timeout_id; /** ID by which glib knows the timeout event */
+ unsigned int timeout_id; /** ID by which glib knows the timeout event */
bool destroy_on_deselect; // only destroy when parent item is deselected, not when mouse leaves
- static gboolean _timeout(gpointer data); ///< callback for when lifetime expired
+ static int _timeout(void* data); ///< callback for when lifetime expired
private:
TemporaryItem(const TemporaryItem&);
diff --git a/src/display/canvas-text.cpp b/src/display/canvas-text.cpp
index fe60d9c65..5ad87b4ef 100644
--- a/src/display/canvas-text.cpp
+++ b/src/display/canvas-text.cpp
@@ -12,10 +12,6 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
#include <sstream>
#include <string.h>
@@ -26,42 +22,17 @@
#include "color.h"
#include "display/sp-canvas.h"
-static void sp_canvastext_class_init (SPCanvasTextClass *klass);
-static void sp_canvastext_init (SPCanvasText *canvastext);
static void sp_canvastext_destroy(SPCanvasItem *object);
static void sp_canvastext_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags);
static void sp_canvastext_render (SPCanvasItem *item, SPCanvasBuf *buf);
-static SPCanvasItemClass *parent_class_ct;
-
-GType
-sp_canvastext_get_type (void)
-{
- static GType type = 0;
-
- if (!type) {
- GTypeInfo info = {
- sizeof (SPCanvasTextClass),
- NULL, NULL,
- (GClassInitFunc) sp_canvastext_class_init,
- NULL, NULL,
- sizeof (SPCanvasText),
- 0,
- (GInstanceInitFunc) sp_canvastext_init,
- NULL
- };
- type = g_type_register_static (SP_TYPE_CANVAS_ITEM, "SPCanvasText", &info, (GTypeFlags)0);
- }
- return type;
-}
+G_DEFINE_TYPE(SPCanvasText, sp_canvastext, SP_TYPE_CANVAS_ITEM);
static void sp_canvastext_class_init(SPCanvasTextClass *klass)
{
SPCanvasItemClass *item_class = SP_CANVAS_ITEM_CLASS(klass);
- parent_class_ct = SP_CANVAS_ITEM_CLASS(g_type_class_peek_parent(klass));
-
item_class->destroy = sp_canvastext_destroy;
item_class->update = sp_canvastext_update;
item_class->render = sp_canvastext_render;
@@ -101,8 +72,8 @@ static void sp_canvastext_destroy(SPCanvasItem *object)
canvastext->text = NULL;
canvastext->item = NULL;
- if (SP_CANVAS_ITEM_CLASS(parent_class_ct)->destroy)
- (* SP_CANVAS_ITEM_CLASS(parent_class_ct)->destroy) (object);
+ if (SP_CANVAS_ITEM_CLASS(sp_canvastext_parent_class)->destroy)
+ SP_CANVAS_ITEM_CLASS(sp_canvastext_parent_class)->destroy(object);
}
static void
@@ -151,8 +122,8 @@ sp_canvastext_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned i
item->canvas->requestRedraw((int)item->x1, (int)item->y1, (int)item->x2, (int)item->y2);
- if (parent_class_ct->update)
- (* parent_class_ct->update) (item, affine, flags);
+ if (SP_CANVAS_ITEM_CLASS(sp_canvastext_parent_class)->update)
+ SP_CANVAS_ITEM_CLASS(sp_canvastext_parent_class)->update(item, affine, flags);
sp_canvas_item_reset_bounds (item);
diff --git a/src/display/curve.cpp b/src/display/curve.cpp
index 50f4c8954..54a62939d 100644
--- a/src/display/curve.cpp
+++ b/src/display/curve.cpp
@@ -1,10 +1,4 @@
-#define __CURVE_C__
-
-/** \file
- * Routines for SPCurve and for its Geom::PathVector
- */
-
-/*
+/**
* Authors:
* Lauris Kaplinski <lauris@kaplinski.com>
* Johan Engelen
@@ -14,7 +8,7 @@
* Copyright (C) 2002 Lauris Kaplinski
* Copyright (C) 2008 Johan Engelen
*
- * Released under GNU GPL
+ * Released under GNU GPL, see file 'COPYING' for more information
*/
#include "display/curve.h"
@@ -25,6 +19,10 @@
#include <2geom/sbasis-to-bezier.h>
#include <2geom/point.h>
+/**
+ * Routines for SPCurve and for its Geom::PathVector
+ */
+
/* Constructors */
/**
@@ -50,7 +48,7 @@ SPCurve::new_from_rect(Geom::Rect const &rect, bool all_four_sides)
Geom::Point p = rect.corner(0);
c->moveto(p);
- for (int i=3; i>=1; i--) {
+ for (int i=3; i>=1; --i) {
c->lineto(rect.corner(i));
}
@@ -89,10 +87,10 @@ SPCurve::get_pathvector() const
* Returns the number of segments of all paths summed
* This count includes the closing line segment of a closed path.
*/
-guint
+size_t
SPCurve::get_segment_count() const
{
- guint nr = 0;
+ size_t nr = 0;
for(Geom::PathVector::const_iterator it = _pathv.begin(); it != _pathv.end(); ++it) {
nr += (*it).size();
@@ -202,7 +200,7 @@ SPCurve::reset()
* Calls SPCurve::moveto() with point made of given coordinates.
*/
void
-SPCurve::moveto(gdouble x, gdouble y)
+SPCurve::moveto(double x, double y)
{
moveto(Geom::Point(x, y));
}
@@ -231,7 +229,7 @@ SPCurve::lineto(Geom::Point const &p)
* Calls SPCurve::lineto( Geom::Point(x,y) )
*/
void
-SPCurve::lineto(gdouble x, gdouble y)
+SPCurve::lineto(double x, double y)
{
lineto(Geom::Point(x,y));
}
@@ -251,7 +249,7 @@ SPCurve::quadto(Geom::Point const &p1, Geom::Point const &p2)
* All coordinates must be finite.
*/
void
-SPCurve::quadto(gdouble x1, gdouble y1, gdouble x2, gdouble y2)
+SPCurve::quadto(double x1, double y1, double x2, double y2)
{
quadto( Geom::Point(x1,y1), Geom::Point(x2,y2) );
}
@@ -271,7 +269,7 @@ SPCurve::curveto(Geom::Point const &p0, Geom::Point const &p1, Geom::Point const
* All coordinates must be finite.
*/
void
-SPCurve::curveto(gdouble x0, gdouble y0, gdouble x1, gdouble y1, gdouble x2, gdouble y2)
+SPCurve::curveto(double x0, double y0, double x1, double y1, double x2, double y2)
{
curveto( Geom::Point(x0,y0), Geom::Point(x1,y1), Geom::Point(x2,y2) );
}
@@ -522,7 +520,7 @@ SPCurve::append(SPCurve const *curve2,
* When one of the curves is empty, this curves path becomes the non-empty path.
*/
SPCurve *
-SPCurve::append_continuous(SPCurve const *c1, gdouble tolerance)
+SPCurve::append_continuous(SPCurve const *c1, double tolerance)
{
using Geom::X;
using Geom::Y;
@@ -632,10 +630,10 @@ SPCurve::move_endpoints(Geom::Point const &new_p0, Geom::Point const &new_p1)
* Sum of nodes in all the paths. When a path is closed, and its closing line segment is of zero-length,
* this function will not count the closing knot double (so basically ignores the closing line segment when it has zero length)
*/
-guint
+size_t
SPCurve::nodes_in_path() const
{
- guint nr = 0;
+ size_t nr = 0;
for(Geom::PathVector::const_iterator it = _pathv.begin(); it != _pathv.end(); ++it) {
nr += (*it).size();
@@ -686,4 +684,4 @@ SPCurve::last_point_additive_move(Geom::Point const & p)
fill-column:99
End:
*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:
diff --git a/src/display/curve.h b/src/display/curve.h
index 4866655c4..5fad75b18 100644
--- a/src/display/curve.h
+++ b/src/display/curve.h
@@ -1,8 +1,5 @@
-#ifndef SEEN_DISPLAY_CURVE_H
-#define SEEN_DISPLAY_CURVE_H
-
-/*
- * Author:
+/**
+ * Authors:
* Lauris Kaplinski <lauris@kaplinski.com>
*
* Copyright (C) 2000 Lauris Kaplinski
@@ -10,17 +7,20 @@
* Copyright (C) 2002 Lauris Kaplinski
* Copyright (C) 2008 Johan Engelen
*
- * Released under GNU GPL
+ * Released under GNU GPL, see file 'COPYING' for more information
*/
-#include <glib.h>
+#ifndef SEEN_DISPLAY_CURVE_H
+#define SEEN_DISPLAY_CURVE_H
#include <2geom/forward.h>
-
+#include <cstddef>
#include <boost/optional.hpp>
+extern "C" { typedef struct _GSList GSList; }
+
/**
- * Wrapper around a Geom::PathVector objects.
+ * Wrapper around a Geom::PathVector object.
*/
class SPCurve {
public:
@@ -39,8 +39,8 @@ public:
SPCurve * copy() const;
- guint get_segment_count() const;
- guint nodes_in_path() const;
+ size_t get_segment_count() const;
+ size_t nodes_in_path() const;
bool is_empty() const;
bool is_closed() const;
@@ -56,13 +56,13 @@ public:
void reset();
void moveto(Geom::Point const &p);
- void moveto(gdouble x, gdouble y);
+ void moveto(double x, double y);
void lineto(Geom::Point const &p);
- void lineto(gdouble x, gdouble y);
+ void lineto(double x, double y);
void quadto(Geom::Point const &p1, Geom::Point const &p2);
- void quadto(gdouble x1, gdouble y1, gdouble x2, gdouble y2);
+ void quadto(double x1, double y1, double x2, double y2);
void curveto(Geom::Point const &p0, Geom::Point const &p1, Geom::Point const &p2);
- void curveto(gdouble x0, gdouble y0, gdouble x1, gdouble y1, gdouble x2, gdouble y2);
+ void curveto(double x0, double y0, double x1, double y1, double x2, double y2);
void closepath();
void closepath_current();
void backspace();
@@ -73,14 +73,14 @@ public:
void last_point_additive_move(Geom::Point const & p);
void append(SPCurve const *curve2, bool use_lineto);
- SPCurve * append_continuous(SPCurve const *c1, gdouble tolerance);
+ SPCurve * append_continuous(SPCurve const *c1, double tolerance);
SPCurve * create_reverse() const;
GSList * split() const;
static SPCurve * concat(GSList const *list);
protected:
- gint _refcount;
+ size_t _refcount;
Geom::PathVector _pathv;
@@ -90,7 +90,7 @@ private:
SPCurve& operator=(const SPCurve&);
};
-#endif /* !SEEN_DISPLAY_CURVE_H */
+#endif // !SEEN_DISPLAY_CURVE_H
/*
Local Variables:
@@ -101,4 +101,4 @@ private:
fill-column:99
End:
*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8 :
diff --git a/src/display/drawing-context.h b/src/display/drawing-context.h
index d990bcb73..a15e0d0e5 100644
--- a/src/display/drawing-context.h
+++ b/src/display/drawing-context.h
@@ -12,13 +12,13 @@
#ifndef SEEN_INKSCAPE_DISPLAY_DRAWING_CONTEXT_H
#define SEEN_INKSCAPE_DISPLAY_DRAWING_CONTEXT_H
-#include <boost/utility.hpp>
-#include <glib.h>
-#include <cairo.h>
#include <2geom/affine.h>
#include <2geom/angle.h>
#include <2geom/rect.h>
#include <2geom/transforms.h>
+#include <boost/utility.hpp>
+#include <cairo.h>
+typedef unsigned int guint32;
namespace Inkscape {
@@ -61,6 +61,7 @@ public:
cairo_curve_to(_ct, p1[Geom::X], p1[Geom::Y], p2[Geom::X], p2[Geom::Y], p3[Geom::X], p3[Geom::Y]);
}
void arc(Geom::Point const &center, double radius, Geom::AngleInterval const &angle);
+ void closePath() { cairo_close_path(_ct); }
void rectangle(Geom::Rect const &r) {
cairo_rectangle(_ct, r.left(), r.top(), r.width(), r.height());
}
diff --git a/src/display/drawing-group.cpp b/src/display/drawing-group.cpp
index 38ace001f..bce89d70e 100644
--- a/src/display/drawing-group.cpp
+++ b/src/display/drawing-group.cpp
@@ -9,13 +9,14 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include "display/cairo-utils.h"
#include "display/drawing.h"
#include "display/drawing-context.h"
#include "display/drawing-item.h"
#include "display/drawing-group.h"
#include "style.h"
+#include "display/cairo-utils.h"
+
namespace Inkscape {
DrawingGroup::DrawingGroup(Drawing &drawing)
diff --git a/src/display/drawing-group.h b/src/display/drawing-group.h
index 651e9d8af..ab1f9895d 100644
--- a/src/display/drawing-group.h
+++ b/src/display/drawing-group.h
@@ -14,7 +14,7 @@
#include "display/drawing-item.h"
-struct SPStyle;
+class SPStyle;
namespace Inkscape {
diff --git a/src/display/drawing-image.cpp b/src/display/drawing-image.cpp
index 5844c8b08..e56f3e58b 100644
--- a/src/display/drawing-image.cpp
+++ b/src/display/drawing-image.cpp
@@ -10,13 +10,15 @@
*/
#include <2geom/bezier-curve.h>
-#include "display/cairo-utils.h"
+
#include "display/drawing.h"
#include "display/drawing-context.h"
#include "display/drawing-image.h"
#include "preferences.h"
#include "style.h"
+#include "display/cairo-utils.h"
+
namespace Inkscape {
DrawingImage::DrawingImage(Drawing &drawing)
@@ -106,7 +108,10 @@ unsigned DrawingImage::_renderItem(DrawingContext &dc, Geom::IntRect const &/*ar
{
bool outline = _drawing.outline();
- if (!outline) {
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ bool imgoutline = prefs->getBool("/options/rendering/imageinoutlinemode", false);
+
+ if (!outline || imgoutline) {
if (!_pixbuf) return RENDER_OK;
Inkscape::DrawingContext::Save save(dc);
@@ -141,7 +146,7 @@ unsigned DrawingImage::_renderItem(DrawingContext &dc, Geom::IntRect const &/*ar
dc.paint(_opacity);
} else { // outline; draw a rect instead
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+
guint32 rgba = prefs->getInt("/options/wireframecolors/images", 0xff0000ff);
{ Inkscape::DrawingContext::Save save(dc);
diff --git a/src/display/drawing-item.cpp b/src/display/drawing-item.cpp
index ccf905e81..8ed74b550 100644
--- a/src/display/drawing-item.cpp
+++ b/src/display/drawing-item.cpp
@@ -10,20 +10,22 @@
*/
#include <climits>
-#include "display/cairo-utils.h"
-#include "display/cairo-templates.h"
+
#include "display/drawing.h"
#include "display/drawing-context.h"
#include "display/drawing-item.h"
#include "display/drawing-group.h"
+#include "display/drawing-pattern.h"
#include "display/drawing-surface.h"
#include "nr-filter.h"
#include "preferences.h"
#include "style.h"
+#include "display/cairo-utils.h"
+#include "display/cairo-templates.h"
+
namespace Inkscape {
-#ifdef WITH_CSSBLEND
void set_cairo_blend_operator( DrawingContext &dc, unsigned blend_mode ) {
// All of the blend modes are implemented in Cairo as of 1.10.
@@ -81,7 +83,6 @@ void set_cairo_blend_operator( DrawingContext &dc, unsigned blend_mode ) {
break;
}
}
-#endif
/**
* @class DrawingItem
@@ -112,6 +113,8 @@ DrawingItem::DrawingItem(Drawing &drawing)
, _transform(NULL)
, _clip(NULL)
, _mask(NULL)
+ , _fill_pattern(NULL)
+ , _stroke_pattern(NULL)
, _filter(NULL)
, _user_data(NULL)
, _cache(NULL)
@@ -129,7 +132,7 @@ DrawingItem::DrawingItem(Drawing &drawing)
, _pick_children(0)
, _antialias(1)
, _isolation(SP_CSS_ISOLATION_AUTO)
- , _blend_mode(SP_CSS_BLEND_NORMAL)
+ , _mix_blend_mode(SP_CSS_BLEND_NORMAL)
{}
DrawingItem::~DrawingItem()
@@ -166,6 +169,12 @@ DrawingItem::~DrawingItem()
case CHILD_ROOT:
_drawing._root = NULL;
break;
+ case CHILD_FILL_PATTERN:
+ _parent->_fill_pattern = NULL;
+ break;
+ case CHILD_STROKE_PATTERN:
+ _parent->_stroke_pattern = NULL;
+ break;
default: ;
}
@@ -174,6 +183,8 @@ DrawingItem::~DrawingItem()
}
clearChildren();
delete _transform;
+ delete _stroke_pattern;
+ delete _fill_pattern;
delete _clip;
delete _mask;
delete _filter;
@@ -293,10 +304,10 @@ DrawingItem::setIsolation(unsigned isolation)
}
void
-DrawingItem::setBlendMode(unsigned blend_mode)
+DrawingItem::setBlendMode(unsigned mix_blend_mode)
{
- _blend_mode = blend_mode;
- //if( blend_mode != 0 ) std::cout << "setBlendMode: " << blend_mode << std::endl;
+ _mix_blend_mode = mix_blend_mode;
+ //if( mix_blend_mode != 0 ) std::cout << "setBlendMode: " << mix_blend_mode << std::endl;
_markForRendering();
}
@@ -368,6 +379,34 @@ DrawingItem::setMask(DrawingItem *item)
_markForUpdate(STATE_ALL, true);
}
+void
+DrawingItem::setFillPattern(DrawingPattern *pattern)
+{
+ _markForRendering();
+ delete _fill_pattern;
+ _fill_pattern = pattern;
+ if (pattern) {
+ pattern->_parent = this;
+ assert(pattern->_child_type == CHILD_ORPHAN);
+ pattern->_child_type = CHILD_FILL_PATTERN;
+ }
+ _markForUpdate(STATE_ALL, true);
+}
+
+void
+DrawingItem::setStrokePattern(DrawingPattern *pattern)
+{
+ _markForRendering();
+ delete _stroke_pattern;
+ _stroke_pattern = pattern;
+ if (pattern) {
+ pattern->_parent = this;
+ assert(pattern->_child_type == CHILD_ORPHAN);
+ pattern->_child_type = CHILD_STROKE_PATTERN;
+ }
+ _markForUpdate(STATE_ALL, true);
+}
+
/// Move this item to the given place in the Z order of siblings.
/// Does nothing if the item has no parent.
void
@@ -409,7 +448,7 @@ DrawingItem::setItemBounds(Geom::OptRect const &bounds)
* @param reset State fields that should be reset before processing them. This is
* a means to force a recomputation of internal data even if the item
* considers it up to date. Mainly for internal use, such as
- * propagating bunding box recomputation to children when the item's
+ * propagating bounding box recomputation to children when the item's
* transform changes.
*/
void
@@ -532,6 +571,12 @@ DrawingItem::update(Geom::IntRect const &area, UpdateContext const &ctx, unsigne
if (to_update & STATE_RENDER) {
// now that we know drawbox, dirty the corresponding rect on canvas
// unless filtered, groups do not need to render by themselves, only their members
+ if (_fill_pattern) {
+ _fill_pattern->update(area, child_ctx, flags, reset);
+ }
+ if (_stroke_pattern) {
+ _stroke_pattern->update(area, child_ctx, flags, reset);
+ }
if (!is_drawing_group(this) || (_filter && render_filters)) {
_markForRendering();
}
@@ -594,9 +639,8 @@ DrawingItem::render(DrawingContext &dc, Geom::IntRect const &area, unsigned flag
if (_cached) {
if (_cache) {
_cache->prepare();
-#ifdef WITH_CSSBLEND
- set_cairo_blend_operator( dc, _blend_mode );
-#endif
+ set_cairo_blend_operator( dc, _mix_blend_mode );
+
_cache->paintFromCache(dc, carea);
if (!carea) return RENDER_OK;
} else {
@@ -625,10 +669,8 @@ DrawingItem::render(DrawingContext &dc, Geom::IntRect const &area, unsigned flag
nir |= (_filter != NULL && render_filters); // 3. it has a filter
nir |= needs_opacity; // 4. it is non-opaque
nir |= (_cache != NULL); // 5. it is cached
-#ifdef WITH_CSSBLEND
- nir |= (_blend_mode != SP_CSS_BLEND_NORMAL); // 6. Blend mode not normal
+ nir |= (_mix_blend_mode != SP_CSS_BLEND_NORMAL); // 6. Blend mode not normal
nir |= (_isolation == SP_CSS_ISOLATION_ISOLATE); // 7. Explicit isolatiom
-#endif
/* How the rendering is done.
*
@@ -740,9 +782,7 @@ DrawingItem::render(DrawingContext &dc, Geom::IntRect const &area, unsigned flag
}
dc.rectangle(*carea);
dc.setSource(&intermediate);
-#ifdef WITH_CSSBLEND
- set_cairo_blend_operator( dc, _blend_mode );
-#endif
+ set_cairo_blend_operator( dc, _mix_blend_mode );
dc.fill();
dc.setSource(0,0,0,0);
// the call above is to clear a ref on the intermediate surface held by dc
@@ -974,7 +1014,7 @@ DrawingItem::_setStyleCommon(SPStyle *&_style, SPStyle *style)
if (_style) sp_style_unref(_style);
_style = style;
- if (style->filter.set && style->getFilter()) {
+ if (style && style->filter.set && style->getFilter()) {
if (!_filter) {
int primitives = sp_filter_primitive_count(SP_FILTER(style->getFilter()));
_filter = new Inkscape::Filters::Filter(primitives);
diff --git a/src/display/drawing-item.h b/src/display/drawing-item.h
index db803cf60..9b399e6e3 100644
--- a/src/display/drawing-item.h
+++ b/src/display/drawing-item.h
@@ -12,15 +12,15 @@
#ifndef SEEN_INKSCAPE_DISPLAY_DRAWING_ITEM_H
#define SEEN_INKSCAPE_DISPLAY_DRAWING_ITEM_H
-#include <list>
-#include <exception>
+#include <2geom/rect.h>
+#include <2geom/affine.h>
#include <boost/operators.hpp>
#include <boost/utility.hpp>
#include <boost/intrusive/list.hpp>
-#include <2geom/rect.h>
-#include <2geom/affine.h>
+#include <exception>
+#include <list>
-struct SPStyle;
+class SPStyle;
namespace Inkscape {
@@ -28,6 +28,7 @@ class Drawing;
class DrawingCache;
class DrawingContext;
class DrawingItem;
+class DrawingPattern;
namespace Filters {
@@ -114,6 +115,8 @@ public:
void setTransform(Geom::Affine const &trans);
void setClip(DrawingItem *item);
void setMask(DrawingItem *item);
+ void setFillPattern(DrawingPattern *pattern);
+ void setStrokePattern(DrawingPattern *pattern);
void setZOrder(unsigned z);
void setItemBounds(Geom::OptRect const &bounds);
void setFilterBounds(Geom::OptRect const &bounds);
@@ -135,8 +138,8 @@ protected:
CHILD_CLIP = 2, // referenced by _clip member of parent
CHILD_MASK = 3, // referenced by _mask member of parent
CHILD_ROOT = 4, // root item of _drawing
- CHILD_FILL_PATTERN = 5, // not yet implemented: referenced by fill pattern of parent
- CHILD_STROKE_PATTERN = 6 // not yet implemented: referenced by stroke pattern of parent
+ CHILD_FILL_PATTERN = 5, // referenced by fill pattern of parent
+ CHILD_STROKE_PATTERN = 6 // referenced by stroke pattern of parent
};
enum RenderResult {
RENDER_OK = 0,
@@ -185,6 +188,8 @@ protected:
DrawingItem *_clip;
DrawingItem *_mask;
+ DrawingPattern *_fill_pattern;
+ DrawingPattern *_stroke_pattern;
Inkscape::Filters::Filter *_filter;
void *_user_data; ///< Used to associate DrawingItems with SPItems that created them
DrawingCache *_cache;
@@ -209,7 +214,7 @@ protected:
unsigned _antialias : 1; ///< Whether to use antialiasing
unsigned _isolation : 1;
- unsigned _blend_mode : 4;
+ unsigned _mix_blend_mode : 4;
friend class Drawing;
};
diff --git a/src/display/drawing-pattern.cpp b/src/display/drawing-pattern.cpp
new file mode 100644
index 000000000..d0bf5de58
--- /dev/null
+++ b/src/display/drawing-pattern.cpp
@@ -0,0 +1,194 @@
+/**
+ * @file
+ * Canvas belonging to SVG pattern.
+ *//*
+ * Authors:
+ * Tomasz Boczkowski <penginsbacon@gmail.com>
+ *
+ * Copyright (C) 2014 Authors
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "display/cairo-utils.h"
+#include "display/drawing-context.h"
+#include "display/drawing-pattern.h"
+#include "display/drawing-surface.h"
+
+namespace Inkscape {
+
+DrawingPattern::DrawingPattern(Drawing &drawing, bool debug)
+ : DrawingGroup(drawing)
+ , _pattern_to_user(NULL)
+ , _overflow_steps(1)
+ , _debug(debug)
+{
+}
+
+DrawingPattern::~DrawingPattern()
+{
+ delete _pattern_to_user; // delete NULL; is safe
+}
+
+void
+DrawingPattern::setPatternToUserTransform(Geom::Affine const &new_trans) {
+ Geom::Affine current;
+ if (_pattern_to_user) {
+ current = *_pattern_to_user;
+ }
+
+ if (!Geom::are_near(current, new_trans, 1e-18)) {
+ // mark the area where the object was for redraw.
+ _markForRendering();
+ if (new_trans.isIdentity()) {
+ delete _pattern_to_user; // delete NULL; is safe
+ _pattern_to_user = NULL;
+ } else {
+ _pattern_to_user = new Geom::Affine(new_trans);
+ }
+ _markForUpdate(STATE_ALL, true);
+ }
+}
+
+void
+DrawingPattern::setTileRect(Geom::Rect const &tile_rect) {
+ _tile_rect = tile_rect;
+}
+
+void
+DrawingPattern::setOverflow(Geom::Affine initial_transform, int steps, Geom::Affine step_transform) {
+ _overflow_initial_transform = initial_transform;
+ _overflow_steps = steps;
+ _overflow_step_transform = step_transform;
+}
+
+cairo_pattern_t *
+DrawingPattern::renderPattern(float opacity) {
+ bool needs_opacity = (1.0 - opacity) >= 1e-3;
+ bool visible = opacity >= 1e-3;
+
+ if (!visible) {
+ return NULL;
+ }
+
+ if (!_tile_rect || (_tile_rect->area() == 0)) {
+ return NULL;
+ }
+ Geom::Rect pattern_tile = *_tile_rect;
+
+ //TODO: If pattern_to_user set it to identity transform
+
+ // The DrawingSurface class handles the mapping from "logical space"
+ // (coordinates in the rendering) to "physical space" (surface pixels).
+ // An oversampling is done as the pattern may not pixel align with the final surface.
+ // The cairo surface is created when the DrawingContext is declared.
+ // Create drawing surface with size of pattern tile (in pattern space) but with number of pixels
+ // based on required resolution (c).
+ Inkscape::DrawingSurface pattern_surface(pattern_tile, _pattern_resolution);
+ Inkscape::DrawingContext dc(pattern_surface);
+ dc.transform( pattern_surface.drawingTransform().inverse() );
+
+ pattern_tile *= pattern_surface.drawingTransform();
+ Geom::IntRect one_tile = pattern_tile.roundOutwards();
+
+ // Render pattern.
+ if (needs_opacity) {
+ dc.pushGroup(); // this group is for pattern + opacity
+ }
+
+ if (_debug) {
+ dc.setSource(0.8, 0.0, 0.8);
+ dc.paint();
+ }
+
+ //FIXME: What flags to choose?
+ if (_overflow_steps == 1) {
+ render(dc, one_tile, RENDER_DEFAULT);
+ } else {
+ //Overflow transforms need to be transformed to the new coordinate system
+ //introduced by dc.transform( pattern_surface.drawingTransform().inverse() );
+ Geom::Affine dt = pattern_surface.drawingTransform();
+ Geom::Affine idt = pattern_surface.drawingTransform().inverse();
+ Geom::Affine initial_transform = idt * _overflow_initial_transform * dt;
+ Geom::Affine step_transform = idt * _overflow_step_transform * dt;
+
+ dc.transform(initial_transform);
+ for (int i = 0; i < _overflow_steps; i++) {
+ render(dc, one_tile, RENDER_DEFAULT);
+ dc.transform(step_transform);
+ }
+ }
+
+ //Uncomment to debug
+ // cairo_surface_t* raw = pattern_surface.raw();
+ // std::cout << " cairo_surface (sp-pattern): "
+ // << " width: " << cairo_image_surface_get_width( raw )
+ // << " height: " << cairo_image_surface_get_height( raw )
+ // << std::endl;
+ // std::string filename = "drawing-pattern.png";
+ // cairo_surface_write_to_png( pattern_surface.raw(), filename.c_str() );
+
+ if (needs_opacity) {
+ dc.popGroupToSource(); // pop raw pattern
+ dc.paint(opacity); // apply opacity
+ }
+
+ cairo_pattern_t *cp = cairo_pattern_create_for_surface(pattern_surface.raw());
+ // Apply transformation to user space. Also compensate for oversampling.
+ if (_pattern_to_user) {
+ ink_cairo_pattern_set_matrix(cp, _pattern_to_user->inverse() * pattern_surface.drawingTransform());
+ } else {
+ ink_cairo_pattern_set_matrix(cp, pattern_surface.drawingTransform());
+ }
+
+ if (_debug) {
+ cairo_pattern_set_extend(cp, CAIRO_EXTEND_NONE);
+ } else {
+ cairo_pattern_set_extend(cp, CAIRO_EXTEND_REPEAT);
+ }
+
+ return cp;
+}
+
+// TODO investigate if area should be used.
+unsigned DrawingPattern::_updateItem(Geom::IntRect const &area, UpdateContext const &ctx, unsigned flags, unsigned reset)
+{
+ UpdateContext pattern_ctx;
+
+ if (!_tile_rect || (_tile_rect->area() == 0)) {
+ return STATE_NONE;
+ }
+
+ Geom::Rect pattern_tile = *_tile_rect;
+ Geom::Coord det_ctm = ctx.ctm.descrim();
+ Geom::Coord det_ps2user = _pattern_to_user ? _pattern_to_user->descrim() : 1.0;
+ Geom::Coord det_child_transform = _child_transform ? _child_transform->descrim() : 1.0;
+ const double oversampling = 2.0;
+ double scale = det_ctm*det_ps2user*det_child_transform * oversampling;
+ //FIXME: When scale is too big (zooming in a hatch), cairo doesn't render the pattern
+ //More precisely it fails when seting pattern matrix in DrawingPattern::renderPattern
+ //Fully correct solution should make use of visible area bbox and change hach tile rect
+ //accordingly
+ if (scale > 25) {
+ scale = 25;
+ }
+ Geom::Point c(pattern_tile.dimensions()*scale*oversampling);
+ _pattern_resolution = c.ceil();
+
+ Inkscape::DrawingSurface pattern_surface(pattern_tile, _pattern_resolution);
+
+ pattern_ctx.ctm = pattern_surface.drawingTransform();
+ return DrawingGroup::_updateItem(Geom::IntRect::infinite(), pattern_ctx, flags, reset);
+}
+
+} // end namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/display/drawing-pattern.h b/src/display/drawing-pattern.h
new file mode 100644
index 000000000..7483ba067
--- /dev/null
+++ b/src/display/drawing-pattern.h
@@ -0,0 +1,87 @@
+/**
+ * @file
+ * Canvas belonging to SVG pattern.
+ *//*
+ * Authors:
+ * Tomasz Boczkowski <penginsbacon@gmail.com>
+ *
+ * Copyright (C) 2014 Authors
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifndef SEEN_INKSCAPE_DISPLAY_DRAWING_PATTERN_H
+#define SEEN_INKSCAPE_DISPLAY_DRAWING_PATTERN_H
+
+#include "display/drawing-group.h"
+
+typedef struct _cairo_pattern cairo_pattern_t;
+class SPStyle;
+
+namespace Inkscape {
+
+/**
+ * @brief Drawing tree node used for rendering paints.
+ *
+ * DrawingPattern is used for rendering patterns and hatches.
+ *
+ * It renders it's children to a cairo_pattern_t structure that can be
+ * applied as source for fill or stroke operations.
+ */
+class DrawingPattern
+ : public DrawingGroup
+{
+public:
+ DrawingPattern(Drawing &drawing, bool debug = false);
+ ~DrawingPattern();
+
+ /**
+ * Set the transformation from pattern to user coordinate systems.
+ * @see SPPattern description for explanation of coordinate systems.
+ */
+ void setPatternToUserTransform(Geom::Affine const &new_trans);
+ /**
+ * Set the tile rect position and dimentions in content coordinate system
+ */
+ void setTileRect(Geom::Rect const &tile_rect);
+ /**
+ * Turn on overflow rendering.
+ *
+ * Overflow is implemented as repeated rendering of pattern contents. In every step
+ * a translation transform is applied.
+ */
+ void setOverflow(Geom::Affine initial_transform, int steps, Geom::Affine step_transform);
+ /**
+ * Render the pattern.
+ *
+ * Returns caito_pattern_t structure that can be set as source surface.
+ */
+ cairo_pattern_t *renderPattern(float opacity);
+protected:
+ virtual unsigned _updateItem(Geom::IntRect const &area, UpdateContext const &ctx,
+ unsigned flags, unsigned reset);
+
+ Geom::Affine *_pattern_to_user;
+ Geom::Affine _overflow_initial_transform;
+ Geom::Affine _overflow_step_transform;
+ int _overflow_steps;
+ Geom::OptRect _tile_rect;
+ bool _debug;
+ Geom::IntPoint _pattern_resolution;
+};
+
+bool is_drawing_group(DrawingItem *item);
+
+} // end namespace Inkscape
+
+#endif // !SEEN_INKSCAPE_DISPLAY_DRAWING_PATTERN_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/display/drawing-shape.cpp b/src/display/drawing-shape.cpp
index 92d71fad3..66160638f 100644
--- a/src/display/drawing-shape.cpp
+++ b/src/display/drawing-shape.cpp
@@ -9,7 +9,7 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include <glib.h>
+#include <glibmm.h>
#include <2geom/curves.h>
#include <2geom/pathvector.h>
#include <2geom/path-sink.h>
@@ -149,14 +149,13 @@ DrawingShape::_updateItem(Geom::IntRect const &area, UpdateContext const &ctx, u
return STATE_ALL;
}
-#ifdef WITH_SVG2
void
DrawingShape::_renderFill(DrawingContext &dc)
{
Inkscape::DrawingContext::Save save(dc);
dc.transform(_ctm);
- bool has_fill = _nrstyle.prepareFill(dc, _item_bbox);
+ bool has_fill = _nrstyle.prepareFill(dc, _item_bbox, _fill_pattern);
if( has_fill ) {
dc.path(_curve->get_pathvector());
@@ -172,7 +171,7 @@ DrawingShape::_renderStroke(DrawingContext &dc)
Inkscape::DrawingContext::Save save(dc);
dc.transform(_ctm);
- bool has_stroke = _nrstyle.prepareStroke(dc, _item_bbox);
+ bool has_stroke = _nrstyle.prepareStroke(dc, _item_bbox, _stroke_pattern);
has_stroke &= (_nrstyle.stroke_width != 0);
if( has_stroke ) {
@@ -183,7 +182,6 @@ DrawingShape::_renderStroke(DrawingContext &dc)
dc.newPath(); // clear path
}
}
-#endif
void
DrawingShape::_renderMarkers(DrawingContext &dc, Geom::IntRect const &area, unsigned flags, DrawingItem *stop_at)
@@ -222,10 +220,9 @@ DrawingShape::_renderItem(DrawingContext &dc, Geom::IntRect const &area, unsigne
}
-#ifdef WITH_SVG2
if( _nrstyle.paint_order_layer[0] == NRStyle::PAINT_ORDER_NORMAL ) {
// This is the most common case, special case so we don't call get_pathvector(), etc. twice
-#endif
+
{
// we assume the context has no path
Inkscape::DrawingContext::Save save(dc);
@@ -234,8 +231,8 @@ DrawingShape::_renderItem(DrawingContext &dc, Geom::IntRect const &area, unsigne
// update fill and stroke paints.
// this cannot be done during nr_arena_shape_update, because we need a Cairo context
// to render svg:pattern
- bool has_fill = _nrstyle.prepareFill(dc, _item_bbox);
- bool has_stroke = _nrstyle.prepareStroke(dc, _item_bbox);
+ bool has_fill = _nrstyle.prepareFill(dc, _item_bbox, _fill_pattern);
+ bool has_stroke = _nrstyle.prepareStroke(dc, _item_bbox, _stroke_pattern);
has_stroke &= (_nrstyle.stroke_width != 0);
if (has_fill || has_stroke) {
@@ -255,7 +252,6 @@ DrawingShape::_renderItem(DrawingContext &dc, Geom::IntRect const &area, unsigne
_renderMarkers(dc, area, flags, stop_at);
return RENDER_OK;
-#ifdef WITH_SVG2
}
// Handle different paint orders
@@ -276,7 +272,6 @@ DrawingShape::_renderItem(DrawingContext &dc, Geom::IntRect const &area, unsigne
}
}
return RENDER_OK;
-#endif
}
void DrawingShape::_clipItem(DrawingContext &dc, Geom::IntRect const & /*area*/)
diff --git a/src/display/drawing-shape.h b/src/display/drawing-shape.h
index 405c789e0..9d93a642f 100644
--- a/src/display/drawing-shape.h
+++ b/src/display/drawing-shape.h
@@ -15,7 +15,7 @@
#include "display/drawing-item.h"
#include "display/nr-style.h"
-struct SPStyle;
+class SPStyle;
class SPCurve;
namespace Inkscape {
@@ -39,10 +39,8 @@ protected:
virtual DrawingItem *_pickItem(Geom::Point const &p, double delta, unsigned flags);
virtual bool _canClip();
-#ifdef WITH_SVG2
void _renderFill(DrawingContext &dc);
void _renderStroke(DrawingContext &dc);
-#endif
void _renderMarkers(DrawingContext &dc, Geom::IntRect const &area, unsigned flags,
DrawingItem *stop_at);
diff --git a/src/display/drawing-surface.h b/src/display/drawing-surface.h
index e937cca55..7bec1606a 100644
--- a/src/display/drawing-surface.h
+++ b/src/display/drawing-surface.h
@@ -14,11 +14,16 @@
#include <boost/shared_ptr.hpp>
#include <cairo.h>
-#include <gdk-pixbuf/gdk-pixbuf.h>
#include <2geom/affine.h>
#include <2geom/rect.h>
#include <2geom/transforms.h>
+extern "C" {
+typedef struct _cairo cairo_t;
+typedef struct _cairo_surface cairo_surface_t;
+typedef struct _cairo_region cairo_region_t;
+}
+
namespace Inkscape {
class DrawingContext;
diff --git a/src/display/drawing-text.cpp b/src/display/drawing-text.cpp
index a280e221a..afe661b2e 100644
--- a/src/display/drawing-text.cpp
+++ b/src/display/drawing-text.cpp
@@ -9,8 +9,8 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include "display/cairo-utils.h"
-#include "display/canvas-bpath.h" // for SPWindRule (WTF!)
+//#include "display/cairo-utils.h"
+//#include "display/canvas-bpath.h" // for SPWindRule (WTF!)
#include "display/drawing.h"
#include "display/drawing-context.h"
#include "display/drawing-surface.h"
@@ -20,6 +20,9 @@
#include "style.h"
#include "2geom/pathvector.h"
+#include "display/cairo-utils.h"
+#include "display/canvas-bpath.h"
+
namespace Inkscape {
@@ -67,16 +70,14 @@ unsigned DrawingGlyphs::_updateItem(Geom::IntRect const &/*area*/, UpdateContext
_pick_bbox = Geom::IntRect();
_bbox = Geom::IntRect();
-/* orignally it did the one line below,
- but it did not handle ws characters at all, and it had problems with scaling for overline/underline.
- Replaced with the section below, which seems to be much more stable.
-
- Geom::OptRect b = bounds_exact_transformed(*_font->PathVector(_glyph), ctx.ctm);
-*/
- /* Make a bounding box that is a little taller and lower (currently 10% extra) than the font's drawing box. Extra space is
- to hold overline or underline, if present. All characters in a font use the same ascent and descent,
- but different widths. This lets leading and trailing spaces have text decorations. If it is not done
- the bounding box is limited to the box surrounding the drawn parts of visible glyphs only, and draws outside are ignored.
+ /*
+ Make a bounding box for drawing that is a little taller and lower (currently 10% extra) than
+ the font's drawing box. Extra space is to hold overline or underline, if present. All
+ characters in a font use the same ascent and descent, but different widths. This lets leading
+ and trailing spaces have text decorations. If it is not done the bounding box is limited to
+ the box surrounding the drawn parts of visible glyphs only, and draws outside are ignored.
+ The box is also a hair wider than the text, since the glyphs do not always start or end at
+ the left and right edges of the box defined in the font.
*/
float scale_bigbox = 1.0;
@@ -84,9 +85,45 @@ unsigned DrawingGlyphs::_updateItem(Geom::IntRect const &/*area*/, UpdateContext
scale_bigbox /= _transform->descrim();
}
- Geom::Rect bigbox(Geom::Point(0.0, _asc*scale_bigbox*1.1),Geom::Point(_width*scale_bigbox, -_dsc*scale_bigbox*1.1));
+ Geom::Rect bigbox(Geom::Point(-_width*scale_bigbox*0.1, _asc*scale_bigbox*1.1),Geom::Point(_width*scale_bigbox, -_dsc*scale_bigbox*1.1));
Geom::Rect b = bigbox * ctx.ctm;
+ /*
+ The pick box matches the characters as best as it can, leaving no extra space above or below
+ for decorations. The pathvector may include spaces, and spaces have no drawable glyph.
+ Catch those and do not pass them to bounds_exact_transformed(), which crashes Inkscape if it
+ sees a nondrawable glyph. Instead mock up a pickbox for them using font characteristics.
+ There may also be some other similar white space characters in some other unforeseen context
+ which should be handled by this code as well..
+ */
+
+ Geom::OptRect pb;
+ if(_drawable){
+ pb = bounds_exact_transformed(*_font->PathVector(_glyph), ctx.ctm);
+ }
+ if(!pb){ // Fallback
+ Geom::Rect pbigbox(Geom::Point(0.0, _asc*scale_bigbox*0.66),Geom::Point(_width*scale_bigbox, 0.0));
+ pb = pbigbox * ctx.ctm;
+ }
+
+#if 0
+ /* FIXME if this is commented out then not even an approximation of pick on decorations */
+ /* adjust the pick box up or down to include the decorations.
+ This is only approximate since at this point we don't know how wide that line is, if it has
+ an unusual offset, and so forth. The selection point is set at what is roughly the center of
+ the decoration (vertically) for the wide ones, like wavy and double line.
+ The text decorations are not actually selectable.
+ */
+ if (_decorations.overline || _decorations.underline) {
+ double top = _asc*scale_bigbox*0.66;
+ double bot = 0;
+ if (_decorations.overline) { top = _asc * scale_bigbox * 1.025; }
+ if (_decorations.underline) { bot = -_dsc * scale_bigbox * 0.2; }
+ Geom::Rect padjbox(Geom::Point(0.0, top),Geom::Point(_width*scale_bigbox, bot));
+ pb.unionWith(padjbox * ctx.ctm);
+ }
+#endif
+
if (ggroup->_nrstyle.stroke.type != NRStyle::PAINT_NONE) {
// this expands the selection box for cases where the stroke is "thick"
float scale = ctx.ctm.descrim();
@@ -96,10 +133,11 @@ unsigned DrawingGlyphs::_updateItem(Geom::IntRect const &/*area*/, UpdateContext
float width = MAX(0.125, ggroup->_nrstyle.stroke_width * scale);
if ( fabs(ggroup->_nrstyle.stroke_width * scale) > 0.01 ) { // FIXME: this is always true
b.expandBy(0.5 * width);
+ pb->expandBy(0.5 * width);
}
// save bbox without miters for picking
- _pick_bbox = b.roundOutwards();
+ _pick_bbox = pb->roundOutwards();
float miterMax = width * ggroup->_nrstyle.miter_limit;
if ( miterMax > 0.01 ) {
@@ -110,35 +148,31 @@ unsigned DrawingGlyphs::_updateItem(Geom::IntRect const &/*area*/, UpdateContext
_bbox = b.roundOutwards();
} else {
_bbox = b.roundOutwards();
- _pick_bbox = *_bbox;
+ _pick_bbox = pb->roundOutwards();
}
-/*
-std::cout << "DEBUG _bbox"
-<< " { " << _bbox->min()[Geom::X] << " , " << _bbox->min()[Geom::Y]
-<< " } , { " << _bbox->max()[Geom::X] << " , " << _bbox->max()[Geom::Y]
-<< " }" << std::endl;
-*/
return STATE_ALL;
}
-DrawingItem *
-DrawingGlyphs::_pickItem(Geom::Point const &p, double delta, unsigned /*flags*/)
+DrawingItem *DrawingGlyphs::_pickItem(Geom::Point const &p, double /*delta*/, unsigned /*flags*/)
{
DrawingText *ggroup = dynamic_cast<DrawingText *>(_parent);
if (!ggroup) {
throw InvalidItemException();
}
+ DrawingItem *result = NULL;
bool invisible = (ggroup->_nrstyle.fill.type == NRStyle::PAINT_NONE) &&
(ggroup->_nrstyle.stroke.type == NRStyle::PAINT_NONE);
- if (!_font || !_bbox || (!_drawing.outline() && invisible) ) {
- return NULL;
- }
- // With text we take a simple approach: pick if the point is in a character bbox
- Geom::Rect expanded(_pick_bbox);
- expanded.expandBy(delta);
- if (expanded.contains(p)) return this;
- return NULL;
+ if (_font && _bbox && (_drawing.outline() || !invisible) ) {
+ // With text we take a simple approach: pick if the point is in a character bbox
+ Geom::Rect expanded(_pick_bbox);
+ // FIXME, why expand by delta? When is the next line needed?
+ // expanded.expandBy(delta);
+ if (expanded.contains(p)) {
+ result = this;
+ }
+ }
+ return result;
}
@@ -195,7 +229,7 @@ DrawingText::_updateItem(Geom::IntRect const &area, UpdateContext const &ctx, un
return DrawingGroup::_updateItem(area, ctx, flags, reset);
}
-void DrawingText::decorateStyle(DrawingContext &dc, double vextent, double xphase, Geom::Point const &p1, Geom::Point const &p2)
+void DrawingText::decorateStyle(DrawingContext &dc, double vextent, double xphase, Geom::Point const &p1, Geom::Point const &p2, double thickness)
{
double wave[16]={
0.000000, 0.382499, 0.706825, 0.923651, 1.000000, 0.923651, 0.706825, 0.382499,
@@ -213,7 +247,6 @@ void DrawingText::decorateStyle(DrawingContext &dc, double vextent, double xphas
4, 3, 2, 1,
-4, -3, -2, -1
};
- Geom::Point p3,p4,ps,pf;
double step = vextent/32.0;
unsigned i = 15 & (unsigned) round(xphase/step); // xphase is >= 0.0
@@ -221,26 +254,19 @@ void DrawingText::decorateStyle(DrawingContext &dc, double vextent, double xphas
This allows decoration continuity within the line, and does not step outside the clip box off the end
For the first/last section on the line though, stay well clear of the edge, or when the
text is dragged it may "spray" pixels.
- if(_nrstyle.tspan_line_end){ pf = p2 - Geom::Point(2*step, 0.0); }
- else { pf = p2; }
- if(_nrstyle.tspan_line_start){ ps = p1 + Geom::Point(2*step, 0.0);
- i = 15 & (i + 2);
- }
- else { ps = p1; }
*/
/* snap to nearest step in X */
-ps = Geom::Point(step * round(p1[Geom::X]/step),p1[Geom::Y]);
-pf = Geom::Point(step * round(p2[Geom::X]/step),p2[Geom::Y]);
+ Geom::Point ps = Geom::Point(step * round(p1[Geom::X]/step),p1[Geom::Y]);
+ Geom::Point pf = Geom::Point(step * round(p2[Geom::X]/step),p2[Geom::Y]);
+ Geom::Point poff = Geom::Point(0,thickness/2.0);
if(_nrstyle.text_decoration_style & TEXT_DECORATION_STYLE_ISDOUBLE){
ps -= Geom::Point(0, vextent/12.0);
pf -= Geom::Point(0, vextent/12.0);
- dc.moveTo(ps);
- dc.lineTo(pf);
+ dc.rectangle( Geom::Rect(ps + poff, pf - poff));
ps += Geom::Point(0, vextent/6.0);
pf += Geom::Point(0, vextent/6.0);
- dc.moveTo(ps);
- dc.lineTo(pf);
+ dc.rectangle( Geom::Rect(ps + poff, pf - poff));
}
/* The next three have a problem in that they are phase dependent. The bits of a line are not
necessarily passing through this routine in order, so we have to use the xphase information
@@ -248,43 +274,52 @@ pf = Geom::Point(step * round(p2[Geom::X]/step),p2[Geom::Y]);
Huge possitive offset should keep the phase calculation from ever being negative.
*/
else if(_nrstyle.text_decoration_style & TEXT_DECORATION_STYLE_DOTTED){
+ // FIXME: Per spec, this should produce round dots.
+ Geom::Point pv = ps;
while(1){
+ Geom::Point pvlast = pv;
if(dots[i]>0){
- if(ps[Geom::X]> pf[Geom::X])break;
- dc.moveTo(ps);
- ps += Geom::Point(step * (double)dots[i], 0.0);
- if(ps[Geom::X]>= pf[Geom::X]){
- dc.lineTo(pf);
+ if(pv[Geom::X] > pf[Geom::X]) break;
+
+ pv += Geom::Point(step * (double)dots[i], 0.0);
+
+ if(pv[Geom::X]>= pf[Geom::X]){
+ // Last dot
+ dc.rectangle( Geom::Rect(pvlast + poff, pf - poff));
break;
+ } else {
+ dc.rectangle( Geom::Rect(pvlast + poff, pv - poff));
}
- else {
- dc.lineTo(ps);
- }
- ps += Geom::Point(step * 4.0, 0.0);
- }
- else {
- ps += Geom::Point(step * -(double)dots[i], 0.0);
+
+ pv += Geom::Point(step * 4.0, 0.0);
+
+ } else {
+ pv += Geom::Point(step * -(double)dots[i], 0.0);
}
i = 0; // once in phase, it stays in phase
}
}
else if(_nrstyle.text_decoration_style & TEXT_DECORATION_STYLE_DASHED){
+ Geom::Point pv = ps;
while(1){
+ Geom::Point pvlast = pv;
if(dashes[i]>0){
- if(ps[Geom::X]> pf[Geom::X])break;
- dc.moveTo(ps);
- ps += Geom::Point(step * (double)dashes[i], 0.0);
- if(ps[Geom::X]>= pf[Geom::X]){
- dc.lineTo(pf);
+ if(pv[Geom::X]> pf[Geom::X]) break;
+
+ pv += Geom::Point(step * (double)dashes[i], 0.0);
+
+ if(pv[Geom::X]>= pf[Geom::X]){
+ // Last dash
+ dc.rectangle( Geom::Rect(pvlast + poff, pf - poff));
break;
+ } else {
+ dc.rectangle( Geom::Rect(pvlast + poff, pv - poff));
}
- else {
- dc.lineTo(ps);
- }
- ps += Geom::Point(step * 8.0, 0.0);
- }
- else {
- ps += Geom::Point(step * -(double)dashes[i], 0.0);
+
+ pv += Geom::Point(step * 8.0, 0.0);
+
+ } else {
+ pv += Geom::Point(step * -(double)dashes[i], 0.0);
}
i = 0; // once in phase, it stays in phase
}
@@ -292,7 +327,7 @@ pf = Geom::Point(step * round(p2[Geom::X]/step),p2[Geom::Y]);
else if(_nrstyle.text_decoration_style & TEXT_DECORATION_STYLE_WAVY){
double amp = vextent/10.0;
double x = ps[Geom::X];
- double y = ps[Geom::Y];
+ double y = ps[Geom::Y] + poff[Geom::Y];
dc.moveTo(Geom::Point(x, y + amp * wave[i]));
while(1){
i = ((i + 1) & 15);
@@ -300,17 +335,25 @@ pf = Geom::Point(step * round(p2[Geom::X]/step),p2[Geom::Y]);
dc.lineTo(Geom::Point(x, y + amp * wave[i]));
if(x >= pf[Geom::X])break;
}
- }
+ y = ps[Geom::Y] - poff[Geom::Y];
+ dc.lineTo(Geom::Point(x, y + amp * wave[i]));
+ while(1){
+ i = ((i - 1) & 15);
+ x -= step;
+ dc.lineTo(Geom::Point(x, y + amp * wave[i]));
+ if(x <= ps[Geom::X])break;
+ }
+ dc.closePath();
+ }
else { // TEXT_DECORATION_STYLE_SOLID, also default in case it was not set for some reason
- dc.moveTo(ps);
- dc.lineTo(pf);
-// dc.revrectangle(Geom::Rect(ps,pf));
+ dc.rectangle( Geom::Rect(ps + poff, pf - poff));
}
}
/* returns scaled line thickness */
-double DrawingText::decorateItem(DrawingContext &dc, Geom::Affine const &aff, double phase_length)
+void DrawingText::decorateItem(DrawingContext &dc, double phase_length, bool under)
{
+ if (_nrstyle.font_size < 1.0e-32)return; // would cause a divide by zero and nothing would be visible anyway
double tsp_width_adj = _nrstyle.tspan_width / _nrstyle.font_size;
double tsp_asc_adj = _nrstyle.ascender / _nrstyle.font_size;
double tsp_size_adj = (_nrstyle.ascender + _nrstyle.descender) / _nrstyle.font_size;
@@ -318,49 +361,54 @@ double DrawingText::decorateItem(DrawingContext &dc, Geom::Affine const &aff, do
double final_underline_thickness = CLAMP(_nrstyle.underline_thickness, tsp_size_adj/30.0, tsp_size_adj/10.0);
double final_line_through_thickness = CLAMP(_nrstyle.line_through_thickness, tsp_size_adj/30.0, tsp_size_adj/10.0);
- double scale = aff.descrim();
double xphase = phase_length/ _nrstyle.font_size; // used to figure out phase of patterns
- Inkscape::DrawingContext::Save save(dc);
- dc.transform(aff); // must be leftmost affine in span
-
Geom::Point p1;
Geom::Point p2;
// All lines must be the same thickness, in combinations, line_through trumps underline
double thickness = final_underline_thickness;
- if(_nrstyle.text_decoration_line & TEXT_DECORATION_LINE_UNDERLINE){
- p1 = Geom::Point(0.0, -_nrstyle.underline_position);
- p2 = Geom::Point(tsp_width_adj,-_nrstyle.underline_position);
- decorateStyle(dc, tsp_size_adj, xphase, p1, p2);
- }
- if(_nrstyle.text_decoration_line & TEXT_DECORATION_LINE_OVERLINE){
- p1 = Geom::Point(0.0, tsp_asc_adj -_nrstyle.underline_position + 1 * final_underline_thickness);
- p2 = Geom::Point(tsp_width_adj,tsp_asc_adj -_nrstyle.underline_position + 1 * final_underline_thickness);
- decorateStyle(dc, tsp_size_adj, xphase, p1, p2);
- }
- if(_nrstyle.text_decoration_line & TEXT_DECORATION_LINE_LINETHROUGH){
- thickness = final_line_through_thickness;
- p1 = Geom::Point(0.0, _nrstyle.line_through_position);
- p2 = Geom::Point(tsp_width_adj,_nrstyle.line_through_position);
- decorateStyle(dc, tsp_size_adj, xphase, p1, p2);
- }
- // Obviously this does not blink, but it does indicate which text has been set with that attribute
- if(_nrstyle.text_decoration_line & TEXT_DECORATION_LINE_BLINK){
- thickness = final_line_through_thickness;
- p1 = Geom::Point(0.0, _nrstyle.line_through_position - 2*final_line_through_thickness);
- p2 = Geom::Point(tsp_width_adj,_nrstyle.line_through_position - 2*final_line_through_thickness);
- decorateStyle(dc, tsp_size_adj, xphase, p1, p2);
- p1 = Geom::Point(0.0, _nrstyle.line_through_position + 2*final_line_through_thickness);
- p2 = Geom::Point(tsp_width_adj,_nrstyle.line_through_position + 2*final_line_through_thickness);
- decorateStyle(dc, tsp_size_adj, xphase, p1, p2);
+ dc.setTolerance(0.5); // Is this really necessary... could effect dots.
+
+ if( under ) {
+
+ if(_nrstyle.text_decoration_line & TEXT_DECORATION_LINE_UNDERLINE){
+ p1 = Geom::Point(0.0, -_nrstyle.underline_position);
+ p2 = Geom::Point(tsp_width_adj,-_nrstyle.underline_position);
+ decorateStyle(dc, tsp_size_adj, xphase, p1, p2, thickness);
+ }
+
+ if(_nrstyle.text_decoration_line & TEXT_DECORATION_LINE_OVERLINE){
+ p1 = Geom::Point(0.0, tsp_asc_adj -_nrstyle.underline_position + 1 * final_underline_thickness);
+ p2 = Geom::Point(tsp_width_adj,tsp_asc_adj -_nrstyle.underline_position + 1 * final_underline_thickness);
+ decorateStyle(dc, tsp_size_adj, xphase, p1, p2, thickness);
+ }
+
+ } else {
+ // Over
+
+ if(_nrstyle.text_decoration_line & TEXT_DECORATION_LINE_LINETHROUGH){
+ thickness = final_line_through_thickness;
+ p1 = Geom::Point(0.0, _nrstyle.line_through_position);
+ p2 = Geom::Point(tsp_width_adj,_nrstyle.line_through_position);
+ decorateStyle(dc, tsp_size_adj, xphase, p1, p2, thickness);
+ }
+
+ // Obviously this does not blink, but it does indicate which text has been set with that attribute
+ if(_nrstyle.text_decoration_line & TEXT_DECORATION_LINE_BLINK){
+ thickness = final_line_through_thickness;
+ p1 = Geom::Point(0.0, _nrstyle.line_through_position - 2*final_line_through_thickness);
+ p2 = Geom::Point(tsp_width_adj,_nrstyle.line_through_position - 2*final_line_through_thickness);
+ decorateStyle(dc, tsp_size_adj, xphase, p1, p2, thickness);
+ p1 = Geom::Point(0.0, _nrstyle.line_through_position + 2*final_line_through_thickness);
+ p2 = Geom::Point(tsp_width_adj,_nrstyle.line_through_position + 2*final_line_through_thickness);
+ decorateStyle(dc, tsp_size_adj, xphase, p1, p2, thickness);
+ }
}
- thickness *= scale;
- return(thickness);
}
unsigned DrawingText::_renderItem(DrawingContext &dc, Geom::IntRect const &/*area*/, unsigned /*flags*/, DrawingItem * /*stop_at*/)
{
- if (_drawing.outline()) {
+ if (_drawing.outline()) {
guint32 rgba = _drawing.outlinecolor;
Inkscape::DrawingContext::Save save(dc);
dc.setSource(rgba);
@@ -382,127 +430,187 @@ unsigned DrawingText::_renderItem(DrawingContext &dc, Geom::IntRect const &/*are
return RENDER_OK;
}
- // NOTE: this is very similar to drawing-shape.cpp; the only difference is in path feeding
- double leftmost = DBL_MAX;
- double phase_length = 0.0;
- bool firsty = true;
- bool decorate = true;
- double starty = 0.0;
- Geom::Affine aff;
- using Geom::X;
- using Geom::Y;
-
- // NOTE:
+ // NOTE: This is very similar to drawing-shape.cpp; the only differences are in path feeding
+ // and in applying text decorations.
+
+
+ // Do we have text decorations?
+ bool decorate = (_nrstyle.text_decoration_line != TEXT_DECORATION_LINE_CLEAR );
+
// prepareFill / prepareStroke need to be called with _ctm in effect.
// However, we might need to apply a different ctm for glyphs.
// Therefore, only apply this ctm temporarily.
- bool has_stroke, has_fill;
+ bool has_stroke = false;
+ bool has_fill = false;
+ bool has_td_fill = false;
+ bool has_td_stroke = false;
{
Inkscape::DrawingContext::Save save(dc);
dc.transform(_ctm);
- has_fill = _nrstyle.prepareFill( dc, _item_bbox);
- has_stroke = _nrstyle.prepareStroke(dc, _item_bbox);
+ has_fill = _nrstyle.prepareFill( dc, _item_bbox, _fill_pattern);
+ has_stroke = _nrstyle.prepareStroke( dc, _item_bbox, _stroke_pattern);
+
+ // Avoid creating patterns if not needed
+ if( decorate ) {
+ has_td_fill = _nrstyle.prepareTextDecorationFill( dc, _item_bbox, _fill_pattern);
+ has_td_stroke = _nrstyle.prepareTextDecorationStroke(dc, _item_bbox, _stroke_pattern);
+ }
}
- if (has_fill || has_stroke) {
- Geom::Affine rotinv;
- bool invset = false;
+ if (has_fill || has_stroke || has_td_fill || has_td_stroke) {
- // accumulate the path that represents the glyphs
- for (ChildrenList::iterator i = _children.begin(); i != _children.end(); ++i) {
- DrawingGlyphs *g = dynamic_cast<DrawingGlyphs *>(&*i);
- if (!g) throw InvalidItemException();
- if (!invset) {
- rotinv = g->_ctm.withoutTranslation().inverse();
- invset = true;
- }
+ // Determine order for fill and stroke.
+ // Text doesn't have markers, we can do paint-order quick and dirty.
+ bool fill_first = false;
+ if( _nrstyle.paint_order_layer[0] == NRStyle::PAINT_ORDER_NORMAL ||
+ _nrstyle.paint_order_layer[0] == NRStyle::PAINT_ORDER_FILL ||
+ _nrstyle.paint_order_layer[2] == NRStyle::PAINT_ORDER_STROKE ) {
+ fill_first = true;
+ } // Won't get "stroke fill stroke" but that isn't 'valid'
+
+
+ // Determine geometry of text decoration
+ double phase_length = 0.0;
+ Geom::Affine aff;
+ if( decorate ) {
+
+ Geom::Affine rotinv;
+ bool invset = false;
+ double leftmost = DBL_MAX;
+ bool first_y = true;
+ double start_y = 0.0;
+ for (ChildrenList::iterator i = _children.begin(); i != _children.end(); ++i) {
+
+ DrawingGlyphs *g = dynamic_cast<DrawingGlyphs *>(&*i);
+ if (!g) throw InvalidItemException();
+
+ if (!invset) {
+ rotinv = g->_ctm.withoutTranslation().inverse();
+ invset = true;
+ }
- Inkscape::DrawingContext::Save save(dc);
- if (g->_ctm.isSingular()) continue;
- dc.transform(g->_ctm);
- if (g->_drawable) {
- dc.path(*g->_font->PathVector(g->_glyph));
- }
- // get the leftmost affine transform (leftmost defined with respect to the x axis of the first transform).
- // That way the decoration will work no matter what mix of L->R, R->L text is in the span.
- if (_nrstyle.text_decoration_line != TEXT_DECORATION_LINE_CLEAR) {
Geom::Point pt = g->_ctm.translation() * rotinv;
- if (pt[X] < leftmost) {
- leftmost = pt[X];
+ if (pt[Geom::X] < leftmost) {
+ leftmost = pt[Geom::X];
aff = g->_ctm;
phase_length = g->_pl;
}
- /* If the text has been mapped onto a path, which causes y to vary, drop the text decorations.
- To handle that properly would need a conformal map
- */
- if (firsty) {
- firsty = false;
- starty = pt[Y];
+
+ // Check for text on a path. FIXME: This needs better test (and probably not here).
+ if (first_y) {
+ first_y = false;
+ start_y = pt[Geom::Y];
}
- else if (fabs(pt[Y] - starty) > 1.0e-6) {
+ else if (fabs(pt[Geom::Y] - start_y) > 1.0e-6) {
+ // If the text has been mapped onto a path, which causes y to vary, drop the
+ // text decorations. To handle that properly would need a conformal map.
decorate = false;
}
}
}
- // draw the text itself
- // we need to apply this object's ctm again
- Inkscape::DrawingContext::Save save(dc);
- dc.transform(_ctm);
+ // Draw text decorations that go UNDER the text (underline, over-line)
+ if( decorate ) {
-#ifdef WITH_SVG2
- // Text doesn't have markers, we can do paint-order quick and dirty.
- bool fill_first = false;
- if( _nrstyle.paint_order_layer[0] == NRStyle::PAINT_ORDER_NORMAL ||
- _nrstyle.paint_order_layer[0] == NRStyle::PAINT_ORDER_FILL ||
- _nrstyle.paint_order_layer[2] == NRStyle::PAINT_ORDER_STROKE ) {
- fill_first = true;
- } // Won't get "stroke fill stroke" but that isn't 'valid'
+ {
+ Inkscape::DrawingContext::Save save(dc);
+ dc.transform(aff); // must be leftmost affine in span
+ decorateItem(dc, phase_length, true);
+ }
+
+ {
+ Inkscape::DrawingContext::Save save(dc);
+ dc.transform(_ctm); // Needed so that fill pattern rotates with text
+
+ if (has_td_fill && fill_first) {
+ _nrstyle.applyTextDecorationFill(dc);
+ dc.fillPreserve();
+ }
+
+ if (has_td_stroke) {
+ _nrstyle.applyTextDecorationStroke(dc);
+ dc.strokePreserve();
+ }
+
+ if (has_td_fill && !fill_first) {
+ _nrstyle.applyTextDecorationFill(dc);
+ dc.fillPreserve();
+ }
- if (has_fill && fill_first) {
-#else
- if (has_fill) {
-#endif
- _nrstyle.applyFill(dc);
- dc.fillPreserve();
+ }
+
+ dc.newPath(); // Clear text-decoration path
}
- if (has_stroke) {
- _nrstyle.applyStroke(dc);
- dc.strokePreserve();
+
+ // accumulate the path that represents the glyphs
+ for (ChildrenList::iterator i = _children.begin(); i != _children.end(); ++i) {
+ DrawingGlyphs *g = dynamic_cast<DrawingGlyphs *>(&*i);
+ if (!g) throw InvalidItemException();
+
+ Inkscape::DrawingContext::Save save(dc);
+ if (g->_ctm.isSingular()) continue;
+ dc.transform(g->_ctm);
+ if (g->_drawable) {
+ dc.path(*g->_font->PathVector(g->_glyph));
+ }
}
-#ifdef WITH_SVG2
- if (has_fill && !fill_first) {
- _nrstyle.applyFill(dc);
- dc.fillPreserve();
+
+ // Draw the glyphs.
+ {
+ Inkscape::DrawingContext::Save save(dc);
+ dc.transform(_ctm);
+
+ if (has_fill && fill_first) {
+ _nrstyle.applyFill(dc);
+ dc.fillPreserve();
+ }
+
+ if (has_stroke) {
+ _nrstyle.applyStroke(dc);
+ dc.strokePreserve();
+ }
+
+ if (has_fill && !fill_first) {
+ _nrstyle.applyFill(dc);
+ dc.fillPreserve();
+ }
}
-#endif
- dc.newPath(); // clear path
-
- // draw text decoration
- if (_nrstyle.text_decoration_line != TEXT_DECORATION_LINE_CLEAR && decorate) {
- guint32 ergba;
- if (_nrstyle.text_decoration_useColor) { // color different from the glyph
- ergba = SP_RGBA32_F_COMPOSE(
- _nrstyle.text_decoration_color.color.v.c[0],
- _nrstyle.text_decoration_color.color.v.c[1],
- _nrstyle.text_decoration_color.color.v.c[2],
- 1.0);
+ dc.newPath(); // Clear glyphs path
+
+ // Draw text decorations that go OVER the text (line through, blink)
+ if (decorate) {
+
+ {
+ Inkscape::DrawingContext::Save save(dc);
+ dc.transform(aff); // must be leftmost affine in span
+ decorateItem(dc, phase_length, false);
}
- else { // whatever the current fill color is
- ergba = SP_RGBA32_F_COMPOSE(
- _nrstyle.fill.color.v.c[0],
- _nrstyle.fill.color.v.c[1],
- _nrstyle.fill.color.v.c[2],
- 1.0);
+
+ {
+ Inkscape::DrawingContext::Save save(dc);
+ dc.transform(_ctm); // Needed so that fill pattern rotates with text
+
+ if (has_td_fill && fill_first) {
+ _nrstyle.applyTextDecorationFill(dc);
+ dc.fillPreserve();
+ }
+
+ if (has_td_stroke) {
+ _nrstyle.applyTextDecorationStroke(dc);
+ dc.strokePreserve();
+ }
+
+ if (has_td_fill && !fill_first) {
+ _nrstyle.applyTextDecorationFill(dc);
+ dc.fillPreserve();
+ }
+
}
- dc.setSource(ergba);
- dc.setTolerance(0.5);
- double thickness = decorateItem(dc, aff, phase_length);
- dc.setLineWidth(thickness);
- dc.strokePreserve();
- dc.newPath(); // clear path
+
+ dc.newPath(); // Clear text-decoration path
}
+
}
return RENDER_OK;
}
diff --git a/src/display/drawing-text.h b/src/display/drawing-text.h
index b863ca2a4..4453a3db4 100644
--- a/src/display/drawing-text.h
+++ b/src/display/drawing-text.h
@@ -15,7 +15,7 @@
#include "display/drawing-group.h"
#include "display/nr-style.h"
-struct SPStyle;
+class SPStyle;
class font_instance;
namespace Inkscape {
@@ -68,8 +68,8 @@ protected:
virtual DrawingItem *_pickItem(Geom::Point const &p, double delta, unsigned flags);
virtual bool _canClip();
- double decorateItem(DrawingContext &dc, Geom::Affine const &aff, double phase_length);
- void decorateStyle(DrawingContext &dc, double vextent, double xphase, Geom::Point const &p1, Geom::Point const &p2);
+ void decorateItem(DrawingContext &dc, double phase_length, bool under);
+ void decorateStyle(DrawingContext &dc, double vextent, double xphase, Geom::Point const &p1, Geom::Point const &p2, double thickness);
NRStyle _nrstyle;
friend class DrawingGlyphs;
diff --git a/src/display/drawing.h b/src/display/drawing.h
index cc74833ba..0c12b1510 100644
--- a/src/display/drawing.h
+++ b/src/display/drawing.h
@@ -12,18 +12,18 @@
#ifndef SEEN_INKSCAPE_DISPLAY_DRAWING_H
#define SEEN_INKSCAPE_DISPLAY_DRAWING_H
-#include <set>
-#include <glib.h>
+#include <2geom/rect.h>
#include <boost/operators.hpp>
#include <boost/utility.hpp>
+#include <set>
#include <sigc++/sigc++.h>
-#include <2geom/rect.h>
+
#include "display/drawing-item.h"
#include "display/rendermode.h"
#include "nr-filter-colormatrix.h"
typedef struct _SPCanvasArena SPCanvasArena;
-
+typedef unsigned int guint32;
namespace Inkscape {
@@ -65,7 +65,7 @@ public:
OutlineColors const &colors() const { return _colors; }
- void setGrayscaleMatrix(gdouble value_matrix[20]);
+ void setGrayscaleMatrix(double value_matrix[20]);
void update(Geom::IntRect const &area = Geom::IntRect::infinite(), UpdateContext const &ctx = UpdateContext(), unsigned flags = DrawingItem::STATE_ALL, unsigned reset = 0);
void render(DrawingContext &dc, Geom::IntRect const &area, unsigned flags = 0);
@@ -100,7 +100,7 @@ private:
OutlineColors _colors;
Filters::FilterColorMatrix::ColorMatrixMatrix _grayscale_colormatrix;
- SPCanvasArena *_canvasarena; // may be NULL is this arena is not the screen
+ SPCanvasArena *_canvasarena; // may be NULL if this arena is not the screen
// but used for export etc.
friend class DrawingItem;
diff --git a/src/display/gnome-canvas-acetate.cpp b/src/display/gnome-canvas-acetate.cpp
index 2cd0f296d..9147a1bbf 100644
--- a/src/display/gnome-canvas-acetate.cpp
+++ b/src/display/gnome-canvas-acetate.cpp
@@ -15,40 +15,17 @@
#include "gnome-canvas-acetate.h"
-static void sp_canvas_acetate_class_init (SPCanvasAcetateClass *klass);
-static void sp_canvas_acetate_init (SPCanvasAcetate *acetate);
static void sp_canvas_acetate_destroy(SPCanvasItem *object);
static void sp_canvas_acetate_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags);
static double sp_canvas_acetate_point (SPCanvasItem *item, Geom::Point p, SPCanvasItem **actual_item);
-static SPCanvasItemClass *parent_class;
-
-GType sp_canvas_acetate_get_type (void)
-{
- static GType acetate_type = 0;
- if (!acetate_type) {
- GTypeInfo acetate_info = {
- sizeof (SPCanvasAcetateClass),
- NULL, NULL,
- (GClassInitFunc) sp_canvas_acetate_class_init,
- NULL, NULL,
- sizeof (SPCanvasAcetate),
- 0,
- (GInstanceInitFunc) sp_canvas_acetate_init,
- NULL
- };
- acetate_type = g_type_register_static(SPCanvasItem::getType(), "SPCanvasAcetate", &acetate_info, GTypeFlags(0));
- }
- return acetate_type;
-}
+G_DEFINE_TYPE(SPCanvasAcetate, sp_canvas_acetate, SP_TYPE_CANVAS_ITEM);
static void sp_canvas_acetate_class_init (SPCanvasAcetateClass *klass)
{
SPCanvasItemClass *item_class = (SPCanvasItemClass *) klass;
- parent_class = (SPCanvasItemClass*)g_type_class_peek_parent (klass);
-
item_class->destroy = sp_canvas_acetate_destroy;
item_class->update = sp_canvas_acetate_update;
item_class->point = sp_canvas_acetate_point;
@@ -64,8 +41,8 @@ static void sp_canvas_acetate_destroy(SPCanvasItem *object)
g_return_if_fail (object != NULL);
g_return_if_fail (GNOME_IS_CANVAS_ACETATE (object));
- if (SP_CANVAS_ITEM_CLASS(parent_class)->destroy)
- (* SP_CANVAS_ITEM_CLASS(parent_class)->destroy) (object);
+ if (SP_CANVAS_ITEM_CLASS(sp_canvas_acetate_parent_class)->destroy)
+ SP_CANVAS_ITEM_CLASS(sp_canvas_acetate_parent_class)->destroy(object);
}
static void sp_canvas_acetate_update( SPCanvasItem *item, Geom::Affine const &/*affine*/, unsigned int /*flags*/ )
diff --git a/src/display/gnome-canvas-acetate.h b/src/display/gnome-canvas-acetate.h
index 447c3a9c4..3e1ba7661 100644
--- a/src/display/gnome-canvas-acetate.h
+++ b/src/display/gnome-canvas-acetate.h
@@ -15,10 +15,8 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include <glib.h>
#include "display/sp-canvas-item.h"
-
#define GNOME_TYPE_CANVAS_ACETATE (sp_canvas_acetate_get_type ())
#define SP_CANVAS_ACETATE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GNOME_TYPE_CANVAS_ACETATE, SPCanvasAcetate))
#define SP_CANVAS_ACETATE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GNOME_TYPE_CANVAS_ACETATE, SPCanvasAcetateClass))
@@ -27,17 +25,15 @@
struct SPCanvasAcetate {
- SPCanvasItem item;
+ SPCanvasItem item;
};
struct SPCanvasAcetateClass {
- SPCanvasItemClass parent_class;
+ SPCanvasItemClass parent_class;
};
GType sp_canvas_acetate_get_type (void);
-
-
#endif // SEEN_SP_CANVAS_ACETATE_H
/*
diff --git a/src/display/grayscale.cpp b/src/display/grayscale.cpp
index f59cf6d23..3c0031e87 100644
--- a/src/display/grayscale.cpp
+++ b/src/display/grayscale.cpp
@@ -36,7 +36,7 @@ guint32 process(guint32 rgba) {
return process(SP_RGBA32_R_U(rgba), SP_RGBA32_G_U(rgba), SP_RGBA32_B_U(rgba), SP_RGBA32_A_U(rgba));
}
-guint32 process(guchar r, guchar g, guchar b, guchar a) {
+guint32 process(unsigned char r, unsigned char g, unsigned char b, unsigned char a) {
/** To reduce banding in gradients, this calculation is tweaked a bit
* by outputing blue+1 or red+1 or both. The luminance is calculated
@@ -62,7 +62,7 @@ guint32 process(guchar r, guchar g, guchar b, guchar a) {
}
}
-guchar luminance(guchar r, guchar g, guchar b) {
+unsigned char luminance(unsigned char r, unsigned char g, unsigned char b) {
guint32 luminance = ( red_factor * r
+ green_factor * g
+ blue_factor * b );
diff --git a/src/display/grayscale.h b/src/display/grayscale.h
index 18162e1f3..0ffe727da 100644
--- a/src/display/grayscale.h
+++ b/src/display/grayscale.h
@@ -10,15 +10,15 @@
* Released under GNU GPL
*/
-#include <gdk/gdk.h>
+typedef unsigned int guint32;
/**
* Provide methods to calculate grayscale values (e.g. convert rgba value to grayscale rgba value).
*/
namespace Grayscale {
guint32 process(guint32 rgba);
- guint32 process(guchar r, guchar g, guchar b, guchar a);
- guchar luminance(guchar r, guchar g, guchar b);
+ guint32 process(unsigned char r, unsigned char g, unsigned char b, unsigned char a);
+ unsigned char luminance(unsigned char r, unsigned char g, unsigned char b);
bool activeDesktopIsGrayscale();
};
diff --git a/src/display/guideline.cpp b/src/display/guideline.cpp
index 55c1ee495..44bbd14bd 100644
--- a/src/display/guideline.cpp
+++ b/src/display/guideline.cpp
@@ -29,8 +29,6 @@
using Inkscape::ControlManager;
-static void sp_guideline_class_init(SPGuideLineClass *c);
-static void sp_guideline_init(SPGuideLine *guideline);
static void sp_guideline_destroy(SPCanvasItem *object);
static void sp_guideline_update(SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags);
@@ -40,34 +38,10 @@ static double sp_guideline_point(SPCanvasItem *item, Geom::Point p, SPCanvasItem
static void sp_guideline_drawline (SPCanvasBuf *buf, gint x0, gint y0, gint x1, gint y1, guint32 rgba);
-static SPCanvasItemClass *parent_class;
-
-GType sp_guideline_get_type()
-{
- static GType guideline_type = 0;
-
- if (!guideline_type) {
- static GTypeInfo const guideline_info = {
- sizeof (SPGuideLineClass),
- NULL, NULL,
- (GClassInitFunc) sp_guideline_class_init,
- NULL, NULL,
- sizeof (SPGuideLine),
- 16,
- (GInstanceInitFunc) sp_guideline_init,
- NULL,
- };
-
- guideline_type = g_type_register_static(SP_TYPE_CANVAS_ITEM, "SPGuideLine", &guideline_info, (GTypeFlags) 0);
- }
-
- return guideline_type;
-}
+G_DEFINE_TYPE(SPGuideLine, sp_guideline, SP_TYPE_CANVAS_ITEM);
static void sp_guideline_class_init(SPGuideLineClass *c)
{
- parent_class = SP_CANVAS_ITEM_CLASS(g_type_class_peek_parent(c));
-
SPCanvasItemClass *item_class = SP_CANVAS_ITEM_CLASS(c);
item_class->destroy = sp_guideline_destroy;
item_class->update = sp_guideline_update;
@@ -108,7 +82,7 @@ static void sp_guideline_destroy(SPCanvasItem *object)
g_free(gl->label);
}
- SP_CANVAS_ITEM_CLASS(parent_class)->destroy(object);
+ SP_CANVAS_ITEM_CLASS(sp_guideline_parent_class)->destroy(object);
}
static void sp_guideline_render(SPCanvasItem *item, SPCanvasBuf *buf)
@@ -197,8 +171,8 @@ static void sp_guideline_update(SPCanvasItem *item, Geom::Affine const &affine,
{
SPGuideLine *gl = SP_GUIDELINE(item);
- if ((SP_CANVAS_ITEM_CLASS(parent_class))->update) {
- (SP_CANVAS_ITEM_CLASS(parent_class))->update(item, affine, flags);
+ if ((SP_CANVAS_ITEM_CLASS(sp_guideline_parent_class))->update) {
+ (SP_CANVAS_ITEM_CLASS(sp_guideline_parent_class))->update(item, affine, flags);
}
gl->affine = affine;
diff --git a/src/display/nr-3dutils.h b/src/display/nr-3dutils.h
index c278c81c6..eb773a9ad 100644
--- a/src/display/nr-3dutils.h
+++ b/src/display/nr-3dutils.h
@@ -1,5 +1,5 @@
-#ifndef __NR_3DUTILS_H__
-#define __NR_3DUTILS_H__
+#ifndef SEEN_NR_3DUTILS_H
+#define SEEN_NR_3DUTILS_H
/*
* 3D utils. Definition of gdouble vectors of dimension 3 and of some basic
@@ -14,7 +14,6 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include <gdk/gdk.h>
#include <2geom/forward.h>
namespace NR {
@@ -51,7 +50,7 @@ const static Fvector EYE_VECTOR(0, 0, 1);
* \param v a reference to a vector with double components
* \return the euclidian norm of v
*/
-gdouble norm(const Fvector &v);
+double norm(const Fvector &v);
/**
* Normalizes a vector
@@ -67,7 +66,7 @@ void normalize_vector(Fvector &v);
* \param b a Fvector reference
* \return the scalar product of a and b
*/
-gdouble scalar_product(const Fvector &a, const Fvector &b);
+double scalar_product(const Fvector &a, const Fvector &b);
/**
* Computes the normalized sum of two Fvectors
@@ -88,7 +87,7 @@ void normalized_sum(Fvector &r, const Fvector &a, const Fvector &b);
* \param z a reference to a z coordinate
* \param z a reference to a transformation matrix
*/
-void convert_coord(gdouble &x, gdouble &y, gdouble &z, Geom::Affine const &trans);
+void convert_coord(double &x, double &y, double &z, Geom::Affine const &trans);
} /* namespace NR */
diff --git a/src/display/nr-filter-blend.cpp b/src/display/nr-filter-blend.cpp
index 099816bce..d0db6b42e 100644
--- a/src/display/nr-filter-blend.cpp
+++ b/src/display/nr-filter-blend.cpp
@@ -20,6 +20,7 @@
#include "config.h"
#endif
+#include <glibmm.h>
#include "display/cairo-templates.h"
#include "display/cairo-utils.h"
#include "display/nr-filter-blend.h"
@@ -83,8 +84,7 @@ void FilterBlend::render_cairo(FilterSlot &slot)
case BLEND_LIGHTEN:
cairo_set_operator(out_ct, CAIRO_OPERATOR_LIGHTEN);
break;
-#ifdef WITH_CSSBLEND
- // NEW
+ // New in CSS Compositing and Blending Level 1
case BLEND_OVERLAY:
cairo_set_operator(out_ct, CAIRO_OPERATOR_OVERLAY);
break;
@@ -118,7 +118,6 @@ void FilterBlend::render_cairo(FilterSlot &slot)
case BLEND_LUMINOSITY:
cairo_set_operator(out_ct, CAIRO_OPERATOR_HSL_LUMINOSITY);
break;
-#endif
case BLEND_NORMAL:
default:
@@ -167,15 +166,12 @@ void FilterBlend::set_input(int input, int slot) {
void FilterBlend::set_mode(FilterBlendMode mode) {
if (mode == BLEND_NORMAL || mode == BLEND_MULTIPLY ||
mode == BLEND_SCREEN || mode == BLEND_DARKEN ||
- mode == BLEND_LIGHTEN
-#ifdef WITH_CSSBLEND
- || mode == BLEND_OVERLAY ||
+ mode == BLEND_LIGHTEN || mode == BLEND_OVERLAY ||
mode == BLEND_COLORDODGE || mode == BLEND_COLORBURN ||
mode == BLEND_HARDLIGHT || mode == BLEND_SOFTLIGHT ||
mode == BLEND_DIFFERENCE || mode == BLEND_EXCLUSION ||
mode == BLEND_HUE || mode == BLEND_SATURATION ||
mode == BLEND_COLOR || mode == BLEND_LUMINOSITY
-#endif
)
{
_blend_mode = mode;
diff --git a/src/display/nr-filter-blend.h b/src/display/nr-filter-blend.h
index 0a2927d87..30c9d6725 100644
--- a/src/display/nr-filter-blend.h
+++ b/src/display/nr-filter-blend.h
@@ -1,5 +1,5 @@
-#ifndef __NR_FILTER_BLEND_H__
-#define __NR_FILTER_BLEND_H__
+#ifndef SEEN_NR_FILTER_BLEND_H
+#define SEEN_NR_FILTER_BLEND_H
/*
* SVG feBlend renderer
@@ -28,7 +28,6 @@ enum FilterBlendMode {
BLEND_SCREEN,
BLEND_DARKEN,
BLEND_LIGHTEN,
-#ifdef WITH_CSSBLEND
// New in CSS Compositing and Blending Level 1
BLEND_OVERLAY,
BLEND_COLORDODGE,
@@ -41,7 +40,6 @@ enum FilterBlendMode {
BLEND_SATURATION,
BLEND_COLOR,
BLEND_LUMINOSITY,
-#endif
BLEND_ENDMODE,
};
diff --git a/src/display/nr-filter-colormatrix.h b/src/display/nr-filter-colormatrix.h
index c7e5e91d9..cc43f4914 100644
--- a/src/display/nr-filter-colormatrix.h
+++ b/src/display/nr-filter-colormatrix.h
@@ -1,5 +1,5 @@
-#ifndef __NR_FILTER_COLOR_MATRIX_H__
-#define __NR_FILTER_COLOR_MATRIX_H__
+#ifndef SEEN_NR_FILTER_COLOR_MATRIX_H
+#define SEEN_NR_FILTER_COLOR_MATRIX_H
/*
* feColorMatrix filter primitive renderer
@@ -16,6 +16,9 @@
#include <2geom/forward.h>
#include "display/nr-filter-primitive.h"
+typedef unsigned int guint32;
+typedef signed int gint32;
+
namespace Inkscape {
namespace Filters {
@@ -40,8 +43,8 @@ public:
virtual double complexity(Geom::Affine const &ctm);
virtual void set_type(FilterColorMatrixType type);
- virtual void set_value(gdouble value);
- virtual void set_values(std::vector<gdouble> const &values);
+ virtual void set_value(double value);
+ virtual void set_values(std::vector<double> const &values);
public:
struct ColorMatrixMatrix {
@@ -52,8 +55,8 @@ public:
};
private:
- std::vector<gdouble> values;
- gdouble value;
+ std::vector<double> values;
+ double value;
FilterColorMatrixType type;
};
diff --git a/src/display/nr-filter-component-transfer.h b/src/display/nr-filter-component-transfer.h
index 558d097a8..7019dde37 100644
--- a/src/display/nr-filter-component-transfer.h
+++ b/src/display/nr-filter-component-transfer.h
@@ -1,5 +1,5 @@
-#ifndef __NR_FILTER_COMPONENT_TRANSFER_H__
-#define __NR_FILTER_COMPONENT_TRANSFER_H__
+#ifndef SEEN_NR_FILTER_COMPONENT_TRANSFER_H
+#define SEEN_NR_FILTER_COMPONENT_TRANSFER_H
/*
* feComponentTransfer filter primitive renderer
@@ -40,7 +40,7 @@ public:
virtual double complexity(Geom::Affine const &ctm);
FilterComponentTransferType type[4];
- std::vector<gdouble> tableValues[4];
+ std::vector<double> tableValues[4];
double slope[4];
double intercept[4];
double amplitude[4];
diff --git a/src/display/nr-filter-composite.h b/src/display/nr-filter-composite.h
index 95579cc0e..35756383b 100644
--- a/src/display/nr-filter-composite.h
+++ b/src/display/nr-filter-composite.h
@@ -1,5 +1,5 @@
-#ifndef __NR_FILTER_COMPOSITE_H__
-#define __NR_FILTER_COMPOSITE_H__
+#ifndef SEEN_NR_FILTER_COMPOSITE_H
+#define SEEN_NR_FILTER_COMPOSITE_H
/*
* feComposite filter effect renderer
diff --git a/src/display/nr-filter-convolve-matrix.h b/src/display/nr-filter-convolve-matrix.h
index 4041ff96f..d2e38eb95 100644
--- a/src/display/nr-filter-convolve-matrix.h
+++ b/src/display/nr-filter-convolve-matrix.h
@@ -1,5 +1,5 @@
-#ifndef __NR_FILTER_CONVOLVE_MATRIX_H__
-#define __NR_FILTER_CONVOLVE_MATRIX_H__
+#ifndef SEEN_NR_FILTER_CONVOLVE_MATRIX_H
+#define SEEN_NR_FILTER_CONVOLVE_MATRIX_H
/*
* feConvolveMatrix filter primitive renderer
@@ -48,10 +48,10 @@ public:
void set_preserveAlpha(bool pa);
private:
- std::vector<gdouble> kernelMatrix;
+ std::vector<double> kernelMatrix;
int targetX, targetY;
int orderX, orderY;
- gdouble divisor, bias;
+ double divisor, bias;
int dx, dy, kernelUnitLength;
FilterConvolveMatrixEdgeMode edgeMode;
bool preserveAlpha;
diff --git a/src/display/nr-filter-diffuselighting.h b/src/display/nr-filter-diffuselighting.h
index 043a5eb39..7739b3ea6 100644
--- a/src/display/nr-filter-diffuselighting.h
+++ b/src/display/nr-filter-diffuselighting.h
@@ -1,5 +1,5 @@
-#ifndef __NR_FILTER_DIFFUSELIGHTING_H__
-#define __NR_FILTER_DIFFUSELIGHTING_H__
+#ifndef SEEN_NR_FILTER_DIFFUSELIGHTING_H
+#define SEEN_NR_FILTER_DIFFUSELIGHTING_H
/*
* feDiffuseLighting renderer
@@ -13,7 +13,6 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include <gdk/gdk.h>
#include "display/nr-light-types.h"
#include "display/nr-filter-primitive.h"
#include "display/nr-filter-slot.h"
@@ -23,6 +22,7 @@ class SPFeDistantLight;
class SPFePointLight;
class SPFeSpotLight;
struct SVGICCColor;
+typedef unsigned int guint32;
namespace Inkscape {
namespace Filters {
@@ -43,8 +43,8 @@ public:
SPFeSpotLight *spot;
} light;
LightType light_type;
- gdouble diffuseConstant;
- gdouble surfaceScale;
+ double diffuseConstant;
+ double surfaceScale;
guint32 lighting_color;
private:
diff --git a/src/display/nr-filter-displacement-map.h b/src/display/nr-filter-displacement-map.h
index a01930045..c4e2400fe 100644
--- a/src/display/nr-filter-displacement-map.h
+++ b/src/display/nr-filter-displacement-map.h
@@ -1,5 +1,5 @@
-#ifndef __NR_FILTER_DISPLACEMENT_MAP_H__
-#define __NR_FILTER_DISPLACEMENT_MAP_H__
+#ifndef SEEN_NR_FILTER_DISPLACEMENT_MAP_H
+#define SEEN_NR_FILTER_DISPLACEMENT_MAP_H
/*
* feDisplacementMap filter primitive renderer
diff --git a/src/display/nr-filter-flood.h b/src/display/nr-filter-flood.h
index 9a968047d..826aa981a 100644
--- a/src/display/nr-filter-flood.h
+++ b/src/display/nr-filter-flood.h
@@ -1,5 +1,5 @@
-#ifndef __NR_FILTER_FLOOD_H__
-#define __NR_FILTER_FLOOD_H__
+#ifndef SEEN_NR_FILTER_FLOOD_H
+#define SEEN_NR_FILTER_FLOOD_H
/*
* feFlood filter primitive renderer
@@ -15,6 +15,7 @@
#include "display/nr-filter-primitive.h"
struct SVGICCColor;
+typedef unsigned int guint32;
namespace Inkscape {
namespace Filters {
diff --git a/src/display/nr-filter-gaussian.h b/src/display/nr-filter-gaussian.h
index 1c35a0f1d..88c38247f 100644
--- a/src/display/nr-filter-gaussian.h
+++ b/src/display/nr-filter-gaussian.h
@@ -1,5 +1,5 @@
-#ifndef __NR_FILTER_GAUSSIAN_H__
-#define __NR_FILTER_GAUSSIAN_H__
+#ifndef SEEN_NR_FILTER_GAUSSIAN_H
+#define SEEN_NR_FILTER_GAUSSIAN_H
/*
* Gaussian blur renderer
diff --git a/src/display/nr-filter-image.h b/src/display/nr-filter-image.h
index 69691ac99..147a8ba6c 100644
--- a/src/display/nr-filter-image.h
+++ b/src/display/nr-filter-image.h
@@ -1,5 +1,5 @@
-#ifndef __NR_FILTER_IMAGE_H__
-#define __NR_FILTER_IMAGE_H__
+#ifndef SEEN_NR_FILTER_IMAGE_H
+#define SEEN_NR_FILTER_IMAGE_H
/*
* feImage filter primitive renderer
@@ -34,7 +34,7 @@ public:
virtual double complexity(Geom::Affine const &ctm);
void set_document( SPDocument *document );
- void set_href(const gchar *href);
+ void set_href(char const *href);
void set_align( unsigned int align );
void set_clip( unsigned int clip );
bool from_element;
@@ -42,7 +42,7 @@ public:
private:
SPDocument *document;
- gchar *feImageHref;
+ char *feImageHref;
Inkscape::Pixbuf *image;
float feImageX, feImageY, feImageWidth, feImageHeight;
unsigned int aspect_align, aspect_clip;
diff --git a/src/display/nr-filter-merge.h b/src/display/nr-filter-merge.h
index 238f9a3e7..b20d663ab 100644
--- a/src/display/nr-filter-merge.h
+++ b/src/display/nr-filter-merge.h
@@ -1,5 +1,5 @@
-#ifndef __NR_FILTER_MERGE_H__
-#define __NR_FILTER_MERGE_H__
+#ifndef SEEN_NR_FILTER_MERGE_H
+#define SEEN_NR_FILTER_MERGE_H
/*
* feMerge filter effect renderer
diff --git a/src/display/nr-filter-morphology.h b/src/display/nr-filter-morphology.h
index 0574ff4ad..cd7dfe775 100644
--- a/src/display/nr-filter-morphology.h
+++ b/src/display/nr-filter-morphology.h
@@ -1,5 +1,5 @@
-#ifndef __NR_FILTER_MORPHOLOGY_H__
-#define __NR_FILTER_MORPHOLOGY_H__
+#ifndef SEEN_NR_FILTER_MORPHOLOGY_H
+#define SEEN_NR_FILTER_MORPHOLOGY_H
/*
* feMorphology filter primitive renderer
diff --git a/src/display/nr-filter-offset.h b/src/display/nr-filter-offset.h
index 1ecc1621e..c1ee1d82a 100644
--- a/src/display/nr-filter-offset.h
+++ b/src/display/nr-filter-offset.h
@@ -1,5 +1,5 @@
-#ifndef __NR_FILTER_OFFSET_H__
-#define __NR_FILTER_OFFSET_H__
+#ifndef SEEN_NR_FILTER_OFFSET_H
+#define SEEN_NR_FILTER_OFFSET_H
/*
* feOffset filter primitive renderer
diff --git a/src/display/nr-filter-primitive.h b/src/display/nr-filter-primitive.h
index 94bd6abb0..4b7577159 100644
--- a/src/display/nr-filter-primitive.h
+++ b/src/display/nr-filter-primitive.h
@@ -13,10 +13,11 @@
#include <2geom/forward.h>
#include <2geom/rect.h>
+
#include "display/nr-filter-types.h"
#include "svg/svg-length.h"
-struct SPStyle;
+class SPStyle;
namespace Inkscape {
namespace Filters {
@@ -30,7 +31,7 @@ public:
virtual ~FilterPrimitive();
virtual void render_cairo(FilterSlot &slot);
- virtual int render(FilterSlot & /*slot*/, FilterUnits const & /*units*/) { return 0; }
+ virtual int render(FilterSlot & /*slot*/, FilterUnits const & /*units*/) { return 0; } // pure virtual?
virtual void area_enlarge(Geom::IntRect &area, Geom::Affine const &m);
/**
diff --git a/src/display/nr-filter-skeleton.h b/src/display/nr-filter-skeleton.h
index 049c0df80..e17c244c1 100644
--- a/src/display/nr-filter-skeleton.h
+++ b/src/display/nr-filter-skeleton.h
@@ -1,5 +1,5 @@
-#ifndef __NR_FILTER_SKELETON_H__
-#define __NR_FILTER_SKELETON_H__
+#ifndef SEEN_NR_FILTER_SKELETON_H
+#define SEEN_NR_FILTER_SKELETON_H
/*
* Filter primitive renderer skeleton class
diff --git a/src/display/nr-filter-slot.h b/src/display/nr-filter-slot.h
index f3c98b8d9..987dedfd1 100644
--- a/src/display/nr-filter-slot.h
+++ b/src/display/nr-filter-slot.h
@@ -1,5 +1,5 @@
-#ifndef __NR_FILTER_SLOT_H__
-#define __NR_FILTER_SLOT_H__
+#ifndef SEEN_NR_FILTER_SLOT_H
+#define SEEN_NR_FILTER_SLOT_H
/*
* A container class for filter slots. Allows for simple getting and
@@ -15,10 +15,14 @@
*/
#include <map>
-#include <cairo.h>
#include "display/nr-filter-types.h"
#include "display/nr-filter-units.h"
+extern "C" {
+typedef struct _cairo cairo_t;
+typedef struct _cairo_surface cairo_surface_t;
+}
+
namespace Inkscape {
class DrawingContext;
class DrawingItem;
diff --git a/src/display/nr-filter-specularlighting.h b/src/display/nr-filter-specularlighting.h
index c57e3a9ff..ff9cda450 100644
--- a/src/display/nr-filter-specularlighting.h
+++ b/src/display/nr-filter-specularlighting.h
@@ -1,5 +1,5 @@
-#ifndef __NR_FILTER_SPECULARLIGHTING_H__
-#define __NR_FILTER_SPECULARLIGHTING_H__
+#ifndef SEEN_NR_FILTER_SPECULARLIGHTING_H
+#define SEEN_NR_FILTER_SPECULARLIGHTING_H
/*
* feSpecularLighting renderer
@@ -13,7 +13,6 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include <gdk/gdk.h>
#include "display/nr-light-types.h"
#include "display/nr-filter-primitive.h"
@@ -21,6 +20,7 @@ class SPFeDistantLight;
class SPFePointLight;
class SPFeSpotLight;
struct SVGICCColor;
+typedef unsigned int guint32;
namespace Inkscape {
namespace Filters {
@@ -44,9 +44,9 @@ public:
SPFeSpotLight *spot;
} light;
LightType light_type;
- gdouble surfaceScale;
- gdouble specularConstant;
- gdouble specularExponent;
+ double surfaceScale;
+ double specularConstant;
+ double specularExponent;
guint32 lighting_color;
private:
diff --git a/src/display/nr-filter-tile.h b/src/display/nr-filter-tile.h
index dc5b99a42..29087f2d6 100644
--- a/src/display/nr-filter-tile.h
+++ b/src/display/nr-filter-tile.h
@@ -1,5 +1,5 @@
-#ifndef __NR_FILTER_TILE_H__
-#define __NR_FILTER_TILE_H__
+#ifndef SEEN_NR_FILTER_TILE_H
+#define SEEN_NR_FILTER_TILE_H
/*
* feTile filter primitive renderer
diff --git a/src/display/nr-filter-turbulence.h b/src/display/nr-filter-turbulence.h
index 360853364..ee8079133 100644
--- a/src/display/nr-filter-turbulence.h
+++ b/src/display/nr-filter-turbulence.h
@@ -1,5 +1,5 @@
-#ifndef __NR_FILTER_TURBULENCE_H__
-#define __NR_FILTER_TURBULENCE_H__
+#ifndef SEEN_NR_FILTER_TURBULENCE_H
+#define SEEN_NR_FILTER_TURBULENCE_H
/*
* feTurbulence filter primitive renderer
@@ -22,6 +22,7 @@
*/
#include <2geom/point.h>
+
#include "display/nr-filter-primitive.h"
#include "display/nr-filter-slot.h"
#include "display/nr-filter-units.h"
diff --git a/src/display/nr-filter-types.h b/src/display/nr-filter-types.h
index 502bfe348..2e35d6da8 100644
--- a/src/display/nr-filter-types.h
+++ b/src/display/nr-filter-types.h
@@ -1,5 +1,5 @@
-#ifndef __NR_FILTER_TYPES_H__
-#define __NR_FILTER_TYPES_H__
+#ifndef SEEN_NR_FILTER_TYPES_H
+#define SEEN_NR_FILTER_TYPES_H
namespace Inkscape {
namespace Filters {
diff --git a/src/display/nr-filter-units.h b/src/display/nr-filter-units.h
index f918cf12e..0ee6c3707 100644
--- a/src/display/nr-filter-units.h
+++ b/src/display/nr-filter-units.h
@@ -1,5 +1,5 @@
-#ifndef __NR_FILTER_UNITS_H__
-#define __NR_FILTER_UNITS_H__
+#ifndef SEEN_NR_FILTER_UNITS_H
+#define SEEN_NR_FILTER_UNITS_H
/*
* Utilities for handling coordinate system transformations in filters
diff --git a/src/display/nr-filter-utils.h b/src/display/nr-filter-utils.h
index 7e073168f..35a74d7c1 100644
--- a/src/display/nr-filter-utils.h
+++ b/src/display/nr-filter-utils.h
@@ -1,5 +1,5 @@
-#ifndef __NR_FILTER_UTILS_H__
-#define __NR_FILTER_UTILS_H__
+#ifndef SEEN_NR_FILTER_UTILS_H
+#define SEEN_NR_FILTER_UTILS_H
/**
* @file
@@ -26,7 +26,6 @@ namespace Filters {
* \return 0 if the value is smaller than 0, 255 if it is greater 255, else v
* \param v the value to clamp
*/
-__attribute__ ((const))
inline int clamp(int const val) {
if (val < 0) return 0;
if (val > 255) return 255;
@@ -39,7 +38,6 @@ inline int clamp(int const val) {
* \return 0 if the value is smaller than 0, 255^3 (16581375) if it is greater than 255^3, else v
* \param v the value to clamp
*/
-__attribute__ ((const))
inline int clamp3(int const val) {
if (val < 0) return 0;
if (val > 16581375) return 16581375;
@@ -59,7 +57,6 @@ inline int clamp3(int const val) {
* \param val the value to clamp
* \param alpha the maximum value to clamp to
*/
-__attribute__ ((const))
inline int clamp_alpha(int const val, int const alpha) {
if (val < 0) return 0;
if (val > alpha) return alpha;
diff --git a/src/display/nr-filter.cpp b/src/display/nr-filter.cpp
index 90b233fbc..dec5b1f57 100644
--- a/src/display/nr-filter.cpp
+++ b/src/display/nr-filter.cpp
@@ -9,7 +9,6 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include "display/nr-filter-image.h"
#include <glib.h>
#include <cmath>
#include <cstring>
@@ -29,6 +28,7 @@
#include "display/nr-filter-component-transfer.h"
#include "display/nr-filter-diffuselighting.h"
#include "display/nr-filter-displacement-map.h"
+#include "display/nr-filter-image.h"
#include "display/nr-filter-flood.h"
#include "display/nr-filter-gaussian.h"
#include "display/nr-filter-merge.h"
diff --git a/src/display/nr-filter.h b/src/display/nr-filter.h
index f9dcf1d84..9a30efabd 100644
--- a/src/display/nr-filter.h
+++ b/src/display/nr-filter.h
@@ -1,5 +1,5 @@
-#ifndef __NR_FILTER_H__
-#define __NR_FILTER_H__
+#ifndef SEEN_NR_FILTER_H
+#define SEEN_NR_FILTER_H
/*
* SVG filters rendering
diff --git a/src/display/nr-light-types.h b/src/display/nr-light-types.h
index 5c9acb324..8cc92db77 100644
--- a/src/display/nr-light-types.h
+++ b/src/display/nr-light-types.h
@@ -1,5 +1,5 @@
-#ifndef __NR_LIGHT_TYPES_H__
-#define __NR_LIGHT_TYPES_H__
+#ifndef SEEN_NR_LIGHT_TYPES_H
+#define SEEN_NR_LIGHT_TYPES_H
namespace Inkscape {
namespace Filters {
diff --git a/src/display/nr-light.cpp b/src/display/nr-light.cpp
index 6331d1546..0e9a55a9f 100644
--- a/src/display/nr-light.cpp
+++ b/src/display/nr-light.cpp
@@ -51,7 +51,7 @@ PointLight::PointLight(SPFePointLight *light, guint32 lighting_color, const Geom
PointLight::~PointLight() {}
-void PointLight::light_vector(NR::Fvector &v, gdouble x, gdouble y, gdouble z) {
+void PointLight::light_vector(NR::Fvector &v, double x, double y, double z) {
v[X_3D] = l_x - x;
v[Y_3D] = l_y - y;
v[Z_3D] = l_z - z;
@@ -65,7 +65,7 @@ void PointLight::light_components(NR::Fvector &lc) {
}
SpotLight::SpotLight(SPFeSpotLight *light, guint32 lighting_color, const Geom::Affine &trans) {
- gdouble p_x, p_y, p_z;
+ double p_x, p_y, p_z;
color = lighting_color;
l_x = light->x;
l_y = light->y;
@@ -86,7 +86,7 @@ SpotLight::SpotLight(SPFeSpotLight *light, guint32 lighting_color, const Geom::A
SpotLight::~SpotLight() {}
-void SpotLight::light_vector(NR::Fvector &v, gdouble x, gdouble y, gdouble z) {
+void SpotLight::light_vector(NR::Fvector &v, double x, double y, double z) {
v[X_3D] = l_x - x;
v[Y_3D] = l_y - y;
v[Z_3D] = l_z - z;
@@ -94,7 +94,7 @@ void SpotLight::light_vector(NR::Fvector &v, gdouble x, gdouble y, gdouble z) {
}
void SpotLight::light_components(NR::Fvector &lc, const NR::Fvector &L) {
- gdouble spmod = (-1) * NR::scalar_product(L, S);
+ double spmod = (-1) * NR::scalar_product(L, S);
if (spmod <= cos_lca)
spmod = 0;
else
diff --git a/src/display/nr-light.h b/src/display/nr-light.h
index 0c1235483..94b573761 100644
--- a/src/display/nr-light.h
+++ b/src/display/nr-light.h
@@ -1,5 +1,6 @@
-#ifndef __NR_LIGHT_H__
-#define __NR_LIGHT_H__
+#ifndef SEEN_NR_LIGHT_H
+#define SEEN_NR_LIGHT_H
+
/** \file
* These classes provide tools to compute interesting objects relative to light
* sources. Each class provides a constructor converting information contained
@@ -8,14 +9,15 @@
* light color components (at a given point).
*/
-#include <gdk/gdk.h>
+#include <2geom/forward.h>
+
#include "display/nr-3dutils.h"
#include "display/nr-light-types.h"
-#include <2geom/forward.h>
class SPFeDistantLight;
class SPFePointLight;
class SPFeSpotLight;
+typedef unsigned int guint32;
namespace Inkscape {
namespace Filters {
@@ -53,8 +55,8 @@ class DistantLight {
private:
guint32 color;
- gdouble azimuth; //azimuth in rad
- gdouble elevation; //elevation in rad
+ double azimuth; //azimuth in rad
+ double elevation; //elevation in rad
};
class PointLight {
@@ -80,7 +82,7 @@ class PointLight {
* \param y y coordinate of the current point
* \param z z coordinate of the current point
*/
- void light_vector(NR::Fvector &v, gdouble x, gdouble y, gdouble z);
+ void light_vector(NR::Fvector &v, double x, double y, double z);
/**
* Computes the light components of the distant light
@@ -92,9 +94,9 @@ class PointLight {
private:
guint32 color;
//light position coordinates in render setting
- gdouble l_x;
- gdouble l_y;
- gdouble l_z;
+ double l_x;
+ double l_y;
+ double l_z;
};
class SpotLight {
@@ -121,7 +123,7 @@ class SpotLight {
* \param y y coordinate of the current point
* \param z z coordinate of the current point
*/
- void light_vector(NR::Fvector &v, gdouble x, gdouble y, gdouble z);
+ void light_vector(NR::Fvector &v, double x, double y, double z);
/**
* Computes the light components of the distant light at the current
@@ -135,11 +137,11 @@ class SpotLight {
private:
guint32 color;
//light position coordinates in render setting
- gdouble l_x;
- gdouble l_y;
- gdouble l_z;
- gdouble cos_lca; //cos of the limiting cone angle
- gdouble speExp; //specular exponent;
+ double l_x;
+ double l_y;
+ double l_z;
+ double cos_lca; //cos of the limiting cone angle
+ double speExp; //specular exponent;
NR::Fvector S; //unit vector from light position in the direction
//the spot point at
};
diff --git a/src/display/nr-style.cpp b/src/display/nr-style.cpp
index 125d0c6d6..96d16bf06 100644
--- a/src/display/nr-style.cpp
+++ b/src/display/nr-style.cpp
@@ -14,6 +14,7 @@
#include "sp-paint-server.h"
#include "display/canvas-bpath.h" // contains SPStrokeJoinType, SPStrokeCapType etc. (WTF!)
#include "display/drawing-context.h"
+#include "display/drawing-pattern.h"
void NRStyle::Paint::clear()
{
@@ -54,8 +55,13 @@ NRStyle::NRStyle()
, line_join(CAIRO_LINE_JOIN_MITER)
, fill_pattern(NULL)
, stroke_pattern(NULL)
+ , text_decoration_fill_pattern(NULL)
+ , text_decoration_stroke_pattern(NULL)
, text_decoration_line(TEXT_DECORATION_LINE_CLEAR)
, text_decoration_style(TEXT_DECORATION_STYLE_CLEAR)
+ , text_decoration_fill()
+ , text_decoration_stroke()
+ , text_decoration_stroke_width(0.0)
, phase_length(0.0)
, tspan_line_start(false)
, tspan_line_end(false)
@@ -69,26 +75,35 @@ NRStyle::NRStyle()
, line_through_position(0)
, font_size(0)
{
-#ifdef WITH_SVG2
paint_order_layer[0] = PAINT_ORDER_NORMAL;
-#endif
}
NRStyle::~NRStyle()
{
if (fill_pattern) cairo_pattern_destroy(fill_pattern);
if (stroke_pattern) cairo_pattern_destroy(stroke_pattern);
+ if (text_decoration_fill_pattern) cairo_pattern_destroy(text_decoration_fill_pattern);
+ if (text_decoration_stroke_pattern) cairo_pattern_destroy(text_decoration_stroke_pattern);
if (dash){
delete [] dash;
}
fill.clear();
stroke.clear();
+ text_decoration_fill.clear();
+ text_decoration_stroke.clear();
}
void NRStyle::set(SPStyle *style)
{
if ( style->fill.isPaintserver() ) {
- fill.set(style->getFillPaintServer());
+ SPPaintServer* server = style->getFillPaintServer();
+ if ( server && server->isValid() ) {
+ fill.set(server);
+ } else if ( style->fill.colorSet ) {
+ fill.set(style->fill.value.color);
+ } else {
+ fill.clear();
+ }
} else if ( style->fill.isColor() ) {
fill.set(style->fill.value.color);
} else if ( style->fill.isNone() ) {
@@ -110,7 +125,14 @@ void NRStyle::set(SPStyle *style)
}
if ( style->stroke.isPaintserver() ) {
- stroke.set(style->getStrokePaintServer());
+ SPPaintServer* server = style->getStrokePaintServer();
+ if ( server && server->isValid() ) {
+ stroke.set(server);
+ } else if ( style->stroke.isColor() ) {
+ stroke.set(style->stroke.colorSet);
+ } else {
+ stroke.clear();
+ }
} else if ( style->stroke.isColor() ) {
stroke.set(style->stroke.value.color);
} else if ( style->stroke.isNone() ) {
@@ -165,7 +187,6 @@ void NRStyle::set(SPStyle *style)
}
-#ifdef WITH_SVG2
for( unsigned i = 0; i < PAINT_ORDER_LAYERS; ++i) {
switch (style->paint_order.layer[i]) {
case SP_CSS_PAINT_ORDER_NORMAL:
@@ -182,7 +203,6 @@ void NRStyle::set(SPStyle *style)
break;
}
}
-#endif
text_decoration_line = TEXT_DECORATION_LINE_CLEAR;
if(style->text_decoration_line.inherit ){ text_decoration_line |= TEXT_DECORATION_LINE_INHERIT; }
@@ -199,16 +219,65 @@ void NRStyle::set(SPStyle *style)
if(style->text_decoration_style.dashed ){ text_decoration_style |= TEXT_DECORATION_STYLE_DASHED + TEXT_DECORATION_STYLE_SET; }
if(style->text_decoration_style.wavy ){ text_decoration_style |= TEXT_DECORATION_STYLE_WAVY + TEXT_DECORATION_STYLE_SET; }
+ /* FIXME
+ The meaning of text-decoration-color in CSS3 for SVG is ambiguous (2014-05-06). Set
+ it for fill, for stroke, for both? Both would seem like the obvious choice but what happens
+ is that for text which is just fill (very common) it makes the lines fatter because it
+ enables stroke on the decorations when it wasn't present on the text. That contradicts the
+ usual behavior where the text and decorations by default have the same fill/stroke.
+
+ The behavior here is that if color is defined it is applied to text_decoration_fill/stroke
+ ONLY if the corresponding fill/stroke is also present.
+
+ Hopefully the standard will be clarified to resolve this issue.
+ */
+
+ SPStyle* style_td = style;
+ if ( style->text_decoration.style_td ) style_td = style->text_decoration.style_td;
+ text_decoration_stroke.opacity = SP_SCALE24_TO_FLOAT(style_td->stroke_opacity.value);
+ text_decoration_stroke_width = style_td->stroke_width.computed;
+
if( style->text_decoration_color.set ||
style->text_decoration_color.inherit ||
- style->text_decoration_color.currentcolor ||
- style->text_decoration_color.colorSet){
- text_decoration_color.set(style->text_decoration_color.value.color);
- text_decoration_useColor = true;
- }
- else {
- text_decoration_color.clear();
- text_decoration_useColor = false;
+ style->text_decoration_color.currentcolor ) {
+
+ if(style->fill.isPaintserver() || style->fill.isColor()) {
+ // SVG sets color specifically
+ text_decoration_fill.set(style->text_decoration_color.value.color);
+ } else {
+ // No decoration fill because no text fill
+ text_decoration_fill.clear();
+ }
+
+ if(style->stroke.isPaintserver() || style->stroke.isColor()) {
+ // SVG sets color specifically
+ text_decoration_stroke.set(style->text_decoration_color.value.color);
+ } else {
+ // No decoration stroke because no text stroke
+ text_decoration_stroke.clear();
+ }
+
+ } else {
+ // Pick color/pattern from text
+ if ( style_td->fill.isPaintserver() ) {
+ text_decoration_fill.set(style_td->getFillPaintServer());
+ } else if ( style_td->fill.isColor() ) {
+ text_decoration_fill.set(style_td->fill.value.color);
+ } else if ( style_td->fill.isNone() ) {
+ text_decoration_fill.clear();
+ } else {
+ g_assert_not_reached();
+ }
+
+ if ( style_td->stroke.isPaintserver() ) {
+ text_decoration_stroke.set(style_td->getStrokePaintServer());
+ } else if ( style_td->stroke.isColor() ) {
+ text_decoration_stroke.set(style_td->stroke.value.color);
+ } else if ( style_td->stroke.isNone() ) {
+ text_decoration_stroke.clear();
+ } else {
+ g_assert_not_reached();
+ }
}
if(text_decoration_line != TEXT_DECORATION_LINE_CLEAR){
@@ -231,16 +300,17 @@ void NRStyle::set(SPStyle *style)
update();
}
-bool NRStyle::prepareFill(Inkscape::DrawingContext &dc, Geom::OptRect const &paintbox)
+bool NRStyle::prepareFill(Inkscape::DrawingContext &dc, Geom::OptRect const &paintbox, Inkscape::DrawingPattern *pattern)
{
// update fill pattern
if (!fill_pattern) {
switch (fill.type) {
- case PAINT_SERVER: {
- //fill_pattern = sp_paint_server_create_pattern(fill.server, dc.raw(), paintbox, fill.opacity);
- fill_pattern = fill.server->pattern_new(dc.raw(), paintbox, fill.opacity);
-
- } break;
+ case PAINT_SERVER:
+ if (pattern) {
+ fill_pattern = pattern->renderPattern(fill.opacity);
+ } else {
+ fill_pattern = fill.server->pattern_new(dc.raw(), paintbox, fill.opacity);
+ } break;
case PAINT_COLOR: {
SPColor const &c = fill.color;
fill_pattern = cairo_pattern_create_rgba(
@@ -259,21 +329,57 @@ void NRStyle::applyFill(Inkscape::DrawingContext &dc)
dc.setFillRule(fill_rule);
}
-bool NRStyle::prepareStroke(Inkscape::DrawingContext &dc, Geom::OptRect const &paintbox)
+bool NRStyle::prepareTextDecorationFill(Inkscape::DrawingContext &dc, Geom::OptRect const &paintbox, Inkscape::DrawingPattern *pattern)
+{
+ // update text decoration pattern
+ if (!text_decoration_fill_pattern) {
+ switch (text_decoration_fill.type) {
+ case PAINT_SERVER:
+ if (pattern) {
+ text_decoration_fill_pattern = pattern->renderPattern(
+ text_decoration_fill.opacity);
+ } else {
+ text_decoration_fill_pattern = text_decoration_fill.server->pattern_new(dc.raw(),
+ paintbox, text_decoration_fill.opacity);
+ }
+ break;
+ case PAINT_COLOR: {
+ SPColor const &c = text_decoration_fill.color;
+ text_decoration_fill_pattern = cairo_pattern_create_rgba(
+ c.v.c[0], c.v.c[1], c.v.c[2], text_decoration_fill.opacity);
+ } break;
+ default: break;
+ }
+ }
+ if (!text_decoration_fill_pattern) return false;
+ return true;
+}
+
+void NRStyle::applyTextDecorationFill(Inkscape::DrawingContext &dc)
+{
+ dc.setSource(text_decoration_fill_pattern);
+ // Fill rule does not matter, no intersections.
+}
+
+bool NRStyle::prepareStroke(Inkscape::DrawingContext &dc, Geom::OptRect const &paintbox, Inkscape::DrawingPattern *pattern)
{
if (!stroke_pattern) {
switch (stroke.type) {
- case PAINT_SERVER: {
- //stroke_pattern = sp_paint_server_create_pattern(stroke.server, dc.raw(), paintbox, stroke.opacity);
- stroke_pattern = stroke.server->pattern_new(dc.raw(), paintbox, stroke.opacity);
-
- } break;
+ case PAINT_SERVER:
+ if (pattern) {
+ stroke_pattern = pattern->renderPattern(stroke.opacity);
+ } else {
+ stroke_pattern = stroke.server->pattern_new(dc.raw(), paintbox, stroke.opacity);
+ }
+ break;
case PAINT_COLOR: {
SPColor const &c = stroke.color;
- stroke_pattern = cairo_pattern_create_rgba(
- c.v.c[0], c.v.c[1], c.v.c[2], stroke.opacity);
- } break;
- default: break;
+ stroke_pattern = cairo_pattern_create_rgba(c.v.c[0], c.v.c[1], c.v.c[2],
+ stroke.opacity);
+ }
+ break;
+ default:
+ break;
}
}
if (!stroke_pattern) return false;
@@ -290,13 +396,52 @@ void NRStyle::applyStroke(Inkscape::DrawingContext &dc)
cairo_set_dash(dc.raw(), dash, n_dash, dash_offset); // fixme
}
+bool NRStyle::prepareTextDecorationStroke(Inkscape::DrawingContext &dc, Geom::OptRect const &paintbox, Inkscape::DrawingPattern *pattern)
+{
+ if (!text_decoration_stroke_pattern) {
+ switch (text_decoration_stroke.type) {
+ case PAINT_SERVER:
+ if (pattern) {
+ text_decoration_stroke_pattern = pattern->renderPattern(
+ text_decoration_stroke.opacity);
+ } else {
+ text_decoration_stroke_pattern = text_decoration_stroke.server->pattern_new(
+ dc.raw(), paintbox, text_decoration_stroke.opacity);
+ }
+ break;
+ case PAINT_COLOR: {
+ SPColor const &c = text_decoration_stroke.color;
+ text_decoration_stroke_pattern = cairo_pattern_create_rgba(
+ c.v.c[0], c.v.c[1], c.v.c[2], text_decoration_stroke.opacity);
+ } break;
+ default: break;
+ }
+ }
+ if (!text_decoration_stroke_pattern) return false;
+ return true;
+}
+
+void NRStyle::applyTextDecorationStroke(Inkscape::DrawingContext &dc)
+{
+ dc.setSource(text_decoration_stroke_pattern);
+ dc.setLineWidth(text_decoration_stroke_width);
+ dc.setLineCap(CAIRO_LINE_CAP_BUTT);
+ dc.setLineJoin(CAIRO_LINE_JOIN_MITER);
+ dc.setMiterLimit(miter_limit);
+ cairo_set_dash(dc.raw(), 0, 0, 0.0); // fixme (no dash)
+}
+
void NRStyle::update()
{
// force pattern update
if (fill_pattern) cairo_pattern_destroy(fill_pattern);
if (stroke_pattern) cairo_pattern_destroy(stroke_pattern);
+ if (text_decoration_fill_pattern) cairo_pattern_destroy(text_decoration_fill_pattern);
+ if (text_decoration_stroke_pattern) cairo_pattern_destroy(text_decoration_stroke_pattern);
fill_pattern = NULL;
stroke_pattern = NULL;
+ text_decoration_fill_pattern = NULL;
+ text_decoration_stroke_pattern = NULL;
}
/*
diff --git a/src/display/nr-style.h b/src/display/nr-style.h
index 717cda899..f324fdb56 100644
--- a/src/display/nr-style.h
+++ b/src/display/nr-style.h
@@ -17,10 +17,11 @@
#include "color.h"
class SPPaintServer;
-struct SPStyle;
+class SPStyle;
namespace Inkscape {
class DrawingContext;
+class DrawingPattern;
}
struct NRStyle {
@@ -28,10 +29,14 @@ struct NRStyle {
~NRStyle();
void set(SPStyle *);
- bool prepareFill(Inkscape::DrawingContext &dc, Geom::OptRect const &paintbox);
- bool prepareStroke(Inkscape::DrawingContext &dc, Geom::OptRect const &paintbox);
+ bool prepareFill(Inkscape::DrawingContext &dc, Geom::OptRect const &paintbox, Inkscape::DrawingPattern *pattern);
+ bool prepareStroke(Inkscape::DrawingContext &dc, Geom::OptRect const &paintbox, Inkscape::DrawingPattern *pattern);
+ bool prepareTextDecorationFill(Inkscape::DrawingContext &dc, Geom::OptRect const &paintbox, Inkscape::DrawingPattern *pattern);
+ bool prepareTextDecorationStroke(Inkscape::DrawingContext &dc, Geom::OptRect const &paintbox, Inkscape::DrawingPattern *pattern);
void applyFill(Inkscape::DrawingContext &dc);
void applyStroke(Inkscape::DrawingContext &dc);
+ void applyTextDecorationFill(Inkscape::DrawingContext &dc);
+ void applyTextDecorationStroke(Inkscape::DrawingContext &dc);
void update();
enum PaintType {
@@ -67,8 +72,9 @@ struct NRStyle {
cairo_pattern_t *fill_pattern;
cairo_pattern_t *stroke_pattern;
+ cairo_pattern_t *text_decoration_fill_pattern;
+ cairo_pattern_t *text_decoration_stroke_pattern;
-#ifdef WITH_SVG2
enum PaintOrderType {
PAINT_ORDER_NORMAL,
PAINT_ORDER_FILL,
@@ -78,7 +84,6 @@ struct NRStyle {
static const size_t PAINT_ORDER_LAYERS = 3;
PaintOrderType paint_order_layer[PAINT_ORDER_LAYERS];
-#endif
#define TEXT_DECORATION_LINE_CLEAR 0x00
#define TEXT_DECORATION_LINE_SET 0x01
@@ -99,8 +104,9 @@ struct NRStyle {
int text_decoration_line;
int text_decoration_style;
- Paint text_decoration_color;
- bool text_decoration_useColor; // if false, use whatever the glyph color was
+ Paint text_decoration_fill;
+ Paint text_decoration_stroke;
+ float text_decoration_stroke_width;
// These are the same as in style.h
float phase_length;
bool tspan_line_start;
diff --git a/src/display/nr-svgfonts.cpp b/src/display/nr-svgfonts.cpp
index 84b4bd080..011f51977 100644
--- a/src/display/nr-svgfonts.cpp
+++ b/src/display/nr-svgfonts.cpp
@@ -4,6 +4,7 @@
*
* Authors:
* Felipe C. da S. Sanches <juca@members.fsf.org>
+ * Jon A. Cruz <jon@joncruz.org>
*
* Copyright (C) 2008 Felipe C. da S. Sanches
*
@@ -32,9 +33,9 @@
#include "sp-font.h"
#include "sp-glyph-kerning.h"
-//*************************//
+// ************************//
// UserFont Implementation //
-//*************************//
+// ************************//
// I wrote this binding code because Cairomm does not yet support userfonts. I have moved this code to cairomm and sent them a patch.
// Once Cairomm incorporate the UserFonts binding, this code should be removed from inkscape and Cairomm API should be used.
@@ -111,16 +112,38 @@ unsigned int size_of_substring(const char* substring, gchar* str){
return 0;
}
-//TODO: in these macros, verify what happens when using unicode strings.
-#define Match_VKerning_Rule ((SP_VKERN(node))->u1->contains(previous_unicode[0])\
- || (SP_VKERN(node))->g1->contains(previous_glyph_name)) &&\
- ((SP_VKERN(node))->u2->contains(this->glyphs[i]->unicode[0])\
- || (SP_VKERN(node))->g2->contains(this->glyphs[i]->glyph_name.c_str()))
-#define Match_HKerning_Rule ((SP_HKERN(node))->u1->contains(previous_unicode[0])\
- || (SP_HKERN(node))->g1->contains(previous_glyph_name)) &&\
- ((SP_HKERN(node))->u2->contains(this->glyphs[i]->unicode[0])\
- || (SP_HKERN(node))->g2->contains(this->glyphs[i]->glyph_name.c_str()))
+namespace {
+
+//TODO: in these functions, verify what happens when using unicode strings.
+
+bool MatchVKerningRule(SPVkern const *vkern,
+ SPGlyph *glyph,
+ char const *previous_unicode,
+ gchar const *previous_glyph_name)
+{
+ bool value = (vkern->u1->contains(previous_unicode[0])
+ || vkern->g1->contains(previous_glyph_name))
+ && (vkern->u2->contains(glyph->unicode[0])
+ || vkern->g2->contains(glyph->glyph_name.c_str()));
+
+ return value;
+}
+
+bool MatchHKerningRule(SPHkern const *hkern,
+ SPGlyph *glyph,
+ char const *previous_unicode,
+ gchar const *previous_glyph_name)
+{
+ bool value = (hkern->u1->contains(previous_unicode[0])
+ || hkern->g1->contains(previous_glyph_name))
+ && (hkern->u2->contains(glyph->unicode[0])
+ || hkern->g2->contains(glyph->glyph_name.c_str()));
+
+ return value;
+}
+
+} // namespace
cairo_status_t
SvgFont::scaled_font_text_to_glyphs (cairo_scaled_font_t */*scaled_font*/,
@@ -182,11 +205,13 @@ SvgFont::scaled_font_text_to_glyphs (cairo_scaled_font_t */*scaled_font*/,
if ( (len = size_of_substring(this->glyphs[i]->unicode.c_str(), _utf8)) ){
for(SPObject* node = this->font->children;previous_unicode && node;node=node->next){
//apply glyph kerning if appropriate
- if (SP_IS_HKERN(node) && is_horizontal_text && Match_HKerning_Rule ){
- x -= ((SP_HKERN(node))->k / 1000.0);//TODO: use here the height of the font
+ SPHkern *hkern = dynamic_cast<SPHkern *>(node);
+ if (hkern && is_horizontal_text && MatchHKerningRule(hkern, this->glyphs[i], previous_unicode, previous_glyph_name) ){
+ x -= (hkern->k / 1000.0);//TODO: use here the height of the font
}
- if (SP_IS_VKERN(node) && !is_horizontal_text && Match_VKerning_Rule ){
- y -= ((SP_VKERN(node))->k / 1000.0);//TODO: use here the "height" of the font
+ SPVkern *vkern = dynamic_cast<SPVkern *>(node);
+ if (vkern && !is_horizontal_text && MatchVKerningRule(vkern, this->glyphs[i], previous_unicode, previous_glyph_name) ){
+ y -= (vkern->k / 1000.0);//TODO: use here the "height" of the font
}
}
previous_unicode = const_cast<char*>(this->glyphs[i]->unicode.c_str());//used for kerning checking
@@ -246,9 +271,8 @@ SvgFont::glyph_modified(SPObject* /* blah */, unsigned int /* bleh */){
Geom::PathVector
SvgFont::flip_coordinate_system(SPFont* spfont, Geom::PathVector pathv){
double units_per_em = 1000;
- SPObject* obj;
- for (obj = (SP_OBJECT(spfont))->children; obj; obj=obj->next){
- if (SP_IS_FONTFACE(obj)){
+ for (SPObject *obj = spfont->children; obj; obj = obj->next){
+ if (dynamic_cast<SPFontFace *>(obj)) {
//XML Tree being directly used here while it shouldn't be.
sp_repr_get_double(obj->getRepr(), "units_per_em", &units_per_em);
}
@@ -275,19 +299,21 @@ SvgFont::scaled_font_render_glyph (cairo_scaled_font_t */*scaled_font*/,
if (glyph > this->glyphs.size()) return CAIRO_STATUS_SUCCESS;//TODO: this is an error!
- SPObject* node;
- if (glyph == this->glyphs.size()){
- if (!this->missingglyph) return CAIRO_STATUS_SUCCESS;
- node = SP_OBJECT(this->missingglyph);
+ SPObject *node = NULL;
+ if (glyph == glyphs.size()){
+ if (!missingglyph) {
+ return CAIRO_STATUS_SUCCESS;
+ }
+ node = missingglyph;
} else {
- node = SP_OBJECT(this->glyphs[glyph]);
+ node = glyphs[glyph];
}
- if (!SP_IS_GLYPH(node) && !SP_IS_MISSING_GLYPH(node)) {
+ if (!dynamic_cast<SPGlyph *>(node) && !dynamic_cast<SPMissingGlyph *>(node)) {
return CAIRO_STATUS_SUCCESS; // FIXME: is this the right code to return?
}
- SPFont* spfont = SP_FONT(node->parent);
+ SPFont* spfont = dynamic_cast<SPFont *>(node->parent);
if (!spfont) {
return CAIRO_STATUS_SUCCESS; // FIXME: is this the right code to return?
}
@@ -296,36 +322,48 @@ SvgFont::scaled_font_render_glyph (cairo_scaled_font_t */*scaled_font*/,
// or using the d attribute of a glyph node.
// pathv stores the path description from the d attribute:
Geom::PathVector pathv;
- if (SP_IS_GLYPH(node) && (SP_GLYPH(node))->d) {
- pathv = sp_svg_read_pathv((SP_GLYPH(node))->d);
- pathv = flip_coordinate_system(spfont, pathv);
- this->render_glyph_path(cr, &pathv);
- } else if (SP_IS_MISSING_GLYPH(node) && (SP_MISSING_GLYPH(node))->d) {
- pathv = sp_svg_read_pathv((SP_MISSING_GLYPH(node))->d);
+
+ SPGlyph *glyphNode = dynamic_cast<SPGlyph *>(node);
+ if (glyphNode && glyphNode->d) {
+ pathv = sp_svg_read_pathv(glyphNode->d);
pathv = flip_coordinate_system(spfont, pathv);
- this->render_glyph_path(cr, &pathv);
+ render_glyph_path(cr, &pathv);
+ } else {
+ SPMissingGlyph *missing = dynamic_cast<SPMissingGlyph *>(node);
+ if (missing && missing->d) {
+ pathv = sp_svg_read_pathv(missing->d);
+ pathv = flip_coordinate_system(spfont, pathv);
+ render_glyph_path(cr, &pathv);
+ }
}
if (node->hasChildren()){
//render the SVG described on this glyph's child nodes.
for(node = node->children; node; node=node->next){
- if (SP_IS_PATH(node)){
- pathv = (SP_SHAPE(node))->_curve->get_pathvector();
- pathv = flip_coordinate_system(spfont, pathv);
- this->render_glyph_path(cr, &pathv);
+ {
+ SPPath *path = dynamic_cast<SPPath *>(node);
+ if (path) {
+ pathv = path->_curve->get_pathvector();
+ pathv = flip_coordinate_system(spfont, pathv);
+ render_glyph_path(cr, &pathv);
+ }
}
- if (SP_IS_OBJECTGROUP(node)){
+ if (dynamic_cast<SPObjectGroup *>(node)) {
g_warning("TODO: svgfonts: render OBJECTGROUP");
}
- if (SP_IS_USE(node)){
- SPItem* item = SP_USE(node)->ref->getObject();
- if (SP_IS_PATH(item)){
- pathv = (SP_SHAPE(item))->_curve->get_pathvector();
+ SPUse *use = dynamic_cast<SPUse *>(node);
+ if (use) {
+ SPItem* item = use->ref->getObject();
+ SPPath *path = dynamic_cast<SPPath *>(item);
+ if (path) {
+ SPShape *shape = dynamic_cast<SPShape *>(item);
+ g_assert(shape != NULL);
+ pathv = shape->_curve->get_pathvector();
pathv = flip_coordinate_system(spfont, pathv);
this->render_glyph_path(cr, &pathv);
}
- glyph_modified_connection = (SP_OBJECT(item))->connectModified(sigc::mem_fun(*this, &SvgFont::glyph_modified));
+ glyph_modified_connection = item->connectModified(sigc::mem_fun(*this, &SvgFont::glyph_modified));
}
}
}
@@ -337,11 +375,13 @@ cairo_font_face_t*
SvgFont::get_font_face(){
if (!this->userfont) {
for(SPObject* node = this->font->children;node;node=node->next){
- if (SP_IS_GLYPH(node)){
- this->glyphs.push_back(SP_GLYPH(node));
+ SPGlyph *glyph = dynamic_cast<SPGlyph *>(node);
+ if (glyph) {
+ glyphs.push_back(glyph);
}
- if (SP_IS_MISSING_GLYPH(node)){
- this->missingglyph=SP_MISSING_GLYPH(node);
+ SPMissingGlyph *missing = dynamic_cast<SPMissingGlyph *>(node);
+ if (missing) {
+ missingglyph = missing;
}
}
this->userfont = new UserFont(this);
diff --git a/src/display/nr-svgfonts.h b/src/display/nr-svgfonts.h
index e1bb047bb..21ab3ed02 100644
--- a/src/display/nr-svgfonts.h
+++ b/src/display/nr-svgfonts.h
@@ -1,4 +1,3 @@
-#include "config.h"
#ifndef NR_SVGFONTS_H_SEEN
#define NR_SVGFONTS_H_SEEN
/*
@@ -13,7 +12,7 @@
* Read the file 'COPYING' for more information.
*/
-#include "cairo.h"
+#include <cairo.h>
#include <sigc++/connection.h>
class SvgFont;
@@ -21,40 +20,50 @@ class SPFont;
class SPGlyph;
class SPMissingGlyph;
-struct _GdkEventExpose;
-typedef _GdkEventExpose GdkEventExpose;
+extern "C" { typedef struct _GdkEventExpose GdkEventExpose; }
namespace Gtk {
class Widget;
}
-class UserFont{
+class UserFont {
public:
-UserFont(SvgFont* instance);
-cairo_font_face_t* face;
+ UserFont(SvgFont* instance);
+ cairo_font_face_t* face;
};
-class SvgFont{
+class SvgFont {
public:
-SvgFont(SPFont* spfont);
-void refresh();
-cairo_font_face_t* get_font_face();
-cairo_status_t scaled_font_init (cairo_scaled_font_t *scaled_font, cairo_font_extents_t *metrics);
-cairo_status_t scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font, const char *utf8, int utf8_len, cairo_glyph_t **glyphs, int *num_glyphs, cairo_text_cluster_t **clusters, int *num_clusters, cairo_text_cluster_flags_t *flags);
-cairo_status_t scaled_font_render_glyph (cairo_scaled_font_t *scaled_font, unsigned long glyph, cairo_t *cr, cairo_text_extents_t *metrics);
+ SvgFont(SPFont* spfont);
+ void refresh();
+ cairo_font_face_t* get_font_face();
+ cairo_status_t scaled_font_init (cairo_scaled_font_t *scaled_font, cairo_font_extents_t *metrics);
+ cairo_status_t scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font, const char *utf8, int utf8_len, cairo_glyph_t **glyphs, int *num_glyphs, cairo_text_cluster_t **clusters, int *num_clusters, cairo_text_cluster_flags_t *flags);
+ cairo_status_t scaled_font_render_glyph (cairo_scaled_font_t *scaled_font, unsigned long glyph, cairo_t *cr, cairo_text_extents_t *metrics);
-Geom::PathVector flip_coordinate_system(SPFont* spfont, Geom::PathVector pathv);
-void render_glyph_path(cairo_t* cr, Geom::PathVector* pathv);
-void glyph_modified(SPObject *, unsigned int);
+ Geom::PathVector flip_coordinate_system(SPFont* spfont, Geom::PathVector pathv);
+ void render_glyph_path(cairo_t* cr, Geom::PathVector* pathv);
+ void glyph_modified(SPObject *, unsigned int);
private:
-SPFont* font;
-UserFont* userfont;
-std::vector<SPGlyph*> glyphs;
-SPMissingGlyph* missingglyph;
-sigc::connection glyph_modified_connection;
+ SPFont* font;
+ UserFont* userfont;
+ std::vector<SPGlyph*> glyphs;
+ SPMissingGlyph* missingglyph;
+ sigc::connection glyph_modified_connection;
-bool drawing_expose_cb (Gtk::Widget *widget, GdkEventExpose *event, gpointer data);
+ bool drawing_expose_cb (Gtk::Widget *widget, GdkEventExpose *event, void* data);
};
#endif //#ifndef NR_SVGFONTS_H_SEEN
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8 :
diff --git a/src/display/snap-indicator.cpp b/src/display/snap-indicator.cpp
index 627bfb2ab..2632d69db 100644
--- a/src/display/snap-indicator.cpp
+++ b/src/display/snap-indicator.cpp
@@ -22,7 +22,7 @@
#include "knot.h"
#include "preferences.h"
#include <glibmm/i18n.h>
-#include "tools-switch.h"
+#include "ui/tools-switch.h"
#include "enums.h"
namespace Inkscape {
@@ -73,6 +73,7 @@ SnapIndicator::set_new_snaptarget(Inkscape::SnappedPoint const &p, bool pre_snap
switch (p.getTarget()) {
case SNAPTARGET_UNDEFINED:
target_name = _("UNDEFINED");
+ g_warning("Snap target has not been specified");
break;
case SNAPTARGET_GRID:
target_name = _("grid line");
@@ -172,7 +173,7 @@ SnapIndicator::set_new_snaptarget(Inkscape::SnappedPoint const &p, bool pre_snap
target_name = _("constraint");
break;
default:
- g_warning("Snap target has not yet been defined!");
+ g_warning("Snap target not in SnapTargetType enum");
break;
}
@@ -180,6 +181,7 @@ SnapIndicator::set_new_snaptarget(Inkscape::SnappedPoint const &p, bool pre_snap
switch (p.getSource()) {
case SNAPSOURCE_UNDEFINED:
source_name = _("UNDEFINED");
+ g_warning("Snap source has not been specified");
break;
case SNAPSOURCE_BBOX_CORNER:
source_name = _("Bounding box corner");
@@ -235,7 +237,7 @@ SnapIndicator::set_new_snaptarget(Inkscape::SnappedPoint const &p, bool pre_snap
source_name = _("Multiple of grid spacing");
break;
default:
- g_warning("Snap source has not yet been defined!");
+ g_warning("Snap source not in SnapSourceType enum");
break;
}
//std::cout << "Snapped " << source_name << " to " << target_name << std::endl;
diff --git a/src/display/sodipodi-ctrl.cpp b/src/display/sodipodi-ctrl.cpp
index 3636319df..327fbce1f 100644
--- a/src/display/sodipodi-ctrl.cpp
+++ b/src/display/sodipodi-ctrl.cpp
@@ -25,9 +25,6 @@ enum {
ARG_PIXBUF
};
-
-static void sp_ctrl_class_init (SPCtrlClass *klass);
-static void sp_ctrl_init (SPCtrl *ctrl);
static void sp_ctrl_destroy(SPCanvasItem *object);
static void sp_ctrl_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
static void sp_ctrl_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
@@ -36,29 +33,7 @@ static void sp_ctrl_render (SPCanvasItem *item, SPCanvasBuf *buf);
static double sp_ctrl_point (SPCanvasItem *item, Geom::Point p, SPCanvasItem **actual_item);
-static SPCanvasItemClass *parent_class;
-
-GType
-sp_ctrl_get_type (void)
-{
- static GType ctrl_type = 0;
- if (!ctrl_type) {
- static GTypeInfo const ctrl_info = {
- sizeof (SPCtrlClass),
- NULL, /* base_init */
- NULL, /* base_finalize */
- (GClassInitFunc) sp_ctrl_class_init,
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof (SPCtrl),
- 0, /* n_preallocs */
- (GInstanceInitFunc) sp_ctrl_init,
- NULL
- };
- ctrl_type = g_type_register_static (SP_TYPE_CANVAS_ITEM, "SPCtrl", &ctrl_info, (GTypeFlags)0);
- }
- return ctrl_type;
-}
+G_DEFINE_TYPE(SPCtrl, sp_ctrl, SP_TYPE_CANVAS_ITEM);
static void
sp_ctrl_class_init (SPCtrlClass *klass)
@@ -66,8 +41,6 @@ sp_ctrl_class_init (SPCtrlClass *klass)
SPCanvasItemClass *item_class = SP_CANVAS_ITEM_CLASS(klass);
GObjectClass *g_object_class = (GObjectClass *) klass;
- parent_class = SP_CANVAS_ITEM_CLASS(g_type_class_peek_parent (klass));
-
g_object_class->set_property = sp_ctrl_set_property;
g_object_class->get_property = sp_ctrl_get_property;
@@ -239,8 +212,8 @@ static void sp_ctrl_destroy(SPCanvasItem *object)
ctrl->cache = NULL;
}
- if (SP_CANVAS_ITEM_CLASS(parent_class)->destroy)
- (* SP_CANVAS_ITEM_CLASS(parent_class)->destroy) (object);
+ if (SP_CANVAS_ITEM_CLASS(sp_ctrl_parent_class)->destroy)
+ SP_CANVAS_ITEM_CLASS(sp_ctrl_parent_class)->destroy(object);
}
static void
@@ -251,8 +224,8 @@ sp_ctrl_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned int fla
ctrl = SP_CTRL (item);
- if ((SP_CANVAS_ITEM_CLASS(parent_class))->update)
- (* (SP_CANVAS_ITEM_CLASS(parent_class))->update) (item, affine, flags);
+ if (SP_CANVAS_ITEM_CLASS(sp_ctrl_parent_class)->update)
+ SP_CANVAS_ITEM_CLASS(sp_ctrl_parent_class)->update(item, affine, flags);
sp_canvas_item_reset_bounds (item);
diff --git a/src/display/sodipodi-ctrlrect.cpp b/src/display/sodipodi-ctrlrect.cpp
index e6e427047..75789ff50 100644
--- a/src/display/sodipodi-ctrlrect.cpp
+++ b/src/display/sodipodi-ctrlrect.cpp
@@ -26,45 +26,19 @@
* Corner coords can be in any order - i.e. x1 < x0 is allowed
*/
-static void sp_ctrlrect_class_init(SPCtrlRectClass *c);
-static void sp_ctrlrect_init(CtrlRect *ctrlrect);
static void sp_ctrlrect_destroy(SPCanvasItem *object);
static void sp_ctrlrect_update(SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags);
static void sp_ctrlrect_render(SPCanvasItem *item, SPCanvasBuf *buf);
-static SPCanvasItemClass *parent_class;
-
static const guint DASH_LENGTH = 4;
-GType sp_ctrlrect_get_type()
-{
- static GType type = 0;
-
- if (!type) {
- GTypeInfo info = {
- sizeof(SPCtrlRectClass),
- 0, // base_init
- 0, // base_finalize
- (GClassInitFunc)sp_ctrlrect_class_init,
- 0, // class_finalize
- 0, // class_data
- sizeof(CtrlRect),
- 0, // n_preallocs
- (GInstanceInitFunc)sp_ctrlrect_init,
- 0 // value_table
- };
- type = g_type_register_static(SP_TYPE_CANVAS_ITEM, "SPCtrlRect", &info, static_cast<GTypeFlags>(0));
- }
- return type;
-}
+G_DEFINE_TYPE(CtrlRect, sp_ctrlrect, SP_TYPE_CANVAS_ITEM);
-static void sp_ctrlrect_class_init(SPCtrlRectClass *c)
+static void sp_ctrlrect_class_init(CtrlRectClass *c)
{
SPCanvasItemClass *item_class = SP_CANVAS_ITEM_CLASS(c);
- parent_class = SP_CANVAS_ITEM_CLASS(g_type_class_peek_parent(c));
-
item_class->destroy = sp_ctrlrect_destroy;
item_class->update = sp_ctrlrect_update;
item_class->render = sp_ctrlrect_render;
@@ -77,8 +51,8 @@ static void sp_ctrlrect_init(CtrlRect *cr)
static void sp_ctrlrect_destroy(SPCanvasItem *object)
{
- if (SP_CANVAS_ITEM_CLASS(parent_class)->destroy) {
- (* SP_CANVAS_ITEM_CLASS(parent_class)->destroy)(object);
+ if (SP_CANVAS_ITEM_CLASS(sp_ctrlrect_parent_class)->destroy) {
+ (* SP_CANVAS_ITEM_CLASS(sp_ctrlrect_parent_class)->destroy)(object);
}
}
@@ -171,8 +145,8 @@ void CtrlRect::update(Geom::Affine const &affine, unsigned int flags)
using Geom::X;
using Geom::Y;
- if ((SP_CANVAS_ITEM_CLASS(parent_class))->update) {
- (SP_CANVAS_ITEM_CLASS(parent_class))->update(this, affine, flags);
+ if ((SP_CANVAS_ITEM_CLASS(sp_ctrlrect_parent_class))->update) {
+ (SP_CANVAS_ITEM_CLASS(sp_ctrlrect_parent_class))->update(this, affine, flags);
}
sp_canvas_item_reset_bounds(this);
diff --git a/src/display/sodipodi-ctrlrect.h b/src/display/sodipodi-ctrlrect.h
index 65a40a850..ff6c55b06 100644
--- a/src/display/sodipodi-ctrlrect.h
+++ b/src/display/sodipodi-ctrlrect.h
@@ -26,7 +26,7 @@ struct SPCanvasBuf;
#define SP_TYPE_CTRLRECT (sp_ctrlrect_get_type ())
#define SP_CTRLRECT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SP_TYPE_CTRLRECT, CtrlRect))
-#define SP_CTRLRECT_CLASS(c) (G_TYPE_CHECK_CLASS_CAST((c), SP_TYPE_CTRLRECT, SPCtrlRectClass))
+#define SP_CTRLRECT_CLASS(c) (G_TYPE_CHECK_CLASS_CAST((c), SP_TYPE_CTRLRECT, CtrlRectClass))
#define SP_IS_CTRLRECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SP_TYPE_CTRLRECT))
#define SP_IS_CTRLRECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SP_TYPE_CTRLRECT))
@@ -57,7 +57,7 @@ private:
int _shadow;
};
-struct SPCtrlRectClass : public SPCanvasItemClass {};
+struct CtrlRectClass : public SPCanvasItemClass {};
GType sp_ctrlrect_get_type();
diff --git a/src/display/sp-canvas-item.h b/src/display/sp-canvas-item.h
index f34ec453c..3b7b7bd4f 100644
--- a/src/display/sp-canvas-item.h
+++ b/src/display/sp-canvas-item.h
@@ -23,10 +23,9 @@
# include "config.h"
#endif
-#include <glib-object.h>
-#include <gtk/gtk.h>
-#include <gdk/gdk.h>
#include <2geom/rect.h>
+#include <glib-object.h>
+
#include "ui/control-types.h"
G_BEGIN_DECLS
@@ -36,8 +35,10 @@ struct SPCanvasBuf;
struct SPCanvasGroup;
typedef struct _SPCanvasItemClass SPCanvasItemClass;
+typedef union _GdkEvent GdkEvent;
+typedef struct _GdkCursor GdkCursor;
-#define SP_TYPE_CANVAS_ITEM (SPCanvasItem::getType())
+#define SP_TYPE_CANVAS_ITEM (sp_canvas_item_get_type())
#define SP_CANVAS_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SP_TYPE_CANVAS_ITEM, SPCanvasItem))
#define SP_CANVAS_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SP_TYPE_CANVAS_ITEM, SPCanvasItemClass))
#define SP_IS_CANVAS_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), SP_TYPE_CANVAS_ITEM))
@@ -50,7 +51,6 @@ typedef struct _SPCanvasItemClass SPCanvasItemClass;
*/
struct SPCanvasItem {
GInitiallyUnowned parent_instance;
- static GType getType();
SPCanvas *canvas;
SPCanvasItem *parent;
@@ -73,6 +73,8 @@ struct SPCanvasItem {
bool in_destruction;
};
+GType sp_canvas_item_get_type();
+
/**
* The vtable of an SPCanvasItem.
*/
diff --git a/src/display/sp-canvas-util.h b/src/display/sp-canvas-util.h
index 07323f31a..73135ed79 100644
--- a/src/display/sp-canvas-util.h
+++ b/src/display/sp-canvas-util.h
@@ -1,5 +1,5 @@
-#ifndef __SP_CANVAS_UTILS_H__
-#define __SP_CANVAS_UTILS_H__
+#ifndef SEEN_SP_CANVAS_UTILS_H
+#define SEEN_SP_CANVAS_UTILS_H
/*
* Helper stuff for SPCanvas
@@ -19,7 +19,7 @@ struct SPCanvasItem;
struct SPCanvasBuf;
namespace Geom {
- class Affine;
+ class Affine;
}
/* Miscellaneous utility & convenience functions for general canvas objects */
diff --git a/src/display/sp-canvas.cpp b/src/display/sp-canvas.cpp
index 6d903867b..305b0950a 100644
--- a/src/display/sp-canvas.cpp
+++ b/src/display/sp-canvas.cpp
@@ -61,8 +61,6 @@ struct SPCanvasGroupClass {
* A group of Items.
*/
struct SPCanvasGroup {
- static GType getType();
-
/**
* Adds an item to a canvas group.
*/
@@ -113,17 +111,8 @@ struct SPCanvasGroup {
GList *items;
GList *last;
-
- static SPCanvasItemClass *parentClass;
};
-SPCanvasItemClass *SPCanvasGroup::parentClass;
-
-GType sp_canvas_group_get_type()
-{
- return SPCanvasGroup::getType();
-}
-
/**
* The SPCanvas vtable.
*/
@@ -161,19 +150,6 @@ enum {
LAST_SIGNAL
};
-void sp_canvas_item_base_class_init(SPCanvasItemClass *klass);
-void sp_canvas_item_base_class_finalize(SPCanvasItemClass *klass);
-
-/**
- * Initializes the SPCanvasItem vtable and the "event" signal.
- */
-void sp_canvas_item_class_init(SPCanvasItemClass *klass);
-
-/**
- * Callback for initialization of SPCanvasItem.
- */
-void sp_canvas_item_init(SPCanvasItem *item, SPCanvasItemClass *klass);
-
/**
* Callback that removes item from all referers and destroys it.
*/
@@ -181,7 +157,6 @@ void sp_canvas_item_dispose(GObject *object);
void sp_canvas_item_finalize(GObject *object);
void sp_canvas_item_real_destroy(SPCanvasItem *object);
-static gpointer parent_class = NULL;
static guint object_signals[LAST_SIGNAL] = { 0 };
/**
@@ -358,45 +333,12 @@ public:
static void requestCanvasUpdate(SPCanvas *canvas);
};
-GType SPCanvasItem::getType()
-{
- static GType object_type = 0;
-
- if (!object_type) {
- static GTypeInfo const object_info = {
- sizeof(SPCanvasItemClass),
- reinterpret_cast<GBaseInitFunc>(sp_canvas_item_base_class_init),
- reinterpret_cast<GBaseFinalizeFunc>(sp_canvas_item_base_class_finalize),
- reinterpret_cast<GClassInitFunc>(sp_canvas_item_class_init),
- NULL, // class_finalize
- NULL, // class_data
- sizeof(SPCanvasItem),
- 16, // n_preallocs
- reinterpret_cast<GInstanceInitFunc>(sp_canvas_item_init),
- NULL // value_table
- };
+G_DEFINE_TYPE(SPCanvasItem, sp_canvas_item, G_TYPE_INITIALLY_UNOWNED);
- object_type = g_type_register_static(G_TYPE_INITIALLY_UNOWNED,
- "SPCanvasItem", &object_info, GTypeFlags(0));
- }
-
- return object_type;
-}
-
-namespace {
-
-void sp_canvas_item_base_class_init(SPCanvasItemClass * /*klass*/)
-{
-}
-
-void sp_canvas_item_base_class_finalize(SPCanvasItemClass * /*klass*/)
-{
-}
-
-void sp_canvas_item_class_init(SPCanvasItemClass *klass)
+static void
+sp_canvas_item_class_init(SPCanvasItemClass *klass)
{
GObjectClass *gobject_class = (GObjectClass *) klass;
- parent_class = g_type_class_ref (G_TYPE_OBJECT);
item_signals[ITEM_EVENT] = g_signal_new ("event",
G_TYPE_FROM_CLASS (klass),
@@ -421,7 +363,8 @@ void sp_canvas_item_class_init(SPCanvasItemClass *klass)
G_TYPE_NONE, 0);
}
-void sp_canvas_item_init(SPCanvasItem *item, SPCanvasItemClass * /*klass*/)
+static void
+sp_canvas_item_init(SPCanvasItem *item)
{
item->xform = Geom::Affine(Geom::identity());
item->ctrlType = Inkscape::CTRL_TYPE_UNKNOWN;
@@ -434,15 +377,13 @@ void sp_canvas_item_init(SPCanvasItem *item, SPCanvasItemClass * /*klass*/)
item->in_destruction = false;
}
-} // namespace
-
SPCanvasItem *sp_canvas_item_new(SPCanvasGroup *parent, GType type, gchar const *first_arg_name, ...)
{
va_list args;
g_return_val_if_fail(parent != NULL, NULL);
g_return_val_if_fail(SP_IS_CANVAS_GROUP(parent), NULL);
- g_return_val_if_fail(g_type_is_a(type, SPCanvasItem::getType()), NULL);
+ g_return_val_if_fail(g_type_is_a(type, SP_TYPE_CANVAS_ITEM), NULL);
SPCanvasItem *item = SP_CANVAS_ITEM(g_object_new(type, NULL));
@@ -554,7 +495,7 @@ void sp_canvas_item_dispose(GObject *object)
item->in_destruction = false;
}
- G_OBJECT_CLASS(parent_class)->dispose(object);
+ G_OBJECT_CLASS(sp_canvas_item_parent_class)->dispose(object);
}
void sp_canvas_item_real_destroy(SPCanvasItem *object)
@@ -574,7 +515,7 @@ void sp_canvas_item_finalize(GObject *gobject)
"and must be removed with g_object_ref_sink().");
}
- G_OBJECT_CLASS (parent_class)->finalize (gobject);
+ G_OBJECT_CLASS (sp_canvas_item_parent_class)->finalize (gobject);
}
} // namespace
@@ -982,37 +923,12 @@ gint sp_canvas_item_order (SPCanvasItem * item)
}
// SPCanvasGroup
+G_DEFINE_TYPE(SPCanvasGroup, sp_canvas_group, SP_TYPE_CANVAS_ITEM);
-/**
- * Registers SPCanvasGroup class with Gtk and returns its type number.
- */
-GType SPCanvasGroup::getType(void)
-{
- static GType type = 0;
- if (!type) {
- GTypeInfo info = {
- sizeof(SPCanvasGroupClass),
- 0, // base_init
- 0, // base_finalize
- reinterpret_cast<GClassInitFunc>(SPCanvasGroup::classInit),
- 0, // class_finalize
- 0, // class_data
- sizeof(SPCanvasGroup),
- 0, // n_preallocs
- reinterpret_cast<GInstanceInitFunc>(SPCanvasGroup::init),
- 0 // value_table
- };
- type = g_type_register_static(SPCanvasItem::getType(), "SPCanvasGroup", &info, static_cast<GTypeFlags>(0));
- }
- return type;
-}
-
-void SPCanvasGroup::classInit(SPCanvasGroupClass *klass)
+static void sp_canvas_group_class_init(SPCanvasGroupClass *klass)
{
SPCanvasItemClass *item_class = reinterpret_cast<SPCanvasItemClass *>(klass);
- parentClass = reinterpret_cast<SPCanvasItemClass*>(g_type_class_peek_parent(klass));
-
item_class->destroy = SPCanvasGroup::destroy;
item_class->update = SPCanvasGroup::update;
item_class->render = SPCanvasGroup::render;
@@ -1020,7 +936,7 @@ void SPCanvasGroup::classInit(SPCanvasGroupClass *klass)
item_class->viewbox_changed = SPCanvasGroup::viewboxChanged;
}
-void SPCanvasGroup::init(SPCanvasGroup * /*group*/)
+static void sp_canvas_group_init(SPCanvasGroup * /*group*/)
{
// Nothing here
}
@@ -1040,8 +956,8 @@ void SPCanvasGroup::destroy(SPCanvasItem *object)
sp_canvas_item_destroy(child);
}
- if (SP_CANVAS_ITEM_CLASS(parentClass)->destroy) {
- (* SP_CANVAS_ITEM_CLASS(parentClass)->destroy)(object);
+ if (SP_CANVAS_ITEM_CLASS(sp_canvas_group_parent_class)->destroy) {
+ (* SP_CANVAS_ITEM_CLASS(sp_canvas_group_parent_class)->destroy)(object);
}
}
@@ -1238,7 +1154,7 @@ sp_canvas_init(SPCanvas *canvas)
canvas->pick_event.crossing.y = 0;
// Create the root item as a special case
- canvas->root = SP_CANVAS_ITEM(g_object_new(SPCanvasGroup::getType(), NULL));
+ canvas->root = SP_CANVAS_ITEM(g_object_new(SP_TYPE_CANVAS_GROUP, NULL));
canvas->root->canvas = canvas;
g_object_ref (canvas->root);
@@ -2153,6 +2069,8 @@ gboolean SPCanvasImpl::handleDraw(GtkWidget *widget, cairo_t *cr) {
canvas->requestRedraw(r.left(), r.top(), r.right(), r.bottom());
}
+ cairo_rectangle_list_destroy(rects);
+
return FALSE;
}
#else
diff --git a/src/display/sp-canvas.h b/src/display/sp-canvas.h
index 72ae4b6bc..48c3de2fc 100644
--- a/src/display/sp-canvas.h
+++ b/src/display/sp-canvas.h
@@ -22,16 +22,6 @@
# include "config.h"
#endif
-#ifdef HAVE_INTTYPES_H
-# include <inttypes.h>
-#else
-# ifdef HAVE_STDINT_H
-# include <stdint.h>
-# endif
-#endif
-
-#include <glib.h>
-#include <gdk/gdk.h>
#include <gtk/gtk.h>
#include <glibmm/ustring.h>
#include <2geom/affine.h>
diff --git a/src/display/sp-ctrlcurve.cpp b/src/display/sp-ctrlcurve.cpp
index d9b687f2e..2e0e8105b 100644
--- a/src/display/sp-ctrlcurve.cpp
+++ b/src/display/sp-ctrlcurve.cpp
@@ -23,42 +23,18 @@
namespace {
-static void sp_ctrlcurve_class_init(SPCtrlCurveClass *klass, gpointer data);
-static void sp_ctrlcurve_init(SPCtrlCurve *ctrlcurve, gpointer g_class);
static void sp_ctrlcurve_destroy(SPCanvasItem *object);
static void sp_ctrlcurve_update(SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags);
static void sp_ctrlcurve_render(SPCanvasItem *item, SPCanvasBuf *buf);
-static SPCanvasItemClass *parent_class;
-
} // namespace
-GType SPCtrlCurve::getType()
-{
- static GType type = 0;
- if (!type) {
- GTypeInfo info = {
- sizeof(SPCtrlCurveClass),
- NULL, NULL,
- reinterpret_cast<GClassInitFunc>(sp_ctrlcurve_class_init),
- NULL, NULL,
- sizeof(SPCtrlCurve),
- 0,
- reinterpret_cast<GInstanceInitFunc>(sp_ctrlcurve_init),
- NULL
- };
- type = g_type_register_static(SP_TYPE_CANVAS_ITEM, "SPCtrlCurve", &info, static_cast<GTypeFlags>(0));
- }
- return type;
-}
+G_DEFINE_TYPE(SPCtrlCurve, sp_ctrlcurve, SP_TYPE_CANVAS_ITEM);
-namespace {
-
-void sp_ctrlcurve_class_init(SPCtrlCurveClass *klass, gpointer /*g_class*/)
+static void
+sp_ctrlcurve_class_init(SPCtrlCurveClass *klass)
{
- parent_class = reinterpret_cast<SPCanvasItemClass*>(g_type_class_peek_parent(klass));
-
klass->destroy = sp_ctrlcurve_destroy;
klass->update = sp_ctrlcurve_update;
@@ -66,13 +42,14 @@ void sp_ctrlcurve_class_init(SPCtrlCurveClass *klass, gpointer /*g_class*/)
}
static void
-sp_ctrlcurve_init(SPCtrlCurve *ctrlcurve, gpointer /*g_class*/)
+sp_ctrlcurve_init(SPCtrlCurve *ctrlcurve)
{
// Points are initialized to 0,0
ctrlcurve->rgba = 0x0000ff7f;
ctrlcurve->item=NULL;
}
+namespace {
static void
sp_ctrlcurve_destroy(SPCanvasItem *object)
{
@@ -83,8 +60,8 @@ sp_ctrlcurve_destroy(SPCanvasItem *object)
ctrlcurve->item=NULL;
- if (SP_CANVAS_ITEM_CLASS (parent_class)->destroy)
- (* SP_CANVAS_ITEM_CLASS (parent_class)->destroy) (object);
+ if (SP_CANVAS_ITEM_CLASS(sp_ctrlcurve_parent_class)->destroy)
+ SP_CANVAS_ITEM_CLASS(sp_ctrlcurve_parent_class)->destroy(object);
}
static void
@@ -125,8 +102,8 @@ sp_ctrlcurve_update(SPCanvasItem *item, Geom::Affine const &affine, unsigned int
item->canvas->requestRedraw(item->x1, item->y1, item->x2, item->y2);
- if (parent_class->update)
- (* parent_class->update) (item, affine, flags);
+ if (SP_CANVAS_ITEM_CLASS(sp_ctrlcurve_parent_class)->update)
+ SP_CANVAS_ITEM_CLASS(sp_ctrlcurve_parent_class)->update(item, affine, flags);
sp_canvas_item_reset_bounds (item);
diff --git a/src/display/sp-ctrlcurve.h b/src/display/sp-ctrlcurve.h
index 90936185c..847944f38 100644
--- a/src/display/sp-ctrlcurve.h
+++ b/src/display/sp-ctrlcurve.h
@@ -19,14 +19,11 @@
class SPItem;
-#define SP_TYPE_CTRLCURVE (SPCtrlCurve::getType())
+#define SP_TYPE_CTRLCURVE (sp_ctrlcurve_get_type())
#define SP_CTRLCURVE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SP_TYPE_CTRLCURVE, SPCtrlCurve))
#define SP_IS_CTRLCURVE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SP_TYPE_CTRLCURVE))
struct SPCtrlCurve : public SPCtrlLine {
-
- static GType getType();
-
void setCoords( gdouble x0, gdouble y0, gdouble x1, gdouble y1,
gdouble x2, gdouble y2, gdouble x3, gdouble y3 );
@@ -36,9 +33,9 @@ struct SPCtrlCurve : public SPCtrlLine {
Geom::Point p0, p1, p2, p3;
};
-struct SPCtrlCurveClass : public SPCtrlLineClass{};
-
+GType sp_ctrlcurve_get_type();
+struct SPCtrlCurveClass : public SPCtrlLineClass{};
#endif // SEEN_INKSCAPE_CTRLCURVE_H
diff --git a/src/display/sp-ctrlline.cpp b/src/display/sp-ctrlline.cpp
index aef284c1a..1bde540c0 100644
--- a/src/display/sp-ctrlline.cpp
+++ b/src/display/sp-ctrlline.cpp
@@ -30,55 +30,31 @@
namespace {
-void sp_ctrlline_class_init(SPCtrlLineClass *klass, gpointer data);
-void sp_ctrlline_init(SPCtrlLine *ctrlline, gpointer g_class);
void sp_ctrlline_destroy(SPCanvasItem *object);
void sp_ctrlline_update(SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags);
void sp_ctrlline_render(SPCanvasItem *item, SPCanvasBuf *buf);
-SPCanvasItemClass *parent_class = 0;
-
} // namespace
-GType SPCtrlLine::getType()
-{
- static GType type = 0;
- if (!type) {
- GTypeInfo info = {
- sizeof(SPCtrlLineClass),
- NULL, NULL,
- reinterpret_cast<GClassInitFunc>(sp_ctrlline_class_init),
- NULL, NULL,
- sizeof(SPCtrlLine),
- 0,
- reinterpret_cast<GInstanceInitFunc>(sp_ctrlline_init),
- NULL
- };
- type = g_type_register_static(SP_TYPE_CANVAS_ITEM, "SPCtrlLine", &info, static_cast<GTypeFlags>(0));
- }
- return type;
-}
-
-namespace {
+G_DEFINE_TYPE(SPCtrlLine, sp_ctrlline, SP_TYPE_CANVAS_ITEM);
-void sp_ctrlline_class_init(SPCtrlLineClass *klass, gpointer /*data*/)
+static void sp_ctrlline_class_init(SPCtrlLineClass *klass)
{
- parent_class = reinterpret_cast<SPCanvasItemClass*>(g_type_class_peek_parent(klass));
-
klass->destroy = sp_ctrlline_destroy;
klass->update = sp_ctrlline_update;
klass->render = sp_ctrlline_render;
}
-void sp_ctrlline_init(SPCtrlLine *ctrlline, gpointer /*g_class*/)
+static void sp_ctrlline_init(SPCtrlLine *ctrlline)
{
ctrlline->rgba = 0x0000ff7f;
ctrlline->s[Geom::X] = ctrlline->s[Geom::Y] = ctrlline->e[Geom::X] = ctrlline->e[Geom::Y] = 0.0;
ctrlline->item=NULL;
}
+namespace {
void sp_ctrlline_destroy(SPCanvasItem *object)
{
g_return_if_fail(object != NULL);
@@ -88,8 +64,8 @@ void sp_ctrlline_destroy(SPCanvasItem *object)
ctrlline->item = NULL;
- if(SP_CANVAS_ITEM_CLASS (parent_class)->destroy) {
- (* SP_CANVAS_ITEM_CLASS (parent_class)->destroy)(object);
+ if(SP_CANVAS_ITEM_CLASS (sp_ctrlline_parent_class)->destroy) {
+ SP_CANVAS_ITEM_CLASS (sp_ctrlline_parent_class)->destroy(object);
}
}
@@ -134,8 +110,8 @@ void sp_ctrlline_update(SPCanvasItem *item, Geom::Affine const &affine, unsigned
item->canvas->requestRedraw(item->x1, item->y1, item->x2, item->y2);
- if (parent_class->update) {
- (* parent_class->update)(item, affine, flags);
+ if (SP_CANVAS_ITEM_CLASS(sp_ctrlline_parent_class)->update) {
+ SP_CANVAS_ITEM_CLASS(sp_ctrlline_parent_class)->update(item, affine, flags);
}
sp_canvas_item_reset_bounds(item);
diff --git a/src/display/sp-ctrlline.h b/src/display/sp-ctrlline.h
index 12be03ca5..b2e222437 100644
--- a/src/display/sp-ctrlline.h
+++ b/src/display/sp-ctrlline.h
@@ -20,13 +20,11 @@
class SPItem;
-#define SP_TYPE_CTRLLINE (SPCtrlLine::getType())
+#define SP_TYPE_CTRLLINE (sp_ctrlline_get_type())
#define SP_CTRLLINE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SP_TYPE_CTRLLINE, SPCtrlLine))
#define SP_IS_CTRLLINE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SP_TYPE_CTRLLINE))
struct SPCtrlLine : public SPCanvasItem {
- static GType getType();
-
void setRgba32(guint32 rgba);
void setCoords(gdouble x0, gdouble y0, gdouble x1, gdouble y1);
@@ -41,6 +39,8 @@ struct SPCtrlLine : public SPCanvasItem {
Geom::Affine affine;
};
+GType sp_ctrlline_get_type();
+
struct SPCtrlLineClass : public SPCanvasItemClass{};
diff --git a/src/display/sp-ctrlpoint.cpp b/src/display/sp-ctrlpoint.cpp
index 026cc7589..1082cb1b3 100644
--- a/src/display/sp-ctrlpoint.cpp
+++ b/src/display/sp-ctrlpoint.cpp
@@ -20,42 +20,17 @@
#include "display/cairo-utils.h"
#include "display/sp-canvas.h"
-
-static void sp_ctrlpoint_class_init (SPCtrlPointClass *klass);
-static void sp_ctrlpoint_init (SPCtrlPoint *ctrlpoint);
static void sp_ctrlpoint_destroy(SPCanvasItem *object);
static void sp_ctrlpoint_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags);
static void sp_ctrlpoint_render (SPCanvasItem *item, SPCanvasBuf *buf);
-static SPCanvasItemClass *parent_class;
-
-GType
-sp_ctrlpoint_get_type (void)
-{
- static GType type = 0;
- if (!type) {
- GTypeInfo info = {
- sizeof(SPCtrlPointClass),
- NULL, NULL,
- (GClassInitFunc) sp_ctrlpoint_class_init,
- NULL, NULL,
- sizeof(SPCtrlPoint),
- 0,
- (GInstanceInitFunc) sp_ctrlpoint_init,
- NULL
- };
- type = g_type_register_static(SP_TYPE_CANVAS_ITEM, "SPCtrlPoint", &info, (GTypeFlags)0);
- }
- return type;
-}
+G_DEFINE_TYPE(SPCtrlPoint, sp_ctrlpoint, SP_TYPE_CANVAS_ITEM);
static void sp_ctrlpoint_class_init(SPCtrlPointClass *klass)
{
SPCanvasItemClass *item_class = SP_CANVAS_ITEM_CLASS(klass);
- parent_class = SP_CANVAS_ITEM_CLASS(g_type_class_peek_parent(klass));
-
item_class->destroy = sp_ctrlpoint_destroy;
item_class->update = sp_ctrlpoint_update;
item_class->render = sp_ctrlpoint_render;
@@ -79,8 +54,8 @@ static void sp_ctrlpoint_destroy(SPCanvasItem *object)
ctrlpoint->item=NULL;
- if (SP_CANVAS_ITEM_CLASS(parent_class)->destroy)
- (* SP_CANVAS_ITEM_CLASS(parent_class)->destroy) (object);
+ if (SP_CANVAS_ITEM_CLASS(sp_ctrlpoint_parent_class)->destroy)
+ SP_CANVAS_ITEM_CLASS(sp_ctrlpoint_parent_class)->destroy(object);
}
static void
@@ -111,8 +86,8 @@ static void sp_ctrlpoint_update(SPCanvasItem *item, Geom::Affine const &affine,
item->canvas->requestRedraw((int)item->x1, (int)item->y1, (int)item->x2, (int)item->y2);
- if (parent_class->update) {
- (* parent_class->update) (item, affine, flags);
+ if (SP_CANVAS_ITEM_CLASS(sp_ctrlpoint_parent_class)->update) {
+ SP_CANVAS_ITEM_CLASS(sp_ctrlpoint_parent_class)->update(item, affine, flags);
}
sp_canvas_item_reset_bounds (item);
diff --git a/src/display/sp-ctrlquadr.cpp b/src/display/sp-ctrlquadr.cpp
index b6a0da109..760e93a6d 100644
--- a/src/display/sp-ctrlquadr.cpp
+++ b/src/display/sp-ctrlquadr.cpp
@@ -29,42 +29,18 @@ struct SPCtrlQuadr : public SPCanvasItem{
struct SPCtrlQuadrClass : public SPCanvasItemClass{};
-static void sp_ctrlquadr_class_init (SPCtrlQuadrClass *klass);
-static void sp_ctrlquadr_init (SPCtrlQuadr *ctrlquadr);
static void sp_ctrlquadr_destroy(SPCanvasItem *object);
static void sp_ctrlquadr_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags);
static void sp_ctrlquadr_render (SPCanvasItem *item, SPCanvasBuf *buf);
-static SPCanvasItemClass *parent_class;
-
-GType
-sp_ctrlquadr_get_type (void)
-{
- static GType type = 0;
- if (!type) {
- GTypeInfo info = {
- sizeof(SPCtrlQuadrClass),
- NULL, NULL,
- (GClassInitFunc) sp_ctrlquadr_class_init,
- NULL, NULL,
- sizeof(SPCtrlQuadr),
- 0,
- (GInstanceInitFunc) sp_ctrlquadr_init,
- NULL
- };
- type = g_type_register_static(SP_TYPE_CANVAS_ITEM, "SPCtrlQuadr", &info, (GTypeFlags)0);
- }
- return type;
-}
+G_DEFINE_TYPE(SPCtrlQuadr, sp_ctrlquadr, SP_TYPE_CANVAS_ITEM);
static void
sp_ctrlquadr_class_init (SPCtrlQuadrClass *klass)
{
SPCanvasItemClass *item_class = SP_CANVAS_ITEM_CLASS(klass);
- parent_class = SP_CANVAS_ITEM_CLASS(g_type_class_peek_parent(klass));
-
item_class->destroy = sp_ctrlquadr_destroy;
item_class->update = sp_ctrlquadr_update;
item_class->render = sp_ctrlquadr_render;
@@ -85,8 +61,8 @@ static void sp_ctrlquadr_destroy(SPCanvasItem *object)
g_return_if_fail (object != NULL);
g_return_if_fail (SP_IS_CTRLQUADR (object));
- if (SP_CANVAS_ITEM_CLASS(parent_class)->destroy)
- (* SP_CANVAS_ITEM_CLASS(parent_class)->destroy) (object);
+ if (SP_CANVAS_ITEM_CLASS(sp_ctrlquadr_parent_class)->destroy)
+ (* SP_CANVAS_ITEM_CLASS(sp_ctrlquadr_parent_class)->destroy) (object);
}
static void
@@ -139,8 +115,8 @@ static void sp_ctrlquadr_update(SPCanvasItem *item, Geom::Affine const &affine,
item->canvas->requestRedraw((int)item->x1, (int)item->y1, (int)item->x2, (int)item->y2);
- if (parent_class->update) {
- (* parent_class->update)(item, affine, flags);
+ if (SP_CANVAS_ITEM_CLASS(sp_ctrlquadr_parent_class)->update) {
+ SP_CANVAS_ITEM_CLASS(sp_ctrlquadr_parent_class)->update(item, affine, flags);
}
sp_canvas_item_reset_bounds (item);
diff --git a/src/document-private.h b/src/document-private.h
index 4560aa28f..8e28b288b 100644
--- a/src/document-private.h
+++ b/src/document-private.h
@@ -34,6 +34,7 @@ class Event;
}
}
+typedef struct _GHashTable GHashTable;
struct SPDocumentPrivate {
typedef std::map<GQuark, SPDocument::IDChangedSignal> IDChangedSignalMap;
diff --git a/src/document-undo.cpp b/src/document-undo.cpp
index 39c8a04a0..15d5d2c70 100644
--- a/src/document-undo.cpp
+++ b/src/document-undo.cpp
@@ -44,19 +44,6 @@
* (Lauris Kaplinski)
*/
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-
-
-#if HAVE_STRING_H
-#endif
-
-
-#if HAVE_STDLIB_H
-#endif
-
#include <string>
#include <cstring>
#include "xml/repr.h"
@@ -112,7 +99,7 @@ void Inkscape::DocumentUndo::done(SPDocument *doc, const unsigned int event_type
maybeDone(doc, NULL, event_type, event_description);
}
-void Inkscape::DocumentUndo::resetKey( Inkscape::Application * /*inkscape*/, SPDesktop * /*desktop*/, GObject *base )
+void Inkscape::DocumentUndo::resetKey( InkscapeApplication * /*inkscape*/, SPDesktop * /*desktop*/, GObject *base )
{
SPDocument *doc = reinterpret_cast<SPDocument *>(base);
doc->actionkey.clear();
@@ -255,6 +242,7 @@ gboolean Inkscape::DocumentUndo::undo(SPDocument *doc)
Inkscape::Event *log=(Inkscape::Event *)doc->priv->undo->data;
doc->priv->undo = g_slist_remove (doc->priv->undo, log);
sp_repr_undo_log (log->event);
+ //doc->_updateDocument();
doc->priv->redo = g_slist_prepend (doc->priv->redo, log);
doc->setModifiedSinceSave();
diff --git a/src/document-undo.h b/src/document-undo.h
index 38e575a34..17b3de252 100644
--- a/src/document-undo.h
+++ b/src/document-undo.h
@@ -9,11 +9,10 @@ typedef struct _GObject GObject;
class SPDesktop;
class SPDocument;
+struct InkscapeApplication;
namespace Inkscape {
-struct Application;
-
class DocumentUndo
{
public:
@@ -42,7 +41,7 @@ public:
static void maybeDone(SPDocument *document, const gchar *keyconst, unsigned int event_type, Glib::ustring const &event_description);
- static void resetKey(Inkscape::Application *inkscape, SPDesktop *desktop, GObject *base);
+ static void resetKey(InkscapeApplication *inkscape, SPDesktop *desktop, GObject *base);
static void cancel(SPDocument *document);
diff --git a/src/document.cpp b/src/document.cpp
index dc7ed254c..f5269eab3 100644
--- a/src/document.cpp
+++ b/src/document.cpp
@@ -229,7 +229,6 @@ SPDocument::~SPDocument() {
// This is at the end of the destructor, because preceding code adds new orphans to the queue
collectOrphans();
- //delete this->_whiteboard_session_manager;
}
sigc::connection SPDocument::connectDestroy(sigc::signal<void>::slot_type slot)
@@ -619,7 +618,10 @@ Inkscape::Util::Quantity SPDocument::getWidth() const
void SPDocument::setWidth(const Inkscape::Util::Quantity &width)
{
- gdouble old_computed = root->width.computed;
+ Inkscape::Util::Unit const *old_units = unit_table.getUnit("px");
+ if (root->width.unit)
+ old_units = unit_table.getUnit(root->width.unit);
+ gdouble old_converted = Inkscape::Util::Quantity::convert(root->width.value, old_units, width.unit);
root->width.computed = width.value("px");
/* SVG does not support meters as a unit, so we must translate meters to
* cm when writing */
@@ -632,7 +634,7 @@ void SPDocument::setWidth(const Inkscape::Util::Quantity &width)
}
if (root->viewBox_set)
- root->viewBox.setMax(Geom::Point(root->viewBox.left() + (root->width.computed / old_computed) * root->viewBox.width(), root->viewBox.bottom()));
+ root->viewBox.setMax(Geom::Point(root->viewBox.left() + (root->width.value / old_converted) * root->viewBox.width(), root->viewBox.bottom()));
root->updateRepr();
}
@@ -657,7 +659,10 @@ Inkscape::Util::Quantity SPDocument::getHeight() const
void SPDocument::setHeight(const Inkscape::Util::Quantity &height)
{
- gdouble old_computed = root->height.computed;
+ Inkscape::Util::Unit const *old_units = unit_table.getUnit("px");
+ if (root->height.unit)
+ old_units = unit_table.getUnit(root->height.unit);
+ gdouble old_converted = Inkscape::Util::Quantity::convert(root->height.value, old_units, height.unit);
root->height.computed = height.value("px");
/* SVG does not support meters as a unit, so we must translate meters to
* cm when writing */
@@ -670,7 +675,7 @@ void SPDocument::setHeight(const Inkscape::Util::Quantity &height)
}
if (root->viewBox_set)
- root->viewBox.setMax(Geom::Point(root->viewBox.right(), root->viewBox.top() + (root->height.computed / old_computed) * root->viewBox.height()));
+ root->viewBox.setMax(Geom::Point(root->viewBox.right(), root->viewBox.top() + (root->height.value / old_converted) * root->viewBox.height()));
root->updateRepr();
}
@@ -707,7 +712,10 @@ void SPDocument::fitToRect(Geom::Rect const &rect, bool with_margins)
double const h = rect.height();
double const old_height = getHeight().value("px");
- Inkscape::Util::Unit const *px = unit_table.getUnit("px");
+ Inkscape::Util::Unit const *nv_units = unit_table.getUnit("px");
+ if (root->height.unit)
+ nv_units = unit_table.getUnit(root->height.unit);
+ SPNamedView *nv = sp_document_namedview(this, NULL);
/* in px */
double margin_top = 0.0;
@@ -715,22 +723,16 @@ void SPDocument::fitToRect(Geom::Rect const &rect, bool with_margins)
double margin_right = 0.0;
double margin_bottom = 0.0;
- SPNamedView *nv = sp_document_namedview(this, NULL);
-
if (with_margins && nv) {
if (nv != NULL) {
- gchar const * const units_abbr = nv->getAttribute("units");
- Inkscape::Util::Unit const *margin_units = NULL;
- if (units_abbr) {
- margin_units = unit_table.getUnit(units_abbr);
- }
- if (!margin_units) {
- margin_units = px;
- }
- margin_top = nv->getMarginLength("fit-margin-top",margin_units, px, w, h, false);
- margin_left = nv->getMarginLength("fit-margin-left",margin_units, px, w, h, true);
- margin_right = nv->getMarginLength("fit-margin-right",margin_units, px, w, h, true);
- margin_bottom = nv->getMarginLength("fit-margin-bottom",margin_units, px, w, h, false);
+ margin_top = nv->getMarginLength("fit-margin-top", nv_units, unit_table.getUnit("px"), w, h, false);
+ margin_left = nv->getMarginLength("fit-margin-left", nv_units, unit_table.getUnit("px"), w, h, true);
+ margin_right = nv->getMarginLength("fit-margin-right", nv_units, unit_table.getUnit("px"), w, h, true);
+ margin_bottom = nv->getMarginLength("fit-margin-bottom", nv_units, unit_table.getUnit("px"), w, h, false);
+ margin_top = Inkscape::Util::Quantity::convert(margin_top, nv_units, "px");
+ margin_left = Inkscape::Util::Quantity::convert(margin_left, nv_units, "px");
+ margin_right = Inkscape::Util::Quantity::convert(margin_right, nv_units, "px");
+ margin_bottom = Inkscape::Util::Quantity::convert(margin_bottom, nv_units, "px");
}
}
@@ -739,8 +741,8 @@ void SPDocument::fitToRect(Geom::Rect const &rect, bool with_margins)
rect.max() + Geom::Point(margin_right, margin_top));
- setWidth(Inkscape::Util::Quantity(rect_with_margins.width(), px));
- setHeight(Inkscape::Util::Quantity(rect_with_margins.height(), px));
+ setWidth(Inkscape::Util::Quantity(Inkscape::Util::Quantity::convert(rect_with_margins.width(), "px", nv_units), nv_units));
+ setHeight(Inkscape::Util::Quantity(Inkscape::Util::Quantity::convert(rect_with_margins.height(), "px", nv_units), nv_units));
Geom::Translate const tr(
Geom::Point(0, old_height - rect_with_margins.height())
@@ -1370,7 +1372,7 @@ GSList *SPDocument::getItemsAtPoints(unsigned const key, std::vector<Geom::Point
}
SPItem *SPDocument::getItemAtPoint( unsigned const key, Geom::Point const &p,
- gboolean const into_groups, SPItem *upto) const
+ bool const into_groups, SPItem *upto) const
{
g_return_val_if_fail(this->priv != NULL, NULL);
@@ -1529,7 +1531,7 @@ void SPDocument::setModifiedSinceSave(bool modified) {
/**
- * Paste SVG defs from the document retrieved from the clipboard into the active document.
+ * Paste SVG defs from the document retrieved from the clipboard or imported document into the active document.
* @param clipdoc The document to paste.
* @pre @c clipdoc != NULL and pasting into the active document is possible.
*/
@@ -1540,27 +1542,117 @@ void SPDocument::importDefs(SPDocument *source)
Inkscape::XML::Node *target_defs = this->getDefs()->getRepr();
prevent_id_clashes(source, this);
+
+ int stagger=0;
+ /* Note, "clipboard" throughout the comments means "the document that is either the clipboard
+ or an imported document", as importDefs is called in both contexts.
+
+ The order of the records in the clipboard is unpredictable and there may be both
+ forward and backwards references to other records within it. There may be definitions in
+ the clipboard that duplicate definitions in the present document OR that duplicate other
+ definitions in the clipboard. (Inkscape will not have created these, but they may be read
+ in from other SVG sources.)
+
+ There are 3 passes to clean this up:
+
+ In the first find and mark definitions in the clipboard that are duplicates of those in the
+ present document. Change the ID to "RESERVED_FOR_INKSCAPE_DUPLICATE_DEF_XXXXXXXXX".
+ (Inkscape will not reuse an ID, and the XXXXXXXXX keeps it from automatically creating new ones.)
+ References in the clipboard to the old clipboard name are converted to the name used
+ in the current document.
+
+ In the second find and mark definitions in the clipboard that are duplicates of earlier
+ definitions in the clipbard. Unfortunately this is O(n^2) and could be very slow for a large
+ SVG with thousands of definitions. As before, references are adjusted to reflect the name
+ going forward.
+
+ In the final cycle copy over those records not marked with that ID.
+
+ If an SVG file uses the special ID it will cause problems!
+
+ If this function is called because of the paste of a true clipboard the caller will have passed in a
+ COPY of the clipboard items. That is good, because this routine modifies that document. If the calling
+ behavior ever changes, so that the same document is passed in on multiple pastes, this routine will break
+ as in the following example:
+ 1. Paste clipboard containing B same as A into document containing A. Result, B is dropped
+ and all references to it will point to A.
+ 2. Paste same clipboard into a new document. It will not contain A, so there will be unsatisfied
+ references in that window.
+ */
+
+ std::string DuplicateDefString = "RESERVED_FOR_INKSCAPE_DUPLICATE_DEF";
+
+ /* First pass: remove duplicates in clipboard of definitions in document */
for (Inkscape::XML::Node *def = defs->firstChild() ; def ; def = def->next()) {
- gboolean duplicate = false;
+ /* If this clipboard has been pasted into one document, and is now being pasted into another,
+ or pasted again into the same, it will already have been processed. If we detect that then
+ skip the rest of this pass. */
+
+ Glib::ustring defid = def->attribute("id");
+ if( defid.find( DuplicateDefString ) != Glib::ustring::npos )break;
+
SPObject *src = source->getObjectByRepr(def);
// Prevent duplicates of solid swatches by checking if equivalent swatch already exists
if (src && SP_IS_GRADIENT(src)) {
- SPGradient *gr = SP_GRADIENT(src);
+ SPGradient *s_gr = SP_GRADIENT(src);
for (SPObject *trg = this->getDefs()->firstChild() ; trg ; trg = trg->getNext()) {
- if (trg && SP_IS_GRADIENT(trg) && src != trg) {
- if (gr->isEquivalent(SP_GRADIENT(trg)) &&
- gr->isAligned(SP_GRADIENT(trg))) {
- // Change object references to the existing equivalent gradient
- change_def_references(src, trg);
- duplicate = true;
- break;
+ if (trg && (src != trg) && SP_IS_GRADIENT(trg)) {
+ SPGradient *t_gr = SP_GRADIENT(trg);
+ if (t_gr && s_gr->isEquivalent(t_gr)) {
+ // Change object references to the existing equivalent gradient
+ Glib::ustring newid = trg->getId();
+ if(newid != defid){ // id could be the same if it is a second paste into the same document
+ change_def_references(src, trg);
+ }
+ gchar *longid = g_strdup_printf("%s_%9.9d", DuplicateDefString.c_str(), stagger++);
+ def->setAttribute("id", longid );
+ g_free(longid);
+ // do NOT break here, there could be more than 1 duplicate!
}
}
}
}
+ }
+
+ /* Second pass: remove duplicates in clipboard of earlier definitions in clipboard */
+ for (Inkscape::XML::Node *def = defs->firstChild() ; def ; def = def->next()) {
+ Glib::ustring defid = def->attribute("id");
+ if( defid.find( DuplicateDefString ) != Glib::ustring::npos )continue; // this one already handled
+ SPObject *src = source->getObjectByRepr(def);
+ if (src && SP_IS_GRADIENT(src)) {
+ SPGradient *s_gr = SP_GRADIENT(src);
+ for (Inkscape::XML::Node *laterDef = def->next() ; laterDef ; laterDef = laterDef->next()) {
+ SPObject *trg = source->getObjectByRepr(laterDef);
+ if(trg && (src != trg) && SP_IS_GRADIENT(trg)) {
+ Glib::ustring newid = trg->getId();
+ if( newid.find( DuplicateDefString ) != Glib::ustring::npos )continue; // this one already handled
+ SPGradient *t_gr = SP_GRADIENT(trg);
+ if (t_gr && s_gr->isEquivalent(t_gr)) {
+ // Change object references to the existing equivalent gradient
+ // two id's in the clipboard should never be the same, so always change references
+ change_def_references(trg, src);
+ gchar *longid = g_strdup_printf("%s_%9.9d", DuplicateDefString.c_str(), stagger++);
+ laterDef->setAttribute("id", longid );
+ g_free(longid);
+ // do NOT break here, there could be more than 1 duplicate!
+ }
+ }
+ }
+ }
+ }
+
+ /* Final pass: copy over those parts which are not duplicates */
+ for (Inkscape::XML::Node *def = defs->firstChild() ; def ; def = def->next()) {
+
+ /* Ignore duplicate defs marked in the first pass */
+ Glib::ustring defid = def->attribute("id");
+ if( defid.find( DuplicateDefString ) != Glib::ustring::npos )continue;
+
+ bool duplicate = false;
+ SPObject *src = source->getObjectByRepr(def);
// Prevent duplication of symbols... could be more clever.
// The tag "_inkscape_duplicate" is added to "id" by ClipboardManagerImpl::copySymbol().
@@ -1597,7 +1689,6 @@ void SPDocument::importDefs(SPDocument *source)
Inkscape::GC::release(dup);
}
}
-
}
/*
diff --git a/src/document.h b/src/document.h
index ee903449d..4ace249ae 100644
--- a/src/document.h
+++ b/src/document.h
@@ -75,8 +75,8 @@ class SPDocument : public Inkscape::GC::Managed<>,
public:
typedef sigc::signal<void, SPObject *> IDChangedSignal;
typedef sigc::signal<void> ResourcesChangedSignal;
- typedef sigc::signal<void, guint> ModifiedSignal;
- typedef sigc::signal<void, gchar const *> URISetSignal;
+ typedef sigc::signal<void, unsigned> ModifiedSignal;
+ typedef sigc::signal<void, char const *> URISetSignal;
typedef sigc::signal<void, double, double> ResizedSignal;
typedef sigc::signal<void> ReconstructionStart;
typedef sigc::signal<void> ReconstructionFinish;
@@ -100,9 +100,9 @@ public:
CRCascade *style_cascade;
protected:
- gchar *uri; ///< A filename (not a URI yet), or NULL
- gchar *base; ///< To be used for resolving relative hrefs.
- gchar *name; ///< basename(uri) or other human-readable label for the document.
+ char *uri; ///< A filename (not a URI yet), or NULL
+ char *base; ///< To be used for resolving relative hrefs.
+ char *name; ///< basename(uri) or other human-readable label for the document.
public:
@@ -112,10 +112,10 @@ public:
Glib::ustring actionkey;
/// Handler ID
- guint modified_id;
+ unsigned modified_id;
/// Connector rerouting handler ID
- guint rerouting_handler_id;
+ unsigned rerouting_handler_id;
Inkscape::ProfileManager* profileManager;
@@ -137,15 +137,15 @@ public:
Inkscape::XML::Document const *getReprDoc() const { return rdoc; }
/** A filename (not a URI yet), or NULL */
- gchar const *getURI() const { return uri; }
- void setUri(gchar const *uri);
+ char const *getURI() const { return uri; }
+ void setUri(char const *uri);
/** To be used for resolving relative hrefs. */
- gchar const *getBase() const { return base; };
- void setBase( gchar const* base );
+ char const *getBase() const { return base; };
+ void setBase( char const* base );
/** basename(uri) or other human-readable label for the document. */
- gchar const* getName() const { return name; }
+ char const* getName() const { return name; }
/** Return the main defs object for the document. */
SPDefs *getDefs();
@@ -173,10 +173,10 @@ public:
sigc::connection connectResized(ResizedSignal::slot_type slot);
sigc::connection connectCommit(CommitSignal::slot_type slot);
- void bindObjectToId(gchar const *id, SPObject *object);
+ void bindObjectToId(char const *id, SPObject *object);
SPObject *getObjectById(Glib::ustring const &id) const;
- SPObject *getObjectById(gchar const *id) const;
- sigc::connection connectIdChanged(const gchar *id, IDChangedSignal::slot_type slot);
+ SPObject *getObjectById(char const *id) const;
+ sigc::connection connectIdChanged(const char *id, IDChangedSignal::slot_type slot);
void bindObjectToRepr(Inkscape::XML::Node *repr, SPObject *object);
SPObject *getObjectByRepr(Inkscape::XML::Node *repr) const;
@@ -222,12 +222,12 @@ public:
sigc::connection _selection_changed_connection;
sigc::connection _desktop_activated_connection;
- sigc::connection connectResourcesChanged(const gchar *key, SPDocument::ResourcesChangedSignal::slot_type slot);
+ sigc::connection connectResourcesChanged(char const *key, SPDocument::ResourcesChangedSignal::slot_type slot);
void fitToRect(Geom::Rect const &rect, bool with_margins = false);
- static SPDocument *createNewDoc(const gchar *uri, unsigned int keepalive,
+ static SPDocument *createNewDoc(char const*uri, unsigned int keepalive,
bool make_new = false, SPDocument *parent=NULL );
- static SPDocument *createNewDocFromMem(const gchar *buffer, gint length, unsigned int keepalive);
+ static SPDocument *createNewDocFromMem(char const*buffer, int length, unsigned int keepalive);
SPDocument *createChildDoc(std::string const &uri);
/**
@@ -235,8 +235,8 @@ public:
*/
static SPItem *getItemFromListAtPointBottom(unsigned int dkey, SPGroup *group, const GSList *list, Geom::Point const &p, bool take_insensitive = false);
- static SPDocument *createDoc(Inkscape::XML::Document *rdoc, gchar const *uri,
- gchar const *base, gchar const *name, unsigned int keepalive,
+ static SPDocument *createDoc(Inkscape::XML::Document *rdoc, char const *uri,
+ char const *base, char const *name, unsigned int keepalive,
SPDocument *parent);
SPDocument *doRef();
@@ -250,25 +250,25 @@ public:
void setHeight(const Inkscape::Util::Quantity &height);
void setViewBox(const Geom::Rect &viewBox);
void requestModified();
- gint ensureUpToDate();
- bool addResource(const gchar *key, SPObject *object);
- bool removeResource(const gchar *key, SPObject *object);
- const GSList *getResourceList(const gchar *key) const;
+ int ensureUpToDate();
+ bool addResource(char const *key, SPObject *object);
+ bool removeResource(char const *key, SPObject *object);
+ const GSList *getResourceList(char const *key) const;
GSList *getItemsInBox(unsigned int dkey, Geom::Rect const &box) const;
GSList *getItemsPartiallyInBox(unsigned int dkey, Geom::Rect const &box) const;
- SPItem *getItemAtPoint(unsigned int key, Geom::Point const &p, gboolean into_groups, SPItem *upto = NULL) const;
+ SPItem *getItemAtPoint(unsigned int key, Geom::Point const &p, bool into_groups, SPItem *upto = NULL) const;
GSList *getItemsAtPoints(unsigned const key, std::vector<Geom::Point> points) const;
SPItem *getGroupAtPoint(unsigned int key, Geom::Point const &p) const;
- void changeUriAndHrefs(gchar const *uri);
- void emitResizedSignal(gdouble width, gdouble height);
+ void changeUriAndHrefs(char const *uri);
+ void emitResizedSignal(double width, double height);
unsigned int vacuumDocument();
void importDefs(SPDocument *source);
private:
- void do_change_uri(gchar const *const filename, bool const rebase);
+ void do_change_uri(char const *const filename, bool const rebase);
void setupViewport(SPItemCtx *ctx);
};
diff --git a/src/ege-color-prof-tracker.cpp b/src/ege-color-prof-tracker.cpp
index eca90ecb7..78ee6b8b5 100644
--- a/src/ege-color-prof-tracker.cpp
+++ b/src/ege-color-prof-tracker.cpp
@@ -273,8 +273,13 @@ void ege_color_prof_tracker_get_profile_for( guint screenNum, guint monitor, gpo
gpointer dataPos = 0;
guint dataLen = 0;
GdkDisplay* display = gdk_display_get_default();
+
+#if GTK_CHECK_VERSION(3,10,0)
+ GdkScreen* screen = (screenNum < 1) ? gdk_display_get_screen(display, screenNum) : 0;
+#else
gint numScreens = gdk_display_get_n_screens(display);
GdkScreen* screen = (screenNum < (guint)numScreens) ? gdk_display_get_screen(display, screenNum) : 0;
+#endif
if ( screen ) {
GSList* curr = tracked_screens;
@@ -494,7 +499,11 @@ GdkFilterReturn x11_win_filter(GdkXEvent *xevent,
if ( stat ) {
GdkDisplay* display = gdk_x11_lookup_xdisplay(native->xproperty.display);
if ( display ) {
+#if GTK_CHECK_VERSION(3,10,0)
+ gint screenCount = 1;
+#else
gint screenCount = gdk_display_get_n_screens(display);
+#endif
GdkScreen* targetScreen = 0;
gint i = 0;
for ( i = 0; i < screenCount; i++ ) {
diff --git a/src/event-log.h b/src/event-log.h
index 7e3ba6817..6d4112a5a 100644
--- a/src/event-log.h
+++ b/src/event-log.h
@@ -11,14 +11,6 @@
#ifndef INKSCAPE_EVENT_LOG_H
#define INKSCAPE_EVENT_LOG_H
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#if GLIBMM_DISABLE_DEPRECATED && HAVE_GLIBMM_THREADS_H
-#include <glibmm/threads.h>
-#endif
-
#include <gtkmm/treestore.h>
#include <glibmm/refptr.h>
#include <gtkmm/treeselection.h>
diff --git a/src/extension/CMakeLists.txt b/src/extension/CMakeLists.txt
index 9bc30a592..47292fd97 100644
--- a/src/extension/CMakeLists.txt
+++ b/src/extension/CMakeLists.txt
@@ -49,7 +49,6 @@ set(extension_SRC
internal/metafile-print.cpp
internal/odf.cpp
internal/latex-text-renderer.cpp
- internal/pdf-input-cairo.cpp
internal/pov-out.cpp
internal/javafx-out.cpp
internal/svg.cpp
@@ -130,9 +129,9 @@ set(extension_SRC
internal/latex-pstricks-out.h
internal/latex-pstricks.h
internal/latex-text-renderer.h
+ internal/metafile-inout.h
internal/metafile-print.h
internal/odf.h
- internal/pdf-input-cairo.h
internal/pdfinput/pdf-input.h
internal/pdfinput/pdf-parser.h
internal/pdfinput/svg-builder.h
diff --git a/src/extension/dbus/Makefile_insert b/src/extension/dbus/Makefile_insert
index 7d851715e..192651d87 100644
--- a/src/extension/dbus/Makefile_insert
+++ b/src/extension/dbus/Makefile_insert
@@ -78,7 +78,7 @@ libinkdbus_la_CFLAGS = \
$(DBUS_CFLAGS) \
$(INKSCAPE_CFLAGS) \
-I$(builddir)/extension/dbus \
- -Wall -Werror
+ -Wall
libinkdbus_la_LIBADD = \
$(DBUS_LIBS) \
diff --git a/src/extension/dbus/document-interface.cpp b/src/extension/dbus/document-interface.cpp
index 221a3e879..e3452f4ce 100644
--- a/src/extension/dbus/document-interface.cpp
+++ b/src/extension/dbus/document-interface.cpp
@@ -169,7 +169,7 @@ selection_get_center_x (Inkscape::Selection *sel){
gdouble
selection_get_center_y (Inkscape::Selection *sel){
Geom::OptRect box = sel->documentBounds(SPItem::GEOMETRIC_BBOX);
- return box ? box->midpoint()[Geom::X] : 0;
+ return box ? box->midpoint()[Geom::Y] : 0;
}
/*
diff --git a/src/extension/dependency.cpp b/src/extension/dependency.cpp
index 78012ccc8..e46b6fbd2 100644
--- a/src/extension/dependency.cpp
+++ b/src/extension/dependency.cpp
@@ -57,14 +57,22 @@ Dependency::Dependency (Inkscape::XML::Node * in_repr)
Inkscape::GC::anchor(_repr);
- const gchar * location = _repr->attribute("location");
- for (int i = 0; i < LOCATION_CNT && location != NULL; i++) {
- if (!strcmp(location, _location_str[i])) {
- _location = (location_t)i;
- break;
+ if (const gchar * location = _repr->attribute("location")) {
+ for (int i = 0; i < LOCATION_CNT && location != NULL; i++) {
+ if (!strcmp(location, _location_str[i])) {
+ _location = (location_t)i;
+ break;
+ }
+ }
+ } else if (const gchar * location = _repr->attribute("reldir")) {
+ for (int i = 0; i < LOCATION_CNT && location != NULL; i++) {
+ if (!strcmp(location, _location_str[i])) {
+ _location = (location_t)i;
+ break;
+ }
}
}
-
+
const gchar * type = _repr->attribute("type");
for (int i = 0; i < TYPE_CNT && type != NULL; i++) {
if (!strcmp(type, _type_str[i])) {
diff --git a/src/extension/extension.cpp b/src/extension/extension.cpp
index d63ec7485..6a22eb585 100644
--- a/src/extension/extension.cpp
+++ b/src/extension/extension.cpp
@@ -111,6 +111,14 @@ Extension::Extension (Inkscape::XML::Node * in_repr, Implementation::Implementat
if (!strcmp(chname, "dependency")) {
_deps.push_back(new Dependency(child_repr));
} /* dependency */
+ if (!strcmp(chname, "script")) {
+ for (Inkscape::XML::Node *child = child_repr->firstChild(); child != NULL ; child = child->next()) {
+ if (child->type() == Inkscape::XML::ELEMENT_NODE) {
+ _deps.push_back(new Dependency(child));
+ break;
+ } /* skip non-element nodes (see LP #1372200) */
+ }
+ } /* check command as a dependency (see LP #505920) */
if (!strcmp(chname, "options")) {
silent = !strcmp( child_repr->attribute("silent"), "true" );
}
@@ -262,6 +270,18 @@ Extension::check (void)
const char * inx_failure = _(" This is caused by an improper .inx file for this extension."
" An improper .inx file could have been caused by a faulty installation of Inkscape.");
+
+ // No need to include Windows only extensions
+ // See LP bug #1307554 for details - https://bugs.launchpad.net/inkscape/+bug/1307554
+#ifndef WIN32
+ const char* win_ext[] = {"com.vaxxine.print.win32"};
+ std::vector<std::string> v (win_ext, win_ext + sizeof(win_ext)/sizeof(win_ext[0]));
+ std::string ext_id(id);
+ if (std::find(v.begin(), v.end(), ext_id) != v.end()) {
+ printFailure(Glib::ustring(_("the extension is designed for Windows only.")) + inx_failure);
+ retval = false;
+ }
+#endif
if (id == NULL) {
printFailure(Glib::ustring(_("an ID was not defined for it.")) + inx_failure);
retval = false;
diff --git a/src/extension/implementation/implementation.h b/src/extension/implementation/implementation.h
index 9d679982a..fb323cd78 100644
--- a/src/extension/implementation/implementation.h
+++ b/src/extension/implementation/implementation.h
@@ -29,7 +29,7 @@ namespace Gtk {
}
class SPDocument;
-struct SPStyle;
+class SPStyle;
namespace Inkscape {
diff --git a/src/extension/implementation/script.cpp b/src/extension/implementation/script.cpp
index f0fd3711b..99c882a01 100644
--- a/src/extension/implementation/script.cpp
+++ b/src/extension/implementation/script.cpp
@@ -1,28 +1,18 @@
-/** \file
- * Code for handling extensions (i.e.\ scripts).
- */
-/*
+/**
+ * Code for handling extensions (i.e. scripts).
+ *
* Authors:
* Bryce Harrington <bryce@osdl.org>
* Ted Gould <ted@gould.cx>
* Jon A. Cruz <jon@joncruz.org>
* Abhishek Sharma
*
- * Copyright (C) 2002-2005,2007 Authors
+ * Copyright (C) 2002-2007 Authors
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#define __INKSCAPE_EXTENSION_IMPLEMENTATION_SCRIPT_C__
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#if GLIBMM_DISABLE_DEPRECATED && HAVE_GLIBMM_THREADS_H
-#include <glibmm/threads.h>
-#endif
-
+#include <glibmm.h>
#include <gtkmm/messagedialog.h>
#include <gtkmm/main.h>
#include <gtkmm/scrolledwindow.h>
@@ -32,44 +22,38 @@
#include <unistd.h>
#include <errno.h>
-#include <glib.h>
#include <glib/gstdio.h>
-#include "ui/view/view.h"
#include "desktop-handles.h"
#include "desktop.h"
-#include "selection.h"
-#include "sp-namedview.h"
-#include "io/sys.h"
-#include "preferences.h"
-#include "../system.h"
+#include "ui/dialog-events.h"
#include "extension/effect.h"
#include "extension/output.h"
#include "extension/input.h"
#include "extension/db.h"
-#include "script.h"
-#include "dialogs/dialog-events.h"
#include "inkscape.h"
+#include "io/sys.h"
+#include "preferences.h"
+#include "script.h"
+#include "selection.h"
+#include "sp-namedview.h"
+#include "extension/system.h"
+#include "ui/view/view.h"
#include "xml/node.h"
#include "xml/attribute-record.h"
#include "util/glib-list-iterators.h"
#include "path-prefix.h"
-
#ifdef WIN32
#include <windows.h>
#include <sys/stat.h>
#include "registrytool.h"
#endif
-
-
/** This is the command buffer that gets allocated from the stack */
#define BUFSIZE (255)
-
-
/* Namespaces */
namespace Inkscape {
namespace Extension {
@@ -742,12 +726,12 @@ void Script::effect(Inkscape::Extension::Effect *module,
vd->emitReconstructionStart();
copy_doc(vd->rroot, mydoc->rroot);
vd->emitReconstructionFinish();
- SPObject *layer = NULL;
-
+
// Getting the named view from the document generated by the extension
SPNamedView *nv = sp_document_namedview(mydoc, NULL);
//Check if it has a default layer set up
+ SPObject *layer = NULL;
if ( nv != NULL)
{
if( nv->default_layer_id != 0 ) {
@@ -776,19 +760,21 @@ void Script::effect(Inkscape::Extension::Effect *module,
/**
- \brief A function to take all the svg elements from one document
- and put them in another.
- \param oldroot The root node of the document to be replaced
- \param newroot The root node of the document to replace it with
-
- This function first deletes all of the data in the old document. It
- does this by creating a list of what needs to be deleted, and then
- goes through the list. This two pass approach removes issues with
- the list being change while parsing through it. Lots of nasty bugs.
-
- Then, it goes through the new document, duplicating all of the
- elements and putting them into the old document. The copy
- is then complete.
+ \brief A function to replace all the elements in an old document
+ by those from a new document.
+ document and repinserts them into an emptied old document.
+ \param oldroot The root node of the old (destination) document.
+ \param newroot The root node of the new (source) document.
+
+ This function first deletes all the elements in the old document by
+ making two pass, the first to create a list of the old elements and
+ the second to actually delete them. This two pass approach removes issues
+ with the list being change while parsing through it... lots of nasty bugs.
+
+ Then, it copies all the element in the new document into the old document.
+
+ Finally, it replaces the attributes in the root element of the old document
+ by the attributes in root of the new document.
*/
void Script::copy_doc (Inkscape::XML::Node * oldroot, Inkscape::XML::Node * newroot)
{
@@ -797,9 +783,21 @@ void Script::copy_doc (Inkscape::XML::Node * oldroot, Inkscape::XML::Node * newr
g_warning("Error on copy_doc: NULL pointer input.");
return;
}
+
+ // For copying attributes in root and in namedview
+ using Inkscape::Util::List;
+ using Inkscape::XML::AttributeRecord;
+
+ // Question: Why is the "sodipodi:namedview" special? Treating it as a normal
+ // elmement results in crashes.
+ // Seems to be a bug:
+ // http://inkscape.13.x6.nabble.com/Effect-that-modifies-the-document-properties-tt2822126.html
+
std::vector<Inkscape::XML::Node *> delete_list;
Inkscape::XML::Node * oldroot_namedview = NULL;
+ Inkscape::XML::Node * newroot_namedview = NULL;
+ // Make list
for (Inkscape::XML::Node * child = oldroot->firstChild();
child != NULL;
child = child->next()) {
@@ -814,14 +812,18 @@ void Script::copy_doc (Inkscape::XML::Node * oldroot, Inkscape::XML::Node * newr
delete_list.push_back(child);
}
}
+
+ // Unparent (delete)
for (unsigned int i = 0; i < delete_list.size(); i++) {
sp_repr_unparent(delete_list[i]);
}
+ // Copy
for (Inkscape::XML::Node * child = newroot->firstChild();
child != NULL;
child = child->next()) {
if (!strcmp("sodipodi:namedview", child->name())) {
+ newroot_namedview = child;
if (oldroot_namedview != NULL) {
for (Inkscape::XML::Node * newroot_namedview_child = child->firstChild();
newroot_namedview_child != NULL;
@@ -834,26 +836,44 @@ void Script::copy_doc (Inkscape::XML::Node * oldroot, Inkscape::XML::Node * newr
}
}
- {
- using Inkscape::Util::List;
- using Inkscape::XML::AttributeRecord;
- std::vector<gchar const *> attribs;
+ std::vector<gchar const *> attribs;
- // Make a list of all attributes of the old root node.
- for (List<AttributeRecord const> iter = oldroot->attributeList(); iter; ++iter) {
- attribs.push_back(g_quark_to_string(iter->key));
- }
+ // Must explicitly copy root attributes.
- // Delete the attributes of the old root nodes.
- for (std::vector<gchar const *>::const_iterator it = attribs.begin(); it != attribs.end(); ++it) {
- oldroot->setAttribute(*it, NULL);
- }
+ // Make a list of all attributes of the old root node.
+ for (List<AttributeRecord const> iter = oldroot->attributeList(); iter; ++iter) {
+ attribs.push_back(g_quark_to_string(iter->key));
+ }
- // Set the new attributes.
- for (List<AttributeRecord const> iter = newroot->attributeList(); iter; ++iter) {
- gchar const *name = g_quark_to_string(iter->key);
- oldroot->setAttribute(name, newroot->attribute(name));
- }
+ // Delete the attributes of the old root node.
+ for (std::vector<gchar const *>::const_iterator it = attribs.begin(); it != attribs.end(); ++it) {
+ oldroot->setAttribute(*it, NULL);
+ }
+
+ // Set the new attributes.
+ for (List<AttributeRecord const> iter = newroot->attributeList(); iter; ++iter) {
+ gchar const *name = g_quark_to_string(iter->key);
+ oldroot->setAttribute(name, newroot->attribute(name));
+ }
+
+ attribs.clear();
+
+ // Must explicitly copy namedview attributes.
+
+ // Make a list of all attributes of the old namedview node.
+ for (List<AttributeRecord const> iter = oldroot_namedview->attributeList(); iter; ++iter) {
+ attribs.push_back(g_quark_to_string(iter->key));
+ }
+
+ // Delete the attributes of the old namedview node.
+ for (std::vector<gchar const *>::const_iterator it = attribs.begin(); it != attribs.end(); ++it) {
+ oldroot_namedview->setAttribute(*it, NULL);
+ }
+
+ // Set the new attributes.
+ for (List<AttributeRecord const> iter = newroot_namedview->attributeList(); iter; ++iter) {
+ gchar const *name = g_quark_to_string(iter->key);
+ oldroot_namedview->setAttribute(name, newroot_namedview->attribute(name));
}
/** \todo Restore correct layer */
@@ -1063,4 +1083,4 @@ int Script::execute (const std::list<std::string> &in_command,
fill-column:99
End:
*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8 :
diff --git a/src/extension/implementation/script.h b/src/extension/implementation/script.h
index 270c361af..6a7d0c3b8 100644
--- a/src/extension/implementation/script.h
+++ b/src/extension/implementation/script.h
@@ -22,81 +22,30 @@
namespace Inkscape {
namespace XML {
class Node;
-}
-}
+} // namespace XML
-
-namespace Inkscape {
namespace Extension {
namespace Implementation {
-
/**
* Utility class used for loading and launching script extensions
*/
class Script : public Implementation {
-
public:
- /**
- *
- */
Script(void);
-
- /**
- *
- */
virtual ~Script();
-
-
- /**
- *
- */
virtual bool load(Inkscape::Extension::Extension *module);
-
- /**
- *
- */
virtual void unload(Inkscape::Extension::Extension *module);
-
- /**
- *
- */
virtual bool check(Inkscape::Extension::Extension *module);
ImplementationDocumentCache * newDocCache(Inkscape::Extension::Extension * ext, Inkscape::UI::View::View * view);
- /**
- *
- */
- virtual Gtk::Widget *prefs_input(Inkscape::Extension::Input *module,
- gchar const *filename);
-
- /**
- *
- */
- virtual SPDocument *open(Inkscape::Extension::Input *module,
- gchar const *filename);
-
- /**
- *
- */
+ virtual Gtk::Widget *prefs_input(Inkscape::Extension::Input *module, gchar const *filename);
+ virtual SPDocument *open(Inkscape::Extension::Input *module, gchar const *filename);
virtual Gtk::Widget *prefs_output(Inkscape::Extension::Output *module);
-
- /**
- *
- */
- virtual void save(Inkscape::Extension::Output *module,
- SPDocument *doc,
- gchar const *filename);
-
- /**
- *
- */
- virtual void effect(Inkscape::Extension::Effect *module,
- Inkscape::UI::View::View *doc,
- ImplementationDocumentCache * docCache);
-
+ virtual void save(Inkscape::Extension::Output *module, SPDocument *doc, gchar const *filename);
+ virtual void effect(Inkscape::Extension::Effect *module, Inkscape::UI::View::View *doc, ImplementationDocumentCache * docCache);
virtual bool cancelProcessing (void);
private:
@@ -105,7 +54,7 @@ private:
Glib::RefPtr<Glib::MainLoop> _main_loop;
/**
- * The command that has been dirived from
+ * The command that has been derived from
* the configuration file with appropriate directories
*/
std::list<std::string> command;
@@ -117,13 +66,10 @@ private:
*/
Glib::ustring helper_extension;
- std::string solve_reldir (Inkscape::XML::Node *reprin);
- bool check_existence (const std::string &command);
- void copy_doc (Inkscape::XML::Node * olddoc,
- Inkscape::XML::Node * newdoc);
- void checkStderr (const Glib::ustring &filename,
- Gtk::MessageType type,
- const Glib::ustring &message);
+ std::string solve_reldir(Inkscape::XML::Node *repr_in);
+ bool check_existence (std::string const& command);
+ void copy_doc(Inkscape::XML::Node * olddoc, Inkscape::XML::Node * newdoc);
+ void checkStderr (Glib::ustring const& filename, Gtk::MessageType type, Glib::ustring const& message);
class file_listener {
Glib::ustring _string;
@@ -140,6 +86,7 @@ private:
bool isDead () { return _dead; }
+ // TODO move these definitions into script.cpp
void init (int fd, Glib::RefPtr<Glib::MainLoop> main) {
_channel = Glib::IOChannel::create_from_fd(fd);
_channel->set_encoding();
@@ -202,11 +149,6 @@ private:
std::string resolveInterpreterExecutable(const Glib::ustring &interpNameArg);
}; // class Script
-
-
-
-
-
} // namespace Implementation
} // namespace Extension
} // namespace Inkscape
diff --git a/src/extension/implementation/xslt.cpp b/src/extension/implementation/xslt.cpp
index bcea06cb5..85ae9efde 100644
--- a/src/extension/implementation/xslt.cpp
+++ b/src/extension/implementation/xslt.cpp
@@ -20,6 +20,7 @@
#include "xslt.h"
#include "../extension.h"
#include "../output.h"
+#include "extension/input.h"
#include "xml/repr.h"
#include "io/sys.h"
@@ -53,8 +54,7 @@ XSLT::XSLT(void) :
{
}
-Glib::ustring
-XSLT::solve_reldir(Inkscape::XML::Node *reprin) {
+Glib::ustring XSLT::solve_reldir(Inkscape::XML::Node *reprin) {
gchar const *s = reprin->attribute("reldir");
@@ -90,8 +90,7 @@ XSLT::solve_reldir(Inkscape::XML::Node *reprin) {
return "";
}
-bool
-XSLT::check(Inkscape::Extension::Extension *module)
+bool XSLT::check(Inkscape::Extension::Extension *module)
{
if (load(module)) {
unload(module);
@@ -101,8 +100,7 @@ XSLT::check(Inkscape::Extension::Extension *module)
}
}
-bool
-XSLT::load(Inkscape::Extension::Extension *module)
+bool XSLT::load(Inkscape::Extension::Extension *module)
{
if (module->loaded()) { return true; }
@@ -130,8 +128,7 @@ XSLT::load(Inkscape::Extension::Extension *module)
return true;
}
-void
-XSLT::unload(Inkscape::Extension::Extension *module)
+void XSLT::unload(Inkscape::Extension::Extension *module)
{
if (!module->loaded()) { return; }
xsltFreeStylesheet(_stylesheet);
@@ -139,8 +136,8 @@ XSLT::unload(Inkscape::Extension::Extension *module)
return;
}
-SPDocument *
-XSLT::open(Inkscape::Extension::Input */*module*/, gchar const *filename)
+SPDocument * XSLT::open(Inkscape::Extension::Input */*module*/,
+ gchar const *filename)
{
xmlDocPtr filein = xmlParseFile(filename);
if (filein == NULL) { return NULL; }
@@ -184,8 +181,7 @@ XSLT::open(Inkscape::Extension::Input */*module*/, gchar const *filename)
return doc;
}
-void
-XSLT::save(Inkscape::Extension::Output */*module*/, SPDocument *doc, gchar const *filename)
+void XSLT::save(Inkscape::Extension::Output *module, SPDocument *doc, gchar const *filename)
{
/* TODO: Should we assume filename to be in utf8 or to be a raw filename?
* See JavaFXOutput::save for discussion. */
@@ -214,10 +210,24 @@ XSLT::save(Inkscape::Extension::Output */*module*/, SPDocument *doc, gchar const
return;
}
- const char * params[1];
- params[0] = NULL;
+ std::list<std::string> params;
+ module->paramListString(params);
+ const int max_parameters = params.size() * 2;
+ const char * xslt_params[max_parameters+1] ;
+
+ int count = 0;
+ for(std::list<std::string>::iterator t=params.begin(); t != params.end(); ++t) {
+ std::size_t pos = t->find("=");
+ std::ostringstream parameter;
+ std::ostringstream value;
+ parameter << t->substr(2,pos-2);
+ value << t->substr(pos+1);
+ xslt_params[count++] = g_strdup_printf("%s", parameter.str().c_str());
+ xslt_params[count++] = g_strdup_printf("'%s'", value.str().c_str());
+ }
+ xslt_params[count] = NULL;
- xmlDocPtr newdoc = xsltApplyStylesheet(_stylesheet, svgdoc, params);
+ xmlDocPtr newdoc = xsltApplyStylesheet(_stylesheet, svgdoc, xslt_params);
//xmlSaveFile(filename, newdoc);
int success = xsltSaveResultToFilename(filename, newdoc, _stylesheet, 0);
diff --git a/src/extension/init.cpp b/src/extension/init.cpp
index 0ff4b79c4..912d58a13 100644
--- a/src/extension/init.cpp
+++ b/src/extension/init.cpp
@@ -19,9 +19,6 @@
#ifdef HAVE_POPPLER
# include "internal/pdfinput/pdf-input.h"
#endif
-#ifdef HAVE_POPPLER_GLIB
-# include "internal/pdf-input-cairo.h"
-#endif
#include "path-prefix.h"
@@ -174,11 +171,6 @@ init()
#ifdef HAVE_POPPLER
Internal::PdfInput::init();
#endif
-#ifdef HAVE_POPPLER_GLIB
- if (1) {
- Internal::PdfInputCairo::init();
- }
-#endif
Internal::PrintEmf::init();
Internal::Emf::init();
Internal::PrintWmf::init();
diff --git a/src/extension/input.h b/src/extension/input.h
index b01ffeb86..2a0a177a0 100644
--- a/src/extension/input.h
+++ b/src/extension/input.h
@@ -14,9 +14,8 @@
#include <exception>
#include <glib.h>
#include "extension.h"
-#include "xml/repr.h"
-#include "document.h"
-#include <gtk/gtk.h>
+
+class SPDocument;
namespace Inkscape {
namespace Extension {
diff --git a/src/extension/internal/Makefile_insert b/src/extension/internal/Makefile_insert
index a31843114..125776d41 100644
--- a/src/extension/internal/Makefile_insert
+++ b/src/extension/internal/Makefile_insert
@@ -106,8 +106,6 @@ ink_common_sources += \
extension/internal/svg.cpp \
extension/internal/svgz.h \
extension/internal/svgz.cpp \
- extension/internal/pdf-input-cairo.cpp \
- extension/internal/pdf-input-cairo.h \
extension/internal/cairo-ps-out.h \
extension/internal/cairo-ps-out.cpp \
extension/internal/cairo-render-context.h \
diff --git a/src/extension/internal/bitmap/crop.cpp b/src/extension/internal/bitmap/crop.cpp
index 0e633afd6..02d92668b 100644
--- a/src/extension/internal/bitmap/crop.cpp
+++ b/src/extension/internal/bitmap/crop.cpp
@@ -74,7 +74,7 @@ Crop::init(void)
"<effects-menu>\n"
"<submenu name=\"" N_("Raster") "\" />\n"
"</effects-menu>\n"
- "<menu-tip>" N_("Crop selected bitmap(s).") "</menu-tip>\n"
+ "<menu-tip>" N_("Crop selected bitmap(s)") "</menu-tip>\n"
"</effect>\n"
"</inkscape-extension>\n", new Crop());
}
diff --git a/src/extension/internal/bitmap/opacity.cpp b/src/extension/internal/bitmap/opacity.cpp
index 742cb7019..f9b4bbc27 100644
--- a/src/extension/internal/bitmap/opacity.cpp
+++ b/src/extension/internal/bitmap/opacity.cpp
@@ -43,7 +43,7 @@ Opacity::init(void)
"<effects-menu>\n"
"<submenu name=\"" N_("Raster") "\" />\n"
"</effects-menu>\n"
- "<menu-tip>" N_("Modify opacity channel(s) of selected bitmap(s).") "</menu-tip>\n"
+ "<menu-tip>" N_("Modify opacity channel(s) of selected bitmap(s)") "</menu-tip>\n"
"</effect>\n"
"</inkscape-extension>\n", new Opacity());
}
diff --git a/src/extension/internal/cairo-ps-out.cpp b/src/extension/internal/cairo-ps-out.cpp
index 055a30add..d1511ba84 100644
--- a/src/extension/internal/cairo-ps-out.cpp
+++ b/src/extension/internal/cairo-ps-out.cpp
@@ -5,7 +5,7 @@
* Authors:
* Ted Gould <ted@gould.cx>
* Ulf Erikson <ulferikson@users.sf.net>
- * Adib Taraben <theAdib@yahoo.com>
+ * Adib Taraben <theAdib@gmail.com>
* Jon A. Cruz <jon@joncruz.org>
* Abhishek Sharma
*
@@ -333,7 +333,7 @@ CairoPsOutput::init (void)
"<param name=\"textToPath\" gui-text=\"" N_("Convert texts to paths") "\" type=\"boolean\">false</param>\n"
"<param name=\"textToLaTeX\" gui-text=\"" N_("PS+LaTeX: Omit text in PS, and create LaTeX file") "\" type=\"boolean\">false</param>\n"
"<param name=\"blurToBitmap\" gui-text=\"" N_("Rasterize filter effects") "\" type=\"boolean\">true</param>\n"
- "<param name=\"resolution\" gui-text=\"" N_("Resolution for rasterization (dpi):") "\" type=\"int\" min=\"1\" max=\"10000\">90</param>\n"
+ "<param name=\"resolution\" gui-text=\"" N_("Resolution for rasterization (dpi):") "\" type=\"int\" min=\"1\" max=\"10000\">96</param>\n"
"<param name=\"area\" gui-text=\"" N_("Output page size") "\" type=\"optiongroup\" >\n"
"<_option value=\"page\">" N_("Use document's page size") "</_option>"
"<_option value=\"drawing\">" N_("Use exported object's size") "</_option>"
@@ -372,7 +372,7 @@ CairoEpsOutput::init (void)
"<param name=\"textToPath\" gui-text=\"" N_("Convert texts to paths") "\" type=\"boolean\">false</param>\n"
"<param name=\"textToLaTeX\" gui-text=\"" N_("EPS+LaTeX: Omit text in EPS, and create LaTeX file") "\" type=\"boolean\">false</param>\n"
"<param name=\"blurToBitmap\" gui-text=\"" N_("Rasterize filter effects") "\" type=\"boolean\">true</param>\n"
- "<param name=\"resolution\" gui-text=\"" N_("Resolution for rasterization (dpi):") "\" type=\"int\" min=\"1\" max=\"10000\">90</param>\n"
+ "<param name=\"resolution\" gui-text=\"" N_("Resolution for rasterization (dpi):") "\" type=\"int\" min=\"1\" max=\"10000\">96</param>\n"
"<param name=\"area\" gui-text=\"" N_("Output page size") "\" type=\"optiongroup\" >\n"
"<_option value=\"page\">" N_("Use document's page size") "</_option>"
"<_option value=\"drawing\">" N_("Use exported object's size") "</_option>"
diff --git a/src/extension/internal/cairo-ps-out.h b/src/extension/internal/cairo-ps-out.h
index 7eda3c510..b438b55b4 100644
--- a/src/extension/internal/cairo-ps-out.h
+++ b/src/extension/internal/cairo-ps-out.h
@@ -5,7 +5,7 @@
* Authors:
* Ted Gould <ted@gould.cx>
* Ulf Erikson <ulferikson@users.sf.net>
- * Adib Taraben <theAdib@yahoo.com>
+ * Adib Taraben <theAdib@gmail.com>
* Abhishek Sharma
*
* Copyright (C) 2004-2006 Authors
diff --git a/src/extension/internal/cairo-render-context.cpp b/src/extension/internal/cairo-render-context.cpp
index c09b8e9c8..d76c187a2 100644
--- a/src/extension/internal/cairo-render-context.cpp
+++ b/src/extension/internal/cairo-render-context.cpp
@@ -39,6 +39,7 @@
#include "sp-item.h"
#include "sp-item-group.h"
#include "style.h"
+#include "sp-hatch.h"
#include "sp-linear-gradient.h"
#include "sp-radial-gradient.h"
#include "sp-pattern.h"
@@ -657,12 +658,12 @@ CairoRenderContext::popLayer(void)
CairoRenderContext *mask_ctx = _renderer->createContext();
// Fix Me: This is a kludge. PDF and PS output is set to 72 dpi but the
- // Cairo surface is expecting the mask to be 90 dpi.
+ // Cairo surface is expecting the mask to be 96 dpi.
float surface_width = _width;
float surface_height = _height;
if( _vector_based_target ) {
- surface_width *= 1.25;
- surface_height *= 1.25;
+ surface_width *= 4.0/3.0;
+ surface_height *= 4.0/3.0;
}
if (!mask_ctx->setupSurface( surface_width, surface_height )) {
TRACE(("mask: setupSurface failed\n"));
@@ -1130,6 +1131,83 @@ CairoRenderContext::_createPatternPainter(SPPaintServer const *const paintserver
}
cairo_pattern_t*
+CairoRenderContext::_createHatchPainter(SPPaintServer const *const paintserver, Geom::OptRect const &pbox) {
+ SPHatch const *hatch = dynamic_cast<SPHatch const *>(paintserver);
+ g_assert( hatch );
+
+ g_assert(hatch->pitch() > 0);
+
+ // create drawing and group
+ Inkscape::Drawing drawing;
+ unsigned dkey = SPItem::display_key_new(1);
+
+ // TODO need to refactor 'evil' referenced code for const correctness.
+ SPHatch *evil = const_cast<SPHatch *>(hatch);
+ evil->show(drawing, dkey, pbox);
+
+ SPHatch::RenderInfo render_info = hatch->calculateRenderInfo(dkey);
+ Geom::Rect tile_rect = render_info.tile_rect;
+
+ // Cairo requires an integer pattern surface width/height.
+ // Subtract 0.5 to prevent small rounding errors from increasing pattern size by one pixel.
+ // Multiply by SUBPIX_SCALE to allow for less than a pixel precision
+ const int subpix_scale = 10;
+ double surface_width = MAX(ceil(subpix_scale * tile_rect.width() - 0.5), 1);
+ double surface_height = MAX(ceil(subpix_scale * tile_rect.height() - 0.5), 1);
+ Geom::Affine drawing_scale = Geom::Scale(surface_width / tile_rect.width(), surface_height / tile_rect.height());
+ Geom::Affine drawing_transform = Geom::Translate(-tile_rect.min()) * drawing_scale;
+
+ Geom::Affine child_transform = render_info.child_transform;
+ child_transform *= drawing_transform;
+
+ //The rendering of hatch overflow is implemented by repeated drawing
+ //of hatch paths over one strip. Within each iteration paths are moved by pitch value.
+ //The movement progresses from right to left. This gives the same result
+ //as drawing whole strips in left-to-right order.
+ gdouble overflow_right_strip = 0.0;
+ int overflow_steps = 1;
+ Geom::Affine overflow_transform;
+ if (hatch->style->overflow.computed == SP_CSS_OVERFLOW_VISIBLE) {
+ Geom::Interval bounds = hatch->bounds();
+ overflow_right_strip = floor(bounds.max() / hatch->pitch()) * hatch->pitch();
+ overflow_steps = ceil((overflow_right_strip - bounds.min()) / hatch->pitch()) + 1;
+ overflow_transform = Geom::Translate(hatch->pitch(), 0.0);
+ }
+
+ CairoRenderContext *pattern_ctx = cloneMe(surface_width, surface_height);
+ pattern_ctx->setTransform(child_transform);
+ pattern_ctx->transform(Geom::Translate(-overflow_right_strip, 0.0));
+ pattern_ctx->pushState();
+
+ std::vector<SPHatchPath *> children(evil->hatchPaths());
+
+ for (int i = 0; i < overflow_steps; i++) {
+ for (std::vector<SPHatchPath *>::iterator iter = children.begin(); iter != children.end(); iter++) {
+ SPHatchPath *path = *iter;
+ _renderer->renderHatchPath(pattern_ctx, *path, dkey);
+ }
+ pattern_ctx->transform(overflow_transform);
+ }
+
+ pattern_ctx->popState();
+
+ // setup a cairo_pattern_t
+ cairo_surface_t *pattern_surface = pattern_ctx->getSurface();
+ TEST(pattern_ctx->saveAsPng("hatch.png"));
+ cairo_pattern_t *result = cairo_pattern_create_for_surface(pattern_surface);
+ cairo_pattern_set_extend(result, CAIRO_EXTEND_REPEAT);
+
+ Geom::Affine pattern_transform;
+ pattern_transform = render_info.pattern_to_user_transform.inverse() * drawing_transform;
+ ink_cairo_pattern_set_matrix(result, pattern_transform);
+
+ evil->hide(dkey);
+
+ delete pattern_ctx;
+ return result;
+}
+
+cairo_pattern_t*
CairoRenderContext::_createPatternForPaintServer(SPPaintServer const *const paintserver,
Geom::OptRect const &pbox, float alpha)
{
@@ -1182,8 +1260,9 @@ CairoRenderContext::_createPatternForPaintServer(SPPaintServer const *const pain
cairo_pattern_add_color_stop_rgba(pattern, rg->vector.stops[i].offset, rgb[0], rgb[1], rgb[2], rg->vector.stops[i].opacity * alpha);
}
} else if (SP_IS_PATTERN (paintserver)) {
-
pattern = _createPatternPainter(paintserver, pbox);
+ } else if ( dynamic_cast<SPHatch const *>(paintserver) ) {
+ pattern = _createHatchPainter(paintserver, pbox);
} else {
return NULL;
}
@@ -1249,26 +1328,29 @@ CairoRenderContext::_setFillStyle(SPStyle const *const style, Geom::OptRect cons
TRACE(("merged op=%f\n", alpha));
}
- if (style->fill.isColor()) {
- float rgb[3];
- sp_color_get_rgb_floatv(&style->fill.value.color, rgb);
+ SPPaintServer const *paint_server = style->getFillPaintServer();
+ if (paint_server && paint_server->isValid()) {
- cairo_set_source_rgba(_cr, rgb[0], rgb[1], rgb[2], alpha);
-
- } else if (!style->fill.set) { // unset fill is black
- cairo_set_source_rgba(_cr, 0, 0, 0, alpha);
-
- } else {
- g_assert( style->fill.isPaintserver()
- || SP_IS_GRADIENT(SP_STYLE_FILL_SERVER(style))
- || SP_IS_PATTERN(SP_STYLE_FILL_SERVER(style)) );
-
- cairo_pattern_t *pattern = _createPatternForPaintServer(SP_STYLE_FILL_SERVER(style), pbox, alpha);
+ g_assert(SP_IS_GRADIENT(SP_STYLE_FILL_SERVER(style))
+ || SP_IS_PATTERN(SP_STYLE_FILL_SERVER(style))
+ || dynamic_cast<SPHatch *>(SP_STYLE_FILL_SERVER(style)));
+ cairo_pattern_t *pattern = _createPatternForPaintServer(paint_server, pbox, alpha);
if (pattern) {
cairo_set_source(_cr, pattern);
cairo_pattern_destroy(pattern);
}
+ } else if (style->fill.colorSet) {
+ float rgb[3];
+ sp_color_get_rgb_floatv(&style->fill.value.color, rgb);
+
+ cairo_set_source_rgba(_cr, rgb[0], rgb[1], rgb[2], alpha);
+
+ } else { // unset fill is black
+ g_assert(!style->fill.set
+ || (paint_server && !paint_server->isValid()));
+
+ cairo_set_source_rgba(_cr, 0, 0, 0, alpha);
}
}
@@ -1279,7 +1361,7 @@ CairoRenderContext::_setStrokeStyle(SPStyle const *style, Geom::OptRect const &p
if (_state->merge_opacity)
alpha *= _state->opacity;
- if (style->stroke.isColor()) {
+ if (style->stroke.isColor() || (style->stroke.isPaintserver() && !style->getStrokePaintServer()->isValid())) {
float rgb[3];
sp_color_get_rgb_floatv(&style->stroke.value.color, rgb);
@@ -1287,7 +1369,8 @@ CairoRenderContext::_setStrokeStyle(SPStyle const *style, Geom::OptRect const &p
} else {
g_assert( style->stroke.isPaintserver()
|| SP_IS_GRADIENT(SP_STYLE_STROKE_SERVER(style))
- || SP_IS_PATTERN(SP_STYLE_STROKE_SERVER(style)) );
+ || SP_IS_PATTERN(SP_STYLE_STROKE_SERVER(style))
+ || dynamic_cast<SPHatch *>(SP_STYLE_STROKE_SERVER(style)));
cairo_pattern_t *pattern = _createPatternForPaintServer(SP_STYLE_STROKE_SERVER(style), pbox, alpha);
diff --git a/src/extension/internal/cairo-render-context.h b/src/extension/internal/cairo-render-context.h
index 8d3e63775..57d155b60 100644
--- a/src/extension/internal/cairo-render-context.h
+++ b/src/extension/internal/cairo-render-context.h
@@ -31,6 +31,9 @@
class SPClipPath;
class SPMask;
+typedef struct _PangoFont PangoFont;
+typedef struct _PangoLayout PangoLayout;
+
namespace Inkscape {
class Pixbuf;
@@ -201,6 +204,7 @@ protected:
cairo_pattern_t *_createPatternForPaintServer(SPPaintServer const *const paintserver,
Geom::OptRect const &pbox, float alpha);
cairo_pattern_t *_createPatternPainter(SPPaintServer const *const paintserver, Geom::OptRect const &pbox);
+ cairo_pattern_t *_createHatchPainter(SPPaintServer const *const paintserver, Geom::OptRect const &pbox);
unsigned int _showGlyphs(cairo_t *cr, PangoFont *font, std::vector<CairoGlyphInfo> const &glyphtext, bool is_stroke);
diff --git a/src/extension/internal/cairo-renderer-pdf-out.cpp b/src/extension/internal/cairo-renderer-pdf-out.cpp
index 0c314a576..0c4ad4f0a 100644
--- a/src/extension/internal/cairo-renderer-pdf-out.cpp
+++ b/src/extension/internal/cairo-renderer-pdf-out.cpp
@@ -250,7 +250,7 @@ CairoRendererPdfOutput::init (void)
"<param name=\"textToPath\" gui-text=\"" N_("Convert texts to paths") "\" type=\"boolean\">false</param>\n"
"<param name=\"textToLaTeX\" gui-text=\"" N_("PDF+LaTeX: Omit text in PDF, and create LaTeX file") "\" type=\"boolean\">false</param>\n"
"<param name=\"blurToBitmap\" gui-text=\"" N_("Rasterize filter effects") "\" type=\"boolean\">true</param>\n"
- "<param name=\"resolution\" gui-text=\"" N_("Resolution for rasterization (dpi):") "\" type=\"int\" min=\"1\" max=\"10000\">90</param>\n"
+ "<param name=\"resolution\" gui-text=\"" N_("Resolution for rasterization (dpi):") "\" type=\"int\" min=\"1\" max=\"10000\">96</param>\n"
"<param name=\"area\" gui-text=\"" N_("Output page size:") "\" type=\"optiongroup\" >\n"
"<_option value=\"page\">" N_("Use document's page size") "</_option>"
"<_option value=\"drawing\">" N_("Use exported object's size") "</_option>"
diff --git a/src/extension/internal/cairo-renderer.cpp b/src/extension/internal/cairo-renderer.cpp
index 6fbc85c05..5a9a28ef9 100644
--- a/src/extension/internal/cairo-renderer.cpp
+++ b/src/extension/internal/cairo-renderer.cpp
@@ -42,7 +42,7 @@
#include "sp-item.h"
#include "sp-item-group.h"
#include "style.h"
-#include "marker.h"
+#include "sp-marker.h"
#include "sp-linear-gradient.h"
#include "sp-radial-gradient.h"
#include "sp-root.h"
@@ -50,6 +50,7 @@
#include "sp-use.h"
#include "sp-text.h"
#include "sp-flowtext.h"
+#include "sp-hatch-path.h"
#include "sp-image.h"
#include "sp-symbol.h"
#include "sp-pattern.h"
@@ -146,13 +147,13 @@ Here comes the rendering part which could be put into the 'render' methods of SP
/* The below functions are copy&pasted plus slightly modified from *_invoke_print functions. */
static void sp_item_invoke_render(SPItem *item, CairoRenderContext *ctx);
-static void sp_group_render(SPItem *item, CairoRenderContext *ctx);
-static void sp_use_render(SPItem *item, CairoRenderContext *ctx);
-static void sp_shape_render(SPItem *item, CairoRenderContext *ctx);
-static void sp_text_render(SPItem *item, CairoRenderContext *ctx);
-static void sp_flowtext_render(SPItem *item, CairoRenderContext *ctx);
-static void sp_image_render(SPItem *item, CairoRenderContext *ctx);
-static void sp_symbol_render(SPItem *item, CairoRenderContext *ctx);
+static void sp_group_render(SPGroup *group, CairoRenderContext *ctx);
+static void sp_use_render(SPUse *use, CairoRenderContext *ctx);
+static void sp_shape_render(SPShape *shape, CairoRenderContext *ctx);
+static void sp_text_render(SPText *text, CairoRenderContext *ctx);
+static void sp_flowtext_render(SPFlowtext *flowtext, CairoRenderContext *ctx);
+static void sp_image_render(SPImage *image, CairoRenderContext *ctx);
+static void sp_symbol_render(SPSymbol *symbol, CairoRenderContext *ctx);
static void sp_asbitmap_render(SPItem *item, CairoRenderContext *ctx);
static void sp_shape_render_invoke_marker_rendering(SPMarker* marker, Geom::Affine tr, SPStyle* style, CairoRenderContext *ctx)
@@ -178,17 +179,15 @@ static void sp_shape_render_invoke_marker_rendering(SPMarker* marker, Geom::Affi
}
}
-static void sp_shape_render (SPItem *item, CairoRenderContext *ctx)
+static void sp_shape_render(SPShape *shape, CairoRenderContext *ctx)
{
- SPShape *shape = SP_SHAPE(item);
-
if (!shape->_curve) {
return;
}
- Geom::OptRect pbox = item->geometricBounds();
+ Geom::OptRect pbox = shape->geometricBounds();
- SPStyle* style = item->style;
+ SPStyle* style = shape->style;
Geom::PathVector const & pathv = shape->_curve->get_pathvector();
if (pathv.empty()) {
@@ -200,10 +199,12 @@ static void sp_shape_render (SPItem *item, CairoRenderContext *ctx)
// START marker
for (int i = 0; i < 2; i++) { // SP_MARKER_LOC and SP_MARKER_LOC_START
if ( shape->_marker[i] ) {
- SPMarker* marker = SP_MARKER (shape->_marker[i]);
+ SPMarker* marker = shape->_marker[i];
Geom::Affine tr;
- if (marker->orient_auto) {
+ if (marker->orient_mode == MARKER_ORIENT_AUTO) {
tr = sp_shape_marker_get_transform_at_start(pathv.begin()->front());
+ } else if (marker->orient_mode == MARKER_ORIENT_AUTO_START_REVERSE) {
+ tr = Geom::Rotate::from_degrees( 180.0 ) * sp_shape_marker_get_transform_at_start(pathv.begin()->front());
} else {
tr = Geom::Rotate::from_degrees(marker->orient) * Geom::Translate(pathv.begin()->front().pointAt(0));
}
@@ -213,14 +214,14 @@ static void sp_shape_render (SPItem *item, CairoRenderContext *ctx)
// MID marker
for (int i = 0; i < 3; i += 2) { // SP_MARKER_LOC and SP_MARKER_LOC_MID
if ( !shape->_marker[i] ) continue;
- SPMarker* marker = SP_MARKER (shape->_marker[i]);
+ SPMarker* marker = shape->_marker[i];
for(Geom::PathVector::const_iterator path_it = pathv.begin(); path_it != pathv.end(); ++path_it) {
// START position
if ( path_it != pathv.begin()
&& ! ((path_it == (pathv.end()-1)) && (path_it->size_default() == 0)) ) // if this is the last path and it is a moveto-only, there is no mid marker there
{
Geom::Affine tr;
- if (marker->orient_auto) {
+ if (marker->orient_mode != MARKER_ORIENT_ANGLE) {
tr = sp_shape_marker_get_transform_at_start(path_it->front());
} else {
tr = Geom::Rotate::from_degrees(marker->orient) * Geom::Translate(path_it->front().pointAt(0));
@@ -237,7 +238,7 @@ static void sp_shape_render (SPItem *item, CairoRenderContext *ctx)
* Loop to end_default (so including closing segment), because when a path is closed,
* there should be a midpoint marker between last segment and closing straight line segment */
Geom::Affine tr;
- if (marker->orient_auto) {
+ if (marker->orient_mode != MARKER_ORIENT_ANGLE) {
tr = sp_shape_marker_get_transform(*curve_it1, *curve_it2);
} else {
tr = Geom::Rotate::from_degrees(marker->orient) * Geom::Translate(curve_it1->pointAt(1));
@@ -253,7 +254,7 @@ static void sp_shape_render (SPItem *item, CairoRenderContext *ctx)
if ( path_it != (pathv.end()-1) && !path_it->empty()) {
Geom::Curve const &lastcurve = path_it->back_default();
Geom::Affine tr;
- if (marker->orient_auto) {
+ if (marker->orient_mode != MARKER_ORIENT_ANGLE) {
tr = sp_shape_marker_get_transform_at_end(lastcurve);
} else {
tr = Geom::Rotate::from_degrees(marker->orient) * Geom::Translate(lastcurve.pointAt(1));
@@ -265,7 +266,7 @@ static void sp_shape_render (SPItem *item, CairoRenderContext *ctx)
// END marker
for (int i = 0; i < 4; i += 3) { // SP_MARKER_LOC and SP_MARKER_LOC_END
if ( shape->_marker[i] ) {
- SPMarker* marker = SP_MARKER (shape->_marker[i]);
+ SPMarker* marker = shape->_marker[i];
/* Get reference to last curve in the path.
* For moveto-only path, this returns the "closing line segment". */
@@ -277,7 +278,7 @@ static void sp_shape_render (SPItem *item, CairoRenderContext *ctx)
Geom::Curve const &lastcurve = path_last[index];
Geom::Affine tr;
- if (marker->orient_auto) {
+ if (marker->orient_mode != MARKER_ORIENT_ANGLE) {
tr = sp_shape_marker_get_transform_at_end(lastcurve);
} else {
tr = Geom::Rotate::from_degrees(marker->orient) * Geom::Translate(lastcurve.pointAt(1));
@@ -288,26 +289,25 @@ static void sp_shape_render (SPItem *item, CairoRenderContext *ctx)
}
}
-static void sp_group_render(SPItem *item, CairoRenderContext *ctx)
+static void sp_group_render(SPGroup *group, CairoRenderContext *ctx)
{
- SPGroup *group = SP_GROUP(item);
CairoRenderer *renderer = ctx->getRenderer();
TRACE(("sp_group_render opacity: %f\n", SP_SCALE24_TO_FLOAT(item->style->opacity.value)));
GSList *l = g_slist_reverse(group->childList(false));
while (l) {
- SPObject *o = SP_OBJECT (l->data);
- if (SP_IS_ITEM(o)) {
- renderer->renderItem (ctx, SP_ITEM (o));
+ SPObject *o = reinterpret_cast<SPObject *>(l->data);
+ SPItem *item = dynamic_cast<SPItem *>(o);
+ if (item) {
+ renderer->renderItem(ctx, item);
}
l = g_slist_remove (l, o);
}
}
-static void sp_use_render(SPItem *item, CairoRenderContext *ctx)
+static void sp_use_render(SPUse *use, CairoRenderContext *ctx)
{
bool translated = false;
- SPUse *use = SP_USE(item);
CairoRenderer *renderer = ctx->getRenderer();
if ((use->x._set && use->x.computed != 0) || (use->y._set && use->y.computed != 0)) {
@@ -317,8 +317,8 @@ static void sp_use_render(SPItem *item, CairoRenderContext *ctx)
translated = true;
}
- if (use->child && SP_IS_ITEM(use->child)) {
- renderer->renderItem(ctx, SP_ITEM(use->child));
+ if (use->child) {
+ renderer->renderItem(ctx, use->child);
}
if (translated) {
@@ -326,30 +326,27 @@ static void sp_use_render(SPItem *item, CairoRenderContext *ctx)
}
}
-static void sp_text_render(SPItem *item, CairoRenderContext *ctx)
+static void sp_text_render(SPText *text, CairoRenderContext *ctx)
{
- SPText *group = SP_TEXT (item);
- group->layout.showGlyphs(ctx);
+ text->layout.showGlyphs(ctx);
}
-static void sp_flowtext_render(SPItem *item, CairoRenderContext *ctx)
+static void sp_flowtext_render(SPFlowtext *flowtext, CairoRenderContext *ctx)
{
- SPFlowtext *group = SP_FLOWTEXT(item);
- group->layout.showGlyphs(ctx);
+ flowtext->layout.showGlyphs(ctx);
}
-static void sp_image_render(SPItem *item, CairoRenderContext *ctx)
+static void sp_image_render(SPImage *image, CairoRenderContext *ctx)
{
- SPImage *image;
- int w, h;
-
- image = SP_IMAGE (item);
-
- if (!image->pixbuf) return;
- if ((image->width.computed <= 0.0) || (image->height.computed <= 0.0)) return;
+ if (!image->pixbuf) {
+ return;
+ }
+ if ((image->width.computed <= 0.0) || (image->height.computed <= 0.0)) {
+ return;
+ }
- w = image->pixbuf->width();
- h = image->pixbuf->height();
+ int w = image->pixbuf->width();
+ int h = image->pixbuf->height();
double x = image->x.computed;
double y = image->y.computed;
@@ -369,12 +366,11 @@ static void sp_image_render(SPItem *item, CairoRenderContext *ctx)
Geom::Scale s(width / (double)w, height / (double)h);
Geom::Affine t(s * tp);
- ctx->renderImage (image->pixbuf, t, item->style);
+ ctx->renderImage(image->pixbuf, t, image->style);
}
-static void sp_symbol_render(SPItem *item, CairoRenderContext *ctx)
+static void sp_symbol_render(SPSymbol *symbol, CairoRenderContext *ctx)
{
- SPSymbol *symbol = SP_SYMBOL(item);
if (!symbol->cloned) {
return;
}
@@ -409,7 +405,7 @@ static void sp_symbol_render(SPItem *item, CairoRenderContext *ctx)
ctx->transform(vb2user);
}
- sp_group_render(item, ctx);
+ sp_group_render(symbol, ctx);
ctx->popState();
}
@@ -476,7 +472,7 @@ static void sp_asbitmap_render(SPItem *item, CairoRenderContext *ctx)
double shift_x = bbox->min()[Geom::X];
double shift_y = bbox->max()[Geom::Y];
- // For default 90 dpi, snap bitmap to pixel grid
+ // For default 96 dpi, snap bitmap to pixel grid
if (res == Inkscape::Util::Quantity::convert(1, "in", "px")) {
shift_x = round (shift_x);
shift_y = -round (-shift_y); // Correct rounding despite coordinate inversion.
@@ -521,34 +517,56 @@ static void sp_item_invoke_render(SPItem *item, CairoRenderContext *ctx)
SPStyle* style = item->style;
if((ctx->getFilterToBitmap() == TRUE) && (style->filter.set != 0)) {
- return sp_asbitmap_render(item, ctx);
+ sp_asbitmap_render(item, ctx);
}
- if (SP_IS_ROOT(item)) {
+ SPRoot *root = dynamic_cast<SPRoot *>(item);
+ if (root) {
TRACE(("root\n"));
- return sp_root_render(SP_ROOT(item), ctx);
- } else if (SP_IS_SYMBOL(item)) {
- TRACE(("symbol\n"));
- return sp_symbol_render(item, ctx);
- } else if (SP_IS_GROUP(item)) {
- TRACE(("group\n"));
- return sp_group_render(item, ctx);
- } else if (SP_IS_SHAPE(item)) {
- TRACE(("shape\n"));
- return sp_shape_render(item, ctx);
- } else if (SP_IS_USE(item)) {
- TRACE(("use begin---\n"));
- sp_use_render(item, ctx);
- TRACE(("---use end\n"));
- } else if (SP_IS_TEXT(item)) {
- TRACE(("text\n"));
- return sp_text_render(item, ctx);
- } else if (SP_IS_FLOWTEXT(item)) {
- TRACE(("flowtext\n"));
- return sp_flowtext_render(item, ctx);
- } else if (SP_IS_IMAGE(item)) {
- TRACE(("image\n"));
- return sp_image_render(item, ctx);
+ sp_root_render(root, ctx);
+ } else {
+ SPSymbol *symbol = dynamic_cast<SPSymbol *>(item);
+ if (symbol) {
+ TRACE(("symbol\n"));
+ sp_symbol_render(symbol, ctx);
+ } else {
+ SPGroup *group = dynamic_cast<SPGroup *>(item);
+ if (group) {
+ TRACE(("group\n"));
+ sp_group_render(group, ctx);
+ } else {
+ SPShape *shape = dynamic_cast<SPShape *>(item);
+ if (shape) {
+ TRACE(("shape\n"));
+ sp_shape_render(shape, ctx);
+ } else {
+ SPUse *use = dynamic_cast<SPUse *>(item);
+ if (use) {
+ TRACE(("use begin---\n"));
+ sp_use_render(use, ctx);
+ TRACE(("---use end\n"));
+ } else {
+ SPText *text = dynamic_cast<SPText *>(item);
+ if (text) {
+ TRACE(("text\n"));
+ sp_text_render(text, ctx);
+ } else {
+ SPFlowtext *flowtext = dynamic_cast<SPFlowtext *>(item);
+ if (flowtext) {
+ TRACE(("flowtext\n"));
+ sp_flowtext_render(flowtext, ctx);
+ } else {
+ SPImage *image = dynamic_cast<SPImage *>(item);
+ if (image) {
+ TRACE(("image\n"));
+ sp_image_render(image, ctx);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
}
}
@@ -568,8 +586,9 @@ CairoRenderer::setStateForItem(CairoRenderContext *ctx, SPItem const *item)
// This is so because we use the image's/(flow)text's transform for positioning
// instead of explicitly specifying it and letting the renderer do the
// transformation before rendering the item.
- if (SP_IS_TEXT(item) || SP_IS_FLOWTEXT(item) || SP_IS_IMAGE(item))
+ if (dynamic_cast<SPText const *>(item) || dynamic_cast<SPFlowtext const *>(item) || dynamic_cast<SPImage const *>(item)) {
state->parent_has_userspace = TRUE;
+ }
TRACE(("setStateForItem opacity: %f\n", state->opacity));
}
@@ -596,6 +615,21 @@ void CairoRenderer::renderItem(CairoRenderContext *ctx, SPItem *item)
ctx->popState();
}
+void CairoRenderer::renderHatchPath(CairoRenderContext *ctx, SPHatchPath const &hatchPath, unsigned key) {
+ ctx->pushState();
+ ctx->setStateForStyle(hatchPath.style);
+ ctx->transform(Geom::Translate(hatchPath.offset.computed, 0));
+
+ SPCurve *curve = hatchPath.calculateRenderCurve(key);
+ Geom::PathVector const & pathv =curve->get_pathvector();
+ if (!pathv.empty()) {
+ ctx->renderPathVector(pathv, hatchPath.style, Geom::OptRect());
+ }
+
+ curve->unref();
+ ctx->popState();
+}
+
bool
CairoRenderer::setupDocument(CairoRenderContext *ctx, SPDocument *doc, bool pageBoundingBox, float bleedmargin_px, SPItem *base)
{
@@ -682,8 +716,8 @@ CairoRenderer::applyClipPath(CairoRenderContext *ctx, SPClipPath const *cp)
TRACE(("BEGIN clip\n"));
SPObject const *co = cp;
for ( SPObject const *child = co->firstChild() ; child; child = child->getNext() ) {
- if (SP_IS_ITEM(child)) {
- SPItem const *item = SP_ITEM(child);
+ SPItem const *item = dynamic_cast<SPItem const *>(child);
+ if (item) {
// combine transform of the item in clippath and the item using clippath:
Geom::Affine tempmat = item->transform * ctx->getCurrentState()->item_transform;
@@ -741,8 +775,8 @@ CairoRenderer::applyMask(CairoRenderContext *ctx, SPMask const *mask)
TRACE(("BEGIN mask\n"));
SPObject const *co = mask;
for ( SPObject const *child = co->firstChild() ; child; child = child->getNext() ) {
- if (SP_IS_ITEM(child)) {
- SPItem const *item = SP_ITEM(child);
+ SPItem const *item = dynamic_cast<SPItem const *>(child);
+ if (item) {
// TODO fix const correctness:
renderItem(ctx, const_cast<SPItem*>(item));
}
diff --git a/src/extension/internal/cairo-renderer.h b/src/extension/internal/cairo-renderer.h
index cfef6bdea..abc0447d8 100644
--- a/src/extension/internal/cairo-renderer.h
+++ b/src/extension/internal/cairo-renderer.h
@@ -29,6 +29,7 @@
class SPClipPath;
class SPMask;
+class SPHatchPath;
namespace Inkscape {
namespace Extension {
@@ -57,6 +58,7 @@ public:
/** Traverses the object tree and invokes the render methods. */
void renderItem(CairoRenderContext *ctx, SPItem *item);
+ void renderHatchPath(CairoRenderContext *ctx, SPHatchPath const &hatchPath, unsigned key);
};
// FIXME: this should be a static method of CairoRenderer
diff --git a/src/extension/internal/cdr-input.cpp b/src/extension/internal/cdr-input.cpp
index 0111ed626..3a3e2b58e 100644
--- a/src/extension/internal/cdr-input.cpp
+++ b/src/extension/internal/cdr-input.cpp
@@ -24,7 +24,21 @@
#include <cstring>
#include <libcdr/libcdr.h>
-#include <libwpd-stream/libwpd-stream.h>
+
+// TODO: Drop this check when librevenge is widespread.
+#if WITH_LIBCDR01
+ #include <librevenge-stream/librevenge-stream.h>
+
+ using librevenge::RVNGString;
+ using librevenge::RVNGFileStream;
+ using librevenge::RVNGStringVector;
+#else
+ #include <libwpd-stream/libwpd-stream.h>
+
+ typedef WPXString RVNGString;
+ typedef WPXFileStream RVNGFileStream;
+ typedef libcdr::CDRStringVector RVNGStringVector;
+#endif
#include <gtkmm/alignment.h>
#include <gtkmm/comboboxtext.h>
@@ -40,7 +54,7 @@
#include "document-undo.h"
#include "inkscape.h"
-#include "dialogs/dialog-events.h"
+#include "ui/dialog-events.h"
#include <gtk/gtk.h>
#include "ui/widget/spinbutton.h"
#include "ui/widget/frame.h"
@@ -60,7 +74,7 @@ namespace Internal {
class CdrImportDialog : public Gtk::Dialog {
public:
- CdrImportDialog(const std::vector<WPXString> &vec);
+ CdrImportDialog(const std::vector<RVNGString> &vec);
virtual ~CdrImportDialog();
bool showDialog();
@@ -86,12 +100,12 @@ private:
class Gtk::VBox * vbox2;
class Gtk::Widget * _previewArea;
- const std::vector<WPXString> &_vec; // Document to be imported
+ const std::vector<RVNGString> &_vec; // Document to be imported
unsigned _current_page; // Current selected page
int _preview_width, _preview_height; // Size of the preview area
};
-CdrImportDialog::CdrImportDialog(const std::vector<WPXString> &vec)
+CdrImportDialog::CdrImportDialog(const std::vector<RVNGString> &vec)
: _vec(vec), _current_page(1)
{
int num_pages = _vec.size();
@@ -139,9 +153,15 @@ CdrImportDialog::CdrImportDialog(const std::vector<WPXString> &vec)
_labelTotalPages->set_use_markup(false);
_labelTotalPages->set_selectable(false);
vbox2->pack_start(*_previewArea, Gtk::PACK_SHRINK, 0);
+#if WITH_GTKMM_3_0
+ this->get_content_area()->set_homogeneous(false);
+ this->get_content_area()->set_spacing(0);
+ this->get_content_area()->pack_start(*vbox2);
+#else
this->get_vbox()->set_homogeneous(false);
this->get_vbox()->set_spacing(0);
this->get_vbox()->pack_start(*vbox2);
+#endif
this->set_title(_("Page Selector"));
this->set_modal(true);
sp_transientize(GTK_WIDGET(this->gobj())); //Make transient
@@ -210,14 +230,20 @@ void CdrImportDialog::_setPreviewPage(unsigned page)
SPDocument *CdrInput::open(Inkscape::Extension::Input * /*mod*/, const gchar * uri)
{
- WPXFileStream input(uri);
+ RVNGFileStream input(uri);
if (!libcdr::CDRDocument::isSupported(&input)) {
return NULL;
}
- libcdr::CDRStringVector output;
+ RVNGStringVector output;
+#if WITH_LIBCDR01
+ librevenge::RVNGSVGDrawingGenerator generator(output, "svg");
+
+ if (!libcdr::CDRDocument::parse(&input, &generator)) {
+#else
if (!libcdr::CDRDocument::generateSVG(&input, output)) {
+#endif
return NULL;
}
@@ -225,9 +251,9 @@ SPDocument *CdrInput::open(Inkscape::Extension::Input * /*mod*/, const gchar * u
return NULL;
}
- std::vector<WPXString> tmpSVGOutput;
+ std::vector<RVNGString> tmpSVGOutput;
for (unsigned i=0; i<output.size(); ++i) {
- WPXString tmpString("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n");
+ RVNGString tmpString("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n");
tmpString.append(output[i]);
tmpSVGOutput.push_back(tmpString);
}
diff --git a/src/extension/internal/emf-inout.cpp b/src/extension/internal/emf-inout.cpp
index eae3bfb5a..4b070cbaa 100644
--- a/src/extension/internal/emf-inout.cpp
+++ b/src/extension/internal/emf-inout.cpp
@@ -27,15 +27,14 @@
# include "config.h"
#endif
-//#include <png.h> //This must precede text_reassemble.h or it blows up in pngconf.h when compiling
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <libuemf/symbol_convert.h>
-#include "sp-root.h"
+#include "document.h"
+#include "sp-root.h" // even though it is included indirectly by wmf-inout.h
#include "sp-path.h"
-#include "style.h"
#include "print.h"
#include "extension/system.h"
#include "extension/print.h"
@@ -45,12 +44,9 @@
#include "display/drawing.h"
#include "display/drawing-item.h"
#include "clear-n_.h"
-#include "document.h"
-#include "util/units.h"
-#include "shape-editor.h"
-#include "sp-namedview.h"
-#include "document-undo.h"
-#include "inkscape.h"
+#include "svg/svg.h"
+#include "util/units.h" // even though it is included indirectly by wmf-inout.h
+#include "inkscape.h" // even though it is included indirectly by wmf-inout.h
#include "emf-print.h"
#include "emf-inout.h"
@@ -65,10 +61,9 @@ namespace Inkscape {
namespace Extension {
namespace Internal {
-static U_RECTL rc_old = rectl_set(pointl_set(-1,-1),pointl_set(-1,-1));
-static bool clipset = false;
static uint32_t ICMmode = 0; // not used yet, but code to read it from EMF implemented
static uint32_t BLTmode = 0;
+float faraway = 10000000; // used in "exclude" clips, hopefully well outside any real drawing!
Emf::Emf (void) // The null constructor
{
@@ -273,54 +268,54 @@ uint32_t Emf::add_hatch(PEMF_CALLBACK_DATA d, uint32_t hatchType, U_COLORREF hat
if(d->hatches.count == d->hatches.size){ enlarge_hatches(d); }
d->hatches.strings[d->hatches.count++]=strdup(hpathname);
- *(d->defs) += "\n";
+ d->defs += "\n";
switch(hatchType){
case U_HS_HORIZONTAL:
- *(d->defs) += " <path id=\"";
- *(d->defs) += hpathname;
- *(d->defs) += "\" d=\"M 0 0 6 0\" style=\"fill:none;stroke:#";
- *(d->defs) += tmpcolor;
- *(d->defs) += "\" />\n";
+ d->defs += " <path id=\"";
+ d->defs += hpathname;
+ d->defs += "\" d=\"M 0 0 6 0\" style=\"fill:none;stroke:#";
+ d->defs += tmpcolor;
+ d->defs += "\" />\n";
break;
case U_HS_VERTICAL:
- *(d->defs) += " <path id=\"";
- *(d->defs) += hpathname;
- *(d->defs) += "\" d=\"M 0 0 0 6\" style=\"fill:none;stroke:#";
- *(d->defs) += tmpcolor;
- *(d->defs) += "\" />\n";
+ d->defs += " <path id=\"";
+ d->defs += hpathname;
+ d->defs += "\" d=\"M 0 0 0 6\" style=\"fill:none;stroke:#";
+ d->defs += tmpcolor;
+ d->defs += "\" />\n";
break;
case U_HS_FDIAGONAL:
- *(d->defs) += " <line id=\"sub";
- *(d->defs) += hpathname;
- *(d->defs) += "\" x1=\"-1\" y1=\"-1\" x2=\"7\" y2=\"7\" stroke=\"#";
- *(d->defs) += tmpcolor;
- *(d->defs) += "\"/>\n";
+ d->defs += " <line id=\"sub";
+ d->defs += hpathname;
+ d->defs += "\" x1=\"-1\" y1=\"-1\" x2=\"7\" y2=\"7\" stroke=\"#";
+ d->defs += tmpcolor;
+ d->defs += "\"/>\n";
break;
case U_HS_BDIAGONAL:
- *(d->defs) += " <line id=\"sub";
- *(d->defs) += hpathname;
- *(d->defs) += "\" x1=\"-1\" y1=\"7\" x2=\"7\" y2=\"-1\" stroke=\"#";
- *(d->defs) += tmpcolor;
- *(d->defs) += "\"/>\n";
+ d->defs += " <line id=\"sub";
+ d->defs += hpathname;
+ d->defs += "\" x1=\"-1\" y1=\"7\" x2=\"7\" y2=\"-1\" stroke=\"#";
+ d->defs += tmpcolor;
+ d->defs += "\"/>\n";
break;
case U_HS_CROSS:
- *(d->defs) += " <path id=\"";
- *(d->defs) += hpathname;
- *(d->defs) += "\" d=\"M 0 0 6 0 M 0 0 0 6\" style=\"fill:none;stroke:#";
- *(d->defs) += tmpcolor;
- *(d->defs) += "\" />\n";
+ d->defs += " <path id=\"";
+ d->defs += hpathname;
+ d->defs += "\" d=\"M 0 0 6 0 M 0 0 0 6\" style=\"fill:none;stroke:#";
+ d->defs += tmpcolor;
+ d->defs += "\" />\n";
break;
case U_HS_DIAGCROSS:
- *(d->defs) += " <line id=\"subfd";
- *(d->defs) += hpathname;
- *(d->defs) += "\" x1=\"-1\" y1=\"-1\" x2=\"7\" y2=\"7\" stroke=\"#";
- *(d->defs) += tmpcolor;
- *(d->defs) += "\"/>\n";
- *(d->defs) += " <line id=\"subbd";
- *(d->defs) += hpathname;
- *(d->defs) += "\" x1=\"-1\" y1=\"7\" x2=\"7\" y2=\"-1\" stroke=\"#";
- *(d->defs) += tmpcolor;
- *(d->defs) += "\"/>\n";
+ d->defs += " <line id=\"subfd";
+ d->defs += hpathname;
+ d->defs += "\" x1=\"-1\" y1=\"-1\" x2=\"7\" y2=\"7\" stroke=\"#";
+ d->defs += tmpcolor;
+ d->defs += "\"/>\n";
+ d->defs += " <line id=\"subbd";
+ d->defs += hpathname;
+ d->defs += "\" x1=\"-1\" y1=\"7\" x2=\"7\" y2=\"-1\" stroke=\"#";
+ d->defs += tmpcolor;
+ d->defs += "\"/>\n";
break;
case U_HS_SOLIDCLR:
case U_HS_DITHEREDCLR:
@@ -329,12 +324,12 @@ uint32_t Emf::add_hatch(PEMF_CALLBACK_DATA d, uint32_t hatchType, U_COLORREF hat
case U_HS_SOLIDBKCLR:
case U_HS_DITHEREDBKCLR:
default:
- *(d->defs) += " <path id=\"";
- *(d->defs) += hpathname;
- *(d->defs) += "\" d=\"M 0 0 6 0 6 6 0 6 z\" style=\"fill:#";
- *(d->defs) += tmpcolor;
- *(d->defs) += ";stroke:none";
- *(d->defs) += "\" />\n";
+ d->defs += " <path id=\"";
+ d->defs += hpathname;
+ d->defs += "\" d=\"M 0 0 6 0 6 6 0 6 z\" style=\"fill:#";
+ d->defs += tmpcolor;
+ d->defs += ";stroke:none";
+ d->defs += "\" />\n";
break;
}
}
@@ -396,12 +391,12 @@ uint32_t Emf::add_hatch(PEMF_CALLBACK_DATA d, uint32_t hatchType, U_COLORREF hat
if(!idx){ // add it if not already present
if(d->hatches.count == d->hatches.size){ enlarge_hatches(d); }
d->hatches.strings[d->hatches.count++]=strdup(hatchname);
- *(d->defs) += "\n";
- *(d->defs) += " <pattern id=\"";
- *(d->defs) += hatchname;
- *(d->defs) += "\" xlink:href=\"#EMFhbasepattern\">\n";
- *(d->defs) += refpath;
- *(d->defs) += " </pattern>\n";
+ d->defs += "\n";
+ d->defs += " <pattern id=\"";
+ d->defs += hatchname;
+ d->defs += "\" xlink:href=\"#EMFhbasepattern\">\n";
+ d->defs += refpath;
+ d->defs += " </pattern>\n";
idx = d->hatches.count;
}
}
@@ -414,12 +409,12 @@ uint32_t Emf::add_hatch(PEMF_CALLBACK_DATA d, uint32_t hatchType, U_COLORREF hat
if(d->hatches.count == d->hatches.size){ enlarge_hatches(d); }
d->hatches.strings[d->hatches.count++]=strdup(hbkname);
- *(d->defs) += "\n";
- *(d->defs) += " <rect id=\"";
- *(d->defs) += hbkname;
- *(d->defs) += "\" x=\"0\" y=\"0\" width=\"6\" height=\"6\" fill=\"#";
- *(d->defs) += bkcolor;
- *(d->defs) += "\" />\n";
+ d->defs += "\n";
+ d->defs += " <rect id=\"";
+ d->defs += hbkname;
+ d->defs += "\" x=\"0\" y=\"0\" width=\"6\" height=\"6\" fill=\"#";
+ d->defs += bkcolor;
+ d->defs += "\" />\n";
}
// this is the pattern, its name will show up in Inkscape's pattern selector
@@ -428,15 +423,15 @@ uint32_t Emf::add_hatch(PEMF_CALLBACK_DATA d, uint32_t hatchType, U_COLORREF hat
if(!idx){ // add it if not already present
if(d->hatches.count == d->hatches.size){ enlarge_hatches(d); }
d->hatches.strings[d->hatches.count++]=strdup(hatchname);
- *(d->defs) += "\n";
- *(d->defs) += " <pattern id=\"";
- *(d->defs) += hatchname;
- *(d->defs) += "\" xlink:href=\"#EMFhbasepattern\">\n";
- *(d->defs) += " <use xlink:href=\"#";
- *(d->defs) += hbkname;
- *(d->defs) += "\" />\n";
- *(d->defs) += refpath;
- *(d->defs) += " </pattern>\n";
+ d->defs += "\n";
+ d->defs += " <pattern id=\"";
+ d->defs += hatchname;
+ d->defs += "\" xlink:href=\"#EMFhbasepattern\">\n";
+ d->defs += " <use xlink:href=\"#";
+ d->defs += hbkname;
+ d->defs += "\" />\n";
+ d->defs += refpath;
+ d->defs += " </pattern>\n";
idx = d->hatches.count;
}
}
@@ -452,7 +447,7 @@ void Emf::enlarge_images(PEMF_CALLBACK_DATA d){
/* See if the image string is already in the list. If it is return its position (1->n, not 1-n-1)
*/
-int Emf::in_images(PEMF_CALLBACK_DATA d, char *test){
+int Emf::in_images(PEMF_CALLBACK_DATA d, const char *test){
int i;
for(i=0; i<d->images.count; i++){
if(strcmp(test,d->images.strings[i])==0)return(i+1);
@@ -544,35 +539,35 @@ uint32_t Emf::add_image(PEMF_CALLBACK_DATA d, void *pEmr, uint32_t cbBits, uint
sprintf(imagename,"EMFimage%d",idx++);
sprintf(xywh," x=\"0\" y=\"0\" width=\"%d\" height=\"%d\" ",width,height); // reuse this buffer
- *(d->defs) += "\n";
- *(d->defs) += " <image id=\"";
- *(d->defs) += imagename;
- *(d->defs) += "\"\n ";
- *(d->defs) += xywh;
- *(d->defs) += "\n";
- if(dibparams == U_BI_JPEG){ *(d->defs) += " xlink:href=\"data:image/jpeg;base64,"; }
- else { *(d->defs) += " xlink:href=\"data:image/png;base64,"; }
- *(d->defs) += base64String;
- *(d->defs) += "\"\n";
- *(d->defs) += " preserveAspectRatio=\"none\"\n";
- *(d->defs) += " />\n";
-
-
- *(d->defs) += "\n";
- *(d->defs) += " <pattern id=\"";
- *(d->defs) += imagename;
- *(d->defs) += "_ref\"\n ";
- *(d->defs) += xywh;
- *(d->defs) += "\n patternUnits=\"userSpaceOnUse\"";
- *(d->defs) += " >\n";
- *(d->defs) += " <use id=\"";
- *(d->defs) += imagename;
- *(d->defs) += "_ign\" ";
- *(d->defs) += " xlink:href=\"#";
- *(d->defs) += imagename;
- *(d->defs) += "\" />\n";
- *(d->defs) += " ";
- *(d->defs) += " </pattern>\n";
+ d->defs += "\n";
+ d->defs += " <image id=\"";
+ d->defs += imagename;
+ d->defs += "\"\n ";
+ d->defs += xywh;
+ d->defs += "\n";
+ if(dibparams == U_BI_JPEG){ d->defs += " xlink:href=\"data:image/jpeg;base64,"; }
+ else { d->defs += " xlink:href=\"data:image/png;base64,"; }
+ d->defs += base64String;
+ d->defs += "\"\n";
+ d->defs += " preserveAspectRatio=\"none\"\n";
+ d->defs += " />\n";
+
+
+ d->defs += "\n";
+ d->defs += " <pattern id=\"";
+ d->defs += imagename;
+ d->defs += "_ref\"\n ";
+ d->defs += xywh;
+ d->defs += "\n patternUnits=\"userSpaceOnUse\"";
+ d->defs += " >\n";
+ d->defs += " <use id=\"";
+ d->defs += imagename;
+ d->defs += "_ign\" ";
+ d->defs += " xlink:href=\"#";
+ d->defs += imagename;
+ d->defs += "\" />\n";
+ d->defs += " ";
+ d->defs += " </pattern>\n";
}
g_free(base64String);//wait until this point to free because it might be a duplicate image
@@ -596,17 +591,17 @@ uint32_t Emf::add_image(PEMF_CALLBACK_DATA d, void *pEmr, uint32_t cbBits, uint
d->images.strings[d->images.count++]=strdup(base64String);
sprintf(imrotname,"EMFimage%d",idx++);
- *(d->defs) += "\n";
- *(d->defs) += " <pattern\n";
- *(d->defs) += " id=\"";
- *(d->defs) += imrotname;
- *(d->defs) += "_ref\"\n";
- *(d->defs) += " xlink:href=\"#";
- *(d->defs) += imagename;
- *(d->defs) += "_ref\"\n";
- *(d->defs) += " patternTransform=";
- *(d->defs) += current_matrix(d, 0.0, 0.0, 0); //j use offset 0,0
- *(d->defs) += " />\n";
+ d->defs += "\n";
+ d->defs += " <pattern\n";
+ d->defs += " id=\"";
+ d->defs += imrotname;
+ d->defs += "_ref\"\n";
+ d->defs += " xlink:href=\"#";
+ d->defs += imagename;
+ d->defs += "_ref\"\n";
+ d->defs += " patternTransform=";
+ d->defs += current_matrix(d, 0.0, 0.0, 0); //j use offset 0,0
+ d->defs += " />\n";
}
g_free(base64String);
}
@@ -623,7 +618,7 @@ void Emf::enlarge_gradients(PEMF_CALLBACK_DATA d){
/* See if the gradient name is already in the list. If it is return its position (1->n, not 1-n-1)
*/
-int Emf::in_gradients(PEMF_CALLBACK_DATA d, char *test){
+int Emf::in_gradients(PEMF_CALLBACK_DATA d, const char *test){
int i;
for(i=0; i<d->gradients.count; i++){
if(strcmp(test,d->gradients.strings[i])==0)return(i+1);
@@ -716,12 +711,71 @@ uint32_t Emf::add_gradient(PEMF_CALLBACK_DATA d, uint32_t gradientType, U_TRIVER
stmp << tmpcolor2;
stmp << ";stop-opacity:1\" />\n";
stmp << " </linearGradient>\n";
- *(d->defs) += stmp.str().c_str();
+ d->defs += stmp.str().c_str();
}
return(idx-1);
}
+/* Add another 100 blank slots to the clips array.
+*/
+void Emf::enlarge_clips(PEMF_CALLBACK_DATA d){
+ d->clips.size += 100;
+ d->clips.strings = (char **) realloc(d->clips.strings,d->clips.size * sizeof(char *));
+}
+
+/* See if the pattern name is already in the list. If it is return its position (1->n, not 1-n-1)
+*/
+int Emf::in_clips(PEMF_CALLBACK_DATA d, const char *test){
+ int i;
+ for(i=0; i<d->clips.count; i++){
+ if(strcmp(test,d->clips.strings[i])==0)return(i+1);
+ }
+ return(0);
+}
+
+/* (Conditionally) add a clip.
+ If a matching clip already exists nothing happens
+ If one does exist it is added to the clips list, entered into <defs>.
+*/
+void Emf::add_clips(PEMF_CALLBACK_DATA d, const char *clippath, unsigned int logic){
+ int op = combine_ops_to_livarot(logic);
+ Geom::PathVector combined_vect;
+ char *combined = NULL;
+ if (op >= 0 && d->dc[d->level].clip_id) {
+ unsigned int real_idx = d->dc[d->level].clip_id - 1;
+ Geom::PathVector old_vect = sp_svg_read_pathv(d->clips.strings[real_idx]);
+ Geom::PathVector new_vect = sp_svg_read_pathv(clippath);
+ combined_vect = sp_pathvector_boolop(new_vect, old_vect, (bool_op) op , (FillRule) fill_oddEven, (FillRule) fill_oddEven);
+ combined = sp_svg_write_path(combined_vect);
+ }
+ else {
+ combined = strdup(clippath); // COPY operation, erases everything and starts a new one
+ }
+
+ uint32_t idx = in_clips(d, combined);
+ if(!idx){ // add clip if not already present
+ if(d->clips.count == d->clips.size){ enlarge_clips(d); }
+ d->clips.strings[d->clips.count++]=strdup(combined);
+ d->dc[d->level].clip_id = d->clips.count; // one more than the slot where it is actually stored
+ SVGOStringStream tmp_clippath;
+ tmp_clippath << "\n<clipPath";
+ tmp_clippath << "\n\tclipPathUnits=\"userSpaceOnUse\" ";
+ tmp_clippath << "\n\tid=\"clipEmfPath" << d->dc[d->level].clip_id << "\"";
+ tmp_clippath << " >";
+ tmp_clippath << "\n\t<path d=\"";
+ tmp_clippath << combined;
+ tmp_clippath << "\"";
+ tmp_clippath << "\n\t/>";
+ tmp_clippath << "\n</clipPath>";
+ d->outdef += tmp_clippath.str().c_str();
+ }
+ else {
+ d->dc[d->level].clip_id = idx;
+ }
+ free(combined);
+}
+
void
@@ -811,8 +865,8 @@ Emf::output_style(PEMF_CALLBACK_DATA d, int iType)
// tmp_id << "\n\tid=\"" << (d->id++) << "\"";
-// *(d->outsvg) += tmp_id.str().c_str();
- *(d->outsvg) += "\n\tstyle=\"";
+// d->outsvg += tmp_id.str().c_str();
+ d->outsvg += "\n\tstyle=\"";
if (iType == U_EMR_STROKEPATH || !d->dc[d->level].fill_set) {
tmp_style << "fill:none;";
} else {
@@ -932,11 +986,10 @@ Emf::output_style(PEMF_CALLBACK_DATA d, int iType)
tmp_style << "stroke-opacity:1;";
}
tmp_style << "\" ";
- if (clipset)
- tmp_style << "\n\tclip-path=\"url(#clipEmfPath" << d->id << ")\" ";
- clipset = false;
+ if (d->dc[d->level].clip_id)
+ tmp_style << "\n\tclip-path=\"url(#clipEmfPath" << d->dc[d->level].clip_id << ")\" ";
- *(d->outsvg) += tmp_style.str().c_str();
+ d->outsvg += tmp_style.str().c_str();
}
@@ -988,13 +1041,30 @@ Emf::pix_to_abs_size(PEMF_CALLBACK_DATA d, double px)
return ppx;
}
-/* returns "x,y" (without the quotes) in inkscape coordinates for a pair of EMF x,y coordinates
+/* snaps coordinate pairs made up of values near +/-faraway, +/-faraway to exactly faraway.
+ This eliminates coordinate drift on repeated clipping cycles which use exclude.
+ It should not affect internals of normal drawings because the value of faraway is so large.
+*/
+void
+Emf::snap_to_faraway_pair(double *x, double *y)
+{
+ if((abs(abs(*x) - faraway)/faraway <= 1e-4) && (abs(abs(*y) - faraway)/faraway <= 1e-4)){
+ *x = (*x > 0 ? faraway : -faraway);
+ *y = (*y > 0 ? faraway : -faraway);
+ }
+}
+
+/* returns "x,y" (without the quotes) in inkscape coordinates for a pair of EMF x,y coordinates.
+ Since exclude clip can go through here, it calls snap_to_faraway_pair for numerical stability.
*/
std::string Emf::pix_to_xy(PEMF_CALLBACK_DATA d, double x, double y){
std::stringstream cxform;
- cxform << pix_to_x_point(d,x,y);
+ double tx = pix_to_x_point(d,x,y);
+ double ty = pix_to_y_point(d,x,y);
+ snap_to_faraway_pair(&tx,&ty);
+ cxform << tx;
cxform << ",";
- cxform << pix_to_y_point(d,x,y);
+ cxform << ty;
return(cxform.str());
}
@@ -1104,14 +1174,11 @@ Emf::select_extpen(PEMF_CALLBACK_DATA d, int index)
if (!d->dc[d->level].style.stroke_dasharray.values.empty() && (d->level==0 || (d->level>0 && d->dc[d->level].style.stroke_dasharray.values!=d->dc[d->level-1].style.stroke_dasharray.values)))
d->dc[d->level].style.stroke_dasharray.values.clear();
for (unsigned int i=0; i<pEmr->elp.elpNumEntries; i++) {
- int cur_level = d->level;
- d->level = d->emf_obj[index].level;
// Doing it this way typically results in a pattern that is tiny, better to assume the array
// is the same scale as for dot/dash below, that is, no scaling should be applied
// double dash_length = pix_to_abs_size( d, pEmr->elp.elpStyleEntry[i] );
double dash_length = pEmr->elp.elpStyleEntry[i];
- d->level = cur_level;
- d->dc[d->level].style.stroke_dasharray.values[i] = dash_length;
+ d->dc[d->level].style.stroke_dasharray.values.push_back(dash_length);
}
d->dc[d->level].style.stroke_dasharray.set = 1;
} else {
@@ -1525,8 +1592,8 @@ void Emf::common_image_extraction(PEMF_CALLBACK_DATA d, void *pEmr,
tmp_image << " preserveAspectRatio=\"none\"\n";
tmp_image << "/> \n";
- *(d->outsvg) += tmp_image.str().c_str();
- *(d->path) = "";
+ d->outsvg += tmp_image.str().c_str();
+ d->path = "";
}
/**
@@ -1573,7 +1640,7 @@ int Emf::myEnhMetaFileProc(char *contents, unsigned int length, PEMF_CALLBACK_DA
lpEMFR = (PU_ENHMETARECORD)(contents + off);
// Uncomment the following to track down toxic records
-//std::cout << "record type: " << lpEMFR->iType << " length: " << lpEMFR->nSize << " offset: " << off <<std::endl;
+// std::cout << "record type: " << lpEMFR->iType << " name " << U_emr_names(lpEMFR->iType) << " length: " << lpEMFR->nSize << " offset: " << off <<std::endl;
off += lpEMFR->nSize;
SVGOStringStream tmp_outsvg;
@@ -1592,11 +1659,19 @@ int Emf::myEnhMetaFileProc(char *contents, unsigned int length, PEMF_CALLBACK_DA
// next record is valid type and forces pending text to be drawn immediately
if ((d->dc[d->level].dirty & DIRTY_TEXT) || ((emr_mask != U_EMR_INVALID) && (emr_mask & U_DRAW_TEXT) && d->tri->dirty)){
TR_layout_analyze(d->tri);
+ if (d->dc[d->level].clip_id){
+ SVGOStringStream tmp_clip;
+ tmp_clip << "\n<g\n\tclip-path=\"url(#clipEmfPath" << d->dc[d->level].clip_id << ")\"\n>";
+ d->outsvg += tmp_clip.str().c_str();
+ }
TR_layout_2_svg(d->tri);
SVGOStringStream ts;
ts << d->tri->out;
- *(d->outsvg) += ts.str().c_str();
+ d->outsvg += ts.str().c_str();
d->tri = trinfo_clear(d->tri);
+ if (d->dc[d->level].clip_id){
+ d->outsvg += "\n</g>\n";
+ }
}
if(d->dc[d->level].dirty){ //Apply the delayed background changes, clear the flag
d->dc[d->level].bkMode = tbkMode;
@@ -1624,7 +1699,7 @@ int Emf::myEnhMetaFileProc(char *contents, unsigned int length, PEMF_CALLBACK_DA
d->dc[d->level].dirty = 0;
}
-//std::cout << "BEFORE DRAW logic d->mask: " << std::hex << d->mask << " emr_mask: " << emr_mask << std::dec << std::endl;
+// std::cout << "BEFORE DRAW logic d->mask: " << std::hex << d->mask << " emr_mask: " << emr_mask << std::dec << std::endl;
/*
std::cout << "BEFORE DRAW"
<< " test0 " << ( d->mask & U_DRAW_VISIBLE)
@@ -1651,8 +1726,8 @@ std::cout << "BEFORE DRAW"
)
)
){
-// std::cout << "PATH DRAW at TOP" << std::endl;
- *(d->outsvg) += " <path "; // this is the ONLY place <path should be used!!! One exception, gradientfill.
+// std::cout << "PATH DRAW at TOP path" << *(d->path) << std::endl;
+ d->outsvg += " <path "; // this is the ONLY place <path should be used!!! One exception, gradientfill.
if(d->drawtype){ // explicit draw type EMR record
output_style(d, d->drawtype);
}
@@ -1662,11 +1737,11 @@ std::cout << "BEFORE DRAW"
else {
output_style(d, U_EMR_STROKEPATH);
}
- *(d->outsvg) += "\n\t";
- *(d->outsvg) += "\n\td=\""; // this is the ONLY place d=" should be used!!!! One exception, gradientfill.
- *(d->outsvg) += *(d->path);
- *(d->outsvg) += " \" /> \n";
- *(d->path) = "";
+ d->outsvg += "\n\t";
+ d->outsvg += "\n\td=\""; // this is the ONLY place d=" should be used!!!! One exception, gradientfill.
+ d->outsvg += d->path;
+ d->outsvg += " \" /> \n";
+ d->path = "";
// reset the flags
d->mask = 0;
d->drawtype = 0;
@@ -1679,12 +1754,12 @@ std::cout << "BEFORE DRAW"
{
dbg_str << "<!-- U_EMR_HEADER -->\n";
- *(d->outdef) += "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n";
+ d->outdef += "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n";
if (d->pDesc) {
- *(d->outdef) += "<!-- ";
- *(d->outdef) += d->pDesc;
- *(d->outdef) += " -->\n";
+ d->outdef += "<!-- ";
+ d->outdef += d->pDesc;
+ d->outdef += " -->\n";
}
PU_EMRHEADER pEmr = (PU_EMRHEADER) lpEMFR;
@@ -1745,8 +1820,8 @@ std::cout << "BEFORE DRAW"
tmp_outdef <<
" width=\"" << d->MMX << "mm\"\n" <<
" height=\"" << d->MMY << "mm\">\n";
- *(d->outdef) += tmp_outdef.str().c_str();
- *(d->outdef) += "<defs>"; // temporary end of header
+ d->outdef += tmp_outdef.str().c_str();
+ d->outdef += "<defs>"; // temporary end of header
// d->defs holds any defines which are read in.
@@ -2015,7 +2090,7 @@ std::cout << "BEFORE DRAW"
dbg_str << "<!-- U_EMR_EOF -->\n";
tmp_outsvg << "</svg>\n";
- *(d->outsvg) = *(d->outdef) + *(d->defs) + *(d->outsvg);
+ d->outsvg = d->outdef + d->defs + d->outsvg;
OK=0;
break;
}
@@ -2123,7 +2198,24 @@ std::cout << "BEFORE DRAW"
}
break;
}
- case U_EMR_OFFSETCLIPRGN: dbg_str << "<!-- U_EMR_OFFSETCLIPRGN -->\n"; break;
+ case U_EMR_OFFSETCLIPRGN:
+ {
+ dbg_str << "<!-- U_EMR_OFFSETCLIPRGN -->\n";
+ if (d->dc[d->level].clip_id) { // can only offsetan existing clipping path
+ PU_EMROFFSETCLIPRGN pEmr = (PU_EMROFFSETCLIPRGN) lpEMFR;
+ U_POINTL off = pEmr->ptlOffset;
+ unsigned int real_idx = d->dc[d->level].clip_id - 1;
+ Geom::PathVector tmp_vect = sp_svg_read_pathv(d->clips.strings[real_idx]);
+ double ox = pix_to_x_point(d, off.x, off.y) - pix_to_x_point(d, 0, 0); // take into account all active transforms
+ double oy = pix_to_y_point(d, off.x, off.y) - pix_to_y_point(d, 0, 0);
+ Geom::Affine tf = Geom::Translate(ox,oy);
+ tmp_vect *= tf;
+ char *tmp_path = sp_svg_write_path(tmp_vect);
+ add_clips(d, tmp_path, U_RGN_COPY);
+ free(tmp_path);
+ }
+ break;
+ }
case U_EMR_MOVETOEX:
{
dbg_str << "<!-- U_EMR_MOVETOEX -->\n";
@@ -2139,36 +2231,51 @@ std::cout << "BEFORE DRAW"
break;
}
case U_EMR_SETMETARGN: dbg_str << "<!-- U_EMR_SETMETARGN -->\n"; break;
- case U_EMR_EXCLUDECLIPRECT: dbg_str << "<!-- U_EMR_EXCLUDECLIPRECT -->\n"; break;
+ case U_EMR_EXCLUDECLIPRECT:
+ {
+ dbg_str << "<!-- U_EMR_EXCLUDECLIPRECT -->\n";
+
+ PU_EMREXCLUDECLIPRECT pEmr = (PU_EMREXCLUDECLIPRECT) lpEMFR;
+ U_RECTL rc = pEmr->rclClip;
+
+ SVGOStringStream tmp_path;
+ //outer rect, clockwise
+ tmp_path << "M " << faraway << "," << faraway << " ";
+ tmp_path << "L " << faraway << "," << -faraway << " ";
+ tmp_path << "L " << -faraway << "," << -faraway << " ";
+ tmp_path << "L " << -faraway << "," << faraway << " ";
+ tmp_path << "z ";
+ //inner rect, counterclockwise (sign of Y is reversed)
+ tmp_path << "M " << pix_to_xy( d, rc.left , rc.top ) << " ";
+ tmp_path << "L " << pix_to_xy( d, rc.right, rc.top ) << " ";
+ tmp_path << "L " << pix_to_xy( d, rc.right, rc.bottom ) << " ";
+ tmp_path << "L " << pix_to_xy( d, rc.left, rc.bottom ) << " ";
+ tmp_path << "z";
+
+ add_clips(d, tmp_path.str().c_str(), U_RGN_AND);
+
+ d->path = "";
+ d->drawtype = 0;
+ break;
+ }
case U_EMR_INTERSECTCLIPRECT:
{
dbg_str << "<!-- U_EMR_INTERSECTCLIPRECT -->\n";
PU_EMRINTERSECTCLIPRECT pEmr = (PU_EMRINTERSECTCLIPRECT) lpEMFR;
U_RECTL rc = pEmr->rclClip;
- clipset = true;
- if ((rc.left == rc_old.left) && (rc.top == rc_old.top) && (rc.right == rc_old.right) && (rc.bottom == rc_old.bottom))
- break;
- rc_old = rc;
- double dx = pix_to_x_point( d, rc.left, rc.top );
- double dy = pix_to_y_point( d, rc.left, rc.top );
- double dw = pix_to_abs_size( d, rc.right - rc.left + 1);
- double dh = pix_to_abs_size( d, rc.bottom - rc.top + 1);
-
- SVGOStringStream tmp_rectangle;
- tmp_rectangle << "\n<clipPath\n\tclipPathUnits=\"userSpaceOnUse\" ";
- tmp_rectangle << "\nid=\"clipEmfPath" << ++(d->id) << "\" >";
- tmp_rectangle << "\n<rect ";
- tmp_rectangle << "\n x=\"" << dx << "\" ";
- tmp_rectangle << "\n y=\"" << dy << "\" ";
- tmp_rectangle << "\n width=\"" << dw << "\" ";
- tmp_rectangle << "\n height=\"" << dh << "\" ";
- tmp_rectangle << "\n transform=" << current_matrix(d, dx, dy, 1); // calculate appropriate offset
- tmp_rectangle << "/>\n</clipPath>";
+ SVGOStringStream tmp_path;
+ tmp_path << "M " << pix_to_xy( d, rc.left , rc.top ) << " ";
+ tmp_path << "L " << pix_to_xy( d, rc.right, rc.top ) << " ";
+ tmp_path << "L " << pix_to_xy( d, rc.right, rc.bottom ) << " ";
+ tmp_path << "L " << pix_to_xy( d, rc.left, rc.bottom ) << " ";
+ tmp_path << "z";
+
+ add_clips(d, tmp_path.str().c_str(), U_RGN_AND);
- *(d->outdef) += tmp_rectangle.str().c_str();
- *(d->path) = "";
+ d->path = "";
+ d->drawtype = 0;
break;
}
case U_EMR_SCALEVIEWPORTEXTEX: dbg_str << "<!-- U_EMR_SCALEVIEWPORTEXTEX -->\n"; break;
@@ -2179,7 +2286,7 @@ std::cout << "BEFORE DRAW"
if (d->level < EMF_MAX_DC) {
d->dc[d->level + 1] = d->dc[d->level];
if(d->dc[d->level].font_name){
- d->dc[d->level + 1].font_name = strdup(d->dc[d->level].font_name); // or memory access problems because font name pointer duplicated
+ d->dc[d->level + 1].font_name = strdup(d->dc[d->level].font_name); // or memory access problems because font name pointer duplicated
}
d->level = d->level + 1;
}
@@ -2442,8 +2549,8 @@ std::cout << "BEFORE DRAW"
double cx = pix_to_x_point( d, (rclBox.left + rclBox.right)/2.0, (rclBox.bottom + rclBox.top)/2.0 );
double cy = pix_to_y_point( d, (rclBox.left + rclBox.right)/2.0, (rclBox.bottom + rclBox.top)/2.0 );
- double rx = pix_to_abs_size( d, fabs(rclBox.right - rclBox.left )/2.0 );
- double ry = pix_to_abs_size( d, fabs(rclBox.top - rclBox.bottom)/2.0 );
+ double rx = pix_to_abs_size( d, std::abs(rclBox.right - rclBox.left )/2.0 );
+ double ry = pix_to_abs_size( d, std::abs(rclBox.top - rclBox.bottom)/2.0 );
SVGOStringStream tmp_ellipse;
tmp_ellipse << "cx=\"" << cx << "\" ";
@@ -2453,12 +2560,12 @@ std::cout << "BEFORE DRAW"
d->mask |= emr_mask;
- *(d->outsvg) += " <ellipse ";
+ d->outsvg += " <ellipse ";
output_style(d, lpEMFR->iType); //
- *(d->outsvg) += "\n\t";
- *(d->outsvg) += tmp_ellipse.str().c_str();
- *(d->outsvg) += "/> \n";
- *(d->path) = "";
+ d->outsvg += "\n\t";
+ d->outsvg += tmp_ellipse.str().c_str();
+ d->outsvg += "/> \n";
+ d->path = "";
break;
}
case U_EMR_RECTANGLE:
@@ -2679,7 +2786,7 @@ std::cout << "BEFORE DRAW"
// The next line should never be needed, should have been handled before main switch
// qualifier added because EMF's encountered where moveto preceded beginpath followed by lineto
if(d->mask & U_DRAW_VISIBLE){
- *(d->path) = "";
+ d->path = "";
}
d->mask |= emr_mask;
break;
@@ -2735,11 +2842,22 @@ std::cout << "BEFORE DRAW"
}
case U_EMR_FLATTENPATH: dbg_str << "<!-- U_EMR_FLATTENPATH -->\n"; break;
case U_EMR_WIDENPATH: dbg_str << "<!-- U_EMR_WIDENPATH -->\n"; break;
- case U_EMR_SELECTCLIPPATH: dbg_str << "<!-- U_EMR_SELECTCLIPPATH -->\n"; break;
+ case U_EMR_SELECTCLIPPATH:
+ {
+ dbg_str << "<!-- U_EMR_SELECTCLIPPATH -->\n";
+ PU_EMRSELECTCLIPPATH pEmr = (PU_EMRSELECTCLIPPATH) lpEMFR;
+ int logic = pEmr->iMode;
+
+ if ((logic < U_RGN_MIN) || (logic > U_RGN_MAX)){ break; }
+ add_clips(d, d->path.c_str(), logic); // finds an existing one or stores this, sets clip_id
+ d->path = "";
+ d->drawtype = 0;
+ break;
+ }
case U_EMR_ABORTPATH:
{
dbg_str << "<!-- U_EMR_ABORTPATH -->\n";
- *(d->path) = "";
+ d->path = "";
d->drawtype = 0;
break;
}
@@ -2778,8 +2896,10 @@ std::cout << "BEFORE DRAW"
dbg_str << "<!-- U_EMR_EXTSELECTCLIPRGN -->\n";
PU_EMREXTSELECTCLIPRGN pEmr = (PU_EMREXTSELECTCLIPRGN) lpEMFR;
- if (pEmr->iMode == U_RGN_COPY)
- clipset = false;
+ // the only mode we implement - this clears the clipping region
+ if (pEmr->iMode == U_RGN_COPY) {
+ d->dc[d->level].clip_id = 0;
+ }
break;
}
case U_EMR_BITBLT:
@@ -3046,11 +3166,19 @@ std::cout << "BEFORE DRAW"
int status = trinfo_load_textrec(d->tri, &tsp, tsp.ori,TR_EMFBOT); // ori is actually escapement
if(status==-1){ // change of escapement, emit what we have and reset
TR_layout_analyze(d->tri);
+ if (d->dc[d->level].clip_id){
+ SVGOStringStream tmp_clip;
+ tmp_clip << "\n<g\n\tclip-path=\"url(#clipEmfPath" << d->dc[d->level].clip_id << ")\"\n>";
+ d->outsvg += tmp_clip.str().c_str();
+ }
TR_layout_2_svg(d->tri);
ts << d->tri->out;
- *(d->outsvg) += ts.str().c_str();
+ d->outsvg += ts.str().c_str();
d->tri = trinfo_clear(d->tri);
(void) trinfo_load_textrec(d->tri, &tsp, tsp.ori,TR_EMFBOT); // ignore return status, it must work
+ if (d->dc[d->level].clip_id){
+ d->outsvg += "\n</g>\n";
+ }
}
g_free(escaped_text);
@@ -3292,7 +3420,7 @@ std::cout << "BEFORE DRAW"
tmp_rectangle << d->gradients.strings[fill_idx];
tmp_rectangle << ");\"\n/>\n";
}
- *(d->outsvg) += tmp_rectangle.str().c_str();
+ d->outsvg += tmp_rectangle.str().c_str();
}
else if(pEmr->ulMode == U_GRADIENT_FILL_TRIANGLE){
SVGOStringStream tmp_triangle;
@@ -3310,9 +3438,9 @@ std::cout << "BEFORE DRAW"
tmp_triangle << tmpcolor;
tmp_triangle << ";\"\n/>\n";
}
- *(d->outsvg) += tmp_triangle.str().c_str();
+ d->outsvg += tmp_triangle.str().c_str();
}
- *(d->path) = "";
+ d->path = "";
// if it is anything else the record is bogus, so ignore it
break;
}
@@ -3325,13 +3453,13 @@ std::cout << "BEFORE DRAW"
break;
} //end of switch
// When testing, uncomment the following to place a comment for each processed EMR record in the SVG
-// *(d->outsvg) += dbg_str.str().c_str();
- *(d->outsvg) += tmp_outsvg.str().c_str();
- *(d->path) += tmp_path.str().c_str();
+// d->outsvg += dbg_str.str().c_str();
+ d->outsvg += tmp_outsvg.str().c_str();
+ d->path += tmp_path.str().c_str();
} //end of while
// When testing, uncomment the following to show the final SVG derived from the EMF
-// std::cout << *(d->outsvg) << std::endl;
+// std::cout << d->outsvg << std::endl;
(void) emr_properties(U_EMR_INVALID); // force the release of the lookup table memory, returned value is irrelevant
return 1;
@@ -3342,6 +3470,8 @@ void Emf::free_emf_strings(EMF_STRINGS name){
for(int i=0; i< name.count; i++){ free(name.strings[i]); }
free(name.strings);
}
+ name.count = 0;
+ name.size = 0;
}
SPDocument *
@@ -3349,61 +3479,22 @@ Emf::open( Inkscape::Extension::Input * /*mod*/, const gchar *uri )
{
EMF_CALLBACK_DATA d;
-// memset(&d, 0, sizeof(d));
- memset(&d, 0, sizeof(EMF_CALLBACK_DATA));
-
- for(int i = 0; i < EMF_MAX_DC+1; i++){ // be sure all values and pointers are empty to start with
- memset(&(d.dc[i]),0,sizeof(EMF_DEVICE_CONTEXT));
- }
-
- d.dc[0].worldTransform.eM11 = 1.0;
- d.dc[0].worldTransform.eM12 = 0.0;
- d.dc[0].worldTransform.eM21 = 0.0;
- d.dc[0].worldTransform.eM22 = 1.0;
- d.dc[0].worldTransform.eDx = 0.0;
- d.dc[0].worldTransform.eDy = 0.0;
- d.dc[0].font_name = strdup("Arial"); // Default font, EMF spec says device can pick whatever it wants
- d.dc[0].textColor = U_RGB(0, 0, 0); // default foreground color (black)
- d.dc[0].bkColor = U_RGB(255, 255, 255); // default background color (white)
- d.dc[0].bkMode = U_TRANSPARENT;
- d.dc[0].dirty = 0;
-
if (uri == NULL) {
return NULL;
}
- d.outsvg = new Glib::ustring("");
- d.path = new Glib::ustring("");
- d.outdef = new Glib::ustring("");
- d.defs = new Glib::ustring("");
- d.mask = 0;
- d.drawtype = 0;
- d.arcdir = U_AD_COUNTERCLOCKWISE;
- d.dwRop2 = U_R2_COPYPEN;
- d.dwRop3 = 0;
- d.E2IdirY = 1.0;
- d.D2PscaleX = 1.0;
- d.D2PscaleY = 1.0;
- d.hatches.size = 0;
- d.hatches.count = 0;
- d.hatches.strings = NULL;
- d.images.size = 0;
- d.images.count = 0;
- d.images.strings = NULL;
- d.gradients.size = 0;
- d.gradients.count = 0;
- d.gradients.strings = NULL;
+ d.dc[0].font_name = strdup("Arial"); // Default font, set only on lowest level, it copies up from there EMF spec says device can pick whatever it wants
// set up the size default for patterns in defs. This might not be referenced if there are no patterns defined in the drawing.
- *(d.defs) += "\n";
- *(d.defs) += " <pattern id=\"EMFhbasepattern\" \n";
- *(d.defs) += " patternUnits=\"userSpaceOnUse\"\n";
- *(d.defs) += " width=\"6\" \n";
- *(d.defs) += " height=\"6\" \n";
- *(d.defs) += " x=\"0\" \n";
- *(d.defs) += " y=\"0\"> \n";
- *(d.defs) += " </pattern> \n";
+ d.defs += "\n";
+ d.defs += " <pattern id=\"EMFhbasepattern\" \n";
+ d.defs += " patternUnits=\"userSpaceOnUse\"\n";
+ d.defs += " width=\"6\" \n";
+ d.defs += " height=\"6\" \n";
+ d.defs += " x=\"0\" \n";
+ d.defs += " y=\"0\"> \n";
+ d.defs += " </pattern> \n";
size_t length;
@@ -3423,17 +3514,14 @@ Emf::open( Inkscape::Extension::Input * /*mod*/, const gchar *uri )
if (d.pDesc){ free( d.pDesc ); }
-// std::cout << "SVG Output: " << std::endl << *(d.outsvg) << std::endl;
+// std::cout << "SVG Output: " << std::endl << d.outsvg << std::endl;
- SPDocument *doc = SPDocument::createNewDocFromMem(d.outsvg->c_str(), strlen(d.outsvg->c_str()), TRUE);
+ SPDocument *doc = SPDocument::createNewDocFromMem(d.outsvg.c_str(), strlen(d.outsvg.c_str()), TRUE);
- delete d.outsvg;
- delete d.path;
- delete d.outdef;
- delete d.defs;
free_emf_strings(d.hatches);
free_emf_strings(d.images);
free_emf_strings(d.gradients);
+ free_emf_strings(d.clips);
if (d.emf_obj) {
int i;
@@ -3444,45 +3532,13 @@ Emf::open( Inkscape::Extension::Input * /*mod*/, const gchar *uri )
d.dc[0].style.stroke_dasharray.values.clear();
- for(int i=0; i<=d.level;i++){
+ for(int i=0; i<=EMF_MAX_DC; i++){
if(d.dc[i].font_name)free(d.dc[i].font_name);
}
d.tri = trinfo_release_except_FC(d.tri);
- // Set viewBox if it doesn't exist
- if (doc && !doc->getRoot()->viewBox_set) {
- bool saved = Inkscape::DocumentUndo::getUndoSensitive(doc);
- Inkscape::DocumentUndo::setUndoSensitive(doc, false);
-
- doc->ensureUpToDate();
-
- // Set document unit
- Inkscape::XML::Node *repr = sp_document_namedview(doc, 0)->getRepr();
- Inkscape::SVGOStringStream os;
- Inkscape::Util::Unit const* doc_unit = doc->getWidth().unit;
- os << doc_unit->abbr;
- repr->setAttribute("inkscape:document-units", os.str().c_str());
-
- // Set viewBox
- doc->setViewBox(Geom::Rect::from_xywh(0, 0, doc->getWidth().value(doc_unit), doc->getHeight().value(doc_unit)));
- doc->ensureUpToDate();
-
- // Scale and translate objects
- double scale = Inkscape::Util::Quantity::convert(1, "px", doc_unit);
- ShapeEditor::blockSetItem(true);
- double dh;
- if(SP_ACTIVE_DOCUMENT){ // for file menu open or import, or paste from clipboard
- dh = SP_ACTIVE_DOCUMENT->getHeight().value("px");
- }
- else { // for open via --file on command line
- dh = doc->getHeight().value("px");
- }
- doc->getRoot()->scaleChildItemsRec(Geom::Scale(scale), Geom::Point(0, dh));
- ShapeEditor::blockSetItem(false);
-
- Inkscape::DocumentUndo::setUndoSensitive(doc, saved);
- }
+ setViewBoxIfMissing(doc);
return doc;
}
diff --git a/src/extension/internal/emf-inout.h b/src/extension/internal/emf-inout.h
index a97cb0a54..c64299093 100644
--- a/src/extension/internal/emf-inout.h
+++ b/src/extension/internal/emf-inout.h
@@ -27,21 +27,62 @@ namespace Internal {
#define DIRTY_FILL 0x02
#define DIRTY_STROKE 0x04
-typedef struct {
+typedef struct emf_object {
+ emf_object() :
+ type(0),
+ level(0),
+ lpEMFR(NULL)
+ {};
int type;
int level;
char *lpEMFR;
} EMF_OBJECT, *PEMF_OBJECT;
-typedef struct {
+typedef struct emf_strings {
+ emf_strings() :
+ size(0),
+ count(0),
+ strings(NULL)
+ {};
int size; // number of slots allocated in strings
int count; // number of slots used in strings
char **strings; // place to store strings
} EMF_STRINGS, *PEMF_STRINGS;
typedef struct emf_device_context {
- struct SPStyle style;
+ emf_device_context() :
+ // SPStyle: class with constructor
+ font_name(NULL),
+ clip_id(0),
+ stroke_set(false), stroke_mode(0), stroke_idx(0), stroke_recidx(0),
+ fill_set(false), fill_mode(0), fill_idx(0), fill_recidx(0),
+ dirty(0),
+ // sizeWnd, sizeView, winorg, vieworg,
+ ScaleInX(0), ScaleInY(0),
+ ScaleOutX(0), ScaleOutY(0),
+ bkMode(U_TRANSPARENT),
+ // bkColor, textColor
+ textAlign(0)
+ // worldTransform, cur
+ {
+ font_name = NULL;
+ sizeWnd = sizel_set( 0.0, 0.0 );
+ sizeView = sizel_set( 0.0, 0.0 );
+ winorg = point32_set( 0.0, 0.0 );
+ vieworg = point32_set( 0.0, 0.0 );
+ bkColor = U_RGB(255, 255, 255); // default foreground color (white)
+ textColor = U_RGB(0, 0, 0); // default foreground color (black)
+ worldTransform.eM11 = 1.0;
+ worldTransform.eM12 = 0.0;
+ worldTransform.eM21 = 0.0;
+ worldTransform.eM22 = 1.0;
+ worldTransform.eDx = 0.0;
+ worldTransform.eDy = 0.0;
+ cur = point32_set( 0, 0 );
+ };
+ SPStyle style;
char *font_name;
+ int clip_id; // 0 if none, else 1 + index into clips
bool stroke_set;
int stroke_mode; // enumeration from drawmode, not used if fill_set is not True
int stroke_idx; // used with DRAW_PATTERN and DRAW_IMAGE to return the appropriate fill
@@ -67,11 +108,34 @@ typedef struct emf_device_context {
#define EMF_MAX_DC 128
-typedef struct {
- Glib::ustring *outsvg;
- Glib::ustring *path;
- Glib::ustring *outdef;
- Glib::ustring *defs;
+typedef struct emf_callback_data {
+
+ emf_callback_data() :
+ // dc: array, structure w/ constructor
+ level(0),
+ E2IdirY(1.0),
+ D2PscaleX(1.0), D2PscaleY(1.0),
+ MM100InX(0), MM100InY(0),
+ PixelsInX(0), PixelsInY(0),
+ PixelsOutX(0), PixelsOutY(0),
+ ulCornerInX(0), ulCornerInY(0),
+ ulCornerOutX(0), ulCornerOutY(0),
+ mask(0),
+ arcdir(U_AD_COUNTERCLOCKWISE),
+ dwRop2(U_R2_COPYPEN), dwRop3(0),
+ MMX(0),MMY(0),
+ drawtype(0),
+ pDesc(NULL),
+ // hatches, images, gradients, struct w/ constructor
+ tri(NULL),
+ n_obj(0)
+ // emf_obj;
+ {};
+
+ Glib::ustring outsvg;
+ Glib::ustring path;
+ Glib::ustring outdef;
+ Glib::ustring defs;
EMF_DEVICE_CONTEXT dc[EMF_MAX_DC+1]; // FIXME: This should be dynamic..
int level;
@@ -92,13 +156,13 @@ typedef struct {
float MMX;
float MMY;
- unsigned int id;
unsigned int drawtype; // one of 0 or U_EMR_FILLPATH, U_EMR_STROKEPATH, U_EMR_STROKEANDFILLPATH
char *pDesc;
// both of these end up in <defs> under the names shown here. These structures allow duplicates to be avoided.
EMF_STRINGS hatches; // hold pattern names, all like EMFhatch#_$$$$$$ where # is the EMF hatch code and $$$$$$ is the color
EMF_STRINGS images; // hold images, all like Image#, where # is the slot the image lives.
EMF_STRINGS gradients; // hold gradient names, all like EMF[HV]_$$$$$$_$$$$$$ where $$$$$$ are the colors
+ EMF_STRINGS clips; // hold clipping paths, referred to be the slot where the clipping path lives
TR_INFO *tri; // Text Reassembly data structure
@@ -137,18 +201,24 @@ protected:
static int in_hatches(PEMF_CALLBACK_DATA d, char *test);
static uint32_t add_hatch(PEMF_CALLBACK_DATA d, uint32_t hatchType, U_COLORREF hatchColor);
static void enlarge_images(PEMF_CALLBACK_DATA d);
- static int in_images(PEMF_CALLBACK_DATA d, char *test);
+ static int in_images(PEMF_CALLBACK_DATA d, const char *test);
static uint32_t add_image(PEMF_CALLBACK_DATA d, void *pEmr, uint32_t cbBits, uint32_t cbBmi,
uint32_t iUsage, uint32_t offBits, uint32_t offBmi);
static void enlarge_gradients(PEMF_CALLBACK_DATA d);
- static int in_gradients(PEMF_CALLBACK_DATA d, char *test);
+ static int in_gradients(PEMF_CALLBACK_DATA d, const char *test);
static uint32_t add_gradient(PEMF_CALLBACK_DATA d, uint32_t gradientType, U_TRIVERTEX tv1, U_TRIVERTEX tv2);
+
+ static void enlarge_clips(PEMF_CALLBACK_DATA d);
+ static int in_clips(PEMF_CALLBACK_DATA d, const char *test);
+ static void add_clips(PEMF_CALLBACK_DATA d, const char *clippath, unsigned int logic);
+
static void output_style(PEMF_CALLBACK_DATA d, int iType);
static double _pix_x_to_point(PEMF_CALLBACK_DATA d, double px);
static double _pix_y_to_point(PEMF_CALLBACK_DATA d, double py);
static double pix_to_x_point(PEMF_CALLBACK_DATA d, double px, double py);
static double pix_to_y_point(PEMF_CALLBACK_DATA d, double px, double py);
static double pix_to_abs_size(PEMF_CALLBACK_DATA d, double px);
+ static void snap_to_faraway_pair(double *x, double *y);
static std::string pix_to_xy(PEMF_CALLBACK_DATA d, double x, double y);
static void select_pen(PEMF_CALLBACK_DATA d, int index);
static void select_extpen(PEMF_CALLBACK_DATA d, int index);
diff --git a/src/extension/internal/emf-print.cpp b/src/extension/internal/emf-print.cpp
index f4f7f08cb..0f43fbca1 100644
--- a/src/extension/internal/emf-print.cpp
+++ b/src/extension/internal/emf-print.cpp
@@ -34,6 +34,7 @@
#include <2geom/pathvector.h>
#include <2geom/rect.h>
#include <2geom/curves.h>
+#include <sp-clippath.h>
#include "helper/geom.h"
#include "helper/geom-curves.h"
@@ -54,6 +55,7 @@
#include "sp-radial-gradient.h"
#include "sp-linear-gradient.h"
#include "display/cairo-utils.h"
+#include "sp-shape.h"
#include "splivarot.h" // pieces for union on shapes
#include "2geom/svg-path-parser.h" // to get from SVG text to Geom::Path
@@ -142,6 +144,7 @@ unsigned int PrintEmf::begin(Inkscape::Extension::Print *mod, SPDocument *doc)
// width and height in px
_width = doc->getWidth().value("px");
_height = doc->getHeight().value("px");
+ _doc_unit_scale = Inkscape::Util::Quantity::convert(1, (doc->getDefaultUnit()), "px");
// initialize a few global variables
hbrush = hbrushOld = hpen = 0;
@@ -297,6 +300,7 @@ unsigned int PrintEmf::begin(Inkscape::Extension::Print *mod, SPDocument *doc)
unsigned int PrintEmf::finish(Inkscape::Extension::Print * /*mod*/)
{
+ do_clip_if_present(NULL); // Terminate any open clip.
char *rec;
if (!et) {
return 0;
@@ -968,16 +972,145 @@ U_TRIVERTEX PrintEmf::make_trivertex(Geom::Point Pt, U_COLORREF uc){
return(tv);
}
+/* Examine clip. If there is a (new) one then apply it. If there is one and it is the
+ same as the preceding one, leave the preceding one active. If style is NULL
+ terminate the current clip, if any, and return.
+*/
+void PrintEmf::do_clip_if_present(SPStyle const *style){
+ char *rec;
+ static SPClipPath *scpActive = NULL;
+ if(!style){
+ if(scpActive){ // clear the existing clip
+ rec = U_EMRRESTOREDC_set(-1);
+ if (!rec || emf_append((PU_ENHMETARECORD)rec, et, U_REC_FREE)) {
+ g_error("Fatal programming error in PrintEmf::fill at U_EMRRESTOREDC_set");
+ }
+ scpActive=NULL;
+ }
+ } else {
+ /* The current implementation converts only one level of clipping. If there were more
+ clips further up the stack they should be combined with the pathvector using "and". Since this
+ comes up rarely, and would involve a lot of searching (all the way up the stack for every
+ draw operation), it has not yet been implemented.
+
+ Note, to debug this section of code use print statements on sp_svg_write_path(combined_pathvector).
+ */
+ /* find the first clip_ref at object or up the stack. There may not be one. */
+ SPClipPath *scp = NULL;
+ SPItem *item = SP_ITEM(style->object);
+ while(1) {
+ scp = (item->clip_ref ? item->clip_ref->getObject() : NULL);
+ if(scp)break;
+ item = SP_ITEM(item->parent);
+ if(!item || SP_IS_ROOT(item))break; // this will never be a clipping path
+ }
+
+ if(scp != scpActive){ // change or remove the clipping
+ if(scpActive){ // clear the existing clip
+ rec = U_EMRRESTOREDC_set(-1);
+ if (!rec || emf_append((PU_ENHMETARECORD)rec, et, U_REC_FREE)) {
+ g_error("Fatal programming error in PrintEmf::fill at U_EMRRESTOREDC_set");
+ }
+ scpActive = NULL;
+ }
+
+ if (scp) { // set the new clip
+ /* because of units and who knows what other transforms that might be applied above we
+ need the full transform all the way to the root.
+ */
+ Geom::Affine tf = item->transform;
+ SPItem *scan_item = item;
+ while(1) {
+ scan_item = SP_ITEM(scan_item->parent);
+ if(!scan_item)break;
+ tf *= scan_item->transform;
+ }
+ tf *= Geom::Scale(_doc_unit_scale);; // Transform must be in PIXELS, no matter what the document unit is.
+
+ /* find the clipping path */
+ Geom::PathVector combined_pathvector;
+ Geom::Affine tfc; // clipping transform, generally not the same as item transform
+ for(item = SP_ITEM(scp->firstChild()); item; item=SP_ITEM(item->getNext())){
+ if (SP_IS_GROUP(item)) { // not implemented
+ // return sp_group_render(item);
+ combined_pathvector = merge_PathVector_with_group(combined_pathvector, item, tfc);
+ } else if (SP_IS_SHAPE(item)) {
+ combined_pathvector = merge_PathVector_with_shape(combined_pathvector, item, tfc);
+ } else { // not implemented
+ }
+ }
+
+ if (!combined_pathvector.empty()) { // if clipping path isn't empty, define EMF clipping record
+ scpActive = scp; // remember for next time
+ // the sole purpose of this SAVEDC is to let us clear the clipping region later.
+ rec = U_EMRSAVEDC_set();
+ if (!rec || emf_append((PU_ENHMETARECORD)rec, et, U_REC_FREE)) {
+ g_error("Fatal programming error in PrintEmf::image at U_EMRSAVEDC_set");
+ }
+ (void) draw_pathv_to_EMF(combined_pathvector, tf);
+ rec = U_EMRSELECTCLIPPATH_set(U_RGN_OR);
+ if (!rec || emf_append((PU_ENHMETARECORD)rec, et, U_REC_FREE)) {
+ g_error("Fatal programming error in PrintEmf::do_clip_if_present at U_EMRSELECTCLIPPATH_set");
+ }
+ }
+ else {
+ scpActive = NULL; // no valid path available to draw, so no DC was saved, so no signal to restore
+ }
+ } // change or remove clipping
+ } // scp exists
+ } // style exists
+}
+
+Geom::PathVector PrintEmf::merge_PathVector_with_group(Geom::PathVector const &combined_pathvector, SPItem const *item, const Geom::Affine &transform)
+{
+ Geom::PathVector new_combined_pathvector;
+ if(!SP_IS_GROUP(item))return(new_combined_pathvector); // sanity test, only a group should be passed in, return empty if something else happens
+
+ new_combined_pathvector = combined_pathvector;
+ SPGroup *group = SP_GROUP(item);
+ Geom::Affine tfc = item->transform * transform;
+ for(SPItem *item = SP_ITEM(group->firstChild()); item; item=SP_ITEM(item->getNext())){
+ if (SP_IS_GROUP(item)) {
+ new_combined_pathvector = merge_PathVector_with_group(new_combined_pathvector, item, tfc); // could be endlessly recursive on a badly formed SVG
+ } else if (SP_IS_SHAPE(item)) {
+ new_combined_pathvector = merge_PathVector_with_shape(new_combined_pathvector, item, tfc);
+ } else { // not implemented
+ }
+ }
+ return new_combined_pathvector;
+}
+
+Geom::PathVector PrintEmf::merge_PathVector_with_shape(Geom::PathVector const &combined_pathvector, SPItem const *item, const Geom::Affine &transform)
+{
+ Geom::PathVector new_combined_pathvector;
+ if(!SP_IS_SHAPE(item))return(new_combined_pathvector); // sanity test, only a shape should be passed in, return empty if something else happens
+
+ Geom::Affine tfc = item->transform * transform;
+ SPShape *shape = SP_SHAPE(item);
+ if (shape->_curve) {
+ Geom::PathVector const & new_vect = shape->_curve->get_pathvector();
+ if(combined_pathvector.empty()){
+ new_combined_pathvector = new_vect * tfc;
+ }
+ else {
+ new_combined_pathvector = sp_pathvector_boolop(new_vect * tfc, combined_pathvector, bool_op_union , (FillRule) fill_oddEven, (FillRule) fill_oddEven);
+ }
+ }
+ return new_combined_pathvector;
+}
+
unsigned int PrintEmf::fill(
Inkscape::Extension::Print * /*mod*/,
Geom::PathVector const &pathv, Geom::Affine const & /*transform*/, SPStyle const *style,
Geom::OptRect const &/*pbox*/, Geom::OptRect const &/*dbox*/, Geom::OptRect const &/*bbox*/)
{
+ char *rec;
using Geom::X;
using Geom::Y;
-
Geom::Affine tf = m_tr_stack.top();
+ do_clip_if_present(style); // If clipping is needed set it up
+
use_fill = true;
use_stroke = false;
@@ -1091,7 +1224,6 @@ unsigned int PrintEmf::fill(
}
} else if (gv.mode == DRAW_LINEAR_GRADIENT) {
if(is_Rect){
- char *rec;
int gMode;
Geom::Point ul, ur, lr;
Geom::Point outUL, outLR; // UL,LR corners of a stop rectangle, in OUTPUT coordinates
@@ -1280,6 +1412,7 @@ unsigned int PrintEmf::stroke(
char *rec = NULL;
Geom::Affine tf = m_tr_stack.top();
+ do_clip_if_present(style); // If clipping is needed set it up
use_stroke = true;
// use_fill was set in ::fill, if it is needed
@@ -1564,12 +1697,14 @@ unsigned int PrintEmf::image(
unsigned int h, /** height of bitmap */
unsigned int rs, /** row stride (normally w*4) */
Geom::Affine const &tf_rect, /** affine transform only used for defining location and size of rect, for all other tranforms, use the one from m_tr_stack */
- SPStyle const * /*style*/) /** provides indirect link to image object */
+ SPStyle const *style) /** provides indirect link to image object */
{
double x1, y1, dw, dh;
char *rec = NULL;
Geom::Affine tf = m_tr_stack.top();
+ do_clip_if_present(style); // If clipping is needed set it up
+
rec = U_EMRSETSTRETCHBLTMODE_set(U_COLORONCOLOR);
if (!rec || emf_append((PU_ENHMETARECORD)rec, et, U_REC_FREE)) {
g_error("Fatal programming error in PrintEmf::image at EMRHEADER");
@@ -1654,28 +1789,14 @@ unsigned int PrintEmf::image(
return 0;
}
-// may also be called with a simple_shape or an empty path, whereupon it just returns without doing anything
-unsigned int PrintEmf::print_pathv(Geom::PathVector const &pathv, const Geom::Affine &transform)
-{
- Geom::Affine tf = transform;
- char *rec = NULL;
-
- simple_shape = print_simple_shape(pathv, tf);
- if (simple_shape || pathv.empty()) {
- if (use_fill) {
- destroy_brush(); // these must be cleared even if nothing is drawn or hbrush,hpen fill up
- }
- if (use_stroke) {
- destroy_pen();
- }
- return TRUE;
- }
+unsigned int PrintEmf::draw_pathv_to_EMF(Geom::PathVector const &pathv, const Geom::Affine &transform) {
+ char *rec;
/* inkscape to EMF scaling is done below, but NOT the rotation/translation transform,
that is handled by the EMF MODIFYWORLDTRANSFORM record
*/
-
- Geom::PathVector pv = pathv_to_linear_and_cubic_beziers(pathv * tf);
+
+ Geom::PathVector pv = pathv_to_linear_and_cubic_beziers(pathv * transform);
rec = U_EMRBEGINPATH_set();
if (!rec || emf_append((PU_ENHMETARECORD)rec, et, U_REC_FREE)) {
@@ -1777,6 +1898,27 @@ unsigned int PrintEmf::print_pathv(Geom::PathVector const &pathv, const Geom::Af
if (!rec || emf_append((PU_ENHMETARECORD)rec, et, U_REC_FREE)) {
g_error("Fatal programming error in PrintEmf::print_pathv at U_EMRENDPATH_set");
}
+ return(0);
+}
+
+// may also be called with a simple_shape or an empty path, whereupon it just returns without doing anything
+unsigned int PrintEmf::print_pathv(Geom::PathVector const &pathv, const Geom::Affine &transform)
+{
+ Geom::Affine tf = transform;
+ char *rec = NULL;
+
+ simple_shape = print_simple_shape(pathv, tf);
+ if (simple_shape || pathv.empty()) {
+ if (use_fill) {
+ destroy_brush(); // these must be cleared even if nothing is drawn or hbrush,hpen fill up
+ }
+ if (use_stroke) {
+ destroy_pen();
+ }
+ return TRUE;
+ }
+
+ (void) draw_pathv_to_EMF(pathv, tf);
// explicit FILL/STROKE commands are needed for each sub section of the path
if (use_fill && !use_stroke) {
@@ -1815,6 +1957,7 @@ unsigned int PrintEmf::text(Inkscape::Extension::Print * /*mod*/, char const *te
return 0;
}
+ do_clip_if_present(style); // If clipping is needed set it up
char *rec = NULL;
int ccount, newfont;
int fix90n = 0;
@@ -1869,7 +2012,7 @@ unsigned int PrintEmf::text(Inkscape::Extension::Print * /*mod*/, char const *te
_lookup_ppt_fontfix("Convert To Wingdings", params);
break;
default: //also CVTNON
- _lookup_ppt_fontfix(style->text->font_family.value, params);
+ _lookup_ppt_fontfix(style->font_family.value, params);
break;
}
if (params.f2 != 0 || params.f3 != 0) {
@@ -1878,7 +2021,7 @@ unsigned int PrintEmf::text(Inkscape::Extension::Print * /*mod*/, char const *te
fix90n = 1; //assume vertical
rot = (double)(((int) round(rot)) - irem);
rotb = rot * M_PI / 1800.0;
- if (abs(rot) == 900.0) {
+ if (std::abs(rot) == 900.0) {
fix90n = 2;
}
}
@@ -1897,7 +2040,7 @@ unsigned int PrintEmf::text(Inkscape::Extension::Print * /*mod*/, char const *te
// of the special fonts.
uint16_t *wfacename;
if (!newfont) {
- wfacename = U_Utf8ToUtf16le(style->text->font_family.value, 0, NULL);
+ wfacename = U_Utf8ToUtf16le(style->font_family.value, 0, NULL);
} else {
wfacename = U_Utf8ToUtf16le(FontName(newfont), 0, NULL);
}
diff --git a/src/extension/internal/emf-print.h b/src/extension/internal/emf-print.h
index 1e4970a46..5bad48de5 100644
--- a/src/extension/internal/emf-print.h
+++ b/src/extension/internal/emf-print.h
@@ -29,7 +29,7 @@ namespace Internal {
class PrintEmf : public PrintMetafile
{
- uint32_t hbrush, hbrushOld, hpen, hpenOld;
+ uint32_t hbrush, hbrushOld, hpen;
unsigned int print_pathv (Geom::PathVector const &pathv, const Geom::Affine &transform);
bool print_simple_shape (Geom::PathVector const &pathv, const Geom::Affine &transform);
@@ -69,6 +69,10 @@ public:
protected:
static void smuggle_adxkyrtl_out(const char *string, uint32_t **adx, double *ky, int *rtl, int *ndx, float scale);
+ void do_clip_if_present(SPStyle const *style);
+ Geom::PathVector merge_PathVector_with_group(Geom::PathVector const &combined_pathvector, SPItem const *item, const Geom::Affine &transform);
+ Geom::PathVector merge_PathVector_with_shape(Geom::PathVector const &combined_pathvector, SPItem const *item, const Geom::Affine &transform);
+ unsigned int draw_pathv_to_EMF(Geom::PathVector const &pathv, const Geom::Affine &transform);
Geom::Path pathv_to_simple_polygon(Geom::PathVector const &pathv, int *vertices);
Geom::Path pathv_to_rect(Geom::PathVector const &pathv, bool *is_rect, double *angle);
Geom::Point get_pathrect_corner(Geom::Path pathRect, double angle, int corner);
diff --git a/src/extension/internal/gdkpixbuf-input.cpp b/src/extension/internal/gdkpixbuf-input.cpp
index a384c7bde..28e44c461 100644
--- a/src/extension/internal/gdkpixbuf-input.cpp
+++ b/src/extension/internal/gdkpixbuf-input.cpp
@@ -1,21 +1,20 @@
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
+#include <gdk-pixbuf/gdk-pixbuf.h>
+
#include <boost/scoped_ptr.hpp>
#include <glib/gprintf.h>
#include <glibmm/i18n.h>
+#include "dir-util.h"
+#include "display/cairo-utils.h"
#include "document-private.h"
-#include <dir-util.h>
+#include "document-undo.h"
#include "extension/input.h"
#include "extension/system.h"
+#include "image-resolution.h"
#include "gdkpixbuf-input.h"
#include "preferences.h"
#include "selection-chemistry.h"
#include "sp-image.h"
-#include "document-undo.h"
#include "util/units.h"
-#include "image-resolution.h"
-#include "display/cairo-utils.h"
#include <set>
namespace Inkscape {
@@ -87,11 +86,11 @@ GdkpixbufInput::open(Inkscape::Extension::Input *mod, char const *uri)
ir = new ImageResolution(uri);
}
if (ir && ir->ok()) {
- xscale = 900.0 / floor(10.*ir->x() + .5); // round-off to 0.1 dpi
- yscale = 900.0 / floor(10.*ir->y() + .5);
+ xscale = 960.0 / floor(10.*ir->x() + .5); // round-off to 0.1 dpi
+ yscale = 960.0 / floor(10.*ir->y() + .5);
} else {
- xscale = 90.0 / defaultxdpi;
- yscale = 90.0 / defaultxdpi;
+ xscale = 96.0 / defaultxdpi;
+ yscale = 96.0 / defaultxdpi;
}
width *= xscale;
diff --git a/src/extension/internal/gdkpixbuf-input.h b/src/extension/internal/gdkpixbuf-input.h
index 597e7246b..2e03a96db 100644
--- a/src/extension/internal/gdkpixbuf-input.h
+++ b/src/extension/internal/gdkpixbuf-input.h
@@ -10,7 +10,7 @@ namespace Internal {
class GdkpixbufInput : Inkscape::Extension::Implementation::Implementation {
public:
SPDocument *open(Inkscape::Extension::Input *mod,
- gchar const *uri);
+ char const *uri);
static void init();
};
diff --git a/src/extension/internal/image-resolution.cpp b/src/extension/internal/image-resolution.cpp
index 18eb97f80..e96fd6437 100644
--- a/src/extension/internal/image-resolution.cpp
+++ b/src/extension/internal/image-resolution.cpp
@@ -353,18 +353,20 @@ void ImageResolution::readmagick(char const *fn) {
g_warning("ImageResolution::readmagick: Unknown error");
return;
}
- Magick::Geometry geo = image.density();
- std::string type = image.magick();
-
- if (type == "PNG") { // PNG only supports pixelspercentimeter
- x_ = Inkscape::Util::Quantity::convert((double)geo.width(), "in", "cm");
- y_ = Inkscape::Util::Quantity::convert((double)geo.height(), "in", "cm");
- } else {
- x_ = (double)geo.width();
- y_ = (double)geo.height();
- }
- ok_ = true;
+ std::string const type = image.magick();
+ x_ = image.xResolution();
+ y_ = image.yResolution();
+
+// TODO: find out why the hell the following convertion is necessary
+ if (type == "BMP") {
+ x_ = Inkscape::Util::Quantity::convert(x_, "in", "cm");
+ y_ = Inkscape::Util::Quantity::convert(y_, "in", "cm");
+ }
+
+ if (x_ != 0 && y_ != 0) {
+ ok_ = true;
+ }
}
#else
diff --git a/src/extension/internal/latex-text-renderer.cpp b/src/extension/internal/latex-text-renderer.cpp
index 398c9f061..ab0733848 100644
--- a/src/extension/internal/latex-text-renderer.cpp
+++ b/src/extension/internal/latex-text-renderer.cpp
@@ -66,7 +66,8 @@ latex_render_document_text_to_file( SPDocument *doc, gchar const *filename,
bool pageBoundingBox = true;
if (exportId && strcmp(exportId, "")) {
// we want to export the given item only
- base = SP_ITEM(doc->getObjectById(exportId));
+ base = dynamic_cast<SPItem *>(doc->getObjectById(exportId));
+ g_assert(base != NULL);
pageBoundingBox = exportCanvas;
}
else {
@@ -225,26 +226,22 @@ LaTeXTextRenderer::writePostamble()
fprintf(_stream, "%s", postamble);
}
-void
-LaTeXTextRenderer::sp_group_render(SPItem *item)
+void LaTeXTextRenderer::sp_group_render(SPGroup *group)
{
- SPGroup *group = SP_GROUP(item);
-
GSList *l = g_slist_reverse(group->childList(false));
while (l) {
- SPObject *o = SP_OBJECT (l->data);
- if (SP_IS_ITEM(o)) {
- renderItem (SP_ITEM (o));
+ SPObject *o = reinterpret_cast<SPObject *>(l->data);
+ SPItem *item = dynamic_cast<SPItem *>(o);
+ if (item) {
+ renderItem(item);
}
l = g_slist_remove (l, o);
}
}
-void
-LaTeXTextRenderer::sp_use_render(SPItem *item)
+void LaTeXTextRenderer::sp_use_render(SPUse *use)
{
bool translated = false;
- SPUse *use = SP_USE(item);
if ((use->x._set && use->x.computed != 0) || (use->y._set && use->y.computed != 0)) {
Geom::Affine tp(Geom::Translate(use->x.computed, use->y.computed));
@@ -252,8 +249,9 @@ LaTeXTextRenderer::sp_use_render(SPItem *item)
translated = true;
}
- if (use->child && SP_IS_ITEM(use->child)) {
- renderItem(SP_ITEM(use->child));
+ SPItem *childItem = dynamic_cast<SPItem *>(use->child);
+ if (childItem) {
+ renderItem(childItem);
}
if (translated) {
@@ -261,16 +259,14 @@ LaTeXTextRenderer::sp_use_render(SPItem *item)
}
}
-void
-LaTeXTextRenderer::sp_text_render(SPItem *item)
+void LaTeXTextRenderer::sp_text_render(SPText *textobj)
{
// Only PDFLaTeX supports importing a single page of a graphics file,
// so only PDF backend gets interleaved text/graphics
if (_pdflatex && _omittext_state == GRAPHIC_ON_TOP)
_omittext_state = NEW_PAGE_ON_GRAPHIC;
- SPText *textobj = SP_TEXT (item);
- SPStyle *style = item->style;
+ SPStyle *style = textobj->style;
// get position and alignment
// Align vertically on the baseline of the font (retreived from the anchor point)
@@ -312,7 +308,7 @@ LaTeXTextRenderer::sp_text_render(SPItem *item)
}
// get rotation
- Geom::Affine i2doc = item->i2doc_affine();
+ Geom::Affine i2doc = textobj->i2doc_affine();
Geom::Affine wotransl = i2doc.withoutTranslation();
double degrees = -180/M_PI * Geom::atan2(wotransl.xAxis());
bool has_rotation = !Geom::are_near(degrees,0.);
@@ -336,11 +332,11 @@ LaTeXTextRenderer::sp_text_render(SPItem *item)
// Walk through all spans in the text object.
// Write span strings to LaTeX, associated with font weight and style.
- Inkscape::Text::Layout const &layout = *(te_get_layout (item));
+ Inkscape::Text::Layout const &layout = *(te_get_layout (textobj));
for (Inkscape::Text::Layout::iterator li = layout.begin(), le = layout.end();
li != le; li.nextStartOfSpan())
{
- SPStyle const &spanstyle = *(sp_te_style_at_position (item, li));
+ SPStyle const &spanstyle = *(sp_te_style_at_position (textobj, li));
bool is_bold = false, is_italic = false, is_oblique = false;
if (spanstyle.font_weight.computed == SP_CSS_FONT_WEIGHT_500 ||
@@ -367,7 +363,7 @@ LaTeXTextRenderer::sp_text_render(SPItem *item)
Inkscape::Text::Layout::iterator ln = li;
ln.nextStartOfSpan();
- Glib::ustring uspanstr = sp_te_get_string_multiline (item, li, ln);
+ Glib::ustring uspanstr = sp_te_get_string_multiline (textobj, li, ln);
const gchar *spanstr = uspanstr.c_str();
if (!spanstr) {
continue;
@@ -394,8 +390,7 @@ LaTeXTextRenderer::sp_text_render(SPItem *item)
fprintf(_stream, "%s", os.str().c_str());
}
-void
-LaTeXTextRenderer::sp_flowtext_render(SPItem * item)
+void LaTeXTextRenderer::sp_flowtext_render(SPFlowtext *flowtext)
{
/*
Flowtext is possible by using a minipage! :)
@@ -407,16 +402,15 @@ Flowing in rectangle is possible, not in arb shape.
if (_pdflatex && _omittext_state == GRAPHIC_ON_TOP)
_omittext_state = NEW_PAGE_ON_GRAPHIC;
- SPFlowtext *flowtext = SP_FLOWTEXT(item);
- SPStyle *style = item->style;
+ SPStyle *style = flowtext->style;
SPItem *frame_item = flowtext->get_frame(NULL);
- if (!frame_item || !SP_IS_RECT(frame_item)) {
+ SPRect *frame = dynamic_cast<SPRect *>(frame_item);
+ if (!frame_item || !frame) {
g_warning("LaTeX export: non-rectangular flowed text shapes are not supported, skipping text.");
return; // don't know how to handle non-rect frames yet. is quite uncommon for latex users i think
}
- SPRect *frame = SP_RECT(frame_item);
Geom::Rect framebox = frame->getRect() * transform();
// get position and alignment
@@ -460,7 +454,7 @@ Flowing in rectangle is possible, not in arb shape.
}
// get rotation
- Geom::Affine i2doc = item->i2doc_affine();
+ Geom::Affine i2doc = flowtext->i2doc_affine();
Geom::Affine wotransl = i2doc.withoutTranslation();
double degrees = -180/M_PI * Geom::atan2(wotransl.xAxis());
bool has_rotation = !Geom::are_near(degrees,0.);
@@ -485,11 +479,11 @@ Flowing in rectangle is possible, not in arb shape.
// Walk through all spans in the text object.
// Write span strings to LaTeX, associated with font weight and style.
- Inkscape::Text::Layout const &layout = *(te_get_layout (item));
+ Inkscape::Text::Layout const &layout = *(te_get_layout(flowtext));
for (Inkscape::Text::Layout::iterator li = layout.begin(), le = layout.end();
li != le; li.nextStartOfSpan())
{
- SPStyle const &spanstyle = *(sp_te_style_at_position (item, li));
+ SPStyle const &spanstyle = *(sp_te_style_at_position(flowtext, li));
bool is_bold = false, is_italic = false, is_oblique = false;
if (spanstyle.font_weight.computed == SP_CSS_FONT_WEIGHT_500 ||
@@ -516,7 +510,7 @@ Flowing in rectangle is possible, not in arb shape.
Inkscape::Text::Layout::iterator ln = li;
ln.nextStartOfSpan();
- Glib::ustring uspanstr = sp_te_get_string_multiline (item, li, ln);
+ Glib::ustring uspanstr = sp_te_get_string_multiline(flowtext, li, ln);
const gchar *spanstr = uspanstr.c_str();
if (!spanstr) {
continue;
@@ -558,22 +552,36 @@ LaTeXTextRenderer::sp_item_invoke_render(SPItem *item)
return;
}
- if (SP_IS_ROOT(item)) {
- return sp_root_render(SP_ROOT(item));
- } else if (SP_IS_GROUP(item)) {
- return sp_group_render(item);
- } else if (SP_IS_USE(item)) {
- sp_use_render(item);
- } else if (SP_IS_TEXT(item)) {
- return sp_text_render(item);
- } else if (SP_IS_FLOWTEXT(item)) {
- return sp_flowtext_render(item);
+ SPRoot *root = dynamic_cast<SPRoot *>(item);
+ if (root) {
+ sp_root_render(root);
} else {
- // Only PDFLaTeX supports importing a single page of a graphics file,
- // so only PDF backend gets interleaved text/graphics
- if (_pdflatex && (_omittext_state == EMPTY || _omittext_state == NEW_PAGE_ON_GRAPHIC))
- writeGraphicPage();
- _omittext_state = GRAPHIC_ON_TOP;
+ SPGroup *group = dynamic_cast<SPGroup *>(item);
+ if (group) {
+ sp_group_render(group);
+ } else {
+ SPUse *use = dynamic_cast<SPUse *>(item);
+ if (use) {
+ sp_use_render(use);
+ } else {
+ SPText *text = dynamic_cast<SPText *>(item);
+ if (text) {
+ sp_text_render(text);
+ } else {
+ SPFlowtext *flowtext = dynamic_cast<SPFlowtext *>(item);
+ if (flowtext) {
+ sp_flowtext_render(flowtext);
+ } else {
+ // Only PDFLaTeX supports importing a single page of a graphics file,
+ // so only PDF backend gets interleaved text/graphics
+ if (_pdflatex && (_omittext_state == EMPTY || _omittext_state == NEW_PAGE_ON_GRAPHIC)) {
+ writeGraphicPage();
+ }
+ _omittext_state = GRAPHIC_ON_TOP;
+ }
+ }
+ }
+ }
}
}
diff --git a/src/extension/internal/latex-text-renderer.h b/src/extension/internal/latex-text-renderer.h
index 77d12bc61..b9563b53b 100644
--- a/src/extension/internal/latex-text-renderer.h
+++ b/src/extension/internal/latex-text-renderer.h
@@ -23,6 +23,10 @@
class SPItem;
class SPRoot;
+class SPGroup;
+class SPUse;
+class SPText;
+class SPFlowtext;
namespace Inkscape {
namespace Extension {
@@ -73,10 +77,10 @@ protected:
void sp_item_invoke_render(SPItem *item);
void sp_root_render(SPRoot *item);
- void sp_group_render(SPItem *item);
- void sp_use_render(SPItem *item);
- void sp_text_render(SPItem *item);
- void sp_flowtext_render(SPItem *item);
+ void sp_group_render(SPGroup *group);
+ void sp_use_render(SPUse *use);
+ void sp_text_render(SPText *text);
+ void sp_flowtext_render(SPFlowtext *flowtext);
};
} /* namespace Internal */
diff --git a/src/extension/internal/metafile-inout.cpp b/src/extension/internal/metafile-inout.cpp
index 1d419a6a0..824934b3e 100644
--- a/src/extension/internal/metafile-inout.cpp
+++ b/src/extension/internal/metafile-inout.cpp
@@ -17,6 +17,7 @@
#include <glib.h>
#include <glibmm/miscutils.h>
+#include "sp-root.h"
#include "display/curve.h"
#include "extension/internal/metafile-inout.h" // picks up PNG
#include "extension/print.h"
@@ -27,6 +28,13 @@
#include "sp-pattern.h"
#include "sp-radial-gradient.h"
#include "style.h"
+#include "document.h"
+#include "util/units.h"
+#include "ui/shape-editor.h"
+#include "sp-namedview.h"
+#include "document-undo.h"
+#include "inkscape.h"
+#include "preferences.h"
namespace Inkscape {
namespace Extension {
@@ -171,6 +179,88 @@ void Metafile::toPNG(PMEMPNG accum, int width, int height, const char *px){
}
+/* If the viewBox is missing, set one
+*/
+void Metafile::setViewBoxIfMissing(SPDocument *doc) {
+
+ if (doc && !doc->getRoot()->viewBox_set) {
+ bool saved = Inkscape::DocumentUndo::getUndoSensitive(doc);
+ Inkscape::DocumentUndo::setUndoSensitive(doc, false);
+
+ doc->ensureUpToDate();
+
+ // Set document unit
+ Inkscape::XML::Node *repr = sp_document_namedview(doc, 0)->getRepr();
+ Inkscape::SVGOStringStream os;
+ Inkscape::Util::Unit const* doc_unit = doc->getWidth().unit;
+ os << doc_unit->abbr;
+ repr->setAttribute("inkscape:document-units", os.str().c_str());
+
+ // Set viewBox
+ doc->setViewBox(Geom::Rect::from_xywh(0, 0, doc->getWidth().value(doc_unit), doc->getHeight().value(doc_unit)));
+ doc->ensureUpToDate();
+
+ // Scale and translate objects
+ double scale = Inkscape::Util::Quantity::convert(1, "px", doc_unit);
+ Inkscape::UI::ShapeEditor::blockSetItem(true);
+ double dh;
+ if(SP_ACTIVE_DOCUMENT){ // for file menu open or import, or paste from clipboard
+ dh = SP_ACTIVE_DOCUMENT->getHeight().value("px");
+ }
+ else { // for open via --file on command line
+ dh = doc->getHeight().value("px");
+ }
+
+ // These should not affect input, but they do, so set them to a neutral state
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ bool transform_stroke = prefs->getBool("/options/transform/stroke", true);
+ bool transform_rectcorners = prefs->getBool("/options/transform/rectcorners", true);
+ bool transform_pattern = prefs->getBool("/options/transform/pattern", true);
+ bool transform_gradient = prefs->getBool("/options/transform/gradient", true);
+ prefs->setBool("/options/transform/stroke", true);
+ prefs->setBool("/options/transform/rectcorners", true);
+ prefs->setBool("/options/transform/pattern", true);
+ prefs->setBool("/options/transform/gradient", true);
+
+ doc->getRoot()->scaleChildItemsRec(Geom::Scale(scale), Geom::Point(0, dh), true);
+ Inkscape::UI::ShapeEditor::blockSetItem(false);
+
+ // restore options
+ prefs->setBool("/options/transform/stroke", transform_stroke);
+ prefs->setBool("/options/transform/rectcorners", transform_rectcorners);
+ prefs->setBool("/options/transform/pattern", transform_pattern);
+ prefs->setBool("/options/transform/gradient", transform_gradient);
+
+ Inkscape::DocumentUndo::setUndoSensitive(doc, saved);
+ }
+}
+
+/**
+ \fn Convert EMF/WMF region combining ops to livarot region combining ops
+ \return combination operators in livarot enumeration, or -1 on no match
+ \param ops (int) combination operator (Inkscape)
+*/
+int Metafile::combine_ops_to_livarot(const int op)
+{
+ int ret = -1;
+ switch(op) {
+ case U_RGN_AND:
+ ret = bool_op_inters;
+ break;
+ case U_RGN_OR:
+ ret = bool_op_union;
+ break;
+ case U_RGN_XOR:
+ ret = bool_op_symdiff;
+ break;
+ case U_RGN_DIFF:
+ ret = bool_op_diff;
+ break;
+ }
+ return(ret);
+}
+
+
/* convert an EMF RGB(A) color to 0RGB
inverse of gethexcolor() in emf-print.cpp
diff --git a/src/extension/internal/metafile-inout.h b/src/extension/internal/metafile-inout.h
index 968773a3a..b3efee2a6 100644
--- a/src/extension/internal/metafile-inout.h
+++ b/src/extension/internal/metafile-inout.h
@@ -71,6 +71,8 @@ protected:
static void my_png_write_data(png_structp png_ptr, png_bytep data, png_size_t length);
static void toPNG(PMEMPNG accum, int width, int height, const char *px);
static gchar *bad_image_png(void);
+ static void setViewBoxIfMissing(SPDocument *doc);
+ static int combine_ops_to_livarot(const int op);
private:
diff --git a/src/extension/internal/metafile-print.h b/src/extension/internal/metafile-print.h
index a21f9de58..d184b72b7 100644
--- a/src/extension/internal/metafile-print.h
+++ b/src/extension/internal/metafile-print.h
@@ -69,6 +69,8 @@ protected:
double _width;
double _height;
+ double _doc_unit_scale; // to pixels, regardless of the document units
+
U_RECTL rc;
uint32_t htextalignment;
diff --git a/src/extension/internal/pdf-input-cairo.cpp b/src/extension/internal/pdf-input-cairo.cpp
deleted file mode 100644
index c45367c08..000000000
--- a/src/extension/internal/pdf-input-cairo.cpp
+++ /dev/null
@@ -1,680 +0,0 @@
- /*
- * Simple PDF import extension using libpoppler and Cairo's SVG surface.
- *
- * Authors:
- * miklos erdelyi
- * Abhishek Sharma
- *
- * Copyright (C) 2007 Authors
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- *
- */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#ifdef HAVE_POPPLER_GLIB
-#ifdef HAVE_POPPLER_CAIRO
-
-#include "pdf-input-cairo.h"
-#include "extension/system.h"
-#include "extension/input.h"
-#include "dialogs/dialog-events.h"
-#include "document.h"
-#include "sp-root.h"
-#include "util/units.h"
-
-#include <2geom/rect.h>
-
-#include "inkscape.h"
-
-#include <cairo-svg.h>
-#include <poppler/glib/poppler.h>
-#include <poppler/glib/poppler-document.h>
-#include <poppler/glib/poppler-page.h>
-
-#include "ui/widget/spinbutton.h"
-#include "ui/widget/frame.h"
-
-#include <gdkmm/general.h>
-
-namespace Inkscape {
-namespace Extension {
-namespace Internal {
-
-
-/**
- * \brief The PDF import dialog
- * FIXME: Probably this should be placed into src/ui/dialog
- */
-
-static const gchar * crop_setting_choices[] = {
- //TRANSLATORS: The following are document crop settings for PDF import
- // more info: http://www.acrobatusers.com/tech_corners/javascript_corner/tips/2006/page_bounds/
- N_("media box"),
- N_("crop box"),
- N_("trim box"),
- N_("bleed box"),
- N_("art box")
-};
-
-PdfImportCairoDialog::PdfImportCairoDialog(PopplerDocument *doc)
-{
- if(doc == NULL) {
- // if there is no document, throw exception here
- throw;
- }
-
- _poppler_doc = doc;
-
- cancelbutton = Gtk::manage(new class Gtk::Button(Gtk::StockID("gtk-cancel")));
- okbutton = Gtk::manage(new class Gtk::Button(Gtk::StockID("gtk-ok")));
- _labelSelect = Gtk::manage(new class Gtk::Label(_("Select page:")));
-
- // Page number
- int num_pages = poppler_document_get_n_pages(_poppler_doc);
-#if WITH_GTKMM_3_0
- Glib::RefPtr<Gtk::Adjustment> _pageNumberSpin_adj( Gtk::Adjustment::create(1, 1, num_pages, 1, 10, 0) );
- _pageNumberSpin = Gtk::manage(new class Inkscape::UI::Widget::SpinButton(_pageNumberSpin_adj, 1, 1));
-#else
- Gtk::Adjustment *_pageNumberSpin_adj = Gtk::manage(new class Gtk::Adjustment(1, 1, num_pages, 1, 10, 0));
- _pageNumberSpin = Gtk::manage(new class Inkscape::UI::Widget::SpinButton(*_pageNumberSpin_adj, 1, 1));
-#endif
- _labelTotalPages = Gtk::manage(new class Gtk::Label());
- hbox2 = Gtk::manage(new class Gtk::HBox(false, 0));
- // Disable the page selector when there's only one page
- if ( num_pages == 1 ) {
- _pageNumberSpin->set_sensitive(false);
- } else {
- // Display total number of pages
- gchar *label_text = g_strdup_printf(_("out of %i"), num_pages);
- _labelTotalPages->set_label(label_text);
- g_free(label_text);
- }
-
- // Crop settings
- _cropCheck = Gtk::manage(new class Gtk::CheckButton(_("Clip to:")));
- _cropTypeCombo = Gtk::manage(new class Gtk::ComboBoxText());
- int num_crop_choices = sizeof(crop_setting_choices) / sizeof(crop_setting_choices[0]);
- for ( int i = 0 ; i < num_crop_choices ; i++ ) {
- _cropTypeCombo->append(_(crop_setting_choices[i]));
- }
- _cropTypeCombo->set_active_text(_(crop_setting_choices[0]));
- _cropTypeCombo->set_sensitive(false);
-
- hbox3 = Gtk::manage(new class Gtk::HBox(false, 4));
- vbox2 = Gtk::manage(new class Gtk::VBox(false, 4));
- _pageSettingsFrame = Gtk::manage(new class Inkscape::UI::Widget::Frame(_("Page settings")));
- _labelPrecision = Gtk::manage(new class Gtk::Label(_("Precision of approximating gradient meshes:")));
- _labelPrecisionWarning = Gtk::manage(new class Gtk::Label(_("<b>Note</b>: setting the precision too high may result in a large SVG file and slow performance.")));
-
-#if WITH_GTKMM_3_0
- _fallbackPrecisionSlider_adj = Gtk::Adjustment::create(2, 1, 256, 1, 10, 10);
- _fallbackPrecisionSlider = Gtk::manage(new Gtk::Scale(_fallbackPrecisionSlider_adj));
-#else
- _fallbackPrecisionSlider_adj = Gtk::manage(new class Gtk::Adjustment(2, 1, 256, 1, 10, 10));
- _fallbackPrecisionSlider = Gtk::manage(new class Gtk::HScale(*_fallbackPrecisionSlider_adj));
-#endif
- _fallbackPrecisionSlider->set_value(2.0);
- _labelPrecisionComment = Gtk::manage(new class Gtk::Label(_("rough")));
- hbox6 = Gtk::manage(new class Gtk::HBox(false, 4));
-
- // Text options
- _labelText = Gtk::manage(new class Gtk::Label(_("Text handling:")));
- _textHandlingCombo = Gtk::manage(new class Gtk::ComboBoxText());
- _textHandlingCombo->append(_("Import text as text"));
- _textHandlingCombo->set_active_text(_("Import text as text"));
- _localFontsCheck = Gtk::manage(new class Gtk::CheckButton(_("Replace PDF fonts by closest-named installed fonts")));
-
- hbox5 = Gtk::manage(new class Gtk::HBox(false, 4));
- _embedImagesCheck = Gtk::manage(new class Gtk::CheckButton(_("Embed images")));
- vbox3 = Gtk::manage(new class Gtk::VBox(false, 4));
- _importSettingsFrame = Gtk::manage(new class Inkscape::UI::Widget::Frame(_("Import settings")));
- vbox1 = Gtk::manage(new class Gtk::VBox(false, 4));
- _previewArea = Gtk::manage(new class Gtk::DrawingArea());
- hbox1 = Gtk::manage(new class Gtk::HBox(false, 4));
- cancelbutton->set_can_focus();
- cancelbutton->set_can_default();
- cancelbutton->set_relief(Gtk::RELIEF_NORMAL);
- okbutton->set_can_focus();
- okbutton->set_can_default();
- okbutton->set_relief(Gtk::RELIEF_NORMAL);
- this->get_action_area()->property_layout_style().set_value(Gtk::BUTTONBOX_END);
- _labelSelect->set_alignment(0.5,0.5);
- _labelSelect->set_padding(4,0);
- _labelSelect->set_justify(Gtk::JUSTIFY_LEFT);
- _labelSelect->set_line_wrap(false);
- _labelSelect->set_use_markup(false);
- _labelSelect->set_selectable(false);
- _pageNumberSpin->set_can_focus();
- _pageNumberSpin->set_update_policy(Gtk::UPDATE_ALWAYS);
- _pageNumberSpin->set_numeric(true);
- _pageNumberSpin->set_digits(0);
- _pageNumberSpin->set_wrap(false);
- _labelTotalPages->set_alignment(0.5,0.5);
- _labelTotalPages->set_padding(4,0);
- _labelTotalPages->set_justify(Gtk::JUSTIFY_LEFT);
- _labelTotalPages->set_line_wrap(false);
- _labelTotalPages->set_use_markup(false);
- _labelTotalPages->set_selectable(false);
- hbox2->pack_start(*_labelSelect, Gtk::PACK_SHRINK, 4);
- hbox2->pack_start(*_pageNumberSpin, Gtk::PACK_SHRINK, 4);
- hbox2->pack_start(*_labelTotalPages, Gtk::PACK_SHRINK, 4);
- _cropCheck->set_can_focus();
- _cropCheck->set_relief(Gtk::RELIEF_NORMAL);
- _cropCheck->set_mode(true);
- _cropCheck->set_active(false);
- _cropTypeCombo->set_border_width(1);
- hbox3->pack_start(*_cropCheck, Gtk::PACK_SHRINK, 4);
- hbox3->pack_start(*_cropTypeCombo, Gtk::PACK_SHRINK, 0);
- vbox2->pack_start(*hbox2);
- vbox2->pack_start(*hbox3);
- _pageSettingsFrame->add(*vbox2);
- _pageSettingsFrame->set_border_width(4);
- _labelPrecision->set_alignment(0,0.5);
- _labelPrecision->set_padding(4,0);
- _labelPrecision->set_justify(Gtk::JUSTIFY_LEFT);
- _labelPrecision->set_line_wrap(true);
- _labelPrecision->set_use_markup(false);
- _labelPrecision->set_selectable(false);
- _labelPrecisionWarning->set_alignment(0,0.5);
- _labelPrecisionWarning->set_padding(4,0);
- _labelPrecisionWarning->set_justify(Gtk::JUSTIFY_LEFT);
- _labelPrecisionWarning->set_line_wrap(true);
- _labelPrecisionWarning->set_use_markup(true);
- _labelPrecisionWarning->set_selectable(false);
- _fallbackPrecisionSlider->set_size_request(180,-1);
- _fallbackPrecisionSlider->set_can_focus();
- _fallbackPrecisionSlider->set_inverted(false);
- _fallbackPrecisionSlider->set_digits(1);
- _fallbackPrecisionSlider->set_draw_value(true);
- _fallbackPrecisionSlider->set_value_pos(Gtk::POS_TOP);
- _labelPrecisionComment->set_size_request(90,-1);
- _labelPrecisionComment->set_alignment(0.5,0.5);
- _labelPrecisionComment->set_padding(4,0);
- _labelPrecisionComment->set_justify(Gtk::JUSTIFY_LEFT);
- _labelPrecisionComment->set_line_wrap(false);
- _labelPrecisionComment->set_use_markup(false);
- _labelPrecisionComment->set_selectable(false);
- hbox6->pack_start(*_fallbackPrecisionSlider, Gtk::PACK_SHRINK, 4);
- hbox6->pack_start(*_labelPrecisionComment, Gtk::PACK_SHRINK, 0);
- _labelText->set_alignment(0.5,0.5);
- _labelText->set_padding(4,0);
- _labelText->set_justify(Gtk::JUSTIFY_LEFT);
- _labelText->set_line_wrap(false);
- _labelText->set_use_markup(false);
- _labelText->set_selectable(false);
- hbox5->pack_start(*_labelText, Gtk::PACK_SHRINK, 0);
- hbox5->pack_start(*_textHandlingCombo, Gtk::PACK_SHRINK, 0);
- _localFontsCheck->set_can_focus();
- _localFontsCheck->set_relief(Gtk::RELIEF_NORMAL);
- _localFontsCheck->set_mode(true);
- _localFontsCheck->set_active(true);
- _embedImagesCheck->set_can_focus();
- _embedImagesCheck->set_relief(Gtk::RELIEF_NORMAL);
- _embedImagesCheck->set_mode(true);
- _embedImagesCheck->set_active(true);
- vbox3->pack_start(*_labelPrecision, Gtk::PACK_SHRINK, 0);
- vbox3->pack_start(*hbox6, Gtk::PACK_SHRINK, 0);
- vbox3->pack_start(*_labelPrecisionWarning, Gtk::PACK_SHRINK, 0);
- vbox3->pack_start(*hbox5, Gtk::PACK_SHRINK, 4);
- vbox3->pack_start(*_localFontsCheck, Gtk::PACK_SHRINK, 0);
- vbox3->pack_start(*_embedImagesCheck, Gtk::PACK_SHRINK, 0);
- _importSettingsFrame->add(*vbox3);
- _importSettingsFrame->set_border_width(4);
- vbox1->pack_start(*_pageSettingsFrame, Gtk::PACK_EXPAND_PADDING, 0);
- vbox1->pack_start(*_importSettingsFrame, Gtk::PACK_EXPAND_PADDING, 0);
- hbox1->pack_start(*vbox1);
- hbox1->pack_start(*_previewArea, Gtk::PACK_EXPAND_WIDGET, 4);
-
-#if WITH_GTKMM_3_0
- get_content_area()->set_homogeneous(false);
- get_content_area()->set_spacing(0);
- get_content_area()->pack_start(*hbox1);
-#else
- this->get_vbox()->set_homogeneous(false);
- this->get_vbox()->set_spacing(0);
- this->get_vbox()->pack_start(*hbox1);
-#endif
-
- this->set_title(_("PDF Import Settings"));
- this->set_modal(true);
- sp_transientize(GTK_WIDGET(this->gobj())); //Make transient
- this->property_window_position().set_value(Gtk::WIN_POS_NONE);
- this->set_resizable(true);
- this->property_destroy_with_parent().set_value(false);
- this->add_action_widget(*cancelbutton, -6);
- this->add_action_widget(*okbutton, -5);
- cancelbutton->show();
- okbutton->show();
- _labelSelect->show();
- _pageNumberSpin->show();
- _labelTotalPages->show();
- hbox2->show();
- _cropCheck->show();
- _cropTypeCombo->show();
- hbox3->show();
- vbox2->show();
- _pageSettingsFrame->show();
- _labelPrecision->show();
- _labelPrecisionWarning->show();
- _fallbackPrecisionSlider->show();
- _labelPrecisionComment->show();
- hbox6->show();
- _labelText->show();
- _textHandlingCombo->show();
- hbox5->show();
- _localFontsCheck->show();
- _embedImagesCheck->show();
- vbox3->show();
- _importSettingsFrame->show();
- vbox1->show();
- _previewArea->show();
- hbox1->show();
-
- // Connect signals
-#if WITH_GTKMM_3_0
- _previewArea->signal_draw().connect(sigc::mem_fun(*this, &PdfImportCairoDialog::_onDraw));
-#else
- _previewArea->signal_expose_event().connect(sigc::mem_fun(*this, &PdfImportCairoDialog::_onExposePreview));
-#endif
- _pageNumberSpin_adj->signal_value_changed().connect(sigc::mem_fun(*this, &PdfImportCairoDialog::_onPageNumberChanged));
- _cropCheck->signal_toggled().connect(sigc::mem_fun(*this, &PdfImportCairoDialog::_onToggleCropping));
- _fallbackPrecisionSlider_adj->signal_value_changed().connect(sigc::mem_fun(*this, &PdfImportCairoDialog::_onPrecisionChanged));
-
- _render_thumb = false;
- _cairo_surface = NULL;
- _render_thumb = true;
-
- // Set default preview size
- _preview_width = 200;
- _preview_height = 300;
-
- // Init preview
- _thumb_data = NULL;
- _pageNumberSpin_adj->set_value(1.0);
- _current_page = 1;
- _setPreviewPage(_current_page);
-
- set_default (*okbutton);
- set_focus (*okbutton);
-}
-
-PdfImportCairoDialog::~PdfImportCairoDialog() {
- if (_cairo_surface) {
- cairo_surface_destroy(_cairo_surface);
- }
- if (_thumb_data) {
- if (_render_thumb) {
- delete _thumb_data;
- } else {
- // -->gfree(_thumb_data);
- delete _thumb_data;
- }
- }
-}
-
-bool PdfImportCairoDialog::showDialog() {
- show();
- gint b = run();
- hide();
- if ( b == Gtk::RESPONSE_OK ) {
- return TRUE;
- } else {
- return FALSE;
- }
-}
-
-int PdfImportCairoDialog::getSelectedPage() {
- return _current_page;
-}
-
-/**
- * \brief Retrieves the current settings into a repr which SvgBuilder will use
- * for determining the behaviour desired by the user
- */
-void PdfImportCairoDialog::getImportSettings(Inkscape::XML::Node *prefs) {
- sp_repr_set_svg_double(prefs, "selectedPage", (double)_current_page);
- if (_cropCheck->get_active()) {
- Glib::ustring current_choice = _cropTypeCombo->get_active_text();
- int num_crop_choices = sizeof(crop_setting_choices) / sizeof(crop_setting_choices[0]);
- int i = 0;
- for ( ; i < num_crop_choices ; i++ ) {
- if ( current_choice == _(crop_setting_choices[i]) ) {
- break;
- }
- }
- sp_repr_set_svg_double(prefs, "cropTo", (double)i);
- } else {
- sp_repr_set_svg_double(prefs, "cropTo", -1.0);
- }
- sp_repr_set_svg_double(prefs, "approximationPrecision",
- _fallbackPrecisionSlider->get_value());
- if (_localFontsCheck->get_active()) {
- prefs->setAttribute("localFonts", "1");
- } else {
- prefs->setAttribute("localFonts", "0");
- }
- if (_embedImagesCheck->get_active()) {
- prefs->setAttribute("embedImages", "1");
- } else {
- prefs->setAttribute("embedImages", "0");
- }
-}
-
-/**
- * \brief Redisplay the comment on the current approximation precision setting
- * Evenly divides the interval of possible values between the available labels.
- */
-void PdfImportCairoDialog::_onPrecisionChanged() {
-
- static Glib::ustring precision_comments[] = {
- Glib::ustring(C_("PDF input precision", "rough")),
- Glib::ustring(C_("PDF input precision", "medium")),
- Glib::ustring(C_("PDF input precision", "fine")),
- Glib::ustring(C_("PDF input precision", "very fine"))
- };
-
- double min = _fallbackPrecisionSlider_adj->get_lower();
- double max = _fallbackPrecisionSlider_adj->get_upper();
- int num_intervals = sizeof(precision_comments) / sizeof(precision_comments[0]);
- double interval_len = ( max - min ) / (double)num_intervals;
- double value = _fallbackPrecisionSlider_adj->get_value();
- int comment_idx = (int)floor( ( value - min ) / interval_len );
- _labelPrecisionComment->set_label(precision_comments[comment_idx]);
-}
-
-void PdfImportCairoDialog::_onToggleCropping() {
- _cropTypeCombo->set_sensitive(_cropCheck->get_active());
-}
-
-void PdfImportCairoDialog::_onPageNumberChanged() {
- int page = _pageNumberSpin->get_value_as_int();
- _current_page = CLAMP(page, 1, poppler_document_get_n_pages(_poppler_doc));
- _setPreviewPage(_current_page);
-}
-
-/**
- * \brief Copies image data from a Cairo surface to a pixbuf
- *
- * Borrowed from libpoppler, from the file poppler-page.cc
- * Copyright (C) 2005, Red Hat, Inc.
- *
- */
-static void copy_cairo_surface_to_pixbuf (cairo_surface_t *surface,
- unsigned char *data,
- GdkPixbuf *pixbuf)
-{
- int cairo_width, cairo_height, cairo_rowstride;
- unsigned char *pixbuf_data, *dst, *cairo_data;
- int pixbuf_rowstride, pixbuf_n_channels;
- unsigned int *src;
- int x, y;
-
- cairo_width = cairo_image_surface_get_width (surface);
- cairo_height = cairo_image_surface_get_height (surface);
- cairo_rowstride = cairo_width * 4;
- cairo_data = data;
-
- pixbuf_data = gdk_pixbuf_get_pixels (pixbuf);
- pixbuf_rowstride = gdk_pixbuf_get_rowstride (pixbuf);
- pixbuf_n_channels = gdk_pixbuf_get_n_channels (pixbuf);
-
- if (cairo_width > gdk_pixbuf_get_width (pixbuf))
- cairo_width = gdk_pixbuf_get_width (pixbuf);
- if (cairo_height > gdk_pixbuf_get_height (pixbuf))
- cairo_height = gdk_pixbuf_get_height (pixbuf);
- for (y = 0; y < cairo_height; y++)
- {
- src = reinterpret_cast<unsigned int *>(cairo_data + y * cairo_rowstride);
- dst = pixbuf_data + y * pixbuf_rowstride;
- for (x = 0; x < cairo_width; x++)
- {
- dst[0] = (*src >> 16) & 0xff;
- dst[1] = (*src >> 8) & 0xff;
- dst[2] = (*src >> 0) & 0xff;
- if (pixbuf_n_channels == 4)
- dst[3] = (*src >> 24) & 0xff;
- dst += pixbuf_n_channels;
- src++;
- }
- }
-}
-
-/**
- * \brief Updates the preview area with the previously rendered thumbnail
- */
-#if !WITH_GTKMM_3_0
-bool PdfImportCairoDialog::_onExposePreview(GdkEventExpose * /*event*/) {
- Cairo::RefPtr<Cairo::Context> cr = _previewArea->get_window()->create_cairo_context();
- return _onDraw(cr);
-}
-#endif
-
-
-bool PdfImportCairoDialog::_onDraw(const Cairo::RefPtr<Cairo::Context>& cr) {
- // Check if we have a thumbnail at all
- if (!_thumb_data) {
- return true;
- }
-
- // Create the pixbuf for the thumbnail
- Glib::RefPtr<Gdk::Pixbuf> thumb;
- if (_render_thumb) {
- thumb = Gdk::Pixbuf::create(Gdk::COLORSPACE_RGB, true,
- 8, _thumb_width, _thumb_height);
- } else {
- thumb = Gdk::Pixbuf::create_from_data(_thumb_data, Gdk::COLORSPACE_RGB,
- false, 8, _thumb_width, _thumb_height, _thumb_rowstride);
- }
- if (!thumb) {
- return true;
- }
-
- // Set background to white
- if (_render_thumb) {
- thumb->fill(0xffffffff);
- Gdk::Cairo::set_source_pixbuf(cr, thumb, 0, 0);
- cr->paint();
- }
-
- // Copy the thumbnail image from the Cairo surface
- if (_render_thumb) {
- copy_cairo_surface_to_pixbuf(_cairo_surface, _thumb_data, thumb->gobj());
- }
- Gdk::Cairo::set_source_pixbuf(cr, thumb, 0, _render_thumb ? 0 : 20);
- cr->paint();
-
- return true;
-}
-
-/**
- * \brief Renders the given page's thumbnail using Cairo
- */
-void PdfImportCairoDialog::_setPreviewPage(int page) {
-
- PopplerPage *_previewed_page = poppler_document_get_page(_poppler_doc, page-1);
-
- // Try to get a thumbnail from the PDF if possible
- if (!_render_thumb) {
- if (_thumb_data) {
- // --> gfree(_thumb_data);
- free(_thumb_data);
- _thumb_data = NULL;
- }
-
-/*
---> if (!_previewed_page->loadThumb(&_thumb_data,
- &_thumb_width, &_thumb_height, &_thumb_rowstride)) {
- return;
- }
-*/
- // Redraw preview area
- _previewArea->set_size_request(_thumb_width, _thumb_height + 20);
- _previewArea->queue_draw();
- return;
- }
-
- // Get page size by accounting for rotation
- double width, height;
- // --> int rotate = _previewed_page->getRotate();
- int rotate = 0;
- if ( rotate == 90 || rotate == 270 ) {
-// --> height = _previewed_page->getCropWidth();
-// --> width = _previewed_page->getCropHeight();
- } else {
- poppler_page_get_size (_previewed_page, &width, &height);
-// --> width = _previewed_page->getCropWidth();
-// --> height = _previewed_page->getCropHeight();
- }
- // Calculate the needed scaling for the page
- double scale_x = (double)_preview_width / width;
- double scale_y = (double)_preview_height / height;
- double scale_factor = ( scale_x > scale_y ) ? scale_y : scale_x;
- // Create new Cairo surface
- _thumb_width = (int)ceil( width * scale_factor );
- _thumb_height = (int)ceil( height * scale_factor );
- _thumb_rowstride = _thumb_width * 4;
- if (_thumb_data) {
- delete _thumb_data;
- }
- _thumb_data = new unsigned char[ _thumb_rowstride * _thumb_height ];
- if (_cairo_surface) {
- cairo_surface_destroy(_cairo_surface);
- }
- _cairo_surface = cairo_image_surface_create_for_data(_thumb_data,
- CAIRO_FORMAT_ARGB32, _thumb_width, _thumb_height, _thumb_rowstride);
- cairo_t *cr = cairo_create(_cairo_surface);
- cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 1.0); // Set fill color to white
- cairo_paint(cr); // Clear it
- cairo_scale(cr, scale_factor, scale_factor); // Use Cairo for resizing the image
- // Render page
- if (_poppler_doc != NULL) {
- PopplerPage *poppler_page = poppler_document_get_page(_poppler_doc, page - 1);
- poppler_page_render(poppler_page, cr);
- g_object_unref(G_OBJECT(poppler_page));
- }
- // Clean up
- cairo_destroy(cr);
- // Redraw preview area
- _previewArea->set_size_request(_preview_width, _preview_height);
- _previewArea->queue_draw();
-
-}
-
-
-static cairo_status_t _write_ustring_cb(void *closure, const unsigned char *data, unsigned int length);
-
-SPDocument *
-PdfInputCairo::open(Inkscape::Extension::Input * /*mod*/, const gchar * uri) {
-
- g_message("Attempting to open using PdfInputCairo\n");
-
- gchar* filename_uri = g_filename_to_uri(uri, NULL, NULL);
-
- GError *error = NULL;
- /// @todo handle passwort
- /// @todo check if win32 unicode needs special attention
- PopplerDocument* document = poppler_document_new_from_file(filename_uri, NULL, &error);
-
- if(error != NULL) {
- g_message("Unable to read file: %s\n", error->message);
- g_error_free (error);
- }
-
- if (document == NULL) {
- return NULL;
- }
-
- // create and show the import dialog
- PdfImportCairoDialog *dlg = NULL;
- if (inkscape_use_gui()) {
- dlg = new PdfImportCairoDialog(document);
- if (!dlg->showDialog()) {
- delete dlg;
- return NULL;
- }
- }
-
- // Get needed page
- int page_num;
- if (dlg) {
- page_num = dlg->getSelectedPage();
- delete dlg;
- }
- else
- page_num = 1;
-
- double width, height;
- PopplerPage* page = poppler_document_get_page(document, page_num - 1);
- poppler_page_get_size(page, &width, &height);
-
- Glib::ustring* output = new Glib::ustring("");
- cairo_surface_t* surface = cairo_svg_surface_create_for_stream(Inkscape::Extension::Internal::_write_ustring_cb,
- output, width, height);
- cairo_t* cr = cairo_create(surface);
-
- poppler_page_render(page, cr);
- cairo_show_page(cr);
-
- cairo_destroy(cr);
- cairo_surface_destroy(surface);
-
- SPDocument * doc = SPDocument::createNewDocFromMem(output->c_str(), output->length(), TRUE);
-
- // Set viewBox if it doesn't exist
- if (doc && !doc->getRoot()->viewBox_set) {
- doc->setViewBox(Geom::Rect::from_xywh(0, 0, doc->getWidth().value(doc->getDefaultUnit()), doc->getHeight().value(doc->getDefaultUnit())));
- }
-
- delete output;
- g_object_unref(page);
- g_object_unref(document);
-
- return doc;
-}
-
-static cairo_status_t
- _write_ustring_cb(void *closure, const unsigned char *data, unsigned int length)
-{
- Glib::ustring* stream = static_cast<Glib::ustring*>(closure);
- stream->append(reinterpret_cast<const char*>(data), length);
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-
-#include "clear-n_.h"
-
-void
-PdfInputCairo::init(void) {
- Inkscape::Extension::build_from_mem(
- "<inkscape-extension xmlns=\"" INKSCAPE_EXTENSION_URI "\">\n"
- "<name>" N_("PDF Input") "</name>\n"
- "<id>org.inkscape.input.cairo-pdf</id>\n"
- "<input>\n"
- "<extension>.pdf</extension>\n"
- "<mimetype>application/pdf</mimetype>\n"
- "<filetypename>" N_("Adobe PDF via poppler-cairo (*.pdf)") "</filetypename>\n"
- "<filetypetooltip>" N_("PDF Document") "</filetypetooltip>\n"
- "</input>\n"
- "</inkscape-extension>", new PdfInputCairo());
-} // init
-
-} } } /* namespace Inkscape, Extension, Implementation */
-
-#endif /* HAVE_POPPLER_CAIRO */
-#endif /* HAVE_POPPLER_GLIB */
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/extension/internal/pdf-input-cairo.h b/src/extension/internal/pdf-input-cairo.h
deleted file mode 100644
index b65d22f48..000000000
--- a/src/extension/internal/pdf-input-cairo.h
+++ /dev/null
@@ -1,157 +0,0 @@
-#ifndef __EXTENSION_INTERNAL_PDFINPUTCAIRO_H__
-#define __EXTENSION_INTERNAL_PDFINPUTCAIRO_H__
-
-/*
- * PDF input using libpoppler and Cairo's SVG surface.
- *
- * Authors:
- * miklos erdelyi
- *
- * Copyright (C) 2007 Authors
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#if GLIBMM_DISABLE_DEPRECATED && HAVE_GLIBMM_THREADS_H
-#include <glibmm/threads.h>
-#endif
-
-#include <gtkmm/dialog.h>
-#include <gtkmm/button.h>
-#include <gtkmm/buttonbox.h>
-#include <gtkmm/label.h>
-#include <gtkmm/box.h>
-#include <gtkmm/checkbutton.h>
-#include <gtkmm/comboboxtext.h>
-#include <gtkmm/drawingarea.h>
-#include <gtkmm/alignment.h>
-#include <gtkmm/frame.h>
-#include <gtkmm/scale.h>
-#include <glibmm/i18n.h>
-#include <gdk/gdk.h>
-
-#ifdef HAVE_POPPLER_GLIB
-#ifdef HAVE_POPPLER_CAIRO
-
-#include <poppler/glib/poppler.h>
-
-#include "../implementation/implementation.h"
-
-namespace Gtk {
-#if WITH_GTKMM_3_0
- class Scale;
-#else
- class HScale;
-#endif
-}
-
-namespace Inkscape {
-
-namespace UI {
-namespace Widget {
- class SpinButton;
- class Frame;
-}
-}
-
-namespace Extension {
-namespace Internal {
-
-class PdfImportCairoDialog : public Gtk::Dialog
-{
-public:
- PdfImportCairoDialog(PopplerDocument* doc);
- virtual ~PdfImportCairoDialog();
-
- bool showDialog();
- int getSelectedPage();
- void getImportSettings(Inkscape::XML::Node *prefs);
-
-private:
- void _setPreviewPage(int page);
-
- // Signal handlers
-#if !WITH_GTKMM_3_0
- bool _onExposePreview(GdkEventExpose *event);
-#endif
-
- bool _onDraw(const Cairo::RefPtr<Cairo::Context>& cr);
- void _onPageNumberChanged();
- void _onToggleCropping();
- void _onPrecisionChanged();
-
- class Gtk::Button * cancelbutton;
- class Gtk::Button * okbutton;
- class Gtk::Label * _labelSelect;
- class Inkscape::UI::Widget::SpinButton * _pageNumberSpin;
- class Gtk::Label * _labelTotalPages;
- class Gtk::HBox * hbox2;
- class Gtk::CheckButton * _cropCheck;
- class Gtk::ComboBoxText * _cropTypeCombo;
- class Gtk::HBox * hbox3;
- class Gtk::VBox * vbox2;
- class Inkscape::UI::Widget::Frame * _pageSettingsFrame;
- class Gtk::Label * _labelPrecision;
- class Gtk::Label * _labelPrecisionWarning;
-#if WITH_GTKMM_3_0
- class Gtk::Scale * _fallbackPrecisionSlider;
- Glib::RefPtr<Gtk::Adjustment> _fallbackPrecisionSlider_adj;
-#else
- class Gtk::HScale * _fallbackPrecisionSlider;
- class Gtk::Adjustment *_fallbackPrecisionSlider_adj;
-#endif
- class Gtk::Label * _labelPrecisionComment;
- class Gtk::HBox * hbox6;
- class Gtk::Label * _labelText;
- class Gtk::ComboBoxText * _textHandlingCombo;
- class Gtk::HBox * hbox5;
- class Gtk::CheckButton * _localFontsCheck;
- class Gtk::CheckButton * _embedImagesCheck;
- class Gtk::VBox * vbox3;
- class Inkscape::UI::Widget::Frame * _importSettingsFrame;
- class Gtk::VBox * vbox1;
- class Gtk::DrawingArea * _previewArea;
- class Gtk::HBox * hbox1;
-
- PopplerDocument *_poppler_doc;
- // PopplerPage *_previewed_page;
- int _current_page; // Current selected page
- unsigned char *_thumb_data; // Thumbnail image data
- int _thumb_width, _thumb_height; // Thumbnail size
- int _thumb_rowstride;
- int _preview_width, _preview_height; // Size of the preview area
- bool _render_thumb; // Whether we can/shall render thumbnails
- cairo_surface_t *_cairo_surface; // this cairo surface is used for preview
-};
-
-
-class PdfInputCairo: public Inkscape::Extension::Implementation::Implementation {
- PdfInputCairo () { };
-public:
- SPDocument *open( Inkscape::Extension::Input *mod,
- const gchar *uri );
- static void init( void );
-
-};
-
-} } } /* namespace Inkscape, Extension, Implementation */
-
-#endif /* HAVE_POPPLER_CAIRO */
-#endif /* HAVE_POPPLER_GLIB */
-
-#endif /* __EXTENSION_INTERNAL_PDFINPUTCAIRO_H__ */
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/extension/internal/pdfinput/pdf-input.cpp b/src/extension/internal/pdfinput/pdf-input.cpp
index 3155ac098..c8a7feabf 100644
--- a/src/extension/internal/pdfinput/pdf-input.cpp
+++ b/src/extension/internal/pdfinput/pdf-input.cpp
@@ -48,7 +48,7 @@
#include "inkscape.h"
#include "util/units.h"
-#include "dialogs/dialog-events.h"
+#include "ui/dialog-events.h"
#include <gtk/gtk.h>
#include "ui/widget/spinbutton.h"
#include "ui/widget/frame.h"
@@ -124,6 +124,9 @@ PdfImportDialog::PdfImportDialog(PDFDoc *doc, const gchar */*uri*/)
_labelPrecision = Gtk::manage(new class Gtk::Label(_("Precision of approximating gradient meshes:")));
_labelPrecisionWarning = Gtk::manage(new class Gtk::Label(_("<b>Note</b>: setting the precision too high may result in a large SVG file and slow performance.")));
+#ifdef HAVE_POPPLER_CAIRO
+ _importviaPopplerCheck = Gtk::manage(new class Gtk::CheckButton(_("import via Poppler")));
+#endif
#if WITH_GTKMM_3_0
_fallbackPrecisionSlider_adj = Gtk::Adjustment::create(2, 1, 256, 1, 10, 10);
_fallbackPrecisionSlider = Gtk::manage(new class Gtk::Scale(_fallbackPrecisionSlider_adj));
@@ -199,6 +202,12 @@ PdfImportDialog::PdfImportDialog(PDFDoc *doc, const gchar */*uri*/)
_labelPrecisionWarning->set_line_wrap(true);
_labelPrecisionWarning->set_use_markup(true);
_labelPrecisionWarning->set_selectable(false);
+#ifdef HAVE_POPPLER_CAIRO
+ _importviaPopplerCheck->set_can_focus();
+ _importviaPopplerCheck->set_relief(Gtk::RELIEF_NORMAL);
+ _importviaPopplerCheck->set_mode(true);
+ _importviaPopplerCheck->set_active(false);
+#endif
_fallbackPrecisionSlider->set_size_request(180,-1);
_fallbackPrecisionSlider->set_can_focus();
_fallbackPrecisionSlider->set_inverted(false);
@@ -230,6 +239,9 @@ PdfImportDialog::PdfImportDialog(PDFDoc *doc, const gchar */*uri*/)
_embedImagesCheck->set_relief(Gtk::RELIEF_NORMAL);
_embedImagesCheck->set_mode(true);
_embedImagesCheck->set_active(true);
+#ifdef HAVE_POPPLER_CAIRO
+ vbox3->pack_start(*_importviaPopplerCheck, Gtk::PACK_SHRINK, 0);
+#endif
vbox3->pack_start(*_labelPrecision, Gtk::PACK_SHRINK, 0);
vbox3->pack_start(*hbox6, Gtk::PACK_SHRINK, 0);
vbox3->pack_start(*_labelPrecisionWarning, Gtk::PACK_SHRINK, 0);
@@ -274,6 +286,9 @@ PdfImportDialog::PdfImportDialog(PDFDoc *doc, const gchar */*uri*/)
_pageSettingsFrame->show();
_labelPrecision->show();
_labelPrecisionWarning->show();
+#ifdef HAVE_POPPLER_CAIRO
+ _importviaPopplerCheck->show();
+#endif
_fallbackPrecisionSlider->show();
_labelPrecisionComment->show();
hbox6->show();
@@ -358,6 +373,14 @@ int PdfImportDialog::getSelectedPage() {
return _current_page;
}
+int PdfImportDialog::getImportMethod() {
+#ifdef HAVE_POPPLER_CAIRO
+ return (_importviaPopplerCheck->get_active()) ? 1 : 0;
+#else
+ return 0;
+#endif
+}
+
/**
* \brief Retrieves the current settings into a repr which SvgBuilder will use
* for determining the behaviour desired by the user
@@ -389,6 +412,13 @@ void PdfImportDialog::getImportSettings(Inkscape::XML::Node *prefs) {
} else {
prefs->setAttribute("embedImages", "0");
}
+#ifdef HAVE_POPPLER_CAIRO
+ if (_importviaPopplerCheck->get_active()) {
+ prefs->setAttribute("importviapoppler", "1");
+ } else {
+ prefs->setAttribute("importviapoppler", "0");
+ }
+#endif
}
/**
@@ -595,6 +625,18 @@ PdfInput::wasCancelled () {
return _cancelled;
}
+#ifdef HAVE_POPPLER_CAIRO
+/// helper method
+static cairo_status_t
+ _write_ustring_cb(void *closure, const unsigned char *data, unsigned int length)
+{
+ Glib::ustring* stream = static_cast<Glib::ustring*>(closure);
+ stream->append(reinterpret_cast<const char*>(data), length);
+
+ return CAIRO_STATUS_SUCCESS;
+}
+#endif
+
/**
* Parses the selected page of the given PDF document using PdfParser.
*/
@@ -605,7 +647,31 @@ PdfInput::open(::Inkscape::Extension::Input * /*mod*/, const gchar * uri) {
// Initialize the globalParams variable for poppler
if (!globalParams) {
+#ifdef ENABLE_OSX_APP_LOCATIONS
+ //
+ // data files for poppler are not relocatable (loaded from
+ // path defined at build time). This fails to work with relocatable
+ // application bundles for OS X.
+ //
+ // Workaround:
+ // 1. define $POPPLER_DATADIR env variable in app launcher script
+ // 2. pass custom $POPPLER_DATADIR via poppler's GlobalParams()
+ //
+ // relevant poppler commit:
+ // <http://cgit.freedesktop.org/poppler/poppler/commit/?id=869584a84eed507775ff1c3183fe484c14b6f77b>
+ //
+ // FIXES: Inkscape bug #956282, #1264793
+ // TODO: report RFE upstream (full relocation support for OS X packaging)
+ //
+ gchar const *poppler_datadir = g_getenv("POPPLER_DATADIR");
+ if (poppler_datadir != NULL) {
+ globalParams = new GlobalParams(poppler_datadir);
+ } else {
+ globalParams = new GlobalParams();
+ }
+#else
globalParams = new GlobalParams();
+#endif // ENABLE_OSX_APP_LOCATIONS
}
// poppler does not use glib g_open. So on win32 we must use unicode call. code was copied from glib gstdio.c
#ifndef WIN32
@@ -672,79 +738,146 @@ PdfInput::open(::Inkscape::Extension::Input * /*mod*/, const gchar * uri) {
page_num = 1;
Catalog *catalog = pdf_doc->getCatalog();
Page *page = catalog->getPage(page_num);
+
+ int is_importvia_poppler = 0;
+ if(dlg)
+ {
+#ifdef HAVE_POPPLER_CAIRO
+ is_importvia_poppler = dlg->getImportMethod();
+#endif
+ }
- SPDocument *doc = SPDocument::createNewDoc(NULL, TRUE, TRUE);
- bool saved = DocumentUndo::getUndoSensitive(doc);
- DocumentUndo::setUndoSensitive(doc, false); // No need to undo in this temporary document
+ SPDocument *doc = NULL;
+ bool saved = false;
+ if(is_importvia_poppler == 0)
+ {
+ // native importer
+ doc = SPDocument::createNewDoc(NULL, TRUE, TRUE);
+ saved = DocumentUndo::getUndoSensitive(doc);
+ DocumentUndo::setUndoSensitive(doc, false); // No need to undo in this temporary document
+
+ // Create builder
+ gchar *docname = g_path_get_basename(uri);
+ gchar *dot = g_strrstr(docname, ".");
+ if (dot) {
+ *dot = 0;
+ }
+ SvgBuilder *builder = new SvgBuilder(doc, docname, pdf_doc->getXRef());
+
+ // Get preferences
+ Inkscape::XML::Node *prefs = builder->getPreferences();
+ if (dlg)
+ dlg->getImportSettings(prefs);
+
+ printf("pdf import via %s.", (is_importvia_poppler != 0) ? "poppler" : "native");
+
+ // Apply crop settings
+ PDFRectangle *clipToBox = NULL;
+ double crop_setting;
+ sp_repr_get_double(prefs, "cropTo", &crop_setting);
+ if ( crop_setting >= 0.0 ) { // Do page clipping
+ int crop_choice = (int)crop_setting;
+ switch (crop_choice) {
+ case 0: // Media box
+ clipToBox = page->getMediaBox();
+ break;
+ case 1: // Crop box
+ clipToBox = page->getCropBox();
+ break;
+ case 2: // Bleed box
+ clipToBox = page->getBleedBox();
+ break;
+ case 3: // Trim box
+ clipToBox = page->getTrimBox();
+ break;
+ case 4: // Art box
+ clipToBox = page->getArtBox();
+ break;
+ default:
+ break;
+ }
+ }
- // Create builder
- gchar *docname = g_path_get_basename(uri);
- gchar *dot = g_strrstr(docname, ".");
- if (dot) {
- *dot = 0;
- }
- SvgBuilder *builder = new SvgBuilder(doc, docname, pdf_doc->getXRef());
+ // Create parser
+ PdfParser *pdf_parser = new PdfParser(pdf_doc->getXRef(), builder, page_num-1, page->getRotate(),
+ page->getResourceDict(), page->getCropBox(), clipToBox);
- // Get preferences
- Inkscape::XML::Node *prefs = builder->getPreferences();
- if (dlg)
- dlg->getImportSettings(prefs);
-
- // Apply crop settings
- PDFRectangle *clipToBox = NULL;
- double crop_setting;
- sp_repr_get_double(prefs, "cropTo", &crop_setting);
- if ( crop_setting >= 0.0 ) { // Do page clipping
- int crop_choice = (int)crop_setting;
- switch (crop_choice) {
- case 0: // Media box
- clipToBox = page->getMediaBox();
- break;
- case 1: // Crop box
- clipToBox = page->getCropBox();
- break;
- case 2: // Bleed box
- clipToBox = page->getBleedBox();
- break;
- case 3: // Trim box
- clipToBox = page->getTrimBox();
- break;
- case 4: // Art box
- clipToBox = page->getArtBox();
- break;
- default:
- break;
+ // Set up approximation precision for parser
+ double color_delta;
+ sp_repr_get_double(prefs, "approximationPrecision", &color_delta);
+ if ( color_delta <= 0.0 ) {
+ color_delta = 1.0 / 2.0;
+ } else {
+ color_delta = 1.0 / color_delta;
+ }
+ for ( int i = 1 ; i <= pdfNumShadingTypes ; i++ ) {
+ pdf_parser->setApproximationPrecision(i, color_delta, 6);
}
- }
- // Create parser
- PdfParser *pdf_parser = new PdfParser(pdf_doc->getXRef(), builder, page_num-1, page->getRotate(),
- page->getResourceDict(), page->getCropBox(), clipToBox);
+ // Parse the document structure
+ Object obj;
+ page->getContents(&obj);
+ if (!obj.isNull()) {
+ pdf_parser->parse(&obj);
+ }
- // Set up approximation precision for parser
- double color_delta;
- sp_repr_get_double(prefs, "approximationPrecision", &color_delta);
- if ( color_delta <= 0.0 ) {
- color_delta = 1.0 / 2.0;
- } else {
- color_delta = 1.0 / color_delta;
- }
- for ( int i = 1 ; i <= pdfNumShadingTypes ; i++ ) {
- pdf_parser->setApproximationPrecision(i, color_delta, 6);
+ // Cleanup
+ obj.free();
+ delete pdf_parser;
+ delete builder;
+ g_free(docname);
}
+ else
+ {
+#ifdef HAVE_POPPLER_CAIRO
+ // the poppler import
+ gchar* filename_uri = g_filename_to_uri(uri, NULL, NULL);
+ GError *error = NULL;
+ /// @todo handle passwort
+ /// @todo check if win32 unicode needs special attention
+ PopplerDocument* document = poppler_document_new_from_file(filename_uri, NULL, &error);
+
+ if(error != NULL) {
+ g_error_free (error);
+ }
- // Parse the document structure
- Object obj;
- page->getContents(&obj);
- if (!obj.isNull()) {
- pdf_parser->parse(&obj);
+ if (document != NULL)
+ {
+ double width, height;
+ PopplerPage* page = poppler_document_get_page(document, page_num - 1);
+ poppler_page_get_size(page, &width, &height);
+
+ Glib::ustring output;
+ cairo_surface_t* surface = cairo_svg_surface_create_for_stream(Inkscape::Extension::Internal::_write_ustring_cb,
+ &output, width, height);
+ cairo_t* cr = cairo_create(surface);
+
+ poppler_page_render_for_printing(page, cr);
+ cairo_show_page(cr);
+
+ cairo_destroy(cr);
+ cairo_surface_destroy(surface);
+
+ doc = SPDocument::createNewDocFromMem(output.c_str(), output.length(), TRUE);
+
+ // Cleanup
+ // delete output;
+ g_object_unref(G_OBJECT(page));
+ g_object_unref(G_OBJECT(document));
+ }
+ else
+ {
+ doc = SPDocument::createNewDoc(NULL, TRUE, TRUE); // fallback create empthy document
+ }
+ saved = DocumentUndo::getUndoSensitive(doc);
+ DocumentUndo::setUndoSensitive(doc, false); // No need to undo in this temporary document
+
+ // Cleanup
+ g_free(filename_uri);
+#endif
}
// Cleanup
- obj.free();
- delete pdf_parser;
- delete builder;
- g_free(docname);
delete pdf_doc;
delete dlg;
diff --git a/src/extension/internal/pdfinput/pdf-input.h b/src/extension/internal/pdfinput/pdf-input.h
index f22a783ff..d57c3e993 100644
--- a/src/extension/internal/pdfinput/pdf-input.h
+++ b/src/extension/internal/pdfinput/pdf-input.h
@@ -75,6 +75,7 @@ public:
bool showDialog();
int getSelectedPage();
+ int getImportMethod();
void getImportSettings(Inkscape::XML::Node *prefs);
private:
@@ -103,6 +104,9 @@ private:
class Inkscape::UI::Widget::Frame * _pageSettingsFrame;
class Gtk::Label * _labelPrecision;
class Gtk::Label * _labelPrecisionWarning;
+#ifdef HAVE_POPPLER_CAIRO
+ class Gtk::CheckButton * _importviaPopplerCheck; // using poppler_cairo for importing
+#endif
#if WITH_GTKMM_3_0
class Gtk::Scale * _fallbackPrecisionSlider;
Glib::RefPtr<Gtk::Adjustment> _fallbackPrecisionSlider_adj;
diff --git a/src/extension/internal/pdfinput/pdf-parser.cpp b/src/extension/internal/pdfinput/pdf-parser.cpp
index b398486e6..0b7dc7905 100644
--- a/src/extension/internal/pdfinput/pdf-parser.cpp
+++ b/src/extension/internal/pdfinput/pdf-parser.cpp
@@ -247,30 +247,74 @@ PdfOperator PdfParser::opTab[] = {
#define numOps (sizeof(opTab) / sizeof(PdfOperator))
+namespace {
+
+GfxPatch blankPatch()
+{
+ GfxPatch patch;
+ memset(&patch, 0, sizeof(patch)); // quick-n-dirty
+ return patch;
+}
+
+} // namespace
+
//------------------------------------------------------------------------
-// PdfParser
+// ClipHistoryEntry
//------------------------------------------------------------------------
-PdfParser::PdfParser(XRef *xrefA, Inkscape::Extension::Internal::SvgBuilder *builderA,
- int /*pageNum*/, int rotate, Dict *resDict,
- PDFRectangle *box, PDFRectangle *cropBox)
-{
- xref = xrefA;
- subPage = gFalse;
- printCommands = false;
+class ClipHistoryEntry {
+public:
+
+ ClipHistoryEntry(GfxPath *clipPath = NULL, GfxClipType clipType = clipNormal);
+ virtual ~ClipHistoryEntry();
- // start the resource stack
- res = new GfxResources(xref, resDict, NULL);
+ // Manipulate clip path stack
+ ClipHistoryEntry *save();
+ ClipHistoryEntry *restore();
+ GBool hasSaves() { return saved != NULL; }
+ void setClip(GfxPath *newClipPath, GfxClipType newClipType = clipNormal);
+ GfxPath *getClipPath() { return clipPath; }
+ GfxClipType getClipType() { return clipType; }
- // initialize
- state = new GfxState(72.0, 72.0, box, rotate, gTrue);
- clipHistory = new ClipHistoryEntry();
+private:
+
+ ClipHistoryEntry *saved; // next clip path on stack
+
+ GfxPath *clipPath; // used as the path to be filled for an 'sh' operator
+ GfxClipType clipType;
+
+ ClipHistoryEntry(ClipHistoryEntry *other);
+};
+
+//------------------------------------------------------------------------
+// PdfParser
+//------------------------------------------------------------------------
+
+PdfParser::PdfParser(XRef *xrefA,
+ Inkscape::Extension::Internal::SvgBuilder *builderA,
+ int /*pageNum*/,
+ int rotate,
+ Dict *resDict,
+ PDFRectangle *box,
+ PDFRectangle *cropBox) :
+ xref(xrefA),
+ builder(builderA),
+ subPage(gFalse),
+ printCommands(false),
+ res(new GfxResources(xref, resDict, NULL)), // start the resource stack
+ state(new GfxState(72.0, 72.0, box, rotate, gTrue)),
+ fontChanged(gFalse),
+ clip(clipNone),
+ ignoreUndef(0),
+ baseMatrix(),
+ formDepth(0),
+ parser(NULL),
+ colorDeltas(),
+ maxDepths(),
+ clipHistory(new ClipHistoryEntry()),
+ operatorHistory(NULL)
+{
setDefaultApproximationPrecision();
- fontChanged = gFalse;
- clip = clipNone;
- ignoreUndef = 0;
- operatorHistory = NULL;
- builder = builderA;
builder->setDocumentSize(Inkscape::Util::Quantity::convert(state->getPageWidth(), "pt", "px"),
Inkscape::Util::Quantity::convert(state->getPageHeight(), "pt", "px"));
@@ -306,50 +350,62 @@ PdfParser::PdfParser(XRef *xrefA, Inkscape::Extension::Internal::SvgBuilder *bui
pushOperator("startPage");
}
-PdfParser::PdfParser(XRef *xrefA, Inkscape::Extension::Internal::SvgBuilder *builderA,
- Dict *resDict, PDFRectangle *box) {
-
- int i;
- parser = NULL;
-
- xref = xrefA;
- subPage = gTrue;
- printCommands = false;
-
- // start the resource stack
- res = new GfxResources(xref, resDict, NULL);
-
- // initialize
- operatorHistory = NULL;
- builder = builderA;
- state = new GfxState(72, 72, box, 0, gFalse);
- clipHistory = new ClipHistoryEntry();
+PdfParser::PdfParser(XRef *xrefA,
+ Inkscape::Extension::Internal::SvgBuilder *builderA,
+ Dict *resDict,
+ PDFRectangle *box) :
+ xref(xrefA),
+ builder(builderA),
+ subPage(gTrue),
+ printCommands(false),
+ res(new GfxResources(xref, resDict, NULL)), // start the resource stack
+ state(new GfxState(72, 72, box, 0, gFalse)),
+ fontChanged(gFalse),
+ clip(clipNone),
+ ignoreUndef(0),
+ baseMatrix(),
+ formDepth(0),
+ parser(NULL),
+ colorDeltas(),
+ maxDepths(),
+ clipHistory(new ClipHistoryEntry()),
+ operatorHistory(NULL)
+{
setDefaultApproximationPrecision();
- fontChanged = gFalse;
- clip = clipNone;
- ignoreUndef = 0;
- for (i = 0; i < 6; ++i) {
+ for (int i = 0; i < 6; ++i) {
baseMatrix[i] = state->getCTM()[i];
}
formDepth = 0;
}
PdfParser::~PdfParser() {
- while (state->hasSaves()) {
+ while(operatorHistory) {
+ OpHistoryEntry *tmp = operatorHistory->next;
+ delete operatorHistory;
+ operatorHistory = tmp;
+ }
+
+ while (state && state->hasSaves()) {
restoreState();
}
+
if (!subPage) {
//out->endPage();
}
+
while (res) {
popResources();
}
+
if (state) {
delete state;
+ state = NULL;
}
+
if (clipHistory) {
delete clipHistory;
+ clipHistory = NULL;
}
}
@@ -460,7 +516,8 @@ void PdfParser::go(GBool /*topLevel*/)
}
}
-void PdfParser::pushOperator(const char *name) {
+void PdfParser::pushOperator(const char *name)
+{
OpHistoryEntry *newEntry = new OpHistoryEntry;
newEntry->name = name;
newEntry->state = NULL;
@@ -866,7 +923,9 @@ void PdfParser::opSetExtGState(Object args[], int /*numArgs*/)
GBool isolated = gFalse;
GBool knockout = gFalse;
if (!obj4.dictLookup(const_cast<char*>("CS"), &obj5)->isNull()) {
-#if defined(POPPLER_NEW_COLOR_SPACE_API) || defined(POPPLER_NEW_ERRORAPI)
+#if defined(POPPLER_EVEN_NEWER_COLOR_SPACE_API)
+ blendingColorSpace = GfxColorSpace::parse(&obj5, NULL, NULL);
+#elif defined(POPPLER_NEW_COLOR_SPACE_API) || defined(POPPLER_NEW_ERRORAPI)
blendingColorSpace = GfxColorSpace::parse(&obj5, NULL);
#else
blendingColorSpace = GfxColorSpace::parse(&obj5);
@@ -1100,7 +1159,13 @@ void PdfParser::opSetFillColorSpace(Object args[], int /*numArgs*/)
res->lookupColorSpace(args[0].getName(), &obj);
GfxColorSpace *colorSpace = 0;
-#if defined(POPPLER_NEW_COLOR_SPACE_API) || defined(POPPLER_NEW_ERRORAPI)
+#if defined(POPPLER_EVEN_NEWER_COLOR_SPACE_API)
+ if (obj.isNull()) {
+ colorSpace = GfxColorSpace::parse(&args[0], NULL, NULL);
+ } else {
+ colorSpace = GfxColorSpace::parse(&obj, NULL, NULL);
+ }
+#elif defined(POPPLER_NEW_COLOR_SPACE_API) || defined(POPPLER_NEW_ERRORAPI)
if (obj.isNull()) {
colorSpace = GfxColorSpace::parse(&args[0], NULL);
} else {
@@ -1137,7 +1202,13 @@ void PdfParser::opSetStrokeColorSpace(Object args[], int /*numArgs*/)
state->setStrokePattern(NULL);
res->lookupColorSpace(args[0].getName(), &obj);
-#if defined(POPPLER_NEW_COLOR_SPACE_API) || defined(POPPLER_NEW_ERRORAPI)
+#if defined(POPPLER_EVEN_NEWER_COLOR_SPACE_API)
+ if (obj.isNull()) {
+ colorSpace = GfxColorSpace::parse(&args[0], NULL, NULL);
+ } else {
+ colorSpace = GfxColorSpace::parse(&obj, NULL, NULL);
+ }
+#elif defined(POPPLER_NEW_COLOR_SPACE_API) || defined(POPPLER_NEW_ERRORAPI)
if (obj.isNull()) {
colorSpace = GfxColorSpace::parse(&args[0], NULL);
} else {
@@ -1231,7 +1302,13 @@ void PdfParser::opSetFillColorN(Object args[], int numArgs) {
builder->updateStyle(state);
}
GfxPattern *pattern;
-#if defined(POPPLER_NEW_COLOR_SPACE_API) || defined(POPPLER_NEW_ERRORAPI)
+#if defined(POPPLER_EVEN_NEWER_COLOR_SPACE_API)
+ if (args[numArgs-1].isName() &&
+ (pattern = res->lookupPattern(args[numArgs-1].getName(), NULL, NULL))) {
+ state->setFillPattern(pattern);
+ builder->updateStyle(state);
+ }
+#elif defined(POPPLER_NEW_COLOR_SPACE_API) || defined(POPPLER_NEW_ERRORAPI)
if (args[numArgs-1].isName() &&
(pattern = res->lookupPattern(args[numArgs-1].getName(), NULL))) {
state->setFillPattern(pattern);
@@ -1291,7 +1368,13 @@ void PdfParser::opSetStrokeColorN(Object args[], int numArgs) {
builder->updateStyle(state);
}
GfxPattern *pattern;
-#if defined(POPPLER_NEW_COLOR_SPACE_API) || defined(POPPLER_NEW_ERRORAPI)
+#if defined(POPPLER_EVEN_NEWER_COLOR_SPACE_API)
+ if (args[numArgs-1].isName() &&
+ (pattern = res->lookupPattern(args[numArgs-1].getName(), NULL, NULL))) {
+ state->setStrokePattern(pattern);
+ builder->updateStyle(state);
+ }
+#elif defined(POPPLER_NEW_COLOR_SPACE_API) || defined(POPPLER_NEW_ERRORAPI)
if (args[numArgs-1].isName() &&
(pattern = res->lookupPattern(args[numArgs-1].getName(), NULL))) {
state->setStrokePattern(pattern);
@@ -1746,7 +1829,11 @@ void PdfParser::opShFill(Object args[], int /*numArgs*/)
double *matrix = NULL;
GBool savedState = gFalse;
-#if defined(POPPLER_NEW_COLOR_SPACE_API) || defined(POPPLER_NEW_ERRORAPI)
+#if defined(POPPLER_EVEN_NEWER_COLOR_SPACE_API)
+ if (!(shading = res->lookupShading(args[0].getName(), NULL, NULL))) {
+ return;
+ }
+#elif defined(POPPLER_NEW_COLOR_SPACE_API) || defined(POPPLER_NEW_ERRORAPI)
if (!(shading = res->lookupShading(args[0].getName(), NULL))) {
return;
}
@@ -2056,13 +2143,19 @@ void PdfParser::doPatchMeshShFill(GfxPatchMeshShading *shading) {
}
void PdfParser::fillPatch(GfxPatch *patch, int nComps, int depth) {
- GfxPatch patch00, patch01, patch10, patch11;
+ GfxPatch patch00 = blankPatch();
+ GfxPatch patch01 = blankPatch();
+ GfxPatch patch10 = blankPatch();
+ GfxPatch patch11 = blankPatch();
#ifdef POPPLER_NEW_GFXPATCH
- GfxColor color;
+ GfxColor color = {{0}};
#endif
- double xx[4][8], yy[4][8];
- double xxm, yym;
- double patchColorDelta = colorDeltas[pdfPatchMeshShading-1];
+ double xx[4][8];
+ double yy[4][8];
+ double xxm;
+ double yym;
+ double patchColorDelta = colorDeltas[pdfPatchMeshShading - 1];
+
int i;
for (i = 0; i < nComps; ++i) {
@@ -2817,7 +2910,9 @@ void PdfParser::doImage(Object * /*ref*/, Stream *str, GBool inlineImg)
}
}
if (!obj1.isNull()) {
-#if defined(POPPLER_NEW_COLOR_SPACE_API) || defined(POPPLER_NEW_ERRORAPI)
+#if defined(POPPLER_EVEN_NEWER_COLOR_SPACE_API)
+ colorSpace = GfxColorSpace::parse(&obj1, NULL, NULL);
+#elif defined(POPPLER_NEW_COLOR_SPACE_API) || defined(POPPLER_NEW_ERRORAPI)
colorSpace = GfxColorSpace::parse(&obj1, NULL);
#else
colorSpace = GfxColorSpace::parse(&obj1);
@@ -2909,7 +3004,9 @@ void PdfParser::doImage(Object * /*ref*/, Stream *str, GBool inlineImg)
obj2.free();
}
}
-#if defined(POPPLER_NEW_COLOR_SPACE_API) || defined(POPPLER_NEW_ERRORAPI)
+#if defined(POPPLER_EVEN_NEWER_COLOR_SPACE_API)
+ GfxColorSpace *maskColorSpace = GfxColorSpace::parse(&obj1, NULL, NULL);
+#elif defined(POPPLER_NEW_COLOR_SPACE_API) || defined(POPPLER_NEW_ERRORAPI)
GfxColorSpace *maskColorSpace = GfxColorSpace::parse(&obj1, NULL);
#else
GfxColorSpace *maskColorSpace = GfxColorSpace::parse(&obj1);
@@ -3099,7 +3196,9 @@ void PdfParser::doForm(Object *str) {
if (obj1.dictLookup(const_cast<char*>("S"), &obj2)->isName(const_cast<char*>("Transparency"))) {
transpGroup = gTrue;
if (!obj1.dictLookup(const_cast<char*>("CS"), &obj3)->isNull()) {
-#if defined(POPPLER_NEW_COLOR_SPACE_API) || defined(POPPLER_NEW_ERRORAPI)
+#if defined(POPPLER_EVEN_NEWER_COLOR_SPACE_API)
+ blendingColorSpace = GfxColorSpace::parse(&obj3, NULL, NULL);
+#elif defined(POPPLER_NEW_COLOR_SPACE_API) || defined(POPPLER_NEW_ERRORAPI)
blendingColorSpace = GfxColorSpace::parse(&obj3, NULL);
#else
blendingColorSpace = GfxColorSpace::parse(&obj3);
@@ -3427,9 +3526,7 @@ void PdfParser::popResources() {
}
void PdfParser::setDefaultApproximationPrecision() {
- int i;
-
- for (i = 1; i <= pdfNumShadingTypes; ++i) {
+ for (int i = 1; i <= pdfNumShadingTypes; ++i) {
setApproximationPrecision(i, defaultShadingColorDelta, defaultShadingMaxDepth);
}
}
@@ -3448,19 +3545,18 @@ void PdfParser::setApproximationPrecision(int shadingType, double colorDelta,
// ClipHistoryEntry
//------------------------------------------------------------------------
-ClipHistoryEntry::ClipHistoryEntry(GfxPath *clipPathA, GfxClipType clipTypeA) {
- if (clipPathA) {
- clipPath = clipPathA->copy();
- } else {
- clipPath = NULL;
- }
- clipType = clipTypeA;
- saved = NULL;
+ClipHistoryEntry::ClipHistoryEntry(GfxPath *clipPathA, GfxClipType clipTypeA) :
+ saved(NULL),
+ clipPath((clipPathA) ? clipPathA->copy() : NULL),
+ clipType(clipTypeA)
+{
}
-ClipHistoryEntry::~ClipHistoryEntry() {
+ClipHistoryEntry::~ClipHistoryEntry()
+{
if (clipPath) {
delete clipPath;
+ clipPath = NULL;
}
}
@@ -3474,6 +3570,7 @@ void ClipHistoryEntry::setClip(GfxPath *clipPathA, GfxClipType clipTypeA) {
clipType = clipTypeA;
} else {
clipPath = NULL;
+ clipType = clipNormal;
}
}
@@ -3490,7 +3587,7 @@ ClipHistoryEntry *ClipHistoryEntry::restore() {
if (saved) {
oldEntry = saved;
saved = NULL;
- delete this;
+ delete this; // TODO really should avoid deleting from inside.
} else {
oldEntry = this;
}
@@ -3504,6 +3601,7 @@ ClipHistoryEntry::ClipHistoryEntry(ClipHistoryEntry *other) {
this->clipType = other->clipType;
} else {
this->clipPath = NULL;
+ this->clipType = clipNormal;
}
saved = NULL;
}
diff --git a/src/extension/internal/pdfinput/pdf-parser.h b/src/extension/internal/pdfinput/pdf-parser.h
index a63d669c7..e28fecc2e 100644
--- a/src/extension/internal/pdfinput/pdf-parser.h
+++ b/src/extension/internal/pdfinput/pdf-parser.h
@@ -58,6 +58,8 @@ class AnnotBorderStyle;
class PdfParser;
+class ClipHistoryEntry;
+
//------------------------------------------------------------------------
#ifndef GFX_H
@@ -101,34 +103,6 @@ struct OpHistoryEntry {
};
//------------------------------------------------------------------------
-// ClipHistoryEntry
-//------------------------------------------------------------------------
-
-class ClipHistoryEntry {
-public:
-
- ClipHistoryEntry(GfxPath *clipPath=NULL, GfxClipType clipType=clipNormal);
- virtual ~ClipHistoryEntry();
-
- // Manipulate clip path stack
- ClipHistoryEntry *save();
- ClipHistoryEntry *restore();
- GBool hasSaves() { return saved != NULL; }
- void setClip(GfxPath *newClipPath, GfxClipType newClipType=clipNormal);
- GfxPath *getClipPath() { return clipPath; }
- GfxClipType getClipType() { return clipType; }
-
-private:
-
- ClipHistoryEntry *saved; // next clip path on stack
-
- GfxPath *clipPath; // used as the path to be filled for an 'sh' operator
- GfxClipType clipType;
-
- ClipHistoryEntry(ClipHistoryEntry *other);
-};
-
-//------------------------------------------------------------------------
// PdfParser
//------------------------------------------------------------------------
diff --git a/src/extension/internal/pdfinput/svg-builder.cpp b/src/extension/internal/pdfinput/svg-builder.cpp
index 71e6dc6ae..7a504add0 100644
--- a/src/extension/internal/pdfinput/svg-builder.cpp
+++ b/src/extension/internal/pdfinput/svg-builder.cpp
@@ -123,12 +123,11 @@ void SvgBuilder::_init() {
_height = 0;
// Fill _availableFontNames (Bug LP #179589) (code cfr. FontLister)
- FamilyToStylesMap familyStyleMap;
- font_factory::Default()->GetUIFamiliesAndStyles(&familyStyleMap);
- for (FamilyToStylesMap::iterator iter = familyStyleMap.begin();
- iter != familyStyleMap.end();
- ++iter) {
- _availableFontNames.push_back(iter->first.c_str());
+ std::vector<PangoFontFamily *> families;
+ font_factory::Default()->GetUIFamilies(families);
+ for ( std::vector<PangoFontFamily *>::iterator iter = families.begin();
+ iter != families.end(); ++iter ) {
+ _availableFontNames.push_back(pango_font_family_get_name(*iter));
}
_transp_group_stack = NULL;
diff --git a/src/extension/internal/svg.cpp b/src/extension/internal/svg.cpp
index 8b272af60..a94bc2141 100644
--- a/src/extension/internal/svg.cpp
+++ b/src/extension/internal/svg.cpp
@@ -24,6 +24,7 @@
#include "extension/output.h"
#include <vector>
#include "xml/attribute-record.h"
+#include "xml/simple-document.h"
#include "sp-root.h"
#include "document.h"
@@ -42,27 +43,37 @@ using Inkscape::Util::List;
using Inkscape::XML::AttributeRecord;
using Inkscape::XML::Node;
-
-
-static void pruneExtendedAttributes( Inkscape::XML::Node *repr )
+/*
+ * Removes all sodipodi and inkscape elements and attributes from an xml tree.
+ * used to make plain svg output.
+ */
+static void pruneExtendedNamespaces( Inkscape::XML::Node *repr )
{
if (repr) {
if ( repr->type() == Inkscape::XML::ELEMENT_NODE ) {
- std::vector<gchar const*> toBeRemoved;
+ std::vector<gchar const*> attrsRemoved;
for ( List<AttributeRecord const> it = repr->attributeList(); it; ++it ) {
const gchar* attrName = g_quark_to_string(it->key);
if ((strncmp("inkscape:", attrName, 9) == 0) || (strncmp("sodipodi:", attrName, 9) == 0)) {
- toBeRemoved.push_back(attrName);
+ attrsRemoved.push_back(attrName);
}
}
// Can't change the set we're interating over while we are iterating.
- for ( std::vector<gchar const*>::iterator it = toBeRemoved.begin(); it != toBeRemoved.end(); ++it ) {
+ for ( std::vector<gchar const*>::iterator it = attrsRemoved.begin(); it != attrsRemoved.end(); ++it ) {
repr->setAttribute(*it, 0);
}
}
+ std::vector<Inkscape::XML::Node *> nodesRemoved;
for ( Node *child = repr->firstChild(); child; child = child->next() ) {
- pruneExtendedAttributes(child);
+ if((strncmp("inkscape:", child->name(), 9) == 0) || strncmp("sodipodi:", child->name(), 9) == 0) {
+ nodesRemoved.push_back(child);
+ } else {
+ pruneExtendedNamespaces(child);
+ }
+ }
+ for ( std::vector<Inkscape::XML::Node *>::iterator it = nodesRemoved.begin(); it != nodesRemoved.end(); ++it ) {
+ repr->removeChild(*it);
}
}
}
@@ -229,24 +240,34 @@ Svg::save(Inkscape::Extension::Output *mod, SPDocument *doc, gchar const *filena
{
g_return_if_fail(doc != NULL);
g_return_if_fail(filename != NULL);
+ Inkscape::XML::Document *rdoc = doc->rdoc;
bool const exportExtensions = ( !mod->get_id()
|| !strcmp (mod->get_id(), SP_MODULE_KEY_OUTPUT_SVG_INKSCAPE)
|| !strcmp (mod->get_id(), SP_MODULE_KEY_OUTPUT_SVGZ_INKSCAPE));
- Inkscape::XML::Document *rdoc = NULL;
- Inkscape::XML::Node *repr = NULL;
- if (exportExtensions) {
- repr = doc->getReprRoot();
- } else {
- rdoc = sp_repr_document_new ("svg:svg");
- repr = rdoc->root();
- repr = doc->getRoot()->updateRepr(rdoc, repr, SP_OBJECT_WRITE_BUILD);
+ if (!exportExtensions) {
+ // We make a duplicate document so we don't prune the in-use document
+ // and loose data. Perhaps the user intends to save as inkscape-svg next.
+ Inkscape::XML::Document *new_rdoc = new Inkscape::XML::SimpleDocument();
+
+ // Comments and PI nodes are not included in this duplication
+ // TODO: Move this code into xml/document.h and duplicate rdoc instead of root.
+ new_rdoc->setAttribute("version", "1.0");
+ new_rdoc->setAttribute("standalone", "no");
+
+ // Get a new xml repr for the svg root node
+ Inkscape::XML::Node *root = rdoc->root()->duplicate(new_rdoc);
+
+ // Add the duplicated svg node as the document's rdoc
+ new_rdoc->appendChild(root);
+ Inkscape::GC::release(root);
- pruneExtendedAttributes(repr);
+ pruneExtendedNamespaces(root);
+ rdoc = new_rdoc;
}
- if (!sp_repr_save_rebased_file(repr->document(), filename, SP_SVG_NS_URI,
+ if (!sp_repr_save_rebased_file(rdoc, filename, SP_SVG_NS_URI,
doc->getBase(), filename)) {
throw Inkscape::Extension::Output::save_failed();
}
diff --git a/src/extension/internal/text_reassemble.c b/src/extension/internal/text_reassemble.c
index 810e3f8cc..4dfc49420 100644
--- a/src/extension/internal/text_reassemble.c
+++ b/src/extension/internal/text_reassemble.c
@@ -67,8 +67,8 @@ Optional compiler switches for development:
File: text_reassemble.c
-Version: 0.0.14
-Date: 25-MAR-2014
+Version: 0.0.15
+Date: 24-JUL-2014
Author: David Mathog, Biology Division, Caltech
email: mathog@caltech.edu
Copyright: 2014 David Mathog and California Institute of Technology (Caltech)
@@ -550,7 +550,7 @@ int TR_check_set_vadvance(TR_INFO *tri, int src, int lines){
See if the line to be added is compatible.
All text fields in a complex have the same advance, so just set/check the first one.
vadvance must be within 1% or do not add a new line */
- if(fabs(1.0 - (tpi->chunks[trec].vadvance/newV) > 0.01)){
+ if(fabs(1.0 - (tpi->chunks[trec].vadvance/newV)) > 0.01){
status = 1;
}
else { /* recalculate the weighted vadvance */
@@ -1820,7 +1820,9 @@ printf("Face idx:%d bbox: xMax/Min:%ld,%ld yMax/Min:%ld,%ld UpEM:%d asc/des:%d,%
fasc = ((double) (fsp->face->ascender) )/64.0;
fdsc = ((double) (fsp->face->descender))/64.0;
- if(tri->load_flags & FT_LOAD_NO_SCALE) xe *= tsp->fs/32.0;
+ /* originally the denominator was just 32.0, but it broke when units_per_EM wasn't 2048 */
+ double fixscale = tsp->fs/(((double) fsp->face->units_per_EM)/64.0);
+ if(tri->load_flags & FT_LOAD_NO_SCALE) xe *= fixscale;
/* now place the rectangle using ALN information */
if( taln & ALIHORI & ALILEFT ){
@@ -1837,11 +1839,11 @@ printf("Face idx:%d bbox: xMax/Min:%ld,%ld yMax/Min:%ld,%ld UpEM:%d asc/des:%d,%
}
tpi->chunks[current].ldir = tsp->ldir;
- if(tri->load_flags & FT_LOAD_NO_SCALE){
- asc *= tsp->fs/32.0;
- dsc *= tsp->fs/32.0;
- fasc *= tsp->fs/32.0;
- fdsc *= tsp->fs/32.0;
+ if(tri->load_flags & FT_LOAD_NO_SCALE){
+ asc *= fixscale;
+ dsc *= fixscale;
+ fasc *= fixscale;
+ fdsc *= fixscale;
}
diff --git a/src/extension/internal/vsd-input.cpp b/src/extension/internal/vsd-input.cpp
index 6fc79237b..9f9bf2651 100644
--- a/src/extension/internal/vsd-input.cpp
+++ b/src/extension/internal/vsd-input.cpp
@@ -24,7 +24,22 @@
#include <cstring>
#include <libvisio/libvisio.h>
-#include <libwpd-stream/libwpd-stream.h>
+
+// TODO: Drop this check when librevenge is widespread.
+#if WITH_LIBVISIO01
+ #include <librevenge-stream/librevenge-stream.h>
+
+ using librevenge::RVNGString;
+ using librevenge::RVNGFileStream;
+ using librevenge::RVNGStringVector;
+#else
+ #include <libwpd-stream/libwpd-stream.h>
+
+ typedef WPXString RVNGString;
+ typedef WPXFileStream RVNGFileStream;
+ typedef libvisio::VSDStringVector RVNGStringVector;
+#endif
+
#include <gtkmm/alignment.h>
#include <gtkmm/comboboxtext.h>
@@ -41,7 +56,7 @@
#include "inkscape.h"
#include "util/units.h"
-#include "dialogs/dialog-events.h"
+#include "ui/dialog-events.h"
#include <gtk/gtk.h>
#include "ui/widget/spinbutton.h"
#include "ui/widget/frame.h"
@@ -59,7 +74,7 @@ namespace Internal {
class VsdImportDialog : public Gtk::Dialog {
public:
- VsdImportDialog(const std::vector<WPXString> &vec);
+ VsdImportDialog(const std::vector<RVNGString> &vec);
virtual ~VsdImportDialog();
bool showDialog();
@@ -85,12 +100,12 @@ private:
class Gtk::VBox * vbox2;
class Gtk::Widget * _previewArea;
- const std::vector<WPXString> &_vec; // Document to be imported
+ const std::vector<RVNGString> &_vec; // Document to be imported
unsigned _current_page; // Current selected page
int _preview_width, _preview_height; // Size of the preview area
};
-VsdImportDialog::VsdImportDialog(const std::vector<WPXString> &vec)
+VsdImportDialog::VsdImportDialog(const std::vector<RVNGString> &vec)
: _vec(vec), _current_page(1)
{
int num_pages = _vec.size();
@@ -138,9 +153,15 @@ VsdImportDialog::VsdImportDialog(const std::vector<WPXString> &vec)
_labelTotalPages->set_use_markup(false);
_labelTotalPages->set_selectable(false);
vbox2->pack_start(*_previewArea, Gtk::PACK_SHRINK, 0);
+#if WITH_GTKMM_3_0
+ this->get_content_area()->set_homogeneous(false);
+ this->get_content_area()->set_spacing(0);
+ this->get_content_area()->pack_start(*vbox2);
+#else
this->get_vbox()->set_homogeneous(false);
this->get_vbox()->set_spacing(0);
this->get_vbox()->pack_start(*vbox2);
+#endif
this->set_title(_("Page Selector"));
this->set_modal(true);
sp_transientize(GTK_WIDGET(this->gobj())); //Make transient
@@ -209,14 +230,20 @@ void VsdImportDialog::_setPreviewPage(unsigned page)
SPDocument *VsdInput::open(Inkscape::Extension::Input * /*mod*/, const gchar * uri)
{
- WPXFileStream input(uri);
+ RVNGFileStream input(uri);
if (!libvisio::VisioDocument::isSupported(&input)) {
return NULL;
}
- libvisio::VSDStringVector output;
+ RVNGStringVector output;
+#if WITH_LIBVISIO01
+ librevenge::RVNGSVGDrawingGenerator generator(output, "svg");
+
+ if (!libvisio::VisioDocument::parse(&input, &generator)) {
+#else
if (!libvisio::VisioDocument::generateSVG(&input, output)) {
+#endif
return NULL;
}
@@ -224,9 +251,9 @@ SPDocument *VsdInput::open(Inkscape::Extension::Input * /*mod*/, const gchar * u
return NULL;
}
- std::vector<WPXString> tmpSVGOutput;
+ std::vector<RVNGString> tmpSVGOutput;
for (unsigned i=0; i<output.size(); ++i) {
- WPXString tmpString("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n");
+ RVNGString tmpString("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n");
tmpString.append(output[i]);
tmpSVGOutput.push_back(tmpString);
}
diff --git a/src/extension/internal/wmf-inout.cpp b/src/extension/internal/wmf-inout.cpp
index ef95dbe45..72c1c8bd3 100644
--- a/src/extension/internal/wmf-inout.cpp
+++ b/src/extension/internal/wmf-inout.cpp
@@ -33,9 +33,9 @@
#include <stdint.h>
#include <libuemf/symbol_convert.h>
-#include "sp-root.h"
+#include "document.h"
+#include "sp-root.h" // even though it is included indirectly by wmf-inout.h
#include "sp-path.h"
-#include "style.h"
#include "print.h"
#include "extension/system.h"
#include "extension/print.h"
@@ -44,13 +44,10 @@
#include "extension/output.h"
#include "display/drawing.h"
#include "display/drawing-item.h"
-#include "util/units.h"
#include "clear-n_.h"
-#include "document.h"
-#include "shape-editor.h"
-#include "sp-namedview.h"
-#include "document-undo.h"
-#include "inkscape.h"
+#include "svg/svg.h"
+#include "util/units.h" // even though it is included indirectly by wmf-inout.h
+#include "inkscape.h" // even though it is included indirectly by wmf-inout.h
#include "wmf-inout.h"
@@ -67,7 +64,6 @@ namespace Extension {
namespace Internal {
-static U_RECT16 rc_old;
static bool clipset = false;
static uint32_t BLTmode=0;
@@ -251,54 +247,54 @@ uint32_t Wmf::add_hatch(PWMF_CALLBACK_DATA d, uint32_t hatchType, U_COLORREF hat
if(d->hatches.count == d->hatches.size){ enlarge_hatches(d); }
d->hatches.strings[d->hatches.count++]=strdup(hpathname);
- *(d->defs) += "\n";
+ d->defs += "\n";
switch(hatchType){
case U_HS_HORIZONTAL:
- *(d->defs) += " <path id=\"";
- *(d->defs) += hpathname;
- *(d->defs) += "\" d=\"M 0 0 6 0\" style=\"fill:none;stroke:#";
- *(d->defs) += tmpcolor;
- *(d->defs) += "\" />\n";
+ d->defs += " <path id=\"";
+ d->defs += hpathname;
+ d->defs += "\" d=\"M 0 0 6 0\" style=\"fill:none;stroke:#";
+ d->defs += tmpcolor;
+ d->defs += "\" />\n";
break;
case U_HS_VERTICAL:
- *(d->defs) += " <path id=\"";
- *(d->defs) += hpathname;
- *(d->defs) += "\" d=\"M 0 0 0 6\" style=\"fill:none;stroke:#";
- *(d->defs) += tmpcolor;
- *(d->defs) += "\" />\n";
+ d->defs += " <path id=\"";
+ d->defs += hpathname;
+ d->defs += "\" d=\"M 0 0 0 6\" style=\"fill:none;stroke:#";
+ d->defs += tmpcolor;
+ d->defs += "\" />\n";
break;
case U_HS_FDIAGONAL:
- *(d->defs) += " <line id=\"sub";
- *(d->defs) += hpathname;
- *(d->defs) += "\" x1=\"-1\" y1=\"-1\" x2=\"7\" y2=\"7\" stroke=\"#";
- *(d->defs) += tmpcolor;
- *(d->defs) += "\"/>\n";
+ d->defs += " <line id=\"sub";
+ d->defs += hpathname;
+ d->defs += "\" x1=\"-1\" y1=\"-1\" x2=\"7\" y2=\"7\" stroke=\"#";
+ d->defs += tmpcolor;
+ d->defs += "\"/>\n";
break;
case U_HS_BDIAGONAL:
- *(d->defs) += " <line id=\"sub";
- *(d->defs) += hpathname;
- *(d->defs) += "\" x1=\"-1\" y1=\"7\" x2=\"7\" y2=\"-1\" stroke=\"#";
- *(d->defs) += tmpcolor;
- *(d->defs) += "\"/>\n";
+ d->defs += " <line id=\"sub";
+ d->defs += hpathname;
+ d->defs += "\" x1=\"-1\" y1=\"7\" x2=\"7\" y2=\"-1\" stroke=\"#";
+ d->defs += tmpcolor;
+ d->defs += "\"/>\n";
break;
case U_HS_CROSS:
- *(d->defs) += " <path id=\"";
- *(d->defs) += hpathname;
- *(d->defs) += "\" d=\"M 0 0 6 0 M 0 0 0 6\" style=\"fill:none;stroke:#";
- *(d->defs) += tmpcolor;
- *(d->defs) += "\" />\n";
+ d->defs += " <path id=\"";
+ d->defs += hpathname;
+ d->defs += "\" d=\"M 0 0 6 0 M 0 0 0 6\" style=\"fill:none;stroke:#";
+ d->defs += tmpcolor;
+ d->defs += "\" />\n";
break;
case U_HS_DIAGCROSS:
- *(d->defs) += " <line id=\"subfd";
- *(d->defs) += hpathname;
- *(d->defs) += "\" x1=\"-1\" y1=\"-1\" x2=\"7\" y2=\"7\" stroke=\"#";
- *(d->defs) += tmpcolor;
- *(d->defs) += "\"/>\n";
- *(d->defs) += " <line id=\"subbd";
- *(d->defs) += hpathname;
- *(d->defs) += "\" x1=\"-1\" y1=\"7\" x2=\"7\" y2=\"-1\" stroke=\"#";
- *(d->defs) += tmpcolor;
- *(d->defs) += "\"/>\n";
+ d->defs += " <line id=\"subfd";
+ d->defs += hpathname;
+ d->defs += "\" x1=\"-1\" y1=\"-1\" x2=\"7\" y2=\"7\" stroke=\"#";
+ d->defs += tmpcolor;
+ d->defs += "\"/>\n";
+ d->defs += " <line id=\"subbd";
+ d->defs += hpathname;
+ d->defs += "\" x1=\"-1\" y1=\"7\" x2=\"7\" y2=\"-1\" stroke=\"#";
+ d->defs += tmpcolor;
+ d->defs += "\"/>\n";
break;
case U_HS_SOLIDCLR:
case U_HS_DITHEREDCLR:
@@ -307,12 +303,12 @@ uint32_t Wmf::add_hatch(PWMF_CALLBACK_DATA d, uint32_t hatchType, U_COLORREF hat
case U_HS_SOLIDBKCLR:
case U_HS_DITHEREDBKCLR:
default:
- *(d->defs) += " <path id=\"";
- *(d->defs) += hpathname;
- *(d->defs) += "\" d=\"M 0 0 6 0 6 6 0 6 z\" style=\"fill:#";
- *(d->defs) += tmpcolor;
- *(d->defs) += ";stroke:none";
- *(d->defs) += "\" />\n";
+ d->defs += " <path id=\"";
+ d->defs += hpathname;
+ d->defs += "\" d=\"M 0 0 6 0 6 6 0 6 z\" style=\"fill:#";
+ d->defs += tmpcolor;
+ d->defs += ";stroke:none";
+ d->defs += "\" />\n";
break;
}
}
@@ -374,12 +370,12 @@ uint32_t Wmf::add_hatch(PWMF_CALLBACK_DATA d, uint32_t hatchType, U_COLORREF hat
if(!idx){ // add it if not already present
if(d->hatches.count == d->hatches.size){ enlarge_hatches(d); }
d->hatches.strings[d->hatches.count++]=strdup(hatchname);
- *(d->defs) += "\n";
- *(d->defs) += " <pattern id=\"";
- *(d->defs) += hatchname;
- *(d->defs) += "\" xlink:href=\"#WMFhbasepattern\">\n";
- *(d->defs) += refpath;
- *(d->defs) += " </pattern>\n";
+ d->defs += "\n";
+ d->defs += " <pattern id=\"";
+ d->defs += hatchname;
+ d->defs += "\" xlink:href=\"#WMFhbasepattern\">\n";
+ d->defs += refpath;
+ d->defs += " </pattern>\n";
idx = d->hatches.count;
}
}
@@ -392,12 +388,12 @@ uint32_t Wmf::add_hatch(PWMF_CALLBACK_DATA d, uint32_t hatchType, U_COLORREF hat
if(d->hatches.count == d->hatches.size){ enlarge_hatches(d); }
d->hatches.strings[d->hatches.count++]=strdup(hbkname);
- *(d->defs) += "\n";
- *(d->defs) += " <rect id=\"";
- *(d->defs) += hbkname;
- *(d->defs) += "\" x=\"0\" y=\"0\" width=\"6\" height=\"6\" fill=\"#";
- *(d->defs) += bkcolor;
- *(d->defs) += "\" />\n";
+ d->defs += "\n";
+ d->defs += " <rect id=\"";
+ d->defs += hbkname;
+ d->defs += "\" x=\"0\" y=\"0\" width=\"6\" height=\"6\" fill=\"#";
+ d->defs += bkcolor;
+ d->defs += "\" />\n";
}
// this is the pattern, its name will show up in Inkscape's pattern selector
@@ -406,15 +402,15 @@ uint32_t Wmf::add_hatch(PWMF_CALLBACK_DATA d, uint32_t hatchType, U_COLORREF hat
if(!idx){ // add it if not already present
if(d->hatches.count == d->hatches.size){ enlarge_hatches(d); }
d->hatches.strings[d->hatches.count++]=strdup(hatchname);
- *(d->defs) += "\n";
- *(d->defs) += " <pattern id=\"";
- *(d->defs) += hatchname;
- *(d->defs) += "\" xlink:href=\"#WMFhbasepattern\">\n";
- *(d->defs) += " <use xlink:href=\"#";
- *(d->defs) += hbkname;
- *(d->defs) += "\" />\n";
- *(d->defs) += refpath;
- *(d->defs) += " </pattern>\n";
+ d->defs += "\n";
+ d->defs += " <pattern id=\"";
+ d->defs += hatchname;
+ d->defs += "\" xlink:href=\"#WMFhbasepattern\">\n";
+ d->defs += " <use xlink:href=\"#";
+ d->defs += hbkname;
+ d->defs += "\" />\n";
+ d->defs += refpath;
+ d->defs += " </pattern>\n";
idx = d->hatches.count;
}
}
@@ -503,35 +499,35 @@ uint32_t Wmf::add_dib_image(PWMF_CALLBACK_DATA d, const char *dib, uint32_t iUsa
sprintf(imagename,"WMFimage%d",idx++);
sprintf(xywh," x=\"0\" y=\"0\" width=\"%d\" height=\"%d\" ",width,height); // reuse this buffer
- *(d->defs) += "\n";
- *(d->defs) += " <image id=\"";
- *(d->defs) += imagename;
- *(d->defs) += "\"\n ";
- *(d->defs) += xywh;
- *(d->defs) += "\n";
- if(dibparams == U_BI_JPEG){ *(d->defs) += " xlink:href=\"data:image/jpeg;base64,"; }
- else { *(d->defs) += " xlink:href=\"data:image/png;base64,"; }
- *(d->defs) += base64String;
- *(d->defs) += "\"\n";
- *(d->defs) += " preserveAspectRatio=\"none\"\n";
- *(d->defs) += " />\n";
-
-
- *(d->defs) += "\n";
- *(d->defs) += " <pattern id=\"";
- *(d->defs) += imagename;
- *(d->defs) += "_ref\"\n ";
- *(d->defs) += xywh;
- *(d->defs) += "\n patternUnits=\"userSpaceOnUse\"";
- *(d->defs) += " >\n";
- *(d->defs) += " <use id=\"";
- *(d->defs) += imagename;
- *(d->defs) += "_ign\" ";
- *(d->defs) += " xlink:href=\"#";
- *(d->defs) += imagename;
- *(d->defs) += "\" />\n";
- *(d->defs) += " ";
- *(d->defs) += " </pattern>\n";
+ d->defs += "\n";
+ d->defs += " <image id=\"";
+ d->defs += imagename;
+ d->defs += "\"\n ";
+ d->defs += xywh;
+ d->defs += "\n";
+ if(dibparams == U_BI_JPEG){ d->defs += " xlink:href=\"data:image/jpeg;base64,"; }
+ else { d->defs += " xlink:href=\"data:image/png;base64,"; }
+ d->defs += base64String;
+ d->defs += "\"\n";
+ d->defs += " preserveAspectRatio=\"none\"\n";
+ d->defs += " />\n";
+
+
+ d->defs += "\n";
+ d->defs += " <pattern id=\"";
+ d->defs += imagename;
+ d->defs += "_ref\"\n ";
+ d->defs += xywh;
+ d->defs += "\n patternUnits=\"userSpaceOnUse\"";
+ d->defs += " >\n";
+ d->defs += " <use id=\"";
+ d->defs += imagename;
+ d->defs += "_ign\" ";
+ d->defs += " xlink:href=\"#";
+ d->defs += imagename;
+ d->defs += "\" />\n";
+ d->defs += " ";
+ d->defs += " </pattern>\n";
}
g_free(base64String); //wait until this point to free because it might be a duplicate image
return(idx-1);
@@ -599,38 +595,99 @@ uint32_t Wmf::add_bm16_image(PWMF_CALLBACK_DATA d, U_BITMAP16 Bm16, const char *
sprintf(imagename,"WMFimage%d",idx++);
sprintf(xywh," x=\"0\" y=\"0\" width=\"%d\" height=\"%d\" ",width,height); // reuse this buffer
- *(d->defs) += "\n";
- *(d->defs) += " <image id=\"";
- *(d->defs) += imagename;
- *(d->defs) += "\"\n ";
- *(d->defs) += xywh;
- *(d->defs) += "\n";
- *(d->defs) += " xlink:href=\"data:image/png;base64,";
- *(d->defs) += base64String;
- *(d->defs) += "\"\n";
- *(d->defs) += " preserveAspectRatio=\"none\"\n";
- *(d->defs) += " />\n";
-
-
- *(d->defs) += "\n";
- *(d->defs) += " <pattern id=\"";
- *(d->defs) += imagename;
- *(d->defs) += "_ref\"\n ";
- *(d->defs) += xywh;
- *(d->defs) += "\n patternUnits=\"userSpaceOnUse\"";
- *(d->defs) += " >\n";
- *(d->defs) += " <use id=\"";
- *(d->defs) += imagename;
- *(d->defs) += "_ign\" ";
- *(d->defs) += " xlink:href=\"#";
- *(d->defs) += imagename;
- *(d->defs) += "\" />\n";
- *(d->defs) += " </pattern>\n";
+ d->defs += "\n";
+ d->defs += " <image id=\"";
+ d->defs += imagename;
+ d->defs += "\"\n ";
+ d->defs += xywh;
+ d->defs += "\n";
+ d->defs += " xlink:href=\"data:image/png;base64,";
+ d->defs += base64String;
+ d->defs += "\"\n";
+ d->defs += " preserveAspectRatio=\"none\"\n";
+ d->defs += " />\n";
+
+
+ d->defs += "\n";
+ d->defs += " <pattern id=\"";
+ d->defs += imagename;
+ d->defs += "_ref\"\n ";
+ d->defs += xywh;
+ d->defs += "\n patternUnits=\"userSpaceOnUse\"";
+ d->defs += " >\n";
+ d->defs += " <use id=\"";
+ d->defs += imagename;
+ d->defs += "_ign\" ";
+ d->defs += " xlink:href=\"#";
+ d->defs += imagename;
+ d->defs += "\" />\n";
+ d->defs += " </pattern>\n";
}
g_free(base64String); //wait until this point to free because it might be a duplicate image
return(idx-1);
}
+/* Add another 100 blank slots to the clips array.
+*/
+void Wmf::enlarge_clips(PWMF_CALLBACK_DATA d){
+ d->clips.size += 100;
+ d->clips.strings = (char **) realloc(d->clips.strings,d->clips.size * sizeof(char *));
+}
+
+/* See if the pattern name is already in the list. If it is return its position (1->n, not 1-n-1)
+*/
+int Wmf::in_clips(PWMF_CALLBACK_DATA d, const char *test){
+ int i;
+ for(i=0; i<d->clips.count; i++){
+ if(strcmp(test,d->clips.strings[i])==0)return(i+1);
+ }
+ return(0);
+}
+
+/* (Conditionally) add a clip.
+ If a matching clip already exists nothing happens
+ If one does exist it is added to the clips list, entered into <defs>.
+*/
+void Wmf::add_clips(PWMF_CALLBACK_DATA d, const char *clippath, unsigned int logic){
+ int op = combine_ops_to_livarot(logic);
+ Geom::PathVector combined_vect;
+ char *combined = NULL;
+ if (op >= 0 && d->dc[d->level].clip_id) {
+ unsigned int real_idx = d->dc[d->level].clip_id - 1;
+ Geom::PathVector old_vect = sp_svg_read_pathv(d->clips.strings[real_idx]);
+ Geom::PathVector new_vect = sp_svg_read_pathv(clippath);
+ combined_vect = sp_pathvector_boolop(new_vect, old_vect, (bool_op) op , (FillRule) fill_oddEven, (FillRule) fill_oddEven);
+ combined = sp_svg_write_path(combined_vect);
+ }
+ else {
+ combined = strdup(clippath); // COPY operation, erases everything and starts a new one
+ }
+
+ uint32_t idx = in_clips(d, combined);
+ if(!idx){ // add clip if not already present
+ if(d->clips.count == d->clips.size){ enlarge_clips(d); }
+ d->clips.strings[d->clips.count++]=strdup(combined);
+ d->dc[d->level].clip_id = d->clips.count; // one more than the slot where it is actually stored
+ SVGOStringStream tmp_clippath;
+ tmp_clippath << "\n<clipPath";
+ tmp_clippath << "\n\tclipPathUnits=\"userSpaceOnUse\" ";
+ tmp_clippath << "\n\tid=\"clipWmfPath" << d->dc[d->level].clip_id << "\"";
+ tmp_clippath << " >";
+ tmp_clippath << "\n\t<path d=\"";
+ tmp_clippath << combined;
+ tmp_clippath << "\"";
+ tmp_clippath << "\n\t/>";
+ tmp_clippath << "\n</clipPath>";
+ d->outdef += tmp_clippath.str().c_str();
+ }
+ else {
+ d->dc[d->level].clip_id = idx;
+ }
+ free(combined);
+}
+
+
+
void
Wmf::output_style(PWMF_CALLBACK_DATA d)
{
@@ -714,8 +771,8 @@ Wmf::output_style(PWMF_CALLBACK_DATA d)
// tmp_id << "\n\tid=\"" << (d->id++) << "\"";
-// *(d->outsvg) += tmp_id.str().c_str();
- *(d->outsvg) += "\n\tstyle=\"";
+// d->outsvg += tmp_id.str().c_str();
+ d->outsvg += "\n\tstyle=\"";
if (!d->dc[d->level].fill_set || ( d->mask & U_DRAW_NOFILL)) { // nofill are lines and arcs
tmp_style << "fill:none;";
} else {
@@ -838,11 +895,10 @@ Wmf::output_style(PWMF_CALLBACK_DATA d)
tmp_style << "stroke-opacity:1;";
}
tmp_style << "\" ";
- if (clipset)
- tmp_style << "\n\tclip-path=\"url(#clipWmfPath" << d->id << ")\" ";
- clipset = false;
+ if (d->dc[d->level].clip_id)
+ tmp_style << "\n\tclip-path=\"url(#clipWmfPath" << d->dc[d->level].clip_id << ")\" ";
- *(d->outsvg) += tmp_style.str().c_str();
+ d->outsvg += tmp_style.str().c_str();
}
@@ -1326,8 +1382,8 @@ void Wmf::common_dib_to_image(PWMF_CALLBACK_DATA d, const char *dib,
tmp_image << " preserveAspectRatio=\"none\"\n";
tmp_image << "/> \n";
- *(d->outsvg) += tmp_image.str().c_str();
- *(d->path) = "";
+ d->outsvg += tmp_image.str().c_str();
+ d->path = "";
}
/**
@@ -1418,8 +1474,8 @@ void Wmf::common_bm16_to_image(PWMF_CALLBACK_DATA d, U_BITMAP16 Bm16, const char
tmp_image << " preserveAspectRatio=\"none\"\n";
tmp_image << "/> \n";
- *(d->outsvg) += tmp_image.str().c_str();
- *(d->path) = "";
+ d->outsvg += tmp_image.str().c_str();
+ d->path = "";
}
/**
@@ -1579,7 +1635,7 @@ int Wmf::myMetaFileProc(const char *contents, unsigned int length, PWMF_CALLBACK
d->dc[0].style.stroke_width.value = pix_to_abs_size( d, 1 ); // This could not be set until the size of the WMF was known
dbg_str << "<!-- U_WMR_HEADER -->\n";
- *(d->outdef) += "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n";
+ d->outdef += "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n";
SVGOStringStream tmp_outdef;
tmp_outdef << "<svg\n";
@@ -1592,8 +1648,8 @@ int Wmf::myMetaFileProc(const char *contents, unsigned int length, PWMF_CALLBACK
tmp_outdef <<
" width=\"" << Inkscape::Util::Quantity::convert(d->PixelsOutX, "px", "mm") << "mm\"\n" <<
" height=\"" << Inkscape::Util::Quantity::convert(d->PixelsOutY, "px", "mm") << "mm\">\n";
- *(d->outdef) += tmp_outdef.str().c_str();
- *(d->outdef) += "<defs>"; // temporary end of header
+ d->outdef += tmp_outdef.str().c_str();
+ d->outdef += "<defs>"; // temporary end of header
// d->defs holds any defines which are read in.
@@ -1633,11 +1689,19 @@ int Wmf::myMetaFileProc(const char *contents, unsigned int length, PWMF_CALLBACK
// next record is valid type and forces pending text to be drawn immediately
if ((d->dc[d->level].dirty & DIRTY_TEXT) || ((wmr_mask != U_WMR_INVALID) && (wmr_mask & U_DRAW_TEXT) && d->tri->dirty)){
TR_layout_analyze(d->tri);
+ if (d->dc[d->level].clip_id){
+ SVGOStringStream tmp_clip;
+ tmp_clip << "\n<g\n\tclip-path=\"url(#clipWmfPath" << d->dc[d->level].clip_id << ")\"\n>";
+ d->outsvg += tmp_clip.str().c_str();
+ }
TR_layout_2_svg(d->tri);
SVGOStringStream ts;
ts << d->tri->out;
- *(d->outsvg) += ts.str().c_str();
+ d->outsvg += ts.str().c_str();
d->tri = trinfo_clear(d->tri);
+ if (d->dc[d->level].clip_id){
+ d->outsvg += "\n</g>\n";
+ }
}
if(d->dc[d->level].dirty){ //Apply the delayed background changes, clear the flag
d->dc[d->level].bkMode = tbkMode;
@@ -1688,13 +1752,13 @@ std::cout << "BEFORE DRAW"
)
){
// std::cout << "PATH DRAW at TOP <<+++++++++++++++++++++++++++++++++++++" << std::endl;
- *(d->outsvg) += " <path "; // this is the ONLY place <path should be used!!!!
+ d->outsvg += " <path "; // this is the ONLY place <path should be used!!!!
output_style(d);
- *(d->outsvg) += "\n\t";
- *(d->outsvg) += "\n\td=\""; // this is the ONLY place d=" should be used!!!!
- *(d->outsvg) += *(d->path);
- *(d->outsvg) += " \" /> \n";
- *(d->path) = ""; //reset the path
+ d->outsvg += "\n\t";
+ d->outsvg += "\n\td=\""; // this is the ONLY place d=" should be used!!!!
+ d->outsvg += d->path;
+ d->outsvg += " \" /> \n";
+ d->path = ""; //reset the path
// reset the flags
d->mask = 0;
d->drawtype = 0;
@@ -1706,7 +1770,7 @@ std::cout << "BEFORE DRAW"
{
dbg_str << "<!-- U_WMR_EOF -->\n";
- *(d->outsvg) = *(d->outdef) + *(d->defs) + "\n</defs>\n\n" + *(d->outsvg) + "</svg>\n";
+ d->outsvg = d->outdef + d->defs + "\n</defs>\n\n" + d->outsvg + "</svg>\n";
OK=0;
break;
}
@@ -1918,34 +1982,51 @@ std::cout << "BEFORE DRAW"
"\n\tM " << pix_to_xy( d, pt16.x, pt16.y ) << " ";
break;
}
- case U_WMR_EXCLUDECLIPRECT: dbg_str << "<!-- U_WMR_EXCLUDECLIPRECT -->\n"; break;
+ case U_WMR_EXCLUDECLIPRECT:
+ {
+ dbg_str << "<!-- U_WMR_EXCLUDECLIPRECT -->\n";
+
+ U_RECT16 rc;
+ nSize = U_WMREXCLUDECLIPRECT_get(contents, &rc);
+
+ SVGOStringStream tmp_path;
+ float faraway = 10000000; // hopefully well outside any real drawing!
+ //outer rect, clockwise
+ tmp_path << "M " << faraway << "," << faraway << " ";
+ tmp_path << "L " << faraway << "," << -faraway << " ";
+ tmp_path << "L " << -faraway << "," << -faraway << " ";
+ tmp_path << "L " << -faraway << "," << faraway << " ";
+ tmp_path << "z ";
+ //inner rect, counterclockwise (sign of Y is reversed)
+ tmp_path << "M " << pix_to_xy( d, rc.left , rc.top ) << " ";
+ tmp_path << "L " << pix_to_xy( d, rc.right, rc.top ) << " ";
+ tmp_path << "L " << pix_to_xy( d, rc.right, rc.bottom ) << " ";
+ tmp_path << "L " << pix_to_xy( d, rc.left, rc.bottom ) << " ";
+ tmp_path << "z";
+
+ add_clips(d, tmp_path.str().c_str(), U_RGN_AND);
+
+ d->path = "";
+ d->drawtype = 0;
+ break;
+ }
case U_WMR_INTERSECTCLIPRECT:
{
dbg_str << "<!-- U_WMR_INTERSECTCLIPRECT -->\n";
nSize = U_WMRINTERSECTCLIPRECT_get(contents, &rc);
- clipset = true;
- if ((rc.left == rc_old.left) && (rc.top == rc_old.top) && (rc.right == rc_old.right) && (rc.bottom == rc_old.bottom))
- break;
- rc_old = rc;
-
- double dx = pix_to_x_point( d, rc.left, rc.top );
- double dy = pix_to_y_point( d, rc.left, rc.top );
- double dw = pix_to_abs_size( d, rc.right - rc.left + 1);
- double dh = pix_to_abs_size( d, rc.bottom - rc.top + 1);
- SVGOStringStream tmp_rectangle;
- tmp_rectangle << "\n<clipPath\n\tclipPathUnits=\"userSpaceOnUse\" ";
- tmp_rectangle << "\nid=\"clipWmfPath" << ++(d->id) << "\" >";
- tmp_rectangle << "\n<rect ";
- tmp_rectangle << "\n x=\"" << dx << "\" ";
- tmp_rectangle << "\n y=\"" << dy << "\" ";
- tmp_rectangle << "\n width=\"" << dw << "\" ";
- tmp_rectangle << "\n height=\"" << dh << "\" />";
- tmp_rectangle << "\n</clipPath>";
+ SVGOStringStream tmp_path;
+ tmp_path << "M " << pix_to_xy( d, rc.left , rc.top ) << " ";
+ tmp_path << "L " << pix_to_xy( d, rc.right, rc.top ) << " ";
+ tmp_path << "L " << pix_to_xy( d, rc.right, rc.bottom ) << " ";
+ tmp_path << "L " << pix_to_xy( d, rc.left, rc.bottom ) << " ";
+ tmp_path << "z";
+
+ add_clips(d, tmp_path.str().c_str(), U_RGN_AND);
- *(d->outdef) += tmp_rectangle.str().c_str();
- *(d->path) = "";
+ d->path = "";
+ d->drawtype = 0;
break;
}
case U_WMR_ARC:
@@ -1981,8 +2062,8 @@ std::cout << "BEFORE DRAW"
double cx = pix_to_x_point( d, (rc.left + rc.right)/2.0, (rc.bottom + rc.top)/2.0 );
double cy = pix_to_y_point( d, (rc.left + rc.right)/2.0, (rc.bottom + rc.top)/2.0 );
- double rx = pix_to_abs_size( d, fabs(rc.right - rc.left )/2.0 );
- double ry = pix_to_abs_size( d, fabs(rc.top - rc.bottom)/2.0 );
+ double rx = pix_to_abs_size( d, std::abs(rc.right - rc.left )/2.0 );
+ double ry = pix_to_abs_size( d, std::abs(rc.top - rc.bottom)/2.0 );
SVGOStringStream tmp_ellipse;
tmp_ellipse << "cx=\"" << cx << "\" ";
@@ -1992,12 +2073,12 @@ std::cout << "BEFORE DRAW"
d->mask |= wmr_mask;
- *(d->outsvg) += " <ellipse ";
+ d->outsvg += " <ellipse ";
output_style(d);
- *(d->outsvg) += "\n\t";
- *(d->outsvg) += tmp_ellipse.str().c_str();
- *(d->outsvg) += "/> \n";
- *(d->path) = "";
+ d->outsvg += "\n\t";
+ d->outsvg += tmp_ellipse.str().c_str();
+ d->outsvg += "/> \n";
+ d->path = "";
break;
}
case U_WMR_FLOODFILL: dbg_str << "<!-- U_WMR_EXTFLOODFILL -->\n"; break;
@@ -2139,7 +2220,24 @@ std::cout << "BEFORE DRAW"
break;
}
case U_WMR_SETPIXEL: dbg_str << "<!-- U_WMR_SETPIXEL -->\n"; break;
- case U_WMR_OFFSETCLIPRGN: dbg_str << "<!-- U_WMR_OFFSETCLIPRGN/POLYLINE -->\n"; break;
+ case U_WMR_OFFSETCLIPRGN:
+ {
+ dbg_str << "<!-- U_EMR_OFFSETCLIPRGN -->\n";
+ U_POINT16 off;
+ nSize = U_WMROFFSETCLIPRGN_get(contents,&off);
+ if (d->dc[d->level].clip_id) { // can only offset an existing clipping path
+ unsigned int real_idx = d->dc[d->level].clip_id - 1;
+ Geom::PathVector tmp_vect = sp_svg_read_pathv(d->clips.strings[real_idx]);
+ double ox = pix_to_x_point(d, off.x, off.y) - pix_to_x_point(d, 0, 0); // take into account all active transforms
+ double oy = pix_to_y_point(d, off.x, off.y) - pix_to_y_point(d, 0, 0);
+ Geom::Affine tf = Geom::Translate(ox,oy);
+ tmp_vect *= tf;
+ char *tmp_path = sp_svg_write_path(tmp_vect);
+ add_clips(d, tmp_path, U_RGN_COPY);
+ free(tmp_path);
+ }
+ break;
+ }
// U_WMR_TEXTOUT should be here, but has been moved down to merge with U_WMR_EXTTEXTOUT
case U_WMR_BITBLT:
{
@@ -2501,11 +2599,19 @@ std::cout << "BEFORE DRAW"
status = trinfo_load_textrec(d->tri, &tsp, tsp.ori,TR_EMFBOT); // ori is actually escapement
if(status==-1){ // change of escapement, emit what we have and reset
TR_layout_analyze(d->tri);
+ if (d->dc[d->level].clip_id){
+ SVGOStringStream tmp_clip;
+ tmp_clip << "\n<g\n\tclip-path=\"url(#clipWmfPath" << d->dc[d->level].clip_id << ")\"\n>";
+ d->outsvg += tmp_clip.str().c_str();
+ }
TR_layout_2_svg(d->tri);
ts << d->tri->out;
- *(d->outsvg) += ts.str().c_str();
+ d->outsvg += ts.str().c_str();
d->tri = trinfo_clear(d->tri);
(void) trinfo_load_textrec(d->tri, &tsp, tsp.ori,TR_EMFBOT); // ignore return status, it must work
+ if (d->dc[d->level].clip_id){
+ d->outsvg += "\n</g>\n";
+ }
}
g_free(escaped_text);
@@ -2910,13 +3016,13 @@ std::cout << "BEFORE DRAW"
break;
} //end of switch
// When testing, uncomment the following to place a comment for each processed WMR record in the SVG
-// *(d->outsvg) += dbg_str.str().c_str();
- *(d->path) += tmp_path.str().c_str();
+// d->outsvg += dbg_str.str().c_str();
+ d->path += tmp_path.str().c_str();
if(!nSize){ OK=0; std::cout << "nSize == 0, oops!!!" << std::endl; } // There was some problem with this record, it is not safe to continue
} //end of while
// When testing, uncomment the following to show the final SVG derived from the WMF
-// std::cout << *(d->outsvg) << std::endl;
+// std::cout << d->outsvg << std::endl;
(void) U_wmr_properties(U_WMR_INVALID); // force the release of the lookup table memory, returned value is irrelevant
return 1;
@@ -2927,6 +3033,8 @@ void Wmf::free_wmf_strings(WMF_STRINGS name){
for(int i=0; i< name.count; i++){ free(name.strings[i]); }
free(name.strings);
}
+ name.count = 0;
+ name.size = 0;
}
SPDocument *
@@ -2935,70 +3043,38 @@ Wmf::open( Inkscape::Extension::Input * /*mod*/, const gchar *uri )
WMF_CALLBACK_DATA d;
- memset(&d, 0, sizeof(WMF_CALLBACK_DATA));
-
- for(int i = 0; i < WMF_MAX_DC+1; i++){ // be sure all values and pointers are empty to start with
- memset(&(d.dc[i]),0,sizeof(WMF_DEVICE_CONTEXT));
- }
- // set default drawing objects, these are active if no object has been selected
- d.dc[0].active_pen = -1; // -1 when the default is used instead of a selected object
- d.dc[0].active_brush = -1;
- d.dc[0].active_font = -1;
- // Default font, WMF spec says device can pick whatever it wants. WMF files that do not specify a font are unlikely to look very good!
- d.dc[0].font_name = strdup("Arial");
+ // Default font, WMF spec says device can pick whatever it wants.
+ // WMF files that do not specify a font are unlikely to look very good!
d.dc[0].style.font_size.computed = 16.0;
d.dc[0].style.font_weight.value = SP_CSS_FONT_WEIGHT_400;
d.dc[0].style.font_style.value = SP_CSS_FONT_STYLE_NORMAL;
d.dc[0].style.text_decoration_line.underline = 0;
d.dc[0].style.text_decoration_line.line_through = 0;
d.dc[0].style.baseline_shift.value = 0;
- d.dc[0].textColor = U_RGB(0, 0, 0); // default foreground color (black)
- d.dc[0].bkColor = U_RGB(255, 255, 255); // default background color (white)
- d.dc[0].bkMode = U_TRANSPARENT;
- d.dc[0].dirty = 0;
+
// Default pen, WMF files that do not specify a pen are unlikely to look very good!
d.dc[0].style.stroke_dasharray.set = 0;
d.dc[0].style.stroke_linecap.computed = 2; // U_PS_ENDCAP_SQUARE;
d.dc[0].style.stroke_linejoin.computed = 0; // U_PS_JOIN_MITER;
- d.dc[0].stroke_set = true;
d.dc[0].style.stroke_width.value = 1.0; // will be reset to something reasonable once WMF draying size is known
d.dc[0].style.stroke.value.color.set( 0, 0, 0 );
- // Default brush = none, WMF files that do not specify a brush are unlikely to look very good!
- d.dc[0].fill_set = false;
if (uri == NULL) {
return NULL;
}
- d.outsvg = new Glib::ustring("");
- d.path = new Glib::ustring("");
- d.outdef = new Glib::ustring("");
- d.defs = new Glib::ustring("");
- d.mask = 0;
- d.drawtype = 0;
- d.arcdir = U_AD_COUNTERCLOCKWISE;
- d.dwRop2 = U_R2_COPYPEN;
- d.dwRop3 = 0;
- d.E2IdirY = 1.0;
- d.D2PscaleX = 1.0;
- d.D2PscaleY = 1.0;
- d.hatches.size = 0;
- d.hatches.count = 0;
- d.hatches.strings = NULL;
- d.images.size = 0;
- d.images.count = 0;
- d.images.strings = NULL;
+ d.dc[0].font_name = strdup("Arial"); // Default font, set only on lowest level, it copies up from there WMF spec says device can pick whatever it wants
// set up the size default for patterns in defs. This might not be referenced if there are no patterns defined in the drawing.
- *(d.defs) += "\n";
- *(d.defs) += " <pattern id=\"WMFhbasepattern\" \n";
- *(d.defs) += " patternUnits=\"userSpaceOnUse\"\n";
- *(d.defs) += " width=\"6\" \n";
- *(d.defs) += " height=\"6\" \n";
- *(d.defs) += " x=\"0\" \n";
- *(d.defs) += " y=\"0\"> \n";
- *(d.defs) += " </pattern> \n";
+ d.defs += "\n";
+ d.defs += " <pattern id=\"WMFhbasepattern\" \n";
+ d.defs += " patternUnits=\"userSpaceOnUse\"\n";
+ d.defs += " width=\"6\" \n";
+ d.defs += " height=\"6\" \n";
+ d.defs += " x=\"0\" \n";
+ d.defs += " y=\"0\"> \n";
+ d.defs += " </pattern> \n";
size_t length;
@@ -3014,16 +3090,13 @@ Wmf::open( Inkscape::Extension::Input * /*mod*/, const gchar *uri )
(void) myMetaFileProc(contents,length, &d);
free(contents);
-// std::cout << "SVG Output: " << std::endl << *(d.outsvg) << std::endl;
+// std::cout << "SVG Output: " << std::endl << d.outsvg << std::endl;
- SPDocument *doc = SPDocument::createNewDocFromMem(d.outsvg->c_str(), strlen(d.outsvg->c_str()), TRUE);
+ SPDocument *doc = SPDocument::createNewDocFromMem(d.outsvg.c_str(), strlen(d.outsvg.c_str()), TRUE);
- delete d.outsvg;
- delete d.path;
- delete d.outdef;
- delete d.defs;
free_wmf_strings(d.hatches);
free_wmf_strings(d.images);
+ free_wmf_strings(d.clips);
if (d.wmf_obj) {
int i;
@@ -3034,45 +3107,13 @@ Wmf::open( Inkscape::Extension::Input * /*mod*/, const gchar *uri )
d.dc[0].style.stroke_dasharray.values.clear();
- for(int i=0; i<=d.level;i++){
+ for(int i=0; i<=WMF_MAX_DC; i++){
if(d.dc[i].font_name)free(d.dc[i].font_name);
}
d.tri = trinfo_release_except_FC(d.tri);
- // Set viewBox if it doesn't exist
- if (doc && !doc->getRoot()->viewBox_set) {
- bool saved = Inkscape::DocumentUndo::getUndoSensitive(doc);
- Inkscape::DocumentUndo::setUndoSensitive(doc, false);
-
- doc->ensureUpToDate();
-
- // Set document unit
- Inkscape::XML::Node *repr = sp_document_namedview(doc, 0)->getRepr();
- Inkscape::SVGOStringStream os;
- Inkscape::Util::Unit const* doc_unit = doc->getWidth().unit;
- os << doc_unit->abbr;
- repr->setAttribute("inkscape:document-units", os.str().c_str());
-
- // Set viewBox
- doc->setViewBox(Geom::Rect::from_xywh(0, 0, doc->getWidth().value(doc_unit), doc->getHeight().value(doc_unit)));
- doc->ensureUpToDate();
-
- // Scale and translate objects
- double scale = Inkscape::Util::Quantity::convert(1, "px", doc_unit);
- ShapeEditor::blockSetItem(true);
- double dh;
- if(SP_ACTIVE_DOCUMENT){ // for file menu open or import, or paste from clipboard
- dh = SP_ACTIVE_DOCUMENT->getHeight().value("px");
- }
- else { // for open via --file on command line
- dh = doc->getHeight().value("px");
- }
- doc->getRoot()->scaleChildItemsRec(Geom::Scale(scale), Geom::Point(0, dh));
- ShapeEditor::blockSetItem(false);
-
- Inkscape::DocumentUndo::setUndoSensitive(doc, saved);
- }
+ setViewBoxIfMissing(doc);
return doc;
}
diff --git a/src/extension/internal/wmf-inout.h b/src/extension/internal/wmf-inout.h
index 3d23ca749..5a0a760dd 100644
--- a/src/extension/internal/wmf-inout.h
+++ b/src/extension/internal/wmf-inout.h
@@ -26,21 +26,57 @@ namespace Internal {
#define DIRTY_FILL 0x02
#define DIRTY_STROKE 0x04 // not used currently
-typedef struct {
+typedef struct wmf_object {
+ wmf_object() :
+ type(0),
+ level(0),
+ record(NULL)
+ {};
int type;
int level;
char *record;
} WMF_OBJECT, *PWMF_OBJECT;
-typedef struct {
+typedef struct wmf_strings {
+ wmf_strings() :
+ size(0),
+ count(0),
+ strings(NULL)
+ {};
int size; // number of slots allocated in strings
int count; // number of slots used in strings
char **strings; // place to store strings
} WMF_STRINGS, *PWMF_STRINGS;
typedef struct wmf_device_context {
- struct SPStyle style;
+ wmf_device_context() :
+ // SPStyle: class with constructor
+ font_name(NULL),
+ clip_id(0),
+ stroke_set(false), stroke_mode(0), stroke_idx(0), stroke_recidx(0),
+ fill_set(false), fill_mode(0), fill_idx(0), fill_recidx(0),
+ dirty(0),
+ active_pen(-1), active_brush(-1), active_font(-1), // -1 when the default is used
+ // sizeWnd, sizeView, winorg, vieworg,
+ ScaleInX(0), ScaleInY(0),
+ ScaleOutX(0), ScaleOutY(0),
+ bkMode(U_TRANSPARENT),
+ // bkColor, textColor
+ textAlign(0)
+ // worldTransform, cur
+ {
+ font_name = NULL;
+ sizeWnd = point16_set( 0.0, 0.0 );
+ sizeView = point16_set( 0.0, 0.0 );
+ winorg = point16_set( 0.0, 0.0 );
+ vieworg = point16_set( 0.0, 0.0 );
+ bkColor = U_RGB(255, 255, 255); // default foreground color (white)
+ textColor = U_RGB(0, 0, 0); // default foreground color (black)
+ cur = point16_set( 0.0, 0.0 );
+ };
+ SPStyle style;
char *font_name;
+ int clip_id; // 0 if none, else 1 + index into clips
bool stroke_set;
int stroke_mode; // enumeration from drawmode, not used if fill_set is not True
int stroke_idx; // used with DRAW_PATTERN and DRAW_IMAGE to return the appropriate fill
@@ -74,11 +110,32 @@ typedef struct wmf_device_context {
// this fixes it, so some confusion between this struct and the one in emf-inout???
//typedef struct wmf_callback_data {
// as does this
-typedef struct {
- Glib::ustring *outsvg;
- Glib::ustring *path;
- Glib::ustring *outdef;
- Glib::ustring *defs;
+typedef struct wmf_callback_data {
+
+ wmf_callback_data() :
+ // dc: array, structure w/ constructor
+ level(0),
+ E2IdirY(1.0),
+ D2PscaleX(1.0), D2PscaleY(1.0),
+ PixelsInX(0), PixelsInY(0),
+ PixelsOutX(0), PixelsOutY(0),
+ ulCornerInX(0), ulCornerInY(0),
+ ulCornerOutX(0), ulCornerOutY(0),
+ mask(0),
+ arcdir(U_AD_COUNTERCLOCKWISE),
+ dwRop2(U_R2_COPYPEN), dwRop3(0),
+ id(0), drawtype(0),
+ // hatches, images, gradients, struct w/ constructor
+ tri(NULL),
+ n_obj(0),
+ low_water(0)
+ //wmf_obj
+ {};
+
+ Glib::ustring outsvg;
+ Glib::ustring path;
+ Glib::ustring outdef;
+ Glib::ustring defs;
WMF_DEVICE_CONTEXT dc[WMF_MAX_DC+1]; // FIXME: This should be dynamic..
int level;
@@ -100,6 +157,7 @@ typedef struct {
// both of these end up in <defs> under the names shown here. These structures allow duplicates to be avoided.
WMF_STRINGS hatches; // hold pattern names, all like WMFhatch#_$$$$$$ where # is the WMF hatch code and $$$$$$ is the color
WMF_STRINGS images; // hold images, all like Image#, where # is the slot the image lives.
+ WMF_STRINGS clips; // hold clipping paths, referred to be the slot where the clipping path lives
TR_INFO *tri; // Text Reassembly data structure
@@ -140,6 +198,11 @@ protected:
static int in_images(PWMF_CALLBACK_DATA d, char *test);
static uint32_t add_dib_image(PWMF_CALLBACK_DATA d, const char *dib, uint32_t iUsage);
static uint32_t add_bm16_image(PWMF_CALLBACK_DATA d, U_BITMAP16 Bm16, const char *px);
+
+ static void enlarge_clips(PWMF_CALLBACK_DATA d);
+ static int in_clips(PWMF_CALLBACK_DATA d, const char *test);
+ static void add_clips(PWMF_CALLBACK_DATA d, const char *clippath, unsigned int logic);
+
static void output_style(PWMF_CALLBACK_DATA d);
static double _pix_x_to_point(PWMF_CALLBACK_DATA d, double px);
static double _pix_y_to_point(PWMF_CALLBACK_DATA d, double py);
diff --git a/src/extension/internal/wmf-print.cpp b/src/extension/internal/wmf-print.cpp
index 5a552ad83..e5ff34009 100644
--- a/src/extension/internal/wmf-print.cpp
+++ b/src/extension/internal/wmf-print.cpp
@@ -1387,7 +1387,7 @@ unsigned int PrintWmf::text(Inkscape::Extension::Print * /*mod*/, char const *te
_lookup_ppt_fontfix("Convert To Wingdings", params);
break;
default: //also CVTNON
- _lookup_ppt_fontfix(style->text->font_family.value, params);
+ _lookup_ppt_fontfix(style->font_family.value, params);
break;
}
if (params.f2 != 0 || params.f3 != 0) {
@@ -1396,7 +1396,7 @@ unsigned int PrintWmf::text(Inkscape::Extension::Print * /*mod*/, char const *te
fix90n = 1; //assume vertical
rot = (double)(((int) round(rot)) - irem);
rotb = rot * M_PI / 1800.0;
- if (abs(rot) == 900.0) {
+ if (std::abs(rot) == 900.0) {
fix90n = 2;
}
}
@@ -1416,7 +1416,7 @@ unsigned int PrintWmf::text(Inkscape::Extension::Print * /*mod*/, char const *te
// of the special fonts.
char *facename;
if (!newfont) {
- facename = U_Utf8ToLatin1(style->text->font_family.value, 0, NULL);
+ facename = U_Utf8ToLatin1(style->font_family.value, 0, NULL);
} else {
facename = U_Utf8ToLatin1(FontName(newfont), 0, NULL);
}
diff --git a/src/extension/internal/wmf-print.h b/src/extension/internal/wmf-print.h
index 1e5d4c323..e4cf19184 100644
--- a/src/extension/internal/wmf-print.h
+++ b/src/extension/internal/wmf-print.h
@@ -28,7 +28,7 @@ namespace Internal {
class PrintWmf : public PrintMetafile
{
- uint32_t hbrush, hpen, hpenOld, hbrush_null, hpen_null;
+ uint32_t hbrush, hpen, hbrush_null, hpen_null;
uint32_t hmiterlimit; // used to minimize redundant records that set this
unsigned int print_pathv (Geom::PathVector const &pathv, const Geom::Affine &transform);
diff --git a/src/extension/internal/wpg-input.cpp b/src/extension/internal/wpg-input.cpp
index 14ff3ec77..12d86a99a 100644
--- a/src/extension/internal/wpg-input.cpp
+++ b/src/extension/internal/wpg-input.cpp
@@ -52,16 +52,24 @@
#include "util/units.h"
#include <cstring>
-// Take a guess and fallback to 0.1.x if no configure has run
-#if !defined(WITH_LIBWPG01) && !defined(WITH_LIBWPG02)
-#define WITH_LIBWPG01 1
+// Take a guess and fallback to 0.2.x if no configure has run
+#if !defined(WITH_LIBWPG03) && !defined(WITH_LIBWPG02)
+#define WITH_LIBWPG02 1
#endif
#include "libwpg/libwpg.h"
-#if WITH_LIBWPG01
-#include "libwpg/WPGStreamImplementation.h"
-#elif WITH_LIBWPG02
-#include "libwpd-stream/libwpd-stream.h"
+#if WITH_LIBWPG03
+ #include <librevenge-stream/librevenge-stream.h>
+
+ using librevenge::RVNGString;
+ using librevenge::RVNGFileStream;
+ using librevenge::RVNGInputStream;
+#else
+ #include "libwpd-stream/libwpd-stream.h"
+
+ typedef WPXString RVNGString;
+ typedef WPXFileStream RVNGFileStream;
+ typedef WPXInputStream RVNGInputStream;
#endif
using namespace libwpg;
@@ -73,17 +81,15 @@ namespace Internal {
SPDocument *WpgInput::open(Inkscape::Extension::Input * /*mod*/, const gchar * uri)
{
-#if WITH_LIBWPG01
- WPXInputStream* input = new libwpg::WPGFileStream(uri);
-#elif WITH_LIBWPG02
- WPXInputStream* input = new WPXFileStream(uri);
-#endif
+ RVNGInputStream* input = new RVNGFileStream(uri);
+#if WITH_LIBWPG03
+ if (input->isStructured()) {
+ RVNGInputStream* olestream = input->getSubStreamByName("PerfectOffice_MAIN");
+#else
if (input->isOLEStream()) {
-#if WITH_LIBWPG01
- WPXInputStream* olestream = input->getDocumentOLEStream();
-#elif WITH_LIBWPG02
- WPXInputStream* olestream = input->getDocumentOLEStream("PerfectOffice_MAIN");
+ RVNGInputStream* olestream = input->getDocumentOLEStream("PerfectOffice_MAIN");
#endif
+
if (olestream) {
delete input;
input = olestream;
@@ -98,15 +104,24 @@ SPDocument *WpgInput::open(Inkscape::Extension::Input * /*mod*/, const gchar * u
return NULL;
}
-#if WITH_LIBWPG01
- libwpg::WPGString output;
-#elif WITH_LIBWPG02
- WPXString output;
-#endif
+#if WITH_LIBWPG03
+ librevenge::RVNGStringVector vec;
+ librevenge::RVNGSVGDrawingGenerator generator(vec, "");
+
+ if (!libwpg::WPGraphics::parse(input, &generator) || vec.empty() || vec[0].empty()) {
+ delete input;
+ return NULL;
+ }
+
+ RVNGString output("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n");
+ output.append(vec[0]);
+#else
+ RVNGString output;
if (!libwpg::WPGraphics::generateSVG(input, output)) {
delete input;
return NULL;
}
+#endif
//printf("I've got a doc: \n%s", painter.document.c_str());
diff --git a/src/extension/output.h b/src/extension/output.h
index c5b1beb45..44a731ca0 100644
--- a/src/extension/output.h
+++ b/src/extension/output.h
@@ -13,7 +13,6 @@
#ifndef INKSCAPE_EXTENSION_OUTPUT_H__
#define INKSCAPE_EXTENSION_OUTPUT_H__
-#include <gtk/gtk.h>
#include "extension.h"
class SPDocument;
diff --git a/src/extension/param/color.cpp b/src/extension/param/color.cpp
index 0a2598c56..5bd70359f 100644
--- a/src/extension/param/color.cpp
+++ b/src/extension/param/color.cpp
@@ -59,9 +59,10 @@ guint32 ParamColor::set( guint32 in, SPDocument * /*doc*/, Inkscape::XML::Node *
return _value;
}
-ParamColor::ParamColor (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, bool gui_hidden, const gchar * gui_tip, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
- Parameter(name, guitext, desc, scope, gui_hidden, gui_tip, ext),
- _changeSignal(0)
+ParamColor::ParamColor(const gchar *name, const gchar *guitext, const gchar *desc, const Parameter::_scope_t scope,
+ bool gui_hidden, const gchar *gui_tip, Inkscape::Extension::Extension *ext,
+ Inkscape::XML::Node *xml)
+ : Parameter(name, guitext, desc, scope, gui_hidden, gui_tip, ext), _value(0), _changeSignal(0)
{
const char * defaulthex = NULL;
if (xml->firstChild() != NULL)
@@ -75,7 +76,8 @@ ParamColor::ParamColor (const gchar * name, const gchar * guitext, const gchar *
if (!paramval.empty())
defaulthex = paramval.data();
- _value = atoi(defaulthex);
+ if (defaulthex)
+ _value = atoi(defaulthex);
}
void ParamColor::string(std::string &string) const
@@ -87,7 +89,7 @@ void ParamColor::string(std::string &string) const
Gtk::Widget *ParamColor::get_widget( SPDocument * /*doc*/, Inkscape::XML::Node * /*node*/, sigc::signal<void> * changeSignal )
{
- if (_gui_hidden) return NULL;
+ if (_gui_hidden) return NULL;
_changeSignal = new sigc::signal<void>(*changeSignal);
Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox(false, 4));
diff --git a/src/extension/param/enum.cpp b/src/extension/param/enum.cpp
index bb50c06e1..74b2a75ad 100644
--- a/src/extension/param/enum.cpp
+++ b/src/extension/param/enum.cpp
@@ -41,8 +41,8 @@ namespace Extension {
class enumentry {
public:
enumentry (Glib::ustring &val, Glib::ustring &text) :
- value(val),
- guitext(text)
+ value(val),
+ guitext(text)
{}
Glib::ustring value;
@@ -50,16 +50,19 @@ public:
};
-ParamComboBox::ParamComboBox (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, bool gui_hidden, const gchar * gui_tip, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
- Parameter(name, guitext, desc, scope, gui_hidden, gui_tip, ext), _indent(0)
+ParamComboBox::ParamComboBox(const gchar *name, const gchar *guitext, const gchar *desc,
+ const Parameter::_scope_t scope, bool gui_hidden, const gchar *gui_tip,
+ Inkscape::Extension::Extension *ext, Inkscape::XML::Node *xml)
+ : Parameter(name, guitext, desc, scope, gui_hidden, gui_tip, ext)
+ , _value(NULL)
+ , _indent(0)
+ , choices(NULL)
{
- choices = NULL;
- _value = NULL;
+ const char *xmlval = NULL; // the value stored in XML
- // Read XML tree to add enumeration items:
- // printf("Extension Constructor: ");
if (xml != NULL) {
- for (Inkscape::XML::Node *node = xml->firstChild(); node; node = node->next()) {
+ // Read XML tree to add enumeration items:
+ for (Inkscape::XML::Node *node = xml->firstChild(); node; node = node->next()) {
char const * chname = node->name();
if (!strcmp(chname, INKSCAPE_EXTENSION_NS "item") || !strcmp(chname, INKSCAPE_EXTENSION_NS "_item")) {
Glib::ustring newguitext, newvalue;
@@ -69,8 +72,8 @@ ParamComboBox::ParamComboBox (const gchar * name, const gchar * guitext, const g
}
if (contents != NULL) {
// don't translate when 'item' but do translate when '_item'
- // NOTE: internal extensions use build_from_mem and don't need _item but
- // still need to include if are to be localized
+ // NOTE: internal extensions use build_from_mem and don't need _item but
+ // still need to include if are to be localized
if (!strcmp(chname, INKSCAPE_EXTENSION_NS "_item")) {
if (node->attribute("msgctxt") != NULL) {
newguitext = g_dpgettext2(NULL, node->attribute("msgctxt"), contents);
@@ -95,30 +98,28 @@ ParamComboBox::ParamComboBox (const gchar * name, const gchar * guitext, const g
}
}
}
- }
-
- // Initialize _value with the default value from xml
- // for simplicity : default to the contents of the first xml-child
- const char * defaultval = NULL;
- if (xml->firstChild() && xml->firstChild()->firstChild()) {
- defaultval = xml->firstChild()->attribute("value");
- }
+
+ // Initialize _value with the default value from xml
+ // for simplicity : default to the contents of the first xml-child
+ if (xml->firstChild() && xml->firstChild()->firstChild()) {
+ xmlval = xml->firstChild()->attribute("value");
+ }
- const char * indent = xml->attribute("indent");
- if (indent != NULL) {
- _indent = atoi(indent) * 12;
+ const char *indent = xml->attribute("indent");
+ if (indent != NULL) {
+ _indent = atoi(indent) * 12;
+ }
}
gchar * pref_name = this->pref_name();
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- Glib::ustring paramval = prefs->getString(extension_pref_root + pref_name);
+ Glib::ustring paramval = prefs ? prefs->getString(extension_pref_root + pref_name) : "";
g_free(pref_name);
if (!paramval.empty()) {
- defaultval = paramval.data();
- }
- if (defaultval != NULL) {
- _value = g_strdup(defaultval);
+ _value = g_strdup(paramval.data());
+ } else if (xmlval) {
+ _value = g_strdup(xmlval);
}
}
diff --git a/src/extension/param/notebook.cpp b/src/extension/param/notebook.cpp
index 97002e33f..9ec31ca6b 100644
--- a/src/extension/param/notebook.cpp
+++ b/src/extension/param/notebook.cpp
@@ -214,7 +214,7 @@ Gtk::Widget * ParamNotebookPage::get_widget(SPDocument * doc, Inkscape::XML::Nod
// printf("Tip: '%s'\n", tip);
vbox->pack_start(*widg, false, false, 2);
if (tip) {
- widg->set_tooltip_text(tip);
+ widg->set_tooltip_text(_(tip));
} else {
widg->set_tooltip_text("");
widg->set_has_tooltip(false);
diff --git a/src/extension/param/radiobutton.cpp b/src/extension/param/radiobutton.cpp
index 75d5a40e3..f9515197c 100644
--- a/src/extension/param/radiobutton.cpp
+++ b/src/extension/param/radiobutton.cpp
@@ -122,7 +122,7 @@ ParamRadioButton::ParamRadioButton (const gchar * name,
defaultval = (static_cast<optionentry*> (choices->data))->value->c_str();
}
- const char * indent = xml->attribute("indent");
+ const char *indent = xml ? xml->attribute("indent") : NULL;
if (indent != NULL) {
_indent = atoi(indent) * 12;
}
diff --git a/src/extension/prefdialog.cpp b/src/extension/prefdialog.cpp
index 1b657f644..0ea15a5cd 100644
--- a/src/extension/prefdialog.cpp
+++ b/src/extension/prefdialog.cpp
@@ -13,7 +13,7 @@
#include <gtkmm/separator.h>
#include <glibmm/i18n.h>
-#include "../dialogs/dialog-events.h"
+#include "ui/dialog-events.h"
#include "xml/repr.h"
// Used to get SP_ACTIVE_DESKTOP
@@ -90,6 +90,10 @@ PrefDialog::PrefDialog (Glib::ustring name, gchar const * help, Gtk::Widget * co
if (_effect != NULL && !_effect->no_live_preview) {
if (_param_preview == NULL) {
XML::Document * doc = sp_repr_read_mem(live_param_xml, strlen(live_param_xml), NULL);
+ if (doc == NULL) {
+ std::cout << "Error encountered loading live parameter XML !!!" << std::endl;
+ return;
+ }
_param_preview = Parameter::make(doc->root(), _effect);
}
@@ -212,6 +216,9 @@ PrefDialog::preview_toggle (void) {
void
PrefDialog::param_change (void) {
if (_exEnv != NULL) {
+ if (!_effect->loaded()) {
+ _effect->set_state(Extension::STATE_LOADED);
+ }
_timersig.disconnect();
_timersig = Glib::signal_timeout().connect(sigc::mem_fun(this, &PrefDialog::param_timer_expire),
250, /* ms */
diff --git a/src/extension/system.cpp b/src/extension/system.cpp
index c244d9c16..5225f11ee 100644
--- a/src/extension/system.cpp
+++ b/src/extension/system.cpp
@@ -20,7 +20,7 @@
# include <config.h>
#endif
-#include <interface.h>
+#include "ui/interface.h"
#include <unistd.h>
#include <glibmm/miscutils.h>
@@ -556,7 +556,7 @@ build_from_file(gchar const *filename)
}
/**
- * \return The module created
+ * \return The module created, or NULL if buffer is invalid
* \brief This function creates a module from a buffer holding an
* XML description.
* \param buffer The buffer holding the XML description of the module.
@@ -568,6 +568,7 @@ Extension *
build_from_mem(gchar const *buffer, Implementation::Implementation *in_imp)
{
Inkscape::XML::Document *doc = sp_repr_read_mem(buffer, strlen(buffer), INKSCAPE_EXTENSION_URI);
+ g_return_val_if_fail(doc != NULL, NULL);
Extension *ext = build_from_reprdoc(doc, in_imp);
Inkscape::GC::release(doc);
return ext;
diff --git a/src/extract-uri.h b/src/extract-uri.h
index a6707f1a1..e9ee0b1d8 100644
--- a/src/extract-uri.h
+++ b/src/extract-uri.h
@@ -1,9 +1,7 @@
#ifndef SEEN_EXTRACT_URI_H
#define SEEN_EXTRACT_URI_H
-#include <glib.h>
-
-gchar *extract_uri(gchar const *s, gchar const** endptr = 0);
+char *extract_uri(char const *s, char const** endptr = 0);
#endif /* !SEEN_EXTRACT_URI_H */
diff --git a/src/factory.h b/src/factory.h
index c76501cfd..c1288b460 100644
--- a/src/factory.h
+++ b/src/factory.h
@@ -91,7 +91,7 @@ struct NodeTraits {
break;
case Inkscape::XML::ELEMENT_NODE: {
- gchar const *const sptype = node.attribute("sodipodi:type");
+ char const *const sptype = node.attribute("sodipodi:type");
if (sptype) {
name = sptype;
diff --git a/src/file.cpp b/src/file.cpp
index 51e629c7d..307944001 100644
--- a/src/file.cpp
+++ b/src/file.cpp
@@ -46,7 +46,7 @@
#include "id-clash.h"
#include "inkscape.h"
#include "inkscape.h"
-#include "interface.h"
+#include "ui/interface.h"
#include "io/sys.h"
#include "message.h"
#include "message-stack.h"
@@ -148,14 +148,14 @@ SPDesktop *sp_file_new(const std::string &templ)
DocumentUndo::setUndoSensitive(doc, true);
}
- SPDesktop *desktop = SP_ACTIVE_DESKTOP;
- if (desktop)
- desktop->setWaitingCursor();
+ SPDesktop *olddesktop = SP_ACTIVE_DESKTOP;
+ if (olddesktop)
+ olddesktop->setWaitingCursor();
SPViewWidget *dtw = sp_desktop_widget_new(sp_document_namedview(doc, NULL)); // TODO this will trigger broken link warnings, etc.
g_return_val_if_fail(dtw != NULL, NULL);
sp_create_window(dtw, TRUE);
- desktop = static_cast<SPDesktop *>(dtw->view);
+ SPDesktop* desktop = static_cast<SPDesktop *>(dtw->view);
doc->doUnref();
@@ -166,6 +166,8 @@ SPDesktop *sp_file_new(const std::string &templ)
Inkscape::Extension::Dbus::dbus_init_desktop_interface(desktop);
#endif
+ if (olddesktop)
+ olddesktop->clearWaitingCursor();
if (desktop)
desktop->clearWaitingCursor();
@@ -669,7 +671,7 @@ file_save(Gtk::Window &parentWindow, SPDocument *doc, const Glib::ustring &uri,
sp_ui_error_dialog(text);
g_free(text);
g_free(safeUri);
- return FALSE;
+ return false;
} catch (Inkscape::Extension::Output::file_read_only &e) {
gchar *safeUri = Inkscape::IO::sanitizeString(uri.c_str());
gchar *text = g_strdup_printf(_("File %s is write protected. Please remove write protection and try again."), safeUri);
@@ -677,7 +679,7 @@ file_save(Gtk::Window &parentWindow, SPDocument *doc, const Glib::ustring &uri,
sp_ui_error_dialog(text);
g_free(text);
g_free(safeUri);
- return FALSE;
+ return false;
} catch (Inkscape::Extension::Output::save_failed &e) {
gchar *safeUri = Inkscape::IO::sanitizeString(uri.c_str());
gchar *text = g_strdup_printf(_("File %s could not be saved."), safeUri);
@@ -685,15 +687,15 @@ file_save(Gtk::Window &parentWindow, SPDocument *doc, const Glib::ustring &uri,
sp_ui_error_dialog(text);
g_free(text);
g_free(safeUri);
- return FALSE;
+ return false;
} catch (Inkscape::Extension::Output::save_cancelled &e) {
SP_ACTIVE_DESKTOP->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("Document not saved."));
- return FALSE;
+ return false;
} catch (Inkscape::Extension::Output::no_overwrite &e) {
return sp_file_save_dialog(parentWindow, doc, save_method);
} catch (...) {
SP_ACTIVE_DESKTOP->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("Document not saved."));
- return FALSE;
+ return false;
}
if (SP_ACTIVE_DESKTOP) {
@@ -1087,9 +1089,9 @@ void sp_import_document(SPDesktop *desktop, SPDocument *clipdoc, bool in_place)
Inkscape::Selection *selection = sp_desktop_selection(desktop);
selection->setReprList(pasted_objects);
- // invers apply parent transform
+ // Apply inverse of parent transform
Geom::Affine doc2parent = SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse();
- sp_selection_apply_affine(selection, desktop->dt2doc() * doc2parent * desktop->doc2dt(), true, false);
+ sp_selection_apply_affine(selection, desktop->dt2doc() * doc2parent * desktop->doc2dt(), true, false, false);
// Update (among other things) all curves in paths, for bounds() to work
target_document->ensureUpToDate();
@@ -1226,7 +1228,7 @@ file_import(SPDocument *in_doc, const Glib::ustring &uri,
// c2p is identity matrix at this point unless ensureUpToDate is called
doc->ensureUpToDate();
Geom::Affine affine = doc->getRoot()->c2p * SP_ITEM(place_to_insert)->i2doc_affine().inverse();
- sp_selection_apply_affine(selection, desktop->dt2doc() * affine * desktop->doc2dt(), true, false);
+ sp_selection_apply_affine(selection, desktop->dt2doc() * affine * desktop->doc2dt(), true, false, false);
// move to mouse pointer
{
diff --git a/src/file.h b/src/file.h
index 7f80f3645..4ffbc8ec0 100644
--- a/src/file.h
+++ b/src/file.h
@@ -75,7 +75,7 @@ bool sp_file_open(
* Displays a file open dialog. Calls sp_file_open on
* an OK.
*/
-void sp_file_open_dialog (Gtk::Window &parentWindow, gpointer object, gpointer data);
+void sp_file_open_dialog (Gtk::Window &parentWindow, void* object, void* data);
/**
* Reverts file to disk-copy on "YES"
@@ -96,19 +96,19 @@ bool file_save_remote(SPDocument *doc, const Glib::ustring &uri,
/**
*
*/
-bool sp_file_save (Gtk::Window &parentWindow, gpointer object, gpointer data);
+bool sp_file_save (Gtk::Window &parentWindow, void* object, void* data);
/**
* Saves the given document. Displays a file select dialog
* to choose the new name.
*/
-bool sp_file_save_as (Gtk::Window &parentWindow, gpointer object, gpointer data);
+bool sp_file_save_as (Gtk::Window &parentWindow, void* object, void* data);
/**
* Saves a copy of the given document. Displays a file select dialog
* to choose a name for the copy.
*/
-bool sp_file_save_a_copy (Gtk::Window &parentWindow, gpointer object, gpointer data);
+bool sp_file_save_a_copy (Gtk::Window &parentWindow, void* object, void* data);
/**
diff --git a/src/filter-chemistry.cpp b/src/filter-chemistry.cpp
index 0f9138560..9298a1ffc 100644
--- a/src/filter-chemistry.cpp
+++ b/src/filter-chemistry.cpp
@@ -15,6 +15,8 @@
#include <cstring>
+#include <glibmm.h>
+
#include "style.h"
#include "document-private.h"
#include "desktop-style.h"
@@ -378,6 +380,11 @@ SPFilter *modify_filter_gaussian_blur_from_item(SPDocument *document, SPItem *it
}
SPFilter *filter = SP_FILTER(item->style->getFilter());
+ if (!filter) {
+ // We reach here when filter.set is true, but the href is not found in the document
+ return new_filter_simple_from_item(document, item, "normal", radius);
+ }
+
Inkscape::XML::Document *xml_doc = document->getReprDoc();
// If there are more users for this filter, duplicate it
diff --git a/src/filter-chemistry.h b/src/filter-chemistry.h
index 2ac3ebe8f..104016845 100644
--- a/src/filter-chemistry.h
+++ b/src/filter-chemistry.h
@@ -14,8 +14,6 @@
#ifndef SEEN_SP_FILTER_CHEMISTRY_H
#define SEEN_SP_FILTER_CHEMISTRY_H
-#include <glib.h>
-
#include "display/nr-filter-types.h"
class SPDocument;
@@ -24,12 +22,11 @@ class SPFilterPrimitive;
class SPItem;
class SPObject;
-
SPFilterPrimitive *filter_add_primitive(SPFilter *filter, Inkscape::Filters::FilterPrimitiveType);
SPFilter *new_filter (SPDocument *document);
-SPFilter *new_filter_gaussian_blur (SPDocument *document, gdouble stdDeviation, double expansion, double expansionX, double expansionY, double width, double height);
-SPFilter *new_filter_simple_from_item (SPDocument *document, SPItem *item, const char *mode, gdouble stdDeviation);
-SPFilter *modify_filter_gaussian_blur_from_item (SPDocument *document, SPItem *item, gdouble stdDeviation);
+SPFilter *new_filter_gaussian_blur (SPDocument *document, double stdDeviation, double expansion, double expansionX, double expansionY, double width, double height);
+SPFilter *new_filter_simple_from_item (SPDocument *document, SPItem *item, const char *mode, double stdDeviation);
+SPFilter *modify_filter_gaussian_blur_from_item (SPDocument *document, SPItem *item, double stdDeviation);
void remove_filter (SPObject *item, bool recursive);
void remove_filter_gaussian_blur (SPObject *item);
bool filter_is_single_gaussian_blur(SPFilter *filter);
diff --git a/src/filter-enums.cpp b/src/filter-enums.cpp
index 7ee57f7fa..ae11aa64f 100644
--- a/src/filter-enums.cpp
+++ b/src/filter-enums.cpp
@@ -9,6 +9,7 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
+#include <glibmm.h>
#include <glibmm/i18n.h>
#include "filter-enums.h"
@@ -53,7 +54,6 @@ const EnumData<Inkscape::Filters::FilterBlendMode> BlendModeData[Inkscape::Filte
{Inkscape::Filters::BLEND_SCREEN, _("Screen"), "screen"},
{Inkscape::Filters::BLEND_DARKEN, _("Darken"), "darken"},
{Inkscape::Filters::BLEND_LIGHTEN, _("Lighten"), "lighten"},
-#ifdef WITH_CSSBLEND
// New in Compositing and Blending Level 1
{Inkscape::Filters::BLEND_OVERLAY, _("Overlay"), "overlay"},
{Inkscape::Filters::BLEND_COLORDODGE, _("Color Dodge"), "color-dodge"},
@@ -66,10 +66,13 @@ const EnumData<Inkscape::Filters::FilterBlendMode> BlendModeData[Inkscape::Filte
{Inkscape::Filters::BLEND_SATURATION, _("Saturation"), "saturation"},
{Inkscape::Filters::BLEND_COLOR, _("Color"), "color"},
{Inkscape::Filters::BLEND_LUMINOSITY, _("Luminosity"), "luminosity"}
-#endif
};
+#ifdef WITH_CSSBLEND
const EnumDataConverter<Inkscape::Filters::FilterBlendMode> BlendModeConverter(BlendModeData, Inkscape::Filters::BLEND_ENDMODE);
-
+#else
+// Disable new blend modes in GUI until widely implemented.
+const EnumDataConverter<Inkscape::Filters::FilterBlendMode> BlendModeConverter(BlendModeData, Inkscape::Filters::BLEND_OVERLAY);
+#endif
const EnumData<Inkscape::Filters::FilterColorMatrixType> ColorMatrixTypeData[Inkscape::Filters::COLORMATRIX_ENDTYPE] = {
{Inkscape::Filters::COLORMATRIX_MATRIX, _("Matrix"), "matrix"},
@@ -116,7 +119,7 @@ const EnumDataConverter<Inkscape::Filters::FilterComponentTransferType> Componen
const EnumData<Inkscape::Filters::FilterConvolveMatrixEdgeMode> ConvolveMatrixEdgeModeData[Inkscape::Filters::CONVOLVEMATRIX_EDGEMODE_ENDTYPE] = {
{Inkscape::Filters::CONVOLVEMATRIX_EDGEMODE_DUPLICATE, _("Duplicate"), "duplicate"},
{Inkscape::Filters::CONVOLVEMATRIX_EDGEMODE_WRAP, _("Wrap"), "wrap"},
- {Inkscape::Filters::CONVOLVEMATRIX_EDGEMODE_NONE, _("None"), "none"}
+ {Inkscape::Filters::CONVOLVEMATRIX_EDGEMODE_NONE, C_("Convolve matrix, edge mode", "None"), "none"}
};
const EnumDataConverter<Inkscape::Filters::FilterConvolveMatrixEdgeMode> ConvolveMatrixEdgeModeConverter(ConvolveMatrixEdgeModeData, Inkscape::Filters::CONVOLVEMATRIX_EDGEMODE_ENDTYPE);
diff --git a/src/filters/blend.cpp b/src/filters/blend.cpp
index 5c78f4f9f..ca1d5bf96 100644
--- a/src/filters/blend.cpp
+++ b/src/filters/blend.cpp
@@ -96,23 +96,18 @@ static Inkscape::Filters::FilterBlendMode sp_feBlend_readmode(gchar const *value
case 's':
if (strncmp(value, "screen", 6) == 0)
return Inkscape::Filters::BLEND_SCREEN;
-#ifdef WITH_CSSBLEND
if (strncmp(value, "saturation", 6) == 0)
return Inkscape::Filters::BLEND_SATURATION;
-#endif
break;
case 'd':
if (strncmp(value, "darken", 6) == 0)
return Inkscape::Filters::BLEND_DARKEN;
-#ifdef WITH_CSSBLEND
if (strncmp(value, "difference", 10) == 0)
return Inkscape::Filters::BLEND_DIFFERENCE;
-#endif
break;
case 'l':
if (strncmp(value, "lighten", 7) == 0)
return Inkscape::Filters::BLEND_LIGHTEN;
-#ifdef WITH_CSSBLEND
if (strncmp(value, "luminosity", 10) == 0)
return Inkscape::Filters::BLEND_LUMINOSITY;
break;
@@ -137,7 +132,6 @@ static Inkscape::Filters::FilterBlendMode sp_feBlend_readmode(gchar const *value
case 'e':
if (strncmp(value, "exclusion", 10) == 0)
return Inkscape::Filters::BLEND_EXCLUSION;
-#endif
default:
std::cout << "Inkscape::Filters::FilterBlendMode: Unimplemented mode: " << value << std::endl;
// do nothing by default
@@ -189,6 +183,8 @@ void SPFeBlend::update(SPCtx *ctx, guint flags) {
/* Unlike normal in, in2 is required attribute. Make sure, we can call
* it by some name. */
+ /* This may not be true.... see issue at
+ * http://www.w3.org/TR/filter-effects/#feBlendElement (but it doesn't hurt). */
if (this->in2 == Inkscape::Filters::NR_FILTER_SLOT_NOT_SET ||
this->in2 == Inkscape::Filters::NR_FILTER_UNNAMED_SLOT)
{
@@ -212,26 +208,30 @@ Inkscape::XML::Node* SPFeBlend::write(Inkscape::XML::Document *doc, Inkscape::XM
repr = doc->createElement("svg:feBlend");
}
- gchar const *out_name = sp_filter_name_for_image(parent, this->in2);
+ gchar const *in2_name = sp_filter_name_for_image(parent, this->in2);
- if (out_name) {
- repr->setAttribute("in2", out_name);
- } else {
+ if( !in2_name ) {
+
+ // This code is very similar to sp_filter_primtive_name_previous_out()
SPObject *i = parent->children;
+ // Find previous filter primitive
while (i && i->next != this) {
i = i->next;
}
- SPFilterPrimitive *i_prim = SP_FILTER_PRIMITIVE(i);
- out_name = sp_filter_name_for_image(parent, i_prim->image_out);
- repr->setAttribute("in2", out_name);
-
- if (!out_name) {
- g_warning("Unable to set in2 for feBlend");
+ if( i ) {
+ SPFilterPrimitive *i_prim = SP_FILTER_PRIMITIVE(i);
+ in2_name = sp_filter_name_for_image(parent, i_prim->image_out);
}
}
+ if (in2_name) {
+ repr->setAttribute("in2", in2_name);
+ } else {
+ g_warning("Unable to set in2 for feBlend");
+ }
+
char const *mode;
switch(this->blend_mode) {
case Inkscape::Filters::BLEND_NORMAL:
@@ -244,7 +244,6 @@ Inkscape::XML::Node* SPFeBlend::write(Inkscape::XML::Document *doc, Inkscape::XM
mode = "darken"; break;
case Inkscape::Filters::BLEND_LIGHTEN:
mode = "lighten"; break;
-#ifdef WITH_CSSBLEND
// New
case Inkscape::Filters::BLEND_OVERLAY:
mode = "overlay"; break;
@@ -268,7 +267,6 @@ Inkscape::XML::Node* SPFeBlend::write(Inkscape::XML::Document *doc, Inkscape::XM
mode = "color"; break;
case Inkscape::Filters::BLEND_LUMINOSITY:
mode = "luminosity"; break;
-#endif
default:
mode = 0;
}
diff --git a/src/filters/composite.cpp b/src/filters/composite.cpp
index 257292f12..e600b6d20 100644
--- a/src/filters/composite.cpp
+++ b/src/filters/composite.cpp
@@ -205,6 +205,8 @@ void SPFeComposite::update(SPCtx *ctx, guint flags) {
/* Unlike normal in, in2 is required attribute. Make sure, we can call
* it by some name. */
+ /* This may not be true.... see issue at
+ * http://www.w3.org/TR/filter-effects/#feBlendElement (but it doesn't hurt). */
if (this->in2 == Inkscape::Filters::NR_FILTER_SLOT_NOT_SET ||
this->in2 == Inkscape::Filters::NR_FILTER_UNNAMED_SLOT)
{
@@ -228,26 +230,30 @@ Inkscape::XML::Node* SPFeComposite::write(Inkscape::XML::Document *doc, Inkscape
repr = doc->createElement("svg:feComposite");
}
- gchar const *out_name = sp_filter_name_for_image(parent, this->in2);
+ gchar const *in2_name = sp_filter_name_for_image(parent, this->in2);
- if (out_name) {
- repr->setAttribute("in2", out_name);
- } else {
+ if( !in2_name ) {
+
+ // This code is very similar to sp_filter_primitive_name_previous_out()
SPObject *i = parent->children;
+ // Find previous filter primitive
while (i && i->next != this) {
i = i->next;
}
- SPFilterPrimitive *i_prim = SP_FILTER_PRIMITIVE(i);
- out_name = sp_filter_name_for_image(parent, i_prim->image_out);
- repr->setAttribute("in2", out_name);
-
- if (!out_name) {
- g_warning("Unable to set in2 for feComposite");
+ if( i ) {
+ SPFilterPrimitive *i_prim = SP_FILTER_PRIMITIVE(i);
+ in2_name = sp_filter_name_for_image(parent, i_prim->image_out);
}
}
+ if (in2_name) {
+ repr->setAttribute("in2", in2_name);
+ } else {
+ g_warning("Unable to set in2 for feComposite");
+ }
+
char const *comp_op;
switch (this->composite_operator) {
diff --git a/src/filters/displacementmap.cpp b/src/filters/displacementmap.cpp
index 473e4913f..7dedfc031 100644
--- a/src/filters/displacementmap.cpp
+++ b/src/filters/displacementmap.cpp
@@ -202,25 +202,30 @@ Inkscape::XML::Node* SPFeDisplacementMap::write(Inkscape::XML::Document *doc, In
repr = doc->createElement("svg:feDisplacementMap");
}
- gchar const *out_name = sp_filter_name_for_image(parent, this->in2);
- if (out_name) {
- repr->setAttribute("in2", out_name);
- } else {
+ gchar const *in2_name = sp_filter_name_for_image(parent, this->in2);
+
+ if( !in2_name ) {
+
+ // This code is very similar to sp_filter_primtive_name_previous_out()
SPObject *i = parent->children;
+ // Find previous filter primitive
while (i && i->next != this) {
i = i->next;
}
- SPFilterPrimitive *i_prim = SP_FILTER_PRIMITIVE(i);
- out_name = sp_filter_name_for_image(parent, i_prim->image_out);
- repr->setAttribute("in2", out_name);
-
- if (!out_name) {
- g_warning("Unable to set in2 for feDisplacementMap");
+ if( i ) {
+ SPFilterPrimitive *i_prim = SP_FILTER_PRIMITIVE(i);
+ in2_name = sp_filter_name_for_image(parent, i_prim->image_out);
}
}
+ if (in2_name) {
+ repr->setAttribute("in2", in2_name);
+ } else {
+ g_warning("Unable to set in2 for feDisplacementMap");
+ }
+
sp_repr_set_svg_double(repr, "scale", this->scale);
repr->setAttribute("xChannelSelector",
get_channelselector_name(this->xChannelSelector));
diff --git a/src/filters/distantlight.h b/src/filters/distantlight.h
index 0eebf768f..6490d987c 100644
--- a/src/filters/distantlight.h
+++ b/src/filters/distantlight.h
@@ -27,21 +27,21 @@ public:
virtual ~SPFeDistantLight();
/** azimuth attribute */
- gfloat azimuth;
- guint azimuth_set : 1;
+ float azimuth;
+ unsigned int azimuth_set : 1;
/** elevation attribute */
- gfloat elevation;
- guint elevation_set : 1;
+ float elevation;
+ unsigned int elevation_set : 1;
protected:
virtual void build(SPDocument* doc, Inkscape::XML::Node* repr);
virtual void release();
- virtual void set(unsigned int key, const gchar* value);
+ virtual void set(unsigned int key, char const* value);
virtual void update(SPCtx* ctx, unsigned int flags);
- virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, guint flags);
+ virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, unsigned int flags);
};
#endif /* !SP_FEDISTANTLIGHT_H_SEEN */
diff --git a/src/filters/pointlight.h b/src/filters/pointlight.h
index 3819d8ff5..1e26d45e7 100644
--- a/src/filters/pointlight.h
+++ b/src/filters/pointlight.h
@@ -26,24 +26,24 @@ public:
virtual ~SPFePointLight();
/** x coordinate of the light source */
- gfloat x;
- guint x_set : 1;
+ float x;
+ unsigned int x_set : 1;
/** y coordinate of the light source */
- gfloat y;
- guint y_set : 1;
+ float y;
+ unsigned int y_set : 1;
/** z coordinate of the light source */
- gfloat z;
- guint z_set : 1;
+ float z;
+ unsigned int z_set : 1;
protected:
virtual void build(SPDocument* doc, Inkscape::XML::Node* repr);
virtual void release();
- virtual void set(unsigned int key, const gchar* value);
+ virtual void set(unsigned int key, char const* value);
virtual void update(SPCtx* ctx, unsigned int flags);
- virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, guint flags);
+ virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, unsigned int flags);
};
#endif /* !SP_FEPOINTLIGHT_H_SEEN */
diff --git a/src/filters/spotlight.h b/src/filters/spotlight.h
index 8caf12858..7d5f6dd30 100644
--- a/src/filters/spotlight.h
+++ b/src/filters/spotlight.h
@@ -26,40 +26,40 @@ public:
virtual ~SPFeSpotLight();
/** x coordinate of the light source */
- gfloat x;
- guint x_set : 1;
+ float x;
+ unsigned int x_set : 1;
/** y coordinate of the light source */
- gfloat y;
- guint y_set : 1;
+ float y;
+ unsigned int y_set : 1;
/** z coordinate of the light source */
- gfloat z;
- guint z_set : 1;
+ float z;
+ unsigned int z_set : 1;
/** x coordinate of the point the source is pointing at */
- gfloat pointsAtX;
- guint pointsAtX_set : 1;
+ float pointsAtX;
+ unsigned int pointsAtX_set : 1;
/** y coordinate of the point the source is pointing at */
- gfloat pointsAtY;
- guint pointsAtY_set : 1;
+ float pointsAtY;
+ unsigned int pointsAtY_set : 1;
/** z coordinate of the point the source is pointing at */
- gfloat pointsAtZ;
- guint pointsAtZ_set : 1;
+ float pointsAtZ;
+ unsigned int pointsAtZ_set : 1;
/** specular exponent (focus of the light) */
- gfloat specularExponent;
- guint specularExponent_set : 1;
+ float specularExponent;
+ unsigned int specularExponent_set : 1;
/** limiting cone angle */
- gfloat limitingConeAngle;
- guint limitingConeAngle_set : 1;
+ float limitingConeAngle;
+ unsigned int limitingConeAngle_set : 1;
//other fields
protected:
virtual void build(SPDocument* doc, Inkscape::XML::Node* repr);
virtual void release();
- virtual void set(unsigned int key, const gchar* value);
+ virtual void set(unsigned int key, char const* value);
virtual void update(SPCtx* ctx, unsigned int flags);
- virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, guint flags);
+ virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, unsigned int flags);
};
#endif /* !SP_FESPOTLIGHT_H_SEEN */
diff --git a/src/gc-anchored.h b/src/gc-anchored.h
index a20904dce..99b78c784 100644
--- a/src/gc-anchored.h
+++ b/src/gc-anchored.h
@@ -9,7 +9,6 @@
#ifndef SEEN_INKSCAPE_GC_ANCHORED_H
#define SEEN_INKSCAPE_GC_ANCHORED_H
-#include <glib.h>
#include "gc-managed.h"
namespace Inkscape {
diff --git a/src/gc-core.h b/src/gc-core.h
index 3957bda1a..d9d0bf4ff 100644
--- a/src/gc-core.h
+++ b/src/gc-core.h
@@ -24,7 +24,6 @@
#else
# include <gc.h>
#endif
-#include <glib.h>
namespace Inkscape {
namespace GC {
diff --git a/src/gradient-chemistry.cpp b/src/gradient-chemistry.cpp
index 89b7968fc..27f4d7a98 100644
--- a/src/gradient-chemistry.cpp
+++ b/src/gradient-chemistry.cpp
@@ -1296,6 +1296,10 @@ Geom::Point getGradientCoords(SPItem *item, GrPointType point_type, guint point_
break;
case POINT_LG_MID:
{
+ if (lg->vector.stops.size() < point_i) {
+ g_message("POINT_LG_MID bug trigger, see LP bug #453067");
+ break;
+ }
gdouble offset = lg->vector.stops.at(point_i).offset;
p = (1-offset) * Geom::Point(lg->x1.computed, lg->y1.computed) + offset * Geom::Point(lg->x2.computed, lg->y2.computed);
}
@@ -1321,12 +1325,20 @@ Geom::Point getGradientCoords(SPItem *item, GrPointType point_type, guint point_
break;
case POINT_RG_MID1:
{
+ if (rg->vector.stops.size() < point_i) {
+ g_message("POINT_RG_MID1 bug trigger, see LP bug #453067");
+ break;
+ }
gdouble offset = rg->vector.stops.at(point_i).offset;
p = (1-offset) * Geom::Point (rg->cx.computed, rg->cy.computed) + offset * Geom::Point(rg->cx.computed + rg->r.computed, rg->cy.computed);
}
break;
case POINT_RG_MID2:
{
+ if (rg->vector.stops.size() < point_i) {
+ g_message("POINT_RG_MID2 bug trigger, see LP bug #453067");
+ break;
+ }
gdouble offset = rg->vector.stops.at(point_i).offset;
p = (1-offset) * Geom::Point (rg->cx.computed, rg->cy.computed) + offset * Geom::Point(rg->cx.computed, rg->cy.computed - rg->r.computed);
}
diff --git a/src/gradient-chemistry.h b/src/gradient-chemistry.h
index 728874f88..792ccc72e 100644
--- a/src/gradient-chemistry.h
+++ b/src/gradient-chemistry.h
@@ -22,6 +22,7 @@
class SPCSSAttr;
class SPItem;
+typedef unsigned int guint32;
/**
* Either normalizes given gradient to vector, or returns fresh normalized
@@ -53,7 +54,7 @@ SPGradient *sp_gradient_vector_for_object( SPDocument *doc, SPDesktop *desktop,
void sp_object_ensure_fill_gradient_normalized (SPObject *object);
void sp_object_ensure_stroke_gradient_normalized (SPObject *object);
-SPGradient *sp_gradient_convert_to_userspace (SPGradient *gr, SPItem *item, const gchar *property);
+SPGradient *sp_gradient_convert_to_userspace (SPGradient *gr, SPItem *item, const char *property);
SPGradient *sp_gradient_reset_to_userspace (SPGradient *gr, SPItem *item);
SPGradient *sp_gradient_fork_vector_if_necessary (SPGradient *gr);
@@ -61,11 +62,11 @@ SPGradient *sp_gradient_get_forked_vector_if_necessary(SPGradient *gradient, boo
SPStop* sp_last_stop(SPGradient *gradient);
-SPStop* sp_get_stop_i(SPGradient *gradient, guint i);
-guint sp_number_of_stops(SPGradient const *gradient);
-guint sp_number_of_stops_before_stop(SPGradient const *gradient, SPStop *target);
+SPStop* sp_get_stop_i(SPGradient *gradient, unsigned int i);
+unsigned int sp_number_of_stops(SPGradient const *gradient);
+unsigned int sp_number_of_stops_before_stop(SPGradient const *gradient, SPStop *target);
-guint32 average_color(guint32 c1, guint32 c2, gdouble p = 0.5);
+guint32 average_color(guint32 c1, guint32 c2, double p = 0.5);
SPStop *sp_vector_add_stop(SPGradient *vector, SPStop* prev_stop, SPStop* next_stop, gfloat offset);
@@ -86,20 +87,20 @@ void sp_gradient_unset_swatch(SPDesktop *desktop, std::string id);
SPGradient *getGradient(SPItem *item, Inkscape::PaintTarget fill_or_stroke);
-void sp_item_gradient_set_coords(SPItem *item, GrPointType point_type, guint point_i, Geom::Point p_desk, Inkscape::PaintTarget fill_or_stroke, bool write_repr, bool scale);
+void sp_item_gradient_set_coords(SPItem *item, GrPointType point_type, unsigned int point_i, Geom::Point p_desk, Inkscape::PaintTarget fill_or_stroke, bool write_repr, bool scale);
/**
* Returns the position of point point_type of the gradient applied to item (either fill_or_stroke),
* in desktop coordinates.
*/
-Geom::Point getGradientCoords(SPItem *item, GrPointType point_type, guint point_i, Inkscape::PaintTarget fill_or_stroke);
+Geom::Point getGradientCoords(SPItem *item, GrPointType point_type, unsigned int point_i, Inkscape::PaintTarget fill_or_stroke);
SPGradient *sp_item_gradient_get_vector(SPItem *item, Inkscape::PaintTarget fill_or_stroke);
SPGradientSpread sp_item_gradient_get_spread(SPItem *item, Inkscape::PaintTarget fill_or_stroke);
-void sp_item_gradient_stop_set_style(SPItem *item, GrPointType point_type, guint point_i, Inkscape::PaintTarget fill_or_stroke, SPCSSAttr *stop);
-guint32 sp_item_gradient_stop_query_style(SPItem *item, GrPointType point_type, guint point_i, Inkscape::PaintTarget fill_or_stroke);
-void sp_item_gradient_edit_stop(SPItem *item, GrPointType point_type, guint point_i, Inkscape::PaintTarget fill_or_stroke);
+void sp_item_gradient_stop_set_style(SPItem *item, GrPointType point_type, unsigned int point_i, Inkscape::PaintTarget fill_or_stroke, SPCSSAttr *stop);
+guint32 sp_item_gradient_stop_query_style(SPItem *item, GrPointType point_type, unsigned int point_i, Inkscape::PaintTarget fill_or_stroke);
+void sp_item_gradient_edit_stop(SPItem *item, GrPointType point_type, unsigned int point_i, Inkscape::PaintTarget fill_or_stroke);
void sp_item_gradient_reverse_vector(SPItem *item, Inkscape::PaintTarget fill_or_stroke);
void sp_item_gradient_invert_vector_color(SPItem *item, Inkscape::PaintTarget fill_or_stroke);
diff --git a/src/gradient-drag.cpp b/src/gradient-drag.cpp
index ee4c1bc8c..d945231fc 100644
--- a/src/gradient-drag.cpp
+++ b/src/gradient-drag.cpp
@@ -21,7 +21,6 @@
#include <glibmm/i18n.h>
#include <cstring>
#include <string>
-//#include <2geom/bezier-curve.h>
#include "desktop-handles.h"
#include "selection.h"
@@ -38,6 +37,7 @@
#include "svg/css-ostringstream.h"
#include "svg/svg.h"
#include "preferences.h"
+#include "inkscape.h"
#include "sp-item.h"
#include "style.h"
#include "knot.h"
@@ -55,6 +55,7 @@
#include "verbs.h"
#include "display/sp-canvas.h"
#include "ui/control-manager.h"
+#include "ui/tools/tool-base.h"
using Inkscape::ControlManager;
using Inkscape::CtrlLineType;
@@ -781,8 +782,13 @@ static void gr_knot_moved_handler(SPKnot *knot, Geom::Point const &ppointer, gui
// unlink and delete this dragger
dragger->parent->draggers = g_list_remove (dragger->parent->draggers, dragger);
+ d_new->parent->draggers = g_list_remove (d_new->parent->draggers, dragger);
+ d_new->parent->selected = g_list_remove (d_new->parent->selected, dragger);
delete dragger;
+ // throw out delayed snap context
+ Inkscape::UI::Tools::sp_event_context_discard_delayed_snap_event(SP_ACTIVE_DESKTOP->event_context);
+
// update the new merged dragger
d_new->fireDraggables(true, false, true);
d_new->parent->updateLines();
@@ -790,8 +796,7 @@ static void gr_knot_moved_handler(SPKnot *knot, Geom::Point const &ppointer, gui
d_new->updateKnotShape ();
d_new->updateTip ();
d_new->updateDependencies(true);
- DocumentUndo::done(sp_desktop_document (d_new->parent->desktop), SP_VERB_CONTEXT_GRADIENT,
- _("Merge gradient handles"));
+ DocumentUndo::done(sp_desktop_document (d_new->parent->desktop), SP_VERB_CONTEXT_GRADIENT, _("Merge gradient handles"));
return;
}
}
diff --git a/src/graphlayout.cpp b/src/graphlayout.cpp
index 7e10ccca1..18159cb41 100644
--- a/src/graphlayout.cpp
+++ b/src/graphlayout.cpp
@@ -195,8 +195,8 @@ void graphlayout(GSList const *const items) {
unsigned v=v_pair->second;
//cout << "Edge: (" << u <<","<<v<<")"<<endl;
es.push_back(make_pair(u,v));
- if(conn->style->marker[SP_MARKER_LOC_END].set) {
- if(directed && strcmp(conn->style->marker[SP_MARKER_LOC_END].value,"none")) {
+ if(conn->style->marker_end.set) {
+ if(directed && strcmp(conn->style->marker_end.value,"none")) {
scy.push_back(new SimpleConstraint(v, u,
(ideal_connector_length * directed_edge_height_modifier)));
}
diff --git a/src/graphlayout.h b/src/graphlayout.h
index 6083ad77f..0ffb645b6 100644
--- a/src/graphlayout.h
+++ b/src/graphlayout.h
@@ -14,10 +14,15 @@
#ifndef SEEN_GRAPHLAYOUT_H
#define SEEN_GRAPHLAYOUT_H
-struct _GSList;
-void graphlayout(_GSList const *const items);
+#include <list>
+
+typedef struct _GSList GSList;
class SPItem;
+
+void graphlayout(GSList const *const items);
+
bool isConnector(SPItem const *const item);
-#include <list>
-void filterConnectors(_GSList const *const items, std::list<SPItem *> &filtered);
+
+void filterConnectors(GSList const *const items, std::list<SPItem *> &filtered);
+
#endif // SEEN_GRAPHLAYOUT_H
diff --git a/src/guide-snapper.cpp b/src/guide-snapper.cpp
index 20c95459d..960caed67 100644
--- a/src/guide-snapper.cpp
+++ b/src/guide-snapper.cpp
@@ -48,7 +48,7 @@ Inkscape::GuideSnapper::LineList Inkscape::GuideSnapper::_getSnapLines(Geom::Poi
for (GSList const *l = _snapmanager->getNamedView()->guides; l != NULL; l = l->next) {
SPGuide const *g = SP_GUIDE(l->data);
if (g != guide_to_ignore) {
- s.push_back(std::make_pair(g->normal_to_line, g->point_on_line));
+ s.push_back(std::pair<Geom::Point, Geom::Point>(g->getNormal(), g->getPoint()));
}
}
diff --git a/src/help.cpp b/src/help.cpp
index 02a1930f4..643945a69 100644
--- a/src/help.cpp
+++ b/src/help.cpp
@@ -1,6 +1,4 @@
-#define __SP_HELP_C__
-
-/*
+/**
* Help/About window
*
* Authors:
@@ -17,20 +15,19 @@
# include "config.h"
#endif
-#include "ui/dialog/aboutbox.h"
-#include "path-prefix.h"
-#include "help.h"
-#include "file.h"
+#include <glibmm.h>
+#include "file.h"
+#include "help.h"
+#include "path-prefix.h"
+#include "ui/dialog/aboutbox.h"
-void
-sp_help_about (void)
+void sp_help_about()
{
Inkscape::UI::Dialog::AboutBox::show_about();
}
-void
-sp_help_open_tutorial(GtkMenuItem *, gpointer data)
+void sp_help_open_tutorial(GtkMenuItem *, void* data)
{
gchar const *name = static_cast<gchar const *>(data);
gchar *c = g_build_filename(INKSCAPE_TUTORIALSDIR, name, NULL);
diff --git a/src/help.h b/src/help.h
index 3fce65fef..3f83e3367 100644
--- a/src/help.h
+++ b/src/help.h
@@ -1,6 +1,4 @@
-#ifndef SEEN_HELP_H
-#define SEEN_HELP_H
-/*
+/**
* Authors:
* Lauris Kaplinski <lauris@kaplinski.com>
*
@@ -10,18 +8,18 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include <glib.h>
-#include <gtk/gtk.h>
+#ifndef SEEN_HELP_H
+#define SEEN_HELP_H
+
+typedef struct _GtkMenuItem GtkMenuItem;
/**
* Help/About window.
*/
-void sp_help_about(void);
-
-void sp_help_open_tutorial(GtkMenuItem *menuitem, gpointer data);
-
+void sp_help_about();
+void sp_help_open_tutorial(GtkMenuItem * /*unused*/, void* data);
-#endif /* !SEEN_HELP_H */
+#endif // !SEEN_HELP_H
/*
Local Variables:
@@ -32,4 +30,4 @@ void sp_help_open_tutorial(GtkMenuItem *menuitem, gpointer data);
fill-column:99
End:
*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8 :
diff --git a/src/helper-fns.h b/src/helper-fns.h
index 699fbbe11..2f1829c37 100644
--- a/src/helper-fns.h
+++ b/src/helper-fns.h
@@ -10,7 +10,7 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include <string.h>
+#include <cstring>
#include <vector>
#include <sstream>
@@ -63,34 +63,6 @@ inline bool helperfns_read_bool(gchar const *value, bool default_value){
* the function can only be used to convert numbers as given by gui elements that use localized representation
* numbers are delimeted by space
* @param value ascii representation of the number
- * @param size number of elements in string
- * @return the vector of the converted numbers
- */
-/*
-inline std::vector<gdouble> helperfns_read_vector(const gchar* value, int size){
- std::vector<gdouble> v(size, (gdouble) 0);
- std::istringstream is(value);
- for(int i = 0; i < size; i++){
- std::string str;
- is >> str;
- char *end;
-
- double ret = g_ascii_strtod(str.c_str(), &end);
- if (*end) {
- g_warning("helper-fns::helperfns_read_vector() Unable to convert \"%s\" to number", str.c_str());
- // We could leave this out, too. If strtod can't convert
- // anything, it will return zero.
- ret = 0;
- }
- v[i] = ret;
- };
- return v;
-}
-*/
-/* convert ascii representation to double
- * the function can only be used to convert numbers as given by gui elements that use localized representation
- * numbers are delimeted by space
- * @param value ascii representation of the number
* @return the vector of the converted numbers
*/
inline std::vector<gdouble> helperfns_read_vector(const gchar* value){
diff --git a/src/helper/action.h b/src/helper/action.h
index 1f2de87b4..4b81ee7f9 100644
--- a/src/helper/action.h
+++ b/src/helper/action.h
@@ -13,12 +13,8 @@
#define SEEN_INKSCAPE_SP_ACTION_H
#include "helper/action-context.h"
-#include <sigc++/sigc++.h>
+#include <sigc++/signal.h>
#include <glibmm/ustring.h>
-#include <glib-object.h>
-
-struct SPAction;
-struct SPActionClass;
#define SP_TYPE_ACTION (sp_action_get_type())
#define SP_ACTION(o) (G_TYPE_CHECK_INSTANCE_CAST((o), SP_TYPE_ACTION, SPAction))
diff --git a/src/helper/geom.cpp b/src/helper/geom.cpp
index c9148a634..6eba6e949 100644
--- a/src/helper/geom.cpp
+++ b/src/helper/geom.cpp
@@ -168,24 +168,25 @@ bounds_exact_transformed(Geom::PathVector const & pv, Geom::Affine const & t)
for (Geom::Path::const_iterator cit = it->begin(); cit != it->end_open(); ++cit) {
Geom::Curve const &c = *cit;
- if( is_straight_curve(c) )
- {
- bbox.expandTo( c.finalPoint() * t );
- }
- else if(Geom::CubicBezier const *cubic_bezier = dynamic_cast<Geom::CubicBezier const *>(&c))
- {
- Geom::Point c0 = (*cubic_bezier)[0] * t;
- Geom::Point c1 = (*cubic_bezier)[1] * t;
- Geom::Point c2 = (*cubic_bezier)[2] * t;
- Geom::Point c3 = (*cubic_bezier)[3] * t;
- cubic_bbox( c0[0], c0[1],
- c1[0], c1[1],
- c2[0], c2[1],
- c3[0], c3[1],
- bbox );
+ unsigned order = 0;
+ if (Geom::BezierCurve const* b = dynamic_cast<Geom::BezierCurve const*>(&c)) {
+ order = b->order();
}
- else
- {
+
+ if (order == 1) { // line segment
+ bbox.expandTo(c.finalPoint() * t);
+
+ // TODO: we can make the case for quadratics faster by degree elevating them to
+ // cubic and then taking the bbox of that.
+
+ } else if (order == 3) { // cubic bezier
+ Geom::CubicBezier const &cubic_bezier = static_cast<Geom::CubicBezier const&>(c);
+ Geom::Point c0 = cubic_bezier[0] * t;
+ Geom::Point c1 = cubic_bezier[1] * t;
+ Geom::Point c2 = cubic_bezier[2] * t;
+ Geom::Point c3 = cubic_bezier[3] * t;
+ cubic_bbox(c0[0], c0[1], c1[0], c1[1], c2[0], c2[1], c3[0], c3[1], bbox);
+ } else {
// should handle all not-so-easy curves:
Geom::Curve *ctemp = cit->transformed(t);
bbox.unionWith( ctemp->boundsExact());
@@ -356,8 +357,11 @@ geom_curve_bbox_wind_distance(Geom::Curve const & c, Geom::Affine const &m,
Geom::Coord tolerance, Geom::Rect const *viewbox,
Geom::Point &p0) // pass p0 through as it represents the last endpoint added (the finalPoint of last curve)
{
- if( is_straight_curve(c) )
- {
+ unsigned order = 0;
+ if (Geom::BezierCurve const* b = dynamic_cast<Geom::BezierCurve const*>(&c)) {
+ order = b->order();
+ }
+ if (order == 1) {
Geom::Point pe = c.finalPoint() * m;
if (bbox) {
bbox->expandTo(pe);
@@ -373,10 +377,11 @@ geom_curve_bbox_wind_distance(Geom::Curve const & c, Geom::Affine const &m,
}
p0 = pe;
}
- else if(Geom::CubicBezier const *cubic_bezier = dynamic_cast<Geom::CubicBezier const *>(&c)) {
- Geom::Point p1 = (*cubic_bezier)[1] * m;
- Geom::Point p2 = (*cubic_bezier)[2] * m;
- Geom::Point p3 = (*cubic_bezier)[3] * m;
+ else if (order == 3) {
+ Geom::CubicBezier const& cubic_bezier = static_cast<Geom::CubicBezier const&>(c);
+ Geom::Point p1 = cubic_bezier[1] * m;
+ Geom::Point p2 = cubic_bezier[2] * m;
+ Geom::Point p3 = cubic_bezier[3] * m;
// get approximate bbox from handles (convex hull property of beziers):
Geom::Rect swept(p0, p3);
@@ -402,7 +407,7 @@ geom_curve_bbox_wind_distance(Geom::Curve const & c, Geom::Affine const &m,
Geom::Path sbasis_path = Geom::cubicbezierpath_from_sbasis(c.toSBasis(), 0.1);
//recurse to convert the new path resulting from the sbasis to svgd
- for(Geom::Path::iterator iter = sbasis_path.begin(); iter != sbasis_path.end(); ++iter) {
+ for (Geom::Path::iterator iter = sbasis_path.begin(); iter != sbasis_path.end(); ++iter) {
geom_curve_bbox_wind_distance(*iter, m, pt, bbox, wind, dist, tolerance, viewbox, p0);
}
}
diff --git a/src/helper/gnome-utils.cpp b/src/helper/gnome-utils.cpp
index 957b7ea5e..3d2b333a2 100644
--- a/src/helper/gnome-utils.cpp
+++ b/src/helper/gnome-utils.cpp
@@ -1,9 +1,7 @@
-#define __GNOME_UTILS_C__
-
-/*
+/**
* Helpers
*
- * Author:
+ * Authors:
* Mitsuru Oka
* Lauris Kaplinski <lauris@kaplinski.com>
*
@@ -25,49 +23,48 @@
* Returns a GList containing strings allocated with g_malloc
* that have been splitted from @uri-list.
*/
-GList*
-gnome_uri_list_extract_uris (const gchar* uri_list)
+GList *gnome_uri_list_extract_uris(const gchar *uri_list)
{
- const gchar *p, *q;
- gchar *retval;
- GList *result = NULL;
-
- g_return_val_if_fail (uri_list != NULL, NULL);
-
- p = uri_list;
-
- /* We don't actually try to validate the URI according to RFC
- * 2396, or even check for allowed characters - we just ignore
- * comments and trim whitespace off the ends. We also
- * allow LF delimination as well as the specified CRLF.
- */
- while (p) {
- if (*p != '#') {
- while (isspace(*p))
- p++;
-
- q = p;
- while (*q && (*q != '\n') && (*q != '\r'))
- q++;
-
- if (q > p) {
- q--;
- while (q > p && isspace(*q))
- q--;
-
- retval = (gchar*)g_malloc (q - p + 2);
- strncpy (retval, p, q - p + 1);
- retval[q - p + 1] = '\0';
-
- result = g_list_prepend (result, retval);
- }
- }
- p = strchr (p, '\n');
- if (p)
- p++;
- }
-
- return g_list_reverse (result);
+ const gchar *p, *q;
+ gchar *retval;
+ GList *result = NULL;
+
+ g_return_val_if_fail(uri_list != NULL, NULL);
+
+ p = uri_list;
+
+ /* We don't actually try to validate the URI according to RFC
+ * 2396, or even check for allowed characters - we just ignore
+ * comments and trim whitespace off the ends. We also
+ * allow LF delimination as well as the specified CRLF.
+ */
+ while (p) {
+ if (*p != '#') {
+ while (isspace(*p))
+ p++;
+
+ q = p;
+ while (*q && (*q != '\n') && (*q != '\r'))
+ q++;
+
+ if (q > p) {
+ q--;
+ while (q > p && isspace(*q))
+ q--;
+
+ retval = (gchar *)g_malloc(q - p + 2);
+ strncpy(retval, p, q - p + 1);
+ retval[q - p + 1] = '\0';
+
+ result = g_list_prepend(result, retval);
+ }
+ }
+ p = strchr(p, '\n');
+ if (p)
+ p++;
+ }
+
+ return g_list_reverse(result);
}
/**
@@ -80,29 +77,40 @@ gnome_uri_list_extract_uris (const gchar* uri_list)
* Note that unlike gnome_uri_list_extract_uris() function, this
* will discard any non-file uri from the result value.
*/
-GList*
-gnome_uri_list_extract_filenames (const gchar* uri_list)
+GList *gnome_uri_list_extract_filenames(const gchar *uri_list)
{
- g_return_val_if_fail (uri_list != NULL, NULL);
-
- GList *result = gnome_uri_list_extract_uris (uri_list);
-
- GList *tmp_list = result;
- while (tmp_list) {
- gchar *s = (gchar*)tmp_list->data;
-
- GList *node = tmp_list;
- tmp_list = tmp_list->next;
-
- if (!strncmp (s, "file:", 5)) {
- node->data = g_filename_from_uri (s, NULL, NULL);
- /* not sure if this fallback is useful at all */
- if (!node->data) node->data = g_strdup (s+5);
- } else {
- result = g_list_remove_link(result, node);
- g_list_free_1 (node);
- }
- g_free (s);
- }
- return result;
+ g_return_val_if_fail(uri_list != NULL, NULL);
+
+ GList *result = gnome_uri_list_extract_uris(uri_list);
+
+ GList *tmp_list = result;
+ while (tmp_list) {
+ gchar *s = (gchar *)tmp_list->data;
+
+ GList *node = tmp_list;
+ tmp_list = tmp_list->next;
+
+ if (!strncmp(s, "file:", 5)) {
+ node->data = g_filename_from_uri(s, NULL, NULL);
+ /* not sure if this fallback is useful at all */
+ if (!node->data)
+ node->data = g_strdup(s + 5);
+ } else {
+ result = g_list_remove_link(result, node);
+ g_list_free_1(node);
+ }
+ g_free(s);
+ }
+ return result;
}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8 :
diff --git a/src/helper/gnome-utils.h b/src/helper/gnome-utils.h
index 3502b28df..6f2f28223 100644
--- a/src/helper/gnome-utils.h
+++ b/src/helper/gnome-utils.h
@@ -1,7 +1,7 @@
-/*
+/**
* GNOME Utils - Migration helper
*
- * Author:
+ * Authors:
* GNOME Developer
* Mitsuru Oka <oka326@parkcity.ne.jp>
* Lauris Kaplinski <lauris@ximian.com>
@@ -11,17 +11,15 @@
* Released under GNU GPL
*/
-
-#ifndef __GNOME_UTILS_H__
-#define __GNOME_UTILS_H__
+#ifndef SEEN_GNOME_UTILS_H
+#define SEEN_GNOME_UTILS_H
#include <glib.h>
GList *gnome_uri_list_extract_uris(gchar const *uri_list);
-
GList *gnome_uri_list_extract_filenames(gchar const *uri_list);
-#endif /* __GNOME_UTILS_H__ */
+#endif // !SEEN_GNOME_UTILS_H
/*
Local Variables:
@@ -32,4 +30,4 @@ GList *gnome_uri_list_extract_filenames(gchar const *uri_list);
fill-column:99
End:
*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8 :
diff --git a/src/helper/pixbuf-ops.cpp b/src/helper/pixbuf-ops.cpp
index d44b2207b..9639096fb 100644
--- a/src/helper/pixbuf-ops.cpp
+++ b/src/helper/pixbuf-ops.cpp
@@ -19,7 +19,7 @@
#include <boost/scoped_ptr.hpp>
#include <2geom/transforms.h>
-#include "interface.h"
+#include "ui/interface.h"
#include "helper/png-write.h"
#include "display/cairo-utils.h"
#include "display/drawing.h"
@@ -34,20 +34,21 @@
#include "helper/pixbuf-ops.h"
-// TODO look for copy-n-past duplication of this function:
+// TODO look for copy-n-paste duplication of this function:
/**
* Hide all items that are not listed in list, recursively, skipping groups and defs.
*/
static void hide_other_items_recursively(SPObject *o, GSList *list, unsigned dkey)
{
- if ( SP_IS_ITEM(o)
- && !SP_IS_DEFS(o)
- && !SP_IS_ROOT(o)
- && !SP_IS_GROUP(o)
- && !SP_IS_USE(o)
+ SPItem *item = dynamic_cast<SPItem *>(o);
+ if ( item
+ && !dynamic_cast<SPDefs *>(item)
+ && !dynamic_cast<SPRoot *>(item)
+ && !dynamic_cast<SPGroup *>(item)
+ && !dynamic_cast<SPUse *>(item)
&& !g_slist_find(list, o) )
{
- SP_ITEM(o)->invoke_hide(dkey);
+ item->invoke_hide(dkey);
}
// recurse
diff --git a/src/helper/png-write.cpp b/src/helper/png-write.cpp
index a7ebe7423..32e50b537 100644
--- a/src/helper/png-write.cpp
+++ b/src/helper/png-write.cpp
@@ -18,7 +18,7 @@
#endif
#include <png.h>
-#include "interface.h"
+#include "ui/interface.h"
#include <2geom/rect.h>
#include <2geom/transforms.h>
#include <glib.h>
diff --git a/src/helper/stock-items.cpp b/src/helper/stock-items.cpp
index a12fa377a..582dcd2a8 100644
--- a/src/helper/stock-items.cpp
+++ b/src/helper/stock-items.cpp
@@ -28,7 +28,7 @@
#include "sp-gradient.h"
#include "document-private.h"
#include "sp-pattern.h"
-#include "marker.h"
+#include "sp-marker.h"
#include "desktop-handles.h"
#include "inkscape.h"
diff --git a/src/helper/window.cpp b/src/helper/window.cpp
index 98fbef170..98e886a38 100644
--- a/src/helper/window.cpp
+++ b/src/helper/window.cpp
@@ -1,6 +1,4 @@
-#define __SP_WINDOW_C__
-
-/*
+/**
* Generic window implementation
*
* Author:
@@ -9,61 +7,61 @@
* This code is in public domain
*/
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#if GLIBMM_DISABLE_DEPRECATED && HAVE_GLIBMM_THREADS_H
-#include <glibmm/threads.h>
-#endif
-
+#include <glibmm.h>
#include <gtkmm/window.h>
+#include "desktop.h"
#include "inkscape.h"
#include "shortcuts.h"
-#include "desktop.h"
#include "ui/tools/tool-base.h"
#include "window.h"
-#include <gtk/gtk.h>
static bool on_window_key_press(GdkEventKey* event)
{
- unsigned int shortcut;
- shortcut = Inkscape::UI::Tools::get_group0_keyval (event) |
+ unsigned shortcut = 0;
+ // FIXME why?
+ shortcut = Inkscape::UI::Tools::get_group0_keyval (event) |
( event->state & GDK_SHIFT_MASK ?
SP_SHORTCUT_SHIFT_MASK : 0 ) |
( event->state & GDK_CONTROL_MASK ?
SP_SHORTCUT_CONTROL_MASK : 0 ) |
( event->state & GDK_MOD1_MASK ?
SP_SHORTCUT_ALT_MASK : 0 );
- return sp_shortcut_invoke (shortcut, SP_ACTIVE_DESKTOP);
+ return sp_shortcut_invoke (shortcut, SP_ACTIVE_DESKTOP);
}
-Gtk::Window *
-Inkscape::UI::window_new (const gchar *title, unsigned int resizeable)
+Gtk::Window * Inkscape::UI::window_new (const gchar *title, unsigned int resizeable)
{
- Gtk::Window *window = new Gtk::Window(Gtk::WINDOW_TOPLEVEL);
- window->set_title (title);
- window->set_resizable (resizeable);
- window->signal_key_press_event().connect(sigc::ptr_fun(&on_window_key_press));
+ Gtk::Window *window = new Gtk::Window(Gtk::WINDOW_TOPLEVEL);
+ window->set_title (title);
+ window->set_resizable (resizeable);
+ window->signal_key_press_event().connect(sigc::ptr_fun(&on_window_key_press));
- return window;
+ return window;
}
-static gboolean
-sp_window_key_press(GtkWidget */*widget*/, GdkEventKey *event)
+static gboolean sp_window_key_press(GtkWidget *, GdkEventKey *event)
{
return on_window_key_press(event);
}
-GtkWidget *
-sp_window_new (const gchar *title, unsigned int resizeable)
+GtkWidget * sp_window_new (const gchar *title, unsigned int resizeable)
{
- GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
- gtk_window_set_title ((GtkWindow *) window, title);
- gtk_window_set_resizable ((GtkWindow *) window, resizeable);
- g_signal_connect_after ((GObject *) window, "key_press_event", (GCallback) sp_window_key_press, NULL);
+ GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_title ((GtkWindow *) window, title);
+ gtk_window_set_resizable ((GtkWindow *) window, resizeable);
+ g_signal_connect_after ((GObject *) window, "key_press_event", (GCallback) sp_window_key_press, NULL);
- return window;
+ return window;
}
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8 :
diff --git a/src/helper/window.h b/src/helper/window.h
index c6807f9e5..a0efcd292 100644
--- a/src/helper/window.h
+++ b/src/helper/window.h
@@ -1,7 +1,7 @@
-#ifndef __SP_WINDOW_H__
-#define __SP_WINDOW_H__
+#ifndef SEEN_SP_WINDOW_H
+#define SEEN_SP_WINDOW_H
-/*
+/**
* Generic window implementation
*
* Author:
@@ -17,10 +17,11 @@ namespace Gtk {
class Window;
}
-/*
- * This function is deprecated. Use Inkscape::UI::window_new instead.
- */
-GtkWidget *sp_window_new (const gchar *title, unsigned int resizeable);
+// Can we just get rid of this altogether?
+#if defined(GCC_VERSION) || defined(__clang__)
+__attribute__((deprecated))
+#endif
+GtkWidget * sp_window_new (const gchar *title, unsigned int resizeable);
namespace Inkscape {
namespace UI {
@@ -30,7 +31,7 @@ Gtk::Window *window_new (const gchar *title, unsigned int resizeable);
}
}
-#endif
+#endif // !SEEN_SP_WINDOW_H
/*
Local Variables:
@@ -41,4 +42,4 @@ Gtk::Window *window_new (const gchar *title, unsigned int resizeable);
fill-column:99
End:
*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8 :
diff --git a/src/icon-size.h b/src/icon-size.h
index 4bb4f1df6..d7a9c9b0b 100644
--- a/src/icon-size.h
+++ b/src/icon-size.h
@@ -12,8 +12,6 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include <glib.h>
-
#include <gtk/gtk.h>
namespace Inkscape {
diff --git a/src/id-clash.cpp b/src/id-clash.cpp
index f59b3b920..4bd66e858 100644
--- a/src/id-clash.cpp
+++ b/src/id-clash.cpp
@@ -53,12 +53,12 @@ const char *href_like_attributes[] = {
#define NUM_HREF_LIKE_ATTRIBUTES (sizeof(href_like_attributes) / sizeof(*href_like_attributes))
const SPIPaint SPStyle::* SPIPaint_members[] = {
- &SPStyle::color,
+ //&SPStyle::color,
&SPStyle::fill,
&SPStyle::stroke,
};
const char* SPIPaint_properties[] = {
- "color",
+ //"color",
"fill",
"stroke",
};
@@ -76,7 +76,7 @@ const char* other_url_properties[] = {
#define NUM_OTHER_URL_PROPERTIES (sizeof(other_url_properties) / sizeof(*other_url_properties))
const char* clipboard_properties[] = {
- "color",
+ //"color",
"fill",
"filter",
"stroke",
@@ -92,7 +92,7 @@ const char* clipboard_properties[] = {
* (e.g., ID selectors in CSS stylesheets, and references in scripts).
*/
static void
-find_references(SPObject *elem, refmap_type *refmap)
+find_references(SPObject *elem, refmap_type &refmap)
{
if (elem->cloned) return;
Inkscape::XML::Node *repr_elem = elem->getRepr();
@@ -110,7 +110,7 @@ find_references(SPObject *elem, refmap_type *refmap)
gchar *uri = extract_uri(value);
if (uri && uri[0] == '#') {
IdReference idref = { REF_CLIPBOARD, elem, attr };
- (*refmap)[uri+1].push_back(idref);
+ refmap[uri+1].push_back(idref);
}
g_free(uri);
}
@@ -127,7 +127,7 @@ find_references(SPObject *elem, refmap_type *refmap)
if (val && val[0] == '#') {
std::string id(val+1);
IdReference idref = { REF_HREF, elem, attr };
- (*refmap)[id].push_back(idref);
+ refmap[id].push_back(idref);
}
}
@@ -142,7 +142,7 @@ find_references(SPObject *elem, refmap_type *refmap)
if (obj) {
const gchar *id = obj->getId();
IdReference idref = { REF_STYLE, elem, SPIPaint_properties[i] };
- (*refmap)[id].push_back(idref);
+ refmap[id].push_back(idref);
}
}
}
@@ -154,19 +154,19 @@ find_references(SPObject *elem, refmap_type *refmap)
if (obj) {
const gchar *id = obj->getId();
IdReference idref = { REF_STYLE, elem, "filter" };
- (*refmap)[id].push_back(idref);
+ refmap[id].push_back(idref);
}
}
/* check for url(#...) references in markers */
const gchar *markers[4] = { "", "marker-start", "marker-mid", "marker-end" };
for (unsigned i = SP_MARKER_LOC_START; i < SP_MARKER_LOC_QTY; i++) {
- const gchar *value = style->marker[i].value;
+ const gchar *value = style->marker_ptrs[i]->value;
if (value) {
gchar *uri = extract_uri(value);
if (uri && uri[0] == '#') {
IdReference idref = { REF_STYLE, elem, markers[i] };
- (*refmap)[uri+1].push_back(idref);
+ refmap[uri+1].push_back(idref);
}
g_free(uri);
}
@@ -180,7 +180,7 @@ find_references(SPObject *elem, refmap_type *refmap)
gchar *uri = extract_uri(value);
if (uri && uri[0] == '#') {
IdReference idref = { REF_URL, elem, attr };
- (*refmap)[uri+1].push_back(idref);
+ refmap[uri+1].push_back(idref);
}
g_free(uri);
}
@@ -199,7 +199,7 @@ find_references(SPObject *elem, refmap_type *refmap)
*/
static void
change_clashing_ids(SPDocument *imported_doc, SPDocument *current_doc,
- SPObject *elem, const refmap_type *refmap,
+ SPObject *elem, refmap_type const &refmap,
id_changelist_type *id_changes)
{
const gchar *id = elem->getId();
@@ -216,8 +216,7 @@ change_clashing_ids(SPDocument *imported_doc, SPDocument *current_doc,
if (cd_obj && SP_IS_GRADIENT(cd_obj)) {
SPGradient *cd_gr = SP_GRADIENT(cd_obj);
- if ( cd_gr->isEquivalent(SP_GRADIENT(elem)) &&
- cd_gr->isAligned(SP_GRADIENT(elem))) {
+ if ( cd_gr->isEquivalent(SP_GRADIENT(elem))) {
fix_clashing_ids = false;
}
}
@@ -234,9 +233,9 @@ change_clashing_ids(SPDocument *imported_doc, SPDocument *current_doc,
}
// Change to the new ID
- elem->getRepr()->setAttribute("id", new_id.c_str());
+ elem->getRepr()->setAttribute("id", new_id);
// Make a note of this change, if we need to fix up refs to it
- if (refmap->find(old_id) != refmap->end())
+ if (refmap.find(old_id) != refmap.end())
id_changes->push_back(id_changeitem_type(elem, old_id));
}
}
@@ -253,36 +252,43 @@ change_clashing_ids(SPDocument *imported_doc, SPDocument *current_doc,
* Fix up references to changed IDs.
*/
static void
-fix_up_refs(const refmap_type *refmap, const id_changelist_type &id_changes)
+fix_up_refs(refmap_type const &refmap, const id_changelist_type &id_changes)
{
id_changelist_type::const_iterator pp;
const id_changelist_type::const_iterator pp_end = id_changes.end();
for (pp = id_changes.begin(); pp != pp_end; ++pp) {
SPObject *obj = pp->first;
- refmap_type::const_iterator pos = refmap->find(pp->second);
+ refmap_type::const_iterator pos = refmap.find(pp->second);
std::list<IdReference>::const_iterator it;
const std::list<IdReference>::const_iterator it_end = pos->second.end();
for (it = pos->second.begin(); it != it_end; ++it) {
- if (it->type == REF_HREF) {
- gchar *new_uri = g_strdup_printf("#%s", obj->getId());
- it->elem->getRepr()->setAttribute(it->attr, new_uri);
- g_free(new_uri);
- } else if (it->type == REF_STYLE) {
- sp_style_set_property_url(it->elem, it->attr, obj, false);
- } else if (it->type == REF_URL) {
- gchar *url = g_strdup_printf("url(#%s)", obj->getId());
- it->elem->getRepr()->setAttribute(it->attr, url);
- g_free(url);
- } else if (it->type == REF_CLIPBOARD) {
- SPCSSAttr *style = sp_repr_css_attr(it->elem->getRepr(), "style");
- gchar *url = g_strdup_printf("url(#%s)", obj->getId());
- sp_repr_css_set_property(style, it->attr, url);
- g_free(url);
- Glib::ustring style_string;
- sp_repr_css_write_string(style, style_string);
- it->elem->getRepr()->setAttribute("style", style_string.c_str());
- } else {
- g_assert(0); // shouldn't happen
+ switch (it->type) {
+ case REF_HREF: {
+ gchar *new_uri = g_strdup_printf("#%s", obj->getId());
+ it->elem->getRepr()->setAttribute(it->attr, new_uri);
+ g_free(new_uri);
+ break;
+ }
+ case REF_STYLE: {
+ sp_style_set_property_url(it->elem, it->attr, obj, false);
+ break;
+ }
+ case REF_URL: {
+ gchar *url = g_strdup_printf("url(#%s)", obj->getId());
+ it->elem->getRepr()->setAttribute(it->attr, url);
+ g_free(url);
+ break;
+ }
+ case REF_CLIPBOARD: {
+ SPCSSAttr *style = sp_repr_css_attr(it->elem->getRepr(), "style");
+ gchar *url = g_strdup_printf("url(#%s)", obj->getId());
+ sp_repr_css_set_property(style, it->attr, url);
+ g_free(url);
+ Glib::ustring style_string;
+ sp_repr_css_write_string(style, style_string);
+ it->elem->getRepr()->setAttribute("style", style_string);
+ break;
+ }
}
}
}
@@ -297,7 +303,7 @@ fix_up_refs(const refmap_type *refmap, const id_changelist_type &id_changes)
void
prevent_id_clashes(SPDocument *imported_doc, SPDocument *current_doc)
{
- refmap_type *refmap = new refmap_type;
+ refmap_type refmap;
id_changelist_type id_changes;
SPObject *imported_root = imported_doc->getRoot();
@@ -305,8 +311,6 @@ prevent_id_clashes(SPDocument *imported_doc, SPDocument *current_doc)
change_clashing_ids(imported_doc, current_doc, imported_root, refmap,
&id_changes);
fix_up_refs(refmap, id_changes);
-
- delete refmap;
}
/*
@@ -315,24 +319,47 @@ prevent_id_clashes(SPDocument *imported_doc, SPDocument *current_doc)
void
change_def_references(SPObject *from_obj, SPObject *to_obj)
{
- refmap_type *refmap = new refmap_type;
+ refmap_type refmap;
SPDocument *current_doc = from_obj->document;
std::string old_id(from_obj->getId());
find_references(current_doc->getRoot(), refmap);
- refmap_type::const_iterator pos = refmap->find(old_id);
- if (pos != refmap->end()) {
+ refmap_type::const_iterator pos = refmap.find(old_id);
+ if (pos != refmap.end()) {
std::list<IdReference>::const_iterator it;
const std::list<IdReference>::const_iterator it_end = pos->second.end();
for (it = pos->second.begin(); it != it_end; ++it) {
- if (it->type == REF_STYLE) {
- sp_style_set_property_url(it->elem, it->attr, to_obj, false);
- }
+ switch (it->type) {
+ case REF_HREF: {
+ gchar *new_uri = g_strdup_printf("#%s", to_obj->getId());
+ it->elem->getRepr()->setAttribute(it->attr, new_uri);
+ g_free(new_uri);
+ break;
+ }
+ case REF_STYLE: {
+ sp_style_set_property_url(it->elem, it->attr, to_obj, false);
+ break;
+ }
+ case REF_URL: {
+ gchar *url = g_strdup_printf("url(#%s)", to_obj->getId());
+ it->elem->getRepr()->setAttribute(it->attr, url);
+ g_free(url);
+ break;
+ }
+ case REF_CLIPBOARD: {
+ SPCSSAttr *style = sp_repr_css_attr(it->elem->getRepr(), "style");
+ gchar *url = g_strdup_printf("url(#%s)", to_obj->getId());
+ sp_repr_css_set_property(style, it->attr, url);
+ g_free(url);
+ Glib::ustring style_string;
+ sp_repr_css_write_string(style, style_string);
+ it->elem->getRepr()->setAttribute("style", style_string);
+ break;
+ }
+ }
}
}
-
- delete refmap;
}
/*
@@ -355,8 +382,7 @@ void rename_id(SPObject *elem, Glib::ustring const &new_name)
}
SPDocument *current_doc = elem->document;
- refmap_type *refmap = new refmap_type;
- id_changelist_type id_changes;
+ refmap_type refmap;
find_references(current_doc->getRoot(), refmap);
std::string old_id(elem->getId());
@@ -374,14 +400,14 @@ void rename_id(SPObject *elem, Glib::ustring const &new_name)
}
// Change to the new ID
- elem->getRepr()->setAttribute("id", new_name2.c_str());
+ elem->getRepr()->setAttribute("id", new_name2);
// Make a note of this change, if we need to fix up refs to it
- if (refmap->find(old_id) != refmap->end()) {
+ id_changelist_type id_changes;
+ if (refmap.find(old_id) != refmap.end()) {
id_changes.push_back(id_changeitem_type(elem, old_id));
}
fix_up_refs(refmap, id_changes);
- delete refmap;
}
/*
diff --git a/src/inkscape-manifest-x64.xml b/src/inkscape-manifest-x64.xml
new file mode 100644
index 000000000..38526cfe6
--- /dev/null
+++ b/src/inkscape-manifest-x64.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+<dependency>
+<dependentAssembly>
+<assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls"
+ version="6.0.0.0" processorArchitecture="amd64"
+ publicKeyToken="6595b64144ccf1df" language="*"/>
+</dependentAssembly>
+</dependency>
+</assembly> \ No newline at end of file
diff --git a/src/inkscape-version.h b/src/inkscape-version.h
index 791351184..ff219047e 100644
--- a/src/inkscape-version.h
+++ b/src/inkscape-version.h
@@ -16,7 +16,7 @@
namespace Inkscape {
-extern gchar const *version_string; ///< Full version string
+extern char const *version_string; ///< Full version string
} // namespace Inkscape
diff --git a/src/inkscape-x64.rc b/src/inkscape-x64.rc
new file mode 100644
index 000000000..7f4d5b9ae
--- /dev/null
+++ b/src/inkscape-x64.rc
@@ -0,0 +1,30 @@
+
+APPLICATION_ICON ICON DISCARDABLE "../inkscape.ico"
+1 24 DISCARDABLE "./inkscape-manifest-x64.xml"
+
+1 VERSIONINFO
+ FILEVERSION 0,91,0,9
+ PRODUCTVERSION 0,91,0,9
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040901b5"
+ BEGIN
+ VALUE "Comments", "Published under the GNU GPL"
+ VALUE "CompanyName", "inkscape.org"
+ VALUE "FileDescription", "Inkscape"
+ VALUE "FileVersion", "0.91+devel"
+ VALUE "InternalName", "Inkscape"
+ VALUE "LegalCopyright", "© 2014 Inkscape"
+ VALUE "ProductName", "Inkscape"
+ VALUE "ProductVersion", "0.91+devel"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 1033, 437
+ END
+END
+
+1000 BITMAP "./show-preview.bmp"
+
diff --git a/src/inkscape.cpp b/src/inkscape.cpp
index 54451aba4..36a802e5f 100644
--- a/src/inkscape.cpp
+++ b/src/inkscape.cpp
@@ -71,7 +71,7 @@
#include "helper/action-context.h"
#include "helper/sp-marshal.h"
-static Inkscape::Application *inkscape = NULL;
+static InkscapeApplication *inkscape = NULL;
/* Backbones of configuration xml data */
#include "menus-skeleton.h"
@@ -99,16 +99,10 @@ enum {
# FORWARD DECLARATIONS
################################*/
-namespace Inkscape {
-struct ApplicationClass;
-}
-
-static void inkscape_class_init (Inkscape::ApplicationClass *klass);
-static void inkscape_init (SPObject *object);
static void inkscape_dispose (GObject *object);
-static void inkscape_activate_desktop_private (Inkscape::Application *inkscape, SPDesktop *desktop);
-static void inkscape_deactivate_desktop_private (Inkscape::Application *inkscape, SPDesktop *desktop);
+static void inkscape_activate_desktop_private (InkscapeApplication *inkscape, SPDesktop *desktop);
+static void inkscape_deactivate_desktop_private (InkscapeApplication *inkscape, SPDesktop *desktop);
class AppSelectionModel {
Inkscape::LayerModel _layer_model;
@@ -126,7 +120,7 @@ public:
Inkscape::Selection *getSelection() const { return _selection; }
};
-struct Inkscape::Application {
+struct InkscapeApplication {
GObject object;
Inkscape::XML::Document *menus;
std::map<SPDocument *, int> document_set;
@@ -140,26 +134,25 @@ struct Inkscape::Application {
guint trackalt;
};
-struct Inkscape::ApplicationClass {
+struct InkscapeApplicationClass {
GObjectClass object_class;
/* Signals */
- void (* change_selection) (Inkscape::Application * inkscape, Inkscape::Selection * selection);
- void (* change_subselection) (Inkscape::Application * inkscape, SPDesktop *desktop);
- void (* modify_selection) (Inkscape::Application * inkscape, Inkscape::Selection * selection, guint flags);
- void (* set_selection) (Inkscape::Application * inkscape, Inkscape::Selection * selection);
- void (* set_eventcontext) (Inkscape::Application * inkscape, Inkscape::UI::Tools::ToolBase * eventcontext);
- void (* activate_desktop) (Inkscape::Application * inkscape, SPDesktop * desktop);
- void (* deactivate_desktop) (Inkscape::Application * inkscape, SPDesktop * desktop);
- void (* destroy_document) (Inkscape::Application *inkscape, SPDocument *doc);
- void (* color_set) (Inkscape::Application *inkscape, SPColor *color, double opacity);
- void (* shut_down) (Inkscape::Application *inkscape);
- void (* dialogs_hide) (Inkscape::Application *inkscape);
- void (* dialogs_unhide) (Inkscape::Application *inkscape);
- void (* external_change) (Inkscape::Application *inkscape);
+ void (* change_selection) (InkscapeApplication * inkscape, Inkscape::Selection * selection);
+ void (* change_subselection) (InkscapeApplication * inkscape, SPDesktop *desktop);
+ void (* modify_selection) (InkscapeApplication * inkscape, Inkscape::Selection * selection, guint flags);
+ void (* set_selection) (InkscapeApplication * inkscape, Inkscape::Selection * selection);
+ void (* set_eventcontext) (InkscapeApplication * inkscape, Inkscape::UI::Tools::ToolBase * eventcontext);
+ void (* activate_desktop) (InkscapeApplication * inkscape, SPDesktop * desktop);
+ void (* deactivate_desktop) (InkscapeApplication * inkscape, SPDesktop * desktop);
+ void (* destroy_document) (InkscapeApplication *inkscape, SPDocument *doc);
+ void (* color_set) (InkscapeApplication *inkscape, SPColor *color, double opacity);
+ void (* shut_down) (InkscapeApplication *inkscape);
+ void (* dialogs_hide) (InkscapeApplication *inkscape);
+ void (* dialogs_unhide) (InkscapeApplication *inkscape);
+ void (* external_change) (InkscapeApplication *inkscape);
};
-static GObjectClass * parent_class;
static guint inkscape_signals[LAST_SIGNAL] = {0};
static void (* segv_handler) (int) = SIG_DFL;
@@ -175,48 +168,21 @@ static void (* bus_handler) (int) = SIG_DFL;
#define INKSCAPE_LEGACY_PROFILE_DIR ".inkscape"
#define MENUS_FILE "menus.xml"
-
-/**
- * Retrieves the GType for the Inkscape Application object.
- */
-GType
-inkscape_get_type (void)
-{
- static GType type = 0;
- if (!type) {
- GTypeInfo info = {
- sizeof (Inkscape::ApplicationClass),
- NULL, NULL,
- (GClassInitFunc) inkscape_class_init,
- NULL, NULL,
- sizeof (Inkscape::Application),
- 4,
- (GInstanceInitFunc) inkscape_init,
- NULL
- };
- type = g_type_register_static (G_TYPE_OBJECT, "Inkscape_Application", &info, (GTypeFlags)0);
- }
- return type;
-}
-
+G_DEFINE_TYPE(InkscapeApplication, inkscape, G_TYPE_OBJECT);
/**
* Initializes the inkscape class, registering all of its signal handlers
* and virtual functions
*/
static void
-inkscape_class_init (Inkscape::ApplicationClass * klass)
+inkscape_class_init (InkscapeApplicationClass * klass)
{
- GObjectClass * object_class;
-
- object_class = (GObjectClass *) klass;
-
- parent_class = (GObjectClass *)g_type_class_peek_parent (klass);
+ GObjectClass * object_class = G_OBJECT_CLASS(klass);
inkscape_signals[MODIFY_SELECTION] = g_signal_new ("modify_selection",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_FIRST,
- G_STRUCT_OFFSET (Inkscape::ApplicationClass, modify_selection),
+ G_STRUCT_OFFSET (InkscapeApplicationClass, modify_selection),
NULL, NULL,
sp_marshal_VOID__POINTER_UINT,
G_TYPE_NONE, 2,
@@ -224,7 +190,7 @@ inkscape_class_init (Inkscape::ApplicationClass * klass)
inkscape_signals[CHANGE_SELECTION] = g_signal_new ("change_selection",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_FIRST,
- G_STRUCT_OFFSET (Inkscape::ApplicationClass, change_selection),
+ G_STRUCT_OFFSET (InkscapeApplicationClass, change_selection),
NULL, NULL,
g_cclosure_marshal_VOID__POINTER,
G_TYPE_NONE, 1,
@@ -232,7 +198,7 @@ inkscape_class_init (Inkscape::ApplicationClass * klass)
inkscape_signals[CHANGE_SUBSELECTION] = g_signal_new ("change_subselection",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_FIRST,
- G_STRUCT_OFFSET (Inkscape::ApplicationClass, change_subselection),
+ G_STRUCT_OFFSET (InkscapeApplicationClass, change_subselection),
NULL, NULL,
g_cclosure_marshal_VOID__POINTER,
G_TYPE_NONE, 1,
@@ -240,7 +206,7 @@ inkscape_class_init (Inkscape::ApplicationClass * klass)
inkscape_signals[SET_SELECTION] = g_signal_new ("set_selection",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_FIRST,
- G_STRUCT_OFFSET (Inkscape::ApplicationClass, set_selection),
+ G_STRUCT_OFFSET (InkscapeApplicationClass, set_selection),
NULL, NULL,
g_cclosure_marshal_VOID__POINTER,
G_TYPE_NONE, 1,
@@ -248,7 +214,7 @@ inkscape_class_init (Inkscape::ApplicationClass * klass)
inkscape_signals[SET_EVENTCONTEXT] = g_signal_new ("set_eventcontext",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_FIRST,
- G_STRUCT_OFFSET (Inkscape::ApplicationClass, set_eventcontext),
+ G_STRUCT_OFFSET (InkscapeApplicationClass, set_eventcontext),
NULL, NULL,
g_cclosure_marshal_VOID__POINTER,
G_TYPE_NONE, 1,
@@ -256,7 +222,7 @@ inkscape_class_init (Inkscape::ApplicationClass * klass)
inkscape_signals[ACTIVATE_DESKTOP] = g_signal_new ("activate_desktop",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_FIRST,
- G_STRUCT_OFFSET (Inkscape::ApplicationClass, activate_desktop),
+ G_STRUCT_OFFSET (InkscapeApplicationClass, activate_desktop),
NULL, NULL,
g_cclosure_marshal_VOID__POINTER,
G_TYPE_NONE, 1,
@@ -264,7 +230,7 @@ inkscape_class_init (Inkscape::ApplicationClass * klass)
inkscape_signals[DEACTIVATE_DESKTOP] = g_signal_new ("deactivate_desktop",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_FIRST,
- G_STRUCT_OFFSET (Inkscape::ApplicationClass, deactivate_desktop),
+ G_STRUCT_OFFSET (InkscapeApplicationClass, deactivate_desktop),
NULL, NULL,
g_cclosure_marshal_VOID__POINTER,
G_TYPE_NONE, 1,
@@ -272,28 +238,28 @@ inkscape_class_init (Inkscape::ApplicationClass * klass)
inkscape_signals[SHUTDOWN_SIGNAL] = g_signal_new ("shut_down",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_FIRST,
- G_STRUCT_OFFSET (Inkscape::ApplicationClass, shut_down),
+ G_STRUCT_OFFSET (InkscapeApplicationClass, shut_down),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
inkscape_signals[DIALOGS_HIDE] = g_signal_new ("dialogs_hide",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_FIRST,
- G_STRUCT_OFFSET (Inkscape::ApplicationClass, dialogs_hide),
+ G_STRUCT_OFFSET (InkscapeApplicationClass, dialogs_hide),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
inkscape_signals[DIALOGS_UNHIDE] = g_signal_new ("dialogs_unhide",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_FIRST,
- G_STRUCT_OFFSET (Inkscape::ApplicationClass, dialogs_unhide),
+ G_STRUCT_OFFSET (InkscapeApplicationClass, dialogs_unhide),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
inkscape_signals[EXTERNAL_CHANGE] = g_signal_new ("external_change",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_FIRST,
- G_STRUCT_OFFSET (Inkscape::ApplicationClass, external_change),
+ G_STRUCT_OFFSET (InkscapeApplicationClass, external_change),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
@@ -494,10 +460,10 @@ void inkscape_autosave_init()
static void
-inkscape_init (SPObject * object)
+inkscape_init (InkscapeApplication * object)
{
if (!inkscape) {
- inkscape = (Inkscape::Application *) object;
+ inkscape = (InkscapeApplication *) object;
} else {
g_assert_not_reached ();
}
@@ -515,7 +481,7 @@ inkscape_init (SPObject * object)
static void
inkscape_dispose (GObject *object)
{
- Inkscape::Application *inkscape = (Inkscape::Application *) object;
+ InkscapeApplication *inkscape = (InkscapeApplication *) object;
g_assert (!inkscape->desktops);
@@ -530,7 +496,7 @@ inkscape_dispose (GObject *object)
inkscape->selection_models.~map();
inkscape->document_set.~map();
- G_OBJECT_CLASS (parent_class)->dispose (object);
+ G_OBJECT_CLASS (inkscape_parent_class)->dispose (object);
gtk_main_quit ();
}
@@ -580,14 +546,14 @@ void inkscape_trackalt(guint trackvalue)
static void
-inkscape_activate_desktop_private (Inkscape::Application */*inkscape*/, SPDesktop *desktop)
+inkscape_activate_desktop_private (InkscapeApplication */*inkscape*/, SPDesktop *desktop)
{
desktop->set_active (true);
}
static void
-inkscape_deactivate_desktop_private (Inkscape::Application */*inkscape*/, SPDesktop *desktop)
+inkscape_deactivate_desktop_private (InkscapeApplication */*inkscape*/, SPDesktop *desktop)
{
desktop->set_active (false);
}
@@ -835,7 +801,7 @@ private:
void
inkscape_application_init (const gchar *argv0, gboolean use_gui)
{
- inkscape = (Inkscape::Application *)g_object_new (SP_TYPE_INKSCAPE, NULL);
+ inkscape = (InkscapeApplication *)g_object_new (SP_TYPE_INKSCAPE, NULL);
/* fixme: load application defaults */
segv_handler = signal (SIGSEGV, inkscape_crash_handler);
@@ -904,9 +870,9 @@ inkscape_application_init (const gchar *argv0, gboolean use_gui)
}
/**
- * Returns the current Inkscape::Application global object
+ * Returns the current InkscapeApplication global object
*/
-Inkscape::Application *
+InkscapeApplication *
inkscape_get_instance()
{
return inkscape;
@@ -921,7 +887,7 @@ gboolean inkscape_use_gui()
* Menus management
*
*/
-bool inkscape_load_menus( Inkscape::Application * inkscape )
+bool inkscape_load_menus( InkscapeApplication * inkscape )
{
gchar *fn = profile_path(MENUS_FILE);
gchar *menus_xml = 0;
@@ -945,7 +911,7 @@ bool inkscape_load_menus( Inkscape::Application * inkscape )
inkscape->menus = sp_repr_read_mem(menus_skeleton, MENUS_SKELETON_SIZE, NULL);
}
- return (inkscape->menus != 0);
+ return (inkscape->menus != NULL);
}
@@ -1391,7 +1357,7 @@ inkscape_action_context_for_document(SPDocument *doc)
#####################*/
void
-inkscape_refresh_display (Inkscape::Application *inkscape)
+inkscape_refresh_display (InkscapeApplication *inkscape)
{
for (GSList *l = inkscape->desktops; l != NULL; l = l->next) {
(static_cast<Inkscape::UI::View::View*>(l->data))->requestRedraw();
@@ -1404,7 +1370,7 @@ inkscape_refresh_display (Inkscape::Application *inkscape)
* saves the preferences if appropriate, and quits.
*/
void
-inkscape_exit (Inkscape::Application */*inkscape*/)
+inkscape_exit (InkscapeApplication */*inkscape*/)
{
g_assert (INKSCAPE);
@@ -1445,6 +1411,11 @@ profile_path(const char *filename)
if (val) {
prefdir = g_strdup(val);
}
+ // Then check for a custom user environment variable
+ gchar const *userenv = g_getenv("INKSCAPE_PROFILE_DIR");
+ if (userenv) {
+ prefdir = g_strdup(userenv);
+ }
#ifdef HAS_SHGetSpecialFolderLocation
// prefer c:\Documents and Settings\UserName\Application Data\ to
@@ -1541,7 +1512,7 @@ profile_path(const char *filename)
}
Inkscape::XML::Node *
-inkscape_get_menus (Inkscape::Application * inkscape)
+inkscape_get_menus (InkscapeApplication * inkscape)
{
Inkscape::XML::Node *repr = inkscape->menus->root();
g_assert (!(strcmp (repr->name(), "inkscape")));
diff --git a/src/inkscape.h b/src/inkscape.h
index 823e7524f..3a9b85fc9 100644
--- a/src/inkscape.h
+++ b/src/inkscape.h
@@ -28,9 +28,10 @@ class ToolBase;
}
}
+struct InkscapeApplication;
+
namespace Inkscape {
class ActionContext;
- struct Application;
namespace XML {
class Node;
struct Document;
@@ -46,11 +47,11 @@ void inkscape_application_init (const gchar *argv0, gboolean use_gui);
bool inkscape_load_config (const gchar *filename, Inkscape::XML::Document *config, const gchar *skeleton, unsigned int skel_size, const gchar *e_notreg, const gchar *e_notxml, const gchar *e_notsp, const gchar *warn);
/* Menus */
-bool inkscape_load_menus (Inkscape::Application * inkscape);
-bool inkscape_save_menus (Inkscape::Application * inkscape);
-Inkscape::XML::Node *inkscape_get_menus (Inkscape::Application * inkscape);
+bool inkscape_load_menus (InkscapeApplication * inkscape);
+bool inkscape_save_menus (InkscapeApplication * inkscape);
+Inkscape::XML::Node *inkscape_get_menus (InkscapeApplication * inkscape);
-Inkscape::Application *inkscape_get_instance();
+InkscapeApplication *inkscape_get_instance();
gboolean inkscape_use_gui();
bool inkscapeIsCrashing();
@@ -108,13 +109,13 @@ bool inkscape_remove_document (SPDocument *document);
* fixme: This has to be rethought
*/
-void inkscape_refresh_display (Inkscape::Application *inkscape);
+void inkscape_refresh_display (InkscapeApplication *inkscape);
/*
* fixme: This also
*/
-void inkscape_exit (Inkscape::Application *inkscape);
+void inkscape_exit (InkscapeApplication *inkscape);
#endif
diff --git a/src/inkscape.rc b/src/inkscape.rc
index efa360c8d..92d38f60e 100644
--- a/src/inkscape.rc
+++ b/src/inkscape.rc
@@ -3,8 +3,8 @@ APPLICATION_ICON ICON DISCARDABLE "../inkscape.ico"
1 24 DISCARDABLE "./inkscape-manifest.xml"
1 VERSIONINFO
- FILEVERSION 0,48,0,9
- PRODUCTVERSION 0,48,0,9
+ FILEVERSION 0,91,0,9
+ PRODUCTVERSION 0,91,0,9
BEGIN
BLOCK "StringFileInfo"
BEGIN
@@ -13,11 +13,11 @@ BEGIN
VALUE "Comments", "Published under the GNU GPL"
VALUE "CompanyName", "inkscape.org"
VALUE "FileDescription", "Inkscape"
- VALUE "FileVersion", "0.48+devel"
+ VALUE "FileVersion", "0.91+devel"
VALUE "InternalName", "Inkscape"
- VALUE "LegalCopyright", "© 2012 Inkscape"
+ VALUE "LegalCopyright", "© 2014 Inkscape"
VALUE "ProductName", "Inkscape"
- VALUE "ProductVersion", "0.48+devel"
+ VALUE "ProductVersion", "0.91+devel"
END
END
BLOCK "VarFileInfo"
diff --git a/src/inkview-manifest-x64.xml b/src/inkview-manifest-x64.xml
new file mode 100644
index 000000000..38526cfe6
--- /dev/null
+++ b/src/inkview-manifest-x64.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+<dependency>
+<dependentAssembly>
+<assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls"
+ version="6.0.0.0" processorArchitecture="amd64"
+ publicKeyToken="6595b64144ccf1df" language="*"/>
+</dependentAssembly>
+</dependency>
+</assembly> \ No newline at end of file
diff --git a/src/inkview-x64.rc b/src/inkview-x64.rc
new file mode 100644
index 000000000..1b7287993
--- /dev/null
+++ b/src/inkview-x64.rc
@@ -0,0 +1,29 @@
+
+APPLICATION_ICON ICON DISCARDABLE "../inkscape.ico"
+1 24 DISCARDABLE "./inkview-manifest-x64.xml"
+
+1 VERSIONINFO
+ FILEVERSION 0,91,0,9
+ PRODUCTVERSION 0,91,0,9
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040901b5"
+ BEGIN
+ VALUE "Comments", "Published under the GNU GPL"
+ VALUE "CompanyName", "inkscape.org"
+ VALUE "FileDescription", "Inkview"
+ VALUE "FileVersion", "0.91+devel"
+ VALUE "InternalName", "Inkview"
+ VALUE "LegalCopyright", "© 2014 Inkscape"
+ VALUE "ProductName", "Inkview"
+ VALUE "ProductVersion", "0.91+devel"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 1033, 437
+ END
+END
+
+1000 BITMAP "./show-preview.bmp"
diff --git a/src/inkview.cpp b/src/inkview.cpp
index 82bd08e34..2969bb140 100644
--- a/src/inkview.cpp
+++ b/src/inkview.cpp
@@ -62,7 +62,7 @@
#include "inkscape-private.h"
-Inkscape::Application *inkscape;
+InkscapeApplication *inkscape;
#include <iostream>
@@ -232,7 +232,7 @@ main (int argc, const char **argv)
ss.view = NULL;
ss.fullscreen = false;
- inkscape = (Inkscape::Application *)g_object_new (SP_TYPE_INKSCAPE, NULL);
+ inkscape = (InkscapeApplication *)g_object_new (SP_TYPE_INKSCAPE, NULL);
// starting at where the commandline options stopped parsing because
// we want all the files to be in the list
@@ -570,16 +570,6 @@ static void usage()
exit(1);
}
-#ifdef XXX
-/* TODO !!! make this temporary stub unnecessary */
-Inkscape::Application *inkscape_get_instance() { return NULL; }
-void inkscape_ref (void) {}
-void inkscape_unref (void) {}
-void inkscape_add_document (SPDocument *document) {}
-void inkscape_remove_document (SPDocument *document) {}
-#endif
-
-
/*
Local Variables:
mode:c++
diff --git a/src/inkview.rc b/src/inkview.rc
index f1fa92247..326b0873a 100644
--- a/src/inkview.rc
+++ b/src/inkview.rc
@@ -3,8 +3,8 @@ APPLICATION_ICON ICON DISCARDABLE "../inkscape.ico"
1 24 DISCARDABLE "./inkview-manifest.xml"
1 VERSIONINFO
- FILEVERSION 0,48,0,9
- PRODUCTVERSION 0,48,0,9
+ FILEVERSION 0,91,0,9
+ PRODUCTVERSION 0,91,0,9
BEGIN
BLOCK "StringFileInfo"
BEGIN
@@ -13,11 +13,11 @@ BEGIN
VALUE "Comments", "Published under the GNU GPL"
VALUE "CompanyName", "inkscape.org"
VALUE "FileDescription", "Inkview"
- VALUE "FileVersion", "0.48+devel"
+ VALUE "FileVersion", "0.91+devel"
VALUE "InternalName", "Inkview"
- VALUE "LegalCopyright", "© 2012 Inkscape"
+ VALUE "LegalCopyright", "© 2014 Inkscape"
VALUE "ProductName", "Inkview"
- VALUE "ProductVersion", "0.48+devel"
+ VALUE "ProductVersion", "0.91+devel"
END
END
BLOCK "VarFileInfo"
diff --git a/src/isinf.h b/src/isinf.h
index b4c56f79d..8d590b972 100644
--- a/src/isinf.h
+++ b/src/isinf.h
@@ -2,7 +2,7 @@
#define __ISINF_H__
/*
- * Fix for missing std::isnormal with SOLARIS8/GCC3.2
+ * Fix for missing std::isinf with SOLARIS8/GCC3.2
*/
#if defined (SOLARIS)
diff --git a/src/isnormal.h b/src/isnormal.h
deleted file mode 100644
index d53105926..000000000
--- a/src/isnormal.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef __ISNORMAL_H__
-#define __ISNORMAL_H__
-
-/*
- * Fix for missing std::isnormal with SOLARIS8/GCC3.2
- */
-
-#if defined (SOLARIS)
-
- #include <ieeefp.h>
- #define isnormal(x) (fpclass(x) >= FP_NZERO)
-
-#else
-
- using std::isnormal;
-
-#endif
-
-#endif /* __ISNORMAL_H__ */
diff --git a/src/knot-holder-entity.cpp b/src/knot-holder-entity.cpp
index 6471124ec..b66156b09 100644
--- a/src/knot-holder-entity.cpp
+++ b/src/knot-holder-entity.cpp
@@ -80,13 +80,17 @@ KnotHolderEntity::~KnotHolderEntity()
void
KnotHolderEntity::update_knot()
{
- Geom::Affine const i2dt(item->i2dt_affine());
+ Geom::Point knot_pos(knot_get());
+ if (knot_pos.isFinite()) {
+ Geom::Point dp(knot_pos * item->i2dt_affine());
- Geom::Point dp(knot_get() * i2dt);
-
- _moved_connection.block();
- knot->setPosition(dp, SP_KNOT_STATE_NORMAL);
- _moved_connection.unblock();
+ _moved_connection.block();
+ knot->setPosition(dp, SP_KNOT_STATE_NORMAL);
+ _moved_connection.unblock();
+ } else {
+ // knot coords are non-finite, hide knot
+ knot->hide();
+ }
}
Geom::Point
@@ -154,7 +158,7 @@ static Geom::Point sp_pattern_extract_trans(SPPattern const *pat)
void
PatternKnotHolderEntityXY::knot_set(Geom::Point const &p, Geom::Point const &origin, guint state)
{
- SPPattern *pat = SP_PATTERN(SP_STYLE_FILL_SERVER(SP_OBJECT(item)->style));
+ SPPattern *pat = _fill ? SP_PATTERN(item->style->getFillPaintServer()) : SP_PATTERN(item->style->getStrokePaintServer());
// FIXME: this snapping should be done together with knowing whether control was pressed. If GDK_CONTROL_MASK, then constrained snapping should be used.
Geom::Point p_snapped = snap_knot_position(p, state);
@@ -169,7 +173,7 @@ PatternKnotHolderEntityXY::knot_set(Geom::Point const &p, Geom::Point const &ori
if (state) {
Geom::Point const q = p_snapped - sp_pattern_extract_trans(pat);
- item->adjust_pattern(Geom::Affine(Geom::Translate(q)));
+ item->adjust_pattern(Geom::Translate(q), false, _fill ? TRANSFORM_FILL : TRANSFORM_STROKE);
}
item->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
@@ -178,14 +182,14 @@ PatternKnotHolderEntityXY::knot_set(Geom::Point const &p, Geom::Point const &ori
Geom::Point
PatternKnotHolderEntityXY::knot_get() const
{
- SPPattern const *pat = SP_PATTERN(SP_STYLE_FILL_SERVER(SP_OBJECT(item)->style));
+ SPPattern *pat = _fill ? SP_PATTERN(item->style->getFillPaintServer()) : SP_PATTERN(item->style->getStrokePaintServer());
return sp_pattern_extract_trans(pat);
}
Geom::Point
PatternKnotHolderEntityAngle::knot_get() const
{
- SPPattern const *pat = SP_PATTERN(SP_STYLE_FILL_SERVER(SP_OBJECT(item)->style));
+ SPPattern *pat = _fill ? SP_PATTERN(item->style->getFillPaintServer()) : SP_PATTERN(item->style->getStrokePaintServer());
gdouble x = pattern_width(pat);
gdouble y = 0;
@@ -203,7 +207,7 @@ PatternKnotHolderEntityAngle::knot_set(Geom::Point const &p, Geom::Point const &
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
int const snaps = prefs->getInt("/options/rotationsnapsperpi/value", 12);
- SPPattern *pat = SP_PATTERN(SP_STYLE_FILL_SERVER(SP_OBJECT(item)->style));
+ SPPattern *pat = _fill ? SP_PATTERN(item->style->getFillPaintServer()) : SP_PATTERN(item->style->getStrokePaintServer());
// get the angle from pattern 0,0 to the cursor pos
Geom::Point delta = p - sp_pattern_extract_trans(pat);
@@ -219,14 +223,14 @@ PatternKnotHolderEntityAngle::knot_set(Geom::Point const &p, Geom::Point const &
Geom::Point const t = sp_pattern_extract_trans(pat);
rot[4] = t[Geom::X];
rot[5] = t[Geom::Y];
- item->adjust_pattern(rot, true);
+ item->adjust_pattern(rot, true, _fill ? TRANSFORM_FILL : TRANSFORM_STROKE);
item->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
}
void
PatternKnotHolderEntityScale::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, guint state)
{
- SPPattern *pat = SP_PATTERN(SP_STYLE_FILL_SERVER(SP_OBJECT(item)->style));
+ SPPattern *pat = _fill ? SP_PATTERN(item->style->getFillPaintServer()) : SP_PATTERN(item->style->getStrokePaintServer());
// FIXME: this snapping should be done together with knowing whether control was pressed. If GDK_CONTROL_MASK, then constrained snapping should be used.
Geom::Point p_snapped = snap_knot_position(p, state);
@@ -253,7 +257,7 @@ PatternKnotHolderEntityScale::knot_set(Geom::Point const &p, Geom::Point const &
Geom::Point const t = sp_pattern_extract_trans(pat);
rot[4] = t[Geom::X];
rot[5] = t[Geom::Y];
- item->adjust_pattern(rot, true);
+ item->adjust_pattern(rot, true, _fill ? TRANSFORM_FILL : TRANSFORM_STROKE);
item->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
}
@@ -261,7 +265,7 @@ PatternKnotHolderEntityScale::knot_set(Geom::Point const &p, Geom::Point const &
Geom::Point
PatternKnotHolderEntityScale::knot_get() const
{
- SPPattern const *pat = SP_PATTERN(SP_STYLE_FILL_SERVER(SP_OBJECT(item)->style));
+ SPPattern *pat = _fill ? SP_PATTERN(item->style->getFillPaintServer()) : SP_PATTERN(item->style->getStrokePaintServer());
gdouble x = pattern_width(pat);
gdouble y = pattern_height(pat);
diff --git a/src/knot-holder-entity.h b/src/knot-holder-entity.h
index a9268d396..43ab25e5c 100644
--- a/src/knot-holder-entity.h
+++ b/src/knot-holder-entity.h
@@ -14,11 +14,11 @@
* Released under GNU GPL
*/
-#include <glib.h>
-#include "knot.h"
#include <2geom/forward.h>
-#include "snapper.h"
+
#include "display/sp-canvas-item.h"
+#include "knot.h"
+#include "snapper.h"
class SPItem;
class SPKnot;
@@ -31,7 +31,7 @@ namespace LivePathEffect {
} // namespace LivePathEffect
} // namespace Inkscape
-typedef void (* SPKnotHolderSetFunc) (SPItem *item, Geom::Point const &p, Geom::Point const &origin, guint state);
+typedef void (* SPKnotHolderSetFunc) (SPItem *item, Geom::Point const &p, Geom::Point const &origin, unsigned int state);
typedef Geom::Point (* SPKnotHolderGetFunc) (SPItem *item);
/**
@@ -50,22 +50,22 @@ public:
virtual void create(SPDesktop *desktop, SPItem *item, KnotHolder *parent,
Inkscape::ControlType type = Inkscape::CTRL_TYPE_UNKNOWN,
- const gchar *tip = "",
+ char const*tip = "",
SPKnotShapeType shape = SP_KNOT_SHAPE_DIAMOND,
SPKnotModeType mode = SP_KNOT_MODE_XOR,
guint32 color = 0xffffff00);
/* the get/set/click handlers are virtual functions; each handler class for a knot
should be derived from KnotHolderEntity and override these functions */
- virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state) = 0;
+ virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state) = 0;
virtual Geom::Point knot_get() const = 0;
- virtual void knot_click(guint /*state*/) {}
+ virtual void knot_click(unsigned int /*state*/) {}
void update_knot();
//private:
- Geom::Point snap_knot_position(Geom::Point const &p, guint state);
- Geom::Point snap_knot_position_constrained(Geom::Point const &p, Inkscape::Snapper::SnapConstraint const &constraint, guint state);
+ Geom::Point snap_knot_position(Geom::Point const &p, unsigned int state);
+ Geom::Point snap_knot_position_constrained(Geom::Point const &p, Inkscape::Snapper::SnapConstraint const &constraint, unsigned int state);
SPKnot *knot;
SPItem *item;
@@ -77,11 +77,11 @@ public:
static int counter;
/** Connection to \a knot's "moved" signal. */
- guint handler_id;
+ unsigned int handler_id;
/** Connection to \a knot's "clicked" signal. */
- guint _click_handler_id;
+ unsigned int _click_handler_id;
/** Connection to \a knot's "ungrabbed" signal. */
- guint _ungrab_handler_id;
+ unsigned int _ungrab_handler_id;
private:
sigc::connection _moved_connection;
@@ -101,20 +101,30 @@ protected:
class PatternKnotHolderEntityXY : public KnotHolderEntity {
public:
+ PatternKnotHolderEntityXY(bool fill) : KnotHolderEntity(), _fill(fill) {}
virtual Geom::Point knot_get() const;
- virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state);
+ virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state);
+private:
+ // true if the entity tracks fill, false for stroke
+ bool _fill;
};
class PatternKnotHolderEntityAngle : public KnotHolderEntity {
public:
+ PatternKnotHolderEntityAngle(bool fill) : KnotHolderEntity(), _fill(fill) {}
virtual Geom::Point knot_get() const;
- virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state);
+ virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state);
+private:
+ bool _fill;
};
class PatternKnotHolderEntityScale : public KnotHolderEntity {
public:
+ PatternKnotHolderEntityScale(bool fill) : KnotHolderEntity(), _fill(fill) {}
virtual Geom::Point knot_get() const;
- virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state);
+ virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state);
+private:
+ bool _fill;
};
#endif /* !SEEN_KNOT_HOLDER_ENTITY_H */
diff --git a/src/knot-ptr.cpp b/src/knot-ptr.cpp
new file mode 100644
index 000000000..de8118ba7
--- /dev/null
+++ b/src/knot-ptr.cpp
@@ -0,0 +1,25 @@
+#include <algorithm>
+#include <glib.h>
+#include <list>
+#include "knot-ptr.h"
+
+static std::list<void*> deleted_knots;
+
+void knot_deleted_callback(void* knot) {
+ if (std::find(deleted_knots.begin(), deleted_knots.end(), knot) == deleted_knots.end()) {
+ deleted_knots.push_back(knot);
+ }
+}
+
+void knot_created_callback(void* knot) {
+ std::list<void*>::iterator it = std::find(deleted_knots.begin(), deleted_knots.end(), knot);
+ if (it != deleted_knots.end()) {
+ deleted_knots.erase(it);
+ }
+}
+
+void check_if_knot_deleted(void* knot) {
+ if (std::find(deleted_knots.begin(), deleted_knots.end(), knot) != deleted_knots.end()) {
+ g_warning("Accessed knot after it was freed at %p", knot);
+ }
+}
diff --git a/src/knot-ptr.h b/src/knot-ptr.h
new file mode 100644
index 000000000..5895dfd2e
--- /dev/null
+++ b/src/knot-ptr.h
@@ -0,0 +1,8 @@
+#ifndef KNOT_PTR_DETECTOR
+#define KNOT_PTR_DETECTOR
+
+void knot_deleted_callback(void* knot);
+void knot_created_callback(void* knot);
+void check_if_knot_deleted(void* knot);
+
+#endif
diff --git a/src/knot.cpp b/src/knot.cpp
index 61d0dff39..4118873c1 100644
--- a/src/knot.cpp
+++ b/src/knot.cpp
@@ -21,12 +21,16 @@
#include "desktop.h"
#include "desktop-handles.h"
#include "knot.h"
+#include "knot-ptr.h"
#include "document.h"
#include "document-undo.h"
#include "preferences.h"
#include "message-stack.h"
#include "message-context.h"
+#include "ui/tools-switch.h"
#include "ui/tools/tool-base.h"
+#include "ui/tools/node-tool.h"
+#include <gtk/gtk.h>
using Inkscape::DocumentUndo;
@@ -118,6 +122,7 @@ SPKnot::SPKnot(SPDesktop *desktop, gchar const *tip)
this->_event_handler_id = g_signal_connect(G_OBJECT(this->item), "event",
G_CALLBACK(sp_knot_handler), this);
+ knot_created_callback(this);
}
SPKnot::~SPKnot() {
@@ -162,6 +167,10 @@ SPKnot::~SPKnot() {
g_free(this->tip);
this->tip = NULL;
}
+
+ // FIXME: cannot snap to destroyed knot (lp:1309050)
+ //sp_event_context_discard_delayed_snap_event(this->desktop->event_context);
+ knot_deleted_callback(this);
}
void SPKnot::startDragging(Geom::Point const &p, gint x, gint y, guint32 etime) {
@@ -254,6 +263,10 @@ static int sp_knot_handler(SPCanvasItem */*item*/, GdkEvent *event, SPKnot *knot
consumed = TRUE;
}
}
+ if (tools_isactive(knot->desktop, TOOLS_NODES)) {
+ Inkscape::UI::Tools::NodeTool *nt = static_cast<Inkscape::UI::Tools::NodeTool*>(knot->desktop->event_context);
+ nt->update_helperpath();
+ }
break;
case GDK_MOTION_NOTIFY:
if (grabbed && knot->desktop && knot->desktop->event_context && !knot->desktop->event_context->space_panning) {
@@ -282,10 +295,14 @@ static int sp_knot_handler(SPCanvasItem */*item*/, GdkEvent *event, SPKnot *knot
knot->setFlag(SP_KNOT_DRAGGING, TRUE);
}
- sp_event_context_snap_delay_handler(knot->desktop->event_context, NULL, (gpointer) knot, (GdkEventMotion *)event, Inkscape::UI::Tools::DelayedSnapEvent::KNOT_HANDLER);
+ sp_event_context_snap_delay_handler(knot->desktop->event_context, NULL, knot, (GdkEventMotion *)event, Inkscape::UI::Tools::DelayedSnapEvent::KNOT_HANDLER);
sp_knot_handler_request_position(event, knot);
moved = TRUE;
}
+ if (tools_isactive(knot->desktop, TOOLS_NODES)) {
+ Inkscape::UI::Tools::NodeTool *nt = static_cast<Inkscape::UI::Tools::NodeTool*>(knot->desktop->event_context);
+ nt->update_helperpath();
+ }
break;
case GDK_ENTER_NOTIFY:
knot->setFlag(SP_KNOT_MOUSEOVER, TRUE);
diff --git a/src/knot.h b/src/knot.h
index b18f89566..e3ad98e66 100644
--- a/src/knot.h
+++ b/src/knot.h
@@ -14,18 +14,20 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include <gdk/gdk.h>
#include <2geom/point.h>
-#include "knot-enums.h"
-#include <stddef.h>
#include <sigc++/sigc++.h>
+
+#include "knot-enums.h"
#include "enums.h"
-#include <gtk/gtk.h>
-#include "sp-item.h"
class SPDesktop;
+class SPItem;
struct SPCanvasItem;
+typedef struct _GdkCursor GdkCursor;
+typedef union _GdkEvent GdkEvent;
+typedef unsigned int guint32;
+
#define SP_KNOT(obj) (dynamic_cast<SPKnot*>(static_cast<SPKnot*>(obj)))
#define SP_IS_KNOT(obj) (dynamic_cast<const SPKnot*>(static_cast<const SPKnot*>(obj)) != NULL)
@@ -38,19 +40,17 @@ struct SPCanvasItem;
*/
class SPKnot {
public:
- SPKnot(SPDesktop *desktop, gchar const *tip);
+ SPKnot(SPDesktop *desktop, char const *tip);
virtual ~SPKnot();
-
- int ref_count;
-
+ int ref_count; // FIXME encapsulation
SPDesktop *desktop; /**< Desktop we are on. */
SPCanvasItem *item; /**< Our CanvasItem. */
SPItem *owner; /**< Optional Owner Item */
- guint flags;
+ unsigned int flags;
- guint size; /**< Always square. */
+ unsigned int size; /**< Always square. */
Geom::Point pos; /**< Our desktop coordinates. */
Geom::Point grabbed_rel_pos; /**< Grabbed relative position. */
Geom::Point drag_origin; /**< Origin of drag. */
@@ -61,39 +61,41 @@ public:
guint32 fill[SP_KNOT_VISIBLE_STATES];
guint32 stroke[SP_KNOT_VISIBLE_STATES];
- guchar *image[SP_KNOT_VISIBLE_STATES];
+ unsigned char *image[SP_KNOT_VISIBLE_STATES];
GdkCursor *cursor[SP_KNOT_VISIBLE_STATES];
GdkCursor *saved_cursor;
- gpointer pixbuf;
+ void* pixbuf;
- gchar *tip;
+ char *tip;
- gulong _event_handler_id;
+ unsigned long _event_handler_id;
double pressure; /**< The tablet pen pressure when the knot is being dragged. */
- sigc::signal<void, SPKnot *, guint> click_signal;
- sigc::signal<void, SPKnot*, guint> doubleclicked_signal;
- sigc::signal<void, SPKnot*, guint> grabbed_signal;
- sigc::signal<void, SPKnot *, guint> ungrabbed_signal;
- sigc::signal<void, SPKnot *, Geom::Point const &, guint> moved_signal;
+ // FIXME: signals should NOT need to emit the object they came from, the callee should
+ // be able to figure that out
+ sigc::signal<void, SPKnot *, unsigned int> click_signal;
+ sigc::signal<void, SPKnot*, unsigned int> doubleclicked_signal;
+ sigc::signal<void, SPKnot*, unsigned int> grabbed_signal;
+ sigc::signal<void, SPKnot *, unsigned int> ungrabbed_signal;
+ sigc::signal<void, SPKnot *, Geom::Point const &, unsigned int> moved_signal;
sigc::signal<bool, SPKnot*, GdkEvent*> event_signal;
- sigc::signal<bool, SPKnot*, Geom::Point*, guint> request_signal;
+ sigc::signal<bool, SPKnot*, Geom::Point*, unsigned int> request_signal;
//TODO: all the members above should eventualle become private, accessible via setters/getters
- void setSize(guint i);
- void setShape(guint i);
- void setAnchor(guint i);
- void setMode(guint i);
- void setPixbuf(gpointer p);
+ void setSize(unsigned int i);
+ void setShape(unsigned int i);
+ void setAnchor(unsigned int i);
+ void setMode(unsigned int i);
+ void setPixbuf(void* p);
void setFill(guint32 normal, guint32 mouseover, guint32 dragging);
void setStroke(guint32 normal, guint32 mouseover, guint32 dragging);
- void setImage(guchar* normal, guchar* mouseover, guchar* dragging);
+ void setImage(unsigned char* normal, unsigned char* mouseover, unsigned char* dragging);
void setCursor(GdkCursor* normal, GdkCursor* mouseover, GdkCursor* dragging);
@@ -110,7 +112,7 @@ public:
/**
* Set flag in knot, with side effects.
*/
- void setFlag(guint flag, bool set);
+ void setFlag(unsigned int flag, bool set);
/**
* Update knot's pixbuf and set its control state.
@@ -120,17 +122,17 @@ public:
/**
* Request or set new position for knot.
*/
- void requestPosition(Geom::Point const &pos, guint state);
+ void requestPosition(Geom::Point const &pos, unsigned int state);
/**
* Update knot for dragging and tell canvas an item was grabbed.
*/
- void startDragging(Geom::Point const &p, gint x, gint y, guint32 etime);
+ void startDragging(Geom::Point const &p, int x, int y, guint32 etime);
/**
* Move knot to new position and emits "moved" signal.
*/
- void setPosition(Geom::Point const &p, guint state);
+ void setPosition(Geom::Point const &p, unsigned int state);
/**
* Move knot to new position, without emitting a MOVED signal.
diff --git a/src/knotholder.cpp b/src/knotholder.cpp
index cf87423d4..f46daa09e 100644
--- a/src/knotholder.cpp
+++ b/src/knotholder.cpp
@@ -6,6 +6,7 @@
* bulia byak <buliabyak@users.sf.net>
* Maximilian Albert <maximilian.albert@gmail.com>
* Abhishek Sharma
+ * Jon A. Cruz <jon@joncruz.org>
*
* Copyright (C) 2001-2008 authors
*
@@ -58,8 +59,7 @@ KnotHolder::KnotHolder(SPDesktop *desktop, SPItem *item, SPKnotHolderReleasedFun
local_change(FALSE),
dragging(false)
{
-
- if (!desktop || !item || !SP_IS_ITEM(item)) {
+ if (!desktop || !item) {
g_print ("Error! Throw an exception, please!\n");
}
@@ -128,34 +128,49 @@ KnotHolder::knot_clicked_handler(SPKnot *knot, guint state)
}
}
- if (SP_IS_SHAPE(saved_item)) {
- SP_SHAPE(saved_item)->set_shape();
+ {
+ SPShape *savedShape = dynamic_cast<SPShape *>(saved_item);
+ if (savedShape) {
+ savedShape->set_shape();
+ }
}
knot_holder->update_knots();
unsigned int object_verb = SP_VERB_NONE;
- if (SP_IS_RECT(saved_item))
+ // TODO extract duplicated blocks;
+ if (dynamic_cast<SPRect *>(saved_item)) {
object_verb = SP_VERB_CONTEXT_RECT;
- else if (SP_IS_BOX3D(saved_item))
+ } else if (dynamic_cast<SPBox3D *>(saved_item)) {
object_verb = SP_VERB_CONTEXT_3DBOX;
- else if (SP_IS_GENERICELLIPSE(saved_item))
+ } else if (dynamic_cast<SPGenericEllipse *>(saved_item)) {
object_verb = SP_VERB_CONTEXT_ARC;
- else if (SP_IS_STAR(saved_item))
+ } else if (dynamic_cast<SPStar *>(saved_item)) {
object_verb = SP_VERB_CONTEXT_STAR;
- else if (SP_IS_SPIRAL(saved_item))
+ } else if (dynamic_cast<SPSpiral *>(saved_item)) {
object_verb = SP_VERB_CONTEXT_SPIRAL;
- else if (SP_IS_OFFSET(saved_item)) {
- if (SP_OFFSET(saved_item)->sourceHref)
- object_verb = SP_VERB_SELECTION_LINKED_OFFSET;
- else
- object_verb = SP_VERB_SELECTION_DYNAMIC_OFFSET;
+ } else {
+ SPOffset *offset = dynamic_cast<SPOffset *>(saved_item);
+ if (offset) {
+ if (offset->sourceHref) {
+ object_verb = SP_VERB_SELECTION_LINKED_OFFSET;
+ } else {
+ object_verb = SP_VERB_SELECTION_DYNAMIC_OFFSET;
+ }
+ }
}
// for drag, this is done by ungrabbed_handler, but for click we must do it here
- DocumentUndo::done(saved_item->document, object_verb,
- _("Change handle"));
+
+ if (saved_item) { //increasingly aggressive sanity checks
+ if (saved_item->document) {
+ if (object_verb <= SP_VERB_LAST && object_verb >= SP_VERB_INVALID) {
+ DocumentUndo::done(saved_item->document, object_verb,
+ _("Change handle"));
+ }
+ }
+ } // else { abort(); }
}
void
@@ -177,8 +192,9 @@ KnotHolder::knot_moved_handler(SPKnot *knot, Geom::Point const &p, guint state)
}
}
- if (SP_IS_SHAPE (item)) {
- SP_SHAPE (item)->set_shape();
+ SPShape *shape = dynamic_cast<SPShape *>(item);
+ if (shape) {
+ shape->set_shape();
}
this->update_knots();
@@ -203,11 +219,11 @@ KnotHolder::knot_ungrabbed_handler(SPKnot */*knot*/, guint)
/* do cleanup tasks (e.g., for LPE items write the parameter values
* that were changed by dragging the handle to SVG)
*/
- if (SP_IS_LPE_ITEM(object)) {
+ SPLPEItem *lpeItem = dynamic_cast<SPLPEItem *>(object);
+ if (lpeItem) {
// This writes all parameters to SVG. Is this sufficiently efficient or should we only
// write the ones that were changed?
-
- Inkscape::LivePathEffect::Effect *lpe = SP_LPE_ITEM(object)->getCurrentLPE();
+ Inkscape::LivePathEffect::Effect *lpe = lpeItem->getCurrentLPE();
if (lpe) {
LivePathEffectObject *lpeobj = lpe->getLPEObj();
lpeobj->updateRepr();
@@ -216,25 +232,29 @@ KnotHolder::knot_ungrabbed_handler(SPKnot */*knot*/, guint)
unsigned int object_verb = SP_VERB_NONE;
- if (SP_IS_RECT(object))
+ // TODO extract duplicated blocks:
+ if (dynamic_cast<SPRect *>(object)) {
object_verb = SP_VERB_CONTEXT_RECT;
- else if (SP_IS_BOX3D(object))
+ } else if (dynamic_cast<SPBox3D *>(object)) {
object_verb = SP_VERB_CONTEXT_3DBOX;
- else if (SP_IS_GENERICELLIPSE(object))
+ } else if (dynamic_cast<SPGenericEllipse *>(object)) {
object_verb = SP_VERB_CONTEXT_ARC;
- else if (SP_IS_STAR(object))
+ } else if (dynamic_cast<SPStar *>(object)) {
object_verb = SP_VERB_CONTEXT_STAR;
- else if (SP_IS_SPIRAL(object))
+ } else if (dynamic_cast<SPSpiral *>(object)) {
object_verb = SP_VERB_CONTEXT_SPIRAL;
- else if (SP_IS_OFFSET(object)) {
- if (SP_OFFSET(object)->sourceHref)
- object_verb = SP_VERB_SELECTION_LINKED_OFFSET;
- else
- object_verb = SP_VERB_SELECTION_DYNAMIC_OFFSET;
+ } else {
+ SPOffset *offset = dynamic_cast<SPOffset *>(object);
+ if (offset) {
+ if (offset->sourceHref) {
+ object_verb = SP_VERB_SELECTION_LINKED_OFFSET;
+ } else {
+ object_verb = SP_VERB_SELECTION_DYNAMIC_OFFSET;
+ }
+ }
}
- DocumentUndo::done(object->document, object_verb,
- _("Move handle"));
+ DocumentUndo::done(object->document, object_verb, _("Move handle"));
}
}
@@ -247,12 +267,32 @@ void KnotHolder::add(KnotHolderEntity *e)
void KnotHolder::add_pattern_knotholder()
{
- if ((item->style->fill.isPaintserver())
- && SP_IS_PATTERN(item->style->getFillPaintServer()))
- {
- PatternKnotHolderEntityXY *entity_xy = new PatternKnotHolderEntityXY();
- PatternKnotHolderEntityAngle *entity_angle = new PatternKnotHolderEntityAngle();
- PatternKnotHolderEntityScale *entity_scale = new PatternKnotHolderEntityScale();
+ if ((item->style->fill.isPaintserver()) && dynamic_cast<SPPattern *>(item->style->getFillPaintServer())) {
+ PatternKnotHolderEntityXY *entity_xy = new PatternKnotHolderEntityXY(true);
+ PatternKnotHolderEntityAngle *entity_angle = new PatternKnotHolderEntityAngle(true);
+ PatternKnotHolderEntityScale *entity_scale = new PatternKnotHolderEntityScale(true);
+ entity_xy->create(desktop, item, this, Inkscape::CTRL_TYPE_POINT,
+ // TRANSLATORS: This refers to the pattern that's inside the object
+ _("<b>Move</b> the pattern fill inside the object"),
+ SP_KNOT_SHAPE_CROSS);
+
+ entity_scale->create(desktop, item, this, Inkscape::CTRL_TYPE_SIZER,
+ _("<b>Scale</b> the pattern fill; uniformly if with <b>Ctrl</b>"),
+ SP_KNOT_SHAPE_SQUARE, SP_KNOT_MODE_XOR);
+
+ entity_angle->create(desktop, item, this, Inkscape::CTRL_TYPE_ROTATE,
+ _("<b>Rotate</b> the pattern fill; with <b>Ctrl</b> to snap angle"),
+ SP_KNOT_SHAPE_CIRCLE, SP_KNOT_MODE_XOR);
+
+ entity.push_back(entity_xy);
+ entity.push_back(entity_angle);
+ entity.push_back(entity_scale);
+ }
+
+ if ((item->style->stroke.isPaintserver()) && dynamic_cast<SPPattern *>(item->style->getStrokePaintServer())) {
+ PatternKnotHolderEntityXY *entity_xy = new PatternKnotHolderEntityXY(false);
+ PatternKnotHolderEntityAngle *entity_angle = new PatternKnotHolderEntityAngle(false);
+ PatternKnotHolderEntityScale *entity_scale = new PatternKnotHolderEntityScale(false);
entity_xy->create(desktop, item, this, Inkscape::CTRL_TYPE_POINT,
// TRANSLATORS: This refers to the pattern that's inside the object
_("<b>Move</b> the pattern fill inside the object"),
diff --git a/src/knotholder.h b/src/knotholder.h
index 3632635f5..f1bacebe5 100644
--- a/src/knotholder.h
+++ b/src/knotholder.h
@@ -17,17 +17,20 @@
*
*/
-#include <glib.h>
#include <2geom/forward.h>
#include <list>
#include <sigc++/connection.h>
namespace Inkscape {
+namespace UI {
+class ShapeEditor;
+}
namespace XML {
class Node;
}
namespace LivePathEffect {
class PowerStrokePointArrayParamKnotHolderEntity;
+class FilletPointArrayParamKnotHolderEntity;
}
}
@@ -46,9 +49,9 @@ public:
void update_knots();
- void knot_moved_handler(SPKnot *knot, Geom::Point const &p, guint state);
- void knot_clicked_handler(SPKnot *knot, guint state);
- void knot_ungrabbed_handler(SPKnot *knot, guint);
+ void knot_moved_handler(SPKnot *knot, Geom::Point const &p, unsigned int state);
+ void knot_clicked_handler(SPKnot *knot, unsigned int state);
+ void knot_ungrabbed_handler(SPKnot *knot, unsigned int);
void add(KnotHolderEntity *e);
@@ -58,8 +61,9 @@ public:
bool knot_mouseover() const;
- friend class ShapeEditor;
- friend class Inkscape::LivePathEffect::PowerStrokePointArrayParamKnotHolderEntity;
+ friend class Inkscape::UI::ShapeEditor; // FIXME why?
+ friend class Inkscape::LivePathEffect::PowerStrokePointArrayParamKnotHolderEntity; // why?
+ friend class Inkscape::LivePathEffect::FilletPointArrayParamKnotHolderEntity; // why?
protected:
@@ -74,7 +78,7 @@ protected:
SPKnotHolderReleasedFunc released;
- gboolean local_change; ///< if true, no need to recreate knotholder if repr was changed.
+ bool local_change; ///< if true, no need to recreate knotholder if repr was changed.
bool dragging;
diff --git a/src/layer-manager.h b/src/layer-manager.h
index 1b69324d5..9eea68004 100644
--- a/src/layer-manager.h
+++ b/src/layer-manager.h
@@ -10,11 +10,12 @@
#ifndef SEEN_INKSCAPE_LAYER_MANAGER_H
#define SEEN_INKSCAPE_LAYER_MANAGER_H
+#include <vector>
+#include <map>
+
#include "document-subset.h"
#include "gc-finalized.h"
#include "gc-soft-ptr.h"
-#include <vector>
-#include <map>
class SPDesktop;
class SPDocument;
@@ -29,8 +30,8 @@ public:
virtual ~LayerManager();
void setCurrentLayer( SPObject* obj );
- void renameLayer( SPObject* obj, gchar const *label, bool uniquify );
- Glib::ustring getNextLayerName( SPObject* obj, gchar const *label);
+ void renameLayer( SPObject* obj, char const *label, bool uniquify );
+ Glib::ustring getNextLayerName( SPObject* obj, char const *label);
sigc::connection connectCurrentLayerChanged(const sigc::slot<void, SPObject *> & slot) {
return _layer_changed_signal.connect(slot);
@@ -44,7 +45,7 @@ private:
friend class LayerWatcher;
class LayerWatcher;
- void _objectModified( SPObject* obj, guint flags );
+ void _objectModified( SPObject* obj, unsigned int flags );
void _setDocument(SPDocument *document);
void _rebuild();
void _selectedLayerChanged(SPObject *layer);
diff --git a/src/layer-model.h b/src/layer-model.h
index 79b7fbe44..86aba63ef 100644
--- a/src/layer-model.h
+++ b/src/layer-model.h
@@ -22,12 +22,8 @@
*
*/
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <stddef.h>
#include <sigc++/sigc++.h>
+#include <cstddef>
class SPDocument;
class SPObject;
diff --git a/src/libavoid/connector.cpp b/src/libavoid/connector.cpp
index 8dcb66f2d..40ded7498 100644
--- a/src/libavoid/connector.cpp
+++ b/src/libavoid/connector.cpp
@@ -442,11 +442,11 @@ void ConnRef::makeActive(void)
void ConnRef::makeInactive(void)
{
- COLA_ASSERT(_active);
-
- // Remove from connRefs list.
- _router->connRefs.erase(_pos);
- _active = false;
+ if (_active) {
+ // Remove from connRefs list.
+ _router->connRefs.erase(_pos);
+ _active = false;
+ }
}
@@ -553,8 +553,12 @@ void ConnRef::unInitialise(void)
void ConnRef::removeFromGraph(void)
{
- _srcVert->removeFromGraph();
- _dstVert->removeFromGraph();
+ if (_srcVert) {
+ _srcVert->removeFromGraph();
+ }
+ if (_dstVert) {
+ _dstVert->removeFromGraph();
+ }
}
@@ -841,7 +845,10 @@ bool ConnRef::generatePath(void)
break;
}
// Check we don't have an apparent infinite connector path.
- COLA_ASSERT(pathlen < 200);
+//#ifdef PATHDEBUG
+ db_printf("Path length: %i\n", pathlen);
+//#endif
+ COLA_ASSERT(pathlen < 10000);
}
std::vector<Point> path(pathlen);
diff --git a/src/libcroco/cr-rgb.c b/src/libcroco/cr-rgb.c
index 06e61ba41..537343579 100644
--- a/src/libcroco/cr-rgb.c
+++ b/src/libcroco/cr-rgb.c
@@ -150,6 +150,7 @@ static const CRRgb gv_standard_colors[] = {
{(const guchar*)"plum", 221, 160, 221, FALSE, FALSE, FALSE, {0,0,0}},
{(const guchar*)"powderblue", 176, 224, 230, FALSE, FALSE, FALSE, {0,0,0}},
{(const guchar*)"purple", 128, 0, 128, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"rebeccapurple", 102, 51, 153, FALSE, FALSE, FALSE, {0,0,0}},
{(const guchar*)"red", 255, 0, 0, FALSE, FALSE, FALSE, {0,0,0}},
{(const guchar*)"rosybrown", 188, 143, 143, FALSE, FALSE, FALSE, {0,0,0}},
{(const guchar*)"royalblue", 65, 105, 225, FALSE, FALSE, FALSE, {0,0,0}},
diff --git a/src/libcroco/cr-sel-eng.c b/src/libcroco/cr-sel-eng.c
index 0eba2b403..4f501ee05 100644
--- a/src/libcroco/cr-sel-eng.c
+++ b/src/libcroco/cr-sel-eng.c
@@ -136,8 +136,9 @@ lang_pseudo_class_handler (CRSelEng *const a_this,
node_iface = PRIVATE(a_this)->node_iface;
- if (strqcmp (a_sel->content.pseudo->name->stryng->str,
- "lang", 4)
+ /* "xml:lang" needed for SVG */
+ if ( (strqcmp (a_sel->content.pseudo->name->stryng->str, "lang", 4 ) &&
+ (strqcmp (a_sel->content.pseudo->name->stryng->str, "xml:lang", 8 ) ) )
|| !a_sel->content.pseudo->type == FUNCTION_PSEUDO) {
cr_utils_trace_info ("This handler is for :lang only");
return FALSE;
@@ -149,6 +150,7 @@ lang_pseudo_class_handler (CRSelEng *const a_this,
return FALSE;
for (; node; node = get_next_parent_element_node (node_iface, node)) {
char *val = node_iface->getProp (node, "lang");
+ if (!val) val = node_iface->getProp (node, "xml:lang");
if (val) {
if (!strcasecmp(val, a_sel->content.pseudo->extra->stryng->str)) {
result = TRUE;
diff --git a/src/libdepixelize/CMakeLists.txt b/src/libdepixelize/CMakeLists.txt
index 895e16e85..a69d37bc7 100644
--- a/src/libdepixelize/CMakeLists.txt
+++ b/src/libdepixelize/CMakeLists.txt
@@ -7,11 +7,11 @@ set(libdepixelize_SRC
kopftracer2011.h
splines.h
- priv/branchless.h
+ priv/branchless.h
priv/colorspace.h
priv/curvature.h
priv/homogeneoussplines.h
- priv/integral
+ priv/integral.h
priv/iterator.h
priv/optimization-kopf2011.h
priv/pixelgraph.h
diff --git a/src/libdepixelize/kopftracer2011.cpp b/src/libdepixelize/kopftracer2011.cpp
index e2f387c86..1e769b0c9 100644
--- a/src/libdepixelize/kopftracer2011.cpp
+++ b/src/libdepixelize/kopftracer2011.cpp
@@ -26,6 +26,8 @@
# include <config.h>
#endif
+#include <glibmm.h>
+
// Build fix under Inkscape build tree
#if GLIBMM_DISABLE_DEPRECATED && HAVE_GLIBMM_THREADS_H
#include <glibmm/threads.h>
diff --git a/src/libdepixelize/kopftracer2011.h b/src/libdepixelize/kopftracer2011.h
index 598f6c79c..c60d0a61a 100644
--- a/src/libdepixelize/kopftracer2011.h
+++ b/src/libdepixelize/kopftracer2011.h
@@ -27,6 +27,7 @@
#include <string>
+#include <glibmm.h>
// Contains exception definitions
#include <glibmm/fileutils.h>
#include <gdkmm/pixbuf.h>
diff --git a/src/libnrtype/CMakeLists.txt b/src/libnrtype/CMakeLists.txt
index 84979d7ea..05fd01a03 100644
--- a/src/libnrtype/CMakeLists.txt
+++ b/src/libnrtype/CMakeLists.txt
@@ -3,14 +3,12 @@ set(nrtype_SRC
FontFactory.cpp
FontInstance.cpp
font-lister.cpp
- font-style-to-pos.cpp
Layout-TNG.cpp
Layout-TNG-Compute.cpp
Layout-TNG-Input.cpp
Layout-TNG-OutIter.cpp
Layout-TNG-Output.cpp
Layout-TNG-Scanline-Makers.cpp
- nr-type-pos-def.cpp
nr-type-primitives.cpp
TextWrapper.cpp
@@ -25,9 +23,7 @@ set(nrtype_SRC
font-glyph.h
font-instance.h
font-lister.h
- font-style-to-pos.h
font-style.h
- nr-type-pos-def.h
nr-type-primitives.h
one-box.h
one-glyph.h
diff --git a/src/libnrtype/FontFactory.cpp b/src/libnrtype/FontFactory.cpp
index 7c0b4ffba..c8f5e1fef 100644
--- a/src/libnrtype/FontFactory.cpp
+++ b/src/libnrtype/FontFactory.cpp
@@ -54,226 +54,11 @@ bool font_descr_equal::operator()( PangoFontDescription *const&a, PangoFontDesc
/////////////////// helper functions
-/**
- * A wrapper for strcasestr that also provides an implementation for Win32.
- */
-static bool
-ink_strstr(char const *haystack, char const *pneedle)
-{
- // windows has no strcasestr implementation, so here is ours...
- // stolen from nmap
- /* FIXME: This is broken for e.g. ink_strstr("aab", "ab"). Report to nmap.
- *
- * Also, suggest use of g_ascii_todown instead of buffer stuff, and g_ascii_tolower instead
- * of tolower. Given that haystack is a font name (i.e. fairly short), it should be ok to
- * do g_ascii_strdown on both haystack and pneedle, and do normal strstr.
- *
- * Rather than fixing in inkscape, consider getting rid of this routine, instead using
- * strdown and plain strstr at caller. We have control over the needle values, so we can
- * modify the callers rather than calling strdown there.
- */
- char buf[512];
- register char const *p;
- char *needle, *q, *foundto;
- if (!*pneedle) return true;
- if (!haystack) return false;
-
- needle = buf;
- p = pneedle; q = needle;
- while ((*q++ = tolower(*p++)))
- ;
- p = haystack - 1; foundto = needle;
- while (*++p) {
- if (tolower(*p) == *foundto) {
- if (!*++foundto) {
- /* Yeah, we found it */
- return true;
- }
- } else foundto = needle;
- }
- return false;
-}
-
-/**
- * Regular fonts are 'Regular', 'Roman', 'Normal', or 'Plain'
- */
-// FIXME: make this UTF8, add non-English style names
-static bool
-is_regular(char const *s)
-{
- if (ink_strstr(s, "Regular")) return true;
- if (ink_strstr(s, "Roman")) return true;
- if (ink_strstr(s, "Normal")) return true;
- if (ink_strstr(s, "Plain")) return true;
- return false;
-}
-
-/**
- * Non-bold fonts are 'Medium' or 'Book'
- */
-static bool
-is_nonbold(char const *s)
-{
- if (ink_strstr(s, "Medium")) return true;
- if (ink_strstr(s, "Book")) return true;
- return false;
-}
-
-/**
- * Italic fonts are 'Italic', 'Oblique', or 'Slanted'
- */
-static bool
-is_italic(char const *s)
-{
- if (ink_strstr(s, "Italic")) return true;
- if (ink_strstr(s, "Oblique")) return true;
- if (ink_strstr(s, "Slanted")) return true;
- return false;
-}
-
-/**
- * Bold fonts are 'Bold'
- */
-static bool
-is_bold(char const *s)
-{
- if (ink_strstr(s, "Bold")) return true;
- return false;
-}
-
-/**
- * Caps fonts are 'Caps'
- */
-static bool
-is_caps(char const *s)
-{
- if (ink_strstr(s, "Caps")) return true;
- return false;
-}
-
-#if 0 /* FIXME: These are all unused. Please delete them or use them (presumably in
-* style_name_compare). */
-/**
- * Monospaced fonts are 'Mono'
- */
-static bool
-is_mono(char const *s)
-{
- if (ink_strstr(s, "Mono")) return true;
- return false;
-}
-
-/**
- * Rounded fonts are 'Round'
- */
-static bool
-is_round(char const *s)
-{
- if (ink_strstr(s, "Round")) return true;
- return false;
-}
-
-/**
- * Outline fonts are 'Outline'
- */
-static bool
-is_outline(char const *s)
-{
- if (ink_strstr(s, "Outline")) return true;
- return false;
-}
-
-/**
- * Swash fonts are 'Swash'
- */
-static bool
-is_swash(char const *s)
-{
- if (ink_strstr(s, "Swash")) return true;
- return false;
-}
-#endif
-
-/**
- * Determines if two style names match. This allows us to match
- * based on the type of style rather than simply doing string matching,
- * because for instance 'Plain' and 'Normal' mean the same thing.
- *
- * Q: Shouldn't this include the other tests such as is_outline, etc.?
- * Q: Is there a problem with strcasecmp on Win32? Should it use stricmp?
- */
-int
-style_name_compare(char const *aa, char const *bb)
-{
- char const *a = (char const *) aa;
- char const *b = (char const *) bb;
-
- if (is_regular(a) && !is_regular(b)) return -1;
- if (is_regular(b) && !is_regular(a)) return 1;
-
- if (is_bold(a) && !is_bold(b)) return 1;
- if (is_bold(b) && !is_bold(a)) return -1;
-
- if (is_italic(a) && !is_italic(b)) return 1;
- if (is_italic(b) && !is_italic(a)) return -1;
-
- if (is_nonbold(a) && !is_nonbold(b)) return 1;
- if (is_nonbold(b) && !is_nonbold(a)) return -1;
-
- if (is_caps(a) && !is_caps(b)) return 1;
- if (is_caps(b) && !is_caps(a)) return -1;
-
- return strcasecmp(a, b);
-}
-
-/*
- defined but not used:
-
-static int
-style_record_compare(void const *aa, void const *bb)
-{
- NRStyleRecord const *a = (NRStyleRecord const *) aa;
- NRStyleRecord const *b = (NRStyleRecord const *) bb;
-
- return (style_name_compare(a->name, b->name));
-}
-
-static void font_factory_name_list_destructor(NRNameList *list)
-{
- for (unsigned int i = 0; i < list->length; i++)
- g_free(list->names[i]);
- if ( list->names ) g_free(list->names);
-}
-
-static void font_factory_style_list_destructor(NRStyleList *list)
-{
- for (unsigned int i = 0; i < list->length; i++) {
- g_free((void *) (list->records)[i].name);
- g_free((void *) (list->records)[i].descr);
- }
- if ( list->records ) g_free(list->records);
-}
-*/
-
-/**
- * On Win32 performs a stricmp(a,b), otherwise does a strcasecmp(a,b)
- */
-int
-family_name_compare(char const *a, char const *b)
-{
-#ifndef WIN32
- return strcasecmp((*((char const **) a)), (*((char const **) b)));
-#else
- return stricmp((*((char const **) a)), (*((char const **) b)));
-#endif
-}
-
static void noop(...) {}
//#define PANGO_DEBUG g_print
#define PANGO_DEBUG noop
-
///////////////////// FontFactory
#ifndef USE_PANGO_WIN32
// the substitute function to tell fontconfig to enforce outline fonts
@@ -312,6 +97,7 @@ font_factory::font_factory(void) :
fontSize(512),
loadedPtr(new FaceMapType())
{
+ // std::cout << pango_version_string() << std::endl;
#ifdef USE_PANGO_WIN32
#else
pango_ft2_font_map_set_resolution(PANGO_FT2_FONT_MAP(fontServer),
@@ -344,13 +130,6 @@ font_factory::~font_factory(void)
delete tmp;
loadedPtr = 0;
}
-
- // Delete the pango font pointers in the string to instance map
- PangoStringToDescrMap::iterator it = fontInstanceMap.begin();
- while (it != fontInstanceMap.end()) {
- pango_font_description_free((*it).second);
- ++it;
- }
}
@@ -463,359 +242,157 @@ Glib::ustring font_factory::GetUIStyleString(PangoFontDescription const *fontDes
return style;
}
-/**
- Replace font family leaving style alone (if possible).
- @param fontSpec the given font
- @param newFamily
- @return the changed fontspec, if the property can not be set return an empty string
- The routine first searches for an exact match.
- If no exact match found, calls FontSpecificationBestMatch().
-*/
-Glib::ustring font_factory::ReplaceFontSpecificationFamily(const Glib::ustring & fontSpec, const Glib::ustring & newFamily)
-{
- Glib::ustring newFontSpec;
-
- // Although we are using the string from pango_font_description_to_string for the
- // font specification, we definitely cannot just set the new family in the
- // PangoFontDescription structure and ask for a new string. This is because
- // what constitutes a "family" in our own UI may be different from how Pango
- // sees it.
-
- // Find the PangoFontDescription associated with the old font specification string.
- PangoStringToDescrMap::iterator it = fontInstanceMap.find(fontSpec);
-
-
- if (it != fontInstanceMap.end()) {
- // Description found!
-
- // Make copy
- PangoFontDescription *descr = pango_font_description_copy((*it).second);
- // Grab the old UI Family string from the descr
- Glib::ustring uiFamily = GetUIFamilyString(descr);
-
- // Replace the UI Family name with the new family name
- std::size_t found = fontSpec.find(uiFamily);
- if (found != Glib::ustring::npos) {
-
- // Add comma to end of newFamily... commas at end don't hurt but are
- // required if the last part of a family name is a valid font style
- // (e.g. "Arial Black").
- Glib::ustring newFamilyComma = newFamily;
- if( *newFamilyComma.rbegin() != ',' ) {
- newFamilyComma += ",";
- }
- newFontSpec = fontSpec;
- newFontSpec.erase(found, uiFamily.size());
- newFontSpec.insert(found, newFamilyComma);
-
- // If the new font specification does not exist in the reference maps,
- // search for the next best match for the faces in that style
- it = fontInstanceMap.find(newFontSpec);
- if (it == fontInstanceMap.end()) {
+/////
- // Search for best match, empty string returned if not found.
- newFontSpec = FontSpecificationBestMatch( newFontSpec );
+// Calculate a Style "value" based on CSS values for ordering styles.
+static int StyleNameValue( const Glib::ustring &style )
+{
- }
- }
+ PangoFontDescription *pfd = pango_font_description_from_string ( style.c_str() );
+ int value =
+ pango_font_description_get_weight ( pfd ) * 1000000 +
+ pango_font_description_get_style ( pfd ) * 10000 +
+ pango_font_description_get_stretch( pfd ) * 100 +
+ pango_font_description_get_variant( pfd );
+ pango_font_description_free ( pfd );
+ return value;
+}
- pango_font_description_free(descr);
- }
+// Determines order in which styles are presented (sorted by CSS style values)
+//static bool StyleNameCompareInternal(const StyleNames &style1, const StyleNames &style2)
+//{
+// return( StyleNameValue( style1.CssName ) < StyleNameValue( style2.CssName ) );
+//}
- return newFontSpec;
+static gint StyleNameCompareInternalGlib(gconstpointer a, gconstpointer b)
+{
+ return( StyleNameValue( ((StyleNames *)a)->CssName ) <
+ StyleNameValue( ((StyleNames *)b)->CssName ) ? -1 : 1 );
}
-/**
- Apply style property to the given font
- @param fontSpec the given font
- @param turnOn true to set italic style
- @return the changed fontspec, if the property can not be set return an empty string
- The routine first searches for an exact match to "FontFamily Italic" or
- "Font Family Oblique" (turnOn is true) or "FontFamily" (turnOn is false).
- If no exact match found, calls FontSpecificationBestMatch().
-*/
-Glib::ustring font_factory::FontSpecificationSetItalic(const Glib::ustring & fontSpec, bool turnOn)
+static bool ustringPairSort(std::pair<PangoFontFamily*, Glib::ustring> const& first, std::pair<PangoFontFamily*, Glib::ustring> const& second)
{
- Glib::ustring newFontSpec;
-
- // Find the PangoFontDescription associated with the font specification string.
- PangoStringToDescrMap::iterator it = fontInstanceMap.find(fontSpec);
-
- if (it != fontInstanceMap.end()) {
- // Description found!
-
- // Make copy.
- PangoFontDescription *descr = pango_font_description_copy((*it).second);
-
- PangoStyle style;
- if (turnOn) {
- // First try Oblique, we'll try Italic later
- style = PANGO_STYLE_OBLIQUE;
- } else {
- style = PANGO_STYLE_NORMAL;
- }
-
- pango_font_description_set_style(descr, style);
-
- newFontSpec = ConstructFontSpecification(descr);
-
- bool exactMatchFound = true;
- if (fontInstanceMap.find(newFontSpec) == fontInstanceMap.end()) {
-
- exactMatchFound = false;
- if (turnOn) {
- // Next try Italic
- style = PANGO_STYLE_ITALIC;
- pango_font_description_set_style(descr, style);
-
- exactMatchFound = true;
- if (fontInstanceMap.find(newFontSpec) == fontInstanceMap.end()) {
- exactMatchFound = false;
- }
- }
- }
-
- // Search for best match, empty string returned if not found.
- if( !exactMatchFound ) {
- newFontSpec = FontSpecificationBestMatch( newFontSpec );
- }
-
- pango_font_description_free(descr);
- }
-
- return newFontSpec; // Empty if not found.
+ // well, this looks weird.
+ return first.second < second.second;
}
-/**
- Apply weight property to the given font
- @param fontSpec the given font
- @param turnOn true to set bold
- @return the changed fontspec, if the property can not be set return an empty string
- This routine first searches for an exact match, if none found
- it calls FontSpecificationBestMatch().
-*/
-Glib::ustring font_factory::FontSpecificationSetBold(const Glib::ustring & fontSpec, bool turnOn)
+void font_factory::GetUIFamilies(std::vector<PangoFontFamily *>& out)
{
- Glib::ustring newFontSpec;
-
- // Find the PangoFontDescription associated with the font specification string.
- PangoStringToDescrMap::iterator it = fontInstanceMap.find(fontSpec);
-
- if (it != fontInstanceMap.end()) {
- // Description found!
-
- // Make copy.
- PangoFontDescription *descr = pango_font_description_copy((*it).second);
-
-
- PangoWeight weight;
- if (turnOn) {
- weight = PANGO_WEIGHT_BOLD;
- } else {
- weight = PANGO_WEIGHT_NORMAL;
- }
-
- pango_font_description_set_weight(descr, weight);
-
- newFontSpec = ConstructFontSpecification(descr);
-
- if (fontInstanceMap.find(newFontSpec) == fontInstanceMap.end()) {
- // Search for best match, empty string returned if not found.
- newFontSpec = FontSpecificationBestMatch( newFontSpec );
+ // Gather the family names as listed by Pango
+ PangoFontFamily** families = NULL;
+ int numFamilies = 0;
+ pango_font_map_list_families(fontServer, &families, &numFamilies);
+
+ std::vector<std::pair<PangoFontFamily *, Glib::ustring> > sorted;
+
+ // not size_t
+ for (int currentFamily = 0; currentFamily < numFamilies; ++currentFamily) {
+ const char* displayName = pango_font_family_get_name(families[currentFamily]);
+
+ if (displayName == 0 || *displayName == '\0') {
+ continue;
}
-
- pango_font_description_free(descr);
+ sorted.push_back(std::make_pair(families[currentFamily], displayName));
}
- return newFontSpec; // Empty if not found.
-}
-
-/**
- Use pango_font_description_better_match() to find best font match.
- This handles cases like Century Schoolbook L where the "normal"
- font is Century Schoolbook L Medium so just removing Italic
- from the font name doesn't yield the correct name.
- @param fontSpec the given font
- @return the changed fontspec, if the property can not be set return an empty string
-*/
-// http://library.gnome.org/devel/pango/1.28/pango-Fonts.html#pango-font-description-better-match
-Glib::ustring font_factory::FontSpecificationBestMatch(const Glib::ustring & fontSpec )
-{
-
- Glib::ustring newFontSpec;
-
- // Look for exact match
- PangoStringToDescrMap::iterator it = fontInstanceMap.find(fontSpec);
-
- // If there is no exact match, look for the best match.
- if (it != fontInstanceMap.end()) {
-
- newFontSpec = fontSpec;
-
- } else {
-
- PangoFontDescription *fontDescr = pango_font_description_from_string(fontSpec.c_str());
- PangoFontDescription *bestMatchDescr = NULL;
-
- // Grab the UI Family string from the descr
- Glib::ustring family = GetUIFamilyString(fontDescr);
- Glib::ustring bestMatchDescription;
-
- bool setFirstFamilyMatch = false;
- for (it = fontInstanceMap.begin(); it != fontInstanceMap.end(); ++it) {
-
- Glib::ustring currentFontSpec = (*it).first;
- Glib::ustring currentFamily = GetUIFamilyString((*it).second);
-
- // Save some time by only looking at the right family.
- // Must use family name rather than fontSpec
- // (otherwise DejaVu Sans matches DejaVu Sans Mono).
- if (currentFamily == family) {
- if (!setFirstFamilyMatch) {
- // This ensures that the closest match is at least within the correct
- // family rather than the first font in the list
- bestMatchDescr = pango_font_description_copy((*it).second);
- bestMatchDescription = currentFontSpec;
- setFirstFamilyMatch = true;
- } else {
- // Get the font description that corresponds, and
- // then see if we've found a better match
- PangoFontDescription *possibleMatch = pango_font_description_copy((*it).second);
-
- if (pango_font_description_better_match(
- fontDescr, bestMatchDescr, possibleMatch)) {
-
- pango_font_description_free(bestMatchDescr);
- bestMatchDescr = possibleMatch;
- bestMatchDescription = currentFontSpec;
- } else {
- pango_font_description_free(possibleMatch);
- }
- }
- }
- } // for
-
- newFontSpec = bestMatchDescription; // If NULL, then no match found
-
- pango_font_description_free(fontDescr);
- pango_font_description_free(bestMatchDescr);
-
+ std::sort(sorted.begin(), sorted.end(), ustringPairSort);
+
+ for (size_t i = 0; i < sorted.size(); ++i) {
+ out.push_back(sorted[i].first);
}
-
- return newFontSpec;
-}
-
-/////
-
-static bool StyleNameCompareInternal(Glib::ustring style1, Glib::ustring style2)
-{
- return (style_name_compare(style1.c_str(), style2.c_str()) < 0);
}
-void font_factory::GetUIFamiliesAndStyles(FamilyToStylesMap *map)
+GList* font_factory::GetUIStyles(PangoFontFamily * in)
{
- g_assert(map);
-
- if (map) {
-
- // Gather the family names as listed by Pango
- PangoFontFamily** families = NULL;
- int numFamilies = 0;
- pango_font_map_list_families(fontServer, &families, &numFamilies);
-
- for (int currentFamily=0; currentFamily < numFamilies; currentFamily++) {
+ GList* ret = NULL;
+ // Gather the styles for this family
+ PangoFontFace** faces = NULL;
+ int numFaces = 0;
+ pango_font_family_list_faces(in, &faces, &numFaces);
- // Gather the styles for this family
- PangoFontFace** faces = NULL;
- int numFaces = 0;
- pango_font_family_list_faces(families[currentFamily], &faces, &numFaces);
+ for (int currentFace = 0; currentFace < numFaces; currentFace++) {
- for (int currentFace=0; currentFace < numFaces; currentFace++) {
-
- // If the face has a name, describe it, and then use the
- // description to get the UI family and face strings
+ // If the face has a name, describe it, and then use the
+ // description to get the UI family and face strings
+ const gchar* displayName = pango_font_face_get_face_name(faces[currentFace]);
+ // std::cout << "Display Name: " << displayName << std::endl;
+ if (displayName == NULL || *displayName == '\0') {
+ continue;
+ }
- if (pango_font_face_get_face_name(faces[currentFace]) == NULL) {
+ PangoFontDescription *faceDescr = pango_font_face_describe(faces[currentFace]);
+ if (faceDescr) {
+ Glib::ustring familyUIName = GetUIFamilyString(faceDescr);
+ Glib::ustring styleUIName = GetUIStyleString(faceDescr);
+ // std::cout << familyUIName << " " << styleUIName << " " << displayName << std::endl;
+ // Disable synthesized (faux) font faces except for CSS generic faces
+ if (pango_font_face_is_synthesized(faces[currentFace]) ) {
+ if (familyUIName.compare( "sans-serif" ) != 0 &&
+ familyUIName.compare( "serif" ) != 0 &&
+ familyUIName.compare( "monospace" ) != 0 &&
+ familyUIName.compare( "fantasy" ) != 0 &&
+ familyUIName.compare( "cursive" ) != 0 ) {
continue;
}
+ }
+
+ // Pango breaks the 1 to 1 mapping between Pango weights and CSS weights by
+ // adding Semi-Light (as of 1.36.7), Book (as of 1.24), and Ultra-Heavy (as of
+ // 1.24). We need to map these weights to CSS weights. Book and Ultra-Heavy
+ // are rarely used. Semi-Light (350) is problematic as it is halfway between
+ // Light (300) and Normal (400) and if care is not taken it is converted to
+ // Normal, rather than Light.
+ //
+ // Note: The ultimate solution to handling various weight in the same
+ // font family is to support the @font rules from CSS.
+ //
+ // Additional notes, helpful for debugging:
+ // Pango's FC backend:
+ // Weights defined in fontconfig/fontconfig.h
+ // String equivalents in src/fcfreetype.c
+ // Weight set from os2->usWeightClass
+ // Use Fontforge: Element->Font Info...->OS/2->Misc->Weight Class to check font weight
+ size_t f = styleUIName.find( "Book" );
+ if( f != Glib::ustring::npos ) {
+ styleUIName.replace( f, 4, "Normal" );
+ }
+ f = styleUIName.find( "Semi-Light" );
+ if( f != Glib::ustring::npos ) {
+ styleUIName.replace( f, 10, "Light" );
+ }
+ f = styleUIName.find( "Ultra-Heavy" );
+ if( f != Glib::ustring::npos ) {
+ styleUIName.replace( f, 11, "Heavy" );
+ }
- PangoFontDescription *faceDescr = pango_font_face_describe(faces[currentFace]);
- if (faceDescr) {
- Glib::ustring familyUIName = GetUIFamilyString(faceDescr);
- Glib::ustring styleUIName = GetUIStyleString(faceDescr);
-
- // Disable synthesized (faux) font faces except for CSS generic faces
- if (pango_font_face_is_synthesized(faces[currentFace]) ) {
- if( familyUIName.compare( "sans-serif" ) != 0 &&
- familyUIName.compare( "serif" ) != 0 &&
- familyUIName.compare( "monospace" ) != 0 &&
- familyUIName.compare( "fantasy" ) != 0 &&
- familyUIName.compare( "cursive" ) != 0 ) {
- //std::cout << "faux: " << familyUIName << " | " << styleUIName << std::endl;
- continue;
- }
- }
-
- if (!familyUIName.empty() && !styleUIName.empty()) {
-
- // Find the right place to put the style information, adding
- // a map entry for the family name if it doesn't yet exist
-
- FamilyToStylesMap::iterator iter = map->find(familyUIName);
-
- // Insert new family
- if (iter == map->end()) {
- map->insert(std::make_pair(familyUIName, std::list<Glib::ustring>()));
- }
-
- // Insert into the style list and save the info in the reference maps
- // only if the style does not yet exist
-
- bool exists = false;
- std::list<Glib::ustring> &styleList = (*map)[familyUIName];
-
- for (std::list<Glib::ustring>::iterator it=styleList.begin();
- it != styleList.end();
- ++it) {
- if (*it == styleUIName) {
- exists = true;
- break;
- }
- }
-
- if (!exists) {
- styleList.push_back(styleUIName);
-
- // Add the string info needed in the reference maps
- fontStringMap.insert(
- std::make_pair(
- Glib::ustring(familyUIName) + Glib::ustring(styleUIName),
- ConstructFontSpecification(faceDescr)));
- fontInstanceMap.insert(
- std::make_pair(ConstructFontSpecification(faceDescr), faceDescr));
-
- } else {
- pango_font_description_free(faceDescr);
- }
- } else {
- pango_font_description_free(faceDescr);
- }
+ bool exists = false;
+ for(GList *temp = ret; temp; temp = temp->next) {
+ if( ((StyleNames*)temp->data)->CssName.compare( styleUIName ) == 0 ) {
+ exists = true;
+ std::cerr << "Warning: Font face with same CSS values already added: "
+ << familyUIName << " " << styleUIName
+ << " (" << ((StyleNames*)temp->data)->DisplayName
+ << ", " << displayName << ")" << std::endl;
+ break;
}
}
- g_free(faces);
- faces = 0;
- }
- g_free(families);
- families = 0;
- // Sort the style lists
- for (FamilyToStylesMap::iterator iter = map->begin() ; iter != map->end(); ++iter) {
- (*iter).second.sort(StyleNameCompareInternal);
+ if (!exists && !familyUIName.empty() && !styleUIName.empty()) {
+ // Add the style information
+ ret = g_list_append(ret, new StyleNames(styleUIName, displayName));
+ }
}
+ pango_font_description_free(faceDescr);
}
+ g_free(faces);
+
+ // Sort the style lists
+ ret = g_list_sort( ret, StyleNameCompareInternalGlib );
+ return ret;
}
+
font_instance* font_factory::FaceFromStyle(SPStyle const *style)
{
font_instance *font = NULL;
@@ -825,25 +402,141 @@ font_instance* font_factory::FaceFromStyle(SPStyle const *style)
if (style) {
// First try to use the font specification if it is set
- if (style->text->font_specification.set
- && style->text->font_specification.value
- && *style->text->font_specification.value) {
+ if (style->font_specification.set
+ && style->font_specification.value
+ && *style->font_specification.value) {
- font = FaceFromFontSpecification(style->text->font_specification.value);
+ font = FaceFromFontSpecification(style->font_specification.value);
}
// If that failed, try using the CSS information in the style
if (!font) {
- font = Face(style->text->font_family.value, font_style_to_pos(*style));
+ PangoFontDescription *temp_descr = pango_font_description_new();
+
+ pango_font_description_set_family(temp_descr, style->font_family.value);
+
+ // This duplicates Layout::EnumConversionItem... perhaps we can share code?
+ switch ( style->font_style.computed ) {
+ case SP_CSS_FONT_STYLE_ITALIC:
+ pango_font_description_set_style(temp_descr, PANGO_STYLE_ITALIC);
+ break;
+
+ case SP_CSS_FONT_STYLE_OBLIQUE:
+ pango_font_description_set_style(temp_descr, PANGO_STYLE_OBLIQUE);
+ break;
- // That was a hatchet job... so we need to check if this font exists!!
- Glib::ustring fontSpec = font_factory::Default()->ConstructFontSpecification(font);
- Glib::ustring newFontSpec = FontSpecificationBestMatch( fontSpec );
- if( fontSpec != newFontSpec ) {
- font->Unref();
- font = FaceFromFontSpecification( newFontSpec.c_str() );
+ case SP_CSS_FONT_STYLE_NORMAL:
+ default:
+ pango_font_description_set_style(temp_descr, PANGO_STYLE_NORMAL);
+ break;
}
+
+ switch( style->font_weight.computed ) {
+ case SP_CSS_FONT_WEIGHT_100:
+ pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_THIN);
+ break;
+
+ case SP_CSS_FONT_WEIGHT_200:
+ pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_ULTRALIGHT);
+ break;
+
+ case SP_CSS_FONT_WEIGHT_300:
+ pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_LIGHT);
+ break;
+
+ case SP_CSS_FONT_WEIGHT_400:
+ case SP_CSS_FONT_WEIGHT_NORMAL:
+ pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_NORMAL);
+ break;
+
+ case SP_CSS_FONT_WEIGHT_500:
+ pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_MEDIUM);
+ break;
+
+ case SP_CSS_FONT_WEIGHT_600:
+ pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_SEMIBOLD);
+ break;
+
+ case SP_CSS_FONT_WEIGHT_700:
+ case SP_CSS_FONT_WEIGHT_BOLD:
+ pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_BOLD);
+ break;
+
+ case SP_CSS_FONT_WEIGHT_800:
+ pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_ULTRABOLD);
+ break;
+
+ case SP_CSS_FONT_WEIGHT_900:
+ pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_HEAVY);
+ break;
+
+ case SP_CSS_FONT_WEIGHT_LIGHTER:
+ case SP_CSS_FONT_WEIGHT_BOLDER:
+ default:
+ g_warning("FaceFromStyle: Unrecognized font_weight.computed value");
+ pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_NORMAL);
+ break;
+ }
+ // PANGO_WIEGHT_ULTRAHEAVY not used (not CSS2)
+
+ switch (style->font_stretch.computed) {
+ case SP_CSS_FONT_STRETCH_ULTRA_CONDENSED:
+ pango_font_description_set_stretch(temp_descr, PANGO_STRETCH_ULTRA_CONDENSED);
+ break;
+
+ case SP_CSS_FONT_STRETCH_EXTRA_CONDENSED:
+ pango_font_description_set_stretch(temp_descr, PANGO_STRETCH_EXTRA_CONDENSED);
+ break;
+
+ case SP_CSS_FONT_STRETCH_CONDENSED:
+ pango_font_description_set_stretch(temp_descr, PANGO_STRETCH_CONDENSED);
+ break;
+
+ case SP_CSS_FONT_STRETCH_SEMI_CONDENSED:
+ pango_font_description_set_stretch(temp_descr, PANGO_STRETCH_SEMI_CONDENSED);
+ break;
+
+ case SP_CSS_FONT_STRETCH_NORMAL:
+ pango_font_description_set_stretch(temp_descr, PANGO_STRETCH_NORMAL);
+ break;
+
+ case SP_CSS_FONT_STRETCH_SEMI_EXPANDED:
+ pango_font_description_set_stretch(temp_descr, PANGO_STRETCH_SEMI_EXPANDED);
+ break;
+
+ case SP_CSS_FONT_STRETCH_EXPANDED:
+ pango_font_description_set_stretch(temp_descr, PANGO_STRETCH_EXPANDED);
+ break;
+
+ case SP_CSS_FONT_STRETCH_EXTRA_EXPANDED:
+ pango_font_description_set_stretch(temp_descr, PANGO_STRETCH_EXTRA_EXPANDED);
+ break;
+
+ case SP_CSS_FONT_STRETCH_ULTRA_EXPANDED:
+ pango_font_description_set_stretch(temp_descr, PANGO_STRETCH_ULTRA_EXPANDED);
+
+ case SP_CSS_FONT_STRETCH_WIDER:
+ case SP_CSS_FONT_STRETCH_NARROWER:
+ default:
+ g_warning("FaceFromStyle: Unrecognized font_stretch.computed value");
+ pango_font_description_set_stretch(temp_descr, PANGO_STRETCH_NORMAL);
+ break;
+ }
+
+ switch ( style->font_variant.computed ) {
+ case SP_CSS_FONT_VARIANT_SMALL_CAPS:
+ pango_font_description_set_variant(temp_descr, PANGO_VARIANT_SMALL_CAPS);
+ break;
+
+ case SP_CSS_FONT_VARIANT_NORMAL:
+ default:
+ pango_font_description_set_variant(temp_descr, PANGO_VARIANT_NORMAL);
+ break;
+ }
+
+ font = Face(temp_descr);
+ pango_font_description_free(temp_descr);
}
}
@@ -859,37 +552,6 @@ font_instance *font_factory::FaceFromDescr(char const *family, char const *style
return res;
}
-font_instance* font_factory::FaceFromUIStrings(char const *uiFamily, char const *uiStyle)
-{
- font_instance *fontInstance = NULL;
-
- g_assert(uiFamily && uiStyle);
- if (uiFamily && uiStyle) {
-
- // If font list, take only first font in list
- gchar** tokens = g_strsplit( uiFamily, ",", 0 );
- g_strstrip( tokens[0] );
-
- Glib::ustring uiString = Glib::ustring(tokens[0]) + Glib::ustring(uiStyle);
-
- g_strfreev( tokens );
-
- UIStringToPangoStringMap::iterator uiToPangoIter = fontStringMap.find(uiString);
-
- if (uiToPangoIter != fontStringMap.end ()) {
- PangoStringToDescrMap::iterator pangoToDescrIter = fontInstanceMap.find((*uiToPangoIter).second);
- if (pangoToDescrIter != fontInstanceMap.end()) {
- // We found the pango description - now we can make a font_instance
- PangoFontDescription *tempDescr = pango_font_description_copy((*pangoToDescrIter).second);
- fontInstance = Face(tempDescr);
- pango_font_description_free(tempDescr);
- }
- }
- }
-
- return fontInstance;
-}
-
font_instance* font_factory::FaceFromPangoString(char const *pangoString)
{
font_instance *fontInstance = NULL;
@@ -897,25 +559,15 @@ font_instance* font_factory::FaceFromPangoString(char const *pangoString)
g_assert(pangoString);
if (pangoString) {
- PangoFontDescription *descr = NULL;
-
- // First attempt to find the font specification in the reference map
- PangoStringToDescrMap::iterator it = fontInstanceMap.find(Glib::ustring(pangoString));
- if (it != fontInstanceMap.end()) {
- descr = pango_font_description_copy((*it).second);
- }
- // Or create a font description from the string - this may fail or
+ // Create a font description from the string - this may fail or
// produce unexpected results if the string does not have a good format
- if (!descr) {
- descr = pango_font_description_from_string(pangoString);
- }
-
- if (descr && (sp_font_description_get_family(descr) != NULL)) {
- fontInstance = Face(descr);
- }
+ PangoFontDescription *descr = pango_font_description_from_string(pangoString);
if (descr) {
+ if (sp_font_description_get_family(descr) != NULL) {
+ fontInstance = Face(descr);
+ }
pango_font_description_free(descr);
}
}
@@ -1030,70 +682,6 @@ font_instance *font_factory::Face(char const *family, int variant, int style, in
return res;
}
-font_instance *font_factory::Face(char const *family, NRTypePosDef apos)
-{
- PangoFontDescription *temp_descr = pango_font_description_new();
-
- pango_font_description_set_family(temp_descr, family);
-
- if ( apos.variant == NR_POS_VARIANT_SMALLCAPS ) {
- pango_font_description_set_variant(temp_descr, PANGO_VARIANT_SMALL_CAPS);
- } else {
- pango_font_description_set_variant(temp_descr, PANGO_VARIANT_NORMAL);
- }
-
- if ( apos.italic ) {
- pango_font_description_set_style(temp_descr, PANGO_STYLE_ITALIC);
- } else if ( apos.oblique ) {
- pango_font_description_set_style(temp_descr, PANGO_STYLE_OBLIQUE);
- } else {
- pango_font_description_set_style(temp_descr, PANGO_STYLE_NORMAL);
- }
-
- if ( apos.weight <= NR_POS_WEIGHT_THIN ) {
- pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_THIN);
- } else if ( apos.weight <= NR_POS_WEIGHT_ULTRA_LIGHT ) {
- pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_ULTRALIGHT);
- } else if ( apos.weight <= NR_POS_WEIGHT_LIGHT ) {
- pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_LIGHT);
- } else if ( apos.weight <= NR_POS_WEIGHT_BOOK ) {
- pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_BOOK);
- } else if ( apos.weight <= NR_POS_WEIGHT_NORMAL ) {
- pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_NORMAL);
- } else if ( apos.weight <= NR_POS_WEIGHT_MEDIUM ) {
- pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_MEDIUM);
- } else if ( apos.weight <= NR_POS_WEIGHT_SEMIBOLD ) {
- pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_SEMIBOLD);
- } else if ( apos.weight <= NR_POS_WEIGHT_BOLD ) {
- pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_BOLD);
- } else if ( apos.weight <= NR_POS_WEIGHT_ULTRA_BOLD ) {
- pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_ULTRABOLD);
- } else {
- pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_HEAVY);
- }
- // PANGO_WIEGHT_ULTRAHEAVY not used (not CSS2)
-
- if ( apos.stretch <= NR_POS_STRETCH_ULTRA_CONDENSED ) {
- pango_font_description_set_stretch(temp_descr, PANGO_STRETCH_EXTRA_CONDENSED);
- } else if ( apos.stretch <= NR_POS_STRETCH_CONDENSED ) {
- pango_font_description_set_stretch(temp_descr, PANGO_STRETCH_CONDENSED);
- } else if ( apos.stretch <= NR_POS_STRETCH_SEMI_CONDENSED ) {
- pango_font_description_set_stretch(temp_descr, PANGO_STRETCH_SEMI_CONDENSED);
- } else if ( apos.stretch <= NR_POS_STRETCH_NORMAL ) {
- pango_font_description_set_stretch(temp_descr, PANGO_STRETCH_NORMAL);
- } else if ( apos.stretch <= NR_POS_STRETCH_SEMI_EXPANDED ) {
- pango_font_description_set_stretch(temp_descr, PANGO_STRETCH_SEMI_EXPANDED);
- } else if ( apos.stretch <= NR_POS_STRETCH_EXPANDED ) {
- pango_font_description_set_stretch(temp_descr, PANGO_STRETCH_EXPANDED);
- } else {
- pango_font_description_set_stretch(temp_descr, PANGO_STRETCH_EXTRA_EXPANDED);
- }
-
- font_instance *res = Face(temp_descr);
- pango_font_description_free(temp_descr);
- return res;
-}
-
void font_factory::UnrefFace(font_instance *who)
{
if ( who ) {
@@ -1145,24 +733,6 @@ void font_factory::AddInCache(font_instance *who)
}
/*
- {
- std::cout << " Printing out fontInstanceMap: " << std::endl;
- PangoStringToDescrMap::iterator it = fontInstanceMap.begin();
- while (it != fontInstanceMap.end()) {
-
- PangoFontDescription *descr = pango_font_description_copy((*it).second);
-
- // Grab the UI Family string from the descr
- Glib::ustring uiFamily = GetUIFamilyString(descr);
- Glib::ustring uiStyle = GetUIStyleString(descr);
- std::cout << " " << uiFamily << " " << uiStyle << std::endl;
-
- it++;
- }
- }
-*/
-
-/*
Local Variables:
mode:c++
c-file-style:"stroustrup"
diff --git a/src/libnrtype/FontFactory.h b/src/libnrtype/FontFactory.h
index 7b606d200..bd5a4460c 100644
--- a/src/libnrtype/FontFactory.h
+++ b/src/libnrtype/FontFactory.h
@@ -21,9 +21,7 @@
#include <pango/pango.h>
#include "nr-type-primitives.h"
-#include "nr-type-pos-def.h"
-#include "font-style-to-pos.h"
-#include "../style.h"
+#include "style.h"
/* Freetype */
#ifdef USE_PANGO_WIN32
@@ -51,15 +49,26 @@ struct font_descr_equal : public std::binary_function<PangoFontDescription*, Pan
bool operator()(PangoFontDescription *const &a, PangoFontDescription *const &b) const;
};
-// Comparison functions for style names
-int style_name_compare(char const *aa, char const *bb);
-int family_name_compare(char const *a, char const *b);
-
// Wraps calls to pango_font_description_get_family with some name substitution
const char *sp_font_description_get_family(PangoFontDescription const *fontDescr);
-// Map type for gathering UI family and style strings
-typedef std::map<Glib::ustring, std::list<Glib::ustring> > FamilyToStylesMap;
+// Class for style strings: both CSS and as suggested by font.
+class StyleNames {
+
+public:
+ StyleNames() {};
+ StyleNames( Glib::ustring name ) :
+ CssName( name ), DisplayName( name ) {};
+ StyleNames( Glib::ustring cssname, Glib::ustring displayname ) :
+ CssName( cssname ), DisplayName( displayname ) {};
+
+public:
+ Glib::ustring CssName; // Style as Pango/CSS would write it.
+ Glib::ustring DisplayName; // Style as Font designer named it.
+};
+
+// Map type for gathering UI family and style names
+typedef std::map<Glib::ustring, std::list<StyleNames> > FamilyToStylesMap;
class font_factory {
public:
@@ -103,16 +112,10 @@ public:
Glib::ustring GetUIFamilyString(PangoFontDescription const *fontDescr);
Glib::ustring GetUIStyleString(PangoFontDescription const *fontDescr);
- /// Modifiers for the font specification (returns new font specification)
- Glib::ustring ReplaceFontSpecificationFamily(const Glib::ustring & fontSpec, const Glib::ustring & newFamily);
- Glib::ustring FontSpecificationSetItalic(const Glib::ustring & fontSpec, bool turnOn);
- Glib::ustring FontSpecificationSetBold(const Glib::ustring & fontSpec, bool turnOn);
-
- Glib::ustring FontSpecificationBestMatch(const Glib::ustring& fontSpec );
-
- // Gathers all strings needed for UI while storing pango information in
- // fontInstanceMap and fontStringMap
- void GetUIFamiliesAndStyles(FamilyToStylesMap *map);
+ // Helpfully inserts all font families into the provided vector
+ void GetUIFamilies(std::vector<PangoFontFamily *>& out);
+ // Retrieves style information about a family in a newly allocated GList.
+ GList* GetUIStyles(PangoFontFamily * in);
/// Retrieve a font_instance from a style object, first trying to use the font-specification, the CSS information
font_instance* FaceFromStyle(SPStyle const *style);
@@ -127,7 +130,6 @@ public:
int variant=PANGO_VARIANT_NORMAL, int style=PANGO_STYLE_NORMAL,
int weight=PANGO_WEIGHT_NORMAL, int stretch=PANGO_STRETCH_NORMAL,
int size=10, int spacing=0);
- font_instance* Face(char const *family, NRTypePosDef apos);
/// Semi-private: tells the font_factory taht the font_instance 'who' has died and should be removed from loadedFaces
void UnrefFace(font_instance* who);
@@ -138,19 +140,37 @@ public:
private:
void* loadedPtr;
+
+ // The following two commented out maps were an attempt to allow Inkscape to use font faces
+ // that could not be distinguished by CSS values alone. In practice, they never were that
+ // useful as PangoFontDescription, which is used throughout our code, cannot distinguish
+ // between faces anymore than raw CSS values (with the exception of two additional weight
+ // values).
+ //
+ // During various works, for example to handle font-family lists and fonts that are not
+ // installed on the system, the code has become less reliant on these maps. And in the work to
+ // catch style information to speed up start up times, the maps were not being filled.
+ // I've removed all code that used these maps as of Oct 2014 in the experimental branch.
+ // The commented out maps are left here as a reminder of the path that was attempted.
+ //
+ // One possible method to keep track of font faces would be to use the 'display name', keeping
+ // pointers to the appropriate PangoFontFace. The font_factory loadedFaces map indexing would
+ // have to be changed to incorporate 'display name' (InkscapeFontDescription?).
+
+
// These two maps are used for translating between what's in the UI and a pango
// font description. This is necessary because Pango cannot always
// reproduce these structures from the names it gave us in the first place.
// Key: A string produced by font_factory::ConstructFontSpecification
// Value: The associated PangoFontDescription
- typedef std::map<Glib::ustring, PangoFontDescription *> PangoStringToDescrMap;
- PangoStringToDescrMap fontInstanceMap;
+ // typedef std::map<Glib::ustring, PangoFontDescription *> PangoStringToDescrMap;
+ // PangoStringToDescrMap fontInstanceMap;
// Key: Family name in UI + Style name in UI
// Value: The associated string that should be produced with font_factory::ConstructFontSpecification
- typedef std::map<Glib::ustring, Glib::ustring> UIStringToPangoStringMap;
- UIStringToPangoStringMap fontStringMap;
+ // typedef std::map<Glib::ustring, Glib::ustring> UIStringToPangoStringMap;
+ // UIStringToPangoStringMap fontStringMap;
};
@@ -166,4 +186,4 @@ private:
fill-column:99
End:
*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8 :
diff --git a/src/libnrtype/FontInstance.cpp b/src/libnrtype/FontInstance.cpp
index 20eca6740..a5572c517 100644
--- a/src/libnrtype/FontInstance.cpp
+++ b/src/libnrtype/FontInstance.cpp
@@ -239,151 +239,6 @@ void font_instance::Unref(void)
}
}
-unsigned int font_instance::Name(gchar *str, unsigned int size)
-{
- return Attribute("name", str, size);
-}
-
-unsigned int font_instance::Family(gchar *str, unsigned int size)
-{
- return Attribute("family", str, size);
-}
-
-unsigned int font_instance::PSName(gchar *str, unsigned int size)
-{
- return Attribute("psname", str, size);
-}
-
-unsigned int font_instance::Attribute(const gchar *key, gchar *str, unsigned int size)
-{
- if ( descr == NULL ) {
- if ( size > 0 ) {
- str[0]=0;
- }
- return 0;
- }
- char* res=NULL;
- bool free_res=false;
-
- if ( strcmp(key,"name") == 0 ) {
- PangoFontDescription* td=pango_font_description_copy(descr);
- pango_font_description_unset_fields (td, PANGO_FONT_MASK_SIZE);
- res=pango_font_description_to_string (td);
- pango_font_description_free(td);
- free_res=true;
- } else if ( strcmp(key,"psname") == 0 ) {
-#ifndef USE_PANGO_WIN32
- res = (char *) FT_Get_Postscript_Name (theFace); // that's the main method, seems to always work
-#endif
- free_res=false;
- if (res == NULL) { // a very limited workaround, only bold, italic, and oblique will work
- PangoStyle style=pango_font_description_get_style(descr);
- bool i = (style == PANGO_STYLE_ITALIC);
- bool o = (style == PANGO_STYLE_OBLIQUE);
- PangoWeight weight=pango_font_description_get_weight(descr);
- bool b = (weight >= PANGO_WEIGHT_BOLD);
-
- res = g_strdup_printf ("%s%s%s%s",
- sp_font_description_get_family(descr),
- (b || i || o) ? "-" : "",
- (b) ? "Bold" : "",
- (i) ? "Italic" : ((o) ? "Oblique" : "") );
- free_res = true;
- }
- } else if ( strcmp(key,"family") == 0 ) {
- res=(char*)sp_font_description_get_family(descr);
- free_res=false;
- } else if ( strcmp(key,"style") == 0 ) {
- PangoStyle v=pango_font_description_get_style(descr);
- if ( v == PANGO_STYLE_ITALIC ) {
- res=(char*)"italic";
- } else if ( v == PANGO_STYLE_OBLIQUE ) {
- res=(char*)"oblique";
- } else {
- res=(char*)"normal";
- }
- free_res=false;
- } else if ( strcmp(key,"weight") == 0 ) {
- PangoWeight v=pango_font_description_get_weight(descr);
- if ( v <= PANGO_WEIGHT_THIN ) {
- res=(char*)"100";
- } else if ( v <= PANGO_WEIGHT_ULTRALIGHT ) {
- res=(char*)"200";
- } else if ( v <= PANGO_WEIGHT_LIGHT ) {
- res=(char*)"300";
- } else if ( v <= PANGO_WEIGHT_BOOK ) {
- res=(char*)"380";
- } else if ( v <= PANGO_WEIGHT_NORMAL ) {
- res=(char*)"normal";
- } else if ( v <= PANGO_WEIGHT_MEDIUM ) {
- res=(char*)"500";
- } else if ( v <= PANGO_WEIGHT_SEMIBOLD ) {
- res=(char*)"600";
- } else if ( v <= PANGO_WEIGHT_BOLD ) {
- res=(char*)"bold";
- } else if ( v <= PANGO_WEIGHT_ULTRABOLD ) {
- res=(char*)"800";
- } else { // HEAVY NB: Pango defines ULTRAHEAVY = 1000 but not CSS2
- res=(char*)"900";
- }
- free_res=false;
- } else if ( strcmp(key,"stretch") == 0 ) {
- PangoStretch v=pango_font_description_get_stretch(descr);
- if ( v <= PANGO_STRETCH_EXTRA_CONDENSED ) {
- res=(char*)"extra-condensed";
- } else if ( v <= PANGO_STRETCH_CONDENSED ) {
- res=(char*)"condensed";
- } else if ( v <= PANGO_STRETCH_SEMI_CONDENSED ) {
- res=(char*)"semi-condensed";
- } else if ( v <= PANGO_STRETCH_NORMAL ) {
- res=(char*)"normal";
- } else if ( v <= PANGO_STRETCH_SEMI_EXPANDED ) {
- res=(char*)"semi-expanded";
- } else if ( v <= PANGO_STRETCH_EXPANDED ) {
- res=(char*)"expanded";
- } else {
- res=(char*)"extra-expanded";
- }
- free_res=false;
- } else if ( strcmp(key,"variant") == 0 ) {
- PangoVariant v=pango_font_description_get_variant(descr);
- if ( v == PANGO_VARIANT_SMALL_CAPS ) {
- res=(char*)"small-caps";
- } else {
- res=(char*)"normal";
- }
- free_res=false;
- } else {
- res = NULL;
- free_res=false;
- }
- if ( res == NULL ) {
- if ( size > 0 ) {
- str[0] = 0;
- }
- return 0;
- }
-
- if (res) {
- unsigned int len=strlen(res);
- unsigned int rlen=(size-1<len)?size-1:len;
- if ( str ) {
- if ( rlen > 0 ) {
- memcpy(str, res, rlen);
- }
- if ( size > 0 ) {
- str[rlen] = 0;
- }
- }
- if (free_res) {
- g_free(res);
- res = 0;
- }
- return len;
- }
- return 0;
-}
-
void font_instance::InitTheFace()
{
if (theFace == NULL && pFont != NULL) {
diff --git a/src/libnrtype/Layout-TNG-Compute.cpp b/src/libnrtype/Layout-TNG-Compute.cpp
index 973db0165..bd1acbe46 100644
--- a/src/libnrtype/Layout-TNG-Compute.cpp
+++ b/src/libnrtype/Layout-TNG-Compute.cpp
@@ -704,6 +704,7 @@ static void dumpUnbrokenSpans(ParagraphInfo *para){
// create the Layout::Character(s)
double advance_width = new_glyph.width;
if (newcluster){
+ newcluster = 0;
// find where the text ends for this log_cluster
end_byte = it_span->start.iter_span->text_bytes; // Upper limit
for(int next_glyph_index = glyph_index+1; next_glyph_index < unbroken_span.glyph_string->num_glyphs; next_glyph_index++){
@@ -751,18 +752,15 @@ static void dumpUnbrokenSpans(ParagraphInfo *para){
log_cluster_size_chars--;
}
- if (newcluster){
- advance_width *= direction_sign;
- if (new_span.direction != para.direction) {
- counter_directional_width_remaining -= advance_width;
- x -= advance_width;
- x_in_span_last -= advance_width;
- } else {
- x += advance_width;
- x_in_span_last += advance_width;
- }
+ advance_width *= direction_sign;
+ if (new_span.direction != para.direction) {
+ counter_directional_width_remaining -= advance_width;
+ x -= advance_width;
+ x_in_span_last -= advance_width;
+ } else {
+ x += advance_width;
+ x_in_span_last += advance_width;
}
- newcluster = 0;
}
} else if (_flow._input_stream[unbroken_span.input_index]->Type() == CONTROL_CODE) {
x += static_cast<InputStreamControlCode const *>(_flow._input_stream[unbroken_span.input_index])->width;
@@ -854,6 +852,8 @@ void Layout::Calculator::BrokenSpan::setZero()
end_glyph_index = start_glyph_index = 0;
ends_with_whitespace = false;
each_whitespace_width = 0.0;
+ letter_spacing = 0.0;
+ word_spacing = 0.0;
}
template<typename T> void Layout::Calculator::ParagraphInfo::free_sequence(T &seq)
@@ -1078,7 +1078,9 @@ void Layout::Calculator::_computeFontLineHeight(font_instance *font, double font
bool compareGlyphWidth(const PangoGlyphInfo &a, const PangoGlyphInfo &b)
{
- return (a.geometry.width > b.geometry.width);
+ bool retval = false;
+ if ( b.geometry.width == 0 && (a.geometry.width > 0))retval = true;
+ return (retval);
}
@@ -1225,13 +1227,27 @@ unsigned Layout::Calculator::_buildSpansForPara(ParagraphInfo *para) const
/*
CAREFUL, within a log_cluster the order of glyphs may not map 1:1, or
even in the same order, to the original unicode characters!!! Among
- other things, diacritical mark glyphs can end up in front of the base
- character. That makes determining kerning, even approximately, difficult
- later on. To resolve this somewhat sort the glyphs with the same
- log_cluster into descending order by width. In theory there should be 1
- that is nonzero, and N that are zero. The order of the zero width ones
- does not matter. Sort the glyphs before copying. If ligatures other than with
- Mark, nonspacing are ever implemented in Pango this will screw up, for instance
+ other things, diacritical mark glyphs can end up sequentially in front of the base
+ character glyph. That makes determining kerning, even approximately, difficult
+ later on.
+
+ To resolve this to the extent possible sort the glyphs within the same
+ log_cluster into descending order by width in a special manner before copying. Diacritical marks
+ and similar have zero width and the glyph they modify has nonzero width. The order
+ of the zero width ones does not matter. A logical cluster is sorted into sequential order
+ [base] [zw_modifier1] [zw_modifier2]
+ where all the modifiers have zero width and the base does not. This works for languages like Hebrew.
+
+ Pango also creates log clusters for languages like Telugu having many glyphs with nonzero widths.
+ Since these are nonzero, their order is not modified.
+
+ If some language mixes these modes, having a log cluster having something like
+ [base1] [zw_modifier1] [base2] [zw_modifier2]
+ the result will be incorrect:
+ base1] [base2] [zw_modifier1] [zw_modifier2]
+
+
+ If ligatures other than with Mark, nonspacing are ever implemented in Pango this will screw up, for instance
changing "fi" to "if".
*/
if(j - i){
@@ -1256,6 +1272,7 @@ unsigned Layout::Calculator::_buildSpansForPara(ParagraphInfo *para) const
while( (j < nglyphs-1) &&
(new_span.glyph_string->log_clusters[j+1] == new_span.glyph_string->log_clusters[i])
)j++;
+ /* see note in preceding section */
if(j - i){
std::sort(&(new_span.glyph_string->glyphs[i]), &(new_span.glyph_string->glyphs[j+1]), compareGlyphWidth);
}
diff --git a/src/libnrtype/Layout-TNG-Input.cpp b/src/libnrtype/Layout-TNG-Input.cpp
index cb3e6f620..fa1e8c11b 100644
--- a/src/libnrtype/Layout-TNG-Input.cpp
+++ b/src/libnrtype/Layout-TNG-Input.cpp
@@ -286,16 +286,15 @@ font_instance *Layout::InputStreamTextSource::styleGetFontInstance() const
PangoFontDescription *Layout::InputStreamTextSource::styleGetFontDescription() const
{
- if (style->text == NULL) return NULL;
PangoFontDescription *descr = pango_font_description_new();
// Pango can't cope with spaces before or after the commas - let's remove them.
// this code is not exactly unicode-safe, but it's similar to what's done in
// pango, so it's not the limiting factor
Glib::ustring family;
- if (style->text->font_family.value == NULL) {
+ if (style->font_family.value == NULL) {
family = "sans-serif";
} else {
- gchar **families = g_strsplit(style->text->font_family.value, ",", -1);
+ gchar **families = g_strsplit(style->font_family.value, ",", -1);
if (families) {
for (gchar **f = families ; *f ; ++f) {
g_strstrip(*f);
diff --git a/src/libnrtype/Layout-TNG-Output.cpp b/src/libnrtype/Layout-TNG-Output.cpp
index 77534e706..61a141cc3 100644
--- a/src/libnrtype/Layout-TNG-Output.cpp
+++ b/src/libnrtype/Layout-TNG-Output.cpp
@@ -511,6 +511,9 @@ static char const *weight_to_text(PangoWeight w)
case PANGO_WEIGHT_THIN : return "thin";
case PANGO_WEIGHT_ULTRALIGHT: return "ultralight";
case PANGO_WEIGHT_LIGHT : return "light";
+#if PANGO_VERSION_CHECK(1,36,6)
+ case PANGO_WEIGHT_SEMILIGHT : return "semilight";
+#endif
case PANGO_WEIGHT_BOOK : return "book";
case PANGO_WEIGHT_NORMAL : return "normalweight";
case PANGO_WEIGHT_MEDIUM : return "medium";
diff --git a/src/libnrtype/Layout-TNG.h b/src/libnrtype/Layout-TNG.h
index c3ccbffb5..fd5bbfaef 100644
--- a/src/libnrtype/Layout-TNG.h
+++ b/src/libnrtype/Layout-TNG.h
@@ -34,7 +34,7 @@ namespace Inkscape {
using Inkscape::Extension::Internal::CairoRenderContext;
#endif
-struct SPStyle;
+class SPStyle;
class Shape;
struct SPPrintContext;
class SVGLength;
@@ -481,6 +481,7 @@ public:
from a call to appendText() then the optional \a text_iterator
parameter is set to point to the actual character, otherwise
\a text_iterator is unaltered. */
+ // TODO FIXME a void* cookie is a very unsafe design, and C++ makes it unnecessary.
void getSourceOfCharacter(iterator const &it, void **source_cookie, Glib::ustring::iterator *text_iterator = NULL) const;
/** For latin text, the left side of the character, on the baseline */
diff --git a/src/libnrtype/Makefile_insert b/src/libnrtype/Makefile_insert
index 0ce8f1fd5..ab9465daa 100644
--- a/src/libnrtype/Makefile_insert
+++ b/src/libnrtype/Makefile_insert
@@ -2,13 +2,9 @@
ink_common_sources += \
libnrtype/boundary-type.h \
- libnrtype/font-style-to-pos.cpp \
- libnrtype/font-style-to-pos.h \
libnrtype/font-glyph.h \
libnrtype/font-instance.h \
libnrtype/font-style.h \
- libnrtype/nr-type-pos-def.cpp \
- libnrtype/nr-type-pos-def.h \
libnrtype/nr-type-primitives.cpp \
libnrtype/nr-type-primitives.h \
libnrtype/FontFactory.cpp \
diff --git a/src/libnrtype/font-instance.h b/src/libnrtype/font-instance.h
index 75106617b..2c7d1ce46 100644
--- a/src/libnrtype/font-instance.h
+++ b/src/libnrtype/font-instance.h
@@ -65,12 +65,6 @@ public:
// for generating slanted cursors for oblique fonts
Geom::OptRect BBox(int glyph_id);
- // attribute queries
- unsigned Name(gchar *str, unsigned size);
- unsigned PSName(gchar *str, unsigned size);
- unsigned Family(gchar *str, unsigned size);
- unsigned Attribute(gchar const *key, gchar *str, unsigned size);
-
private:
void FreeTheFace();
diff --git a/src/libnrtype/font-lister.cpp b/src/libnrtype/font-lister.cpp
index 89d0cb037..fad06cd00 100644
--- a/src/libnrtype/font-lister.cpp
+++ b/src/libnrtype/font-lister.cpp
@@ -1,9 +1,9 @@
#ifdef HAVE_CONFIG_H
-# include <config.h>
+#include <config.h>
#endif
-#include <gtkmm/treemodel.h>
#include <gtkmm/liststore.h>
+#include <gtkmm/treemodel.h>
#include <libnrtype/font-instance.h>
#include <libnrtype/TextWrapper.h>
@@ -25,371 +25,434 @@
//#define DEBUG_FONT
-namespace Inkscape
+// CSS dictates that font family names are case insensitive.
+// This should really implement full Unicode case unfolding.
+bool familyNamesAreEqual(const Glib::ustring &a, const Glib::ustring &b)
{
- FontLister::FontLister ()
- {
- font_list_store = Gtk::ListStore::create (FontList);
- font_list_store->freeze_notify();
-
- FamilyToStylesMap familyStyleMap;
- font_factory::Default()->GetUIFamiliesAndStyles(&familyStyleMap);
-
- // Grab the family names into a list and then sort them
- std::list<Glib::ustring> familyList;
- for (FamilyToStylesMap::iterator iter = familyStyleMap.begin();
- iter != familyStyleMap.end();
- ++iter) {
- familyList.push_back((*iter).first);
+ return (a.casefold().compare(b.casefold()) == 0);
+}
+
+static const char* sp_font_family_get_name(PangoFontFamily* family)
+{
+ const char* name = pango_font_family_get_name(family);
+ if (strncmp(name, "Sans", 4) == 0 && strlen(name) == 4)
+ return "sans-serif";
+ if (strncmp(name, "Serif", 5) == 0 && strlen(name) == 5)
+ return "serif";
+ if (strncmp(name, "Monospace", 9) == 0 && strlen(name) == 9)
+ return "monospace";
+ return name;
+}
+
+namespace Inkscape {
+
+FontLister::FontLister()
+{
+ font_list_store = Gtk::ListStore::create(FontList);
+ font_list_store->freeze_notify();
+
+ /* Create default styles for use when font-family is unknown on system. */
+ default_styles = g_list_append(NULL, new StyleNames("Normal"));
+ default_styles = g_list_append(default_styles, new StyleNames("Italic"));
+ default_styles = g_list_append(default_styles, new StyleNames("Bold"));
+ default_styles = g_list_append(default_styles, new StyleNames("Bold Italic"));
+
+ // Get sorted font families from Pango
+ std::vector<PangoFontFamily *> familyVector;
+ font_factory::Default()->GetUIFamilies(familyVector);
+
+ // Traverse through the family names and set up the list store
+ for (size_t i = 0; i < familyVector.size(); ++i) {
+ const char* displayName = sp_font_family_get_name(familyVector[i]);
+
+ if (displayName == 0 || *displayName == '\0') {
+ continue;
}
- familyList.sort();
- // Traverse through the family names and set up the list store (note that
- // the styles list that are the map's values are already sorted)
- while (!familyList.empty()) {
- Glib::ustring familyName = familyList.front();
- familyList.pop_front();
-
- if (!familyName.empty()) {
- Gtk::TreeModel::iterator treeModelIter = font_list_store->append();
- //(*treeModelIter)[FontList.family] = reinterpret_cast<const char*>(g_strdup(familyName.c_str()));
- (*treeModelIter)[FontList.family] = familyName;
-
- // Now go through the styles
- GList *styles = NULL;
- std::list<Glib::ustring> &styleStrings = familyStyleMap[familyName];
- for (std::list<Glib::ustring>::iterator it=styleStrings.begin();
- it != styleStrings.end();
- ++it) {
- styles = g_list_append(styles, g_strdup((*it).c_str()));
+ Glib::ustring familyName = displayName;
+ if (!familyName.empty()) {
+ Gtk::TreeModel::iterator treeModelIter = font_list_store->append();
+ (*treeModelIter)[FontList.family] = familyName;
+
+ // we don't set this now (too slow) but the style will be cached if the user
+ // ever decides to use this font
+ (*treeModelIter)[FontList.styles] = NULL;
+ // store the pango representation for generating the style
+ (*treeModelIter)[FontList.pango_family] = familyVector[i];
+ (*treeModelIter)[FontList.onSystem] = true;
+ }
+ }
+
+ current_family_row = 0;
+ current_family = "sans-serif";
+ current_style = "Normal";
+ current_fontspec = "sans-serif"; // Empty style -> Normal
+ current_fontspec_system = "Sans";
+
+ font_list_store->thaw_notify();
+
+ style_list_store = Gtk::ListStore::create(FontStyleList);
+
+ // Initialize style store with defaults
+ style_list_store->freeze_notify();
+ style_list_store->clear();
+ for (GList *l = default_styles; l; l = l->next) {
+ Gtk::TreeModel::iterator treeModelIter = style_list_store->append();
+ (*treeModelIter)[FontStyleList.cssStyle] = ((StyleNames *)l->data)->CssName;
+ (*treeModelIter)[FontStyleList.displayStyle] = ((StyleNames *)l->data)->DisplayName;
+ }
+ style_list_store->thaw_notify();
+}
+
+FontLister::~FontLister()
+{
+ // Delete default_styles
+ for (GList *l = default_styles; l; l = l->next) {
+ delete ((StyleNames *)l->data);
+ }
+
+ // Delete other styles
+ Gtk::TreeModel::iterator iter = font_list_store->get_iter("0");
+ while (iter != font_list_store->children().end()) {
+ Gtk::TreeModel::Row row = *iter;
+ GList *styles = row[FontList.styles];
+ for (GList *l = styles; l; l = l->next) {
+ delete ((StyleNames *)l->data);
+ }
+ ++iter;
+ }
+}
+
+FontLister *FontLister::get_instance()
+{
+ static Inkscape::FontLister *instance = new Inkscape::FontLister();
+ return instance;
+}
+
+void FontLister::ensureRowStyles(GtkTreeModel* model, GtkTreeIter const* iterator)
+{
+ Gtk::TreeIter iter(model, iterator);
+ Gtk::TreeModel::Row row = *iter;
+ if (!row[FontList.styles]) {
+ if (row[FontList.pango_family]) {
+ row[FontList.styles] = font_factory::Default()->GetUIStyles(row[FontList.pango_family]);
+ }
+ }
+}
+
+// Example of how to use "foreach_iter"
+// bool
+// FontLister::print_document_font( const Gtk::TreeModel::iterator &iter ) {
+// Gtk::TreeModel::Row row = *iter;
+// if( !row[FontList.onSystem] ) {
+// std::cout << " Not on system: " << row[FontList.family] << std::endl;
+// return false;
+// }
+// return true;
+// }
+// font_list_store->foreach_iter( sigc::mem_fun(*this, &FontLister::print_document_font ));
+
+/* Used to insert a font that was not in the document and not on the system into the font list. */
+void FontLister::insert_font_family(Glib::ustring new_family)
+{
+ GList *styles = default_styles;
+
+ /* In case this is a fallback list, check if first font-family on system. */
+ std::vector<Glib::ustring> tokens = Glib::Regex::split_simple(",", new_family);
+ if (!tokens.empty() && !tokens[0].empty()) {
+ Gtk::TreeModel::iterator iter2 = font_list_store->get_iter("0");
+ while (iter2 != font_list_store->children().end()) {
+ Gtk::TreeModel::Row row = *iter2;
+ if (row[FontList.onSystem] && familyNamesAreEqual(tokens[0], row[FontList.family])) {
+ if (!row[FontList.styles]) {
+ row[FontList.styles] = font_factory::Default()->GetUIStyles(row[FontList.pango_family]);
}
-
- (*treeModelIter)[FontList.styles] = styles;
- (*treeModelIter)[FontList.onSystem] = true;
+ styles = row[FontList.styles];
+ break;
}
+ ++iter2;
}
- current_family_row = 0;
- current_family = "sans-serif";
- current_style = "Normal";
- current_fontspec = "sans-serif"; // Empty style -> Normal
- current_fontspec_system = "Sans";
-
- /* Create default styles for use when font-family is unknown on system. */
- default_styles = g_list_append( NULL, g_strdup("Normal") );
- default_styles = g_list_append( default_styles, g_strdup("Italic") );
- default_styles = g_list_append( default_styles, g_strdup("Bold") );
- default_styles = g_list_append( default_styles, g_strdup("Bold Italic") );
+ }
- font_list_store->thaw_notify();
+ Gtk::TreeModel::iterator treeModelIter = font_list_store->prepend();
+ (*treeModelIter)[FontList.family] = new_family;
+ (*treeModelIter)[FontList.styles] = styles;
+ (*treeModelIter)[FontList.onSystem] = false;
+}
- style_list_store = Gtk::ListStore::create (FontStyleList);
+void FontLister::update_font_list(SPDocument *document)
+{
+ SPObject *r = document->getRoot();
+ if (!r) {
+ return;
}
- // Example of how to use "foreach_iter"
- // bool
- // FontLister::print_document_font( const Gtk::TreeModel::iterator &iter ) {
- // Gtk::TreeModel::Row row = *iter;
- // if( !row[FontList.onSystem] ) {
- // std::cout << " Not on system: " << row[FontList.family] << std::endl;
- // return false;
- // }
- // return true;
- // }
- // font_list_store->foreach_iter( sigc::mem_fun(*this, &FontLister::print_document_font ));
-
- void
- FontLister::update_font_list( SPDocument* document ) {
-
- SPObject *r = document->getRoot();
- if( !r ) {
- return;
- }
-
- font_list_store->freeze_notify();
-
- /* Find if current row is in document or system part of list */
- gboolean row_is_system = false;
- if( current_family_row > -1 ) {
- Gtk::TreePath path;
- path.push_back( current_family_row );
- Gtk::TreeModel::iterator iter = font_list_store->get_iter( path );
- if( iter ) {
- row_is_system = (*iter)[FontList.onSystem];
- // std::cout << " In: row: " << current_family_row << " " << (*iter)[FontList.family] << std::endl;
- }
- }
-
- /* Clear all old document font-family entries */
- Gtk::TreeModel::iterator iter = font_list_store->get_iter( "0" );
- while( iter != font_list_store->children().end() ) {
- Gtk::TreeModel::Row row = *iter;
- if( !row[FontList.onSystem] ) {
- // std::cout << " Not on system: " << row[FontList.family] << std::endl;
- iter = font_list_store->erase( iter );
- } else {
- // std::cout << " First on system: " << row[FontList.family] << std::endl;
- break;
- }
- }
-
- /* Get "font-family"s used in document. */
- std::list<Glib::ustring> fontfamilies;
- update_font_list_recursive( r, &fontfamilies );
-
- fontfamilies.sort();
- fontfamilies.unique();
- fontfamilies.reverse();
-
- /* Insert separator */
- if( !fontfamilies.empty() ) {
- Gtk::TreeModel::iterator treeModelIter = font_list_store->prepend();
- (*treeModelIter)[FontList.family] = "#";
- (*treeModelIter)[FontList.onSystem] = false;
- }
-
- /* Insert font-family's in document. */
- std::list<Glib::ustring>::iterator i;
- for( i = fontfamilies.begin(); i != fontfamilies.end(); ++i) {
-
- GList *styles = default_styles;
+ font_list_store->freeze_notify();
+
+ /* Find if current row is in document or system part of list */
+ gboolean row_is_system = false;
+ if (current_family_row > -1) {
+ Gtk::TreePath path;
+ path.push_back(current_family_row);
+ Gtk::TreeModel::iterator iter = font_list_store->get_iter(path);
+ if (iter) {
+ row_is_system = (*iter)[FontList.onSystem];
+ // std::cout << " In: row: " << current_family_row << " " << (*iter)[FontList.family] << std::endl;
+ }
+ }
- /* See if font-family (or first in fallback list) is on system. If so, get styles. */
- std::vector<Glib::ustring> tokens = Glib::Regex::split_simple(",", *i );
- if( !tokens.empty() && !tokens[0].empty() ) {
-
- Gtk::TreeModel::iterator iter2 = font_list_store->get_iter( "0" );
- while( iter2 != font_list_store->children().end() ) {
- Gtk::TreeModel::Row row = *iter2;
- if( row[FontList.onSystem] && tokens[0].compare( row[FontList.family] ) == 0 ) {
- styles = row[FontList.styles];
- break;
- }
- ++iter2;
- }
- }
-
- Gtk::TreeModel::iterator treeModelIter = font_list_store->prepend();
- (*treeModelIter)[FontList.family] = reinterpret_cast<const char*>(g_strdup((*i).c_str()));
- (*treeModelIter)[FontList.styles] = styles;
- (*treeModelIter)[FontList.onSystem] = false;
- }
-
- /* Now we do a song and dance to find the correct row as the row corresponding
- * to the current_family may have changed. We can't simply search for the
- * family name in the list since it can occur twice, once in the document
- * font family part and once in the system font family part. Above we determined
- * which part it is in.
- */
- if( current_family_row > -1 ) {
- int start = 0;
- if( row_is_system ) start = fontfamilies.size();
- int length = font_list_store->children().size();
- for( int i = 0; i < length; ++i ) {
- int row = i + start;
- if( row >= length ) row -= length;
- Gtk::TreePath path;
- path.push_back( row );
- Gtk::TreeModel::iterator iter = font_list_store->get_iter( path );
- if( iter ) {
- if( current_family.compare( (*iter)[FontList.family] ) == 0 ) {
- current_family_row = row;
- break;
- }
- }
- }
- }
- // std::cout << " Out: row: " << current_family_row << " " << current_family << std::endl;
-
- font_list_store->thaw_notify();
+ /* Clear all old document font-family entries */
+ Gtk::TreeModel::iterator iter = font_list_store->get_iter("0");
+ while (iter != font_list_store->children().end()) {
+ Gtk::TreeModel::Row row = *iter;
+ if (!row[FontList.onSystem]) {
+ // std::cout << " Not on system: " << row[FontList.family] << std::endl;
+ iter = font_list_store->erase(iter);
+ } else {
+ // std::cout << " First on system: " << row[FontList.family] << std::endl;
+ break;
+ }
}
- // FIXME: why do we parse the style attribute instead of the object's SPStyle?
- void
- FontLister::update_font_list_recursive( SPObject *r, std::list<Glib::ustring> *l ) {
+ /* Get "font-family"s used in document. */
+ std::list<Glib::ustring> fontfamilies;
+ update_font_list_recursive(r, &fontfamilies);
- const gchar *style = r->getRepr()->attribute("style");
- if( style != NULL ) {
+ fontfamilies.sort();
+ fontfamilies.unique();
+ fontfamilies.reverse();
- std::vector<Glib::ustring> tokens = Glib::Regex::split_simple(";", style );
- for( size_t i=0; i < tokens.size(); ++i ) {
- Glib::ustring token = tokens[i];
- size_t found = token.find("font-family:");
+ /* Insert separator */
+ if (!fontfamilies.empty()) {
+ Gtk::TreeModel::iterator treeModelIter = font_list_store->prepend();
+ (*treeModelIter)[FontList.family] = "#";
+ (*treeModelIter)[FontList.onSystem] = false;
+ }
- if( found != Glib::ustring::npos ) {
+ /* Insert font-family's in document. */
+ std::list<Glib::ustring>::iterator i;
+ for (i = fontfamilies.begin(); i != fontfamilies.end(); ++i) {
- // Remove "font-family:"
- token.erase(found,12);
+ GList *styles = default_styles;
- // Remove any leading single or double quote
- if( token[0] == '\'' || token[0] == '"' ) {
- token.erase(0,1);
- }
+ /* See if font-family (or first in fallback list) is on system. If so, get styles. */
+ std::vector<Glib::ustring> tokens = Glib::Regex::split_simple(",", *i);
+ if (!tokens.empty() && !tokens[0].empty()) {
+
+ Gtk::TreeModel::iterator iter2 = font_list_store->get_iter("0");
+ while (iter2 != font_list_store->children().end()) {
+ Gtk::TreeModel::Row row = *iter2;
+ if (row[FontList.onSystem] && familyNamesAreEqual(tokens[0], row[FontList.family])) {
+ if (!row[FontList.styles]) {
+ row[FontList.styles] = font_factory::Default()->GetUIStyles(row[FontList.pango_family]);
+ }
+ styles = row[FontList.styles];
+ break;
+ }
+ ++iter2;
+ }
+ }
+
+ Gtk::TreeModel::iterator treeModelIter = font_list_store->prepend();
+ (*treeModelIter)[FontList.family] = reinterpret_cast<const char *>(g_strdup((*i).c_str()));
+ (*treeModelIter)[FontList.styles] = styles;
+ (*treeModelIter)[FontList.onSystem] = false;
- // Remove any trailing single or double quote
- if( token[token.length()-1] == '\'' || token[token.length()-1] == '"' ) {
- token.erase(token.length()-1);
- }
+ }
- l->push_back( token );
- }
+ /* Now we do a song and dance to find the correct row as the row corresponding
+ * to the current_family may have changed. We can't simply search for the
+ * family name in the list since it can occur twice, once in the document
+ * font family part and once in the system font family part. Above we determined
+ * which part it is in.
+ */
+ if (current_family_row > -1) {
+ int start = 0;
+ if (row_is_system)
+ start = fontfamilies.size();
+ int length = font_list_store->children().size();
+ for (int i = 0; i < length; ++i) {
+ int row = i + start;
+ if (row >= length)
+ row -= length;
+ Gtk::TreePath path;
+ path.push_back(row);
+ Gtk::TreeModel::iterator iter = font_list_store->get_iter(path);
+ if (iter) {
+ if (familyNamesAreEqual(current_family, (*iter)[FontList.family])) {
+ current_family_row = row;
+ break;
+ }
+ }
}
- }
+ }
+ // std::cout << " Out: row: " << current_family_row << " " << current_family << std::endl;
+
+ font_list_store->thaw_notify();
+}
- for (SPObject *child = r->firstChild(); child; child = child->getNext()) {
- update_font_list_recursive( child, l );
- }
+void FontLister::update_font_list_recursive(SPObject *r, std::list<Glib::ustring> *l)
+{
+ const gchar *font_family = r->style->font_family.value;
+ if (font_family) {
+ l->push_back(Glib::ustring(font_family));
}
- Glib::ustring
- FontLister::canonize_fontspec( Glib::ustring fontspec ) {
-
- // Pass fontspec to and back from Pango to get a the fontspec in
- // canonical form. -inkscape-font-specification relies on the
- // Pango constructed fontspec not changing form. If it does,
- // this is the place to fix it.
- PangoFontDescription *descr = pango_font_description_from_string( fontspec.c_str() );
- gchar* canonized = pango_font_description_to_string ( descr );
- Glib::ustring Canonized = canonized;
- g_free( canonized );
- pango_font_description_free( descr );
-
- // Pango canonized strings remove space after comma between family names. Put it back.
- size_t i = 0;
- while( (i = Canonized.find(",", i)) != std::string::npos) {
- Canonized.replace(i, 1, ", ");
- i += 2;
- }
-
- return Canonized;
+ for (SPObject *child = r->firstChild(); child; child = child->getNext()) {
+ update_font_list_recursive(child, l);
}
+}
- Glib::ustring
- FontLister::system_fontspec( Glib::ustring fontspec ) {
+Glib::ustring FontLister::canonize_fontspec(Glib::ustring fontspec)
+{
- // Find what Pango thinks is the closest match.
- Glib::ustring out = fontspec;
+ // Pass fontspec to and back from Pango to get a the fontspec in
+ // canonical form. -inkscape-font-specification relies on the
+ // Pango constructed fontspec not changing form. If it does,
+ // this is the place to fix it.
+ PangoFontDescription *descr = pango_font_description_from_string(fontspec.c_str());
+ gchar *canonized = pango_font_description_to_string(descr);
+ Glib::ustring Canonized = canonized;
+ g_free(canonized);
+ pango_font_description_free(descr);
+
+ // Pango canonized strings remove space after comma between family names. Put it back.
+ size_t i = 0;
+ while ((i = Canonized.find(",", i)) != std::string::npos) {
+ Canonized.replace(i, 1, ", ");
+ i += 2;
+ }
+
+ return Canonized;
+}
+
+Glib::ustring FontLister::system_fontspec(Glib::ustring fontspec)
+{
- PangoFontDescription *descr = pango_font_description_from_string(fontspec.c_str());
- font_instance *res = (font_factory::Default())->Face(descr);
- if (res->pFont) {
+ // Find what Pango thinks is the closest match.
+ Glib::ustring out = fontspec;
+
+ PangoFontDescription *descr = pango_font_description_from_string(fontspec.c_str());
+ font_instance *res = (font_factory::Default())->Face(descr);
+ if (res->pFont) {
PangoFontDescription *nFaceDesc = pango_font_describe(res->pFont);
out = sp_font_description_get_family(nFaceDesc);
- }
- pango_font_description_free(descr);
-
- return out;
}
+ pango_font_description_free(descr);
+
+ return out;
+}
- std::pair<Glib::ustring, Glib::ustring>
- FontLister::ui_from_fontspec( Glib::ustring fontspec ) {
-
- PangoFontDescription *descr = pango_font_description_from_string(fontspec.c_str());
- const gchar* family = pango_font_description_get_family(descr);
- if(!family)
- family = "sans-serif";
- Glib::ustring Family = family;
-
- // PANGO BUG...
- // A font spec of Delicious, 500 Italic should result in a family of 'Delicious'
- // and a style of 'Medium Italic'. It results instead with: a family of
- // 'Delicious, 500' with a style of 'Medium Italic'. We chop of any weight numbers
- // at the end of the family: match ",[1-9]00^".
- Glib::RefPtr<Glib::Regex> weight = Glib::Regex::create(",[1-9]00$");
- Family = weight->replace( Family, 0, "", Glib::REGEX_MATCH_PARTIAL );
-
- // Pango canonized strings remove space after comma between family names. Put it back.
- size_t i = 0;
- while( (i = Family.find(",", i)) != std::string::npos) {
- Family.replace(i, 1, ", ");
- i += 2;
- }
-
- pango_font_description_unset_fields(descr, PANGO_FONT_MASK_FAMILY);
- gchar* style = pango_font_description_to_string( descr );
- Glib::ustring Style = style;
- pango_font_description_free(descr);
- g_free( style );
-
- return std::make_pair( Family, Style );
+std::pair<Glib::ustring, Glib::ustring> FontLister::ui_from_fontspec(Glib::ustring fontspec)
+{
+ PangoFontDescription *descr = pango_font_description_from_string(fontspec.c_str());
+ const gchar *family = pango_font_description_get_family(descr);
+ if (!family)
+ family = "sans-serif";
+ Glib::ustring Family = family;
+
+ // PANGO BUG...
+ // A font spec of Delicious, 500 Italic should result in a family of 'Delicious'
+ // and a style of 'Medium Italic'. It results instead with: a family of
+ // 'Delicious, 500' with a style of 'Medium Italic'. We chop of any weight numbers
+ // at the end of the family: match ",[1-9]00^".
+ Glib::RefPtr<Glib::Regex> weight = Glib::Regex::create(",[1-9]00$");
+ Family = weight->replace(Family, 0, "", Glib::REGEX_MATCH_PARTIAL);
+
+ // Pango canonized strings remove space after comma between family names. Put it back.
+ size_t i = 0;
+ while ((i = Family.find(",", i)) != std::string::npos) {
+ Family.replace(i, 1, ", ");
+ i += 2;
}
- std::pair<Glib::ustring, Glib::ustring>
- FontLister::selection_update () {
+ pango_font_description_unset_fields(descr, PANGO_FONT_MASK_FAMILY);
+ gchar *style = pango_font_description_to_string(descr);
+ Glib::ustring Style = style;
+ pango_font_description_free(descr);
+ g_free(style);
+
+ return std::make_pair(Family, Style);
+}
+
+std::pair<Glib::ustring, Glib::ustring> FontLister::selection_update()
+{
#ifdef DEBUG_FONT
- std::cout << "\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
- std::cout << "FontLister::selection_update: entrance" << std::endl;
+ std::cout << "\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
+ std::cout << "FontLister::selection_update: entrance" << std::endl;
#endif
- // Get fontspec from a selection, preferences, or thin air.
- Glib::ustring fontspec;
- SPStyle *query = sp_style_new (SP_ACTIVE_DOCUMENT);
-
- // Directly from stored font specification.
- int result =
- sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONT_SPECIFICATION);
-
- //std::cout << " Attempting selected style" << std::endl;
- if( result != QUERY_STYLE_NOTHING && query->text->font_specification.set ) {
- fontspec = query->text->font_specification.value;
- //std::cout << " fontspec from query :" << fontspec << ":" << std::endl;
- }
-
- // From style
- if( fontspec.empty() ) {
+ // Get fontspec from a selection, preferences, or thin air.
+ Glib::ustring fontspec;
+ SPStyle *query = sp_style_new(SP_ACTIVE_DOCUMENT);
+
+ // Directly from stored font specification.
+ int result =
+ sp_desktop_query_style(SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONT_SPECIFICATION);
+
+ //std::cout << " Attempting selected style" << std::endl;
+ if (result != QUERY_STYLE_NOTHING && query->font_specification.set) {
+ fontspec = query->font_specification.value;
+ //std::cout << " fontspec from query :" << fontspec << ":" << std::endl;
+ }
+
+ // From style
+ if (fontspec.empty()) {
//std::cout << " Attempting desktop style" << std::endl;
- int rfamily = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTFAMILY);
- int rstyle = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTSTYLE);
-
- // Must have text in selection
- if( rfamily != QUERY_STYLE_NOTHING && rstyle != QUERY_STYLE_NOTHING ) {
- fontspec = fontspec_from_style( query );
- }
- //std::cout << " fontspec from style :" << fontspec << ":" << std::endl;
- }
-
- // From preferences
- if( fontspec.empty() ) {
+ int rfamily = sp_desktop_query_style(SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTFAMILY);
+ int rstyle = sp_desktop_query_style(SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTSTYLE);
+
+ // Must have text in selection
+ if (rfamily != QUERY_STYLE_NOTHING && rstyle != QUERY_STYLE_NOTHING) {
+ fontspec = fontspec_from_style(query);
+ }
+ //std::cout << " fontspec from style :" << fontspec << ":" << std::endl;
+ }
+
+ // From preferences
+ if (fontspec.empty()) {
//std::cout << " Attempting preferences" << std::endl;
sp_style_read_from_prefs(query, "/tools/text");
- fontspec = fontspec_from_style( query );
- //std::cout << " fontspec from prefs :" << fontspec << ":" << std::endl;
- }
- sp_style_unref(query);
+ fontspec = fontspec_from_style(query);
+ //std::cout << " fontspec from prefs :" << fontspec << ":" << std::endl;
+ }
+ sp_style_unref(query);
- // From thin air
- if( fontspec.empty() ) {
+ // From thin air
+ if (fontspec.empty()) {
//std::cout << " Attempting thin air" << std::endl;
- fontspec = current_family + ", " + current_style;
- //std::cout << " fontspec from thin air :" << fontspec << ":" << std::endl;
- }
-
- // Do we really need? Removes spaces between font-families.
- //current_fontspec = canonize_fontspec( fontspec );
- current_fontspec = fontspec; // Ignore for now
+ fontspec = current_family + ", " + current_style;
+ //std::cout << " fontspec from thin air :" << fontspec << ":" << std::endl;
+ }
- current_fontspec_system = system_fontspec( current_fontspec );
+ // Do we really need? Removes spaces between font-families.
+ //current_fontspec = canonize_fontspec( fontspec );
+ current_fontspec = fontspec; // Ignore for now
- std::pair<Glib::ustring, Glib::ustring> ui = ui_from_fontspec( current_fontspec );
- set_font_family( ui.first );
+ current_fontspec_system = system_fontspec(current_fontspec);
+
+ std::pair<Glib::ustring, Glib::ustring> ui = ui_from_fontspec(current_fontspec);
+ set_font_family(ui.first);
+ set_font_style(ui.second);
#ifdef DEBUG_FONT
- std::cout << " family_row: :" << current_family_row << ":" << std::endl;
- std::cout << " canonized: :" << current_fontspec << ":" << std::endl;
- std::cout << " system: :" << current_fontspec_system << ":" << std::endl;
- std::cout << " family: :" << current_family << ":" << std::endl;
- std::cout << " style: :" << current_style << ":" << std::endl;
- std::cout << "FontLister::selection_update: exit" << std::endl;
- std::cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" << std::endl;
+ std::cout << " family_row: :" << current_family_row << ":" << std::endl;
+ std::cout << " canonized: :" << current_fontspec << ":" << std::endl;
+ std::cout << " system: :" << current_fontspec_system << ":" << std::endl;
+ std::cout << " family: :" << current_family << ":" << std::endl;
+ std::cout << " style: :" << current_style << ":" << std::endl;
+ std::cout << "FontLister::selection_update: exit" << std::endl;
+ std::cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" << std::endl;
#endif
- return std::make_pair( current_family, current_style );
- }
-
+ return std::make_pair(current_family, current_style);
+}
+
// Set fontspec. If check is false, best style match will not be done.
-void FontLister::set_fontspec(Glib::ustring new_fontspec, gboolean /*check*/)
+void FontLister::set_fontspec(Glib::ustring new_fontspec, bool /*check*/)
{
- std::pair<Glib::ustring,Glib::ustring> ui = ui_from_fontspec( new_fontspec );
+ std::pair<Glib::ustring, Glib::ustring> ui = ui_from_fontspec(new_fontspec);
Glib::ustring new_family = ui.first;
Glib::ustring new_style = ui.second;
@@ -398,13 +461,13 @@ void FontLister::set_fontspec(Glib::ustring new_fontspec, gboolean /*check*/)
<< " style:" << new_style << std::endl;
#endif
- set_font_family( new_family, false );
- set_font_style( new_style );
+ set_font_family(new_family, false);
+ set_font_style(new_style);
}
// TODO: use to determine font-selector best style
-std::pair<Glib::ustring, Glib::ustring> FontLister::new_font_family (Glib::ustring new_family, gboolean /*check_style*/ )
+std::pair<Glib::ustring, Glib::ustring> FontLister::new_font_family(Glib::ustring new_family, bool /*check_style*/)
{
#ifdef DEBUG_FONT
std::cout << "\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
@@ -412,12 +475,12 @@ std::pair<Glib::ustring, Glib::ustring> FontLister::new_font_family (Glib::ustri
#endif
// No need to do anything if new family is same as old family.
- if ( new_family.compare( current_family ) == 0 ) {
+ if (familyNamesAreEqual(new_family, current_family)) {
#ifdef DEBUG_FONT
- std::cout << "FontLister::new_font_family: exit: no change in family." << std::endl;
- std::cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" << std::endl;
+ std::cout << "FontLister::new_font_family: exit: no change in family." << std::endl;
+ std::cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" << std::endl;
#endif
- return std::make_pair( current_family, current_style );
+ return std::make_pair(current_family, current_style);
}
// We need to do two things:
@@ -425,591 +488,602 @@ std::pair<Glib::ustring, Glib::ustring> FontLister::new_font_family (Glib::ustri
// 2. Select best valid style match to old style.
// For finding style list, use list of first family in font-family list.
- GList* styles = NULL;
- Gtk::TreeModel::iterator iter = font_list_store->get_iter( "0" );
- while( iter != font_list_store->children().end() ) {
+ GList *styles = NULL;
+ Gtk::TreeModel::iterator iter = font_list_store->get_iter("0");
+ while (iter != font_list_store->children().end()) {
- Gtk::TreeModel::Row row = *iter;
+ Gtk::TreeModel::Row row = *iter;
- if( new_family.compare( row[FontList.family] ) == 0 ) {
+ if (familyNamesAreEqual(new_family, row[FontList.family])) {
+ if (!row[FontList.styles]) {
+ row[FontList.styles] = font_factory::Default()->GetUIStyles(row[FontList.pango_family]);
+ }
styles = row[FontList.styles];
break;
- }
- ++iter;
+ }
+ ++iter;
}
// Newly typed in font-family may not yet be in list... use default list.
// TODO: if font-family is list, check if first family in list is on system
// and set style accordingly.
- if( styles == NULL ) {
- styles = default_styles;
+ if (styles == NULL) {
+ styles = default_styles;
}
-
+
// Update style list.
style_list_store->freeze_notify();
style_list_store->clear();
- for (GList *l=styles; l; l = l->next) {
- Gtk::TreeModel::iterator treeModelIter = style_list_store->append();
- (*treeModelIter)[FontStyleList.styles] = (char*)l->data;
+ for (GList *l = styles; l; l = l->next) {
+ Gtk::TreeModel::iterator treeModelIter = style_list_store->append();
+ (*treeModelIter)[FontStyleList.cssStyle] = ((StyleNames *)l->data)->CssName;
+ (*treeModelIter)[FontStyleList.displayStyle] = ((StyleNames *)l->data)->DisplayName;
}
style_list_store->thaw_notify();
-
+
// Find best match to the style from the old font-family to the
// styles available with the new font.
// TODO: Maybe check if an exact match exists before using Pango.
- Glib::ustring best_style = get_best_style_match( new_family, current_style );
+ Glib::ustring best_style = get_best_style_match(new_family, current_style);
#ifdef DEBUG_FONT
std::cout << "FontLister::new_font_family: exit: " << new_family << " " << best_style << std::endl;
std::cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" << std::endl;
#endif
- return std::make_pair( new_family, best_style );
+ return std::make_pair(new_family, best_style);
}
-
- std::pair<Glib::ustring, Glib::ustring>
- FontLister::set_font_family (Glib::ustring new_family, gboolean check_style) {
+
+std::pair<Glib::ustring, Glib::ustring> FontLister::set_font_family(Glib::ustring new_family, bool check_style)
+{
#ifdef DEBUG_FONT
- std::cout << "\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
- std::cout << "FontLister::set_font_family: " << new_family << std::endl;
+ std::cout << "\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
+ std::cout << "FontLister::set_font_family: " << new_family << std::endl;
#endif
- std::pair<Glib::ustring, Glib::ustring> ui = new_font_family( new_family, check_style );
- current_family = ui.first;
- current_style = ui.second;
- current_fontspec = canonize_fontspec( current_family + ", " + current_style );
- current_fontspec_system = system_fontspec( current_fontspec );
+ std::pair<Glib::ustring, Glib::ustring> ui = new_font_family(new_family, check_style);
+ current_family = ui.first;
+ current_style = ui.second;
+ current_fontspec = canonize_fontspec(current_family + ", " + current_style);
+ current_fontspec_system = system_fontspec(current_fontspec);
#ifdef DEBUG_FONT
- std::cout << " family_row: :" << current_family_row << ":" << std::endl;
- std::cout << " canonized: :" << current_fontspec << ":" << std::endl;
- std::cout << " system: :" << current_fontspec_system << ":" << std::endl;
- std::cout << " family: :" << current_family << ":" << std::endl;
- std::cout << " style: :" << current_style << ":" << std::endl;
- std::cout << "FontLister::set_font_family: end" << std::endl;
- std::cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" << std::endl;
+ std::cout << " family_row: :" << current_family_row << ":" << std::endl;
+ std::cout << " canonized: :" << current_fontspec << ":" << std::endl;
+ std::cout << " system: :" << current_fontspec_system << ":" << std::endl;
+ std::cout << " family: :" << current_family << ":" << std::endl;
+ std::cout << " style: :" << current_style << ":" << std::endl;
+ std::cout << "FontLister::set_font_family: end" << std::endl;
+ std::cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" << std::endl;
#endif
- return ui;
- }
-
+ return ui;
+}
+
- std::pair<Glib::ustring, Glib::ustring>
- FontLister::set_font_family (int row, gboolean check_style) {
+std::pair<Glib::ustring, Glib::ustring> FontLister::set_font_family(int row, bool check_style)
+{
#ifdef DEBUG_FONT
- std::cout << "\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
- std::cout << "FontLister::set_font_family( row ): " << row << std::endl;
+ std::cout << "\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
+ std::cout << "FontLister::set_font_family( row ): " << row << std::endl;
#endif
- current_family_row = row;
- Gtk::TreePath path;
- path.push_back( row );
- Glib::ustring new_family = current_family;
- Gtk::TreeModel::iterator iter = font_list_store->get_iter( path );
- if( iter ) {
- new_family = (*iter)[FontList.family];
- }
+ current_family_row = row;
+ Gtk::TreePath path;
+ path.push_back(row);
+ Glib::ustring new_family = current_family;
+ Gtk::TreeModel::iterator iter = font_list_store->get_iter(path);
+ if (iter) {
+ new_family = (*iter)[FontList.family];
+ }
- std::pair<Glib::ustring, Glib::ustring> ui = set_font_family( new_family, check_style );
+ std::pair<Glib::ustring, Glib::ustring> ui = set_font_family(new_family, check_style);
#ifdef DEBUG_FONT
- std::cout << "FontLister::set_font_family( row ): end" << std::endl;
- std::cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" << std::endl;
+ std::cout << "FontLister::set_font_family( row ): end" << std::endl;
+ std::cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" << std::endl;
#endif
- return ui;
- }
+ return ui;
+}
- void
- FontLister::set_font_style (Glib::ustring new_style) {
+void FontLister::set_font_style(Glib::ustring new_style)
+{
- // TODO: Validate input using Pango. If Pango doesn't recognize a style it will
- // attach the "invalid" style to the font-family.
+// TODO: Validate input using Pango. If Pango doesn't recognize a style it will
+// attach the "invalid" style to the font-family.
#ifdef DEBUG_FONT
- std::cout << "\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
- std::cout << "FontLister:set_font_style: " << new_style << std::endl;
+ std::cout << "\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
+ std::cout << "FontLister:set_font_style: " << new_style << std::endl;
#endif
- current_style = new_style;
- current_fontspec = canonize_fontspec( current_family + ", " + current_style );
- current_fontspec_system = system_fontspec( current_fontspec );
+ current_style = new_style;
+ current_fontspec = canonize_fontspec(current_family + ", " + current_style);
+ current_fontspec_system = system_fontspec(current_fontspec);
#ifdef DEBUG_FONT
- std::cout << " canonized: :" << current_fontspec << ":" << std::endl;
- std::cout << " system: :" << current_fontspec_system << ":" << std::endl;
- std::cout << " family: " << current_family << std::endl;
- std::cout << " style: " << current_style << std::endl;
- std::cout << "FontLister::set_font_style: end" << std::endl;
- std::cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" << std::endl;
+ std::cout << " canonized: :" << current_fontspec << ":" << std::endl;
+ std::cout << " system: :" << current_fontspec_system << ":" << std::endl;
+ std::cout << " family: " << current_family << std::endl;
+ std::cout << " style: " << current_style << std::endl;
+ std::cout << "FontLister::set_font_style: end" << std::endl;
+ std::cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" << std::endl;
+#endif
+}
+
+
+// We do this ourselves as we can't rely on FontFactory.
+void FontLister::fill_css(SPCSSAttr *css, Glib::ustring fontspec)
+{
+
+ if (fontspec.empty()) {
+ fontspec = current_fontspec;
+ }
+ std::pair<Glib::ustring, Glib::ustring> ui = ui_from_fontspec(fontspec);
+
+ Glib::ustring family = ui.first;
+
+
+ // Font spec is single quoted... for the moment
+ Glib::ustring fontspec_quoted(fontspec);
+ css_quote(fontspec_quoted);
+ sp_repr_css_set_property(css, "-inkscape-font-specification", fontspec_quoted.c_str());
+
+ // Font families needs to be properly quoted in CSS (used unquoted in font-lister)
+ css_font_family_quote(family);
+ sp_repr_css_set_property(css, "font-family", family.c_str());
+
+ PangoFontDescription *desc = pango_font_description_from_string(fontspec.c_str());
+ PangoWeight weight = pango_font_description_get_weight(desc);
+ switch (weight) {
+ case PANGO_WEIGHT_THIN:
+ sp_repr_css_set_property(css, "font-weight", "100");
+ break;
+ case PANGO_WEIGHT_ULTRALIGHT:
+ sp_repr_css_set_property(css, "font-weight", "200");
+ break;
+ case PANGO_WEIGHT_LIGHT:
+ sp_repr_css_set_property(css, "font-weight", "300");
+ break;
+#if PANGO_VERSION_CHECK(1,36,6)
+ case PANGO_WEIGHT_SEMILIGHT:
+ sp_repr_css_set_property(css, "font-weight", "350");
+ break;
#endif
+ case PANGO_WEIGHT_BOOK:
+ sp_repr_css_set_property(css, "font-weight", "380");
+ break;
+ case PANGO_WEIGHT_NORMAL:
+ sp_repr_css_set_property(css, "font-weight", "normal");
+ break;
+ case PANGO_WEIGHT_MEDIUM:
+ sp_repr_css_set_property(css, "font-weight", "500");
+ break;
+ case PANGO_WEIGHT_SEMIBOLD:
+ sp_repr_css_set_property(css, "font-weight", "600");
+ break;
+ case PANGO_WEIGHT_BOLD:
+ sp_repr_css_set_property(css, "font-weight", "bold");
+ break;
+ case PANGO_WEIGHT_ULTRABOLD:
+ sp_repr_css_set_property(css, "font-weight", "800");
+ break;
+ case PANGO_WEIGHT_HEAVY:
+ sp_repr_css_set_property(css, "font-weight", "900");
+ break;
+ case PANGO_WEIGHT_ULTRAHEAVY:
+ sp_repr_css_set_property(css, "font-weight", "1000");
+ break;
}
+ PangoStyle style = pango_font_description_get_style(desc);
+ switch (style) {
+ case PANGO_STYLE_NORMAL:
+ sp_repr_css_set_property(css, "font-style", "normal");
+ break;
+ case PANGO_STYLE_OBLIQUE:
+ sp_repr_css_set_property(css, "font-style", "oblique");
+ break;
+ case PANGO_STYLE_ITALIC:
+ sp_repr_css_set_property(css, "font-style", "italic");
+ break;
+ }
- // We do this ourselves as we can't rely on FontFactory.
- void
- FontLister::fill_css( SPCSSAttr *css, Glib::ustring fontspec ) {
-
- if( fontspec.empty() ) {
- fontspec = current_fontspec;
- }
- std::pair<Glib::ustring,Glib::ustring> ui = ui_from_fontspec( fontspec );
-
- Glib::ustring family = ui.first;
-
- sp_repr_css_set_property (css, "-inkscape-font-specification", fontspec.c_str() );
- sp_repr_css_set_property (css, "font-family", family.c_str() ); //Canonized w/ spaces
-
- PangoFontDescription *desc = pango_font_description_from_string( fontspec.c_str() );
- PangoWeight weight = pango_font_description_get_weight( desc );
- switch ( weight ) {
- case PANGO_WEIGHT_THIN:
- sp_repr_css_set_property (css, "font-weight", "100" );
- break;
- case PANGO_WEIGHT_ULTRALIGHT:
- sp_repr_css_set_property (css, "font-weight", "200" );
- break;
- case PANGO_WEIGHT_LIGHT:
- sp_repr_css_set_property (css, "font-weight", "300" );
- break;
- case PANGO_WEIGHT_BOOK:
- sp_repr_css_set_property (css, "font-weight", "380" );
- break;
- case PANGO_WEIGHT_NORMAL:
- sp_repr_css_set_property (css, "font-weight", "normal" );
- break;
- case PANGO_WEIGHT_MEDIUM:
- sp_repr_css_set_property (css, "font-weight", "500" );
- break;
- case PANGO_WEIGHT_SEMIBOLD:
- sp_repr_css_set_property (css, "font-weight", "600" );
- break;
- case PANGO_WEIGHT_BOLD:
- sp_repr_css_set_property (css, "font-weight", "bold" );
- break;
- case PANGO_WEIGHT_ULTRABOLD:
- sp_repr_css_set_property (css, "font-weight", "800" );
- break;
- case PANGO_WEIGHT_HEAVY:
- sp_repr_css_set_property (css, "font-weight", "900" );
- break;
- case PANGO_WEIGHT_ULTRAHEAVY:
- sp_repr_css_set_property (css, "font-weight", "1000" );
- break;
- }
-
- PangoStyle style = pango_font_description_get_style( desc );
- switch ( style ) {
- case PANGO_STYLE_NORMAL:
- sp_repr_css_set_property (css, "font-style", "normal" );
- break;
- case PANGO_STYLE_OBLIQUE:
- sp_repr_css_set_property (css, "font-style", "oblique" );
- break;
- case PANGO_STYLE_ITALIC:
- sp_repr_css_set_property (css, "font-style", "italic" );
- break;
- }
-
- PangoStretch stretch = pango_font_description_get_stretch( desc );
- switch ( stretch ) {
- case PANGO_STRETCH_ULTRA_CONDENSED:
- sp_repr_css_set_property (css, "font-stretch", "ultra-condensed" );
- break;
- case PANGO_STRETCH_EXTRA_CONDENSED:
- sp_repr_css_set_property (css, "font-stretch", "extra-condensed" );
- break;
- case PANGO_STRETCH_CONDENSED:
- sp_repr_css_set_property (css, "font-stretch", "condensed" );
- break;
- case PANGO_STRETCH_SEMI_CONDENSED:
- sp_repr_css_set_property (css, "font-stretch", "semi-condensed" );
- break;
- case PANGO_STRETCH_NORMAL:
- sp_repr_css_set_property (css, "font-stretch", "normal" );
- break;
- case PANGO_STRETCH_SEMI_EXPANDED:
- sp_repr_css_set_property (css, "font-stretch", "semi-expanded" );
- break;
- case PANGO_STRETCH_EXPANDED:
- sp_repr_css_set_property (css, "font-stretch", "expanded" );
- break;
- case PANGO_STRETCH_EXTRA_EXPANDED:
- sp_repr_css_set_property (css, "font-stretch", "extra-expanded" );
- break;
- case PANGO_STRETCH_ULTRA_EXPANDED:
- sp_repr_css_set_property (css, "font-stretch", "ultra-expanded" );
- break;
- }
-
- PangoVariant variant = pango_font_description_get_variant( desc );
- switch ( variant ) {
- case PANGO_VARIANT_NORMAL:
- sp_repr_css_set_property (css, "font-variant", "normal" );
- break;
- case PANGO_VARIANT_SMALL_CAPS:
- sp_repr_css_set_property (css, "font-variant", "small-caps" );
- break;
- }
+ PangoStretch stretch = pango_font_description_get_stretch(desc);
+ switch (stretch) {
+ case PANGO_STRETCH_ULTRA_CONDENSED:
+ sp_repr_css_set_property(css, "font-stretch", "ultra-condensed");
+ break;
+ case PANGO_STRETCH_EXTRA_CONDENSED:
+ sp_repr_css_set_property(css, "font-stretch", "extra-condensed");
+ break;
+ case PANGO_STRETCH_CONDENSED:
+ sp_repr_css_set_property(css, "font-stretch", "condensed");
+ break;
+ case PANGO_STRETCH_SEMI_CONDENSED:
+ sp_repr_css_set_property(css, "font-stretch", "semi-condensed");
+ break;
+ case PANGO_STRETCH_NORMAL:
+ sp_repr_css_set_property(css, "font-stretch", "normal");
+ break;
+ case PANGO_STRETCH_SEMI_EXPANDED:
+ sp_repr_css_set_property(css, "font-stretch", "semi-expanded");
+ break;
+ case PANGO_STRETCH_EXPANDED:
+ sp_repr_css_set_property(css, "font-stretch", "expanded");
+ break;
+ case PANGO_STRETCH_EXTRA_EXPANDED:
+ sp_repr_css_set_property(css, "font-stretch", "extra-expanded");
+ break;
+ case PANGO_STRETCH_ULTRA_EXPANDED:
+ sp_repr_css_set_property(css, "font-stretch", "ultra-expanded");
+ break;
+ }
+
+ PangoVariant variant = pango_font_description_get_variant(desc);
+ switch (variant) {
+ case PANGO_VARIANT_NORMAL:
+ sp_repr_css_set_property(css, "font-variant", "normal");
+ break;
+ case PANGO_VARIANT_SMALL_CAPS:
+ sp_repr_css_set_property(css, "font-variant", "small-caps");
+ break;
}
+}
- // We do this ourselves as we can't rely on FontFactory.
- Glib::ustring
- FontLister::fontspec_from_style (SPStyle* style) {
+// We do this ourselves as we can't rely on FontFactory.
+Glib::ustring FontLister::fontspec_from_style(SPStyle *style)
+{
- //std::cout << "FontLister:fontspec_from_style: " << std::endl;
+ //std::cout << "FontLister:fontspec_from_style: " << std::endl;
- Glib::ustring fontspec;
- if (style) {
+ Glib::ustring fontspec;
+ if (style) {
- // First try to use the font specification if it is set
- if (style->text->font_specification.set
- && style->text->font_specification.value
- && *style->text->font_specification.value) {
+ // First try to use the font specification if it is set
+ if (style->font_specification.set && style->font_specification.value && *style->font_specification.value) {
- fontspec = style->text->font_specification.value;
+ fontspec = style->font_specification.value;
} else {
- fontspec = style->text->font_family.value;
- fontspec += ",";
-
- switch (style->font_weight.computed) {
+ fontspec = style->font_family.value;
+ fontspec += ",";
- case SP_CSS_FONT_WEIGHT_100:
- fontspec += " 100";
- break;
-
- case SP_CSS_FONT_WEIGHT_200:
- fontspec += " 200";
- break;
+ // Use weight names as defined by Pango
+ switch (style->font_weight.computed) {
- case SP_CSS_FONT_WEIGHT_300:
- fontspec += " 300";
- break;
+ case SP_CSS_FONT_WEIGHT_100:
+ fontspec += " Thin";
+ break;
- case SP_CSS_FONT_WEIGHT_400:
- case SP_CSS_FONT_WEIGHT_NORMAL:
- //fontspec += " normal";
- break;
-
- case SP_CSS_FONT_WEIGHT_500:
- fontspec += " 500";
- break;
-
- case SP_CSS_FONT_WEIGHT_600:
- fontspec += " 600";
- break;
-
- case SP_CSS_FONT_WEIGHT_700:
- case SP_CSS_FONT_WEIGHT_BOLD:
- fontspec += " bold";
- break;
-
- case SP_CSS_FONT_WEIGHT_800:
- fontspec += " 800";
- break;
-
- case SP_CSS_FONT_WEIGHT_900:
- fontspec += " 900";
- break;
-
- case SP_CSS_FONT_WEIGHT_LIGHTER:
- case SP_CSS_FONT_WEIGHT_BOLDER:
- default:
- g_warning("Unrecognized font_weight.computed value");
- break;
- }
-
- switch (style->font_style.computed) {
- case SP_CSS_FONT_STYLE_ITALIC:
- fontspec += " italic";
- break;
-
- case SP_CSS_FONT_STYLE_OBLIQUE:
- fontspec += " oblique";
- break;
-
- case SP_CSS_FONT_STYLE_NORMAL:
- default:
- //fontspec += " normal";
- break;
- }
-
- switch (style->font_stretch.computed) {
-
- case SP_CSS_FONT_STRETCH_ULTRA_CONDENSED:
- fontspec += " extra-condensed";
- break;
-
- case SP_CSS_FONT_STRETCH_EXTRA_CONDENSED:
- fontspec += " extra-condensed";
- break;
-
- case SP_CSS_FONT_STRETCH_CONDENSED:
- case SP_CSS_FONT_STRETCH_NARROWER:
- fontspec += " condensed";
- break;
-
- case SP_CSS_FONT_STRETCH_SEMI_CONDENSED:
- fontspec += " semi-condensed";
- break;
-
- case SP_CSS_FONT_STRETCH_NORMAL:
- //fontspec += " normal";
- break;
-
- case SP_CSS_FONT_STRETCH_SEMI_EXPANDED:
- fontspec += " semi-expanded";
- break;
-
- case SP_CSS_FONT_STRETCH_EXPANDED:
- case SP_CSS_FONT_STRETCH_WIDER:
- fontspec += " expanded";
- break;
-
- case SP_CSS_FONT_STRETCH_EXTRA_EXPANDED:
- fontspec += " extra-expanded";
- break;
-
- case SP_CSS_FONT_STRETCH_ULTRA_EXPANDED:
- fontspec += " ultra-expanded";
- break;
-
- default:
- //fontspec += " normal";
- break;
- }
-
- switch (style->font_variant.computed) {
-
- case SP_CSS_FONT_VARIANT_SMALL_CAPS:
- fontspec += "small-caps";
- break;
-
- default:
- //fontspec += "normal";
- break;
- }
- }
- }
- return canonize_fontspec( fontspec );
- }
+ case SP_CSS_FONT_WEIGHT_200:
+ fontspec += " Ultra-Light";
+ break;
+ case SP_CSS_FONT_WEIGHT_300:
+ fontspec += " Light";
+ break;
- Gtk::TreeModel::Row
- FontLister::get_row_for_font (Glib::ustring family)
- {
- Gtk::TreePath path;
+ case SP_CSS_FONT_WEIGHT_400:
+ case SP_CSS_FONT_WEIGHT_NORMAL:
+ //fontspec += " normal";
+ break;
+
+ case SP_CSS_FONT_WEIGHT_500:
+ fontspec += " Medium";
+ break;
- Gtk::TreeModel::iterator iter = font_list_store->get_iter( "0" );
- while( iter != font_list_store->children().end() ) {
+ case SP_CSS_FONT_WEIGHT_600:
+ fontspec += " Semi-Bold";
+ break;
- Gtk::TreeModel::Row row = *iter;
+ case SP_CSS_FONT_WEIGHT_700:
+ case SP_CSS_FONT_WEIGHT_BOLD:
+ fontspec += " Bold";
+ break;
- if( family.compare( row[FontList.family] ) == 0 ) {
- return row;
- }
+ case SP_CSS_FONT_WEIGHT_800:
+ fontspec += " Ultra-Bold";
+ break;
- ++iter;
- }
+ case SP_CSS_FONT_WEIGHT_900:
+ fontspec += " Heavy";
+ break;
- throw FAMILY_NOT_FOUND;
- }
+ case SP_CSS_FONT_WEIGHT_LIGHTER:
+ case SP_CSS_FONT_WEIGHT_BOLDER:
+ default:
+ g_warning("Unrecognized font_weight.computed value");
+ break;
+ }
- Gtk::TreePath
- FontLister::get_path_for_font (Glib::ustring family)
- {
- return font_list_store->get_path( get_row_for_font ( family ) );
+ switch (style->font_style.computed) {
+ case SP_CSS_FONT_STYLE_ITALIC:
+ fontspec += " italic";
+ break;
+
+ case SP_CSS_FONT_STYLE_OBLIQUE:
+ fontspec += " oblique";
+ break;
+
+ case SP_CSS_FONT_STYLE_NORMAL:
+ default:
+ //fontspec += " normal";
+ break;
+ }
+
+ switch (style->font_stretch.computed) {
+
+ case SP_CSS_FONT_STRETCH_ULTRA_CONDENSED:
+ fontspec += " ultra-condensed";
+ break;
+
+ case SP_CSS_FONT_STRETCH_EXTRA_CONDENSED:
+ fontspec += " extra-condensed";
+ break;
+
+ case SP_CSS_FONT_STRETCH_CONDENSED:
+ case SP_CSS_FONT_STRETCH_NARROWER:
+ fontspec += " condensed";
+ break;
+
+ case SP_CSS_FONT_STRETCH_SEMI_CONDENSED:
+ fontspec += " semi-condensed";
+ break;
+
+ case SP_CSS_FONT_STRETCH_NORMAL:
+ //fontspec += " normal";
+ break;
+
+ case SP_CSS_FONT_STRETCH_SEMI_EXPANDED:
+ fontspec += " semi-expanded";
+ break;
+
+ case SP_CSS_FONT_STRETCH_EXPANDED:
+ case SP_CSS_FONT_STRETCH_WIDER:
+ fontspec += " expanded";
+ break;
+
+ case SP_CSS_FONT_STRETCH_EXTRA_EXPANDED:
+ fontspec += " extra-expanded";
+ break;
+
+ case SP_CSS_FONT_STRETCH_ULTRA_EXPANDED:
+ fontspec += " ultra-expanded";
+ break;
+
+ default:
+ //fontspec += " normal";
+ break;
+ }
+
+ switch (style->font_variant.computed) {
+
+ case SP_CSS_FONT_VARIANT_SMALL_CAPS:
+ fontspec += "small-caps";
+ break;
+
+ default:
+ //fontspec += "normal";
+ break;
+ }
+ }
}
+ return canonize_fontspec(fontspec);
+}
- Gtk::TreeModel::Row
- FontLister::get_row_for_style (Glib::ustring style)
- {
- Gtk::TreePath path;
- Gtk::TreeModel::iterator iter = style_list_store->get_iter( "0" );
- while( iter != style_list_store->children().end() ) {
+Gtk::TreeModel::Row FontLister::get_row_for_font(Glib::ustring family)
+{
+ Gtk::TreePath path;
- Gtk::TreeModel::Row row = *iter;
+ Gtk::TreeModel::iterator iter = font_list_store->get_iter("0");
+ while (iter != font_list_store->children().end()) {
- if( style.compare( row[FontStyleList.styles] ) == 0 ) {
- return row;
- }
+ Gtk::TreeModel::Row row = *iter;
- ++iter;
- }
+ if (familyNamesAreEqual(family, row[FontList.family])) {
+ return row;
+ }
- throw STYLE_NOT_FOUND;
+ ++iter;
}
- static gint
- compute_distance (const PangoFontDescription *a,
- const PangoFontDescription *b ) {
-
- // Weight: multiples of 100
- gint distance = abs( pango_font_description_get_weight( a ) -
- pango_font_description_get_weight( b ) );
-
- distance += 10000 * abs( pango_font_description_get_stretch( a ) -
- pango_font_description_get_stretch( b ) );
-
- PangoStyle style_a = pango_font_description_get_style( a );
- PangoStyle style_b = pango_font_description_get_style( b );
- if( style_a != style_b ) {
- if( (style_a == PANGO_STYLE_OBLIQUE && style_b == PANGO_STYLE_ITALIC) ||
- (style_b == PANGO_STYLE_OBLIQUE && style_a == PANGO_STYLE_ITALIC) ) {
- distance += 1000; // Oblique and italic are almost the same
- } else {
- distance += 100000; // Normal vs oblique/italic, not so similar
- }
- }
-
- // Normal vs small-caps
- distance += 1000000 * abs( pango_font_description_get_variant( a ) -
- pango_font_description_get_variant( b ) );
- return distance;
+ throw FAMILY_NOT_FOUND;
+}
+
+Gtk::TreePath FontLister::get_path_for_font(Glib::ustring family)
+{
+ return font_list_store->get_path(get_row_for_font(family));
+}
+
+Gtk::TreeModel::Row FontLister::get_row_for_style(Glib::ustring style)
+{
+ Gtk::TreePath path;
+
+ Gtk::TreeModel::iterator iter = style_list_store->get_iter("0");
+ while (iter != style_list_store->children().end()) {
+
+ Gtk::TreeModel::Row row = *iter;
+
+ if (familyNamesAreEqual(style, row[FontStyleList.cssStyle])) {
+ return row;
+ }
+
+ ++iter;
}
- // This is inspired by pango_font_description_better_match, but that routine
- // always returns false if variant or stretch are different. This means, for
- // example, that PT Sans Narrow with style Bold Condensed is never matched
- // to another font-family with Bold style.
- gboolean
- font_description_better_match( PangoFontDescription* target,
- PangoFontDescription* old_desc,
- PangoFontDescription* new_desc ) {
+ throw STYLE_NOT_FOUND;
+}
+
+static gint compute_distance(const PangoFontDescription *a, const PangoFontDescription *b)
+{
- if( old_desc == NULL ) return true;
- if( new_desc == NULL ) return false;
+ // Weight: multiples of 100
+ gint distance = abs(pango_font_description_get_weight(a) -
+ pango_font_description_get_weight(b));
- int old_distance = compute_distance( target, old_desc );
- int new_distance = compute_distance( target, new_desc );
- //std::cout << "font_description_better_match: old: " << old_distance << std::endl;
- //std::cout << " new: " << new_distance << std::endl;
+ distance += 10000 * abs(pango_font_description_get_stretch(a) -
+ pango_font_description_get_stretch(b));
- return (new_distance < old_distance );
+ PangoStyle style_a = pango_font_description_get_style(a);
+ PangoStyle style_b = pango_font_description_get_style(b);
+ if (style_a != style_b) {
+ if ((style_a == PANGO_STYLE_OBLIQUE && style_b == PANGO_STYLE_ITALIC) ||
+ (style_b == PANGO_STYLE_OBLIQUE && style_a == PANGO_STYLE_ITALIC)) {
+ distance += 1000; // Oblique and italic are almost the same
+ } else {
+ distance += 100000; // Normal vs oblique/italic, not so similar
+ }
}
- // void
- // font_description_dump( PangoFontDescription* target ) {
- // std::cout << " Font: " << pango_font_description_to_string( target ) << std::endl;
- // std::cout << " style: " << pango_font_description_get_style( target ) << std::endl;
- // std::cout << " weight: " << pango_font_description_get_weight( target ) << std::endl;
- // std::cout << " variant: " << pango_font_description_get_variant( target ) << std::endl;
- // std::cout << " stretch: " << pango_font_description_get_stretch( target ) << std::endl;
- // std::cout << " gravity: " << pango_font_description_get_gravity( target ) << std::endl;
- // }
-
- /* Returns style string */
- // TODO: Remove or turn into function to be used by new_font_family.
- Glib::ustring
- FontLister::get_best_style_match (Glib::ustring family, Glib::ustring target_style) {
+ // Normal vs small-caps
+ distance += 1000000 * abs(pango_font_description_get_variant(a) -
+ pango_font_description_get_variant(b));
+ return distance;
+}
-#ifdef DEBUG_FONT
- std::cout << "\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
- std::cout << "FontLister::get_best_style_match: " << family << " : " << target_style << std::endl;
-#endif
+// This is inspired by pango_font_description_better_match, but that routine
+// always returns false if variant or stretch are different. This means, for
+// example, that PT Sans Narrow with style Bold Condensed is never matched
+// to another font-family with Bold style.
+gboolean font_description_better_match(PangoFontDescription *target, PangoFontDescription *old_desc, PangoFontDescription *new_desc)
+{
+ if (old_desc == NULL)
+ return true;
+ if (new_desc == NULL)
+ return false;
- Glib::ustring fontspec = family + ", " + target_style;
-
- Gtk::TreeModel::Row row;
- try {
- row = get_row_for_font( family );
- } catch (...) {
- //std::cout << " ERROR: can't find family: " << family << std::endl;
- return (target_style);
- }
-
- PangoFontDescription* target = pango_font_description_from_string( fontspec.c_str() );
- PangoFontDescription* best = NULL;
-
- //font_description_dump( target );
-
- GList* styles = row[FontList.styles];
- for (GList *l=styles; l; l = l->next) {
- Glib::ustring fontspec = family + ", " + (char*)l->data;
- PangoFontDescription* candidate = pango_font_description_from_string( fontspec.c_str() );
- //font_description_dump( candidate );
- //std::cout << " " << font_description_better_match( target, best, candidate ) << std::endl;
- if( font_description_better_match( target, best, candidate ) ) {
- pango_font_description_free( best );
- best = candidate;
- //std::cout << " ... better: " << std::endl;
- } else {
- pango_font_description_free( candidate );
- //std::cout << " ... not better: " << std::endl;
- }
- }
-
- Glib::ustring best_style = target_style;
- if( best ) {
- pango_font_description_unset_fields( best, PANGO_FONT_MASK_FAMILY );
- best_style = pango_font_description_to_string( best );
- }
-
- if( target ) pango_font_description_free( target );
- if( best ) pango_font_description_free( best );
+ int old_distance = compute_distance(target, old_desc);
+ int new_distance = compute_distance(target, new_desc);
+ //std::cout << "font_description_better_match: old: " << old_distance << std::endl;
+ //std::cout << " new: " << new_distance << std::endl;
+
+ return (new_distance < old_distance);
+}
+// void
+// font_description_dump( PangoFontDescription* target ) {
+// std::cout << " Font: " << pango_font_description_to_string( target ) << std::endl;
+// std::cout << " style: " << pango_font_description_get_style( target ) << std::endl;
+// std::cout << " weight: " << pango_font_description_get_weight( target ) << std::endl;
+// std::cout << " variant: " << pango_font_description_get_variant( target ) << std::endl;
+// std::cout << " stretch: " << pango_font_description_get_stretch( target ) << std::endl;
+// std::cout << " gravity: " << pango_font_description_get_gravity( target ) << std::endl;
+// }
+
+/* Returns style string */
+// TODO: Remove or turn into function to be used by new_font_family.
+Glib::ustring FontLister::get_best_style_match(Glib::ustring family, Glib::ustring target_style)
+{
#ifdef DEBUG_FONT
- std::cout << " Returning: " << best_style << std::endl;
- std::cout << "FontLister::get_best_style_match: exit" << std::endl;
- std::cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" << std::endl;
+ std::cout << "\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
+ std::cout << "FontLister::get_best_style_match: " << family << " : " << target_style << std::endl;
#endif
- return best_style;
- }
- FontLister::~FontLister ()
- {
- };
+ Glib::ustring fontspec = family + ", " + target_style;
- const Glib::RefPtr<Gtk::ListStore>
- FontLister::get_font_list () const
+ Gtk::TreeModel::Row row;
+ try
{
- return font_list_store;
+ row = get_row_for_font(family);
}
-
- const Glib::RefPtr<Gtk::ListStore>
- FontLister::get_style_list () const
+ catch (...)
{
- return style_list_store;
+ //std::cout << " ERROR: can't find family: " << family << std::endl;
+ return (target_style);
+ }
+
+ PangoFontDescription *target = pango_font_description_from_string(fontspec.c_str());
+ PangoFontDescription *best = NULL;
+
+ //font_description_dump( target );
+
+ if (!row[FontList.styles]) {
+ row[FontList.styles] = font_factory::Default()->GetUIStyles(row[FontList.pango_family]);
+ }
+ GList *styles = row[FontList.styles];
+ for (GList *l = styles; l; l = l->next) {
+ Glib::ustring fontspec = family + ", " + ((StyleNames *)l->data)->CssName;
+ PangoFontDescription *candidate = pango_font_description_from_string(fontspec.c_str());
+ //font_description_dump( candidate );
+ //std::cout << " " << font_description_better_match( target, best, candidate ) << std::endl;
+ if (font_description_better_match(target, best, candidate)) {
+ pango_font_description_free(best);
+ best = candidate;
+ //std::cout << " ... better: " << std::endl;
+ } else {
+ pango_font_description_free(candidate);
+ //std::cout << " ... not better: " << std::endl;
+ }
}
+
+ Glib::ustring best_style = target_style;
+ if (best) {
+ pango_font_description_unset_fields(best, PANGO_FONT_MASK_FAMILY);
+ best_style = pango_font_description_to_string(best);
+ }
+
+ if (target)
+ pango_font_description_free(target);
+ if (best)
+ pango_font_description_free(best);
+
+
+#ifdef DEBUG_FONT
+ std::cout << " Returning: " << best_style << std::endl;
+ std::cout << "FontLister::get_best_style_match: exit" << std::endl;
+ std::cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" << std::endl;
+#endif
+ return best_style;
}
+const Glib::RefPtr<Gtk::ListStore> FontLister::get_font_list() const
+{
+ return font_list_store;
+}
+
+const Glib::RefPtr<Gtk::ListStore> FontLister::get_style_list() const
+{
+ return style_list_store;
+}
+
+} // namespace Inkscape
+
// Helper functions
// Separator function (if true, a separator will be drawn)
-gboolean font_lister_separator_func(GtkTreeModel *model,
- GtkTreeIter *iter,
- gpointer /*data*/)
+gboolean font_lister_separator_func(GtkTreeModel *model, GtkTreeIter *iter, gpointer /*data*/)
{
- gchar* text = 0;
- gtk_tree_model_get(model, iter, 0, &text, -1 ); // Column 0: FontList.family
- return (text && strcmp(text,"#") == 0);
+ gchar *text = 0;
+ gtk_tree_model_get(model, iter, 0, &text, -1); // Column 0: FontList.family
+ return (text && strcmp(text, "#") == 0);
}
-void font_lister_cell_data_func(GtkCellLayout */*cell_layout*/,
- GtkCellRenderer *cell,
- GtkTreeModel *model,
- GtkTreeIter *iter,
- gpointer /*data*/)
+void font_lister_cell_data_func(GtkCellLayout * /*cell_layout*/,
+ GtkCellRenderer *cell,
+ GtkTreeModel *model,
+ GtkTreeIter *iter,
+ gpointer /*data*/)
{
gchar *family;
gboolean onSystem = false;
gtk_tree_model_get(model, iter, 0, &family, 2, &onSystem, -1);
- Glib::ustring family_escaped = g_markup_escape_text(family, -1);
+ gchar* family_escaped = g_markup_escape_text(family, -1);
//g_free(family);
Glib::ustring markup;
- if( !onSystem ) {
+ if (!onSystem) {
markup = "<span foreground='darkblue'>";
/* See if font-family on system */
- std::vector<Glib::ustring> tokens = Glib::Regex::split_simple("\\s*,\\s*", family_escaped );
- for( size_t i=0; i < tokens.size(); ++i ) {
+ std::vector<Glib::ustring> tokens = Glib::Regex::split_simple("\\s*,\\s*", family_escaped);
+ for (size_t i = 0; i < tokens.size(); ++i) {
Glib::ustring token = tokens[i];
@@ -1018,17 +1092,17 @@ void font_lister_cell_data_func(GtkCellLayout */*cell_layout*/,
gchar *family = 0;
gboolean onSystem = true;
gboolean found = false;
- for( valid = gtk_tree_model_get_iter_first( GTK_TREE_MODEL(model), &iter );
+ for (valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter);
valid;
- valid = gtk_tree_model_iter_next( GTK_TREE_MODEL(model), &iter ) ) {
+ valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(model), &iter)) {
gtk_tree_model_get(model, &iter, 0, &family, 2, &onSystem, -1);
- if( onSystem && token.compare( family ) == 0 ) {
+ if (onSystem && familyNamesAreEqual(token, family)) {
found = true;
break;
}
}
- if( found ) {
+ if (found) {
markup += g_markup_escape_text(token.c_str(), -1);
markup += ", ";
} else {
@@ -1039,13 +1113,13 @@ void font_lister_cell_data_func(GtkCellLayout */*cell_layout*/,
}
}
// Remove extra comma and space from end.
- if( markup.size() >= 2 ) {
- markup.resize( markup.size()-2 );
+ if (markup.size() >= 2) {
+ markup.resize(markup.size() - 2);
}
markup += "</span>";
// std::cout << markup << std::endl;
} else {
- markup = family_escaped;
+ markup = family_escaped;
}
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
@@ -1053,17 +1127,20 @@ void font_lister_cell_data_func(GtkCellLayout */*cell_layout*/,
if (show_sample) {
Glib::ustring sample = prefs->getString("/tools/text/font_sample");
- Glib::ustring sample_escaped = g_markup_escape_text(sample.data(), -1);
+ gchar* sample_escaped = g_markup_escape_text(sample.data(), -1);
markup += " <span foreground='gray' font_family='";
markup += family_escaped;
markup += "'>";
markup += sample_escaped;
markup += "</span>";
+ g_free(sample_escaped);
}
- g_object_set (G_OBJECT (cell), "markup", markup.c_str(), NULL);
+ g_object_set(G_OBJECT(cell), "markup", markup.c_str(), NULL);
+ g_free(family_escaped);
}
+
/*
Local Variables:
mode:c++
@@ -1073,4 +1150,4 @@ void font_lister_cell_data_func(GtkCellLayout */*cell_layout*/,
fill-column:99
End:
*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8 :
diff --git a/src/libnrtype/font-lister.h b/src/libnrtype/font-lister.h
index 5a8f578d9..18e0d4b6e 100644
--- a/src/libnrtype/font-lister.h
+++ b/src/libnrtype/font-lister.h
@@ -26,285 +26,282 @@
class SPObject;
class SPDocument;
class SPCSSAttr;
-struct SPStyle;
-
-namespace Inkscape
-{
- /**
- * This class enumerates fonts using libnrtype into reusable data stores and
- * allows for random access to the font-family list and the font-style list.
- * Setting the font-family updates the font-style list. "Style" in this case
- * refers to everything but family and size (e.g. italic/oblique, weight).
- *
- * This class handles font-family lists and fonts that are not on the system,
- * where there is not an entry in the fontInstanceMap.
- *
- * This class uses the idea of "font_spec". This is a plain text string as used by
- * Pango. It is similar to the CSS font shorthand except that font-family comes
- * first and in this class the font-size is not used.
- *
- * This class uses the FontFactory class to get a list of system fonts
- * and to find best matches via Pango. The Pango interface is only setup
- * to deal with fonts that are on the system so care must be taken. For
- * example, best matches should only be done with the first font-family
- * in a font-family list. If the first font-family is not on the system
- * then a generic font-family should be used (sans-serif -> Sans).
- *
- * This class is used by the UI interface (text-toolbar, font-select, etc.).
- *
- * "Font" includes family and style. It should not be used when one
- * means font-family.
- */
- class FontLister
- {
- public:
-
- enum Exceptions
- {
- FAMILY_NOT_FOUND,
- STYLE_NOT_FOUND
- };
-
-
- virtual ~FontLister ();
-
- /** GtkTreeModelColumnRecord for the font-family list Gtk::ListStore
- */
- class FontListClass
- : public Gtk::TreeModelColumnRecord
- {
- public:
- /** Column containing the family name
- */
- Gtk::TreeModelColumn<Glib::ustring> family;
-
- /** Column containing the styles for each family name.
- */
- Gtk::TreeModelColumn<GList*> styles;
-
- /** Column containing flag if font is on system
- */
- Gtk::TreeModelColumn<gboolean> onSystem;
-
- FontListClass ()
- {
- add (family);
- add (styles);
- add (onSystem);
- }
- };
-
- FontListClass FontList;
-
- class FontStyleListClass
- : public Gtk::TreeModelColumnRecord
- {
- public:
- /** Column containing the styles
- */
- Gtk::TreeModelColumn<Glib::ustring> styles;
-
- FontStyleListClass ()
- {
- add (styles);
- }
- };
-
- FontStyleListClass FontStyleList;
-
- /** Returns the ListStore with the family names
- *
- * The return is const and the function is declared as const.
- * The ListStore is ready to be used after class instantiation
- * and should not (cannot) be modified.
- */
- const Glib::RefPtr<Gtk::ListStore>
- get_font_list () const;
-
- /** Returns the ListStore with the styles
- *
- */
- const Glib::RefPtr<Gtk::ListStore>
- get_style_list () const;
-
- /** Updates font list to include fonts in document
- *
- */
- void
- update_font_list ( SPDocument* document);
-
- private:
- void
- update_font_list_recursive( SPObject *r, std::list<Glib::ustring> *l );
-
- public:
- static Inkscape::FontLister*
- get_instance ()
- {
- static Inkscape::FontLister* instance = new Inkscape::FontLister();
- return instance;
- }
-
- /** Takes a hand written font spec and returns a Pango generated one in
- * standard form.
- */
- Glib::ustring canonize_fontspec( Glib::ustring fontspec );
-
- /** Find closest system font to given font.
- */
- Glib::ustring system_fontspec( Glib::ustring fontspec );
-
- /** Gets font-family and style from fontspec.
- * font-family and style returned.
- */
- std::pair<Glib::ustring, Glib::ustring>
- ui_from_fontspec (Glib::ustring fontspec);
-
- /** Sets font-family and style after a selection change.
- * New font-family and style returned.
- */
- std::pair<Glib::ustring, Glib::ustring>
- selection_update ();
-
- /** Sets current_fontspec, etc. If check is false, won't
- * try to find best style match (assumes style in fontspec
- * valid for given font-family).
- */
- void
- set_fontspec (Glib::ustring fontspec, gboolean check=true);
-
- Glib::ustring
- get_fontspec ()
- {
- return current_fontspec;
- }
-
- /** Changes font-family, updating style list and attempting to find
- * closest style to current_style style (if check_style is true).
- * New font-family and style returned.
- * Does NOT update current_family and current_style.
- * (For potential use in font-selector which doesn't update until
- * "Apply" button clicked.)
- */
- std::pair<Glib::ustring, Glib::ustring>
- new_font_family (Glib::ustring family, gboolean check_style = true);
-
- /** Sets font-family, updating style list and attempting
- * to find closest style to old current_style.
- * New font-family and style returned.
- * Updates current_family and current_style.
- * Calls new_font_family().
- * (For use in text-toolbar where update is immediate.)
- */
- std::pair<Glib::ustring, Glib::ustring>
- set_font_family (Glib::ustring family, gboolean check_style = true);
-
- /** Sets font-family from row in list store.
- * The row can be used to determine if we are in the
- * document or system part of the font-family list.
- * This is needed to handle scrolling through the
- * font-family list correctly.
- * Calls set_font_family().
- */
- std::pair<Glib::ustring, Glib::ustring>
- set_font_family (int row, gboolean check_style = true);
-
- Glib::ustring
- get_font_family ()
- {
- return current_family;
- }
-
- int
- get_font_family_row ()
- {
- return current_family_row;
- }
-
- /** Sets style. Does not validate style for family.
- */
- void
- set_font_style (Glib::ustring style);
-
- Glib::ustring
- get_font_style ()
- {
- return current_style;
- }
-
- Glib::ustring
- fontspec_from_style (SPStyle* style);
-
- /** Fill css using current_fontspec.
- */
- void
- fill_css( SPCSSAttr *css, Glib::ustring fontspec = "" );
-
- Gtk::TreeModel::Row
- get_row_for_font (Glib::ustring family);
-
- Gtk::TreePath
- get_path_for_font (Glib::ustring family);
-
- Gtk::TreeModel::Row
- get_row_for_style (Glib::ustring style);
-
- Gtk::TreePath
- get_path_for_style (Glib::ustring style);
-
- std::pair<Gtk::TreePath, Gtk::TreePath>
- get_paths (Glib::ustring family, Glib::ustring style);
-
- /** Return best style match for new font given style for old font.
- */
- Glib::ustring
- get_best_style_match (Glib::ustring family, Glib::ustring style);
-
- /* Not Used */
- const NRNameList
- get_name_list () const
- {
- return families;
- }
-
- private:
-
- FontLister ();
-
- NRNameList families;
-
- Glib::RefPtr<Gtk::ListStore> font_list_store;
- Glib::RefPtr<Gtk::ListStore> style_list_store;
-
- /** Info for currently selected font (what is shown in the UI).
- * May include font-family lists and fonts not on system.
- */
- int current_family_row;
- Glib::ustring current_family;
- Glib::ustring current_style;
- Glib::ustring current_fontspec;
-
- /** fontspec of system font closest to current_fontspec.
- * (What the system will use to display current_fontspec.)
- */
- Glib::ustring current_fontspec_system;
-
- /** If a font-family is not on system, this list of styles is used.
- */
- GList *default_styles;
- };
-}
+class SPStyle;
+
+namespace Inkscape {
+
+/**
+ * This class enumerates fonts using libnrtype into reusable data stores and
+ * allows for random access to the font-family list and the font-style list.
+ * Setting the font-family updates the font-style list. "Style" in this case
+ * refers to everything but family and size (e.g. italic/oblique, weight).
+ *
+ * This class handles font-family lists and fonts that are not on the system,
+ * where there is not an entry in the fontInstanceMap.
+ *
+ * This class uses the idea of "font_spec". This is a plain text string as used by
+ * Pango. It is similar to the CSS font shorthand except that font-family comes
+ * first and in this class the font-size is not used.
+ *
+ * This class uses the FontFactory class to get a list of system fonts
+ * and to find best matches via Pango. The Pango interface is only setup
+ * to deal with fonts that are on the system so care must be taken. For
+ * example, best matches should only be done with the first font-family
+ * in a font-family list. If the first font-family is not on the system
+ * then a generic font-family should be used (sans-serif -> Sans).
+ *
+ * This class is used by the UI interface (text-toolbar, font-select, etc.).
+ *
+ * "Font" includes family and style. It should not be used when one
+ * means font-family.
+ */
+
+class FontLister {
+public:
+ enum Exceptions {
+ FAMILY_NOT_FOUND,
+ STYLE_NOT_FOUND
+ };
+
+ virtual ~FontLister();
+
+ /**
+ * GtkTreeModelColumnRecord for the font-family list Gtk::ListStore
+ */
+ struct FontListClass : public Gtk::TreeModelColumnRecord {
+ /**
+ * Column containing the family name
+ */
+ Gtk::TreeModelColumn<Glib::ustring> family;
+
+ /**
+ * Column containing the styles for each family name.
+ */
+ Gtk::TreeModelColumn<GList *> styles;
+
+ /**
+ * Column containing flag if font is on system
+ */
+ Gtk::TreeModelColumn<bool> onSystem;
+
+ /**
+ * Not actually a column.
+ * Necessary for quick initialization of FontLister,
+ * we initially store the pango family and if the
+ * font style is actually used we'll cache it in
+ * %styles.
+ */
+ Gtk::TreeModelColumn<PangoFontFamily *> pango_family;
+
+ FontListClass()
+ {
+ add(family);
+ add(styles);
+ add(onSystem);
+ add(pango_family);
+ }
+ };
+
+ FontListClass FontList;
+
+ struct FontStyleListClass : public Gtk::TreeModelColumnRecord {
+ /**
+ * Column containing the styles as Font designer used.
+ */
+ Gtk::TreeModelColumn<Glib::ustring> displayStyle;
+
+ /**
+ * Column containing the styles in CSS/Pango format.
+ */
+ Gtk::TreeModelColumn<Glib::ustring> cssStyle;
+
+ FontStyleListClass()
+ {
+ add(cssStyle);
+ add(displayStyle);
+ }
+ };
+
+ FontStyleListClass FontStyleList;
+
+ /**
+ * @return the ListStore with the family names
+ *
+ * The return is const and the function is declared as const.
+ * The ListStore is ready to be used after class instantiation
+ * and should not be modified.
+ */
+ const Glib::RefPtr<Gtk::ListStore> get_font_list() const;
+
+ /**
+ * @return the ListStore with the styles
+ */
+ const Glib::RefPtr<Gtk::ListStore> get_style_list() const;
+
+ /**
+ * Inserts a font family or font-fallback list (for use when not
+ * already in document or on system).
+ */
+ void insert_font_family(Glib::ustring new_family);
+
+ /**
+ * Updates font list to include fonts in document.
+ */
+ void update_font_list(SPDocument *document);
+
+public:
+ static Inkscape::FontLister *get_instance();
+
+ /**
+ * Takes a hand written font spec and returns a Pango generated one in
+ * standard form.
+ */
+ Glib::ustring canonize_fontspec(Glib::ustring fontspec);
+
+ /**
+ * Find closest system font to given font.
+ */
+ Glib::ustring system_fontspec(Glib::ustring fontspec);
+
+ /**
+ * Gets font-family and style from fontspec.
+ * font-family and style returned.
+ */
+ std::pair<Glib::ustring, Glib::ustring> ui_from_fontspec(Glib::ustring fontspec);
+
+ /**
+ * Sets font-family and style after a selection change.
+ * New font-family and style returned.
+ */
+ std::pair<Glib::ustring, Glib::ustring> selection_update();
+
+ /**
+ * Sets current_fontspec, etc. If check is false, won't
+ * try to find best style match (assumes style in fontspec
+ * valid for given font-family).
+ */
+ void set_fontspec(Glib::ustring fontspec, bool check = true);
+
+ Glib::ustring get_fontspec()
+ {
+ return current_fontspec;
+ }
+
+ /**
+ * Changes font-family, updating style list and attempting to find
+ * closest style to current_style style (if check_style is true).
+ * New font-family and style returned.
+ * Does NOT update current_family and current_style.
+ * (For potential use in font-selector which doesn't update until
+ * "Apply" button clicked.)
+ */
+ std::pair<Glib::ustring, Glib::ustring> new_font_family(Glib::ustring family, bool check_style = true);
+
+ /**
+ * Sets font-family, updating style list and attempting
+ * to find closest style to old current_style.
+ * New font-family and style returned.
+ * Updates current_family and current_style.
+ * Calls new_font_family().
+ * (For use in text-toolbar where update is immediate.)
+ */
+ std::pair<Glib::ustring, Glib::ustring> set_font_family(Glib::ustring family, bool check_style = true);
+
+ /**
+ * Sets font-family from row in list store.
+ * The row can be used to determine if we are in the
+ * document or system part of the font-family list.
+ * This is needed to handle scrolling through the
+ * font-family list correctly.
+ * Calls set_font_family().
+ */
+ std::pair<Glib::ustring, Glib::ustring> set_font_family(int row, bool check_style = true);
+
+ Glib::ustring get_font_family()
+ {
+ return current_family;
+ }
+
+ int get_font_family_row()
+ {
+ return current_family_row;
+ }
+
+ /**
+ * Sets style. Does not validate style for family.
+ */
+ void set_font_style(Glib::ustring style);
+
+ Glib::ustring get_font_style()
+ {
+ return current_style;
+ }
+
+ Glib::ustring fontspec_from_style(SPStyle *style);
+
+ /**
+ * Fill css using current_fontspec.
+ */
+ void fill_css(SPCSSAttr *css, Glib::ustring fontspec = "");
+
+ Gtk::TreeModel::Row get_row_for_font(Glib::ustring family);
+
+ Gtk::TreePath get_path_for_font(Glib::ustring family);
+
+ Gtk::TreeModel::Row get_row_for_style(Glib::ustring style);
+
+ Gtk::TreePath get_path_for_style(Glib::ustring style);
+
+ std::pair<Gtk::TreePath, Gtk::TreePath> get_paths(Glib::ustring family, Glib::ustring style);
+
+ /**
+ * Return best style match for new font given style for old font.
+ */
+ Glib::ustring get_best_style_match(Glib::ustring family, Glib::ustring style);
+
+ void ensureRowStyles(GtkTreeModel* model, GtkTreeIter const* iter);
+
+private:
+ FontLister();
+
+ void update_font_list_recursive(SPObject *r, std::list<Glib::ustring> *l);
+
+ Glib::RefPtr<Gtk::ListStore> font_list_store;
+ Glib::RefPtr<Gtk::ListStore> style_list_store;
+
+ /**
+ * Info for currently selected font (what is shown in the UI).
+ * May include font-family lists and fonts not on system.
+ */
+ int current_family_row;
+ Glib::ustring current_family;
+ Glib::ustring current_style;
+ Glib::ustring current_fontspec;
+
+ /**
+ * fontspec of system font closest to current_fontspec.
+ * (What the system will use to display current_fontspec.)
+ */
+ Glib::ustring current_fontspec_system;
+
+ /**
+ * If a font-family is not on system, this list of styles is used.
+ */
+ GList *default_styles;
+};
+
+} // namespace Inkscape
// Helper functions
gboolean font_lister_separator_func(GtkTreeModel *model,
- GtkTreeIter *iter,
- gpointer /*data*/);
+ GtkTreeIter *iter,
+ gpointer /*data*/);
-void font_lister_cell_data_func(GtkCellLayout */*cell_layout*/,
- GtkCellRenderer *cell,
- GtkTreeModel *model,
- GtkTreeIter *iter,
- gpointer /*data*/);
+void font_lister_cell_data_func(GtkCellLayout * /*cell_layout*/,
+ GtkCellRenderer *cell,
+ GtkTreeModel *model,
+ GtkTreeIter *iter,
+ gpointer /*data*/);
#endif
@@ -317,4 +314,4 @@ void font_lister_cell_data_func(GtkCellLayout */*cell_layout*/,
fill-column:99
End:
*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8 :
diff --git a/src/libnrtype/font-style-to-pos.cpp b/src/libnrtype/font-style-to-pos.cpp
deleted file mode 100644
index 02f5ef37c..000000000
--- a/src/libnrtype/font-style-to-pos.cpp
+++ /dev/null
@@ -1,120 +0,0 @@
-#include "font-style-to-pos.h"
-#include <style.h>
-
-/* 'lighter' and 'darker' have to be resolved earlier */
-/**
-Given a style struct (CSS representation), sets the corresponding fields in a NRTypePosDef.
- */
-NRTypePosDef
-font_style_to_pos (SPStyle const &style)
-{
- NRTypePosDef ret;
-
- switch (style.font_weight.computed) {
- case SP_CSS_FONT_WEIGHT_100:
- ret.weight = NR_POS_WEIGHT_CSS100;
- break;
-
- case SP_CSS_FONT_WEIGHT_200:
- ret.weight = NR_POS_WEIGHT_CSS200;
- break;
-
- case SP_CSS_FONT_WEIGHT_300:
- ret.weight = NR_POS_WEIGHT_CSS300;
- break;
-
- case SP_CSS_FONT_WEIGHT_400:
- case SP_CSS_FONT_WEIGHT_NORMAL:
- ret.weight = NR_POS_WEIGHT_CSS400;
- break;
-
- case SP_CSS_FONT_WEIGHT_500:
- ret.weight = NR_POS_WEIGHT_CSS500;
- break;
-
- case SP_CSS_FONT_WEIGHT_600:
- ret.weight = NR_POS_WEIGHT_CSS600;
- break;
-
- case SP_CSS_FONT_WEIGHT_700:
- case SP_CSS_FONT_WEIGHT_BOLD:
- ret.weight = NR_POS_WEIGHT_CSS700;
- break;
-
- case SP_CSS_FONT_WEIGHT_800:
- ret.weight = NR_POS_WEIGHT_CSS800;
- break;
-
- case SP_CSS_FONT_WEIGHT_900:
- ret.weight = NR_POS_WEIGHT_CSS900;
- break;
-
- case SP_CSS_FONT_WEIGHT_LIGHTER:
- case SP_CSS_FONT_WEIGHT_BOLDER:
- default:
- g_warning("Unrecognized font_weight.computed value");
- ret.weight = NR_POS_WEIGHT_NORMAL;
- break;
- }
-
- switch (style.font_style.computed) {
- case SP_CSS_FONT_STYLE_ITALIC:
- ret.italic = 1;
- break;
-
- case SP_CSS_FONT_STYLE_OBLIQUE:
- ret.oblique = 1;
- break;
-
- case SP_CSS_FONT_STYLE_NORMAL:
- default:
- ret.italic = 0;
- ret.oblique = 0;
- break;
- }
-
- switch (style.font_stretch.computed) {
- case SP_CSS_FONT_STRETCH_ULTRA_CONDENSED:
- case SP_CSS_FONT_STRETCH_EXTRA_CONDENSED:
- ret.stretch = NR_POS_STRETCH_EXTRA_CONDENSED;
- break;
-
- case SP_CSS_FONT_STRETCH_CONDENSED:
- case SP_CSS_FONT_STRETCH_NARROWER:
- ret.stretch = NR_POS_STRETCH_CONDENSED;
- break;
-
- case SP_CSS_FONT_STRETCH_SEMI_CONDENSED:
- ret.stretch = NR_POS_STRETCH_SEMI_CONDENSED;
- break;
-
- case SP_CSS_FONT_STRETCH_SEMI_EXPANDED:
- ret.stretch = NR_POS_STRETCH_SEMI_EXPANDED;
- break;
-
- case SP_CSS_FONT_STRETCH_EXPANDED:
- case SP_CSS_FONT_STRETCH_WIDER:
- ret.stretch = NR_POS_STRETCH_EXPANDED;
- break;
-
- case SP_CSS_FONT_STRETCH_EXTRA_EXPANDED:
- case SP_CSS_FONT_STRETCH_ULTRA_EXPANDED:
- ret.stretch = NR_POS_STRETCH_EXTRA_EXPANDED;
- break;
-
- default:
- ret.stretch = NR_POS_STRETCH_NORMAL;
- break;
- }
-
- switch (style.font_variant.computed) {
- case SP_CSS_FONT_VARIANT_SMALL_CAPS:
- ret.variant = NR_POS_VARIANT_SMALLCAPS;
- break;
- default:
- ret.variant = NR_POS_VARIANT_NORMAL;
- break;
- }
-
- return ret;
-}
diff --git a/src/libnrtype/font-style-to-pos.h b/src/libnrtype/font-style-to-pos.h
deleted file mode 100644
index 56eb391c2..000000000
--- a/src/libnrtype/font-style-to-pos.h
+++ /dev/null
@@ -1,21 +0,0 @@
-#ifndef SEEN_FONT_STYLE_TO_POS_H
-#define SEEN_FONT_STYLE_TO_POS_H
-
-#include <libnrtype/nr-type-pos-def.h>
-
-struct SPStyle;
-
-NRTypePosDef font_style_to_pos(SPStyle const &style);
-
-#endif // SEEN_FONT_STYLE_TO_POS_H
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/libnrtype/nr-type-pos-def.cpp b/src/libnrtype/nr-type-pos-def.cpp
deleted file mode 100644
index fef04039e..000000000
--- a/src/libnrtype/nr-type-pos-def.cpp
+++ /dev/null
@@ -1,268 +0,0 @@
-#include "nr-type-pos-def.h"
-#include <glib.h>
-#include <string.h>
-
-/**
- * Given a font name or style name, returns a constant describing its
- * apparent style (normal/italic/oblique).
-*/
-int
-parse_name_for_style (char const *cc)
-{
- g_assert ( cc != NULL );
- gchar *c = g_ascii_strdown (cc, -1);
-
- gint style;
- // first dab at i18n... french and german
- if (strstr (c, "italic") || strstr (c, "italique") || strstr (c, "kursiv")) {
- style = NR_POS_STYLE_ITALIC;
- } else if (strstr (c, "oblique")) {
- style = NR_POS_STYLE_OBLIQUE;
- } else {
- style = NR_POS_STYLE_NORMAL;
- }
-
- g_free (c);
- return style;
-}
-
-
-/**
- * Given a font name or style name, returns a constant describing its
- * apparent weight.
-*/
-int
-parse_name_for_weight (char const *cc)
-{
- g_assert ( cc != NULL );
- gchar *c = g_ascii_strdown (cc, -1);
-
- gint weight;
- if (strstr (c, "thin")) {
- weight = NR_POS_WEIGHT_THIN;
- } else if (strstr (c, "extra light")) {
- weight = NR_POS_WEIGHT_EXTRA_LIGHT;
- } else if (strstr (c, "ultra light")) {
- weight = NR_POS_WEIGHT_ULTRA_LIGHT;
- } else if (strstr (c, "light")) {
- weight = NR_POS_WEIGHT_LIGHT;
- } else if (strstr (c, "book")) {
- weight = NR_POS_WEIGHT_BOOK;
- } else if (strstr (c, "medium")) {
- weight = NR_POS_WEIGHT_MEDIUM;
- } else if (strstr (c, "semi bold")) {
- weight = NR_POS_WEIGHT_SEMIBOLD;
- } else if (strstr (c, "semibold")) {
- weight = NR_POS_WEIGHT_SEMIBOLD;
- } else if (strstr (c, "demi bold")) {
- weight = NR_POS_WEIGHT_DEMIBOLD;
- } else if (strstr (c, "demibold") || strstr (c, "demi")) {
- weight = NR_POS_WEIGHT_DEMIBOLD;
- } else if (strstr (c, "ultra bold")) {
- weight = NR_POS_WEIGHT_ULTRA_BOLD;
- } else if (strstr (c, "extra bold") || strstr (c, "xbold") || strstr (c, "xtrabold")) {
- weight = NR_POS_WEIGHT_EXTRA_BOLD;
- } else if (strstr (c, "black") || strstr (c, "heavy")) {
- weight = NR_POS_WEIGHT_BLACK;
- } else if (strstr (c, "bold")) {
- /* Must come after the checks for `blah bold'. */
- weight = NR_POS_WEIGHT_BOLD;
- } else {
- weight = NR_POS_WEIGHT_NORMAL;
- }
-
- g_free (c);
- return weight;
-}
-
-/**
- * Given a font name or style name, returns a constant describing its
- * apparent stretch.
-*/
-int
-parse_name_for_stretch (char const *cc)
-{
- g_assert ( cc != NULL );
- gchar *c = g_ascii_strdown (cc, -1);
-
- gint stretch;
- if (strstr (c, "ultra narrow") || strstr (c, "ultra condensed") || strstr (c, "extra condensed")) {
- stretch = NR_POS_STRETCH_EXTRA_CONDENSED;
- } else if (strstr (c, "ultra wide") || strstr (c, "ultra expanded") || strstr (c, "ultra extended") || strstr (c, "extra expanded")) {
- stretch = NR_POS_STRETCH_EXTRA_EXPANDED;
- } else if (strstr (c, "semi condensed") || strstr (c, "semicondensed")) {
- stretch = NR_POS_STRETCH_SEMI_CONDENSED;
- } else if (strstr (c, "semi extended") || strstr (c, "semiextended")) {
- stretch = NR_POS_STRETCH_SEMI_EXPANDED;
- } else if (strstr (c, "narrow") || strstr (c, "condensed")) {
- stretch = NR_POS_STRETCH_CONDENSED;
- } else if (strstr (c, "wide") || strstr (c, "expanded") || strstr (c, "extended")) {
- stretch = NR_POS_STRETCH_EXPANDED;
- } else {
- stretch = NR_POS_STRETCH_NORMAL;
- }
-
- g_free (c);
- return stretch;
-}
-
-/**
- * Given a font name or style name, returns a constant describing its
- * apparent variant (normal/smallcaps).
-*/
-int
-parse_name_for_variant (char const *cc)
-{
- g_assert ( cc != NULL );
- gchar *c = g_ascii_strdown (cc, -1);
-
- gint variant;
- if (strstr (c, "small caps") || strstr (c, "smallcaps") || strstr (c, "caps")) {
- variant = NR_POS_VARIANT_SMALLCAPS;
- } else {
- variant = NR_POS_VARIANT_NORMAL;
- }
-
- g_free (c);
- return variant;
-}
-
-/**
- * Given a style constant, returns the CSS value for font-style.
-*/
-const char *
-style_to_css (int style)
-{
- switch (style) {
- case NR_POS_STYLE_NORMAL:
- return "normal";
- break;
- case NR_POS_STYLE_ITALIC:
- return "italic";
- break;
- case NR_POS_STYLE_OBLIQUE:
- return "oblique";
- break;
- default:
- break;
- }
- return NULL;
-}
-
-
-/**
- * Given a weight constant, returns the CSS value for font-weight.
-*/
-const char *
-weight_to_css (int weight)
-{
- switch (weight) {
- case NR_POS_WEIGHT_THIN:
- return "100";
- break;
- case NR_POS_WEIGHT_EXTRA_LIGHT:
- return "200";
- break;
- case NR_POS_WEIGHT_LIGHT:
- return "300";
- break;
- case NR_POS_WEIGHT_BOOK:
- return "normal";
- break;
- case NR_POS_WEIGHT_MEDIUM:
- return "500";
- break;
- case NR_POS_WEIGHT_SEMIBOLD:
- return "600";
- break;
- case NR_POS_WEIGHT_BOLD:
- return "bold";
- break;
- case NR_POS_WEIGHT_EXTRA_BOLD:
- return "800";
- break;
- case NR_POS_WEIGHT_BLACK:
- return "900";
- break;
- default:
- break;
- }
- return NULL;
-}
-
-/**
- * Given a stretch constant, returns the CSS value for font-stretch.
-*/
-const char *
-stretch_to_css (int stretch)
-{
- switch (stretch) {
- case NR_POS_STRETCH_EXTRA_CONDENSED:
- return "extra-condensed";
- break;
- case NR_POS_STRETCH_CONDENSED:
- return "condensed";
- break;
- case NR_POS_STRETCH_SEMI_CONDENSED:
- return "semi-condensed";
- break;
- case NR_POS_STRETCH_NORMAL:
- return "normal";
- break;
- case NR_POS_STRETCH_SEMI_EXPANDED:
- return "semi-expanded";
- break;
- case NR_POS_STRETCH_EXPANDED:
- return "expanded";
- break;
- case NR_POS_STRETCH_EXTRA_EXPANDED:
- return "extra-expanded";
- break;
- default:
- break;
- }
- return NULL;
-}
-
-/**
- * Given a variant constant, returns the CSS value for font-variant.
-*/
-const char *
-variant_to_css (int stretch)
-{
- switch (stretch) {
- case NR_POS_VARIANT_SMALLCAPS:
- return "small-caps";
- break;
- case NR_POS_VARIANT_NORMAL:
- return "normal";
- break;
- default:
- break;
- }
- return NULL;
-}
-
-
-/**
- * Constructor for NRTypePostDef. Sets the italic, oblique, weight,
- * stretch, and variant.
- */
-NRTypePosDef::NRTypePosDef(char const *description) {
- // we cannot use strcasestr, it's linux only... so we must lowercase the string first
- g_assert ( description != NULL );
- gchar *c = g_ascii_strdown (description, -1);
-
- /* copied from nr-type-directory.cpp:nr_type_calculate_position. */
-
- italic = (strstr (c, "italic") != NULL);
- oblique = (strstr (c, "oblique") != NULL);
-
- weight = parse_name_for_weight (c);
-
- stretch = parse_name_for_stretch (c);
-
- variant = parse_name_for_variant (c);
-
- g_free (c);
-}
diff --git a/src/libnrtype/nr-type-pos-def.h b/src/libnrtype/nr-type-pos-def.h
deleted file mode 100644
index ab9f5b45c..000000000
--- a/src/libnrtype/nr-type-pos-def.h
+++ /dev/null
@@ -1,102 +0,0 @@
-#ifndef __NR_TYPE_POS_DEF_H__
-#define __NR_TYPE_POS_DEF_H__
-
-#define NR_POS_STYLE_NORMAL 0
-#define NR_POS_STYLE_ITALIC 1
-#define NR_POS_STYLE_OBLIQUE 2
-
-#define NR_POS_WEIGHT_THIN 32
-#define NR_POS_WEIGHT_EXTRA_LIGHT 64
-#define NR_POS_WEIGHT_ULTRA_LIGHT 64
-#define NR_POS_WEIGHT_LIGHT 96
-#define NR_POS_WEIGHT_BOOK 128
-#define NR_POS_WEIGHT_NORMAL 128
-#define NR_POS_WEIGHT_MEDIUM 144
-#define NR_POS_WEIGHT_SEMIBOLD 160
-#define NR_POS_WEIGHT_DEMIBOLD 160
-#define NR_POS_WEIGHT_BOLD 192
-#define NR_POS_WEIGHT_ULTRA_BOLD 224
-#define NR_POS_WEIGHT_EXTRA_BOLD 224
-#define NR_POS_WEIGHT_BLACK 255
-
-#define NR_POS_STRETCH_ULTRA_CONDENSED 48
-#define NR_POS_STRETCH_EXTRA_CONDENSED 48
-#define NR_POS_STRETCH_CONDENSED 88
-#define NR_POS_STRETCH_SEMI_CONDENSED 108
-#define NR_POS_STRETCH_NORMAL 128
-#define NR_POS_STRETCH_SEMI_EXPANDED 148
-#define NR_POS_STRETCH_EXPANDED 168
-#define NR_POS_STRETCH_EXTRA_EXPANDED 228
-#define NR_POS_STRETCH_ULTRA_EXPANDED 228
-
-// This is an enumerate, rather than on/off property,
-// for I sincerely hope the vocabulary of this property will be
-// extended by the W3C in the future to allow for more fancy fonts
-#define NR_POS_VARIANT_NORMAL 0
-#define NR_POS_VARIANT_SMALLCAPS 1
-
-/* Mapping from CSS weight numbers.
-
- for i in `seq 9`; do
- if [ $i -le 4 ]; then w=$((32 * $i));
- elif [ $i = 5 ]; then w=144;
- elif [ $i -lt 9 ]; then w=$((32 * $(($i - 1))));
- else w=255;
- fi;
- printf '#define NR_POS_WEIGHT_CSS%d00\t\t%3d\n' $i $w;
- done
-
- This calculation approximately matches the old to-and-from-text code,
- I don't claim it to be reasonable. ("approximately": some of the old
- code wrote strings like "semi" and "heavy" that weren't being parsed
- at the other end, and it had CSS100 darker than CSS200.)
- */
-#define NR_POS_WEIGHT_CSS100 32
-#define NR_POS_WEIGHT_CSS200 64
-#define NR_POS_WEIGHT_CSS300 96
-#define NR_POS_WEIGHT_CSS400 128
-#define NR_POS_WEIGHT_CSS500 144
-#define NR_POS_WEIGHT_CSS600 160
-#define NR_POS_WEIGHT_CSS700 192
-#define NR_POS_WEIGHT_CSS800 224
-#define NR_POS_WEIGHT_CSS900 255
-
-
-class NRTypePosDef {
-public:
- unsigned int italic : 1;
- unsigned int oblique : 1;
- unsigned int weight : 8;
- unsigned int stretch : 8;
- unsigned int variant : 8;
- /* These can probably be made sensible sizes rather than bitfields; for the moment we'll
- keep the old definition. */
-
-public:
- NRTypePosDef() :
- italic(0),
- oblique(0),
- weight(NR_POS_WEIGHT_NORMAL),
- stretch(NR_POS_STRETCH_NORMAL),
- variant(NR_POS_VARIANT_NORMAL)
- { }
-
- NRTypePosDef(char const *description);
-
- bool signature() {return this->italic +
- this->oblique * 255 +
- this->weight * 255 * 255 +
- this->stretch * 255 * 255 * 255 +
- this->variant * 255 * 255 * 255 * 255;};
-};
-
-int parse_name_for_style (char const *c);
-int parse_name_for_weight (char const *c);
-int parse_name_for_stretch (char const *c);
-int parse_name_for_variant (char const *c);
-const char *style_to_css (int style);
-const char *weight_to_css (int weight);
-const char *stretch_to_css (int stretch);
-const char *variant_to_css (int variant);
-
-#endif /* __NR_TYPE_POS_DEF_H__ */
diff --git a/src/libnrtype/nr-type-primitives.cpp b/src/libnrtype/nr-type-primitives.cpp
index 63a3abcc5..3ad4a3771 100644
--- a/src/libnrtype/nr-type-primitives.cpp
+++ b/src/libnrtype/nr-type-primitives.cpp
@@ -1,6 +1,4 @@
-#define __NR_TYPE_PRIMITIVES_C__
-
-/*
+/**
* Typeface and script library
*
* Authors:
@@ -12,26 +10,27 @@
/* This should be enough for approximately 10000 fonts */
#define NR_DICTSIZE 2777
-#include <stdlib.h>
+#include <cstdlib>
#include <string.h>
#include <glib.h>
+
#include "nr-type-primitives.h"
/**
* An entry in a list of key->value pairs
*/
struct NRTDEntry {
- NRTDEntry *next;
- const gchar *key;
- void *val;
+ NRTDEntry *next;
+ const gchar *key;
+ void *val;
};
/**
* Type Dictionary, consisting of size number of key-value entries
*/
struct NRTypeDict {
- unsigned int size;
- NRTDEntry **entries;
+ unsigned int size;
+ NRTDEntry **entries;
};
static NRTDEntry *nr_td_entry_new (void);
@@ -42,17 +41,17 @@ static NRTDEntry *nr_td_entry_new (void);
void
nr_name_list_release (NRNameList *list)
{
- if (list->destructor) {
- list->destructor (list);
- }
+ if (list->destructor) {
+ list->destructor (list);
+ }
}
void
nr_style_list_release (NRStyleList *list)
{
- if (list->destructor) {
- list->destructor (list);
- }
+ if (list->destructor) {
+ list->destructor (list);
+ }
}
/**
@@ -62,18 +61,18 @@ nr_style_list_release (NRStyleList *list)
NRTypeDict *
nr_type_dict_new (void)
{
- NRTypeDict *td;
- int i;
+ NRTypeDict *td;
+ int i;
- td = g_new (NRTypeDict, 1);
+ td = g_new (NRTypeDict, 1);
- td->size = NR_DICTSIZE;
- td->entries = g_new (NRTDEntry *, td->size);
- for (i = 0; i < NR_DICTSIZE; i++) {
- td->entries[i] = NULL;
- }
+ td->size = NR_DICTSIZE;
+ td->entries = g_new (NRTDEntry *, td->size);
+ for (i = 0; i < NR_DICTSIZE; i++) {
+ td->entries[i] = NULL;
+ }
- return td;
+ return td;
}
/**
@@ -82,15 +81,15 @@ nr_type_dict_new (void)
static unsigned int
nr_str_hash (const gchar *p)
{
- unsigned int h;
+ unsigned int h;
- h = *p;
+ h = *p;
- if (h != 0) {
- for (p += 1; *p; p++) h = (h << 5) - h + *p;
- }
+ if (h != 0) {
+ for (p += 1; *p; p++) h = (h << 5) - h + *p;
+ }
- return h;
+ return h;
}
/**
@@ -99,25 +98,25 @@ nr_str_hash (const gchar *p)
void
nr_type_dict_insert (NRTypeDict *td, const gchar *key, void *val)
{
- if (key) {
- NRTDEntry *tde;
- unsigned int hval;
-
- hval = nr_str_hash (key) % td->size;
-
- for (tde = td->entries[hval]; tde; tde = tde->next) {
- if (!strcmp (key, tde->key)) {
- tde->val = val;
- return;
- }
- }
-
- tde = nr_td_entry_new ();
- tde->next = td->entries[hval];
- tde->key = key;
- tde->val = val;
- td->entries[hval] = tde;
- }
+ if (key) {
+ NRTDEntry *tde;
+ unsigned int hval;
+
+ hval = nr_str_hash (key) % td->size;
+
+ for (tde = td->entries[hval]; tde; tde = tde->next) {
+ if (!strcmp (key, tde->key)) {
+ tde->val = val;
+ return;
+ }
+ }
+
+ tde = nr_td_entry_new ();
+ tde->next = td->entries[hval];
+ tde->key = key;
+ tde->val = val;
+ td->entries[hval] = tde;
+ }
}
/**
@@ -126,16 +125,16 @@ nr_type_dict_insert (NRTypeDict *td, const gchar *key, void *val)
void *
nr_type_dict_lookup (NRTypeDict *td, const gchar *key)
{
- if (key) {
- NRTDEntry *tde;
- unsigned int hval;
- hval = nr_str_hash (key) % td->size;
- for (tde = td->entries[hval]; tde; tde = tde->next) {
- if (!strcmp (key, tde->key)) return tde->val;
- }
- }
-
- return NULL;
+ if (key) {
+ NRTDEntry *tde;
+ unsigned int hval;
+ hval = nr_str_hash (key) % td->size;
+ for (tde = td->entries[hval]; tde; tde = tde->next) {
+ if (!strcmp (key, tde->key)) return tde->val;
+ }
+ }
+
+ return NULL;
}
#define NR_TDE_BLOCK_SIZE 32
@@ -148,20 +147,30 @@ static NRTDEntry *nr_tde_free_list;
static NRTDEntry *
nr_td_entry_new (void)
{
- NRTDEntry *tde;
+ NRTDEntry *tde;
- if (!nr_tde_free_list) {
- int i;
- nr_tde_free_list = g_new (NRTDEntry, NR_TDE_BLOCK_SIZE);
- for (i = 0; i < (NR_TDE_BLOCK_SIZE - 1); i++) {
- nr_tde_free_list[i].next = nr_tde_free_list + i + 1;
- }
- nr_tde_free_list[i].next = NULL;
- }
+ if (!nr_tde_free_list) {
+ int i;
+ nr_tde_free_list = g_new (NRTDEntry, NR_TDE_BLOCK_SIZE);
+ for (i = 0; i < (NR_TDE_BLOCK_SIZE - 1); i++) {
+ nr_tde_free_list[i].next = nr_tde_free_list + i + 1;
+ }
+ nr_tde_free_list[i].next = NULL;
+ }
- tde = nr_tde_free_list;
- nr_tde_free_list = tde->next;
+ tde = nr_tde_free_list;
+ nr_tde_free_list = tde->next;
- return tde;
+ return tde;
}
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8 :
diff --git a/src/libnrtype/nr-type-primitives.h b/src/libnrtype/nr-type-primitives.h
index 9bb181c4b..863803433 100644
--- a/src/libnrtype/nr-type-primitives.h
+++ b/src/libnrtype/nr-type-primitives.h
@@ -1,12 +1,12 @@
-#ifndef __NR_TYPE_PRIMITIVES_H__
-#define __NR_TYPE_PRIMITIVES_H__
+#ifndef SEEN_NR_TYPE_PRIMITIVES_H
+#define SEEN_NR_TYPE_PRIMITIVES_H
-/*
+/**
* Typeface and script library
*
* Authors:
* Lauris Kaplinski <lauris@kaplinski.com>
- * g++ port: Nathan Hurst <njh@mail.csse.monash.edu.au>
+ * c++ port: Nathan Hurst <njh@mail.csse.monash.edu.au>
*
* This code is in public domain
*/
@@ -47,4 +47,15 @@ void nr_type_dict_insert (NRTypeDict *td, const gchar *key, void *val);
void *nr_type_dict_lookup (NRTypeDict *td, const gchar *key);
-#endif
+#endif // !SEEN_NR_TYPE_PRIMITIVES_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8 :
diff --git a/src/libuemf/uemf.c b/src/libuemf/uemf.c
index 069cf901b..1d417dece 100644
--- a/src/libuemf/uemf.c
+++ b/src/libuemf/uemf.c
@@ -16,8 +16,8 @@
/*
File: uemf.c
-Version: 0.0.26
-Date: 24-MAR-2014
+Version: 0.0.28
+Date: 04-APR-2014
Author: David Mathog, Biology Division, Caltech
email: mathog@caltech.edu
Copyright: 2014 David Mathog and California Institute of Technology (Caltech)
@@ -417,7 +417,7 @@ uint32_t emr_properties(uint32_t type){
table[ 64] = 0x90; // U_EMRSTROKEPATH 1 0 0 1 0 0 0 0
table[ 65] = 0xA0; // U_EMRFLATTENPATH 1 0 1 0 0 0 0 0
table[ 66] = 0xA0; // U_EMRWIDENPATH 1 0 1 0 0 0 0 0
- table[ 67] = 0xA0; // U_EMRSELECTCLIPPATH 1 0 1 0 0 0 0 0
+ table[ 67] = 0x80; // U_EMRSELECTCLIPPATH 1 0 0 0 0 0 0 0 consumes the path, draws nothing
table[ 68] = 0xA0; // U_EMRABORTPATH 1 0 1 0 0 0 0 0
table[ 69] = 0xA0; // U_EMRUNDEF69 1 0 1 0 0 0 0 0
table[ 70] = 0x00; // U_EMRCOMMENT 0 0 0 0 0 0 0 0
diff --git a/src/libuemf/uemf.h b/src/libuemf/uemf.h
index cde1b6c85..a792a65de 100644
--- a/src/libuemf/uemf.h
+++ b/src/libuemf/uemf.h
@@ -95,8 +95,8 @@ these WMF enumerations is by referencing the following table:
/*
File: uemf.h
-Version: 0.0.26
-Date: 27-MAR-2014
+Version: 0.0.27
+Date: 28-MAR-2014
Author: David Mathog, Biology Division, Caltech
email: mathog@caltech.edu
Copyright: 2014 David Mathog and California Institute of Technology (Caltech)
@@ -1167,6 +1167,7 @@ typedef struct {
EMF manual 2.1.29
@{
*/
+#define U_RGN_NONE 0 //!< not part of EMF standard, may be used by others
#define U_RGN_AND 1 //!< Region becomes intersection of existing region and new region.
#define U_RGN_OR 2 //!< Region becomes union of existing region and new region.
#define U_RGN_XOR 3 //!< Region becomes XOR of existing and new regions.
diff --git a/src/libuemf/uwmf.c b/src/libuemf/uwmf.c
index b4a1dfc52..b378e587f 100644
--- a/src/libuemf/uwmf.c
+++ b/src/libuemf/uwmf.c
@@ -19,8 +19,8 @@
/*
File: uwmf.c
-Version: 0.0.14
-Date: 24-MAR-2014
+Version: 0.0.15
+Date: 11-APR-2014
Author: David Mathog, Biology Division, Caltech
email: mathog@caltech.edu
Copyright: 2014 David Mathog and California Institute of Technology (Caltech)
@@ -3019,7 +3019,7 @@ char *U_WMRESCAPE_set(uint16_t Escape, uint16_t Length, const void *Data){
\param DC Drawing Context to restore. (negative is relative to current, positive is absolute)
*/
char *U_WMRRESTOREDC_set(int16_t DC){
- return U_WMRCORE_1U16_set(U_WMR_SETMAPMODE, DC);
+ return U_WMRCORE_1U16_set(U_WMR_RESTOREDC, DC);
}
/**
diff --git a/src/line-geometry.h b/src/line-geometry.h
index d7be9570c..a77d6e1f3 100644
--- a/src/line-geometry.h
+++ b/src/line-geometry.h
@@ -12,13 +12,14 @@
#ifndef SEEN_LINE_GEOMETRY_H
#define SEEN_LINE_GEOMETRY_H
+#include <2geom/point.h>
#include <boost/optional.hpp>
-#include "glib.h"
+
#include "axis-manip.h" // FIXME: This is only for Box3D::epsilon; move that to a better location
-#include "2geom/point.h"
#include "persp3d.h"
class SPDesktop;
+typedef unsigned int guint32;
namespace Box3D {
diff --git a/src/line-snapper.cpp b/src/line-snapper.cpp
index 930b7fca9..6122b133a 100644
--- a/src/line-snapper.cpp
+++ b/src/line-snapper.cpp
@@ -11,9 +11,10 @@
*/
#include <2geom/line.h>
+#include <cassert>
+
#include "line-snapper.h"
#include "snapped-line.h"
-//#include <gtk/gtk.h>
#include "snap.h"
Inkscape::LineSnapper::LineSnapper(SnapManager *sm, Geom::Coord const d) : Snapper(sm, d)
@@ -37,7 +38,7 @@ void Inkscape::LineSnapper::freeSnap(IntermSnapResults &isr,
Geom::Point const p1 = i->second; // point at guide/grid line
Geom::Point const p2 = p1 + Geom::rot90(i->first); // 2nd point at guide/grid line
// std::cout << " line through " << i->second << " with normal " << i->first;
- g_assert(i->first != Geom::Point(0,0)); // we cannot project on an linesegment of zero length
+ assert(i->first != Geom::Point(0,0)); // we cannot project on an linesegment of zero length
Geom::Point const p_proj = Geom::projection(p.getPoint(), Geom::Line(p1, p2));
Geom::Coord const dist = Geom::L2(p_proj - p.getPoint());
diff --git a/src/line-snapper.h b/src/line-snapper.h
index 4b165e0a5..b2fc3d389 100644
--- a/src/line-snapper.h
+++ b/src/line-snapper.h
@@ -12,10 +12,9 @@
#include "snapper.h"
-namespace Inkscape
-{
-class SnapCandidatePoint;
+namespace Inkscape {
+class SnapCandidatePoint;
/**
* Superclass for snappers to horizontal and vertical lines.
diff --git a/src/livarot/Path.h b/src/livarot/Path.h
index a109298a2..32ee71ffc 100644
--- a/src/livarot/Path.h
+++ b/src/livarot/Path.h
@@ -20,7 +20,7 @@ struct PathDescrCubicTo;
struct PathDescrBezierTo;
struct PathDescrIntermBezierTo;
-struct SPStyle;
+class SPStyle;
/*
* the Path class: a structure to hold path description and their polyline approximation (not kept in sync)
diff --git a/src/livarot/PathStroke.cpp b/src/livarot/PathStroke.cpp
index 50c335176..6ec7fa209 100644
--- a/src/livarot/PathStroke.cpp
+++ b/src/livarot/PathStroke.cpp
@@ -748,12 +748,12 @@ void Path::RecRound(Shape *dest, int sNo, int eNo, // start and end index
}
/*
- Local Variables:
-mode:c++
-c-file-style:"stroustrup"
-c-file-offsets:((innamespace . 0)(inline-open . 0))
-indent-tabs-mode:nil
-fill-column:99
-End:
- */
-// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/live_effects/CMakeLists.txt b/src/live_effects/CMakeLists.txt
index a5f50a69d..c8a02c810 100644
--- a/src/live_effects/CMakeLists.txt
+++ b/src/live_effects/CMakeLists.txt
@@ -2,8 +2,10 @@
set(live_effects_SRC
effect.cpp
lpe-angle_bisector.cpp
+ lpe-attach-path.cpp
lpe-bendpath.cpp
lpe-boolops.cpp
+ lpe-bounding-box.cpp
lpe-circle_3pts.cpp
lpe-circle_with_radius.cpp
lpe-clone-original.cpp
@@ -11,8 +13,12 @@ set(live_effects_SRC
lpe-copy_rotate.cpp
lpe-curvestitch.cpp
lpe-dynastroke.cpp
+ lpe-ellipse-5pts.cpp
lpe-envelope.cpp
lpe-extrude.cpp
+ lpe-fill-between-many.cpp
+ lpe-fill-between-strokes.cpp
+ lpe-fillet-chamfer.cpp
lpe-gears.cpp
lpe-interpolate.cpp
lpe-knot.cpp
@@ -25,15 +31,20 @@ set(live_effects_SRC
lpe-patternalongpath.cpp
lpe-perp_bisector.cpp
lpe-perspective_path.cpp
+ lpe-perspective-envelope.cpp
lpe-powerstroke.cpp
lpe-recursiveskeleton.cpp
lpe-rough-hatches.cpp
lpe-ruler.cpp
+ lpe-show_handles.cpp
+ lpe-simplify.cpp
# lpe-skeleton.cpp
lpe-sketch.cpp
lpe-spiro.cpp
+ lpe-roughen.cpp
lpe-tangent_to_curve.cpp
lpe-test-doEffect-stack.cpp
+ lpe-bspline.cpp
lpe-text_label.cpp
lpe-vonkoch.cpp
lpegroupbbox.cpp
@@ -44,14 +55,18 @@ set(live_effects_SRC
parameter/array.cpp
parameter/bool.cpp
+ parameter/filletchamferpointarray.cpp
parameter/parameter.cpp
parameter/path.cpp
parameter/originalpath.cpp
+ parameter/originalpatharray.cpp
parameter/path-reference.cpp
parameter/point.cpp
parameter/powerstrokepointarray.cpp
parameter/random.cpp
parameter/text.cpp
+ paramter/transformedpoint.cpp
+ parameter/togglebutton.cpp
parameter/unit.cpp
parameter/vector.cpp
@@ -61,8 +76,10 @@ set(live_effects_SRC
effect-enum.h
effect.h
lpe-angle_bisector.h
+ lpe-attach-path.h
lpe-bendpath.h
lpe-boolops.h
+ lpe-bounding-box.h
lpe-circle_3pts.h
lpe-circle_with_radius.h
lpe-clone-original.h
@@ -70,8 +87,12 @@ set(live_effects_SRC
lpe-copy_rotate.h
lpe-curvestitch.h
lpe-dynastroke.h
+ lpe-ellipse-5pts.h
lpe-envelope.h
lpe-extrude.h
+ lpe-fill-between-many.h
+ lpe-fill-between-strokes.h
+ lpe-fillet-chamfer.h
lpe-gears.h
lpe-interpolate.h
lpe-knot.h
@@ -84,16 +105,21 @@ set(live_effects_SRC
lpe-patternalongpath.h
lpe-perp_bisector.h
lpe-perspective_path.h
+ lpe-perspective-envelope.h
lpe-powerstroke.h
lpe-powerstroke-interpolators.h
lpe-recursiveskeleton.h
lpe-rough-hatches.h
lpe-ruler.h
+ lpe-simplify.h
+ lpe-show_handles.h
lpe-skeleton.h
lpe-sketch.h
lpe-spiro.h
+ lpe-roughen.h
lpe-tangent_to_curve.h
lpe-test-doEffect-stack.h
+ lpe-bspline.h
lpe-text_label.h
lpe-vonkoch.h
lpegroupbbox.h
@@ -104,15 +130,18 @@ set(live_effects_SRC
parameter/array.h
parameter/bool.h
+ parameter/filletchamferpointarray.h
parameter/enum.h
parameter/parameter.h
parameter/path-reference.h
parameter/path.h
parameter/originalpath.h
+ parameter/originalpatharray.h
parameter/point.h
parameter/powerstrokepointarray.h
parameter/random.h
parameter/text.h
+ parameter/togglebutton.h
parameter/unit.h
parameter/vector.h
diff --git a/src/live_effects/Makefile_insert b/src/live_effects/Makefile_insert
index 9c3c171f2..8f0a3ac57 100644
--- a/src/live_effects/Makefile_insert
+++ b/src/live_effects/Makefile_insert
@@ -32,14 +32,28 @@ ink_common_sources += \
live_effects/lpe-curvestitch.h \
live_effects/lpe-constructgrid.cpp \
live_effects/lpe-constructgrid.h \
+ live_effects/lpe-fillet-chamfer.cpp \
+ live_effects/lpe-fillet-chamfer.h \
live_effects/lpe-gears.cpp \
live_effects/lpe-gears.h \
live_effects/lpe-interpolate.cpp \
live_effects/lpe-interpolate.h \
+ live_effects/lpe-interpolate_points.cpp \
+ live_effects/lpe-interpolate_points.h \
live_effects/lpe-test-doEffect-stack.cpp \
live_effects/lpe-test-doEffect-stack.h \
+ live_effects/lpe-bspline.cpp \
+ live_effects/lpe-bspline.h \
live_effects/lpe-lattice.cpp \
live_effects/lpe-lattice.h \
+ live_effects/lpe-lattice2.cpp \
+ live_effects/lpe-lattice2.h \
+ live_effects/lpe-roughen.cpp \
+ live_effects/lpe-roughen.h \
+ live_effects/lpe-show_handles.cpp \
+ live_effects/lpe-show_handles.h \
+ live_effects/lpe-simplify.cpp \
+ live_effects/lpe-simplify.h \
live_effects/lpe-envelope.cpp \
live_effects/lpe-envelope.h \
live_effects/lpe-spiro.cpp \
@@ -56,6 +70,8 @@ ink_common_sources += \
live_effects/lpe-circle_with_radius.h \
live_effects/lpe-perspective_path.cpp \
live_effects/lpe-perspective_path.h \
+ live_effects/lpe-perspective-envelope.cpp \
+ live_effects/lpe-perspective-envelope.h \
live_effects/lpe-mirror_symmetry.cpp \
live_effects/lpe-mirror_symmetry.h \
live_effects/lpe-circle_3pts.cpp \
@@ -82,4 +98,20 @@ ink_common_sources += \
live_effects/lpe-path_length.cpp \
live_effects/lpe-path_length.h \
live_effects/lpe-line_segment.cpp \
- live_effects/lpe-line_segment.h
+ live_effects/lpe-line_segment.h \
+ live_effects/lpe-bounding-box.cpp \
+ live_effects/lpe-bounding-box.h \
+ live_effects/lpe-attach-path.cpp \
+ live_effects/lpe-attach-path.h \
+ live_effects/lpe-fill-between-strokes.cpp \
+ live_effects/lpe-fill-between-strokes.h \
+ live_effects/lpe-fill-between-many.cpp \
+ live_effects/lpe-fill-between-many.h \
+ live_effects/lpe-ellipse_5pts.cpp \
+ live_effects/lpe-ellipse_5pts.h \
+ live_effects/pathoutlineprovider.cpp \
+ live_effects/pathoutlineprovider.h \
+ live_effects/lpe-jointype.cpp \
+ live_effects/lpe-jointype.h \
+ live_effects/lpe-taperstroke.cpp \
+ live_effects/lpe-taperstroke.h
diff --git a/src/live_effects/effect-enum.h b/src/live_effects/effect-enum.h
index 43af33b53..383eec19e 100644
--- a/src/live_effects/effect-enum.h
+++ b/src/live_effects/effect-enum.h
@@ -28,6 +28,10 @@ enum EffectType {
PERSPECTIVE_PATH,
SPIRO,
LATTICE,
+ LATTICE2,
+ ROUGHEN,
+ SHOW_HANDLES,
+ SIMPLIFY,
ENVELOPE,
CONSTRUCT_GRID,
PERP_BISECTOR,
@@ -41,15 +45,26 @@ enum EffectType {
RULER,
BOOLOPS,
INTERPOLATE,
+ INTERPOLATE_POINTS,
TEXT_LABEL,
PATH_LENGTH,
LINE_SEGMENT,
DOEFFECTSTACK_TEST,
+ BSPLINE,
DYNASTROKE,
RECURSIVE_SKELETON,
EXTRUDE,
POWERSTROKE,
CLONE_ORIGINAL,
+ ATTACH_PATH,
+ FILL_BETWEEN_STROKES,
+ FILL_BETWEEN_MANY,
+ ELLIPSE_5PTS,
+ BOUNDING_BOX,
+ JOIN_TYPE,
+ TAPER_STROKE,
+ PERSPECTIVE_ENVELOPE,
+ FILLET_CHAMFER,
INVALID_LPE // This must be last (I made it such that it is not needed anymore I think..., Don't trust on it being last. - johan)
};
diff --git a/src/live_effects/effect.cpp b/src/live_effects/effect.cpp
index 12990ee24..e49a15dd0 100644
--- a/src/live_effects/effect.cpp
+++ b/src/live_effects/effect.cpp
@@ -5,7 +5,7 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-//#define LPE_ENABLE_TEST_EFFECTS
+//#define LPE_ENABLE_TEST_EFFECTS //uncomment for toy effects
#ifdef HAVE_CONFIG_H
# include "config.h"
@@ -25,8 +25,13 @@
#include "live_effects/lpe-curvestitch.h"
#include "live_effects/lpe-circle_with_radius.h"
#include "live_effects/lpe-perspective_path.h"
+#include "live_effects/lpe-perspective-envelope.h"
#include "live_effects/lpe-spiro.h"
#include "live_effects/lpe-lattice.h"
+#include "live_effects/lpe-lattice2.h"
+#include "live_effects/lpe-roughen.h"
+#include "live_effects/lpe-show_handles.h"
+#include "live_effects/lpe-simplify.h"
#include "live_effects/lpe-envelope.h"
#include "live_effects/lpe-constructgrid.h"
#include "live_effects/lpe-perp_bisector.h"
@@ -40,6 +45,7 @@
#include "live_effects/lpe-ruler.h"
#include "live_effects/lpe-boolops.h"
#include "live_effects/lpe-interpolate.h"
+#include "live_effects/lpe-interpolate_points.h"
#include "live_effects/lpe-text_label.h"
#include "live_effects/lpe-path_length.h"
#include "live_effects/lpe-line_segment.h"
@@ -47,6 +53,15 @@
#include "live_effects/lpe-extrude.h"
#include "live_effects/lpe-powerstroke.h"
#include "live_effects/lpe-clone-original.h"
+#include "live_effects/lpe-bspline.h"
+#include "live_effects/lpe-attach-path.h"
+#include "live_effects/lpe-fill-between-strokes.h"
+#include "live_effects/lpe-fill-between-many.h"
+#include "live_effects/lpe-ellipse_5pts.h"
+#include "live_effects/lpe-bounding-box.h"
+#include "live_effects/lpe-jointype.h"
+#include "live_effects/lpe-taperstroke.h"
+#include "live_effects/lpe-fillet-chamfer.h"
#include "xml/node-event-vector.h"
#include "sp-object.h"
@@ -59,9 +74,7 @@
#include "xml/document.h"
#include <glibmm/i18n.h>
#include "ui/tools/pen-tool.h"
-#include "tools-switch.h"
-#include "message-stack.h"
-#include "desktop.h"
+#include "ui/tools-switch.h"
#include "knotholder.h"
#include "sp-lpe-item.h"
#include "live_effects/lpeobject.h"
@@ -105,7 +118,7 @@ const Util::EnumData<EffectType> LPETypeData[] = {
{TEXT_LABEL, N_("Text label"), "text_label"},
#endif
/* 0.46 */
- {BEND_PATH, N_("Bend"), "bend_path"},
+ {BEND_PATH, N_("Bend"), "bend_path"},
{GEARS, N_("Gears"), "gears"},
{PATTERN_ALONG_PATH, N_("Pattern Along Path"), "skeletal"}, // for historic reasons, this effect is called skeletal(strokes) in Inkscape:SVG
{CURVE_STITCH, N_("Stitch Sub-Paths"), "curvestitching"},
@@ -119,9 +132,27 @@ const Util::EnumData<EffectType> LPETypeData[] = {
{ROUGH_HATCHES, N_("Hatches (rough)"), "rough_hatches"},
{SKETCH, N_("Sketch"), "sketch"},
{RULER, N_("Ruler"), "ruler"},
-/* 0.49 */
- {POWERSTROKE, N_("Power stroke"), "powerstroke"},
- {CLONE_ORIGINAL, N_("Clone original path"), "clone_original"},
+/* 0.91 */
+ {POWERSTROKE, N_("Power stroke"), "powerstroke"},
+ {CLONE_ORIGINAL, N_("Clone original path"), "clone_original"},
+/* EXPERIMENTAL */
+ {SHOW_HANDLES, N_("Show handles"), "show_handles"},
+ {ROUGHEN, N_("Roughen"), "roughen"},
+ {BSPLINE, N_("BSpline"), "bspline"},
+ {JOIN_TYPE, N_("Join type"), "join_type"},
+ {TAPER_STROKE, N_("Taper stroke"), "taper_stroke"},
+/* Ponyscape */
+ {ATTACH_PATH, N_("Attach path"), "attach_path"},
+ {FILL_BETWEEN_STROKES, N_("Fill between strokes"), "fill_between_strokes"},
+ {FILL_BETWEEN_MANY, N_("Fill between many"), "fill_between_many"},
+ {ELLIPSE_5PTS, N_("Ellipse by 5 points"), "ellipse_5pts"},
+ {BOUNDING_BOX, N_("Bounding Box"), "bounding_box"},
+/* 0.91 */
+ {SIMPLIFY, N_("Simplify"), "simplify"},
+ {LATTICE2, N_("Lattice Deformation 2"), "lattice2"},
+ {PERSPECTIVE_ENVELOPE, N_("Perspective/Envelope"), "perspective-envelope"},
+ {FILLET_CHAMFER, N_("Fillet/Chamfer"), "fillet-chamfer"},
+ {INTERPOLATE_POINTS, N_("Interpolate points"), "interpolate_points"},
};
const Util::EnumDataConverter<EffectType> LPETypeConverter(LPETypeData, sizeof(LPETypeData)/sizeof(*LPETypeData));
@@ -218,6 +249,9 @@ Effect::New(EffectType lpenr, LivePathEffectObject *lpeobj)
case INTERPOLATE:
neweffect = static_cast<Effect*> ( new LPEInterpolate(lpeobj) );
break;
+ case INTERPOLATE_POINTS:
+ neweffect = static_cast<Effect*> ( new LPEInterpolatePoints(lpeobj) );
+ break;
case TEXT_LABEL:
neweffect = static_cast<Effect*> ( new LPETextLabel(lpeobj) );
break;
@@ -230,6 +264,9 @@ Effect::New(EffectType lpenr, LivePathEffectObject *lpeobj)
case DOEFFECTSTACK_TEST:
neweffect = static_cast<Effect*> ( new LPEdoEffectStackTest(lpeobj) );
break;
+ case BSPLINE:
+ neweffect = static_cast<Effect*> ( new LPEBSpline(lpeobj) );
+ break;
case DYNASTROKE:
neweffect = static_cast<Effect*> ( new LPEDynastroke(lpeobj) );
break;
@@ -245,8 +282,47 @@ Effect::New(EffectType lpenr, LivePathEffectObject *lpeobj)
case CLONE_ORIGINAL:
neweffect = static_cast<Effect*> ( new LPECloneOriginal(lpeobj) );
break;
+ case ATTACH_PATH:
+ neweffect = static_cast<Effect*> ( new LPEAttachPath(lpeobj) );
+ break;
+ case FILL_BETWEEN_STROKES:
+ neweffect = static_cast<Effect*> ( new LPEFillBetweenStrokes(lpeobj) );
+ break;
+ case FILL_BETWEEN_MANY:
+ neweffect = static_cast<Effect*> ( new LPEFillBetweenMany(lpeobj) );
+ break;
+ case ELLIPSE_5PTS:
+ neweffect = static_cast<Effect*> ( new LPEEllipse5Pts(lpeobj) );
+ break;
+ case BOUNDING_BOX:
+ neweffect = static_cast<Effect*> ( new LPEBoundingBox(lpeobj) );
+ break;
+ case JOIN_TYPE:
+ neweffect = static_cast<Effect*> ( new LPEJoinType(lpeobj) );
+ break;
+ case TAPER_STROKE:
+ neweffect = static_cast<Effect*> ( new LPETaperStroke(lpeobj) );
+ break;
+ case SIMPLIFY:
+ neweffect = static_cast<Effect*> ( new LPESimplify(lpeobj) );
+ break;
+ case LATTICE2:
+ neweffect = static_cast<Effect*> ( new LPELattice2(lpeobj) );
+ break;
+ case PERSPECTIVE_ENVELOPE:
+ neweffect = static_cast<Effect*> ( new LPEPerspectiveEnvelope(lpeobj) );
+ break;
+ case FILLET_CHAMFER:
+ neweffect = static_cast<Effect*> ( new LPEFilletChamfer(lpeobj) );
+ break;
+ case ROUGHEN:
+ neweffect = static_cast<Effect*> ( new LPERoughen(lpeobj) );
+ break;
+ case SHOW_HANDLES:
+ neweffect = static_cast<Effect*> ( new LPEShowHandles(lpeobj) );
+ break;
default:
- g_warning("LivePathEffect::Effect::New called with invalid patheffect type (%d)", lpenr);
+ g_warning("LivePathEffect::Effect::New called with invalid patheffect type (%d)", lpenr);
neweffect = NULL;
break;
}
@@ -292,6 +368,7 @@ Effect::Effect(LivePathEffectObject *lpeobject)
{
registerParameter( dynamic_cast<Parameter *>(&is_visible) );
is_visible.widget_is_visible = false;
+ current_zoom = 0.0;
}
Effect::~Effect()
@@ -320,6 +397,38 @@ Effect::doOnApply (SPLPEItem const*/*lpeitem*/)
{
}
+void
+Effect::setSelectedNodePoints(std::vector<Geom::Point> sNP)
+{
+ selectedNodesPoints = sNP;
+}
+
+void
+Effect::setCurrentZoom(double cZ)
+{
+ current_zoom = cZ;
+}
+
+bool
+Effect::isNodePointSelected(Geom::Point const &nodePoint) const
+{
+ if (selectedNodesPoints.size() > 0) {
+ using Geom::X;
+ using Geom::Y;
+ for (std::vector<Geom::Point>::const_iterator i = selectedNodesPoints.begin();
+ i != selectedNodesPoints.end(); ++i) {
+ Geom::Point p = *i;
+ Geom::Affine transformCoordinate = sp_lpe_item->i2dt_affine();
+ Geom::Point p2(nodePoint[X],nodePoint[Y]);
+ p2 *= transformCoordinate;
+ if (Geom::are_near(p, p2, 0.01)) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
/**
* Is performed each time before the effect is updated.
*/
@@ -329,6 +438,35 @@ Effect::doBeforeEffect (SPLPEItem const*/*lpeitem*/)
//Do nothing for simple effects
}
+void Effect::doAfterEffect (SPLPEItem const* /*lpeitem*/)
+{
+}
+
+void Effect::doOnRemove (SPLPEItem const* /*lpeitem*/)
+{
+}
+
+//secret impl methods (shhhh!)
+void Effect::doOnApply_impl(SPLPEItem const* lpeitem)
+{
+ sp_lpe_item = const_cast<SPLPEItem *>(lpeitem);
+ defaultUnit = &sp_lpe_item->document->getDefaultUnit()->abbr;
+ /*sp_curve = SP_SHAPE(sp_lpe_item)->getCurve();
+ pathvector_before_effect = sp_curve->get_pathvector();*/
+ doOnApply(lpeitem);
+}
+
+void Effect::doBeforeEffect_impl(SPLPEItem const* lpeitem)
+{
+ sp_lpe_item = const_cast<SPLPEItem *>(lpeitem);
+ defaultUnit = &sp_lpe_item->document->getDefaultUnit()->abbr;
+ //printf("(SPLPEITEM*) %p\n", sp_lpe_item);
+ sp_curve = SP_SHAPE(sp_lpe_item)->getCurve();
+ pathvector_before_effect = sp_curve->get_pathvector();
+
+ doBeforeEffect(lpeitem);
+}
+
/**
* Effects can have a parameter path set before they are applied by accepting a nonzero number of
* mouse clicks. This method activates the pen context, which waits for the specified number of
@@ -496,11 +634,6 @@ Effect::getCanvasIndicators(SPLPEItem const* lpeitem)
{
std::vector<Geom::PathVector> hp_vec;
- if (!SP_IS_SHAPE(lpeitem)) {
-// g_print ("How to handle helperpaths for non-shapes?\n"); // non-shapes are for example SPGroups.
- return hp_vec;
- }
-
// add indicators provided by the effect itself
addCanvasIndicators(lpeitem, hp_vec);
diff --git a/src/live_effects/effect.h b/src/live_effects/effect.h
index 1da9b4cc9..7da76b267 100644
--- a/src/live_effects/effect.h
+++ b/src/live_effects/effect.h
@@ -13,6 +13,7 @@
#include "parameter/bool.h"
#include "effect-enum.h"
+
#define LPE_CONVERSION_TOLERANCE 0.01 // FIXME: find good solution for this.
class SPDocument;
@@ -53,8 +54,18 @@ public:
EffectType effectType() const;
+ //basically, to get this method called before the derived classes, a bit
+ //of indirection is needed. We first call these methods, then the below.
+ void doOnApply_impl(SPLPEItem const* lpeitem);
+ void doBeforeEffect_impl(SPLPEItem const* lpeitem);
+ void setCurrentZoom(double cZ);
+ void setSelectedNodePoints(std::vector<Geom::Point> sNP);
+ bool isNodePointSelected(Geom::Point const &nodePoint) const;
virtual void doOnApply (SPLPEItem const* lpeitem);
virtual void doBeforeEffect (SPLPEItem const* lpeitem);
+
+ virtual void doAfterEffect (SPLPEItem const* lpeitem);
+ virtual void doOnRemove (SPLPEItem const* lpeitem);
void writeParamsToSVG();
@@ -101,6 +112,7 @@ public:
Inkscape::XML::Node * getRepr();
SPDocument * getSPDoc();
LivePathEffectObject * getLPEObj() {return lpeobj;};
+ LivePathEffectObject const * getLPEObj() const {return lpeobj;};
Parameter * getParameter(const char * key);
void readallParameters(Inkscape::XML::Node const* repr);
@@ -146,6 +158,12 @@ protected:
// instead of normally 'splitting' the path into continuous pwd2 paths and calling doEffect_pwd2 for each.
bool concatenate_before_pwd2;
+ SPLPEItem * sp_lpe_item; // these get stored in doBeforeEffect_impl, and derived classes may do as they please with them.
+ Glib::ustring const * defaultUnit; // these get stored in doBeforeEffect_impl, and derived classes may do as they please with them.
+ double current_zoom;
+ std::vector<Geom::Point> selectedNodesPoints;
+ SPCurve * sp_curve;
+ std::vector<Geom::Path> pathvector_before_effect;
private:
bool provides_own_flash_paths; // if true, the standard flash path is suppressed
diff --git a/src/live_effects/lpe-attach-path.cpp b/src/live_effects/lpe-attach-path.cpp
new file mode 100644
index 000000000..768c66ee2
--- /dev/null
+++ b/src/live_effects/lpe-attach-path.cpp
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) Theodore Janeczko 2012 <flutterguy317@gmail.com>
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <glibmm/i18n.h>
+#include <math.h>
+
+#include "live_effects/lpe-attach-path.h"
+
+#include "display/curve.h"
+#include "sp-item.h"
+#include "2geom/path.h"
+#include "sp-shape.h"
+#include "sp-text.h"
+#include "2geom/bezier-curve.h"
+#include "2geom/path-sink.h"
+#include "parameter/parameter.h"
+#include "live_effects/parameter/point.h"
+#include "parameter/originalpath.h"
+#include "2geom/affine.h"
+
+namespace Inkscape {
+namespace LivePathEffect {
+
+LPEAttachPath::LPEAttachPath(LivePathEffectObject *lpeobject) :
+ Effect(lpeobject),
+ start_path(_("Start path:"), _("Path to attach to the start of this path"), "startpath", &wr, this),
+ start_path_position(_("Start path position:"), _("Position to attach path start to"), "startposition", &wr, this, 0.0),
+ start_path_curve_start(_("Start path curve start:"), _("Starting curve"), "startcurvestart", &wr, this, Geom::Point(20,0)/*, true*/),
+ start_path_curve_end(_("Start path curve end:"), _("Ending curve"), "startcurveend", &wr, this, Geom::Point(20,0)/*, true*/),
+ end_path(_("End path:"), _("Path to attach to the end of this path"), "endpath", &wr, this),
+ end_path_position(_("End path position:"), _("Position to attach path end to"), "endposition", &wr, this, 0.0),
+ end_path_curve_start(_("End path curve start:"), _("Starting curve"), "endcurvestart", &wr, this, Geom::Point(20,0)/*, true*/),
+ end_path_curve_end(_("End path curve end:"), _("Ending curve"), "endcurveend", &wr, this, Geom::Point(20,0)/*, true*/)
+{
+ registerParameter(&start_path);
+ registerParameter(&start_path_position);
+ registerParameter(&start_path_curve_start);
+ registerParameter(&start_path_curve_end);
+
+ registerParameter(&end_path);
+ registerParameter(&end_path_position);
+ registerParameter(&end_path_curve_start);
+ registerParameter(&end_path_curve_end);
+
+ //perceived_path = true;
+ show_orig_path = true;
+ curve_start_previous_origin = start_path_curve_end.getOrigin();
+ curve_end_previous_origin = end_path_curve_end.getOrigin();
+}
+
+LPEAttachPath::~LPEAttachPath()
+{
+
+}
+
+void LPEAttachPath::resetDefaults(SPItem const * /*item*/)
+{
+ curve_start_previous_origin = start_path_curve_end.getOrigin();
+ curve_end_previous_origin = end_path_curve_end.getOrigin();
+}
+
+void LPEAttachPath::doEffect (SPCurve * curve)
+{
+ std::vector<Geom::Path> this_pathv = curve->get_pathvector();
+ if (sp_lpe_item && !this_pathv.empty()) {
+ Geom::Path p = Geom::Path(this_pathv.front().initialPoint());
+
+ bool set_start_end = start_path_curve_end.getOrigin() != curve_start_previous_origin;
+ bool set_end_end = end_path_curve_end.getOrigin() != curve_end_previous_origin;
+
+ if (start_path.linksToPath()) {
+
+ std::vector<Geom::Path> linked_pathv = start_path.get_pathvector();
+ Geom::Affine linkedtransform = start_path.getObject()->getRelativeTransform(sp_lpe_item);
+
+ if ( !linked_pathv.empty() )
+ {
+ Geom::Path transformedpath = linked_pathv.front() * linkedtransform;
+ start_path_curve_start.setOrigin(this_pathv.front().initialPoint());
+
+ std::vector<Geom::Point> derivs = this_pathv.front().front().pointAndDerivatives(0, 3);
+
+ for (unsigned deriv_n = 1; deriv_n < derivs.size(); deriv_n++) {
+ Geom::Coord length = derivs[deriv_n].length();
+ if ( ! Geom::are_near(length, 0) ) {
+ if (set_start_end) {
+ start_path_position.param_set_value(transformedpath.nearestPoint(start_path_curve_end.getOrigin()));
+ }
+
+ if (start_path_position > transformedpath.size()) {
+ start_path_position.param_set_value(transformedpath.size());
+ } else if (start_path_position < 0) {
+ start_path_position.param_set_value(0);
+ }
+ const Geom::Curve *c = start_path_position >= transformedpath.size() ? &transformedpath.back() : &transformedpath.at_index((int)start_path_position);
+
+ std::vector<Geom::Point> derivs_2 = c->pointAndDerivatives(start_path_position >= transformedpath.size() ? 1 : (start_path_position - (int)start_path_position), 3);
+ for (unsigned deriv_n_2 = 1; deriv_n_2 < derivs_2.size(); deriv_n_2++) {
+ Geom::Coord length_2 = derivs[deriv_n_2].length();
+ if ( ! Geom::are_near(length_2, 0) ) {
+ start_path_curve_end.setOrigin(derivs_2[0]);
+ curve_start_previous_origin = start_path_curve_end.getOrigin();
+
+ double startangle = atan2(start_path_curve_start.getVector().y(), start_path_curve_start.getVector().x());
+ double endangle = atan2(start_path_curve_end.getVector().y(), start_path_curve_end.getVector().x());
+ double startderiv = atan2(derivs[deriv_n].y(), derivs[deriv_n].x());
+ double endderiv = atan2(derivs_2[deriv_n_2].y(), derivs_2[deriv_n_2].x());
+ Geom::Point pt1 = Geom::Point(start_path_curve_start.getVector().length() * cos(startangle + startderiv), start_path_curve_start.getVector().length() * sin(startangle + startderiv));
+ Geom::Point pt2 = Geom::Point(start_path_curve_end.getVector().length() * cos(endangle + endderiv), start_path_curve_end.getVector().length() * sin(endangle + endderiv));
+ p = Geom::Path(derivs_2[0]);
+ p.appendNew<Geom::CubicBezier>(-pt2 + derivs_2[0], -pt1 + this_pathv.front().initialPoint(), this_pathv.front().initialPoint());
+ break;
+
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ p.append(this_pathv.front());
+
+ if (end_path.linksToPath()) {
+
+ std::vector<Geom::Path> linked_pathv = end_path.get_pathvector();
+ Geom::Affine linkedtransform = end_path.getObject()->getRelativeTransform(sp_lpe_item);
+
+ if ( !linked_pathv.empty() )
+ {
+ Geom::Path transformedpath = linked_pathv.front() * linkedtransform;
+ Geom::Curve * last_seg_reverse = this_pathv.front().back().reverse();
+
+ end_path_curve_start.setOrigin(last_seg_reverse->initialPoint());
+
+ std::vector<Geom::Point> derivs = last_seg_reverse->pointAndDerivatives(0, 3);
+ for (unsigned deriv_n = 1; deriv_n < derivs.size(); deriv_n++) {
+ Geom::Coord length = derivs[deriv_n].length();
+ if ( ! Geom::are_near(length, 0) ) {
+ if (set_end_end) {
+ end_path_position.param_set_value(transformedpath.nearestPoint(end_path_curve_end.getOrigin()));
+ }
+
+ if (end_path_position > transformedpath.size()) {
+ end_path_position.param_set_value(transformedpath.size());
+ } else if (end_path_position < 0) {
+ end_path_position.param_set_value(0);
+ }
+ const Geom::Curve *c = end_path_position >= transformedpath.size() ? &transformedpath.back() : &transformedpath.at_index((int)end_path_position);
+
+ std::vector<Geom::Point> derivs_2 = c->pointAndDerivatives(end_path_position >= transformedpath.size() ? 1 : (end_path_position - (int)end_path_position), 3);
+ for (unsigned deriv_n_2 = 1; deriv_n_2 < derivs_2.size(); deriv_n_2++) {
+ Geom::Coord length_2 = derivs[deriv_n_2].length();
+ if ( ! Geom::are_near(length_2, 0) ) {
+
+ end_path_curve_end.setOrigin(derivs_2[0]);
+ curve_end_previous_origin = end_path_curve_end.getOrigin();
+
+ double startangle = atan2(end_path_curve_start.getVector().y(), end_path_curve_start.getVector().x());
+ double endangle = atan2(end_path_curve_end.getVector().y(), end_path_curve_end.getVector().x());
+ double startderiv = atan2(derivs[deriv_n].y(), derivs[deriv_n].x());
+ double endderiv = atan2(derivs_2[deriv_n_2].y(), derivs_2[deriv_n_2].x());
+ Geom::Point pt1 = Geom::Point(end_path_curve_start.getVector().length() * cos(startangle + startderiv), end_path_curve_start.getVector().length() * sin(startangle + startderiv));
+ Geom::Point pt2 = Geom::Point(end_path_curve_end.getVector().length() * cos(endangle + endderiv), end_path_curve_end.getVector().length() * sin(endangle + endderiv));
+ p.appendNew<Geom::CubicBezier>(-pt1 + this_pathv.front().finalPoint(), -pt2 + derivs_2[0], derivs_2[0]);
+
+ break;
+
+ }
+ }
+ break;
+ }
+ }
+ delete last_seg_reverse;
+ }
+ }
+ Geom::PathVector outvector;
+ outvector.push_back(p);
+ curve->set_pathvector(outvector);
+ }
+}
+
+} // namespace LivePathEffect
+} /* namespace Inkscape */
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/live_effects/lpe-attach-path.h b/src/live_effects/lpe-attach-path.h
new file mode 100644
index 000000000..1d6c590d1
--- /dev/null
+++ b/src/live_effects/lpe-attach-path.h
@@ -0,0 +1,52 @@
+#ifndef INKSCAPE_LPE_ATTACH_PATH_H
+#define INKSCAPE_LPE_ATTACH_PATH_H
+
+/*
+ * Inkscape::LPEAttachPath
+ *
+ * Copyright (C) Ted Janeczko 2012 <flutterguy317@gmail.com>
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "live_effects/effect.h"
+#include "live_effects/parameter/parameter.h"
+#include "live_effects/parameter/point.h"
+#include "live_effects/parameter/originalpath.h"
+#include "live_effects/parameter/vector.h"
+#include "live_effects/parameter/bool.h"
+#include "live_effects/parameter/transformedpoint.h"
+
+namespace Inkscape {
+namespace LivePathEffect {
+
+class LPEAttachPath : public Effect {
+public:
+ LPEAttachPath(LivePathEffectObject *lpeobject);
+ virtual ~LPEAttachPath();
+
+ virtual void doEffect (SPCurve * curve);
+ virtual void resetDefaults(SPItem const * item);
+
+private:
+ LPEAttachPath(const LPEAttachPath&);
+ LPEAttachPath& operator=(const LPEAttachPath&);
+
+ Geom::Point curve_start_previous_origin;
+ Geom::Point curve_end_previous_origin;
+
+ OriginalPathParam start_path;
+ ScalarParam start_path_position;
+ TransformedPointParam start_path_curve_start;
+ VectorParam start_path_curve_end;
+
+ OriginalPathParam end_path;
+ ScalarParam end_path_position;
+ TransformedPointParam end_path_curve_start;
+ VectorParam end_path_curve_end;
+};
+
+}; //namespace LivePathEffect
+}; //namespace Inkscape
+
+#endif
diff --git a/src/live_effects/lpe-bendpath.cpp b/src/live_effects/lpe-bendpath.cpp
index eaf9fe4a6..33171b184 100644
--- a/src/live_effects/lpe-bendpath.cpp
+++ b/src/live_effects/lpe-bendpath.cpp
@@ -76,6 +76,9 @@ LPEBendPath::doBeforeEffect (SPLPEItem const* lpeitem)
{
// get the item bounding box
original_bbox(lpeitem);
+ SPLPEItem * item = const_cast<SPLPEItem*>(lpeitem);
+ item->apply_to_clippath(item);
+ item->apply_to_mask(item);
}
Geom::Piecewise<Geom::D2<Geom::SBasis> >
diff --git a/src/live_effects/lpe-bounding-box.cpp b/src/live_effects/lpe-bounding-box.cpp
new file mode 100644
index 000000000..bafd5e70e
--- /dev/null
+++ b/src/live_effects/lpe-bounding-box.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) Theodore Janeczko 2012 <flutterguy317@gmail.com>
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <glibmm/i18n.h>
+
+#include "live_effects/lpe-bounding-box.h"
+
+#include "display/curve.h"
+#include "sp-item.h"
+#include "2geom/path.h"
+#include "sp-shape.h"
+#include "sp-text.h"
+#include "2geom/bezier-curve.h"
+#include "lpe-bounding-box.h"
+
+namespace Inkscape {
+namespace LivePathEffect {
+
+LPEBoundingBox::LPEBoundingBox(LivePathEffectObject *lpeobject) :
+ Effect(lpeobject),
+ linked_path(_("Linked path:"), _("Path from which to take the original path data"), "linkedpath", &wr, this),
+ visual_bounds(_("Visual Bounds"), _("Uses the visual bounding box"), "visualbounds", &wr, this)
+{
+ registerParameter( dynamic_cast<Parameter *>(&linked_path) );
+ registerParameter( dynamic_cast<Parameter *>(&visual_bounds) );
+ //perceived_path = true;
+}
+
+LPEBoundingBox::~LPEBoundingBox()
+{
+
+}
+
+void LPEBoundingBox::doEffect (SPCurve * curve)
+{
+ if (curve) {
+ if ( linked_path.linksToPath() && linked_path.getObject() ) {
+ SPItem * item = linked_path.getObject();
+ Geom::OptRect bbox = visual_bounds.get_value() ? item->visualBounds() : item->geometricBounds();
+ Geom::Path p(Geom::Point(bbox->left(), bbox->top()));
+ p.appendNew<Geom::LineSegment>(Geom::Point(bbox->right(), bbox->top()));
+ p.appendNew<Geom::LineSegment>(Geom::Point(bbox->right(), bbox->bottom()));
+ p.appendNew<Geom::LineSegment>(Geom::Point(bbox->left(), bbox->bottom()));
+ p.appendNew<Geom::LineSegment>(Geom::Point(bbox->left(), bbox->top()));
+ std::vector<Geom::Path> out;
+ out.push_back(p);
+ curve->set_pathvector(out);
+ }
+ }
+}
+
+} // namespace LivePathEffect
+} /* namespace Inkscape */
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/live_effects/lpe-bounding-box.h b/src/live_effects/lpe-bounding-box.h
new file mode 100644
index 000000000..d028a20ac
--- /dev/null
+++ b/src/live_effects/lpe-bounding-box.h
@@ -0,0 +1,37 @@
+#ifndef INKSCAPE_LPE_BOUNDING_BOX_H
+#define INKSCAPE_LPE_BOUNDING_BOX_H
+
+/*
+ * Inkscape::LPEFillBetweenStrokes
+ *
+ * Copyright (C) Theodore Janeczko 2012 <flutterguy317@gmail.com>
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "live_effects/effect.h"
+#include "live_effects/parameter/originalpath.h"
+
+namespace Inkscape {
+namespace LivePathEffect {
+
+class LPEBoundingBox : public Effect {
+public:
+ LPEBoundingBox(LivePathEffectObject *lpeobject);
+ virtual ~LPEBoundingBox();
+
+ virtual void doEffect (SPCurve * curve);
+
+private:
+ OriginalPathParam linked_path;
+ BoolParam visual_bounds;
+
+private:
+ LPEBoundingBox(const LPEBoundingBox&);
+ LPEBoundingBox& operator=(const LPEBoundingBox&);
+};
+
+}; //namespace LivePathEffect
+}; //namespace Inkscape
+
+#endif
diff --git a/src/live_effects/lpe-bspline.cpp b/src/live_effects/lpe-bspline.cpp
new file mode 100644
index 000000000..c5390a0c9
--- /dev/null
+++ b/src/live_effects/lpe-bspline.cpp
@@ -0,0 +1,537 @@
+/*
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <gtkmm.h>
+
+#if WITH_GLIBMM_2_32
+# include <glibmm/threads.h>
+#endif
+
+#include <glib.h>
+#include <glibmm/i18n.h>
+
+
+#include "display/curve.h"
+#include <2geom/bezier-curve.h>
+#include <2geom/point.h>
+#include "helper/geom-curves.h"
+#include "live_effects/lpe-bspline.h"
+#include "live_effects/lpeobject.h"
+#include "live_effects/parameter/parameter.h"
+#include "ui/widget/scalar.h"
+#include "xml/repr.h"
+#include "svg/svg.h"
+#include "sp-path.h"
+#include "style.h"
+#include "document-private.h"
+#include "document.h"
+#include "document-undo.h"
+#include "verbs.h"
+#include "sp-lpe-item.h"
+#include "sp-namedview.h"
+#include "display/sp-canvas.h"
+#include <typeinfo>
+#include <vector>
+#include "util/units.h"
+// For handling un-continuous paths:
+#include "message-stack.h"
+#include "inkscape.h"
+
+using Inkscape::DocumentUndo;
+
+namespace Inkscape {
+namespace LivePathEffect {
+
+const double handleCubicGap = 0.01;
+const double noPower = 0.0;
+const double defaultStartPower = 0.3334;
+const double defaultEndPower = 0.6667;
+
+LPEBSpline::LPEBSpline(LivePathEffectObject *lpeobject)
+ : Effect(lpeobject),
+ // initialise your parameters here:
+ //testpointA(_("Test Point A"), _("Test A"), "ptA", &wr, this,
+ //Geom::Point(100,100)),
+ steps(_("Steps with CTRL:"), _("Change number of steps with CTRL pressed"), "steps", &wr, this, 2),
+ ignoreCusp(_("Ignore cusp nodes"), _("Change ignoring cusp nodes"), "ignoreCusp", &wr, this, true),
+ onlySelected(_("Change only selected nodes"), _("Change only selected nodes"), "onlySelected", &wr, this, false),
+ showHelper(_("Show helper paths"), _("Show helper paths"), "showHelper", &wr, this, false),
+ weight(_("Change weight:"), _("Change weight of the effect"), "weight", &wr, this, defaultStartPower)
+{
+ registerParameter(dynamic_cast<Parameter *>(&weight));
+ registerParameter(dynamic_cast<Parameter *>(&steps));
+ registerParameter(dynamic_cast<Parameter *>(&ignoreCusp));
+ registerParameter(dynamic_cast<Parameter *>(&onlySelected));
+ registerParameter(dynamic_cast<Parameter *>(&showHelper));
+
+ weight.param_set_range(noPower, 1);
+ weight.param_set_increments(0.1, 0.1);
+ weight.param_set_digits(4);
+
+ steps.param_set_range(1, 10);
+ steps.param_set_increments(1, 1);
+ steps.param_set_digits(0);
+}
+
+LPEBSpline::~LPEBSpline() {}
+
+void LPEBSpline::doBeforeEffect (SPLPEItem const* /*lpeitem*/)
+{
+ if(!hp.empty()){
+ hp.clear();
+ }
+}
+
+
+void LPEBSpline::doOnApply(SPLPEItem const* lpeitem)
+{
+ if (!SP_IS_SHAPE(lpeitem)) {
+ g_warning("LPE BSpline can only be applied to shapes (not groups).");
+ SPLPEItem * item = const_cast<SPLPEItem*>(lpeitem);
+ item->removeCurrentPathEffect(false);
+ }
+}
+
+void LPEBSpline::doEffect(SPCurve *curve)
+{
+
+ if (curve->get_segment_count() < 1){
+ return;
+ }
+ // Make copy of old path as it is changed during processing
+ Geom::PathVector const original_pathv = curve->get_pathvector();
+ curve->reset();
+ double radiusHelperNodes = 6.0;
+ radiusHelperNodes /= current_zoom;
+ radiusHelperNodes = Inkscape::Util::Quantity::convert(radiusHelperNodes, "px", *defaultUnit);
+ for (Geom::PathVector::const_iterator path_it = original_pathv.begin();
+ path_it != original_pathv.end(); ++path_it) {
+ if (path_it->empty())
+ continue;
+
+ Geom::Path::const_iterator curve_it1 = path_it->begin();
+ Geom::Path::const_iterator curve_it2 = ++(path_it->begin());
+ Geom::Path::const_iterator curve_endit = path_it->end_default();
+ SPCurve *nCurve = new SPCurve();
+ Geom::Point previousNode(0, 0);
+ Geom::Point node(0, 0);
+ Geom::Point pointAt1(0, 0);
+ Geom::Point pointAt2(0, 0);
+ Geom::Point nextPointAt1(0, 0);
+ Geom::D2<Geom::SBasis> SBasisIn;
+ Geom::D2<Geom::SBasis> SBasisOut;
+ Geom::D2<Geom::SBasis> SBasisHelper;
+ Geom::CubicBezier const *cubic = NULL;
+ if (path_it->closed()) {
+ // if the path is closed, maybe we have to stop a bit earlier because the
+ // closing line segment has zerolength.
+ const Geom::Curve &closingline =
+ path_it->back_closed(); // the closing line segment is always of type
+ // Geom::LineSegment.
+ if (are_near(closingline.initialPoint(), closingline.finalPoint())) {
+ // closingline.isDegenerate() did not work, because it only checks for
+ // *exact* zero length, which goes wrong for relative coordinates and
+ // rounding errors...
+ // the closing line segment has zero-length. So stop before that one!
+ curve_endit = path_it->end_open();
+ }
+ }
+ nCurve->moveto(curve_it1->initialPoint());
+ while (curve_it1 != curve_endit) {
+ SPCurve *in = new SPCurve();
+ in->moveto(curve_it1->initialPoint());
+ in->lineto(curve_it1->finalPoint());
+ cubic = dynamic_cast<Geom::CubicBezier const *>(&*curve_it1);
+ if (cubic) {
+ SBasisIn = in->first_segment()->toSBasis();
+ if(are_near((*cubic)[1],(*cubic)[0]) && !are_near((*cubic)[2],(*cubic)[3])) {
+ pointAt1 = SBasisIn.valueAt(defaultStartPower);
+ } else {
+ pointAt1 = SBasisIn.valueAt(Geom::nearest_point((*cubic)[1], *in->first_segment()));
+ }
+ if(are_near((*cubic)[2],(*cubic)[3]) && !are_near((*cubic)[1],(*cubic)[0])) {
+ pointAt2 = SBasisIn.valueAt(defaultEndPower);
+ } else {
+ pointAt2 = SBasisIn.valueAt(Geom::nearest_point((*cubic)[2], *in->first_segment()));
+ }
+ } else {
+ pointAt1 = in->first_segment()->initialPoint();
+ pointAt2 = in->first_segment()->finalPoint();
+ }
+ in->reset();
+ delete in;
+ if ( curve_it2 != curve_endit ) {
+ SPCurve *out = new SPCurve();
+ out->moveto(curve_it2->initialPoint());
+ out->lineto(curve_it2->finalPoint());
+ cubic = dynamic_cast<Geom::CubicBezier const *>(&*curve_it2);
+ if (cubic) {
+ SBasisOut = out->first_segment()->toSBasis();
+ if(are_near((*cubic)[1],(*cubic)[0]) && !are_near((*cubic)[2],(*cubic)[3])) {
+ nextPointAt1 = SBasisIn.valueAt(defaultStartPower);
+ } else {
+ nextPointAt1 = SBasisOut.valueAt(Geom::nearest_point((*cubic)[1], *out->first_segment()));
+ }
+ } else {
+ nextPointAt1 = out->first_segment()->initialPoint();
+ }
+ out->reset();
+ delete out;
+ }
+ if (path_it->closed() && curve_it2 == curve_endit) {
+ SPCurve *start = new SPCurve();
+ start->moveto(path_it->begin()->initialPoint());
+ start->lineto(path_it->begin()->finalPoint());
+ Geom::D2<Geom::SBasis> SBasisStart = start->first_segment()->toSBasis();
+ SPCurve *lineHelper = new SPCurve();
+ cubic = dynamic_cast<Geom::CubicBezier const *>(&*path_it->begin());
+ if (cubic) {
+ lineHelper->moveto(SBasisStart.valueAt(
+ Geom::nearest_point((*cubic)[1], *start->first_segment())));
+ } else {
+ lineHelper->moveto(start->first_segment()->initialPoint());
+ }
+ start->reset();
+ delete start;
+
+ SPCurve *end = new SPCurve();
+ end->moveto(curve_it1->initialPoint());
+ end->lineto(curve_it1->finalPoint());
+ Geom::D2<Geom::SBasis> SBasisEnd = end->first_segment()->toSBasis();
+ cubic = dynamic_cast<Geom::CubicBezier const *>(&*curve_it1);
+ if (cubic) {
+ lineHelper->lineto(SBasisEnd.valueAt(
+ Geom::nearest_point((*cubic)[2], *end->first_segment())));
+ } else {
+ lineHelper->lineto(end->first_segment()->finalPoint());
+ }
+ end->reset();
+ delete end;
+ SBasisHelper = lineHelper->first_segment()->toSBasis();
+ lineHelper->reset();
+ delete lineHelper;
+ node = SBasisHelper.valueAt(0.5);
+ nCurve->curveto(pointAt1, pointAt2, node);
+ nCurve->move_endpoints(node, node);
+ } else if ( curve_it2 == curve_endit) {
+ nCurve->curveto(pointAt1, pointAt2, curve_it1->finalPoint());
+ nCurve->move_endpoints(path_it->begin()->initialPoint(), curve_it1->finalPoint());
+ } else {
+ SPCurve *lineHelper = new SPCurve();
+ lineHelper->moveto(pointAt2);
+ lineHelper->lineto(nextPointAt1);
+ SBasisHelper = lineHelper->first_segment()->toSBasis();
+ lineHelper->reset();
+ delete lineHelper;
+ previousNode = node;
+ node = SBasisHelper.valueAt(0.5);
+ Geom::CubicBezier const *cubic2 = dynamic_cast<Geom::CubicBezier const *>(&*curve_it1);
+ if((cubic && are_near((*cubic)[0],(*cubic)[1])) || (cubic2 && are_near((*cubic2)[2],(*cubic2)[3]))) {
+ node = curve_it1->finalPoint();
+ }
+ nCurve->curveto(pointAt1, pointAt2, node);
+ }
+ if(!are_near(node,curve_it1->finalPoint()) && showHelper){
+ drawHandle(node, radiusHelperNodes);
+ }
+ ++curve_it1;
+ ++curve_it2;
+ }
+ //y cerramos la curva
+ if (path_it->closed()) {
+ nCurve->closepath_current();
+ }
+ curve->append(nCurve, false);
+ nCurve->reset();
+ delete nCurve;
+ }
+ if(showHelper){
+ Geom::PathVector const pathv = curve->get_pathvector();
+ hp.push_back(pathv[0]);
+ }
+}
+
+void
+LPEBSpline::drawHandle(Geom::Point p, double radiusHelperNodes)
+{
+ char const * svgd = "M 1,0.5 A 0.5,0.5 0 0 1 0.5,1 0.5,0.5 0 0 1 0,0.5 0.5,0.5 0 0 1 0.5,0 0.5,0.5 0 0 1 1,0.5 Z";
+ Geom::PathVector pathv = sp_svg_read_pathv(svgd);
+ Geom::Affine aff = Geom::Affine();
+ aff *= Geom::Scale(radiusHelperNodes);
+ pathv *= aff;
+ pathv += p - Geom::Point(0.5*radiusHelperNodes, 0.5*radiusHelperNodes);
+ hp.push_back(pathv[0]);
+}
+
+void
+LPEBSpline::addCanvasIndicators(SPLPEItem const */*lpeitem*/, std::vector<Geom::PathVector> &hp_vec)
+{
+ hp_vec.push_back(hp);
+}
+Gtk::Widget *LPEBSpline::newWidget()
+{
+ // use manage here, because after deletion of Effect object, others might
+ // still be pointing to this widget.
+ Gtk::VBox *vbox = Gtk::manage(new Gtk::VBox(Effect::newWidget()));
+
+ vbox->set_border_width(5);
+ std::vector<Parameter *>::iterator it = param_vector.begin();
+ while (it != param_vector.end()) {
+ if ((*it)->widget_is_visible) {
+ Parameter *param = *it;
+ Gtk::Widget *widg = dynamic_cast<Gtk::Widget *>(param->param_newWidget());
+ if (param->param_key == "weight") {
+ Gtk::HBox * buttons = Gtk::manage(new Gtk::HBox(true,0));
+ Gtk::Button *defaultWeight =
+ Gtk::manage(new Gtk::Button(Glib::ustring(_("Default weight"))));
+ defaultWeight->signal_clicked()
+ .connect(sigc::mem_fun(*this, &LPEBSpline::toDefaultWeight));
+ buttons->pack_start(*defaultWeight, true, true, 2);
+ Gtk::Button *makeCusp =
+ Gtk::manage(new Gtk::Button(Glib::ustring(_("Make cusp"))));
+ makeCusp->signal_clicked()
+ .connect(sigc::mem_fun(*this, &LPEBSpline::toMakeCusp));
+ buttons->pack_start(*makeCusp, true, true, 2);
+ vbox->pack_start(*buttons, true, true, 2);
+ }
+ if (param->param_key == "weight" || param->param_key == "steps") {
+ Inkscape::UI::Widget::Scalar *widgRegistered =
+ Gtk::manage(dynamic_cast<Inkscape::UI::Widget::Scalar *>(widg));
+ widgRegistered->signal_value_changed()
+ .connect(sigc::mem_fun(*this, &LPEBSpline::toWeight));
+ widg = dynamic_cast<Gtk::Widget *>(widgRegistered);
+ if (widg) {
+ Gtk::HBox * scalarParameter = dynamic_cast<Gtk::HBox *>(widg);
+ std::vector< Gtk::Widget* > childList = scalarParameter->get_children();
+ Gtk::Entry* entryWidg = dynamic_cast<Gtk::Entry *>(childList[1]);
+ entryWidg->set_width_chars(6);
+ }
+ }
+ if (param->param_key == "onlySelected") {
+ Gtk::CheckButton *widgRegistered =
+ Gtk::manage(dynamic_cast<Gtk::CheckButton *>(widg));
+ widg = dynamic_cast<Gtk::Widget *>(widgRegistered);
+ }
+ if (param->param_key == "ignoreCusp") {
+ Gtk::CheckButton *widgRegistered =
+ Gtk::manage(dynamic_cast<Gtk::CheckButton *>(widg));
+ widg = dynamic_cast<Gtk::Widget *>(widgRegistered);
+ }
+ Glib::ustring *tip = param->param_getTooltip();
+ if (widg) {
+ vbox->pack_start(*widg, true, true, 2);
+ if (tip) {
+ widg->set_tooltip_text(*tip);
+ } else {
+ widg->set_tooltip_text("");
+ widg->set_has_tooltip(false);
+ }
+ }
+ }
+
+ ++it;
+ }
+ return dynamic_cast<Gtk::Widget *>(vbox);
+}
+
+void LPEBSpline::toDefaultWeight()
+{
+ changeWeight(defaultStartPower);
+}
+
+void LPEBSpline::toMakeCusp()
+{
+ changeWeight(noPower);
+}
+
+void LPEBSpline::toWeight()
+{
+ changeWeight(weight);
+}
+
+void LPEBSpline::changeWeight(double weightValue)
+{
+ SPPath *path = SP_PATH(sp_lpe_item);
+ SPCurve *curve = path->get_curve_for_edit();
+ LPEBSpline::doBSplineFromWidget(curve, weightValue);
+ gchar *str = sp_svg_write_path(curve->get_pathvector());
+ path->getRepr()->setAttribute("inkscape:original-d", str);
+}
+
+void LPEBSpline::doBSplineFromWidget(SPCurve *curve, double weightValue)
+{
+ using Geom::X;
+ using Geom::Y;
+ if (curve->get_segment_count() < 1)
+ return;
+ // Make copy of old path as it is changed during processing
+ Geom::PathVector const original_pathv = curve->get_pathvector();
+ curve->reset();
+
+ for (Geom::PathVector::const_iterator path_it = original_pathv.begin();
+ path_it != original_pathv.end(); ++path_it) {
+
+ if (path_it->empty()){
+ continue;
+ }
+ Geom::Path::const_iterator curve_it1 = path_it->begin();
+ Geom::Path::const_iterator curve_it2 = ++(path_it->begin());
+ Geom::Path::const_iterator curve_endit = path_it->end_default();
+
+ SPCurve *nCurve = new SPCurve();
+ Geom::Point pointAt0(0, 0);
+ Geom::Point pointAt1(0, 0);
+ Geom::Point pointAt2(0, 0);
+ Geom::Point pointAt3(0, 0);
+ Geom::D2<Geom::SBasis> SBasisIn;
+ Geom::D2<Geom::SBasis> SBasisOut;
+ Geom::CubicBezier const *cubic = NULL;
+ if (path_it->closed()) {
+ // if the path is closed, maybe we have to stop a bit earlier because the
+ // closing line segment has zerolength.
+ const Geom::Curve &closingline =
+ path_it->back_closed(); // the closing line segment is always of type
+ // Geom::LineSegment.
+ if (are_near(closingline.initialPoint(), closingline.finalPoint())) {
+ // closingline.isDegenerate() did not work, because it only checks for
+ // *exact* zero length, which goes wrong for relative coordinates and
+ // rounding errors...
+ // the closing line segment has zero-length. So stop before that one!
+ curve_endit = path_it->end_open();
+ }
+ }
+ nCurve->moveto(curve_it1->initialPoint());
+ while (curve_it1 != curve_endit) {
+ SPCurve *in = new SPCurve();
+ in->moveto(curve_it1->initialPoint());
+ in->lineto(curve_it1->finalPoint());
+ cubic = dynamic_cast<Geom::CubicBezier const *>(&*curve_it1);
+ pointAt0 = in->first_segment()->initialPoint();
+ pointAt3 = in->first_segment()->finalPoint();
+ SBasisIn = in->first_segment()->toSBasis();
+ if (!onlySelected) {
+ if (cubic) {
+ if (!ignoreCusp || !Geom::are_near((*cubic)[1], pointAt0)) {
+ pointAt1 = SBasisIn.valueAt(weightValue);
+ if (weightValue != noPower) {
+ pointAt1 =
+ Geom::Point(pointAt1[X] + handleCubicGap, pointAt1[Y] + handleCubicGap);
+ }
+ } else {
+ pointAt1 = in->first_segment()->initialPoint();
+ }
+ if (!ignoreCusp || !Geom::are_near((*cubic)[2], pointAt3)) {
+ pointAt2 = SBasisIn.valueAt(1 - weightValue);
+ if (weightValue != noPower) {
+ pointAt2 =
+ Geom::Point(pointAt2[X] + handleCubicGap, pointAt2[Y] + handleCubicGap);
+ }
+ } else {
+ pointAt2 = in->first_segment()->finalPoint();
+ }
+ } else {
+ if (!ignoreCusp && weightValue != noPower) {
+ pointAt1 = SBasisIn.valueAt(weightValue);
+ if (weightValue != noPower) {
+ pointAt1 =
+ Geom::Point(pointAt1[X] + handleCubicGap, pointAt1[Y] + handleCubicGap);
+ }
+ pointAt2 = SBasisIn.valueAt(1 - weightValue);
+ if (weightValue != noPower) {
+ pointAt2 =
+ Geom::Point(pointAt2[X] + handleCubicGap, pointAt2[Y] + handleCubicGap);
+ }
+ } else {
+ pointAt1 = in->first_segment()->initialPoint();
+ pointAt2 = in->first_segment()->finalPoint();
+ }
+ }
+ } else {
+ if (cubic) {
+ if (!ignoreCusp || !Geom::are_near((*cubic)[1], pointAt0)) {
+ if (isNodePointSelected(pointAt0)) {
+ pointAt1 = SBasisIn.valueAt(weightValue);
+ if (weightValue != noPower) {
+ pointAt1 =
+ Geom::Point(pointAt1[X] + handleCubicGap, pointAt1[Y] + handleCubicGap);
+ }
+ } else {
+ pointAt1 = (*cubic)[1];
+ }
+ } else {
+ pointAt1 = in->first_segment()->initialPoint();
+ }
+ if (!ignoreCusp || !Geom::are_near((*cubic)[2], pointAt3)) {
+ if (isNodePointSelected(pointAt3)) {
+ pointAt2 = SBasisIn.valueAt(1 - weightValue);
+ if (weightValue != noPower) {
+ pointAt2 =
+ Geom::Point(pointAt2[X] + handleCubicGap, pointAt2[Y] + handleCubicGap);
+ }
+ } else {
+ pointAt2 = (*cubic)[2];
+ }
+ } else {
+ pointAt2 = in->first_segment()->finalPoint();
+ }
+ } else {
+ if (!ignoreCusp && weightValue != noPower) {
+ if (isNodePointSelected(pointAt0)) {
+ pointAt1 = SBasisIn.valueAt(weightValue);
+ pointAt1 =
+ Geom::Point(pointAt1[X] + handleCubicGap, pointAt1[Y] + handleCubicGap);
+ } else {
+ pointAt1 = in->first_segment()->initialPoint();
+ }
+ if (isNodePointSelected(pointAt3)) {
+ pointAt2 = SBasisIn.valueAt(weightValue);
+ pointAt2 =
+ Geom::Point(pointAt2[X] + handleCubicGap, pointAt2[Y] + handleCubicGap);
+ } else {
+ pointAt2 = in->first_segment()->finalPoint();
+ }
+ } else {
+ pointAt1 = in->first_segment()->initialPoint();
+ pointAt2 = in->first_segment()->finalPoint();
+ }
+ }
+ }
+ in->reset();
+ delete in;
+ nCurve->curveto(pointAt1, pointAt2, pointAt3);
+ ++curve_it1;
+ ++curve_it2;
+ }
+ if (path_it->closed()) {
+ nCurve->move_endpoints(path_it->begin()->initialPoint(),
+ path_it->begin()->initialPoint());
+ } else {
+ nCurve->move_endpoints(path_it->begin()->initialPoint(), pointAt3);
+ }
+ if (path_it->closed()) {
+ nCurve->closepath_current();
+ }
+ curve->append(nCurve, false);
+ nCurve->reset();
+ delete nCurve;
+ }
+}
+
+}; //namespace LivePathEffect
+}; /* namespace Inkscape */
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/live_effects/lpe-bspline.h b/src/live_effects/lpe-bspline.h
new file mode 100644
index 000000000..a17c0c4ac
--- /dev/null
+++ b/src/live_effects/lpe-bspline.h
@@ -0,0 +1,54 @@
+#ifndef INKSCAPE_LPE_BSPLINE_H
+#define INKSCAPE_LPE_BSPLINE_H
+
+/*
+ * Inkscape::LPEBSpline
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "live_effects/effect.h"
+#include "live_effects/parameter/bool.h"
+#include <vector>
+
+namespace Inkscape {
+namespace LivePathEffect {
+
+class LPEBSpline : public Effect {
+public:
+ LPEBSpline(LivePathEffectObject *lpeobject);
+ virtual ~LPEBSpline();
+
+ virtual LPEPathFlashType pathFlashType() const {
+ return SUPPRESS_FLASH;
+ }
+ virtual void doOnApply(SPLPEItem const* lpeitem);
+ virtual void doEffect(SPCurve *curve);
+ virtual void doBeforeEffect (SPLPEItem const* lpeitem);
+ void drawHandle(Geom::Point p, double radiusHelperNodes);
+ virtual void doBSplineFromWidget(SPCurve *curve, double value);
+ void addCanvasIndicators(SPLPEItem const */*lpeitem*/, std::vector<Geom::PathVector> &hp_vec);
+ virtual Gtk::Widget *newWidget();
+ virtual void changeWeight(double weightValue);
+ virtual void toDefaultWeight();
+ virtual void toMakeCusp();
+ virtual void toWeight();
+
+ // TODO make this private
+ ScalarParam steps;
+
+private:
+ BoolParam ignoreCusp;
+ BoolParam onlySelected;
+ BoolParam showHelper;
+ ScalarParam weight;
+ Geom::PathVector hp;
+
+ LPEBSpline(const LPEBSpline &);
+ LPEBSpline &operator=(const LPEBSpline &);
+
+};
+
+} //namespace LivePathEffect
+} //namespace Inkscape
+#endif
diff --git a/src/live_effects/lpe-copy_rotate.cpp b/src/live_effects/lpe-copy_rotate.cpp
index 65bbcdad1..51787e292 100644
--- a/src/live_effects/lpe-copy_rotate.cpp
+++ b/src/live_effects/lpe-copy_rotate.cpp
@@ -12,6 +12,7 @@
*/
#include <glibmm/i18n.h>
+#include <gdk/gdk.h>
#include "live_effects/lpe-copy_rotate.h"
#include "sp-shape.h"
@@ -37,12 +38,6 @@ public:
virtual Geom::Point knot_get() const;
};
-class KnotHolderEntityRotationAngle : public LPEKnotHolderEntity {
-public:
- KnotHolderEntityRotationAngle(LPECopyRotate *effect) : LPEKnotHolderEntity(effect) {};
- virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state);
- virtual Geom::Point knot_get() const;
-};
} // namespace CR
@@ -51,6 +46,7 @@ LPECopyRotate::LPECopyRotate(LivePathEffectObject *lpeobject) :
starting_angle(_("Starting:"), _("Angle of the first copy"), "starting_angle", &wr, this, 0.0),
rotation_angle(_("Rotation angle:"), _("Angle between two successive copies"), "rotation_angle", &wr, this, 30.0),
num_copies(_("Number of copies:"), _("Number of copies of the original path"), "num_copies", &wr, this, 5),
+ copiesTo360(_("360º Copies"), _("No rotation angle, fixed to 360º"), "copiesTo360", &wr, this, true),
origin(_("Origin"), _("Origin of the rotation"), "origin", &wr, this, "Adjust the origin of the rotation"),
dist_angle_handle(100)
{
@@ -58,6 +54,7 @@ LPECopyRotate::LPECopyRotate(LivePathEffectObject *lpeobject) :
_provides_knotholder_entities = true;
// register all your parameters here, so Inkscape knows which parameters this effect has:
+ registerParameter( dynamic_cast<Parameter *>(&copiesTo360) );
registerParameter( dynamic_cast<Parameter *>(&starting_angle) );
registerParameter( dynamic_cast<Parameter *>(&rotation_angle) );
registerParameter( dynamic_cast<Parameter *>(&num_copies) );
@@ -75,11 +72,13 @@ LPECopyRotate::~LPECopyRotate()
void
LPECopyRotate::doOnApply(SPLPEItem const* lpeitem)
{
- SPCurve const *curve = SP_SHAPE(lpeitem)->_curve;
+ using namespace Geom;
- A = *(curve->first_point());
- B = *(curve->last_point());
+ original_bbox(lpeitem);
+ Point A(boundingbox_X.min(), boundingbox_Y.middle());
+ Point B(boundingbox_X.max(), boundingbox_Y.middle());
+ Point C(boundingbox_X.middle(), boundingbox_Y.middle());
origin.param_setValue(A);
dir = unit_vector(B - A);
@@ -94,7 +93,11 @@ LPECopyRotate::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & p
// I first suspected the minus sign to be a bug in 2geom but it is
// likely due to SVG's choice of coordinate system orientation (max)
start_pos = origin + dir * Rotate(-deg_to_rad(starting_angle)) * dist_angle_handle;
- rot_pos = origin + dir * Rotate(-deg_to_rad(starting_angle + rotation_angle)) * dist_angle_handle;
+ double rotation_angle_end = rotation_angle;
+ if(copiesTo360){
+ rotation_angle_end = 360.0/(double)num_copies;
+ }
+ rot_pos = origin + dir * Rotate(-deg_to_rad(starting_angle + rotation_angle_end)) * dist_angle_handle;
A = pwd2_in.firstValue();
B = pwd2_in.lastValue();
@@ -106,7 +109,7 @@ LPECopyRotate::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & p
for (int i = 0; i < num_copies; ++i) {
// I first suspected the minus sign to be a bug in 2geom but it is
// likely due to SVG's choice of coordinate system orientation (max)
- Rotate rot(-deg_to_rad(rotation_angle * i));
+ Rotate rot(-deg_to_rad(rotation_angle_end * i));
Affine t = pre * rot * Translate(origin);
output.concat(pwd2_in * t);
}
@@ -122,12 +125,12 @@ LPECopyRotate::addCanvasIndicators(SPLPEItem const */*lpeitem*/, std::vector<Geo
Path path(start_pos);
path.appendNew<LineSegment>((Geom::Point) origin);
path.appendNew<LineSegment>(rot_pos);
-
PathVector pathv;
pathv.push_back(path);
hp_vec.push_back(pathv);
}
+
void LPECopyRotate::addKnotHolderEntities(KnotHolder *knotholder, SPDesktop *desktop, SPItem *item) {
{
KnotHolderEntity *e = new CR::KnotHolderEntityStartingAngle(this);
@@ -135,12 +138,6 @@ void LPECopyRotate::addKnotHolderEntities(KnotHolder *knotholder, SPDesktop *des
_("Adjust the starting angle") );
knotholder->add(e);
}
- {
- KnotHolderEntity *e = new CR::KnotHolderEntityRotationAngle(this);
- e->create( desktop, item, knotholder, Inkscape::CTRL_TYPE_UNKNOWN,
- _("Adjust the rotation angle") );
- knotholder->add(e);
- }
};
namespace CR {
@@ -167,26 +164,6 @@ KnotHolderEntityStartingAngle::knot_set(Geom::Point const &p, Geom::Point const
sp_lpe_item_update_patheffect (SP_LPE_ITEM(item), false, true);
}
-void
-KnotHolderEntityRotationAngle::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, guint state)
-{
- LPECopyRotate* lpe = dynamic_cast<LPECopyRotate *>(_effect);
-
- Geom::Point const s = snap_knot_position(p, state);
-
- // I first suspected the minus sign to be a bug in 2geom but it is
- // likely due to SVG's choice of coordinate system orientation (max)
- lpe->rotation_angle.param_set_value(rad_to_deg(-angle_between(lpe->dir, s - lpe->origin)) - lpe->starting_angle);
- if (state & GDK_SHIFT_MASK) {
- lpe->dist_angle_handle = L2(lpe->B - lpe->A);
- } else {
- lpe->dist_angle_handle = L2(p - lpe->origin);
- }
-
- // FIXME: this should not directly ask for updating the item. It should write to SVG, which triggers updating.
- sp_lpe_item_update_patheffect (SP_LPE_ITEM(item), false, true);
-}
-
Geom::Point
KnotHolderEntityStartingAngle::knot_get() const
{
@@ -194,13 +171,6 @@ KnotHolderEntityStartingAngle::knot_get() const
return lpe->start_pos;
}
-Geom::Point
-KnotHolderEntityRotationAngle::knot_get() const
-{
- LPECopyRotate const *lpe = dynamic_cast<LPECopyRotate const*>(_effect);
- return lpe->rot_pos;
-}
-
} // namespace CR
diff --git a/src/live_effects/lpe-copy_rotate.h b/src/live_effects/lpe-copy_rotate.h
index ca7aa269c..123c92cdd 100644
--- a/src/live_effects/lpe-copy_rotate.h
+++ b/src/live_effects/lpe-copy_rotate.h
@@ -16,6 +16,7 @@
#include "live_effects/effect.h"
#include "live_effects/parameter/point.h"
+#include "live_effects/lpegroupbbox.h"
namespace Inkscape {
namespace LivePathEffect {
@@ -26,7 +27,7 @@ namespace CR {
class KnotHolderEntityRotationAngle;
}
-class LPECopyRotate : public Effect {
+class LPECopyRotate : public Effect, GroupBBoxEffect {
public:
LPECopyRotate(LivePathEffectObject *lpeobject);
virtual ~LPECopyRotate();
@@ -37,7 +38,6 @@ public:
/* the knotholder entity classes must be declared friends */
friend class CR::KnotHolderEntityStartingAngle;
- friend class CR::KnotHolderEntityRotationAngle;
void addKnotHolderEntities(KnotHolder *knotholder, SPDesktop *desktop, SPItem *item);
protected:
@@ -47,6 +47,7 @@ private:
ScalarParam starting_angle;
ScalarParam rotation_angle;
ScalarParam num_copies;
+ BoolParam copiesTo360;
PointParam origin;
diff --git a/src/live_effects/lpe-ellipse_5pts.cpp b/src/live_effects/lpe-ellipse_5pts.cpp
new file mode 100644
index 000000000..b0a5919fe
--- /dev/null
+++ b/src/live_effects/lpe-ellipse_5pts.cpp
@@ -0,0 +1,214 @@
+/** \file
+ * LPE "Ellipse through 5 points" implementation
+ */
+
+/*
+ * Authors:
+ * Theodore Janeczko
+ *
+ * Copyright (C) Theodore Janeczko 2012 <flutterguy317@gmail.com>
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "live_effects/lpe-ellipse_5pts.h"
+
+// You might need to include other 2geom files. You can add them here:
+#include <glibmm/i18n.h>
+#include <2geom/path.h>
+#include <2geom/circle.h>
+#include <2geom/ellipse.h>
+#include <2geom/path-sink.h>
+#include "inkscape.h"
+#include "desktop.h"
+#include "message-stack.h"
+
+namespace Inkscape {
+namespace LivePathEffect {
+
+LPEEllipse5Pts::LPEEllipse5Pts(LivePathEffectObject *lpeobject) :
+ Effect(lpeobject)
+{
+ //perceived_path = true;
+}
+
+LPEEllipse5Pts::~LPEEllipse5Pts()
+{
+}
+
+static double _det3(double (*mat)[3])
+{
+ for (int i = 0; i < 2; i++)
+ {
+ for (int j = i + 1; j < 3; j++)
+ {
+ for (int k = i + 1; k < 3; k++)
+ {
+ mat[j][k] = (mat[j][k] * mat[i][i] - mat[j][i] * mat[i][k]);
+ if (i) mat[j][k] /= mat[i-1][i-1];
+ }
+ }
+ }
+ return mat[2][2];
+}
+static double _det5(double (*mat)[5])
+{
+ for (int i = 0; i < 4; i++)
+ {
+ for (int j = i + 1; j < 5; j++)
+ {
+ for (int k = i + 1; k < 5; k++)
+ {
+ mat[j][k] = (mat[j][k] * mat[i][i] - mat[j][i] * mat[i][k]);
+ if (i) mat[j][k] /= mat[i-1][i-1];
+ }
+ }
+ }
+ return mat[4][4];
+}
+
+std::vector<Geom::Path>
+LPEEllipse5Pts::doEffect_path (std::vector<Geom::Path> const & path_in)
+{
+ std::vector<Geom::Path> path_out = std::vector<Geom::Path>();
+
+ if (path_in[0].size() < 4) {
+
+ SP_ACTIVE_DESKTOP->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Five points required for constructing an ellipse"));
+ return path_in;
+ }
+ // we assume that the path has >= 3 nodes
+ Geom::Point A = path_in[0].initialPoint();
+ Geom::Point B = path_in[0].pointAt(1);
+ Geom::Point C = path_in[0].pointAt(2);
+ Geom::Point D = path_in[0].pointAt(3);
+ Geom::Point E = path_in[0].pointAt(4);
+
+ using namespace Geom;
+
+ double rowmajor_matrix[5][6] =
+ {
+ {A.x()*A.x(), A.x()*A.y(), A.y()*A.y(), A.x(), A.y(), 1},
+ {B.x()*B.x(), B.x()*B.y(), B.y()*B.y(), B.x(), B.y(), 1},
+ {C.x()*C.x(), C.x()*C.y(), C.y()*C.y(), C.x(), C.y(), 1},
+ {D.x()*D.x(), D.x()*D.y(), D.y()*D.y(), D.x(), D.y(), 1},
+ {E.x()*E.x(), E.x()*E.y(), E.y()*E.y(), E.x(), E.y(), 1}
+ };
+
+ double mat_a[5][5] =
+ {
+ {rowmajor_matrix[0][1], rowmajor_matrix[1][1], rowmajor_matrix[2][1], rowmajor_matrix[3][1], rowmajor_matrix[4][1]},
+ {rowmajor_matrix[0][2], rowmajor_matrix[1][2], rowmajor_matrix[2][2], rowmajor_matrix[3][2], rowmajor_matrix[4][2]},
+ {rowmajor_matrix[0][3], rowmajor_matrix[1][3], rowmajor_matrix[2][3], rowmajor_matrix[3][3], rowmajor_matrix[4][3]},
+ {rowmajor_matrix[0][4], rowmajor_matrix[1][4], rowmajor_matrix[2][4], rowmajor_matrix[3][4], rowmajor_matrix[4][4]},
+ {rowmajor_matrix[0][5], rowmajor_matrix[1][5], rowmajor_matrix[2][5], rowmajor_matrix[3][5], rowmajor_matrix[4][5]}
+ };
+ double mat_b[5][5] =
+ {
+ {rowmajor_matrix[0][0], rowmajor_matrix[1][0], rowmajor_matrix[2][0], rowmajor_matrix[3][0], rowmajor_matrix[4][0]},
+ {rowmajor_matrix[0][2], rowmajor_matrix[1][2], rowmajor_matrix[2][2], rowmajor_matrix[3][2], rowmajor_matrix[4][2]},
+ {rowmajor_matrix[0][3], rowmajor_matrix[1][3], rowmajor_matrix[2][3], rowmajor_matrix[3][3], rowmajor_matrix[4][3]},
+ {rowmajor_matrix[0][4], rowmajor_matrix[1][4], rowmajor_matrix[2][4], rowmajor_matrix[3][4], rowmajor_matrix[4][4]},
+ {rowmajor_matrix[0][5], rowmajor_matrix[1][5], rowmajor_matrix[2][5], rowmajor_matrix[3][5], rowmajor_matrix[4][5]}
+ };
+ double mat_c[5][5] =
+ {
+ {rowmajor_matrix[0][0], rowmajor_matrix[1][0], rowmajor_matrix[2][0], rowmajor_matrix[3][0], rowmajor_matrix[4][0]},
+ {rowmajor_matrix[0][1], rowmajor_matrix[1][1], rowmajor_matrix[2][1], rowmajor_matrix[3][1], rowmajor_matrix[4][1]},
+ {rowmajor_matrix[0][3], rowmajor_matrix[1][3], rowmajor_matrix[2][3], rowmajor_matrix[3][3], rowmajor_matrix[4][3]},
+ {rowmajor_matrix[0][4], rowmajor_matrix[1][4], rowmajor_matrix[2][4], rowmajor_matrix[3][4], rowmajor_matrix[4][4]},
+ {rowmajor_matrix[0][5], rowmajor_matrix[1][5], rowmajor_matrix[2][5], rowmajor_matrix[3][5], rowmajor_matrix[4][5]}
+ };
+ double mat_d[5][5] =
+ {
+ {rowmajor_matrix[0][0], rowmajor_matrix[1][0], rowmajor_matrix[2][0], rowmajor_matrix[3][0], rowmajor_matrix[4][0]},
+ {rowmajor_matrix[0][1], rowmajor_matrix[1][1], rowmajor_matrix[2][1], rowmajor_matrix[3][1], rowmajor_matrix[4][1]},
+ {rowmajor_matrix[0][2], rowmajor_matrix[1][2], rowmajor_matrix[2][2], rowmajor_matrix[3][2], rowmajor_matrix[4][2]},
+ {rowmajor_matrix[0][4], rowmajor_matrix[1][4], rowmajor_matrix[2][4], rowmajor_matrix[3][4], rowmajor_matrix[4][4]},
+ {rowmajor_matrix[0][5], rowmajor_matrix[1][5], rowmajor_matrix[2][5], rowmajor_matrix[3][5], rowmajor_matrix[4][5]}
+ };
+ double mat_e[5][5] =
+ {
+ {rowmajor_matrix[0][0], rowmajor_matrix[1][0], rowmajor_matrix[2][0], rowmajor_matrix[3][0], rowmajor_matrix[4][0]},
+ {rowmajor_matrix[0][1], rowmajor_matrix[1][1], rowmajor_matrix[2][1], rowmajor_matrix[3][1], rowmajor_matrix[4][1]},
+ {rowmajor_matrix[0][2], rowmajor_matrix[1][2], rowmajor_matrix[2][2], rowmajor_matrix[3][2], rowmajor_matrix[4][2]},
+ {rowmajor_matrix[0][3], rowmajor_matrix[1][3], rowmajor_matrix[2][3], rowmajor_matrix[3][3], rowmajor_matrix[4][3]},
+ {rowmajor_matrix[0][5], rowmajor_matrix[1][5], rowmajor_matrix[2][5], rowmajor_matrix[3][5], rowmajor_matrix[4][5]}
+ };
+ double mat_f[5][5] =
+ {
+ {rowmajor_matrix[0][0], rowmajor_matrix[1][0], rowmajor_matrix[2][0], rowmajor_matrix[3][0], rowmajor_matrix[4][0]},
+ {rowmajor_matrix[0][1], rowmajor_matrix[1][1], rowmajor_matrix[2][1], rowmajor_matrix[3][1], rowmajor_matrix[4][1]},
+ {rowmajor_matrix[0][2], rowmajor_matrix[1][2], rowmajor_matrix[2][2], rowmajor_matrix[3][2], rowmajor_matrix[4][2]},
+ {rowmajor_matrix[0][3], rowmajor_matrix[1][3], rowmajor_matrix[2][3], rowmajor_matrix[3][3], rowmajor_matrix[4][3]},
+ {rowmajor_matrix[0][4], rowmajor_matrix[1][4], rowmajor_matrix[2][4], rowmajor_matrix[3][4], rowmajor_matrix[4][4]}
+ };
+
+ double a1 = _det5(mat_a);
+ double b1 = -_det5(mat_b);
+ double c1 = _det5(mat_c);
+ double d1 = -_det5(mat_d);
+ double e1 = _det5(mat_e);
+ double f1 = -_det5(mat_f);
+
+ double mat_check[][3] =
+ {
+ {a1, b1/2, d1/2},
+ {b1/2, c1, e1/2},
+ {d1/2, e1/2, f1}
+ };
+
+ if (_det3(mat_check) == 0 || a1*c1 - b1*b1/4 <= 0) {
+ SP_ACTIVE_DESKTOP->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("No ellipse found for specified points"));
+ return path_in;
+ }
+
+ Geom::Ellipse el(a1, b1, c1, d1, e1, f1);
+
+ double s, e;
+ double x0, y0, x1, y1, x2, y2, x3, y3;
+ double len;
+
+ // figure out if we have a slice, guarding against rounding errors
+
+ Path p(Geom::Point(cos(0), sin(0)));
+
+ double end = 2 * M_PI;
+ for (s = 0; s < end; s += M_PI_2) {
+ e = s + M_PI_2;
+ if (e > end)
+ e = end;
+ len = 4*tan((e - s)/4)/3;
+ x0 = cos(s);
+ y0 = sin(s);
+ x1 = x0 + len * cos(s + M_PI_2);
+ y1 = y0 + len * sin(s + M_PI_2);
+ x3 = cos(e);
+ y3 = sin(e);
+ x2 = x3 + len * cos(e - M_PI_2);
+ y2 = y3 + len * sin(e - M_PI_2);
+ p.appendNew<Geom::CubicBezier>(Geom::Point(x1,y1), Geom::Point(x2,y2), Geom::Point(x3,y3));
+ }
+
+ Geom::Affine aff = Geom::Scale(el.ray(Geom::X), el.ray(Geom::Y)) * Geom::Rotate(el.rot_angle()) * Geom::Translate(el.center());
+
+ path_out.push_back(p * aff);
+
+ return path_out;
+}
+
+/* ######################## */
+
+} //namespace LivePathEffect
+} /* namespace Inkscape */
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/live_effects/lpe-ellipse_5pts.h b/src/live_effects/lpe-ellipse_5pts.h
new file mode 100644
index 000000000..d3b1fccfa
--- /dev/null
+++ b/src/live_effects/lpe-ellipse_5pts.h
@@ -0,0 +1,50 @@
+#ifndef INKSCAPE_LPE_ELLIPSE_5PTS_H
+#define INKSCAPE_LPE_ELLIPSE_5PTS_H
+
+/** \file
+ * LPE "Ellipse through 5 points" implementation
+ */
+
+/*
+ * Authors:
+ * Theodore Janeczko
+ *
+ * Copyright (C) Theodore Janeczko 2012 <flutterguy317@gmail.com>
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "live_effects/effect.h"
+#include "live_effects/parameter/parameter.h"
+#include "live_effects/parameter/point.h"
+
+namespace Inkscape {
+namespace LivePathEffect {
+
+class LPEEllipse5Pts : public Effect {
+public:
+ LPEEllipse5Pts(LivePathEffectObject *lpeobject);
+ virtual ~LPEEllipse5Pts();
+
+ virtual std::vector<Geom::Path> doEffect_path (std::vector<Geom::Path> const & path_in);
+
+private:
+ LPEEllipse5Pts(const LPEEllipse5Pts&);
+ LPEEllipse5Pts& operator=(const LPEEllipse5Pts&);
+};
+
+} //namespace LivePathEffect
+} //namespace Inkscape
+
+#endif
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/live_effects/lpe-envelope.cpp b/src/live_effects/lpe-envelope.cpp
index 4f5623fba..05a672ae8 100644
--- a/src/live_effects/lpe-envelope.cpp
+++ b/src/live_effects/lpe-envelope.cpp
@@ -32,7 +32,7 @@ LPEEnvelope::LPEEnvelope(LivePathEffectObject *lpeobject) :
bend_path2(_("Right bend path:"), _("Right path along which to bend the original path"), "bendpath2", &wr, this, "M0,0 L1,0"),
bend_path3(_("Bottom bend path:"), _("Bottom path along which to bend the original path"), "bendpath3", &wr, this, "M0,0 L1,0"),
bend_path4(_("Left bend path:"), _("Left path along which to bend the original path"), "bendpath4", &wr, this, "M0,0 L1,0"),
- xx(_("E_nable left & right paths"), _("Enable the left and right deformation paths"), "xx", &wr, this, true),
+ xx(_("_Enable left & right paths"), _("Enable the left and right deformation paths"), "xx", &wr, this, true),
yy(_("_Enable top & bottom paths"), _("Enable the top and bottom deformation paths"), "yy", &wr, this, true)
{
registerParameter( dynamic_cast<Parameter *>(&yy) );
@@ -54,6 +54,9 @@ LPEEnvelope::doBeforeEffect (SPLPEItem const* lpeitem)
{
// get the item bounding box
original_bbox(lpeitem);
+ SPLPEItem * item = const_cast<SPLPEItem*>(lpeitem);
+ item->apply_to_clippath(item);
+ item->apply_to_mask(item);
}
Geom::Piecewise<Geom::D2<Geom::SBasis> >
diff --git a/src/live_effects/lpe-fill-between-many.cpp b/src/live_effects/lpe-fill-between-many.cpp
new file mode 100644
index 000000000..7cf354044
--- /dev/null
+++ b/src/live_effects/lpe-fill-between-many.cpp
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) Theodore Janeczko 2012 <flutterguy317@gmail.com>
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <gtkmm/box.h>
+
+#include "live_effects/lpe-fill-between-many.h"
+
+#include "display/curve.h"
+#include "sp-item.h"
+#include "2geom/path.h"
+#include "sp-shape.h"
+#include "sp-text.h"
+#include "2geom/bezier-curve.h"
+
+#include <glibmm/i18n.h>
+
+namespace Inkscape {
+namespace LivePathEffect {
+
+LPEFillBetweenMany::LPEFillBetweenMany(LivePathEffectObject *lpeobject) :
+ Effect(lpeobject),
+ linked_paths(_("Linked path:"), _("Paths from which to take the original path data"), "linkedpaths", &wr, this)
+{
+ registerParameter( dynamic_cast<Parameter *>(&linked_paths) );
+ //perceived_path = true;
+}
+
+LPEFillBetweenMany::~LPEFillBetweenMany()
+{
+
+}
+
+void LPEFillBetweenMany::doEffect (SPCurve * curve)
+{
+ std::vector<Geom::Path> res_pathv;
+ SPItem * firstObj = NULL;
+ for (std::vector<PathAndDirection*>::iterator iter = linked_paths._vector.begin(); iter != linked_paths._vector.end(); iter++) {
+ SPObject *obj;
+ if ((*iter)->ref.isAttached() && (obj = (*iter)->ref.getObject()) && SP_IS_ITEM(obj) && !(*iter)->_pathvector.empty()) {
+ Geom::Path linked_path;
+ if ((*iter)->reversed) {
+ linked_path = (*iter)->_pathvector.front().reverse();
+ } else {
+ linked_path = (*iter)->_pathvector.front();
+ }
+
+ if (!res_pathv.empty()) {
+ linked_path = linked_path * SP_ITEM(obj)->getRelativeTransform(firstObj);
+ res_pathv.front().appendNew<Geom::LineSegment>(linked_path.initialPoint());
+ res_pathv.front().append(linked_path);
+ } else {
+ firstObj = SP_ITEM(obj);
+ res_pathv.push_back(linked_path);
+ }
+ }
+ }
+ if (!res_pathv.empty()) {
+ res_pathv.front().close();
+ }
+ curve->set_pathvector(res_pathv);
+}
+
+} // namespace LivePathEffect
+} /* namespace Inkscape */
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/live_effects/lpe-fill-between-many.h b/src/live_effects/lpe-fill-between-many.h
new file mode 100644
index 000000000..99ee8b15f
--- /dev/null
+++ b/src/live_effects/lpe-fill-between-many.h
@@ -0,0 +1,36 @@
+#ifndef INKSCAPE_LPE_FILL_BETWEEN_MANY_H
+#define INKSCAPE_LPE_FILL_BETWEEN_MANY_H
+
+/*
+ * Inkscape::LPEFillBetweenStrokes
+ *
+ * Copyright (C) Theodore Janeczko 2012 <flutterguy317@gmail.com>
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "live_effects/effect.h"
+#include "live_effects/parameter/originalpatharray.h"
+
+namespace Inkscape {
+namespace LivePathEffect {
+
+class LPEFillBetweenMany : public Effect {
+public:
+ LPEFillBetweenMany(LivePathEffectObject *lpeobject);
+ virtual ~LPEFillBetweenMany();
+
+ virtual void doEffect (SPCurve * curve);
+
+private:
+ OriginalPathArrayParam linked_paths;
+
+private:
+ LPEFillBetweenMany(const LPEFillBetweenMany&);
+ LPEFillBetweenMany& operator=(const LPEFillBetweenMany&);
+};
+
+}; //namespace LivePathEffect
+}; //namespace Inkscape
+
+#endif
diff --git a/src/live_effects/lpe-fill-between-strokes.cpp b/src/live_effects/lpe-fill-between-strokes.cpp
new file mode 100644
index 000000000..e72979ed0
--- /dev/null
+++ b/src/live_effects/lpe-fill-between-strokes.cpp
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) Theodore Janeczko 2012 <flutterguy317@gmail.com>
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <glibmm/i18n.h>
+
+#include "live_effects/lpe-fill-between-strokes.h"
+
+#include "display/curve.h"
+#include "sp-item.h"
+#include "2geom/path.h"
+#include "sp-shape.h"
+#include "sp-text.h"
+#include "2geom/bezier-curve.h"
+
+namespace Inkscape {
+namespace LivePathEffect {
+
+LPEFillBetweenStrokes::LPEFillBetweenStrokes(LivePathEffectObject *lpeobject) :
+ Effect(lpeobject),
+ linked_path(_("Linked path:"), _("Path from which to take the original path data"), "linkedpath", &wr, this),
+ second_path(_("Second path:"), _("Second path from which to take the original path data"), "secondpath", &wr, this),
+ reverse_second(_("Reverse Second"), _("Reverses the second path order"), "reversesecond", &wr, this)
+{
+ registerParameter( dynamic_cast<Parameter *>(&linked_path) );
+ registerParameter( dynamic_cast<Parameter *>(&second_path) );
+ registerParameter( dynamic_cast<Parameter *>(&reverse_second) );
+ //perceived_path = true;
+}
+
+LPEFillBetweenStrokes::~LPEFillBetweenStrokes()
+{
+
+}
+
+void LPEFillBetweenStrokes::doEffect (SPCurve * curve)
+{
+ if (curve) {
+ if ( linked_path.linksToPath() && second_path.linksToPath() && linked_path.getObject() && second_path.getObject() ) {
+ std::vector<Geom::Path> linked_pathv = linked_path.get_pathvector();
+ std::vector<Geom::Path> second_pathv = second_path.get_pathvector();
+ std::vector<Geom::Path> result_linked_pathv;
+ std::vector<Geom::Path> result_second_pathv;
+ Geom::Affine second_transform = second_path.getObject()->getRelativeTransform(linked_path.getObject());
+
+ for (std::vector<Geom::Path>::iterator iter = linked_pathv.begin(); iter != linked_pathv.end(); ++iter)
+ {
+ result_linked_pathv.push_back((*iter));
+ }
+ for (std::vector<Geom::Path>::iterator iter = second_pathv.begin(); iter != second_pathv.end(); ++iter)
+ {
+ result_second_pathv.push_back((*iter) * second_transform);
+ }
+
+ if ( !result_linked_pathv.empty() && !result_second_pathv.empty() && !result_linked_pathv.front().closed() ) {
+ if (reverse_second.get_value())
+ {
+ result_linked_pathv.front().appendNew<Geom::LineSegment>(result_second_pathv.front().finalPoint());
+ result_linked_pathv.front().append(result_second_pathv.front().reverse());
+ }
+ else
+ {
+ result_linked_pathv.front().appendNew<Geom::LineSegment>(result_second_pathv.front().initialPoint());
+ result_linked_pathv.front().append(result_second_pathv.front());
+ }
+ curve->set_pathvector(result_linked_pathv);
+ }
+ else if ( !result_linked_pathv.empty() ) {
+ curve->set_pathvector(result_linked_pathv);
+ }
+ else if ( !result_second_pathv.empty() ) {
+ curve->set_pathvector(result_second_pathv);
+ }
+ }
+ else if ( linked_path.linksToPath() && linked_path.getObject() ) {
+ std::vector<Geom::Path> linked_pathv = linked_path.get_pathvector();
+ std::vector<Geom::Path> result_pathv;
+
+ for (std::vector<Geom::Path>::iterator iter = linked_pathv.begin(); iter != linked_pathv.end(); ++iter)
+ {
+ result_pathv.push_back((*iter));
+ }
+ if ( !result_pathv.empty() ) {
+ curve->set_pathvector(result_pathv);
+ }
+ }
+ else if ( second_path.linksToPath() && second_path.getObject() ) {
+ std::vector<Geom::Path> second_pathv = second_path.get_pathvector();
+ std::vector<Geom::Path> result_pathv;
+
+ for (std::vector<Geom::Path>::iterator iter = second_pathv.begin(); iter != second_pathv.end(); ++iter)
+ {
+ result_pathv.push_back((*iter));
+ }
+ if ( !result_pathv.empty() ) {
+ curve->set_pathvector(result_pathv);
+ }
+ }
+ }
+}
+
+} // namespace LivePathEffect
+} /* namespace Inkscape */
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/live_effects/lpe-fill-between-strokes.h b/src/live_effects/lpe-fill-between-strokes.h
new file mode 100644
index 000000000..ec57b1852
--- /dev/null
+++ b/src/live_effects/lpe-fill-between-strokes.h
@@ -0,0 +1,38 @@
+#ifndef INKSCAPE_LPE_FILL_BETWEEN_STROKES_H
+#define INKSCAPE_LPE_FILL_BETWEEN_STROKES_H
+
+/*
+ * Inkscape::LPEFillBetweenStrokes
+ *
+ * Copyright (C) Theodore Janeczko 2012 <flutterguy317@gmail.com>
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "live_effects/effect.h"
+#include "live_effects/parameter/originalpath.h"
+
+namespace Inkscape {
+namespace LivePathEffect {
+
+class LPEFillBetweenStrokes : public Effect {
+public:
+ LPEFillBetweenStrokes(LivePathEffectObject *lpeobject);
+ virtual ~LPEFillBetweenStrokes();
+
+ virtual void doEffect (SPCurve * curve);
+
+private:
+ OriginalPathParam linked_path;
+ OriginalPathParam second_path;
+ BoolParam reverse_second;
+
+private:
+ LPEFillBetweenStrokes(const LPEFillBetweenStrokes&);
+ LPEFillBetweenStrokes& operator=(const LPEFillBetweenStrokes&);
+};
+
+}; //namespace LivePathEffect
+}; //namespace Inkscape
+
+#endif
diff --git a/src/live_effects/lpe-fillet-chamfer.cpp b/src/live_effects/lpe-fillet-chamfer.cpp
new file mode 100644
index 000000000..119759b87
--- /dev/null
+++ b/src/live_effects/lpe-fillet-chamfer.cpp
@@ -0,0 +1,660 @@
+/*
+ * Author(s):
+ * Jabiertxo Arraiza Cenoz <jabier.arraiza@marker.es>
+ *
+ * Copyright (C) 2014 Author(s)
+ *
+ * Special thanks to Johan Engelen for the base of the effect -powerstroke-
+ * Also to ScislaC for point me to the idea
+ * Also su_v for his construvtive feedback and time
+ * Also to Mc- (IRC nick) for his important contribution to find real time
+ * values based on
+ * and finaly to Liam P. White for his big help on coding, that save me a lot of hours
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+#include "live_effects/lpe-fillet-chamfer.h"
+
+#include <2geom/sbasis-to-bezier.h>
+#include <2geom/svg-elliptical-arc.h>
+#include <2geom/line.h>
+
+#include "desktop.h"
+#include "display/curve.h"
+#include "helper/geom-nodetype.h"
+#include "helper/geom-curves.h"
+#include "helper/geom.h"
+
+#include "live_effects/parameter/filletchamferpointarray.h"
+
+// for programmatically updating knots
+#include "ui/tools-switch.h"
+#include <util/units.h>
+
+// TODO due to internal breakage in glibmm headers, this must be last:
+#include <glibmm/i18n.h>
+
+using namespace Geom;
+namespace Inkscape {
+namespace LivePathEffect {
+
+static const Util::EnumData<FilletMethod> FilletMethodData[FM_END] = {
+ { FM_AUTO, N_("Auto"), "auto" },
+ { FM_ARC, N_("Force arc"), "arc" },
+ { FM_BEZIER, N_("Force bezier"), "bezier" }
+};
+static const Util::EnumDataConverter<FilletMethod>
+FMConverter(FilletMethodData, FM_END);
+
+const double tolerance = 0.001;
+const double gapHelper = 0.00001;
+
+LPEFilletChamfer::LPEFilletChamfer(LivePathEffectObject *lpeobject) :
+ Effect(lpeobject),
+ fillet_chamfer_values(_("Fillet point"), _("Fillet point"), "fillet_chamfer_values", &wr, this),
+ hide_knots(_("Hide knots"), _("Hide knots"), "hide_knots", &wr, this, false),
+ ignore_radius_0(_("Ignore 0 radius knots"), _("Ignore 0 radius knots"), "ignore_radius_0", &wr, this, false),
+ only_selected(_("Change only selected nodes"), _("Change only selected nodes"), "only_selected", &wr, this, false),
+ flexible(_("Flexible radius size (%)"), _("Flexible radius size (%)"), "flexible", &wr, this, false),
+ use_knot_distance(_("Use knots distance instead radius"), _("Use knots distance instead radius"), "use_knot_distance", &wr, this, false),
+ unit(_("Unit"), _("Unit"), "unit", &wr, this),
+ method(_("Method"), _("Fillets methods"), "method", FMConverter, &wr, this, FM_AUTO),
+ radius(_("Radius (unit or %)"), _("Radius, in unit or %"), "radius", &wr, this, 0.),
+ chamfer_steps(_("Chamfer steps"), _("Chamfer steps"), "chamfer_steps", &wr, this, 0),
+
+ helper_size(_("Helper size with direction"), _("Helper size with direction"), "helper_size", &wr, this, 0)
+{
+ registerParameter(&fillet_chamfer_values);
+ registerParameter(&unit);
+ registerParameter(&method);
+ registerParameter(&radius);
+ registerParameter(&chamfer_steps);
+ registerParameter(&helper_size);
+ registerParameter(&flexible);
+ registerParameter(&use_knot_distance);
+ registerParameter(&ignore_radius_0);
+ registerParameter(&only_selected);
+ registerParameter(&hide_knots);
+
+ radius.param_set_range(0., infinity());
+ radius.param_set_increments(1, 1);
+ radius.param_set_digits(4);
+ chamfer_steps.param_set_range(1, 999);
+ chamfer_steps.param_set_increments(1, 1);
+ chamfer_steps.param_set_digits(0);
+ helper_size.param_set_range(0, infinity());
+ helper_size.param_set_increments(5, 5);
+ helper_size.param_set_digits(0);
+ fillet_chamfer_values.set_chamfer_steps(3);
+}
+
+LPEFilletChamfer::~LPEFilletChamfer() {}
+
+Gtk::Widget *LPEFilletChamfer::newWidget()
+{
+ // use manage here, because after deletion of Effect object, others might
+ // still be pointing to this widget.
+ Gtk::VBox *vbox = Gtk::manage(new Gtk::VBox(Effect::newWidget()));
+
+ vbox->set_border_width(5);
+ vbox->set_homogeneous(false);
+ vbox->set_spacing(2);
+ std::vector<Parameter *>::iterator it = param_vector.begin();
+ while (it != param_vector.end()) {
+ if ((*it)->widget_is_visible) {
+ Parameter *param = *it;
+ Gtk::Widget *widg = param->param_newWidget();
+ if (param->param_key == "radius") {
+ Inkscape::UI::Widget::Scalar *widgRegistered = Gtk::manage(dynamic_cast<Inkscape::UI::Widget::Scalar *>(widg));
+ widgRegistered->signal_value_changed().connect(sigc::mem_fun(*this, &LPEFilletChamfer::updateFillet));
+ widg = widgRegistered;
+ if (widg) {
+ Gtk::HBox *scalarParameter = dynamic_cast<Gtk::HBox *>(widg);
+ std::vector<Gtk::Widget *> childList = scalarParameter->get_children();
+ Gtk::Entry *entryWidg = dynamic_cast<Gtk::Entry *>(childList[1]);
+ entryWidg->set_width_chars(6);
+ }
+ } else if (param->param_key == "chamfer_steps") {
+ Inkscape::UI::Widget::Scalar *widgRegistered = Gtk::manage(dynamic_cast<Inkscape::UI::Widget::Scalar *>(widg));
+ widgRegistered->signal_value_changed().connect(sigc::mem_fun(*this, &LPEFilletChamfer::chamferSubdivisions));
+ widg = widgRegistered;
+ if (widg) {
+ Gtk::HBox *scalarParameter = dynamic_cast<Gtk::HBox *>(widg);
+ std::vector<Gtk::Widget *> childList = scalarParameter->get_children();
+ Gtk::Entry *entryWidg = dynamic_cast<Gtk::Entry *>(childList[1]);
+ entryWidg->set_width_chars(3);
+ }
+ } else if (param->param_key == "flexible") {
+ Gtk::CheckButton *widgRegistered = Gtk::manage(dynamic_cast<Gtk::CheckButton *>(widg));
+ widgRegistered->signal_clicked().connect(sigc::mem_fun(*this, &LPEFilletChamfer::toggleFlexFixed));
+ } else if (param->param_key == "helper_size") {
+ Inkscape::UI::Widget::Scalar *widgRegistered = Gtk::manage(dynamic_cast<Inkscape::UI::Widget::Scalar *>(widg));
+ widgRegistered->signal_value_changed().connect(sigc::mem_fun(*this, &LPEFilletChamfer::refreshKnots));
+ } else if (param->param_key == "hide_knots") {
+ Gtk::CheckButton *widgRegistered = Gtk::manage(dynamic_cast<Gtk::CheckButton *>(widg));
+ widgRegistered->signal_clicked().connect(sigc::mem_fun(*this, &LPEFilletChamfer::toggleHide));
+ } else if (param->param_key == "only_selected") {
+ Gtk::manage(widg);
+ } else if (param->param_key == "ignore_radius_0") {
+ Gtk::manage(widg);
+ }
+
+ Glib::ustring *tip = param->param_getTooltip();
+ if (widg) {
+ vbox->pack_start(*widg, true, true, 2);
+ if (tip) {
+ widg->set_tooltip_text(*tip);
+ } else {
+ widg->set_tooltip_text("");
+ widg->set_has_tooltip(false);
+ }
+ }
+ }
+
+ ++it;
+ }
+ Gtk::HBox *filletContainer = Gtk::manage(new Gtk::HBox(true, 0));
+ Gtk::Button *fillet = Gtk::manage(new Gtk::Button(Glib::ustring(_("Fillet"))));
+ fillet->signal_clicked().connect(sigc::mem_fun(*this, &LPEFilletChamfer::fillet));
+
+ filletContainer->pack_start(*fillet, true, true, 2);
+ Gtk::Button *inverseFillet = Gtk::manage(new Gtk::Button(Glib::ustring(_("Inverse fillet"))));
+ inverseFillet->signal_clicked().connect(sigc::mem_fun(*this, &LPEFilletChamfer::inverseFillet));
+ filletContainer->pack_start(*inverseFillet, true, true, 2);
+
+ Gtk::HBox *chamferContainer = Gtk::manage(new Gtk::HBox(true, 0));
+ Gtk::Button *chamfer = Gtk::manage(new Gtk::Button(Glib::ustring(_("Chamfer"))));
+ chamfer->signal_clicked().connect(sigc::mem_fun(*this, &LPEFilletChamfer::chamfer));
+
+ chamferContainer->pack_start(*chamfer, true, true, 2);
+ Gtk::Button *inverseChamfer = Gtk::manage(new Gtk::Button(Glib::ustring(_("Inverse chamfer"))));
+ inverseChamfer->signal_clicked().connect(sigc::mem_fun(*this, &LPEFilletChamfer::inverseChamfer));
+ chamferContainer->pack_start(*inverseChamfer, true, true, 2);
+
+ vbox->pack_start(*filletContainer, true, true, 2);
+ vbox->pack_start(*chamferContainer, true, true, 2);
+
+ return vbox;
+}
+
+void LPEFilletChamfer::toggleHide()
+{
+ std::vector<Point> filletChamferData = fillet_chamfer_values.data();
+ std::vector<Geom::Point> result;
+ for (std::vector<Point>::const_iterator point_it = filletChamferData.begin();
+ point_it != filletChamferData.end(); ++point_it) {
+ if (hide_knots) {
+ result.push_back(Point((*point_it)[X], std::abs((*point_it)[Y]) * -1));
+ } else {
+ result.push_back(Point((*point_it)[X], std::abs((*point_it)[Y])));
+ }
+ }
+ fillet_chamfer_values.param_set_and_write_new_value(result);
+ refreshKnots();
+}
+
+void LPEFilletChamfer::toggleFlexFixed()
+{
+ std::vector<Point> filletChamferData = fillet_chamfer_values.data();
+ std::vector<Geom::Point> result;
+ unsigned int i = 0;
+ for (std::vector<Point>::const_iterator point_it = filletChamferData.begin();
+ point_it != filletChamferData.end(); ++point_it) {
+ if (flexible) {
+ result.push_back(Point(fillet_chamfer_values.to_time(i, (*point_it)[X]),
+ (*point_it)[Y]));
+ } else {
+ result.push_back(Point(fillet_chamfer_values.to_len(i, (*point_it)[X]),
+ (*point_it)[Y]));
+ }
+ i++;
+ }
+ if (flexible) {
+ radius.param_set_range(0., 100);
+ radius.param_set_value(0);
+ } else {
+ radius.param_set_range(0., infinity());
+ radius.param_set_value(0);
+ }
+ fillet_chamfer_values.param_set_and_write_new_value(result);
+}
+
+void LPEFilletChamfer::updateFillet()
+{
+ double power = 0;
+ if (!flexible) {
+ power = Inkscape::Util::Quantity::convert(radius, unit.get_abbreviation(), *defaultUnit) * -1;
+ } else {
+ power = radius;
+ }
+ Piecewise<D2<SBasis> > const &pwd2 = fillet_chamfer_values.get_pwd2();
+ doUpdateFillet(path_from_piecewise(pwd2, tolerance), power);
+}
+
+void LPEFilletChamfer::fillet()
+{
+ Piecewise<D2<SBasis> > const &pwd2 = fillet_chamfer_values.get_pwd2();
+ doChangeType(path_from_piecewise(pwd2, tolerance), 1);
+}
+
+void LPEFilletChamfer::inverseFillet()
+{
+ Piecewise<D2<SBasis> > const &pwd2 = fillet_chamfer_values.get_pwd2();
+ doChangeType(path_from_piecewise(pwd2, tolerance), 2);
+}
+
+void LPEFilletChamfer::chamferSubdivisions()
+{
+ fillet_chamfer_values.set_chamfer_steps(chamfer_steps);
+ Piecewise<D2<SBasis> > const &pwd2 = fillet_chamfer_values.get_pwd2();
+ doChangeType(path_from_piecewise(pwd2, tolerance), chamfer_steps + 5000);
+}
+
+void LPEFilletChamfer::chamfer()
+{
+ fillet_chamfer_values.set_chamfer_steps(chamfer_steps);
+ Piecewise<D2<SBasis> > const &pwd2 = fillet_chamfer_values.get_pwd2();
+ doChangeType(path_from_piecewise(pwd2, tolerance), chamfer_steps + 3000);
+}
+
+void LPEFilletChamfer::inverseChamfer()
+{
+ fillet_chamfer_values.set_chamfer_steps(chamfer_steps);
+ Piecewise<D2<SBasis> > const &pwd2 = fillet_chamfer_values.get_pwd2();
+ doChangeType(path_from_piecewise(pwd2, tolerance), chamfer_steps + 4000);
+}
+
+void LPEFilletChamfer::refreshKnots()
+{
+ Piecewise<D2<SBasis> > const &pwd2 = fillet_chamfer_values.get_pwd2();
+ fillet_chamfer_values.recalculate_knots(pwd2);
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ if (tools_isactive(desktop, TOOLS_NODES)) {
+ tools_switch(desktop, TOOLS_SELECT);
+ tools_switch(desktop, TOOLS_NODES);
+ }
+}
+
+void LPEFilletChamfer::doUpdateFillet(std::vector<Geom::Path> const& original_pathv, double power)
+{
+ std::vector<Point> filletChamferData = fillet_chamfer_values.data();
+ std::vector<Geom::Point> result;
+ std::vector<Geom::Path> original_pathv_processed = pathv_to_linear_and_cubic_beziers(original_pathv);
+ int counter = 0;
+ for (PathVector::const_iterator path_it = original_pathv_processed.begin();
+ path_it != original_pathv_processed.end(); ++path_it) {
+ if (path_it->empty())
+ continue;
+
+ Geom::Path::const_iterator curve_it1 = path_it->begin();
+ Geom::Path::const_iterator curve_it2 = ++(path_it->begin());
+ Geom::Path::const_iterator curve_endit = path_it->end_default();
+ if (path_it->closed() && path_it->back_closed().isDegenerate()) {
+ const Curve &closingline = path_it->back_closed();
+ if (are_near(closingline.initialPoint(), closingline.finalPoint())) {
+ curve_endit = path_it->end_open();
+ }
+ }
+ double powerend = 0;
+ while (curve_it1 != curve_endit) {
+ powerend = power;
+ if (power < 0 && !use_knot_distance) {
+ powerend = fillet_chamfer_values.rad_to_len(counter,powerend);
+ }
+ if (power > 0) {
+ powerend = counter + (power / 100);
+ }
+ if (ignore_radius_0 && (filletChamferData[counter][X] == 0 ||
+ filletChamferData[counter][X] == counter)) {
+ powerend = filletChamferData[counter][X];
+ }
+ if (filletChamferData[counter][Y] == 0) {
+ powerend = filletChamferData[counter][X];
+ }
+ if (only_selected && !isNodePointSelected(curve_it1->initialPoint())) {
+ powerend = filletChamferData[counter][X];
+ }
+ result.push_back(Point(powerend, filletChamferData[counter][Y]));
+ ++curve_it1;
+ ++curve_it2;
+ counter++;
+ }
+ }
+ fillet_chamfer_values.param_set_and_write_new_value(result);
+}
+
+void LPEFilletChamfer::doChangeType(std::vector<Geom::Path> const& original_pathv, int type)
+{
+ std::vector<Point> filletChamferData = fillet_chamfer_values.data();
+ std::vector<Geom::Point> result;
+ std::vector<Geom::Path> original_pathv_processed = pathv_to_linear_and_cubic_beziers(original_pathv);
+ int counter = 0;
+ for (PathVector::const_iterator path_it = original_pathv_processed.begin(); path_it != original_pathv_processed.end(); ++path_it) {
+ int pathCounter = 0;
+ if (path_it->empty())
+ continue;
+
+ Geom::Path::const_iterator curve_it1 = path_it->begin();
+ Geom::Path::const_iterator curve_it2 = ++(path_it->begin());
+ Geom::Path::const_iterator curve_endit = path_it->end_default();
+ if (path_it->closed() && path_it->back_closed().isDegenerate()) {
+ const Curve &closingline = path_it->back_closed();
+ if (are_near(closingline.initialPoint(), closingline.finalPoint())) {
+ curve_endit = path_it->end_open();
+ }
+ }
+ while (curve_it1 != curve_endit) {
+ bool toggle = true;
+ if (filletChamferData[counter][Y] == 0 ||
+ (ignore_radius_0 && (filletChamferData[counter][X] == 0 ||
+ filletChamferData[counter][X] == counter)) ||
+ (only_selected && !isNodePointSelected(curve_it1->initialPoint()))) {
+ toggle = false;
+ }
+ if (toggle) {
+ if(type >= 5000){
+ if(filletChamferData[counter][Y] >= 3000 && filletChamferData[counter][Y] < 4000){
+ type = type - 2000;
+ } else if (filletChamferData[counter][Y] >= 4000 && filletChamferData[counter][Y] < 5000){
+ type = type - 1000;
+ }
+ }
+ result.push_back(Point(filletChamferData[counter][X], type));
+ } else {
+ result.push_back(filletChamferData[counter]);
+ }
+ ++curve_it1;
+ if (curve_it2 != curve_endit) {
+ ++curve_it2;
+ }
+ counter++;
+ pathCounter++;
+ }
+ }
+ fillet_chamfer_values.param_set_and_write_new_value(result);
+}
+
+void LPEFilletChamfer::doOnApply(SPLPEItem const *lpeItem)
+{
+ if (SP_IS_SHAPE(lpeItem)) {
+ std::vector<Point> point;
+ PathVector const &original_pathv = pathv_to_linear_and_cubic_beziers(SP_SHAPE(lpeItem)->_curve->get_pathvector());
+ Piecewise<D2<SBasis> > pwd2_in = paths_to_pw(original_pathv);
+ for (PathVector::const_iterator path_it = original_pathv.begin(); path_it != original_pathv.end(); ++path_it) {
+ if (path_it->empty())
+ continue;
+
+ Geom::Path::const_iterator curve_it1 = path_it->begin();
+ Geom::Path::const_iterator curve_it2 = ++(path_it->begin());
+ Geom::Path::const_iterator curve_endit = path_it->end_default();
+ if (path_it->closed()) {
+ const Geom::Curve &closingline = path_it->back_closed();
+ // the closing line segment is always of type
+ // Geom::LineSegment.
+ if (are_near(closingline.initialPoint(), closingline.finalPoint())) {
+ // closingline.isDegenerate() did not work, because it only checks for
+ // *exact* zero length, which goes wrong for relative coordinates and
+ // rounding errors...
+ // the closing line segment has zero-length. So stop before that one!
+ curve_endit = path_it->end_open();
+ }
+ }
+ int counter = 0;
+ while (curve_it1 != curve_endit) {
+ std::pair<std::size_t, std::size_t> positions = fillet_chamfer_values.get_positions(counter, original_pathv);
+ Geom::NodeType nodetype;
+ if (positions.second == 0) {
+ if (path_it->closed()) {
+ Piecewise<D2<SBasis> > u;
+ u.push_cut(0);
+ u.push(pwd2_in[fillet_chamfer_values.last_index(counter, original_pathv)], 1);
+ Geom::Curve const * A = path_from_piecewise(u, 0.1)[0][0].duplicate();
+ nodetype = get_nodetype(*A, *curve_it1);
+ } else {
+ nodetype = NODE_NONE;
+ }
+ } else {
+ nodetype = get_nodetype((*path_it)[counter - 1], *curve_it1);
+ }
+ if (nodetype == NODE_CUSP) {
+ point.push_back(Point(0, 1));
+ } else {
+ point.push_back(Point(0, 0));
+ }
+ ++curve_it1;
+ if (curve_it2 != curve_endit) {
+ ++curve_it2;
+ }
+ counter++;
+ }
+ }
+ fillet_chamfer_values.param_set_and_write_new_value(point);
+ } else {
+ g_warning("LPE Fillet can only be applied to shapes (not groups).");
+ SPLPEItem * item = const_cast<SPLPEItem*>(lpeItem);
+ item->removeCurrentPathEffect(false);
+ }
+}
+
+void LPEFilletChamfer::doBeforeEffect(SPLPEItem const *lpeItem)
+{
+ if (SP_IS_SHAPE(lpeItem)) {
+ if(hide_knots){
+ fillet_chamfer_values.set_helper_size(0);
+ } else {
+ fillet_chamfer_values.set_helper_size(helper_size);
+ }
+ fillet_chamfer_values.set_document_unit(defaultUnit);
+ fillet_chamfer_values.set_use_distance(use_knot_distance);
+ fillet_chamfer_values.set_unit(unit.get_abbreviation());
+ SPCurve *c = SP_IS_PATH(lpeItem) ? static_cast<SPPath const *>(lpeItem)
+ ->get_original_curve()
+ : SP_SHAPE(lpeItem)->getCurve();
+ std::vector<Point> filletChamferData = fillet_chamfer_values.data();
+ if (!filletChamferData.empty() && getKnotsNumber(c) != (int)
+ filletChamferData.size()) {
+ PathVector const original_pathv = pathv_to_linear_and_cubic_beziers(c->get_pathvector());
+ Piecewise<D2<SBasis> > pwd2_in = paths_to_pw(original_pathv);
+ fillet_chamfer_values.recalculate_controlpoints_for_new_pwd2(pwd2_in);
+ }
+ } else {
+ g_warning("LPE Fillet can only be applied to shapes (not groups).");
+ }
+}
+
+int LPEFilletChamfer::getKnotsNumber(SPCurve const *c)
+{
+ int nKnots = c->nodes_in_path();
+ PathVector const pv = pathv_to_linear_and_cubic_beziers(c->get_pathvector());
+ for (std::vector<Geom::Path>::const_iterator path_it = pv.begin();
+ path_it != pv.end(); ++path_it) {
+ if (!(*path_it).closed()) {
+ nKnots--;
+ }
+ }
+ return nKnots;
+}
+
+void
+LPEFilletChamfer::adjustForNewPath(std::vector<Geom::Path> const &path_in)
+{
+ if (!path_in.empty()) {
+ fillet_chamfer_values.recalculate_controlpoints_for_new_pwd2(pathv_to_linear_and_cubic_beziers(path_in)[0].toPwSb());
+ }
+}
+
+std::vector<Geom::Path>
+LPEFilletChamfer::doEffect_path(std::vector<Geom::Path> const &path_in)
+{
+ std::vector<Geom::Path> pathvector_out;
+ Piecewise<D2<SBasis> > pwd2_in = paths_to_pw(pathv_to_linear_and_cubic_beziers(path_in));
+ pwd2_in = remove_short_cuts(pwd2_in, .01);
+ Piecewise<D2<SBasis> > der = derivative(pwd2_in);
+ Piecewise<D2<SBasis> > n = rot90(unitVector(der));
+ fillet_chamfer_values.set_pwd2(pwd2_in, n);
+ std::vector<Point> filletChamferData = fillet_chamfer_values.data();
+ unsigned int counter = 0;
+ const double K = (4.0 / 3.0) * (sqrt(2.0) - 1.0);
+ std::vector<Geom::Path> path_in_processed = pathv_to_linear_and_cubic_beziers(path_in);
+ for (PathVector::const_iterator path_it = path_in_processed.begin();
+ path_it != path_in_processed.end(); ++path_it) {
+ if (path_it->empty())
+ continue;
+ Geom::Path path_out;
+ Geom::Path::const_iterator curve_it1 = path_it->begin();
+ Geom::Path::const_iterator curve_it2 = ++(path_it->begin());
+ Geom::Path::const_iterator curve_endit = path_it->end_default();
+ if (path_it->closed()) {
+ const Geom::Curve &closingline = path_it->back_closed();
+ // the closing line segment is always of type
+ // Geom::LineSegment.
+ if (are_near(closingline.initialPoint(), closingline.finalPoint())) {
+ // closingline.isDegenerate() did not work, because it only checks for
+ // *exact* zero length, which goes wrong for relative coordinates and
+ // rounding errors...
+ // the closing line segment has zero-length. So stop before that one!
+ curve_endit = path_it->end_open();
+ }
+ }
+ unsigned int counterCurves = 0;
+ while (curve_it1 != curve_endit) {
+ Curve *curve_it2Fixed = (*path_it->begin()).duplicate();
+ if(!path_it->closed() || curve_it2 != curve_endit){
+ curve_it2Fixed = (*curve_it2).duplicate();
+ }
+ bool last = curve_it2 == curve_endit;
+ std::vector<double> times = fillet_chamfer_values.get_times(counter, path_in, last);
+ Curve *knotCurve1 = curve_it1->portion(times[0], times[1]);
+ if (counterCurves > 0) {
+ knotCurve1->setInitial(path_out.finalPoint());
+ } else {
+ path_out.start((*curve_it1).pointAt(times[0]));
+ }
+ Curve *knotCurve2 = curve_it2Fixed->portion(times[2], 1);
+ Point startArcPoint = knotCurve1->finalPoint();
+ Point endArcPoint = curve_it2Fixed->pointAt(times[2]);
+ double k1 = distance(startArcPoint, curve_it1->finalPoint()) * K;
+ double k2 = distance(endArcPoint, curve_it1->finalPoint()) * K;
+ Geom::CubicBezier const *cubic1 = dynamic_cast<Geom::CubicBezier const *>(&*knotCurve1);
+ Ray ray1(startArcPoint, curve_it1->finalPoint());
+ if (cubic1) {
+ ray1.setPoints((*cubic1)[2], startArcPoint);
+ }
+ Point handle1 = Point::polar(ray1.angle(),k1) + startArcPoint;
+ Geom::CubicBezier const *cubic2 =
+ dynamic_cast<Geom::CubicBezier const *>(&*knotCurve2);
+ Ray ray2(curve_it1->finalPoint(), endArcPoint);
+ if (cubic2) {
+ ray2.setPoints(endArcPoint, (*cubic2)[1]);
+ }
+ Point handle2 = endArcPoint - Point::polar(ray2.angle(),k2);
+ bool ccwToggle = cross(curve_it1->finalPoint() - startArcPoint, endArcPoint - startArcPoint) < 0;
+ double angle = angle_between(ray1, ray2, ccwToggle);
+ double handleAngle = ray1.angle() - angle;
+ if (ccwToggle) {
+ handleAngle = ray1.angle() + angle;
+ }
+ Point inverseHandle1 = Point::polar(handleAngle,k1) + startArcPoint;
+ handleAngle = ray2.angle() + angle;
+ if (ccwToggle) {
+ handleAngle = ray2.angle() - angle;
+ }
+ Point inverseHandle2 = endArcPoint - Point::polar(handleAngle,k2);
+ //straigth lines arc based
+ Line const x_line(Geom::Point(0,0),Geom::Point(1,0));
+ Line const angled_line(startArcPoint,endArcPoint);
+ double angleArc = Geom::angle_between( x_line,angled_line);
+ double radius = Geom::distance(startArcPoint,middle_point(startArcPoint,endArcPoint))/sin(angle/2.0);
+ Coord rx = radius;
+ Coord ry = rx;
+
+ if (times[1] != 1) {
+ if (times[1] != gapHelper && times[1] != times[0] + gapHelper) {
+ path_out.append(*knotCurve1);
+ }
+ int type = 0;
+ if(path_it->closed() && last){
+ type = std::abs(filletChamferData[counter - counterCurves][Y]);
+ } else if (!path_it->closed() && last){
+ //0
+ } else {
+ type = std::abs(filletChamferData[counter + 1][Y]);
+ }
+ if(are_near(middle_point(startArcPoint,endArcPoint),curve_it1->finalPoint(), 0.0001)){
+ path_out.appendNew<Geom::LineSegment>(endArcPoint);
+ } else if (type >= 3000 && type < 4000) {
+ unsigned int chamferSubs = type-3000;
+ Geom::Path path_chamfer;
+ path_chamfer.start(path_out.finalPoint());
+ if((is_straight_curve(*curve_it1) && is_straight_curve(*curve_it2Fixed) && method != FM_BEZIER )|| method == FM_ARC){
+ path_chamfer.appendNew<SVGEllipticalArc>(rx, ry, angleArc, 0, ccwToggle, endArcPoint);
+ } else {
+ path_chamfer.appendNew<Geom::CubicBezier>(handle1, handle2, endArcPoint);
+ }
+ double chamfer_stepsTime = 1.0/chamferSubs;
+ for(unsigned int i = 1; i < chamferSubs; i++){
+ Geom::Point chamferStep = path_chamfer.pointAt(chamfer_stepsTime * i);
+ path_out.appendNew<Geom::LineSegment>(chamferStep);
+ }
+ path_out.appendNew<Geom::LineSegment>(endArcPoint);
+ } else if (type >= 4000 && type < 5000) {
+ unsigned int chamferSubs = type-4000;
+ Geom::Path path_chamfer;
+ path_chamfer.start(path_out.finalPoint());
+ if((is_straight_curve(*curve_it1) && is_straight_curve(*curve_it2Fixed) && method != FM_BEZIER )|| method == FM_ARC){
+ ccwToggle = ccwToggle?0:1;
+ path_chamfer.appendNew<SVGEllipticalArc>(rx, ry, angleArc, 0, ccwToggle, endArcPoint);
+ }else{
+ path_chamfer.appendNew<Geom::CubicBezier>(inverseHandle1, inverseHandle2, endArcPoint);
+ }
+ double chamfer_stepsTime = 1.0/chamferSubs;
+ for(unsigned int i = 1; i < chamferSubs; i++){
+ Geom::Point chamferStep = path_chamfer.pointAt(chamfer_stepsTime * i);
+ path_out.appendNew<Geom::LineSegment>(chamferStep);
+ }
+ path_out.appendNew<Geom::LineSegment>(endArcPoint);
+ } else if (type == 2) {
+ if((is_straight_curve(*curve_it1) && is_straight_curve(*curve_it2Fixed) && method != FM_BEZIER )|| method == FM_ARC){
+ ccwToggle = ccwToggle?0:1;
+ path_out.appendNew<SVGEllipticalArc>(rx, ry, angleArc, 0, ccwToggle, endArcPoint);
+ }else{
+ path_out.appendNew<Geom::CubicBezier>(inverseHandle1, inverseHandle2, endArcPoint);
+ }
+ } else if (type == 1){
+ if((is_straight_curve(*curve_it1) && is_straight_curve(*curve_it2Fixed) && method != FM_BEZIER )|| method == FM_ARC){
+ path_out.appendNew<SVGEllipticalArc>(rx, ry, angleArc, 0, ccwToggle, endArcPoint);
+ } else {
+ path_out.appendNew<Geom::CubicBezier>(handle1, handle2, endArcPoint);
+ }
+ }
+ } else {
+ path_out.append(*knotCurve1);
+ }
+ if (path_it->closed() && last) {
+ path_out.close();
+ }
+ ++curve_it1;
+ if (curve_it2 != curve_endit) {
+ ++curve_it2;
+ }
+ counter++;
+ counterCurves++;
+ }
+ pathvector_out.push_back(path_out);
+ }
+ return pathvector_out;
+}
+
+}; //namespace LivePathEffect
+}; /* namespace Inkscape */
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offset:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/live_effects/lpe-fillet-chamfer.h b/src/live_effects/lpe-fillet-chamfer.h
new file mode 100644
index 000000000..0d6a1ff17
--- /dev/null
+++ b/src/live_effects/lpe-fillet-chamfer.h
@@ -0,0 +1,102 @@
+#ifndef INKSCAPE_LPE_FILLET_CHAMFER_H
+#define INKSCAPE_LPE_FILLET_CHAMFER_H
+
+/*
+ * Author(s):
+ * Jabiertxo Arraiza Cenoz <jabier.arraiza@marker.es>
+ *
+ * Copyright (C) 2014 Author(s)
+ *
+ * Special thanks to Johan Engelen for the base of the effect -powerstroke-
+ * Also to ScislaC for point me to the idea
+ * Also su_v for his construvtive feedback and time
+ * and finaly to Liam P. White for his big help on coding, that save me a lot of hours
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#if defined(GLIBMM_DISABLE_DEPRECATED) && defined(HAVE_GLIBMM_THREADS_H)
+# include <glibmm/threads.h>
+#endif
+
+#include "live_effects/parameter/enum.h"
+#include "live_effects/parameter/bool.h"
+#include "live_effects/parameter/unit.h"
+
+#include "live_effects/parameter/filletchamferpointarray.h"
+#include "live_effects/effect.h"
+
+namespace Inkscape {
+namespace LivePathEffect {
+
+enum FilletMethod {
+ FM_AUTO,
+ FM_ARC,
+ FM_BEZIER,
+ FM_END
+};
+
+class LPEFilletChamfer : public Effect {
+public:
+ LPEFilletChamfer(LivePathEffectObject *lpeobject);
+ virtual ~LPEFilletChamfer();
+
+ virtual std::vector<Geom::Path> doEffect_path(std::vector<Geom::Path> const &path_in);
+
+ virtual void doOnApply(SPLPEItem const *lpeItem);
+ virtual void doBeforeEffect(SPLPEItem const *lpeItem);
+ virtual void adjustForNewPath(std::vector<Geom::Path> const &path_in);
+ virtual Gtk::Widget* newWidget();
+
+ int getKnotsNumber(SPCurve const *c);
+ void toggleHide();
+ void toggleFlexFixed();
+ void chamfer();
+ void chamferSubdivisions();
+ void inverseChamfer();
+ void fillet();
+ void inverseFillet();
+ void updateFillet();
+ void doUpdateFillet(std::vector<Geom::Path> const& original_pathv, double power);
+ void doChangeType(std::vector<Geom::Path> const& original_pathv, int type);
+ void refreshKnots();
+
+ FilletChamferPointArrayParam fillet_chamfer_values;
+
+private:
+
+ BoolParam hide_knots;
+ BoolParam ignore_radius_0;
+ BoolParam only_selected;
+ BoolParam flexible;
+ BoolParam use_knot_distance;
+ UnitParam unit;
+ EnumParam<FilletMethod> method;
+ ScalarParam radius;
+ ScalarParam chamfer_steps;
+ ScalarParam helper_size;
+
+ LPEFilletChamfer(const LPEFilletChamfer &);
+ LPEFilletChamfer &operator=(const LPEFilletChamfer &);
+
+};
+
+} //namespace LivePathEffect
+} //namespace Inkscape
+
+#endif
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/live_effects/lpe-interpolate_points.cpp b/src/live_effects/lpe-interpolate_points.cpp
new file mode 100644
index 000000000..4ac139752
--- /dev/null
+++ b/src/live_effects/lpe-interpolate_points.cpp
@@ -0,0 +1,94 @@
+/** \file
+ * LPE interpolate_points implementation
+ * Interpolates between knots of the input path.
+ */
+/*
+ * Authors:
+ * Johan Engelen
+ *
+ * Copyright (C) Johan Engelen 2014 <j.b.c.engelen@alumnus.utwente.nl>
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "live_effects/lpe-interpolate_points.h"
+
+#include <2geom/path.h>
+
+#include "live_effects/lpe-powerstroke-interpolators.h"
+
+namespace Inkscape {
+namespace LivePathEffect {
+
+
+static const Util::EnumData<unsigned> InterpolatorTypeData[] = {
+ {Geom::Interpolate::INTERP_LINEAR , N_("Linear"), "Linear"},
+ {Geom::Interpolate::INTERP_CUBICBEZIER , N_("CubicBezierFit"), "CubicBezierFit"},
+ {Geom::Interpolate::INTERP_CUBICBEZIER_JOHAN , N_("CubicBezierJohan"), "CubicBezierJohan"},
+ {Geom::Interpolate::INTERP_SPIRO , N_("SpiroInterpolator"), "SpiroInterpolator"},
+ {Geom::Interpolate::INTERP_CENTRIPETAL_CATMULLROM, N_("Centripetal Catmull-Rom"), "CentripetalCatmullRom"}
+};
+static const Util::EnumDataConverter<unsigned> InterpolatorTypeConverter(InterpolatorTypeData, sizeof(InterpolatorTypeData)/sizeof(*InterpolatorTypeData));
+
+
+LPEInterpolatePoints::LPEInterpolatePoints(LivePathEffectObject *lpeobject)
+ : Effect(lpeobject)
+ , interpolator_type(
+ _("Interpolator type:"),
+ _("Determines which kind of interpolator will be used to interpolate between stroke width along the path"),
+ "interpolator_type", InterpolatorTypeConverter, &wr, this, Geom::Interpolate::INTERP_CENTRIPETAL_CATMULLROM)
+{
+ show_orig_path = false;
+
+ registerParameter( &interpolator_type );
+}
+
+LPEInterpolatePoints::~LPEInterpolatePoints()
+{
+}
+
+
+Geom::PathVector
+LPEInterpolatePoints::doEffect_path (Geom::PathVector const & path_in)
+{
+ Geom::PathVector path_out;
+
+ std::auto_ptr<Geom::Interpolate::Interpolator> interpolator( Geom::Interpolate::Interpolator::create(static_cast<Geom::Interpolate::InterpolatorType>(interpolator_type.get_value())) );
+
+ for(Geom::PathVector::const_iterator path_it = path_in.begin(); path_it != path_in.end(); ++path_it) {
+ if (path_it->empty())
+ continue;
+
+ if (path_it->closed()) {
+ g_warning("Interpolate points LPE currently ignores whether path is closed or not.");
+ }
+
+ std::vector<Geom::Point> pts;
+ pts.push_back(path_it->initialPoint());
+
+ for (Geom::Path::const_iterator it = path_it->begin(), e = path_it->end_default(); it != e; ++it) {
+ pts.push_back((*it).finalPoint());
+ }
+
+ Geom::Path path = interpolator->interpolateToPath(pts);
+
+ path_out.push_back(path);
+ }
+
+ return path_out;
+}
+
+
+} //namespace LivePathEffect
+} /* namespace Inkscape */
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/live_effects/lpe-interpolate_points.h b/src/live_effects/lpe-interpolate_points.h
new file mode 100644
index 000000000..7a3364747
--- /dev/null
+++ b/src/live_effects/lpe-interpolate_points.h
@@ -0,0 +1,51 @@
+#ifndef INKSCAPE_LPE_INTERPOLATEPOINTS_H
+#define INKSCAPE_LPE_INTERPOLATEPOINTS_H
+
+/** \file
+ * LPE interpolate_points implementation, see lpe-interpolate_points.cpp.
+ */
+
+/*
+ * Authors:
+ * Johan Engelen
+ *
+ * Copyright (C) Johan Engelen 2014 <j.b.c.engelen@alumnus.utwente.nl>
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "live_effects/parameter/enum.h"
+#include "live_effects/effect.h"
+
+namespace Inkscape {
+namespace LivePathEffect {
+
+class LPEInterpolatePoints : public Effect {
+public:
+ LPEInterpolatePoints(LivePathEffectObject *lpeobject);
+ virtual ~LPEInterpolatePoints();
+
+ virtual std::vector<Geom::Path> doEffect_path (std::vector<Geom::Path> const & path_in);
+
+private:
+ EnumParam<unsigned> interpolator_type;
+
+ LPEInterpolatePoints(const LPEInterpolatePoints&);
+ LPEInterpolatePoints& operator=(const LPEInterpolatePoints&);
+};
+
+} //namespace LivePathEffect
+} //namespace Inkscape
+
+#endif // INKSCAPE_LPE_INTERPOLATEPOINTS_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/live_effects/lpe-jointype.cpp b/src/live_effects/lpe-jointype.cpp
new file mode 100644
index 000000000..bf2526986
--- /dev/null
+++ b/src/live_effects/lpe-jointype.cpp
@@ -0,0 +1,190 @@
+/* Authors:
+*
+* Liam P White
+*
+* Copyright (C) 2014 Authors
+*
+* Released under GNU GPL v2, read the file 'COPYING' for more information
+*/
+
+#include "live_effects/parameter/enum.h"
+#include "live_effects/pathoutlineprovider.h"
+
+#include "sp-shape.h"
+#include "style.h"
+#include "xml/repr.h"
+#include "sp-paint-server.h"
+#include "svg/svg-color.h"
+#include "desktop-style.h"
+#include "svg/css-ostringstream.h"
+#include "display/curve.h"
+
+#include <2geom/path.h>
+#include <2geom/svg-elliptical-arc.h>
+
+#include "lpe-jointype.h"
+
+namespace Inkscape {
+namespace LivePathEffect {
+
+static const Util::EnumData<unsigned> JoinTypeData[] = {
+ {LINEJOIN_STRAIGHT, N_("Beveled"), "bevel"},
+ {LINEJOIN_ROUND, N_("Rounded"), "round"},
+ {LINEJOIN_POINTY, N_("Miter"), "miter"},
+ {LINEJOIN_REFLECTED, N_("Reflected"), "extrapolated"},
+ {LINEJOIN_EXTRAPOLATED, N_("Extrapolated arc"), "extrp_arc"}
+};
+
+static const Util::EnumData<unsigned> CapTypeData[] = {
+ {BUTT_STRAIGHT, N_("Butt"), "butt"},
+ {BUTT_ROUND, N_("Rounded"), "round"},
+ {BUTT_SQUARE, N_("Square"), "square"},
+ {BUTT_POINTY, N_("Peak"), "peak"},
+ {BUTT_LEANED, N_("Leaned"), "leaned"}
+};
+
+static const Util::EnumDataConverter<unsigned> CapTypeConverter(CapTypeData, sizeof(CapTypeData)/sizeof(*CapTypeData));
+static const Util::EnumDataConverter<unsigned> JoinTypeConverter(JoinTypeData, sizeof(JoinTypeData)/sizeof(*JoinTypeData));
+
+LPEJoinType::LPEJoinType(LivePathEffectObject *lpeobject) :
+ Effect(lpeobject),
+ line_width(_("Line width"), _("Thickness of the stroke"), "line_width", &wr, this, 1.),
+ linecap_type(_("Line cap"), _("The end shape of the stroke"), "linecap_type", CapTypeConverter, &wr, this, butt_straight),
+ linejoin_type(_("Join:"), _("Determines the shape of the path's corners"), "linejoin_type", JoinTypeConverter, &wr, this, LINEJOIN_EXTRAPOLATED),
+ start_lean(_("Start path lean"), _("Start path lean"), "start_lean", &wr, this, 0.),
+ end_lean(_("End path lean"), _("End path lean"), "end_lean", &wr, this, 0.),
+ miter_limit(_("Miter limit:"), _("Maximum length of the miter join (in units of stroke width)"), "miter_limit", &wr, this, 100.),
+ attempt_force_join(_("Force miter"), _("Overrides the miter limit and forces a join."), "attempt_force_join", &wr, this, true)
+{
+ show_orig_path = true;
+ registerParameter(&linecap_type);
+ registerParameter(&line_width);
+ registerParameter(&linejoin_type);
+ registerParameter(&start_lean);
+ registerParameter(&end_lean);
+ registerParameter(&miter_limit);
+ registerParameter(&attempt_force_join);
+ was_initialized = false;
+ start_lean.param_set_range(-1,1);
+ start_lean.param_set_increments(0.1, 0.1);
+ start_lean.param_set_digits(4);
+ end_lean.param_set_range(-1,1);
+ end_lean.param_set_increments(0.1, 0.1);
+ end_lean.param_set_digits(4);
+}
+
+LPEJoinType::~LPEJoinType()
+{
+}
+
+//from LPEPowerStroke -- sets fill if stroke color because we will
+//be converting to a fill to make the new join.
+
+void LPEJoinType::doOnApply(SPLPEItem const* lpeitem)
+{
+ if (SP_IS_SHAPE(lpeitem)) {
+ SPLPEItem* item = const_cast<SPLPEItem*>(lpeitem);
+ double width = (lpeitem && lpeitem->style) ? lpeitem->style->stroke_width.computed : 1.;
+
+ SPCSSAttr *css = sp_repr_css_attr_new ();
+ if (true) {
+ if (lpeitem->style->stroke.isPaintserver()) {
+ SPPaintServer * server = lpeitem->style->getStrokePaintServer();
+ if (server) {
+ Glib::ustring str;
+ str += "url(#";
+ str += server->getId();
+ str += ")";
+ sp_repr_css_set_property (css, "fill", str.c_str());
+ }
+ } else if (lpeitem->style->stroke.isColor()) {
+ gchar c[64];
+ sp_svg_write_color (c, sizeof(c), lpeitem->style->stroke.value.color.toRGBA32(SP_SCALE24_TO_FLOAT(lpeitem->style->stroke_opacity.value)));
+ sp_repr_css_set_property (css, "fill", c);
+ } else {
+ sp_repr_css_set_property (css, "fill", "none");
+ }
+ } else {
+ sp_repr_css_unset_property (css, "fill");
+ }
+
+ sp_repr_css_set_property(css, "stroke", "none");
+
+ sp_desktop_apply_css_recursive(item, css, true);
+ sp_repr_css_attr_unref (css);
+ if (!was_initialized)
+ {
+ was_initialized = true;
+ line_width.param_set_value(width);
+ }
+ } else {
+ g_warning("LPE Join Type can only be applied to paths (not groups).");
+ }
+}
+
+//from LPEPowerStroke -- sets stroke color from existing fill color
+
+void LPEJoinType::doOnRemove(SPLPEItem const* lpeitem)
+{
+
+ if (SP_IS_SHAPE(lpeitem)) {
+ SPLPEItem *item = const_cast<SPLPEItem*>(lpeitem);
+
+ SPCSSAttr *css = sp_repr_css_attr_new ();
+ if (true) {
+ if (lpeitem->style->fill.isPaintserver()) {
+ SPPaintServer * server = lpeitem->style->getFillPaintServer();
+ if (server) {
+ Glib::ustring str;
+ str += "url(#";
+ str += server->getId();
+ str += ")";
+ sp_repr_css_set_property (css, "stroke", str.c_str());
+ }
+ } else if (lpeitem->style->fill.isColor()) {
+ gchar c[64];
+ sp_svg_write_color (c, sizeof(c), lpeitem->style->stroke.value.color.toRGBA32(SP_SCALE24_TO_FLOAT(lpeitem->style->stroke_opacity.value)));
+ sp_repr_css_set_property (css, "stroke", c);
+ } else {
+ sp_repr_css_set_property (css, "stroke", "none");
+ }
+ } else {
+ sp_repr_css_unset_property (css, "stroke");
+ }
+
+ Inkscape::CSSOStringStream os;
+ os << fabs(line_width);
+ sp_repr_css_set_property (css, "stroke-width", os.str().c_str());
+
+ sp_repr_css_set_property(css, "fill", "none");
+
+ sp_desktop_apply_css_recursive(item, css, true);
+ sp_repr_css_attr_unref (css);
+ item->updateRepr();
+ }
+}
+
+// NOTE: I originally had all the outliner functions defined in here, but they were actually useful
+// enough for other LPEs so I moved them all into pathoutlineprovider.cpp. The code here is just a
+// wrapper around it.
+std::vector<Geom::Path> LPEJoinType::doEffect_path(std::vector<Geom::Path> const & path_in)
+{
+ return Outline::PathVectorOutline(path_in, line_width, static_cast<ButtTypeMod>(linecap_type.get_value()),
+ static_cast<LineJoinType>(linejoin_type.get_value()),
+ (attempt_force_join ? std::numeric_limits<double>::max() : miter_limit),
+ start_lean/2 ,end_lean/2);
+}
+
+} // namespace LivePathEffect
+} // namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8 :
diff --git a/src/live_effects/lpe-jointype.h b/src/live_effects/lpe-jointype.h
new file mode 100644
index 000000000..73705666d
--- /dev/null
+++ b/src/live_effects/lpe-jointype.h
@@ -0,0 +1,57 @@
+/* Authors:
+ * Liam P White
+ *
+ * Copyright (C) 2014 Authors
+ *
+ * Released under GNU GPL v2, read the file COPYING for more information
+ */
+
+#ifndef INKSCAPE_LPE_JOINTYPE_H
+#define INKSCAPE_LPE_JOINTYPE_H
+
+#include "live_effects/effect.h"
+#include "live_effects/parameter/parameter.h"
+#include "live_effects/parameter/point.h"
+#include "live_effects/parameter/enum.h"
+
+namespace Inkscape {
+namespace LivePathEffect {
+
+class LPEJoinType : public Effect {
+public:
+ LPEJoinType(LivePathEffectObject *lpeobject);
+ virtual ~LPEJoinType();
+
+ virtual void doOnApply(SPLPEItem const* lpeitem);
+ virtual void doOnRemove(SPLPEItem const* lpeitem);
+ virtual std::vector <Geom::Path> doEffect_path (std::vector<Geom::Path> const & path_in);
+
+private:
+ LPEJoinType(const LPEJoinType&);
+ LPEJoinType& operator=(const LPEJoinType&);
+
+ ScalarParam line_width;
+ EnumParam<unsigned> linecap_type;
+ EnumParam<unsigned> linejoin_type;
+ ScalarParam start_lean;
+ ScalarParam end_lean;
+ ScalarParam miter_limit;
+ BoolParam attempt_force_join;
+ bool was_initialized;
+};
+
+} //namespace LivePathEffect
+} //namespace Inkscape
+
+#endif
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8 :
diff --git a/src/live_effects/lpe-knot.cpp b/src/live_effects/lpe-knot.cpp
index 581c632f5..3876aa24b 100644
--- a/src/live_effects/lpe-knot.cpp
+++ b/src/live_effects/lpe-knot.cpp
@@ -22,6 +22,7 @@
#include "knotholder.h"
#include <glibmm/i18n.h>
+#include <gdk/gdk.h>
#include <2geom/sbasis-to-bezier.h>
#include <2geom/sbasis.h>
@@ -353,7 +354,11 @@ LPEKnot::LPEKnot(LivePathEffectObject *lpeobject) :
add_other_stroke_width(_("_Crossing path stroke width"), _("Add crossed stroke width to the interruption size"), "add_other_stroke_width", &wr, this, true),
switcher_size(_("S_witcher size:"), _("Orientation indicator/switcher size"), "switcher_size", &wr, this, 15),
crossing_points_vector(_("Crossing Signs"), _("Crossings signs"), "crossing_points_vector", &wr, this),
- gpaths(),gstroke_widths()
+ crossing_points(),
+ gpaths(),
+ gstroke_widths(),
+ selectedCrossing(0),
+ switcher(0.,0.)
{
// register all your parameters here, so Inkscape knows which parameters this effect has:
registerParameter( dynamic_cast<Parameter *>(&interruption_width) );
@@ -363,10 +368,6 @@ LPEKnot::LPEKnot(LivePathEffectObject *lpeobject) :
registerParameter( dynamic_cast<Parameter *>(&switcher_size) );
registerParameter( dynamic_cast<Parameter *>(&crossing_points_vector) );
- crossing_points = LPEKnotNS::CrossingPoints();
- selectedCrossing = 0;
- switcher = Geom::Point(0,0);
-
_provides_knotholder_entities = true;
}
@@ -386,9 +387,7 @@ LPEKnot::updateSwitcher(){
//std::cout<<"placing switcher at "<<switcher<<" \n";
}else{
//std::cout<<"hiding switcher!\n";
- //TODO: is there a way to properly hide the helper.
- //switcher = Geom::Point(Geom::infinity(),Geom::infinity());
- switcher = Geom::Point(1e10,1e10);
+ switcher = Geom::Point(Geom::infinity(),Geom::infinity());
}
}
@@ -538,9 +537,14 @@ LPEKnot::doBeforeEffect (SPLPEItem const* lpeitem)
{
using namespace Geom;
original_bbox(lpeitem);
+
+ if (SP_IS_PATH(lpeitem)) {
+ supplied_path = SP_PATH(lpeitem)->getCurve()->get_pathvector();
+ }
+
+ gpaths.clear();
+ gstroke_widths.clear();
- gpaths = std::vector<Geom::Path>();
- gstroke_widths = std::vector<double>();
collectPathsAndWidths(lpeitem, gpaths, gstroke_widths);
// std::cout<<"\nPaths on input:\n";
@@ -586,7 +590,10 @@ LPEKnot::doBeforeEffect (SPLPEItem const* lpeitem)
// std::cout<<crossing_points[toto].sign<<"),";
// }
crossing_points.inherit_signs(old_crdata);
- crossing_points_vector.param_set_and_write_new_value(crossing_points.to_vector());
+
+ // Don't write to XML here, only store it in the param itself. Will be written to SVG later
+ crossing_points_vector.param_setValue(crossing_points.to_vector());
+
updateSwitcher();
}
diff --git a/src/live_effects/lpe-knot.h b/src/live_effects/lpe-knot.h
index b937f9021..080f32de2 100644
--- a/src/live_effects/lpe-knot.h
+++ b/src/live_effects/lpe-knot.h
@@ -64,7 +64,8 @@ public:
void addKnotHolderEntities(KnotHolder *knotholder, SPDesktop *desktop, SPItem *item);
protected:
- virtual void addCanvasIndicators(SPLPEItem const *lpeitem, std::vector<Geom::PathVector> &hp_vec);
+ virtual void addCanvasIndicators(SPLPEItem const *lpeitem, std::vector<Geom::PathVector> &hp_vec);
+ std::vector<Geom::Path> supplied_path; //for knotholder business
private:
void updateSwitcher();
@@ -74,7 +75,6 @@ private:
BoolParam add_stroke_width;
BoolParam add_other_stroke_width;
ScalarParam switcher_size;
- double stroke_width;
ArrayParam<double> crossing_points_vector;//svg storage of crossing_points
LPEKnotNS::CrossingPoints crossing_points;//topology representation of the knot.
diff --git a/src/live_effects/lpe-lattice.cpp b/src/live_effects/lpe-lattice.cpp
index 8136569e8..a241a8a2e 100644
--- a/src/live_effects/lpe-lattice.cpp
+++ b/src/live_effects/lpe-lattice.cpp
@@ -176,6 +176,9 @@ void
LPELattice::doBeforeEffect (SPLPEItem const* lpeitem)
{
original_bbox(lpeitem);
+ SPLPEItem * item = const_cast<SPLPEItem*>(lpeitem);
+ item->apply_to_clippath(item);
+ item->apply_to_mask(item);
}
void
diff --git a/src/live_effects/lpe-lattice.h b/src/live_effects/lpe-lattice.h
index a44dda3fd..5eb48909b 100644
--- a/src/live_effects/lpe-lattice.h
+++ b/src/live_effects/lpe-lattice.h
@@ -58,7 +58,6 @@ private:
PointParam grid_point13;
PointParam grid_point14;
PointParam grid_point15;
-
LPELattice(const LPELattice&);
LPELattice& operator=(const LPELattice&);
};
diff --git a/src/live_effects/lpe-lattice2.cpp b/src/live_effects/lpe-lattice2.cpp
new file mode 100644
index 000000000..e1cd91340
--- /dev/null
+++ b/src/live_effects/lpe-lattice2.cpp
@@ -0,0 +1,499 @@
+/** \file
+ * LPE <lattice2> implementation
+
+ */
+/*
+ * Authors:
+ * Johan Engelen <j.b.c.engelen@utwente.nl>
+ * Steren Giannini
+ * Noé Falzon
+ * Victor Navez
+ * ~suv
+ * Jabiertxo Arraiza
+*
+* Copyright (C) 2007-2008 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "live_effects/lpe-lattice2.h"
+
+#include "sp-shape.h"
+#include "sp-item.h"
+#include "sp-path.h"
+#include "display/curve.h"
+#include "svg/svg.h"
+
+#include <2geom/sbasis.h>
+#include <2geom/sbasis-2d.h>
+#include <2geom/sbasis-geometric.h>
+#include <2geom/bezier-to-sbasis.h>
+#include <2geom/sbasis-to-bezier.h>
+#include <2geom/d2.h>
+#include <2geom/piecewise.h>
+#include <2geom/transforms.h>
+#include "ui/tools-switch.h"
+
+#include "desktop.h" // TODO: should be factored out (see below)
+
+using namespace Geom;
+
+namespace Inkscape {
+namespace LivePathEffect {
+
+LPELattice2::LPELattice2(LivePathEffectObject *lpeobject) :
+ Effect(lpeobject),
+ // initialise your parameters here:
+ grid_point0(_("Control handle 0:"), _("Control handle 0 - Ctrl+Alt+Click to reset"), "gridpoint0", &wr, this),
+ grid_point1(_("Control handle 1:"), _("Control handle 1 - Ctrl+Alt+Click to reset"), "gridpoint1", &wr, this),
+ grid_point2(_("Control handle 2:"), _("Control handle 2 - Ctrl+Alt+Click to reset"), "gridpoint2", &wr, this),
+ grid_point3(_("Control handle 3:"), _("Control handle 3 - Ctrl+Alt+Click to reset"), "gridpoint3", &wr, this),
+ grid_point4(_("Control handle 4:"), _("Control handle 4 - Ctrl+Alt+Click to reset"), "gridpoint4", &wr, this),
+ grid_point5(_("Control handle 5:"), _("Control handle 5 - Ctrl+Alt+Click to reset"), "gridpoint5", &wr, this),
+ grid_point6(_("Control handle 6:"), _("Control handle 6 - Ctrl+Alt+Click to reset"), "gridpoint6", &wr, this),
+ grid_point7(_("Control handle 7:"), _("Control handle 7 - Ctrl+Alt+Click to reset"), "gridpoint7", &wr, this),
+ grid_point8x9(_("Control handle 8x9:"), _("Control handle 8x9 - Ctrl+Alt+Click to reset"), "gridpoint8x9", &wr, this),
+ grid_point10x11(_("Control handle 10x11:"), _("Control handle 10x11 - Ctrl+Alt+Click to reset"), "gridpoint10x11", &wr, this),
+ grid_point12(_("Control handle 12:"), _("Control handle 12 - Ctrl+Alt+Click to reset"), "gridpoint12", &wr, this),
+ grid_point13(_("Control handle 13:"), _("Control handle 13 - Ctrl+Alt+Click to reset"), "gridpoint13", &wr, this),
+ grid_point14(_("Control handle 14:"), _("Control handle 14 - Ctrl+Alt+Click to reset"), "gridpoint14", &wr, this),
+ grid_point15(_("Control handle 15:"), _("Control handle 15 - Ctrl+Alt+Click to reset"), "gridpoint15", &wr, this),
+ grid_point16(_("Control handle 16:"), _("Control handle 16 - Ctrl+Alt+Click to reset"), "gridpoint16", &wr, this),
+ grid_point17(_("Control handle 17:"), _("Control handle 17 - Ctrl+Alt+Click to reset"), "gridpoint17", &wr, this),
+ grid_point18(_("Control handle 18:"), _("Control handle 18 - Ctrl+Alt+Click to reset"), "gridpoint18", &wr, this),
+ grid_point19(_("Control handle 19:"), _("Control handle 19 - Ctrl+Alt+Click to reset"), "gridpoint19", &wr, this),
+ grid_point20x21(_("Control handle 20x21:"), _("Control handle 20x21 - Ctrl+Alt+Click to reset"), "gridpoint20x21", &wr, this),
+ grid_point22x23(_("Control handle 22x23:"), _("Control handle 22x23 - Ctrl+Alt+Click to reset"), "gridpoint22x23", &wr, this),
+ grid_point24x26(_("Control handle 24x26:"), _("Control handle 24x26 - Ctrl+Alt+Click to reset"), "gridpoint24x26", &wr, this),
+ grid_point25x27(_("Control handle 25x27:"), _("Control handle 25x27 - Ctrl+Alt+Click to reset"), "gridpoint25x27", &wr, this),
+ grid_point28x30(_("Control handle 28x30:"), _("Control handle 28x30 - Ctrl+Alt+Click to reset"), "gridpoint28x30", &wr, this),
+ grid_point29x31(_("Control handle 29x31:"), _("Control handle 29x31 - Ctrl+Alt+Click to reset"), "gridpoint29x31", &wr, this),
+ grid_point32x33x34x35(_("Control handle 32x33x34x35:"), _("Control handle 32x33x34x35 - Ctrl+Alt+Click to reset"), "gridpoint32x33x34x35", &wr, this)
+
+
+{
+ // register all your parameters here, so Inkscape knows which parameters this effect has:
+ registerParameter( dynamic_cast<Parameter *>(&grid_point0) );
+ registerParameter( dynamic_cast<Parameter *>(&grid_point1) );
+ registerParameter( dynamic_cast<Parameter *>(&grid_point2) );
+ registerParameter( dynamic_cast<Parameter *>(&grid_point3) );
+ registerParameter( dynamic_cast<Parameter *>(&grid_point4) );
+ registerParameter( dynamic_cast<Parameter *>(&grid_point5) );
+ registerParameter( dynamic_cast<Parameter *>(&grid_point6) );
+ registerParameter( dynamic_cast<Parameter *>(&grid_point7) );
+ registerParameter( dynamic_cast<Parameter *>(&grid_point8x9) );
+ registerParameter( dynamic_cast<Parameter *>(&grid_point10x11) );
+ registerParameter( dynamic_cast<Parameter *>(&grid_point12) );
+ registerParameter( dynamic_cast<Parameter *>(&grid_point13) );
+ registerParameter( dynamic_cast<Parameter *>(&grid_point14) );
+ registerParameter( dynamic_cast<Parameter *>(&grid_point15) );
+ registerParameter( dynamic_cast<Parameter *>(&grid_point16) );
+ registerParameter( dynamic_cast<Parameter *>(&grid_point17) );
+ registerParameter( dynamic_cast<Parameter *>(&grid_point18) );
+ registerParameter( dynamic_cast<Parameter *>(&grid_point19) );
+ registerParameter( dynamic_cast<Parameter *>(&grid_point20x21) );
+ registerParameter( dynamic_cast<Parameter *>(&grid_point22x23) );
+ registerParameter( dynamic_cast<Parameter *>(&grid_point24x26) );
+ registerParameter( dynamic_cast<Parameter *>(&grid_point25x27) );
+ registerParameter( dynamic_cast<Parameter *>(&grid_point28x30) );
+ registerParameter( dynamic_cast<Parameter *>(&grid_point29x31) );
+ registerParameter( dynamic_cast<Parameter *>(&grid_point32x33x34x35) );
+}
+
+LPELattice2::~LPELattice2()
+{
+}
+
+Geom::Piecewise<Geom::D2<Geom::SBasis> >
+LPELattice2::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_in)
+{
+ D2<SBasis2d> sb2;
+
+ //Initialisation of the sb2
+ for(unsigned dim = 0; dim < 2; dim++) {
+ sb2[dim].us = 3;
+ sb2[dim].vs = 3;
+ const int depth = sb2[dim].us*sb2[dim].vs;
+ sb2[dim].resize(depth, Linear2d(0));
+ }
+
+ //Grouping the point params in a convenient vector
+ std::vector<Geom::Point *> handles(36);
+
+ handles[0] = &grid_point0;
+ handles[1] = &grid_point1;
+ handles[2] = &grid_point2;
+ handles[3] = &grid_point3;
+ handles[4] = &grid_point4;
+ handles[5] = &grid_point5;
+ handles[6] = &grid_point6;
+ handles[7] = &grid_point7;
+ handles[8] = &grid_point8x9;
+ handles[9] = &grid_point8x9;
+ handles[10] = &grid_point10x11;
+ handles[11] = &grid_point10x11;
+ handles[12] = &grid_point12;
+ handles[13] = &grid_point13;
+ handles[14] = &grid_point14;
+ handles[15] = &grid_point15;
+ handles[16] = &grid_point16;
+ handles[17] = &grid_point17;
+ handles[18] = &grid_point18;
+ handles[19] = &grid_point19;
+ handles[20] = &grid_point20x21;
+ handles[21] = &grid_point20x21;
+ handles[22] = &grid_point22x23;
+ handles[23] = &grid_point22x23;
+ handles[24] = &grid_point24x26;
+ handles[25] = &grid_point25x27;
+ handles[26] = &grid_point24x26;
+ handles[27] = &grid_point25x27;
+ handles[28] = &grid_point28x30;
+ handles[29] = &grid_point29x31;
+ handles[30] = &grid_point28x30;
+ handles[31] = &grid_point29x31;
+ handles[32] = &grid_point32x33x34x35;
+ handles[33] = &grid_point32x33x34x35;
+ handles[34] = &grid_point32x33x34x35;
+ handles[35] = &grid_point32x33x34x35;
+
+ Geom::Point origin = Geom::Point(boundingbox_X.min(),boundingbox_Y.min());
+
+ double width = boundingbox_X.extent();
+ double height = boundingbox_Y.extent();
+
+ //numbering is based on 4 rectangles.16
+ for(unsigned dim = 0; dim < 2; dim++) {
+ Geom::Point dir(0,0);
+ dir[dim] = 1;
+ for(unsigned vi = 0; vi < sb2[dim].vs; vi++) {
+ for(unsigned ui = 0; ui < sb2[dim].us; ui++) {
+ for(unsigned iv = 0; iv < 2; iv++) {
+ for(unsigned iu = 0; iu < 2; iu++) {
+ unsigned corner = iu + 2*iv;
+ unsigned i = ui + vi*sb2[dim].us;
+
+ //This is the offset from the Upperleft point
+ Geom::Point base( (ui + iu*(4-2*ui))*width/4.,
+ (vi + iv*(4-2*vi))*height/4.);
+
+ //Special action for corners
+ if(vi == 0 && ui == 0) {
+ base = Geom::Point(0,0);
+ }
+
+ // i = Upperleft corner of the considerated rectangle
+ // corner = actual corner of the rectangle
+ // origin = Upperleft point
+ double dl = dot((*handles[corner+4*i] - (base + origin)), dir)/dot(dir,dir);
+ sb2[dim][i][corner] = dl/( dim ? height : width )*pow(4.0,ui+vi);
+ }
+ }
+ }
+ }
+ }
+
+ Piecewise<D2<SBasis> > output;
+ output.push_cut(0.);
+ for(unsigned i = 0; i < pwd2_in.size(); i++) {
+ D2<SBasis> B = pwd2_in[i];
+ B[Geom::X] -= origin[Geom::X];
+ B[Geom::X]*= 1/width;
+ B[Geom::Y] -= origin[Geom::Y];
+ B[Geom::Y]*= 1/height;
+ //Here comes the magic
+ D2<SBasis> tB = compose_each(sb2,B);
+ tB[Geom::X] = tB[Geom::X] * width + origin[Geom::X];
+ tB[Geom::Y] = tB[Geom::Y] * height + origin[Geom::Y];
+
+ output.push(tB,i+1);
+ }
+ return output;
+}
+
+Gtk::Widget *
+LPELattice2::newWidget()
+{
+ // use manage here, because after deletion of Effect object, others might still be pointing to this widget.
+ Gtk::VBox * vbox = Gtk::manage( new Gtk::VBox(Effect::newWidget()) );
+
+ vbox->set_border_width(5);
+ Gtk::Button* resetButton = Gtk::manage(new Gtk::Button(Glib::ustring(_("Reset grid"))));
+ resetButton->set_alignment(0.0, 0.5);
+ resetButton->signal_clicked().connect(sigc::mem_fun (*this,&LPELattice2::resetGrid));
+ Gtk::Widget* resetButtonWidget = dynamic_cast<Gtk::Widget *>(resetButton);
+ resetButtonWidget->set_tooltip_text("Reset grid");
+ vbox->pack_start(*resetButtonWidget, true, true,2);
+ std::vector<Parameter *>::iterator it = param_vector.begin();
+ while (it != param_vector.end()) {
+ if ((*it)->widget_is_visible) {
+ Parameter * param = *it;
+ Gtk::Widget * widg = dynamic_cast<Gtk::Widget *>(param->param_newWidget());
+ if(param->param_key == "grid"){
+ widg = NULL;
+ }
+ Glib::ustring * tip = param->param_getTooltip();
+ if (widg) {
+ vbox->pack_start(*widg, true, true, 2);
+ if (tip) {
+ widg->set_tooltip_text(*tip);
+ } else {
+ widg->set_tooltip_text("");
+ widg->set_has_tooltip(false);
+ }
+ }
+ }
+
+ ++it;
+ }
+ return dynamic_cast<Gtk::Widget *>(vbox);
+}
+
+void
+LPELattice2::doBeforeEffect (SPLPEItem const* lpeitem)
+{
+ original_bbox(lpeitem);
+ setDefaults();
+ SPLPEItem * item = const_cast<SPLPEItem*>(lpeitem);
+ item->apply_to_clippath(item);
+ item->apply_to_mask(item);
+}
+
+void
+LPELattice2::setDefaults()
+{
+ Geom::Point gp0((boundingbox_X.max()-boundingbox_X.min())/4*0+boundingbox_X.min(),
+ (boundingbox_Y.max()-boundingbox_Y.min())/4*0+boundingbox_Y.min());
+
+ Geom::Point gp1((boundingbox_X.max()-boundingbox_X.min())/4*4+boundingbox_X.min(),
+ (boundingbox_Y.max()-boundingbox_Y.min())/4*0+boundingbox_Y.min());
+
+ Geom::Point gp2((boundingbox_X.max()-boundingbox_X.min())/4*0+boundingbox_X.min(),
+ (boundingbox_Y.max()-boundingbox_Y.min())/4*4+boundingbox_Y.min());
+
+ Geom::Point gp3((boundingbox_X.max()-boundingbox_X.min())/4*4+boundingbox_X.min(),
+ (boundingbox_Y.max()-boundingbox_Y.min())/4*4+boundingbox_Y.min());
+
+ Geom::Point gp4((boundingbox_X.max()-boundingbox_X.min())/4*1+boundingbox_X.min(),
+ (boundingbox_Y.max()-boundingbox_Y.min())/4*0+boundingbox_Y.min());
+
+ Geom::Point gp5((boundingbox_X.max()-boundingbox_X.min())/4*3+boundingbox_X.min(),
+ (boundingbox_Y.max()-boundingbox_Y.min())/4*0+boundingbox_Y.min());
+
+ Geom::Point gp6((boundingbox_X.max()-boundingbox_X.min())/4*1+boundingbox_X.min(),
+ (boundingbox_Y.max()-boundingbox_Y.min())/4*4+boundingbox_Y.min());
+
+ Geom::Point gp7((boundingbox_X.max()-boundingbox_X.min())/4*3+boundingbox_X.min(),
+ (boundingbox_Y.max()-boundingbox_Y.min())/4*4+boundingbox_Y.min());
+
+ Geom::Point gp8x9((boundingbox_X.max()-boundingbox_X.min())/4*2+boundingbox_X.min(),
+ (boundingbox_Y.max()-boundingbox_Y.min())/4*0+boundingbox_Y.min());
+
+ Geom::Point gp10x11((boundingbox_X.max()-boundingbox_X.min())/4*2+boundingbox_X.min(),
+ (boundingbox_Y.max()-boundingbox_Y.min())/4*4+boundingbox_Y.min());
+
+ Geom::Point gp12((boundingbox_X.max()-boundingbox_X.min())/4*0+boundingbox_X.min(),
+ (boundingbox_Y.max()-boundingbox_Y.min())/4*1+boundingbox_Y.min());
+
+ Geom::Point gp13((boundingbox_X.max()-boundingbox_X.min())/4*4+boundingbox_X.min(),
+ (boundingbox_Y.max()-boundingbox_Y.min())/4*1+boundingbox_Y.min());
+
+ Geom::Point gp14((boundingbox_X.max()-boundingbox_X.min())/4*0+boundingbox_X.min(),
+ (boundingbox_Y.max()-boundingbox_Y.min())/4*3+boundingbox_Y.min());
+
+ Geom::Point gp15((boundingbox_X.max()-boundingbox_X.min())/4*4+boundingbox_X.min(),
+ (boundingbox_Y.max()-boundingbox_Y.min())/4*3+boundingbox_Y.min());
+
+ Geom::Point gp16((boundingbox_X.max()-boundingbox_X.min())/4*1+boundingbox_X.min(),
+ (boundingbox_Y.max()-boundingbox_Y.min())/4*1+boundingbox_Y.min());
+
+ Geom::Point gp17((boundingbox_X.max()-boundingbox_X.min())/4*3+boundingbox_X.min(),
+ (boundingbox_Y.max()-boundingbox_Y.min())/4*1+boundingbox_Y.min());
+
+ Geom::Point gp18((boundingbox_X.max()-boundingbox_X.min())/4*1+boundingbox_X.min(),
+ (boundingbox_Y.max()-boundingbox_Y.min())/4*3+boundingbox_Y.min());
+
+ Geom::Point gp19((boundingbox_X.max()-boundingbox_X.min())/4*3+boundingbox_X.min(),
+ (boundingbox_Y.max()-boundingbox_Y.min())/4*3+boundingbox_Y.min());
+
+ Geom::Point gp20x21((boundingbox_X.max()-boundingbox_X.min())/4*2+boundingbox_X.min(),
+ (boundingbox_Y.max()-boundingbox_Y.min())/4*1+boundingbox_Y.min());
+
+ Geom::Point gp22x23((boundingbox_X.max()-boundingbox_X.min())/4*2+boundingbox_X.min(),
+ (boundingbox_Y.max()-boundingbox_Y.min())/4*3+boundingbox_Y.min());
+
+ Geom::Point gp24x26((boundingbox_X.max()-boundingbox_X.min())/4*0+boundingbox_X.min(),
+ (boundingbox_Y.max()-boundingbox_Y.min())/4*2+boundingbox_Y.min());
+
+ Geom::Point gp25x27((boundingbox_X.max()-boundingbox_X.min())/4*4+boundingbox_X.min(),
+ (boundingbox_Y.max()-boundingbox_Y.min())/4*2+boundingbox_Y.min());
+
+ Geom::Point gp28x30((boundingbox_X.max()-boundingbox_X.min())/4*1+boundingbox_X.min(),
+ (boundingbox_Y.max()-boundingbox_Y.min())/4*2+boundingbox_Y.min());
+
+ Geom::Point gp29x31((boundingbox_X.max()-boundingbox_X.min())/4*3+boundingbox_X.min(),
+ (boundingbox_Y.max()-boundingbox_Y.min())/4*2+boundingbox_Y.min());
+
+ Geom::Point gp32x33x34x35((boundingbox_X.max()-boundingbox_X.min())/4*2+boundingbox_X.min(),
+ (boundingbox_Y.max()-boundingbox_Y.min())/4*2+boundingbox_Y.min());
+
+ grid_point0.param_update_default(gp0);
+ grid_point1.param_update_default(gp1);
+ grid_point2.param_update_default(gp2);
+ grid_point3.param_update_default(gp3);
+ grid_point4.param_update_default(gp4);
+ grid_point5.param_update_default(gp5);
+ grid_point6.param_update_default(gp6);
+ grid_point7.param_update_default(gp7);
+ grid_point8x9.param_update_default(gp8x9);
+ grid_point10x11.param_update_default(gp10x11);
+ grid_point12.param_update_default(gp12);
+ grid_point13.param_update_default(gp13);
+ grid_point14.param_update_default(gp14);
+ grid_point15.param_update_default(gp15);
+ grid_point16.param_update_default(gp16);
+ grid_point17.param_update_default(gp17);
+ grid_point18.param_update_default(gp18);
+ grid_point19.param_update_default(gp19);
+ grid_point20x21.param_update_default(gp20x21);
+ grid_point22x23.param_update_default(gp22x23);
+ grid_point24x26.param_update_default(gp24x26);
+ grid_point25x27.param_update_default(gp25x27);
+ grid_point28x30.param_update_default(gp28x30);
+ grid_point29x31.param_update_default(gp29x31);
+ grid_point32x33x34x35.param_update_default(gp32x33x34x35);
+}
+
+void
+LPELattice2::resetGrid()
+{
+ grid_point0.param_set_and_write_default();
+ grid_point1.param_set_and_write_default();
+ grid_point2.param_set_and_write_default();
+ grid_point3.param_set_and_write_default();
+ grid_point4.param_set_and_write_default();
+ grid_point5.param_set_and_write_default();
+ grid_point6.param_set_and_write_default();
+ grid_point7.param_set_and_write_default();
+ grid_point8x9.param_set_and_write_default();
+ grid_point10x11.param_set_and_write_default();
+ grid_point12.param_set_and_write_default();
+ grid_point13.param_set_and_write_default();
+ grid_point14.param_set_and_write_default();
+ grid_point15.param_set_and_write_default();
+ grid_point16.param_set_and_write_default();
+ grid_point17.param_set_and_write_default();
+ grid_point18.param_set_and_write_default();
+ grid_point19.param_set_and_write_default();
+ grid_point20x21.param_set_and_write_default();
+ grid_point22x23.param_set_and_write_default();
+ grid_point24x26.param_set_and_write_default();
+ grid_point25x27.param_set_and_write_default();
+ grid_point28x30.param_set_and_write_default();
+ grid_point29x31.param_set_and_write_default();
+ grid_point32x33x34x35.param_set_and_write_default();
+ //todo:this hack is only to reposition the knots on reser grid button
+ //Better update path effect in LPEITEM
+ SPDesktop * desktop = SP_ACTIVE_DESKTOP;
+ tools_switch(desktop, TOOLS_SELECT);
+ tools_switch(desktop, TOOLS_NODES);
+}
+
+void
+LPELattice2::resetDefaults(SPItem const* item)
+{
+ Effect::resetDefaults(item);
+ original_bbox(SP_LPE_ITEM(item));
+ setDefaults();
+ resetGrid();
+}
+
+void
+LPELattice2::calculateCurve(Geom::Point a,Geom::Point b, SPCurve* c, bool horizontal, bool move)
+{
+ using Geom::X;
+ using Geom::Y;
+ if(move) c->moveto(a);
+ Geom::Point cubic1 = a + (1./3)* (b - a);
+ Geom::Point cubic2 = b + (1./3)* (a - b);
+ if(horizontal) c->curveto(Geom::Point(cubic1[X],a[Y]),Geom::Point(cubic2[X],b[Y]),b);
+ else c->curveto(Geom::Point(a[X],cubic1[Y]),Geom::Point(b[X],cubic2[Y]),b);
+}
+
+void
+LPELattice2::addCanvasIndicators(SPLPEItem const */*lpeitem*/, std::vector<Geom::PathVector> &hp_vec)
+{
+ hp_vec.clear();
+
+ SPCurve *c = new SPCurve();
+ calculateCurve(grid_point0,grid_point4, c,true, true);
+ calculateCurve(grid_point4,grid_point8x9, c,true, false);
+ calculateCurve(grid_point8x9,grid_point5, c,true, false);
+ calculateCurve(grid_point5,grid_point1, c,true, false);
+
+ calculateCurve(grid_point12,grid_point16, c,true, true);
+ calculateCurve(grid_point16,grid_point20x21, c,true, false);
+ calculateCurve(grid_point20x21,grid_point17, c,true, false);
+ calculateCurve(grid_point17,grid_point13, c,true, false);
+
+ calculateCurve(grid_point24x26,grid_point28x30, c,true, true);
+ calculateCurve(grid_point28x30,grid_point32x33x34x35, c,true, false);
+ calculateCurve(grid_point32x33x34x35,grid_point29x31, c,true, false);
+ calculateCurve(grid_point29x31,grid_point25x27, c,true, false);
+
+ calculateCurve(grid_point14,grid_point18, c,true, true);
+ calculateCurve(grid_point18,grid_point22x23, c,true, false);
+ calculateCurve(grid_point22x23,grid_point19, c,true, false);
+ calculateCurve(grid_point19,grid_point15, c,true, false);
+
+ calculateCurve(grid_point2,grid_point6, c,true, true);
+ calculateCurve(grid_point6,grid_point10x11, c,true, false);
+ calculateCurve(grid_point10x11,grid_point7, c,true, false);
+ calculateCurve(grid_point7,grid_point3, c,true, false);
+
+ calculateCurve(grid_point0,grid_point12, c,false, true);
+ calculateCurve(grid_point12,grid_point24x26, c,false, false);
+ calculateCurve(grid_point24x26,grid_point14, c,false, false);
+ calculateCurve(grid_point14,grid_point2, c,false, false);
+
+ calculateCurve(grid_point4,grid_point16, c,false, true);
+ calculateCurve(grid_point16,grid_point28x30, c,false, false);
+ calculateCurve(grid_point28x30,grid_point18, c,false, false);
+ calculateCurve(grid_point18,grid_point6, c,false, false);
+
+ calculateCurve(grid_point8x9,grid_point20x21, c,false, true);
+ calculateCurve(grid_point20x21,grid_point32x33x34x35, c,false, false);
+ calculateCurve(grid_point32x33x34x35,grid_point22x23, c,false, false);
+ calculateCurve(grid_point22x23,grid_point10x11, c,false, false);
+
+ calculateCurve(grid_point5,grid_point17, c, false, true);
+ calculateCurve(grid_point17,grid_point29x31, c,false, false);
+ calculateCurve(grid_point29x31,grid_point19, c,false, false);
+ calculateCurve(grid_point19,grid_point7, c,false, false);
+
+ calculateCurve(grid_point1,grid_point13, c, false, true);
+ calculateCurve(grid_point13,grid_point25x27, c,false, false);
+ calculateCurve(grid_point25x27,grid_point15, c,false, false);
+ calculateCurve(grid_point15,grid_point3, c, false, false);
+ hp_vec.push_back(c->get_pathvector());
+}
+
+
+/* ######################## */
+
+} //namespace LivePathEffect
+} /* namespace Inkscape */
+
+
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/live_effects/lpe-lattice2.h b/src/live_effects/lpe-lattice2.h
new file mode 100644
index 000000000..461f835c6
--- /dev/null
+++ b/src/live_effects/lpe-lattice2.h
@@ -0,0 +1,92 @@
+#ifndef INKSCAPE_LPE_LATTICE2_H
+#define INKSCAPE_LPE_LATTICE2_H
+
+/** \file
+ * LPE <lattice2> implementation, see lpe-lattice2.cpp.
+ */
+
+/*
+ * Authors:
+ * Johan Engelen
+ * Steren Giannini
+ * Noé Falzon
+ * Victor Navez
+ * ~suv
+ * Jabiertxo Arraiza
+*
+* Copyright (C) Johan Engelen 2007 <j.b.c.engelen@utwente.nl>
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "live_effects/parameter/enum.h"
+#include "live_effects/effect.h"
+#include "live_effects/parameter/pointreseteable.h"
+#include "live_effects/lpegroupbbox.h"
+
+namespace Inkscape {
+namespace LivePathEffect {
+
+class LPELattice2 : public Effect, GroupBBoxEffect {
+public:
+
+ LPELattice2(LivePathEffectObject *lpeobject);
+ virtual ~LPELattice2();
+
+ virtual Geom::Piecewise<Geom::D2<Geom::SBasis> > doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_in);
+
+ virtual void resetDefaults(SPItem const* item);
+
+ virtual void doBeforeEffect(SPLPEItem const* lpeitem);
+
+ virtual Gtk::Widget * newWidget();
+
+ virtual void calculateCurve(Geom::Point a,Geom::Point b, SPCurve *c, bool horizontal, bool move);
+
+ virtual void setDefaults();
+
+ virtual void resetGrid();
+
+ //virtual void original_bbox(SPLPEItem const* lpeitem, bool absolute = false);
+
+ //virtual void addCanvasIndicators(SPLPEItem const*/*lpeitem*/, std::vector<Geom::PathVector> &/*hp_vec*/);
+
+ //virtual std::vector<Geom::PathVector> getHelperPaths(SPLPEItem const* lpeitem);
+protected:
+ void addCanvasIndicators(SPLPEItem const */*lpeitem*/, std::vector<Geom::PathVector> &hp_vec);
+private:
+
+ PointReseteableParam grid_point0;
+ PointReseteableParam grid_point1;
+ PointReseteableParam grid_point2;
+ PointReseteableParam grid_point3;
+ PointReseteableParam grid_point4;
+ PointReseteableParam grid_point5;
+ PointReseteableParam grid_point6;
+ PointReseteableParam grid_point7;
+ PointReseteableParam grid_point8x9;
+ PointReseteableParam grid_point10x11;
+ PointReseteableParam grid_point12;
+ PointReseteableParam grid_point13;
+ PointReseteableParam grid_point14;
+ PointReseteableParam grid_point15;
+ PointReseteableParam grid_point16;
+ PointReseteableParam grid_point17;
+ PointReseteableParam grid_point18;
+ PointReseteableParam grid_point19;
+ PointReseteableParam grid_point20x21;
+ PointReseteableParam grid_point22x23;
+ PointReseteableParam grid_point24x26;
+ PointReseteableParam grid_point25x27;
+ PointReseteableParam grid_point28x30;
+ PointReseteableParam grid_point29x31;
+ PointReseteableParam grid_point32x33x34x35;
+
+ LPELattice2(const LPELattice2&);
+ LPELattice2& operator=(const LPELattice2&);
+};
+
+} //namespace LivePathEffect
+} //namespace Inkscape
+
+#endif
diff --git a/src/live_effects/lpe-mirror_symmetry.cpp b/src/live_effects/lpe-mirror_symmetry.cpp
index 4d4837d8d..0bb67a4a2 100644
--- a/src/live_effects/lpe-mirror_symmetry.cpp
+++ b/src/live_effects/lpe-mirror_symmetry.cpp
@@ -43,6 +43,14 @@ LPEMirrorSymmetry::~LPEMirrorSymmetry()
}
void
+LPEMirrorSymmetry::doBeforeEffect (SPLPEItem const* lpeitem)
+{
+ SPLPEItem * item = const_cast<SPLPEItem*>(lpeitem);
+ item->apply_to_clippath(item);
+ item->apply_to_mask(item);
+}
+
+void
LPEMirrorSymmetry::doOnApply (SPLPEItem const* lpeitem)
{
using namespace Geom;
diff --git a/src/live_effects/lpe-mirror_symmetry.h b/src/live_effects/lpe-mirror_symmetry.h
index c01d1bf6f..a4a2b86c0 100644
--- a/src/live_effects/lpe-mirror_symmetry.h
+++ b/src/live_effects/lpe-mirror_symmetry.h
@@ -30,6 +30,8 @@ public:
virtual void doOnApply (SPLPEItem const* lpeitem);
+ virtual void doBeforeEffect (SPLPEItem const* lpeitem);
+
virtual std::vector<Geom::Path> doEffect_path (std::vector<Geom::Path> const & path_in);
private:
diff --git a/src/live_effects/lpe-offset.cpp b/src/live_effects/lpe-offset.cpp
index 192bd17ca..dc91775b7 100644
--- a/src/live_effects/lpe-offset.cpp
+++ b/src/live_effects/lpe-offset.cpp
@@ -55,6 +55,14 @@ static void append_half_circle(Geom::Piecewise<Geom::D2<Geom::SBasis> > &pwd2,
pwd2.continuousConcat(cap_pwd2);
}
+void
+LPEOffset::doBeforeEffect (SPLPEItem const* lpeitem)
+{
+ SPLPEItem * item = const_cast<SPLPEItem*>(lpeitem);
+ item->apply_to_clippath(item);
+ item->apply_to_mask(item);
+}
+
Geom::Piecewise<Geom::D2<Geom::SBasis> >
LPEOffset::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_in)
{
diff --git a/src/live_effects/lpe-offset.h b/src/live_effects/lpe-offset.h
index 9966fd45d..997311c7d 100644
--- a/src/live_effects/lpe-offset.h
+++ b/src/live_effects/lpe-offset.h
@@ -28,6 +28,8 @@ public:
virtual void doOnApply (SPLPEItem const* lpeitem);
+ virtual void doBeforeEffect (SPLPEItem const* lpeitem);
+
virtual Geom::Piecewise<Geom::D2<Geom::SBasis> > doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_in);
private:
diff --git a/src/live_effects/lpe-perspective-envelope.cpp b/src/live_effects/lpe-perspective-envelope.cpp
new file mode 100644
index 000000000..b5ef26e2f
--- /dev/null
+++ b/src/live_effects/lpe-perspective-envelope.cpp
@@ -0,0 +1,387 @@
+/** \file
+ * LPE <perspective-envelope> implementation
+
+ */
+/*
+ * Authors:
+ * Jabiertxof Code migration from python extensions envelope and perspective
+ * Aaron Spike, aaron@ekips.org from envelope and perspective phyton code
+ * Dmitry Platonov, shadowjack@mail.ru, 2006 perspective approach & math
+ * Jose Hevia (freon) Transform algorithm from envelope
+ *
+ * Copyright (C) 2007-2014 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <gtkmm.h>
+#include "live_effects/lpe-perspective-envelope.h"
+#include "helper/geom.h"
+#include "display/curve.h"
+#include "svg/svg.h"
+#include "ui/tools-switch.h"
+#include <gsl/gsl_linalg.h>
+#include "desktop.h"
+
+using namespace Geom;
+
+namespace Inkscape {
+namespace LivePathEffect {
+
+enum DeformationType {
+ DEFORMATION_PERSPECTIVE,
+ DEFORMATION_ENVELOPE
+};
+
+static const Util::EnumData<unsigned> DeformationTypeData[] = {
+ {DEFORMATION_PERSPECTIVE , N_("Perspective"), "Perspective"},
+ {DEFORMATION_ENVELOPE , N_("Envelope deformation"), "Envelope deformation"}
+};
+
+static const Util::EnumDataConverter<unsigned> DeformationTypeConverter(DeformationTypeData, sizeof(DeformationTypeData)/sizeof(*DeformationTypeData));
+
+LPEPerspectiveEnvelope::LPEPerspectiveEnvelope(LivePathEffectObject *lpeobject) :
+ Effect(lpeobject),
+ // initialise your parameters here:
+ deform_type(_("Type"), _("Select the type of deformation"), "deform_type", DeformationTypeConverter, &wr, this, DEFORMATION_PERSPECTIVE),
+ Up_Left_Point(_("Top Left"), _("Top Left - Ctrl+Alt+Click to reset"), "Up_Left_Point", &wr, this),
+ Up_Right_Point(_("Top Right"), _("Top Right - Ctrl+Alt+Click to reset"), "Up_Right_Point", &wr, this),
+ Down_Left_Point(_("Down Left"), _("Down Left - Ctrl+Alt+Click to reset"), "Down_Left_Point", &wr, this),
+ Down_Right_Point(_("Down Right"), _("Down Right - Ctrl+Alt+Click to reset"), "Down_Right_Point", &wr, this)
+{
+ // register all your parameters here, so Inkscape knows which parameters this effect has:
+ registerParameter( dynamic_cast<Parameter *>(&deform_type));
+ registerParameter( dynamic_cast<Parameter *>(&Up_Left_Point) );
+ registerParameter( dynamic_cast<Parameter *>(&Up_Right_Point) );
+ registerParameter( dynamic_cast<Parameter *>(&Down_Left_Point) );
+ registerParameter( dynamic_cast<Parameter *>(&Down_Right_Point) );
+}
+
+LPEPerspectiveEnvelope::~LPEPerspectiveEnvelope()
+{
+}
+
+void LPEPerspectiveEnvelope::doEffect(SPCurve *curve) {
+ using Geom::X;
+ using Geom::Y;
+ double projmatrix[3][3];
+ if(deform_type == DEFORMATION_PERSPECTIVE){
+ std::vector<Geom::Point> handles(4);
+ handles[0] = Down_Left_Point;
+ handles[1] = Up_Left_Point;
+ handles[2] = Up_Right_Point;
+ handles[3] = Down_Right_Point;
+ std::vector<Geom::Point> sourceHandles(4);
+ sourceHandles[0] = Geom::Point(boundingbox_X.min(), boundingbox_Y.max());
+ sourceHandles[1] = Geom::Point(boundingbox_X.min(), boundingbox_Y.min());
+ sourceHandles[2] = Geom::Point(boundingbox_X.max(), boundingbox_Y.min());
+ sourceHandles[3] = Geom::Point(boundingbox_X.max(), boundingbox_Y.max());
+ double solmatrix[8][8] = {{0}};
+ double free_term[8] = {0};
+ double gslSolmatrix[64];
+ for(unsigned int i = 0; i < 4; ++i){
+ solmatrix[i][0] = sourceHandles[i][X];
+ solmatrix[i][1] = sourceHandles[i][Y];
+ solmatrix[i][2] = 1;
+ solmatrix[i][6] = -handles[i][X] * sourceHandles[i][X];
+ solmatrix[i][7] = -handles[i][X] * sourceHandles[i][Y];
+ solmatrix[i+4][3] = sourceHandles[i][X];
+ solmatrix[i+4][4] = sourceHandles[i][Y];
+ solmatrix[i+4][5] = 1;
+ solmatrix[i+4][6] = -handles[i][Y] * sourceHandles[i][X];
+ solmatrix[i+4][7] = -handles[i][Y] * sourceHandles[i][Y];
+ free_term[i] = handles[i][X];
+ free_term[i+4] = handles[i][Y];
+ }
+ int h = 0;
+ for( int i = 0; i < 8; i++ ) {
+ for( int j = 0; j < 8; j++ ) {
+ gslSolmatrix[h] = solmatrix[i][j];
+ h++;
+ }
+ }
+ //this is get by this page:
+ //http://www.gnu.org/software/gsl/manual/html_node/Linear-Algebra-Examples.html#Linear-Algebra-Examples
+ gsl_matrix_view m = gsl_matrix_view_array (gslSolmatrix, 8, 8);
+ gsl_vector_view b = gsl_vector_view_array (free_term, 8);
+ gsl_vector *x = gsl_vector_alloc (8);
+ int s;
+ gsl_permutation * p = gsl_permutation_alloc (8);
+ gsl_linalg_LU_decomp (&m.matrix, p, &s);
+ gsl_linalg_LU_solve (&m.matrix, p, &b.vector, x);
+ h = 0;
+ for( int i = 0; i < 3; i++ ) {
+ for( int j = 0; j < 3; j++ ) {
+ if(h==8){
+ projmatrix[2][2] = 1.0;
+ continue;
+ }
+ projmatrix[i][j] = gsl_vector_get(x, h);
+ h++;
+ }
+ }
+ gsl_permutation_free (p);
+ gsl_vector_free (x);
+ }
+ Geom::PathVector const original_pathv = pathv_to_linear_and_cubic_beziers(curve->get_pathvector());
+ curve->reset();
+ Geom::CubicBezier const *cubic = NULL;
+ Geom::Point pointAt1(0, 0);
+ Geom::Point pointAt2(0, 0);
+ Geom::Point pointAt3(0, 0);
+ for (Geom::PathVector::const_iterator path_it = original_pathv.begin(); path_it != original_pathv.end(); ++path_it) {
+ //Si está vacío...
+ if (path_it->empty())
+ continue;
+ //Itreadores
+ SPCurve *nCurve = new SPCurve();
+ Geom::Path::const_iterator curve_it1 = path_it->begin();
+ Geom::Path::const_iterator curve_it2 = ++(path_it->begin());
+ Geom::Path::const_iterator curve_endit = path_it->end_default();
+
+ if (path_it->closed()) {
+ const Geom::Curve &closingline =
+ path_it->back_closed();
+ if (are_near(closingline.initialPoint(), closingline.finalPoint())) {
+ curve_endit = path_it->end_open();
+ }
+ }
+ if(deform_type == DEFORMATION_PERSPECTIVE){
+ nCurve->moveto(project_point(curve_it1->initialPoint(),projmatrix));
+ }else{
+ nCurve->moveto(project_point(curve_it1->initialPoint()));
+ }
+ while (curve_it1 != curve_endit) {
+ cubic = dynamic_cast<Geom::CubicBezier const *>(&*curve_it1);
+ if (cubic) {
+ pointAt1 = (*cubic)[1];
+ pointAt2 = (*cubic)[2];
+ } else {
+ pointAt1 = curve_it1->initialPoint();
+ pointAt2 = curve_it1->finalPoint();
+ }
+ pointAt3 = curve_it1->finalPoint();
+ if(deform_type == DEFORMATION_PERSPECTIVE){
+ pointAt1 = project_point(pointAt1,projmatrix);
+ pointAt2 = project_point(pointAt2,projmatrix);
+ pointAt3 = project_point(pointAt3,projmatrix);
+ }else{
+ pointAt1 = project_point(pointAt1);
+ pointAt2 = project_point(pointAt2);
+ pointAt3 = project_point(pointAt3);
+ }
+ nCurve->curveto(pointAt1, pointAt2, pointAt3);
+ ++curve_it1;
+ if(curve_it2 != curve_endit) {
+ ++curve_it2;
+ }
+ }
+ //y cerramos la curva
+ if (path_it->closed()) {
+ nCurve->move_endpoints(pointAt3, pointAt3);
+ nCurve->closepath_current();
+ }
+ curve->append(nCurve, false);
+ nCurve->reset();
+ delete nCurve;
+ }
+}
+
+Geom::Point
+LPEPerspectiveEnvelope::project_point(Geom::Point p){
+ double width = boundingbox_X.extent();
+ double height = boundingbox_Y.extent();
+ double delta_x = boundingbox_X.min() - p[X];
+ double delta_y = boundingbox_Y.max() - p[Y];
+ Geom::Coord xratio = (delta_x * -1) / width;
+ Geom::Coord yratio = delta_y / height;
+ Geom::Line* horiz = new Geom::Line();
+ Geom::Line* vert = new Geom::Line();
+ vert->setPoints (pointAtRatio(yratio,Down_Left_Point,Up_Left_Point),pointAtRatio(yratio,Down_Right_Point,Up_Right_Point));
+ horiz->setPoints (pointAtRatio(xratio,Down_Left_Point,Down_Right_Point),pointAtRatio(xratio,Up_Left_Point,Up_Right_Point));
+
+ OptCrossing crossPoint = intersection(*horiz,*vert);
+ if(crossPoint){
+ return horiz->pointAt(Geom::Coord(crossPoint->ta));
+ }else{
+ return p;
+ }
+}
+
+Geom::Point
+LPEPerspectiveEnvelope::project_point(Geom::Point p, double m[][3]){
+ Geom::Coord x = p[0];
+ Geom::Coord y = p[1];
+ return Geom::Point(
+ Geom::Coord((x*m[0][0] + y*m[0][1] + m[0][2])/(x*m[2][0]+y*m[2][1]+m[2][2])),
+ Geom::Coord((x*m[1][0] + y*m[1][1] + m[1][2])/(x*m[2][0]+y*m[2][1]+m[2][2])));
+}
+
+Geom::Point
+LPEPerspectiveEnvelope::pointAtRatio(Geom::Coord ratio,Geom::Point A, Geom::Point B){
+ Geom::Coord x = A[X] + (ratio * (B[X]-A[X]));
+ Geom::Coord y = A[Y]+ (ratio * (B[Y]-A[Y]));
+ return Point(x, y);
+}
+
+
+Gtk::Widget *
+LPEPerspectiveEnvelope::newWidget()
+{
+ // use manage here, because after deletion of Effect object, others might still be pointing to this widget.
+ Gtk::VBox * vbox = Gtk::manage( new Gtk::VBox(Effect::newWidget()) );
+
+ vbox->set_border_width(5);
+ vbox->set_homogeneous(false);
+ vbox->set_spacing(6);
+ std::vector<Parameter *>::iterator it = param_vector.begin();
+ Gtk::HBox * hboxUpHandles = Gtk::manage(new Gtk::HBox(false,0));
+ Gtk::HBox * hboxDownHandles = Gtk::manage(new Gtk::HBox(false,0));
+ while (it != param_vector.end()) {
+ if ((*it)->widget_is_visible) {
+ Parameter * param = *it;
+ Gtk::Widget * widg = dynamic_cast<Gtk::Widget *>(param->param_newWidget());
+ if (param->param_key == "Up_Left_Point" ||
+ param->param_key == "Up_Right_Point" ||
+ param->param_key == "Down_Left_Point" ||
+ param->param_key == "Down_Right_Point")
+ {
+ Gtk::HBox * pointParameter = dynamic_cast<Gtk::HBox *>(widg);
+ std::vector< Gtk::Widget* > childList = pointParameter->get_children();
+ Gtk::HBox * pointParameterHBox = dynamic_cast<Gtk::HBox *>(childList[0]);
+ std::vector< Gtk::Widget* > childList2 = pointParameterHBox->get_children();
+ pointParameterHBox->remove(childList2[0][0]);
+ Glib::ustring * tip = param->param_getTooltip();
+ if (widg) {
+ if(param->param_key == "Up_Left_Point"){
+ Gtk::Label* handles = Gtk::manage(new Gtk::Label(Glib::ustring(_("Handles:")),Gtk::ALIGN_START));
+ vbox->pack_start(*handles, false, false, 2);
+ hboxUpHandles->pack_start(*widg, true, true, 2);
+ hboxUpHandles->pack_start(*Gtk::manage(new Gtk::VSeparator()), Gtk::PACK_EXPAND_WIDGET);
+ }else if(param->param_key == "Up_Right_Point"){
+ hboxUpHandles->pack_start(*widg, true, true, 2);
+ }else if(param->param_key == "Down_Left_Point"){
+ hboxDownHandles->pack_start(*widg, true, true, 2);
+ hboxDownHandles->pack_start(*Gtk::manage(new Gtk::VSeparator()), Gtk::PACK_EXPAND_WIDGET);
+ }else{
+ hboxDownHandles->pack_start(*widg, true, true, 2);
+ }
+ if (tip) {
+ widg->set_tooltip_text(*tip);
+ } else {
+ widg->set_tooltip_text("");
+ widg->set_has_tooltip(false);
+ }
+ }
+ }else{
+ Glib::ustring * tip = param->param_getTooltip();
+ if (widg) {
+ vbox->pack_start(*widg, true, true, 2);
+ if (tip) {
+ widg->set_tooltip_text(*tip);
+ } else {
+ widg->set_tooltip_text("");
+ widg->set_has_tooltip(false);
+ }
+ }
+ }
+ }
+
+ ++it;
+ }
+ vbox->pack_start(*hboxUpHandles,true, true, 2);
+ Gtk::HBox * hboxMiddle = Gtk::manage(new Gtk::HBox(true,2));
+ hboxMiddle->pack_start(*Gtk::manage(new Gtk::HSeparator()), Gtk::PACK_EXPAND_WIDGET);
+ hboxMiddle->pack_start(*Gtk::manage(new Gtk::HSeparator()), Gtk::PACK_EXPAND_WIDGET);
+ vbox->pack_start(*hboxMiddle, false, true, 2);
+ vbox->pack_start(*hboxDownHandles, true, true, 2);
+ Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox(false,0));
+ Gtk::Button* resetButton = Gtk::manage(new Gtk::Button(Gtk::Stock::CLEAR));
+ resetButton->signal_clicked().connect(sigc::mem_fun (*this,&LPEPerspectiveEnvelope::resetGrid));
+ resetButton->set_size_request(140,45);
+ vbox->pack_start(*hbox, true,true,2);
+ hbox->pack_start(*resetButton, false, false,2);
+ return dynamic_cast<Gtk::Widget *>(vbox);
+}
+
+void
+LPEPerspectiveEnvelope::doBeforeEffect (SPLPEItem const* lpeitem)
+{
+ original_bbox(lpeitem);
+ SPLPEItem * item = const_cast<SPLPEItem*>(lpeitem);
+ item->apply_to_clippath(item);
+ item->apply_to_mask(item);
+ setDefaults();
+}
+
+void
+LPEPerspectiveEnvelope::setDefaults()
+{
+ Geom::Point Up_Left(boundingbox_X.min(), boundingbox_Y.min());
+ Geom::Point Up_Right(boundingbox_X.max(), boundingbox_Y.min());
+ Geom::Point Down_Left(boundingbox_X.min(), boundingbox_Y.max());
+ Geom::Point Down_Right(boundingbox_X.max(), boundingbox_Y.max());
+
+ Up_Left_Point.param_update_default(Up_Left);
+ Up_Right_Point.param_update_default(Up_Right);
+ Down_Right_Point.param_update_default(Down_Right);
+ Down_Left_Point.param_update_default(Down_Left);
+}
+
+void
+LPEPerspectiveEnvelope::resetGrid()
+{
+ Up_Left_Point.param_set_and_write_default();
+ Up_Right_Point.param_set_and_write_default();
+ Down_Right_Point.param_set_and_write_default();
+ Down_Left_Point.param_set_and_write_default();
+ //todo:this hack is only to reposition the knots on reser grid button
+ //Better update path effect in LPEITEM
+ SPDesktop * desktop = SP_ACTIVE_DESKTOP;
+ tools_switch(desktop, TOOLS_SELECT);
+ tools_switch(desktop, TOOLS_NODES);
+}
+
+void
+LPEPerspectiveEnvelope::resetDefaults(SPItem const* item)
+{
+ Effect::resetDefaults(item);
+ original_bbox(SP_LPE_ITEM(item));
+ setDefaults();
+ resetGrid();
+}
+
+void
+LPEPerspectiveEnvelope::addCanvasIndicators(SPLPEItem const */*lpeitem*/, std::vector<Geom::PathVector> &hp_vec)
+{
+ hp_vec.clear();
+
+ SPCurve *c = new SPCurve();
+ c->reset();
+ c->moveto(Up_Left_Point);
+ c->lineto(Up_Right_Point);
+ c->lineto(Down_Right_Point);
+ c->lineto(Down_Left_Point);
+ c->lineto(Up_Left_Point);
+ hp_vec.push_back(c->get_pathvector());
+}
+
+
+/* ######################## */
+
+} //namespace LivePathEffect
+} /* namespace Inkscape */
+
+
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: file_type=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/live_effects/lpe-perspective-envelope.h b/src/live_effects/lpe-perspective-envelope.h
new file mode 100644
index 000000000..2f253882e
--- /dev/null
+++ b/src/live_effects/lpe-perspective-envelope.h
@@ -0,0 +1,70 @@
+#ifndef INKSCAPE_LPE_PERSPECTIVE_ENVELOPE_H
+#define INKSCAPE_LPE_PERSPECTIVE_ENVELOPE_H
+
+/** \file
+ * LPE <perspective-envelope> implementation , see lpe-perspective-envelope.cpp.
+
+ */
+/*
+ * Authors:
+ * Jabiertxof Code migration from python extensions envelope and perspective
+ * Aaron Spike, aaron@ekips.org from envelope and perspective phyton code
+ * Dmitry Platonov, shadowjack@mail.ru, 2006 perspective approach & math
+ * Jose Hevia (freon) Transform algorithm from envelope
+ *
+ * Copyright (C) 2007-2014 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "live_effects/parameter/enum.h"
+#include "live_effects/effect.h"
+#include "live_effects/parameter/pointreseteable.h"
+#include "live_effects/lpegroupbbox.h"
+
+namespace Inkscape {
+namespace LivePathEffect {
+
+class LPEPerspectiveEnvelope : public Effect, GroupBBoxEffect {
+public:
+
+ LPEPerspectiveEnvelope(LivePathEffectObject *lpeobject);
+
+ virtual ~LPEPerspectiveEnvelope();
+
+ virtual void doEffect(SPCurve *curve);
+
+ virtual Geom::Point project_point(Geom::Point p);
+
+ virtual Geom::Point project_point(Geom::Point p, double m[][3]);
+
+ virtual Geom::Point pointAtRatio(Geom::Coord ratio,Geom::Point A, Geom::Point B);
+
+ virtual void resetDefaults(SPItem const* item);
+
+ virtual void doBeforeEffect(SPLPEItem const* lpeitem);
+
+ virtual Gtk::Widget * newWidget();
+
+ virtual void setDefaults();
+
+ virtual void resetGrid();
+
+protected:
+ void addCanvasIndicators(SPLPEItem const */*lpeitem*/, std::vector<Geom::PathVector> &hp_vec);
+private:
+
+ EnumParam<unsigned> deform_type;
+ PointReseteableParam Up_Left_Point;
+ PointReseteableParam Up_Right_Point;
+ PointReseteableParam Down_Left_Point;
+ PointReseteableParam Down_Right_Point;
+
+ LPEPerspectiveEnvelope(const LPEPerspectiveEnvelope&);
+ LPEPerspectiveEnvelope& operator=(const LPEPerspectiveEnvelope&);
+};
+
+} //namespace LivePathEffect
+} //namespace Inkscape
+
+#endif
diff --git a/src/live_effects/lpe-perspective_path.cpp b/src/live_effects/lpe-perspective_path.cpp
index c255f8665..901519b4f 100644
--- a/src/live_effects/lpe-perspective_path.cpp
+++ b/src/live_effects/lpe-perspective_path.cpp
@@ -10,18 +10,20 @@
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-
+#include <gtkmm.h>
#include <glibmm/i18n.h>
#include "persp3d.h"
//#include "transf_mat_3x4.h"
#include "document.h"
-
+#include "document-private.h"
#include "live_effects/lpe-perspective_path.h"
+#include "live_effects/lpeobject.h"
#include "sp-item-group.h"
#include "knot-holder-entity.h"
#include "knotholder.h"
-
+#include "desktop.h"
+#include <util/units.h>
#include "inkscape.h"
#include <2geom/path.h>
@@ -41,6 +43,9 @@ public:
} // namespace PP
+static Glib::ustring perspectiveID = _("First perspective");
+
+
LPEPerspectivePath::LPEPerspectivePath(LivePathEffectObject *lpeobject) :
Effect(lpeobject),
// initialise your parameters here:
@@ -59,23 +64,84 @@ LPEPerspectivePath::LPEPerspectivePath(LivePathEffectObject *lpeobject) :
concatenate_before_pwd2 = true; // don't split the path into its subpaths
_provides_knotholder_entities = true;
-
- Persp3D *persp = persp3d_document_first_persp(inkscape_active_document());
- Proj::TransfMat3x4 pmat = persp->perspective_impl->tmat;
- pmat.copy_tmat(tmat);
}
LPEPerspectivePath::~LPEPerspectivePath()
{
}
-
+void
+LPEPerspectivePath::doOnApply(SPLPEItem const* lpeitem)
+{
+ Persp3D *persp = persp3d_document_first_persp(lpeitem->document);
+ if(persp == 0 ){
+ char *msg = _("You need a BOX 3D object");
+ Gtk::MessageDialog dialog(msg, false, Gtk::MESSAGE_INFO,
+ Gtk::BUTTONS_OK, true);
+ dialog.run();
+ SPLPEItem * item = const_cast<SPLPEItem*>(lpeitem);
+ item->removeCurrentPathEffect(false);
+ }
+}
void
LPEPerspectivePath::doBeforeEffect (SPLPEItem const* lpeitem)
{
original_bbox(lpeitem, true);
+ SPLPEItem * item = const_cast<SPLPEItem*>(lpeitem);
+ Persp3D *persp = persp3d_document_first_persp(lpeitem->document);
+ if(persp == 0 ){
+ char *msg = _("You need a BOX 3D object");
+ Gtk::MessageDialog dialog(msg, false, Gtk::MESSAGE_INFO,
+ Gtk::BUTTONS_OK, true);
+ dialog.run();
+ return;
+ }
+ Proj::TransfMat3x4 pmat = persp->perspective_impl->tmat;
+ Geom::Affine doc2d = Geom::Scale(1, -1) * Geom::Translate(0, item->document->getHeight().value("px"));
+ pmat = pmat * doc2d;
+ pmat.copy_tmat(tmat);
+ item->apply_to_clippath(item);
+ item->apply_to_mask(item);
}
+void LPEPerspectivePath::refresh(Gtk::Entry* perspective) {
+ perspectiveID = perspective->get_text();
+ Persp3D *first = 0;
+ Persp3D *persp = 0;
+ for ( SPObject *child = this->lpeobj->document->getDefs()->firstChild(); child && !persp; child = child->getNext() ) {
+ if (SP_IS_PERSP3D(child) && first == 0) {
+ first = SP_PERSP3D(child);
+ }
+ if (SP_IS_PERSP3D(child) && strcmp(child->getId(), const_cast<const gchar *>(perspectiveID.c_str())) == 0) {
+ persp = SP_PERSP3D(child);
+ break;
+ }
+ }
+ if(first == 0 ){
+ char *msg = _("You need a BOX 3D object");
+ Gtk::MessageDialog dialog(msg, false, Gtk::MESSAGE_INFO,
+ Gtk::BUTTONS_OK, true);
+ dialog.run();
+ return;
+ }
+ if(persp == 0){
+ persp = first;
+ char *msg = _("First perspective selected");
+ Gtk::MessageDialog dialog(msg, false, Gtk::MESSAGE_INFO,
+ Gtk::BUTTONS_OK, true);
+ dialog.run();
+ perspectiveID = _("First perspective");
+ }else{
+ char *msg = _("Perspective changed");
+ Gtk::MessageDialog dialog(msg, false, Gtk::MESSAGE_INFO,
+ Gtk::BUTTONS_OK, true);
+ dialog.run();
+ }
+ Proj::TransfMat3x4 pmat = persp->perspective_impl->tmat;
+ pmat = pmat * SP_ACTIVE_DESKTOP->doc2dt();
+ pmat.copy_tmat(tmat);
+};
+
Geom::Piecewise<Geom::D2<Geom::SBasis> >
LPEPerspectivePath::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_in)
{
@@ -91,7 +157,7 @@ LPEPerspectivePath::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > cons
Piecewise<SBasis> preimage[4];
//Geom::Point orig = Geom::Point(bounds_X.min(), bounds_Y.middle());
- //orig = Geom::Point(orig[X], sp_document_height(inkscape_active_document()) - orig[Y]);
+ //orig = Geom::Point(orig[X], sp_document_height(this->lpeobj->document) - orig[Y]);
//double offset = uses_plane_xy ? boundingbox_X.extent() : 0.0;
@@ -139,6 +205,49 @@ LPEPerspectivePath::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > cons
return output;
}
+Gtk::Widget *
+LPEPerspectivePath::newWidget()
+{
+ // use manage here, because after deletion of Effect object, others might still be pointing to this widget.
+ Gtk::VBox * vbox = Gtk::manage( new Gtk::VBox(Effect::newWidget()) );
+
+ vbox->set_border_width(5);
+ std::vector<Parameter *>::iterator it = param_vector.begin();
+ while (it != param_vector.end()) {
+ if ((*it)->widget_is_visible) {
+ Parameter * param = *it;
+ Gtk::Widget * widg = dynamic_cast<Gtk::Widget *>(param->param_newWidget());
+ Glib::ustring * tip = param->param_getTooltip();
+ if (widg) {
+ vbox->pack_start(*widg, true, true, 2);
+ if (tip) {
+ widg->set_tooltip_text(*tip);
+ } else {
+ widg->set_tooltip_text("");
+ widg->set_has_tooltip(false);
+ }
+ }
+ }
+
+ ++it;
+ }
+ Gtk::HBox * perspectiveId = Gtk::manage(new Gtk::HBox(true,0));
+ Gtk::Label* labelPerspective = Gtk::manage(new Gtk::Label("Perspective ID:", 0., 0.));
+ Gtk::Entry* perspective = Gtk::manage(new Gtk::Entry());
+ perspective->set_text(perspectiveID);
+ perspective->set_tooltip_text("Set the perspective ID to apply");
+ perspectiveId->pack_start(*labelPerspective, true, true, 2);
+ perspectiveId->pack_start(*perspective, true, true, 2);
+ vbox->pack_start(*perspectiveId, true, true, 2);
+ Gtk::Button* apply3D = Gtk::manage(new Gtk::Button(Glib::ustring(_("Refresh perspective"))));
+ apply3D->set_alignment(0.0, 0.5);
+ apply3D->signal_clicked().connect(sigc::bind<Gtk::Entry*>(sigc::mem_fun(*this,&LPEPerspectivePath::refresh),perspective));
+ Gtk::Widget* apply3DWidget = dynamic_cast<Gtk::Widget *>(apply3D);
+ apply3DWidget->set_tooltip_text("Refresh perspective");
+ vbox->pack_start(*apply3DWidget, true, true,2);
+ return dynamic_cast<Gtk::Widget *>(vbox);
+}
+
void LPEPerspectivePath::addKnotHolderEntities(KnotHolder *knotholder, SPDesktop *desktop, SPItem *item) {
KnotHolderEntity *e = new PP::KnotHolderEntityOffset(this);
e->create( desktop, item, knotholder, Inkscape::CTRL_TYPE_UNKNOWN,
diff --git a/src/live_effects/lpe-perspective_path.h b/src/live_effects/lpe-perspective_path.h
index a9ee004f9..c4ddf1853 100644
--- a/src/live_effects/lpe-perspective_path.h
+++ b/src/live_effects/lpe-perspective_path.h
@@ -33,11 +33,12 @@ class LPEPerspectivePath : public Effect, GroupBBoxEffect {
public:
LPEPerspectivePath(LivePathEffectObject *lpeobject);
virtual ~LPEPerspectivePath();
-
virtual void doBeforeEffect (SPLPEItem const* lpeitem);
-
+ virtual void doOnApply(SPLPEItem const* lpeitem);
virtual Geom::Piecewise<Geom::D2<Geom::SBasis> > doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_in);
+ virtual void refresh(Gtk::Entry* perspective);
+ virtual Gtk::Widget * newWidget();
/* the knotholder entity classes must be declared friends */
friend class PP::KnotHolderEntityOffset;
void addKnotHolderEntities(KnotHolder *knotholder, SPDesktop *desktop, SPItem *item);
@@ -51,7 +52,6 @@ private:
ScalarParam offsety;
BoolParam uses_plane_xy;
// there are all kinds of parameters. Check the /live_effects/parameter directory which types exist!
-
Geom::Point orig;
LPEPerspectivePath(const LPEPerspectivePath&);
diff --git a/src/live_effects/lpe-powerstroke-interpolators.h b/src/live_effects/lpe-powerstroke-interpolators.h
index 6f5b75af8..e3ab37e27 100644
--- a/src/live_effects/lpe-powerstroke-interpolators.h
+++ b/src/live_effects/lpe-powerstroke-interpolators.h
@@ -27,7 +27,9 @@ enum InterpolatorType {
INTERP_LINEAR,
INTERP_CUBICBEZIER,
INTERP_CUBICBEZIER_JOHAN,
- INTERP_SPIRO
+ INTERP_SPIRO,
+ INTERP_CUBICBEZIER_SMOOTH,
+ INTERP_CENTRIPETAL_CATMULLROM
};
class Interpolator {
@@ -133,6 +135,43 @@ private:
CubicBezierJohan& operator=(const CubicBezierJohan&);
};
+/// @todo invent name for this class
+class CubicBezierSmooth : public Interpolator {
+public:
+ CubicBezierSmooth(double beta = 0.2) {
+ _beta = beta;
+ };
+ virtual ~CubicBezierSmooth() {};
+
+ virtual Path interpolateToPath(std::vector<Point> const &points) const {
+ Path fit;
+ fit.start(points.at(0));
+ unsigned int num_points = points.size();
+ for (unsigned int i = 1; i < num_points; ++i) {
+ Point p0 = points.at(i-1);
+ Point p1 = points.at(i);
+ Point dx = Point(p1[X] - p0[X], 0);
+ if (i == 1) {
+ fit.appendNew<CubicBezier>(p0, p1-0.75*dx, p1);
+ } else if (i == points.size() - 1) {
+ fit.appendNew<CubicBezier>(p0+0.75*dx, p1, p1);
+ } else {
+ fit.appendNew<CubicBezier>(p0+_beta*dx, p1-_beta*dx, p1);
+ }
+ }
+ return fit;
+ };
+
+ void setBeta(double beta) {
+ _beta = beta;
+ }
+
+ double _beta;
+
+private:
+ CubicBezierSmooth(const CubicBezierSmooth&);
+ CubicBezierSmooth& operator=(const CubicBezierSmooth&);
+};
class SpiroInterpolator : public Interpolator {
public:
@@ -167,8 +206,88 @@ private:
SpiroInterpolator& operator=(const SpiroInterpolator&);
};
+// Quick mockup for testing the behavior for powerstroke controlpoint interpolation
+class CentripetalCatmullRomInterpolator : public Interpolator {
+public:
+ CentripetalCatmullRomInterpolator() {};
+ virtual ~CentripetalCatmullRomInterpolator() {};
+
+ virtual Path interpolateToPath(std::vector<Point> const &points) const {
+ unsigned int n_points = points.size();
+
+ Geom::Path fit(points.front());
+
+ if (n_points < 3) return fit; // TODO special cases for 0,1 and 2 input points
+
+ // return n_points-1 cubic segments
+
+ // duplicate first point
+ fit.append(calc_bezier(points[0],points[0],points[1],points[2]));
+
+ for (std::size_t i = 0; i < n_points-2; ++i) {
+ Point p0 = points[i];
+ Point p1 = points[i+1];
+ Point p2 = points[i+2];
+ Point p3 = (i < n_points-3) ? points[i+3] : points[i+2];
+
+ fit.append(calc_bezier(p0, p1, p2, p3));
+ }
+
+ return fit;
+ };
+
+private:
+ CubicBezier calc_bezier(Point p0, Point p1, Point p2, Point p3) const {
+ // create interpolating bezier between p1 and p2
+
+ // Part of the code comes from StackOverflow user eriatarka84
+ // http://stackoverflow.com/a/23980479/2929337
+
+ // calculate time coords (deltas) of points
+ // the factor 0.25 can be generalized for other Catmull-Rom interpolation types
+ // see alpha in Yuksel et al. "On the Parameterization of Catmull-Rom Curves",
+ // --> http://www.cemyuksel.com/research/catmullrom_param/catmullrom.pdf
+ double dt0 = powf(distanceSq(p0, p1), 0.25);
+ double dt1 = powf(distanceSq(p1, p2), 0.25);
+ double dt2 = powf(distanceSq(p2, p3), 0.25);
+
+
+ // safety check for repeated points
+ double eps = Geom::EPSILON;
+ if (dt1 < eps)
+ dt1 = 1.0;
+ if (dt0 < eps)
+ dt0 = dt1;
+ if (dt2 < eps)
+ dt2 = dt1;
+
+ // compute tangents when parameterized in [t1,t2]
+ Point tan1 = (p1 - p0) / dt0 - (p2 - p0) / (dt0 + dt1) + (p2 - p1) / dt1;
+ Point tan2 = (p2 - p1) / dt1 - (p3 - p1) / (dt1 + dt2) + (p3 - p2) / dt2;
+ // rescale tangents for parametrization in [0,1]
+ tan1 *= dt1;
+ tan2 *= dt1;
+
+ // create bezier from tangents (this is already in 2geom somewhere, or should be moved to it)
+ // the tangent of a bezier curve is: B'(t) = 3(1-t)^2 (b1 - b0) + 6(1-t)t(b2-b1) + 3t^2(b3-b2)
+ // So we have to make sure that B'(0) = tan1 and B'(1) = tan2, and we already know that b0=p1 and b3=p2
+ // tan1 = B'(0) = 3 (b1 - p1) --> p1 + (tan1)/3 = b1
+ // tan2 = B'(1) = 3 (p2 - b2) --> p2 - (tan2)/3 = b2
+
+ Point b0 = p1;
+ Point b1 = p1 + tan1 / 3;
+ Point b2 = p2 - tan2 / 3;
+ Point b3 = p2;
+
+ return CubicBezier(b0, b1, b2, b3);
+ }
+
+ CentripetalCatmullRomInterpolator(const CentripetalCatmullRomInterpolator&);
+ CentripetalCatmullRomInterpolator& operator=(const CentripetalCatmullRomInterpolator&);
+};
+
-Interpolator*
+inline Interpolator*
Interpolator::create(InterpolatorType type) {
switch (type) {
case INTERP_LINEAR:
@@ -179,6 +298,10 @@ Interpolator::create(InterpolatorType type) {
return new Geom::Interpolate::CubicBezierJohan();
case INTERP_SPIRO:
return new Geom::Interpolate::SpiroInterpolator();
+ case INTERP_CUBICBEZIER_SMOOTH:
+ return new Geom::Interpolate::CubicBezierSmooth();
+ case INTERP_CENTRIPETAL_CATMULLROM:
+ return new Geom::Interpolate::CentripetalCatmullRomInterpolator();
default:
return new Geom::Interpolate::Linear();
}
diff --git a/src/live_effects/lpe-powerstroke.cpp b/src/live_effects/lpe-powerstroke.cpp
index 90b01aaa4..f7fe9592d 100644
--- a/src/live_effects/lpe-powerstroke.cpp
+++ b/src/live_effects/lpe-powerstroke.cpp
@@ -15,6 +15,11 @@
#include "sp-shape.h"
#include "style.h"
+#include "xml/repr.h"
+#include "sp-paint-server.h"
+#include "svg/svg-color.h"
+#include "desktop-style.h"
+#include "svg/css-ostringstream.h"
#include "display/curve.h"
#include <2geom/path.h>
@@ -185,10 +190,12 @@ namespace Inkscape {
namespace LivePathEffect {
static const Util::EnumData<unsigned> InterpolatorTypeData[] = {
+ {Geom::Interpolate::INTERP_CUBICBEZIER_SMOOTH, N_("CubicBezierSmooth"), "CubicBezierSmooth"},
{Geom::Interpolate::INTERP_LINEAR , N_("Linear"), "Linear"},
{Geom::Interpolate::INTERP_CUBICBEZIER , N_("CubicBezierFit"), "CubicBezierFit"},
{Geom::Interpolate::INTERP_CUBICBEZIER_JOHAN , N_("CubicBezierJohan"), "CubicBezierJohan"},
- {Geom::Interpolate::INTERP_SPIRO , N_("SpiroInterpolator"), "SpiroInterpolator"}
+ {Geom::Interpolate::INTERP_SPIRO , N_("SpiroInterpolator"), "SpiroInterpolator"},
+ {Geom::Interpolate::INTERP_CENTRIPETAL_CATMULLROM, N_("Centripetal Catmull-Rom"), "CentripetalCatmullRom"}
};
static const Util::EnumDataConverter<unsigned> InterpolatorTypeConverter(InterpolatorTypeData, sizeof(InterpolatorTypeData)/sizeof(*InterpolatorTypeData));
@@ -219,12 +226,10 @@ enum LineJoinType {
static const Util::EnumData<unsigned> LineJoinTypeData[] = {
{LINEJOIN_BEVEL, N_("Beveled"), "bevel"},
{LINEJOIN_ROUND, N_("Rounded"), "round"},
- {LINEJOIN_EXTRP_MITER, N_("Extrapolated"), "extrapolated"},
+// {LINEJOIN_EXTRP_MITER, N_("Extrapolated"), "extrapolated"}, // disabled because doesn't work well
+ {LINEJOIN_EXTRP_MITER_ARC, N_("Extrapolated arc"), "extrp_arc"},
{LINEJOIN_MITER, N_("Miter"), "miter"},
{LINEJOIN_SPIRO, N_("Spiro"), "spiro"},
-#ifdef LPE_ENABLE_TEST_EFFECTS
- {LINEJOIN_EXTRP_MITER_ARC, N_("Extrapolated arc"), "extrp_arc"},
-#endif
};
static const Util::EnumDataConverter<unsigned> LineJoinTypeConverter(LineJoinTypeData, sizeof(LineJoinTypeData)/sizeof(*LineJoinTypeData));
@@ -232,12 +237,12 @@ LPEPowerStroke::LPEPowerStroke(LivePathEffectObject *lpeobject) :
Effect(lpeobject),
offset_points(_("Offset points"), _("Offset points"), "offset_points", &wr, this),
sort_points(_("Sort points"), _("Sort offset points according to their time value along the curve"), "sort_points", &wr, this, true),
- interpolator_type(_("Interpolator type:"), _("Determines which kind of interpolator will be used to interpolate between stroke width along the path"), "interpolator_type", InterpolatorTypeConverter, &wr, this, Geom::Interpolate::INTERP_CUBICBEZIER_JOHAN),
+ interpolator_type(_("Interpolator type:"), _("Determines which kind of interpolator will be used to interpolate between stroke width along the path"), "interpolator_type", InterpolatorTypeConverter, &wr, this, Geom::Interpolate::INTERP_CUBICBEZIER),
interpolator_beta(_("Smoothness:"), _("Sets the smoothness for the CubicBezierJohan interpolator; 0 = linear interpolation, 1 = smooth"), "interpolator_beta", &wr, this, 0.2),
- start_linecap_type(_("Start cap:"), _("Determines the shape of the path's start"), "start_linecap_type", LineCapTypeConverter, &wr, this, LINECAP_ROUND),
- linejoin_type(_("Join:"), _("Determines the shape of the path's corners"), "linejoin_type", LineJoinTypeConverter, &wr, this, LINEJOIN_ROUND),
+ start_linecap_type(_("Start cap:"), _("Determines the shape of the path's start"), "start_linecap_type", LineCapTypeConverter, &wr, this, LINECAP_BUTT),
+ linejoin_type(_("Join:"), _("Determines the shape of the path's corners"), "linejoin_type", LineJoinTypeConverter, &wr, this, LINEJOIN_EXTRP_MITER_ARC),
miter_limit(_("Miter limit:"), _("Maximum length of the miter (in units of stroke width)"), "miter_limit", &wr, this, 4.),
- end_linecap_type(_("End cap:"), _("Determines the shape of the path's end"), "end_linecap_type", LineCapTypeConverter, &wr, this, LINECAP_ROUND)
+ end_linecap_type(_("End cap:"), _("Determines the shape of the path's end"), "end_linecap_type", LineCapTypeConverter, &wr, this, LINECAP_BUTT)
{
show_orig_path = true;
@@ -266,20 +271,52 @@ void
LPEPowerStroke::doOnApply(SPLPEItem const* lpeitem)
{
if (SP_IS_SHAPE(lpeitem)) {
+ SPLPEItem* item = const_cast<SPLPEItem*>(lpeitem);
std::vector<Geom::Point> points;
Geom::PathVector const &pathv = SP_SHAPE(lpeitem)->_curve->get_pathvector();
- double width = (lpeitem && lpeitem->style) ? lpeitem->style->stroke_width.computed : 1.;
+ double width = (lpeitem && lpeitem->style) ? lpeitem->style->stroke_width.computed / 2 : 1.;
+
+ SPCSSAttr *css = sp_repr_css_attr_new ();
+ if (lpeitem->style) {
+ if (lpeitem->style->stroke.isPaintserver()) {
+ SPPaintServer * server = lpeitem->style->getStrokePaintServer();
+ if (server) {
+ Glib::ustring str;
+ str += "url(#";
+ str += server->getId();
+ str += ")";
+ sp_repr_css_set_property (css, "fill", str.c_str());
+ }
+ } else if (lpeitem->style->stroke.isColor()) {
+ gchar c[64];
+ sp_svg_write_color (c, sizeof(c), lpeitem->style->stroke.value.color.toRGBA32(SP_SCALE24_TO_FLOAT(lpeitem->style->stroke_opacity.value)));
+ sp_repr_css_set_property (css, "fill", c);
+ } else {
+ sp_repr_css_set_property (css, "fill", "none");
+ }
+ } else {
+ sp_repr_css_unset_property (css, "fill");
+ }
+
+ sp_repr_css_set_property(css, "stroke", "none");
+
+ sp_desktop_apply_css_recursive(item, css, true);
+ sp_repr_css_attr_unref (css);
+
+ item->updateRepr();
if (pathv.empty()) {
- points.push_back( Geom::Point(0.,width) );
+ points.push_back( Geom::Point(0.2,width) );
points.push_back( Geom::Point(0.5,width) );
- points.push_back( Geom::Point(1.,width) );
+ points.push_back( Geom::Point(0.8,width) );
} else {
Geom::Path const &path = pathv.front();
Geom::Path::size_type const size = path.size_default();
- points.push_back( Geom::Point(0.,width) );
+ if (!path.closed()) {
+ points.push_back( Geom::Point(0.2,width) );
+ }
points.push_back( Geom::Point(0.5*size,width) );
if (!path.closed()) {
- points.push_back( Geom::Point(size,width) );
+ points.push_back( Geom::Point(size - 0.2,width) );
}
}
offset_points.param_set_and_write_new_value(points);
@@ -288,6 +325,45 @@ LPEPowerStroke::doOnApply(SPLPEItem const* lpeitem)
}
}
+void LPEPowerStroke::doOnRemove(SPLPEItem const* lpeitem)
+{
+ if (SP_IS_SHAPE(lpeitem)) {
+ SPLPEItem *item = const_cast<SPLPEItem*>(lpeitem);
+ SPCSSAttr *css = sp_repr_css_attr_new ();
+ if (true) {
+ if (lpeitem->style->fill.isPaintserver()) {
+ SPPaintServer * server = lpeitem->style->getFillPaintServer();
+ if (server) {
+ Glib::ustring str;
+ str += "url(#";
+ str += server->getId();
+ str += ")";
+ sp_repr_css_set_property (css, "stroke", str.c_str());
+ }
+ } else if (lpeitem->style->fill.isColor()) {
+ gchar c[64];
+ sp_svg_write_color (c, sizeof(c), lpeitem->style->stroke.value.color.toRGBA32(SP_SCALE24_TO_FLOAT(lpeitem->style->stroke_opacity.value)));
+ sp_repr_css_set_property (css, "stroke", c);
+ } else {
+ sp_repr_css_set_property (css, "stroke", "none");
+ }
+ } else {
+ sp_repr_css_unset_property (css, "stroke");
+ }
+
+ Inkscape::CSSOStringStream os;
+ os << offset_points.median_width() * 2;
+ sp_repr_css_set_property (css, "stroke-width", os.str().c_str());
+
+ sp_repr_css_set_property(css, "fill", "none");
+
+ sp_desktop_apply_css_recursive(item, css, true);
+ sp_repr_css_attr_unref (css);
+
+ item->updateRepr();
+ }
+}
+
void
LPEPowerStroke::adjustForNewPath(std::vector<Geom::Path> const & path_in)
{
@@ -406,8 +482,9 @@ static Geom::Path path_from_piecewise_fix_cusps( Geom::Piecewise<Geom::D2<Geom::
break;
}
case LINEJOIN_EXTRP_MITER_ARC: {
- Geom::Circle circle1 = Geom::touching_circle(reverse(B[prev_i]),0.);
- Geom::Circle circle2 = Geom::touching_circle(B[i],0.);
+ // Extrapolate using the curvature at the end of the path segments to join
+ Geom::Circle circle1 = Geom::touching_circle(reverse(B[prev_i]), 0.0);
+ Geom::Circle circle2 = Geom::touching_circle(B[i], 0.0);
Geom::Point points[2];
int solutions = circle_circle_intersection(circle1, circle2, points[0], points[1]);
if (solutions == 2) {
@@ -582,14 +659,29 @@ LPEPowerStroke::doEffect_path (std::vector<Geom::Path> const & path_in)
ts.push_back( Point( pwd2_in.domain().max(),
(end_linecap==LINECAP_ZERO_WIDTH) ? 0. : ts.back()[Geom::Y]) );
}
+
+ // do the interpolation in a coordinate system that is more alike to the on-canvas knots,
+ // instead of the heavily compressed coordinate system of (segment_no offset, Y) in which the knots are stored
+ double pwd2_in_arclength = length(pwd2_in);
+ double xcoord_scaling = pwd2_in_arclength / ts.back()[Geom::X];
+ for (std::size_t i = 0, e = ts.size(); i < e; ++i) {
+ ts[i][Geom::X] *= xcoord_scaling;
+ }
+
// create stroke path where points (x,y) := (t, offset)
Geom::Interpolate::Interpolator *interpolator = Geom::Interpolate::Interpolator::create(static_cast<Geom::Interpolate::InterpolatorType>(interpolator_type.get_value()));
if (Geom::Interpolate::CubicBezierJohan *johan = dynamic_cast<Geom::Interpolate::CubicBezierJohan*>(interpolator)) {
johan->setBeta(interpolator_beta);
}
+ if (Geom::Interpolate::CubicBezierSmooth *smooth = dynamic_cast<Geom::Interpolate::CubicBezierSmooth*>(interpolator)) {
+ smooth->setBeta(interpolator_beta);
+ }
Geom::Path strokepath = interpolator->interpolateToPath(ts);
delete interpolator;
+ // apply the inverse knot-xcoord scaling that was applied before the interpolation
+ strokepath *= Scale(1/xcoord_scaling, 1);
+
D2<Piecewise<SBasis> > patternd2 = make_cuts_independent(strokepath.toPwSb());
Piecewise<SBasis> x = Piecewise<SBasis>(patternd2[0]);
Piecewise<SBasis> y = Piecewise<SBasis>(patternd2[1]);
diff --git a/src/live_effects/lpe-powerstroke.h b/src/live_effects/lpe-powerstroke.h
index 7bc736820..a773434aa 100644
--- a/src/live_effects/lpe-powerstroke.h
+++ b/src/live_effects/lpe-powerstroke.h
@@ -25,9 +25,11 @@ public:
LPEPowerStroke(LivePathEffectObject *lpeobject);
virtual ~LPEPowerStroke();
+
virtual std::vector<Geom::Path> doEffect_path (std::vector<Geom::Path> const & path_in);
virtual void doOnApply(SPLPEItem const* lpeitem);
+ virtual void doOnRemove(SPLPEItem const* lpeitem);
// methods called by path-manipulator upon edits
void adjustForNewPath(std::vector<Geom::Path> const & path_in);
diff --git a/src/live_effects/lpe-roughen.cpp b/src/live_effects/lpe-roughen.cpp
new file mode 100644
index 000000000..07d9e63e8
--- /dev/null
+++ b/src/live_effects/lpe-roughen.cpp
@@ -0,0 +1,358 @@
+/**
+ * @file
+ * Roughen LPE implementation. Creates roughen paths.
+ */
+/* Authors:
+ * Jabier Arraiza Cenoz <jabier.arraiza@marker.es>
+ *
+ * Thanks to all people involved specialy to Josh Andler for the idea and to the
+ * original extensions authors.
+ *
+ * Copyright (C) 2014 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <gtkmm.h>
+#include "desktop.h"
+#include "live_effects/lpe-roughen.h"
+#include "display/curve.h"
+#include "live_effects/parameter/parameter.h"
+#include "helper/geom.h"
+#include <glibmm/i18n.h>
+#include <util/units.h>
+#include <cmath>
+
+namespace Inkscape {
+namespace LivePathEffect {
+
+static const Util::EnumData<DivisionMethod> DivisionMethodData[DM_END] = {
+ { DM_SEGMENTS, N_("By number of segments"), "segments" },
+ { DM_SIZE, N_("By max. segment size"), "size" }
+};
+static const Util::EnumDataConverter<DivisionMethod>
+DMConverter(DivisionMethodData, DM_END);
+
+LPERoughen::LPERoughen(LivePathEffectObject *lpeobject)
+ : Effect(lpeobject),
+ // initialise your parameters here:
+ unit(_("Unit"), _("Unit"), "unit", &wr, this),
+ method(_("Method"), _("Division method"), "method", DMConverter, &wr,
+ this, DM_SEGMENTS),
+ maxSegmentSize(_("Max. segment size"), _("Max. segment size"),
+ "maxSegmentSize", &wr, this, 10.),
+ segments(_("Number of segments"), _("Number of segments"), "segments",
+ &wr, this, 2),
+ displaceX(_("Max. displacement in X"), _("Max. displacement in X"),
+ "displaceX", &wr, this, 10.),
+ displaceY(_("Max. displacement in Y"), _("Max. displacement in Y"),
+ "displaceY", &wr, this, 10.),
+ globalRandomize(_("Global randomize"), _("Global randomize"),
+ "globalRandomize", &wr, this, 1.),
+ shiftNodes(_("Shift nodes"), _("Shift nodes"), "shiftNodes", &wr, this,
+ true),
+ shiftNodeHandles(_("Shift node handles"), _("Shift node handles"),
+ "shiftNodeHandles", &wr, this, true)
+{
+ registerParameter(&unit);
+ registerParameter(&method);
+ registerParameter(&maxSegmentSize);
+ registerParameter(&segments);
+ registerParameter(&displaceX);
+ registerParameter(&displaceY);
+ registerParameter(&globalRandomize);
+ registerParameter(&shiftNodes);
+ registerParameter(&shiftNodeHandles);
+ displaceX.param_set_range(0., Geom::infinity());
+ displaceY.param_set_range(0., Geom::infinity());
+ globalRandomize.param_set_range(0., Geom::infinity());
+ maxSegmentSize.param_set_range(0., Geom::infinity());
+ maxSegmentSize.param_set_increments(1, 1);
+ maxSegmentSize.param_set_digits(1);
+ segments.param_set_range(1, Geom::infinity());
+ segments.param_set_increments(1, 1);
+ segments.param_set_digits(0);
+}
+
+LPERoughen::~LPERoughen() {}
+
+void LPERoughen::doBeforeEffect(SPLPEItem const *lpeitem)
+{
+ displaceX.resetRandomizer();
+ displaceY.resetRandomizer();
+ globalRandomize.resetRandomizer();
+ srand(1);
+ SPLPEItem * item = const_cast<SPLPEItem*>(lpeitem);
+ item->apply_to_clippath(item);
+ item->apply_to_mask(item);
+}
+
+Gtk::Widget *LPERoughen::newWidget()
+{
+ Gtk::VBox *vbox = Gtk::manage(new Gtk::VBox(Effect::newWidget()));
+ vbox->set_border_width(5);
+ vbox->set_homogeneous(false);
+ vbox->set_spacing(2);
+ std::vector<Parameter *>::iterator it = param_vector.begin();
+ while (it != param_vector.end()) {
+ if ((*it)->widget_is_visible) {
+ Parameter *param = *it;
+ Gtk::Widget *widg = dynamic_cast<Gtk::Widget *>(param->param_newWidget());
+ if (param->param_key == "unit") {
+ Gtk::Label *unitLabel = Gtk::manage(new Gtk::Label(
+ Glib::ustring(_("<b>Roughen unit</b>")), Gtk::ALIGN_START));
+ unitLabel->set_use_markup(true);
+ vbox->pack_start(*unitLabel, false, false, 2);
+ vbox->pack_start(*Gtk::manage(new Gtk::HSeparator()),
+ Gtk::PACK_EXPAND_WIDGET);
+ }
+ if (param->param_key == "method") {
+ Gtk::Label *methodLabel = Gtk::manage(new Gtk::Label(
+ Glib::ustring(_("<b>Add nodes</b> Subdivide each segment")),
+ Gtk::ALIGN_START));
+ methodLabel->set_use_markup(true);
+ vbox->pack_start(*methodLabel, false, false, 2);
+ vbox->pack_start(*Gtk::manage(new Gtk::HSeparator()),
+ Gtk::PACK_EXPAND_WIDGET);
+ }
+ if (param->param_key == "displaceX") {
+ Gtk::Label *displaceXLabel = Gtk::manage(new Gtk::Label(
+ Glib::ustring(_("<b>Jitter nodes</b> Move nodes/handles")),
+ Gtk::ALIGN_START));
+ displaceXLabel->set_use_markup(true);
+ vbox->pack_start(*displaceXLabel, false, false, 2);
+ vbox->pack_start(*Gtk::manage(new Gtk::HSeparator()),
+ Gtk::PACK_EXPAND_WIDGET);
+ }
+ if (param->param_key == "globalRandomize") {
+ Gtk::Label *displaceXLabel = Gtk::manage(new Gtk::Label(
+ Glib::ustring(_("<b>Extra roughen</b> Add a extra layer of rough")),
+ Gtk::ALIGN_START));
+ displaceXLabel->set_use_markup(true);
+ vbox->pack_start(*displaceXLabel, false, false, 2);
+ vbox->pack_start(*Gtk::manage(new Gtk::HSeparator()),
+ Gtk::PACK_EXPAND_WIDGET);
+ }
+ Glib::ustring *tip = param->param_getTooltip();
+ if (widg) {
+ vbox->pack_start(*widg, true, true, 2);
+ if (tip) {
+ widg->set_tooltip_text(*tip);
+ } else {
+ widg->set_tooltip_text("");
+ widg->set_has_tooltip(false);
+ }
+ }
+ }
+
+ ++it;
+ }
+ return dynamic_cast<Gtk::Widget *>(vbox);
+}
+
+double LPERoughen::sign(double randNumber)
+{
+ if (rand() % 100 < 49) {
+ randNumber *= -1.;
+ }
+ return randNumber;
+}
+
+Geom::Point LPERoughen::randomize()
+{
+ Inkscape::Util::Unit const *doc_units = SP_ACTIVE_DESKTOP->namedview->doc_units;
+ double displaceXParsed = Inkscape::Util::Quantity::convert(
+ displaceX * globalRandomize, unit.get_abbreviation(), doc_units->abbr);
+ double displaceYParsed = Inkscape::Util::Quantity::convert(
+ displaceY * globalRandomize, unit.get_abbreviation(), doc_units->abbr);
+
+ Geom::Point output = Geom::Point(sign(displaceXParsed), sign(displaceYParsed));
+ return output;
+}
+
+void LPERoughen::doEffect(SPCurve *curve)
+{
+ Geom::PathVector const original_pathv =
+ pathv_to_linear_and_cubic_beziers(curve->get_pathvector());
+ curve->reset();
+ Inkscape::Util::Unit const *doc_units = SP_ACTIVE_DESKTOP->namedview->doc_units;
+ for (Geom::PathVector::const_iterator path_it = original_pathv.begin();
+ path_it != original_pathv.end(); ++path_it) {
+ if (path_it->empty())
+ continue;
+
+ Geom::Path::const_iterator curve_it1 = path_it->begin();
+ Geom::Path::const_iterator curve_it2 = ++(path_it->begin());
+ Geom::Path::const_iterator curve_endit = path_it->end_default();
+ SPCurve *nCurve = new SPCurve();
+ if (path_it->closed()) {
+ const Geom::Curve &closingline =
+ path_it->back_closed();
+ if (are_near(closingline.initialPoint(), closingline.finalPoint())) {
+ curve_endit = path_it->end_open();
+ }
+ }
+ Geom::Point initialMove(0, 0);
+ if (shiftNodes) {
+ initialMove = randomize();
+ }
+ Geom::Point initialPoint = curve_it1->initialPoint() + initialMove;
+ nCurve->moveto(initialPoint);
+ Geom::Point A0(0, 0);
+ Geom::Point A1(0, 0);
+ Geom::Point A2(0, 0);
+ Geom::Point A3(0, 0);
+ bool first = true;
+ while (curve_it1 != curve_endit) {
+ Geom::CubicBezier const *cubic = NULL;
+ A0 = curve_it1->initialPoint();
+ A1 = curve_it1->initialPoint();
+ A2 = curve_it1->finalPoint();
+ A3 = curve_it1->finalPoint();
+ cubic = dynamic_cast<Geom::CubicBezier const *>(&*curve_it1);
+ if (cubic) {
+ A1 = (*cubic)[1];
+ if (shiftNodes && first) {
+ A1 = (*cubic)[1] + initialMove;
+ }
+ A2 = (*cubic)[2];
+ nCurve->curveto(A1, A2, A3);
+ } else {
+ nCurve->lineto(A3);
+ }
+ double length = Inkscape::Util::Quantity::convert(
+ curve_it1->length(0.001), doc_units->abbr, unit.get_abbreviation());
+ std::size_t splits = 0;
+ if (method == DM_SEGMENTS) {
+ splits = segments;
+ } else {
+ splits = ceil(length / maxSegmentSize);
+ }
+ for (unsigned int t = splits; t >= 1; t--) {
+ if (t == 1 && splits != 1) {
+ continue;
+ }
+ const SPCurve *tmp;
+ if (splits == 1) {
+ tmp = jitter(nCurve->last_segment());
+ } else {
+ tmp = addNodesAndJitter(nCurve->last_segment(), 1. / t);
+ }
+ if (nCurve->get_segment_count() > 1) {
+ nCurve->backspace();
+ nCurve->append_continuous(tmp, 0.001);
+ } else {
+ nCurve = tmp->copy();
+ }
+ delete tmp;
+ }
+ ++curve_it1;
+ if(curve_it2 != curve_endit) {
+ ++curve_it2;
+ }
+ first = false;
+ }
+ if (path_it->closed()) {
+ nCurve->closepath_current();
+ }
+ curve->append(nCurve, false);
+ nCurve->reset();
+ delete nCurve;
+ }
+}
+
+SPCurve *LPERoughen::addNodesAndJitter(const Geom::Curve *A, double t)
+{
+ SPCurve *out = new SPCurve();
+ Geom::CubicBezier const *cubic = dynamic_cast<Geom::CubicBezier const *>(&*A);
+ Geom::Point A1(0, 0);
+ Geom::Point A2(0, 0);
+ Geom::Point A3(0, 0);
+ Geom::Point B1(0, 0);
+ Geom::Point B2(0, 0);
+ Geom::Point B3(0, 0);
+ if (shiftNodes) {
+ A3 = randomize();
+ B3 = randomize();
+ }
+ if (shiftNodeHandles) {
+ A1 = randomize();
+ A2 = randomize();
+ B1 = randomize();
+ B2 = randomize();
+ } else {
+ A2 = A3;
+ B1 = A3;
+ B2 = B3;
+ }
+ if (cubic) {
+ std::pair<Geom::CubicBezier, Geom::CubicBezier> div = cubic->subdivide(t);
+ std::vector<Geom::Point> seg1 = div.first.points(),
+ seg2 = div.second.points();
+ out->moveto(seg1[0]);
+ out->curveto(seg1[1] + A1, seg1[2] + A2, seg1[3] + A3);
+ out->curveto(seg2[1] + B1, seg2[2], seg2[3]);
+ } else if (shiftNodeHandles) {
+ out->moveto(A->initialPoint());
+ out->curveto(A->pointAt(t / 3) + A1, A->pointAt((t / 3) * 2) + A2,
+ A->pointAt(t) + A3);
+ out->curveto(A->pointAt(t + (t / 3)) + B1, A->pointAt(t + ((t / 3) * 2)),
+ A->finalPoint());
+ } else {
+ out->moveto(A->initialPoint());
+ out->lineto(A->pointAt(t) + A3);
+ out->lineto(A->finalPoint());
+ }
+ return out;
+}
+
+SPCurve *LPERoughen::jitter(const Geom::Curve *A)
+{
+ SPCurve *out = new SPCurve();
+ Geom::CubicBezier const *cubic = dynamic_cast<Geom::CubicBezier const *>(&*A);
+ Geom::Point A1(0, 0);
+ Geom::Point A2(0, 0);
+ Geom::Point A3(0, 0);
+ if (shiftNodes) {
+ A3 = randomize();
+ }
+ if (shiftNodeHandles) {
+ A1 = randomize();
+ A2 = randomize();
+ } else {
+ A2 = A3;
+ }
+ if (cubic) {
+ out->moveto((*cubic)[0]);
+ out->curveto((*cubic)[1] + A1, (*cubic)[2] + A2, (*cubic)[3] + A3);
+ } else if (shiftNodeHandles) {
+ out->moveto(A->initialPoint());
+ out->curveto(A->pointAt(0.3333) + A1, A->pointAt(0.6666) + A2,
+ A->finalPoint() + A3);
+ } else {
+ out->moveto(A->initialPoint());
+ out->lineto(A->finalPoint() + A3);
+ }
+ return out;
+}
+
+Geom::Point LPERoughen::tpoint(Geom::Point A, Geom::Point B, double t)
+{
+ using Geom::X;
+ using Geom::Y;
+ return Geom::Point(A[X] + t * (B[X] - A[X]), A[Y] + t * (B[Y] - A[Y]));
+}
+
+}; //namespace LivePathEffect
+}; /* namespace Inkscape */
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/live_effects/lpe-roughen.h b/src/live_effects/lpe-roughen.h
new file mode 100644
index 000000000..74331f1ef
--- /dev/null
+++ b/src/live_effects/lpe-roughen.h
@@ -0,0 +1,65 @@
+/** @file
+ * @brief Roughen LPE effect, see lpe-roughen.cpp.
+ */
+/* Authors:
+ * Jabier Arraiza Cenoz <jabier.arraiza@marker.es>
+ *
+ * Copyright (C) 2014 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifndef INKSCAPE_LPE_ROUGHEN_H
+#define INKSCAPE_LPE_ROUGHEN_H
+
+#include "live_effects/parameter/enum.h"
+#include "live_effects/effect.h"
+#include "live_effects/parameter/parameter.h"
+#include "live_effects/parameter/path.h"
+#include "live_effects/parameter/bool.h"
+#include "live_effects/parameter/unit.h"
+#include "live_effects/parameter/random.h"
+
+namespace Inkscape {
+namespace LivePathEffect {
+
+enum DivisionMethod {
+ DM_SEGMENTS,
+ DM_SIZE,
+ DM_END
+};
+
+class LPERoughen : public Effect {
+
+public:
+ LPERoughen(LivePathEffectObject *lpeobject);
+ virtual ~LPERoughen();
+
+ virtual void doEffect(SPCurve *curve);
+ virtual double sign(double randNumber);
+ virtual Geom::Point randomize();
+ virtual void doBeforeEffect(SPLPEItem const * lpeitem);
+ virtual SPCurve *addNodesAndJitter(const Geom::Curve *A, double t);
+ virtual SPCurve *jitter(const Geom::Curve *A);
+ virtual Geom::Point tpoint(Geom::Point A, Geom::Point B, double t = 0.5);
+ virtual Gtk::Widget *newWidget();
+
+private:
+ UnitParam unit;
+ EnumParam<DivisionMethod> method;
+ ScalarParam maxSegmentSize;
+ ScalarParam segments;
+ RandomParam displaceX;
+ RandomParam displaceY;
+ RandomParam globalRandomize;
+ BoolParam shiftNodes;
+ BoolParam shiftNodeHandles;
+
+ LPERoughen(const LPERoughen &);
+ LPERoughen &operator=(const LPERoughen &);
+
+};
+
+}; //namespace LivePathEffect
+}; //namespace Inkscape
+#endif
diff --git a/src/live_effects/lpe-ruler.cpp b/src/live_effects/lpe-ruler.cpp
index 788ab593a..fd611c78d 100644
--- a/src/live_effects/lpe-ruler.cpp
+++ b/src/live_effects/lpe-ruler.cpp
@@ -29,7 +29,7 @@ static const Util::EnumData<MarkDirType> MarkDirData[] = {
static const Util::EnumDataConverter<MarkDirType> MarkDirTypeConverter(MarkDirData, sizeof(MarkDirData)/sizeof(*MarkDirData));
static const Util::EnumData<BorderMarkType> BorderMarkData[] = {
- {BORDERMARK_NONE , N_("None"), "none"},
+ {BORDERMARK_NONE , NC_("Border mark", "None"), "none"},
{BORDERMARK_START , N_("Start"), "start"},
{BORDERMARK_END , N_("End"), "end"},
{BORDERMARK_BOTH , N_("Both"), "both"},
diff --git a/src/live_effects/lpe-show_handles.cpp b/src/live_effects/lpe-show_handles.cpp
new file mode 100644
index 000000000..7b2b445b7
--- /dev/null
+++ b/src/live_effects/lpe-show_handles.cpp
@@ -0,0 +1,211 @@
+/*
+ * Authors:
+ * Jabier Arraiza Cenoz
+*
+* Copyright (C) Jabier Arraiza Cenoz 2014 <jabier.arraiza@marker.es>
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <gtkmm.h>
+#include <glibmm/i18n.h>
+#include "live_effects/lpe-show_handles.h"
+#include "live_effects/parameter/parameter.h"
+#include <2geom/sbasis-to-bezier.h>
+#include <2geom/svg-path-parser.h>
+#include "helper/geom.h"
+#include "desktop-style.h"
+#include "style.h"
+#include "svg/svg.h"
+
+namespace Inkscape {
+namespace LivePathEffect {
+
+LPEShowHandles::LPEShowHandles(LivePathEffectObject *lpeobject)
+ : Effect(lpeobject),
+ nodes(_("Show nodes"), _("Show nodes"), "nodes", &wr, this, true),
+ handles(_("Show handles"), _("Show handles"), "handles", &wr, this, true),
+ originalPath(_("Show path"), _("Show path"), "originalPath", &wr, this, true),
+ scaleNodesAndHandles(_("Scale nodes and handles"), _("Scale nodes and handles"), "scaleNodesAndHandles", &wr, this, 10)
+{
+ registerParameter(dynamic_cast<Parameter *>(&nodes));
+ registerParameter(dynamic_cast<Parameter *>(&handles));
+ registerParameter(dynamic_cast<Parameter *>(&originalPath));
+ registerParameter(dynamic_cast<Parameter *>(&scaleNodesAndHandles));
+ scaleNodesAndHandles.param_set_range(0, 500.);
+ scaleNodesAndHandles.param_set_increments(1, 1);
+ scaleNodesAndHandles.param_set_digits(2);
+ strokeWidth = 1.0;
+}
+
+bool LPEShowHandles::alertsOff = false;
+
+/**
+ * Sets default styles to element
+ * this permanently remove.some styles of the element
+ */
+
+void LPEShowHandles::doOnApply(SPLPEItem const* lpeitem)
+{
+ if(!alertsOff) {
+ char *msg = _("The \"show handles\" path effect will remove any custom style on the object you are applying it to. If this is not what you want, click Cancel.");
+ Gtk::MessageDialog dialog(msg, false, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_OK_CANCEL, true);
+ gint response = dialog.run();
+ alertsOff = true;
+ if(response == GTK_RESPONSE_CANCEL) {
+ SPLPEItem* item = const_cast<SPLPEItem*>(lpeitem);
+ item->removeCurrentPathEffect(false);
+ return;
+ }
+ }
+ SPLPEItem* item = const_cast<SPLPEItem*>(lpeitem);
+ SPCSSAttr *css = sp_repr_css_attr_new ();
+ sp_repr_css_set_property (css, "stroke", "black");
+ sp_repr_css_set_property (css, "stroke-width", "1");
+ sp_repr_css_set_property (css, "stroke-linecap", "butt");
+ sp_repr_css_set_property(css, "fill", "none");
+
+ sp_desktop_apply_css_recursive(item, css, true);
+ sp_repr_css_attr_unref (css);
+}
+
+void LPEShowHandles::doBeforeEffect (SPLPEItem const* lpeitem)
+{
+ SPItem const* item = SP_ITEM(lpeitem);
+ strokeWidth = item->style->stroke_width.computed;
+}
+
+std::vector<Geom::Path> LPEShowHandles::doEffect_path (std::vector<Geom::Path> const & path_in)
+{
+ std::vector<Geom::Path> path_out;
+ Geom::PathVector const original_pathv = pathv_to_linear_and_cubic_beziers(path_in);
+ if(originalPath) {
+ for (unsigned int i=0; i < path_in.size(); i++) {
+ path_out.push_back(path_in[i]);
+ }
+ }
+ if(!outlinepath.empty()) {
+ outlinepath.clear();
+ }
+ generateHelperPath(original_pathv);
+ for (unsigned int i=0; i < outlinepath.size(); i++) {
+ path_out.push_back(outlinepath[i]);
+ }
+ return path_out;
+}
+
+void
+LPEShowHandles::generateHelperPath(Geom::PathVector result)
+{
+ if(!handles && !nodes) {
+ return;
+ }
+
+ Geom::CubicBezier const *cubic = NULL;
+ for (Geom::PathVector::iterator path_it = result.begin(); path_it != result.end(); ++path_it) {
+ //Si está vacío...
+ if (path_it->empty()) {
+ continue;
+ }
+ //Itreadores
+ Geom::Path::const_iterator curve_it1 = path_it->begin(); // incoming curve
+ Geom::Path::const_iterator curve_it2 = ++(path_it->begin()); // outgoing curve
+ Geom::Path::const_iterator curve_endit = path_it->end_default(); // this determines when the loop has to stop
+
+ if (path_it->closed()) {
+ // if the path is closed, maybe we have to stop a bit earlier because the
+ // closing line segment has zerolength.
+ const Geom::Curve &closingline = path_it->back_closed(); // the closing line segment is always of type
+ // Geom::LineSegment.
+ if (are_near(closingline.initialPoint(), closingline.finalPoint())) {
+ // closingline.isDegenerate() did not work, because it only checks for
+ // *exact* zero length, which goes wrong for relative coordinates and
+ // rounding errors...
+ // the closing line segment has zero-length. So stop before that one!
+ curve_endit = path_it->end_open();
+ }
+ }
+ if(nodes) {
+ drawNode(curve_it1->initialPoint());
+ }
+ while (curve_it1 != curve_endit) {
+ cubic = dynamic_cast<Geom::CubicBezier const *>(&*curve_it1);
+ if (cubic) {
+ if(handles) {
+ if(!are_near((*cubic)[0],(*cubic)[1])){
+ drawHandle((*cubic)[1]);
+ drawHandleLine((*cubic)[0],(*cubic)[1]);
+ }
+ if(!are_near((*cubic)[3],(*cubic)[2])){
+ drawHandle((*cubic)[2]);
+ drawHandleLine((*cubic)[3],(*cubic)[2]);
+ }
+ }
+ }
+ if(nodes) {
+ drawNode(curve_it1->finalPoint());
+ }
+ ++curve_it1;
+ if(curve_it2 != curve_endit){
+ ++curve_it2;
+ }
+ }
+ }
+}
+
+void
+LPEShowHandles::drawNode(Geom::Point p)
+{
+ if(strokeWidth * scaleNodesAndHandles > 0.0) {
+ double diameter = strokeWidth * scaleNodesAndHandles;
+ char const * svgd;
+ svgd = "M 0.55,0.5 A 0.05,0.05 0 0 1 0.5,0.55 0.05,0.05 0 0 1 0.45,0.5 0.05,0.05 0 0 1 0.5,0.45 0.05,0.05 0 0 1 0.55,0.5 Z M 0,0 1,0 1,1 0,1 Z";
+ Geom::PathVector pathv = sp_svg_read_pathv(svgd);
+ pathv *= Geom::Affine(diameter,0,0,diameter,0,0);
+ pathv += p - Geom::Point(diameter/2,diameter/2);
+ outlinepath.push_back(pathv[0]);
+ outlinepath.push_back(pathv[1]);
+ }
+}
+
+void
+LPEShowHandles::drawHandle(Geom::Point p)
+{
+ if(strokeWidth * scaleNodesAndHandles > 0.0) {
+ double diameter = strokeWidth * scaleNodesAndHandles;
+ char const * svgd;
+ svgd = "M 0.7,0.35 A 0.35,0.35 0 0 1 0.35,0.7 0.35,0.35 0 0 1 0,0.35 0.35,0.35 0 0 1 0.35,0 0.35,0.35 0 0 1 0.7,0.35 Z";
+ Geom::PathVector pathv = sp_svg_read_pathv(svgd);
+ pathv *= Geom::Affine(diameter,0,0,diameter,0,0);
+ pathv += p - Geom::Point(diameter * 0.35,diameter * 0.35);
+ outlinepath.push_back(pathv[0]);
+ }
+}
+
+
+void
+LPEShowHandles::drawHandleLine(Geom::Point p,Geom::Point p2)
+{
+ Geom::Path path;
+ double diameter = strokeWidth * scaleNodesAndHandles;
+ if(diameter > 0.0 && Geom::distance(p,p2) > (diameter * 0.35)){
+ Geom::Ray ray2(p, p2);
+ p2 = p2 - Geom::Point::polar(ray2.angle(),(diameter * 0.35));
+ }
+ path.start( p );
+ path.appendNew<Geom::LineSegment>( p2 );
+ outlinepath.push_back(path);
+}
+
+}; //namespace LivePathEffect
+}; /* namespace Inkscape */
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/live_effects/lpe-show_handles.h b/src/live_effects/lpe-show_handles.h
new file mode 100644
index 000000000..278908bb5
--- /dev/null
+++ b/src/live_effects/lpe-show_handles.h
@@ -0,0 +1,61 @@
+#ifndef INKSCAPE_LPE_SHOW_HANDLES_H
+#define INKSCAPE_LPE_SHOW_HANDLES_H
+
+/*
+ * Authors:
+ * Jabier Arraiza Cenoz
+*
+* Copyright (C) Jabier Arraiza Cenoz 2014 <jabier.arraiza@marker.es>
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "live_effects/effect.h"
+#include "live_effects/lpegroupbbox.h"
+#include "live_effects/parameter/bool.h"
+
+namespace Inkscape {
+namespace LivePathEffect {
+
+class LPEShowHandles : public Effect , GroupBBoxEffect {
+
+public:
+ LPEShowHandles(LivePathEffectObject *lpeobject);
+ virtual ~LPEShowHandles(){}
+
+ virtual void doOnApply(SPLPEItem const* lpeitem);
+
+ virtual void doBeforeEffect (SPLPEItem const* lpeitem);
+
+ virtual void generateHelperPath(Geom::PathVector result);
+
+ virtual void drawNode(Geom::Point p);
+
+ virtual void drawHandle(Geom::Point p);
+
+ virtual void drawHandleLine(Geom::Point p,Geom::Point p2);
+
+protected:
+
+ virtual std::vector<Geom::Path> doEffect_path (std::vector<Geom::Path> const & path_in);
+
+private:
+
+ BoolParam nodes;
+ BoolParam handles;
+ BoolParam originalPath;
+ ScalarParam scaleNodesAndHandles;
+ double strokeWidth;
+ static bool alertsOff;
+
+ Geom::PathVector outlinepath;
+
+ LPEShowHandles(const LPEShowHandles &);
+ LPEShowHandles &operator=(const LPEShowHandles &);
+
+};
+
+}; //namespace LivePathEffect
+}; //namespace Inkscape
+#endif
+
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/live_effects/lpe-simplify.cpp b/src/live_effects/lpe-simplify.cpp
new file mode 100644
index 000000000..2b2efb1a9
--- /dev/null
+++ b/src/live_effects/lpe-simplify.cpp
@@ -0,0 +1,292 @@
+/*
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <gtkmm.h>
+
+#include "live_effects/lpe-simplify.h"
+#include "display/curve.h"
+#include "live_effects/parameter/parameter.h"
+#include <glibmm/i18n.h>
+#include "helper/geom.h"
+#include "livarot/Path.h"
+#include "splivarot.h"
+#include <2geom/svg-path-parser.h>
+#include "desktop.h"
+#include "inkscape.h"
+#include "svg/svg.h"
+#include "ui/tools/node-tool.h"
+#include <2geom/d2.h>
+#include <2geom/generic-rect.h>
+#include <2geom/interval.h>
+#include "ui/icon-names.h"
+
+namespace Inkscape {
+namespace LivePathEffect {
+
+LPESimplify::LPESimplify(LivePathEffectObject *lpeobject)
+ : Effect(lpeobject),
+ steps(_("Steps:"),_("Change number of simplify steps "), "steps", &wr, this,1),
+ threshold(_("Roughly threshold:"), _("Roughly threshold:"), "threshold", &wr, this, 0.003),
+ helper_size(_("Helper size:"), _("Helper size"), "helper_size", &wr, this, 2.),
+ nodes(_("Helper nodes"), _("Show helper nodes"), "nodes", &wr, this, false,
+ "", INKSCAPE_ICON("on"), INKSCAPE_ICON("off")),
+ handles(_("Helper handles"), _("Show helper handles"), "handles", &wr, this, false,
+ "", INKSCAPE_ICON("on"), INKSCAPE_ICON("off")),
+ simplifyindividualpaths(_("Paths separately"), _("Simplifying paths (separately)"), "simplifyindividualpaths", &wr, this, false,
+ "", INKSCAPE_ICON("on"), INKSCAPE_ICON("off")),
+ simplifyJustCoalesce(_("Just coalesce"), _("Simplify just coalesce"), "simplifyJustCoalesce", &wr, this, false,
+ "", INKSCAPE_ICON("on"), INKSCAPE_ICON("off"))
+ {
+ registerParameter(dynamic_cast<Parameter *>(&steps));
+ registerParameter(dynamic_cast<Parameter *>(&threshold));
+ registerParameter(dynamic_cast<Parameter *>(&helper_size));
+ registerParameter(dynamic_cast<Parameter *>(&nodes));
+ registerParameter(dynamic_cast<Parameter *>(&handles));
+ registerParameter(dynamic_cast<Parameter *>(&simplifyindividualpaths));
+ registerParameter(dynamic_cast<Parameter *>(&simplifyJustCoalesce));
+ threshold.param_set_range(0.0001, Geom::infinity());
+ threshold.param_set_increments(0.0001, 0.0001);
+ threshold.param_set_digits(6);
+ steps.param_set_range(0, 100);
+ steps.param_set_increments(1, 1);
+ steps.param_set_digits(0);
+ helper_size.param_set_range(0.1, 100);
+ helper_size.param_set_increments(1, 1);
+ helper_size.param_set_digits(1);
+}
+
+LPESimplify::~LPESimplify() {}
+
+void
+LPESimplify::doBeforeEffect (SPLPEItem const* lpeitem)
+{
+ if(!hp.empty()){
+ hp.clear();
+ }
+ bbox = SP_ITEM(lpeitem)->visualBounds();
+ SPLPEItem * item = const_cast<SPLPEItem*>(lpeitem);
+ item->apply_to_clippath(item);
+ item->apply_to_mask(item);
+
+}
+
+Gtk::Widget *
+LPESimplify::newWidget()
+{
+ // use manage here, because after deletion of Effect object, others might still be pointing to this widget.
+ Gtk::VBox * vbox = Gtk::manage( new Gtk::VBox(Effect::newWidget()) );
+ vbox->set_border_width(5);
+ vbox->set_homogeneous(false);
+ vbox->set_spacing(2);
+ std::vector<Parameter *>::iterator it = param_vector.begin();
+ Gtk::HBox * buttons = Gtk::manage(new Gtk::HBox(true,0));
+ Gtk::HBox * buttonsTwo = Gtk::manage(new Gtk::HBox(true,0));
+ while (it != param_vector.end()) {
+ if ((*it)->widget_is_visible) {
+ Parameter * param = *it;
+ Gtk::Widget * widg = dynamic_cast<Gtk::Widget *>(param->param_newWidget());
+ if (param->param_key == "simplifyindividualpaths" ||
+ param->param_key == "simplifyJustCoalesce")
+ {
+ Glib::ustring * tip = param->param_getTooltip();
+ if (widg) {
+ buttonsTwo->pack_start(*widg, true, true, 2);
+ if (tip) {
+ widg->set_tooltip_text(*tip);
+ } else {
+ widg->set_tooltip_text("");
+ widg->set_has_tooltip(false);
+ }
+ }
+ } else if (param->param_key == "nodes" ||
+ param->param_key == "handles")
+ {
+ Glib::ustring * tip = param->param_getTooltip();
+ if (widg) {
+ buttons->pack_start(*widg, true, true, 2);
+ if (tip) {
+ widg->set_tooltip_text(*tip);
+ } else {
+ widg->set_tooltip_text("");
+ widg->set_has_tooltip(false);
+ }
+ }
+ }else{
+ Glib::ustring * tip = param->param_getTooltip();
+ if (widg) {
+ Gtk::HBox * scalarParameter = dynamic_cast<Gtk::HBox *>(widg);
+ std::vector< Gtk::Widget* > childList = scalarParameter->get_children();
+ Gtk::Entry* entryWidg = dynamic_cast<Gtk::Entry *>(childList[1]);
+ entryWidg->set_width_chars(8);
+ vbox->pack_start(*widg, true, true, 2);
+ if (tip) {
+ widg->set_tooltip_text(*tip);
+ } else {
+ widg->set_tooltip_text("");
+ widg->set_has_tooltip(false);
+ }
+ }
+ }
+ }
+
+ ++it;
+ }
+ vbox->pack_start(*buttons,true, true, 2);
+ vbox->pack_start(*buttonsTwo,true, true, 2);
+ return dynamic_cast<Gtk::Widget *>(vbox);
+}
+
+void
+LPESimplify::doEffect(SPCurve *curve) {
+ Geom::PathVector const original_pathv = pathv_to_linear_and_cubic_beziers(curve->get_pathvector());
+ gdouble size = Geom::L2(bbox->dimensions());
+ //size /= Geom::Affine(0,0,0,0,0,0).descrim();
+ Path* pathliv = Path_for_pathvector(original_pathv);
+ if(simplifyindividualpaths){
+ size = Geom::L2(Geom::bounds_fast(original_pathv)->dimensions());
+ }
+ for (int unsigned i = 0; i < steps; i++){
+ if ( simplifyJustCoalesce ) {
+ pathliv->Coalesce(threshold * size);
+ }else{
+ pathliv->ConvertEvenLines(threshold * size);
+ pathliv->Simplify(threshold * size);
+ }
+ }
+ Geom::PathVector outres = Geom::parse_svg_path(pathliv->svg_dump_path());
+ generateHelperPath(outres);
+ curve->set_pathvector(outres);
+ SPDesktop* desktop = SP_ACTIVE_DESKTOP;
+ if(desktop && INK_IS_NODE_TOOL(desktop->event_context)){
+ Inkscape::UI::Tools::NodeTool *nt = static_cast<Inkscape::UI::Tools::NodeTool*>(desktop->event_context);
+ nt->update_helperpath();
+ }
+}
+
+void
+LPESimplify::generateHelperPath(Geom::PathVector result)
+{
+ if(!handles && !nodes){
+ return;
+ }
+
+ if(steps < 1){
+ return;
+ }
+
+ Geom::CubicBezier const *cubic = NULL;
+ for (Geom::PathVector::iterator path_it = result.begin(); path_it != result.end(); ++path_it) {
+ //Si está vacío...
+ if (path_it->empty()){
+ continue;
+ }
+ //Itreadores
+ Geom::Path::const_iterator curve_it1 = path_it->begin(); // incoming curve
+ Geom::Path::const_iterator curve_it2 =
+ ++(path_it->begin()); // outgoing curve
+ Geom::Path::const_iterator curve_endit =
+ path_it->end_default(); // this determines when the loop has to stop
+
+ if (path_it->closed()) {
+ // if the path is closed, maybe we have to stop a bit earlier because the
+ // closing line segment has zerolength.
+ const Geom::Curve &closingline =
+ path_it->back_closed(); // the closing line segment is always of type
+ // Geom::LineSegment.
+ if (are_near(closingline.initialPoint(), closingline.finalPoint())) {
+ // closingline.isDegenerate() did not work, because it only checks for
+ // *exact* zero length, which goes wrong for relative coordinates and
+ // rounding errors...
+ // the closing line segment has zero-length. So stop before that one!
+ curve_endit = path_it->end_open();
+ }
+ }
+ if(nodes){
+ drawNode(curve_it1->initialPoint());
+ }
+ while (curve_it1 != curve_endit) {
+ cubic = dynamic_cast<Geom::CubicBezier const *>(&*curve_it1);
+ if (cubic) {
+ if(handles) {
+ if(!are_near((*cubic)[0],(*cubic)[1])){
+ drawHandle((*cubic)[1]);
+ drawHandleLine((*cubic)[0],(*cubic)[1]);
+ }
+ if(!are_near((*cubic)[3],(*cubic)[2])){
+ drawHandle((*cubic)[2]);
+ drawHandleLine((*cubic)[3],(*cubic)[2]);
+ }
+ }
+ }
+ if(nodes) {
+ drawNode(curve_it1->finalPoint());
+ }
+ ++curve_it1;
+ if(curve_it2 != curve_endit){
+ ++curve_it2;
+ }
+ }
+ }
+}
+
+void
+LPESimplify::drawNode(Geom::Point p)
+{
+ double r = helper_size/0.67;
+ char const * svgd;
+ svgd = "M 0.55,0.5 A 0.05,0.05 0 0 1 0.5,0.55 0.05,0.05 0 0 1 0.45,0.5 0.05,0.05 0 0 1 0.5,0.45 0.05,0.05 0 0 1 0.55,0.5 Z M 0,0 1,0 1,1 0,1 Z";
+ Geom::PathVector pathv = sp_svg_read_pathv(svgd);
+ pathv *= Geom::Affine(r,0,0,r,0,0);
+ pathv += p - Geom::Point(0.5*r,0.5*r);
+ hp.push_back(pathv[0]);
+ hp.push_back(pathv[1]);
+}
+
+void
+LPESimplify::drawHandle(Geom::Point p)
+{
+ double r = helper_size/0.67;
+ char const * svgd;
+ svgd = "M 0.7,0.35 A 0.35,0.35 0 0 1 0.35,0.7 0.35,0.35 0 0 1 0,0.35 0.35,0.35 0 0 1 0.35,0 0.35,0.35 0 0 1 0.7,0.35 Z";
+ Geom::PathVector pathv = sp_svg_read_pathv(svgd);
+ pathv *= Geom::Affine(r,0,0,r,0,0);
+ pathv += p - Geom::Point(0.35*r,0.35*r);
+ hp.push_back(pathv[0]);
+}
+
+
+void
+LPESimplify::drawHandleLine(Geom::Point p,Geom::Point p2)
+{
+ Geom::Path path;
+ path.start( p );
+ double diameter = helper_size/0.67;
+ if(helper_size > 0.0 && Geom::distance(p,p2) > (diameter * 0.35)){
+ Geom::Ray ray2(p, p2);
+ p2 = p2 - Geom::Point::polar(ray2.angle(),(diameter * 0.35));
+ }
+ path.appendNew<Geom::LineSegment>( p2 );
+ hp.push_back(path);
+}
+
+void
+LPESimplify::addCanvasIndicators(SPLPEItem const */*lpeitem*/, std::vector<Geom::PathVector> &hp_vec)
+{
+ hp_vec.push_back(hp);
+}
+
+
+}; //namespace LivePathEffect
+}; /* namespace Inkscape */
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/live_effects/lpe-simplify.h b/src/live_effects/lpe-simplify.h
new file mode 100644
index 000000000..6acf2f2d4
--- /dev/null
+++ b/src/live_effects/lpe-simplify.h
@@ -0,0 +1,59 @@
+#ifndef INKSCAPE_LPE_SIMPLIFY_H
+#define INKSCAPE_LPE_SIMPLIFY_H
+
+/*
+ * Inkscape::LPESimplify
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "live_effects/effect.h"
+#include "live_effects/parameter/togglebutton.h"
+#include "live_effects/lpegroupbbox.h"
+
+namespace Inkscape {
+namespace LivePathEffect {
+
+class LPESimplify : public Effect , GroupBBoxEffect{
+
+public:
+ LPESimplify(LivePathEffectObject *lpeobject);
+ virtual ~LPESimplify();
+
+ virtual void doEffect(SPCurve *curve);
+
+ virtual void doBeforeEffect (SPLPEItem const* lpeitem);
+
+ virtual void generateHelperPath(Geom::PathVector result);
+
+ virtual Gtk::Widget * newWidget();
+
+ virtual void drawNode(Geom::Point p);
+
+ virtual void drawHandle(Geom::Point p);
+
+ virtual void drawHandleLine(Geom::Point p,Geom::Point p2);
+
+protected:
+ void addCanvasIndicators(SPLPEItem const */*lpeitem*/, std::vector<Geom::PathVector> &hp_vec);
+
+private:
+ ScalarParam steps;
+ ScalarParam threshold;
+ ScalarParam helper_size;
+ ToggleButtonParam nodes;
+ ToggleButtonParam handles;
+ ToggleButtonParam simplifyindividualpaths;
+ ToggleButtonParam simplifyJustCoalesce;
+
+ Geom::PathVector hp;
+ Geom::OptRect bbox;
+
+ LPESimplify(const LPESimplify &);
+ LPESimplify &operator=(const LPESimplify &);
+
+};
+
+}; //namespace LivePathEffect
+}; //namespace Inkscape
+#endif
diff --git a/src/live_effects/lpe-tangent_to_curve.cpp b/src/live_effects/lpe-tangent_to_curve.cpp
index dbebdf7fb..bce4876af 100644
--- a/src/live_effects/lpe-tangent_to_curve.cpp
+++ b/src/live_effects/lpe-tangent_to_curve.cpp
@@ -16,8 +16,6 @@
#include <glibmm/i18n.h>
#include "live_effects/lpe-tangent_to_curve.h"
-// FIXME: The following are only needed to convert the path's SPCurve* to pwd2.
-// There must be a more convenient way to achieve this.
#include "sp-path.h"
#include "display/curve.h"
@@ -108,13 +106,13 @@ LPETangentToCurve::addKnotHolderEntities(KnotHolder *knotholder, SPDesktop *desk
{
KnotHolderEntity *e = new TtC::KnotHolderEntityLeftEnd(this);
e->create( desktop, item, knotholder, Inkscape::CTRL_TYPE_UNKNOWN,
- _("Adjust the \"left\" end of the tangent") );
+ _("Adjust the <b>left</b> end of the tangent") );
knotholder->add(e);
}
{
KnotHolderEntity *e = new TtC::KnotHolderEntityRightEnd(this);
e->create( desktop, item, knotholder, Inkscape::CTRL_TYPE_UNKNOWN,
- _("Adjust the \"right\" end of the tangent") );
+ _("Adjust the <b>right</b> end of the tangent") );
knotholder->add(e);
}
};
@@ -130,14 +128,13 @@ KnotHolderEntityAttachPt::knot_set(Geom::Point const &p, Geom::Point const &/*or
Geom::Point const s = snap_knot_position(p, state);
- // FIXME: There must be a better way of converting the path's SPCurve* to pwd2.
- SPCurve *curve = SP_PATH(item)->get_curve_for_edit();
- Geom::PathVector pathv = curve->get_pathvector();
- Piecewise<D2<SBasis> > pwd2;
- for (unsigned int i=0; i < pathv.size(); i++) {
- pwd2.concat(pathv[i].toPwSb());
+ if ( !SP_IS_SHAPE(lpe->sp_lpe_item) ) {
+ //lpe->t_attach.param_set_value(0);
+ g_warning("LPEItem is not a path! %s:%d\n", __FILE__, __LINE__);
+ return;
}
-
+ Piecewise<D2<SBasis> > pwd2 = paths_to_pw( lpe->pathvector_before_effect );
+
double t0 = nearest_point(s, pwd2);
lpe->t_attach.param_set_value(t0);
diff --git a/src/live_effects/lpe-tangent_to_curve.h b/src/live_effects/lpe-tangent_to_curve.h
index 309afc14b..8e44c01d1 100644
--- a/src/live_effects/lpe-tangent_to_curve.h
+++ b/src/live_effects/lpe-tangent_to_curve.h
@@ -34,7 +34,6 @@ class LPETangentToCurve : public Effect {
public:
LPETangentToCurve(LivePathEffectObject *lpeobject);
virtual ~LPETangentToCurve();
-
virtual Geom::Piecewise<Geom::D2<Geom::SBasis> >
doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_in);
diff --git a/src/live_effects/lpe-taperstroke.cpp b/src/live_effects/lpe-taperstroke.cpp
new file mode 100644
index 000000000..b595b8d55
--- /dev/null
+++ b/src/live_effects/lpe-taperstroke.cpp
@@ -0,0 +1,632 @@
+/**
+ * @file
+ * Taper Stroke path effect, provided as an alternative to Power Strokes
+ * for otherwise constant-width paths.
+ *
+ * Authors:
+ * Liam P White <inkscapebrony@gmail.com>
+ *
+ * Copyright (C) 2014 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "live_effects/lpe-taperstroke.h"
+
+#include <2geom/path.h>
+#include <2geom/shape.h>
+#include <2geom/path.h>
+#include <2geom/circle.h>
+#include <2geom/sbasis-to-bezier.h>
+
+#include "pathoutlineprovider.h"
+#include "display/curve.h"
+#include "sp-shape.h"
+#include "style.h"
+#include "xml/repr.h"
+#include "sp-paint-server.h"
+#include "svg/svg-color.h"
+#include "desktop-style.h"
+#include "svg/css-ostringstream.h"
+#include "svg/svg.h"
+
+#include "knot-holder-entity.h"
+#include "knotholder.h"
+
+#include <glibmm/i18n.h>
+
+template<typename T>
+inline bool withinRange(T value, T low, T high) {
+ return (value > low && value < high);
+}
+
+namespace Inkscape {
+namespace LivePathEffect {
+
+namespace TpS {
+ class KnotHolderEntityAttachBegin : public LPEKnotHolderEntity {
+ public:
+ KnotHolderEntityAttachBegin(LPETaperStroke * effect) : LPEKnotHolderEntity(effect) {}
+ virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state);
+ virtual Geom::Point knot_get() const;
+ };
+
+ class KnotHolderEntityAttachEnd : public LPEKnotHolderEntity {
+ public:
+ KnotHolderEntityAttachEnd(LPETaperStroke * effect) : LPEKnotHolderEntity(effect) {}
+ virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state);
+ virtual Geom::Point knot_get() const;
+ };
+} // TpS
+
+static const Util::EnumData<unsigned> JoinType[] = {
+ {LINEJOIN_STRAIGHT, N_("Beveled"), "bevel"},
+ {LINEJOIN_ROUND, N_("Rounded"), "round"},
+ {LINEJOIN_REFLECTED, N_("Reflected"), "reflected"},
+ {LINEJOIN_POINTY, N_("Miter"), "miter"},
+ {LINEJOIN_EXTRAPOLATED, N_("Extrapolated"), "extrapolated"}
+};
+
+static const Util::EnumDataConverter<unsigned> JoinTypeConverter(JoinType, sizeof (JoinType)/sizeof(*JoinType));
+
+LPETaperStroke::LPETaperStroke(LivePathEffectObject *lpeobject) :
+ Effect(lpeobject),
+ line_width(_("Stroke width"), _("The (non-tapered) width of the path"), "stroke_width", &wr, this, 1.),
+ attach_start(_("Start offset"), _("Taper distance from path start"), "attach_start", &wr, this, 0.2),
+ attach_end(_("End offset"), _("The ending position of the taper"), "end_offset", &wr, this, 0.2),
+ smoothing(_("Taper smoothing"), _("Amount of smoothing to apply to the tapers"), "smoothing", &wr, this, 0.5),
+ join_type(_("Join type"), _("Join type for non-smooth nodes"), "jointype", JoinTypeConverter, &wr, this, LINEJOIN_EXTRAPOLATED),
+ miter_limit(_("Miter limit"), _("Limit for miter joins"), "miter_limit", &wr, this, 100.)
+{
+ show_orig_path = true;
+ _provides_knotholder_entities = true;
+
+ attach_start.param_set_digits(3);
+ attach_end.param_set_digits(3);
+
+ registerParameter(&line_width);
+ registerParameter(&attach_start);
+ registerParameter(&attach_end);
+ registerParameter(&smoothing);
+ registerParameter(&join_type);
+ registerParameter(&miter_limit);
+}
+
+// from LPEPowerStroke -- sets fill if stroke color because we will
+// be converting to a fill to make the new join.
+
+void LPETaperStroke::doOnApply(SPLPEItem const* lpeitem)
+{
+ if (SP_IS_SHAPE(lpeitem)) {
+ SPLPEItem* item = const_cast<SPLPEItem*>(lpeitem);
+ double width = (lpeitem && lpeitem->style) ? lpeitem->style->stroke_width.computed : 1.;
+
+ SPCSSAttr *css = sp_repr_css_attr_new ();
+ if (true) {
+ if (lpeitem->style->stroke.isPaintserver()) {
+ SPPaintServer * server = lpeitem->style->getStrokePaintServer();
+ if (server) {
+ Glib::ustring str;
+ str += "url(#";
+ str += server->getId();
+ str += ")";
+ sp_repr_css_set_property (css, "fill", str.c_str());
+ }
+ } else if (lpeitem->style->stroke.isColor()) {
+ gchar c[64];
+ sp_svg_write_color (c, sizeof(c), lpeitem->style->stroke.value.color.toRGBA32(SP_SCALE24_TO_FLOAT(lpeitem->style->stroke_opacity.value)));
+ sp_repr_css_set_property (css, "fill", c);
+ } else {
+ sp_repr_css_set_property (css, "fill", "none");
+ }
+ } else {
+ sp_repr_css_unset_property (css, "fill");
+ }
+
+ sp_repr_css_set_property(css, "stroke", "none");
+
+ sp_desktop_apply_css_recursive(item, css, true);
+ sp_repr_css_attr_unref (css);
+
+ line_width.param_set_value(width);
+ } else {
+ printf("WARNING: It only makes sense to apply Join Type to paths (not groups).\n");
+ }
+}
+
+// from LPEPowerStroke -- sets stroke color from existing fill color
+
+void LPETaperStroke::doOnRemove(SPLPEItem const* lpeitem)
+{
+ if (SP_IS_SHAPE(lpeitem)) {
+ SPLPEItem *item = const_cast<SPLPEItem*>(lpeitem);
+
+ SPCSSAttr *css = sp_repr_css_attr_new ();
+ if (true) {
+ if (lpeitem->style->fill.isPaintserver()) {
+ SPPaintServer * server = lpeitem->style->getFillPaintServer();
+ if (server) {
+ Glib::ustring str;
+ str += "url(#";
+ str += server->getId();
+ str += ")";
+ sp_repr_css_set_property (css, "stroke", str.c_str());
+ }
+ } else if (lpeitem->style->fill.isColor()) {
+ gchar c[64];
+ sp_svg_write_color (c, sizeof(c), lpeitem->style->stroke.value.color.toRGBA32(SP_SCALE24_TO_FLOAT(lpeitem->style->stroke_opacity.value)));
+ sp_repr_css_set_property (css, "stroke", c);
+ } else {
+ sp_repr_css_set_property (css, "stroke", "none");
+ }
+ } else {
+ sp_repr_css_unset_property (css, "stroke");
+ }
+
+ Inkscape::CSSOStringStream os;
+ os << fabs(line_width);
+ sp_repr_css_set_property (css, "stroke-width", os.str().c_str());
+
+ sp_repr_css_set_property(css, "fill", "none");
+
+ sp_desktop_apply_css_recursive(item, css, true);
+ sp_repr_css_attr_unref (css);
+ }
+}
+
+using Geom::Piecewise;
+using Geom::D2;
+using Geom::SBasis;
+// leave Geom::Path
+
+Geom::Path return_at_first_cusp(Geom::Path const & path_in, double /*smooth_tolerance*/ = 0.05) {
+ return Geom::split_at_cusps(path_in)[0];
+}
+
+Piecewise<D2<SBasis> > stretch_along(Piecewise<D2<SBasis> > pwd2_in, Geom::Path pattern, double width);
+
+// references to pointers
+void subdivideCurve(Geom::Curve * curve_in, Geom::Coord t, Geom::Curve *& val_first, Geom::Curve *& val_second);
+
+// actual effect
+
+Geom::PathVector LPETaperStroke::doEffect_path(Geom::PathVector const& path_in)
+{
+ Geom::Path first_cusp = return_at_first_cusp(path_in[0]);
+ Geom::Path last_cusp = return_at_first_cusp(path_in[0].reverse());
+
+ bool zeroStart = false; // [distance from start taper knot -> start of path] == 0
+ bool zeroEnd = false; // [distance from end taper knot -> end of path] == 0
+ bool metInMiddle = false; // knots are touching
+
+ // there is a pretty good chance that people will try to drag the knots
+ // on top of each other, so block it
+
+ unsigned size = path_in[0].size();
+ if (size == first_cusp.size()) {
+ // check to see if the knots were dragged over each other
+ // if so, reset the end offset, but still allow the start offset.
+ if ( attach_start >= (size - attach_end) ) {
+ attach_end.param_set_value( size - attach_start );
+ metInMiddle = true;
+ }
+ }
+
+ if (attach_start == size - attach_end) {
+ metInMiddle = true;
+ }
+ if (attach_end == size - attach_start) {
+ metInMiddle = true;
+ }
+
+ // don't let it be integer (TODO this is stupid!)
+ {
+ if (double(unsigned(attach_start)) == attach_start) {
+ attach_start.param_set_value(attach_start - 0.00001);
+ }
+ if (double(unsigned(attach_end)) == attach_end) {
+ attach_end.param_set_value(attach_end - 0.00001);
+ }
+ }
+
+ unsigned allowed_start = first_cusp.size();
+ unsigned allowed_end = last_cusp.size();
+
+ // don't let the knots be farther than they are allowed to be
+ {
+ if ((unsigned)attach_start >= allowed_start) {
+ attach_start.param_set_value((double)allowed_start - 0.00001);
+ }
+ if ((unsigned)attach_end >= allowed_end) {
+ attach_end.param_set_value((double)allowed_end - 0.00001);
+ }
+ }
+
+ // don't let it be zero (this is stupid too!)
+ if (attach_start < 0.0000001 || withinRange(double(attach_start), 0.00000001, 0.000001)) {
+ attach_start.param_set_value( 0.0000001 );
+ zeroStart = true;
+ }
+ if (attach_end < 0.0000001 || withinRange(double(attach_end), 0.00000001, 0.000001)) {
+ attach_end.param_set_value( 0.0000001 );
+ zeroEnd = true;
+ }
+
+ // Path::operator () means get point at time t
+ start_attach_point = first_cusp(attach_start);
+ end_attach_point = last_cusp(attach_end);
+ Geom::PathVector pathv_out;
+
+ // the following function just splits it up into three pieces.
+ pathv_out = doEffect_simplePath(path_in);
+
+ // now for the actual tapering. the stretch_along method (stolen from PaP) is used to accomplish this
+
+ Geom::PathVector real_pathv;
+ Geom::Path real_path;
+ Geom::PathVector pat_vec;
+ Piecewise<D2<SBasis> > pwd2;
+ Geom::Path throwaway_path;
+
+ if (!zeroStart) {
+ // Construct the pattern
+ std::stringstream pat_str;
+ pat_str.imbue(std::locale::classic());
+ pat_str << "M 1,0 C " << 1 - (double)smoothing << ",0 0,0.5 0,0.5 0,0.5 " << 1 - (double)smoothing << ",1 1,1";
+
+ pat_vec = sp_svg_read_pathv(pat_str.str().c_str());
+ pwd2.concat(stretch_along(pathv_out[0].toPwSb(), pat_vec[0], -fabs(line_width)));
+ throwaway_path = Geom::path_from_piecewise(pwd2, LPE_CONVERSION_TOLERANCE)[0];
+
+ real_path.append(throwaway_path);
+ }
+
+ // if this condition happens to evaluate false, i.e. there was no space for a path to be drawn, it is simply skipped.
+ // although this seems obvious, it can probably lead to bugs.
+ if (!metInMiddle) {
+ // append the outside outline of the path (goes with the direction of the path)
+ throwaway_path = Outline::PathOutsideOutline(pathv_out[1], -fabs(line_width), static_cast<LineJoinType>(join_type.get_value()), miter_limit);
+ if (!zeroStart && real_path.size() >= 1 && throwaway_path.size() >= 1) {
+ if (!Geom::are_near(real_path.finalPoint(), throwaway_path.initialPoint())) {
+ real_path.appendNew<Geom::LineSegment>(throwaway_path.initialPoint());
+ } else {
+ real_path.setFinal(throwaway_path.initialPoint());
+ }
+ }
+ real_path.append(throwaway_path);
+ }
+
+ if (!zeroEnd) {
+ // append the ending taper
+ std::stringstream pat_str_1;
+ pat_str_1.imbue(std::locale::classic());
+ pat_str_1 << "M 0,1 C " << (double)smoothing << ",1 1,0.5 1,0.5 1,0.5 " << double(smoothing) << ",0 0,0";
+ pat_vec = sp_svg_read_pathv(pat_str_1.str().c_str());
+
+ pwd2 = Piecewise<D2<SBasis> >();
+ pwd2.concat(stretch_along(pathv_out[2].toPwSb(), pat_vec[0], -fabs(line_width)));
+
+ throwaway_path = Geom::path_from_piecewise(pwd2, LPE_CONVERSION_TOLERANCE)[0];
+ if (!Geom::are_near(real_path.finalPoint(), throwaway_path.initialPoint()) && real_path.size() >= 1) {
+ real_path.appendNew<Geom::LineSegment>(throwaway_path.initialPoint());
+ } else {
+ real_path.setFinal(throwaway_path.initialPoint());
+ }
+ real_path.append(throwaway_path);
+ }
+
+ if (!metInMiddle) {
+ // append the inside outline of the path (against direction)
+ throwaway_path = Outline::PathOutsideOutline(pathv_out[1].reverse(), -fabs(line_width), static_cast<LineJoinType>(join_type.get_value()), miter_limit);
+
+ if (!Geom::are_near(real_path.finalPoint(), throwaway_path.initialPoint()) && real_path.size() >= 1) {
+ real_path.appendNew<Geom::LineSegment>(throwaway_path.initialPoint());
+ } else {
+ real_path.setFinal(throwaway_path.initialPoint());
+ }
+ real_path.append(throwaway_path);
+ }
+
+ if (!Geom::are_near(real_path.finalPoint(), real_path.initialPoint())) {
+ real_path.appendNew<Geom::LineSegment>(real_path.initialPoint());
+ } else {
+ real_path.setFinal(real_path.initialPoint());
+ }
+ real_path.close();
+
+ real_pathv.push_back(real_path);
+
+ return real_pathv;
+}
+
+/**
+ * @return Always returns a PathVector with three elements.
+ *
+ * The positions of the effect knots are accessed to determine
+ * where exactly the input path should be split.
+ */
+Geom::PathVector LPETaperStroke::doEffect_simplePath(Geom::PathVector const & path_in)
+{
+ size_t size = path_in[0].size();
+
+ unsigned loc = (unsigned)attach_start;
+ Geom::Curve * curve_start = path_in[0] [loc].duplicate();
+
+ std::vector<Geom::Path> pathv_out;
+ Geom::Path path_out = Geom::Path();
+
+ Geom::Path trimmed_start = Geom::Path();
+ Geom::Path trimmed_end = Geom::Path();
+
+ for (size_t i = 0; i < loc; ++i) {
+ trimmed_start.append(path_in[0] [i]);
+ }
+
+ Geom::Curve * temp;
+ subdivideCurve(curve_start, attach_start - loc, temp, curve_start);
+ trimmed_start.append(*temp);
+ if (temp) delete temp; temp = 0;
+
+ // special case: path is one segment long
+ // special case: what if the two knots occupy the same segment?
+ if ((size == 1) || ( size - unsigned(attach_end) - 1 == loc )) {
+
+ // If you look into it, I don't actually think there is a working way to do this
+ // with only point math. So we use nearest_point instead.
+ Geom::Coord t = Geom::nearest_point(end_attach_point, *curve_start);
+
+ // it is just a dumb segment
+ // we have to do some shifting here because the value changed when we reduced the length
+ // of the previous segment.
+
+ subdivideCurve(curve_start, t, curve_start, temp);
+ trimmed_end.append(*temp);
+ if (temp) delete temp; temp = 0;
+
+ for (size_t j = (size - attach_end) + 1; j < size; ++j) {
+ trimmed_end.append(path_in[0] [j]);
+ }
+
+ path_out.append(*curve_start);
+ pathv_out.push_back(trimmed_start);
+ pathv_out.push_back(path_out);
+ pathv_out.push_back(trimmed_end);
+ return pathv_out;
+ }
+
+ pathv_out.push_back(trimmed_start);
+
+ // append almost all of the rest of the path, ignore the curves that the knot is past (we'll get to it in a minute)
+ path_out.append(*curve_start);
+
+ for (size_t k = loc + 1; k < (size - unsigned(attach_end)) - 1; ++k) {
+ path_out.append(path_in[0] [k]);
+ }
+
+ // deal with the last segment in a very similar fashion to the first
+ loc = size - attach_end;
+
+ Geom::Curve * curve_end = path_in[0] [loc].duplicate();
+
+ Geom::Coord t = Geom::nearest_point(end_attach_point, *curve_end);
+
+ subdivideCurve(curve_end, t, curve_end, temp);
+ trimmed_end.append(*temp);
+ if (temp) delete temp; temp = 0;
+
+ for (size_t j = (size - attach_end) + 1; j < size; ++j) {
+ trimmed_end.append(path_in[0] [j]);
+ }
+
+ path_out.append(*curve_end);
+ pathv_out.push_back(path_out);
+
+ pathv_out.push_back(trimmed_end);
+
+ if (curve_end) delete curve_end;
+ if (curve_start) delete curve_start;
+ return pathv_out;
+}
+
+
+/**
+ * Most of the below function is verbatim from Pattern Along Path. However, it needed a little
+ * tweaking to get it to work right in this case. Also, large portions of the effect have been
+ * stripped out as I deemed them unnecessary for the relative simplicity of this effect.
+ */
+Piecewise<D2<SBasis> > stretch_along(Piecewise<D2<SBasis> > pwd2_in, Geom::Path pattern, double prop_scale)
+{
+ using namespace Geom;
+
+ // Don't allow empty path parameter:
+ if ( pattern.empty() ) {
+ return pwd2_in;
+ }
+
+ /* Much credit should go to jfb and mgsloan of lib2geom development for the code below! */
+ Piecewise<D2<SBasis> > output;
+ std::vector<Piecewise<D2<SBasis> > > pre_output;
+
+ D2<Piecewise<SBasis> > patternd2 = make_cuts_independent(pattern.toPwSb());
+ Piecewise<SBasis> x0 = Piecewise<SBasis>(patternd2[0]);
+ Piecewise<SBasis> y0 = Piecewise<SBasis>(patternd2[1]);
+ OptInterval pattBndsX = bounds_exact(x0);
+ OptInterval pattBndsY = bounds_exact(y0);
+ if (pattBndsX && pattBndsY) {
+ x0 -= pattBndsX->min();
+ y0 -= pattBndsY->middle();
+
+ double xspace = 0;
+ double noffset = 0;
+ double toffset = 0;
+ // Prevent more than 90% overlap...
+ if (xspace < -pattBndsX->extent()*.9) {
+ xspace = -pattBndsX->extent()*.9;
+ }
+
+ y0+=noffset;
+
+ std::vector<Piecewise<D2<SBasis> > > paths_in;
+ paths_in = split_at_discontinuities(pwd2_in);
+
+ for (unsigned idx = 0; idx < paths_in.size(); idx++) {
+ Piecewise<D2<SBasis> > path_i = paths_in[idx];
+ Piecewise<SBasis> x = x0;
+ Piecewise<SBasis> y = y0;
+ Piecewise<D2<SBasis> > uskeleton = arc_length_parametrization(path_i,2,.1);
+ uskeleton = remove_short_cuts(uskeleton,.01);
+ Piecewise<D2<SBasis> > n = rot90(derivative(uskeleton));
+ n = force_continuity(remove_short_cuts(n,.1));
+
+ int nbCopies = 0;
+ double scaling = 1;
+ nbCopies = 1;
+ scaling = (uskeleton.domain().extent() - toffset)/pattBndsX->extent();
+
+ double pattWidth = pattBndsX->extent() * scaling;
+
+ if (scaling != 1.0) {
+ x*=scaling;
+ }
+ if ( false ) {
+ y*=(scaling*prop_scale);
+ } else {
+ if (prop_scale != 1.0) y *= prop_scale;
+ }
+ x += toffset;
+
+ double offs = 0;
+ for (int i=0; i<nbCopies; i++) {
+ if (false) {
+ Piecewise<D2<SBasis> > output_piece = compose(uskeleton,x+offs)+y*compose(n,x+offs);
+ std::vector<Piecewise<D2<SBasis> > > splited_output_piece = split_at_discontinuities(output_piece);
+ pre_output.insert(pre_output.end(), splited_output_piece.begin(), splited_output_piece.end() );
+ } else {
+ output.concat(compose(uskeleton,x+offs)+y*compose(n,x+offs));
+ }
+ offs+=pattWidth;
+ }
+ }
+ return output;
+ } else {
+ return pwd2_in;
+ }
+}
+
+void subdivideCurve(Geom::Curve * curve_in, Geom::Coord t, Geom::Curve *& val_first, Geom::Curve *& val_second)
+{
+ if (Geom::LineSegment* linear = dynamic_cast<Geom::LineSegment*>(curve_in)) {
+ // special case for line segments
+ std::pair<Geom::LineSegment, Geom::LineSegment> seg_pair = linear->subdivide(t);
+ val_first = seg_pair.first.duplicate();
+ val_second = seg_pair.second.duplicate();
+ } else {
+ // all other cases:
+ Geom::CubicBezier cubic = Geom::sbasis_to_cubicbezier(curve_in->toSBasis());
+ std::pair<Geom::CubicBezier, Geom::CubicBezier> cubic_pair = cubic.subdivide(t);
+ val_first = cubic_pair.first.duplicate();
+ val_second = cubic_pair.second.duplicate();
+ }
+}
+
+
+void LPETaperStroke::addKnotHolderEntities(KnotHolder *knotholder, SPDesktop *desktop, SPItem *item)
+{
+ KnotHolderEntity *e = new TpS::KnotHolderEntityAttachBegin(this);
+ e->create(desktop, item, knotholder, Inkscape::CTRL_TYPE_UNKNOWN, _("Start point of the taper"), SP_KNOT_SHAPE_CIRCLE);
+ knotholder->add(e);
+
+ KnotHolderEntity *f = new TpS::KnotHolderEntityAttachEnd(this);
+ f->create(desktop, item, knotholder, Inkscape::CTRL_TYPE_UNKNOWN, _("End point of the taper"), SP_KNOT_SHAPE_CIRCLE);
+ knotholder->add(f);
+}
+
+namespace TpS {
+
+void KnotHolderEntityAttachBegin::knot_set(Geom::Point const &p, Geom::Point const&/*origin*/, guint state)
+{
+ using namespace Geom;
+
+ LPETaperStroke* lpe = dynamic_cast<LPETaperStroke *>(_effect);
+
+ Geom::Point const s = snap_knot_position(p, state);
+
+ if (!SP_IS_SHAPE(lpe->sp_lpe_item)) {
+ printf("WARNING: LPEItem is not a path!\n");
+ return;
+ }
+
+ SPCurve* curve;
+ if (!(curve = SP_SHAPE(lpe->sp_lpe_item)->getCurve())) {
+ // oops
+ return;
+ }
+ // in case you are wondering, the above are simply sanity checks. we never want to actually
+ // use that object.
+
+ Geom::PathVector pathv = lpe->pathvector_before_effect;
+
+ Piecewise<D2<SBasis> > pwd2;
+ Geom::Path p_in = return_at_first_cusp(pathv[0]);
+ pwd2.concat(p_in.toPwSb());
+
+ double t0 = nearest_point(s, pwd2);
+ lpe->attach_start.param_set_value(t0);
+
+ // FIXME: this should not directly ask for updating the item. It should write to SVG, which triggers updating.
+ sp_lpe_item_update_patheffect(SP_LPE_ITEM(item), false, true);
+}
+void KnotHolderEntityAttachEnd::knot_set(Geom::Point const &p, Geom::Point const& /*origin*/, guint state)
+{
+ using namespace Geom;
+
+ LPETaperStroke* lpe = dynamic_cast<LPETaperStroke *>(_effect);
+
+ Geom::Point const s = snap_knot_position(p, state);
+
+ if (!SP_IS_SHAPE(lpe->sp_lpe_item) ) {
+ printf("WARNING: LPEItem is not a path!\n");
+ return;
+ }
+
+ SPCurve* curve;
+ if ( !(curve = SP_SHAPE(lpe->sp_lpe_item)->getCurve()) ) {
+ // oops
+ return;
+ }
+ Geom::PathVector pathv = lpe->pathvector_before_effect;
+ Geom::Path p_in = return_at_first_cusp(pathv[0].reverse());
+ Piecewise<D2<SBasis> > pwd2 = p_in.toPwSb();
+
+ double t0 = nearest_point(s, pwd2);
+ lpe->attach_end.param_set_value(t0);
+
+ sp_lpe_item_update_patheffect (SP_LPE_ITEM(item), false, true);
+}
+
+Geom::Point KnotHolderEntityAttachBegin::knot_get() const
+{
+ LPETaperStroke const * lpe = dynamic_cast<LPETaperStroke const*> (_effect);
+ return lpe->start_attach_point;
+}
+
+Geom::Point KnotHolderEntityAttachEnd::knot_get() const
+{
+ LPETaperStroke const * lpe = dynamic_cast<LPETaperStroke const*> (_effect);
+ return lpe->end_attach_point;
+}
+
+} // namespace TpS
+} // namespace LivePathEffect
+} // namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8 :
diff --git a/src/live_effects/lpe-taperstroke.h b/src/live_effects/lpe-taperstroke.h
new file mode 100644
index 000000000..88604486e
--- /dev/null
+++ b/src/live_effects/lpe-taperstroke.h
@@ -0,0 +1,72 @@
+/** @file
+ * @brief Taper Stroke path effect (meant as a replacement for using Power Strokes for tapering)
+ */
+/* Authors:
+ * Liam P White <inkscapebrony@gmail.com>
+ * Copyright (C) 2014 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifndef INKSCAPE_LPE_TAPERSTROKE_H
+#define INKSCAPE_LPE_TAPERSTROKE_H
+
+#include "live_effects/parameter/enum.h"
+#include "live_effects/effect.h"
+#include "live_effects/parameter/parameter.h"
+#include "live_effects/parameter/vector.h"
+
+namespace Inkscape {
+namespace LivePathEffect {
+
+namespace TpS {
+// we need a separate namespace to avoid clashes with other LPEs
+class KnotHolderEntityAttachBegin;
+class KnotHolderEntityAttachEnd;
+}
+
+class LPETaperStroke : public Effect {
+public:
+ LPETaperStroke(LivePathEffectObject *lpeobject);
+ virtual ~LPETaperStroke() {}
+
+ virtual void doOnApply(SPLPEItem const* lpeitem);
+ virtual void doOnRemove(SPLPEItem const* lpeitem);
+
+ virtual Geom::PathVector doEffect_path (Geom::PathVector const& path_in);
+ Geom::PathVector doEffect_simplePath(Geom::PathVector const& path_in);
+
+ virtual void addKnotHolderEntities(KnotHolder * knotholder, SPDesktop * desktop, SPItem * item);
+
+ friend class TpS::KnotHolderEntityAttachBegin;
+ friend class TpS::KnotHolderEntityAttachEnd;
+private:
+ ScalarParam line_width;
+ ScalarParam attach_start;
+ ScalarParam attach_end;
+ ScalarParam smoothing;
+ EnumParam<unsigned> join_type;
+ ScalarParam miter_limit;
+
+ Geom::Point start_attach_point;
+ Geom::Point end_attach_point;
+
+ LPETaperStroke(const LPETaperStroke&);
+ LPETaperStroke& operator=(const LPETaperStroke&);
+};
+
+} //namespace LivePathEffect
+} //namespace Inkscape
+
+#endif
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8 :
diff --git a/src/live_effects/lpe-vonkoch.cpp b/src/live_effects/lpe-vonkoch.cpp
index c0050fa60..b52816c87 100644
--- a/src/live_effects/lpe-vonkoch.cpp
+++ b/src/live_effects/lpe-vonkoch.cpp
@@ -4,11 +4,10 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include <cstdio>
+#include "live_effects/lpe-vonkoch.h"
#include <glibmm/i18n.h>
-#include "live_effects/lpe-vonkoch.h"
#include <2geom/transforms.h>
//using std::vector;
@@ -133,8 +132,8 @@ LPEVonKoch::doEffect_path (std::vector<Geom::Path> const & path_in)
int path_in_complexity = 0;
for (unsigned k = 0; k < path_in.size(); k++){
path_in_complexity+=path_in[k].size();
- }
- double complexity = std::pow(transforms.size(),nbgenerations)*path_in_complexity;
+ }
+ double complexity = std::pow(transforms.size(), nbgenerations) * path_in_complexity;
if (drawall.get_value()){
int k = transforms.size();
if(k>1){
@@ -142,8 +141,6 @@ LPEVonKoch::doEffect_path (std::vector<Geom::Path> const & path_in)
}else{
complexity = nbgenerations*k*path_in_complexity;
}
- }else{
- complexity = std::pow(transforms.size(),nbgenerations)*path_in_complexity;
}
if (complexity > double(maxComplexity)){
g_warning("VonKoch lpe's output too complex. Effect bypassed.");
@@ -265,6 +262,9 @@ LPEVonKoch::doBeforeEffect (SPLPEItem const* lpeitem)
tmp_pathv.push_back(tmp_path);
ref_path.set_new_value(tmp_pathv,true);
}
+ SPLPEItem * item = const_cast<SPLPEItem*>(lpeitem);
+ item->apply_to_clippath(item);
+ item->apply_to_mask(item);
}
diff --git a/src/live_effects/lpeobject-reference.h b/src/live_effects/lpeobject-reference.h
index b1ba1ee4e..374e715ec 100644
--- a/src/live_effects/lpeobject-reference.h
+++ b/src/live_effects/lpeobject-reference.h
@@ -9,10 +9,10 @@
* Released under GNU GPL, read the file 'COPYING' for more information.
*/
-#include <uri-references.h>
-#include <stddef.h>
#include <sigc++/sigc++.h>
+#include "uri-references.h"
+
namespace Inkscape {
namespace XML {
class Node;
@@ -33,7 +33,7 @@ public:
SPObject *owner;
// concerning the LPEObject that is refered to:
- gchar *lpeobject_href;
+ char *lpeobject_href;
Inkscape::XML::Node *lpeobject_repr;
LivePathEffectObject *lpeobject;
diff --git a/src/live_effects/lpeobject.h b/src/live_effects/lpeobject.h
index 9700024fe..2e62707e3 100644
--- a/src/live_effects/lpeobject.h
+++ b/src/live_effects/lpeobject.h
@@ -47,9 +47,9 @@ protected:
virtual void build(SPDocument* doc, Inkscape::XML::Node* repr);
virtual void release();
- virtual void set(unsigned int key, const gchar* value);
+ virtual void set(unsigned int key, char const* value);
- virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, guint flags);
+ virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, unsigned int flags);
};
#endif
diff --git a/src/live_effects/parameter/Makefile_insert b/src/live_effects/parameter/Makefile_insert
index efdda686a..f990f41c7 100644
--- a/src/live_effects/parameter/Makefile_insert
+++ b/src/live_effects/parameter/Makefile_insert
@@ -11,6 +11,8 @@ ink_common_sources += \
live_effects/parameter/random.h \
live_effects/parameter/point.cpp \
live_effects/parameter/point.h \
+ live_effects/parameter/pointreseteable.cpp \
+ live_effects/parameter/pointreseteable.h \
live_effects/parameter/enum.h \
live_effects/parameter/path-reference.cpp \
live_effects/parameter/path-reference.h \
@@ -18,10 +20,18 @@ ink_common_sources += \
live_effects/parameter/path.h \
live_effects/parameter/originalpath.cpp \
live_effects/parameter/originalpath.h \
+ live_effects/parameter/originalpatharray.cpp \
+ live_effects/parameter/originalpatharray.h \
live_effects/parameter/powerstrokepointarray.cpp \
live_effects/parameter/powerstrokepointarray.h \
+ live_effects/parameter/filletchamferpointarray.cpp \
+ live_effects/parameter/filletchamferpointarray.h \
live_effects/parameter/text.cpp \
live_effects/parameter/text.h \
+ live_effects/parameter/transformedpoint.cpp \
+ live_effects/parameter/transformedpoint.h \
+ live_effects/parameter/togglebutton.cpp \
+ live_effects/parameter/togglebutton.h \
live_effects/parameter/unit.cpp \
live_effects/parameter/unit.h \
live_effects/parameter/vector.cpp \
diff --git a/src/live_effects/parameter/bool.h b/src/live_effects/parameter/bool.h
index fafb1beca..b45eeb0b3 100644
--- a/src/live_effects/parameter/bool.h
+++ b/src/live_effects/parameter/bool.h
@@ -4,7 +4,7 @@
/*
* Inkscape::LivePathEffectParameters
*
-* Copyright (C) Johan Engelen 2007 <j.b.c.engelen@utwente.nl>
+ * Copyright (C) Johan Engelen 2007 <j.b.c.engelen@utwente.nl>
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
diff --git a/src/live_effects/parameter/filletchamferpointarray.cpp b/src/live_effects/parameter/filletchamferpointarray.cpp
new file mode 100644
index 000000000..7d8c8e9b0
--- /dev/null
+++ b/src/live_effects/parameter/filletchamferpointarray.cpp
@@ -0,0 +1,881 @@
+/*
+ * Copyright (C) Jabiertxo Arraiza Cenoz <jabier.arraiza@marker.es>
+ * Special thanks to Johan Engelen for the base of the effect -powerstroke-
+ * Also to ScislaC for point me to the idea
+ * Also su_v for his construvtive feedback and time
+ * and finaly to Liam P. White for his big help on coding, that save me a lot of
+ * hours
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <2geom/piecewise.h>
+#include <2geom/sbasis-to-bezier.h>
+#include <2geom/sbasis-geometric.h>
+#include <2geom/svg-elliptical-arc.h>
+#include <2geom/line.h>
+#include <2geom/path-intersection.h>
+
+#include "ui/dialog/lpe-fillet-chamfer-properties.h"
+#include "live_effects/parameter/filletchamferpointarray.h"
+#include "live_effects/effect.h"
+#include "svg/svg.h"
+#include "svg/stringstream.h"
+#include "knotholder.h"
+#include "sp-lpe-item.h"
+#include "selection.h"
+
+// needed for on-canvas editting:
+#include "desktop.h"
+#include "live_effects/lpeobject.h"
+#include "helper/geom-nodetype.h"
+#include "helper/geom-curves.h"
+#include "ui/tools/node-tool.h"
+
+// TODO due to internal breakage in glibmm headers,
+// this has to be included last.
+#include <glibmm/i18n.h>
+
+
+using namespace Geom;
+
+namespace Inkscape {
+
+namespace LivePathEffect {
+
+FilletChamferPointArrayParam::FilletChamferPointArrayParam(
+ const Glib::ustring &label, const Glib::ustring &tip,
+ const Glib::ustring &key, Inkscape::UI::Widget::Registry *wr,
+ Effect *effect)
+ : ArrayParam<Point>(label, tip, key, wr, effect, 0)
+{
+ knot_shape = SP_KNOT_SHAPE_DIAMOND;
+ knot_mode = SP_KNOT_MODE_XOR;
+ knot_color = 0x00ff0000;
+}
+
+FilletChamferPointArrayParam::~FilletChamferPointArrayParam() {}
+
+Gtk::Widget *FilletChamferPointArrayParam::param_newWidget()
+{
+ return NULL;
+ /*
+ Inkscape::UI::Widget::RegisteredTransformedPoint * pointwdg =
+ Gtk::manage(
+ new Inkscape::UI::Widget::RegisteredTransformedPoint(
+ param_label,
+ param_tooltip,
+ param_key,
+ *param_wr,
+ param_effect->getRepr(),
+ param_effect->getSPDoc()
+ ) );
+ // TODO: fix to get correct desktop (don't use SP_ACTIVE_DESKTOP)
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ Affine transf = desktop->doc2dt();
+ pointwdg->setTransform(transf);
+ pointwdg->setValue( *this );
+ pointwdg->clearProgrammatically();
+ pointwdg->set_undo_parameters(SP_VERB_DIALOG_LIVE_PATH_EFFECT,
+ _("Change point parameter"));
+
+ Gtk::HBox * hbox = Gtk::manage( new Gtk::HBox() );
+ static_cast<Gtk::HBox*>(hbox)->pack_start(*pointwdg, true, true);
+ static_cast<Gtk::HBox*>(hbox)->show_all_children();
+
+ return dynamic_cast<Gtk::Widget *> (hbox);
+ */
+}
+
+void
+FilletChamferPointArrayParam::param_transform_multiply(Affine const &postmul,
+ bool /*set*/)
+{
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+
+ if (prefs->getBool("/options/transform/rectcorners", true) &&
+ _vector[1][X] <= 0) {
+ std::vector<Geom::Point> result;
+ for (std::vector<Point>::const_iterator point_it = _vector.begin();
+ point_it != _vector.end(); ++point_it) {
+ Coord A =
+ (*point_it)[X] * ((postmul.expansionX() + postmul.expansionY()) / 2);
+ result.push_back(Point(A, (*point_it)[Y]));
+ }
+ param_set_and_write_new_value(result);
+ }
+
+ // param_set_and_write_new_value( (*this) * postmul );
+}
+
+/** call this method to recalculate the controlpoints such that they stay at the
+ * same location relative to the new path. Useful after adding/deleting nodes to
+ * the path.*/
+void FilletChamferPointArrayParam::recalculate_controlpoints_for_new_pwd2(
+ Piecewise<D2<SBasis> > const &pwd2_in)
+{
+ if (!last_pwd2.empty()) {
+ PathVector const pathv =
+ path_from_piecewise(remove_short_cuts(pwd2_in, 0.1), 0.001);
+ PathVector last_pathv =
+ path_from_piecewise(remove_short_cuts(last_pwd2, 0.1), 0.001);
+ std::vector<Point> result;
+ unsigned long counter = 0;
+ unsigned long counterPaths = 0;
+ unsigned long counterCurves = 0;
+ long offset = 0;
+ long offsetPaths = 0;
+ Geom::NodeType nodetype;
+ for (PathVector::const_iterator path_it = pathv.begin();
+ path_it != pathv.end(); ++path_it) {
+ if (path_it->empty()) {
+ counterPaths++;
+ counter++;
+ continue;
+ }
+ Geom::Path::const_iterator curve_it1 = path_it->begin();
+ Geom::Path::const_iterator curve_it2 = ++(path_it->begin());
+ Geom::Path::const_iterator curve_endit = path_it->end_default();
+ if (path_it->closed() && path_it->back_closed().isDegenerate()) {
+ const Curve &closingline = path_it->back_closed();
+ if (are_near(closingline.initialPoint(), closingline.finalPoint())) {
+ curve_endit = path_it->end_open();
+ }
+ }
+ counterCurves = 0;
+ while (curve_it1 != curve_endit) {
+ //if start a path get node type
+ if (counterCurves == 0) {
+ if (path_it->closed()) {
+ if (path_it->back_closed().isDegenerate()) {
+ nodetype = get_nodetype(path_it->back_open(), *curve_it1);
+ } else {
+ nodetype = get_nodetype(path_it->back_closed(), *curve_it1);
+ }
+ } else {
+ nodetype = NODE_NONE;
+ }
+ } else {
+ //check node type also whith straight lines because get_nodetype
+ //return non cusp node in a node inserted inside a straight line
+ //todo: if the path remove some nodes whith the result of a straight
+ //line but with handles, the node inserted into dont fire the knot
+ // because is not handle as cusp node by get_nodetype function
+ bool this_is_line = true;
+ bool next_is_line = is_straight_curve(*curve_it1);
+ this_is_line = is_straight_curve((*path_it)[counterCurves - 1]);
+ nodetype = get_nodetype((*path_it)[counterCurves - 1], *curve_it1);
+ if (this_is_line || next_is_line) {
+ nodetype = NODE_CUSP;
+ }
+ }
+ if (last_pathv.size() > pathv.size() ||
+ (last_pathv.size() > counterPaths &&
+ last_pathv[counterPaths].size() > counter - offset &&
+ !are_near(curve_it1->initialPoint(),
+ last_pathv[counterPaths][counter - offset].initialPoint(),
+ 0.1))) {
+ if ( curve_it2 == curve_endit) {
+ if (last_pathv[counterPaths].size() != pathv[counterPaths].size()) {
+ offset = (last_pathv[counterPaths].size() - pathv[counterPaths].size()) * -1;
+ } else {
+ offset = 0;
+ }
+ offsetPaths += offset;
+ offset = offsetPaths;
+ } else if (counterCurves == 0 && last_pathv.size() <= pathv.size() &&
+ counter - offset <= last_pathv[counterPaths].size() &&
+ are_near(curve_it1->initialPoint(),
+ last_pathv[counterPaths].finalPoint(), 0.1) &&
+ !last_pathv[counterPaths].closed()) {
+ long e = counter - offset + 1;
+ std::vector<Point> tmp = _vector;
+ for (unsigned long i =
+ last_pathv[counterPaths].size() + counter - offset;
+ i > counterCurves - offset + 1; i--) {
+
+ if (tmp[i - 1][X] > 0) {
+ double fractpart, intpart;
+ fractpart = modf(tmp[i - 1][X], &intpart);
+ _vector[e] = Point(e + fractpart, tmp[i - 1][Y]);
+ } else {
+ _vector[e] = Point(tmp[i - 1][X], tmp[i - 1][Y]);
+ }
+ e++;
+ }
+ //delete temp vector
+ std::vector<Point>().swap(tmp);
+ if (last_pathv.size() > counterPaths) {
+ last_pathv[counterPaths] = last_pathv[counterPaths].reverse();
+ }
+ } else {
+ if (last_pathv.size() > counterPaths) {
+ if (last_pathv[counterPaths].size() <
+ pathv[counterPaths].size()) {
+ offset++;
+ } else if (last_pathv[counterPaths].size() >
+ pathv[counterPaths].size()) {
+ offset--;
+ continue;
+ }
+ } else {
+ offset++;
+ }
+ }
+ double xPos = 0;
+ if (_vector[1][X] > 0) {
+ xPos = nearest_point(curve_it1->initialPoint(), pwd2_in);
+ }
+ if (nodetype == NODE_CUSP) {
+ result.push_back(Point(xPos, 1));
+ } else {
+ result.push_back(Point(xPos, 0));
+ }
+ } else {
+ double xPos = _vector[counter - offset][X];
+ if (_vector.size() <= (unsigned)(counter - offset)) {
+ if (_vector[1][X] > 0) {
+ xPos = nearest_point(curve_it1->initialPoint(), pwd2_in);
+ } else {
+ xPos = 0;
+ }
+ }
+ if (nodetype == NODE_CUSP) {
+ double vectorY = _vector[counter - offset][Y];
+ if (_vector.size() <= (unsigned)(counter - offset) || vectorY == 0) {
+ vectorY = 1;
+ }
+ result.push_back(Point(xPos, vectorY));
+ } else {
+ if (_vector[1][X] < 0) {
+ xPos = 0;
+ }
+ result.push_back(Point(floor(xPos), 0));
+ }
+ }
+ ++curve_it1;
+ if (curve_it2 != curve_endit) {
+ ++curve_it2;
+ }
+ counter++;
+ counterCurves++;
+ }
+ counterPaths++;
+ }
+ _vector = result;
+ write_to_SVG();
+ }
+}
+
+void FilletChamferPointArrayParam::recalculate_knots(
+ Piecewise<D2<SBasis> > const &pwd2_in)
+{
+ bool change = false;
+ PathVector pathv = path_from_piecewise(pwd2_in, 0.001);
+ if (!pathv.empty()) {
+ std::vector<Point> result;
+ int counter = 0;
+ int counterCurves = 0;
+ Geom::NodeType nodetype;
+ for (PathVector::const_iterator path_it = pathv.begin();
+ path_it != pathv.end(); ++path_it) {
+ if (path_it->empty()) {
+ counter++;
+ continue;
+ }
+ Geom::Path::const_iterator curve_it1 = path_it->begin();
+ Geom::Path::const_iterator curve_it2 = ++(path_it->begin());
+ Geom::Path::const_iterator curve_endit = path_it->end_default();
+ if (path_it->closed() && path_it->back_closed().isDegenerate()) {
+ const Curve &closingline = path_it->back_closed();
+ if (are_near(closingline.initialPoint(), closingline.finalPoint())) {
+ curve_endit = path_it->end_open();
+ }
+ }
+ counterCurves = 0;
+ while (curve_it1 != curve_endit) {
+ //if start a path get node type
+ if (counterCurves == 0) {
+ if (path_it->closed()) {
+ if (path_it->back_closed().isDegenerate()) {
+ nodetype = get_nodetype(path_it->back_open(), *curve_it1);
+ } else {
+ nodetype = get_nodetype(path_it->back_closed(), *curve_it1);
+ }
+ } else {
+ nodetype = NODE_NONE;
+ }
+ } else {
+ bool this_is_line = true;
+ bool next_is_line = is_straight_curve(*curve_it1);
+ this_is_line = is_straight_curve((*path_it)[counterCurves - 1]);
+ nodetype = get_nodetype((*path_it)[counterCurves - 1], *curve_it1);
+ if (this_is_line || next_is_line) {
+ nodetype = NODE_CUSP;
+ }
+ }
+ if (nodetype == NODE_CUSP) {
+ double vectorY = _vector[counter][Y];
+ if (vectorY == 0) {
+ vectorY = 1;
+ change = true;
+ }
+ result.push_back(Point(_vector[counter][X], vectorY));
+ } else {
+ double xPos = floor(_vector[counter][X]);
+ if (_vector[1][X] < 0) {
+ xPos = 0;
+ }
+ double vectorY = _vector[counter][Y];
+ if (vectorY != 0) {
+ change = true;
+ }
+ result.push_back(Point(xPos, 0));
+ }
+ ++curve_it1;
+ counter++;
+ if (curve_it2 != curve_endit) {
+ ++curve_it2;
+ }
+ counterCurves++;
+ }
+ }
+ if (change) {
+ _vector = result;
+ write_to_SVG();
+ }
+ }
+}
+
+void FilletChamferPointArrayParam::set_pwd2(
+ Piecewise<D2<SBasis> > const &pwd2_in,
+ Piecewise<D2<SBasis> > const &pwd2_normal_in)
+{
+ last_pwd2 = pwd2_in;
+ last_pwd2_normal = pwd2_normal_in;
+}
+
+void FilletChamferPointArrayParam::set_document_unit(Glib::ustring const * value_document_unit)
+{
+ documentUnit = value_document_unit;
+}
+
+void FilletChamferPointArrayParam::set_helper_size(int hs)
+{
+ helper_size = hs;
+}
+
+void FilletChamferPointArrayParam::set_chamfer_steps(int value_chamfer_steps)
+{
+ chamfer_steps = value_chamfer_steps;
+}
+
+void FilletChamferPointArrayParam::set_use_distance(bool use_knot_distance )
+{
+ use_distance = use_knot_distance;
+}
+
+void FilletChamferPointArrayParam::set_unit(const gchar *abbr)
+{
+ unit = abbr;
+}
+
+void FilletChamferPointArrayParam::updateCanvasIndicators()
+{
+ std::vector<Point> ts = data();
+ hp.clear();
+ unsigned int i = 0;
+ for (std::vector<Point>::const_iterator point_it = ts.begin();
+ point_it != ts.end(); ++point_it) {
+ double Xvalue = to_time(i, (*point_it)[X]) -i;
+ if (Xvalue == 0) {
+ i++;
+ continue;
+ }
+ Geom::Point ptA = last_pwd2[i].valueAt(Xvalue);
+ Geom::Point derivA = unit_vector(derivative(last_pwd2[i]).valueAt(Xvalue));
+ Geom::Rotate rot(Geom::Rotate::from_degrees(-90));
+ derivA = derivA * rot;
+ Geom::Point C = ptA - derivA * helper_size;
+ Geom::Point D = ptA + derivA * helper_size;
+ Geom::Ray ray1(C, D);
+ char const * svgd = "M 1,0.25 0.5,0 1,-0.25 M 1,0.5 0,0 1,-0.5";
+ Geom::PathVector pathv = sp_svg_read_pathv(svgd);
+ Geom::Affine aff = Geom::Affine();
+ aff *= Geom::Scale(helper_size);
+ aff *= Geom::Rotate(ray1.angle() - deg_to_rad(270));
+ pathv *= aff;
+ pathv += last_pwd2[i].valueAt(Xvalue);
+ hp.push_back(pathv[0]);
+ hp.push_back(pathv[1]);
+ i++;
+ }
+}
+
+void FilletChamferPointArrayParam::addCanvasIndicators(
+ SPLPEItem const */*lpeitem*/, std::vector<Geom::PathVector> &hp_vec)
+{
+ hp_vec.push_back(hp);
+}
+
+double FilletChamferPointArrayParam::rad_to_len(int index, double rad)
+{
+ double len = 0;
+ std::vector<Geom::Path> subpaths = path_from_piecewise(last_pwd2, 0.1);
+ std::pair<std::size_t, std::size_t> positions = get_positions(index, subpaths);
+ D2<SBasis> A = last_pwd2[last_index(index, subpaths)];
+ if(positions.second != 0){
+ A = last_pwd2[index-1];
+ }else{
+ if(!subpaths[positions.first].closed()){
+ return len;
+ }
+ }
+ D2<SBasis> B = last_pwd2[index];
+ Piecewise<D2<SBasis> > offset_curve0 = Piecewise<D2<SBasis> >(A)+rot90(unitVector(derivative(A)))*(rad);
+ Piecewise<D2<SBasis> > offset_curve1 = Piecewise<D2<SBasis> >(B)+rot90(unitVector(derivative(B)))*(rad);
+ Geom::Path p0 = path_from_piecewise(offset_curve0, 0.1)[0];
+ Geom::Path p1 = path_from_piecewise(offset_curve1, 0.1)[0];
+ Geom::Crossings cs = Geom::crossings(p0, p1);
+ if(cs.size() > 0){
+ Point cp =p0(cs[0].ta);
+ double p0pt = nearest_point(cp, B);
+ len = time_to_len(index,p0pt);
+ } else {
+ if(rad < 0){
+ len = rad_to_len(index, rad * -1);
+ }
+ }
+ return len;
+}
+
+double FilletChamferPointArrayParam::len_to_rad(int index, double len)
+{
+ double rad = 0;
+ double tmp_len = _vector[index][X];
+ _vector[index] = Geom::Point(len,_vector[index][Y]);
+ std::vector<Geom::Path> subpaths = path_from_piecewise(last_pwd2, 0.1);
+ std::pair<std::size_t, std::size_t> positions = get_positions(index, subpaths);
+ Piecewise<D2<SBasis> > u;
+ u.push_cut(0);
+ u.push(last_pwd2[last_index(index, subpaths)], 1);
+ Geom::Curve * A = path_from_piecewise(u, 0.1)[0][0].duplicate();
+ Geom::Curve * B = subpaths[positions.first][positions.second].duplicate();
+ std::vector<double> times;
+ if(positions.second != 0){
+ A = subpaths[positions.first][positions.second-1].duplicate();
+ times = get_times(index-1, subpaths, false);
+ }else{
+ if(!subpaths[positions.first].closed()){
+ return rad;
+ }
+ times = get_times(last_index(index, subpaths), subpaths, true);
+ }
+ _vector[index] = Geom::Point(tmp_len,_vector[index][Y]);
+ Geom::Point startArcPoint = A->toSBasis().valueAt(times[1]);
+ Geom::Point endArcPoint = B->toSBasis().valueAt(times[2]);
+ Curve *knotCurve1 = A->portion(times[0], times[1]);
+ Curve *knotCurve2 = B->portion(times[2], 1);
+ Geom::CubicBezier const *cubic1 = dynamic_cast<Geom::CubicBezier const *>(&*knotCurve1);
+ Ray ray1(startArcPoint, A->finalPoint());
+ if (cubic1) {
+ ray1.setPoints((*cubic1)[2], startArcPoint);
+ }
+ Geom::CubicBezier const *cubic2 = dynamic_cast<Geom::CubicBezier const *>(&*knotCurve2);
+ Ray ray2(B->initialPoint(), endArcPoint);
+ if (cubic2) {
+ ray2.setPoints(endArcPoint, (*cubic2)[1]);
+ }
+ bool ccwToggle = cross(A->finalPoint() - startArcPoint, endArcPoint - startArcPoint) < 0;
+ double distanceArc = Geom::distance(startArcPoint,middle_point(startArcPoint,endArcPoint));
+ double angleBetween = angle_between(ray1, ray2, ccwToggle);
+ rad = distanceArc/sin(angleBetween/2.0);
+ return rad * -1;
+}
+
+std::vector<double> FilletChamferPointArrayParam::get_times(int index, std::vector<Geom::Path> subpaths, bool last)
+{
+ const double tolerance = 0.001;
+ const double gapHelper = 0.00001;
+ std::pair<std::size_t, std::size_t> positions = get_positions(index, subpaths);
+ Curve *curve_it1;
+ curve_it1 = subpaths[positions.first][positions.second].duplicate();
+ Coord it1_length = (*curve_it1).length(tolerance);
+ double time_it1, time_it2, time_it1_B, intpart;
+ time_it1 = modf(to_time(index, _vector[index][X]), &intpart);
+ if (_vector[index][Y] == 0) {
+ time_it1 = 0;
+ }
+ double resultLenght = 0;
+ time_it1_B = 1;
+ if (subpaths[positions.first].closed() && last) {
+ time_it2 = modf(to_time(index - positions.second , _vector[index - positions.second ][X]), &intpart);
+ resultLenght = it1_length + to_len(index - positions.second, _vector[index - positions.second ][X]);
+ } else if (!subpaths[positions.first].closed() && last){
+ time_it2 = 0;
+ resultLenght = 0;
+ } else {
+ time_it2 = modf(to_time(index + 1, _vector[index + 1][X]), &intpart);
+ resultLenght = it1_length + to_len( index + 1, _vector[index + 1][X]);
+ }
+ if (resultLenght > 0 && time_it2 != 0) {
+ time_it1_B = modf(to_time(index, -resultLenght), &intpart);
+ } else {
+ if (time_it2 == 0) {
+ time_it1_B = 1;
+ } else {
+ time_it1_B = gapHelper;
+ }
+ }
+
+ if ((subpaths[positions.first].closed() && last && _vector[index - positions.second][Y] == 0) || (subpaths[positions.first].size() > positions.second + 1 && _vector[index + 1][Y] == 0)) {
+ time_it1_B = 1;
+ time_it2 = 0;
+ }
+ if (time_it1_B < time_it1) {
+ time_it1_B = time_it1 + gapHelper;
+ }
+ std::vector<double> out;
+ out.push_back(time_it1);
+ out.push_back(time_it1_B);
+ out.push_back(time_it2);
+ return out;
+}
+
+std::pair<std::size_t, std::size_t> FilletChamferPointArrayParam::get_positions(int index, std::vector<Geom::Path> subpaths)
+{
+ int counter = -1;
+ std::size_t first = 0;
+ std::size_t second = 0;
+ for (PathVector::const_iterator path_it = subpaths.begin(); path_it != subpaths.end(); ++path_it) {
+ if (path_it->empty())
+ continue;
+ Geom::Path::const_iterator curve_it1 = path_it->begin();
+ Geom::Path::const_iterator curve_endit = path_it->end_default();
+ if (path_it->closed()) {
+ const Geom::Curve &closingline = path_it->back_closed();
+ // the closing line segment is always of type
+ // Geom::LineSegment.
+ if (are_near(closingline.initialPoint(), closingline.finalPoint())) {
+ // closingline.isDegenerate() did not work, because it only checks for
+ // *exact* zero length, which goes wrong for relative coordinates and
+ // rounding errors...
+ // the closing line segment has zero-length. So stop before that one!
+ curve_endit = path_it->end_open();
+ }
+ }
+ first++;
+ second = 0;
+ while (curve_it1 != curve_endit) {
+ counter++;
+ second++;
+ if(counter == index){
+ break;
+ }
+ ++curve_it1;
+ }
+ if(counter == index){
+ break;
+ }
+ }
+ first--;
+ second--;
+ std::pair<std::size_t, std::size_t> out(first, second);
+ return out;
+}
+
+int FilletChamferPointArrayParam::last_index(int index, std::vector<Geom::Path> subpaths)
+{
+ int counter = -1;
+ bool inSubpath = false;
+ for (PathVector::const_iterator path_it = subpaths.begin(); path_it != subpaths.end(); ++path_it) {
+ if (path_it->empty())
+ continue;
+ Geom::Path::const_iterator curve_it1 = path_it->begin();
+ Geom::Path::const_iterator curve_endit = path_it->end_default();
+ if (path_it->closed()) {
+ const Geom::Curve &closingline = path_it->back_closed();
+ if (are_near(closingline.initialPoint(), closingline.finalPoint())) {
+ curve_endit = path_it->end_open();
+ }
+ }
+ while (curve_it1 != curve_endit) {
+ counter++;
+ if(counter == index){
+ inSubpath = true;
+ }
+ ++curve_it1;
+ }
+ if(inSubpath){
+ break;
+ }
+ }
+ if(!inSubpath){
+ counter = -1;
+ }
+ return counter;
+}
+
+
+double FilletChamferPointArrayParam::len_to_time(int index, double len)
+{
+ double t = 0;
+ if (last_pwd2.size() > (unsigned) index) {
+ if (len != 0) {
+ if (last_pwd2[index][0].degreesOfFreedom() != 2) {
+ Piecewise<D2<SBasis> > u;
+ u.push_cut(0);
+ u.push(last_pwd2[index], 1);
+ std::vector<double> t_roots = roots(arcLengthSb(u) - std::abs(len));
+ if (t_roots.size() > 0) {
+ t = t_roots[0];
+ }
+ } else {
+ double lenghtPart = 0;
+ if (last_pwd2.size() > (unsigned) index) {
+ lenghtPart = length(last_pwd2[index], EPSILON);
+ }
+ if (std::abs(len) < lenghtPart && lenghtPart != 0) {
+ t = std::abs(len) / lenghtPart;
+ }
+ }
+ }
+ t = double(index) + t;
+ } else {
+ t = double(last_pwd2.size() - 1);
+ }
+
+ return t;
+}
+
+double FilletChamferPointArrayParam::time_to_len(int index, double time)
+{
+ double intpart;
+ double len = 0;
+ time = modf(time, &intpart);
+ double lenghtPart = 0;
+ if (last_pwd2.size() <= (unsigned) index || time == 0) {
+ return len;
+ }
+ if (last_pwd2[index][0].degreesOfFreedom() != 2) {
+ Piecewise<D2<SBasis> > u;
+ u.push_cut(0);
+ u.push(last_pwd2[index], 1);
+ u = portion(u, 0, time);
+ return length(u, 0.001) * -1;
+ }
+ lenghtPart = length(last_pwd2[index], EPSILON);
+ return (time * lenghtPart) * -1;
+}
+
+double FilletChamferPointArrayParam::to_time(int index, double A)
+{
+ if (A > 0) {
+ return A;
+ } else {
+ return len_to_time(index, A);
+ }
+}
+
+double FilletChamferPointArrayParam::to_len(int index, double A)
+{
+ if (A > 0) {
+ return time_to_len(index, A);
+ } else {
+ return A;
+ }
+}
+
+void FilletChamferPointArrayParam::set_oncanvas_looks(SPKnotShapeType shape,
+ SPKnotModeType mode,
+ guint32 color)
+{
+ knot_shape = shape;
+ knot_mode = mode;
+ knot_color = color;
+}
+
+FilletChamferPointArrayParamKnotHolderEntity::
+FilletChamferPointArrayParamKnotHolderEntity(
+ FilletChamferPointArrayParam *p, unsigned int index)
+ : _pparam(p), _index(index) {}
+
+void FilletChamferPointArrayParamKnotHolderEntity::knot_set(Point const &p,
+ Point const &/*origin*/,
+ guint state)
+{
+ using namespace Geom;
+
+ if (!valid_index(_index)) {
+ return;
+ }
+ Piecewise<D2<SBasis> > const &pwd2 = _pparam->get_pwd2();
+ double t = nearest_point(p, pwd2[_index]);
+ Geom::Point const s = snap_knot_position(pwd2[_index].valueAt(t), state);
+ t = nearest_point(s, pwd2[_index]);
+ if (t == 1) {
+ t = 0.9999;
+ }
+ t += _index;
+
+ if (_pparam->_vector.at(_index)[X] <= 0) {
+ _pparam->_vector.at(_index) =
+ Point(_pparam->time_to_len(_index, t), _pparam->_vector.at(_index)[Y]);
+ } else {
+ _pparam->_vector.at(_index) = Point(t, _pparam->_vector.at(_index)[Y]);
+ }
+ sp_lpe_item_update_patheffect(SP_LPE_ITEM(item), false, false);
+}
+
+Point FilletChamferPointArrayParamKnotHolderEntity::knot_get() const
+{
+ using namespace Geom;
+
+ if (!valid_index(_index)) {
+ return Point(infinity(), infinity());
+ }
+
+ Piecewise<D2<SBasis> > const &pwd2 = _pparam->get_pwd2();
+
+ double time_it = _pparam->to_time(_index, _pparam->_vector.at(_index)[X]);
+ Point canvas_point = pwd2.valueAt(time_it);
+
+ _pparam->updateCanvasIndicators();
+ return canvas_point;
+
+}
+
+void FilletChamferPointArrayParamKnotHolderEntity::knot_click(guint state)
+{
+ if (state & GDK_CONTROL_MASK) {
+ if (state & GDK_MOD1_MASK) {
+ _pparam->_vector.at(_index) = Point(_index, _pparam->_vector.at(_index)[Y]);
+ _pparam->param_set_and_write_new_value(_pparam->_vector);
+ sp_lpe_item_update_patheffect(SP_LPE_ITEM(item), false, false);
+ }else{
+ using namespace Geom;
+ int type = (int)_pparam->_vector.at(_index)[Y];
+ if (type >=3000 && type < 4000){
+ type = 3;
+ }
+ if (type >=4000 && type < 5000){
+ type = 4;
+ }
+ switch(type){
+ case 1:
+ type = 2;
+ break;
+ case 2:
+ type = _pparam->chamfer_steps + 3000;
+ break;
+ case 3:
+ type = _pparam->chamfer_steps + 4000;
+ break;
+ default:
+ type = 1;
+ break;
+ }
+ _pparam->_vector.at(_index) = Point(_pparam->_vector.at(_index)[X], (double)type);
+ _pparam->param_set_and_write_new_value(_pparam->_vector);
+ sp_lpe_item_update_patheffect(SP_LPE_ITEM(item), false, false);
+ const gchar *tip;
+ if (type >=3000 && type < 4000){
+ tip = _("<b>Chamfer</b>: <b>Ctrl+Click</b> toogle type, "
+ "<b>Shift+Click</b> open dialog, "
+ "<b>Ctrl+Alt+Click</b> reset");
+ } else if (type >=4000 && type < 5000) {
+ tip = _("<b>Inverse Chamfer</b>: <b>Ctrl+Click</b> toogle type, "
+ "<b>Shift+Click</b> open dialog, "
+ "<b>Ctrl+Alt+Click</b> reset");
+ } else if (type == 2) {
+ tip = _("<b>Inverse Fillet</b>: <b>Ctrl+Click</b> toogle type, "
+ "<b>Shift+Click</b> open dialog, "
+ "<b>Ctrl+Alt+Click</b> reset");
+ } else {
+ tip = _("<b>Fillet</b>: <b>Ctrl+Click</b> toogle type, "
+ "<b>Shift+Click</b> open dialog, "
+ "<b>Ctrl+Alt+Click</b> reset");
+ }
+ this->knot->tip = g_strdup(tip);
+ this->knot->show();
+ }
+ } else if (state & GDK_SHIFT_MASK) {
+ double xModified = _pparam->_vector.at(_index).x();
+ if(xModified < 0 && !_pparam->use_distance){
+ xModified = _pparam->len_to_rad(_index, _pparam->_vector.at(_index).x());
+ }
+ std::vector<Geom::Path> subpaths = path_from_piecewise(_pparam->last_pwd2, 0.1);
+ std::pair<std::size_t, std::size_t> positions = _pparam->get_positions(_index, subpaths);
+ D2<SBasis> A = _pparam->last_pwd2[_pparam->last_index(_index, subpaths)];
+ if(positions.second != 0){
+ A = _pparam->last_pwd2[_index-1];
+ }
+ D2<SBasis> B = _pparam->last_pwd2[_index];
+ bool aprox = (A[0].degreesOfFreedom() != 2 || B[0].degreesOfFreedom() != 2) && !_pparam->use_distance?true:false;
+ Geom::Point offset = Geom::Point(xModified, _pparam->_vector.at(_index).y());
+ Inkscape::UI::Dialogs::FilletChamferPropertiesDialog::showDialog(
+ this->desktop, offset, this, _pparam->unit, _pparam->use_distance, aprox, _pparam->documentUnit);
+ }
+
+}
+
+void FilletChamferPointArrayParamKnotHolderEntity::knot_set_offset(
+ Geom::Point offset)
+{
+ double xModified = offset.x();
+ if(xModified < 0 && !_pparam->use_distance){
+ xModified = _pparam->rad_to_len(_index, offset.x());
+ }
+ _pparam->_vector.at(_index) = Geom::Point(xModified, offset.y());
+ this->parent_holder->knot_ungrabbed_handler(this->knot, 0);
+}
+
+void FilletChamferPointArrayParam::addKnotHolderEntities(KnotHolder *knotholder,
+ SPDesktop *desktop,
+ SPItem *item)
+{
+ recalculate_knots(get_pwd2());
+ for (unsigned int i = 0; i < _vector.size(); ++i) {
+ if (_vector[i][Y] <= 0) {
+ continue;
+ }
+ const gchar *tip;
+ if (_vector[i][Y] >=3000 && _vector[i][Y] < 4000){
+ tip = _("<b>Chamfer</b>: <b>Ctrl+Click</b> toogle type, "
+ "<b>Shift+Click</b> open dialog, "
+ "<b>Ctrl+Alt+Click</b> reset");
+ } else if (_vector[i][Y] >=4000 && _vector[i][Y] < 5000) {
+ tip = _("<b>Inverse Chamfer</b>: <b>Ctrl+Click</b> toogle type, "
+ "<b>Shift+Click</b> open dialog, "
+ "<b>Ctrl+Alt+Click</b> reset");
+ } else if (_vector[i][Y] == 2) {
+ tip = _("<b>Inverse Fillet</b>: <b>Ctrl+Click</b> toogle type, "
+ "<b>Shift+Click</b> open dialog, "
+ "<b>Ctrl+Alt+Click</b> reset");
+ } else {
+ tip = _("<b>Fillet</b>: <b>Ctrl+Click</b> toogle type, "
+ "<b>Shift+Click</b> open dialog, "
+ "<b>Ctrl+Alt+Click</b> reset");
+ }
+ FilletChamferPointArrayParamKnotHolderEntity *e =
+ new FilletChamferPointArrayParamKnotHolderEntity(this, i);
+ e->create(desktop, item, knotholder, Inkscape::CTRL_TYPE_UNKNOWN, _(tip),
+ knot_shape, knot_mode, knot_color);
+ knotholder->add(e);
+ }
+ updateCanvasIndicators();
+}
+
+} /* namespace LivePathEffect */
+
+} /* namespace Inkscape */
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/live_effects/parameter/filletchamferpointarray.h b/src/live_effects/parameter/filletchamferpointarray.h
new file mode 100644
index 000000000..6e5cce353
--- /dev/null
+++ b/src/live_effects/parameter/filletchamferpointarray.h
@@ -0,0 +1,127 @@
+#ifndef INKSCAPE_LIVEPATHEFFECT_FILLET_CHAMFER_POINT_ARRAY_H
+#define INKSCAPE_LIVEPATHEFFECT_FILLET_CHAMFER_POINT_ARRAY_H
+
+/*
+ * Inkscape::LivePathEffectParameters
+ * Copyright (C) Jabiertxo Arraiza Cenoz <jabier.arraiza@marker.es>
+ * Special thanks to Johan Engelen for the base of the effect -powerstroke-
+ * Also to ScislaC for point me to the idea
+ * Also su_v for his construvtive feedback and time
+ * and finaly to Liam P. White for his big help on coding, that save me a lot of
+ * hours
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <glib.h>
+#include <2geom/point.h>
+
+#include "live_effects/parameter/array.h"
+
+#include "knot-holder-entity.h"
+
+namespace Inkscape {
+
+namespace LivePathEffect {
+
+class FilletChamferPointArrayParamKnotHolderEntity;
+
+class FilletChamferPointArrayParam : public ArrayParam<Geom::Point> {
+public:
+ FilletChamferPointArrayParam(const Glib::ustring &label,
+ const Glib::ustring &tip,
+ const Glib::ustring &key,
+ Inkscape::UI::Widget::Registry *wr,
+ Effect *effect);
+ virtual ~FilletChamferPointArrayParam();
+
+ virtual Gtk::Widget *param_newWidget();
+
+ virtual void param_transform_multiply(Geom::Affine const &postmul,
+ bool /*set*/);
+
+ void set_oncanvas_looks(SPKnotShapeType shape, SPKnotModeType mode,
+ guint32 color);
+ virtual double to_time(int index, double A);
+ virtual double to_len(int index, double A);
+ virtual double rad_to_len(int index, double rad);
+ virtual double len_to_rad(int index, double len);
+ virtual double len_to_time(int index, double len);
+ virtual double time_to_len(int index, double time);
+ virtual std::pair<std::size_t, std::size_t> get_positions(int index, std::vector<Geom::Path> subpaths);
+ virtual int last_index(int index, std::vector<Geom::Path> subpaths);
+ std::vector<double> get_times(int index, std::vector<Geom::Path> subpaths, bool last);
+ virtual void set_helper_size(int hs);
+ virtual void set_use_distance(bool use_knot_distance);
+ virtual void set_chamfer_steps(int value_chamfer_steps);
+ virtual void set_document_unit(Glib::ustring const * value_document_unit);
+ virtual void set_unit(const gchar *abbr);
+ virtual void addCanvasIndicators(SPLPEItem const *lpeitem,
+ std::vector<Geom::PathVector> &hp_vec);
+ virtual bool providesKnotHolderEntities() const {
+ return true;
+ }
+ virtual void updateCanvasIndicators();
+ virtual void addKnotHolderEntities(KnotHolder *knotholder, SPDesktop *desktop,
+ SPItem *item);
+
+ void set_pwd2(Geom::Piecewise<Geom::D2<Geom::SBasis> > const &pwd2_in,
+ Geom::Piecewise<Geom::D2<Geom::SBasis> > const &pwd2_normal_in);
+ Geom::Piecewise<Geom::D2<Geom::SBasis> > const &get_pwd2() const {
+ return last_pwd2;
+ }
+ Geom::Piecewise<Geom::D2<Geom::SBasis> > const &get_pwd2_normal() const {
+ return last_pwd2_normal;
+ }
+
+ void recalculate_controlpoints_for_new_pwd2(
+ Geom::Piecewise<Geom::D2<Geom::SBasis> > const &pwd2_in);
+ void recalculate_knots(
+ Geom::Piecewise<Geom::D2<Geom::SBasis> > const &pwd2_in);
+ friend class FilletChamferPointArrayParamKnotHolderEntity;
+
+private:
+ FilletChamferPointArrayParam(const FilletChamferPointArrayParam &);
+ FilletChamferPointArrayParam &operator=(const FilletChamferPointArrayParam &);
+
+ SPKnotShapeType knot_shape;
+ SPKnotModeType knot_mode;
+ guint32 knot_color;
+ int helper_size;
+ int chamfer_steps;
+ bool use_distance;
+ const gchar *unit;
+ Glib::ustring const * documentUnit;
+ Geom::PathVector hp;
+
+ Geom::Piecewise<Geom::D2<Geom::SBasis> > last_pwd2;
+ Geom::Piecewise<Geom::D2<Geom::SBasis> > last_pwd2_normal;
+};
+
+class FilletChamferPointArrayParamKnotHolderEntity : public KnotHolderEntity {
+public:
+ FilletChamferPointArrayParamKnotHolderEntity(FilletChamferPointArrayParam *p,
+ unsigned int index);
+ virtual ~FilletChamferPointArrayParamKnotHolderEntity() {}
+
+ virtual void knot_set(Geom::Point const &p, Geom::Point const &origin,
+ guint state);
+ virtual Geom::Point knot_get() const;
+ virtual void knot_click(guint state);
+ virtual void knot_set_offset(Geom::Point offset);
+
+ /*Checks whether the index falls within the size of the parameter's vector*/
+ bool valid_index(unsigned int index) const {
+ return (_pparam->_vector.size() > index);
+ }
+ ;
+
+private:
+ FilletChamferPointArrayParam *_pparam;
+ unsigned int _index;
+};
+
+} //namespace LivePathEffect
+
+} //namespace Inkscape
+
+#endif
diff --git a/src/live_effects/parameter/originalpatharray.cpp b/src/live_effects/parameter/originalpatharray.cpp
new file mode 100644
index 000000000..7706dbdf8
--- /dev/null
+++ b/src/live_effects/parameter/originalpatharray.cpp
@@ -0,0 +1,487 @@
+/*
+ * Copyright (C) Theodore Janeczko 2012 <flutterguy317@gmail.com>
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#if GLIBMM_DISABLE_DEPRECATED && HAVE_GLIBMM_THREADS_H
+#include <glibmm/threads.h>
+#endif
+
+#include "live_effects/parameter/originalpatharray.h"
+
+#include <gtkmm/widget.h>
+#include <gtkmm/icontheme.h>
+#include <gtkmm/imagemenuitem.h>
+#include <gtkmm/separatormenuitem.h>
+#include <gtkmm/scrolledwindow.h>
+
+#include <glibmm/i18n.h>
+
+#include "inkscape.h"
+#include "icon-size.h"
+#include "widgets/icon.h"
+#include "ui/clipboard.h"
+#include "svg/svg.h"
+#include "svg/stringstream.h"
+#include "originalpath.h"
+#include "uri.h"
+#include "display/curve.h"
+
+#include <2geom/coord.h>
+#include <2geom/point.h>
+#include "sp-shape.h"
+#include "sp-text.h"
+#include "live_effects/effect.h"
+
+#include "verbs.h"
+#include "document-undo.h"
+#include "document.h"
+
+namespace Inkscape {
+
+namespace LivePathEffect {
+
+class OriginalPathArrayParam::ModelColumns : public Gtk::TreeModel::ColumnRecord
+{
+public:
+
+ ModelColumns()
+ {
+ add(_colObject);
+ add(_colLabel);
+ add(_colReverse);
+ }
+ virtual ~ModelColumns() {}
+
+ Gtk::TreeModelColumn<PathAndDirection*> _colObject;
+ Gtk::TreeModelColumn<Glib::ustring> _colLabel;
+ Gtk::TreeModelColumn<bool> _colReverse;
+};
+
+OriginalPathArrayParam::OriginalPathArrayParam( const Glib::ustring& label,
+ const Glib::ustring& tip,
+ const Glib::ustring& key,
+ Inkscape::UI::Widget::Registry* wr,
+ Effect* effect )
+: Parameter(label, tip, key, wr, effect),
+ _vector(),
+ _tree(),
+ _text_renderer(),
+ _toggle_renderer(),
+ _scroller()
+{
+ _model = new ModelColumns();
+ _store = Gtk::TreeStore::create(*_model);
+ _tree.set_model(_store);
+
+ _tree.set_reorderable(true);
+ _tree.enable_model_drag_dest (Gdk::ACTION_MOVE);
+
+ _text_renderer = manage(new Gtk::CellRendererText());
+ int nameColNum = _tree.append_column(_("Name"), *_text_renderer) - 1;
+ _name_column = _tree.get_column(nameColNum);
+ _name_column->add_attribute(_text_renderer->property_text(), _model->_colLabel);
+
+ _tree.set_expander_column( *_tree.get_column(nameColNum) );
+ _tree.set_search_column(_model->_colLabel);
+
+ Gtk::CellRendererToggle * _toggle_renderer = manage(new Gtk::CellRendererToggle());
+ int toggleColNum = _tree.append_column(_("Reverse"), *_toggle_renderer) - 1;
+ Gtk::TreeViewColumn* col = _tree.get_column(toggleColNum);
+ _toggle_renderer->set_activatable(true);
+ _toggle_renderer->signal_toggled().connect(sigc::mem_fun(*this, &OriginalPathArrayParam::on_reverse_toggled));
+ col->add_attribute(_toggle_renderer->property_active(), _model->_colReverse);
+
+ //quick little hack -- newer versions of gtk gave the item zero space allotment
+ _scroller.set_size_request(-1, 120);
+
+ _scroller.add(_tree);
+ _scroller.set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC );
+ //_scroller.set_shadow_type(Gtk::SHADOW_IN);
+
+ oncanvas_editable = true;
+
+}
+
+OriginalPathArrayParam::~OriginalPathArrayParam()
+{
+ while (!_vector.empty()) {
+ PathAndDirection *w = _vector.back();
+ _vector.pop_back();
+ unlink(w);
+ delete w;
+ }
+ delete _model;
+}
+
+void OriginalPathArrayParam::on_reverse_toggled(const Glib::ustring& path)
+{
+ Gtk::TreeModel::iterator iter = _store->get_iter(path);
+ Gtk::TreeModel::Row row = *iter;
+ PathAndDirection *w = row[_model->_colObject];
+ row[_model->_colReverse] = !row[_model->_colReverse];
+ w->reversed = row[_model->_colReverse];
+
+ gchar * full = param_getSVGValue();
+ param_write_to_repr(full);
+ g_free(full);
+ DocumentUndo::done(param_effect->getSPDoc(), SP_VERB_DIALOG_LIVE_PATH_EFFECT,
+ _("Link path parameter to path"));
+}
+
+void OriginalPathArrayParam::param_set_default()
+{
+
+}
+
+Gtk::Widget* OriginalPathArrayParam::param_newWidget()
+{
+ Gtk::VBox* vbox = Gtk::manage(new Gtk::VBox());
+ Gtk::HBox* hbox = Gtk::manage(new Gtk::HBox());
+
+ vbox->pack_start(_scroller, Gtk::PACK_EXPAND_WIDGET);
+
+
+ { // Paste path to link button
+ Gtk::Widget *pIcon = Gtk::manage( sp_icon_get_icon( GTK_STOCK_PASTE, Inkscape::ICON_SIZE_BUTTON) );
+ Gtk::Button *pButton = Gtk::manage(new Gtk::Button());
+ pButton->set_relief(Gtk::RELIEF_NONE);
+ pIcon->show();
+ pButton->add(*pIcon);
+ pButton->show();
+ pButton->signal_clicked().connect(sigc::mem_fun(*this, &OriginalPathArrayParam::on_link_button_click));
+ hbox->pack_start(*pButton, Gtk::PACK_SHRINK);
+ pButton->set_tooltip_text(_("Link to path"));
+ }
+
+ { // Remove linked path
+ Gtk::Widget *pIcon = Gtk::manage( sp_icon_get_icon( GTK_STOCK_REMOVE, Inkscape::ICON_SIZE_BUTTON) );
+ Gtk::Button *pButton = Gtk::manage(new Gtk::Button());
+ pButton->set_relief(Gtk::RELIEF_NONE);
+ pIcon->show();
+ pButton->add(*pIcon);
+ pButton->show();
+ pButton->signal_clicked().connect(sigc::mem_fun(*this, &OriginalPathArrayParam::on_remove_button_click));
+ hbox->pack_start(*pButton, Gtk::PACK_SHRINK);
+ pButton->set_tooltip_text(_("Remove Path"));
+ }
+
+ { // Move Down
+ Gtk::Widget *pIcon = Gtk::manage( sp_icon_get_icon( GTK_STOCK_GO_DOWN, Inkscape::ICON_SIZE_BUTTON) );
+ Gtk::Button *pButton = Gtk::manage(new Gtk::Button());
+ pButton->set_relief(Gtk::RELIEF_NONE);
+ pIcon->show();
+ pButton->add(*pIcon);
+ pButton->show();
+ pButton->signal_clicked().connect(sigc::mem_fun(*this, &OriginalPathArrayParam::on_down_button_click));
+ hbox->pack_end(*pButton, Gtk::PACK_SHRINK);
+ pButton->set_tooltip_text(_("Move Down"));
+ }
+
+ { // Move Down
+ Gtk::Widget *pIcon = Gtk::manage( sp_icon_get_icon( GTK_STOCK_GO_UP, Inkscape::ICON_SIZE_BUTTON) );
+ Gtk::Button *pButton = Gtk::manage(new Gtk::Button());
+ pButton->set_relief(Gtk::RELIEF_NONE);
+ pIcon->show();
+ pButton->add(*pIcon);
+ pButton->show();
+ pButton->signal_clicked().connect(sigc::mem_fun(*this, &OriginalPathArrayParam::on_up_button_click));
+ hbox->pack_end(*pButton, Gtk::PACK_SHRINK);
+ pButton->set_tooltip_text(_("Move Up"));
+ }
+
+ vbox->pack_end(*hbox, Gtk::PACK_SHRINK);
+
+ vbox->show_all_children(true);
+
+ return vbox;
+}
+
+bool OriginalPathArrayParam::_selectIndex(const Gtk::TreeIter& iter, int* i)
+{
+ if ((*i)-- <= 0) {
+ _tree.get_selection()->select(iter);
+ return true;
+ }
+ return false;
+}
+
+void OriginalPathArrayParam::on_up_button_click()
+{
+ Gtk::TreeModel::iterator iter = _tree.get_selection()->get_selected();
+ if (iter) {
+ Gtk::TreeModel::Row row = *iter;
+
+ int i = -1;
+ std::vector<PathAndDirection*>::iterator piter = _vector.begin();
+ for (std::vector<PathAndDirection*>::iterator iter = _vector.begin(); iter != _vector.end(); piter = iter, i++, iter++) {
+ if (*iter == row[_model->_colObject]) {
+ _vector.erase(iter);
+ _vector.insert(piter, row[_model->_colObject]);
+ break;
+ }
+ }
+
+ gchar * full = param_getSVGValue();
+ param_write_to_repr(full);
+ g_free(full);
+
+ DocumentUndo::done(param_effect->getSPDoc(), SP_VERB_DIALOG_LIVE_PATH_EFFECT,
+ _("Move path up"));
+
+ _store->foreach_iter(sigc::bind<int*>(sigc::mem_fun(*this, &OriginalPathArrayParam::_selectIndex), &i));
+ }
+}
+
+void OriginalPathArrayParam::on_down_button_click()
+{
+ Gtk::TreeModel::iterator iter = _tree.get_selection()->get_selected();
+ if (iter) {
+ Gtk::TreeModel::Row row = *iter;
+
+ int i = 0;
+ for (std::vector<PathAndDirection*>::iterator iter = _vector.begin(); iter != _vector.end(); i++, iter++) {
+ if (*iter == row[_model->_colObject]) {
+ std::vector<PathAndDirection*>::iterator niter = _vector.erase(iter);
+ if (niter != _vector.end()) {
+ niter++;
+ i++;
+ }
+ _vector.insert(niter, row[_model->_colObject]);
+ break;
+ }
+ }
+
+ gchar * full = param_getSVGValue();
+ param_write_to_repr(full);
+ g_free(full);
+
+ DocumentUndo::done(param_effect->getSPDoc(), SP_VERB_DIALOG_LIVE_PATH_EFFECT,
+ _("Move path down"));
+
+ _store->foreach_iter(sigc::bind<int*>(sigc::mem_fun(*this, &OriginalPathArrayParam::_selectIndex), &i));
+ }
+}
+
+void OriginalPathArrayParam::on_remove_button_click()
+{
+ Gtk::TreeModel::iterator iter = _tree.get_selection()->get_selected();
+ if (iter) {
+ Gtk::TreeModel::Row row = *iter;
+ remove_link(row[_model->_colObject]);
+
+ gchar * full = param_getSVGValue();
+ param_write_to_repr(full);
+ g_free(full);
+
+ DocumentUndo::done(param_effect->getSPDoc(), SP_VERB_DIALOG_LIVE_PATH_EFFECT,
+ _("Remove path"));
+ }
+
+}
+
+void
+OriginalPathArrayParam::on_link_button_click()
+{
+ Inkscape::UI::ClipboardManager *cm = Inkscape::UI::ClipboardManager::get();
+ Glib::ustring pathid = cm->getShapeOrTextObjectId(SP_ACTIVE_DESKTOP);
+
+ if (pathid == "") {
+ return;
+ }
+ // add '#' at start to make it an uri.
+ pathid.insert(pathid.begin(), '#');
+
+ Inkscape::SVGOStringStream os;
+ bool foundOne = false;
+ for (std::vector<PathAndDirection*>::const_iterator iter = _vector.begin(); iter != _vector.end(); iter++) {
+ if (foundOne) {
+ os << "|";
+ } else {
+ foundOne = true;
+ }
+ os << (*iter)->href << "," << ((*iter)->reversed ? "1" : "0");
+ }
+
+ if (foundOne) {
+ os << "|";
+ }
+
+ os << pathid.c_str() << ",0";
+
+ param_write_to_repr(os.str().c_str());
+ DocumentUndo::done(param_effect->getSPDoc(), SP_VERB_DIALOG_LIVE_PATH_EFFECT,
+ _("Link path parameter to path"));
+}
+
+void OriginalPathArrayParam::unlink(PathAndDirection* to)
+{
+ to->linked_modified_connection.disconnect();
+ to->linked_delete_connection.disconnect();
+ to->ref.detach();
+ to->_pathvector = Geom::PathVector();
+ if (to->href) {
+ g_free(to->href);
+ to->href = NULL;
+ }
+}
+
+void OriginalPathArrayParam::remove_link(PathAndDirection* to)
+{
+ unlink(to);
+ for (std::vector<PathAndDirection*>::iterator iter = _vector.begin(); iter != _vector.end(); iter++) {
+ if (*iter == to) {
+ PathAndDirection *w = *iter;
+ _vector.erase(iter);
+ delete w;
+ return;
+ }
+ }
+}
+
+void OriginalPathArrayParam::linked_delete(SPObject */*deleted*/, PathAndDirection* /*to*/)
+{
+ //remove_link(to);
+
+ gchar * full = param_getSVGValue();
+ param_write_to_repr(full);
+ g_free(full);
+}
+
+bool OriginalPathArrayParam::_updateLink(const Gtk::TreeIter& iter, PathAndDirection* pd)
+{
+ Gtk::TreeModel::Row row = *iter;
+ if (row[_model->_colObject] == pd) {
+ SPObject *obj = pd->ref.getObject();
+ row[_model->_colLabel] = obj && obj->getId() ? ( obj->label() ? obj->label() : obj->getId() ) : pd->href;
+ return true;
+ }
+ return false;
+}
+
+void OriginalPathArrayParam::linked_changed(SPObject */*old_obj*/, SPObject *new_obj, PathAndDirection* to)
+{
+ to->linked_delete_connection.disconnect();
+ to->linked_modified_connection.disconnect();
+ to->linked_transformed_connection.disconnect();
+
+ if (new_obj && SP_IS_ITEM(new_obj)) {
+ to->linked_delete_connection = new_obj->connectDelete(sigc::bind<PathAndDirection*>(sigc::mem_fun(*this, &OriginalPathArrayParam::linked_delete), to));
+ to->linked_modified_connection = new_obj->connectModified(sigc::bind<PathAndDirection*>(sigc::mem_fun(*this, &OriginalPathArrayParam::linked_modified), to));
+ to->linked_transformed_connection = SP_ITEM(new_obj)->connectTransformed(sigc::bind<PathAndDirection*>(sigc::mem_fun(*this, &OriginalPathArrayParam::linked_transformed), to));
+
+ linked_modified(new_obj, SP_OBJECT_MODIFIED_FLAG, to);
+ } else {
+ to->_pathvector = Geom::PathVector();
+ SP_OBJECT(param_effect->getLPEObj())->requestModified(SP_OBJECT_MODIFIED_FLAG);
+ _store->foreach_iter(sigc::bind<PathAndDirection*>(sigc::mem_fun(*this, &OriginalPathArrayParam::_updateLink), to));
+ }
+}
+
+void OriginalPathArrayParam::setPathVector(SPObject *linked_obj, guint /*flags*/, PathAndDirection* to)
+{
+ if (!to) {
+ return;
+ }
+ SPCurve *curve = NULL;
+ if (SP_IS_SHAPE(linked_obj)) {
+ curve = SP_SHAPE(linked_obj)->getCurveBeforeLPE();
+ }
+ if (SP_IS_TEXT(linked_obj)) {
+ curve = SP_TEXT(linked_obj)->getNormalizedBpath();
+ }
+
+ if (curve == NULL) {
+ // curve invalid, set empty pathvector
+ to->_pathvector = Geom::PathVector();
+ } else {
+ to->_pathvector = curve->get_pathvector();
+ curve->unref();
+ }
+}
+
+void OriginalPathArrayParam::linked_modified(SPObject *linked_obj, guint flags, PathAndDirection* to)
+{
+ if (!to) {
+ return;
+ }
+ setPathVector(linked_obj, flags, to);
+ SP_OBJECT(param_effect->getLPEObj())->requestModified(SP_OBJECT_MODIFIED_FLAG);
+ _store->foreach_iter(sigc::bind<PathAndDirection*>(sigc::mem_fun(*this, &OriginalPathArrayParam::_updateLink), to));
+}
+
+bool OriginalPathArrayParam::param_readSVGValue(const gchar* strvalue)
+{
+ if (strvalue) {
+ while (!_vector.empty()) {
+ PathAndDirection *w = _vector.back();
+ unlink(w);
+ _vector.pop_back();
+ delete w;
+ }
+ _store->clear();
+
+ gchar ** strarray = g_strsplit(strvalue, "|", 0);
+ for (gchar ** iter = strarray; *iter != NULL; iter++) {
+ if ((*iter)[0] == '#') {
+ gchar ** substrarray = g_strsplit(*iter, ",", 0);
+ PathAndDirection* w = new PathAndDirection((SPObject *)param_effect->getLPEObj());
+ w->href = g_strdup(*substrarray);
+ w->reversed = *(substrarray+1) != NULL && (*(substrarray+1))[0] == '1';
+
+ w->linked_changed_connection = w->ref.changedSignal().connect(sigc::bind<PathAndDirection *>(sigc::mem_fun(*this, &OriginalPathArrayParam::linked_changed), w));
+ w->ref.attach(URI(w->href));
+
+ _vector.push_back(w);
+
+ Gtk::TreeModel::iterator iter = _store->append();
+ Gtk::TreeModel::Row row = *iter;
+ SPObject *obj = w->ref.getObject();
+
+ row[_model->_colObject] = w;
+ row[_model->_colLabel] = obj ? ( obj->label() ? obj->label() : obj->getId() ) : w->href;
+ row[_model->_colReverse] = w->reversed;
+ g_strfreev (substrarray);
+ }
+ }
+ g_strfreev (strarray);
+ return true;
+ }
+ return false;
+}
+
+gchar * OriginalPathArrayParam::param_getSVGValue() const
+{
+ Inkscape::SVGOStringStream os;
+ bool foundOne = false;
+ for (std::vector<PathAndDirection*>::const_iterator iter = _vector.begin(); iter != _vector.end(); iter++) {
+ if (foundOne) {
+ os << "|";
+ } else {
+ foundOne = true;
+ }
+ os << (*iter)->href << "," << ((*iter)->reversed ? "1" : "0");
+ }
+ gchar * str = g_strdup(os.str().c_str());
+ return str;
+}
+
+} /* namespace LivePathEffect */
+
+} /* namespace Inkscape */
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/live_effects/parameter/originalpatharray.h b/src/live_effects/parameter/originalpatharray.h
new file mode 100644
index 000000000..6c792613f
--- /dev/null
+++ b/src/live_effects/parameter/originalpatharray.h
@@ -0,0 +1,122 @@
+#ifndef INKSCAPE_LIVEPATHEFFECT_PARAMETER_ORIGINALPATHARRAY_H
+#define INKSCAPE_LIVEPATHEFFECT_PARAMETER_ORIGINALPATHARRAY_H
+
+/*
+ * Inkscape::LivePathEffectParameters
+ *
+ * Copyright (C) Theodore Janeczko 2012 <flutterguy317@gmail.com>
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <vector>
+
+#include <gtkmm/box.h>
+#include <gtkmm/treeview.h>
+#include <gtkmm/treestore.h>
+#include <gtkmm/scrolledwindow.h>
+
+#include "live_effects/parameter/parameter.h"
+#include "live_effects/parameter/path-reference.h"
+
+#include "svg/svg.h"
+#include "svg/stringstream.h"
+#include "path-reference.h"
+#include "sp-object.h"
+
+namespace Inkscape {
+
+namespace LivePathEffect {
+
+class PathAndDirection {
+public:
+ PathAndDirection(SPObject *owner)
+ : href(NULL),
+ ref(owner),
+ _pathvector(Geom::PathVector()),
+ reversed(false)
+ {
+
+ }
+ gchar *href;
+ URIReference ref;
+ std::vector<Geom::Path> _pathvector;
+ bool reversed;
+
+ sigc::connection linked_changed_connection;
+ sigc::connection linked_delete_connection;
+ sigc::connection linked_modified_connection;
+ sigc::connection linked_transformed_connection;
+};
+
+class OriginalPathArrayParam : public Parameter {
+public:
+ class ModelColumns;
+
+ OriginalPathArrayParam( const Glib::ustring& label,
+ const Glib::ustring& tip,
+ const Glib::ustring& key,
+ Inkscape::UI::Widget::Registry* wr,
+ Effect* effect);
+
+ virtual ~OriginalPathArrayParam();
+
+ virtual Gtk::Widget * param_newWidget();
+ virtual bool param_readSVGValue(const gchar * strvalue);
+ virtual gchar * param_getSVGValue() const;
+ virtual void param_set_default();
+
+ /** Disable the canvas indicators of parent class by overriding this method */
+ virtual void param_editOncanvas(SPItem * /*item*/, SPDesktop * /*dt*/) {};
+ /** Disable the canvas indicators of parent class by overriding this method */
+ virtual void addCanvasIndicators(SPLPEItem const* /*lpeitem*/, std::vector<Geom::PathVector> & /*hp_vec*/) {};
+
+ std::vector<PathAndDirection*> _vector;
+
+protected:
+ bool _updateLink(const Gtk::TreeIter& iter, PathAndDirection* pd);
+ bool _selectIndex(const Gtk::TreeIter& iter, int* i);
+ void unlink(PathAndDirection* to);
+ void remove_link(PathAndDirection* to);
+ void setPathVector(SPObject *linked_obj, guint flags, PathAndDirection* to);
+
+ void linked_changed(SPObject *old_obj, SPObject *new_obj, PathAndDirection* to);
+ void linked_modified(SPObject *linked_obj, guint flags, PathAndDirection* to);
+ void linked_transformed(Geom::Affine const *, SPItem *, PathAndDirection*) {}
+ void linked_delete(SPObject *deleted, PathAndDirection* to);
+
+ ModelColumns *_model;
+ Glib::RefPtr<Gtk::TreeStore> _store;
+ Gtk::TreeView _tree;
+ Gtk::CellRendererText *_text_renderer;
+ Gtk::CellRendererToggle *_toggle_renderer;
+ Gtk::TreeView::Column *_name_column;
+ Gtk::ScrolledWindow _scroller;
+
+ void on_link_button_click();
+ void on_remove_button_click();
+ void on_up_button_click();
+ void on_down_button_click();
+ void on_reverse_toggled(const Glib::ustring& path);
+
+private:
+ OriginalPathArrayParam(const OriginalPathArrayParam&);
+ OriginalPathArrayParam& operator=(const OriginalPathArrayParam&);
+};
+
+} //namespace LivePathEffect
+
+} //namespace Inkscape
+
+#endif
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/live_effects/parameter/parameter.cpp b/src/live_effects/parameter/parameter.cpp
index a5de2169e..beb750404 100644
--- a/src/live_effects/parameter/parameter.cpp
+++ b/src/live_effects/parameter/parameter.cpp
@@ -36,13 +36,26 @@ Parameter::Parameter( const Glib::ustring& label, const Glib::ustring& tip,
{
}
-
void
Parameter::param_write_to_repr(const char * svgd)
{
param_effect->getRepr()->setAttribute(param_key.c_str(), svgd);
}
+// In gtk2, this wasn't an issue; we could toss around
+// G_MAXDOUBLE and not worry about size allocations. But
+// in gtk3, it is an issue: it allocates widget size for the maxmium
+// value you pass to it, leading to some insane lengths.
+// If you need this to be more, please be conservative about it.
+const double SCALARPARAM_G_MAXDOUBLE = 10000000000.0; // TODO fixme: using an arbitrary large number as a magic value seems fragile.
+
+void Parameter::write_to_SVG(void)
+{
+ gchar * str = param_getSVGValue();
+ param_write_to_repr(str);
+ g_free(str);
+}
+
/*###########################################
* REAL PARAM
*/
@@ -51,8 +64,8 @@ ScalarParam::ScalarParam( const Glib::ustring& label, const Glib::ustring& tip,
Effect* effect, gdouble default_value)
: Parameter(label, tip, key, wr, effect),
value(default_value),
- min(-G_MAXDOUBLE),
- max(G_MAXDOUBLE),
+ min(-SCALARPARAM_G_MAXDOUBLE),
+ max(SCALARPARAM_G_MAXDOUBLE),
integer(false),
defvalue(default_value),
digits(2),
@@ -108,8 +121,22 @@ ScalarParam::param_set_value(gdouble val)
void
ScalarParam::param_set_range(gdouble min, gdouble max)
{
- this->min = min;
- this->max = max;
+ // if you look at client code, you'll see that many effects
+ // has a tendency to set an upper range of Geom::infinity().
+ // Once again, in gtk2, this is not a problem. But in gtk3,
+ // widgets get allocated the amount of size they ask for,
+ // leading to excessively long widgets.
+
+ if (min >= -SCALARPARAM_G_MAXDOUBLE) {
+ this->min = min;
+ } else {
+ this->min = -SCALARPARAM_G_MAXDOUBLE;
+ }
+ if (max <= SCALARPARAM_G_MAXDOUBLE) {
+ this->max = max;
+ } else {
+ this->max = SCALARPARAM_G_MAXDOUBLE;
+ }
param_set_value(value); // reset value to see whether it is in ranges
}
diff --git a/src/live_effects/parameter/parameter.h b/src/live_effects/parameter/parameter.h
index 785ada92e..2e6cae49f 100644
--- a/src/live_effects/parameter/parameter.h
+++ b/src/live_effects/parameter/parameter.h
@@ -49,7 +49,7 @@ public:
virtual bool param_readSVGValue(const gchar * strvalue) = 0; // returns true if new value is valid / accepted.
virtual gchar * param_getSVGValue() const = 0;
- void write_to_SVG() { param_write_to_repr(param_getSVGValue()); }
+ void write_to_SVG();
virtual void param_set_default() = 0;
diff --git a/src/live_effects/parameter/path.cpp b/src/live_effects/parameter/path.cpp
index cdbbef1db..2a14d4208 100644
--- a/src/live_effects/parameter/path.cpp
+++ b/src/live_effects/parameter/path.cpp
@@ -28,8 +28,8 @@
#include "document-undo.h"
// needed for on-canvas editting:
-#include "tools-switch.h"
-#include "shape-editor.h"
+#include "ui/tools-switch.h"
+#include "ui/shape-editor.h"
#include "desktop-handles.h"
#include "selection.h"
// clipboard support
@@ -118,6 +118,11 @@ PathParam::param_readSVGValue(const gchar * strvalue)
// Now do the attaching, which emits the changed signal.
try {
ref.attach(Inkscape::URI(href));
+ //lp:1299948
+ SPItem* i = ref.getObject();
+ if (i) {
+ linked_modified_callback(i, SP_OBJECT_MODIFIED_FLAG);
+ } // else: document still processing new events. Repr of the linked object not created yet.
} catch (Inkscape::BadURIException &e) {
g_warning("%s", e.what());
ref.detach();
@@ -138,7 +143,7 @@ gchar *
PathParam::param_getSVGValue() const
{
if (href) {
- return href;
+ return g_strdup(href);
} else {
gchar * svgd = sp_svg_write_path( _pathvector );
return svgd;
@@ -192,7 +197,7 @@ PathParam::param_newWidget()
pButton->show();
pButton->signal_clicked().connect(sigc::mem_fun(*this, &PathParam::on_link_button_click));
static_cast<Gtk::HBox*>(_widget)->pack_start(*pButton, true, true);
- pButton->set_tooltip_text(_("Link to path"));
+ pButton->set_tooltip_text(_("Link to path on clipboard"));
static_cast<Gtk::HBox*>(_widget)->show_all_children();
diff --git a/src/live_effects/parameter/pointreseteable.cpp b/src/live_effects/parameter/pointreseteable.cpp
new file mode 100644
index 000000000..c0f8858b8
--- /dev/null
+++ b/src/live_effects/parameter/pointreseteable.cpp
@@ -0,0 +1,210 @@
+/*
+ * Copyright (C) Johan Engelen 2007 <j.b.c.engelen@utwente.nl>
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "ui/widget/registered-widget.h"
+#include "live_effects/parameter/pointreseteable.h"
+#include "live_effects/effect.h"
+#include "svg/svg.h"
+#include "svg/stringstream.h"
+#include "ui/widget/point.h"
+#include "widgets/icon.h"
+#include "inkscape.h"
+#include "verbs.h"
+#include "knotholder.h"
+#include <glibmm/i18n.h>
+#include "ui/tools-switch.h"
+#include "ui/tools/node-tool.h"
+
+// needed for on-canvas editting:
+#include "desktop.h"
+
+namespace Inkscape {
+
+namespace LivePathEffect {
+
+PointReseteableParam::PointReseteableParam( const Glib::ustring& label, const Glib::ustring& tip,
+ const Glib::ustring& key, Inkscape::UI::Widget::Registry* wr,
+ Effect* effect, const gchar *htip, Geom::Point default_value)
+ : Geom::Point(default_value), Parameter(label, tip, key, wr, effect), defvalue(default_value)
+{
+ knot_shape = SP_KNOT_SHAPE_DIAMOND;
+ knot_mode = SP_KNOT_MODE_XOR;
+ knot_color = 0xffffff00;
+ handle_tip = g_strdup(htip);
+}
+
+PointReseteableParam::~PointReseteableParam()
+{
+ if (handle_tip)
+ g_free(handle_tip);
+}
+
+void
+PointReseteableParam::param_set_default()
+{
+ param_setValue(defvalue);
+}
+
+void
+PointReseteableParam::param_set_and_write_default()
+{
+ param_set_and_write_new_value(defvalue);
+}
+
+void
+PointReseteableParam::param_update_default(Geom::Point newpoint)
+{
+ this->defvalue = newpoint;
+}
+
+bool
+PointReseteableParam::param_readSVGValue(const gchar * strvalue)
+{
+ gchar ** strarray = g_strsplit(strvalue, ",", 2);
+ double newx, newy;
+ unsigned int success = sp_svg_number_read_d(strarray[0], &newx);
+ success += sp_svg_number_read_d(strarray[1], &newy);
+ g_strfreev (strarray);
+ if (success == 2) {
+ param_setValue( Geom::Point(newx, newy) );
+ return true;
+ }
+ return false;
+}
+
+gchar *
+PointReseteableParam::param_getSVGValue() const
+{
+ Inkscape::SVGOStringStream os;
+ os << *dynamic_cast<Geom::Point const *>( this );
+ gchar * str = g_strdup(os.str().c_str());
+ return str;
+}
+
+Gtk::Widget *
+PointReseteableParam::param_newWidget()
+{
+ Inkscape::UI::Widget::RegisteredTransformedPoint * pointwdg = Gtk::manage(
+ new Inkscape::UI::Widget::RegisteredTransformedPoint( param_label,
+ param_tooltip,
+ param_key,
+ *param_wr,
+ param_effect->getRepr(),
+ param_effect->getSPDoc() ) );
+ // TODO: fix to get correct desktop (don't use SP_ACTIVE_DESKTOP)
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ Geom::Affine transf = desktop->doc2dt();
+ pointwdg->setTransform(transf);
+ pointwdg->setValue( *this );
+ pointwdg->clearProgrammatically();
+ pointwdg->set_undo_parameters(SP_VERB_DIALOG_LIVE_PATH_EFFECT, _("Change point parameter"));
+
+ Gtk::HBox * hbox = Gtk::manage( new Gtk::HBox() );
+ static_cast<Gtk::HBox*>(hbox)->pack_start(*pointwdg, true, true);
+ static_cast<Gtk::HBox*>(hbox)->show_all_children();
+
+ return dynamic_cast<Gtk::Widget *> (hbox);
+}
+
+void
+PointReseteableParam::param_setValue(Geom::Point newpoint)
+{
+ *dynamic_cast<Geom::Point *>( this ) = newpoint;
+ if(SP_ACTIVE_DESKTOP){
+ SPDesktop* desktop = SP_ACTIVE_DESKTOP;
+ if (tools_isactive( desktop, TOOLS_NODES)) {
+ Inkscape::UI::Tools::NodeTool *nt = static_cast<Inkscape::UI::Tools::NodeTool*>( desktop->event_context);
+ nt->update_helperpath();
+ }
+ }
+}
+
+void
+PointReseteableParam::param_set_and_write_new_value (Geom::Point newpoint)
+{
+ Inkscape::SVGOStringStream os;
+ os << newpoint;
+ gchar * str = g_strdup(os.str().c_str());
+ param_write_to_repr(str);
+ g_free(str);
+}
+
+void
+PointReseteableParam::param_transform_multiply(Geom::Affine const& postmul, bool /*set*/)
+{
+ param_set_and_write_new_value( (*this) * postmul );
+}
+
+
+void
+PointReseteableParam::set_oncanvas_looks(SPKnotShapeType shape, SPKnotModeType mode, guint32 color)
+{
+ knot_shape = shape;
+ knot_mode = mode;
+ knot_color = color;
+}
+
+class PointReseteableParamKnotHolderEntity : public KnotHolderEntity {
+public:
+ PointReseteableParamKnotHolderEntity(PointReseteableParam *p) { this->pparam = p; }
+ virtual ~PointReseteableParamKnotHolderEntity() {}
+
+ virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state);
+ virtual Geom::Point knot_get() const;
+ virtual void knot_click(guint state);
+
+private:
+ PointReseteableParam *pparam;
+};
+
+void
+PointReseteableParamKnotHolderEntity::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, guint state)
+{
+ Geom::Point const s = snap_knot_position(p, state);
+ pparam->param_setValue(s);
+ sp_lpe_item_update_patheffect(SP_LPE_ITEM(item), false, false);
+}
+
+Geom::Point
+PointReseteableParamKnotHolderEntity::knot_get() const
+{
+ return *pparam;
+}
+
+void
+PointReseteableParamKnotHolderEntity::knot_click(guint state)
+{
+ if (state & GDK_CONTROL_MASK) {
+ if (state & GDK_MOD1_MASK) {
+ this->pparam->param_set_default();
+ sp_lpe_item_update_patheffect(SP_LPE_ITEM(item), false, false);
+ }
+ }
+}
+
+void
+PointReseteableParam::addKnotHolderEntities(KnotHolder *knotholder, SPDesktop *desktop, SPItem *item)
+{
+ PointReseteableParamKnotHolderEntity *e = new PointReseteableParamKnotHolderEntity(this);
+ // TODO: can we ditch handleTip() etc. because we have access to handle_tip etc. itself???
+ e->create(desktop, item, knotholder, Inkscape::CTRL_TYPE_UNKNOWN, handleTip(), knot_shape, knot_mode, knot_color);
+ knotholder->add(e);
+}
+
+} /* namespace LivePathEffect */
+
+} /* namespace Inkscape */
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/live_effects/parameter/pointreseteable.h b/src/live_effects/parameter/pointreseteable.h
new file mode 100644
index 000000000..5ae1fdf02
--- /dev/null
+++ b/src/live_effects/parameter/pointreseteable.h
@@ -0,0 +1,74 @@
+#ifndef INKSCAPE_LIVEPATHEFFECT_PARAMETER_POINT_RESETEABLE_H
+#define INKSCAPE_LIVEPATHEFFECT_PARAMETER_POINT_RESETEABLE_H
+
+/*
+ * Inkscape::LivePathEffectParameters
+ *
+* Copyright (C) Johan Engelen 2007 <j.b.c.engelen@utwente.nl>
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <glib.h>
+#include <2geom/point.h>
+
+#include "live_effects/parameter/parameter.h"
+
+#include "knot-holder-entity.h"
+
+namespace Inkscape {
+
+namespace LivePathEffect {
+
+class PointReseteableParamKnotHolderEntity;
+
+class PointReseteableParam : public Geom::Point, public Parameter {
+public:
+ PointReseteableParam( const Glib::ustring& label,
+ const Glib::ustring& tip,
+ const Glib::ustring& key,
+ Inkscape::UI::Widget::Registry* wr,
+ Effect* effect,
+ const gchar *handle_tip = NULL,
+ Geom::Point default_value = Geom::Point(0,0) ); // tip for automatically associated on-canvas handle
+ virtual ~PointReseteableParam();
+
+ virtual Gtk::Widget * param_newWidget();
+
+ bool param_readSVGValue(const gchar * strvalue);
+ gchar * param_getSVGValue() const;
+ inline const gchar *handleTip() const { return handle_tip ? handle_tip : param_tooltip.c_str(); }
+
+ void param_setValue(Geom::Point newpoint);
+ void param_set_default();
+ void param_set_and_write_default();
+ void param_update_default(Geom::Point newpoint);
+
+ void param_set_and_write_new_value(Geom::Point newpoint);
+
+ virtual void param_transform_multiply(Geom::Affine const& /*postmul*/, bool /*set*/);
+
+ void set_oncanvas_looks(SPKnotShapeType shape, SPKnotModeType mode, guint32 color);
+
+ virtual bool providesKnotHolderEntities() const { return true; }
+ virtual void addKnotHolderEntities(KnotHolder *knotholder, SPDesktop *desktop, SPItem *item);
+
+ friend class PointReseteableParamKnotHolderEntity;
+private:
+ PointReseteableParam(const PointReseteableParam&);
+ PointReseteableParam& operator=(const PointReseteableParam&);
+
+ Geom::Point defvalue;
+
+ SPKnotShapeType knot_shape;
+ SPKnotModeType knot_mode;
+ guint32 knot_color;
+ gchar *handle_tip;
+};
+
+
+} //namespace LivePathEffect
+
+} //namespace Inkscape
+
+#endif
diff --git a/src/live_effects/parameter/powerstrokepointarray.cpp b/src/live_effects/parameter/powerstrokepointarray.cpp
index fecdfeda8..e0c2f4c68 100644
--- a/src/live_effects/parameter/powerstrokepointarray.cpp
+++ b/src/live_effects/parameter/powerstrokepointarray.cpp
@@ -4,22 +4,19 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include <glibmm/i18n.h>
-
+#include "ui/dialog/lpe-powerstroke-properties.h"
#include "live_effects/parameter/powerstrokepointarray.h"
#include "live_effects/effect.h"
-#include "svg/svg.h"
-#include "svg/stringstream.h"
#include "knotholder.h"
#include "sp-lpe-item.h"
#include <2geom/piecewise.h>
#include <2geom/sbasis-geometric.h>
-// needed for on-canvas editting:
-#include "desktop.h"
-#include "live_effects/lpeobject.h"
+#include "preferences.h" // for proportional stroke/path scaling behavior
+
+#include <glibmm/i18n.h>
namespace Inkscape {
@@ -43,37 +40,27 @@ Gtk::Widget *
PowerStrokePointArrayParam::param_newWidget()
{
return NULL;
-/*
- Inkscape::UI::Widget::RegisteredTransformedPoint * pointwdg = Gtk::manage(
- new Inkscape::UI::Widget::RegisteredTransformedPoint( param_label,
- param_tooltip,
- param_key,
- *param_wr,
- param_effect->getRepr(),
- param_effect->getSPDoc() ) );
- // TODO: fix to get correct desktop (don't use SP_ACTIVE_DESKTOP)
- SPDesktop *desktop = SP_ACTIVE_DESKTOP;
- Geom::Affine transf = desktop->doc2dt();
- pointwdg->setTransform(transf);
- pointwdg->setValue( *this );
- pointwdg->clearProgrammatically();
- pointwdg->set_undo_parameters(SP_VERB_DIALOG_LIVE_PATH_EFFECT, _("Change point parameter"));
-
- Gtk::HBox * hbox = Gtk::manage( new Gtk::HBox() );
- static_cast<Gtk::HBox*>(hbox)->pack_start(*pointwdg, true, true);
- static_cast<Gtk::HBox*>(hbox)->show_all_children();
-
- return dynamic_cast<Gtk::Widget *> (hbox);
-*/
}
-
-void PowerStrokePointArrayParam::param_transform_multiply(Geom::Affine const& /*postmul*/, bool /*set*/)
+void PowerStrokePointArrayParam::param_transform_multiply(Geom::Affine const &postmul, bool /*set*/)
{
-// param_set_and_write_new_value( (*this) * postmul );
+ // Check if proportional stroke-width scaling is on
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ bool transform_stroke = prefs ? prefs->getBool("/options/transform/stroke", true) : true;
+ if (transform_stroke) {
+ std::vector<Geom::Point> result;
+ result.reserve(_vector.size()); // reserve space for the points that will be added in the for loop
+ for (std::vector<Geom::Point>::const_iterator point_it = _vector.begin(), e = _vector.end();
+ point_it != e; ++point_it)
+ {
+ // scale each width knot with the average scaling in X and Y
+ Geom::Coord const A = (*point_it)[Geom::Y] * ((postmul.expansionX() + postmul.expansionY()) / 2);
+ result.push_back(Geom::Point((*point_it)[Geom::X], A));
+ }
+ param_set_and_write_new_value(result);
+ }
}
-
/** call this method to recalculate the controlpoints such that they stay at the same location relative to the new path. Useful after adding/deleting nodes to the path.*/
void
PowerStrokePointArrayParam::recalculate_controlpoints_for_new_pwd2(Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_in)
@@ -102,6 +89,23 @@ PowerStrokePointArrayParam::recalculate_controlpoints_for_new_pwd2(Geom::Piecewi
}
}
+float PowerStrokePointArrayParam::median_width()
+{
+ size_t size = _vector.size();
+ if (size > 0)
+ {
+ if (size % 2 == 0)
+ {
+ return (_vector[size / 2 - 1].y() + _vector[size / 2].y()) / 2;
+ }
+ else
+ {
+ return _vector[size / 2].y();
+ }
+ }
+ return 1;
+}
+
void
PowerStrokePointArrayParam::set_pwd2(Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_in, Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_normal_in)
{
@@ -117,7 +121,7 @@ PowerStrokePointArrayParam::set_oncanvas_looks(SPKnotShapeType shape, SPKnotMode
knot_mode = mode;
knot_color = color;
}
-
+/*
class PowerStrokePointArrayParamKnotHolderEntity : public KnotHolderEntity {
public:
PowerStrokePointArrayParamKnotHolderEntity(PowerStrokePointArrayParam *p, unsigned int index);
@@ -127,7 +131,7 @@ public:
virtual Geom::Point knot_get() const;
virtual void knot_click(guint state);
- /** Checks whether the index falls within the size of the parameter's vector */
+ // Checks whether the index falls within the size of the parameter's vector
bool valid_index(unsigned int index) const {
return (_pparam->_vector.size() > index);
};
@@ -135,7 +139,7 @@ public:
private:
PowerStrokePointArrayParam *_pparam;
unsigned int _index;
-};
+};*/
PowerStrokePointArrayParamKnotHolderEntity::PowerStrokePointArrayParamKnotHolderEntity(PowerStrokePointArrayParam *p, unsigned int index)
: _pparam(p),
@@ -176,11 +180,20 @@ PowerStrokePointArrayParamKnotHolderEntity::knot_get() const
Piecewise<D2<SBasis> > const & n = _pparam->get_pwd2_normal();
Point offset_point = _pparam->_vector.at(_index);
-
+ if (offset_point[X] > pwd2.size() || offset_point[X] < 0) {
+ g_warning("Broken powerstroke point at %f, I won't try to add that", offset_point[X]);
+ return Geom::Point(infinity(), infinity());
+ }
Point canvas_point = pwd2.valueAt(offset_point[X]) + offset_point[Y] * n.valueAt(offset_point[X]);
return canvas_point;
}
+void PowerStrokePointArrayParamKnotHolderEntity::knot_set_offset(Geom::Point offset)
+{
+ _pparam->_vector.at(_index) = Geom::Point(offset.x(), offset.y() / 2);
+ this->parent_holder->knot_ungrabbed_handler(this->knot, 0);
+}
+
void
PowerStrokePointArrayParamKnotHolderEntity::knot_click(guint state)
{
@@ -223,10 +236,15 @@ PowerStrokePointArrayParamKnotHolderEntity::knot_click(guint state)
// add knot to knotholder
PowerStrokePointArrayParamKnotHolderEntity *e = new PowerStrokePointArrayParamKnotHolderEntity(_pparam, _index+1);
e->create( this->desktop, this->item, parent_holder, Inkscape::CTRL_TYPE_UNKNOWN,
- _("<b>Stroke width control point</b>: drag to alter the stroke width. <b>Ctrl+click</b> adds a control point, <b>Ctrl+Alt+click</b> deletes it."),
+ _("<b>Stroke width control point</b>: drag to alter the stroke width. <b>Ctrl+click</b> adds a control point, <b>Ctrl+Alt+click</b> deletes it, <b>Shift+click</b> launches width dialog."),
_pparam->knot_shape, _pparam->knot_mode, _pparam->knot_color);
parent_holder->add(e);
}
+ }
+ else if ((state & GDK_MOD1_MASK) || (state & GDK_SHIFT_MASK))
+ {
+ Geom::Point offset = Geom::Point(_pparam->_vector.at(_index).x(), _pparam->_vector.at(_index).y() * 2);
+ Inkscape::UI::Dialogs::PowerstrokePropertiesDialog::showDialog(this->desktop, offset, this);
}
}
@@ -235,7 +253,7 @@ void PowerStrokePointArrayParam::addKnotHolderEntities(KnotHolder *knotholder, S
for (unsigned int i = 0; i < _vector.size(); ++i) {
PowerStrokePointArrayParamKnotHolderEntity *e = new PowerStrokePointArrayParamKnotHolderEntity(this, i);
e->create( desktop, item, knotholder, Inkscape::CTRL_TYPE_UNKNOWN,
- _("<b>Stroke width control point</b>: drag to alter the stroke width. <b>Ctrl+click</b> adds a control point, <b>Ctrl+Alt+click</b> deletes it."),
+ _("<b>Stroke width control point</b>: drag to alter the stroke width. <b>Ctrl+click</b> adds a control point, <b>Ctrl+Alt+click</b> deletes it, <b>Shift+click</b> launches width dialog."),
knot_shape, knot_mode, knot_color);
knotholder->add(e);
}
diff --git a/src/live_effects/parameter/powerstrokepointarray.h b/src/live_effects/parameter/powerstrokepointarray.h
index e1fa440f2..70b22e27e 100644
--- a/src/live_effects/parameter/powerstrokepointarray.h
+++ b/src/live_effects/parameter/powerstrokepointarray.h
@@ -20,8 +20,6 @@ namespace Inkscape {
namespace LivePathEffect {
-class PowerStrokePointArrayParamKnotHolderEntity;
-
class PowerStrokePointArrayParam : public ArrayParam<Geom::Point> {
public:
PowerStrokePointArrayParam( const Glib::ustring& label,
@@ -33,10 +31,12 @@ public:
virtual Gtk::Widget * param_newWidget();
- virtual void param_transform_multiply(Geom::Affine const& /*postmul*/, bool /*set*/);
+ virtual void param_transform_multiply(Geom::Affine const& postmul, bool /*set*/);
void set_oncanvas_looks(SPKnotShapeType shape, SPKnotModeType mode, guint32 color);
+ float median_width();
+
virtual bool providesKnotHolderEntities() const { return true; }
virtual void addKnotHolderEntities(KnotHolder *knotholder, SPDesktop *desktop, SPItem *item);
@@ -60,6 +60,25 @@ private:
Geom::Piecewise<Geom::D2<Geom::SBasis> > last_pwd2_normal;
};
+class PowerStrokePointArrayParamKnotHolderEntity : public KnotHolderEntity {
+public:
+ PowerStrokePointArrayParamKnotHolderEntity(PowerStrokePointArrayParam *p, unsigned int index);
+ virtual ~PowerStrokePointArrayParamKnotHolderEntity() {}
+
+ virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state);
+ virtual Geom::Point knot_get() const;
+ virtual void knot_set_offset(Geom::Point offset);
+ virtual void knot_click(guint state);
+
+ /** Checks whether the index falls within the size of the parameter's vector */
+ bool valid_index(unsigned int index) const {
+ return (_pparam->_vector.size() > index);
+ };
+
+private:
+ PowerStrokePointArrayParam *_pparam;
+ unsigned int _index;
+};
} //namespace LivePathEffect
diff --git a/src/live_effects/parameter/text.cpp b/src/live_effects/parameter/text.cpp
index fcb2fc9fc..956a001ad 100644
--- a/src/live_effects/parameter/text.cpp
+++ b/src/live_effects/parameter/text.cpp
@@ -85,7 +85,7 @@ TextParam::param_readSVGValue(const gchar * strvalue)
gchar *
TextParam::param_getSVGValue() const
{
- return (gchar *) value.c_str();
+ return g_strdup(value.c_str());
}
Gtk::Widget *
diff --git a/src/live_effects/parameter/togglebutton.cpp b/src/live_effects/parameter/togglebutton.cpp
new file mode 100644
index 000000000..c5da8b858
--- /dev/null
+++ b/src/live_effects/parameter/togglebutton.cpp
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) Johan Engelen 2007 <j.b.c.engelen@utwente.nl>
+ * Copyright (C) Jabiertxo Arraiza Cenoz 2014 <j.b.c.engelen@utwente.nl>
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "ui/widget/registered-widget.h"
+#include <glibmm/i18n.h>
+
+#include "live_effects/parameter/togglebutton.h"
+#include "live_effects/effect.h"
+#include "svg/svg.h"
+#include "svg/stringstream.h"
+#include "widgets/icon.h"
+#include "inkscape.h"
+#include "verbs.h"
+#include "helper-fns.h"
+
+namespace Inkscape {
+
+namespace LivePathEffect {
+
+ToggleButtonParam::ToggleButtonParam( const Glib::ustring& label, const Glib::ustring& tip,
+ const Glib::ustring& key, Inkscape::UI::Widget::Registry* wr,
+ Effect* effect, bool default_value, const Glib::ustring& inactive_label,
+ char const * icon_active, char const * icon_inactive,
+ Inkscape::IconSize icon_size)
+ : Parameter(label, tip, key, wr, effect), value(default_value), defvalue(default_value),
+ inactiveLabel(inactive_label), iconActive(icon_active), iconInactive(icon_inactive), iconSize(icon_size)
+{
+ checkwdg = NULL;
+}
+
+ToggleButtonParam::~ToggleButtonParam()
+{
+ if (_toggled_connection.connected()) {
+ _toggled_connection.disconnect();
+ }
+}
+
+void
+ToggleButtonParam::param_set_default()
+{
+ param_setValue(defvalue);
+}
+
+bool
+ToggleButtonParam::param_readSVGValue(const gchar * strvalue)
+{
+ param_setValue(helperfns_read_bool(strvalue, defvalue));
+ return true; // not correct: if value is unacceptable, should return false!
+}
+
+gchar *
+ToggleButtonParam::param_getSVGValue() const
+{
+ gchar * str = g_strdup(value ? "true" : "false");
+ return str;
+}
+
+Gtk::Widget *
+ToggleButtonParam::param_newWidget()
+{
+ if (_toggled_connection.connected()) {
+ _toggled_connection.disconnect();
+ }
+
+ checkwdg = Gtk::manage(
+ new Inkscape::UI::Widget::RegisteredToggleButton( param_label,
+ param_tooltip,
+ param_key,
+ *param_wr,
+ false,
+ param_effect->getRepr(),
+ param_effect->getSPDoc()) );
+#if GTK_CHECK_VERSION(3,0,0)
+ GtkWidget * boxButton = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+ gtk_box_set_homogeneous(GTK_BOX(boxButton), false);
+#else
+ GtkWidget * boxButton = gtk_hbox_new (false, 0);
+#endif
+ GtkWidget * labelButton = gtk_label_new ("");
+ if (!param_label.empty()) {
+ if(value || inactiveLabel.empty()){
+ gtk_label_set_text(GTK_LABEL(labelButton), param_label.c_str());
+ }else{
+ gtk_label_set_text(GTK_LABEL(labelButton), inactiveLabel.c_str());
+ }
+ }
+ gtk_widget_show(labelButton);
+ if ( iconActive ) {
+ if(!iconInactive){
+ iconInactive = iconActive;
+ }
+ gtk_widget_show(boxButton);
+ GtkWidget *iconButton = sp_icon_new(iconSize, iconActive);
+ if(!value){
+ iconButton = sp_icon_new(iconSize, iconInactive);
+ }
+ gtk_widget_show(iconButton);
+ gtk_box_pack_start (GTK_BOX(boxButton), iconButton, false, false, 1);
+ if (!param_label.empty()) {
+ gtk_box_pack_start (GTK_BOX(boxButton), labelButton, false, false, 1);
+ }
+ }else{
+ gtk_box_pack_start (GTK_BOX(boxButton), labelButton, false, false, 1);
+ }
+ checkwdg->add(*Gtk::manage(Glib::wrap(boxButton)));
+ checkwdg->setActive(value);
+ checkwdg->setProgrammatically = false;
+ checkwdg->set_undo_parameters(SP_VERB_DIALOG_LIVE_PATH_EFFECT, _("Change togglebutton parameter"));
+
+ _toggled_connection = checkwdg->signal_toggled().connect(sigc::mem_fun(*this, &ToggleButtonParam::toggled));
+
+ return checkwdg;
+}
+
+void
+ToggleButtonParam::refresh_button()
+{
+ if(!checkwdg){
+ return;
+ }
+ Gtk::Widget * boxButton = checkwdg->get_child();
+ if(!boxButton){
+ return;
+ }
+ GList * childs = gtk_container_get_children(GTK_CONTAINER(boxButton->gobj()));
+ guint totalWidgets = g_list_length (childs);
+ if (!param_label.empty()) {
+ if(value || inactiveLabel.empty()){
+ gtk_label_set_text(GTK_LABEL(g_list_nth_data(childs, totalWidgets-1)), param_label.c_str());
+ }else{
+ gtk_label_set_text(GTK_LABEL(g_list_nth_data(childs, totalWidgets-1)), inactiveLabel.c_str());
+ }
+ }
+ if ( iconActive ) {
+ GdkPixbuf * iconPixbuf = sp_pixbuf_new( iconSize, iconActive );
+ if(!value){
+ iconPixbuf = sp_pixbuf_new( iconSize, iconInactive);
+ }
+ gtk_image_set_from_pixbuf (GTK_IMAGE(g_list_nth_data(childs, 0)), iconPixbuf);
+ }
+}
+
+void
+ToggleButtonParam::param_setValue(bool newvalue)
+{
+ value = newvalue;
+ refresh_button();
+}
+
+void
+ToggleButtonParam::toggled() {
+ _signal_toggled.emit();
+}
+
+} /* namespace LivePathEffect */
+
+} /* namespace Inkscape */
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/live_effects/parameter/togglebutton.h b/src/live_effects/parameter/togglebutton.h
new file mode 100644
index 000000000..4e545bcfd
--- /dev/null
+++ b/src/live_effects/parameter/togglebutton.h
@@ -0,0 +1,77 @@
+#ifndef INKSCAPE_LIVEPATHEFFECT_PARAMETER_TOGGLEBUTTON_H
+#define INKSCAPE_LIVEPATHEFFECT_PARAMETER_TOGGLEBUTTON_H
+
+/*
+ * Copyright (C) Jabiertxo Arraiza Cenoz 2014
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <glib.h>
+#include <sigc++/connection.h>
+#include <sigc++/signal.h>
+
+#include "live_effects/parameter/parameter.h"
+#include "icon-size.h"
+#include "ui/widget/registered-widget.h"
+
+namespace Inkscape {
+
+namespace LivePathEffect {
+
+/**
+ * class ToggleButtonParam:
+ * represents a Gtk::ToggleButton as a Live Path Effect parameter
+ */
+class ToggleButtonParam : public Parameter {
+public:
+ ToggleButtonParam( const Glib::ustring& label,
+ const Glib::ustring& tip,
+ const Glib::ustring& key,
+ Inkscape::UI::Widget::Registry* wr,
+ Effect* effect,
+ bool default_value = false,
+ const Glib::ustring& inactive_label = "",
+ char const * icon_active = NULL,
+ char const * icon_inactive = NULL,
+ Inkscape::IconSize icon_size = Inkscape::ICON_SIZE_SMALL_TOOLBAR);
+ virtual ~ToggleButtonParam();
+
+ virtual Gtk::Widget * param_newWidget();
+
+ virtual bool param_readSVGValue(const gchar * strvalue);
+ virtual gchar * param_getSVGValue() const;
+
+ void param_setValue(bool newvalue);
+ virtual void param_set_default();
+
+ bool get_value() const { return value; };
+
+ inline operator bool() const { return value; };
+
+ sigc::signal<void>& signal_toggled() { return _signal_toggled; }
+ virtual void toggled();
+
+private:
+ ToggleButtonParam(const ToggleButtonParam&);
+ ToggleButtonParam& operator=(const ToggleButtonParam&);
+
+ void refresh_button();
+ bool value;
+ bool defvalue;
+ const Glib::ustring inactiveLabel;
+ const char * iconActive;
+ const char * iconInactive;
+ Inkscape::IconSize iconSize;
+ Inkscape::UI::Widget::RegisteredToggleButton * checkwdg;
+
+ sigc::signal<void> _signal_toggled;
+ sigc::connection _toggled_connection;
+};
+
+
+} //namespace LivePathEffect
+
+} //namespace Inkscape
+
+#endif
diff --git a/src/live_effects/parameter/transformedpoint.cpp b/src/live_effects/parameter/transformedpoint.cpp
new file mode 100644
index 000000000..0d03432c3
--- /dev/null
+++ b/src/live_effects/parameter/transformedpoint.cpp
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) Theodore Janeczko 2012 <flutterguy317@gmail.com>
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "ui/widget/registered-widget.h"
+#include "live_effects/parameter/transformedpoint.h"
+#include "sp-lpe-item.h"
+#include "knotholder.h"
+#include "svg/svg.h"
+#include "svg/stringstream.h"
+
+#include "live_effects/effect.h"
+#include "desktop.h"
+#include "verbs.h"
+
+#include <glibmm/i18n.h>
+
+namespace Inkscape {
+
+namespace LivePathEffect {
+
+TransformedPointParam::TransformedPointParam( const Glib::ustring& label, const Glib::ustring& tip,
+ const Glib::ustring& key, Inkscape::UI::Widget::Registry* wr,
+ Effect* effect, Geom::Point default_vector,
+ bool dontTransform)
+ : Parameter(label, tip, key, wr, effect),
+ defvalue(default_vector),
+ origin(0.,0.),
+ vector(default_vector),
+ noTransform(dontTransform)
+{
+ vec_knot_shape = SP_KNOT_SHAPE_DIAMOND;
+ vec_knot_mode = SP_KNOT_MODE_XOR;
+ vec_knot_color = 0xffffb500;
+}
+
+TransformedPointParam::~TransformedPointParam()
+{
+
+}
+
+void
+TransformedPointParam::param_set_default()
+{
+ setOrigin(Geom::Point(0.,0.));
+ setVector(defvalue);
+}
+
+bool
+TransformedPointParam::param_readSVGValue(const gchar * strvalue)
+{
+ gchar ** strarray = g_strsplit(strvalue, ",", 4);
+ if (!strarray) {
+ return false;
+ }
+ double val[4];
+ unsigned int i = 0;
+ while (i < 4 && strarray[i]) {
+ if (sp_svg_number_read_d(strarray[i], &val[i]) != 0) {
+ i++;
+ } else {
+ break;
+ }
+ }
+ g_strfreev (strarray);
+ if (i == 4) {
+ setOrigin( Geom::Point(val[0], val[1]) );
+ setVector( Geom::Point(val[2], val[3]) );
+ return true;
+ }
+ return false;
+}
+
+gchar *
+TransformedPointParam::param_getSVGValue() const
+{
+ Inkscape::SVGOStringStream os;
+ os << origin << " , " << vector;
+ gchar * str = g_strdup(os.str().c_str());
+ return str;
+}
+
+Gtk::Widget *
+TransformedPointParam::param_newWidget()
+{
+ Inkscape::UI::Widget::RegisteredVector * pointwdg = Gtk::manage(
+ new Inkscape::UI::Widget::RegisteredVector( param_label,
+ param_tooltip,
+ param_key,
+ *param_wr,
+ param_effect->getRepr(),
+ param_effect->getSPDoc() ) );
+ pointwdg->setPolarCoords();
+ pointwdg->setValue( vector, origin );
+ pointwdg->clearProgrammatically();
+ pointwdg->set_undo_parameters(SP_VERB_DIALOG_LIVE_PATH_EFFECT, _("Change vector parameter"));
+
+ Gtk::HBox * hbox = Gtk::manage( new Gtk::HBox() );
+ static_cast<Gtk::HBox*>(hbox)->pack_start(*pointwdg, true, true);
+ static_cast<Gtk::HBox*>(hbox)->show_all_children();
+
+ return dynamic_cast<Gtk::Widget *> (hbox);
+}
+
+void
+TransformedPointParam::set_and_write_new_values(Geom::Point const &new_origin, Geom::Point const &new_vector)
+{
+ setValues(new_origin, new_vector);
+ gchar * str = param_getSVGValue();
+ param_write_to_repr(str);
+ g_free(str);
+}
+
+void
+TransformedPointParam::param_transform_multiply(Geom::Affine const& postmul, bool /*set*/)
+{
+ if (!noTransform) {
+ set_and_write_new_values( origin * postmul, vector * postmul.withoutTranslation() );
+ }
+}
+
+
+void
+TransformedPointParam::set_vector_oncanvas_looks(SPKnotShapeType shape, SPKnotModeType mode, guint32 color)
+{
+ vec_knot_shape = shape;
+ vec_knot_mode = mode;
+ vec_knot_color = color;
+}
+
+void
+TransformedPointParam::set_oncanvas_color(guint32 color)
+{
+ vec_knot_color = color;
+}
+
+class TransformedPointParamKnotHolderEntity_Vector : public KnotHolderEntity {
+public:
+ TransformedPointParamKnotHolderEntity_Vector(TransformedPointParam *p) : param(p) { }
+ virtual ~TransformedPointParamKnotHolderEntity_Vector() {}
+
+ virtual void knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, guint /*state*/) {
+ Geom::Point const s = p - param->origin;
+ /// @todo implement angle snapping when holding CTRL
+ param->setVector(s);
+ sp_lpe_item_update_patheffect(SP_LPE_ITEM(item), false, false);
+ };
+ virtual Geom::Point knot_get() const{
+ return param->origin + param->vector;
+ };
+ virtual void knot_click(guint /*state*/){
+ g_print ("This is the vector handle associated to parameter '%s'\n", param->param_key.c_str());
+ };
+
+private:
+ TransformedPointParam *param;
+};
+
+void
+TransformedPointParam::addKnotHolderEntities(KnotHolder *knotholder, SPDesktop *desktop, SPItem *item)
+{
+ TransformedPointParamKnotHolderEntity_Vector *vector_e = new TransformedPointParamKnotHolderEntity_Vector(this);
+ vector_e->create(desktop, item, knotholder, Inkscape::CTRL_TYPE_UNKNOWN, handleTip(), vec_knot_shape, vec_knot_mode, vec_knot_color);
+ knotholder->add(vector_e);
+}
+
+} /* namespace LivePathEffect */
+
+} /* namespace Inkscape */
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/live_effects/parameter/transformedpoint.h b/src/live_effects/parameter/transformedpoint.h
new file mode 100644
index 000000000..c96bedb53
--- /dev/null
+++ b/src/live_effects/parameter/transformedpoint.h
@@ -0,0 +1,82 @@
+#ifndef INKSCAPE_LIVEPATHEFFECT_PARAMETER_TRANSFORMED_POINT_H
+#define INKSCAPE_LIVEPATHEFFECT_PARAMETER_TRANSFORMED_POINT_H
+
+/*
+ * Inkscape::LivePathEffectParameters
+ *
+ * Copyright (C) Theodore Janeczko 2012 <flutterguy317@gmail.com>
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <glib.h>
+#include <2geom/point.h>
+
+#include "live_effects/parameter/parameter.h"
+
+#include "knot-holder-entity.h"
+
+namespace Inkscape {
+
+namespace LivePathEffect {
+
+
+class TransformedPointParam : public Parameter {
+public:
+ TransformedPointParam( const Glib::ustring& label,
+ const Glib::ustring& tip,
+ const Glib::ustring& key,
+ Inkscape::UI::Widget::Registry* wr,
+ Effect* effect,
+ Geom::Point default_vector = Geom::Point(1,0),
+ bool dontTransform = false);
+ virtual ~TransformedPointParam();
+
+ virtual Gtk::Widget * param_newWidget();
+ inline const gchar *handleTip() const { return param_tooltip.c_str(); }
+
+ virtual bool param_readSVGValue(const gchar * strvalue);
+ virtual gchar * param_getSVGValue() const;
+
+ Geom::Point getVector() const { return vector; };
+ Geom::Point getOrigin() const { return origin; };
+ void setValues(Geom::Point const &new_origin, Geom::Point const &new_vector) { setVector(new_vector); setOrigin(new_origin); };
+ void setVector(Geom::Point const &new_vector) { vector = new_vector; };
+ void setOrigin(Geom::Point const &new_origin) { origin = new_origin; };
+ virtual void param_set_default();
+
+ void set_and_write_new_values(Geom::Point const &new_origin, Geom::Point const &new_vector);
+
+ virtual void param_transform_multiply(Geom::Affine const &postmul, bool set);
+
+ void set_vector_oncanvas_looks(SPKnotShapeType shape, SPKnotModeType mode, guint32 color);
+ void set_oncanvas_color(guint32 color);
+
+ virtual bool providesKnotHolderEntities() const { return true; }
+ virtual void addKnotHolderEntities(KnotHolder *knotholder, SPDesktop *desktop, SPItem *item);
+
+private:
+ TransformedPointParam(const TransformedPointParam&);
+ TransformedPointParam& operator=(const TransformedPointParam&);
+
+ Geom::Point defvalue;
+
+ Geom::Point origin;
+ Geom::Point vector;
+
+ bool noTransform;
+
+ /// The looks of the vector and origin knots oncanvas
+ SPKnotShapeType vec_knot_shape;
+ SPKnotModeType vec_knot_mode;
+ guint32 vec_knot_color;
+
+ friend class TransformedPointParamKnotHolderEntity_Vector;
+};
+
+
+} //namespace LivePathEffect
+
+} //namespace Inkscape
+
+#endif
diff --git a/src/live_effects/pathoutlineprovider.cpp b/src/live_effects/pathoutlineprovider.cpp
new file mode 100644
index 000000000..21a0fb809
--- /dev/null
+++ b/src/live_effects/pathoutlineprovider.cpp
@@ -0,0 +1,803 @@
+/* Author:
+ * Liam P. White <inkscapebrony@gmail.com>
+ *
+ * Copyright (C) 2014 Author
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <2geom/angle.h>
+#include <2geom/path.h>
+#include <2geom/circle.h>
+#include <2geom/sbasis-to-bezier.h>
+#include <2geom/shape.h>
+#include <2geom/transforms.h>
+#include <2geom/path-sink.h>
+#include <cstdio>
+
+#include "pathoutlineprovider.h"
+#include "livarot/path-description.h"
+#include "helper/geom-nodetype.h"
+#include "svg/svg.h"
+
+namespace Geom {
+/**
+* Refer to: Weisstein, Eric W. "Circle-Circle Intersection."
+ From MathWorld--A Wolfram Web Resource.
+ http://mathworld.wolfram.com/Circle-CircleIntersection.html
+*
+* @return 0 if no intersection
+* @return 1 if one circle is contained in the other
+* @return 2 if intersections are found (they are written to p0 and p1)
+*/
+static int circle_circle_intersection(Circle const &circle0, Circle const &circle1, Point & p0, Point & p1)
+{
+ Point X0 = circle0.center();
+ double r0 = circle0.ray();
+ Point X1 = circle1.center();
+ double r1 = circle1.ray();
+
+ /* dx and dy are the vertical and horizontal distances between
+ * the circle centers.
+ */
+ Point D = X1 - X0;
+
+ /* Determine the straight-line distance between the centers. */
+ double d = L2(D);
+
+ /* Check for solvability. */
+ if (d > (r0 + r1)) {
+ /* no solution. circles do not intersect. */
+ return 0;
+ }
+ if (d <= fabs(r0 - r1)) {
+ /* no solution. one circle is contained in the other */
+ return 1;
+ }
+
+ /* 'point 2' is the point where the line through the circle
+ * intersection points crosses the line between the circle
+ * centers.
+ */
+
+ /* Determine the distance from point 0 to point 2. */
+ double a = ((r0*r0) - (r1*r1) + (d*d)) / (2.0 * d) ;
+
+ /* Determine the coordinates of point 2. */
+ Point p2 = X0 + D * (a/d);
+
+ /* Determine the distance from point 2 to either of the
+ * intersection points.
+ */
+ double h = std::sqrt((r0*r0) - (a*a));
+
+ /* Now determine the offsets of the intersection points from
+ * point 2.
+ */
+ Point r = (h/d)*rot90(D);
+
+ /* Determine the absolute intersection points. */
+ p0 = p2 + r;
+ p1 = p2 - r;
+
+ return 2;
+}
+/**
+* Find circle that touches inside of the curve, with radius matching the curvature, at time value \c t.
+* Because this method internally uses unitTangentAt, t should be smaller than 1.0 (see unitTangentAt).
+*/
+static Circle touching_circle( D2<SBasis> const &curve, double t, double tol=0.01 )
+{
+ D2<SBasis> dM=derivative(curve);
+ if ( are_near(L2sq(dM(t)),0.) ) {
+ dM=derivative(dM);
+ }
+ if ( are_near(L2sq(dM(t)),0.) ) { // try second time
+ dM=derivative(dM);
+ }
+ Piecewise<D2<SBasis> > unitv = unitVector(dM,tol);
+ Piecewise<SBasis> dMlength = dot(Piecewise<D2<SBasis> >(dM),unitv);
+ Piecewise<SBasis> k = cross(derivative(unitv),unitv);
+ k = divide(k,dMlength,tol,3);
+ double curv = k(t); // note that this value is signed
+
+ Geom::Point normal = unitTangentAt(curve, t).cw();
+ double radius = 1/curv;
+ Geom::Point center = curve(t) + radius*normal;
+ return Geom::Circle(center, fabs(radius));
+}
+
+std::vector<Geom::Path> split_at_cusps(const Geom::Path& in)
+{
+ PathVector out = PathVector();
+ Path temp = Path();
+
+ for (unsigned i = 0; i < in.size(); i++) {
+ temp.append(in[i]);
+ if ( get_nodetype(in[i], in[i + 1]) != Geom::NODE_SMOOTH ) {
+ out.push_back(temp);
+ temp = Path();
+ }
+ }
+ if (temp.size() > 0) {
+ out.push_back(temp);
+ }
+ return out;
+}
+
+Geom::CubicBezier sbasis_to_cubicbezier(Geom::D2<Geom::SBasis> const & sbasis_in)
+{
+ std::vector<Geom::Point> temp;
+ sbasis_to_bezier(temp, sbasis_in, 4);
+ return Geom::CubicBezier( temp );
+}
+
+static boost::optional<Geom::Point> intersection_point(Geom::Point const & origin_a, Geom::Point const & vector_a, Geom::Point const & origin_b, Geom::Point const & vector_b)
+{
+ Geom::Coord denom = cross(vector_b, vector_a);
+ if (!Geom::are_near(denom,0.)) {
+ Geom::Coord t = (cross(origin_a,vector_b) + cross(vector_b,origin_b)) / denom;
+ return origin_a + t * vector_a;
+ }
+ return boost::none;
+}
+
+} // namespace Geom
+
+namespace Outline {
+
+typedef Geom::D2<Geom::SBasis> D2SB;
+typedef Geom::Piecewise<D2SB> PWD2;
+
+// UTILITY
+
+unsigned bezierOrder (const Geom::Curve* curve_in)
+{
+ using namespace Geom;
+ if ( const BezierCurve* bz = dynamic_cast<const BezierCurve*>(curve_in) ) {
+ return bz->order();
+ }
+ return 0;
+}
+
+/**
+ * @return true if the angle formed by the curves and their handles is greater than 180 degrees clockwise, otherwise false.
+ */
+bool outside_angle (const Geom::Curve& cbc1, const Geom::Curve& cbc2)
+{
+ Geom::Point start_point;
+ Geom::Point cross_point = cbc1.finalPoint();
+ Geom::Point end_point;
+
+ if (cross_point != cbc2.initialPoint()) {
+ printf("WARNING: Non-contiguous path in Outline::outside_angle()");
+ return false;
+ }
+
+ Geom::CubicBezier cubicBezier = Geom::sbasis_to_cubicbezier(cbc1.toSBasis());
+ start_point = cubicBezier [2];
+
+ /*
+ * Because the node editor does not yet support true quadratics, paths are converted to
+ * cubic beziers in the node tool with degenerate handles on one side.
+ */
+
+ if (are_near(start_point, cross_point, 0.0000001)) {
+ start_point = cubicBezier [1];
+ }
+ cubicBezier = Geom::sbasis_to_cubicbezier(cbc2.toSBasis());
+ end_point = cubicBezier [1];
+ if (are_near(end_point, cross_point, 0.0000001)) {
+ end_point = cubicBezier [2];
+ }
+
+ // got our three points, now let's see what their clockwise angle is
+
+ // Definition of a Graham scan
+
+ /********************************************************************
+ # Three points are a counter-clockwise turn if ccw > 0, clockwise if
+ # ccw < 0, and collinear if ccw = 0 because ccw is a determinant that
+ # gives the signed area of the triangle formed by p1, p2 and p3.
+ function ccw(p1, p2, p3):
+ return (p2.x - p1.x)*(p3.y - p1.y) - (p2.y - p1.y)*(p3.x - p1.x)
+ *********************************************************************/
+
+ double ccw = ( (cross_point.x() - start_point.x()) * (end_point.y() - start_point.y()) ) -
+ ( (cross_point.y() - start_point.y()) * (end_point.x() - start_point.x()) );
+ return ccw > 0;
+}
+
+// LINE JOINS
+
+typedef Geom::BezierCurveN<1u> BezierLine;
+
+/**
+ * Removes the crossings on an interior join.
+ * @param path_builder Contains the incoming segment; result is appended to this
+ * @param outgoing The outgoing segment
+ */
+void joinInside(Geom::Path& path_builder, Geom::Curve const& outgoing)
+{
+ Geom::Curve const& incoming = path_builder.back();
+
+ // Using Geom::crossings to find intersections between two curves
+ Geom::Crossings cross = Geom::crossings(incoming, outgoing);
+ if (!cross.empty()) {
+ // Crossings found, create the join
+ Geom::CubicBezier cubic = Geom::sbasis_to_cubicbezier(incoming.toSBasis());
+ cubic = cubic.subdivide(cross[0].ta).first;
+ // erase the last segment, as we're going to overwrite it now
+ path_builder.erase_last();
+ path_builder.append(cubic, Geom::Path::STITCH_DISCONTINUOUS);
+
+ cubic = Geom::sbasis_to_cubicbezier(outgoing.toSBasis());
+ cubic = cubic.subdivide(cross[0].tb).second;
+ path_builder.append(cubic, Geom::Path::STITCH_DISCONTINUOUS);
+ } else {
+ // No crossings occurred, or Geom::crossings() failed; default to bevel
+ if (Geom::are_near(incoming.finalPoint(), outgoing.initialPoint())) {
+ path_builder.appendNew<BezierLine>(outgoing.initialPoint());
+ } else {
+ path_builder.setFinal(outgoing.initialPoint());
+ }
+ }
+}
+
+/**
+ * Try to create a miter join. Falls back to bevel if no miter can be created.
+ * @param path_builder Path to append curves to; back() is the incoming curve
+ * @param outgoing Outgoing curve.
+ * @param miter_limit When mitering, don't exceed this length
+ * @param line_width The thickness of the line.
+ */
+void miter_curves(Geom::Path& path_builder, Geom::Curve const& outgoing, double miter_limit, double line_width)
+{
+ using namespace Geom;
+ Curve const& incoming = path_builder.back();
+ Point tang1 = unitTangentAt(Geom::reverse(incoming.toSBasis()), 0.);
+ Point tang2 = unitTangentAt(outgoing.toSBasis(), 0);
+
+ boost::optional <Point> p = intersection_point (incoming.finalPoint(), tang1, outgoing.initialPoint(), tang2);
+ if (p) {
+ // check size of miter
+ Point point_on_path = incoming.finalPoint() - rot90(tang1) * line_width;
+ Coord len = distance(*p, point_on_path);
+ if (len <= miter_limit) {
+ // miter OK
+ path_builder.appendNew<BezierLine>(*p);
+ }
+ }
+ path_builder.appendNew<BezierLine>(outgoing.initialPoint());
+}
+
+/**
+ * Smoothly extrapolate curves along a circular route. Falls back to miter if necessary.
+ * @param path_builder Path to append curves to; back() is the incoming curve
+ * @param outgoing Outgoing curve.
+ * @param miter_limit When mitering, don't exceed this length
+ * @param line_width The thickness of the line. Used for miter fallback.
+ */
+void extrapolate_curves(Geom::Path& path_builder, Geom::Curve const& outgoing, double miter_limit, double line_width)
+{
+ Geom::Curve const& incoming = path_builder.back();
+ Geom::Point endPt = outgoing.initialPoint();
+
+ // The method used when extrapolating curves fails to work when either side of the join to be extrapolated
+ // is a line segment. When this situation is encountered, fall back to a regular miter join.
+ bool lineProblem = (dynamic_cast<const BezierLine *>(&incoming)) || (dynamic_cast<const BezierLine *>(&outgoing));
+ if (lineProblem == false) {
+ // Geom::Point tang1 = Geom::unitTangentAt(Geom::reverse(incoming.toSBasis()), 0.);
+ Geom::Point tang2 = Geom::unitTangentAt(outgoing.toSBasis(), 0);
+
+ Geom::Circle circle1 = Geom::touching_circle(Geom::reverse(incoming.toSBasis()), 0.);
+ Geom::Circle circle2 = Geom::touching_circle(outgoing.toSBasis(), 0);
+
+ Geom::Point points[2];
+ int solutions = Geom::circle_circle_intersection(circle1, circle2, points[0], points[1]);
+ if (solutions == 2) {
+ Geom::Point sol(0,0);
+ if ( dot(tang2,points[0]-endPt) > 0 ) {
+ // points[0] is bad, choose points[1]
+ sol = points[1];
+ } else if ( dot(tang2,points[1]-endPt) > 0 ) { // points[0] could be good, now check points[1]
+ // points[1] is bad, choose points[0]
+ sol = points[0];
+ } else {
+ // both points are good, choose nearest
+ sol = ( distanceSq(endPt, points[0]) < distanceSq(endPt, points[1]) ) ? points[0] : points[1];
+ }
+
+ Geom::EllipticalArc *arc0 = circle1.arc(incoming.finalPoint(), 0.5*(incoming.finalPoint()+sol), sol, true);
+ Geom::EllipticalArc *arc1 = circle2.arc(sol, 0.5*(sol+endPt), endPt, true);
+ try {
+ if (arc0) {
+ path_builder.append (arc0->toSBasis());
+ delete arc0;
+ arc0 = NULL;
+ } else {
+ throw std::exception();
+ }
+
+ if (arc1) {
+ path_builder.append (arc1->toSBasis());
+ delete arc1;
+ arc1 = NULL;
+ } else {
+ throw std::exception();
+ }
+
+ } catch (std::exception const & ex) {
+ printf("WARNING: Error extrapolating line join: %s\n", ex.what());
+ path_builder.appendNew<Geom::LineSegment>(endPt);
+ }
+ } else {
+ // 1 or no solutions found, default to miter
+ miter_curves(path_builder, outgoing, miter_limit, line_width);
+ }
+ } else {
+ // Line segments exist
+ miter_curves(path_builder, outgoing, miter_limit, line_width);
+ }
+}
+
+/**
+ * Extrapolate curves by reflecting them along the line that would be given by beveling the join.
+ * @param path_builder Path to append curves to; back() is the incoming curve
+ * @param outgoing Outgoing curve.
+ * @param miter_limit When mitering, don't exceed this length
+ * @param line_width The thickness of the line. Used for miter fallback.
+ */
+void reflect_curves(Geom::Path& path_builder, Geom::Curve const& outgoing, double miter_limit, double line_width)
+{
+ using namespace Geom;
+ Curve const& incoming = path_builder.back();
+ // On the outside, we'll take the incoming curve, the outgoing curve, and
+ // reflect them over the line formed by taking the unit tangent vector at times
+ // 0 and 1, respectively, rotated by 90 degrees.
+ Crossings cross;
+
+ // reflect curves along the line that would be given by beveling the join
+ Point tang1 = unitTangentAt(reverse(incoming.toSBasis()), 0.);
+ D2SB newcurve1 = incoming.toSBasis() * reflection(-rot90(tang1), incoming.finalPoint());
+ CubicBezier bzr1 = sbasis_to_cubicbezier(reverse(newcurve1));
+
+ Point tang2 = Geom::unitTangentAt(outgoing.toSBasis(), 0.);
+ D2SB newcurve2 = outgoing.toSBasis() * reflection(-rot90(tang2), outgoing.initialPoint());
+ CubicBezier bzr2 = sbasis_to_cubicbezier(reverse(newcurve2));
+
+ cross = crossings(bzr1, bzr2);
+ if (cross.empty()) {
+ // paths don't cross, fall back to miter
+ miter_curves(path_builder, outgoing, miter_limit, line_width);
+ } else {
+ // reflected join
+ std::pair<CubicBezier, CubicBezier> sub1 = bzr1.subdivide(cross[0].ta);
+ std::pair<CubicBezier, CubicBezier> sub2 = bzr2.subdivide(cross[0].tb);
+
+ // TODO it seems as if a bug in 2geom sometimes doesn't catch the first
+ // crossing of paths, but the second instead; but only sometimes.
+ path_builder.appendNew <CubicBezier> (sub1.first[1], sub1.first[2], sub2.second[0]);
+ path_builder.appendNew <CubicBezier> (sub2.second[1], sub2.second[2], outgoing.initialPoint());
+ }
+}
+
+// Ideal function pointer we want to pass
+typedef void JoinFunc(Geom::Path& /*path_builder*/, Geom::Curve const& /*outgoing*/, double /*miter_limit*/, double /*line_width*/);
+
+/**
+ * Helper function for repeated logic in outlineHalf.
+ */
+static void outlineHelper(Geom::Path& path_builder, Geom::PathVector* path_vec, bool outside, double width, double miter, JoinFunc func)
+{
+ Geom::Curve * cbc2 = path_vec->front()[0].duplicate();
+
+ if (outside) {
+ func(path_builder, *cbc2, miter, width);
+ } else {
+ joinInside(path_builder, *cbc2);
+ }
+
+ // store it
+ Geom::Path temp_path = path_vec->front();
+ if (!outside) {
+ // erase the first segment since the inside join code already appended it
+ temp_path.erase(temp_path.begin());
+ }
+
+ if (temp_path.initialPoint() != path_builder.finalPoint()) {
+ temp_path.setInitial(path_builder.finalPoint());
+ }
+
+ path_builder.append(temp_path);
+
+ delete cbc2;
+}
+
+/**
+ * Offsets exactly one half of a bezier spline (path).
+ * @param path_in The input path to use. (To create the other side use path_in.reverse() )
+ * @param line_width the line width to use (usually you want to divide this by 2)
+ * @param miter_limit the miter parameter
+ * @param func Join function to apply at each join.
+ */
+
+Geom::Path outlineHalf(const Geom::Path& path_in, double line_width, double miter_limit, JoinFunc func)
+{
+ // NOTE: it is important to notice the distinction between a Geom::Path and a livarot ::Path here!
+ // if you do not see "Geom::" there is a different function set!
+
+ Geom::PathVector pv = split_at_cusps(path_in);
+
+ ::Path to_outline;
+ ::Path outlined_result;
+
+ Geom::Path path_builder = Geom::Path(); // the path to store the result in
+ Geom::PathVector* path_vec; // needed because livarot returns a pointer (TODO make this not a pointer)
+
+ // Do two curves at a time for efficiency, since the join function needs to know the outgoing curve as well
+ const size_t k = pv.size();
+ for (size_t u = 0; u < k; u += 2) {
+ to_outline = Path();
+ outlined_result = Path();
+
+ to_outline.LoadPath(pv[u], Geom::identity(), false, false);
+ to_outline.OutsideOutline(&outlined_result, line_width / 2, join_straight, butt_straight, 10);
+ // now a curve has been outside outlined and loaded into outlined_result
+
+ // get the Geom::Path
+ path_vec = outlined_result.MakePathVector();
+
+ // on the first run through, there is no join
+ if (u == 0) {
+ path_builder.start(path_vec->front().initialPoint());
+ path_builder.append(path_vec->front());
+ } else {
+ outlineHelper(path_builder, path_vec, outside_angle(pv[u-1][pv[u-1].size()-1], pv[u][0]), line_width, miter_limit, func);
+ }
+
+ // outline the next segment, but don't store it yet
+ if (path_vec)
+ delete path_vec;
+ path_vec = NULL;
+
+ // odd number of paths
+ if (u < k - 1) {
+ outlined_result = Path();
+ to_outline = Path();
+
+ to_outline.LoadPath(pv[u+1], Geom::Affine(), false, false);
+ to_outline.OutsideOutline(&outlined_result, line_width / 2, join_straight, butt_straight, 10);
+
+ path_vec = outlined_result.MakePathVector();
+ outlineHelper(path_builder, path_vec, outside_angle(pv[u][pv[u].size()-1], pv[u+1][0]), line_width, miter_limit, func);
+
+ if (path_vec)
+ delete path_vec;
+ path_vec = NULL;
+ }
+ }
+
+ if (path_in.closed()) {
+ Geom::Curve * cbc1;
+ Geom::Curve * cbc2;
+
+ if ( path_in[path_in.size()].isDegenerate() ) {
+ // handle case for last segment curved
+ outlined_result = Path();
+ to_outline = Path();
+
+ Geom::Path oneCurve; oneCurve.append(path_in[0]);
+
+ to_outline.LoadPath(oneCurve, Geom::Affine(), false, false);
+ to_outline.OutsideOutline(&outlined_result, line_width / 2, join_straight, butt_straight, 10);
+
+ path_vec = outlined_result.MakePathVector();
+
+ cbc1 = path_builder[path_builder.size() - 1].duplicate();
+ cbc2 = path_vec->front()[0].duplicate();
+
+ delete path_vec;
+ } else {
+ // handle case for last segment straight
+ // since the path doesn't actually give us access to it, we'll do it ourselves
+ outlined_result = Path();
+ to_outline = Path();
+
+ Geom::Path oneCurve; oneCurve.append(Geom::LineSegment(path_in.finalPoint(), path_in.initialPoint()));
+
+ to_outline.LoadPath(oneCurve, Geom::Affine(), false, false);
+ to_outline.OutsideOutline(&outlined_result, line_width / 2, join_straight, butt_straight, 10);
+
+ path_vec = outlined_result.MakePathVector();
+
+ cbc1 = path_builder[path_builder.size() - 1].duplicate();
+ cbc2 = (*path_vec)[0] [0].duplicate();
+
+ outlineHelper(path_builder, path_vec, outside_angle(path_in[path_in.size()-1], oneCurve[0]), line_width, miter_limit, func);
+
+ delete cbc1;
+ cbc1 = cbc2->duplicate();
+ delete path_vec;
+
+ oneCurve = Geom::Path(); oneCurve.append(path_in[0]);
+
+ to_outline.LoadPath(oneCurve, Geom::Affine(), false, false);
+ to_outline.OutsideOutline(&outlined_result, line_width / 2, join_straight, butt_straight, 10);
+
+ path_vec = outlined_result.MakePathVector();
+ delete cbc2; cbc2 = (*path_vec)[0] [0].duplicate();
+ delete path_vec;
+ }
+
+ Geom::Path temporary;
+ temporary.append(*cbc1);
+
+ Geom::Curve const & prev_curve = path_in[path_in.size()].isDegenerate() ? path_in[path_in.size() - 1] : path_in[path_in.size()];
+ Geom::Path isStraight;
+ isStraight.append(prev_curve);
+ isStraight.append(path_in[0]);
+ // does closing path require a join?
+ if (Geom::split_at_cusps(isStraight).size() > 1) {
+ bool outside = outside_angle(prev_curve, path_in[0]);
+ if (outside) {
+ func(temporary, *cbc2, miter_limit, line_width);
+ } else {
+ joinInside(temporary, *cbc2);
+ path_builder.erase(path_builder.begin());
+ }
+
+ // extract the appended curves
+ path_builder.erase_last();
+ if (Geom::are_near(path_builder.finalPoint(), temporary.initialPoint())) {
+ path_builder.setFinal(temporary.initialPoint());
+ } else {
+ path_builder.appendNew<BezierLine>(temporary.initialPoint());
+ }
+ path_builder.append(temporary);
+ } else {
+ // closing path does not require a join
+ path_builder.setFinal(path_builder.initialPoint());
+ }
+ path_builder.close();
+
+ if (cbc1) delete cbc1;
+ if (cbc2) delete cbc2;
+ }
+
+ return path_builder;
+}
+
+Geom::PathVector outlinePath(const Geom::PathVector& path_in, double line_width, LineJoinType join, ButtTypeMod butt, double miter_lim, bool extrapolate, double start_lean, double end_lean)
+{
+ Geom::PathVector path_out;
+
+ unsigned pv_size = path_in.size();
+ for (unsigned i = 0; i < pv_size; i++) {
+
+ if (path_in[i].size() > 1) {
+ Geom::Path with_direction;
+ Geom::Path against_direction;
+
+ with_direction = Outline::outlineHalf(path_in[i], -line_width, miter_lim, extrapolate ? extrapolate_curves : reflect_curves);
+ against_direction = Outline::outlineHalf(path_in[i].reverse(), -line_width, miter_lim, extrapolate ? extrapolate_curves : reflect_curves);
+
+ Geom::PathBuilder pb;
+
+ pb.moveTo(with_direction.initialPoint());
+ pb.append(with_direction);
+
+ //add in our line caps
+ if (!path_in[i].closed()) {
+ switch (butt) {
+ case BUTT_STRAIGHT:
+ pb.lineTo(against_direction.initialPoint());
+ break;
+ case BUTT_ROUND:
+ pb.arcTo((-line_width) / 2, (-line_width) / 2, 0., true, true, against_direction.initialPoint() );
+ break;
+ case BUTT_POINTY: {
+ Geom::Point end_deriv = -Geom::unitTangentAt(Geom::reverse(path_in[i].back().toSBasis()), 0.);
+ double radius = 0.5 * Geom::distance(with_direction.finalPoint(), against_direction.initialPoint());
+ Geom::Point midpoint = 0.5 * (with_direction.finalPoint() + against_direction.initialPoint()) + radius*end_deriv;
+ pb.lineTo(midpoint);
+ pb.lineTo(against_direction.initialPoint());
+ break;
+ }
+ case BUTT_SQUARE: {
+ Geom::Point end_deriv = -Geom::unitTangentAt(Geom::reverse(path_in[i].back().toSBasis()), 0.);
+ double radius = 0.5 * Geom::distance(with_direction.finalPoint(), against_direction.initialPoint());
+ pb.lineTo(with_direction.finalPoint() + radius*end_deriv);
+ pb.lineTo(against_direction.initialPoint() + radius*end_deriv);
+ pb.lineTo(against_direction.initialPoint());
+ break;
+ }
+ case BUTT_LEANED: {
+ Geom::Point end_deriv = -Geom::unitTangentAt(Geom::reverse(path_in[i].back().toSBasis()), 0.);
+ double maxRadius = (end_lean+0.5) * Geom::distance(with_direction.finalPoint(), against_direction.initialPoint());
+ double minRadius = ((end_lean*-1)+0.5) * Geom::distance(with_direction.finalPoint(), against_direction.initialPoint());
+ pb.lineTo(with_direction.finalPoint() + maxRadius*end_deriv);
+ pb.lineTo(against_direction.initialPoint() + minRadius*end_deriv);
+ pb.lineTo(against_direction.initialPoint());
+ break;
+ }
+ }
+ } else {
+ pb.moveTo(against_direction.initialPoint());
+ }
+
+ pb.append(against_direction);
+
+ //cap (if necessary)
+ if (!path_in[i].closed()) {
+ switch (butt) {
+ case BUTT_STRAIGHT:
+ pb.lineTo(with_direction.initialPoint());
+ break;
+ case BUTT_ROUND:
+ pb.arcTo((-line_width) / 2, (-line_width) / 2, 0., true, true, with_direction.initialPoint() );
+ break;
+ case BUTT_POINTY: {
+ Geom::Point end_deriv = -Geom::unitTangentAt(path_in[i].front().toSBasis(), 0.);
+ double radius = 0.5 * Geom::distance(against_direction.finalPoint(), with_direction.initialPoint());
+ Geom::Point midpoint = 0.5 * (against_direction.finalPoint() + with_direction.initialPoint()) + radius*end_deriv;
+ pb.lineTo(midpoint);
+ pb.lineTo(with_direction.initialPoint());
+ break;
+ }
+ case BUTT_SQUARE: {
+ Geom::Point end_deriv = -Geom::unitTangentAt(path_in[i].front().toSBasis(), 0.);
+ double radius = 0.5 * Geom::distance(against_direction.finalPoint(), with_direction.initialPoint());
+ pb.lineTo(against_direction.finalPoint() + radius*end_deriv);
+ pb.lineTo(with_direction.initialPoint() + radius*end_deriv);
+ pb.lineTo(with_direction.initialPoint());
+ break;
+ }
+ case BUTT_LEANED: {
+ Geom::Point end_deriv = -Geom::unitTangentAt(path_in[i].front().toSBasis(), 0.);
+ double maxRadius = (start_lean+0.5) * Geom::distance(against_direction.finalPoint(), with_direction.initialPoint());
+ double minRadius = ((start_lean*-1)+0.5) * Geom::distance(against_direction.finalPoint(), with_direction.initialPoint());
+ pb.lineTo(against_direction.finalPoint() + minRadius*end_deriv);
+ pb.lineTo(with_direction.initialPoint() + maxRadius*end_deriv);
+ pb.lineTo(with_direction.initialPoint());
+ break;
+ }
+ }
+ }
+ pb.flush();
+ path_out.push_back(pb.peek()[0]);
+ if (path_in[i].closed()) {
+ path_out.push_back(pb.peek()[1]);
+ }
+ } else {
+ Path p = Path();
+ Path outlinepath = Path();
+ ButtType original_butt;
+ switch (butt) {
+ case BUTT_STRAIGHT:
+ original_butt = butt_straight;
+ break;
+ case BUTT_ROUND:
+ original_butt = butt_round;
+ break;
+ case butt_pointy: {
+ original_butt = butt_pointy;
+ break;
+ }
+ case BUTT_SQUARE: {
+ original_butt = butt_square;
+ break;
+ }
+ case BUTT_LEANED: {
+ original_butt = butt_straight;
+ break;
+ }
+ }
+ p.LoadPath(path_in[i], Geom::Affine(), false, false);
+ p.Outline(&outlinepath, line_width / 2, static_cast<join_typ>(join), original_butt, miter_lim);
+ Geom::PathVector *pv_p = outlinepath.MakePathVector();
+ //somewhat hack-ish
+ path_out.push_back( (*pv_p)[0].reverse() );
+ if (pv_p) delete pv_p;
+ }
+ }
+ return path_out;
+}
+
+#define miter_lim fabs(line_width * miter_limit)
+
+Geom::PathVector PathVectorOutline(Geom::PathVector const & path_in, double line_width, ButtTypeMod linecap_type, LineJoinType linejoin_type, double miter_limit, double start_lean, double end_lean)
+{
+ std::vector<Geom::Path> path_out = std::vector<Geom::Path>();
+ if (path_in.empty()) {
+ return path_out;
+ }
+ Path p = Path();
+ Path outlinepath = Path();
+ for (unsigned i = 0; i < path_in.size(); i++) {
+ p.LoadPath(path_in[i], Geom::Affine(), false, ( (i==0) ? false : true));
+ }
+
+ // magic!
+ ButtType original_butt;
+ switch (linecap_type) {
+ case BUTT_STRAIGHT:
+ original_butt = butt_straight;
+ break;
+ case BUTT_ROUND:
+ original_butt = butt_round;
+ break;
+ case butt_pointy: {
+ original_butt = butt_pointy;
+ break;
+ }
+ case BUTT_SQUARE: {
+ original_butt = butt_square;
+ break;
+ }
+ case BUTT_LEANED: {
+ original_butt = butt_straight;
+ break;
+ }
+ }
+ if (linejoin_type <= LINEJOIN_POINTY) {
+ p.Outline(&outlinepath, line_width / 2, static_cast<join_typ>(linejoin_type),
+ original_butt, miter_lim);
+ // fix memory leak
+ std::vector<Geom::Path> *pv_p = outlinepath.MakePathVector();
+ path_out = *pv_p;
+ delete pv_p;
+
+ } else if (linejoin_type == LINEJOIN_REFLECTED) {
+ // reflected arc join
+ path_out = outlinePath(path_in, line_width, static_cast<LineJoinType>(linejoin_type),
+ linecap_type , miter_lim, false, start_lean, end_lean);
+
+ } else if (linejoin_type == LINEJOIN_EXTRAPOLATED) {
+ // extrapolated arc join
+ path_out = outlinePath(path_in, line_width, LINEJOIN_STRAIGHT, linecap_type, miter_lim, true, start_lean, end_lean);
+ }
+
+ return path_out;
+}
+
+Geom::Path PathOutsideOutline(Geom::Path const & path_in, double line_width, LineJoinType linejoin_type, double miter_limit)
+{
+
+ Geom::Path path_out;
+
+ if (linejoin_type <= LINEJOIN_POINTY || path_in.size() <= 1) {
+
+ Geom::PathVector * pathvec;
+
+ Path path_tangent = Path();
+ Path path_outline = Path();
+ path_outline.LoadPath(path_in, Geom::Affine(), false, false);
+ path_outline.OutsideOutline(&path_tangent, line_width / 2, static_cast<join_typ>(linejoin_type), butt_straight, miter_lim);
+
+ pathvec = path_tangent.MakePathVector();
+ path_out = pathvec->front();
+ delete pathvec;
+ return path_out;
+ } else if (linejoin_type == LINEJOIN_REFLECTED) {
+ path_out = outlineHalf(path_in, line_width, miter_lim, reflect_curves);
+ return path_out;
+ } else if (linejoin_type == LINEJOIN_EXTRAPOLATED) {
+ path_out = outlineHalf(path_in, line_width, miter_lim, extrapolate_curves);
+ return path_out;
+ }
+ return path_out;
+}
+
+} // namespace Outline
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8 :
diff --git a/src/live_effects/pathoutlineprovider.h b/src/live_effects/pathoutlineprovider.h
new file mode 100644
index 000000000..c17584be2
--- /dev/null
+++ b/src/live_effects/pathoutlineprovider.h
@@ -0,0 +1,55 @@
+#ifndef SEEN_PATH_OUTLINE_H
+#define SEEN_PATH_OUTLINE_H
+
+/* Author:
+ * Liam P. White <inkscapebrony@gmail.com>
+ *
+ * Copyright (C) 2014 Author
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <livarot/Path.h>
+#include <livarot/LivarotDefs.h>
+
+enum LineJoinType {
+ LINEJOIN_STRAIGHT,
+ LINEJOIN_ROUND,
+ LINEJOIN_POINTY,
+ LINEJOIN_REFLECTED,
+ LINEJOIN_EXTRAPOLATED
+};
+enum ButtTypeMod {
+ BUTT_STRAIGHT,
+ BUTT_ROUND,
+ BUTT_SQUARE,
+ BUTT_POINTY,
+ BUTT_LEANED
+};
+
+namespace Geom
+{
+ Geom::CubicBezier sbasis_to_cubicbezier(Geom::D2<Geom::SBasis> const & sbasis_in);
+ std::vector<Geom::Path> split_at_cusps(const Geom::Path& in);
+}
+
+namespace Outline
+{
+ unsigned bezierOrder (const Geom::Curve* curve_in);
+ std::vector<Geom::Path> PathVectorOutline(std::vector<Geom::Path> const & path_in, double line_width, ButtTypeMod linecap_type,
+ LineJoinType linejoin_type, double miter_limit, double start_lean = 0, double end_lean = 0);
+ Geom::Path PathOutsideOutline(Geom::Path const & path_in, double line_width, LineJoinType linejoin_type, double miter_limit);
+}
+
+#endif // SEEN_PATH_OUTLINE_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8 :
diff --git a/src/macros.h b/src/macros.h
index b221ebdc2..cbb9bca78 100644
--- a/src/macros.h
+++ b/src/macros.h
@@ -1,7 +1,7 @@
-#ifndef __MACROS_H__
-#define __MACROS_H__
+#ifndef SEEN_MACROS_H
+#define SEEN_MACROS_H
-/*
+/**
* Useful macros for inkscape
*
* Author:
@@ -12,6 +12,9 @@
* Released under GNU GPL
*/
+// I'm of the opinion that this file should be removed, so I will in the future take the necessary steps to wipe it out.
+// Macros are not in general bad, but these particular ones are rather ugly. Especially that sp_round one. --Liam
+
#ifdef SP_MACROS_SILENT
#define SP_PRINT_MATRIX(s,m)
#define SP_PRINT_TRANSFORM(s,t)
@@ -51,4 +54,4 @@
fill-column:99
End:
*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8 :
diff --git a/src/main-cmdlineact.h b/src/main-cmdlineact.h
index fe11357fa..c8ef64f10 100644
--- a/src/main-cmdlineact.h
+++ b/src/main-cmdlineact.h
@@ -15,20 +15,18 @@
* Released under GNU GPL v2.x, read the file 'COPYING' for more information
*/
-#include <glib.h>
-
namespace Inkscape {
class ActionContext;
class CmdLineAction {
bool _isVerb;
- gchar * _arg;
+ char * _arg;
static std::list <CmdLineAction *> _list;
public:
- CmdLineAction (bool isVerb, gchar const * arg);
+ CmdLineAction (bool isVerb, char const * arg);
virtual ~CmdLineAction ();
void doIt (ActionContext const & context);
diff --git a/src/main.cpp b/src/main.cpp
index 00d0fcbb6..12ddb76e6 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -64,7 +64,7 @@
#include "layer-model.h"
#include "selection.h"
#include "sp-object.h"
-#include "interface.h"
+#include "ui/interface.h"
#include "print.h"
#include "color.h"
#include "sp-item.h"
@@ -322,7 +322,7 @@ struct poptOption options[] = {
{"export-dpi", 'd',
POPT_ARG_STRING, &sp_export_dpi, SP_ARG_EXPORT_DPI,
- N_("Resolution for exporting to bitmap and for rasterization of filters in PS/EPS/PDF (default 90)"),
+ N_("Resolution for exporting to bitmap and for rasterization of filters in PS/EPS/PDF (default 96)"),
N_("DPI")},
{"export-area", 'a',
@@ -1145,7 +1145,8 @@ static int sp_process_file_list(GSList *fl)
if (!sp_export_svg && (sp_vacuum_defs || has_performed_actions)) {
// save under the name given in the command line
- sp_repr_save_file(doc->rdoc, filename, SP_SVG_NS_URI);
+ Inkscape::Extension::save(Inkscape::Extension::db.get("org.inkscape.output.svg.inkscape"), doc, filename, false,
+ false, false, Inkscape::Extension::FILE_SAVE_METHOD_INKSCAPE_SVG);
}
if (sp_global_printer) {
sp_print_document_to_file(doc, sp_global_printer);
@@ -1157,6 +1158,7 @@ static int sp_process_file_list(GSList *fl)
if (sp_export_text_to_path) {
GSList *items = NULL;
SPRoot *root = doc->getRoot();
+ doc->ensureUpToDate();
for ( SPObject *iter = root->firstChild(); iter ; iter = iter->getNext()) {
SPItem* item = (SPItem*) iter;
if (! (SP_IS_TEXT(item) || SP_IS_FLOWTEXT(item) || SP_IS_GROUP(item))) {
@@ -1176,14 +1178,25 @@ static int sp_process_file_list(GSList *fl)
g_slist_free (selected);
g_slist_free (to_select);
}
+ if(sp_export_id) {
+ doc->ensureUpToDate();
- Inkscape::XML::Document *rdoc;
- Inkscape::XML::Node *repr;
- rdoc = sp_repr_document_new("svg:svg");
- repr = rdoc->root();
- repr = doc->getRoot()->updateRepr(rdoc, repr, SP_OBJECT_WRITE_BUILD);
- sp_repr_save_rebased_file(repr->document(), sp_export_svg, SP_SVG_NS_URI,
- doc->getBase(), sp_export_svg);
+ // "crop" the document to the specified object, cleaning as we go.
+ SPObject *obj = doc->getObjectById(sp_export_id);
+ Geom::OptRect const bbox(SP_ITEM(obj)->visualBounds());
+
+ if (bbox) {
+ doc->fitToRect(*bbox, false);
+ }
+
+ if (sp_export_id_only) {
+ // If -j then remove all other objects to complete the "crop"
+ doc->getRoot()->cropToObject(obj);
+ }
+ }
+
+ Inkscape::Extension::save(Inkscape::Extension::db.get("org.inkscape.output.svg.plain"), doc, sp_export_svg, false,
+ false, false, Inkscape::Extension::FILE_SAVE_METHOD_SAVE_COPY);
}
if (sp_export_ps) {
retVal |= do_export_ps_pdf(doc, sp_export_ps, "image/x-postscript");
@@ -1725,12 +1738,12 @@ static int do_export_ps_pdf(SPDocument* doc, gchar const* uri, char const* mime)
} else {
(*i)->set_param_bool("blurToBitmap", TRUE);
- gdouble dpi = 90.0;
+ gdouble dpi = 96.0;
if (sp_export_dpi) {
dpi = atof(sp_export_dpi);
if ((dpi < 1) || (dpi > 10000.0)) {
- g_warning("DPI value %s out of range [1 - 10000]. Using 90 dpi instead.", sp_export_dpi);
- dpi = 90;
+ g_warning("DPI value %s out of range [1 - 10000]. Using 96 dpi instead.", sp_export_dpi);
+ dpi = 96;
}
}
diff --git a/src/menus-skeleton.h b/src/menus-skeleton.h
index f888555d2..18a26d82c 100644
--- a/src/menus-skeleton.h
+++ b/src/menus-skeleton.h
@@ -178,6 +178,9 @@ static char const menus_skeleton[] =
" <verb verb-id=\"DialogLayers\" />\n"
" </submenu>\n"
" <submenu name=\"" N_("_Object") "\">\n"
+" <verb verb-id=\"DialogObjects\" />\n"
+" <verb verb-id=\"DialogTags\" />\n"
+" <separator/>\n"
" <verb verb-id=\"DialogFillStroke\" />\n"
" <verb verb-id=\"DialogObjectProperties\" />\n"
" <verb verb-id=\"DialogSymbols\" />\n"
diff --git a/src/message-context.h b/src/message-context.h
index a92874d68..ea86c4ec0 100644
--- a/src/message-context.h
+++ b/src/message-context.h
@@ -14,8 +14,9 @@
#ifndef SEEN_INKSCAPE_MESSAGE_CONTEXT_H
#define SEEN_INKSCAPE_MESSAGE_CONTEXT_H
-#include <stdarg.h>
+#include <cstdarg>
#include <glib.h>
+
#include "message.h"
namespace Inkscape {
@@ -48,7 +49,7 @@ public:
* @param type the message type
* @param message the message text
*/
- void set(MessageType type, gchar const *message);
+ void set(MessageType type, char const *message);
/** @brief pushes a message on the stack using prinf-style formatting,
* and replacing our old message
@@ -56,7 +57,7 @@ public:
* @param type the message type
* @param format a printf-style formatting string
*/
- void setF(MessageType type, gchar const *format, ...) G_GNUC_PRINTF(3,4);
+ void setF(MessageType type, char const *format, ...) G_GNUC_PRINTF(3,4);
/** @brief pushes a message on the stack using printf-style formatting,
* and a stdarg argument list
@@ -65,7 +66,7 @@ public:
* @param format a printf-style formatting string
* @param args printf-style arguments
*/
- void setVF(MessageType type, gchar const *format, va_list args);
+ void setVF(MessageType type, char const *format, va_list args);
/** @brief pushes a message onto the stack for a brief period of time
* without disturbing our "current" message
@@ -73,7 +74,7 @@ public:
* @param type the message type
* @param message the message text
*/
- void flash(MessageType type, gchar const *message);
+ void flash(MessageType type, char const *message);
/** @brief pushes a message onto the stack for a brief period of time
* using printf-style formatting, without disturbing our current
@@ -82,7 +83,7 @@ public:
* @param type the message type
* @param format a printf-style formatting string
*/
- void flashF(MessageType type, gchar const *format, ...) G_GNUC_PRINTF(3,4);
+ void flashF(MessageType type, char const *format, ...) G_GNUC_PRINTF(3,4);
/** @brief pushes a message onto the stack for a brief period of time
* using printf-style formatting and a stdarg argument list;
@@ -92,7 +93,7 @@ public:
* @param format a printf-style formatting string
* @param args printf-style arguments
*/
- void flashVF(MessageType type, gchar const *format, va_list args);
+ void flashVF(MessageType type, char const *format, va_list args);
/** @brief removes our current message from the stack */
void clear();
diff --git a/src/message-stack.h b/src/message-stack.h
index 3b8307761..42bf4e8a7 100644
--- a/src/message-stack.h
+++ b/src/message-stack.h
@@ -16,11 +16,12 @@
#ifndef SEEN_INKSCAPE_MESSAGE_STACK_H
#define SEEN_INKSCAPE_MESSAGE_STACK_H
-#include <stddef.h>
-#include <sigc++/sigc++.h>
-#include <glib.h>
-#include <stdarg.h>
+#include <cstdarg>
+#include <cstddef>
+#include <glib.h> // G_GNUC_PRINTF is the only thing worth having from here
#include <glibmm/ustring.h>
+#include <sigc++/sigc++.h>
+
#include "gc-managed.h"
#include "gc-finalized.h"
#include "gc-anchored.h"
@@ -61,14 +62,14 @@ public:
/** @brief returns the text of the message currently at the top of
* the stack
*/
- gchar const *currentMessage() {
+ char const *currentMessage() {
return _messages ? _messages->message : NULL;
}
/** @brief connects to the "changed" signal which is emitted whenever
* the topmost message on the stack changes.
*/
- sigc::connection connectChanged(sigc::slot<void, MessageType, gchar const *> slot)
+ sigc::connection connectChanged(sigc::slot<void, MessageType, char const *> slot)
{
return _changed_signal.connect(slot);
}
@@ -80,7 +81,7 @@ public:
*
* @return the id of the pushed message
*/
- MessageId push(MessageType type, gchar const *message);
+ MessageId push(MessageType type, char const *message);
/** @brief pushes a message onto the stack using printf-like formatting
*
@@ -89,7 +90,7 @@ public:
*
* @return the id of the pushed message
*/
- MessageId pushF(MessageType type, gchar const *format, ...) G_GNUC_PRINTF(3,4);
+ MessageId pushF(MessageType type, char const *format, ...) G_GNUC_PRINTF(3,4);
/** @brief pushes a message onto the stack using printf-like formatting,
* using a stdarg argument list
@@ -100,7 +101,7 @@ public:
*
* @return the id of the pushed message
*/
- MessageId pushVF(MessageType type, gchar const *format, va_list args);
+ MessageId pushVF(MessageType type, char const *format, va_list args);
/** @brief removes a message from the stack, given its id
*
@@ -119,7 +120,7 @@ public:
*
* @return the id of the pushed message
*/
- MessageId flash(MessageType type, gchar const *message);
+ MessageId flash(MessageType type, char const *message);
/**
* Temporarily pushes a message onto the stack.
@@ -140,7 +141,7 @@ public:
*
* @return the id of the pushed message
*/
- MessageId flashF(MessageType type, gchar const *format, ...) G_GNUC_PRINTF(3,4);
+ MessageId flashF(MessageType type, char const *format, ...) G_GNUC_PRINTF(3,4);
/** @brief temporarily pushes a message onto the stack using
* printf-like formatting, using a stdarg argument list
@@ -151,7 +152,7 @@ public:
*
* @return the id of the pushed message
*/
- MessageId flashVF(MessageType type, gchar const *format, va_list args);
+ MessageId flashVF(MessageType type, char const *format, va_list args);
private:
struct Message {
@@ -167,13 +168,13 @@ private:
void operator=(MessageStack const &); // no assign
/// pushes a message onto the stack with an optional timeout
- MessageId _push(MessageType type, guint lifetime, gchar const *message);
+ MessageId _push(MessageType type, unsigned int lifetime, char const *message);
Message *_discard(Message *m); ///< frees a message struct and returns the next such struct in the list
void _emitChanged(); ///< emits the "changed" signal
- static gboolean _timeout(gpointer data); ///< callback to expire flashed messages
+ static int _timeout(void* data); ///< callback to expire flashed messages
- sigc::signal<void, MessageType, gchar const *> _changed_signal;
+ sigc::signal<void, MessageType, char const *> _changed_signal;
Message *_messages; ///< the stack of messages as a linked list
MessageId _next_id; ///< the next message id to assign
};
diff --git a/src/number-opt-number.h b/src/number-opt-number.h
index d9ab56102..f6fe584f9 100644
--- a/src/number-opt-number.h
+++ b/src/number-opt-number.h
@@ -13,27 +13,23 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
#include <glib.h>
#include <glib/gprintf.h>
-//todo: use glib instead of stdlib
-#include <stdlib.h>
+#include <cstdlib>
+
#include "svg/stringstream.h"
class NumberOptNumber {
public:
- gfloat number;
+ float number;
- gfloat optNumber;
+ float optNumber;
- guint _set : 1;
+ unsigned int _set : 1;
- guint optNumber_set : 1;
+ unsigned int optNumber_set : 1;
NumberOptNumber()
{
@@ -44,27 +40,27 @@ public:
optNumber_set = FALSE;
}
- gfloat getNumber()
+ float getNumber()
{
if(_set)
return number;
return -1;
}
- gfloat getOptNumber()
+ float getOptNumber()
{
if(optNumber_set)
return optNumber;
return -1;
}
- void setOptNumber(gfloat num)
+ void setOptNumber(float num)
{
optNumber_set = true;
optNumber = num;
}
- void setNumber(gfloat num)
+ void setNumber(float num)
{
_set = true;
number = num;
@@ -78,7 +74,7 @@ public:
return _set;
}
- gchar *getValueString()
+ char *getValueString()
{
Inkscape::SVGOStringStream os;
@@ -96,12 +92,12 @@ public:
return g_strdup(os.str().c_str());
}
- void set(gchar const *str)
+ void set(char const *str)
{
if(!str)
return;
- gchar **values = g_strsplit(str, " ", 2);
+ char **values = g_strsplit(str, " ", 2);
if( values[0] != NULL )
{
diff --git a/src/object-hierarchy.cpp b/src/object-hierarchy.cpp
index f2bf177dc..f241da83d 100644
--- a/src/object-hierarchy.cpp
+++ b/src/object-hierarchy.cpp
@@ -9,6 +9,9 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
+#include <cstdio>
+#include <cassert>
+
#include "sp-object.h"
#include "object-hierarchy.h"
@@ -32,7 +35,7 @@ void ObjectHierarchy::clear() {
}
void ObjectHierarchy::setTop(SPObject *object) {
- g_return_if_fail(object != NULL);
+ if (object == NULL) { printf("Assertion object != NULL failed\n"); return; }
if ( top() == object ) {
return;
@@ -53,8 +56,8 @@ void ObjectHierarchy::setTop(SPObject *object) {
}
void ObjectHierarchy::_addTop(SPObject *senior, SPObject *junior) {
- g_assert(junior != NULL);
- g_assert(senior != NULL);
+ assert(junior != NULL);
+ assert(senior != NULL);
SPObject *object = junior->parent;
do {
@@ -64,7 +67,7 @@ void ObjectHierarchy::_addTop(SPObject *senior, SPObject *junior) {
}
void ObjectHierarchy::_addTop(SPObject *object) {
- g_assert(object != NULL);
+ assert(object != NULL);
_hierarchy.push_back(_attach(object));
_added_signal.emit(object);
}
@@ -82,7 +85,7 @@ void ObjectHierarchy::_trimAbove(SPObject *limit) {
}
void ObjectHierarchy::setBottom(SPObject *object) {
- g_return_if_fail(object != NULL);
+ if (object == NULL) { printf("assertion object != NULL failed\n"); return; }
if ( bottom() == object ) {
return;
@@ -125,8 +128,8 @@ void ObjectHierarchy::_trimBelow(SPObject *limit) {
}
void ObjectHierarchy::_addBottom(SPObject *senior, SPObject *junior) {
- g_assert(junior != NULL);
- g_assert(senior != NULL);
+ assert(junior != NULL);
+ assert(senior != NULL);
if ( junior != senior ) {
_addBottom(senior, junior->parent);
@@ -135,15 +138,15 @@ void ObjectHierarchy::_addBottom(SPObject *senior, SPObject *junior) {
}
void ObjectHierarchy::_addBottom(SPObject *object) {
- g_assert(object != NULL);
+ assert(object != NULL);
_hierarchy.push_front(_attach(object));
_added_signal.emit(object);
}
void ObjectHierarchy::_trim_for_release(SPObject *object) {
this->_trimBelow(object);
- g_assert(!this->_hierarchy.empty());
- g_assert(this->_hierarchy.front().object == object);
+ assert(!this->_hierarchy.empty());
+ assert(this->_hierarchy.front().object == object);
sp_object_ref(object, NULL);
this->_detach(this->_hierarchy.front());
diff --git a/src/object-hierarchy.h b/src/object-hierarchy.h
index 0343d850e..16004c81a 100644
--- a/src/object-hierarchy.h
+++ b/src/object-hierarchy.h
@@ -10,12 +10,11 @@
#ifndef SEEN_INKSCAPE_OBJECT_HIERARCHY_H
#define SEEN_INKSCAPE_OBJECT_HIERARCHY_H
+#include <cstddef>
#include <exception>
#include <list>
-#include <stddef.h>
#include <sigc++/connection.h>
#include <sigc++/signal.h>
-#include <glib.h>
class SPObject;
diff --git a/src/object-snapper.cpp b/src/object-snapper.cpp
index 3b8956bc8..338f91463 100644
--- a/src/object-snapper.cpp
+++ b/src/object-snapper.cpp
@@ -91,7 +91,8 @@ void Inkscape::ObjectSnapper::_findCandidates(SPObject* parent,
for ( SPObject *o = parent->firstChild(); o; o = o->getNext() ) {
g_assert(dt != NULL);
- if (SP_IS_ITEM(o) && !(dt->itemIsHidden(SP_ITEM(o)) && !clip_or_mask)) {
+ SPItem *item = dynamic_cast<SPItem *>(o);
+ if (item && !(dt->itemIsHidden(item) && !clip_or_mask)) {
// Snapping to items in a locked layer is allowed
// Don't snap to hidden objects, unless they're a clipped path or a mask
/* See if this item is on the ignore list */
@@ -104,23 +105,22 @@ void Inkscape::ObjectSnapper::_findCandidates(SPObject* parent,
}
if (it == NULL || i == it->end()) {
- SPItem *item = SP_ITEM(o);
if (item) {
if (!clip_or_mask) { // cannot clip or mask more than once
// The current item is not a clipping path or a mask, but might
// still be the subject of clipping or masking itself ; if so, then
// we should also consider that path or mask for snapping to
- SPObject *obj = SP_OBJECT(item->clip_ref ? item->clip_ref->getObject() : NULL);
+ SPObject *obj = item->clip_ref ? item->clip_ref->getObject() : NULL;
if (obj && _snapmanager->snapprefs.isTargetSnappable(SNAPTARGET_PATH_CLIP)) {
_findCandidates(obj, it, false, bbox_to_snap, true, item->i2doc_affine());
}
- obj = SP_OBJECT(item->mask_ref ? item->mask_ref->getObject() : NULL);
+ obj = item->mask_ref ? item->mask_ref->getObject() : NULL;
if (obj && _snapmanager->snapprefs.isTargetSnappable(SNAPTARGET_PATH_MASK)) {
_findCandidates(obj, it, false, bbox_to_snap, true, item->i2doc_affine());
}
}
- if (SP_IS_GROUP(o)) {
+ if (dynamic_cast<SPGroup *>(item)) {
_findCandidates(o, it, false, bbox_to_snap, clip_or_mask, additional_affine);
} else {
Geom::OptRect bbox_of_item;
@@ -147,6 +147,10 @@ void Inkscape::ObjectSnapper::_findCandidates(SPObject* parent,
// For debugging: print the id of the candidate to the console
// SPObject *obj = (SPObject*)item;
// std::cout << "Snap candidate added: " << obj->getId() << std::endl;
+ if (_candidates->size() > 200) { // This makes Inkscape crawl already
+ std::cout << "Warning: limit of 200 snap target paths reached, some will be ignored" << std::endl;
+ break;
+ }
}
}
}
@@ -193,8 +197,10 @@ void Inkscape::ObjectSnapper::_collectNodes(SnapSourceType const &t,
for (std::vector<SnapCandidateItem>::const_iterator i = _candidates->begin(); i != _candidates->end(); ++i) {
//Geom::Affine i2doc(Geom::identity());
SPItem *root_item = (*i).item;
- if (SP_IS_USE((*i).item)) {
- root_item = SP_USE((*i).item)->root();
+
+ SPUse *use = dynamic_cast<SPUse *>((*i).item);
+ if (use) {
+ root_item = use->root();
}
g_return_if_fail(root_item);
@@ -285,7 +291,7 @@ void Inkscape::ObjectSnapper::_snapNodes(IntermSnapResults &isr,
for (std::vector<SnapCandidatePoint>::const_iterator k = _points_to_snap_to->begin(); k != _points_to_snap_to->end(); ++k) {
if (_allowSourceToSnapToTarget(p.getSourceType(), (*k).getTargetType(), strict_snapping)) {
Geom::Point target_pt = (*k).getPoint();
- Geom::Coord dist = Geom::infinity();
+ Geom::Coord dist = Geom::L2(target_pt - p.getPoint()); // Default: free (unconstrained) snapping
if (!c.isUndefined()) {
// We're snapping to nodes along a constraint only, so find out if this node
// is at the constraint, while allowing for a small margin
@@ -295,9 +301,6 @@ void Inkscape::ObjectSnapper::_snapNodes(IntermSnapResults &isr,
continue;
}
dist = Geom::L2(target_pt - p_proj_on_constraint);
- } else {
- // Free (unconstrained) snapping
- dist = Geom::L2(target_pt - p.getPoint());
}
if (dist < getSnapperTolerance() && dist < s.getSnapDistance()) {
@@ -381,9 +384,10 @@ void Inkscape::ObjectSnapper::_collectPaths(Geom::Point /*p*/,
Geom::Affine i2doc(Geom::identity());
SPItem *root_item = NULL;
/* We might have a clone at hand, so make sure we get the root item */
- if (SP_IS_USE((*i).item)) {
- i2doc = SP_USE((*i).item)->get_root_transform();
- root_item = SP_USE((*i).item)->root();
+ SPUse *use = dynamic_cast<SPUse *>((*i).item);
+ if (use) {
+ i2doc = use->get_root_transform();
+ root_item = use->root();
g_return_if_fail(root_item);
} else {
i2doc = (*i).item->i2doc_affine();
@@ -395,7 +399,7 @@ void Inkscape::ObjectSnapper::_collectPaths(Geom::Point /*p*/,
//Add the item's path to snap to
if (_snapmanager->snapprefs.isTargetSnappable(SNAPTARGET_PATH, SNAPTARGET_PATH_INTERSECTION, SNAPTARGET_TEXT_BASELINE)) {
if (p_is_other || p_is_a_node || (!_snapmanager->snapprefs.getStrictSnapping() && p_is_a_bbox)) {
- if (SP_IS_TEXT(root_item) || SP_IS_FLOWTEXT(root_item)) {
+ if (dynamic_cast<SPText *>(root_item) || dynamic_cast<SPFlowtext *>(root_item)) {
if (_snapmanager->snapprefs.isTargetSnappable(SNAPTARGET_TEXT_BASELINE)) {
// Snap to the text baseline
Text::Layout const *layout = te_get_layout(static_cast<SPItem *>(root_item));
@@ -410,15 +414,17 @@ void Inkscape::ObjectSnapper::_collectPaths(Geom::Point /*p*/,
// the CPU, so we'll only snap to paths having no more than 500 nodes
// This also leads to a lag of approx. 500 msec (in my lousy test set-up).
bool very_complex_path = false;
- if (SP_IS_PATH(root_item)) {
- very_complex_path = SP_PATH(root_item)->nodesInPath() > 500;
+ SPPath *path = dynamic_cast<SPPath *>(root_item);
+ if (path) {
+ very_complex_path = path->nodesInPath() > 500;
}
if (!very_complex_path && root_item && _snapmanager->snapprefs.isTargetSnappable(SNAPTARGET_PATH, SNAPTARGET_PATH_INTERSECTION)) {
SPCurve *curve = NULL;
- if (SP_IS_SHAPE(root_item)) {
- curve = SP_SHAPE(root_item)->getCurve();
- }/* else if (SP_IS_TEXT(root_item) || SP_IS_FLOWTEXT(root_item)) {
+ SPShape *shape = dynamic_cast<SPShape *>(root_item);
+ if (shape) {
+ curve = shape->getCurve();
+ }/* else if (dynamic_cast<SPText *>(root_item) || dynamic_cast<SPFlowtext *>(root_item)) {
curve = te_get_layout(root_item)->convertToCurves();
}*/
if (curve) {
@@ -673,7 +679,7 @@ void Inkscape::ObjectSnapper::_snapPathsConstrained(IntermSnapResults &isr,
(*p_inters) = dt->doc2dt(*p_inters);
// Construct a snapped point
Geom::Coord dist = Geom::L2(p.getPoint() - *p_inters);
- SnappedPoint s = SnappedPoint(*p_inters, p.getSourceType(), p.getSourceNum(), k->target_type, dist, getSnapperTolerance(), getSnapperAlwaysSnap(), true, k->target_bbox);;
+ SnappedPoint s = SnappedPoint(*p_inters, p.getSourceType(), p.getSourceNum(), k->target_type, dist, getSnapperTolerance(), getSnapperAlwaysSnap(), true, false, k->target_bbox);
// Store the snapped point
if (dist <= tolerance) { // If the intersection is within snapping range, then we might snap to it
isr.points.push_back(s);
@@ -710,10 +716,11 @@ void Inkscape::ObjectSnapper::freeSnap(IntermSnapResults &isr,
* That path must not be ignored however when snapping to the paths, so we add it here
* manually when applicable
*/
- SPPath *path = NULL;
+ SPPath const *path = NULL;
if (it != NULL) {
- if (it->size() == 1 && SP_IS_PATH(*it->begin())) {
- path = SP_PATH(*it->begin());
+ SPPath const *tmpPath = dynamic_cast<SPPath const *>(*it->begin());
+ if ((it->size() == 1) && tmpPath) {
+ path = tmpPath;
} // else: *it->begin() might be a SPGroup, e.g. when editing a LPE of text that has been converted to a group of paths
// as reported in bug #356743. In that case we can just ignore it, i.e. not snap to this item
}
diff --git a/src/object-test.h b/src/object-test.h
new file mode 100644
index 000000000..d6a9dbbd3
--- /dev/null
+++ b/src/object-test.h
@@ -0,0 +1,233 @@
+#ifndef SEEN_OBJECT_TEST_H
+#define SEEN_OBJECT_TEST_H
+
+#include <cassert>
+#include <ctime>
+#include <cxxtest/TestSuite.h>
+#include <string>
+#include <vector>
+
+#include "document.h"
+#include "sp-item-group.h"
+#include "sp-object.h"
+#include "sp-path.h"
+#include "sp-root.h"
+#include "xml/document.h"
+#include "xml/node.h"
+
+class ObjectTest : public CxxTest::TestSuite
+{
+public:
+ virtual ~ObjectTest() {}
+
+ static ObjectTest *createSuite() { return new ObjectTest(); }
+ static void destroySuite(ObjectTest *suite) { delete suite; }
+
+ void testObjects()
+ {
+ clock_t begin, end;
+ // Sample document
+ // svg:svg
+ // svg:defs
+ // svg:path
+ // svg:linearGradient
+ // svg:stop
+ // svg:filter
+ // svg:feGaussianBlur (feel free to implement for other filters)
+ // svg:clipPath
+ // svg:rect
+ // svg:g
+ // svg:use
+ // svg:circle
+ // svg:ellipse
+ // svg:text
+ // svg:polygon
+ // svg:polyline
+ // svg:image
+ // svg:line
+
+ char const *docString =
+ "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n"
+ "<!-- just a comment -->\n"
+ "<title id=\"title\">SVG test</title>\n"
+ "<defs>\n"
+ " <path id=\"P\" d=\"M -21,-4 -5,0 -18,12 -3,4 -4,21 0,5 12,17 4,2 21,3 5,-1 17,-12 2,-4 3,-21 -1,-5 -12,-18 -4,-3z\"/>\n"
+ " <linearGradient id=\"LG\" x1=\"0%\" y1=\"0%\" x2=\"100%\" y2=\"0%\">\n"
+ " <stop offset=\"0%\" style=\"stop-color:#ffff00;stop-opacity:1\"/>\n"
+ " <stop offset=\"100%\" style=\"stop-color:red;stop-opacity:1\"/>\n"
+ " </linearGradient>\n"
+ " <clipPath id=\"clip\" clipPathUnits=\"userSpaceOnUse\">\n"
+ " <rect x=\"10\" y=\"10\" width=\"100\" height=\"100\"/>\n"
+ " </clipPath>\n"
+ " <filter style=\"color-interpolation-filters:sRGB\" id=\"filter\" x=\"-0.15\" width=\"1.34\" y=\"0\" height=\"1\">\n"
+ " <feGaussianBlur stdDeviation=\"4.26\"/>\n"
+ " </filter>\n"
+ "</defs>\n"
+
+ "<g id=\"G\" transform=\"skewX(10.5) translate(9,5)\">\n"
+ " <use id=\"U\" xlink:href=\"#P\" opacity=\"0.5\" fill=\"#1dace3\" transform=\"rotate(4)\"/>\n"
+ " <circle id=\"C\" cx=\"45.5\" cy=\"67\" r=\"23\" fill=\"#000\"/>\n"
+ " <ellipse id=\"E\" cx=\"200\" cy=\"70\" rx=\"85\" ry=\"55\" fill=\"url(#LG)\"/>\n"
+ " <text id=\"T\" fill=\"#fff\" style=\"font-size:45;font-family:Verdana\" x=\"150\" y=\"86\">TEST</text>\n"
+ " <polygon id=\"PG\" points=\"60,20 100,40 100,80 60,100 20,80 20,40\" clip-path=\"url(#clip)\" filter=\"url(#filter)\"/>\n"
+ " <polyline id=\"PL\" points=\"0,40 40,40 40,80 80,80 80,120 120,120 120,160\" style=\"fill:none;stroke:red;stroke-width:4\"/>\n"
+ " <image id=\"I\" xlink:href=\"data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjE4MCIgd2lkdGg9IjUwMCI+PHBhdGggZD0iTTAsNDAgNDAsNDAgNDAs" // this is one line
+ "ODAgODAsODAgODAsMTIwIDEyMCwxMjAgMTIwLDE2MCIgc3R5bGU9ImZpbGw6d2hpdGU7c3Ryb2tlOnJlZDtzdHJva2Utd2lkdGg6NCIvPjwvc3ZnPgo=\"/>\n"
+ " <line id=\"L\" x1=\"20\" y1=\"100\" x2=\"100\" y2=\"20\" stroke=\"black\" stroke-width=\"2\"/>\n"
+ "</g>\n"
+ "</svg>\n";
+
+ begin = clock();
+ SPDocument *doc = SPDocument::createNewDocFromMem(docString, strlen(docString), false);
+ end = clock();
+
+ assert(doc != NULL); // cannot continue if doc is null, abort!
+ assert(doc->getRoot() != NULL);
+
+ SPRoot *root = doc->getRoot();
+ assert(root->getRepr() != NULL);
+ assert(root->hasChildren());
+
+ std::cout << "Took " << double(end - begin) / double(CLOCKS_PER_SEC) << " seconds to construct the test document\n";
+
+ SPPath *path = dynamic_cast<SPPath *>(doc->getObjectById("P"));
+ testClones(path);
+
+ SPGroup *group = dynamic_cast<SPGroup *>(doc->getObjectById("G"));
+ testGrouping(group);
+
+ // Test parent behavior
+ SPObject *child = root->firstChild();
+ assert(child != NULL);
+ TS_ASSERT(child->parent == root);
+ TS_ASSERT(child->document == doc);
+ TS_ASSERT(root->isAncestorOf(child));
+
+ // Test list behavior
+ SPObject *next = child->getNext();
+ SPObject *prev = next;
+ TS_ASSERT(next->getPrev() == child);
+ prev = next;
+ next = next->getNext();
+ while (next != NULL) {
+ // Walk the list
+ TS_ASSERT(next->getPrev() == prev);
+ prev = next;
+ next = next->getNext();
+ }
+ TS_ASSERT(child->lastChild() == next);
+
+ // Test hrefcount
+ TS_ASSERT(path->isReferenced());
+ }
+
+ void testClones(SPPath *path)
+ {
+ clock_t begin, end;
+
+ assert(path != NULL);
+
+ // Since we don't yet have any clean way to do this (FIXME), we'll abuse the XML tree a bit.
+ Inkscape::XML::Node *node = path->getRepr();
+ assert(node != NULL);
+
+ Inkscape::XML::Document *xml_doc = node->document();
+
+ Inkscape::XML::Node *parent = node->parent();
+ assert(parent != NULL);
+
+ TS_TRACE("Benchmarking clones...");
+ const size_t num_clones = 10000;
+
+ std::string href(std::string("#") + std::string(path->getId()));
+ std::vector<Inkscape::XML::Node *> clones(num_clones, NULL);
+
+ begin = clock();
+ // Create num_clones clones of this path and stick them in the document
+ for (size_t i = 0; i < num_clones; ++i) {
+ Inkscape::XML::Node *clone = xml_doc->createElement("svg:use");
+ Inkscape::GC::release(clone);
+ clone->setAttribute("xlink:href", href.c_str());
+ parent->addChild(clone, node);
+ clones[i] = clone;
+ }
+ end = clock();
+
+ std::cout << "Took " << double(end - begin) / double(CLOCKS_PER_SEC) << " seconds to write " << num_clones << " clones of a path\n";
+
+ begin = clock();
+ // Remove those clones
+ for (size_t i = num_clones - 1; i >= 1; --i) {
+ parent->removeChild(clones[i]);
+ }
+ end = clock();
+
+ std::cout << "Took " << double(end - begin) / double(CLOCKS_PER_SEC) << " seconds to remove " << num_clones << " clones of a path\n";
+ }
+
+ void testGrouping(SPGroup *group)
+ {
+ clock_t begin, end;
+
+ assert(group != NULL);
+
+ // Since we don't yet have any clean way to do this (FIXME), we'll abuse the XML tree a bit.
+ Inkscape::XML::Node *node = group->getRepr();
+ assert(node != NULL);
+
+ Inkscape::XML::Document *xml_doc = node->document();
+
+ TS_TRACE("Benchmarking groups...");
+ const size_t num_elements = 10000;
+
+ Inkscape::XML::Node *new_group = xml_doc->createElement("svg:g");
+ Inkscape::GC::release(new_group);
+ node->addChild(new_group, NULL);
+
+ std::vector<Inkscape::XML::Node *> elements(num_elements, NULL);
+
+ begin = clock();
+ for (size_t i = 0; i < num_elements; ++i) {
+ Inkscape::XML::Node *circle = xml_doc->createElement("svg:circle");
+ Inkscape::GC::release(circle);
+ circle->setAttribute("cx", "2048");
+ circle->setAttribute("cy", "1024");
+ circle->setAttribute("r", "1.5");
+ new_group->addChild(circle, NULL);
+ elements[i] = circle;
+ }
+ end = clock();
+
+ std::cout << "Took " << double(end - begin) / double(CLOCKS_PER_SEC) << " seconds to write " << num_elements << " elements into a group\n";
+
+ SPGroup *n_group = dynamic_cast<SPGroup *>(group->get_child_by_repr(new_group));
+ assert(n_group != NULL);
+
+ begin = clock();
+ sp_item_group_ungroup(n_group, NULL, false);
+ end = clock();
+
+ std::cout << "Took " << double(end - begin) / double(CLOCKS_PER_SEC) << " seconds to ungroup a <g> with " << num_elements << " elements\n";
+
+ begin = clock();
+ // Remove those elements
+ for (size_t i = num_elements - 1; i >= 1; --i) {
+ elements[i]->parent()->removeChild(elements[i]);
+ }
+ end = clock();
+
+ std::cout << "Took " << double(end - begin) / double(CLOCKS_PER_SEC) << " seconds to remove " << num_elements << " elements\n";
+ }
+};
+#endif // SEEN_OBJECT_TEST_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/path-chemistry.cpp b/src/path-chemistry.cpp
index d355b49fe..0c3f9cde7 100644
--- a/src/path-chemistry.cpp
+++ b/src/path-chemistry.cpp
@@ -22,6 +22,7 @@
#include "xml/repr.h"
#include "svg/svg.h"
#include "display/curve.h"
+#include "color.h"
#include <glib.h>
#include <glibmm/i18n.h>
#include "sp-path.h"
@@ -65,8 +66,9 @@ sp_selected_path_combine(SPDesktop *desktop)
GSList *to_paths = NULL;
for (GSList *i = items; i != NULL; i = i->next) {
SPItem *item = (SPItem *) i->data;
- if (!SP_IS_PATH(item) && !SP_IS_GROUP(item))
+ if (!dynamic_cast<SPPath *>(item) && !dynamic_cast<SPGroup *>(item)) {
to_paths = g_slist_prepend(to_paths, item);
+ }
}
GSList *converted = NULL;
bool did = sp_item_list_to_curves(to_paths, &items, &converted);
@@ -78,6 +80,7 @@ sp_selected_path_combine(SPDesktop *desktop)
items = g_slist_sort(items, (GCompareFunc) sp_item_repr_compare_position);
items = g_slist_reverse(items);
+ assert(items); // cannot be NULL because of list length check at top of function
// remember the position, id, transform and style of the topmost path, they will be assigned to the combined one
gint position = 0;
@@ -97,7 +100,8 @@ sp_selected_path_combine(SPDesktop *desktop)
for (GSList *i = items; i != NULL; i = i->next) { // going from top to bottom
SPItem *item = (SPItem *) i->data;
- if (!SP_IS_PATH(item)) {
+ SPPath *path = dynamic_cast<SPPath *>(item);
+ if (!path) {
continue;
}
@@ -106,7 +110,7 @@ sp_selected_path_combine(SPDesktop *desktop)
did = true;
}
- SPCurve *c = SP_PATH(item)->get_curve_for_edit();
+ SPCurve *c = path->get_curve_for_edit();
if (first == NULL) { // this is the topmost path
first = item;
parent = first->getRepr()->parent();
@@ -202,12 +206,11 @@ sp_selected_path_break_apart(SPDesktop *desktop)
SPItem *item = (SPItem *) items->data;
- if (!SP_IS_PATH(item)) {
+ SPPath *path = dynamic_cast<SPPath *>(item);
+ if (!path) {
continue;
}
- SPPath *path = SP_PATH(item);
-
SPCurve *curve = path->get_curve_for_edit();
if (curve == NULL) {
continue;
@@ -364,17 +367,20 @@ sp_item_list_to_curves(const GSList *items, GSList **selected, GSList **to_selec
items != NULL;
items = items->next) {
- SPItem *item = SP_ITEM(items->data);
+ SPItem *item = dynamic_cast<SPItem *>(static_cast<SPObject *>(items->data));
+ g_assert(item != NULL);
SPDocument *document = item->document;
+ SPGroup *group = dynamic_cast<SPGroup *>(item);
if ( skip_all_lpeitems &&
- SP_IS_LPE_ITEM(item) &&
- !SP_IS_GROUP(item) ) // also convert objects in an SPGroup when skip_all_lpeitems is set.
+ dynamic_cast<SPLPEItem *>(item) &&
+ !group ) // also convert objects in an SPGroup when skip_all_lpeitems is set.
{
continue;
}
- if (SP_IS_PATH(item) && !SP_SHAPE(item)->_curve_before_lpe) {
+ SPPath *path = dynamic_cast<SPPath *>(item);
+ if (path && !path->_curve_before_lpe) {
// remove connector attributes
if (item->getAttribute("inkscape:connector-type") != NULL) {
item->removeAttribute("inkscape:connection-start");
@@ -386,9 +392,10 @@ sp_item_list_to_curves(const GSList *items, GSList **selected, GSList **to_selec
continue; // already a path, and no path effect
}
- if (SP_IS_BOX3D(item)) {
+ SPBox3D *box = dynamic_cast<SPBox3D *>(item);
+ if (box) {
// convert 3D box to ordinary group of paths; replace the old element in 'selected' with the new group
- Inkscape::XML::Node *repr = box3d_convert_to_group(SP_BOX3D(item))->getRepr();
+ Inkscape::XML::Node *repr = box3d_convert_to_group(box)->getRepr();
if (repr) {
*to_select = g_slist_prepend (*to_select, repr);
@@ -399,9 +406,9 @@ sp_item_list_to_curves(const GSList *items, GSList **selected, GSList **to_selec
continue;
}
- if (SP_IS_GROUP(item)) {
- SP_LPE_ITEM(item)->removeAllPathEffects(true);
- GSList *item_list = sp_item_group_item_list(SP_GROUP(item));
+ if (group) {
+ group->removeAllPathEffects(true);
+ GSList *item_list = sp_item_group_item_list(group);
GSList *item_to_select = NULL;
GSList *item_selected = NULL;
@@ -433,6 +440,10 @@ sp_item_list_to_curves(const GSList *items, GSList **selected, GSList **to_selec
gchar *title = item->title();
// remember description
gchar *desc = item->desc();
+ // remember highlight color
+ guint32 highlight_color = 0;
+ if (item->isHighlightSet())
+ highlight_color = item->highlight_color();
// It's going to resurrect, so we delete without notifying listeners.
item->deleteObject(false);
@@ -450,6 +461,9 @@ sp_item_list_to_curves(const GSList *items, GSList **selected, GSList **to_selec
newObj->setDesc(desc);
g_free(desc);
}
+ if (highlight_color && newObj) {
+ SP_ITEM(newObj)->setHighlightColor( highlight_color );
+ }
// move to the saved position
repr->setPosition(pos > 0 ? pos : 0);
@@ -471,7 +485,7 @@ sp_selected_item_to_curved_repr(SPItem *item, guint32 /*text_grouping_policy*/)
Inkscape::XML::Document *xml_doc = item->getRepr()->document();
- if (SP_IS_TEXT(item) || SP_IS_FLOWTEXT(item)) {
+ if (dynamic_cast<SPText *>(item) || dynamic_cast<SPFlowtext *>(item)) {
// Special treatment for text: convert each glyph to separate path, then group the paths
Inkscape::XML::Node *g_repr = xml_doc->createElement("svg:g");
g_repr->setAttribute("transform", item->getRepr()->attribute("transform"));
@@ -488,7 +502,7 @@ sp_selected_item_to_curved_repr(SPItem *item, guint32 /*text_grouping_policy*/)
g_repr->setAttribute("inkscape:transform-center-y", item->getRepr()->attribute("inkscape:transform-center-y"), false);
/* Whole text's style */
gchar *style_str = sp_style_write_difference(item->style,
- item->parent->style);
+ item->parent ? item->parent->style : NULL); // TODO investigate posibility
g_repr->setAttribute("style", style_str);
g_free(style_str);
Inkscape::Text::Layout::iterator iter = te_get_layout(item)->begin();
@@ -505,11 +519,11 @@ sp_selected_item_to_curved_repr(SPItem *item, guint32 /*text_grouping_policy*/)
if (!rawptr || !SP_IS_OBJECT(rawptr)) // no source for glyph, abort
break;
pos_obj = SP_OBJECT(rawptr);
- while (SP_IS_STRING(pos_obj) && pos_obj->parent) {
+ while (dynamic_cast<SPString const *>(pos_obj) && pos_obj->parent) {
pos_obj = pos_obj->parent; // SPStrings don't have style
}
gchar *style_str = sp_style_write_difference(pos_obj->style,
- pos_obj->parent->style);
+ pos_obj->parent ? pos_obj->parent->style : NULL); // TODO investigate posibility
// get path from iter to iter_next:
SPCurve *curve = te_get_layout(item)->convertToCurves(iter, iter_next);
@@ -546,8 +560,11 @@ sp_selected_item_to_curved_repr(SPItem *item, guint32 /*text_grouping_policy*/)
}
SPCurve *curve = NULL;
- if (SP_IS_SHAPE(item)) {
- curve = SP_SHAPE(item)->getCurve();
+ {
+ SPShape *shape = dynamic_cast<SPShape *>(item);
+ if (shape) {
+ curve = shape->getCurve();
+ }
}
if (!curve)
@@ -566,7 +583,7 @@ sp_selected_item_to_curved_repr(SPItem *item, guint32 /*text_grouping_policy*/)
repr->setAttribute("transform", item->getRepr()->attribute("transform"));
/* Style */
gchar *style_str = sp_style_write_difference(item->style,
- item->parent->style);
+ item->parent ? item->parent->style : NULL); // TODO investigate posibility
repr->setAttribute("style", style_str);
g_free(style_str);
@@ -613,12 +630,12 @@ sp_selected_path_reverse(SPDesktop *desktop)
for (GSList *i = items; i != NULL; i = i->next) {
- if (!SP_IS_PATH(i->data)) {
+ SPPath *path = dynamic_cast<SPPath *>(static_cast<SPObject *>(i->data));
+ if (!path) {
continue;
}
did = true;
- SPPath *path = SP_PATH(i->data);
SPCurve *rcurve = path->get_curve_reference()->create_reverse();
diff --git a/src/path-chemistry.h b/src/path-chemistry.h
index efc687b44..a2150440c 100644
--- a/src/path-chemistry.h
+++ b/src/path-chemistry.h
@@ -13,8 +13,6 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include <glib.h>
-
class SPDesktop;
class SPItem;
@@ -25,6 +23,9 @@ class Node;
} // namespace XML
} // namespace Inkscape
+typedef unsigned int guint32;
+typedef struct _GSList GSList;
+
void sp_selected_path_combine (SPDesktop *desktop);
void sp_selected_path_break_apart (SPDesktop *desktop);
// interactive=true only has an effect if desktop != NULL, i.e. if a GUI is available
diff --git a/src/path-prefix.h b/src/path-prefix.h
index be57ae354..7042d5124 100644
--- a/src/path-prefix.h
+++ b/src/path-prefix.h
@@ -10,15 +10,15 @@
* define'd directories, and instead should use only the paths defined here.
*
*/
-#ifndef _PATH_PREFIX_H_
-#define _PATH_PREFIX_H_
+#ifndef SEEN_PATH_PREFIX_H
+#define SEEN_PATH_PREFIX_H
#include "require-config.h" // INKSCAPE_DATADIR
#include "prefix.h"
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
+//#ifdef __cplusplus
+//extern "C" {
+//#endif /* __cplusplus */
#ifdef ENABLE_BINRELOC
# define INKSCAPE_APPICONDIR BR_DATADIR( "/pixmaps" )
@@ -66,23 +66,23 @@ extern "C" {
# define CREATE_PALETTESDIR WIN32_DATADIR("create\\swatches")
# define CREATE_PATTERNSDIR WIN32_DATADIR("create\\patterns\\vector")
# elif defined ENABLE_OSX_APP_LOCATIONS
-# define INKSCAPE_APPICONDIR "Contents/Resources/pixmaps"
-# define INKSCAPE_ATTRRELDIR "Contents/Resources/attributes"
-# define INKSCAPE_BINDDIR "Contents/Resources/bind"
-# define INKSCAPE_EXAMPLESDIR "Contents/Resources/examples"
-# define INKSCAPE_EXTENSIONDIR "Contents/Resources/extensions"
-# define INKSCAPE_FILTERDIR "Contents/Resources/filters"
-# define INKSCAPE_GRADIENTSDIR "Contents/Resources/gradients"
-# define INKSCAPE_KEYSDIR "Contents/Resources/keys"
-# define INKSCAPE_PIXMAPDIR "Contents/Resources/icons"
-# define INKSCAPE_MARKERSDIR "Contents/Resources/markers"
-# define INKSCAPE_PALETTESDIR "Contents/Resources/palettes"
-# define INKSCAPE_PATTERNSDIR "Contents/Resources/patterns"
-# define INKSCAPE_SCREENSDIR "Contents/Resources/screens"
-# define INKSCAPE_SYMBOLSDIR "Contents/Resources/symbols"
-# define INKSCAPE_TUTORIALSDIR "Contents/Resources/tutorials"
-# define INKSCAPE_TEMPLATESDIR "Contents/Resources/templates"
-# define INKSCAPE_UIDIR "Contents/Resources/ui"
+# define INKSCAPE_APPICONDIR "Contents/Resources/share/pixmaps"
+# define INKSCAPE_ATTRRELDIR "Contents/Resources/share/inkscape/attributes"
+# define INKSCAPE_BINDDIR "Contents/Resources/share/inkscape/bind"
+# define INKSCAPE_EXAMPLESDIR "Contents/Resources/share/inkscape/examples"
+# define INKSCAPE_EXTENSIONDIR "Contents/Resources/share/inkscape/extensions"
+# define INKSCAPE_FILTERDIR "Contents/Resources/share/inkscape/filters"
+# define INKSCAPE_GRADIENTSDIR "Contents/Resources/share/inkscape/gradients"
+# define INKSCAPE_KEYSDIR "Contents/Resources/share/inkscape/keys"
+# define INKSCAPE_PIXMAPDIR "Contents/Resources/share/inkscape/icons"
+# define INKSCAPE_MARKERSDIR "Contents/Resources/share/inkscape/markers"
+# define INKSCAPE_PALETTESDIR "Contents/Resources/share/inkscape/palettes"
+# define INKSCAPE_PATTERNSDIR "Contents/Resources/share/inkscape/patterns"
+# define INKSCAPE_SCREENSDIR "Contents/Resources/share/inkscape/screens"
+# define INKSCAPE_SYMBOLSDIR "Contents/Resources/share/inkscape/symbols"
+# define INKSCAPE_TUTORIALSDIR "Contents/Resources/share/inkscape/tutorials"
+# define INKSCAPE_TEMPLATESDIR "Contents/Resources/share/inkscape/templates"
+# define INKSCAPE_UIDIR "Contents/Resources/share/inkscape/ui"
//CREATE V0.1 support
# define CREATE_GRADIENTSDIR "/Library/Application Support/create/gradients/gimp"
# define CREATE_PALETTESDIR "/Library/Application Support/create/swatches"
@@ -112,8 +112,8 @@ extern "C" {
# endif
#endif
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
+//#ifdef __cplusplus
+//}
+//#endif /* __cplusplus */
#endif /* _PATH_PREFIX_H_ */
diff --git a/src/persp3d-reference.h b/src/persp3d-reference.h
index fa9eca5c9..cce497d94 100644
--- a/src/persp3d-reference.h
+++ b/src/persp3d-reference.h
@@ -10,9 +10,10 @@
* Released under GNU GPL, read the file 'COPYING' for more information.
*/
-#include "uri-references.h"
-#include <stddef.h>
+#include <cstddef>
#include <sigc++/sigc++.h>
+
+#include "uri-references.h"
#include "persp3d.h"
class SPObject;
@@ -35,7 +36,7 @@ public:
SPObject *owner;
// concerning the Persp3D (we only use SPBox3D) that is refered to:
- gchar *persp_href;
+ char *persp_href;
Inkscape::XML::Node *persp_repr;
Persp3D *persp;
diff --git a/src/persp3d.h b/src/persp3d.h
index bd3777a19..be5680bcb 100644
--- a/src/persp3d.h
+++ b/src/persp3d.h
@@ -1,5 +1,5 @@
-#ifndef __PERSP3D_H__
-#define __PERSP3D_H__
+#ifndef SEEN_PERSP3D_H
+#define SEEN_PERSP3D_H
/*
* Implementation of 3D perspectives as SPObjects
@@ -16,8 +16,9 @@
#define SP_IS_PERSP3D(obj) (dynamic_cast<const Persp3D*>((SPObject*)obj) != NULL)
#include <list>
-#include <vector>
#include <map>
+#include <vector>
+
#include "transf_mat_3x4.h"
#include "document.h"
#include "inkscape.h" // for SP_ACTIVE_DOCUMENT
@@ -64,11 +65,11 @@ protected:
virtual void build(SPDocument* doc, Inkscape::XML::Node* repr);
virtual void release();
- virtual void set(unsigned int key, const gchar* value);
+ virtual void set(unsigned int key, char const* value);
virtual void update(SPCtx* ctx, unsigned int flags);
- virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, guint flags);
+ virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, unsigned int flags);
};
@@ -100,7 +101,7 @@ void persp3d_update_z_orders (Persp3D *persp);
inline unsigned int persp3d_num_boxes (Persp3D *persp) { return persp->perspective_impl->boxes.size(); }
std::list<SPBox3D *> persp3d_list_of_boxes(Persp3D *persp);
-bool persp3d_perspectives_coincide(const Persp3D *lhs, const Persp3D *rhs);
+bool persp3d_perspectives_coincide(Persp3D const *lhs, Persp3D const *rhs);
void persp3d_absorb(Persp3D *persp1, Persp3D *persp2);
Persp3D * persp3d_create_xml_element (SPDocument *document, Persp3DImpl *dup = NULL);
@@ -112,7 +113,7 @@ void persp3d_print_debugging_info (Persp3D *persp);
void persp3d_print_debugging_info_all(SPDocument *doc);
void persp3d_print_all_selected();
-void print_current_persp3d(gchar *func_name, Persp3D *persp);
+void print_current_persp3d(char *func_name, Persp3D *persp);
#endif /* __PERSP3D_H__ */
diff --git a/src/perspective-line.cpp b/src/perspective-line.cpp
index 4fd68f8ed..e6c78403b 100644
--- a/src/perspective-line.cpp
+++ b/src/perspective-line.cpp
@@ -1,6 +1,4 @@
-#define __PERSPECTIVE_LINE_C__
-
-/*
+/**
* Perspective line for 3D perspectives
*
* Authors:
@@ -40,4 +38,4 @@ PerspectiveLine::PerspectiveLine (Geom::Point const &pt, Proj::Axis const axis,
fill-column:99
End:
*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8 :
diff --git a/src/perspective-line.h b/src/perspective-line.h
index 57abaae9c..64f7d03bd 100644
--- a/src/perspective-line.h
+++ b/src/perspective-line.h
@@ -13,7 +13,6 @@
#define SEEN_PERSPECTIVE_LINE_H
#include "line-geometry.h"
-#include <glib.h>
class SPDesktop;
diff --git a/src/preferences-skeleton.h b/src/preferences-skeleton.h
index 2211baddb..66a3e47d4 100644
--- a/src/preferences-skeleton.h
+++ b/src/preferences-skeleton.h
@@ -1,8 +1,9 @@
#ifndef SEEN_PREFERENCES_SKELETON_H
#define SEEN_PREFERENCES_SKELETON_H
-#include <inkscape-version.h>
+#include "inkscape-version.h"
+// FIXME why is this here?
#ifdef N_
#undef N_
#endif
@@ -293,6 +294,9 @@ static char const preferences_skeleton[] =
#ifdef WIN32 // FIXME: Temporary Win32 special code to enable transient dialogs
" <group id=\"dialogsontopwin32\" value=\"0\"/>\n"
#endif
+#if !defined(GDK_WINDOWING_QUARTZ) // No maximise for Quartz, see lp:1302627
+ " <group id=\"defaultwindowsize\" value=\"2\" />\n"
+#endif
" <group id=\"arenatilescachesize\" value=\"8192\"/>\n"
" <group id=\"preservetransform\" value=\"0\"/>\n"
" <group id=\"clonecompensation\" value=\"1\"/>\n"
diff --git a/src/preferences.cpp b/src/preferences.cpp
index 2fec3b307..d0c3783b5 100644
--- a/src/preferences.cpp
+++ b/src/preferences.cpp
@@ -581,6 +581,8 @@ XML::Node *Preferences::_findObserverNode(Glib::ustring const &pref_path, Glib::
// find the node corresponding to the "directory".
Inkscape::XML::Node *node = _getNode(node_key, create), *child;
+ if (!node) return node;
+
for (child = node->firstChild(); child; child = child->next()) {
// If there is a node with id corresponding to the attr key,
// this means that the last part of the path is actually a key (folder).
@@ -601,7 +603,7 @@ void Preferences::addObserver(Observer &o)
if ( _observer_map.find(&o) == _observer_map.end() ) {
Glib::ustring node_key, attr_key;
Inkscape::XML::Node *node;
- node = _findObserverNode(o.observed_path, node_key, attr_key, false);
+ node = _findObserverNode(o.observed_path, node_key, attr_key, true);
if (node) {
// set additional data
if (o._data) {
diff --git a/src/preferences.h b/src/preferences.h
index d5429815e..d5ae40e56 100644
--- a/src/preferences.h
+++ b/src/preferences.h
@@ -13,14 +13,16 @@
#ifndef INKSCAPE_PREFSTORE_H
#define INKSCAPE_PREFSTORE_H
-#include <map>
-#include <vector>
#include <climits>
#include <cfloat>
#include <glibmm/ustring.h>
+#include <map>
+#include <vector>
+
#include "xml/repr.h"
class SPCSSAttr;
+typedef unsigned int guint32;
namespace Inkscape {
diff --git a/src/prefix.cpp b/src/prefix.cpp
index 99e20171f..6bf5cb2cf 100644
--- a/src/prefix.cpp
+++ b/src/prefix.cpp
@@ -44,9 +44,6 @@ extern "C" {
#endif /* __cplusplus */
-#undef NULL
-#define NULL ((void *) 0)
-
#ifdef __GNUC__
#define br_return_val_if_fail(expr,val) if (!(expr)) {fprintf (stderr, "** BinReloc (%s): assertion %s failed\n", __PRETTY_FUNCTION__, #expr); return val;}
#else
@@ -189,7 +186,7 @@ br_locate_prefix (void *symbol)
* br_prepend_prefix (&argc, "/share/foo/data.png"); --> Returns "/usr/share/foo/data.png"
*/
char *
-br_prepend_prefix (void *symbol, char *path)
+br_prepend_prefix (void *symbol, char const *path)
{
char *tmp, *newpath;
diff --git a/src/prefix.h b/src/prefix.h
index af96fa746..7c5a1fd3c 100644
--- a/src/prefix.h
+++ b/src/prefix.h
@@ -80,7 +80,7 @@ extern "C" {
const char *br_thread_local_store (char *str);
char *br_locate (void *symbol);
char *br_locate_prefix (void *symbol);
-char *br_prepend_prefix (void *symbol, char *path);
+char *br_prepend_prefix (void *symbol, char const *path);
#endif /* ENABLE_BINRELOC */
diff --git a/src/print.h b/src/print.h
index 80d0446fd..ab2bcc0a7 100644
--- a/src/print.h
+++ b/src/print.h
@@ -18,7 +18,7 @@ class Window;
}
class SPDocument;
-struct SPStyle;
+class SPStyle;
namespace Inkscape {
namespace Extension {
@@ -41,18 +41,18 @@ unsigned int sp_print_stroke(SPPrintContext *ctx, Geom::PathVector const &pathv,
Geom::OptRect const &pbox, Geom::OptRect const &dbox, Geom::OptRect const &bbox);
unsigned int sp_print_image_R8G8B8A8_N(SPPrintContext *ctx,
- guchar *px, unsigned int w, unsigned int h, unsigned int rs,
+ unsigned char *px, unsigned int w, unsigned int h, unsigned int rs,
Geom::Affine const &transform, SPStyle const *style);
unsigned int sp_print_text(SPPrintContext *ctx, char const *text, Geom::Point p,
SPStyle const *style);
-void sp_print_get_param(SPPrintContext *ctx, gchar *name, bool *value);
+void sp_print_get_param(SPPrintContext *ctx, char *name, bool *value);
/* UI */
void sp_print_document(Gtk::Window& parentWindow, SPDocument *doc);
-void sp_print_document_to_file(SPDocument *doc, gchar const *filename);
+void sp_print_document_to_file(SPDocument *doc, char const *filename);
#endif /* !PRINT_H_INKSCAPE */
diff --git a/src/profile-manager.h b/src/profile-manager.h
index be9446c17..54cd4a1da 100644
--- a/src/profile-manager.h
+++ b/src/profile-manager.h
@@ -9,9 +9,10 @@
#ifndef SEEN_INKSCAPE_PROFILE_MANAGER_H
#define SEEN_INKSCAPE_PROFILE_MANAGER_H
+#include <vector>
+
#include "document-subset.h"
#include "gc-finalized.h"
-#include <vector>
class SPDocument;
@@ -26,7 +27,7 @@ public:
ProfileManager(SPDocument *document);
~ProfileManager();
- ColorProfile* find(gchar const* name);
+ ColorProfile* find(char const* name);
private:
ProfileManager(ProfileManager const &); // no copy
diff --git a/src/proj_pt.cpp b/src/proj_pt.cpp
index 28286948d..311b9a034 100644
--- a/src/proj_pt.cpp
+++ b/src/proj_pt.cpp
@@ -1,6 +1,4 @@
-#define __PROJ_PT_C__
-
-/*
+/**
* 3x4 transformation matrix to map points from projective 3-space into the projective plane
*
* Authors:
@@ -11,12 +9,14 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
+#include <glib.h>
+
#include "proj_pt.h"
#include "svg/stringstream.h"
namespace Proj {
-Pt2::Pt2(const gchar *coord_str) {
+Pt2::Pt2(const char *coord_str) {
if (!coord_str) {
pt[0] = 0.0;
pt[1] = 0.0;
@@ -24,7 +24,7 @@ Pt2::Pt2(const gchar *coord_str) {
g_warning ("Coordinate string is empty. Creating default Pt2\n");
return;
}
- gchar **coords = g_strsplit(coord_str, ":", 0);
+ char **coords = g_strsplit(coord_str, ":", 0);
if (coords[0] == NULL || coords[1] == NULL || coords[2] == NULL) {
g_strfreev (coords);
g_warning ("Malformed coordinate string.\n");
@@ -54,7 +54,7 @@ Pt2::affine() {
return Geom::Point (pt[0]/pt[2], pt[1]/pt[2]);
}
-gchar *
+char *
Pt2::coord_string() {
Inkscape::SVGOStringStream os;
os << pt[0] << " : "
@@ -63,7 +63,7 @@ Pt2::coord_string() {
return g_strdup(os.str().c_str());
}
-Pt3::Pt3(const gchar *coord_str) {
+Pt3::Pt3(const char *coord_str) {
if (!coord_str) {
pt[0] = 0.0;
pt[1] = 0.0;
@@ -72,7 +72,7 @@ Pt3::Pt3(const gchar *coord_str) {
g_warning ("Coordinate string is empty. Creating default Pt2\n");
return;
}
- gchar **coords = g_strsplit(coord_str, ":", 0);
+ char **coords = g_strsplit(coord_str, ":", 0);
if (coords[0] == NULL || coords[1] == NULL ||
coords[2] == NULL || coords[3] == NULL) {
g_strfreev (coords);
@@ -96,7 +96,7 @@ Pt3::normalize() {
pt[3] = 1.0;
}
-gchar *
+char *
Pt3::coord_string() {
Inkscape::SVGOStringStream os;
os << pt[0] << " : "
@@ -117,4 +117,4 @@ Pt3::coord_string() {
fill-column:99
End:
*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8 :
diff --git a/src/proj_pt.h b/src/proj_pt.h
index 90b9df201..1ee4b7f14 100644
--- a/src/proj_pt.h
+++ b/src/proj_pt.h
@@ -1,7 +1,4 @@
-#ifndef __PROJ_PT_H__
-#define __PROJ_PT_H__
-
-/*
+/**
* 3x4 transformation matrix to map points from projective 3-space into the projective plane
*
* Authors:
@@ -12,8 +9,11 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
+#ifndef SEEN_PROJ_PT_H
+#define SEEN_PROJ_PT_H
+
#include <2geom/point.h>
-#include <gtk/gtk.h>
+#include <cstdio>
namespace Proj {
@@ -25,7 +25,7 @@ public:
Pt2 () { pt[0] = 0; pt[1] = 0; pt[2] = 1.0; } // we default to (0 : 0 : 1)
Pt2 (double x, double y, double w) { pt[0] = x; pt[1] = y; pt[2] = w; }
Pt2 (Geom::Point const &point) { pt[0] = point[Geom::X]; pt[1] = point[Geom::Y]; pt[2] = 1; }
- Pt2 (const gchar *coord_str);
+ Pt2 (const char *coord_str);
inline double operator[] (unsigned int index) const {
if (index > 2) { return Geom::infinity(); }
@@ -81,8 +81,8 @@ public:
void normalize();
Geom::Point affine();
inline bool is_finite() { return pt[2] != 0; } // FIXME: Should we allow for some tolerance?
- gchar *coord_string();
- inline void print(gchar const *s) const { g_print ("%s(%8.2f : %8.2f : %8.2f)\n", s, pt[0], pt[1], pt[2]); }
+ char *coord_string();
+ inline void print(char const *s) const { printf ("%s(%8.2f : %8.2f : %8.2f)\n", s, pt[0], pt[1], pt[2]); }
private:
double pt[3];
@@ -93,7 +93,7 @@ class Pt3 {
public:
Pt3 () { pt[0] = 0; pt[1] = 0; pt[2] = 0; pt[3] = 1.0; } // we default to (0 : 0 : 0 : 1)
Pt3 (double x, double y, double z, double w) { pt[0] = x; pt[1] = y; pt[2] = z; pt[3] = w; }
- Pt3 (const gchar *coord_str);
+ Pt3 (const char *coord_str);
inline bool operator== (Pt3 &rhs) {
normalize();
@@ -146,9 +146,9 @@ public:
}
void normalize();
inline bool is_finite() { return pt[3] != 0; } // FIXME: Should we allow for some tolerance?
- gchar *coord_string();
- inline void print(gchar const *s) const {
- g_print ("%s(%8.2f : %8.2f : %8.2f : %8.2f)\n", s, pt[0], pt[1], pt[2], pt[3]);
+ char *coord_string();
+ inline void print(char const *s) const {
+ printf ("%s(%8.2f : %8.2f : %8.2f : %8.2f)\n", s, pt[0], pt[1], pt[2], pt[3]);
}
private:
@@ -157,7 +157,7 @@ private:
} // namespace Proj
-#endif /* __PROJ_PT_H__ */
+#endif // !SEEN_PROJ_PT_H
/*
Local Variables:
@@ -168,4 +168,4 @@ private:
fill-column:99
End:
*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8 :
diff --git a/src/rdf.h b/src/rdf.h
index 3dde1cb48..c3ced1583 100644
--- a/src/rdf.h
+++ b/src/rdf.h
@@ -11,7 +11,6 @@
#ifndef SEEN_RDF_H
#define SEEN_RDF_H
-#include <glib.h>
#include <glibmm/i18n.h>
#include "document.h"
@@ -22,18 +21,18 @@
* \brief Holds license name/resource doubles for rdf_license_t entries
*/
struct rdf_double_t {
- gchar const *name;
- gchar const *resource;
+ char const *name;
+ char const *resource;
};
/**
* \brief Holds license name and RDF information
*/
struct rdf_license_t {
- gchar const *name; /* localized name of this license */
- gchar const *uri; /* URL for the RDF/Work/license element */
+ char const *name; /* localized name of this license */
+ char const *uri; /* URL for the RDF/Work/license element */
struct rdf_double_t *details; /* the license details */
-// gchar const *fragment; /* XML contents for the RDF/License tag */
+// char const *fragment; /* XML contents for the RDF/License tag */
};
extern rdf_license_t rdf_licenses [];
@@ -69,10 +68,10 @@ enum RDF_Editable {
*/
struct rdf_work_entity_t {
char const *name; /* unique name of this entity for internal reference */
- gchar const *title; /* localized title of this entity for data entry */
- gchar const *tag; /* namespace tag for the RDF/Work element */
+ char const *title; /* localized title of this entity for data entry */
+ char const *tag; /* namespace tag for the RDF/Work element */
RDFType datatype; /* how to extract/inject the RDF information */
- gchar const *tip; /* tool tip to explain the meaning of the entity */
+ char const *tip; /* tool tip to explain the meaning of the entity */
RDF_Format format; /* in what format is this data edited? */
RDF_Editable editable;/* in what way is the data editable? */
};
@@ -83,19 +82,19 @@ extern rdf_work_entity_t rdf_work_entities [];
* \brief Generic collection of RDF information for the RDF debug function
*/
struct rdf_t {
- gchar* work_title;
- gchar* work_date;
- gchar* work_creator;
- gchar* work_owner;
- gchar* work_publisher;
- gchar* work_type;
- gchar* work_source;
- gchar* work_subject;
- gchar* work_description;
+ char* work_title;
+ char* work_date;
+ char* work_creator;
+ char* work_owner;
+ char* work_publisher;
+ char* work_type;
+ char* work_source;
+ char* work_subject;
+ char* work_description;
struct rdf_license_t* license;
};
-struct rdf_work_entity_t * rdf_find_entity(gchar const * name);
+struct rdf_work_entity_t * rdf_find_entity(char const * name);
/**
* \brief Retrieves a known RDF/Work entity's contents from the document XML by name
@@ -114,7 +113,7 @@ const gchar * rdf_get_work_entity(SPDocument const * doc,
*/
unsigned int rdf_set_work_entity(SPDocument * doc,
struct rdf_work_entity_t * entity,
- const gchar * text);
+ const char * text);
/**
* \brief Attempts to match and retrieve a known RDF/License from the document XML
diff --git a/src/removeoverlap.h b/src/removeoverlap.h
index 1ba41572a..7109c9513 100644
--- a/src/removeoverlap.h
+++ b/src/removeoverlap.h
@@ -13,7 +13,7 @@
#ifndef SEEN_REMOVEOVERLAP_H
#define SEEN_REMOVEOVERLAP_H
-#include <glib.h>
+typedef struct _GSList GSList;
void removeoverlap(GSList const *items, double xGap, double yGap);
diff --git a/src/rubberband.h b/src/rubberband.h
index fbebe2b08..a7bc57145 100644
--- a/src/rubberband.h
+++ b/src/rubberband.h
@@ -10,17 +10,17 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include <boost/optional.hpp>
-#include <vector>
#include <2geom/point.h>
#include <2geom/rect.h>
+#include <boost/optional.hpp>
+#include <vector>
/* fixme: do multidocument safe */
-class CtrlRect;
+class CtrlRect;
+class SPCurve;
+class SPDesktop;
struct SPCanvasItem;
-class SPCurve;
-class SPDesktop;
enum {
RUBBERBAND_MODE_RECT,
diff --git a/src/satisfied-guide-cns.h b/src/satisfied-guide-cns.h
index 73e1e7e7f..25e5919d0 100644
--- a/src/satisfied-guide-cns.h
+++ b/src/satisfied-guide-cns.h
@@ -3,7 +3,7 @@
#include <2geom/forward.h>
#include <vector>
-#include <sp-item.h>
+#include "sp-item.h"
class SPDesktop;
class SPGuideConstraint;
diff --git a/src/selcue.h b/src/selcue.h
index bcac7315f..d9b16b0f5 100644
--- a/src/selcue.h
+++ b/src/selcue.h
@@ -1,5 +1,5 @@
-#ifndef __SP_SELCUE_H__
-#define __SP_SELCUE_H__
+#ifndef SEEN_SP_SELCUE_H
+#define SEEN_SP_SELCUE_H
/*
* Helper object for showing selected items
@@ -13,8 +13,8 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
+#include <cstddef>
#include <list>
-#include <stddef.h>
#include <sigc++/sigc++.h>
class SPDesktop;
@@ -52,7 +52,7 @@ private:
void _updateItemBboxes();
void _updateItemBboxes(Inkscape::Preferences *prefs);
- void _updateItemBboxes(gint mode, int prefs_bbox);
+ void _updateItemBboxes(int mode, int prefs_bbox);
void _newItemBboxes();
void _newTextBaselines();
void _boundingBoxPrefsChanged(int prefs_bbox);
diff --git a/src/selection-chemistry.cpp b/src/selection-chemistry.cpp
index 5a981c6a0..ffa149cee 100644
--- a/src/selection-chemistry.cpp
+++ b/src/selection-chemistry.cpp
@@ -37,11 +37,11 @@ SPCycleType SP_CYCLING = SP_CYCLE_FOCUS;
#include "dir-util.h"
#include "layer-model.h"
#include "selection.h"
-#include "tools-switch.h"
+#include "ui/tools-switch.h"
#include "desktop-handles.h"
#include "message-stack.h"
#include "sp-item-transform.h"
-#include "marker.h"
+#include "sp-marker.h"
#include "sp-use.h"
#include "sp-textpath.h"
#include "sp-tspan.h"
@@ -112,7 +112,7 @@ SPCycleType SP_CYCLING = SP_CYCLE_FOCUS;
#include "sp-item-group.h"
// For clippath editing
-#include "tools-switch.h"
+#include "ui/tools-switch.h"
#include "ui/tools/node-tool.h"
#include "ui/clipboard.h"
@@ -284,11 +284,12 @@ void SelectionHelper::fixSelection(SPDesktop *dt)
GSList const *selList = selection->itemList();
for( GSList const *i = selList; i; i = i->next ) {
- if( SP_IS_ITEM(i->data) &&
- !dt->isLayer(SP_ITEM(i->data)) &&
- (!SP_ITEM(i->data)->isLocked()))
+ SPItem *item = dynamic_cast<SPItem *>(static_cast<SPObject *>(i->data));
+ if( item &&
+ !dt->isLayer(item) &&
+ (!item->isLocked()))
{
- items = g_slist_prepend(items, SP_ITEM(i->data));
+ items = g_slist_prepend(items, item);
}
}
@@ -332,18 +333,27 @@ static void sp_selection_copy_impl(GSList const *items, GSList **clip, Inkscape:
sorted_items = g_slist_sort(static_cast<GSList *>(sorted_items), (GCompareFunc) sp_object_compare_position);
// Copy item reprs:
- for (GSList *i = (GSList *) sorted_items; i != NULL; i = i->next) {
- sp_selection_copy_one(SP_OBJECT(i->data)->getRepr(), SP_ITEM(i->data)->i2doc_affine(), clip, xml_doc);
+ for (GSList *i = sorted_items; i != NULL; i = i->next) {
+ SPItem *item = dynamic_cast<SPItem *>(SP_OBJECT(i->data));
+ if (item) {
+ sp_selection_copy_one(item->getRepr(), item->i2doc_affine(), clip, xml_doc);
+ } else {
+ g_assert_not_reached();
+ }
}
*clip = g_slist_reverse(*clip);
g_slist_free(static_cast<GSList *>(sorted_items));
}
+// TODO check if parent parameter should be changed to SPItem, of if the code should handle non-items.
static GSList *sp_selection_paste_impl(SPDocument *doc, SPObject *parent, GSList **clip)
{
Inkscape::XML::Document *xml_doc = doc->getReprDoc();
+ SPItem *parentItem = dynamic_cast<SPItem *>(parent);
+ g_assert(parentItem != NULL);
+
GSList *copied = NULL;
// add objects to document
for (GSList *l = *clip; l != NULL; l = l->next) {
@@ -351,7 +361,7 @@ static GSList *sp_selection_paste_impl(SPDocument *doc, SPObject *parent, GSList
Inkscape::XML::Node *copy = repr->duplicate(xml_doc);
// premultiply the item transform by the accumulated parent transform in the paste layer
- Geom::Affine local(SP_ITEM(parent)->i2doc_affine());
+ Geom::Affine local(parentItem->i2doc_affine());
if (!local.isIdentity()) {
gchar const *t_str = copy->attribute("transform");
Geom::Affine item_t(Geom::identity());
@@ -428,7 +438,7 @@ static void add_ids_recursive(std::vector<const gchar *> &ids, SPObject *obj)
if (obj) {
ids.push_back(obj->getId());
- if (SP_IS_GROUP(obj)) {
+ if (dynamic_cast<SPGroup *>(obj)) {
for (SPObject *child = obj->firstChild() ; child; child = child->getNext() ) {
add_ids_recursive(ids, child);
}
@@ -484,8 +494,9 @@ void sp_selection_duplicate(SPDesktop *desktop, bool suppressDone)
if (fork_livepatheffects) {
SPObject *new_obj = doc->getObjectByRepr(copy);
- if (new_obj && SP_IS_LPE_ITEM(new_obj)) {
- SP_LPE_ITEM(new_obj)->forkPathEffectsIfNecessary(1);
+ SPLPEItem *newLPEObj = dynamic_cast<SPLPEItem *>(new_obj);
+ if (newLPEObj) {
+ newLPEObj->forkPathEffectsIfNecessary(1);
}
}
@@ -501,8 +512,9 @@ void sp_selection_duplicate(SPDesktop *desktop, bool suppressDone)
for (unsigned int i = 0; i < old_ids.size(); i++) {
const gchar *id = old_ids[i];
SPObject *old_clone = doc->getObjectById(id);
- if (SP_IS_USE(old_clone)) {
- SPItem *orig = SP_USE(old_clone)->get_original();
+ SPUse *use = dynamic_cast<SPUse *>(old_clone);
+ if (use) {
+ SPItem *orig = use->get_original();
if (!orig) // orphaned
continue;
for (unsigned int j = 0; j < old_ids.size(); j++) {
@@ -516,13 +528,16 @@ void sp_selection_duplicate(SPDesktop *desktop, bool suppressDone)
g_free(newref);
}
}
- } else if (SP_IS_OFFSET(old_clone)) {
- for (guint j = 0; j < old_ids.size(); j++) {
- gchar *source_href = SP_OFFSET(old_clone)->sourceHref;
- if (source_href && source_href[0]=='#' && !strcmp(source_href+1, old_ids[j])) {
- gchar *newref = g_strdup_printf("#%s", new_ids[j]);
- doc->getObjectById(new_ids[i])->getRepr()->setAttribute("xlink:href", newref);
- g_free(newref);
+ } else {
+ SPOffset *offset = dynamic_cast<SPOffset *>(old_clone);
+ if (offset) {
+ for (guint j = 0; j < old_ids.size(); j++) {
+ gchar *source_href = offset->sourceHref;
+ if (source_href && source_href[0]=='#' && !strcmp(source_href+1, old_ids[j])) {
+ gchar *newref = g_strdup_printf("#%s", new_ids[j]);
+ doc->getObjectById(new_ids[i])->getRepr()->setAttribute("xlink:href", newref);
+ g_free(newref);
+ }
}
}
}
@@ -548,8 +563,9 @@ void sp_edit_clear_all(Inkscape::Selection *selection)
SPDocument *doc = selection->layers()->getDocument();
selection->clear();
- g_return_if_fail(SP_IS_GROUP(selection->layers()->currentLayer()));
- GSList *items = sp_item_group_item_list(SP_GROUP(selection->layers()->currentLayer()));
+ SPGroup *group = dynamic_cast<SPGroup *>(selection->layers()->currentLayer());
+ g_return_if_fail(group != NULL);
+ GSList *items = sp_item_group_item_list(group);
while (items) {
reinterpret_cast<SPObject*>(items->data)->deleteObject();
@@ -573,17 +589,18 @@ void sp_edit_clear_all(Inkscape::Selection *selection)
GSList *get_all_items(GSList *list, SPObject *from, SPDesktop *desktop, bool onlyvisible, bool onlysensitive, bool ingroups, GSList const *exclude)
{
for ( SPObject *child = from->firstChild() ; child; child = child->getNext() ) {
- if (SP_IS_ITEM(child) &&
- !desktop->isLayer(SP_ITEM(child)) &&
- (!onlysensitive || !SP_ITEM(child)->isLocked()) &&
- (!onlyvisible || !desktop->itemIsHidden(SP_ITEM(child))) &&
+ SPItem *item = dynamic_cast<SPItem *>(child);
+ if (item &&
+ !desktop->isLayer(item) &&
+ (!onlysensitive || !item->isLocked()) &&
+ (!onlyvisible || !desktop->itemIsHidden(item)) &&
(!exclude || !g_slist_find(const_cast<GSList *>(exclude), child))
)
{
- list = g_slist_prepend(list, SP_ITEM(child));
+ list = g_slist_prepend(list, item);
}
- if (ingroups || (SP_IS_ITEM(child) && desktop->isLayer(SP_ITEM(child)))) {
+ if (ingroups || (item && desktop->isLayer(item))) {
list = get_all_items(list, child, desktop, onlyvisible, onlysensitive, ingroups, exclude);
}
}
@@ -598,7 +615,7 @@ static void sp_edit_select_all_full(SPDesktop *dt, bool force_all_layers, bool i
Inkscape::Selection *selection = sp_desktop_selection(dt);
- g_return_if_fail(SP_IS_GROUP(dt->currentLayer()));
+ g_return_if_fail(dynamic_cast<SPGroup *>(dt->currentLayer()));
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
PrefsSelectionContext inlayer = (PrefsSelectionContext) prefs->getInt("/options/kbselection/inlayer", PREFS_SELECTION_LAYER);
@@ -617,14 +634,14 @@ static void sp_edit_select_all_full(SPDesktop *dt, bool force_all_layers, bool i
switch (inlayer) {
case PREFS_SELECTION_LAYER: {
- if ( (onlysensitive && SP_ITEM(dt->currentLayer())->isLocked()) ||
- (onlyvisible && dt->itemIsHidden(SP_ITEM(dt->currentLayer()))) )
+ if ( (onlysensitive && dynamic_cast<SPItem *>(dt->currentLayer())->isLocked()) ||
+ (onlyvisible && dt->itemIsHidden(dynamic_cast<SPItem *>(dt->currentLayer()))) )
return;
- GSList *all_items = sp_item_group_item_list(SP_GROUP(dt->currentLayer()));
+ GSList *all_items = sp_item_group_item_list(dynamic_cast<SPGroup *>(dt->currentLayer()));
for (GSList *i = all_items; i; i = i->next) {
- SPItem *item = SP_ITEM(i->data);
+ SPItem *item = dynamic_cast<SPItem *>(static_cast<SPObject *>(i->data));
if (item && (!onlysensitive || !item->isLocked())) {
if (!onlyvisible || !dt->itemIsHidden(item)) {
@@ -703,7 +720,7 @@ static void sp_selection_group_impl(GSList *p, Inkscape::XML::Node *group, Inksc
Geom::Affine item_t(Geom::identity());
if (t_str)
sp_svg_transform_read(t_str, &item_t);
- item_t *= SP_ITEM(doc->getObjectByRepr(current->parent()))->i2doc_affine();
+ item_t *= dynamic_cast<SPItem *>(doc->getObjectByRepr(current->parent()))->i2doc_affine();
// FIXME: when moving both clone and original from a transformed group (either by
// grouping into another parent, or by cut/paste) the transform from the original's
// parent becomes embedded into original itself, and this affects its clones. Fix
@@ -762,7 +779,7 @@ void sp_selection_group(Inkscape::Selection *selection, SPDesktop *desktop)
sp_selection_group_impl(p, group, xml_doc, doc);
DocumentUndo::done(doc, SP_VERB_SELECTION_GROUP,
- _("Group"));
+ C_("Verb", "Group"));
selection->set(group);
Inkscape::GC::release(group);
@@ -794,7 +811,7 @@ void sp_selection_ungroup(Inkscape::Selection *selection, SPDesktop *desktop)
GSList *groups = NULL;
for (GSList *item = old_select; item; item = item->next) {
SPItem *obj = static_cast<SPItem*>(item->data);
- if (SP_IS_GROUP(obj)) {
+ if (dynamic_cast<SPGroup *>(obj)) {
groups = g_slist_prepend(groups, obj);
}
}
@@ -815,8 +832,8 @@ void sp_selection_ungroup(Inkscape::Selection *selection, SPDesktop *desktop)
SPUse *use = dynamic_cast<SPUse *>(static_cast<SPItem *>(item->data));
SPItem *original = use;
- while (SP_IS_USE(original)) {
- original = SP_USE(original)->get_original();
+ while (dynamic_cast<SPUse *>(original)) {
+ original = dynamic_cast<SPUse *>(original)->get_original();
}
if (g_slist_find(groups, original) != NULL) {
@@ -843,7 +860,7 @@ void sp_selection_ungroup(Inkscape::Selection *selection, SPDesktop *desktop)
// ungroup only the groups marked earlier
if (g_slist_find(groups, item->data) != NULL) {
GSList *children = NULL;
- sp_item_group_ungroup(SP_GROUP(obj), &children, false);
+ sp_item_group_ungroup(dynamic_cast<SPGroup *>(obj), &children, false);
// add the items resulting from ungrouping to the selection
new_select = g_slist_concat(new_select, children);
item->data = NULL; // zero out the original pointer, which is no longer valid
@@ -868,11 +885,12 @@ sp_degroup_list(GSList *items)
GSList *out = NULL;
bool has_groups = false;
for (GSList *item = items; item; item = item->next) {
- if (!SP_IS_GROUP(item->data)) {
+ SPGroup *group = dynamic_cast<SPGroup *>(static_cast<SPObject *>(item->data));
+ if (!group) {
out = g_slist_prepend(out, item->data);
} else {
has_groups = true;
- GSList *members = sp_item_group_item_list(SP_GROUP(item->data));
+ GSList *members = sp_item_group_item_list(group);
for (GSList *member = members; member; member = member->next) {
out = g_slist_prepend(out, member->data);
}
@@ -899,7 +917,7 @@ sp_item_list_common_parent_group(GSList const *items)
}
SPObject *parent = SP_OBJECT(items->data)->parent;
// Strictly speaking this CAN happen, if user selects <svg> from Inkscape::XML editor
- if (!SP_IS_GROUP(parent)) {
+ if (!dynamic_cast<SPGroup *>(parent)) {
return NULL;
}
for (items = items->next; items; items = items->next) {
@@ -908,7 +926,7 @@ sp_item_list_common_parent_group(GSList const *items)
}
}
- return SP_GROUP(parent);
+ return dynamic_cast<SPGroup *>(parent);
}
/** Finds out the minimum common bbox of the selected items. */
@@ -928,7 +946,7 @@ enclose_items(GSList const *items)
static SPObject *prev_sibling(SPObject *child)
{
SPObject *prev = 0;
- if ( child && SP_IS_GROUP(child->parent) ) {
+ if ( child && dynamic_cast<SPGroup *>(child->parent) ) {
prev = child->getPrev();
}
return prev;
@@ -965,8 +983,9 @@ sp_selection_raise(Inkscape::Selection *selection, SPDesktop *desktop)
// for each selected object, find the next sibling
for (SPObject *newref = child->next; newref; newref = newref->next) {
// if the sibling is an item AND overlaps our selection,
- if (SP_IS_ITEM(newref)) {
- Geom::OptRect newref_bbox = SP_ITEM(newref)->desktopVisualBounds();
+ SPItem *newItem = dynamic_cast<SPItem *>(newref);
+ if (newItem) {
+ Geom::OptRect newref_bbox = newItem->desktopVisualBounds();
if ( newref_bbox && selected->intersects(*newref_bbox) ) {
// AND if it's not one of our selected objects,
if (!g_slist_find(const_cast<GSList *>(items), newref)) {
@@ -1050,8 +1069,9 @@ void sp_selection_lower(Inkscape::Selection *selection, SPDesktop *desktop)
// for each selected object, find the prev sibling
for (SPObject *newref = prev_sibling(child); newref; newref = prev_sibling(newref)) {
// if the sibling is an item AND overlaps our selection,
- if (SP_IS_ITEM(newref)) {
- Geom::OptRect ref_bbox = SP_ITEM(newref)->desktopVisualBounds();
+ SPItem *newItem = dynamic_cast<SPItem *>(newref);
+ if (newItem) {
+ Geom::OptRect ref_bbox = newItem->desktopVisualBounds();
if ( ref_bbox && selected->intersects(*ref_bbox) ) {
// AND if it's not one of our selected objects,
if (!g_slist_find(const_cast<GSList *>(items), newref)) {
@@ -1105,9 +1125,9 @@ void sp_selection_lower_to_bottom(Inkscape::Selection *selection, SPDesktop *des
Inkscape::XML::Node *repr = static_cast<Inkscape::XML::Node *>(l->data);
pp = document->getObjectByRepr(repr->parent());
minpos = 0;
- g_assert(SP_IS_GROUP(pp));
+ g_assert(dynamic_cast<SPGroup *>(pp));
pc = pp->firstChild();
- while (!SP_IS_ITEM(pc)) {
+ while (!dynamic_cast<SPItem *>(pc)) {
minpos += 1;
pc = pc->next;
}
@@ -1162,8 +1182,8 @@ take_style_from_item(SPObject *object)
if (css == NULL)
return NULL;
- if ((SP_IS_GROUP(object) && object->children) ||
- (SP_IS_TEXT(object) && object->children && object->children->next == NULL)) {
+ if ((dynamic_cast<SPGroup *>(object) && object->children) ||
+ (dynamic_cast<SPText *>(object) && object->children && object->children->next == NULL)) {
// if this is a text with exactly one tspan child, merge the style of that tspan as well
// If this is a group, merge the style of its topmost (last) child with style
for (SPObject *last_element = object->lastChild(); last_element != NULL; last_element = last_element->getPrev()) {
@@ -1178,14 +1198,19 @@ take_style_from_item(SPObject *object)
}
}
- if (!(SP_IS_TEXT(object) || SP_IS_TSPAN(object) || SP_IS_TREF(object) || SP_IS_STRING(object))) {
+ // Remove black-listed properties (those that should not be used in a default style)
+ css = sp_css_attr_unset_blacklist(css);
+
+ if (!(dynamic_cast<SPText *>(object) || dynamic_cast<SPTSpan *>(object) || dynamic_cast<SPTRef *>(object) || dynamic_cast<SPString *>(object))) {
// do not copy text properties from non-text objects, it's confusing
css = sp_css_attr_unset_text(css);
}
- if (SP_IS_ITEM(object)) {
+
+ SPItem *item = dynamic_cast<SPItem *>(object);
+ if (item) {
// FIXME: also transform gradient/pattern fills, by forking? NO, this must be nondestructive
- double ex = SP_ITEM(object)->i2doc_affine().descrim();
+ double ex = item->i2doc_affine().descrim();
if (ex != 1.0) {
css = sp_css_attr_scale(css, ex);
}
@@ -1425,22 +1450,23 @@ selection_contains_original(SPItem *item, Inkscape::Selection *selection)
{
bool contains_original = false;
- bool is_use = SP_IS_USE(item);
SPItem *item_use = item;
SPItem *item_use_first = item;
- while (is_use && item_use && !contains_original)
+ SPUse *use = dynamic_cast<SPUse *>(item_use);
+ while (use && item_use && !contains_original)
{
- item_use = SP_USE(item_use)->get_original();
+ item_use = use->get_original();
+ use = dynamic_cast<SPUse *>(item_use);
contains_original |= selection->includes(item_use);
if (item_use == item_use_first)
break;
- is_use = SP_IS_USE(item_use);
}
// If it's a tref, check whether the object containing the character
// data is part of the selection
- if (!contains_original && SP_IS_TREF(item)) {
- contains_original = selection->includes(SP_TREF(item)->getObjectReferredTo());
+ SPTRef *tref = dynamic_cast<SPTRef *>(item);
+ if (!contains_original && tref) {
+ contains_original = selection->includes(tref->getObjectReferredTo());
}
return contains_original;
@@ -1452,10 +1478,12 @@ selection_contains_both_clone_and_original(Inkscape::Selection *selection)
{
bool clone_with_original = false;
for (GSList const *l = selection->itemList(); l != NULL; l = l->next) {
- SPItem *item = SP_ITEM(l->data);
- clone_with_original |= selection_contains_original(item, selection);
- if (clone_with_original)
- break;
+ SPItem *item = dynamic_cast<SPItem *>(static_cast<SPObject *>(l->data));
+ if (item) {
+ clone_with_original |= selection_contains_original(item, selection);
+ if (clone_with_original)
+ break;
+ }
}
return clone_with_original;
}
@@ -1466,7 +1494,7 @@ value of set_i2d==false is only used by seltrans when it's dragging objects live
that case, items are already in the new position, but the repr is in the old, and this function
then simply updates the repr from item->transform.
*/
-void sp_selection_apply_affine(Inkscape::Selection *selection, Geom::Affine const &affine, bool set_i2d, bool compensate)
+void sp_selection_apply_affine(Inkscape::Selection *selection, Geom::Affine const &affine, bool set_i2d, bool compensate, bool adjust_transf_center)
{
if (selection->isEmpty())
return;
@@ -1495,9 +1523,9 @@ void sp_selection_apply_affine(Inkscape::Selection *selection, Geom::Affine cons
}
for (GSList const *l = selection->itemList(); l != NULL; l = l->next) {
- SPItem *item = SP_ITEM(l->data);
+ SPItem *item = dynamic_cast<SPItem *>(static_cast<SPObject *>(l->data));
- if( SP_IS_ROOT(item) ) {
+ if( dynamic_cast<SPRoot *>(item) ) {
// An SVG element cannot have a transform. We could change 'x' and 'y' in response
// to a translation... but leave that for another day.
selection->desktop()->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Cannot transform an embedded SVG."));
@@ -1515,24 +1543,32 @@ void sp_selection_apply_affine(Inkscape::Selection *selection, Geom::Affine cons
// we're moving both a clone and its original or any ancestor in clone chain?
bool transform_clone_with_original = selection_contains_original(item, selection);
+
// ...both a text-on-path and its path?
- bool transform_textpath_with_path = (SP_IS_TEXT_TEXTPATH(item) && selection->includes( sp_textpath_get_path_item(SP_TEXTPATH(item->firstChild())) ));
+ bool transform_textpath_with_path = ((dynamic_cast<SPText *>(item) && item->firstChild() && dynamic_cast<SPTextPath *>(item->firstChild()))
+ && selection->includes( sp_textpath_get_path_item(dynamic_cast<SPTextPath *>(item->firstChild())) ));
+
// ...both a flowtext and its frame?
- bool transform_flowtext_with_frame = (SP_IS_FLOWTEXT(item) && selection->includes( SP_FLOWTEXT(item)->get_frame(NULL))); // (only the first frame is checked so far)
+ bool transform_flowtext_with_frame = (dynamic_cast<SPFlowtext *>(item) && selection->includes( dynamic_cast<SPFlowtext *>(item)->get_frame(NULL))); // (only the first frame is checked so far)
+
// ...both an offset and its source?
- bool transform_offset_with_source = (SP_IS_OFFSET(item) && SP_OFFSET(item)->sourceHref) && selection->includes( sp_offset_get_source(SP_OFFSET(item)) );
+ bool transform_offset_with_source = (dynamic_cast<SPOffset *>(item) && dynamic_cast<SPOffset *>(item)->sourceHref) && selection->includes( sp_offset_get_source(dynamic_cast<SPOffset *>(item)) );
// If we're moving a connector, we want to detach it
// from shapes that aren't part of the selection, but
// leave it attached if they are
if (Inkscape::UI::Tools::cc_item_is_connector(item)) {
- SPItem *attItem[2];
- SP_PATH(item)->connEndPair.getAttachedItems(attItem);
-
- for (int n = 0; n < 2; ++n) {
- if (!selection->includes(attItem[n])) {
- sp_conn_end_detach(item, n);
+ SPPath *path = dynamic_cast<SPPath *>(item);
+ if (path) {
+ SPItem *attItem[2] = {0, 0};
+ path->connEndPair.getAttachedItems(attItem);
+ for (int n = 0; n < 2; ++n) {
+ if (!selection->includes(attItem[n])) {
+ sp_conn_end_detach(item, n);
+ }
}
+ } else {
+ g_assert_not_reached();
}
}
@@ -1556,10 +1592,11 @@ void sp_selection_apply_affine(Inkscape::Selection *selection, Geom::Affine cons
// apply the inverse of the region's transform to the <use> so that the flow remains
// the same (even though the output itself gets transformed)
for ( SPObject *region = item->firstChild() ; region ; region = region->getNext() ) {
- if (SP_IS_FLOWREGION(region) || SP_IS_FLOWREGIONEXCLUDE(region)) {
- for ( SPObject *use = region->firstChild() ; use ; use = use->getNext() ) {
- if ( SP_IS_USE(use) ) {
- SP_USE(use)->doWriteTransform(use->getRepr(), item->transform.inverse(), NULL, compensate);
+ if (dynamic_cast<SPFlowregion *>(region) || dynamic_cast<SPFlowregionExclude *>(region)) {
+ for ( SPObject *item = region->firstChild() ; item ; item = item->getNext() ) {
+ SPUse *use = dynamic_cast<SPUse *>(item);
+ if ( use ) {
+ use->doWriteTransform(use->getRepr(), use->transform.inverse(), NULL, compensate);
}
}
}
@@ -1573,7 +1610,15 @@ void sp_selection_apply_affine(Inkscape::Selection *selection, Geom::Affine cons
item->readAttr( "transform" );
// calculate the matrix we need to apply to the clone to cancel its induced transform from its original
- Geom::Affine parent2dt = SP_ITEM(item->parent)->i2dt_affine();
+ Geom::Affine parent2dt;
+ {
+ SPItem *parentItem = dynamic_cast<SPItem *>(item->parent);
+ if (parentItem) {
+ parent2dt = parentItem->i2dt_affine();
+ } else {
+ g_assert_not_reached();
+ }
+ }
Geom::Affine t = parent2dt * affine * parent2dt.inverse();
Geom::Affine t_inv = t.inverse();
Geom::Affine result = t_inv * item->transform * t;
@@ -1582,7 +1627,15 @@ void sp_selection_apply_affine(Inkscape::Selection *selection, Geom::Affine cons
// we need to cancel out the move compensation, too
// find out the clone move, same as in sp_use_move_compensate
- Geom::Affine parent = SP_USE(item)->get_parent_transform();
+ Geom::Affine parent;
+ {
+ SPUse *use = dynamic_cast<SPUse *>(item);
+ if (use) {
+ parent = use->get_parent_transform();
+ } else {
+ g_assert_not_reached();
+ }
+ }
Geom::Affine clone_move = parent.inverse() * t * parent;
if (prefs_parallel) {
@@ -1590,7 +1643,7 @@ void sp_selection_apply_affine(Inkscape::Selection *selection, Geom::Affine cons
item->doWriteTransform(item->getRepr(), move, &move, compensate);
} else if (prefs_unmoved) {
- //if (SP_IS_USE(sp_use_get_original(SP_USE(item))))
+ //if (dynamic_cast<SPUse *>(sp_use_get_original(dynamic_cast<SPUse *>(item))))
// clone_move = Geom::identity();
Geom::Affine move = result * clone_move;
item->doWriteTransform(item->getRepr(), move, &t, compensate);
@@ -1621,11 +1674,13 @@ void sp_selection_apply_affine(Inkscape::Selection *selection, Geom::Affine cons
item->doWriteTransform(item->getRepr(), item->transform, NULL, compensate);
}
- // if we're moving the actual object, not just updating the repr, we can transform the
- // center by the same matrix (only necessary for non-translations)
- if (set_i2d && item->isCenterSet() && !(affine.isTranslation() || affine.isIdentity())) {
- item->setCenter(old_center * affine);
- item->updateRepr();
+ if (adjust_transf_center) { // The transformation center should not be touched in case of pasting or importing, which is allowed by this if clause
+ // if we're moving the actual object, not just updating the repr, we can transform the
+ // center by the same matrix (only necessary for non-translations)
+ if (set_i2d && item->isCenterSet() && !(affine.isTranslation() || affine.isIdentity())) {
+ item->setCenter(old_center * affine);
+ item->updateRepr();
+ }
}
}
}
@@ -1741,8 +1796,12 @@ void sp_selection_rotate_90(SPDesktop *desktop, bool ccw)
GSList const *l = selection->itemList();
Geom::Rotate const rot_90(Geom::Point(0, ccw ? 1 : -1)); // pos. or neg. rotation, depending on the value of ccw
for (GSList const *l2 = l ; l2 != NULL ; l2 = l2->next) {
- SPItem *item = SP_ITEM(l2->data);
- sp_item_rotate_rel(item, rot_90);
+ SPItem *item = dynamic_cast<SPItem *>(static_cast<SPObject *>(l2->data));
+ if (item) {
+ sp_item_rotate_rel(item, rot_90);
+ } else {
+ g_assert_not_reached();
+ }
}
DocumentUndo::done(sp_desktop_document(desktop),
@@ -1800,7 +1859,7 @@ void sp_select_same_fill_stroke_style(SPDesktop *desktop, gboolean fill, gboolea
Inkscape::Selection *selection = sp_desktop_selection (desktop);
for (GSList const* sel_iter = selection->itemList(); sel_iter; sel_iter = sel_iter->next) {
- SPItem *sel = SP_ITEM(sel_iter->data);
+ SPItem *sel = dynamic_cast<SPItem *>(static_cast<SPObject *>(sel_iter->data));
GSList *matches = all_list;
if (fill) {
matches = sp_get_same_fill_or_stroke_color(sel, matches, SP_FILL_COLOR);
@@ -1853,8 +1912,12 @@ void sp_select_same_object_type(SPDesktop *desktop)
Inkscape::Selection *selection = sp_desktop_selection (desktop);
for (GSList const* sel_iter = selection->itemList(); sel_iter; sel_iter = sel_iter->next) {
- SPItem *sel = SP_ITEM(sel_iter->data);
- matches = sp_get_same_object_type(sel, matches);
+ SPItem *sel = dynamic_cast<SPItem *>(static_cast<SPObject *>(sel_iter->data));
+ if (sel) {
+ matches = sp_get_same_object_type(sel, matches);
+ } else {
+ g_assert_not_reached();
+ }
}
selection->clear();
@@ -1891,10 +1954,14 @@ void sp_select_same_stroke_style(SPDesktop *desktop)
Inkscape::Selection *selection = sp_desktop_selection (desktop);
for (GSList const* sel_iter = selection->itemList(); sel_iter; sel_iter = sel_iter->next) {
- SPItem *sel = SP_ITEM(sel_iter->data);
- matches = sp_get_same_stroke_style(sel, matches, SP_STROKE_STYLE_WIDTH);
- matches = sp_get_same_stroke_style(sel, matches, SP_STROKE_STYLE_DASHES);
- matches = sp_get_same_stroke_style(sel, matches, SP_STROKE_STYLE_MARKERS);
+ SPItem *sel = dynamic_cast<SPItem *>(static_cast<SPObject *>(sel_iter->data));
+ if (sel) {
+ matches = sp_get_same_stroke_style(sel, matches, SP_STROKE_STYLE_WIDTH);
+ matches = sp_get_same_stroke_style(sel, matches, SP_STROKE_STYLE_DASHES);
+ matches = sp_get_same_stroke_style(sel, matches, SP_STROKE_STYLE_MARKERS);
+ } else {
+ g_assert_not_reached();
+ }
}
selection->clear();
@@ -1920,45 +1987,49 @@ GSList *sp_get_same_fill_or_stroke_color(SPItem *sel, GSList *src, SPSelectStrok
SPIPaint *sel_paint = (type == SP_FILL_COLOR) ? &(sel->style->fill) : &(sel->style->stroke);
for (GSList *i = src; i != NULL; i = i->next) {
- SPItem *iter = SP_ITEM(i->data);
- SPIPaint *iter_paint = (type == SP_FILL_COLOR) ? &(iter->style->fill) : &(iter->style->stroke);
- match = false;
- if (sel_paint->isColor() && iter_paint->isColor() // color == color comparision doesnt seem to work here.
+ SPItem *iter = dynamic_cast<SPItem *>(static_cast<SPObject *>(i->data));
+ if (iter) {
+ SPIPaint *iter_paint = (type == SP_FILL_COLOR) ? &(iter->style->fill) : &(iter->style->stroke);
+ match = false;
+ if (sel_paint->isColor() && iter_paint->isColor() // color == color comparision doesnt seem to work here.
&& (sel_paint->value.color.toRGBA32(1.0) == iter_paint->value.color.toRGBA32(1.0))) {
- match = true;
- } else if (sel_paint->isPaintserver() && iter_paint->isPaintserver()) {
+ match = true;
+ } else if (sel_paint->isPaintserver() && iter_paint->isPaintserver()) {
- SPPaintServer *sel_server =
+ SPPaintServer *sel_server =
(type == SP_FILL_COLOR) ? sel->style->getFillPaintServer() : sel->style->getStrokePaintServer();
- SPPaintServer *iter_server =
+ SPPaintServer *iter_server =
(type == SP_FILL_COLOR) ? iter->style->getFillPaintServer() : iter->style->getStrokePaintServer();
- if ((SP_IS_LINEARGRADIENT(sel_server) || SP_IS_RADIALGRADIENT(sel_server) ||
- (SP_IS_GRADIENT(sel_server) && SP_GRADIENT(sel_server)->getVector()->isSwatch()))
+ if ((dynamic_cast<SPLinearGradient *>(sel_server) || dynamic_cast<SPRadialGradient *>(sel_server) ||
+ (dynamic_cast<SPGradient *>(sel_server) && dynamic_cast<SPGradient *>(sel_server)->getVector()->isSwatch()))
&&
- (SP_IS_LINEARGRADIENT(iter_server) || SP_IS_RADIALGRADIENT(iter_server) ||
- (SP_IS_GRADIENT(iter_server) && SP_GRADIENT(iter_server)->getVector()->isSwatch()))) {
- SPGradient *sel_vector = SP_GRADIENT(sel_server)->getVector();
- SPGradient *iter_vector = SP_GRADIENT(iter_server)->getVector();
- if (sel_vector == iter_vector) {
- match = true;
- }
+ (dynamic_cast<SPLinearGradient *>(iter_server) || dynamic_cast<SPRadialGradient *>(iter_server) ||
+ (dynamic_cast<SPGradient *>(iter_server) && dynamic_cast<SPGradient *>(iter_server)->getVector()->isSwatch()))) {
+ SPGradient *sel_vector = dynamic_cast<SPGradient *>(sel_server)->getVector();
+ SPGradient *iter_vector = dynamic_cast<SPGradient *>(iter_server)->getVector();
+ if (sel_vector == iter_vector) {
+ match = true;
+ }
- } else if (SP_IS_PATTERN(sel_server) && SP_IS_PATTERN(iter_server)) {
- SPPattern *sel_pat = pattern_getroot(SP_PATTERN(sel_server));
- SPPattern *iter_pat = pattern_getroot(SP_PATTERN(iter_server));
- if (sel_pat == iter_pat) {
- match = true;
+ } else if (dynamic_cast<SPPattern *>(sel_server) && dynamic_cast<SPPattern *>(iter_server)) {
+ SPPattern *sel_pat = pattern_getroot(dynamic_cast<SPPattern *>(sel_server));
+ SPPattern *iter_pat = pattern_getroot(dynamic_cast<SPPattern *>(iter_server));
+ if (sel_pat == iter_pat) {
+ match = true;
+ }
}
+ } else if (sel_paint->isNone() && iter_paint->isNone()) {
+ match = true;
+ } else if (sel_paint->isNoneSet() && iter_paint->isNoneSet()) {
+ match = true;
}
- } else if (sel_paint->isNone() && iter_paint->isNone()) {
- match = true;
- } else if (sel_paint->isNoneSet() && iter_paint->isNoneSet()) {
- match = true;
- }
- if (match) {
- matches = g_slist_prepend(matches, iter);
+ if (match) {
+ matches = g_slist_prepend(matches, iter);
+ }
+ } else {
+ g_assert_not_reached();
}
}
@@ -1967,35 +2038,35 @@ GSList *sp_get_same_fill_or_stroke_color(SPItem *sel, GSList *src, SPSelectStrok
static bool item_type_match (SPItem *i, SPItem *j)
{
- if ( SP_IS_RECT(i)) {
- return ( SP_IS_RECT(j) );
+ if ( dynamic_cast<SPRect *>(i)) {
+ return ( dynamic_cast<SPRect *>(j) );
- } else if (SP_IS_GENERICELLIPSE(i)) {
- return (SP_IS_GENERICELLIPSE(j));
+ } else if (dynamic_cast<SPGenericEllipse *>(i)) {
+ return (dynamic_cast<SPGenericEllipse *>(j));
- } else if (SP_IS_STAR(i) || SP_IS_POLYGON(i)) {
- return (SP_IS_STAR(j) || SP_IS_POLYGON(j)) ;
+ } else if (dynamic_cast<SPStar *>(i) || dynamic_cast<SPPolygon *>(i)) {
+ return (dynamic_cast<SPStar *>(j) || dynamic_cast<SPPolygon *>(j)) ;
- } else if (SP_IS_SPIRAL(i)) {
- return (SP_IS_SPIRAL(j));
+ } else if (dynamic_cast<SPSpiral *>(i)) {
+ return (dynamic_cast<SPSpiral *>(j));
- } else if (SP_IS_PATH(i) || SP_IS_LINE(i) || SP_IS_POLYLINE(i)) {
- return (SP_IS_PATH(j) || SP_IS_LINE(j) || SP_IS_POLYLINE(j));
+ } else if (dynamic_cast<SPPath *>(i) || dynamic_cast<SPLine *>(i) || dynamic_cast<SPPolyLine *>(i)) {
+ return (dynamic_cast<SPPath *>(j) || dynamic_cast<SPLine *>(j) || dynamic_cast<SPPolyLine *>(j));
- } else if (SP_IS_TEXT(i) || SP_IS_FLOWTEXT(i) || SP_IS_TSPAN(i) || SP_IS_TREF(i) || SP_IS_STRING(i)) {
- return (SP_IS_TEXT(j) || SP_IS_FLOWTEXT(j) || SP_IS_TSPAN(j) || SP_IS_TREF(j) || SP_IS_STRING(j));
+ } else if (dynamic_cast<SPText *>(i) || dynamic_cast<SPFlowtext *>(i) || dynamic_cast<SPTSpan *>(i) || dynamic_cast<SPTRef *>(i) || dynamic_cast<SPString *>(i)) {
+ return (dynamic_cast<SPText *>(j) || dynamic_cast<SPFlowtext *>(j) || dynamic_cast<SPTSpan *>(j) || dynamic_cast<SPTRef *>(j) || dynamic_cast<SPString *>(j));
- } else if (SP_IS_USE(i)) {
- return (SP_IS_USE(j)) ;
+ } else if (dynamic_cast<SPUse *>(i)) {
+ return (dynamic_cast<SPUse *>(j)) ;
- } else if (SP_IS_IMAGE(i)) {
- return (SP_IS_IMAGE(j));
+ } else if (dynamic_cast<SPImage *>(i)) {
+ return (dynamic_cast<SPImage *>(j));
- } else if (SP_IS_OFFSET(i) && SP_OFFSET(i)->sourceHref) { // Linked offset
- return (SP_IS_OFFSET(j) && SP_OFFSET(j)->sourceHref);
+ } else if (dynamic_cast<SPOffset *>(i) && dynamic_cast<SPOffset *>(i)->sourceHref) { // Linked offset
+ return (dynamic_cast<SPOffset *>(j) && dynamic_cast<SPOffset *>(j)->sourceHref);
- } else if (SP_IS_OFFSET(i) && !SP_OFFSET(i)->sourceHref) { // Dynamic offset
- return (SP_IS_OFFSET(j) && !SP_OFFSET(j)->sourceHref);
+ } else if (dynamic_cast<SPOffset *>(i) && !dynamic_cast<SPOffset *>(i)->sourceHref) { // Dynamic offset
+ return (dynamic_cast<SPOffset *>(j) && !dynamic_cast<SPOffset *>(j)->sourceHref);
}
@@ -2011,8 +2082,8 @@ GSList *sp_get_same_object_type(SPItem *sel, GSList *src)
GSList *matches = NULL;
for (GSList *i = src; i != NULL; i = i->next) {
- SPItem *item = SP_ITEM(i->data);
- if (item_type_match (sel, item)) {
+ SPItem *item = dynamic_cast<SPItem *>(static_cast<SPObject *>(i->data));
+ if (item && item_type_match(sel, item)) {
matches = g_slist_prepend (matches, item);
}
}
@@ -2048,45 +2119,49 @@ GSList *sp_get_same_stroke_style(SPItem *sel, GSList *src, SPSelectStrokeStyleTy
}
for (GSList *i = src; i != NULL; i = i->next) {
- SPItem *iter = SP_ITEM(i->data);
- SPStyle *iter_style = iter->style;
- match = false;
-
- if (type == SP_STROKE_STYLE_WIDTH) {
- match = (sel_style->stroke_width.set == iter_style->stroke_width.set);
- if (sel_style->stroke_width.set && iter_style->stroke_width.set) {
- GSList *objects = NULL;
- objects = g_slist_prepend(objects, iter);
- SPStyle *iter_style_for_width = sp_style_new (SP_ACTIVE_DOCUMENT);
- objects_query_strokewidth (objects, iter_style_for_width);
-
- if (sel_style_for_width) {
- match = (sel_style_for_width->stroke_width.computed == iter_style_for_width->stroke_width.computed);
+ SPItem *iter = dynamic_cast<SPItem *>(static_cast<SPObject *>(i->data));
+ if (iter) {
+ SPStyle *iter_style = iter->style;
+ match = false;
+
+ if (type == SP_STROKE_STYLE_WIDTH) {
+ match = (sel_style->stroke_width.set == iter_style->stroke_width.set);
+ if (sel_style->stroke_width.set && iter_style->stroke_width.set) {
+ GSList *objects = NULL;
+ objects = g_slist_prepend(objects, iter);
+ SPStyle *iter_style_for_width = sp_style_new (SP_ACTIVE_DOCUMENT);
+ objects_query_strokewidth (objects, iter_style_for_width);
+
+ if (sel_style_for_width) {
+ match = (sel_style_for_width->stroke_width.computed == iter_style_for_width->stroke_width.computed);
+ }
+ g_slist_free(objects);
}
- g_slist_free(objects);
}
- }
- else if (type == SP_STROKE_STYLE_DASHES ) {
- match = (sel_style->stroke_dasharray.set == iter_style->stroke_dasharray.set);
- if (sel_style->stroke_dasharray.set && iter_style->stroke_dasharray.set) {
- match = (sel_style->stroke_dasharray.values == iter_style->stroke_dasharray.values);
+ else if (type == SP_STROKE_STYLE_DASHES ) {
+ match = (sel_style->stroke_dasharray.set == iter_style->stroke_dasharray.set);
+ if (sel_style->stroke_dasharray.set && iter_style->stroke_dasharray.set) {
+ match = (sel_style->stroke_dasharray.values == iter_style->stroke_dasharray.values);
+ }
}
- }
- else if (type == SP_STROKE_STYLE_MARKERS) {
+ else if (type == SP_STROKE_STYLE_MARKERS) {
match = true;
int len = sizeof(sel_style->marker)/sizeof(SPIString);
for (int i = 0; i < len; i++) {
- match = (sel_style->marker[i].set == iter_style->marker[i].set);
- if (sel_style->marker[i].set && iter_style->marker[i].set &&
- (strcmp(sel_style->marker[i].value, iter_style->marker[i].value))) {
+ match = (sel_style->marker_ptrs[i]->set == iter_style->marker_ptrs[i]->set);
+ if (sel_style->marker_ptrs[i]->set && iter_style->marker_ptrs[i]->set &&
+ (strcmp(sel_style->marker_ptrs[i]->value, iter_style->marker_ptrs[i]->value))) {
match = false;
break;
}
}
- }
+ }
- if (match) {
- matches = g_slist_prepend(matches, iter);
+ if (match) {
+ matches = g_slist_prepend(matches, iter);
+ }
+ } else {
+ g_assert_not_reached();
}
}
@@ -2433,7 +2508,7 @@ SPItem *next_item_from_list(SPDesktop *desktop, GSList const *items,
{
SPObject *current=root;
while (items) {
- SPItem *item=SP_ITEM(items->data);
+ SPItem *item = dynamic_cast<SPItem *>(static_cast<SPObject *>(items->data));
if ( root->isAncestorOf(item) &&
( !only_in_viewport || desktop->isWithinViewport(item) ) )
{
@@ -2487,13 +2562,16 @@ SPItem *next_item(SPDesktop *desktop, GSList *path, SPObject *root,
if (PREFS_SELECTION_LAYER != inlayer) { // recurse into sublayers
found = next_item<D>(desktop, NULL, object, only_in_viewport, inlayer, onlyvisible, onlysensitive);
}
- } else if ( SP_IS_ITEM(object) &&
- ( !only_in_viewport || desktop->isWithinViewport(SP_ITEM(object)) ) &&
- ( !onlyvisible || !desktop->itemIsHidden(SP_ITEM(object))) &&
- ( !onlysensitive || !SP_ITEM(object)->isLocked()) &&
- !desktop->isLayer(SP_ITEM(object)) )
- {
- found = SP_ITEM(object);
+ } else {
+ SPItem *item = dynamic_cast<SPItem *>(object);
+ if ( item &&
+ ( !only_in_viewport || desktop->isWithinViewport(item) ) &&
+ ( !onlyvisible || !desktop->itemIsHidden(item)) &&
+ ( !onlysensitive || !item->isLocked()) &&
+ !desktop->isLayer(item) )
+ {
+ found = item;
+ }
}
iter = D::next(iter);
}
@@ -2611,12 +2689,11 @@ sp_selection_relink(SPDesktop *desktop)
{
SPItem *item = static_cast<SPItem *>(items->data);
- if (!SP_IS_USE(item))
- continue;
-
- item->getRepr()->setAttribute("xlink:href", newref);
- item->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
- relinked = true;
+ if (dynamic_cast<SPUse *>(item)) {
+ item->getRepr()->setAttribute("xlink:href", newref);
+ item->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+ relinked = true;
+ }
}
g_free(newref);
@@ -2652,7 +2729,7 @@ sp_selection_unlink(SPDesktop *desktop)
{
SPItem *item = static_cast<SPItem *>(items->data);
- if (SP_IS_TEXT(item)) {
+ if (dynamic_cast<SPText *>(item)) {
SPObject *tspan = sp_tref_convert_to_tspan(item);
if (tspan) {
@@ -2664,22 +2741,24 @@ sp_selection_unlink(SPDesktop *desktop)
unlinked = true;
}
- if (!(SP_IS_USE(item) || SP_IS_TREF(item))) {
+ if (!(dynamic_cast<SPUse *>(item) || dynamic_cast<SPTRef *>(item))) {
// keep the non-use item in the new selection
new_select = g_slist_prepend(new_select, item);
continue;
}
- SPItem *unlink;
- if (SP_IS_USE(item)) {
- unlink = SP_USE(item)->unlink();
+ SPItem *unlink = NULL;
+ SPUse *use = dynamic_cast<SPUse *>(item);
+ if (use) {
+ unlink = use->unlink();
// Unable to unlink use (external or invalid href?)
if (!unlink) {
new_select = g_slist_prepend(new_select, item);
continue;
}
} else /*if (SP_IS_TREF(use))*/ {
- unlink = SP_ITEM(sp_tref_convert_to_tspan(item));
+ unlink = dynamic_cast<SPItem *>(sp_tref_convert_to_tspan(item));
+ g_assert(unlink != NULL);
}
unlinked = true;
@@ -2719,24 +2798,39 @@ sp_select_clone_original(SPDesktop *desktop)
}
SPItem *original = NULL;
- if (SP_IS_USE(item)) {
- original = SP_USE(item)->get_original();
- } else if (SP_IS_OFFSET(item) && SP_OFFSET(item)->sourceHref) {
- original = sp_offset_get_source(SP_OFFSET(item));
- } else if (SP_IS_TEXT_TEXTPATH(item)) {
- original = sp_textpath_get_path_item(SP_TEXTPATH(item->firstChild()));
- } else if (SP_IS_FLOWTEXT(item)) {
- original = SP_FLOWTEXT(item)->get_frame(NULL); // first frame only
- } else if (SP_IS_LPE_ITEM(item)) {
- // check if the applied LPE is Clone original, if so, go to the refered path
- Inkscape::LivePathEffect::Effect* lpe = SP_LPE_ITEM(item)->getPathEffectOfType(Inkscape::LivePathEffect::CLONE_ORIGINAL);
- if (lpe) {
- Inkscape::LivePathEffect::Parameter *lpeparam = lpe->getParameter("linkedpath");
- if (Inkscape::LivePathEffect::OriginalPathParam *pathparam = dynamic_cast<Inkscape::LivePathEffect::OriginalPathParam *>(lpeparam)) {
- original = pathparam->getObject();
+ SPUse *use = dynamic_cast<SPUse *>(item);
+ if (use) {
+ original = use->get_original();
+ } else {
+ SPOffset *offset = dynamic_cast<SPOffset *>(item);
+ if (offset && offset->sourceHref) {
+ original = sp_offset_get_source(offset);
+ } else {
+ SPText *text = dynamic_cast<SPText *>(item);
+ SPTextPath *textpath = (text) ? dynamic_cast<SPTextPath *>(text->firstChild()) : NULL;
+ if (text && textpath) {
+ original = sp_textpath_get_path_item(textpath);
+ } else {
+ SPFlowtext *flowtext = dynamic_cast<SPFlowtext *>(item);
+ if (flowtext) {
+ original = flowtext->get_frame(NULL); // first frame only
+ } else {
+ SPLPEItem *lpeItem = dynamic_cast<SPLPEItem *>(item);
+ if (lpeItem) {
+ // check if the applied LPE is Clone original, if so, go to the refered path
+ Inkscape::LivePathEffect::Effect* lpe = lpeItem->getPathEffectOfType(Inkscape::LivePathEffect::CLONE_ORIGINAL);
+ if (lpe) {
+ Inkscape::LivePathEffect::Parameter *lpeparam = lpe->getParameter("linkedpath");
+ if (Inkscape::LivePathEffect::OriginalPathParam *pathparam = dynamic_cast<Inkscape::LivePathEffect::OriginalPathParam *>(lpeparam)) {
+ original = pathparam->getObject();
+ }
+ }
+ }
+ }
}
}
}
+
if (original == NULL) { // it's an object that we don't know what to do with
desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, error);
return;
@@ -2747,8 +2841,8 @@ sp_select_clone_original(SPDesktop *desktop)
return;
}
- for (SPObject *o = original; o && !SP_IS_ROOT(o); o = o->parent) {
- if (SP_IS_DEFS(o)) {
+ for (SPObject *o = original; o && !dynamic_cast<SPRoot *>(o); o = o->parent) {
+ if (dynamic_cast<SPDefs *>(o)) {
desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("The object you're trying to select is <b>not visible</b> (it is in &lt;defs&gt;)"));
return;
}
@@ -2790,54 +2884,52 @@ void sp_selection_clone_original_path_lpe(SPDesktop *desktop)
if (desktop == NULL) {
return;
}
-
- Inkscape::Selection *selection = sp_desktop_selection(desktop);
- SPItem *item = selection->singleItem();
- if (g_slist_length(const_cast<GSList *>(selection->itemList())) != 1 || !item) {
- desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select <b>one</b> path to clone."));
- return;
- }
- if ( !(SP_IS_SHAPE(item) || SP_IS_TEXT(item)) ) {
- desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select one <b>path</b> to clone."));
- return;
- }
-
- Inkscape::XML::Document *xml_doc = desktop->doc()->getReprDoc();
- Inkscape::XML::Node *parent = item->getRepr()->parent();
-
- // create the LPE
- Inkscape::XML::Node *lpe_repr = xml_doc->createElement("inkscape:path-effect");
- {
- lpe_repr->setAttribute("effect", "clone_original");
- gchar *href = g_strdup_printf("#%s", item->getRepr()->attribute("id"));
- lpe_repr->setAttribute("linkedpath", href);
- g_free(href);
- desktop->doc()->getDefs()->getRepr()->addChild(lpe_repr, NULL); // adds to <defs> and assigns the 'id' attribute
- }
- const gchar * lpe_id = lpe_repr->attribute("id");
- Inkscape::GC::release(lpe_repr);
-
- // create the new path
- Inkscape::XML::Node *clone = xml_doc->createElement("svg:path");
- {
- clone->setAttribute("d", "M 0 0", false);
- // add the new clone to the top of the original's parent
- parent->appendChild(clone);
- SPObject *clone_obj = desktop->doc()->getObjectById(clone->attribute("id"));
- if (SP_IS_LPE_ITEM(clone_obj)) {
- gchar *href = g_strdup_printf("#%s", lpe_id);
- SP_LPE_ITEM(clone_obj)->addPathEffect( href, false );
- g_free(href);
+
+ Inkscape::SVGOStringStream os;
+ SPObject * firstItem = NULL;
+ for (const GSList * item = desktop->selection->itemList(); item != NULL; item = item->next) {
+ if (SP_IS_SHAPE(item->data) || SP_IS_TEXT(item->data)) {
+ if (firstItem) {
+ os << "|";
+ } else {
+ firstItem = SP_ITEM(item->data);
+ }
+ os << "#" << SP_ITEM(item->data)->getId() << ",0";
}
}
+ if (firstItem) {
+ Inkscape::XML::Document *xml_doc = desktop->doc()->getReprDoc();
+ SPObject *parent = firstItem->parent;
- DocumentUndo::done(sp_desktop_document(desktop), SP_VERB_EDIT_CLONE_ORIGINAL_PATH_LPE,
- _("Clone original path"));
+ // create the LPE
+ Inkscape::XML::Node *lpe_repr = xml_doc->createElement("inkscape:path-effect");
+ {
+ lpe_repr->setAttribute("effect", "fill_between_many");
+ lpe_repr->setAttribute("linkedpaths", os.str().c_str());
+ desktop->doc()->getDefs()->getRepr()->addChild(lpe_repr, NULL); // adds to <defs> and assigns the 'id' attribute
+ }
+ const gchar * lpe_id = lpe_repr->attribute("id");
+ Inkscape::GC::release(lpe_repr);
- // select the new object:
- selection->set(clone);
+ // create the new path
+ Inkscape::XML::Node *clone = xml_doc->createElement("svg:path");
+ {
+ clone->setAttribute("d", "M 0 0", false);
+ // add the new clone to the top of the original's parent
+ parent->appendChildRepr(clone);
+ SPObject *clone_obj = desktop->doc()->getObjectById(clone->attribute("id"));
+ SPLPEItem *clone_lpeitem = dynamic_cast<SPLPEItem *>(clone_obj);
+ if (clone_lpeitem) {
+ gchar *href = g_strdup_printf("#%s", lpe_id);
+ clone_lpeitem->addPathEffect(href, false);
+ g_free(href);
+ }
+ }
- Inkscape::GC::release(clone);
+ DocumentUndo::done(sp_desktop_document(desktop), SP_VERB_EDIT_CLONE_ORIGINAL_PATH_LPE, _("Fill between many"));
+ } else {
+ desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select path(s) to fill."));
+ }
}
void sp_selection_to_marker(SPDesktop *desktop, bool apply)
@@ -2884,7 +2976,15 @@ void sp_selection_to_marker(SPDesktop *desktop, bool apply)
// bottommost object, after sorting
SPObject *parent = SP_OBJECT(items->data)->parent;
- Geom::Affine parent_transform(SP_ITEM(parent)->i2doc_affine());
+ Geom::Affine parent_transform;
+ {
+ SPItem *parentItem = dynamic_cast<SPItem *>(parent);
+ if (parent) {
+ parent_transform = parentItem->i2doc_affine();
+ } else {
+ g_assert_not_reached();
+ }
+ }
// Create a list of duplicates, to be pasted inside marker element.
GSList *repr_copies = NULL;
@@ -2925,8 +3025,9 @@ void sp_selection_to_marker(SPDesktop *desktop, bool apply)
}
static void sp_selection_to_guides_recursive(SPItem *item, bool wholegroups) {
- if (SP_IS_GROUP(item) && !SP_IS_BOX3D(item) && !wholegroups) {
- for (GSList *i = sp_item_group_item_list(SP_GROUP(item)); i != NULL; i = i->next) {
+ SPGroup *group = dynamic_cast<SPGroup *>(item);
+ if (group && !dynamic_cast<SPBox3D *>(item) && !wholegroups) {
+ for (GSList *i = sp_item_group_item_list(group); i != NULL; i = i->next) {
sp_selection_to_guides_recursive(static_cast<SPItem*>(i->data), wholegroups);
}
} else {
@@ -3018,13 +3119,13 @@ void sp_selection_symbol(SPDesktop *desktop, bool /*apply*/ )
// Find out if we have a single group
bool single_group = false;
- SPObject *the_group = NULL;
+ SPGroup *the_group = NULL;
Geom::Affine transform;
if( g_slist_length( items ) == 1 ) {
SPObject *object = reinterpret_cast<SPObject *>( items->data );
- if( SP_IS_GROUP( object ) ) {
+ the_group = dynamic_cast<SPGroup *>(object);
+ if ( the_group ) {
single_group = true;
- the_group = object;
if( !sp_svg_transform_read( object->getAttribute("transform"), &transform ))
transform = Geom::identity();
@@ -3043,7 +3144,7 @@ void sp_selection_symbol(SPDesktop *desktop, bool /*apply*/ )
prefs->setInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED);
// Remove transform on group, updating clones.
- SP_ITEM(object)->doWriteTransform(object->getRepr(), Geom::identity());
+ the_group->doWriteTransform(object->getRepr(), Geom::identity());
// restore compensation setting
prefs->setInt("/options/clonecompensation/value", saved_compensation);
@@ -3137,7 +3238,7 @@ void sp_selection_unsymbol(SPDesktop *desktop)
// Make sure we have only one object in selection.
// Require that we really have a <symbol>.
- if( symbol == NULL || !SP_IS_SYMBOL( symbol )) {
+ if( symbol == NULL || !dynamic_cast<SPSymbol *>( symbol )) {
desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select only one <b>symbol</b> in Symbol dialog to convert to group."));
return;
}
@@ -3156,7 +3257,7 @@ void sp_selection_unsymbol(SPDesktop *desktop)
// group that only adds a transform to the symbol content).
if( g_slist_length( children ) == 1 ) {
SPObject *object = reinterpret_cast<SPObject *>( children->data );
- if( SP_IS_GROUP( object ) ) {
+ if ( dynamic_cast<SPGroup *>( object ) ) {
if( object->getAttribute("style") == NULL ||
object->getAttribute("class") == NULL ) {
@@ -3235,8 +3336,17 @@ sp_selection_tile(SPDesktop *desktop, bool apply)
// bottommost object, after sorting
SPObject *parent = SP_OBJECT(items->data)->parent;
+
- Geom::Affine parent_transform(SP_ITEM(parent)->i2doc_affine());
+ Geom::Affine parent_transform;
+ {
+ SPItem *parentItem = dynamic_cast<SPItem *>(parent);
+ if (parentItem) {
+ parent_transform = parentItem->i2doc_affine();
+ } else {
+ g_assert_not_reached();
+ }
+ }
// remember the position of the first item
gint pos = SP_OBJECT(items->data)->getRepr()->position();
@@ -3341,20 +3451,22 @@ void sp_selection_untile(SPDesktop *desktop)
SPPaintServer *server = item->style->getFillPaintServer();
- if (!SP_IS_PATTERN(server))
+ SPPattern *basePat = dynamic_cast<SPPattern *>(server);
+ if (!basePat) {
continue;
+ }
did = true;
- SPPattern *pattern = pattern_getroot(SP_PATTERN(server));
+ SPPattern *pattern = pattern_getroot(basePat);
- Geom::Affine pat_transform = pattern_patternTransform(SP_PATTERN(server));
+ Geom::Affine pat_transform = pattern_patternTransform(basePat);
pat_transform *= item->transform;
for (SPObject *child = pattern->firstChild() ; child != NULL; child = child->next ) {
- if (SP_IS_ITEM(child)) {
+ if (dynamic_cast<SPItem *>(child)) {
Inkscape::XML::Node *copy = child->getRepr()->duplicate(xml_doc);
- SPItem *i = SP_ITEM(desktop->currentLayer()->appendChildRepr(copy));
+ SPItem *i = dynamic_cast<SPItem *>(desktop->currentLayer()->appendChildRepr(copy));
// FIXME: relink clones to the new canvas objects
// use SPObject::setid when mental finishes it to steal ids of
@@ -3362,10 +3474,14 @@ void sp_selection_untile(SPDesktop *desktop)
// this is needed to make sure the new item has curve (simply requestDisplayUpdate does not work)
doc->ensureUpToDate();
- Geom::Affine transform( i->transform * pat_transform );
- i->doWriteTransform(i->getRepr(), transform);
+ if (i) {
+ Geom::Affine transform( i->transform * pat_transform );
+ i->doWriteTransform(i->getRepr(), transform);
- new_select = g_slist_prepend(new_select, i);
+ new_select = g_slist_prepend(new_select, i);
+ } else {
+ g_assert_not_reached();
+ }
}
}
@@ -3548,7 +3664,7 @@ void sp_selection_create_bitmap_copy(SPDesktop *desktop)
if (hint_xdpi != 0) {
res = hint_xdpi;
} else {
- // if all else fails, take the default 90 dpi
+ // if all else fails, take the default 96 dpi
res = Inkscape::Util::Quantity::convert(1, "in", "px");
}
}
@@ -3583,12 +3699,20 @@ void sp_selection_create_bitmap_copy(SPDesktop *desktop)
}
// Calculate the matrix that will be applied to the image so that it exactly overlaps the source objects
- Geom::Affine eek(SP_ITEM(parent_object)->i2dt_affine());
+ Geom::Affine eek;
+ {
+ SPItem *parentItem = dynamic_cast<SPItem *>(parent_object);
+ if (parentItem) {
+ eek = parentItem->i2dt_affine();
+ } else {
+ g_assert_not_reached();
+ }
+ }
Geom::Affine t;
double shift_x = bbox->min()[Geom::X];
double shift_y = bbox->max()[Geom::Y];
- if (res == Inkscape::Util::Quantity::convert(1, "in", "px")) { // for default 90 dpi, snap it to pixel grid
+ if (res == Inkscape::Util::Quantity::convert(1, "in", "px")) { // for default 96 dpi, snap it to pixel grid
shift_x = round(shift_x);
shift_y = -round(-shift_y); // this gets correct rounding despite coordinate inversion, remove the negations when the inversion is gone
}
@@ -3623,7 +3747,7 @@ void sp_selection_create_bitmap_copy(SPDesktop *desktop)
// TODO: avoid unnecessary roundtrip between data URI and decoded pixbuf
Inkscape::XML::Node * repr = xml_doc->createElement("svg:image");
sp_embed_image(repr, pb);
- if (res == Inkscape::Util::Quantity::convert(1, "in", "px")) { // for default 90 dpi, snap it to pixel grid
+ if (res == Inkscape::Util::Quantity::convert(1, "in", "px")) { // for default 96 dpi, snap it to pixel grid
sp_repr_set_svg_double(repr, "width", width);
sp_repr_set_svg_double(repr, "height", height);
} else {
@@ -3661,6 +3785,118 @@ void sp_selection_create_bitmap_copy(SPDesktop *desktop)
g_free(filepath);
}
+/* Creates a mask or clipPath from selection.
+ * What is a clip group?
+ * A clip group is a tangled mess of XML that allows an object inside a group
+ * to clip the entire group using a few <use>s and generally irritating me.
+ */
+
+void sp_selection_set_clipgroup(SPDesktop *desktop)
+{
+ if (desktop == NULL) {
+ return;
+ }
+ SPDocument* doc = sp_desktop_document(desktop);
+ Inkscape::XML::Document *xml_doc = doc->getReprDoc();
+
+ Inkscape::Selection *selection = sp_desktop_selection(desktop);
+ if (selection->isEmpty()) {
+ desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select <b>object(s)</b> to create clippath or mask from."));
+ return;
+ }
+
+ GSList const *l = const_cast<GSList *>(selection->reprList());
+
+ GSList *p = g_slist_copy(const_cast<GSList *>(l));
+
+ p = g_slist_sort(p, (GCompareFunc) sp_repr_compare_position);
+
+ selection->clear();
+
+ gint topmost = (static_cast<Inkscape::XML::Node *>(g_slist_last(p)->data))->position();
+ Inkscape::XML::Node *topmost_parent = (static_cast<Inkscape::XML::Node *>(g_slist_last(p)->data))->parent();
+
+ Inkscape::XML::Node *inner = xml_doc->createElement("svg:g");
+ inner->setAttribute("inkscape:label", "Clip");
+
+ while (p) {
+ Inkscape::XML::Node *current = static_cast<Inkscape::XML::Node *>(p->data);
+
+ if (current->parent() == topmost_parent) {
+ Inkscape::XML::Node *spnew = current->duplicate(xml_doc);
+ sp_repr_unparent(current);
+ inner->appendChild(spnew);
+ Inkscape::GC::release(spnew);
+ topmost --; // only reduce count for those items deleted from topmost_parent
+ } else { // move it to topmost_parent first
+ GSList *temp_clip = NULL;
+
+ // At this point, current may already have no item, due to its being a clone whose original is already moved away
+ // So we copy it artificially calculating the transform from its repr->attr("transform") and the parent transform
+ gchar const *t_str = current->attribute("transform");
+ Geom::Affine item_t(Geom::identity());
+ if (t_str)
+ sp_svg_transform_read(t_str, &item_t);
+ item_t *= SP_ITEM(doc->getObjectByRepr(current->parent()))->i2doc_affine();
+ // FIXME: when moving both clone and original from a transformed group (either by
+ // grouping into another parent, or by cut/paste) the transform from the original's
+ // parent becomes embedded into original itself, and this affects its clones. Fix
+ // this by remembering the transform diffs we write to each item into an array and
+ // then, if this is clone, looking up its original in that array and pre-multiplying
+ // it by the inverse of that original's transform diff.
+
+ sp_selection_copy_one(current, item_t, &temp_clip, xml_doc);
+ sp_repr_unparent(current);
+
+ // paste into topmost_parent (temporarily)
+ GSList *copied = sp_selection_paste_impl(doc, doc->getObjectByRepr(topmost_parent), &temp_clip);
+ if (temp_clip) g_slist_free(temp_clip);
+ if (copied) { // if success,
+ // take pasted object (now in topmost_parent)
+ Inkscape::XML::Node *in_topmost = static_cast<Inkscape::XML::Node *>(copied->data);
+ // make a copy
+ Inkscape::XML::Node *spnew = in_topmost->duplicate(xml_doc);
+ // remove pasted
+ sp_repr_unparent(in_topmost);
+ // put its copy into group
+ inner->appendChild(spnew);
+ Inkscape::GC::release(spnew);
+ g_slist_free(copied);
+ }
+ }
+ p = g_slist_remove(p, current);
+ }
+
+ Inkscape::XML::Node *outer = xml_doc->createElement("svg:g");
+ outer->appendChild(inner);
+ topmost_parent->appendChild(outer);
+ outer->setPosition(topmost + 1);
+
+ Inkscape::XML::Node *clone = xml_doc->createElement("svg:use");
+ clone->setAttribute("x", "0", false);
+ clone->setAttribute("y", "0", false);
+ clone->setAttribute("xlink:href", g_strdup_printf("#%s", inner->attribute("id")), false);
+
+ clone->setAttribute("inkscape:transform-center-x", inner->attribute("inkscape:transform-center-x"), false);
+ clone->setAttribute("inkscape:transform-center-y", inner->attribute("inkscape:transform-center-y"), false);
+
+ const Geom::Affine maskTransform(Geom::Affine::identity());
+ GSList *templist = NULL;
+
+ templist = g_slist_append(templist, clone);
+ // add the new clone to the top of the original's parent
+ gchar const *mask_id = SPClipPath::create(templist, doc, &maskTransform);
+
+ g_slist_free(templist);
+
+ outer->setAttribute("clip-path", g_strdup_printf("url(#%s)", mask_id));
+
+ Inkscape::GC::release(clone);
+
+ selection->set(outer);
+ DocumentUndo::done(doc, SP_VERB_OBJECT_SET_CLIPPATH, _("Create Clip Group"));
+}
+
/**
* Creates a mask or clipPath from selection.
* Two different modes:
@@ -3929,14 +4165,14 @@ void sp_selection_unset_mask(SPDesktop *desktop, bool apply_clip_path) {
SP_OBJECT(i->data)->getRepr()->setAttribute(attributeName, "none");
- if (ungroup_masked && SP_IS_GROUP(i->data)) {
+ SPGroup *group = dynamic_cast<SPGroup *>(static_cast<SPObject *>(i->data));
+ if (ungroup_masked && group) {
// if we had previously enclosed masked object in group,
// add it to list so we can ungroup it later
- SPGroup *item = SP_GROUP(i->data);
// ungroup only groups we created when setting clip/mask
- if (item->layerMode() == SPGroup::MASK_HELPER) {
- items_to_ungroup = g_slist_prepend(items_to_ungroup, item);
+ if (group->layerMode() == SPGroup::MASK_HELPER) {
+ items_to_ungroup = g_slist_prepend(items_to_ungroup, group);
}
}
@@ -3950,6 +4186,10 @@ void sp_selection_unset_mask(SPDesktop *desktop, bool apply_clip_path) {
for ( SPObject *child = obj->firstChild() ; child; child = child->getNext() ) {
// Collect all clipped paths and masks within a single group
Inkscape::XML::Node *copy = SP_OBJECT(child)->getRepr()->duplicate(xml_doc);
+ if(copy->attribute("inkscape:original-d") && copy->attribute("inkscape:path-effect"))
+ {
+ copy->setAttribute("d", copy->attribute("inkscape:original-d"));
+ }
items_to_move = g_slist_prepend(items_to_move, copy);
}
@@ -3984,10 +4224,15 @@ void sp_selection_unset_mask(SPDesktop *desktop, bool apply_clip_path) {
// ungroup marked groups added when setting mask
for (GSList *i = items_to_ungroup ; NULL != i ; i = i->next) {
- items_to_select = g_slist_remove(items_to_select, SP_GROUP(i->data));
- GSList *children = NULL;
- sp_item_group_ungroup(SP_GROUP(i->data), &children, false);
- items_to_select = g_slist_concat(children, items_to_select);
+ SPGroup *group = dynamic_cast<SPGroup *>(static_cast<SPObject *>(i->data));
+ if (group) {
+ items_to_select = g_slist_remove(items_to_select, group);
+ GSList *children = NULL;
+ sp_item_group_ungroup(group, &children, false);
+ items_to_select = g_slist_concat(children, items_to_select);
+ } else {
+ g_assert_not_reached();
+ }
}
g_slist_free(items_to_ungroup);
@@ -4095,12 +4340,16 @@ void fit_canvas_to_selection_or_drawing(SPDesktop *desktop) {
static void itemtree_map(void (*f)(SPItem *, SPDesktop *), SPObject *root, SPDesktop *desktop) {
// don't operate on layers
- if (SP_IS_ITEM(root) && !desktop->isLayer(SP_ITEM(root))) {
- f(SP_ITEM(root), desktop);
+ {
+ SPItem *item = dynamic_cast<SPItem *>(root);
+ if (item && !desktop->isLayer(item)) {
+ f(item, desktop);
+ }
}
for ( SPObject::SiblingIterator iter = root->firstChild() ; iter ; ++iter ) {
//don't recurse into locked layers
- if (!(SP_IS_ITEM(&*iter) && desktop->isLayer(SP_ITEM(&*iter)) && SP_ITEM(&*iter)->isLocked())) {
+ SPItem *item = dynamic_cast<SPItem *>(&*iter);
+ if (!(item && desktop->isLayer(item) && item->isLocked())) {
itemtree_map(f, iter, desktop);
}
}
diff --git a/src/selection-chemistry.h b/src/selection-chemistry.h
index d76a67a9d..d86906548 100644
--- a/src/selection-chemistry.h
+++ b/src/selection-chemistry.h
@@ -17,21 +17,21 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
+#include <2geom/forward.h>
#include "sp-item.h"
-#include "2geom/forward.h"
-namespace Inkscape { class Selection; }
+class SPCSSAttr;
+class SPDesktop;
+typedef struct _GSList GSList;
namespace Inkscape {
+
+class Selection;
+
namespace LivePathEffect {
class PathParam;
}
-}
-class SPCSSAttr;
-class SPDesktop;
-
-namespace Inkscape {
class SelectionHelper {
public:
static void selectAll(SPDesktop *desktop);
@@ -104,25 +104,25 @@ void sp_selection_to_next_layer( SPDesktop *desktop, bool suppressDone = false )
void sp_selection_to_prev_layer( SPDesktop *desktop, bool suppressDone = false );
void sp_selection_to_layer( SPDesktop *desktop, SPObject *layer, bool suppressDone = false );
-void sp_selection_apply_affine(Inkscape::Selection *selection, Geom::Affine const &affine, bool set_i2d = true, bool compensate = true);
+void sp_selection_apply_affine(Inkscape::Selection *selection, Geom::Affine const &affine, bool set_i2d = true, bool compensate = true, bool adjust_transf_center = true);
void sp_selection_remove_transform (SPDesktop *desktop);
void sp_selection_scale_absolute (Inkscape::Selection *selection, double x0, double x1, double y0, double y1);
void sp_selection_scale_relative(Inkscape::Selection *selection, Geom::Point const &align, Geom::Scale const &scale);
-void sp_selection_rotate_relative (Inkscape::Selection *selection, Geom::Point const &center, gdouble angle);
+void sp_selection_rotate_relative (Inkscape::Selection *selection, Geom::Point const &center, double angle);
void sp_selection_skew_relative (Inkscape::Selection *selection, Geom::Point const &align, double dx, double dy);
void sp_selection_move_relative (Inkscape::Selection *selection, Geom::Point const &move, bool compensate = true);
void sp_selection_move_relative (Inkscape::Selection *selection, double dx, double dy);
void sp_selection_rotate_90 (SPDesktop *desktop, bool ccw);
-void sp_selection_rotate (Inkscape::Selection *selection, gdouble angle);
-void sp_selection_rotate_screen (Inkscape::Selection *selection, gdouble angle);
+void sp_selection_rotate (Inkscape::Selection *selection, double angle);
+void sp_selection_rotate_screen (Inkscape::Selection *selection, double angle);
-void sp_selection_scale (Inkscape::Selection *selection, gdouble grow);
-void sp_selection_scale_screen (Inkscape::Selection *selection, gdouble grow_pixels);
-void sp_selection_scale_times (Inkscape::Selection *selection, gdouble times);
+void sp_selection_scale (Inkscape::Selection *selection, double grow);
+void sp_selection_scale_screen (Inkscape::Selection *selection, double grow_pixels);
+void sp_selection_scale_times (Inkscape::Selection *selection, double times);
-void sp_selection_move (Inkscape::Selection *selection, gdouble dx, gdouble dy);
-void sp_selection_move_screen (Inkscape::Selection *selection, gdouble dx, gdouble dy);
+void sp_selection_move (Inkscape::Selection *selection, double dx, double dy);
+void sp_selection_move_screen (Inkscape::Selection *selection, double dx, double dy);
void sp_selection_item_next (SPDesktop *desktop);
void sp_selection_item_prev (SPDesktop *desktop);
@@ -156,6 +156,7 @@ void sp_document_get_export_hints (SPDocument * doc, Glib::ustring &filename, fl
void sp_selection_create_bitmap_copy (SPDesktop *desktop);
+void sp_selection_set_clipgroup(SPDesktop *desktop);
void sp_selection_set_mask(SPDesktop *desktop, bool apply_clip_path, bool apply_to_layer);
void sp_selection_unset_mask(SPDesktop *desktop, bool apply_clip_path);
diff --git a/src/selection-describer.cpp b/src/selection-describer.cpp
index 88450dfdf..f7814fd57 100644
--- a/src/selection-describer.cpp
+++ b/src/selection-describer.cpp
@@ -5,6 +5,7 @@
* MenTaLguY <mental@rydia.net>
* bulia byak <buliabyak@users.sf.net>
* Abhishek Sharma
+ * Jon A. Cruz <jon@joncruz.org>
*
* Copyright (C) 2004-2006 Authors
*
@@ -46,23 +47,46 @@ char* collect_terms (GSList *items)
bool first = true;
for (GSList *i = (GSList *)items; i != NULL; i = i->next) {
- const char *term = SP_ITEM(i->data)->displayName();
- if (term != NULL && g_slist_find (check, term) == NULL) {
- check = g_slist_prepend (check, (void *) term);
- ss << (first ? "" : ", ") << "<b>" << term << "</b>";
- first = false;
+ SPItem *item = dynamic_cast<SPItem *>(reinterpret_cast<SPObject *>(i->data));
+ if (item) {
+ const char *term = item->displayName();
+ if (term != NULL && g_slist_find (check, term) == NULL) {
+ check = g_slist_prepend (check, (void *) term);
+ ss << (first ? "" : ", ") << "<b>" << term << "</b>";
+ first = false;
+ }
}
}
return g_strdup(ss.str().c_str());
}
+// Returns the number of terms in the list
+static int count_terms (GSList *items)
+{
+ GSList *check = NULL;
+ int count=0;
+ for (GSList *i = (GSList *)items; i != NULL; i = i->next) {
+ SPItem *item = dynamic_cast<SPItem *>(reinterpret_cast<SPObject *>(i->data));
+ if (item) {
+ const char *term = item->displayName();
+ if (term != NULL && g_slist_find (check, term) == NULL) {
+ check = g_slist_prepend (check, (void *) term);
+ count++;
+ }
+ }
+ }
+ return count;
+}
+
// Returns the number of filtered items in the list
static int count_filtered (GSList *items)
{
int count=0;
for (GSList *i = items; i != NULL; i = i->next) {
- SPItem *item = SP_ITEM(i->data);
- count += item->isFiltered();
+ SPItem *item = dynamic_cast<SPItem *>(reinterpret_cast<SPObject *>((i->data)));
+ if (item) {
+ count += item->isFiltered();
+ }
}
return count;
}
@@ -103,7 +127,8 @@ void SelectionDescriber::_updateMessageFromSelection(Inkscape::Selection *select
if (!items) { // no items
_context.set(Inkscape::NORMAL_MESSAGE, _when_nothing);
} else {
- SPItem *item = SP_ITEM(items->data);
+ SPItem *item = dynamic_cast<SPItem *>(reinterpret_cast<SPObject *>(items->data));
+ g_assert(item != NULL);
SPObject *layer = selection->layers()->layerForObject(item);
SPObject *root = selection->layers()->currentRoot();
@@ -166,37 +191,51 @@ void SelectionDescriber::_updateMessageFromSelection(Inkscape::Selection *select
if (!items->next) { // one item
char *item_desc = item->detailedDescription();
- if (SP_IS_USE(item) && SP_IS_SYMBOL(item->firstChild())) {
+ bool isUse = dynamic_cast<SPUse *>(item) != NULL;
+ if (isUse && dynamic_cast<SPSymbol *>(item->firstChild())) {
_context.setF(Inkscape::NORMAL_MESSAGE, "%s%s. %s. %s.",
item_desc, in_phrase,
_("Convert symbol to group to edit"), _when_selected);
- } else if (SP_IS_SYMBOL(item)) {
+ } else if (dynamic_cast<SPSymbol *>(item)) {
_context.setF(Inkscape::NORMAL_MESSAGE, "%s%s. %s.",
item_desc, in_phrase,
_("Remove from symbols tray to edit symbol"));
- } else if (SP_IS_USE(item) || (SP_IS_OFFSET(item) && SP_OFFSET(item)->sourceHref)) {
- _context.setF(Inkscape::NORMAL_MESSAGE, "%s%s. %s. %s.",
- item_desc, in_phrase,
- _("Use <b>Shift+D</b> to look up original"), _when_selected);
- } else if (SP_IS_TEXT_TEXTPATH(item)) {
- _context.setF(Inkscape::NORMAL_MESSAGE, "%s%s. %s. %s.",
- item_desc, in_phrase,
- _("Use <b>Shift+D</b> to look up path"), _when_selected);
- } else if (SP_IS_FLOWTEXT(item) && !SP_FLOWTEXT(item)->has_internal_frame()) {
- _context.setF(Inkscape::NORMAL_MESSAGE, "%s%s. %s. %s.",
- item_desc, in_phrase,
- _("Use <b>Shift+D</b> to look up frame"), _when_selected);
} else {
- _context.setF(Inkscape::NORMAL_MESSAGE, "%s%s. %s.",
- item_desc, in_phrase, _when_selected);
+ SPOffset *offset = (isUse) ? NULL : dynamic_cast<SPOffset *>(item);
+ if (isUse || (offset && offset->sourceHref)) {
+ _context.setF(Inkscape::NORMAL_MESSAGE, "%s%s. %s. %s.",
+ item_desc, in_phrase,
+ _("Use <b>Shift+D</b> to look up original"), _when_selected);
+ } else {
+ SPText *text = dynamic_cast<SPText *>(item);
+ if (text && text->firstChild() && dynamic_cast<SPText *>(text->firstChild())) {
+ _context.setF(Inkscape::NORMAL_MESSAGE, "%s%s. %s. %s.",
+ item_desc, in_phrase,
+ _("Use <b>Shift+D</b> to look up path"), _when_selected);
+ } else {
+ SPFlowtext *flowtext = dynamic_cast<SPFlowtext *>(item);
+ if (flowtext && !flowtext->has_internal_frame()) {
+ _context.setF(Inkscape::NORMAL_MESSAGE, "%s%s. %s. %s.",
+ item_desc, in_phrase,
+ _("Use <b>Shift+D</b> to look up frame"), _when_selected);
+ } else {
+ _context.setF(Inkscape::NORMAL_MESSAGE, "%s%s. %s.",
+ item_desc, in_phrase, _when_selected);
+ }
+ }
+ }
}
+
g_free(item_desc);
} else { // multiple items
int objcount = g_slist_length((GSList *)items);
char *terms = collect_terms ((GSList *)items);
-
- gchar *objects_str = g_strdup_printf(
- "<b>%i</b> objects selected of types %s", objcount, terms);
+ int n_terms = count_terms((GSList *)items);
+
+ gchar *objects_str = g_strdup_printf(ngettext(
+ "<b>%i</b> objects selected of type %s",
+ "<b>%i</b> objects selected of types %s", n_terms),
+ objcount, terms);
g_free(terms);
diff --git a/src/selection-describer.h b/src/selection-describer.h
index b4174edd8..5514ce4b1 100644
--- a/src/selection-describer.h
+++ b/src/selection-describer.h
@@ -16,11 +16,10 @@
#include <sigc++/sigc++.h>
#include "message-context.h"
-namespace Inkscape { class Selection; }
-
namespace Inkscape {
class MessageStack;
+class Selection;
class SelectionDescriber : public sigc::trackable {
public:
@@ -29,7 +28,7 @@ public:
private:
void _updateMessageFromSelection(Inkscape::Selection *selection);
- void _selectionModified(Inkscape::Selection *selection, guint /*flags*/);
+ void _selectionModified(Inkscape::Selection *selection, unsigned int /*flags*/);
sigc::connection *_selection_changed_connection;
sigc::connection *_selection_modified_connection;
@@ -43,6 +42,7 @@ private:
}
#endif
+
/*
Local Variables:
mode:c++
diff --git a/src/selection.h b/src/selection.h
index ba38bec08..5964b20e8 100644
--- a/src/selection.h
+++ b/src/selection.h
@@ -30,6 +30,7 @@ class SPDesktop;
class SPItem;
class SPBox3D;
class Persp3D;
+typedef struct _GSList GSList;
namespace Inkscape {
class LayerModel;
@@ -256,10 +257,10 @@ public:
std::list<SPBox3D *> const box3DList(Persp3D *persp = NULL);
/** Returns the number of layers in which there are selected objects. */
- guint numberOfLayers();
+ unsigned int numberOfLayers();
/** Returns the number of parents to which the selected objects belong. */
- guint numberOfParents();
+ unsigned int numberOfParents();
/** Returns the bounding rectangle of the selection. */
Geom::OptRect bounds(SPItem::BBoxType type) const;
@@ -317,11 +318,11 @@ public:
* @return the resulting connection
*
*/
- sigc::connection connectModified(sigc::slot<void, Selection *, guint> const &slot)
+ sigc::connection connectModified(sigc::slot<void, Selection *, unsigned int> const &slot)
{
return _modified_signal.connect(slot);
}
- sigc::connection connectModifiedFirst(sigc::slot<void, Selection *, guint> const &slot)
+ sigc::connection connectModifiedFirst(sigc::slot<void, Selection *, unsigned int> const &slot)
{
return _modified_signal.slots().insert(_modified_signal.slots().begin(), slot);
}
@@ -333,12 +334,12 @@ private:
void operator=(Selection const &);
/** Issues modification notification signals. */
- static gboolean _emit_modified(Selection *selection);
+ static int _emit_modified(Selection *selection);
/** Schedules an item modification signal to be sent. */
- void _schedule_modified(SPObject *obj, guint flags);
+ void _schedule_modified(SPObject *obj, unsigned int flags);
/** Issues modified selection signal. */
- void _emitModified(guint flags);
+ void _emitModified(unsigned int flags);
/** Issues changed selection signal. */
void _emitChanged(bool persist_selection_context = false);
@@ -374,15 +375,15 @@ private:
LayerModel *_layers;
GC::soft_ptr<SPDesktop> _desktop;
SPObject* _selection_context;
- guint _flags;
- guint _idle;
+ unsigned int _flags;
+ unsigned int _idle;
std::map<SPObject *, sigc::connection> _modified_connections;
std::map<SPObject *, sigc::connection> _release_connections;
sigc::connection _context_release_connection;
sigc::signal<void, Selection *> _changed_signal;
- sigc::signal<void, Selection *, guint> _modified_signal;
+ sigc::signal<void, Selection *, unsigned int> _modified_signal;
};
}
diff --git a/src/seltrans-handles.h b/src/seltrans-handles.h
index 740729a6e..ebd5758c8 100644
--- a/src/seltrans-handles.h
+++ b/src/seltrans-handles.h
@@ -14,11 +14,13 @@
#include <2geom/forward.h>
#include <gdk/gdk.h>
+
#include "enums.h"
-namespace Inkscape
-{
- class SelTrans;
+typedef unsigned int guint32;
+
+namespace Inkscape {
+ class SelTrans;
}
guint32 const DEF_COLOR[] = { 0xff, 0xff6600, 0xff6600, 0xff, 0xff, 0xff };
@@ -34,7 +36,7 @@ enum SPSelTransType {
struct SPSelTransTypeInfo {
guint32 const *color;
- gchar const *tip;
+ char const *tip;
};
// One per handle type in order
extern SPSelTransTypeInfo const handtypes[5];
@@ -45,7 +47,7 @@ struct SPSelTransHandle {
SPSelTransType type;
SPAnchorType anchor;
GdkCursorType cursor;
- guint control;
+ unsigned int control;
gdouble x, y;
};
// These are 4 * each handle type + 1 for center
@@ -64,5 +66,3 @@ extern SPSelTransHandle const hands[17];
End:
*/
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
-
-
diff --git a/src/seltrans.cpp b/src/seltrans.cpp
index 60a0bfa11..96c7fb49b 100644
--- a/src/seltrans.cpp
+++ b/src/seltrans.cpp
@@ -9,7 +9,7 @@
* Abhishek Sharma
*
* Copyright (C) 1999-2002 Lauris Kaplinski
- * Copyright (C) 1999-2008 Authors
+ * Copyright (C) 1999-2014 Authors
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
@@ -304,6 +304,7 @@ void Inkscape::SelTrans::grab(Geom::Point const &p, gdouble x, gdouble y, bool s
/* Snapping a huge number of nodes will take way too long, so limit the number of snappable nodes
A typical user would rarely ever try to snap such a large number of nodes anyway, because
(s)he would hardly be able to discern which node would be snapping */
+ std::cout << "Warning: limit of 200 snap sources reached, some will be ignored" << std::endl;
_snap_points.resize(200);
// Unfortunately, by now we will have lost the font-baseline snappoints :-(
}
@@ -389,6 +390,7 @@ void Inkscape::SelTrans::transform(Geom::Affine const &rel_affine, Geom::Point c
}
Geom::Affine const &prev_transform = _items_affines[i];
item.set_i2d_affine(prev_transform * affine);
+ // The new affine will only have been applied if the transformation is different from the previous one, see SPItem::set_item_transform
}
} else {
if (_bbox) {
@@ -439,21 +441,25 @@ void Inkscape::SelTrans::ungrab()
_message_context.clear();
if (!_empty && _changed) {
- sp_selection_apply_affine(selection, _current_relative_affine, (_show == SHOW_OUTLINE)? true : false);
- if (_center) {
- *_center *= _current_relative_affine;
- _center_is_set = true;
- }
+ if (!_current_relative_affine.isIdentity()) { // we can have a identity affine
+ // when trying to stretch a perfectly vertical line in horizontal direction, which will not be allowed by the handles;
+
+ sp_selection_apply_affine(selection, _current_relative_affine, (_show == SHOW_OUTLINE)? true : false);
+ if (_center) {
+ *_center *= _current_relative_affine;
+ _center_is_set = true;
+ }
-// If dragging showed content live, sp_selection_apply_affine cannot change the centers
-// appropriately - it does not know the original positions of the centers (all objects already have
-// the new bboxes). So we need to reset the centers from our saved array.
- if (_show != SHOW_OUTLINE && !_current_relative_affine.isTranslation()) {
- for (unsigned i = 0; i < _items_centers.size(); i++) {
- SPItem *currentItem = _items[i];
- if (currentItem->isCenterSet()) { // only if it's already set
- currentItem->setCenter (_items_centers[i] * _current_relative_affine);
- currentItem->updateRepr();
+ // If dragging showed content live, sp_selection_apply_affine cannot change the centers
+ // appropriately - it does not know the original positions of the centers (all objects already have
+ // the new bboxes). So we need to reset the centers from our saved array.
+ if (_show != SHOW_OUTLINE && !_current_relative_affine.isTranslation()) {
+ for (unsigned i = 0; i < _items_centers.size(); i++) {
+ SPItem *currentItem = _items[i];
+ if (currentItem->isCenterSet()) { // only if it's already set
+ currentItem->setCenter (_items_centers[i] * _current_relative_affine);
+ currentItem->updateRepr();
+ }
}
}
}
@@ -463,18 +469,22 @@ void Inkscape::SelTrans::ungrab()
_items_affines.clear();
_items_centers.clear();
- if (_current_relative_affine.isTranslation()) {
- DocumentUndo::done(sp_desktop_document(_desktop), SP_VERB_CONTEXT_SELECT,
- _("Move"));
- } else if (_current_relative_affine.withoutTranslation().isScale()) {
- DocumentUndo::done(sp_desktop_document(_desktop), SP_VERB_CONTEXT_SELECT,
- _("Scale"));
- } else if (_current_relative_affine.withoutTranslation().isRotation()) {
- DocumentUndo::done(sp_desktop_document(_desktop), SP_VERB_CONTEXT_SELECT,
- _("Rotate"));
- } else {
- DocumentUndo::done(sp_desktop_document(_desktop), SP_VERB_CONTEXT_SELECT,
- _("Skew"));
+ if (!_current_relative_affine.isIdentity()) { // we can have a identity affine
+ // when trying to stretch a perfectly vertical line in horizontal direction, which will not be allowed
+ // by the handles; this would be identified as a (zero) translation by isTranslation()
+ if (_current_relative_affine.isTranslation()) {
+ DocumentUndo::done(sp_desktop_document(_desktop), SP_VERB_CONTEXT_SELECT,
+ _("Move"));
+ } else if (_current_relative_affine.withoutTranslation().isScale()) {
+ DocumentUndo::done(sp_desktop_document(_desktop), SP_VERB_CONTEXT_SELECT,
+ _("Scale"));
+ } else if (_current_relative_affine.withoutTranslation().isRotation()) {
+ DocumentUndo::done(sp_desktop_document(_desktop), SP_VERB_CONTEXT_SELECT,
+ _("Rotate"));
+ } else {
+ DocumentUndo::done(sp_desktop_document(_desktop), SP_VERB_CONTEXT_SELECT,
+ _("Skew"));
+ }
}
} else {
@@ -506,7 +516,7 @@ void Inkscape::SelTrans::stamp()
bool fixup = !_grabbed;
if ( fixup && _stamp_cache ) {
- // TODO - give a proper fix. Simple temproary work-around for the grab() issue
+ // TODO - give a proper fix. Simple temporary work-around for the grab() issue
g_slist_free(_stamp_cache);
_stamp_cache = NULL;
}
@@ -565,7 +575,7 @@ void Inkscape::SelTrans::stamp()
}
if ( fixup && _stamp_cache ) {
- // TODO - give a proper fix. Simple temproary work-around for the grab() issue
+ // TODO - give a proper fix. Simple temporary work-around for the grab() issue
g_slist_free(_stamp_cache);
_stamp_cache = NULL;
}
@@ -641,7 +651,7 @@ void Inkscape::SelTrans::_makeHandles()
{
for (int i = 0; i < NUMHANDS; i++) {
SPSelTransTypeInfo info = handtypes[hands[i].type];
- knots[i] = new SPKnot(_desktop, info.tip);
+ knots[i] = new SPKnot(_desktop, _(info.tip));
knots[i]->setShape(SP_CTRL_SHAPE_BITMAP);
knots[i]->setSize(13);
@@ -914,23 +924,28 @@ gboolean Inkscape::SelTrans::scaleRequest(Geom::Point &pt, guint state)
sn = m.freeSnapScale(_snap_points, _point, geom_scale, _origin_for_specpoints);
}
- if (!(bb.getSnapped() || sn.getSnapped())) {
+ // These lines below are duplicated in stretchRequest
+ if (bb.getSnapped() || sn.getSnapped()) {
+ if (bb.getSnapped()) {
+ if (!bb.isOtherSnapBetter(sn, false)) {
+ // We snapped the bbox (which is either visual or geometric)
+ _desktop->snapindicator->set_new_snaptarget(bb);
+ default_scale = Geom::Scale(bb.getTransformation());
+ // Calculate the new transformation and update the handle position
+ pt = _calcAbsAffineDefault(default_scale);
+ }
+ } else if (sn.getSnapped()) {
+ _desktop->snapindicator->set_new_snaptarget(sn);
+ // We snapped the special points (e.g. nodes), which are not at the visual bbox
+ // The handle location however (pt) might however be at the visual bbox, so we
+ // will have to calculate pt taking the stroke width into account
+ geom_scale = Geom::Scale(sn.getTransformation());
+ pt = _calcAbsAffineGeom(geom_scale);
+ }
+ } else {
// We didn't snap at all! Don't update the handle position, just calculate the new transformation
_calcAbsAffineDefault(default_scale);
_desktop->snapindicator->remove_snaptarget();
- } else if (bb.getSnapped() && !bb.isOtherSnapBetter(sn, false)) {
- // We snapped the bbox (which is either visual or geometric)
- _desktop->snapindicator->set_new_snaptarget(bb);
- default_scale = Geom::Scale(bb.getTransformation());
- // Calculate the new transformation and update the handle position
- pt = _calcAbsAffineDefault(default_scale);
- } else {
- _desktop->snapindicator->set_new_snaptarget(sn);
- // We snapped the special points (e.g. nodes), which are not at the visual bbox
- // The handle location however (pt) might however be at the visual bbox, so we
- // will have to calculate pt taking the stroke width into account
- geom_scale = Geom::Scale(sn.getTransformation());
- pt = _calcAbsAffineGeom(geom_scale);
}
m.unSetup();
}
@@ -1013,20 +1028,28 @@ gboolean Inkscape::SelTrans::stretchRequest(SPSelTransHandle const &handle, Geom
geom_scale[perp] = fabs(geom_scale[axis]);
}
- if (!(bb.getSnapped() || sn.getSnapped())) {
+ // These lines below are duplicated in scaleRequest
+ if (bb.getSnapped() || sn.getSnapped()) {
+ if (bb.getSnapped()) {
+ if (!bb.isOtherSnapBetter(sn, false)) {
+ // We snapped the bbox (which is either visual or geometric)
+ _desktop->snapindicator->set_new_snaptarget(bb);
+ default_scale = Geom::Scale(bb.getTransformation());
+ // Calculate the new transformation and update the handle position
+ pt = _calcAbsAffineDefault(default_scale);
+ }
+ } else if (sn.getSnapped()) {
+ _desktop->snapindicator->set_new_snaptarget(sn);
+ // We snapped the special points (e.g. nodes), which are not at the visual bbox
+ // The handle location however (pt) might however be at the visual bbox, so we
+ // will have to calculate pt taking the stroke width into account
+ geom_scale = Geom::Scale(sn.getTransformation());
+ pt = _calcAbsAffineGeom(geom_scale);
+ }
+ } else {
// We didn't snap at all! Don't update the handle position, just calculate the new transformation
_calcAbsAffineDefault(default_scale);
_desktop->snapindicator->remove_snaptarget();
- } else if (bb.getSnapped() && !bb.isOtherSnapBetter(sn, false)) {
- _desktop->snapindicator->set_new_snaptarget(bb);
- // Calculate the new transformation and update the handle position
- pt = _calcAbsAffineDefault(default_scale);
- } else {
- _desktop->snapindicator->set_new_snaptarget(sn);
- // We snapped the special points (e.g. nodes), which are not at the visual bbox
- // The handle location however (pt) might however be at the visual bbox, so we
- // will have to calculate pt taking the stroke width into account
- pt = _calcAbsAffineGeom(geom_scale);
}
m.unSetup();
@@ -1086,10 +1109,17 @@ gboolean Inkscape::SelTrans::skewRequest(SPSelTransHandle const &handle, Geom::P
break;
}
+ // _point and _origin are noisy, ranging from 1 to 1e-9 or even smaller; this is due to the
+ // limited SVG output precision, which can be arbitrarily set in the preferences
Geom::Point const initial_delta = _point - _origin;
- if (fabs(initial_delta[dim_a]) < 1e-15) {
- return false;
+ // The handle and the origin shouldn't be too close to each other; let's check for that!
+ // Due to the limited resolution though (see above), we'd better use a relative error here
+ if (_bbox) {
+ Geom::Coord d = (*_bbox).dimensions()[dim_a];
+ if (fabs(initial_delta[dim_a]/d) < 1e-4) {
+ return false;
+ }
}
// Calculate the scale factors, which can be either visual or geometric
diff --git a/src/seltrans.h b/src/seltrans.h
index 44268ed69..d5db1542d 100644
--- a/src/seltrans.h
+++ b/src/seltrans.h
@@ -15,32 +15,33 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include <stddef.h>
-#include <sigc++/sigc++.h>
#include <2geom/point.h>
#include <2geom/affine.h>
#include <2geom/rect.h>
+#include <cstddef>
+#include <sigc++/sigc++.h>
+#include <vector>
+
#include "knot.h"
-#include "selcue.h"
#include "message-context.h"
-#include <vector>
-#include "sp-item.h"
#include "seltrans-handles.h"
+#include "selcue.h"
+#include "sp-item.h"
+
class SPKnot;
class SPDesktop;
struct SPCanvasItem;
struct SPCtrlLine;
struct SPSelTransHandle;
+typedef struct _GSList GSList;
-namespace Inkscape
-{
+namespace Inkscape {
Geom::Scale calcScaleFactors(Geom::Point const &initial_point, Geom::Point const &new_point, Geom::Point const &origin, bool const skew = false);
-namespace XML
-{
- class Node;
+namespace XML {
+ class Node;
}
class SelTrans
@@ -56,26 +57,26 @@ public:
void increaseState();
void resetState();
void setCenter(Geom::Point const &p);
- void grab(Geom::Point const &p, gdouble x, gdouble y, bool show_handles, bool translating);
+ void grab(Geom::Point const &p, double x, double y, bool show_handles, bool translating);
void transform(Geom::Affine const &rel_affine, Geom::Point const &norm);
void ungrab();
void stamp();
- void moveTo(Geom::Point const &xy, guint state);
- void stretch(SPSelTransHandle const &handle, Geom::Point &pt, guint state);
- void scale(Geom::Point &pt, guint state);
- void skew(SPSelTransHandle const &handle, Geom::Point &pt, guint state);
- void rotate(Geom::Point &pt, guint state);
- gboolean request(SPSelTransHandle const &handle, Geom::Point &pt, guint state);
- gboolean scaleRequest(Geom::Point &pt, guint state);
- gboolean stretchRequest(SPSelTransHandle const &handle, Geom::Point &pt, guint state);
- gboolean skewRequest(SPSelTransHandle const &handle, Geom::Point &pt, guint state);
- gboolean rotateRequest(Geom::Point &pt, guint state);
- gboolean centerRequest(Geom::Point &pt, guint state);
-
- gboolean handleRequest(SPKnot *knot, Geom::Point *position, guint state, SPSelTransHandle const &handle);
- void handleGrab(SPKnot *knot, guint state, SPSelTransHandle const &handle);
- void handleClick(SPKnot *knot, guint state, SPSelTransHandle const &handle);
- void handleNewEvent(SPKnot *knot, Geom::Point *position, guint state, SPSelTransHandle const &handle);
+ void moveTo(Geom::Point const &xy, unsigned int state);
+ void stretch(SPSelTransHandle const &handle, Geom::Point &pt, unsigned int state);
+ void scale(Geom::Point &pt, unsigned int state);
+ void skew(SPSelTransHandle const &handle, Geom::Point &pt, unsigned int state);
+ void rotate(Geom::Point &pt, unsigned int state);
+ int request(SPSelTransHandle const &handle, Geom::Point &pt, unsigned int state);
+ int scaleRequest(Geom::Point &pt, unsigned int state);
+ int stretchRequest(SPSelTransHandle const &handle, Geom::Point &pt, unsigned int state);
+ int skewRequest(SPSelTransHandle const &handle, Geom::Point &pt, unsigned int state);
+ int rotateRequest(Geom::Point &pt, unsigned int state);
+ int centerRequest(Geom::Point &pt, unsigned int state);
+
+ int handleRequest(SPKnot *knot, Geom::Point *position, unsigned int state, SPSelTransHandle const &handle);
+ void handleGrab(SPKnot *knot, unsigned int state, SPSelTransHandle const &handle);
+ void handleClick(SPKnot *knot, unsigned int state, SPSelTransHandle const &handle);
+ void handleNewEvent(SPKnot *knot, Geom::Point *position, unsigned int state, SPSelTransHandle const &handle);
enum Show
{
@@ -115,7 +116,7 @@ private:
void _updateHandles();
void _updateVolatileState();
void _selChanged(Inkscape::Selection *selection);
- void _selModified(Inkscape::Selection *selection, guint flags);
+ void _selModified(Inkscape::Selection *selection, unsigned int flags);
void _boundingBoxPrefsChanged(int prefs_bbox);
void _makeHandles();
void _showHandles(SPSelTransType type);
@@ -156,7 +157,7 @@ private:
Geom::OptRect _bbox;
Geom::OptRect _visual_bbox;
Geom::OptRect _geometric_bbox;
- gdouble _strokewidth;
+ double _strokewidth;
Geom::Affine _current_relative_affine;
Geom::Affine _absolute_affine;
@@ -173,8 +174,8 @@ private:
Geom::Point _origin_for_specpoints;
Geom::Point _origin_for_bboxpoints;
- gdouble _handle_x;
- gdouble _handle_y;
+ double _handle_x;
+ double _handle_y;
boost::optional<Geom::Point> _center;
bool _center_is_set; ///< we've already set _center, no need to reread it from items
@@ -184,8 +185,8 @@ private:
SPCanvasItem *_norm;
SPCanvasItem *_grip;
SPCtrlLine *_l[4];
- guint _sel_changed_id;
- guint _sel_modified_id;
+ unsigned int _sel_changed_id;
+ unsigned int _sel_modified_id;
GSList *_stamp_cache;
Geom::Point _origin; ///< position of origin for transforms
diff --git a/src/shape-editor.cpp b/src/shape-editor.cpp
deleted file mode 100644
index bf53e8bc3..000000000
--- a/src/shape-editor.cpp
+++ /dev/null
@@ -1,255 +0,0 @@
-/*
- * Inkscape::ShapeEditor
- *
- * Authors:
- * bulia byak <buliabyak@users.sf.net>
- * Krzysztof Kosiński <tweenk.pl@gmail.com>
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <string.h>
-#include <glibmm/i18n.h>
-
-#include "sp-object.h"
-#include "sp-item.h"
-#include "sp-lpe-item.h"
-#include "live_effects/lpeobject.h"
-#include "selection.h"
-#include "desktop.h"
-#include "document.h"
-#include "desktop-handles.h"
-#include "knotholder.h"
-#include "live_effects/parameter/point.h"
-#include "xml/node-event-vector.h"
-#include "preferences.h"
-#include "object-edit.h"
-#include "style.h"
-#include "display/curve.h"
-#include <2geom/pathvector.h>
-
-#include "shape-editor.h"
-
-using Inkscape::createKnotHolder;
-
-bool ShapeEditor::_blockSetItem = false;
-
-ShapeEditor::ShapeEditor(SPDesktop *dt) {
- this->desktop = dt;
- this->knotholder = NULL;
- this->knotholder_listener_attached_for = NULL;
-}
-
-ShapeEditor::~ShapeEditor() {
- unset_item(SH_KNOTHOLDER);
-}
-
-void ShapeEditor::unset_item(SubType type, bool keep_knotholder) {
- switch (type) {
- case SH_NODEPATH:
- // defunct
- break;
- case SH_KNOTHOLDER:
- if (this->knotholder) {
- Inkscape::XML::Node *old_repr = this->knotholder->repr;
- if (old_repr && old_repr == knotholder_listener_attached_for) {
- sp_repr_remove_listener_by_data(old_repr, this);
- Inkscape::GC::release(old_repr);
- knotholder_listener_attached_for = NULL;
- }
-
- if (!keep_knotholder) {
- delete this->knotholder;
- this->knotholder = NULL;
- }
- }
- break;
- }
-}
-
-bool ShapeEditor::has_nodepath () {
- return false;
-}
-
-bool ShapeEditor::has_knotholder () {
- return (this->knotholder != NULL);
-}
-
-void ShapeEditor::update_knotholder () {
- if (this->knotholder)
- this->knotholder->update_knots();
-}
-
-bool ShapeEditor::has_local_change (SubType type) {
- switch (type) {
- case SH_NODEPATH:
- // defunct
- return false;
- case SH_KNOTHOLDER:
- return (this->knotholder && this->knotholder->local_change != 0);
- default:
- g_assert_not_reached();
- }
-}
-
-void ShapeEditor::decrement_local_change (SubType type) {
- switch (type) {
- case SH_NODEPATH:
- // defunct
- break;
- case SH_KNOTHOLDER:
- if (this->knotholder) {
- this->knotholder->local_change = FALSE;
- }
- break;
- default:
- g_assert_not_reached();
- }
-}
-
-const SPItem *ShapeEditor::get_item (SubType type) {
- const SPItem *item = NULL;
- switch (type) {
- case SH_NODEPATH:
- // defunct
- break;
- case SH_KNOTHOLDER:
- if (this->has_knotholder()) {
- item = this->knotholder->getItem();
- }
- break;
- }
- return item;
-}
-
-GList *ShapeEditor::save_nodepath_selection () {
- // defunct stub
- return NULL;
-}
-
-void ShapeEditor::restore_nodepath_selection (GList */*saved*/) {
- // defunct stub
-}
-
-void ShapeEditor::shapeeditor_event_attr_changed(gchar const *name)
-{
- gboolean changed_kh = FALSE;
-
- if (has_knotholder())
- {
- changed_kh = !has_local_change(SH_KNOTHOLDER);
- decrement_local_change(SH_KNOTHOLDER);
- if (changed_kh) {
- // this can happen if an LPEItem's knotholder handle was dragged, in which case we want
- // to keep the knotholder; in all other cases (e.g., if the LPE itself changes) we delete it
- reset_item(SH_KNOTHOLDER, !strcmp(name, "d"));
- }
- }
-}
-
-
-static void shapeeditor_event_attr_changed(Inkscape::XML::Node */*repr*/, gchar const *name,
- gchar const */*old_value*/, gchar const */*new_value*/,
- bool /*is_interactive*/, gpointer data)
-{
- g_assert(data);
- ShapeEditor *sh = static_cast<ShapeEditor *>(data);
-
- sh->shapeeditor_event_attr_changed(name);
-}
-
-static Inkscape::XML::NodeEventVector shapeeditor_repr_events = {
- NULL, /* child_added */
- NULL, /* child_removed */
- shapeeditor_event_attr_changed,
- NULL, /* content_changed */
- NULL /* order_changed */
-};
-
-
-void ShapeEditor::set_item(SPItem *item, SubType type, bool keep_knotholder) {
- if (_blockSetItem) {
- return;
- }
-
- // this happens (and should only happen) when for an LPEItem having both knotholder and
- // nodepath the knotholder is adapted; in this case we don't want to delete the knotholder
- // since this freezes the handles
- unset_item(type, keep_knotholder);
-
- if (item) {
- Inkscape::XML::Node *repr;
- switch(type) {
- case SH_NODEPATH:
- // defunct
- break;
-
- case SH_KNOTHOLDER:
- if (!this->knotholder) {
- // only recreate knotholder if none is present
- this->knotholder = createKnotHolder(item, desktop);
- }
- if (this->knotholder) {
- this->knotholder->update_knots();
- // setting new listener
- repr = this->knotholder->repr;
- if (repr != knotholder_listener_attached_for) {
- Inkscape::GC::anchor(repr);
- sp_repr_add_listener(repr, &shapeeditor_repr_events, this);
- knotholder_listener_attached_for = repr;
- }
- }
- break;
- }
- }
-}
-
-
-/** FIXME: This thing is only called when the item needs to be updated in response to repr change.
- Why not make a reload function in NodePath and in KnotHolder? */
-void ShapeEditor::reset_item (SubType type, bool keep_knotholder)
-{
- switch (type) {
- case SH_NODEPATH:
- // defunct
- break;
- case SH_KNOTHOLDER:
- if ( knotholder ) {
- SPObject *obj = sp_desktop_document(desktop)->getObjectByRepr(knotholder_listener_attached_for); /// note that it is not certain that this is an SPItem; it could be a LivePathEffectObject.
- set_item(SP_ITEM(obj), SH_KNOTHOLDER, keep_knotholder);
- }
- break;
- }
-}
-
-void ShapeEditor::nodepath_destroyed () {
-}
-
-bool ShapeEditor::has_selection() {
- return false; // so far, knotholder cannot have selection
-}
-
-/**
- * Returns true if this ShapeEditor has a knot above which the mouse currently hovers.
- */
-bool ShapeEditor::knot_mouseover() const {
- if (this->knotholder) {
- return knotholder->knot_mouseover();
- }
-
- return false;
-}
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/shape-editor.h b/src/shape-editor.h
deleted file mode 100644
index ec4b50fa3..000000000
--- a/src/shape-editor.h
+++ /dev/null
@@ -1,95 +0,0 @@
-#ifndef SEEN_SHAPE_EDITOR_H
-#define SEEN_SHAPE_EDITOR_H
-
-/*
- * Inkscape::ShapeEditor
- *
- * This is a container class which contains either knotholder (for shapes) or nodepath (for
- * paths). It is attached to a single item so only one of these is active at a time.
- *
- * Authors:
- * bulia byak <buliabyak@users.sf.net>
- *
- */
-
-#include <glib.h>
-
-#include <2geom/forward.h>
-
-
-namespace Inkscape { namespace NodePath { class Path; } }
-namespace Inkscape { namespace XML { class Node; } }
-
-class KnotHolder;
-class LivePathEffectObject;
-class SPDesktop;
-class SPItem;
-class SPNodeContext;
-class ShapeEditorsCollective;
-
-#include <2geom/point.h>
-#include <boost/optional.hpp>
-#include <vector>
-
-enum SubType{
- SH_NODEPATH,
- SH_KNOTHOLDER
-};
-
-class ShapeEditor {
-public:
-
- ShapeEditor(SPDesktop *desktop);
- ~ShapeEditor();
-
- void set_item (SPItem *item, SubType type, bool keep_knotholder = false);
- void unset_item (SubType type, bool keep_knotholder = false);
-
- bool has_nodepath (); //((deprecated))
- void update_knotholder (); //((deprecated))
-
- bool has_local_change (SubType type);
- void decrement_local_change (SubType type);
-
- GList *save_nodepath_selection ();
- void restore_nodepath_selection (GList *saved);
-
- void nodepath_destroyed ();
-
- bool has_selection ();
-
- Inkscape::NodePath::Path *get_nodepath() {return NULL;} //((deprecated))
- ShapeEditorsCollective *get_container() {return NULL;}
-
- // this one is only public because it's called from non-C++ repr changed callback
- void shapeeditor_event_attr_changed(gchar const *name);
-
- bool knot_mouseover() const;
-
- static void blockSetItem(bool b) {_blockSetItem = b;}
-
-private:
- bool has_knotholder ();
- void reset_item (SubType type, bool keep_knotholder = true);
- const SPItem *get_item (SubType type);
- static bool _blockSetItem;
-
- SPDesktop *desktop;
- KnotHolder *knotholder;
- Inkscape::XML::Node *knotholder_listener_attached_for;
-};
-
-#endif // SEEN_SHAPE_EDITOR_H
-
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
-
diff --git a/src/shortcuts.h b/src/shortcuts.h
index 406768f97..f24a82603 100644
--- a/src/shortcuts.h
+++ b/src/shortcuts.h
@@ -1,5 +1,5 @@
-#ifndef __SP_SHORTCUTS_H__
-#define __SP_SHORTCUTS_H__
+#ifndef SEEN_SP_SHORTCUTS_H
+#define SEEN_SP_SHORTCUTS_H
/*
* Keyboard shortcut processing
@@ -16,9 +16,6 @@
typedef struct _GtkAccelGroup GtkAccelGroup;
typedef struct _GtkWidget GtkWidget;
-struct _GtkAccelGroup;
-struct _GtkWidget;
-
namespace Inkscape {
class Verb;
namespace UI {
@@ -42,14 +39,14 @@ bool sp_shortcut_invoke (unsigned int shortcut, Inkscape::UI::View::View *view);
void sp_shortcut_init();
Inkscape::Verb * sp_shortcut_get_verb (unsigned int shortcut);
unsigned int sp_shortcut_get_primary (Inkscape::Verb * verb); // Returns GDK_VoidSymbol if no shortcut is found.
-gchar* sp_shortcut_get_label (unsigned int shortcut); // Returns the human readable form of the shortcut (or NULL), for example Shift+Ctrl+F. Free the returned string with g_free.
+char* sp_shortcut_get_label (unsigned int shortcut); // Returns the human readable form of the shortcut (or NULL), for example Shift+Ctrl+F. Free the returned string with g_free.
void sp_shortcut_set(unsigned int const shortcut, Inkscape::Verb *const verb, bool const is_primary, bool const is_user_set=false);
void sp_shortcut_unset(unsigned int const shortcut);
void sp_shortcut_add_to_file(char const *action, unsigned int const shortcut);
void sp_shortcut_delete_from_file(char const *action, unsigned int const shortcut);
void sp_shortcuts_delete_all_from_file();
Glib::ustring sp_shortcut_to_label(unsigned int const shortcut);
-unsigned int sp_gdkmodifier_to_shortcut(guint accel_key, Gdk::ModifierType gdkmodifier, guint hardware_keycode);
+unsigned int sp_gdkmodifier_to_shortcut(unsigned int accel_key, Gdk::ModifierType gdkmodifier, unsigned int hardware_keycode);
void sp_shortcut_get_file_names(std::vector<Glib::ustring> *names, std::vector<Glib::ustring> *paths);
bool sp_shortcut_is_user_set(Inkscape::Verb *verb);
void sp_shortcut_file_export();
diff --git a/src/snap-candidate.h b/src/snap-candidate.h
index 8bb7cb52f..54e33e1a8 100644
--- a/src/snap-candidate.h
+++ b/src/snap-candidate.h
@@ -14,7 +14,10 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-//#include "snapped-point.h"
+#include <2geom/point.h>
+#include <2geom/rect.h>
+#include <cstdio>
+
#include "snap-enums.h"
class SPItem; // forward declaration
diff --git a/src/snap-preferences.h b/src/snap-preferences.h
index a7a2e2926..7bdeea52e 100644
--- a/src/snap-preferences.h
+++ b/src/snap-preferences.h
@@ -49,13 +49,13 @@ public:
void setSnapPerp(bool enabled) {_snap_perp = enabled;}
void setSnapTang(bool enabled) {_snap_tang = enabled;}
- gdouble getGridTolerance() const {return _grid_tolerance;}
- gdouble getGuideTolerance() const {return _guide_tolerance;}
- gdouble getObjectTolerance() const {return _object_tolerance;}
+ double getGridTolerance() const {return _grid_tolerance;}
+ double getGuideTolerance() const {return _guide_tolerance;}
+ double getObjectTolerance() const {return _object_tolerance;}
- void setGridTolerance(gdouble val) {_grid_tolerance = val;}
- void setGuideTolerance(gdouble val) {_guide_tolerance = val;}
- void setObjectTolerance(gdouble val) {_object_tolerance = val;}
+ void setGridTolerance(double val) {_grid_tolerance = val;}
+ void setGuideTolerance(double val) {_guide_tolerance = val;}
+ void setObjectTolerance(double val) {_object_tolerance = val;}
private:
@@ -91,9 +91,9 @@ private:
bool _snap_perp;
bool _snap_tang;
- gdouble _grid_tolerance;
- gdouble _guide_tolerance;
- gdouble _object_tolerance;
+ double _grid_tolerance;
+ double _guide_tolerance;
+ double _object_tolerance;
};
}
diff --git a/src/snap.cpp b/src/snap.cpp
index ecf799cdc..8138e4546 100644
--- a/src/snap.cpp
+++ b/src/snap.cpp
@@ -116,7 +116,7 @@ void SnapManager::freeSnapReturnByRef(Geom::Point &p,
Inkscape::SnapSourceType const source_type,
Geom::OptRect const &bbox_to_snap) const
{
- Inkscape::SnappedPoint const s = freeSnap(Inkscape::SnapCandidatePoint(p, source_type), bbox_to_snap);
+ Inkscape::SnappedPoint const s = freeSnap(Inkscape::SnapCandidatePoint(p, source_type, Inkscape::SNAPTARGET_PATH), bbox_to_snap);
s.getPointIfSnapped(p);
}
@@ -239,7 +239,7 @@ Inkscape::SnappedPoint SnapManager::constrainedSnap(Inkscape::SnapCandidatePoint
// Snapping the mouse pointer instead of the constrained position of the knot allows
// to snap to things which don't intersect with the constraint line; this is basically
// then just a freesnap with the constraint applied afterwards
- // We'll only to this if we're dragging a single handle, and for example not when transforming an object in the selector tool
+ // We'll only do this if we're dragging a single handle, and for example not when transforming an object in the selector tool
result = freeSnap(p, bbox_to_snap);
if (result.getSnapped()) {
// only change the snap indicator if we really snapped to something
@@ -274,7 +274,7 @@ Inkscape::SnappedPoint SnapManager::constrainedSnap(Inkscape::SnapCandidatePoint
/* See the documentation for constrainedSnap() directly above for more details.
* The difference is that multipleConstrainedSnaps() will take a list of constraints instead of a single one,
- * and will try to snap the SnapCandidatePoint to all of the provided constraints and see which one fits best
+ * and will try to snap the SnapCandidatePoint to only the closest constraint
* \param p Source point to be snapped
* \param constraints List of directions or lines along which snapping must occur
* \param dont_snap If true then we will only apply the constraint, without snapping
@@ -293,16 +293,11 @@ Inkscape::SnappedPoint SnapManager::multipleConstrainedSnaps(Inkscape::SnapCandi
return no_snap;
}
- IntermSnapResults isr;
- SnapperList const snappers = getSnappers();
- std::vector<Geom::Point> projections;
- bool snapping_is_futile = !someSnapperMightSnap() || dont_snap;
-
- Inkscape::SnappedPoint result = no_snap;
-
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- bool snap_mouse = prefs->getBool("/options/snapmousepointer/value", false);
+ // We haven't tried to snap yet; we will first determine which constraint is closest to where we are now,
+ // i.e. lets find out which of the constraints yields the closest projection of point p
+ // Project the mouse pointer on each of the constraints
+ std::vector<Geom::Point> projections;
for (std::vector<Inkscape::Snapper::SnapConstraint>::const_iterator c = constraints.begin(); c != constraints.end(); ++c) {
// Project the mouse pointer onto the constraint; In case we don't snap then we will
// return the projection onto the constraint, such that the constraint is always enforced
@@ -310,55 +305,47 @@ Inkscape::SnappedPoint SnapManager::multipleConstrainedSnaps(Inkscape::SnapCandi
projections.push_back(pp);
}
- if (snap_mouse && p.isSingleHandle() && !dont_snap) {
+ // Select the closest constraint
+ no_snap.setPoint(projections.front());
+ Inkscape::Snapper::SnapConstraint cc = constraints.front(); //closest constraint
+
+ std::vector<Inkscape::Snapper::SnapConstraint>::const_iterator c = constraints.begin();
+ std::vector<Geom::Point>::iterator pp = projections.begin();
+ for (; pp != projections.end(); ++pp) {
+ if (Geom::L2(*pp - p.getPoint()) < Geom::L2(no_snap.getPoint() - p.getPoint())) {
+ no_snap.setPoint(*pp); // Remember the projection onto the closest constraint
+ cc = *c; // Remember the closest constraint itself
+ }
+ ++c;
+ }
+
+ if (!someSnapperMightSnap() || dont_snap) {
+ return no_snap;
+ }
+
+ IntermSnapResults isr;
+ SnapperList const snappers = getSnappers();
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ bool snap_mouse = prefs->getBool("/options/snapmousepointer/value", false);
+
+ Inkscape::SnappedPoint result = no_snap;
+ if (snap_mouse && p.isSingleHandle()) {
// Snapping the mouse pointer instead of the constrained position of the knot allows
// to snap to things which don't intersect with the constraint line; this is basically
// then just a freesnap with the constraint applied afterwards
// We'll only to this if we're dragging a single handle, and for example not when transforming an object in the selector tool
result = freeSnap(p, bbox_to_snap);
+ // Now apply the constraint afterwards
+ result.setPoint(cc.projection(result.getPoint()));
} else {
- // Iterate over the constraints
- for (std::vector<Inkscape::Snapper::SnapConstraint>::const_iterator c = constraints.begin(); c != constraints.end(); ++c) {
- // Try to snap to the constraint
- if (!snapping_is_futile) {
- for (SnapperList::const_iterator i = snappers.begin(); i != snappers.end(); ++i) {
- (*i)->constrainedSnap(isr, p, bbox_to_snap, *c, &_items_to_ignore,_unselected_nodes);
- }
- }
+ // Try to snap along the closest constraint
+ for (SnapperList::const_iterator i = snappers.begin(); i != snappers.end(); ++i) {
+ (*i)->constrainedSnap(isr, p, bbox_to_snap, cc, &_items_to_ignore,_unselected_nodes);
}
result = findBestSnap(p, isr, true);
}
- if (result.getSnapped()) {
- if (snap_mouse) {
- // If "snap_mouse" then we still have to apply the constraint, because so far we only tried a freeSnap
- Geom::Point result_closest;
- for (std::vector<Inkscape::Snapper::SnapConstraint>::const_iterator c = constraints.begin(); c != constraints.end(); ++c) {
- // Project the mouse pointer onto the constraint; In case we don't snap then we will
- // return the projection onto the constraint, such that the constraint is always enforced
- Geom::Point result_p = (*c).projection(result.getPoint());
- if (c == constraints.begin() || (Geom::L2(result_p - p.getPoint()) < Geom::L2(result_closest - p.getPoint()))) {
- result_closest = result_p;
- }
- }
- result.setPoint(result_closest);
- }
- return result;
- }
-
- // So we didn't snap, but we still need to return a point on one of the constraints
- // Find out which of the constraints yielded the closest projection of point p
- for (std::vector<Geom::Point>::iterator pp = projections.begin(); pp != projections.end(); ++pp) {
- if (pp != projections.begin()) {
- if (Geom::L2(*pp - p.getPoint()) < Geom::L2(no_snap.getPoint() - p.getPoint())) {
- no_snap.setPoint(*pp);
- }
- } else {
- no_snap.setPoint(projections.front());
- }
- }
-
- return no_snap;
+ return result.getSnapped() ? result : no_snap;
}
Inkscape::SnappedPoint SnapManager::constrainedAngularSnap(Inkscape::SnapCandidatePoint const &p,
@@ -443,7 +430,7 @@ void SnapManager::guideConstrainedSnap(Geom::Point &p, SPGuide const &guideline)
Inkscape::SnapCandidatePoint candidate(p, Inkscape::SNAPSOURCE_GUIDE_ORIGIN, Inkscape::SNAPTARGET_UNDEFINED);
IntermSnapResults isr;
- Inkscape::Snapper::SnapConstraint cl(guideline.point_on_line, Geom::rot90(guideline.normal_to_line));
+ Inkscape::Snapper::SnapConstraint cl(guideline.getPoint(), Geom::rot90(guideline.getNormal()));
SnapperList snappers = getSnappers();
for (SnapperList::const_iterator i = snappers.begin(); i != snappers.end(); ++i) {
@@ -570,7 +557,7 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed(
// be collected. Therefore we enforce that the first SnapCandidatePoint that is to be freeSnapped always
// has source_num == 0;
// TODO: This is a bit ugly so fix this; do we need sourcenum for anything else? if we don't then get rid
- // of it and explicitely communicate to the object snapper that this is a first point
+ // of it and explicitly communicate to the object snapper that this is a first point
if (first_free_snap) {
(*j).setSourceNum(0);
first_free_snap = false;
@@ -616,8 +603,8 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed(
// and the scaling factor for the other direction should remain
// untouched (unless scaling is uniform of course)
for (int index = 0; index < 2; index++) {
- if (fabs(b[index]) > 1e-6) { // if SCALING CAN occur in this direction
- if (fabs(fabs(a[index]/b[index]) - fabs(transformation[index])) > 1e-12) { // if SNAPPING DID occur in this direction
+ if (fabs(b[index]) > 1e-4) { // if SCALING CAN occur in this direction
+ if (fabs(fabs(a[index]/b[index]) - fabs(transformation[index])) > 1e-7) { // if SNAPPING DID occur in this direction
result[index] = a[index] / b[index]; // then calculate it!
}
// we might have left result[1-index] = Geom::infinity()
@@ -669,7 +656,7 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed(
case ROTATE:
// a is vector to snapped point; b is vector to original point; now lets calculate angle between a and b
result[0] = atan2(Geom::dot(Geom::rot90(b), a), Geom::dot(b, a));
- result[1] = result[1]; // how else should we store an angle in a point ;-)
+ result[1] = result[0]; // dummy value; how else should we store an angle in a point ;-)
if (Geom::L2(b) < 1e-9) { // points too close to the rotation center will not move. Don't try to snap these
// as they will always yield a perfect snap result if they're already snapped beforehand (e.g.
// when the transformation center has been snapped to a grid intersection in the selector tool)
diff --git a/src/snap.h b/src/snap.h
index 67af20063..20b2b246f 100644
--- a/src/snap.h
+++ b/src/snap.h
@@ -32,6 +32,7 @@ enum SPGuideDragType { // used both here and in desktop-events.cpp
class SPGuide;
class SPNamedView;
+typedef struct _GSList GSList;
/**
* Class to coordinate snapping operations.
diff --git a/src/snapped-curve.h b/src/snapped-curve.h
index 6bb8bfeca..0e3a1c747 100644
--- a/src/snapped-curve.h
+++ b/src/snapped-curve.h
@@ -11,14 +11,14 @@
* Released under GNU GPL, read the file 'COPYING' for more information.
*/
+#include <2geom/forward.h>
#include <vector>
#include <list>
+
#include "snapped-point.h"
#include "snapped-line.h"
-#include <2geom/forward.h>
-namespace Inkscape
-{
+namespace Inkscape {
/// Class describing the result of an attempt to snap to a curve.
class SnappedCurve : public SnappedPoint
diff --git a/src/snapped-point.h b/src/snapped-point.h
index bf440c450..9d77ab162 100644
--- a/src/snapped-point.h
+++ b/src/snapped-point.h
@@ -12,10 +12,11 @@
* Released under GNU GPL, read the file 'COPYING' for more information.
*/
-#include <vector>
-#include <list>
#include <2geom/geom.h>
-#include <snap-candidate.h>
+#include <list>
+#include <vector>
+
+#include "snap-candidate.h"
namespace Inkscape
{
diff --git a/src/snapper.h b/src/snapper.h
index c609239cf..9616d0954 100644
--- a/src/snapper.h
+++ b/src/snapper.h
@@ -12,15 +12,14 @@
* Released under GNU GPL, read the file 'COPYING' for more information.
*/
-#include <map>
-#include <list>
#include <boost/optional.hpp>
-#include <glib.h> // for g_assert
+#include <cstdio>
+#include <list>
+#include "snap-candidate.h"
#include "snapped-point.h"
#include "snapped-line.h"
#include "snapped-curve.h"
-#include "snap-candidate.h"
struct IntermSnapResults {
std::list<Inkscape::SnappedPoint> points;
@@ -86,7 +85,7 @@ public:
bool hasPoint() const {return _type != DIRECTION && _type != UNDEFINED;}
Geom::Point getPoint() const {
- g_assert(_type != DIRECTION && _type != UNDEFINED);
+ assert(_type != DIRECTION && _type != UNDEFINED);
return _point;
}
@@ -95,7 +94,7 @@ public:
}
Geom::Coord getRadius() const {
- g_assert(_type == CIRCLE);
+ assert(_type == CIRCLE);
return _radius;
}
@@ -121,7 +120,7 @@ public:
Geom::Point const p2_on_cl = p1_on_cl + _direction;
return Geom::projection(p, Geom::Line(p1_on_cl, p2_on_cl));
} else {
- g_warning("Bug: trying to find the projection onto an undefined constraint");
+ printf("WARNING: Bug: trying to find the projection onto an undefined constraint");
return Geom::Point();
}
}
diff --git a/src/sp-anchor.h b/src/sp-anchor.h
index 778640032..d17718344 100644
--- a/src/sp-anchor.h
+++ b/src/sp-anchor.h
@@ -1,5 +1,5 @@
-#ifndef __SP_ANCHOR_H__
-#define __SP_ANCHOR_H__
+#ifndef SEEN_SP_ANCHOR_H
+#define SEEN_SP_ANCHOR_H
/*
* SVG <a> element implementation
@@ -23,16 +23,16 @@ public:
SPAnchor();
virtual ~SPAnchor();
- gchar *href;
+ char *href;
virtual void build(SPDocument *document, Inkscape::XML::Node *repr);
virtual void release();
- virtual void set(unsigned int key, gchar const* value);
- virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags);
+ virtual void set(unsigned int key, char const* value);
+ virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags);
virtual const char* displayName() const;
- virtual gchar* description() const;
- virtual gint event(SPEvent *event);
+ virtual char* description() const;
+ virtual int event(SPEvent *event);
};
#endif
diff --git a/src/sp-clippath.h b/src/sp-clippath.h
index ba7a90a57..eb8b14174 100644
--- a/src/sp-clippath.h
+++ b/src/sp-clippath.h
@@ -19,6 +19,9 @@
#define SP_IS_CLIPPATH(obj) (dynamic_cast<const SPClipPath*>((SPObject*)obj) != NULL)
struct SPClipPathView;
+typedef struct _GSList GSList;
+
+#include <cstdio>
#include "sp-object-group.h"
#include "uri-references.h"
@@ -42,8 +45,8 @@ public:
unsigned int clipPathUnits : 1;
SPClipPathView *display;
- static const gchar *create(GSList *reprs, SPDocument *document, Geom::Affine const* applyTransform);
- static GType sp_clippath_get_type(void);
+ static char const *create(GSList *reprs, SPDocument *document, Geom::Affine const* applyTransform);
+ //static GType sp_clippath_get_type(void);
Inkscape::DrawingItem *show(Inkscape::Drawing &drawing, unsigned int key);
void hide(unsigned int key);
@@ -57,12 +60,12 @@ protected:
virtual void child_added(Inkscape::XML::Node* child, Inkscape::XML::Node* ref);
- virtual void set(unsigned int key, const gchar* value);
+ virtual void set(unsigned int key, char const* value);
virtual void update(SPCtx* ctx, unsigned int flags);
virtual void modified(unsigned int flags);
- virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, guint flags);
+ virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, unsigned int flags);
};
@@ -90,10 +93,10 @@ protected:
Inkscape::XML::Node * const owner_repr = owner->getRepr();
//XML Tree being used directly here while it shouldn't be...
Inkscape::XML::Node * const obj_repr = obj->getRepr();
- gchar const * owner_name = NULL;
- gchar const * owner_clippath = NULL;
- gchar const * obj_name = NULL;
- gchar const * obj_id = NULL;
+ char const * owner_name = NULL;
+ char const * owner_clippath = NULL;
+ char const * obj_name = NULL;
+ char const * obj_id = NULL;
if (owner_repr != NULL) {
owner_name = owner_repr->name();
owner_clippath = owner_repr->attribute("clippath");
@@ -102,7 +105,7 @@ protected:
obj_name = obj_repr->name();
obj_id = obj_repr->attribute("id");
}
- g_warning("Ignoring recursive clippath reference "
+ printf("WARNING: Ignoring recursive clippath reference "
"<%s clippath=\"%s\"> in <%s id=\"%s\">",
owner_name, owner_clippath,
obj_name, obj_id);
diff --git a/src/sp-conn-end-pair.h b/src/sp-conn-end-pair.h
index 9f7f5a5d2..93f54378c 100644
--- a/src/sp-conn-end-pair.h
+++ b/src/sp-conn-end-pair.h
@@ -11,12 +11,10 @@
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include <glib.h>
-#include <stddef.h>
-#include <sigc++/connection.h>
-#include <sigc++/functors/slot.h>
-#include <sigc++/signal.h>
+#include <cstddef>
+#include <sigc++/sigc++.h>
+
#include "libavoid/connector.h"
@@ -33,21 +31,21 @@ class Node;
}
}
-extern void recreateCurve(SPCurve *curve, Avoid::ConnRef *connRef, gdouble curvature);
+extern void recreateCurve(SPCurve *curve, Avoid::ConnRef *connRef, double curvature);
class SPConnEndPair {
public:
SPConnEndPair(SPPath *);
~SPConnEndPair();
void release();
- void setAttr(unsigned const key, gchar const *const value);
+ void setAttr(unsigned const key, char const *const value);
void writeRepr(Inkscape::XML::Node *const repr) const;
void getAttachedItems(SPItem *[2]) const;
void getEndpoints(Geom::Point endPts[]) const;
- gdouble getCurvature(void) const;
+ double getCurvature(void) const;
SPConnEnd** getConnEnds(void);
bool isOrthogonal(void) const;
- friend void recreateCurve(SPCurve *curve, Avoid::ConnRef *connRef, gdouble curvature);
+ friend void recreateCurve(SPCurve *curve, Avoid::ConnRef *connRef, double curvature);
void tellLibavoidNewEndpoints(const bool processTransaction = false);
bool reroutePathFromLibavoid(void);
void makePathInvalid(void);
@@ -64,7 +62,7 @@ private:
Avoid::ConnRef *_connRef;
int _connType;
- gdouble _connCurvature;
+ double _connCurvature;
// A sigc connection for transformed signal.
sigc::connection _transformed_connection;
diff --git a/src/sp-conn-end.h b/src/sp-conn-end.h
index a0b1ba5df..2b89a159d 100644
--- a/src/sp-conn-end.h
+++ b/src/sp-conn-end.h
@@ -1,8 +1,7 @@
#ifndef SEEN_SP_CONN_END
#define SEEN_SP_CONN_END
-#include <glib.h>
-#include <stddef.h>
+#include <cstddef>
#include <sigc++/connection.h>
#include "sp-use-reference.h"
@@ -15,7 +14,7 @@ public:
SPConnEnd(SPObject *owner);
SPUseReference ref;
- gchar *href;
+ char *href;
/** Change of href string (not a modification of the attributes of the referrent). */
sigc::connection _changed_connection;
@@ -29,13 +28,13 @@ public:
/** A sigc connection for owning group transformed, used to do move compensation. */
sigc::connection _group_connection;
- void setAttacherHref(gchar const *, SPPath *);
- void setAttacherEndpoint(gchar const *, SPPath *);
+ void setAttacherHref(char const * value, SPPath * unused);
+ //void setAttacherEndpoint(char const *, SPPath *); // not defined
private:
- SPConnEnd(SPConnEnd const &);
- SPConnEnd &operator=(SPConnEnd const &);
+ SPConnEnd(SPConnEnd const &); // no copy
+ SPConnEnd &operator=(SPConnEnd const &); // no assign
};
void sp_conn_end_href_changed(SPObject *old_ref, SPObject *ref,
diff --git a/src/sp-cursor.cpp b/src/sp-cursor.cpp
index ea73da00c..16659d1cf 100644
--- a/src/sp-cursor.cpp
+++ b/src/sp-cursor.cpp
@@ -17,13 +17,14 @@
*/
#include <cstring>
+#include <gdk/gdk.h>
#include <map>
#include <sstream>
#include "color.h"
#include "sp-cursor.h"
-static void free_cursor_data(guchar *pixels, gpointer /*data*/) {
+static void free_cursor_data(unsigned char *pixels, void* /*data*/) {
delete [] reinterpret_cast<guint32*>(pixels);
}
@@ -53,7 +54,7 @@ struct RGBA {
}
};
-GdkPixbuf *sp_cursor_pixbuf_from_xpm(gchar const *const *xpm, GdkColor const& black, GdkColor const& white, guint32 fill, guint32 stroke)
+GdkPixbuf *sp_cursor_pixbuf_from_xpm(char const *const *xpm, GdkColor const& black, GdkColor const& white, guint32 fill, guint32 stroke)
{
int height = 0;
int width = 0;
@@ -72,7 +73,7 @@ GdkPixbuf *sp_cursor_pixbuf_from_xpm(gchar const *const *xpm, GdkColor const& bl
char const *p = xpm[1 + i];
g_assert(*p >=0);
- guchar const ccode = (guchar) *p;
+ unsigned char const ccode = (guchar) *p;
p++;
while (isspace(*p)) {
@@ -110,7 +111,7 @@ GdkPixbuf *sp_cursor_pixbuf_from_xpm(gchar const *const *xpm, GdkColor const& bl
return gdk_pixbuf_new_from_data(reinterpret_cast<guchar*>(pixmap_buffer), GDK_COLORSPACE_RGB, TRUE, 8, width, height, width * sizeof(guint32), free_cursor_data, NULL);
}
-GdkCursor *sp_cursor_new_from_xpm(gchar const *const *xpm, gint hot_x, gint hot_y)
+GdkCursor *sp_cursor_new_from_xpm(char const *const *xpm, int hot_x, int hot_y)
{
GdkCursor *cursor = 0;
GdkPixbuf *pixbuf = gdk_pixbuf_new_from_xpm_data((const gchar **)xpm);
diff --git a/src/sp-cursor.h b/src/sp-cursor.h
index f445127ad..c0b8b46a3 100644
--- a/src/sp-cursor.h
+++ b/src/sp-cursor.h
@@ -1,10 +1,13 @@
#ifndef SP_CURSOR_H
#define SP_CURSOR_H
-#include <gdk/gdk.h>
+typedef unsigned int guint32;
+typedef struct _GdkPixbuf GdkPixbuf;
+typedef struct _GdkCursor GdkCursor;
+typedef struct _GdkColor GdkColor;
-GdkPixbuf* sp_cursor_pixbuf_from_xpm(gchar const *const *xpm, GdkColor const& black, GdkColor const& white, guint32 fill, guint32 stroke);
-GdkCursor *sp_cursor_new_from_xpm(gchar const *const *xpm, gint hot_x, gint hot_y);
+GdkPixbuf* sp_cursor_pixbuf_from_xpm(char const *const *xpm, GdkColor const& black, GdkColor const& white, guint32 fill, guint32 stroke);
+GdkCursor *sp_cursor_new_from_xpm(char const *const *xpm, int hot_x, int hot_y);
#endif
diff --git a/src/sp-defs.h b/src/sp-defs.h
index 6efdea1f3..c122cb2a9 100644
--- a/src/sp-defs.h
+++ b/src/sp-defs.h
@@ -27,7 +27,7 @@ protected:
virtual void release();
virtual void update(SPCtx* ctx, unsigned int flags);
virtual void modified(unsigned int flags);
- virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags);
+ virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags);
};
#endif // !SEEN_SP_DEFS_H
diff --git a/src/sp-desc.h b/src/sp-desc.h
index 2bb42b333..40888bee4 100644
--- a/src/sp-desc.h
+++ b/src/sp-desc.h
@@ -1,5 +1,5 @@
-#ifndef __SP_DESC_H__
-#define __SP_DESC_H__
+#ifndef SEEN_SP_DESC_H
+#define SEEN_SP_DESC_H
/*
* SVG <desc> implementation
@@ -23,7 +23,7 @@ public:
virtual ~SPDesc();
protected:
- virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, guint flags);
+ virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, unsigned int flags);
};
#endif
diff --git a/src/sp-ellipse.cpp b/src/sp-ellipse.cpp
index 25e4c07d7..a74d4687d 100644
--- a/src/sp-ellipse.cpp
+++ b/src/sp-ellipse.cpp
@@ -14,26 +14,25 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include "svg/svg.h"
-#include "svg/path-string.h"
-#include "xml/repr.h"
-#include "attributes.h"
-#include "style.h"
-#include "display/curve.h"
+#include <glibmm.h>
#include <glibmm/i18n.h>
+
#include <2geom/angle.h>
#include <2geom/ellipse.h>
-#include <2geom/transforms.h>
-#include <2geom/pathvector.h>
#include <2geom/path-sink.h>
+#include <2geom/pathvector.h>
+#include <2geom/transforms.h>
+
+#include "attributes.h"
+#include "display/curve.h"
#include "document.h"
-#include "sp-ellipse.h"
#include "preferences.h"
#include "snap-candidate.h"
+#include "sp-ellipse.h"
+#include "style.h"
+#include "svg/svg.h"
+#include "svg/path-string.h"
+#include "xml/repr.h"
#include "sp-factory.h"
@@ -42,21 +41,21 @@ SPObject *create_ellipse()
{
SPGenericEllipse *ellipse = new SPGenericEllipse();
ellipse->type = SP_GENERIC_ELLIPSE_ELLIPSE;
- return (SPObject*)ellipse;
+ return ellipse;
}
SPObject *create_circle()
{
SPGenericEllipse *circle = new SPGenericEllipse();
circle->type = SP_GENERIC_ELLIPSE_CIRCLE;
- return (SPObject*)circle;
+ return circle;
}
SPObject *create_arc()
{
SPGenericEllipse *arc = new SPGenericEllipse();
arc->type = SP_GENERIC_ELLIPSE_ARC;
- return (SPObject*)arc;
+ return arc;
}
bool ellipse_registered = SPFactory::instance().registerObject("svg:ellipse", create_ellipse);
@@ -419,62 +418,35 @@ void SPGenericEllipse::set_shape()
// For simplicity, we use a circle with center (0, 0) and radius 1 for our calculations.
Geom::Circle circle(0, 0, 1);
- if (this->_isSlice()) {
- Geom::Point center(0, 0);
- Geom::Point start_point = Geom::Point::polar(start);
- Geom::Point end_point = Geom::Point::polar(end);
- Geom::Point middle_point = make_angle_bisector_ray(Geom::Ray(center, start), Geom::Ray(center, end)).versor();
-
- Geom::EllipticalArc *arc = circle.arc(start_point, middle_point, end_point);
-
- Geom::Path path(start_point);
- path.append(*arc);
-
- delete arc;
-
- Geom::PathBuilder pb;
- pb.append(path);
-
- if (this->_closed) {
- // "pizza slice"
- pb.lineTo(center);
- pb.closePath();
- } else {
- // arc only
- pb.flush();
- }
-
- curve = new SPCurve(pb.peek());
- } else {
- // Full ellipse
- // This code converts the circle to four elliptical arcs explicitly.
- // Circle::getPath currently creates cubic bezier curves, these are not suitable here
- // as a circle should have four mid markers at 0, 90, 180, 270 degrees.
- Geom::Path path(Geom::Point::polar(0));
- Geom::EllipticalArc* arc;
-
- arc = circle.arc(Geom::Point::polar(0), Geom::Point::polar(M_PI / 4.0), Geom::Point::polar(M_PI / 2.0));
- path.append(*arc);
- delete arc;
-
- arc = circle.arc(Geom::Point::polar(M_PI / 2.0), Geom::Point::polar(3.0 * M_PI / 4.0), Geom::Point::polar(M_PI));
- path.append(*arc);
- delete arc;
+ if (!this->_isSlice()) {
+ start = 0.0;
+ end = 2.0*M_PI;
+ }
+ double incr = end - start; // arc angle
+ if (incr < 0.0) incr += 2.0*M_PI;
- arc = circle.arc(Geom::Point::polar(M_PI), Geom::Point::polar(5.0 * M_PI / 4.0), Geom::Point::polar(3.0 * M_PI / 2.0));
- path.append(*arc);
- delete arc;
+ int numsegs = 1 + int(incr*2.0/M_PI); // number of arc segments
+ if (numsegs > 4) numsegs = 4;
- arc = circle.arc(Geom::Point::polar(3.0 * M_PI / 2.0), Geom::Point::polar(7.0 * M_PI / 4.0), Geom::Point::polar(2.0 * M_PI));
+ incr = incr/numsegs; // limit arc angle to less than 90 degrees
+ Geom::Path path(Geom::Point::polar(start));
+ Geom::EllipticalArc* arc;
+ for (int seg = 0; seg < numsegs; seg++) {
+ arc = circle.arc(Geom::Point::polar(start + seg*incr), Geom::Point::polar(start + (seg + 0.5)*incr), Geom::Point::polar(start + (seg + 1.0)*incr));
path.append(*arc);
delete arc;
-
- Geom::PathBuilder pb;
- pb.append(path);
+ }
+ Geom::PathBuilder pb;
+ pb.append(path);
+ if (this->_isSlice() && this->_closed) {
+ pb.lineTo(Geom::Point(0, 0));
+ }
+ if (this->_closed) {
pb.closePath();
-
- curve = new SPCurve(pb.peek());
+ } else {
+ pb.flush();
}
+ curve = new SPCurve(pb.peek());
// gchar *str = sp_svg_write_path(curve->get_pathvector());
// std::cout << " path: " << str << std::endl;
@@ -632,7 +604,7 @@ void SPGenericEllipse::update_patheffect(bool write)
if (write) {
Inkscape::XML::Node *repr = this->getRepr();
- if (this->_curve != NULL) {
+ if (this->_curve != NULL && type == SP_GENERIC_ELLIPSE_ARC) {
gchar *str = sp_svg_write_path(this->_curve->get_pathvector());
repr->setAttribute("d", str);
g_free(str);
@@ -670,8 +642,8 @@ bool SPGenericEllipse::set_elliptical_path_attribute(Inkscape::XML::Node *repr)
// Make sure our pathvector is up to date.
this->set_shape();
- if (this->getCurve() != NULL) {
- gchar* d = sp_svg_write_path(this->getCurve()->get_pathvector());
+ if (_curve != NULL) {
+ gchar* d = sp_svg_write_path(_curve->get_pathvector());
repr->setAttribute("d", d);
@@ -722,4 +694,4 @@ bool SPGenericEllipse::_isSlice() const
fill-column:99
End:
*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8 :
diff --git a/src/sp-ellipse.h b/src/sp-ellipse.h
index cb988b8bb..09768fd6d 100644
--- a/src/sp-ellipse.h
+++ b/src/sp-ellipse.h
@@ -1,7 +1,4 @@
-#ifndef __SP_ELLIPSE_H__
-#define __SP_ELLIPSE_H__
-
-/*
+/**
* SVG <ellipse> and related implementations
*
* Authors:
@@ -16,15 +13,18 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
+#ifndef SEEN_SP_ELLIPSE_H
+#define SEEN_SP_ELLIPSE_H
+
#include "svg/svg-length.h"
#include "sp-shape.h"
/* Common parent class */
-#define SP_GENERICELLIPSE(obj) (dynamic_cast<SPGenericEllipse*>((SPObject*)obj))
-#define SP_IS_GENERICELLIPSE(obj) (dynamic_cast<const SPGenericEllipse*>((SPObject*)obj) != NULL)
+#define SP_GENERICELLIPSE(obj) (dynamic_cast<SPGenericEllipse*>(obj))
+#define SP_IS_GENERICELLIPSE(obj) (dynamic_cast<const SPGenericEllipse*>((obj)) != NULL)
enum GenericEllipseType {
- SP_GENERIC_ELLIPSE_UNDEFINED,
+ SP_GENERIC_ELLIPSE_UNDEFINED, // FIXME shouldn't exist
SP_GENERIC_ELLIPSE_ARC,
SP_GENERIC_ELLIPSE_CIRCLE,
SP_GENERIC_ELLIPSE_ELLIPSE
@@ -53,10 +53,10 @@ public:
virtual void build(SPDocument *document, Inkscape::XML::Node *repr);
- virtual void set(unsigned int key, gchar const *value);
+ virtual void set(unsigned int key, char const *value);
virtual void update(SPCtx *ctx, unsigned int flags);
- virtual Inkscape::XML::Node *write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags);
+ virtual Inkscape::XML::Node *write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags);
virtual const char *displayName() const;
virtual void set_shape();
@@ -76,7 +76,7 @@ public:
Geom::Point getPointAtAngle(double arg) const;
bool set_elliptical_path_attribute(Inkscape::XML::Node *repr);
- void position_set(gdouble x, gdouble y, gdouble rx, gdouble ry);
+ void position_set(double x, double y, double rx, double ry);
protected:
/**
@@ -98,4 +98,4 @@ protected:
fill-column:99
End:
*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8 :
diff --git a/src/sp-filter-primitive.cpp b/src/sp-filter-primitive.cpp
index ceb91c984..1f85c8193 100644
--- a/src/sp-filter-primitive.cpp
+++ b/src/sp-filter-primitive.cpp
@@ -19,14 +19,15 @@
#include <string.h>
+#include "display/nr-filter-primitive.h"
+#include "display/nr-filter-types.h"
+
#include "attributes.h"
#include "style.h"
#include "sp-filter-primitive.h"
#include "xml/repr.h"
#include "sp-filter.h"
#include "sp-item.h"
-#include "display/nr-filter-primitive.h"
-#include "display/nr-filter-types.h"
// CPPIFY: Make pure virtual.
diff --git a/src/sp-filter-primitive.h b/src/sp-filter-primitive.h
index 040e2f31f..d81adbd10 100644
--- a/src/sp-filter-primitive.h
+++ b/src/sp-filter-primitive.h
@@ -1,5 +1,5 @@
-#ifndef __SP_FILTER_PRIMITIVE_H__
-#define __SP_FILTER_PRIMITIVE_H__
+#ifndef SEEN_SP_FILTER_PRIMITIVE_H
+#define SEEN_SP_FILTER_PRIMITIVE_H
/** \file
* Document level base class for all SVG filter primitives.
@@ -40,11 +40,11 @@ protected:
virtual void build(SPDocument* doc, Inkscape::XML::Node* repr);
virtual void release();
- virtual void set(unsigned int key, const gchar* value);
+ virtual void set(unsigned int key, char const* value);
virtual void update(SPCtx* ctx, unsigned int flags);
- virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, guint flags);
+ virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, unsigned int flags);
public:
virtual void build_renderer(Inkscape::Filters::Filter* filter) = 0;
@@ -54,8 +54,8 @@ public:
void sp_filter_primitive_renderer_common(SPFilterPrimitive *sp_prim, Inkscape::Filters::FilterPrimitive *nr_prim);
int sp_filter_primitive_name_previous_out(SPFilterPrimitive *prim);
-int sp_filter_primitive_read_in(SPFilterPrimitive *prim, gchar const *name);
-int sp_filter_primitive_read_result(SPFilterPrimitive *prim, gchar const *name);
+int sp_filter_primitive_read_in(SPFilterPrimitive *prim, char const *name);
+int sp_filter_primitive_read_result(SPFilterPrimitive *prim, char const *name);
#endif
/*
diff --git a/src/sp-filter.cpp b/src/sp-filter.cpp
index e8319baca..9cb33a6f3 100644
--- a/src/sp-filter.cpp
+++ b/src/sp-filter.cpp
@@ -22,8 +22,9 @@
using std::map;
using std::pair;
-#include <glibmm/stringutils.h>
+#include <glibmm.h>
#include "attributes.h"
+#include "display/nr-filter.h"
#include "document.h"
#include "sp-filter.h"
#include "sp-filter-reference.h"
@@ -37,8 +38,6 @@ using std::pair;
#define SP_MACROS_SILENT
#include "macros.h"
-#include "display/nr-filter.h"
-
static void filter_ref_changed(SPObject *old_ref, SPObject *ref, SPFilter *filter);
static void filter_ref_modified(SPObject *href, guint flags, SPFilter *filter);
@@ -466,6 +465,10 @@ int sp_filter_set_image_name(SPFilter *filter, gchar const *name) {
pair<gchar*,int> new_pair(name_copy, value);
pair<map<gchar*,int,ltstr>::iterator,bool> ret = filter->_image_name->insert(new_pair);
if (ret.second == false) {
+ // The element is not inserted (because an element with the same key was already in the map)
+ // Therefore, free the memory allocated for the new entry:
+ free(name_copy);
+
return (*ret.first).second;
}
return value;
diff --git a/src/sp-filter.h b/src/sp-filter.h
index 0d087c5bf..e6318c569 100644
--- a/src/sp-filter.h
+++ b/src/sp-filter.h
@@ -12,6 +12,7 @@
#ifndef SP_FILTER_H_SEEN
#define SP_FILTER_H_SEEN
+#include <glibmm/ustring.h>
#include <map>
#include "number-opt-number.h"
@@ -19,8 +20,6 @@
#include "sp-filter-units.h"
#include "svg/svg-length.h"
-#include <glibmm/ustring.h>
-
#define SP_FILTER(obj) (dynamic_cast<SPFilter*>((SPObject*)obj))
#define SP_IS_FILTER(obj) (dynamic_cast<const SPFilter*>((SPObject*)obj) != NULL)
@@ -45,9 +44,9 @@ public:
virtual ~SPFilter();
SPFilterUnits filterUnits;
- guint filterUnits_set : 1;
+ unsigned int filterUnits_set : 1;
SPFilterUnits primitiveUnits;
- guint primitiveUnits_set : 1;
+ unsigned int primitiveUnits_set : 1;
SVGLength x;
SVGLength y;
SVGLength width;
@@ -68,11 +67,11 @@ protected:
virtual void child_added(Inkscape::XML::Node* child, Inkscape::XML::Node* ref);
virtual void remove_child(Inkscape::XML::Node* child);
- virtual void set(unsigned int key, const gchar* value);
+ virtual void set(unsigned int key, const char* value);
virtual void update(SPCtx* ctx, unsigned int flags);
- virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, guint flags);
+ virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, unsigned int flags);
};
void sp_filter_set_filter_units(SPFilter *filter, SPFilterUnits filterUnits);
@@ -88,14 +87,14 @@ void sp_filter_build_renderer(SPFilter *sp_filter, Inkscape::Filters::Filter *nr
int sp_filter_primitive_count(SPFilter *filter);
/// Returns a slot number for given image name, or -1 for unknown name.
-int sp_filter_get_image_name(SPFilter *filter, gchar const *name);
+int sp_filter_get_image_name(SPFilter *filter, char const *name);
/// Returns slot number for given image name, even if it's unknown.
-int sp_filter_set_image_name(SPFilter *filter, gchar const *name);
+int sp_filter_set_image_name(SPFilter *filter, char const *name);
/** Finds image name based on it's slot number. Returns 0 for unknown slot
* numbers. */
-gchar const *sp_filter_name_for_image(SPFilter const *filter, int const image);
+char const *sp_filter_name_for_image(SPFilter const *filter, int const image);
/// Returns a result image name that is not in use inside this filter.
Glib::ustring sp_filter_get_new_result_name(SPFilter *filter);
diff --git a/src/sp-flowdiv.h b/src/sp-flowdiv.h
index d00cfc51b..4a3690726 100644
--- a/src/sp-flowdiv.h
+++ b/src/sp-flowdiv.h
@@ -1,5 +1,5 @@
-#ifndef __SP_ITEM_FLOWDIV_H__
-#define __SP_ITEM_FLOWDIV_H__
+#ifndef SEEN_SP_ITEM_FLOWDIV_H
+#define SEEN_SP_ITEM_FLOWDIV_H
/*
*/
@@ -31,11 +31,11 @@ public:
protected:
virtual void build(SPDocument *document, Inkscape::XML::Node *repr);
virtual void release();
- virtual void update(SPCtx* ctx, guint flags);
+ virtual void update(SPCtx* ctx, unsigned int flags);
virtual void modified(unsigned int flags);
- virtual void set(unsigned int key, gchar const* value);
- virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags);
+ virtual void set(unsigned int key, char const* value);
+ virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags);
};
class SPFlowtspan : public SPItem {
@@ -46,11 +46,11 @@ public:
protected:
virtual void build(SPDocument *document, Inkscape::XML::Node *repr);
virtual void release();
- virtual void update(SPCtx* ctx, guint flags);
+ virtual void update(SPCtx* ctx, unsigned int flags);
virtual void modified(unsigned int flags);
- virtual void set(unsigned int key, gchar const* value);
- virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags);
+ virtual void set(unsigned int key, char const* value);
+ virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags);
};
class SPFlowpara : public SPItem {
@@ -61,11 +61,11 @@ public:
protected:
virtual void build(SPDocument *document, Inkscape::XML::Node *repr);
virtual void release();
- virtual void update(SPCtx* ctx, guint flags);
+ virtual void update(SPCtx* ctx, unsigned int flags);
virtual void modified(unsigned int flags);
- virtual void set(unsigned int key, gchar const* value);
- virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags);
+ virtual void set(unsigned int key, char const* value);
+ virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags);
};
// these do not need any style
@@ -78,7 +78,7 @@ protected:
virtual void release();
virtual void modified(unsigned int flags);
- virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags);
+ virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags);
};
class SPFlowregionbreak : public SPObject {
@@ -90,7 +90,7 @@ protected:
virtual void release();
virtual void modified(unsigned int flags);
- virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags);
+ virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags);
};
#endif
diff --git a/src/sp-flowregion.cpp b/src/sp-flowregion.cpp
index 709e9e464..580945d74 100644
--- a/src/sp-flowregion.cpp
+++ b/src/sp-flowregion.cpp
@@ -42,15 +42,12 @@ static void GetDest(SPObject* child,Shape **computed);
SPFlowregion::SPFlowregion() : SPItem() {
- //new (&this->computed) std::vector<Shape*>;
}
SPFlowregion::~SPFlowregion() {
for (std::vector<Shape*>::iterator it = this->computed.begin() ; it != this->computed.end() ; ++it) {
delete *it;
}
-
- //this->computed.~vector<Shape*>();
}
void SPFlowregion::child_added(Inkscape::XML::Node *child, Inkscape::XML::Node *ref) {
@@ -88,12 +85,14 @@ void SPFlowregion::update(SPCtx *ctx, unsigned int flags) {
l = g_slist_reverse(l);
while (l) {
- SPObject *child = SP_OBJECT(l->data);
+ SPObject *child = reinterpret_cast<SPObject *>(l->data);
+ g_assert(child != NULL);
l = g_slist_remove(l, child);
+ SPItem *item = dynamic_cast<SPItem *>(child);
if (childflags || (child->uflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) {
- if (SP_IS_ITEM (child)) {
- SPItem const &chi = *SP_ITEM(child);
+ if (item) {
+ SPItem const &chi = *item;
cctx.i2doc = chi.transform * ictx->i2doc;
cctx.i2vp = chi.transform * ictx->i2vp;
child->updateDisplay((SPCtx *)&cctx, childflags);
@@ -141,7 +140,8 @@ void SPFlowregion::modified(guint flags) {
l = g_slist_reverse(l);
while (l) {
- SPObject *child = SP_OBJECT(l->data);
+ SPObject *child = reinterpret_cast<SPObject *>(l->data);
+ g_assert(child != NULL);
l = g_slist_remove(l, child);
if (flags || (child->mflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) {
@@ -160,7 +160,7 @@ Inkscape::XML::Node *SPFlowregion::write(Inkscape::XML::Document *xml_doc, Inksc
GSList *l = NULL;
for ( SPObject *child = this->firstChild() ; child; child = child->getNext() ) {
- if ( !SP_IS_TITLE(child) && !SP_IS_DESC(child) ) {
+ if ( !dynamic_cast<SPTitle *>(child) && !dynamic_cast<SPDesc *>(child) ) {
Inkscape::XML::Node *crepr = child->updateRepr(xml_doc, NULL, flags);
if (crepr) {
@@ -177,7 +177,7 @@ Inkscape::XML::Node *SPFlowregion::write(Inkscape::XML::Document *xml_doc, Inksc
} else {
for ( SPObject *child = this->firstChild() ; child; child = child->getNext() ) {
- if ( !SP_IS_TITLE(child) && !SP_IS_DESC(child) ) {
+ if ( !dynamic_cast<SPTitle *>(child) && !dynamic_cast<SPDesc *>(child) ) {
child->updateRepr(flags);
}
}
@@ -185,6 +185,8 @@ Inkscape::XML::Node *SPFlowregion::write(Inkscape::XML::Document *xml_doc, Inksc
SPItem::write(xml_doc, repr, flags);
+ this->UpdateComputed(); // copied from update(), see LP Bug 1339305
+
return repr;
}
@@ -241,12 +243,14 @@ void SPFlowregionExclude::update(SPCtx *ctx, unsigned int flags) {
l = g_slist_reverse (l);
while (l) {
- SPObject *child = SP_OBJECT(l->data);
+ SPObject *child = reinterpret_cast<SPObject *>(l->data);
+ g_assert(child != NULL);
l = g_slist_remove(l, child);
if (flags || (child->uflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) {
- if (SP_IS_ITEM (child)) {
- SPItem const &chi = *SP_ITEM(child);
+ SPItem *item = dynamic_cast<SPItem *>(child);
+ if (item) {
+ SPItem const &chi = *item;
cctx.i2doc = chi.transform * ictx->i2doc;
cctx.i2vp = chi.transform * ictx->i2vp;
child->updateDisplay((SPCtx *)&cctx, flags);
@@ -291,7 +295,8 @@ void SPFlowregionExclude::modified(guint flags) {
l = g_slist_reverse (l);
while (l) {
- SPObject *child = SP_OBJECT(l->data);
+ SPObject *child = reinterpret_cast<SPObject *>(l->data);
+ g_assert(child != NULL);
l = g_slist_remove(l, child);
if (flags || (child->mflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) {
@@ -364,18 +369,28 @@ static void GetDest(SPObject* child,Shape **computed)
SPCurve *curve=NULL;
Geom::Affine tr_mat;
- SPObject* u_child=child;
- if ( SP_IS_USE(u_child) ) {
- u_child=SP_USE(u_child)->child;
- tr_mat = SP_ITEM(u_child)->getRelativeTransform(child->parent);
- } else {
- tr_mat = SP_ITEM(u_child)->transform;
- }
- if ( SP_IS_SHAPE (u_child) ) {
- curve = SP_SHAPE (u_child)->getCurve ();
- } else if ( SP_IS_TEXT (u_child) ) {
- curve = SP_TEXT (u_child)->getNormalizedBpath ();
- }
+ SPObject* u_child = child;
+ SPItem *item = dynamic_cast<SPItem *>(u_child);
+ g_assert(item != NULL);
+ SPUse *use = dynamic_cast<SPUse *>(item);
+ if ( use ) {
+ u_child = use->child;
+ tr_mat = use->getRelativeTransform(child->parent);
+ } else {
+ tr_mat = item->transform;
+ }
+ SPShape *shape = dynamic_cast<SPShape *>(u_child);
+ if ( shape ) {
+ if (!(shape->_curve)) {
+ shape->set_shape();
+ }
+ curve = shape->getCurve();
+ } else {
+ SPText *text = dynamic_cast<SPText *>(u_child);
+ if ( text ) {
+ curve = text->getNormalizedBpath();
+ }
+ }
if ( curve ) {
Path* temp=new Path;
diff --git a/src/sp-flowregion.h b/src/sp-flowregion.h
index 721eb0432..024a298b8 100644
--- a/src/sp-flowregion.h
+++ b/src/sp-flowregion.h
@@ -1,5 +1,5 @@
-#ifndef __SP_ITEM_FLOWREGION_H__
-#define __SP_ITEM_FLOWREGION_H__
+#ifndef SEEN_SP_ITEM_FLOWREGION_H
+#define SEEN_SP_ITEM_FLOWREGION_H
/*
*/
@@ -30,7 +30,7 @@ public:
virtual void remove_child(Inkscape::XML::Node *child);
virtual void update(SPCtx *ctx, unsigned int flags);
virtual void modified(guint flags);
- virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags);
+ virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags);
virtual const char* displayName() const;
};
@@ -47,7 +47,7 @@ public:
virtual void remove_child(Inkscape::XML::Node *child);
virtual void update(SPCtx *ctx, unsigned int flags);
virtual void modified(guint flags);
- virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags);
+ virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags);
virtual const char* displayName() const;
};
diff --git a/src/sp-flowtext.cpp b/src/sp-flowtext.cpp
index b4fd54ee4..766026980 100644
--- a/src/sp-flowtext.cpp
+++ b/src/sp-flowtext.cpp
@@ -46,11 +46,9 @@ namespace {
SPFlowtext::SPFlowtext() : SPItem() {
this->par_indent = 0;
- //new (&this->layout) Inkscape::Text::Layout();
}
SPFlowtext::~SPFlowtext() {
- //this->layout.~Layout();
}
void SPFlowtext::child_added(Inkscape::XML::Node* child, Inkscape::XML::Node* ref) {
@@ -88,12 +86,14 @@ void SPFlowtext::update(SPCtx* ctx, unsigned int flags) {
l = g_slist_reverse(l);
while (l) {
- SPObject *child = SP_OBJECT(l->data);
+ SPObject *child = reinterpret_cast<SPObject *>(l->data);
+ g_assert(child != NULL);
l = g_slist_remove(l, child);
if (childflags || (child->uflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) {
- if (SP_IS_ITEM(child)) {
- SPItem const &chi = *SP_ITEM(child);
+ SPItem *item = dynamic_cast<SPItem *>(child);
+ if (item) {
+ SPItem const &chi = *item;
cctx.i2doc = chi.transform * ictx->i2doc;
cctx.i2vp = chi.transform * ictx->i2vp;
child->updateDisplay((SPCtx *)&cctx, childflags);
@@ -131,19 +131,18 @@ void SPFlowtext::modified(unsigned int flags) {
// FIXME: the below stanza is copied over from sp_text_modified, consider factoring it out
if (flags & ( SP_OBJECT_STYLE_MODIFIED_FLAG )) {
- SPFlowtext *text = SP_FLOWTEXT(this);
- Geom::OptRect pbox = text->geometricBounds();
+ Geom::OptRect pbox = geometricBounds();
- for (SPItemView* v = text->display; v != NULL; v = v->next) {
+ for (SPItemView* v = display; v != NULL; v = v->next) {
Inkscape::DrawingGroup *g = dynamic_cast<Inkscape::DrawingGroup *>(v->arenaitem);
- text->_clearFlow(g);
- g->setStyle(this->style);
- text->layout.show(g, pbox);
+ _clearFlow(g);
+ g->setStyle(style);
+ layout.show(g, pbox);
}
}
for ( SPObject *o = this->firstChild() ; o ; o = o->getNext() ) {
- if (SP_IS_FLOWREGION(o)) {
+ if (dynamic_cast<SPFlowregion *>(o)) {
region = o;
break;
}
@@ -233,7 +232,7 @@ Inkscape::XML::Node* SPFlowtext::write(Inkscape::XML::Document* doc, Inkscape::X
for (SPObject *child = this->firstChild() ; child ; child = child->getNext() ) {
Inkscape::XML::Node *c_repr = NULL;
- if ( SP_IS_FLOWDIV(child) || SP_IS_FLOWPARA(child) || SP_IS_FLOWREGION(child) || SP_IS_FLOWREGIONEXCLUDE(child)) {
+ if ( dynamic_cast<SPFlowdiv *>(child) || dynamic_cast<SPFlowpara *>(child) || dynamic_cast<SPFlowregion *>(child) || dynamic_cast<SPFlowregionExclude *>(child)) {
c_repr = child->updateRepr(doc, NULL, flags);
}
@@ -249,12 +248,14 @@ Inkscape::XML::Node* SPFlowtext::write(Inkscape::XML::Document* doc, Inkscape::X
}
} else {
for (SPObject *child = this->firstChild() ; child ; child = child->getNext() ) {
- if ( SP_IS_FLOWDIV(child) || SP_IS_FLOWPARA(child) || SP_IS_FLOWREGION(child) || SP_IS_FLOWREGIONEXCLUDE(child) ) {
+ if ( dynamic_cast<SPFlowdiv *>(child) || dynamic_cast<SPFlowpara *>(child) || dynamic_cast<SPFlowregion *>(child) || dynamic_cast<SPFlowregionExclude *>(child)) {
child->updateRepr(flags);
}
}
}
+ this->rebuildLayout(); // copied from update(), see LP Bug 1339305
+
SPItem::write(doc, repr, flags);
return repr;
@@ -285,7 +286,7 @@ void SPFlowtext::print(SPPrintContext *ctx) {
}
const char* SPFlowtext::displayName() const {
- if (SP_FLOWTEXT(this)->has_internal_frame()) {
+ if (has_internal_frame()) {
return _("Flowed Text");
} else {
return _("Linked Flowed Text");
@@ -293,7 +294,6 @@ const char* SPFlowtext::displayName() const {
}
gchar* SPFlowtext::description() const {
- Inkscape::Text::Layout const &layout = SP_FLOWTEXT(this)->layout;
int const nChars = layout.iteratorToCharIndex(layout.end());
char const *trunc = (layout.inputTruncated()) ? _(" [truncated]") : "";
@@ -346,12 +346,17 @@ void SPFlowtext::_buildLayoutInput(SPObject *root, Shape const *exclusion_shape,
Inkscape::Text::Layout::OptionalTextTagAttrs pi;
bool with_indent = false;
- if (SP_IS_FLOWPARA(root)) {
+ if (dynamic_cast<SPFlowpara *>(root)) {
// emulate par-indent with the first char's kern
SPObject *t = root;
- for ( ; t != NULL && !SP_IS_FLOWTEXT(t); t = t->parent){};
- if (SP_IS_FLOWTEXT(t)) {
- double indent = SP_FLOWTEXT(t)->par_indent;
+ SPFlowtext *ft = NULL;
+ while (t && !ft) {
+ ft = dynamic_cast<SPFlowtext *>(t);
+ t = t->parent;
+ }
+
+ if (ft) {
+ double indent = ft->par_indent;
if (indent != 0) {
with_indent = true;
SVGLength sl;
@@ -363,7 +368,7 @@ void SPFlowtext::_buildLayoutInput(SPObject *root, Shape const *exclusion_shape,
}
if (*pending_line_break_object) {
- if (SP_IS_FLOWREGIONBREAK(*pending_line_break_object)) {
+ if (dynamic_cast<SPFlowregionbreak *>(*pending_line_break_object)) {
layout.appendControlCode(Inkscape::Text::Layout::SHAPE_BREAK, *pending_line_break_object);
} else {
layout.appendControlCode(Inkscape::Text::Layout::PARAGRAPH_BREAK, *pending_line_break_object);
@@ -372,9 +377,10 @@ void SPFlowtext::_buildLayoutInput(SPObject *root, Shape const *exclusion_shape,
}
for (SPObject *child = root->firstChild() ; child ; child = child->getNext() ) {
- if (SP_IS_STRING(child)) {
+ SPString *str = dynamic_cast<SPString *>(child);
+ if (str) {
if (*pending_line_break_object) {
- if (SP_IS_FLOWREGIONBREAK(*pending_line_break_object))
+ if (dynamic_cast<SPFlowregionbreak *>(*pending_line_break_object))
layout.appendControlCode(Inkscape::Text::Layout::SHAPE_BREAK, *pending_line_break_object);
else {
layout.appendControlCode(Inkscape::Text::Layout::PARAGRAPH_BREAK, *pending_line_break_object);
@@ -382,31 +388,35 @@ void SPFlowtext::_buildLayoutInput(SPObject *root, Shape const *exclusion_shape,
*pending_line_break_object = NULL;
}
if (with_indent) {
- layout.appendText(SP_STRING(child)->string, root->style, child, &pi);
+ layout.appendText(str->string, root->style, child, &pi);
} else {
- layout.appendText(SP_STRING(child)->string, root->style, child);
+ layout.appendText(str->string, root->style, child);
}
- } else if (SP_IS_FLOWREGION(child)) {
- std::vector<Shape*> const &computed = SP_FLOWREGION(child)->computed;
- for (std::vector<Shape*>::const_iterator it = computed.begin() ; it != computed.end() ; ++it) {
- shapes->push_back(Shape());
- if (exclusion_shape->hasEdges()) {
- shapes->back().Booleen(*it, const_cast<Shape*>(exclusion_shape), bool_op_diff);
- } else {
- shapes->back().Copy(*it);
+ } else {
+ SPFlowregion *region = dynamic_cast<SPFlowregion *>(child);
+ if (region) {
+ std::vector<Shape*> const &computed = region->computed;
+ for (std::vector<Shape*>::const_iterator it = computed.begin() ; it != computed.end() ; ++it) {
+ shapes->push_back(Shape());
+ if (exclusion_shape->hasEdges()) {
+ shapes->back().Booleen(*it, const_cast<Shape*>(exclusion_shape), bool_op_diff);
+ } else {
+ shapes->back().Copy(*it);
+ }
+ layout.appendWrapShape(&shapes->back());
}
- layout.appendWrapShape(&shapes->back());
}
- }
- //XML Tree is being directly used while it shouldn't be.
- else if (!SP_IS_FLOWREGIONEXCLUDE(child) && !sp_repr_is_meta_element(child->getRepr())) {
- _buildLayoutInput(child, exclusion_shape, shapes, pending_line_break_object);
+ //Xml Tree is being directly used while it shouldn't be.
+ else if (!dynamic_cast<SPFlowregionExclude *>(child) && !sp_repr_is_meta_element(child->getRepr())) {
+ _buildLayoutInput(child, exclusion_shape, shapes, pending_line_break_object);
+ }
}
}
- if (SP_IS_FLOWDIV(root) || SP_IS_FLOWPARA(root) || SP_IS_FLOWREGIONBREAK(root) || SP_IS_FLOWLINE(root)) {
- if (!root->hasChildren())
+ if (dynamic_cast<SPFlowdiv *>(root) || dynamic_cast<SPFlowpara *>(root) || dynamic_cast<SPFlowregionbreak *>(root) || dynamic_cast<SPFlowline *>(root)) {
+ if (!root->hasChildren()) {
layout.appendText("", root->style, root);
+ }
*pending_line_break_object = root;
}
}
@@ -418,16 +428,13 @@ Shape* SPFlowtext::_buildExclusionShape() const
for (SPObject *child = children ; child ; child = child->getNext() ) {
// RH: is it right that this shouldn't be recursive?
- if ( SP_IS_FLOWREGIONEXCLUDE(child) ) {
- SPFlowregionExclude *c_child = SP_FLOWREGIONEXCLUDE(child);
-
- if ( c_child->computed && c_child->computed->hasEdges() ) {
- if (shape->hasEdges()) {
- shape_temp->Booleen(shape, c_child->computed, bool_op_union);
- std::swap(shape, shape_temp);
- } else {
- shape->Copy(c_child->computed);
- }
+ SPFlowregionExclude *c_child = dynamic_cast<SPFlowregionExclude *>(child);
+ if ( c_child && c_child->computed && c_child->computed->hasEdges() ) {
+ if (shape->hasEdges()) {
+ shape_temp->Booleen(shape, c_child->computed, bool_op_union);
+ std::swap(shape, shape_temp);
+ } else {
+ shape->Copy(c_child->computed);
}
}
}
@@ -514,24 +521,23 @@ Inkscape::XML::Node *SPFlowtext::getAsText()
sp_repr_set_svg_double(line_tspan, "y", anchor_point[Geom::Y]);
}
- SPObject *source_obj = 0;
void *rawptr = 0;
Glib::ustring::iterator span_text_start_iter;
this->layout.getSourceOfCharacter(it, &rawptr, &span_text_start_iter);
- source_obj = SP_OBJECT (rawptr);
- gchar *style_text = sp_style_write_difference((SP_IS_STRING(source_obj) ? source_obj->parent : source_obj)->style, this->style);
+ SPObject *source_obj = reinterpret_cast<SPObject *>(rawptr);
+ gchar *style_text = sp_style_write_difference((dynamic_cast<SPString *>(source_obj) ? source_obj->parent : source_obj)->style, this->style);
if (style_text && *style_text) {
span_tspan->setAttribute("style", style_text);
g_free(style_text);
}
- if (SP_IS_STRING(source_obj)) {
- Glib::ustring *string = &SP_STRING(source_obj)->string;
- SPObject *span_end_obj = 0;
+ SPString *str = dynamic_cast<SPString *>(source_obj);
+ if (str) {
+ Glib::ustring *string = &(str->string); // TODO fixme: dangerous, unsafe premature-optimization
void *rawptr = 0;
Glib::ustring::iterator span_text_end_iter;
this->layout.getSourceOfCharacter(it_span_end, &rawptr, &span_text_end_iter);
- span_end_obj = SP_OBJECT(rawptr);
+ SPObject *span_end_obj = reinterpret_cast<SPObject *>(rawptr);
if (span_end_obj != source_obj) {
if (it_span_end == this->layout.end()) {
span_text_end_iter = span_text_start_iter;
@@ -562,13 +568,19 @@ Inkscape::XML::Node *SPFlowtext::getAsText()
return repr;
}
-SPItem *SPFlowtext::get_frame(SPItem *after)
+SPItem const *SPFlowtext::get_frame(SPItem const *after) const
+{
+ SPItem *item = const_cast<SPFlowtext *>(this)->get_frame(after);
+ return item;
+}
+
+SPItem *SPFlowtext::get_frame(SPItem const *after)
{
SPItem *frame = 0;
SPObject *region = 0;
for (SPObject *o = firstChild() ; o ; o = o->getNext() ) {
- if (SP_IS_FLOWREGION(o)) {
+ if (dynamic_cast<SPFlowregion *>(o)) {
region = o;
break;
}
@@ -578,29 +590,31 @@ SPItem *SPFlowtext::get_frame(SPItem *after)
bool past = false;
for (SPObject *o = region->firstChild() ; o ; o = o->getNext() ) {
- if (SP_IS_ITEM(o)) {
+ SPItem *item = dynamic_cast<SPItem *>(o);
+ if (item) {
if ( (after == NULL) || past ) {
- frame = SP_ITEM(o);
+ frame = item;
} else {
- if (SP_ITEM(o) == after) {
+ if (item == after) {
past = true;
}
}
}
}
- if ( frame && SP_IS_USE(frame) ) {
- frame = SP_USE(frame)->get_original();
+ SPUse *use = dynamic_cast<SPUse *>(frame);
+ if ( use ) {
+ frame = use->get_original();
}
}
return frame;
}
-bool SPFlowtext::has_internal_frame()
+bool SPFlowtext::has_internal_frame() const
{
- SPItem *frame = get_frame(NULL);
+ SPItem const *frame = get_frame(NULL);
- return (frame && this->isAncestorOf(frame) && SP_IS_RECT(frame));
+ return (frame && isAncestorOf(frame) && dynamic_cast<SPRect const *>(frame));
}
@@ -611,19 +625,21 @@ SPItem *create_flowtext_with_internal_frame (SPDesktop *desktop, Geom::Point p0,
Inkscape::XML::Document *xml_doc = doc->getReprDoc();
Inkscape::XML::Node *root_repr = xml_doc->createElement("svg:flowRoot");
root_repr->setAttribute("xml:space", "preserve"); // we preserve spaces in the text objects we create
- SPItem *ft_item = SP_ITEM(desktop->currentLayer()->appendChildRepr(root_repr));
+ SPItem *ft_item = dynamic_cast<SPItem *>(desktop->currentLayer()->appendChildRepr(root_repr));
+ g_assert(ft_item != NULL);
SPObject *root_object = doc->getObjectByRepr(root_repr);
- g_assert(SP_IS_FLOWTEXT(root_object));
+ g_assert(dynamic_cast<SPFlowtext *>(root_object) != NULL);
Inkscape::XML::Node *region_repr = xml_doc->createElement("svg:flowRegion");
root_repr->appendChild(region_repr);
SPObject *region_object = doc->getObjectByRepr(region_repr);
- g_assert(SP_IS_FLOWREGION(region_object));
+ g_assert(dynamic_cast<SPFlowregion *>(region_object) != NULL);
Inkscape::XML::Node *rect_repr = xml_doc->createElement("svg:rect"); // FIXME: use path!!! after rects are converted to use path
region_repr->appendChild(rect_repr);
- SPRect *rect = SP_RECT(doc->getObjectByRepr(rect_repr));
+ SPRect *rect = dynamic_cast<SPRect *>(doc->getObjectByRepr(rect_repr));
+ g_assert(rect != NULL);
p0 *= desktop->dt2doc();
p1 *= desktop->dt2doc();
@@ -642,7 +658,7 @@ SPItem *create_flowtext_with_internal_frame (SPDesktop *desktop, Geom::Point p0,
Inkscape::XML::Node *para_repr = xml_doc->createElement("svg:flowPara");
root_repr->appendChild(para_repr);
SPObject *para_object = doc->getObjectByRepr(para_repr);
- g_assert(SP_IS_FLOWPARA(para_object));
+ g_assert(dynamic_cast<SPFlowpara *>(para_object) != NULL);
Inkscape::XML::Node *text = xml_doc->createTextNode("");
para_repr->appendChild(text);
@@ -652,7 +668,10 @@ SPItem *create_flowtext_with_internal_frame (SPDesktop *desktop, Geom::Point p0,
Inkscape::GC::release(para_repr);
Inkscape::GC::release(rect_repr);
- ft_item->transform = SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse();
+
+ SPItem *item = dynamic_cast<SPItem *>(desktop->currentLayer());
+ g_assert(item != NULL);
+ ft_item->transform = item->i2doc_affine().inverse();
return ft_item;
}
@@ -673,6 +692,21 @@ Geom::Affine SPFlowtext::set_transform (Geom::Affine const &xform)
return xform;
}
+ SPObject *region = NULL;
+ for ( SPObject *o = this->firstChild() ; o ; o = o->getNext() ) {
+ if (dynamic_cast<SPFlowregion *>(o)) {
+ region = o;
+ break;
+ }
+ }
+ if (region) {
+ SPRect *rect = dynamic_cast<SPRect *>(region->firstChild());
+ if (rect) {
+ rect->set_i2d_affine(xform * rect->i2dt_affine());
+ rect->doWriteTransform(rect->getRepr(), rect->transform, NULL, true);
+ }
+ }
+
Geom::Affine ret(xform);
ret[0] /= ex;
ret[1] /= ex;
@@ -693,7 +727,7 @@ Geom::Affine SPFlowtext::set_transform (Geom::Affine const &xform)
this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_TEXT_LAYOUT_MODIFIED_FLAG);
- return ret;
+ return Geom::Affine();
}
/*
diff --git a/src/sp-flowtext.h b/src/sp-flowtext.h
index a5b7db22e..9e6046469 100644
--- a/src/sp-flowtext.h
+++ b/src/sp-flowtext.h
@@ -4,10 +4,10 @@
/*
*/
-#include "sp-item.h"
-
#include <2geom/forward.h>
+
#include "libnrtype/Layout-TNG.h"
+#include "sp-item.h"
#define SP_FLOWTEXT(obj) (dynamic_cast<SPFlowtext*>((SPObject*)obj))
#define SP_IS_FLOWTEXT(obj) (dynamic_cast<const SPFlowtext*>((SPObject*)obj) != NULL)
@@ -31,9 +31,13 @@ public:
but losing the automatic wrapping ability. */
Inkscape::XML::Node *getAsText();
- SPItem *get_frame(SPItem *after);
+ // TODO check if these should return SPRect instead of SPItem
+
+ SPItem *get_frame(SPItem const *after);
+
+ SPItem const *get_frame(SPItem const *after) const;
- bool has_internal_frame();
+ bool has_internal_frame() const;
//semiprivate: (need to be accessed by the C-style functions still)
Inkscape::Text::Layout layout;
@@ -63,18 +67,18 @@ public:
virtual void child_added(Inkscape::XML::Node* child, Inkscape::XML::Node* ref);
virtual void remove_child(Inkscape::XML::Node* child);
- virtual void set(unsigned int key, const gchar* value);
+ virtual void set(unsigned int key, const char* value);
virtual Geom::Affine set_transform(Geom::Affine const& xform);
virtual void update(SPCtx* ctx, unsigned int flags);
virtual void modified(unsigned int flags);
- virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, guint flags);
+ virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, unsigned int flags);
virtual Geom::OptRect bbox(Geom::Affine const &transform, SPItem::BBoxType type) const;
virtual void print(SPPrintContext *ctx);
virtual const char* displayName() const;
- virtual gchar* description() const;
+ virtual char* description() const;
virtual Inkscape::DrawingItem* show(Inkscape::Drawing &drawing, unsigned int key, unsigned int flags);
virtual void hide(unsigned int key);
virtual void snappoints(std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs) const;
diff --git a/src/sp-font-face.h b/src/sp-font-face.h
index 531dd5843..669b93197 100644
--- a/src/sp-font-face.h
+++ b/src/sp-font-face.h
@@ -1,9 +1,5 @@
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#ifndef __SP_FONTFACE_H__
-#define __SP_FONTFACE_H__
+#ifndef SEEN_SP_FONTFACE_H
+#define SEEN_SP_FONTFACE_H
#include <vector>
@@ -117,11 +113,11 @@ protected:
virtual void child_added(Inkscape::XML::Node* child, Inkscape::XML::Node* ref);
virtual void remove_child(Inkscape::XML::Node* child);
- virtual void set(unsigned int key, const gchar* value);
+ virtual void set(unsigned int key, const char* value);
virtual void update(SPCtx* ctx, unsigned int flags);
- virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, guint flags);
+ virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, unsigned int flags);
};
#endif //#ifndef __SP_FONTFACE_H__
diff --git a/src/sp-font.h b/src/sp-font.h
index 6e6f4eec2..6e26a02b2 100644
--- a/src/sp-font.h
+++ b/src/sp-font.h
@@ -1,7 +1,3 @@
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
#ifndef SP_FONT_H_SEEN
#define SP_FONT_H_SEEN
@@ -40,11 +36,11 @@ protected:
virtual void child_added(Inkscape::XML::Node* child, Inkscape::XML::Node* ref);
virtual void remove_child(Inkscape::XML::Node* child);
- virtual void set(unsigned int key, const gchar* value);
+ virtual void set(unsigned int key, char const* value);
virtual void update(SPCtx* ctx, unsigned int flags);
- virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, guint flags);
+ virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, unsigned int flags);
};
#endif //#ifndef SP_FONT_H_SEEN
diff --git a/src/sp-glyph-kerning.cpp b/src/sp-glyph-kerning.cpp
index be47c7621..f33d3c509 100644
--- a/src/sp-glyph-kerning.cpp
+++ b/src/sp-glyph-kerning.cpp
@@ -1,18 +1,12 @@
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#define __SP_ANCHOR_C__
-
-/*
+/**
* SVG <hkern> and <vkern> elements implementation
* W3C SVG 1.1 spec, page 476, section 20.7
*
- * Author:
+ * Authors:
* Felipe C. da S. Sanches <juca@members.fsf.org>
* Abhishek Sharma
*
- * Copyright (C) 2008, Felipe C. da S. Sanches
+ * Copyright (C) 2008 Authors
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
@@ -26,45 +20,49 @@
#include <cstring>
-SPGlyphKerning::SPGlyphKerning() : SPObject() {
+SPGlyphKerning::SPGlyphKerning()
+ : SPObject()
//TODO: correct these values:
- this->u1 = NULL;
- this->g1 = NULL;
- this->u2 = NULL;
- this->g2 = NULL;
- this->k = 0;
-}
-
-SPGlyphKerning::~SPGlyphKerning() {
+ , u1(NULL)
+ , g1(NULL)
+ , u2(NULL)
+ , g2(NULL)
+ , k(0)
+{
}
-void SPGlyphKerning::build(SPDocument *document, Inkscape::XML::Node *repr) {
- SPObject::build(document, repr);
+void SPGlyphKerning::build(SPDocument *document, Inkscape::XML::Node *repr)
+{
+ SPObject::build(document, repr);
- this->readAttr( "u1" );
- this->readAttr( "g1" );
- this->readAttr( "u2" );
- this->readAttr( "g2" );
- this->readAttr( "k" );
+ this->readAttr( "u1" );
+ this->readAttr( "g1" );
+ this->readAttr( "u2" );
+ this->readAttr( "g2" );
+ this->readAttr( "k" );
}
-void SPGlyphKerning::release() {
- SPObject::release();
+void SPGlyphKerning::release()
+{
+ SPObject::release();
}
-GlyphNames::GlyphNames(const gchar* value){
+GlyphNames::GlyphNames(const gchar* value)
+{
if (value) {
- this->names = strdup(value);
+ names = g_strdup(value);
}
}
-GlyphNames::~GlyphNames(){
- if (this->names) {
- g_free(this->names);
+GlyphNames::~GlyphNames()
+{
+ if (names) {
+ g_free(names);
}
}
-bool GlyphNames::contains(const char* name){
+bool GlyphNames::contains(const char* name)
+{
if (!(this->names) || !name) {
return false;
}
@@ -75,14 +73,15 @@ bool GlyphNames::contains(const char* name){
while (is >> str) {
if (str == s) {
- return true;
+ return true;
}
}
return false;
}
-void SPGlyphKerning::set(unsigned int key, const gchar *value) {
+void SPGlyphKerning::set(unsigned int key, const gchar *value)
+{
switch (key) {
case SP_ATTR_U1:
{
@@ -143,15 +142,16 @@ void SPGlyphKerning::set(unsigned int key, const gchar *value) {
}
/**
- * * Receives update notifications.
- * */
-void SPGlyphKerning::update(SPCtx *ctx, guint flags) {
+ * Receives update notifications.
+ */
+void SPGlyphKerning::update(SPCtx *ctx, guint flags)
+{
if (flags & SP_OBJECT_MODIFIED_FLAG) {
/* do something to trigger redisplay, updates? */
- this->readAttr( "u1" );
- this->readAttr( "u2" );
- this->readAttr( "g2" );
- this->readAttr( "k" );
+ this->readAttr( "u1" );
+ this->readAttr( "u2" );
+ this->readAttr( "g2" );
+ this->readAttr( "k" );
}
SPObject::update(ctx, flags);
@@ -159,37 +159,26 @@ void SPGlyphKerning::update(SPCtx *ctx, guint flags) {
#define COPY_ATTR(rd,rs,key) (rd)->setAttribute((key), rs->attribute(key));
-Inkscape::XML::Node* SPGlyphKerning::write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags) {
- if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) {
- repr = xml_doc->createElement("svg:glyphkerning");//fix this!
- }
-
- /* I am commenting out this part because I am not certain how does it work. I will have to study it later. Juca
- repr->setAttribute("unicode", glyph->unicode);
- repr->setAttribute("glyph-name", glyph->glyph_name);
- repr->setAttribute("d", glyph->d);
- sp_repr_set_svg_double(repr, "orientation", (double) glyph->orientation);
- sp_repr_set_svg_double(repr, "arabic-form", (double) glyph->arabic_form);
- repr->setAttribute("lang", glyph->lang);
- sp_repr_set_svg_double(repr, "horiz-adv-x", glyph->horiz_adv_x);
- sp_repr_set_svg_double(repr, "vert-origin-x", glyph->vert_origin_x);
- sp_repr_set_svg_double(repr, "vert-origin-y", glyph->vert_origin_y);
- sp_repr_set_svg_double(repr, "vert-adv-y", glyph->vert_adv_y);
- */
- if (repr != this->getRepr()) {
- // All the COPY_ATTR functions below use
- // XML Tree directly, while they shouldn't.
- COPY_ATTR(repr, this->getRepr(), "u1");
- COPY_ATTR(repr, this->getRepr(), "g1");
- COPY_ATTR(repr, this->getRepr(), "u2");
- COPY_ATTR(repr, this->getRepr(), "g2");
- COPY_ATTR(repr, this->getRepr(), "k");
- }
-
- SPObject::write(xml_doc, repr, flags);
-
- return repr;
+Inkscape::XML::Node* SPGlyphKerning::write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags)
+{
+ if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) {
+ repr = xml_doc->createElement("svg:glyphkerning"); // fix this!
+ }
+
+ if (repr != this->getRepr()) {
+ // All the COPY_ATTR functions below use
+ // XML Tree directly, while they shouldn't.
+ COPY_ATTR(repr, this->getRepr(), "u1");
+ COPY_ATTR(repr, this->getRepr(), "g1");
+ COPY_ATTR(repr, this->getRepr(), "u2");
+ COPY_ATTR(repr, this->getRepr(), "g2");
+ COPY_ATTR(repr, this->getRepr(), "k");
+ }
+ SPObject::write(xml_doc, repr, flags);
+
+ return repr;
}
+
/*
Local Variables:
mode:c++
diff --git a/src/sp-glyph-kerning.h b/src/sp-glyph-kerning.h
index 5cae6b9dd..c96c0b6e4 100644
--- a/src/sp-glyph-kerning.h
+++ b/src/sp-glyph-kerning.h
@@ -1,10 +1,3 @@
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#ifndef __SP_GLYPH_KERNING_H__
-#define __SP_GLYPH_KERNING_H__
-
/*
* SVG <hkern> and <vkern> elements implementation
*
@@ -16,41 +9,35 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
+#ifndef SEEN_SP_GLYPH_KERNING_H
+#define SEEN_SP_GLYPH_KERNING_H
+
#include "sp-object.h"
#include "unicoderange.h"
-//#define SP_HKERN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SP_TYPE_HKERN, SPHkern))
-//#define SP_HKERN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SP_TYPE_HKERN, SPGlyphKerningClass))
-//#define SP_IS_HKERN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SP_TYPE_HKERN))
-//#define SP_IS_HKERN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SP_TYPE_HKERN))
+#define SP_HKERN(obj) (dynamic_cast<SPHkern*>(obj))
+#define SP_IS_HKERN(obj) (dynamic_cast<const SPHkern*>(obj) != NULL)
-#define SP_HKERN(obj) (dynamic_cast<SPHkern*>((SPObject*)obj))
-#define SP_IS_HKERN(obj) (dynamic_cast<const SPHkern*>((SPObject*)obj) != NULL)
-
-//#define SP_VKERN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SP_TYPE_VKERN, SPVkern))
-//#define SP_VKERN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SP_TYPE_VKERN, SPGlyphKerningClass))
-//#define SP_IS_VKERN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SP_TYPE_VKERN))
-//#define SP_IS_VKERN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SP_TYPE_VKERN))
-
-#define SP_VKERN(obj) (dynamic_cast<SPVkern*>((SPObject*)obj))
-#define SP_IS_VKERN(obj) (dynamic_cast<const SPVkern*>((SPObject*)obj) != NULL)
+#define SP_VKERN(obj) (dynamic_cast<SPVkern*>(obj))
+#define SP_IS_VKERN(obj) (dynamic_cast<const SPVkern*>(obj) != NULL)
// CPPIFY: These casting macros are buggy, as Vkern and Hkern aren't "real" classes.
-class GlyphNames{
+class GlyphNames {
public:
-GlyphNames(const gchar* value);
-~GlyphNames();
-bool contains(const char* name);
+ GlyphNames(char const* value);
+ ~GlyphNames();
+ bool contains(char const* name);
private:
-gchar* names;
+ char* names;
};
class SPGlyphKerning : public SPObject {
public:
- SPGlyphKerning();
- virtual ~SPGlyphKerning();
+ SPGlyphKerning();
+ virtual ~SPGlyphKerning() {}
+ // FIXME encapsulation
UnicodeRange* u1;
GlyphNames* g1;
UnicodeRange* u2;
@@ -58,22 +45,30 @@ public:
double k;
protected:
- virtual void build(SPDocument* doc, Inkscape::XML::Node* repr);
- virtual void release();
-
- virtual void set(unsigned int key, const gchar* value);
-
- virtual void update(SPCtx* ctx, unsigned int flags);
-
- virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, guint flags);
+ virtual void build(SPDocument* doc, Inkscape::XML::Node* repr);
+ virtual void release();
+ virtual void set(unsigned int key, char const* value);
+ virtual void update(SPCtx* ctx, unsigned int flags);
+ virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, unsigned int flags);
};
class SPHkern : public SPGlyphKerning {
-
+ virtual ~SPHkern() {}
};
class SPVkern : public SPGlyphKerning {
-
+ virtual ~SPVkern() {}
};
-#endif //#ifndef __SP_GLYPH_KERNING_H__
+#endif // !SEEN_SP_GLYPH_KERNING_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8 :
diff --git a/src/sp-glyph.cpp b/src/sp-glyph.cpp
index 695af03ba..eaa69d486 100644
--- a/src/sp-glyph.cpp
+++ b/src/sp-glyph.cpp
@@ -2,8 +2,6 @@
# include <config.h>
#endif
-#define __SP_GLYPH_C__
-
/*
* SVG <glyph> element implementation
*
@@ -25,46 +23,44 @@
#include "sp-factory.h"
namespace {
- SPObject* createGlyph() {
- return new SPGlyph();
- }
-
- bool glyphRegistered = SPFactory::instance().registerObject("svg:glyph", createGlyph);
+ SPObject* createGlyph() {
+ return new SPGlyph();
+ }
+ bool glyphRegistered = SPFactory::instance().registerObject("svg:glyph", createGlyph);
}
-SPGlyph::SPGlyph() : SPObject() {
+SPGlyph::SPGlyph()
+ : SPObject()
//TODO: correct these values:
-
- this->d = NULL;
- this->orientation = GLYPH_ORIENTATION_BOTH;
- this->arabic_form = GLYPH_ARABIC_FORM_INITIAL;
- this->lang = NULL;
- this->horiz_adv_x = 0;
- this->vert_origin_x = 0;
- this->vert_origin_y = 0;
- this->vert_adv_y = 0;
-}
-
-SPGlyph::~SPGlyph() {
+ , d(NULL)
+ , orientation(GLYPH_ORIENTATION_BOTH)
+ , arabic_form(GLYPH_ARABIC_FORM_INITIAL)
+ , lang(NULL)
+ , horiz_adv_x(0)
+ , vert_origin_x(0)
+ , vert_origin_y(0)
+ , vert_adv_y(0)
+{
}
-void SPGlyph::build(SPDocument *document, Inkscape::XML::Node *repr) {
- SPObject::build(document, repr);
+void SPGlyph::build(SPDocument *document, Inkscape::XML::Node *repr)
+{
+ SPObject::build(document, repr);
- this->readAttr( "unicode" );
- this->readAttr( "glyph-name" );
- this->readAttr( "d" );
- this->readAttr( "orientation" );
- this->readAttr( "arabic-form" );
- this->readAttr( "lang" );
- this->readAttr( "horiz-adv-x" );
- this->readAttr( "vert-origin-x" );
- this->readAttr( "vert-origin-y" );
- this->readAttr( "vert-adv-y" );
+ this->readAttr( "unicode" );
+ this->readAttr( "glyph-name" );
+ this->readAttr( "d" );
+ this->readAttr( "orientation" );
+ this->readAttr( "arabic-form" );
+ this->readAttr( "lang" );
+ this->readAttr( "horiz-adv-x" );
+ this->readAttr( "vert-origin-x" );
+ this->readAttr( "vert-origin-y" );
+ this->readAttr( "vert-adv-y" );
}
void SPGlyph::release() {
- SPObject::release();
+ SPObject::release();
}
static glyphArabicForm sp_glyph_read_arabic_form(gchar const *value){
@@ -97,7 +93,8 @@ static glyphArabicForm sp_glyph_read_arabic_form(gchar const *value){
return GLYPH_ARABIC_FORM_INITIAL; //TODO: VERIFY DEFAULT!
}
-static glyphOrientation sp_glyph_read_orientation(gchar const *value){
+static glyphOrientation sp_glyph_read_orientation(gchar const *value)
+{
if (!value) {
return GLYPH_ORIENTATION_BOTH;
}
@@ -115,7 +112,8 @@ static glyphOrientation sp_glyph_read_orientation(gchar const *value){
return GLYPH_ORIENTATION_BOTH;
}
-void SPGlyph::set(unsigned int key, const gchar *value) {
+void SPGlyph::set(unsigned int key, const gchar *value)
+{
switch (key) {
case SP_ATTR_UNICODE:
{
@@ -228,21 +226,22 @@ void SPGlyph::set(unsigned int key, const gchar *value) {
}
/**
- * * Receives update notifications.
- * */
-void SPGlyph::update(SPCtx *ctx, guint flags) {
+ * Receives update notifications.
+ */
+void SPGlyph::update(SPCtx *ctx, guint flags)
+{
if (flags & SP_OBJECT_MODIFIED_FLAG) {
/* do something to trigger redisplay, updates? */
- this->readAttr( "unicode" );
- this->readAttr( "glyph-name" );
- this->readAttr( "d" );
- this->readAttr( "orientation" );
- this->readAttr( "arabic-form" );
- this->readAttr( "lang" );
- this->readAttr( "horiz-adv-x" );
- this->readAttr( "vert-origin-x" );
- this->readAttr( "vert-origin-y" );
- this->readAttr( "vert-adv-y" );
+ this->readAttr( "unicode" );
+ this->readAttr( "glyph-name" );
+ this->readAttr( "d" );
+ this->readAttr( "orientation" );
+ this->readAttr( "arabic-form" );
+ this->readAttr( "lang" );
+ this->readAttr( "horiz-adv-x" );
+ this->readAttr( "vert-origin-x" );
+ this->readAttr( "vert-origin-y" );
+ this->readAttr( "vert-adv-y" );
}
SPObject::update(ctx, flags);
@@ -250,42 +249,45 @@ void SPGlyph::update(SPCtx *ctx, guint flags) {
#define COPY_ATTR(rd,rs,key) (rd)->setAttribute((key), rs->attribute(key));
-Inkscape::XML::Node* SPGlyph::write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags) {
- if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) {
- repr = xml_doc->createElement("svg:glyph");
- }
+Inkscape::XML::Node* SPGlyph::write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags)
+{
+ if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) {
+ repr = xml_doc->createElement("svg:glyph");
+ }
- /* I am commenting out this part because I am not certain how does it work. I will have to study it later. Juca
- repr->setAttribute("unicode", glyph->unicode);
- repr->setAttribute("glyph-name", glyph->glyph_name);
- repr->setAttribute("d", glyph->d);
- sp_repr_set_svg_double(repr, "orientation", (double) glyph->orientation);
- sp_repr_set_svg_double(repr, "arabic-form", (double) glyph->arabic_form);
- repr->setAttribute("lang", glyph->lang);
- sp_repr_set_svg_double(repr, "horiz-adv-x", glyph->horiz_adv_x);
- sp_repr_set_svg_double(repr, "vert-origin-x", glyph->vert_origin_x);
- sp_repr_set_svg_double(repr, "vert-origin-y", glyph->vert_origin_y);
- sp_repr_set_svg_double(repr, "vert-adv-y", glyph->vert_adv_y);
- */
- if (repr != this->getRepr()) {
- // All the COPY_ATTR functions below use
- // XML Tree directly while they shouldn't.
- COPY_ATTR(repr, this->getRepr(), "unicode");
- COPY_ATTR(repr, this->getRepr(), "glyph-name");
- COPY_ATTR(repr, this->getRepr(), "d");
- COPY_ATTR(repr, this->getRepr(), "orientation");
- COPY_ATTR(repr, this->getRepr(), "arabic-form");
- COPY_ATTR(repr, this->getRepr(), "lang");
- COPY_ATTR(repr, this->getRepr(), "horiz-adv-x");
- COPY_ATTR(repr, this->getRepr(), "vert-origin-x");
- COPY_ATTR(repr, this->getRepr(), "vert-origin-y");
- COPY_ATTR(repr, this->getRepr(), "vert-adv-y");
- }
+ /* I am commenting out this part because I am not certain how does it work. I will have to study it later. Juca
+ repr->setAttribute("unicode", glyph->unicode);
+ repr->setAttribute("glyph-name", glyph->glyph_name);
+ repr->setAttribute("d", glyph->d);
+ sp_repr_set_svg_double(repr, "orientation", (double) glyph->orientation);
+ sp_repr_set_svg_double(repr, "arabic-form", (double) glyph->arabic_form);
+ repr->setAttribute("lang", glyph->lang);
+ sp_repr_set_svg_double(repr, "horiz-adv-x", glyph->horiz_adv_x);
+ sp_repr_set_svg_double(repr, "vert-origin-x", glyph->vert_origin_x);
+ sp_repr_set_svg_double(repr, "vert-origin-y", glyph->vert_origin_y);
+ sp_repr_set_svg_double(repr, "vert-adv-y", glyph->vert_adv_y);
+ */
- SPObject::write(xml_doc, repr, flags);
+ if (repr != this->getRepr()) {
+ // All the COPY_ATTR functions below use
+ // XML Tree directly while they shouldn't.
+ COPY_ATTR(repr, this->getRepr(), "unicode");
+ COPY_ATTR(repr, this->getRepr(), "glyph-name");
+ COPY_ATTR(repr, this->getRepr(), "d");
+ COPY_ATTR(repr, this->getRepr(), "orientation");
+ COPY_ATTR(repr, this->getRepr(), "arabic-form");
+ COPY_ATTR(repr, this->getRepr(), "lang");
+ COPY_ATTR(repr, this->getRepr(), "horiz-adv-x");
+ COPY_ATTR(repr, this->getRepr(), "vert-origin-x");
+ COPY_ATTR(repr, this->getRepr(), "vert-origin-y");
+ COPY_ATTR(repr, this->getRepr(), "vert-adv-y");
+ }
- return repr;
+ SPObject::write(xml_doc, repr, flags);
+
+ return repr;
}
+
/*
Local Variables:
mode:c++
diff --git a/src/sp-glyph.h b/src/sp-glyph.h
index 798d9ff2f..297ac930e 100644
--- a/src/sp-glyph.h
+++ b/src/sp-glyph.h
@@ -1,13 +1,4 @@
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#ifndef __SP_GLYPH_H__
-#define __SP_GLYPH_H__
-
-/*
- * SVG <glyph> element implementation
- *
+/**
* Authors:
* Felipe C. da S. Sanches <juca@members.fsf.org>
*
@@ -16,6 +7,9 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
+#ifndef SEEN_SP_GLYPH_H
+#define SEEN_SP_GLYPH_H
+
#include "sp-object.h"
#define SP_GLYPH(obj) (dynamic_cast<SPGlyph*>((SPObject*)obj))
@@ -34,11 +28,16 @@ enum glyphOrientation {
GLYPH_ORIENTATION_BOTH
};
+/*
+ * SVG <glyph> element
+ */
+
class SPGlyph : public SPObject {
public:
- SPGlyph();
- virtual ~SPGlyph();
+ SPGlyph();
+ virtual ~SPGlyph() {}
+ // FIXME encapsulation
Glib::ustring unicode;
Glib::ustring glyph_name;
char* d;
@@ -51,14 +50,23 @@ public:
double vert_adv_y;
protected:
- virtual void build(SPDocument* doc, Inkscape::XML::Node* repr);
- virtual void release();
-
- virtual void set(unsigned int key, const gchar* value);
+ virtual void build(SPDocument* doc, Inkscape::XML::Node* repr);
+ virtual void release();
+ virtual void set(unsigned int key, const char* value);
+ virtual void update(SPCtx* ctx, unsigned int flags);
+ virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, unsigned int flags);
- virtual void update(SPCtx* ctx, unsigned int flags);
-
- virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, guint flags);
};
-#endif //#ifndef __SP_GLYPH_H__
+#endif // !SEEN_SP_GLYPH_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8 :
diff --git a/src/sp-gradient-vector.h b/src/sp-gradient-vector.h
index 8e860c169..e57820b56 100644
--- a/src/sp-gradient-vector.h
+++ b/src/sp-gradient-vector.h
@@ -1,7 +1,6 @@
#ifndef SEEN_SP_GRADIENT_VECTOR_H
#define SEEN_SP_GRADIENT_VECTOR_H
-#include <glib.h>
#include <vector>
#include "color.h"
@@ -14,9 +13,9 @@
* copying from SPStop to SPGradientStop.
*/
struct SPGradientStop {
- gdouble offset;
+ double offset;
SPColor color;
- gfloat opacity;
+ float opacity;
};
/**
diff --git a/src/sp-gradient.cpp b/src/sp-gradient.cpp
index 115cb754a..b3e885560 100644
--- a/src/sp-gradient.cpp
+++ b/src/sp-gradient.cpp
@@ -54,9 +54,6 @@
#include "style.h"
#include "display/grayscale.h"
-#define SP_MACROS_SILENT
-#include "macros.h"
-
/// Has to be power of 2 Seems to be unused.
//#define NCOLORS NR_GRADIENT_VECTOR_LENGTH
@@ -107,31 +104,36 @@ void SPGradient::setSwatch( bool swatch )
* Equivalent meaning they have the same stop count, same stop colors and same stop opacity
* @param that - A gradient to compare this to
*/
-gboolean SPGradient::isEquivalent(SPGradient *that)
+bool SPGradient::isEquivalent(SPGradient *that)
{
//TODO Make this work for mesh gradients
- bool status = FALSE;
+ bool status = false;
while(1){ // not really a loop, used to avoid deep nesting or multiple exit points from function
if (this->getStopCount() != that->getStopCount()) { break; }
if (this->hasStops() != that->hasStops()) { break; }
if (!this->getVector() || !that->getVector()) { break; }
- if ( (SP_IS_LINEARGRADIENT(this) && SP_IS_LINEARGRADIENT(that)) ||
- (SP_IS_RADIALGRADIENT(this) && SP_IS_RADIALGRADIENT(that)) ||
- (SP_IS_MESHGRADIENT(this) && SP_IS_MESHGRADIENT(that))) {
- /* OK! */
+ if (this->isSwatch() != that->isSwatch()) { break; }
+ if ( this->isSwatch() ){
+ // drop down to check stops.
+ }
+ else if (
+ (SP_IS_LINEARGRADIENT(this) && SP_IS_LINEARGRADIENT(that)) ||
+ (SP_IS_RADIALGRADIENT(this) && SP_IS_RADIALGRADIENT(that)) ||
+ (SP_IS_MESHGRADIENT(this) && SP_IS_MESHGRADIENT(that))) {
+ if(!this->isAligned(that))break;
}
- else { break; }
+ else { break; } // this should never happen, some unhandled type of gradient
SPStop *as = this->getVector()->getFirstStop();
SPStop *bs = that->getVector()->getFirstStop();
- bool effective = TRUE;
+ bool effective = true;
while (effective && (as && bs)) {
if (!as->getEffectiveColor().isClose(bs->getEffectiveColor(), 0.001) ||
as->offset != bs->offset) {
- effective = FALSE;
+ effective = false;
break;
}
else {
@@ -139,9 +141,9 @@ gboolean SPGradient::isEquivalent(SPGradient *that)
bs = bs->getNextStop();
}
}
- if(!effective)break;
+ if (!effective) break;
- status = TRUE;
+ status = true;
break;
}
return status;
@@ -152,10 +154,22 @@ gboolean SPGradient::isEquivalent(SPGradient *that)
* Aligned means that they have exactly the same coordinates and transform.
* @param that - A gradient to compare this to
*/
-gboolean SPGradient::isAligned(SPGradient *that)
+bool SPGradient::isAligned(SPGradient *that)
{
- bool status = FALSE;
+ bool status = false;
+ /* Some gradients have coordinates/other values specified, some don't.
+ yes/yes check the coordinates/other values
+ no/no aligned (because both have all default values)
+ yes/no not aligned
+ no/yes not aligned
+ It is NOT safe to just compare the computed values because if that field has
+ not been set the computed value could be full of garbage.
+
+ In theory the yes/no and no/yes cases could be aligned if the specified value
+ matches the default value.
+ */
+
while(1){ // not really a loop, used to avoid deep nesting or multiple exit points from function
if(this->gradientTransform_set != that->gradientTransform_set) { break; }
if(this->gradientTransform_set &&
@@ -164,35 +178,49 @@ gboolean SPGradient::isAligned(SPGradient *that)
SPLinearGradient *sg=SP_LINEARGRADIENT(this);
SPLinearGradient *tg=SP_LINEARGRADIENT(that);
- if( !sg->x1._set || !tg->x1._set || // assume that if these are set so will be all the others
- (sg->x1.computed != tg->x1.computed) ||
- (sg->y1.computed != tg->y1.computed) ||
- (sg->x2.computed != tg->x2.computed) ||
- (sg->y2.computed != tg->y2.computed)
- ) { break; }
+ if( sg->x1._set != tg->x1._set) { break; }
+ if( sg->y1._set != tg->y1._set) { break; }
+ if( sg->x2._set != tg->x2._set) { break; }
+ if( sg->y2._set != tg->y2._set) { break; }
+ if( sg->x1._set && sg->y1._set && sg->x2._set && sg->y2._set) {
+ if( (sg->x1.computed != tg->x1.computed) ||
+ (sg->y1.computed != tg->y1.computed) ||
+ (sg->x2.computed != tg->x2.computed) ||
+ (sg->y2.computed != tg->y2.computed) ) { break; }
+ } else if( sg->x1._set || sg->y1._set || sg->x2._set || sg->y2._set) { break; } // some mix of set and not set
+ // none set? assume aligned and fall through
} else if (SP_IS_RADIALGRADIENT(this) && SP_IS_LINEARGRADIENT(that)) {
SPRadialGradient *sg=SP_RADIALGRADIENT(this);
SPRadialGradient *tg=SP_RADIALGRADIENT(that);
- if( !sg->cx._set || !tg->cx._set || // assume that if these are set so will be all the others
- (sg->cx.computed != tg->cx.computed) ||
- (sg->cy.computed != tg->cy.computed) ||
- (sg->r.computed != tg->r.computed ) ||
- (sg->fx.computed != tg->fx.computed) ||
- (sg->fy.computed != tg->fy.computed)
- ) { break; }
+
+ if( sg->cx._set != tg->cx._set) { break; }
+ if( sg->cy._set != tg->cy._set) { break; }
+ if( sg->r._set != tg->r._set) { break; }
+ if( sg->fx._set != tg->fx._set) { break; }
+ if( sg->fy._set != tg->fy._set) { break; }
+ if( sg->cx._set && sg->cy._set && sg->fx._set && sg->fy._set && sg->r._set) {
+ if( (sg->cx.computed != tg->cx.computed) ||
+ (sg->cy.computed != tg->cy.computed) ||
+ (sg->r.computed != tg->r.computed ) ||
+ (sg->fx.computed != tg->fx.computed) ||
+ (sg->fy.computed != tg->fy.computed) ) { break; }
+ } else if( sg->cx._set || sg->cy._set || sg->fx._set || sg->fy._set || sg->r._set ) { break; } // some mix of set and not set
+ // none set? assume aligned and fall through
} else if (SP_IS_MESHGRADIENT(this) && SP_IS_MESHGRADIENT(that)) {
SPMeshGradient *sg=SP_MESHGRADIENT(this);
SPMeshGradient *tg=SP_MESHGRADIENT(that);
- if( !sg->x._set || !tg->x._set ||
- !sg->y._set || !tg->y._set ||
- (sg->x.computed != tg->x.computed) ||
- (sg->y.computed != tg->y.computed)
- ) { break; }
+ if( sg->x._set != !tg->x._set) { break; }
+ if( sg->y._set != !tg->y._set) { break; }
+ if( sg->x._set && sg->y._set) {
+ if( (sg->x.computed != tg->x.computed) ||
+ (sg->y.computed != tg->y.computed) ) { break; }
+ } else if( sg->x._set || sg->y._set) { break; } // some mix of set and not set
+ // none set? assume aligned and fall through
} else {
break;
}
- status = TRUE;
+ status = true;
break;
}
return status;
@@ -231,8 +259,6 @@ SPGradient::SPGradient() : SPPaintServer(), units(),
this->vector.built = false;
this->vector.stops.clear();
-
- //new (&this->modified_connection) sigc::connection();
}
SPGradient::~SPGradient() {
diff --git a/src/sp-gradient.h b/src/sp-gradient.h
index 1dfff22ee..fbb48df62 100644
--- a/src/sp-gradient.h
+++ b/src/sp-gradient.h
@@ -14,30 +14,18 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include <vector>
-#include <gdk/gdk.h>
-#include <glibmm/ustring.h>
#include <2geom/affine.h>
+#include <cstddef>
+#include <glibmm/ustring.h>
+#include <sigc++/connection.h>
+#include <vector>
+
#include "sp-paint-server.h"
#include "sp-gradient-spread.h"
#include "sp-gradient-units.h"
#include "sp-gradient-vector.h"
#include "sp-mesh-array.h"
-#include <stddef.h>
-#include <sigc++/connection.h>
-
-
-
-//#include <glib.h>
-//#include <glib-object.h>
-//#include <2geom/forward.h>
-//#include "sp-gradient-spread.h"
-//#include "sp-gradient-units.h"
-//
-//class SPGradient;
-//struct SPMeshGradient;
-
class SPGradientReference;
class SPStop;
@@ -109,30 +97,30 @@ public:
private:
/** gradientUnits attribute */
SPGradientUnits units;
- guint units_set : 1;
+ unsigned int units_set : 1;
public:
/** gradientTransform attribute */
Geom::Affine gradientTransform;
- guint gradientTransform_set : 1;
+ unsigned int gradientTransform_set : 1;
private:
/** spreadMethod attribute */
SPGradientSpread spread;
- guint spread_set : 1;
+ unsigned int spread_set : 1;
/** Gradient stops */
- guint has_stops : 1;
+ unsigned int has_stops : 1;
/** Gradient patches */
- guint has_patches : 1;
+ unsigned int has_patches : 1;
public:
/** Reference (href) */
SPGradientReference *ref;
/** State in Inkscape gradient system */
- guint state;
+ unsigned int state;
/** Linear and Radial Gradients */
@@ -146,8 +134,8 @@ public:
SPStop* getFirstStop();
int getStopCount() const;
- gboolean isEquivalent(SPGradient *b);
- gboolean isAligned(SPGradient *b);
+ bool isEquivalent(SPGradient *b);
+ bool isAligned(SPGradient *b);
/** Mesh Gradients **************/
@@ -175,7 +163,7 @@ public:
*/
SPGradient *getVector(bool force_private = false);
- static GType getType();
+ //static GType getType();
/** Forces vector to be built, if not present (i.e. changed) */
void ensureVector();
@@ -196,7 +184,7 @@ public:
void setSwatch(bool swatch = true);
- static void gradientRefModified(SPObject *href, guint flags, SPGradient *gradient);
+ static void gradientRefModified(SPObject *href, unsigned int flags, SPGradient *gradient);
static void gradientRefChanged(SPObject *old_ref, SPObject *ref, SPGradient *gr);
private:
@@ -208,13 +196,13 @@ private:
protected:
virtual void build(SPDocument *document, Inkscape::XML::Node *repr);
virtual void release();
- virtual void modified(guint flags);
- virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags);
+ virtual void modified(unsigned int flags);
+ virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags);
virtual void child_added(Inkscape::XML::Node *child, Inkscape::XML::Node *ref);
virtual void remove_child(Inkscape::XML::Node *child);
- virtual void set(unsigned key, gchar const *value);
+ virtual void set(unsigned key, char const *value);
};
void
diff --git a/src/sp-guide-constraint.h b/src/sp-guide-constraint.h
index ebc3b01ce..29f47f45a 100644
--- a/src/sp-guide-constraint.h
+++ b/src/sp-guide-constraint.h
@@ -29,10 +29,8 @@ public:
}
};
-
#endif // SEEN_SP_GUIDE_CONSTRAINT_H
-
/*
Local Variables:
mode:c++
diff --git a/src/sp-guide.cpp b/src/sp-guide.cpp
index 60f15a79d..581c8a440 100644
--- a/src/sp-guide.cpp
+++ b/src/sp-guide.cpp
@@ -46,117 +46,38 @@
using Inkscape::DocumentUndo;
using std::vector;
-//enum {
-// PROP_0,
-// PROP_COLOR,
-// PROP_HICOLOR
-//};
-//
-//static void sp_guide_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
-//static void sp_guide_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
-
#include "sp-factory.h"
namespace {
- SPObject* createGuide() {
- return new SPGuide();
- }
-
- bool guideRegistered = SPFactory::instance().registerObject("sodipodi:guide", createGuide);
-}
-
-//static void sp_guide_class_init(SPGuideClass *gc)
-//{
-// GObjectClass *gobject_class = (GObjectClass *) gc;
-//
-// gobject_class->set_property = sp_guide_set_property;
-// gobject_class->get_property = sp_guide_get_property;
-//
-// g_object_class_install_property(gobject_class,
-// PROP_COLOR,
-// g_param_spec_uint("color", "Color", "Color",
-// 0,
-// 0xffffffff,
-// 0xff000000,
-// (GParamFlags) G_PARAM_READWRITE));
-//
-// g_object_class_install_property(gobject_class,
-// PROP_HICOLOR,
-// g_param_spec_uint("hicolor", "HiColor", "HiColor",
-// 0,
-// 0xffffffff,
-// 0xff000000,
-// (GParamFlags) G_PARAM_READWRITE));
-//}
-// CPPIFY: properties!
-
-SPGuide::SPGuide() : SPObject() {
- this->label = NULL;
- this->views = NULL;
-
- this->normal_to_line = Geom::Point(0.,1.);
- this->point_on_line = Geom::Point(0.,0.);
- this->color = 0x0000ff7f;
- this->hicolor = 0xff00007f;
-}
-
-SPGuide::~SPGuide() {
-}
-
-guint32 SPGuide::getColor() const {
- return color;
-}
+ SPObject* createGuide() {
+ return new SPGuide();
+ }
-guint32 SPGuide::getHiColor() const {
- return hicolor;
+ bool guideRegistered = SPFactory::instance().registerObject("sodipodi:guide", createGuide);
}
-void SPGuide::setColor(guint32 c) {
- color = c;
-
- for (GSList *l = this->views; l != NULL; l = l->next) {
- sp_guideline_set_color(SP_GUIDELINE(l->data), this->color);
- }
-}
+SPGuide::SPGuide()
+ : SPObject()
+ , label(NULL)
+ , views(NULL)
+ , normal_to_line(Geom::Point(0.,1.))
+ , point_on_line(Geom::Point(0.,0.))
+ , color(0x0000ff7f)
+ , hicolor(0xff00007f)
+{}
+
+void SPGuide::setColor(guint32 c)
+{
+ color = c;
-void SPGuide::setHiColor(guint32 h) {
- this->hicolor = h;
+ for (GSList *l = this->views; l != NULL; l = l->next) {
+ sp_guideline_set_color(SP_GUIDELINE(l->data), this->color);
+ }
}
-//static void sp_guide_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec */*pspec*/)
-//{
-// SPGuide &guide = *SP_GUIDE(object);
-//
-// switch (prop_id) {
-// case PROP_COLOR:
-// guide.color = g_value_get_uint(value);
-// for (GSList *l = guide.views; l != NULL; l = l->next) {
-// sp_guideline_set_color(SP_GUIDELINE(l->data), guide.color);
-// }
-// break;
-//
-// case PROP_HICOLOR:
-// guide.hicolor = g_value_get_uint(value);
-// break;
-// }
-//}
-//
-//static void sp_guide_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec */*pspec*/)
-//{
-// SPGuide const &guide = *SP_GUIDE(object);
-//
-// switch (prop_id) {
-// case PROP_COLOR:
-// g_value_set_uint(value, guide.color);
-// break;
-// case PROP_HICOLOR:
-// g_value_set_uint(value, guide.hicolor);
-// break;
-// }
-//}
-
-void SPGuide::build(SPDocument *document, Inkscape::XML::Node *repr) {
- SPObject::build(document, repr);
+void SPGuide::build(SPDocument *document, Inkscape::XML::Node *repr)
+{
+ SPObject::build(document, repr);
this->readAttr( "inkscape:label" );
this->readAttr( "orientation" );
@@ -166,7 +87,8 @@ void SPGuide::build(SPDocument *document, Inkscape::XML::Node *repr) {
document->addResource("guide", this);
}
-void SPGuide::release() {
+void SPGuide::release()
+{
while (this->views) {
sp_guideline_delete(SP_GUIDELINE(this->views->data));
this->views = g_slist_remove(this->views, this->views->data);
@@ -191,67 +113,67 @@ void SPGuide::set(unsigned int key, const gchar *value) {
this->label = NULL;
}
- sp_guide_set_label(*this, this->label, false);
+ this->set_label(this->label, false);
break;
case SP_ATTR_ORIENTATION:
- {
- if (value && !strcmp(value, "horizontal")) {
- /* Visual representation of a horizontal line, constrain vertically (y coordinate). */
- this->normal_to_line = Geom::Point(0., 1.);
- } else if (value && !strcmp(value, "vertical")) {
- this->normal_to_line = Geom::Point(1., 0.);
- } else if (value) {
- gchar ** strarray = g_strsplit(value, ",", 2);
- double newx, newy;
- unsigned int success = sp_svg_number_read_d(strarray[0], &newx);
- success += sp_svg_number_read_d(strarray[1], &newy);
- g_strfreev (strarray);
- if (success == 2 && (fabs(newx) > 1e-6 || fabs(newy) > 1e-6)) {
- Geom::Point direction(newx, newy);
- direction.normalize();
- this->normal_to_line = direction;
- } else {
- // default to vertical line for bad arguments
- this->normal_to_line = Geom::Point(1., 0.);
- }
+ {
+ if (value && !strcmp(value, "horizontal")) {
+ /* Visual representation of a horizontal line, constrain vertically (y coordinate). */
+ this->normal_to_line = Geom::Point(0., 1.);
+ } else if (value && !strcmp(value, "vertical")) {
+ this->normal_to_line = Geom::Point(1., 0.);
+ } else if (value) {
+ gchar ** strarray = g_strsplit(value, ",", 2);
+ double newx, newy;
+ unsigned int success = sp_svg_number_read_d(strarray[0], &newx);
+ success += sp_svg_number_read_d(strarray[1], &newy);
+ g_strfreev (strarray);
+ if (success == 2 && (fabs(newx) > 1e-6 || fabs(newy) > 1e-6)) {
+ Geom::Point direction(newx, newy);
+ direction.normalize();
+ this->normal_to_line = direction;
} else {
// default to vertical line for bad arguments
this->normal_to_line = Geom::Point(1., 0.);
}
- sp_guide_set_normal(*this, this->normal_to_line, false);
+ } else {
+ // default to vertical line for bad arguments
+ this->normal_to_line = Geom::Point(1., 0.);
}
- break;
+ this->set_normal(this->normal_to_line, false);
+ }
+ break;
case SP_ATTR_POSITION:
- {
- if (value) {
- gchar ** strarray = g_strsplit(value, ",", 2);
- double newx, newy;
- unsigned int success = sp_svg_number_read_d(strarray[0], &newx);
- success += sp_svg_number_read_d(strarray[1], &newy);
- g_strfreev (strarray);
- if (success == 2) {
- this->point_on_line = Geom::Point(newx, newy);
- } else if (success == 1) {
- // before 0.46 style guideline definition.
- const gchar *attr = this->getRepr()->attribute("orientation");
- if (attr && !strcmp(attr, "horizontal")) {
- this->point_on_line = Geom::Point(0, newx);
- } else {
- this->point_on_line = Geom::Point(newx, 0);
- }
+ {
+ if (value) {
+ gchar ** strarray = g_strsplit(value, ",", 2);
+ double newx, newy;
+ unsigned int success = sp_svg_number_read_d(strarray[0], &newx);
+ success += sp_svg_number_read_d(strarray[1], &newy);
+ g_strfreev (strarray);
+ if (success == 2) {
+ this->point_on_line = Geom::Point(newx, newy);
+ } else if (success == 1) {
+ // before 0.46 style guideline definition.
+ const gchar *attr = this->getRepr()->attribute("orientation");
+ if (attr && !strcmp(attr, "horizontal")) {
+ this->point_on_line = Geom::Point(0, newx);
+ } else {
+ this->point_on_line = Geom::Point(newx, 0);
}
- } else {
- // default to (0,0) for bad arguments
- this->point_on_line = Geom::Point(0,0);
}
- // update position in non-committing way
- // fixme: perhaps we need to add an update method instead, and request_update here
- sp_guide_moveto(*this, this->point_on_line, false);
+ } else {
+ // default to (0,0) for bad arguments
+ this->point_on_line = Geom::Point(0,0);
}
- break;
+ // update position in non-committing way
+ // fixme: perhaps we need to add an update method instead, and request_update here
+ this->moveto(this->point_on_line, false);
+ }
+ break;
default:
SPObject::set(key, value);
- break;
+ break;
}
}
@@ -276,15 +198,15 @@ SPGuide *SPGuide::createSPGuide(SPDocument *doc, Geom::Point const &pt1, Geom::P
return guide;
}
-void
-sp_guide_pt_pairs_to_guides(SPDocument *doc, std::list<std::pair<Geom::Point, Geom::Point> > &pts) {
+void sp_guide_pt_pairs_to_guides(SPDocument *doc, std::list<std::pair<Geom::Point, Geom::Point> > &pts)
+{
for (std::list<std::pair<Geom::Point, Geom::Point> >::iterator i = pts.begin(); i != pts.end(); ++i) {
SPGuide::createSPGuide(doc, (*i).first, (*i).second);
}
}
-void
-sp_guide_create_guides_around_page(SPDesktop *dt) {
+void sp_guide_create_guides_around_page(SPDesktop *dt)
+{
SPDocument *doc=sp_desktop_document(dt);
std::list<std::pair<Geom::Point, Geom::Point> > pts;
@@ -303,8 +225,8 @@ sp_guide_create_guides_around_page(SPDesktop *dt) {
DocumentUndo::done(doc, SP_VERB_NONE, _("Create Guides Around the Page"));
}
-void
-sp_guide_delete_all_guides(SPDesktop *dt) {
+void sp_guide_delete_all_guides(SPDesktop *dt)
+{
SPDocument *doc=sp_desktop_document(dt);
const GSList *current;
while ( (current = doc->getResourceList("guide")) ) {
@@ -325,6 +247,14 @@ void SPGuide::showSPGuide(SPCanvasGroup *group, GCallback handler)
views = g_slist_prepend(views, item);
}
+void SPGuide::showSPGuide()
+{
+ for (GSList *v = views; v != NULL; v = v->next) {
+ sp_canvas_item_show(SP_CANVAS_ITEM(v->data));
+ sp_canvas_item_show(SP_CANVAS_ITEM(SP_GUIDELINE(v->data)->origin));
+ }
+}
+
void SPGuide::hideSPGuide(SPCanvas *canvas)
{
g_assert(canvas != NULL);
@@ -338,10 +268,18 @@ void SPGuide::hideSPGuide(SPCanvas *canvas)
}
}
- g_assert_not_reached();
+ assert(false);
+}
+
+void SPGuide::hideSPGuide()
+{
+ for (GSList *v = views; v != NULL; v = v->next) {
+ sp_canvas_item_hide(SP_CANVAS_ITEM(v->data));
+ sp_canvas_item_hide(SP_CANVAS_ITEM(SP_GUIDELINE(v->data)->origin));
+ }
}
-void SPGuide::sensitize(SPCanvas *canvas, gboolean sensitive)
+void SPGuide::sensitize(SPCanvas *canvas, bool sensitive)
{
g_assert(canvas != NULL);
g_assert(SP_IS_CANVAS(canvas));
@@ -353,7 +291,7 @@ void SPGuide::sensitize(SPCanvas *canvas, gboolean sensitive)
}
}
- g_assert_not_reached();
+ assert(false);
}
Geom::Point SPGuide::getPositionFrom(Geom::Point const &pt) const
@@ -371,11 +309,9 @@ double SPGuide::getDistanceFrom(Geom::Point const &pt) const
* true indicates a "committing" version: in response to button release event after
* dragging a guideline, or clicking OK in guide editing dialog.
*/
-void sp_guide_moveto(SPGuide &guide, Geom::Point const point_on_line, bool const commit)
+void SPGuide::moveto(Geom::Point const point_on_line, bool const commit)
{
- g_assert(SP_IS_GUIDE(&guide));
-
- for (GSList *l = guide.views; l != NULL; l = l->next) {
+ for (GSList *l = views; l != NULL; l = l->next) {
sp_guideline_set_position(SP_GUIDELINE(l->data), point_on_line);
}
@@ -383,16 +319,16 @@ void sp_guide_moveto(SPGuide &guide, Geom::Point const point_on_line, bool const
case, so that the guide's new position is available for sp_item_rm_unsatisfied_cns. */
if (commit) {
//XML Tree being used here directly while it shouldn't be.
- sp_repr_set_point(guide.getRepr(), "position", point_on_line);
+ sp_repr_set_point(getRepr(), "position", point_on_line);
}
/* DISABLED CODE BECAUSE SPGuideAttachment IS NOT USE AT THE MOMENT (johan)
- for (vector<SPGuideAttachment>::const_iterator i(guide.attached_items.begin()),
- iEnd(guide.attached_items.end());
+ for (vector<SPGuideAttachment>::const_iterator i(attached_items.begin()),
+ iEnd(attached_items.end());
i != iEnd; ++i)
{
SPGuideAttachment const &att = *i;
- sp_item_notify_moveto(*att.item, guide, att.snappoint_ix, position, commit);
+ sp_item_notify_moveto(*att.item, this, att.snappoint_ix, position, commit);
}
*/
}
@@ -402,11 +338,9 @@ void sp_guide_moveto(SPGuide &guide, Geom::Point const point_on_line, bool const
* true indicates a "committing" version: in response to button release event after
* dragging a guideline, or clicking OK in guide editing dialog.
*/
-void sp_guide_set_normal(SPGuide &guide, Geom::Point const normal_to_line, bool const commit)
+void SPGuide::set_normal(Geom::Point const normal_to_line, bool const commit)
{
- g_assert(SP_IS_GUIDE(&guide));
-
- for (GSList *l = guide.views; l != NULL; l = l->next) {
+ for (GSList *l = this->views; l != NULL; l = l->next) {
sp_guideline_set_normal(SP_GUIDELINE(l->data), normal_to_line);
}
@@ -414,47 +348,45 @@ void sp_guide_set_normal(SPGuide &guide, Geom::Point const normal_to_line, bool
case, so that the guide's new position is available for sp_item_rm_unsatisfied_cns. */
if (commit) {
//XML Tree being used directly while it shouldn't be
- sp_repr_set_point(guide.getRepr(), "orientation", normal_to_line);
+ sp_repr_set_point(getRepr(), "orientation", normal_to_line);
}
/* DISABLED CODE BECAUSE SPGuideAttachment IS NOT USE AT THE MOMENT (johan)
- for (vector<SPGuideAttachment>::const_iterator i(guide.attached_items.begin()),
- iEnd(guide.attached_items.end());
+ for (vector<SPGuideAttachment>::const_iterator i(attached_items.begin()),
+ iEnd(attached_items.end());
i != iEnd; ++i)
{
SPGuideAttachment const &att = *i;
- sp_item_notify_moveto(*att.item, guide, att.snappoint_ix, position, commit);
+ sp_item_notify_moveto(*att.item, this, att.snappoint_ix, position, commit);
}
*/
}
-void sp_guide_set_color(SPGuide &guide, const unsigned r, const unsigned g, const unsigned b, bool const commit)
+void SPGuide::set_color(const unsigned r, const unsigned g, const unsigned b, bool const commit)
{
- g_assert(SP_IS_GUIDE(&guide));
- guide.color = (r << 24) | (g << 16) | (b << 8) | 0x7f;
+ this->color = (r << 24) | (g << 16) | (b << 8) | 0x7f;
- if (guide.views){
- sp_guideline_set_color(SP_GUIDELINE(guide.views->data), guide.color);
+ if (views) {
+ sp_guideline_set_color(SP_GUIDELINE(views->data), this->color);
}
- if (commit){
+ if (commit) {
std::ostringstream os;
os << "rgb(" << r << "," << g << "," << b << ")";
//XML Tree being used directly while it shouldn't be
- guide.getRepr()->setAttribute("inkscape:color", os.str().c_str());
+ getRepr()->setAttribute("inkscape:color", os.str().c_str());
}
}
-void sp_guide_set_label(SPGuide &guide, const char* label, bool const commit)
+void SPGuide::set_label(const char* label, bool const commit)
{
- g_assert(SP_IS_GUIDE(&guide));
- if (guide.views){
- sp_guideline_set_label(SP_GUIDELINE(guide.views->data), label);
+ if (views) {
+ sp_guideline_set_label(SP_GUIDELINE(views->data), label);
}
- if (commit){
+ if (commit) {
//XML Tree being used directly while it shouldn't be
- guide.getRepr()->setAttribute("inkscape:label", label);
+ getRepr()->setAttribute("inkscape:label", label);
}
}
@@ -464,33 +396,33 @@ void sp_guide_set_label(SPGuide &guide, const char* label, bool const commit)
*
* The caller is responsible for freeing the string.
*/
-char *sp_guide_description(SPGuide const *guide, const bool verbose)
+char* SPGuide::description(bool const verbose) const
{
using Geom::X;
using Geom::Y;
- char *descr = 0;
- if ( !guide->document ) {
+ char *descr = NULL;
+ if ( !this->document ) {
// Guide has probably been deleted and no longer has an attached namedview.
- descr = g_strdup_printf("%s", _("Deleted"));
+ descr = g_strdup(_("Deleted"));
} else {
- SPNamedView *namedview = sp_document_namedview(guide->document, NULL);
+ SPNamedView *namedview = sp_document_namedview(this->document, NULL);
- Inkscape::Util::Quantity x_q = Inkscape::Util::Quantity(guide->point_on_line[X], "px");
- Inkscape::Util::Quantity y_q = Inkscape::Util::Quantity(guide->point_on_line[Y], "px");
+ Inkscape::Util::Quantity x_q = Inkscape::Util::Quantity(this->point_on_line[X], "px");
+ Inkscape::Util::Quantity y_q = Inkscape::Util::Quantity(this->point_on_line[Y], "px");
GString *position_string_x = g_string_new(x_q.string(namedview->doc_units).c_str());
GString *position_string_y = g_string_new(y_q.string(namedview->doc_units).c_str());
gchar *shortcuts = g_strdup_printf("; %s", _("<b>Shift+drag</b> to rotate, <b>Ctrl+drag</b> to move origin, <b>Del</b> to delete"));
- if ( are_near(guide->normal_to_line, Geom::Point(1., 0.)) ||
- are_near(guide->normal_to_line, -Geom::Point(1., 0.)) ) {
+ if ( are_near(this->normal_to_line, Geom::Point(1., 0.)) ||
+ are_near(this->normal_to_line, -Geom::Point(1., 0.)) ) {
descr = g_strdup_printf(_("vertical, at %s"), position_string_x->str);
- } else if ( are_near(guide->normal_to_line, Geom::Point(0., 1.)) ||
- are_near(guide->normal_to_line, -Geom::Point(0., 1.)) ) {
+ } else if ( are_near(this->normal_to_line, Geom::Point(0., 1.)) ||
+ are_near(this->normal_to_line, -Geom::Point(0., 1.)) ) {
descr = g_strdup_printf(_("horizontal, at %s"), position_string_y->str);
} else {
- double const radians = guide->angle();
+ double const radians = this->angle();
double const degrees = Geom::rad_to_deg(radians);
int const degrees_int = (int) round(degrees);
descr = g_strdup_printf(_("at %d degrees, through (%s,%s)"),
@@ -537,4 +469,4 @@ void sp_guide_remove(SPGuide *guide)
fill-column:99
End:
*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/sp-guide.h b/src/sp-guide.h
index fa4f0033b..382ea56f0 100644
--- a/src/sp-guide.h
+++ b/src/sp-guide.h
@@ -13,15 +13,21 @@
*
*/
+#include <2geom/point.h>
#include <vector>
-#include <2geom/point.h>
#include "sp-object.h"
#include "sp-guide-attachment.h"
+typedef unsigned int guint32;
+extern "C" {
+ typedef void (*GCallback) (void);
+ typedef struct _GSList GSList;
+}
+
+class SPDesktop;
struct SPCanvas;
struct SPCanvasGroup;
-class SPDesktop;
#define SP_GUIDE(obj) (dynamic_cast<SPGuide*>((SPObject*)obj))
#define SP_IS_GUIDE(obj) (dynamic_cast<const SPGuide*>((SPObject*)obj) != NULL)
@@ -29,51 +35,65 @@ class SPDesktop;
/* Represents the constraint on p that dot(g.direction, p) == g.position. */
class SPGuide : public SPObject {
public:
- SPGuide();
- virtual ~SPGuide();
+ SPGuide();
+ virtual ~SPGuide() {}
- char* label;
- Geom::Point normal_to_line;
- Geom::Point point_on_line;
+ void set_color(const unsigned r, const unsigned g, const unsigned b, bool const commit);
+ void setColor(guint32 c);
+ void setHiColor(guint32 h) { hicolor = h; }
- guint32 color;
- guint32 hicolor;
- GSList *views;
- std::vector<SPGuideAttachment> attached_items;
+ guint32 getColor() const { return color; }
+ guint32 getHiColor() const { return hicolor; }
+ Geom::Point getPoint() const { return point_on_line; }
+ Geom::Point getNormal() const { return normal_to_line; }
- guint32 getColor() const;
- guint32 getHiColor() const;
- void setColor(guint32 c);
- void setHiColor(guint32 h);
+ void moveto(Geom::Point const point_on_line, bool const commit);
+ void set_normal(Geom::Point const normal_to_line, bool const commit);
+
+ void set_label(const char* label, bool const commit);
+ char const* getLabel() const { return label; }
- inline bool isHorizontal() const { return (normal_to_line[Geom::X] == 0.); };
- inline bool isVertical() const { return (normal_to_line[Geom::Y] == 0.); };
- inline double angle() const { return std::atan2( - normal_to_line[Geom::X], normal_to_line[Geom::Y] ); };
static SPGuide *createSPGuide(SPDocument *doc, Geom::Point const &pt1, Geom::Point const &pt2);
+
void showSPGuide(SPCanvasGroup *group, GCallback handler);
void hideSPGuide(SPCanvas *canvas);
- void sensitize(SPCanvas *canvas, gboolean sensitive);
- Geom::Point getPositionFrom(Geom::Point const &pt) const;
+ void showSPGuide(); // argument-free versions
+ void hideSPGuide();
+
+ void sensitize(SPCanvas *canvas, bool sensitive);
+
+ bool isHorizontal() const { return (normal_to_line[Geom::X] == 0.); };
+ bool isVertical() const { return (normal_to_line[Geom::Y] == 0.); };
+
+ char* description(bool const verbose = true) const;
+
+ double angle() const { return std::atan2( - normal_to_line[Geom::X], normal_to_line[Geom::Y] ); }
double getDistanceFrom(Geom::Point const &pt) const;
+ Geom::Point getPositionFrom(Geom::Point const &pt) const;
protected:
- virtual void build(SPDocument* doc, Inkscape::XML::Node* repr);
- virtual void release();
- virtual void set(unsigned int key, const gchar* value);
+ virtual void build(SPDocument* doc, Inkscape::XML::Node* repr);
+ virtual void release();
+ virtual void set(unsigned int key, const char* value);
+
+ char* label;
+ GSList *views; // contains an object of type SPGuideline (see display/guideline.cpp for definition)
+ Geom::Point normal_to_line;
+ Geom::Point point_on_line;
+
+ guint32 color;
+ guint32 hicolor;
+public:
+ std::vector<SPGuideAttachment> attached_items; // unused
};
+// These functions rightfully belong to SPDesktop. What gives?!
void sp_guide_pt_pairs_to_guides(SPDocument *doc, std::list<std::pair<Geom::Point, Geom::Point> > &pts);
void sp_guide_create_guides_around_page(SPDesktop *dt);
void sp_guide_delete_all_guides(SPDesktop *dt);
-void sp_guide_moveto(SPGuide &guide, Geom::Point const point_on_line, bool const commit);
-void sp_guide_set_normal(SPGuide &guide, Geom::Point const normal_to_line, bool const commit);
-void sp_guide_set_label(SPGuide &guide, const char* label, bool const commit);
-void sp_guide_set_color(SPGuide &guide, const unsigned r, const unsigned g, const unsigned b, bool const commit);
void sp_guide_remove(SPGuide *guide);
-char *sp_guide_description(SPGuide const *guide, const bool verbose = true);
-
#endif // SEEN_SP_GUIDE_H
/*
diff --git a/src/sp-hatch-path.cpp b/src/sp-hatch-path.cpp
new file mode 100644
index 000000000..8558b67f2
--- /dev/null
+++ b/src/sp-hatch-path.cpp
@@ -0,0 +1,361 @@
+/**
+ * @file
+ * SVG <hatchPath> implementation
+ */
+/*
+ * Author:
+ * Tomasz Boczkowski <penginsbacon@gmail.com>
+ * Jon A. Cruz <jon@joncruz.org>
+ *
+ * Copyright (C) 2014 Tomasz Boczkowski
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <cstring>
+#include <string>
+#include <2geom/path.h>
+#include <2geom/transforms.h>
+
+#include "svg/svg.h"
+#include "display/cairo-utils.h"
+#include "display/curve.h"
+#include "display/drawing-context.h"
+#include "display/drawing-surface.h"
+#include "display/drawing.h"
+#include "display/drawing-shape.h"
+#include "helper/geom.h"
+#include "attributes.h"
+#include "document-private.h"
+#include "uri.h"
+#include "style.h"
+#include "sp-hatch-path.h"
+#include "svg/css-ostringstream.h"
+#include "xml/repr.h"
+
+#include "sp-factory.h"
+
+namespace {
+
+SPObject* createHatchPath()
+{
+ return new SPHatchPath();
+}
+
+bool hatchRegistered = SPFactory::instance().registerObject("svg:hatchPath", createHatchPath);
+
+} // namespace
+
+SPHatchPath::SPHatchPath()
+ : offset(),
+ _display(),
+ _curve(NULL),
+ _continuous(false)
+{
+ offset.unset();
+}
+
+SPHatchPath::~SPHatchPath()
+{
+}
+
+void SPHatchPath::setCurve(SPCurve *new_curve, bool owner)
+{
+ if (_curve) {
+ _curve = _curve->unref();
+ }
+
+ if (new_curve) {
+ if (owner) {
+ _curve = new_curve->ref();
+ } else {
+ _curve = new_curve->copy();
+ }
+ }
+
+ requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+}
+
+void SPHatchPath::build(SPDocument* doc, Inkscape::XML::Node* repr)
+{
+ SPObject::build(doc, repr);
+
+ readAttr("d");
+ readAttr("offset");
+ readAttr( "style" );
+
+ style->fill.setNone();
+}
+
+void SPHatchPath::release()
+{
+ for (ViewIterator iter = _display.begin(); iter != _display.end(); ++iter) {
+ delete iter->arenaitem;
+ iter->arenaitem = NULL;
+ }
+
+ SPObject::release();
+}
+
+void SPHatchPath::set(unsigned int key, const gchar* value)
+{
+ switch (key) {
+ case SP_ATTR_D:
+ if (value) {
+ Geom::PathVector pv;
+ _readHatchPathVector(value, pv, _continuous);
+ SPCurve *curve = new SPCurve(pv);
+
+ if (curve) {
+ setCurve(curve, true);
+ curve->unref();
+ }
+ } else {
+ setCurve(NULL, true);
+ }
+
+ requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+ break;
+
+ case SP_ATTR_OFFSET:
+ offset.readOrUnset(value);
+ requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+ break;
+
+ default:
+ if (SP_ATTRIBUTE_IS_CSS(key)) {
+ sp_style_read_from_object(style, this);
+ requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG);
+ } else {
+ SPObject::set(key, value);
+ }
+ break;
+ }
+}
+
+
+void SPHatchPath::update(SPCtx* ctx, unsigned int flags)
+{
+ if (flags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG | SP_OBJECT_VIEWPORT_MODIFIED_FLAG)) {
+ flags &= ~SP_OBJECT_USER_MODIFIED_FLAG_B;
+ }
+
+ if (flags & (SP_OBJECT_STYLE_MODIFIED_FLAG | SP_OBJECT_VIEWPORT_MODIFIED_FLAG)) {
+ if (style->stroke_width.unit == SP_CSS_UNIT_PERCENT) {
+ //TODO: Check specification
+
+ SPItemCtx *ictx = static_cast<SPItemCtx *>(ctx);
+ double const aw = (ictx) ? 1.0 / ictx->i2vp.descrim() : 1.0;
+ style->stroke_width.computed = style->stroke_width.value * aw;
+
+ for (ViewIterator iter = _display.begin(); iter != _display.end(); ++iter) {
+ iter->arenaitem->setStyle(style);
+ }
+ }
+ }
+
+ if (flags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_PARENT_MODIFIED_FLAG)) {
+ for (ViewIterator iter = _display.begin(); iter != _display.end(); ++iter) {
+ _updateView(*iter);
+ }
+ }
+}
+
+bool SPHatchPath::isValid() const
+{
+ if (_curve && (_repeatLength() <= 0)) {
+ return false;
+ } else {
+ return true;
+ }
+}
+
+Inkscape::DrawingItem *SPHatchPath::show(Inkscape::Drawing &drawing, unsigned int key, Geom::OptInterval extents)
+{
+ Inkscape::DrawingShape *s = new Inkscape::DrawingShape(drawing);
+ _display.push_front(View(s, key));
+ _display.front().extents = extents;
+
+ _updateView(_display.front());
+
+ return s;
+}
+
+void SPHatchPath::hide(unsigned int key)
+{
+ for (ViewIterator iter = _display.begin(); iter != _display.end(); ++iter) {
+ if (iter->key == key) {
+ delete iter->arenaitem;
+ _display.erase(iter);
+ return;
+ }
+ }
+
+ g_assert_not_reached();
+}
+
+void SPHatchPath::setStripExtents(unsigned int key, Geom::OptInterval const &extents)
+{
+ for (ViewIterator iter = _display.begin(); iter != _display.end(); ++iter) {
+ if (iter->key == key) {
+ iter->extents = extents;
+ break;
+ }
+ }
+}
+
+Geom::Interval SPHatchPath::bounds() const
+{
+ Geom::OptRect bbox;
+ Geom::Interval result;
+
+ Geom::Affine transform = Geom::Translate(offset.computed, 0);
+ if (!_curve) {
+ SPCurve test_curve;
+ test_curve.moveto(Geom::Point(0, 0));
+ test_curve.moveto(Geom::Point(0, 1));
+ bbox = bounds_exact_transformed(test_curve.get_pathvector(), transform);
+ } else {
+ bbox = bounds_exact_transformed(_curve->get_pathvector(), transform);
+ }
+
+ gdouble stroke_width = style->stroke_width.computed;
+ result.setMin(bbox->left() - stroke_width / 2);
+ result.setMax(bbox->right() + stroke_width / 2);
+ return result;
+}
+
+SPCurve *SPHatchPath::calculateRenderCurve(unsigned key) const
+{
+ for (ConstViewIterator iter = _display.begin(); iter != _display.end(); ++iter) {
+ if (iter->key == key) {
+ return _calculateRenderCurve(*iter);
+ }
+ }
+ g_assert_not_reached();
+ return NULL;
+}
+
+gdouble SPHatchPath::_repeatLength() const
+{
+ gdouble val = 0;
+
+ if (_curve && _curve->last_point()) {
+ val = _curve->last_point()->y();
+ }
+
+ return val;
+}
+
+void SPHatchPath::_updateView(View &view)
+{
+ SPCurve *calculated_curve = _calculateRenderCurve(view);
+
+ Geom::Affine offset_transform = Geom::Translate(offset.computed, 0);
+ view.arenaitem->setTransform(offset_transform);
+ style->fill.setNone();
+ view.arenaitem->setStyle(style);
+ view.arenaitem->setPath(calculated_curve);
+
+ calculated_curve->unref();
+}
+
+SPCurve *SPHatchPath::_calculateRenderCurve(View const &view) const
+{
+ SPCurve *calculated_curve = new SPCurve;
+
+ if (!view.extents) {
+ return calculated_curve;
+ }
+
+ if (!_curve) {
+ calculated_curve->moveto(0, view.extents->min());
+ calculated_curve->lineto(0, view.extents->max());
+ //TODO: if hatch has a dasharray defined, adjust line ends
+ } else {
+ gdouble repeatLength = _repeatLength();
+ if (repeatLength > 0) {
+ gdouble initial_y = floor(view.extents->min() / repeatLength) * repeatLength;
+ int segment_cnt = ceil((view.extents->extent()) / repeatLength) + 1;
+
+ SPCurve *segment =_curve->copy();
+ segment->transform(Geom::Translate(0, initial_y));
+
+ Geom::Affine step_transform = Geom::Translate(0, repeatLength);
+ for (int i = 0; i < segment_cnt; ++i) {
+ if (_continuous) {
+ calculated_curve->append_continuous(segment, 0.0625);
+ } else {
+ calculated_curve->append(segment, false);
+ }
+ segment->transform(step_transform);
+ }
+
+ segment->unref();
+ }
+ }
+ return calculated_curve;
+}
+
+
+void SPHatchPath::_readHatchPathVector(char const *str, Geom::PathVector &pathv, bool &continous_join)
+{
+ if (!str) {
+ return;
+ }
+
+ pathv = sp_svg_read_pathv(str);
+
+ if (!pathv.empty()) {
+ continous_join = false;
+ } else {
+ Glib::ustring str2 = Glib::ustring::compose("M0,0 %1", str);
+ pathv = sp_svg_read_pathv(str2.c_str());
+ if (pathv.empty()) {
+ return;
+ }
+
+ gdouble last_point_x = pathv.back().finalPoint().x();
+ Inkscape::CSSOStringStream stream;
+ stream << last_point_x;
+ Glib::ustring str3 = Glib::ustring::compose("M%1,0 %2", stream.str(), str);
+ Geom::PathVector pathv3 = sp_svg_read_pathv(str3.c_str());
+
+ //Path can be composed of relative commands only. In this case final point
+ //coordinates would depend on first point position. If this happens, fall
+ //back to using 0,0 as first path point
+ if (pathv3.back().finalPoint().y() == pathv.back().finalPoint().y()) {
+ pathv = pathv3;
+ }
+ continous_join = true;
+ }
+}
+
+SPHatchPath::View::View(Inkscape::DrawingShape *arenaitem, int key)
+ : arenaitem(arenaitem),
+ extents(),
+ key(key)
+{
+}
+
+SPHatchPath::View::~View()
+{
+ // remember, do not delete arenaitem here
+ arenaitem = NULL;
+}
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+ */
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/sp-hatch-path.h b/src/sp-hatch-path.h
new file mode 100644
index 000000000..11fc274ec
--- /dev/null
+++ b/src/sp-hatch-path.h
@@ -0,0 +1,95 @@
+/**
+ * @file
+ * SVG <hatchPath> implementation
+ */
+/*
+ * Author:
+ * Tomasz Boczkowski <penginsbacon@gmail.com>
+ * Jon A. Cruz <jon@joncruz.org>
+ *
+ * Copyright (C) 2014 Tomasz Boczkowski
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifndef SEEN_SP_HATCH_PATH_H
+#define SEEN_SP_HATCH_PATH_H
+
+#include <list>
+#include <stddef.h>
+#include <glibmm/ustring.h>
+#include <sigc++/connection.h>
+
+#include "svg/svg-length.h"
+
+namespace Inkscape {
+
+class Drawing;
+class DrawingShape;
+
+}
+
+class SPHatchPath : public SPObject {
+public:
+ SPHatchPath();
+ virtual ~SPHatchPath();
+
+ SVGLength offset;
+
+ void setCurve(SPCurve *curve, bool owner);
+
+ bool isValid() const;
+
+ Inkscape::DrawingItem *show(Inkscape::Drawing &drawing, unsigned int key, Geom::OptInterval extents);
+ void hide(unsigned int key);
+
+ void setStripExtents(unsigned int key, Geom::OptInterval const &extents);
+ Geom::Interval bounds() const;
+
+ SPCurve *calculateRenderCurve(unsigned key) const;
+
+protected:
+ virtual void build(SPDocument* doc, Inkscape::XML::Node* repr);
+ virtual void release();
+ virtual void set(unsigned int key, const gchar* value);
+ virtual void update(SPCtx* ctx, unsigned int flags);
+
+private:
+ class View {
+ public:
+ View(Inkscape::DrawingShape *arenaitem, int key);
+ //Do not delete arenaitem in destructor.
+
+ ~View();
+
+ Inkscape::DrawingShape *arenaitem;
+ Geom::OptInterval extents;
+ unsigned int key;
+ };
+
+ typedef std::list<SPHatchPath::View>::iterator ViewIterator;
+ typedef std::list<SPHatchPath::View>::const_iterator ConstViewIterator;
+ std::list<View> _display;
+
+ gdouble _repeatLength() const;
+ void _updateView(View &view);
+ SPCurve *_calculateRenderCurve(View const &view) const;
+
+ void _readHatchPathVector(char const *str, Geom::PathVector &pathv, bool &continous_join);
+
+ SPCurve *_curve;
+ bool _continuous;
+};
+
+#endif // SEEN_SP_HATCH_PATH_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/sp-hatch.cpp b/src/sp-hatch.cpp
new file mode 100644
index 000000000..4a8707e08
--- /dev/null
+++ b/src/sp-hatch.cpp
@@ -0,0 +1,756 @@
+/**
+ * @file
+ * SVG <hatch> implementation
+ */
+/*
+ * Authors:
+ * Tomasz Boczkowski <penginsbacon@gmail.com>
+ * Jon A. Cruz <jon@joncruz.org>
+ *
+ * Copyright (C) 2014 Tomasz Boczkowski
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <cstring>
+#include <string>
+#include <2geom/transforms.h>
+#include <sigc++/functors/mem_fun.h>
+
+#include "svg/svg.h"
+#include "display/cairo-utils.h"
+#include "display/drawing-context.h"
+#include "display/drawing-surface.h"
+#include "display/drawing.h"
+#include "display/drawing-pattern.h"
+#include "attributes.h"
+#include "document-private.h"
+#include "uri.h"
+#include "style.h"
+#include "sp-hatch.h"
+#include "sp-hatch-path.h"
+#include "xml/repr.h"
+
+#include "sp-factory.h"
+
+namespace {
+
+SPObject* createHatch() {
+ return new SPHatch();
+}
+
+bool hatchRegistered = SPFactory::instance().registerObject("svg:hatch", createHatch);
+
+} // namespace
+
+SPHatch::SPHatch()
+ : SPPaintServer(),
+ href(),
+ ref(NULL), // avoiding 'this' in initializer list
+ _hatchUnits(UNITS_OBJECTBOUNDINGBOX),
+ _hatchUnits_set(false),
+ _hatchContentUnits(UNITS_USERSPACEONUSE),
+ _hatchContentUnits_set(false),
+ _hatchTransform(Geom::identity()),
+ _hatchTransform_set(false),
+ _x(),
+ _y(),
+ _pitch(),
+ _rotate(),
+ _modified_connection(),
+ _display()
+{
+ ref = new SPHatchReference(this);
+ ref->changedSignal().connect(sigc::mem_fun(this, &SPHatch::_onRefChanged));
+
+ // TODO check that these should start already as unset:
+ _x.unset();
+ _y.unset();
+ _pitch.unset();
+ _rotate.unset();
+}
+
+SPHatch::~SPHatch() {
+}
+
+void SPHatch::build(SPDocument* doc, Inkscape::XML::Node* repr)
+{
+ SPPaintServer::build(doc, repr);
+
+ readAttr("hatchUnits");
+ readAttr("hatchContentUnits");
+ readAttr("hatchTransform");
+ readAttr("x");
+ readAttr("y");
+ readAttr("pitch");
+ readAttr("rotate");
+ readAttr("xlink:href");
+ readAttr( "style" );
+
+ // Register ourselves
+ doc->addResource("hatch", this);
+}
+
+void SPHatch::release()
+{
+ if (document) {
+ // Unregister ourselves
+ document->removeResource("hatch", this);
+ }
+
+ std::vector<SPHatchPath *> children(hatchPaths());
+ for (ViewIterator view_iter = _display.begin(); view_iter != _display.end(); ++view_iter) {
+ for (ChildIterator child_iter = children.begin(); child_iter != children.end(); ++child_iter) {
+ SPHatchPath *child = *child_iter;
+ child->hide(view_iter->key);
+ }
+ delete view_iter->arenaitem;
+ view_iter->arenaitem = NULL;
+ }
+
+ if (ref) {
+ _modified_connection.disconnect();
+ ref->detach();
+ delete ref;
+ ref = NULL;
+ }
+
+ SPPaintServer::release();
+}
+
+void SPHatch::child_added(Inkscape::XML::Node* child, Inkscape::XML::Node* ref)
+{
+ SPObject::child_added(child, ref);
+
+ SPHatchPath *path_child = dynamic_cast<SPHatchPath *>(document->getObjectByRepr(child));
+
+ if (path_child) {
+ for (ViewIterator iter = _display.begin(); iter != _display.end(); iter++) {
+ Geom::OptInterval extents = _calculateStripExtents(iter->bbox);
+ Inkscape::DrawingItem *ac = path_child->show(iter->arenaitem->drawing(), iter->key, extents);
+
+ path_child->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+ if (ac) {
+ iter->arenaitem->prependChild(ac);
+ }
+ }
+ }
+ //FIXME: notify all hatches that refer to this child set
+}
+
+void SPHatch::set(unsigned int key, const gchar* value)
+{
+ switch (key) {
+ case SP_ATTR_HATCHUNITS:
+ if (value) {
+ if (!strcmp(value, "userSpaceOnUse")) {
+ _hatchUnits = UNITS_USERSPACEONUSE;
+ } else {
+ _hatchUnits = UNITS_OBJECTBOUNDINGBOX;
+ }
+
+ _hatchUnits_set = true;
+ } else {
+ _hatchUnits_set = false;
+ }
+
+ requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+ break;
+
+ case SP_ATTR_HATCHCONTENTUNITS:
+ if (value) {
+ if (!strcmp(value, "userSpaceOnUse")) {
+ _hatchContentUnits = UNITS_USERSPACEONUSE;
+ } else {
+ _hatchContentUnits = UNITS_OBJECTBOUNDINGBOX;
+ }
+
+ _hatchContentUnits_set = true;
+ } else {
+ _hatchContentUnits_set = false;
+ }
+
+ requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+ break;
+
+ case SP_ATTR_HATCHTRANSFORM: {
+ Geom::Affine t;
+
+ if (value && sp_svg_transform_read(value, &t)) {
+ _hatchTransform = t;
+ _hatchTransform_set = true;
+ } else {
+ _hatchTransform = Geom::identity();
+ _hatchTransform_set = false;
+ }
+
+ requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+ break;
+ }
+ case SP_ATTR_X:
+ _x.readOrUnset(value);
+ requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+ break;
+
+ case SP_ATTR_Y:
+ _y.readOrUnset(value);
+ requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+ break;
+
+ case SP_ATTR_PITCH:
+ _pitch.readOrUnset(value);
+ requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+ break;
+
+ case SP_ATTR_ROTATE:
+ _rotate.readOrUnset(value);
+ requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+ break;
+
+ case SP_ATTR_XLINK_HREF:
+ if (value && href == value) {
+ // Href unchanged, do nothing.
+ } else {
+ href.clear();
+
+ if (value) {
+ // First, set the href field; it's only used in the "unchanged" check above.
+ href = value;
+ // Now do the attaching, which emits the changed signal.
+ if (value) {
+ try {
+ ref->attach(Inkscape::URI(value));
+ } catch (Inkscape::BadURIException &e) {
+ g_warning("%s", e.what());
+ ref->detach();
+ }
+ } else {
+ ref->detach();
+ }
+ }
+ }
+ requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+ break;
+
+ default:
+ if (SP_ATTRIBUTE_IS_CSS(key)) {
+ sp_style_read_from_object(style, this);
+ requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG);
+ } else {
+ SPPaintServer::set(key, value);
+ }
+ break;
+ }
+}
+
+bool SPHatch::_hasHatchPatchChildren(SPHatch const *hatch)
+{
+ bool matched = false;
+ for (SPObject const *child = hatch->firstChild(); child && !matched; child = child->getNext() ) {
+ SPHatchPath const *hatchPath = dynamic_cast<SPHatchPath const *>(child);
+ if (hatchPath) {
+ matched = true;
+ }
+ }
+ return matched;
+}
+
+std::vector<SPHatchPath*> SPHatch::hatchPaths()
+{
+ std::vector<SPHatchPath*> list;
+ SPHatch *src = chase_hrefs<SPHatch>(this, sigc::ptr_fun(&_hasHatchPatchChildren));
+
+ if (src) {
+ for (SPObject *child = src->firstChild(); child; child = child->getNext()) {
+ SPHatchPath *hatchPath = dynamic_cast<SPHatchPath *>(child);
+ if (hatchPath) {
+ list.push_back(hatchPath);
+ }
+ }
+ }
+ return list;
+}
+
+std::vector<SPHatchPath const*> SPHatch::hatchPaths() const
+{
+ std::vector<SPHatchPath const*> list;
+ SPHatch const *src = chase_hrefs<SPHatch const>(this, sigc::ptr_fun(&_hasHatchPatchChildren));
+
+ if (src) {
+ for (SPObject const *child = src->firstChild(); child; child = child->getNext()) {
+ SPHatchPath const *hatchPath = dynamic_cast<SPHatchPath const*>(child);
+ if (hatchPath) {
+ list.push_back(hatchPath);
+ }
+ }
+ }
+ return list;
+}
+
+// TODO: ::remove_child and ::order_changed handles - see SPPattern
+
+
+void SPHatch::update(SPCtx* ctx, unsigned int flags)
+{
+ typedef std::list<SPHatch::View>::iterator ViewIterator;
+
+ if (flags & SP_OBJECT_MODIFIED_FLAG) {
+ flags |= SP_OBJECT_PARENT_MODIFIED_FLAG;
+ }
+
+ flags &= SP_OBJECT_MODIFIED_CASCADE;
+
+ std::vector<SPHatchPath *> children(hatchPaths());
+
+ for (ChildIterator iter = children.begin(); iter != children.end(); ++iter) {
+ SPHatchPath* child = *iter;
+
+ sp_object_ref(child, NULL);
+
+ for (ViewIterator view_iter = _display.begin(); view_iter != _display.end(); ++view_iter) {
+ Geom::OptInterval strip_extents = _calculateStripExtents(view_iter->bbox);
+ child->setStripExtents(view_iter->key, strip_extents);
+ }
+
+ if (flags || (child->mflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) {
+
+ child->updateDisplay(ctx, flags);
+ }
+
+ sp_object_unref(child, NULL);
+ }
+
+ for (ViewIterator iter = _display.begin(); iter != _display.end(); ++iter) {
+ _updateView(*iter);
+ }
+}
+
+void SPHatch::modified(unsigned int flags)
+{
+ if (flags & SP_OBJECT_MODIFIED_FLAG) {
+ flags |= SP_OBJECT_PARENT_MODIFIED_FLAG;
+ }
+
+ flags &= SP_OBJECT_MODIFIED_CASCADE;
+
+ std::vector<SPHatchPath *> children(hatchPaths());
+
+ for (ChildIterator iter = children.begin(); iter != children.end(); ++iter) {
+ SPObject *child = *iter;
+
+ sp_object_ref(child, NULL);
+
+ if (flags || (child->mflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) {
+ child->emitModified(flags);
+ }
+
+ sp_object_unref(child, NULL);
+ }
+}
+
+void SPHatch::_onRefChanged(SPObject *old_ref, SPObject *ref)
+{
+ typedef std::list<SPHatch::View>::iterator ViewIterator;
+
+ if (old_ref) {
+ _modified_connection.disconnect();
+ }
+
+ SPHatch *hatch = dynamic_cast<SPHatch *>(ref);
+ if (hatch) {
+ _modified_connection = ref->connectModified(sigc::mem_fun(this, &SPHatch::_onRefModified));
+ }
+
+ if (!_hasHatchPatchChildren(this)) {
+ SPHatch *old_shown = NULL;
+ SPHatch *new_shown = NULL;
+ std::vector<SPHatchPath *> oldhatchPaths;
+ std::vector<SPHatchPath *> newhatchPaths;
+
+ SPHatch *old_hatch = dynamic_cast<SPHatch *>(old_ref);
+ if (old_hatch) {
+ old_shown = old_hatch->rootHatch();
+ oldhatchPaths = old_shown->hatchPaths();
+ }
+ if (hatch) {
+ new_shown = hatch->rootHatch();
+ newhatchPaths = new_shown->hatchPaths();
+ }
+ if (old_shown != new_shown) {
+
+ for (ViewIterator iter = _display.begin(); iter != _display.end(); ++iter) {
+ Geom::OptInterval extents = _calculateStripExtents(iter->bbox);
+
+ for (ChildIterator child_iter = oldhatchPaths.begin(); child_iter != oldhatchPaths.end(); ++child_iter) {
+ SPHatchPath *child = *child_iter;
+ child->hide(iter->key);
+ }
+ for (ChildIterator child_iter = newhatchPaths.begin(); child_iter != newhatchPaths.end(); ++child_iter) {
+ SPHatchPath *child = *child_iter;
+ Inkscape::DrawingItem *cai = child->show(iter->arenaitem->drawing(), iter->key, extents);
+ child->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+ if (cai) {
+ iter->arenaitem->appendChild(cai);
+ }
+
+ }
+ }
+ }
+ }
+
+ _onRefModified(ref, 0);
+}
+
+void SPHatch::_onRefModified(SPObject */*ref*/, guint /*flags*/)
+{
+ requestModified(SP_OBJECT_MODIFIED_FLAG);
+ // Conditional to avoid causing infinite loop if there's a cycle in the href chain.
+}
+
+
+SPHatch *SPHatch::rootHatch()
+{
+ SPHatch *src = chase_hrefs<SPHatch>(this, sigc::ptr_fun(&_hasHatchPatchChildren));
+ return src ? src : this; // document is broken, we can't get to root; but at least we can return pat which is supposedly a valid hatch
+}
+
+// Access functions that look up fields up the chain of referenced hatchs and return the first one which is set
+// FIXME: all of them must use chase_hrefs as children() and rootHatch()
+
+SPHatch::HatchUnits SPHatch::hatchUnits() const
+{
+ HatchUnits units = _hatchUnits;
+ for (SPHatch const *pat_i = this; pat_i; pat_i = (pat_i->ref) ? pat_i->ref->getObject() : NULL) {
+ if (pat_i->_hatchUnits_set) {
+ units = pat_i->_hatchUnits;
+ break;
+ }
+ }
+ return units;
+}
+
+SPHatch::HatchUnits SPHatch::hatchContentUnits() const
+{
+ HatchUnits units = _hatchContentUnits;
+ for (SPHatch const *pat_i = this; pat_i; pat_i = (pat_i->ref) ? pat_i->ref->getObject() : NULL) {
+ if (pat_i->_hatchContentUnits_set) {
+ units = pat_i->_hatchContentUnits;
+ break;
+ }
+ }
+ return units;
+}
+
+Geom::Affine const &SPHatch::hatchTransform() const
+{
+ for (SPHatch const *pat_i = this; pat_i; pat_i = (pat_i->ref) ? pat_i->ref->getObject() : NULL) {
+ if (pat_i->_hatchTransform_set) {
+ return pat_i->_hatchTransform;
+ }
+ }
+ return _hatchTransform;
+}
+
+gdouble SPHatch::x() const
+{
+ gdouble val = 0;
+ for (SPHatch const *pat_i = this; pat_i; pat_i = (pat_i->ref) ? pat_i->ref->getObject() : NULL) {
+ if (pat_i->_x._set) {
+ val = pat_i->_x.computed;
+ break;
+ }
+ }
+ return val;
+}
+
+gdouble SPHatch::y() const
+{
+ gdouble val = 0;
+ for (SPHatch const *pat_i = this; pat_i; pat_i = (pat_i->ref) ? pat_i->ref->getObject() : NULL) {
+ if (pat_i->_y._set) {
+ val = pat_i->_y.computed;
+ break;
+ }
+ }
+ return val;
+}
+
+gdouble SPHatch::pitch() const
+{
+ gdouble val = 0;
+ for (SPHatch const *pat_i = this; pat_i; pat_i = (pat_i->ref) ? pat_i->ref->getObject() : NULL) {
+ if (pat_i->_pitch._set) {
+ val = pat_i->_pitch.computed;
+ break;
+ }
+ }
+ return val;
+}
+
+gdouble SPHatch::rotate() const
+{
+ gdouble val = 0;
+ for (SPHatch const *pat_i = this; pat_i; pat_i = (pat_i->ref) ? pat_i->ref->getObject() : NULL) {
+ if (pat_i->_rotate._set) {
+ val = pat_i->_rotate.computed;
+ break;
+ }
+ }
+ return val;
+}
+
+bool SPHatch::isValid() const
+{
+ bool valid = false;
+
+ if (pitch() > 0) {
+ std::vector<SPHatchPath const *> children(hatchPaths());
+ if (!children.empty()) {
+ valid = true;
+ for (ConstChildIterator iter = children.begin(); (iter != children.end()) && valid; ++iter) {
+ SPHatchPath const *child = *iter;
+ valid = child->isValid();
+ }
+ }
+ }
+
+ return valid;
+}
+
+Inkscape::DrawingPattern *SPHatch::show(Inkscape::Drawing &drawing, unsigned int key, Geom::OptRect bbox)
+{
+ Inkscape::DrawingPattern *ai = new Inkscape::DrawingPattern(drawing);
+ //TODO: set some debug flag to see DrawingPattern
+ _display.push_front(View(ai, key));
+ _display.front().bbox = bbox;
+
+ std::vector<SPHatchPath *> children(hatchPaths());
+
+ Geom::OptInterval extents = _calculateStripExtents(bbox);
+ for (ChildIterator iter = children.begin(); iter != children.end(); ++iter) {
+ SPHatchPath *child = *iter;
+ Inkscape::DrawingItem *cai = child->show(drawing, key, extents);
+ if (cai) {
+ ai->appendChild(cai);
+ }
+ }
+
+ View& view = _display.front();
+ _updateView(view);
+
+ return ai;
+}
+
+void SPHatch::hide(unsigned int key)
+{
+ std::vector<SPHatchPath *> children(hatchPaths());
+
+ for (ChildIterator iter = children.begin(); iter != children.end(); ++iter) {
+ SPHatchPath *child = *iter;
+ child->hide(key);
+ }
+
+ for (ViewIterator iter = _display.begin(); iter != _display.end(); ++iter) {
+ if (iter->key == key) {
+ delete iter->arenaitem;
+ _display.erase(iter);
+ return;
+ }
+ }
+
+ g_assert_not_reached();
+}
+
+
+Geom::Interval SPHatch::bounds() const
+{
+ Geom::Interval result;
+ std::vector<SPHatchPath const *> children(hatchPaths());
+
+ for (ConstChildIterator iter = children.begin(); iter != children.end(); ++iter) {
+ SPHatchPath const *child = *iter;
+ if (result.extent() == 0) {
+ result = child->bounds();
+ } else {
+ result |= child->bounds();
+ }
+ }
+ return result;
+}
+
+SPHatch::RenderInfo SPHatch::calculateRenderInfo(unsigned key) const
+{
+ RenderInfo info;
+ for (ConstViewIterator iter = _display.begin(); iter != _display.end(); ++iter) {
+ if (iter->key == key) {
+ return _calculateRenderInfo(*iter);
+ }
+ }
+ g_assert_not_reached();
+ return info;
+}
+
+void SPHatch::_updateView(View &view)
+{
+ RenderInfo info = _calculateRenderInfo(view);
+ //The rendering of hatch overflow is implemented by repeated drawing
+ //of hatch paths over one strip. Within each iteration paths are moved by pitch value.
+ //The movement progresses from right to left. This gives the same result
+ //as drawing whole strips in left-to-right order.
+
+
+ view.arenaitem->setChildTransform(info.child_transform);
+ view.arenaitem->setPatternToUserTransform(info.pattern_to_user_transform);
+ view.arenaitem->setTileRect(info.tile_rect);
+ view.arenaitem->setStyle(style);
+ view.arenaitem->setOverflow(info.overflow_initial_transform, info.overflow_steps,
+ info.overflow_step_transform);
+}
+
+SPHatch::RenderInfo SPHatch::_calculateRenderInfo(View const &view) const
+{
+ RenderInfo info;
+
+ Geom::OptInterval extents = _calculateStripExtents(view.bbox);
+ if (extents) {
+ double tile_x = x();
+ double tile_y = y();
+ double tile_width = pitch();
+ double tile_height = extents->max() - extents->min();
+ double tile_rotate = rotate();
+ double tile_render_y = extents->min();
+
+ if (view.bbox && (hatchUnits() == UNITS_OBJECTBOUNDINGBOX)) {
+ tile_x *= view.bbox->width();
+ tile_y *= view.bbox->height();
+ tile_width *= view.bbox->width();
+ tile_height *= view.bbox->height();
+ tile_render_y *= view.bbox->height();
+ }
+
+ // Pattern size in hatch space
+ Geom::Rect hatch_tile = Geom::Rect::from_xywh(0, tile_render_y, tile_width, tile_height);
+
+ // Content to bbox
+ Geom::Affine content2ps;
+ if (view.bbox && (hatchContentUnits() == UNITS_OBJECTBOUNDINGBOX)) {
+ content2ps = Geom::Affine(view.bbox->width(), 0.0, 0.0, view.bbox->height(), 0, 0);
+ }
+
+ // Tile (hatch space) to user.
+ Geom::Affine ps2user = Geom::Translate(tile_x, tile_y) * Geom::Rotate::from_degrees(tile_rotate) * hatchTransform();
+
+ info.child_transform = content2ps;
+ info.pattern_to_user_transform = ps2user;
+ info.tile_rect = hatch_tile;
+
+ if (style->overflow.computed == SP_CSS_OVERFLOW_VISIBLE) {
+ Geom::Interval bounds = this->bounds();
+ gdouble pitch = this->pitch();
+ gdouble overflow_right_strip = floor(bounds.max() / pitch) * pitch;
+ info.overflow_steps = ceil((overflow_right_strip - bounds.min()) / pitch) + 1;
+ info.overflow_step_transform = Geom::Translate(pitch, 0.0);
+ info.overflow_initial_transform = Geom::Translate(-overflow_right_strip, 0.0);
+ } else {
+ info.overflow_steps = 1;
+ }
+ }
+
+ return info;
+}
+
+//calculates strip extents in content space
+Geom::OptInterval SPHatch::_calculateStripExtents(Geom::OptRect const &bbox) const
+{
+ if (!bbox || (bbox->area() == 0)) {
+ return Geom::OptInterval();
+ } else {
+ double tile_x = x();
+ double tile_y = y();
+ double tile_rotate = rotate();
+
+ Geom::Affine ps2user = Geom::Translate(tile_x, tile_y) * Geom::Rotate::from_degrees(tile_rotate) * hatchTransform();
+ Geom::Affine user2ps = ps2user.inverse();
+
+ Geom::Interval extents;
+ for (int i = 0; i < 4; ++i) {
+ Geom::Point corner = bbox->corner(i);
+ Geom::Point corner_ps = corner * user2ps;
+ if (i == 0 || corner_ps.y() < extents.min()) {
+ extents.setMin(corner_ps.y());
+ }
+ if (i == 0 || corner_ps.y() > extents.max()) {
+ extents.setMax(corner_ps.y());
+ }
+ }
+
+ if (hatchUnits() == UNITS_OBJECTBOUNDINGBOX) {
+ extents /= bbox->height();
+ }
+
+ return extents;
+ }
+}
+
+cairo_pattern_t* SPHatch::pattern_new(cairo_t * /*base_ct*/, Geom::OptRect const &/*bbox*/, double /*opacity*/)
+{
+ //this code should not be used
+ //it is however required by the fact that SPPaintServer::hatch_new is pure virtual
+ return cairo_pattern_create_rgb(0.5, 0.5, 1.0);
+}
+
+void SPHatch::setBBox(unsigned int key, Geom::OptRect const &bbox)
+{
+ for (ViewIterator iter = _display.begin(); iter != _display.end(); ++iter) {
+ if (iter->key == key) {
+ iter->bbox = bbox;
+ break;
+ }
+ }
+}
+
+//
+
+SPHatch::RenderInfo::RenderInfo()
+ : child_transform(),
+ pattern_to_user_transform(),
+ tile_rect(),
+ overflow_steps(0),
+ overflow_step_transform(),
+ overflow_initial_transform()
+{
+}
+
+SPHatch::RenderInfo::~RenderInfo()
+{
+}
+
+//
+
+SPHatch::View::View(Inkscape::DrawingPattern *arenaitem, int key)
+ : arenaitem(arenaitem),
+ bbox(),
+ key(key)
+{
+}
+
+SPHatch::View::~View()
+{
+ // remember, do not delete arenaitem here
+ arenaitem = NULL;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+ */
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/sp-hatch.h b/src/sp-hatch.h
new file mode 100644
index 000000000..5004a611f
--- /dev/null
+++ b/src/sp-hatch.h
@@ -0,0 +1,186 @@
+/**
+ * @file
+ * SVG <hatch> implementation
+ */
+/*
+ * Authors:
+ * Tomasz Boczkowski <penginsbacon@gmail.com>
+ * Jon A. Cruz <jon@joncruz.org>
+ *
+ * Copyright (C) 2014 Tomasz Boczkowski
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifndef SEEN_SP_HATCH_H
+#define SEEN_SP_HATCH_H
+
+#include <list>
+#include <stddef.h>
+#include <glibmm/ustring.h>
+#include <sigc++/connection.h>
+
+#include "svg/svg-length.h"
+#include "svg/svg-angle.h"
+#include "sp-paint-server.h"
+#include "uri-references.h"
+
+class SPHatchReference;
+class SPHatchPath;
+class SPItem;
+
+namespace Inkscape {
+
+class Drawing;
+class DrawingPattern;
+
+namespace XML {
+
+class Node;
+
+}
+}
+
+class SPHatch : public SPPaintServer {
+public:
+ enum HatchUnits {
+ UNITS_USERSPACEONUSE,
+ UNITS_OBJECTBOUNDINGBOX
+ };
+
+ class RenderInfo {
+ public:
+ RenderInfo();
+ ~RenderInfo();
+
+ Geom::Affine child_transform;
+ Geom::Affine pattern_to_user_transform;
+ Geom::Rect tile_rect;
+
+ int overflow_steps;
+ Geom::Affine overflow_step_transform;
+ Geom::Affine overflow_initial_transform;
+ };
+
+ SPHatch();
+ virtual ~SPHatch();
+
+ // Reference (href)
+ Glib::ustring href;
+ SPHatchReference *ref;
+
+ gdouble x() const;
+ gdouble y() const;
+ gdouble pitch() const;
+ gdouble rotate() const;
+ HatchUnits hatchUnits() const;
+ HatchUnits hatchContentUnits() const;
+ Geom::Affine const &hatchTransform() const;
+ SPHatch *rootHatch(); //TODO: const
+
+ std::vector<SPHatchPath *> hatchPaths();
+ std::vector<SPHatchPath const *> hatchPaths() const;
+
+ bool isValid() const;
+
+ Inkscape::DrawingPattern *show(Inkscape::Drawing &drawing, unsigned int key, Geom::OptRect bbox);
+ void hide(unsigned int key);
+ virtual cairo_pattern_t* pattern_new(cairo_t *ct, Geom::OptRect const &bbox, double opacity);
+
+ RenderInfo calculateRenderInfo(unsigned key) const;
+ Geom::Interval bounds() const;
+ void setBBox(unsigned int key, Geom::OptRect const &bbox);
+
+protected:
+ virtual void build(SPDocument* doc, Inkscape::XML::Node* repr);
+ virtual void release();
+ virtual void child_added(Inkscape::XML::Node* child, Inkscape::XML::Node* ref);
+ virtual void set(unsigned int key, const gchar* value);
+ virtual void update(SPCtx* ctx, unsigned int flags);
+ virtual void modified(unsigned int flags);
+
+private:
+ class View {
+ public:
+ View(Inkscape::DrawingPattern *arenaitem, int key);
+ //Do not delete arenaitem in destructor.
+
+ ~View();
+
+ Inkscape::DrawingPattern *arenaitem;
+ Geom::OptRect bbox;
+ unsigned int key;
+ };
+
+ typedef std::vector<SPHatchPath *>::iterator ChildIterator;
+ typedef std::vector<SPHatchPath const *>::const_iterator ConstChildIterator;
+ typedef std::list<View>::iterator ViewIterator;
+ typedef std::list<View>::const_iterator ConstViewIterator;
+
+ static bool _hasHatchPatchChildren(SPHatch const* hatch);
+
+ void _updateView(View &view);
+ RenderInfo _calculateRenderInfo(View const &view) const;
+ Geom::OptInterval _calculateStripExtents(Geom::OptRect const &bbox) const;
+
+
+ /**
+ * Gets called when the hatch is reattached to another <hatch>
+ */
+ void _onRefChanged(SPObject *old_ref, SPObject *ref);
+
+ /**
+ * Gets called when the referenced <hatch> is changed
+ */
+ void _onRefModified(SPObject *ref, guint flags);
+
+ // patternUnits and patternContentUnits attribute
+ HatchUnits _hatchUnits : 1;
+ bool _hatchUnits_set : 1;
+ HatchUnits _hatchContentUnits : 1;
+ bool _hatchContentUnits_set : 1;
+
+ // hatchTransform attribute
+ Geom::Affine _hatchTransform;
+ bool _hatchTransform_set : 1;
+
+ // Strip
+ SVGLength _x;
+ SVGLength _y;
+ SVGLength _pitch;
+ SVGAngle _rotate;
+
+ sigc::connection _modified_connection;
+
+ std::list<View> _display;
+};
+
+
+class SPHatchReference : public Inkscape::URIReference {
+public:
+ SPHatchReference (SPObject *obj)
+ : URIReference(obj)
+ {}
+
+ SPHatch *getObject() const {
+ return reinterpret_cast<SPHatch *>(URIReference::getObject());
+ }
+
+protected:
+ virtual bool _acceptObject(SPObject *obj) const {
+ return dynamic_cast<SPHatch *>(obj) != NULL;
+ }
+};
+
+#endif // SEEN_SP_HATCH_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/sp-image.cpp b/src/sp-image.cpp
index cb8ede2b2..b6177fae6 100644
--- a/src/sp-image.cpp
+++ b/src/sp-image.cpp
@@ -20,6 +20,7 @@
#include <cstring>
#include <algorithm>
#include <string>
+#include <glibmm.h>
#include <glib/gstdio.h>
#include <2geom/rect.h>
#include <2geom/transforms.h>
diff --git a/src/sp-image.h b/src/sp-image.h
index 17262d74f..9fa33b5de 100644
--- a/src/sp-image.h
+++ b/src/sp-image.h
@@ -14,7 +14,6 @@
#ifndef SEEN_INKSCAPE_SP_IMAGE_H
#define SEEN_INKSCAPE_SP_IMAGE_H
-#include <gdk-pixbuf/gdk-pixbuf.h>
#include <glibmm/ustring.h>
#include "svg/svg-length.h"
#include "display/curve.h"
@@ -43,24 +42,24 @@ public:
SPCurve *curve; // This curve is at the image's boundary for snapping
- gchar *href;
+ char *href;
#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
- gchar *color_profile;
+ char *color_profile;
#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
Inkscape::Pixbuf *pixbuf;
virtual void build(SPDocument *document, Inkscape::XML::Node *repr);
virtual void release();
- virtual void set(unsigned int key, gchar const* value);
- virtual void update(SPCtx *ctx, guint flags);
- virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags);
+ virtual void set(unsigned int key, char const* value);
+ virtual void update(SPCtx *ctx, unsigned int flags);
+ virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags);
virtual void modified(unsigned int flags);
virtual Geom::OptRect bbox(Geom::Affine const &transform, SPItem::BBoxType type) const;
virtual void print(SPPrintContext *ctx);
virtual const char* displayName() const;
- virtual gchar* description() const;
+ virtual char* description() const;
virtual Inkscape::DrawingItem* show(Inkscape::Drawing &drawing, unsigned int key, unsigned int flags);
virtual void snappoints(std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs) const;
virtual Geom::Affine set_transform(Geom::Affine const &transform);
diff --git a/src/sp-item-group.cpp b/src/sp-item-group.cpp
index 2cfe97db8..992bca631 100644
--- a/src/sp-item-group.cpp
+++ b/src/sp-item-group.cpp
@@ -70,11 +70,9 @@ namespace {
SPGroup::SPGroup() : SPLPEItem() {
this->_layer_mode = SPGroup::GROUP;
- //new (&this->_display_modes) std::map<unsigned int, SPGroup::LayerMode>();
}
SPGroup::~SPGroup() {
- //this->_display_modes.~map();
}
void SPGroup::build(SPDocument *document, Inkscape::XML::Node *repr) {
@@ -98,14 +96,14 @@ void SPGroup::child_added(Inkscape::XML::Node* child, Inkscape::XML::Node* ref)
if (last_child && last_child->getRepr() == child) {
// optimization for the common special case where the child is being added at the end
- SPObject *ochild = last_child;
- if ( SP_IS_ITEM(ochild) ) {
+ SPItem *item = dynamic_cast<SPItem *>(last_child);
+ if ( item ) {
/* TODO: this should be moved into SPItem somehow */
SPItemView *v;
Inkscape::DrawingItem *ac;
for (v = this->display; v != NULL; v = v->next) {
- ac = SP_ITEM (ochild)->invoke_show (v->arenaitem->drawing(), v->key, v->flags);
+ ac = item->invoke_show (v->arenaitem->drawing(), v->key, v->flags);
if (ac) {
v->arenaitem->appendChild(ac);
@@ -113,16 +111,16 @@ void SPGroup::child_added(Inkscape::XML::Node* child, Inkscape::XML::Node* ref)
}
}
} else { // general case
- SPObject *ochild = this->get_child_by_repr(child);
- if ( ochild && SP_IS_ITEM(ochild) ) {
+ SPItem *item = dynamic_cast<SPItem *>(get_child_by_repr(child));
+ if ( item ) {
/* TODO: this should be moved into SPItem somehow */
SPItemView *v;
Inkscape::DrawingItem *ac;
- unsigned position = SP_ITEM(ochild)->pos_in_parent();
+ unsigned position = item->pos_in_parent();
for (v = this->display; v != NULL; v = v->next) {
- ac = SP_ITEM (ochild)->invoke_show (v->arenaitem->drawing(), v->key, v->flags);
+ ac = item->invoke_show (v->arenaitem->drawing(), v->key, v->flags);
if (ac) {
v->arenaitem->prependChild(ac);
@@ -147,12 +145,12 @@ void SPGroup::order_changed (Inkscape::XML::Node *child, Inkscape::XML::Node *ol
{
SPLPEItem::order_changed(child, old_ref, new_ref);
- SPObject *ochild = this->get_child_by_repr(child);
- if ( ochild && SP_IS_ITEM(ochild) ) {
+ SPItem *item = dynamic_cast<SPItem *>(get_child_by_repr(child));
+ if ( item ) {
/* TODO: this should be moved into SPItem somehow */
SPItemView *v;
- unsigned position = SP_ITEM(ochild)->pos_in_parent();
- for ( v = SP_ITEM (ochild)->display ; v != NULL ; v = v->next ) {
+ unsigned position = item->pos_in_parent();
+ for ( v = item->display ; v != NULL ; v = v->next ) {
v->arenaitem->setZOrder(position);
}
}
@@ -179,10 +177,10 @@ void SPGroup::update(SPCtx *ctx, unsigned int flags) {
l = g_slist_remove (l, child);
if (childflags || (child->uflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) {
- if (SP_IS_ITEM (child)) {
- SPItem const &chi = *SP_ITEM(child);
- cctx.i2doc = chi.transform * ictx->i2doc;
- cctx.i2vp = chi.transform * ictx->i2vp;
+ SPItem *item = dynamic_cast<SPItem *>(child);
+ if (item) {
+ cctx.i2doc = item->transform * ictx->i2doc;
+ cctx.i2vp = item->transform * ictx->i2vp;
child->updateDisplay((SPCtx *)&cctx, childflags);
} else {
child->updateDisplay(ctx, childflags);
@@ -232,14 +230,11 @@ void SPGroup::modified(guint flags) {
}
Inkscape::XML::Node* SPGroup::write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags) {
- SPGroup* object = this;
- SPGroup *group = SP_GROUP(object);
-
if (flags & SP_OBJECT_WRITE_BUILD) {
- GSList *l;
+ GSList *l = NULL;
if (!repr) {
- if (SP_IS_SWITCH(object)) {
+ if (dynamic_cast<SPSwitch *>(this)) {
repr = xml_doc->createElement("svg:switch");
} else {
repr = xml_doc->createElement("svg:g");
@@ -248,8 +243,8 @@ Inkscape::XML::Node* SPGroup::write(Inkscape::XML::Document *xml_doc, Inkscape::
l = NULL;
- for (SPObject *child = object->firstChild(); child; child = child->getNext() ) {
- if ( !SP_IS_TITLE(child) && !SP_IS_DESC(child) ) {
+ for (SPObject *child = firstChild(); child; child = child->getNext() ) {
+ if ( !dynamic_cast<SPTitle *>(child) && !dynamic_cast<SPDesc *>(child) ) {
Inkscape::XML::Node *crepr = child->updateRepr(xml_doc, NULL, flags);
if (crepr) {
@@ -264,8 +259,8 @@ Inkscape::XML::Node* SPGroup::write(Inkscape::XML::Document *xml_doc, Inkscape::
l = g_slist_remove (l, l->data);
}
} else {
- for (SPObject *child = object->firstChild() ; child ; child = child->getNext() ) {
- if ( !SP_IS_TITLE(child) && !SP_IS_DESC(child) ) {
+ for (SPObject *child = firstChild() ; child ; child = child->getNext() ) {
+ if ( !dynamic_cast<SPTitle *>(child) && !dynamic_cast<SPDesc *>(child) ) {
child->updateRepr(flags);
}
}
@@ -273,9 +268,9 @@ Inkscape::XML::Node* SPGroup::write(Inkscape::XML::Document *xml_doc, Inkscape::
if ( flags & SP_OBJECT_WRITE_EXT ) {
const char *value;
- if ( group->_layer_mode == SPGroup::LAYER ) {
+ if ( _layer_mode == SPGroup::LAYER ) {
value = "layer";
- } else if ( group->_layer_mode == SPGroup::MASK_HELPER ) {
+ } else if ( _layer_mode == SPGroup::MASK_HELPER ) {
value = "maskhelper";
} else if ( flags & SP_OBJECT_WRITE_ALL ) {
value = "group";
@@ -295,16 +290,16 @@ Geom::OptRect SPGroup::bbox(Geom::Affine const &transform, SPItem::BBoxType bbox
{
Geom::OptRect bbox;
- // CPPIFY: replace this const_cast later
+ // TODO CPPIFY: replace this const_cast later
GSList *l = const_cast<SPGroup*>(this)->childList(false, SPObject::ActionBBox);
while (l) {
SPObject *o = SP_OBJECT (l->data);
- if (SP_IS_ITEM(o) && !SP_ITEM(o)->isHidden()) {
- SPItem *child = SP_ITEM(o);
- Geom::Affine const ct(child->transform * transform);
- bbox |= child->bounds(bboxtype, ct);
+ SPItem *item = dynamic_cast<SPItem *>(o);
+ if (item && !item->isHidden()) {
+ Geom::Affine const ct(item->transform * transform);
+ bbox |= item->bounds(bboxtype, ct);
}
l = g_slist_remove (l, o);
@@ -319,8 +314,9 @@ void SPGroup::print(SPPrintContext *ctx) {
while (l) {
SPObject *o = SP_OBJECT (l->data);
- if (SP_IS_ITEM(o)) {
- SP_ITEM(o)->invoke_print (ctx);
+ SPItem *item = dynamic_cast<SPItem *>(o);
+ if (item) {
+ item->invoke_print(ctx);
}
l = g_slist_remove (l, o);
@@ -367,16 +363,14 @@ Inkscape::DrawingItem *SPGroup::show (Inkscape::Drawing &drawing, unsigned int k
}
void SPGroup::hide (unsigned int key) {
- SPItem * child;
-
GSList *l = g_slist_reverse(this->childList(false, SPObject::ActionShow));
while (l) {
SPObject *o = SP_OBJECT (l->data);
- if (SP_IS_ITEM (o)) {
- child = SP_ITEM (o);
- child->invoke_hide (key);
+ SPItem *item = dynamic_cast<SPItem *>(o);
+ if (item) {
+ item->invoke_hide(key);
}
l = g_slist_remove (l, o);
@@ -389,8 +383,9 @@ void SPGroup::hide (unsigned int key) {
void SPGroup::snappoints(std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs) const {
for ( SPObject const *o = this->firstChild(); o; o = o->getNext() )
{
- if (SP_IS_ITEM(o)) {
- SP_ITEM(o)->getSnappoints(p, snapprefs);
+ SPItem const *item = dynamic_cast<SPItem const *>(o);
+ if (item) {
+ item->getSnappoints(p, snapprefs);
}
}
}
@@ -400,14 +395,12 @@ void
sp_item_group_ungroup (SPGroup *group, GSList **children, bool do_done)
{
g_return_if_fail (group != NULL);
- g_return_if_fail (SP_IS_GROUP (group));
SPDocument *doc = group->document;
SPRoot *root = doc->getRoot();
SPObject *defs = root->defs;
- SPItem *gitem = group;
- Inkscape::XML::Node *grepr = gitem->getRepr();
+ Inkscape::XML::Node *grepr = group->getRepr();
g_return_if_fail (!strcmp (grepr->name(), "svg:g")
|| !strcmp (grepr->name(), "svg:a")
@@ -415,33 +408,34 @@ sp_item_group_ungroup (SPGroup *group, GSList **children, bool do_done)
|| !strcmp (grepr->name(), "svg:svg"));
// this converts the gradient/pattern fill/stroke on the group, if any, to userSpaceOnUse
- gitem->adjust_paint_recursive (Geom::identity(), Geom::identity(), false);
+ group->adjust_paint_recursive (Geom::identity(), Geom::identity(), false);
- SPItem *pitem = SP_ITEM(gitem->parent);
+ SPItem *pitem = dynamic_cast<SPItem *>(group->parent);
+ g_assert(pitem);
Inkscape::XML::Node *prepr = pitem->getRepr();
- if (SP_IS_BOX3D(gitem)) {
- group = box3d_convert_to_group(SP_BOX3D(gitem));
- gitem = group;
- }
+ {
+ SPBox3D *box = dynamic_cast<SPBox3D *>(group);
+ if (box) {
+ group = box3d_convert_to_group(box);
+ }
+ }
- SP_LPE_ITEM(group)->removeAllPathEffects(false);
+ group->removeAllPathEffects(false);
/* Step 1 - generate lists of children objects */
GSList *items = NULL;
GSList *objects = NULL;
for (SPObject *child = group->firstChild() ; child; child = child->getNext() ) {
- if (SP_IS_ITEM (child)) {
-
- SPItem *citem = SP_ITEM (child);
-
+ SPItem *citem = dynamic_cast<SPItem *>(child);
+ if (citem) {
/* Merging of style */
// this converts the gradient/pattern fill/stroke, if any, to userSpaceOnUse; we need to do
// it here _before_ the new transform is set, so as to use the pre-transform bbox
citem->adjust_paint_recursive (Geom::identity(), Geom::identity(), false);
- sp_style_merge_from_dying_parent(child->style, gitem->style);
+ sp_style_merge_from_dying_parent(child->style, group->style);
/*
* fixme: We currently make no allowance for the case where child is cloned
* and the group has any style settings.
@@ -470,20 +464,21 @@ sp_item_group_ungroup (SPGroup *group, GSList **children, bool do_done)
// Merging transform
Geom::Affine ctrans;
- Geom::Affine const g(gitem->transform);
- if (SP_IS_USE(citem) && SP_USE(citem)->get_original() &&
- SP_USE(citem)->get_original()->parent == SP_OBJECT(group)) {
+ Geom::Affine const g(group->transform);
+ SPUse *useitem = dynamic_cast<SPUse *>(citem);
+ if (useitem && useitem->get_original() &&
+ useitem->get_original()->parent == dynamic_cast<SPObject *>(group)) {
// make sure a clone's effective transform is the same as was under group
ctrans = g.inverse() * citem->transform * g;
} else {
// We should not apply the group's transformation to both a linked offset AND to its source
- if (SP_IS_OFFSET(citem)) { // Do we have an offset at hand (whether it's dynamic or linked)?
- SPItem *source = sp_offset_get_source(SP_OFFSET(citem));
+ if (dynamic_cast<SPOffset *>(citem)) { // Do we have an offset at hand (whether it's dynamic or linked)?
+ SPItem *source = sp_offset_get_source(dynamic_cast<SPOffset *>(citem));
// When dealing with a chain of linked offsets, the transformation of an offset will be
// tied to the transformation of the top-most source, not to any of the intermediate
// offsets. So let's find the top-most source
- while (source != NULL && SP_IS_OFFSET(source)) {
- source = sp_offset_get_source(SP_OFFSET(source));
+ while (source != NULL && dynamic_cast<SPOffset *>(source)) {
+ source = sp_offset_get_source(dynamic_cast<SPOffset *>(source));
}
if (source != NULL && // If true then we must be dealing with a linked offset ...
group->isAncestorOf(source) == false) { // ... of which the source is not in the same group
@@ -550,10 +545,14 @@ sp_item_group_ungroup (SPGroup *group, GSList **children, bool do_done)
// fill in the children list if non-null
SPItem *item = static_cast<SPItem *>(doc->getObjectByRepr(repr));
- item->doWriteTransform(repr, item->transform, NULL, false);
+ if (item) {
+ item->doWriteTransform(repr, item->transform, NULL, false);
+ } else {
+ g_assert_not_reached();
+ }
Inkscape::GC::release(repr);
- if (children && SP_IS_ITEM(item)) {
+ if (children && item) {
*children = g_slist_prepend(*children, item);
}
@@ -572,12 +571,11 @@ sp_item_group_ungroup (SPGroup *group, GSList **children, bool do_done)
GSList *sp_item_group_item_list(SPGroup * group)
{
g_return_val_if_fail(group != NULL, NULL);
- g_return_val_if_fail(SP_IS_GROUP(group), NULL);
GSList *s = NULL;
for (SPObject *o = group->firstChild() ; o ; o = o->getNext() ) {
- if ( SP_IS_ITEM(o) ) {
+ if ( dynamic_cast<SPItem *>(o) ) {
s = g_slist_prepend(s, o);
}
}
@@ -616,6 +614,18 @@ SPGroup::LayerMode SPGroup::layerDisplayMode(unsigned int dkey) const {
}
}
+void SPGroup::setExpanded(bool isexpanded) {
+ if ( _expanded != isexpanded ){
+ _expanded = isexpanded;
+ }
+}
+
+void SPGroup::setInsertBottom(bool insertbottom) {
+ if ( _insertBottom != insertbottom) {
+ _insertBottom = insertbottom;
+ }
+}
+
void SPGroup::setLayerDisplayMode(unsigned int dkey, SPGroup::LayerMode mode) {
if ( layerDisplayMode(dkey) != mode ) {
_display_modes[dkey] = mode;
@@ -639,53 +649,110 @@ void SPGroup::translateChildItems(Geom::Translate const &tr)
{
if ( hasChildren() ) {
for (SPObject *o = firstChild() ; o ; o = o->getNext() ) {
- if ( SP_IS_ITEM(o) ) {
- sp_item_move_rel(reinterpret_cast<SPItem *>(o), tr);
+ SPItem *item = dynamic_cast<SPItem *>(o);
+ if ( item ) {
+ sp_item_move_rel(item, tr);
}
}
}
}
-// Recursively scale child items around a point
-void SPGroup::scaleChildItemsRec(Geom::Scale const &sc, Geom::Point const &p)
+// Recursively (or not) scale child items around a point
+void SPGroup::scaleChildItemsRec(Geom::Scale const &sc, Geom::Point const &p, bool noRecurse)
{
if ( hasChildren() ) {
for (SPObject *o = firstChild() ; o ; o = o->getNext() ) {
- if ( SP_IS_ITEM(o) ) {
- if (SP_IS_GROUP(o) && !SP_IS_BOX3D(o)) {
- SP_GROUP(o)->scaleChildItemsRec(sc, p);
+ if ( SPDefs *defs = dynamic_cast<SPDefs *>(o) ) { // select symbols from defs, ignore clips, masks, patterns
+ for (SPObject *defschild = defs->firstChild() ; defschild ; defschild = defschild->getNext() ) {
+ SPGroup *defsgroup = dynamic_cast<SPGroup *>(defschild);
+ if (defsgroup)
+ defsgroup->scaleChildItemsRec(sc, p, false);
+ }
+ } else if ( SPItem *item = dynamic_cast<SPItem *>(o) ) {
+ SPGroup *group = dynamic_cast<SPGroup *>(item);
+ if (group && !dynamic_cast<SPBox3D *>(item)) {
+ /* Using recursion breaks clipping because transforms are applied
+ in coordinates for draws but nothing in defs is changed
+ instead change the transform on the entire group, and the transform
+ is applied after any references to clipping paths. However NOT using
+ recursion apparently breaks as of r13544 other parts of Inkscape
+ involved with showing/modifying units. So offer both for use
+ in different contexts.
+ */
+ if(noRecurse) {
+ // used for EMF import
+ Geom::Translate const s(p);
+ Geom::Affine final = s.inverse() * sc * s;
+ Geom::Affine tAff = item->i2dt_affine() * final;
+ item->set_i2d_affine(tAff);
+ tAff = item->transform;
+ // Eliminate common rounding error affecting EMF/WMF input.
+ // When the rounding error persists it converts the simple
+ // transform=scale() to transform=matrix().
+ if(std::abs(tAff[4]) < 1.0e-5 && std::abs(tAff[5]) < 1.0e-5){
+ tAff[4] = 0.0;
+ tAff[5] = 0.0;
+ }
+ item->doWriteTransform(item->getRepr(), tAff, NULL, true);
+ } else {
+ // used for other import
+ SPItem *subItem = NULL;
+ if (item->clip_ref->getObject()) {
+ subItem = dynamic_cast<SPItem *>(item->clip_ref->getObject()->firstChild());
+ }
+ if (subItem != NULL) {
+ Geom::Affine tdoc2dt = Geom::Scale(1, -1) * Geom::Translate(p); // re-create doc2dt()
+ Geom::Affine ti2doc = item->i2doc_affine();
+ subItem->set_i2d_affine(ti2doc * sc * ti2doc.inverse() * tdoc2dt);
+ subItem->doWriteTransform(subItem->getRepr(), subItem->transform, NULL, true);
+ }
+ subItem = NULL;
+ if (item->mask_ref->getObject()) {
+ subItem = dynamic_cast<SPItem *>(item->mask_ref->getObject()->firstChild());
+ }
+ if (subItem != NULL) {
+ Geom::Affine tdoc2dt = Geom::Scale(1, -1) * Geom::Translate(p); // re-create doc2dt()
+ Geom::Affine ti2doc = item->i2doc_affine();
+ subItem->set_i2d_affine(ti2doc * sc * ti2doc.inverse() * tdoc2dt);
+ subItem->doWriteTransform(item->getRepr(), item->transform, NULL, true);
+ }
+ group->scaleChildItemsRec(sc, p, false);
+ }
} else {
- SPItem *item = SP_ITEM(o);
Geom::OptRect bbox = item->desktopVisualBounds();
if (bbox) {
// Scale item
Geom::Translate const s(p);
Geom::Affine final = s.inverse() * sc * s;
- Geom::Point old_center(0,0);
- if (item->isCenterSet()) {
- old_center = item->getCenter();
- }
-
gchar const *conn_type = NULL;
- if (SP_IS_TEXT_TEXTPATH(item)) {
- SP_TEXT(item)->optimizeTextpathText();
- } else if (SP_IS_FLOWTEXT(item)) {
- SP_FLOWTEXT(item)->optimizeScaledText();
- } else if (SP_IS_BOX3D(item)) {
- // Force recalculation from perspective
- box3d_position_set(SP_BOX3D(item));
- } else if (item->getAttribute("inkscape:connector-type") != NULL
- && (item->getAttribute("inkscape:connection-start") == NULL
- || item->getAttribute("inkscape:connection-end") == NULL)) {
- // Remove and store connector type for transform if disconnected
- conn_type = item->getAttribute("inkscape:connector-type");
- item->removeAttribute("inkscape:connector-type");
+ SPText *textItem = dynamic_cast<SPText *>(item);
+ bool isTextTextpath = textItem && textItem->firstChild() && dynamic_cast<SPTextPath *>(textItem->firstChild());
+ if (isTextTextpath) {
+ textItem->optimizeTextpathText();
+ } else {
+ SPFlowtext *flowText = dynamic_cast<SPFlowtext *>(item);
+ if (flowText) {
+ flowText->optimizeScaledText();
+ } else {
+ SPBox3D *box = dynamic_cast<SPBox3D *>(item);
+ if (box) {
+ // Force recalculation from perspective
+ box3d_position_set(box);
+ } else if (item->getAttribute("inkscape:connector-type") != NULL
+ && (item->getAttribute("inkscape:connection-start") == NULL
+ || item->getAttribute("inkscape:connection-end") == NULL)) {
+ // Remove and store connector type for transform if disconnected
+ conn_type = item->getAttribute("inkscape:connector-type");
+ item->removeAttribute("inkscape:connector-type");
+ }
+ }
}
- if (SP_IS_PERSP3D(item)) {
- persp3d_apply_affine_transformation(SP_PERSP3D(item), final);
- } else if ((SP_IS_TEXT_TEXTPATH(item) || SP_IS_FLOWTEXT(item)) && !item->transform.isIdentity()) {
+ Persp3D *persp = dynamic_cast<Persp3D *>(item);
+ if (persp) {
+ persp3d_apply_affine_transformation(persp, final);
+ } else if (isTextTextpath && !item->transform.isIdentity()) {
// Save and reset current transform
Geom::Affine tmp(item->transform);
item->transform = Geom::Affine();
@@ -696,7 +763,7 @@ void SPGroup::scaleChildItemsRec(Geom::Scale const &sc, Geom::Point const &p)
tmp[4] *= sc[0];
tmp[5] *= sc[1];
item->doWriteTransform(item->getRepr(), tmp, NULL, true);
- } else if (SP_IS_USE(item)) {
+ } else if (dynamic_cast<SPUse *>(item)) {
// calculate the matrix we need to apply to the clone
// to cancel its induced transform from its original
Geom::Affine move = final.inverse() * item->transform * final;
@@ -711,7 +778,7 @@ void SPGroup::scaleChildItemsRec(Geom::Scale const &sc, Geom::Point const &p)
}
if (item->isCenterSet() && !(final.isTranslation() || final.isIdentity())) {
- item->setCenter(old_center * final);
+ item->scaleCenter(sc); // All coordinates have been scaled, so also the center must be scaled
item->updateRepr();
}
}
@@ -724,7 +791,7 @@ void SPGroup::scaleChildItemsRec(Geom::Scale const &sc, Geom::Point const &p)
gint SPGroup::getItemCount() const {
gint len = 0;
for (SPObject const *o = this->firstChild() ; o ; o = o->getNext() ) {
- if (SP_IS_ITEM(o)) {
+ if (dynamic_cast<SPItem const *>(o)) {
len++;
}
}
@@ -734,12 +801,11 @@ gint SPGroup::getItemCount() const {
void SPGroup::_showChildren (Inkscape::Drawing &drawing, Inkscape::DrawingItem *ai, unsigned int key, unsigned int flags) {
Inkscape::DrawingItem *ac = NULL;
- SPItem * child = NULL;
GSList *l = g_slist_reverse(this->childList(false, SPObject::ActionShow));
while (l) {
SPObject *o = SP_OBJECT (l->data);
- if (SP_IS_ITEM (o)) {
- child = SP_ITEM (o);
+ SPItem * child = dynamic_cast<SPItem *>(o);
+ if (child) {
ac = child->invoke_show (drawing, key, flags);
if (ac) {
ai->appendChild(ac);
@@ -759,8 +825,9 @@ void SPGroup::update_patheffect(bool write) {
for ( GSList const *iter = item_list; iter; iter = iter->next ) {
SPObject *subitem = static_cast<SPObject *>(iter->data);
- if (SP_IS_LPE_ITEM(subitem)) {
- ((SPLPEItem*)subitem)->update_patheffect(write);
+ SPLPEItem *lpeItem = dynamic_cast<SPLPEItem *>(subitem);
+ if (lpeItem) {
+ lpeItem->update_patheffect(write);
}
}
@@ -781,40 +848,45 @@ void SPGroup::update_patheffect(bool write) {
static void
sp_group_perform_patheffect(SPGroup *group, SPGroup *topgroup, bool write)
{
- GSList const *item_list = sp_item_group_item_list(SP_GROUP(group));
+ GSList const *item_list = sp_item_group_item_list(group);
for ( GSList const *iter = item_list; iter; iter = iter->next ) {
SPObject *subitem = static_cast<SPObject *>(iter->data);
- if (SP_IS_GROUP(subitem)) {
- sp_group_perform_patheffect(SP_GROUP(subitem), topgroup, write);
- } else if (SP_IS_SHAPE(subitem)) {
- SPCurve * c = NULL;
+ SPGroup *subGroup = dynamic_cast<SPGroup *>(subitem);
+ if (subGroup) {
+ sp_group_perform_patheffect(subGroup, topgroup, write);
+ } else {
+ SPShape *subShape = dynamic_cast<SPShape *>(subitem);
+ if (subShape) {
+ SPCurve * c = NULL;
- if (SP_IS_PATH(subitem)) {
- c = SP_PATH(subitem)->get_original_curve();
- } else {
- c = SP_SHAPE(subitem)->getCurve();
- }
+ SPPath *subPath = dynamic_cast<SPPath *>(subShape);
+ if (subPath) {
+ c = subPath->get_original_curve();
+ } else {
+ c = subShape->getCurve();
+ }
- // only run LPEs when the shape has a curve defined
- if (c) {
- c->transform(i2anc_affine(subitem, topgroup));
- SP_LPE_ITEM(topgroup)->performPathEffect(c);
- c->transform(i2anc_affine(subitem, topgroup).inverse());
- SP_SHAPE(subitem)->setCurve(c, TRUE);
-
- if (write) {
- Inkscape::XML::Node *repr = subitem->getRepr();
- gchar *str = sp_svg_write_path(c->get_pathvector());
- repr->setAttribute("d", str);
+ // only run LPEs when the shape has a curve defined
+ if (c) {
+ c->transform(i2anc_affine(subitem, topgroup));
+ topgroup->performPathEffect(c);
+ c->transform(i2anc_affine(subitem, topgroup).inverse());
+ subShape->setCurve(c, TRUE);
+
+ if (write) {
+ Inkscape::XML::Node *repr = subitem->getRepr();
+ gchar *str = sp_svg_write_path(c->get_pathvector());
+ repr->setAttribute("d", str);
#ifdef GROUP_VERBOSE
-g_message("sp_group_perform_patheffect writes 'd' attribute");
+ g_message("sp_group_perform_patheffect writes 'd' attribute");
#endif
- g_free(str);
- }
+ g_free(str);
+ }
- c->unref();
+ c->unref();
+ }
}
}
}
diff --git a/src/sp-item-group.h b/src/sp-item-group.h
index 2004a72b8..15bb58f22 100644
--- a/src/sp-item-group.h
+++ b/src/sp-item-group.h
@@ -1,5 +1,5 @@
-#ifndef __SP_ITEM_GROUP_H__
-#define __SP_ITEM_GROUP_H__
+#ifndef SEEN_SP_ITEM_GROUP_H
+#define SEEN_SP_ITEM_GROUP_H
/*
* SVG <g> implementation
@@ -25,6 +25,7 @@ namespace Inkscape {
class Drawing;
class DrawingItem;
+typedef struct _GSList GSList;
} // namespace Inkscape
@@ -35,12 +36,20 @@ public:
enum LayerMode { GROUP, LAYER, MASK_HELPER };
+ bool _expanded;
+ bool _insertBottom;
LayerMode _layer_mode;
std::map<unsigned int, LayerMode> _display_modes;
LayerMode layerMode() const { return _layer_mode; }
void setLayerMode(LayerMode mode);
+ bool expanded() const { return _expanded; }
+ void setExpanded(bool isexpanded);
+
+ bool insertBottom() const { return _insertBottom; }
+ void setInsertBottom(bool insertbottom);
+
LayerMode effectiveLayerMode(unsigned int display_key) const {
if ( _layer_mode == LAYER ) {
return LAYER;
@@ -52,9 +61,9 @@ public:
LayerMode layerDisplayMode(unsigned int display_key) const;
void setLayerDisplayMode(unsigned int display_key, LayerMode mode);
void translateChildItems(Geom::Translate const &tr);
- void scaleChildItemsRec(Geom::Scale const &sc, Geom::Point const &p);
+ void scaleChildItemsRec(Geom::Scale const &sc, Geom::Point const &p, bool noRecurse);
- gint getItemCount() const;
+ int getItemCount() const;
virtual void _showChildren (Inkscape::Drawing &drawing, Inkscape::DrawingItem *ai, unsigned int key, unsigned int flags);
private:
@@ -69,15 +78,15 @@ public:
virtual void order_changed(Inkscape::XML::Node *child, Inkscape::XML::Node *old_ref, Inkscape::XML::Node *new_ref);
virtual void update(SPCtx *ctx, unsigned int flags);
- virtual void modified(guint flags);
- virtual void set(unsigned int key, gchar const* value);
+ virtual void modified(unsigned int flags);
+ virtual void set(unsigned int key, char const* value);
- virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags);
+ virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags);
virtual Geom::OptRect bbox(Geom::Affine const &transform, SPItem::BBoxType bboxtype) const;
virtual void print(SPPrintContext *ctx);
virtual const char* displayName() const;
- virtual gchar *description() const;
+ virtual char *description() const;
virtual Inkscape::DrawingItem *show (Inkscape::Drawing &drawing, unsigned int key, unsigned int flags);
virtual void hide (unsigned int key);
@@ -90,7 +99,7 @@ void sp_item_group_ungroup (SPGroup *group, GSList **children, bool do_done = tr
GSList *sp_item_group_item_list (SPGroup *group);
-SPObject *sp_item_group_get_child_by_name (SPGroup *group, SPObject *ref, const gchar *name);
+SPObject *sp_item_group_get_child_by_name (SPGroup *group, SPObject *ref, const char *name);
#endif
diff --git a/src/sp-item-notify-moveto.cpp b/src/sp-item-notify-moveto.cpp
index 0f5117289..dcc91fd0b 100644
--- a/src/sp-item-notify-moveto.cpp
+++ b/src/sp-item-notify-moveto.cpp
@@ -9,6 +9,7 @@
#include <sp-item-notify-moveto.h>
using std::vector;
+#define return_if_fail(test) if (!(test)) { printf("WARNING: assertion '%s' failed", #test); return; }
/**
* Called by sp_guide_moveto to indicate that the guide line corresponding to g has been moved, and
@@ -19,15 +20,15 @@ using std::vector;
void sp_item_notify_moveto(SPItem &item, SPGuide const &mv_g, int const snappoint_ix,
double const position, bool const commit)
{
- g_return_if_fail(SP_IS_ITEM(&item));
- g_return_if_fail( unsigned(snappoint_ix) < 8 );
- Geom::Point const dir( mv_g.normal_to_line );
+ return_if_fail(SP_IS_ITEM(&item));
+ return_if_fail( unsigned(snappoint_ix) < 8 );
+ Geom::Point const dir( mv_g.getNormal() );
double const dir_lensq(dot(dir, dir));
- g_return_if_fail( dir_lensq != 0 );
+ return_if_fail( dir_lensq != 0 );
std::vector<Inkscape::SnapCandidatePoint> snappoints;
item.getSnappoints(snappoints, NULL);
- g_return_if_fail( snappoint_ix < int(snappoints.size()) );
+ return_if_fail( snappoint_ix < int(snappoints.size()) );
double const pos0 = dot(dir, snappoints[snappoint_ix].getPoint());
/// \todo effic: skip if mv_g is already satisfied.
diff --git a/src/sp-item-transform.cpp b/src/sp-item-transform.cpp
index 086da56ff..86beee907 100644
--- a/src/sp-item-transform.cpp
+++ b/src/sp-item-transform.cpp
@@ -18,6 +18,8 @@
#include "sp-item.h"
#include "sp-item-transform.h"
+#include <glib.h>
+
void sp_item_rotate_rel(SPItem *item, Geom::Rotate const &rotation)
{
Geom::Point center = item->getCenter();
diff --git a/src/sp-item-transform.h b/src/sp-item-transform.h
index 230d5a3dd..d563c9768 100644
--- a/src/sp-item-transform.h
+++ b/src/sp-item-transform.h
@@ -1,9 +1,8 @@
#ifndef SEEN_SP_ITEM_TRANSFORM_H
#define SEEN_SP_ITEM_TRANSFORM_H
-#include <glib.h>
-
#include <2geom/forward.h>
+
class SPItem;
void sp_item_rotate_rel(SPItem *item, Geom::Rotate const &rotation);
@@ -11,9 +10,9 @@ void sp_item_scale_rel (SPItem *item, Geom::Scale const &scale);
void sp_item_skew_rel (SPItem *item, double skewX, double skewY);
void sp_item_move_rel(SPItem *item, Geom::Translate const &tr);
-Geom::Affine get_scale_transform_for_uniform_stroke (Geom::Rect const &bbox_visual, gdouble stroke_x, gdouble stroke_y, bool transform_stroke, bool preserve, gdouble x0, gdouble y0, gdouble x1, gdouble y1);
-Geom::Affine get_scale_transform_for_variable_stroke (Geom::Rect const &bbox_visual, Geom::Rect const &bbox_geom, bool transform_stroke, bool preserve, gdouble x0, gdouble y0, gdouble x1, gdouble y1);
-Geom::Rect get_visual_bbox (Geom::OptRect const &initial_geom_bbox, Geom::Affine const &abs_affine, gdouble const initial_strokewidth, bool const transform_stroke);
+Geom::Affine get_scale_transform_for_uniform_stroke (Geom::Rect const &bbox_visual, double stroke_x, double stroke_y, bool transform_stroke, bool preserve, double x0, double y0, double x1, double y1);
+Geom::Affine get_scale_transform_for_variable_stroke (Geom::Rect const &bbox_visual, Geom::Rect const &bbox_geom, bool transform_stroke, bool preserve, double x0, double y0, double x1, double y1);
+Geom::Rect get_visual_bbox (Geom::OptRect const &initial_geom_bbox, Geom::Affine const &abs_affine, double const initial_strokewidth, bool const transform_stroke);
#endif // SEEN_SP_ITEM_TRANSFORM_H
diff --git a/src/sp-item.cpp b/src/sp-item.cpp
index b10aae1c6..73347fc4e 100644
--- a/src/sp-item.cpp
+++ b/src/sp-item.cpp
@@ -1,6 +1,3 @@
-/** \file
- * Base class for visual SVG elements
- */
/*
* Authors:
* Lauris Kaplinski <lauris@kaplinski.com>
@@ -15,12 +12,6 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-/** \class SPItem
- *
- * SPItem is an abstract base class for all graphic (visible) SVG nodes. It
- * is a subclass of SPObject, with great deal of specific functionality.
- */
-
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
@@ -44,6 +35,7 @@
#include "sp-rect.h"
#include "sp-use.h"
#include "sp-text.h"
+#include "sp-textpath.h"
#include "sp-item-rm-unsatisfied-cns.h"
#include "sp-pattern.h"
#include "sp-paint-server.h"
@@ -99,6 +91,8 @@ SPItem::SPItem() : SPObject() {
sensitive = TRUE;
bbox_valid = FALSE;
+ _highlightColor = NULL;
+
transform_center_x = 0;
transform_center_y = 0;
@@ -117,11 +111,10 @@ SPItem::SPItem() : SPObject() {
mask_ref = new SPMaskReference(this);
mask_ref->changedSignal().connect(sigc::bind(sigc::ptr_fun(mask_ref_changed), this));
- avoidRef = new SPAvoidRef(this);
-
- //new (&constraints) std::vector<SPGuideConstraint>();
+ style->signal_fill_ps_changed.connect(sigc::bind(sigc::ptr_fun(fill_ps_ref_changed), this));
+ style->signal_stroke_ps_changed.connect(sigc::bind(sigc::ptr_fun(stroke_ps_ref_changed), this));
- //new (&_transformed_signal) sigc::signal<void, Geom::Affine const *, SPItem *>();
+ avoidRef = new SPAvoidRef(this);
}
SPItem::~SPItem() {
@@ -137,7 +130,8 @@ bool SPItem::isVisibleAndUnlocked(unsigned display_key) const {
bool SPItem::isLocked() const {
for (SPObject const *o = this; o != NULL; o = o->parent) {
- if (SP_IS_ITEM(o) && !(SP_ITEM(o)->sensitive)) {
+ SPItem const *item = dynamic_cast<SPItem const *>(o);
+ if (item && !(item->sensitive)) {
return true;
}
}
@@ -183,6 +177,29 @@ bool SPItem::isHidden(unsigned display_key) const {
return true;
}
+bool SPItem::isHighlightSet() const {
+ return _highlightColor != NULL;
+}
+
+guint32 SPItem::highlight_color() const {
+ if (_highlightColor)
+ {
+ return atoi(_highlightColor) | 0x00000000;
+ }
+ else {
+ SPItem const *item = dynamic_cast<SPItem const *>(parent);
+ if (parent && (parent != this) && item)
+ {
+ return item->highlight_color();
+ }
+ else
+ {
+ static Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ return prefs->getInt("/tools/nodes/highlight_color", 0xff0000ff) | 0x00000000;
+ }
+ }
+}
+
void SPItem::setEvaluated(bool evaluated) {
_is_evaluated = evaluated;
_evaluated_status = StatusSet;
@@ -196,8 +213,9 @@ void SPItem::resetEvaluated() {
requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG);
}
} if ( StatusSet == _evaluated_status ) {
- if (SP_IS_SWITCH(parent)) {
- SP_SWITCH(parent)->resetChildEvaluated();
+ SPSwitch *switchItem = dynamic_cast<SPSwitch *>(parent);
+ if (switchItem) {
+ switchItem->resetChildEvaluated();
}
}
}
@@ -210,20 +228,12 @@ bool SPItem::isEvaluated() const {
return _is_evaluated;
}
-/**
- * Returns something suitable for the `Hide' checkbox in the Object Properties dialog box.
- * Corresponds to setExplicitlyHidden.
- */
bool SPItem::isExplicitlyHidden() const
{
return (style->display.set
&& style->display.value == SP_CSS_DISPLAY_NONE);
}
-/**
- * Sets the display CSS property to `hidden' if \a val is true,
- * otherwise makes it unset
- */
void SPItem::setExplicitlyHidden(bool val) {
style->display.set = val;
style->display.value = ( val ? SP_CSS_DISPLAY_NONE : SP_CSS_DISPLAY_INLINE );
@@ -231,19 +241,27 @@ void SPItem::setExplicitlyHidden(bool val) {
updateRepr();
}
-/**
- * Sets the transform_center_x and transform_center_y properties to retain the rotation centre
- */
void SPItem::setCenter(Geom::Point const &object_centre) {
document->ensureUpToDate();
+ // Copied from DocumentProperties::onDocUnitChange()
+ gdouble viewscale = 1.0;
+ Geom::Rect vb = this->document->getRoot()->viewBox;
+ if ( !vb.hasZeroArea() ) {
+ gdouble viewscale_w = this->document->getWidth().value("px") / vb.width();
+ gdouble viewscale_h = this->document->getHeight().value("px")/ vb.height();
+ viewscale = std::min(viewscale_h, viewscale_w);
+ }
+
// FIXME this is seriously wrong
Geom::OptRect bbox = desktopGeometricBounds();
if (bbox) {
- transform_center_x = object_centre[Geom::X] - bbox->midpoint()[Geom::X];
+ // object centre is document coordinates (i.e. in pixels), so we need to consider the viewbox
+ // to translate to user units; transform_center_x/y is in user units
+ transform_center_x = (object_centre[Geom::X] - bbox->midpoint()[Geom::X])/viewscale;
if (Geom::are_near(transform_center_x, 0)) // rounding error
transform_center_x = 0;
- transform_center_y = object_centre[Geom::Y] - bbox->midpoint()[Geom::Y];
+ transform_center_y = (object_centre[Geom::Y] - bbox->midpoint()[Geom::Y])/viewscale;
if (Geom::are_near(transform_center_y, 0)) // rounding error
transform_center_y = 0;
}
@@ -259,23 +277,41 @@ bool SPItem::isCenterSet() const {
return (transform_center_x != 0 || transform_center_y != 0);
}
+// Get the item's transformation center in document coordinates (i.e. in pixels)
Geom::Point SPItem::getCenter() const {
document->ensureUpToDate();
+ // Copied from DocumentProperties::onDocUnitChange()
+ gdouble viewscale = 1.0;
+ Geom::Rect vb = this->document->getRoot()->viewBox;
+ if ( !vb.hasZeroArea() ) {
+ gdouble viewscale_w = this->document->getWidth().value("px") / vb.width();
+ gdouble viewscale_h = this->document->getHeight().value("px")/ vb.height();
+ viewscale = std::min(viewscale_h, viewscale_w);
+ }
+
// FIXME this is seriously wrong
Geom::OptRect bbox = desktopGeometricBounds();
if (bbox) {
- return bbox->midpoint() + Geom::Point (transform_center_x, transform_center_y);
+ // transform_center_x/y are stored in user units, so we have to take the viewbox into account to translate to document coordinates
+ return bbox->midpoint() + Geom::Point (transform_center_x*viewscale, transform_center_y*viewscale);
+
} else {
return Geom::Point(0, 0); // something's wrong!
}
+
}
+void
+SPItem::scaleCenter(Geom::Scale const &sc) {
+ transform_center_x *= sc[Geom::X];
+ transform_center_y *= sc[Geom::Y];
+}
namespace {
bool is_item(SPObject const &object) {
- return SP_IS_ITEM(&object);
+ return dynamic_cast<SPItem const *>(&object) != NULL;
}
}
@@ -338,12 +374,7 @@ void SPItem::lowerToBottom() {
}
}
-/*
- * Move this SPItem into or after another SPItem in the doc
- * \param target - the SPItem to move into or after
- * \param intoafter - move to after the target (false), move inside (sublayer) of the target (true)
- */
-void SPItem::moveTo(SPItem *target, gboolean intoafter) {
+void SPItem::moveTo(SPItem *target, bool intoafter) {
Inkscape::XML::Node *target_ref = ( target ? target->getRepr() : NULL );
Inkscape::XML::Node *our_ref = getRepr();
@@ -396,6 +427,7 @@ void SPItem::build(SPDocument *document, Inkscape::XML::Node *repr) {
object->readAttr( "inkscape:transform-center-y" );
object->readAttr( "inkscape:connector-avoid" );
object->readAttr( "inkscape:connection-points" );
+ object->readAttr( "inkscape:highlight-color" );
SPObject::build(document, repr);
}
@@ -416,7 +448,15 @@ void SPItem::release() {
SPObject::release();
+ SPPaintServer *fill_ps = style->getFillPaintServer();
+ SPPaintServer *stroke_ps = style->getStrokePaintServer();
while (item->display) {
+ if (fill_ps) {
+ fill_ps->hide(item->display->arenaitem->key());
+ }
+ if (stroke_ps) {
+ stroke_ps->hide(item->display->arenaitem->key());
+ }
item->display = sp_item_view_list_remove(item->display, item->display);
}
@@ -470,11 +510,23 @@ void SPItem::set(unsigned int key, gchar const* value) {
break;
}
case SP_ATTR_SODIPODI_INSENSITIVE:
+ {
item->sensitive = !value;
for (SPItemView *v = item->display; v != NULL; v = v->next) {
v->arenaitem->setSensitive(item->sensitive);
}
break;
+ }
+ case SP_ATTR_INKSCAPE_HIGHLIGHT_COLOR:
+ {
+ g_free(item->_highlightColor);
+ if (value) {
+ item->_highlightColor = g_strdup(value);
+ } else {
+ item->_highlightColor = NULL;
+ }
+ break;
+ }
case SP_ATTR_CONNECTOR_AVOID:
item->avoidRef->setAvoid(value);
break;
@@ -519,20 +571,23 @@ void SPItem::clip_ref_changed(SPObject *old_clip, SPObject *clip, SPItem *item)
SPItemView *v;
/* Hide clippath */
for (v = item->display; v != NULL; v = v->next) {
- SP_CLIPPATH(old_clip)->hide(v->arenaitem->key());
+ SPClipPath *oldPath = dynamic_cast<SPClipPath *>(old_clip);
+ g_assert(oldPath != NULL);
+ oldPath->hide(v->arenaitem->key());
}
}
- if (SP_IS_CLIPPATH(clip)) {
+ SPClipPath *clipPath = dynamic_cast<SPClipPath *>(clip);
+ if (clipPath) {
Geom::OptRect bbox = item->geometricBounds();
for (SPItemView *v = item->display; v != NULL; v = v->next) {
if (!v->arenaitem->key()) {
v->arenaitem->setKey(SPItem::display_key_new(3));
}
- Inkscape::DrawingItem *ai = SP_CLIPPATH(clip)->show(
+ Inkscape::DrawingItem *ai = clipPath->show(
v->arenaitem->drawing(),
v->arenaitem->key());
v->arenaitem->setClip(ai);
- SP_CLIPPATH(clip)->setBBox(v->arenaitem->key(), bbox);
+ clipPath->setBBox(v->arenaitem->key(), bbox);
clip->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
}
}
@@ -543,25 +598,78 @@ void SPItem::mask_ref_changed(SPObject *old_mask, SPObject *mask, SPItem *item)
if (old_mask) {
/* Hide mask */
for (SPItemView *v = item->display; v != NULL; v = v->next) {
- SP_MASK(old_mask)->sp_mask_hide(v->arenaitem->key());
+ SPMask *maskItem = dynamic_cast<SPMask *>(old_mask);
+ g_assert(maskItem != NULL);
+ maskItem->sp_mask_hide(v->arenaitem->key());
}
}
- if (SP_IS_MASK(mask)) {
+ SPMask *maskItem = dynamic_cast<SPMask *>(mask);
+ if (maskItem) {
Geom::OptRect bbox = item->geometricBounds();
for (SPItemView *v = item->display; v != NULL; v = v->next) {
if (!v->arenaitem->key()) {
v->arenaitem->setKey(SPItem::display_key_new(3));
}
- Inkscape::DrawingItem *ai = SP_MASK(mask)->sp_mask_show(
+ Inkscape::DrawingItem *ai = maskItem->sp_mask_show(
v->arenaitem->drawing(),
v->arenaitem->key());
v->arenaitem->setMask(ai);
- SP_MASK(mask)->sp_mask_set_bbox(v->arenaitem->key(), bbox);
+ maskItem->sp_mask_set_bbox(v->arenaitem->key(), bbox);
mask->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
}
}
}
+void SPItem::fill_ps_ref_changed(SPObject *old_ps, SPObject *ps, SPItem *item) {
+ SPPaintServer *old_fill_ps = dynamic_cast<SPPaintServer *>(old_ps);
+ if (old_fill_ps) {
+ for (SPItemView *v =item->display; v != NULL; v = v->next) {
+ old_fill_ps->hide(v->arenaitem->key());
+ }
+ }
+
+ SPPaintServer *new_fill_ps = dynamic_cast<SPPaintServer *>(ps);
+ if (new_fill_ps) {
+ Geom::OptRect bbox = item->geometricBounds();
+ for (SPItemView *v = item->display; v != NULL; v = v->next) {
+ if (!v->arenaitem->key()) {
+ v->arenaitem->setKey(SPItem::display_key_new(3));
+ }
+ Inkscape::DrawingPattern *pi = new_fill_ps->show(
+ v->arenaitem->drawing(), v->arenaitem->key(), bbox);
+ v->arenaitem->setFillPattern(pi);
+ if (pi) {
+ new_fill_ps->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+ }
+ }
+ }
+}
+
+void SPItem::stroke_ps_ref_changed(SPObject *old_ps, SPObject *ps, SPItem *item) {
+ SPPaintServer *old_stroke_ps = dynamic_cast<SPPaintServer *>(old_ps);
+ if (old_stroke_ps) {
+ for (SPItemView *v =item->display; v != NULL; v = v->next) {
+ old_stroke_ps->hide(v->arenaitem->key());
+ }
+ }
+
+ SPPaintServer *new_stroke_ps = dynamic_cast<SPPaintServer *>(ps);
+ if (new_stroke_ps) {
+ Geom::OptRect bbox = item->geometricBounds();
+ for (SPItemView *v = item->display; v != NULL; v = v->next) {
+ if (!v->arenaitem->key()) {
+ v->arenaitem->setKey(SPItem::display_key_new(3));
+ }
+ Inkscape::DrawingPattern *pi = new_stroke_ps->show(
+ v->arenaitem->drawing(), v->arenaitem->key(), bbox);
+ v->arenaitem->setStrokePattern(pi);
+ if (pi) {
+ new_stroke_ps->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+ }
+ }
+ }
+}
+
void SPItem::update(SPCtx* /*ctx*/, guint flags) {
SPItem *item = this;
SPItem* object = item;
@@ -601,7 +709,7 @@ void SPItem::update(SPCtx* /*ctx*/, guint flags) {
v->arenaitem->setOpacity(SP_SCALE24_TO_FLOAT(object->style->opacity.value));
v->arenaitem->setAntialiasing(object->style->shape_rendering.computed != SP_CSS_SHAPE_RENDERING_CRISPEDGES);
v->arenaitem->setIsolation( object->style->isolation.value );
- v->arenaitem->setBlendMode( object->style->blend_mode.value );
+ v->arenaitem->setBlendMode( object->style->mix_blend_mode.value );
v->arenaitem->setVisible(!item->isHidden());
}
}
@@ -621,6 +729,10 @@ void SPItem::update(SPCtx* /*ctx*/, guint flags) {
item->avoidRef->handleSettingChange();
}
+void SPItem::modified(unsigned int /*flags*/)
+{
+}
+
Inkscape::XML::Node* SPItem::write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags) {
SPItem *item = this;
SPItem* object = item;
@@ -630,7 +742,7 @@ Inkscape::XML::Node* SPItem::write(Inkscape::XML::Document *xml_doc, Inkscape::X
if (flags & SP_OBJECT_WRITE_BUILD) {
GSList *l = NULL;
for (SPObject *child = object->firstChild(); child != NULL; child = child->next ) {
- if (SP_IS_TITLE(child) || SP_IS_DESC(child)) {
+ if (dynamic_cast<SPTitle *>(child) || dynamic_cast<SPDesc *>(child)) {
Inkscape::XML::Node *crepr = child->updateRepr(xml_doc, NULL, flags);
if (crepr) {
l = g_slist_prepend (l, crepr);
@@ -644,7 +756,7 @@ Inkscape::XML::Node* SPItem::write(Inkscape::XML::Document *xml_doc, Inkscape::X
}
} else {
for (SPObject *child = object->firstChild() ; child != NULL; child = child->next ) {
- if (SP_IS_TITLE(child) || SP_IS_DESC(child)) {
+ if (dynamic_cast<SPTitle *>(child) || dynamic_cast<SPDesc *>(child)) {
child->updateRepr(flags);
}
}
@@ -684,6 +796,11 @@ Inkscape::XML::Node* SPItem::write(Inkscape::XML::Document *xml_doc, Inkscape::X
g_free ((void *) uri);
}
}
+ if (item->_highlightColor){
+ repr->setAttribute("inkscape:highlight-color", item->_highlightColor);
+ } else {
+ repr->setAttribute("inkscape:highlight-color", NULL);
+ }
SPObject::write(xml_doc, repr, flags);
@@ -695,11 +812,7 @@ Geom::OptRect SPItem::bbox(Geom::Affine const & /*transform*/, SPItem::BBoxType
//throw;
return Geom::OptRect();
}
-/**
- * Get item's geometric bounding box in this item's coordinate system.
- *
- * The geometric bounding box includes only the path, disregarding all style attributes.
- */
+
Geom::OptRect SPItem::geometricBounds(Geom::Affine const &transform) const
{
Geom::OptRect bbox;
@@ -712,11 +825,6 @@ Geom::OptRect SPItem::geometricBounds(Geom::Affine const &transform) const
return bbox;
}
-/**
- * Get item's visual bounding box in this item's coordinate system.
- *
- * The visual bounding box includes the stroke and the filter region.
- */
Geom::OptRect SPItem::visualBounds(Geom::Affine const &transform) const
{
using Geom::X;
@@ -724,13 +832,14 @@ Geom::OptRect SPItem::visualBounds(Geom::Affine const &transform) const
Geom::OptRect bbox;
- if ( style && style->filter.href && style->getFilter() && SP_IS_FILTER(style->getFilter())) {
+
+ SPFilter *filter = (style && style->filter.href) ? dynamic_cast<SPFilter *>(style->getFilter()) : NULL;
+ if ( filter ) {
// call the subclass method
// CPPIFY
//bbox = this->bbox(Geom::identity(), SPItem::VISUAL_BBOX);
bbox = const_cast<SPItem*>(this)->bbox(Geom::identity(), SPItem::GEOMETRIC_BBOX); // see LP Bug 1229971
- SPFilter *filter = SP_FILTER(style->getFilter());
// default filer area per the SVG spec:
SVGLength x, y, w, h;
Geom::Point minp, maxp;
@@ -777,7 +886,10 @@ Geom::OptRect SPItem::visualBounds(Geom::Affine const &transform) const
bbox = const_cast<SPItem*>(this)->bbox(transform, SPItem::VISUAL_BBOX);
}
if (clip_ref->getObject()) {
- bbox.intersectWith(SP_CLIPPATH(clip_ref->getObject())->geometricBounds(transform));
+ SPItem *ownerItem = dynamic_cast<SPItem *>(clip_ref->getOwner());
+ g_assert(ownerItem != NULL);
+ ownerItem->bbox_valid = FALSE; // LP Bug 1349018
+ bbox.intersectWith(clip_ref->getObject()->geometricBounds(transform));
}
return bbox;
@@ -792,14 +904,11 @@ Geom::OptRect SPItem::bounds(BBoxType type, Geom::Affine const &transform) const
}
}
-/** Get item's geometric bbox in document coordinate system.
- * Document coordinates are the default coordinates of the root element:
- * the origin is at the top left, X grows to the right and Y grows downwards. */
Geom::OptRect SPItem::documentGeometricBounds() const
{
return geometricBounds(i2doc_affine());
}
-/// Get item's visual bbox in document coordinate system.
+
Geom::OptRect SPItem::documentVisualBounds() const
{
if (!bbox_valid) {
@@ -816,14 +925,12 @@ Geom::OptRect SPItem::documentBounds(BBoxType type) const
return documentVisualBounds();
}
}
-/** Get item's geometric bbox in desktop coordinate system.
- * Desktop coordinates should be user defined. Currently they are hardcoded:
- * origin is at bottom left, X grows to the right and Y grows upwards. */
+
Geom::OptRect SPItem::desktopGeometricBounds() const
{
return geometricBounds(i2dt_affine());
}
-/// Get item's visual bbox in desktop coordinate system.
+
Geom::OptRect SPItem::desktopVisualBounds() const
{
/// @fixme hardcoded desktop transform
@@ -862,7 +969,7 @@ unsigned int SPItem::pos_in_parent() const {
return pos;
}
- if (SP_IS_ITEM(iter)) {
+ if (dynamic_cast<SPItem *>(iter)) {
pos++;
}
}
@@ -904,10 +1011,11 @@ void SPItem::getSnappoints(std::vector<Inkscape::SnapCandidatePoint> &p, Inkscap
if (*o) {
// obj is a group object, the children are the actual clippers
for (SPObject *child = (*o)->children ; child ; child = child->next) {
- if (SP_IS_ITEM(child)) {
+ SPItem *item = dynamic_cast<SPItem *>(child);
+ if (item) {
std::vector<Inkscape::SnapCandidatePoint> p_clip_or_mask;
// Please note the recursive call here!
- SP_ITEM(child)->getSnappoints(p_clip_or_mask, snapprefs);
+ item->getSnappoints(p_clip_or_mask, snapprefs);
// Take into account the transformation of the item being clipped or masked
for (std::vector<Inkscape::SnapCandidatePoint>::const_iterator p_orig = p_clip_or_mask.begin(); p_orig != p_clip_or_mask.end(); ++p_orig) {
// All snappoints are in desktop coordinates, but the item's transformation is
@@ -947,11 +1055,6 @@ gchar* SPItem::description() const {
return g_strdup("");
}
-/**
- * Returns a string suitable for status bar, formatted in pango markup language.
- *
- * Must be freed by caller.
- */
gchar *SPItem::detailedDescription() const {
gchar* s = g_strdup_printf("<b>%s</b> %s",
this->displayName(), this->description());
@@ -985,20 +1088,10 @@ gchar *SPItem::detailedDescription() const {
return s;
}
-/**
- * Returns true if the item is filtered, false otherwise. Used with groups/lists to determine how many, or if any, are filtered
- *
- */
bool SPItem::isFiltered() const {
return (style && style->filter.href && style->filter.href->getObject());
}
-/**
- * Allocates unique integer keys.
- * \param numkeys Number of keys required.
- * \return First allocated key; hence if the returned key is n
- * you can use n, n + 1, ..., n + (numkeys - 1)
- */
unsigned SPItem::display_key_new(unsigned numkeys)
{
static unsigned dkey = 0;
@@ -1027,7 +1120,7 @@ Inkscape::DrawingItem *SPItem::invoke_show(Inkscape::Drawing &drawing, unsigned
ai->setTransform(transform);
ai->setOpacity(SP_SCALE24_TO_FLOAT(style->opacity.value));
ai->setIsolation( style->isolation.value );
- ai->setBlendMode( style->blend_mode.value );
+ ai->setBlendMode( style->mix_blend_mode.value );
//ai->setCompositeOperator( style->composite_op.value );
ai->setVisible(!isHidden());
ai->setSensitive(sensitive);
@@ -1044,7 +1137,7 @@ Inkscape::DrawingItem *SPItem::invoke_show(Inkscape::Drawing &drawing, unsigned
ai->setClip(ac);
// Update bbox, in case the clip uses bbox units
- SP_CLIPPATH(cp)->setBBox(clip_key, item_bbox);
+ cp->setBBox(clip_key, item_bbox);
cp->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
}
if (mask_ref->getObject()) {
@@ -1060,9 +1153,36 @@ Inkscape::DrawingItem *SPItem::invoke_show(Inkscape::Drawing &drawing, unsigned
ai->setMask(ac);
// Update bbox, in case the mask uses bbox units
- SP_MASK(mask)->sp_mask_set_bbox(mask_key, item_bbox);
+ mask->sp_mask_set_bbox(mask_key, item_bbox);
mask->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
}
+
+ SPPaintServer *fill_ps = style->getFillPaintServer();
+ if (fill_ps) {
+ if (!display->arenaitem->key()) {
+ display->arenaitem->setKey(display_key_new(3));
+ }
+ int fill_key = display->arenaitem->key();
+
+ Inkscape::DrawingPattern *ap = fill_ps->show(drawing, fill_key, item_bbox);
+ ai->setFillPattern(ap);
+ if (ap) {
+ fill_ps->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+ }
+ }
+ SPPaintServer *stroke_ps = style->getStrokePaintServer();
+ if (stroke_ps) {
+ if (!display->arenaitem->key()) {
+ display->arenaitem->setKey(display_key_new(3));
+ }
+ int stroke_key = display->arenaitem->key();
+
+ Inkscape::DrawingPattern *ap = stroke_ps->show(drawing, stroke_key, item_bbox);
+ ai->setStrokePattern(ap);
+ if (ap) {
+ stroke_ps->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+ }
+ }
ai->setData(this);
ai->setItemBounds(geometricBounds());
}
@@ -1092,6 +1212,14 @@ void SPItem::invoke_hide(unsigned key)
mask_ref->getObject()->sp_mask_hide(v->arenaitem->key());
v->arenaitem->setMask(NULL);
}
+ SPPaintServer *fill_ps = style->getFillPaintServer();
+ if (fill_ps) {
+ fill_ps->hide(v->arenaitem->key());
+ }
+ SPPaintServer *stroke_ps = style->getStrokePaintServer();
+ if (stroke_ps) {
+ stroke_ps->hide(v->arenaitem->key());
+ }
if (!ref) {
display = v->next;
} else {
@@ -1108,20 +1236,24 @@ void SPItem::invoke_hide(unsigned key)
// Adjusters
-void SPItem::adjust_pattern (Geom::Affine const &postmul, bool set)
+void SPItem::adjust_pattern(Geom::Affine const &postmul, bool set, PatternTransform pt)
{
- if (style && (style->fill.isPaintserver())) {
+ bool fill = (pt == TRANSFORM_FILL || pt == TRANSFORM_BOTH);
+ if (fill && style && (style->fill.isPaintserver())) {
SPObject *server = style->getFillPaintServer();
- if ( SP_IS_PATTERN(server) ) {
- SPPattern *pattern = sp_pattern_clone_if_necessary(this, SP_PATTERN(server), "fill");
+ SPPattern *serverPatt = dynamic_cast<SPPattern *>(server);
+ if ( serverPatt ) {
+ SPPattern *pattern = sp_pattern_clone_if_necessary(this, serverPatt, "fill");
sp_pattern_transform_multiply(pattern, postmul, set);
}
}
- if (style && (style->stroke.isPaintserver())) {
+ bool stroke = (pt == TRANSFORM_STROKE || pt == TRANSFORM_BOTH);
+ if (stroke && style && (style->stroke.isPaintserver())) {
SPObject *server = style->getStrokePaintServer();
- if ( SP_IS_PATTERN(server) ) {
- SPPattern *pattern = sp_pattern_clone_if_necessary(this, SP_PATTERN(server), "stroke");
+ SPPattern *serverPatt = dynamic_cast<SPPattern *>(server);
+ if ( serverPatt ) {
+ SPPattern *pattern = sp_pattern_clone_if_necessary(this, serverPatt, "stroke");
sp_pattern_transform_multiply(pattern, postmul, set);
}
}
@@ -1131,7 +1263,8 @@ void SPItem::adjust_gradient( Geom::Affine const &postmul, bool set )
{
if ( style && style->fill.isPaintserver() ) {
SPPaintServer *server = style->getFillPaintServer();
- if ( SP_IS_GRADIENT(server) ) {
+ SPGradient *serverGrad = dynamic_cast<SPGradient *>(server);
+ if ( serverGrad ) {
/**
* \note Bbox units for a gradient are generally a bad idea because
@@ -1142,7 +1275,7 @@ void SPItem::adjust_gradient( Geom::Affine const &postmul, bool set )
* \todo FIXME: convert back to bbox units after transforming with
* the item, so as to preserve the original units.
*/
- SPGradient *gradient = sp_gradient_convert_to_userspace( SP_GRADIENT(server), this, "fill" );
+ SPGradient *gradient = sp_gradient_convert_to_userspace( serverGrad, this, "fill" );
sp_gradient_transform_multiply( gradient, postmul, set );
}
@@ -1150,8 +1283,9 @@ void SPItem::adjust_gradient( Geom::Affine const &postmul, bool set )
if ( style && style->stroke.isPaintserver() ) {
SPPaintServer *server = style->getStrokePaintServer();
- if ( SP_IS_GRADIENT(server) ) {
- SPGradient *gradient = sp_gradient_convert_to_userspace( SP_GRADIENT(server), this, "stroke");
+ SPGradient *serverGrad = dynamic_cast<SPGradient *>(server);
+ if ( serverGrad ) {
+ SPGradient *gradient = sp_gradient_convert_to_userspace( serverGrad, this, "stroke");
sp_gradient_transform_multiply( gradient, postmul, set );
}
}
@@ -1198,18 +1332,16 @@ static Geom::Affine sp_item_transform_repr (SPItem *item)
}
-/**
- * Recursively scale stroke width in \a item and its children by \a expansion.
- */
void SPItem::adjust_stroke_width_recursive(double expansion)
{
adjust_stroke (expansion);
// A clone's child is the ghost of its original - we must not touch it, skip recursion
- if ( !SP_IS_USE(this) ) {
+ if ( !dynamic_cast<SPUse *>(this) ) {
for ( SPObject *o = children; o; o = o->getNext() ) {
- if (SP_IS_ITEM(o)) {
- SP_ITEM(o)->adjust_stroke_width_recursive(expansion);
+ SPItem *item = dynamic_cast<SPItem *>(o);
+ if (item) {
+ item->adjust_stroke_width_recursive(expansion);
}
}
}
@@ -1220,10 +1352,11 @@ void SPItem::freeze_stroke_width_recursive(bool freeze)
freeze_stroke_width = freeze;
// A clone's child is the ghost of its original - we must not touch it, skip recursion
- if ( !SP_IS_USE(this) ) {
+ if ( !dynamic_cast<SPUse *>(this) ) {
for ( SPObject *o = children; o; o = o->getNext() ) {
- if (SP_IS_ITEM(o)) {
- SP_ITEM(o)->freeze_stroke_width_recursive(freeze);
+ SPItem *item = dynamic_cast<SPItem *>(o);
+ if (item) {
+ item->freeze_stroke_width_recursive(freeze);
}
}
}
@@ -1235,19 +1368,19 @@ void SPItem::freeze_stroke_width_recursive(bool freeze)
static void
sp_item_adjust_rects_recursive(SPItem *item, Geom::Affine advertized_transform)
{
- if (SP_IS_RECT (item)) {
- SP_RECT(item)->compensateRxRy(advertized_transform);
+ SPRect *rect = dynamic_cast<SPRect *>(item);
+ if (rect) {
+ rect->compensateRxRy(advertized_transform);
}
for (SPObject *o = item->children; o != NULL; o = o->next) {
- if (SP_IS_ITEM(o))
- sp_item_adjust_rects_recursive(SP_ITEM(o), advertized_transform);
+ SPItem *item = dynamic_cast<SPItem *>(o);
+ if (item) {
+ sp_item_adjust_rects_recursive(item, advertized_transform);
+ }
}
}
-/**
- * Recursively compensate pattern or gradient transform.
- */
void SPItem::adjust_paint_recursive (Geom::Affine advertized_transform, Geom::Affine t_ancestors, bool is_pattern)
{
// _Before_ full pattern/gradient transform: t_paint * t_item * t_ancestors
@@ -1259,12 +1392,13 @@ void SPItem::adjust_paint_recursive (Geom::Affine advertized_transform, Geom::Af
// Within text, we do not fork gradients, and so must not recurse to avoid double compensation;
// also we do not recurse into clones, because a clone's child is the ghost of its original -
// we must not touch it
- if (!(this && (SP_IS_TEXT(this) || SP_IS_USE(this)))) {
+ if (!(this && (dynamic_cast<SPText *>(this) || dynamic_cast<SPUse *>(this)))) {
for (SPObject *o = children; o != NULL; o = o->next) {
- if (SP_IS_ITEM(o)) {
+ SPItem *item = dynamic_cast<SPItem *>(o);
+ if (item) {
// At the level of the transformed item, t_ancestors is identity;
// below it, it is the accmmulated chain of transforms from this level to the top level
- SP_ITEM(o)->adjust_paint_recursive (advertized_transform, t_item * t_ancestors, is_pattern);
+ item->adjust_paint_recursive (advertized_transform, t_item * t_ancestors, is_pattern);
}
}
}
@@ -1283,20 +1417,18 @@ void SPItem::adjust_paint_recursive (Geom::Affine advertized_transform, Geom::Af
void SPItem::adjust_livepatheffect (Geom::Affine const &postmul, bool set)
{
- if ( SP_IS_LPE_ITEM(this) ) {
- SPLPEItem *lpeitem = SP_LPE_ITEM (this);
- if ( lpeitem->hasPathEffect() ) {
- lpeitem->forkPathEffectsIfNecessary();
-
- // now that all LPEs are forked_if_necessary, we can apply the transform
- PathEffectList effect_list = lpeitem->getEffectList();
- for (PathEffectList::iterator it = effect_list.begin(); it != effect_list.end(); ++it)
- {
- LivePathEffectObject *lpeobj = (*it)->lpeobject;
- if (lpeobj && lpeobj->get_lpe()) {
- Inkscape::LivePathEffect::Effect * effect = lpeobj->get_lpe();
- effect->transform_multiply(postmul, set);
- }
+ SPLPEItem *lpeitem = dynamic_cast<SPLPEItem *>(this);
+ if ( lpeitem && lpeitem->hasPathEffect() ) {
+ lpeitem->forkPathEffectsIfNecessary();
+
+ // now that all LPEs are forked_if_necessary, we can apply the transform
+ PathEffectList effect_list = lpeitem->getEffectList();
+ for (PathEffectList::iterator it = effect_list.begin(); it != effect_list.end(); ++it)
+ {
+ LivePathEffectObject *lpeobj = (*it)->lpeobject;
+ if (lpeobj && lpeobj->get_lpe()) {
+ Inkscape::LivePathEffect::Effect * effect = lpeobj->get_lpe();
+ effect->transform_multiply(postmul, set);
}
}
}
@@ -1309,14 +1441,6 @@ Geom::Affine SPItem::set_transform(Geom::Affine const &transform) {
return transform;
}
-/**
- * Set a new transform on an object.
- *
- * Compensate for stroke scaling and gradient/pattern fill transform, if
- * necessary. Call the object's set_transform method if transforms are
- * stored optimized. Send _transformed_signal. Invoke _write method so that
- * the repr is updated with the new transform.
- */
void SPItem::doWriteTransform(Inkscape::XML::Node *repr, Geom::Affine const &transform, Geom::Affine const *adv, bool compensate)
{
g_return_if_fail(repr != NULL);
@@ -1379,10 +1503,11 @@ void SPItem::doWriteTransform(Inkscape::XML::Node *repr, Geom::Affine const &tra
// onSetTransform cannot be pure due to the fact that not all visible Items are transformable.
if ( // run the object's set_transform (i.e. embed transform) only if:
- !preserve && // user did not chose to preserve all transforms
+ (dynamic_cast<SPText *>(this) && firstChild() && dynamic_cast<SPTextPath *>(firstChild())) ||
+ (!preserve && // user did not chose to preserve all transforms
(!clip_ref || !clip_ref->getObject()) && // the object does not have a clippath
(!mask_ref || !mask_ref->getObject()) && // the object does not have a mask
- !(!transform.isTranslation() && style && style->getFilter()) // the object does not have a filter, or the transform is translation (which is supposed to not affect filters)
+ !(!transform.isTranslation() && style && style->getFilter())) // the object does not have a filter, or the transform is translation (which is supposed to not affect filters)
)
{
transform_attr = this->set_transform(transform);
@@ -1427,10 +1552,6 @@ gint SPItem::emitEvent(SPEvent &event)
return this->event(&event);
}
-/**
- * Sets item private transform (not propagated to repr), without compensating stroke widths,
- * gradients, patterns as sp_item_write_transform does.
- */
void SPItem::set_item_transform(Geom::Affine const &transform_matrix)
{
if (!Geom::are_near(transform_matrix, transform, 1e-18)) {
@@ -1448,21 +1569,19 @@ void SPItem::set_item_transform(Geom::Affine const &transform_matrix)
//}
-/**
- * \pre \a ancestor really is an ancestor (\>=) of \a object, or NULL.
- * ("Ancestor (\>=)" here includes as far as \a object itself.)
- */
-Geom::Affine
-i2anc_affine(SPObject const *object, SPObject const *const ancestor) {
+Geom::Affine i2anc_affine(SPObject const *object, SPObject const *const ancestor) {
Geom::Affine ret(Geom::identity());
g_return_val_if_fail(object != NULL, ret);
/* stop at first non-renderable ancestor */
- while ( object != ancestor && SP_IS_ITEM(object) ) {
- if (SP_IS_ROOT(object)) {
- ret *= SP_ROOT(object)->c2p;
+ while ( object != ancestor && dynamic_cast<SPItem const *>(object) ) {
+ SPRoot const *root = dynamic_cast<SPRoot const *>(object);
+ if (root) {
+ ret *= root->c2p;
} else {
- ret *= SP_ITEM(object)->transform;
+ SPItem const *item = dynamic_cast<SPItem const *>(object);
+ g_assert(item != NULL);
+ ret *= item->transform;
}
object = object->parent;
}
@@ -1480,18 +1599,11 @@ Geom::Affine SPItem::getRelativeTransform(SPObject const *dest) const {
return i2i_affine(this, dest);
}
-/**
- * Returns the accumulated transformation of the item and all its ancestors, including root's viewport.
- * \pre (item != NULL) and SP_IS_ITEM(item).
- */
Geom::Affine SPItem::i2doc_affine() const
{
return i2anc_affine(this, NULL);
}
-/**
- * Returns the transformation from item to desktop coords
- */
Geom::Affine SPItem::i2dt_affine() const
{
Geom::Affine ret;
@@ -1522,9 +1634,6 @@ void SPItem::set_i2d_affine(Geom::Affine const &i2dt)
}
-/**
- * should rather be named "sp_item_d2i_affine" to match "sp_item_i2d_affine" (or vice versa)
- */
Geom::Affine SPItem::dt2i_affine() const
{
/* fixme: Implement the right way (Lauris) */
@@ -1536,7 +1645,7 @@ Geom::Affine SPItem::dt2i_affine() const
SPItemView *SPItem::sp_item_view_new_prepend(SPItemView *list, SPItem *item, unsigned flags, unsigned key, Inkscape::DrawingItem *drawing_item)
{
g_assert(item != NULL);
- g_assert(SP_IS_ITEM(item));
+ g_assert(dynamic_cast<SPItem *>(item) != NULL);
g_assert(drawing_item != NULL);
SPItemView *new_view = g_new(SPItemView, 1);
@@ -1568,10 +1677,6 @@ sp_item_view_list_remove(SPItemView *list, SPItemView *view)
return ret;
}
-/**
- * Return the arenaitem corresponding to the given item in the display
- * with the given key
- */
Inkscape::DrawingItem *SPItem::get_arenaitem(unsigned key)
{
for ( SPItemView *iv = display ; iv ; iv = iv->next ) {
@@ -1598,8 +1703,9 @@ SPItem *sp_item_first_item_child(SPObject *obj)
{
SPItem *child = 0;
for ( SPObject *iter = obj->firstChild() ; iter ; iter = iter->next ) {
- if ( SP_IS_ITEM(iter) ) {
- child = SP_ITEM(iter);
+ SPItem *tmp = dynamic_cast<SPItem *>(iter);
+ if ( tmp ) {
+ child = tmp;
break;
}
}
diff --git a/src/sp-item.h b/src/sp-item.h
index d605c99b9..b9d71c551 100644
--- a/src/sp-item.h
+++ b/src/sp-item.h
@@ -1,7 +1,8 @@
#ifndef SEEN_SP_ITEM_H
#define SEEN_SP_ITEM_H
-/** \file
+/**
+ * @file
* Some things pertinent to all visible shapes: SPItem, SPItemView, SPItemCtx, SPItemClass, SPEvent.
*/
@@ -18,10 +19,11 @@
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include <vector>
+
#include <2geom/forward.h>
#include <2geom/affine.h>
#include <2geom/rect.h>
+#include <vector>
#include "sp-object.h"
#include "snap-preferences.h"
@@ -33,7 +35,9 @@
class SPClipPathReference;
class SPMaskReference;
class SPAvoidRef;
+class SPPattern;
struct SPPrintContext;
+typedef unsigned int guint32;
namespace Inkscape {
@@ -51,10 +55,18 @@ enum {
SP_EVENT_MOUSEOUT
};
+// TODO make a completely new function that transforms either the fill or
+// stroke of any SPItem without adding an extra parameter to adjust_pattern.
+enum PatternTransform {
+ TRANSFORM_BOTH,
+ TRANSFORM_FILL,
+ TRANSFORM_STROKE
+};
+
/**
* Event structure.
*
- * \todo This is just placeholder. Plan:
+ * @todo This is just placeholder. Plan:
* We do extensible event structure, that hold applicable (ui, non-ui)
* data pointers. So it is up to given object/arena implementation
* to process correct ones in meaningful way.
@@ -64,10 +76,9 @@ enum {
class SPEvent {
public:
unsigned int type;
- gpointer data;
+ void* data;
};
-/// SPItemView
class SPItemView {
public:
SPItemView *next;
@@ -84,17 +95,21 @@ public:
/**
* Flag for referenced views (i.e. markers, clippaths, masks and patterns);
- currently unused, does the same as DISPLAY
+ * currently unused, does the same as DISPLAY
*/
#define SP_ITEM_REFERENCE_FLAGS (1 << 1)
-/// Contains transformations to document/viewport and the viewport size.
+/**
+ * Contains transformations to document/viewport and the viewport size.
+ */
class SPItemCtx : public SPCtx {
public:
/** Item to document transformation */
Geom::Affine i2doc;
+
/** Viewport size */
Geom::Rect viewport;
+
/** Item to viewport transformation */
Geom::Affine i2vp;
};
@@ -102,7 +117,11 @@ public:
#define SP_ITEM(obj) (dynamic_cast<SPItem*>((SPObject*)obj))
#define SP_IS_ITEM(obj) (dynamic_cast<const SPItem*>((SPObject*)obj) != NULL)
-/** Abstract base class for all visible shapes. */
+/**
+ * Base class for visual SVG elements.
+ * SPItem is an abstract base class for all graphic (visible) SVG nodes. It
+ * is a subclass of SPObject, with great deal of specific functionality.
+ */
class SPItem : public SPObject {
public:
enum BBoxType {
@@ -145,20 +164,46 @@ public:
bool isHidden() const;
void setHidden(bool hidden);
+ // Objects dialogue
+ bool isSensitive() const {
+ return sensitive;
+ };
+
+ bool isHighlightSet() const;
+ guint32 highlight_color() const;
+
+ void setHighlightColor(guint32 color);
+
+ void unsetHighlightColor();
+ //====================
+
bool isEvaluated() const;
void setEvaluated(bool visible);
void resetEvaluated();
bool isHidden(unsigned display_key) const;
+ /**
+ * Returns something suitable for the `Hide' checkbox in the Object Properties dialog box.
+ * Corresponds to setExplicitlyHidden.
+ */
bool isExplicitlyHidden() const;
+ /**
+ * Sets the display CSS property to `hidden' if \a val is true,
+ * otherwise makes it unset.
+ */
void setExplicitlyHidden(bool val);
+ /**
+ * Sets the transform_center_x and transform_center_y properties to retain the rotation center
+ */
void setCenter(Geom::Point const &object_centre);
+
void unsetCenter();
bool isCenterSet() const;
Geom::Point getCenter() const;
+ void scaleCenter(Geom::Scale const &sc);
bool isVisibleAndUnlocked() const;
@@ -170,51 +215,155 @@ public:
void lowerOne();
void raiseToTop();
void lowerToBottom();
- void moveTo(SPItem *target, gboolean intoafter);
+
+ /**
+ * Move this SPItem into or after another SPItem in the doc.
+ *
+ * @param target the SPItem to move into or after.
+ * @param intoafter move to after the target (false), move inside (sublayer) of the target (true).
+ */
+ void moveTo(SPItem *target, bool intoafter);
sigc::connection connectTransformed(sigc::slot<void, Geom::Affine const *, SPItem *> slot) {
return _transformed_signal.connect(slot);
}
+ /**
+ * Get item's geometric bounding box in this item's coordinate system.
+ *
+ * The geometric bounding box includes only the path, disregarding all style attributes.
+ */
Geom::OptRect geometricBounds(Geom::Affine const &transform = Geom::identity()) const;
+
+ /**
+ * Get item's visual bounding box in this item's coordinate system.
+ *
+ * The visual bounding box includes the stroke and the filter region.
+ */
Geom::OptRect visualBounds(Geom::Affine const &transform = Geom::identity()) const;
+
Geom::OptRect bounds(BBoxType type, Geom::Affine const &transform = Geom::identity()) const;
+
+ /**
+ * Get item's geometric bbox in document coordinate system.
+ * Document coordinates are the default coordinates of the root element:
+ * the origin is at the top left, X grows to the right and Y grows downwards.
+ */
Geom::OptRect documentGeometricBounds() const;
+
+ /**
+ * Get item's visual bbox in document coordinate system.
+ */
Geom::OptRect documentVisualBounds() const;
+
Geom::OptRect documentBounds(BBoxType type) const;
+
+ /**
+ * Get item's geometric bbox in desktop coordinate system.
+ * Desktop coordinates should be user defined. Currently they are hardcoded:
+ * origin is at bottom left, X grows to the right and Y grows upwards.
+ */
Geom::OptRect desktopGeometricBounds() const;
+
+ /**
+ * Get item's visual bbox in desktop coordinate system.
+ */
Geom::OptRect desktopVisualBounds() const;
+
Geom::OptRect desktopPreferredBounds() const;
Geom::OptRect desktopBounds(BBoxType type) const;
unsigned int pos_in_parent() const;
- gchar *detailedDescription() const;
-
+ /**
+ * Returns a string suitable for status bar, formatted in pango markup language.
+ *
+ * Must be freed by caller.
+ */
+ char *detailedDescription() const;
+
+ /**
+ * Returns true if the item is filtered, false otherwise.
+ * Used with groups/lists to determine how many, or if any, are filtered.
+ */
bool isFiltered() const;
void invoke_print(SPPrintContext *ctx);
+
+ /**
+ * Allocates unique integer keys.
+ *
+ * @param numkeys Number of keys required.
+ * @return First allocated key; hence if the returned key is n
+ * you can use n, n + 1, ..., n + (numkeys - 1)
+ */
static unsigned int display_key_new(unsigned int numkeys);
+
Inkscape::DrawingItem *invoke_show(Inkscape::Drawing &drawing, unsigned int key, unsigned int flags);
void invoke_hide(unsigned int key);
void getSnappoints(std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs=0) const;
- void adjust_pattern(/* Geom::Affine const &premul, */ Geom::Affine const &postmul, bool set = false);
+ void adjust_pattern(/* Geom::Affine const &premul, */ Geom::Affine const &postmul, bool set = false, PatternTransform = TRANSFORM_BOTH);
void adjust_gradient(/* Geom::Affine const &premul, */ Geom::Affine const &postmul, bool set = false);
- void adjust_stroke(gdouble ex);
- void adjust_stroke_width_recursive(gdouble ex);
+ void adjust_stroke(double ex);
+
+ /**
+ * Recursively scale stroke width in \a item and its children by \a expansion.
+ */
+ void adjust_stroke_width_recursive(double ex);
+
void freeze_stroke_width_recursive(bool freeze);
+
+ /**
+ * Recursively compensate pattern or gradient transform.
+ */
void adjust_paint_recursive(Geom::Affine advertized_transform, Geom::Affine t_ancestors, bool is_pattern);
+
void adjust_livepatheffect(Geom::Affine const &postmul, bool set = false);
+
+ /**
+ * Set a new transform on an object.
+ *
+ * Compensate for stroke scaling and gradient/pattern fill transform, if
+ * necessary. Call the object's set_transform method if transforms are
+ * stored optimized. Send _transformed_signal. Invoke _write method so that
+ * the repr is updated with the new transform.
+ */
void doWriteTransform(Inkscape::XML::Node *repr, Geom::Affine const &transform, Geom::Affine const *adv = NULL, bool compensate = true);
+
+ /**
+ * Sets item private transform (not propagated to repr), without compensating stroke widths,
+ * gradients, patterns as sp_item_write_transform does.
+ */
void set_item_transform(Geom::Affine const &transform_matrix);
- gint emitEvent (SPEvent &event);
+
+ int emitEvent (SPEvent &event);
+
+ /**
+ * Return the arenaitem corresponding to the given item in the display
+ * with the given key
+ */
Inkscape::DrawingItem *get_arenaitem(unsigned int key);
+ /**
+ * Returns the accumulated transformation of the item and all its ancestors, including root's viewport.
+ * @pre (item != NULL) and SP_IS_ITEM(item).
+ */
Geom::Affine i2doc_affine() const;
+
+ /**
+ * Returns the transformation from item to desktop coords
+ */
Geom::Affine i2dt_affine() const;
+
void set_i2d_affine(Geom::Affine const &transform);
+
+ /**
+ * should rather be named "sp_item_d2i_affine" to match "sp_item_i2d_affine" (or vice versa).
+ */
Geom::Affine dt2i_affine() const;
+ char *_highlightColor;
+
private:
enum EvaluatedStatus
{
@@ -227,18 +376,21 @@ private:
static SPItemView *sp_item_view_new_prepend(SPItemView *list, SPItem *item, unsigned flags, unsigned key, Inkscape::DrawingItem *arenaitem);
static void clip_ref_changed(SPObject *old_clip, SPObject *clip, SPItem *item);
static void mask_ref_changed(SPObject *old_clip, SPObject *clip, SPItem *item);
+ static void fill_ps_ref_changed(SPObject *old_clip, SPObject *clip, SPItem *item);
+ static void stroke_ps_ref_changed(SPObject *old_clip, SPObject *clip, SPItem *item);
public:
virtual void build(SPDocument *document, Inkscape::XML::Node *repr);
virtual void release();
- virtual void set(unsigned int key, gchar const* value);
- virtual void update(SPCtx *ctx, guint flags);
- virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags);
+ virtual void set(unsigned int key, char const* value);
+ virtual void update(SPCtx *ctx, unsigned int flags);
+ virtual void modified(unsigned int flags);
+ virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags);
virtual Geom::OptRect bbox(Geom::Affine const &transform, SPItem::BBoxType type) const;
virtual void print(SPPrintContext *ctx);
virtual const char* displayName() const;
- virtual gchar* description() const;
+ virtual char* description() const;
virtual Inkscape::DrawingItem* show(Inkscape::Drawing &drawing, unsigned int key, unsigned int flags);
virtual void hide(unsigned int key);
virtual void snappoints(std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs) const;
@@ -246,23 +398,22 @@ public:
virtual void convert_to_guides() const;
- virtual gint event(SPEvent *event);
+ virtual int event(SPEvent *event);
};
// Utility
+/**
+ * @pre \a ancestor really is an ancestor (\>=) of \a object, or NULL.
+ * ("Ancestor (\>=)" here includes as far as \a object itself.)
+ */
Geom::Affine i2anc_affine(SPObject const *item, SPObject const *ancestor);
+
Geom::Affine i2i_affine(SPObject const *src, SPObject const *dest);
/* fixme: - these are evil, but OK */
-/* Fill *TRANSFORM with the item-to-desktop transform. See doc/coordinates.txt
- * for a description of `Desktop coordinates'; though see also mental's comment
- * at the top of that file.
- *
- * \return TRANSFORM.
- */
int sp_item_repr_compare_position(SPItem const *first, SPItem const *second);
SPItem *sp_item_first_item_child (SPObject *obj);
SPItem const *sp_item_first_item_child (SPObject const *obj);
diff --git a/src/sp-line.h b/src/sp-line.h
index c1932d3ee..d6a075659 100644
--- a/src/sp-line.h
+++ b/src/sp-line.h
@@ -31,13 +31,13 @@ public:
SVGLength y2;
virtual void build(SPDocument *document, Inkscape::XML::Node *repr);
- virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags);
- virtual void set(unsigned int key, gchar const* value);
+ virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags);
+ virtual void set(unsigned int key, char const* value);
virtual const char* displayName() const;
virtual Geom::Affine set_transform(Geom::Affine const &transform);
virtual void convert_to_guides() const;
- virtual void update(SPCtx* ctx, guint flags);
+ virtual void update(SPCtx* ctx, unsigned int flags);
virtual void set_shape();
};
diff --git a/src/sp-linear-gradient.cpp b/src/sp-linear-gradient.cpp
index 959e8d733..6e9f5e6dd 100644
--- a/src/sp-linear-gradient.cpp
+++ b/src/sp-linear-gradient.cpp
@@ -1,3 +1,5 @@
+#include <cairo.h>
+
#include "sp-linear-gradient.h"
#include "attributes.h"
diff --git a/src/sp-linear-gradient.h b/src/sp-linear-gradient.h
index ac3fdb04a..a152e7fe2 100644
--- a/src/sp-linear-gradient.h
+++ b/src/sp-linear-gradient.h
@@ -26,8 +26,8 @@ public:
protected:
virtual void build(SPDocument *document, Inkscape::XML::Node *repr);
- virtual void set(unsigned key, gchar const *value);
- virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags);
+ virtual void set(unsigned key, char const *value);
+ virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags);
};
#endif /* !SP_LINEAR_GRADIENT_H */
diff --git a/src/sp-lpe-item.cpp b/src/sp-lpe-item.cpp
index 666c79e49..019d15162 100644
--- a/src/sp-lpe-item.cpp
+++ b/src/sp-lpe-item.cpp
@@ -16,6 +16,8 @@
# include "config.h"
#endif
+#include "ui/tool/multi-path-manipulator.h"
+
#include <glibmm/i18n.h>
#include "live_effects/effect.h"
@@ -34,8 +36,16 @@
#include "message-stack.h"
#include "inkscape.h"
#include "desktop.h"
-#include "shape-editor.h"
+#include "ui/shape-editor.h"
#include "sp-ellipse.h"
+#include "display/curve.h"
+#include "svg/svg.h"
+#include <2geom/pathvector.h>
+#include "sp-clippath.h"
+#include "sp-mask.h"
+#include "ui/tools-switch.h"
+#include "ui/tools/node-tool.h"
+#include "ui/tools/tool-base.h"
#include <algorithm>
@@ -46,24 +56,26 @@ static void lpeobject_ref_modified(SPObject *href, guint flags, SPLPEItem *lpeit
static void sp_lpe_item_create_original_path_recursive(SPLPEItem *lpeitem);
static void sp_lpe_item_cleanup_original_path_recursive(SPLPEItem *lpeitem);
+
typedef std::list<std::string> HRefList;
static std::string patheffectlist_write_svg(PathEffectList const & list);
static std::string hreflist_write_svg(HRefList const & list);
-SPLPEItem::SPLPEItem() : SPItem() {
- this->path_effects_enabled = 1;
-
- this->path_effect_list = new PathEffectList();
- this->current_path_effect = NULL;
-
- this->lpe_modified_connection_list = new std::list<sigc::connection>();
+SPLPEItem::SPLPEItem()
+ : SPItem()
+ , path_effects_enabled(1)
+ , path_effect_list(new PathEffectList())
+ , lpe_modified_connection_list(new std::list<sigc::connection>())
+ , current_path_effect(NULL)
+ , lpe_helperpaths()
+{
}
SPLPEItem::~SPLPEItem() {
}
void SPLPEItem::build(SPDocument *document, Inkscape::XML::Node *repr) {
- this->readAttr( "inkscape:path-effect" );
+ this->readAttr( "inkscape:path-effect" );
SPItem::build(document, repr);
}
@@ -166,9 +178,9 @@ void SPLPEItem::set(unsigned int key, gchar const* value) {
}
void SPLPEItem::update(SPCtx* ctx, unsigned int flags) {
- SPItem::update(ctx, flags);
+ SPItem::update(ctx, flags);
- // update the helperpaths of all LPEs applied to the item
+ // update the helperpaths of all LPEs applied to the item
// TODO: re-add for the new node tool
}
@@ -200,11 +212,11 @@ Inkscape::XML::Node* SPLPEItem::write(Inkscape::XML::Document *xml_doc, Inkscape
*/
bool SPLPEItem::performPathEffect(SPCurve *curve) {
if (!this) {
- return false;
+ return false;
}
if (!curve) {
- return false;
+ return false;
}
if (this->hasPathEffect() && this->pathEffectsEnabled()) {
@@ -236,7 +248,7 @@ bool SPLPEItem::performPathEffect(SPCurve *curve) {
// Groups have their doBeforeEffect called elsewhere
if (!SP_IS_GROUP(this)) {
- lpe->doBeforeEffect(this);
+ lpe->doBeforeEffect_impl(this);
}
try {
@@ -250,6 +262,9 @@ bool SPLPEItem::performPathEffect(SPCurve *curve) {
}
return false;
}
+ if (!SP_IS_GROUP(this)) {
+ lpe->doAfterEffect(this);
+ }
}
}
}
@@ -259,7 +274,7 @@ bool SPLPEItem::performPathEffect(SPCurve *curve) {
// CPPIFY: make pure virtual
void SPLPEItem::update_patheffect(bool /*write*/) {
- //throw;
+ //throw;
}
/**
@@ -326,6 +341,18 @@ lpeobject_ref_modified(SPObject */*href*/, guint /*flags*/, SPLPEItem *lpeitem)
static void
sp_lpe_item_create_original_path_recursive(SPLPEItem *lpeitem)
{
+ g_return_if_fail(lpeitem != NULL);
+
+ SPMask * mask = lpeitem->mask_ref->getObject();
+ if(mask)
+ {
+ sp_lpe_item_create_original_path_recursive(SP_LPE_ITEM(mask->firstChild()));
+ }
+ SPClipPath * clipPath = lpeitem->clip_ref->getObject();
+ if(clipPath)
+ {
+ sp_lpe_item_create_original_path_recursive(SP_LPE_ITEM(clipPath->firstChild()));
+ }
if (SP_IS_GROUP(lpeitem)) {
GSList const *item_list = sp_item_group_item_list(SP_GROUP(lpeitem));
for ( GSList const *iter = item_list; iter; iter = iter->next ) {
@@ -346,7 +373,21 @@ sp_lpe_item_create_original_path_recursive(SPLPEItem *lpeitem)
static void
sp_lpe_item_cleanup_original_path_recursive(SPLPEItem *lpeitem)
{
+ g_return_if_fail(lpeitem != NULL);
+
if (SP_IS_GROUP(lpeitem)) {
+ if (!lpeitem->hasPathEffectRecursive()) {
+ SPMask * mask = lpeitem->mask_ref->getObject();
+ if(mask)
+ {
+ sp_lpe_item_cleanup_original_path_recursive(SP_LPE_ITEM(mask->firstChild()));
+ }
+ SPClipPath * clipPath = lpeitem->clip_ref->getObject();
+ if(clipPath)
+ {
+ sp_lpe_item_cleanup_original_path_recursive(SP_LPE_ITEM(clipPath->firstChild()));
+ }
+ }
GSList const *item_list = sp_item_group_item_list(SP_GROUP(lpeitem));
for ( GSList const *iter = item_list; iter; iter = iter->next ) {
SPObject *subitem = static_cast<SPObject *>(iter->data);
@@ -358,6 +399,16 @@ sp_lpe_item_cleanup_original_path_recursive(SPLPEItem *lpeitem)
else if (SP_IS_PATH(lpeitem)) {
Inkscape::XML::Node *repr = lpeitem->getRepr();
if (!lpeitem->hasPathEffectRecursive() && repr->attribute("inkscape:original-d")) {
+ SPMask * mask = lpeitem->mask_ref->getObject();
+ if(mask)
+ {
+ sp_lpe_item_cleanup_original_path_recursive(SP_LPE_ITEM(mask->firstChild()));
+ }
+ SPClipPath * clipPath = lpeitem->clip_ref->getObject();
+ if(clipPath)
+ {
+ sp_lpe_item_cleanup_original_path_recursive(SP_LPE_ITEM(clipPath->firstChild()));
+ }
repr->setAttribute("d", repr->attribute("inkscape:original-d"));
repr->setAttribute("inkscape:original-d", NULL);
}
@@ -416,6 +467,15 @@ void SPLPEItem::addPathEffect(gchar *value, bool reset)
// Apply the path effect
sp_lpe_item_update_patheffect(this, true, true);
+
+ //fix bug 1219324
+ if (SP_ACTIVE_DESKTOP ) {
+ Inkscape::UI::Tools::ToolBase *ec = SP_ACTIVE_DESKTOP->event_context;
+ if (INK_IS_NODE_TOOL(ec)) {
+ tools_switch(SP_ACTIVE_DESKTOP, TOOLS_LPETOOL); //mhh
+ tools_switch(SP_ACTIVE_DESKTOP, TOOLS_NODES);
+ }
+ }
}
}
@@ -427,41 +487,51 @@ void SPLPEItem::addPathEffect(LivePathEffectObject * new_lpeobj)
g_free(hrefstr);
}
+/**
+ * If keep_path == true, the item should not be updated, effectively 'flattening' the LPE.
+ */
void SPLPEItem::removeCurrentPathEffect(bool keep_paths)
{
Inkscape::LivePathEffect::LPEObjectReference* lperef = this->getCurrentLPEReference();
if (!lperef)
return;
+ if (Inkscape::LivePathEffect::Effect* effect_ = this->getCurrentLPE()) {
+ effect_->doOnRemove(this);
+ }
PathEffectList new_list = *this->path_effect_list;
new_list.remove(lperef); //current lpe ref is always our 'own' pointer from the path_effect_list
std::string r = patheffectlist_write_svg(new_list);
-
+
if (!r.empty()) {
this->getRepr()->setAttribute("inkscape:path-effect", r.c_str());
} else {
this->getRepr()->setAttribute("inkscape:path-effect", NULL);
+ }
+
+ if (!keep_paths) {
// Make sure that ellipse is stored as <svg:circle> or <svg:ellipse> if possible.
if( SP_IS_GENERICELLIPSE(this)) {
SP_GENERICELLIPSE(this)->write( this->getRepr()->document(), this->getRepr(), SP_OBJECT_WRITE_EXT );
}
- }
- if (!keep_paths) {
sp_lpe_item_cleanup_original_path_recursive(this);
}
}
+/**
+ * If keep_path == true, the item should not be updated, effectively 'flattening' the LPE.
+ */
void SPLPEItem::removeAllPathEffects(bool keep_paths)
{
this->getRepr()->setAttribute("inkscape:path-effect", NULL);
- // Make sure that ellipse is stored as <svg:circle> or <svg:ellipse> if possible.
- if( SP_IS_GENERICELLIPSE(this)) {
- SP_GENERICELLIPSE(this)->write( this->getRepr()->document(), this->getRepr(), SP_OBJECT_WRITE_EXT );
- }
-
if (!keep_paths) {
+ // Make sure that ellipse is stored as <svg:circle> or <svg:ellipse> if possible.
+ if (SP_IS_GENERICELLIPSE(this)) {
+ SP_GENERICELLIPSE(this)->write(this->getRepr()->document(), this->getRepr(), SP_OBJECT_WRITE_EXT);
+ }
+
sp_lpe_item_cleanup_original_path_recursive(this);
}
}
@@ -574,6 +644,160 @@ bool SPLPEItem::hasPathEffectRecursive() const
return hasPathEffect();
}
}
+void
+SPLPEItem::apply_to_clippath(SPItem *item)
+{
+ SPClipPath *clipPath = item->clip_ref->getObject();
+ if(clipPath) {
+ SPObject * clip_data = clipPath->firstChild();
+ SPCurve * clip_curve = NULL;
+
+ if (SP_IS_PATH(clip_data)) {
+ clip_curve = SP_PATH(clip_data)->get_original_curve();
+ } else if(SP_IS_SHAPE(clip_data)) {
+ clip_curve = SP_SHAPE(clip_data)->getCurve();
+ } else if(SP_IS_GROUP(clip_data)) {
+ apply_to_clip_or_mask_group(SP_ITEM(clip_data), item);
+ return;
+ }
+ if(clip_curve) {
+ bool success = false;
+ if(SP_IS_GROUP(this)){
+ clip_curve->transform(i2anc_affine(SP_GROUP(item), SP_GROUP(this)));
+ success = this->performPathEffect(clip_curve);
+ clip_curve->transform(i2anc_affine(SP_GROUP(item), SP_GROUP(this)).inverse());
+ } else {
+ success = this->performPathEffect(clip_curve);
+ }
+ Inkscape::XML::Node *reprClip = clip_data->getRepr();
+ if (success) {
+ gchar *str = sp_svg_write_path(clip_curve->get_pathvector());
+ reprClip->setAttribute("d", str);
+ g_free(str);
+ } else {
+ // LPE was unsuccesfull. Read the old 'd'-attribute.
+ if (gchar const * value = reprClip->attribute("d")) {
+ Geom::PathVector pv = sp_svg_read_pathv(value);
+ SPCurve *oldcurve = new SPCurve(pv);
+ if (oldcurve) {
+ SP_SHAPE(clip_data)->setCurve(oldcurve, TRUE);
+ oldcurve->unref();
+ }
+ }
+ }
+ clip_curve->unref();
+ }
+ }
+ if(SP_IS_GROUP(item)){
+ GSList const *item_list = sp_item_group_item_list(SP_GROUP(item));
+ for ( GSList const *iter = item_list; iter; iter = iter->next ) {
+ SPObject *subitem = static_cast<SPObject *>(iter->data);
+ apply_to_clippath(SP_ITEM(subitem));
+ }
+ }
+}
+
+void
+SPLPEItem::apply_to_mask(SPItem *item)
+{
+ SPMask *mask = item->mask_ref->getObject();
+ if(mask) {
+ SPObject *mask_data = mask->firstChild();
+ SPCurve * mask_curve = NULL;
+ if (SP_IS_PATH(mask_data)) {
+ mask_curve = SP_PATH(mask_data)->get_original_curve();
+ } else if(SP_IS_SHAPE(mask_data)) {
+ mask_curve = SP_SHAPE(mask_data)->getCurve();
+ } else if(SP_IS_GROUP(mask_data)) {
+ apply_to_clip_or_mask_group(SP_ITEM(mask_data), item);
+ return;
+ }
+ if(mask_curve) {
+ bool success = false;
+ if(SP_IS_GROUP(this)){
+ mask_curve->transform(i2anc_affine(SP_GROUP(item), SP_GROUP(this)));
+ success = this->performPathEffect(mask_curve);
+ mask_curve->transform(i2anc_affine(SP_GROUP(item), SP_GROUP(this)).inverse());
+ } else {
+ success = this->performPathEffect(mask_curve);
+ }
+ Inkscape::XML::Node *reprmask = mask_data->getRepr();
+ if (success) {
+ gchar *str = sp_svg_write_path(mask_curve->get_pathvector());
+ reprmask->setAttribute("d", str);
+ g_free(str);
+ } else {
+ // LPE was unsuccesfull. Read the old 'd'-attribute.
+ if (gchar const * value = reprmask->attribute("d")) {
+ Geom::PathVector pv = sp_svg_read_pathv(value);
+ SPCurve *oldcurve = new SPCurve(pv);
+ if (oldcurve) {
+ SP_SHAPE(mask_data)->setCurve(oldcurve, TRUE);
+ oldcurve->unref();
+ }
+ }
+ }
+ mask_curve->unref();
+ }
+ }
+ if(SP_IS_GROUP(item)){
+ GSList const *item_list = sp_item_group_item_list(SP_GROUP(item));
+ for ( GSList const *iter = item_list; iter; iter = iter->next ) {
+ SPObject *subitem = static_cast<SPObject *>(iter->data);
+ apply_to_mask(SP_ITEM(subitem));
+ }
+ }
+}
+
+void
+SPLPEItem::apply_to_clip_or_mask_group(SPItem *group, SPItem *item)
+{
+ if (!SP_IS_GROUP(group)) {
+ return;
+ }
+ GSList *item_list = sp_item_group_item_list(SP_GROUP(group));
+ for ( GSList *iter = item_list; iter; iter = iter->next ) {
+ SPObject *subitem = static_cast<SPObject *>(iter->data);
+ if (SP_IS_GROUP(subitem)) {
+ apply_to_clip_or_mask_group(SP_ITEM(subitem), item);
+ } else if (SP_IS_SHAPE(subitem)) {
+ SPCurve * c = NULL;
+
+ if (SP_IS_PATH(subitem)) {
+ c = SP_PATH(subitem)->get_original_curve();
+ } else {
+ c = SP_SHAPE(subitem)->getCurve();
+ }
+ if (c) {
+ bool success = false;
+ if(SP_IS_GROUP(group)){
+ c->transform(i2anc_affine(SP_GROUP(item), SP_GROUP(this)));
+ success = this->performPathEffect(c);
+ c->transform(i2anc_affine(SP_GROUP(item), SP_GROUP(this)).inverse());
+ } else {
+ success = this->performPathEffect(c);
+ }
+ Inkscape::XML::Node *repr = subitem->getRepr();
+ if (success) {
+ gchar *str = sp_svg_write_path(c->get_pathvector());
+ repr->setAttribute("d", str);
+ g_free(str);
+ } else {
+ // LPE was unsuccesfull. Read the old 'd'-attribute.
+ if (gchar const * value = repr->attribute("d")) {
+ Geom::PathVector pv = sp_svg_read_pathv(value);
+ SPCurve *oldcurve = new SPCurve(pv);
+ if (oldcurve) {
+ SP_SHAPE(subitem)->setCurve(oldcurve, TRUE);
+ oldcurve->unref();
+ }
+ }
+ }
+ c->unref();
+ }
+ }
+ }
+}
Inkscape::LivePathEffect::Effect*
SPLPEItem::getPathEffectOfType(int type)
@@ -591,6 +815,22 @@ SPLPEItem::getPathEffectOfType(int type)
return NULL;
}
+Inkscape::LivePathEffect::Effect const*
+SPLPEItem::getPathEffectOfType(int type) const
+{
+ std::list<Inkscape::LivePathEffect::LPEObjectReference *>::const_iterator i;
+ for (i = path_effect_list->begin(); i != path_effect_list->end(); ++i) {
+ LivePathEffectObject const *lpeobj = (*i)->lpeobject;
+ if (lpeobj) {
+ Inkscape::LivePathEffect::Effect const *lpe = lpeobj->get_lpe();
+ if (lpe && (lpe->effectType() == type)) {
+ return lpe;
+ }
+ }
+ }
+ return NULL;
+}
+
void SPLPEItem::editNextParamOncanvas(SPDesktop *dt)
{
Inkscape::LivePathEffect::LPEObjectReference *lperef = this->getCurrentLPEReference();
diff --git a/src/sp-lpe-item.h b/src/sp-lpe-item.h
index cd72ac55b..9c052b7b1 100644
--- a/src/sp-lpe-item.h
+++ b/src/sp-lpe-item.h
@@ -14,14 +14,12 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include "sp-item.h"
-
#include <list>
+#include "sp-item.h"
#define SP_LPE_ITEM(obj) (dynamic_cast<SPLPEItem*>((SPObject*)obj))
#define SP_IS_LPE_ITEM(obj) (dynamic_cast<const SPLPEItem*>((SPObject*)obj) != NULL)
-class CLPEItem;
class LivePathEffectObject;
class SPCurve;
class SPDesktop;
@@ -58,7 +56,7 @@ public:
virtual void build(SPDocument* doc, Inkscape::XML::Node* repr);
virtual void release();
- virtual void set(unsigned int key, gchar const* value);
+ virtual void set(unsigned int key, char const* value);
virtual void update(SPCtx* ctx, unsigned int flags);
virtual void modified(unsigned int flags);
@@ -66,7 +64,7 @@ public:
virtual void child_added(Inkscape::XML::Node* child, Inkscape::XML::Node* ref);
virtual void remove_child(Inkscape::XML::Node* child);
- virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags);
+ virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags);
virtual void update_patheffect(bool write);
@@ -77,6 +75,7 @@ public:
bool hasPathEffectOfType(int const type) const;
bool hasPathEffectRecursive() const;
Inkscape::LivePathEffect::Effect* getPathEffectOfType(int type);
+ Inkscape::LivePathEffect::Effect const* getPathEffectOfType(int type) const;
bool hasBrokenPathEffect() const;
PathEffectList getEffectList();
@@ -89,9 +88,11 @@ public:
bool setCurrentPathEffect(Inkscape::LivePathEffect::LPEObjectReference* lperef);
void removeCurrentPathEffect(bool keep_paths);
void removeAllPathEffects(bool keep_paths);
- void addPathEffect(gchar *value, bool reset);
+ void addPathEffect(char *value, bool reset);
void addPathEffect(LivePathEffectObject * new_lpeobj);
-
+ void apply_to_mask(SPItem * item);
+ void apply_to_clippath(SPItem * item);
+ void apply_to_clip_or_mask_group(SPItem * group, SPItem * item);
bool forkPathEffectsIfNecessary(unsigned int nr_of_allowed_users = 1);
void editNextParamOncanvas(SPDesktop *dt);
diff --git a/src/marker.cpp b/src/sp-marker.cpp
index 7fee16ead..e955594ab 100644
--- a/src/marker.cpp
+++ b/src/sp-marker.cpp
@@ -24,7 +24,7 @@
#include "display/drawing-group.h"
#include "xml/repr.h"
#include "attributes.h"
-#include "marker.h"
+#include "sp-marker.h"
#include "document.h"
#include "document-private.h"
#include "preferences.h"
@@ -52,7 +52,7 @@ SPMarker::SPMarker() : SPGroup(), SPViewBox() {
this->markerUnits = 0;
this->markerUnits_set = 0;
- this->orient_auto = 0;
+ this->orient_mode = MARKER_ORIENT_ANGLE;
this->orient_set = 0;
this->orient = 0;
@@ -158,16 +158,20 @@ void SPMarker::set(unsigned int key, const gchar* value) {
case SP_ATTR_ORIENT:
this->orient_set = FALSE;
- this->orient_auto = FALSE;
+ this->orient_mode = MARKER_ORIENT_ANGLE;
this->orient = 0.0;
if (value) {
- if (!strcmp (value, "auto")) {
- this->orient_auto = TRUE;
- this->orient_set = TRUE;
- } else if (sp_svg_number_read_f (value, &this->orient)) {
- this->orient_set = TRUE;
- }
+ if (!strcmp (value, "auto")) {
+ this->orient_mode = MARKER_ORIENT_AUTO;
+ this->orient_set = TRUE;
+ } else if (!strcmp (value, "auto-start-reverse")) {
+ this->orient_mode = MARKER_ORIENT_AUTO_START_REVERSE;
+ this->orient_set = TRUE;
+ } else if (sp_svg_number_read_f (value, &this->orient)) {
+ this->orient_mode = MARKER_ORIENT_ANGLE;
+ this->orient_set = TRUE;
+ }
}
this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
@@ -264,15 +268,17 @@ Inkscape::XML::Node* SPMarker::write(Inkscape::XML::Document *xml_doc, Inkscape:
}
if (this->orient_set) {
- if (this->orient_auto) {
- repr->setAttribute("orient", "auto");
- } else {
- sp_repr_set_css_double(repr, "orient", this->orient);
- }
+ if (this->orient_mode == MARKER_ORIENT_AUTO) {
+ repr->setAttribute("orient", "auto");
+ } else if (this->orient_mode == MARKER_ORIENT_AUTO_START_REVERSE) {
+ repr->setAttribute("orient", "auto-start-reverse");
+ } else {
+ sp_repr_set_css_double(repr, "orient", this->orient);
+ }
} else {
- repr->setAttribute("orient", NULL);
+ repr->setAttribute("orient", NULL);
}
-
+
/* fixme: */
//XML Tree being used directly here while it shouldn't be....
repr->setAttribute("viewBox", this->getRepr()->attribute("viewBox"));
@@ -381,7 +387,10 @@ sp_marker_show_instance ( SPMarker *marker, Inkscape::DrawingItem *parent,
}
if (v->items[pos]) {
Geom::Affine m;
- if (marker->orient_auto) {
+ if (marker->orient_mode == MARKER_ORIENT_AUTO) {
+ m = base;
+ } else if (marker->orient_mode == MARKER_ORIENT_AUTO_START_REVERSE) {
+ m = Geom::Rotate::from_degrees( 180.0 ) * base;
m = base;
} else {
/* fixme: Orient units (Lauris) */
diff --git a/src/marker.h b/src/sp-marker.h
index 585615476..b58523251 100644
--- a/src/marker.h
+++ b/src/sp-marker.h
@@ -1,5 +1,5 @@
-#ifndef __SP_MARKER_H__
-#define __SP_MARKER_H__
+#ifndef SEEN_SP_MARKER_H
+#define SEEN_SP_MARKER_H
/*
* SVG <marker> implementation
@@ -12,7 +12,6 @@
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-
/*
* This is quite similar in logic to <svg>
* Maybe we should merge them somehow (Lauris)
@@ -26,12 +25,19 @@ struct SPMarkerView;
#include <2geom/rect.h>
#include <2geom/affine.h>
-#include "svg/svg-length.h"
+
#include "enums.h"
+#include "svg/svg-length.h"
#include "sp-item-group.h"
#include "uri-references.h"
#include "viewbox.h"
+enum markerOrient {
+ MARKER_ORIENT_ANGLE,
+ MARKER_ORIENT_AUTO,
+ MARKER_ORIENT_AUTO_START_REVERSE
+};
+
class SPMarker : public SPGroup, public SPViewBox {
public:
SPMarker();
@@ -51,7 +57,7 @@ public:
/* orient */
unsigned int orient_set : 1;
- unsigned int orient_auto : 1;
+ markerOrient orient_mode : 2;
float orient;
/* Private views */
@@ -87,7 +93,7 @@ Inkscape::DrawingItem *sp_marker_show_instance (SPMarker *marker, Inkscape::Draw
unsigned int key, unsigned int pos,
Geom::Affine const &base, float linewidth);
void sp_marker_hide (SPMarker *marker, unsigned int key);
-const gchar *generate_marker (GSList *reprs, Geom::Rect bounds, SPDocument *document, Geom::Point center, Geom::Affine move);
+const char *generate_marker (GSList *reprs, Geom::Rect bounds, SPDocument *document, Geom::Point center, Geom::Affine move);
SPObject *sp_marker_fork_if_necessary(SPObject *marker);
#endif
diff --git a/src/sp-mask.h b/src/sp-mask.h
index e08d1e81e..e991fedb6 100644
--- a/src/sp-mask.h
+++ b/src/sp-mask.h
@@ -55,12 +55,12 @@ protected:
virtual void child_added(Inkscape::XML::Node* child, Inkscape::XML::Node* ref);
- virtual void set(unsigned int key, const gchar* value);
+ virtual void set(unsigned int key, const char* value);
virtual void update(SPCtx* ctx, unsigned int flags);
virtual void modified(unsigned int flags);
- virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, guint flags);
+ virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, unsigned int flags);
};
class SPMaskReference : public Inkscape::URIReference {
@@ -86,10 +86,10 @@ protected:
Inkscape::XML::Node * const owner_repr = owner->getRepr();
//XML Tree being used directly here while it shouldn't be...
Inkscape::XML::Node * const obj_repr = obj->getRepr();
- gchar const * owner_name = NULL;
- gchar const * owner_mask = NULL;
- gchar const * obj_name = NULL;
- gchar const * obj_id = NULL;
+ char const * owner_name = NULL;
+ char const * owner_mask = NULL;
+ char const * obj_name = NULL;
+ char const * obj_id = NULL;
if (owner_repr != NULL) {
owner_name = owner_repr->name();
owner_mask = owner_repr->attribute("mask");
@@ -98,7 +98,7 @@ protected:
obj_name = obj_repr->name();
obj_id = obj_repr->attribute("id");
}
- g_warning("Ignoring recursive mask reference "
+ printf("WARNING: Ignoring recursive mask reference "
"<%s mask=\"%s\"> in <%s id=\"%s\">",
owner_name, owner_mask,
obj_name, obj_id);
@@ -108,6 +108,6 @@ protected:
}
};
-const gchar *sp_mask_create (GSList *reprs, SPDocument *document, Geom::Affine const* applyTransform);
+const char *sp_mask_create (GSList *reprs, SPDocument *document, Geom::Affine const* applyTransform);
#endif // SEEN_SP_MASK_H
diff --git a/src/sp-mesh-array.cpp b/src/sp-mesh-array.cpp
index ab14e75d2..8bfe23656 100644
--- a/src/sp-mesh-array.cpp
+++ b/src/sp-mesh-array.cpp
@@ -37,6 +37,15 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
+#include <glibmm.h>
+
+// For color picking
+#include "display/drawing.h"
+#include "display/drawing-context.h"
+#include "display/cairo-utils.h"
+#include "document.h"
+#include "sp-root.h"
+
#include "sp-mesh-array.h"
#include "sp-mesh-gradient.h"
#include "sp-mesh-row.h"
@@ -51,13 +60,6 @@
// For writing color/opacity to style
#include "svg/css-ostringstream.h"
-// For color picking
-#include "display/drawing.h"
-#include "display/drawing-context.h"
-#include "display/cairo-utils.h"
-#include "document.h"
-#include "sp-root.h"
-
// For default color
#include "style.h"
#include "svg/svg-color.h"
diff --git a/src/sp-mesh-array.h b/src/sp-mesh-array.h
index b10974e7e..330f6d87b 100644
--- a/src/sp-mesh-array.h
+++ b/src/sp-mesh-array.h
@@ -39,8 +39,6 @@
an array which simplifies things like inserting new rows or columns.
*/
-#include <gdk/gdk.h>
-#include <glibmm/ustring.h>
#include <2geom/point.h>
#include "color.h"
@@ -89,13 +87,13 @@ public:
opacity = 0.0;
}
NodeType node_type;
- guint node_edge;
+ unsigned int node_edge;
bool set;
Geom::Point p;
- guint draggable; // index of on-screen node
- gchar path_type;
+ unsigned int draggable; // index of on-screen node
+ char path_type;
SPColor color;
- gdouble opacity;
+ double opacity;
};
@@ -110,21 +108,21 @@ private:
public:
SPMeshPatchI( std::vector<std::vector< SPMeshNode* > > *n, int r, int c );
- Geom::Point getPoint( guint side, guint point );
- std::vector< Geom::Point > getPointsForSide( guint i );
- void setPoint( guint side, guint point, Geom::Point p, bool set = true );
- gchar getPathType( guint i );
- void setPathType( guint, gchar t );
- Geom::Point getTensorPoint( guint i );
- void setTensorPoint( guint i, Geom::Point p );
+ Geom::Point getPoint( unsigned int side, unsigned int point );
+ std::vector< Geom::Point > getPointsForSide( unsigned int i );
+ void setPoint( unsigned int side, unsigned int point, Geom::Point p, bool set = true );
+ char getPathType( unsigned int i );
+ void setPathType( unsigned int, char t );
+ Geom::Point getTensorPoint( unsigned int i );
+ void setTensorPoint( unsigned int i, Geom::Point p );
bool tensorIsSet();
- bool tensorIsSet( guint i );
- Geom::Point coonsTensorPoint( guint i );
+ bool tensorIsSet( unsigned int i );
+ Geom::Point coonsTensorPoint( unsigned int i );
void updateNodes();
- SPColor getColor( guint i );
- void setColor( guint i, SPColor c );
- gdouble getOpacity( guint i );
- void setOpacity( guint i, gdouble o );
+ SPColor getColor( unsigned int i );
+ void setColor( unsigned int i, SPColor c );
+ double getOpacity( unsigned int i );
+ void setOpacity( unsigned int i, double o );
};
class SPMeshGradient;
@@ -160,26 +158,26 @@ public:
void print();
// Get size of patch
- guint patch_rows();
- guint patch_columns();
+ unsigned int patch_rows();
+ unsigned int patch_columns();
- SPMeshNode * node( guint i, guint j ) { return nodes[i][j]; }
+ SPMeshNode * node( unsigned int i, unsigned int j ) { return nodes[i][j]; }
// Operations on corners
- bool adjacent_corners( guint i, guint j, SPMeshNode* n[4] );
- guint side_toggle( std::vector< guint > );
- guint side_arc( std::vector< guint > );
- guint tensor_toggle( std::vector< guint > );
- guint color_smooth( std::vector< guint > );
- guint color_pick( std::vector< guint >, SPItem* );
+ bool adjacent_corners( unsigned int i, unsigned int j, SPMeshNode* n[4] );
+ unsigned int side_toggle( std::vector< unsigned int > );
+ unsigned int side_arc( std::vector< unsigned int > );
+ unsigned int tensor_toggle( std::vector< unsigned int > );
+ unsigned int color_smooth( std::vector< unsigned int > );
+ unsigned int color_pick( std::vector< unsigned int >, SPItem* );
// Update other nodes in response to a node move.
- void update_handles( guint corner, std::vector< guint > selected_corners, Geom::Point old_p, MeshNodeOperation op );
+ void update_handles( unsigned int corner, std::vector< unsigned int > selected_corners, Geom::Point old_p, MeshNodeOperation op );
- void split_row( guint i, guint n );
- void split_column( guint j, guint n );
- void split_row( guint i, double coord );
- void split_column( guint j, double coord );
+ void split_row( unsigned int i, unsigned int n );
+ void split_column( unsigned int j, unsigned int n );
+ void split_row( unsigned int i, double coord );
+ void split_column( unsigned int j, double coord );
};
#endif /* !SEEN_SP_MESH_ARRAY_H */
diff --git a/src/sp-mesh-gradient.cpp b/src/sp-mesh-gradient.cpp
index eb5ed1bd0..bf28164a9 100644
--- a/src/sp-mesh-gradient.cpp
+++ b/src/sp-mesh-gradient.cpp
@@ -1,8 +1,10 @@
-#include "sp-mesh-gradient.h"
+#include <glibmm.h>
#include "attributes.h"
-#include "xml/repr.h"
#include "display/cairo-utils.h"
+#include "xml/repr.h"
+
+#include "sp-mesh-gradient.h"
#include "sp-factory.h"
diff --git a/src/sp-mesh-gradient.h b/src/sp-mesh-gradient.h
index 0b570c4dd..4df753f62 100644
--- a/src/sp-mesh-gradient.h
+++ b/src/sp-mesh-gradient.h
@@ -24,8 +24,8 @@ public:
protected:
virtual void build(SPDocument *document, Inkscape::XML::Node *repr);
- virtual void set(unsigned key, gchar const *value);
- virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags);
+ virtual void set(unsigned key, char const *value);
+ virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags);
};
#endif /* !SP_MESH_GRADIENT_H */
diff --git a/src/sp-mesh-patch.h b/src/sp-mesh-patch.h
index ddade6503..e57ad1699 100644
--- a/src/sp-mesh-patch.h
+++ b/src/sp-mesh-patch.h
@@ -12,9 +12,7 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include <glib.h>
#include <glibmm/ustring.h>
-//#include "svg/svg-length.h"
#include "sp-object.h"
#define SP_MESHPATCH(obj) (dynamic_cast<SPMeshPatch*>((SPObject*)obj))
@@ -34,8 +32,8 @@ public:
protected:
virtual void build(SPDocument* doc, Inkscape::XML::Node* repr);
- virtual void set(unsigned int key, const gchar* value);
- virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, guint flags);
+ virtual void set(unsigned int key, const char* value);
+ virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, unsigned int flags);
};
#endif /* !SEEN_SP_MESHPATCH_H */
diff --git a/src/sp-mesh-row.h b/src/sp-mesh-row.h
index e39bdc631..793b5a645 100644
--- a/src/sp-mesh-row.h
+++ b/src/sp-mesh-row.h
@@ -11,7 +11,6 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include <glib.h>
#include "sp-object.h"
#define SP_MESHROW(obj) (dynamic_cast<SPMeshRow*>((SPObject*)obj))
@@ -28,8 +27,8 @@ public:
protected:
virtual void build(SPDocument* doc, Inkscape::XML::Node* repr);
- virtual void set(unsigned int key, const gchar* value);
- virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, guint flags);
+ virtual void set(unsigned int key, const char* value);
+ virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, unsigned int flags);
};
#endif /* !SEEN_SP_MESHROW_H */
diff --git a/src/sp-metadata.h b/src/sp-metadata.h
index 2a9d58e11..a89020390 100644
--- a/src/sp-metadata.h
+++ b/src/sp-metadata.h
@@ -1,5 +1,5 @@
-#ifndef __SP_METADATA_H__
-#define __SP_METADATA_H__
+#ifndef SEEN_SP_METADATA_H
+#define SEEN_SP_METADATA_H
/*
* SVG <metadata> implementation
@@ -14,7 +14,6 @@
#include "sp-object.h"
-
/* Metadata base class */
#define SP_METADATA(obj) (dynamic_cast<SPMetadata*>((SPObject*)obj))
@@ -29,9 +28,9 @@ protected:
virtual void build(SPDocument* doc, Inkscape::XML::Node* repr);
virtual void release();
- virtual void set(unsigned int key, const gchar* value);
+ virtual void set(unsigned int key, const char* value);
virtual void update(SPCtx* ctx, unsigned int flags);
- virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, guint flags);
+ virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, unsigned int flags);
};
SPMetadata * sp_document_metadata (SPDocument *document);
diff --git a/src/sp-missing-glyph.h b/src/sp-missing-glyph.h
index a72ed0e99..06bc92231 100644
--- a/src/sp-missing-glyph.h
+++ b/src/sp-missing-glyph.h
@@ -1,9 +1,5 @@
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#ifndef __SP_MISSING_GLYPH_H__
-#define __SP_MISSING_GLYPH_H__
+#ifndef SEEN_SP_MISSING_GLYPH_H
+#define SEEN_SP_MISSING_GLYPH_H
/*
* SVG <missing-glyph> element implementation
@@ -31,8 +27,8 @@ public:
protected:
virtual void build(SPDocument* doc, Inkscape::XML::Node* repr);
virtual void release();
- virtual void set(unsigned int key, const gchar* value);
- virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, guint flags);
+ virtual void set(unsigned int key, char const* value);
+ virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, unsigned int flags);
private:
double horiz_adv_x;
diff --git a/src/sp-namedview.cpp b/src/sp-namedview.cpp
index a01ba891e..b68421dc6 100644
--- a/src/sp-namedview.cpp
+++ b/src/sp-namedview.cpp
@@ -72,7 +72,7 @@ SPNamedView::SPNamedView() : SPObjectGroup(), snap_manager(this) {
this->guidehicolor = 0;
this->views = NULL;
this->borderlayer = 0;
- this->units = NULL;
+ this->page_size_units = NULL;
this->window_x = 0;
this->cy = 0;
this->window_y = 0;
@@ -581,6 +581,7 @@ void SPNamedView::set(unsigned int key, const gchar* value) {
break;
}
case SP_ATTR_UNITS: {
+ // Only used in "Custom size" section of Document Properties dialog
Inkscape::Util::Unit const *new_unit = NULL;
if (value) {
@@ -599,7 +600,7 @@ void SPNamedView::set(unsigned int key, const gchar* value) {
/* fixme: Don't use g_log (see above). */
}
}
- this->units = new_unit;
+ this->page_size_units = new_unit;
this->requestModified(SP_OBJECT_MODIFIED_FLAG);
break;
}
@@ -935,7 +936,7 @@ void SPNamedView::hide(SPDesktop const *desktop)
views = g_slist_remove(views, desktop);
}
-void SPNamedView::activateGuides(gpointer desktop, gboolean active)
+void SPNamedView::activateGuides(void* desktop, bool active)
{
g_assert(desktop != NULL);
g_assert(g_slist_find(views, desktop));
@@ -956,14 +957,10 @@ static void sp_namedview_setup_guides(SPNamedView *nv)
static void sp_namedview_show_single_guide(SPGuide* guide, bool show)
{
- for (GSList *v = guide->views; v != NULL; v = v->next) {
- if (show) {
- sp_canvas_item_show(SP_CANVAS_ITEM(v->data));
- sp_canvas_item_show(SP_CANVAS_ITEM(SP_GUIDELINE(v->data)->origin));
- } else {
- sp_canvas_item_hide(SP_CANVAS_ITEM(v->data));
- sp_canvas_item_hide(SP_CANVAS_ITEM(SP_GUIDELINE(v->data)->origin));
- }
+ if (show) {
+ guide->showSPGuide();
+ } else {
+ guide->hideSPGuide();
}
}
@@ -1156,9 +1153,9 @@ Inkscape::CanvasGrid * sp_namedview_get_first_enabled_grid(SPNamedView *namedvie
void SPNamedView::translateGuides(Geom::Translate const &tr) {
for (GSList *l = guides; l != NULL; l = l->next) {
SPGuide &guide = *SP_GUIDE(l->data);
- Geom::Point point_on_line = guide.point_on_line;
+ Geom::Point point_on_line = guide.getPoint();
point_on_line *= tr;
- sp_guide_moveto(guide, point_on_line, true);
+ guide.moveto(point_on_line, true);
}
}
diff --git a/src/sp-namedview.h b/src/sp-namedview.h
index 05cbcc398..4746b2962 100644
--- a/src/sp-namedview.h
+++ b/src/sp-namedview.h
@@ -29,6 +29,9 @@ namespace Inkscape {
}
}
+typedef unsigned int guint32;
+typedef guint32 GQuark;
+
enum {
SP_BORDER_LAYER_BOTTOM,
SP_BORDER_LAYER_TOP
@@ -48,18 +51,18 @@ public:
double zoom;
double cx;
double cy;
- gint window_width;
- gint window_height;
- gint window_x;
- gint window_y;
- gint window_maximized;
+ int window_width;
+ int window_height;
+ int window_x;
+ int window_y;
+ int window_maximized;
SnapManager snap_manager;
GSList * grids;
bool grids_visible;
Inkscape::Util::Unit const *doc_units;
- Inkscape::Util::Unit const *units;
+ Inkscape::Util::Unit const *page_size_units; // Only used in "Custom size" part of Document Properties dialog
GQuark default_layer_id;
@@ -74,13 +77,13 @@ public:
GSList *guides;
GSList *views;
- gint viewcount;
+ int viewcount;
void show(SPDesktop *desktop);
void hide(SPDesktop const *desktop);
- void activateGuides(gpointer desktop, gboolean active);
- gchar const *getName() const;
- guint getViewCount();
+ void activateGuides(void* desktop, bool active);
+ char const *getName() const;
+ unsigned int getViewCount();
GSList const *getViewList() const;
Inkscape::Util::Unit const * getDefaultUnit() const;
@@ -100,17 +103,17 @@ private:
protected:
virtual void build(SPDocument *document, Inkscape::XML::Node *repr);
virtual void release();
- virtual void set(unsigned int key, gchar const* value);
+ virtual void set(unsigned int key, char const* value);
virtual void child_added(Inkscape::XML::Node* child, Inkscape::XML::Node* ref);
virtual void remove_child(Inkscape::XML::Node* child);
- virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags);
+ virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags);
};
-SPNamedView *sp_document_namedview(SPDocument *document, gchar const *name);
-SPNamedView const *sp_document_namedview(SPDocument const *document, gchar const *name);
+SPNamedView *sp_document_namedview(SPDocument *document, char const *name);
+SPNamedView const *sp_document_namedview(SPDocument const *document, char const *name);
void sp_namedview_window_from_document(SPDesktop *desktop);
void sp_namedview_document_from_window(SPDesktop *desktop);
diff --git a/src/sp-object-group.h b/src/sp-object-group.h
index 4df346228..dcaa8a1d0 100644
--- a/src/sp-object-group.h
+++ b/src/sp-object-group.h
@@ -30,7 +30,7 @@ protected:
virtual void order_changed(Inkscape::XML::Node* child, Inkscape::XML::Node* old, Inkscape::XML::Node* new_repr);
- virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags);
+ virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags);
};
#endif // SEEN_SP_OBJECTGROUP_H
diff --git a/src/sp-object.cpp b/src/sp-object.cpp
index be3a1ab9d..024fce85a 100644
--- a/src/sp-object.cpp
+++ b/src/sp-object.cpp
@@ -406,9 +406,9 @@ void SPObject::requestOrphanCollection() {
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
// do not remove style or script elements (Bug #276244)
- if (SP_IS_STYLE_ELEM(this)) {
+ if (dynamic_cast<SPStyleElem *>(this)) {
// leave it
- } else if (SP_IS_SCRIPT(this)) {
+ } else if (dynamic_cast<SPScript *>(this)) {
// leave it
} else if ((! prefs->getBool("/options/cleanupswatches/value", false)) && SP_IS_PAINT_SERVER(this) && static_cast<SPPaintServer*>(this)->isSwatch() ) {
@@ -460,6 +460,23 @@ void SPObject::deleteObject(bool propagate, bool propagate_descendants)
sp_object_unref(this, NULL);
}
+void SPObject::cropToObject(SPObject *except)
+{
+ std::vector<SPObject*> toDelete;
+ for ( SPObject *child = this->firstChild(); child; child = child->getNext() ) {
+ if (SP_IS_ITEM(child)) {
+ if (child->isAncestorOf(except)) {
+ child->cropToObject(except);
+ } else if(child != except) {
+ toDelete.push_back(child);
+ }
+ }
+ }
+ for (std::size_t i = 0; i < toDelete.size(); ++i) {
+ (toDelete[i])->deleteObject(true, true);
+ }
+}
+
void SPObject::attach(SPObject *object, SPObject *prev)
{
//g_return_if_fail(parent != NULL);
@@ -1389,12 +1406,12 @@ bool SPObject::setDesc(gchar const *desc, bool verbatim)
return setTitleOrDesc(desc, "svg:desc", verbatim);
}
-gchar * SPObject::getTitleOrDesc(gchar const *svg_tagname) const
+char * SPObject::getTitleOrDesc(gchar const *svg_tagname) const
{
- gchar *result = 0;
+ char *result = NULL;
SPObject *elem = findFirstChild(svg_tagname);
if ( elem ) {
- result = g_string_free(elem->textualContent(), FALSE);
+ result = elem->textualContent();
}
return result;
}
@@ -1476,7 +1493,7 @@ SPObject * SPObject::findFirstChild(gchar const *tagname) const
return NULL;
}
-GString * SPObject::textualContent() const
+char* SPObject::textualContent() const
{
GString* text = g_string_new("");
@@ -1485,15 +1502,15 @@ GString * SPObject::textualContent() const
Inkscape::XML::NodeType child_type = child->repr->type();
if (child_type == Inkscape::XML::ELEMENT_NODE) {
- GString * new_text = child->textualContent();
- g_string_append(text, new_text->str);
- g_string_free(new_text, TRUE);
+ char* new_string = child->textualContent();
+ g_string_append(text, new_string);
+ g_free(new_string);
}
else if (child_type == Inkscape::XML::TEXT_NODE) {
g_string_append(text, child->repr->content());
}
}
- return text;
+ return g_string_free(text, FALSE);
}
/*
diff --git a/src/sp-object.h b/src/sp-object.h
index cf18d4523..575198f36 100644
--- a/src/sp-object.h
+++ b/src/sp-object.h
@@ -45,8 +45,9 @@ class SPObject;
#define SP_OBJECT_WRITE_BUILD (1 << 0)
#define SP_OBJECT_WRITE_EXT (1 << 1)
#define SP_OBJECT_WRITE_ALL (1 << 2)
+#define SP_OBJECT_WRITE_NO_CHILDREN (1 << 3)
-#include <glib-object.h>
+#include <cassert>
#include <stddef.h>
#include <sigc++/connection.h>
#include <sigc++/functors/slot.h>
@@ -56,7 +57,8 @@ class SPObject;
#include "util/forward-pointer-iterator.h"
class SPCSSAttr;
-struct SPStyle;
+class SPStyle;
+typedef struct _GSList GSList;
namespace Inkscape {
namespace XML {
@@ -109,8 +111,8 @@ class SPDocument;
class SPIXmlSpace {
public:
SPIXmlSpace(): set(0), value(SP_XML_SPACE_DEFAULT) {};
- guint set : 1;
- guint value : 1;
+ unsigned int set : 1;
+ unsigned int value : 1;
};
/*
@@ -152,7 +154,7 @@ SPObject *sp_object_unref(SPObject *object, SPObject *owner=NULL);
* \pre object points to real object
* @todo need to move this to be a member of SPObject.
*/
-SPObject *sp_object_href(SPObject *object, gpointer owner);
+SPObject *sp_object_href(SPObject *object, void* owner);
/**
* Decrease weak refcount.
@@ -164,7 +166,7 @@ SPObject *sp_object_href(SPObject *object, gpointer owner);
* \pre object points to real object and hrefcount>0
* @todo need to move this to be a member of SPObject.
*/
-SPObject *sp_object_hunref(SPObject *object, gpointer owner);
+SPObject *sp_object_hunref(SPObject *object, void* owner);
/**
* SPObject is an abstract base class of all of the document nodes at the
@@ -183,7 +185,7 @@ SPObject *sp_object_hunref(SPObject *object, gpointer owner);
* provides document level functionality such as the undo stack,
* dictionary and so on. Source: doc/architecture.txt
*/
-class SPObject { // : public GObject {
+class SPObject {
public:
enum CollectionPolicy {
COLLECT_WITH_PARENT,
@@ -209,7 +211,7 @@ private:
SPObject(const SPObject&);
SPObject& operator=(const SPObject&);
- gchar *id; /* Our very own unique id */
+ char *id; /* Our very own unique id */
Inkscape::XML::Node *repr; /* Our xml representation */
public:
int refCount;
@@ -217,7 +219,7 @@ public:
/**
* Returns the objects current ID string.
*/
- gchar const* getId() const;
+ char const* getId() const;
/**
* Returns the XML representation of tree
@@ -281,7 +283,7 @@ public:
typedef Inkscape::Util::ForwardPointerIterator<SPObject const, SiblingIteratorStrategy> ConstSiblingIterator;
bool isSiblingOf(SPObject const *object) const {
- g_return_val_if_fail(object != NULL, false);
+ if (object == NULL) return false;
return this->parent && this->parent == object->parent;
}
@@ -332,26 +334,26 @@ public:
* Gets the author-visible label property for the object or a default if
* no label is defined.
*/
- gchar const *label() const;
+ char const *label() const;
/**
* Returns a default label property for this object.
*/
- gchar const *defaultLabel() const;
+ char const *defaultLabel() const;
/**
* Sets the author-visible label for this object.
*
* @param label the new label.
*/
- void setLabel(gchar const *label);
+ void setLabel(char const *label);
/**
* Returns the title of this object, or NULL if there is none.
* The caller must free the returned string using g_free() - see comment
* for getTitleOrDesc() below.
*/
- gchar *title() const;
+ char *title() const;
/**
* Sets the title of this object.
@@ -359,14 +361,14 @@ public:
* (if any) should be deleted.
* The second argument is optional - @see setTitleOrDesc() below for details.
*/
- bool setTitle(gchar const *title, bool verbatim = false);
+ bool setTitle(char const *title, bool verbatim = false);
/**
* Returns the description of this object, or NULL if there is none.
* The caller must free the returned string using g_free() - see comment
* for getTitleOrDesc() below.
*/
- gchar *desc() const;
+ char *desc() const;
/**
* Sets the description of this object.
@@ -374,7 +376,7 @@ public:
* description (if any) should be deleted.
* The second argument is optional - @see setTitleOrDesc() below for details.
*/
- bool setDesc(gchar const *desc, bool verbatim=false);
+ bool setDesc(char const *desc, bool verbatim=false);
/**
* Set the policy under which this object will be orphan-collected.
@@ -465,6 +467,11 @@ public:
}
/**
+ * Removes all children except for the given object, it's children and it's ancesstors.
+ */
+ void cropToObject(SPObject *except);
+
+ /**
* Connects a slot to be called when an object is deleted.
*
* This connects a slot to an object's internal delete signal, which is invoked when the object
@@ -496,9 +503,9 @@ public:
* Indicates that another object supercedes this one.
*/
void setSuccessor(SPObject *successor) {
- g_assert(successor != NULL);
- g_assert(_successor == NULL);
- g_assert(successor->_successor == NULL);
+ assert(successor != NULL);
+ assert(_successor == NULL);
+ assert(successor->_successor == NULL);
sp_object_ref(successor, NULL);
_successor = successor;
}
@@ -650,8 +657,8 @@ public:
sigc::signal<void, SPObject *, unsigned int> _modified_signal;
SPObject *_successor;
CollectionPolicy _collection_policy;
- gchar *_label;
- mutable gchar *_default_label;
+ char *_label;
+ mutable char *_default_label;
// WARNING:
// Methods below should not be used outside of the SP tree,
@@ -685,7 +692,7 @@ public:
unsigned getPosition();
- gchar const * getAttribute(gchar const *name,SPException *ex=NULL) const;
+ char const * getAttribute(char const *name,SPException *ex=NULL) const;
void appendChild(Inkscape::XML::Node *child);
@@ -694,18 +701,18 @@ public:
/**
* Call virtual set() function of object.
*/
- void setKeyValue(unsigned int key, gchar const *value);
+ void setKeyValue(unsigned int key, char const *value);
- void setAttribute(gchar const *key, gchar const *value, SPException *ex=NULL);
+ void setAttribute(char const *key, char const *value, SPException *ex=NULL);
/**
* Read value of key attribute from XML node into object.
*/
- void readAttr(gchar const *key);
+ void readAttr(char const *key);
- gchar const *getTagName(SPException *ex) const;
+ char const *getTagName(SPException *ex) const;
- void removeAttribute(gchar const *key, SPException *ex=NULL);
+ void removeAttribute(char const *key, SPException *ex=NULL);
/**
* Returns an object style property.
@@ -735,13 +742,13 @@ public:
* <use> element instead), we should probably make the caller
* responsible for ascending the repr tree as necessary.
*/
- gchar const *getStyleProperty(gchar const *key, gchar const *def) const;
+ char const *getStyleProperty(char const *key, char const *def) const;
- void setCSS(SPCSSAttr *css, gchar const *attr);
+ void setCSS(SPCSSAttr *css, char const *attr);
- void changeCSS(SPCSSAttr *css, gchar const *attr);
+ void changeCSS(SPCSSAttr *css, char const *attr);
- bool storeAsDouble( gchar const *key, double *val ) const;
+ bool storeAsDouble( char const *key, double *val ) const;
private:
// Private member functions used in the definitions of setTitle(),
@@ -764,7 +771,7 @@ private:
* The return value is true if a change was made to the title/description,
* and usually false otherwise.
*/
- bool setTitleOrDesc(gchar const *value, gchar const *svg_tagname, bool verbatim);
+ bool setTitleOrDesc(char const *value, char const *svg_tagname, bool verbatim);
/**
* Returns the title or description of this object, or NULL if there is none.
@@ -776,20 +783,20 @@ private:
* Consequently, the return value is a newly allocated string (or NULL), and
* must be freed (using g_free()) by the caller.
*/
- gchar * getTitleOrDesc(gchar const *svg_tagname) const;
+ char * getTitleOrDesc(char const *svg_tagname) const;
/**
* Find the first child of this object with a given tag name,
* and return it. Returns NULL if there is no matching child.
*/
- SPObject * findFirstChild(gchar const *tagname) const;
+ SPObject * findFirstChild(char const *tagname) const;
/**
* Return the full textual content of an element (typically all the
* content except the tags).
* Must not be used on anything except elements.
*/
- GString * textualContent() const;
+ char * textualContent() const;
/* Real handlers of repr signals */
@@ -797,17 +804,17 @@ public:
/**
* Callback for attr_changed node event.
*/
- static void repr_attr_changed(Inkscape::XML::Node *repr, gchar const *key, gchar const *oldval, gchar const *newval, bool is_interactive, gpointer data);
+ static void repr_attr_changed(Inkscape::XML::Node *repr, char const *key, char const *oldval, char const *newval, bool is_interactive, void* data);
/**
* Callback for content_changed node event.
*/
- static void repr_content_changed(Inkscape::XML::Node *repr, gchar const *oldcontent, gchar const *newcontent, gpointer data);
+ static void repr_content_changed(Inkscape::XML::Node *repr, char const *oldcontent, char const *newcontent, void* data);
/**
* Callback for child_added node event.
*/
- static void repr_child_added(Inkscape::XML::Node *repr, Inkscape::XML::Node *child, Inkscape::XML::Node *ref, gpointer data);
+ static void repr_child_added(Inkscape::XML::Node *repr, Inkscape::XML::Node *child, Inkscape::XML::Node *ref, void* data);
/**
* Callback for remove_child node event.
@@ -819,7 +826,7 @@ public:
*
* \todo fixme:
*/
- static void repr_order_changed(Inkscape::XML::Node *repr, Inkscape::XML::Node *child, Inkscape::XML::Node *old, Inkscape::XML::Node *newer, gpointer data);
+ static void repr_order_changed(Inkscape::XML::Node *repr, Inkscape::XML::Node *child, Inkscape::XML::Node *old, Inkscape::XML::Node *newer, void* data);
friend class SPObjectImpl;
@@ -833,12 +840,12 @@ protected:
virtual void order_changed(Inkscape::XML::Node* child, Inkscape::XML::Node* old_repr, Inkscape::XML::Node* new_repr);
- virtual void set(unsigned int key, const gchar* value);
+ virtual void set(unsigned int key, const char* value);
virtual void update(SPCtx* ctx, unsigned int flags);
virtual void modified(unsigned int flags);
- virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, guint flags);
+ virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, unsigned int flags);
public:
virtual void read_content();
diff --git a/src/sp-offset.cpp b/src/sp-offset.cpp
index c6a4b730d..3aa1e4eb6 100644
--- a/src/sp-offset.cpp
+++ b/src/sp-offset.cpp
@@ -107,11 +107,6 @@ SPOffset::SPOffset() : SPShape() {
this->sourceRepr = NULL;
this->sourceObject = NULL;
- new (&this->_modified_connection) sigc::connection();
- new (&this->_delete_connection) sigc::connection();
- new (&this->_changed_connection) sigc::connection();
- new (&this->_transformed_connection) sigc::connection();
-
// set up the uri reference
this->sourceRef = new SPUseReference(this);
this->_changed_connection = this->sourceRef->changedSignal().connect(sigc::bind(sigc::ptr_fun(sp_offset_href_changed), this));
diff --git a/src/sp-offset.h b/src/sp-offset.h
index 259a69b78..eb3fe227c 100644
--- a/src/sp-offset.h
+++ b/src/sp-offset.h
@@ -11,11 +11,11 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include "sp-shape.h"
-
-#include <stddef.h>
+#include <cstddef>
#include <sigc++/sigc++.h>
+#include "sp-shape.h"
+
#define SP_OFFSET(obj) (dynamic_cast<SPOffset*>((SPObject*)obj))
#define SP_IS_OFFSET(obj) (dynamic_cast<const SPOffset*>((SPObject*)obj) != NULL)
@@ -54,7 +54,7 @@ public:
SPOffset();
virtual ~SPOffset();
- void *originalPath; ///< will be a livarot Path, just don't declare it here to please the gcc linker
+ void *originalPath; ///< will be a livarot Path, just don't declare it here to please the gcc linker FIXME what?
char *original; ///< SVG description of the source path
float rad; ///< offset radius
@@ -65,7 +65,7 @@ public:
bool sourceDirty;
bool isUpdating;
- gchar *sourceHref;
+ char *sourceHref;
SPUseReference *sourceRef;
Inkscape::XML::Node *sourceRepr; ///< the repr associated with that id
SPObject *sourceObject;
@@ -76,14 +76,14 @@ public:
sigc::connection _transformed_connection;
virtual void build(SPDocument *document, Inkscape::XML::Node *repr);
- virtual void set(unsigned int key, gchar const* value);
- virtual void update(SPCtx *ctx, guint flags);
- virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags);
+ virtual void set(unsigned int key, char const* value);
+ virtual void update(SPCtx *ctx, unsigned int flags);
+ virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned flags);
virtual void release();
virtual void snappoints(std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs) const;
virtual const char* displayName() const;
- virtual gchar* description() const;
+ virtual char* description() const;
virtual void set_shape();
};
diff --git a/src/sp-paint-server-reference.h b/src/sp-paint-server-reference.h
index e08694c2f..bbd9c25fa 100644
--- a/src/sp-paint-server-reference.h
+++ b/src/sp-paint-server-reference.h
@@ -15,9 +15,10 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include "sp-object.h"
#include "uri-references.h"
+class SPDocument;
+class SPObject;
class SPPaintServer;
class SPPaintServerReference : public Inkscape::URIReference {
diff --git a/src/sp-paint-server.cpp b/src/sp-paint-server.cpp
index 692265bd8..ae40ad1aa 100644
--- a/src/sp-paint-server.cpp
+++ b/src/sp-paint-server.cpp
@@ -58,6 +58,29 @@ bool SPPaintServer::isSolid() const
return solid;
}
+bool SPPaintServer::isValid() const
+{
+ return true;
+}
+
+Inkscape::DrawingPattern *SPPaintServer::show(Inkscape::Drawing &/*drawing*/, unsigned int /*key*/, Geom::OptRect /*bbox*/)
+{
+ return NULL;
+}
+
+void SPPaintServer::hide(unsigned int /*key*/)
+{
+}
+
+void SPPaintServer::setBBox(unsigned int /*key*/, Geom::OptRect const &/*bbox*/)
+{
+}
+
+cairo_pattern_t* SPPaintServer::pattern_new(cairo_t * /*ct*/, Geom::OptRect const &/*bbox*/, double /*opacity*/)
+{
+ return NULL;
+}
+
/*
Local Variables:
mode:c++
diff --git a/src/sp-paint-server.h b/src/sp-paint-server.h
index 02e2f10ec..7f3bfcba0 100644
--- a/src/sp-paint-server.h
+++ b/src/sp-paint-server.h
@@ -17,8 +17,16 @@
#include <cairo.h>
#include <2geom/rect.h>
+#include <sigc++/slot.h>
#include "sp-object.h"
+namespace Inkscape {
+
+class Drawing;
+class DrawingPattern;
+
+}
+
#define SP_PAINT_SERVER(obj) (dynamic_cast<SPPaintServer*>((SPObject*)obj))
#define SP_IS_PAINT_SERVER(obj) (dynamic_cast<const SPPaintServer*>((SPObject*)obj) != NULL)
@@ -29,13 +37,61 @@ public:
bool isSwatch() const;
bool isSolid() const;
+ virtual bool isValid() const;
- virtual cairo_pattern_t* pattern_new(cairo_t *ct, Geom::OptRect const &bbox, double opacity) = 0;
+ //There are two ways to render a paint. The simple one is to create cairo_pattern_t structure
+ //on demand by pattern_new method. It is used for gradients. The other one is to add elements
+ //representing PaintServer in NR tree. It is used by hatches and patterns.
+ //Either pattern new or all three methods show, hide, setBBox need to be implemented
+ virtual Inkscape::DrawingPattern *show(Inkscape::Drawing &drawing, unsigned int key, Geom::OptRect bbox); // TODO check passing bbox by value. Looks suspicious.
+ virtual void hide(unsigned int key);
+ virtual void setBBox(unsigned int key, Geom::OptRect const &bbox);
+
+ virtual cairo_pattern_t* pattern_new(cairo_t *ct, Geom::OptRect const &bbox, double opacity);
protected:
bool swatch;
};
+/**
+ * Returns the first of {src, src-\>ref-\>getObject(),
+ * src-\>ref-\>getObject()-\>ref-\>getObject(),...}
+ * for which \a match is true, or NULL if none found.
+ *
+ * The raison d'être of this routine is that it correctly handles cycles in the href chain (e.g., if
+ * a gradient gives itself as its href, or if each of two gradients gives the other as its href).
+ *
+ * \pre SP_IS_GRADIENT(src).
+ */
+template <class PaintServer>
+PaintServer *chase_hrefs(PaintServer *src, sigc::slot<bool, PaintServer const *> match) {
+ /* Use a pair of pointers for detecting loops: p1 advances half as fast as p2. If there is a
+ loop, then once p1 has entered the loop, we'll detect it the next time the distance between
+ p1 and p2 is a multiple of the loop size. */
+ PaintServer *p1 = src, *p2 = src;
+ bool do1 = false;
+ for (;;) {
+ if (match(p2)) {
+ return p2;
+ }
+
+ p2 = p2->ref->getObject();
+ if (!p2) {
+ return p2;
+ }
+ if (do1) {
+ p1 = p1->ref->getObject();
+ }
+ do1 = !do1;
+
+ if ( p2 == p1 ) {
+ /* We've been here before, so return NULL to indicate that no matching gradient found
+ * in the chain. */
+ return NULL;
+ }
+ }
+}
+
#endif // SEEN_SP_PAINT_SERVER_H
/*
Local Variables:
diff --git a/src/sp-path.cpp b/src/sp-path.cpp
index cbb61b0f6..5c076b7cb 100644
--- a/src/sp-path.cpp
+++ b/src/sp-path.cpp
@@ -140,7 +140,21 @@ void SPPath::build(SPDocument *document, Inkscape::XML::Node *repr) {
SPShape::build(document, repr);
- this->readAttr( "inkscape:original-d" );
+ // this->readAttr( "inkscape:original-d" ); // lp1299948
+ if (gchar const* s = this->getRepr()->attribute("inkscape:original-d"))
+ {
+ // write it to XML, and to my curve, but don't update patheffects
+ Geom::PathVector pv = sp_svg_read_pathv(s);
+ SPCurve *curve = new SPCurve(pv);
+
+ if (_curve_before_lpe) {
+ _curve_before_lpe = _curve_before_lpe->unref();
+ }
+
+ if (curve) {
+ _curve_before_lpe = curve->ref();
+ }
+ }
this->readAttr( "d" );
/* d is a required attribute */
@@ -314,7 +328,6 @@ g_message("sp_path_update_patheffect");
#ifdef PATH_VERBOSE
g_message("sp_path_update_patheffect writes 'd' attribute");
#endif
-
if (_curve) {
gchar *str = sp_svg_write_path(this->_curve->get_pathvector());
repr->setAttribute("d", str);
diff --git a/src/sp-path.h b/src/sp-path.h
index 5f8a91d98..572fd648d 100644
--- a/src/sp-path.h
+++ b/src/sp-path.h
@@ -32,7 +32,7 @@ public:
SPPath();
virtual ~SPPath();
- gint nodesInPath() const;
+ int nodesInPath() const;
// still in lowercase because the names should be clearer on whether curve, curve->copy or curve-ref is returned.
void set_original_curve (SPCurve *curve, unsigned int owner, bool write);
@@ -49,13 +49,13 @@ public:
virtual void build(SPDocument *document, Inkscape::XML::Node *repr);
virtual void release();
- virtual void update(SPCtx* ctx, guint flags);
+ virtual void update(SPCtx* ctx, unsigned int flags);
- virtual void set(unsigned int key, gchar const* value);
- virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags);
+ virtual void set(unsigned int key, char const* value);
+ virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags);
virtual const char* displayName() const;
- virtual gchar* description() const;
+ virtual char* description() const;
virtual Geom::Affine set_transform(Geom::Affine const &transform);
virtual void convert_to_guides() const;
diff --git a/src/sp-pattern.cpp b/src/sp-pattern.cpp
index e465565c4..961ab0f84 100644
--- a/src/sp-pattern.cpp
+++ b/src/sp-pattern.cpp
@@ -18,7 +18,9 @@
#include <cstring>
#include <string>
+#include <glibmm.h>
#include <2geom/transforms.h>
+
#include "macros.h"
#include "svg/svg.h"
#include "display/cairo-utils.h"
@@ -541,6 +543,16 @@ static bool pattern_hasItemChildren (SPPattern const *pat)
return hasChildren;
}
+bool SPPattern::isValid() const
+{
+ double tile_width = pattern_width(this);
+ double tile_height = pattern_height(this);
+
+ if (tile_width <= 0 || tile_height <= 0)
+ return false;
+ return true;
+}
+
cairo_pattern_t* SPPattern::pattern_new(cairo_t *base_ct, Geom::OptRect const &bbox, double opacity) {
bool needs_opacity = (1.0 - opacity) >= 1e-3;
@@ -593,7 +605,7 @@ cairo_pattern_t* SPPattern::pattern_new(cairo_t *base_ct, Geom::OptRect const &b
double tile_y = pattern_y(this);
double tile_width = pattern_width(this);
double tile_height = pattern_height(this);
- if (pattern_patternUnits(this) == SP_PATTERN_UNITS_OBJECTBOUNDINGBOX) {
+ if ( bbox && (pattern_patternUnits(this) == SP_PATTERN_UNITS_OBJECTBOUNDINGBOX) ) {
tile_x *= bbox->width();
tile_y *= bbox->height();
tile_width *= bbox->width();
@@ -605,16 +617,17 @@ cairo_pattern_t* SPPattern::pattern_new(cairo_t *base_ct, Geom::OptRect const &b
// Content to tile (pattern space)
Geom::Affine content2ps;
- if (this->viewBox_set) {
+ Geom::OptRect effective_view_box = pattern_viewBox(this);
+ if (effective_view_box) {
// viewBox to pattern server (using SPViewBox)
- viewBox = *pattern_viewBox(this);
+ viewBox = *effective_view_box;
c2p.setIdentity();
apply_viewbox( pattern_tile );
content2ps = c2p;
} else {
// Content to bbox
- if (pattern_patternContentUnits (this) == SP_PATTERN_UNITS_OBJECTBOUNDINGBOX) {
+ if (bbox && (pattern_patternContentUnits(this) == SP_PATTERN_UNITS_OBJECTBOUNDINGBOX) ) {
content2ps = Geom::Affine(bbox->width(), 0.0, 0.0, bbox->height(), 0,0);
}
}
diff --git a/src/sp-pattern.h b/src/sp-pattern.h
index f69ba10b3..f021101e2 100644
--- a/src/sp-pattern.h
+++ b/src/sp-pattern.h
@@ -13,21 +13,18 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include <gtk/gtk.h>
-
-#include "sp-item.h"
-
#define SP_PATTERN(obj) (dynamic_cast<SPPattern*>((SPObject*)obj))
#define SP_IS_PATTERN(obj) (dynamic_cast<const SPPattern*>((SPObject*)obj) != NULL)
class SPPatternReference;
+class SPItem;
+typedef struct _GSList GSList;
#include "svg/svg-length.h"
#include "sp-paint-server.h"
#include "uri-references.h"
#include "viewbox.h"
-#include <stddef.h>
#include <sigc++/connection.h>
@@ -37,17 +34,17 @@ public:
virtual ~SPPattern();
/* Reference (href) */
- gchar *href;
+ char *href;
SPPatternReference *ref;
/* patternUnits and patternContentUnits attribute */
- guint patternUnits : 1;
- guint patternUnits_set : 1;
- guint patternContentUnits : 1;
- guint patternContentUnits_set : 1;
+ unsigned int patternUnits : 1;
+ unsigned int patternUnits_set : 1;
+ unsigned int patternContentUnits : 1;
+ unsigned int patternContentUnits_set : 1;
/* patternTransform attribute */
Geom::Affine patternTransform;
- guint patternTransform_set : 1;
+ unsigned int patternTransform_set : 1;
/* Tile rectangle */
SVGLength x;
SVGLength y;
@@ -56,6 +53,8 @@ public:
sigc::connection modified_connection;
+ bool isValid() const;
+
virtual cairo_pattern_t* pattern_new(cairo_t *ct, Geom::OptRect const &bbox, double opacity);
protected:
@@ -85,22 +84,22 @@ enum {
SP_PATTERN_UNITS_OBJECTBOUNDINGBOX
};
-guint pattern_users (SPPattern *pattern);
+unsigned int pattern_users (SPPattern *pattern);
SPPattern *pattern_chain (SPPattern *pattern);
-SPPattern *sp_pattern_clone_if_necessary (SPItem *item, SPPattern *pattern, const gchar *property);
+SPPattern *sp_pattern_clone_if_necessary (SPItem *item, SPPattern *pattern, const char *property);
void sp_pattern_transform_multiply (SPPattern *pattern, Geom::Affine postmul, bool set);
-const gchar *pattern_tile (GSList *reprs, Geom::Rect bounds, SPDocument *document, Geom::Affine transform, Geom::Affine move);
+const char *pattern_tile (GSList *reprs, Geom::Rect bounds, SPDocument *document, Geom::Affine transform, Geom::Affine move);
SPPattern *pattern_getroot (SPPattern *pat);
-guint pattern_patternUnits (SPPattern const *pat);
-guint pattern_patternContentUnits (SPPattern const *pat);
+unsigned int pattern_patternUnits (SPPattern const *pat);
+unsigned int pattern_patternContentUnits (SPPattern const *pat);
Geom::Affine const &pattern_patternTransform(SPPattern const *pat);
-gdouble pattern_x (SPPattern const *pat);
-gdouble pattern_y (SPPattern const *pat);
-gdouble pattern_width (SPPattern const *pat);
-gdouble pattern_height (SPPattern const *pat);
+double pattern_x (SPPattern const *pat);
+double pattern_y (SPPattern const *pat);
+double pattern_width (SPPattern const *pat);
+double pattern_height (SPPattern const *pat);
Geom::OptRect pattern_viewBox (SPPattern const *pat);
#endif // SEEN_SP_PATTERN_H
diff --git a/src/sp-polygon.h b/src/sp-polygon.h
index 41ab245bd..438fdf794 100644
--- a/src/sp-polygon.h
+++ b/src/sp-polygon.h
@@ -1,5 +1,5 @@
-#ifndef __SP_POLYGON_H__
-#define __SP_POLYGON_H__
+#ifndef SEEN_SP_POLYGON_H
+#define SEEN_SP_POLYGON_H
/*
* SVG <polygon> implementation
@@ -15,7 +15,6 @@
#include "sp-shape.h"
-
#define SP_POLYGON(obj) (dynamic_cast<SPPolygon*>((SPObject*)obj))
#define SP_IS_POLYGON(obj) (dynamic_cast<const SPPolygon*>((SPObject*)obj) != NULL)
@@ -25,12 +24,12 @@ public:
virtual ~SPPolygon();
virtual void build(SPDocument *document, Inkscape::XML::Node *repr);
- virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags);
- virtual void set(unsigned int key, gchar const* value);
- virtual gchar* description() const;
+ virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags);
+ virtual void set(unsigned int key, char const* value);
+ virtual char* description() const;
};
// made 'public' so that SPCurve can set it as friend:
-void sp_polygon_set(SPObject *object, unsigned int key, const gchar *value);
+void sp_polygon_set(SPObject *object, unsigned int key, char const*value);
#endif
diff --git a/src/sp-polyline.h b/src/sp-polyline.h
index e24ea95c7..1ca102a9e 100644
--- a/src/sp-polyline.h
+++ b/src/sp-polyline.h
@@ -12,10 +12,10 @@ public:
virtual ~SPPolyLine();
virtual void build(SPDocument* doc, Inkscape::XML::Node* repr);
- virtual void set(unsigned int key, gchar const* value);
- virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags);
+ virtual void set(unsigned int key, char const* value);
+ virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags);
- virtual gchar* description() const;
+ virtual char* description() const;
};
#endif // SEEN_SP_POLYLINE_H
diff --git a/src/sp-radial-gradient.cpp b/src/sp-radial-gradient.cpp
index 7c481fead..2c2b17b7d 100644
--- a/src/sp-radial-gradient.cpp
+++ b/src/sp-radial-gradient.cpp
@@ -1,3 +1,5 @@
+#include <cairo.h>
+
#include "sp-radial-gradient.h"
#include "attributes.h"
diff --git a/src/sp-radial-gradient.h b/src/sp-radial-gradient.h
index 42ff109aa..f753623b7 100644
--- a/src/sp-radial-gradient.h
+++ b/src/sp-radial-gradient.h
@@ -5,10 +5,12 @@
* SPRadialGradient: SVG <radialgradient> implementtion.
*/
-#include <glib.h>
#include "sp-gradient.h"
#include "svg/svg-length.h"
+typedef struct _cairo cairo_t;
+typedef struct _cairo_pattern cairo_pattern_t;
+
#define SP_RADIALGRADIENT(obj) (dynamic_cast<SPRadialGradient*>((SPObject*)obj))
#define SP_IS_RADIALGRADIENT(obj) (dynamic_cast<const SPRadialGradient*>((SPObject*)obj) != NULL)
@@ -28,8 +30,8 @@ public:
protected:
virtual void build(SPDocument *document, Inkscape::XML::Node *repr);
- virtual void set(unsigned key, gchar const *value);
- virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags);
+ virtual void set(unsigned key, char const *value);
+ virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags);
};
#endif /* !SP_RADIAL_GRADIENT_H */
diff --git a/src/sp-rect.h b/src/sp-rect.h
index aa3f88e42..757229724 100644
--- a/src/sp-rect.h
+++ b/src/sp-rect.h
@@ -14,10 +14,10 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include "svg/svg-length.h"
-#include "sp-shape.h"
#include <2geom/forward.h>
+#include "svg/svg-length.h"
+#include "sp-shape.h"
#define SP_RECT(obj) (dynamic_cast<SPRect*>((SPObject*)obj))
#define SP_IS_RECT(obj) (dynamic_cast<const SPRect*>((SPObject*)obj) != NULL)
@@ -27,34 +27,34 @@ public:
SPRect();
virtual ~SPRect();
- void setPosition(gdouble x, gdouble y, gdouble width, gdouble height);
+ void setPosition(double x, double y, double width, double height);
/* If SET if FALSE, VALUE is just ignored */
- void setRx(bool set, gdouble value);
- void setRy(bool set, gdouble value);
+ void setRx(bool set, double value);
+ void setRy(bool set, double value);
- gdouble getVisibleRx() const;
- void setVisibleRx(gdouble rx);
+ double getVisibleRx() const;
+ void setVisibleRx(double rx);
- gdouble getVisibleRy() const;
- void setVisibleRy(gdouble ry);
+ double getVisibleRy() const;
+ void setVisibleRy(double ry);
Geom::Rect getRect() const;
- gdouble getVisibleWidth() const;
- void setVisibleWidth(gdouble rx);
+ double getVisibleWidth() const;
+ void setVisibleWidth(double rx);
- gdouble getVisibleHeight() const;
- void setVisibleHeight(gdouble ry);
+ double getVisibleHeight() const;
+ void setVisibleHeight(double ry);
void compensateRxRy(Geom::Affine xform);
virtual void build(SPDocument* doc, Inkscape::XML::Node* repr);
- virtual void set(unsigned key, gchar const *value);
+ virtual void set(unsigned key, char const *value);
virtual void update(SPCtx* ctx, unsigned int flags);
- virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags);
+ virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags);
virtual const char* displayName() const;
virtual void set_shape();
@@ -71,7 +71,7 @@ public:
SVGLength ry;
private:
- static gdouble vectorStretch(Geom::Point p0, Geom::Point p1, Geom::Affine xform);
+ static double vectorStretch(Geom::Point p0, Geom::Point p1, Geom::Affine xform);
};
#endif // SEEN_SP_RECT_H
diff --git a/src/sp-root.h b/src/sp-root.h
index a25e8030c..2776ae887 100644
--- a/src/sp-root.h
+++ b/src/sp-root.h
@@ -40,7 +40,7 @@ public:
SVGLength width;
SVGLength height;
- gchar *onload;
+ char *onload;
/**
* Primary \<defs\> element where we put new defs (patterns, gradients etc.).
@@ -52,9 +52,9 @@ public:
virtual void build(SPDocument *document, Inkscape::XML::Node *repr);
virtual void release();
- virtual void set(unsigned int key, gchar const* value);
- virtual void update(SPCtx *ctx, guint flags);
- virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags);
+ virtual void set(unsigned int key, char const* value);
+ virtual void update(SPCtx *ctx, unsigned int flags);
+ virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags);
virtual void modified(unsigned int flags);
virtual void child_added(Inkscape::XML::Node* child, Inkscape::XML::Node* ref);
diff --git a/src/sp-script.h b/src/sp-script.h
index 36072a0ca..cdacb8493 100644
--- a/src/sp-script.h
+++ b/src/sp-script.h
@@ -1,11 +1,12 @@
-#ifndef __SP_SCRIPT_H__
-#define __SP_SCRIPT_H__
+#ifndef SEEN_SP_SCRIPT_H
+#define SEEN_SP_SCRIPT_H
/*
* SVG <script> implementation
*
* Author:
* Felipe C. da S. Sanches <juca@members.fsf.org>
+ * Jon A. Cruz <jon@joncruz.org>
*
* Copyright (C) 2008 Author
*
@@ -15,24 +16,21 @@
#include "sp-object.h"
#include "document.h"
-#define SP_SCRIPT(obj) (dynamic_cast<SPScript*>((SPObject*)obj))
-#define SP_IS_SCRIPT(obj) (dynamic_cast<const SPScript*>((SPObject*)obj) != NULL)
-
/* SPScript */
class SPScript : public SPObject {
public:
SPScript();
virtual ~SPScript();
- gchar *xlinkhref;
+ char *xlinkhref;
protected:
virtual void build(SPDocument* doc, Inkscape::XML::Node* repr);
virtual void release();
- virtual void set(unsigned int key, const gchar* value);
+ virtual void set(unsigned int key, char const* value);
virtual void update(SPCtx* ctx, unsigned int flags);
virtual void modified(unsigned int flags);
- virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, guint flags);
+ virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, unsigned int flags);
};
#endif
diff --git a/src/sp-shape.cpp b/src/sp-shape.cpp
index b3a331cba..8b7e735e0 100644
--- a/src/sp-shape.cpp
+++ b/src/sp-shape.cpp
@@ -35,7 +35,7 @@
#include "print.h"
#include "document.h"
#include "style.h"
-#include "marker.h"
+#include "sp-marker.h"
#include "sp-path.h"
#include "preferences.h"
#include "attributes.h"
@@ -57,8 +57,6 @@ static void sp_shape_update_marker_view (SPShape *shape, Inkscape::DrawingItem *
SPShape::SPShape() : SPLPEItem() {
for ( int i = 0 ; i < SP_MARKER_LOC_QTY ; i++ ) {
- new (&this->_release_connect[i]) sigc::connection();
- new (&this->_modified_connect[i]) sigc::connection();
this->_marker[i] = NULL;
}
@@ -77,7 +75,7 @@ void SPShape::build(SPDocument *document, Inkscape::XML::Node *repr) {
SPLPEItem::build(document, repr);
for (int i = 0 ; i < SP_MARKER_LOC_QTY ; i++) {
- sp_shape_set_marker (this, i, this->style->marker[i].value);
+ sp_shape_set_marker (this, i, this->style->marker_ptrs[i]->value);
}
}
@@ -97,12 +95,12 @@ void SPShape::release() {
if (this->_marker[i]) {
for (SPItemView *v = this->display; v != NULL; v = v->next) {
- sp_marker_hide ((SPMarker *) this->_marker[i], v->arenaitem->key() + i);
+ sp_marker_hide(_marker[i], v->arenaitem->key() + i);
}
this->_release_connect[i].disconnect();
this->_modified_connect[i].disconnect();
- this->_marker[i] = sp_object_hunref (this->_marker[i], this);
+ _marker[i] = static_cast<SPMarker *>(sp_object_hunref(_marker[i], this));
}
}
@@ -136,7 +134,7 @@ void SPShape::update(SPCtx* ctx, guint flags) {
* match the style.
*/
for (int i = 0 ; i < SP_MARKER_LOC_QTY ; i++) {
- sp_shape_set_marker (this, i, this->style->marker[i].value);
+ sp_shape_set_marker (this, i, this->style->marker_ptrs[i]->value);
}
if (flags & (SP_OBJECT_STYLE_MODIFIED_FLAG | SP_OBJECT_VIEWPORT_MODIFIED_FLAG)) {
@@ -172,10 +170,10 @@ void SPShape::update(SPCtx* ctx, guint flags) {
}
for (int i = 0 ; i < SP_MARKER_LOC_QTY ; i++) {
- if (this->_marker[i]) {
- sp_marker_show_dimension ((SPMarker *) this->_marker[i],
- v->arenaitem->key() + i,
- this->numberOfMarkers (i));
+ if (_marker[i]) {
+ sp_marker_show_dimension(_marker[i],
+ v->arenaitem->key() + i,
+ numberOfMarkers(i));
}
}
}
@@ -290,9 +288,14 @@ sp_shape_update_marker_view(SPShape *shape, Inkscape::DrawingItem *ai)
Geom::Affine const m (sp_shape_marker_get_transform_at_start(pathv.begin()->front()));
for (int i = 0; i < 2; i++) { // SP_MARKER_LOC and SP_MARKER_LOC_START
if ( shape->_marker[i] ) {
- sp_marker_show_instance ((SPMarker* ) shape->_marker[i], ai,
- ai->key() + i, counter[i], m,
- shape->style->stroke_width.computed);
+ Geom::Affine m_auto = m;
+ // Reverse start marker if necessary.
+ if (shape->_marker[i]->orient_mode == MARKER_ORIENT_AUTO_START_REVERSE) {
+ m_auto = Geom::Rotate::from_degrees( 180.0 ) * m;
+ }
+ sp_marker_show_instance(shape->_marker[i], ai,
+ ai->key() + i, counter[i], m_auto,
+ shape->style->stroke_width.computed);
counter[i]++;
}
}
@@ -308,9 +311,9 @@ sp_shape_update_marker_view(SPShape *shape, Inkscape::DrawingItem *ai)
Geom::Affine const m (sp_shape_marker_get_transform_at_start(path_it->front()));
for (int i = 0; i < 3; i += 2) { // SP_MARKER_LOC and SP_MARKER_LOC_MID
if ( shape->_marker[i] ) {
- sp_marker_show_instance ((SPMarker* ) shape->_marker[i], ai,
- ai->key() + i, counter[i], m,
- shape->style->stroke_width.computed);
+ sp_marker_show_instance(shape->_marker[i], ai,
+ ai->key() + i, counter[i], m,
+ shape->style->stroke_width.computed);
counter[i]++;
}
}
@@ -328,9 +331,9 @@ sp_shape_update_marker_view(SPShape *shape, Inkscape::DrawingItem *ai)
Geom::Affine const m (sp_shape_marker_get_transform(*curve_it1, *curve_it2));
for (int i = 0; i < 3; i += 2) { // SP_MARKER_LOC and SP_MARKER_LOC_MID
if (shape->_marker[i]) {
- sp_marker_show_instance ((SPMarker* ) shape->_marker[i], ai,
- ai->key() + i, counter[i], m,
- shape->style->stroke_width.computed);
+ sp_marker_show_instance(shape->_marker[i], ai,
+ ai->key() + i, counter[i], m,
+ shape->style->stroke_width.computed);
counter[i]++;
}
}
@@ -345,9 +348,9 @@ sp_shape_update_marker_view(SPShape *shape, Inkscape::DrawingItem *ai)
Geom::Affine const m = sp_shape_marker_get_transform_at_end(lastcurve);
for (int i = 0; i < 3; i += 2) { // SP_MARKER_LOC and SP_MARKER_LOC_MID
if (shape->_marker[i]) {
- sp_marker_show_instance ((SPMarker* ) shape->_marker[i], ai,
- ai->key() + i, counter[i], m,
- shape->style->stroke_width.computed);
+ sp_marker_show_instance(shape->_marker[i], ai,
+ ai->key() + i, counter[i], m,
+ shape->style->stroke_width.computed);
counter[i]++;
}
}
@@ -369,9 +372,9 @@ sp_shape_update_marker_view(SPShape *shape, Inkscape::DrawingItem *ai)
for (int i = 0; i < 4; i += 3) { // SP_MARKER_LOC and SP_MARKER_LOC_END
if (shape->_marker[i]) {
- sp_marker_show_instance ((SPMarker* ) shape->_marker[i], ai,
- ai->key() + i, counter[i], m,
- shape->style->stroke_width.computed);
+ sp_marker_show_instance(shape->_marker[i], ai,
+ ai->key() + i, counter[i], m,
+ shape->style->stroke_width.computed);
counter[i]++;
}
}
@@ -421,23 +424,25 @@ Geom::OptRect SPShape::bbox(Geom::Affine const &transform, SPItem::BBoxType bbox
// START marker
for (unsigned i = 0; i < 2; i++) { // SP_MARKER_LOC and SP_MARKER_LOC_START
if ( this->_marker[i] ) {
- SPMarker* marker = SP_MARKER (this->_marker[i]);
- SPItem* marker_item = sp_item_first_item_child( marker );
+ SPItem* marker_item = sp_item_first_item_child( _marker[i] );
if (marker_item) {
Geom::Affine tr(sp_shape_marker_get_transform_at_start(pathv.begin()->front()));
- if (!marker->orient_auto) {
+ if (_marker[i]->orient_mode == MARKER_ORIENT_AUTO_START_REVERSE) {
+ // Reverse start marker if necessary
+ tr = Geom::Rotate::from_degrees( 180.0 ) * tr;
+ } else if (_marker[i]->orient_mode == MARKER_ORIENT_ANGLE) {
Geom::Point transl = tr.translation();
- tr = Geom::Rotate::from_degrees(marker->orient) * Geom::Translate(transl);
+ tr = Geom::Rotate::from_degrees(_marker[i]->orient) * Geom::Translate(transl);
}
- if (marker->markerUnits == SP_MARKER_UNITS_STROKEWIDTH) {
+ if (_marker[i]->markerUnits == SP_MARKER_UNITS_STROKEWIDTH) {
tr = Geom::Scale(this->style->stroke_width.computed) * tr;
}
// total marker transform
- tr = marker_item->transform * marker->c2p * tr * transform;
+ tr = marker_item->transform * _marker[i]->c2p * tr * transform;
// get bbox of the marker with that transform
bbox |= marker_item->visualBounds(tr);
@@ -451,7 +456,7 @@ Geom::OptRect SPShape::bbox(Geom::Affine const &transform, SPItem::BBoxType bbox
continue;
}
- SPMarker* marker = SP_MARKER (this->_marker[i]);
+ SPMarker* marker = _marker[i];
SPItem* marker_item = sp_item_first_item_child( marker );
if ( !marker_item ) {
@@ -465,7 +470,7 @@ Geom::OptRect SPShape::bbox(Geom::Affine const &transform, SPItem::BBoxType bbox
{
Geom::Affine tr(sp_shape_marker_get_transform_at_start(path_it->front()));
- if (!marker->orient_auto) {
+ if (marker->orient_mode == MARKER_ORIENT_ANGLE) {
Geom::Point transl = tr.translation();
tr = Geom::Rotate::from_degrees(marker->orient) * Geom::Translate(transl);
}
@@ -489,13 +494,13 @@ Geom::OptRect SPShape::bbox(Geom::Affine const &transform, SPItem::BBoxType bbox
* Loop to end_default (so including closing segment), because when a path is closed,
* there should be a midpoint marker between last segment and closing straight line segment */
- SPMarker* marker = SP_MARKER (this->_marker[i]);
+ SPMarker* marker = _marker[i];
SPItem* marker_item = sp_item_first_item_child( marker );
if (marker_item) {
Geom::Affine tr(sp_shape_marker_get_transform(*curve_it1, *curve_it2));
- if (!marker->orient_auto) {
+ if (marker->orient_mode == MARKER_ORIENT_ANGLE) {
Geom::Point transl = tr.translation();
tr = Geom::Rotate::from_degrees(marker->orient) * Geom::Translate(transl);
}
@@ -518,7 +523,7 @@ Geom::OptRect SPShape::bbox(Geom::Affine const &transform, SPItem::BBoxType bbox
Geom::Curve const &lastcurve = path_it->back_default();
Geom::Affine tr = sp_shape_marker_get_transform_at_end(lastcurve);
- if (!marker->orient_auto) {
+ if (marker->orient_mode == MARKER_ORIENT_ANGLE) {
Geom::Point transl = tr.translation();
tr = Geom::Rotate::from_degrees(marker->orient) * Geom::Translate(transl);
}
@@ -535,8 +540,8 @@ Geom::OptRect SPShape::bbox(Geom::Affine const &transform, SPItem::BBoxType bbox
// END marker
for (unsigned i = 0; i < 4; i += 3) { // SP_MARKER_LOC and SP_MARKER_LOC_END
- if ( this->_marker[i] ) {
- SPMarker* marker = SP_MARKER (this->_marker[i]);
+ if ( _marker[i] ) {
+ SPMarker* marker = _marker[i];
SPItem* marker_item = sp_item_first_item_child( marker );
if (marker_item) {
@@ -553,7 +558,7 @@ Geom::OptRect SPShape::bbox(Geom::Affine const &transform, SPItem::BBoxType bbox
Geom::Affine tr = sp_shape_marker_get_transform_at_end(lastcurve);
- if (!marker->orient_auto) {
+ if (marker->orient_mode == MARKER_ORIENT_ANGLE) {
Geom::Point transl = tr.translation();
tr = Geom::Rotate::from_degrees(marker->orient) * Geom::Translate(transl);
}
@@ -723,7 +728,7 @@ Inkscape::DrawingItem* SPShape::show(Inkscape::Drawing &drawing, unsigned int /*
* match the style.
*/
for (int i = 0 ; i < SP_MARKER_LOC_QTY ; i++) {
- sp_shape_set_marker (this, i, this->style->marker[i].value);
+ sp_shape_set_marker (this, i, this->style->marker_ptrs[i]->value);
}
if (this->hasMarkers ()) {
@@ -733,10 +738,10 @@ Inkscape::DrawingItem* SPShape::show(Inkscape::Drawing &drawing, unsigned int /*
}
for (int i = 0; i < SP_MARKER_LOC_QTY; i++) {
- if (this->_marker[i]) {
- sp_marker_show_dimension ((SPMarker *) this->_marker[i],
- s->key() + i,
- this->numberOfMarkers (i));
+ if (_marker[i]) {
+ sp_marker_show_dimension(_marker[i],
+ s->key() + i,
+ numberOfMarkers(i));
}
}
@@ -751,17 +756,17 @@ Inkscape::DrawingItem* SPShape::show(Inkscape::Drawing &drawing, unsigned int /*
* Sets style, path, and paintbox. Updates marker views, including dimensions.
*/
void SPShape::hide(unsigned int key) {
- for (int i=0; i<SP_MARKER_LOC_QTY; i++) {
- if (this->_marker[i]) {
- for (SPItemView* v = this->display; v != NULL; v = v->next) {
- if (key == v->key) {
- sp_marker_hide ((SPMarker *) this->_marker[i], v->arenaitem->key() + i);
- }
- }
- }
- }
+ for (int i = 0; i < SP_MARKER_LOC_QTY; ++i) {
+ if (_marker[i]) {
+ for (SPItemView* v = display; v != NULL; v = v->next) {
+ if (key == v->key) {
+ sp_marker_hide(_marker[i], v->arenaitem->key() + i);
+ }
+ }
+ }
+ }
- //SPLPEItem::onHide(key);
+ //SPLPEItem::onHide(key);
}
/**
@@ -776,7 +781,7 @@ int SPShape::hasMarkers() const
// Ignore markers for objects which are inside markers themselves.
for (SPObject *parent = this->parent; parent != NULL; parent = parent->parent) {
- if(SP_IS_MARKER(parent)) {
+ if (dynamic_cast<SPMarker *>(parent)) {
return 0;
}
}
@@ -854,22 +859,20 @@ int SPShape::numberOfMarkers(int type) const {
static void
sp_shape_marker_release (SPObject *marker, SPShape *shape)
{
- SPItem *item;
- int i;
+ SPItem *item = dynamic_cast<SPItem *>(shape);
+ g_return_if_fail(item != NULL);
- item = (SPItem *) shape;
-
- for (i = 0; i < SP_MARKER_LOC_QTY; i++) {
+ for (int i = 0; i < SP_MARKER_LOC_QTY; i++) {
if (marker == shape->_marker[i]) {
SPItemView *v;
/* Hide marker */
for (v = item->display; v != NULL; v = v->next) {
- sp_marker_hide ((SPMarker *) (shape->_marker[i]), v->arenaitem->key() + i);
+ sp_marker_hide(shape->_marker[i], v->arenaitem->key() + i);
}
/* Detach marker */
shape->_release_connect[i].disconnect();
shape->_modified_connect[i].disconnect();
- shape->_marker[i] = sp_object_hunref (shape->_marker[i], item);
+ shape->_marker[i] = static_cast<SPMarker *>(sp_object_hunref(shape->_marker[i], item));
}
}
}
@@ -894,15 +897,16 @@ sp_shape_marker_modified (SPObject */*marker*/, guint /*flags*/, SPItem */*item*
void
sp_shape_set_marker (SPObject *object, unsigned int key, const gchar *value)
{
- SPItem *item = (SPItem *) object;
- SPShape *shape = (SPShape *) object;
+ SPShape *shape = dynamic_cast<SPShape *>(object);
+ g_return_if_fail(shape != NULL);
if (key > SP_MARKER_LOC_END) {
return;
}
SPObject *mrk = sp_css_uri_reference_resolve(object->document, value);
- if (mrk != shape->_marker[key]) {
+ SPMarker *marker = dynamic_cast<SPMarker *>(mrk);
+ if (marker != shape->_marker[key]) {
if (shape->_marker[key]) {
SPItemView *v;
@@ -911,18 +915,18 @@ sp_shape_set_marker (SPObject *object, unsigned int key, const gchar *value)
shape->_modified_connect[key].disconnect();
/* Hide marker */
- for (v = item->display; v != NULL; v = v->next) {
- sp_marker_hide ((SPMarker *) (shape->_marker[key]),
- v->arenaitem->key() + key);
+ for (v = shape->display; v != NULL; v = v->next) {
+ sp_marker_hide(shape->_marker[key],
+ v->arenaitem->key() + key);
}
/* Unref marker */
- shape->_marker[key] = sp_object_hunref (shape->_marker[key], object);
+ shape->_marker[key] = static_cast<SPMarker *>(sp_object_hunref(shape->_marker[key], object));
}
- if (SP_IS_MARKER (mrk)) {
- shape->_marker[key] = sp_object_href (mrk, object);
- shape->_release_connect[key] = mrk->connectRelease(sigc::bind<1>(sigc::ptr_fun(&sp_shape_marker_release), shape));
- shape->_modified_connect[key] = mrk->connectModified(sigc::bind<2>(sigc::ptr_fun(&sp_shape_marker_modified), shape));
+ if (marker) {
+ shape->_marker[key] = static_cast<SPMarker *>(sp_object_href(marker, object));
+ shape->_release_connect[key] = marker->connectRelease(sigc::bind<1>(sigc::ptr_fun(&sp_shape_marker_release), shape));
+ shape->_modified_connect[key] = marker->connectModified(sigc::bind<2>(sigc::ptr_fun(&sp_shape_marker_modified), shape));
}
}
}
diff --git a/src/sp-shape.h b/src/sp-shape.h
index f260c1ee6..fe9d03275 100644
--- a/src/sp-shape.h
+++ b/src/sp-shape.h
@@ -15,19 +15,20 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include "sp-lpe-item.h"
-#include "sp-marker-loc.h"
#include <2geom/forward.h>
-
-#include <stddef.h>
+#include <cstddef>
#include <sigc++/connection.h>
+#include "sp-lpe-item.h"
+#include "sp-marker-loc.h"
+
#define SP_SHAPE(obj) (dynamic_cast<SPShape*>((SPObject*)obj))
#define SP_IS_SHAPE(obj) (dynamic_cast<const SPShape*>((SPObject*)obj) != NULL)
#define SP_SHAPE_WRITE_PATH (1 << 2)
class SPDesktop;
+class SPMarker;
namespace Inkscape { class DrawingItem; }
/**
@@ -51,17 +52,17 @@ public: // temporarily public, until SPPath is properly classed, etc.
SPCurve *_curve;
public:
- SPObject *_marker[SP_MARKER_LOC_QTY];
+ SPMarker *_marker[SP_MARKER_LOC_QTY];
sigc::connection _release_connect [SP_MARKER_LOC_QTY];
sigc::connection _modified_connect [SP_MARKER_LOC_QTY];
virtual void build(SPDocument *document, Inkscape::XML::Node *repr);
virtual void release();
- virtual void update(SPCtx* ctx, guint flags);
+ virtual void update(SPCtx* ctx, unsigned int flags);
virtual void modified(unsigned int flags);
- virtual void set(unsigned int key, gchar const* value);
- virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags);
+ virtual void set(unsigned int key, char const* value);
+ virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags);
virtual Geom::OptRect bbox(Geom::Affine const &transform, SPItem::BBoxType bboxtype) const;
virtual void print(SPPrintContext* ctx);
@@ -75,7 +76,7 @@ public:
};
-void sp_shape_set_marker (SPObject *object, unsigned int key, const gchar *value);
+void sp_shape_set_marker (SPObject *object, unsigned int key, const char *value);
Geom::Affine sp_shape_marker_get_transform(Geom::Curve const & c1, Geom::Curve const & c2);
Geom::Affine sp_shape_marker_get_transform_at_start(Geom::Curve const & c);
diff --git a/src/sp-solid-color.cpp b/src/sp-solid-color.cpp
new file mode 100644
index 000000000..0d6b96b62
--- /dev/null
+++ b/src/sp-solid-color.cpp
@@ -0,0 +1,99 @@
+/** @file
+ * @solid color class.
+ */
+/* Authors:
+ * Tavmjong Bah <tavjong@free.fr>
+ *
+ * Copyright (C) 2014 Tavmjong Bah
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+#include <cairo.h>
+
+#include "sp-solid-color.h"
+
+#include "attributes.h"
+#include "style.h"
+#include "xml/repr.h"
+
+#include "sp-factory.h"
+#include "sp-item.h"
+#include "style-internal.h"
+
+namespace {
+ SPObject* createSolidColor() {
+ return new SPSolidColor();
+ }
+
+ bool solidColorRegistered = SPFactory::instance().registerObject("svg:solidColor", createSolidColor);
+}
+
+
+/*
+ * Solid Color
+ */
+SPSolidColor::SPSolidColor() : SPPaintServer() {
+}
+
+SPSolidColor::~SPSolidColor() {
+}
+
+void SPSolidColor::build(SPDocument* doc, Inkscape::XML::Node* repr) {
+ SPPaintServer::build(doc, repr);
+
+ this->readAttr( "style" );
+ this->readAttr( "solid-color" );
+ this->readAttr( "solid-opacity" );
+}
+
+/**
+ * Virtual build: set solidcolor attributes from its associated XML node.
+ */
+
+void SPSolidColor::set(unsigned int key, const gchar* value) {
+
+ if (SP_ATTRIBUTE_IS_CSS(key)) {
+ sp_style_read_from_object(this->style, this);
+ this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG);
+ } else {
+ SPPaintServer::set(key, value);
+ }
+}
+
+/**
+ * Virtual set: set attribute to value.
+ */
+
+Inkscape::XML::Node* SPSolidColor::write(Inkscape::XML::Document* xml_doc, Inkscape::XML::Node* repr, guint flags) {
+ if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) {
+ repr = xml_doc->createElement("svg:solidColor");
+ }
+
+ SPObject::write(xml_doc, repr, flags);
+
+ return repr;
+}
+
+cairo_pattern_t* SPSolidColor::pattern_new(cairo_t * /*ct*/, Geom::OptRect const & /*bbox*/, double opacity) {
+
+ SPIColor *c = &(this->style->solid_color);
+ cairo_pattern_t *cp = cairo_pattern_create_rgba ( c->value.color.v.c[0], c->value.color.v.c[1], c->value.color.v.c[2], SP_SCALE24_TO_FLOAT(this->style->solid_opacity.value) * opacity );
+
+ return cp;
+}
+
+
+/**
+ * Virtual write: write object attributes to repr.
+ */
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/sp-solid-color.h b/src/sp-solid-color.h
new file mode 100644
index 000000000..4dbb573b0
--- /dev/null
+++ b/src/sp-solid-color.h
@@ -0,0 +1,48 @@
+#ifndef SEEN_SP_SOLIDCOLOR_H
+#define SEEN_SP_SOLIDCOLOR_H
+
+/** \file
+ * SPSolidColor: SVG <solidColor> implementation.
+ */
+/*
+ * Authors: Tavmjong Bah
+ * Copyright (C) 2012 Tavmjong Bah
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "color.h"
+#include "sp-paint-server.h"
+
+typedef struct _cairo cairo_t;
+typedef struct _cairo_pattern cairo_pattern_t;
+
+#define SP_SOLIDCOLOR(obj) (dynamic_cast<SPSolidColor*>((SPObject*)obj))
+#define SP_IS_SOLIDCOLOR(obj) (dynamic_cast<const SPSolidColor*>((SPObject*)obj) != NULL)
+
+/** Gradient SolidColor. */
+class SPSolidColor : public SPPaintServer {
+public:
+ SPSolidColor();
+ virtual ~SPSolidColor();
+
+ virtual cairo_pattern_t* pattern_new(cairo_t *ct, Geom::OptRect const &bbox, double opacity);
+
+protected:
+ virtual void build(SPDocument* doc, Inkscape::XML::Node* repr);
+ virtual void set(unsigned int key, char const* value);
+ virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, unsigned int flags);
+};
+
+#endif /* !SEEN_SP_SOLIDCOLOR_H */
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/sp-spiral.h b/src/sp-spiral.h
index 64b95d951..94724685c 100644
--- a/src/sp-spiral.h
+++ b/src/sp-spiral.h
@@ -52,29 +52,29 @@ public:
float t0;
/* Lowlevel interface */
- void setPosition(gdouble cx, gdouble cy, gdouble exp, gdouble revo, gdouble rad, gdouble arg, gdouble t0);
+ void setPosition(double cx, double cy, double exp, double revo, double rad, double arg, double t0);
virtual Geom::Affine set_transform(Geom::Affine const& xform);
- Geom::Point getXY(gdouble t) const;
+ Geom::Point getXY(double t) const;
- void getPolar(gdouble t, gdouble* rad, gdouble* arg) const;
+ void getPolar(double t, double* rad, double* arg) const;
bool isInvalid() const;
virtual void build(SPDocument* doc, Inkscape::XML::Node* repr);
- virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags);
- virtual void update(SPCtx *ctx, guint flags);
- virtual void set(unsigned int key, gchar const* value);
+ virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags);
+ virtual void update(SPCtx *ctx, unsigned int flags);
+ virtual void set(unsigned int key, char const* value);
virtual void snappoints(std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs) const;
virtual const char* displayName() const;
- virtual gchar* description() const;
+ virtual char* description() const;
virtual void set_shape();
virtual void update_patheffect(bool write);
private:
- Geom::Point getTangent(gdouble t) const;
+ Geom::Point getTangent(double t) const;
void fitAndDraw(SPCurve* c, double dstep, Geom::Point darray[], Geom::Point const& hat1, Geom::Point& hat2, double* t) const;
};
diff --git a/src/sp-star.cpp b/src/sp-star.cpp
index eac33ed7b..97a690520 100644
--- a/src/sp-star.cpp
+++ b/src/sp-star.cpp
@@ -515,6 +515,7 @@ void SPStar::snappoints(std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::
Geom::Affine SPStar::set_transform(Geom::Affine const &xform)
{
+ bool opt_trans = (randomized == 0);
// Only set transform with proportional scaling
if (!xform.withoutTranslation().isUniformScale()) {
return xform;
@@ -530,7 +531,7 @@ Geom::Affine SPStar::set_transform(Geom::Affine const &xform)
/* This function takes care of translation and scaling, we return whatever parts we can't
handle. */
- Geom::Affine ret(Geom::Affine(xform).withoutTranslation());
+ Geom::Affine ret(opt_trans ? xform.withoutTranslation() : xform);
gdouble const s = hypot(ret[0], ret[1]);
if (s > 1e-9) {
ret[0] /= s;
diff --git a/src/sp-star.h b/src/sp-star.h
index 0070ce685..1ebe3298a 100644
--- a/src/sp-star.h
+++ b/src/sp-star.h
@@ -1,5 +1,5 @@
-#ifndef __SP_STAR_H__
-#define __SP_STAR_H__
+#ifndef SEEN_SP_STAR_H
+#define SEEN_SP_STAR_H
/*
* <sodipodi:star> implementation
@@ -30,7 +30,7 @@ public:
SPStar();
virtual ~SPStar();
- gint sides;
+ int sides;
Geom::Point center;
double r[2];
@@ -46,12 +46,12 @@ public:
// What does polygon have that shape doesn't?
virtual void build(SPDocument *document, Inkscape::XML::Node *repr);
- virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags);
- virtual void set(unsigned int key, gchar const* value);
- virtual void update(SPCtx* ctx, guint flags);
+ virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags);
+ virtual void set(unsigned int key, char const* value);
+ virtual void update(SPCtx* ctx, unsigned int flags);
virtual const char* displayName() const;
- virtual gchar* description() const;
+ virtual char* description() const;
virtual void snappoints(std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs) const;
virtual void update_patheffect(bool write);
@@ -59,9 +59,9 @@ public:
virtual Geom::Affine set_transform(Geom::Affine const& xform);
};
-void sp_star_position_set (SPStar *star, gint sides, Geom::Point center, gdouble r1, gdouble r2, gdouble arg1, gdouble arg2, bool isflat, double rounded, double randomized);
+void sp_star_position_set (SPStar *star, int sides, Geom::Point center, double r1, double r2, double arg1, double arg2, bool isflat, double rounded, double randomized);
-Geom::Point sp_star_get_xy (SPStar const *star, SPStarPoint point, gint index, bool randomized = false);
+Geom::Point sp_star_get_xy (SPStar const *star, SPStarPoint point, int index, bool randomized = false);
diff --git a/src/sp-stop.h b/src/sp-stop.h
index b1996e054..f7b3a677a 100644
--- a/src/sp-stop.h
+++ b/src/sp-stop.h
@@ -5,12 +5,13 @@
* SPStop: SVG <stop> implementation.
*/
/*
- * Authors?
+ * Authors:
*/
#include "sp-object.h"
#include "color.h"
-#include <glib.h>
+
+typedef unsigned int guint32;
namespace Glib {
class ustring;
@@ -26,7 +27,7 @@ public:
virtual ~SPStop();
/// \todo fixme: Should be SPSVGPercentage
- gfloat offset;
+ float offset;
bool currentColor;
@@ -37,7 +38,7 @@ public:
SPColor specified_color;
/// \todo fixme: Implement SPSVGNumber or something similar.
- gfloat opacity;
+ float opacity;
Glib::ustring * path_string;
//SPCurve path;
@@ -53,8 +54,8 @@ public:
protected:
virtual void build(SPDocument* doc, Inkscape::XML::Node* repr);
- virtual void set(unsigned int key, const gchar* value);
- virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, guint flags);
+ virtual void set(unsigned int key, const char* value);
+ virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, unsigned int flags);
};
diff --git a/src/sp-string.cpp b/src/sp-string.cpp
index 08755a5fc..b561187d0 100644
--- a/src/sp-string.cpp
+++ b/src/sp-string.cpp
@@ -30,10 +30,14 @@
#include "sp-string.h"
+#include "style.h"
+
#include "xml/repr.h"
#include "sp-factory.h"
+#include <iostream>
+
namespace {
SPObject* createString() {
return new SPString();
@@ -47,7 +51,6 @@ namespace {
#####################################################*/
SPString::SPString() : SPObject() {
- //new (&this->string) Glib::ustring();
}
SPString::~SPString() {
@@ -66,45 +69,110 @@ void SPString::release() {
void SPString::read_content() {
- SPString* object = this;
+ SPString* object = this;
SPString *string = SP_STRING(object);
string->string.clear();
//XML Tree being used directly here while it shouldn't be.
gchar const *xml_string = string->getRepr()->content();
- // see algorithms described in svg 1.1 section 10.15
- if (object->xml_space.value == SP_XML_SPACE_PRESERVE) {
- for ( ; *xml_string ; xml_string = g_utf8_next_char(xml_string) ) {
- gunichar c = g_utf8_get_char(xml_string);
- if ((c == 0xa) || (c == 0xd) || (c == '\t')) {
- c = ' ';
- }
- string->string += c;
+
+ // std::cout << ">" << (xml_string?xml_string:"Null") << "<" << std::endl;
+
+ // SVG2/CSS Text Level 3 'white-space' has five values.
+ // See: http://dev.w3.org/csswg/css-text/#white-space
+ // | New Lines | Spaces/Tabs | Text Wrapping
+ // ---------|------------|--------------|--------------
+ // normal | Collapes | Collapse | Wrap
+ // pre | Preserve | Preserve | No Wrap
+ // nowrap | Collapse | Collapse | No Wrap
+ // pre-wrap | Preserve | Preserve | Wrap
+ // pre-line | Preserve | Collapse | Wrap
+
+ // 'xml:space' has two values:
+ // 'default' which corresponds to 'normal' (without wrapping).
+ // 'preserve' which corresponds to 'pre' except new lines are converted to spaces.
+ // See algorithms described in svg 1.1 section 10.15
+
+ bool collapse_space = true;
+ bool collapse_line = true;
+ bool is_css = false;
+
+ // Strings don't have style, check parent for style
+ if( object->parent && object->parent->style ) {
+ if( object->parent->style->white_space.computed == SP_CSS_WHITE_SPACE_PRE ||
+ object->parent->style->white_space.computed == SP_CSS_WHITE_SPACE_PREWRAP ||
+ object->parent->style->white_space.computed == SP_CSS_WHITE_SPACE_PRELINE ) {
+ collapse_line = false;
+ }
+ if( object->parent->style->white_space.computed == SP_CSS_WHITE_SPACE_PRE ||
+ object->parent->style->white_space.computed == SP_CSS_WHITE_SPACE_PREWRAP ) {
+ collapse_space = false;
+ }
+ if( object->parent->style->white_space.computed != SP_CSS_WHITE_SPACE_NORMAL ) {
+ is_css = true; // If white-space not normal, we assume white-space is set.
}
}
- else {
- bool whitespace = false;
- for ( ; *xml_string ; xml_string = g_utf8_next_char(xml_string) ) {
- gunichar c = g_utf8_get_char(xml_string);
- if ((c == 0xa) || (c == 0xd)) {
+ if( !is_css ) {
+ // SVG 2: Use 'xml:space' only if 'white-space' not 'normal'.
+ if (object->xml_space.value == SP_XML_SPACE_PRESERVE) {
+ collapse_space = false;
+ }
+ }
+
+ bool white_space = false;
+ for ( ; *xml_string ; xml_string = g_utf8_next_char(xml_string) ) {
+
+ gunichar c = g_utf8_get_char(xml_string);
+ switch (c) {
+ case 0xd: // Carriage return
+ // XML Parsers convert 0xa, 0xd, 0xD 0xA to 0xA. CSS also follows this rule so we
+ // should never see 0xd.
+ std::cerr << "SPString: Carriage Return found! Argh!" << std::endl;
continue;
- }
- if ((c == ' ') || (c == '\t')) {
- whitespace = true;
- } else {
- if (whitespace && (!string->string.empty() || (object->getPrev() != NULL))) {
+ break;
+ case 0xa: // Line feed
+ if( collapse_line ) {
+ if( !is_css && collapse_space ) continue; // xml:space == 'default' strips LFs.
+ white_space = true; // Convert to space and collapse
+ } else {
+ string->string += c; // Preserve line feed
+ continue;
+ }
+ break;
+ case '\t': // Tab
+ if( collapse_space ) {
+ white_space = true; // Convert to space and collapse
+ } else {
+ string->string += c; // Preserve tab
+ continue;
+ }
+ break;
+ case ' ': // Space
+ if( collapse_space ) {
+ white_space = true; // Collapse white space
+ } else {
+ string->string += c; // Preserve space
+ continue;
+ }
+ break;
+ default:
+ if( white_space && (!string->string.empty() || (object->getPrev() != NULL))) {
string->string += ' ';
}
string->string += c;
- whitespace = false;
- }
- }
- if (whitespace && object->getRepr()->next() != NULL) { // can't use SPObject::getNext() when the SPObject tree is still being built
- string->string += ' ';
- }
+ white_space = false;
+
+ } // End switch
+ } // End loop
+
+ // Insert white space at end if more text follows
+ if (white_space && object->getRepr()->next() != NULL) { // can't use SPObject::getNext() when the SPObject tree is still being built
+ string->string += ' ';
}
+
+ // std::cout << ">" << string->string << "<" << std::endl;
object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
}
diff --git a/src/sp-string.h b/src/sp-string.h
index eabf76353..b80b4b8bf 100644
--- a/src/sp-string.h
+++ b/src/sp-string.h
@@ -1,5 +1,5 @@
-#ifndef __SP_STRING_H__
-#define __SP_STRING_H__
+#ifndef SEEN_SP_STRING_H
+#define SEEN_SP_STRING_H
/*
* string elements
diff --git a/src/sp-style-elem.cpp b/src/sp-style-elem.cpp
index 84f110134..da17b08d9 100644
--- a/src/sp-style-elem.cpp
+++ b/src/sp-style-elem.cpp
@@ -26,23 +26,18 @@ SPStyleElem::~SPStyleElem() {
}
void SPStyleElem::set(unsigned int key, const gchar* value) {
- SPStyleElem* object = this;
-
- g_return_if_fail(object);
- SPStyleElem &style_elem = *SP_STYLE_ELEM(object);
-
switch (key) {
case SP_ATTR_TYPE: {
if (!value) {
/* TODO: `type' attribute is required. Give error message as per
http://www.w3.org/TR/SVG11/implnote.html#ErrorProcessing. */
- style_elem.is_css = false;
+ is_css = false;
} else {
/* fixme: determine what whitespace is allowed. Will probably need to ask on SVG
- * list; though the relevant RFC may give info on its lexer. */
- style_elem.is_css = ( g_ascii_strncasecmp(value, "text/css", 8) == 0
- && ( value[8] == '\0' ||
- value[8] == ';' ) );
+ list; though the relevant RFC may give info on its lexer. */
+ is_css = ( g_ascii_strncasecmp(value, "text/css", 8) == 0
+ && ( value[8] == '\0' ||
+ value[8] == ';' ) );
}
break;
}
@@ -67,14 +62,18 @@ static void
child_add_rm_cb(Inkscape::XML::Node *, Inkscape::XML::Node *, Inkscape::XML::Node *,
void *const data)
{
- static_cast<SPObject *>(data)->read_content();
+ SPObject *obj = reinterpret_cast<SPObject *>(data);
+ g_assert(data != NULL);
+ obj->read_content();
}
static void
content_changed_cb(Inkscape::XML::Node *, gchar const *, gchar const *,
void *const data)
{
- static_cast<SPObject *>(data)->read_content();
+ SPObject *obj = reinterpret_cast<SPObject *>(data);
+ g_assert(data != NULL);
+ obj->read_content();
}
static void
@@ -82,24 +81,22 @@ child_order_changed_cb(Inkscape::XML::Node *, Inkscape::XML::Node *,
Inkscape::XML::Node *, Inkscape::XML::Node *,
void *const data)
{
- static_cast<SPObject *>(data)->read_content();
+ SPObject *obj = reinterpret_cast<SPObject *>(data);
+ g_assert(data != NULL);
+ obj->read_content();
}
Inkscape::XML::Node* SPStyleElem::write(Inkscape::XML::Document* xml_doc, Inkscape::XML::Node* repr, guint flags) {
- SPStyleElem* object = this;
-
if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) {
repr = xml_doc->createElement("svg:style");
}
- g_return_val_if_fail(object, repr);
- SPStyleElem &style_elem = *SP_STYLE_ELEM(object);
if (flags & SP_OBJECT_WRITE_BUILD) {
g_warning("nyi: Forming <style> content for SP_OBJECT_WRITE_BUILD.");
/* fixme: Consider having the CRStyleSheet be a member of SPStyleElem, and then
pretty-print to a string s, then repr->addChild(xml_doc->createTextNode(s), NULL). */
}
- if (style_elem.is_css) {
+ if (is_css) {
repr->setAttribute("type", "text/css");
}
/* todo: media */
@@ -263,10 +260,6 @@ property_cb(CRDocHandler *const a_handler,
}
void SPStyleElem::read_content() {
- SPStyleElem* object = this;
-
- SPStyleElem &style_elem = *SP_STYLE_ELEM(object);
-
/* fixme: If there's more than one <style> element in a document, then the document stylesheet
* will be set to a random one of them, even switching between them.
*
@@ -283,7 +276,7 @@ void SPStyleElem::read_content() {
*/
//XML Tree being used directly here while it shouldn't be.
- GString *const text = concat_children(*style_elem.getRepr());
+ GString *const text = concat_children(*getRepr());
CRParser *parser = cr_parser_new_from_buf(reinterpret_cast<guchar *>(text->str), text->len,
CR_UTF_8, FALSE);
@@ -312,7 +305,7 @@ void SPStyleElem::read_content() {
CRStatus const parse_status = cr_parser_parse(parser);
g_assert(sac_handler->app_data == &parse_tmp);
if (parse_status == CR_OK) {
- cr_cascade_set_sheet(style_elem.document->style_cascade, stylesheet, ORIGIN_AUTHOR);
+ cr_cascade_set_sheet(document->style_cascade, stylesheet, ORIGIN_AUTHOR);
} else {
if (parse_status != CR_PARSING_ERROR) {
g_printerr("parsing error code=%u\n", unsigned(parse_status));
@@ -323,7 +316,7 @@ void SPStyleElem::read_content() {
}
}
cr_parser_destroy(parser);
- //object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+ //requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
// Style references via class= do not, and actually cannot, use autoupdating URIReferences.
// Therefore, if an object refers to a stylesheet which has not yet loaded when the object is being loaded
@@ -331,7 +324,6 @@ void SPStyleElem::read_content() {
// Below is a partial hack that fixes this for a single case: when the <style> is a child of the object
// that uses a style from it. It just forces the parent of <style> to reread its style as soon as the stylesheet
// is fully loaded. Naturally, this won't work if the user of the stylesheet is its grandparent or precedent.
- SPObject *parent = object->parent;
if ( parent ) {
sp_style_read_from_object(parent->style, parent);
}
@@ -351,12 +343,10 @@ rec_add_listener(Inkscape::XML::Node &repr,
}
void SPStyleElem::build(SPDocument *document, Inkscape::XML::Node *repr) {
- SPStyleElem* object = this;
-
- object->read_content();
+ read_content();
- object->readAttr( "type" );
- object->readAttr( "media" );
+ readAttr( "type" );
+ readAttr( "media" );
static Inkscape::XML::NodeEventVector const nodeEventVector = {
child_add_rm_cb, // child_added
@@ -365,7 +355,7 @@ void SPStyleElem::build(SPDocument *document, Inkscape::XML::Node *repr) {
content_changed_cb, // content_changed
child_order_changed_cb, // order_changed
};
- rec_add_listener(*repr, &nodeEventVector, object);
+ rec_add_listener(*repr, &nodeEventVector, this);
SPObject::build(document, repr);
}
diff --git a/src/sp-style-elem.h b/src/sp-style-elem.h
index 8e8a2b3a8..a3f4bdc70 100644
--- a/src/sp-style-elem.h
+++ b/src/sp-style-elem.h
@@ -4,9 +4,6 @@
#include "sp-object.h"
#include "media.h"
-#define SP_STYLE_ELEM(obj) (dynamic_cast<SPStyleElem*>((SPObject*)obj))
-#define SP_IS_STYLE_ELEM(obj) (dynamic_cast<const SPStyleElem*>((SPObject*)obj) != NULL)
-
class SPStyleElem : public SPObject {
public:
SPStyleElem();
@@ -16,9 +13,9 @@ public:
bool is_css;
virtual void build(SPDocument* doc, Inkscape::XML::Node* repr);
- virtual void set(unsigned int key, gchar const* value);
+ virtual void set(unsigned int key, char const* value);
virtual void read_content();
- virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, guint flags);
+ virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, unsigned int flags);
};
diff --git a/src/sp-switch.h b/src/sp-switch.h
index c35982860..4fce1f5a6 100644
--- a/src/sp-switch.h
+++ b/src/sp-switch.h
@@ -1,5 +1,5 @@
-#ifndef __SP_SWITCH_H__
-#define __SP_SWITCH_H__
+#ifndef SEEN_SP_SWITCH_H
+#define SEEN_SP_SWITCH_H
/*
* SVG <switch> implementation
@@ -12,10 +12,12 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
+#include <cstddef>
+#include <sigc++/connection.h>
+
#include "sp-item-group.h"
-#include <stddef.h>
-#include <sigc++/connection.h>
+typedef struct _GSList GSList;
#define SP_SWITCH(obj) (dynamic_cast<SPSwitch*>((SPObject*)obj))
#define SP_IS_SWITCH(obj) (dynamic_cast<const SPSwitch*>((SPObject*)obj) != NULL)
diff --git a/src/sp-symbol.h b/src/sp-symbol.h
index a2e769cc2..6b46a8c1a 100644
--- a/src/sp-symbol.h
+++ b/src/sp-symbol.h
@@ -1,5 +1,5 @@
-#ifndef __SP_SYMBOL_H__
-#define __SP_SYMBOL_H__
+#ifndef SEEN_SP_SYMBOL_H
+#define SEEN_SP_SYMBOL_H
/*
* SVG <symbol> implementation
@@ -17,14 +17,14 @@
* Maybe we should merge them somehow (Lauris)
*/
-#define SP_TYPE_SYMBOL (sp_symbol_get_type ())
-#define SP_SYMBOL(obj) (dynamic_cast<SPSymbol*>((SPObject*)obj))
-#define SP_IS_SYMBOL(obj) (dynamic_cast<const SPSymbol*>((SPObject*)obj) != NULL)
-
#include <2geom/affine.h>
#include "sp-item-group.h"
#include "viewbox.h"
+#define SP_TYPE_SYMBOL (sp_symbol_get_type ())
+#define SP_SYMBOL(obj) (dynamic_cast<SPSymbol*>((SPObject*)obj))
+#define SP_IS_SYMBOL(obj) (dynamic_cast<const SPSymbol*>((SPObject*)obj) != NULL)
+
class SPSymbol : public SPGroup, public SPViewBox {
public:
SPSymbol();
@@ -32,9 +32,9 @@ public:
virtual void build(SPDocument *document, Inkscape::XML::Node *repr);
virtual void release();
- virtual void set(unsigned int key, gchar const* value);
- virtual void update(SPCtx *ctx, guint flags);
- virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags);
+ virtual void set(unsigned int key, char const* value);
+ virtual void update(SPCtx *ctx, unsigned int flags);
+ virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags);
virtual void modified(unsigned int flags);
virtual void child_added(Inkscape::XML::Node* child, Inkscape::XML::Node* ref);
diff --git a/src/sp-tag-use-reference.cpp b/src/sp-tag-use-reference.cpp
new file mode 100644
index 000000000..50c011812
--- /dev/null
+++ b/src/sp-tag-use-reference.cpp
@@ -0,0 +1,156 @@
+/*
+ * The reference corresponding to href of <inkscape:tagref> element.
+ *
+ * Copyright (C) Theodore Janeczko 2012-2014 <flutterguy317@gmail.com>
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information.
+ */
+
+#include <cstring>
+#include <string>
+#include <string.h>
+
+#include "enums.h"
+#include "sp-tag-use-reference.h"
+
+#include "display/curve.h"
+#include "livarot/Path.h"
+#include "preferences.h"
+#include "sp-shape.h"
+#include "sp-text.h"
+#include "uri.h"
+
+#if 0
+namespace {
+ SPObject* createTagUseReference() {
+ return new SPTag();
+ }
+ bool tagUseReferencesRegistered = SPFactory::instance().registerObject("inkscape:tag", createTag);
+}
+// this SPObject doesn't need to be registered
+#endif
+
+
+bool SPTagUseReference::_acceptObject(SPObject * const obj) const
+{
+ if (SP_IS_ITEM(obj)) {
+ SPObject * const owner = getOwner();
+ // Refuse references to us or to an ancestor.
+ for ( SPObject *iter = owner ; iter ; iter = iter->parent ) {
+ if ( iter == obj ) {
+ return false;
+ }
+ }
+ return true;
+ } else {
+ return false;
+ }
+}
+
+
+static void sp_usepath_href_changed(SPObject *old_ref, SPObject *ref, SPTagUsePath *offset);
+static void sp_usepath_delete_self(SPObject *deleted, SPTagUsePath *offset);
+
+SPTagUsePath::SPTagUsePath(SPObject* i_owner):SPTagUseReference(i_owner)
+{
+ owner=i_owner;
+ originalPath = NULL;
+ sourceDirty=false;
+ sourceHref = NULL;
+ sourceRepr = NULL;
+ sourceObject = NULL;
+ _changed_connection = changedSignal().connect(sigc::bind(sigc::ptr_fun(sp_usepath_href_changed), this)); // listening to myself, this should be virtual instead
+
+ user_unlink = NULL;
+}
+
+SPTagUsePath::~SPTagUsePath(void)
+{
+ delete originalPath;
+ originalPath = NULL;
+
+ _changed_connection.disconnect(); // to do before unlinking
+
+ quit_listening();
+ unlink();
+}
+
+void
+SPTagUsePath::link(char *to)
+{
+ if ( to == NULL ) {
+ quit_listening();
+ unlink();
+ } else {
+ if ( !sourceHref || ( strcmp(to, sourceHref) != 0 ) ) {
+ g_free(sourceHref);
+ sourceHref = g_strdup(to);
+ try {
+ attach(Inkscape::URI(to));
+ } catch (Inkscape::BadURIException &e) {
+ /* TODO: Proper error handling as per
+ * http://www.w3.org/TR/SVG11/implnote.html#ErrorProcessing.
+ */
+ g_warning("%s", e.what());
+ detach();
+ }
+ }
+ }
+}
+
+void
+SPTagUsePath::unlink(void)
+{
+ g_free(sourceHref);
+ sourceHref = NULL;
+ detach();
+}
+
+void
+SPTagUsePath::start_listening(SPObject* to)
+{
+ if ( to == NULL ) {
+ return;
+ }
+ sourceObject = to;
+ sourceRepr = to->getRepr();
+ _delete_connection = to->connectDelete(sigc::bind(sigc::ptr_fun(&sp_usepath_delete_self), this));
+}
+
+void
+SPTagUsePath::quit_listening(void)
+{
+ if ( sourceObject == NULL ) {
+ return;
+ }
+ _delete_connection.disconnect();
+ sourceRepr = NULL;
+ sourceObject = NULL;
+}
+
+static void
+sp_usepath_href_changed(SPObject */*old_ref*/, SPObject */*ref*/, SPTagUsePath *offset)
+{
+ offset->quit_listening();
+ SPItem *refobj = offset->getObject();
+ if ( refobj ) {
+ offset->start_listening(refobj);
+ }
+}
+
+static void
+sp_usepath_delete_self(SPObject */*deleted*/, SPTagUsePath *offset)
+{
+ offset->owner->deleteObject();
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/sp-tag-use-reference.h b/src/sp-tag-use-reference.h
new file mode 100644
index 000000000..2a59fd6bd
--- /dev/null
+++ b/src/sp-tag-use-reference.h
@@ -0,0 +1,78 @@
+#ifndef SEEN_SP_TAG_USE_REFERENCE_H
+#define SEEN_SP_TAG_USE_REFERENCE_H
+
+/*
+ * The reference corresponding to href of <inkscape:tagref> element.
+ *
+ * Copyright (C) Theodore Janeczko 2012-2014 <flutterguy317@gmail.com>
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information.
+ */
+
+#include <glib.h>
+#include "sp-object.h"
+#include "sp-item.h"
+#include <uri-references.h>
+#include <stddef.h>
+#include <sigc++/sigc++.h>
+
+class Path;
+
+namespace Inkscape {
+namespace XML {
+ class Node;
+}
+}
+
+
+class SPTagUseReference : public Inkscape::URIReference {
+public:
+ SPTagUseReference(SPObject *owner) : URIReference(owner) {}
+
+ SPItem *getObject() const {
+ return static_cast<SPItem *>(URIReference::getObject());
+ }
+
+protected:
+ virtual bool _acceptObject(SPObject * const obj) const;
+
+};
+
+
+class SPTagUsePath : public SPTagUseReference {
+public:
+ Path *originalPath;
+ bool sourceDirty;
+
+ SPObject *owner;
+ gchar *sourceHref;
+ Inkscape::XML::Node *sourceRepr;
+ SPObject *sourceObject;
+
+ sigc::connection _delete_connection;
+ sigc::connection _changed_connection;
+
+ SPTagUsePath(SPObject* i_owner);
+ ~SPTagUsePath(void);
+
+ void link(char* to);
+ void unlink(void);
+ void start_listening(SPObject* to);
+ void quit_listening(void);
+ void refresh_source(void);
+
+ void (*user_unlink) (SPObject *user);
+};
+
+#endif /* !SEEN_SP_USE_REFERENCE_H */
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/sp-tag-use.cpp b/src/sp-tag-use.cpp
new file mode 100644
index 000000000..5851598f2
--- /dev/null
+++ b/src/sp-tag-use.cpp
@@ -0,0 +1,206 @@
+/*
+ * SVG <inkscape:tagref> implementation
+ *
+ * Authors:
+ * Theodore Janeczko
+ * Liam P White
+ *
+ * Copyright (C) Theodore Janeczko 2012-2014 <flutterguy317@gmail.com>
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <cstring>
+#include <string>
+
+#include <glibmm/i18n.h>
+#include "display/drawing-group.h"
+#include "attributes.h"
+#include "document.h"
+#include "uri.h"
+#include "xml/repr.h"
+#include "preferences.h"
+#include "style.h"
+#include "sp-factory.h"
+#include "sp-symbol.h"
+#include "sp-tag-use.h"
+#include "sp-tag-use-reference.h"
+
+namespace {
+ SPObject* createTagUse() {
+ return new SPTagUse();
+ }
+ bool tagUseRegistered = SPFactory::instance().registerObject("inkscape:tagref", createTagUse);
+}
+
+SPTagUse::SPTagUse()
+{
+ href = NULL;
+ //new (_changed_connection) sigc::connection;
+ ref = new SPTagUseReference(this);
+
+ _changed_connection = ref->changedSignal().connect(sigc::mem_fun(*this, &SPTagUse::href_changed));
+}
+
+SPTagUse::~SPTagUse()
+{
+
+ if (child) {
+ detach(child);
+ child = NULL;
+ }
+
+ ref->detach();
+ delete ref;
+ ref = 0;
+
+ _changed_connection.~connection(); //FIXME why?
+}
+
+void
+SPTagUse::build(SPDocument *document, Inkscape::XML::Node *repr)
+{
+ SPObject::build(document, repr);
+ readAttr( "xlink:href" );
+
+ // We don't need to create child here:
+ // reading xlink:href will attach ref, and that will cause the changed signal to be emitted,
+ // which will call sp_tag_use_href_changed, and that will take care of the child
+}
+
+void
+SPTagUse::release()
+{
+
+ if (child) {
+ detach(child);
+ child = NULL;
+ }
+
+ _changed_connection.disconnect();
+
+ g_free(href);
+ href = NULL;
+
+ ref->detach();
+
+ SPObject::release();
+}
+
+void
+SPTagUse::set(unsigned key, gchar const *value)
+{
+
+ switch (key) {
+ case SP_ATTR_XLINK_HREF: {
+ if ( value && href && ( strcmp(value, href) == 0 ) ) {
+ /* No change, do nothing. */
+ } else {
+ g_free(href);
+ href = NULL;
+ if (value) {
+ // First, set the href field, because sp_tag_use_href_changed will need it.
+ href = g_strdup(value);
+
+ // Now do the attaching, which emits the changed signal.
+ try {
+ ref->attach(Inkscape::URI(value));
+ } catch (Inkscape::BadURIException &e) {
+ g_warning("%s", e.what());
+ ref->detach();
+ }
+ } else {
+ ref->detach();
+ }
+ }
+ break;
+ }
+
+ default:
+ SPObject::set(key, value);
+ break;
+ }
+}
+
+Inkscape::XML::Node *
+SPTagUse::write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags)
+{
+ if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) {
+ repr = xml_doc->createElement("inkscape:tagref");
+ }
+
+ SPObject::write(xml_doc, repr, flags);
+
+ if (ref->getURI()) {
+ gchar *uri_string = ref->getURI()->toString();
+ repr->setAttribute("xlink:href", uri_string);
+ g_free(uri_string);
+ }
+
+ return repr;
+}
+
+/**
+ * Returns the ultimate original of a SPTagUse (i.e. the first object in the chain of its originals
+ * which is not an SPTagUse). If no original is found, NULL is returned (it is the responsibility
+ * of the caller to make sure that this is handled correctly).
+ *
+ * Note that the returned is the clone object, i.e. the child of an SPTagUse (of the argument one for
+ * the trivial case) and not the "true original".
+ */
+
+SPItem * SPTagUse::root()
+{
+ SPObject *orig = child;
+ while (orig && SP_IS_TAG_USE(orig)) {
+ orig = SP_TAG_USE(orig)->child;
+ }
+ if (!orig || !SP_IS_ITEM(orig))
+ return NULL;
+ return SP_ITEM(orig);
+}
+
+void
+SPTagUse::href_changed(SPObject */*old_ref*/, SPObject */*ref*/)
+{
+ if (href) {
+ SPItem *refobj = ref->getObject();
+ if (refobj) {
+ Inkscape::XML::Node *childrepr = refobj->getRepr();
+ const std::string typeString = NodeTraits::get_type_string(*childrepr);
+
+ SPObject* child_ = SPFactory::instance().createObject(typeString);
+ if (child_) {
+ child = child_;
+ attach(child_, lastChild());
+ sp_object_unref(child_, 0);
+ child_->invoke_build(this->document, childrepr, TRUE);
+
+ }
+ }
+ }
+}
+
+SPItem * SPTagUse::get_original()
+{
+ SPItem *ref_ = NULL;
+ if (ref) {
+ ref_ = ref->getObject();
+ }
+ return ref_;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/sp-tag-use.h b/src/sp-tag-use.h
new file mode 100644
index 000000000..3f238d654
--- /dev/null
+++ b/src/sp-tag-use.h
@@ -0,0 +1,55 @@
+#ifndef __SP_TAG_USE_H__
+#define __SP_TAG_USE_H__
+
+/*
+ * SVG <inkscape:tagref> implementation
+ *
+ * Authors:
+ * Theodore Janeczko
+ *
+ * Copyright (C) Theodore Janeczko 2012 <flutterguy317@gmail.com>
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <glib.h>
+#include <stddef.h>
+#include <sigc++/sigc++.h>
+#include "svg/svg-length.h"
+#include "sp-object.h"
+
+
+#define SP_TAG_USE(obj) (dynamic_cast<SPTagUse*> (obj))
+#define SP_IS_TAG_USE(obj) (dynamic_cast<SPTagUse*> (obj) != NULL)
+
+class SPTagUse;
+class SPTagUseReference;
+
+class SPTagUse : public SPObject {
+
+public:
+ // item built from the original's repr (the visible clone)
+ // relative to the SPUse itself, it is treated as a child, similar to a grouped item relative to its group
+ SPObject *child;
+ gchar *href;
+public:
+ SPTagUse();
+ virtual ~SPTagUse();
+
+ virtual void build(SPDocument *doc, Inkscape::XML::Node *repr);
+ virtual void set(unsigned key, gchar const *value);
+ virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, guint flags);
+ virtual void release();
+
+ virtual void href_changed(SPObject* old_ref, SPObject* ref);
+
+ //virtual SPItem* unlink();
+ virtual SPItem* get_original();
+ virtual SPItem* root();
+
+ // the reference to the original object
+ SPTagUseReference *ref;
+ sigc::connection _changed_connection;
+};
+
+#endif
diff --git a/src/sp-tag.cpp b/src/sp-tag.cpp
new file mode 100644
index 000000000..c4b40417f
--- /dev/null
+++ b/src/sp-tag.cpp
@@ -0,0 +1,154 @@
+/** \file
+ * SVG <inkscape:tag> implementation
+ *
+ * Authors:
+ * Theodore Janeczko
+ * Liam P. White
+ *
+ * Copyright (C) Theodore Janeczko 2012-2014 <flutterguy317@gmail.com>
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "attributes.h"
+#include "sp-factory.h"
+#include "sp-tag.h"
+#include "xml/repr.h"
+#include <cstring>
+
+namespace {
+ SPObject* createTag() {
+ return new SPTag();
+ }
+ bool tagsRegistered = SPFactory::instance().registerObject("inkscape:tag", createTag);
+}
+
+/*
+ * Move this SPItem into or after another SPItem in the doc
+ * \param target - the SPItem to move into or after
+ * \param intoafter - move to after the target (false), move inside (sublayer) of the target (true)
+ */
+void SPTag::moveTo(SPObject *target, gboolean intoafter) {
+
+ Inkscape::XML::Node *target_ref = ( target ? target->getRepr() : NULL );
+ Inkscape::XML::Node *our_ref = getRepr();
+ gboolean first = FALSE;
+
+ if (target_ref == our_ref) {
+ // Move to ourself ignore
+ return;
+ }
+
+ if (!target_ref) {
+ // Assume move to the "first" in the top node, find the top node
+ target_ref = our_ref;
+ while (target_ref->parent() != target_ref->root()) {
+ target_ref = target_ref->parent();
+ }
+ first = TRUE;
+ }
+
+ if (intoafter) {
+ // Move this inside of the target at the end
+ our_ref->parent()->removeChild(our_ref);
+ target_ref->addChild(our_ref, NULL);
+ } else if (target_ref->parent() != our_ref->parent()) {
+ // Change in parent, need to remove and add
+ our_ref->parent()->removeChild(our_ref);
+ target_ref->parent()->addChild(our_ref, target_ref);
+ } else if (!first) {
+ // Same parent, just move
+ our_ref->parent()->changeOrder(our_ref, target_ref);
+ }
+}
+
+/**
+ * Reads the Inkscape::XML::Node, and initializes SPTag variables. For this to get called,
+ * our name must be associated with a repr via "sp_object_type_register". Best done through
+ * sp-object-repr.cpp's repr_name_entries array.
+ */
+void
+SPTag::build(SPDocument *document, Inkscape::XML::Node *repr)
+{
+ readAttr( "inkscape:expanded" );
+ SPObject::build(document, repr);
+}
+
+/**
+ * Sets a specific value in the SPTag.
+ */
+void
+SPTag::set(unsigned int key, gchar const *value)
+{
+
+ switch (key)
+ {
+ case SP_ATTR_INKSCAPE_EXPANDED:
+ if ( value && !strcmp(value, "true") ) {
+ setExpanded(true);
+ }
+ break;
+ default:
+ SPObject::set(key, value);
+ break;
+ }
+}
+
+void SPTag::setExpanded(bool isexpanded) {
+ //if ( _expanded != isexpanded ){
+ _expanded = isexpanded;
+ //}
+}
+
+/**
+ * Receives update notifications.
+ */
+void
+SPTag::update(SPCtx *ctx, guint flags)
+{
+ if (flags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG |
+ SP_OBJECT_VIEWPORT_MODIFIED_FLAG)) {
+
+ /* do something to trigger redisplay, updates? */
+
+ }
+ SPObject::update(ctx, flags);
+}
+
+/**
+ * Writes its settings to an incoming repr object, if any.
+ */
+Inkscape::XML::Node *
+SPTag::write(Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags)
+{
+ if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) {
+ repr = doc->createElement("inkscape:tag");
+ }
+
+ // Inkscape-only object, not copied during an "plain SVG" dump:
+ if (flags & SP_OBJECT_WRITE_EXT) {
+ if (_expanded) {
+ repr->setAttribute("inkscape:expanded", "true");
+ } else {
+ repr->setAttribute("inkscape:expanded", NULL);
+ }
+ }
+ SPObject::write(doc, repr, flags);
+ return repr;
+}
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/sp-tag.h b/src/sp-tag.h
new file mode 100644
index 000000000..927bb45d1
--- /dev/null
+++ b/src/sp-tag.h
@@ -0,0 +1,57 @@
+#ifndef SP_TAG_H_SEEN
+#define SP_TAG_H_SEEN
+
+/** \file
+ * SVG <inkscape:tag> implementation
+ *
+ * Authors:
+ * Theodore Janeczko
+ *
+ * Copyright (C) Theodore Janeczko 2012 <flutterguy317@gmail.com>
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "sp-object.h"
+
+/* Skeleton base class */
+
+#define SP_TAG(o) (dynamic_cast<SPTag*>(o))
+#define SP_IS_TAG(o) (dynamic_cast<SPTag*>(o) != NULL)
+
+class SPTag;
+
+class SPTag : public SPObject {
+public:
+ SPTag() {}
+ virtual ~SPTag() {}
+
+ virtual void build(SPDocument * doc, Inkscape::XML::Node *repr);
+ //virtual void release();
+ virtual void set(unsigned key, const gchar* value);
+ virtual void update(SPCtx * ctx, unsigned flags);
+
+ virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, guint flags);
+
+ bool expanded() const { return _expanded; }
+ void setExpanded(bool isexpanded);
+
+ void moveTo(SPObject *target, gboolean intoafter);
+
+private:
+ bool _expanded;
+};
+
+
+#endif /* !SP_SKELETON_H_SEEN */
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/sp-text.cpp b/src/sp-text.cpp
index bbc7ec43d..93d81e47b 100644
--- a/src/sp-text.cpp
+++ b/src/sp-text.cpp
@@ -30,7 +30,6 @@
#include <2geom/affine.h>
#include <libnrtype/FontFactory.h>
#include <libnrtype/font-instance.h>
-#include <libnrtype/font-style-to-pos.h>
#include <glibmm/i18n.h>
#include "svg/svg.h"
@@ -70,8 +69,6 @@ namespace {
# SPTEXT
#####################################################*/
SPText::SPText() : SPItem() {
- //new (&this->layout) Inkscape::Text::Layout;
- //new (&this->attributes) TextTagAttributes;
}
SPText::~SPText() {
@@ -84,19 +81,22 @@ void SPText::build(SPDocument *doc, Inkscape::XML::Node *repr) {
this->readAttr( "dy" );
this->readAttr( "rotate" );
+ // SVG 2 Auto wrapped text
+ this->readAttr( "width" );
+ this->readAttr( "height" );
+
SPItem::build(doc, repr);
this->readAttr( "sodipodi:linespacing" ); // has to happen after the styles are read
}
void SPText::release() {
- //this->attributes.~TextTagAttributes();
- //this->layout.~Layout();
-
SPItem::release();
}
void SPText::set(unsigned int key, const gchar* value) {
+ //std::cout << "SPText::set: " << sp_attribute_name( key ) << ": " << (value?value:"Null") << std::endl;
+
if (this->attributes.readSingleAttribute(key, value)) {
this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
} else {
@@ -114,6 +114,22 @@ void SPText::set(unsigned int key, const gchar* value) {
this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_TEXT_LAYOUT_MODIFIED_FLAG);
break;
+ case SP_ATTR_WIDTH:
+ if (!this->width.read(value) || this->width.value < 0.0) {
+ this->width.unset();
+ }
+
+ this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+ break;
+
+ case SP_ATTR_HEIGHT:
+ if (!this->height.read(value) || this->height.value < 0.0) {
+ this->height.unset();
+ }
+
+ this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+ break;
+
default:
SPItem::set(key, value);
break;
@@ -278,6 +294,7 @@ Inkscape::XML::Node *SPText::write(Inkscape::XML::Document *xml_doc, Inkscape::X
}
this->attributes.writeTo(repr);
+ this->rebuildLayout(); // copied from update(), see LP Bug 1339305
// deprecated attribute, but keep it around for backwards compatibility
if (this->style->line_height.set && !this->style->line_height.inherit && !this->style->line_height.normal && this->style->line_height.unit == SP_CSS_UNIT_PERCENT) {
@@ -288,6 +305,14 @@ Inkscape::XML::Node *SPText::write(Inkscape::XML::Document *xml_doc, Inkscape::X
this->getRepr()->setAttribute("sodipodi:linespacing", NULL);
}
+ // SVG 2 Auto-wrapped text
+ if( this->width.computed > 0.0 ) {
+ sp_repr_set_svg_double(repr, "width", this->width.computed);
+ }
+ if( this->height.computed > 0.0 ) {
+ sp_repr_set_svg_double(repr, "height", this->height.computed);
+ }
+
SPItem::write(xml_doc, repr, flags);
return repr;
@@ -331,21 +356,10 @@ const char* SPText::displayName() const {
}
gchar* SPText::description() const {
- SPStyle *style = this->style;
- font_instance *tf = font_factory::Default()->FaceFromStyle(style);
-
- char *n;
+ SPStyle *style = this->style;
- if (tf) {
- char name_buf[256];
- tf->Family(name_buf, sizeof(name_buf));
- n = xml_quote_strdup(name_buf);
- tf->Unref();
- } else {
- /* TRANSLATORS: For description of font with no name. */
- n = g_strdup(_("&lt;no name found&gt;"));
- }
+ char *n = xml_quote_strdup( style->font_family.value );
Inkscape::Util::Quantity q = Inkscape::Util::Quantity(style->font_size.computed, "px");
GString *xs = g_string_new(q.string(sp_desktop_namedview(SP_ACTIVE_DESKTOP)->doc_units).c_str());
@@ -358,9 +372,8 @@ gchar* SPText::description() const {
}
char *ret = ( SP_IS_TEXT_TEXTPATH(this)
- ? g_strdup_printf(_("on path%s (%s, %s)"), trunc, n, xs->str)
- : g_strdup_printf(_("%s (%s, %s)"), trunc, n, xs->str) );
- g_free(n);
+ ? g_strdup_printf(_("on path%s (%s, %s)"), trunc, n, xs->str)
+ : g_strdup_printf(_("%s (%s, %s)"), trunc, n, xs->str) );
return ret;
}
diff --git a/src/sp-text.h b/src/sp-text.h
index 5f0485083..be48d7fcb 100644
--- a/src/sp-text.h
+++ b/src/sp-text.h
@@ -1,5 +1,5 @@
-#ifndef __SP_TEXT_H__
-#define __SP_TEXT_H__
+#ifndef SEEN_SP_TEXT_H
+#define SEEN_SP_TEXT_H
/*
* SVG <text> and <tspan> implementation
@@ -13,13 +13,13 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include <glib.h>
-#include <stddef.h>
+#include <cstddef>
#include <sigc++/sigc++.h>
-#include "sp-string.h" // Provides many other headers with SP_IS_STRING
+
+#include "libnrtype/Layout-TNG.h"
#include "sp-item.h"
+#include "sp-string.h" // Provides many other headers with SP_IS_STRING
#include "text-tag-attributes.h"
-#include "libnrtype/Layout-TNG.h"
#define SP_TEXT(obj) (dynamic_cast<SPText*>((SPObject*)obj))
#define SP_IS_TEXT(obj) (dynamic_cast<const SPText*>((SPObject*)obj) != NULL)
@@ -45,7 +45,11 @@ public:
//semiprivate: (need to be accessed by the C-style functions still)
TextTagAttributes attributes;
Inkscape::Text::Layout layout;
-
+
+ // SVG 2 Auto-wrapped text
+ SVGLength width;
+ SVGLength height;
+
/** when the object is transformed it's nicer to change the font size
and coordinates when we can, rather than just applying a matrix
transform. is_root is used to indicate to the function that it should
@@ -77,15 +81,15 @@ public:
virtual void release();
virtual void child_added(Inkscape::XML::Node* child, Inkscape::XML::Node* ref);
virtual void remove_child(Inkscape::XML::Node* child);
- virtual void set(unsigned int key, const gchar* value);
+ virtual void set(unsigned int key, const char* value);
virtual void update(SPCtx* ctx, unsigned int flags);
virtual void modified(unsigned int flags);
- virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, guint flags);
+ virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, unsigned int flags);
virtual Geom::OptRect bbox(Geom::Affine const &transform, SPItem::BBoxType type) const;
virtual void print(SPPrintContext *ctx);
virtual const char* displayName() const;
- virtual gchar* description() const;
+ virtual char* description() const;
virtual Inkscape::DrawingItem* show(Inkscape::Drawing &drawing, unsigned int key, unsigned int flags);
virtual void hide(unsigned int key);
virtual void snappoints(std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs) const;
diff --git a/src/sp-textpath.h b/src/sp-textpath.h
index 075743d8e..4457cb8cf 100644
--- a/src/sp-textpath.h
+++ b/src/sp-textpath.h
@@ -1,14 +1,13 @@
#ifndef INKSCAPE_SP_TEXTPATH_H
#define INKSCAPE_SP_TEXTPATH_H
-#include <glib.h>
#include "svg/svg-length.h"
#include "sp-item.h"
#include "sp-text.h"
+
class SPUsePath;
class Path;
-
#define SP_TEXTPATH(obj) (dynamic_cast<SPTextPath*>((SPObject*)obj))
#define SP_IS_TEXTPATH(obj) (dynamic_cast<const SPTextPath*>((SPObject*)obj) != NULL)
@@ -26,10 +25,10 @@ public:
virtual void build(SPDocument* doc, Inkscape::XML::Node* repr);
virtual void release();
- virtual void set(unsigned int key, const gchar* value);
+ virtual void set(unsigned int key, const char* value);
virtual void update(SPCtx* ctx, unsigned int flags);
virtual void modified(unsigned int flags);
- virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, guint flags);
+ virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, unsigned int flags);
};
#define SP_IS_TEXT_TEXTPATH(obj) (SP_IS_TEXT(obj) && obj->firstChild() && SP_IS_TEXTPATH(obj->firstChild()))
diff --git a/src/sp-title.h b/src/sp-title.h
index 14faf4b0a..04f3829c6 100644
--- a/src/sp-title.h
+++ b/src/sp-title.h
@@ -1,5 +1,5 @@
-#ifndef __SP_TITLE_H__
-#define __SP_TITLE_H__
+#ifndef SEEN_SP_TITLE_H
+#define SEEN_SP_TITLE_H
/*
* SVG <title> implementation
@@ -22,7 +22,7 @@ public:
SPTitle();
virtual ~SPTitle();
- virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags);
+ virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags);
};
#endif
diff --git a/src/sp-tref-reference.h b/src/sp-tref-reference.h
index 10cc25121..b555ace2d 100644
--- a/src/sp-tref-reference.h
+++ b/src/sp-tref-reference.h
@@ -12,15 +12,17 @@
* Released under GNU GPL, read the file 'COPYING' for more information.
*/
-#include "sp-item.h"
-#include <uri-references.h>
-#include <stddef.h>
+#include <cstddef>
#include <sigc++/sigc++.h>
+#include "sp-item.h"
+#include "uri-references.h"
+
#include "util/share.h"
#include "xml/node-observer.h"
#include "xml/subtree.h"
+typedef unsigned int GQuark;
class SPTRefReference : public Inkscape::URIReference,
public Inkscape::XML::NodeObserver {
diff --git a/src/sp-tref.cpp b/src/sp-tref.cpp
index edbb9faa7..0f6eb106f 100644
--- a/src/sp-tref.cpp
+++ b/src/sp-tref.cpp
@@ -64,12 +64,8 @@ static void sp_tref_delete_self(SPObject *deleted, SPTRef *self);
SPTRef::SPTRef() : SPItem() {
this->stringChild = NULL;
- //new (&this->attributes) TextTagAttributes;
-
this->href = NULL;
this->uriOriginalRef = new SPTRefReference(this);
- //new (&this->_delete_connection) sigc::connection();
- //new (&this->_changed_connection) sigc::connection();
this->_changed_connection =
this->uriOriginalRef->changedSignal().connect(sigc::bind(sigc::ptr_fun(sp_tref_href_changed), this));
@@ -77,9 +73,6 @@ SPTRef::SPTRef() : SPItem() {
SPTRef::~SPTRef() {
delete this->uriOriginalRef;
-
- //this->_delete_connection.~connection();
- //this->_changed_connection.~connection();
}
void SPTRef::build(SPDocument *document, Inkscape::XML::Node *repr) {
diff --git a/src/sp-tref.h b/src/sp-tref.h
index f5aed9ba6..1727620cd 100644
--- a/src/sp-tref.h
+++ b/src/sp-tref.h
@@ -34,7 +34,7 @@ public:
TextTagAttributes attributes;
// Text stored in the xlink:href attribute
- gchar *href;
+ char *href;
// URI reference to original object
SPTRefReference *uriOriginalRef;
@@ -53,14 +53,14 @@ public:
virtual void build(SPDocument* doc, Inkscape::XML::Node* repr);
virtual void release();
- virtual void set(unsigned int key, const gchar* value);
+ virtual void set(unsigned int key, char const* value);
virtual void update(SPCtx* ctx, unsigned int flags);
virtual void modified(unsigned int flags);
virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, guint flags);
virtual Geom::OptRect bbox(Geom::Affine const &transform, SPItem::BBoxType type) const;
virtual const char* displayName() const;
- virtual gchar* description() const;
+ virtual char* description() const;
};
void sp_tref_update_text(SPTRef *tref);
diff --git a/src/sp-tspan.cpp b/src/sp-tspan.cpp
index 8c4105777..c3f7689e7 100644
--- a/src/sp-tspan.cpp
+++ b/src/sp-tspan.cpp
@@ -63,7 +63,6 @@ namespace {
#####################################################*/
SPTSpan::SPTSpan() : SPItem() {
this->role = SP_TSPAN_ROLE_UNSPECIFIED;
- //new (&this->attributes) TextTagAttributes;
}
SPTSpan::~SPTSpan() {
@@ -81,8 +80,6 @@ void SPTSpan::build(SPDocument *doc, Inkscape::XML::Node *repr) {
}
void SPTSpan::release() {
- //this->attributes.~TextTagAttributes();
-
SPItem::release();
}
@@ -227,8 +224,6 @@ const char* SPTSpan::displayName() const {
void refresh_textpath_source(SPTextPath* offset);
SPTextPath::SPTextPath() : SPItem() {
- //new (&this->attributes) TextTagAttributes;
-
this->startOffset._set = false;
this->originalPath = NULL;
this->isUpdating=false;
diff --git a/src/sp-tspan.h b/src/sp-tspan.h
index 4c23b2eba..1aef4cd0c 100644
--- a/src/sp-tspan.h
+++ b/src/sp-tspan.h
@@ -5,7 +5,6 @@
* tspan and textpath, based on the flowtext routines
*/
-#include <glib.h>
#include "sp-item.h"
#include "text-tag-attributes.h"
@@ -23,15 +22,15 @@ public:
SPTSpan();
virtual ~SPTSpan();
- guint role : 2;
+ unsigned int role : 2;
TextTagAttributes attributes;
virtual void build(SPDocument* doc, Inkscape::XML::Node* repr);
virtual void release();
- virtual void set(unsigned int key, const gchar* value);
+ virtual void set(unsigned int key, const char* value);
virtual void update(SPCtx* ctx, unsigned int flags);
virtual void modified(unsigned int flags);
- virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, guint flags);
+ virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, unsigned int flags);
virtual Geom::OptRect bbox(Geom::Affine const &transform, SPItem::BBoxType type) const;
virtual const char* displayName() const;
diff --git a/src/sp-use-reference.h b/src/sp-use-reference.h
index d99b425f1..297bdc26c 100644
--- a/src/sp-use-reference.h
+++ b/src/sp-use-reference.h
@@ -9,11 +9,11 @@
* Released under GNU GPL, read the file 'COPYING' for more information.
*/
-#include "sp-item.h"
-#include <uri-references.h>
-#include <stddef.h>
#include <sigc++/sigc++.h>
+#include "sp-item.h"
+#include "uri-references.h"
+
class Path;
namespace Inkscape {
@@ -43,7 +43,7 @@ public:
bool sourceDirty;
SPObject *owner;
- gchar *sourceHref;
+ char *sourceHref;
Inkscape::XML::Node *sourceRepr;
SPObject *sourceObject;
diff --git a/src/sp-use.cpp b/src/sp-use.cpp
index e8fe3687f..2bd6757ff 100644
--- a/src/sp-use.cpp
+++ b/src/sp-use.cpp
@@ -37,6 +37,9 @@
#include "sp-symbol.h"
#include "sp-use.h"
#include "sp-use-reference.h"
+#include "sp-shape.h"
+#include "sp-text.h"
+#include "sp-flowtext.h"
namespace {
SPObject* createUse() {
@@ -47,10 +50,17 @@ namespace {
}
SPUse::SPUse()
- : SPItem()
- , child(NULL)
- , href(NULL)
- , ref(new SPUseReference(this))
+ : SPItem(),
+ child(NULL),
+ x(),
+ y(),
+ width(),
+ height(),
+ href(NULL),
+ ref(new SPUseReference(this)),
+ _delete_connection(),
+ _changed_connection(),
+ _transformed_connection()
{
this->x.unset();
this->y.unset();
@@ -176,6 +186,25 @@ Inkscape::XML::Node* SPUse::write(Inkscape::XML::Document *xml_doc, Inkscape::XM
g_free(uri_string);
}
+ SPShape *shape = dynamic_cast<SPShape *>(child);
+ if (shape) {
+ shape->set_shape(); // evaluate SPCurve of child
+ } else {
+ SPText *text = dynamic_cast<SPText *>(child);
+ if (text) {
+ text->rebuildLayout(); // refresh Layout, LP Bug 1339305
+ } else {
+ SPFlowtext *flowtext = dynamic_cast<SPFlowtext *>(child);
+ if (flowtext) {
+ SPFlowregion *flowregion = dynamic_cast<SPFlowregion *>(flowtext->firstChild());
+ if (flowregion) {
+ flowregion->UpdateComputed();
+ }
+ flowtext->rebuildLayout();
+ }
+ }
+ }
+
return repr;
}
@@ -210,18 +239,18 @@ void SPUse::print(SPPrintContext* ctx) {
}
const char* SPUse::displayName() const {
- if (this->child && SP_IS_SYMBOL( this->child )) {
+ if (dynamic_cast<SPSymbol *>(child)) {
return _("Symbol");
+ } else {
+ return _("Clone");
}
-
- return _("Clone");
}
gchar* SPUse::description() const {
- if (this->child) {
- if( SP_IS_SYMBOL( this->child ) ) {
- if (this->child->title()) {
- return g_strdup_printf(_("called %s"), Glib::Markup::escape_text(Glib::ustring( g_dpgettext2(NULL, "Symbol", this->child->title()))).c_str());
+ if (child) {
+ if ( dynamic_cast<SPSymbol *>(child) ) {
+ if (child->title()) {
+ return g_strdup_printf(_("called %s"), Glib::Markup::escape_text(Glib::ustring( g_dpgettext2(NULL, "Symbol", child->title()))).c_str());
} else {
return g_strdup_printf(_("called %s"), _("Unnamed Symbol"));
}
@@ -289,12 +318,10 @@ void SPUse::hide(unsigned int key) {
SPItem *SPUse::root() {
SPItem *orig = this->child;
- while (orig && SP_IS_USE(orig)) {
- orig = SP_USE(orig)->child;
- }
-
- if (!orig) {
- return NULL;
+ SPUse *use = dynamic_cast<SPUse *>(orig);
+ while (orig && use) {
+ orig = use->child;
+ use = dynamic_cast<SPUse *>(orig);
}
return orig;
@@ -312,13 +339,16 @@ int SPUse::cloneDepth() const {
unsigned depth = 1;
SPItem *orig = this->child;
- while (orig && SP_IS_USE(orig)) {
+ while (orig && dynamic_cast<SPUse *>(orig)) {
++depth;
- orig = SP_USE(orig)->child;
+ orig = dynamic_cast<SPUse *>(orig)->child;
}
- if (!orig) return -1;
- return depth;
+ if (!orig) {
+ return -1;
+ } else {
+ return depth;
+ }
}
/**
@@ -332,9 +362,9 @@ Geom::Affine SPUse::get_root_transform() {
GSList *chain = NULL;
chain = g_slist_prepend(chain, this);
- while (SP_IS_USE(orig)) {
+ while (dynamic_cast<SPUse *>(orig)) {
chain = g_slist_prepend(chain, orig);
- orig = SP_USE(orig)->child;
+ orig = dynamic_cast<SPUse *>(orig)->child;
}
chain = g_slist_prepend(chain, orig);
@@ -344,14 +374,13 @@ Geom::Affine SPUse::get_root_transform() {
Geom::Affine t(Geom::identity());
for (GSList *i = chain; i != NULL; i = i->next) {
- SPItem *i_tem = SP_ITEM(i->data);
+ SPItem *i_tem = reinterpret_cast<SPItem *>(i->data);
// "An additional transformation translate(x,y) is appended to the end (i.e.,
// right-side) of the transform attribute on the generated 'g', where x and y
// represent the values of the x and y attributes on the 'use' element." - http://www.w3.org/TR/SVG11/struct.html#UseElement
- if (SP_IS_USE(i_tem)) {
- SPUse *i_use = SP_USE(i_tem);
-
+ SPUse *i_use = dynamic_cast<SPUse *>(i_tem);
+ if (i_use) {
if ((i_use->x._set && i_use->x.computed != 0) || (i_use->y._set && i_use->y.computed != 0)) {
t = t * Geom::Translate(i_use->x._set ? i_use->x.computed : 0, i_use->y._set ? i_use->y.computed : 0);
}
@@ -392,7 +421,7 @@ void SPUse::move_compensate(Geom::Affine const *mp) {
}
// never compensate uses which are used in flowtext
- if (this->parent && SP_IS_FLOWREGION(this->parent)) {
+ if (parent && dynamic_cast<SPFlowregion *>(parent)) {
return;
}
@@ -449,8 +478,9 @@ void SPUse::href_changed() {
SPObject* obj = SPFactory::instance().createObject(NodeTraits::get_type_string(*childrepr));
- if (SP_IS_ITEM(obj)) {
- this->child = SP_ITEM(obj);
+ SPItem *item = dynamic_cast<SPItem *>(obj);
+ if (item) {
+ child = item;
this->attach(this->child, this->lastChild());
sp_object_unref(this->child, this);
@@ -482,8 +512,8 @@ void SPUse::href_changed() {
void SPUse::delete_self() {
// always delete uses which are used in flowtext
- if (this->parent && SP_IS_FLOWREGION(this->parent)) {
- this->deleteObject();
+ if (parent && dynamic_cast<SPFlowregion *>(parent)) {
+ deleteObject();
return;
}
@@ -534,9 +564,10 @@ void SPUse::update(SPCtx *ctx, unsigned flags) {
sp_object_ref(this->child);
if (childflags || (this->child->uflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) {
- SPItem const &chi = *SP_ITEM(this->child);
- cctx.i2doc = chi.transform * ictx->i2doc;
- cctx.i2vp = chi.transform * ictx->i2vp;
+ SPItem const *chi = dynamic_cast<SPItem const *>(child);
+ g_assert(chi != NULL);
+ cctx.i2doc = chi->transform * ictx->i2doc;
+ cctx.i2vp = chi->transform * ictx->i2vp;
this->child->updateDisplay((SPCtx *)&cctx, childflags);
}
@@ -608,7 +639,7 @@ SPItem *SPUse::unlink() {
Inkscape::XML::Node *copy = NULL;
- if (SP_IS_SYMBOL(orig)) { // make a group, copy children
+ if (dynamic_cast<SPSymbol *>(orig)) { // make a group, copy children
copy = xml_doc->createElement("svg:g");
for (Inkscape::XML::Node *child = orig->getRepr()->firstChild() ; child != NULL; child = child->next()) {
@@ -656,7 +687,8 @@ SPItem *SPUse::unlink() {
this->setSuccessor(unlinked);
sp_object_unref(this, NULL);
- SPItem *item = SP_ITEM(unlinked);
+ SPItem *item = dynamic_cast<SPItem *>(unlinked);
+ g_assert(item != NULL);
// Set the accummulated transform.
{
diff --git a/src/sp-use.h b/src/sp-use.h
index 215eb44d7..81e4391aa 100644
--- a/src/sp-use.h
+++ b/src/sp-use.h
@@ -1,27 +1,27 @@
-#ifndef __SP_USE_H__
-#define __SP_USE_H__
+#ifndef SEEN_SP_USE_H
+#define SEEN_SP_USE_H
/*
* SVG <use> implementation
*
* Authors:
* Lauris Kaplinski <lauris@kaplinski.com>
+ * Jon A. Cruz <jon@joncruz.org>
*
+ * Copyright (C) 1999-2014 Authors
* Copyright (C) 1999-2002 Lauris Kaplinski
* Copyright (C) 2000-2001 Ximian, Inc.
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include <stddef.h>
+#include <cstddef>
#include <sigc++/sigc++.h>
+
#include "svg/svg-length.h"
#include "sp-item.h"
#include "enums.h"
-#define SP_USE(obj) (dynamic_cast<SPUse*>((SPObject*)obj))
-#define SP_IS_USE(obj) (dynamic_cast<const SPUse*>((SPObject*)obj) != NULL)
-
class SPUseReference;
class SPUse : public SPItem {
@@ -38,7 +38,7 @@ public:
SVGLength y;
SVGLength width;
SVGLength height;
- gchar *href;
+ char *href;
// the reference to the original object
SPUseReference *ref;
@@ -52,14 +52,14 @@ public:
virtual void build(SPDocument* doc, Inkscape::XML::Node* repr);
virtual void release();
- virtual void set(unsigned key, gchar const *value);
- virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags);
+ virtual void set(unsigned key, char const *value);
+ virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags);
virtual void update(SPCtx* ctx, unsigned int flags);
virtual void modified(unsigned int flags);
virtual Geom::OptRect bbox(Geom::Affine const &transform, SPItem::BBoxType bboxtype) const;
virtual const char* displayName() const;
- virtual gchar* description() const;
+ virtual char* description() const;
virtual void print(SPPrintContext *ctx);
virtual Inkscape::DrawingItem* show(Inkscape::Drawing &drawing, unsigned int key, unsigned int flags);
virtual void hide(unsigned int key);
diff --git a/src/splivarot.cpp b/src/splivarot.cpp
index 6aec42c5b..1a75a6f29 100644
--- a/src/splivarot.cpp
+++ b/src/splivarot.cpp
@@ -25,7 +25,7 @@
#include "sp-path.h"
#include "sp-shape.h"
#include "sp-image.h"
-#include "marker.h"
+#include "sp-marker.h"
#include "enums.h"
#include "sp-text.h"
#include "sp-flowtext.h"
@@ -960,16 +960,17 @@ Geom::PathVector* item_outline(SPItem const *item, bool bbox_only)
Geom::Affine const transform(item->transform);
float const scale = transform.descrim();
- float o_width, o_miter;
+ float o_width = i_style->stroke_width.computed;
+ if (o_width < Geom::EPSILON) {
+ // This may result in rounding errors for very small stroke widths (happens e.g. when user unit is large).
+ // See bug lp:1244861
+ o_width = Geom::EPSILON;
+ }
+ float o_miter = i_style->stroke_miterlimit.value * o_width;
+
JoinType o_join;
ButtType o_butt;
{
- o_width = i_style->stroke_width.computed;
- if (o_width < 0.01) {
- o_width = 0.01;
- }
- o_miter = i_style->stroke_miterlimit.value * o_width;
-
switch (i_style->stroke_linejoin.computed) {
case SP_STROKE_LINEJOIN_MITER:
o_join = join_pointy;
@@ -1456,13 +1457,21 @@ sp_selected_path_outline(SPDesktop *desktop)
g_repr, xml_doc, doc );
}
}
+ //bug lp:1290573 : completely destroy the old object first
+ curve->unref();
+ selection->remove(item);
+ item->deleteObject(false);
selection->add(g_repr);
Inkscape::GC::release(g_repr);
-
- } else {
+ } else
+ {
+ //lp:1290573
+ curve->unref();
+ selection->remove(item);
+ item->deleteObject(false);
// add the new repr to the parent
parent->appendChild(repr);
@@ -1488,10 +1497,6 @@ sp_selected_path_outline(SPDesktop *desktop)
Inkscape::GC::release(repr);
- curve->unref();
- selection->remove(item);
- item->deleteObject(false);
-
}
if (title) {
g_free(title);
diff --git a/src/splivarot.h b/src/splivarot.h
index 329fc65d2..ba314399f 100644
--- a/src/splivarot.h
+++ b/src/splivarot.h
@@ -1,5 +1,5 @@
-#ifndef __SP_LIVAROT_H__
-#define __SP_LIVAROT_H__
+#ifndef SEEN_SP_LIVAROT_H
+#define SEEN_SP_LIVAROT_H
/*
* boolops and outlines
@@ -7,9 +7,10 @@
* public domain
*/
-#include "livarot/Path.h"
#include <2geom/forward.h>
#include <2geom/path.h>
+#include "livarot/Path.h"
+
class SPCurve;
class SPDesktop;
class SPItem;
diff --git a/src/streq.h b/src/streq.h
index a3524a941..7edc5cfe9 100644
--- a/src/streq.h
+++ b/src/streq.h
@@ -2,7 +2,6 @@
#define INKSCAPE_STREQ_H
#include <cstring>
-#include <string>
/** Convenience/readability wrapper for strcmp(a,b)==0. */
inline bool
diff --git a/src/style-enums.h b/src/style-enums.h
index c6f9a1ea1..f52752018 100644
--- a/src/style-enums.h
+++ b/src/style-enums.h
@@ -15,7 +15,9 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-/* SPTextStyle */
+/* SPFontStyle */
+
+#include "display/canvas-bpath.h" // FIXME those enums belong here!
enum SPCSSFontSize {
SP_CSS_FONT_SIZE_XX_SMALL,
@@ -111,6 +113,14 @@ enum SPTextAnchor {
SP_CSS_TEXT_ANCHOR_END
};
+enum SPWhiteSpace {
+ SP_CSS_WHITE_SPACE_NORMAL,
+ SP_CSS_WHITE_SPACE_PRE,
+ SP_CSS_WHITE_SPACE_NOWRAP,
+ SP_CSS_WHITE_SPACE_PREWRAP,
+ SP_CSS_WHITE_SPACE_PRELINE
+};
+
enum SPCSSBaselineShift {
SP_CSS_BASELINE_SHIFT_BASELINE,
SP_CSS_BASELINE_SHIFT_SUB,
@@ -215,6 +225,276 @@ enum SPTextRendering {
SP_CSS_TEXT_RENDERING_GEOMETRICPRECISION
};
+
+struct SPStyleEnum {
+ char const *key;
+ int value;
+};
+
+static SPStyleEnum const enum_fill_rule[] = {
+ {"nonzero", SP_WIND_RULE_NONZERO},
+ {"evenodd", SP_WIND_RULE_EVENODD},
+ {NULL, -1}
+};
+
+static SPStyleEnum const enum_stroke_linecap[] = {
+ {"butt", SP_STROKE_LINECAP_BUTT},
+ {"round", SP_STROKE_LINECAP_ROUND},
+ {"square", SP_STROKE_LINECAP_SQUARE},
+ {NULL, -1}
+};
+
+static SPStyleEnum const enum_stroke_linejoin[] = {
+ {"miter", SP_STROKE_LINEJOIN_MITER},
+ {"round", SP_STROKE_LINEJOIN_ROUND},
+ {"bevel", SP_STROKE_LINEJOIN_BEVEL},
+ {NULL, -1}
+};
+
+static SPStyleEnum const enum_font_style[] = {
+ {"normal", SP_CSS_FONT_STYLE_NORMAL},
+ {"italic", SP_CSS_FONT_STYLE_ITALIC},
+ {"oblique", SP_CSS_FONT_STYLE_OBLIQUE},
+ {NULL, -1}
+};
+
+static SPStyleEnum const enum_font_size[] = {
+ {"xx-small", SP_CSS_FONT_SIZE_XX_SMALL},
+ {"x-small", SP_CSS_FONT_SIZE_X_SMALL},
+ {"small", SP_CSS_FONT_SIZE_SMALL},
+ {"medium", SP_CSS_FONT_SIZE_MEDIUM},
+ {"large", SP_CSS_FONT_SIZE_LARGE},
+ {"x-large", SP_CSS_FONT_SIZE_X_LARGE},
+ {"xx-large", SP_CSS_FONT_SIZE_XX_LARGE},
+ {"smaller", SP_CSS_FONT_SIZE_SMALLER},
+ {"larger", SP_CSS_FONT_SIZE_LARGER},
+ {NULL, -1}
+};
+
+static SPStyleEnum const enum_font_variant[] = {
+ {"normal", SP_CSS_FONT_VARIANT_NORMAL},
+ {"small-caps", SP_CSS_FONT_VARIANT_SMALL_CAPS},
+ {NULL, -1}
+};
+
+static SPStyleEnum const enum_font_weight[] = {
+ {"100", SP_CSS_FONT_WEIGHT_100},
+ {"200", SP_CSS_FONT_WEIGHT_200},
+ {"300", SP_CSS_FONT_WEIGHT_300},
+ {"400", SP_CSS_FONT_WEIGHT_400},
+ {"500", SP_CSS_FONT_WEIGHT_500},
+ {"600", SP_CSS_FONT_WEIGHT_600},
+ {"700", SP_CSS_FONT_WEIGHT_700},
+ {"800", SP_CSS_FONT_WEIGHT_800},
+ {"900", SP_CSS_FONT_WEIGHT_900},
+ {"normal", SP_CSS_FONT_WEIGHT_NORMAL},
+ {"bold", SP_CSS_FONT_WEIGHT_BOLD},
+ {"lighter", SP_CSS_FONT_WEIGHT_LIGHTER},
+ {"bolder", SP_CSS_FONT_WEIGHT_BOLDER},
+ {NULL, -1}
+};
+
+static SPStyleEnum const enum_font_stretch[] = {
+ {"ultra-condensed", SP_CSS_FONT_STRETCH_ULTRA_CONDENSED},
+ {"extra-condensed", SP_CSS_FONT_STRETCH_EXTRA_CONDENSED},
+ {"condensed", SP_CSS_FONT_STRETCH_CONDENSED},
+ {"semi-condensed", SP_CSS_FONT_STRETCH_SEMI_CONDENSED},
+ {"normal", SP_CSS_FONT_STRETCH_NORMAL},
+ {"semi-expanded", SP_CSS_FONT_STRETCH_SEMI_EXPANDED},
+ {"expanded", SP_CSS_FONT_STRETCH_EXPANDED},
+ {"extra-expanded", SP_CSS_FONT_STRETCH_EXTRA_EXPANDED},
+ {"ultra-expanded", SP_CSS_FONT_STRETCH_ULTRA_EXPANDED},
+ {"narrower", SP_CSS_FONT_STRETCH_NARROWER},
+ {"wider", SP_CSS_FONT_STRETCH_WIDER},
+ {NULL, -1}
+};
+
+static SPStyleEnum const enum_text_align[] = {
+ {"start", SP_CSS_TEXT_ALIGN_START},
+ {"end", SP_CSS_TEXT_ALIGN_END},
+ {"left", SP_CSS_TEXT_ALIGN_LEFT},
+ {"right", SP_CSS_TEXT_ALIGN_RIGHT},
+ {"center", SP_CSS_TEXT_ALIGN_CENTER},
+ {"justify", SP_CSS_TEXT_ALIGN_JUSTIFY},
+ {NULL, -1}
+};
+
+static SPStyleEnum const enum_text_transform[] = {
+ {"capitalize", SP_CSS_TEXT_TRANSFORM_CAPITALIZE},
+ {"uppercase", SP_CSS_TEXT_TRANSFORM_UPPERCASE},
+ {"lowercase", SP_CSS_TEXT_TRANSFORM_LOWERCASE},
+ {"none", SP_CSS_TEXT_TRANSFORM_NONE},
+ {NULL, -1}
+};
+
+static SPStyleEnum const enum_text_anchor[] = {
+ {"start", SP_CSS_TEXT_ANCHOR_START},
+ {"middle", SP_CSS_TEXT_ANCHOR_MIDDLE},
+ {"end", SP_CSS_TEXT_ANCHOR_END},
+ {NULL, -1}
+};
+
+static SPStyleEnum const enum_white_space[] = {
+ {"normal", SP_CSS_WHITE_SPACE_NORMAL },
+ {"pre", SP_CSS_WHITE_SPACE_PRE },
+ {"nowrap", SP_CSS_WHITE_SPACE_NOWRAP },
+ {"pre-wrap", SP_CSS_WHITE_SPACE_PREWRAP},
+ {"pre-line", SP_CSS_WHITE_SPACE_PRELINE},
+ {NULL, -1}
+};
+
+static SPStyleEnum const enum_direction[] = {
+ {"ltr", SP_CSS_DIRECTION_LTR},
+ {"rtl", SP_CSS_DIRECTION_RTL},
+ {NULL, -1}
+};
+
+static SPStyleEnum const enum_block_progression[] = {
+ {"tb", SP_CSS_BLOCK_PROGRESSION_TB},
+ {"rl", SP_CSS_BLOCK_PROGRESSION_RL},
+ {"lr", SP_CSS_BLOCK_PROGRESSION_LR},
+ {NULL, -1}
+};
+
+static SPStyleEnum const enum_writing_mode[] = {
+ /* Note that using the same enumerator for lr as lr-tb means we write as lr-tb even if the
+ * input file said lr. We prefer writing lr-tb on the grounds that the spec says the initial
+ * value is lr-tb rather than lr.
+ *
+ * ECMA scripts may be surprised to find tb-rl in DOM if they set the attribute to rl, so
+ * sharing enumerators for different strings may be a bug (once we support ecma script).
+ */
+ {"lr-tb", SP_CSS_WRITING_MODE_LR_TB},
+ {"rl-tb", SP_CSS_WRITING_MODE_RL_TB},
+ {"tb-rl", SP_CSS_WRITING_MODE_TB_RL},
+ {"lr", SP_CSS_WRITING_MODE_LR_TB},
+ {"rl", SP_CSS_WRITING_MODE_RL_TB},
+ {"tb", SP_CSS_WRITING_MODE_TB_RL},
+ {NULL, -1}
+};
+
+static SPStyleEnum const enum_baseline_shift[] = {
+ {"baseline", SP_CSS_BASELINE_SHIFT_BASELINE},
+ {"sub", SP_CSS_BASELINE_SHIFT_SUB},
+ {"super", SP_CSS_BASELINE_SHIFT_SUPER},
+ {NULL, -1}
+};
+
+static SPStyleEnum const enum_visibility[] = {
+ {"hidden", SP_CSS_VISIBILITY_HIDDEN},
+ {"collapse", SP_CSS_VISIBILITY_COLLAPSE},
+ {"visible", SP_CSS_VISIBILITY_VISIBLE},
+ {NULL, -1}
+};
+
+static SPStyleEnum const enum_overflow[] = {
+ {"visible", SP_CSS_OVERFLOW_VISIBLE},
+ {"hidden", SP_CSS_OVERFLOW_HIDDEN},
+ {"scroll", SP_CSS_OVERFLOW_SCROLL},
+ {"auto", SP_CSS_OVERFLOW_AUTO},
+ {NULL, -1}
+};
+
+// CSS Compositing and Blending Level 1
+static SPStyleEnum const enum_isolation[] = {
+ {"auto", SP_CSS_ISOLATION_AUTO},
+ {"isolate", SP_CSS_ISOLATION_ISOLATE},
+ {NULL, -1}
+};
+
+static SPStyleEnum const enum_blend_mode[] = {
+ {"normal", SP_CSS_BLEND_NORMAL},
+ {"multiply", SP_CSS_BLEND_MULTIPLY},
+ {"screen", SP_CSS_BLEND_SCREEN},
+ {"darken", SP_CSS_BLEND_DARKEN},
+ {"lighten", SP_CSS_BLEND_LIGHTEN},
+ {"overlay", SP_CSS_BLEND_OVERLAY},
+ {"color-dodge", SP_CSS_BLEND_COLORDODGE},
+ {"color-burn", SP_CSS_BLEND_COLORBURN},
+ {"hard-light", SP_CSS_BLEND_HARDLIGHT},
+ {"soft-light", SP_CSS_BLEND_SOFTLIGHT},
+ {"difference", SP_CSS_BLEND_DIFFERENCE},
+ {"exclusion", SP_CSS_BLEND_EXCLUSION},
+ {"hue", SP_CSS_BLEND_HUE},
+ {"saturation", SP_CSS_BLEND_SATURATION},
+ {"color", SP_CSS_BLEND_COLOR},
+ {"luminosity", SP_CSS_BLEND_LUMINOSITY},
+ {NULL, -1}
+};
+
+static SPStyleEnum const enum_display[] = {
+ {"none", SP_CSS_DISPLAY_NONE},
+ {"inline", SP_CSS_DISPLAY_INLINE},
+ {"block", SP_CSS_DISPLAY_BLOCK},
+ {"list-item", SP_CSS_DISPLAY_LIST_ITEM},
+ {"run-in", SP_CSS_DISPLAY_RUN_IN},
+ {"compact", SP_CSS_DISPLAY_COMPACT},
+ {"marker", SP_CSS_DISPLAY_MARKER},
+ {"table", SP_CSS_DISPLAY_TABLE},
+ {"inline-table", SP_CSS_DISPLAY_INLINE_TABLE},
+ {"table-row-group", SP_CSS_DISPLAY_TABLE_ROW_GROUP},
+ {"table-header-group", SP_CSS_DISPLAY_TABLE_HEADER_GROUP},
+ {"table-footer-group", SP_CSS_DISPLAY_TABLE_FOOTER_GROUP},
+ {"table-row", SP_CSS_DISPLAY_TABLE_ROW},
+ {"table-column-group", SP_CSS_DISPLAY_TABLE_COLUMN_GROUP},
+ {"table-column", SP_CSS_DISPLAY_TABLE_COLUMN},
+ {"table-cell", SP_CSS_DISPLAY_TABLE_CELL},
+ {"table-caption", SP_CSS_DISPLAY_TABLE_CAPTION},
+ {NULL, -1}
+};
+
+static SPStyleEnum const enum_shape_rendering[] = {
+ {"auto", SP_CSS_SHAPE_RENDERING_AUTO},
+ {"optimizeSpeed", SP_CSS_SHAPE_RENDERING_OPTIMIZESPEED},
+ {"crispEdges", SP_CSS_SHAPE_RENDERING_CRISPEDGES},
+ {"geometricPrecision", SP_CSS_SHAPE_RENDERING_GEOMETRICPRECISION},
+ {NULL, -1}
+};
+
+static SPStyleEnum const enum_color_rendering[] = {
+ {"auto", SP_CSS_COLOR_RENDERING_AUTO},
+ {"optimizeSpeed", SP_CSS_COLOR_RENDERING_OPTIMIZESPEED},
+ {"optimizeQuality", SP_CSS_COLOR_RENDERING_OPTIMIZEQUALITY},
+ {NULL, -1}
+};
+
+static SPStyleEnum const enum_image_rendering[] = {
+ {"auto", SP_CSS_IMAGE_RENDERING_AUTO},
+ {"optimizeSpeed", SP_CSS_IMAGE_RENDERING_OPTIMIZESPEED},
+ {"optimizeQuality", SP_CSS_IMAGE_RENDERING_OPTIMIZEQUALITY},
+ {"-inkscape-crisp-edges", SP_CSS_IMAGE_RENDERING_CRISPEDGES},
+ {"-inkscape-pixelated", SP_CSS_IMAGE_RENDERING_PIXELATED},
+ {NULL, -1}
+};
+
+static SPStyleEnum const enum_text_rendering[] = {
+ {"auto", SP_CSS_TEXT_RENDERING_AUTO},
+ {"optimizeSpeed", SP_CSS_TEXT_RENDERING_OPTIMIZESPEED},
+ {"optimizeLegibility", SP_CSS_TEXT_RENDERING_OPTIMIZELEGIBILITY},
+ {"geometricPrecision", SP_CSS_TEXT_RENDERING_GEOMETRICPRECISION},
+ {NULL, -1}
+};
+
+static SPStyleEnum const enum_enable_background[] = {
+ {"accumulate", SP_CSS_BACKGROUND_ACCUMULATE},
+ {"new", SP_CSS_BACKGROUND_NEW},
+ {NULL, -1}
+};
+
+static SPStyleEnum const enum_clip_rule[] = {
+ {"nonzero", SP_WIND_RULE_NONZERO},
+ {"evenodd", SP_WIND_RULE_EVENODD},
+ {NULL, -1}
+};
+
+static SPStyleEnum const enum_color_interpolation[] = {
+ {"auto", SP_CSS_COLOR_INTERPOLATION_AUTO},
+ {"sRGB", SP_CSS_COLOR_INTERPOLATION_SRGB},
+ {"linearRGB", SP_CSS_COLOR_INTERPOLATION_LINEARRGB},
+ {NULL, -1}
+};
+
+
#endif // SEEN_SP_STYLE_ENUMS_H
diff --git a/src/style-internal.cpp b/src/style-internal.cpp
new file mode 100644
index 000000000..b858e5cb6
--- /dev/null
+++ b/src/style-internal.cpp
@@ -0,0 +1,2648 @@
+/**
+ * @file
+ * SVG stylesheets implementation - Classes used by SPStyle class.
+ */
+
+/* Authors:
+ * C++ conversion:
+ * Tavmjong Bah <tavmjong@free.fr>
+ * Legacy C implementation:
+ * Lauris Kaplinski <lauris@kaplinski.com>
+ * Peter Moulder <pmoulder@mail.csse.monash.edu.au>
+ * bulia byak <buliabyak@users.sf.net>
+ * Abhishek Sharma
+ * Kris De Gussem <Kris.DeGussem@gmail.com>
+ *
+ * Copyright (C) 2001-2002 Lauris Kaplinski
+ * Copyright (C) 2001 Ximian, Inc.
+ * Copyright (C) 2005 Monash University
+ * Copyright (C) 2012 Kris De Gussem
+ * Copyright (C) 2014 Tavmjong Bah
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "style-internal.h"
+#include "style-enums.h"
+#include "style.h"
+
+#include "svg/svg.h"
+#include "svg/svg-color.h"
+#include "svg/svg-icc-color.h"
+
+#include "streq.h"
+#include "strneq.h"
+
+#include "extract-uri.h"
+#include "preferences.h"
+#include "svg/css-ostringstream.h"
+#include "util/units.h"
+
+#include <sigc++/functors/ptr_fun.h>
+#include <sigc++/adaptors/bind.h>
+
+// TODO REMOVE OR MAKE MEMBER FUNCTIONS
+void sp_style_fill_paint_server_ref_changed( SPObject *old_ref, SPObject *ref, SPStyle *style);
+void sp_style_stroke_paint_server_ref_changed(SPObject *old_ref, SPObject *ref, SPStyle *style);
+void sp_style_filter_ref_changed( SPObject *old_ref, SPObject *ref, SPStyle *style);
+void sp_style_set_ipaint_to_uri(SPStyle *style, SPIPaint *paint, const Inkscape::URI *uri, SPDocument *document);
+void sp_style_set_ipaint_to_uri_string (SPStyle *style, SPIPaint *paint, const gchar *uri);
+
+using Inkscape::CSSOStringStream;
+
+// SPIBase --------------------------------------------------------------
+
+
+// SPIFloat -------------------------------------------------------------
+
+void
+SPIFloat::read( gchar const *str ) {
+
+ if( !str ) return;
+
+ if ( !strcmp(str, "inherit") ) {
+ set = true;
+ inherit = true;
+ } else {
+ gfloat value_tmp;
+ if (sp_svg_number_read_f(str, &value_tmp)) {
+ set = true;
+ inherit = false;
+ value = value_tmp;
+ }
+ }
+}
+
+const Glib::ustring
+SPIFloat::write( guint const flags, SPIBase const *const base) const {
+
+ SPIFloat const *const my_base = dynamic_cast<const SPIFloat*>(base);
+ if ( (flags & SP_STYLE_FLAG_ALWAYS) ||
+ ((flags & SP_STYLE_FLAG_IFSET) && this->set) ||
+ ((flags & SP_STYLE_FLAG_IFDIFF) && this->set
+ && (!my_base->set || this != my_base )))
+ {
+ if (this->inherit) {
+ return (name + ":inherit;");
+ } else {
+ Inkscape::CSSOStringStream os;
+ os << name << ":" << this->value << ";";
+ return os.str();
+ }
+ }
+ return Glib::ustring("");
+}
+
+void
+SPIFloat::cascade( const SPIBase* const parent ) {
+ if( const SPIFloat* p = dynamic_cast<const SPIFloat*>(parent) ) {
+ if( (inherits && !set) || inherit ) value = p->value;
+ } else {
+ std::cerr << "SPIFloat::cascade(): Incorrect parent type" << std::endl;
+ }
+}
+
+void
+SPIFloat::merge( const SPIBase* const parent ) {
+ if( const SPIFloat* p = dynamic_cast<const SPIFloat*>(parent) ) {
+ if( inherits ) {
+ if( (!set || inherit) && p->set && !(p->inherit) ) {
+ set = p->set;
+ inherit = p->inherit;
+ value = p->value;
+ }
+ }
+ } else {
+ std::cerr << "SPIFloat::merge(): Incorrect parent type" << std::endl;
+ }
+}
+
+bool
+SPIFloat::operator==(const SPIBase& rhs) {
+ if( const SPIFloat* r = dynamic_cast<const SPIFloat*>(&rhs) ) {
+ return (value == r->value && SPIBase::operator==(rhs));
+ } else {
+ return false;
+ }
+}
+
+
+
+// SPIScale24 -----------------------------------------------------------
+
+void
+SPIScale24::read( gchar const *str ) {
+
+ if( !str ) return;
+
+ if ( !strcmp(str, "inherit") ) {
+ set = true;
+ inherit = true;
+ } else {
+ gfloat value_in;
+ if (sp_svg_number_read_f(str, &value_in)) {
+ set = true;
+ inherit = false;
+ value_in = CLAMP(value_in, 0.0, 1.0);
+ value = SP_SCALE24_FROM_FLOAT( value_in );
+ }
+ }
+}
+
+const Glib::ustring
+SPIScale24::write( guint const flags, SPIBase const *const base) const {
+
+ SPIScale24 const *const my_base = dynamic_cast<const SPIScale24*>(base);
+ if ( (flags & SP_STYLE_FLAG_ALWAYS) ||
+ ((flags & SP_STYLE_FLAG_IFSET) && this->set) ||
+ ((flags & SP_STYLE_FLAG_IFDIFF) && this->set
+ && (!my_base->set || this != my_base )))
+ {
+ if (this->inherit) {
+ return (name + ":inherit;");
+ } else {
+ Inkscape::CSSOStringStream os;
+ os << name << ":" << SP_SCALE24_TO_FLOAT(this->value) << ";";
+ return os.str();
+ }
+ }
+ return Glib::ustring("");
+}
+
+void
+SPIScale24::cascade( const SPIBase* const parent ) {
+ if( const SPIScale24* p = dynamic_cast<const SPIScale24*>(parent) ) {
+ if( (inherits && !set) || inherit ) value = p->value;
+ } else {
+ std::cerr << "SPIScale24::cascade(): Incorrect parent type" << std::endl;
+ }
+}
+
+void
+SPIScale24::merge( const SPIBase* const parent ) {
+ if( const SPIScale24* p = dynamic_cast<const SPIScale24*>(parent) ) {
+ if( inherits ) {
+ if( (!set || inherit) && p->set && !(p->inherit) ) {
+ set = p->set;
+ inherit = p->inherit;
+ value = p->value;
+ }
+ } else {
+ // Needed only for 'opacity' which does not inherit. See comment at bottom of file.
+ if( name.compare( "opacity" ) != 0 )
+ std::cerr << "SPIScale24::merge: unhandled property: " << name << std::endl;
+ if( !set || (!inherit && value == SP_SCALE24_MAX) ) {
+ value = p->value;
+ } else {
+ if( inherit ) value = p->value; // Insures child is up-to-date
+ value = SP_SCALE24_MUL( value, p->value );
+ inherit = (inherit && p->inherit && (p->value == 0 || p->value == SP_SCALE24_MAX) );
+ set = (inherit || value < SP_SCALE24_MAX);
+ }
+ }
+ } else {
+ std::cerr << "SPIScale24::merge(): Incorrect parent type" << std::endl;
+ }
+}
+
+bool
+SPIScale24::operator==(const SPIBase& rhs) {
+ if( const SPIScale24* r = dynamic_cast<const SPIScale24*>(&rhs) ) {
+ return (value == r->value && SPIBase::operator==(rhs));
+ } else {
+ return false;
+ }
+}
+
+
+
+// SPILength ------------------------------------------------------------
+
+void
+SPILength::read( gchar const *str ) {
+
+ if( !str ) return;
+
+ if (!strcmp(str, "inherit")) {
+ set = true;
+ inherit = true;
+ unit = SP_CSS_UNIT_NONE;
+ value = computed = 0.0;
+ } else {
+ gdouble value_tmp;
+ gchar *e;
+ /** \todo fixme: Move this to standard place (Lauris) */
+ value_tmp = g_ascii_strtod(str, &e);
+ if ( !IS_FINITE(value_tmp) ) { // fix for bug lp:935157
+ return;
+ }
+ if ((gchar const *) e != str) {
+
+ value = value_tmp;
+ if (!*e) {
+ /* Userspace */
+ unit = SP_CSS_UNIT_NONE;
+ computed = value;
+ } else if (!strcmp(e, "px")) {
+ /* Userspace */
+ unit = SP_CSS_UNIT_PX;
+ computed = value;
+ } else if (!strcmp(e, "pt")) {
+ /* Userspace / DEVICESCALE */
+ unit = SP_CSS_UNIT_PT;
+ computed = Inkscape::Util::Quantity::convert(value, "pt", "px");
+ } else if (!strcmp(e, "pc")) {
+ unit = SP_CSS_UNIT_PC;
+ computed = Inkscape::Util::Quantity::convert(value, "pc", "px");
+ } else if (!strcmp(e, "mm")) {
+ unit = SP_CSS_UNIT_MM;
+ computed = Inkscape::Util::Quantity::convert(value, "mm", "px");
+ } else if (!strcmp(e, "cm")) {
+ unit = SP_CSS_UNIT_CM;
+ computed = Inkscape::Util::Quantity::convert(value, "cm", "px");
+ } else if (!strcmp(e, "in")) {
+ unit = SP_CSS_UNIT_IN;
+ computed = Inkscape::Util::Quantity::convert(value, "in", "px");
+ } else if (!strcmp(e, "em")) {
+ /* EM square */
+ unit = SP_CSS_UNIT_EM;
+ if( style ) {
+ computed = value * style->font_size.computed;
+ } else {
+ computed = value * SPIFontSize::font_size_default;
+ }
+ } else if (!strcmp(e, "ex")) {
+ /* ex square */
+ unit = SP_CSS_UNIT_EX;
+ if( style ) {
+ computed = value * style->font_size.computed * 0.5; // FIXME
+ } else {
+ computed = value * SPIFontSize::font_size_default * 0.5;
+ }
+ } else if (!strcmp(e, "%")) {
+ /* Percentage */
+ unit = SP_CSS_UNIT_PERCENT;
+ value = value * 0.01;
+ if (name.compare( "line-height" ) == 0) {
+ // See: http://www.w3.org/TR/CSS2/visudet.html#propdef-line-height
+ if( style ) {
+ computed = value * style->font_size.computed;
+ } else {
+ computed = value * SPIFontSize::font_size_default;
+ }
+ }
+ } else {
+ /* Invalid */
+ return;
+ }
+ set = true;
+ inherit = false;
+ }
+ }
+}
+
+const Glib::ustring
+SPILength::write( guint const flags, SPIBase const *const base) const {
+
+ SPILength const *const my_base = dynamic_cast<const SPILength*>(base);
+ if ( (flags & SP_STYLE_FLAG_ALWAYS) ||
+ ((flags & SP_STYLE_FLAG_IFSET) && this->set) ||
+ ((flags & SP_STYLE_FLAG_IFDIFF) && this->set
+ && (!my_base->set || this != my_base )))
+ {
+ if (this->inherit) {
+ return (name + ":inherit;");
+ } else {
+ Inkscape::CSSOStringStream os;
+ switch (this->unit) {
+ case SP_CSS_UNIT_NONE:
+ os << name << ":" << this->computed << ";";
+ break;
+ case SP_CSS_UNIT_PX:
+ os << name << ":" << this->computed << "px;";
+ break;
+ case SP_CSS_UNIT_PT:
+ os << name << ":" << Inkscape::Util::Quantity::convert(this->computed, "px", "pt") << "pt;";
+ break;
+ case SP_CSS_UNIT_PC:
+ os << name << ":" << Inkscape::Util::Quantity::convert(this->computed, "px", "pc") << "pc;";
+ break;
+ case SP_CSS_UNIT_MM:
+ os << name << ":" << Inkscape::Util::Quantity::convert(this->computed, "px", "mm") << "mm;";
+ break;
+ case SP_CSS_UNIT_CM:
+ os << name << ":" << Inkscape::Util::Quantity::convert(this->computed, "px", "cm") << "cm;";
+ break;
+ case SP_CSS_UNIT_IN:
+ os << name << ":" << Inkscape::Util::Quantity::convert(this->computed, "px", "in") << "in;";
+ break;
+ case SP_CSS_UNIT_EM:
+ os << name << ":" << this->value << "em;";
+ break;
+ case SP_CSS_UNIT_EX:
+ os << name << ":" << this->value << "ex;";
+ break;
+ case SP_CSS_UNIT_PERCENT:
+ os << name << ":" << (this->value * 100.0) << "%;";
+ break;
+ default:
+ /* Invalid */
+ break;
+ }
+ return os.str();
+ }
+ }
+ return Glib::ustring("");
+}
+
+void
+SPILength::cascade( const SPIBase* const parent ) {
+ if( const SPILength* p = dynamic_cast<const SPILength*>(parent) ) {
+ if( (inherits && !set) || inherit ) {
+ unit = p->unit;
+ value = p->value;
+ computed = p->computed;
+ } else {
+ // Recalculate based on new font-size, font-family inherited from parent
+ double const em = style->font_size.computed;
+ if (unit == SP_CSS_UNIT_EM) {
+ computed = value * em;
+ } else if (unit == SP_CSS_UNIT_EX) {
+ // FIXME: Get x height from libnrtype or pango.
+ computed = value * em * 0.5;
+ } else if (unit == SP_CSS_UNIT_PERCENT && name.compare( "line-height" ) == 0 ) {
+ // Special case
+ computed = value * em;
+ }
+ }
+ } else {
+ std::cerr << "SPILength::cascade(): Incorrect parent type" << std::endl;
+ }
+}
+
+void
+SPILength::merge( const SPIBase* const parent ) {
+ if( const SPILength* p = dynamic_cast<const SPILength*>(parent) ) {
+ if( inherits ) {
+ if( (!set || inherit) && p->set && !(p->inherit) ) {
+ set = p->set;
+ inherit = p->inherit;
+ unit = p->unit;
+ value = p->value;
+ computed = p->computed;
+
+ // Fix up so values are correct
+ switch (p->unit) {
+ case SP_CSS_UNIT_EM:
+ case SP_CSS_UNIT_EX:
+ g_assert( &style->font_size != NULL && &p->style->font_size != NULL );
+ value *= p->style->font_size.computed / style->font_size.computed;
+ /** \todo
+ * FIXME: Have separate ex ratio parameter.
+ * Get x height from libnrtype or pango.
+ */
+ if (!IS_FINITE(value)) {
+ value = computed;
+ unit = SP_CSS_UNIT_NONE;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+ } else {
+ std::cerr << "SPIFloat::merge(): Incorrect parent type" << std::endl;
+ }
+}
+
+bool
+SPILength::operator==(const SPIBase& rhs) {
+ if( const SPILength* r = dynamic_cast<const SPILength*>(&rhs) ) {
+
+ if( unit != r->unit ) return false;
+
+ // If length depends on external parameter, lengths cannot be equal.
+ if (unit == SP_CSS_UNIT_EM) return false;
+ if (unit == SP_CSS_UNIT_EX) return false;
+ if (unit == SP_CSS_UNIT_PERCENT) return false;
+ if (r->unit == SP_CSS_UNIT_EM) return false;
+ if (r->unit == SP_CSS_UNIT_EX) return false;
+ if (r->unit == SP_CSS_UNIT_PERCENT) return false;
+
+ return (computed == r->computed );
+ } else {
+ return false;
+ }
+}
+
+
+
+// SPILengthOrNormal ----------------------------------------------------
+
+void
+SPILengthOrNormal::read( gchar const *str ) {
+
+ if( !str ) return;
+
+ if ( !strcmp(str, "normal") ) {
+ set = true;
+ inherit = false;
+ unit = SP_CSS_UNIT_NONE;
+ value = computed = 0.0;
+ normal = true;
+ } else {
+ SPILength::read( str );
+ normal = false;
+ }
+};
+
+const Glib::ustring
+SPILengthOrNormal::write( guint const flags, SPIBase const *const base) const {
+
+ SPILength const *const my_base = dynamic_cast<const SPILength*>(base);
+ if ( (flags & SP_STYLE_FLAG_ALWAYS) ||
+ ((flags & SP_STYLE_FLAG_IFSET) && this->set) ||
+ ((flags & SP_STYLE_FLAG_IFDIFF) && this->set
+ && (!my_base->set || this != my_base )))
+ {
+ if (this->normal) {
+ return (name + ":normal;");
+ } else {
+ return SPILength::write(flags, base);
+ }
+ }
+ return Glib::ustring("");
+}
+
+void
+SPILengthOrNormal::cascade( const SPIBase* const parent ) {
+ if( const SPILengthOrNormal* p = dynamic_cast<const SPILengthOrNormal*>(parent) ) {
+ if( (inherits && !set) || inherit ) {
+ normal = p->normal;
+ }
+ SPILength::cascade( parent );
+ } else {
+ std::cerr << "SPILengthOrNormal::cascade(): Incorrect parent type" << std::endl;
+ }
+}
+
+void
+SPILengthOrNormal::merge( const SPIBase* const parent ) {
+ if( const SPILengthOrNormal* p = dynamic_cast<const SPILengthOrNormal*>(parent) ) {
+ if( inherits ) {
+ if( (!set || inherit) && p->set && !(p->inherit) ) {
+ normal = p->normal;
+ SPILength::merge( parent );
+ }
+ }
+ }
+}
+
+bool
+SPILengthOrNormal::operator==(const SPIBase& rhs) {
+ if( const SPILengthOrNormal* r = dynamic_cast<const SPILengthOrNormal*>(&rhs) ) {
+ if( normal && r->normal ) { return true; }
+ if( normal != r->normal ) { return false; }
+ return SPILength::operator==(rhs);
+ } else {
+ return false;
+ }
+}
+
+
+
+// SPIEnum --------------------------------------------------------------
+
+void
+SPIEnum::read( gchar const *str ) {
+
+ if( !str ) return;
+
+ if( !strcmp(str, "inherit") ) {
+ set = true;
+ inherit = true;
+ } else {
+ for (unsigned i = 0; enums[i].key; i++) {
+ if (!strcmp(str, enums[i].key)) {
+ set = true;
+ inherit = false;
+ value = enums[i].value;
+ /* Save copying for values not needing it */
+ computed = value;
+ break;
+ }
+ }
+ // The following is defined in CSS 2.1
+ if( name.compare("font-weight" ) == 0 ) {
+ if( value == SP_CSS_FONT_WEIGHT_NORMAL ) {
+ computed = SP_CSS_FONT_WEIGHT_400;
+ } else if (value == SP_CSS_FONT_WEIGHT_BOLD ) {
+ computed = SP_CSS_FONT_WEIGHT_700;
+ }
+ }
+ }
+}
+
+const Glib::ustring
+SPIEnum::write( guint const flags, SPIBase const *const base) const {
+
+ SPIEnum const *const my_base = dynamic_cast<const SPIEnum*>(base);
+ if ( (flags & SP_STYLE_FLAG_ALWAYS) ||
+ ((flags & SP_STYLE_FLAG_IFSET) && this->set) ||
+ ((flags & SP_STYLE_FLAG_IFDIFF) && this->set
+ && (!my_base->set || this != my_base )))
+ {
+ if (this->inherit) {
+ return (name + ":inherit;");
+ }
+ for (unsigned i = 0; enums[i].key; ++i) {
+ if (enums[i].value == static_cast< gint > (this->value) ) {
+ return (name + ":" + enums[i].key + ";");
+ }
+ }
+ }
+ return Glib::ustring("");
+}
+
+void
+SPIEnum::cascade( const SPIBase* const parent ) {
+ if( const SPIEnum* p = dynamic_cast<const SPIEnum*>(parent) ) {
+ if( inherits && (!set || inherit) ) {
+ computed = p->computed;
+ } else {
+ if( name.compare("font-stretch" ) == 0 ) {
+ unsigned const parent_val = p->computed;
+ if( value == SP_CSS_FONT_STRETCH_NARROWER ) {
+ computed = (parent_val == SP_CSS_FONT_STRETCH_ULTRA_CONDENSED ?
+ parent_val : parent_val - 1);
+ } else if (value == SP_CSS_FONT_STRETCH_WIDER ) {
+ computed = (parent_val == SP_CSS_FONT_STRETCH_ULTRA_EXPANDED ?
+ parent_val : parent_val + 1);
+ }
+ }
+ // strictly, 'bolder' and 'lighter' should go to the next weight
+ // expressible in the current font family, but that's difficult to
+ // find out, so jumping by 3 seems an appropriate approximation
+ if( name.compare("font-weight" ) == 0 ) {
+ unsigned const parent_val = p->computed;
+ if( value == SP_CSS_FONT_WEIGHT_LIGHTER ) {
+ computed = (parent_val <= SP_CSS_FONT_WEIGHT_100 + 3 ?
+ (unsigned)SP_CSS_FONT_WEIGHT_100 : parent_val - 3);
+ } else if (value == SP_CSS_FONT_WEIGHT_BOLDER ) {
+ computed = (parent_val >= SP_CSS_FONT_WEIGHT_900 - 3 ?
+ (unsigned)SP_CSS_FONT_WEIGHT_900 : parent_val + 3);
+ }
+ }
+ }
+ } else {
+ std::cerr << "SPIEnum::cascade(): Incorrect parent type" << std::endl;
+ }
+}
+
+// FIXME Handle font_stretch and font_weight (relative values) New derived class?
+void
+SPIEnum::merge( const SPIBase* const parent ) {
+ if( const SPIEnum* p = dynamic_cast<const SPIEnum*>(parent) ) {
+ if( inherits ) {
+ if( p->set && !p->inherit ) {
+ if( !set || inherit ) {
+ set = p->set;
+ inherit = p->inherit;
+ value = p->value;
+ computed = p->computed; // Different from value for font-weight and font-stretch
+ } else {
+ // The following is to special case 'font-stretch' and 'font-weight'
+ unsigned max_computed_val = 100;
+ unsigned smaller_val = 100;
+ if( name.compare("font-stretch" ) == 0 ) {
+ max_computed_val = SP_CSS_FONT_STRETCH_ULTRA_EXPANDED;
+ smaller_val = SP_CSS_FONT_STRETCH_NARROWER;
+ } else if( name.compare("font-weight" ) == 0 ) {
+ max_computed_val = SP_CSS_FONT_WEIGHT_900;
+ smaller_val = SP_CSS_FONT_WEIGHT_LIGHTER;
+ }
+ unsigned const min_computed_val = 0;
+ unsigned const larger_val = smaller_val + 1;
+ if( value < smaller_val ) {
+ // Child has absolute value, leave as is.
+ // Works for all enum properties
+ } else if( (value == smaller_val && p->value == larger_val ) ||
+ (value == larger_val && p->value == smaller_val) ) {
+ // Values cancel, unset
+ set = false;
+ } else if( value == p->value ) {
+ // Leave as is, what does applying "wider" twice do?
+ } else {
+ // Child is smaller or larger, adjust parent value accordingly
+ unsigned const parent_val = p->computed;
+ value = (value == smaller_val ?
+ ( parent_val == min_computed_val ? parent_val : parent_val - 1 ) :
+ ( parent_val == max_computed_val ? parent_val : parent_val + 1 ) );
+ g_assert(value <= max_computed_val);
+ inherit = false;
+ g_assert(set);
+ }
+ }
+ }
+ }
+ }
+}
+
+bool
+SPIEnum::operator==(const SPIBase& rhs) {
+ if( const SPIEnum* r = dynamic_cast<const SPIEnum*>(&rhs) ) {
+ return (computed == r->computed && SPIBase::operator==(rhs));
+ } else {
+ return false;
+ }
+}
+
+
+
+// SPIString ------------------------------------------------------------
+
+void
+SPIString::read( gchar const *str ) {
+
+ if( !str ) return;
+
+ if (!strcmp(str, "inherit")) {
+ set = true;
+ inherit = true;
+ value = NULL;
+ } else {
+ set = true;
+ inherit = false;
+
+ Glib::ustring str_temp(str);
+ if( name.compare( "font-family" ) == 0 ) {
+ // Family names may be quoted in CSS, internally we use unquoted names.
+ css_font_family_unquote( str_temp );
+ } else if( name.compare( "-inkscape-font-specification" ) == 0 ) {
+ css_unquote( str_temp );
+ }
+
+ value = g_strdup(str_temp.c_str());
+ }
+}
+
+
+// This routine is actually rarely used. Writing is done usually
+// in sp_repr_css_write_string...
+const Glib::ustring
+SPIString::write( guint const flags, SPIBase const *const base) const {
+
+ SPIString const *const my_base = dynamic_cast<const SPIString*>(base);
+ if ( (flags & SP_STYLE_FLAG_ALWAYS) ||
+ ((flags & SP_STYLE_FLAG_IFSET) && this->set) ||
+ ((flags & SP_STYLE_FLAG_IFDIFF) && this->set
+ && (!my_base->set || this != my_base )))
+ {
+ if (this->inherit) {
+ return (name + ":inherit;");
+ } else {
+ if( this->value ) {
+ if( name.compare( "font-family" ) == 0 ) {
+ Glib::ustring font_family( this->value );
+ css_font_family_quote( font_family );
+ return (name + ":" + font_family + ";");
+ } else if( name.compare( "-inkscape-font-specification" ) == 0 ) {
+ Glib::ustring font_spec( this->value );
+ css_quote( font_spec );
+ return (name + ":" + font_spec + ";");
+ } else {
+ return (name + ":" + this->value + ";");
+ }
+ }
+ }
+ }
+ return Glib::ustring("");
+}
+
+void
+SPIString::clear() {
+ SPIBase::clear();
+ g_free( value );
+ value = NULL;
+ if( value_default ) value = strdup( value_default );
+}
+
+void
+SPIString::cascade( const SPIBase* const parent ) {
+ if( const SPIString* p = dynamic_cast<const SPIString*>(parent) ) {
+ if( inherits && (!set || inherit) ) {
+ g_free(value);
+ value = g_strdup(p->value);
+ }
+ } else {
+ std::cerr << "SPIString::cascade(): Incorrect parent type" << std::endl;
+ }
+}
+
+void
+SPIString::merge( const SPIBase* const parent ) {
+ if( const SPIString* p = dynamic_cast<const SPIString*>(parent) ) {
+ if( inherits ) {
+ if( (!set || inherit) && p->set && !(p->inherit) ) {
+ set = p->set;
+ inherit = p->inherit;
+ g_free(value);
+ value = g_strdup(p->value);
+ }
+ }
+ }
+}
+
+bool
+SPIString::operator==(const SPIBase& rhs) {
+ if( const SPIString* r = dynamic_cast<const SPIString*>(&rhs) ) {
+ if( value == NULL && r->value == NULL ) return (SPIBase::operator==(rhs));
+ if( value == NULL || r->value == NULL ) return false;
+
+ return (strcmp(value, r->value) == 0 && SPIBase::operator==(rhs));
+ } else {
+ return false;
+ }
+}
+
+
+
+// SPIColor -------------------------------------------------------------
+
+// Used for 'color', 'text-decoration-color', 'flood-color', 'lighting-color', and 'stop-color'.
+// (The last three have yet to be implemented.)
+// CSS3: 'currentcolor' is allowed value and is equal to inherit for the 'color' property.
+// FIXME: We should preserve named colors, hsl colors, etc.
+void SPIColor::read( gchar const *str ) {
+
+ if( !str ) return;
+
+ set = false;
+ inherit = false;
+ currentcolor = false;
+ if ( !strcmp(str, "inherit") ) {
+ set = true;
+ inherit = true;
+ } else if ( !strcmp(str, "currentColor") ) {
+ set = true;
+ currentcolor = true;
+ if( name.compare( "color") == 0 ) {
+ inherit = true; // CSS3
+ } else {
+ setColor( style->color.value.color );
+ }
+ } else {
+ guint32 const rgb0 = sp_svg_read_color(str, 0xff);
+ if (rgb0 != 0xff) {
+ setColor(rgb0);
+ set = true;
+ }
+ }
+}
+
+const Glib::ustring
+SPIColor::write( guint const flags, SPIBase const *const base) const {
+
+ SPIColor const *const my_base = dynamic_cast<const SPIColor*>(base);
+ if ( (flags & SP_STYLE_FLAG_ALWAYS) ||
+ ((flags & SP_STYLE_FLAG_IFSET) && this->set) ||
+ ((flags & SP_STYLE_FLAG_IFDIFF) && this->set
+ && (!my_base->set || this != my_base )))
+ {
+ CSSOStringStream css;
+
+ if (this->currentcolor) {
+ // currentcolor goes first to handle special case for 'color' property
+ css << "currentColor";
+ } else if (this->inherit) {
+ css << "inherit";
+ } else {
+ char color_buf[8];
+ sp_svg_write_color(color_buf, sizeof(color_buf), this->value.color.toRGBA32( 0 ));
+ css << color_buf;
+
+ if (this->value.color.icc) {
+ if ( !css.str().empty() ) {
+ css << " ";
+ }
+ css << "icc-color(" << this->value.color.icc->colorProfile;
+ for (std::vector<double>::const_iterator i(this->value.color.icc->colors.begin()),
+ iEnd(this->value.color.icc->colors.end());
+ i != iEnd; ++i) {
+ css << ", " << *i;
+ }
+ css << ')';
+ }
+ }
+
+ if ( !css.str().empty() ) {
+ return (name + ":" + css.str() + ";");
+ }
+ }
+
+ return Glib::ustring("");
+}
+
+void
+SPIColor::cascade( const SPIBase* const parent ) {
+ if( const SPIColor* p = dynamic_cast<const SPIColor*>(parent) ) {
+ if( (inherits && !set) || inherit) { // FIXME verify for 'color'
+ if( !(inherit && currentcolor) ) currentcolor = p->currentcolor;
+ setColor( p->value.color );
+ } else {
+ // Add CSS4 Color: Lighter, Darker
+ }
+ } else {
+ std::cerr << "SPIColor::cascade(): Incorrect parent type" << std::endl;
+ }
+
+}
+
+void
+SPIColor::merge( const SPIBase* const parent ) {
+ if( const SPIColor* p = dynamic_cast<const SPIColor*>(parent) ) {
+ if( inherits ) {
+ if( (!set || inherit) && p->set && !(p->inherit) ) {
+ set = p->set;
+ inherit = p->inherit;
+ currentcolor = p->currentcolor;
+ value.color = p->value.color;
+ }
+ }
+ }
+}
+
+bool
+SPIColor::operator==(const SPIBase& rhs) {
+ if( const SPIColor* r = dynamic_cast<const SPIColor*>(&rhs) ) {
+
+ if ( (this->currentcolor != r->currentcolor ) ||
+ (this->value.color != r->value.color ) ||
+ (this->value.color.icc != r->value.color.icc ) ||
+ (this->value.color.icc && r->value.color.icc &&
+ this->value.color.icc->colorProfile != r->value.color.icc->colorProfile &&
+ this->value.color.icc->colors != r->value.color.icc->colors ) ) {
+ return false;
+ }
+
+ return SPIBase::operator==(rhs);
+
+ } else {
+ return false;
+ }
+}
+
+
+
+// SPIPaint -------------------------------------------------------------
+
+// Paint is used for 'fill' and 'stroke'. SPIPaint perhaps should be derived from SPIColor.
+// 'style' is set in SPStyle::SPStyle or in the legacy SPIPaint::read( gchar, style, document )
+// It is needed for computed value when value is 'currentColor'. It is also needed to
+// find the object for creating an href (this is done through document but should be done
+// directly so document not needed.. FIXME).
+
+SPIPaint::~SPIPaint() {
+ if( value.href ) {
+ clear();
+ delete value.href;
+ value.href = NULL;
+ }
+}
+
+/**
+ * Set SPIPaint object from string.
+ *
+ * \pre paint == \&style.fill || paint == \&style.stroke.
+ */
+void
+SPIPaint::read( gchar const *str ) {
+
+ // std::cout << "SPIPaint::read: Entrance: " << " |" << (str?str:"null") << "|" << std::endl;
+ // if( style ) {
+ // std::cout << " document: " << (void*)style->document << std::endl;
+ // std::cout << " object: " << (style->object?"present":"null") << std::endl;
+ // if( style->object )
+ // std::cout << " : " << (style->object->getId()?style->object->getId():"no ID")
+ // << " document: " << (style->object->document?"yes":"no") << std::endl;
+ // }
+
+ if(!str ) return;
+
+ reset( false ); // Do not init
+
+ // Is this necessary?
+ while (g_ascii_isspace(*str)) {
+ ++str;
+ }
+
+ if (streq(str, "inherit")) {
+ set = true;
+ inherit = true;
+ } else {
+ // Read any URL first. The other values can be stand-alone or backup to the URL.
+
+ if ( strneq(str, "url", 3) ) {
+
+ // FIXME: THE FOLLOWING CODE SHOULD BE PUT IN A PRIVATE FUNCTION FOR REUSE
+ gchar *uri = extract_uri( str, &str );
+ if(uri == NULL || uri[0] == '\0') {
+ std::cerr << "SPIPaint::read: url is empty or invalid" << std::endl;
+ } else if (!style ) {
+ std::cerr << "SPIPaint::read: url with empty SPStyle pointer" << std::endl;
+ } else {
+ set = true;
+ SPDocument *document = (style->object) ? style->object->document : NULL;
+
+ // Create href if not done already
+ if (!value.href && document) {
+ // std::cout << " Creating value.href" << std::endl;
+ value.href = new SPPaintServerReference(document);
+ if (this == &style->fill) {
+ style->fill_ps_changed_connection = value.href->changedSignal().connect(sigc::bind(sigc::ptr_fun(sp_style_fill_paint_server_ref_changed), style));
+ } else {
+ style->stroke_ps_changed_connection = value.href->changedSignal().connect(sigc::bind(sigc::ptr_fun(sp_style_stroke_paint_server_ref_changed), style));
+ }
+ }
+
+ // std::cout << "uri: " << (uri?uri:"null") << std::endl;
+ // TODO check what this does in light of move away from union
+ sp_style_set_ipaint_to_uri_string ( style, this, uri);
+ }
+ g_free( uri );
+ }
+
+ while ( g_ascii_isspace(*str) ) {
+ ++str;
+ }
+
+ if (streq(str, "currentColor")) {
+ set = true;
+ currentcolor = true;
+ if (style) {
+ setColor( style->color.value.color );
+ } else {
+ // Normally an SPIPaint is part of an SPStyle and the value of 'color' is
+ // available. SPIPaint can be used 'stand-alone' (e.g. to parse color values) in
+ // which case a value of 'currentColor' is meaningless, thus we shouldn't reach
+ // here.
+ std::cerr << "SPIPaint::read(): value is 'currentColor' but 'color' not available." << std::endl;
+ setColor( 0 );
+ }
+ } else if (streq(str, "none")) {
+ set = true;
+ noneSet = true;
+ } else {
+ guint32 const rgb0 = sp_svg_read_color(str, &str, 0xff);
+ if (rgb0 != 0xff) {
+ setColor( rgb0 );
+ set = true;
+
+ while (g_ascii_isspace(*str)) {
+ ++str;
+ }
+ if (strneq(str, "icc-color(", 10)) {
+ SVGICCColor* tmp = new SVGICCColor();
+ if ( ! sp_svg_read_icc_color( str, &str, tmp ) ) {
+ delete tmp;
+ tmp = 0;
+ }
+ value.color.icc = tmp;
+ }
+ }
+ }
+ }
+}
+
+// Stand-alone read (Legacy read()), used multiple places, e.g. sp-stop.cpp
+// This function should not be necessary. FIXME
+void
+SPIPaint::read( gchar const *str, SPStyle &style_in, SPDocument *document_in ) {
+ style = &style_in;
+ style->document = document_in;
+ read( str );
+}
+
+const Glib::ustring
+SPIPaint::write( guint const flags, SPIBase const *const base) const {
+
+ SPIPaint const *const my_base = dynamic_cast<const SPIPaint*>(base);
+ if ( (flags & SP_STYLE_FLAG_ALWAYS) ||
+ ((flags & SP_STYLE_FLAG_IFSET) && this->set) ||
+ ((flags & SP_STYLE_FLAG_IFDIFF) && this->set
+ && (!my_base->set || this != my_base )))
+ {
+ CSSOStringStream css;
+
+ if (this->inherit) {
+ css << "inherit";
+ } else {
+
+ // url must go first as other values can serve as fallbacks
+ if ( this->value.href && this->value.href->getURI() ) {
+ const gchar* uri = this->value.href->getURI()->toString();
+ css << "url(" << uri << ")";
+ g_free((void *)uri);
+ }
+
+ if ( this->noneSet ) {
+ if ( !css.str().empty() ) {
+ css << " ";
+ }
+ css << "none";
+ }
+
+ if ( this->currentcolor ) {
+ if ( !css.str().empty() ) {
+ css << " ";
+ }
+ css << "currentColor";
+ }
+
+ if ( this->colorSet && !this->currentcolor ) {
+ if ( !css.str().empty() ) {
+ css << " ";
+ }
+ char color_buf[8];
+ sp_svg_write_color(color_buf, sizeof(color_buf), this->value.color.toRGBA32( 0 ));
+ css << color_buf;
+ }
+
+ if (this->value.color.icc && !this->currentcolor) {
+ if ( !css.str().empty() ) {
+ css << " ";
+ }
+ css << "icc-color(" << this->value.color.icc->colorProfile;
+ for (std::vector<double>::const_iterator i(this->value.color.icc->colors.begin()),
+ iEnd(this->value.color.icc->colors.end());
+ i != iEnd; ++i) {
+ css << ", " << *i;
+ }
+ css << ')';
+ }
+ }
+
+ if ( !css.str().empty() ) {
+ return (name + ":" + css.str() + ";");
+ }
+ }
+
+ return Glib::ustring("");
+}
+
+void
+SPIPaint::clear() {
+ // std::cout << "SPIPaint::clear(): " << name << std::endl;
+ reset( true ); // Reset and Init
+}
+
+void
+SPIPaint::reset( bool init ) {
+
+ // std::cout << "SPIPaint::reset(): " << name << " " << init << std::endl;
+ SPIBase::clear();
+ currentcolor = false;
+ colorSet = false;
+ noneSet = false;
+ value.color.set( false );
+ if (value.href){
+ if (value.href->getObject()) {
+ value.href->detach();
+ }
+ }
+ if( init ) {
+ if( name.compare( "fill" ) == 0 ) {
+ // 'black' is default for 'fill'
+ setColor(0.0, 0.0, 0.0);
+ }
+ if( name.compare( "text-decoration-color" ) == 0 ) {
+ // currentcolor = true;
+ }
+ }
+}
+
+void
+SPIPaint::cascade( const SPIBase* const parent ) {
+
+ // std::cout << "SPIPaint::cascade" << std::endl;
+ if( const SPIPaint* p = dynamic_cast<const SPIPaint*>(parent) ) {
+ if(!set || inherit) { // Always inherits
+
+ reset( false ); // Do not init
+
+ if( p->isPaintserver() ) {
+ if( p->value.href) {
+ // Why can we use p->document ?
+ sp_style_set_ipaint_to_uri( style, this, p->value.href->getURI(), p->value.href->getOwnerDocument());
+ } else {
+ std::cerr << "SPIPaint::cascade: Expected paint server not found." << std::endl;
+ }
+ } else if( p->isColor() ) {
+ setColor( p->value.color );
+ } else if( p->isNoneSet() ) {
+ noneSet = true;
+ } else if( p->currentcolor ) {
+ currentcolor = true;
+ setColor( style->color.value.color );
+ } else if( isNone() ) {
+ //
+ } else {
+ g_assert_not_reached();
+ }
+ } else {
+ if( currentcolor ) {
+ // Update in case color value changed.
+ setColor( style->color.value.color );
+ }
+ }
+
+ } else {
+ std::cerr << "SPIPaint::cascade(): Incorrect parent type" << std::endl;
+ }
+
+}
+
+void
+SPIPaint::merge( const SPIBase* const parent ) {
+ if( const SPIPaint* p = dynamic_cast<const SPIPaint*>(parent) ) {
+ // if( inherits ) { Paint always inherits
+ if( (!set || inherit) && p->set && !(p->inherit) ) {
+ this->cascade( parent ); // Must call before setting 'set'
+ set = p->set;
+ inherit = p->inherit;
+ }
+ }
+}
+
+bool
+SPIPaint::operator==(const SPIBase& rhs) {
+
+ if( const SPIPaint* r = dynamic_cast<const SPIPaint*>(&rhs) ) {
+
+ if ( (this->isColor() != r->isColor() ) ||
+ (this->isPaintserver() != r->isPaintserver() ) ||
+ (this->currentcolor != r->currentcolor ) ) {
+ return false;
+ }
+
+ if ( this->isPaintserver() ) {
+ if( this->value.href == NULL || r->value.href == NULL ||
+ this->value.href->getObject() != r->value.href->getObject() ) {
+ return false;
+ }
+ }
+
+ if ( this->isColor() ) {
+ if ( (this->value.color != r->value.color ) ||
+ (this->value.color.icc != r->value.color.icc ) ||
+ (this->value.color.icc && r->value.color.icc &&
+ this->value.color.icc->colorProfile != r->value.color.icc->colorProfile &&
+ this->value.color.icc->colors != r->value.color.icc->colors ) ) {
+ return false;
+ }
+ }
+
+ return SPIBase::operator==(rhs);
+
+ } else {
+ return false;
+ }
+}
+
+
+
+// SPIPaintOrder --------------------------------------------------------
+
+void
+SPIPaintOrder::read( gchar const *str ) {
+
+ if( !str ) return;
+
+ g_free(value);
+ set = false;
+ inherit = false;
+
+ if (!strcmp(str, "inherit")) {
+ set = true;
+ inherit = true;
+ } else {
+ set = true;
+ value = g_strdup(str);
+
+ if (!strcmp(value, "normal")) {
+ layer[0] = SP_CSS_PAINT_ORDER_NORMAL;
+ layer_set[0] = true;
+ } else {
+ // This certainly can be done more efficiently
+ gchar** c = g_strsplit(value, " ", PAINT_ORDER_LAYERS + 1);
+ bool used[3] = {false, false, false};
+ unsigned int i = 0;
+ for( ; i < PAINT_ORDER_LAYERS; ++i ) {
+ if( c[i] ) {
+ layer_set[i] = false;
+ if( !strcmp( c[i], "fill")) {
+ layer[i] = SP_CSS_PAINT_ORDER_FILL;
+ layer_set[i] = true;
+ used[0] = true;
+ } else if( !strcmp( c[i], "stroke")) {
+ layer[i] = SP_CSS_PAINT_ORDER_STROKE;
+ layer_set[i] = true;
+ used[1] = true;
+ } else if( !strcmp( c[i], "markers")) {
+ layer[i] = SP_CSS_PAINT_ORDER_MARKER;
+ layer_set[i] = true;
+ used[2] = true;
+ } else {
+ std::cerr << "sp_style_read_ipaintorder: illegal value: " << c[i] << std::endl;
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+ g_strfreev(c);
+
+ // Fill out rest of the layers using the default order
+ if( !used[0] && i < PAINT_ORDER_LAYERS ) {
+ layer[i] = SP_CSS_PAINT_ORDER_FILL;
+ layer_set[i] = false;
+ ++i;
+ }
+ if( !used[1] && i < PAINT_ORDER_LAYERS ) {
+ layer[i] = SP_CSS_PAINT_ORDER_STROKE;
+ layer_set[i] = false;
+ ++i;
+ }
+ if( !used[2] && i < PAINT_ORDER_LAYERS ) {
+ layer[i] = SP_CSS_PAINT_ORDER_MARKER;
+ layer_set[i] = false;
+ }
+ }
+ }
+}
+
+const Glib::ustring
+SPIPaintOrder::write( guint const flags, SPIBase const *const base) const {
+
+ SPIPaintOrder const *const my_base = dynamic_cast<const SPIPaintOrder*>(base);
+ if ( (flags & SP_STYLE_FLAG_ALWAYS) ||
+ ((flags & SP_STYLE_FLAG_IFSET) && this->set) ||
+ ((flags & SP_STYLE_FLAG_IFDIFF) && this->set
+ && (!my_base->set || this != my_base )))
+ {
+ CSSOStringStream css;
+
+ if (this->inherit) {
+ css << "inherit";
+ } else {
+ for( unsigned i = 0; i < PAINT_ORDER_LAYERS; ++i ) {
+ if( this->layer_set[i] == true ) {
+ switch (this->layer[i]) {
+ case SP_CSS_PAINT_ORDER_NORMAL:
+ css << "normal";
+ assert( i == 0 );
+ break;
+ case SP_CSS_PAINT_ORDER_FILL:
+ if (i!=0) css << " ";
+ css << "fill";
+ break;
+ case SP_CSS_PAINT_ORDER_STROKE:
+ if (i!=0) css << " ";
+ css << "stroke";
+ break;
+ case SP_CSS_PAINT_ORDER_MARKER:
+ if (i!=0) css << " ";
+ css << "markers";
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+ }
+ return (name + ":" + css.str() + ";");
+ }
+ return Glib::ustring("");
+}
+
+void
+SPIPaintOrder::cascade( const SPIBase* const parent ) {
+ if( const SPIPaintOrder* p = dynamic_cast<const SPIPaintOrder*>(parent) ) {
+ if(!set || inherit) { // Always inherits
+ for( unsigned i = 0; i < PAINT_ORDER_LAYERS; ++i ) {
+ layer[i] = p->layer[i];
+ layer_set[i] = p->layer_set[i];
+ }
+ g_free( value );
+ value = g_strdup(p->value);
+ }
+ } else {
+ std::cerr << "SPIPaintOrder::cascade(): Incorrect parent type" << std::endl;
+ }
+}
+
+void
+SPIPaintOrder::merge( const SPIBase* const parent ) {
+ if( const SPIPaintOrder* p = dynamic_cast<const SPIPaintOrder*>(parent) ) {
+ // if( inherits ) { PaintOrder always inherits
+ if( (!set || inherit) && p->set && !(p->inherit) ) {
+ this->cascade( parent ); // Must call be setting 'set'
+ set = p->set;
+ inherit = p->inherit;
+ }
+ }
+}
+
+bool
+SPIPaintOrder::operator==(const SPIBase& rhs) {
+ if( const SPIPaintOrder* r = dynamic_cast<const SPIPaintOrder*>(&rhs) ) {
+ if( layer[0] == SP_CSS_PAINT_ORDER_NORMAL &&
+ r->layer[0] == SP_CSS_PAINT_ORDER_NORMAL ) return SPIBase::operator==(rhs);
+ for (unsigned i = 0; i < PAINT_ORDER_LAYERS; ++i ) {
+ if( layer[i] != r->layer[i] ) return false;
+ }
+ return SPIBase::operator==(rhs);
+ } else {
+ return false;
+ }
+}
+
+
+
+// SPIFilter ------------------------------------------------------------
+
+SPIFilter::~SPIFilter() {
+ if( href ) {
+ clear();
+ delete href;
+ href = NULL;
+ }
+}
+
+void
+SPIFilter::read( gchar const *str ) {
+
+ if( !str ) return;
+
+ clear();
+
+ if ( streq(str, "inherit") ) {
+ set = true;
+ inherit = true;
+ } else if(streq(str, "none")) {
+ set = true;
+ } else if (strneq(str, "url", 3)) {
+ gchar *uri = extract_uri(str);
+ if(uri == NULL || uri[0] == '\0') {
+ std::cerr << "SPIFilter::read: url is empty or invalid" << std::endl;
+ return;
+ } else if (!style) {
+ std::cerr << "SPIFilter::read: url with empty SPStyle pointer" << std::endl;
+ return;
+ }
+ set = true;
+
+ // Create href if not already done.
+ if (!href) {
+ if (style->object) {
+ href = new SPFilterReference(style->object);
+ }
+ // Do we have href now?
+ if ( href ) {
+ href->changedSignal().connect(sigc::bind(sigc::ptr_fun(sp_style_filter_ref_changed), style));
+ } else {
+ std::cerr << "SPIFilter::read(): Could not allocate 'href'" << std::endl;
+ return;
+ }
+ }
+
+ // We have href
+ try {
+ href->attach(Inkscape::URI(uri));
+ } catch (Inkscape::BadURIException &e) {
+ std::cerr << "SPIFilter::read() " << e.what() << std::endl;
+ href->detach();
+ }
+ g_free (uri);
+
+ } else {
+ std::cerr << "SPIFilter::read(): malformed value: " << str << std::endl;
+ }
+}
+
+const Glib::ustring SPIFilter::write( guint const flags, SPIBase const *const /*base*/) const
+{
+ // TODO: fix base
+ //SPILength const *const my_base = dynamic_cast<const SPILength*>(base);
+ if ( (flags & SP_STYLE_FLAG_ALWAYS) ||
+ ((flags & SP_STYLE_FLAG_IFSET) && this->set) ||
+ ((flags & SP_STYLE_FLAG_IFDIFF) && this->set))
+ {
+ if (this->inherit) {
+ return (name + ":inherit;");
+ } else if(this->href && this->href->getURI()) {
+ gchar *uri = this->href->getURI()->toString();
+ Glib::ustring retval = name + ":url(" + uri + ");";
+ g_free(uri);
+ return retval;
+ }
+ }
+ return Glib::ustring("");
+}
+
+
+void
+SPIFilter::clear() {
+
+ SPIBase::clear();
+ if( href ) {
+ if( href->getObject() ) {
+ href->detach();
+ }
+ }
+}
+
+void
+SPIFilter::cascade( const SPIBase* const parent ) {
+ if( const SPIFilter* p = dynamic_cast<const SPIFilter*>(parent) ) {
+ if( inherit ) { // Only inherits if 'inherit' true/
+ // This is rather unlikely so ignore for now. FIXME
+ (void)p;
+ std::cerr << "SPIFilter::cascade: value 'inherit' not supported." << std::endl;
+ } else {
+ // Do nothing
+ }
+ } else {
+ std::cerr << "SPIFilter::cascade(): Incorrect parent type" << std::endl;
+ }
+}
+
+void
+SPIFilter::merge( const SPIBase* const parent ) {
+ if( const SPIFilter* p = dynamic_cast<const SPIFilter*>(parent) ) {
+ // The "correct" thing to do is to combine the filter primitives.
+ // The next best thing is to keep any filter on this object. If there
+ // is no filter on this object, then use any filter on the parent.
+ if( (!set || inherit) && p->href && p->href->getObject() ) { // is the getObject() needed?
+ set = p->set;
+ inherit = p->inherit;
+ if( href ) {
+ // If we alread have an href, use it (unlikely but heck...)
+ if( href->getObject() ) {
+ href->detach();
+ }
+ } else {
+ // If we don't have an href, create it
+ if( style->document ) { // FIXME
+ href = new SPFilterReference(style->document);
+ //href->changedSignal().connect(sigc::bind(sigc::ptr_fun(sp_style_filter_ref_changed), style));
+ } else if (style->object) {
+ href = new SPFilterReference(style->object);
+ }
+ }
+ if( href ) {
+ // If we now have an href, try to attach parent filter
+ try {
+ href->attach(*p->href->getURI());
+ } catch (Inkscape::BadURIException &e) {
+ std::cerr << "SPIFilter::merge: " << e.what() << std::endl;
+ href->detach();
+ }
+ }
+ }
+ }
+}
+
+// FIXME
+bool
+SPIFilter::operator==(const SPIBase& rhs) {
+ if( const SPIFilter* r = dynamic_cast<const SPIFilter*>(&rhs) ) {
+ (void)r;
+ return true;
+ } else {
+ return false;
+ }
+}
+
+
+
+// SPIDashArray ---------------------------------------------------------
+
+void
+SPIDashArray::read( gchar const *str ) {
+
+ if( !str ) return;
+
+ set = true;
+
+ if( strcmp( str, "inherit") == 0 ) {
+ inherit = true;
+ return;
+ }
+
+ values.clear();
+
+ if( strcmp(str, "none") == 0) {
+ return;
+ }
+
+ gchar *e = NULL;
+ bool LineSolid = true;
+ while (e != str) {
+ /* TODO: Should allow <length> rather than just a unitless (px) number. */
+ double number = g_ascii_strtod(str, (char **) &e);
+ values.push_back( number );
+ if (number > 0.00000001)
+ LineSolid = false;
+ if (e != str) {
+ str = e;
+ }
+ while (str && *str && !isalnum(*str)) str += 1;
+ }
+
+ if (LineSolid) {
+ values.clear();
+ }
+ return;
+}
+
+const Glib::ustring
+SPIDashArray::write( guint const flags, SPIBase const *const base) const {
+
+ SPIDashArray const *const my_base = dynamic_cast<const SPIDashArray*>(base);
+ if ( (flags & SP_STYLE_FLAG_ALWAYS) ||
+ ((flags & SP_STYLE_FLAG_IFSET) && this->set) ||
+ ((flags & SP_STYLE_FLAG_IFDIFF) && this->set
+ && (!my_base->set || this != my_base )))
+ {
+ if (this->inherit) {
+ return (name + ":inherit;");
+ } else if (this->values.empty() ) {
+ return (name + ":none;");
+ } else {
+ Inkscape::CSSOStringStream os;
+ os << name << ":";
+ for (unsigned i = 0; i < this->values.size(); ++i) {
+ if (i) {
+ os << ", ";
+ }
+ os << this->values[i];
+ }
+ os << ";";
+ return os.str();
+ }
+ }
+ return Glib::ustring("");
+}
+
+
+void
+SPIDashArray::cascade( const SPIBase* const parent ) {
+ if( const SPIDashArray* p = dynamic_cast<const SPIDashArray*>(parent) ) {
+ if( !set || inherit ) values = p->values; // Always inherits
+ } else {
+ std::cerr << "SPIDashArray::cascade(): Incorrect parent type" << std::endl;
+ }
+}
+
+void
+SPIDashArray::merge( const SPIBase* const parent ) {
+ if( const SPIDashArray* p = dynamic_cast<const SPIDashArray*>(parent) ) {
+ if( inherits ) {
+ if( (!set || inherit) && p->set && !(p->inherit) ) {
+ set = p->set;
+ inherit = p->inherit;
+ values = p->values;
+ }
+ }
+ } else {
+ std::cerr << "SPIDashArray::merge(): Incorrect parent type" << std::endl;
+ }
+}
+
+bool
+SPIDashArray::operator==(const SPIBase& rhs) {
+ if( const SPIDashArray* r = dynamic_cast<const SPIDashArray*>(&rhs) ) {
+ return values == r->values && SPIBase::operator==(rhs);
+ } else {
+ return false;
+ }
+}
+
+
+
+// SPIFontSize ----------------------------------------------------------
+
+/** Indexed by SP_CSS_FONT_SIZE_blah. These seem a bit small */
+float const SPIFontSize::font_size_table[] = {6.0, 8.0, 10.0, 12.0, 14.0, 18.0, 24.0};
+float const SPIFontSize::font_size_default = 12.0;
+
+void
+SPIFontSize::read( gchar const *str ) {
+
+ if( !str ) return;
+
+ if (!strcmp(str, "inherit")) {
+ set = true;
+ inherit = true;
+ } else if ((*str == 'x') || (*str == 's') || (*str == 'm') || (*str == 'l')) {
+ // xx-small, x-small, etc.
+ for (unsigned i = 0; enum_font_size[i].key; i++) {
+ if (!strcmp(str, enum_font_size[i].key)) {
+ set = true;
+ inherit = false;
+ type = SP_FONT_SIZE_LITERAL;
+ literal = enum_font_size[i].value;
+ return;
+ }
+ }
+ /* Invalid */
+ return;
+ } else {
+ SPILength length("temp");
+ length.set = false;
+ length.read( str );
+ if( length.set ) {
+ set = true;
+ inherit = length.inherit;
+ unit = length.unit;
+ value = length.value;
+ computed = length.computed;
+ if( unit == SP_CSS_UNIT_PERCENT ) {
+ type = SP_FONT_SIZE_PERCENTAGE;
+ } else {
+ type = SP_FONT_SIZE_LENGTH;
+ }
+ }
+ return;
+ }
+}
+
+const Glib::ustring
+SPIFontSize::write( guint const flags, SPIBase const *const base) const {
+
+ SPIFontSize const *const my_base = dynamic_cast<const SPIFontSize*>(base);
+ if ( (flags & SP_STYLE_FLAG_ALWAYS) ||
+ ((flags & SP_STYLE_FLAG_IFSET) && this->set) ||
+ ((flags & SP_STYLE_FLAG_IFDIFF) && this->set
+ && (!my_base->set || this != my_base )))
+ {
+ CSSOStringStream css;
+
+ if (this->inherit) {
+ css << "inherit";
+ } else if (this->type == SP_FONT_SIZE_LITERAL) {
+ for (unsigned i = 0; enum_font_size[i].key; i++) {
+ if (enum_font_size[i].value == static_cast< gint > (this->literal) ) {
+ css << enum_font_size[i].key;
+ }
+ }
+ } else if (this->type == SP_FONT_SIZE_LENGTH) {
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ int unit = prefs->getInt("/options/font/unitType", SP_CSS_UNIT_PT);
+ if (prefs->getBool("/options/font/textOutputPx", true)) {
+ unit = SP_CSS_UNIT_PX;
+ }
+ css << sp_style_css_size_px_to_units(this->computed, unit) << sp_style_get_css_unit_string(unit);
+ } else if (this->type == SP_FONT_SIZE_PERCENTAGE) {
+ css << (this->value * 100.0) << "%";
+ }
+ return (name + ":" + css.str() + ";");
+ }
+ return Glib::ustring("");
+}
+
+void
+SPIFontSize::cascade( const SPIBase* const parent ) {
+ if( const SPIFontSize* p = dynamic_cast<const SPIFontSize*>(parent) ) {
+ if( !set || inherit ) { // Always inherits
+ computed = p->computed;value = p->value;
+
+
+ // Calculate computed based on parent as needed
+ } else if( type == SP_FONT_SIZE_LITERAL ) {
+ if( literal < SP_CSS_FONT_SIZE_SMALLER ) {
+ computed = font_size_table[ literal ];
+ } else if( literal == SP_CSS_FONT_SIZE_SMALLER ) {
+ computed = p->computed / 1.2;
+ } else if( literal == SP_CSS_FONT_SIZE_LARGER ) {
+ computed = p->computed * 1.2;
+ } else {
+ std::cerr << "SPIFontSize::cascade: Illegal literal value" << std::endl;
+ }
+ } else if( type == SP_FONT_SIZE_PERCENTAGE ) {
+ // Percentage for font size is relative to parent computed (rather than viewport)
+ computed = p->computed * value;
+ } else if( type == SP_FONT_SIZE_LENGTH ) {
+ switch ( unit ) {
+ case SP_CSS_UNIT_EM:
+ /* Relative to parent font size */
+ computed = p->computed * value;
+ break;
+ case SP_CSS_UNIT_EX:
+ /* Relative to parent font size */
+ computed = p->computed * value * 0.5; /* Hack FIXME */
+ break;
+ default:
+ /* No change */
+ break;
+ }
+ }
+ } else {
+ std::cerr << "SPIFontSize::cascade(): Incorrect parent type" << std::endl;
+ }
+}
+
+double
+SPIFontSize::relative_fraction() const {
+
+ switch (type) {
+ case SP_FONT_SIZE_LITERAL: {
+ switch (literal) {
+ case SP_CSS_FONT_SIZE_SMALLER:
+ return 5.0 / 6.0;
+
+ case SP_CSS_FONT_SIZE_LARGER:
+ return 6.0 / 5.0;
+
+ default:
+ g_assert_not_reached();
+ }
+ }
+
+ case SP_FONT_SIZE_PERCENTAGE:
+ return value;
+
+ case SP_FONT_SIZE_LENGTH: {
+ switch (unit ) {
+ case SP_CSS_UNIT_EM:
+ return value;
+
+ case SP_CSS_UNIT_EX:
+ return value * 0.5;
+
+ default:
+ g_assert_not_reached();
+ }
+ }
+ }
+ g_assert_not_reached();
+}
+
+void
+SPIFontSize::merge( const SPIBase* const parent ) {
+ if( const SPIFontSize* p = dynamic_cast<const SPIFontSize*>(parent) ) {
+ if( p->set && !(p->inherit) ) {
+ // Parent has definined font-size
+ if( (!set || inherit) ) {
+ // Computed value same as parent
+ set = p->set;
+ inherit = p->inherit;
+ value = p->value;
+ computed = p->computed; // Just to be sure
+ } else if ( type == SP_FONT_SIZE_LENGTH &&
+ unit != SP_CSS_UNIT_EM &&
+ unit != SP_CSS_UNIT_EX ) {
+ // Absolute size, computed value already set
+ } else if ( type == SP_FONT_SIZE_LITERAL &&
+ literal < SP_CSS_FONT_SIZE_SMALLER ) {
+ // Absolute size, computed value already set
+ //g_assert( literal < G_N_ELEMENTS(font_size_table) );
+ g_assert( computed == font_size_table[literal] );
+ } else {
+ // Relative size
+ double const child_frac( relative_fraction() );
+ set = true;
+ inherit = false;
+ computed = p->computed * child_frac;
+
+ if ( ( p->type == SP_FONT_SIZE_LITERAL &&
+ p->literal < SP_CSS_FONT_SIZE_SMALLER ) ||
+ ( p->type == SP_FONT_SIZE_LENGTH &&
+ p->unit != SP_CSS_UNIT_EM &&
+ p->unit != SP_CSS_UNIT_EX ) ) {
+ // Parent absolut size
+ type = SP_FONT_SIZE_LENGTH;
+
+ } else {
+ // Parent relative size
+ double const parent_frac( p->relative_fraction() );
+ if( type == SP_FONT_SIZE_LENGTH ) {
+ // ex/em
+ value *= parent_frac;
+ } else {
+ value = parent_frac * child_frac;
+ type = SP_FONT_SIZE_PERCENTAGE;
+ }
+ }
+ } // Relative size
+ } // Parent set and not inherit
+ } else {
+ std::cerr << "SPIFontSize::merge(): Incorrect parent type" << std::endl;
+ }
+}
+
+// What about different SVG units?
+bool
+SPIFontSize::operator==(const SPIBase& rhs) {
+ if( const SPIFontSize* r = dynamic_cast<const SPIFontSize*>(&rhs) ) {
+ if( type != r->type ) { return false;}
+ if( type == SP_FONT_SIZE_LENGTH ) {
+ if( computed != r->computed ) { return false;}
+ } else if (type == SP_FONT_SIZE_LITERAL ) {
+ if( literal != r->literal ) { return false;}
+ } else {
+ if( value != r->value ) { return false;}
+ }
+ return SPIBase::operator==(rhs);
+ } else {
+ return false;
+ }
+}
+
+
+
+// SPIFont ----------------------------------------------------------
+
+void
+SPIFont::read( gchar const *str ) {
+
+ if( !str ) return;
+
+ if( !style ) {
+ std::cerr << "SPIFont::read(): style is void" << std::endl;
+ return;
+ }
+
+ if ( !strcmp(str, "inherit") ) {
+ set = true;
+ inherit = true;
+ } else {
+
+ // Break string into white space separated tokens
+ std::stringstream os( str );
+ Glib::ustring param;
+
+ while (os >> param) {
+
+ // CSS is case insensitive but we're comparing against lowercase strings
+ Glib::ustring lparam = param.lowercase();
+
+ if (lparam == "/" ) {
+ // line_height follows... note: font-size already read
+
+ os >> param;
+ lparam = param.lowercase();
+ style->line_height.readIfUnset( lparam.c_str() );
+
+ } else {
+ // Try to parse each property in turn
+
+ SPIEnum test_style("font-style", enum_font_style);
+ test_style.read( lparam.c_str() );
+ if( test_style.set ) {
+ style->font_style = test_style;
+ continue;
+ }
+
+ // font-variant (Note: only CSS2.1 value small-caps is valid in shortcut.)
+ SPIEnum test_variant("font-variant", enum_font_variant);
+ test_variant.read( lparam.c_str() );
+ if( test_variant.set ) {
+ style->font_variant = test_variant;
+ continue;
+ }
+
+ // font-weight
+ SPIEnum test_weight("font-weight", enum_font_weight);
+ test_weight.read( lparam.c_str() );
+ if( test_weight.set ) {
+ style->font_weight = test_weight;
+ continue;
+ }
+
+ // font-stretch (added in CSS 3 Fonts)
+ SPIEnum test_stretch("font-stretch", enum_font_stretch);
+ test_stretch.read( lparam.c_str() );
+ if( test_stretch.set ) {
+ style->font_stretch = test_stretch;
+ continue;
+ }
+
+ // font-size
+ SPIFontSize test_size;
+ test_size.read( lparam.c_str() );
+ if( test_size.set ) {
+ style->font_size = test_size;
+ continue;
+ }
+
+ // No valid property value found.
+ break;
+ }
+ } // params
+
+ // The rest must be font-family...
+ std::string str_s = str; // Why this extra step?
+ std::string family = str_s.substr( str_s.find( param ) );
+
+ style->font_family.readIfUnset( family.c_str() );
+
+ // Everything in shorthand is set per CSS rules, this works since
+ // properties are read backwards from end to start.
+ style->font_style.set = true;
+ style->font_variant.set = true;
+ style->font_weight.set = true;
+ style->font_stretch.set = true;
+ style->font_size.set = true;
+ style->line_height.set = true;
+ style->font_family.set = true;
+ // style->font_size_adjust.set = true;
+ // style->font_kerning.set = true;
+ // style->font_language_override.set = true;;
+ }
+}
+
+const Glib::ustring SPIFont::write( guint const /*flags*/, SPIBase const *const /*base*/) const
+{
+ // At the moment, do nothing. We could add a preference to write out
+ // 'font' shorthand rather than longhand properties.
+
+ // SPIFontSize const *const my_base = dynamic_cast<const SPIFontSize*>(base);
+ // if ( (flags & SP_STYLE_FLAG_ALWAYS) ||
+ // ((flags & SP_STYLE_FLAG_IFSET) && this->set) ||
+ // ((flags & SP_STYLE_FLAG_IFDIFF) && this->set
+ // && (!my_base->set || this != my_base )))
+ // {
+ // CSSOStringStream css;
+ // }
+ return Glib::ustring("");
+}
+
+// void
+// SPIFont::cascade( const SPIBase* const parent ) {
+// }
+
+// void
+// SPIFont::merge( const SPIBase* const parent ) {
+// }
+
+// Does nothing...
+bool
+SPIFont::operator==(const SPIBase& rhs) {
+ if( /* const SPIFont* r = */ dynamic_cast<const SPIFont*>(&rhs) ) {
+ return SPIBase::operator==(rhs);
+ } else {
+ return false;
+ }
+}
+
+
+
+// SPIBaselineShift -----------------------------------------------------
+
+void
+SPIBaselineShift::read( gchar const *str ) {
+
+ if( !str ) return;
+
+ if (!strcmp(str, "inherit")) {
+ set = true;
+ inherit = true;
+ } else if ((*str == 'b') || (*str == 's')) {
+ // baseline or sub or super
+ for (unsigned i = 0; enum_baseline_shift[i].key; i++) {
+ if (!strcmp(str, enum_baseline_shift[i].key)) {
+ set = true;
+ inherit = false;
+ type = SP_BASELINE_SHIFT_LITERAL;
+ literal = enum_baseline_shift[i].value;
+ return;
+ }
+ }
+ /* Invalid */
+ return;
+ } else {
+ SPILength length( "temp" );
+ length.read( str );
+ set = length.set;
+ inherit = length.inherit;
+ unit = length.unit;
+ value = length.value;
+ computed = length.computed;
+ if( unit == SP_CSS_UNIT_PERCENT ) {
+ type = SP_BASELINE_SHIFT_PERCENTAGE;
+ } else {
+ type = SP_BASELINE_SHIFT_LENGTH;
+ }
+ return;
+ }
+}
+
+const Glib::ustring
+SPIBaselineShift::write( guint const flags, SPIBase const *const base) const {
+
+ SPIBaselineShift const *const my_base = dynamic_cast<const SPIBaselineShift*>(base);
+ if ( (flags & SP_STYLE_FLAG_ALWAYS) ||
+ ((flags & SP_STYLE_FLAG_IFSET) && this->set) ||
+ ((flags & SP_STYLE_FLAG_IFDIFF) && this->set
+ && (!my_base->set || !this->isZero() )))
+ {
+ CSSOStringStream css;
+
+ if (this->inherit) {
+ css << "inherit";
+ } else if (this->type == SP_BASELINE_SHIFT_LITERAL) {
+ for (unsigned i = 0; enum_baseline_shift[i].key; i++) {
+ if (enum_baseline_shift[i].value == static_cast< gint > (this->literal) ) {
+ css << enum_baseline_shift[i].key;
+ }
+ }
+ } else if (this->type == SP_BASELINE_SHIFT_LENGTH) {
+ if( this->unit == SP_CSS_UNIT_EM || this->unit == SP_CSS_UNIT_EX ) {
+ css << this->value << (this->unit == SP_CSS_UNIT_EM ? "em" : "ex");
+ } else {
+ css << this->computed << "px"; // must specify px, see inkscape bug 1221626, mozilla bug 234789
+ }
+ } else if (this->type == SP_BASELINE_SHIFT_PERCENTAGE) {
+ css << (this->value * 100.0) << "%";
+ }
+ return (name + ":" + css.str() + ";");
+ }
+ return Glib::ustring("");
+}
+
+void
+SPIBaselineShift::cascade( const SPIBase* const parent ) {
+ if( const SPIBaselineShift* p = dynamic_cast<const SPIBaselineShift*>(parent) ) {
+ SPIFontSize *pfont_size = &(p->style->font_size);
+ g_assert( pfont_size != NULL );
+
+ if( !set || inherit ) {
+ computed = p->computed; // Shift relative to parent shift, corrected below
+ } else if (type == SP_BASELINE_SHIFT_LITERAL) {
+ if( literal == SP_CSS_BASELINE_SHIFT_BASELINE ) {
+ computed = 0; // No change
+ } else if (literal == SP_CSS_BASELINE_SHIFT_SUB ) {
+ // Should use subscript position from font relative to alphabetic baseline
+ // OpenOffice, Adobe: -0.33, Word -0.14, LaTex about -0.2.
+ computed = -0.2 * pfont_size->computed;
+ } else if (literal == SP_CSS_BASELINE_SHIFT_SUPER ) {
+ // Should use superscript position from font relative to alphabetic baseline
+ // OpenOffice, Adobe: 0.33, Word 0.35, LaTex about 0.45.
+ computed = 0.4 * pfont_size->computed;
+ } else {
+ /* Illegal value */
+ }
+ } else if (type == SP_BASELINE_SHIFT_PERCENTAGE) {
+ // Percentage for baseline shift is relative to computed "line-height"
+ // which is just font-size (see SVG1.1 'font').
+ computed = pfont_size->computed * value;
+ } else if (type == SP_BASELINE_SHIFT_LENGTH) {
+ switch (unit) {
+ case SP_CSS_UNIT_EM:
+ computed = value * pfont_size->computed;
+ break;
+ case SP_CSS_UNIT_EX:
+ computed = value * 0.5 * pfont_size->computed;
+ break;
+ default:
+ /* No change */
+ break;
+ }
+ }
+ // baseline-shifts are relative to parent baseline
+ computed += p->computed;
+
+ } else {
+ std::cerr << "SPIBaselineShift::cascade(): Incorrect parent type" << std::endl;
+ }
+}
+
+// This was not defined in the legacy C code, it needs some serious thinking (but is low priority).
+// FIX ME
+void
+SPIBaselineShift::merge( const SPIBase* const parent ) {
+ if( const SPIBaselineShift* p = dynamic_cast<const SPIBaselineShift*>(parent) ) {
+ if( (!set || inherit) && p->set && !(p->inherit) ) {
+ set = p->set;
+ inherit = p->inherit;
+ value = p->value;
+ }
+ } else {
+ std::cerr << "SPIBaselineShift::merge(): Incorrect parent type" << std::endl;
+ }
+}
+
+// This is not used but we have it for completeness, it has not been tested.
+bool
+SPIBaselineShift::operator==(const SPIBase& rhs) {
+ if( const SPIBaselineShift* r = dynamic_cast<const SPIBaselineShift*>(&rhs) ) {
+ if( type != r->type ) return false;
+ if( type == SP_BASELINE_SHIFT_LENGTH ) {
+ if( computed != r->computed ) return false;
+ } else if ( type == SP_BASELINE_SHIFT_LITERAL ) {
+ if( literal != r->literal ) return false;
+ } else {
+ if( value != r->value ) return false;
+ }
+ return SPIBase::operator==(rhs);
+ } else {
+ return false;
+ }
+}
+
+bool
+SPIBaselineShift::isZero() const {
+ if( type == SP_BASELINE_SHIFT_LITERAL ) {
+ if( literal == SP_CSS_BASELINE_SHIFT_BASELINE ) return true;
+ } else {
+ if( value == 0.0 ) return true;
+ }
+ return false;
+}
+
+
+
+// SPITextDecorationLine ------------------------------------------------
+
+void
+SPITextDecorationLine::read( gchar const *str ) {
+
+ if( !str ) return;
+
+ if (!strcmp(str, "inherit")) {
+ set = true;
+ inherit = true;
+ } else if (!strcmp(str, "none")) {
+ set = true;
+ inherit = false;
+ underline = false;
+ overline = false;
+ line_through = false;
+ blink = false;
+ } else {
+ bool found_one = false;
+ bool hit_one = false;
+
+ // CSS 2 keywords
+ bool found_underline = false;
+ bool found_overline = false;
+ bool found_line_through = false;
+ bool found_blink = false;
+
+ // This method ignores inlineid keys and extra delimiters, so " ,,, blink hello" will set
+ // blink and ignore hello
+ const gchar *hstr = str;
+ while (1) {
+ if (*str == ' ' || *str == ',' || *str == '\0'){
+ int slen = str - hstr;
+ // CSS 2 keywords
+ while(1){ // not really a loop, used to avoid a goto
+ hit_one = true; // most likely we will
+ if ((slen == 9) && strneq(hstr, "underline", slen)){ found_underline = true; break; }
+ if ((slen == 8) && strneq(hstr, "overline", slen)){ found_overline = true; break; }
+ if ((slen == 12) && strneq(hstr, "line-through", slen)){ found_line_through = true; break; }
+ if ((slen == 5) && strneq(hstr, "blink", slen)){ found_blink = true; break; }
+ if ((slen == 4) && strneq(hstr, "none", slen)){ break; }
+
+ hit_one = false; // whatever this thing is, we do not recognize it
+ break;
+ }
+ found_one |= hit_one;
+ if(*str == '\0')break;
+ hstr = str + 1;
+ }
+ str++;
+ }
+ if (found_one) {
+ set = true;
+ inherit = false;
+ underline = found_underline;
+ overline = found_overline;
+ line_through = found_line_through;
+ blink = found_blink;
+ }
+ else {
+ set = false;
+ inherit = false;
+ }
+ }
+}
+
+const Glib::ustring
+SPITextDecorationLine::write( guint const flags, SPIBase const *const base) const {
+ SPITextDecorationLine const *const my_base = dynamic_cast<const SPITextDecorationLine*>(base);
+ if ( (flags & SP_STYLE_FLAG_ALWAYS) ||
+ ((flags & SP_STYLE_FLAG_IFSET) && this->set) ||
+ ((flags & SP_STYLE_FLAG_IFDIFF) && this->set
+ && (!my_base->set || this != my_base )))
+ {
+ Inkscape::CSSOStringStream os;
+ os << name << ":";
+ if( inherit ) {
+ os << "inherit";
+ } else if (this->underline || this->overline || this->line_through || this->blink) {
+ if (this->underline) os << " underline";
+ if (this->overline) os << " overline";
+ if (this->line_through) os << " line-through";
+ if (this->blink) os << " blink"; // Deprecated
+ } else {
+ os << "none";
+ }
+ os << ";";
+ return ( os.str() );
+ }
+ return Glib::ustring("");
+}
+
+void
+SPITextDecorationLine::cascade( const SPIBase* const parent ) {
+ if( const SPITextDecorationLine* p = dynamic_cast<const SPITextDecorationLine*>(parent) ) {
+ if( inherits && (!set || inherit) ) {
+ underline = p->underline;
+ overline = p->overline;
+ line_through = p->line_through;
+ blink = p->blink;
+ }
+ } else {
+ std::cerr << "SPITextDecorationLine::cascade(): Incorrect parent type" << std::endl;
+ }
+}
+
+void
+SPITextDecorationLine::merge( const SPIBase* const parent ) {
+ if( const SPITextDecorationLine* p = dynamic_cast<const SPITextDecorationLine*>(parent) ) {
+ if( inherits ) { // Always inherits... but special rules?
+ if( (!set || inherit) && p->set && !(p->inherit) ) {
+ set = p->set;
+ inherit = p->inherit;
+ underline = p->underline;
+ overline = p->overline;
+ line_through = p->line_through;
+ blink = p->blink;
+ }
+ }
+ }
+}
+
+bool
+SPITextDecorationLine::operator==(const SPIBase& rhs) {
+ if( const SPITextDecorationLine* r = dynamic_cast<const SPITextDecorationLine*>(&rhs) ) {
+ return
+ (underline == r->underline ) &&
+ (overline == r->overline ) &&
+ (line_through == r->line_through ) &&
+ (blink == r->blink ) &&
+ SPIBase::operator==(rhs);
+ } else {
+ return false;
+ }
+}
+
+
+
+// SPITextDecorationStyle -----------------------------------------------
+
+void
+SPITextDecorationStyle::read( gchar const *str ) {
+
+ if( !str ) return;
+
+ set = false;
+ inherit = false;
+
+ solid = true; // Default
+ isdouble = false;
+ dotted = false;
+ dashed = false;
+ wavy = false;
+
+ if (!strcmp(str, "inherit")) {
+ set = true;
+ inherit = true;
+ solid = false;
+ } else {
+ // note, these are CSS 3 keywords
+ bool found_solid = false;
+ bool found_double = false;
+ bool found_dotted = false;
+ bool found_dashed = false;
+ bool found_wavy = false;
+ bool found_one = false;
+
+ // this method ignores inlineid keys and extra delimiters, so " ,,, style hello" will set style and ignore hello
+ // if more than one style is present, the first is used
+ const gchar *hstr = str;
+ while (1) {
+ if (*str == ' ' || *str == ',' || *str == '\0'){
+ int slen = str - hstr;
+ if ( (slen == 5) && strneq(hstr, "solid", slen)){ found_solid = true; found_one = true; break; }
+ else if ((slen == 6) && strneq(hstr, "double", slen)){ found_double = true; found_one = true; break; }
+ else if ((slen == 6) && strneq(hstr, "dotted", slen)){ found_dotted = true; found_one = true; break; }
+ else if ((slen == 6) && strneq(hstr, "dashed", slen)){ found_dashed = true; found_one = true; break; }
+ else if ((slen == 4) && strneq(hstr, "wavy", slen)){ found_wavy = true; found_one = true; break; }
+ if(*str == '\0')break; // nothing more to test
+ hstr = str + 1;
+ }
+ str++;
+ }
+ if(found_one){
+ set = true;
+ solid = found_solid;
+ isdouble = found_double;
+ dotted = found_dotted;
+ dashed = found_dashed;
+ wavy = found_wavy;
+ }
+ else {
+ set = false;
+ inherit = false;
+ }
+ }
+}
+
+const Glib::ustring
+SPITextDecorationStyle::write( guint const flags, SPIBase const *const base) const {
+ SPITextDecorationStyle const *const my_base = dynamic_cast<const SPITextDecorationStyle*>(base);
+ if ( (flags & SP_STYLE_FLAG_ALWAYS) ||
+ ((flags & SP_STYLE_FLAG_IFSET) && this->set) ||
+ ((flags & SP_STYLE_FLAG_IFDIFF) && this->set
+ && (!my_base->set || this != my_base )))
+ {
+ Inkscape::CSSOStringStream os;
+ os << name << ":";
+ if( inherit ) {
+ os << "inherit";
+ } else if (this->solid ) {
+ os << "solid";
+ } else if (this->isdouble ) {
+ os << "double";
+ } else if (this->dotted ) {
+ os << "dotted";
+ } else if (this->dashed ) {
+ os << "dashed";
+ } else if (this->wavy ) {
+ os << "wavy";
+ } else {
+ std::cerr << "SPITextDecorationStyle::write(): No valid value for property" << std::endl;
+ return Glib::ustring("");
+ }
+ os << ";";
+ return ( os.str() );
+ }
+ return Glib::ustring("");
+}
+
+void
+SPITextDecorationStyle::cascade( const SPIBase* const parent ) {
+ if( const SPITextDecorationStyle* p = dynamic_cast<const SPITextDecorationStyle*>(parent) ) {
+ if( inherits && (!set || inherit) ) {
+ solid = p->solid;
+ isdouble = p->isdouble;
+ dotted = p->dotted;
+ dashed = p->dashed;
+ wavy = p->wavy;
+ }
+ } else {
+ std::cerr << "SPITextDecorationStyle::cascade(): Incorrect parent type" << std::endl;
+ }
+}
+
+void
+SPITextDecorationStyle::merge( const SPIBase* const parent ) {
+ if( const SPITextDecorationStyle* p = dynamic_cast<const SPITextDecorationStyle*>(parent) ) {
+ if( inherits ) { // Always inherits... but special rules?
+ if( (!set || inherit) && p->set && !(p->inherit) ) {
+ set = p->set;
+ inherit = p->inherit;
+ solid = p->solid;
+ isdouble = p->isdouble;
+ dotted = p->dotted;
+ dashed = p->dashed;
+ wavy = p->wavy;
+ }
+ }
+ }
+}
+
+bool
+SPITextDecorationStyle::operator==(const SPIBase& rhs) {
+ if( const SPITextDecorationStyle* r = dynamic_cast<const SPITextDecorationStyle*>(&rhs) ) {
+ return
+ (solid == r->solid ) &&
+ (isdouble == r->isdouble ) &&
+ (dotted == r->dotted ) &&
+ (dashed == r->dashed ) &&
+ (wavy == r->wavy ) &&
+ SPIBase::operator==(rhs);
+ } else {
+ return false;
+ }
+}
+
+
+
+// TextDecorationColor is handled by SPIPaint (should be SPIColor), default value is "currentColor"
+// FIXME
+
+
+
+// SPITextDecoration ----------------------------------------------------
+
+void
+SPITextDecoration::read( gchar const *str ) {
+
+ if( !str ) return;
+
+ bool is_css3 = false;
+
+ SPITextDecorationLine test_line;
+ test_line.read( str );
+ if( test_line.set ) {
+ style->text_decoration_line = test_line;
+ }
+
+ SPITextDecorationStyle test_style;
+ test_style.read( str );
+ if( test_style.set ) {
+ style->text_decoration_style = test_style;
+ is_css3 = true;
+ }
+
+ // the color routine must be fed one token at a time - if multiple colors are found the LAST
+ // one is used ???? then why break on set?
+
+ // This could certainly be designed better
+ SPIColor test_color("text-decoration-color");
+ test_color.setStylePointer( style );
+ test_color.read( "currentColor" ); // Default value
+ test_color.set = false;
+ const gchar *hstr = str;
+ while (1) {
+ if (*str == ' ' || *str == ',' || *str == '\0'){
+ int slen = str - hstr;
+ gchar *frag = g_strndup(hstr,slen+1); // only send one piece at a time, since keywords may be intermixed
+
+ if( strcmp( frag, "none" ) != 0 ) { // 'none' not allowed
+ test_color.read( frag );
+ }
+
+ free(frag);
+ if( test_color.set ) {
+ style->text_decoration_color = test_color;
+ is_css3 = true;
+ break;
+ }
+ test_color.read( "currentColor" ); // Default value
+ test_color.set = false;
+ if( *str == '\0' )break;
+ hstr = str + 1;
+ }
+ str++;
+ }
+
+ // If we read a style or color then we have CSS3 which require any non-set values to be
+ // set to their default values.
+ if( is_css3 ) {
+ style->text_decoration_line.set = true;
+ style->text_decoration_style.set = true;
+ style->text_decoration_color.set = true;
+ }
+
+ // If we set text_decoration_line, then update style_td (for CSS2 text-decoration)
+ if( style->text_decoration_line.set == true ) {
+ style_td = style;
+ }
+}
+
+// Returns CSS2 'text-decoration' (using settings in SPTextDecorationLine)
+// This is required until all SVG renderers support CSS3 'text-decoration'
+const Glib::ustring
+SPITextDecoration::write( guint const flags, SPIBase const *const base) const {
+ SPITextDecoration const *const my_base = dynamic_cast<const SPITextDecoration*>(base);
+ if ( (flags & SP_STYLE_FLAG_ALWAYS) ||
+ ((flags & SP_STYLE_FLAG_IFSET) && style->text_decoration_line.set) ||
+ ((flags & SP_STYLE_FLAG_IFDIFF) && style->text_decoration_line.set
+ && (!my_base->style->text_decoration_line.set ||
+ style->text_decoration_line != my_base->style->text_decoration_line )))
+ {
+ Inkscape::CSSOStringStream os;
+ os << name << ":";
+ if( inherit ) {
+ os << "inherit";
+ } else if (style->text_decoration_line.underline ||
+ style->text_decoration_line.overline ||
+ style->text_decoration_line.line_through ||
+ style->text_decoration_line.blink) {
+ if (style->text_decoration_line.underline) os << " underline";
+ if (style->text_decoration_line.overline) os << " overline";
+ if (style->text_decoration_line.line_through) os << " line-through";
+ if (style->text_decoration_line.blink) os << " blink"; // Deprecated
+ } else {
+ os << "none";
+ }
+ os << ";";
+ return ( os.str() );
+ }
+ return Glib::ustring("");
+}
+
+void
+SPITextDecoration::cascade( const SPIBase* const parent ) {
+ if( const SPITextDecoration* p = dynamic_cast<const SPITextDecoration*>(parent) ) {
+ if( style_td == NULL ) {
+ style_td = p->style_td;
+ }
+ } else {
+ std::cerr << "SPITextDecoration::cascade(): Incorrect parent type" << std::endl;
+ }
+
+}
+
+void
+SPITextDecoration::merge( const SPIBase* const parent ) {
+ if( const SPITextDecoration* p = dynamic_cast<const SPITextDecoration*>(parent) ) {
+ if( style_td == NULL ) {
+ style_td = p->style_td;
+ }
+ } else {
+ std::cerr << "SPITextDecoration::merge(): Incorrect parent type" << std::endl;
+ }
+
+}
+
+// Use CSS2 value
+bool
+SPITextDecoration::operator==(const SPIBase& rhs) {
+ if( const SPITextDecoration* r = dynamic_cast<const SPITextDecoration*>(&rhs) ) {
+ return (style->text_decoration_line == r->style->text_decoration_line &&
+ SPIBase::operator==(rhs));
+ } else {
+ return false;
+ }
+}
+
+
+
+/* ---------------------------- NOTES ----------------------------- */
+
+/*
+ * opacity's effect is cumulative; we set the new value to the combined effect. The
+ * default value for opacity is 1.0, not inherit. (Note that stroke-opacity and
+ * fill-opacity are quite different from opacity, and don't need any special handling.)
+ *
+ * Cases:
+ * - parent & child were each previously unset, in which case the effective
+ * opacity value is 1.0, and style should remain unset.
+ * - parent was previously unset (so computed opacity value of 1.0)
+ * and child was set to inherit. The merged child should
+ * get a value of 1.0, and shouldn't inherit (lest the new parent
+ * has a different opacity value). Given that opacity's default
+ * value is 1.0 (rather than inherit), we might as well have the
+ * merged child's opacity be unset.
+ * - parent was previously unset (so opacity 1.0), and child was set to a number.
+ * The merged child should retain its existing settings (though it doesn't matter
+ * if we make it unset if that number was 1.0).
+ * - parent was inherit and child was unset. Merged child should be set to inherit.
+ * - parent was inherit and child was inherit. (We can't in general reproduce this
+ * effect (short of introducing a new group), but setting opacity to inherit is rare.)
+ * If the inherited value was strictly between 0.0 and 1.0 (exclusive) then the merged
+ * child's value should be set to the product of the two, i.e. the square of the
+ * inherited value, and should not be marked as inherit. (This decision assumes that it
+ * is more important to retain the effective opacity than to retain the inheriting
+ * effect, and assumes that the inheriting effect either isn't important enough to create
+ * a group or isn't common enough to bother maintaining the code to create a group.) If
+ * the inherited value was 0.0 or 1.0, then marking the merged child as inherit comes
+ * closer to maintaining the effect.
+ * - parent was inherit and child was set to a numerical value. If the child's value
+ * was 1.0, then the merged child should have the same settings as the parent.
+ * If the child's value was 0, then the merged child should also be set to 0.
+ * If the child's value was anything else, then we do the same as for the inherit/inherit
+ * case above: have the merged child set to the product of the two opacities and not
+ * marked as inherit, for the same reasons as for that case.
+ * - parent was set to a value, and child was unset. The merged child should have
+ * parent's settings.
+ * - parent was set to a value, and child was inherit. The merged child should
+ * be set to the product, i.e. the square of the parent's value.
+ * - parent & child are each set to a value. The merged child should be set to the
+ * product.
+ */
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/style-internal.h b/src/style-internal.h
index 7d45f96f8..faae76ac5 100644
--- a/src/style-internal.h
+++ b/src/style-internal.h
@@ -7,7 +7,9 @@
/* Authors:
* Lauris Kaplinski <lauris@kaplinski.com>
* Jon A. Cruz <jon@joncruz.org>
+ * Tavmjong Bah <tavmjong@free.fr>
*
+ * Copyright (C) 2014 Tavmjong Bah
* Copyright (C) 2010 Jon A. Cruz
* Copyright (C) 2001-2002 Lauris Kaplinski
* Copyright (C) 2001 Ximian, Inc.
@@ -15,21 +17,218 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
+#include "style-enums.h"
+
#include "color.h"
+#include "svg/svg-icc-color.h"
#include "sp-marker-loc.h"
#include "sp-filter.h"
#include "sp-filter-reference.h"
#include "sp-paint-server-reference.h"
#include "uri.h"
+#include "xml/repr.h"
#include <vector>
-/// Float type internal to SPStyle.
-struct SPIFloat {
- unsigned set : 1;
- unsigned inherit : 1;
- unsigned data : 30;
+struct SPStyleEnum;
+
+static const unsigned SP_STYLE_FLAG_ALWAYS (1 << 2);
+static const unsigned SP_STYLE_FLAG_IFSET (1 << 0);
+static const unsigned SP_STYLE_FLAG_IFDIFF (1 << 1);
+
+enum SPStyleSrc {
+ SP_STYLE_SRC_UNSET,
+ SP_STYLE_SRC_STYLE_PROP,
+ SP_STYLE_SRC_STYLE_SHEET,
+ SP_STYLE_SRC_ATTRIBUTE
+};
+
+/* General comments:
+ *
+ * This code is derived from the original C style code in style.cpp.
+ *
+ * Overview:
+ * Style can be obtained (in order of precidence) [CHECK]
+ * 1. "style" property in an element (style="fill:red").
+ * 2. Style sheet, internal or external (<style> rect {fill:red;}</style>).
+ * 3. Attributes in an element (fill="red").
+ * 4. Parent's style.
+ * A later property overrides an earlier property. This is implemented by
+ * reading in the properties backwards. If a property is already set, it
+ * prevents an earlier property from being read.
+ *
+ * In order for cascading to work, each element in the tree must be read in from top to bottom
+ * (parent before child). At each step, if a style property is not explicitly set, the property
+ * value is taken from the parent. Some properties have "computed" values that depend on:
+ * the parent's value (e.g. "font-size:larger"),
+ * another property value ("stroke-width":1em"), or
+ * an external value ("stroke-width:5%").
+ *
+ * To summarize:
+ *
+ * An explicitly set value (including 'inherit') has a 'true' "set" flag.
+ * The "value" is either explicitly set or inherited.
+ * The "computed" value (if present) is calculated from "value" and some other input.
+ *
+ * Functions:
+ * write(): Write a property and its value to a string.
+ * Flags:
+ * ALWAYS: Always write out property.
+ * IFSET: Write a property if 'set' flag is true, otherwise return empty string.
+ * IFDIFF: Write a property if computed values are different, otherwise return empty string,
+ * This is only used for text!!
+ *
+ * read(): Set a property value from a string.
+ * clear(): Set a property to its default value and set the 'set' flag to false.
+ * cascade(): Cascade the parent's property values to the child if the child's property
+ * is unset (and it allows inheriting) or the value is 'inherit'.
+ * Calculate computed values that depend on parent.
+ * This requires that the parent already be updated.
+ * merge(): Merge the property values of a child and a parent that is being deleted,
+ * attempting to preserve the style of the child.
+ * operator=: Assignment operator required due to use of templates (in original C code).
+ * operator==: True if computed values are equal. TO DO: DEFINE EXACTLY WHAT THIS MEANS
+ * operator!=: Inverse of operator==.
+ *
+ *
+ * Outside dependencies:
+ *
+ * The C structures that these classes are evolved from were designed to be embedded in to the
+ * style structure (i.e they are "internal" and thus have an "I" in the SPI prefix). However,
+ * they should be reasonably stand-alone and can provide some functionality outside of the style
+ * stucture (i.e. reading and writing style strings). Some properties do need access to other
+ * properties from the same object (e.g. SPILength sometimes needs to know font size) to
+ * calculate 'computed' values. Inheritence, of course, requires access to the parent object's
+ * style class.
+ *
+ * The only real outside dependancy is SPObject... which is needed in the cases of SPIPaint and
+ * SPIFilter for setting up the "href". (Currently, SPDocument is needed but this dependency
+ * should be removed as an "href" only needs the SPDocument for attaching an external document to
+ * the XML tree [see uri-references.cpp]. If SPDocument is really needed, it can be obtained from
+ * SPObject.)
+ *
+ */
+
+/// Virtual base class for all SPStyle interal classes
+class SPIBase
+{
+
+public:
+ SPIBase( Glib::ustring const &name, bool inherits = true )
+ : name(name),
+ inherits(inherits),
+ set(false),
+ inherit(false),
+ style_src(SP_STYLE_SRC_UNSET),
+ style(NULL)
+ {}
+
+ virtual ~SPIBase()
+ {}
+
+ virtual void read( gchar const *str ) = 0;
+ virtual void readIfUnset( gchar const *str ) {
+ if ( !set ) {
+ read( str );
+ }
+ }
+
+ virtual void readAttribute( Inkscape::XML::Node *repr ) {
+ readIfUnset( repr->attribute( name.c_str() ) );
+ }
+
+ virtual const Glib::ustring write( guint const flags = SP_STYLE_FLAG_IFSET,
+ SPIBase const *const base = NULL ) const = 0;
+ virtual void clear() {
+ set = false, inherit = false;
+ }
+
+ virtual void cascade( const SPIBase* const parent ) = 0;
+ virtual void merge( const SPIBase* const parent ) = 0;
+
+ virtual void setStylePointer( SPStyle *style_in ) {
+ style = style_in;
+ }
+
+ // Explicit assignment operator required due to templates.
+ SPIBase& operator=(const SPIBase& rhs) {
+ name = rhs.name;
+ inherits = rhs.inherits;
+ set = rhs.set;
+ inherit = rhs.inherit;
+ style_src = rhs.style_src;
+ style = rhs.style;
+ return *this;
+ }
+
+ // Check apples being compared to apples
+ virtual bool operator==(const SPIBase& rhs) {
+ return (name == rhs.name);
+ }
+
+ virtual bool operator!=(const SPIBase& rhs) {
+ return !(*this == rhs);
+ }
+
+ // To do: make private
+public:
+ Glib::ustring name; // Make const
+ unsigned inherits : 1; // Property inherits by default from parent.
+ unsigned set : 1; // Property has been explicitly set (vs. inherited).
+ unsigned inherit : 1; // Property value set to 'inherit'.
+ SPStyleSrc style_src : 2; // Source (attribute, style attribute, style-sheet). NOT USED YET FIX ME
+
+ // To do: make private after g_asserts removed
+public:
+ SPStyle* style; // Used by SPIPaint, SPIFilter... to find values of other properties
+};
+
+/// Float type internal to SPStyle. (Only 'stroke-miterlimit')
+class SPIFloat : public SPIBase
+{
+
+public:
+ SPIFloat()
+ : SPIBase( "anonymous_float" ),
+ value(0.0)
+ {}
+
+ SPIFloat( Glib::ustring const &name, float value_default = 0.0 )
+ : SPIBase( name ),
+ value(value_default),
+ value_default(value_default)
+ {}
+
+ virtual ~SPIFloat() {}
+ virtual void read( gchar const *str );
+ virtual const Glib::ustring write( guint const flags = SP_STYLE_FLAG_IFSET,
+ SPIBase const *const base = NULL ) const;
+ virtual void clear() {
+ SPIBase::clear();
+ value = value_default;
+ }
+
+ virtual void cascade( const SPIBase* const parent );
+ virtual void merge( const SPIBase* const parent );
+
+ SPIFloat& operator=(const SPIFloat& rhs) {
+ SPIBase::operator=(rhs);
+ value = rhs.value;
+ value_default = rhs.value_default;
+ return *this;
+ }
+
+ virtual bool operator==(const SPIBase& rhs);
+ virtual bool operator!=(const SPIBase& rhs) {
+ return !(*this == rhs);
+ }
+
+ // To do: make private
+public:
float value;
+
+private:
+ float value_default;
};
/*
@@ -60,45 +259,61 @@ static const unsigned SP_SCALE24_MAX = 0xff0000;
/** Returns a scale24 for the product of two scale24 values. */
#define SP_SCALE24_MUL(_v1, _v2) unsigned((double)(_v1) * (_v2) / SP_SCALE24_MAX + .5)
+
/// 24 bit data type internal to SPStyle.
-struct SPIScale24 {
- unsigned set : 1;
- unsigned inherit : 1;
- unsigned value : 24;
-};
+// Used only for opacity, fill-opacity, stroke-opacity.
+// Opacity does not inherit but stroke-opacity and fill-opacity do.
+class SPIScale24 : public SPIBase
+{
-/// Int type internal to SPStyle.
-struct SPIInt {
- unsigned set : 1;
- unsigned inherit : 1;
- unsigned data : 30;
- int value;
-};
+public:
+ SPIScale24()
+ : SPIBase( "anonymous_scale24" ),
+ value(0)
+ {}
-/// Short type internal to SPStyle.
-struct SPIShort {
- unsigned set : 1;
- unsigned inherit : 1;
- unsigned data : 14;
- int value : 16;
-};
+ SPIScale24( Glib::ustring const &name, unsigned value = 0, bool inherits = true )
+ : SPIBase( name, inherits ),
+ value(value),
+ value_default(value)
+ {}
-/// Enum type internal to SPStyle.
-struct SPIEnum {
- unsigned set : 1;
- unsigned inherit : 1;
- unsigned value : 8;
- unsigned computed : 8;
-};
+ virtual ~SPIScale24()
+ {}
-/// String type internal to SPStyle.
-struct SPIString {
- unsigned set : 1;
- unsigned inherit : 1;
- unsigned data : 30;
- gchar *value;
+ virtual void read( gchar const *str );
+ virtual const Glib::ustring write( guint const flags = SP_STYLE_FLAG_IFSET,
+ SPIBase const *const base = NULL ) const;
+ virtual void clear() {
+ SPIBase::clear();
+ value = value_default;
+ }
+
+ virtual void cascade( const SPIBase* const parent );
+ virtual void merge( const SPIBase* const parent );
+
+ SPIScale24& operator=(const SPIScale24& rhs) {
+ SPIBase::operator=(rhs);
+ value = rhs.value;
+ value_default = rhs.value_default;
+ return *this;
+ }
+
+ virtual bool operator==(const SPIBase& rhs);
+ virtual bool operator!=(const SPIBase& rhs) {
+ return !(*this == rhs);
+ }
+
+
+ // To do: make private
+public:
+ unsigned value : 24;
+
+private:
+ unsigned value_default : 24;
};
+
enum SPCSSUnit {
SP_CSS_UNIT_NONE,
SP_CSS_UNIT_PX,
@@ -112,57 +327,401 @@ enum SPCSSUnit {
SP_CSS_UNIT_PERCENT
};
+
/// Length type internal to SPStyle.
-struct SPILength {
- unsigned set : 1;
- unsigned inherit : 1;
+// Needs access to 'font-size' and 'font-family' for computed values.
+// Used for 'stroke-width' 'stroke-dash-offset' ('none' not handled), text-indent
+class SPILength : public SPIBase
+{
+
+public:
+ SPILength()
+ : SPIBase( "anonymous_length" ),
+ unit(SP_CSS_UNIT_NONE),
+ value(0),
+ computed(0)
+ {}
+
+ SPILength( Glib::ustring const &name, unsigned value = 0 )
+ : SPIBase( name ),
+ unit(SP_CSS_UNIT_NONE),
+ value(value),
+ computed(value),
+ value_default(value)
+ {}
+
+ virtual ~SPILength()
+ {}
+
+ virtual void read( gchar const *str );
+ virtual const Glib::ustring write( guint const flags = SP_STYLE_FLAG_IFSET,
+ SPIBase const *const base = NULL ) const;
+ virtual void clear() {
+ SPIBase::clear();
+ unit = SP_CSS_UNIT_NONE, value = value_default;
+ computed = value_default;
+ }
+
+ virtual void cascade( const SPIBase* const parent );
+ virtual void merge( const SPIBase* const parent );
+
+ SPILength& operator=(const SPILength& rhs) {
+ SPIBase::operator=(rhs);
+ unit = rhs.unit;
+ value = rhs.value;
+ computed = rhs.computed;
+ value_default = rhs.value_default;
+ return *this;
+ }
+
+ virtual bool operator==(const SPIBase& rhs);
+ virtual bool operator!=(const SPIBase& rhs) {
+ return !(*this == rhs);
+ }
+
+ // To do: make private
+public:
unsigned unit : 4;
float value;
float computed;
+
+private:
+ float value_default;
};
-#define SP_STYLE_FILL_SERVER(s) ((const_cast<SPStyle *> (s))->getFillPaintServer())
-#define SP_STYLE_STROKE_SERVER(s) ((const_cast<SPStyle *> (s))->getStrokePaintServer())
-/// Paint type internal to SPStyle.
-struct SPIPaint {
- unsigned int set : 1; //c++ bitfields are used here as opposed to bools to reduce memory consumption, see http://tinyurl.com/cswh6mq
- unsigned int inherit : 1;
- unsigned int currentcolor : 1;
- unsigned int colorSet : 1;
- unsigned int noneSet : 1;
+/// Extended length type internal to SPStyle.
+// Used for: line-height, letter-spacing, word-spacing
+class SPILengthOrNormal : public SPILength
+{
+
+public:
+ SPILengthOrNormal()
+ : SPILength( "anonymous_length" ),
+ normal(true)
+ {}
+
+ SPILengthOrNormal( Glib::ustring const &name, unsigned value = 0 )
+ : SPILength( name, value ),
+ normal(true)
+ {}
+
+ virtual ~SPILengthOrNormal()
+ {}
+
+ virtual void read( gchar const *str );
+ virtual const Glib::ustring write( guint const flags = SP_STYLE_FLAG_IFSET,
+ SPIBase const *const base = NULL ) const;
+ virtual void clear() {
+ SPILength::clear();
+ normal = true;
+ }
+
+ virtual void cascade( const SPIBase* const parent );
+ virtual void merge( const SPIBase* const parent );
+
+ SPILengthOrNormal& operator=(const SPILengthOrNormal& rhs) {
+ SPILength::operator=(rhs);
+ normal = rhs.normal;
+ return *this;
+ }
+
+ virtual bool operator==(const SPIBase& rhs);
+ virtual bool operator!=(const SPIBase& rhs) {
+ return !(*this == rhs);
+ }
+
+ // To do: make private
+public:
+ bool normal : 1;
+};
+
+
+/// Enum type internal to SPStyle.
+// Used for many properties. 'font-stretch' and 'font-weight' must be special cased.
+class SPIEnum : public SPIBase
+{
+
+public:
+ SPIEnum() :
+ SPIBase( "anonymous_enum" ),
+ enums( NULL ),
+ value(0),
+ computed(0)
+ {}
+
+ SPIEnum( Glib::ustring const &name, SPStyleEnum const *enums, unsigned value = 0, bool inherits = true ) :
+ SPIBase( name, inherits ),
+ enums( enums ),
+ value(value),
+ computed(value),
+ value_default(value),
+ computed_default(value)
+ {}
+
+ // Following is needed for font-weight
+ SPIEnum( Glib::ustring const &name, SPStyleEnum const *enums, SPCSSFontWeight value, SPCSSFontWeight computed ) :
+ SPIBase( name ),
+ enums( enums ),
+ value(value),
+ computed(computed),
+ value_default(value),
+ computed_default(computed)
+ {}
+
+ virtual ~SPIEnum()
+ {}
+
+ virtual void read( gchar const *str );
+ virtual const Glib::ustring write( guint const flags = SP_STYLE_FLAG_IFSET,
+ SPIBase const *const base = NULL ) const;
+ virtual void clear() {
+ SPIBase::clear();
+ value = value_default, computed = computed_default;
+ }
+
+ virtual void cascade( const SPIBase* const parent );
+ virtual void merge( const SPIBase* const parent );
+
+ SPIEnum& operator=(const SPIEnum& rhs) {
+ SPIBase::operator=(rhs);
+ value = rhs.value;
+ computed = rhs.computed;
+ value_default = rhs.value_default;
+ computed_default = rhs.computed_default;
+ return *this;
+ }
+
+ virtual bool operator==(const SPIBase& rhs);
+ virtual bool operator!=(const SPIBase& rhs) {
+ return !(*this == rhs);
+ }
+
+ // To do: make private
+public:
+ SPStyleEnum const *enums;
+
+ unsigned value : 8;
+ unsigned computed: 8;
+
+private:
+ unsigned value_default : 8;
+ unsigned computed_default: 8; // for font-weight
+};
+
+
+/// String type internal to SPStyle.
+// Used for 'marker', ..., 'font', 'font-family', 'inkscape-font-specification'
+class SPIString : public SPIBase
+{
+
+public:
+ SPIString()
+ : SPIBase( "anonymous_string" ),
+ value(NULL)
+ {}
+
+ // TODO probably want to avoid gchar* and c-style strings.
+ SPIString( Glib::ustring const &name, gchar const* value_default_in = NULL )
+ : SPIBase( name ),
+ value(NULL),
+ value_default(value_default_in ? g_strdup(value_default_in) : NULL)
+ {}
+
+ virtual ~SPIString() {
+ g_free(value);
+ g_free(value_default);
+ }
+
+ virtual void read( gchar const *str );
+ virtual const Glib::ustring write( guint const flags = SP_STYLE_FLAG_IFSET,
+ SPIBase const *const base = NULL ) const;
+ virtual void clear(); // TODO check about value and value_default
+ virtual void cascade( const SPIBase* const parent );
+ virtual void merge( const SPIBase* const parent );
+
+ SPIString& operator=(const SPIString& rhs) {
+ SPIBase::operator=(rhs);
+ g_free(value);
+ g_free(value_default);
+ value = rhs.value ? g_strdup(rhs.value) : NULL;
+ value_default = rhs.value_default ? g_strdup(rhs.value_default) : NULL;
+ return *this;
+ }
+
+ virtual bool operator==(const SPIBase& rhs);
+ virtual bool operator!=(const SPIBase& rhs) {
+ return !(*this == rhs);
+ }
+
+ // To do: make private, convert value to Glib::ustring
+public:
+ gchar *value;
+ gchar *value_default;
+};
+
+/// Color type interal to SPStyle, FIXME Add string value to store SVG named color.
+class SPIColor : public SPIBase
+{
+
+public:
+ SPIColor()
+ : SPIBase( "anonymous_color" ),
+ currentcolor(false) {
+ value.color.set(0);
+ }
+
+ SPIColor( Glib::ustring const &name )
+ : SPIBase( name ),
+ currentcolor(false) {
+ value.color.set(0);
+ }
+
+ virtual ~SPIColor()
+ {}
+
+ virtual void read( gchar const *str );
+ virtual const Glib::ustring write( guint const flags = SP_STYLE_FLAG_IFSET,
+ SPIBase const *const base = NULL ) const;
+ virtual void clear() {
+ SPIBase::clear();
+ value.color.set(0);
+ }
+
+ virtual void cascade( const SPIBase* const parent );
+ virtual void merge( const SPIBase* const parent );
+
+ SPIColor& operator=(const SPIColor& rhs) {
+ SPIBase::operator=(rhs);
+ currentcolor = rhs.currentcolor;
+ value.color = rhs.value.color;
+ return *this;
+ }
+
+ virtual bool operator==(const SPIBase& rhs);
+ virtual bool operator!=(const SPIBase& rhs) {
+ return !(*this == rhs);
+ }
+
+ void setColor( float r, float g, float b ) {
+ value.color.set( r, g, b );
+ }
+
+ void setColor( guint32 val ) {
+ value.color.set( val );
+ }
+
+ void setColor( SPColor const& color ) {
+ value.color = color;
+ }
+
+public:
+ bool currentcolor : 1;
+ // FIXME: remove structure and derive SPIPaint from this class.
struct {
- SPPaintServerReference *href;
SPColor color;
} value;
+};
- SPIPaint();
- bool isSet() const { return true; /* set || colorSet*/}
- bool isSameType( SPIPaint const & other ) const {return (isPaintserver() == other.isPaintserver()) && (colorSet == other.colorSet) && (currentcolor == other.currentcolor);}
- bool isNoneSet() const {return noneSet;}
+#define SP_STYLE_FILL_SERVER(s) ((const_cast<SPStyle *> (s))->getFillPaintServer())
+#define SP_STYLE_STROKE_SERVER(s) ((const_cast<SPStyle *> (s))->getStrokePaintServer())
- bool isNone() const {return !currentcolor && !colorSet && !isPaintserver();} // TODO refine
- bool isColor() const {return colorSet && !isPaintserver();}
- bool isPaintserver() const {return (value.href) ? value.href->getObject():0;}
+/// Paint type internal to SPStyle.
+class SPIPaint : public SPIBase
+{
- void clear();
+public:
+ SPIPaint()
+ : SPIBase( "anonymous_paint" ),
+ currentcolor(false),
+ colorSet(false),
+ noneSet(false) {
+ value.href = NULL;
+ clear();
+ }
- void setColor( float r, float g, float b ) {value.color.set( r, g, b ); colorSet = true;}
- void setColor( guint32 val ) {value.color.set( val ); colorSet = true;}
- void setColor( SPColor const& color ) {value.color = color; colorSet = true;}
+ SPIPaint( Glib::ustring const &name )
+ : SPIBase( name ),
+ currentcolor(false),
+ colorSet(false),
+ noneSet(false) {
+ value.href = NULL;
+ clear(); // Sets defaults
+ }
- void read( gchar const *str, SPStyle &tyle, SPDocument *document = 0);
-};
+ virtual ~SPIPaint(); // Clear and delete href.
+ virtual void read( gchar const *str );
+ virtual void read( gchar const *str, SPStyle &style, SPDocument *document = 0);
+ virtual const Glib::ustring write( guint const flags = SP_STYLE_FLAG_IFSET,
+ SPIBase const *const base = NULL ) const;
+ virtual void clear();
+ virtual void reset( bool init ); // Used internally when reading or cascading
+ virtual void cascade( const SPIBase* const parent );
+ virtual void merge( const SPIBase* const parent );
-class SPIDashArray {
- public:
- unsigned set : 1;
- unsigned inherit : 1;
- std::vector<double> values;
+ SPIPaint& operator=(const SPIPaint& rhs) {
+ SPIBase::operator=(rhs);
+ currentcolor = rhs.currentcolor;
+ colorSet = rhs.colorSet;
+ noneSet = rhs.noneSet;
+ value.color = rhs.value.color;
+ value.href = rhs.value.href;
+ return *this;
+ }
+
+ virtual bool operator==(const SPIBase& rhs);
+ virtual bool operator!=(const SPIBase& rhs) {
+ return !(*this == rhs);
+ }
+
+ bool isSameType( SPIPaint const & other ) const {
+ return (isPaintserver() == other.isPaintserver()) && (colorSet == other.colorSet) && (currentcolor == other.currentcolor);
+ }
+
+ bool isNoneSet() const {
+ return noneSet;
+ }
+
+ bool isNone() const {
+ return !currentcolor && !colorSet && !isPaintserver();
+ } // TODO refine
+
+ bool isColor() const {
+ return colorSet && !isPaintserver();
+ }
+
+ bool isPaintserver() const {
+ return (value.href) ? value.href->getObject() : 0;
+ }
+
+ void setColor( float r, float g, float b ) {
+ value.color.set( r, g, b ); colorSet = true;
+ }
+
+ void setColor( guint32 val ) {
+ value.color.set( val ); colorSet = true;
+ }
+
+ void setColor( SPColor const& color ) {
+ value.color = color; colorSet = true;
+ }
+
+ void setNone() {noneSet = true; colorSet=false;}
+
+ // To do: make private
+public:
+ bool currentcolor : 1;
+ bool colorSet : 1;
+ bool noneSet : 1;
+ struct {
+ SPPaintServerReference *href;
+ SPColor color;
+ } value;
};
+
// SVG 2
enum SPPaintOrderLayer {
SP_CSS_PAINT_ORDER_NORMAL,
@@ -171,54 +730,295 @@ enum SPPaintOrderLayer {
SP_CSS_PAINT_ORDER_MARKER
};
+// Normal maybe should be moved out as is done in other classes.
+// This could be replaced by a generic enum class where multiple keywords are allowed and
+// where order matters (in contrast to 'text-decoration-line' where order does not matter).
+
+// Each layer represents a layer of paint which can be a fill, a stroke, or markers.
const size_t PAINT_ORDER_LAYERS = 3;
-struct SPIPaintOrder {
- unsigned set : 1;
- unsigned inherit : 1;
+
+/// Paint order type internal to SPStyle
+class SPIPaintOrder : public SPIBase
+{
+
+public:
+ SPIPaintOrder()
+ : SPIBase( "paint-order" ),
+ value(NULL) {
+ this->clear();
+ }
+
+ virtual ~SPIPaintOrder() {
+ g_free( value );
+ }
+
+ virtual void read( gchar const *str );
+ virtual const Glib::ustring write( guint const flags = SP_STYLE_FLAG_IFSET,
+ SPIBase const *const base = NULL ) const;
+ virtual void clear() {
+ SPIBase::clear();
+ for( unsigned i = 0; i < PAINT_ORDER_LAYERS; ++i ) {
+ layer[i] = SP_CSS_PAINT_ORDER_NORMAL;
+ layer_set[i] = false;
+ }
+ g_free(value);
+ value = NULL;
+ }
+ virtual void cascade( const SPIBase* const parent );
+ virtual void merge( const SPIBase* const parent );
+
+ SPIPaintOrder& operator=(const SPIPaintOrder& rhs) {
+ SPIBase::operator=(rhs);
+ for( unsigned i = 0; i < PAINT_ORDER_LAYERS; ++i ) {
+ layer[i] = rhs.layer[i];
+ layer_set[i] = rhs.layer_set[i];
+ }
+ g_free(value);
+ value = g_strdup(rhs.value);
+ return *this;
+ }
+
+ virtual bool operator==(const SPIBase& rhs);
+ virtual bool operator!=(const SPIBase& rhs) {
+ return !(*this == rhs);
+ }
+
+
+ // To do: make private
+public:
SPPaintOrderLayer layer[PAINT_ORDER_LAYERS];
bool layer_set[PAINT_ORDER_LAYERS];
gchar *value; // Raw string
};
+
/// Filter type internal to SPStyle
-struct SPIFilter {
- unsigned set : 1;
- unsigned inherit : 1;
+class SPIDashArray : public SPIBase
+{
+
+public:
+ SPIDashArray()
+ : SPIBase( "stroke-dasharray" )
+ {} // Only one instance of SPIDashArray
+
+ virtual ~SPIDashArray()
+ {}
+
+ virtual void read( gchar const *str );
+ virtual const Glib::ustring write( guint const flags = SP_STYLE_FLAG_IFSET,
+ SPIBase const *const base = NULL ) const;
+ virtual void clear() {
+ SPIBase::clear();
+ values.clear();
+ }
+
+ virtual void cascade( const SPIBase* const parent );
+ virtual void merge( const SPIBase* const parent );
+
+ SPIDashArray& operator=(const SPIDashArray& rhs) {
+ SPIBase::operator=(rhs);
+ values = rhs.values;
+ return *this;
+ }
+
+ virtual bool operator==(const SPIBase& rhs);
+ virtual bool operator!=(const SPIBase& rhs) {
+ return !(*this == rhs);
+ }
+
+
+ // To do: make private, change double to SVGLength
+public:
+ std::vector<double> values;
+};
+
+/// Filter type internal to SPStyle
+class SPIFilter : public SPIBase
+{
+
+public:
+ SPIFilter()
+ : SPIBase( "filter", false ),
+ href(NULL)
+ {}
+
+ virtual ~SPIFilter();
+ virtual void read( gchar const *str );
+ virtual const Glib::ustring write( guint const flags = SP_STYLE_FLAG_IFSET,
+ SPIBase const *const base = NULL ) const;
+ virtual void clear();
+ virtual void cascade( const SPIBase* const parent );
+ virtual void merge( const SPIBase* const parent );
+
+ SPIFilter& operator=(const SPIFilter& rhs) {
+ SPIBase::operator=(rhs);
+ href = rhs.href;
+ return *this;
+ }
+
+ virtual bool operator==(const SPIBase& rhs);
+ virtual bool operator!=(const SPIBase& rhs) {
+ return !(*this == rhs);
+ }
+
+ // To do: make private
+public:
SPFilterReference *href;
};
+
+
enum {
SP_FONT_SIZE_LITERAL,
SP_FONT_SIZE_LENGTH,
SP_FONT_SIZE_PERCENTAGE
};
-enum {
- SP_BASELINE_SHIFT_LITERAL,
- SP_BASELINE_SHIFT_LENGTH,
- SP_BASELINE_SHIFT_PERCENTAGE
-};
+/// Fontsize type internal to SPStyle (also used by libnrtype/Layout-TNG-Input.cpp).
+class SPIFontSize : public SPIBase
+{
+public:
+ SPIFontSize()
+ : SPIBase( "font-size" ) {
+ this->clear();
+ }
-#define SP_STYLE_FLAG_IFSET (1 << 0)
-#define SP_STYLE_FLAG_IFDIFF (1 << 1)
-#define SP_STYLE_FLAG_ALWAYS (1 << 2)
+ virtual ~SPIFontSize()
+ {}
-/// Fontsize type internal to SPStyle (also used by libnrtype/Layout-TNG-Input.cpp).
-struct SPIFontSize {
- unsigned set : 1;
- unsigned inherit : 1;
+ virtual void read( gchar const *str );
+ virtual const Glib::ustring write( guint const flags = SP_STYLE_FLAG_IFSET,
+ SPIBase const *const base = NULL ) const;
+ virtual void clear() {
+ SPIBase::clear();
+ type = SP_FONT_SIZE_LITERAL, unit = SP_CSS_UNIT_NONE,
+ literal = SP_CSS_FONT_SIZE_MEDIUM, value = 12.0, computed = 12.0;
+ }
+
+ virtual void cascade( const SPIBase* const parent );
+ virtual void merge( const SPIBase* const parent );
+
+ SPIFontSize& operator=(const SPIFontSize& rhs) {
+ SPIBase::operator=(rhs);
+ type = rhs.type;
+ unit = rhs.unit;
+ literal = rhs.literal;
+ value = rhs.value;
+ computed = rhs.computed;
+ return *this;
+ }
+
+ virtual bool operator==(const SPIBase& rhs);
+ virtual bool operator!=(const SPIBase& rhs) {
+ return !(*this == rhs);
+ }
+
+public:
+ static float const font_size_default;
+
+ // To do: make private
+public:
unsigned type : 2;
unsigned unit : 4;
- unsigned literal: 4;
+ unsigned literal : 4;
float value;
float computed;
+
+private:
+ double relative_fraction() const;
+ static float const font_size_table[];
};
-/// Baseline shift type internal to SPStyle.
-struct SPIBaselineShift {
- unsigned set : 1;
- unsigned inherit : 1;
+
+/// Font type internal to SPStyle ('font' shorthand)
+class SPIFont : public SPIBase
+{
+
+public:
+ SPIFont()
+ : SPIBase( "font" )
+ {}
+
+ virtual ~SPIFont()
+ {}
+
+ virtual void read( gchar const *str );
+ virtual const Glib::ustring write( guint const flags = SP_STYLE_FLAG_IFSET,
+ SPIBase const *const base = NULL ) const;
+ virtual void clear() {
+ SPIBase::clear();
+ }
+
+ virtual void cascade( const SPIBase* const /*parent*/ )
+ {} // Done in dependent properties
+
+ virtual void merge( const SPIBase* const /*parent*/ )
+ {}
+
+ SPIFont& operator=(const SPIFont& rhs) {
+ SPIBase::operator=(rhs);
+ return *this;
+ }
+
+ virtual bool operator==(const SPIBase& rhs);
+ virtual bool operator!=(const SPIBase& rhs) {
+ return !(*this == rhs);
+ }
+};
+
+
+enum {
+ SP_BASELINE_SHIFT_LITERAL,
+ SP_BASELINE_SHIFT_LENGTH,
+ SP_BASELINE_SHIFT_PERCENTAGE
+};
+
+/// Baseline shift type internal to SPStyle. (This is actually just like SPIFontSize)
+class SPIBaselineShift : public SPIBase
+{
+
+public:
+ SPIBaselineShift()
+ : SPIBase( "baseline-shift", false ) {
+ this->clear();
+ }
+
+ virtual ~SPIBaselineShift()
+ {}
+
+ virtual void read( gchar const *str );
+ virtual const Glib::ustring write( guint const flags = SP_STYLE_FLAG_IFSET,
+ SPIBase const *const base = NULL ) const;
+ virtual void clear() {
+ SPIBase::clear();
+ type=SP_BASELINE_SHIFT_LITERAL, unit=SP_CSS_UNIT_NONE,
+ literal = SP_CSS_BASELINE_SHIFT_BASELINE, value = 0.0, computed = 0.0;
+ }
+
+ virtual void cascade( const SPIBase* const parent );
+ virtual void merge( const SPIBase* const parent );
+
+ SPIBaselineShift& operator=(const SPIBaselineShift& rhs) {
+ SPIBase::operator=(rhs);
+ type = rhs.type;
+ unit = rhs.unit;
+ literal = rhs.literal;
+ value = rhs.value;
+ computed = rhs.computed;
+ return *this;
+ }
+
+ // This is not used but we have it for completeness, it has not been tested.
+ virtual bool operator==(const SPIBase& rhs);
+ virtual bool operator!=(const SPIBase& rhs) {
+ return !(*this == rhs);
+ }
+
+ bool isZero() const;
+
+ // To do: make private
+public:
unsigned type : 2;
unsigned unit : 4;
unsigned literal: 2;
@@ -227,38 +1027,152 @@ struct SPIBaselineShift {
};
// CSS 2. Changes in CSS 3, where description is for TextDecorationLine, NOT TextDecoration
-/// Text decoration type internal to SPStyle.
-struct SPITextDecorationLine {
- unsigned set : 1;
- unsigned inherit : 1;
- unsigned underline : 1;
- unsigned overline : 1;
- unsigned line_through : 1;
- unsigned blink : 1; // "Conforming user agents are not required to support this value." yay!
+// See http://www.w3.org/TR/css-text-decor-3/
+
+// CSS3 2.2
+/// Text decoration line type internal to SPStyle. THIS SHOULD BE A GENERIC CLASS
+class SPITextDecorationLine : public SPIBase
+{
+
+public:
+ SPITextDecorationLine()
+ : SPIBase( "text-decoration-line" ) {
+ this->clear();
+ }
+
+ virtual ~SPITextDecorationLine()
+ {}
+
+ virtual void read( gchar const *str );
+ virtual const Glib::ustring write( guint const flags = SP_STYLE_FLAG_IFSET,
+ SPIBase const *const base = NULL ) const;
+ virtual void clear() {
+ SPIBase::clear();
+ underline = false, overline = false, line_through = false, blink = false;
+ }
+
+ virtual void cascade( const SPIBase* const parent );
+ virtual void merge( const SPIBase* const parent );
+
+ SPITextDecorationLine& operator=(const SPITextDecorationLine& rhs) {
+ SPIBase::operator=(rhs);
+ underline = rhs.underline;
+ overline = rhs.overline;
+ line_through = rhs.line_through;
+ blink = rhs.blink;
+ return *this;
+ }
+
+ virtual bool operator==(const SPIBase& rhs);
+ virtual bool operator!=(const SPIBase& rhs) {
+ return !(*this == rhs);
+ }
+
+ // To do: make private
+public:
+ bool underline : 1;
+ bool overline : 1;
+ bool line_through : 1;
+ bool blink : 1; // "Conforming user agents are not required to support this value." yay!
};
// CSS3 2.2
-/// Text decoration style type internal to SPStyle.
-struct SPITextDecorationStyle {
- unsigned set : 1;
- unsigned inherit : 1;
- unsigned solid : 1;
- unsigned isdouble : 1; // cannot use "double" as it is a reserved keyword
- unsigned dotted : 1;
- unsigned dashed : 1;
- unsigned wavy : 1;
+/// Text decoration style type internal to SPStyle. THIS SHOULD JUST BE SPIEnum!
+class SPITextDecorationStyle : public SPIBase
+{
+
+public:
+ SPITextDecorationStyle()
+ : SPIBase( "text-decoration-style" ) {
+ this->clear();
+ }
+
+ virtual ~SPITextDecorationStyle()
+ {}
+
+ virtual void read( gchar const *str );
+ virtual const Glib::ustring write( guint const flags = SP_STYLE_FLAG_IFSET,
+ SPIBase const *const base = NULL ) const;
+ virtual void clear() {
+ SPIBase::clear();
+ solid = true, isdouble = false, dotted = false, dashed = false, wavy = false;
+ }
+
+ virtual void cascade( const SPIBase* const parent );
+ virtual void merge( const SPIBase* const parent );
+
+ SPITextDecorationStyle& operator=(const SPITextDecorationStyle& rhs) {
+ SPIBase::operator=(rhs);
+ solid = rhs.solid;
+ isdouble = rhs.isdouble;
+ dotted = rhs.dotted;
+ dashed = rhs.dashed;
+ wavy = rhs.wavy;
+ return *this;
+ }
+
+ virtual bool operator==(const SPIBase& rhs);
+ virtual bool operator!=(const SPIBase& rhs) {
+ return !(*this == rhs);
+ }
+
+ // To do: make private
+public:
+ bool solid : 1;
+ bool isdouble : 1; // cannot use "double" as it is a reserved keyword
+ bool dotted : 1;
+ bool dashed : 1;
+ bool wavy : 1;
};
-/// Extended length type internal to SPStyle.
-struct SPILengthOrNormal {
- unsigned set : 1;
- unsigned inherit : 1;
- unsigned normal : 1;
- unsigned unit : 4;
- float value;
- float computed;
+
+
+// This class reads in both CSS2 and CSS3 'text-decoration' property. It passes the line, style,
+// and color parts to the appropriate CSS3 long-hand classes for reading and storing values. When
+// writing out data, we write all four properties, with 'text-decoration' being written out with
+// the CSS2 format. This allows CSS1/CSS2 renderers to at least render lines, even if they are not
+// the right style. (See http://www.w3.org/TR/css-text-decor-3/#text-decoration-property )
+
+/// Text decoration type internal to SPStyle.
+class SPITextDecoration : public SPIBase
+{
+
+public:
+ SPITextDecoration()
+ : SPIBase( "text-decoration" ),
+ style_td( NULL )
+ {}
+
+ virtual ~SPITextDecoration()
+ {}
+
+ virtual void read( gchar const *str );
+ virtual const Glib::ustring write( guint const flags = SP_STYLE_FLAG_IFSET,
+ SPIBase const *const base = NULL ) const;
+ virtual void clear() {
+ SPIBase::clear();
+ style_td = NULL;
+ }
+
+ virtual void cascade( const SPIBase* const parent );
+ virtual void merge( const SPIBase* const parent );
+
+ SPITextDecoration& operator=(const SPITextDecoration& rhs) {
+ SPIBase::operator=(rhs);
+ return *this;
+ }
+
+ // Use CSS2 value
+ virtual bool operator==(const SPIBase& rhs);
+ virtual bool operator!=(const SPIBase& rhs) {
+ return !(*this == rhs);
+ }
+
+public:
+ SPStyle* style_td; // Style to be used for drawing CSS2 text decorations
};
+
// These are used to implement text_decoration. The values are not saved to or read from SVG file
struct SPITextDecorationData {
float phase_length; // length along text line,used for phase for dot/dash/wavy
@@ -274,22 +1188,6 @@ struct SPITextDecorationData {
float line_through_position;
};
-struct SPTextStyle;
-
-/// An SPTextStyle has a refcount, a font family, and a font name.
-struct SPTextStyle {
- int refcount;
-
- /* CSS font properties */
- SPIString font_family;
-
- /* Full font name, as font_factory::ConstructFontSpecification would give */
- SPIString font_specification;
-
- /** \todo fixme: The 'font' property is ugly, and not working (lauris) */
- SPIString font;
-};
-
#endif // SEEN_SP_STYLE_INTERNAL_H
diff --git a/src/style-test.h b/src/style-test.h
index c88c1c30a..e14ed4db7 100644
--- a/src/style-test.h
+++ b/src/style-test.h
@@ -48,6 +48,7 @@ public:
// ---------------------------------------------------------------
// ---------------------------------------------------------------
+ // Reading and writing style string
void testOne()
{
struct TestCase {
@@ -95,20 +96,38 @@ public:
TestCase("overflow:visible"), // SPIEnum
TestCase("overflow:auto"), // SPIEnum
- // Not directly read
+ TestCase("color:#ff0000"),
+ TestCase("color:blue", "color:#0000ff"),
+ // TestCase("color:currentColor"), SVG 1.1 does not allow color value 'currentColor'
+
+ // Font shorthand
TestCase("font:bold 12px Arial",
- "font-size:12px;font-style:normal;font-variant:normal;font-weight:bold;font-family:Arial"),
- // line-height not read in
- //TestCase("font:bold 12px/24px 'Times New Roman'",
- // "font-size:12px;font-style:normal;font-variant:normal;font-weight:bold;line-height:24px;font-family:Times New Roman"),
+ "font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:12px;line-height:normal;font-family:Arial"),
+ TestCase("font:bold 12px/24px 'Times New Roman'",
+ "font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:12px;line-height:24px;font-family:\'Times New Roman\'"),
+ // From CSS 3 Fonts (examples):
+ TestCase("font: 12pt/15pt sans-serif",
+ "font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;line-height:15pt;font-family:sans-serif"),
+ TestCase("font: 80% sans-serif",
+ "font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:80.00000119%;line-height:normal;font-family:sans-serif"),
+ TestCase("font: x-large/110% 'new century schoolbook', serif",
+ "font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:x-large;line-height:110.00000238%;font-family:\'new century schoolbook\', serif"),
+ TestCase("font: bold italic large Palatino, serif",
+ "font-style:italic;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:large;line-height:normal;font-family:Palatino, serif"),
+ TestCase("font: normal small-caps 120%/120% fantasy",
+ "font-style:normal;font-variant:small-caps;font-weight:normal;font-stretch:normal;font-size:120.00000477%;line-height:120.00000477%;font-family:fantasy"),
+ TestCase("font: condensed oblique 12pt 'Helvetica Neue', serif;",
+ "font-style:oblique;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:16px;line-height:normal;font-family:\'Helvetica Neue\', serif"),
+
TestCase("font-family:sans-serif"), // SPIString, text_private
TestCase("font-family:Arial"),
- TestCase("font-variant:normal;font-stretch:normal;-inkscape-font-specification:Nimbus Roman No9 L Bold Italic"),
+ // TestCase("font-variant:normal;font-stretch:normal;-inkscape-font-specification:Nimbus Roman No9 L Bold Italic"),
+
// Needs to be fixed (quotes should be around each font-family):
- TestCase("font-family:Georgia, 'Minion Web'","font-family:'Georgia, \"Minion Web\"'"),
+ TestCase("font-family:Georgia, 'Minion Web'","font-family:Georgia, \'Minion Web\'"),
TestCase("font-size:12", "font-size:12px"), // SPIFontSize
TestCase("font-size:12px"),
- TestCase("font-size:12pt", "font-size:15px"),
+ TestCase("font-size:12pt", "font-size:16px"),
TestCase("font-size:medium"),
TestCase("font-size:smaller"),
TestCase("font-style:italic"), // SPIEnum
@@ -121,9 +140,31 @@ public:
// Should be moved down
TestCase("text-indent:12em"), // SPILength?
TestCase("text-align:center"), // SPIEnum
- TestCase("text-decoration: underline"), // SPITextDecoration
- TestCase("text-decoration: underline wavy #0000ff"), // SPITextDecoration CSS3
- TestCase("text-decoration: overline double #ff0000"),
+
+ // SPITextDecoration
+ // The default value for 'text-decoration-color' is 'currentColor', but
+ // we cannot set the default to that value yet. (We need to switch
+ // SPIPaint to SPIColor and then add the ability to set default.)
+ // TestCase("text-decoration: underline",
+ // "text-decoration: underline;text-decoration-line: underline;text-decoration-color:currentColor"),
+ // TestCase("text-decoration: overline underline",
+ // "text-decoration: underline overline;text-decoration-line: underline overline;text-decoration-color:currentColor"),
+
+ TestCase("text-decoration: underline wavy #0000ff",
+ "text-decoration: underline;text-decoration-line: underline;text-decoration-style:wavy;text-decoration-color:#0000ff"),
+ TestCase("text-decoration: double overline underline #ff0000",
+ "text-decoration: underline overline;text-decoration-line: underline overline;text-decoration-style:double;text-decoration-color:#ff0000"),
+
+ // SPITextDecorationLine
+ TestCase("text-decoration-line: underline",
+ "text-decoration: underline;text-decoration-line: underline"),
+
+ // SPITextDecorationStyle
+ TestCase("text-decoration-style:solid"),
+ TestCase("text-decoration-style:dotted"),
+
+ // SPITextDecorationColor
+ TestCase("text-decoration-color:#ff00ff"),
// Should be moved up
TestCase("line-height:24px"), // SPILengthOrNormal
@@ -166,11 +207,13 @@ public:
TestCase("paint-order:stroke"), // SPIPaintOrder
TestCase("paint-order:normal"),
TestCase("paint-order: markers stroke fill", "paint-order:markers stroke fill"),
+
#endif
TestCase(0)
};
for ( gint i = 0; cases[i].src; i++ ) {
+ // std::cout << "Test one: " << i << std::endl;
SPStyle *style = sp_style_new(_doc);
TS_ASSERT(style);
if ( style ) {
@@ -188,10 +231,10 @@ public:
gchar *str0_set = sp_style_write_string( style, SP_STYLE_FLAG_IFSET );
//printf("<<%s>>\n", str0_set);
if ( cases[i].dst ) {
- //std::cout << " " << std::string(str0_set) << " " << std::string(cases[i].dst) << std::endl;
+ // std::cout << " " << std::string(str0_set) << " " << std::string(cases[i].dst) << std::endl;
TS_ASSERT_EQUALS( std::string(str0_set), std::string(cases[i].dst) );
} else {
- //std::cout << " " << std::string(str0_set) << " " << std::string(cases[i].src) << std::endl;
+ // std::cout << " " << std::string(str0_set) << " " << std::string(cases[i].src) << std::endl;
TS_ASSERT_EQUALS( std::string(str0_set), std::string(cases[i].src) );
}
@@ -201,6 +244,273 @@ public:
}
}
+ // Testing operator==
+ void testTwo()
+ {
+ struct TestCase {
+ TestCase(gchar const* src, gchar const* dst, bool match) :
+ src(src), dst(dst), match(match) {}
+ gchar const* src;
+ gchar const* dst;
+ bool match;
+ };
+
+ TestCase cases[] = {
+
+ // SPIFloat
+ TestCase("stroke-miterlimit:4", "stroke-miterlimit:4", true ),
+ TestCase("stroke-miterlimit:4", "stroke-miterlimit:2", false),
+ TestCase("stroke-miterlimit:4", "", true ), // Default
+
+ // SPIScale24
+ TestCase("opacity:0.3", "opacity:0.3", true ),
+ TestCase("opacity:0.3", "opacity:0.6", false),
+ TestCase("opacity:1.0", "", true ), // Default
+
+ // SPILength
+ TestCase("text-indent:3", "text-indent:3", true ),
+ TestCase("text-indent:6", "text-indent:3", false),
+ TestCase("text-indent:6px", "text-indent:3", false),
+ TestCase("text-indent:1px", "text-indent:12pc", false),
+ TestCase("text-indent:2ex", "text-indent:2ex", false),
+
+ // SPILengthOrNormal
+ TestCase("letter-spacing:normal", "letter-spacing:normal", true ),
+ TestCase("letter-spacing:2", "letter-spacing:normal", false),
+ TestCase("letter-spacing:normal", "letter-spacing:2", false),
+ TestCase("letter-spacing:5px", "letter-spacing:5px", true ),
+ TestCase("letter-spacing:10px", "letter-spacing:5px", false),
+ TestCase("letter-spacing:10em", "letter-spacing:10em", false),
+
+ // SPIEnum
+ TestCase("text-anchor:start", "text-anchor:start", true ),
+ TestCase("text-anchor:start", "text-anchor:middle", false),
+ TestCase("text-anchor:start", "", true ), // Default
+ TestCase("text-anchor:start", "text-anchor:junk", true ), // Bad value
+
+ TestCase("font-weight:normal", "font-weight:400", true ),
+ TestCase("font-weight:bold", "font-weight:700", true ),
+
+
+ // SPIString and SPIFontString
+ TestCase("font-family:Arial", "font-family:Arial", true ),
+ TestCase("font-family:A B", "font-family:A B", true ),
+ TestCase("font-family:A B", "font-family:A C", false),
+ // Default is not set by class... value is NULL which cannot be compared
+ // TestCase("font-family:sans-serif", "", true ), // Default
+
+ // SPIColor
+ TestCase("color:blue", "color:blue", true ),
+ TestCase("color:blue", "color:red", false),
+ TestCase("color:red", "color:#ff0000", true ),
+
+ // SPIPaint
+ TestCase("fill:blue", "fill:blue", true ),
+ TestCase("fill:blue", "fill:red", false),
+ TestCase("fill:currentColor", "fill:currentColor", true ),
+ TestCase("fill:url(#xxx)", "fill:url(#xxx)", true ),
+ // Needs URL defined as in test 1
+ //TestCase("fill:url(#xxx)", "fill:url(#yyy)", false),
+
+ // SPIPaintOrder
+ TestCase("paint-order:markers", "paint-order:markers", true ),
+ TestCase("paint-order:markers", "paint-order:stroke", false),
+ //TestCase("paint-order:fill stroke markers", "", true ), // Default
+ TestCase("paint-order:normal", "paint-order:normal", true ),
+ //TestCase("paint-order:fill stroke markers", "paint-order:normal", true ),
+
+ // SPIDashArray
+ TestCase("stroke-dasharray:0 1 2 3","stroke-dasharray:0 1 2 3",true ),
+ TestCase("stroke-dasharray:0 1", "stroke-dasharray:0 2", false),
+
+ // SPIFilter
+
+ // SPIFontSize
+ TestCase("font-size:12px", "font-size:12px", true ),
+ TestCase("font-size:12px", "font-size:24px", false),
+ TestCase("font-size:12ex", "font-size:24ex", false),
+ TestCase("font-size:medium", "font-size:medium", true ),
+ TestCase("font-size:medium", "font-size:large", false),
+
+ // SPIBaselineShift
+ TestCase("baseline-shift:baseline", "baseline-shift:baseline", true ),
+ TestCase("baseline-shift:sub", "baseline-shift:sub", true ),
+ TestCase("baseline-shift:sub", "baseline-shift:super", false),
+ TestCase("baseline-shift:baseline", "baseline-shift:sub", false),
+ TestCase("baseline-shift:10px", "baseline-shift:10px", true ),
+ TestCase("baseline-shift:10px", "baseline-shift:12px", false),
+
+
+ // SPITextDecorationLine
+ TestCase("text-decoration-line:underline", "text-decoration-line:underline", true ),
+ TestCase("text-decoration-line:underline", "text-decoration-line:overline", false),
+ TestCase("text-decoration-line:underline overline", "text-decoration-line:underline overline", true ),
+ TestCase("text-decoration-line:none", "", true ), // Default
+
+
+ // SPITextDecorationStyle
+ TestCase("text-decoration-style:solid", "text-decoration-style:solid", true ),
+ TestCase("text-decoration-style:dotted", "text-decoration-style:solid", false),
+ TestCase("text-decoration-style:solid", "", true ), // Default
+
+ // SPITextDecoration
+ TestCase("text-decoration:underline", "text-decoration:underline", true ),
+ TestCase("text-decoration:underline", "text-decoration:overline", false),
+ TestCase("text-decoration:underline overline","text-decoration:underline overline",true ),
+ TestCase("text-decoration:overline underline","text-decoration:underline overline",true ),
+ // TestCase("text-decoration:none", "text-decoration-color:currentColor", true ), // Default
+
+
+ // Terminate
+ TestCase(0,0,0)
+ };
+ for ( gint i = 0; cases[i].src; i++ ) {
+ // std::cout << "Test two: " << i << std::endl;
+ SPStyle *style_src = sp_style_new(_doc);
+ TS_ASSERT(style_src);
+ SPStyle *style_dst = sp_style_new(_doc);
+ TS_ASSERT(style_dst);
+
+ if ( style_src && style_dst ) {
+ sp_style_merge_from_style_string( style_src, cases[i].src );
+ sp_style_merge_from_style_string( style_dst, cases[i].dst );
+ // std::cout << "Test:" << std::endl;
+ // std::cout << " C: |" << cases[i].src << "| |" << cases[i].dst << "|" << std::endl;
+ // std::cout << " S: |" << style_src->write( SP_STYLE_FLAG_IFSET, NULL ) << "| |"
+ // << style_dst->write( SP_STYLE_FLAG_IFSET, NULL ) << "|" <<std::endl;
+ TS_ASSERT( (*style_src == *style_dst) == cases[i].match );
+ sp_style_unref(style_src);
+ sp_style_unref(style_dst);
+ // std::cout << "End Test\n" << std::endl;
+ }
+ }
+ }
+
+ // Test of cascade
+ void testThree()
+ {
+ struct TestCase {
+ TestCase(gchar const* parent, gchar const* child, gchar const* result) :
+ parent(parent), child(child), result(result) {}
+ gchar const* parent;
+ gchar const* child;
+ gchar const* result;
+ };
+
+ TestCase cases[] = {
+
+ // SPIFloat
+ TestCase("stroke-miterlimit:6", "stroke-miterlimit:2", "stroke-miterlimit:2" ),
+ TestCase("stroke-miterlimit:6", "", "stroke-miterlimit:6" ),
+ TestCase("", "stroke-miterlimit:2", "stroke-miterlimit:2" ),
+
+ // SPIScale24
+ TestCase("opacity:0.3", "opacity:0.3", "opacity:0.3" ),
+ TestCase("opacity:0.3", "opacity:0.6", "opacity:0.6" ),
+ // 'opacity' does not inherit
+ TestCase("opacity:0.3", "", "opacity:1.0" ),
+ TestCase("", "opacity:0.3", "opacity:0.3" ),
+ TestCase("opacity:0.5", "opacity:inherit", "opacity:0.5" ),
+ TestCase("", "", "opacity:1.0" ),
+
+ // SPILength
+ TestCase("text-indent:3", "text-indent:3", "text-indent:3" ),
+ TestCase("text-indent:6", "text-indent:3", "text-indent:3" ),
+ TestCase("text-indent:6px", "text-indent:3", "text-indent:3" ),
+ TestCase("text-indent:1px", "text-indent:12pc", "text-indent:12pc" ),
+ // ex, em cannot be equal
+ //TestCase("text-indent:2ex", "text-indent:2ex", "text-indent:2ex" ),
+ TestCase("text-indent:3", "", "text-indent:3" ),
+ TestCase("text-indent:3", "text-indent:inherit", "text-indent:3" ),
+
+ // SPILengthOrNormal
+ TestCase("letter-spacing:normal", "letter-spacing:normal", "letter-spacing:normal" ),
+ TestCase("letter-spacing:2", "letter-spacing:normal", "letter-spacing:normal" ),
+ TestCase("letter-spacing:normal", "letter-spacing:2", "letter-spacing:2" ),
+ TestCase("letter-spacing:5px", "letter-spacing:5px", "letter-spacing:5px" ),
+ TestCase("letter-spacing:10px", "letter-spacing:5px", "letter-spacing:5px" ),
+ // ex, em cannot be equal
+ // TestCase("letter-spacing:10em", "letter-spacing:10em", "letter-spacing:10em" ),
+
+ // SPIEnum
+ TestCase("text-anchor:start", "text-anchor:start", "text-anchor:start" ),
+ TestCase("text-anchor:start", "text-anchor:middle", "text-anchor:middle" ),
+ TestCase("text-anchor:start", "", "text-anchor:start" ),
+ TestCase("text-anchor:start", "text-anchor:junk", "text-anchor:start" ),
+ TestCase("text-anchor:end", "text-anchor:inherit", "text-anchor:end" ),
+
+ TestCase("font-weight:400", "font-weight:400", "font-weight:400" ),
+ TestCase("font-weight:400", "font-weight:700", "font-weight:700" ),
+ TestCase("font-weight:400", "font-weight:bolder", "font-weight:700" ),
+ TestCase("font-weight:700", "font-weight:bolder", "font-weight:900" ),
+ TestCase("font-weight:400", "font-weight:lighter", "font-weight:100" ),
+ TestCase("font-weight:200", "font-weight:lighter", "font-weight:100" ),
+
+ TestCase("font-stretch:condensed","font-stretch:expanded", "font-stretch:expanded" ),
+ TestCase("font-stretch:condensed","font-stretch:wider", "font-stretch:semi-condensed" ),
+
+ // SPIString and SPIFontString
+
+ // SPIPaint
+
+ // SPIPaintOrder
+
+ // SPIDashArray
+
+ // SPIFilter
+
+ // SPIFontSize
+
+ // SPIBaselineShift
+
+
+ // SPITextDecorationLine
+ TestCase("text-decoration-line:overline", "text-decoration-line:underline",
+ "text-decoration-line:underline" ),
+
+ // SPITextDecorationStyle
+
+ // SPITextDecoration
+
+ // Terminate
+ TestCase(0,0,0)
+ };
+ for ( gint i = 0; cases[i].parent; i++ ) {
+ // std::cout << "Test three: " << i << std::endl;
+ SPStyle *style_parent = sp_style_new(_doc);
+ TS_ASSERT(style_parent);
+ SPStyle *style_child = sp_style_new(_doc);
+ TS_ASSERT(style_child);
+ SPStyle *style_result = sp_style_new(_doc);
+ TS_ASSERT(style_result);
+
+ if ( style_parent && style_child && style_result ) {
+ sp_style_merge_from_style_string( style_parent, cases[i].parent );
+ sp_style_merge_from_style_string( style_child, cases[i].child );
+ sp_style_merge_from_style_string( style_result, cases[i].result );
+ // std::cout << "Test:" << std::endl;
+ // std::cout << " Input: ";
+ // std::cout << " Parent: " << cases[i].parent
+ // << " Child: " << cases[i].child
+ // << " Result: " << cases[i].result << std::endl;
+ // std::cout << " Write: ";
+ // std::cout << " Parent: " << style_parent->write( SP_STYLE_FLAG_IFSET )
+ // << " Child: " << style_child->write( SP_STYLE_FLAG_IFSET )
+ // << " Result: " << style_result->write( SP_STYLE_FLAG_IFSET ) << std::endl;
+
+ //sp_style_merge_from_parent( style_child, style_parent );
+ style_child->cascade( style_parent );
+
+ TS_ASSERT(*style_child == *style_result );
+
+ sp_style_unref(style_child);
+ sp_style_unref(style_parent);
+ sp_style_unref(style_result);
+ // std::cout << "End Test: *************\n" << std::endl;
+ }
+ }
+ }
+
};
diff --git a/src/style.cpp b/src/style.cpp
index bc869b127..a7e50b17a 100644
--- a/src/style.cpp
+++ b/src/style.cpp
@@ -14,6 +14,7 @@
* Copyright (C) 2001 Ximian, Inc.
* Copyright (C) 2005 Monash University
* Copyright (C) 2012 Kris De Gussem
+ * Copyright (C) 2014 Tavmjong Bah
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
@@ -24,6 +25,7 @@
#include <cstring>
#include <string>
+#include <algorithm>
#include "libcroco/cr-sel-eng.h"
#include "xml/croco-node-iface.h"
@@ -56,6 +58,8 @@
#include <2geom/math-utils.h>
+#include <glibmm/regex.h>
+
using Inkscape::CSSOStringStream;
using std::vector;
@@ -65,925 +69,546 @@ using std::vector;
struct SPStyleEnum;
+int SPStyle::_count = 0;
+
/*#########################
## FORWARD DECLARATIONS
#########################*/
-static void sp_style_clear(SPStyle *style);
-
-static void sp_style_merge_property(SPStyle *style, gint id, gchar const *val);
-
-static void sp_style_merge_ipaint(SPStyle *style, SPIPaint *paint, SPIPaint const *parent);
-static void sp_style_merge_ifilter(SPStyle *style, SPIFilter const *parent);
-static void sp_style_read_dash(SPStyle *style, gchar const *str);
-
-static SPTextStyle *sp_text_style_new(void);
-static void sp_text_style_clear(SPTextStyle *ts);
-static SPTextStyle *sp_text_style_unref(SPTextStyle *st);
-static SPTextStyle *sp_text_style_duplicate_unset(SPTextStyle *st);
-static guint sp_text_style_write(gchar *p, guint len, SPTextStyle const *st, guint flags = SP_STYLE_FLAG_IFSET);
-static void sp_style_privatize_text(SPStyle *style);
-
-static void sp_style_read_ifloat(SPIFloat *val, gchar const *str);
-static void sp_style_read_iscale24(SPIScale24 *val, gchar const *str);
-static void sp_style_read_ienum(SPIEnum *val, gchar const *str, SPStyleEnum const *dict, bool can_explicitly_inherit);
-static void sp_style_read_istring(SPIString *val, gchar const *str);
-static void sp_style_read_ilength(SPILength *val, gchar const *str);
-static void sp_style_read_ilengthornormal(SPILengthOrNormal *val, gchar const *str);
-
-static void sp_style_read_ipaintorder(SPIPaintOrder *val, gchar const *str);
-
-static void sp_style_read_itextdecoration(SPITextDecorationLine *line, SPITextDecorationStyle *style, SPIPaint *color, gchar const *str);
-static void sp_style_read_itextdecorationLine(SPITextDecorationLine *line, gchar const *str);
-static void sp_style_read_itextdecorationStyle(SPITextDecorationStyle *style, gchar const *str);
-static void sp_style_read_itextdecorationColor(SPIPaint *color, gchar const *str);
-
-static void sp_style_read_icolor(SPIPaint *paint, gchar const *str, SPStyle *style, SPDocument *document);
-static void sp_style_read_ifontsize(SPIFontSize *val, gchar const *str);
-static void sp_style_read_ibaselineshift(SPIBaselineShift *val, gchar const *str);
-static void sp_style_read_ifilter(gchar const *str, SPStyle *style, SPDocument *document);
-
-static void sp_style_read_penum(SPIEnum *val, Inkscape::XML::Node *repr, gchar const *key, SPStyleEnum const *dict, bool can_explicitly_inherit);
-static void sp_style_read_plength(SPILength *val, Inkscape::XML::Node *repr, gchar const *key);
-static void sp_style_read_pfontsize(SPIFontSize *val, Inkscape::XML::Node *repr, gchar const *key);
-static void sp_style_read_pbaselineshift(SPIBaselineShift *val, Inkscape::XML::Node *repr, gchar const *key);
-static void sp_style_read_pfloat(SPIFloat *val, Inkscape::XML::Node *repr, gchar const *key);
-
-static gint sp_style_write_ifloat(gchar *p, gint len, gchar const *key, SPIFloat const *val, SPIFloat const *base, guint flags);
-static gint sp_style_write_iscale24(gchar *p, gint len, gchar const *key, SPIScale24 const *val, SPIScale24 const *base, guint flags);
-static gint sp_style_write_ienum(gchar *p, gint len, gchar const *key, SPStyleEnum const *dict, SPIEnum const *val, SPIEnum const *base, guint flags);
-static gint sp_style_write_istring(gchar *p, gint len, gchar const *key, SPIString const *val, SPIString const *base, guint flags);
-static gint sp_style_write_ilength(gchar *p, gint len, gchar const *key, SPILength const *val, SPILength const *base, guint flags);
-static gint sp_style_write_ipaint(gchar *b, gint len, gchar const *key, SPIPaint const *paint, SPIPaint const *base, guint flags);
-static gint sp_style_write_ipaintorder(gchar *p, gint len, gchar const *key, SPIPaintOrder const *paint_order, SPIPaintOrder const *base, guint flags);
-static gint sp_style_write_idasharray(gchar *p, gint const len, gchar const *const key, SPIDashArray const *const val, SPIDashArray const *const base, guint const flags);
-
-static gint sp_style_write_ifontsize(gchar *p, gint len, gchar const *key, SPIFontSize const *val, SPIFontSize const *base, guint flags);
-static gint sp_style_write_ibaselineshift(gchar *p, gint len, gchar const *key, SPIBaselineShift const *val, SPIBaselineShift const *base, guint flags);
-static gint sp_style_write_ilengthornormal(gchar *p, gint const len, gchar const *const key, SPILengthOrNormal const *const val, SPILengthOrNormal const *const base, guint const flags);
-static gint sp_style_write_itextdecoration(gchar *p, gint const len, gchar const *const key,
- SPITextDecorationLine const *const line,
- SPITextDecorationStyle const *const style,
- SPIPaint const *const color,
- SPITextDecorationLine const *const baseLine,
- SPITextDecorationStyle const *const baseStyle,
- SPIPaint const *const baseColor,
- guint const flags);
-static gint sp_style_write_ifilter(gchar *b, gint len, gchar const *key, SPIFilter const *filter, SPIFilter const *base, guint flags);
-
-static void sp_style_filter_clear(SPStyle *style);
-
-#define SPS_READ_IENUM_IF_UNSET(v,s,d,i) if (!(v)->set) {sp_style_read_ienum((v), (s), (d), (i));}
-#define SPS_READ_PENUM_IF_UNSET(v,r,k,d,i) if (!(v)->set) {sp_style_read_penum((v), (r), (k), (d), (i));}
-
-#define SPS_READ_ILENGTH_IF_UNSET(v,s) if (!(v)->set) {sp_style_read_ilength((v), (s));}
-#define SPS_READ_PLENGTH_IF_UNSET(v,r,k) if (!(v)->set) {sp_style_read_plength((v), (r), (k));}
-
-#define SPS_READ_PFLOAT_IF_UNSET(v,r,k) if (!(v)->set) {sp_style_read_pfloat((v), (r), (k));}
-
-#define SPS_READ_IFONTSIZE_IF_UNSET(v,s) if (!(v)->set) {sp_style_read_ifontsize((v), (s));}
-#define SPS_READ_PFONTSIZE_IF_UNSET(v,r,k) if (!(v)->set) {sp_style_read_pfontsize((v), (r), (k));}
-
-#define SPS_READ_IBASELINE_SHIFT_IF_UNSET(v,s) if (!(v)->set) {sp_style_read_ibaselineshift((v), (s));}
-#define SPS_READ_PBASELINE_SHIFT_IF_UNSET(v,r,k) if (!(v)->set) {sp_style_read_pbaselineshift((v), (r), (k));}
-
-static void sp_style_merge_from_object_stylesheet(SPStyle *, SPObject const *);
-
-struct SPStyleEnum {
- gchar const *key;
- gint value;
-};
-
-static SPStyleEnum const enum_fill_rule[] = {
- {"nonzero", SP_WIND_RULE_NONZERO},
- {"evenodd", SP_WIND_RULE_EVENODD},
- {NULL, -1}
-};
-
-static SPStyleEnum const enum_stroke_linecap[] = {
- {"butt", SP_STROKE_LINECAP_BUTT},
- {"round", SP_STROKE_LINECAP_ROUND},
- {"square", SP_STROKE_LINECAP_SQUARE},
- {NULL, -1}
-};
-
-static SPStyleEnum const enum_stroke_linejoin[] = {
- {"miter", SP_STROKE_LINEJOIN_MITER},
- {"round", SP_STROKE_LINEJOIN_ROUND},
- {"bevel", SP_STROKE_LINEJOIN_BEVEL},
- {NULL, -1}
-};
-
-static SPStyleEnum const enum_font_style[] = {
- {"normal", SP_CSS_FONT_STYLE_NORMAL},
- {"italic", SP_CSS_FONT_STYLE_ITALIC},
- {"oblique", SP_CSS_FONT_STYLE_OBLIQUE},
- {NULL, -1}
-};
-
-static SPStyleEnum const enum_font_size[] = {
- {"xx-small", SP_CSS_FONT_SIZE_XX_SMALL},
- {"x-small", SP_CSS_FONT_SIZE_X_SMALL},
- {"small", SP_CSS_FONT_SIZE_SMALL},
- {"medium", SP_CSS_FONT_SIZE_MEDIUM},
- {"large", SP_CSS_FONT_SIZE_LARGE},
- {"x-large", SP_CSS_FONT_SIZE_X_LARGE},
- {"xx-large", SP_CSS_FONT_SIZE_XX_LARGE},
- {"smaller", SP_CSS_FONT_SIZE_SMALLER},
- {"larger", SP_CSS_FONT_SIZE_LARGER},
- {NULL, -1}
-};
-
-static SPStyleEnum const enum_font_variant[] = {
- {"normal", SP_CSS_FONT_VARIANT_NORMAL},
- {"small-caps", SP_CSS_FONT_VARIANT_SMALL_CAPS},
- {NULL, -1}
-};
-
-static SPStyleEnum const enum_font_weight[] = {
- {"100", SP_CSS_FONT_WEIGHT_100},
- {"200", SP_CSS_FONT_WEIGHT_200},
- {"300", SP_CSS_FONT_WEIGHT_300},
- {"400", SP_CSS_FONT_WEIGHT_400},
- {"500", SP_CSS_FONT_WEIGHT_500},
- {"600", SP_CSS_FONT_WEIGHT_600},
- {"700", SP_CSS_FONT_WEIGHT_700},
- {"800", SP_CSS_FONT_WEIGHT_800},
- {"900", SP_CSS_FONT_WEIGHT_900},
- {"normal", SP_CSS_FONT_WEIGHT_NORMAL},
- {"bold", SP_CSS_FONT_WEIGHT_BOLD},
- {"lighter", SP_CSS_FONT_WEIGHT_LIGHTER},
- {"bolder", SP_CSS_FONT_WEIGHT_BOLDER},
- {NULL, -1}
-};
-
-static SPStyleEnum const enum_font_stretch[] = {
- {"ultra-condensed", SP_CSS_FONT_STRETCH_ULTRA_CONDENSED},
- {"extra-condensed", SP_CSS_FONT_STRETCH_EXTRA_CONDENSED},
- {"condensed", SP_CSS_FONT_STRETCH_CONDENSED},
- {"semi-condensed", SP_CSS_FONT_STRETCH_SEMI_CONDENSED},
- {"normal", SP_CSS_FONT_STRETCH_NORMAL},
- {"semi-expanded", SP_CSS_FONT_STRETCH_SEMI_EXPANDED},
- {"expanded", SP_CSS_FONT_STRETCH_EXPANDED},
- {"extra-expanded", SP_CSS_FONT_STRETCH_EXTRA_EXPANDED},
- {"ultra-expanded", SP_CSS_FONT_STRETCH_ULTRA_EXPANDED},
- {"narrower", SP_CSS_FONT_STRETCH_NARROWER},
- {"wider", SP_CSS_FONT_STRETCH_WIDER},
- {NULL, -1}
-};
-
-static SPStyleEnum const enum_text_align[] = {
- {"start", SP_CSS_TEXT_ALIGN_START},
- {"end", SP_CSS_TEXT_ALIGN_END},
- {"left", SP_CSS_TEXT_ALIGN_LEFT},
- {"right", SP_CSS_TEXT_ALIGN_RIGHT},
- {"center", SP_CSS_TEXT_ALIGN_CENTER},
- {"justify", SP_CSS_TEXT_ALIGN_JUSTIFY},
- {NULL, -1}
-};
-
-static SPStyleEnum const enum_text_transform[] = {
- {"capitalize", SP_CSS_TEXT_TRANSFORM_CAPITALIZE},
- {"uppercase", SP_CSS_TEXT_TRANSFORM_UPPERCASE},
- {"lowercase", SP_CSS_TEXT_TRANSFORM_LOWERCASE},
- {"none", SP_CSS_TEXT_TRANSFORM_NONE},
- {NULL, -1}
-};
-
-static SPStyleEnum const enum_text_anchor[] = {
- {"start", SP_CSS_TEXT_ANCHOR_START},
- {"middle", SP_CSS_TEXT_ANCHOR_MIDDLE},
- {"end", SP_CSS_TEXT_ANCHOR_END},
- {NULL, -1}
-};
-
-static SPStyleEnum const enum_direction[] = {
- {"ltr", SP_CSS_DIRECTION_LTR},
- {"rtl", SP_CSS_DIRECTION_RTL},
- {NULL, -1}
-};
-
-static SPStyleEnum const enum_block_progression[] = {
- {"tb", SP_CSS_BLOCK_PROGRESSION_TB},
- {"rl", SP_CSS_BLOCK_PROGRESSION_RL},
- {"lr", SP_CSS_BLOCK_PROGRESSION_LR},
- {NULL, -1}
-};
-
-static SPStyleEnum const enum_writing_mode[] = {
- /* Note that using the same enumerator for lr as lr-tb means we write as lr-tb even if the
- * input file said lr. We prefer writing lr-tb on the grounds that the spec says the initial
- * value is lr-tb rather than lr.
- *
- * ECMA scripts may be surprised to find tb-rl in DOM if they set the attribute to rl, so
- * sharing enumerators for different strings may be a bug (once we support ecma script).
- */
- {"lr-tb", SP_CSS_WRITING_MODE_LR_TB},
- {"rl-tb", SP_CSS_WRITING_MODE_RL_TB},
- {"tb-rl", SP_CSS_WRITING_MODE_TB_RL},
- {"lr", SP_CSS_WRITING_MODE_LR_TB},
- {"rl", SP_CSS_WRITING_MODE_RL_TB},
- {"tb", SP_CSS_WRITING_MODE_TB_RL},
- {NULL, -1}
-};
-
-static SPStyleEnum const enum_baseline_shift[] = {
- {"baseline", SP_CSS_BASELINE_SHIFT_BASELINE},
- {"sub", SP_CSS_BASELINE_SHIFT_SUB},
- {"super", SP_CSS_BASELINE_SHIFT_SUPER},
- {NULL, -1}
-};
-
-static SPStyleEnum const enum_visibility[] = {
- {"hidden", SP_CSS_VISIBILITY_HIDDEN},
- {"collapse", SP_CSS_VISIBILITY_COLLAPSE},
- {"visible", SP_CSS_VISIBILITY_VISIBLE},
- {NULL, -1}
-};
-
-static SPStyleEnum const enum_overflow[] = {
- {"visible", SP_CSS_OVERFLOW_VISIBLE},
- {"hidden", SP_CSS_OVERFLOW_HIDDEN},
- {"scroll", SP_CSS_OVERFLOW_SCROLL},
- {"auto", SP_CSS_OVERFLOW_AUTO},
- {NULL, -1}
-};
-
-// CSS Compositing and Blending Level 1
-static SPStyleEnum const enum_isolation[] = {
- {"auto", SP_CSS_ISOLATION_AUTO},
- {"isolate", SP_CSS_ISOLATION_ISOLATE},
- {NULL, -1}
-};
-
-static SPStyleEnum const enum_blend_mode[] = {
- {"normal", SP_CSS_BLEND_NORMAL},
- {"multiply", SP_CSS_BLEND_MULTIPLY},
- {"screen", SP_CSS_BLEND_SCREEN},
- {"darken", SP_CSS_BLEND_DARKEN},
- {"lighten", SP_CSS_BLEND_LIGHTEN},
- {"overlay", SP_CSS_BLEND_OVERLAY},
- {"color-dodge", SP_CSS_BLEND_COLORDODGE},
- {"color-burn", SP_CSS_BLEND_COLORBURN},
- {"hard-light", SP_CSS_BLEND_HARDLIGHT},
- {"soft-light", SP_CSS_BLEND_SOFTLIGHT},
- {"difference", SP_CSS_BLEND_DIFFERENCE},
- {"exclusion", SP_CSS_BLEND_EXCLUSION},
- {"hue", SP_CSS_BLEND_HUE},
- {"saturation", SP_CSS_BLEND_SATURATION},
- {"color", SP_CSS_BLEND_COLOR},
- {"luminosity", SP_CSS_BLEND_LUMINOSITY},
- {NULL, -1}
-};
-
-static SPStyleEnum const enum_display[] = {
- {"none", SP_CSS_DISPLAY_NONE},
- {"inline", SP_CSS_DISPLAY_INLINE},
- {"block", SP_CSS_DISPLAY_BLOCK},
- {"list-item", SP_CSS_DISPLAY_LIST_ITEM},
- {"run-in", SP_CSS_DISPLAY_RUN_IN},
- {"compact", SP_CSS_DISPLAY_COMPACT},
- {"marker", SP_CSS_DISPLAY_MARKER},
- {"table", SP_CSS_DISPLAY_TABLE},
- {"inline-table", SP_CSS_DISPLAY_INLINE_TABLE},
- {"table-row-group", SP_CSS_DISPLAY_TABLE_ROW_GROUP},
- {"table-header-group", SP_CSS_DISPLAY_TABLE_HEADER_GROUP},
- {"table-footer-group", SP_CSS_DISPLAY_TABLE_FOOTER_GROUP},
- {"table-row", SP_CSS_DISPLAY_TABLE_ROW},
- {"table-column-group", SP_CSS_DISPLAY_TABLE_COLUMN_GROUP},
- {"table-column", SP_CSS_DISPLAY_TABLE_COLUMN},
- {"table-cell", SP_CSS_DISPLAY_TABLE_CELL},
- {"table-caption", SP_CSS_DISPLAY_TABLE_CAPTION},
- {NULL, -1}
-};
-
-static SPStyleEnum const enum_shape_rendering[] = {
- {"auto", SP_CSS_SHAPE_RENDERING_AUTO},
- {"optimizeSpeed", SP_CSS_SHAPE_RENDERING_OPTIMIZESPEED},
- {"crispEdges", SP_CSS_SHAPE_RENDERING_CRISPEDGES},
- {"geometricPrecision", SP_CSS_SHAPE_RENDERING_GEOMETRICPRECISION},
- {NULL, -1}
-};
-
-static SPStyleEnum const enum_color_rendering[] = {
- {"auto", SP_CSS_COLOR_RENDERING_AUTO},
- {"optimizeSpeed", SP_CSS_COLOR_RENDERING_OPTIMIZESPEED},
- {"optimizeQuality", SP_CSS_COLOR_RENDERING_OPTIMIZEQUALITY},
- {NULL, -1}
-};
-
-static SPStyleEnum const enum_image_rendering[] = {
- {"auto", SP_CSS_IMAGE_RENDERING_AUTO},
- {"optimizeSpeed", SP_CSS_IMAGE_RENDERING_OPTIMIZESPEED},
- {"optimizeQuality", SP_CSS_IMAGE_RENDERING_OPTIMIZEQUALITY},
- {"-inkscape-crisp-edges", SP_CSS_IMAGE_RENDERING_CRISPEDGES},
- {"-inkscape-pixelated", SP_CSS_IMAGE_RENDERING_PIXELATED},
- {NULL, -1}
-};
-
-static SPStyleEnum const enum_text_rendering[] = {
- {"auto", SP_CSS_TEXT_RENDERING_AUTO},
- {"optimizeSpeed", SP_CSS_TEXT_RENDERING_OPTIMIZESPEED},
- {"optimizeLegibility", SP_CSS_TEXT_RENDERING_OPTIMIZELEGIBILITY},
- {"geometricPrecision", SP_CSS_TEXT_RENDERING_GEOMETRICPRECISION},
- {NULL, -1}
-};
-
-static SPStyleEnum const enum_enable_background[] = {
- {"accumulate", SP_CSS_BACKGROUND_ACCUMULATE},
- {"new", SP_CSS_BACKGROUND_NEW},
- {NULL, -1}
-};
-
-static SPStyleEnum const enum_clip_rule[] = {
- {"nonzero", SP_WIND_RULE_NONZERO},
- {"evenodd", SP_WIND_RULE_EVENODD},
- {NULL, -1}
-};
-
-static SPStyleEnum const enum_color_interpolation[] = {
- {"auto", SP_CSS_COLOR_INTERPOLATION_AUTO},
- {"sRGB", SP_CSS_COLOR_INTERPOLATION_SRGB},
- {"linearRGB", SP_CSS_COLOR_INTERPOLATION_LINEARRGB},
- {NULL, -1}
-};
+void sp_style_filter_ref_changed(SPObject *old_ref, SPObject *ref, SPStyle *style);
+void sp_style_fill_paint_server_ref_changed(SPObject *old_ref, SPObject *ref, SPStyle *style);
+void sp_style_stroke_paint_server_ref_changed(SPObject *old_ref, SPObject *ref, SPStyle *style);
+
+static void sp_style_object_release(SPObject *object, SPStyle *style);
+static CRSelEng *sp_repr_sel_eng();
+
+
+//SPPropMap SPStyle::_propmap;
+
+// C++11 allows one constructor to call another... might be useful. The original C code
+// had separate calls to create SPStyle, one with only SPDocument and the other with only
+// SPObject as parameters.
+SPStyle::SPStyle(SPDocument *document_in, SPObject *object_in) :
+
+ // Unimplemented SVG 1.1: alignment-baseline, clip, clip-path, color-profile, cursor,
+ // dominant-baseline, flood-color, flood-opacity, font-size-adjust,
+ // glyph-orientation-horizontal, glyph-orientation-vertical, kerning, lighting-color,
+ // pointer-events, stop-color, stop-opacity, unicode-bidi
+
+ // For enums: property( name, enumeration, default value , inherits = true );
+ // For scale24: property( name, default value = 0, inherits = true );
+
+ // 'font', 'font-size', and 'font-family' must come first as other properties depend on them
+ // for calculated values (through 'em' and 'ex'). ('ex' is currently not read.)
+ // The following properties can depend on 'em' and 'ex':
+ // baseline-shift, kerning, letter-spacing, stroke-dash-offset, stroke-width, word-spacing,
+ // Non-SVG 1.1: text-indent, line-spacing
+
+ // Hidden in SPIFontStyle: (to be refactored)
+ // font-family
+ // font-specification
+
+ // Font related properties and 'font' shorthand
+ font_style( "font-style", enum_font_style, SP_CSS_FONT_STYLE_NORMAL ),
+ font_variant( "font-variant", enum_font_variant, SP_CSS_FONT_VARIANT_NORMAL ),
+ font_weight( "font-weight", enum_font_weight, SP_CSS_FONT_WEIGHT_NORMAL, SP_CSS_FONT_WEIGHT_400 ),
+ font_stretch( "font-stretch", enum_font_stretch, SP_CSS_FONT_STRETCH_NORMAL ),
+ font_size(),
+ line_height( "line-height", 1.0 ), // SPILengthOrNormal
+ font_family( "font-family", "sans-serif" ), // SPIString w/default
+ font(), // SPIFont
+ font_specification( "-inkscape-font-specification" ), // SPIString
+
+ // Text related properties
+ text_indent( "text-indent", 0.0 ), // SPILength
+ text_align( "text-align", enum_text_align, SP_CSS_TEXT_ALIGN_START ),
+
+ letter_spacing( "letter-spacing", 0.0 ), // SPILengthOrNormal
+ word_spacing( "word-spacing", 0.0 ), // SPILengthOrNormal
+ text_transform( "text-transform", enum_text_transform, SP_CSS_TEXT_TRANSFORM_NONE ),
+
+ direction( "direction", enum_direction, SP_CSS_DIRECTION_LTR ),
+ block_progression("block-progression", enum_block_progression, SP_CSS_BLOCK_PROGRESSION_TB),
+ writing_mode( "writing-mode", enum_writing_mode, SP_CSS_WRITING_MODE_LR_TB ),
+ baseline_shift(),
+ text_anchor( "text-anchor", enum_text_anchor, SP_CSS_TEXT_ANCHOR_START ),
+ white_space( "white-space", enum_white_space, SP_CSS_WHITE_SPACE_NORMAL ),
+
+ text_decoration(),
+ text_decoration_line(),
+ text_decoration_style(),
+ text_decoration_color( "text-decoration-color" ), // SPIColor
+
+ // General visual properties
+ clip_rule( "clip-rule", enum_clip_rule, SP_WIND_RULE_NONZERO ),
+ display( "display", enum_display, SP_CSS_DISPLAY_INLINE, false ),
+ overflow( "overflow", enum_overflow, SP_CSS_OVERFLOW_VISIBLE, false ),
+ visibility( "visibility", enum_visibility, SP_CSS_VISIBILITY_VISIBLE ),
+ opacity( "opacity", SP_SCALE24_MAX, false ),
+
+ isolation( "isolation", enum_isolation, SP_CSS_ISOLATION_AUTO ),
+ mix_blend_mode( "mix-blend-mode", enum_blend_mode, SP_CSS_BLEND_NORMAL ),
+
+ paint_order(), // SPIPaintOrder
+
+ // Color properties
+ color( "color" ), // SPIColor
+ color_interpolation( "color-interpolation", enum_color_interpolation, SP_CSS_COLOR_INTERPOLATION_SRGB),
+ color_interpolation_filters("color-interpolation-filters", enum_color_interpolation, SP_CSS_COLOR_INTERPOLATION_LINEARRGB),
+
+ // Solid color properties
+ solid_color( "solid-color" ), // SPIColor
+ solid_opacity( "solid-opacity", SP_SCALE24_MAX ),
+
+ // Fill properties
+ fill( "fill" ), // SPIPaint
+ fill_opacity( "fill-opacity", SP_SCALE24_MAX ),
+ fill_rule( "fill-rule", enum_fill_rule, SP_WIND_RULE_NONZERO ),
+
+ // Stroke properites
+ stroke( "stroke" ), // SPIPaint
+ stroke_width( "stroke-width", 1.0 ), // SPILength
+ stroke_linecap( "stroke-linecap", enum_stroke_linecap, SP_STROKE_LINECAP_BUTT ),
+ stroke_linejoin( "stroke-linejoin", enum_stroke_linejoin, SP_STROKE_LINEJOIN_MITER ),
+ stroke_miterlimit("stroke-miterlimit", 4 ), // SPIFloat (only use of float!)
+ stroke_dasharray(), // SPIDashArray
+ stroke_dashoffset("stroke-dashoffset", 0.0 ), // SPILength for now
+
+ stroke_opacity( "stroke-opacity", SP_SCALE24_MAX ),
+
+ marker( "marker" ), // SPIString
+ marker_start( "marker-start" ), // SPIString
+ marker_mid( "marker-mid" ), // SPIString
+ marker_end( "marker-end" ), // SPIString
+
+ // Filter properties
+ filter(),
+ filter_blend_mode("filter-blend-mode", enum_blend_mode, SP_CSS_BLEND_NORMAL),
+ filter_gaussianBlur_deviation( "filter-gaussianBlur-deviation", 0.0 ), // SPILength
+ enable_background("enable-background", enum_enable_background, SP_CSS_BACKGROUND_ACCUMULATE, false),
+
+ // Rendering hint properties
+ color_rendering( "color-rendering", enum_color_rendering, SP_CSS_COLOR_RENDERING_AUTO),
+ image_rendering( "image-rendering", enum_image_rendering, SP_CSS_IMAGE_RENDERING_AUTO),
+ shape_rendering( "shape-rendering", enum_shape_rendering, SP_CSS_SHAPE_RENDERING_AUTO),
+ text_rendering( "text-rendering", enum_text_rendering, SP_CSS_TEXT_RENDERING_AUTO )
+{
+ // std::cout << "SPStyle::SPStyle( SPDocument ): Entrance: (" << _count << ")" << std::endl;
+ // std::cout << " Document: " << (document_in?"present":"null") << std::endl;
+ // std::cout << " Object: "
+ // << (object_in?(object_in->getId()?object_in->getId():"id null"):"object null") << std::endl;
+
+ // static bool first = true;
+ // if( first ) {
+ // std::cout << "Size of SPStyle: " << sizeof(SPStyle) << std::endl;
+ // std::cout << " SPIBase: " << sizeof(SPIBase) << std::endl;
+ // std::cout << " SPIFloat: " << sizeof(SPIFloat) << std::endl;
+ // std::cout << " SPIScale24: " << sizeof(SPIScale24) << std::endl;
+ // std::cout << " SPILength: " << sizeof(SPILength) << std::endl;
+ // std::cout << " SPILengthOrNormal: " << sizeof(SPILengthOrNormal) << std::endl;
+ // std::cout << " SPIColor: " << sizeof(SPIColor) << std::endl;
+ // std::cout << " SPIPaint: " << sizeof(SPIPaint) << std::endl;
+ // std::cout << " SPITextDecorationLine" << sizeof(SPITextDecorationLine) << std::endl;
+ // std::cout << " Glib::ustring:" << sizeof(Glib::ustring) << std::endl;
+ // std::cout << " SPColor: " << sizeof(SPColor) << std::endl;
+ // first = false;
+ // }
+
+ ++_count; // Poor man's memory leak detector
+
+ _refcount = 1;
+
+ cloned = false;
+
+ object = object_in;
+ if( object ) {
+ g_assert( SP_IS_OBJECT(object) );
+ document = object->document;
+ release_connection =
+ object->connectRelease(sigc::bind<1>(sigc::ptr_fun(&sp_style_object_release), this));
+
+ cloned = object->cloned;
-/**
- * Release callback.
- */
-static void
-sp_style_object_release(SPObject *object, SPStyle *style)
-{
- (void)object; // TODO
- style->object = NULL;
-}
+ } else {
+ document = document_in;
+ }
+
+ // 'font' shorthand requires access to included properties.
+ font.setStylePointer( this );
+
+ // Properties that depend on 'font-size' for calculating lengths.
+ baseline_shift.setStylePointer( this );
+ text_indent.setStylePointer( this );
+ line_height.setStylePointer( this );
+ letter_spacing.setStylePointer( this );
+ word_spacing.setStylePointer( this );
+ stroke_width.setStylePointer( this );
+ stroke_dashoffset.setStylePointer( this );
+
+ // Properties that depend on 'color'
+ text_decoration_color.setStylePointer( this );
+ fill.setStylePointer( this );
+ stroke.setStylePointer( this );
+ // color.setStylePointer( this ); // Doen't need reference to self
+
+ // 'text_decoration' shorthand requires access to included properties.
+ text_decoration.setStylePointer( this );
+
+ // SPIPaint, SPIFilter needs access to 'this' (SPStyle)
+ // for setting up signals... 'fill', 'stroke' already done
+ filter.setStylePointer( this );
+
+ // Used to iterate over markers
+ marker_ptrs[SP_MARKER_LOC] = &marker;
+ marker_ptrs[SP_MARKER_LOC_START] = &marker_start;
+ marker_ptrs[SP_MARKER_LOC_MID] = &marker_mid;
+ marker_ptrs[SP_MARKER_LOC_END] = &marker_end;
+
+
+ // This might be too resource hungary... but for now it possible to loop over properties
+
+ // 'color' must be before 'fill', 'stroke', 'text-decoration-color', ...
+ _properties.push_back( &color );
+
+ // 'font-size'/'font' must be before properties that need to know em, ex size (SPILength,
+ // SPILenghtOrNormal)
+ _properties.push_back( &font_style );
+ _properties.push_back( &font_variant );
+ _properties.push_back( &font_weight );
+ _properties.push_back( &font_stretch );
+ _properties.push_back( &font_size );
+ _properties.push_back( &line_height );
+ _properties.push_back( &font_family );
+ _properties.push_back( &font );
+ _properties.push_back( &font_specification );
+
+ _properties.push_back( &text_indent );
+ _properties.push_back( &text_align );
+
+ _properties.push_back( &text_decoration );
+ _properties.push_back( &text_decoration_line );
+ _properties.push_back( &text_decoration_style );
+ _properties.push_back( &text_decoration_color );
+
+ _properties.push_back( &letter_spacing );
+ _properties.push_back( &word_spacing );
+ _properties.push_back( &text_transform );
+
+ _properties.push_back( &direction );
+ _properties.push_back( &block_progression );
+ _properties.push_back( &writing_mode );
+ _properties.push_back( &baseline_shift );
+ _properties.push_back( &text_anchor );
+ _properties.push_back( &white_space );
+
+ _properties.push_back( &clip_rule );
+ _properties.push_back( &display );
+ _properties.push_back( &overflow );
+ _properties.push_back( &visibility );
+ _properties.push_back( &opacity );
+
+ _properties.push_back( &isolation );
+ _properties.push_back( &mix_blend_mode );
+
+ _properties.push_back( &color_interpolation );
+ _properties.push_back( &color_interpolation_filters );
+
+ _properties.push_back( &solid_color );
+ _properties.push_back( &solid_opacity );
+
+ _properties.push_back( &fill );
+ _properties.push_back( &fill_opacity );
+ _properties.push_back( &fill_rule );
+
+ _properties.push_back( &stroke );
+ _properties.push_back( &stroke_width );
+ _properties.push_back( &stroke_linecap );
+ _properties.push_back( &stroke_linejoin );
+ _properties.push_back( &stroke_miterlimit );
+ _properties.push_back( &stroke_dasharray );
+ _properties.push_back( &stroke_dashoffset );
+ _properties.push_back( &stroke_opacity );
+
+ _properties.push_back( &marker );
+ _properties.push_back( &marker_start );
+ _properties.push_back( &marker_mid );
+ _properties.push_back( &marker_end );
+
+ _properties.push_back( &paint_order );
+
+ _properties.push_back( &filter );
+ _properties.push_back( &filter_blend_mode );
+ _properties.push_back( &filter_gaussianBlur_deviation );
+
+ _properties.push_back( &color_rendering );
+ _properties.push_back( &image_rendering );
+ _properties.push_back( &shape_rendering );
+ _properties.push_back( &text_rendering );
+
+ _properties.push_back( &enable_background );
+
+ // MAP -------------------------------------------
-/**
- * Emit style modified signal on style's object if the filter changed.
- */
-static void
-sp_style_filter_ref_modified(SPObject *obj, guint flags, SPStyle *style)
-{
- (void)flags; // TODO
- SPFilter *filter=static_cast<SPFilter *>(obj);
- if (style->getFilter() == filter)
- {
- if (style->object) {
- style->object->requestModified(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG);
- }
- }
-}
+ // if( _propmap.size() == 0 ) {
-/**
- * Gets called when the filter is (re)attached to the style
- */
-static void
-sp_style_filter_ref_changed(SPObject *old_ref, SPObject *ref, SPStyle *style)
-{
- if (old_ref) {
- style->filter_modified_connection.disconnect();
- }
- if ( SP_IS_FILTER(ref))
- {
- style->filter_modified_connection =
- ref->connectModified(sigc::bind(sigc::ptr_fun(&sp_style_filter_ref_modified), style));
- }
+ // // 'color' must be before 'fill', 'stroke', 'text-decoration-color', ...
+ // _propmap.insert( std::make_pair( color.name, reinterpret_cast<SPIBasePtr>(&SPStyle::color ) ) );
- sp_style_filter_ref_modified(ref, 0, style);
-}
+ // // 'font-size' must be before properties that need to know em, ex size (SPILength, SPILenghtOrNormal)
+ // _propmap.insert( std::make_pair( font_style.name, reinterpret_cast<SPIBasePtr>(&SPStyle::font_style ) ) );
+ // _propmap.insert( std::make_pair( font_variant.name, reinterpret_cast<SPIBasePtr>(&SPStyle::font_variant ) ) );
+ // _propmap.insert( std::make_pair( font_weight.name, reinterpret_cast<SPIBasePtr>(&SPStyle::font_weight ) ) );
+ // _propmap.insert( std::make_pair( font_stretch.name, reinterpret_cast<SPIBasePtr>(&SPStyle::font_stretch ) ) );
+ // _propmap.insert( std::make_pair( font_size.name, reinterpret_cast<SPIBasePtr>(&SPStyle::font_size ) ) );
+ // _propmap.insert( std::make_pair( line_height.name, reinterpret_cast<SPIBasePtr>(&SPStyle::line_height ) ) );
+ // _propmap.insert( std::make_pair( font_family.name, reinterpret_cast<SPIBasePtr>(&SPStyle::font_family ) ) );
+ // _propmap.insert( std::make_pair( font.name, reinterpret_cast<SPIBasePtr>(&SPStyle::font ) ) );
+ // _propmap.insert( std::make_pair( font_specification.name, reinterpret_cast<SPIBasePtr>(&SPStyle::font_specification ) ) );
-/**
- * Emit style modified signal on style's object if server is style's fill
- * or stroke paint server.
- */
-static void
-sp_style_paint_server_ref_modified(SPObject *obj, guint flags, SPStyle *style)
-{
- (void)flags; // TODO
- SPPaintServer *server = static_cast<SPPaintServer *>(obj);
+ // _propmap.insert( std::make_pair( text_indent.name, reinterpret_cast<SPIBasePtr>(&SPStyle::text_indent ) ) );
+ // _propmap.insert( std::make_pair( text_align.name, reinterpret_cast<SPIBasePtr>(&SPStyle::text_align ) ) );
- if ((style->fill.isPaintserver())
- && style->getFillPaintServer() == server)
- {
- if (style->object) {
- /** \todo
- * fixme: I do not know, whether it is optimal - we are
- * forcing reread of everything (Lauris)
- */
- /** \todo
- * fixme: We have to use object_modified flag, because parent
- * flag is only available downstreams.
- */
- style->object->requestModified(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG);
- }
- } else if ((style->stroke.isPaintserver())
- && style->getStrokePaintServer() == server)
- {
- if (style->object) {
- /// \todo fixme:
- style->object->requestModified(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG);
- }
- } else if (server) {
- g_assert_not_reached();
- }
-}
+ // _propmap.insert( std::make_pair( text_decoration.name, reinterpret_cast<SPIBasePtr>(&SPStyle::text_decoration ) ) );
+ // _propmap.insert( std::make_pair( text_decoration_line.name, reinterpret_cast<SPIBasePtr>(&SPStyle::text_decoration_line ) ) );
+ // _propmap.insert( std::make_pair( text_decoration_style.name, reinterpret_cast<SPIBasePtr>(&SPStyle::text_decoration_style ) ) );
+ // _propmap.insert( std::make_pair( text_decoration_color.name, reinterpret_cast<SPIBasePtr>(&SPStyle::text_decoration_color ) ) );
-/**
- * Gets called when the paintserver is (re)attached to the style
- */
-static void
-sp_style_fill_paint_server_ref_changed(SPObject *old_ref, SPObject *ref, SPStyle *style)
-{
- if (old_ref) {
- style->fill_ps_modified_connection.disconnect();
- }
- if (SP_IS_PAINT_SERVER(ref)) {
- style->fill_ps_modified_connection =
- ref->connectModified(sigc::bind(sigc::ptr_fun(&sp_style_paint_server_ref_modified), style));
- }
+ // _propmap.insert( std::make_pair( letter_spacing.name, reinterpret_cast<SPIBasePtr>(&SPStyle::letter_spacing ) ) );
+ // _propmap.insert( std::make_pair( word_spacing.name, reinterpret_cast<SPIBasePtr>(&SPStyle::word_spacing ) ) );
+ // _propmap.insert( std::make_pair( text_transform.name, reinterpret_cast<SPIBasePtr>(&SPStyle::text_transform ) ) );
- sp_style_paint_server_ref_modified(ref, 0, style);
-}
+ // _propmap.insert( std::make_pair( direction.name, reinterpret_cast<SPIBasePtr>(&SPStyle::direction ) ) );
+ // _propmap.insert( std::make_pair( block_progression.name, reinterpret_cast<SPIBasePtr>(&SPStyle::block_progression ) ) );
+ // _propmap.insert( std::make_pair( writing_mode.name, reinterpret_cast<SPIBasePtr>(&SPStyle::writing_mode ) ) );
+ // _propmap.insert( std::make_pair( baseline_shift.name, reinterpret_cast<SPIBasePtr>(&SPStyle::baseline_shift ) ) );
+ // _propmap.insert( std::make_pair( text_anchor.name, reinterpret_cast<SPIBasePtr>(&SPStyle::text_anchor ) ) );
+ // _propmap.insert( std::make_pair( white_space.name, reinterpret_cast<SPIBasePtr>(&SPStyle::white_space ) ) );
-/**
- * Gets called when the paintserver is (re)attached to the style
- */
-static void
-sp_style_stroke_paint_server_ref_changed(SPObject *old_ref, SPObject *ref, SPStyle *style)
-{
- if (old_ref) {
- style->stroke_ps_modified_connection.disconnect();
- }
- if (SP_IS_PAINT_SERVER(ref)) {
- style->stroke_ps_modified_connection =
- ref->connectModified(sigc::bind(sigc::ptr_fun(&sp_style_paint_server_ref_modified), style));
- }
+ // _propmap.insert( std::make_pair( clip_rule.name, reinterpret_cast<SPIBasePtr>(&SPStyle::clip_rule ) ) );
+ // _propmap.insert( std::make_pair( display.name, reinterpret_cast<SPIBasePtr>(&SPStyle::display ) ) );
+ // _propmap.insert( std::make_pair( overflow.name, reinterpret_cast<SPIBasePtr>(&SPStyle::overflow ) ) );
+ // _propmap.insert( std::make_pair( visibility.name, reinterpret_cast<SPIBasePtr>(&SPStyle::visibility ) ) );
+ // _propmap.insert( std::make_pair( opacity.name, reinterpret_cast<SPIBasePtr>(&SPStyle::opacity ) ) );
- sp_style_paint_server_ref_modified(ref, 0, style);
-}
+ // _propmap.insert( std::make_pair( isolation.name, reinterpret_cast<SPIBasePtr>(&SPStyle::isolation ) ) );
+ // _propmap.insert( std::make_pair( mix_blend_mode.name, reinterpret_cast<SPIBasePtr>(&SPStyle::mix_blend_mode ) ) );
-/**
- * Returns a new SPStyle object with settings as per sp_style_clear().
- */
-SPStyle *
-sp_style_new(SPDocument *document)
-{
- SPStyle *const style = g_new0(SPStyle, 1);
+ // _propmap.insert( std::make_pair( color_interpolation.name, reinterpret_cast<SPIBasePtr>(&SPStyle::color_interpolation ) ) );
+ // _propmap.insert( std::make_pair( color_interpolation_filters.name, reinterpret_cast<SPIBasePtr>(&SPStyle::color_interpolation_filters ) ) );
- style->refcount = 1;
- style->object = NULL;
- style->document = document;
- style->text = sp_text_style_new();
- style->text_private = TRUE;
+ // _propmap.insert( std::make_pair( solid_color.name, reinterpret_cast<SPIBasePtr>(&SPStyle::solid_color ) ) );
+ // _propmap.insert( std::make_pair( solid_opacity.name, reinterpret_cast<SPIBasePtr>(&SPStyle::solid_opacity ) ) );
- sp_style_clear(style);
+ // _propmap.insert( std::make_pair( fill.name, reinterpret_cast<SPIBasePtr>(&SPStyle::fill ) ) );
+ // _propmap.insert( std::make_pair( fill_opacity.name, reinterpret_cast<SPIBasePtr>(&SPStyle::fill_opacity ) ) );
+ // _propmap.insert( std::make_pair( fill_rule.name, reinterpret_cast<SPIBasePtr>(&SPStyle::fill_rule ) ) );
- style->cloned = false;
- new (&style->release_connection) sigc::connection();
- new (&style->filter_modified_connection) sigc::connection();
- new (&style->fill_ps_modified_connection) sigc::connection();
- new (&style->stroke_ps_modified_connection) sigc::connection();
+ // _propmap.insert( std::make_pair( stroke.name, reinterpret_cast<SPIBasePtr>(&SPStyle::stroke ) ) );
+ // _propmap.insert( std::make_pair( stroke_width.name, reinterpret_cast<SPIBasePtr>(&SPStyle::stroke_width ) ) );
+ // _propmap.insert( std::make_pair( stroke_linecap.name, reinterpret_cast<SPIBasePtr>(&SPStyle::stroke_linecap ) ) );
+ // _propmap.insert( std::make_pair( stroke_linejoin.name, reinterpret_cast<SPIBasePtr>(&SPStyle::stroke_linejoin ) ) );
+ // _propmap.insert( std::make_pair( stroke_miterlimit.name, reinterpret_cast<SPIBasePtr>(&SPStyle::stroke_miterlimit ) ) );
+ // _propmap.insert( std::make_pair( stroke_dasharray.name, reinterpret_cast<SPIBasePtr>(&SPStyle::stroke_dasharray ) ) );
+ // _propmap.insert( std::make_pair( stroke_dashoffset.name, reinterpret_cast<SPIBasePtr>(&SPStyle::stroke_dashoffset ) ) );
+ // _propmap.insert( std::make_pair( stroke_opacity.name, reinterpret_cast<SPIBasePtr>(&SPStyle::stroke_opacity ) ) );
- return style;
+ // _propmap.insert( std::make_pair( marker.name, reinterpret_cast<SPIBasePtr>(&SPStyle::marker ) ) );
+ // _propmap.insert( std::make_pair( marker_start.name, reinterpret_cast<SPIBasePtr>(&SPStyle::marker_start ) ) );
+ // _propmap.insert( std::make_pair( marker_mid.name, reinterpret_cast<SPIBasePtr>(&SPStyle::marker_mid ) ) );
+ // _propmap.insert( std::make_pair( marker_end.name, reinterpret_cast<SPIBasePtr>(&SPStyle::marker_end ) ) );
+
+ // _propmap.insert( std::make_pair( paint_order.name, reinterpret_cast<SPIBasePtr>(&SPStyle::paint_order ) ) );
+
+ // _propmap.insert( std::make_pair( filter.name, reinterpret_cast<SPIBasePtr>(&SPStyle::filter ) ) );
+ // _propmap.insert( std::make_pair( filter_blend_mode.name, reinterpret_cast<SPIBasePtr>(&SPStyle::filter_blend_mode ) ) );
+ // _propmap.insert( std::make_pair( filter_gaussianBlur_deviation.name, reinterpret_cast<SPIBasePtr>(&SPStyle::filter_gaussianBlur_deviation ) ) );
+
+ // _propmap.insert( std::make_pair( color_rendering.name, reinterpret_cast<SPIBasePtr>(&SPStyle::color_rendering ) ) );
+ // _propmap.insert( std::make_pair( image_rendering.name, reinterpret_cast<SPIBasePtr>(&SPStyle::image_rendering ) ) );
+ // _propmap.insert( std::make_pair( shape_rendering.name, reinterpret_cast<SPIBasePtr>(&SPStyle::shape_rendering ) ) );
+ // _propmap.insert( std::make_pair( text_rendering.name, reinterpret_cast<SPIBasePtr>(&SPStyle::text_rendering ) ) );
+
+ // _propmap.insert( std::make_pair( enable_background.name, reinterpret_cast<SPIBasePtr>(&SPStyle::enable_background ) ) );
+
+ // }
}
+SPStyle::~SPStyle() {
-/**
- * Creates a new SPStyle object, and attaches it to the specified SPObject.
- */
-SPStyle *
-sp_style_new_from_object(SPObject *object)
-{
- g_return_val_if_fail(object != NULL, NULL);
- g_return_val_if_fail(SP_IS_OBJECT(object), NULL);
+ // std::cout << "SPStyle::~SPStyle" << std::endl;
+ --_count; // Poor man's memory leak detector.
- SPStyle *style = sp_style_new( object->document );
- style->object = object;
- style->release_connection = object->connectRelease(sigc::bind<1>(sigc::ptr_fun(&sp_style_object_release), style));
+ // Remove connections
+ release_connection.disconnect();
+ fill_ps_changed_connection.disconnect();
+ stroke_ps_changed_connection.disconnect();
- if (object->cloned) {
- style->cloned = true;
+ // The following shoud be moved into SPIPaint and SPIFilter
+ if (fill.value.href) {
+ fill_ps_modified_connection.disconnect();
}
- return style;
-}
+ if (stroke.value.href) {
+ stroke_ps_modified_connection.disconnect();
+ }
+ if (filter.href) {
+ filter_modified_connection.disconnect();
+ }
-/**
- * Increase refcount of style.
- */
-SPStyle *
-sp_style_ref(SPStyle *style)
-{
- g_return_val_if_fail(style != NULL, NULL);
- g_return_val_if_fail(style->refcount > 0, NULL);
+ _properties.clear();
- style->refcount += 1;
+ // std::cout << "SPStyle::~SPstyle(): Exit\n" << std::endl;
+}
- return style;
+// Used in SPStyle::clear()
+void clear_property( SPIBase* p ) {
+ p->clear();
}
-/**
- * Decrease refcount of style with possible destruction.
- */
-SPStyle *
-sp_style_unref(SPStyle *style)
-{
- g_return_val_if_fail(style != NULL, NULL);
- g_return_val_if_fail(style->refcount > 0, NULL);
-
- style->refcount -= 1;
-
- if (style->refcount < 1) {
- style->release_connection.disconnect();
- style->release_connection.~connection();
- if (style->text) sp_text_style_unref(style->text);
-
- if (style->fill.value.href) {
- style->fill_ps_modified_connection.disconnect();
- delete style->fill.value.href;
- style->fill.value.href = NULL;
- }
- if (style->stroke.value.href) {
- style->stroke_ps_modified_connection.disconnect();
- delete style->stroke.value.href;
- style->stroke.value.href = NULL;
- }
- if (style->filter.href) {
- style->filter_modified_connection.disconnect();
- delete style->filter.href;
- style->filter.href = NULL;
- }
-
- style->filter_modified_connection.~connection();
- style->fill_ps_modified_connection.~connection();
- style->stroke_ps_modified_connection.~connection();
-
- style->fill.clear();
- style->stroke.clear();
- sp_style_filter_clear(style);
-
- style->stroke_dasharray.values.clear();
-
- for (unsigned i = SP_MARKER_LOC; i < SP_MARKER_LOC_QTY; i++) {
- if (style->marker[i].value) {
- g_free(style->marker[i].value);
- style->marker[i].value = NULL;
- }
- }
+// Matches void sp_style_clear();
+void
+SPStyle::clear() {
- g_free(style);
- return NULL;
+ for_each( _properties.begin(), _properties.end(), clear_property );
+ // for(SPPropMap::iterator i = _propmap.begin(); i != _propmap.end(); ++i ) {
+ // (this->*(i->second)).clear();
+ // }
+
+ // Release connection to object, created in sp_style_new_from_object()
+ release_connection.disconnect();
+
+ // href->detach() called in fill->clear()...
+ fill_ps_modified_connection.disconnect();
+ if (fill.value.href) {
+ delete fill.value.href;
+ fill.value.href = NULL;
}
- return style;
+ stroke_ps_modified_connection.disconnect();
+ if (stroke.value.href) {
+ delete stroke.value.href;
+ stroke.value.href = NULL;
+ }
+ filter_modified_connection.disconnect();
+ if (filter.href) {
+ delete filter.href;
+ filter.href = NULL;
+ }
+
+ if (document) {
+ filter.href = new SPFilterReference(document);
+ filter.href->changedSignal().connect(sigc::bind(sigc::ptr_fun(sp_style_filter_ref_changed), this));
+
+ fill.value.href = new SPPaintServerReference(document);
+ fill_ps_changed_connection = fill.value.href->changedSignal().connect(sigc::bind(sigc::ptr_fun(sp_style_fill_paint_server_ref_changed), this));
+
+ stroke.value.href = new SPPaintServerReference(document);
+ stroke_ps_changed_connection = stroke.value.href->changedSignal().connect(sigc::bind(sigc::ptr_fun(sp_style_stroke_paint_server_ref_changed), this));
+ }
+
+ cloned = false;
+
}
-/**
- * Reads the various style parameters for an object from repr.
- */
-static void
-sp_style_read(SPStyle *style, SPObject *object, Inkscape::XML::Node *repr)
-{
- g_assert(style != NULL);
+// Matches void sp_style_read(SPStyle *style, SPObject *object, Inkscape::XML::Node *repr)
+void
+SPStyle::read( SPObject *object, Inkscape::XML::Node *repr ) {
+
+ // std::cout << "SPstyle::read( SPObject, Inkscape::XML::Node ): Entrance: "
+ // << (object?(object->getId()?object->getId():"id null"):"object null") << " "
+ // << (repr?(repr->name()?repr->name():"no name"):"repr null")
+ // << std::endl;
g_assert(repr != NULL);
g_assert(!object || (object->getRepr() == repr));
- sp_style_clear(style);
+ // // Uncomment to verify that we don't need to call clear.
+ // std::cout << " Creating temp style for testing" << std::endl;
+ // SPStyle *temp = new SPStyle();
+ // if( !(*temp == *this ) ) std::cout << "SPStyle::read: Need to clear" << std::endl;
+ // delete temp;
+
+ clear(); // FIXME, If this isn't here, gradient editing stops working. Why?
if (object && object->cloned) {
- style->cloned = true;
+ cloned = true;
}
/* 1. Style attribute */
+ // std::cout << " MERGING STYLE ATTRIBUTE" << std::endl;
gchar const *val = repr->attribute("style");
- if (val != NULL && *val) {
- sp_style_merge_from_style_string(style, val);
+ if( val != NULL && *val ) {
+ _mergeString( val );
}
+ /* 2 Style sheet */
+ // std::cout << " MERGING OBJECT STYLESHEET" << std::endl;
if (object) {
- sp_style_merge_from_object_stylesheet(style, object);
+ _mergeObjectStylesheet( object );
} else {
- /** \todo No stylesheet information. Find out under what circumstances
- * this occurs, and handle accordingly. (If we really wanted to, we
- * could probably get stylesheets by going through repr->doc.)
- */
- }
-
- /* 2. Presentation attributes */
- /* Attributes are only read in if not already set in a style sheet or style attribute above. */
-
- /* CSS2 */
- SPS_READ_PENUM_IF_UNSET(&style->visibility, repr, "visibility", enum_visibility, true);
- SPS_READ_PENUM_IF_UNSET(&style->display, repr, "display", enum_display, true);
- SPS_READ_PENUM_IF_UNSET(&style->overflow, repr, "overflow", enum_overflow, true);
-
- /* CSS Compositing and Blending Level 1 */
- SPS_READ_PENUM_IF_UNSET(&style->isolation, repr, "isolation", enum_isolation, true);
- SPS_READ_PENUM_IF_UNSET(&style->blend_mode, repr, "mix_blend_mode", enum_blend_mode, true);
-
- /* Font */
- SPS_READ_PFONTSIZE_IF_UNSET(&style->font_size, repr, "font-size");
- SPS_READ_PENUM_IF_UNSET(&style->font_style, repr, "font-style", enum_font_style, true);
- SPS_READ_PENUM_IF_UNSET(&style->font_variant, repr, "font-variant", enum_font_variant, true);
- SPS_READ_PENUM_IF_UNSET(&style->font_weight, repr, "font-weight", enum_font_weight, true);
- SPS_READ_PENUM_IF_UNSET(&style->font_stretch, repr, "font-stretch", enum_font_stretch, true);
- /* Text (css2 chapter 16) */
- SPS_READ_PLENGTH_IF_UNSET(&style->text_indent, repr, "text-indent");
- SPS_READ_PENUM_IF_UNSET(&style->text_align, repr, "text-align", enum_text_align, true);
- if (!style->text_decoration_line.set) {
- // assume it uses either text-decoration or text-decoration-line, but not both
- if ((val = repr->attribute("text-decoration")) || (val = repr->attribute("text-decoration-line"))) {
- sp_style_read_itextdecoration(&style->text_decoration_line, &style->text_decoration_style, &style->text_decoration_color, val);
- }
- }
- if (!style->line_height.set) {
- val = repr->attribute("line-height");
- if (val) {
- sp_style_read_ilengthornormal(&style->line_height, val);
- }
- }
- if (!style->letter_spacing.set) {
- val = repr->attribute("letter-spacing");
- if (val) {
- sp_style_read_ilengthornormal(&style->letter_spacing, val);
- }
- }
- if (!style->word_spacing.set) {
- val = repr->attribute("word-spacing");
- if (val) {
- sp_style_read_ilengthornormal(&style->word_spacing, val);
- }
- }
- SPS_READ_PENUM_IF_UNSET(&style->text_transform, repr, "text-transform", enum_text_transform, true);
- SPS_READ_PENUM_IF_UNSET(&style->direction, repr, "direction", enum_direction, true);
- SPS_READ_PENUM_IF_UNSET(&style->block_progression, repr, "block_progression", enum_block_progression, true);
-
- /* SVG */
- SPS_READ_PENUM_IF_UNSET(&style->writing_mode, repr, "writing-mode",
- enum_writing_mode, true);
- SPS_READ_PENUM_IF_UNSET(&style->text_anchor, repr, "text-anchor",
- enum_text_anchor, true);
- SPS_READ_PBASELINE_SHIFT_IF_UNSET(&style->baseline_shift, repr, "baseline-shift");
-
- /* opacity */
- if (!style->opacity.set) {
- val = repr->attribute("opacity");
- if (val) {
- sp_style_read_iscale24(&style->opacity, val);
- }
- }
- /* color */
- if (!style->color.set) {
- val = repr->attribute("color");
- if (val) {
- sp_style_read_icolor(&style->color, val, style, ( object
- ? object->document
- : NULL ));
- }
- }
- /* color interpolation */
- SPS_READ_PENUM_IF_UNSET(&style->color_interpolation, repr, "color-interpolation", enum_color_interpolation, true);
- /* color interpolation filters*/
- SPS_READ_PENUM_IF_UNSET(&style->color_interpolation_filters, repr, "color-interpolation-filters", enum_color_interpolation, true);
- /* fill */
- if (!style->fill.set) {
- val = repr->attribute("fill");
- if (val) {
- style->fill.read( val, *style, (object) ? object->document : NULL );
- }
- }
- /* fill-opacity */
- if (!style->fill_opacity.set) {
- val = repr->attribute("fill-opacity");
- if (val) {
- sp_style_read_iscale24(&style->fill_opacity, val);
- }
- }
- /* fill-rule */
- SPS_READ_PENUM_IF_UNSET(&style->fill_rule, repr, "fill-rule", enum_fill_rule, true);
- /* stroke */
- if (!style->stroke.set) {
- val = repr->attribute("stroke");
- if (val) {
- style->stroke.read( val, *style, (object) ? object->document : NULL );
- }
- }
- SPS_READ_PLENGTH_IF_UNSET(&style->stroke_width, repr, "stroke-width");
- SPS_READ_PENUM_IF_UNSET(&style->stroke_linecap, repr, "stroke-linecap", enum_stroke_linecap, true);
- SPS_READ_PENUM_IF_UNSET(&style->stroke_linejoin, repr, "stroke-linejoin", enum_stroke_linejoin, true);
- SPS_READ_PFLOAT_IF_UNSET(&style->stroke_miterlimit, repr, "stroke-miterlimit");
-
- /* markers */
- if (!style->marker[SP_MARKER_LOC].set) {
- val = repr->attribute("marker");
- if (val) {
- sp_style_read_istring(&style->marker[SP_MARKER_LOC], val);
- }
- }
- if (!style->marker[SP_MARKER_LOC_START].set) {
- val = repr->attribute("marker-start");
- if (val) {
- sp_style_read_istring(&style->marker[SP_MARKER_LOC_START], val);
- }
- }
- if (!style->marker[SP_MARKER_LOC_MID].set) {
- val = repr->attribute("marker-mid");
- if (val) {
- sp_style_read_istring(&style->marker[SP_MARKER_LOC_MID], val);
- }
- }
- if (!style->marker[SP_MARKER_LOC_END].set) {
- val = repr->attribute("marker-end");
- if (val) {
- sp_style_read_istring(&style->marker[SP_MARKER_LOC_END], val);
- }
- }
-
- /* stroke-opacity */
- if (!style->stroke_opacity.set) {
- val = repr->attribute("stroke-opacity");
- if (val) {
- sp_style_read_iscale24(&style->stroke_opacity, val);
- }
- }
- if (!style->stroke_dasharray.set) {
- val = repr->attribute("stroke-dasharray");
- if (val) {
- sp_style_read_dash(style, val);
- }
- }
- SPS_READ_PLENGTH_IF_UNSET(&style->stroke_width, repr, "stroke-dashoffset");
-
- /* paint-order */
- if (!style->paint_order.set) {
- val = repr->attribute("paint-order");
- if (val) {
- sp_style_read_ipaintorder(&style->paint_order, val);
- } else {
- style->paint_order.layer[0] = SP_CSS_PAINT_ORDER_NORMAL;
- }
- }
-
- /* -inkscape-font-specification */
- if (!style->text_private || !style->text->font_specification.set) {
- val = repr->attribute("-inkscape-font-specification");
- if (val) {
- if (!style->text_private) sp_style_privatize_text(style);
- gchar *val_unquoted = attribute_unquote(val);
- sp_style_read_istring(&style->text->font_specification, val_unquoted);
- if (val_unquoted) g_free (val_unquoted);
- }
- }
-
- /* font-family */
- if (!style->text_private || !style->text->font_family.set) {
- val = repr->attribute("font-family");
- if (val) {
- if (!style->text_private) sp_style_privatize_text(style);
- gchar *val_unquoted = attribute_unquote(val);
- sp_style_read_istring(&style->text->font_family, val_unquoted);
- if (val_unquoted) g_free (val_unquoted);
- }
+ // std::cerr << "SPStyle::read: No object! Can not read style sheet" << std::endl;
}
- /* filter effects */
- if (!style->filter.set) {
- val = repr->attribute("filter");
- if (val) {
- sp_style_read_ifilter(val, style, (object) ? object->document : NULL);
- }
+ /* 3 Presentation attributes */
+ // std::cout << " MERGING PRESENTATION ATTRIBUTES" << std::endl;
+ for(std::vector<SPIBase*>::size_type i = 0; i != _properties.size(); ++i) {
+ _properties[i]->readAttribute( repr );
}
- SPS_READ_PENUM_IF_UNSET(&style->enable_background, repr,
- "enable-background", enum_enable_background, true);
-
- /* clip-rule */
- SPS_READ_PENUM_IF_UNSET(&style->clip_rule, repr, "clip-rule", enum_clip_rule, true);
-
- /* color_rendering, image_rendering, shape_rendering, text_rendering */
- SPS_READ_PENUM_IF_UNSET(&style->color_rendering, repr, "color-rendering", enum_color_rendering, true);
- SPS_READ_PENUM_IF_UNSET(&style->image_rendering, repr, "image-rendering", enum_image_rendering, true);
- SPS_READ_PENUM_IF_UNSET(&style->shape_rendering, repr, "shape-rendering", enum_shape_rendering, true);
- SPS_READ_PENUM_IF_UNSET(&style->text_rendering, repr, "text-rendering", enum_text_rendering, true);
+ // for(SPPropMap::iterator i = _propmap.begin(); i != _propmap.end(); ++i ) {
+ // (this->*(i->second)).readAttribute( repr );
+ // }
- /* 3. Merge from parent */
- if (object) {
- if (object->parent) {
- sp_style_merge_from_parent(style, object->parent->style);
+ /* 4 Cascade from parent */
+ // std::cout << " CASCADING FROM PARENT" << std::endl;
+ if( object ) {
+ if( object->parent ) {
+ cascade( object->parent->style );
}
} else {
- if (repr->parent()) {
- /// \todo fixme: This is not the prettiest thing (Lauris)
- SPStyle *parent = sp_style_new(NULL);
- sp_style_read(parent, NULL, repr->parent());
- sp_style_merge_from_parent(style, parent);
- sp_style_unref(parent);
+ // When does this happen?
+ // std::cout << "SPStyle::read(): reading via repr->parent()" << std::endl;
+ if( repr->parent() ) {
+ SPStyle *parent = new SPStyle();
+ parent->read( NULL, repr->parent() );
+ cascade( parent );
+ delete parent;
}
}
}
-
-/**
- * Read style properties from object's repr.
- *
- * 1. Reset existing object style
- * 2. Load current effective object style
- * 3. Load i attributes from immediate parent (which has to be up-to-date)
- */
+// Matches void sp_style_read_from_object(SPStyle *style, SPObject *object);
void
-sp_style_read_from_object(SPStyle *style, SPObject *object)
-{
- g_return_if_fail(style != NULL);
+SPStyle::readFromObject( SPObject *object ) {
+
+ // std::cout << "SPStyle::readFromObject: "<< (object->getId()?object->getId():"null")<< std::endl;
+
g_return_if_fail(object != NULL);
g_return_if_fail(SP_IS_OBJECT(object));
Inkscape::XML::Node *repr = object->getRepr();
g_return_if_fail(repr != NULL);
- sp_style_read(style, object, repr);
+ read( object, repr );
}
-
-/**
- * Read style properties from preferences.
- * @param style The style to write to
- * @param path Preferences directory from which the style should be read
- */
+// Matches sp_style_merge_property(SPStyle *style, gint id, gchar const *val)
void
-sp_style_read_from_prefs(SPStyle *style, Glib::ustring const &path)
-{
- g_return_if_fail(style != NULL);
- g_return_if_fail(path != "");
-
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
-
- // not optimal: we reconstruct the node based on the prefs, then pass it to
- // sp_style_read for actual processing.
- Inkscape::XML::SimpleDocument *tempdoc = new Inkscape::XML::SimpleDocument;
- Inkscape::XML::Node *tempnode = tempdoc->createElement("temp");
+SPStyle::readIfUnset( gint id, gchar const *val ) {
- std::vector<Inkscape::Preferences::Entry> attrs = prefs->getAllEntries(path);
- for (std::vector<Inkscape::Preferences::Entry>::iterator i = attrs.begin(); i != attrs.end(); ++i) {
- tempnode->setAttribute(i->getEntryName().data(), i->getString().data());
- }
-
- sp_style_read(style, NULL, tempnode);
-
- Inkscape::GC::release(tempnode);
- Inkscape::GC::release(tempdoc);
- delete tempdoc;
-}
-
-
-
-/**
- *
- */
-static void
-sp_style_privatize_text(SPStyle *style)
-{
- SPTextStyle *text = style->text;
- style->text = sp_text_style_duplicate_unset(style->text);
- sp_text_style_unref(text);
- style->text_private = TRUE;
-}
-
-
-/**
- * Merge property into style.
- *
- * Should be called in order of highest to lowest precedence.
- * E.g. for a single style string, call from the last declaration to the first,
- * as CSS says that later declarations override earlier ones.
- *
- * \pre val != NULL.
- */
-static void
-sp_style_merge_property(SPStyle *style, gint id, gchar const *val)
-{
+ // std::cout << "SPStyle::readIfUnset: Entrance: " << (val?val:"null") << std::endl;
+ // To Do: If it is not too slow, use std::map instead of std::vector inorder to remove switch()
+ // (looking up SP_PROP_xxxx already uses a hash).
g_return_if_fail(val != NULL);
switch (id) {
case SP_PROP_INKSCAPE_FONT_SPEC:
- if (!style->text_private) sp_style_privatize_text(style);
- if (!style->text->font_specification.set) {
- gchar *val_unquoted = attribute_unquote(val);
- sp_style_read_istring(&style->text->font_specification, val_unquoted);
- if (val_unquoted) g_free (val_unquoted);
- }
+ font_specification.readIfUnset( val );
break;
- /* CSS2 */
- /* Font */
case SP_PROP_FONT_FAMILY:
- if (!style->text_private) sp_style_privatize_text(style);
- if (!style->text->font_family.set) {
- gchar *val_unquoted = attribute_unquote(val);
- sp_style_read_istring(&style->text->font_family, val_unquoted);
- if (val_unquoted) g_free (val_unquoted);
- }
+ font_family.readIfUnset( val );
break;
case SP_PROP_FONT_SIZE:
- SPS_READ_IFONTSIZE_IF_UNSET(&style->font_size, val);
+ font_size.readIfUnset( val );
break;
case SP_PROP_FONT_SIZE_ADJUST:
if (strcmp(val, "none") != 0) {
@@ -991,220 +616,74 @@ sp_style_merge_property(SPStyle *style, gint id, gchar const *val)
}
break;
case SP_PROP_FONT_STYLE:
- SPS_READ_IENUM_IF_UNSET(&style->font_style, val, enum_font_style, true);
+ font_style.readIfUnset( val );
break;
case SP_PROP_FONT_VARIANT:
- SPS_READ_IENUM_IF_UNSET(&style->font_variant, val, enum_font_variant, true);
+ font_variant.readIfUnset( val );
break;
case SP_PROP_FONT_WEIGHT:
- SPS_READ_IENUM_IF_UNSET(&style->font_weight, val, enum_font_weight, true);
+ font_weight.readIfUnset( val );
break;
case SP_PROP_FONT_STRETCH:
- SPS_READ_IENUM_IF_UNSET(&style->font_stretch, val, enum_font_stretch, true);
+ font_stretch.readIfUnset( val );
break;
case SP_PROP_FONT:
- if (!style->text_private) sp_style_privatize_text(style);
- if (!style->text->font.set) {
- g_free(style->text->font.value);
- style->text->font.value = g_strdup(val);
- style->text->font.set = TRUE;
- style->text->font.inherit = (val && !strcmp(val, "inherit"));
-
- // Break string into white space separated tokens
- std::stringstream os( val );
- Glib::ustring param;
-
- while (os >> param) {
-
- // CSS is case insensitive but we're comparing against lowercase strings
- Glib::ustring lparam = param.lowercase();
-
- if (lparam == "/") {
-
- os >> param;
- // Eat the line-height for the moment as it is not an SVG property.
- // lparam = param.lowercase();
- // sp_style_read_ilengthornormal(&style->line_height, lparam);
-
- } else {
-
- // Skip if "normal" as that is the default (and we don't know which attribute it applies to).
- if (lparam == "normal") continue;
-
- // Check each property in turn
-
- // font-style
- SPIEnum test_style;
- test_style.set = FALSE;
-
- // Read once to see if param is valid style. If valid, .set will be TRUE.
- sp_style_read_ienum(&test_style, lparam.c_str(), enum_font_style, true);
-
- // If valid style parameter
- if (test_style.set) {
-
- // If not previously set
- if (!style->font_style.set) {
- style->font_style.set = TRUE;
- style->font_style.inherit = test_style.inherit;
- style->font_style.value = test_style.value;
- style->font_style.computed = test_style.computed;
- }
- continue; // Next parameter.
- }
-
- // font-variant (small-caps)
- SPIEnum test_variant;
- test_variant.set = FALSE;
- sp_style_read_ienum(&test_variant, lparam.c_str(), enum_font_variant, true);
-
- // If valid variant parameter
- if (test_variant.set) {
-
- // If not previously set
- if (!style->font_variant.set) {
- style->font_variant.set = TRUE;
- style->font_variant.inherit = test_variant.inherit;
- style->font_variant.value = test_variant.value;
- style->font_variant.computed = test_variant.computed;
- }
- continue; // Next parameter.
- }
-
- // font-weight
- SPIEnum test_weight;
- test_weight.set = FALSE;
- sp_style_read_ienum(&test_weight, lparam.c_str(), enum_font_weight, true);
-
- // If valid weight parameter
- if (test_weight.set) {
-
- // If not previously set
- if (!style->font_weight.set) {
- style->font_weight.set = TRUE;
- style->font_weight.inherit = test_weight.inherit;
- style->font_weight.value = test_weight.value;
- style->font_weight.computed = test_weight.computed;
- }
- continue; // Next parameter
- }
-
- // Font-size
- SPIFontSize test_size;
- test_size.set = FALSE;
-
- // Read once to see if param is valid size.
- sp_style_read_ifontsize( &test_size, lparam.c_str() );
-
- // If valid size parameter
- if (test_size.set) {
-
- // If not previously set
- if (!style->font_size.set) {
- style->font_size.set = TRUE;
- style->font_size.inherit = test_size.inherit;
- style->font_size.unit = test_size.unit;
- style->font_size.value = test_size.value;
- style->font_size.computed = test_size.computed;
- style->font_size.type = test_size.type;
- style->font_size.literal = test_size.literal;
- }
- continue;
- }
-
- // No valid property value found.
- break;
- }
- } // params
-
- // The rest must be font-family...
- std::string val_s = val;
- std::string family = val_s.substr( val_s.find( param ) );
-
- if (!style->text_private) sp_style_privatize_text(style);
- if (!style->text->font_family.set) {
- gchar *val_unquoted = attribute_unquote( family.c_str() );
- sp_style_read_istring(&style->text->font_family, val_unquoted);
- if (val_unquoted) g_free (val_unquoted);
- }
-
- // Set all properties to their default values per CSS 2.1 spec if not already set
- SPS_READ_IFONTSIZE_IF_UNSET(&style->font_size, "medium" );
- SPS_READ_IENUM_IF_UNSET(&style->font_style, "normal", enum_font_style, true);
- SPS_READ_IENUM_IF_UNSET(&style->font_variant, "normal", enum_font_variant, true);
- SPS_READ_IENUM_IF_UNSET(&style->font_weight, "normal", enum_font_weight, true);
- // Line height is not an SVG property but Inkscape uses it for multi-line text.
- // sp_style_read_ilengthornormal(&style->line_height, "normal");
-
- }
-
+ font.readIfUnset( val );
break;
/* Text */
case SP_PROP_TEXT_INDENT:
- SPS_READ_ILENGTH_IF_UNSET(&style->text_indent, val);
+ text_indent.readIfUnset( val );
break;
case SP_PROP_TEXT_ALIGN:
- SPS_READ_IENUM_IF_UNSET(&style->text_align, val, enum_text_align, true);
+ text_align.readIfUnset( val );
break;
case SP_PROP_TEXT_DECORATION:
- if (!style->text_decoration_line.set) {
- sp_style_read_itextdecoration(&style->text_decoration_line, &style->text_decoration_style, &style->text_decoration_color, val);
- }
+ text_decoration.readIfUnset( val );
break;
case SP_PROP_TEXT_DECORATION_LINE:
- if (!style->text_decoration_line.set) {
- sp_style_read_itextdecorationLine(&style->text_decoration_line, val);
- }
+ text_decoration_line.readIfUnset( val );
break;
case SP_PROP_TEXT_DECORATION_STYLE:
- if (!style->text_decoration_style.set) {
- sp_style_read_itextdecorationStyle(&style->text_decoration_style, val);
- }
+ text_decoration_style.readIfUnset( val );
break;
case SP_PROP_TEXT_DECORATION_COLOR:
- if (!style->text_decoration_color.set) {
- sp_style_read_itextdecorationColor(&style->text_decoration_color, val);
- }
+ text_decoration_color.readIfUnset( val );
break;
case SP_PROP_LINE_HEIGHT:
- if (!style->line_height.set) {
- sp_style_read_ilengthornormal(&style->line_height, val);
- }
+ line_height.readIfUnset( val );
break;
case SP_PROP_LETTER_SPACING:
- if (!style->letter_spacing.set) {
- sp_style_read_ilengthornormal(&style->letter_spacing, val);
- }
+ letter_spacing.readIfUnset( val );
break;
case SP_PROP_WORD_SPACING:
- if (!style->word_spacing.set) {
- sp_style_read_ilengthornormal(&style->word_spacing, val);
- }
+ word_spacing.readIfUnset( val );
break;
case SP_PROP_TEXT_TRANSFORM:
- SPS_READ_IENUM_IF_UNSET(&style->text_transform, val, enum_text_transform, true);
+ text_transform.readIfUnset( val );
break;
/* Text (css3) */
case SP_PROP_DIRECTION:
- SPS_READ_IENUM_IF_UNSET(&style->direction, val, enum_direction, true);
+ direction.readIfUnset( val );
break;
case SP_PROP_BLOCK_PROGRESSION:
- SPS_READ_IENUM_IF_UNSET(&style->block_progression, val, enum_block_progression, true);
+ block_progression.readIfUnset( val );
break;
case SP_PROP_WRITING_MODE:
- SPS_READ_IENUM_IF_UNSET(&style->writing_mode, val, enum_writing_mode, true);
+ writing_mode.readIfUnset( val );
break;
case SP_PROP_TEXT_ANCHOR:
- SPS_READ_IENUM_IF_UNSET(&style->text_anchor, val, enum_text_anchor, true);
+ text_anchor.readIfUnset( val );
+ break;
+ case SP_PROP_WHITE_SPACE:
+ white_space.readIfUnset( val );
break;
case SP_PROP_BASELINE_SHIFT:
- SPS_READ_IBASELINE_SHIFT_IF_UNSET(&style->baseline_shift, val);
+ baseline_shift.readIfUnset( val );
break;
- case SP_PROP_TEXT_RENDERING: {
- SPS_READ_IENUM_IF_UNSET(&style->text_rendering, val, enum_text_rendering, true);
+ case SP_PROP_TEXT_RENDERING:
+ text_rendering.readIfUnset( val );
break;
- }
case SP_PROP_ALIGNMENT_BASELINE:
g_warning("Unimplemented style property SP_PROP_ALIGNMENT_BASELINE: value: %s", val);
break;
@@ -1225,31 +704,25 @@ sp_style_merge_property(SPStyle *style, gint id, gchar const *val)
g_warning("Unimplemented style property SP_PROP_CLIP: value: %s", val);
break;
case SP_PROP_COLOR:
- if (!style->color.set) {
- sp_style_read_icolor(&style->color, val, style, (style->object) ? style->object->document : NULL);
- }
+ color.readIfUnset( val );
break;
case SP_PROP_CURSOR:
g_warning("Unimplemented style property SP_PROP_CURSOR: value: %s", val);
break;
case SP_PROP_DISPLAY:
- SPS_READ_IENUM_IF_UNSET(&style->display, val, enum_display, true);
+ display.readIfUnset( val );
break;
case SP_PROP_OVERFLOW:
- /** \todo
- * FIXME: not supported properly yet, we just read and write it,
- * but act as if it is always "display".
- */
- SPS_READ_IENUM_IF_UNSET(&style->overflow, val, enum_overflow, true);
+ overflow.readIfUnset( val );
break;
case SP_PROP_VISIBILITY:
- SPS_READ_IENUM_IF_UNSET(&style->visibility, val, enum_visibility, true);
+ visibility.readIfUnset( val );
break;
case SP_PROP_ISOLATION:
- SPS_READ_IENUM_IF_UNSET(&style->isolation, val, enum_isolation, true);
+ isolation.readIfUnset( val );
break;
- case SP_PROP_BLEND_MODE:
- SPS_READ_IENUM_IF_UNSET(&style->blend_mode, val, enum_blend_mode, true);
+ case SP_PROP_MIX_BLEND_MODE:
+ mix_blend_mode.readIfUnset( val );
break;
/* SVG */
@@ -1264,12 +737,10 @@ sp_style_merge_property(SPStyle *style, gint id, gchar const *val)
g_warning("attribute 'clip-path' given as CSS");
//XML Tree being directly used here.
- style->object->getRepr()->setAttribute("clip-path", val);
+ this->object->getRepr()->setAttribute("clip-path", val);
break;
case SP_PROP_CLIP_RULE:
- if (!style->clip_rule.set) {
- sp_style_read_ienum(&style->clip_rule, val, enum_clip_rule, true);
- }
+ clip_rule.readIfUnset( val );
break;
case SP_PROP_MASK:
/** \todo
@@ -1278,22 +749,17 @@ sp_style_merge_property(SPStyle *style, gint id, gchar const *val)
g_warning("attribute 'mask' given as CSS");
//XML Tree being directly used here.
- style->object->getRepr()->setAttribute("mask", val);
+ this->object->getRepr()->setAttribute("mask", val);
break;
case SP_PROP_OPACITY:
- if (!style->opacity.set) {
- sp_style_read_iscale24(&style->opacity, val);
- }
+ opacity.readIfUnset( val );
break;
case SP_PROP_ENABLE_BACKGROUND:
- SPS_READ_IENUM_IF_UNSET(&style->enable_background, val,
- enum_enable_background, true);
+ enable_background.readIfUnset( val );
break;
/* Filter */
case SP_PROP_FILTER:
- if (!style->filter.set && !style->filter.inherit) {
- sp_style_read_ifilter(val, style, (style->object) ? style->object->document : NULL);
- }
+ if( !filter.inherit ) filter.readIfUnset( val );
break;
case SP_PROP_FLOOD_COLOR:
g_warning("Unimplemented style property SP_PROP_FLOOD_COLOR: value: %s", val);
@@ -1318,139 +784,192 @@ sp_style_merge_property(SPStyle *style, gint id, gchar const *val)
/* Paint */
case SP_PROP_COLOR_INTERPOLATION:
// We read it but issue warning
- SPS_READ_IENUM_IF_UNSET(&style->color_interpolation, val, enum_color_interpolation, true);
- if( style->color_interpolation.value != SP_CSS_COLOR_INTERPOLATION_SRGB ) {
+ color_interpolation.readIfUnset( val );
+ if( color_interpolation.value != SP_CSS_COLOR_INTERPOLATION_SRGB ) {
g_warning("Inkscape currently only supports color-interpolation = sRGB");
}
break;
case SP_PROP_COLOR_INTERPOLATION_FILTERS:
- SPS_READ_IENUM_IF_UNSET(&style->color_interpolation_filters, val, enum_color_interpolation, true);
+ color_interpolation_filters.readIfUnset( val );
break;
case SP_PROP_COLOR_PROFILE:
g_warning("Unimplemented style property SP_PROP_COLOR_PROFILE: value: %s", val);
break;
- case SP_PROP_COLOR_RENDERING: {
- SPS_READ_IENUM_IF_UNSET(&style->color_rendering, val, enum_color_rendering, true);
+ case SP_PROP_COLOR_RENDERING:
+ color_rendering.readIfUnset( val );
+ break;
+ case SP_PROP_SOLID_COLOR:
+ solid_color.readIfUnset( val );
+ break;
+ case SP_PROP_SOLID_OPACITY:
+ solid_opacity.readIfUnset( val );
break;
- }
case SP_PROP_FILL:
- if (!style->fill.set) {
- style->fill.read( val, *style, (style->object) ? style->object->document : NULL );
- }
+ fill.readIfUnset( val );
break;
case SP_PROP_FILL_OPACITY:
- if (!style->fill_opacity.set) {
- sp_style_read_iscale24(&style->fill_opacity, val);
- }
+ fill_opacity.readIfUnset( val );
break;
case SP_PROP_FILL_RULE:
- if (!style->fill_rule.set) {
- sp_style_read_ienum(&style->fill_rule, val, enum_fill_rule, true);
- }
+ fill_rule.readIfUnset( val );
break;
- case SP_PROP_IMAGE_RENDERING: {
- SPS_READ_IENUM_IF_UNSET(&style->image_rendering, val, enum_image_rendering, true);
+ case SP_PROP_IMAGE_RENDERING:
+ image_rendering.readIfUnset( val );
break;
- }
case SP_PROP_MARKER:
- /* TODO: Call sp_uri_reference_resolve(SPDocument *document, guchar const *uri) */
- /* style->marker[SP_MARKER_LOC] = g_quark_from_string(val); */
- if (!style->marker[SP_MARKER_LOC].set) {
- g_free(style->marker[SP_MARKER_LOC].value);
- style->marker[SP_MARKER_LOC].value = g_strdup(val);
- style->marker[SP_MARKER_LOC].set = TRUE;
- style->marker[SP_MARKER_LOC].inherit = (val && !strcmp(val, "inherit"));
- }
+ /* TODO: Call sp_uri_reference_resolve(SPDocument *document, guchar const *uri) */
+ marker.readIfUnset( val );
break;
-
case SP_PROP_MARKER_START:
/* TODO: Call sp_uri_reference_resolve(SPDocument *document, guchar const *uri) */
- if (!style->marker[SP_MARKER_LOC_START].set) {
- g_free(style->marker[SP_MARKER_LOC_START].value);
- style->marker[SP_MARKER_LOC_START].value = g_strdup(val);
- style->marker[SP_MARKER_LOC_START].set = TRUE;
- style->marker[SP_MARKER_LOC_START].inherit = (val && !strcmp(val, "inherit"));
- }
+ marker_start.readIfUnset( val );
break;
case SP_PROP_MARKER_MID:
/* TODO: Call sp_uri_reference_resolve(SPDocument *document, guchar const *uri) */
- if (!style->marker[SP_MARKER_LOC_MID].set) {
- g_free(style->marker[SP_MARKER_LOC_MID].value);
- style->marker[SP_MARKER_LOC_MID].value = g_strdup(val);
- style->marker[SP_MARKER_LOC_MID].set = TRUE;
- style->marker[SP_MARKER_LOC_MID].inherit = (val && !strcmp(val, "inherit"));
- }
+ marker_mid.readIfUnset( val );
break;
case SP_PROP_MARKER_END:
/* TODO: Call sp_uri_reference_resolve(SPDocument *document, guchar const *uri) */
- if (!style->marker[SP_MARKER_LOC_END].set) {
- g_free(style->marker[SP_MARKER_LOC_END].value);
- style->marker[SP_MARKER_LOC_END].value = g_strdup(val);
- style->marker[SP_MARKER_LOC_END].set = TRUE;
- style->marker[SP_MARKER_LOC_END].inherit = (val && !strcmp(val, "inherit"));
- }
+ marker_end.readIfUnset( val );
break;
-
- case SP_PROP_SHAPE_RENDERING: {
- SPS_READ_IENUM_IF_UNSET(&style->shape_rendering, val, enum_shape_rendering, true);
+ case SP_PROP_SHAPE_RENDERING:
+ shape_rendering.readIfUnset( val );
break;
- }
-
case SP_PROP_STROKE:
- if (!style->stroke.set) {
- style->stroke.read( val, *style, (style->object) ? style->object->document : NULL );
- }
+ stroke.readIfUnset( val );
break;
case SP_PROP_STROKE_WIDTH:
- SPS_READ_ILENGTH_IF_UNSET(&style->stroke_width, val);
+ stroke_width.readIfUnset( val );
break;
case SP_PROP_STROKE_DASHARRAY:
- if (!style->stroke_dasharray.set) {
- sp_style_read_dash(style, val);
- }
+ stroke_dasharray.readIfUnset( val );
break;
case SP_PROP_STROKE_DASHOFFSET:
- SPS_READ_ILENGTH_IF_UNSET(&style->stroke_dashoffset, val);
+ stroke_dashoffset.readIfUnset( val );
break;
case SP_PROP_STROKE_LINECAP:
- if (!style->stroke_linecap.set) {
- sp_style_read_ienum(&style->stroke_linecap, val, enum_stroke_linecap, true);
- }
+ stroke_linecap.readIfUnset( val );
break;
case SP_PROP_STROKE_LINEJOIN:
- if (!style->stroke_linejoin.set) {
- sp_style_read_ienum(&style->stroke_linejoin, val, enum_stroke_linejoin, true);
- }
+ stroke_linejoin.readIfUnset( val );
break;
case SP_PROP_STROKE_MITERLIMIT:
- if (!style->stroke_miterlimit.set) {
- sp_style_read_ifloat(&style->stroke_miterlimit, val);
- }
+ stroke_miterlimit.readIfUnset( val );
break;
case SP_PROP_STROKE_OPACITY:
- if (!style->stroke_opacity.set) {
- sp_style_read_iscale24(&style->stroke_opacity, val);
- }
+ stroke_opacity.readIfUnset( val );
break;
case SP_PROP_PAINT_ORDER:
- if (!style->paint_order.set) {
- sp_style_read_ipaintorder(&style->paint_order, val);
- }
+ paint_order.readIfUnset( val );
break;
-
default:
- g_warning("Invalid style property id: %d value: %s", id, val);
+ g_warning("SPIStyle::readIfUnset(): Invalid style property id: %d value: %s", id, val);
break;
}
}
-static void
-sp_style_merge_style_from_decl(SPStyle *const style, CRDeclaration const *const decl)
-{
- /** \todo Ensure that property is lcased, as per
- * http://www.w3.org/TR/REC-CSS2/syndata.html#q4.
- * Should probably be done in libcroco.
- */
+Glib::ustring
+SPStyle::write( guint const flags, SPStyle const *const base ) const {
+
+ // std::cout << "SPStyle::write" << std::endl;
+
+ Glib::ustring style_string;
+ for(std::vector<SPIBase*>::size_type i = 0; i != _properties.size(); ++i) {
+ if( base != NULL ) {
+ style_string += _properties[i]->write( flags, base->_properties[i] );
+ } else {
+ style_string += _properties[i]->write( flags, NULL );
+ }
+ }
+ // for(SPPropMap::iterator i = _propmap.begin(); i != _propmap.end(); ++i ) {
+ // if( base != NULL ) {
+ // style_string += (this->*(i->second)).write( flags, &(base->*(i->second)) );
+ // } else {
+ // style_string += (this->*(i->second)).write( flags, NULL );
+ // }
+ // }
+
+ // Remove trailing ';'
+ if( style_string.size() > 0 ) {
+ style_string.erase( style_string.size() - 1 );
+ }
+ return style_string;
+}
+
+// Corresponds to sp_style_merge_from_parent()
+void
+SPStyle::cascade( SPStyle const *const parent ) {
+ // std::cout << "SPStyle::cascade" << std::endl;
+ for(std::vector<SPIBase*>::size_type i = 0; i != _properties.size(); ++i) {
+ _properties[i]->cascade( parent->_properties[i] );
+ }
+ // for(SPPropMap::iterator i = _propmap.begin(); i != _propmap.end(); ++i ) {
+ // (this->*(i->second)).cascade( &(parent->*(i->second)) );
+ // }
+}
+
+// Corresponds to sp_style_merge_from_dying_parent()
+void
+SPStyle::merge( SPStyle const *const parent ) {
+ // std::cout << "SPStyle::merge" << std::endl;
+ for(std::vector<SPIBase*>::size_type i = 0; i != _properties.size(); ++i) {
+ _properties[i]->merge( parent->_properties[i] );
+ }
+ // for(SPPropMap::iterator i = _propmap.begin(); i != _propmap.end(); ++i ) {
+ // (this->*(i->second)).cascade( &(parent->*(i->second)) );
+ // }
+}
+
+// Mostly for unit testing
+bool
+SPStyle::operator==(const SPStyle& rhs) {
+
+ // Uncomment for testing
+ // for(std::vector<SPIBase*>::size_type i = 0; i != _properties.size(); ++i) {
+ // if( *_properties[i] != *rhs._properties[i])
+ // std::cout << _properties[i]->name << ": "
+ // << _properties[i]->write(SP_STYLE_FLAG_ALWAYS,NULL) << " "
+ // << rhs._properties[i]->write(SP_STYLE_FLAG_ALWAYS,NULL)
+ // << (*_properties[i] == *rhs._properties[i]) << std::endl;
+ // }
+
+ for(std::vector<SPIBase*>::size_type i = 0; i != _properties.size(); ++i) {
+ if( *_properties[i] != *rhs._properties[i]) return false;
+ }
+ return true;
+}
+
+void
+SPStyle::_mergeString( gchar const *const p ) {
+
+ // std::cout << "SPStyle::_mergeString: " << (p?p:"null") << std::endl;
+ CRDeclaration *const decl_list
+ = cr_declaration_parse_list_from_buf(reinterpret_cast<guchar const *>(p), CR_UTF_8);
+ if (decl_list) {
+ _mergeDeclList( decl_list );
+ cr_declaration_destroy(decl_list);
+ }
+}
+
+void
+SPStyle::_mergeDeclList( CRDeclaration const *const decl_list ) {
+
+ // std::cout << "SPStyle::_mergeDeclList" << std::endl;
+
+ // In reverse order, as later declarations to take precedence over earlier ones.
+ // (Properties are only set if not previously set. See:
+ // Ref: http://www.w3.org/TR/REC-CSS2/cascade.html#cascading-order point 4.)
+ if (decl_list->next) {
+ _mergeDeclList( decl_list->next );
+ }
+ _mergeDecl( decl_list );
+}
+
+void
+SPStyle::_mergeDecl( CRDeclaration const *const decl ) {
+
+ // std::cout << "SPStyle::_mergeDecl" << std::endl;
+
unsigned const prop_idx = sp_attribute_lookup(decl->property->stryng->str);
if (prop_idx != SP_ATTR_INVALID) {
/** \todo
@@ -1460,71 +979,30 @@ sp_style_merge_style_from_decl(SPStyle *const style, CRDeclaration const *const
*/
guchar *const str_value_unsigned = cr_term_to_string(decl->value);
gchar *const str_value = reinterpret_cast<gchar *>(str_value_unsigned);
- sp_style_merge_property(style, prop_idx, str_value);
+ readIfUnset( prop_idx, str_value );
g_free(str_value);
}
}
-static void
-sp_style_merge_from_props(SPStyle *const style, CRPropList *const props)
-{
-#if 0 /* forwards */
- for (CRPropList const *cur = props; cur; cur = cr_prop_list_get_next(cur)) {
- CRDeclaration *decl = NULL;
- cr_prop_list_get_decl(cur, &decl);
- sp_style_merge_style_from_decl(style, decl);
- }
-#else /* in reverse order, as we need later declarations to take precedence over earlier ones. */
+void
+SPStyle::_mergeProps( CRPropList *const props ) {
+
+ // std::cout << "SPStyle::_mergeProps" << std::endl;
+
+ // In reverse order, as later declarations to take precedence over earlier ones.
if (props) {
- sp_style_merge_from_props(style, cr_prop_list_get_next(props));
+ _mergeProps( cr_prop_list_get_next( props ) );
CRDeclaration *decl = NULL;
cr_prop_list_get_decl(props, &decl);
- sp_style_merge_style_from_decl(style, decl);
- }
-#endif
-}
-
-/**
- * \pre decl_list != NULL
- */
-static void
-sp_style_merge_from_decl_list(SPStyle *const style, CRDeclaration const *const decl_list)
-{
- // read the decls from end to start, using head recursion, so that latter declarations override
- // (Ref: http://www.w3.org/TR/REC-CSS2/cascade.html#cascading-order point 4.)
- // because sp_style_merge_style_from_decl only sets properties that are unset
- if (decl_list->next) {
- sp_style_merge_from_decl_list(style, decl_list->next);
+ _mergeDecl( decl );
}
- sp_style_merge_style_from_decl(style, decl_list);
}
-static CRSelEng *
-sp_repr_sel_eng()
-{
- CRSelEng *const ret = cr_sel_eng_new();
- cr_sel_eng_set_node_iface(ret, &Inkscape::XML::croco_node_iface);
-
- /** \todo
- * Check whether we need to register any pseudo-class handlers.
- * libcroco has its own default handlers for first-child and lang.
- *
- * We probably want handlers for link and arguably visited (though
- * inkscape can't visit links at the time of writing). hover etc.
- * more useful in inkview than the editor inkscape.
- *
- * http://www.w3.org/TR/SVG11/styling.html#StylingWithCSS says that
- * the following should be honoured, at least by inkview:
- * :hover, :active, :focus, :visited, :link.
- */
+void
+SPStyle::_mergeObjectStylesheet( SPObject const *const object ) {
- g_assert(ret);
- return ret;
-}
+ // std::cout << "SPStyle::_mergeObjectStylesheet: " << (object->getId()?object->getId():"null") << std::endl;
-static void
-sp_style_merge_from_object_stylesheet(SPStyle *const style, SPObject const *const object)
-{
static CRSelEng *sel_eng = NULL;
if (!sel_eng) {
sel_eng = sp_repr_sel_eng();
@@ -1540,586 +1018,321 @@ sp_style_merge_from_object_stylesheet(SPStyle *const style, SPObject const *cons
g_return_if_fail(status == CR_OK);
/// \todo Check what errors can occur, and handle them properly.
if (props) {
- sp_style_merge_from_props(style, props);
+ _mergeProps(props);
cr_prop_list_destroy(props);
}
}
+// Internal
/**
- * Parses a style="..." string and merges it with an existing SPStyle.
+ * Release callback.
*/
-void
-sp_style_merge_from_style_string(SPStyle *const style, gchar const *const p)
-{
- /*
- * Reference: http://www.w3.org/TR/SVG11/styling.html#StyleAttribute:
- * ``When CSS styling is used, CSS inline style is specified by including
- * semicolon-separated property declarations of the form "name : value"
- * within the style attribute''.
- *
- * That's fairly ambiguous. Is a `value' allowed to contain semicolons?
- * Why does it say "including", what else is allowed in the style
- * attribute value?
- */
-
- CRDeclaration *const decl_list
- = cr_declaration_parse_list_from_buf(reinterpret_cast<guchar const *>(p), CR_UTF_8);
- if (decl_list) {
- sp_style_merge_from_decl_list(style, decl_list);
- cr_declaration_destroy(decl_list);
- }
-}
-
-/** Indexed by SP_CSS_FONT_SIZE_blah. */
-static float const font_size_table[] = {6.0, 8.0, 10.0, 12.0, 14.0, 18.0, 24.0};
-
static void
-sp_style_merge_font_size_from_parent(SPIFontSize &child, SPIFontSize const &parent)
+sp_style_object_release(SPObject *object, SPStyle *style)
{
- /* 'font-size' */
- if (!child.set || child.inherit) {
- /* Inherit the computed value. Reference: http://www.w3.org/TR/SVG11/styling.html#Inheritance */
- child.computed = parent.computed;
- } else if (child.type == SP_FONT_SIZE_LITERAL) {
- /** \todo
- * fixme: SVG and CSS do not specify clearly, whether we should use
- * user or screen coordinates (Lauris)
- */
- if (child.literal < SP_CSS_FONT_SIZE_SMALLER) {
- child.computed = font_size_table[child.literal];
- } else if (child.literal == SP_CSS_FONT_SIZE_SMALLER) {
- child.computed = parent.computed / 1.2;
- } else if (child.literal == SP_CSS_FONT_SIZE_LARGER) {
- child.computed = parent.computed * 1.2;
- } else {
- /* Illegal value */
- }
- } else if (child.type == SP_FONT_SIZE_PERCENTAGE) {
- /* Unlike most other lengths, percentage for font size is relative to parent computed value
- * rather than viewport. */
- child.computed = parent.computed * child.value;
- } else if (child.type == SP_FONT_SIZE_LENGTH) {
- switch (child.unit) {
- case SP_CSS_UNIT_EM:
- /* Relative to parent font size */
- child.computed = parent.computed * child.value;
- break;
- case SP_CSS_UNIT_EX:
- /* Relative to parent font size */
- child.computed = parent.computed * child.value * 0.5; /* Hack */
- break;
- default:
- /* No change */
- break;
- }
- }
+ (void)object; // TODO
+ style->object = NULL;
}
-// Some shifts are defined relative to parent.
+// Internal
+/**
+ * Emit style modified signal on style's object if the filter changed.
+ */
static void
-sp_style_merge_baseline_shift_from_parent(SPIBaselineShift &child, SPIBaselineShift const &parent,
- SPIFontSize const &pfont_size)
+sp_style_filter_ref_modified(SPObject *obj, guint flags, SPStyle *style)
{
- /* 'baseline-shift' */
- if (!child.set || child.inherit) {
- /* Inherit the computed value. Reference: http://www.w3.org/TR/SVG11/styling.html#Inheritance */
- child.computed = parent.computed; // Does this make sense (applying a shift a second time)?
- } else if (child.type == SP_BASELINE_SHIFT_LITERAL) {
- if( child.literal == SP_CSS_BASELINE_SHIFT_BASELINE ) {
- child.computed = 0; // No change
- } else if (child.literal == SP_CSS_BASELINE_SHIFT_SUB ) {
- // Should use subscript position from font relative to alphabetic baseline
- // OpenOffice, Adobe: -0.33, Word -0.14, LaTex about -0.2.
- child.computed = -0.2 * pfont_size.computed;
- } else if (child.literal == SP_CSS_BASELINE_SHIFT_SUPER ) {
- // Should use superscript position from font relative to alphabetic baseline
- // OpenOffice, Adobe: 0.33, Word 0.35, LaTex about 0.45.
- child.computed = 0.4 * pfont_size.computed;
- } else {
- /* Illegal value */
- }
- } else if (child.type == SP_BASELINE_SHIFT_PERCENTAGE) {
- // Percentage for baseline shift is relative to computed "line-height"
- // which is just font-size (see SVG1.1 'font').
- child.computed = pfont_size.computed * child.value;
- } else if (child.type == SP_BASELINE_SHIFT_LENGTH) {
- switch (child.unit) {
- case SP_CSS_UNIT_EM:
- child.computed = child.value * pfont_size.computed;
- break;
- case SP_CSS_UNIT_EX:
- child.computed = child.value * 0.5 * pfont_size.computed;
- break;
- default:
- /* No change */
- break;
+ (void)flags; // TODO
+ SPFilter *filter=static_cast<SPFilter *>(obj);
+ if (style->getFilter() == filter)
+ {
+ if (style->object) {
+ style->object->requestModified(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG);
}
}
- // baseline-shifts are relative to parent baseline
- child.computed += parent.computed;
}
+// Internal
/**
- * Sets computed values in \a style, which may involve inheriting from (or in some other way
- * calculating from) corresponding computed values of \a parent.
- *
- * References: http://www.w3.org/TR/SVG11/propidx.html shows what properties inherit by default.
- * http://www.w3.org/TR/SVG11/styling.html#Inheritance gives general rules as to what it means to
- * inherit a value. http://www.w3.org/TR/REC-CSS2/cascade.html#computed-value is more precise
- * about what the computed value is (not obvious for lengths).
- *
- * \pre \a parent's computed values are already up-to-date.
+ * Gets called when the filter is (re)attached to the style
*/
void
-sp_style_merge_from_parent(SPStyle *const style, SPStyle const *const parent)
+sp_style_filter_ref_changed(SPObject *old_ref, SPObject *ref, SPStyle *style)
{
- g_return_if_fail(style != NULL);
-
- /** \todo
- * fixme: Check for existing callers that might pass null parent.
- * This should probably be g_return_if_fail, or else we should make a
- * best attempt to set computed values correctly without having a parent
- * (i.e., by assuming parent has initial values).
- */
- if (!parent)
- return;
-
- /* CSS2 */
- /* Font */
- sp_style_merge_font_size_from_parent(style->font_size, parent->font_size);
-
- /* 'font-style' */
- if (!style->font_style.set || style->font_style.inherit) {
- style->font_style.computed = parent->font_style.computed;
- }
-
- /* 'font-variant' */
- if (!style->font_variant.set || style->font_variant.inherit) {
- style->font_variant.computed = parent->font_variant.computed;
- }
-
- /* 'font-weight' */
- if (!style->font_weight.set || style->font_weight.inherit) {
- style->font_weight.computed = parent->font_weight.computed;
- } else if (style->font_weight.value == SP_CSS_FONT_WEIGHT_NORMAL) {
- /** \todo
- * fixme: This is unconditional, i.e., happens even if parent not
- * present.
- */
- style->font_weight.computed = SP_CSS_FONT_WEIGHT_400;
- } else if (style->font_weight.value == SP_CSS_FONT_WEIGHT_BOLD) {
- style->font_weight.computed = SP_CSS_FONT_WEIGHT_700;
- } else if (style->font_weight.value == SP_CSS_FONT_WEIGHT_LIGHTER) {
- unsigned const parent_val = parent->font_weight.computed;
- g_assert(SP_CSS_FONT_WEIGHT_100 == 0);
- // strictly, 'bolder' and 'lighter' should go to the next weight
- // expressible in the current font family, but that's difficult to
- // find out, so jumping by 3 seems an appropriate approximation
- style->font_weight.computed = (parent_val <= SP_CSS_FONT_WEIGHT_100 + 3
- ? (unsigned)SP_CSS_FONT_WEIGHT_100
- : parent_val - 3);
- g_assert(style->font_weight.computed <= (unsigned) SP_CSS_FONT_WEIGHT_900);
- } else if (style->font_weight.value == SP_CSS_FONT_WEIGHT_BOLDER) {
- unsigned const parent_val = parent->font_weight.computed;
- g_assert(parent_val <= SP_CSS_FONT_WEIGHT_900);
- style->font_weight.computed = (parent_val >= SP_CSS_FONT_WEIGHT_900 - 3
- ? (unsigned)SP_CSS_FONT_WEIGHT_900
- : parent_val + 3);
- g_assert(style->font_weight.computed <= (unsigned) SP_CSS_FONT_WEIGHT_900);
- }
-
- /* 'font-stretch' */
- if (!style->font_stretch.set || style->font_stretch.inherit) {
- style->font_stretch.computed = parent->font_stretch.computed;
- } else if (style->font_stretch.value == SP_CSS_FONT_STRETCH_NARROWER) {
- unsigned const parent_val = parent->font_stretch.computed;
- style->font_stretch.computed = (parent_val == SP_CSS_FONT_STRETCH_ULTRA_CONDENSED
- ? parent_val
- : parent_val - 1);
- g_assert(style->font_stretch.computed <= (unsigned) SP_CSS_FONT_STRETCH_ULTRA_EXPANDED);
- } else if (style->font_stretch.value == SP_CSS_FONT_STRETCH_WIDER) {
- unsigned const parent_val = parent->font_stretch.computed;
- g_assert(parent_val <= SP_CSS_FONT_STRETCH_ULTRA_EXPANDED);
- style->font_stretch.computed = (parent_val == SP_CSS_FONT_STRETCH_ULTRA_EXPANDED
- ? parent_val
- : parent_val + 1);
- g_assert(style->font_stretch.computed <= (unsigned) SP_CSS_FONT_STRETCH_ULTRA_EXPANDED);
- }
-
- /* text (css2) */
- if (!style->text_indent.set || style->text_indent.inherit) {
- style->text_indent.computed = parent->text_indent.computed;
- }
-
- if (!style->text_align.set || style->text_align.inherit) {
- style->text_align.computed = parent->text_align.computed;
- }
-
- if (!style->text_decoration_line.set || style->text_decoration_line.inherit) {
- style->text_decoration_line.underline = parent->text_decoration_line.underline;
- style->text_decoration_line.overline = parent->text_decoration_line.overline;
- style->text_decoration_line.line_through = parent->text_decoration_line.line_through;
- style->text_decoration_line.blink = parent->text_decoration_line.blink;
- }
-
- if (!style->text_decoration_style.set || style->text_decoration_style.inherit) {
- style->text_decoration_style.solid = parent->text_decoration_style.solid;
- style->text_decoration_style.isdouble = parent->text_decoration_style.isdouble;
- style->text_decoration_style.dotted = parent->text_decoration_style.dotted;
- style->text_decoration_style.dashed = parent->text_decoration_style.dashed;
- style->text_decoration_style.wavy = parent->text_decoration_style.wavy;
+ if (old_ref) {
+ style->filter_modified_connection.disconnect();
}
-
- if (!style->text_decoration_color.set || style->text_decoration_color.inherit) {
- sp_style_merge_ipaint(style, &style->text_decoration_color, &parent->text_decoration_color);
+ if ( SP_IS_FILTER(ref))
+ {
+ style->filter_modified_connection =
+ ref->connectModified(sigc::bind(sigc::ptr_fun(&sp_style_filter_ref_modified), style));
}
- if (!style->line_height.set || style->line_height.inherit) {
- style->line_height.value = parent->line_height.value;
- style->line_height.computed = parent->line_height.computed;
- style->line_height.normal = parent->line_height.normal;
- }
+ sp_style_filter_ref_modified(ref, 0, style);
+}
- if (!style->letter_spacing.set || style->letter_spacing.inherit) {
- style->letter_spacing.value = parent->letter_spacing.value;
- style->letter_spacing.computed = parent->letter_spacing.computed;
- style->letter_spacing.normal = parent->letter_spacing.normal;
- }
+/**
+ * Emit style modified signal on style's object if server is style's fill
+ * or stroke paint server.
+ */
+static void
+sp_style_paint_server_ref_modified(SPObject *obj, guint flags, SPStyle *style)
+{
+ (void)flags; // TODO
+ SPPaintServer *server = static_cast<SPPaintServer *>(obj);
- if (!style->word_spacing.set || style->word_spacing.inherit) {
- style->word_spacing.value = parent->word_spacing.value;
- style->word_spacing.computed = parent->word_spacing.computed;
- style->word_spacing.normal = parent->word_spacing.normal;
+ if ((style->fill.isPaintserver())
+ && style->getFillPaintServer() == server)
+ {
+ if (style->object) {
+ /** \todo
+ * fixme: I do not know, whether it is optimal - we are
+ * forcing reread of everything (Lauris)
+ */
+ /** \todo
+ * fixme: We have to use object_modified flag, because parent
+ * flag is only available downstreams.
+ */
+ style->object->requestModified(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG);
+ }
+ } else if ((style->stroke.isPaintserver())
+ && style->getStrokePaintServer() == server)
+ {
+ if (style->object) {
+ /// \todo fixme:
+ style->object->requestModified(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG);
+ }
+ } else if (server) {
+ g_assert_not_reached();
}
+}
- if (!style->text_transform.set || style->text_transform.inherit) {
- style->text_transform.computed = parent->text_transform.computed;
+/**
+ * Gets called when the paintserver is (re)attached to the style
+ */
+void
+sp_style_fill_paint_server_ref_changed(SPObject *old_ref, SPObject *ref, SPStyle *style)
+{
+ if (old_ref) {
+ style->fill_ps_modified_connection.disconnect();
}
-
- if (!style->direction.set || style->direction.inherit) {
- style->direction.computed = parent->direction.computed;
+ if (SP_IS_PAINT_SERVER(ref)) {
+ style->fill_ps_modified_connection =
+ ref->connectModified(sigc::bind(sigc::ptr_fun(&sp_style_paint_server_ref_modified), style));
}
- if (!style->block_progression.set || style->block_progression.inherit) {
- style->block_progression.computed = parent->block_progression.computed;
- }
+ style->signal_fill_ps_changed.emit(old_ref, ref);
+ sp_style_paint_server_ref_modified(ref, 0, style);
+}
- if (!style->writing_mode.set || style->writing_mode.inherit) {
- style->writing_mode.computed = parent->writing_mode.computed;
+/**
+ * Gets called when the paintserver is (re)attached to the style
+ */
+void
+sp_style_stroke_paint_server_ref_changed(SPObject *old_ref, SPObject *ref, SPStyle *style)
+{
+ if (old_ref) {
+ style->stroke_ps_modified_connection.disconnect();
}
-
- if (!style->text_anchor.set || style->text_anchor.inherit) {
- style->text_anchor.computed = parent->text_anchor.computed;
+ if (SP_IS_PAINT_SERVER(ref)) {
+ style->stroke_ps_modified_connection =
+ ref->connectModified(sigc::bind(sigc::ptr_fun(&sp_style_paint_server_ref_modified), style));
}
- /* Baseline Shift... Some shifts are relative to parent. */
- sp_style_merge_baseline_shift_from_parent(style->baseline_shift, parent->baseline_shift,
- parent->font_size);
+ style->signal_stroke_ps_changed.emit(old_ref, ref);
+ sp_style_paint_server_ref_modified(ref, 0, style);
+}
- if (style->opacity.inherit) {
- style->opacity.value = parent->opacity.value;
- }
+// Called in: desktop-style.cpp, gradient-chemistry.cpp, sp-object.cpp, sp-stop.cpp, style.cpp
+// text-editing.cpp, libnrtype/font-lister.cpp, widgets/dash-selector.cpp, widgets/fill-style.cpp,
+// widgets/stroke-style.cpp, widgets/text-toolbar.cpp, ui/dialog/glyphs.cpp, ui/dialog/swatches.cpp,
+// ui/dialog/swatches.cpp, ui/dialog/text-edit.cpp. ui/tools/freehand-base.cpp,
+// ui/widget/object-composite-settings.cpp, ui/widget/selected-style.cpp, ui/widget/style-swatch.cpp
+/**
+ * Returns a new SPStyle object with default settings.
+ */
+SPStyle *
+sp_style_new(SPDocument *document)
+{
+ SPStyle *const style = new SPStyle( document );
+ return style;
+}
- /* Color */
- if (!style->color.set || style->color.inherit) {
- sp_style_merge_ipaint(style, &style->color, &parent->color);
- }
- if (!style->color_interpolation.set || style->color_interpolation.inherit) {
- style->color_interpolation.computed = parent->color_interpolation.computed;
- }
- if (!style->color_interpolation_filters.set || style->color_interpolation_filters.inherit) {
- style->color_interpolation_filters.computed = parent->color_interpolation_filters.computed;
- }
+// Called in: sp-object.cpp
+/**
+ * Creates a new SPStyle object, and attaches it to the specified SPObject.
+ */
+SPStyle *
+sp_style_new_from_object(SPObject *object)
+{
+ g_return_val_if_fail(object != NULL, NULL);
+ g_return_val_if_fail(SP_IS_OBJECT(object), NULL);
+ SPStyle *const style = new SPStyle( NULL, object );
+ return style;
+}
- /* Fill */
- if (!style->fill.set || style->fill.inherit || style->fill.currentcolor) {
- sp_style_merge_ipaint(style, &style->fill, &parent->fill);
- }
+// Called in display/drawing-item.cpp, display/nr-filter-primitive.cpp, libnrtype/Layout-TNG-Input.cpp
+/**
+ * Increase refcount of style.
+ */
+SPStyle *
+sp_style_ref(SPStyle *style)
+{
+ g_return_val_if_fail(style != NULL, NULL);
- if (!style->fill_opacity.set || style->fill_opacity.inherit) {
- style->fill_opacity.value = parent->fill_opacity.value;
- }
+ style->ref(); // Increase ref count
- if (!style->fill_rule.set || style->fill_rule.inherit) {
- style->fill_rule.computed = parent->fill_rule.computed;
- }
+ return style;
+}
- /* Stroke */
- if (!style->stroke.set || style->stroke.inherit || style->stroke.currentcolor) {
- sp_style_merge_ipaint(style, &style->stroke, &parent->stroke);
+// Called in style.cpp, desktop-style.cpp, sp-object.cpp, sp-stop.cpp, text-editing.cpp
+// display/drawing-group.cpp, ...
+/**
+ * Decrease refcount of style with possible destruction.
+ */
+SPStyle *
+sp_style_unref(SPStyle *style)
+{
+ g_return_val_if_fail(style != NULL, NULL);
+ if (style->unref() < 1) {
+ delete style;
+ return NULL;
}
+ return style;
+}
- if (!style->stroke_width.set || style->stroke_width.inherit) {
- style->stroke_width.computed = parent->stroke_width.computed;
- } else {
- /* Update computed value for any change in font inherited from parent. */
- double const em = style->font_size.computed;
- if (style->stroke_width.unit == SP_CSS_UNIT_EM) {
- style->stroke_width.computed = style->stroke_width.value * em;
- } else if (style->stroke_width.unit == SP_CSS_UNIT_EX) {
- double const ex = em * 0.5; // fixme: Get x height from libnrtype or pango.
- style->stroke_width.computed = style->stroke_width.value * ex;
- }
- }
- if (!style->stroke_linecap.set || style->stroke_linecap.inherit) {
- style->stroke_linecap.computed = parent->stroke_linecap.computed;
- }
- if (!style->stroke_linejoin.set || style->stroke_linejoin.inherit) {
- style->stroke_linejoin.computed = parent->stroke_linejoin.computed;
- }
+// Called in: sp-clippath.cpp, sp-item.cpp (suspicious), sp-object.cpp, sp-style-elem.cpp
+/**
+ * Read style properties from object's repr.
+ *
+ * 1. Reset existing object style
+ * 2. Load current effective object style
+ * 3. Load i attributes from immediate parent (which has to be up-to-date)
+ */
+void
+sp_style_read_from_object(SPStyle *style, SPObject *object)
+{
+ // std::cout << "sp_style_read_from_object: " << (object->getId()?object->getId():"null") << std::endl;
+ g_return_if_fail(style != NULL);
+ g_return_if_fail(object != NULL);
+ g_return_if_fail(SP_IS_OBJECT(object));
- if (!style->stroke_miterlimit.set || style->stroke_miterlimit.inherit) {
- style->stroke_miterlimit.value = parent->stroke_miterlimit.value;
- }
+ Inkscape::XML::Node *repr = object->getRepr();
+ g_return_if_fail(repr != NULL);
- if (!style->stroke_dasharray.set || style->stroke_dasharray.inherit) {
- style->stroke_dasharray.values = parent->stroke_dasharray.values;
- }
+ style->read( object, repr );
+}
- if (!style->stroke_dashoffset.set || style->stroke_dashoffset.inherit) {
- style->stroke_dashoffset.value = parent->stroke_dashoffset.value;
- }
+// Called in: libnrtype/font-lister.cpp, widgets/dash-selector.cpp, widgets/text-toolbar.cpp,
+// ui/dialog/text-edit.cpp
+// Why is this called when draging a gradient handle?
+/**
+ * Read style properties from preferences.
+ * @param style The style to write to
+ * @param path Preferences directory from which the style should be read
+ */
+void
+sp_style_read_from_prefs(SPStyle *style, Glib::ustring const &path)
+{
+ g_return_if_fail(style != NULL);
+ g_return_if_fail(path != "");
- if (!style->stroke_opacity.set || style->stroke_opacity.inherit) {
- style->stroke_opacity.value = parent->stroke_opacity.value;
- }
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- if (!style->paint_order.set || style->paint_order.inherit) {
- g_free(style->paint_order.value);
- style->paint_order.value = g_strdup(parent->paint_order.value);
- for (unsigned i = 0; i < PAINT_ORDER_LAYERS; ++i) {
- style->paint_order.layer[i] = parent->paint_order.layer[i];
- style->paint_order.layer_set[i] = parent->paint_order.layer_set[i];
- }
- }
+ // not optimal: we reconstruct the node based on the prefs, then pass it to
+ // sp_style_read for actual processing.
+ Inkscape::XML::SimpleDocument *tempdoc = new Inkscape::XML::SimpleDocument;
+ Inkscape::XML::Node *tempnode = tempdoc->createElement("prefs");
- if (style->text && parent->text) {
- if (!style->text->font_family.set || style->text->font_family.inherit) {
- g_free(style->text->font_family.value);
- style->text->font_family.value = g_strdup(parent->text->font_family.value);
- }
+ std::vector<Inkscape::Preferences::Entry> attrs = prefs->getAllEntries(path);
+ for (std::vector<Inkscape::Preferences::Entry>::iterator i = attrs.begin(); i != attrs.end(); ++i) {
+ tempnode->setAttribute(i->getEntryName().data(), i->getString().data());
}
- if (style->text && parent->text) {
- if (!style->text->font_specification.set || style->text->font_specification.inherit) {
- g_free(style->text->font_specification.value);
- style->text->font_specification.value = g_strdup(parent->text->font_specification.value);
- }
- }
+ style->read( NULL, tempnode );
- /* Markers - Free the old value and make copy of the new */
- for (unsigned i = SP_MARKER_LOC; i < SP_MARKER_LOC_QTY; i++) {
- if (!style->marker[i].set || style->marker[i].inherit) {
- g_free(style->marker[i].value);
- style->marker[i].value = g_strdup(parent->marker[i].value);
- }
- }
+ Inkscape::GC::release(tempnode);
+ Inkscape::GC::release(tempdoc);
+ delete tempdoc;
+}
- /* Filter effects */
- if (style->filter.inherit) {
- sp_style_merge_ifilter(style, &parent->filter);
- }
- if(style->enable_background.inherit) {
- style->enable_background.value = parent->enable_background.value;
- }
+static CRSelEng *
+sp_repr_sel_eng()
+{
+ CRSelEng *const ret = cr_sel_eng_new();
+ cr_sel_eng_set_node_iface(ret, &Inkscape::XML::croco_node_iface);
- /* Clipping */
- if (!style->clip_rule.set || style->clip_rule.inherit) {
- style->clip_rule.computed = parent->clip_rule.computed;
- }
+ /** \todo
+ * Check whether we need to register any pseudo-class handlers.
+ * libcroco has its own default handlers for first-child and lang.
+ *
+ * We probably want handlers for link and arguably visited (though
+ * inkscape can't visit links at the time of writing). hover etc.
+ * more useful in inkview than the editor inkscape.
+ *
+ * http://www.w3.org/TR/SVG11/styling.html#StylingWithCSS says that
+ * the following should be honoured, at least by inkview:
+ * :hover, :active, :focus, :visited, :link.
+ */
- /* Rendering */
- if (!style->color_rendering.set || style->color_rendering.inherit) {
- style->color_rendering.computed = parent->color_rendering.computed;
- }
- if (!style->image_rendering.set || style->image_rendering.inherit) {
- style->image_rendering.computed = parent->image_rendering.computed;
- }
- if (!style->shape_rendering.set || style->shape_rendering.inherit) {
- style->shape_rendering.computed = parent->shape_rendering.computed;
- }
- if (!style->text_rendering.set || style->text_rendering.inherit) {
- style->text_rendering.computed = parent->text_rendering.computed;
- }
+ g_assert(ret);
+ return ret;
}
-template <typename T>
-static void
-sp_style_merge_prop_from_dying_parent(T &child, T const &parent)
-{
- if ( ( !(child.set) || child.inherit )
- && parent.set && !(parent.inherit) )
- {
- child = parent;
- }
-}
+// Called in text-editting.cpp, ui/tools/frehand-base.cpp, ui/widget/style-swatch.cpp
/**
- * Copy SPIString from parent to child.
+ * Parses a style="..." string and merges it with an existing SPStyle.
*/
-static void
-sp_style_merge_string_prop_from_dying_parent(SPIString &child, SPIString const &parent)
-{
- if ( ( !(child.set) || child.inherit )
- && parent.set && !(parent.inherit) )
- {
- g_free(child.value);
- child.value = g_strdup(parent.value);
- child.set = parent.set;
- child.inherit = parent.inherit;
- }
-}
-
-static void
-sp_style_merge_paint_prop_from_dying_parent(SPStyle *style,
- SPIPaint &child, SPIPaint const &parent)
+void
+sp_style_merge_from_style_string(SPStyle *const style, gchar const *const p)
{
- /** \todo
- * I haven't given this much attention. See comments below about
- * currentColor, colorProfile, and relative URIs.
+ // std::cout << "sp_style_merge_from_style_string: " << (p?p:"null") <<std::endl;
+ /*
+ * Reference: http://www.w3.org/TR/SVG11/styling.html#StyleAttribute:
+ * ``When CSS styling is used, CSS inline style is specified by including
+ * semicolon-separated property declarations of the form "name : value"
+ * within the style attribute''.
+ *
+ * That's fairly ambiguous. Is a `value' allowed to contain semicolons?
+ * Why does it say "including", what else is allowed in the style
+ * attribute value?
*/
- if (!child.set || child.inherit) {
- sp_style_merge_ipaint(style, &child, &parent);
- child.set = parent.set;
- child.inherit = parent.inherit;
- }
+ style->_mergeString( p );
}
-static void
-sp_style_merge_rel_enum_prop_from_dying_parent(SPIEnum &child, SPIEnum const &parent,
- unsigned const max_computed_val,
- unsigned const smaller_val)
-{
- /* We assume that min computed val is 0, contiguous up to max_computed_val,
- then zero or more other absolute values, then smaller_val then larger_val. */
- unsigned const min_computed_val = 0;
- unsigned const larger_val = smaller_val + 1;
- g_return_if_fail(min_computed_val < max_computed_val);
- g_return_if_fail(max_computed_val < smaller_val);
-
- if (parent.set && !parent.inherit) {
- if (!child.set || child.inherit) {
- child.value = parent.value;
- child.set = parent.set; // i.e. true
- child.inherit = parent.inherit; // i.e. false
- } else if (child.value < smaller_val) {
- /* Child has absolute value: leave as is. */
- } else if ( ( child.value == smaller_val
- && parent.value == larger_val )
- || ( parent.value == smaller_val
- && child.value == larger_val ) )
- {
- child.set = false;
- /*
- * Note that this can result in a change in computed value in the
- * rare case that the parent's setting was a no-op (i.e. if the
- * parent's parent's computed value was already ultra-condensed or
- * ultra-expanded). However, I'd guess that the change is for the
- * better: I'd guess that if the properties were specified
- * relatively, then the intent is to counteract parent's effect.
- * I.e. I believe this is the best code even in that case.
- */
- } else if (child.value == parent.value) {
- /* Leave as is. */
- /** \todo
- * It's unclear what to do if style and parent specify the same
- * relative directive (narrower or wider). We can either convert
- * to absolute specification or coalesce to a single relative
- * request (of half the strength of the original pair).
- *
- * Converting to a single level of relative specification is a
- * better choice if the newly-unlinked clone is itself cloned to
- * other contexts (inheriting different font stretchiness): it
- * would preserve the effect that it will be narrower than
- * the inherited context in each case. The disadvantage is that
- * it will ~certainly affect the computed value of the
- * newly-unlinked clone.
- */
- } else {
- unsigned const parent_val = parent.computed;
- child.value = ( child.value == smaller_val
- ? ( parent_val == min_computed_val
- ? parent_val
- : parent_val - 1 )
- : ( parent_val == max_computed_val
- ? parent_val
- : parent_val + 1 ) );
- g_assert(child.value <= max_computed_val);
- child.inherit = false;
- g_assert(child.set);
- }
- }
-}
-
-template <typename LengthT>
-static void
-sp_style_merge_length_prop_from_dying_parent(LengthT &child, LengthT const &parent,
- double const parent_child_em_ratio)
-{
- if ( ( !(child.set) || child.inherit )
- && parent.set && !(parent.inherit) )
- {
- child = parent;
- switch (parent.unit) {
- case SP_CSS_UNIT_EM:
- case SP_CSS_UNIT_EX:
- child.value *= parent_child_em_ratio;
- /** \todo
- * fixme: Have separate ex ratio parameter.
- * Get x height from libnrtype or pango.
- */
- if (!IS_FINITE(child.value)) {
- child.value = child.computed;
- child.unit = SP_CSS_UNIT_NONE;
- }
- break;
-
- default:
- break;
- }
- }
-}
+/** Indexed by SP_CSS_FONT_SIZE_blah. These seem a bit small */
+static float const font_size_table[] = {6.0, 8.0, 10.0, 12.0, 14.0, 18.0, 24.0};
-static double
-get_relative_font_size_frac(SPIFontSize const &font_size)
+// Called in sp-object.cpp, sp-tref.cpp, sp-use.cpp
+/**
+ * Sets computed values in \a style, which may involve inheriting from (or in some other way
+ * calculating from) corresponding computed values of \a parent.
+ *
+ * References: http://www.w3.org/TR/SVG11/propidx.html shows what properties inherit by default.
+ * http://www.w3.org/TR/SVG11/styling.html#Inheritance gives general rules as to what it means to
+ * inherit a value. http://www.w3.org/TR/REC-CSS2/cascade.html#computed-value is more precise
+ * about what the computed value is (not obvious for lengths).
+ *
+ * \pre \a parent's computed values are already up-to-date.
+ */
+void
+sp_style_merge_from_parent(SPStyle *const style, SPStyle const *const parent)
{
- switch (font_size.type) {
- case SP_FONT_SIZE_LITERAL: {
- switch (font_size.literal) {
- case SP_CSS_FONT_SIZE_SMALLER:
- return 5.0 / 6.0;
-
- case SP_CSS_FONT_SIZE_LARGER:
- return 6.0 / 5.0;
-
- default:
- g_assert_not_reached();
- }
- }
-
- case SP_FONT_SIZE_PERCENTAGE:
- return font_size.value;
-
- case SP_FONT_SIZE_LENGTH: {
- switch (font_size.unit ) {
- case SP_CSS_UNIT_EM:
- return font_size.value;
+ // std::cout << "sp_style_merge_from_parent" << std::endl;
+ g_return_if_fail(style != NULL);
- case SP_CSS_UNIT_EX:
- return font_size.value * 0.5;
+ if (!parent)
+ return;
- default:
- g_assert_not_reached();
- }
- }
- }
- g_assert_not_reached();
+ style->cascade( parent );
+ return;
}
+// Called in: sp-use.cpp, sp-tref.cpp, sp-item.cpp
/**
* Combine \a style and \a parent style specifications into a single style specification that
* preserves (as much as possible) the effect of the existing \a style being a child of \a parent.
@@ -2140,375 +1353,25 @@ get_relative_font_size_frac(SPIFontSize const &font_size)
void
sp_style_merge_from_dying_parent(SPStyle *const style, SPStyle const *const parent)
{
- /** \note
- * The general rule for each property is as follows:
- *
- * If style is set to an absolute value, then leave it as is.
- *
- * Otherwise (i.e. if style has a relative value):
- *
- * If parent is set to an absolute value, then set style to the computed value.
- *
- * Otherwise, calculate the combined relative value (e.g. multiplying the two percentages).
- */
-
- /* We do font-size first, to ensure that em size is up-to-date. */
- /** \todo
- * fixme: We'll need to have more font-related things up the top once
- * we're getting x-height from pango or libnrtype.
- */
-
- /* Some things that allow relative specifications. */
- {
- /* font-size. Note that we update the computed font-size of style,
- to assist in em calculations later in this function. */
-
- if (parent->font_size.set && !parent->font_size.inherit) {
- /* Parent has defined font-size */
-
- if (!style->font_size.set || style->font_size.inherit) {
- /* font_size inherits the computed value, so we can use the parent value
- * verbatim. */
- style->font_size = parent->font_size;
-
- } else if ( style->font_size.type == SP_FONT_SIZE_LENGTH &&
- style->font_size.unit != SP_CSS_UNIT_EM &&
- style->font_size.unit != SP_CSS_UNIT_EX ) {
-
- /* Child already has absolute size (stored in computed value), so do nothing. */
-
- } else if ( style->font_size.type == SP_FONT_SIZE_LITERAL
- && style->font_size.literal < SP_CSS_FONT_SIZE_SMALLER ) {
- /* Child already has absolute size, but we ensure that the computed value
- is up-to-date. */
- unsigned const ix = style->font_size.literal;
- g_assert(ix < G_N_ELEMENTS(font_size_table));
- style->font_size.computed = font_size_table[ix];
-
- } else {
- /* Child has relative size. */
- double const child_frac(get_relative_font_size_frac(style->font_size));
- style->font_size.set = true;
- style->font_size.inherit = false;
- style->font_size.computed = parent->font_size.computed * child_frac;
-
- if ( ( parent->font_size.type == SP_FONT_SIZE_LITERAL
- && parent->font_size.literal < SP_CSS_FONT_SIZE_SMALLER ) ||
- ( parent->font_size.type == SP_FONT_SIZE_LENGTH &&
- parent->font_size.unit != SP_CSS_UNIT_EM &&
- parent->font_size.unit != SP_CSS_UNIT_EX ) ) {
-
- /* Absolute value. */
- style->font_size.type = SP_FONT_SIZE_LENGTH;
- /* .value is unused for non ex/em SP_FONT_SIZE_LENGTH. */
-
- } else {
- /* Relative value. */
-
- double const parent_frac(get_relative_font_size_frac(parent->font_size));
- if( style->font_size.type == SP_FONT_SIZE_LENGTH ) {
- /* Value in terms of ex/em */
- style->font_size.value *= parent_frac;
- } else {
- style->font_size.value = parent_frac * child_frac;
- style->font_size.type = SP_FONT_SIZE_PERCENTAGE;
- }
- }
- }
- }
-
- /* 'font-stretch' */
- sp_style_merge_rel_enum_prop_from_dying_parent(style->font_stretch,
- parent->font_stretch,
- SP_CSS_FONT_STRETCH_ULTRA_EXPANDED,
- SP_CSS_FONT_STRETCH_NARROWER);
-
- /* font-weight */
- sp_style_merge_rel_enum_prop_from_dying_parent(style->font_weight,
- parent->font_weight,
- SP_CSS_FONT_WEIGHT_900,
- SP_CSS_FONT_WEIGHT_LIGHTER);
- }
-
-
- /* Enum values that don't have any relative settings (other than `inherit'). */
- {
- SPIEnum SPStyle::*const fields[] = {
- &SPStyle::blend_mode,
- &SPStyle::clip_rule,
- &SPStyle::color_interpolation,
- &SPStyle::color_interpolation_filters,
- &SPStyle::color_rendering,
- &SPStyle::direction,
- &SPStyle::fill_rule,
- &SPStyle::font_style,
- &SPStyle::font_variant,
- &SPStyle::image_rendering,
- &SPStyle::isolation,
- //nyi: SPStyle::pointer_events,
- &SPStyle::shape_rendering,
- &SPStyle::stroke_linecap,
- &SPStyle::stroke_linejoin,
- &SPStyle::text_anchor,
- &SPStyle::text_rendering,
- &SPStyle::visibility,
- &SPStyle::writing_mode
- };
-
- for (unsigned i = 0; i < G_N_ELEMENTS(fields); ++i) {
- SPIEnum SPStyle::*const fld = fields[i];
- sp_style_merge_prop_from_dying_parent<SPIEnum>(style->*fld, parent->*fld);
- }
- }
-
- /* A few other simple inheritance properties. */
- {
- sp_style_merge_prop_from_dying_parent<SPIScale24>(style->fill_opacity, parent->fill_opacity);
- sp_style_merge_prop_from_dying_parent<SPIScale24>(style->stroke_opacity, parent->stroke_opacity);
- sp_style_merge_prop_from_dying_parent<SPIFloat>(style->stroke_miterlimit, parent->stroke_miterlimit);
-
- /** \todo
- * We currently treat text-decoration as if it were a simple inherited
- * property (fixme). This code may need changing once we do the
- * special fill/stroke inheritance mentioned by the spec.
- */
- sp_style_merge_prop_from_dying_parent<SPITextDecorationLine>( style->text_decoration_line, parent->text_decoration_line);
- sp_style_merge_prop_from_dying_parent<SPITextDecorationStyle>(style->text_decoration_style, parent->text_decoration_style);
- sp_style_merge_paint_prop_from_dying_parent(style,style->text_decoration_color, parent->text_decoration_color);
-
- //nyi: font-size-adjust, // <number> | none | inherit
- //nyi: glyph-orientation-horizontal,
- //nyi: glyph-orientation-vertical,
- }
-
- /* Properties that involve length but are easy in other respects. */
- {
- /* The difficulty with lengths is that font-relative units need adjusting if the font
- * varies between parent & child.
- *
- * Lengths specified in the existing child can stay as they are: its computed font
- * specification should stay unchanged, so em & ex lengths should continue to mean the same
- * size.
- *
- * Lengths specified in the dying parent in em or ex need to be scaled according to the
- * ratio of em or ex size between parent & child.
- */
- double const parent_child_em_ratio = parent->font_size.computed / style->font_size.computed;
-
- SPILength SPStyle::*const lfields[] = {
- &SPStyle::stroke_width,
- &SPStyle::text_indent
- };
- for (unsigned i = 0; i < G_N_ELEMENTS(lfields); ++i) {
- SPILength SPStyle::*fld = lfields[i];
- sp_style_merge_length_prop_from_dying_parent<SPILength>(style->*fld,
- parent->*fld,
- parent_child_em_ratio);
- }
-
- SPILengthOrNormal SPStyle::*const nfields[] = {
- &SPStyle::letter_spacing,
- &SPStyle::line_height,
- &SPStyle::word_spacing
- };
- for (unsigned i = 0; i < G_N_ELEMENTS(nfields); ++i) {
- SPILengthOrNormal SPStyle::*fld = nfields[i];
- sp_style_merge_length_prop_from_dying_parent<SPILengthOrNormal>(style->*fld,
- parent->*fld,
- parent_child_em_ratio);
- }
-
- //nyi: &SPStyle::kerning: length or `auto'
-
- /* fixme: Move stroke-dash and stroke-dash-offset here once they
- can accept units. */
- }
-
- /* Properties that involve a URI but are easy in other respects. */
- {
- /** \todo
- * Could cause problems if original object was in another document
- * and it used a relative URL. (At the time of writing, we don't
- * allow hrefs to other documents, so this isn't a problem yet.)
- * Paint properties also allow URIs.
- */
- //nyi: cursor, // may involve change in effect, but we can't do much better
- //nyi: color-profile,
-
- // Markers (marker-start, marker-mid, marker-end).
- for (unsigned i = SP_MARKER_LOC; i < SP_MARKER_LOC_QTY; i++) {
- sp_style_merge_string_prop_from_dying_parent(style->marker[i], parent->marker[i]);
- }
- }
-
- /* CSS2 */
- /* Font */
-
- if (style->text && parent->text) {
- sp_style_merge_string_prop_from_dying_parent(style->text->font_specification,
- parent->text->font_specification);
-
- sp_style_merge_string_prop_from_dying_parent(style->text->font_family,
- parent->text->font_family);
- }
-
-
- /* Properties that don't inherit by default. Most of these need special handling. */
- {
- /*
- * opacity's effect is cumulative; we set the new value to the combined effect. The
- * default value for opacity is 1.0, not inherit. (Note that stroke-opacity and
- * fill-opacity are quite different from opacity, and don't need any special handling.)
- *
- * Cases:
- * - parent & child were each previously unset, in which case the effective
- * opacity value is 1.0, and style should remain unset.
- * - parent was previously unset (so computed opacity value of 1.0)
- * and child was set to inherit. The merged child should
- * get a value of 1.0, and shouldn't inherit (lest the new parent
- * has a different opacity value). Given that opacity's default
- * value is 1.0 (rather than inherit), we might as well have the
- * merged child's opacity be unset.
- * - parent was previously unset (so opacity 1.0), and child was set to a number.
- * The merged child should retain its existing settings (though it doesn't matter
- * if we make it unset if that number was 1.0).
- * - parent was inherit and child was unset. Merged child should be set to inherit.
- * - parent was inherit and child was inherit. (We can't in general reproduce this
- * effect (short of introducing a new group), but setting opacity to inherit is rare.)
- * If the inherited value was strictly between 0.0 and 1.0 (exclusive) then the merged
- * child's value should be set to the product of the two, i.e. the square of the
- * inherited value, and should not be marked as inherit. (This decision assumes that it
- * is more important to retain the effective opacity than to retain the inheriting
- * effect, and assumes that the inheriting effect either isn't important enough to create
- * a group or isn't common enough to bother maintaining the code to create a group.) If
- * the inherited value was 0.0 or 1.0, then marking the merged child as inherit comes
- * closer to maintaining the effect.
- * - parent was inherit and child was set to a numerical value. If the child's value
- * was 1.0, then the merged child should have the same settings as the parent.
- * If the child's value was 0, then the merged child should also be set to 0.
- * If the child's value was anything else, then we do the same as for the inherit/inherit
- * case above: have the merged child set to the product of the two opacities and not
- * marked as inherit, for the same reasons as for that case.
- * - parent was set to a value, and child was unset. The merged child should have
- * parent's settings.
- * - parent was set to a value, and child was inherit. The merged child should
- * be set to the product, i.e. the square of the parent's value.
- * - parent & child are each set to a value. The merged child should be set to the
- * product.
- */
- if ( !style->opacity.set
- || ( !style->opacity.inherit
- && style->opacity.value == SP_SCALE24_MAX ) )
- {
- style->opacity = parent->opacity;
- } else {
- /* Ensure that style's computed value is up-to-date. */
- if (style->opacity.inherit) {
- style->opacity.value = parent->opacity.value;
- }
-
- /* Multiplication of opacities occurs even if a child's opacity is set to inherit. */
- style->opacity.value = SP_SCALE24_MUL(style->opacity.value,
- parent->opacity.value);
-
- style->opacity.inherit = (parent->opacity.inherit
- && style->opacity.inherit
- && (parent->opacity.value == 0 ||
- parent->opacity.value == SP_SCALE24_MAX));
- style->opacity.set = ( style->opacity.inherit
- || style->opacity.value < SP_SCALE24_MAX );
- }
-
- /* display is in principle similar to opacity, but implementation is easier. */
- if ( parent->display.set && !parent->display.inherit
- && parent->display.value == SP_CSS_DISPLAY_NONE ) {
- style->display.value = SP_CSS_DISPLAY_NONE;
- style->display.set = true;
- style->display.inherit = false;
- } else if (style->display.inherit) {
- style->display.value = parent->display.value;
- style->display.set = parent->display.set;
- style->display.inherit = parent->display.inherit;
- } else {
- /* Leave as is. (display doesn't inherit by default.) */
- }
-
- /* enable-background - this is rather complicated, because
- * it is valid only when applied to container elements.
- * Let's check a simple case anyhow. */
- if (parent->enable_background.set
- && !parent->enable_background.inherit
- && style->enable_background.inherit)
- {
- style->enable_background.set = true;
- style->enable_background.inherit = false;
- style->enable_background.value = parent->enable_background.value;
- }
-
- if (!style->filter.set || style->filter.inherit)
- {
- sp_style_merge_ifilter(style, &parent->filter);
-
+ // std::cout << "sp_style_merge_from_dying_parent" << std::endl;
+ style->merge( parent );
}
- /** \todo
- * fixme: Check that we correctly handle all properties that don't
- * inherit by default (as shown in
- * http://www.w3.org/TR/SVG11/propidx.html for most SVG 1.1 properties).
- */
- }
-
- /* SPIPaint properties (including color). */
- {
- /** \todo
- * Think about the issues involved if specified as currentColor or
- * if specified relative to colorProfile, and if the currentColor or
- * colorProfile differs between parent \& child. See also comments
- * elsewhere in this function about URIs.
- */
- SPIPaint SPStyle::*const fields[] = {
- &SPStyle::color,
- &SPStyle::fill,
- &SPStyle::stroke
- };
- for (unsigned i = 0; i < G_N_ELEMENTS(fields); ++i) {
- SPIPaint SPStyle::*const fld = fields[i];
- sp_style_merge_paint_prop_from_dying_parent(style, style->*fld, parent->*fld);
- }
- }
- /* Things from SVG 1.2 or CSS3. */
- {
- /* Note: If we ever support setting string values for text-align then we'd need strdup
- * handling here. */
- sp_style_merge_prop_from_dying_parent<SPIEnum>(style->text_align, parent->text_align);
-
- sp_style_merge_prop_from_dying_parent<SPIEnum>(style->text_transform, parent->text_transform);
- sp_style_merge_prop_from_dying_parent<SPIEnum>(style->block_progression, parent->block_progression);
- }
-
- /* Note: this will need length handling once dasharray supports units. */
- if ( ( !style->stroke_dasharray.set || style->stroke_dasharray.inherit )
- && parent->stroke_dasharray.set && !parent->stroke_dasharray.inherit )
- {
- style->stroke_dasharray.values = parent->stroke_dasharray.values;
- style->stroke_dasharray.set = parent->stroke_dasharray.set;
- style->stroke_dasharray.inherit = parent->stroke_dasharray.inherit;
- }
-
- {
- sp_style_merge_prop_from_dying_parent<SPILength>(style->stroke_dashoffset, parent->stroke_dashoffset);
- }
-}
-
-
-static void
+// The following functions should be incorporated into SPIPaint. FIXME
+// Called in: style.cpp, style-internal.cpp
+void
sp_style_set_ipaint_to_uri(SPStyle *style, SPIPaint *paint, const Inkscape::URI *uri, SPDocument *document)
{
+ // std::cout << "sp_style_set_ipaint_to_uri: Entrance: " << uri << " " << (void*)document << std::endl;
// it may be that this style's SPIPaint has not yet created its URIReference;
// now that we have a document, we can create it here
if (!paint->value.href && document) {
paint->value.href = new SPPaintServerReference(document);
- paint->value.href->changedSignal().connect(sigc::bind(sigc::ptr_fun((paint == &style->fill)? sp_style_fill_paint_server_ref_changed : sp_style_stroke_paint_server_ref_changed), style));
+ if (paint == &style->fill) {
+ style->fill_ps_changed_connection = paint->value.href->changedSignal().connect(sigc::bind(sigc::ptr_fun(sp_style_fill_paint_server_ref_changed), style));
+ } else {
+ style->stroke_ps_changed_connection = paint->value.href->changedSignal().connect(sigc::bind(sigc::ptr_fun(sp_style_stroke_paint_server_ref_changed), style));
+ }
}
if (paint->value.href){
@@ -2525,7 +1388,8 @@ sp_style_set_ipaint_to_uri(SPStyle *style, SPIPaint *paint, const Inkscape::URI
}
}
-static void
+// Called in: style.cpp, style-internal.cpp
+void
sp_style_set_ipaint_to_uri_string (SPStyle *style, SPIPaint *paint, const gchar *uri)
{
try {
@@ -2536,12 +1400,14 @@ sp_style_set_ipaint_to_uri_string (SPStyle *style, SPIPaint *paint, const gchar
}
}
+// Called in: desktop-style.cpp
void
sp_style_set_to_uri_string (SPStyle *style, bool isfill, const gchar *uri)
{
sp_style_set_ipaint_to_uri_string (style, isfill? &style->fill : &style->stroke, uri);
}
+// Called in: widgets/font-selector.cpp, widgets/text-toolbar.cpp, ui/dialog/text-edit.cpp
gchar const *
sp_style_get_css_unit_string(int unit)
{
@@ -2564,6 +1430,7 @@ sp_style_get_css_unit_string(int unit)
return "px";
}
+// Called in: style-internal.cpp, widgets/text-toolbar.cpp, ui/dialog/text-edit.cpp
/*
* Convert a size in pixels into another CSS unit size
*/
@@ -2592,6 +1459,7 @@ sp_style_css_size_px_to_units(double size, int unit)
return unit_size;
}
+// Called in: widgets/text-toolbar.cpp, ui/dialog/text-edit.cpp
/*
* Convert a size in a CSS unit size to pixels
*/
@@ -2604,82 +1472,8 @@ sp_style_css_size_units_to_px(double size, int unit)
//g_message("sp_style_css_size_units_to_px %f %d = %f px", size, unit, out);
return size * (size / sp_style_css_size_px_to_units(size, unit));;
}
-/**
- *
- */
-static void
-sp_style_merge_ipaint(SPStyle *style, SPIPaint *paint, SPIPaint const *parent)
-{
- if ((paint->set && paint->currentcolor) || parent->currentcolor) {
- bool isset = paint->set;
- paint->clear();
- paint->set = isset;
- paint->currentcolor = TRUE;
- paint->setColor(style->color.value.color);
- return;
- }
-
- paint->clear();
- if ( parent->isPaintserver() ) {
- if (parent->value.href) {
- sp_style_set_ipaint_to_uri(style, paint, parent->value.href->getURI(), parent->value.href->getOwnerDocument());
- } else {
- g_warning("Expected paint server not found.");
- }
- } else if ( parent->isColor() ) {
- paint->setColor( parent->value.color );
- } else if ( parent->isNoneSet() ) {
- paint->noneSet = TRUE;
- } else if ( parent->isNone() ) {
- //
- } else {
- g_assert_not_reached();
- }
-}
-
-
-/**
- * Merge filter style from parent.
- * Filter effects do not inherit by default
- */
-static void
-sp_style_merge_ifilter(SPStyle *style, SPIFilter const *parent)
-{
- // FIXME:
- // instead of just copying over, we need to _really merge_ the two filters by combining their
- // filter primitives
-
- sp_style_filter_clear(style);
- style->filter.set = parent->set;
- style->filter.inherit = parent->inherit;
-
- if (style->filter.href){
- if (style->filter.href->getObject()){
- style->filter.href->detach();
- }
- }
- else{
- // it may be that this style has not yet created its SPFilterReference
- if (style->object){
- if (style->object->document) {
- style->filter.href = new SPFilterReference(style->object->document);
- style->filter.href->changedSignal().connect(sigc::bind(sigc::ptr_fun(sp_style_filter_ref_changed), style));
- }
- }
- }
-
- if (style->filter.href && parent->href){
- if (parent->href->getObject()) {
- try {
- style->filter.href->attach(*parent->href->getURI());
- } catch (Inkscape::BadURIException &e) {
- g_warning("%s", e.what());
- style->filter.href->detach();
- }
- }
- }
-}
+// Called in style.cpp, text-editing.cpp
/**
* Dumps the style to a CSS string, with either SP_STYLE_FLAG_IFSET or
* SP_STYLE_FLAG_ALWAYS flags. Used with Always for copying an object's
@@ -2702,146 +1496,11 @@ sp_style_write_string(SPStyle const *const style, guint const flags)
(flags == SP_STYLE_FLAG_ALWAYS) ),
NULL);
- gchar c[BMAX];
- gchar *p = c;
- *p = '\0';
-
- p += sp_style_write_ifontsize(p, c + BMAX - p, "font-size", &style->font_size, NULL, flags);
- p += sp_style_write_ienum(p, c + BMAX - p, "font-style", enum_font_style, &style->font_style, NULL, flags);
- p += sp_style_write_ienum(p, c + BMAX - p, "font-variant", enum_font_variant, &style->font_variant, NULL, flags);
- p += sp_style_write_ienum(p, c + BMAX - p, "font-weight", enum_font_weight, &style->font_weight, NULL, flags);
- p += sp_style_write_ienum(p, c + BMAX - p, "font-stretch", enum_font_stretch, &style->font_stretch, NULL, flags);
-
- /* Text */
- p += sp_style_write_ilength(p, c + BMAX - p, "text-indent", &style->text_indent, NULL, flags);
- p += sp_style_write_ienum(p, c + BMAX - p, "text-align", enum_text_align, &style->text_align, NULL, flags);
- p += sp_style_write_itextdecoration(p, c + BMAX - p, "text-decoration",
- &style->text_decoration_line, &style->text_decoration_style, &style->text_decoration_color,
- NULL, NULL, NULL, flags);
- p += sp_style_write_ilengthornormal(p, c + BMAX - p, "line-height", &style->line_height, NULL, flags);
- p += sp_style_write_ilengthornormal(p, c + BMAX - p, "letter-spacing", &style->letter_spacing, NULL, flags);
- p += sp_style_write_ilengthornormal(p, c + BMAX - p, "word-spacing", &style->word_spacing, NULL, flags);
- p += sp_style_write_ienum(p, c + BMAX - p, "text-transform", enum_text_transform, &style->text_transform, NULL, flags);
- p += sp_style_write_ienum(p, c + BMAX - p, "direction", enum_direction, &style->direction, NULL, flags);
- p += sp_style_write_ienum(p, c + BMAX - p, "block-progression", enum_block_progression, &style->block_progression, NULL, flags);
- p += sp_style_write_ienum(p, c + BMAX - p, "writing-mode", enum_writing_mode, &style->writing_mode, NULL, flags);
-
- p += sp_style_write_ienum(p, c + BMAX - p, "text-anchor", enum_text_anchor, &style->text_anchor, NULL, flags);
- p += sp_style_write_ibaselineshift(p, c + BMAX - p, "baseline-shift", &style->baseline_shift, NULL, flags);
-
-
- /// \todo fixme: Per type methods need default flag too (lauris)
-
- if (style->opacity.value != SP_SCALE24_MAX) {
- p += sp_style_write_iscale24(p, c + BMAX - p, "opacity", &style->opacity, NULL, flags);
- }
-
- if (!style->color.noneSet) { // CSS does not permit "none" for color
- p += sp_style_write_ipaint(p, c + BMAX - p, "color", &style->color, NULL, flags);
- }
- p += sp_style_write_ienum(p, c + BMAX - p, "color-interpolation", enum_color_interpolation, &style->color_interpolation, NULL, flags);
- p += sp_style_write_ienum(p, c + BMAX - p, "color-interpolation-filters", enum_color_interpolation, &style->color_interpolation_filters, NULL, flags);
-
-
- p += sp_style_write_ipaint(p, c + BMAX - p, "fill", &style->fill, NULL, flags);
- // if fill:none, skip writing fill properties
- if (!style->fill.noneSet) {
- p += sp_style_write_iscale24(p, c + BMAX - p, "fill-opacity", &style->fill_opacity, NULL, flags);
- p += sp_style_write_ienum(p, c + BMAX - p, "fill-rule", enum_fill_rule, &style->fill_rule, NULL, flags);
- }
-
- p += sp_style_write_ipaint(p, c + BMAX - p, "stroke", &style->stroke, NULL, flags);
-
- // stroke width affects markers, so write it if there's stroke OR any markers
- if (!style->stroke.noneSet ||
- style->marker[SP_MARKER_LOC].set ||
- style->marker[SP_MARKER_LOC_START].set ||
- style->marker[SP_MARKER_LOC_MID].set ||
- style->marker[SP_MARKER_LOC_END].set) {
- p += sp_style_write_ilength(p, c + BMAX - p, "stroke-width", &style->stroke_width, NULL, flags);
- }
-
- // if stroke:none, skip writing stroke properties
- if (!style->stroke.noneSet) {
- p += sp_style_write_ienum(p, c + BMAX - p, "stroke-linecap", enum_stroke_linecap, &style->stroke_linecap, NULL, flags);
- p += sp_style_write_ienum(p, c + BMAX - p, "stroke-linejoin", enum_stroke_linejoin, &style->stroke_linejoin, NULL, flags);
- p += sp_style_write_ifloat(p, c + BMAX - p, "stroke-miterlimit", &style->stroke_miterlimit, NULL, flags);
- p += sp_style_write_iscale24(p, c + BMAX - p, "stroke-opacity", &style->stroke_opacity, NULL, flags);
- p += sp_style_write_idasharray(p, c + BMAX - p, "stroke-dasharray", &style->stroke_dasharray, NULL, flags);
- p += sp_style_write_ilength(p, c + BMAX - p, "stroke-dashoffset", &style->stroke_dashoffset, NULL, flags);
- }
-
- if (style->paint_order.set) {
- p += sp_style_write_ipaintorder(p, c + BMAX - p, "paint-order", &style->paint_order, NULL, flags);
- } else if (flags == SP_STYLE_FLAG_ALWAYS) {
- p += g_snprintf(p, c + BMAX - p, "paint-order:normal;");
- }
-
- bool marker_none = false;
- gchar *master = style->marker[SP_MARKER_LOC].value;
- if (style->marker[SP_MARKER_LOC].set) {
- p += g_snprintf(p, c + BMAX - p, "marker:%s;", style->marker[SP_MARKER_LOC].value);
- } else if (flags == SP_STYLE_FLAG_ALWAYS) {
- p += g_snprintf(p, c + BMAX - p, "marker:none;");
- marker_none = true;
- }
- if (style->marker[SP_MARKER_LOC_START].set
- && (!master || strcmp(master, style->marker[SP_MARKER_LOC_START].value))) {
- p += g_snprintf(p, c + BMAX - p, "marker-start:%s;", style->marker[SP_MARKER_LOC_START].value);
- } else if (flags == SP_STYLE_FLAG_ALWAYS && !marker_none) {
- p += g_snprintf(p, c + BMAX - p, "marker-start:none;");
- }
- if (style->marker[SP_MARKER_LOC_MID].set
- && (!master || strcmp(master, style->marker[SP_MARKER_LOC_MID].value))) {
- p += g_snprintf(p, c + BMAX - p, "marker-mid:%s;", style->marker[SP_MARKER_LOC_MID].value);
- } else if (flags == SP_STYLE_FLAG_ALWAYS && !marker_none) {
- p += g_snprintf(p, c + BMAX - p, "marker-mid:none;");
- }
- if (style->marker[SP_MARKER_LOC_END].set
- && (!master || strcmp(master, style->marker[SP_MARKER_LOC_END].value))) {
- p += g_snprintf(p, c + BMAX - p, "marker-end:%s;", style->marker[SP_MARKER_LOC_END].value);
- } else if (flags == SP_STYLE_FLAG_ALWAYS && !marker_none) {
- p += g_snprintf(p, c + BMAX - p, "marker-end:none;");
- }
-
- p += sp_style_write_ienum(p, c + BMAX - p, "visibility", enum_visibility, &style->visibility, NULL, flags);
- p += sp_style_write_ienum(p, c + BMAX - p, "display", enum_display, &style->display, NULL, flags);
- p += sp_style_write_ienum(p, c + BMAX - p, "overflow", enum_overflow, &style->overflow, NULL, flags);
- p += sp_style_write_ienum(p, c + BMAX - p, "isolation", enum_isolation, &style->isolation, NULL, flags);
- p += sp_style_write_ienum(p, c + BMAX - p, "mix-blend-mode", enum_blend_mode, &style->blend_mode, NULL, flags);
-
- /* filter: */
- p += sp_style_write_ifilter(p, c + BMAX - p, "filter", &style->filter, NULL, flags);
-
- p += sp_style_write_ienum(p, c + BMAX - p, "enable-background", enum_enable_background, &style->enable_background, NULL, flags);
-
- /* clipping */
- p += sp_style_write_ienum(p, c + BMAX - p, "clip-rule", enum_clip_rule, &style->clip_rule, NULL, flags);
-
- /* rendering */
- p += sp_style_write_ienum(p, c + BMAX - p, "color-rendering", enum_color_rendering, &style->color_rendering, NULL, flags);
- p += sp_style_write_ienum(p, c + BMAX - p, "image-rendering", enum_image_rendering, &style->image_rendering, NULL, flags);
- p += sp_style_write_ienum(p, c + BMAX - p, "shape-rendering", enum_shape_rendering, &style->shape_rendering, NULL, flags);
- p += sp_style_write_ienum(p, c + BMAX - p, "text-rendering", enum_text_rendering, &style->text_rendering, NULL, flags);
-
- /* fixme: */
- p += sp_text_style_write(p, c + BMAX - p, style->text, flags);
-
- /* Get rid of trailing `;'. */
- if (p != c) {
- --p;
- if (*p == ';') {
- *p = '\0';
- }
- }
-
- return g_strdup(c);
+ return g_strdup( style->write( flags ).c_str() );
}
-#define STYLE_BUF_MAX
-
-
+// Called in style.cpp, path-chemistry, NOT in text-editting.cpp (because of bug)
/**
* Dumps style to CSS string, see sp_style_write_string()
*
@@ -2855,2016 +1514,7 @@ sp_style_write_difference(SPStyle const *const from, SPStyle const *const to)
g_return_val_if_fail(from != NULL, NULL);
g_return_val_if_fail(to != NULL, NULL);
- gchar c[BMAX], *p = c;
- *p = '\0';
-
- p += sp_style_write_ifontsize(p, c + BMAX - p, "font-size", &from->font_size, &to->font_size, SP_STYLE_FLAG_IFDIFF);
- p += sp_style_write_ienum(p, c + BMAX - p, "font-style", enum_font_style, &from->font_style, &to->font_style, SP_STYLE_FLAG_IFDIFF);
- p += sp_style_write_ienum(p, c + BMAX - p, "font-variant", enum_font_variant, &from->font_variant, &to->font_variant, SP_STYLE_FLAG_IFDIFF);
- p += sp_style_write_ienum(p, c + BMAX - p, "font-weight", enum_font_weight, &from->font_weight, &to->font_weight, SP_STYLE_FLAG_IFDIFF);
- p += sp_style_write_ienum(p, c + BMAX - p, "font-stretch", enum_font_stretch, &from->font_stretch, &to->font_stretch, SP_STYLE_FLAG_IFDIFF);
-
- /* Text */
- p += sp_style_write_ilength(p, c + BMAX - p, "text-indent", &from->text_indent, &to->text_indent, SP_STYLE_FLAG_IFDIFF);
- p += sp_style_write_ienum(p, c + BMAX - p, "text-align", enum_text_align, &from->text_align, &to->text_align, SP_STYLE_FLAG_IFDIFF);
- p += sp_style_write_itextdecoration(p, c + BMAX - p, "text-decoration",
- &from->text_decoration_line, &from->text_decoration_style, &from->text_decoration_color,
- &to->text_decoration_line, &to->text_decoration_style, &to->text_decoration_color,
- SP_STYLE_FLAG_IFDIFF);
- p += sp_style_write_ilengthornormal(p, c + BMAX - p, "line-height", &from->line_height, &to->line_height, SP_STYLE_FLAG_IFDIFF);
- p += sp_style_write_ilengthornormal(p, c + BMAX - p, "letter-spacing", &from->letter_spacing, &to->letter_spacing, SP_STYLE_FLAG_IFDIFF);
- p += sp_style_write_ilengthornormal(p, c + BMAX - p, "word-spacing", &from->word_spacing, &to->word_spacing, SP_STYLE_FLAG_IFDIFF);
- p += sp_style_write_ienum(p, c + BMAX - p, "text-transform", enum_text_transform, &from->text_transform, &to->text_transform, SP_STYLE_FLAG_IFDIFF);
- p += sp_style_write_ienum(p, c + BMAX - p, "direction", enum_direction, &from->direction, &to->direction, SP_STYLE_FLAG_IFDIFF);
- p += sp_style_write_ienum(p, c + BMAX - p, "block-progression", enum_block_progression, &from->block_progression, &to->block_progression, SP_STYLE_FLAG_IFDIFF);
- p += sp_style_write_ienum(p, c + BMAX - p, "writing-mode", enum_writing_mode, &from->writing_mode, &to->writing_mode, SP_STYLE_FLAG_IFDIFF);
-
- p += sp_style_write_ienum(p, c + BMAX - p, "text-anchor", enum_text_anchor, &from->text_anchor, &to->text_anchor, SP_STYLE_FLAG_IFDIFF);
- p += sp_style_write_ibaselineshift(p, c + BMAX - p, "baseline-shift", &from->baseline_shift, &to->baseline_shift, SP_STYLE_FLAG_IFDIFF);
-
- /// \todo fixme: Per type methods need default flag too
- if (from->opacity.set && from->opacity.value != SP_SCALE24_MAX) {
- p += sp_style_write_iscale24(p, c + BMAX - p, "opacity", &from->opacity, &to->opacity, SP_STYLE_FLAG_IFSET);
- }
-
- if (!from->color.noneSet) { // CSS does not permit "none" for color
- p += sp_style_write_ipaint(p, c + BMAX - p, "color", &from->color, &to->color, SP_STYLE_FLAG_IFSET);
- }
- p += sp_style_write_ienum(p, c + BMAX - p, "color-interpolation", enum_color_interpolation, &from->color_interpolation, &to->color_interpolation, SP_STYLE_FLAG_IFDIFF);
- p += sp_style_write_ienum(p, c + BMAX - p, "color-interpolation-filters", enum_color_interpolation, &from->color_interpolation_filters, &to->color_interpolation_filters, SP_STYLE_FLAG_IFDIFF);
-
- p += sp_style_write_ipaint(p, c + BMAX - p, "fill", &from->fill, &to->fill, SP_STYLE_FLAG_IFDIFF);
- // if fill:none, skip writing fill properties
- if (!from->fill.noneSet) {
- p += sp_style_write_iscale24(p, c + BMAX - p, "fill-opacity", &from->fill_opacity, &to->fill_opacity, SP_STYLE_FLAG_IFDIFF);
- p += sp_style_write_ienum(p, c + BMAX - p, "fill-rule", enum_fill_rule, &from->fill_rule, &to->fill_rule, SP_STYLE_FLAG_IFDIFF);
- }
-
- p += sp_style_write_ipaint(p, c + BMAX - p, "stroke", &from->stroke, &to->stroke, SP_STYLE_FLAG_IFDIFF);
-
- // stroke width affects markers, so write it if there's stroke OR any markers
- if (!from->stroke.noneSet ||
- from->marker[SP_MARKER_LOC].set ||
- from->marker[SP_MARKER_LOC_START].set ||
- from->marker[SP_MARKER_LOC_MID].set ||
- from->marker[SP_MARKER_LOC_END].set) {
- p += sp_style_write_ilength(p, c + BMAX - p, "stroke-width", &from->stroke_width, &to->stroke_width, SP_STYLE_FLAG_IFDIFF);
- }
-
- // if stroke:none, skip writing stroke properties
- if (!from->stroke.noneSet) {
- p += sp_style_write_ienum(p, c + BMAX - p, "stroke-linecap", enum_stroke_linecap,
- &from->stroke_linecap, &to->stroke_linecap, SP_STYLE_FLAG_IFDIFF);
- p += sp_style_write_ienum(p, c + BMAX - p, "stroke-linejoin", enum_stroke_linejoin,
- &from->stroke_linejoin, &to->stroke_linejoin, SP_STYLE_FLAG_IFDIFF);
- p += sp_style_write_ifloat(p, c + BMAX - p, "stroke-miterlimit",
- &from->stroke_miterlimit, &to->stroke_miterlimit, SP_STYLE_FLAG_IFDIFF);
- p += sp_style_write_idasharray(p, c + BMAX - p, "stroke-dasharray",
- &from->stroke_dasharray, &to->stroke_dasharray, SP_STYLE_FLAG_IFDIFF);
- p += sp_style_write_ilength(p, c + BMAX - p, "stroke-dashoffset", &from->stroke_dashoffset, &to->stroke_dashoffset, SP_STYLE_FLAG_IFDIFF);
- p += sp_style_write_iscale24(p, c + BMAX - p, "stroke-opacity", &from->stroke_opacity, &to->stroke_opacity, SP_STYLE_FLAG_IFDIFF);
- }
-
- /* paint-order */
- if( from->paint_order.set) {
- p += sp_style_write_ipaintorder(p, c + BMAX - p, "paint-order", &from->paint_order, &to->paint_order, SP_STYLE_FLAG_IFDIFF);
- }
-
- /* markers */
- gchar *master = from->marker[SP_MARKER_LOC].value;
- if (master != NULL) {
- p += g_snprintf(p, c + BMAX - p, "marker:%s;", master);
- }
- if (from->marker[SP_MARKER_LOC_START].value != NULL && (!master || strcmp(master, from->marker[SP_MARKER_LOC_START].value))) {
- p += g_snprintf(p, c + BMAX - p, "marker-start:%s;", from->marker[SP_MARKER_LOC_START].value);
- }
- if (from->marker[SP_MARKER_LOC_MID].value != NULL && (!master || strcmp(master, from->marker[SP_MARKER_LOC_MID].value))) {
- p += g_snprintf(p, c + BMAX - p, "marker-mid:%s;", from->marker[SP_MARKER_LOC_MID].value);
- }
- if (from->marker[SP_MARKER_LOC_END].value != NULL && (!master || strcmp(master, from->marker[SP_MARKER_LOC_END].value))) {
- p += g_snprintf(p, c + BMAX - p, "marker-end:%s;", from->marker[SP_MARKER_LOC_END].value);
- }
-
- p += sp_style_write_ienum(p, c + BMAX - p, "visibility", enum_visibility, &from->visibility, &to->visibility, SP_STYLE_FLAG_IFSET);
- p += sp_style_write_ienum(p, c + BMAX - p, "display", enum_display, &from->display, &to->display, SP_STYLE_FLAG_IFSET);
- p += sp_style_write_ienum(p, c + BMAX - p, "overflow", enum_overflow, &from->overflow, &to->overflow, SP_STYLE_FLAG_IFSET);
- p += sp_style_write_ienum(p, c + BMAX - p, "isolation", enum_isolation, &from->isolation, &to->isolation, SP_STYLE_FLAG_IFSET);
- p += sp_style_write_ienum(p, c + BMAX - p, "mix-blend-mode", enum_blend_mode, &from->blend_mode, &to->blend_mode, SP_STYLE_FLAG_IFSET);
-
- /* filter: */
- p += sp_style_write_ifilter(p, c + BMAX - p, "filter", &from->filter, &to->filter, SP_STYLE_FLAG_IFDIFF);
-
- p += sp_style_write_ienum(p, c + BMAX - p, "enable-background", enum_enable_background, &from->enable_background, &to->enable_background, SP_STYLE_FLAG_IFSET);
-
- p += sp_text_style_write(p, c + BMAX - p, from->text, SP_STYLE_FLAG_IFDIFF);
-
- p += sp_style_write_ienum(p, c + BMAX - p, "clip-rule", enum_clip_rule, &from->clip_rule, &to->clip_rule, SP_STYLE_FLAG_IFDIFF);
-
- /* rendering */
- p += sp_style_write_ienum(p, c + BMAX - p, "color-rendering", enum_color_rendering, &from->color_rendering, &to->color_rendering, SP_STYLE_FLAG_IFDIFF);
- p += sp_style_write_ienum(p, c + BMAX - p, "image-rendering", enum_image_rendering, &from->image_rendering, &to->image_rendering, SP_STYLE_FLAG_IFDIFF);
- p += sp_style_write_ienum(p, c + BMAX - p, "shape-rendering", enum_shape_rendering, &from->shape_rendering, &to->shape_rendering, SP_STYLE_FLAG_IFDIFF);
- p += sp_style_write_ienum(p, c + BMAX - p, "text-rendering", enum_text_rendering, &from->text_rendering, &to->text_rendering, SP_STYLE_FLAG_IFDIFF);
-
- /** \todo
- * The reason we use IFSET rather than IFDIFF is the belief that the IFDIFF
- * flag is mainly only for attributes that don't handle explicit unset well.
- * We may need to revisit the behaviour of this routine.
- */
-
- /* Get rid of trailing `;'. */
- if (p != c) {
- --p;
- if (*p == ';') {
- *p = '\0';
- }
- }
-
- return g_strdup(c);
-}
-
-
-
-/**
- * Reset all style properties.
- */
-static void
-sp_style_clear(SPStyle *style)
-{
- g_return_if_fail(style != NULL);
-
- style->fill.clear();
- style->stroke.clear();
- sp_style_filter_clear(style);
-
- style->release_connection.disconnect();
-
- style->fill_ps_modified_connection.disconnect();
- if (style->fill.value.href) {
- delete style->fill.value.href;
- style->fill.value.href = NULL;
- }
- style->stroke_ps_modified_connection.disconnect();
- if (style->stroke.value.href) {
- delete style->stroke.value.href;
- style->stroke.value.href = NULL;
- }
- style->filter_modified_connection.disconnect();
- if (style->filter.href) {
- delete style->filter.href;
- style->filter.href = NULL;
- }
-
- style->stroke_dasharray.values.clear();
- style->stroke_dasharray.inherit = FALSE;
- style->stroke_dashoffset.inherit = FALSE;
-
- /** \todo fixme: Do that text manipulation via parents */
- SPObject *object = style->object;
- SPDocument *document = style->document;
- gint const refcount = style->refcount;
- SPTextStyle *text = style->text;
- unsigned const text_private = style->text_private;
-
-
- style->refcount = refcount;
- style->object = object;
- style->document = document;
-
- if (document) {
- style->filter.href = new SPFilterReference(document);
- style->filter.href->changedSignal().connect(sigc::bind(sigc::ptr_fun(sp_style_filter_ref_changed), style));
-
- style->fill.value.href = new SPPaintServerReference(document);
- style->fill.value.href->changedSignal().connect(sigc::bind(sigc::ptr_fun(sp_style_fill_paint_server_ref_changed), style));
-
- style->stroke.value.href = new SPPaintServerReference(document);
- style->stroke.value.href->changedSignal().connect(sigc::bind(sigc::ptr_fun(sp_style_stroke_paint_server_ref_changed), style));
- }
-
- style->text = text;
- style->text_private = text_private;
-
- style->text->font_specification.set = FALSE;
- style->text->font.set = FALSE;
- style->text->font_family.set = FALSE;
-
- style->font_size.set = FALSE;
- style->font_size.inherit = FALSE;
- style->font_size.type = SP_FONT_SIZE_LITERAL;
- style->font_size.unit = 0;
- style->font_size.literal = SP_CSS_FONT_SIZE_MEDIUM;
- style->font_size.value = 12.0;
- style->font_size.computed = 12.0;
- style->font_style.set = FALSE;
- style->font_style.inherit = FALSE;
- style->font_style.value = style->font_style.computed = SP_CSS_FONT_STYLE_NORMAL;
- style->font_variant.set = FALSE;
- style->font_variant.inherit = FALSE;
- style->font_variant.value = style->font_variant.computed = SP_CSS_FONT_VARIANT_NORMAL;
- style->font_weight.set = FALSE;
- style->font_weight.inherit = FALSE;
- style->font_weight.value = SP_CSS_FONT_WEIGHT_NORMAL;
- style->font_weight.computed = SP_CSS_FONT_WEIGHT_400;
- style->font_stretch.set = FALSE;
- style->font_stretch.inherit = FALSE;
- style->font_stretch.value = style->font_stretch.computed = SP_CSS_FONT_STRETCH_NORMAL;
-
- /* text */
- style->text_indent.set = FALSE;
- style->text_indent.inherit = FALSE;
- style->text_indent.unit = SP_CSS_UNIT_NONE;
- style->text_indent.computed = 0.0;
-
- style->text_align.set = FALSE;
- style->text_align.inherit = FALSE;
- style->text_align.value = style->text_align.computed = SP_CSS_TEXT_ALIGN_START;
-
- style->text_decoration_line.set = FALSE;
- style->text_decoration_line.inherit = FALSE;
- style->text_decoration_line.underline = FALSE;
- style->text_decoration_line.overline = FALSE;
- style->text_decoration_line.line_through = FALSE;
- style->text_decoration_line.blink = FALSE;
-
- style->text_decoration_style.set = FALSE;
- style->text_decoration_style.inherit = FALSE;
- style->text_decoration_style.solid = FALSE;
- style->text_decoration_style.isdouble = FALSE;
- style->text_decoration_style.dotted = FALSE;
- style->text_decoration_style.dashed = FALSE;
- style->text_decoration_style.wavy = FALSE;
-
- style->text_decoration_color.clear();
-
- style->line_height.set = FALSE;
- style->line_height.inherit = FALSE;
- style->line_height.unit = SP_CSS_UNIT_PERCENT;
- style->line_height.normal = TRUE;
- style->line_height.value = style->line_height.computed = 1.0;
-
- style->letter_spacing.set = FALSE;
- style->letter_spacing.inherit = FALSE;
- style->letter_spacing.unit = SP_CSS_UNIT_NONE;
- style->letter_spacing.normal = TRUE;
- style->letter_spacing.value = style->letter_spacing.computed = 0.0;
-
- style->word_spacing.set = FALSE;
- style->word_spacing.inherit = FALSE;
- style->word_spacing.unit = SP_CSS_UNIT_NONE;
- style->word_spacing.normal = TRUE;
- style->word_spacing.value = style->word_spacing.computed = 0.0;
-
- style->baseline_shift.set = FALSE;
- style->baseline_shift.inherit = FALSE;
- style->baseline_shift.type = SP_BASELINE_SHIFT_LITERAL;
- style->baseline_shift.unit = SP_CSS_UNIT_NONE;
- style->baseline_shift.literal = SP_CSS_BASELINE_SHIFT_BASELINE;
- style->baseline_shift.value = 0.0;
- style->baseline_shift.computed = 0.0;
-
- style->text_transform.set = FALSE;
- style->text_transform.inherit = FALSE;
- style->text_transform.value = style->text_transform.computed = SP_CSS_TEXT_TRANSFORM_NONE;
-
- style->direction.set = FALSE;
- style->direction.inherit = FALSE;
- style->direction.value = style->direction.computed = SP_CSS_DIRECTION_LTR;
-
- style->block_progression.set = FALSE;
- style->block_progression.inherit = FALSE;
- style->block_progression.value = style->block_progression.computed = SP_CSS_BLOCK_PROGRESSION_TB;
-
- style->writing_mode.set = FALSE;
- style->writing_mode.inherit = FALSE;
- style->writing_mode.value = style->writing_mode.computed = SP_CSS_WRITING_MODE_LR_TB;
-
- style->text_anchor.set = FALSE;
- style->text_anchor.inherit = FALSE;
- style->text_anchor.value = style->text_anchor.computed = SP_CSS_TEXT_ANCHOR_START;
-
- style->clip_set = FALSE;
- style->color_set = FALSE;
- style->cursor_set = FALSE;
- style->overflow_set = FALSE;
- style->clip_path_set = FALSE;
- style->mask_set = FALSE;
-
- style->clip_rule.set = FALSE;
- style->clip_rule.inherit = FALSE;
- style->clip_rule.value = style->clip_rule.computed = SP_WIND_RULE_NONZERO;
-
- style->opacity.set = FALSE;
- style->opacity.inherit = FALSE;
- style->opacity.value = SP_SCALE24_MAX;
- style->visibility.set = FALSE;
- style->visibility.inherit = FALSE;
- style->visibility.value = style->visibility.computed = SP_CSS_VISIBILITY_VISIBLE;
- style->display.set = FALSE;
- style->display.inherit = FALSE;
- style->display.value = style->display.computed = SP_CSS_DISPLAY_INLINE;
- style->overflow.set = FALSE;
- style->overflow.inherit = FALSE;
- style->overflow.value = style->overflow.computed = SP_CSS_OVERFLOW_VISIBLE;
- style->isolation.set = FALSE;
- style->isolation.inherit = FALSE;
- style->isolation.value = style->isolation.computed = SP_CSS_ISOLATION_AUTO;
- style->blend_mode.set = FALSE;
- style->blend_mode.inherit = FALSE;
- style->blend_mode.value = style->blend_mode.computed = SP_CSS_BLEND_NORMAL;
-
- style->color.clear();
- style->color.setColor(0.0, 0.0, 0.0);
- style->color_interpolation.set = FALSE;
- style->color_interpolation.inherit = FALSE;
- style->color_interpolation.value = style->color_interpolation.computed = SP_CSS_COLOR_INTERPOLATION_SRGB;
- style->color_interpolation_filters.set = FALSE;
- style->color_interpolation_filters.inherit = FALSE;
- style->color_interpolation_filters.value = style->color_interpolation_filters.computed = SP_CSS_COLOR_INTERPOLATION_LINEARRGB;
-
-
- style->fill.clear();
- style->fill.setColor(0.0, 0.0, 0.0);
- style->fill_opacity.set = FALSE;
- style->fill_opacity.inherit = FALSE;
- style->fill_opacity.value = SP_SCALE24_MAX;
- style->fill_rule.set = FALSE;
- style->fill_rule.inherit = FALSE;
- style->fill_rule.value = style->fill_rule.computed = SP_WIND_RULE_NONZERO;
-
- style->stroke.clear();
- style->stroke_opacity.set = FALSE;
- style->stroke_opacity.inherit = FALSE;
- style->stroke_opacity.value = SP_SCALE24_MAX;
-
- style->stroke_width.set = FALSE;
- style->stroke_width.inherit = FALSE;
- style->stroke_width.unit = SP_CSS_UNIT_NONE;
- style->stroke_width.value = style->stroke_width.computed = 1.0;
-
- style->stroke_linecap.set = FALSE;
- style->stroke_linecap.inherit = FALSE;
- style->stroke_linecap.value = style->stroke_linecap.computed = SP_STROKE_LINECAP_BUTT;
- style->stroke_linejoin.set = FALSE;
- style->stroke_linejoin.inherit = FALSE;
- style->stroke_linejoin.value = style->stroke_linejoin.computed = SP_STROKE_LINEJOIN_MITER;
-
- style->stroke_miterlimit.set = FALSE;
- style->stroke_miterlimit.inherit = FALSE;
- style->stroke_miterlimit.value = 4.0;
-
- style->stroke_dasharray.values.clear();
- style->stroke_dasharray.set = FALSE;
- style->stroke_dasharray.inherit = FALSE;
-
- style->stroke_dashoffset.value = style->stroke_dashoffset.computed = 0.0;
- style->stroke_dashoffset.set = FALSE;
- style->stroke_dashoffset.inherit = FALSE;
-
- for (unsigned i = SP_MARKER_LOC; i < SP_MARKER_LOC_QTY; i++) {
- g_free(style->marker[i].value);
- style->marker[i].set = FALSE;
- style->marker[i].inherit = FALSE;
- style->marker[i].data = 0;
- style->marker[i].value = NULL;
- }
-
- /* SVG 2 */
- style->paint_order.set = FALSE;
- style->paint_order.inherit = FALSE; // For now
- for (unsigned i = 0; i < PAINT_ORDER_LAYERS; ++i) {
- style->paint_order.layer[i] = SP_CSS_PAINT_ORDER_NORMAL;
- style->paint_order.layer_set[i] = false;
- }
- style->paint_order.value = NULL;
-
- style->filter.set = FALSE;
- style->filter.inherit = FALSE;
- style->filter.href = NULL;
-
- style->enable_background.value = SP_CSS_BACKGROUND_ACCUMULATE;
- style->enable_background.set = false;
- style->enable_background.inherit = false;
-
- style->filter_blend_mode.set = style->filter_blend_mode.inherit = false;
- style->filter_blend_mode.value = style->filter_blend_mode.computed = 0;
- style->filter_gaussianBlur_deviation.set = style->filter_gaussianBlur_deviation.inherit = false;
- style->filter_gaussianBlur_deviation.value = style->filter_gaussianBlur_deviation.computed = 0;
-
- style->color_rendering.set = style->color_rendering.inherit = false;
- style->color_rendering.value = style->color_rendering.computed = SP_CSS_COLOR_RENDERING_AUTO;
- style->image_rendering.set = style->image_rendering.inherit = false;
- style->image_rendering.value = style->image_rendering.computed = SP_CSS_IMAGE_RENDERING_AUTO;
- style->shape_rendering.set = style->shape_rendering.inherit = false;
- style->shape_rendering.value = style->shape_rendering.computed = SP_CSS_SHAPE_RENDERING_AUTO;
- style->text_rendering.set = style->text_rendering.inherit = false;
- style->text_rendering.value = style->text_rendering.computed = SP_CSS_TEXT_RENDERING_AUTO;
-
- style->cloned = false;
-}
-
-
-
-/**
- *
- */
-static void
-sp_style_read_dash(SPStyle *style, gchar const *str)
-{
- /* Ref: http://www.w3.org/TR/SVG11/painting.html#StrokeDasharrayProperty */
- style->stroke_dasharray.set = TRUE;
-
- if (strcmp(str, "inherit") == 0) {
- style->stroke_dasharray.inherit = true;
- return;
- }
- style->stroke_dasharray.inherit = false;
-
- style->stroke_dasharray.values.clear();
-
- if (strcmp(str, "none") == 0) {
- return;
- }
-
- gchar *e = NULL;
- bool LineSolid = true;
- while (e != str) {
- /* TODO: Should allow <length> rather than just a unitless (px) number. */
- double number = g_ascii_strtod(str, (char **) &e);
- style->stroke_dasharray.values.push_back( number );
- if (number > 0.00000001)
- LineSolid = false;
- if (e != str) {
- str = e;
- }
- while (str && *str && !isalnum(*str)) str += 1;
- }
-
- if (LineSolid) {
- style->stroke_dasharray.values.clear();
- }
-}
-
-
-/*#########################
-## SPTextStyle operations
-#########################*/
-
-
-/**
- * Return new SPTextStyle object with default settings.
- */
-static SPTextStyle *
-sp_text_style_new()
-{
- SPTextStyle *ts = g_new0(SPTextStyle, 1);
- ts->refcount = 1;
- sp_text_style_clear(ts);
-
- ts->font_specification.value = g_strdup("sans-serif");
- ts->font.value = g_strdup("sans-serif");
- ts->font_family.value = g_strdup("sans-serif");
-
- return ts;
-}
-
-
-/**
- * Clear text style settings.
- */
-static void
-sp_text_style_clear(SPTextStyle *ts)
-{
- ts->font_specification.set = FALSE;
- ts->font.set = FALSE;
- ts->font_family.set = FALSE;
-}
-
-
-
-/**
- * Reduce refcount of text style and possibly free it.
- */
-static SPTextStyle *
-sp_text_style_unref(SPTextStyle *st)
-{
- st->refcount -= 1;
-
- if (st->refcount < 1) {
- g_free(st->font_specification.value);
- g_free(st->font.value);
- g_free(st->font_family.value);
- g_free(st);
- }
-
- return NULL;
-}
-
-
-
-/**
- * Return duplicate of text style.
- */
-static SPTextStyle *
-sp_text_style_duplicate_unset(SPTextStyle *st)
-{
- SPTextStyle *nt = g_new0(SPTextStyle, 1);
- nt->refcount = 1;
-
- nt->font_specification.value = g_strdup(st->font_specification.value);
- nt->font.value = g_strdup(st->font.value);
- nt->font_family.value = g_strdup(st->font_family.value);
-
- return nt;
-}
-
-
-
-/**
- * Write SPTextStyle object into string.
- */
-static guint
-sp_text_style_write(gchar *p, guint const len, SPTextStyle const *const st, guint flags)
-{
- gint d = 0;
-
- // We do not do diffing for text style
- if (flags == SP_STYLE_FLAG_IFDIFF)
- flags = SP_STYLE_FLAG_IFSET;
-
- d += sp_style_write_istring(p + d, len - d, "font-family", &st->font_family, NULL, flags);
- d += sp_style_write_istring(p + d, len - d, "-inkscape-font-specification", &st->font_specification, NULL, flags);
- return d;
-}
-
-
-
-/* The following sp_tyle_read_* functions ignore invalid values, as per
- * http://www.w3.org/TR/REC-CSS2/syndata.html#parsing-errors.
- *
- * [However, the SVG spec is somewhat unclear as to whether the style attribute should
- * be handled as per CSS2 rules or whether it must simply be a set of PROPERTY:VALUE
- * pairs, in which case SVG's error-handling rules
- * http://www.w3.org/TR/SVG11/implnote.html#ErrorProcessing should instead be applied.]
- */
-
-
-/**
- * Set SPIFloat object from string.
- */
-static void
-sp_style_read_ifloat(SPIFloat *val, gchar const *str)
-{
- if (!strcmp(str, "inherit")) {
- val->set = TRUE;
- val->inherit = TRUE;
- } else {
- gfloat value;
- if (sp_svg_number_read_f(str, &value)) {
- val->set = TRUE;
- val->inherit = FALSE;
- val->value = value;
- }
- }
-}
-
-
-
-/**
- * Set SPIScale24 object from string.
- */
-static void
-sp_style_read_iscale24(SPIScale24 *val, gchar const *str)
-{
- if (!strcmp(str, "inherit")) {
- val->set = TRUE;
- val->inherit = TRUE;
- } else {
- gfloat value;
- if (sp_svg_number_read_f(str, &value)) {
- val->set = TRUE;
- val->inherit = FALSE;
- value = CLAMP(value, 0.0, 1.0);
- val->value = SP_SCALE24_FROM_FLOAT(value);
- }
- }
-}
-
-/**
- * Reads a style value and performs lookup based on the given style value enumerations.
- */
-static void
-sp_style_read_ienum(SPIEnum *val, gchar const *str, SPStyleEnum const *dict,
- bool const can_explicitly_inherit)
-{
- if ( can_explicitly_inherit && !strcmp(str, "inherit") ) {
- val->set = TRUE;
- val->inherit = TRUE;
- } else {
- for (unsigned i = 0; dict[i].key; i++) {
- if (!strcmp(str, dict[i].key)) {
- val->set = TRUE;
- val->inherit = FALSE;
- val->value = dict[i].value;
- /* Save copying for values not needing it */
- val->computed = val->value;
- break;
- }
- }
- }
- return;
-}
-
-
-
-/**
- * Set SPIString object from string.
- */
-static void
-sp_style_read_istring(SPIString *val, gchar const *str)
-{
- g_free(val->value);
-
- if (!strcmp(str, "inherit")) {
- val->set = TRUE;
- val->inherit = TRUE;
- val->value = NULL;
- } else {
- val->set = TRUE;
- val->inherit = FALSE;
- val->value = g_strdup(str);
- }
-}
-
-
-
-/**
- * Set SPILength object from string.
- */
-static void
-sp_style_read_ilength(SPILength *val, gchar const *str)
-{
- if (!strcmp(str, "inherit")) {
- val->set = TRUE;
- val->inherit = TRUE;
- } else {
- gdouble value;
- gchar *e;
- /** \todo fixme: Move this to standard place (Lauris) */
- value = g_ascii_strtod(str, &e);
- if ( !IS_FINITE(value) ) { // fix for bug lp:935157
- return;
- }
- if ((gchar const *) e != str) {
- /** \todo
- * Allow the number of px per inch to vary (document preferences,
- * X server or whatever). E.g. don't fill in computed here, do
- * it at the same time as percentage units are done.
- */
- val->value = value;
- if (!*e) {
- /* Userspace */
- val->unit = SP_CSS_UNIT_NONE;
- val->computed = value;
- } else if (!strcmp(e, "px")) {
- /* Userspace */
- val->unit = SP_CSS_UNIT_PX;
- val->computed = value;
- } else if (!strcmp(e, "pt")) {
- /* Userspace / DEVICESCALE */
- val->unit = SP_CSS_UNIT_PT;
- val->computed = Inkscape::Util::Quantity::convert(value, "pt", "px");
- } else if (!strcmp(e, "pc")) {
- val->unit = SP_CSS_UNIT_PC;
- val->computed = Inkscape::Util::Quantity::convert(value, "pc", "px");
- } else if (!strcmp(e, "mm")) {
- val->unit = SP_CSS_UNIT_MM;
- val->computed = Inkscape::Util::Quantity::convert(value, "mm", "px");
- } else if (!strcmp(e, "cm")) {
- val->unit = SP_CSS_UNIT_CM;
- val->computed = Inkscape::Util::Quantity::convert(value, "cm", "px");
- } else if (!strcmp(e, "in")) {
- val->unit = SP_CSS_UNIT_IN;
- val->computed = Inkscape::Util::Quantity::convert(value, "in", "px");
- } else if (!strcmp(e, "em")) {
- /* EM square */
- val->unit = SP_CSS_UNIT_EM;
- val->computed = value * SP_CSS_FONT_SIZE_DEFAULT;
- } else if (!strcmp(e, "ex")) {
- /* ex square */
- val->unit = SP_CSS_UNIT_EX;
- val->computed = value * 0.5 * SP_CSS_FONT_SIZE_DEFAULT;
- } else if (!strcmp(e, "%")) {
- /* Percentage */
- val->unit = SP_CSS_UNIT_PERCENT;
- val->value = value * 0.01;
- } else {
- /* Invalid */
- return;
- }
- val->set = TRUE;
- val->inherit = FALSE;
- }
- }
-}
-
-/**
- * Set SPILengthOrNormal object from string.
- */
-static void
-sp_style_read_ilengthornormal(SPILengthOrNormal *val, gchar const *str)
-{
- if (!strcmp(str, "normal")) {
- val->set = TRUE;
- val->inherit = FALSE;
- val->normal = TRUE;
- val->unit = SP_CSS_UNIT_NONE;
- val->value = val->computed = 0.0;
- } else {
- SPILength length;
- sp_style_read_ilength(&length, str);
- val->set = length.set;
- val->inherit = length.inherit;
- val->normal = FALSE;
- val->unit = length.unit;
- val->value = length.value;
- val->computed = length.computed;
- }
-}
-
-/**
- * Set SPIPaintOrder object from string.
- */
-static void
-sp_style_read_ipaintorder(SPIPaintOrder *val, gchar const *str)
-{
- g_free(val->value);
-
- if (!strcmp(str, "inherit")) {
- // NEED TO CHECK FINAL SPEC
- val->set = TRUE;
- val->inherit = TRUE;
- val->value = NULL;
- } else {
- val->set = TRUE;
- val->inherit = FALSE;
- val->value = g_strdup(str);
-
- if (!strcmp(str, "normal")) {
- val->layer[0] = SP_CSS_PAINT_ORDER_NORMAL;
- val->layer_set[0] = true;
- } else {
- // This certainly can be done more efficiently
- gchar** c = g_strsplit(str, " ", PAINT_ORDER_LAYERS + 1);
- bool used[3] = {false, false, false};
- unsigned int i = 0;
- for( ; i < PAINT_ORDER_LAYERS; ++i ) {
- if( c[i] ) {
- val->layer_set[i] = false;
- if( !strcmp( c[i], "fill")) {
- val->layer[i] = SP_CSS_PAINT_ORDER_FILL;
- val->layer_set[i] = true;
- used[0] = true;
- } else if( !strcmp( c[i], "stroke")) {
- val->layer[i] = SP_CSS_PAINT_ORDER_STROKE;
- val->layer_set[i] = true;
- used[1] = true;
- } else if( !strcmp( c[i], "markers")) {
- val->layer[i] = SP_CSS_PAINT_ORDER_MARKER;
- val->layer_set[i] = true;
- used[2] = true;
- } else {
- break;
- }
- } else {
- break;
- }
- }
- g_strfreev(c);
-
- // Fill out rest of the layers using the default order
- if( !used[0] && i < PAINT_ORDER_LAYERS ) {
- val->layer[i] = SP_CSS_PAINT_ORDER_FILL;
- val->layer_set[i] = false;
- ++i;
- }
- if( !used[1] && i < PAINT_ORDER_LAYERS ) {
- val->layer[i] = SP_CSS_PAINT_ORDER_STROKE;
- val->layer_set[i] = false;
- ++i;
- }
- if( !used[2] && i < PAINT_ORDER_LAYERS ) {
- val->layer[i] = SP_CSS_PAINT_ORDER_MARKER;
- val->layer_set[i] = false;
- }
- }
- }
-}
-
-
-
-/**
- * Set SPITextDecoration object from string.
- */
-static void
-sp_style_read_itextdecoration(SPITextDecorationLine *line, SPITextDecorationStyle *style, SPIPaint *color, gchar const *str){
- sp_style_read_itextdecorationLine(line, str); // scans all tokens for line types
- sp_style_read_itextdecorationStyle(style, str); // scans all tokens for style types
- // the color routine must be fed one token at a time - if multiple colors are found the LAST one is used
- const gchar *hstr = str;
- while (1) {
- if (*str == ' ' || *str == ',' || *str == '\0'){
- int slen = str - hstr;
- gchar *frag = g_strndup(hstr,slen+1); // only send one piece at a time, since keywords may be intermixed
- sp_style_read_itextdecorationColor(color, frag);
- g_free(frag);
- if(color->set)break;
- if(*str == '\0')break;
- hstr = str + 1;
- }
- str++;
- }
-}
-
-/**
- * Set SPITextDecorationLine object from string.
- * returns true if there was a match, false otherwise
- */
-static void
-sp_style_read_itextdecorationLine(SPITextDecorationLine *line, gchar const *str){
- if (!strcmp(str, "inherit")) {
- line->set = true;
- line->inherit = true;
- } else if (!strcmp(str, "none")) {
- line->set = true;
- line->inherit = false;
- line->underline = false;
- line->overline = false;
- line->line_through = false;
- line->blink = false;
- } else {
- bool found_one = false;
- bool hit_one = false;
-
- // CSS 2 keywords
- bool found_underline = false;
- bool found_overline = false;
- bool found_line_through = false;
- bool found_blink = false;
-
- // this method ignores inlineid keys and extra delimiters, so " ,,, blink hello" will set blink and ignore hello
- const gchar *hstr = str;
- while (1) {
- if (*str == ' ' || *str == ',' || *str == '\0'){
- int slen = str - hstr;
- // CSS 2 keywords
- while(1){ // not really a loop, used to avoid a goto
- hit_one = true; // most likely we will
- if ((slen == 9) && strneq(hstr, "underline", slen)){ found_underline = true; break; }
- if ((slen == 8) && strneq(hstr, "overline", slen)){ found_overline = true; break; }
- if ((slen == 12) && strneq(hstr, "line-through", slen)){ found_line_through = true; break; }
- if ((slen == 5) && strneq(hstr, "blink", slen)){ found_blink = true; break; }
- if ((slen == 4) && strneq(hstr, "none", slen)){ break; }
-
- hit_one = false; // whatever this thing is, we do not recognize it
- break;
- }
- found_one |= hit_one;
- if(*str == '\0')break;
- hstr = str + 1;
- }
- str++;
- }
- if (found_one) {
- line->set = true;
- line->inherit = false;
- line->underline = found_underline;
- line->overline = found_overline;
- line->line_through = found_line_through;
- line->blink = found_blink;
- }
- else {
- line->set = false;
- line->inherit = false;
- }
- }
-}
-
-/**
- * Set SPITextDecorationStyle object from string.
- * returns true if there was a match, false otherwise
-*/
-static void
-sp_style_read_itextdecorationStyle(SPITextDecorationStyle *style, gchar const *str){
- if (!strcmp(str, "inherit")) {
- style->set = true;
- style->inherit = true;
- } else if (!strcmp(str, "none")) {
- style->set = true;
- style->inherit = false;
- style->solid = false;
- style->isdouble = false;
- style->dotted = false;
- style->dashed = false;
- style->wavy = false;
- } else {
- // note, these are CSS 3 keywords
- bool found_solid = false;
- bool found_double = false;
- bool found_dotted = false;
- bool found_dashed = false;
- bool found_wavy = false;
- bool found_one = false;
-
- // this method ignores inlineid keys and extra delimiters, so " ,,, style hello" will set style and ignore hello
- // if more than one style is present, the first is used
- const gchar *hstr = str;
- while (1) {
- if (*str == ' ' || *str == ',' || *str == '\0'){
- int slen = str - hstr;
- if ( (slen == 5) && strneq(hstr, "solid", slen)){ found_solid = true; found_one = true; break; }
- else if ((slen == 6) && strneq(hstr, "double", slen)){ found_double = true; found_one = true; break; }
- else if ((slen == 6) && strneq(hstr, "dotted", slen)){ found_dotted = true; found_one = true; break; }
- else if ((slen == 6) && strneq(hstr, "dashed", slen)){ found_dashed = true; found_one = true; break; }
- else if ((slen == 4) && strneq(hstr, "wavy", slen)){ found_wavy = true; found_one = true; break; }
- if(*str == '\0')break; // nothing more to test
- hstr = str + 1;
- }
- str++;
- }
- if(found_one){
- style->set = true;
- style->inherit = false;
- style->solid = found_solid;
- style->isdouble = found_double;
- style->dotted = found_dotted;
- style->dashed = found_dashed;
- style->wavy = found_wavy;
- }
- else {
- style->set = false;
- style->inherit = false;
- }
- }
-}
-
-/**
- * Set SPIPaint object from string.
- */
-static void
-sp_style_read_itextdecorationColor(SPIPaint *color, gchar const *str){
- sp_style_read_icolor(color, str, NULL,NULL);
-}
-
-
-/**
- * Set SPIPaint object from string containing an integer value.
- * \param document Ignored
- */
-static void
-sp_style_read_icolor(SPIPaint *paint, gchar const *str, SPStyle *style, SPDocument *document)
-{
- (void)style; // TODO
- (void)document; // TODO
- paint->currentcolor = FALSE; /* currentColor not a valid <color>. */
- if (!strcmp(str, "inherit")) {
- paint->set = TRUE;
- paint->inherit = TRUE;
- } else {
- paint->inherit = FALSE;
- guint32 const rgb0 = sp_svg_read_color(str, 0xff);
- if (rgb0 != 0xff) {
- paint->setColor(rgb0);
- paint->set = TRUE;
- }
- }
-}
-
-
-/**
- * Set SPIPaint object from string.
- *
- * \pre paint == \&style.fill || paint == \&style.stroke.
- */
-void SPIPaint::read( gchar const *str, SPStyle &style, SPDocument *document )
-{
- while (g_ascii_isspace(*str)) {
- ++str;
- }
-
- clear();
-
- if (streq(str, "inherit")) {
- set = TRUE;
- inherit = TRUE;
- } else {
- if ( strneq(str, "url", 3) ) {
- gchar *uri = extract_uri( str, &str );
- while ( g_ascii_isspace(*str) ) {
- ++str;
- }
- // TODO check on and comment the comparrison "paint != &style->color".
- if ( uri && *uri && (this != &style.color) ) {
- set = TRUE;
-
- // it may be that this style's SPIPaint has not yet created its URIReference;
- // now that we have a document, we can create it here
- if (!value.href && document) {
- value.href = new SPPaintServerReference(document);
- value.href->changedSignal().connect(sigc::bind(sigc::ptr_fun((this == &style.fill)? sp_style_fill_paint_server_ref_changed : sp_style_stroke_paint_server_ref_changed), &style));
- }
-
- // TODO check what this does in light of move away from union
- sp_style_set_ipaint_to_uri_string (&style, this, uri);
- }
- g_free( uri );
- }
-
- if (streq(str, "currentColor") && (this != &style.color)) {
- set = TRUE;
- currentcolor = TRUE;
- } else if (streq(str, "none") && (this != &style.color)) {
- set = TRUE;
- noneSet = TRUE;
- } else {
- guint32 const rgb0 = sp_svg_read_color(str, &str, 0xff);
- if (rgb0 != 0xff) {
- setColor( rgb0 );
- set = TRUE;
-
- while (g_ascii_isspace(*str)) {
- ++str;
- }
- if (strneq(str, "icc-color(", 10)) {
- SVGICCColor* tmp = new SVGICCColor();
- if ( ! sp_svg_read_icc_color( str, &str, tmp ) ) {
- delete tmp;
- tmp = 0;
- }
- value.color.icc = tmp;
- }
- }
- }
- }
-}
-
-
-
-/**
- * Set SPIFontSize object from string.
- */
-static void
-sp_style_read_ifontsize(SPIFontSize *val, gchar const *str)
-{
- if (!strcmp(str, "inherit")) {
- val->set = TRUE;
- val->inherit = TRUE;
- } else if ((*str == 'x') || (*str == 's') || (*str == 'm') || (*str == 'l')) {
- // xx-small, x-small, etc.
- for (unsigned i = 0; enum_font_size[i].key; i++) {
- if (!strcmp(str, enum_font_size[i].key)) {
- val->set = TRUE;
- val->inherit = FALSE;
- val->type = SP_FONT_SIZE_LITERAL;
- val->literal = enum_font_size[i].value;
- return;
- }
- }
- /* Invalid */
- return;
- } else {
- SPILength length;
- length.set = FALSE;
- sp_style_read_ilength(&length, str);
- if( length.set ) {
- val->set = TRUE;
- val->inherit = length.inherit;
- val->unit = length.unit;
- val->value = length.value;
- val->computed = length.computed;
- if( val->unit == SP_CSS_UNIT_PERCENT ) {
- val->type = SP_FONT_SIZE_PERCENTAGE;
- } else {
- val->type = SP_FONT_SIZE_LENGTH;
- }
- }
- return;
- }
-}
-
-
-/**
- * Set SPIBaselineShift object from string.
- */
-static void
-sp_style_read_ibaselineshift(SPIBaselineShift *val, gchar const *str)
-{
- if (!strcmp(str, "inherit")) {
- val->set = TRUE;
- val->inherit = TRUE;
- } else if ((*str == 'b') || (*str == 's')) {
- // baseline or sub or super
- for (unsigned i = 0; enum_baseline_shift[i].key; i++) {
- if (!strcmp(str, enum_baseline_shift[i].key)) {
- val->set = TRUE;
- val->inherit = FALSE;
- val->type = SP_BASELINE_SHIFT_LITERAL;
- val->literal = enum_baseline_shift[i].value;
- return;
- }
- }
- /* Invalid */
- return;
- } else {
- SPILength length;
- sp_style_read_ilength(&length, str);
- val->set = length.set;
- val->inherit = length.inherit;
- val->unit = length.unit;
- val->value = length.value;
- val->computed = length.computed;
- if( val->unit == SP_CSS_UNIT_PERCENT ) {
- val->type = SP_BASELINE_SHIFT_PERCENTAGE;
- } else {
- val->type = SP_BASELINE_SHIFT_LENGTH;
- }
- return;
- }
-}
-
-
-/**
- * Set SPIFilter object from string.
- */
-static void
-sp_style_read_ifilter(gchar const *str, SPStyle * style, SPDocument *document)
-{
- SPIFilter *f = &(style->filter);
- /* Try all possible values: inherit, none, uri */
- if (streq(str, "inherit")) {
- f->set = TRUE;
- f->inherit = TRUE;
- if (f->href){
- if (f->href->getObject()){
- f->href->detach();
- }
- }
- } else if(streq(str, "none")) {
- f->set = TRUE;
- f->inherit = FALSE;
- if (f->href){
- if (f->href->getObject()){
- f->href->detach();
- }
- }
- } else if (strneq(str, "url", 3)) {
- char *uri = extract_uri(str);
- if(uri == NULL || uri[0] == '\0') {
- g_warning("Specified filter url is empty");
- f->set = TRUE;
- f->inherit = FALSE;
- return;
- }
- f->set = TRUE;
- f->inherit = FALSE;
- if (f->href){
- if (f->href->getObject()){
- f->href->detach();
- }
- }
-
- // it may be that this style has not yet created its SPFilterReference;
- // now that we have a document, we can create it here
- if (!f->href && document) {
- f->href = new SPFilterReference(document);
- f->href->changedSignal().connect(sigc::bind(sigc::ptr_fun(sp_style_filter_ref_changed), style));
- }
-
- try {
- f->href->attach(Inkscape::URI(uri));
- } catch (Inkscape::BadURIException &e) {
- g_warning("%s", e.what());
- f->href->detach();
- }
- g_free (uri);
-
- } else {
- /* We shouldn't reach this if SVG input is well-formed */
- f->set = FALSE;
- f->inherit = FALSE;
- if (f->href){
- if (f->href->getObject()){
- f->href->detach();
- }
- }
- }
-}
-
-/**
- * Set SPIEnum object from repr attribute.
- */
-static void
-sp_style_read_penum(SPIEnum *val, Inkscape::XML::Node *repr,
- gchar const *key, SPStyleEnum const *dict,
- bool const can_explicitly_inherit)
-{
- gchar const *str = repr->attribute(key);
- if (str) {
- sp_style_read_ienum(val, str, dict, can_explicitly_inherit);
- }
-}
-
-
-
-/**
- * Set SPILength object from repr attribute.
- */
-static void
-sp_style_read_plength(SPILength *val, Inkscape::XML::Node *repr, gchar const *key)
-{
- gchar const *str = repr->attribute(key);
- if (str) {
- sp_style_read_ilength(val, str);
- }
-}
-
-/**
- * Set SPIFontSize object from repr attribute.
- */
-static void
-sp_style_read_pfontsize(SPIFontSize *val, Inkscape::XML::Node *repr, gchar const *key)
-{
- gchar const *str = repr->attribute(key);
- if (str) {
- sp_style_read_ifontsize(val, str);
- }
-}
-
-
-/**
- * Set SPIBaselineShift object from repr attribute.
- */
-static void
-sp_style_read_pbaselineshift(SPIBaselineShift *val, Inkscape::XML::Node *repr, gchar const *key)
-{
- gchar const *str = repr->attribute(key);
- if (str) {
- sp_style_read_ibaselineshift(val, str);
- }
-}
-
-
-/**
- * Set SPIFloat object from repr attribute.
- */
-static void
-sp_style_read_pfloat(SPIFloat *val, Inkscape::XML::Node *repr, gchar const *key)
-{
- gchar const *str = repr->attribute(key);
- if (str) {
- sp_style_read_ifloat(val, str);
- }
-}
-
-
-/**
- * Write SPIFloat object into string.
- */
-static gint
-sp_style_write_ifloat(gchar *p, gint const len, gchar const *const key,
- SPIFloat const *const val, SPIFloat const *const base, guint const flags)
-{
- Inkscape::CSSOStringStream os;
-
- if ((flags & SP_STYLE_FLAG_ALWAYS)
- || ((flags & SP_STYLE_FLAG_IFSET) && val->set)
- || ((flags & SP_STYLE_FLAG_IFDIFF) && val->set
- && (!base->set || (val->value != base->value))))
- {
- if (val->inherit) {
- return g_snprintf(p, len, "%s:inherit;", key);
- } else {
- os << key << ":" << val->value << ";";
- return g_strlcpy(p, os.str().c_str(), len);
- }
- }
- return 0;
-}
-
-
-/**
- * Write SPIScale24 object into string.
- */
-static gint
-sp_style_write_iscale24(gchar *p, gint const len, gchar const *const key,
- SPIScale24 const *const val, SPIScale24 const *const base,
- guint const flags)
-{
- Inkscape::CSSOStringStream os;
-
- if ((flags & SP_STYLE_FLAG_ALWAYS)
- || ((flags & SP_STYLE_FLAG_IFSET) && val->set)
- || ((flags & SP_STYLE_FLAG_IFDIFF) && val->set
- && (!base->set || (val->value != base->value))))
- {
- if (val->inherit) {
- return g_snprintf(p, len, "%s:inherit;", key);
- } else {
- os << key << ":" << SP_SCALE24_TO_FLOAT(val->value) << ";";
- return g_strlcpy(p, os.str().c_str(), len);
- }
- }
- return 0;
-}
-
-
-/**
- * Write SPIEnum object into string.
- */
-static gint
-sp_style_write_ienum(gchar *p, gint const len, gchar const *const key,
- SPStyleEnum const *const dict,
- SPIEnum const *const val, SPIEnum const *const base, guint const flags)
-{
- if ((flags & SP_STYLE_FLAG_ALWAYS)
- || ((flags & SP_STYLE_FLAG_IFSET) && val->set)
- || ((flags & SP_STYLE_FLAG_IFDIFF) && val->set
- && (!base->set || (val->computed != base->computed))))
- {
- if (val->inherit) {
- return g_snprintf(p, len, "%s:inherit;", key);
- }
- for (unsigned i = 0; dict[i].key; i++) {
- if (dict[i].value == static_cast< gint > (val->value) ) {
- return g_snprintf(p, len, "%s:%s;", key, dict[i].key);
- }
- }
- }
- return 0;
-}
-
-
-
-/**
- * Write SPIString object into string.
- */
-static gint
-sp_style_write_istring(gchar *p, gint const len, gchar const *const key,
- SPIString const *const val, SPIString const *const base, guint const flags)
-{
- gint res = 0;
- if ((flags & SP_STYLE_FLAG_ALWAYS)
- || ((flags & SP_STYLE_FLAG_IFSET) && val->set)
- || ((flags & SP_STYLE_FLAG_IFDIFF) && val->set
- && (!base->set || strcmp(val->value, base->value))))
- {
- if (val->inherit) {
- res = g_snprintf(p, len, "%s:inherit;", key);
- } else {
- Glib::ustring val_quoted = css2_escape_quote(val->value);
- if (~val_quoted.empty()) {
- res = g_snprintf(p, len, "%s:%s;", key, val_quoted.c_str());
- }
- }
- }
- return res;
-}
-
-
-/**
- *
- */
-static bool
-sp_length_differ(SPILength const *const a, SPILength const *const b)
-{
- if (a->unit != b->unit) {
- if (a->unit == SP_CSS_UNIT_EM) return true;
- if (a->unit == SP_CSS_UNIT_EX) return true;
- if (a->unit == SP_CSS_UNIT_PERCENT) return true;
- if (b->unit == SP_CSS_UNIT_EM) return true;
- if (b->unit == SP_CSS_UNIT_EX) return true;
- if (b->unit == SP_CSS_UNIT_PERCENT) return true;
- }
-
- return (a->computed != b->computed);
-}
-
-
-
-/**
- * Write SPILength object into string.
- */
-static gint
-sp_style_write_ilength(gchar *p, gint const len, gchar const *const key,
- SPILength const *const val, SPILength const *const base, guint const flags)
-{
- Inkscape::CSSOStringStream os;
-
- if ((flags & SP_STYLE_FLAG_ALWAYS)
- || ((flags & SP_STYLE_FLAG_IFSET) && val->set)
- || ((flags & SP_STYLE_FLAG_IFDIFF) && val->set
- && (!base->set || sp_length_differ(val, base))))
- {
- if (val->inherit) {
- return g_snprintf(p, len, "%s:inherit;", key);
- } else {
- switch (val->unit) {
- case SP_CSS_UNIT_NONE:
- os << key << ":" << val->computed << ";";
- return g_strlcpy(p, os.str().c_str(), len);
- break;
- case SP_CSS_UNIT_PX:
- os << key << ":" << val->computed << "px;";
- return g_strlcpy(p, os.str().c_str(), len);
- break;
- case SP_CSS_UNIT_PT:
- os << key << ":" << Inkscape::Util::Quantity::convert(val->computed, "px", "pt") << "pt;";
- return g_strlcpy(p, os.str().c_str(), len);
- break;
- case SP_CSS_UNIT_PC:
- os << key << ":" << Inkscape::Util::Quantity::convert(val->computed, "px", "pc") << "pc;";
- return g_strlcpy(p, os.str().c_str(), len);
- break;
- case SP_CSS_UNIT_MM:
- os << key << ":" << Inkscape::Util::Quantity::convert(val->computed, "px", "mm") << "mm;";
- return g_strlcpy(p, os.str().c_str(), len);
- break;
- case SP_CSS_UNIT_CM:
- os << key << ":" << Inkscape::Util::Quantity::convert(val->computed, "px", "cm") << "cm;";
- return g_strlcpy(p, os.str().c_str(), len);
- break;
- case SP_CSS_UNIT_IN:
- os << key << ":" << Inkscape::Util::Quantity::convert(val->computed, "px", "in") << "in;";
- return g_strlcpy(p, os.str().c_str(), len);
- break;
- case SP_CSS_UNIT_EM:
- os << key << ":" << val->value << "em;";
- return g_strlcpy(p, os.str().c_str(), len);
- break;
- case SP_CSS_UNIT_EX:
- os << key << ":" << val->value << "ex;";
- return g_strlcpy(p, os.str().c_str(), len);
- break;
- case SP_CSS_UNIT_PERCENT:
- os << key << ":" << (val->value * 100.0) << "%;";
- return g_strlcpy(p, os.str().c_str(), len);
- break;
- default:
- /* Invalid */
- break;
- }
- }
- }
- return 0;
-}
-
-
-/**
- *
- */
-static bool
-sp_lengthornormal_differ(SPILengthOrNormal const *const a, SPILengthOrNormal const *const b)
-{
- if (a->normal != b->normal) return true;
- if (a->normal) return false;
-
- if (a->unit != b->unit) {
- if (a->unit == SP_CSS_UNIT_EM) return true;
- if (a->unit == SP_CSS_UNIT_EX) return true;
- if (a->unit == SP_CSS_UNIT_PERCENT) return true;
- if (b->unit == SP_CSS_UNIT_EM) return true;
- if (b->unit == SP_CSS_UNIT_EX) return true;
- if (b->unit == SP_CSS_UNIT_PERCENT) return true;
- }
-
- return (a->computed != b->computed);
-}
-
-/**
- * Write SPILengthOrNormal object into string.
- */
-static gint
-sp_style_write_ilengthornormal(gchar *p, gint const len, gchar const *const key,
- SPILengthOrNormal const *const val,
- SPILengthOrNormal const *const base,
- guint const flags)
-{
- if ((flags & SP_STYLE_FLAG_ALWAYS)
- || ((flags & SP_STYLE_FLAG_IFSET) && val->set)
- || ((flags & SP_STYLE_FLAG_IFDIFF) && val->set
- && (!base->set || sp_lengthornormal_differ(val, base))))
- {
- if (val->normal) {
- return g_snprintf(p, len, "%s:normal;", key);
- } else {
- SPILength length;
- length.set = val->set;
- length.inherit = val->inherit;
- length.unit = val->unit;
- length.value = val->value;
- length.computed = val->computed;
- return sp_style_write_ilength(p, len, key, &length, NULL, SP_STYLE_FLAG_ALWAYS);
- }
- }
- return 0;
-}
-
-/**
- * Write SPIDashArray object into string.
- */
-static gint
-sp_style_write_idasharray(gchar *p, gint const len, gchar const *const /*key*/,
- SPIDashArray const *const val, SPIDashArray const *const base, guint const flags)
-{
- if ((flags & SP_STYLE_FLAG_ALWAYS)
- || ((flags & SP_STYLE_FLAG_IFSET) && val->set)
- || ((flags & SP_STYLE_FLAG_IFDIFF) && val->set
- && (!base->set || (val->values != base->values))))
- {
- if (val->inherit) {
- return g_snprintf(p, len, "stroke-dasharray:inherit;");
- } else if ( !val->values.empty() ) {
- Inkscape::CSSOStringStream os;
- os << "stroke-dasharray:";
- for (unsigned i = 0; i < val->values.size(); i++) {
- if (i) {
- os << ", ";
- }
- os << val->values[i];
- }
- os << ";";
- return g_strlcpy(p, os.str().c_str(), len);
- } else {
- return g_snprintf(p, len, "stroke-dasharray:none;");
- }
- }
- return 0;
-}
-
-
-/**
- *
- */
-static bool
-sp_textdecorationLine_differ(SPITextDecorationLine const *const a, SPITextDecorationLine const *const b)
-{
- return( (a->underline != b->underline )
- || (a->overline != b->overline )
- || (a->line_through != b->line_through)
- || (a->blink != b->blink )
- );
-}
-
-/**
- *
- */
-static bool
-sp_textdecorationStyle_differ(SPITextDecorationStyle const *const a, SPITextDecorationStyle const *const b)
-{
- return( (a->solid != b->solid )
- || (a->isdouble != b->isdouble )
- || (a->dotted != b->dotted )
- || (a->dashed != b->dashed )
- || (a->wavy != b->wavy )
- );
-}
-
-/**
- *
- */
-static bool
-sp_textdecorationColor_differ(SPIPaint const *const a, SPIPaint const *const b)
-{
- bool status = (a->isPaintserver() == b->isPaintserver()) &&
- (a->colorSet == b->colorSet) &&
- (a->currentcolor == b->currentcolor);
- return(status);
-}
-
-/**
- * Write SPITextDecoration object into string.
- */
-static gint
-sp_style_write_itextdecoration(gchar *p, gint const len, gchar const *const key,
- SPITextDecorationLine const *const line,
- SPITextDecorationStyle const *const style,
- SPIPaint const *const color,
- SPITextDecorationLine const *const baseLine,
- SPITextDecorationStyle const *const baseStyle,
- SPIPaint const *const baseColor,
- guint const flags)
-{
- Inkscape::CSSOStringStream os;
-
- if ( (flags & SP_STYLE_FLAG_ALWAYS)
- || ((flags & SP_STYLE_FLAG_IFSET) && line->set)
- || ((flags & SP_STYLE_FLAG_IFDIFF) && line->set
- && ( !baseLine->set || sp_textdecorationLine_differ(line, baseLine)))
- || ((flags & SP_STYLE_FLAG_IFSET) && style->set)
- || ((flags & SP_STYLE_FLAG_IFDIFF) && style->set
- && ( !baseStyle->set || sp_textdecorationStyle_differ(style, baseStyle)))
- || ((flags & SP_STYLE_FLAG_IFSET) && color->set)
- || ((flags & SP_STYLE_FLAG_IFDIFF) && color->set
- && ( !baseColor->set || sp_textdecorationColor_differ(color, baseColor)))
- ){
- os << key << ":";
- if (line->inherit || style->inherit || color->inherit) {
- os << " inherit";
- }
- else if (line->underline || line->overline || line->line_through || line->blink) {
- if (line->underline) os << " underline";
- if (line->overline) os << " overline";
- if (line->line_through) os << " line-through";
- if (line->blink) os << " blink";
-
- if ( style->solid) os << " solid";
- else if (style->isdouble) os << " double";
- else if (style->dotted) os << " dotted";
- else if (style->dashed) os << " dashed";
- else if (style->wavy) os << " wavy";
- // color, if it is set, otherwise omit it
- if(color->set){
- char color_buf[8];
- sp_svg_write_color(color_buf, sizeof(color_buf), color->value.color.toRGBA32( 0 ));
- os << " ";
- os << color_buf;
- }
- }
- else {
- os << "none";
- }
- os << ";";
- return g_strlcpy(p, os.str().c_str(), len);
- }
- return 0;
-}
-
-/**
- *
- */
-static bool
-sp_paint_differ(SPIPaint const *const a, SPIPaint const *const b)
-{
- if ( (a->isColor() != b->isColor())
- || (a->isPaintserver() != b->isPaintserver())
- || (a->set != b->set)
- || (a->currentcolor != b->currentcolor)
- || (a->inherit!= b->inherit) ) {
- return true;
- }
-
- // TODO refactor to allow for mixed paints (rgb() *and* url(), etc)
-
- if ( a->isPaintserver() ) {
- return (a->value.href == NULL || b->value.href == NULL || a->value.href->getObject() != b->value.href->getObject());
- }
-
- if ( a->isColor() ) {
- return !( (a->value.color == b->value.color)
- && ((a->value.color.icc == b->value.color.icc)
- || (a->value.color.icc && b->value.color.icc
- && (a->value.color.icc->colorProfile == b->value.color.icc->colorProfile)
- && (a->value.color.icc->colors == b->value.color.icc->colors))));
- /* todo: Allow for epsilon differences in iccColor->colors, e.g. changes small enough not to show up
- * in the string representation. */
- }
-
- return false;
-}
-
-
-
-/**
- * Write SPIPaint object into string.
- */
-static gint
-sp_style_write_ipaint(gchar *b, gint const len, gchar const *const key,
- SPIPaint const *const paint, SPIPaint const *const base, guint const flags)
-{
- int retval = 0;
-
- if ((flags & SP_STYLE_FLAG_ALWAYS)
- || ((flags & SP_STYLE_FLAG_IFSET) && paint->set)
- || ((flags & SP_STYLE_FLAG_IFDIFF) && paint->set
- && (!base->set || sp_paint_differ(paint, base))))
- {
- CSSOStringStream css;
-
- if (paint->inherit) {
- css << "inherit";
- } else {
- if ( paint->value.href && paint->value.href->getURI() ) {
- const gchar* uri = paint->value.href->getURI()->toString();
- css << "url(" << uri << ")";
- g_free((void *)uri);
- }
-
- if ( paint->noneSet ) {
- if ( !css.str().empty() ) {
- css << " ";
- }
- css << "none";
- }
-
- if ( paint->currentcolor ) {
- if ( !css.str().empty() ) {
- css << " ";
- }
- css << "currentColor";
- }
-
- if ( paint->colorSet && !paint->currentcolor ) {
- if ( !css.str().empty() ) {
- css << " ";
- }
- char color_buf[8];
- sp_svg_write_color(color_buf, sizeof(color_buf), paint->value.color.toRGBA32( 0 ));
- css << color_buf;
- }
-
- if (paint->value.color.icc && !paint->currentcolor) {
- if ( !css.str().empty() ) {
- css << " ";
- }
- css << "icc-color(" << paint->value.color.icc->colorProfile;
- for (vector<double>::const_iterator i(paint->value.color.icc->colors.begin()),
- iEnd(paint->value.color.icc->colors.end());
- i != iEnd; ++i) {
- css << ", " << *i;
- }
- css << ')';
- }
- }
-
- if ( !css.str().empty() ) {
- retval = g_snprintf( b, len, "%s:%s;", key, css.str().c_str() );
- }
- }
-
- return retval;
-}
-
-
-/**
- *
- */
-static bool
-sp_paint_order_differ(SPIPaintOrder const *const a, SPIPaintOrder const *const b)
-{
- if( (a->set != b->set) ||
- (a->inherit!= b->inherit) ) {
- return true;
- }
-
- // Check this works when paint-order value is 'normal'
- for (unsigned i = 0; i < PAINT_ORDER_LAYERS; ++i ) {
- if( (a->layer[i] != b->layer[i]) ||
- (a->layer_set[i] != b->layer_set[i]) ) {
- return true;
- }
- }
- return false;
-}
-
-
-
-/**
- * Write SPIPaintOrder object into string.
- */
-static gint
-sp_style_write_ipaintorder(gchar *p, gint len, gchar const *key, SPIPaintOrder const *paint_order, SPIPaintOrder const *base, guint flags)
-{
- int retval = 0;
-
- if ((flags & SP_STYLE_FLAG_ALWAYS)
- || ((flags & SP_STYLE_FLAG_IFSET) && paint_order->set)
- || ((flags & SP_STYLE_FLAG_IFDIFF) && paint_order->set
- && (!base->set || sp_paint_order_differ(paint_order, base))))
- {
- CSSOStringStream css;
-
- if (paint_order->inherit) {
- css << "inherit";
- } else {
- for( unsigned i = 0; i < PAINT_ORDER_LAYERS; ++i ) {
- if( paint_order->layer_set[i] == true ) {
- switch (paint_order->layer[i]) {
- case SP_CSS_PAINT_ORDER_NORMAL:
- css << "normal";
- assert( i == 0 );
- break;
- case SP_CSS_PAINT_ORDER_FILL:
- if (i!=0) css << " ";
- css << "fill";
- break;
- case SP_CSS_PAINT_ORDER_STROKE:
- if (i!=0) css << " ";
- css << "stroke";
- break;
- case SP_CSS_PAINT_ORDER_MARKER:
- if (i!=0) css << " ";
- css << "markers";
- break;
- }
- } else {
- break;
- }
- }
- }
-
- if ( !css.str().empty() ) {
- retval = g_snprintf( p, len, "%s:%s;", key, css.str().c_str() );
- }
- }
-
- return retval;
-}
-
-/**
- *
- */
-static bool
-sp_fontsize_differ(SPIFontSize const *const a, SPIFontSize const *const b)
-{
- if (a->type != b->type)
- return true;
- if (a->type == SP_FONT_SIZE_LENGTH) {
- if (a->computed != b->computed)
- return true;
- } else {
- if (a->value != b->value)
- return true;
- }
- return false;
-}
-
-
-/**
- * Write SPIFontSize object into string.
- */
-static gint
-sp_style_write_ifontsize(gchar *p, gint const len, gchar const *key,
- SPIFontSize const *const val, SPIFontSize const *const base,
- guint const flags)
-{
- if ((flags & SP_STYLE_FLAG_ALWAYS)
- || ((flags & SP_STYLE_FLAG_IFSET) && val->set)
- || ((flags & SP_STYLE_FLAG_IFDIFF) && val->set
- && (!base->set || sp_fontsize_differ(val, base))))
- {
- if (val->inherit) {
- return g_snprintf(p, len, "%s:inherit;", key);
- } else if (val->type == SP_FONT_SIZE_LITERAL) {
- for (unsigned i = 0; enum_font_size[i].key; i++) {
- if (enum_font_size[i].value == static_cast< gint > (val->literal) ) {
- return g_snprintf(p, len, "%s:%s;", key, enum_font_size[i].key);
- }
- }
- } else if (val->type == SP_FONT_SIZE_LENGTH) {
- Inkscape::CSSOStringStream os;
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- int unit = prefs->getInt("/options/font/unitType", SP_CSS_UNIT_PT);
- if (prefs->getBool("/options/font/textOutputPx", true)) {
- unit = SP_CSS_UNIT_PX;
- }
- os << key << ":" << sp_style_css_size_px_to_units(val->computed, unit) << sp_style_get_css_unit_string(unit) << ";";
- return g_strlcpy(p, os.str().c_str(), len);
- } else if (val->type == SP_FONT_SIZE_PERCENTAGE) {
- Inkscape::CSSOStringStream os;
- os << key << ":" << (val->value * 100.0) << "%;";
- return g_strlcpy(p, os.str().c_str(), len);
- }
- }
- return 0;
-}
-
-
-/*
- * baseline-shift is relative to parent. The only time it should
- * not be written out is if it is zero (or not set).
- */
-static bool
-sp_baseline_shift_notzero(SPIBaselineShift const *const a )
-{
- if( a->type == SP_BASELINE_SHIFT_LITERAL ) {
- if( a->literal == SP_CSS_BASELINE_SHIFT_BASELINE ) {
- return false;
- }
- } else {
- if( a->value == 0.0 ) {
- return false;
- }
- }
- return true;
-}
-
-/**
- * Write SPIBaselineShift object into string.
- */
-static gint
-sp_style_write_ibaselineshift(gchar *p, gint const len, gchar const *key,
- SPIBaselineShift const *const val, SPIBaselineShift const *const base,
- guint const flags)
-{
- if ((flags & SP_STYLE_FLAG_ALWAYS)
- || ((flags & SP_STYLE_FLAG_IFSET) && val->set)
- || ((flags & SP_STYLE_FLAG_IFDIFF) && val->set
- && (!base->set || sp_baseline_shift_notzero(val) )))
- {
- if (val->inherit) {
- return g_snprintf(p, len, "%s:inherit;", key);
- } else if (val->type == SP_BASELINE_SHIFT_LITERAL) {
- for (unsigned i = 0; enum_baseline_shift[i].key; i++) {
- if (enum_baseline_shift[i].value == static_cast< gint > (val->literal) ) {
- return g_snprintf(p, len, "%s:%s;", key, enum_baseline_shift[i].key);
- }
- }
- } else if (val->type == SP_BASELINE_SHIFT_LENGTH) {
- if( val->unit == SP_CSS_UNIT_EM || val->unit == SP_CSS_UNIT_EX ) {
- Inkscape::CSSOStringStream os;
- os << key << ":" << val->value << (val->unit == SP_CSS_UNIT_EM ? "em;" : "ex;");
- return g_strlcpy(p, os.str().c_str(), len);
- } else {
- Inkscape::CSSOStringStream os;
- os << key << ":" << val->computed << "px;"; // must specify px, see inkscape bug 1221626, mozilla bug 234789
- return g_strlcpy(p, os.str().c_str(), len);
- }
- } else if (val->type == SP_BASELINE_SHIFT_PERCENTAGE) {
- Inkscape::CSSOStringStream os;
- os << key << ":" << (val->value * 100.0) << "%;";
- return g_strlcpy(p, os.str().c_str(), len);
- }
- }
- return 0;
-}
-
-
-
-/**
- * Write SPIFilter object into string.
- */
-static gint
-sp_style_write_ifilter(gchar *p, gint const len, gchar const *key,
- SPIFilter const *const val, SPIFilter const *const base,
- guint const flags)
-{
- (void)base; // TODO
- if ((flags & SP_STYLE_FLAG_ALWAYS)
- || ((flags & SP_STYLE_FLAG_IFSET) && val->set)
- || ((flags & SP_STYLE_FLAG_IFDIFF) && val->set))
- {
- if (val->inherit) {
- return g_snprintf(p, len, "%s:inherit;", key);
- } else if (val->href && val->href->getURI()) {
- gchar *uri = val->href->getURI()->toString();
- gint ret = g_snprintf(p, len, "%s:url(%s);", key, uri);
- g_free(uri);
- return ret;
- }
- }
-
-
- return 0;
-}
-
-SPIPaint::SPIPaint() :
- set(false),
- inherit(0),
- currentcolor(0),
- colorSet(0),
- noneSet(0),
- value()
-{
- value.color.set( 0 );
- value.href = 0;
-}
-
-void SPIPaint::clear()
-{
- set = false;
- inherit = false;
- currentcolor = false;
- colorSet = false;
- noneSet = false;
- value.color.set( 0 );
- if (value.href){
- if (value.href->getObject()){
- value.href->detach();
- }
- }
-}
-
-/**
- * Clear filter object, and disconnect style from paintserver (if present).
- */
-static void
-sp_style_filter_clear(SPStyle *style)
-{
- if (style->filter.href){
- if (style->filter.href->getObject()){
- style->filter.href->detach();
- }
- }
+ return g_strdup( from->write( SP_STYLE_FLAG_IFDIFF, to ).c_str() );
}
@@ -4894,7 +1544,7 @@ sp_style_set_property_url (SPObject *item, gchar const *property, SPObject *link
sp_repr_css_attr_unref(css);
}
-
+// Called in sp-object.cpp
/**
* Clear all style property attributes in object.
*/
@@ -4927,6 +1577,12 @@ sp_style_unset_property_attrs(SPObject *o)
if (style->color_interpolation_filters.set) {
repr->setAttribute("color-interpolation-filters", NULL);
}
+ if (style->solid_color.set) {
+ repr->setAttribute("solid-color", NULL);
+ }
+ if (style->solid_opacity.set) {
+ repr->setAttribute("solid-opacity", NULL);
+ }
if (style->fill.set) {
repr->setAttribute("fill", NULL);
}
@@ -4948,16 +1604,16 @@ sp_style_unset_property_attrs(SPObject *o)
if (style->stroke_linejoin.set) {
repr->setAttribute("stroke-linejoin", NULL);
}
- if (style->marker[SP_MARKER_LOC].set) {
+ if (style->marker.set) {
repr->setAttribute("marker", NULL);
}
- if (style->marker[SP_MARKER_LOC_START].set) {
+ if (style->marker_start.set) {
repr->setAttribute("marker-start", NULL);
}
- if (style->marker[SP_MARKER_LOC_MID].set) {
+ if (style->marker_mid.set) {
repr->setAttribute("marker-mid", NULL);
}
- if (style->marker[SP_MARKER_LOC_END].set) {
+ if (style->marker_end.set) {
repr->setAttribute("marker-end", NULL);
}
if (style->stroke_opacity.set) {
@@ -4972,15 +1628,18 @@ sp_style_unset_property_attrs(SPObject *o)
if (style->paint_order.set) {
repr->setAttribute("paint-order", NULL);
}
- if (style->text_private && style->text->font_specification.set) {
+ if (style->font_specification.set) {
repr->setAttribute("-inkscape-font-specification", NULL);
}
- if (style->text_private && style->text->font_family.set) {
+ if (style->font_family.set) {
repr->setAttribute("font-family", NULL);
}
if (style->text_anchor.set) {
repr->setAttribute("text-anchor", NULL);
}
+ if (style->white_space.set) {
+ repr->setAttribute("white_space", NULL);
+ }
if (style->writing_mode.set) {
repr->setAttribute("writing_mode", NULL);
}
@@ -5025,7 +1684,8 @@ sp_css_attr_from_style(SPStyle const *const style, guint const flags)
return css;
}
-
+// Called in: selection-chemistry.cpp, widgets/stroke-marker-selector.cpp, widgets/stroke-style.cpp,
+// ui/tools/freehand-base.cpp
/**
* \pre object != NULL
* \pre flags in {IFSET, ALWAYS}.
@@ -5042,13 +1702,14 @@ SPCSSAttr *sp_css_attr_from_object(SPObject *object, guint const flags)
return result;
}
+// Called in: selection-chemistry.cpp, ui/dialog/inkscape-preferences.cpp
/**
* Unset any text-related properties
*/
SPCSSAttr *
sp_css_attr_unset_text(SPCSSAttr *css)
{
- sp_repr_css_set_property(css, "font", NULL); // not implemented yet
+ sp_repr_css_set_property(css, "font", NULL);
sp_repr_css_set_property(css, "-inkscape-font-specification", NULL);
sp_repr_css_set_property(css, "font-size", NULL);
sp_repr_css_set_property(css, "font-size-adjust", NULL); // not implemented yet
@@ -5059,7 +1720,6 @@ sp_css_attr_unset_text(SPCSSAttr *css)
sp_repr_css_set_property(css, "font-family", NULL);
sp_repr_css_set_property(css, "text-indent", NULL);
sp_repr_css_set_property(css, "text-align", NULL);
- sp_repr_css_set_property(css, "text-decoration", NULL);
sp_repr_css_set_property(css, "line-height", NULL);
sp_repr_css_set_property(css, "letter-spacing", NULL);
sp_repr_css_set_property(css, "word-spacing", NULL);
@@ -5068,14 +1728,52 @@ sp_css_attr_unset_text(SPCSSAttr *css)
sp_repr_css_set_property(css, "block-progression", NULL);
sp_repr_css_set_property(css, "writing-mode", NULL);
sp_repr_css_set_property(css, "text-anchor", NULL);
+ sp_repr_css_set_property(css, "white-space", NULL);
sp_repr_css_set_property(css, "kerning", NULL); // not implemented yet
sp_repr_css_set_property(css, "dominant-baseline", NULL); // not implemented yet
sp_repr_css_set_property(css, "alignment-baseline", NULL); // not implemented yet
sp_repr_css_set_property(css, "baseline-shift", NULL);
+ sp_repr_css_set_property(css, "text-decoration", NULL);
+ sp_repr_css_set_property(css, "text-decoration-line", NULL);
+ sp_repr_css_set_property(css, "text-decoration-color", NULL);
+ sp_repr_css_set_property(css, "text-decoration-style", NULL);
+
return css;
}
+// ui/dialog/inkscape-preferences.cpp
+/**
+ * Unset properties that should not be set for default tool style.
+ * This list needs to be reviewed.
+ */
+SPCSSAttr *
+sp_css_attr_unset_blacklist(SPCSSAttr *css)
+{
+ sp_repr_css_set_property(css, "color", NULL);
+ sp_repr_css_set_property(css, "clip-rule", NULL);
+ sp_repr_css_set_property(css, "display", NULL);
+ sp_repr_css_set_property(css, "overflow", NULL);
+ sp_repr_css_set_property(css, "visibility", NULL);
+ sp_repr_css_set_property(css, "isolation", NULL);
+ sp_repr_css_set_property(css, "mix-blend-mode", NULL);
+ sp_repr_css_set_property(css, "color-interpolation", NULL);
+ sp_repr_css_set_property(css, "color-interpolation-filters", NULL);
+ sp_repr_css_set_property(css, "solid-color", NULL);
+ sp_repr_css_set_property(css, "solid-opacity", NULL);
+ sp_repr_css_set_property(css, "fill-rule", NULL);
+ sp_repr_css_set_property(css, "filter-blend-mode", NULL);
+ sp_repr_css_set_property(css, "filter-gaussianBlur-deviation", NULL);
+ sp_repr_css_set_property(css, "color-rendering", NULL);
+ sp_repr_css_set_property(css, "image-rendering", NULL);
+ sp_repr_css_set_property(css, "shape-rendering", NULL);
+ sp_repr_css_set_property(css, "text-rendering", NULL);
+ sp_repr_css_set_property(css, "enable-background", NULL);
+
+ return css;
+}
+
+// Called in style.cpp
static bool
is_url(char const *p)
{
@@ -5088,6 +1786,7 @@ is_url(char const *p)
return (g_ascii_strncasecmp(p, "url(", 4) == 0);
}
+// Called in: ui/dialog/inkscape-preferences.cpp, ui/tools/tweek-tool.cpp
/**
* Unset any properties that contain URI values.
*
@@ -5113,6 +1812,7 @@ sp_css_attr_unset_uris(SPCSSAttr *css)
return css;
}
+// Called in style.cpp
/**
* Scale a single-value property.
*/
@@ -5137,6 +1837,7 @@ sp_css_attr_scale_property_single(SPCSSAttr *css, gchar const *property,
}
}
+// Called in style.cpp for stroke-dasharray
/**
* Scale a list-of-values property.
*/
@@ -5169,6 +1870,7 @@ sp_css_attr_scale_property_list(SPCSSAttr *css, gchar const *property, double ex
}
}
+// Called in: text-editing.cpp,
/**
* Scale any properties that may hold <length> by ex.
*/
@@ -5190,79 +1892,97 @@ sp_css_attr_scale(SPCSSAttr *css, double ex)
/**
- * Remove quotes and escapes from a string. Returned value must be g_free'd.
- * Note: in CSS (in style= and in stylesheets), unquoting and unescaping is done
- * by libcroco, our CSS parser, though it adds a new pair of "" quotes for the strings
- * it parsed for us. So this function is only used to remove those quotes and for
- * presentation attributes, without any unescaping. (XML unescaping
- * (&amp; etc) is done by XML parser.)
+ * Quote and/or escape string for writing to CSS, changing strings in place.
+ * See: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
*/
-gchar *
-attribute_unquote(gchar const *val)
+void
+css_quote(Glib::ustring &val)
{
- if (val) {
- if (*val == '\'' || *val == '"') {
- int l = strlen(val);
- if (l >= 2) {
- if ( ( val[0] == '"' && val[l - 1] == '"' ) ||
- ( val[0] == '\'' && val[l - 1] == '\'' ) ) {
- return (g_strndup (val+1, l-2));
- }
- }
- }
- }
-
- return (val? g_strdup (val) : NULL);
-}
-
-/**
- * Quote and/or escape string for writing to CSS (style=). Returned value must be g_free'd.
- */
-Glib::ustring css2_escape_quote(gchar const *val) {
-
- Glib::ustring t;
+ Glib::ustring out;
bool quote = false;
- bool last_was_space = false;
-
- for (gchar const *i = val; *i; i++) {
- bool is_space = ( *i == ' ' );
- if (g_ascii_isalnum(*i) || *i=='-' || *i=='_') {
- // ASCII alphanumeric, - and _ don't require quotes
- t.push_back(*i);
- } else if ( is_space && !last_was_space ) {
- // non-consecutive spaces don't require quotes
- t.push_back(*i);
- } else if (*i=='\'') {
- // single quotes require escaping and quotes
- t.push_back('\\');
- t.push_back(*i);
+
+ // Can't wait for C++11!
+ for( Glib::ustring::iterator it = val.begin(); it != val.end(); ++it) {
+ if(g_ascii_isalnum(*it) || *it=='-' || *it=='_' || *it > 0xA0) {
+ out += *it;
+ } else if (*it == '\'') {
+ // Single quotes require escaping and quotes.
+ out += '\\';
+ out += *it;
quote = true;
} else {
- // everything else requires quotes
- t.push_back(*i);
+ // Quote everything else including spaces.
+ // (CSS Fonts Level 3 recommends quoting with spaces.)
+ out += *it;
quote = true;
}
- if (i == val && !g_ascii_isalpha(*i)) {
- // a non-ASCII/non-alpha initial character requires quotes
+ if( it == val.begin() && !g_ascii_isalpha(*it) ) {
+ // A non-ASCII/non-alpha initial value on any indentifier needs quotes.
+ // (Actually it's a bit more complicated but as it never hurts to quote...)
quote = true;
}
- last_was_space = is_space;
}
-
- if (last_was_space) {
- // a trailing space requires quotes
- quote = true;
+ if( quote ) {
+ out.insert( out.begin(), '\'' );
+ out += '\'';
}
+ val = out;
+}
- if (quote) {
- // we use single quotes so the result can be stored in an XML
- // attribute without incurring un-aesthetic additional quoting
- // (our XML emitter always uses double quotes)
- t.insert(t.begin(), '\'');
- t.push_back('\'');
+
+/**
+ * Quote font names in font-family lists, changing string in place.
+ * We use unquoted names internally but some need to be quoted in CSS.
+ */
+void
+css_font_family_quote(Glib::ustring &val)
+{
+ std::vector<Glib::ustring> tokens = Glib::Regex::split_simple("\\s*,\\s*", val );
+
+ val.erase();
+ for( unsigned i=0; i < tokens.size(); ++i ) {
+ css_quote( tokens[i] );
+ val += tokens[i] + ", ";
}
+ if( val.size() > 1 )
+ val.erase( val.size() - 2 ); // Remove trailing ", "
+}
+
- return t;
+// Called in style-internal.cpp, xml/repr-css.cpp
+/**
+ * Remove paired single and double quotes from a string, changing string in place.
+ */
+void
+css_unquote(Glib::ustring &val)
+{
+ if( val.size() > 1 &&
+ ( (val[0] == '"' && val[val.size()-1] == '"' ) ||
+ (val[0] == '\'' && val[val.size()-1] == '\'' ) ) ) {
+
+ val.erase( 0, 1 );
+ val.erase( val.size()-1 );
+ }
+}
+
+// Called in style-internal.cpp, text-toolbar.cpp
+/**
+ * Remove paired single and double quotes from font names in font-family lists,
+ * changing string in place.
+ * We use unquoted family names internally but CSS sometimes uses quoted names.
+ */
+void
+css_font_family_unquote(Glib::ustring &val)
+{
+ std::vector<Glib::ustring> tokens = Glib::Regex::split_simple("\\s*,\\s*", val );
+
+ val.erase();
+ for( unsigned i=0; i < tokens.size(); ++i ) {
+ css_unquote( tokens[i] );
+ val += tokens[i] + ", ";
+ }
+ if( val.size() > 1 )
+ val.erase( val.size() - 2 ); // Remove trailing ", "
}
/*
diff --git a/src/style.h b/src/style.h
index 939ace0d3..1b1596458 100644
--- a/src/style.h
+++ b/src/style.h
@@ -7,7 +7,9 @@
/* Authors:
* Lauris Kaplinski <lauris@kaplinski.com>
* Jon A. Cruz <jon@joncruz.org>
+ * Tavmjong Bah <tavmjong@free.fr>
*
+ * Copyright (C) 2014 Tavmjong Bah
* Copyright (C) 2010 Jon A. Cruz
* Copyright (C) 2001-2002 Lauris Kaplinski
* Copyright (C) 2001 Ximian, Inc.
@@ -18,8 +20,15 @@
#include "style-enums.h"
#include "style-internal.h"
-#include <stddef.h>
#include <sigc++/connection.h>
+#include <iostream>
+#include <vector>
+
+// Define SPIBasePtr, a Pointer to a data member of SPStyle of type SPIBase;
+typedef SPIBase SPStyle::*SPIBasePtr;
+
+// Define SPPropMap, a map linking property name to property data
+// typedef std::map<std::string, SPIBasePtr> SPPropMap;
namespace Inkscape {
namespace XML {
@@ -27,24 +36,62 @@ class Node;
}
}
+#include "libcroco/cr-declaration.h"
+#include "libcroco/cr-prop-list.h"
+
/// An SVG style object.
-struct SPStyle {
- int refcount;
+class SPStyle {
+public:
+
+ SPStyle(SPDocument *document = NULL, SPObject *object = NULL);// document is ignored if valid object given
+ ~SPStyle();
+ void clear();
+ void read(SPObject *object, Inkscape::XML::Node *repr);
+ void readFromObject(SPObject *object);
+ void readFromPrefs(Glib::ustring const &path);
+ void readIfUnset( int id, char const *val );
+ Glib::ustring write( unsigned int const flags, SPStyle const *const base = NULL ) const;
+ void cascade( SPStyle const *const parent );
+ void merge( SPStyle const *const parent );
+ bool operator==(const SPStyle& rhs);
+
+ int ref() { ++_refcount; return _refcount; }
+ int unref() { --_refcount; return _refcount; }
+
+//FIXME: Make private
+public:
+ void _mergeString( char const *const p ); // Rename to readFromString?
+private:
+ void _mergeDeclList( CRDeclaration const *const decl_list );
+ void _mergeDecl( CRDeclaration const *const decl );
+ void _mergeProps( CRPropList *const props );
+ void _mergeObjectStylesheet( SPObject const *const object );
+
+private:
+ int _refcount;
+ static int _count; // Poor man's leak detector
+
+// FIXME: Make private
+public:
/** Object we are attached to */
SPObject *object;
/** Document we are associated with */
SPDocument *document;
- /** Our text style component */
- SPTextStyle *text;
- unsigned text_private : 1;
+private:
+ /// Pointers to all the properties (for looping through them)
+ std::vector<SPIBase *> _properties;
+ // static SPPropMap _propmap;
- /* CSS2 */
- /* Font */
- /** Size of the font */
- SPIFontSize font_size;
- /** Style of the font */
+public:
+
+ /* ----------------------- THE PROPERTIES ------------------------- */
+ /* Match order in style.cpp. */
+
+ /* Font ---------------------------- */
+
+ /** Font style */
SPIEnum font_style;
/** Which substyle of the font */
SPIEnum font_variant;
@@ -52,26 +99,24 @@ struct SPStyle {
SPIEnum font_weight;
/** Stretch of the font */
SPIEnum font_stretch;
+ /** Size of the font */
+ SPIFontSize font_size;
+ /** Line height (css2 10.8.1) */
+ SPILengthOrNormal line_height;
+ /** Font family */
+ SPIString font_family;
+ /** Font shorthand */
+ SPIFont font;
+ /** Full font name, as font_factory::ConstructFontSpecification would give, for internal use. */
+ SPIString font_specification;
+
+ /* Text ----------------------------- */
/** First line indent of paragraphs (css2 16.1) */
SPILength text_indent;
/** text alignment (css2 16.2) (not to be confused with text-anchor) */
SPIEnum text_align;
- /** text decoration (css2 16.3.1) is now handled as a subset of css3 2.4 */
- // SPITextDecoration text_decoration;
-
- /** CSS 3 2.1, 2.2, 2.3 */
- /** Not done yet, test_decoration3 = css3 2.4*/
- SPITextDecorationLine text_decoration_line;
- SPIPaint text_decoration_color;
- SPITextDecorationStyle text_decoration_style;
- // used to implement text_decoration, not saved to or read from SVG file
- SPITextDecorationData text_decoration_data;
-
- // 16.3.2 is text-shadow. That's complicated.
- /** Line spacing (css2 10.8.1) */
- SPILengthOrNormal line_height;
/** letter spacing (css2 16.4) */
SPILengthOrNormal letter_spacing;
/** word spacing (also css2 16.4) */
@@ -93,13 +138,24 @@ struct SPStyle {
/** Anchor of the text (svg1.1 10.9.1) */
SPIEnum text_anchor;
- /* Misc attributes */
- unsigned clip_set : 1;
- unsigned color_set : 1;
- unsigned cursor_set : 1;
- unsigned overflow_set : 1;
- unsigned clip_path_set : 1;
- unsigned mask_set : 1;
+ /** white space (svg2) */
+ SPIEnum white_space;
+
+ /* Text Decoration ----------------------- */
+
+ /** text decoration (css2 16.3.1) */
+ SPITextDecoration text_decoration;
+ /** CSS 3 2.1, 2.2, 2.3 */
+ /** Not done yet, test_decoration3 = css3 2.4*/
+ SPITextDecorationLine text_decoration_line;
+ SPITextDecorationStyle text_decoration_style; // SPIEnum? Only one can be set at time.
+ SPIColor text_decoration_color;
+ // used to implement text_decoration, not saved to or read from SVG file
+ SPITextDecorationData text_decoration_data;
+
+ // 16.3.2 is text-shadow. That's complicated.
+
+ /* General visual properties ------------- */
/** clip-rule: 0 nonzero, 1 evenodd */
SPIEnum clip_rule;
@@ -118,16 +174,22 @@ struct SPStyle {
/** mix-blend-mode: CSS Compositing and Blending Level 1 */
SPIEnum isolation;
- // Could be shared with Filter blending mode
- SPIEnum blend_mode;
+ SPIEnum mix_blend_mode;
+
+ SPIPaintOrder paint_order;
/** color */
- SPIPaint color;
+ SPIColor color;
/** color-interpolation */
SPIEnum color_interpolation;
/** color-interpolation-filters */
SPIEnum color_interpolation_filters;
+ /** solid-color */
+ SPIColor solid_color;
+ /** solid-opacity */
+ SPIScale24 solid_opacity;
+
/** fill */
SPIPaint fill;
/** fill-opacity */
@@ -153,18 +215,25 @@ struct SPStyle {
SPIScale24 stroke_opacity;
/** Marker list */
- SPIString marker[SP_MARKER_LOC_QTY];
+ SPIString marker;
+ SPIString marker_start;
+ SPIString marker_mid;
+ SPIString marker_end;
+ SPIString* marker_ptrs[SP_MARKER_LOC_QTY];
- SPIPaintOrder paint_order;
+ /* Filter effects ------------------------ */
/** Filter effect */
SPIFilter filter;
-
+ /** Filter blend mode */
SPIEnum filter_blend_mode;
-
- /** normally not used, but duplicates the Gaussian blur deviation (if any) from the attached
+ /** normally not used, but duplicates the Gaussian blur deviation (if any) from the attached
filter when the style is used for querying */
SPILength filter_gaussianBlur_deviation;
+ /** enable-background, used for defining where filter effects get their background image */
+ SPIEnum enable_background;
+
+ /* Rendering hints ----------------------- */
/** hints on how to render: e.g. speed vs. accuracy.
* As of April, 2013, only image_rendering used. */
@@ -173,9 +242,7 @@ struct SPStyle {
SPIEnum shape_rendering;
SPIEnum text_rendering;
- /** enable-background, used for defining where filter effects get
- * their background image */
- SPIEnum enable_background;
+ /* ----------------------- END PROPERTIES ------------------------- */
/// style belongs to a cloned object
bool cloned;
@@ -185,61 +252,82 @@ struct SPStyle {
sigc::connection filter_modified_connection;
sigc::connection fill_ps_modified_connection;
sigc::connection stroke_ps_modified_connection;
-
- SPObject *getFilter() { return (filter.href) ? filter.href->getObject() : NULL; }
- SPObject const *getFilter() const { return (filter.href) ? filter.href->getObject() : NULL; }
- gchar const *getFilterURI() const { return (filter.href) ? filter.href->getURI()->toString() : NULL; }
-
- SPPaintServer *getFillPaintServer() { return (fill.value.href) ? fill.value.href->getObject() : NULL; }
- SPPaintServer const *getFillPaintServer() const { return (fill.value.href) ? fill.value.href->getObject() : NULL; }
- gchar const *getFillURI() const { return (fill.value.href) ? fill.value.href->getURI()->toString() : NULL; }
-
- SPPaintServer *getStrokePaintServer() { return (stroke.value.href) ? stroke.value.href->getObject() : NULL; }
+ sigc::connection fill_ps_changed_connection;
+ sigc::connection stroke_ps_changed_connection;
+
+ /**
+ * Emitted when paint server object, fill paint refers to, is changed. That is
+ * when the reference starts pointing to a different address in memory.
+ *
+ * NB It is different from fill_ps_modified signal. When paint server is modified
+ * it means some of it's attributes or chilren change.
+ */
+ sigc::signal<void, SPObject *, SPObject *> signal_fill_ps_changed;
+ /**
+ * Emitted when paint server object, fill paint refers to, is changed. That is
+ * when the reference starts pointing to a different address in memory.
+ */
+ sigc::signal<void, SPObject *, SPObject *> signal_stroke_ps_changed;
+
+ SPObject *getFilter() { return (filter.href) ? filter.href->getObject() : NULL; }
+ SPObject const *getFilter() const { return (filter.href) ? filter.href->getObject() : NULL; }
+ char const *getFilterURI() const { return (filter.href) ? filter.href->getURI()->toString() : NULL; }
+
+ SPPaintServer *getFillPaintServer() { return (fill.value.href) ? fill.value.href->getObject() : NULL; }
+ SPPaintServer const *getFillPaintServer() const { return (fill.value.href) ? fill.value.href->getObject() : NULL; }
+ char const *getFillURI() const { return (fill.value.href) ? fill.value.href->getURI()->toString() : NULL; }
+
+ SPPaintServer *getStrokePaintServer() { return (stroke.value.href) ? stroke.value.href->getObject() : NULL; }
SPPaintServer const *getStrokePaintServer() const { return (stroke.value.href) ? stroke.value.href->getObject() : NULL; }
- gchar const *getStrokeURI() const { return (stroke.value.href) ? stroke.value.href->getURI()->toString() : NULL; }
+ char const *getStrokeURI() const { return (stroke.value.href) ? stroke.value.href->getURI()->toString() : NULL; }
};
-SPStyle *sp_style_new(SPDocument *document);
+SPStyle *sp_style_new(SPDocument *document); // SPStyle::SPStyle( SPDocument *document = NULL );
-SPStyle *sp_style_new_from_object(SPObject *object);
+SPStyle *sp_style_new_from_object(SPObject *object); // SPStyle::SPStyle( SPObject *object );
-SPStyle *sp_style_ref(SPStyle *style);
+SPStyle *sp_style_ref(SPStyle *style); // SPStyle::ref();
-SPStyle *sp_style_unref(SPStyle *style);
+SPStyle *sp_style_unref(SPStyle *style); // SPStyle::unref();
-void sp_style_read_from_object(SPStyle *style, SPObject *object);
+void sp_style_read_from_object(SPStyle *style, SPObject *object); //SPStyle::read( SPObject * object);
-void sp_style_read_from_prefs(SPStyle *style, Glib::ustring const &path);
+void sp_style_read_from_prefs(SPStyle *style, Glib::ustring const &path); // SPStyle::read( ... );
-void sp_style_merge_from_style_string(SPStyle *style, gchar const *p);
+void sp_style_merge_from_style_string(SPStyle *style, char const *p); // SPStyle::merge( ... );?
-void sp_style_merge_from_parent(SPStyle *style, SPStyle const *parent);
+void sp_style_merge_from_parent(SPStyle *style, SPStyle const *parent); // SPStyle::cascade( ... );
-void sp_style_merge_from_dying_parent(SPStyle *style, SPStyle const *parent);
+void sp_style_merge_from_dying_parent(SPStyle *style, SPStyle const *parent); // SPStyle::merge( ... )
-gchar *sp_style_write_string(SPStyle const *style, guint flags = SP_STYLE_FLAG_IFSET);
+char *sp_style_write_string(SPStyle const *style, unsigned int flags = SP_STYLE_FLAG_IFSET);//SPStyle::write
-gchar *sp_style_write_difference(SPStyle const *from, SPStyle const *to);
+char *sp_style_write_difference(SPStyle const *from, SPStyle const *to); // SPStyle::write
-void sp_style_set_to_uri_string (SPStyle *style, bool isfill, const gchar *uri);
+void sp_style_set_to_uri_string (SPStyle *style, bool isfill, const char *uri); // ?
-gchar const *sp_style_get_css_unit_string(int unit);
-double sp_style_css_size_px_to_units(double size, int unit);
-double sp_style_css_size_units_to_px(double size, int unit);
+char const *sp_style_get_css_unit_string(int unit); // No change?
+double sp_style_css_size_px_to_units(double size, int unit); // No change?
+double sp_style_css_size_units_to_px(double size, int unit); // No change?
-SPCSSAttr *sp_css_attr_from_style (SPStyle const *const style, guint flags);
-SPCSSAttr *sp_css_attr_from_object(SPObject *object, guint flags = SP_STYLE_FLAG_IFSET);
+SPCSSAttr *sp_css_attr_from_style (SPStyle const *const style, unsigned int flags);
+SPCSSAttr *sp_css_attr_from_object(SPObject *object, unsigned int flags = SP_STYLE_FLAG_IFSET);
SPCSSAttr *sp_css_attr_unset_text(SPCSSAttr *css);
+SPCSSAttr *sp_css_attr_unset_blacklist(SPCSSAttr *css);
SPCSSAttr *sp_css_attr_unset_uris(SPCSSAttr *css);
SPCSSAttr *sp_css_attr_scale(SPCSSAttr *css, double ex);
void sp_style_unset_property_attrs(SPObject *o);
-void sp_style_set_property_url (SPObject *item, gchar const *property, SPObject *linked, bool recursive);
+void sp_style_set_property_url (SPObject *item, char const *property, SPObject *linked, bool recursive);
+
+void css_quote( Glib::ustring &val ); // Add quotes around CSS values
+void css_unquote( Glib::ustring &val ); // Remove quotes from CSS values (style-internal.cpp, xml/repr-css.cpp)
+void css_font_family_quote( Glib::ustring &val ); // style-internal.cpp, text-toolbar.cpp
+void css_font_family_unquote( Glib::ustring &val ); // style-internal.cpp, text-toolbar.cpp
-gchar *attribute_unquote(gchar const *val);
-Glib::ustring css2_escape_quote(gchar const *val);
+Glib::ustring css2_escape_quote(char const *val);
#endif // SEEN_SP_STYLE_H
@@ -254,3 +342,4 @@ Glib::ustring css2_escape_quote(gchar const *val);
End:
*/
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
+
diff --git a/src/svg-view-widget.cpp b/src/svg-view-widget.cpp
index 567156fec..c568d3ca7 100644
--- a/src/svg-view-widget.cpp
+++ b/src/svg-view-widget.cpp
@@ -14,7 +14,6 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include <gtk/gtk.h>
#include "display/sp-canvas.h"
#include "display/sp-canvas-group.h"
#include "display/canvas-arena.h"
@@ -23,8 +22,6 @@
#include "svg-view-widget.h"
#include "util/units.h"
-static void sp_svg_view_widget_class_init (SPSVGSPViewWidgetClass *klass);
-static void sp_svg_view_widget_init (SPSVGSPViewWidget *widget);
static void sp_svg_view_widget_dispose(GObject *object);
static void sp_svg_view_widget_size_allocate (GtkWidget *widget, GtkAllocation *allocation);
@@ -42,28 +39,7 @@ static void sp_svg_view_widget_get_preferred_height(GtkWidget *widget,
static void sp_svg_view_widget_view_resized (SPViewWidget *vw, Inkscape::UI::View::View *view, gdouble width, gdouble height);
-static SPViewWidgetClass *widget_parent_class;
-
-GType sp_svg_view_widget_get_type(void)
-{
- static GType type = 0;
- if (!type) {
- GTypeInfo info = {
- sizeof(SPSVGSPViewWidgetClass),
- 0, // base_init
- 0, // base_finalize
- (GClassInitFunc)sp_svg_view_widget_class_init,
- 0, // class_finalize
- 0, // class_data
- sizeof(SPSVGSPViewWidget),
- 0, // n_preallocs
- (GInstanceInitFunc)sp_svg_view_widget_init,
- 0 // value_table
- };
- type = g_type_register_static(SP_TYPE_VIEW_WIDGET, "SPSVGSPViewWidget", &info, static_cast<GTypeFlags>(0));
- }
- return type;
-}
+G_DEFINE_TYPE(SPSVGSPViewWidget, sp_svg_view_widget, SP_TYPE_VIEW_WIDGET);
/**
* Callback to initialize SPSVGSPViewWidget vtable.
@@ -74,8 +50,6 @@ static void sp_svg_view_widget_class_init(SPSVGSPViewWidgetClass *klass)
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
SPViewWidgetClass *vw_class = SP_VIEW_WIDGET_CLASS (klass);
- widget_parent_class = static_cast<SPViewWidgetClass *>(g_type_class_peek_parent (klass));
-
object_class->dispose = sp_svg_view_widget_dispose;
widget_class->size_allocate = sp_svg_view_widget_size_allocate;
@@ -94,7 +68,6 @@ static void sp_svg_view_widget_class_init(SPSVGSPViewWidgetClass *klass)
*/
static void sp_svg_view_widget_init(SPSVGSPViewWidget *vw)
{
- GtkStyle *style;
SPCanvasItem *parent;
/* Settings */
@@ -117,14 +90,22 @@ static void sp_svg_view_widget_init(SPSVGSPViewWidget *vw)
vw->canvas = SPCanvas::createAA();
-#if !GTK_CHECK_VERSION(3,0,0)
+#if GTK_CHECK_VERSION(3,0,0)
+ GdkRGBA white = {1,1,1,0};
+ gtk_widget_override_background_color(vw->canvas, GTK_STATE_FLAG_NORMAL, &white);
+#else
gtk_widget_pop_colormap ();
-#endif
-
- style = gtk_style_copy (gtk_widget_get_style (vw->canvas));
+ GtkStyle *style = gtk_style_copy (gtk_widget_get_style (vw->canvas));
style->bg[GTK_STATE_NORMAL] = style->white;
gtk_widget_set_style (vw->canvas, style);
+#endif
+
+#if GTK_CHECK_VERSION(3,8,0)
+ gtk_container_add (GTK_CONTAINER (vw->sw), vw->canvas);
+#else
gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (vw->sw), vw->canvas);
+#endif
+
gtk_widget_show (vw->canvas);
/* View */
@@ -142,8 +123,8 @@ static void sp_svg_view_widget_dispose(GObject *object)
vw->canvas = NULL;
- if (((GObjectClass *) (widget_parent_class))->dispose) {
- (* ((GObjectClass *) (widget_parent_class))->dispose) (object);
+ if (G_OBJECT_CLASS(sp_svg_view_widget_parent_class)->dispose) {
+ G_OBJECT_CLASS(sp_svg_view_widget_parent_class)->dispose(object);
}
}
@@ -156,17 +137,18 @@ static void sp_svg_view_widget_size_request(GtkWidget *widget, GtkRequisition *r
Inkscape::UI::View::View *v = SP_VIEW_WIDGET_VIEW (widget);
#if GTK_CHECK_VERSION(3,0,0)
- if (((GtkWidgetClass *) (widget_parent_class))->get_preferred_width && ((GtkWidgetClass *) (widget_parent_class))->get_preferred_width) {
+ if (GTK_WIDGET_CLASS(sp_svg_view_widget_parent_class)->get_preferred_width &&
+ GTK_WIDGET_CLASS(sp_svg_view_widget_parent_class)->get_preferred_height) {
gint width_min, height_min, width_nat, height_nat;
- (* ((GtkWidgetClass *) (widget_parent_class))->get_preferred_width) (widget, &width_min, &width_nat);
- (* ((GtkWidgetClass *) (widget_parent_class))->get_preferred_height) (widget, &height_min, &height_nat);
+ GTK_WIDGET_CLASS(sp_svg_view_widget_parent_class)->get_preferred_width(widget, &width_min, &width_nat);
+ GTK_WIDGET_CLASS(sp_svg_view_widget_parent_class)->get_preferred_height(widget, &height_min, &height_nat);
req->width=width_min;
req->height=height_min;
}
#else
- if (((GtkWidgetClass *) (widget_parent_class))->size_request) {
- (* ((GtkWidgetClass *) (widget_parent_class))->size_request) (widget, req);
+ if (GTK_WIDGET_CLASS(sp_svg_view_widget_parent_class)->size_request) {
+ GTK_WIDGET_CLASS(sp_svg_view_widget_parent_class)->size_request(widget, req);
}
#endif
@@ -220,8 +202,8 @@ static void sp_svg_view_widget_size_allocate(GtkWidget *widget, GtkAllocation *a
{
SPSVGSPViewWidget *svgvw = SP_SVG_VIEW_WIDGET (widget);
- if (((GtkWidgetClass *) (widget_parent_class))->size_allocate) {
- (* ((GtkWidgetClass *) (widget_parent_class))->size_allocate) (widget, allocation);
+ if (GTK_WIDGET_CLASS(sp_svg_view_widget_parent_class)->size_allocate) {
+ GTK_WIDGET_CLASS(sp_svg_view_widget_parent_class)->size_allocate(widget, allocation);
}
if (!svgvw->resize) {
diff --git a/src/svg-view-widget.h b/src/svg-view-widget.h
index eab5be75b..34c70f396 100644
--- a/src/svg-view-widget.h
+++ b/src/svg-view-widget.h
@@ -44,7 +44,7 @@ public:
/// Whether to resize automatically
bool resize;
- gdouble maxwidth, maxheight;
+ double maxwidth, maxheight;
// C++ Wrappers
diff --git a/src/svg-view.h b/src/svg-view.h
index 89f38ad34..bd6fd683a 100644
--- a/src/svg-view.h
+++ b/src/svg-view.h
@@ -16,7 +16,6 @@
struct SPCanvasGroup;
struct SPCanvasItem;
-
/**
* Generic SVG view.
*/
@@ -25,12 +24,12 @@ public:
unsigned int _dkey;
SPCanvasGroup *_parent;
SPCanvasItem *_drawing;
- gdouble _hscale; ///< horizontal scale
- gdouble _vscale; ///< vertical scale
+ double _hscale; ///< horizontal scale
+ double _vscale; ///< vertical scale
bool _rescale; ///< whether to rescale automatically
bool _keepaspect;
- gdouble _width;
- gdouble _height;
+ double _width;
+ double _height;
/**
@@ -43,12 +42,12 @@ public:
/**
* Rescales SPSVGView to given proportions.
*/
- void setScale(gdouble hscale, gdouble vscale);
+ void setScale(double hscale, double vscale);
/**
* Rescales SPSVGView and keeps aspect ratio.
*/
- void setRescale(bool rescale, bool keepaspect, gdouble width, gdouble height);
+ void setRescale(bool rescale, bool keepaspect, double width, double height);
/**
* Helper function that sets rescale ratio and emits resize event.
diff --git a/src/svg/CMakeLists.txt b/src/svg/CMakeLists.txt
index 968287895..f9d0bc52d 100644
--- a/src/svg/CMakeLists.txt
+++ b/src/svg/CMakeLists.txt
@@ -7,6 +7,7 @@ set(svg_SRC
strip-trailing-zeros.cpp
svg-affine.cpp
svg-color.cpp
+ svg-angle.cpp
svg-length.cpp
svg-path.cpp
# test-stubs.cpp
@@ -24,6 +25,7 @@ set(svg_SRC
svg-color-test.h
svg-color.h
svg-icc-color.h
+ svg-angle.h
svg-length-test.h
svg-length.h
svg-path-geom-test.h
diff --git a/src/svg/Makefile_insert b/src/svg/Makefile_insert
index cf9bf3fbb..4f82bdd76 100644
--- a/src/svg/Makefile_insert
+++ b/src/svg/Makefile_insert
@@ -13,6 +13,8 @@ ink_common_sources += \
svg/svg-color.cpp \
svg/svg-color.h \
svg/svg-icc-color.h \
+ svg/svg-angle.cpp \
+ svg/svg-angle.h \
svg/svg-length.cpp \
svg/svg-length.h \
svg/svg-path.cpp \
diff --git a/src/svg/css-ostringstream.h b/src/svg/css-ostringstream.h
index 8cedb0979..2c66dff16 100644
--- a/src/svg/css-ostringstream.h
+++ b/src/svg/css-ostringstream.h
@@ -1,7 +1,6 @@
#ifndef SVG_CSS_OSTRINGSTREAM_H_INKSCAPE
#define SVG_CSS_OSTRINGSTREAM_H_INKSCAPE
-#include <glib.h>
#include <sstream>
namespace Inkscape {
@@ -42,8 +41,8 @@ public:
#undef INK_CSS_STR_OP
- gchar const *gcharp() const {
- return reinterpret_cast<gchar const *>(ostr.str().c_str());
+ char const *gcharp() const {
+ return ostr.str().c_str();
}
std::string str() const {
diff --git a/src/svg/path-string.h b/src/svg/path-string.h
index 3a891873d..6c7e23017 100644
--- a/src/svg/path-string.h
+++ b/src/svg/path-string.h
@@ -15,10 +15,10 @@
#ifndef SEEN_INKSCAPE_SVG_PATH_STRING_H
#define SEEN_INKSCAPE_SVG_PATH_STRING_H
+#include <2geom/point.h>
+#include <cstdio>
#include <glibmm/ustring.h>
#include <string>
-#include <stdio.h>
-#include <2geom/point.h>
namespace Inkscape {
diff --git a/src/svg/stringstream-test.h b/src/svg/stringstream-test.h
index ce32683f8..305cf6b8d 100644
--- a/src/svg/stringstream-test.h
+++ b/src/svg/stringstream-test.h
@@ -37,9 +37,9 @@ public:
svg_test_float(-0.0625, "-0.0625");
svg_test_float(30.0, "30");
svg_test_float(12345678.0, "12345678");
- svg_test_float(3e9, "3e+09");
- svg_test_float(-3.5e9, "-3.5e+09");
- svg_test_float(32768e9, "3.2768e+13");
+ svg_test_float(3e9, "3e+009");
+ svg_test_float(-3.5e9, "-3.5e+009");
+ svg_test_float(32768e9, "3.2768e+013");
svg_test_float(-10.5, "-10.5");
}
diff --git a/src/svg/stringstream.h b/src/svg/stringstream.h
index d143abee8..c9cfdd601 100644
--- a/src/svg/stringstream.h
+++ b/src/svg/stringstream.h
@@ -1,7 +1,6 @@
#ifndef INKSCAPE_STRINGSTREAM_H
#define INKSCAPE_STRINGSTREAM_H
-#include <glib.h>
#include <sstream>
#include <string>
@@ -41,8 +40,8 @@ public:
#undef INK_SVG_STR_OP
- gchar const *gcharp() const {
- return reinterpret_cast<gchar const *>(ostr.str().c_str());
+ char const *gcharp() const {
+ return ostr.str().c_str();
}
std::string str() const {
diff --git a/src/svg/svg-affine-test.h b/src/svg/svg-affine-test.h
index 11b9012a8..af670a3a8 100644
--- a/src/svg/svg-affine-test.h
+++ b/src/svg/svg-affine-test.h
@@ -34,8 +34,8 @@ private:
static char const * const read_fail_tests[25];
static test_t const write_matrix_tests[2];
static test_t const write_translate_tests[3];
- static test_t const write_scale_tests[2];
- static test_t const write_rotate_tests[2];
+ static test_t const write_scale_tests[3];
+ static test_t const write_rotate_tests[3];
static test_t const write_skew_tests[3];
public:
SvgAffineTest() {
@@ -238,16 +238,18 @@ SvgAffineTest::test_t const SvgAffineTest::write_translate_tests[3] = {
{"translate(1,1)",Geom::Affine(1,0,0,1,1,1)},
{"translate(1)",Geom::Affine(1,0,0,1,1,0)},
{"translate(-1345,0.123)",Geom::Affine(1,0,0,1,-1.345e3,.123)}};
-SvgAffineTest::test_t const SvgAffineTest::write_scale_tests[2] = {
+SvgAffineTest::test_t const SvgAffineTest::write_scale_tests[3] = {
{"scale(0)",Geom::Affine(0,0,0,0,0,0)},
+ {"scale(7)",Geom::Affine(7,0,0,7,0,0)},
{"scale(2,3)",Geom::Affine(2,0,0,3,0,0)}};
-SvgAffineTest::test_t const SvgAffineTest::write_rotate_tests[2] = {
+SvgAffineTest::test_t const SvgAffineTest::write_rotate_tests[3] = {
{"rotate(13)",Geom::Affine(cos(13.*DEGREE),sin(13.*DEGREE),-sin(13.*DEGREE),cos(13.*DEGREE),0,0)},
- {"rotate(-13,7,11)",Geom::Affine(cos(-13.*DEGREE),sin(-13.*DEGREE),-sin(-13.*DEGREE),cos(-13.*DEGREE),(1-cos(-13.*DEGREE))*7+sin(-13.*DEGREE)*11,(1-cos(-13.*DEGREE))*11-sin(-13.*DEGREE)*7)}};
+ {"rotate(-13,7,11)",Geom::Affine(cos(-13.*DEGREE),sin(-13.*DEGREE),-sin(-13.*DEGREE),cos(-13.*DEGREE),(1-cos(-13.*DEGREE))*7+sin(-13.*DEGREE)*11,(1-cos(-13.*DEGREE))*11-sin(-13.*DEGREE)*7)},
+ {"rotate(-34.5,6.7,89)",Geom::Affine(cos(-34.5*DEGREE),sin(-34.5*DEGREE),-sin(-34.5*DEGREE),cos(-34.5*DEGREE),(1-cos(-34.5*DEGREE))*6.7+sin(-34.5*DEGREE)*89,(1-cos(-34.5*DEGREE))*89-sin(-34.5*DEGREE)*6.7)}};
SvgAffineTest::test_t const SvgAffineTest::write_skew_tests[3] = {
{"skewX(30)",Geom::Affine(1,0,tan(30.*DEGREE),1,0,0)},
{"skewX(-30)",Geom::Affine(1,0,tan(-30.*DEGREE),1,0,0)},
- {"skewY(390)",Geom::Affine(1,tan(30.*DEGREE),0,1,0,0)}};
+ {"skewY(30)",Geom::Affine(1,tan(30.*DEGREE),0,1,0,0)}};
/*
Local Variables:
diff --git a/src/svg/svg-affine.cpp b/src/svg/svg-affine.cpp
index 44567a2bd..c853f9930 100644
--- a/src/svg/svg-affine.cpp
+++ b/src/svg/svg-affine.cpp
@@ -162,65 +162,105 @@ sp_svg_transform_write(Geom::Affine const &transform)
int prec = prefs->getInt("/options/svgoutput/numericprecision", 8);
int min_exp = prefs->getInt("/options/svgoutput/minimumexponent", -8);
- /* fixme: We could use t1 * t1 + t2 * t2 here instead */
- if ( Geom::are_near(transform[1], 0.0, e) && Geom::are_near (transform[2], 0.0, e)) {
- if (Geom::are_near (transform[4], 0.0, e) && Geom::are_near (transform[5], 0.0, e)) {
- if (Geom::are_near (transform[0], 1.0, e) && Geom::are_near (transform[3], 1.0, e)) {
- /* We are more or less identity */
- return NULL;
- } else {
- /* We are more or less scale */
- gchar c[256];
- unsigned p = 0;
- strcpy (c + p, "scale(");
- p += 6;
- p += sp_svg_number_write_de( c + p, sizeof(c) - p, transform[0], prec, min_exp );
- c[p++] = ',';
- p += sp_svg_number_write_de( c + p, sizeof(c) - p, transform[3], prec, min_exp );
- c[p++] = ')';
- c[p] = '\000';
- g_assert( p <= sizeof(c) );
- return g_strdup(c);
- }
+ // Special case: when all fields of the affine are zero,
+ // the optimized transformation is scale(0)
+ if (transform[0] == 0 && transform[1] == 0 && transform[2] == 0 &&
+ transform[3] == 0 && transform[4] == 0 && transform[5] == 0)
+ {
+ return g_strdup("scale(0)");
+ }
+
+ // FIXME legacy C code!
+ // the function sp_svg_number_write_de is stopping me from using a proper C++ string
+
+ gchar c[256]; // string buffer
+ unsigned p = 0; // position in the buffer
+
+ if (transform.isIdentity()) {
+ // We are more or less identity, so no transform attribute needed:
+ return NULL;
+ } else if (transform.isScale()) {
+ // We are more or less a uniform scale
+ strcpy (c + p, "scale(");
+ p += 6;
+ p += sp_svg_number_write_de( c + p, sizeof(c) - p, transform[0], prec, min_exp );
+ if (Geom::are_near(transform[0], transform[3], e)) {
+ c[p++] = ')';
+ c[p] = '\000';
} else {
- if (Geom::are_near (transform[0], 1.0, e) && Geom::are_near (transform[3], 1.0, e)) {
- /* We are more or less translate */
- gchar c[256];
- unsigned p = 0;
- strcpy (c + p, "translate(");
- p += 10;
- p += sp_svg_number_write_de( c + p, sizeof(c) - p, transform[4], prec, min_exp );
- c[p++] = ',';
- p += sp_svg_number_write_de( c + p, sizeof(c) - p, transform[5], prec, min_exp );
- c[p++] = ')';
- c[p] = '\000';
- g_assert( p <= sizeof(c) );
- return g_strdup(c);
- } else {
- gchar c[256];
- unsigned p = 0;
- strcpy (c + p, "matrix(");
- p += 7;
- p += sp_svg_number_write_de( c + p, sizeof(c) - p, transform[0], prec, min_exp );
- c[p++] = ',';
- p += sp_svg_number_write_de( c + p, sizeof(c) - p, transform[1], prec, min_exp );
- c[p++] = ',';
- p += sp_svg_number_write_de( c + p, sizeof(c) - p, transform[2], prec, min_exp );
- c[p++] = ',';
- p += sp_svg_number_write_de( c + p, sizeof(c) - p, transform[3], prec, min_exp );
- c[p++] = ',';
- p += sp_svg_number_write_de( c + p, sizeof(c) - p, transform[4], prec, min_exp );
- c[p++] = ',';
- p += sp_svg_number_write_de( c + p, sizeof(c) - p, transform[5], prec, min_exp );
- c[p++] = ')';
- c[p] = '\000';
- g_assert( p <= sizeof(c) );
- return g_strdup(c);
- }
+ c[p++] = ',';
+ p += sp_svg_number_write_de( c + p, sizeof(c) - p, transform[3], prec, min_exp );
+ c[p++] = ')';
+ c[p] = '\000';
}
+ } else if (transform.isTranslation()) {
+ // We are more or less a pure translation
+ strcpy (c + p, "translate(");
+ p += 10;
+ p += sp_svg_number_write_de( c + p, sizeof(c) - p, transform[4], prec, min_exp );
+ if (Geom::are_near(transform[5], 0.0, e)) {
+ c[p++] = ')';
+ c[p] = '\000';
+ } else {
+ c[p++] = ',';
+ p += sp_svg_number_write_de( c + p, sizeof(c) - p, transform[5], prec, min_exp );
+ c[p++] = ')';
+ c[p] = '\000';
+ }
+ } else if (transform.isRotation()) {
+ // We are more or less a pure rotation
+ strcpy(c + p, "rotate(");
+ p += 7;
+
+ double angle = std::atan2(transform[1], transform[0]) * (180 / M_PI);
+ p += sp_svg_number_write_de(c + p, sizeof(c) - p, angle, prec, min_exp);
+
+ c[p++] = ')';
+ c[p] = '\000';
+ } else if (transform.withoutTranslation().isRotation()) {
+ // Solution found by Johan Engelen
+ // Refer to the matrix in svg-affine-test.h
+
+ // We are a rotation about a special axis
+ strcpy(c + p, "rotate(");
+ p += 7;
+
+ double angle = std::atan2(transform[1], transform[0]) * (180 / M_PI);
+ p += sp_svg_number_write_de(c + p, sizeof(c) - p, angle, prec, min_exp);
+ c[p++] = ',';
+
+ Geom::Affine const& m = transform;
+ double tx = (m[2]*m[5]+m[4]-m[4]*m[3]) / (1-m[3]-m[0]+m[0]*m[3]-m[2]*m[1]);
+ p += sp_svg_number_write_de(c + p, sizeof(c) - p, tx, prec, min_exp);
+
+ c[p++] = ',';
+
+ double ty = (m[1]*tx + m[5]) / (1 - m[3]);
+ p += sp_svg_number_write_de(c + p, sizeof(c) - p, ty, prec, min_exp);
+
+ c[p++] = ')';
+ c[p] = '\000';
+ } else if (transform.isHShear()) {
+ // We are more or less a pure skewX
+ strcpy(c + p, "skewX(");
+ p += 6;
+
+ double angle = atan(transform[2]) * (180 / M_PI);
+ p += sp_svg_number_write_de(c + p, sizeof(c) - p, angle, prec, min_exp);
+
+ c[p++] = ')';
+ c[p] = '\000';
+ } else if (transform.isVShear()) {
+ // We are more or less a pure skewY
+ strcpy(c + p, "skewY(");
+ p += 6;
+
+ double angle = atan(transform[1]) * (180 / M_PI);
+ p += sp_svg_number_write_de(c + p, sizeof(c) - p, angle, prec, min_exp);
+
+ c[p++] = ')';
+ c[p] = '\000';
} else {
- gchar c[256];
- unsigned p = 0;
strcpy (c + p, "matrix(");
p += 7;
p += sp_svg_number_write_de( c + p, sizeof(c) - p, transform[0], prec, min_exp );
@@ -236,9 +276,10 @@ sp_svg_transform_write(Geom::Affine const &transform)
p += sp_svg_number_write_de( c + p, sizeof(c) - p, transform[5], prec, min_exp );
c[p++] = ')';
c[p] = '\000';
- g_assert( p <= sizeof(c) );
- return g_strdup(c);
}
+
+ assert(p <= sizeof(c));
+ return g_strdup(c);
}
diff --git a/src/svg/svg-angle.cpp b/src/svg/svg-angle.cpp
new file mode 100644
index 000000000..ed5ccd45e
--- /dev/null
+++ b/src/svg/svg-angle.cpp
@@ -0,0 +1,140 @@
+/**
+ * \file src/svg/svg-angle.cpp
+ * \brief SVG angle type
+ */
+/*
+ * Authors:
+ * Tomasz Boczkowski <penginsbacon@gmail.com>
+ *
+ * Copyright (C) 1999-2002 Lauris Kaplinski
+ * Copyright (C) 2000-2001 Ximian, Inc.
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <cstring>
+#include <string>
+#include <math.h>
+#include <glib.h>
+
+#include "svg.h"
+#include "stringstream.h"
+#include "svg/svg-angle.h"
+#include "util/units.h"
+
+
+static bool sp_svg_angle_read_lff(gchar const *str, SVGAngle::Unit &unit, float &val, float &computed);
+
+SVGAngle::SVGAngle()
+ : _set(false)
+ , unit(NONE)
+ , value(0)
+ , computed(0)
+{
+}
+
+/* Angle */
+
+bool SVGAngle::read(gchar const *str)
+{
+ if (!str) {
+ return false;
+ }
+
+ SVGAngle::Unit u;
+ float v;
+ float c;
+ if (!sp_svg_angle_read_lff(str, u, v, c)) {
+ return false;
+ }
+
+ _set = true;
+ unit = u;
+ value = v;
+ computed = c;
+
+ return true;
+}
+
+void SVGAngle::unset(SVGAngle::Unit u, float v, float c) {
+ _set = false;
+ unit = u;
+ value = v;
+ computed = c;
+}
+
+void SVGAngle::readOrUnset(gchar const *str, Unit u, float v, float c) {
+ if (!read(str)) {
+ unset(u, v, c);
+ }
+}
+
+static bool sp_svg_angle_read_lff(gchar const *str, SVGAngle::Unit &unit, float &val, float &computed)
+{
+ if (!str) {
+ return false;
+ }
+
+ gchar const *e;
+ float const v = g_ascii_strtod(str, (char **) &e);
+ if (e == str) {
+ return false;
+ }
+
+ if (!e[0]) {
+ /* Unitless (defaults to degrees)*/
+ unit = SVGAngle::NONE;
+ val = v;
+ computed = v;
+ return true;
+ } else if (!g_ascii_isalnum(e[0])) {
+ if (g_ascii_isspace(e[0]) && e[1] && g_ascii_isalpha(e[1])) {
+ return false; // spaces between value and unit are not allowed
+ } else {
+ /* Unitless (defaults to degrees)*/
+ unit = SVGAngle::NONE;
+ val = v;
+ computed = v;
+ return true;
+ }
+ } else {
+ if (strncmp(e, "deg", 3) == 0) {
+ unit = SVGAngle::DEG;
+ val = v;
+ computed = v;
+ } else if (strncmp(e, "grad", 4) == 0) {
+ unit = SVGAngle::GRAD;
+ val = v;
+ computed = Inkscape::Util::Quantity::convert(v, "grad", "°");
+ } else if (strncmp(e, "rad", 3) == 0) {
+ unit = SVGAngle::RAD;
+ val = v;
+ computed = Inkscape::Util::Quantity::convert(v, "rad", "°");
+ } else if (strncmp(e, "turn", 4) == 0) {
+ unit = SVGAngle::TURN;
+ val = v;
+ computed = Inkscape::Util::Quantity::convert(v, "turn", "°");
+ } else {
+ return false;
+ }
+ return true;
+ }
+
+ /* Invalid */
+ return false;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/svg/svg-angle.h b/src/svg/svg-angle.h
new file mode 100644
index 000000000..966491174
--- /dev/null
+++ b/src/svg/svg-angle.h
@@ -0,0 +1,69 @@
+#ifndef SEEN_SP_SVG_ANGLE_H
+#define SEEN_SP_SVG_ANGLE_H
+
+/**
+ * \file src/svg/svg-angle.h
+ * \brief SVG angle type
+ */
+/*
+ * Authors:
+ * Tomasz Boczkowski <penginsbacon@gmail.com>
+ *
+ * Copyright (C) 1999-2002 Lauris Kaplinski
+ * Copyright (C) 2000-2001 Ximian, Inc.
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <glib.h>
+
+class SVGAngle
+{
+public:
+ SVGAngle();
+
+ enum Unit {
+ NONE,
+ DEG,
+ GRAD,
+ RAD,
+ TURN,
+ LAST_UNIT = TURN
+ };
+
+ // The object's value is valid / exists in SVG.
+ bool _set;
+
+ // The unit of value.
+ Unit unit;
+
+ // The value of this SVGAngle as found in the SVG.
+ float value;
+
+ // The value in degrees.
+ float computed;
+
+ float operator=(float v) {
+ _set = true;
+ unit = NONE;
+ value = computed = v;
+ return v;
+ }
+
+ bool read(gchar const *str);
+ void unset(Unit u = NONE, float v = 0, float c = 0);
+ void readOrUnset(gchar const *str, Unit u = NONE, float v = 0, float c = 0);
+};
+
+#endif // SEEN_SP_SVG_ANGLE_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/svg/svg-color.cpp b/src/svg/svg-color.cpp
index 57f542373..c9f22f8a4 100644
--- a/src/svg/svg-color.cpp
+++ b/src/svg/svg-color.cpp
@@ -173,6 +173,7 @@ static SPSVGColor const sp_svg_color_named[] = {
{ 0xDDA0DD, "plum" },
{ 0xB0E0E6, "powderblue" },
{ 0x800080, "purple" },
+ { 0x663399, "rebeccapurple" },
{ 0xFF0000, "red" },
{ 0xBC8F8F, "rosybrown" },
{ 0x4169E1, "royalblue" },
@@ -309,6 +310,59 @@ static guint32 internal_sp_svg_read_color(gchar const *str, gchar const **end_pt
*end_ptr = s;
}
return val;
+ } else if (strneq(str, "hsl(", 4)) {
+
+ gchar *ptr = (gchar *) str + 4;
+
+ gchar *e; // ptr after read
+
+ double h = g_ascii_strtod(ptr, &e); // Read h (0-360)
+ if (ptr == e) return def; // Read failed
+ ptr = e;
+
+ while (*ptr && g_ascii_isspace(*ptr)) ptr += 1; // Remove any white space
+ if (*ptr != ',') return def; // Need comma
+ ptr += 1;
+ while (*ptr && g_ascii_isspace(*ptr)) ptr += 1; // Remove any white space
+
+ double s = g_ascii_strtod(ptr, &e); // Read s (percent)
+ if (ptr == e) return def; // Read failed
+ ptr = e;
+ while (*ptr && g_ascii_isspace(*ptr)) ptr += 1; // Remove any white space
+ if (*ptr != '%') return def; // Need %
+ ptr += 1;
+
+ while (*ptr && g_ascii_isspace(*ptr)) ptr += 1; // Remove any white space
+ if (*ptr != ',') return def; // Need comma
+ ptr += 1;
+ while (*ptr && g_ascii_isspace(*ptr)) ptr += 1; // Remove any white space
+
+ double l = g_ascii_strtod(ptr, &e); // Read l (percent)
+ if (ptr == e) return def; // Read failed
+ ptr = e;
+ while (*ptr && g_ascii_isspace(*ptr)) ptr += 1; // Remove any white space
+ if (*ptr != '%') return def; // Need %
+ ptr += 1;
+
+ if (end_ptr) {
+ *end_ptr = ptr;
+ }
+
+
+ // Normalize to 0..1
+ h /= 360.0;
+ s /= 100.0;
+ l /= 100.0;
+
+ gfloat rgb[3];
+
+ sp_color_hsl_to_rgb_floatv( rgb, h, s, l );
+
+ val = static_cast<guint>(floor(CLAMP(rgb[0], 0.0, 1.0) * 255.9999)) << 24;
+ val |= (static_cast<guint>(floor(CLAMP(rgb[1], 0.0, 1.0) * 255.9999)) << 16);
+ val |= (static_cast<guint>(floor(CLAMP(rgb[2], 0.0, 1.0) * 255.9999)) << 8);
+ return val;
+
} else {
gint i;
if (colors.empty()) {
@@ -457,18 +511,18 @@ sp_svg_create_color_hash()
void icc_color_to_sRGB(SVGICCColor* icc, guchar* r, guchar* g, guchar* b)
{
- guchar color_out[4];
- guchar color_in[4];
if (icc) {
g_message("profile name: %s", icc->colorProfile.c_str());
Inkscape::ColorProfile* prof = SP_ACTIVE_DOCUMENT->profileManager->find(icc->colorProfile.c_str());
if ( prof ) {
+ guchar color_out[4] = {0,0,0,0};
cmsHTRANSFORM trans = prof->getTransfToSRGB8();
if ( trans ) {
std::vector<colorspace::Component> comps = colorspace::getColorSpaceInfo( prof );
size_t count = CMSSystem::getChannelCount( prof );
size_t cap = std::min(count, comps.size());
+ guchar color_in[4];
for (size_t i = 0; i < cap; i++) {
color_in[i] = static_cast<guchar>((((gdouble)icc->colors[i]) * 256.0) * (gdouble)comps[i].scale);
g_message("input[%d]: %d", (int)i, (int)color_in[i]);
diff --git a/src/svg/svg-color.h b/src/svg/svg-color.h
index b8e317e3b..ea0896872 100644
--- a/src/svg/svg-color.h
+++ b/src/svg/svg-color.h
@@ -1,16 +1,15 @@
#ifndef SVG_SVG_COLOR_H_SEEN
#define SVG_SVG_COLOR_H_SEEN
-#include <glib.h>
-
+typedef unsigned int guint32;
struct SVGICCColor;
-guint32 sp_svg_read_color(gchar const *str, unsigned int dfl);
-guint32 sp_svg_read_color(gchar const *str, gchar const **end_ptr, guint32 def);
+guint32 sp_svg_read_color(char const *str, unsigned int dfl);
+guint32 sp_svg_read_color(char const *str, char const **end_ptr, guint32 def);
void sp_svg_write_color(char *buf, unsigned int buflen, unsigned int rgba32);
-bool sp_svg_read_icc_color( gchar const *str, gchar const **end_ptr, SVGICCColor* dest );
-bool sp_svg_read_icc_color( gchar const *str, SVGICCColor* dest );
-void icc_color_to_sRGB(SVGICCColor* dest, guchar* r, guchar* g, guchar* b);
+bool sp_svg_read_icc_color( char const *str, char const **end_ptr, SVGICCColor* dest );
+bool sp_svg_read_icc_color( char const *str, SVGICCColor* dest );
+void icc_color_to_sRGB(SVGICCColor* dest, unsigned char* r, unsigned char* g, unsigned char* b);
#endif /* !SVG_SVG_COLOR_H_SEEN */
diff --git a/src/svg/svg-length-test.h b/src/svg/svg-length-test.h
index 81a28c9e7..796943e45 100644
--- a/src/svg/svg-length-test.h
+++ b/src/svg/svg-length-test.h
@@ -164,13 +164,13 @@ SvgLengthTest::test_t const SvgLengthTest::absolute_tests[12] = {
{"1.00001", SVGLength::NONE, 1.00001 , 1.00001},
{"1px", SVGLength::PX , 1 , 1},
{".1px", SVGLength::PX , 0.1 , 0.1},
- {"100pt", SVGLength::PT , 100 , 125},
- {"1e2pt", SVGLength::PT , 100 , 125},
- {"3pc", SVGLength::PC , 3 , 45},
- {"-3.5pc", SVGLength::PC , -3.5 , -3.5*15.},
- {"1.2345678mm", SVGLength::MM , 1.2345678, 1.2345678*3.543307}, // TODO: More precise constants? (a 7 digit constant when the default precision is 8 digits?)
- {"123.45678cm", SVGLength::CM , 123.45678 , 123.45678*35.43307},
- {"73.162987in", SVGLength::INCH, 73.162987 , 73.162987*90}};
+ {"100pt", SVGLength::PT , 100 , 400.0/3.0},
+ {"1e2pt", SVGLength::PT , 100 , 400.0/3.0},
+ {"3pc", SVGLength::PC , 3 , 48},
+ {"-3.5pc", SVGLength::PC , -3.5 , -3.5*16.0},
+ {"1.2345678mm", SVGLength::MM , 1.2345678, 1.2345678f*96.0/25.4}, // TODO: More precise constants? (a 7 digit constant when the default precision is 8 digits?)
+ {"123.45678cm", SVGLength::CM , 123.45678 , 123.45678f*96.0/2.54}, // Note that svg_length_read is casting the result from g_ascii_strtod to float.
+ {"73.162987in", SVGLength::INCH, 73.162987 , 73.162987f*96.0/1.00}};
SvgLengthTest::test_t const SvgLengthTest::relative_tests[3] = {
{"123em", SVGLength::EM, 123, 123. * 7.},
{"123ex", SVGLength::EX, 123, 123. * 13.},
diff --git a/src/svg/svg-length.cpp b/src/svg/svg-length.cpp
index b9e8e6340..b9b475f4b 100644
--- a/src/svg/svg-length.cpp
+++ b/src/svg/svg-length.cpp
@@ -1,6 +1,4 @@
-#define __SP_SVG_LENGTH_C__
-
-/*
+/**
* SVG data parser
*
* Authors:
@@ -12,20 +10,15 @@
* This code is in public domain
*/
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
+#include <cmath>
#include <cstring>
#include <string>
-#include <math.h>
#include <glib.h>
#include "svg.h"
#include "stringstream.h"
#include "util/units.h"
-
static unsigned sp_svg_length_read_lff(gchar const *str, SVGLength::Unit *unit, float *val, float *computed, char **next);
#ifndef MAX
@@ -570,4 +563,4 @@ void SVGLength::readOrUnset(gchar const *str, Unit u, float v, float c)
fill-column:99
End:
*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8 :
diff --git a/src/svg/svg-length.h b/src/svg/svg-length.h
index 477b3ef81..c34905d07 100644
--- a/src/svg/svg-length.h
+++ b/src/svg/svg-length.h
@@ -1,11 +1,4 @@
-#ifndef SEEN_SP_SVG_LENGTH_H
-#define SEEN_SP_SVG_LENGTH_H
-
/**
- * \file src/svg/svg-length.h
- * \brief SVG length type
- */
-/*
* Authors:
* Lauris Kaplinski <lauris@kaplinski.com>
* Carl Hetherington <inkscape@carlh.net>
@@ -16,10 +9,13 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include <glib.h>
+#ifndef SEEN_SP_SVG_LENGTH_H
+#define SEEN_SP_SVG_LENGTH_H
-class SVGLength
-{
+/**
+ * SVG length type
+ */
+class SVGLength {
public:
SVGLength();
@@ -57,9 +53,9 @@ public:
return v;
}
- bool read(gchar const *str);
- void readOrUnset(gchar const *str, Unit u = NONE, float v = 0, float c = 0);
- bool readAbsolute(gchar const *str);
+ bool read(char const *str);
+ void readOrUnset(char const *str, Unit u = NONE, float v = 0, float c = 0);
+ bool readAbsolute(char const *str);
void set(Unit u, float v, float c);
void unset(Unit u = NONE, float v = 0, float c = 0);
void update(double em, double ex, double scale);
@@ -76,4 +72,4 @@ public:
fill-column:99
End:
*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8 :
diff --git a/src/svg/svg-path.cpp b/src/svg/svg-path.cpp
index 59dad9ead..9ba3c0ebd 100644
--- a/src/svg/svg-path.cpp
+++ b/src/svg/svg-path.cpp
@@ -1,41 +1,25 @@
-#define __SP_SVG_PARSE_C__
/*
- svg-path.c: Parse SVG path element data into bezier path.
-
- Copyright (C) 2000 Eazel, Inc.
- Copyright (C) 2000 Lauris Kaplinski
- Copyright (C) 2001 Ximian, Inc.
- Copyright (C) 2008 Johan Engelen
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public
- License along with this program; if not, write to the
- Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
-
- Authors:
- Johan Engelen
- (old nartbpath code that has been deleted: Raph Levien <raph@artofcode.com>)
- (old nartbpath code that has been deleted: Lauris Kaplinski <lauris@ximian.com>)
-*/
+ * svg-path.cpp: Parse SVG path element data into bezier path.
+ * Authors:
+ * Johan Engelen
+ * (old nartbpath code that has been deleted: Raph Levien <raph@artofcode.com>)
+ * (old nartbpath code that has been deleted: Lauris Kaplinski <lauris@ximian.com>)
+ *
+ * Copyright (C) 2000 Eazel, Inc.
+ * Copyright (C) 2000 Lauris Kaplinski
+ * Copyright (C) 2001 Ximian, Inc.
+ * Copyright (C) 2008 Johan Engelen
+ *
+ * Copyright (C) 2000-2008 authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
#include <cstring>
#include <string>
#include <cassert>
#include <glib.h> // g_assert()
-#include "svg/svg.h"
-#include "svg/path-string.h"
-
#include <2geom/pathvector.h>
#include <2geom/path.h>
#include <2geom/curves.h>
@@ -45,6 +29,9 @@
#include <2geom/exception.h>
#include <2geom/angle.h>
+#include "svg/svg.h"
+#include "svg/path-string.h"
+
/*
* Parses the path in str. When an error is found in the pathstring, this method
* returns a truncated path up to where the error was found in the pathstring.
@@ -150,4 +137,4 @@ gchar * sp_svg_write_path(Geom::Path const &p) {
fill-column:99
End:
*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8 :
diff --git a/src/svg/svg.h b/src/svg/svg.h
index a7795b82e..6ce9db937 100644
--- a/src/svg/svg.h
+++ b/src/svg/svg.h
@@ -11,7 +11,7 @@
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include <glib.h>
+
#include <vector>
#include <cstring>
#include <string>
@@ -28,13 +28,13 @@
* Return FALSE and let val untouched on error
*/
-unsigned int sp_svg_number_read_f( const gchar *str, float *val );
-unsigned int sp_svg_number_read_d( const gchar *str, double *val );
+unsigned int sp_svg_number_read_f( const char *str, float *val );
+unsigned int sp_svg_number_read_d( const char *str, double *val );
/*
* No buffer overflow checking is done, so better wrap them if needed
*/
-unsigned int sp_svg_number_write_de( gchar *buf, int bufLen, double val, unsigned int tprec, int min_exp );
+unsigned int sp_svg_number_write_de( char *buf, int bufLen, double val, unsigned int tprec, int min_exp );
/* Length */
@@ -47,24 +47,24 @@ unsigned int sp_svg_number_write_de( gchar *buf, int bufLen, double val, unsigne
* Any return value pointer can be NULL
*/
-unsigned int sp_svg_length_read_computed_absolute( const gchar *str, float *length );
-std::vector<SVGLength> sp_svg_length_list_read( const gchar *str );
-unsigned int sp_svg_length_read_ldd( const gchar *str, SVGLength::Unit *unit, double *value, double *computed );
+unsigned int sp_svg_length_read_computed_absolute( const char *str, float *length );
+std::vector<SVGLength> sp_svg_length_list_read( const char *str );
+unsigned int sp_svg_length_read_ldd( const char *str, SVGLength::Unit *unit, double *value, double *computed );
std::string sp_svg_length_write_with_units(SVGLength const &length);
-bool sp_svg_transform_read(gchar const *str, Geom::Affine *transform);
+bool sp_svg_transform_read(char const *str, Geom::Affine *transform);
-gchar *sp_svg_transform_write(Geom::Affine const &transform);
-gchar *sp_svg_transform_write(Geom::Affine const *transform);
+char *sp_svg_transform_write(Geom::Affine const &transform);
+char *sp_svg_transform_write(Geom::Affine const *transform);
double sp_svg_read_percentage( const char * str, double def );
/* NB! As paths can be long, we use here dynamic string */
Geom::PathVector sp_svg_read_pathv( char const * str );
-gchar * sp_svg_write_path( Geom::PathVector const &p );
-gchar * sp_svg_write_path( Geom::Path const &p );
+char * sp_svg_write_path( Geom::PathVector const &p );
+char * sp_svg_write_path( Geom::Path const &p );
#endif // SEEN_SP_SVG_H
diff --git a/src/text-chemistry.h b/src/text-chemistry.h
index 1ae0a1779..c983f005f 100644
--- a/src/text-chemistry.h
+++ b/src/text-chemistry.h
@@ -1,6 +1,8 @@
#ifndef SEEN_TEXT_CHEMISTRY_H
#define SEEN_TEXT_CHEMISTRY_H
+// TODO move to selection-chemistry?
+
/*
* Text commands
*
diff --git a/src/text-editing.cpp b/src/text-editing.cpp
index cae123616..47964880c 100644
--- a/src/text-editing.cpp
+++ b/src/text-editing.cpp
@@ -776,7 +776,7 @@ sp_te_delete (SPItem *item, Inkscape::Text::Layout::iterator const &start,
bool has_text_decoration = false;
gchar const *root_style = (item)->getRepr()->attribute("style");
- if(strstr(root_style,"text-decoration"))has_text_decoration = true;
+ if(root_style && strstr(root_style,"text-decoration"))has_text_decoration = true;
if (start_item == end_item) {
// the quick case where we're deleting stuff all from the same string
@@ -2035,7 +2035,7 @@ void sp_te_apply_style(SPItem *text, Inkscape::Text::Layout::iterator const &sta
roundtrippability. */
bool has_text_decoration = false;
gchar const *root_style = (text)->getRepr()->attribute("style");
- if(strstr(root_style,"text-decoration"))has_text_decoration = true;
+ if(root_style && strstr(root_style,"text-decoration")) has_text_decoration = true;
while (tidy_xml_tree_recursively(common_ancestor, has_text_decoration)){};
// if we only modified subobjects this won't have been automatically sent
diff --git a/src/text-editing.h b/src/text-editing.h
index 04ef6461d..3a86bf48e 100644
--- a/src/text-editing.h
+++ b/src/text-editing.h
@@ -13,16 +13,15 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include <glib.h>
#include <utility> // std::pair
#include "libnrtype/Layout-TNG.h"
#include "text-tag-attributes.h"
-class SPCSSAttr;
-class SPDesktop;
-class SPItem;
-class SPObject;
-struct SPStyle;
+class SPCSSAttr;
+class SPDesktop;
+class SPItem;
+class SPObject;
+class SPStyle;
typedef std::pair<Inkscape::Text::Layout::iterator, Inkscape::Text::Layout::iterator> iterator_pair;
@@ -54,14 +53,14 @@ double sp_te_get_average_linespacing (SPItem *text);
SPStyle const * sp_te_style_at_position(SPItem const *text, Inkscape::Text::Layout::iterator const &position);
SPObject const * sp_te_object_at_position(SPItem const *text, Inkscape::Text::Layout::iterator const &position);
-Inkscape::Text::Layout::iterator sp_te_insert(SPItem *item, Inkscape::Text::Layout::iterator const &position, gchar const *utf8);
-Inkscape::Text::Layout::iterator sp_te_replace(SPItem *item, Inkscape::Text::Layout::iterator const &start, Inkscape::Text::Layout::iterator const &end, gchar const *utf8);
+Inkscape::Text::Layout::iterator sp_te_insert(SPItem *item, Inkscape::Text::Layout::iterator const &position, char const *utf8);
+Inkscape::Text::Layout::iterator sp_te_replace(SPItem *item, Inkscape::Text::Layout::iterator const &start, Inkscape::Text::Layout::iterator const &end, char const *utf8);
Inkscape::Text::Layout::iterator sp_te_insert_line (SPItem *text, Inkscape::Text::Layout::iterator const &position);
bool sp_te_delete (SPItem *item, Inkscape::Text::Layout::iterator const &start, Inkscape::Text::Layout::iterator const &end, iterator_pair &iter_pair);
-gchar *sp_te_get_string_multiline(SPItem const *text);
+char *sp_te_get_string_multiline(SPItem const *text);
Glib::ustring sp_te_get_string_multiline(SPItem const *text, Inkscape::Text::Layout::iterator const &start, Inkscape::Text::Layout::iterator const &end);
-void sp_te_set_repr_text_multiline(SPItem *text, gchar const *str);
+void sp_te_set_repr_text_multiline(SPItem *text, char const *str);
TextTagAttributes*
text_tag_attributes_at_position(SPItem *item, Inkscape::Text::Layout::iterator const &position, unsigned *char_index);
@@ -70,12 +69,12 @@ void sp_te_adjust_kerning_screen(SPItem *text, Inkscape::Text::Layout::iterator
void sp_te_adjust_dx (SPItem *item, Inkscape::Text::Layout::iterator const &start, Inkscape::Text::Layout::iterator const &end, SPDesktop *desktop, double delta);
void sp_te_adjust_dy (SPItem *item, Inkscape::Text::Layout::iterator const &start, Inkscape::Text::Layout::iterator const &end, SPDesktop *desktop, double delta);
-void sp_te_adjust_rotation_screen(SPItem *text, Inkscape::Text::Layout::iterator const &start, Inkscape::Text::Layout::iterator const &end, SPDesktop *desktop, gdouble pixels);
-void sp_te_adjust_rotation(SPItem *text, Inkscape::Text::Layout::iterator const &start, Inkscape::Text::Layout::iterator const &end, SPDesktop *desktop, gdouble degrees);
-void sp_te_set_rotation(SPItem *text, Inkscape::Text::Layout::iterator const &start, Inkscape::Text::Layout::iterator const &end, SPDesktop *desktop, gdouble degrees);
+void sp_te_adjust_rotation_screen(SPItem *text, Inkscape::Text::Layout::iterator const &start, Inkscape::Text::Layout::iterator const &end, SPDesktop *desktop, double pixels);
+void sp_te_adjust_rotation(SPItem *text, Inkscape::Text::Layout::iterator const &start, Inkscape::Text::Layout::iterator const &end, SPDesktop *desktop, double degrees);
+void sp_te_set_rotation(SPItem *text, Inkscape::Text::Layout::iterator const &start, Inkscape::Text::Layout::iterator const &end, SPDesktop *desktop, double degrees);
-void sp_te_adjust_tspan_letterspacing_screen(SPItem *text, Inkscape::Text::Layout::iterator const &start, Inkscape::Text::Layout::iterator const &end, SPDesktop *desktop, gdouble by);
-void sp_te_adjust_linespacing_screen(SPItem *text, Inkscape::Text::Layout::iterator const &start, Inkscape::Text::Layout::iterator const &end, SPDesktop *desktop, gdouble by);
+void sp_te_adjust_tspan_letterspacing_screen(SPItem *text, Inkscape::Text::Layout::iterator const &start, Inkscape::Text::Layout::iterator const &end, SPDesktop *desktop, double by);
+void sp_te_adjust_linespacing_screen(SPItem *text, Inkscape::Text::Layout::iterator const &start, Inkscape::Text::Layout::iterator const &end, SPDesktop *desktop, double by);
void sp_te_apply_style(SPItem *text, Inkscape::Text::Layout::iterator const &start, Inkscape::Text::Layout::iterator const &end, SPCSSAttr const *css);
bool is_part_of_text_subtree (SPObject *obj);
diff --git a/src/transf_mat_3x4.cpp b/src/transf_mat_3x4.cpp
index 20eee658c..05d0e9d6d 100644
--- a/src/transf_mat_3x4.cpp
+++ b/src/transf_mat_3x4.cpp
@@ -62,11 +62,9 @@ TransfMat3x4::image (Pt3 const &point) {
Pt3
TransfMat3x4::preimage (Geom::Point const &pt, double coord, Proj::Axis axis) {
- double x[4];
- double v[3];
- v[0] = pt[Geom::X];
- v[1] = pt[Geom::Y];
- v[2] = 1.0;
+ const double init_val = std::numeric_limits<double>::quiet_NaN();
+ double x[4] = { init_val, init_val, init_val, init_val };
+ double v[3] = { pt[Geom::X], pt[Geom::Y], 1.0 };
int index = (int) axis;
SysEq::SolutionKind sol = SysEq::gaussjord_solve<3,4>(tmat, x, v, index, coord, true);
diff --git a/src/transf_mat_3x4.h b/src/transf_mat_3x4.h
index 8542e5e00..7c0c72120 100644
--- a/src/transf_mat_3x4.h
+++ b/src/transf_mat_3x4.h
@@ -35,7 +35,7 @@ public:
return Geom::atan2(Geom::Point(vp[0], vp[1])) * 180.0/M_PI;
}
void set_infinite_direction (Proj::Axis axis, double angle) { // angle is in degrees
- g_return_if_fail(tmat[2][axis] == 0); // don't set directions for finite VPs
+ if (tmat[2][axis] != 0) return; // don't set directions for finite VPs
double a = angle * M_PI/180;
Geom::Point pt(tmat[0][axis], tmat[1][axis]);
@@ -44,7 +44,7 @@ public:
}
inline bool has_finite_image (Proj::Axis axis) { return (tmat[2][axis] != 0.0); }
- gchar * pt_to_str (Proj::Axis axis);
+ char * pt_to_str (Proj::Axis axis);
bool operator==(const TransfMat3x4 &rhs) const;
TransfMat3x4 operator*(Geom::Affine const &A) const;
diff --git a/src/ui/CMakeLists.txt b/src/ui/CMakeLists.txt
index 7d80f1e36..e5c605889 100644
--- a/src/ui/CMakeLists.txt
+++ b/src/ui/CMakeLists.txt
@@ -2,7 +2,13 @@
set(ui_SRC
clipboard.cpp
control-manager.cpp
+ dialog-events.cpp
+ draw-anchor.cpp
+ interface.cpp
+ object-edit.cpp
previewholder.cpp
+ shape-editor.cpp
+ tools-switch.cpp
uxmanager.cpp
cache/svg_preview_cache.cpp
@@ -78,6 +84,7 @@ set(ui_SRC
dialog/layers.cpp
dialog/livepatheffect-add.cpp
dialog/livepatheffect-editor.cpp
+ dialog/lpe-fillet-chamfer-properties.cpp
dialog/memory.cpp
dialog/messages.cpp
dialog/new-from-template.cpp
@@ -89,7 +96,6 @@ set(ui_SRC
dialog/print.cpp
dialog/symbols.cpp
dialog/xml-tree.cpp
- # dialog/session-player.cpp
dialog/spellcheck.cpp
dialog/svg-fonts-dialog.cpp
dialog/swatches.cpp
@@ -101,9 +107,6 @@ set(ui_SRC
dialog/pixelartdialog.cpp
dialog/transformation.cpp
dialog/undo-history.cpp
- # dialog/whiteboard-connect.cpp
- # dialog/whiteboard-sharewithchat.cpp
- # dialog/whiteboard-sharewithuser.cpp
widget/anchor-selector.cpp
widget/button.cpp
@@ -155,10 +158,17 @@ set(ui_SRC
clipboard.h
control-manager.h
control-types.h
+ dialog-events.h
+ draw-anchor.h
icon-names.h
+ interface.h
+ object-edit.h
previewable.h
previewfillable.h
previewholder.h
+ shape-editor.h
+ tool-factory.h
+ tools-switch.h
uxmanager.h
cache/svg_preview_cache.h
@@ -198,6 +208,7 @@ set(ui_SRC
dialog/layers.h
dialog/livepatheffect-add.h
dialog/livepatheffect-editor.h
+ dialog/lpe-fillet-chamfer-properties.h
dialog/memory.h
dialog/messages.h
dialog/new-from-template.h
diff --git a/src/ui/Makefile_insert b/src/ui/Makefile_insert
index 4081f86f8..7aeb4a83d 100644
--- a/src/ui/Makefile_insert
+++ b/src/ui/Makefile_insert
@@ -6,10 +6,23 @@ ink_common_sources += \
ui/control-manager.cpp \
ui/control-manager.h \
ui/control-types.h \
+ ui/dialog-events.cpp \
+ ui/dialog-events.h \
+ ui/draw-anchor.cpp \
+ ui/draw-anchor.h \
ui/icon-names.h \
+ ui/interface.cpp \
+ ui/interface.h \
+ ui/object-edit.cpp \
+ ui/object-edit.h \
ui/previewable.h \
ui/previewfillable.h \
ui/previewholder.cpp \
ui/previewholder.h \
+ ui/shape-editor.cpp \
+ ui/shape-editor.h \
+ ui/tool-factory.h \
+ ui/tools-switch.cpp \
+ ui/tools-switch.h \
ui/uxmanager.cpp \
ui/uxmanager.h
diff --git a/src/ui/clipboard.cpp b/src/ui/clipboard.cpp
index 8e2502545..153ed9830 100644
--- a/src/ui/clipboard.cpp
+++ b/src/ui/clipboard.cpp
@@ -54,6 +54,7 @@
#include <2geom/transforms.h>
#include "box3d.h"
#include "gradient-drag.h"
+#include "sp-marker.h"
#include "sp-item.h"
#include "sp-item-transform.h" // for sp_item_scale_rel, used in _pasteSize
#include "sp-path.h"
@@ -76,7 +77,7 @@
#include "svg/css-ostringstream.h" // used in copy
#include "ui/tools/text-tool.h"
#include "text-editing.h"
-#include "tools-switch.h"
+#include "ui/tools-switch.h"
#include "path-chemistry.h"
#include "util/units.h"
#include "helper/png-write.h"
@@ -329,6 +330,13 @@ void ClipboardManagerImpl::copySymbol(Inkscape::XML::Node* symbol, gchar const*
use->setAttribute("xlink:href", id.c_str() );
// Set a default style in <use> rather than <symbol> so it can be changed.
use->setAttribute("style", style );
+
+ Inkscape::XML::Node *nv_repr = sp_desktop_namedview(inkscape_active_desktop())->getRepr();
+ gdouble scale_units = Inkscape::Util::Quantity::convert(1, nv_repr->attribute("inkscape:document-units"), "px");
+ gchar *transform_str = sp_svg_transform_write(Geom::Scale(scale_units, scale_units));
+ use->setAttribute("transform", transform_str);
+ g_free(transform_str);
+
_root->appendChild(use);
// This min and max sets offsets, we don't have any so set to zero.
@@ -505,12 +513,15 @@ bool ClipboardManagerImpl::pasteSize(SPDesktop *desktop, bool separately, bool a
// resize each object in the selection
if (separately) {
for (GSList *i = const_cast<GSList*>(selection->itemList()) ; i ; i = i->next) {
- SPItem *item = SP_ITEM(i->data);
- Geom::OptRect obj_size = item->desktopVisualBounds();
- if ( !obj_size ) {
- continue;
+ SPItem *item = dynamic_cast<SPItem *>(static_cast<SPObject *>(i->data));
+ if (item) {
+ Geom::OptRect obj_size = item->desktopVisualBounds();
+ if ( obj_size ) {
+ sp_item_scale_rel(item, _getScale(desktop, min, max, *obj_size, apply_x, apply_y));
+ }
+ } else {
+ g_assert_not_reached();
}
- sp_item_scale_rel(item, _getScale(desktop, min, max, *obj_size, apply_x, apply_y));
}
}
// resize the selection as a whole
@@ -601,6 +612,12 @@ Glib::ustring ClipboardManagerImpl::getPathParameter(SPDesktop* desktop)
*/
Glib::ustring ClipboardManagerImpl::getShapeOrTextObjectId(SPDesktop *desktop)
{
+ // https://bugs.launchpad.net/inkscape/+bug/1293979
+ // basically, when we do a depth-first search, we're stopping
+ // at the first object to be <svg:path> or <svg:text>.
+ // but that could then return the id of the object's
+ // clip path or mask, not the original path!
+
SPDocument *tempdoc = _retrieveClipboard(); // any target will do here
if ( tempdoc == NULL ) {
_userWarn(desktop, _("Nothing on the clipboard."));
@@ -608,6 +625,9 @@ Glib::ustring ClipboardManagerImpl::getShapeOrTextObjectId(SPDesktop *desktop)
}
Inkscape::XML::Node *root = tempdoc->getReprRoot();
+ // 1293979: strip out the defs of the document
+ root->removeChild(tempdoc->getDefs()->getRepr());
+
Inkscape::XML::Node *repr = sp_repr_lookup_name(root, "svg:path", -1); // unlimited search depth
if ( repr == NULL ) {
repr = sp_repr_lookup_name(root, "svg:text", -1);
@@ -631,7 +651,12 @@ void ClipboardManagerImpl::_copySelection(Inkscape::Selection *selection)
GSList const *items = selection->itemList();
// copy the defs used by all items
for (GSList *i = const_cast<GSList *>(items) ; i != NULL ; i = i->next) {
- _copyUsedDefs(SP_ITEM (i->data));
+ SPItem *item = dynamic_cast<SPItem *>(static_cast<SPObject *>(i->data));
+ if (item) {
+ _copyUsedDefs(item);
+ } else {
+ g_assert_not_reached();
+ }
}
// copy the representation of the items
@@ -639,36 +664,38 @@ void ClipboardManagerImpl::_copySelection(Inkscape::Selection *selection)
sorted_items = g_slist_sort(sorted_items, (GCompareFunc) sp_object_compare_position);
for (GSList *i = sorted_items ; i ; i = i->next) {
- if (!SP_IS_ITEM(i->data)) {
- continue;
+ SPItem *item = dynamic_cast<SPItem *>(static_cast<SPObject *>(i->data));
+ if (item) {
+ Inkscape::XML::Node *obj = item->getRepr();
+ Inkscape::XML::Node *obj_copy = _copyNode(obj, _doc, _root);
+
+ // copy complete inherited style
+ SPCSSAttr *css = sp_repr_css_attr_inherited(obj, "style");
+ sp_repr_css_set(obj_copy, css, "style");
+ sp_repr_css_attr_unref(css);
+
+ // write the complete accumulated transform passed to us
+ // (we're dealing with unattached representations, so we write to their attributes
+ // instead of using sp_item_set_transform)
+ gchar *transform_str = sp_svg_transform_write(item->i2doc_affine());
+ obj_copy->setAttribute("transform", transform_str);
+ g_free(transform_str);
}
- Inkscape::XML::Node *obj = reinterpret_cast<SPObject *>(i->data)->getRepr();
- Inkscape::XML::Node *obj_copy = _copyNode(obj, _doc, _root);
-
- // copy complete inherited style
- SPCSSAttr *css = sp_repr_css_attr_inherited(obj, "style");
- sp_repr_css_set(obj_copy, css, "style");
- sp_repr_css_attr_unref(css);
-
- // write the complete accumulated transform passed to us
- // (we're dealing with unattached representations, so we write to their attributes
- // instead of using sp_item_set_transform)
- gchar *transform_str = sp_svg_transform_write(SP_ITEM(i->data)->i2doc_affine());
- obj_copy->setAttribute("transform", transform_str);
- g_free(transform_str);
}
// copy style for Paste Style action
if (sorted_items) {
- if (SP_IS_ITEM(sorted_items->data)) {
- SPCSSAttr *style = take_style_from_item((SPItem *) sorted_items->data);
+ SPObject *object = static_cast<SPObject *>(sorted_items->data);
+ SPItem *item = dynamic_cast<SPItem *>(object);
+ if (item) {
+ SPCSSAttr *style = take_style_from_item(item);
sp_repr_css_set(_clipnode, style, "style");
sp_repr_css_attr_unref(style);
}
// copy path effect from the first path
- if (SP_IS_OBJECT(sorted_items->data)) {
- gchar const *effect = reinterpret_cast<SPObject *>(sorted_items->data)->getRepr()->attribute("inkscape:path-effect");
+ if (object) {
+ gchar const *effect =object->getRepr()->attribute("inkscape:path-effect");
if (effect) {
_clipnode->setAttribute("inkscape:path-effect", effect);
}
@@ -695,35 +722,38 @@ void ClipboardManagerImpl::_copyUsedDefs(SPItem *item)
if (style && (style->fill.isPaintserver())) {
SPPaintServer *server = item->style->getFillPaintServer();
- if ( SP_IS_LINEARGRADIENT(server) || SP_IS_RADIALGRADIENT(server) ) {
- _copyGradient(SP_GRADIENT(server));
+ if ( dynamic_cast<SPLinearGradient *>(server) || dynamic_cast<SPRadialGradient *>(server) ) {
+ _copyGradient(dynamic_cast<SPGradient *>(server));
}
- if ( SP_IS_PATTERN(server) ) {
- _copyPattern(SP_PATTERN(server));
+ SPPattern *pattern = dynamic_cast<SPPattern *>(server);
+ if ( pattern ) {
+ _copyPattern(pattern);
}
}
if (style && (style->stroke.isPaintserver())) {
SPPaintServer *server = item->style->getStrokePaintServer();
- if ( SP_IS_LINEARGRADIENT(server) || SP_IS_RADIALGRADIENT(server) ) {
- _copyGradient(SP_GRADIENT(server));
+ if ( dynamic_cast<SPLinearGradient *>(server) || dynamic_cast<SPRadialGradient *>(server) ) {
+ _copyGradient(dynamic_cast<SPGradient *>(server));
}
- if ( SP_IS_PATTERN(server) ) {
- _copyPattern(SP_PATTERN(server));
+ SPPattern *pattern = dynamic_cast<SPPattern *>(server);
+ if ( pattern ) {
+ _copyPattern(pattern);
}
}
// For shapes, copy all of the shape's markers
- if (SP_IS_SHAPE(item)) {
- SPShape *shape = SP_SHAPE (item);
+ SPShape *shape = dynamic_cast<SPShape *>(item);
+ if (shape) {
for (int i = 0 ; i < SP_MARKER_LOC_QTY ; i++) {
if (shape->_marker[i]) {
_copyNode(shape->_marker[i]->getRepr(), _doc, _defs);
}
}
}
+
// For lpe items, copy lpe stack if applicable
- if (SP_IS_LPE_ITEM(item)) {
- SPLPEItem *lpeitem = SP_LPE_ITEM (item);
+ SPLPEItem *lpeitem = dynamic_cast<SPLPEItem *>(item);
+ if (lpeitem) {
if (lpeitem->hasPathEffect()) {
for (PathEffectList::iterator it = lpeitem->path_effect_list->begin(); it != lpeitem->path_effect_list->end(); ++it)
{
@@ -734,14 +764,24 @@ void ClipboardManagerImpl::_copyUsedDefs(SPItem *item)
}
}
}
+
// For 3D boxes, copy perspectives
- if (SP_IS_BOX3D(item)) {
- _copyNode(box3d_get_perspective(SP_BOX3D(item))->getRepr(), _doc, _defs);
+ {
+ SPBox3D *box = dynamic_cast<SPBox3D *>(item);
+ if (box) {
+ _copyNode(box3d_get_perspective(box)->getRepr(), _doc, _defs);
+ }
}
+
// Copy text paths
- if (SP_IS_TEXT_TEXTPATH(item)) {
- _copyTextPath(SP_TEXTPATH(item->firstChild()));
+ {
+ SPText *text = dynamic_cast<SPText *>(item);
+ SPTextPath *textpath = (text) ? dynamic_cast<SPTextPath *>(text->firstChild()) : NULL;
+ if (textpath) {
+ _copyTextPath(textpath);
+ }
}
+
// Copy clipping objects
if (item->clip_ref){
if (item->clip_ref->getObject()) {
@@ -755,8 +795,9 @@ void ClipboardManagerImpl::_copyUsedDefs(SPItem *item)
_copyNode(mask->getRepr(), _doc, _defs);
// recurse into the mask for its gradients etc.
for (SPObject *o = mask->children ; o != NULL ; o = o->next) {
- if (SP_IS_ITEM(o)) {
- _copyUsedDefs(SP_ITEM(o));
+ SPItem *childItem = dynamic_cast<SPItem *>(o);
+ if (childItem) {
+ _copyUsedDefs(childItem);
}
}
}
@@ -765,15 +806,16 @@ void ClipboardManagerImpl::_copyUsedDefs(SPItem *item)
// Copy filters
if (style->getFilter()) {
SPObject *filter = style->getFilter();
- if (SP_IS_FILTER(filter)) {
+ if (dynamic_cast<SPFilter *>(filter)) {
_copyNode(filter->getRepr(), _doc, _defs);
}
}
// recurse
for (SPObject *o = item->children ; o != NULL ; o = o->next) {
- if (SP_IS_ITEM(o)) {
- _copyUsedDefs(SP_ITEM(o));
+ SPItem *childItem = dynamic_cast<SPItem *>(o);
+ if (childItem) {
+ _copyUsedDefs(childItem);
}
}
}
@@ -808,10 +850,10 @@ void ClipboardManagerImpl::_copyPattern(SPPattern *pattern)
// items in the pattern may also use gradients and other patterns, so recurse
for ( SPObject *child = pattern->firstChild() ; child ; child = child->getNext() ) {
- if (!SP_IS_ITEM (child)) {
- continue;
+ SPItem *childItem = dynamic_cast<SPItem *>(child);
+ if (childItem) {
+ _copyUsedDefs(childItem);
}
- _copyUsedDefs(SP_ITEM(child));
}
if (pattern->ref){
pattern = pattern->ref->getObject();
@@ -930,13 +972,13 @@ void ClipboardManagerImpl::_applyPathEffect(SPItem *item, gchar const *effectsta
if ( item == NULL ) {
return;
}
- if ( SP_IS_RECT(item) ) {
+ if ( dynamic_cast<SPRect *>(item) ) {
return;
}
- if (SP_IS_LPE_ITEM(item))
+ SPLPEItem *lpeitem = dynamic_cast<SPLPEItem *>(item);
+ if (lpeitem)
{
- SPLPEItem *lpeitem = SP_LPE_ITEM(item);
// for each effect in the stack, check if we need to fork it before adding it to the item
lpeitem->forkPathEffectsIfNecessary(1);
diff --git a/src/dialogs/dialog-events.cpp b/src/ui/dialog-events.cpp
index a12e3eafc..6bd93bbc3 100644
--- a/src/dialogs/dialog-events.cpp
+++ b/src/ui/dialog-events.cpp
@@ -29,7 +29,7 @@
#include "preferences.h"
#include "ui/tools/tool-base.h"
-#include "dialog-events.h"
+#include "ui/dialog-events.h"
/**
@@ -187,7 +187,7 @@ void on_transientize (SPDesktop *desktop, win_data *wd )
}
void
-sp_transientize_callback ( Inkscape::Application * /*inkscape*/,
+sp_transientize_callback ( InkscapeApplication * /*inkscape*/,
SPDesktop *desktop, win_data *wd )
{
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
diff --git a/src/dialogs/dialog-events.h b/src/ui/dialog-events.h
index 623058282..b33eb3f38 100644
--- a/src/dialogs/dialog-events.h
+++ b/src/ui/dialog-events.h
@@ -29,9 +29,7 @@ class Entry;
class SPDesktop;
-namespace Inkscape {
-struct Application;
-} // namespace Inkscape
+struct InkscapeApplication;
typedef struct {
GtkWidget *win;
@@ -55,7 +53,7 @@ void sp_transientize ( GtkWidget *win );
void on_transientize ( SPDesktop *desktop,
win_data *wd );
-void sp_transientize_callback ( Inkscape::Application *inkscape,
+void sp_transientize_callback ( InkscapeApplication *inkscape,
SPDesktop *desktop,
win_data *wd );
diff --git a/src/ui/dialog/Makefile_insert b/src/ui/dialog/Makefile_insert
index daa8aea22..cbdae1cb0 100644
--- a/src/ui/dialog/Makefile_insert
+++ b/src/ui/dialog/Makefile_insert
@@ -100,6 +100,8 @@ ink_common_sources += \
ui/dialog/template-load-tab.h \
ui/dialog/template-widget.cpp \
ui/dialog/template-widget.h \
+ ui/dialog/tags.cpp \
+ ui/dialog/tags.h \
ui/dialog/text-edit.cpp \
ui/dialog/text-edit.h \
ui/dialog/tile.cpp \
@@ -114,4 +116,10 @@ ink_common_sources += \
ui/dialog/undo-history.h \
ui/dialog/xml-tree.cpp \
ui/dialog/xml-tree.h \
+ ui/dialog/lpe-powerstroke-properties.cpp \
+ ui/dialog/lpe-powerstroke-properties.h \
+ ui/dialog/objects.cpp \
+ ui/dialog/objects.h \
+ ui/dialog/lpe-fillet-chamfer-properties.cpp \
+ ui/dialog/lpe-fillet-chamfer-properties.h \
$(inkboard_dialogs)
diff --git a/src/ui/dialog/aboutbox.cpp b/src/ui/dialog/aboutbox.cpp
index 121773b6d..50b35ca2f 100644
--- a/src/ui/dialog/aboutbox.cpp
+++ b/src/ui/dialog/aboutbox.cpp
@@ -254,6 +254,7 @@ void AboutBox::initStrings() {
"Nicholas Bishop\n"
"Joshua L. Blocher\n"
"Hanno Böck\n"
+"Tomasz Boczkowski\n"
"Henrik Bohre\n"
"Boldewyn\n"
"Daniel Borgmann\n"
@@ -270,6 +271,7 @@ void AboutBox::initStrings() {
"Gail Carmichael\n"
"Ed Catmur\n"
"Chema Celorio\n"
+"Jabiertxo Arraiza Cenoz\n"
"Johan Ceuppens\n"
"Zbigniew Chyla\n"
"Alexander Clausen\n"
@@ -311,6 +313,7 @@ void AboutBox::initStrings() {
"Hannes Hochreiner\n"
"Thomas Holder\n"
"Joel Holdsworth\n"
+"Christoffer Holmstedt\n"
"Alan Horkan\n"
"Karl Ove Hufthammer\n"
"Richard Hughes\n"
@@ -319,6 +322,7 @@ void AboutBox::initStrings() {
"Thomas Ingham\n"
"Jean-Olivier Irisson\n"
"Bob Jamison\n"
+"Ted Janeczko\n"
"jEsuSdA\n"
"Fernando Lucchesi Bastos Jurema\n"
"Lauris Kaplinski\n"
@@ -342,7 +346,9 @@ void AboutBox::initStrings() {
"Aurel-Aimé Marmion\n"
"Colin Marquardt\n"
"Craig Marshall\n"
+"Ivan Masár\n"
"Dmitry G. Mastrukov\n"
+"David Mathog\n"
"Matiphas\n"
"Michael Meeks\n"
"Federico Mena\n"
@@ -360,8 +366,10 @@ void AboutBox::initStrings() {
"Nick\n"
"Andreas Nilsson\n"
"Mitsuru Oka\n"
+"Vinícius dos Santos Oliveira\n"
"Martin Owens\n"
"Alvin Penner\n"
+"Matthew Petroff\n"
"Jon Phillips\n"
"Zdenko Podobny\n"
"Alexandre Prokoudine\n"
@@ -398,6 +406,8 @@ void AboutBox::initStrings() {
"Joakim Verona\n"
"Lucas Vieites\n"
"Daniel Wagenaar\n"
+"Liam P. White\n"
+"Sebastian Wüst\n"
"Michael Wybrow\n"
"Gellule Xg\n"
"Daniel Yacob\n"
@@ -442,13 +452,13 @@ void AboutBox::initStrings() {
*/
gchar const *allTranslators =
"3ARRANO.com <3arrano@3arrano.com>, 2005.\n"
-"Adib Taraben <theadib@googlemail.com>, 2004.\n"
+"Adib Taraben <theadib@gmail.com>, 2004-2014.\n"
"Alan Monfort <alan.monfort@free.fr>, 2009-2010.\n"
"Alastair McKinstry <mckinstry@computer.org>, 2000.\n"
"Aleksandar Urošević <urke@users.sourceforge.net>, 2004-2006.\n"
"Alessio Frusciante <algol@firenze.linux.it>, 2002, 2003.\n"
"Alexander Shopov <ash@contact.bg>, 2006.\n"
-"Alexandre Prokoudine <alexandre.prokoudine@gmail.com>, 2005, 2010-2013.\n"
+"Alexandre Prokoudine <alexandre.prokoudine@gmail.com>, 2005, 2010-2014.\n"
"Alexey Remizov <alexey@remizov.pp.ru>, 2004.\n"
"Ali Ghanavatian <ghanvatian.ali@gmail.com>, 2010.\n"
"Ãlvaro Lopes <alvieboy@alvie.com>, 2001, 2002.\n"
@@ -482,6 +492,7 @@ void AboutBox::initStrings() {
"Elias Norberg <elno0959 at student.su.se>, 2009.\n"
"Equipe de Tradução Inkscape Brasil <www.inkscapebrasil.org>, 2007.\n"
"Fatih Demir <kabalak@gtranslator.org>, 2000.\n"
+"Firas Hanife <FirasHanife@gmail.com>, 2014.\n"
"Foppe Benedictus <foppe.benedictus@gmail.com>, 2007-2009.\n"
"Francesc Dorca <f.dorca@filnet.es>, 2003. Traducció sodipodi.\n"
"Francisco Javier F. Serrador <serrador@arrakis.es>, 2003.\n"
@@ -492,9 +503,10 @@ void AboutBox::initStrings() {
"Hleb Valoshka <375gnu@gmail.com>, 2008-2009.\n"
"Hizkuntza Politikarako Sailburuordetza <hizkpol@ej-gv.es>, 2005.\n"
"Ilia Penev <lichopicho@gmail.com>, 2006.\n"
-"Ivan Masár <helix84@centrum.sk>, 2006-2010. \n"
+"Ivan Masár <helix84@centrum.sk>, 2006-2014. \n"
+"Ivan Řihošek <irihosek@seznam.cz>, 2014.\n"
"Iñaki Larrañaga <dooteo@euskalgnu.org>, 2006.\n"
-"JÄnis Eisaks <jancs@dv.lv>, 2012, 2013.\n"
+"JÄnis Eisaks <jancs@dv.lv>, 2012-2014.\n"
"Jeffrey Steve Borbón Sanabria <jeff_kerokid@yahoo.com>, 2005.\n"
"Jesper Öqvist <jesper@llbit.se>, 2010, 2011.\n"
"Joaquim Perez i Noguer <noguer@gmail.com>, 2008-2009.\n"
@@ -516,7 +528,7 @@ void AboutBox::initStrings() {
"Kingsley Turner <kingsley@maddogsbreakfast.com.au>, 2006.\n"
"Kitae <bluetux@gmail.com>, 2006.\n"
"Kjartan Maraas <kmaraas@gnome.org>, 2000-2002.\n"
-"Kris De Gussem <Kris.DeGussem@gmail.com>, 2008-2013.\n"
+"Kris De Gussem <Kris.DeGussem@gmail.com>, 2008-2014.\n"
"Lauris Kaplinski <lauris@ariman.ee>, 2000.\n"
"Leandro Regueiro <leandro.regueiro@gmail.com>, 2006-2008, 2010.\n"
"Liu Xiaoqin <liuxqsmile@gmail.com>, 2008.\n"
@@ -525,7 +537,7 @@ void AboutBox::initStrings() {
"Mahesh subedi <submanesh@hotmail.com>, 2006.\n"
"Martin Srebotnjak, <miles@filmsi.net>, 2005, 2010.\n"
"Masatake YAMATO <jet@gyve.org>, 2002.\n"
-"Masato Hashimoto <cabezon.hashimoto@gmail.com>, 2009-2012.\n"
+"Masato Hashimoto <cabezon.hashimoto@gmail.com>, 2009-2014.\n"
"Matiphas <matiphas _a_ free _point_ fr>, 2004-2006.\n"
"Mattias Hultgren <mattias_hultgren@tele2.se>, 2005, 2006.\n"
"Maxim Dziumanenko <mvd@mylinux.com.ua>, 2004.\n"
@@ -536,12 +548,12 @@ void AboutBox::initStrings() {
"Muhammad Bashir Al-Noimi <mhdbnoimi@gmail.com>, 2008.\n"
"Myckel Habets <myckel@sdf.lonestar.org>, 2008.\n"
"Nguyen Dinh Trung <nguyendinhtrung141@gmail.com>, 2007, 2008.\n"
-"Nicolas Dufour <nicoduf@yahoo.fr>, 2008-2013.\n"
+"Nicolas Dufour <nicoduf@yahoo.fr>, 2008-2014.\n"
"Pawan Chitrakar <pchitrakar@gmail.com>, 2006.\n"
"Przemysław Loesch <p_loesch@poczta.onet.pl>, 2005.\n"
"Quico Llach <quico@softcatala.org>, 2000. Traducció sodipodi.\n"
"Raymond Ostertag <raymond@linuxgraphic.org>, 2002, 2003.\n"
-"Riku Leino <tsoots@gmail.com>, 2006.\n"
+"Riku Leino <tsoots@gmail.com>, 2006-2011.\n"
"Rune Rønde Laursen <runerl@skjoldhoej.dk>, 2006.\n"
"Ruud Steltenpool <svg@steltenpower.com>, 2006.\n"
"Serdar Soytetir <sendirom@gmail.com>, 2005.\n"
@@ -557,9 +569,11 @@ void AboutBox::initStrings() {
"Thiago Pimentel <thiago.merces@gmail.com>, 2006.\n"
"Toshifumi Sato <sato@centrosystem.com>, 2005.\n"
"Jon South <striker@lunar-linux.org>, 2006. \n"
-"Uwe Schöler <oss@oss-marketplace.com>, 2006-2013.\n"
+"Uwe Schöler <oss@oss-marketplace.com>, 2006-2014.\n"
"Valek Filippov <frob@df.ru>, 2000, 2003.\n"
"Victor Dachev <vdachev@gmail.com>, 2006.\n"
+"Victor Westmann <victor.westmann@gmail.com>, 2011, 2014.\n"
+"Ville Pätsi, 2013.\n"
"Vincent van Adrighem <V.vanAdrighem@dirck.mine.nu>, 2003.\n"
"Vital Khilko <dojlid@mova.org>, 2003.\n"
"Vitaly Lipatov <lav@altlinux.ru>, 2002, 2004.\n"
@@ -572,7 +586,7 @@ void AboutBox::initStrings() {
"Yaron Shahrabani <sh.yaron@gmail.com>, 2009.\n"
"Yukihiro Nakai <nakai@gnome.gr.jp>, 2000, 2003.\n"
"Yuri Beznos <zhiz0id@gmail.com>, 2006.\n"
-"Yuri Chornoivan <yurchor@ukr.net>, 2007-2013.\n"
+"Yuri Chornoivan <yurchor@ukr.net>, 2007-2014.\n"
"Yuri Syrota <rasta@renome.rovno.ua>, 2000.\n"
"Yves Guillou <yvesguillou@users.sourceforge.net>, 2004.\n"
"Zdenko Podobný <zdpo@mailbox.sk>, 2003, 2004."
@@ -941,13 +955,13 @@ void AboutBox::initStrings() {
} // namespace UI
} // namespace Inkscape
-/*
+/*
Local Variables:
mode:c++
c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0))
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
indent-tabs-mode:nil
fill-column:99
End:
*/
-// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/ui/dialog/aboutbox.h b/src/ui/dialog/aboutbox.h
index 7b3308672..015e344a1 100644
--- a/src/ui/dialog/aboutbox.h
+++ b/src/ui/dialog/aboutbox.h
@@ -55,13 +55,13 @@ private:
#endif // INKSCAPE_UI_DIALOG_ABOUTBOX_H
-/*
+/*
Local Variables:
mode:c++
c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0))
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
indent-tabs-mode:nil
fill-column:99
End:
*/
-// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/ui/dialog/align-and-distribute.cpp b/src/ui/dialog/align-and-distribute.cpp
index 6b4aeebb9..431da7ad1 100644
--- a/src/ui/dialog/align-and-distribute.cpp
+++ b/src/ui/dialog/align-and-distribute.cpp
@@ -38,7 +38,7 @@
#include "sp-item-transform.h"
#include "sp-text.h"
#include "text-editing.h"
-#include "tools-switch.h"
+#include "ui/tools-switch.h"
#include "ui/icon-names.h"
#include "ui/tools/node-tool.h"
#include "ui/tool/multi-path-manipulator.h"
@@ -829,14 +829,14 @@ private :
-static void on_tool_changed(Inkscape::Application */*inkscape*/, Inkscape::UI::Tools::ToolBase */*context*/, AlignAndDistribute *daad)
+static void on_tool_changed(InkscapeApplication */*inkscape*/, Inkscape::UI::Tools::ToolBase */*context*/, AlignAndDistribute *daad)
{
SPDesktop *desktop = SP_ACTIVE_DESKTOP;
if (desktop && desktop->getEventContext())
daad->setMode(tools_active(desktop) == TOOLS_NODES);
}
-static void on_selection_changed(Inkscape::Application */*inkscape*/, Inkscape::Selection */*selection*/, AlignAndDistribute *daad)
+static void on_selection_changed(InkscapeApplication */*inkscape*/, Inkscape::Selection */*selection*/, AlignAndDistribute *daad)
{
daad->randomize_bbox = Geom::OptRect();
}
@@ -1002,7 +1002,7 @@ AlignAndDistribute::AlignAndDistribute()
_combo.append(_("Smallest object"));
_combo.append(_("Page"));
_combo.append(_("Drawing"));
- _combo.append(_("Selection"));
+ _combo.append(_("Selection Area"));
_combo.set_active(prefs->getInt("/dialogs/align/align-to", 6));
_combo.signal_changed().connect(sigc::mem_fun(*this, &AlignAndDistribute::on_ref_change));
diff --git a/src/ui/dialog/calligraphic-profile-rename.h b/src/ui/dialog/calligraphic-profile-rename.h
index 3256338eb..fa13db196 100644
--- a/src/ui/dialog/calligraphic-profile-rename.h
+++ b/src/ui/dialog/calligraphic-profile-rename.h
@@ -16,7 +16,7 @@
#endif
#if GLIBMM_DISABLE_DEPRECATED && HAVE_GLIBMM_THREADS_H
-#include <glibmm/threads.h>
+# include <glibmm/threads.h>
#endif
#include <gtkmm/dialog.h>
diff --git a/src/ui/dialog/clonetiler.cpp b/src/ui/dialog/clonetiler.cpp
index fb131d8da..d1a675735 100644
--- a/src/ui/dialog/clonetiler.cpp
+++ b/src/ui/dialog/clonetiler.cpp
@@ -1,5 +1,6 @@
-/** @file
+/**
+ * @file
* Clone tiling dialog
*/
/* Authors:
@@ -38,7 +39,7 @@
#include "util/units.h"
#include "helper/window.h"
#include "inkscape.h"
-#include "interface.h"
+#include "ui/interface.h"
#include "macros.h"
#include "message-stack.h"
#include "preferences.h"
@@ -1349,7 +1350,7 @@ void CloneTiler::on_picker_color_changed(guint rgba)
is_updating = false;
}
-void CloneTiler::clonetiler_change_selection(Inkscape::Application * /*inkscape*/, Inkscape::Selection *selection, GtkWidget *dlg)
+void CloneTiler::clonetiler_change_selection(InkscapeApplication * /*inkscape*/, Inkscape::Selection *selection, GtkWidget *dlg)
{
GtkWidget *buttons = GTK_WIDGET(g_object_get_data (G_OBJECT(dlg), "buttons_on_tiles"));
GtkWidget *status = GTK_WIDGET(g_object_get_data (G_OBJECT(dlg), "status"));
@@ -1378,7 +1379,7 @@ void CloneTiler::clonetiler_change_selection(Inkscape::Application * /*inkscape*
}
}
-void CloneTiler::clonetiler_external_change(Inkscape::Application * /*inkscape*/, GtkWidget *dlg)
+void CloneTiler::clonetiler_external_change(InkscapeApplication * /*inkscape*/, GtkWidget *dlg)
{
clonetiler_change_selection (NULL, sp_desktop_selection(SP_ACTIVE_DESKTOP), dlg);
}
@@ -2002,7 +2003,7 @@ bool CloneTiler::clonetiler_is_a_clone_of(SPObject *tile, SPObject *obj)
id_href = g_strdup_printf("#%s", obj_repr->attribute("id"));
}
- if (SP_IS_USE(tile) &&
+ if (dynamic_cast<SPUse *>(tile) &&
tile->getRepr()->attribute("xlink:href") &&
(!id_href || !strcmp(id_href, tile->getRepr()->attribute("xlink:href"))) &&
tile->getRepr()->attribute("inkscape:tiled-clone-of") &&
@@ -2025,8 +2026,10 @@ void CloneTiler::clonetiler_trace_hide_tiled_clones_recursively(SPObject *from)
return;
for (SPObject *o = from->firstChild(); o != NULL; o = o->next) {
- if (SP_IS_ITEM(o) && clonetiler_is_a_clone_of (o, NULL))
- SP_ITEM(o)->invoke_hide(trace_visionkey); // FIXME: hide each tiled clone's original too!
+ SPItem *item = dynamic_cast<SPItem *>(o);
+ if (item && clonetiler_is_a_clone_of(o, NULL)) {
+ item->invoke_hide(trace_visionkey); // FIXME: hide each tiled clone's original too!
+ }
clonetiler_trace_hide_tiled_clones_recursively (o);
}
}
@@ -2160,7 +2163,9 @@ void CloneTiler::clonetiler_remove(GtkWidget */*widget*/, GtkWidget *dlg, bool d
}
}
for (GSList *i = to_delete; i; i = i->next) {
- SP_OBJECT(i->data)->deleteObject();
+ SPObject *obj = reinterpret_cast<SPObject *>(i->data);
+ g_assert(obj != NULL);
+ obj->deleteObject();
}
g_slist_free (to_delete);
@@ -2235,13 +2240,19 @@ void CloneTiler::clonetiler_apply(GtkWidget */*widget*/, GtkWidget *dlg)
gdk_window_process_all_updates();
SPObject *obj = selection->singleItem();
- SPItem *item = SP_IS_ITEM(obj) ? SP_ITEM(obj) : 0;
+ if (!obj) {
+ // Should never happen (empty selection checked above).
+ std::cerr << "CloneTiler::clonetile_apply(): No object in single item selection!!!" << std::endl;
+ return;
+ }
Inkscape::XML::Node *obj_repr = obj->getRepr();
const char *id_href = g_strdup_printf("#%s", obj_repr->attribute("id"));
SPObject *parent = obj->parent;
clonetiler_remove (NULL, dlg, false);
+ double scale_units = Inkscape::Util::Quantity::convert(1, "px", sp_desktop_document(desktop)->getDefaultUnit());
+
double shiftx_per_i = 0.01 * prefs->getDoubleLimited(prefs_path + "shiftx_per_i", 0, -10000, 10000);
double shifty_per_i = 0.01 * prefs->getDoubleLimited(prefs_path + "shifty_per_i", 0, -10000, 10000);
double shiftx_per_j = 0.01 * prefs->getDoubleLimited(prefs_path + "shiftx_per_j", 0, -10000, 10000);
@@ -2311,8 +2322,8 @@ void CloneTiler::clonetiler_apply(GtkWidget */*widget*/, GtkWidget *dlg)
int jmax = prefs->getInt(prefs_path + "jmax", 2);
bool fillrect = prefs->getBool(prefs_path + "fillrect");
- double fillwidth = prefs->getDoubleLimited(prefs_path + "fillwidth", 50, 0, 1e6);
- double fillheight = prefs->getDoubleLimited(prefs_path + "fillheight", 50, 0, 1e6);
+ double fillwidth = scale_units*prefs->getDoubleLimited(prefs_path + "fillwidth", 50, 0, 1e6);
+ double fillheight = scale_units*prefs->getDoubleLimited(prefs_path + "fillheight", 50, 0, 1e6);
bool dotrace = prefs->getBool(prefs_path + "dotrace");
int pick = prefs->getInt(prefs_path + "pick");
@@ -2324,6 +2335,7 @@ void CloneTiler::clonetiler_apply(GtkWidget */*widget*/, GtkWidget *dlg)
bool invert_picked = prefs->getBool(prefs_path + "invert_picked");
double gamma_picked = prefs->getDoubleLimited(prefs_path + "gamma_picked", 0, -10, 10);
+ SPItem *item = dynamic_cast<SPItem *>(obj);
if (dotrace) {
clonetiler_trace_setup (sp_desktop_document(desktop), 1.0, item);
}
@@ -2358,11 +2370,11 @@ void CloneTiler::clonetiler_apply(GtkWidget */*widget*/, GtkWidget *dlg)
SPItem::VISUAL_BBOX : SPItem::GEOMETRIC_BBOX );
Geom::OptRect r = item->documentBounds(bbox_type);
if (r) {
- w = r->dimensions()[Geom::X];
- h = r->dimensions()[Geom::Y];
- x0 = r->min()[Geom::X];
- y0 = r->min()[Geom::Y];
- center = desktop->dt2doc(item->getCenter());
+ w = scale_units*r->dimensions()[Geom::X];
+ h = scale_units*r->dimensions()[Geom::Y];
+ x0 = scale_units*r->min()[Geom::X];
+ y0 = scale_units*r->min()[Geom::Y];
+ center = scale_units*desktop->dt2doc(item->getCenter());
sp_repr_set_svg_double(obj_repr, "inkscape:tile-cx", center[Geom::X]);
sp_repr_set_svg_double(obj_repr, "inkscape:tile-cy", center[Geom::Y]);
@@ -2578,7 +2590,7 @@ void CloneTiler::clonetiler_apply(GtkWidget */*widget*/, GtkWidget *dlg)
Geom::Point new_center;
bool center_set = false;
if (obj_repr->attribute("inkscape:transform-center-x") || obj_repr->attribute("inkscape:transform-center-y")) {
- new_center = desktop->dt2doc(item->getCenter()) * t;
+ new_center = scale_units*desktop->dt2doc(item->getCenter()) * t;
center_set = true;
}
@@ -2614,9 +2626,10 @@ void CloneTiler::clonetiler_apply(GtkWidget */*widget*/, GtkWidget *dlg)
if (center_set) {
SPObject *clone_object = sp_desktop_document(desktop)->getObjectByRepr(clone);
- if (clone_object && SP_IS_ITEM(clone_object)) {
+ SPItem *item = dynamic_cast<SPItem *>(clone_object);
+ if (clone_object && item) {
clone_object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
- SP_ITEM(clone_object)->setCenter(desktop->doc2dt(new_center));
+ item->setCenter(desktop->doc2dt(new_center));
clone_object->updateRepr();
}
}
diff --git a/src/ui/dialog/clonetiler.h b/src/ui/dialog/clonetiler.h
index e2a0240ee..70da86338 100644
--- a/src/ui/dialog/clonetiler.h
+++ b/src/ui/dialog/clonetiler.h
@@ -11,7 +11,6 @@
#define __SP_CLONE_TILER_H__
#include "ui/widget/panel.h"
-#include <gtk/gtk.h>
#include "ui/dialog/desktop-tracker.h"
#include "ui/widget/color-picker.h"
@@ -58,8 +57,8 @@ protected:
static void clonetiler_keep_bbox_toggled(GtkToggleButton *tb, gpointer /*data*/);
static void clonetiler_apply(GtkWidget */*widget*/, GtkWidget *dlg);
static void clonetiler_unclump(GtkWidget */*widget*/, void *);
- static void clonetiler_change_selection(Inkscape::Application * /*inkscape*/, Inkscape::Selection *selection, GtkWidget *dlg);
- static void clonetiler_external_change(Inkscape::Application * /*inkscape*/, GtkWidget *dlg);
+ static void clonetiler_change_selection(InkscapeApplication * /*inkscape*/, Inkscape::Selection *selection, GtkWidget *dlg);
+ static void clonetiler_external_change(InkscapeApplication * /*inkscape*/, GtkWidget *dlg);
static void clonetiler_disconnect_gsignal(GObject *widget, gpointer source);
static void clonetiler_reset(GtkWidget */*widget*/, GtkWidget *dlg);
static guint clonetiler_number_of_clones(SPObject *obj);
diff --git a/src/ui/dialog/color-item.cpp b/src/ui/dialog/color-item.cpp
index 7940c28ae..bab7e18e1 100644
--- a/src/ui/dialog/color-item.cpp
+++ b/src/ui/dialog/color-item.cpp
@@ -684,6 +684,7 @@ void ColorItem::buttonClicked(bool secondary)
descr = secondary? _("Set stroke color to none") : _("Set fill color to none");
break;
}
+//mark
case ege::PaintDef::RGB: {
Glib::ustring colorspec;
if ( _grad ){
@@ -696,6 +697,7 @@ void ColorItem::buttonClicked(bool secondary)
sp_svg_write_color(c, sizeof(c), rgba);
colorspec = c;
}
+//end mark
sp_repr_css_set_property( css, attrName, colorspec.c_str() );
descr = secondary? _("Set stroke color from swatch") : _("Set fill color from swatch");
break;
diff --git a/src/ui/dialog/desktop-tracker.cpp b/src/ui/dialog/desktop-tracker.cpp
index 8a359dd2d..3ed998252 100644
--- a/src/ui/dialog/desktop-tracker.cpp
+++ b/src/ui/dialog/desktop-tracker.cpp
@@ -94,7 +94,7 @@ sigc::connection DesktopTracker::connectDesktopChanged( const sigc::slot<void, S
return desktopChangedSig.connect(slot);
}
-gboolean DesktopTracker::activateDesktopCB(Inkscape::Application */*inkscape*/, SPDesktop *desktop, DesktopTracker *self )
+gboolean DesktopTracker::activateDesktopCB(InkscapeApplication */*inkscape*/, SPDesktop *desktop, DesktopTracker *self )
{
if (self && self->trackActive) {
self->setDesktop(desktop);
diff --git a/src/ui/dialog/desktop-tracker.h b/src/ui/dialog/desktop-tracker.h
index 7da55cf2f..7b944ddfa 100644
--- a/src/ui/dialog/desktop-tracker.h
+++ b/src/ui/dialog/desktop-tracker.h
@@ -12,11 +12,10 @@
typedef struct _GtkWidget GtkWidget;
class SPDesktop;
+struct InkscapeApplication;
namespace Inkscape {
-struct Application;
-
namespace UI {
namespace Dialog {
@@ -37,7 +36,7 @@ public:
sigc::connection connectDesktopChanged( const sigc::slot<void, SPDesktop*> & slot );
private:
- static gboolean activateDesktopCB(Inkscape::Application *inkscape, SPDesktop *desktop, DesktopTracker *self );
+ static gboolean activateDesktopCB(InkscapeApplication *inkscape, SPDesktop *desktop, DesktopTracker *self );
static bool hierarchyChangeCB(GtkWidget *widget, GtkWidget* prev, DesktopTracker *self);
void handleHierarchyChange();
diff --git a/src/ui/dialog/dialog-manager.cpp b/src/ui/dialog/dialog-manager.cpp
index 47e1fdd30..7b1b36908 100644
--- a/src/ui/dialog/dialog-manager.cpp
+++ b/src/ui/dialog/dialog-manager.cpp
@@ -54,6 +54,8 @@
#include "ui/dialog/xml-tree.h"
#include "ui/dialog/clonetiler.h"
#include "ui/dialog/svg-fonts-dialog.h"
+#include "ui/dialog/objects.h"
+#include "ui/dialog/tags.h"
namespace Inkscape {
namespace UI {
@@ -70,13 +72,13 @@ inline Dialog *create() { return PanelDialog<B>::template create<T>(); }
/**
* This class is provided as a container for Inkscape's various
- * dialogs. This allows Inkscape::Application to treat the various
+ * dialogs. This allows InkscapeApplication to treat the various
* dialogs it invokes, as abstractions.
*
* DialogManager is essentially a cache of dialogs. It lets us
* initialize dialogs lazily - instead of constructing them during
* application startup, they're constructed the first time they're
- * actually invoked by Inkscape::Application. The constructed
+ * actually invoked by InkscapeApplication. The constructed
* dialog is held here after that, so future invokations of the
* dialog don't need to get re-constructed each time. The memory for
* the dialogs are then reclaimed when the DialogManager is destroyed.
@@ -96,6 +98,9 @@ DialogManager::DialogManager() {
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
int dialogs_type = prefs->getIntLimited("/options/dialogtype/value", DOCK, 0, 1);
+ // The preferences dialog is broken, the DockBehavior code resizes it's floating window to the smallest size
+ registerFactory("InkscapePreferences", &create<InkscapePreferences, FloatingBehavior>);
+
if (dialogs_type == FLOATING) {
registerFactory("AlignAndDistribute", &create<AlignAndDistribute, FloatingBehavior>);
registerFactory("DocumentMetadata", &create<DocumentMetadata, FloatingBehavior>);
@@ -106,8 +111,9 @@ DialogManager::DialogManager() {
registerFactory("Find", &create<Find, FloatingBehavior>);
registerFactory("Glyphs", &create<GlyphsPanel, FloatingBehavior>);
registerFactory("IconPreviewPanel", &create<IconPreviewPanel, FloatingBehavior>);
- registerFactory("InkscapePreferences", &create<InkscapePreferences, FloatingBehavior>);
registerFactory("LayersPanel", &create<LayersPanel, FloatingBehavior>);
+ registerFactory("ObjectsPanel", &create<ObjectsPanel, FloatingBehavior>);
+ registerFactory("TagsPanel", &create<TagsPanel, FloatingBehavior>);
registerFactory("LivePathEffect", &create<LivePathEffectEditor, FloatingBehavior>);
registerFactory("Memory", &create<Memory, FloatingBehavior>);
registerFactory("Messages", &create<Messages, FloatingBehavior>);
@@ -126,8 +132,8 @@ DialogManager::DialogManager() {
registerFactory("TextFont", &create<TextEdit, FloatingBehavior>);
registerFactory("SpellCheck", &create<SpellCheck, FloatingBehavior>);
registerFactory("Export", &create<Export, FloatingBehavior>);
- registerFactory("XmlTree", &create<XmlTree, FloatingBehavior>);
registerFactory("CloneTiler", &create<CloneTiler, FloatingBehavior>);
+ registerFactory("XmlTree", &create<XmlTree, FloatingBehavior>);
} else {
@@ -140,8 +146,9 @@ DialogManager::DialogManager() {
registerFactory("Find", &create<Find, DockBehavior>);
registerFactory("Glyphs", &create<GlyphsPanel, DockBehavior>);
registerFactory("IconPreviewPanel", &create<IconPreviewPanel, DockBehavior>);
- registerFactory("InkscapePreferences", &create<InkscapePreferences, DockBehavior>);
registerFactory("LayersPanel", &create<LayersPanel, DockBehavior>);
+ registerFactory("ObjectsPanel", &create<ObjectsPanel, DockBehavior>);
+ registerFactory("TagsPanel", &create<TagsPanel, DockBehavior>);
registerFactory("LivePathEffect", &create<LivePathEffectEditor, DockBehavior>);
registerFactory("Memory", &create<Memory, DockBehavior>);
registerFactory("Messages", &create<Messages, DockBehavior>);
@@ -160,8 +167,8 @@ DialogManager::DialogManager() {
registerFactory("TextFont", &create<TextEdit, DockBehavior>);
registerFactory("SpellCheck", &create<SpellCheck, DockBehavior>);
registerFactory("Export", &create<Export, DockBehavior>);
- registerFactory("XmlTree", &create<XmlTree, DockBehavior>);
registerFactory("CloneTiler", &create<CloneTiler, DockBehavior>);
+ registerFactory("XmlTree", &create<XmlTree, DockBehavior>);
}
}
@@ -250,7 +257,7 @@ void DialogManager::showDialog(gchar const *name, bool grabfocus) {
/**
* Shows the named dialog, creating it if necessary.
*/
-void DialogManager::showDialog(GQuark name, bool grabfocus) {
+void DialogManager::showDialog(GQuark name, bool /*grabfocus*/) {
bool wantTiming = Inkscape::Preferences::get()->getBool("/dialogs/debug/trackAppear", false);
GTimer *timer = (wantTiming) ? g_timer_new() : 0; // if needed, must be created/started before getDialog()
Dialog *dialog = getDialog(name);
@@ -261,8 +268,8 @@ void DialogManager::showDialog(GQuark name, bool grabfocus) {
tracker->setAutodelete(true);
timer = 0;
}
- if (grabfocus)
- dialog->present();
+ // should check for grabfocus, but lp:1348927 prevents it
+ dialog->present();
}
if ( timer ) {
diff --git a/src/ui/dialog/dialog.cpp b/src/ui/dialog/dialog.cpp
index 645294bb5..213965a18 100644
--- a/src/ui/dialog/dialog.cpp
+++ b/src/ui/dialog/dialog.cpp
@@ -28,7 +28,7 @@
#include "desktop-handles.h"
#include "shortcuts.h"
#include "preferences.h"
-#include "interface.h"
+#include "ui/interface.h"
#include "verbs.h"
#include "ui/tool/event-utils.h"
@@ -41,7 +41,7 @@ namespace Inkscape {
namespace UI {
namespace Dialog {
-void sp_retransientize(Inkscape::Application */*inkscape*/, SPDesktop *desktop, gpointer dlgPtr)
+void sp_retransientize(InkscapeApplication */*inkscape*/, SPDesktop *desktop, gpointer dlgPtr)
{
Dialog *dlg = static_cast<Dialog *>(dlgPtr);
dlg->onDesktopActivated (desktop);
@@ -317,20 +317,8 @@ void Dialog::_apply()
void Dialog::_close()
{
- GtkWidget *dlg = GTK_WIDGET(_behavior->gobj());
-
- GdkEventAny event;
- event.type = GDK_DELETE;
- event.window = gtk_widget_get_window(dlg);
- event.send_event = TRUE;
-
- if (event.window)
- g_object_ref(G_OBJECT(event.window));
-
- gtk_main_do_event ((GdkEvent*)&event);
-
- if (event.window)
- g_object_unref(G_OBJECT(event.window));
+ _behavior->hide();
+ _onDeleteEvent(NULL);
}
void Dialog::_defocus()
diff --git a/src/ui/dialog/dialog.h b/src/ui/dialog/dialog.h
index ec5d203bc..ccff43a56 100644
--- a/src/ui/dialog/dialog.h
+++ b/src/ui/dialog/dialog.h
@@ -18,10 +18,10 @@
#include "floating-behavior.h"
class SPDesktop;
+struct InkscapeApplication;
namespace Inkscape {
class Selection;
-struct Application;
}
namespace Inkscape {
@@ -30,7 +30,7 @@ namespace Dialog {
enum BehaviorType { FLOATING, DOCK };
-void sp_retransientize(Inkscape::Application *inkscape, SPDesktop *desktop, gpointer dlgPtr);
+void sp_retransientize(InkscapeApplication *inkscape, SPDesktop *desktop, gpointer dlgPtr);
gboolean sp_retransientize_again(gpointer dlgPtr);
void sp_dialog_shutdown(GObject *object, gpointer dlgPtr);
diff --git a/src/ui/dialog/dock-behavior.cpp b/src/ui/dialog/dock-behavior.cpp
index 9b216e841..50a6db208 100644
--- a/src/ui/dialog/dock-behavior.cpp
+++ b/src/ui/dialog/dock-behavior.cpp
@@ -18,13 +18,13 @@
#include "dock-behavior.h"
#include "inkscape.h"
#include "desktop.h"
-#include "interface.h"
+#include "ui/interface.h"
#include "widgets/icon.h"
#include "ui/widget/dock.h"
#include "verbs.h"
#include "dialog.h"
#include "preferences.h"
-#include "dialogs/dialog-events.h"
+#include "ui/dialog-events.h"
#include <gtkmm/invisible.h>
#include <gtkmm/label.h>
diff --git a/src/ui/dialog/document-metadata.cpp b/src/ui/dialog/document-metadata.cpp
index 09c505860..77ea175d9 100644
--- a/src/ui/dialog/document-metadata.cpp
+++ b/src/ui/dialog/document-metadata.cpp
@@ -223,7 +223,7 @@ DocumentMetadata::_handleDocumentReplaced(SPDesktop* desktop, SPDocument *)
}
void
-DocumentMetadata::_handleActivateDesktop(Inkscape::Application *, SPDesktop *desktop)
+DocumentMetadata::_handleActivateDesktop(InkscapeApplication *, SPDesktop *desktop)
{
Inkscape::XML::Node *repr = sp_desktop_namedview(desktop)->getRepr();
repr->addListener(&_repr_events, this);
@@ -231,7 +231,7 @@ DocumentMetadata::_handleActivateDesktop(Inkscape::Application *, SPDesktop *des
}
void
-DocumentMetadata::_handleDeactivateDesktop(Inkscape::Application *, SPDesktop *desktop)
+DocumentMetadata::_handleDeactivateDesktop(InkscapeApplication *, SPDesktop *desktop)
{
Inkscape::XML::Node *repr = sp_desktop_namedview(desktop)->getRepr();
repr->removeListenerByData(this);
diff --git a/src/ui/dialog/document-metadata.h b/src/ui/dialog/document-metadata.h
index 3b7ed1ec8..77084bc3d 100644
--- a/src/ui/dialog/document-metadata.h
+++ b/src/ui/dialog/document-metadata.h
@@ -56,8 +56,8 @@ protected:
void init();
void _handleDocumentReplaced(SPDesktop* desktop, SPDocument *document);
- void _handleActivateDesktop(Inkscape::Application *application, SPDesktop *desktop);
- void _handleDeactivateDesktop(Inkscape::Application *application, SPDesktop *desktop);
+ void _handleActivateDesktop(InkscapeApplication *application, SPDesktop *desktop);
+ void _handleDeactivateDesktop(InkscapeApplication *application, SPDesktop *desktop);
Gtk::Notebook _notebook;
diff --git a/src/ui/dialog/document-properties.cpp b/src/ui/dialog/document-properties.cpp
index 67e788e21..6064c2a5e 100644
--- a/src/ui/dialog/document-properties.cpp
+++ b/src/ui/dialog/document-properties.cpp
@@ -31,13 +31,13 @@
#include "inkscape.h"
#include "io/sys.h"
#include "preferences.h"
-#include "shape-editor.h"
+#include "ui/shape-editor.h"
#include "sp-namedview.h"
#include "sp-root.h"
#include "sp-script.h"
#include "style.h"
#include "svg/stringstream.h"
-#include "tools-switch.h"
+#include "ui/tools-switch.h"
#include "ui/widget/color-picker.h"
#include "ui/widget/scalar-unit.h"
#include "ui/dialog/filedialog.h"
@@ -45,6 +45,7 @@
#include "widgets/icon.h"
#include "xml/node-event-vector.h"
#include "xml/repr.h"
+#include <algorithm> // std::min
#include "rdf.h"
#include "ui/widget/entity-entry.h"
@@ -596,6 +597,7 @@ void DocumentProperties::removeSelectedProfile(){
//XML Tree being used directly here while it shouldn't be.
sp_repr_unparent(obj->getRepr());
DocumentUndo::done(SP_ACTIVE_DOCUMENT, SP_VERB_EDIT_REMOVE_COLOR_PROFILE, _("Remove linked color profile"));
+ break; // removing the color profile likely invalidates part of the traversed list, stop traversing here.
}
current = g_slist_next(current);
}
@@ -1203,10 +1205,10 @@ void DocumentProperties::removeExternalScript(){
const GSList *current = SP_ACTIVE_DOCUMENT->getResourceList( "script" );
while ( current ) {
- if (current->data && SP_IS_OBJECT(current->data)) {
- SPObject* obj = SP_OBJECT(current->data);
- SPScript* script = SP_SCRIPT(obj);
- if (name == script->xlinkhref){
+ SPObject* obj = reinterpret_cast<SPObject *>(current->data);
+ if (obj) {
+ SPScript* script = dynamic_cast<SPScript *>(obj);
+ if (script && (name == script->xlinkhref)) {
//XML Tree being used directly here while it shouldn't be.
Inkscape::XML::Node *repr = obj->getRepr();
@@ -1236,23 +1238,16 @@ void DocumentProperties::removeEmbeddedScript(){
}
}
- const GSList *current = SP_ACTIVE_DOCUMENT->getResourceList( "script" );
- while ( current ) {
- if (current->data && SP_IS_OBJECT(current->data)) {
- SPObject* obj = SP_OBJECT(current->data);
- if (id == obj->getId()){
-
- //XML Tree being used directly here while it shouldn't be.
- Inkscape::XML::Node *repr = obj->getRepr();
- if (repr){
- sp_repr_unparent(repr);
+ SPObject* obj = SP_ACTIVE_DOCUMENT->getObjectById(id);
+ if (obj) {
+ //XML Tree being used directly here while it shouldn't be.
+ Inkscape::XML::Node *repr = obj->getRepr();
+ if (repr){
+ sp_repr_unparent(repr);
- // inform the document, so we can undo
- DocumentUndo::done(SP_ACTIVE_DOCUMENT, SP_VERB_EDIT_REMOVE_EMBEDDED_SCRIPT, _("Remove embedded script"));
- }
- }
+ // inform the document, so we can undo
+ DocumentUndo::done(SP_ACTIVE_DOCUMENT, SP_VERB_EDIT_REMOVE_EMBEDDED_SCRIPT, _("Remove embedded script"));
}
- current = g_slist_next(current);
}
populate_script_lists();
@@ -1359,10 +1354,15 @@ void DocumentProperties::populate_script_lists(){
_ExternalScriptsListStore->clear();
_EmbeddedScriptsListStore->clear();
const GSList *current = SP_ACTIVE_DOCUMENT->getResourceList( "script" );
- if (current) _scripts_observer.set(SP_OBJECT(current->data)->parent);
+ if (current) {
+ SPObject *obj = reinterpret_cast<SPObject *>(current->data);
+ g_assert(obj != NULL);
+ _scripts_observer.set(obj->parent);
+ }
while ( current ) {
- SPObject* obj = SP_OBJECT(current->data);
- SPScript* script = SP_SCRIPT(obj);
+ SPObject* obj = reinterpret_cast<SPObject *>(current->data);
+ SPScript* script = dynamic_cast<SPScript *>(obj);
+ g_assert(script != NULL);
if (script->xlinkhref)
{
Gtk::TreeModel::Row row = *(_ExternalScriptsListStore->append());
@@ -1599,7 +1599,7 @@ void DocumentProperties::_handleDocumentReplaced(SPDesktop* desktop, SPDocument
update();
}
-void DocumentProperties::_handleActivateDesktop(Inkscape::Application *, SPDesktop *desktop)
+void DocumentProperties::_handleActivateDesktop(InkscapeApplication *, SPDesktop *desktop)
{
Inkscape::XML::Node *repr = sp_desktop_namedview(desktop)->getRepr();
repr->addListener(&_repr_events, this);
@@ -1608,7 +1608,7 @@ void DocumentProperties::_handleActivateDesktop(Inkscape::Application *, SPDeskt
update();
}
-void DocumentProperties::_handleDeactivateDesktop(Inkscape::Application *, SPDesktop *desktop)
+void DocumentProperties::_handleDeactivateDesktop(InkscapeApplication *, SPDesktop *desktop)
{
Inkscape::XML::Node *repr = sp_desktop_namedview(desktop)->getRepr();
repr->removeListenerByData(this);
@@ -1741,14 +1741,19 @@ void DocumentProperties::onDocUnitChange()
prefs->setBool("/options/transform/gradient", true);
{
ShapeEditor::blockSetItem(true);
- gdouble viewscale = doc->getWidth().value("px")/doc->getRoot()->viewBox.width();
- if (doc->getHeight().value("px")/doc->getRoot()->viewBox.height() < viewscale)
- viewscale = doc->getHeight().value("px")/doc->getRoot()->viewBox.height();
+ gdouble viewscale = 1.0;
+ Geom::Rect vb = doc->getRoot()->viewBox;
+ if ( !vb.hasZeroArea() ) {
+ gdouble viewscale_w = doc->getWidth().value("px") / vb.width();
+ gdouble viewscale_h = doc->getHeight().value("px")/ vb.height();
+ viewscale = std::min(viewscale_h, viewscale_w);
+ }
gdouble scale = Inkscape::Util::Quantity::convert(1, old_doc_unit, doc_unit);
doc->getRoot()->scaleChildItemsRec(Geom::Scale(scale), Geom::Point(-viewscale*doc->getRoot()->viewBox.min()[Geom::X] +
(doc->getWidth().value("px") - viewscale*doc->getRoot()->viewBox.width())/2,
viewscale*doc->getRoot()->viewBox.min()[Geom::Y] +
- (doc->getHeight().value("px") + viewscale*doc->getRoot()->viewBox.height())/2));
+ (doc->getHeight().value("px") + viewscale*doc->getRoot()->viewBox.height())/2),
+ false);
ShapeEditor::blockSetItem(false);
}
prefs->setBool("/options/transform/stroke", transform_stroke);
diff --git a/src/ui/dialog/document-properties.h b/src/ui/dialog/document-properties.h
index 495f3177d..ee7e88b18 100644
--- a/src/ui/dialog/document-properties.h
+++ b/src/ui/dialog/document-properties.h
@@ -94,8 +94,8 @@ protected:
void save_default_metadata();
void _handleDocumentReplaced(SPDesktop* desktop, SPDocument *document);
- void _handleActivateDesktop(Inkscape::Application *application, SPDesktop *desktop);
- void _handleDeactivateDesktop(Inkscape::Application *application, SPDesktop *desktop);
+ void _handleActivateDesktop(InkscapeApplication *application, SPDesktop *desktop);
+ void _handleDeactivateDesktop(InkscapeApplication *application, SPDesktop *desktop);
Inkscape::XML::SignalObserver _emb_profiles_observer, _scripts_observer;
Gtk::Notebook _notebook;
diff --git a/src/ui/dialog/export.cpp b/src/ui/dialog/export.cpp
index 913713e5c..b044a6e2c 100644
--- a/src/ui/dialog/export.cpp
+++ b/src/ui/dialog/export.cpp
@@ -62,10 +62,10 @@
#include "sp-namedview.h"
#include "selection-chemistry.h"
-#include "dialogs/dialog-events.h"
+#include "ui/dialog-events.h"
#include "preferences.h"
#include "verbs.h"
-#include "interface.h"
+#include "ui/interface.h"
#include "sp-root.h"
#include "extension/output.h"
@@ -537,7 +537,7 @@ Gtk::Adjustment * Export::createSpinbutton( gchar const * /*key*/, float val, fl
sb->set_sensitive (sensitive);
pos++;
- if (!ll.empty()) {
+ if (l) {
l->set_mnemonic_widget(*sb);
}
diff --git a/src/ui/dialog/export.h b/src/ui/dialog/export.h
index 6f3c0dfac..23af0109b 100644
--- a/src/ui/dialog/export.h
+++ b/src/ui/dialog/export.h
@@ -12,20 +12,11 @@
#ifndef SP_EXPORT_H
#define SP_EXPORT_H
-#include <gtk/gtk.h>
-#include <glibmm/i18n.h>
-
-#include <gtkmm/comboboxtext.h>
-#include <gtkmm/expander.h>
-#include <gtkmm/frame.h>
#include <gtkmm/progressbar.h>
-#include <gtkmm/textview.h>
-#include "desktop.h"
#include "ui/dialog/desktop-tracker.h"
#include "ui/widget/panel.h"
#include "ui/widget/button.h"
-#include "ui/widget/entry.h"
namespace Gtk {
class Dialog;
diff --git a/src/ui/dialog/extension-editor.cpp b/src/ui/dialog/extension-editor.cpp
index cd5491c24..9bdddc0e0 100644
--- a/src/ui/dialog/extension-editor.cpp
+++ b/src/ui/dialog/extension-editor.cpp
@@ -25,7 +25,7 @@
#include "verbs.h"
#include "preferences.h"
-#include "interface.h"
+#include "ui/interface.h"
#include "extension/extension.h"
#include "extension/db.h"
diff --git a/src/ui/dialog/filedialog.cpp b/src/ui/dialog/filedialog.cpp
index e71605739..00ed09551 100644
--- a/src/ui/dialog/filedialog.cpp
+++ b/src/ui/dialog/filedialog.cpp
@@ -20,7 +20,7 @@
#include "filedialog.h"
#include "gc-core.h"
-#include <dialogs/dialog-events.h>
+#include "ui/dialog-events.h"
#include "extension/output.h"
#include "preferences.h"
diff --git a/src/ui/dialog/filedialog.h b/src/ui/dialog/filedialog.h
index 8dfcf5dce..175031bcf 100644
--- a/src/ui/dialog/filedialog.h
+++ b/src/ui/dialog/filedialog.h
@@ -48,6 +48,7 @@ typedef enum {
IMPORT_TYPES,
EXPORT_TYPES,
EXE_TYPES,
+ SWATCH_TYPES,
CUSTOM_TYPE
} FileDialogType;
diff --git a/src/ui/dialog/filedialogimpl-gtkmm.cpp b/src/ui/dialog/filedialogimpl-gtkmm.cpp
index 8ba3ad684..5d330f7f0 100644
--- a/src/ui/dialog/filedialogimpl-gtkmm.cpp
+++ b/src/ui/dialog/filedialogimpl-gtkmm.cpp
@@ -21,9 +21,11 @@
#include <config.h>
#endif
+#include <iostream>
+
#include "filedialogimpl-gtkmm.h"
-#include "dialogs/dialog-events.h"
-#include "interface.h"
+#include "ui/dialog-events.h"
+#include "ui/interface.h"
#include "io/sys.h"
#include "path-prefix.h"
#include "preferences.h"
@@ -40,6 +42,9 @@
#include <glibmm/i18n.h>
#include <glibmm/miscutils.h>
+#include <glibmm/regex.h>
+
+#include "document.h"
#include "extension/input.h"
#include "extension/output.h"
#include "extension/db.h"
@@ -190,6 +195,40 @@ void SVGPreview::showImage(Glib::ustring &theFileName)
{
Glib::ustring fileName = theFileName;
+ // Let's get real width and height from SVG file. These are template
+ // files so we assume they are well formed.
+
+ // std::cout << "SVGPreview::showImage: " << theFileName << std::endl;
+ std::ifstream input(theFileName.c_str());
+
+ std::string width;
+ std::string height;
+
+ if( !input ) {
+ std::cerr << "SVGPreview::showImage: Failed to open file: " << theFileName << std::endl;
+ } else {
+
+ std::string token;
+
+ Glib::MatchInfo match_info;
+ Glib::RefPtr<Glib::Regex> regex1 = Glib::Regex::create("width=\"(.*)\"");
+ Glib::RefPtr<Glib::Regex> regex2 = Glib::Regex::create("height=\"(.*)\"");
+
+ while( !input.eof() && (height.empty() || width.empty()) ) {
+
+ input >> token;
+ // std::cout << "|" << token << "|" << std::endl;
+
+ if (regex1->match(token, match_info)) {
+ width = match_info.fetch(1).raw();
+ }
+
+ if (regex2->match(token, match_info)) {
+ height = match_info.fetch(1).raw();
+ }
+
+ }
+ }
/*#####################################
# LET'S HAVE SOME FUN WITH SVG!
@@ -269,7 +308,7 @@ void SVGPreview::showImage(Glib::ustring &theFileName)
" style=\"font-size:24.000000;font-style:normal;font-weight:normal;"
" fill:#000000;fill-opacity:1.0000000;stroke:none;"
" font-family:Sans\"\n"
- " x=\"10\" y=\"26\">%d x %d</text>\n" //# VALUES HERE
+ " x=\"10\" y=\"26\">%s x %s</text>\n" //# VALUES HERE
"</svg>\n\n";
// if (!Glib::get_charset()) //If we are not utf8
@@ -279,7 +318,7 @@ void SVGPreview::showImage(Glib::ustring &theFileName)
/* FIXME: Do proper XML quoting for fileName. */
gchar *xmlBuffer =
g_strdup_printf(xformat, previewWidth, previewHeight, imgX, imgY, scaledImgWidth, scaledImgHeight,
- fileName.c_str(), rectX, rectY, rectWidth, rectHeight, imgWidth, imgHeight);
+ fileName.c_str(), rectX, rectY, rectWidth, rectHeight, width.c_str(), height.c_str() );
// g_message("%s\n", xmlBuffer);
diff --git a/src/ui/dialog/filedialogimpl-win32.cpp b/src/ui/dialog/filedialogimpl-win32.cpp
index 9d91f5d56..ee6a0ef3a 100644
--- a/src/ui/dialog/filedialogimpl-win32.cpp
+++ b/src/ui/dialog/filedialogimpl-win32.cpp
@@ -31,7 +31,7 @@
//Inkscape includes
#include "inkscape.h"
-#include "dialogs/dialog-events.h"
+#include "ui/dialog-events.h"
#include "extension/input.h"
#include "extension/output.h"
#include "extension/db.h"
@@ -72,13 +72,6 @@ const unsigned long MaxPreviewFileSize = 10240; // kB
#define IDC_SHOW_PREVIEW 1000
-// Windows 2000 version of OPENFILENAMEW
-struct OPENFILENAMEEXW : public OPENFILENAMEW {
- void * pvReserved;
- DWORD dwReserved;
- DWORD FlagsEx;
-};
-
struct Filter
{
gunichar2* name;
@@ -483,7 +476,7 @@ void FileOpenDialogImplWin32::createFilterMenu()
void FileOpenDialogImplWin32::GetOpenFileName_thread()
{
- OPENFILENAMEEXW ofn;
+ OPENFILENAMEW ofn;
g_assert(this != NULL);
g_assert(_mutex != NULL);
@@ -1829,7 +1822,7 @@ void FileSaveDialogImplWin32::addFileType(Glib::ustring name, Glib::ustring patt
void FileSaveDialogImplWin32::GetSaveFileName_thread()
{
- OPENFILENAMEEXW ofn;
+ OPENFILENAMEW ofn;
g_assert(this != NULL);
g_assert(_main_loop != NULL);
@@ -1860,7 +1853,6 @@ void FileSaveDialogImplWin32::GetSaveFileName_thread()
ofn.nFilterIndex = _filter_index;
ofn.lpfnHook = GetSaveFileName_hookproc;
ofn.lCustData = (LPARAM)this;
-
_result = GetSaveFileNameW(&ofn) != 0;
g_assert(ofn.nFilterIndex >= 1 && ofn.nFilterIndex <= _filter_count);
diff --git a/src/ui/dialog/filedialogimpl-win32.h b/src/ui/dialog/filedialogimpl-win32.h
index 29bcb9a45..f77249abd 100644
--- a/src/ui/dialog/filedialogimpl-win32.h
+++ b/src/ui/dialog/filedialogimpl-win32.h
@@ -13,16 +13,23 @@
# include "config.h"
#endif
+#include <glibmm.h>
+
#ifdef WIN32
#if WITH_GLIBMM_2_32
#if GLIBMM_DISABLE_DEPRECATED && HAVE_GLIBMM_THREADS_H
# include <glibmm/threads.h>
#endif
-
#endif
+
+#include "filedialogimpl-gtkmm.h"
+
#include "gc-core.h"
+ // define WINVER high enough so we get the correct OPENFILENAMEW size
+#ifndef WINVER
+#define WINVER 0x0500
+#endif
#include <windows.h>
-#include "filedialogimpl-gtkmm.h"
namespace Inkscape
diff --git a/src/ui/dialog/fill-and-stroke.h b/src/ui/dialog/fill-and-stroke.h
index 340cb860f..35c98ef9c 100644
--- a/src/ui/dialog/fill-and-stroke.h
+++ b/src/ui/dialog/fill-and-stroke.h
@@ -41,7 +41,7 @@ public:
virtual void setDesktop(SPDesktop *desktop);
- void selectionChanged(Inkscape::Application *inkscape,
+ void selectionChanged(InkscapeApplication *inkscape,
Inkscape::Selection *selection);
void showPageFill();
diff --git a/src/ui/dialog/filter-effects-dialog.cpp b/src/ui/dialog/filter-effects-dialog.cpp
index c2367c2a2..bd44846a3 100644
--- a/src/ui/dialog/filter-effects-dialog.cpp
+++ b/src/ui/dialog/filter-effects-dialog.cpp
@@ -546,7 +546,7 @@ public:
_matrix(SP_ATTR_VALUES, _("This matrix determines a linear transform on color space. Each line affects one of the color components. Each column determines how much of each color component from the input is passed to the output. The last column does not depend on input colors, so can be used to adjust a constant component value.")),
_saturation("", 0, 0, 1, 0.1, 0.01, 2, SP_ATTR_VALUES),
_angle("", 0, 0, 360, 0.1, 0.01, 1, SP_ATTR_VALUES),
- _label(_("None"), Gtk::ALIGN_START),
+ _label(C_("Label", "None"), Gtk::ALIGN_START),
_use_stored(false),
_saturation_store(0),
_angle_store(0)
diff --git a/src/ui/dialog/find.cpp b/src/ui/dialog/find.cpp
index 37f2761df..1a7832688 100644
--- a/src/ui/dialog/find.cpp
+++ b/src/ui/dialog/find.cpp
@@ -31,9 +31,9 @@
#include "selection.h"
#include "desktop-handles.h"
-#include "dialogs/dialog-events.h"
+#include "ui/dialog-events.h"
#include "verbs.h"
-#include "interface.h"
+#include "ui/interface.h"
#include "preferences.h"
#include "sp-text.h"
#include "sp-flowtext.h"
@@ -241,7 +241,7 @@ Find::Find()
Inkscape::Selection *selection = sp_desktop_selection (SP_ACTIVE_DESKTOP);
SPItem *item = selection->singleItem();
if (item) {
- if (SP_IS_TEXT(item) || SP_IS_FLOWTEXT(item)) {
+ if (dynamic_cast<SPText *>(item) || dynamic_cast<SPFlowtext *>(item)) {
gchar *str;
str = sp_te_get_string_multiline (item);
entry_find.getEntry()->set_text(str);
@@ -343,7 +343,7 @@ bool Find::item_text_match (SPItem *item, const gchar *find, bool exact, bool ca
return false;
}
- if (SP_IS_TEXT(item) || SP_IS_FLOWTEXT(item)) {
+ if (dynamic_cast<SPText *>(item) || dynamic_cast<SPFlowtext *>(item)) {
const gchar *item_text = sp_te_get_string_multiline (item);
if (item_text == NULL) {
return false;
@@ -388,7 +388,7 @@ bool Find::item_id_match (SPItem *item, const gchar *id, bool exact, bool casema
return false;
}
- if (SP_IS_STRING(item)) { // SPStrings have "on demand" ids which are useless for searching
+ if (dynamic_cast<SPString *>(item)) { // SPStrings have "on demand" ids which are useless for searching
return false;
}
@@ -561,11 +561,14 @@ GSList *Find::filter_fields (GSList *l, bool exact, bool casematch)
if (check_searchin_text.get_active()) {
for (GSList *i = in; i != NULL; i = i->next) {
- if (item_text_match (SP_ITEM(i->data), text, exact, casematch)) {
+ SPObject *obj = reinterpret_cast<SPObject *>(i->data);
+ SPItem *item = dynamic_cast<SPItem *>(obj);
+ g_assert(item != NULL);
+ if (item_text_match(item, text, exact, casematch)) {
if (!g_slist_find(out, i->data)) {
out = g_slist_prepend (out, i->data);
if (_action_replace) {
- item_text_match (SP_ITEM(i->data), text, exact, casematch, _action_replace);
+ item_text_match(item, text, exact, casematch, _action_replace);
}
}
}
@@ -581,11 +584,13 @@ GSList *Find::filter_fields (GSList *l, bool exact, bool casematch)
if (ids) {
for (GSList *i = in; i != NULL; i = i->next) {
- if (item_id_match (SP_ITEM(i->data), text, exact, casematch)) {
+ SPObject *obj = reinterpret_cast<SPObject *>(i->data);
+ SPItem *item = dynamic_cast<SPItem *>(obj);
+ if (item_id_match(item, text, exact, casematch)) {
if (!g_slist_find(out, i->data)) {
out = g_slist_prepend (out, i->data);
if (_action_replace) {
- item_id_match (SP_ITEM(i->data), text, exact, casematch, _action_replace);
+ item_id_match(item, text, exact, casematch, _action_replace);
}
}
}
@@ -595,12 +600,15 @@ GSList *Find::filter_fields (GSList *l, bool exact, bool casematch)
if (style) {
for (GSList *i = in; i != NULL; i = i->next) {
- if (item_style_match (SP_ITEM(i->data), text, exact, casematch)) {
+ SPObject *obj = reinterpret_cast<SPObject *>(i->data);
+ SPItem *item = dynamic_cast<SPItem *>(obj);
+ g_assert(item != NULL);
+ if (item_style_match(item, text, exact, casematch)) {
if (!g_slist_find(out, i->data))
if (!g_slist_find(out, i->data)) {
out = g_slist_prepend (out, i->data);
if (_action_replace) {
- item_style_match (SP_ITEM(i->data), text, exact, casematch, _action_replace);
+ item_style_match(item, text, exact, casematch, _action_replace);
}
}
}
@@ -610,11 +618,14 @@ GSList *Find::filter_fields (GSList *l, bool exact, bool casematch)
if (attrname) {
for (GSList *i = in; i != NULL; i = i->next) {
- if (item_attr_match (SP_ITEM(i->data), text, exact, casematch)) {
+ SPObject *obj = reinterpret_cast<SPObject *>(i->data);
+ SPItem *item = dynamic_cast<SPItem *>(obj);
+ g_assert(item != NULL);
+ if (item_attr_match(item, text, exact, casematch)) {
if (!g_slist_find(out, i->data)) {
out = g_slist_prepend (out, i->data);
if (_action_replace) {
- item_attr_match (SP_ITEM(i->data), text, exact, casematch, _action_replace);
+ item_attr_match(item, text, exact, casematch, _action_replace);
}
}
}
@@ -624,11 +635,14 @@ GSList *Find::filter_fields (GSList *l, bool exact, bool casematch)
if (attrvalue) {
for (GSList *i = in; i != NULL; i = i->next) {
- if (item_attrvalue_match (SP_ITEM(i->data), text, exact, casematch)) {
+ SPObject *obj = reinterpret_cast<SPObject *>(i->data);
+ SPItem *item = dynamic_cast<SPItem *>(obj);
+ g_assert(item != NULL);
+ if (item_attrvalue_match(item, text, exact, casematch)) {
if (!g_slist_find(out, i->data)) {
out = g_slist_prepend (out, i->data);
if (_action_replace) {
- item_attrvalue_match (SP_ITEM(i->data), text, exact, casematch, _action_replace);
+ item_attrvalue_match(item, text, exact, casematch, _action_replace);
}
}
}
@@ -638,11 +652,14 @@ GSList *Find::filter_fields (GSList *l, bool exact, bool casematch)
if (font) {
for (GSList *i = in; i != NULL; i = i->next) {
- if (item_font_match (SP_ITEM(i->data), text, exact, casematch)) {
+ SPObject *obj = reinterpret_cast<SPObject *>(i->data);
+ SPItem *item = dynamic_cast<SPItem *>(obj);
+ g_assert(item != NULL);
+ if (item_font_match(item, text, exact, casematch)) {
if (!g_slist_find(out, i->data)) {
out = g_slist_prepend (out, i->data);
if (_action_replace) {
- item_font_match (SP_ITEM(i->data), text, exact, casematch, _action_replace);
+ item_font_match(item, text, exact, casematch, _action_replace);
}
}
}
@@ -661,34 +678,34 @@ bool Find::item_type_match (SPItem *item)
{
bool all =check_alltypes.get_active();
- if ( SP_IS_RECT(item)) {
+ if ( dynamic_cast<SPRect *>(item)) {
return ( all ||check_rects.get_active());
- } else if (SP_IS_GENERICELLIPSE(item)) {
+ } else if (dynamic_cast<SPGenericEllipse *>(item)) {
return ( all || check_ellipses.get_active());
- } else if (SP_IS_STAR(item) || SP_IS_POLYGON(item)) {
+ } else if (dynamic_cast<SPStar *>(item) || dynamic_cast<SPPolygon *>(item)) {
return ( all || check_stars.get_active());
- } else if (SP_IS_SPIRAL(item)) {
+ } else if (dynamic_cast<SPSpiral *>(item)) {
return ( all || check_spirals.get_active());
- } else if (SP_IS_PATH(item) || SP_IS_LINE(item) || SP_IS_POLYLINE(item)) {
+ } else if (dynamic_cast<SPPath *>(item) || dynamic_cast<SPLine *>(item) || dynamic_cast<SPPolyLine *>(item)) {
return (all || check_paths.get_active());
- } else if (SP_IS_TEXT(item) || SP_IS_TSPAN(item) || SP_IS_TREF(item) || SP_IS_STRING(item)) {
+ } else if (dynamic_cast<SPText *>(item) || dynamic_cast<SPTSpan *>(item) || dynamic_cast<SPTRef *>(item) || dynamic_cast<SPString *>(item)) {
return (all || check_texts.get_active());
- } else if (SP_IS_GROUP(item) && !desktop->isLayer(item) ) { // never select layers!
+ } else if (dynamic_cast<SPGroup *>(item) && !desktop->isLayer(item) ) { // never select layers!
return (all || check_groups.get_active());
- } else if (SP_IS_USE(item)) {
+ } else if (dynamic_cast<SPUse *>(item)) {
return (all || check_clones.get_active());
- } else if (SP_IS_IMAGE(item)) {
+ } else if (dynamic_cast<SPImage *>(item)) {
return (all || check_images.get_active());
- } else if (SP_IS_OFFSET(item)) {
+ } else if (dynamic_cast<SPOffset *>(item)) {
return (all || check_offsets.get_active());
}
@@ -699,7 +716,10 @@ GSList *Find::filter_types (GSList *l)
{
GSList *n = NULL;
for (GSList *i = l; i != NULL; i = i->next) {
- if (item_type_match (SP_ITEM(i->data))) {
+ SPObject *obj = reinterpret_cast<SPObject *>(i->data);
+ SPItem *item = dynamic_cast<SPItem *>(obj);
+ g_assert(item != NULL);
+ if (item_type_match(item)) {
n = g_slist_prepend (n, i->data);
}
}
@@ -716,7 +736,7 @@ GSList *Find::filter_list (GSList *l, bool exact, bool casematch)
GSList *Find::all_items (SPObject *r, GSList *l, bool hidden, bool locked)
{
- if (SP_IS_DEFS(r)) {
+ if (dynamic_cast<SPDefs *>(r)) {
return l; // we're not interested in items in defs
}
@@ -725,8 +745,8 @@ GSList *Find::all_items (SPObject *r, GSList *l, bool hidden, bool locked)
}
for (SPObject *child = r->firstChild(); child; child = child->getNext()) {
- if (SP_IS_ITEM(child) && !child->cloned && !desktop->isLayer(SP_ITEM(child))) {
- SPItem *item = reinterpret_cast<SPItem *>(child);
+ SPItem *item = dynamic_cast<SPItem *>(child);
+ if (item && !child->cloned && !desktop->isLayer(item)) {
if ((hidden || !desktop->itemIsHidden(item)) && (locked || !item->isLocked())) {
l = g_slist_prepend (l, child);
}
@@ -739,16 +759,18 @@ GSList *Find::all_items (SPObject *r, GSList *l, bool hidden, bool locked)
GSList *Find::all_selection_items (Inkscape::Selection *s, GSList *l, SPObject *ancestor, bool hidden, bool locked)
{
for (GSList *i = (GSList *) s->itemList(); i != NULL; i = i->next) {
- if (SP_IS_ITEM (i->data) && !reinterpret_cast<SPItem *>(i->data)->cloned && !desktop->isLayer(SP_ITEM(i->data))) {
- SPItem *item = reinterpret_cast<SPItem *>(i->data);
+ SPObject *obj = reinterpret_cast<SPObject *>(i->data);
+ SPItem *item = dynamic_cast<SPItem *>(obj);
+ g_assert(item != NULL);
+ if (item && !item->cloned && !desktop->isLayer(item)) {
if (!ancestor || ancestor->isAncestorOf(item)) {
if ((hidden || !desktop->itemIsHidden(item)) && (locked || !item->isLocked())) {
l = g_slist_prepend (l, i->data);
}
}
}
- if (!ancestor || ancestor->isAncestorOf(SP_OBJECT (i->data))) {
- l = all_items (SP_OBJECT (i->data), l, hidden, locked);
+ if (!ancestor || ancestor->isAncestorOf(item)) {
+ l = all_items(item, l, hidden, locked);
}
}
return l;
@@ -831,7 +853,10 @@ void Find::onAction()
Inkscape::Selection *selection = sp_desktop_selection (desktop);
selection->clear();
selection->setList(n);
- scroll_to_show_item (desktop, SP_ITEM(n->data));
+ SPObject *obj = reinterpret_cast<SPObject *>(n->data);
+ SPItem *item = dynamic_cast<SPItem *>(obj);
+ g_assert(item != NULL);
+ scroll_to_show_item(desktop, item);
if (_action_replace) {
DocumentUndo::done(sp_desktop_document(desktop), SP_VERB_CONTEXT_TEXT, _("Replace text or property"));
diff --git a/src/ui/dialog/floating-behavior.cpp b/src/ui/dialog/floating-behavior.cpp
index dd07f009a..11db14801 100644
--- a/src/ui/dialog/floating-behavior.cpp
+++ b/src/ui/dialog/floating-behavior.cpp
@@ -28,8 +28,8 @@
#include "inkscape.h"
#include "desktop.h"
-#include "dialogs/dialog-events.h"
-#include "interface.h"
+#include "ui/dialog-events.h"
+#include "ui/interface.h"
#include "preferences.h"
#include "verbs.h"
diff --git a/src/ui/dialog/font-substitution.cpp b/src/ui/dialog/font-substitution.cpp
index bf9133086..db7bdf222 100644
--- a/src/ui/dialog/font-substitution.cpp
+++ b/src/ui/dialog/font-substitution.cpp
@@ -27,7 +27,7 @@
#include "document.h"
#include "selection.h"
-#include "dialogs/dialog-events.h"
+#include "ui/dialog-events.h"
#include "desktop-handles.h"
#include "selection-chemistry.h"
#include "preferences.h"
@@ -200,16 +200,16 @@ GSList * FontSubstitution::getFontReplacedItems(SPDocument* doc, Glib::ustring *
}
}
- if (style && style->text) {
+ if (style) {
gchar const *style_font = NULL;
- if (style->text->font_family.set)
- style_font = style->text->font_family.value;
- else if (style->text->font_specification.set)
- style_font = style->text->font_specification.value;
- else if (style->text->font_family.value)
- style_font = style->text->font_family.value;
- else if (style->text->font_specification.value)
- style_font = style->text->font_specification.value;
+ if (style->font_family.set)
+ style_font = style->font_family.value;
+ else if (style->font_specification.set)
+ style_font = style->font_specification.value;
+ else if (style->font_family.value)
+ style_font = style->font_family.value;
+ else if (style->font_specification.value)
+ style_font = style->font_specification.value;
if (style_font) {
if (has_visible_text(item)) {
diff --git a/src/ui/dialog/grid-arrange-tab.cpp b/src/ui/dialog/grid-arrange-tab.cpp
index 8c0a4dc66..1417b39fa 100644
--- a/src/ui/dialog/grid-arrange-tab.cpp
+++ b/src/ui/dialog/grid-arrange-tab.cpp
@@ -572,7 +572,7 @@ void GridArrangeTab::updateSelection()
## Experimental
##########################*/
-static void updateSelectionCallback(Inkscape::Application */*inkscape*/, Inkscape::Selection */*selection*/, GridArrangeTab *dlg)
+static void updateSelectionCallback(InkscapeApplication */*inkscape*/, Inkscape::Selection */*selection*/, GridArrangeTab *dlg)
{
dlg->updateSelection();
}
@@ -708,7 +708,7 @@ GridArrangeTab::GridArrangeTab(ArrangeDialog *parent)
HorizAlign = prefs->getInt("/dialogs/gridtiler/HorizAlign", 1);
// Anchor selection widget
- AlignLabel.set_label("Alignment:");
+ AlignLabel.set_label(_("Alignment:"));
AlignLabel.set_alignment(Gtk::ALIGN_START, Gtk::ALIGN_CENTER);
AlignmentSelector.setAlignment(HorizAlign, VertAlign);
AlignmentSelector.on_selectionChanged().connect(sigc::mem_fun(*this, &GridArrangeTab::Align_changed));
diff --git a/src/ui/dialog/grid-arrange-tab.h b/src/ui/dialog/grid-arrange-tab.h
index 9d6700b39..a137d1694 100644
--- a/src/ui/dialog/grid-arrange-tab.h
+++ b/src/ui/dialog/grid-arrange-tab.h
@@ -17,14 +17,16 @@
#ifndef INKSCAPE_UI_DIALOG_GRID_ARRANGE_TAB_H
#define INKSCAPE_UI_DIALOG_GRID_ARRANGE_TAB_H
-#include <gtkmm.h>
-
+#include "ui/widget/scalar-unit.h"
#include "ui/dialog/arrange-tab.h"
#include "ui/widget/anchor-selector.h"
-#include "ui/widget/scalar-unit.h"
#include "ui/widget/spinbutton.h"
+#include <gtkmm/checkbutton.h>
+#include <gtkmm/radiobutton.h>
+#include <gtkmm/radiobuttongroup.h>
+
namespace Inkscape {
namespace UI {
namespace Dialog {
diff --git a/src/ui/dialog/guides.cpp b/src/ui/dialog/guides.cpp
index 80740113c..4519a905f 100644
--- a/src/ui/dialog/guides.cpp
+++ b/src/ui/dialog/guides.cpp
@@ -28,7 +28,7 @@
#include "ui/tools/tool-base.h"
#include "widgets/desktop-widget.h"
#include <glibmm/i18n.h>
-#include "dialogs/dialog-events.h"
+#include "ui/dialog-events.h"
#include "message-context.h"
#include "xml/repr.h"
#include "verbs.h"
@@ -100,7 +100,7 @@ void GuidelinePropertiesDialog::_onOK()
double rad_angle = Geom::deg_to_rad( deg_angle );
normal = Geom::rot90(Geom::Point::polar(rad_angle, 1.0));
}
- sp_guide_set_normal(*_guide, normal, true);
+ _guide->set_normal(normal, true);
double const points_x = _spin_button_x.getValue("px");
double const points_y = _spin_button_y.getValue("px");
@@ -108,11 +108,11 @@ void GuidelinePropertiesDialog::_onOK()
if (!_mode)
newpos += _oldpos;
- sp_guide_moveto(*_guide, newpos, true);
+ _guide->moveto(newpos, true);
const gchar* name = g_strdup( _label_entry.getEntry()->get_text().c_str() );
- sp_guide_set_label(*_guide, name, true);
+ _guide->set_label(name, true);
g_free((gpointer) name);
#if WITH_GTKMM_3_0
@@ -124,7 +124,7 @@ void GuidelinePropertiesDialog::_onOK()
#endif
//TODO: why 257? verify this!
- sp_guide_set_color(*_guide, r, g, b, true);
+ _guide->set_color(r, g, b, true);
DocumentUndo::done(_guide->document, SP_VERB_NONE,
_("Set guide properties"));
@@ -295,16 +295,17 @@ void GuidelinePropertiesDialog::_setup() {
signal_response().connect(sigc::mem_fun(*this, &GuidelinePropertiesDialog::_response));
// initialize dialog
- _oldpos = _guide->point_on_line;
+ _oldpos = _guide->getPoint();
if (_guide->isVertical()) {
_oldangle = 90;
} else if (_guide->isHorizontal()) {
_oldangle = 0;
} else {
- _oldangle = Geom::rad_to_deg( std::atan2( - _guide->normal_to_line[Geom::X], _guide->normal_to_line[Geom::Y] ) );
+ _oldangle = Geom::rad_to_deg( std::atan2( - _guide->getNormal()[Geom::X], _guide->getNormal()[Geom::Y] ) );
}
{
+ // FIXME holy crap!!!
Inkscape::XML::Node *repr = _guide->getRepr();
const gchar *guide_id = repr->attribute("id");
gchar *label = g_strdup_printf(_("Guideline ID: %s"), guide_id);
@@ -312,7 +313,7 @@ void GuidelinePropertiesDialog::_setup() {
g_free(label);
}
{
- gchar *guide_description = sp_guide_description(_guide, false);
+ gchar *guide_description = _guide->description(false);
gchar *label = g_strdup_printf(_("Current: %s"), guide_description);
g_free(guide_description);
_label_descr.set_markup(label);
@@ -320,15 +321,15 @@ void GuidelinePropertiesDialog::_setup() {
}
// init name entry
- _label_entry.getEntry()->set_text(_guide->label ? _guide->label : "");
+ _label_entry.getEntry()->set_text(_guide->getLabel() ? _guide->getLabel() : "");
#if WITH_GTKMM_3_0
Gdk::RGBA c;
- c.set_rgba(((_guide->color>>24)&0xff) / 255.0, ((_guide->color>>16)&0xff) / 255.0, ((_guide->color>>8)&0xff) / 255.0);
+ c.set_rgba(((_guide->getColor()>>24)&0xff) / 255.0, ((_guide->getColor()>>16)&0xff) / 255.0, ((_guide->getColor()>>8)&0xff) / 255.0);
_color.set_rgba(c);
#else
Gdk::Color c;
- c.set_rgb_p(((_guide->color>>24)&0xff) / 255.0, ((_guide->color>>16)&0xff) / 255.0, ((_guide->color>>8)&0xff) / 255.0);
+ c.set_rgb_p(((_guide->getColor()>>24)&0xff) / 255.0, ((_guide->getColor()>>16)&0xff) / 255.0, ((_guide->getColor()>>8)&0xff) / 255.0);
_color.set_color(c);
#endif
diff --git a/src/ui/dialog/inkscape-preferences.cpp b/src/ui/dialog/inkscape-preferences.cpp
index d826ece09..75cfe5bfe 100644
--- a/src/ui/dialog/inkscape-preferences.cpp
+++ b/src/ui/dialog/inkscape-preferences.cpp
@@ -19,6 +19,7 @@
#include "inkscape-preferences.h"
#include <glibmm/i18n.h>
+#include <glibmm/markup.h>
#include <glibmm/miscutils.h>
#include <gtkmm/main.h>
#include <gtkmm/frame.h>
@@ -76,7 +77,8 @@ InkscapePreferences::InkscapePreferences()
: UI::Widget::Panel ("", "/dialogs/preferences", SP_VERB_DIALOG_DISPLAY),
_max_dialog_width(0),
_max_dialog_height(0),
- _current_page(0)
+ _current_page(0),
+ _init(true)
{
//get the width of a spinbutton
Inkscape::UI::Widget::SpinButton* sb = new Inkscape::UI::Widget::SpinButton;
@@ -232,6 +234,9 @@ static void StyleFromSelectionToTool(Glib::ustring const &prefs_path, StyleSwatc
if (!css) return;
+ // remove black-listed properties
+ css = sp_css_attr_unset_blacklist (css);
+
// only store text style for the text tool
if (prefs_path != "/tools/text") {
css = sp_css_attr_unset_text (css);
@@ -329,7 +334,7 @@ void InkscapePreferences::initPageTools()
_page_selector.add_line( true, "", _t_sel_trans_outl, "",
_("Show only a box outline of the objects when moving or transforming"));
_page_selector.add_group_header( _("Per-object selection cue"));
- _t_sel_cue_none.init ( _("None"), "/options/selcue/value", Inkscape::SelCue::NONE, false, 0);
+ _t_sel_cue_none.init ( C_("Selection cue", "None"), "/options/selcue/value", Inkscape::SelCue::NONE, false, 0);
_page_selector.add_line( true, "", _t_sel_cue_none, "",
_("No per-object selection indication"));
_t_sel_cue_mark.init ( _("Mark"), "/options/selcue/value", Inkscape::SelCue::MARK, true, &_t_sel_cue_none);
@@ -500,10 +505,12 @@ void InkscapePreferences::initPageTools()
_page_connector.add_line(false, "", _connector_ignore_text, "",
_("If on, connector attachment points will not be shown for text objects"));
+#ifdef WITH_LPETOOL
//LPETool
- // commented out, because the LPETool is not finished yet.
- //this->AddPage(_page_lpetool, _("LPE Tool"), iter_tools, PREFS_PAGE_TOOLS_LPETOOL);
- //this->AddNewObjectsStyle(_page_lpetool, "/tools/lpetool");
+ //disabled, because the LPETool is not finished yet.
+ this->AddPage(_page_lpetool, _("LPE Tool"), iter_tools, PREFS_PAGE_TOOLS_LPETOOL);
+ this->AddNewObjectsStyle(_page_lpetool, "/tools/lpetool");
+#endif // WITH_LPETOOL
}
void InkscapePreferences::initPageUI()
@@ -522,11 +529,11 @@ void InkscapePreferences::initPageUI()
_("Mongolian (mn)"), _("Nepali (ne)"), _("Norwegian Bokmål (nb)"), _("Norwegian Nynorsk (nn)"), _("Panjabi (pa)"),
_("Polish (pl)"), _("Portuguese (pt)"), _("Portuguese/Brazil (pt_BR)"), _("Romanian (ro)"), _("Russian (ru)"),
_("Serbian (sr)"), _("Serbian in Latin script (sr@latin)"), _("Slovak (sk)"), _("Slovenian (sl)"), _("Spanish (es)"), _("Spanish/Mexico (es_MX)"),
- _("Swedish (sv)"),_("Telugu (te_IN)"), _("Thai (th)"), _("Turkish (tr)"), _("Ukrainian (uk)"), _("Vietnamese (vi)")};
+ _("Swedish (sv)"),_("Telugu (te)"), _("Thai (th)"), _("Turkish (tr)"), _("Ukrainian (uk)"), _("Vietnamese (vi)")};
Glib::ustring langValues[] = {"", "sq", "am", "ar", "hy", "az", "eu", "be", "bg", "bn", "bn_BD", "br", "ca", "ca@valencia", "zh_CN", "zh_TW", "hr", "cs", "da", "nl",
"dz", "de", "el", "en", "en_AU", "en_CA", "en_GB", "en_US@piglatin", "eo", "et", "fa", "fi", "fr", "ga",
"gl", "he", "hu", "id", "it", "ja", "km", "rw", "ko", "lt", "lv", "mk", "mn", "ne", "nb", "nn", "pa",
- "pl", "pt", "pt_BR", "ro", "ru", "sr", "sr@latin", "sk", "sl", "es", "es_MX", "sv", "te_IN", "th", "tr", "uk", "vi" };
+ "pl", "pt", "pt_BR", "ro", "ru", "sr", "sr@latin", "sk", "sl", "es", "es_MX", "sv", "te", "th", "tr", "uk", "vi" };
{
// sorting languages according to translated name
@@ -638,7 +645,7 @@ void InkscapePreferences::initPageUI()
_win_save_viewport.init ( _("Save and restore documents viewport"), "/options/savedocviewport/value", true);
_win_zoom_resize.init ( _("Zoom when window is resized"), "/options/stickyzoom/value", false);
_win_show_close.init ( _("Show close button on dialogs"), "/dialogs/showclose", false);
- _win_ontop_none.init ( _("None"), "/options/transientpolicy/value", 0, false, 0);
+ _win_ontop_none.init ( C_("Dialog on top", "None"), "/options/transientpolicy/value", 0, false, 0);
_win_ontop_normal.init ( _("Normal"), "/options/transientpolicy/value", 1, true, &_win_ontop_none);
_win_ontop_agressive.init ( _("Aggressive"), "/options/transientpolicy/value", 2, false, &_win_ontop_none);
@@ -834,7 +841,7 @@ void InkscapePreferences::initPageIO()
_save_use_current_dir.init( _("Use current directory for \"Save As ...\""), "/dialogs/save_as/use_current_dir", true);
_page_io.add_line( false, "", _save_use_current_dir, "",
- _("When this option is on, the \"Save as...\" and \"Save a Copy\" dialogs will always open in the directory where the currently open document is; when it's off, each will open in the directory where you last saved a file using it"), true);
+ _("When this option is on, the \"Save as...\" and \"Save a Copy...\" dialogs will always open in the directory where the currently open document is; when it's off, each will open in the directory where you last saved a file using it"), true);
_misc_comment.init( _("Add label comments to printing output"), "/printing/debug/show-label-comments", false);
_page_io.add_line( false, "", _misc_comment, "",
@@ -1256,7 +1263,7 @@ void InkscapePreferences::initPageBehavior()
_page_steps.add_line( false, "", _steps_compass, "",
_("When on, angles are displayed with 0 at north, 0 to 360 range, positive clockwise; otherwise with 0 at east, -180 to 180 range, positive counterclockwise"));
int const num_items = 17;
- Glib::ustring labels[num_items] = {"90", "60", "45", "36", "30", "22.5", "18", "15", "12", "10", "7.5", "6", "3", "2", "1", "0.5", _("None")};
+ Glib::ustring labels[num_items] = {"90", "60", "45", "36", "30", "22.5", "18", "15", "12", "10", "7.5", "6", "3", "2", "1", "0.5", C_("Rotation angle", "None")};
int values[num_items] = {2, 3, 4, 5, 6, 8, 10, 12, 15, 18, 24, 30, 60, 90, 180, 360, 0};
_steps_rot_snap.set_size_request(_sb_width);
_steps_rot_snap.init("/options/rotationsnapsperpi/value", labels, values, num_items, 12);
@@ -1463,6 +1470,11 @@ void InkscapePreferences::initPageBitmaps()
_page_bitmaps.add_line( false, "", _importexport_import_res_override, "",
_("Use default bitmap resolution in favor of information from file"));
+ _page_bitmaps.add_group_header( _("Render"));
+ // rendering outlines for pixmap image tags
+ _rendering_image_outline.init( _("Images in Outline Mode"), "/options/rendering/imageinoutlinemode", false);
+ _page_bitmaps.add_line(false, "", _rendering_image_outline, "", _("When active will render images while in outline mode instead of a red box with an x. This is useful for manual tracing."));
+
this->AddPage(_page_bitmaps, _("Bitmaps"), PREFS_PAGE_BITMAPS);
}
@@ -1827,7 +1839,7 @@ void InkscapePreferences::initPageSpellcheck()
AspellDictInfoEnumeration *dels = aspell_dict_info_list_elements(dlist);
- languages.push_back(Glib::ustring(_("None")));
+ languages.push_back(Glib::ustring(C_("Spellchecker language", "None")));
langValues.push_back(Glib::ustring(""));
const AspellDictInfo *entry;
@@ -1993,6 +2005,7 @@ bool InkscapePreferences::PresentPage(const Gtk::TreeModel::iterator& iter)
Gtk::TreeModel::Row row = *iter;
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
int desired_page = prefs->getInt("/dialogs/preferences/page", 0);
+ _init = false;
if (desired_page == row[_page_list_columns._col_id])
{
if (desired_page >= PREFS_PAGE_TOOLS && desired_page <= PREFS_PAGE_TOOLS_CONNECTOR)
@@ -2042,8 +2055,11 @@ void InkscapePreferences::on_pagelist_selection_changed()
Gtk::TreeModel::Row row = *iter;
_current_page = row[_page_list_columns._col_page];
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- prefs->setInt("/dialogs/preferences/page", row[_page_list_columns._col_id]);
- _page_title.set_markup("<span size='large'><b>" + row[_page_list_columns._col_name] + "</b></span>");
+ if (!_init) {
+ prefs->setInt("/dialogs/preferences/page", row[_page_list_columns._col_id]);
+ }
+ Glib::ustring col_name_escaped = Glib::Markup::escape_text( row[_page_list_columns._col_name] );
+ _page_title.set_markup("<span size='large'><b>" + col_name_escaped + "</b></span>");
_page_frame.add(*_current_page);
_current_page->show();
while (Gtk::Main::events_pending())
diff --git a/src/ui/dialog/inkscape-preferences.h b/src/ui/dialog/inkscape-preferences.h
index da85b805d..dcea91741 100644
--- a/src/ui/dialog/inkscape-preferences.h
+++ b/src/ui/dialog/inkscape-preferences.h
@@ -292,6 +292,7 @@ protected:
UI::Widget::PrefCheckButton _show_filters_info_box;
UI::Widget::PrefCombo _dockbar_style;
UI::Widget::PrefCombo _switcher_style;
+ UI::Widget::PrefCheckButton _rendering_image_outline;
UI::Widget::PrefSpinButton _rendering_cache_size;
UI::Widget::PrefSpinButton _filter_multi_threaded;
@@ -531,6 +532,7 @@ private:
InkscapePreferences();
InkscapePreferences(InkscapePreferences const &d);
InkscapePreferences operator=(InkscapePreferences const &d);
+ bool _init;
};
} // namespace Dialog
@@ -543,9 +545,9 @@ private:
Local Variables:
mode:c++
c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0))
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
indent-tabs-mode:nil
fill-column:99
End:
*/
-// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/ui/dialog/input.cpp b/src/ui/dialog/input.cpp
index 4be6716a5..8343cd6fe 100644
--- a/src/ui/dialog/input.cpp
+++ b/src/ui/dialog/input.cpp
@@ -1622,7 +1622,7 @@ void InputDialogImpl::ConfPanel::setAxis(gint count)
if (barNum < count) {
row[axisColumns.value] = Glib::ustring::format(barNum+1);
} else {
- row[axisColumns.value] = _("None");
+ row[axisColumns.value] = C_("Input device axe", "None");
}
}
diff --git a/src/ui/dialog/layers.cpp b/src/ui/dialog/layers.cpp
index b5dac0595..65351cb68 100644
--- a/src/ui/dialog/layers.cpp
+++ b/src/ui/dialog/layers.cpp
@@ -926,9 +926,8 @@ LayersPanel::LayersPanel() :
// -------------------------------------------------------
{
- _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_RENAME, 0, "Rename", (int)BUTTON_RENAME ) );
- _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_DUPLICATE, 0, "Duplicate", (int)BUTTON_DUPLICATE ) );
_watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_NEW, 0, "New", (int)BUTTON_NEW ) );
+ _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_RENAME, 0, "Rename", (int)BUTTON_RENAME ) );
_popupMenu.append(*Gtk::manage(new Gtk::SeparatorMenuItem()));
@@ -944,9 +943,14 @@ LayersPanel::LayersPanel() :
_popupMenu.append(*Gtk::manage(new Gtk::SeparatorMenuItem()));
- _watchingNonTop.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_RAISE, INKSCAPE_ICON("go-up"), "Up", (int)BUTTON_UP ) );
- _watchingNonBottom.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_LOWER, INKSCAPE_ICON("go-down"), "Down", (int)BUTTON_DOWN ) );
+ _watchingNonTop.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_RAISE, INKSCAPE_ICON("layer-raise"), "Up", (int)BUTTON_UP ) );
+ _watchingNonBottom.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_LOWER, INKSCAPE_ICON("layer-lower"), "Down", (int)BUTTON_DOWN ) );
+ _popupMenu.append(*Gtk::manage(new Gtk::SeparatorMenuItem()));
+
+ _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_DUPLICATE, 0, "Duplicate", (int)BUTTON_DUPLICATE ) );
+ _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_DELETE, 0, "Delete", (int)BUTTON_DELETE ) );
+
_popupMenu.show_all_children();
}
// -------------------------------------------------------
diff --git a/src/ui/dialog/livepatheffect-add.cpp b/src/ui/dialog/livepatheffect-add.cpp
index b5f51d81d..c558eddaf 100644
--- a/src/ui/dialog/livepatheffect-add.cpp
+++ b/src/ui/dialog/livepatheffect-add.cpp
@@ -38,6 +38,7 @@ LivePathEffectAdd::LivePathEffectAdd() :
scrolled_window.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
scrolled_window.set_shadow_type(Gtk::SHADOW_IN);
scrolled_window.set_size_request(250, 200);
+ scrolled_window.set_can_focus();
/**
* Effect Store and Tree
@@ -83,10 +84,12 @@ LivePathEffectAdd::LivePathEffectAdd() :
add_action_widget(close_button, Gtk::RESPONSE_CLOSE);
add_action_widget(add_button, Gtk::RESPONSE_APPLY);
+
/**
* Signal handlers
*/
effectlist_treeview.signal_button_press_event().connect_notify( sigc::mem_fun(*this, &LivePathEffectAdd::onButtonEvent) );
+ effectlist_treeview.signal_key_press_event().connect_notify(sigc::mem_fun(*this, &LivePathEffectAdd::onKeyEvent));
close_button.signal_clicked().connect(sigc::mem_fun(*this, &LivePathEffectAdd::onClose));
add_button.signal_clicked().connect(sigc::mem_fun(*this, &LivePathEffectAdd::onAdd));
signal_delete_event().connect( sigc::bind_return(sigc::hide(sigc::mem_fun(*this, &LivePathEffectAdd::onClose)), true ) );
@@ -107,6 +110,16 @@ void LivePathEffectAdd::onClose()
hide();
}
+void LivePathEffectAdd::onKeyEvent(GdkEventKey* evt)
+{
+ if (evt->keyval == GDK_KEY_Return) {
+ onAdd();
+ }
+ if (evt->keyval == GDK_KEY_Escape) {
+ onClose();
+ }
+}
+
void LivePathEffectAdd::onButtonEvent(GdkEventButton* evt)
{
// Double click on tree is same as clicking the add button
@@ -135,6 +148,7 @@ void LivePathEffectAdd::show(SPDesktop *desktop)
dial.set_modal(true);
desktop->setWindowTransient (dial.gobj());
dial.property_destroy_with_parent() = true;
+ dial.effectlist_treeview.grab_focus();
dial.run();
}
diff --git a/src/ui/dialog/livepatheffect-add.h b/src/ui/dialog/livepatheffect-add.h
index 7fa766272..99ead878c 100644
--- a/src/ui/dialog/livepatheffect-add.h
+++ b/src/ui/dialog/livepatheffect-add.h
@@ -74,6 +74,10 @@ protected:
*/
void onButtonEvent(GdkEventButton* evt);
+ /**
+ * Key event
+ */
+ void onKeyEvent(GdkEventKey* evt);
private:
Gtk::TreeView effectlist_treeview;
diff --git a/src/ui/dialog/livepatheffect-editor.cpp b/src/ui/dialog/livepatheffect-editor.cpp
index 9a569725c..eb3857ee7 100644
--- a/src/ui/dialog/livepatheffect-editor.cpp
+++ b/src/ui/dialog/livepatheffect-editor.cpp
@@ -295,9 +295,8 @@ LivePathEffectEditor::onSelectionChanged(Inkscape::Selection *sel)
if ( sel && !sel->isEmpty() ) {
SPItem *item = sel->singleItem();
if ( item ) {
- if ( SP_IS_LPE_ITEM(item) ) {
- SPLPEItem *lpeitem = SP_LPE_ITEM(item);
-
+ SPLPEItem *lpeitem = dynamic_cast<SPLPEItem *>(item);
+ if ( lpeitem ) {
effect_list_reload(lpeitem);
current_lpeitem = lpeitem;
@@ -318,25 +317,28 @@ LivePathEffectEditor::onSelectionChanged(Inkscape::Selection *sel)
button_up.set_sensitive(false);
button_down.set_sensitive(false);
}
- } else if ( SP_IS_USE(item) ) {
- // test whether linked object is supported by the CLONE_ORIGINAL LPE
- SPItem *orig = SP_USE(item)->get_original();
- if ( SP_IS_SHAPE(orig) ||
- SP_IS_TEXT(orig) )
- {
- // Note that an SP_USE cannot have an LPE applied, so we only need to worry about the "add effect" case.
- set_sensitize_all(true);
- showText(_("Click add button to convert clone"));
- button_remove.set_sensitive(false);
- button_up.set_sensitive(false);
- button_down.set_sensitive(false);
+ } else {
+ SPUse *use = dynamic_cast<SPUse *>(item);
+ if ( use ) {
+ // test whether linked object is supported by the CLONE_ORIGINAL LPE
+ SPItem *orig = use->get_original();
+ if ( dynamic_cast<SPShape *>(orig) ||
+ dynamic_cast<SPText *>(orig) )
+ {
+ // Note that an SP_USE cannot have an LPE applied, so we only need to worry about the "add effect" case.
+ set_sensitize_all(true);
+ showText(_("Click add button to convert clone"));
+ button_remove.set_sensitive(false);
+ button_up.set_sensitive(false);
+ button_down.set_sensitive(false);
+ } else {
+ showText(_("Select a path or shape"));
+ set_sensitize_all(false);
+ }
} else {
showText(_("Select a path or shape"));
set_sensitize_all(false);
}
- } else {
- showText(_("Select a path or shape"));
- set_sensitize_all(false);
}
} else {
showText(_("Only one item can be selected"));
@@ -423,7 +425,7 @@ LivePathEffectEditor::onAdd()
if ( sel && !sel->isEmpty() ) {
SPItem *item = sel->singleItem();
if (item) {
- if ( SP_IS_LPE_ITEM(item) ) {
+ if ( dynamic_cast<SPLPEItem *>(item) ) {
// show effectlist dialog
using Inkscape::UI::Dialog::LivePathEffectAdd;
LivePathEffectAdd::show(current_desktop);
@@ -439,7 +441,7 @@ LivePathEffectEditor::onAdd()
}
// If item is a SPRect, convert it to path first:
- if ( SP_IS_RECT(item) ) {
+ if ( dynamic_cast<SPRect *>(item) ) {
sp_selected_path_to_curves(sel, current_desktop, false);
item = sel->singleItem(); // get new item
}
@@ -451,41 +453,43 @@ LivePathEffectEditor::onAdd()
lpe_list_locked = false;
onSelectionChanged(sel);
- }
- else if ( SP_IS_USE(item) ) {
- // item is a clone. do not show effectlist dialog.
- // convert to path, apply CLONE_ORIGINAL LPE, link it to the cloned path
-
- // test whether linked object is supported by the CLONE_ORIGINAL LPE
- SPItem *orig = SP_USE(item)->get_original();
- if ( SP_IS_SHAPE(orig) ||
- SP_IS_TEXT(orig) )
- {
- // select original
- sel->set(orig);
-
- // delete clone but remember its id and transform
- gchar *id = g_strdup(item->getRepr()->attribute("id"));
- gchar *transform = g_strdup(item->getRepr()->attribute("transform"));
- item->deleteObject(false);
- item = NULL;
-
- // run sp_selection_clone_original_path_lpe
- sp_selection_clone_original_path_lpe(current_desktop);
- SPItem *new_item = sel->singleItem();
- new_item->getRepr()->setAttribute("id", id);
- new_item->getRepr()->setAttribute("transform", transform);
- g_free(id);
- g_free(transform);
-
- /// \todo Add the LPE stack of the original path?
-
- SPDocument *doc = current_desktop->doc();
- DocumentUndo::done(doc, SP_VERB_DIALOG_LIVE_PATH_EFFECT,
- _("Create and apply Clone original path effect"));
-
- lpe_list_locked = false;
- onSelectionChanged(sel);
+ } else {
+ SPUse *use = dynamic_cast<SPUse *>(item);
+ if ( use ) {
+ // item is a clone. do not show effectlist dialog.
+ // convert to path, apply CLONE_ORIGINAL LPE, link it to the cloned path
+
+ // test whether linked object is supported by the CLONE_ORIGINAL LPE
+ SPItem *orig = use->get_original();
+ if ( dynamic_cast<SPShape *>(orig) ||
+ dynamic_cast<SPText *>(orig) )
+ {
+ // select original
+ sel->set(orig);
+
+ // delete clone but remember its id and transform
+ gchar *id = g_strdup(item->getRepr()->attribute("id"));
+ gchar *transform = g_strdup(item->getRepr()->attribute("transform"));
+ item->deleteObject(false);
+ item = NULL;
+
+ // run sp_selection_clone_original_path_lpe
+ sp_selection_clone_original_path_lpe(current_desktop);
+ SPItem *new_item = sel->singleItem();
+ new_item->getRepr()->setAttribute("id", id);
+ new_item->getRepr()->setAttribute("transform", transform);
+ g_free(id);
+ g_free(transform);
+
+ /// \todo Add the LPE stack of the original path?
+
+ SPDocument *doc = current_desktop->doc();
+ DocumentUndo::done(doc, SP_VERB_DIALOG_LIVE_PATH_EFFECT,
+ _("Create and apply Clone original path effect"));
+
+ lpe_list_locked = false;
+ onSelectionChanged(sel);
+ }
}
}
}
@@ -498,13 +502,14 @@ LivePathEffectEditor::onRemove()
Inkscape::Selection *sel = _getSelection();
if ( sel && !sel->isEmpty() ) {
SPItem *item = sel->singleItem();
- if ( item && SP_IS_LPE_ITEM(item) ) {
- SP_LPE_ITEM(item)->removeCurrentPathEffect(false);
+ SPLPEItem *lpeitem = dynamic_cast<SPLPEItem *>(item);
+ if ( lpeitem ) {
+ lpeitem->removeCurrentPathEffect(false);
DocumentUndo::done( sp_desktop_document(current_desktop), SP_VERB_DIALOG_LIVE_PATH_EFFECT,
_("Remove path effect") );
- effect_list_reload(SP_LPE_ITEM(item));
+ effect_list_reload(lpeitem);
}
}
@@ -515,7 +520,8 @@ void LivePathEffectEditor::onUp()
Inkscape::Selection *sel = _getSelection();
if ( sel && !sel->isEmpty() ) {
SPItem *item = sel->singleItem();
- if ( SPLPEItem *lpeitem = SP_LPE_ITEM(item) ) {
+ SPLPEItem *lpeitem = dynamic_cast<SPLPEItem *>(item);
+ if ( lpeitem ) {
lpeitem->upCurrentPathEffect();
DocumentUndo::done( sp_desktop_document(current_desktop), SP_VERB_DIALOG_LIVE_PATH_EFFECT,
@@ -531,7 +537,8 @@ void LivePathEffectEditor::onDown()
Inkscape::Selection *sel = _getSelection();
if ( sel && !sel->isEmpty() ) {
SPItem *item = sel->singleItem();
- if ( SPLPEItem *lpeitem = SP_LPE_ITEM(item) ) {
+ SPLPEItem *lpeitem = dynamic_cast<SPLPEItem *>(item);
+ if ( lpeitem ) {
lpeitem->downCurrentPathEffect();
DocumentUndo::done( sp_desktop_document(current_desktop), SP_VERB_DIALOG_LIVE_PATH_EFFECT,
diff --git a/src/ui/dialog/lpe-fillet-chamfer-properties.cpp b/src/ui/dialog/lpe-fillet-chamfer-properties.cpp
new file mode 100644
index 000000000..55a19fc51
--- /dev/null
+++ b/src/ui/dialog/lpe-fillet-chamfer-properties.cpp
@@ -0,0 +1,301 @@
+/**
+ * From the code of Liam P.White from his Power Stroke Knot dialog
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#if GLIBMM_DISABLE_DEPRECATED &&HAVE_GLIBMM_THREADS_H
+#include <glibmm/threads.h>
+#endif
+
+#include <gtkmm.h>
+#include "lpe-fillet-chamfer-properties.h"
+#include <boost/lexical_cast.hpp>
+#include <glibmm/main.h>
+#include <glibmm/i18n.h>
+#include "inkscape.h"
+#include "desktop.h"
+#include "document.h"
+#include "document-undo.h"
+#include "layer-manager.h"
+#include "message-stack.h"
+#include "desktop-handles.h"
+#include "sp-object.h"
+#include "sp-item.h"
+#include "verbs.h"
+#include "selection.h"
+#include "selection-chemistry.h"
+#include "ui/icon-names.h"
+#include "ui/widget/imagetoggler.h"
+#include "util/units.h"
+#include <cmath>
+
+//#include "event-context.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Dialogs {
+
+FilletChamferPropertiesDialog::FilletChamferPropertiesDialog()
+ : _desktop(NULL), _knotpoint(NULL), _position_visible(false)
+{
+ Gtk::Box *mainVBox = get_vbox();
+ mainVBox->set_homogeneous(false);
+ _layout_table.set_spacings(4);
+ _layout_table.resize(3, 3);
+
+ // Layer name widgets
+ _fillet_chamfer_position_numeric.set_digits(4);
+ _fillet_chamfer_position_numeric.set_increments(1,1);
+ //todo: get tha max aloable infinity freeze the widget
+ _fillet_chamfer_position_numeric.set_range(0., 999999999999999999.);
+
+ _fillet_chamfer_position_label.set_label(_("Radius (pixels):"));
+ _fillet_chamfer_position_label.set_alignment(1.0, 0.5);
+
+ _layout_table.attach(_fillet_chamfer_position_label, 0, 1, 0, 1, Gtk::FILL,
+ Gtk::FILL);
+ _layout_table.attach(_fillet_chamfer_position_numeric, 1, 2, 0, 1,
+ Gtk::FILL | Gtk::EXPAND, Gtk::FILL);
+ _fillet_chamfer_chamfer_subdivisions.set_digits(0);
+ _fillet_chamfer_chamfer_subdivisions.set_increments(1,1);
+ //todo: get tha max aloable infinity freeze the widget
+ _fillet_chamfer_chamfer_subdivisions.set_range(0, 999999999999999999.0);
+
+ _fillet_chamfer_chamfer_subdivisions_label.set_label(_("Chamfer subdivisions:"));
+ _fillet_chamfer_chamfer_subdivisions_label.set_alignment(1.0, 0.5);
+
+ _layout_table.attach(_fillet_chamfer_chamfer_subdivisions_label, 0, 1, 1, 2, Gtk::FILL,
+ Gtk::FILL);
+ _layout_table.attach(_fillet_chamfer_chamfer_subdivisions, 1, 2, 1, 2,
+ Gtk::FILL | Gtk::EXPAND, Gtk::FILL);
+ _fillet_chamfer_type_fillet.set_label(_("Fillet"));
+ _fillet_chamfer_type_fillet.set_group(_fillet_chamfer_type_group);
+ _fillet_chamfer_type_inverse_fillet.set_label(_("Inverse fillet"));
+ _fillet_chamfer_type_inverse_fillet.set_group(_fillet_chamfer_type_group);
+ _fillet_chamfer_type_chamfer.set_label(_("Chamfer"));
+ _fillet_chamfer_type_chamfer.set_group(_fillet_chamfer_type_group);
+ _fillet_chamfer_type_inverse_chamfer.set_label(_("Inverse chamfer"));
+ _fillet_chamfer_type_inverse_chamfer.set_group(_fillet_chamfer_type_group);
+
+
+ mainVBox->pack_start(_layout_table, true, true, 4);
+ mainVBox->pack_start(_fillet_chamfer_type_fillet, true, true, 4);
+ mainVBox->pack_start(_fillet_chamfer_type_inverse_fillet, true, true, 4);
+ mainVBox->pack_start(_fillet_chamfer_type_chamfer, true, true, 4);
+ mainVBox->pack_start(_fillet_chamfer_type_inverse_chamfer, true, true, 4);
+
+ // Buttons
+ _close_button.set_use_stock(true);
+ _close_button.set_label(Gtk::Stock::CANCEL.id);
+ _close_button.set_can_default();
+
+ _apply_button.set_use_underline(true);
+ _apply_button.set_can_default();
+
+ _close_button.signal_clicked()
+ .connect(sigc::mem_fun(*this, &FilletChamferPropertiesDialog::_close));
+ _apply_button.signal_clicked()
+ .connect(sigc::mem_fun(*this, &FilletChamferPropertiesDialog::_apply));
+
+ signal_delete_event().connect(sigc::bind_return(
+ sigc::hide(sigc::mem_fun(*this, &FilletChamferPropertiesDialog::_close)),
+ true));
+
+ add_action_widget(_close_button, Gtk::RESPONSE_CLOSE);
+ add_action_widget(_apply_button, Gtk::RESPONSE_APPLY);
+
+ _apply_button.grab_default();
+
+ show_all_children();
+
+ set_focus(_fillet_chamfer_position_numeric);
+}
+
+FilletChamferPropertiesDialog::~FilletChamferPropertiesDialog()
+{
+
+ _set_desktop(NULL);
+}
+
+void FilletChamferPropertiesDialog::showDialog(
+ SPDesktop *desktop, Geom::Point knotpoint,
+ const Inkscape::LivePathEffect::
+ FilletChamferPointArrayParamKnotHolderEntity *pt,
+ const gchar *unit,
+ bool use_distance,
+ bool aprox_radius,
+ Glib::ustring const * documentUnit)
+{
+ FilletChamferPropertiesDialog *dialog = new FilletChamferPropertiesDialog();
+
+ dialog->_set_desktop(desktop);
+ dialog->_set_unit(unit);
+ dialog->_set_use_distance(use_distance);
+ dialog->_set_aprox(aprox_radius);
+ dialog->_set_document_unit(documentUnit);
+ dialog->_set_knot_point(knotpoint);
+ dialog->_set_pt(pt);
+
+ dialog->set_title(_("Modify Fillet-Chamfer"));
+ dialog->_apply_button.set_label(_("_Modify"));
+
+ dialog->set_modal(true);
+ desktop->setWindowTransient(dialog->gobj());
+ dialog->property_destroy_with_parent() = true;
+
+ dialog->show();
+ dialog->present();
+}
+
+void FilletChamferPropertiesDialog::_apply()
+{
+ double d_width;
+ double d_pos = _fillet_chamfer_position_numeric.get_value();
+ if (d_pos) {
+ if (_fillet_chamfer_type_fillet.get_active() == true) {
+ d_width = 1;
+ } else if (_fillet_chamfer_type_inverse_fillet.get_active() == true) {
+ d_width = 2;
+ } else if (_fillet_chamfer_type_inverse_chamfer.get_active() == true) {
+ d_width = _fillet_chamfer_chamfer_subdivisions.get_value() + 4000;
+ } else {
+ d_width = _fillet_chamfer_chamfer_subdivisions.get_value() + 3000;
+ }
+ if (_flexible) {
+ if (d_pos > 99.99999 || d_pos < 0) {
+ d_pos = 0;
+ }
+ d_pos = _index + (d_pos / 100);
+ } else {
+ d_pos = Inkscape::Util::Quantity::convert(d_pos, unit, *document_unit);
+ d_pos = d_pos * -1;
+ }
+ _knotpoint->knot_set_offset(Geom::Point(d_pos, d_width));
+ }
+ _close();
+}
+
+void FilletChamferPropertiesDialog::_close()
+{
+ _set_desktop(NULL);
+ destroy_();
+ Glib::signal_idle().connect(
+ sigc::bind_return(
+ sigc::bind(sigc::ptr_fun(&::operator delete), this),
+ false
+ )
+ );
+}
+
+bool FilletChamferPropertiesDialog::_handleKeyEvent(GdkEventKey * /*event*/)
+{
+ return false;
+}
+
+void FilletChamferPropertiesDialog::_handleButtonEvent(GdkEventButton *event)
+{
+ if ((event->type == GDK_2BUTTON_PRESS) && (event->button == 1)) {
+ _apply();
+ }
+}
+
+void FilletChamferPropertiesDialog::_set_knot_point(Geom::Point knotpoint)
+{
+ double position;
+ std::string distance_or_radius = std::string(_("Radius "));
+ if(aprox){
+ distance_or_radius = std::string(_("Radius approximated "));
+ }
+ if(use_distance){
+ distance_or_radius = std::string(_("Knot distance "));
+ }
+ if (knotpoint.x() > 0) {
+ double intpart;
+ position = modf(knotpoint[Geom::X], &intpart) * 100;
+ _flexible = true;
+ _index = intpart;
+ _fillet_chamfer_position_label.set_label(_("Position (%):"));
+ } else {
+ _flexible = false;
+ std::string posConcat = distance_or_radius +
+ std::string(_("(")) + std::string(unit) + std::string(")");
+ _fillet_chamfer_position_label.set_label(_(posConcat.c_str()));
+ position = knotpoint[Geom::X] * -1;
+
+ position = Inkscape::Util::Quantity::convert(position, *document_unit, unit);
+ }
+ _fillet_chamfer_position_numeric.set_value(position);
+ if (knotpoint.y() == 1) {
+ _fillet_chamfer_type_fillet.set_active(true);
+ } else if (knotpoint.y() == 2) {
+ _fillet_chamfer_type_inverse_fillet.set_active(true);
+ } else if (knotpoint.y() >= 3000 && knotpoint.y() < 4000) {
+ _fillet_chamfer_chamfer_subdivisions.set_value(knotpoint.y() - 3000);
+ _fillet_chamfer_type_chamfer.set_active(true);
+ } else if (knotpoint.y() >= 4000 && knotpoint.y() < 5000) {
+ _fillet_chamfer_chamfer_subdivisions.set_value(knotpoint.y() - 4000);
+ _fillet_chamfer_type_inverse_chamfer.set_active(true);
+ }
+}
+
+void FilletChamferPropertiesDialog::_set_pt(
+ const Inkscape::LivePathEffect::
+ FilletChamferPointArrayParamKnotHolderEntity *pt)
+{
+ _knotpoint = const_cast<
+ Inkscape::LivePathEffect::FilletChamferPointArrayParamKnotHolderEntity *>(
+ pt);
+}
+
+void FilletChamferPropertiesDialog::_set_unit(const gchar *abbr)
+{
+ unit = abbr;
+}
+
+void FilletChamferPropertiesDialog::_set_document_unit(Glib::ustring const *abbr)
+{
+ document_unit = abbr;
+}
+
+void FilletChamferPropertiesDialog::_set_use_distance(bool use_knot_distance)
+{
+ use_distance = use_knot_distance;
+}
+
+void FilletChamferPropertiesDialog::_set_aprox(bool aprox_radius)
+{
+ aprox = aprox_radius;
+}
+
+void FilletChamferPropertiesDialog::_set_desktop(SPDesktop *desktop)
+{
+ if (desktop) {
+ Inkscape::GC::anchor(desktop);
+ }
+ if (_desktop) {
+ Inkscape::GC::release(_desktop);
+ }
+ _desktop = desktop;
+}
+
+} // namespace
+} // namespace
+} // namespace
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim:
+// filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99
+// :
diff --git a/src/ui/dialog/lpe-fillet-chamfer-properties.h b/src/ui/dialog/lpe-fillet-chamfer-properties.h
new file mode 100644
index 000000000..3807e98c8
--- /dev/null
+++ b/src/ui/dialog/lpe-fillet-chamfer-properties.h
@@ -0,0 +1,115 @@
+/**
+ *
+ * From the code of Liam P.White from his Power Stroke Knot dialog
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information
+ */
+
+#ifndef INKSCAPE_DIALOG_FILLET_CHAMFER_PROPERTIES_H
+#define INKSCAPE_DIALOG_FILLET_CHAMFER_PROPERTIES_H
+
+#include <2geom/point.h>
+#include <gtkmm.h>
+#include "live_effects/parameter/filletchamferpointarray.h"
+
+class SPDesktop;
+
+namespace Inkscape {
+namespace UI {
+namespace Dialogs {
+
+class FilletChamferPropertiesDialog : public Gtk::Dialog {
+public:
+ FilletChamferPropertiesDialog();
+ virtual ~FilletChamferPropertiesDialog();
+
+ Glib::ustring getName() const {
+ return "LayerPropertiesDialog";
+ }
+
+ static void showDialog(SPDesktop *desktop, Geom::Point knotpoint,
+ const Inkscape::LivePathEffect::
+ FilletChamferPointArrayParamKnotHolderEntity *pt,
+ const gchar *unit,
+ bool use_distance,
+ bool aprox_radius,
+ Glib::ustring const * documentUnit);
+
+protected:
+
+ SPDesktop *_desktop;
+ Inkscape::LivePathEffect::FilletChamferPointArrayParamKnotHolderEntity *
+ _knotpoint;
+
+ Gtk::Label _fillet_chamfer_position_label;
+ Gtk::SpinButton _fillet_chamfer_position_numeric;
+ Gtk::RadioButton::Group _fillet_chamfer_type_group;
+ Gtk::RadioButton _fillet_chamfer_type_fillet;
+ Gtk::RadioButton _fillet_chamfer_type_inverse_fillet;
+ Gtk::RadioButton _fillet_chamfer_type_chamfer;
+ Gtk::RadioButton _fillet_chamfer_type_inverse_chamfer;
+ Gtk::Label _fillet_chamfer_chamfer_subdivisions_label;
+ Gtk::SpinButton _fillet_chamfer_chamfer_subdivisions;
+
+ Gtk::Table _layout_table;
+ bool _position_visible;
+ double _index;
+
+ Gtk::Button _close_button;
+ Gtk::Button _apply_button;
+
+ sigc::connection _destroy_connection;
+
+ static FilletChamferPropertiesDialog &_instance() {
+ static FilletChamferPropertiesDialog instance;
+ return instance;
+ }
+
+ void _set_desktop(SPDesktop *desktop);
+ void _set_pt(const Inkscape::LivePathEffect::
+ FilletChamferPointArrayParamKnotHolderEntity *pt);
+ void _set_unit(const gchar *abbr);
+ void _set_document_unit(Glib::ustring const * abbr);
+ void _set_use_distance(bool use_knot_distance);
+ void _set_aprox(bool aprox_radius);
+ void _apply();
+ void _close();
+ bool _flexible;
+ const gchar *unit;
+ Glib::ustring const * document_unit;
+ bool use_distance;
+ bool aprox;
+ void _set_knot_point(Geom::Point knotpoint);
+ void _prepareLabelRenderer(Gtk::TreeModel::const_iterator const &row);
+
+ bool _handleKeyEvent(GdkEventKey *event);
+ void _handleButtonEvent(GdkEventButton *event);
+
+ friend class Inkscape::LivePathEffect::
+ FilletChamferPointArrayParamKnotHolderEntity;
+
+private:
+ FilletChamferPropertiesDialog(
+ FilletChamferPropertiesDialog const &); // no copy
+ FilletChamferPropertiesDialog &operator=(
+ FilletChamferPropertiesDialog const &); // no assign
+};
+
+} // namespace
+} // namespace
+} // namespace
+
+#endif //INKSCAPE_DIALOG_LAYER_PROPERTIES_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim:
+// filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99
+// :
diff --git a/src/ui/dialog/lpe-powerstroke-properties.cpp b/src/ui/dialog/lpe-powerstroke-properties.cpp
new file mode 100644
index 000000000..55f938a48
--- /dev/null
+++ b/src/ui/dialog/lpe-powerstroke-properties.cpp
@@ -0,0 +1,211 @@
+/**
+ * @file
+ * Dialog for renaming layers.
+ */
+/* Author:
+ * Bryce W. Harrington <bryce@bryceharrington.com>
+ * Andrius R. <knutux@gmail.com>
+ * Abhishek Sharma
+ *
+ * Copyright (C) 2004 Bryce Harrington
+ * Copyright (C) 2006 Andrius R.
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#if GLIBMM_DISABLE_DEPRECATED && HAVE_GLIBMM_THREADS_H
+#include <glibmm/threads.h>
+#endif
+
+#include "lpe-powerstroke-properties.h"
+#include <boost/lexical_cast.hpp>
+#include <gtkmm/stock.h>
+#include <glibmm/main.h>
+#include <glibmm/i18n.h>
+#include "inkscape.h"
+#include "desktop.h"
+#include "document.h"
+#include "document-undo.h"
+#include "layer-manager.h"
+#include "message-stack.h"
+#include "desktop-handles.h"
+#include "sp-object.h"
+#include "sp-item.h"
+#include "verbs.h"
+#include "selection.h"
+#include "selection-chemistry.h"
+#include "ui/icon-names.h"
+#include "ui/widget/imagetoggler.h"
+//#include "event-context.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Dialogs {
+
+PowerstrokePropertiesDialog::PowerstrokePropertiesDialog()
+: _desktop(NULL), _knotpoint(NULL), _position_visible(false)
+{
+ Gtk::Box *mainVBox = get_vbox();
+
+ _layout_table.set_spacings(4);
+ _layout_table.resize (2, 2);
+
+ // Layer name widgets
+ _powerstroke_position_entry.set_activates_default(true);
+ _powerstroke_position_label.set_label(_("Position:"));
+ _powerstroke_position_label.set_alignment(1.0, 0.5);
+
+ _powerstroke_width_entry.set_activates_default(true);
+ _powerstroke_width_label.set_label(_("Width:"));
+ _powerstroke_width_label.set_alignment(1.0, 0.5);
+
+ _layout_table.attach(_powerstroke_position_label,
+ 0, 1, 0, 1, Gtk::FILL, Gtk::FILL);
+ _layout_table.attach(_powerstroke_position_entry,
+ 1, 2, 0, 1, Gtk::FILL | Gtk::EXPAND, Gtk::FILL);
+
+ _layout_table.attach(_powerstroke_width_label, 0, 1, 1, 2, Gtk::FILL, Gtk::FILL);
+ _layout_table.attach(_powerstroke_width_entry, 1, 2, 1, 2, Gtk::FILL | Gtk::EXPAND, Gtk::FILL);
+
+ mainVBox->pack_start(_layout_table, true, true, 4);
+
+ // Buttons
+ _close_button.set_use_stock(true);
+ _close_button.set_label(Gtk::Stock::CANCEL.id);
+ _close_button.set_can_default();
+
+ _apply_button.set_use_underline(true);
+ _apply_button.set_can_default();
+
+ _close_button.signal_clicked()
+ .connect(sigc::mem_fun(*this, &PowerstrokePropertiesDialog::_close));
+ _apply_button.signal_clicked()
+ .connect(sigc::mem_fun(*this, &PowerstrokePropertiesDialog::_apply));
+
+ signal_delete_event().connect(
+ sigc::bind_return(
+ sigc::hide(sigc::mem_fun(*this, &PowerstrokePropertiesDialog::_close)),
+ true
+ )
+ );
+
+ add_action_widget(_close_button, Gtk::RESPONSE_CLOSE);
+ add_action_widget(_apply_button, Gtk::RESPONSE_APPLY);
+
+ _apply_button.grab_default();
+
+ show_all_children();
+
+ set_focus(_powerstroke_width_entry);
+}
+
+PowerstrokePropertiesDialog::~PowerstrokePropertiesDialog() {
+
+ _setDesktop(NULL);
+}
+
+void PowerstrokePropertiesDialog::showDialog(SPDesktop *desktop, Geom::Point knotpoint, const Inkscape::LivePathEffect::PowerStrokePointArrayParamKnotHolderEntity *pt)
+{
+ PowerstrokePropertiesDialog *dialog = new PowerstrokePropertiesDialog();
+
+ dialog->_setDesktop(desktop);
+ dialog->_setKnotPoint(knotpoint);
+ dialog->_setPt(pt);
+
+ dialog->set_title(_("Modify Node Position"));
+ dialog->_apply_button.set_label(_("_Move"));
+
+ dialog->set_modal(true);
+ desktop->setWindowTransient (dialog->gobj());
+ dialog->property_destroy_with_parent() = true;
+
+ dialog->show();
+ dialog->present();
+}
+
+void
+PowerstrokePropertiesDialog::_apply()
+{
+ std::istringstream i_pos(_powerstroke_position_entry.get_text());
+ std::istringstream i_width(_powerstroke_width_entry.get_text());
+ double d_pos, d_width;
+ if ((i_pos >> d_pos) && i_width >> d_width) {
+ _knotpoint->knot_set_offset(Geom::Point(d_pos, d_width));
+ }
+ _close();
+}
+
+void
+PowerstrokePropertiesDialog::_close()
+{
+ _setDesktop(NULL);
+ destroy_();
+ Glib::signal_idle().connect(
+ sigc::bind_return(
+ sigc::bind(sigc::ptr_fun(&::operator delete), this),
+ false
+ )
+ );
+}
+
+bool PowerstrokePropertiesDialog::_handleKeyEvent(GdkEventKey * /*event*/)
+{
+
+ /*switch (get_group0_keyval(event)) {
+ case GDK_KEY_Return:
+ case GDK_KEY_KP_Enter: {
+ _apply();
+ return true;
+ }
+ break;
+ }*/
+ return false;
+}
+
+void PowerstrokePropertiesDialog::_handleButtonEvent(GdkEventButton* event)
+{
+ if ( (event->type == GDK_2BUTTON_PRESS) && (event->button == 1) ) {
+ _apply();
+ }
+}
+
+void PowerstrokePropertiesDialog::_setKnotPoint(Geom::Point knotpoint)
+{
+ _powerstroke_position_entry.set_text(boost::lexical_cast<std::string>(knotpoint.x()));
+ _powerstroke_width_entry.set_text(boost::lexical_cast<std::string>(knotpoint.y()));
+}
+
+void PowerstrokePropertiesDialog::_setPt(const Inkscape::LivePathEffect::PowerStrokePointArrayParamKnotHolderEntity *pt)
+{
+ _knotpoint = const_cast<Inkscape::LivePathEffect::PowerStrokePointArrayParamKnotHolderEntity *>(pt);
+}
+
+void PowerstrokePropertiesDialog::_setDesktop(SPDesktop *desktop) {
+ if (desktop) {
+ Inkscape::GC::anchor (desktop);
+ }
+ if (_desktop) {
+ Inkscape::GC::release (_desktop);
+ }
+ _desktop = desktop;
+}
+
+} // namespace
+} // namespace
+} // namespace
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/ui/dialog/lpe-powerstroke-properties.h b/src/ui/dialog/lpe-powerstroke-properties.h
new file mode 100644
index 000000000..c53eac0d9
--- /dev/null
+++ b/src/ui/dialog/lpe-powerstroke-properties.h
@@ -0,0 +1,99 @@
+/** @file
+ * @brief Dialog for renaming layers
+ */
+/* Author:
+ * Bryce W. Harrington <bryce@bryceharrington.com>
+ *
+ * Copyright (C) 2004 Bryce Harrington
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information
+ */
+
+#ifndef INKSCAPE_DIALOG_POWERSTROKE_PROPERTIES_H
+#define INKSCAPE_DIALOG_POWERSTROKE_PROPERTIES_H
+
+#include <2geom/point.h>
+#include <gtkmm/dialog.h>
+#include <gtkmm/entry.h>
+#include <gtkmm/label.h>
+#include <gtkmm/table.h>
+#include <gtkmm/combobox.h>
+#include <gtkmm/liststore.h>
+#include <gtkmm/treeview.h>
+#include <gtkmm/treestore.h>
+#include <gtkmm/scrolledwindow.h>
+#include "live_effects/parameter/powerstrokepointarray.h"
+
+class SPDesktop;
+
+namespace Inkscape {
+namespace UI {
+namespace Dialogs {
+
+class PowerstrokePropertiesDialog : public Gtk::Dialog {
+ public:
+ PowerstrokePropertiesDialog();
+ virtual ~PowerstrokePropertiesDialog();
+
+ Glib::ustring getName() const { return "LayerPropertiesDialog"; }
+
+ static void showDialog(SPDesktop *desktop, Geom::Point knotpoint, const Inkscape::LivePathEffect::PowerStrokePointArrayParamKnotHolderEntity *pt);
+
+protected:
+
+ SPDesktop *_desktop;
+ Inkscape::LivePathEffect::PowerStrokePointArrayParamKnotHolderEntity *_knotpoint;
+
+ Gtk::Label _powerstroke_position_label;
+ Gtk::Entry _powerstroke_position_entry;
+ Gtk::Label _powerstroke_width_label;
+ Gtk::Entry _powerstroke_width_entry;
+ Gtk::Table _layout_table;
+ bool _position_visible;
+
+ Gtk::Button _close_button;
+ Gtk::Button _apply_button;
+
+ sigc::connection _destroy_connection;
+
+ static PowerstrokePropertiesDialog &_instance() {
+ static PowerstrokePropertiesDialog instance;
+ return instance;
+ }
+
+ void _setDesktop(SPDesktop *desktop);
+ void _setPt(const Inkscape::LivePathEffect::PowerStrokePointArrayParamKnotHolderEntity *pt);
+
+ void _apply();
+ void _close();
+
+ void _setKnotPoint(Geom::Point knotpoint);
+ void _prepareLabelRenderer(Gtk::TreeModel::const_iterator const &row);
+
+ bool _handleKeyEvent(GdkEventKey *event);
+ void _handleButtonEvent(GdkEventButton* event);
+
+ friend class Inkscape::LivePathEffect::PowerStrokePointArrayParamKnotHolderEntity;
+
+private:
+ PowerstrokePropertiesDialog(PowerstrokePropertiesDialog const &); // no copy
+ PowerstrokePropertiesDialog &operator=(PowerstrokePropertiesDialog const &); // no assign
+};
+
+} // namespace
+} // namespace
+} // namespace
+
+
+#endif //INKSCAPE_DIALOG_LAYER_PROPERTIES_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/ui/dialog/new-from-template.cpp b/src/ui/dialog/new-from-template.cpp
index f326bb3ee..e30b148bb 100644
--- a/src/ui/dialog/new-from-template.cpp
+++ b/src/ui/dialog/new-from-template.cpp
@@ -8,6 +8,9 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
+#if HAVE_CONFIG_H
+ #include "config.h"
+#endif
#include "new-from-template.h"
#include "file.h"
@@ -25,12 +28,22 @@ NewFromTemplate::NewFromTemplate()
{
set_title(_("New From Template"));
resize(400, 400);
-
+
+#if WITH_GTKMM_3_0
+ get_content_area()->pack_start(_main_widget);
+#else
get_vbox()->pack_start(_main_widget);
+#endif
Gtk::Alignment *align;
align = Gtk::manage(new Gtk::Alignment(Gtk::ALIGN_END, Gtk::ALIGN_CENTER, 0.0, 0.0));
+
+#if WITH_GTKMM_3_0
+ get_content_area()->pack_end(*align, Gtk::PACK_SHRINK);
+#else
get_vbox()->pack_end(*align, Gtk::PACK_SHRINK);
+#endif
+
align->set_padding(0, 0, 0, 15);
align->add(_create_template_button);
diff --git a/src/ui/dialog/objects.cpp b/src/ui/dialog/objects.cpp
new file mode 100644
index 000000000..c95529a56
--- /dev/null
+++ b/src/ui/dialog/objects.cpp
@@ -0,0 +1,2144 @@
+/*
+ * A simple panel for objects
+ *
+ * Authors:
+ * Theodore Janeczko
+ * Tweaked by Liam P White for use in Inkscape
+ *
+ * Copyright (C) Theodore Janeczko 2012 <flutterguy317@gmail.com>
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "objects.h"
+#include <gtkmm/widget.h>
+#include <gtkmm/icontheme.h>
+#include <gtkmm/imagemenuitem.h>
+#include <gtkmm/separatormenuitem.h>
+#include <gtkmm/stock.h>
+
+#include <glibmm/i18n.h>
+#include <glibmm/main.h>
+
+#include "desktop.h"
+#include "desktop-style.h"
+#include "ui/dialog-events.h"
+#include "document.h"
+#include "document-undo.h"
+#include "filter-chemistry.h"
+#include "filters/blend.h"
+#include "filters/gaussian-blur.h"
+#include "helper/action.h"
+#include "inkscape.h"
+#include "layer-manager.h"
+#include "preferences.h"
+#include "selection.h"
+#include "sp-clippath.h"
+#include "sp-mask.h"
+#include "sp-item.h"
+#include "sp-object.h"
+#include "sp-root.h"
+#include "sp-shape.h"
+#include "style.h"
+#include "ui/tools-switch.h"
+#include "ui/icon-names.h"
+#include "ui/widget/imagetoggler.h"
+#include "ui/widget/layertypeicon.h"
+#include "ui/widget/insertordericon.h"
+#include "ui/widget/clipmaskicon.h"
+#include "ui/widget/highlight-picker.h"
+#include "ui/tools/node-tool.h"
+#include "ui/tools/tool-base.h"
+#include "verbs.h"
+#include "widgets/sp-color-notebook.h"
+#include "widgets/icon.h"
+#include "xml/node.h"
+#include "xml/node-observer.h"
+#include "xml/repr.h"
+
+//#define DUMP_LAYERS 1
+
+namespace Inkscape {
+namespace UI {
+namespace Dialog {
+
+using Inkscape::XML::Node;
+
+/**
+ * Gets an instance of the Objects panel
+ */
+ObjectsPanel& ObjectsPanel::getInstance()
+{
+ return *new ObjectsPanel();
+}
+
+/**
+ * Column enumeration
+ */
+enum {
+ COL_VISIBLE = 1,
+ COL_LOCKED,
+ COL_TYPE,
+// COL_INSERTORDER,
+ COL_CLIPMASK,
+ COL_HIGHLIGHT
+};
+
+/**
+ * Button enumeration
+ */
+enum {
+ BUTTON_NEW = 0,
+ BUTTON_RENAME,
+ BUTTON_TOP,
+ BUTTON_BOTTOM,
+ BUTTON_UP,
+ BUTTON_DOWN,
+ BUTTON_DUPLICATE,
+ BUTTON_DELETE,
+ BUTTON_SOLO,
+ BUTTON_SHOW_ALL,
+ BUTTON_HIDE_ALL,
+ BUTTON_LOCK_OTHERS,
+ BUTTON_LOCK_ALL,
+ BUTTON_UNLOCK_ALL,
+ BUTTON_SETCLIP,
+ BUTTON_CLIPGROUP,
+// BUTTON_SETINVCLIP,
+ BUTTON_UNSETCLIP,
+ BUTTON_SETMASK,
+ BUTTON_UNSETMASK,
+ BUTTON_GROUP,
+ BUTTON_UNGROUP,
+ BUTTON_COLLAPSE_ALL,
+ DRAGNDROP
+};
+
+/**
+ * Xml node observer for observing objects in the document
+ */
+class ObjectsPanel::ObjectWatcher : public Inkscape::XML::NodeObserver {
+public:
+ /**
+ * Creates a new object watcher
+ * @param pnl The panel to which the object watcher belongs
+ * @param obj The object to watch
+ */
+ ObjectWatcher(ObjectsPanel* pnl, SPObject* obj) :
+ _pnl(pnl),
+ _obj(obj),
+ _repr(obj->getRepr()),
+ _highlightAttr(g_quark_from_string("inkscape:highlight-color")),
+ _lockedAttr(g_quark_from_string("sodipodi:insensitive")),
+ _labelAttr(g_quark_from_string("inkscape:label")),
+ _groupAttr(g_quark_from_string("inkscape:groupmode")),
+ _styleAttr(g_quark_from_string("style")),
+ _clipAttr(g_quark_from_string("clip-path")),
+ _maskAttr(g_quark_from_string("mask"))
+ {}
+
+ virtual void notifyChildAdded( Node &/*node*/, Node &/*child*/, Node */*prev*/ )
+ {
+ if ( _pnl && _obj ) {
+ _pnl->_objectsChanged( _obj );
+ }
+ }
+ virtual void notifyChildRemoved( Node &/*node*/, Node &/*child*/, Node */*prev*/ )
+ {
+ if ( _pnl && _obj ) {
+ _pnl->_objectsChanged( _obj );
+ }
+ }
+ virtual void notifyChildOrderChanged( Node &/*node*/, Node &/*child*/, Node */*old_prev*/, Node */*new_prev*/ )
+ {
+ if ( _pnl && _obj ) {
+ _pnl->_objectsChanged( _obj );
+ }
+ }
+ virtual void notifyContentChanged( Node &/*node*/, Util::ptr_shared<char> /*old_content*/, Util::ptr_shared<char> /*new_content*/ ) {}
+ virtual void notifyAttributeChanged( Node &/*node*/, GQuark name, Util::ptr_shared<char> /*old_value*/, Util::ptr_shared<char> /*new_value*/ ) {
+ if ( _pnl && _obj ) {
+ if ( name == _lockedAttr || name == _labelAttr || name == _highlightAttr || name == _groupAttr || name == _styleAttr || name == _clipAttr || name == _maskAttr ) {
+ _pnl->_updateObject(_obj, name == _highlightAttr);
+ if ( name == _styleAttr ) {
+ _pnl->_updateComposite();
+ }
+ }
+ }
+ }
+
+ /**
+ * Objects panel to which this watcher belongs
+ */
+ ObjectsPanel* _pnl;
+
+ /**
+ * The object that is being observed
+ */
+ SPObject* _obj;
+
+ /**
+ * The xml representation of the object that is being observed
+ */
+ Inkscape::XML::Node* _repr;
+
+ /* These are quarks which define the attributes that we are observing */
+ GQuark _highlightAttr;
+ GQuark _lockedAttr;
+ GQuark _labelAttr;
+ GQuark _groupAttr;
+ GQuark _styleAttr;
+ GQuark _clipAttr;
+ GQuark _maskAttr;
+};
+
+class ObjectsPanel::InternalUIBounce
+{
+public:
+ int _actionCode;
+};
+
+class ObjectsPanel::ModelColumns : public Gtk::TreeModel::ColumnRecord
+{
+public:
+
+ ModelColumns()
+ {
+ add(_colObject);
+ add(_colVisible);
+ add(_colLocked);
+ add(_colLabel);
+ add(_colType);
+ add(_colHighlight);
+ add(_colClipMask);
+ //add(_colInsertOrder);
+ }
+ virtual ~ModelColumns() {}
+
+ Gtk::TreeModelColumn<SPItem*> _colObject;
+ Gtk::TreeModelColumn<Glib::ustring> _colLabel;
+ Gtk::TreeModelColumn<bool> _colVisible;
+ Gtk::TreeModelColumn<bool> _colLocked;
+ Gtk::TreeModelColumn<int> _colType;
+ Gtk::TreeModelColumn<guint32> _colHighlight;
+ Gtk::TreeModelColumn<int> _colClipMask;
+ //Gtk::TreeModelColumn<int> _colInsertOrder;
+};
+
+/**
+ * Stylizes a button using the given icon name and tooltip
+ */
+void ObjectsPanel::_styleButton( Gtk::Button& btn, char const* iconName, char const* tooltip )
+{
+ GtkWidget *child = sp_icon_new( Inkscape::ICON_SIZE_SMALL_TOOLBAR, iconName );
+ gtk_widget_show( child );
+ btn.add( *Gtk::manage(Glib::wrap(child)) );
+ btn.set_relief(Gtk::RELIEF_NONE);
+
+ btn.set_tooltip_text (tooltip);
+
+}
+
+/**
+ * Adds an item to the pop-up (right-click) menu
+ * @param desktop The active destktop
+ * @param code Action code
+ * @param iconName Icon name
+ * @param fallback Fallback text
+ * @param id Button id for callback function
+ * @return The generated menu item
+ */
+Gtk::MenuItem& ObjectsPanel::_addPopupItem( SPDesktop *desktop, unsigned int code, char const* iconName, char const* fallback, int id )
+{
+ GtkWidget* iconWidget = 0;
+ const char* label = 0;
+
+ if ( iconName ) {
+ iconWidget = sp_icon_new( Inkscape::ICON_SIZE_MENU, iconName );
+ }
+
+ if ( desktop ) {
+ Verb *verb = Verb::get( code );
+ if ( verb ) {
+ SPAction *action = verb->get_action(desktop);
+ if ( !iconWidget && action && action->image ) {
+ iconWidget = sp_icon_new( Inkscape::ICON_SIZE_MENU, action->image );
+ }
+
+ if ( action ) {
+ // label = action->name;
+ }
+ }
+ }
+
+ if ( !label && fallback ) {
+ label = fallback;
+ }
+
+ Gtk::Widget* wrapped = 0;
+ if ( iconWidget ) {
+ wrapped = Gtk::manage(Glib::wrap(iconWidget));
+ wrapped->show();
+ }
+
+
+ Gtk::MenuItem* item = 0;
+
+ if (wrapped) {
+ item = Gtk::manage(new Gtk::ImageMenuItem(*wrapped, label, true));
+ } else {
+ item = Gtk::manage(new Gtk::MenuItem(label, true));
+ }
+
+ item->signal_activate().connect(sigc::bind(sigc::mem_fun(*this, &ObjectsPanel::_takeAction), id));
+ _popupMenu.append(*item);
+
+ return *item;
+}
+
+/**
+ * Callback function for when an object changes. Essentially refreshes the entire tree
+ * @param obj Object which was changed (currently not used as the entire tree is recreated)
+ */
+void ObjectsPanel::_objectsChanged(SPObject */*obj*/)
+{
+ //First, unattach the watchers
+ while (!_objectWatchers.empty())
+ {
+ ObjectsPanel::ObjectWatcher *w = _objectWatchers.back();
+ w->_repr->removeObserver(*w);
+ _objectWatchers.pop_back();
+ delete w;
+ }
+
+ if (_desktop) {
+ //Get the current document's root and use that to enumerate the tree
+ SPDocument* document = _desktop->doc();
+ SPRoot* root = document->getRoot();
+ if ( root ) {
+ _selectedConnection.block();
+ //Clear the tree store
+ _store->clear();
+ //Add all items recursively
+ _addObject( root, 0 );
+ _selectedConnection.unblock();
+ //Set the tree selection
+ _objectsSelected(_desktop->selection);
+ //Handle button sensitivity
+ _checkTreeSelection();
+ }
+ }
+}
+
+/**
+ * Recursively adds the children of the given item to the tree
+ * @param obj Root object to add to the tree
+ * @param parentRow Parent tree row (or NULL if adding to tree root)
+ */
+void ObjectsPanel::_addObject(SPObject* obj, Gtk::TreeModel::Row* parentRow)
+{
+ if ( _desktop && obj ) {
+ for ( SPObject *child = obj->children; child != NULL; child = child->next) {
+
+ if (SP_IS_ITEM(child))
+ {
+ SPItem * item = SP_ITEM(child);
+ SPGroup * group = SP_IS_GROUP(child) ? SP_GROUP(child) : 0;
+
+ //Add the item to the tree and set the column information
+ Gtk::TreeModel::iterator iter = parentRow ? _store->prepend(parentRow->children()) : _store->prepend();
+ Gtk::TreeModel::Row row = *iter;
+ row[_model->_colObject] = item;
+ //this seems to crash on convert stroke to path then undo (probably no ID?)
+ try {
+ row[_model->_colLabel] = item->label() ? item->label() : item->getId();
+ } catch (...) {
+ row[_model->_colLabel] = Glib::ustring("getId_failure");
+ g_critical("item->getId() failed, using \"getId_failure\"");
+ }
+ row[_model->_colVisible] = !item->isHidden();
+ row[_model->_colLocked] = !item->isSensitive();
+ row[_model->_colType] = group ? (group->layerMode() == SPGroup::LAYER ? 2 : 1) : 0;
+ row[_model->_colHighlight] = item->isHighlightSet() ? item->highlight_color() : item->highlight_color() & 0xffffff00;
+ row[_model->_colClipMask] = item->clip_ref && item->clip_ref->getObject() ? 1 : (item->mask_ref && item->mask_ref->getObject() ? 2 : 0);
+ //row[_model->_colInsertOrder] = group ? (group->insertBottom() ? 2 : 1) : 0;
+
+ //If our parent object is a group and it's expanded, expand the tree
+ if (SP_IS_GROUP(obj) && SP_GROUP(obj)->expanded())
+ {
+ _tree.expand_to_path( _store->get_path(iter) );
+ }
+
+ //Add an object watcher to the item
+ ObjectsPanel::ObjectWatcher *w = new ObjectsPanel::ObjectWatcher(this, child);
+ child->getRepr()->addObserver(*w);
+ _objectWatchers.push_back(w);
+
+ //If the item is a group, recursively add its children
+ if (group)
+ {
+ _addObject( child, &row );
+ }
+ }
+ }
+ }
+}
+
+/**
+ * Updates an item in the tree and optionally recursively updates the item's children
+ * @param obj The item to update in the tree
+ * @param recurse Whether to recurse through the item's children
+ */
+void ObjectsPanel::_updateObject( SPObject *obj, bool recurse ) {
+ //Find the object in the tree store and update it
+
+ //mark
+ _store->foreach_iter( sigc::bind<SPObject*>(sigc::mem_fun(*this, &ObjectsPanel::_checkForUpdated), obj) );
+ //end mark
+ if (recurse)
+ {
+ for (SPObject * iter = obj->children; iter != NULL; iter = iter->next)
+ {
+ _updateObject(iter, recurse);
+ }
+ }
+}
+
+/**
+ * Checks items in the tree store and updates the given item
+ * @param iter Current item being looked at in the tree
+ * @param obj Object to update
+ * @return
+ */
+bool ObjectsPanel::_checkForUpdated(const Gtk::TreeIter& iter, SPObject* obj)
+{
+ Gtk::TreeModel::Row row = *iter;
+ if ( obj == row[_model->_colObject] )
+ {
+ //We found our item in the tree!! Update it!
+ SPItem * item = SP_IS_ITEM(obj) ? SP_ITEM(obj) : 0;
+ SPGroup * group = SP_IS_GROUP(obj) ? SP_GROUP(obj) : 0;
+
+ row[_model->_colLabel] = obj->label() ? obj->label() : obj->getId();
+ row[_model->_colVisible] = item ? !item->isHidden() : false;
+ row[_model->_colLocked] = item ? !item->isSensitive() : false;
+ row[_model->_colType] = group ? (group->layerMode() == SPGroup::LAYER ? 2 : 1) : 0;
+ row[_model->_colHighlight] = item ? (item->isHighlightSet() ? item->highlight_color() : item->highlight_color() & 0xffffff00) : 0;
+ row[_model->_colClipMask] = item ? (item->clip_ref && item->clip_ref->getObject() ? 1 : (item->mask_ref && item->mask_ref->getObject() ? 2 : 0)) : 0;
+ //row[_model->_colInsertOrder] = group ? (group->insertBottom() ? 2 : 1) : 0;
+
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * Updates the composite controls for the selected item
+ */
+void ObjectsPanel::_updateComposite() {
+ if (!_blockCompositeUpdate)
+ {
+ //Set the default values
+ bool setValues = true;
+
+ //Get/set the values
+ _tree.get_selection()->selected_foreach_iter(sigc::bind<bool *>(sigc::mem_fun(*this, &ObjectsPanel::_compositingChanged), &setValues));
+ }
+}
+
+/**
+ * Sets the compositing values for the first selected item in the tree
+ * @param iter Current tree item
+ * @param setValues Whether to set the compositing values
+ * @param blur Blur value to use
+ */
+void ObjectsPanel::_compositingChanged( const Gtk::TreeModel::iterator& iter, bool *setValues )
+{
+ if (iter) {
+ Gtk::TreeModel::Row row = *iter;
+ SPItem *item = row[_model->_colObject];
+ if (*setValues)
+ {
+ _setCompositingValues(item);
+ *setValues = false;
+ }
+ }
+}
+
+/**
+ * Occurs when the current desktop selection changes
+ * @param sel The current selection
+ */
+void ObjectsPanel::_objectsSelected( Selection *sel ) {
+
+ bool setOpacity = true;
+ _selectedConnection.block();
+ _tree.get_selection()->unselect_all();
+ SPItem *item = NULL;
+ for (const GSList * iter = sel->itemList(); iter != NULL; iter = iter->next)
+ {
+ item = reinterpret_cast<SPItem *>(iter->data);
+ if (setOpacity)
+ {
+ _setCompositingValues(item);
+ setOpacity = false;
+ }
+ _store->foreach(sigc::bind<SPItem *, bool>( sigc::mem_fun(*this, &ObjectsPanel::_checkForSelected), item, iter->next == NULL));
+ }
+ if (!item) {
+ if (_desktop->currentLayer() && SP_IS_ITEM(_desktop->currentLayer())) {
+ item = SP_ITEM(_desktop->currentLayer());
+ _setCompositingValues(item);
+ _store->foreach(sigc::bind<SPItem *, bool>( sigc::mem_fun(*this, &ObjectsPanel::_checkForSelected), item, true));
+ }
+ }
+ _selectedConnection.unblock();
+ _checkTreeSelection();
+}
+
+/**
+ * Helper function for setting the compositing values
+ * @param item Item to use for setting the compositing values
+ */
+void ObjectsPanel::_setCompositingValues(SPItem *item)
+{
+ //Block the connections to avoid interference
+ _opacityConnection.block();
+ _blendConnection.block();
+ _blurConnection.block();
+
+ //Set the opacity
+#if WITH_GTKMM_3_0
+ _opacity_adjustment->set_value((item->style->opacity.set ? SP_SCALE24_TO_FLOAT(item->style->opacity.value) : 1) * _opacity_adjustment->get_upper());
+#else
+ _opacity_adjustment.set_value((item->style->opacity.set ? SP_SCALE24_TO_FLOAT(item->style->opacity.value) : 1) * _opacity_adjustment.get_upper());
+#endif
+ SPFeBlend *spblend = NULL;
+ SPGaussianBlur *spblur = NULL;
+ if (item->style->getFilter())
+ {
+ for(SPObject *primitive_obj = item->style->getFilter()->children; primitive_obj && SP_IS_FILTER_PRIMITIVE(primitive_obj); primitive_obj = primitive_obj->next) {
+ if(SP_IS_FEBLEND(primitive_obj) && !spblend) {
+ //Get the blend mode
+ spblend = SP_FEBLEND(primitive_obj);
+ }
+
+ if(SP_IS_GAUSSIANBLUR(primitive_obj) && !spblur) {
+ //Get the blur value
+ spblur = SP_GAUSSIANBLUR(primitive_obj);
+ }
+ }
+ }
+
+ //Set the blend mode
+ _fe_cb.set_blend_mode(spblend ? spblend->blend_mode : Inkscape::Filters::BLEND_NORMAL);
+
+ //Set the blur value
+ Geom::OptRect bbox = item->bounds(SPItem::GEOMETRIC_BBOX);
+ if (bbox && spblur) {
+ double perimeter = bbox->dimensions()[Geom::X] + bbox->dimensions()[Geom::Y]; // fixme: this is only half the perimeter, is that correct?
+ _fe_blur.set_blur_value(spblur->stdDeviation.getNumber() * 400 / perimeter);
+ } else {
+ _fe_blur.set_blur_value(0);
+ }
+
+ //Unblock connections
+ _blurConnection.unblock();
+ _blendConnection.unblock();
+ _opacityConnection.unblock();
+}
+
+/**
+ * Checks the tree and selects the specified item, optionally scrolling to the item
+ * @param path Current tree path
+ * @param iter Current tree item
+ * @param item Item to select in the tree
+ * @param scrollto Whether to scroll to the item
+ * @return Whether to continue searching the tree
+ */
+bool ObjectsPanel::_checkForSelected(const Gtk::TreePath &path, const Gtk::TreeIter& iter, SPItem* item, bool scrollto)
+{
+ bool stopGoing = false;
+
+ Gtk::TreeModel::Row row = *iter;
+ if ( item == row[_model->_colObject] )
+ {
+ //We found the item! Expand to the path and select it in the tree.
+ _tree.expand_to_path( path );
+
+ Glib::RefPtr<Gtk::TreeSelection> select = _tree.get_selection();
+
+ select->select(iter);
+ if (scrollto) {
+ //Scroll to the item in the tree
+ _tree.scroll_to_row(path);
+ }
+
+ stopGoing = true;
+ }
+
+ return stopGoing;
+}
+
+/**
+ * Pushes the current tree selection to the canvas
+ */
+void ObjectsPanel::_pushTreeSelectionToCurrent()
+{
+ if ( _desktop && _desktop->currentRoot() ) {
+ //block connections for selection and compositing values to prevent interference
+ _selectionChangedConnection.block();
+
+ //Clear the selection and then iterate over the tree selection, pushing each item to the desktop
+ _desktop->selection->clear();
+ bool setOpacity = true;
+ _tree.get_selection()->selected_foreach_iter( sigc::bind<bool *>(sigc::mem_fun(*this, &ObjectsPanel::_selected_row_callback), &setOpacity));
+ //unblock connections
+ _selectionChangedConnection.unblock();
+
+ _checkTreeSelection();
+ }
+}
+
+/**
+ * Helper function for pushing the current tree selection to the current desktop
+ * @param iter Current tree item
+ * @param setCompositingValues Whether to set the compositing values
+ * @param blur
+ */
+void ObjectsPanel::_selected_row_callback( const Gtk::TreeModel::iterator& iter, bool *setCompositingValues )
+{
+ if (iter) {
+ Gtk::TreeModel::Row row = *iter;
+ SPItem *item = row[_model->_colObject];
+ if (!SP_IS_GROUP(item) || SP_GROUP(item)->layerMode() != SPGroup::LAYER)
+ {
+ //If the item is not a layer, then select it and set the current layer to its parent (if it's the first item)
+ if (_desktop->selection->isEmpty()) _desktop->setCurrentLayer(item->parent);
+ _desktop->selection->add(item);
+ }
+ else
+ {
+ //If the item is a layer, set the current layer
+ if (_desktop->selection->isEmpty()) _desktop->setCurrentLayer(item);
+ }
+ if (*setCompositingValues)
+ {
+ //Only set the compositing values for the first item
+ _setCompositingValues(item);
+ *setCompositingValues = false;
+ }
+ }
+}
+
+/**
+ * Handles button sensitivity
+ */
+void ObjectsPanel::_checkTreeSelection()
+{
+ bool sensitive = _tree.get_selection()->count_selected_rows() > 0;
+ //TODO: top/bottom sensitivity
+ bool sensitiveNonTop = true;
+ bool sensitiveNonBottom = true;
+
+ for ( std::vector<Gtk::Widget*>::iterator it = _watching.begin(); it != _watching.end(); ++it ) {
+ (*it)->set_sensitive( sensitive );
+ }
+ for ( std::vector<Gtk::Widget*>::iterator it = _watchingNonTop.begin(); it != _watchingNonTop.end(); ++it ) {
+ (*it)->set_sensitive( sensitiveNonTop );
+ }
+ for ( std::vector<Gtk::Widget*>::iterator it = _watchingNonBottom.begin(); it != _watchingNonBottom.end(); ++it ) {
+ (*it)->set_sensitive( sensitiveNonBottom );
+ }
+}
+
+/**
+ * Sets visibility of items in the tree
+ * @param iter Current item in the tree
+ * @param visible Whether the item should be visible or not
+ */
+void ObjectsPanel::_setVisibleIter( const Gtk::TreeModel::iterator& iter, const bool visible )
+{
+ Gtk::TreeModel::Row row = *iter;
+ SPItem* item = row[_model->_colObject];
+ if (item)
+ {
+ item->setHidden( !visible );
+ row[_model->_colVisible] = visible;
+ item->updateRepr(SP_OBJECT_WRITE_NO_CHILDREN | SP_OBJECT_WRITE_EXT);
+ }
+}
+
+/**
+ * Sets sensitivity of items in the tree
+ * @param iter Current item in the tree
+ * @param locked Whether the item should be locked
+ */
+void ObjectsPanel::_setLockedIter( const Gtk::TreeModel::iterator& iter, const bool locked )
+{
+ Gtk::TreeModel::Row row = *iter;
+ SPItem* item = row[_model->_colObject];
+ if (item)
+ {
+ item->setLocked( locked );
+ row[_model->_colLocked] = locked;
+ item->updateRepr(SP_OBJECT_WRITE_NO_CHILDREN | SP_OBJECT_WRITE_EXT);
+ }
+}
+
+/**
+ * Handles keyboard events
+ * @param event Keyboard event passed in from GDK
+ * @return Whether the event should be eaten (om nom nom)
+ */
+bool ObjectsPanel::_handleKeyEvent(GdkEventKey *event)
+{
+
+ bool empty = _desktop->selection->isEmpty();
+
+ switch (Inkscape::UI::Tools::get_group0_keyval(event)) {
+ case GDK_KEY_Return:
+ case GDK_KEY_KP_Enter:
+ case GDK_KEY_F2:
+ {
+ Gtk::TreeModel::iterator iter = _tree.get_selection()->get_selected();
+ if (iter && !_text_renderer->property_editable()) {
+ //Rename item
+ Gtk::TreeModel::Path *path = new Gtk::TreeModel::Path(iter);
+ _text_renderer->property_editable() = true;
+ _tree.set_cursor(*path, *_name_column, true);
+ grab_focus();
+ return true;
+ }
+ }
+ break;
+ case GDK_KEY_Home:
+ //Move item(s) to top of containing group/layer
+ _fireAction( empty ? SP_VERB_LAYER_TO_TOP : SP_VERB_SELECTION_TO_FRONT );
+ break;
+ case GDK_KEY_End:
+ //Move item(s) to bottom of containing group/layer
+ _fireAction( empty ? SP_VERB_LAYER_TO_BOTTOM : SP_VERB_SELECTION_TO_BACK );
+ break;
+ case GDK_KEY_Page_Up:
+ {
+ //Move item(s) up in containing group/layer
+ int ch = event->state & GDK_SHIFT_MASK ? SP_VERB_LAYER_MOVE_TO_NEXT : SP_VERB_SELECTION_RAISE;
+ _fireAction( empty ? SP_VERB_LAYER_RAISE : ch );
+ break;
+ }
+ case GDK_KEY_Page_Down:
+ {
+ //Move item(s) down in containing group/layer
+ int ch = event->state & GDK_SHIFT_MASK ? SP_VERB_LAYER_MOVE_TO_PREV : SP_VERB_SELECTION_LOWER;
+ _fireAction( empty ? SP_VERB_LAYER_LOWER : ch );
+ break;
+ }
+
+ //TODO: Handle Ctrl-A, etc.
+ default:
+ return false;
+ }
+ return true;
+}
+
+/**
+ * Handles mouse events
+ * @param event Mouse event from GDK
+ * @return whether to eat the event (om nom nom)
+ */
+bool ObjectsPanel::_handleButtonEvent(GdkEventButton* event)
+{
+ static unsigned doubleclick = 0;
+ static bool overVisible = false;
+
+ //Right mouse button was clicked, launch the pop-up menu
+ if ( (event->type == GDK_BUTTON_PRESS) && (event->button == 3) ) {
+ Gtk::TreeModel::Path path;
+ int x = static_cast<int>(event->x);
+ int y = static_cast<int>(event->y);
+ if ( _tree.get_path_at_pos( x, y, path ) ) {
+ _checkTreeSelection();
+ _popupMenu.popup(event->button, event->time);
+ if (_tree.get_selection()->is_selected(path)) {
+ return true;
+ }
+ }
+ }
+
+ //Left mouse button was pressed! In order to handle multiple item drag & drop,
+ //we need to defer selection by setting the select function so that the tree doesn't
+ //automatically select anything. In order to handle multiple item icon clicking,
+ //we need to eat the event. There might be a better way to do both of these...
+ if ( (event->type == GDK_BUTTON_PRESS) && (event->button == 1)) {
+ overVisible = false;
+ Gtk::TreeModel::Path path;
+ Gtk::TreeViewColumn* col = 0;
+ int x = static_cast<int>(event->x);
+ int y = static_cast<int>(event->y);
+ int x2 = 0;
+ int y2 = 0;
+ if ( _tree.get_path_at_pos( x, y, path, col, x2, y2 ) ) {
+ if (col == _tree.get_column(COL_VISIBLE-1)) {
+ //Click on visible column, eat this event to keep row selection
+ overVisible = true;
+ return true;
+ } else if (col == _tree.get_column(COL_LOCKED-1) ||
+ col == _tree.get_column(COL_TYPE-1) ||
+ //col == _tree.get_column(COL_INSERTORDER - 1) ||
+ col == _tree.get_column(COL_HIGHLIGHT-1)) {
+ //Click on an icon column, eat this event to keep row selection
+ return true;
+ } else if ( !(event->state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK)) & _tree.get_selection()->is_selected(path) ) {
+ //Click on a selected item with no modifiers, defer selection to the mouse-up by
+ //setting the select function to _noSelection
+ _tree.get_selection()->set_select_function(sigc::mem_fun(*this, &ObjectsPanel::_noSelection));
+ _defer_target = path;
+ }
+ }
+ }
+
+ //Restore the selection function to allow tree selection on mouse button release
+ if ( event->type == GDK_BUTTON_RELEASE) {
+ _tree.get_selection()->set_select_function(sigc::mem_fun(*this, &ObjectsPanel::_rowSelectFunction));
+ }
+
+ //CellRenderers do not have good support for dealing with multiple items, so
+ //we handle all events on them here
+ if ( (event->type == GDK_BUTTON_RELEASE) && (event->button == 1)) {
+
+ Gtk::TreeModel::Path path;
+ Gtk::TreeViewColumn* col = 0;
+ int x = static_cast<int>(event->x);
+ int y = static_cast<int>(event->y);
+ int x2 = 0;
+ int y2 = 0;
+ if ( _tree.get_path_at_pos( x, y, path, col, x2, y2 ) ) {
+ if (_defer_target) {
+ //We had deferred a selection target, select it here (assuming no drag & drop)
+ if (_defer_target == path && !(event->x == 0 && event->y == 0))
+ {
+ _tree.set_cursor(path, *col, false);
+ }
+ _defer_target = Gtk::TreeModel::Path();
+ }
+ else {
+ if (event->state & GDK_SHIFT_MASK) {
+ // Shift left click on the visible/lock columns toggles "solo" mode
+ if (col == _tree.get_column(COL_VISIBLE - 1)) {
+ _takeAction(BUTTON_SOLO);
+ } else if (col == _tree.get_column(COL_LOCKED - 1)) {
+ _takeAction(BUTTON_LOCK_OTHERS);
+ }
+ } else if (event->state & GDK_MOD1_MASK) {
+ // Alt+left click on the visible/lock columns toggles "solo" mode and preserves selection
+ Gtk::TreeModel::iterator iter = _store->get_iter(path);
+ if (_store->iter_is_valid(iter)) {
+ Gtk::TreeModel::Row row = *iter;
+ SPItem *item = row[_model->_colObject];
+ if (col == _tree.get_column(COL_VISIBLE - 1)) {
+ _desktop->toggleLayerSolo( item );
+ DocumentUndo::maybeDone(_desktop->doc(), "layer:solo", SP_VERB_LAYER_SOLO, _("Toggle layer solo"));
+ } else if (col == _tree.get_column(COL_LOCKED - 1)) {
+ _desktop->toggleLockOtherLayers( item );
+ DocumentUndo::maybeDone(_desktop->doc(), "layer:lockothers", SP_VERB_LAYER_LOCK_OTHERS, _("Lock other layers"));
+ }
+ }
+ } else {
+ Gtk::TreeModel::Children::iterator iter = _tree.get_model()->get_iter(path);
+ Gtk::TreeModel::Row row = *iter;
+
+ SPItem* item = row[_model->_colObject];
+
+ if (col == _tree.get_column(COL_VISIBLE - 1)) {
+ if (overVisible) {
+ //Toggle visibility
+ bool newValue = !row[_model->_colVisible];
+ if (_tree.get_selection()->is_selected(path))
+ {
+ //If the current row is selected, toggle the visibility
+ //for all selected items
+ _tree.get_selection()->selected_foreach_iter(sigc::bind<bool>(sigc::mem_fun(*this, &ObjectsPanel::_setVisibleIter), newValue));
+ }
+ else
+ {
+ //If the current row is not selected, toggle just its visibility
+ row[_model->_colVisible] = newValue;
+ item->setHidden(!newValue);
+ item->updateRepr(SP_OBJECT_WRITE_NO_CHILDREN | SP_OBJECT_WRITE_EXT);
+ }
+ DocumentUndo::done( _desktop->doc() , SP_VERB_DIALOG_OBJECTS,
+ newValue? _("Unhide objects") : _("Hide objects"));
+ overVisible = false;
+ }
+ } else if (col == _tree.get_column(COL_LOCKED - 1)) {
+ //Toggle locking
+ bool newValue = !row[_model->_colLocked];
+ if (_tree.get_selection()->is_selected(path))
+ {
+ //If the current row is selected, toggle the sensitivity for
+ //all selected items
+ _tree.get_selection()->selected_foreach_iter(sigc::bind<bool>(sigc::mem_fun(*this, &ObjectsPanel::_setLockedIter), newValue));
+ }
+ else
+ {
+ //If the current row is not selected, toggle just its sensitivity
+ row[_model->_colLocked] = newValue;
+ item->setLocked( newValue );
+ item->updateRepr(SP_OBJECT_WRITE_NO_CHILDREN | SP_OBJECT_WRITE_EXT);
+ }
+ DocumentUndo::done( _desktop->doc() , SP_VERB_DIALOG_OBJECTS,
+ newValue? _("Lock objects") : _("Unlock objects"));
+
+ } else if (col == _tree.get_column(COL_TYPE - 1)) {
+ if (SP_IS_GROUP(item))
+ {
+ //Toggle the current item between a group and a layer
+ SPGroup * g = SP_GROUP(item);
+ bool newValue = g->layerMode() == SPGroup::LAYER;
+ row[_model->_colType] = newValue ? 1: 2;
+ g->setLayerMode(newValue ? SPGroup::GROUP : SPGroup::LAYER);
+ g->updateRepr(SP_OBJECT_WRITE_NO_CHILDREN | SP_OBJECT_WRITE_EXT);
+ DocumentUndo::done( _desktop->doc() , SP_VERB_DIALOG_OBJECTS,
+ newValue? _("Layer to group") : _("Group to layer"));
+ }
+ } /*else if (col == _tree.get_column(COL_INSERTORDER - 1)) {
+ if (SP_IS_GROUP(item))
+ {
+ //Toggle the current item's insert order
+ SPGroup * g = SP_GROUP(item);
+ bool newValue = !g->insertBottom();
+ row[_model->_colInsertOrder] = newValue ? 2: 1;
+ g->setInsertBottom(newValue);
+ g->updateRepr(SP_OBJECT_WRITE_NO_CHILDREN | SP_OBJECT_WRITE_EXT);
+ DocumentUndo::done( _desktop->doc() , SP_VERB_DIALOG_OBJECTS,
+ newValue? _("Set insert mode bottom") : _("Set insert mode top"));
+ }
+ }*/ else if (col == _tree.get_column(COL_HIGHLIGHT - 1)) {
+ //Clear the highlight targets
+ _highlight_target.clear();
+ if (_tree.get_selection()->is_selected(path))
+ {
+ //If the current item is selected, store all selected items
+ //in the highlight source
+ _tree.get_selection()->selected_foreach_iter(sigc::mem_fun(*this, &ObjectsPanel::_storeHighlightTarget));
+ } else {
+ //If the current item is not selected, store only it in the highlight source
+ _storeHighlightTarget(iter);
+ }
+ if (_colorSelector)
+ {
+ //Set up the color selector
+ SPColor color;
+ color.set( row[_model->_colHighlight] );
+ _colorSelector->base->setColorAlpha(color, SP_RGBA32_A_F(row[_model->_colHighlight]));
+ }
+ //Show the color selector dialog
+ _colorSelectorDialog.show();
+ }
+ }
+ }
+ }
+ }
+
+ //Second mouse button press, set double click status for when the mouse is released
+ if ( (event->type == GDK_2BUTTON_PRESS) && (event->button == 1) ) {
+ doubleclick = 1;
+ }
+
+ //Double click on mouse button release, if we're over the label column, edit
+ //the item name
+ if ( event->type == GDK_BUTTON_RELEASE && doubleclick) {
+ doubleclick = 0;
+ Gtk::TreeModel::Path path;
+ Gtk::TreeViewColumn* col = 0;
+ int x = static_cast<int>(event->x);
+ int y = static_cast<int>(event->y);
+ int x2 = 0;
+ int y2 = 0;
+ if ( _tree.get_path_at_pos( x, y, path, col, x2, y2 ) && col == _name_column) {
+ // Double click on the Layer name, enable editing
+ _text_renderer->property_editable() = true;
+ _tree.set_cursor (path, *_name_column, true);
+ grab_focus();
+ }
+ }
+
+ return false;
+}
+
+/**
+ * Stores items in the highlight target vector to manipulate with the color selector
+ * @param iter Current tree item to store
+ */
+void ObjectsPanel::_storeHighlightTarget(const Gtk::TreeModel::iterator& iter)
+{
+ Gtk::TreeModel::Row row = *iter;
+ SPItem* item = row[_model->_colObject];
+ if (item)
+ {
+ _highlight_target.push_back(item);
+ }
+}
+
+/*
+ * Drap and drop within the tree
+ */
+bool ObjectsPanel::_handleDragDrop(const Glib::RefPtr<Gdk::DragContext>& /*context*/, int x, int y, guint /*time*/)
+{
+ int cell_x = 0, cell_y = 0;
+ Gtk::TreeModel::Path target_path;
+ Gtk::TreeView::Column *target_column;
+
+ //Set up our defaults and clear the source vector
+ _dnd_into = false;
+ _dnd_target = NULL;
+ _dnd_source.clear();
+
+ //Add all selected items to the source vector
+ _tree.get_selection()->selected_foreach_iter(sigc::mem_fun(*this, &ObjectsPanel::_storeDragSource));
+
+ if (_tree.get_path_at_pos (x, y, target_path, target_column, cell_x, cell_y)) {
+ // Are we before, inside or after the drop layer
+ Gdk::Rectangle rect;
+ _tree.get_background_area (target_path, *target_column, rect);
+ int cell_height = rect.get_height();
+ _dnd_into = (cell_y > (int)(cell_height * 1/4) && cell_y <= (int)(cell_height * 3/4));
+ if (cell_y > (int)(cell_height * 3/4)) {
+ Gtk::TreeModel::Path next_path = target_path;
+ next_path.next();
+ if (_store->iter_is_valid(_store->get_iter(next_path))) {
+ target_path = next_path;
+ } else {
+ // Dragging to the "end"
+ Gtk::TreeModel::Path up_path = target_path;
+ up_path.up();
+ if (_store->iter_is_valid(_store->get_iter(up_path))) {
+ // Drop into parent
+ target_path = up_path;
+ _dnd_into = true;
+ } else {
+ // Drop into the top level
+ _dnd_target = NULL;
+ }
+ }
+ }
+ Gtk::TreeModel::iterator iter = _store->get_iter(target_path);
+ if (_store->iter_is_valid(iter)) {
+ Gtk::TreeModel::Row row = *iter;
+ //Set the drop target. If we're not dropping into a group, we cannot
+ //drop into it, so set _dnd_into false.
+ _dnd_target = row[_model->_colObject];
+ if (!(SP_IS_GROUP(_dnd_target))) _dnd_into = false;
+ }
+ }
+
+ _takeAction(DRAGNDROP);
+
+ return false;
+}
+
+/**
+ * Stores all selected items as the drag source
+ * @param iter Current tree item
+ */
+void ObjectsPanel::_storeDragSource(const Gtk::TreeModel::iterator& iter)
+{
+ Gtk::TreeModel::Row row = *iter;
+ SPItem* item = row[_model->_colObject];
+ if (item)
+ {
+ _dnd_source.push_back(item);
+ }
+}
+
+/*
+ * Move a layer in response to a drag & drop action
+ */
+void ObjectsPanel::_doTreeMove( )
+{
+ g_assert(_desktop != NULL);
+ g_assert(_document != NULL);
+
+ std::vector<gchar *> idvector;
+
+ //Clear the desktop selection
+ _desktop->selection->clear();
+ while (!_dnd_source.empty())
+ {
+ SPItem *obj = _dnd_source.back();
+ _dnd_source.pop_back();
+
+ if (obj != _dnd_target) {
+ //Store the object id (for selection later) and move the object
+ idvector.push_back(g_strdup(obj->getId()));
+ obj->moveTo(_dnd_target, _dnd_into);
+ }
+ }
+
+ //Select items
+ while (!idvector.empty()) {
+ //Grab the id from the vector, get the item in the document and select it
+ gchar * id = idvector.back();
+ idvector.pop_back();
+ SPObject *obj = _document->getObjectById(id);
+ g_free(id);
+ if (obj && SP_IS_ITEM(obj)) {
+ SPItem *item = SP_ITEM(obj);
+ if (!SP_IS_GROUP(item) || SP_GROUP(item)->layerMode() != SPGroup::LAYER)
+ {
+ if (_desktop->selection->isEmpty()) _desktop->setCurrentLayer(item->parent);
+ _desktop->selection->add(item);
+ }
+ else
+ {
+ if (_desktop->selection->isEmpty()) _desktop->setCurrentLayer(item);
+ }
+ }
+ }
+
+ DocumentUndo::done( _desktop->doc() , SP_VERB_NONE,
+ _("Moved objects"));
+}
+
+/**
+ * Fires the action verb
+ */
+void ObjectsPanel::_fireAction( unsigned int code )
+{
+ if ( _desktop ) {
+ Verb *verb = Verb::get( code );
+ if ( verb ) {
+ SPAction *action = verb->get_action(_desktop);
+ if ( action ) {
+ sp_action_perform( action, NULL );
+ }
+ }
+ }
+}
+
+/**
+ * Executes the given button action during the idle time
+ */
+void ObjectsPanel::_takeAction( int val )
+{
+ if ( !_pending ) {
+ _pending = new InternalUIBounce();
+ _pending->_actionCode = val;
+ Glib::signal_timeout().connect( sigc::mem_fun(*this, &ObjectsPanel::_executeAction), 0 );
+ }
+}
+
+/**
+ * Executes the pending button action
+ */
+bool ObjectsPanel::_executeAction()
+{
+ // Make sure selected layer hasn't changed since the action was triggered
+ if ( _document && _pending)
+ {
+ int val = _pending->_actionCode;
+// SPObject* target = _pending->_target;
+
+ switch ( val ) {
+ case BUTTON_NEW:
+ {
+ _fireAction( SP_VERB_LAYER_NEW );
+ }
+ break;
+ case BUTTON_RENAME:
+ {
+ _fireAction( SP_VERB_LAYER_RENAME );
+ }
+ break;
+ case BUTTON_TOP:
+ {
+ if (_desktop->selection->isEmpty())
+ {
+ _fireAction( SP_VERB_LAYER_TO_TOP );
+ }
+ else
+ {
+ _fireAction( SP_VERB_SELECTION_TO_FRONT);
+ }
+ }
+ break;
+ case BUTTON_BOTTOM:
+ {
+ if (_desktop->selection->isEmpty())
+ {
+ _fireAction( SP_VERB_LAYER_TO_BOTTOM );
+ }
+ else
+ {
+ _fireAction( SP_VERB_SELECTION_TO_BACK);
+ }
+ }
+ break;
+ case BUTTON_UP:
+ {
+ if (_desktop->selection->isEmpty())
+ {
+ _fireAction( SP_VERB_LAYER_RAISE );
+ }
+ else
+ {
+ _fireAction( SP_VERB_SELECTION_RAISE );
+ }
+ }
+ break;
+ case BUTTON_DOWN:
+ {
+ if (_desktop->selection->isEmpty())
+ {
+ _fireAction( SP_VERB_LAYER_LOWER );
+ }
+ else
+ {
+ _fireAction( SP_VERB_SELECTION_LOWER );
+ }
+ }
+ break;
+ case BUTTON_DUPLICATE:
+ {
+ if (_desktop->selection->isEmpty())
+ {
+ _fireAction( SP_VERB_LAYER_DUPLICATE );
+ }
+ else
+ {
+ _fireAction( SP_VERB_EDIT_DUPLICATE );
+ }
+ }
+ break;
+ case BUTTON_DELETE:
+ {
+ if (_desktop->selection->isEmpty())
+ {
+ _fireAction( SP_VERB_LAYER_DELETE );
+ }
+ else
+ {
+ _fireAction( SP_VERB_EDIT_DELETE );
+ }
+ }
+ break;
+ case BUTTON_SOLO:
+ {
+ _fireAction( SP_VERB_LAYER_SOLO );
+ }
+ break;
+ case BUTTON_SHOW_ALL:
+ {
+ _fireAction( SP_VERB_LAYER_SHOW_ALL );
+ }
+ break;
+ case BUTTON_HIDE_ALL:
+ {
+ _fireAction( SP_VERB_LAYER_HIDE_ALL );
+ }
+ break;
+ case BUTTON_LOCK_OTHERS:
+ {
+ _fireAction( SP_VERB_LAYER_LOCK_OTHERS );
+ }
+ break;
+ case BUTTON_LOCK_ALL:
+ {
+ _fireAction( SP_VERB_LAYER_LOCK_ALL );
+ }
+ break;
+ case BUTTON_UNLOCK_ALL:
+ {
+ _fireAction( SP_VERB_LAYER_UNLOCK_ALL );
+ }
+ break;
+ case BUTTON_CLIPGROUP:
+ {
+ _fireAction ( SP_VERB_OBJECT_CREATE_CLIP_GROUP );
+ }
+ case BUTTON_SETCLIP:
+ {
+ _fireAction( SP_VERB_OBJECT_SET_CLIPPATH );
+ }
+ break;
+ case BUTTON_UNSETCLIP:
+ {
+ _fireAction( SP_VERB_OBJECT_UNSET_CLIPPATH );
+ }
+ break;
+ case BUTTON_SETMASK:
+ {
+ _fireAction( SP_VERB_OBJECT_SET_MASK );
+ }
+ break;
+ case BUTTON_UNSETMASK:
+ {
+ _fireAction( SP_VERB_OBJECT_UNSET_MASK );
+ }
+ break;
+ case BUTTON_GROUP:
+ {
+ _fireAction( SP_VERB_SELECTION_GROUP );
+ }
+ break;
+ case BUTTON_UNGROUP:
+ {
+ _fireAction( SP_VERB_SELECTION_UNGROUP );
+ }
+ break;
+ case BUTTON_COLLAPSE_ALL:
+ {
+ for (SPObject* obj = _document->getRoot()->firstChild(); obj != NULL; obj = obj->next) {
+ if (SP_IS_GROUP(obj)) {
+ _setCollapsed(SP_GROUP(obj));
+ }
+ }
+ _objectsChanged(_document->getRoot());
+ }
+ break;
+ case DRAGNDROP:
+ {
+ _doTreeMove( );
+ }
+ break;
+ }
+
+ delete _pending;
+ _pending = 0;
+ }
+
+ return false;
+}
+
+/**
+ * Handles an unsuccessful item label edit (escape pressed, etc.)
+ */
+void ObjectsPanel::_handleEditingCancelled()
+{
+ _text_renderer->property_editable() = false;
+}
+
+/**
+ * Handle a successful item label edit
+ * @param path Tree path of the item currently being edited
+ * @param new_text New label text
+ */
+void ObjectsPanel::_handleEdited(const Glib::ustring& path, const Glib::ustring& new_text)
+{
+ Gtk::TreeModel::iterator iter = _tree.get_model()->get_iter(path);
+ Gtk::TreeModel::Row row = *iter;
+
+ _renameObject(row, new_text);
+ _text_renderer->property_editable() = false;
+}
+
+/**
+ * Renames an item in the tree
+ * @param row Tree row
+ * @param name New label to give to the item
+ */
+void ObjectsPanel::_renameObject(Gtk::TreeModel::Row row, const Glib::ustring& name)
+{
+ if ( row && _desktop) {
+ SPItem* item = row[_model->_colObject];
+ if ( item ) {
+ gchar const* oldLabel = item->label();
+ if ( !name.empty() && (!oldLabel || name != oldLabel) ) {
+ item->setLabel(name.c_str());
+ DocumentUndo::done( _desktop->doc() , SP_VERB_NONE,
+ _("Rename object"));
+ }
+ }
+ }
+}
+
+/**
+ * A row selection function used by the tree that doesn't allow any new items to be selected.
+ * Currently, this is used to allow multi-item drag & drop.
+ */
+bool ObjectsPanel::_noSelection( Glib::RefPtr<Gtk::TreeModel> const & /*model*/, Gtk::TreeModel::Path const & /*path*/, bool /*currentlySelected*/ )
+{
+ return false;
+}
+
+/**
+ * Default row selection function taken from the layers dialog
+ */
+bool ObjectsPanel::_rowSelectFunction( Glib::RefPtr<Gtk::TreeModel> const & /*model*/, Gtk::TreeModel::Path const & /*path*/, bool currentlySelected )
+{
+ bool val = true;
+ if ( !currentlySelected && _toggleEvent )
+ {
+ GdkEvent* event = gtk_get_current_event();
+ if ( event ) {
+ // (keep these checks separate, so we know when to call gdk_event_free()
+ if ( event->type == GDK_BUTTON_PRESS ) {
+ GdkEventButton const* target = reinterpret_cast<GdkEventButton const*>(_toggleEvent);
+ GdkEventButton const* evtb = reinterpret_cast<GdkEventButton const*>(event);
+
+ if ( (evtb->window == target->window)
+ && (evtb->send_event == target->send_event)
+ && (evtb->time == target->time)
+ && (evtb->state == target->state)
+ )
+ {
+ // Ooooh! It's a magic one
+ val = false;
+ }
+ }
+ gdk_event_free(event);
+ }
+ }
+ return val;
+}
+
+/**
+ * Sets a group to be collapsed and recursively collapses its children
+ * @param group The group to collapse
+ */
+void ObjectsPanel::_setCollapsed(SPGroup * group)
+{
+ group->setExpanded(false);
+ group->updateRepr(SP_OBJECT_WRITE_NO_CHILDREN | SP_OBJECT_WRITE_EXT);
+ for (SPObject *iter = group->children; iter != NULL; iter = iter->next)
+ {
+ if (SP_IS_GROUP(iter)) _setCollapsed(SP_GROUP(iter));
+ }
+}
+
+/**
+ * Sets a group to be expanded or collapsed
+ * @param iter Current tree item
+ * @param isexpanded Whether to expand or collapse
+ */
+void ObjectsPanel::_setExpanded(const Gtk::TreeModel::iterator& iter, const Gtk::TreeModel::Path& /*path*/, bool isexpanded)
+{
+ Gtk::TreeModel::Row row = *iter;
+
+ SPItem* item = row[_model->_colObject];
+ if (item && SP_IS_GROUP(item))
+ {
+ if (isexpanded)
+ {
+ //If we're expanding, simply perform the expansion
+ SP_GROUP(item)->setExpanded(isexpanded);
+ item->updateRepr(SP_OBJECT_WRITE_NO_CHILDREN | SP_OBJECT_WRITE_EXT);
+ }
+ else
+ {
+ //If we're collapsing, we need to recursively collapse, so call our helper function
+ _setCollapsed(SP_GROUP(item));
+ }
+ }
+}
+
+/**
+ * Callback for when the highlight color is changed
+ * @param csel Color selector
+ * @param cp Objects panel
+ */
+void sp_highlight_picker_color_mod(SPColorSelector *csel, GObject * cp)
+{
+ SPColor color;
+ float alpha = 0;
+ csel->base->getColorAlpha(color, alpha);
+ guint32 rgba = color.toRGBA32( alpha );
+
+ ObjectsPanel *ptr = reinterpret_cast<ObjectsPanel *>(cp);
+
+ //Set the highlight color for all items in the _highlight_target (all selected items)
+ for (std::vector<SPItem *>::iterator iter = ptr->_highlight_target.begin(); iter != ptr->_highlight_target.end(); ++iter)
+ {
+ SPItem * target = *iter;
+ target->setHighlightColor(rgba);
+ target->updateRepr(SP_OBJECT_WRITE_NO_CHILDREN | SP_OBJECT_WRITE_EXT);
+ }
+ DocumentUndo::maybeDone(SP_ACTIVE_DOCUMENT, "highlight", SP_VERB_DIALOG_OBJECTS, _("Set object highlight color"));
+}
+
+/**
+ * Callback for when the opacity value is changed
+ */
+void ObjectsPanel::_opacityValueChanged()
+{
+ _blockCompositeUpdate = true;
+ _tree.get_selection()->selected_foreach_iter(sigc::mem_fun(*this, &ObjectsPanel::_opacityChangedIter));
+ DocumentUndo::maybeDone(_document, "opacity", SP_VERB_DIALOG_OBJECTS, _("Set object opacity"));
+ _blockCompositeUpdate = false;
+}
+
+/**
+ * Change the opacity of the selected items in the tree
+ * @param iter Current tree item
+ */
+void ObjectsPanel::_opacityChangedIter(const Gtk::TreeIter& iter)
+{
+ Gtk::TreeModel::Row row = *iter;
+ SPItem* item = row[_model->_colObject];
+ if (item)
+ {
+ item->style->opacity.set = TRUE;
+#if WITH_GTKMM_3_0
+ item->style->opacity.value = SP_SCALE24_FROM_FLOAT(_opacity_adjustment->get_value() / _opacity_adjustment->get_upper());
+#else
+ item->style->opacity.value = SP_SCALE24_FROM_FLOAT(_opacity_adjustment.get_value() / _opacity_adjustment.get_upper());
+#endif
+ item->updateRepr(SP_OBJECT_WRITE_NO_CHILDREN | SP_OBJECT_WRITE_EXT);
+ }
+}
+
+/**
+ * Callback for when the blend mode is changed
+ */
+void ObjectsPanel::_blendValueChanged()
+{
+ _blockCompositeUpdate = true;
+ const Glib::ustring blendmode = _fe_cb.get_blend_mode();
+
+ _tree.get_selection()->selected_foreach_iter(sigc::bind<Glib::ustring>(sigc::mem_fun(*this, &ObjectsPanel::_blendChangedIter), blendmode));
+ DocumentUndo::done(_document, SP_VERB_DIALOG_OBJECTS, _("Set object blend mode"));
+ _blockCompositeUpdate = false;
+}
+
+/**
+ * Sets the blend mode of the selected tree items
+ * @param iter Current tree item
+ * @param blendmode Blend mode to set
+ */
+void ObjectsPanel::_blendChangedIter(const Gtk::TreeIter& iter, Glib::ustring blendmode)
+{
+ Gtk::TreeModel::Row row = *iter;
+ SPItem* item = row[_model->_colObject];
+ if (item)
+ {
+ //Since blur and blend are both filters, we need to set both at the same time
+ SPStyle *style = item->style;
+ g_assert(style != NULL);
+
+ if (blendmode != "normal") {
+ gdouble radius = 0;
+ if (item->style->getFilter()) {
+ for (SPObject *primitive = item->style->getFilter()->children; primitive && SP_IS_FILTER_PRIMITIVE(primitive); primitive = primitive->next) {
+ if (SP_IS_GAUSSIANBLUR(primitive)) {
+ Geom::OptRect bbox = item->bounds(SPItem::GEOMETRIC_BBOX);
+ if (bbox) {
+ radius = SP_GAUSSIANBLUR(primitive)->stdDeviation.getNumber();
+ }
+ }
+ }
+ }
+ SPFilter *filter = new_filter_simple_from_item(_document, item, blendmode.c_str(), radius);
+ sp_style_set_property_url(item, "filter", filter, false);
+ } else {
+ for (SPObject *primitive = item->style->getFilter()->children; primitive && SP_IS_FILTER_PRIMITIVE(primitive); primitive = primitive->next) {
+ if (SP_IS_FEBLEND(primitive)) {
+ primitive->deleteObject();
+ break;
+ }
+ }
+ if (!item->style->getFilter()->children) {
+ remove_filter(item, false);
+ }
+ }
+
+ item->updateRepr(SP_OBJECT_WRITE_NO_CHILDREN | SP_OBJECT_WRITE_EXT);
+ }
+}
+
+/**
+ * Callback for when the blur value has changed
+ */
+void ObjectsPanel::_blurValueChanged()
+{
+ _blockCompositeUpdate = true;
+ _tree.get_selection()->selected_foreach_iter(sigc::bind<double>(sigc::mem_fun(*this, &ObjectsPanel::_blurChangedIter), _fe_blur.get_blur_value()));
+ DocumentUndo::maybeDone(_document, "blur", SP_VERB_DIALOG_OBJECTS, _("Set object blur"));
+ _blockCompositeUpdate = false;
+}
+
+/**
+ * Sets the blur value for the selected items in the tree
+ * @param iter Current tree item
+ * @param blur Blur value to set
+ */
+void ObjectsPanel::_blurChangedIter(const Gtk::TreeIter& iter, double blur)
+{
+ Gtk::TreeModel::Row row = *iter;
+ SPItem* item = row[_model->_colObject];
+ if (item)
+ {
+ //Since blur and blend are both filters, we need to set both at the same time
+ SPStyle *style = item->style;
+ if (style) {
+ Geom::OptRect bbox = item->bounds(SPItem::GEOMETRIC_BBOX);
+ double radius;
+ if (bbox) {
+ double perimeter = bbox->dimensions()[Geom::X] + bbox->dimensions()[Geom::Y]; // fixme: this is only half the perimeter, is that correct?
+ radius = blur * perimeter / 400;
+ } else {
+ radius = 0;
+ }
+
+ if (radius != 0) {
+ SPFilter *filter = modify_filter_gaussian_blur_from_item(_document, item, radius);
+ sp_style_set_property_url(item, "filter", filter, false);
+ } else if (item->style->filter.set && item->style->getFilter()) {
+ for (SPObject *primitive = item->style->getFilter()->children; primitive && SP_IS_FILTER_PRIMITIVE(primitive); primitive = primitive->next) {
+ if (SP_IS_GAUSSIANBLUR(primitive)) {
+ primitive->deleteObject();
+ break;
+ }
+ }
+ if (!item->style->getFilter()->children) {
+ remove_filter(item, false);
+ }
+ }
+ item->updateRepr(SP_OBJECT_WRITE_NO_CHILDREN | SP_OBJECT_WRITE_EXT);
+ }
+ }
+}
+
+/**
+ * Constructor
+ */
+ObjectsPanel::ObjectsPanel() :
+ UI::Widget::Panel("", "/dialogs/objects", SP_VERB_DIALOG_OBJECTS),
+ _rootWatcher(0),
+ _deskTrack(),
+ _desktop(0),
+ _document(0),
+ _model(0),
+ _pending(0),
+ _toggleEvent(0),
+ _defer_target(),
+ _composite_vbox(false, 0),
+ _opacity_vbox(false, 0),
+ _opacity_label(_("Opacity:")),
+ _opacity_label_unit(_("%")),
+#if WITH_GTKMM_3_0
+ _opacity_adjustment(Gtk::Adjustment::create(100.0, 0.0, 100.0, 1.0, 1.0, 0.0)),
+#else
+ _opacity_adjustment(100.0, 0.0, 100.0, 1.0, 1.0, 0.0),
+#endif
+ _opacity_hscale(_opacity_adjustment),
+ _opacity_spin_button(_opacity_adjustment, 0.01, 1),
+ _fe_cb(UI::Widget::SimpleFilterModifier::BLEND),
+ _fe_vbox(false, 0),
+ _fe_alignment(1, 1, 1, 1),
+ _fe_blur(UI::Widget::SimpleFilterModifier::BLUR),
+ _blur_vbox(false, 0),
+ _blur_alignment(1, 1, 1, 1),
+ _colorSelectorDialog("dialogs.colorpickerwindow")
+{
+ //Create the tree model and store
+ ModelColumns *zoop = new ModelColumns();
+ _model = zoop;
+
+ _store = Gtk::TreeStore::create( *zoop );
+
+ //Set up the tree
+ _tree.set_model( _store );
+ _tree.set_headers_visible(false);
+ _tree.set_reorderable(true);
+ _tree.enable_model_drag_dest (Gdk::ACTION_MOVE);
+
+ //Create the column CellRenderers
+ //Visible
+ Inkscape::UI::Widget::ImageToggler *eyeRenderer = Gtk::manage( new Inkscape::UI::Widget::ImageToggler(
+ INKSCAPE_ICON("object-visible"), INKSCAPE_ICON("object-hidden")) );
+ int visibleColNum = _tree.append_column("vis", *eyeRenderer) - 1;
+ eyeRenderer->property_activatable() = true;
+ Gtk::TreeViewColumn* col = _tree.get_column(visibleColNum);
+ if ( col ) {
+ col->add_attribute( eyeRenderer->property_active(), _model->_colVisible );
+ }
+
+ //Locked
+ Inkscape::UI::Widget::ImageToggler * renderer = Gtk::manage( new Inkscape::UI::Widget::ImageToggler(
+ INKSCAPE_ICON("object-locked"), INKSCAPE_ICON("object-unlocked")) );
+ int lockedColNum = _tree.append_column("lock", *renderer) - 1;
+ renderer->property_activatable() = true;
+ col = _tree.get_column(lockedColNum);
+ if ( col ) {
+ col->add_attribute( renderer->property_active(), _model->_colLocked );
+ }
+
+ //Type
+ Inkscape::UI::Widget::LayerTypeIcon * typeRenderer = Gtk::manage( new Inkscape::UI::Widget::LayerTypeIcon());
+ int typeColNum = _tree.append_column("type", *typeRenderer) - 1;
+ typeRenderer->property_activatable() = true;
+ col = _tree.get_column(typeColNum);
+ if ( col ) {
+ col->add_attribute( typeRenderer->property_active(), _model->_colType );
+ }
+
+ //Insert order (LiamW: unused)
+ /*Inkscape::UI::Widget::InsertOrderIcon * insertRenderer = Gtk::manage( new Inkscape::UI::Widget::InsertOrderIcon());
+ int insertColNum = _tree.append_column("type", *insertRenderer) - 1;
+ col = _tree.get_column(insertColNum);
+ if ( col ) {
+ col->add_attribute( insertRenderer->property_active(), _model->_colInsertOrder );
+ }*/
+
+ //Clip/mask
+ Inkscape::UI::Widget::ClipMaskIcon * clipRenderer = Gtk::manage( new Inkscape::UI::Widget::ClipMaskIcon());
+ int clipColNum = _tree.append_column("clipmask", *clipRenderer) - 1;
+ col = _tree.get_column(clipColNum);
+ if ( col ) {
+ col->add_attribute( clipRenderer->property_active(), _model->_colClipMask );
+ }
+
+ //Highlight
+ Inkscape::UI::Widget::HighlightPicker * highlightRenderer = Gtk::manage( new Inkscape::UI::Widget::HighlightPicker());
+ int highlightColNum = _tree.append_column("highlight", *highlightRenderer) - 1;
+ col = _tree.get_column(highlightColNum);
+ if ( col ) {
+ col->add_attribute( highlightRenderer->property_active(), _model->_colHighlight );
+ }
+
+ //Label
+ _text_renderer = Gtk::manage(new Gtk::CellRendererText());
+ int nameColNum = _tree.append_column("Name", *_text_renderer) - 1;
+ _name_column = _tree.get_column(nameColNum);
+ _name_column->add_attribute(_text_renderer->property_text(), _model->_colLabel);
+
+ //Set the expander and search columns
+ _tree.set_expander_column( *_tree.get_column(nameColNum) );
+ _tree.set_search_column(_model->_colLabel);
+
+ //Set up the tree selection
+ _tree.get_selection()->set_mode(Gtk::SELECTION_MULTIPLE);
+ _selectedConnection = _tree.get_selection()->signal_changed().connect( sigc::mem_fun(*this, &ObjectsPanel::_pushTreeSelectionToCurrent) );
+ _tree.get_selection()->set_select_function( sigc::mem_fun(*this, &ObjectsPanel::_rowSelectFunction) );
+
+ //Set up tree signals
+ _tree.signal_button_press_event().connect( sigc::mem_fun(*this, &ObjectsPanel::_handleButtonEvent), false );
+ _tree.signal_button_release_event().connect( sigc::mem_fun(*this, &ObjectsPanel::_handleButtonEvent), false );
+ _tree.signal_key_press_event().connect( sigc::mem_fun(*this, &ObjectsPanel::_handleKeyEvent), false );
+ _tree.signal_drag_drop().connect( sigc::mem_fun(*this, &ObjectsPanel::_handleDragDrop), false);
+ _tree.signal_row_collapsed().connect( sigc::bind<bool>(sigc::mem_fun(*this, &ObjectsPanel::_setExpanded), false));
+ _tree.signal_row_expanded().connect( sigc::bind<bool>(sigc::mem_fun(*this, &ObjectsPanel::_setExpanded), true));
+
+ //Set up the label editing signals
+ _text_renderer->signal_edited().connect( sigc::mem_fun(*this, &ObjectsPanel::_handleEdited) );
+ _text_renderer->signal_editing_canceled().connect( sigc::mem_fun(*this, &ObjectsPanel::_handleEditingCancelled) );
+
+ //Set up the scroller window and pack the page
+ _scroller.add( _tree );
+ _scroller.set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC );
+ _scroller.set_shadow_type(Gtk::SHADOW_IN);
+ Gtk::Requisition sreq;
+#if WITH_GTKMM_3_0
+ Gtk::Requisition sreq_natural;
+ _scroller.get_preferred_size(sreq_natural, sreq);
+#else
+ sreq = _scroller.size_request();
+#endif
+ int minHeight = 70;
+ if (sreq.height < minHeight) {
+ // Set a min height to see the layers when used with Ubuntu liboverlay-scrollbar
+ _scroller.set_size_request(sreq.width, minHeight);
+ }
+
+ _page.pack_start( _scroller, Gtk::PACK_EXPAND_WIDGET );
+
+ //Set up the compositing items
+ //Blend mode filter effect
+ _composite_vbox.pack_start(_fe_vbox, false, false, 2);
+ _fe_alignment.set_padding(0, 0, 4, 0);
+ _fe_alignment.add(_fe_cb);
+ _fe_vbox.pack_start(_fe_alignment, false, false, 0);
+ _blendConnection = _fe_cb.signal_blend_blur_changed().connect(sigc::mem_fun(*this, &ObjectsPanel::_blendValueChanged));
+
+ //Blur filter effect
+ _composite_vbox.pack_start(_blur_vbox, false, false, 2);
+ _blur_alignment.set_padding(0, 0, 4, 0);
+ _blur_alignment.add(_fe_blur);
+ _blur_vbox.pack_start(_blur_alignment, false, false, 0);
+ _blurConnection = _fe_blur.signal_blend_blur_changed().connect(sigc::mem_fun(*this, &ObjectsPanel::_blurValueChanged));
+
+ //Opacity
+ _composite_vbox.pack_start(_opacity_vbox, false, false, 2);
+ _opacity_label.set_alignment(Gtk::ALIGN_END, Gtk::ALIGN_CENTER);
+ _opacity_hbox.pack_start(_opacity_label, false, false, 3);
+ _opacity_vbox.pack_start(_opacity_hbox, false, false, 0);
+ _opacity_hbox.pack_start(_opacity_hscale, true, true, 0);
+ _opacity_hbox.pack_start(_opacity_spin_button, false, false, 0);
+ _opacity_hbox.pack_start(_opacity_label_unit, false, false, 3);
+ _opacity_hscale.set_draw_value(false);
+#if WITH_GTKMM_3_0
+ _opacityConnection = _opacity_adjustment->signal_value_changed().connect(sigc::mem_fun(*this, &ObjectsPanel::_opacityValueChanged));
+ _opacity_label.set_mnemonic_widget(_opacity_hscale);
+#else
+ _opacityConnection = _opacity_adjustment.signal_value_changed().connect(sigc::mem_fun(*this, &ObjectsPanel::_opacityValueChanged));
+ _opacity_label.set_mnemonic_widget(_opacity_hscale);
+#endif
+
+ //Keep the labels aligned
+ GtkSizeGroup *labels = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
+ gtk_size_group_add_widget(labels, GTK_WIDGET(_opacity_label.gobj()));
+ gtk_size_group_add_widget(labels, GTK_WIDGET(_fe_cb.get_blur_label()->gobj()));
+ gtk_size_group_add_widget(labels, GTK_WIDGET(_fe_blur.get_blur_label()->gobj()));
+
+ //Pack the compositing functions and the button row
+ _page.pack_end(_composite_vbox, Gtk::PACK_SHRINK);
+ _page.pack_end(_buttonsRow, Gtk::PACK_SHRINK);
+
+ //Pack into the panel contents
+ _getContents()->pack_start(_page, Gtk::PACK_EXPAND_WIDGET);
+
+ SPDesktop* targetDesktop = getDesktop();
+
+ //Set up the button row
+
+
+ //Add object/layer
+ Gtk::Button* btn = Gtk::manage( new Gtk::Button() );
+ btn->set_tooltip_text(_("Add layer..."));
+#if GTK_CHECK_VERSION(3,10,0)
+ btn->set_image_from_icon_name(INKSCAPE_ICON("list-add"), Gtk::ICON_SIZE_SMALL_TOOLBAR);
+#else
+ Gtk::Image *image_add = Gtk::manage(new Gtk::Image());
+ image_add->set_from_icon_name(INKSCAPE_ICON("list-add"), Gtk::ICON_SIZE_SMALL_TOOLBAR);
+ btn->set_image(*image_add);
+#endif
+ btn->set_relief(Gtk::RELIEF_NONE);
+ btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &ObjectsPanel::_takeAction), (int)BUTTON_NEW) );
+ _buttonsSecondary.pack_start(*btn, Gtk::PACK_SHRINK);
+
+
+ //Remove object
+ btn = Gtk::manage( new Gtk::Button() );
+ btn->set_tooltip_text(_("Remove object"));
+#if GTK_CHECK_VERSION(3,10,0)
+ btn->set_image_from_icon_name(INKSCAPE_ICON("list-remove"), Gtk::ICON_SIZE_SMALL_TOOLBAR);
+#else
+ Gtk::Image *image_remove = Gtk::manage(new Gtk::Image());
+ image_remove->set_from_icon_name(INKSCAPE_ICON("list-remove"), Gtk::ICON_SIZE_SMALL_TOOLBAR);
+ btn->set_image(*image_remove);
+#endif
+ btn->set_relief(Gtk::RELIEF_NONE);
+ btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &ObjectsPanel::_takeAction), (int)BUTTON_DELETE) );
+ _watching.push_back( btn );
+ _buttonsSecondary.pack_start(*btn, Gtk::PACK_SHRINK);
+
+ //Move to bottom
+ btn = Gtk::manage( new Gtk::Button() );
+ btn->set_tooltip_text(_("Move To Bottom"));
+#if GTK_CHECK_VERSION(3,10,0)
+ btn->set_image_from_icon_name(INKSCAPE_ICON("go-bottom"), Gtk::ICON_SIZE_SMALL_TOOLBAR);
+#else
+ image_remove = Gtk::manage(new Gtk::Image());
+ image_remove->set_from_icon_name(INKSCAPE_ICON("go-bottom"), Gtk::ICON_SIZE_SMALL_TOOLBAR);
+ btn->set_image(*image_remove);
+#endif
+ btn->set_relief(Gtk::RELIEF_NONE);
+ btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &ObjectsPanel::_takeAction), (int)BUTTON_BOTTOM) );
+ _watchingNonBottom.push_back( btn );
+ _buttonsPrimary.pack_end(*btn, Gtk::PACK_SHRINK);
+
+ //Move down
+ btn = Gtk::manage( new Gtk::Button() );
+ btn->set_tooltip_text(_("Move Down"));
+#if GTK_CHECK_VERSION(3,10,0)
+ btn->set_image_from_icon_name(INKSCAPE_ICON("go-down"), Gtk::ICON_SIZE_SMALL_TOOLBAR);
+#else
+ image_remove = Gtk::manage(new Gtk::Image());
+ image_remove->set_from_icon_name(INKSCAPE_ICON("go-down"), Gtk::ICON_SIZE_SMALL_TOOLBAR);
+ btn->set_image(*image_remove);
+#endif
+ btn->set_relief(Gtk::RELIEF_NONE);
+ btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &ObjectsPanel::_takeAction), (int)BUTTON_DOWN) );
+ _watchingNonBottom.push_back( btn );
+ _buttonsPrimary.pack_end(*btn, Gtk::PACK_SHRINK);
+
+ //Move up
+ btn = Gtk::manage( new Gtk::Button() );
+ btn->set_tooltip_text(_("Move Up"));
+#if GTK_CHECK_VERSION(3,10,0)
+ btn->set_image_from_icon_name(INKSCAPE_ICON("go-up"), Gtk::ICON_SIZE_SMALL_TOOLBAR);
+#else
+ image_remove = Gtk::manage(new Gtk::Image());
+ image_remove->set_from_icon_name(INKSCAPE_ICON("go-up"), Gtk::ICON_SIZE_SMALL_TOOLBAR);
+ btn->set_image(*image_remove);
+#endif
+ btn->set_relief(Gtk::RELIEF_NONE);
+ btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &ObjectsPanel::_takeAction), (int)BUTTON_UP) );
+ _watchingNonTop.push_back( btn );
+ _buttonsPrimary.pack_end(*btn, Gtk::PACK_SHRINK);
+
+ //Move to top
+ btn = Gtk::manage( new Gtk::Button() );
+ btn->set_tooltip_text(_("Move To Top"));
+#if GTK_CHECK_VERSION(3,10,0)
+ btn->set_image_from_icon_name(INKSCAPE_ICON("go-top"), Gtk::ICON_SIZE_SMALL_TOOLBAR);
+#else
+ image_remove = Gtk::manage(new Gtk::Image());
+ image_remove->set_from_icon_name(INKSCAPE_ICON("go-top"), Gtk::ICON_SIZE_SMALL_TOOLBAR);
+ btn->set_image(*image_remove);
+#endif
+ btn->set_relief(Gtk::RELIEF_NONE);
+ btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &ObjectsPanel::_takeAction), (int)BUTTON_TOP) );
+ _watchingNonTop.push_back( btn );
+ _buttonsPrimary.pack_end(*btn, Gtk::PACK_SHRINK);
+
+ //Collapse all
+ btn = Gtk::manage( new Gtk::Button() );
+ btn->set_tooltip_text(_("Collapse All"));
+#if GTK_CHECK_VERSION(3,10,0)
+ btn->set_image_from_icon_name(INKSCAPE_ICON("gtk-unindent-ltr"), Gtk::ICON_SIZE_SMALL_TOOLBAR);
+#else
+ image_remove = Gtk::manage(new Gtk::Image());
+ image_remove->set_from_icon_name(INKSCAPE_ICON("gtk-unindent-ltr"), Gtk::ICON_SIZE_SMALL_TOOLBAR);
+ btn->set_image(*image_remove);
+#endif
+ btn->set_relief(Gtk::RELIEF_NONE);
+ btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &ObjectsPanel::_takeAction), (int)BUTTON_COLLAPSE_ALL) );
+ _watchingNonBottom.push_back( btn );
+ _buttonsPrimary.pack_end(*btn, Gtk::PACK_SHRINK);
+
+ _buttonsRow.pack_start(_buttonsSecondary, Gtk::PACK_EXPAND_WIDGET);
+ _buttonsRow.pack_end(_buttonsPrimary, Gtk::PACK_EXPAND_WIDGET);
+
+ _watching.push_back(&_composite_vbox);
+
+ //Set up the pop-up menu
+ // -------------------------------------------------------
+ {
+ _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_RENAME, 0, "Rename", (int)BUTTON_RENAME ) );
+ _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_EDIT_DUPLICATE, 0, "Duplicate", (int)BUTTON_DUPLICATE ) );
+ _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_NEW, 0, "New", (int)BUTTON_NEW ) );
+
+ _popupMenu.append(*Gtk::manage(new Gtk::SeparatorMenuItem()));
+
+ _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_SOLO, 0, "Solo", (int)BUTTON_SOLO ) );
+ _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_SHOW_ALL, 0, "Show All", (int)BUTTON_SHOW_ALL ) );
+ _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_HIDE_ALL, 0, "Hide All", (int)BUTTON_HIDE_ALL ) );
+
+ _popupMenu.append(*Gtk::manage(new Gtk::SeparatorMenuItem()));
+
+ _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_LOCK_OTHERS, 0, "Lock Others", (int)BUTTON_LOCK_OTHERS ) );
+ _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_LOCK_ALL, 0, "Lock All", (int)BUTTON_LOCK_ALL ) );
+ _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_UNLOCK_ALL, 0, "Unlock All", (int)BUTTON_UNLOCK_ALL ) );
+
+ _popupMenu.append(*Gtk::manage(new Gtk::SeparatorMenuItem()));
+
+ _watchingNonTop.push_back( &_addPopupItem( targetDesktop, SP_VERB_SELECTION_RAISE, GTK_STOCK_GO_UP, "Up", (int)BUTTON_UP ) );
+ _watchingNonBottom.push_back( &_addPopupItem( targetDesktop, SP_VERB_SELECTION_LOWER, GTK_STOCK_GO_DOWN, "Down", (int)BUTTON_DOWN ) );
+
+ _popupMenu.append(*Gtk::manage(new Gtk::SeparatorMenuItem()));
+
+ _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_SELECTION_GROUP, 0, "Group", (int)BUTTON_GROUP ) );
+ _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_SELECTION_UNGROUP, 0, "Ungroup", (int)BUTTON_UNGROUP ) );
+
+ _popupMenu.append(*Gtk::manage(new Gtk::SeparatorMenuItem()));
+
+ _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_OBJECT_SET_CLIPPATH, 0, "Set Clip", (int)BUTTON_SETCLIP ) );
+
+ _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_OBJECT_CREATE_CLIP_GROUP, 0, "Create Clip Group", (int)BUTTON_CLIPGROUP ) );
+
+ //will never be implemented
+ //_watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_OBJECT_SET_INVERSE_CLIPPATH, 0, "Set Inverse Clip", (int)BUTTON_SETINVCLIP ) );
+ _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_OBJECT_UNSET_CLIPPATH, 0, "Unset Clip", (int)BUTTON_UNSETCLIP ) );
+
+ _popupMenu.append(*Gtk::manage(new Gtk::SeparatorMenuItem()));
+
+ _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_OBJECT_SET_MASK, 0, "Set Mask", (int)BUTTON_SETMASK ) );
+ _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_OBJECT_UNSET_MASK, 0, "Unset Mask", (int)BUTTON_UNSETMASK ) );
+
+ _popupMenu.show_all_children();
+ }
+ // -------------------------------------------------------
+
+ //Set initial sensitivity of buttons
+ for ( std::vector<Gtk::Widget*>::iterator it = _watching.begin(); it != _watching.end(); ++it ) {
+ (*it)->set_sensitive( false );
+ }
+ for ( std::vector<Gtk::Widget*>::iterator it = _watchingNonTop.begin(); it != _watchingNonTop.end(); ++it ) {
+ (*it)->set_sensitive( false );
+ }
+ for ( std::vector<Gtk::Widget*>::iterator it = _watchingNonBottom.begin(); it != _watchingNonBottom.end(); ++it ) {
+ (*it)->set_sensitive( false );
+ }
+
+ //Set up the color selection dialog
+ GtkWidget *dlg = GTK_WIDGET(_colorSelectorDialog.gobj());
+ sp_transientize(dlg);
+
+ _colorSelectorDialog.hide();
+ _colorSelectorDialog.set_title (_("Select Highlight Color"));
+ _colorSelectorDialog.set_border_width (4);
+ _colorSelectorDialog.property_modal() = true;
+ _colorSelector = SP_COLOR_SELECTOR(sp_color_selector_new(SP_TYPE_COLOR_NOTEBOOK));
+ _colorSelectorDialog.get_vbox()->pack_start (
+ *Glib::wrap(&_colorSelector->vbox), true, true, 0);
+
+ g_signal_connect(G_OBJECT(_colorSelector), "dragged",
+ G_CALLBACK(sp_highlight_picker_color_mod), (void *)this);
+ g_signal_connect(G_OBJECT(_colorSelector), "released",
+ G_CALLBACK(sp_highlight_picker_color_mod), (void *)this);
+ g_signal_connect(G_OBJECT(_colorSelector), "changed",
+ G_CALLBACK(sp_highlight_picker_color_mod), (void *)this);
+
+ gtk_widget_show(GTK_WIDGET(_colorSelector));
+
+ setDesktop( targetDesktop );
+
+ show_all_children();
+
+ //Connect the desktop changed connection
+ desktopChangeConn = _deskTrack.connectDesktopChanged( sigc::mem_fun(*this, &ObjectsPanel::setDesktop) );
+ _deskTrack.connect(GTK_WIDGET(gobj()));
+}
+
+/**
+ * Destructor
+ */
+ObjectsPanel::~ObjectsPanel()
+{
+ //Close the highlight selection dialog
+ _colorSelectorDialog.hide();
+ _colorSelector = NULL;
+
+ //Set the desktop to null, which will disconnect all object watchers
+ setDesktop(NULL);
+
+ if ( _model )
+ {
+ delete _model;
+ _model = 0;
+ }
+
+ if (_pending) {
+ delete _pending;
+ _pending = 0;
+ }
+
+ if ( _toggleEvent )
+ {
+ gdk_event_free( _toggleEvent );
+ _toggleEvent = 0;
+ }
+
+ desktopChangeConn.disconnect();
+ _deskTrack.disconnect();
+}
+
+/**
+ * Sets the current document
+ */
+void ObjectsPanel::setDocument(SPDesktop* /*desktop*/, SPDocument* document)
+{
+ //Clear all object watchers
+ while (!_objectWatchers.empty())
+ {
+ ObjectsPanel::ObjectWatcher *w = _objectWatchers.back();
+ w->_repr->removeObserver(*w);
+ _objectWatchers.pop_back();
+ delete w;
+ }
+
+ //Delete the root watcher
+ if (_rootWatcher)
+ {
+ _rootWatcher->_repr->removeObserver(*_rootWatcher);
+ delete _rootWatcher;
+ _rootWatcher = NULL;
+ }
+
+ _document = document;
+
+ if (document && document->getRoot() && document->getRoot()->getRepr())
+ {
+ //Create a new root watcher for the document and then call _objectsChanged to fill the tree
+ _rootWatcher = new ObjectsPanel::ObjectWatcher(this, document->getRoot());
+ document->getRoot()->getRepr()->addObserver(*_rootWatcher);
+ _objectsChanged(document->getRoot());
+ }
+}
+
+/**
+ * Set the current panel desktop
+ */
+void ObjectsPanel::setDesktop( SPDesktop* desktop )
+{
+ Panel::setDesktop(desktop);
+
+ if ( desktop != _desktop ) {
+ _documentChangedConnection.disconnect();
+ _selectionChangedConnection.disconnect();
+ if ( _desktop ) {
+ _desktop = 0;
+ }
+
+ _desktop = Panel::getDesktop();
+ if ( _desktop ) {
+ //Connect desktop signals
+ _documentChangedConnection = _desktop->connectDocumentReplaced( sigc::mem_fun(*this, &ObjectsPanel::setDocument));
+ _selectionChangedConnection = _desktop->selection->connectChanged( sigc::mem_fun(*this, &ObjectsPanel::_objectsSelected));
+
+ setDocument(_desktop, _desktop->doc());
+ } else {
+ setDocument(NULL, NULL);
+ }
+ }
+ _deskTrack.setBase(desktop);
+}
+} //namespace Dialogs
+} //namespace UI
+} //namespace Inkscape
+
+//should be okay to put these here because they are never referenced anywhere else
+using namespace Inkscape::UI::Tools;
+
+void SPItem::setHighlightColor(guint32 const color)
+{
+ g_free(_highlightColor);
+ if (color & 0x000000ff)
+ {
+ _highlightColor = g_strdup_printf("%u", color);
+ }
+ else
+ {
+ _highlightColor = NULL;
+ }
+
+ NodeTool *tool = 0;
+ if (SP_ACTIVE_DESKTOP ) {
+ Inkscape::UI::Tools::ToolBase *ec = SP_ACTIVE_DESKTOP->event_context;
+ if (INK_IS_NODE_TOOL(ec)) {
+ tool = static_cast<NodeTool*>(ec);
+ tools_switch(tool->desktop, TOOLS_NODES);
+ }
+ }
+}
+
+void SPItem::unsetHighlightColor()
+{
+ g_free(_highlightColor);
+ _highlightColor = NULL;
+ NodeTool *tool = 0;
+ if (SP_ACTIVE_DESKTOP ) {
+ Inkscape::UI::Tools::ToolBase *ec = SP_ACTIVE_DESKTOP->event_context;
+ if (INK_IS_NODE_TOOL(ec)) {
+ tool = static_cast<NodeTool*>(ec);
+ tools_switch(tool->desktop, TOOLS_NODES);
+ }
+ }
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/ui/dialog/objects.h b/src/ui/dialog/objects.h
new file mode 100644
index 000000000..74c2382ac
--- /dev/null
+++ b/src/ui/dialog/objects.h
@@ -0,0 +1,263 @@
+/*
+ * A simple dialog for objects UI.
+ *
+ * Authors:
+ * Theodore Janeczko
+ *
+ * Copyright (C) Theodore Janeczko 2012 <flutterguy317@gmail.com>
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifndef SEEN_OBJECTS_PANEL_H
+#define SEEN_OBJECTS_PANEL_H
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#if GLIBMM_DISABLE_DEPRECATED && HAVE_GLIBMM_THREADS_H
+# include <glibmm/threads.h>
+#endif
+
+#include <gtkmm/box.h>
+#include <gtkmm/treeview.h>
+#include <gtkmm/treestore.h>
+#include <gtkmm/scrolledwindow.h>
+#include <gtkmm/dialog.h>
+#include "ui/widget/spinbutton.h"
+#include "ui/widget/panel.h"
+#include "ui/widget/object-composite-settings.h"
+#include "desktop-tracker.h"
+#include "ui/widget/style-subject.h"
+#include "selection.h"
+#include "ui/widget/filter-effect-chooser.h"
+
+class SPObject;
+class SPGroup;
+struct SPColorSelector;
+
+namespace Inkscape {
+
+namespace UI {
+namespace Dialog {
+
+
+/**
+ * A panel that displays objects.
+ */
+class ObjectsPanel : public UI::Widget::Panel
+{
+public:
+ ObjectsPanel();
+ virtual ~ObjectsPanel();
+
+ static ObjectsPanel& getInstance();
+
+ void setDesktop( SPDesktop* desktop );
+ void setDocument( SPDesktop* desktop, SPDocument* document);
+
+private:
+ //Internal Classes:
+ class ModelColumns;
+ class InternalUIBounce;
+ class ObjectWatcher;
+
+ //Connections, Watchers, Trackers:
+
+ //Document root watcher
+ ObjectsPanel::ObjectWatcher* _rootWatcher;
+
+ //All object watchers
+ std::vector<ObjectsPanel::ObjectWatcher*> _objectWatchers;
+
+ //Connection for when the desktop changes
+ sigc::connection desktopChangeConn;
+
+ //Connection for when the document changes
+ sigc::connection _documentChangedConnection;
+
+ //Connection for when the active selection in the document changes
+ sigc::connection _selectionChangedConnection;
+
+ //Connection for when the selection in the dialog changes
+ sigc::connection _selectedConnection;
+
+ //Connections for when the opacity/blend/blur of the active selection in the document changes
+ sigc::connection _opacityConnection;
+ sigc::connection _blendConnection;
+ sigc::connection _blurConnection;
+
+ //Desktop tracker for grabbing the desktop changed connection
+ DesktopTracker _deskTrack;
+
+ //Members:
+
+ //The current desktop
+ SPDesktop* _desktop;
+
+ //The current document
+ SPDocument* _document;
+
+ //Tree data model
+ ModelColumns* _model;
+
+ //Prevents the composite controls from updating
+ bool _blockCompositeUpdate;
+
+ //
+ InternalUIBounce* _pending;
+
+ //Whether the drag & drop was dragged into an item
+ gboolean _dnd_into;
+
+ //List of drag & drop source items
+ std::vector<SPItem*> _dnd_source;
+
+ //Drag & drop target item
+ SPItem* _dnd_target;
+
+ //List of items to change the highlight on
+ std::vector<SPItem*> _highlight_target;
+
+ //GUI Members:
+
+ GdkEvent* _toggleEvent;
+
+ Gtk::TreeModel::Path _defer_target;
+
+ Glib::RefPtr<Gtk::TreeStore> _store;
+ std::vector<Gtk::Widget*> _watching;
+ std::vector<Gtk::Widget*> _watchingNonTop;
+ std::vector<Gtk::Widget*> _watchingNonBottom;
+
+ Gtk::TreeView _tree;
+ Gtk::CellRendererText *_text_renderer;
+ Gtk::TreeView::Column *_name_column;
+#if WITH_GTKMM_3_0
+ Gtk::Box _buttonsRow;
+ Gtk::Box _buttonsPrimary;
+ Gtk::Box _buttonsSecondary;
+#else
+ Gtk::HBox _buttonsRow;
+ Gtk::HBox _buttonsPrimary;
+ Gtk::HBox _buttonsSecondary;
+#endif
+ Gtk::ScrolledWindow _scroller;
+ Gtk::Menu _popupMenu;
+ Inkscape::UI::Widget::SpinButton _spinBtn;
+ Gtk::VBox _page;
+
+ /* Composite Settings */
+ Gtk::VBox _composite_vbox;
+ Gtk::VBox _opacity_vbox;
+ Gtk::HBox _opacity_hbox;
+ Gtk::Label _opacity_label;
+ Gtk::Label _opacity_label_unit;
+#if WITH_GTKMM_3_0
+ Glib::RefPtr<Gtk::Adjustment> _opacity_adjustment;
+#else
+ Gtk::Adjustment _opacity_adjustment;
+#endif
+ Gtk::HScale _opacity_hscale;
+ Inkscape::UI::Widget::SpinButton _opacity_spin_button;
+
+ Inkscape::UI::Widget::SimpleFilterModifier _fe_cb;
+ Gtk::VBox _fe_vbox;
+ Gtk::Alignment _fe_alignment;
+ Inkscape::UI::Widget::SimpleFilterModifier _fe_blur;
+ Gtk::VBox _blur_vbox;
+ Gtk::Alignment _blur_alignment;
+
+ Gtk::Dialog _colorSelectorDialog;
+ SPColorSelector *_colorSelector;
+
+
+ //Methods:
+
+ ObjectsPanel(ObjectsPanel const &); // no copy
+ ObjectsPanel &operator=(ObjectsPanel const &); // no assign
+
+ void _styleButton( Gtk::Button& btn, char const* iconName, char const* tooltip );
+ void _fireAction( unsigned int code );
+
+ Gtk::MenuItem& _addPopupItem( SPDesktop *desktop, unsigned int code, char const* iconName, char const* fallback, int id );
+
+ void _setVisibleIter( const Gtk::TreeModel::iterator& iter, const bool visible );
+ void _setLockedIter( const Gtk::TreeModel::iterator& iter, const bool locked );
+
+ bool _handleButtonEvent(GdkEventButton *event);
+ bool _handleKeyEvent(GdkEventKey *event);
+
+ void _storeHighlightTarget(const Gtk::TreeModel::iterator& iter);
+ void _storeDragSource(const Gtk::TreeModel::iterator& iter);
+ bool _handleDragDrop(const Glib::RefPtr<Gdk::DragContext>& context, int x, int y, guint time);
+ void _handleEdited(const Glib::ustring& path, const Glib::ustring& new_text);
+ void _handleEditingCancelled();
+
+ void _doTreeMove();
+ void _renameObject(Gtk::TreeModel::Row row, const Glib::ustring& name);
+
+ void _pushTreeSelectionToCurrent();
+ void _selected_row_callback( const Gtk::TreeModel::iterator& iter, bool *setOpacity );
+
+ void _checkTreeSelection();
+
+ void _takeAction( int val );
+ bool _executeAction();
+
+ void _setExpanded( const Gtk::TreeModel::iterator& iter, const Gtk::TreeModel::Path& path, bool isexpanded );
+ void _setCollapsed(SPGroup * group);
+
+ bool _noSelection( Glib::RefPtr<Gtk::TreeModel> const & model, Gtk::TreeModel::Path const & path, bool b );
+ bool _rowSelectFunction( Glib::RefPtr<Gtk::TreeModel> const & model, Gtk::TreeModel::Path const & path, bool b );
+
+ void _compositingChanged( const Gtk::TreeModel::iterator& iter, bool *setValues );
+ void _updateComposite();
+ void _setCompositingValues(SPItem *item);
+
+ void _updateObject(SPObject *obj, bool recurse);
+ bool _checkForUpdated(const Gtk::TreeIter& iter, SPObject* obj);
+
+ void _objectsSelected(Selection *sel);
+ bool _checkForSelected(const Gtk::TreePath& path, const Gtk::TreeIter& iter, SPItem* item, bool scrollto);
+
+ void _objectsChanged(SPObject *obj);
+ void _addObject( SPObject* obj, Gtk::TreeModel::Row* parentRow );
+
+ void _opacityChangedIter(const Gtk::TreeIter& iter);
+ void _opacityValueChanged();
+
+ void _blendChangedIter(const Gtk::TreeIter& iter, Glib::ustring blendmode);
+ void _blendValueChanged();
+
+ void _blurChangedIter(const Gtk::TreeIter& iter, double blur);
+ void _blurValueChanged();
+
+
+ void setupDialog(const Glib::ustring &title);
+
+ friend void sp_highlight_picker_color_mod(SPColorSelector *csel, GObject *cp);
+
+};
+
+
+
+} //namespace Dialogs
+} //namespace UI
+} //namespace Inkscape
+
+
+
+#endif // SEEN_OBJECTS_PANEL_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/ui/dialog/ocaldialogs.cpp b/src/ui/dialog/ocaldialogs.cpp
index f676e75fd..c4dd9df98 100644
--- a/src/ui/dialog/ocaldialogs.cpp
+++ b/src/ui/dialog/ocaldialogs.cpp
@@ -25,9 +25,9 @@
#include "path-prefix.h"
#include "filedialogimpl-gtkmm.h"
-#include "interface.h"
+#include "ui/interface.h"
#include "gc-core.h"
-#include <dialogs/dialog-events.h>
+#include "ui/dialog-events.h"
#include "io/sys.h"
#include "preferences.h"
diff --git a/src/ui/dialog/ocaldialogs.h b/src/ui/dialog/ocaldialogs.h
index e21030bcd..bd028c145 100644
--- a/src/ui/dialog/ocaldialogs.h
+++ b/src/ui/dialog/ocaldialogs.h
@@ -38,8 +38,7 @@
//Inkscape includes
#include "ui/dialog/filedialog.h"
-
-#include <dialogs/dialog-events.h>
+#include "ui/dialog-events.h"
struct _xmlNode;
typedef _xmlNode xmlNode;
diff --git a/src/ui/dialog/panel-dialog.h b/src/ui/dialog/panel-dialog.h
index 1fefd811e..b4a355083 100644
--- a/src/ui/dialog/panel-dialog.h
+++ b/src/ui/dialog/panel-dialog.h
@@ -49,19 +49,19 @@ public:
virtual UI::Widget::Panel &getPanel() { return _panel; }
protected:
- static void handle_deactivate_desktop(Inkscape::Application *application, SPDesktop *desktop, void *data) {
+ static void handle_deactivate_desktop(InkscapeApplication *application, SPDesktop *desktop, void *data) {
g_return_if_fail(data != NULL);
static_cast<PanelDialogBase *>(data)->_propagateDesktopDeactivated(application, desktop);
}
- static void _handle_activate_desktop(Inkscape::Application *application, SPDesktop *desktop, void *data) {
+ static void _handle_activate_desktop(InkscapeApplication *application, SPDesktop *desktop, void *data) {
g_return_if_fail(data != NULL);
static_cast<PanelDialogBase *>(data)->_propagateDesktopActivated(application, desktop);
}
inline virtual void _propagateDocumentReplaced(SPDesktop* desktop, SPDocument *document);
- inline virtual void _propagateDesktopActivated(Inkscape::Application *, SPDesktop *);
- inline virtual void _propagateDesktopDeactivated(Inkscape::Application *, SPDesktop *);
+ inline virtual void _propagateDesktopActivated(InkscapeApplication *, SPDesktop *);
+ inline virtual void _propagateDesktopDeactivated(InkscapeApplication *, SPDesktop *);
UI::Widget::Panel &_panel;
sigc::connection _document_replaced_connection;
@@ -134,14 +134,14 @@ void PanelDialogBase::_propagateDocumentReplaced(SPDesktop *desktop, SPDocument
_panel.signalDocumentReplaced().emit(desktop, document);
}
-void PanelDialogBase::_propagateDesktopActivated(Inkscape::Application *application, SPDesktop *desktop)
+void PanelDialogBase::_propagateDesktopActivated(InkscapeApplication *application, SPDesktop *desktop)
{
_document_replaced_connection =
desktop->connectDocumentReplaced(sigc::mem_fun(*this, &PanelDialogBase::_propagateDocumentReplaced));
_panel.signalActivateDesktop().emit(application, desktop);
}
-void PanelDialogBase::_propagateDesktopDeactivated(Inkscape::Application *application, SPDesktop *desktop)
+void PanelDialogBase::_propagateDesktopDeactivated(InkscapeApplication *application, SPDesktop *desktop)
{
_document_replaced_connection.disconnect();
_panel.signalDeactiveDesktop().emit(application, desktop);
diff --git a/src/ui/dialog/pixelartdialog.cpp b/src/ui/dialog/pixelartdialog.cpp
index 2d25f54d7..5113f172a 100644
--- a/src/ui/dialog/pixelartdialog.cpp
+++ b/src/ui/dialog/pixelartdialog.cpp
@@ -385,8 +385,8 @@ void PixelArtDialogImpl::vectorize()
if ( input.pixbuf->get_width() > 256
|| input.pixbuf->get_height() > 256 ) {
- char *msg = _("Image looks too big. Process may take a while and is"
- " wise to save your document before continue."
+ char *msg = _("Image looks too big. Process may take a while and it is"
+ " wise to save your document before continuing."
"\n\nContinue the procedure (without saving)?");
Gtk::MessageDialog dialog(msg, false, Gtk::MESSAGE_WARNING,
Gtk::BUTTONS_OK_CANCEL, true);
diff --git a/src/ui/dialog/polar-arrange-tab.cpp b/src/ui/dialog/polar-arrange-tab.cpp
index a00b8fc02..80579c9d3 100644
--- a/src/ui/dialog/polar-arrange-tab.cpp
+++ b/src/ui/dialog/polar-arrange-tab.cpp
@@ -25,6 +25,7 @@
#include "desktop.h"
#include "sp-ellipse.h"
#include "sp-item-transform.h"
+#include <gtkmm/messagedialog.h>
namespace Inkscape {
namespace UI {
@@ -32,7 +33,11 @@ namespace Dialog {
PolarArrangeTab::PolarArrangeTab(ArrangeDialog *parent_)
: parent(parent_),
+#if WITH_GTKMM_3_0
+ parametersTable(),
+#else
parametersTable(3, 3, false),
+#endif
centerY("", "Y coordinate of the center", UNIT_TYPE_LINEAR),
centerX("", "X coordinate of the center", centerY),
radiusY("", "Y coordinate of the radius", UNIT_TYPE_LINEAR),
@@ -76,7 +81,11 @@ PolarArrangeTab::PolarArrangeTab(ArrangeDialog *parent_)
pack_start(arrangeOnParametersRadio, false, false);
centerLabel.set_text(_("Center X/Y:"));
+#if WITH_GTKMM_3_0
+ parametersTable.attach(centerLabel, 0, 0, 1, 1);
+#else
parametersTable.attach(centerLabel, 0, 1, 0, 1, Gtk::FILL);
+#endif
centerX.setDigits(2);
centerX.setIncrements(0.2, 0);
centerX.setRange(-10000, 10000);
@@ -85,11 +94,20 @@ PolarArrangeTab::PolarArrangeTab(ArrangeDialog *parent_)
centerY.setIncrements(0.2, 0);
centerY.setRange(-10000, 10000);
centerY.setValue(0, "px");
+#if WITH_GTKMM_3_0
+ parametersTable.attach(centerX, 1, 0, 1, 1);
+ parametersTable.attach(centerY, 2, 0, 1, 1);
+#else
parametersTable.attach(centerX, 1, 2, 0, 1, Gtk::FILL);
parametersTable.attach(centerY, 2, 3, 0, 1, Gtk::FILL);
+#endif
radiusLabel.set_text(_("Radius X/Y:"));
+#if WITH_GTKMM_3_0
+ parametersTable.attach(radiusLabel, 0, 1, 1, 1);
+#else
parametersTable.attach(radiusLabel, 0, 1, 1, 2, Gtk::FILL);
+#endif
radiusX.setDigits(2);
radiusX.setIncrements(0.2, 0);
radiusX.setRange(0.001, 10000);
@@ -98,11 +116,20 @@ PolarArrangeTab::PolarArrangeTab(ArrangeDialog *parent_)
radiusY.setIncrements(0.2, 0);
radiusY.setRange(0.001, 10000);
radiusY.setValue(100, "px");
+#if WITH_GTKMM_3_0
+ parametersTable.attach(radiusX, 1, 1, 1, 1);
+ parametersTable.attach(radiusY, 2, 1, 1, 1);
+#else
parametersTable.attach(radiusX, 1, 2, 1, 2, Gtk::FILL);
parametersTable.attach(radiusY, 2, 3, 1, 2, Gtk::FILL);
+#endif
angleLabel.set_text(_("Angle X/Y:"));
+#if WITH_GTKMM_3_0
+ parametersTable.attach(angleLabel, 0, 2, 1, 1);
+#else
parametersTable.attach(angleLabel, 0, 1, 2, 3, Gtk::FILL);
+#endif
angleX.setDigits(2);
angleX.setIncrements(0.2, 0);
angleX.setRange(-10000, 10000);
@@ -111,8 +138,13 @@ PolarArrangeTab::PolarArrangeTab(ArrangeDialog *parent_)
angleY.setIncrements(0.2, 0);
angleY.setRange(-10000, 10000);
angleY.setValue(180, "°");
+#if WITH_GTKMM_3_0
+ parametersTable.attach(angleX, 1, 2, 1, 1);
+ parametersTable.attach(angleY, 2, 2, 1, 1);
+#else
parametersTable.attach(angleX, 1, 2, 2, 3, Gtk::FILL);
parametersTable.attach(angleY, 2, 3, 2, 3, Gtk::FILL);
+#endif
pack_start(parametersTable, false, false);
rotateObjectsCheckBox.set_label(_("Rotate objects"));
diff --git a/src/ui/dialog/polar-arrange-tab.h b/src/ui/dialog/polar-arrange-tab.h
index f6c3b2906..f7d7bf11f 100644
--- a/src/ui/dialog/polar-arrange-tab.h
+++ b/src/ui/dialog/polar-arrange-tab.h
@@ -10,9 +10,22 @@
#ifndef INKSCAPE_UI_DIALOG_POLAR_ARRANGE_TAB_H
#define INKSCAPE_UI_DIALOG_POLAR_ARRANGE_TAB_H
+#if HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#include "ui/widget/scalar-unit.h"
#include "ui/widget/anchor-selector.h"
#include "ui/dialog/arrange-tab.h"
-#include "ui/widget/scalar-unit.h"
+
+#include <gtkmm/radiobutton.h>
+#include <gtkmm/radiobuttongroup.h>
+
+#if WITH_GTKMM_3_0
+ #include <gtkmm/grid.h>
+#else
+ #include <gtkmm/table.h>
+#endif
namespace Inkscape {
namespace UI {
@@ -62,7 +75,11 @@ private:
Gtk::RadioButton arrangeOnLastCircleRadio;
Gtk::RadioButton arrangeOnParametersRadio;
+#if WITH_GTKMM_3_0
+ Gtk::Grid parametersTable;
+#else
Gtk::Table parametersTable;
+#endif
Gtk::Label centerLabel;
Inkscape::UI::Widget::ScalarUnit centerY;
diff --git a/src/ui/dialog/print.cpp b/src/ui/dialog/print.cpp
index 03ac9dc64..a015d28f9 100644
--- a/src/ui/dialog/print.cpp
+++ b/src/ui/dialog/print.cpp
@@ -13,13 +13,16 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
+
+#include <gtkmm.h>
+
#ifdef WIN32
#include <io.h>
#include <windows.h>
#endif
+#include "preferences.h"
#include "print.h"
-#include <gtkmm/stock.h>
#include "extension/internal/cairo-render-context.h"
#include "extension/internal/cairo-renderer.h"
@@ -44,14 +47,18 @@ static void draw_page(
gint /*page_nr*/,
gpointer user_data)
{
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
struct workaround_gtkmm *junk = (struct workaround_gtkmm*)user_data;
//printf("%s %d\n",__FUNCTION__, page_nr);
if (junk->_tab->as_bitmap()) {
// Render as exported PNG
+ prefs->setBool("/dialogs/printing/asbitmap", true);
gdouble width = (junk->_doc)->getWidth().value("px");
gdouble height = (junk->_doc)->getHeight().value("px");
gdouble dpi = junk->_tab->bitmap_dpi();
+ prefs->setDouble("/dialogs/printing/dpi", dpi);
+
std::string tmp_png;
std::string tmp_base = "inkscape-print-png-XXXXXX";
@@ -92,7 +99,7 @@ static void draw_page(
cairo_get_matrix(cr, &m);
cairo_scale(cr, Inkscape::Util::Quantity::convert(1, "in", "pt") / dpi, Inkscape::Util::Quantity::convert(1, "in", "pt") / dpi);
// FIXME: why is the origin offset??
- cairo_set_source_surface(cr, png->cobj(), -16.0, -16.0);
+ cairo_set_source_surface(cr, png->cobj(), 0, 0);
cairo_paint(cr);
cairo_set_matrix(cr, &m);
}
@@ -106,6 +113,7 @@ static void draw_page(
}
else {
// Render as vectors
+ prefs->setBool("/dialogs/printing/asbitmap", false);
Inkscape::Extension::Internal::CairoRenderer renderer;
Inkscape::Extension::Internal::CairoRenderContext *ctx = renderer.createContext();
diff --git a/src/ui/dialog/spellcheck.cpp b/src/ui/dialog/spellcheck.cpp
index 8a4ddc57e..9faa8a2cb 100644
--- a/src/ui/dialog/spellcheck.cpp
+++ b/src/ui/dialog/spellcheck.cpp
@@ -23,9 +23,9 @@
#include "selection.h"
#include "desktop.h"
#include "desktop-handles.h"
-#include "tools-switch.h"
+#include "ui/tools-switch.h"
#include "ui/tools/text-tool.h"
-#include "interface.h"
+#include "ui/interface.h"
#include "preferences.h"
#include "sp-text.h"
#include "sp-flowtext.h"
@@ -347,7 +347,7 @@ SpellCheck::init(SPDesktop *d)
char *slashPos = strrchr(exeName, '\\');
if (slashPos)
*slashPos = '\0';
- g_print ("%s\n", exeName);
+ //g_print ("Aspell prefix path: %s\n", exeName);
#endif
_stops = 0;
@@ -356,54 +356,54 @@ SpellCheck::init(SPDesktop *d)
#ifdef HAVE_ASPELL
{
- AspellConfig *config = new_aspell_config();
+ AspellConfig *config = new_aspell_config();
#ifdef WIN32
- aspell_config_replace(config, "prefix", exeName);
+ aspell_config_replace(config, "prefix", exeName);
#endif
- aspell_config_replace(config, "lang", _lang.c_str());
- aspell_config_replace(config, "encoding", "UTF-8");
- AspellCanHaveError *ret = new_aspell_speller(config);
- delete_aspell_config(config);
- if (aspell_error(ret) != 0) {
- g_warning("Error: %s\n", aspell_error_message(ret));
- delete_aspell_can_have_error(ret);
- return false;
- }
- _speller = to_aspell_speller(ret);
+ aspell_config_replace(config, "lang", _lang.c_str());
+ aspell_config_replace(config, "encoding", "UTF-8");
+ AspellCanHaveError *ret = new_aspell_speller(config);
+ delete_aspell_config(config);
+ if (aspell_error(ret) != 0) {
+ g_warning("Error: %s\n", aspell_error_message(ret));
+ delete_aspell_can_have_error(ret);
+ return false;
+ }
+ _speller = to_aspell_speller(ret);
}
if (_lang2 != "") {
- AspellConfig *config = new_aspell_config();
+ AspellConfig *config = new_aspell_config();
#ifdef WIN32
- aspell_config_replace(config, "prefix", exeName);
+ aspell_config_replace(config, "prefix", exeName);
#endif
- aspell_config_replace(config, "lang", _lang2.c_str());
- aspell_config_replace(config, "encoding", "UTF-8");
- AspellCanHaveError *ret = new_aspell_speller(config);
- delete_aspell_config(config);
- if (aspell_error(ret) != 0) {
- g_warning("Error: %s\n", aspell_error_message(ret));
- delete_aspell_can_have_error(ret);
- return false;
- }
- _speller2 = to_aspell_speller(ret);
+ aspell_config_replace(config, "lang", _lang2.c_str());
+ aspell_config_replace(config, "encoding", "UTF-8");
+ AspellCanHaveError *ret = new_aspell_speller(config);
+ delete_aspell_config(config);
+ if (aspell_error(ret) != 0) {
+ g_warning("Error: %s\n", aspell_error_message(ret));
+ delete_aspell_can_have_error(ret);
+ return false;
+ }
+ _speller2 = to_aspell_speller(ret);
}
if (_lang3 != "") {
- AspellConfig *config = new_aspell_config();
+ AspellConfig *config = new_aspell_config();
#ifdef WIN32
- aspell_config_replace(config, "prefix", exeName);
+ aspell_config_replace(config, "prefix", exeName);
#endif
- aspell_config_replace(config, "lang", _lang3.c_str());
- aspell_config_replace(config, "encoding", "UTF-8");
- AspellCanHaveError *ret = new_aspell_speller(config);
- delete_aspell_config(config);
- if (aspell_error(ret) != 0) {
- g_warning("Error: %s\n", aspell_error_message(ret));
- delete_aspell_can_have_error(ret);
- return false;
- }
- _speller3 = to_aspell_speller(ret);
+ aspell_config_replace(config, "lang", _lang3.c_str());
+ aspell_config_replace(config, "encoding", "UTF-8");
+ AspellCanHaveError *ret = new_aspell_speller(config);
+ delete_aspell_config(config);
+ if (aspell_error(ret) != 0) {
+ g_warning("Error: %s\n", aspell_error_message(ret));
+ delete_aspell_can_have_error(ret);
+ return false;
+ }
+ _speller3 = to_aspell_speller(ret);
}
#endif /* HAVE_ASPELL */
diff --git a/src/ui/dialog/swatches.cpp b/src/ui/dialog/swatches.cpp
index 4f0cb211a..a3cfeeba8 100644
--- a/src/ui/dialog/swatches.cpp
+++ b/src/ui/dialog/swatches.cpp
@@ -745,11 +745,10 @@ void SwatchesPanel::setDesktop( SPDesktop* desktop )
class DocTrack
{
public:
- DocTrack(SPDocument *doc, sigc::connection &docDestroy, sigc::connection &gradientRsrcChanged, sigc::connection &defsChanged, sigc::connection &defsModified) :
- doc(doc),
+ DocTrack(SPDocument *doc, sigc::connection &gradientRsrcChanged, sigc::connection &defsChanged, sigc::connection &defsModified) :
+ doc(doc->doRef()),
updatePending(false),
lastGradientUpdate(0.0),
- docDestroy(docDestroy),
gradientRsrcChanged(gradientRsrcChanged),
defsChanged(defsChanged),
defsModified(defsModified)
@@ -774,10 +773,10 @@ public:
}
}
if (doc) {
- docDestroy.disconnect();
gradientRsrcChanged.disconnect();
defsChanged.disconnect();
defsModified.disconnect();
+ doc->doUnref();
doc = NULL;
}
}
@@ -798,7 +797,6 @@ public:
SPDocument *doc;
bool updatePending;
double lastGradientUpdate;
- sigc::connection docDestroy;
sigc::connection gradientRsrcChanged;
sigc::connection defsChanged;
sigc::connection defsModified;
@@ -894,12 +892,11 @@ void SwatchesPanel::_trackDocument( SwatchesPanel *panel, SPDocument *document )
}
docPerPanel[panel] = document;
if (!found) {
- sigc::connection conn0 = document->connectDestroy(sigc::bind(sigc::ptr_fun(&SwatchesPanel::handleDocumentDestroy), document));
sigc::connection conn1 = document->connectResourcesChanged( "gradient", sigc::bind(sigc::ptr_fun(&SwatchesPanel::handleGradientsChange), document) );
sigc::connection conn2 = document->getDefs()->connectRelease( sigc::hide(sigc::bind(sigc::ptr_fun(&SwatchesPanel::handleDefsModified), document)) );
sigc::connection conn3 = document->getDefs()->connectModified( sigc::hide(sigc::hide(sigc::bind(sigc::ptr_fun(&SwatchesPanel::handleDefsModified), document))) );
- DocTrack *dt = new DocTrack(document, conn0, conn1, conn2, conn3);
+ DocTrack *dt = new DocTrack(document, conn1, conn2, conn3);
docTrackings.push_back(dt);
if (docPalettes.find(document) == docPalettes.end()) {
@@ -928,13 +925,11 @@ static void recalcSwatchContents(SPDocument* doc,
{
std::vector<SPGradient*> newList;
- if (doc) {
- const GSList *gradients = doc->getResourceList("gradient");
- for (const GSList *item = gradients; item; item = item->next) {
- SPGradient* grad = SP_GRADIENT(item->data);
- if ( grad->isSwatch() ) {
- newList.push_back(SP_GRADIENT(item->data));
- }
+ const GSList *gradients = doc->getResourceList("gradient");
+ for (const GSList *item = gradients; item; item = item->next) {
+ SPGradient* grad = SP_GRADIENT(item->data);
+ if ( grad->isSwatch() ) {
+ newList.push_back(SP_GRADIENT(item->data));
}
}
@@ -973,37 +968,6 @@ static void recalcSwatchContents(SPDocument* doc,
}
}
-void SwatchesPanel::handleDocumentDestroy(SPDocument *document)
-{
- if (document) {
- for (std::vector<DocTrack*>::iterator it = docTrackings.begin(); it != docTrackings.end(); ++it){
- if ((*it)->doc == document) {
- delete *it;
- docTrackings.erase(it);
- break;
- }
- }
-
- if (docPalettes.find(document) != docPalettes.end()) {
- docPalettes.erase(document);
- }
-
- for (std::map<SwatchesPanel*, SPDocument*>::iterator it = docPerPanel.begin(); it != docPerPanel.end(); ++it) {
- if (it->second == document) {
- SwatchesPanel* swp = it->first;
- std::vector<SwatchPage*> pages = swp->_getSwatchSets();
- if ((swp->_currentIndex >= static_cast<int>(pages.size())) && (pages.size() > 0))
- {
- swp->_setSelectedIndex(swp->_getSwatchSets().size() - 1);
- }
- swp->_rebuild();
- docPerPanel.erase(it);
- break;
- }
- }
- }
-}
-
void SwatchesPanel::handleGradientsChange(SPDocument *document)
{
SwatchPage *docPalette = (docPalettes.find(document) != docPalettes.end()) ? docPalettes[document] : 0;
@@ -1178,45 +1142,38 @@ void SwatchesPanel::_handleAction( int setId, int itemId )
switch( setId ) {
case 3:
{
- _setSelectedIndex(itemId);
- }
- break;
- }
-}
+ std::vector<SwatchPage*> pages = _getSwatchSets();
+ if ( itemId >= 0 && itemId < static_cast<int>(pages.size()) ) {
+ _currentIndex = itemId;
-void SwatchesPanel::_setSelectedIndex( int index )
-{
- std::vector<SwatchPage*> pages = _getSwatchSets();
- if ( index >= 0 && index < static_cast<int>(pages.size()) ) {
- _currentIndex = index;
+ if ( !_prefs_path.empty() ) {
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ prefs->setString(_prefs_path + "/palette", pages[_currentIndex]->_name);
+ }
- if ( !_prefs_path.empty() ) {
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- prefs->setString(_prefs_path + "/palette", pages[_currentIndex]->_name);
+ _rebuild();
+ }
}
-
- _rebuild();
+ break;
}
}
void SwatchesPanel::_rebuild()
{
std::vector<SwatchPage*> pages = _getSwatchSets();
- if (_currentIndex < static_cast<int>(pages.size())) {
- SwatchPage* curr = pages[_currentIndex];
- _holder->clear();
+ SwatchPage* curr = pages[_currentIndex];
+ _holder->clear();
- if ( curr->_prefWidth > 0 ) {
- _holder->setColumnPref( curr->_prefWidth );
- }
- _holder->freezeUpdates();
- // TODO restore once 'clear' works _holder->addPreview(_clear);
- _holder->addPreview(_remove);
- for ( boost::ptr_vector<ColorItem>::iterator it = curr->_colors.begin(); it != curr->_colors.end(); ++it) {
- _holder->addPreview(&*it);
- }
- _holder->thawUpdates();
+ if ( curr->_prefWidth > 0 ) {
+ _holder->setColumnPref( curr->_prefWidth );
+ }
+ _holder->freezeUpdates();
+ // TODO restore once 'clear' works _holder->addPreview(_clear);
+ _holder->addPreview(_remove);
+ for ( boost::ptr_vector<ColorItem>::iterator it = curr->_colors.begin(); it != curr->_colors.end(); ++it) {
+ _holder->addPreview(&*it);
}
+ _holder->thawUpdates();
}
} //namespace Dialogs
diff --git a/src/ui/dialog/swatches.h b/src/ui/dialog/swatches.h
index 3abb81d98..ca4c1687d 100644
--- a/src/ui/dialog/swatches.h
+++ b/src/ui/dialog/swatches.h
@@ -43,13 +43,11 @@ public:
virtual int getSelectedIndex() {return _currentIndex;} // temporary
protected:
- static void handleDocumentDestroy(SPDocument *document);
static void handleGradientsChange(SPDocument *document);
virtual void _updateFromSelection();
virtual void _handleAction( int setId, int itemId );
virtual void _setDocument( SPDocument *document );
- virtual void _setSelectedIndex( int index );
virtual void _rebuild();
virtual std::vector<SwatchPage*> _getSwatchSets() const;
diff --git a/src/ui/dialog/symbols.cpp b/src/ui/dialog/symbols.cpp
index 8e0d085a4..a17a03861 100644
--- a/src/ui/dialog/symbols.cpp
+++ b/src/ui/dialog/symbols.cpp
@@ -62,8 +62,20 @@
#include "widgets/icon.h"
#ifdef WITH_LIBVISIO
-#include <libvisio/libvisio.h>
-#include <libwpd-stream/libwpd-stream.h>
+ #include <libvisio/libvisio.h>
+
+ // TODO: Drop this check when librevenge is widespread.
+ #if WITH_LIBVISIO01
+ #include <librevenge-stream/librevenge-stream.h>
+
+ using librevenge::RVNGFileStream;
+ using librevenge::RVNGStringVector;
+ #else
+ #include <libwpd-stream/libwpd-stream.h>
+
+ typedef WPXFileStream RVNGFileStream;
+ typedef libvisio::VSDStringVector RVNGStringVector;
+ #endif
#endif
#include "verbs.h"
@@ -219,25 +231,27 @@ SymbolsDialog::SymbolsDialog( gchar const* prefsPath ) :
Gtk::Label* spacer = Gtk::manage(new Gtk::Label(""));
tools->pack_start(* Gtk::manage(spacer));
- in_sizes = 2; // Default 32px
+ // Pack size (controls display area)
+ pack_size = 2; // Default 32px
button = Gtk::manage(new Gtk::Button());
button->add(*Gtk::manage(Glib::wrap(
- sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_ICON("symbol-bigger")))) );
- button->set_tooltip_text(_("Make Icons bigger by zooming in."));
+ sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_ICON("pack-more")))) );
+ button->set_tooltip_text(_("Display more icons in row."));
button->set_relief( Gtk::RELIEF_NONE );
button->set_focus_on_click( false );
- button->signal_clicked().connect(sigc::mem_fun(*this, &SymbolsDialog::zoomin));
+ button->signal_clicked().connect(sigc::mem_fun(*this, &SymbolsDialog::packmore));
tools->pack_start(* button, Gtk::PACK_SHRINK);
button = Gtk::manage(new Gtk::Button());
button->add(*Gtk::manage(Glib::wrap(
- sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_ICON("symbol-smaller")))) );
- button->set_tooltip_text(_("Make Icons smaller by zooming out."));
+ sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_ICON("pack-less")))) );
+ button->set_tooltip_text(_("Display fewer icons in row."));
button->set_relief( Gtk::RELIEF_NONE );
button->set_focus_on_click( false );
- button->signal_clicked().connect(sigc::mem_fun(*this, &SymbolsDialog::zoomout));
+ button->signal_clicked().connect(sigc::mem_fun(*this, &SymbolsDialog::packless));
tools->pack_start(* button, Gtk::PACK_SHRINK);
+ // Toggle scale to fit on/off
fitSymbol = Gtk::manage(new Gtk::ToggleButton());
fitSymbol->add(*Gtk::manage(Glib::wrap(
sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_ICON("symbol-fit")))) );
@@ -248,6 +262,28 @@ SymbolsDialog::SymbolsDialog( gchar const* prefsPath ) :
fitSymbol->signal_clicked().connect(sigc::mem_fun(*this, &SymbolsDialog::rebuild));
tools->pack_start(* fitSymbol, Gtk::PACK_SHRINK);
+ // Render size (scales symbols within display area)
+ scale_factor = 0; // Default 1:1 * pack_size/pack_size default
+ zoomOut = Gtk::manage(new Gtk::Button());
+ zoomOut->add(*Gtk::manage(Glib::wrap(
+ sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_ICON("symbol-smaller")))) );
+ zoomOut->set_tooltip_text(_("Make symbols smaller by zooming out."));
+ zoomOut->set_relief( Gtk::RELIEF_NONE );
+ zoomOut->set_focus_on_click( false );
+ zoomOut->set_sensitive( false );
+ zoomOut->signal_clicked().connect(sigc::mem_fun(*this, &SymbolsDialog::zoomout));
+ tools->pack_start(* zoomOut, Gtk::PACK_SHRINK);
+
+ zoomIn = Gtk::manage(new Gtk::Button());
+ zoomIn->add(*Gtk::manage(Glib::wrap(
+ sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_ICON("symbol-bigger")))) );
+ zoomIn->set_tooltip_text(_("Make symbols bigger by zooming in."));
+ zoomIn->set_relief( Gtk::RELIEF_NONE );
+ zoomIn->set_focus_on_click( false );
+ zoomIn->set_sensitive( false );
+ zoomIn->signal_clicked().connect(sigc::mem_fun(*this, &SymbolsDialog::zoomin));
+ tools->pack_start(* zoomIn, Gtk::PACK_SHRINK);
+
++row;
/**********************************************************/
@@ -262,8 +298,7 @@ SymbolsDialog::SymbolsDialog( gchar const* prefsPath ) :
// This might need to be a global variable so setTargetDesktop can modify it
SPDefs *defs = currentDocument->getDefs();
- sigc::connection defsModifiedConn = (SP_OBJECT(defs))->connectModified(
- sigc::mem_fun(*this, &SymbolsDialog::defsModified));
+ sigc::connection defsModifiedConn = defs->connectModified(sigc::mem_fun(*this, &SymbolsDialog::defsModified));
instanceConns.push_back(defsModifiedConn);
sigc::connection selectionChangedConn = currentDesktop->selection->connectChanged(
@@ -298,22 +333,44 @@ SymbolsDialog& SymbolsDialog::getInstance()
return *new SymbolsDialog();
}
+void SymbolsDialog::packless() {
+ if(pack_size < 4) {
+ pack_size++;
+ rebuild();
+ }
+}
+
+void SymbolsDialog::packmore() {
+ if(pack_size > 0) {
+ pack_size--;
+ rebuild();
+ }
+}
+
void SymbolsDialog::zoomin() {
- if(in_sizes < 4) {
- in_sizes++;
+ if(scale_factor < 4) {
+ scale_factor++;
rebuild();
}
}
void SymbolsDialog::zoomout() {
- if(in_sizes > 0) {
- in_sizes--;
+ if(scale_factor > -8) {
+ scale_factor--;
rebuild();
}
}
void SymbolsDialog::rebuild() {
+ if( fitSymbol->get_active() ) {
+ zoomIn->set_sensitive( false );
+ zoomOut->set_sensitive( false );
+ } else {
+ zoomIn->set_sensitive( true);
+ zoomOut->set_sensitive( true );
+ }
+
store->clear();
Glib::ustring symbolSetString = symbolSet->get_active_text();
@@ -449,14 +506,20 @@ void SymbolsDialog::iconChanged() {
// Read Visio stencil files
SPDocument* read_vss( gchar* fullname, gchar* filename ) {
- WPXFileStream input(fullname);
+ RVNGFileStream input(fullname);
if (!libvisio::VisioDocument::isSupported(&input)) {
return NULL;
}
- libvisio::VSDStringVector output;
+ RVNGStringVector output;
+#if WITH_LIBVISIO01
+ librevenge::RVNGSVGDrawingGenerator generator(output, "svg");
+
+ if (!libvisio::VisioDocument::parseStencils(&input, &generator)) {
+#else
if (!libvisio::VisioDocument::generateSVGStencils(&input, output)) {
+#endif
return NULL;
}
@@ -594,11 +657,11 @@ GSList* SymbolsDialog::symbols_in_doc_recursive (SPObject *r, GSList *l)
g_return_val_if_fail(r != NULL, l);
// Stop multiple counting of same symbol
- if( SP_IS_USE(r) ) {
+ if ( dynamic_cast<SPUse *>(r) ) {
return l;
}
- if( SP_IS_SYMBOL(r) ) {
+ if ( dynamic_cast<SPSymbol *>(r) ) {
l = g_slist_prepend (l, r);
}
@@ -613,13 +676,14 @@ GSList* SymbolsDialog::symbols_in_doc( SPDocument* symbolDocument ) {
GSList *l = NULL;
l = symbols_in_doc_recursive (symbolDocument->getRoot(), l );
+ l = g_slist_reverse( l );
return l;
}
GSList* SymbolsDialog::use_in_doc_recursive (SPObject *r, GSList *l)
{
- if( SP_IS_USE(r) ) {
+ if ( dynamic_cast<SPUse *>(r) ) {
l = g_slist_prepend (l, r);
}
@@ -644,8 +708,9 @@ gchar const* SymbolsDialog::style_from_use( gchar const* id, SPDocument* documen
gchar const* style = 0;
GSList* l = use_in_doc( document );
for( ; l != NULL; l = l->next ) {
- SPObject* use = SP_OBJECT(l->data);
- if( SP_IS_USE( use ) ) {
+ SPObject *obj = reinterpret_cast<SPObject *>(l->data);
+ SPUse *use = dynamic_cast<SPUse *>(obj);
+ if ( use ) {
gchar const *href = use->getRepr()->attribute("xlink:href");
if( href ) {
Glib::ustring href2(href);
@@ -665,8 +730,9 @@ void SymbolsDialog::add_symbols( SPDocument* symbolDocument ) {
GSList* l = symbols_in_doc( symbolDocument );
for( ; l != NULL; l = l->next ) {
- SPObject* symbol = SP_OBJECT(l->data);
- if (SP_IS_SYMBOL(symbol)) {
+ SPObject *obj = reinterpret_cast<SPObject *>(l->data);
+ SPSymbol *symbol = dynamic_cast<SPSymbol *>(obj);
+ if (symbol) {
add_symbol( symbol );
}
}
@@ -755,8 +821,9 @@ SymbolsDialog::draw_symbol(SPObject *symbol)
previewDocument->getRoot()->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
previewDocument->ensureUpToDate();
- SPItem *item = SP_ITEM(object_temp);
- unsigned psize = SYMBOL_ICON_SIZES[in_sizes];
+ SPItem *item = dynamic_cast<SPItem *>(object_temp);
+ g_assert(item != NULL);
+ unsigned psize = SYMBOL_ICON_SIZES[pack_size];
Glib::RefPtr<Gdk::Pixbuf> pixbuf(NULL);
// We could use cache here, but it doesn't really work with the structure
@@ -778,6 +845,8 @@ SymbolsDialog::draw_symbol(SPObject *symbol)
if( fitSymbol->get_active() )
scale = psize / std::max(width, height);
+ else
+ scale = pow( 2.0, scale_factor/2.0 ) * psize / 32.0;
pixbuf = Glib::wrap(render_pixbuf(renderDrawing, scale, *dbox, psize));
}
diff --git a/src/ui/dialog/symbols.h b/src/ui/dialog/symbols.h
index 8021fb0c1..5dc1e3cad 100644
--- a/src/ui/dialog/symbols.h
+++ b/src/ui/dialog/symbols.h
@@ -65,6 +65,8 @@ private:
static SymbolColumns *getColumns();
+ void packless();
+ void packmore();
void zoomin();
void zoomout();
void rebuild();
@@ -95,13 +97,18 @@ private:
std::map<Glib::ustring, SPDocument*> symbolSets;
// Index into sizes which is selected
- int in_sizes;
+ int pack_size;
+
+ // Scale factor
+ int scale_factor;
Glib::RefPtr<Gtk::ListStore> store;
Gtk::ComboBoxText* symbolSet;
Gtk::IconView* iconView;
Gtk::Button* addSymbol;
Gtk::Button* removeSymbol;
+ Gtk::Button* zoomIn;
+ Gtk::Button* zoomOut;
Gtk::ToggleButton* fitSymbol;
void setTargetDesktop(SPDesktop *desktop);
diff --git a/src/ui/dialog/tags.cpp b/src/ui/dialog/tags.cpp
new file mode 100644
index 000000000..8a104d137
--- /dev/null
+++ b/src/ui/dialog/tags.cpp
@@ -0,0 +1,1166 @@
+/*
+ * A simple panel for tags
+ *
+ * Authors:
+ * Theodore Janeczko
+ *
+ * Copyright (C) Theodore Janeczko 2012 <flutterguy317@gmail.com>
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#if WITH_GLIBMM_2_32
+# include <glibmm/threads.h>
+#endif
+
+#include "tags.h"
+#include <gtkmm/widget.h>
+#include <gtkmm/icontheme.h>
+#include <gtkmm/imagemenuitem.h>
+#include <gtkmm/separatormenuitem.h>
+
+#include <glibmm/main.h>
+#include <glibmm/i18n.h>
+
+#include "desktop.h"
+#include "desktop-style.h"
+#include "document.h"
+#include "document-undo.h"
+#include "helper/action.h"
+#include "inkscape.h"
+#include "layer-fns.h"
+#include "layer-manager.h"
+#include "preferences.h"
+#include "sp-item.h"
+#include "sp-object.h"
+#include "sp-shape.h"
+#include "svg/css-ostringstream.h"
+#include "ui/icon-names.h"
+#include "ui/widget/layertypeicon.h"
+#include "ui/widget/addtoicon.h"
+#include "verbs.h"
+#include "widgets/icon.h"
+#include "xml/node.h"
+#include "xml/node-observer.h"
+#include "xml/repr.h"
+#include "sp-root.h"
+#include "ui/tools/tool-base.h" //"event-context.h"
+#include "selection.h"
+//#include "dialogs/dialog-events.h"
+#include "widgets/sp-color-notebook.h"
+#include "style.h"
+#include "filter-chemistry.h"
+#include "filters/blend.h"
+#include "filters/gaussian-blur.h"
+#include "sp-clippath.h"
+#include "sp-mask.h"
+#include "sp-tag.h"
+#include "sp-defs.h"
+#include "sp-tag-use.h"
+#include "sp-tag-use-reference.h"
+
+//#define DUMP_LAYERS 1
+
+namespace Inkscape {
+namespace UI {
+namespace Dialog {
+
+using Inkscape::XML::Node;
+
+TagsPanel& TagsPanel::getInstance()
+{
+ return *new TagsPanel();
+}
+
+enum {
+ COL_ADD = 1
+};
+
+enum {
+ BUTTON_NEW = 0,
+ BUTTON_TOP,
+ BUTTON_BOTTOM,
+ BUTTON_UP,
+ BUTTON_DOWN,
+ BUTTON_DELETE,
+ DRAGNDROP
+};
+
+class TagsPanel::ObjectWatcher : public Inkscape::XML::NodeObserver {
+public:
+ ObjectWatcher(TagsPanel* pnl, SPObject* obj, Inkscape::XML::Node * repr) :
+ _pnl(pnl),
+ _obj(obj),
+ _repr(repr),
+ _labelAttr(g_quark_from_string("inkscape:label"))
+ {}
+
+ ObjectWatcher(TagsPanel* pnl, SPObject* obj) :
+ _pnl(pnl),
+ _obj(obj),
+ _repr(obj->getRepr()),
+ _labelAttr(g_quark_from_string("inkscape:label"))
+ {}
+
+ virtual void notifyChildAdded( Node &/*node*/, Node &/*child*/, Node */*prev*/ )
+ {
+ if ( _pnl && _obj ) {
+ _pnl->_objectsChanged( _obj );
+ }
+ }
+ virtual void notifyChildRemoved( Node &/*node*/, Node &/*child*/, Node */*prev*/ )
+ {
+ if ( _pnl && _obj ) {
+ _pnl->_objectsChanged( _obj );
+ }
+ }
+ virtual void notifyChildOrderChanged( Node &/*node*/, Node &/*child*/, Node */*old_prev*/, Node */*new_prev*/ )
+ {
+ if ( _pnl && _obj ) {
+ _pnl->_objectsChanged( _obj );
+ }
+ }
+ virtual void notifyContentChanged( Node &/*node*/, Util::ptr_shared<char> /*old_content*/, Util::ptr_shared<char> /*new_content*/ ) {}
+ virtual void notifyAttributeChanged( Node &/*node*/, GQuark name, Util::ptr_shared<char> /*old_value*/, Util::ptr_shared<char> /*new_value*/ ) {
+ if ( _pnl && _obj ) {
+ if ( name == _labelAttr ) {
+ _pnl->_updateObject( _obj);
+ }
+ }
+ }
+
+ TagsPanel* _pnl;
+ SPObject* _obj;
+ Inkscape::XML::Node* _repr;
+ GQuark _labelAttr;
+};
+
+class TagsPanel::InternalUIBounce
+{
+public:
+ int _actionCode;
+};
+
+void TagsPanel::_styleButton( Gtk::Button& btn, SPDesktop *desktop, unsigned int code, char const* iconName, char const* tooltip )
+{
+ bool set = false;
+
+ if ( iconName ) {
+ GtkWidget *child = sp_icon_new( Inkscape::ICON_SIZE_SMALL_TOOLBAR, iconName );
+ gtk_widget_show( child );
+ btn.add( *manage(Glib::wrap(child)) );
+ btn.set_relief(Gtk::RELIEF_NONE);
+ set = true;
+ }
+
+ if ( desktop ) {
+ Verb *verb = Verb::get( code );
+ if ( verb ) {
+ SPAction *action = verb->get_action(desktop);
+ if ( !set && action && action->image ) {
+ GtkWidget *child = sp_icon_new( Inkscape::ICON_SIZE_SMALL_TOOLBAR, action->image );
+ gtk_widget_show( child );
+ btn.add( *manage(Glib::wrap(child)) );
+ set = true;
+ }
+ }
+ }
+
+ btn.set_tooltip_text (tooltip);
+}
+
+
+Gtk::MenuItem& TagsPanel::_addPopupItem( SPDesktop *desktop, unsigned int code, char const* iconName, char const* fallback, int id )
+{
+ GtkWidget* iconWidget = 0;
+ const char* label = 0;
+
+ if ( iconName ) {
+ iconWidget = sp_icon_new( Inkscape::ICON_SIZE_MENU, iconName );
+ }
+
+ if ( desktop ) {
+ Verb *verb = Verb::get( code );
+ if ( verb ) {
+ SPAction *action = verb->get_action(desktop);
+ if ( !iconWidget && action && action->image ) {
+ iconWidget = sp_icon_new( Inkscape::ICON_SIZE_MENU, action->image );
+ }
+
+ if ( action ) {
+ label = action->name;
+ }
+ }
+ }
+
+ if ( !label && fallback ) {
+ label = fallback;
+ }
+
+ Gtk::Widget* wrapped = 0;
+ if ( iconWidget ) {
+ wrapped = manage(Glib::wrap(iconWidget));
+ wrapped->show();
+ }
+
+
+ Gtk::MenuItem* item = 0;
+
+ if (wrapped) {
+ item = Gtk::manage(new Gtk::ImageMenuItem(*wrapped, label, true));
+ } else {
+ item = Gtk::manage(new Gtk::MenuItem(label, true));
+ }
+
+ item->signal_activate().connect(sigc::bind(sigc::mem_fun(*this, &TagsPanel::_takeAction), id));
+ _popupMenu.append(*item);
+
+ return *item;
+}
+
+void TagsPanel::_fireAction( unsigned int code )
+{
+ if ( _desktop ) {
+ Verb *verb = Verb::get( code );
+ if ( verb ) {
+ SPAction *action = verb->get_action(_desktop);
+ if ( action ) {
+ sp_action_perform( action, NULL );
+ }
+ }
+ }
+}
+
+void TagsPanel::_takeAction( int val )
+{
+ if ( !_pending ) {
+ _pending = new InternalUIBounce();
+ _pending->_actionCode = val;
+ Glib::signal_timeout().connect( sigc::mem_fun(*this, &TagsPanel::_executeAction), 0 );
+ }
+}
+
+bool TagsPanel::_executeAction()
+{
+ // Make sure selected layer hasn't changed since the action was triggered
+ if ( _pending)
+ {
+ int val = _pending->_actionCode;
+// SPObject* target = _pending->_target;
+ bool empty = _desktop->selection->isEmpty();
+
+ switch ( val ) {
+ case BUTTON_NEW:
+ {
+ _fireAction( SP_VERB_TAG_NEW );
+ }
+ break;
+ case BUTTON_TOP:
+ {
+ _fireAction( empty ? SP_VERB_LAYER_TO_TOP : SP_VERB_SELECTION_TO_FRONT);
+ }
+ break;
+ case BUTTON_BOTTOM:
+ {
+ _fireAction( empty ? SP_VERB_LAYER_TO_BOTTOM : SP_VERB_SELECTION_TO_BACK );
+ }
+ break;
+ case BUTTON_UP:
+ {
+ _fireAction( empty ? SP_VERB_LAYER_RAISE : SP_VERB_SELECTION_RAISE );
+ }
+ break;
+ case BUTTON_DOWN:
+ {
+ _fireAction( empty ? SP_VERB_LAYER_LOWER : SP_VERB_SELECTION_LOWER );
+ }
+ break;
+ case BUTTON_DELETE:
+ {
+ std::vector<SPObject *> todelete;
+ _tree.get_selection()->selected_foreach_iter(sigc::bind<std::vector<SPObject *>*>(sigc::mem_fun(*this, &TagsPanel::_checkForDeleted), &todelete));
+ for (std::vector<SPObject *>::iterator iter = todelete.begin(); iter != todelete.end(); ++iter) {
+ SPObject * obj = *iter;
+ if (obj && obj->parent && obj->getRepr() && obj->parent->getRepr()) {
+ //obj->parent->getRepr()->removeChild(obj->getRepr());
+ obj->deleteObject(true, true);
+ }
+ }
+ DocumentUndo::done(_document, SP_VERB_DIALOG_TAGS, _("Remove from selection set"));
+ }
+ break;
+ case DRAGNDROP:
+ {
+ _doTreeMove( );
+ }
+ break;
+ }
+
+ delete _pending;
+ _pending = 0;
+ }
+
+ return false;
+}
+
+
+class TagsPanel::ModelColumns : public Gtk::TreeModel::ColumnRecord
+{
+public:
+
+ ModelColumns()
+ {
+ add(_colParentObject);
+ add(_colObject);
+ add(_colLabel);
+ add(_colAddRemove);
+ add(_colAllowAddRemove);
+ }
+ virtual ~ModelColumns() {}
+
+ Gtk::TreeModelColumn<SPObject*> _colParentObject;
+ Gtk::TreeModelColumn<SPObject*> _colObject;
+ Gtk::TreeModelColumn<Glib::ustring> _colLabel;
+ Gtk::TreeModelColumn<bool> _colAddRemove;
+ Gtk::TreeModelColumn<bool> _colAllowAddRemove;
+};
+
+void TagsPanel::_checkForDeleted(const Gtk::TreeIter& iter, std::vector<SPObject *>* todelete)
+{
+ Gtk::TreeRow row = *iter;
+ SPObject * obj = row[_model->_colObject];
+ if (obj && obj->parent) {
+ todelete->push_back(obj);
+ }
+}
+
+void TagsPanel::_updateObject( SPObject *obj ) {
+ _store->foreach( sigc::bind<SPObject*>(sigc::mem_fun(*this, &TagsPanel::_checkForUpdated), obj) );
+}
+
+bool TagsPanel::_checkForUpdated(const Gtk::TreePath &/*path*/, const Gtk::TreeIter& iter, SPObject* obj)
+{
+ Gtk::TreeModel::Row row = *iter;
+ if ( obj == row[_model->_colObject] )
+ {
+ /*
+ * We get notified of layer update here (from layer->setLabel()) before layer->label() is set
+ * with the correct value (sp-object bug?). So use the inkscape:label attribute instead which
+ * has the correct value (bug #168351)
+ */
+ //row[_model->_colLabel] = layer->label() ? layer->label() : layer->getId();
+ gchar const *label;
+ SPTagUse * use = SP_IS_TAG_USE(obj) ? SP_TAG_USE(obj) : 0;
+ if (use && use->ref->isAttached()) {
+ label = use->ref->getObject()->getAttribute("inkscape:label");
+ } else {
+ label = obj->getAttribute("inkscape:label");
+ }
+ row[_model->_colLabel] = label ? label : obj->getId();
+ row[_model->_colAddRemove] = SP_IS_TAG(obj);
+ }
+
+ return false;
+}
+
+void TagsPanel::_objectsSelected( Selection *sel ) {
+
+ _selectedConnection.block();
+ _tree.get_selection()->unselect_all();
+ for (const GSList * iter = sel->list(); iter != NULL; iter = iter->next)
+ {
+ SPObject *obj = reinterpret_cast<SPObject *>(iter->data);
+ _store->foreach(sigc::bind<SPObject *>( sigc::mem_fun(*this, &TagsPanel::_checkForSelected), obj));
+ }
+ _selectedConnection.unblock();
+ _checkTreeSelection();
+}
+
+bool TagsPanel::_checkForSelected(const Gtk::TreePath &/*path*/, const Gtk::TreeIter& iter, SPObject* obj)
+{
+ Gtk::TreeModel::Row row = *iter;
+ SPObject * it = row[_model->_colObject];
+ if ( it && SP_IS_TAG_USE(it) && SP_TAG_USE(it)->ref->getObject() == obj )
+ {
+ Glib::RefPtr<Gtk::TreeSelection> select = _tree.get_selection();
+
+ select->select(iter);
+ }
+ return false;
+}
+
+// TODO does not look good that we're ignoring the passed in root. Investigate.
+void TagsPanel::_objectsChanged(SPObject* root)
+{
+ while (!_objectWatchers.empty())
+ {
+ TagsPanel::ObjectWatcher *w = _objectWatchers.back();
+ w->_repr->removeObserver(*w);
+ _objectWatchers.pop_back();
+ delete w;
+ }
+
+ if (_desktop) {
+ SPDocument* document = _desktop->doc();
+ SPDefs* root = document->getDefs();
+ if ( root ) {
+ _selectedConnection.block();
+ _store->clear();
+ _addObject( document, root, 0 );
+ _selectedConnection.unblock();
+ _objectsSelected(_desktop->selection);
+ _checkTreeSelection();
+ }
+ }
+}
+
+void TagsPanel::_addObject( SPDocument* doc, SPObject* obj, Gtk::TreeModel::Row* parentRow )
+{
+ if ( _desktop && obj ) {
+ for ( SPObject *child = obj->children; child != NULL; child = child->next) {
+ if (SP_IS_TAG(child))
+ {
+ Gtk::TreeModel::iterator iter = parentRow ? _store->prepend(parentRow->children()) : _store->prepend();
+ Gtk::TreeModel::Row row = *iter;
+ row[_model->_colObject] = child;
+ row[_model->_colParentObject] = NULL;
+ row[_model->_colLabel] = child->label() ? child->label() : child->getId();
+ row[_model->_colAddRemove] = true;
+ row[_model->_colAllowAddRemove] = true;
+
+ _tree.expand_to_path( _store->get_path(iter) );
+
+ TagsPanel::ObjectWatcher *w = new TagsPanel::ObjectWatcher(this, child);
+ child->getRepr()->addObserver(*w);
+ _objectWatchers.push_back(w);
+ _addObject( doc, child, &row );
+ }
+ }
+ if (SP_IS_TAG(obj) && obj->children)
+ {
+ Gtk::TreeModel::iterator iteritems = parentRow ? _store->append(parentRow->children()) : _store->prepend();
+ Gtk::TreeModel::Row rowitems = *iteritems;
+ rowitems[_model->_colObject] = NULL;
+ rowitems[_model->_colParentObject] = obj;
+ rowitems[_model->_colLabel] = _("Items");
+ rowitems[_model->_colAddRemove] = false;
+ rowitems[_model->_colAllowAddRemove] = false;
+
+ _tree.expand_to_path( _store->get_path(iteritems) );
+
+ for ( SPObject *child = obj->children; child != NULL; child = child->next) {
+ if (SP_IS_TAG_USE(child))
+ {
+ SPItem *item = SP_TAG_USE(child)->ref->getObject();
+ Gtk::TreeModel::iterator iter = _store->prepend(rowitems->children());
+ Gtk::TreeModel::Row row = *iter;
+ row[_model->_colObject] = child;
+ row[_model->_colParentObject] = NULL;
+ row[_model->_colLabel] = item ? (item->label() ? item->label() : item->getId()) : SP_TAG_USE(child)->href;
+ row[_model->_colAddRemove] = false;
+ row[_model->_colAllowAddRemove] = true;
+
+ if (SP_TAG(obj)->expanded()) {
+ _tree.expand_to_path( _store->get_path(iter) );
+ }
+
+ if (item) {
+ TagsPanel::ObjectWatcher *w = new TagsPanel::ObjectWatcher(this, child, item->getRepr());
+ item->getRepr()->addObserver(*w);
+ _objectWatchers.push_back(w);
+ }
+ }
+ }
+ }
+ }
+}
+
+void TagsPanel::_select_tag( SPTag * tag )
+{
+ for (SPObject * child = tag->children; child != NULL; child = child->next)
+ {
+ if (SP_IS_TAG(child)) {
+ _select_tag(SP_TAG(child));
+ } else if (SP_IS_TAG_USE(child)) {
+ SPObject * obj = SP_TAG_USE(child)->ref->getObject();
+ if (obj) {
+ if (_desktop->selection->isEmpty()) _desktop->setCurrentLayer(obj->parent);
+ _desktop->selection->add(obj);
+ }
+ }
+ }
+}
+
+void TagsPanel::_selected_row_callback( const Gtk::TreeModel::iterator& iter )
+{
+ if (iter) {
+ Gtk::TreeModel::Row row = *iter;
+ SPObject *obj = row[_model->_colObject];
+ if (obj) {
+ if (SP_IS_TAG(obj)) {
+ _select_tag(SP_TAG(obj));
+ } else if (SP_IS_TAG_USE(obj)) {
+ SPObject * item = SP_TAG_USE(obj)->ref->getObject();
+ if (item) {
+ if (_desktop->selection->isEmpty()) _desktop->setCurrentLayer(item->parent);
+ _desktop->selection->add(item);
+ }
+ }
+ }
+ }
+}
+
+void TagsPanel::_pushTreeSelectionToCurrent()
+{
+ _selectionChangedConnection.block();
+ // TODO hunt down the possible API abuse in getting NULL
+ if ( _desktop && _desktop->currentRoot() ) {
+ _desktop->selection->clear();
+ _tree.get_selection()->selected_foreach_iter( sigc::mem_fun(*this, &TagsPanel::_selected_row_callback));
+ }
+ _selectionChangedConnection.unblock();
+
+ _checkTreeSelection();
+}
+
+void TagsPanel::_checkTreeSelection()
+{
+ bool sensitive = _tree.get_selection()->count_selected_rows() > 0;
+ bool sensitiveNonTop = true;
+ bool sensitiveNonBottom = true;
+// if ( _tree.get_selection()->count_selected_rows() > 0 ) {
+// sensitive = true;
+//
+// SPObject* inTree = _selectedLayer();
+// if ( inTree ) {
+//
+// sensitiveNonTop = (Inkscape::Nex(inTree->parent, inTree) != 0);
+// sensitiveNonBottom = (Inkscape::previous_layer(inTree->parent, inTree) != 0);
+//
+// }
+// }
+
+
+ for ( std::vector<Gtk::Widget*>::iterator it = _watching.begin(); it != _watching.end(); ++it ) {
+ (*it)->set_sensitive( sensitive );
+ }
+ for ( std::vector<Gtk::Widget*>::iterator it = _watchingNonTop.begin(); it != _watchingNonTop.end(); ++it ) {
+ (*it)->set_sensitive( sensitiveNonTop );
+ }
+ for ( std::vector<Gtk::Widget*>::iterator it = _watchingNonBottom.begin(); it != _watchingNonBottom.end(); ++it ) {
+ (*it)->set_sensitive( sensitiveNonBottom );
+ }
+}
+
+bool TagsPanel::_handleKeyEvent(GdkEventKey *event)
+{
+
+ switch (Inkscape::UI::Tools::get_group0_keyval(event)) {
+ case GDK_KEY_Return:
+ case GDK_KEY_KP_Enter:
+ case GDK_KEY_F2: {
+ Gtk::TreeModel::iterator iter = _tree.get_selection()->get_selected();
+ if (iter && !_text_renderer->property_editable()) {
+ Gtk::TreeRow row = *iter;
+ SPObject * obj = row[_model->_colObject];
+ if (obj && SP_IS_TAG(obj)) {
+ Gtk::TreeModel::Path *path = new Gtk::TreeModel::Path(iter);
+ // Edit the layer label
+ _text_renderer->property_editable() = true;
+ _tree.set_cursor(*path, *_name_column, true);
+ grab_focus();
+ return true;
+ }
+ }
+ }
+ case GDK_KEY_Delete: {
+ std::vector<SPObject *> todelete;
+ _tree.get_selection()->selected_foreach_iter(sigc::bind<std::vector<SPObject *>*>(sigc::mem_fun(*this, &TagsPanel::_checkForDeleted), &todelete));
+ if (!todelete.empty()) {
+ for (std::vector<SPObject *>::iterator iter = todelete.begin(); iter != todelete.end(); ++iter) {
+ SPObject * obj = *iter;
+ if (obj && obj->parent && obj->getRepr() && obj->parent->getRepr()) {
+ //obj->parent->getRepr()->removeChild(obj->getRepr());
+ obj->deleteObject(true, true);
+ }
+ }
+ DocumentUndo::done(_document, SP_VERB_DIALOG_TAGS, _("Remove from selection set"));
+ }
+ return true;
+ }
+ break;
+ }
+ return false;
+}
+
+bool TagsPanel::_handleButtonEvent(GdkEventButton* event)
+{
+ static unsigned doubleclick = 0;
+
+ if ( (event->type == GDK_BUTTON_PRESS) && (event->button == 3) ) {
+ // TODO - fix to a better is-popup function
+ Gtk::TreeModel::Path path;
+ int x = static_cast<int>(event->x);
+ int y = static_cast<int>(event->y);
+ if ( _tree.get_path_at_pos( x, y, path ) ) {
+ _checkTreeSelection();
+ _popupMenu.popup(event->button, event->time);
+ if (_tree.get_selection()->is_selected(path)) {
+ return true;
+ }
+ }
+ }
+
+ if ( (event->type == GDK_BUTTON_PRESS) && (event->button == 1)) {
+ // Alt left click on the visible/lock columns - eat this event to keep row selection
+ Gtk::TreeModel::Path path;
+ Gtk::TreeViewColumn* col = 0;
+ int x = static_cast<int>(event->x);
+ int y = static_cast<int>(event->y);
+ int x2 = 0;
+ int y2 = 0;
+ if ( _tree.get_path_at_pos( x, y, path, col, x2, y2 ) ) {
+ if (col == _tree.get_column(COL_ADD-1)) {
+ down_at_add = true;
+ return true;
+ } else if ( !(event->state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK)) & _tree.get_selection()->is_selected(path) ) {
+ _tree.get_selection()->set_select_function(sigc::mem_fun(*this, &TagsPanel::_noSelection));
+ _defer_target = path;
+ } else {
+ down_at_add = false;
+ }
+ } else {
+ down_at_add = false;
+ }
+ }
+
+ if ( event->type == GDK_BUTTON_RELEASE) {
+ _tree.get_selection()->set_select_function(sigc::mem_fun(*this, &TagsPanel::_rowSelectFunction));
+ }
+
+ // TODO - ImageToggler doesn't seem to handle Shift/Alt clicks - so we deal with them here.
+ if ( (event->type == GDK_BUTTON_RELEASE) && (event->button == 1)) {
+
+ Gtk::TreeModel::Path path;
+ Gtk::TreeViewColumn* col = 0;
+ int x = static_cast<int>(event->x);
+ int y = static_cast<int>(event->y);
+ int x2 = 0;
+ int y2 = 0;
+ if ( _tree.get_path_at_pos( x, y, path, col, x2, y2 ) ) {
+ if (_defer_target) {
+ if (_defer_target == path && !(event->x == 0 && event->y == 0))
+ {
+ _tree.set_cursor(path, *col, false);
+ }
+ _defer_target = Gtk::TreeModel::Path();
+ } else {
+ Gtk::TreeModel::Children::iterator iter = _tree.get_model()->get_iter(path);
+ Gtk::TreeModel::Row row = *iter;
+
+ SPObject* obj = row[_model->_colObject];
+
+ if (obj) {
+ if (col == _tree.get_column(COL_ADD - 1) && down_at_add) {
+ if (SP_IS_TAG(obj)) {
+ bool wasadded = false;
+ for (const GSList * iter = _desktop->selection->itemList(); iter != NULL; iter = iter->next)
+ {
+ SPObject *newobj = reinterpret_cast<SPObject *>(iter->data);
+ bool addchild = true;
+ for ( SPObject *child = obj->children; child != NULL; child = child->next) {
+ if (SP_IS_TAG_USE(child) && SP_TAG_USE(child)->ref->getObject() == newobj) {
+ addchild = false;
+ }
+ }
+ if (addchild) {
+ Inkscape::XML::Node *clone = _document->getReprDoc()->createElement("inkscape:tagref");
+ clone->setAttribute("xlink:href", g_strdup_printf("#%s", newobj->getRepr()->attribute("id")), false);
+ obj->appendChild(clone);
+ wasadded = true;
+ }
+ }
+ if (wasadded) {
+ DocumentUndo::done(_document, SP_VERB_DIALOG_TAGS, _("Add selection to set"));
+ }
+ } else {
+ std::vector<SPObject *> todelete;
+ // FIXME unnecessary use of XML tree
+ _tree.get_selection()->selected_foreach_iter(sigc::bind<std::vector<SPObject *>*>(sigc::mem_fun(*this, &TagsPanel::_checkForDeleted), &todelete));
+ if (!todelete.empty()) {
+ for (std::vector<SPObject *>::iterator iter = todelete.begin(); iter != todelete.end(); ++iter) {
+ SPObject * tobj = *iter;
+ if (tobj && tobj->parent && tobj->getRepr() && tobj->parent->getRepr()) {
+ //tobj->parent->getRepr()->removeChild(tobj->getRepr());
+ tobj->deleteObject(true, true);
+ }
+ }
+ } else if (obj && obj->parent && obj->getRepr() && obj->parent->getRepr()) {
+ obj->parent->getRepr()->removeChild(obj->getRepr());
+ }
+ DocumentUndo::done(_document, SP_VERB_DIALOG_TAGS, _("Remove from selection set"));
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+ if ( (event->type == GDK_2BUTTON_PRESS) && (event->button == 1) ) {
+ doubleclick = 1;
+ }
+
+ if ( event->type == GDK_BUTTON_RELEASE && doubleclick) {
+ doubleclick = 0;
+ Gtk::TreeModel::Path path;
+ Gtk::TreeViewColumn* col = 0;
+ int x = static_cast<int>(event->x);
+ int y = static_cast<int>(event->y);
+ int x2 = 0;
+ int y2 = 0;
+ if ( _tree.get_path_at_pos( x, y, path, col, x2, y2 ) && col == _name_column) {
+ Gtk::TreeModel::Children::iterator iter = _tree.get_model()->get_iter(path);
+ Gtk::TreeModel::Row row = *iter;
+
+ SPObject* obj = row[_model->_colObject];
+ if (obj && (SP_IS_TAG(obj) || (SP_IS_TAG_USE(obj) && SP_TAG_USE(obj)->ref->getObject()))) {
+ // Double click on the Layer name, enable editing
+ _text_renderer->property_editable() = true;
+ _tree.set_cursor (path, *_name_column, true);
+ grab_focus();
+ }
+ }
+ }
+
+ return false;
+}
+
+void TagsPanel::_storeDragSource(const Gtk::TreeModel::iterator& iter)
+{
+ Gtk::TreeModel::Row row = *iter;
+ SPObject* obj = row[_model->_colObject];
+ SPTag* item = ( obj && SP_IS_TAG(obj) ) ? SP_TAG(obj) : 0;
+ if (item)
+ {
+ _dnd_source.push_back(item);
+ }
+}
+
+/*
+ * Drap and drop within the tree
+ * Save the drag source and drop target SPObjects and if its a drag between layers or into (sublayer) a layer
+ */
+bool TagsPanel::_handleDragDrop(const Glib::RefPtr<Gdk::DragContext>& /*context*/, int x, int y, guint /*time*/)
+{
+ int cell_x = 0, cell_y = 0;
+ Gtk::TreeModel::Path target_path;
+ Gtk::TreeView::Column *target_column;
+
+ _dnd_into = true;
+ _dnd_target = _document->getDefs();
+ _dnd_source.clear();
+ _tree.get_selection()->selected_foreach_iter(sigc::mem_fun(*this, &TagsPanel::_storeDragSource));
+
+ if (_dnd_source.empty()) {
+ return true;
+ }
+
+ if (_tree.get_path_at_pos (x, y, target_path, target_column, cell_x, cell_y)) {
+ // Are we before, inside or after the drop layer
+ Gdk::Rectangle rect;
+ _tree.get_background_area (target_path, *target_column, rect);
+ int cell_height = rect.get_height();
+ _dnd_into = (cell_y > (int)(cell_height * 1/3) && cell_y <= (int)(cell_height * 2/3));
+ if (cell_y > (int)(cell_height * 2/3)) {
+ Gtk::TreeModel::Path next_path = target_path;
+ next_path.next();
+ if (_store->iter_is_valid(_store->get_iter(next_path))) {
+ target_path = next_path;
+ } else {
+ // Dragging to the "end"
+ Gtk::TreeModel::Path up_path = target_path;
+ up_path.up();
+ if (_store->iter_is_valid(_store->get_iter(up_path))) {
+ // Drop into parent
+ target_path = up_path;
+ _dnd_into = true;
+ } else {
+ // Drop into the top level
+ _dnd_target = _document->getDefs();
+ _dnd_into = true;
+ }
+ }
+ }
+ Gtk::TreeModel::iterator iter = _store->get_iter(target_path);
+ if (_store->iter_is_valid(iter)) {
+ Gtk::TreeModel::Row row = *iter;
+ SPObject *obj = row[_model->_colObject];
+ SPObject *pobj = row[_model->_colParentObject];
+ if (obj) {
+ if (SP_IS_TAG(obj)) {
+ _dnd_target = SP_TAG(obj);
+ } else if (SP_IS_TAG(obj->parent)) {
+ _dnd_target = SP_TAG(obj->parent);
+ _dnd_into = true;
+ }
+ } else if (pobj && SP_IS_TAG(pobj)) {
+ _dnd_target = SP_TAG(pobj);
+ _dnd_into = true;
+ } else {
+ return true;
+ }
+ }
+ }
+
+ _takeAction(DRAGNDROP);
+
+ return false;
+}
+
+/*
+ * Move a layer in response to a drag & drop action
+ */
+void TagsPanel::_doTreeMove( )
+{
+ if (_dnd_target) {
+ for (std::vector<SPTag *>::iterator iter = _dnd_source.begin(); iter != _dnd_source.end(); ++iter)
+ {
+ SPTag *src = *iter;
+ if (src != _dnd_target) {
+ src->moveTo(_dnd_target, _dnd_into);
+ }
+ }
+ _desktop->selection->clear();
+ while (!_dnd_source.empty())
+ {
+ SPTag *src = _dnd_source.back();
+ _select_tag(src);
+ _dnd_source.pop_back();
+ }
+ DocumentUndo::done( _desktop->doc() , SP_VERB_DIALOG_TAGS,
+ _("Moved sets"));
+ }
+}
+
+
+void TagsPanel::_handleEdited(const Glib::ustring& path, const Glib::ustring& new_text)
+{
+ Gtk::TreeModel::iterator iter = _tree.get_model()->get_iter(path);
+ Gtk::TreeModel::Row row = *iter;
+
+ _renameObject(row, new_text);
+ _text_renderer->property_editable() = false;
+}
+
+void TagsPanel::_handleEditingCancelled()
+{
+ _text_renderer->property_editable() = false;
+}
+
+void TagsPanel::_renameObject(Gtk::TreeModel::Row row, const Glib::ustring& name)
+{
+ if ( row && _desktop) {
+ SPObject* obj = row[_model->_colObject];
+ if ( obj ) {
+ if (SP_IS_TAG(obj)) {
+ gchar const* oldLabel = obj->label();
+ if ( !name.empty() && (!oldLabel || name != oldLabel) ) {
+ obj->setLabel(name.c_str());
+ DocumentUndo::done( _desktop->doc() , SP_VERB_NONE,
+ _("Rename object"));
+ }
+ } else if (SP_IS_TAG_USE(obj) && (obj = SP_TAG_USE(obj)->ref->getObject())) {
+ gchar const* oldLabel = obj->label();
+ if ( !name.empty() && (!oldLabel || name != oldLabel) ) {
+ obj->setLabel(name.c_str());
+ DocumentUndo::done( _desktop->doc() , SP_VERB_NONE,
+ _("Rename object"));
+ }
+ }
+ }
+ }
+}
+
+bool TagsPanel::_noSelection( Glib::RefPtr<Gtk::TreeModel> const & /*model*/, Gtk::TreeModel::Path const & /*path*/, bool /*currentlySelected*/ )
+{
+ return false;
+}
+
+bool TagsPanel::_rowSelectFunction( Glib::RefPtr<Gtk::TreeModel> const & /*model*/, Gtk::TreeModel::Path const & /*path*/, bool currentlySelected )
+{
+ bool val = true;
+ if ( !currentlySelected && _toggleEvent )
+ {
+ GdkEvent* event = gtk_get_current_event();
+ if ( event ) {
+ // (keep these checks separate, so we know when to call gdk_event_free()
+ if ( event->type == GDK_BUTTON_PRESS ) {
+ GdkEventButton const* target = reinterpret_cast<GdkEventButton const*>(_toggleEvent);
+ GdkEventButton const* evtb = reinterpret_cast<GdkEventButton const*>(event);
+
+ if ( (evtb->window == target->window)
+ && (evtb->send_event == target->send_event)
+ && (evtb->time == target->time)
+ && (evtb->state == target->state)
+ )
+ {
+ // Ooooh! It's a magic one
+ val = false;
+ }
+ }
+ gdk_event_free(event);
+ }
+ }
+ return val;
+}
+
+void TagsPanel::_setExpanded(const Gtk::TreeModel::iterator& iter, const Gtk::TreeModel::Path& /*path*/, bool isexpanded)
+{
+ Gtk::TreeModel::Row row = *iter;
+
+ SPObject* obj = row[_model->_colParentObject];
+ if (obj && SP_IS_TAG(obj))
+ {
+ SP_TAG(obj)->setExpanded(isexpanded);
+ obj->updateRepr(SP_OBJECT_WRITE_NO_CHILDREN | SP_OBJECT_WRITE_EXT);
+ }
+}
+
+/**
+ * Constructor
+ */
+TagsPanel::TagsPanel() :
+ UI::Widget::Panel("", "/dialogs/tags", SP_VERB_DIALOG_TAGS),
+ _rootWatcher(0),
+ deskTrack(),
+ _desktop(0),
+ _document(0),
+ _model(0),
+ _pending(0),
+ _toggleEvent(0),
+ _defer_target(),
+ desktopChangeConn()
+{
+ //Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+
+ ModelColumns *zoop = new ModelColumns();
+ _model = zoop;
+
+ _store = Gtk::TreeStore::create( *zoop );
+
+ _tree.set_model( _store );
+ _tree.set_headers_visible(false);
+ _tree.set_reorderable(true);
+ _tree.enable_model_drag_dest (Gdk::ACTION_MOVE);
+
+ Inkscape::UI::Widget::AddToIcon * addRenderer = manage( new Inkscape::UI::Widget::AddToIcon());
+ int addColNum = _tree.append_column("type", *addRenderer) - 1;
+ Gtk::TreeViewColumn *col = _tree.get_column(addColNum);
+ if ( col ) {
+ col->add_attribute( addRenderer->property_active(), _model->_colAddRemove );
+ col->add_attribute( addRenderer->property_visible(), _model->_colAllowAddRemove );
+ }
+
+ _text_renderer = manage(new Gtk::CellRendererText());
+ int nameColNum = _tree.append_column("Name", *_text_renderer) - 1;
+ _name_column = _tree.get_column(nameColNum);
+ _name_column->add_attribute(_text_renderer->property_text(), _model->_colLabel);
+
+ _tree.set_expander_column( *_tree.get_column(nameColNum) );
+
+ _tree.get_selection()->set_mode(Gtk::SELECTION_MULTIPLE);
+ _selectedConnection = _tree.get_selection()->signal_changed().connect( sigc::mem_fun(*this, &TagsPanel::_pushTreeSelectionToCurrent) );
+ _tree.get_selection()->set_select_function( sigc::mem_fun(*this, &TagsPanel::_rowSelectFunction) );
+
+ _tree.signal_drag_drop().connect( sigc::mem_fun(*this, &TagsPanel::_handleDragDrop), false);
+ _collapsedConnection = _tree.signal_row_collapsed().connect( sigc::bind<bool>(sigc::mem_fun(*this, &TagsPanel::_setExpanded), false));
+ _expandedConnection = _tree.signal_row_expanded().connect( sigc::bind<bool>(sigc::mem_fun(*this, &TagsPanel::_setExpanded), true));
+
+ _text_renderer->signal_edited().connect( sigc::mem_fun(*this, &TagsPanel::_handleEdited) );
+ _text_renderer->signal_editing_canceled().connect( sigc::mem_fun(*this, &TagsPanel::_handleEditingCancelled) );
+
+ _tree.signal_button_press_event().connect( sigc::mem_fun(*this, &TagsPanel::_handleButtonEvent), false );
+ _tree.signal_button_release_event().connect( sigc::mem_fun(*this, &TagsPanel::_handleButtonEvent), false );
+ _tree.signal_key_press_event().connect( sigc::mem_fun(*this, &TagsPanel::_handleKeyEvent), false );
+
+ _scroller.add( _tree );
+ _scroller.set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC );
+ _scroller.set_shadow_type(Gtk::SHADOW_IN);
+ Gtk::Requisition sreq;
+#if WITH_GTKMM_3_0
+ Gtk::Requisition sreq_natural;
+ _scroller.get_preferred_size(sreq_natural, sreq);
+#else
+ sreq = _scroller.size_request();
+#endif
+ int minHeight = 70;
+ if (sreq.height < minHeight) {
+ // Set a min height to see the layers when used with Ubuntu liboverlay-scrollbar
+ _scroller.set_size_request(sreq.width, minHeight);
+ }
+
+ _layersPage.pack_start( _scroller, Gtk::PACK_EXPAND_WIDGET );
+
+ _layersPage.pack_end(_buttonsRow, Gtk::PACK_SHRINK);
+
+ _getContents()->pack_start(_layersPage, Gtk::PACK_EXPAND_WIDGET);
+
+ SPDesktop* targetDesktop = getDesktop();
+
+ Gtk::Button* btn = manage( new Gtk::Button() );
+ _styleButton( *btn, targetDesktop, SP_VERB_TAG_NEW, GTK_STOCK_ADD, _("Add a new selection set") );
+ btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &TagsPanel::_takeAction), (int)BUTTON_NEW) );
+ _buttonsSecondary.pack_start(*btn, Gtk::PACK_SHRINK);
+
+// btn = manage( new Gtk::Button("Dup") );
+// btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &LayersPanel::_takeAction), (int)BUTTON_DUPLICATE) );
+// _buttonsRow.add( *btn );
+
+ btn = manage( new Gtk::Button() );
+ _styleButton( *btn, targetDesktop, SP_VERB_LAYER_DELETE, GTK_STOCK_REMOVE, _("Remove Item/Set") );
+ btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &TagsPanel::_takeAction), (int)BUTTON_DELETE) );
+ _watching.push_back( btn );
+ _buttonsSecondary.pack_start(*btn, Gtk::PACK_SHRINK);
+
+ _buttonsRow.pack_start(_buttonsSecondary, Gtk::PACK_EXPAND_WIDGET);
+ _buttonsRow.pack_end(_buttonsPrimary, Gtk::PACK_EXPAND_WIDGET);
+
+ // -------------------------------------------------------
+ {
+ _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_TAG_NEW, 0, "Add a new selection set", (int)BUTTON_NEW ) );
+
+ _popupMenu.show_all_children();
+ }
+ // -------------------------------------------------------
+
+
+
+ for ( std::vector<Gtk::Widget*>::iterator it = _watching.begin(); it != _watching.end(); ++it ) {
+ (*it)->set_sensitive( false );
+ }
+ for ( std::vector<Gtk::Widget*>::iterator it = _watchingNonTop.begin(); it != _watchingNonTop.end(); ++it ) {
+ (*it)->set_sensitive( false );
+ }
+ for ( std::vector<Gtk::Widget*>::iterator it = _watchingNonBottom.begin(); it != _watchingNonBottom.end(); ++it ) {
+ (*it)->set_sensitive( false );
+ }
+
+ setDesktop( targetDesktop );
+
+ show_all_children();
+
+ // restorePanelPrefs();
+
+ // Connect this up last
+ desktopChangeConn = deskTrack.connectDesktopChanged( sigc::mem_fun(*this, &TagsPanel::setDesktop) );
+ deskTrack.connect(GTK_WIDGET(gobj()));
+}
+
+TagsPanel::~TagsPanel()
+{
+
+ setDesktop(NULL);
+
+ if ( _model )
+ {
+ delete _model;
+ _model = 0;
+ }
+
+ if (_pending) {
+ delete _pending;
+ _pending = 0;
+ }
+
+ if ( _toggleEvent )
+ {
+ gdk_event_free( _toggleEvent );
+ _toggleEvent = 0;
+ }
+
+ desktopChangeConn.disconnect();
+ deskTrack.disconnect();
+}
+
+void TagsPanel::setDocument(SPDesktop* /*desktop*/, SPDocument* document)
+{
+ while (!_objectWatchers.empty())
+ {
+ TagsPanel::ObjectWatcher *w = _objectWatchers.back();
+ w->_repr->removeObserver(*w);
+ _objectWatchers.pop_back();
+ delete w;
+ }
+
+ if (_rootWatcher)
+ {
+ _rootWatcher->_repr->removeObserver(*_rootWatcher);
+ delete _rootWatcher;
+ _rootWatcher = NULL;
+ }
+
+ _document = document;
+
+ if (document && document->getDefs() && document->getDefs()->getRepr())
+ {
+ _rootWatcher = new TagsPanel::ObjectWatcher(this, document->getDefs());
+ document->getDefs()->getRepr()->addObserver(*_rootWatcher);
+ _objectsChanged(document->getDefs());
+ }
+}
+
+void TagsPanel::setDesktop( SPDesktop* desktop )
+{
+ Panel::setDesktop(desktop);
+
+ if ( desktop != _desktop ) {
+ _documentChangedConnection.disconnect();
+ _selectionChangedConnection.disconnect();
+ if ( _desktop ) {
+ _desktop = 0;
+ }
+
+ _desktop = Panel::getDesktop();
+ if ( _desktop ) {
+ //setLabel( _desktop->doc()->name );
+ _documentChangedConnection = _desktop->connectDocumentReplaced( sigc::mem_fun(*this, &TagsPanel::setDocument));
+ _selectionChangedConnection = _desktop->selection->connectChanged( sigc::mem_fun(*this, &TagsPanel::_objectsSelected));
+
+ setDocument(_desktop, _desktop->doc());
+ }
+ }
+/*
+ GSList const *layers = _desktop->doc()->getResourceList( "layer" );
+ g_message( "layers list starts at %p", layers );
+ for ( GSList const *iter=layers ; iter ; iter = iter->next ) {
+ SPObject *layer=static_cast<SPObject *>(iter->data);
+ g_message(" {%s} [%s]", layer->id, layer->label() );
+ }
+*/
+ deskTrack.setBase(desktop);
+}
+
+
+
+
+
+} //namespace Dialogs
+} //namespace UI
+} //namespace Inkscape
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/ui/dialog/tags.h b/src/ui/dialog/tags.h
new file mode 100644
index 000000000..d35dfba01
--- /dev/null
+++ b/src/ui/dialog/tags.h
@@ -0,0 +1,181 @@
+/*
+ * A simple dialog for tags UI.
+ *
+ * Authors:
+ * Theodore Janeczko
+ *
+ * Copyright (C) Theodore Janeczko 2012 <flutterguy317@gmail.com>
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifndef SEEN_TAGS_PANEL_H
+#define SEEN_TAGS_PANEL_H
+
+#include <gtkmm/box.h>
+#include <gtkmm/treeview.h>
+#include <gtkmm/treestore.h>
+#include <gtkmm/scrolledwindow.h>
+#include <gtkmm/dialog.h>
+#include "ui/widget/spinbutton.h"
+#include "ui/widget/panel.h"
+#include "ui/widget/object-composite-settings.h"
+#include "desktop-tracker.h"
+#include "ui/widget/style-subject.h"
+#include "selection.h"
+#include "ui/widget/filter-effect-chooser.h"
+
+class SPObject;
+class SPTag;
+struct SPColorSelector;
+
+namespace Inkscape {
+
+namespace UI {
+namespace Dialog {
+
+
+/**
+ * A panel that displays layers.
+ */
+class TagsPanel : public UI::Widget::Panel
+{
+public:
+ TagsPanel();
+ virtual ~TagsPanel();
+
+ //virtual void setOrientation( Gtk::AnchorType how );
+
+ static TagsPanel& getInstance();
+
+ void setDesktop( SPDesktop* desktop );
+ void setDocument( SPDesktop* desktop, SPDocument* document);
+
+protected:
+ //virtual void _handleAction( int setId, int itemId );
+ friend void sp_highlight_picker_color_mod(SPColorSelector *csel, GObject *cp);
+private:
+ class ModelColumns;
+ class InternalUIBounce;
+ class ObjectWatcher;
+
+ TagsPanel(TagsPanel const &); // no copy
+ TagsPanel &operator=(TagsPanel const &); // no assign
+
+ void _styleButton( Gtk::Button& btn, SPDesktop *desktop, unsigned int code, char const* iconName, char const* tooltip );
+ void _fireAction( unsigned int code );
+ Gtk::MenuItem& _addPopupItem( SPDesktop *desktop, unsigned int code, char const* iconName, char const* fallback, int id );
+
+ bool _handleButtonEvent(GdkEventButton *event);
+ bool _handleKeyEvent(GdkEventKey *event);
+
+ void _storeDragSource(const Gtk::TreeModel::iterator& iter);
+ bool _handleDragDrop(const Glib::RefPtr<Gdk::DragContext>& context, int x, int y, guint time);
+ void _handleEdited(const Glib::ustring& path, const Glib::ustring& new_text);
+ void _handleEditingCancelled();
+
+ void _doTreeMove();
+ void _renameObject(Gtk::TreeModel::Row row, const Glib::ustring& name);
+
+ void _pushTreeSelectionToCurrent();
+ void _selected_row_callback( const Gtk::TreeModel::iterator& iter );
+ void _select_tag( SPTag * tag );
+
+ void _checkTreeSelection();
+
+ void _takeAction( int val );
+ bool _executeAction();
+
+ void _setExpanded( const Gtk::TreeModel::iterator& iter, const Gtk::TreeModel::Path& path, bool isexpanded );
+
+ bool _noSelection( Glib::RefPtr<Gtk::TreeModel> const & model, Gtk::TreeModel::Path const & path, bool b );
+ bool _rowSelectFunction( Glib::RefPtr<Gtk::TreeModel> const & model, Gtk::TreeModel::Path const & path, bool b );
+
+ void _updateObject(SPObject *obj);
+ bool _checkForUpdated(const Gtk::TreePath &path, const Gtk::TreeIter& iter, SPObject* obj);
+
+ void _objectsSelected(Selection *sel);
+ bool _checkForSelected(const Gtk::TreePath& path, const Gtk::TreeIter& iter, SPObject* layer);
+
+ void _objectsChanged(SPObject *root);
+ void _addObject( SPDocument* doc, SPObject* obj, Gtk::TreeModel::Row* parentRow );
+
+ void _checkForDeleted(const Gtk::TreeIter& iter, std::vector<SPObject *>* todelete);
+
+// std::vector<sigc::connection> groupConnections;
+ TagsPanel::ObjectWatcher* _rootWatcher;
+ std::vector<TagsPanel::ObjectWatcher*> _objectWatchers;
+
+ // Hooked to the layer manager:
+ sigc::connection _documentChangedConnection;
+ sigc::connection _selectionChangedConnection;
+
+ sigc::connection _changedConnection;
+ sigc::connection _addedConnection;
+ sigc::connection _removedConnection;
+
+ // Internal
+ sigc::connection _selectedConnection;
+ sigc::connection _expandedConnection;
+ sigc::connection _collapsedConnection;
+
+ DesktopTracker deskTrack;
+ SPDesktop* _desktop;
+ SPDocument* _document;
+ ModelColumns* _model;
+ InternalUIBounce* _pending;
+ gboolean _dnd_into;
+ std::vector<SPTag*> _dnd_source;
+ SPObject* _dnd_target;
+
+ GdkEvent* _toggleEvent;
+ bool down_at_add;
+
+ Gtk::TreeModel::Path _defer_target;
+
+ Glib::RefPtr<Gtk::TreeStore> _store;
+ std::vector<Gtk::Widget*> _watching;
+ std::vector<Gtk::Widget*> _watchingNonTop;
+ std::vector<Gtk::Widget*> _watchingNonBottom;
+
+ Gtk::TreeView _tree;
+ Gtk::CellRendererText *_text_renderer;
+ Gtk::TreeView::Column *_name_column;
+#if WITH_GTKMM_3_0
+ Gtk::Box _buttonsRow;
+ Gtk::Box _buttonsPrimary;
+ Gtk::Box _buttonsSecondary;
+#else
+ Gtk::HBox _buttonsRow;
+ Gtk::HBox _buttonsPrimary;
+ Gtk::HBox _buttonsSecondary;
+#endif
+ Gtk::ScrolledWindow _scroller;
+ Gtk::Menu _popupMenu;
+ Inkscape::UI::Widget::SpinButton _spinBtn;
+ Gtk::VBox _layersPage;
+
+ sigc::connection desktopChangeConn;
+
+};
+
+
+
+} //namespace Dialogs
+} //namespace UI
+} //namespace Inkscape
+
+
+
+#endif // SEEN_OBJECTS_PANEL_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/ui/dialog/template-load-tab.cpp b/src/ui/dialog/template-load-tab.cpp
index d75f81456..13cb01eef 100644
--- a/src/ui/dialog/template-load-tab.cpp
+++ b/src/ui/dialog/template-load-tab.cpp
@@ -24,7 +24,7 @@
#include "extension/db.h"
#include "extension/effect.h"
#include "inkscape.h"
-#include "interface.h"
+#include "ui/interface.h"
#include "file.h"
#include "path-prefix.h"
#include "preferences.h"
diff --git a/src/ui/dialog/template-widget.cpp b/src/ui/dialog/template-widget.cpp
index ef91962d4..f79d166f2 100644
--- a/src/ui/dialog/template-widget.cpp
+++ b/src/ui/dialog/template-widget.cpp
@@ -24,6 +24,7 @@
#include "document.h"
#include "document-undo.h"
#include "file.h"
+#include "sp-namedview.h"
#include "extension/implementation/implementation.h"
#include "inkscape.h"
@@ -69,7 +70,10 @@ void TemplateWidget::create()
_current_template.tpl_effect->effect(desc);
DocumentUndo::clearUndo(sp_desktop_document(desc));
sp_desktop_document(desc)->setModifiedSinceSave(false);
-
+
+ // Apply cx,cy etc. from document
+ sp_namedview_window_from_document( desc );
+
if (desktop)
desktop->clearWaitingCursor();
}
@@ -120,7 +124,7 @@ void TemplateWidget::_displayTemplateDetails()
if (_current_template.long_description != "")
message += _("Description: ") + _current_template.long_description + "\n\n";
- if (~_current_template.keywords.empty()){
+ if (!_current_template.keywords.empty()){
message += _("Keywords: ");
for (std::set<Glib::ustring>::iterator it = _current_template.keywords.begin(); it != _current_template.keywords.end(); ++it)
message += *it + " ";
diff --git a/src/ui/dialog/text-edit.cpp b/src/ui/dialog/text-edit.cpp
index 17c29c69f..0f4a6f7f1 100644
--- a/src/ui/dialog/text-edit.cpp
+++ b/src/ui/dialog/text-edit.cpp
@@ -32,7 +32,6 @@ extern "C" {
#include <gtkmm/stock.h>
#include <libnrtype/font-instance.h>
-#include <libnrtype/font-style-to-pos.h>
#include <libnrtype/font-lister.h>
#include <xml/repr.h>
@@ -52,7 +51,7 @@ extern "C" {
#include "ui/icon-names.h"
#include "preferences.h"
#include "verbs.h"
-#include "interface.h"
+#include "ui/interface.h"
#include "svg/css-ostringstream.h"
#include "widgets/icon.h"
#include "widgets/font-selector.h"
@@ -344,9 +343,9 @@ void TextEdit::onReadSelection ( gboolean dostyle, gboolean /*docontent*/ )
Inkscape::FontLister* fontlister = Inkscape::FontLister::get_instance();
- // This is done for us by text-toolbar. No need to do it twice.
- // fontlister->update_font_list( sp_desktop_document( SP_ACTIVE_DESKTOP ));
- // fontlister->selection_update();
+ // This is normally done for us by text-toolbar but only when we are in text editing context
+ fontlister->update_font_list(sp_desktop_document(this->desktop));
+ fontlister->selection_update();
Glib::ustring fontspec = fontlister->get_fontspec();
@@ -404,12 +403,12 @@ void TextEdit::setPreviewText (Glib::ustring font_spec, Glib::ustring phrase)
double pt_size = Inkscape::Util::Quantity::convert(sp_style_css_size_units_to_px(sp_font_selector_get_size(fsel), unit), "px", "pt");
// Pango font size is in 1024ths of a point
- // C++11: Glib::ustring size = std::to_string( pt_size * PANGO_SCALE );
+ // C++11: Glib::ustring size = std::to_string( int(pt_size * PANGO_SCALE) );
std::ostringstream size_st;
- size_st << pt_size * PANGO_SCALE;
+ size_st << int(pt_size * PANGO_SCALE); // Markup code expects integers
- Glib::ustring markup = "<span font=\"" + font_spec +
- "\" size=\"" + size_st.str() + "\">" + phrase_escaped + "</span>";
+ Glib::ustring markup = "<span font=\'" + font_spec +
+ "\' size=\'" + size_st.str() + "\'>" + phrase_escaped + "</span>";
preview_label.set_markup(markup.c_str());
}
diff --git a/src/ui/dialog/transformation.cpp b/src/ui/dialog/transformation.cpp
index a7f0b068e..3e135b9b2 100644
--- a/src/ui/dialog/transformation.cpp
+++ b/src/ui/dialog/transformation.cpp
@@ -47,13 +47,13 @@ namespace Inkscape {
namespace UI {
namespace Dialog {
-static void on_selection_changed(Inkscape::Application */*inkscape*/, Inkscape::Selection *selection, Transformation *daad)
+static void on_selection_changed(InkscapeApplication */*inkscape*/, Inkscape::Selection *selection, Transformation *daad)
{
int page = daad->getCurrentPage();
daad->updateSelection((Inkscape::UI::Dialog::Transformation::PageType)page, selection);
}
-static void on_selection_modified( Inkscape::Application */*inkscape*/,
+static void on_selection_modified( InkscapeApplication */*inkscape*/,
Inkscape::Selection *selection,
guint /*flags*/,
Transformation *daad )
diff --git a/src/ui/dialog/xml-tree.cpp b/src/ui/dialog/xml-tree.cpp
index 55d0aff09..7ab6c78ba 100644
--- a/src/ui/dialog/xml-tree.cpp
+++ b/src/ui/dialog/xml-tree.cpp
@@ -24,13 +24,13 @@
#include "desktop.h"
#include "desktop-handles.h"
-#include "dialogs/dialog-events.h"
+#include "ui/dialog-events.h"
#include "document.h"
#include "document-undo.h"
#include "ui/tools/tool-base.h"
#include "helper/window.h"
#include "inkscape.h"
-#include "interface.h"
+#include "ui/interface.h"
#include "macros.h"
#include "message-context.h"
#include "message-stack.h"
@@ -1033,6 +1033,7 @@ void XmlTree::cmd_set_attr()
updated->updateRepr();
}
+ reinterpret_cast<SPObject *>(current_desktop->currentLayer())->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
DocumentUndo::done(current_document, SP_VERB_DIALOG_XML_EDITOR,
_("Change attribute"));
diff --git a/src/draw-anchor.cpp b/src/ui/draw-anchor.cpp
index 00db936e1..84c919018 100644
--- a/src/draw-anchor.cpp
+++ b/src/ui/draw-anchor.cpp
@@ -13,7 +13,7 @@
*/
-#include "draw-anchor.h"
+#include "ui/draw-anchor.h"
#include "desktop.h"
#include "desktop-handles.h"
#include "ui/tools/tool-base.h"
@@ -30,7 +30,7 @@ using Inkscape::ControlManager;
/**
* Creates an anchor object and initializes it.
*/
-SPDrawAnchor *sp_draw_anchor_new(Inkscape::UI::Tools::FreehandBase *dc, SPCurve *curve, gboolean start, Geom::Point delta)
+SPDrawAnchor *sp_draw_anchor_new(Inkscape::UI::Tools::FreehandBase *dc, SPCurve *curve, bool start, Geom::Point delta)
{
if (SP_IS_LPETOOL_CONTEXT(dc)) {
// suppress all kinds of anchors in LPEToolContext
@@ -73,7 +73,7 @@ SPDrawAnchor *sp_draw_anchor_destroy(SPDrawAnchor *anchor)
* Test if point is near anchor, if so fill anchor on canvas and return
* pointer to it or NULL.
*/
-SPDrawAnchor *sp_draw_anchor_test(SPDrawAnchor *anchor, Geom::Point w, gboolean activate)
+SPDrawAnchor *sp_draw_anchor_test(SPDrawAnchor *anchor, Geom::Point w, bool activate)
{
SPCtrl *ctrl = SP_CTRL(anchor->ctrl);
diff --git a/src/draw-anchor.h b/src/ui/draw-anchor.h
index e7b252186..1f7b55920 100644
--- a/src/draw-anchor.h
+++ b/src/ui/draw-anchor.h
@@ -5,7 +5,6 @@
* Drawing anchors.
*/
-#include <glib.h>
#include <2geom/point.h>
namespace Inkscape {
@@ -26,17 +25,17 @@ struct SPCanvasItem;
struct SPDrawAnchor {
Inkscape::UI::Tools::FreehandBase *dc;
SPCurve *curve;
- guint start : 1;
- guint active : 1;
+ unsigned int start : 1;
+ unsigned int active : 1;
Geom::Point dp;
SPCanvasItem *ctrl;
};
-SPDrawAnchor *sp_draw_anchor_new(Inkscape::UI::Tools::FreehandBase *dc, SPCurve *curve, gboolean start,
+SPDrawAnchor *sp_draw_anchor_new(Inkscape::UI::Tools::FreehandBase *dc, SPCurve *curve, bool start,
Geom::Point delta);
SPDrawAnchor *sp_draw_anchor_destroy(SPDrawAnchor *anchor);
-SPDrawAnchor *sp_draw_anchor_test(SPDrawAnchor *anchor, Geom::Point w, gboolean activate);
+SPDrawAnchor *sp_draw_anchor_test(SPDrawAnchor *anchor, Geom::Point w, bool activate);
#endif /* !SEEN_DRAW_ANCHOR_H */
diff --git a/src/interface.cpp b/src/ui/interface.cpp
index 1cbeb44a3..7830a8de1 100644
--- a/src/interface.cpp
+++ b/src/ui/interface.cpp
@@ -39,7 +39,7 @@
#include "shortcuts.h"
#include "document.h"
#include "desktop-handles.h"
-#include "interface.h"
+#include "ui/interface.h"
#include "desktop.h"
#include "selection.h"
#include "selection-chemistry.h"
@@ -57,7 +57,7 @@
#include "helper/gnome-utils.h"
#include "helper/window.h"
#include "io/sys.h"
-#include "dialogs/dialog-events.h"
+#include "ui/dialog-events.h"
#include "message-context.h"
#include "ui/uxmanager.h"
#include "ui/clipboard.h"
@@ -149,7 +149,7 @@ static void injectRenamedIcons();
static const int MIN_ONSCREEN_DISTANCE = 50;
void
-sp_create_window(SPViewWidget *vw, gboolean editable)
+sp_create_window(SPViewWidget *vw, bool editable)
{
g_return_if_fail(vw != NULL);
g_return_if_fail(SP_IS_VIEW_WIDGET(vw));
@@ -1756,6 +1756,13 @@ void ContextMenu::MakeItemMenu (void)
}
mi->show();
append(*mi);
+
+ /*SSet Clip Group */
+ mi = Gtk::manage(new Gtk::MenuItem(_("Create Clip G_roup"),1));
+ mi->signal_activate().connect(sigc::mem_fun(*this, &ContextMenu::CreateGroupClip));
+ mi->set_sensitive(TRUE);
+ mi->show();
+ append(*mi);
/* Set Clip */
mi = Gtk::manage(new Gtk::MenuItem(_("Set Cl_ip"), 1));
@@ -1867,6 +1874,10 @@ void ContextMenu::ReleaseMask(void)
sp_selection_unset_mask(_desktop, false);
}
+void ContextMenu::CreateGroupClip(void)
+{
+ sp_selection_set_clipgroup(_desktop);
+}
void ContextMenu::SetClip(void)
{
diff --git a/src/interface.h b/src/ui/interface.h
index 215a3bfc9..6fb74046f 100644
--- a/src/interface.h
+++ b/src/ui/interface.h
@@ -17,13 +17,9 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#if GLIBMM_DISABLE_DEPRECATED && HAVE_GLIBMM_THREADS_H
-#include <glibmm/threads.h>
-#endif
+//#ifdef HAVE_CONFIG_H
+//# include <config.h>
+//#endif
#include <gtkmm/menu.h>
@@ -50,7 +46,7 @@ class View;
/**
* Create a new document window.
*/
-void sp_create_window (SPViewWidget *vw, gboolean editable);
+void sp_create_window (SPViewWidget *vw, bool editable);
/**
* \param widget unused
@@ -87,15 +83,15 @@ unsigned int sp_ui_close_all (void);
GtkWidget *sp_ui_main_menubar (Inkscape::UI::View::View *view);
void sp_menu_append_recent_documents (GtkWidget *menu);
-void sp_ui_dialog_title_string (Inkscape::Verb * verb, gchar* c);
+void sp_ui_dialog_title_string (Inkscape::Verb * verb, char* c);
Glib::ustring getLayoutPrefPath( Inkscape::UI::View::View *view );
/**
*
*/
-void sp_ui_error_dialog (const gchar * message);
-bool sp_ui_overwrite_file (const gchar * filename);
+void sp_ui_error_dialog (char const* message);
+bool sp_ui_overwrite_file (char const* filename);
/**
@@ -187,6 +183,7 @@ class ContextMenu : public Gtk::Menu
void SelectSameStrokeStyle(void);
void SelectSameObjectType(void);
void ItemCreateLink(void);
+ void CreateGroupClip(void);
void SetMask(void);
void ReleaseMask(void);
void SetClip(void);
diff --git a/src/object-edit.cpp b/src/ui/object-edit.cpp
index e9b183eca..ca550502d 100644
--- a/src/object-edit.cpp
+++ b/src/ui/object-edit.cpp
@@ -6,6 +6,7 @@
* Mitsuru Oka
* Maximilian Albert <maximilian.albert@gmail.com>
* Abhishek Sharma
+ * Jon A. Cruz <jon@joncruz.org>
*
* Licensed under GNU GPL
*/
@@ -33,7 +34,7 @@
#include "sp-pattern.h"
#include "sp-path.h"
#include <glibmm/i18n.h>
-#include "object-edit.h"
+#include "ui/object-edit.h"
#include "xml/repr.h"
#include <2geom/math-utils.h>
#include "knot-holder-entity.h"
@@ -42,11 +43,11 @@
namespace {
-static KnotHolder *sp_lpe_knot_holder(SPItem *item, SPDesktop *desktop)
+static KnotHolder *sp_lpe_knot_holder(SPLPEItem *item, SPDesktop *desktop)
{
KnotHolder *knot_holder = new KnotHolder(desktop, item, NULL);
- Inkscape::LivePathEffect::Effect *effect = SP_LPE_ITEM(item)->getCurrentLPE();
+ Inkscape::LivePathEffect::Effect *effect = item->getCurrentLPE();
effect->addHandles(knot_holder, desktop, item);
return knot_holder;
@@ -55,40 +56,46 @@ static KnotHolder *sp_lpe_knot_holder(SPItem *item, SPDesktop *desktop)
} // namespace
namespace Inkscape {
+namespace UI {
KnotHolder *createKnotHolder(SPItem *item, SPDesktop *desktop)
{
KnotHolder *knotholder = NULL;
- if (SP_IS_LPE_ITEM(item) &&
- SP_LPE_ITEM(item)->getCurrentLPE() &&
- SP_LPE_ITEM(item)->getCurrentLPE()->isVisible() &&
- SP_LPE_ITEM(item)->getCurrentLPE()->providesKnotholder()) {
- knotholder = sp_lpe_knot_holder(item, desktop);
- } else if (SP_IS_RECT(item)) {
+ SPLPEItem *lpe = dynamic_cast<SPLPEItem *>(item);
+ if (lpe &&
+ lpe->getCurrentLPE() &&
+ lpe->getCurrentLPE()->isVisible() &&
+ lpe->getCurrentLPE()->providesKnotholder()) {
+ knotholder = sp_lpe_knot_holder(lpe, desktop);
+ } else if (dynamic_cast<SPRect *>(item)) {
knotholder = new RectKnotHolder(desktop, item, NULL);
- } else if (SP_IS_BOX3D(item)) {
+ } else if (dynamic_cast<SPBox3D *>(item)) {
knotholder = new Box3DKnotHolder(desktop, item, NULL);
- } else if (SP_IS_GENERICELLIPSE(item)) {
+ } else if (dynamic_cast<SPGenericEllipse *>(item)) {
knotholder = new ArcKnotHolder(desktop, item, NULL);
- } else if (SP_IS_STAR(item)) {
+ } else if (dynamic_cast<SPStar *>(item)) {
knotholder = new StarKnotHolder(desktop, item, NULL);
- } else if (SP_IS_SPIRAL(item)) {
+ } else if (dynamic_cast<SPSpiral *>(item)) {
knotholder = new SpiralKnotHolder(desktop, item, NULL);
- } else if (SP_IS_OFFSET(item)) {
+ } else if (dynamic_cast<SPOffset *>(item)) {
knotholder = new OffsetKnotHolder(desktop, item, NULL);
- } else if (SP_IS_FLOWTEXT(item) && SP_FLOWTEXT(item)->has_internal_frame()) {
- knotholder = new FlowtextKnotHolder(desktop, SP_FLOWTEXT(item)->get_frame(NULL), NULL);
- } else if ((item->style->fill.isPaintserver())
- && SP_IS_PATTERN(item->style->getFillPaintServer())) {
- knotholder = new KnotHolder(desktop, item, NULL);
- knotholder->add_pattern_knotholder();
+ } else {
+ SPFlowtext *flowtext = dynamic_cast<SPFlowtext *>(item);
+ if (flowtext && flowtext->has_internal_frame()) {
+ knotholder = new FlowtextKnotHolder(desktop, flowtext->get_frame(NULL), NULL);
+ } else if ((item->style->fill.isPaintserver() && dynamic_cast<SPPattern *>(item->style->getFillPaintServer())) ||
+ (item->style->stroke.isPaintserver() && dynamic_cast<SPPattern *>(item->style->getStrokePaintServer()))) {
+ knotholder = new KnotHolder(desktop, item, NULL);
+ knotholder->add_pattern_knotholder();
+ }
}
return knotholder;
}
-} // Inkscape
+}
+} // namespace Inkscape
/* SPRect */
@@ -96,47 +103,49 @@ KnotHolder *createKnotHolder(SPItem *item, SPDesktop *desktop)
class RectKnotHolderEntityRX : public KnotHolderEntity {
public:
virtual Geom::Point knot_get() const;
- virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state);
- virtual void knot_click(guint state);
+ virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state);
+ virtual void knot_click(unsigned int state);
};
/* handle for vertical rounding radius */
class RectKnotHolderEntityRY : public KnotHolderEntity {
public:
virtual Geom::Point knot_get() const;
- virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state);
- virtual void knot_click(guint state);
+ virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state);
+ virtual void knot_click(unsigned int state);
};
/* handle for width/height adjustment */
class RectKnotHolderEntityWH : public KnotHolderEntity {
public:
virtual Geom::Point knot_get() const;
- virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state);
+ virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state);
protected:
- void set_internal(Geom::Point const &p, Geom::Point const &origin, guint state);
+ void set_internal(Geom::Point const &p, Geom::Point const &origin, unsigned int state);
};
/* handle for x/y adjustment */
class RectKnotHolderEntityXY : public KnotHolderEntity {
public:
virtual Geom::Point knot_get() const;
- virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state);
+ virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state);
};
Geom::Point
RectKnotHolderEntityRX::knot_get() const
{
- SPRect *rect = SP_RECT(item);
+ SPRect *rect = dynamic_cast<SPRect *>(item);
+ g_assert(rect != NULL);
return Geom::Point(rect->x.computed + rect->width.computed - rect->rx.computed, rect->y.computed);
}
void
-RectKnotHolderEntityRX::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, guint state)
+RectKnotHolderEntityRX::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, unsigned int state)
{
- SPRect *rect = SP_RECT(item);
+ SPRect *rect = dynamic_cast<SPRect *>(item);
+ g_assert(rect != NULL);
//In general we cannot just snap this radius to an arbitrary point, as we have only a single
//degree of freedom. For snapping to an arbitrary point we need two DOF. If we're going to snap
@@ -155,13 +164,14 @@ RectKnotHolderEntityRX::knot_set(Geom::Point const &p, Geom::Point const &/*orig
update_knot();
- (static_cast<SPObject*>(rect))->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+ rect->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
}
void
-RectKnotHolderEntityRX::knot_click(guint state)
+RectKnotHolderEntityRX::knot_click(unsigned int state)
{
- SPRect *rect = SP_RECT(item);
+ SPRect *rect = dynamic_cast<SPRect *>(item);
+ g_assert(rect != NULL);
if (state & GDK_SHIFT_MASK) {
/* remove rounding from rectangle */
@@ -177,15 +187,17 @@ RectKnotHolderEntityRX::knot_click(guint state)
Geom::Point
RectKnotHolderEntityRY::knot_get() const
{
- SPRect *rect = SP_RECT(item);
+ SPRect *rect = dynamic_cast<SPRect *>(item);
+ g_assert(rect != NULL);
return Geom::Point(rect->x.computed + rect->width.computed, rect->y.computed + rect->ry.computed);
}
void
-RectKnotHolderEntityRY::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, guint state)
+RectKnotHolderEntityRY::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, unsigned int state)
{
- SPRect *rect = SP_RECT(item);
+ SPRect *rect = dynamic_cast<SPRect *>(item);
+ g_assert(rect != NULL);
//In general we cannot just snap this radius to an arbitrary point, as we have only a single
//degree of freedom. For snapping to an arbitrary point we need two DOF. If we're going to snap
@@ -213,13 +225,14 @@ RectKnotHolderEntityRY::knot_set(Geom::Point const &p, Geom::Point const &/*orig
update_knot();
- (static_cast<SPObject *>(rect))->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+ rect->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
}
void
-RectKnotHolderEntityRY::knot_click(guint state)
+RectKnotHolderEntityRY::knot_click(unsigned int state)
{
- SPRect *rect = SP_RECT(item);
+ SPRect *rect = dynamic_cast<SPRect *>(item);
+ g_assert(rect != NULL);
if (state & GDK_SHIFT_MASK) {
/* remove rounding */
@@ -249,15 +262,17 @@ static void sp_rect_clamp_radii(SPRect *rect)
Geom::Point
RectKnotHolderEntityWH::knot_get() const
{
- SPRect *rect = SP_RECT(item);
+ SPRect *rect = dynamic_cast<SPRect *>(item);
+ g_assert(rect != NULL);
return Geom::Point(rect->x.computed + rect->width.computed, rect->y.computed + rect->height.computed);
}
void
-RectKnotHolderEntityWH::set_internal(Geom::Point const &p, Geom::Point const &origin, guint state)
+RectKnotHolderEntityWH::set_internal(Geom::Point const &p, Geom::Point const &origin, unsigned int state)
{
- SPRect *rect = SP_RECT(item);
+ SPRect *rect = dynamic_cast<SPRect *>(item);
+ g_assert(rect != NULL);
Geom::Point s = p;
@@ -323,11 +338,11 @@ RectKnotHolderEntityWH::set_internal(Geom::Point const &p, Geom::Point const &or
sp_rect_clamp_radii(rect);
- (static_cast<SPObject *>(rect))->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+ rect->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
}
void
-RectKnotHolderEntityWH::knot_set(Geom::Point const &p, Geom::Point const &origin, guint state)
+RectKnotHolderEntityWH::knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state)
{
set_internal(p, origin, state);
update_knot();
@@ -336,15 +351,17 @@ RectKnotHolderEntityWH::knot_set(Geom::Point const &p, Geom::Point const &origin
Geom::Point
RectKnotHolderEntityXY::knot_get() const
{
- SPRect *rect = SP_RECT(item);
+ SPRect *rect = dynamic_cast<SPRect *>(item);
+ g_assert(rect != NULL);
return Geom::Point(rect->x.computed, rect->y.computed);
}
void
-RectKnotHolderEntityXY::knot_set(Geom::Point const &p, Geom::Point const &origin, guint state)
+RectKnotHolderEntityXY::knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state)
{
- SPRect *rect = SP_RECT(item);
+ SPRect *rect = dynamic_cast<SPRect *>(item);
+ g_assert(rect != NULL);
// opposite corner (unmoved)
gdouble opposite_x = (rect->x.computed + rect->width.computed);
@@ -424,7 +441,7 @@ RectKnotHolderEntityXY::knot_set(Geom::Point const &p, Geom::Point const &origin
update_knot();
- (static_cast<SPObject *>(rect))->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+ rect->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
}
RectKnotHolder::RectKnotHolder(SPDesktop *desktop, SPItem *item, SPKnotHolderReleasedFunc relhandler) :
@@ -468,25 +485,31 @@ RectKnotHolder::RectKnotHolder(SPDesktop *desktop, SPItem *item, SPKnotHolderRel
class Box3DKnotHolderEntity : public KnotHolderEntity {
public:
virtual Geom::Point knot_get() const = 0;
- virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state) = 0;
+ virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state) = 0;
Geom::Point knot_get_generic(SPItem *item, unsigned int knot_id) const;
- void knot_set_generic(SPItem *item, unsigned int knot_id, Geom::Point const &p, guint state);
+ void knot_set_generic(SPItem *item, unsigned int knot_id, Geom::Point const &p, unsigned int state);
};
Geom::Point
Box3DKnotHolderEntity::knot_get_generic(SPItem *item, unsigned int knot_id) const
{
- return box3d_get_corner_screen(SP_BOX3D(item), knot_id);
+ SPBox3D *box = dynamic_cast<SPBox3D *>(item);
+ if (box) {
+ return box3d_get_corner_screen(box, knot_id);
+ } else {
+ return Geom::Point(); // TODO investigate proper fallback
+ }
}
void
-Box3DKnotHolderEntity::knot_set_generic(SPItem *item, unsigned int knot_id, Geom::Point const &new_pos, guint state)
+Box3DKnotHolderEntity::knot_set_generic(SPItem *item, unsigned int knot_id, Geom::Point const &new_pos, unsigned int state)
{
Geom::Point const s = snap_knot_position(new_pos, state);
g_assert(item != NULL);
- SPBox3D *box = SP_BOX3D(item);
+ SPBox3D *box = dynamic_cast<SPBox3D *>(item);
+ g_assert(box != NULL);
Geom::Affine const i2dt (item->i2dt_affine ());
Box3D::Axis movement;
@@ -504,55 +527,55 @@ Box3DKnotHolderEntity::knot_set_generic(SPItem *item, unsigned int knot_id, Geom
class Box3DKnotHolderEntity0 : public Box3DKnotHolderEntity {
public:
virtual Geom::Point knot_get() const;
- virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state);
+ virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state);
};
class Box3DKnotHolderEntity1 : public Box3DKnotHolderEntity {
public:
virtual Geom::Point knot_get() const;
- virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state);
+ virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state);
};
class Box3DKnotHolderEntity2 : public Box3DKnotHolderEntity {
public:
virtual Geom::Point knot_get() const;
- virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state);
+ virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state);
};
class Box3DKnotHolderEntity3 : public Box3DKnotHolderEntity {
public:
virtual Geom::Point knot_get() const;
- virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state);
+ virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state);
};
class Box3DKnotHolderEntity4 : public Box3DKnotHolderEntity {
public:
virtual Geom::Point knot_get() const;
- virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state);
+ virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state);
};
class Box3DKnotHolderEntity5 : public Box3DKnotHolderEntity {
public:
virtual Geom::Point knot_get() const;
- virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state);
+ virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state);
};
class Box3DKnotHolderEntity6 : public Box3DKnotHolderEntity {
public:
virtual Geom::Point knot_get() const;
- virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state);
+ virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state);
};
class Box3DKnotHolderEntity7 : public Box3DKnotHolderEntity {
public:
virtual Geom::Point knot_get() const;
- virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state);
+ virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state);
};
class Box3DKnotHolderEntityCenter : public KnotHolderEntity {
public:
virtual Geom::Point knot_get() const;
- virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state);
+ virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state);
};
Geom::Point
@@ -606,66 +629,72 @@ Box3DKnotHolderEntity7::knot_get() const
Geom::Point
Box3DKnotHolderEntityCenter::knot_get() const
{
- return box3d_get_center_screen(SP_BOX3D(item));
+ SPBox3D *box = dynamic_cast<SPBox3D *>(item);
+ if (box) {
+ return box3d_get_center_screen(box);
+ } else {
+ return Geom::Point(); // TODO investigate proper fallback
+ }
}
void
-Box3DKnotHolderEntity0::knot_set(Geom::Point const &new_pos, Geom::Point const &/*origin*/, guint state)
+Box3DKnotHolderEntity0::knot_set(Geom::Point const &new_pos, Geom::Point const &/*origin*/, unsigned int state)
{
knot_set_generic(item, 0, new_pos, state);
}
void
-Box3DKnotHolderEntity1::knot_set(Geom::Point const &new_pos, Geom::Point const &/*origin*/, guint state)
+Box3DKnotHolderEntity1::knot_set(Geom::Point const &new_pos, Geom::Point const &/*origin*/, unsigned int state)
{
knot_set_generic(item, 1, new_pos, state);
}
void
-Box3DKnotHolderEntity2::knot_set(Geom::Point const &new_pos, Geom::Point const &/*origin*/, guint state)
+Box3DKnotHolderEntity2::knot_set(Geom::Point const &new_pos, Geom::Point const &/*origin*/, unsigned int state)
{
knot_set_generic(item, 2, new_pos, state);
}
void
-Box3DKnotHolderEntity3::knot_set(Geom::Point const &new_pos, Geom::Point const &/*origin*/, guint state)
+Box3DKnotHolderEntity3::knot_set(Geom::Point const &new_pos, Geom::Point const &/*origin*/, unsigned int state)
{
knot_set_generic(item, 3, new_pos, state);
}
void
-Box3DKnotHolderEntity4::knot_set(Geom::Point const &new_pos, Geom::Point const &/*origin*/, guint state)
+Box3DKnotHolderEntity4::knot_set(Geom::Point const &new_pos, Geom::Point const &/*origin*/, unsigned int state)
{
knot_set_generic(item, 4, new_pos, state);
}
void
-Box3DKnotHolderEntity5::knot_set(Geom::Point const &new_pos, Geom::Point const &/*origin*/, guint state)
+Box3DKnotHolderEntity5::knot_set(Geom::Point const &new_pos, Geom::Point const &/*origin*/, unsigned int state)
{
knot_set_generic(item, 5, new_pos, state);
}
void
-Box3DKnotHolderEntity6::knot_set(Geom::Point const &new_pos, Geom::Point const &/*origin*/, guint state)
+Box3DKnotHolderEntity6::knot_set(Geom::Point const &new_pos, Geom::Point const &/*origin*/, unsigned int state)
{
knot_set_generic(item, 6, new_pos, state);
}
void
-Box3DKnotHolderEntity7::knot_set(Geom::Point const &new_pos, Geom::Point const &/*origin*/, guint state)
+Box3DKnotHolderEntity7::knot_set(Geom::Point const &new_pos, Geom::Point const &/*origin*/, unsigned int state)
{
knot_set_generic(item, 7, new_pos, state);
}
void
-Box3DKnotHolderEntityCenter::knot_set(Geom::Point const &new_pos, Geom::Point const &origin, guint state)
+Box3DKnotHolderEntityCenter::knot_set(Geom::Point const &new_pos, Geom::Point const &origin, unsigned int state)
{
Geom::Point const s = snap_knot_position(new_pos, state);
- SPBox3D *box = SP_BOX3D(item);
+ SPBox3D *box = dynamic_cast<SPBox3D *>(item);
+ g_assert(box != NULL);
Geom::Affine const i2dt (item->i2dt_affine ());
- box3d_set_center (SP_BOX3D(item), s * i2dt, origin * i2dt, !(state & GDK_SHIFT_MASK) ? Box3D::XY : Box3D::Z,
+ box3d_set_center(box, s * i2dt, origin * i2dt, !(state & GDK_SHIFT_MASK) ? Box3D::XY : Box3D::Z,
state & GDK_CONTROL_MASK);
box3d_set_z_orders(box);
@@ -739,29 +768,29 @@ Box3DKnotHolder::Box3DKnotHolder(SPDesktop *desktop, SPItem *item, SPKnotHolderR
class ArcKnotHolderEntityStart : public KnotHolderEntity {
public:
virtual Geom::Point knot_get() const;
- virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state);
- virtual void knot_click(guint state);
+ virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state);
+ virtual void knot_click(unsigned int state);
};
class ArcKnotHolderEntityEnd : public KnotHolderEntity {
public:
virtual Geom::Point knot_get() const;
- virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state);
- virtual void knot_click(guint state);
+ virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state);
+ virtual void knot_click(unsigned int state);
};
class ArcKnotHolderEntityRX : public KnotHolderEntity {
public:
virtual Geom::Point knot_get() const;
- virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state);
- virtual void knot_click(guint state);
+ virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state);
+ virtual void knot_click(unsigned int state);
};
class ArcKnotHolderEntityRY : public KnotHolderEntity {
public:
virtual Geom::Point knot_get() const;
- virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state);
- virtual void knot_click(guint state);
+ virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state);
+ virtual void knot_click(unsigned int state);
};
/*
@@ -783,11 +812,12 @@ sp_genericellipse_side(SPGenericEllipse *ellipse, Geom::Point const &p)
}
void
-ArcKnotHolderEntityStart::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, guint state)
+ArcKnotHolderEntityStart::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, unsigned int state)
{
int snaps = Inkscape::Preferences::get()->getInt("/options/rotationsnapsperpi/value", 12);
- SPGenericEllipse *arc = SP_GENERICELLIPSE(item);
+ SPGenericEllipse *arc = dynamic_cast<SPGenericEllipse *>(item);
+ g_assert(arc != NULL);
arc->setClosed(sp_genericellipse_side(arc, p) == -1);
@@ -807,28 +837,31 @@ ArcKnotHolderEntityStart::knot_set(Geom::Point const &p, Geom::Point const &/*or
Geom::Point
ArcKnotHolderEntityStart::knot_get() const
{
- SPGenericEllipse const *ge = SP_GENERICELLIPSE(item);
+ SPGenericEllipse const *ge = dynamic_cast<SPGenericEllipse const *>(item);
+ g_assert(ge != NULL);
return ge->getPointAtAngle(ge->start);
}
void
-ArcKnotHolderEntityStart::knot_click(guint state)
+ArcKnotHolderEntityStart::knot_click(unsigned int state)
{
- SPGenericEllipse *ge = SP_GENERICELLIPSE(item);
+ SPGenericEllipse *ge = dynamic_cast<SPGenericEllipse *>(item);
+ g_assert(ge != NULL);
if (state & GDK_SHIFT_MASK) {
ge->end = ge->start = 0;
- (static_cast<SPObject *>(ge))->updateRepr();
+ ge->updateRepr();
}
}
void
-ArcKnotHolderEntityEnd::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, guint state)
+ArcKnotHolderEntityEnd::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, unsigned int state)
{
int snaps = Inkscape::Preferences::get()->getInt("/options/rotationsnapsperpi/value", 12);
- SPGenericEllipse *arc = SP_GENERICELLIPSE(item);
+ SPGenericEllipse *arc = dynamic_cast<SPGenericEllipse *>(item);
+ g_assert(arc != NULL);
arc->setClosed(sp_genericellipse_side(arc, p) == -1);
@@ -848,28 +881,31 @@ ArcKnotHolderEntityEnd::knot_set(Geom::Point const &p, Geom::Point const &/*orig
Geom::Point
ArcKnotHolderEntityEnd::knot_get() const
{
- SPGenericEllipse const *ge = SP_GENERICELLIPSE(item);
+ SPGenericEllipse const *ge = dynamic_cast<SPGenericEllipse const *>(item);
+ g_assert(ge != NULL);
return ge->getPointAtAngle(ge->end);
}
void
-ArcKnotHolderEntityEnd::knot_click(guint state)
+ArcKnotHolderEntityEnd::knot_click(unsigned int state)
{
- SPGenericEllipse *ge = SP_GENERICELLIPSE(item);
+ SPGenericEllipse *ge = dynamic_cast<SPGenericEllipse *>(item);
+ g_assert(ge != NULL);
if (state & GDK_SHIFT_MASK) {
ge->end = ge->start = 0;
- (static_cast<SPObject *>(ge))->updateRepr();
+ ge->updateRepr();
}
}
void
-ArcKnotHolderEntityRX::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, guint state)
+ArcKnotHolderEntityRX::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, unsigned int state)
{
- SPGenericEllipse *ge = SP_GENERICELLIPSE(item);
+ SPGenericEllipse *ge = dynamic_cast<SPGenericEllipse *>(item);
+ g_assert(ge != NULL);
Geom::Point const s = snap_knot_position(p, state);
@@ -879,32 +915,35 @@ ArcKnotHolderEntityRX::knot_set(Geom::Point const &p, Geom::Point const &/*origi
ge->ry.computed = ge->rx.computed;
}
- (static_cast<SPObject *>(item))->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+ item->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
}
Geom::Point
ArcKnotHolderEntityRX::knot_get() const
{
- SPGenericEllipse const *ge = SP_GENERICELLIPSE(item);
+ SPGenericEllipse const *ge = dynamic_cast<SPGenericEllipse const *>(item);
+ g_assert(ge != NULL);
return (Geom::Point(ge->cx.computed, ge->cy.computed) - Geom::Point(ge->rx.computed, 0));
}
void
-ArcKnotHolderEntityRX::knot_click(guint state)
+ArcKnotHolderEntityRX::knot_click(unsigned int state)
{
- SPGenericEllipse *ge = SP_GENERICELLIPSE(item);
+ SPGenericEllipse *ge = dynamic_cast<SPGenericEllipse *>(item);
+ g_assert(ge != NULL);
if (state & GDK_CONTROL_MASK) {
ge->ry.computed = ge->rx.computed;
- (static_cast<SPObject *>(ge))->updateRepr();
+ ge->updateRepr();
}
}
void
-ArcKnotHolderEntityRY::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, guint state)
+ArcKnotHolderEntityRY::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, unsigned int state)
{
- SPGenericEllipse *ge = SP_GENERICELLIPSE(item);
+ SPGenericEllipse *ge = dynamic_cast<SPGenericEllipse *>(item);
+ g_assert(ge != NULL);
Geom::Point const s = snap_knot_position(p, state);
@@ -914,25 +953,27 @@ ArcKnotHolderEntityRY::knot_set(Geom::Point const &p, Geom::Point const &/*origi
ge->rx.computed = ge->ry.computed;
}
- (static_cast<SPObject *>(item))->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+ item->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
}
Geom::Point
ArcKnotHolderEntityRY::knot_get() const
{
- SPGenericEllipse const *ge = SP_GENERICELLIPSE(item);
+ SPGenericEllipse const *ge = dynamic_cast<SPGenericEllipse *>(item);
+ g_assert(ge != NULL);
return (Geom::Point(ge->cx.computed, ge->cy.computed) - Geom::Point(0, ge->ry.computed));
}
void
-ArcKnotHolderEntityRY::knot_click(guint state)
+ArcKnotHolderEntityRY::knot_click(unsigned int state)
{
- SPGenericEllipse *ge = SP_GENERICELLIPSE(item);
+ SPGenericEllipse *ge = dynamic_cast<SPGenericEllipse *>(item);
+ g_assert(ge != NULL);
if (state & GDK_CONTROL_MASK) {
ge->rx.computed = ge->ry.computed;
- (static_cast<SPObject *>(ge))->updateRepr();
+ ge->updateRepr();
}
}
@@ -975,21 +1016,22 @@ ArcKnotHolder::ArcKnotHolder(SPDesktop *desktop, SPItem *item, SPKnotHolderRelea
class StarKnotHolderEntity1 : public KnotHolderEntity {
public:
virtual Geom::Point knot_get() const;
- virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state);
- virtual void knot_click(guint state);
+ virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state);
+ virtual void knot_click(unsigned int state);
};
class StarKnotHolderEntity2 : public KnotHolderEntity {
public:
virtual Geom::Point knot_get() const;
- virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state);
- virtual void knot_click(guint state);
+ virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state);
+ virtual void knot_click(unsigned int state);
};
void
-StarKnotHolderEntity1::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, guint state)
+StarKnotHolderEntity1::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, unsigned int state)
{
- SPStar *star = SP_STAR(item);
+ SPStar *star = dynamic_cast<SPStar *>(item);
+ g_assert(star != NULL);
Geom::Point const s = snap_knot_position(p, state);
@@ -1009,13 +1051,14 @@ StarKnotHolderEntity1::knot_set(Geom::Point const &p, Geom::Point const &/*origi
star->arg[0] = arg1;
star->arg[1] += darg1;
}
- (static_cast<SPObject *>(star))->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+ star->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
}
void
-StarKnotHolderEntity2::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, guint state)
+StarKnotHolderEntity2::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, unsigned int state)
{
- SPStar *star = SP_STAR(item);
+ SPStar *star = dynamic_cast<SPStar *>(item);
+ g_assert(star != NULL);
Geom::Point const s = snap_knot_position(p, state);
@@ -1037,7 +1080,7 @@ StarKnotHolderEntity2::knot_set(Geom::Point const &p, Geom::Point const &/*origi
star->r[1] = L2(d);
star->arg[1] = atan2(d);
}
- (static_cast<SPObject *>(star))->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+ star->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
}
}
@@ -1046,7 +1089,8 @@ StarKnotHolderEntity1::knot_get() const
{
g_assert(item != NULL);
- SPStar const *star = SP_STAR(item);
+ SPStar const *star = dynamic_cast<SPStar const *>(item);
+ g_assert(star != NULL);
return sp_star_get_xy(star, SP_STAR_POINT_KNOT1, 0);
@@ -1057,36 +1101,38 @@ StarKnotHolderEntity2::knot_get() const
{
g_assert(item != NULL);
- SPStar const *star = SP_STAR(item);
+ SPStar const *star = dynamic_cast<SPStar const *>(item);
+ g_assert(star != NULL);
return sp_star_get_xy(star, SP_STAR_POINT_KNOT2, 0);
}
static void
-sp_star_knot_click(SPItem *item, guint state)
+sp_star_knot_click(SPItem *item, unsigned int state)
{
- SPStar *star = SP_STAR(item);
+ SPStar *star = dynamic_cast<SPStar *>(item);
+ g_assert(star != NULL);
if (state & GDK_MOD1_MASK) {
star->randomized = 0;
- (static_cast<SPObject *>(star))->updateRepr();
+ star->updateRepr();
} else if (state & GDK_SHIFT_MASK) {
star->rounded = 0;
- (static_cast<SPObject *>(star))->updateRepr();
+ star->updateRepr();
} else if (state & GDK_CONTROL_MASK) {
star->arg[1] = star->arg[0] + M_PI / star->sides;
- (static_cast<SPObject *>(star))->updateRepr();
+ star->updateRepr();
}
}
void
-StarKnotHolderEntity1::knot_click(guint state)
+StarKnotHolderEntity1::knot_click(unsigned int state)
{
sp_star_knot_click(item, state);
}
void
-StarKnotHolderEntity2::knot_click(guint state)
+StarKnotHolderEntity2::knot_click(unsigned int state)
{
sp_star_knot_click(item, state);
}
@@ -1094,7 +1140,8 @@ StarKnotHolderEntity2::knot_click(guint state)
StarKnotHolder::StarKnotHolder(SPDesktop *desktop, SPItem *item, SPKnotHolderReleasedFunc relhandler) :
KnotHolder(desktop, item, relhandler)
{
- SPStar *star = SP_STAR(item);
+ SPStar *star = dynamic_cast<SPStar *>(item);
+ g_assert(item != NULL);
StarKnotHolderEntity1 *entity1 = new StarKnotHolderEntity1();
entity1->create(desktop, item, this, Inkscape::CTRL_TYPE_SHAPER,
@@ -1119,14 +1166,14 @@ StarKnotHolder::StarKnotHolder(SPDesktop *desktop, SPItem *item, SPKnotHolderRel
class SpiralKnotHolderEntityInner : public KnotHolderEntity {
public:
virtual Geom::Point knot_get() const;
- virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state);
- virtual void knot_click(guint state);
+ virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state);
+ virtual void knot_click(unsigned int state);
};
class SpiralKnotHolderEntityOuter : public KnotHolderEntity {
public:
virtual Geom::Point knot_get() const;
- virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state);
+ virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state);
};
@@ -1137,12 +1184,13 @@ public:
* [control] constrain inner arg to round per PI/4
*/
void
-SpiralKnotHolderEntityInner::knot_set(Geom::Point const &p, Geom::Point const &origin, guint state)
+SpiralKnotHolderEntityInner::knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state)
{
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
int snaps = prefs->getInt("/options/rotationsnapsperpi/value", 12);
- SPSpiral *spiral = SP_SPIRAL(item);
+ SPSpiral *spiral = dynamic_cast<SPSpiral *>(item);
+ g_assert(spiral != NULL);
gdouble dx = p[Geom::X] - spiral->cx;
gdouble dy = p[Geom::Y] - spiral->cy;
@@ -1177,7 +1225,7 @@ SpiralKnotHolderEntityInner::knot_set(Geom::Point const &p, Geom::Point const &o
spiral->t0 = CLAMP(spiral->t0, 0.0, 0.999);
}
- (static_cast<SPObject *>(spiral))->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+ spiral->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
}
/*
@@ -1186,12 +1234,13 @@ SpiralKnotHolderEntityInner::knot_set(Geom::Point const &p, Geom::Point const &o
* [control] constrain inner arg to round per PI/4
*/
void
-SpiralKnotHolderEntityOuter::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, guint state)
+SpiralKnotHolderEntityOuter::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, unsigned int state)
{
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
int snaps = prefs->getInt("/options/rotationsnapsperpi/value", 12);
- SPSpiral *spiral = SP_SPIRAL(item);
+ SPSpiral *spiral = dynamic_cast<SPSpiral *>(item);
+ g_assert(spiral != NULL);
gdouble dx = p[Geom::X] - spiral->cx;
gdouble dy = p[Geom::Y] - spiral->cy;
@@ -1256,13 +1305,14 @@ SpiralKnotHolderEntityOuter::knot_set(Geom::Point const &p, Geom::Point const &/
spiral->t0 = CLAMP(spiral->t0, 0.0, 0.999);
}
- (static_cast<SPObject *>(spiral))->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+ spiral->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
}
Geom::Point
SpiralKnotHolderEntityInner::knot_get() const
{
- SPSpiral const *spiral = SP_SPIRAL(item);
+ SPSpiral const *spiral = dynamic_cast<SPSpiral const *>(item);
+ g_assert(spiral != NULL);
return spiral->getXY(spiral->t0);
}
@@ -1270,22 +1320,24 @@ SpiralKnotHolderEntityInner::knot_get() const
Geom::Point
SpiralKnotHolderEntityOuter::knot_get() const
{
- SPSpiral const *spiral = SP_SPIRAL(item);
+ SPSpiral const *spiral = dynamic_cast<SPSpiral const *>(item);
+ g_assert(spiral != NULL);
return spiral->getXY(1.0);
}
void
-SpiralKnotHolderEntityInner::knot_click(guint state)
+SpiralKnotHolderEntityInner::knot_click(unsigned int state)
{
- SPSpiral *spiral = SP_SPIRAL(item);
+ SPSpiral *spiral = dynamic_cast<SPSpiral *>(item);
+ g_assert(spiral != NULL);
if (state & GDK_MOD1_MASK) {
spiral->exp = 1;
- (static_cast<SPObject *>(spiral))->updateRepr();
+ spiral->updateRepr();
} else if (state & GDK_SHIFT_MASK) {
spiral->t0 = 0;
- (static_cast<SPObject *>(spiral))->updateRepr();
+ spiral->updateRepr();
}
}
@@ -1314,26 +1366,28 @@ SpiralKnotHolder::SpiralKnotHolder(SPDesktop *desktop, SPItem *item, SPKnotHolde
class OffsetKnotHolderEntity : public KnotHolderEntity {
public:
virtual Geom::Point knot_get() const;
- virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state);
+ virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state);
};
void
-OffsetKnotHolderEntity::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, guint /*state*/)
+OffsetKnotHolderEntity::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, unsigned int /*state*/)
{
- SPOffset *offset = SP_OFFSET(item);
+ SPOffset *offset = dynamic_cast<SPOffset *>(item);
+ g_assert(offset != NULL);
offset->rad = sp_offset_distance_to_original(offset, p);
offset->knot = p;
offset->knotSet = true;
- (static_cast<SPObject *>(offset))->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+ offset->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
}
Geom::Point
OffsetKnotHolderEntity::knot_get() const
{
- SPOffset const *offset = SP_OFFSET(item);
+ SPOffset const *offset = dynamic_cast<SPOffset const *>(item);
+ g_assert(offset != NULL);
Geom::Point np;
sp_offset_top_point(offset,&np);
@@ -1357,19 +1411,20 @@ OffsetKnotHolder::OffsetKnotHolder(SPDesktop *desktop, SPItem *item, SPKnotHolde
class FlowtextKnotHolderEntity : public RectKnotHolderEntityWH {
public:
virtual Geom::Point knot_get() const;
- virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state);
+ virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state);
};
Geom::Point
FlowtextKnotHolderEntity::knot_get() const
{
- SPRect const *rect = SP_RECT(item);
+ SPRect const *rect = dynamic_cast<SPRect const *>(item);
+ g_assert(rect != NULL);
return Geom::Point(rect->x.computed + rect->width.computed, rect->y.computed + rect->height.computed);
}
void
-FlowtextKnotHolderEntity::knot_set(Geom::Point const &p, Geom::Point const &origin, guint state)
+FlowtextKnotHolderEntity::knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state)
{
set_internal(p, origin, state);
}
diff --git a/src/object-edit.h b/src/ui/object-edit.h
index ba59e46cd..75f3ce12b 100644
--- a/src/object-edit.h
+++ b/src/ui/object-edit.h
@@ -14,12 +14,13 @@
#include "knotholder.h"
-namespace Inkscape
-{
+namespace Inkscape {
+namespace UI {
KnotHolder *createKnotHolder(SPItem *item, SPDesktop *desktop);
}
+}
class RectKnotHolder : public KnotHolder {
public:
diff --git a/src/ui/shape-editor.cpp b/src/ui/shape-editor.cpp
new file mode 100644
index 000000000..0b9fc24c5
--- /dev/null
+++ b/src/ui/shape-editor.cpp
@@ -0,0 +1,177 @@
+/*
+ * Inkscape::ShapeEditor
+ *
+ * Authors:
+ * bulia byak <buliabyak@users.sf.net>
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+#include <glibmm/i18n.h>
+
+#include "desktop-handles.h"
+#include "document.h"
+#include "gc-anchored.h"
+#include "knotholder.h"
+#include "ui/object-edit.h"
+#include "sp-item.h"
+#include "sp-object.h"
+#include "ui/shape-editor.h"
+#include "xml/node-event-vector.h"
+
+//using Inkscape::createKnotHolder;
+
+namespace Inkscape {
+namespace UI {
+
+bool ShapeEditor::_blockSetItem = false;
+
+ShapeEditor::ShapeEditor(SPDesktop *dt) {
+ this->desktop = dt;
+ this->knotholder = NULL;
+ this->knotholder_listener_attached_for = NULL;
+}
+
+ShapeEditor::~ShapeEditor() {
+ unset_item();
+}
+
+void ShapeEditor::unset_item(bool keep_knotholder) {
+ if (this->knotholder) {
+ Inkscape::XML::Node *old_repr = this->knotholder->repr;
+ if (old_repr && old_repr == knotholder_listener_attached_for) {
+ sp_repr_remove_listener_by_data(old_repr, this);
+ Inkscape::GC::release(old_repr);
+ knotholder_listener_attached_for = NULL;
+ }
+
+ if (!keep_knotholder) {
+ delete this->knotholder;
+ this->knotholder = NULL;
+ }
+ }
+}
+
+bool ShapeEditor::has_knotholder() {
+ return this->knotholder != NULL;
+}
+
+void ShapeEditor::update_knotholder() {
+ if (this->knotholder)
+ this->knotholder->update_knots();
+}
+
+bool ShapeEditor::has_local_change() {
+ return (this->knotholder && this->knotholder->local_change != 0);
+}
+
+void ShapeEditor::decrement_local_change() {
+ if (this->knotholder) {
+ this->knotholder->local_change = FALSE;
+ }
+}
+
+const SPItem *ShapeEditor::get_item() {
+ const SPItem *item = NULL;
+ if (this->has_knotholder()) {
+ item = this->knotholder->getItem();
+ }
+ return item;
+}
+
+void ShapeEditor::event_attr_changed(Inkscape::XML::Node *, gchar const *name, gchar const *, gchar const *, bool, void *data)
+{
+ g_assert(data);
+ ShapeEditor *sh = static_cast<ShapeEditor *>(data);
+ bool changed_kh = false;
+
+ if (sh->has_knotholder())
+ {
+ changed_kh = !sh->has_local_change();
+ sh->decrement_local_change();
+ if (changed_kh) {
+ // this can happen if an LPEItem's knotholder handle was dragged, in which case we want
+ // to keep the knotholder; in all other cases (e.g., if the LPE itself changes) we delete it
+ sh->reset_item(!strcmp(name, "d"));
+ }
+ }
+}
+
+static Inkscape::XML::NodeEventVector shapeeditor_repr_events = {
+ NULL, /* child_added */
+ NULL, /* child_removed */
+ ShapeEditor::event_attr_changed,
+ NULL, /* content_changed */
+ NULL /* order_changed */
+};
+
+
+void ShapeEditor::set_item(SPItem *item, bool keep_knotholder) {
+ if (_blockSetItem) {
+ return;
+ }
+
+ // this happens (and should only happen) when for an LPEItem having both knotholder and
+ // nodepath the knotholder is adapted; in this case we don't want to delete the knotholder
+ // since this freezes the handles
+ unset_item(keep_knotholder);
+
+ if (item) {
+ Inkscape::XML::Node *repr;
+ if (!this->knotholder) {
+ // only recreate knotholder if none is present
+ this->knotholder = createKnotHolder(item, desktop);
+ }
+ if (this->knotholder) {
+ this->knotholder->update_knots();
+ // setting new listener
+ repr = this->knotholder->repr;
+ if (repr != knotholder_listener_attached_for) {
+ Inkscape::GC::anchor(repr);
+ sp_repr_add_listener(repr, &shapeeditor_repr_events, this);
+ knotholder_listener_attached_for = repr;
+ }
+ }
+ }
+}
+
+
+/** FIXME: This thing is only called when the item needs to be updated in response to repr change.
+ Why not make a reload function in KnotHolder? */
+void ShapeEditor::reset_item(bool keep_knotholder)
+{
+ if (knotholder) {
+ SPObject *obj = sp_desktop_document(desktop)->getObjectByRepr(knotholder_listener_attached_for); /// note that it is not certain that this is an SPItem; it could be a LivePathEffectObject.
+ set_item(SP_ITEM(obj), keep_knotholder);
+ }
+}
+
+/**
+ * Returns true if this ShapeEditor has a knot above which the mouse currently hovers.
+ */
+bool ShapeEditor::knot_mouseover() const {
+ if (this->knotholder) {
+ return knotholder->knot_mouseover();
+ }
+
+ return false;
+}
+
+} // namespace UI
+} // namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/shape-editor.h b/src/ui/shape-editor.h
new file mode 100644
index 000000000..142a2493b
--- /dev/null
+++ b/src/ui/shape-editor.h
@@ -0,0 +1,71 @@
+#ifndef SEEN_SHAPE_EDITOR_H
+#define SEEN_SHAPE_EDITOR_H
+
+/*
+ * Inkscape::ShapeEditor
+ *
+ * This is a container class which contains a knotholder for shapes.
+ * It is attached to a single item.
+ *
+ * Authors:
+ * bulia byak <buliabyak@users.sf.net>
+ *
+ */
+
+class KnotHolder;
+class LivePathEffectObject;
+class SPDesktop;
+class SPItem;
+
+namespace Inkscape { namespace XML { class Node; }
+namespace UI {
+
+class ShapeEditor {
+public:
+
+ ShapeEditor(SPDesktop *desktop);
+ ~ShapeEditor();
+
+ void set_item(SPItem *item, bool keep_knotholder = false);
+ void unset_item(bool keep_knotholder = false);
+
+ void update_knotholder(); //((deprecated))
+
+ bool has_local_change();
+ void decrement_local_change();
+
+ bool knot_mouseover() const;
+
+ static void blockSetItem(bool b) { _blockSetItem = b; } // kludge
+
+ static void event_attr_changed(Inkscape::XML::Node * /*repr*/, char const *name, char const * /*old_value*/,
+ char const * /*new_value*/, bool /*is_interactive*/, void *data);
+private:
+ bool has_knotholder();
+ void reset_item (bool keep_knotholder = true);
+ const SPItem *get_item();
+
+ static bool _blockSetItem;
+
+ SPDesktop *desktop;
+ KnotHolder *knotholder;
+ Inkscape::XML::Node *knotholder_listener_attached_for;
+};
+
+} // namespace UI
+} // namespace Inkscape
+
+#endif // SEEN_SHAPE_EDITOR_H
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
+
diff --git a/src/tool-factory.h b/src/ui/tool-factory.h
index 726706732..726706732 100644
--- a/src/tool-factory.h
+++ b/src/ui/tool-factory.h
diff --git a/src/ui/tool/control-point-selection.cpp b/src/ui/tool/control-point-selection.cpp
index d10ed0f0d..998f74ee0 100644
--- a/src/ui/tool/control-point-selection.cpp
+++ b/src/ui/tool/control-point-selection.cpp
@@ -74,7 +74,7 @@ ControlPointSelection::~ControlPointSelection()
}
/** Add a control point to the selection. */
-std::pair<ControlPointSelection::iterator, bool> ControlPointSelection::insert(const value_type &x)
+std::pair<ControlPointSelection::iterator, bool> ControlPointSelection::insert(const value_type &x, bool notify)
{
iterator found = _points.find(x);
if (found != _points.end()) {
@@ -86,6 +86,10 @@ std::pair<ControlPointSelection::iterator, bool> ControlPointSelection::insert(c
x->updateState();
_pointChanged(x, true);
+ if (notify) {
+ signal_selection_changed.emit(std::vector<key_type>(1, x), true);
+ }
+
return std::pair<iterator, bool>(found, true);
}
@@ -97,47 +101,75 @@ void ControlPointSelection::erase(iterator pos)
erased->updateState();
_pointChanged(erased, false);
}
-ControlPointSelection::size_type ControlPointSelection::erase(const key_type &k)
+ControlPointSelection::size_type ControlPointSelection::erase(const key_type &k, bool notify)
{
iterator pos = _points.find(k);
if (pos == _points.end()) return 0;
erase(pos);
+
+ if (notify) {
+ signal_selection_changed.emit(std::vector<key_type>(1, k), false);
+ }
return 1;
}
void ControlPointSelection::erase(iterator first, iterator last)
{
+ std::vector<SelectableControlPoint *> out(first, last);
while (first != last) erase(first++);
+ signal_selection_changed.emit(out, false);
}
/** Remove all points from the selection, making it empty. */
void ControlPointSelection::clear()
{
+ std::vector<SelectableControlPoint *> out(begin(), end());
for (iterator i = begin(); i != end(); )
erase(i++);
+ if (!out.empty())
+ signal_selection_changed.emit(out, false);
}
/** Select all points that this selection can contain. */
void ControlPointSelection::selectAll()
{
for (set_type::iterator i = _all_points.begin(); i != _all_points.end(); ++i) {
- insert(*i);
+ insert(*i, false);
}
+ std::vector<SelectableControlPoint *> out(_all_points.begin(), _all_points.end());
+ if (!out.empty())
+ signal_selection_changed.emit(out, true);
}
/** Select all points inside the given rectangle (in desktop coordinates). */
void ControlPointSelection::selectArea(Geom::Rect const &r)
{
+ std::vector<SelectableControlPoint *> out;
for (set_type::iterator i = _all_points.begin(); i != _all_points.end(); ++i) {
- if (r.contains(**i))
- insert(*i);
+ if (r.contains(**i)) {
+ insert(*i, false);
+ out.push_back(*i);
+ }
}
+ if (!out.empty())
+ signal_selection_changed.emit(out, true);
}
/** Unselect all selected points and select all unselected points. */
void ControlPointSelection::invertSelection()
{
+ std::vector<SelectableControlPoint *> in, out;
for (set_type::iterator i = _all_points.begin(); i != _all_points.end(); ++i) {
- if ((*i)->selected()) erase(*i);
- else insert(*i);
+ if ((*i)->selected()) {
+ in.push_back(*i);
+ erase(*i);
+ }
+ else {
+ out.push_back(*i);
+ insert(*i, false);
+ }
}
+ if (!in.empty())
+ signal_selection_changed.emit(in, false);
+ if (!out.empty())
+ signal_selection_changed.emit(out, true);
}
void ControlPointSelection::spatialGrow(SelectableControlPoint *origin, int dir)
{
@@ -166,6 +198,7 @@ void ControlPointSelection::spatialGrow(SelectableControlPoint *origin, int dir)
if (match) {
if (grow) insert(match);
else erase(match);
+ signal_selection_changed.emit(std::vector<value_type>(1, match), grow);
}
}
@@ -389,7 +422,7 @@ void ControlPointSelection::_pointChanged(SelectableControlPoint *p, bool select
_handles->rotationCenter().move(_bounds->midpoint());
}
- signal_point_changed.emit(p, selected);
+ //signal_point_changed.emit(p, selected);
}
void ControlPointSelection::_mouseoverChanged()
diff --git a/src/ui/tool/control-point-selection.h b/src/ui/tool/control-point-selection.h
index a087e0455..2d812c0a3 100644
--- a/src/ui/tool/control-point-selection.h
+++ b/src/ui/tool/control-point-selection.h
@@ -62,18 +62,19 @@ public:
const_iterator end() const { return _points.end(); }
// insert
- std::pair<iterator, bool> insert(const value_type& x);
+ std::pair<iterator, bool> insert(const value_type& x, bool notify = true);
template <class InputIterator>
void insert(InputIterator first, InputIterator last) {
for (; first != last; ++first) {
- insert(*first);
+ insert(*first, false);
}
+ signal_selection_changed.emit(std::vector<key_type>(first, last), true);
}
// erase
void clear();
void erase(iterator pos);
- size_type erase(const key_type& k);
+ size_type erase(const key_type& k, bool notify = true);
void erase(iterator first, iterator last);
// find
@@ -108,7 +109,9 @@ public:
void toggleTransformHandlesMode();
sigc::signal<void> signal_update;
- sigc::signal<void, SelectableControlPoint *, bool> signal_point_changed;
+ // It turns out that emitting a signal after every point is selected or deselected is not too efficient,
+ // so this can be done in a massive group once the selection is finally changed.
+ sigc::signal<void, std::vector<SelectableControlPoint *>, bool> signal_selection_changed;
sigc::signal<void, CommitEvent> signal_commit;
void getOriginalPoints(std::vector<Inkscape::SnapCandidatePoint> &pts);
@@ -166,4 +169,4 @@ private:
fill-column:99
End:
*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8 :
diff --git a/src/ui/tool/curve-drag-point.cpp b/src/ui/tool/curve-drag-point.cpp
index 4ca736f80..013553410 100644
--- a/src/ui/tool/curve-drag-point.cpp
+++ b/src/ui/tool/curve-drag-point.cpp
@@ -53,9 +53,11 @@ bool CurveDragPoint::grabbed(GdkEventMotion */*event*/)
// delta is a vector equal 1/3 of distance from first to second
Geom::Point delta = (second->position() - first->position()) / 3.0;
- first->front()->move(first->front()->position() + delta);
- second->back()->move(second->back()->position() - delta);
-
+ // only update the nodes if the mode is bspline
+ if(!_pm.isBSpline(false)){
+ first->front()->move(first->front()->position() + delta);
+ second->back()->move(second->back()->position() - delta);
+ }
_pm.update();
} else {
_segment_was_degenerate = false;
@@ -88,9 +90,12 @@ void CurveDragPoint::dragged(Geom::Point &new_pos, GdkEventMotion *event)
Geom::Point offset0 = ((1-weight)/(3*t*(1-t)*(1-t))) * delta;
Geom::Point offset1 = (weight/(3*t*t*(1-t))) * delta;
- first->front()->move(first->front()->position() + offset0);
- second->back()->move(second->back()->position() + offset1);
-
+ //modified so that, if the trace is bspline, it only acts if the SHIFT key is pressed
+ if(!_pm.isBSpline(false)){
+ first->front()->move(first->front()->position() + offset0);
+ second->back()->move(second->back()->position() + offset1);
+ }else if(weight>=0.8 && held_shift(*event))second->back()->move(new_pos);
+ else if(weight<=0.2 && held_shift(*event))first->front()->move(new_pos);
_pm.update();
}
diff --git a/src/ui/tool/multi-path-manipulator.cpp b/src/ui/tool/multi-path-manipulator.cpp
index 65987ad52..d7b35c974 100644
--- a/src/ui/tool/multi-path-manipulator.cpp
+++ b/src/ui/tool/multi-path-manipulator.cpp
@@ -122,7 +122,7 @@ MultiPathManipulator::MultiPathManipulator(PathSharedData &data, sigc::connectio
{
_selection.signal_commit.connect(
sigc::mem_fun(*this, &MultiPathManipulator::_commit));
- _selection.signal_point_changed.connect(
+ _selection.signal_selection_changed.connect(
sigc::hide( sigc::hide(
signal_coords_changed.make_slot())));
}
@@ -182,7 +182,7 @@ void MultiPathManipulator::setItems(std::set<ShapeRecord> const &s)
ShapeRecord const &r = *i;
if (!SP_IS_PATH(r.item) && !IS_LIVEPATHEFFECT(r.item)) continue;
boost::shared_ptr<PathManipulator> newpm(new PathManipulator(*this, (SPPath*) r.item,
- r.edit_transform, _getOutlineColor(r.role), r.lpe_key));
+ r.edit_transform, _getOutlineColor(r.role, r.item), r.lpe_key));
newpm->showHandles(_show_handles);
// always show outlines for clips and masks
newpm->showOutline(_show_outline || r.role != SHAPE_ROLE_NORMAL);
@@ -670,7 +670,18 @@ bool MultiPathManipulator::event(Inkscape::UI::Tools::ToolBase *event_context, G
// a) del preserves shape, and control is not pressed
// b) ctrl+del preserves shape (del_preserves_shape is false), and control is pressed
// Hence xor
- deleteNodes(del_preserves_shape ^ held_control(event->key));
+ guint mode = prefs->getInt("/tools/freehand/pen/freehand-mode", 0);
+
+ //if the trace is bspline ( mode 2)
+ if(mode==2){
+ // is this correct ?
+ if(del_preserves_shape ^ held_control(event->key))
+ deleteNodes(false);
+ else
+ deleteNodes(true);
+ }
+ else
+ deleteNodes(del_preserves_shape ^ held_control(event->key));
// Delete any selected gradient nodes as well
event_context->deleteSelectedDrag(held_control(event->key));
@@ -833,7 +844,7 @@ void MultiPathManipulator::_doneWithCleanup(gchar const *reason, bool alert_LPE)
}
/** Get an outline color based on the shape's role (normal, mask, LPE parameter, etc.). */
-guint32 MultiPathManipulator::_getOutlineColor(ShapeRole role)
+guint32 MultiPathManipulator::_getOutlineColor(ShapeRole role, SPItem *item)
{
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
switch(role) {
@@ -845,7 +856,7 @@ guint32 MultiPathManipulator::_getOutlineColor(ShapeRole role)
return prefs->getColor("/tools/nodes/lpe_param_color", 0x009000ff);
case SHAPE_ROLE_NORMAL:
default:
- return prefs->getColor("/tools/nodes/outline_color", 0xff0000ff);
+ return item->highlight_color();
}
}
diff --git a/src/ui/tool/multi-path-manipulator.h b/src/ui/tool/multi-path-manipulator.h
index 1328372c6..cdbf34e9d 100644
--- a/src/ui/tool/multi-path-manipulator.h
+++ b/src/ui/tool/multi-path-manipulator.h
@@ -53,6 +53,7 @@ public:
void insertNodesAtExtrema(ExtremumType extremum);
void insertNodes();
+ void alertLPE();
void duplicateNodes();
void joinNodes();
void breakNodes();
@@ -104,9 +105,9 @@ private:
}
void _commit(CommitEvent cps);
- void _done(gchar const *reason, bool alert_LPE = false);
+ void _done(gchar const *reason, bool alert_LPE = true);
void _doneWithCleanup(gchar const *reason, bool alert_LPE = false);
- guint32 _getOutlineColor(ShapeRole role);
+ guint32 _getOutlineColor(ShapeRole role, SPItem *item);
MapType _mmap;
public:
diff --git a/src/ui/tool/node.cpp b/src/ui/tool/node.cpp
index fbbc4be64..8a1ca0b90 100644
--- a/src/ui/tool/node.cpp
+++ b/src/ui/tool/node.cpp
@@ -13,7 +13,6 @@
#include <glib/gi18n.h>
#include <2geom/bezier-utils.h>
#include <2geom/transforms.h>
-
#include "display/sp-ctrlline.h"
#include "display/sp-canvas.h"
#include "display/sp-canvas-util.h"
@@ -28,7 +27,10 @@
#include "ui/tool/event-utils.h"
#include "ui/tool/node.h"
#include "ui/tool/path-manipulator.h"
+#include "ui/tools/node-tool.h"
+#include "ui/tools-switch.h"
#include <gdk/gdkkeysyms.h>
+#include <cmath>
namespace {
@@ -58,6 +60,11 @@ Inkscape::ControlType nodeTypeToCtrlType(Inkscape::UI::NodeType type)
namespace Inkscape {
namespace UI {
+/*const double handleCubicGap = 0.01;*/
+const double noPower = 0.0;
+const double defaultStartPower = 0.3334;
+/*const double defaultEndPower = 0.6667;*/
+
ControlPoint::ColorSet Node::node_colors = {
{0xbfbfbf00, 0x000000ff}, // normal fill, stroke
{0xff000000, 0x000000ff}, // mouseover fill, stroke
@@ -166,6 +173,12 @@ void Handle::move(Geom::Point const &new_pos)
}
}
setPosition(new_pos);
+
+ //move the handler and its oposite the same proportion
+ if(_pm().isBSpline()){
+ setPosition(_pm().BSplineHandleReposition(this,this));
+ this->other()->setPosition(_pm().BSplineHandleReposition(this->other(),this));
+ }
return;
}
@@ -177,6 +190,13 @@ void Handle::move(Geom::Point const &new_pos)
Geom::Point new_delta = (Geom::dot(delta, direction)
/ Geom::L2sq(direction)) * direction;
setRelativePos(new_delta);
+
+ //move the handler and its oposite the same proportion
+ if(_pm().isBSpline()){
+ setPosition(_pm().BSplineHandleReposition(this,this));
+ this->other()->setPosition(_pm().BSplineHandleReposition(this->other(),this));
+ }
+
return;
}
@@ -195,8 +215,14 @@ void Handle::move(Geom::Point const &new_pos)
break;
default: break;
}
-
setPosition(new_pos);
+
+ // moves the handler and its oposite the same proportion
+ if(_pm().isBSpline()){
+ setPosition(_pm().BSplineHandleReposition(this,this));
+ this->other()->setPosition(_pm().BSplineHandleReposition(this->other(),this));
+ }
+
}
void Handle::setPosition(Geom::Point const &p)
@@ -273,12 +299,27 @@ bool Handle::_eventHandler(Inkscape::UI::Tools::ToolBase *event_context, GdkEven
break;
default: break;
}
+ break;
+ // new double click event to set the handlers of a node to the default proportion, defaultStartPower%
+ case GDK_2BUTTON_PRESS:
+ handle_2button_press();
+ break;
+
default: break;
}
return ControlPoint::_eventHandler(event_context, event);
}
+//this function moves the handler and its oposite to the default proportion of defaultStartPower
+void Handle::handle_2button_press(){
+ if(_pm().isBSpline()){
+ setPosition(_pm().BSplineHandleReposition(this,defaultStartPower));
+ this->other()->setPosition(_pm().BSplineHandleReposition(this->other(),defaultStartPower));
+ _pm().update();
+ }
+}
+
bool Handle::grabbed(GdkEventMotion *)
{
_saved_other_pos = other()->position();
@@ -289,6 +330,10 @@ bool Handle::grabbed(GdkEventMotion *)
void Handle::dragged(Geom::Point &new_pos, GdkEventMotion *event)
{
+ if (tools_isactive(_desktop, TOOLS_NODES)) {
+ Inkscape::UI::Tools::NodeTool *nt = static_cast<Inkscape::UI::Tools::NodeTool*>(_desktop->event_context);
+ nt->update_helperpath();
+ }
Geom::Point parent_pos = _parent->position();
Geom::Point origin = _last_drag_origin();
SnapManager &sm = _desktop->namedview->snap_manager;
@@ -326,10 +371,18 @@ void Handle::dragged(Geom::Point &new_pos, GdkEventMotion *event)
ctrl_constraint = Inkscape::Snapper::SnapConstraint(parent_pos, parent_pos - perp_pos);
}
new_pos = result;
+ // moves the handler and its oposite in X fixed positions depending on parameter "steps with control"
+ // by default in live BSpline
+ if(_pm().isBSpline()){
+ setPosition(new_pos);
+ int steps = _pm().BSplineGetSteps();
+ new_pos=_pm().BSplineHandleReposition(this,ceilf(_pm().BSplineHandlePosition(this,this)*steps)/steps);
+ }
}
std::vector<Inkscape::SnapCandidatePoint> unselected;
- if (snap) {
+ //if the snap adjustment is activated and it is not bspline
+ if (snap && !_pm().isBSpline(false)) {
ControlPointSelection::Set &nodes = _parent->_selection.allPoints();
for (ControlPointSelection::Set::iterator i = nodes.begin(); i != nodes.end(); ++i) {
Node *n = static_cast<Node*>(*i);
@@ -369,6 +422,10 @@ void Handle::dragged(Geom::Point &new_pos, GdkEventMotion *event)
other()->setPosition(_saved_other_pos);
}
}
+ //if it is bspline but SHIFT or CONTROL are not pressed it fixes it in the original position
+ if(_pm().isBSpline() && !held_shift(*event) && !held_control(*event)){
+ new_pos=_last_drag_origin();
+ }
move(new_pos); // needed for correct update, even though it's redundant
_pm().update();
}
@@ -427,13 +484,19 @@ static double snap_increment_degrees() {
Glib::ustring Handle::_getTip(unsigned state) const
{
char const *more;
+ // a trick to mark as bspline if the node has no strength, we are going to use it later
+ // to show the appropiate messages. We cannot do it in any different way becasue the function is constant
+
+ bool isBSpline = _pm().isBSpline();
bool can_shift_rotate = _parent->type() == NODE_CUSP && !other()->isDegenerate();
- if (can_shift_rotate) {
+ if (can_shift_rotate && !isBSpline) {
more = C_("Path handle tip", "more: Shift, Ctrl, Alt");
- } else {
+ } else if(isBSpline){
+ more = C_("Path handle tip", "more: Ctrl");
+ }else {
more = C_("Path handle tip", "more: Ctrl, Alt");
}
- if (state_held_alt(state)) {
+ if (state_held_alt(state) && !isBSpline) {
if (state_held_control(state)) {
if (state_held_shift(state) && can_shift_rotate) {
return format_tip(C_("Path handle tip",
@@ -456,18 +519,24 @@ Glib::ustring Handle::_getTip(unsigned state) const
}
} else {
if (state_held_control(state)) {
- if (state_held_shift(state) && can_shift_rotate) {
+ if (state_held_shift(state) && can_shift_rotate && !isBSpline) {
return format_tip(C_("Path handle tip",
"<b>Shift+Ctrl</b>: snap rotation angle to %g° increments and rotate both handles"),
snap_increment_degrees());
- } else {
+ } else if(isBSpline){
+ return format_tip(C_("Path handle tip",
+ "<b>Ctrl</b>: Move handle by his actual steps in BSpline Live Effect"));
+ }else{
return format_tip(C_("Path handle tip",
"<b>Ctrl</b>: snap rotation angle to %g° increments, click to retract"),
snap_increment_degrees());
}
- } else if (state_held_shift(state) && can_shift_rotate) {
+ } else if (state_held_shift(state) && can_shift_rotate && !isBSpline) {
return C_("Path hande tip",
"<b>Shift</b>: rotate both handles by the same angle");
+ } else if(state_held_shift(state) && isBSpline){
+ return C_("Path hande tip",
+ "<b>Shift</b>: move handle");
}
}
@@ -476,9 +545,13 @@ Glib::ustring Handle::_getTip(unsigned state) const
return format_tip(C_("Path handle tip",
"<b>Auto node handle</b>: drag to convert to smooth node (%s)"), more);
default:
- return format_tip(C_("Path handle tip",
- "<b>%s</b>: drag to shape the segment (%s)"),
- handle_type_to_localized_string(_parent->type()), more);
+ if(!isBSpline){
+ return format_tip(C_("Path handle tip",
+ "<b>Auto node handle</b>: drag to convert to smooth node (%s)"), more);
+ }else{
+ return format_tip(C_("Path handle tip",
+ "<b>BSpline node handle</b>: Shift to drag, double click to reset (%s)"), more);
+ }
}
}
@@ -553,18 +626,80 @@ void Node::move(Geom::Point const &new_pos)
// move handles when the node moves.
Geom::Point old_pos = position();
Geom::Point delta = new_pos - position();
+
+ // save the previous nodes strength to apply it again once the node is moved
+ double nodeWeight = noPower;
+ double nextNodeWeight = noPower;
+ double prevNodeWeight = noPower;
+ Node *n = this;
+ Node * nextNode = n->nodeToward(n->front());
+ Node * prevNode = n->nodeToward(n->back());
+ nodeWeight = fmax(_pm().BSplineHandlePosition(n->front()),_pm().BSplineHandlePosition(n->back()));
+ if(prevNode){
+ if(prevNode->isEndNode()){
+ prevNodeWeight = _pm().BSplineHandlePosition(prevNode->front(),prevNode->front());
+ }
+ }
+ if(nextNode){
+ if(nextNode->isEndNode()){
+ nextNodeWeight = _pm().BSplineHandlePosition(nextNode->back(),nextNode->back());
+ }
+ }
+
setPosition(new_pos);
+
_front.setPosition(_front.position() + delta);
_back.setPosition(_back.position() + delta);
// if the node has a smooth handle after a line segment, it should be kept colinear
// with the segment
_fixNeighbors(old_pos, new_pos);
+
+ // move the affected handlers. First the node ones, later the adjoining ones.
+ if(_pm().isBSpline()){
+ _front.setPosition(_pm().BSplineHandleReposition(this->front(),nodeWeight));
+ _back.setPosition(_pm().BSplineHandleReposition(this->back(),nodeWeight));
+ if(prevNode){
+ if(prevNode->isEndNode()){
+ prevNode->front()->setPosition(_pm().BSplineHandleReposition(prevNode->front(),prevNodeWeight));
+ }else{
+ prevNode->front()->setPosition(_pm().BSplineHandleReposition(prevNode->front(),prevNode->back()));
+ }
+ }
+ if(nextNode){
+ if(nextNode->isEndNode()){
+ nextNode->back()->setPosition(_pm().BSplineHandleReposition(nextNode->back(),nextNodeWeight));
+ }else{
+ nextNode->back()->setPosition(_pm().BSplineHandleReposition(nextNode->back(),nextNode->front()));
+ }
+ }
+ }
}
void Node::transform(Geom::Affine const &m)
{
+
Geom::Point old_pos = position();
+
+ // save the previous nodes strength to apply it again once the node is moved
+ double nodeWeight = noPower;
+ double nextNodeWeight = noPower;
+ double prevNodeWeight = noPower;
+ Node *n = this;
+ Node * nextNode = n->nodeToward(n->front());
+ Node * prevNode = n->nodeToward(n->back());
+ nodeWeight = _pm().BSplineHandlePosition(n->front());
+ if(prevNode){
+ if(prevNode->isEndNode()){
+ prevNodeWeight = _pm().BSplineHandlePosition(prevNode->front(),prevNode->front());
+ }
+ }
+ if(nextNode){
+ if(nextNode->isEndNode()){
+ nextNodeWeight = _pm().BSplineHandlePosition(nextNode->back(),nextNode->back());
+ }
+ }
+
setPosition(position() * m);
_front.setPosition(_front.position() * m);
_back.setPosition(_back.position() * m);
@@ -572,6 +707,26 @@ void Node::transform(Geom::Affine const &m)
/* Affine transforms keep handle invariants for smooth and symmetric nodes,
* but smooth nodes at ends of linear segments and auto nodes need special treatment */
_fixNeighbors(old_pos, position());
+
+ // move the involved handlers, first the node ones, later the adjoining ones
+ if(_pm().isBSpline()){
+ _front.setPosition(_pm().BSplineHandleReposition(this->front(),nodeWeight));
+ _back.setPosition(_pm().BSplineHandleReposition(this->back(),nodeWeight));
+ if(prevNode){
+ if(prevNode->isEndNode()){
+ prevNode->front()->setPosition(_pm().BSplineHandleReposition(prevNode->front(),prevNodeWeight));
+ }else{
+ prevNode->front()->setPosition(_pm().BSplineHandleReposition(prevNode->front(),prevNode->back()));
+ }
+ }
+ if(nextNode){
+ if(nextNode->isEndNode()){
+ nextNode->back()->setPosition(_pm().BSplineHandleReposition(nextNode->back(),nextNodeWeight));
+ }else{
+ nextNode->back()->setPosition(_pm().BSplineHandleReposition(nextNode->back(),nextNode->front()));
+ }
+ }
+ }
}
Geom::Rect Node::bounds() const
@@ -657,6 +812,7 @@ void Node::showHandles(bool v)
if (!_back.isDegenerate()) {
_back.setVisible(v);
}
+
}
void Node::updateHandles()
@@ -758,6 +914,16 @@ void Node::setType(NodeType type, bool update_handles)
break;
default: break;
}
+ /* in node type changes, about bspline traces, we can mantain them with noPower power in border mode,
+ or we give them the default power in curve mode */
+ if(_pm().isBSpline()){
+ double weight = noPower;
+ if(_pm().BSplineHandlePosition(this->front()) != noPower ){
+ weight = defaultStartPower;
+ }
+ _front.setPosition(_pm().BSplineHandleReposition(this->front(),weight));
+ _back.setPosition(_pm().BSplineHandleReposition(this->back(),weight));
+ }
}
_type = type;
_setControlType(nodeTypeToCtrlType(_type));
@@ -870,6 +1036,7 @@ bool Node::_eventHandler(Inkscape::UI::Tools::ToolBase *event_context, GdkEvent
_selection.spatialGrow(this, dir);
}
return true;
+
default:
break;
}
@@ -1004,6 +1171,11 @@ void Node::_setState(State state)
case STATE_CLICKED:
mgr.setActive(_canvas_item, true);
mgr.setPrelight(_canvas_item, false);
+ //this shows the handlers when selecting the nodes
+ if(_pm().isBSpline()){
+ this->front()->setPosition(_pm().BSplineHandleReposition(this->front()));
+ this->back()->setPosition(_pm().BSplineHandleReposition(this->back()));
+ }
break;
}
SelectableControlPoint::_setState(state);
@@ -1055,6 +1227,10 @@ bool Node::grabbed(GdkEventMotion *event)
void Node::dragged(Geom::Point &new_pos, GdkEventMotion *event)
{
+ if (tools_isactive(_desktop, TOOLS_NODES)) {
+ Inkscape::UI::Tools::NodeTool *nt = static_cast<Inkscape::UI::Tools::NodeTool*>(_desktop->event_context);
+ nt->update_helperpath();
+ }
// For a note on how snapping is implemented in Inkscape, see snap.h.
SnapManager &sm = _desktop->namedview->snap_manager;
// even if we won't really snap, we might still call the one of the
@@ -1258,6 +1434,7 @@ Node *Node::nodeAwayFrom(Handle *h)
Glib::ustring Node::_getTip(unsigned state) const
{
+ bool isBSpline = _pm().isBSpline();
if (state_held_shift(state)) {
bool can_drag_out = (_next() && _front.isDegenerate()) || (_prev() && _back.isDegenerate());
if (can_drag_out) {
@@ -1287,15 +1464,24 @@ Glib::ustring Node::_getTip(unsigned state) const
// No modifiers: assemble tip from node type
char const *nodetype = node_type_to_localized_string(_type);
if (_selection.transformHandlesEnabled() && selected()) {
- if (_selection.size() == 1) {
+ if (_selection.size() == 1 && !isBSpline) {
return format_tip(C_("Path node tip",
"<b>%s</b>: drag to shape the path (more: Shift, Ctrl, Alt)"), nodetype);
+ }else if(_selection.size() == 1){
+ return format_tip(C_("Path node tip",
+ "<b>BSpline node</b>: %g weight, drag to shape the path (more: Shift, Ctrl, Alt)"),noPower/*this->bsplineWeight*/);
}
return format_tip(C_("Path node tip",
"<b>%s</b>: drag to shape the path, click to toggle scale/rotation handles (more: Shift, Ctrl, Alt)"), nodetype);
}
- return format_tip(C_("Path node tip",
- "<b>%s</b>: drag to shape the path, click to select only this node (more: Shift, Ctrl, Alt)"), nodetype);
+ if (!isBSpline) {
+ return format_tip(C_("Path node tip",
+ "<b>%s</b>: drag to shape the path, click to select only this node (more: Shift, Ctrl, Alt)"), nodetype);
+ }else{
+ return format_tip(C_("Path node tip",
+ "<b>BSpline node</b>: drag to shape the path, click to select only this node (more: Shift, Ctrl, Alt)"));
+
+ }
}
Glib::ustring Node::_getDragTip(GdkEventMotion */*event*/) const
@@ -1452,7 +1638,37 @@ void NodeList::reverse()
void NodeList::clear()
{
- for (iterator i = begin(); i != end();) erase (i++);
+ // ugly but more efficient clearing mechanism
+ std::vector<ControlPointSelection *> to_clear;
+ std::vector<std::pair<SelectableControlPoint *, long> > nodes;
+ long in = -1;
+ for (iterator i = begin(); i != end(); ++i) {
+ SelectableControlPoint *rm = static_cast<Node*>(i._node);
+ if (std::find(to_clear.begin(), to_clear.end(), &rm->_selection) == to_clear.end()) {
+ to_clear.push_back(&rm->_selection);
+ ++in;
+ }
+ nodes.push_back(std::make_pair(rm, in));
+ }
+ for (size_t i = 0, e = nodes.size(); i != e; ++i) {
+ to_clear[nodes[i].second]->erase(nodes[i].first, false);
+ }
+ std::vector<std::vector<SelectableControlPoint *> > emission;
+ for (long i = 0, e = to_clear.size(); i != e; ++i) {
+ emission.push_back(std::vector<SelectableControlPoint *>());
+ for (size_t j = 0, f = nodes.size(); j != f; ++j) {
+ if (nodes[j].second != i)
+ break;
+ emission[i].push_back(nodes[j].first);
+ }
+ }
+
+ for (size_t i = 0, e = emission.size(); i != e; ++i) {
+ to_clear[i]->signal_selection_changed.emit(emission[i], false);
+ }
+
+ for (iterator i = begin(); i != end();)
+ erase (i++);
}
NodeList::iterator NodeList::erase(iterator i)
diff --git a/src/ui/tool/node.h b/src/ui/tool/node.h
index 4582d998a..101af4817 100644
--- a/src/ui/tool/node.h
+++ b/src/ui/tool/node.h
@@ -41,6 +41,7 @@ template <typename> class NodeIterator;
}
}
+/*
#if HAVE_TR1_UNORDERED_SET
namespace std {
namespace tr1 {
@@ -48,6 +49,8 @@ template <typename N> struct hash< Inkscape::UI::NodeIterator<N> >;
}
}
#endif
+#endif
+*/
namespace Inkscape {
namespace UI {
@@ -117,7 +120,7 @@ public:
protected:
Handle(NodeSharedData const &data, Geom::Point const &initial_pos, Node *parent);
-
+ virtual void handle_2button_press();
virtual bool _eventHandler(Inkscape::UI::Tools::ToolBase *event_context, GdkEvent *event);
virtual void dragged(Geom::Point &new_pos, GdkEventMotion *event);
virtual bool grabbed(GdkEventMotion *event);
@@ -131,6 +134,7 @@ protected:
private:
inline PathManipulator &_pm();
+ inline PathManipulator &_pm() const;
Node *_parent; // the handle's lifetime does not extend beyond that of the parent node,
// so a naked pointer is OK and allows setting it during Node's construction
SPCtrlLine *_handle_line;
@@ -217,6 +221,7 @@ public:
Node *nodeAwayFrom(Handle *h);
NodeList &nodeList() { return *(static_cast<ListNode*>(this)->ln_list); }
+ NodeList &nodeList() const { return *(static_cast<ListNode const*>(this)->ln_list); }
/**
* Move the node to the bottom of its canvas group.
@@ -263,6 +268,7 @@ private:
Inkscape::SnapSourceType _snapSourceType() const;
Inkscape::SnapTargetType _snapTargetType() const;
inline PathManipulator &_pm();
+ inline PathManipulator &_pm() const;
/** Determine whether two nodes are joined by a linear segment. */
static bool _is_line_segment(Node *first, Node *second);
@@ -490,10 +496,17 @@ inline double Handle::length() const {
inline PathManipulator &Handle::_pm() {
return _parent->_pm();
}
+inline PathManipulator &Handle::_pm() const {
+ return _parent->_pm();
+}
inline PathManipulator &Node::_pm() {
return nodeList().subpathList().pm();
}
+inline PathManipulator &Node::_pm() const {
+ return nodeList().subpathList().pm();
+}
+
// definitions for node iterator
template <typename N>
NodeIterator<N>::operator bool() const {
diff --git a/src/ui/tool/path-manipulator.cpp b/src/ui/tool/path-manipulator.cpp
index 338499672..8b99c33b8 100644
--- a/src/ui/tool/path-manipulator.cpp
+++ b/src/ui/tool/path-manipulator.cpp
@@ -11,6 +11,7 @@
*/
#include "live_effects/lpe-powerstroke.h"
+#include "live_effects/lpe-fillet-chamfer.h"
#include <string>
#include <sstream>
#include <deque>
@@ -42,6 +43,7 @@
#include "ui/tool/multi-path-manipulator.h"
#include "xml/node.h"
#include "xml/node-observer.h"
+#include "live_effects/lpe-bspline.h"
namespace Inkscape {
namespace UI {
@@ -54,6 +56,10 @@ enum PathChange {
};
} // anonymous namespace
+const double handleCubicGap = 0.01;
+const double noPower = 0.0;
+const double defaultStartPower = 0.3334;
+
/**
* Notifies the path manipulator when something changes the path being edited
@@ -102,7 +108,6 @@ private:
};
void build_segment(Geom::PathBuilder &, Node *, Node *);
-
PathManipulator::PathManipulator(MultiPathManipulator &mpm, SPPath *path,
Geom::Affine const &et, guint32 outline_color, Glib::ustring lpe_key)
: PointManipulator(mpm._path_data.node_data.desktop, *mpm._path_data.node_data.selection)
@@ -139,12 +144,14 @@ PathManipulator::PathManipulator(MultiPathManipulator &mpm, SPPath *path,
_selection.signal_update.connect(
sigc::bind(sigc::mem_fun(*this, &PathManipulator::update), false));
- _selection.signal_point_changed.connect(
- sigc::mem_fun(*this, &PathManipulator::_selectionChanged));
+ _selection.signal_selection_changed.connect(
+ sigc::mem_fun(*this, &PathManipulator::_selectionChangedM));
_desktop->signal_zoom_changed.connect(
sigc::hide( sigc::mem_fun(*this, &PathManipulator::_updateOutlineOnZoomChange)));
_createControlPointsFromGeometry();
+ //Define if the path is BSpline on construction
+ isBSpline(true);
}
PathManipulator::~PathManipulator()
@@ -662,6 +669,15 @@ unsigned PathManipulator::_deleteStretch(NodeList::iterator start, NodeList::ite
nl.erase(start);
start = next;
}
+ // if we are removing, we readjust the handlers
+ if(isBSpline()){
+ if(start.prev()){
+ start.prev()->front()->setPosition(BSplineHandleReposition(start.prev()->front(),start.prev()->back()));
+ }
+ if(end){
+ end->back()->setPosition(BSplineHandleReposition(end->back(),end->front()));
+ }
+ }
return del_len;
}
@@ -816,7 +832,6 @@ void PathManipulator::scaleHandle(Node *n, int which, int dir, bool pixel)
}
h->setRelativePos(relpos);
update();
-
gchar const *key = which < 0 ? "handle:scale:left" : "handle:scale:right";
_commit(_("Scale handle"), key);
}
@@ -980,9 +995,36 @@ NodeList::iterator PathManipulator::subdivideSegment(NodeList::iterator first, d
// set new handle positions
Node *n = new Node(_multi_path_manipulator._path_data.node_data, seg2[0]);
- n->back()->setPosition(seg1[2]);
- n->front()->setPosition(seg2[1]);
- n->setType(NODE_SMOOTH, false);
+ if(!isBSpline()){
+ n->back()->setPosition(seg1[2]);
+ n->front()->setPosition(seg2[1]);
+ n->setType(NODE_SMOOTH, false);
+ } else {
+ Geom::D2< Geom::SBasis > SBasisInsideNodes;
+ SPCurve *lineInsideNodes = new SPCurve();
+ if(second->back()->isDegenerate()){
+ lineInsideNodes->moveto(n->position());
+ lineInsideNodes->lineto(second->position());
+ SBasisInsideNodes = lineInsideNodes->first_segment()->toSBasis();
+ Geom::Point next = SBasisInsideNodes.valueAt(defaultStartPower);
+ next = Geom::Point(next[Geom::X] + handleCubicGap,next[Geom::Y] + handleCubicGap);
+ lineInsideNodes->reset();
+ n->front()->setPosition(next);
+ }else{
+ n->front()->setPosition(seg2[1]);
+ }
+ if(first->front()->isDegenerate()){
+ lineInsideNodes->moveto(n->position());
+ lineInsideNodes->lineto(first->position());
+ SBasisInsideNodes = lineInsideNodes->first_segment()->toSBasis();
+ Geom::Point previous = SBasisInsideNodes.valueAt(defaultStartPower);
+ previous = Geom::Point(previous[Geom::X] + handleCubicGap,previous[Geom::Y] + handleCubicGap);
+ n->back()->setPosition(previous);
+ }else{
+ n->back()->setPosition(seg1[2]);
+ }
+ n->setType(NODE_CUSP, false);
+ }
inserted = list.insert(insert_at, n);
first->front()->move(seg1[1]);
@@ -1104,7 +1146,6 @@ void PathManipulator::_createControlPointsFromGeometry()
Geom::Curve const &cseg = pit->back_closed();
bool fuse_ends = pit->closed()
&& Geom::are_near(cseg.initialPoint(), cseg.finalPoint());
-
for (Geom::Path::const_iterator cit = pit->begin(); cit != pit->end_open(); ++cit) {
Geom::Point pos = cit->finalPoint();
Node *current_node;
@@ -1171,6 +1212,91 @@ void PathManipulator::_createControlPointsFromGeometry()
}
}
+//determines if the trace has a bspline effect and the number of steps that it takes
+int PathManipulator::BSplineGetSteps() const {
+
+ LivePathEffect::LPEBSpline const *lpe_bsp = NULL;
+
+ if (SP_IS_LPE_ITEM(_path) && _path->hasPathEffect()){
+ Inkscape::LivePathEffect::Effect const *thisEffect = SP_LPE_ITEM(_path)->getPathEffectOfType(Inkscape::LivePathEffect::BSPLINE);
+ if(thisEffect){
+ lpe_bsp = dynamic_cast<LivePathEffect::LPEBSpline const*>(thisEffect->getLPEObj()->get_lpe());
+ }
+ }
+ int steps = 0;
+ if(lpe_bsp){
+ steps = lpe_bsp->steps+1;
+ }
+ return steps;
+}
+
+// determines if the trace has bspline effect
+bool PathManipulator::isBSpline(bool recalculate){
+ if(recalculate){
+ _is_bspline = this->BSplineGetSteps() > 0;
+ }
+ return _is_bspline;
+}
+
+bool PathManipulator::isBSpline() const {
+ return BSplineGetSteps() > 0;
+}
+
+// returns the corresponding strength to the position of the handlers
+double PathManipulator::BSplineHandlePosition(Handle *h, Handle *h2){
+ using Geom::X;
+ using Geom::Y;
+ if(h2){
+ h = h2;
+ }
+ double pos = noPower;
+ Node *n = h->parent();
+ Node * nextNode = NULL;
+ nextNode = n->nodeToward(h);
+ if(nextNode){
+ SPCurve *lineInsideNodes = new SPCurve();
+ lineInsideNodes->moveto(n->position());
+ lineInsideNodes->lineto(nextNode->position());
+ if(!are_near(h->position(), n->position())){
+ pos = Geom::nearest_point(Geom::Point(h->position()[X] - handleCubicGap, h->position()[Y] - handleCubicGap), *lineInsideNodes->first_segment());
+ }
+ }
+ if (pos == noPower && !h2){
+ return BSplineHandlePosition(h, h->other());
+ }
+ return pos;
+}
+
+// give the location for the handler in the corresponding position
+Geom::Point PathManipulator::BSplineHandleReposition(Handle *h, Handle *h2){
+ double pos = this->BSplineHandlePosition(h, h2);
+ return BSplineHandleReposition(h,pos);
+}
+
+// give the location for the handler to the specified position
+Geom::Point PathManipulator::BSplineHandleReposition(Handle *h,double pos){
+ using Geom::X;
+ using Geom::Y;
+ Geom::Point ret = h->position();
+ Node *n = h->parent();
+ Geom::D2< Geom::SBasis > SBasisInsideNodes;
+ SPCurve *lineInsideNodes = new SPCurve();
+ Node * nextNode = NULL;
+ nextNode = n->nodeToward(h);
+ if(nextNode && pos != noPower){
+ lineInsideNodes->moveto(n->position());
+ lineInsideNodes->lineto(nextNode->position());
+ SBasisInsideNodes = lineInsideNodes->first_segment()->toSBasis();
+ ret = SBasisInsideNodes.valueAt(pos);
+ ret = Geom::Point(ret[X] + handleCubicGap,ret[Y] + handleCubicGap);
+ }else{
+ if(pos == noPower){
+ ret = n->position();
+ }
+ }
+ return ret;
+}
+
/** Construct the geometric representation of nodes and handles, update the outline
* and display
* \param alert_LPE if true, first the LPE is warned what the new path is going to be before updating it
@@ -1178,6 +1304,8 @@ void PathManipulator::_createControlPointsFromGeometry()
void PathManipulator::_createGeometryFromControlPoints(bool alert_LPE)
{
Geom::PathBuilder builder;
+ //Refresh if is bspline some times -think on path change selection, this value get lost
+ isBSpline(true);
for (std::list<SubpathPtr>::iterator spi = _subpaths.begin(); spi != _subpaths.end(); ) {
SubpathPtr subpath = *spi;
if (subpath->empty()) {
@@ -1186,7 +1314,6 @@ void PathManipulator::_createGeometryFromControlPoints(bool alert_LPE)
}
NodeList::iterator prev = subpath->begin();
builder.moveTo(prev->position());
-
for (NodeList::iterator i = ++subpath->begin(); i != subpath->end(); ++i) {
build_segment(builder, prev.ptr(), i.ptr());
prev = i;
@@ -1207,11 +1334,20 @@ void PathManipulator::_createGeometryFromControlPoints(bool alert_LPE)
_spcurve->set_pathvector(pathv);
if (alert_LPE) {
/// \todo note that _path can be an Inkscape::LivePathEffect::Effect* too, kind of confusing, rework member naming?
- if (SP_IS_LPE_ITEM(_path) && _path->hasPathEffect()) {
- PathEffectList effect_list = _path->getEffectList();
- LivePathEffect::LPEPowerStroke *lpe_pwr = dynamic_cast<LivePathEffect::LPEPowerStroke*>( effect_list.front()->lpeobject->get_lpe() );
- if (lpe_pwr) {
- lpe_pwr->adjustForNewPath(pathv);
+ if (SP_IS_LPE_ITEM(_path) && _path->hasPathEffect()){
+ Inkscape::LivePathEffect::Effect* thisEffect = SP_LPE_ITEM(_path)->getPathEffectOfType(Inkscape::LivePathEffect::POWERSTROKE);
+ if(thisEffect){
+ LivePathEffect::LPEPowerStroke *lpe_pwr = dynamic_cast<LivePathEffect::LPEPowerStroke*>(thisEffect->getLPEObj()->get_lpe());
+ if (lpe_pwr) {
+ lpe_pwr->adjustForNewPath(pathv);
+ }
+ }
+ thisEffect = SP_LPE_ITEM(_path)->getPathEffectOfType(Inkscape::LivePathEffect::FILLET_CHAMFER);
+ if(thisEffect){
+ LivePathEffect::LPEFilletChamfer *lpe_fll = dynamic_cast<LivePathEffect::LPEFilletChamfer*>(thisEffect->getLPEObj()->get_lpe());
+ if (lpe_fll) {
+ lpe_fll->adjustForNewPath(pathv);
+ }
}
}
}
@@ -1419,6 +1555,12 @@ bool PathManipulator::_handleClicked(Handle *h, GdkEventButton *event)
return false;
}
+void PathManipulator::_selectionChangedM(std::vector<SelectableControlPoint *> pvec, bool selected) {
+ for (size_t n = 0, e = pvec.size(); n < e; ++n) {
+ _selectionChanged(pvec[n], selected);
+ }
+}
+
void PathManipulator::_selectionChanged(SelectableControlPoint *p, bool selected)
{
if (selected) ++_num_selected;
diff --git a/src/ui/tool/path-manipulator.h b/src/ui/tool/path-manipulator.h
index 7a13ce723..4d2bf4300 100644
--- a/src/ui/tool/path-manipulator.h
+++ b/src/ui/tool/path-manipulator.h
@@ -19,6 +19,7 @@
#include <boost/weak_ptr.hpp>
#include "ui/tool/node.h"
#include "ui/tool/manipulator.h"
+#include "live_effects/lpe-bspline.h"
struct SPCanvasItem;
class SPCurve;
@@ -95,6 +96,7 @@ public:
NodeList::iterator extremeNode(NodeList::iterator origin, bool search_selected,
bool search_unselected, bool closest);
+ int BSplineGetSteps() const;
// this is necessary for Tab-selection in MultiPathManipulator
SubpathList &subpathList() { return _subpaths; }
@@ -104,6 +106,12 @@ private:
typedef boost::shared_ptr<NodeList> SubpathPtr;
void _createControlPointsFromGeometry();
+
+ bool isBSpline(bool recalculate = false);
+ bool isBSpline() const;
+ double BSplineHandlePosition(Handle *h, Handle *h2 = NULL);
+ Geom::Point BSplineHandleReposition(Handle *h, Handle *h2 = NULL);
+ Geom::Point BSplineHandleReposition(Handle *h, double pos);
void _createGeometryFromControlPoints(bool alert_LPE = false);
unsigned _deleteStretch(NodeList::iterator first, NodeList::iterator last, bool keep_shape);
std::string _createTypeString();
@@ -114,7 +122,8 @@ private:
Glib::ustring _nodetypesKey();
Inkscape::XML::Node *_getXMLNode();
- void _selectionChanged(SelectableControlPoint *p, bool selected);
+ void _selectionChangedM(std::vector<SelectableControlPoint *> pvec, bool selected);
+ void _selectionChanged(SelectableControlPoint * p, bool selected);
bool _nodeClicked(Node *, GdkEventButton *);
void _handleGrabbed();
bool _handleClicked(Handle *, GdkEventButton *);
@@ -145,6 +154,7 @@ private:
bool _show_path_direction;
bool _live_outline;
bool _live_objects;
+ bool _is_bspline;
Glib::ustring _lpe_key;
friend class PathManipulatorObserver;
diff --git a/src/ui/tool/selectable-control-point.h b/src/ui/tool/selectable-control-point.h
index 8acfc1168..362d4addc 100644
--- a/src/ui/tool/selectable-control-point.h
+++ b/src/ui/tool/selectable-control-point.h
@@ -28,6 +28,7 @@ public:
virtual Geom::Rect bounds() const {
return Geom::Rect(position(), position());
}
+ friend class NodeList;
protected:
diff --git a/src/tools-switch.cpp b/src/ui/tools-switch.cpp
index fe9d32f43..47b9d2832 100644
--- a/src/tools-switch.cpp
+++ b/src/ui/tools-switch.cpp
@@ -4,16 +4,14 @@
* Authors:
* bulia byak <buliabyak@users.sf.net>
* Josh Andler <scislac@users.sf.net>
+ * Jon A. Cruz <jon@joncruz.org>
*
* Copyright (C) 2003-2007 authors
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
+#include <gtkmm.h> // prevents deprecation warnings
#include <cstring>
#include <string>
@@ -25,40 +23,44 @@
#include <xml/repr.h>
-#include "ui/tools/select-tool.h"
-#include "ui/tools/node-tool.h"
-#include "ui/tools/tweak-tool.h"
-#include "ui/tools/spray-tool.h"
-#include "sp-path.h"
-#include "ui/tools/rect-tool.h"
-#include "sp-rect.h"
-#include "ui/tools/box3d-tool.h"
+#include "ui/tools-switch.h"
+
#include "box3d.h"
-#include "ui/tools/arc-tool.h"
#include "sp-ellipse.h"
-#include "ui/tools/tweak-tool.h"
+#include "sp-flowtext.h"
+#include "sp-offset.h"
+#include "sp-path.h"
+#include "sp-rect.h"
#include "sp-star.h"
-#include "ui/tools/spiral-tool.h"
#include "sp-spiral.h"
+#include "sp-text.h"
+
+// TODO: How many of these are actually needed?
+#include "ui/tools/arc-tool.h"
+#include "ui/tools/box3d-tool.h"
#include "ui/tools/calligraphic-tool.h"
+#include "ui/tools/connector-tool.h"
+#include "ui/tools/dropper-tool.h"
#include "ui/tools/eraser-tool.h"
+#include "ui/tools/flood-tool.h"
+#include "ui/tools/gradient-tool.h"
+#include "ui/tools/lpe-tool.h"
+#include "ui/tools/measure-tool.h"
+#include "ui/tools/mesh-tool.h"
+#include "ui/tools/node-tool.h"
#include "ui/tools/pen-tool.h"
#include "ui/tools/pencil-tool.h"
-#include "ui/tools/lpe-tool.h"
+#include "ui/tools/rect-tool.h"
+#include "ui/tools/select-tool.h"
+#include "ui/tools/spiral-tool.h"
+#include "ui/tools/spray-tool.h"
#include "ui/tools/text-tool.h"
-#include "sp-text.h"
-#include "sp-flowtext.h"
-#include "ui/tools/gradient-tool.h"
-#include "ui/tools/mesh-tool.h"
+#include "ui/tools/tweak-tool.h"
#include "ui/tools/zoom-tool.h"
-#include "ui/tools/measure-tool.h"
-#include "ui/tools/dropper-tool.h"
-#include "ui/tools/connector-tool.h"
-#include "ui/tools/flood-tool.h"
-#include "sp-offset.h"
+
#include "message-context.h"
-#include "tools-switch.h"
+using Inkscape::UI::Tools::ToolBase;
static char const *const tool_names[] = {
NULL,
@@ -86,6 +88,8 @@ static char const *const tool_names[] = {
"/tools/lpetool",
NULL
};
+
+// TODO: HEY! these belong to the tools themselves!
static char const *const tool_msg[] = {
NULL,
N_("<b>Click</b> to Select and Transform objects, <b>Drag</b> to select many objects."),
@@ -129,9 +133,11 @@ int
tools_isactive(SPDesktop *dt, unsigned num)
{
g_assert( num < G_N_ELEMENTS(tool_names) );
- if (SP_IS_EVENT_CONTEXT(dt->event_context))
+ if (dynamic_cast<ToolBase *>(dt->event_context)) {
return dt->event_context->pref_observer->observed_path == tool_names[num];
- else return FALSE;
+ } else {
+ return FALSE;
+ }
}
int
@@ -158,27 +164,27 @@ tools_switch(SPDesktop *dt, int num)
void tools_switch_by_item(SPDesktop *dt, SPItem *item, Geom::Point const p)
{
- if (SP_IS_RECT(item)) {
+ if (dynamic_cast<SPRect *>(item)) {
tools_switch(dt, TOOLS_SHAPES_RECT);
- } else if (SP_IS_BOX3D(item)) {
+ } else if (dynamic_cast<SPBox3D *>(item)) {
tools_switch(dt, TOOLS_SHAPES_3DBOX);
- } else if (SP_IS_GENERICELLIPSE(item)) {
+ } else if (dynamic_cast<SPGenericEllipse *>(item)) {
tools_switch(dt, TOOLS_SHAPES_ARC);
- } else if (SP_IS_STAR(item)) {
+ } else if (dynamic_cast<SPStar *>(item)) {
tools_switch(dt, TOOLS_SHAPES_STAR);
- } else if (SP_IS_SPIRAL(item)) {
+ } else if (dynamic_cast<SPSpiral *>(item)) {
tools_switch(dt, TOOLS_SHAPES_SPIRAL);
- } else if (SP_IS_PATH(item)) {
+ } else if (dynamic_cast<SPPath *>(item)) {
if (Inkscape::UI::Tools::cc_item_is_connector(item)) {
tools_switch(dt, TOOLS_CONNECTOR);
}
else {
tools_switch(dt, TOOLS_NODES);
}
- } else if (SP_IS_TEXT(item) || SP_IS_FLOWTEXT(item)) {
+ } else if (dynamic_cast<SPText *>(item) || dynamic_cast<SPFlowtext *>(item)) {
tools_switch(dt, TOOLS_TEXT);
- sp_text_context_place_cursor_at (SP_TEXT_CONTEXT(dt->event_context), SP_OBJECT(item), p);
- } else if (SP_IS_OFFSET(item)) {
+ sp_text_context_place_cursor_at (SP_TEXT_CONTEXT(dt->event_context), item, p);
+ } else if (dynamic_cast<SPOffset *>(item)) {
tools_switch(dt, TOOLS_NODES);
}
}
diff --git a/src/tools-switch.h b/src/ui/tools-switch.h
index 280837e87..280837e87 100644
--- a/src/tools-switch.h
+++ b/src/ui/tools-switch.h
diff --git a/src/ui/tools/arc-tool.cpp b/src/ui/tools/arc-tool.cpp
index 43f8eb9e1..4f64ade25 100644
--- a/src/ui/tools/arc-tool.cpp
+++ b/src/ui/tools/arc-tool.cpp
@@ -40,7 +40,7 @@
#include "desktop-style.h"
#include "context-fns.h"
#include "verbs.h"
-#include "shape-editor.h"
+#include "ui/shape-editor.h"
#include "ui/tools/tool-base.h"
#include "ui/tools/arc-tool.h"
@@ -48,7 +48,7 @@
using Inkscape::DocumentUndo;
-#include "tool-factory.h"
+#include "ui/tool-factory.h"
namespace Inkscape {
namespace UI {
@@ -102,8 +102,8 @@ ArcTool::~ArcTool() {
* destroys old and creates new knotholder.
*/
void ArcTool::selection_changed(Inkscape::Selection* selection) {
- this->shape_editor->unset_item(SH_KNOTHOLDER);
- this->shape_editor->set_item(selection->singleItem(), SH_KNOTHOLDER);
+ this->shape_editor->unset_item();
+ this->shape_editor->set_item(selection->singleItem());
}
void ArcTool::setup() {
@@ -115,7 +115,7 @@ void ArcTool::setup() {
SPItem *item = sp_desktop_selection(this->desktop)->singleItem();
if (item) {
- this->shape_editor->set_item(item, SH_KNOTHOLDER);
+ this->shape_editor->set_item(item);
}
this->sel_changed_connection.disconnect();
diff --git a/src/ui/tools/arc-tool.h b/src/ui/tools/arc-tool.h
index c4c67660d..55cbaf78c 100644
--- a/src/ui/tools/arc-tool.h
+++ b/src/ui/tools/arc-tool.h
@@ -30,7 +30,7 @@ namespace Inkscape {
}
#define SP_ARC_CONTEXT(obj) (dynamic_cast<Inkscape::UI::Tools::ArcTool*>((Inkscape::UI::Tools::ToolBase*)obj))
-#define SP_IS_ARC_CONTEXT(obj) (dynamic_cast<const Inkscape::UI::Tools::ArcTool*>(const Inkscape::UI::Tools::ToolBase*(obj)) != NULL)
+#define SP_IS_ARC_CONTEXT(obj) (dynamic_cast<const Inkscape::UI::Tools::ArcTool*>(obj) != NULL)
namespace Inkscape {
namespace UI {
diff --git a/src/ui/tools/box3d-tool.cpp b/src/ui/tools/box3d-tool.cpp
index e00894d55..0a20a0842 100644
--- a/src/ui/tools/box3d-tool.cpp
+++ b/src/ui/tools/box3d-tool.cpp
@@ -47,12 +47,12 @@
#include "box3d-side.h"
#include "document-private.h"
#include "line-geometry.h"
-#include "shape-editor.h"
+#include "ui/shape-editor.h"
#include "verbs.h"
using Inkscape::DocumentUndo;
-#include "tool-factory.h"
+#include "ui/tool-factory.h"
namespace Inkscape {
namespace UI {
@@ -112,8 +112,8 @@ Box3dTool::~Box3dTool() {
* destroys old and creates new knotholder.
*/
void Box3dTool::selection_changed(Inkscape::Selection* selection) {
- this->shape_editor->unset_item(SH_KNOTHOLDER);
- this->shape_editor->set_item(selection->singleItem(), SH_KNOTHOLDER);
+ this->shape_editor->unset_item();
+ this->shape_editor->set_item(selection->singleItem());
if (selection->perspList().size() == 1) {
// selecting a single box changes the current perspective
@@ -147,7 +147,7 @@ void Box3dTool::setup() {
SPItem *item = sp_desktop_selection(this->desktop)->singleItem();
if (item) {
- this->shape_editor->set_item(item, SH_KNOTHOLDER);
+ this->shape_editor->set_item(item);
}
this->sel_changed_connection.disconnect();
diff --git a/src/ui/tools/calligraphic-tool.cpp b/src/ui/tools/calligraphic-tool.cpp
index 64097e834..d297fe5e1 100644
--- a/src/ui/tools/calligraphic-tool.cpp
+++ b/src/ui/tools/calligraphic-tool.cpp
@@ -82,7 +82,7 @@ using Inkscape::DocumentUndo;
#define DYNA_MIN_WIDTH 1.0e-6
-#include "tool-factory.h"
+#include "ui/tool-factory.h"
namespace Inkscape {
namespace UI {
diff --git a/src/ui/tools/connector-tool.cpp b/src/ui/tools/connector-tool.cpp
index d1355e807..7b5c84c16 100644
--- a/src/ui/tools/connector-tool.cpp
+++ b/src/ui/tools/connector-tool.cpp
@@ -109,7 +109,7 @@
using Inkscape::DocumentUndo;
-#include "tool-factory.h"
+#include "ui/tool-factory.h"
namespace Inkscape {
namespace UI {
diff --git a/src/ui/tools/dropper-tool.cpp b/src/ui/tools/dropper-tool.cpp
index 99d42a211..6c55f7484 100644
--- a/src/ui/tools/dropper-tool.cpp
+++ b/src/ui/tools/dropper-tool.cpp
@@ -52,7 +52,7 @@ using Inkscape::DocumentUndo;
static GdkCursor *cursor_dropper_fill = NULL;
static GdkCursor *cursor_dropper_stroke = NULL;
-#include "tool-factory.h"
+#include "ui/tool-factory.h"
namespace Inkscape {
namespace UI {
diff --git a/src/ui/tools/eraser-tool.cpp b/src/ui/tools/eraser-tool.cpp
index 4106785e7..bf4015b4c 100644
--- a/src/ui/tools/eraser-tool.cpp
+++ b/src/ui/tools/eraser-tool.cpp
@@ -84,7 +84,7 @@ using Inkscape::DocumentUndo;
#define DRAG_DEFAULT 1.0
#define DRAG_MAX 1.0
-#include "tool-factory.h"
+#include "ui/tool-factory.h"
namespace Inkscape {
namespace UI {
diff --git a/src/ui/tools/flood-tool.cpp b/src/ui/tools/flood-tool.cpp
index d74848dc6..5745fc9cc 100644
--- a/src/ui/tools/flood-tool.cpp
+++ b/src/ui/tools/flood-tool.cpp
@@ -50,7 +50,7 @@
#include "preferences.h"
#include "rubberband.h"
#include "selection.h"
-#include "shape-editor.h"
+#include "ui/shape-editor.h"
#include "sp-defs.h"
#include "sp-item.h"
#include "splivarot.h"
@@ -74,7 +74,7 @@ using Inkscape::Display::ExtractARGB32;
using Inkscape::Display::ExtractRGB32;
using Inkscape::Display::AssembleARGB32;
-#include "tool-factory.h"
+#include "ui/tool-factory.h"
namespace Inkscape {
namespace UI {
@@ -119,8 +119,8 @@ FloodTool::~FloodTool() {
* destroys old and creates new knotholder.
*/
void FloodTool::selection_changed(Inkscape::Selection* selection) {
- this->shape_editor->unset_item(SH_KNOTHOLDER);
- this->shape_editor->set_item(selection->singleItem(), SH_KNOTHOLDER);
+ this->shape_editor->unset_item();
+ this->shape_editor->set_item(selection->singleItem());
}
void FloodTool::setup() {
@@ -130,7 +130,7 @@ void FloodTool::setup() {
SPItem *item = sp_desktop_selection(this->desktop)->singleItem();
if (item) {
- this->shape_editor->set_item(item, SH_KNOTHOLDER);
+ this->shape_editor->set_item(item);
}
this->sel_changed_connection.disconnect();
diff --git a/src/ui/tools/flood-tool.h b/src/ui/tools/flood-tool.h
index 3ed670e8b..5104a42e9 100644
--- a/src/ui/tools/flood-tool.h
+++ b/src/ui/tools/flood-tool.h
@@ -11,9 +11,7 @@
* Released under GNU GPL
*/
-#include <stddef.h>
-#include <sigc++/sigc++.h>
-#include <gtk/gtk.h>
+#include <sigc++/connection.h>
#include "ui/tools/tool-base.h"
#define SP_FLOOD_CONTEXT(obj) (dynamic_cast<Inkscape::UI::Tools::FloodTool*>((Inkscape::UI::Tools::ToolBase*)obj))
diff --git a/src/ui/tools/freehand-base.cpp b/src/ui/tools/freehand-base.cpp
index 4f2ec6c48..68b57dc90 100644
--- a/src/ui/tools/freehand-base.cpp
+++ b/src/ui/tools/freehand-base.cpp
@@ -31,7 +31,7 @@
#include "desktop-handles.h"
#include "desktop-style.h"
#include "document.h"
-#include "draw-anchor.h"
+#include "ui/draw-anchor.h"
#include "macros.h"
#include "message-stack.h"
#include "ui/tools/pen-tool.h"
@@ -45,6 +45,7 @@
#include "live_effects/lpe-powerstroke.h"
#include "style.h"
#include "ui/control-manager.h"
+// clipboard support
#include "ui/clipboard.h"
#include "ui/tools/freehand-base.h"
@@ -80,6 +81,7 @@ FreehandBase::FreehandBase(gchar const *const *cursor_shape, gint hot_x, gint ho
, red_color(0xff00007f)
, blue_color(0x0000ff7f)
, green_color(0x00ff007f)
+ , highlight_color(0x0000007f)
, red_bpath(NULL)
, red_curve(NULL)
, blue_bpath(NULL)
@@ -91,6 +93,7 @@ FreehandBase::FreehandBase(gchar const *const *cursor_shape, gint hot_x, gint ho
, white_item(NULL)
, white_curves(NULL)
, white_anchors(NULL)
+ , overwriteCurve(NULL)
, sa(NULL)
, ea(NULL)
, waiting_LPE_type(Inkscape::LivePathEffect::INVALID_LPE)
@@ -146,6 +149,9 @@ void FreehandBase::setup() {
this->green_anchor = NULL;
this->green_closed = FALSE;
+ // Create start anchor alternative curve
+ this->overwriteCurve = new SPCurve();
+
this->attach = TRUE;
spdc_attach_selection(this, this->selection);
}
@@ -227,6 +233,32 @@ static void spdc_apply_powerstroke_shape(const std::vector<Geom::Point> & points
Effect* lpe = SP_LPE_ITEM(item)->getCurrentLPE();
static_cast<LPEPowerStroke*>(lpe)->offset_points.param_set_and_write_new_value(points);
+ // find out stroke width (TODO: is there an easier way??)
+ SPDesktop *desktop = dc->desktop;
+ Inkscape::XML::Document *xml_doc = desktop->doc()->getReprDoc();
+ Inkscape::XML::Node *repr = xml_doc->createElement("svg:path");
+ Inkscape::GC::release(repr);
+
+ char const* tool = SP_IS_PEN_CONTEXT(dc) ? "/tools/freehand/pen" : "/tools/freehand/pencil";
+
+ // apply the tool's current style
+ sp_desktop_apply_style_tool(desktop, repr, tool, false);
+
+ double stroke_width = 1.0;
+ char const *style_str = NULL;
+ style_str = repr->attribute("style");
+ if (style_str) {
+ SPStyle *style = sp_style_new(SP_ACTIVE_DOCUMENT);
+ sp_style_merge_from_style_string(style, style_str);
+ stroke_width = style->stroke_width.computed;
+ style->stroke_width.computed = 0;
+ sp_style_unref(style);
+ }
+
+ std::ostringstream s;
+ s.imbue(std::locale::classic());
+ s << "0," << stroke_width / 2.;
+
// write powerstroke parameters:
lpe->getRepr()->setAttribute("start_linecap_type", "zerowidth");
lpe->getRepr()->setAttribute("end_linecap_type", "zerowidth");
@@ -234,6 +266,7 @@ static void spdc_apply_powerstroke_shape(const std::vector<Geom::Point> & points
lpe->getRepr()->setAttribute("sort_points", "true");
lpe->getRepr()->setAttribute("interpolator_type", "CubicBezierJohan");
lpe->getRepr()->setAttribute("interpolator_beta", "0.2");
+ lpe->getRepr()->setAttribute("offset_points", s.str().c_str());
}
@@ -241,7 +274,9 @@ static void spdc_apply_bend_shape(gchar const *svgd, FreehandBase *dc, SPItem *i
{
using namespace Inkscape::LivePathEffect;
- Effect::createAndApply(BEND_PATH, dc->desktop->doc(), item);
+ if(!SP_LPE_ITEM(item)->hasPathEffectOfType(BEND_PATH)){
+ Effect::createAndApply(BEND_PATH, dc->desktop->doc(), item);
+ }
Effect* lpe = SP_LPE_ITEM(item)->getCurrentLPE();
// write bend parameters:
@@ -261,37 +296,41 @@ static void spdc_check_for_and_apply_waiting_LPE(FreehandBase *dc, SPItem *item,
if (prefs->getInt(tool_name(dc) + "/freehand-mode", 0) == 1) {
Effect::createAndApply(SPIRO, dc->desktop->doc(), item);
}
+ //add the bspline node in the waiting effects
+ if (prefs->getInt(tool_name(dc) + "/freehand-mode", 0) == 2) {
+ Effect::createAndApply(BSPLINE, dc->desktop->doc(), item);
+ }
+
+ //Store the clipboard path to apply in the future without the use of clipboard
- //Store the clipboard path to apply in the future without the use of clipboard
static Geom::PathVector previous_shape_pathv;
- //Last shape applied type "-1" means "no previous shape"
- int shape = prefs->getInt(tool_name(dc) + "/shape", 0);
+ enum shapeType { NONE, TRIANGLE_IN, TRIANGLE_OUT, ELLIPSE, CLIPBOARD, BEND_CLIPBOARD, LAST_APPLIED };
+ static shapeType previous_shape_type = NONE;
+
+
+ shapeType shape = (shapeType)prefs->getInt(tool_name(dc) + "/shape", 0);
bool shape_applied = false;
SPCSSAttr *css_item = sp_css_attr_from_object(item, SP_STYLE_FLAG_ALWAYS);
const char *cstroke = sp_repr_css_property(css_item, "stroke", "none");
- static SPItem *itemEnd;
+ static SPItem *bendItem;
#define SHAPE_LENGTH 10
#define SHAPE_HEIGHT 10
- if(shape == 6){
+
+ if(shape == LAST_APPLIED){
+
shape = previous_shape_type;
- if(shape == 4){
- shape = 6;
- }
- if(shape == 5){
- shape = 7;
- }
- if(previous_shape_type == -1){
- shape = 0;
+ if(shape == CLIPBOARD || shape == BEND_CLIPBOARD){
+ shape = LAST_APPLIED;
}
}
switch (shape) {
- case 0:
+ case NONE:
// don't apply any shape
break;
- case 1:
+ case TRIANGLE_IN:
{
// "triangle in"
std::vector<Geom::Point> points(1);
@@ -301,7 +340,7 @@ static void spdc_check_for_and_apply_waiting_LPE(FreehandBase *dc, SPItem *item,
shape_applied = true;
break;
}
- case 2:
+ case TRIANGLE_OUT:
{
// "triangle out"
guint curve_length = curve->get_segment_count();
@@ -312,7 +351,7 @@ static void spdc_check_for_and_apply_waiting_LPE(FreehandBase *dc, SPItem *item,
shape_applied = true;
break;
}
- case 3:
+ case ELLIPSE:
{
// "ellipse"
SPCurve *c = new SPCurve();
@@ -329,7 +368,7 @@ static void spdc_check_for_and_apply_waiting_LPE(FreehandBase *dc, SPItem *item,
shape_applied = true;
break;
}
- case 4:
+ case CLIPBOARD:
{
// take shape from clipboard; TODO: catch the case where clipboard is empty
Effect::createAndApply(PATTERN_ALONG_PATH, dc->desktop->doc(), item);
@@ -342,74 +381,56 @@ static void spdc_check_for_and_apply_waiting_LPE(FreehandBase *dc, SPItem *item,
shape_applied = true;
break;
}
- case 5:
+ case BEND_CLIPBOARD:
{
- // take shape from clipboard; TODO: catch the case where clipboard is empty
Inkscape::UI::ClipboardManager *cm = Inkscape::UI::ClipboardManager::get();
if(cm->paste(SP_ACTIVE_DESKTOP,false) == true){
gchar const *svgd = item->getRepr()->attribute("d");
- item->deleteObject();
- if(itemEnd != NULL && itemEnd->getRepr() != NULL)
- itemEnd->deleteObject();
- Inkscape::Selection *selection = sp_desktop_selection(dc->desktop);
- sp_selection_group(selection, dc->desktop);
- GSList *items = const_cast<GSList *>(selection->itemList());
- SPObject *obj = reinterpret_cast<SPObject *>(g_slist_nth_data(items,0));
- if(SP_IS_OBJECT(obj)){
- itemEnd = SP_ITEM(obj);
- sp_selection_duplicate(dc->desktop);
- itemEnd->setExplicitlyHidden(true);
- items = const_cast<GSList *>(selection->itemList());
- obj = reinterpret_cast<SPObject *>(g_slist_nth_data(items,0));
- if(SP_IS_OBJECT(obj)){
- spdc_apply_bend_shape(svgd, dc, SP_ITEM(obj));
- SP_ITEM(obj)->setExplicitlyHidden(false);
- selection->set(SP_ITEM(obj),true);
- }
- }
- }
- break;
- }
- case 6:
- {
- if(previous_shape_pathv.size() != 0){
- SPCurve * c = new SPCurve();
- c->set_pathvector(previous_shape_pathv);
- spdc_paste_curve_as_freehand_shape(c, dc, item);
- c->unref();
-
- shape_applied = true;
+ item->getRepr()->setAttribute("d", "");
+ bendItem = dc->selection->singleItem();
+ item->setSuccessor(bendItem);
+ item = bendItem;
+ g_assert(item != NULL);
+ spdc_apply_bend_shape(svgd, dc, item);
+ dc->selection->set(item,true);
}
-
- shape = previous_shape_type;
break;
}
- case 7:
+ case LAST_APPLIED:
{
- // take shape from clipboard; TODO: catch the case where clipboard is empty
- if(itemEnd != NULL && itemEnd->getRepr() != NULL){
- gchar const *svgd = item->getRepr()->attribute("d");
- item->deleteObject();
- Inkscape::Selection *selection = sp_desktop_selection(dc->desktop);
- selection->add(SP_OBJECT(itemEnd));
- sp_selection_duplicate(dc->desktop);
- selection->remove(SP_OBJECT(itemEnd));
- GSList *items = const_cast<GSList *>(selection->itemList());
- SPObject *obj = reinterpret_cast<SPObject *>(g_slist_nth_data(items,0));
- if(SP_IS_OBJECT(obj)){
- SP_ITEM(obj)->getRepr()->setAttribute("inkscape:path-effect", NULL);
- spdc_apply_bend_shape(svgd, dc, SP_ITEM(obj));
- SP_ITEM(obj)->setExplicitlyHidden(false);
- selection->set(SP_ITEM(obj),true);
+ if(previous_shape_type == CLIPBOARD){
+ if(previous_shape_pathv.size() != 0){
+ SPCurve * c = new SPCurve();
+ c->set_pathvector(previous_shape_pathv);
+ spdc_paste_curve_as_freehand_shape(c, dc, item);
+ c->unref();
+
+ shape_applied = true;
+ }
+ } else {
+ if(bendItem != NULL && bendItem->getRepr() != NULL){
+ gchar const *svgd = item->getRepr()->attribute("d");
+ item->getRepr()->setAttribute("d", "");
+ Inkscape::Selection *selection = sp_desktop_selection(dc->desktop);
+ selection->add(SP_OBJECT(bendItem));
+ sp_selection_duplicate(dc->desktop);
+ selection->remove(SP_OBJECT(bendItem));
+ bendItem = dc->selection->singleItem();
+ item->setSuccessor(bendItem);
+ item = bendItem;
+ g_assert(item != NULL);
+ spdc_apply_bend_shape(svgd, dc, item);
+ dc->selection->set(item,true);
}
}
- shape = previous_shape_type;
break;
}
default:
break;
}
- previous_shape_type = shape;
+ if(shape != LAST_APPLIED){
+ previous_shape_type = shape;
+ }
if (shape_applied) {
// apply original stroke color as fill and unset stroke; then return
SPCSSAttr *css = sp_repr_css_attr_new();
@@ -424,8 +445,9 @@ static void spdc_check_for_and_apply_waiting_LPE(FreehandBase *dc, SPItem *item,
sp_repr_css_attr_unref(css);
return;
}
- if(previous_shape_type == 5)return;
-
+ if(previous_shape_type == 5 || previous_shape_type == 6 || previous_shape_type == 7){
+ return;
+ }
if (dc->waiting_LPE_type != INVALID_LPE) {
Effect::createAndApply(dc->waiting_LPE_type, dc->desktop->doc(), item);
dc->waiting_LPE_type = INVALID_LPE;
@@ -564,7 +586,7 @@ void spdc_concat_colors_and_flush(FreehandBase *dc, gboolean forceclosed)
{
// Concat RBG
SPCurve *c = dc->green_curve;
-
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
// Green
dc->green_curve = new SPCurve();
while (dc->green_bpaths) {
@@ -611,9 +633,20 @@ void spdc_concat_colors_and_flush(FreehandBase *dc, gboolean forceclosed)
if (dc->sa->start && !(dc->sa->curve->is_closed()) ) {
c = reverse_then_unref(c);
}
- dc->sa->curve->append_continuous(c, 0.0625);
- c->unref();
- dc->sa->curve->closepath_current();
+ if(prefs->getInt(tool_name(dc) + "/freehand-mode", 0) == 1 ||
+ prefs->getInt(tool_name(dc) + "/freehand-mode", 0) == 2){
+ dc->overwriteCurve->append_continuous(c, 0.0625);
+ c->unref();
+ dc->overwriteCurve->closepath_current();
+ if(dc->sa){
+ dc->white_curves = g_slist_remove(dc->white_curves, dc->sa->curve);
+ dc->white_curves = g_slist_append(dc->white_curves, dc->overwriteCurve);
+ }
+ }else{
+ dc->sa->curve->append_continuous(c, 0.0625);
+ c->unref();
+ dc->sa->curve->closepath_current();
+ }
spdc_flush_white(dc, NULL);
return;
}
@@ -622,6 +655,10 @@ void spdc_concat_colors_and_flush(FreehandBase *dc, gboolean forceclosed)
if (dc->sa) {
SPCurve *s = dc->sa->curve;
dc->white_curves = g_slist_remove(dc->white_curves, s);
+ if(prefs->getInt(tool_name(dc) + "/freehand-mode", 0) == 1 ||
+ prefs->getInt(tool_name(dc) + "/freehand-mode", 0) == 2){
+ s = dc->overwriteCurve;
+ }
if (dc->sa->start) {
s = reverse_then_unref(s);
}
@@ -634,6 +671,25 @@ void spdc_concat_colors_and_flush(FreehandBase *dc, gboolean forceclosed)
if (!dc->ea->start) {
e = reverse_then_unref(e);
}
+ if(prefs->getInt(tool_name(dc) + "/freehand-mode", 0) == 1 ||
+ prefs->getInt(tool_name(dc) + "/freehand-mode", 0) == 2){
+ e = reverse_then_unref(e);
+ Geom::CubicBezier const * cubic = dynamic_cast<Geom::CubicBezier const*>(&*e->last_segment());
+ SPCurve *lastSeg = new SPCurve();
+ if(cubic){
+ lastSeg->moveto((*cubic)[0]);
+ lastSeg->curveto((*cubic)[1],(*cubic)[3],(*cubic)[3]);
+ if( e->get_segment_count() == 1){
+ e = lastSeg;
+ }else{
+ //we eliminate the last segment
+ e->backspace();
+ //and we add it again with the recreation
+ e->append_continuous(lastSeg, 0.0625);
+ }
+ }
+ e = reverse_then_unref(e);
+ }
c->append_continuous(e, 0.0625);
e->unref();
}
@@ -647,7 +703,6 @@ void spdc_concat_colors_and_flush(FreehandBase *dc, gboolean forceclosed)
static void spdc_flush_white(FreehandBase *dc, SPCurve *gc)
{
SPCurve *c;
-
if (dc->white_curves) {
g_assert(dc->white_item);
c = SPCurve::concat(dc->white_curves);
@@ -677,6 +732,7 @@ static void spdc_flush_white(FreehandBase *dc, SPCurve *gc)
bool has_lpe = false;
Inkscape::XML::Node *repr;
+
if (dc->white_item) {
repr = dc->white_item->getRepr();
has_lpe = SP_LPE_ITEM(dc->white_item)->hasPathEffectRecursive();
@@ -700,12 +756,17 @@ static void spdc_flush_white(FreehandBase *dc, SPCurve *gc)
// we finished the path; now apply any waiting LPEs or freehand shapes
spdc_check_for_and_apply_waiting_LPE(dc, item, c);
-
- if(previous_shape_type != 5) dc->selection->set(repr);
+ if(previous_shape_type == -1 || previous_shape_type == 5 || previous_shape_type == 6){
+ return;
+ }
+ if(previous_shape_type != 7){
+ dc->selection->set(repr);
+ }
+
Inkscape::GC::release(repr);
- if(previous_shape_type != 5) item->transform = SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse();
- if(previous_shape_type != 5) item->doWriteTransform(item->getRepr(), item->transform, NULL, true);
- if(previous_shape_type != 5) item->updateRepr();
+ item->transform = SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse();
+ item->updateRepr();
+ item->doWriteTransform(item->getRepr(), item->transform, NULL, true);
}
DocumentUndo::done(doc, SP_IS_PEN_CONTEXT(dc)? SP_VERB_CONTEXT_PEN : SP_VERB_CONTEXT_PENCIL,
@@ -740,7 +801,6 @@ SPDrawAnchor *spdc_test_inside(FreehandBase *dc, Geom::Point p)
active = na;
}
}
-
return active;
}
diff --git a/src/ui/tools/freehand-base.h b/src/ui/tools/freehand-base.h
index 5a4b91800..6b4265215 100644
--- a/src/ui/tools/freehand-base.h
+++ b/src/ui/tools/freehand-base.h
@@ -55,6 +55,7 @@ public:
guint32 red_color;
guint32 blue_color;
guint32 green_color;
+ guint32 highlight_color;
// Red
SPCanvasItem *red_bpath;
@@ -75,12 +76,17 @@ public:
GSList *white_curves;
GSList *white_anchors;
+ //ALternative curve to use on continuing exisiting curve in case of bspline or spirolive
+ //because usigh anchor curves give memory and random bugs, - and obscure code- in some plataform reported by su_v in mac
+ SPCurve *overwriteCurve;
+
// Start anchor
SPDrawAnchor *sa;
// End anchor
SPDrawAnchor *ea;
+
/* type of the LPE that is to be applied automatically to a finished path (if any) */
Inkscape::LivePathEffect::EffectType waiting_LPE_type;
diff --git a/src/ui/tools/gradient-tool.cpp b/src/ui/tools/gradient-tool.cpp
index a0bbfbaf1..9c853917e 100644
--- a/src/ui/tools/gradient-tool.cpp
+++ b/src/ui/tools/gradient-tool.cpp
@@ -51,7 +51,7 @@
using Inkscape::DocumentUndo;
-#include "tool-factory.h"
+#include "ui/tool-factory.h"
namespace Inkscape {
namespace UI {
@@ -213,17 +213,20 @@ sp_gradient_context_is_over_line (GradientTool *rc, SPItem *item, Geom::Point ev
//Translate mouse point into proper coord system
rc->mousepoint_doc = desktop->w2d(event_p);
- SPCtrlLine* line = SP_CTRLLINE(item);
+ if (SP_IS_CTRLLINE(item)) {
+ SPCtrlLine* line = SP_CTRLLINE(item);
- Geom::LineSegment ls(line->s, line->e);
- Geom::Point nearest = ls.pointAt(ls.nearestPoint(rc->mousepoint_doc));
- double dist_screen = Geom::L2 (rc->mousepoint_doc - nearest) * desktop->current_zoom();
+ Geom::LineSegment ls(line->s, line->e);
+ Geom::Point nearest = ls.pointAt(ls.nearestPoint(rc->mousepoint_doc));
+ double dist_screen = Geom::L2 (rc->mousepoint_doc - nearest) * desktop->current_zoom();
- double tolerance = (double) SP_EVENT_CONTEXT(rc)->tolerance;
+ double tolerance = (double) SP_EVENT_CONTEXT(rc)->tolerance;
- bool close = (dist_screen < tolerance);
+ bool close = (dist_screen < tolerance);
- return close;
+ return close;
+ }
+ return false;
}
static std::vector<Geom::Point>
diff --git a/src/ui/tools/lpe-tool.cpp b/src/ui/tools/lpe-tool.cpp
index 9ab6d7814..1fd1ebf8c 100644
--- a/src/ui/tools/lpe-tool.cpp
+++ b/src/ui/tools/lpe-tool.cpp
@@ -28,7 +28,7 @@
#include "desktop.h"
#include "message-context.h"
#include "preferences.h"
-#include "shape-editor.h"
+#include "ui/shape-editor.h"
#include "selection.h"
#include "desktop-handles.h"
#include "document.h"
@@ -59,7 +59,7 @@ SubtoolEntry lpesubtools[] = {
};
-#include "tool-factory.h"
+#include "ui/tool-factory.h"
namespace Inkscape {
namespace UI {
@@ -129,8 +129,7 @@ void LpeTool::setup() {
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
if (item) {
- this->shape_editor->set_item(item, SH_NODEPATH);
- this->shape_editor->set_item(item, SH_KNOTHOLDER);
+ this->shape_editor->set_item(item);
}
if (prefs->getBool("/tools/lpetool/selcue")) {
@@ -146,9 +145,9 @@ void sp_lpetool_context_selection_changed(Inkscape::Selection *selection, gpoint
{
LpeTool *lc = SP_LPETOOL_CONTEXT(data);
- lc->shape_editor->unset_item(SH_KNOTHOLDER);
+ lc->shape_editor->unset_item();
SPItem *item = selection->singleItem();
- lc->shape_editor->set_item(item, SH_KNOTHOLDER);
+ lc->shape_editor->set_item(item);
}
void LpeTool::set(const Inkscape::Preferences::Entry& val) {
diff --git a/src/ui/tools/measure-tool.cpp b/src/ui/tools/measure-tool.cpp
index 2c85874bc..6b5cbeccd 100644
--- a/src/ui/tools/measure-tool.cpp
+++ b/src/ui/tools/measure-tool.cpp
@@ -49,7 +49,7 @@ using Inkscape::ControlManager;
using Inkscape::CTLINE_SECONDARY;
using Inkscape::Util::unit_table;
-#include "tool-factory.h"
+#include "ui/tool-factory.h"
namespace Inkscape {
namespace UI {
@@ -277,21 +277,13 @@ void MeasureTool::finish() {
// return ret;
//}
-static bool GeomPointSortPredicate(const Geom::Point& p1, const Geom::Point& p2)
+static void calculate_intersections(SPDesktop * /*desktop*/, SPItem* item, Geom::PathVector const &lineseg, SPCurve *curve, std::vector<double> &intersections)
{
- if (p1[Geom::Y] == p2[Geom::Y]) {
- return p1[Geom::X] < p2[Geom::X];
- } else {
- return p1[Geom::Y] < p2[Geom::Y];
- }
-}
-static void calculate_intersections(SPDesktop * /*desktop*/, SPItem* item, Geom::PathVector const &lineseg, SPCurve *curve, std::vector<Geom::Point> &intersections)
-{
curve->transform(item->i2doc_affine());
-
// Find all intersections of the control-line with this shape
Geom::CrossingSet cs = Geom::crossings(lineseg, curve->get_pathvector());
+ Geom::delete_duplicates(cs[0]);
// Reconstruct and store the points of intersection
for (Geom::Crossings::const_iterator m = cs[0].begin(); m != cs[0].end(); ++m) {
@@ -304,10 +296,11 @@ static void calculate_intersections(SPDesktop * /*desktop*/, SPItem* item, Geom:
item == doc->getItemAtPoint(desktop->dkey, lineseg[0].pointAt((*m).ta - eps), false, NULL)) ||
((*m).ta + eps < 1 &&
item == doc->getItemAtPoint(desktop->dkey, lineseg[0].pointAt((*m).ta + eps), false, NULL)) ) {
- intersections.push_back(intersection);
+ intersections.push_back((*m).ta);
}
#else
- intersections.push_back(lineseg[0].pointAt((*m).ta));
+ intersections.push_back((*m).ta);
+
#endif
}
}
@@ -441,28 +434,20 @@ bool MeasureTool::root_handler(GdkEvent* event) {
points.push_back(desktop->d2w(start_point + (i / NPOINTS) * (end_point - start_point)));
}
-// TODO: Felipe, why don't you simply iterate over all items, and test whether their bounding boxes intersect
-// with the measurement line, instead of interpolating? E.g. bbox_of_measurement_line.intersects(*bbox_of_item).
-// That's also how the object-snapper works, see _findCandidates() in object-snapper.cpp.
+ // TODO: Felipe, why don't you simply iterate over all items, and test whether their bounding boxes intersect
+ // with the measurement line, instead of interpolating over 800 points? E.g. bbox_of_measurement_line.intersects(*bbox_of_item).
+ // That's also how the object-snapper works, see _findCandidates() in object-snapper.cpp.
+
+ // TODO switch to a different variable name. The single letter 'l' is easy to misread.
//select elements crossed by line segment:
GSList *items = sp_desktop_document(desktop)->getItemsAtPoints(desktop->dkey, points);
- std::vector<Geom::Point> intersections;
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- bool ignore_1st_and_last = prefs->getBool("/tools/measure/ignore_1st_and_last", true);
-
- if (!ignore_1st_and_last) {
- intersections.push_back(desktop->dt2doc(start_point));
- }
-
- std::vector<LabelPlacement> placements;
-
- // TODO switch to a different variable name. The single letter 'l' is easy to misread.
+ std::vector<double> intersection_times;
for (GSList *l = items; l != NULL; l = l->next) {
SPItem *item = static_cast<SPItem*>(l->data);
if (SP_IS_SHAPE(item)) {
- calculate_intersections(desktop, item, lineseg, SP_SHAPE(item)->getCurve(), intersections);
+ calculate_intersections(desktop, item, lineseg, SP_SHAPE(item)->getCurve(), intersection_times);
} else {
if (SP_IS_TEXT(item) || SP_IS_FLOWTEXT(item)) {
Inkscape::Text::Layout::iterator iter = te_get_layout(item)->begin();
@@ -486,7 +471,7 @@ bool MeasureTool::root_handler(GdkEvent* event) {
curve->transform(item->i2doc_affine());
- calculate_intersections(desktop, item, lineseg, curve, intersections);
+ calculate_intersections(desktop, item, lineseg, curve, intersection_times);
if (iter == te_get_layout(item)->end()) {
break;
@@ -496,13 +481,10 @@ bool MeasureTool::root_handler(GdkEvent* event) {
}
}
- if (!ignore_1st_and_last) {
- intersections.push_back(desktop->dt2doc(end_point));
- }
-
- //sort intersections
- if (intersections.size() > 2) {
- std::sort(intersections.begin(), intersections.end(), GeomPointSortPredicate);
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ if (!prefs->getBool("/tools/measure/ignore_1st_and_last", true)) {
+ intersection_times.push_back(0);
+ intersection_times.push_back(1);
}
Glib::ustring unit_name = prefs->getString("/tools/measure/unit");
@@ -516,6 +498,13 @@ bool MeasureTool::root_handler(GdkEvent* event) {
Geom::Point windowNormal = Geom::unit_vector(Geom::rot90(desktop->d2w(end_point - start_point)));
Geom::Point normal = desktop->w2d(windowNormal);
+ std::vector<Geom::Point> intersections;
+ std::sort(intersection_times.begin(), intersection_times.end());
+ for (std::vector<double>::iterator iter_t = intersection_times.begin(); iter_t != intersection_times.end(); iter_t++) {
+ intersections.push_back(lineseg[0].pointAt(*iter_t));
+ }
+
+ std::vector<LabelPlacement> placements;
for (size_t idx = 1; idx < intersections.size(); ++idx) {
LabelPlacement placement;
placement.lengthVal = (intersections[idx] - intersections[idx - 1]).length();
diff --git a/src/ui/tools/mesh-tool.cpp b/src/ui/tools/mesh-tool.cpp
index 7d6d3bc23..8a1fb7c72 100644
--- a/src/ui/tools/mesh-tool.cpp
+++ b/src/ui/tools/mesh-tool.cpp
@@ -53,7 +53,7 @@
using Inkscape::DocumentUndo;
-#include "tool-factory.h"
+#include "ui/tool-factory.h"
namespace Inkscape {
namespace UI {
diff --git a/src/ui/tools/node-tool.cpp b/src/ui/tools/node-tool.cpp
index b1e11bd66..838c2a884 100644
--- a/src/ui/tools/node-tool.cpp
+++ b/src/ui/tools/node-tool.cpp
@@ -19,10 +19,13 @@
#include "display/curve.h"
#include "display/sp-canvas.h"
#include "document.h"
+#include "live_effects/effect.h"
#include "live_effects/lpeobject.h"
#include "message-context.h"
#include "selection.h"
-#include "shape-editor.h" // temporary!
+#include "ui/shape-editor.h" // temporary!
+#include "live_effects/effect.h"
+#include "display/curve.h"
#include "sp-clippath.h"
#include "sp-item-group.h"
#include "sp-mask.h"
@@ -104,7 +107,7 @@
using Inkscape::ControlManager;
-#include "tool-factory.h"
+#include "ui/tool-factory.h"
namespace Inkscape {
namespace UI {
@@ -166,6 +169,13 @@ NodeTool::~NodeTool() {
if (this->flash_tempitem) {
this->desktop->remove_temporary_canvasitem(this->flash_tempitem);
}
+ if (this->helperpath_tmpitem) {
+ this->desktop->remove_temporary_canvasitem(this->helperpath_tmpitem);
+ }
+
+ if (this->helperpath_tmpitem) {
+ this->desktop->remove_temporary_canvasitem(this->helperpath_tmpitem);
+ }
this->_selection_changed_connection.disconnect();
//this->_selection_modified_connection.disconnect();
@@ -235,7 +245,7 @@ void NodeTool::setup() {
)
);
- this->_selected_nodes->signal_point_changed.connect(
+ this->_selected_nodes->signal_selection_changed.connect(
// Hide both signal parameters and bind the function parameter to 0
// sigc::signal<void, SelectableControlPoint *, bool>
// <=>
@@ -246,12 +256,14 @@ void NodeTool::setup() {
)))
);
+ this->helperpath_tmpitem = NULL;
this->cursor_drag = false;
this->show_transform_handles = true;
this->single_node_transform_handles = false;
this->flash_tempitem = NULL;
this->flashed_item = NULL;
this->_last_over = NULL;
+ this->helperpath_tmpitem = NULL;
// read prefs before adding items to selection to prevent momentarily showing the outline
sp_event_context_read(this, "show_handles");
@@ -278,6 +290,50 @@ void NodeTool::setup() {
}
this->desktop->emitToolSubselectionChanged(NULL); // sets the coord entry fields to inactive
+ this->update_helperpath();
+}
+
+// show helper paths of the applied LPE, if any
+void NodeTool::update_helperpath () {
+ Inkscape::Selection *selection = sp_desktop_selection (this->desktop);
+
+ if (this->helperpath_tmpitem) {
+ this->desktop->remove_temporary_canvasitem(this->helperpath_tmpitem);
+ this->helperpath_tmpitem = NULL;
+ }
+
+ if (SP_IS_LPE_ITEM(selection->singleItem())) {
+ Inkscape::LivePathEffect::Effect *lpe = SP_LPE_ITEM(selection->singleItem())->getCurrentLPE();
+ if (lpe && lpe->isVisible()/* && lpe->showOrigPath()*/) {
+ Inkscape::UI::ControlPointSelection::Set &selectionNodes = _selected_nodes->allPoints();
+ std::vector<Geom::Point> selectedNodesPositions;
+ for (Inkscape::UI::ControlPointSelection::Set::iterator i = selectionNodes.begin(); i != selectionNodes.end(); ++i) {
+ if ((*i)->selected()) {
+ Inkscape::UI::Node *n = dynamic_cast<Inkscape::UI::Node *>(*i);
+ selectedNodesPositions.push_back(n->position());
+ }
+ }
+ lpe->setSelectedNodePoints(selectedNodesPositions);
+ lpe->setCurrentZoom(this->desktop->current_zoom());
+ SPCurve *c = new SPCurve();
+ SPCurve *cc = new SPCurve();
+ std::vector<Geom::PathVector> cs = lpe->getCanvasIndicators(SP_LPE_ITEM(selection->singleItem()));
+ for (std::vector<Geom::PathVector>::iterator p = cs.begin(); p != cs.end(); ++p) {
+ cc->set_pathvector(*p);
+ c->append(cc, false);
+ cc->reset();
+ }
+ if (!c->is_empty()) {
+ SPCanvasItem *helperpath = sp_canvas_bpath_new(sp_desktop_tempgroup(this->desktop), c);
+ sp_canvas_bpath_set_stroke(SP_CANVAS_BPATH(helperpath), 0x0000ff9A, 1.0, SP_STROKE_LINEJOIN_MITER, SP_STROKE_LINECAP_BUTT);
+ sp_canvas_bpath_set_fill(SP_CANVAS_BPATH(helperpath), 0, SP_WIND_RULE_NONZERO);
+ sp_canvas_item_affine_absolute(helperpath, selection->singleItem()->i2dt_affine());
+ this->helperpath_tmpitem = this->desktop->add_temporary_canvasitem(helperpath, 0);
+ }
+ c->unref();
+ cc->unref();
+ }
+ }
}
void NodeTool::set(const Inkscape::Preferences::Entry& value) {
@@ -392,11 +448,11 @@ void NodeTool::selection_changed(Inkscape::Selection *sel) {
for (std::set<ShapeRecord>::iterator i = shapes.begin(); i != shapes.end(); ++i) {
ShapeRecord const &r = *i;
- if ((SP_IS_SHAPE(r.item) || SP_IS_TEXT(r.item)) &&
+ if ((SP_IS_SHAPE(r.item) || SP_IS_TEXT(r.item) || SP_IS_GROUP(r.item) || SP_IS_OBJECTGROUP(r.item)) &&
this->_shape_editors.find(r.item) == this->_shape_editors.end())
{
ShapeEditor *si = new ShapeEditor(this->desktop);
- si->set_item(r.item, SH_KNOTHOLDER);
+ si->set_item(r.item);
this->_shape_editors.insert(const_cast<SPItem*&>(r.item), si);
}
}
@@ -416,7 +472,7 @@ bool NodeTool::root_handler(GdkEvent* event) {
Inkscape::Selection *selection = desktop->selection;
static Inkscape::Preferences *prefs = Inkscape::Preferences::get();
-
+
if (this->_multipath->event(this, event)) {
return true;
}
@@ -432,7 +488,9 @@ bool NodeTool::root_handler(GdkEvent* event) {
switch (event->type)
{
case GDK_MOTION_NOTIFY: {
+ this->update_helperpath();
combine_motion_events(desktop->canvas, event->motion, 0);
+ this->update_helperpath();
SPItem *over_item = sp_event_context_find_item (desktop, event_point(event->button),
FALSE, TRUE);
@@ -441,7 +499,6 @@ bool NodeTool::root_handler(GdkEvent* event) {
//ink_node_tool_update_tip(nt, event);
this->update_tip(event);
}
-
// create pathflash outline
if (prefs->getBool("/tools/nodes/pathflash_enabled")) {
if (over_item == this->flashed_item) {
@@ -473,7 +530,8 @@ bool NodeTool::root_handler(GdkEvent* event) {
SPCanvasItem *flash = sp_canvas_bpath_new(sp_desktop_tempgroup(desktop), c);
sp_canvas_bpath_set_stroke(SP_CANVAS_BPATH(flash),
- prefs->getInt("/tools/nodes/highlight_color", 0xff0000ff), 1.0,
+ //prefs->getInt("/tools/nodes/highlight_color", 0xff0000ff), 1.0,
+ over_item->highlight_color(), 1.0,
SP_STROKE_LINEJOIN_MITER, SP_STROKE_LINECAP_BUTT);
sp_canvas_bpath_set_fill(SP_CANVAS_BPATH(flash), 0, SP_WIND_RULE_NONZERO);
diff --git a/src/ui/tools/node-tool.h b/src/ui/tools/node-tool.h
index 4d15ab70e..ab72f3632 100644
--- a/src/ui/tools/node-tool.h
+++ b/src/ui/tools/node-tool.h
@@ -15,6 +15,9 @@
#include <glib.h>
#include "ui/tools/tool-base.h"
+// we need it to call it from Live Effect
+#include "selection.h"
+
namespace Inkscape {
namespace Display {
class TemporaryItem;
@@ -51,6 +54,7 @@ public:
static const std::string prefsPath;
virtual void setup();
+ virtual void update_helperpath();
virtual void set(const Inkscape::Preferences::Entry& val);
virtual bool root_handler(GdkEvent* event);
@@ -62,6 +66,7 @@ private:
sigc::connection _sizeUpdatedConn;
SPItem *flashed_item;
+ Inkscape::Display::TemporaryItem *helperpath_tmpitem;
Inkscape::Display::TemporaryItem *flash_tempitem;
Inkscape::UI::Selector* _selector;
Inkscape::UI::PathSharedData* _path_data;
diff --git a/src/ui/tools/pen-tool.cpp b/src/ui/tools/pen-tool.cpp
index 09c0a2a4f..92937a135 100644
--- a/src/ui/tools/pen-tool.cpp
+++ b/src/ui/tools/pen-tool.cpp
@@ -26,7 +26,7 @@
#include "desktop-handles.h"
#include "selection.h"
#include "selection-chemistry.h"
-#include "draw-anchor.h"
+#include "ui/draw-anchor.h"
#include "message-stack.h"
#include "message-context.h"
#include "preferences.h"
@@ -40,9 +40,40 @@
#include <glibmm/i18n.h>
#include "macros.h"
#include "context-fns.h"
-#include "tools-switch.h"
+#include "ui/tools-switch.h"
#include "ui/control-manager.h"
-#include "tool-factory.h"
+// we include the necessary files for BSpline & Spiro
+#include "live_effects/effect.h"
+#include "live_effects/lpeobject.h"
+#include "live_effects/lpeobject-reference.h"
+#include "live_effects/parameter/path.h"
+#define INKSCAPE_LPE_SPIRO_C
+#include "live_effects/lpe-spiro.h"
+
+
+#include <typeinfo>
+#include <2geom/pathvector.h>
+#include <2geom/affine.h>
+#include <2geom/bezier-curve.h>
+#include <2geom/hvlinesegment.h>
+#include "helper/geom-nodetype.h"
+#include "helper/geom-curves.h"
+
+// For handling un-continuous paths:
+#include "message-stack.h"
+#include "inkscape.h"
+#include "desktop.h"
+
+#include "live_effects/spiro.h"
+
+#define INKSCAPE_LPE_BSPLINE_C
+#include "live_effects/lpe-bspline.h"
+#include <2geom/nearest-point.h>
+
+#include "ui/tool-factory.h"
+
+#include "live_effects/effect.h"
+
using Inkscape::ControlManager;
@@ -53,17 +84,17 @@ namespace Tools {
static Geom::Point pen_drag_origin_w(0, 0);
static bool pen_within_tolerance = false;
static int pen_last_paraxial_dir = 0; // last used direction in horizontal/vertical mode; 0 = horizontal, 1 = vertical
-
+const double handleCubicGap = 0.01;
namespace {
- ToolBase* createPenContext() {
- return new PenTool();
- }
+ ToolBase* createPenContext() {
+ return new PenTool();
+ }
- bool penContextRegistered = ToolFactory::instance().registerObject("/tools/freehand/pen", createPenContext);
+ bool penContextRegistered = ToolFactory::instance().registerObject("/tools/freehand/pen", createPenContext);
}
const std::string& PenTool::getPrefsPath() {
- return PenTool::prefsPath;
+ return PenTool::prefsPath;
}
const std::string PenTool::prefsPath = "/tools/freehand/pen";
@@ -135,8 +166,22 @@ PenTool::~PenTool() {
void PenTool::setPolylineMode() {
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
guint mode = prefs->getInt("/tools/freehand/pen/freehand-mode", 0);
- this->polylines_only = (mode == 2 || mode == 3);
- this->polylines_paraxial = (mode == 3);
+ // change the nodes to make space for bspline mode
+ this->polylines_only = (mode == 3 || mode == 4);
+ this->polylines_paraxial = (mode == 4);
+ //we call the function which defines the Spiro modes and the BSpline
+ //todo: merge to one function only
+ this->_pen_context_set_mode(mode);
+}
+
+/*
+*.Set the mode of draw spiro, and bsplines
+*/
+void PenTool::_pen_context_set_mode(guint mode) {
+ // define the nodes
+ this->spiro = (mode == 1);
+ this->bspline = (mode == 2);
+ this->_bspline_spiro_color();
}
/**
@@ -144,7 +189,6 @@ void PenTool::setPolylineMode() {
*/
void PenTool::setup() {
FreehandBase::setup();
-
ControlManager &mgr = ControlManager::getManager();
// Pen indicators
@@ -195,7 +239,9 @@ void PenTool::finish() {
sp_event_context_discard_delayed_snap_event(this);
if (this->npoints != 0) {
- this->_cancel();
+ // switching context - finish path
+ this->ea = NULL; // unset end anchor if set (otherwise crashes)
+ this->_finish(false);
}
FreehandBase::finish();
@@ -277,7 +323,7 @@ bool PenTool::item_handler(SPItem* item, GdkEvent* event) {
}
if (!ret) {
- ret = FreehandBase::item_handler(item, event);
+ ret = FreehandBase::item_handler(item, event);
}
return ret;
@@ -315,7 +361,7 @@ bool PenTool::root_handler(GdkEvent* event) {
}
if (!ret) {
- ret = FreehandBase::root_handler(event);
+ ret = FreehandBase::root_handler(event);
}
return ret;
@@ -332,9 +378,20 @@ bool PenTool::_handleButtonPress(GdkEventButton const &bevent) {
Geom::Point const event_w(bevent.x, bevent.y);
Geom::Point event_dt(desktop->w2d(event_w));
-
+ //Test whether we hit any anchor.
+ SPDrawAnchor * const anchor = spdc_test_inside(this, event_w);
+
+ //with this we avoid creating a new point over the existing one
+ if(bevent.button != 3 && (this->spiro || this->bspline) && this->npoints > 0 && this->p[0] == this->p[3]){
+ if( anchor && anchor == this->sa && this->green_curve->is_empty()){
+ //remove the following line to avoid having one node on top of another
+ _finishSegment(event_dt, bevent.state);
+ _finish( false);
+ return true;
+ }
+ return false;
+ }
bool ret = false;
-
if (bevent.button == 1 && !this->space_panning
// make sure this is not the last click for a waiting LPE (otherwise we want to finish the path)
&& this->expecting_clicks_for_LPE != 1) {
@@ -355,10 +412,8 @@ bool PenTool::_handleButtonPress(GdkEventButton const &bevent) {
pen_drag_origin_w = event_w;
pen_within_tolerance = true;
- // Test whether we hit any anchor.
- SPDrawAnchor * const anchor = spdc_test_inside(this, event_w);
-
switch (this->mode) {
+
case PenTool::MODE_CLICK:
// In click mode we add point on release
switch (this->state) {
@@ -380,7 +435,7 @@ bool PenTool::_handleButtonPress(GdkEventButton const &bevent) {
// This is allowed, if we just canceled curve
case PenTool::POINT:
if (this->npoints == 0) {
-
+ this->_bspline_spiro_color();
Geom::Point p;
if ((bevent.state & GDK_CONTROL_MASK) && (this->polylines_only || this->polylines_paraxial)) {
p = event_dt;
@@ -399,8 +454,12 @@ bool PenTool::_handleButtonPress(GdkEventButton const &bevent) {
// distinction so that the case of a waiting LPE is treated separately
// Set start anchor
+
this->sa = anchor;
- if (anchor && !this->hasWaitingLPE()) {
+ if(anchor){
+ this->_bspline_spiro_start_anchor(bevent.state & GDK_SHIFT_MASK);
+ }
+ if (anchor && (!this->hasWaitingLPE()|| this->bspline || this->spiro)) {
// Adjust point to anchor if needed; if we have a waiting LPE, we need
// a fresh path to be created so don't continue an existing one
p = anchor->dp;
@@ -422,7 +481,7 @@ bool PenTool::_handleButtonPress(GdkEventButton const &bevent) {
// Create green anchor
p = event_dt;
this->_endpointSnap(p, bevent.state);
- this->green_anchor = sp_draw_anchor_new(this, this->green_curve, TRUE, p);
+ this->green_anchor = sp_draw_anchor_new(this, this->green_curve, true, p);
}
this->_setInitialPoint(p);
} else {
@@ -439,7 +498,7 @@ bool PenTool::_handleButtonPress(GdkEventButton const &bevent) {
if (this->green_anchor && this->green_anchor->active) {
// we clicked on the current curve start, so close it even if
// we drag a handle away from it
- this->green_closed = TRUE;
+ this->green_closed = true;
}
ret = true;
break;
@@ -450,8 +509,8 @@ bool PenTool::_handleButtonPress(GdkEventButton const &bevent) {
this->_setSubsequentPoint(p, true);
}
}
-
- this->state = this->polylines_only ? PenTool::POINT : PenTool::CONTROL;
+ // avoid the creation of a control point so a node is created in the release event
+ this->state = (this->spiro || this->bspline || this->polylines_only) ? PenTool::POINT : PenTool::CONTROL;
ret = true;
break;
case PenTool::CONTROL:
@@ -481,6 +540,7 @@ bool PenTool::_handleButtonPress(GdkEventButton const &bevent) {
ret = true;
} else if (bevent.button == 3 && this->npoints != 0) {
// right click - finish path
+ this->ea = NULL; // unset end anchor if set (otherwise crashes)
this->_finish(false);
ret = true;
}
@@ -510,9 +570,11 @@ bool PenTool::_handleMotionNotify(GdkEventMotion const &mevent) {
Geom::Point const event_w(mevent.x, mevent.y);
+ //we take out the function the const "tolerance" because we need it later
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ gint const tolerance = prefs->getIntLimited("/options/dragtolerance/value", 0, 0, 100);
+
if (pen_within_tolerance) {
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- gint const tolerance = prefs->getIntLimited("/options/dragtolerance/value", 0, 0, 100);
if ( Geom::LInfty( event_w - pen_drag_origin_w ) < tolerance ) {
return false; // Do not drag if we're within tolerance from origin.
}
@@ -536,7 +598,7 @@ bool PenTool::_handleMotionNotify(GdkEventMotion const &mevent) {
// Only set point, if we are already appending
this->_endpointSnap(p, mevent.state);
this->_setSubsequentPoint(p, true);
- ret = TRUE;
+ ret = true;
} else if (!this->sp_event_context_knot_mouseover()) {
SnapManager &m = desktop->namedview->snap_manager;
m.setup(desktop);
@@ -572,7 +634,11 @@ bool PenTool::_handleMotionNotify(GdkEventMotion const &mevent) {
}
if (anchor && !this->anchor_statusbar) {
- this->message_context->set(Inkscape::NORMAL_MESSAGE, _("<b>Click</b> or <b>click and drag</b> to close and finish the path."));
+ if(!this->spiro && !this->bspline){
+ this->message_context->set(Inkscape::NORMAL_MESSAGE, _("<b>Click</b> or <b>click and drag</b> to close and finish the path."));
+ }else{
+ this->message_context->set(Inkscape::NORMAL_MESSAGE, _("<b>Click</b> or <b>click and drag</b> to close and finish the path. Shift+Click make a cusp node"));
+ }
this->anchor_statusbar = true;
} else if (!anchor && this->anchor_statusbar) {
this->message_context->clear();
@@ -582,11 +648,16 @@ bool PenTool::_handleMotionNotify(GdkEventMotion const &mevent) {
ret = true;
} else {
if (anchor && !this->anchor_statusbar) {
- this->message_context->set(Inkscape::NORMAL_MESSAGE, _("<b>Click</b> or <b>click and drag</b> to continue the path from this point."));
+ if(!this->spiro && !this->bspline){
+ this->message_context->set(Inkscape::NORMAL_MESSAGE, _("<b>Click</b> or <b>click and drag</b> to continue the path from this point."));
+ }else{
+ this->message_context->set(Inkscape::NORMAL_MESSAGE, _("<b>Click</b> or <b>click and drag</b> to continue the path from this point. Shift+Click make a cusp node"));
+ }
this->anchor_statusbar = true;
} else if (!anchor && this->anchor_statusbar) {
this->message_context->clear();
this->anchor_statusbar = false;
+
}
if (!this->sp_event_context_knot_mouseover()) {
SnapManager &m = desktop->namedview->snap_manager;
@@ -601,6 +672,7 @@ bool PenTool::_handleMotionNotify(GdkEventMotion const &mevent) {
// Placing controls is last operation in CLOSE state
// snap the handle
+
this->_endpointSnapHandle(p, mevent.state);
if (!this->polylines_only) {
@@ -608,6 +680,7 @@ bool PenTool::_handleMotionNotify(GdkEventMotion const &mevent) {
} else {
this->_setCtrl(this->p[1], mevent.state);
}
+
gobble_motion_events(GDK_BUTTON1_MASK);
ret = true;
break;
@@ -627,6 +700,16 @@ bool PenTool::_handleMotionNotify(GdkEventMotion const &mevent) {
default:
break;
}
+ // calls the function "bspline_spiro_motion" when the mouse starts or stops moving
+ if(this->bspline){
+ this->_bspline_spiro_motion(mevent.state & GDK_SHIFT_MASK);
+ }else{
+ if ( Geom::LInfty( event_w - pen_drag_origin_w ) > (tolerance/2) || mevent.time == 0) {
+ this->_bspline_spiro_motion(mevent.state & GDK_SHIFT_MASK);
+ pen_drag_origin_w = event_w;
+ }
+ }
+
return ret;
}
@@ -648,7 +731,12 @@ bool PenTool::_handleButtonRelease(GdkEventButton const &revent) {
Geom::Point p = this->desktop->w2d(event_w);
// Test whether we hit any anchor.
+
SPDrawAnchor *anchor = spdc_test_inside(this, event_w);
+ // if we try to create a node in the same place as another node, we skip
+ if((!anchor || anchor == this->sa) && (this->spiro || this->bspline) && this->npoints > 0 && this->p[0] == this->p[3]){
+ return true;
+ }
switch (this->mode) {
case PenTool::MODE_CLICK:
@@ -656,10 +744,17 @@ bool PenTool::_handleButtonRelease(GdkEventButton const &revent) {
case PenTool::POINT:
if ( this->npoints == 0 ) {
// Start new thread only with button release
+ this->_bspline_spiro_color();
if (anchor) {
p = anchor->dp;
}
this->sa = anchor;
+ // continue the existing curve
+ if (anchor) {
+ if(this->bspline || this->spiro){
+ this->_bspline_spiro_start_anchor(revent.state & GDK_SHIFT_MASK);;
+ }
+ }
this->_setInitialPoint(p);
} else {
// Set end anchor here
@@ -684,6 +779,10 @@ bool PenTool::_handleButtonRelease(GdkEventButton const &revent) {
this->_endpointSnap(p, revent.state);
}
this->_finishSegment(p, revent.state);
+ // hude the guide of the penultimate node when closing the curve
+ if(this->spiro){
+ sp_canvas_item_hide(this->c1);
+ }
this->_finish(true);
this->state = PenTool::POINT;
ret = true;
@@ -707,6 +806,10 @@ bool PenTool::_handleButtonRelease(GdkEventButton const &revent) {
case PenTool::CLOSE:
this->_endpointSnap(p, revent.state);
this->_finishSegment(p, revent.state);
+ // hide the penultimate node guide when closing the curve
+ if(this->spiro){
+ sp_canvas_item_hide(this->c1);
+ }
if (this->green_closed) {
// finishing at the start anchor, close curve
this->_finish(true);
@@ -727,7 +830,6 @@ bool PenTool::_handleButtonRelease(GdkEventButton const &revent) {
default:
break;
}
-
if (this->grab) {
// Release grab now
sp_canvas_item_ungrab(this->grab, revent.time);
@@ -736,7 +838,7 @@ bool PenTool::_handleButtonRelease(GdkEventButton const &revent) {
ret = true;
- this->green_closed = FALSE;
+ this->green_closed = false;
}
// TODO: can we be sure that the path was created correctly?
@@ -764,7 +866,7 @@ bool PenTool::_handle2ButtonPress(GdkEventButton const &bevent) {
bool ret = false;
// only end on LMB double click. Otherwise horizontal scrolling causes ending of the path
if (this->npoints != 0 && bevent.button == 1) {
- this->_finish(FALSE);
+ this->_finish(false);
ret = true;
}
return ret;
@@ -785,7 +887,6 @@ void PenTool::_redrawAll() {
this->green_bpaths = g_slist_prepend(this->green_bpaths, cshape);
}
-
if (this->green_anchor)
SP_CTRL(this->green_anchor->ctrl)->moveto(this->green_anchor->dp);
@@ -795,7 +896,8 @@ void PenTool::_redrawAll() {
sp_canvas_bpath_set_bpath(SP_CANVAS_BPATH(this->red_bpath), this->red_curve);
// handles
- if (this->p[0] != this->p[1]) {
+ // hide the handlers in bspline and spiro modes
+ if (this->p[0] != this->p[1] && !this->spiro && !this->bspline) {
SP_CTRL(this->c1)->moveto(this->p[1]);
this->cl1->setCoords(this->p[0], this->p[1]);
sp_canvas_item_show(this->c1);
@@ -808,8 +910,9 @@ void PenTool::_redrawAll() {
Geom::Curve const * last_seg = this->green_curve->last_segment();
if (last_seg) {
Geom::CubicBezier const * cubic = dynamic_cast<Geom::CubicBezier const *>( last_seg );
+ // hide the handlers in bspline and spiro modes
if ( cubic &&
- (*cubic)[2] != this->p[0] )
+ (*cubic)[2] != this->p[0] && !this->spiro && !this->bspline )
{
Geom::Point p2 = (*cubic)[2];
SP_CTRL(this->c0)->moveto(p2);
@@ -821,6 +924,10 @@ void PenTool::_redrawAll() {
sp_canvas_item_hide(this->cl0);
}
}
+
+ // simply redraw the spiro. because its a redrawing, we don't call the global function,
+ // but we call the redrawing at the ending.
+ this->_bspline_spiro_build();
}
void PenTool::_lastpointMove(gdouble x, gdouble y) {
@@ -838,6 +945,7 @@ void PenTool::_lastpointMove(gdouble x, gdouble y) {
}
// red
+
this->p[0] += Geom::Point(x, y);
this->p[1] += Geom::Point(x, y);
this->_redrawAll();
@@ -848,25 +956,105 @@ void PenTool::_lastpointMoveScreen(gdouble x, gdouble y) {
}
void PenTool::_lastpointToCurve() {
- if (this->npoints != 5)
+ // avoid that if the "red_curve" contains only two points ( rect ), it doesn't stop here.
+ if (this->npoints != 5 && !this->spiro && !this->bspline)
return;
- Geom::CubicBezier const * cubic = dynamic_cast<Geom::CubicBezier const *>( this->green_curve->last_segment() );
- if ( cubic ) {
- this->p[1] = this->p[0] + (Geom::Point)( (*cubic)[3] - (*cubic)[2] );
- } else {
- this->p[1] = this->p[0] + (1./3)*(this->p[3] - this->p[0]);
+ this->p[1] = this->red_curve->last_segment()->initialPoint() + (1./3.)*(this->red_curve->last_segment()->finalPoint() - this->red_curve->last_segment()->initialPoint());
+ //modificate the last segment of the green curve so it creates the type of node we need
+ if (this->spiro||this->bspline) {
+ if (!this->green_curve->is_empty()) {
+ Geom::Point A(0,0);
+ Geom::Point B(0,0);
+ Geom::Point C(0,0);
+ Geom::Point D(0,0);
+ Geom::CubicBezier const *cubic = dynamic_cast<Geom::CubicBezier const *>( this->green_curve->last_segment() );
+ //We obtain the last segment 4 points in the previous curve
+ if ( cubic ){
+ A = (*cubic)[0];
+ B = (*cubic)[1];
+ if (this->spiro) {
+ C = this->p[0] + (this->p[0] - this->p[1]);
+ } else {
+ C = this->green_curve->last_segment()->finalPoint() + (1./3.)*(this->green_curve->last_segment()->initialPoint() - this->green_curve->last_segment()->finalPoint());
+ }
+ D = (*cubic)[3];
+ } else {
+ A = this->green_curve->last_segment()->initialPoint();
+ B = this->green_curve->last_segment()->initialPoint();
+ if (this->spiro) {
+ C = this->p[0] + (this->p[0] - this->p[1]);
+ } else {
+ C = this->green_curve->last_segment()->finalPoint() + (1./3.)*(this->green_curve->last_segment()->initialPoint() - this->green_curve->last_segment()->finalPoint());
+ }
+ D = this->green_curve->last_segment()->finalPoint();
+ }
+ SPCurve *previous = new SPCurve();
+ previous->moveto(A);
+ previous->curveto(B, C, D);
+ if ( this->green_curve->get_segment_count() == 1) {
+ this->green_curve = previous;
+ } else {
+ //we eliminate the last segment
+ this->green_curve->backspace();
+ //and we add it again with the recreation
+ this->green_curve->append_continuous(previous, 0.0625);
+ }
+ }
+ //if the last node is an union with another curve
+ if (this->green_curve->is_empty() && this->sa && !this->sa->curve->is_empty()) {
+ this->_bspline_spiro_start_anchor(false);
+ }
}
this->_redrawAll();
}
+
void PenTool::_lastpointToLine() {
- if (this->npoints != 5)
+ // avoid that if the "red_curve" contains only two points ( rect) it doesn't stop here.
+ if (this->npoints != 5 && !this->bspline)
return;
+ // modify the last segment of the green curve so the type of node we want is created.
+ if(this->spiro || this->bspline){
+ if(!this->green_curve->is_empty()){
+ Geom::Point A(0,0);
+ Geom::Point B(0,0);
+ Geom::Point C(0,0);
+ Geom::Point D(0,0);
+ SPCurve * previous = new SPCurve();
+ Geom::CubicBezier const * cubic = dynamic_cast<Geom::CubicBezier const *>( this->green_curve->last_segment() );
+ if ( cubic ) {
+ A = this->green_curve->last_segment()->initialPoint();
+ B = (*cubic)[1];
+ C = this->green_curve->last_segment()->finalPoint();
+ D = C;
+ } else {
+ //We obtain the last segment 4 points in the previous curve
+ A = this->green_curve->last_segment()->initialPoint();
+ B = A;
+ C = this->green_curve->last_segment()->finalPoint();
+ D = C;
+ }
+ previous->moveto(A);
+ previous->curveto(B, C, D);
+ if( this->green_curve->get_segment_count() == 1){
+ this->green_curve = previous;
+ }else{
+ //we eliminate the last segment
+ this->green_curve->backspace();
+ //and we add it again with the recreation
+ this->green_curve->append_continuous(previous, 0.0625);
+ }
+ }
+ // if the last node is an union with another curve
+ if(this->green_curve->is_empty() && this->sa && !this->sa->curve->is_empty()){
+ this->_bspline_spiro_start_anchor(true);
+ }
+ }
+
this->p[1] = this->p[0];
-
this->_redrawAll();
}
@@ -971,7 +1159,7 @@ bool PenTool::_handleKeyPress(GdkEvent *event) {
case GDK_KEY_p:
if (MOD__SHIFT_ONLY(event)) {
sp_pen_context_wait_for_LPE_mouse_clicks(pc, Inkscape::LivePathEffect::PARALLEL, 2);
- ret = TRUE;
+ ret = true;
}
break;
@@ -979,7 +1167,7 @@ bool PenTool::_handleKeyPress(GdkEvent *event) {
case GDK_KEY_c:
if (MOD__SHIFT_ONLY(event)) {
sp_pen_context_wait_for_LPE_mouse_clicks(pc, Inkscape::LivePathEffect::CIRCLE_3PTS, 3);
- ret = TRUE;
+ ret = true;
}
break;
@@ -987,7 +1175,7 @@ bool PenTool::_handleKeyPress(GdkEvent *event) {
case GDK_KEY_b:
if (MOD__SHIFT_ONLY(event)) {
sp_pen_context_wait_for_LPE_mouse_clicks(pc, Inkscape::LivePathEffect::PERP_BISECTOR, 2);
- ret = TRUE;
+ ret = true;
}
break;
@@ -995,7 +1183,7 @@ bool PenTool::_handleKeyPress(GdkEvent *event) {
case GDK_KEY_a:
if (MOD__SHIFT_ONLY(event)) {
sp_pen_context_wait_for_LPE_mouse_clicks(pc, Inkscape::LivePathEffect::ANGLE_BISECTOR, 3);
- ret = TRUE;
+ ret = true;
}
break;
*/
@@ -1018,6 +1206,7 @@ bool PenTool::_handleKeyPress(GdkEvent *event) {
case GDK_KEY_Return:
case GDK_KEY_KP_Enter:
if (this->npoints != 0) {
+ this->ea = NULL; // unset end anchor if set (otherwise crashes)
this->_finish(false);
ret = true;
}
@@ -1059,8 +1248,9 @@ bool PenTool::_handleKeyPress(GdkEvent *event) {
this->red_curve->reset();
// Destroy topmost green bpath
if (this->green_bpaths) {
- if (this->green_bpaths->data)
+ if (this->green_bpaths->data) {
sp_canvas_item_destroy(SP_CANVAS_ITEM(this->green_bpaths->data));
+ }
this->green_bpaths = g_slist_remove(this->green_bpaths, this->green_bpaths->data);
}
// Get last segment
@@ -1068,19 +1258,49 @@ bool PenTool::_handleKeyPress(GdkEvent *event) {
g_warning("pen_handle_key_press, case GDK_KP_Delete: Green curve is empty");
break;
}
- // The code below assumes that pc->green_curve has only ONE path !
+ // The code below assumes that this->green_curve has only ONE path !
Geom::Curve const * crv = this->green_curve->last_segment();
this->p[0] = crv->initialPoint();
if ( Geom::CubicBezier const * cubic = dynamic_cast<Geom::CubicBezier const *>(crv)) {
this->p[1] = (*cubic)[1];
+
} else {
this->p[1] = this->p[0];
}
- Geom::Point const pt(( this->npoints < 4
- ? (Geom::Point)(crv->finalPoint())
- : this->p[3] ));
+
+ // asign the value in a third of the distance of the last segment.
+ if (this->bspline){
+ this->p[1] = this->p[0] + (1./3)*(this->p[3] - this->p[0]);
+ }
+
+ Geom::Point const pt( (this->npoints < 4) ? crv->finalPoint() : this->p[3] );
+
this->npoints = 2;
- this->green_curve->backspace();
+ // delete the last segment of the green curve
+ if (this->green_curve->get_segment_count() == 1) {
+ this->npoints = 5;
+ if (this->green_bpaths) {
+ if (this->green_bpaths->data) {
+ sp_canvas_item_destroy(SP_CANVAS_ITEM(this->green_bpaths->data));
+ }
+ this->green_bpaths = g_slist_remove(this->green_bpaths, this->green_bpaths->data);
+ }
+ this->green_curve->reset();
+ } else {
+ this->green_curve->backspace();
+ }
+
+ // assign the value of this->p[1] to the oposite of the green line last segment
+ if (this->spiro){
+ Geom::CubicBezier const *cubic = dynamic_cast<Geom::CubicBezier const *>(this->green_curve->last_segment());
+ if ( cubic ) {
+ this->p[1] = (*cubic)[3] + (*cubic)[3] - (*cubic)[2];
+ SP_CTRL(this->c1)->moveto(this->p[0]);
+ } else {
+ this->p[1] = this->p[0];
+ }
+ }
+
sp_canvas_item_hide(this->c0);
sp_canvas_item_hide(this->c1);
sp_canvas_item_hide(this->cl0);
@@ -1088,6 +1308,9 @@ bool PenTool::_handleKeyPress(GdkEvent *event) {
this->state = PenTool::POINT;
this->_setSubsequentPoint(pt, true);
pen_last_paraxial_dir = !pen_last_paraxial_dir;
+
+ //redraw
+ this->_bspline_spiro_build();
ret = true;
}
break;
@@ -1154,11 +1377,686 @@ void PenTool::_setAngleDistanceStatusMessage(Geom::Point const p, int pc_point_t
}
this->message_context->setF(Inkscape::IMMEDIATE_MESSAGE, message, angle, dist->str);
- g_string_free(dist, FALSE);
+ g_string_free(dist, false);
+}
+
+// this function changes the colors red, green and blue making them transparent or not, depending on if spiro is being used.
+void PenTool::_bspline_spiro_color()
+{
+ static Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ if(this->spiro){
+ this->red_color = 0xff00000;
+ this->green_color = 0x00ff000;
+ }else if(this->bspline){
+ this->highlight_color = SP_ITEM(this->desktop->currentLayer())->highlight_color();
+ if((unsigned int)prefs->getInt("/tools/nodes/highlight_color", 0xff0000ff) == this->highlight_color){
+ this->green_color = 0xff00007f;
+ this->red_color = 0xff00007f;
+ } else {
+ this->green_color = this->highlight_color;
+ this->red_color = this->highlight_color;
+ }
+ }else{
+ this->highlight_color = SP_ITEM(this->desktop->currentLayer())->highlight_color();
+ this->red_color = 0xff00007f;
+ if((unsigned int)prefs->getInt("/tools/nodes/highlight_color", 0xff0000ff) == this->highlight_color){
+ this->green_color = 0x00ff007f;
+ } else {
+ this->green_color = this->highlight_color;
+ }
+ sp_canvas_item_hide(this->blue_bpath);
+ }
+ //We erase all the "green_bpaths" to recreate them after with the colour
+ //transparency recently modified
+ if (this->green_bpaths) {
+ // remove old piecewise green canvasitems
+ while (this->green_bpaths) {
+ sp_canvas_item_destroy(SP_CANVAS_ITEM(this->green_bpaths->data));
+ this->green_bpaths = g_slist_remove(this->green_bpaths, this->green_bpaths->data);
+ }
+ // one canvas bpath for all of green_curve
+ SPCanvasItem *cshape = sp_canvas_bpath_new(sp_desktop_sketch(this->desktop), this->green_curve);
+ sp_canvas_bpath_set_stroke(SP_CANVAS_BPATH(cshape), this->green_color, 1.0, SP_STROKE_LINEJOIN_MITER, SP_STROKE_LINECAP_BUTT);
+ sp_canvas_bpath_set_fill(SP_CANVAS_BPATH(cshape), 0, SP_WIND_RULE_NONZERO);
+ this->green_bpaths = g_slist_prepend(this->green_bpaths, cshape);
+ }
+ sp_canvas_bpath_set_stroke(SP_CANVAS_BPATH(this->red_bpath), this->red_color, 1.0, SP_STROKE_LINEJOIN_MITER, SP_STROKE_LINECAP_BUTT);
+}
+
+
+void PenTool::_bspline_spiro(bool shift)
+{
+ if(!this->spiro && !this->bspline)
+ return;
+
+ shift?this->_bspline_spiro_off():this->_bspline_spiro_on();
+ this->_bspline_spiro_build();
+}
+
+void PenTool::_bspline_spiro_on()
+{
+ if(!this->red_curve->is_empty()){
+ using Geom::X;
+ using Geom::Y;
+ this->npoints = 5;
+ this->p[0] = this->red_curve->first_segment()->initialPoint();
+ this->p[3] = this->red_curve->first_segment()->finalPoint();
+ this->p[2] = this->p[3] + (1./3)*(this->p[0] - this->p[3]);
+ this->p[2] = Geom::Point(this->p[2][X] + handleCubicGap,this->p[2][Y] + handleCubicGap);
+ }
+}
+
+void PenTool::_bspline_spiro_off()
+{
+ if(!this->red_curve->is_empty()){
+ this->npoints = 5;
+ this->p[0] = this->red_curve->first_segment()->initialPoint();
+ this->p[3] = this->red_curve->first_segment()->finalPoint();
+ this->p[2] = this->p[3];
+ }
+}
+
+void PenTool::_bspline_spiro_start_anchor(bool shift)
+{
+ if(this->sa->curve->is_empty()){
+ return;
+ }
+
+ LivePathEffect::LPEBSpline *lpe_bsp = NULL;
+
+ if (SP_IS_LPE_ITEM(this->white_item) && SP_LPE_ITEM(this->white_item)->hasPathEffect()){
+ Inkscape::LivePathEffect::Effect* thisEffect = SP_LPE_ITEM(this->white_item)->getPathEffectOfType(Inkscape::LivePathEffect::BSPLINE);
+ if(thisEffect){
+ lpe_bsp = dynamic_cast<LivePathEffect::LPEBSpline*>(thisEffect->getLPEObj()->get_lpe());
+ }
+ }
+ if(lpe_bsp){
+ this->bspline = true;
+ }else{
+ this->bspline = false;
+ }
+ LivePathEffect::LPESpiro *lpe_spi = NULL;
+
+ if (SP_IS_LPE_ITEM(this->white_item) && SP_LPE_ITEM(this->white_item)->hasPathEffect()){
+ Inkscape::LivePathEffect::Effect* thisEffect = SP_LPE_ITEM(this->white_item)->getPathEffectOfType(Inkscape::LivePathEffect::SPIRO);
+ if(thisEffect){
+ lpe_spi = dynamic_cast<LivePathEffect::LPESpiro*>(thisEffect->getLPEObj()->get_lpe());
+ }
+ }
+ if(lpe_spi){
+ this->spiro = true;
+ }else{
+ this->spiro = false;
+ }
+ if(!this->spiro && !this->bspline)
+ return;
+
+ if(shift)
+ this->_bspline_spiro_start_anchor_off();
+ else
+ this->_bspline_spiro_start_anchor_on();
+}
+
+void PenTool::_bspline_spiro_start_anchor_on()
+{
+ using Geom::X;
+ using Geom::Y;
+ SPCurve *tmpCurve = new SPCurve();
+ tmpCurve = this->sa->curve->copy();
+ if(this->sa->start)
+ tmpCurve = tmpCurve->create_reverse();
+ Geom::CubicBezier const * cubic = dynamic_cast<Geom::CubicBezier const*>(&*tmpCurve->last_segment());
+ SPCurve *lastSeg = new SPCurve();
+ Geom::Point A = tmpCurve->last_segment()->initialPoint();
+ Geom::Point D = tmpCurve->last_segment()->finalPoint();
+ Geom::Point C = D + (1./3)*(A - D);
+ C = Geom::Point(C[X] + handleCubicGap,C[Y] + handleCubicGap);
+ if(cubic){
+ lastSeg->moveto(A);
+ lastSeg->curveto((*cubic)[1],C,D);
+ }else{
+ lastSeg->moveto(A);
+ lastSeg->curveto(A,C,D);
+ }
+ if( tmpCurve->get_segment_count() == 1){
+ tmpCurve = lastSeg;
+ }else{
+ //we eliminate the last segment
+ tmpCurve->backspace();
+ //and we add it again with the recreation
+ tmpCurve->append_continuous(lastSeg, 0.0625);
+ }
+ if (this->sa->start) {
+ tmpCurve = tmpCurve->create_reverse();
+ }
+ this->overwriteCurve = tmpCurve;
+}
+
+void PenTool::_bspline_spiro_start_anchor_off()
+{
+ SPCurve *tmpCurve = new SPCurve();
+ tmpCurve = this->sa->curve->copy();
+ if(this->sa->start)
+ tmpCurve = tmpCurve->create_reverse();
+ Geom::CubicBezier const * cubic = dynamic_cast<Geom::CubicBezier const*>(&*tmpCurve->last_segment());
+ if(cubic){
+ SPCurve *lastSeg = new SPCurve();
+ lastSeg->moveto((*cubic)[0]);
+ lastSeg->curveto((*cubic)[1],(*cubic)[3],(*cubic)[3]);
+ if( tmpCurve->get_segment_count() == 1){
+ tmpCurve = lastSeg;
+ }else{
+ //we eliminate the last segment
+ tmpCurve->backspace();
+ //and we add it again with the recreation
+ tmpCurve->append_continuous(lastSeg, 0.0625);
+ }
+ }
+ if (this->sa->start) {
+ tmpCurve = tmpCurve->create_reverse();
+ }
+ this->overwriteCurve = tmpCurve;
+}
+
+void PenTool::_bspline_spiro_motion(bool shift){
+ if(!this->spiro && !this->bspline)
+ return;
+
+ using Geom::X;
+ using Geom::Y;
+ if(this->red_curve->is_empty()) return;
+ this->npoints = 5;
+ SPCurve *tmpCurve = new SPCurve();
+ this->p[2] = this->p[3] + (1./3)*(this->p[0] - this->p[3]);
+ this->p[2] = Geom::Point(this->p[2][X] + handleCubicGap,this->p[2][Y] + handleCubicGap);
+ if(this->green_curve->is_empty() && !this->sa){
+ this->p[1] = this->p[0] + (1./3)*(this->p[3] - this->p[0]);
+ this->p[1] = Geom::Point(this->p[1][X] + handleCubicGap,this->p[1][Y] + handleCubicGap);
+ if(shift){
+ this->p[2] = this->p[3];
+ }
+ }else if(!this->green_curve->is_empty()){
+ tmpCurve = this->green_curve->copy();
+ }else{
+ tmpCurve = this->overwriteCurve->copy();
+ if(this->sa->start)
+ tmpCurve = tmpCurve->create_reverse();
+ }
+
+ if(!tmpCurve->is_empty()){
+ Geom::CubicBezier const * cubic = dynamic_cast<Geom::CubicBezier const*>(&*tmpCurve->last_segment());
+ if(cubic){
+ if(this->bspline){
+ SPCurve * WPower = new SPCurve();
+ Geom::D2< Geom::SBasis > SBasisWPower;
+ WPower->moveto(tmpCurve->last_segment()->finalPoint());
+ WPower->lineto(tmpCurve->last_segment()->initialPoint());
+ float WP = Geom::nearest_point((*cubic)[2],*WPower->first_segment());
+ WPower->reset();
+ WPower->moveto(this->red_curve->last_segment()->initialPoint());
+ WPower->lineto(this->red_curve->last_segment()->finalPoint());
+ SBasisWPower = WPower->first_segment()->toSBasis();
+ WPower->reset();
+ this->p[1] = SBasisWPower.valueAt(WP);
+ if(!Geom::are_near(this->p[1],this->p[0])){
+ this->p[1] = Geom::Point(this->p[1][X] + handleCubicGap,this->p[1][Y] + handleCubicGap);
+ } else {
+ this->p[1] = this->p[0];
+ }
+ if(shift)
+ this->p[2] = this->p[3];
+ }else{
+ this->p[1] = (*cubic)[3] + ((*cubic)[3] - (*cubic)[2] );
+ }
+ }else{
+ this->p[1] = this->p[0];
+ if(shift)
+ this->p[2] = this->p[3];
+ }
+ }
+
+ if(this->anchor_statusbar && !this->red_curve->is_empty()){
+ if(shift){
+ this->_bspline_spiro_end_anchor_off();
+ }else{
+ this->_bspline_spiro_end_anchor_on();
+ }
+ }
+
+ this->_bspline_spiro_build();
+}
+
+void PenTool::_bspline_spiro_end_anchor_on()
+{
+
+ using Geom::X;
+ using Geom::Y;
+ this->p[2] = this->p[3] + (1./3)*(this->p[0] - this->p[3]);
+ this->p[2] = Geom::Point(this->p[2][X] + handleCubicGap,this->p[2][Y] + handleCubicGap);
+ SPCurve *tmpCurve = new SPCurve();
+ SPCurve *lastSeg = new SPCurve();
+ Geom::Point C(0,0);
+ bool reverse = false;
+ if( this->green_anchor && this->green_anchor->active ){
+ tmpCurve = this->green_curve->create_reverse();
+ if(this->green_curve->get_segment_count()==0){
+ return;
+ }
+ reverse = true;
+ } else if(this->sa){
+ tmpCurve = this->overwriteCurve->copy();
+ if(!this->sa->start){
+ tmpCurve = tmpCurve->create_reverse();
+ reverse = true;
+ }
+ }else{
+ return;
+ }
+ Geom::CubicBezier const * cubic = dynamic_cast<Geom::CubicBezier const*>(&*tmpCurve->last_segment());
+ if(this->bspline){
+ C = tmpCurve->last_segment()->finalPoint() + (1./3)*(tmpCurve->last_segment()->initialPoint() - tmpCurve->last_segment()->finalPoint());
+ C = Geom::Point(C[X] + handleCubicGap,C[Y] + handleCubicGap);
+ }else{
+ C = this->p[3] + this->p[3] - this->p[2];
+ }
+ if(cubic){
+ lastSeg->moveto((*cubic)[0]);
+ lastSeg->curveto((*cubic)[1],C,(*cubic)[3]);
+ }else{
+ lastSeg->moveto(tmpCurve->last_segment()->initialPoint());
+ lastSeg->lineto(tmpCurve->last_segment()->finalPoint());
+ }
+ if( tmpCurve->get_segment_count() == 1){
+ tmpCurve = lastSeg;
+ }else{
+ //we eliminate the last segment
+ tmpCurve->backspace();
+ //and we add it again with the recreation
+ tmpCurve->append_continuous(lastSeg, 0.0625);
+ }
+ if (reverse) {
+ tmpCurve = tmpCurve->create_reverse();
+ }
+ if( this->green_anchor && this->green_anchor->active )
+ {
+ this->green_curve->reset();
+ this->green_curve = tmpCurve;
+ }else{
+ this->overwriteCurve->reset();
+ this->overwriteCurve = tmpCurve;
+ }
+}
+
+void PenTool::_bspline_spiro_end_anchor_off()
+{
+
+ SPCurve *tmpCurve = new SPCurve();
+ SPCurve *lastSeg = new SPCurve();
+ bool reverse = false;
+ this->p[2] = this->p[3];
+ if( this->green_anchor && this->green_anchor->active ){
+ tmpCurve = this->green_curve->create_reverse();
+ if(this->green_curve->get_segment_count()==0){
+ return;
+ }
+ reverse = true;
+ } else if(this->sa){
+ tmpCurve = this->overwriteCurve->copy();
+ if(!this->sa->start){
+ tmpCurve = tmpCurve->create_reverse();
+ reverse = true;
+ }
+ }else{
+ return;
+ }
+ Geom::CubicBezier const * cubic = dynamic_cast<Geom::CubicBezier const*>(&*tmpCurve->last_segment());
+ if(cubic){
+ lastSeg->moveto((*cubic)[0]);
+ lastSeg->curveto((*cubic)[1],(*cubic)[3],(*cubic)[3]);
+ }else{
+ lastSeg->moveto(tmpCurve->last_segment()->initialPoint());
+ lastSeg->lineto(tmpCurve->last_segment()->finalPoint());
+ }
+ if( tmpCurve->get_segment_count() == 1){
+ tmpCurve = lastSeg;
+ }else{
+ //we eliminate the last segment
+ tmpCurve->backspace();
+ //and we add it again with the recreation
+ tmpCurve->append_continuous(lastSeg, 0.0625);
+ }
+ if (reverse) {
+ tmpCurve = tmpCurve->create_reverse();
+ }
+ if( this->green_anchor && this->green_anchor->active )
+ {
+ this->green_curve->reset();
+ this->green_curve = tmpCurve;
+ }else{
+ this->overwriteCurve->reset();
+ this->overwriteCurve = tmpCurve;
+ }
+}
+
+//prepares the curves for its transformation into BSpline curve.
+void PenTool::_bspline_spiro_build()
+{
+ if(!this->spiro && !this->bspline){
+ return;
+ }
+
+ //We create the base curve
+ SPCurve *curve = new SPCurve();
+ //If we continuate the existing curve we add it at the start
+ if(this->sa && !this->sa->curve->is_empty()){
+ curve = this->overwriteCurve->copy();
+ if (this->sa->start) {
+ curve = curve->create_reverse();
+ }
+ }
+
+ if (!this->green_curve->is_empty()){
+ curve->append_continuous(this->green_curve, 0.0625);
+ }
+
+ //and the red one
+ if (!this->red_curve->is_empty()){
+ this->red_curve->reset();
+ this->red_curve->moveto(this->p[0]);
+ if(this->anchor_statusbar && !this->sa && !(this->green_anchor && this->green_anchor->active)){
+ this->red_curve->curveto(this->p[1],this->p[3],this->p[3]);
+ }else{
+ this->red_curve->curveto(this->p[1],this->p[2],this->p[3]);
+ }
+ sp_canvas_bpath_set_bpath(SP_CANVAS_BPATH(this->red_bpath), this->red_curve);
+ curve->append_continuous(this->red_curve, 0.0625);
+ }
+
+ if(!curve->is_empty()){
+ // close the curve if the final points of the curve are close enough
+ if(Geom::are_near(curve->first_path()->initialPoint(), curve->last_path()->finalPoint())){
+ curve->closepath_current();
+ }
+ //TODO: CALL TO CLONED FUNCTION SPIRO::doEffect IN lpe-spiro.cpp
+ //For example
+ //using namespace Inkscape::LivePathEffect;
+ //LivePathEffectObject *lpeobj = static_cast<LivePathEffectObject*> (curve);
+ //Effect *spr = static_cast<Effect*> ( new LPEbspline(lpeobj) );
+ //spr->doEffect(curve);
+ if(this->bspline){
+ this->_bspline_doEffect(curve);
+ }else{
+ this->_spiro_doEffect(curve);
+ }
+
+ sp_canvas_bpath_set_bpath(SP_CANVAS_BPATH(this->blue_bpath), curve);
+ sp_canvas_bpath_set_stroke(SP_CANVAS_BPATH(this->blue_bpath), this->blue_color, 1.0, SP_STROKE_LINEJOIN_MITER, SP_STROKE_LINECAP_BUTT);
+ sp_canvas_item_show(this->blue_bpath);
+ curve->unref();
+ this->blue_curve->reset();
+ //We hide the holders that doesn't contribute anything
+ if(this->spiro){
+ sp_canvas_item_show(this->c1);
+ SP_CTRL(this->c1)->moveto(this->p[0]);
+ }else
+ sp_canvas_item_hide(this->c1);
+ sp_canvas_item_hide(this->cl1);
+ sp_canvas_item_hide(this->c0);
+ sp_canvas_item_hide(this->cl0);
+ }else{
+ //if the curve is empty
+ sp_canvas_item_hide(this->blue_bpath);
+
+ }
+}
+
+void PenTool::_bspline_doEffect(SPCurve * curve)
+{
+ // commenting the function doEffect in src/live_effects/lpe-bspline.cpp
+ if (curve->get_segment_count() < 1){
+ return;
+ }
+ // Make copy of old path as it is changed during processing
+ Geom::PathVector const original_pathv = curve->get_pathvector();
+ curve->reset();
+
+ //Recorremos todos los paths a los que queremos aplicar el efecto, hasta el
+ //penúltimo
+ for (Geom::PathVector::const_iterator path_it = original_pathv.begin();
+ path_it != original_pathv.end(); ++path_it) {
+ //Si está vacío...
+ if (path_it->empty())
+ continue;
+ //Itreadores
+
+ Geom::Path::const_iterator curve_it1 = path_it->begin();
+ Geom::Path::const_iterator curve_it2 = ++(path_it->begin());
+ Geom::Path::const_iterator curve_endit = path_it->end_default();
+ SPCurve *nCurve = new SPCurve();
+ Geom::Point previousNode(0, 0);
+ Geom::Point node(0, 0);
+ Geom::Point pointAt1(0, 0);
+ Geom::Point pointAt2(0, 0);
+ Geom::Point nextPointAt1(0, 0);
+ Geom::D2<Geom::SBasis> SBasisIn;
+ Geom::D2<Geom::SBasis> SBasisOut;
+ Geom::D2<Geom::SBasis> SBasisHelper;
+ Geom::CubicBezier const *cubic = NULL;
+ if (path_it->closed()) {
+ const Geom::Curve &closingline =
+ path_it->back_closed(); // the closing line segment is always of type
+ if (are_near(closingline.initialPoint(), closingline.finalPoint())) {
+ curve_endit = path_it->end_open();
+ }
+ }
+ nCurve->moveto(curve_it1->initialPoint());
+ while (curve_it1 != curve_endit) {
+ SPCurve *in = new SPCurve();
+ in->moveto(curve_it1->initialPoint());
+ in->lineto(curve_it1->finalPoint());
+ cubic = dynamic_cast<Geom::CubicBezier const *>(&*curve_it1);
+ if (cubic) {
+ SBasisIn = in->first_segment()->toSBasis();
+ if(are_near((*cubic)[1],(*cubic)[0]) && !are_near((*cubic)[2],(*cubic)[3])) {
+ pointAt1 = SBasisIn.valueAt(0.3334);
+ } else {
+ pointAt1 = SBasisIn.valueAt(Geom::nearest_point((*cubic)[1], *in->first_segment()));
+ }
+ if(are_near((*cubic)[2],(*cubic)[3]) && !are_near((*cubic)[1],(*cubic)[0])) {
+ pointAt2 = SBasisIn.valueAt(0.6667);
+ } else {
+ pointAt2 = SBasisIn.valueAt(Geom::nearest_point((*cubic)[2], *in->first_segment()));
+ }
+ } else {
+ pointAt1 = in->first_segment()->initialPoint();
+ pointAt2 = in->first_segment()->finalPoint();
+ }
+ in->reset();
+ delete in;
+ if ( curve_it2 != curve_endit ) {
+ SPCurve *out = new SPCurve();
+ out->moveto(curve_it2->initialPoint());
+ out->lineto(curve_it2->finalPoint());
+ cubic = dynamic_cast<Geom::CubicBezier const *>(&*curve_it2);
+ if (cubic) {
+ SBasisOut = out->first_segment()->toSBasis();
+ if(are_near((*cubic)[1],(*cubic)[0]) && !are_near((*cubic)[2],(*cubic)[3])) {
+ nextPointAt1 = SBasisIn.valueAt(0.3334);
+ } else {
+ nextPointAt1 = SBasisOut.valueAt(Geom::nearest_point((*cubic)[1], *out->first_segment()));
+ }
+ } else {
+ nextPointAt1 = out->first_segment()->initialPoint();
+ }
+ out->reset();
+ delete out;
+ }
+ Geom::Point startNode = path_it->begin()->initialPoint();
+ if (path_it->closed() && curve_it2 == curve_endit) {
+ SPCurve *start = new SPCurve();
+ start->moveto(path_it->begin()->initialPoint());
+ start->lineto(path_it->begin()->finalPoint());
+ Geom::D2<Geom::SBasis> SBasisStart = start->first_segment()->toSBasis();
+ SPCurve *lineHelper = new SPCurve();
+ cubic = dynamic_cast<Geom::CubicBezier const *>(&*path_it->begin());
+ if (cubic) {
+ lineHelper->moveto(SBasisStart.valueAt(
+ Geom::nearest_point((*cubic)[1], *start->first_segment())));
+ } else {
+ lineHelper->moveto(start->first_segment()->initialPoint());
+ }
+ start->reset();
+ delete start;
+
+ SPCurve *end = new SPCurve();
+ end->moveto(curve_it1->initialPoint());
+ end->lineto(curve_it1->finalPoint());
+ Geom::D2<Geom::SBasis> SBasisEnd = end->first_segment()->toSBasis();
+ cubic = dynamic_cast<Geom::CubicBezier const *>(&*curve_it1);
+ if (cubic) {
+ lineHelper->lineto(SBasisEnd.valueAt(
+ Geom::nearest_point((*cubic)[2], *end->first_segment())));
+ } else {
+ lineHelper->lineto(end->first_segment()->finalPoint());
+ }
+ end->reset();
+ delete end;
+ SBasisHelper = lineHelper->first_segment()->toSBasis();
+ lineHelper->reset();
+ delete lineHelper;
+ startNode = SBasisHelper.valueAt(0.5);
+ nCurve->curveto(pointAt1, pointAt2, startNode);
+ nCurve->move_endpoints(startNode, startNode);
+ } else if ( curve_it2 == curve_endit) {
+ nCurve->curveto(pointAt1, pointAt2, curve_it1->finalPoint());
+ nCurve->move_endpoints(path_it->begin()->initialPoint(), curve_it1->finalPoint());
+ } else {
+ SPCurve *lineHelper = new SPCurve();
+ lineHelper->moveto(pointAt2);
+ lineHelper->lineto(nextPointAt1);
+ SBasisHelper = lineHelper->first_segment()->toSBasis();
+ lineHelper->reset();
+ delete lineHelper;
+ previousNode = node;
+ node = SBasisHelper.valueAt(0.5);
+ Geom::CubicBezier const *cubic2 = dynamic_cast<Geom::CubicBezier const *>(&*curve_it1);
+ if((cubic && are_near((*cubic)[0],(*cubic)[1])) || (cubic2 && are_near((*cubic2)[2],(*cubic2)[3]))) {
+ node = curve_it1->finalPoint();
+ }
+ nCurve->curveto(pointAt1, pointAt2, node);
+ }
+ ++curve_it1;
+ ++curve_it2;
+ }
+ if (path_it->closed()) {
+ nCurve->closepath_current();
+ }
+ curve->append(nCurve, false);
+ nCurve->reset();
+ delete nCurve;
+ }
+}
+
+//Spiro function cloned from lpe-spiro.cpp
+// commenting the function "doEffect" from src/live_effects/lpe-spiro.cpp
+void PenTool::_spiro_doEffect(SPCurve * curve)
+{
+ using Geom::X;
+ using Geom::Y;
+
+ Geom::PathVector const original_pathv = curve->get_pathvector();
+ guint len = curve->get_segment_count() + 2;
+
+ curve->reset();
+ Spiro::spiro_cp *path = g_new (Spiro::spiro_cp, len);
+ int ip = 0;
+
+ for(Geom::PathVector::const_iterator path_it = original_pathv.begin(); path_it != original_pathv.end(); ++path_it) {
+ if (path_it->empty())
+ continue;
+
+ {
+ Geom::Point p = path_it->front().pointAt(0);
+ path[ip].x = p[X];
+ path[ip].y = p[Y];
+ path[ip].ty = '{' ;
+ ip++;
+ }
+
+ Geom::Path::const_iterator curve_it1 = path_it->begin();
+ Geom::Path::const_iterator curve_it2 = ++(path_it->begin());
+
+ Geom::Path::const_iterator curve_endit = path_it->end_default();
+ if (path_it->closed()) {
+ const Geom::Curve &closingline = path_it->back_closed();
+ if (are_near(closingline.initialPoint(), closingline.finalPoint())) {
+ curve_endit = path_it->end_open();
+ }
+ }
+
+ while ( curve_it2 != curve_endit )
+ {
+ Geom::Point p = curve_it1->finalPoint();
+ path[ip].x = p[X];
+ path[ip].y = p[Y];
+
+ bool this_is_line = is_straight_curve(*curve_it1);
+ bool next_is_line = is_straight_curve(*curve_it2);
+
+ Geom::NodeType nodetype = Geom::get_nodetype(*curve_it1, *curve_it2);
+
+ if ( nodetype == Geom::NODE_SMOOTH || nodetype == Geom::NODE_SYMM )
+ {
+ if (this_is_line && !next_is_line) {
+ path[ip].ty = ']';
+ } else if (next_is_line && !this_is_line) {
+ path[ip].ty = '[';
+ } else {
+ path[ip].ty = 'c';
+ }
+ } else {
+ path[ip].ty = 'v';
+ }
+
+ ++curve_it1;
+ ++curve_it2;
+ ip++;
+ }
+
+ Geom::Point p = curve_it1->finalPoint();
+ path[ip].x = p[X];
+ path[ip].y = p[Y];
+ if (path_it->closed()) {
+ Geom::NodeType nodetype = Geom::get_nodetype(*curve_it1, path_it->front());
+ switch (nodetype) {
+ case Geom::NODE_NONE:
+ path[ip].ty = '}';
+ ip++;
+ break;
+ case Geom::NODE_CUSP:
+ path[0].ty = path[ip].ty = 'v';
+ break;
+ case Geom::NODE_SMOOTH:
+ case Geom::NODE_SYMM:
+ path[0].ty = path[ip].ty = 'c';
+ break;
+ }
+ } else {
+ path[ip].ty = '}';
+ ip++;
+ }
+
+ int sp_len = ip;
+ Spiro::spiro_run(path, sp_len, *curve);
+ ip = 0;
+ }
+
+ g_free (path);
}
void PenTool::_setSubsequentPoint(Geom::Point const p, bool statusbar, guint status) {
g_assert( this->npoints != 0 );
+
// todo: Check callers to see whether 2 <= npoints is guaranteed.
this->p[2] = p;
@@ -1172,7 +2070,7 @@ void PenTool::_setSubsequentPoint(Geom::Point const p, bool statusbar, guint sta
// we are drawing horizontal/vertical lines and hit an anchor;
Geom::Point const origin = this->p[0];
// if the previous point and the anchor are not aligned either horizontally or vertically...
- if ((abs(p[Geom::X] - origin[Geom::X]) > 1e-9) && (abs(p[Geom::Y] - origin[Geom::Y]) > 1e-9)) {
+ if ((std::abs(p[Geom::X] - origin[Geom::X]) > 1e-9) && (std::abs(p[Geom::Y] - origin[Geom::Y]) > 1e-9)) {
// ...then we should draw an L-shaped path, consisting of two paraxial segments
Geom::Point intermed = p;
this->_setToNearestHorizVert(intermed, status, false);
@@ -1182,7 +2080,7 @@ void PenTool::_setSubsequentPoint(Geom::Point const p, bool statusbar, guint sta
is_curve = false;
} else {
// one of the 'regular' modes
- if (this->p[1] != this->p[0]) {
+ if (this->p[1] != this->p[0] || this->spiro) {
this->red_curve->curveto(this->p[1], p, p);
is_curve = true;
} else {
@@ -1197,10 +2095,16 @@ void PenTool::_setSubsequentPoint(Geom::Point const p, bool statusbar, guint sta
gchar *message = is_curve ?
_("<b>Curve segment</b>: angle %3.2f&#176;, distance %s; with <b>Ctrl</b> to snap angle, <b>Enter</b> to finish the path" ):
_("<b>Line segment</b>: angle %3.2f&#176;, distance %s; with <b>Ctrl</b> to snap angle, <b>Enter</b> to finish the path");
+ if(this->spiro || this->bspline){
+ message = is_curve ?
+ _("<b>Curve segment</b>: angle %3.2f&#176;, distance %s; with <b>Shift+Click</b> make a cusp node, <b>Enter</b> to finish the path" ):
+ _("<b>Line segment</b>: angle %3.2f&#176;, distance %s; with <b>Shift+Click</b> make a cusp node, <b>Enter</b> to finish the path");
+ }
this->_setAngleDistanceStatusMessage(p, 0, message);
}
}
+
void PenTool::_setCtrl(Geom::Point const p, guint const state) {
sp_canvas_item_show(this->c1);
sp_canvas_item_show(this->cl1);
@@ -1211,7 +2115,6 @@ void PenTool::_setCtrl(Geom::Point const p, guint const state) {
sp_canvas_item_hide(this->cl0);
SP_CTRL(this->c1)->moveto(this->p[1]);
this->cl1->setCoords(this->p[0], this->p[1]);
-
this->_setAngleDistanceStatusMessage(p, 0, _("<b>Curve handle</b>: angle %3.2f&#176;, length %s; with <b>Ctrl</b> to snap angle"));
} else if ( this->npoints == 5 ) {
this->p[4] = p;
@@ -1233,6 +2136,8 @@ void PenTool::_setCtrl(Geom::Point const p, guint const state) {
SP_CTRL(this->c1)->moveto(this->p[4]);
this->cl1->setCoords(this->p[3], this->p[4]);
+
+
gchar *message = is_symm ?
_("<b>Curve handle, symmetric</b>: angle %3.2f&#176;, length %s; with <b>Ctrl</b> to snap angle, with <b>Shift</b> to move this handle only") :
_("<b>Curve handle</b>: angle %3.2f&#176;, length %s; with <b>Ctrl</b> to snap angle, with <b>Shift</b> to move this handle only");
@@ -1247,11 +2152,14 @@ void PenTool::_finishSegment(Geom::Point const p, guint const state) {
pen_last_paraxial_dir = this->nextParaxialDirection(p, this->p[0], state);
}
- ++this->num_clicks;
+ ++num_clicks;
+
if (!this->red_curve->is_empty()) {
+ this->_bspline_spiro(state & GDK_SHIFT_MASK);
this->green_curve->append_continuous(this->red_curve, 0.0625);
SPCurve *curve = this->red_curve->copy();
+
/// \todo fixme:
SPCanvasItem *cshape = sp_canvas_bpath_new(sp_desktop_sketch(this->desktop), curve);
curve->unref();
@@ -1273,15 +2181,19 @@ void PenTool::_finish(gboolean const closed) {
return;
}
+
this->num_clicks = 0;
this->_disableEvents();
this->message_context->clear();
+
desktop->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Drawing finished"));
+ // cancelate line without a created segment
this->red_curve->reset();
spdc_concat_colors_and_flush(this, closed);
+ this->overwriteCurve = NULL;
this->sa = NULL;
this->ea = NULL;
@@ -1330,7 +2242,7 @@ int PenTool::nextParaxialDirection(Geom::Point const &pt, Geom::Point const &ori
//
// num_clicks is not reliable because spdc_pen_finish_segment is sometimes called too early
// (on first mouse release), in which case num_clicks immediately becomes 1.
- // if (pc->num_clicks == 0) {
+ // if (this->num_clicks == 0) {
if (this->green_curve->is_empty()) {
// first mouse click
diff --git a/src/ui/tools/pen-tool.h b/src/ui/tools/pen-tool.h
index 4dec7b4fe..98fd0a43e 100644
--- a/src/ui/tools/pen-tool.h
+++ b/src/ui/tools/pen-tool.h
@@ -49,6 +49,9 @@ public:
bool polylines_only;
bool polylines_paraxial;
+ // propiety which saves if Spiro mode is active or not
+ bool spiro;
+ bool bspline;
int num_clicks;
unsigned int expecting_clicks_for_LPE; // if positive, finish the path after this many clicks
@@ -85,6 +88,34 @@ private:
bool _handleButtonRelease(GdkEventButton const &revent);
bool _handle2ButtonPress(GdkEventButton const &bevent);
bool _handleKeyPress(GdkEvent *event);
+ //adds spiro & bspline modes
+ void _pen_context_set_mode(guint mode);
+ //this function changes the colors red, green and blue making them transparent or not depending on if the function uses spiro
+ void _bspline_spiro_color();
+ //creates a node in bspline or spiro modes
+ void _bspline_spiro(bool shift);
+ //creates a node in bspline or spiro modes
+ void _bspline_spiro_on();
+ //creates a CUSP node
+ void _bspline_spiro_off();
+ //continues the existing curve in bspline or spiro mode
+ void _bspline_spiro_start_anchor(bool shift);
+ //continues the existing curve with the union node in bspline or spiro modes
+ void _bspline_spiro_start_anchor_on();
+ //continues an existing curve with the union node in CUSP mode
+ void _bspline_spiro_start_anchor_off();
+ //modifies the "red_curve" when it detects movement
+ void _bspline_spiro_motion(bool shift);
+ //closes the curve with the last node in bspline or spiro mode
+ void _bspline_spiro_end_anchor_on();
+ //closes the curve with the last node in CUSP mode
+ void _bspline_spiro_end_anchor_off();
+ //CHECK: join all the curves "in game" and we call doEffect function
+ void _bspline_spiro_build();
+ //function bspline cloned from lpe-bspline.cpp
+ void _bspline_doEffect(SPCurve * curve);
+ //function spiro cloned from lpe-spiro.cpp
+ void _spiro_doEffect(SPCurve * curve);
void _setInitialPoint(Geom::Point const p);
void _setSubsequentPoint(Geom::Point const p, bool statusbar, guint status = 0);
diff --git a/src/ui/tools/pencil-tool.cpp b/src/ui/tools/pencil-tool.cpp
index fb4e82c32..3ea2ae843 100644
--- a/src/ui/tools/pencil-tool.cpp
+++ b/src/ui/tools/pencil-tool.cpp
@@ -23,7 +23,7 @@
#include "desktop-handles.h"
#include "selection.h"
#include "selection-chemistry.h"
-#include "draw-anchor.h"
+#include "ui/draw-anchor.h"
#include "message-stack.h"
#include "message-context.h"
#include "sp-path.h"
@@ -43,7 +43,7 @@
#include "display/sp-canvas.h"
#include "display/curve.h"
#include "livarot/Path.h"
-#include "tool-factory.h"
+#include "ui/tool-factory.h"
#include "ui/tool/event-utils.h"
namespace Inkscape {
@@ -200,6 +200,7 @@ bool PencilTool::_handleButtonPress(GdkEventButton const &bevent) {
}
if (anchor) {
p = anchor->dp;
+ this->overwriteCurve = anchor->curve;
desktop->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Continuing selected path"));
} else {
m.setup(desktop);
@@ -301,7 +302,7 @@ bool PencilTool::_handleMotionNotify(GdkEventMotion const &mevent) {
if ( this->npoints != 0) { // buttonpress may have happened before we entered draw context!
if (this->ps.empty()) {
- // Only in freehand mode we have to add the first point also to pc->ps (apparently)
+ // Only in freehand mode we have to add the first point also to this->ps (apparently)
// - We cannot add this point in spdc_set_startpoint, because we only need it for freehand
// - We cannot do this in the button press handler because at that point we don't know yet
// wheter we're going into freehand mode or not
@@ -640,6 +641,9 @@ void PencilTool::_interpolate() {
return;
}
+ using Geom::X;
+ using Geom::Y;
+
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
double const tol = prefs->getDoubleLimited("/tools/freehand/pencil/tolerance", 10.0, 1.0, 100.0) * 0.4;
double const tolerance_sq = 0.02 * square(this->desktop->w2d().descrim() * tol) * exp(0.2 * tol - 2);
@@ -661,10 +665,21 @@ void PencilTool::_interpolate() {
if (n_segs > 0) {
/* Fit and draw and reset state */
- this->green_curve->moveto(b[0]);
+ this->green_curve->moveto(b[0]);
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ guint mode = prefs->getInt("/tools/freehand/pencil/freehand-mode", 0);
for (int c = 0; c < n_segs; c++) {
- this->green_curve->curveto(b[4 * c + 1], b[4 * c + 2], b[4 * c + 3]);
+ // if we are in BSpline we modify the trace to create adhoc nodes
+ if(mode == 2){
+ Geom::Point BP = b[4*c+0] + (1./3)*(b[4*c+3] - b[4*c+0]);
+ BP = Geom::Point(BP[X] + 0.0001,BP[Y] + 0.0001);
+ Geom::Point CP = b[4*c+3] + (1./3)*(b[4*c+0] - b[4*c+3]);
+ CP = Geom::Point(CP[X] + 0.0001,CP[Y] + 0.0001);
+ this->green_curve->curveto(BP,CP,b[4*c+3]);
+ }else{
+ this->green_curve->curveto(b[4 * c + 1], b[4 * c + 2], b[4 * c + 3]);
+ }
}
sp_canvas_bpath_set_bpath(SP_CANVAS_BPATH(this->red_bpath), this->green_curve);
@@ -788,6 +803,7 @@ void PencilTool::_fitAndSplit() {
g_assert(is_zero(this->req_tangent)
|| is_unit_vector(this->req_tangent));
Geom::Point const tHatEnd(0, 0);
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
int const n_segs = Geom::bezier_fit_cubic_full(b, NULL, this->p, this->npoints,
this->req_tangent, tHatEnd,
tolerance_sq, 1);
@@ -795,9 +811,22 @@ void PencilTool::_fitAndSplit() {
&& unsigned(this->npoints) < G_N_ELEMENTS(this->p) )
{
/* Fit and draw and reset state */
+
this->red_curve->reset();
this->red_curve->moveto(b[0]);
- this->red_curve->curveto(b[1], b[2], b[3]);
+ using Geom::X;
+ using Geom::Y;
+ // if we are in BSpline we modify the trace to create adhoc nodes
+ guint mode = prefs->getInt("/tools/freehand/pencil/freehand-mode", 0);
+ if(mode == 2){
+ Geom::Point B = b[0] + (1./3)*(b[3] - b[0]);
+ B = Geom::Point(B[X] + 0.0001,B[Y] + 0.0001);
+ Geom::Point C = b[3] + (1./3)*(b[0] - b[3]);
+ C = Geom::Point(C[X] + 0.0001,C[Y] + 0.0001);
+ this->red_curve->curveto(B,C,b[3]);
+ }else{
+ this->red_curve->curveto(b[1], b[2], b[3]);
+ }
sp_canvas_bpath_set_bpath(SP_CANVAS_BPATH(this->red_bpath), this->red_curve);
this->red_curve_is_valid = true;
} else {
@@ -826,6 +855,13 @@ void PencilTool::_fitAndSplit() {
/// \todo fixme:
SPCanvasItem *cshape = sp_canvas_bpath_new(sp_desktop_sketch(this->desktop), curve);
curve->unref();
+
+ this->highlight_color = SP_ITEM(this->desktop->currentLayer())->highlight_color();
+ if((unsigned int)prefs->getInt("/tools/nodes/highlight_color", 0xff0000ff) == this->highlight_color){
+ this->green_color = 0x00ff007f;
+ } else {
+ this->green_color = this->highlight_color;
+ }
sp_canvas_bpath_set_stroke(SP_CANVAS_BPATH(cshape), this->green_color, 1.0, SP_STROKE_LINEJOIN_MITER, SP_STROKE_LINECAP_BUTT);
this->green_bpaths = g_slist_prepend(this->green_bpaths, cshape);
diff --git a/src/ui/tools/rect-tool.cpp b/src/ui/tools/rect-tool.cpp
index 39f422c1a..de91dcff4 100644
--- a/src/ui/tools/rect-tool.cpp
+++ b/src/ui/tools/rect-tool.cpp
@@ -40,13 +40,13 @@
#include "xml/node-event-vector.h"
#include "preferences.h"
#include "context-fns.h"
-#include "shape-editor.h"
+#include "ui/shape-editor.h"
#include "verbs.h"
#include "display/sp-canvas-item.h"
using Inkscape::DocumentUndo;
-#include "tool-factory.h"
+#include "ui/tool-factory.h"
namespace Inkscape {
namespace UI {
@@ -102,8 +102,8 @@ RectTool::~RectTool() {
* destroys old and creates new knotholder.
*/
void RectTool::selection_changed(Inkscape::Selection* selection) {
- this->shape_editor->unset_item(SH_KNOTHOLDER);
- this->shape_editor->set_item(selection->singleItem(), SH_KNOTHOLDER);
+ this->shape_editor->unset_item();
+ this->shape_editor->set_item(selection->singleItem());
}
void RectTool::setup() {
@@ -113,7 +113,7 @@ void RectTool::setup() {
SPItem *item = sp_desktop_selection(this->desktop)->singleItem();
if (item) {
- this->shape_editor->set_item(item, SH_KNOTHOLDER);
+ this->shape_editor->set_item(item);
}
this->sel_changed_connection.disconnect();
diff --git a/src/ui/tools/rect-tool.h b/src/ui/tools/rect-tool.h
index a50fd7b24..a22f1caa8 100644
--- a/src/ui/tools/rect-tool.h
+++ b/src/ui/tools/rect-tool.h
@@ -6,6 +6,7 @@
*
* Author:
* Lauris Kaplinski <lauris@kaplinski.com>
+ * Jon A. Cruz <jon@joncruz.org>
*
* Copyright (C) 2000 Lauris Kaplinski
* Copyright (C) 2000-2001 Ximian, Inc.
@@ -21,9 +22,6 @@
#include "sp-rect.h"
-#define SP_RECT_CONTEXT(obj) (dynamic_cast<Inkscape::UI::Tools::RectTool*>((Inkscape::UI::Tools::ToolBase*)obj))
-#define SP_IS_RECT_CONTEXT(obj) (dynamic_cast<const Inkscape::UI::Tools::RectTool*>((const Inkscape::UI::Tools::ToolBase*)obj) != NULL)
-
namespace Inkscape {
namespace UI {
namespace Tools {
diff --git a/src/ui/tools/select-tool.cpp b/src/ui/tools/select-tool.cpp
index 83bef17c9..a8267ea1d 100644
--- a/src/ui/tools/select-tool.cpp
+++ b/src/ui/tools/select-tool.cpp
@@ -41,7 +41,7 @@
#include "desktop-handles.h"
#include "sp-root.h"
#include "preferences.h"
-#include "tools-switch.h"
+#include "ui/tools-switch.h"
#include "message-stack.h"
#include "selection-describer.h"
#include "seltrans.h"
@@ -49,7 +49,7 @@
#include "display/sp-canvas.h"
#include "display/sp-canvas-item.h"
#include "display/drawing-item.h"
-#include "tool-factory.h"
+#include "ui/tool-factory.h"
using Inkscape::DocumentUndo;
@@ -264,15 +264,16 @@ sp_select_context_up_one_layer(SPDesktop *desktop)
SPObject *const current_layer = desktop->currentLayer();
if (current_layer) {
SPObject *const parent = current_layer->parent;
+ SPGroup *current_group = dynamic_cast<SPGroup *>(current_layer);
if ( parent
&& ( parent->parent
- || !( SP_IS_GROUP(current_layer)
- && ( SPGroup::LAYER
- == SP_GROUP(current_layer)->layerMode() ) ) ) )
+ || !( current_group
+ && ( SPGroup::LAYER == current_group->layerMode() ) ) ) )
{
desktop->setCurrentLayer(parent);
- if (SP_IS_GROUP(current_layer) && SPGroup::LAYER != SP_GROUP(current_layer)->layerMode())
+ if (current_group && (SPGroup::LAYER != current_group->layerMode())) {
sp_desktop_selection(desktop)->set(current_layer);
+ }
}
}
}
@@ -403,7 +404,8 @@ void SelectTool::sp_select_context_cycle_through_items(Inkscape::Selection *sele
}
Inkscape::DrawingItem *arenaitem;
- SPItem *item = SP_ITEM(this->cycling_cur_item->data);
+ SPItem *item = dynamic_cast<SPItem *>(static_cast<SPObject *>(cycling_cur_item->data));
+ g_assert(item != NULL);
// Deactivate current item
if (!g_list_find(this->cycling_items_selected_before, item) && selection->includes(item)) {
@@ -427,7 +429,8 @@ void SelectTool::sp_select_context_cycle_through_items(Inkscape::Selection *sele
if (next) {
this->cycling_cur_item = next;
- item = SP_ITEM(this->cycling_cur_item->data);
+ item = dynamic_cast<SPItem *>(static_cast<SPObject *>(this->cycling_cur_item->data));
+ g_assert(item != NULL);
}
arenaitem = item->get_arenaitem(desktop->dkey);
@@ -442,8 +445,13 @@ void SelectTool::sp_select_context_cycle_through_items(Inkscape::Selection *sele
void SelectTool::sp_select_context_reset_opacities() {
for (GList *l = this->cycling_items; l != NULL; l = g_list_next(l)) {
- Inkscape::DrawingItem *arenaitem = SP_ITEM(l->data)->get_arenaitem(this->desktop->dkey);
- arenaitem->setOpacity(SP_SCALE24_TO_FLOAT(SP_ITEM(l->data)->style->opacity.value));
+ SPItem *item = dynamic_cast<SPItem *>(static_cast<SPObject *>(l->data));
+ if (item) {
+ Inkscape::DrawingItem *arenaitem = item->get_arenaitem(desktop->dkey);
+ arenaitem->setOpacity(SP_SCALE24_TO_FLOAT(item->style->opacity.value));
+ } else {
+ g_assert_not_reached();
+ }
}
g_list_free(this->cycling_items);
@@ -475,8 +483,8 @@ bool SelectTool::root_handler(GdkEvent* event) {
if (!selection->isEmpty()) {
SPItem *clicked_item = static_cast<SPItem *>(selection->itemList()->data);
- if (SP_IS_GROUP(clicked_item) && !SP_IS_BOX3D(clicked_item)) { // enter group if it's not a 3D box
- desktop->setCurrentLayer(reinterpret_cast<SPObject *>(clicked_item));
+ if (dynamic_cast<SPGroup *>(clicked_item) && !dynamic_cast<SPBox3D *>(clicked_item)) { // enter group if it's not a 3D box
+ desktop->setCurrentLayer(clicked_item);
sp_desktop_selection(desktop)->clear();
this->dragging = false;
sp_event_context_discard_delayed_snap_event(this);
@@ -591,8 +599,11 @@ bool SelectTool::root_handler(GdkEvent* event) {
item_in_group = desktop->getItemAtPoint(Geom::Point(event->button.x, event->button.y), TRUE);
group_at_point = desktop->getGroupAtPoint(Geom::Point(event->button.x, event->button.y));
- if (SP_IS_LAYER(selection->single())) {
- group_at_point = SP_GROUP(selection->single());
+ {
+ SPGroup *selGroup = dynamic_cast<SPGroup *>(selection->single());
+ if (selGroup && (selGroup->layerMode() == SPGroup::LAYER)) {
+ group_at_point = selGroup;
+ }
}
// group-at-point is meant to be topmost item if it's a group,
@@ -673,10 +684,11 @@ bool SelectTool::root_handler(GdkEvent* event) {
selection->toggle(this->item);
} else {
SPObject* single = selection->single();
+ SPGroup *singleGroup = dynamic_cast<SPGroup *>(single);
// without shift, increase state (i.e. toggle scale/rotation handles)
if (selection->includes(this->item)) {
_seltrans->increaseState();
- } else if (SP_IS_LAYER(single) && single->isAncestorOf(this->item)) {
+ } else if (singleGroup && (singleGroup->layerMode() == SPGroup::LAYER) && single->isAncestorOf(this->item)) {
_seltrans->increaseState();
} else {
_seltrans->resetState();
@@ -818,7 +830,7 @@ bool SelectTool::root_handler(GdkEvent* event) {
SPItem *item = desktop->getItemAtPoint(p, true, NULL);
// Save pointer to current cycle-item so that we can find it again later, in the freshly built list
- SPItem *tmp_cur_item = this->cycling_cur_item ? SP_ITEM(this->cycling_cur_item->data) : NULL;
+ SPItem *tmp_cur_item = this->cycling_cur_item ? dynamic_cast<SPItem *>(static_cast<SPObject *>(this->cycling_cur_item->data)) : NULL;
g_list_free(this->cycling_items);
this->cycling_items = NULL;
this->cycling_cur_item = NULL;
@@ -851,11 +863,14 @@ bool SelectTool::root_handler(GdkEvent* event) {
Inkscape::DrawingItem *arenaitem;
for(GList *l = this->cycling_items_cmp; l != NULL; l = l->next) {
- arenaitem = SP_ITEM(l->data)->get_arenaitem(desktop->dkey);
- arenaitem->setOpacity(1.0);
- //if (!shift_pressed && !g_list_find(this->cycling_items_selected_before, SP_ITEM(l->data)) && selection->includes(SP_ITEM(l->data)))
- if (!g_list_find(this->cycling_items_selected_before, SP_ITEM(l->data)) && selection->includes(SP_ITEM(l->data))) {
- selection->remove(SP_ITEM(l->data));
+ SPItem *item = dynamic_cast<SPItem *>(static_cast<SPObject *>(l->data));
+ if (item) {
+ arenaitem = item->get_arenaitem(desktop->dkey);
+ arenaitem->setOpacity(1.0);
+ //if (!shift_pressed && !g_list_find(this->cycling_items_selected_before, item) && selection->includes(item))
+ if (!g_list_find(this->cycling_items_selected_before, item) && selection->includes(item)) {
+ selection->remove(item);
+ }
}
}
@@ -869,16 +884,19 @@ bool SelectTool::root_handler(GdkEvent* event) {
// ... and rebuild them with the new items.
this->cycling_items_cmp = g_list_copy(this->cycling_items);
- SPItem *item;
for(GList *l = this->cycling_items; l != NULL; l = l->next) {
- item = SP_ITEM(l->data);
- arenaitem = item->get_arenaitem(desktop->dkey);
- arenaitem->setOpacity(0.3);
-
- if (selection->includes(item)) {
- // already selected items are stored separately, too
- this->cycling_items_selected_before = g_list_append(this->cycling_items_selected_before, item);
+ SPItem *item = dynamic_cast<SPItem *>(static_cast<SPObject *>(l->data));
+ if (item) {
+ arenaitem = item->get_arenaitem(desktop->dkey);
+ arenaitem->setOpacity(0.3);
+
+ if (selection->includes(item)) {
+ // already selected items are stored separately, too
+ this->cycling_items_selected_before = g_list_append(this->cycling_items_selected_before, item);
+ }
+ } else {
+ g_assert_not_reached();
}
}
@@ -1134,9 +1152,9 @@ bool SelectTool::root_handler(GdkEvent* event) {
if (MOD__CTRL_ONLY(event)) {
if (selection->singleItem()) {
SPItem *clicked_item = selection->singleItem();
-
- if ( SP_IS_GROUP(clicked_item) || SP_IS_BOX3D(clicked_item)) { // enter group or a 3D box
- desktop->setCurrentLayer(reinterpret_cast<SPObject *>(clicked_item));
+ SPGroup *clickedGroup = dynamic_cast<SPGroup *>(clicked_item);
+ if ( (clickedGroup && (clickedGroup->layerMode() != SPGroup::LAYER)) || dynamic_cast<SPBox3D *>(clicked_item)) { // enter group or a 3D box
+ desktop->setCurrentLayer(clicked_item);
sp_desktop_selection(desktop)->clear();
} else {
this->desktop->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Selected object is not a group. Cannot enter."));
diff --git a/src/ui/tools/select-tool.h b/src/ui/tools/select-tool.h
index edc4069a2..5af99a56a 100644
--- a/src/ui/tools/select-tool.h
+++ b/src/ui/tools/select-tool.h
@@ -13,7 +13,6 @@
*/
#include "ui/tools/tool-base.h"
-#include <gtk/gtk.h>
#define SP_SELECT_CONTEXT(obj) (dynamic_cast<Inkscape::UI::Tools::SelectTool*>((Inkscape::UI::Tools::ToolBase*)obj))
#define SP_IS_SELECT_CONTEXT(obj) (dynamic_cast<const Inkscape::UI::Tools::SelectTool*>((const Inkscape::UI::Tools::ToolBase*)obj) != NULL)
diff --git a/src/ui/tools/spiral-tool.cpp b/src/ui/tools/spiral-tool.cpp
index 5ae229df8..18c3e4e2d 100644
--- a/src/ui/tools/spiral-tool.cpp
+++ b/src/ui/tools/spiral-tool.cpp
@@ -39,13 +39,13 @@
#include "xml/node-event-vector.h"
#include "preferences.h"
#include "context-fns.h"
-#include "shape-editor.h"
+#include "ui/shape-editor.h"
#include "verbs.h"
#include "display/sp-canvas-item.h"
using Inkscape::DocumentUndo;
-#include "tool-factory.h"
+#include "ui/tool-factory.h"
namespace Inkscape {
namespace UI {
@@ -104,8 +104,8 @@ SpiralTool::~SpiralTool() {
* destroys old and creates new knotholder.
*/
void SpiralTool::selection_changed(Inkscape::Selection *selection) {
- this->shape_editor->unset_item(SH_KNOTHOLDER);
- this->shape_editor->set_item(selection->singleItem(), SH_KNOTHOLDER);
+ this->shape_editor->unset_item();
+ this->shape_editor->set_item(selection->singleItem());
}
void SpiralTool::setup() {
@@ -119,7 +119,7 @@ void SpiralTool::setup() {
SPItem *item = sp_desktop_selection(this->desktop)->singleItem();
if (item) {
- this->shape_editor->set_item(item, SH_KNOTHOLDER);
+ this->shape_editor->set_item(item);
}
Inkscape::Selection *selection = sp_desktop_selection(this->desktop);
diff --git a/src/ui/tools/spiral-tool.h b/src/ui/tools/spiral-tool.h
index 416aeb7e4..add92342d 100644
--- a/src/ui/tools/spiral-tool.h
+++ b/src/ui/tools/spiral-tool.h
@@ -15,17 +15,15 @@
* Released under GNU GPL
*/
-#include <gtk/gtk.h>
-#include <stddef.h>
-#include <sigc++/sigc++.h>
+#include <sigc++/connection.h>
#include <2geom/point.h>
#include "ui/tools/tool-base.h"
-#include "sp-spiral.h"
-
#define SP_SPIRAL_CONTEXT(obj) (dynamic_cast<Inkscape::UI::Tools::SpiralTool*>((Inkscape::UI::Tools::ToolBase*)obj))
#define SP_IS_SPIRAL_CONTEXT(obj) (dynamic_cast<const Inkscape::UI::Tools::SpiralTool*>((const Inkscape::UI::Tools::ToolBase*)obj) != NULL)
+class SPSpiral;
+
namespace Inkscape {
namespace UI {
namespace Tools {
diff --git a/src/ui/tools/spray-tool.cpp b/src/ui/tools/spray-tool.cpp
index 08d3119a1..cdc608558 100644
--- a/src/ui/tools/spray-tool.cpp
+++ b/src/ui/tools/spray-tool.cpp
@@ -84,7 +84,7 @@ using namespace std;
// Please enable again when working on 1.0
#define ENABLE_SPRAY_MODE_SINGLE_PATH
-#include "tool-factory.h"
+#include "ui/tool-factory.h"
namespace Inkscape {
namespace UI {
@@ -384,11 +384,14 @@ static bool sp_spray_recursive(SPDesktop *desktop,
gint _distrib)
{
bool did = false;
-
- if (SP_IS_BOX3D(item) ) {
- // convert 3D boxes to ordinary groups before spraying their shapes
- item = box3d_convert_to_group(SP_BOX3D(item));
- selection->add(item);
+
+ {
+ SPBox3D *box = dynamic_cast<SPBox3D *>(item);
+ if (box) {
+ // convert 3D boxes to ordinary groups before spraying their shapes
+ item = box3d_convert_to_group(box);
+ selection->add(item);
+ }
}
double _fid = g_random_double_range(0, 1);
@@ -413,7 +416,7 @@ static bool sp_spray_recursive(SPDesktop *desktop,
parent->appendChild(copy);
SPObject *new_obj = doc->getObjectByRepr(copy);
- item_copied = SP_ITEM(new_obj); // Convertion object->item
+ item_copied = dynamic_cast<SPItem *>(new_obj); // Convertion object->item
Geom::Point center=item->getCenter();
sp_spray_scale_rel(center,desktop, item_copied, Geom::Scale(_scale,_scale));
sp_spray_scale_rel(center,desktop, item_copied, Geom::Scale(scale,scale));
@@ -437,7 +440,7 @@ static bool sp_spray_recursive(SPDesktop *desktop,
items != NULL;
items = items->next) {
- SPItem *item1 = SP_ITEM(items->data);
+ SPItem *item1 = dynamic_cast<SPItem *>(static_cast<SPObject *>(items->data));
if (i == 1) {
parent_item = item1;
}
@@ -458,7 +461,7 @@ static bool sp_spray_recursive(SPDesktop *desktop,
Inkscape::XML::Node *copy = old_repr->duplicate(xml_doc);
parent->appendChild(copy);
SPObject *new_obj = doc->getObjectByRepr(copy);
- item_copied = SP_ITEM(new_obj);
+ item_copied = dynamic_cast<SPItem *>(new_obj);
// Move around the cursor
Geom::Point move = (Geom::Point(cos(tilt)*cos(dp)*dr/(1-ratio)+sin(tilt)*sin(dp)*dr/(1+ratio), -sin(tilt)*cos(dp)*dr/(1-ratio)+cos(tilt)*sin(dp)*dr/(1+ratio)))+(p-a->midpoint());
@@ -503,7 +506,7 @@ static bool sp_spray_recursive(SPDesktop *desktop,
SPObject *clone_object = doc->getObjectByRepr(clone);
// Conversion object->item
- item_copied = SP_ITEM(clone_object);
+ item_copied = dynamic_cast<SPItem *>(clone_object);
Geom::Point center = item->getCenter();
sp_spray_scale_rel(center, desktop, item_copied, Geom::Scale(_scale, _scale));
sp_spray_scale_rel(center, desktop, item_copied, Geom::Scale(scale, scale));
@@ -554,13 +557,16 @@ static bool sp_spray_dilate(SprayTool *tc, Geom::Point /*event_p*/, Geom::Point
for (GSList *items = original_selection;
items != NULL;
items = items->next) {
- sp_object_ref(SP_ITEM(items->data));
+ SPItem *item = dynamic_cast<SPItem *>(static_cast<SPObject *>(items->data));
+ g_assert(item != NULL);
+ sp_object_ref(item);
}
for (GSList *items = original_selection;
items != NULL;
items = items->next) {
- SPItem *item = SP_ITEM(items->data);
+ SPItem *item = dynamic_cast<SPItem *>(static_cast<SPObject *>(items->data));
+ g_assert(item != NULL);
if (is_transform_modes(tc->mode)) {
if (sp_spray_recursive(desktop, selection, item, p, vector, tc->mode, radius, move_force, tc->population, tc->scale, tc->scale_variation, reverse, move_mean, move_standard_deviation, tc->ratio, tc->tilt, tc->rotation_variation, tc->distrib)) {
@@ -576,7 +582,9 @@ static bool sp_spray_dilate(SprayTool *tc, Geom::Point /*event_p*/, Geom::Point
for (GSList *items = original_selection;
items != NULL;
items = items->next) {
- sp_object_unref(SP_ITEM(items->data));
+ SPItem *item = dynamic_cast<SPItem *>(static_cast<SPObject *>(items->data));
+ g_assert(item != NULL);
+ sp_object_unref(item);
}
}
@@ -677,7 +685,7 @@ bool SprayTool::root_handler(GdkEvent* event) {
desktop->setToolboxAdjustmentValue("population", this->population * 100);
Geom::Point const scroll_w(event->button.x, event->button.y);
Geom::Point const scroll_dt = desktop->point();;
- Geom::Point motion_doc(desktop->dt2doc(scroll_dt));
+
switch (event->scroll.direction) {
case GDK_SCROLL_DOWN:
case GDK_SCROLL_UP: {
diff --git a/src/ui/tools/star-tool.cpp b/src/ui/tools/star-tool.cpp
index 68f998920..7604ba04e 100644
--- a/src/ui/tools/star-tool.cpp
+++ b/src/ui/tools/star-tool.cpp
@@ -41,7 +41,7 @@
#include "xml/repr.h"
#include "xml/node-event-vector.h"
#include "context-fns.h"
-#include "shape-editor.h"
+#include "ui/shape-editor.h"
#include "verbs.h"
#include "display/sp-canvas-item.h"
@@ -49,7 +49,7 @@
using Inkscape::DocumentUndo;
-#include "tool-factory.h"
+#include "ui/tool-factory.h"
namespace Inkscape {
namespace UI {
@@ -112,8 +112,8 @@ StarTool::~StarTool() {
void StarTool::selection_changed(Inkscape::Selection* selection) {
g_assert (selection != NULL);
- this->shape_editor->unset_item(SH_KNOTHOLDER);
- this->shape_editor->set_item(selection->singleItem(), SH_KNOTHOLDER);
+ this->shape_editor->unset_item();
+ this->shape_editor->set_item(selection->singleItem());
}
void StarTool::setup() {
@@ -129,7 +129,7 @@ void StarTool::setup() {
SPItem *item = sp_desktop_selection(this->desktop)->singleItem();
if (item) {
- this->shape_editor->set_item(item, SH_KNOTHOLDER);
+ this->shape_editor->set_item(item);
}
Inkscape::Selection *selection = sp_desktop_selection(this->desktop);
diff --git a/src/ui/tools/text-tool.cpp b/src/ui/tools/text-tool.cpp
index ac830fe6b..a72748733 100644
--- a/src/ui/tools/text-tool.cpp
+++ b/src/ui/tools/text-tool.cpp
@@ -40,7 +40,7 @@
#include "rubberband.h"
#include "selection-chemistry.h"
#include "selection.h"
-#include "shape-editor.h"
+#include "ui/shape-editor.h"
#include "sp-flowtext.h"
#include "sp-namedview.h"
#include "sp-text.h"
@@ -52,7 +52,7 @@
#include "xml/node-event-vector.h"
#include "xml/repr.h"
#include <gtk/gtk.h>
-#include "tool-factory.h"
+#include "ui/tool-factory.h"
using Inkscape::ControlManager;
using Inkscape::DocumentUndo;
@@ -177,7 +177,7 @@ void TextTool::setup() {
SPItem *item = sp_desktop_selection(this->desktop)->singleItem();
if (item && SP_IS_FLOWTEXT(item) && SP_FLOWTEXT(item)->has_internal_frame()) {
- this->shape_editor->set_item(item, SH_KNOTHOLDER);
+ this->shape_editor->set_item(item);
}
this->sel_changed_connection = sp_desktop_selection(desktop)->connectChangedFirst(
@@ -1411,10 +1411,10 @@ void TextTool::_selectionChanged(Inkscape::Selection *selection)
ToolBase *ec = SP_EVENT_CONTEXT(this);
- ec->shape_editor->unset_item(SH_KNOTHOLDER);
+ ec->shape_editor->unset_item();
SPItem *item = selection->singleItem();
if (item && SP_IS_FLOWTEXT(item) && SP_FLOWTEXT(item)->has_internal_frame()) {
- ec->shape_editor->set_item(item, SH_KNOTHOLDER);
+ ec->shape_editor->set_item(item);
}
if (this->text && (item != this->text)) {
diff --git a/src/ui/tools/text-tool.h b/src/ui/tools/text-tool.h
index ca2b3d19a..289ee180d 100644
--- a/src/ui/tools/text-tool.h
+++ b/src/ui/tools/text-tool.h
@@ -14,10 +14,7 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-/* #include <gdk/gdkic.h> */
-#include <stddef.h>
-#include <sigc++/sigc++.h>
-#include <gtk/gtk.h>
+#include <sigc++/connection.h>
#include "ui/tools/tool-base.h"
#include <2geom/point.h>
@@ -26,6 +23,8 @@
#define SP_TEXT_CONTEXT(obj) (dynamic_cast<Inkscape::UI::Tools::TextTool*>((Inkscape::UI::Tools::ToolBase*)obj))
#define SP_IS_TEXT_CONTEXT(obj) (dynamic_cast<const Inkscape::UI::Tools::TextTool*>((const Inkscape::UI::Tools::ToolBase*)obj) != NULL)
+typedef struct _GtkIMContext GtkIMContext;
+
struct SPCtrlLine;
namespace Inkscape {
diff --git a/src/ui/tools/tool-base.cpp b/src/ui/tools/tool-base.cpp
index 4195c9eb2..37ca5eeea 100644
--- a/src/ui/tools/tool-base.cpp
+++ b/src/ui/tools/tool-base.cpp
@@ -18,6 +18,8 @@
# include "config.h"
#endif
+#include "widgets/desktop-widget.h"
+
#if GLIBMM_DISABLE_DEPRECATED && HAVE_GLIBMM_THREADS_H
#include <glibmm/threads.h>
#endif
@@ -40,12 +42,11 @@
#include "desktop-handles.h"
#include "desktop-events.h"
#include "desktop-style.h"
-#include "widgets/desktop-widget.h"
#include "sp-namedview.h"
#include "selection.h"
-#include "interface.h"
+#include "ui/interface.h"
#include "macros.h"
-#include "tools-switch.h"
+#include "ui/tools-switch.h"
#include "preferences.h"
#include "message-context.h"
#include "gradient-drag.h"
@@ -54,10 +55,11 @@
#include "selcue.h"
#include "ui/tools/lpe-tool.h"
#include "ui/tool/control-point.h"
-#include "shape-editor.h"
+#include "ui/shape-editor.h"
#include "sp-guide.h"
#include "color.h"
#include "knot.h"
+#include "knot-ptr.h"
// globals for temporary switching to selector by space
static bool selector_toggled = FALSE;
@@ -1289,8 +1291,7 @@ void sp_event_context_snap_delay_handler(ToolBase *ec,
// now, just in case there's no future motion event that drops under the speed limit (when
// stopping abruptly)
delete ec->_delayed_snap_event;
- ec->_delayed_snap_event = new DelayedSnapEvent(ec, dse_item, dse_item2,
- event, origin); // watchdog is reset, i.e. pushed forward in time
+ ec->_delayed_snap_event = new DelayedSnapEvent(ec, dse_item, dse_item2, event, origin); // watchdog is reset, i.e. pushed forward in time
// If the watchdog expires before a new motion event is received, we will snap (as explained
// above). This means however that when the timer is too short, we will always snap and that the
// speed threshold is ineffective. In the extreme case the delay is set to zero, and snapping will
@@ -1301,15 +1302,13 @@ void sp_event_context_snap_delay_handler(ToolBase *ec,
// snap, and set a new watchdog again.
if (ec->_delayed_snap_event == NULL) { // no watchdog has been set
// it might have already expired, so we'll set a new one; the snapping frequency will be limited this way
- ec->_delayed_snap_event = new DelayedSnapEvent(ec, dse_item,
- dse_item2, event, origin);
+ ec->_delayed_snap_event = new DelayedSnapEvent(ec, dse_item, dse_item2, event, origin);
} // else: watchdog has been set before and we'll wait for it to expire
}
} else {
// This is the first GDK_MOTION_NOTIFY event, so postpone snapping and set the watchdog
g_assert(ec->_delayed_snap_event == NULL);
- ec->_delayed_snap_event = new DelayedSnapEvent(ec, dse_item, dse_item2,
- event, origin);
+ ec->_delayed_snap_event = new DelayedSnapEvent(ec, dse_item, dse_item2, event, origin);
}
prev_pos = event_pos;
@@ -1362,6 +1361,7 @@ gboolean sp_event_context_snap_watchdog_callback(gpointer data) {
break;
case DelayedSnapEvent::KNOT_HANDLER: {
gpointer knot = dse->getItem2();
+ check_if_knot_deleted(knot);
if (knot && SP_IS_KNOT(knot)) {
sp_knot_handler_request_position(dse->getEvent(), SP_KNOT(knot));
}
diff --git a/src/ui/tools/tool-base.h b/src/ui/tools/tool-base.h
index b27de9030..7a6ab83e7 100644
--- a/src/ui/tools/tool-base.h
+++ b/src/ui/tools/tool-base.h
@@ -30,7 +30,6 @@ namespace Glib {
class GrDrag;
class SPDesktop;
class SPItem;
-class ShapeEditor;
namespace Inkscape {
class MessageContext;
@@ -42,6 +41,9 @@ namespace Inkscape {
namespace Inkscape {
namespace UI {
+
+class ShapeEditor;
+
namespace Tools {
class ToolBase;
diff --git a/src/ui/tools/tweak-tool.cpp b/src/ui/tools/tweak-tool.cpp
index 75650d3af..f56975de2 100644
--- a/src/ui/tools/tweak-tool.cpp
+++ b/src/ui/tools/tweak-tool.cpp
@@ -91,7 +91,7 @@ using Inkscape::DocumentUndo;
#define DYNA_MIN_WIDTH 1.0e-6
-#include "tool-factory.h"
+#include "ui/tool-factory.h"
namespace Inkscape {
namespace UI {
@@ -372,13 +372,16 @@ sp_tweak_dilate_recursive (Inkscape::Selection *selection, SPItem *item, Geom::P
{
bool did = false;
- if (SP_IS_BOX3D(item) && !is_transform_mode(mode) && !is_color_mode(mode)) {
- // convert 3D boxes to ordinary groups before tweaking their shapes
- item = box3d_convert_to_group(SP_BOX3D(item));
- selection->add(item);
+ {
+ SPBox3D *box = dynamic_cast<SPBox3D *>(item);
+ if (box && !is_transform_mode(mode) && !is_color_mode(mode)) {
+ // convert 3D boxes to ordinary groups before tweaking their shapes
+ item = box3d_convert_to_group(box);
+ selection->add(item);
+ }
}
- if (SP_IS_TEXT(item) || SP_IS_FLOWTEXT(item)) {
+ if (dynamic_cast<SPText *>(item) || dynamic_cast<SPFlowtext *>(item)) {
GSList *items = g_slist_prepend (NULL, item);
GSList *selected = NULL;
GSList *to_select = NULL;
@@ -387,22 +390,25 @@ sp_tweak_dilate_recursive (Inkscape::Selection *selection, SPItem *item, Geom::P
g_slist_free (items);
SPObject* newObj = doc->getObjectByRepr(static_cast<Inkscape::XML::Node *>(to_select->data));
g_slist_free (to_select);
- item = SP_ITEM(newObj);
+ item = dynamic_cast<SPItem *>(newObj);
+ g_assert(item != NULL);
selection->add(item);
}
- if (SP_IS_GROUP(item) && !SP_IS_BOX3D(item)) {
+ if (dynamic_cast<SPGroup *>(item) && !dynamic_cast<SPBox3D *>(item)) {
GSList *children = NULL;
for (SPObject *child = item->firstChild() ; child; child = child->getNext() ) {
- if (SP_IS_ITEM(child)) {
+ if (dynamic_cast<SPItem *>(static_cast<SPObject *>(child))) {
children = g_slist_prepend(children, child);
}
}
for (GSList *i = children; i; i = i->next) {
- SPItem *child = SP_ITEM(i->data);
- if (sp_tweak_dilate_recursive (selection, SP_ITEM(child), p, vector, mode, radius, force, fidelity, reverse))
+ SPItem *child = dynamic_cast<SPItem *>(static_cast<SPObject *>(i->data));
+ g_assert(child != NULL);
+ if (sp_tweak_dilate_recursive (selection, child, p, vector, mode, radius, force, fidelity, reverse)) {
did = true;
+ }
}
g_slist_free(children);
@@ -509,13 +515,13 @@ sp_tweak_dilate_recursive (Inkscape::Selection *selection, SPItem *item, Geom::P
}
}
- } else if (SP_IS_PATH(item) || SP_IS_SHAPE(item)) {
+ } else if (dynamic_cast<SPPath *>(item) || dynamic_cast<SPShape *>(item)) {
Inkscape::XML::Node *newrepr = NULL;
gint pos = 0;
Inkscape::XML::Node *parent = NULL;
char const *id = NULL;
- if (!SP_IS_PATH(item)) {
+ if (!dynamic_cast<SPPath *>(item)) {
newrepr = sp_selected_item_to_curved_repr(item, 0);
if (!newrepr) {
return false;
@@ -631,7 +637,8 @@ sp_tweak_dilate_recursive (Inkscape::Selection *selection, SPItem *item, Geom::P
if (newrepr) {
newrepr->setAttribute("d", str);
} else {
- if (SP_IS_LPE_ITEM(item) && SP_LPE_ITEM(item)->hasPathEffectRecursive()) {
+ SPLPEItem *lpeitem = dynamic_cast<SPLPEItem *>(item);
+ if (lpeitem && lpeitem->hasPathEffectRecursive()) {
item->getRepr()->setAttribute("inkscape:original-d", str);
} else {
item->getRepr()->setAttribute("d", str);
@@ -769,7 +776,7 @@ static void tweak_colors_in_gradient(SPItem *item, Inkscape::PaintTarget fill_or
{
SPGradient *gradient = getGradient(item, fill_or_stroke);
- if (!gradient || !SP_IS_GRADIENT(gradient)) {
+ if (!gradient || !dynamic_cast<SPGradient *>(gradient)) {
return;
}
@@ -780,9 +787,9 @@ static void tweak_colors_in_gradient(SPItem *item, Inkscape::PaintTarget fill_or
double pos = 0;
double r = 0;
- if (SP_IS_LINEARGRADIENT(gradient)) {
- SPLinearGradient *lg = SP_LINEARGRADIENT(gradient);
+ SPLinearGradient *lg = dynamic_cast<SPLinearGradient *>(gradient);
+ if (lg) {
Geom::Point p1(lg->x1.computed, lg->y1.computed);
Geom::Point p2(lg->x2.computed, lg->y2.computed);
Geom::Point pdiff(p2 - p1);
@@ -800,11 +807,13 @@ static void tweak_colors_in_gradient(SPItem *item, Inkscape::PaintTarget fill_or
// Calculate radius in lenfth-of-gradient-line units
r = radius / vl;
- } else if (SP_IS_RADIALGRADIENT(gradient)) {
- SPRadialGradient *rg = SP_RADIALGRADIENT(gradient);
- Geom::Point c (rg->cx.computed, rg->cy.computed);
- pos = Geom::L2(p - c) / rg->r.computed;
- r = radius / rg->r.computed;
+ } else {
+ SPRadialGradient *rg = dynamic_cast<SPRadialGradient *>(gradient);
+ if (rg) {
+ Geom::Point c (rg->cx.computed, rg->cy.computed);
+ pos = Geom::L2(p - c) / rg->r.computed;
+ r = radius / rg->r.computed;
+ }
}
// Normalize pos to 0..1, taking into accound gradient spread:
@@ -836,14 +845,16 @@ static void tweak_colors_in_gradient(SPItem *item, Inkscape::PaintTarget fill_or
double offset_h = 0;
SPObject *child_prev = NULL;
for (SPObject *child = vector->firstChild(); child; child = child->getNext()) {
- if (!SP_IS_STOP(child)) {
+ SPStop *stop = dynamic_cast<SPStop *>(child);
+ if (!stop) {
continue;
}
- SPStop *stop = SP_STOP (child);
offset_h = stop->offset;
if (child_prev) {
+ SPStop *prevStop = dynamic_cast<SPStop *>(child_prev);
+ g_assert(prevStop != NULL);
if (offset_h - offset_l > r && pos_e >= offset_l && pos_e <= offset_h) {
// the summit falls in this interstop, and the radius is small,
@@ -853,9 +864,9 @@ static void tweak_colors_in_gradient(SPItem *item, Inkscape::PaintTarget fill_or
tweak_color (mode, stop->specified_color.v.c, rgb_goal,
force * (pos_e - offset_l) / (offset_h - offset_l),
do_h, do_s, do_l);
- tweak_color (mode, SP_STOP(child_prev)->specified_color.v.c, rgb_goal,
- force * (offset_h - pos_e) / (offset_h - offset_l),
- do_h, do_s, do_l);
+ tweak_color(mode, prevStop->specified_color.v.c, rgb_goal,
+ force * (offset_h - pos_e) / (offset_h - offset_l),
+ do_h, do_s, do_l);
stop->updateRepr();
child_prev->updateRepr();
break;
@@ -863,9 +874,9 @@ static void tweak_colors_in_gradient(SPItem *item, Inkscape::PaintTarget fill_or
// wide brush, may affect more than 2 stops,
// paint each stop by the force from the profile curve
if (offset_l <= pos_e && offset_l > pos_e - r) {
- tweak_color (mode, SP_STOP(child_prev)->specified_color.v.c, rgb_goal,
- force * tweak_profile (fabs (pos_e - offset_l), r),
- do_h, do_s, do_l);
+ tweak_color(mode, prevStop->specified_color.v.c, rgb_goal,
+ force * tweak_profile (fabs (pos_e - offset_l), r),
+ do_h, do_s, do_l);
child_prev->updateRepr();
}
@@ -894,10 +905,11 @@ sp_tweak_color_recursive (guint mode, SPItem *item, SPItem *item_at_point,
{
bool did = false;
- if (SP_IS_GROUP(item)) {
+ if (dynamic_cast<SPGroup *>(item)) {
for (SPObject *child = item->firstChild() ; child; child = child->getNext() ) {
- if (SP_IS_ITEM(child)) {
- if (sp_tweak_color_recursive (mode, SP_ITEM(child), item_at_point,
+ SPItem *childItem = dynamic_cast<SPItem *>(child);
+ if (childItem) {
+ if (sp_tweak_color_recursive (mode, childItem, item_at_point,
fill_goal, do_fill,
stroke_goal, do_stroke,
opacity_goal, do_opacity,
@@ -953,11 +965,11 @@ sp_tweak_color_recursive (guint mode, SPItem *item, SPItem *item_at_point,
//cycle through filter primitives
SPObject *primitive_obj = style->getFilter()->children;
while (primitive_obj) {
- if (SP_IS_FILTER_PRIMITIVE(primitive_obj)) {
- SPFilterPrimitive *primitive = SP_FILTER_PRIMITIVE(primitive_obj);
+ SPFilterPrimitive *primitive = dynamic_cast<SPFilterPrimitive *>(primitive_obj);
+ if (primitive) {
//if primitive is gaussianblur
- if(SP_IS_GAUSSIANBLUR(primitive)) {
- SPGaussianBlur * spblur = SP_GAUSSIANBLUR(primitive);
+ SPGaussianBlur * spblur = dynamic_cast<SPGaussianBlur *>(primitive);
+ if (spblur) {
float num = spblur->stdDeviation.getNumber();
blur_now += num * i2dt.descrim(); // sum all blurs in the filter
}
@@ -1080,7 +1092,7 @@ sp_tweak_dilate (TweakTool *tc, Geom::Point event_p, Geom::Point p, Geom::Point
items != NULL;
items = items->next) {
- SPItem *item = SP_ITEM(items->data);
+ SPItem *item = dynamic_cast<SPItem *>(static_cast<SPObject *>(items->data));
if (is_color_mode (tc->mode)) {
if (do_fill || do_stroke || do_opacity) {
diff --git a/src/ui/tools/zoom-tool.cpp b/src/ui/tools/zoom-tool.cpp
index 9f99cfe2e..b3fb78c8f 100644
--- a/src/ui/tools/zoom-tool.cpp
+++ b/src/ui/tools/zoom-tool.cpp
@@ -25,7 +25,7 @@
#include "selection-chemistry.h"
#include "ui/tools/zoom-tool.h"
-#include "tool-factory.h"
+#include "ui/tool-factory.h"
namespace Inkscape {
namespace UI {
diff --git a/src/ui/view/view-widget.cpp b/src/ui/view/view-widget.cpp
index 5cb0df215..671a4afe6 100644
--- a/src/ui/view/view-widget.cpp
+++ b/src/ui/view/view-widget.cpp
@@ -15,32 +15,9 @@
//using namespace Inkscape::UI::View;
// SPViewWidget
-
-static void sp_view_widget_class_init(SPViewWidgetClass *vwc);
-static void sp_view_widget_init(SPViewWidget *widget);
static void sp_view_widget_dispose(GObject *object);
-static GtkEventBoxClass *widget_parent_class;
-
-GType sp_view_widget_get_type(void)
-{
- static GType type = 0;
- if (!type) {
- GTypeInfo info = {
- sizeof(SPViewWidgetClass),
- NULL, NULL,
- (GClassInitFunc) sp_view_widget_class_init,
- NULL, NULL,
- sizeof(SPViewWidget),
- 0,
- (GInstanceInitFunc) sp_view_widget_init,
- NULL
- };
- type = g_type_register_static (GTK_TYPE_EVENT_BOX, "SPViewWidget", &info, (GTypeFlags)0);
- }
-
- return type;
-}
+G_DEFINE_TYPE(SPViewWidget, sp_view_widget, GTK_TYPE_EVENT_BOX);
/**
* Callback to initialize the SPViewWidget vtable.
@@ -48,8 +25,6 @@ GType sp_view_widget_get_type(void)
static void sp_view_widget_class_init(SPViewWidgetClass *vwc)
{
GObjectClass *object_class = G_OBJECT_CLASS(vwc);
-
- widget_parent_class = (GtkEventBoxClass*) g_type_class_peek_parent(vwc);
object_class->dispose = sp_view_widget_dispose;
}
@@ -77,8 +52,8 @@ static void sp_view_widget_dispose(GObject *object)
vw->view = NULL;
}
- if (((GObjectClass *) (widget_parent_class))->dispose) {
- (* ((GObjectClass *) (widget_parent_class))->dispose)(object);
+ if (G_OBJECT_CLASS(sp_view_widget_parent_class)->dispose) {
+ G_OBJECT_CLASS(sp_view_widget_parent_class)->dispose(object);
}
Inkscape::GC::request_early_collection();
diff --git a/src/ui/widget/Makefile_insert b/src/ui/widget/Makefile_insert
index 608dd5334..e18b790bd 100644
--- a/src/ui/widget/Makefile_insert
+++ b/src/ui/widget/Makefile_insert
@@ -83,5 +83,14 @@ ink_common_sources += \
ui/widget/unit-menu.cpp \
ui/widget/unit-menu.h \
ui/widget/unit-tracker.h \
- ui/widget/unit-tracker.cpp
-
+ ui/widget/unit-tracker.cpp \
+ ui/widget/clipmaskicon.cpp \
+ ui/widget/clipmaskicon.h \
+ ui/widget/highlight-picker.cpp \
+ ui/widget/highlight-picker.h \
+ ui/widget/layertypeicon.cpp \
+ ui/widget/layertypeicon.h \
+ ui/widget/insertordericon.cpp \
+ ui/widget/insertordericon.h \
+ ui/widget/addtoicon.cpp \
+ ui/widget/addtoicon.h
diff --git a/src/ui/widget/addtoicon.cpp b/src/ui/widget/addtoicon.cpp
new file mode 100644
index 000000000..0798d1c98
--- /dev/null
+++ b/src/ui/widget/addtoicon.cpp
@@ -0,0 +1,156 @@
+/*
+ * Authors:
+ * Theodore Janeczko
+ *
+ * Copyright (C) Theodore Janeczko 2012 <flutterguy317@gmail.com>
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#if GLIBMM_DISABLE_DEPRECATED && HAVE_GLIBMM_THREADS_H
+# include <glibmm/threads.h>
+#endif
+
+#include "ui/widget/addtoicon.h"
+
+#include <gtkmm/icontheme.h>
+
+#include "widgets/icon.h"
+#include "widgets/toolbox.h"
+#include "ui/icon-names.h"
+#include "layertypeicon.h"
+#include "addtoicon.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+AddToIcon::AddToIcon() :
+ Glib::ObjectBase(typeid(AddToIcon)),
+ Gtk::CellRendererPixbuf(),
+// _pixAddName(INKSCAPE_ICON("layer-new")),
+ _property_active(*this, "active", false)
+// _property_pixbuf_add(*this, "pixbuf_on", Glib::RefPtr<Gdk::Pixbuf>(0))
+{
+ property_mode() = Gtk::CELL_RENDERER_MODE_ACTIVATABLE;
+ phys = sp_icon_get_phys_size((int)Inkscape::ICON_SIZE_BUTTON);
+// Glib::RefPtr<Gtk::IconTheme> icon_theme = Gtk::IconTheme::get_default();
+//
+// if (!icon_theme->has_icon(_pixAddName)) {
+// Inkscape::queueIconPrerender( INKSCAPE_ICON(_pixAddName.data()), Inkscape::ICON_SIZE_DECORATION );
+// }
+// if (icon_theme->has_icon(_pixAddName)) {
+// _property_pixbuf_add = icon_theme->load_icon(_pixAddName, phys, (Gtk::IconLookupFlags)0);
+// }
+//
+// _property_pixbuf_add = Gtk::Widget::
+
+ property_stock_id() = GTK_STOCK_ADD;
+}
+
+
+#if WITH_GTKMM_3_0
+void AddToIcon::get_preferred_height_vfunc(Gtk::Widget& widget,
+ int& min_h,
+ int& nat_h) const
+{
+ Gtk::CellRendererPixbuf::get_preferred_height_vfunc(widget, min_h, nat_h);
+
+ if (min_h) {
+ min_h += (min_h) >> 1;
+ }
+
+ if (nat_h) {
+ nat_h += (nat_h) >> 1;
+ }
+}
+
+void AddToIcon::get_preferred_width_vfunc(Gtk::Widget& widget,
+ int& min_w,
+ int& nat_w) const
+{
+ Gtk::CellRendererPixbuf::get_preferred_width_vfunc(widget, min_w, nat_w);
+
+ if (min_w) {
+ min_w += (min_w) >> 1;
+ }
+
+ if (nat_w) {
+ nat_w += (nat_w) >> 1;
+ }
+}
+#else
+void AddToIcon::get_size_vfunc(Gtk::Widget& widget,
+ const Gdk::Rectangle* cell_area,
+ int* x_offset,
+ int* y_offset,
+ int* width,
+ int* height ) const
+{
+ Gtk::CellRendererPixbuf::get_size_vfunc( widget, cell_area, x_offset, y_offset, width, height );
+
+ if ( width ) {
+ *width = phys;//+= (*width) >> 1;
+ }
+ if ( height ) {
+ *height =phys;//+= (*height) >> 1;
+ }
+}
+#endif
+
+#if WITH_GTKMM_3_0
+void AddToIcon::render_vfunc( const Cairo::RefPtr<Cairo::Context>& cr,
+ Gtk::Widget& widget,
+ const Gdk::Rectangle& background_area,
+ const Gdk::Rectangle& cell_area,
+ Gtk::CellRendererState flags )
+#else
+void AddToIcon::render_vfunc( const Glib::RefPtr<Gdk::Drawable>& window,
+ Gtk::Widget& widget,
+ const Gdk::Rectangle& background_area,
+ const Gdk::Rectangle& cell_area,
+ const Gdk::Rectangle& expose_area,
+ Gtk::CellRendererState flags )
+#endif
+{
+ property_stock_id() = property_active().get_value() ? GTK_STOCK_ADD : GTK_STOCK_DELETE;
+
+#if WITH_GTKMM_3_0
+ Gtk::CellRendererPixbuf::render_vfunc( cr, widget, background_area, cell_area, flags );
+#else
+ Gtk::CellRendererPixbuf::render_vfunc( window, widget, background_area, cell_area, expose_area, flags );
+#endif
+}
+
+bool AddToIcon::activate_vfunc(GdkEvent* /*event*/,
+ Gtk::Widget& /*widget*/,
+ const Glib::ustring& /*path*/,
+ const Gdk::Rectangle& /*background_area*/,
+ const Gdk::Rectangle& /*cell_area*/,
+ Gtk::CellRendererState /*flags*/)
+{
+ return false;
+}
+
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
+
+
diff --git a/src/ui/widget/addtoicon.h b/src/ui/widget/addtoicon.h
new file mode 100644
index 000000000..9c134d231
--- /dev/null
+++ b/src/ui/widget/addtoicon.h
@@ -0,0 +1,98 @@
+#ifndef __UI_DIALOG_ADDTOICON_H__
+#define __UI_DIALOG_ADDTOICON_H__
+/*
+ * Authors:
+ * Theodore Janeczko
+ *
+ * Copyright (C) Theodore Janeczko 2012 <flutterguy317@gmail.com>
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gtkmm/cellrendererpixbuf.h>
+#include <gtkmm/widget.h>
+#include <glibmm/property.h>
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+class AddToIcon : public Gtk::CellRendererPixbuf {
+public:
+ AddToIcon();
+ virtual ~AddToIcon() {};
+
+ Glib::PropertyProxy<bool> property_active() { return _property_active.get_proxy(); }
+ Glib::PropertyProxy< Glib::RefPtr<Gdk::Pixbuf> > property_pixbuf_on();
+ Glib::PropertyProxy< Glib::RefPtr<Gdk::Pixbuf> > property_pixbuf_off();
+
+protected:
+
+#if WITH_GTKMM_3_0
+ virtual void render_vfunc( const Cairo::RefPtr<Cairo::Context>& cr,
+ Gtk::Widget& widget,
+ const Gdk::Rectangle& background_area,
+ const Gdk::Rectangle& cell_area,
+ Gtk::CellRendererState flags );
+
+ virtual void get_preferred_width_vfunc(Gtk::Widget& widget,
+ int& min_w,
+ int& nat_w) const;
+
+ virtual void get_preferred_height_vfunc(Gtk::Widget& widget,
+ int& min_h,
+ int& nat_h) const;
+#else
+ virtual void render_vfunc( const Glib::RefPtr<Gdk::Drawable>& window,
+ Gtk::Widget& widget,
+ const Gdk::Rectangle& background_area,
+ const Gdk::Rectangle& cell_area,
+ const Gdk::Rectangle& expose_area,
+ Gtk::CellRendererState flags );
+
+ virtual void get_size_vfunc( Gtk::Widget &widget,
+ Gdk::Rectangle const *cell_area,
+ int *x_offset, int *y_offset, int *width, int *height ) const;
+#endif
+
+ virtual bool activate_vfunc(GdkEvent *event,
+ Gtk::Widget &widget,
+ const Glib::ustring &path,
+ const Gdk::Rectangle &background_area,
+ const Gdk::Rectangle &cell_area,
+ Gtk::CellRendererState flags);
+
+
+private:
+ int phys;
+
+// Glib::ustring _pixAddName;
+
+ Glib::Property<bool> _property_active;
+// Glib::Property< Glib::RefPtr<Gdk::Pixbuf> > _property_pixbuf_add;
+
+};
+
+
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+
+#endif /* __UI_DIALOG_IMAGETOGGLER_H__ */
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/ui/widget/anchor-selector.cpp b/src/ui/widget/anchor-selector.cpp
index 82e27ee89..df00b786a 100644
--- a/src/ui/widget/anchor-selector.cpp
+++ b/src/ui/widget/anchor-selector.cpp
@@ -28,7 +28,11 @@ void AnchorSelector::setupButton(const Glib::ustring& icon, Gtk::ToggleButton& b
AnchorSelector::AnchorSelector()
: Gtk::Alignment(0.5, 0, 0, 0),
+#if WITH_GTKMM_3_0
+ _container()
+#else
_container(3, 3, true)
+#endif
{
setupButton(INKSCAPE_ICON("boundingbox_top_left"), _buttons[0]);
setupButton(INKSCAPE_ICON("boundingbox_top"), _buttons[1]);
@@ -40,10 +44,20 @@ AnchorSelector::AnchorSelector()
setupButton(INKSCAPE_ICON("boundingbox_bottom"), _buttons[7]);
setupButton(INKSCAPE_ICON("boundingbox_bottom_right"), _buttons[8]);
+#if WITH_GTKMM_3_0
+ _container.set_row_homogeneous();
+ _container.set_column_homogeneous(true);
+#endif
+
for(int i = 0; i < 9; ++i) {
_buttons[i].signal_clicked().connect(
sigc::bind(sigc::mem_fun(*this, &AnchorSelector::btn_activated), i));
+
+#if WITH_GTKMM_3_0
+ _container.attach(_buttons[i], i % 3, i / 3, 1, 1);
+#else
_container.attach(_buttons[i], i % 3, i % 3+1, i / 3, i / 3+1, Gtk::FILL, Gtk::FILL);
+#endif
}
_selection = 4;
_buttons[4].set_active();
@@ -94,4 +108,4 @@ void AnchorSelector::setAlignment(int horizontal, int vertical)
fill-column:99
End:
*/
-// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/widget/anchor-selector.h b/src/ui/widget/anchor-selector.h
index 2263438e3..0a702d296 100644
--- a/src/ui/widget/anchor-selector.h
+++ b/src/ui/widget/anchor-selector.h
@@ -10,7 +10,18 @@
#ifndef ANCHOR_SELECTOR_H_
#define ANCHOR_SELECTOR_H_
-#include <gtkmm.h>
+#if HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#include <gtkmm/alignment.h>
+#include <gtkmm/togglebutton.h>
+
+#if WITH_GTKMM_3_0
+ #include <gtkmm/grid.h>
+#else
+ #include <gtkmm/table.h>
+#endif
namespace Inkscape {
namespace UI {
@@ -21,7 +32,12 @@ class AnchorSelector : public Gtk::Alignment
private:
Gtk::ToggleButton _buttons[9];
int _selection;
+
+#if WITH_GTKMM_3_0
+ Gtk::Grid _container;
+#else
Gtk::Table _container;
+#endif
sigc::signal<void> _selectionChanged;
@@ -56,4 +72,4 @@ public:
fill-column:99
End:
*/
-// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/widget/button.cpp b/src/ui/widget/button.cpp
index bac866920..6c2d419cf 100644
--- a/src/ui/widget/button.cpp
+++ b/src/ui/widget/button.cpp
@@ -51,13 +51,13 @@ RadioButton::RadioButton(Glib::ustring const &label, Glib::ustring const &toolti
} // namespace UI
} // namespace Inkscape
-/*
+/*
Local Variables:
mode:c++
c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0))
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
indent-tabs-mode:nil
fill-column:99
End:
*/
-// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/ui/widget/button.h b/src/ui/widget/button.h
index a214dd881..471b7d8a2 100644
--- a/src/ui/widget/button.h
+++ b/src/ui/widget/button.h
@@ -67,13 +67,13 @@ public:
#endif // INKSCAPE_UI_WIDGET_BUTTON_H
-/*
+/*
Local Variables:
mode:c++
c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0))
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
indent-tabs-mode:nil
fill-column:99
End:
*/
-// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/ui/widget/clipmaskicon.cpp b/src/ui/widget/clipmaskicon.cpp
new file mode 100644
index 000000000..943b1bebc
--- /dev/null
+++ b/src/ui/widget/clipmaskicon.cpp
@@ -0,0 +1,183 @@
+/*
+ * Authors:
+ * Theodore Janeczko
+ *
+ * Copyright (C) Theodore Janeczko 2012 <flutterguy317@gmail.com>
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#if GLIBMM_DISABLE_DEPRECATED && HAVE_GLIBMM_THREADS_H
+# include <glibmm/threads.h>
+#endif
+
+#include "ui/widget/clipmaskicon.h"
+
+#include <gtkmm/icontheme.h>
+
+#include "widgets/icon.h"
+#include "widgets/toolbox.h"
+#include "ui/icon-names.h"
+#include "layertypeicon.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+ClipMaskIcon::ClipMaskIcon() :
+ Glib::ObjectBase(typeid(ClipMaskIcon)),
+ Gtk::CellRendererPixbuf(),
+ _pixClipName(INKSCAPE_ICON("path-intersection")),
+ _pixInverseName(INKSCAPE_ICON("path-difference")),
+ _pixMaskName(INKSCAPE_ICON("mask-intersection")),
+ _property_active(*this, "active", 0),
+ _property_pixbuf_clip(*this, "pixbuf_on", Glib::RefPtr<Gdk::Pixbuf>(0)),
+ _property_pixbuf_inverse(*this, "pixbuf_on", Glib::RefPtr<Gdk::Pixbuf>(0)),
+ _property_pixbuf_mask(*this, "pixbuf_off", Glib::RefPtr<Gdk::Pixbuf>(0))
+{
+
+ property_mode() = Gtk::CELL_RENDERER_MODE_ACTIVATABLE;
+ phys = sp_icon_get_phys_size((int)Inkscape::ICON_SIZE_DECORATION);
+ Glib::RefPtr<Gtk::IconTheme> icon_theme = Gtk::IconTheme::get_default();
+
+ if (!icon_theme->has_icon(_pixClipName)) {
+ Inkscape::queueIconPrerender( INKSCAPE_ICON(_pixClipName.data()), Inkscape::ICON_SIZE_DECORATION );
+ }
+ if (!icon_theme->has_icon(_pixInverseName)) {
+ Inkscape::queueIconPrerender( INKSCAPE_ICON(_pixInverseName.data()), Inkscape::ICON_SIZE_DECORATION );
+ }
+ if (!icon_theme->has_icon(_pixMaskName)) {
+ Inkscape::queueIconPrerender( INKSCAPE_ICON(_pixMaskName.data()), Inkscape::ICON_SIZE_DECORATION );
+ }
+
+ if (icon_theme->has_icon(_pixClipName)) {
+ _property_pixbuf_clip = icon_theme->load_icon(_pixClipName, phys, (Gtk::IconLookupFlags)0);
+ }
+ if (icon_theme->has_icon(_pixInverseName)) {
+ _property_pixbuf_inverse = icon_theme->load_icon(_pixInverseName, phys, (Gtk::IconLookupFlags)0);
+ }
+ if (icon_theme->has_icon(_pixMaskName)) {
+ _property_pixbuf_mask = icon_theme->load_icon(_pixMaskName, phys, (Gtk::IconLookupFlags)0);
+ }
+
+ property_pixbuf() = Glib::RefPtr<Gdk::Pixbuf>(0);
+}
+
+
+#if WITH_GTKMM_3_0
+void ClipMaskIcon::get_preferred_height_vfunc(Gtk::Widget& widget,
+ int& min_h,
+ int& nat_h) const
+{
+ Gtk::CellRendererPixbuf::get_preferred_height_vfunc(widget, min_h, nat_h);
+
+ if (min_h) {
+ min_h += (min_h) >> 1;
+ }
+
+ if (nat_h) {
+ nat_h += (nat_h) >> 1;
+ }
+}
+
+void ClipMaskIcon::get_preferred_width_vfunc(Gtk::Widget& widget,
+ int& min_w,
+ int& nat_w) const
+{
+ Gtk::CellRendererPixbuf::get_preferred_width_vfunc(widget, min_w, nat_w);
+
+ if (min_w) {
+ min_w += (min_w) >> 1;
+ }
+
+ if (nat_w) {
+ nat_w += (nat_w) >> 1;
+ }
+}
+#else
+void ClipMaskIcon::get_size_vfunc(Gtk::Widget& widget,
+ const Gdk::Rectangle* cell_area,
+ int* x_offset,
+ int* y_offset,
+ int* width,
+ int* height ) const
+{
+ Gtk::CellRendererPixbuf::get_size_vfunc( widget, cell_area, x_offset, y_offset, width, height );
+
+ if ( width ) {
+ *width = phys;//+= (*width) >> 1;
+ }
+ if ( height ) {
+ *height =phys;//+= (*height) >> 1;
+ }
+}
+#endif
+
+#if WITH_GTKMM_3_0
+void ClipMaskIcon::render_vfunc( const Cairo::RefPtr<Cairo::Context>& cr,
+ Gtk::Widget& widget,
+ const Gdk::Rectangle& background_area,
+ const Gdk::Rectangle& cell_area,
+ Gtk::CellRendererState flags )
+#else
+void ClipMaskIcon::render_vfunc( const Glib::RefPtr<Gdk::Drawable>& window,
+ Gtk::Widget& widget,
+ const Gdk::Rectangle& background_area,
+ const Gdk::Rectangle& cell_area,
+ const Gdk::Rectangle& expose_area,
+ Gtk::CellRendererState flags )
+#endif
+{
+ switch (_property_active.get_value())
+ {
+ case 1:
+ property_pixbuf() = _property_pixbuf_clip;
+ break;
+ case 2:
+ property_pixbuf() = _property_pixbuf_mask;
+ break;
+ case 3:
+ property_pixbuf() = _property_pixbuf_inverse;
+ break;
+ default:
+ property_pixbuf() = Glib::RefPtr<Gdk::Pixbuf>(0);
+ break;
+ }
+#if WITH_GTKMM_3_0
+ Gtk::CellRendererPixbuf::render_vfunc( cr, widget, background_area, cell_area, flags );
+#else
+ Gtk::CellRendererPixbuf::render_vfunc( window, widget, background_area, cell_area, expose_area, flags );
+#endif
+}
+
+bool ClipMaskIcon::activate_vfunc(GdkEvent* /*event*/,
+ Gtk::Widget& /*widget*/,
+ const Glib::ustring& /*path*/,
+ const Gdk::Rectangle& /*background_area*/,
+ const Gdk::Rectangle& /*cell_area*/,
+ Gtk::CellRendererState /*flags*/)
+{
+ return false;
+}
+
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
+
+
diff --git a/src/ui/widget/clipmaskicon.h b/src/ui/widget/clipmaskicon.h
new file mode 100644
index 000000000..eca852a83
--- /dev/null
+++ b/src/ui/widget/clipmaskicon.h
@@ -0,0 +1,102 @@
+#ifndef __UI_DIALOG_CLIPMASKICON_H__
+#define __UI_DIALOG_CLIPMASKICON_H__
+/*
+ * Authors:
+ * Theodore Janeczko
+ *
+ * Copyright (C) Theodore Janeczko 2012 <flutterguy317@gmail.com>
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gtkmm/cellrendererpixbuf.h>
+#include <gtkmm/widget.h>
+#include <glibmm/property.h>
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+class ClipMaskIcon : public Gtk::CellRendererPixbuf {
+public:
+ ClipMaskIcon();
+ virtual ~ClipMaskIcon() {};
+
+ Glib::PropertyProxy<int> property_active() { return _property_active.get_proxy(); }
+ Glib::PropertyProxy< Glib::RefPtr<Gdk::Pixbuf> > property_pixbuf_on();
+ Glib::PropertyProxy< Glib::RefPtr<Gdk::Pixbuf> > property_pixbuf_off();
+
+protected:
+
+#if WITH_GTKMM_3_0
+ virtual void render_vfunc( const Cairo::RefPtr<Cairo::Context>& cr,
+ Gtk::Widget& widget,
+ const Gdk::Rectangle& background_area,
+ const Gdk::Rectangle& cell_area,
+ Gtk::CellRendererState flags );
+
+ virtual void get_preferred_width_vfunc(Gtk::Widget& widget,
+ int& min_w,
+ int& nat_w) const;
+
+ virtual void get_preferred_height_vfunc(Gtk::Widget& widget,
+ int& min_h,
+ int& nat_h) const;
+#else
+ virtual void render_vfunc( const Glib::RefPtr<Gdk::Drawable>& window,
+ Gtk::Widget& widget,
+ const Gdk::Rectangle& background_area,
+ const Gdk::Rectangle& cell_area,
+ const Gdk::Rectangle& expose_area,
+ Gtk::CellRendererState flags );
+
+ virtual void get_size_vfunc( Gtk::Widget &widget,
+ Gdk::Rectangle const *cell_area,
+ int *x_offset, int *y_offset, int *width, int *height ) const;
+#endif
+
+ virtual bool activate_vfunc(GdkEvent *event,
+ Gtk::Widget &widget,
+ const Glib::ustring &path,
+ const Gdk::Rectangle &background_area,
+ const Gdk::Rectangle &cell_area,
+ Gtk::CellRendererState flags);
+
+
+private:
+ int phys;
+
+ Glib::ustring _pixClipName;
+ Glib::ustring _pixInverseName;
+ Glib::ustring _pixMaskName;
+
+ Glib::Property<int> _property_active;
+ Glib::Property< Glib::RefPtr<Gdk::Pixbuf> > _property_pixbuf_clip;
+ Glib::Property< Glib::RefPtr<Gdk::Pixbuf> > _property_pixbuf_inverse;
+ Glib::Property< Glib::RefPtr<Gdk::Pixbuf> > _property_pixbuf_mask;
+
+};
+
+
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+
+#endif /* __UI_DIALOG_IMAGETOGGLER_H__ */
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/ui/widget/color-picker.cpp b/src/ui/widget/color-picker.cpp
index 5585f2db4..6b5a351f6 100644
--- a/src/ui/widget/color-picker.cpp
+++ b/src/ui/widget/color-picker.cpp
@@ -15,7 +15,7 @@
#include "desktop-handles.h"
#include "document.h"
#include "document-undo.h"
-#include "dialogs/dialog-events.h"
+#include "ui/dialog-events.h"
#include "widgets/sp-color-notebook.h"
#include "verbs.h"
diff --git a/src/ui/widget/entity-entry.cpp b/src/ui/widget/entity-entry.cpp
index 0f526f77a..c7d5efe29 100644
--- a/src/ui/widget/entity-entry.cpp
+++ b/src/ui/widget/entity-entry.cpp
@@ -206,9 +206,9 @@ EntityMultiLineEntry::on_changed()
Local Variables:
mode:c++
c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0))
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
indent-tabs-mode:nil
fill-column:99
End:
*/
-// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/ui/widget/entity-entry.h b/src/ui/widget/entity-entry.h
index 09289496d..35f6ecfb4 100644
--- a/src/ui/widget/entity-entry.h
+++ b/src/ui/widget/entity-entry.h
@@ -76,9 +76,9 @@ protected:
Local Variables:
mode:c++
c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0))
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
indent-tabs-mode:nil
fill-column:99
End:
*/
-// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/ui/widget/filter-effect-chooser.cpp b/src/ui/widget/filter-effect-chooser.cpp
index 65706a9dc..4754b9c23 100644
--- a/src/ui/widget/filter-effect-chooser.cpp
+++ b/src/ui/widget/filter-effect-chooser.cpp
@@ -23,6 +23,8 @@ namespace Widget {
SimpleFilterModifier::SimpleFilterModifier(int flags)
: _lb_blend(_("Blend mode:")),
+ _lb_blur(_("_Blur:")),
+ _lb_blur_unit(_("%")),
_blend(BlendModeConverter, SP_ATTR_INVALID, false),
_blur(_("Blur (%)"), 0, 0, 100, 1, 0.01, 1)
{
@@ -56,15 +58,12 @@ const Glib::ustring SimpleFilterModifier::get_blend_mode()
if (!(_flags & BLEND)) {
return "normal";
}
- if (_blend.get_active_row_number() == 5) {
+
+ const Util::EnumData<Inkscape::Filters::FilterBlendMode> *d = _blend.get_active_data();
+ if (d) {
+ return _blend.get_active_data()->key;
+ } else
return "normal";
- } else {
- const Util::EnumData<Inkscape::Filters::FilterBlendMode> *d = _blend.get_active_data();
- if (d) {
- return _blend.get_active_data()->key;
- } else
- return "normal";
- }
}
void SimpleFilterModifier::set_blend_mode(const int val)
diff --git a/src/ui/widget/filter-effect-chooser.h b/src/ui/widget/filter-effect-chooser.h
index 8d2389b15..6092c61a5 100644
--- a/src/ui/widget/filter-effect-chooser.h
+++ b/src/ui/widget/filter-effect-chooser.h
@@ -53,11 +53,13 @@ public:
double get_blur_value() const;
void set_blur_value(const double);
void set_blur_sensitive(const bool);
+ Gtk::Label *get_blur_label() { return &_lb_blur; };
private:
int _flags;
Gtk::HBox _hb_blend;
- Gtk::Label _lb_blend;
+ Gtk::HBox _hb_blur;
+ Gtk::Label _lb_blend, _lb_blur, _lb_blur_unit;
ComboBoxEnum<Inkscape::Filters::FilterBlendMode> _blend;
SpinScale _blur;
diff --git a/src/ui/widget/highlight-picker.cpp b/src/ui/widget/highlight-picker.cpp
new file mode 100644
index 000000000..09999b52d
--- /dev/null
+++ b/src/ui/widget/highlight-picker.cpp
@@ -0,0 +1,206 @@
+/*
+ * Authors:
+ * Theodore Janeczko
+ *
+ * Copyright (C) Theodore Janeczko 2012 <flutterguy317@gmail.com>
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <glibmm.h>
+#include <gtkmm/icontheme.h>
+
+#include "display/cairo-utils.h"
+
+#include "highlight-picker.h"
+#include "widgets/icon.h"
+#include "widgets/toolbox.h"
+#include "ui/icon-names.h"
+#include <glibmm/i18n.h>
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+HighlightPicker::HighlightPicker() :
+ Glib::ObjectBase(typeid(HighlightPicker)),
+ Gtk::CellRendererPixbuf(),
+ _property_active(*this, "active", 0)
+{
+
+ property_mode() = Gtk::CELL_RENDERER_MODE_ACTIVATABLE;
+}
+
+HighlightPicker::~HighlightPicker()
+{
+}
+
+
+#if WITH_GTKMM_3_0
+void HighlightPicker::get_preferred_height_vfunc(Gtk::Widget& widget,
+ int& min_h,
+ int& nat_h) const
+{
+ Gtk::CellRendererPixbuf::get_preferred_height_vfunc(widget, min_h, nat_h);
+
+ if (min_h) {
+ min_h += (min_h) >> 1;
+ }
+
+ if (nat_h) {
+ nat_h += (nat_h) >> 1;
+ }
+}
+
+void HighlightPicker::get_preferred_width_vfunc(Gtk::Widget& widget,
+ int& min_w,
+ int& nat_w) const
+{
+ Gtk::CellRendererPixbuf::get_preferred_width_vfunc(widget, min_w, nat_w);
+
+ if (min_w) {
+ min_w += (min_w) >> 1;
+ }
+
+ if (nat_w) {
+ nat_w += (nat_w) >> 1;
+ }
+}
+#else
+void HighlightPicker::get_size_vfunc(Gtk::Widget& widget,
+ const Gdk::Rectangle* cell_area,
+ int* x_offset,
+ int* y_offset,
+ int* width,
+ int* height ) const
+{
+ Gtk::CellRendererPixbuf::get_size_vfunc( widget, cell_area, x_offset, y_offset, width, height );
+
+ if ( width ) {
+ *width = 10;//+= (*width) >> 1;
+ }
+ if ( height ) {
+ *height = 20; //cell_area ? cell_area->get_height() / 2 : 50; //+= (*height) >> 1;
+ }
+}
+#endif
+
+#if WITH_GTKMM_3_0
+void HighlightPicker::render_vfunc( const Cairo::RefPtr<Cairo::Context>& cr,
+ Gtk::Widget& widget,
+ const Gdk::Rectangle& background_area,
+ const Gdk::Rectangle& cell_area,
+ Gtk::CellRendererState flags )
+#else
+void HighlightPicker::render_vfunc( const Glib::RefPtr<Gdk::Drawable>& window,
+ Gtk::Widget& widget,
+ const Gdk::Rectangle& background_area,
+ const Gdk::Rectangle& cell_area,
+ const Gdk::Rectangle& expose_area,
+ Gtk::CellRendererState flags )
+#endif
+{
+ GdkRectangle carea;
+
+ cairo_surface_t *s = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 10, 20);
+ cairo_t *ct = cairo_create(s);
+
+ /* Transparent area */
+ carea.x = 0;
+ carea.y = 0;
+ carea.width = 10;
+ carea.height = 20;
+
+ cairo_pattern_t *checkers = ink_cairo_pattern_create_checkerboard();
+
+ cairo_rectangle(ct, carea.x, carea.y, carea.width, carea.height / 2);
+ cairo_set_source(ct, checkers);
+ cairo_fill_preserve(ct);
+ ink_cairo_set_source_rgba32(ct, _property_active.get_value());
+ cairo_fill(ct);
+
+ cairo_pattern_destroy(checkers);
+
+ cairo_rectangle(ct, carea.x, carea.y + carea.height / 2, carea.width, carea.height / 2);
+ ink_cairo_set_source_rgba32(ct, _property_active.get_value() | 0x000000ff);
+ cairo_fill(ct);
+
+ cairo_rectangle(ct, carea.x, carea.y, carea.width, carea.height);
+ ink_cairo_set_source_rgba32(ct, 0x333333ff);
+ cairo_set_line_width(ct, 2);
+ cairo_stroke(ct);
+
+ cairo_destroy(ct);
+ cairo_surface_flush(s);
+
+ GdkPixbuf* pixbuf = gdk_pixbuf_new_from_data( cairo_image_surface_get_data(s),
+ GDK_COLORSPACE_RGB, TRUE, 8,
+ 10, 20, cairo_image_surface_get_stride(s),
+ ink_cairo_pixbuf_cleanup, s);
+ convert_pixbuf_argb32_to_normal(pixbuf);
+
+ property_pixbuf() = Glib::wrap(pixbuf);
+#if WITH_GTKMM_3_0
+ Gtk::CellRendererPixbuf::render_vfunc( cr, widget, background_area, cell_area, flags );
+#else
+ Gtk::CellRendererPixbuf::render_vfunc( window, widget, background_area, cell_area, expose_area, flags );
+#endif
+}
+
+bool HighlightPicker::activate_vfunc(GdkEvent* /*event*/,
+ Gtk::Widget& /*widget*/,
+ const Glib::ustring& /*path*/,
+ const Gdk::Rectangle& /*background_area*/,
+ const Gdk::Rectangle& /*cell_area*/,
+ Gtk::CellRendererState /*flags*/)
+{
+ return false;
+}
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+//should be okay to put this here
+/**
+ * Converts GdkPixbuf's data to premultiplied ARGB.
+ * This function will convert a GdkPixbuf in place into Cairo's native pixel format.
+ * Note that this is a hack intended to save memory. When the pixbuf is in Cairo's format,
+ * using it with GTK will result in corrupted drawings.
+ */
+void
+convert_pixbuf_normal_to_argb32(GdkPixbuf *pb)
+{
+ convert_pixels_pixbuf_to_argb32(
+ gdk_pixbuf_get_pixels(pb),
+ gdk_pixbuf_get_width(pb),
+ gdk_pixbuf_get_height(pb),
+ gdk_pixbuf_get_rowstride(pb));
+}
+
+/**
+ * Converts GdkPixbuf's data back to its native format.
+ * Once this is done, the pixbuf can be used with GTK again.
+ */
+void
+convert_pixbuf_argb32_to_normal(GdkPixbuf *pb)
+{
+ convert_pixels_argb32_to_pixbuf(
+ gdk_pixbuf_get_pixels(pb),
+ gdk_pixbuf_get_width(pb),
+ gdk_pixbuf_get_height(pb),
+ gdk_pixbuf_get_rowstride(pb));
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
+
+
diff --git a/src/ui/widget/highlight-picker.h b/src/ui/widget/highlight-picker.h
new file mode 100644
index 000000000..c5fe4c02c
--- /dev/null
+++ b/src/ui/widget/highlight-picker.h
@@ -0,0 +1,90 @@
+#ifndef __UI_DIALOG_HIGHLIGHT_PICKER_H__
+#define __UI_DIALOG_HIGHLIGHT_PICKER_H__
+/*
+ * Authors:
+ * Theodore Janeczko
+ *
+ * Copyright (C) Theodore Janeczko 2012 <flutterguy317@gmail.com>
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gtkmm/cellrendererpixbuf.h>
+#include <gtkmm/widget.h>
+#include <glibmm/property.h>
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+class HighlightPicker : public Gtk::CellRendererPixbuf {
+public:
+ HighlightPicker();
+ virtual ~HighlightPicker();
+
+ Glib::PropertyProxy<guint32> property_active() { return _property_active.get_proxy(); }
+
+protected:
+
+#if WITH_GTKMM_3_0
+ virtual void render_vfunc( const Cairo::RefPtr<Cairo::Context>& cr,
+ Gtk::Widget& widget,
+ const Gdk::Rectangle& background_area,
+ const Gdk::Rectangle& cell_area,
+ Gtk::CellRendererState flags );
+
+ virtual void get_preferred_width_vfunc(Gtk::Widget& widget,
+ int& min_w,
+ int& nat_w) const;
+
+ virtual void get_preferred_height_vfunc(Gtk::Widget& widget,
+ int& min_h,
+ int& nat_h) const;
+#else
+ virtual void render_vfunc( const Glib::RefPtr<Gdk::Drawable>& window,
+ Gtk::Widget& widget,
+ const Gdk::Rectangle& background_area,
+ const Gdk::Rectangle& cell_area,
+ const Gdk::Rectangle& expose_area,
+ Gtk::CellRendererState flags );
+
+ virtual void get_size_vfunc( Gtk::Widget &widget,
+ Gdk::Rectangle const *cell_area,
+ int *x_offset, int *y_offset, int *width, int *height ) const;
+#endif
+
+ virtual bool activate_vfunc(GdkEvent *event,
+ Gtk::Widget &widget,
+ const Glib::ustring &path,
+ const Gdk::Rectangle &background_area,
+ const Gdk::Rectangle &cell_area,
+ Gtk::CellRendererState flags);
+
+private:
+
+ Glib::Property<guint32> _property_active;
+};
+
+
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+
+#endif /* __UI_DIALOG_IMAGETOGGLER_H__ */
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/ui/widget/insertordericon.cpp b/src/ui/widget/insertordericon.cpp
new file mode 100644
index 000000000..9aec7d135
--- /dev/null
+++ b/src/ui/widget/insertordericon.cpp
@@ -0,0 +1,164 @@
+/*
+ * Authors:
+ * Theodore Janeczko
+ *
+ * Copyright (C) Theodore Janeczko 2012 <flutterguy317@gmail.com>
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "ui/widget/insertordericon.h"
+
+#include <gtkmm/icontheme.h>
+
+#include "widgets/icon.h"
+#include "widgets/toolbox.h"
+#include "ui/icon-names.h"
+#include "layertypeicon.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+InsertOrderIcon::InsertOrderIcon() :
+ Glib::ObjectBase(typeid(InsertOrderIcon)),
+ Gtk::CellRendererPixbuf(),
+ _pixTopName(INKSCAPE_ICON("insert-top")),
+ _pixBottomName(INKSCAPE_ICON("insert-bottom")),
+ _property_active(*this, "active", 0),
+ _property_pixbuf_top(*this, "pixbuf_on", Glib::RefPtr<Gdk::Pixbuf>(0)),
+ _property_pixbuf_bottom(*this, "pixbuf_on", Glib::RefPtr<Gdk::Pixbuf>(0))
+{
+
+ property_mode() = Gtk::CELL_RENDERER_MODE_ACTIVATABLE;
+ phys = sp_icon_get_phys_size((int)Inkscape::ICON_SIZE_DECORATION);
+ Glib::RefPtr<Gtk::IconTheme> icon_theme = Gtk::IconTheme::get_default();
+
+ if (!icon_theme->has_icon(_pixTopName)) {
+ Inkscape::queueIconPrerender( INKSCAPE_ICON(_pixTopName.data()), Inkscape::ICON_SIZE_DECORATION );
+ }
+ if (!icon_theme->has_icon(_pixBottomName)) {
+ Inkscape::queueIconPrerender( INKSCAPE_ICON(_pixBottomName.data()), Inkscape::ICON_SIZE_DECORATION );
+ }
+
+ if (icon_theme->has_icon(_pixTopName)) {
+ _property_pixbuf_top = icon_theme->load_icon(_pixTopName, phys, (Gtk::IconLookupFlags)0);
+ }
+ if (icon_theme->has_icon(_pixBottomName)) {
+ _property_pixbuf_bottom = icon_theme->load_icon(_pixBottomName, phys, (Gtk::IconLookupFlags)0);
+ }
+
+ property_pixbuf() = Glib::RefPtr<Gdk::Pixbuf>(0);
+}
+
+
+#if WITH_GTKMM_3_0
+void InsertOrderIcon::get_preferred_height_vfunc(Gtk::Widget& widget,
+ int& min_h,
+ int& nat_h) const
+{
+ Gtk::CellRendererPixbuf::get_preferred_height_vfunc(widget, min_h, nat_h);
+
+ if (min_h) {
+ min_h += (min_h) >> 1;
+ }
+
+ if (nat_h) {
+ nat_h += (nat_h) >> 1;
+ }
+}
+
+void InsertOrderIcon::get_preferred_width_vfunc(Gtk::Widget& widget,
+ int& min_w,
+ int& nat_w) const
+{
+ Gtk::CellRendererPixbuf::get_preferred_width_vfunc(widget, min_w, nat_w);
+
+ if (min_w) {
+ min_w += (min_w) >> 1;
+ }
+
+ if (nat_w) {
+ nat_w += (nat_w) >> 1;
+ }
+}
+#else
+void InsertOrderIcon::get_size_vfunc(Gtk::Widget& widget,
+ const Gdk::Rectangle* cell_area,
+ int* x_offset,
+ int* y_offset,
+ int* width,
+ int* height ) const
+{
+ Gtk::CellRendererPixbuf::get_size_vfunc( widget, cell_area, x_offset, y_offset, width, height );
+
+ if ( width ) {
+ *width = phys;//+= (*width) >> 1;
+ }
+ if ( height ) {
+ *height =phys;//+= (*height) >> 1;
+ }
+}
+#endif
+
+#if WITH_GTKMM_3_0
+void InsertOrderIcon::render_vfunc( const Cairo::RefPtr<Cairo::Context>& cr,
+ Gtk::Widget& widget,
+ const Gdk::Rectangle& background_area,
+ const Gdk::Rectangle& cell_area,
+ Gtk::CellRendererState flags )
+#else
+void InsertOrderIcon::render_vfunc( const Glib::RefPtr<Gdk::Drawable>& window,
+ Gtk::Widget& widget,
+ const Gdk::Rectangle& background_area,
+ const Gdk::Rectangle& cell_area,
+ const Gdk::Rectangle& expose_area,
+ Gtk::CellRendererState flags )
+#endif
+{
+ switch (_property_active.get_value())
+ {
+ case 1:
+ property_pixbuf() = _property_pixbuf_top;
+ break;
+ case 2:
+ property_pixbuf() = _property_pixbuf_bottom;
+ break;
+ default:
+ property_pixbuf() = Glib::RefPtr<Gdk::Pixbuf>(0);
+ break;
+ }
+#if WITH_GTKMM_3_0
+ Gtk::CellRendererPixbuf::render_vfunc( cr, widget, background_area, cell_area, flags );
+#else
+ Gtk::CellRendererPixbuf::render_vfunc( window, widget, background_area, cell_area, expose_area, flags );
+#endif
+}
+
+bool InsertOrderIcon::activate_vfunc(GdkEvent* /*event*/,
+ Gtk::Widget& /*widget*/,
+ const Glib::ustring& /*path*/,
+ const Gdk::Rectangle& /*background_area*/,
+ const Gdk::Rectangle& /*cell_area*/,
+ Gtk::CellRendererState /*flags*/)
+{
+ return false;
+}
+
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
+
+
diff --git a/src/ui/widget/insertordericon.h b/src/ui/widget/insertordericon.h
new file mode 100644
index 000000000..fb3412d3f
--- /dev/null
+++ b/src/ui/widget/insertordericon.h
@@ -0,0 +1,100 @@
+#ifndef __UI_DIALOG_INSERTORDERICON_H__
+#define __UI_DIALOG_INSERTORDERICON_H__
+/*
+ * Authors:
+ * Theodore Janeczko
+ *
+ * Copyright (C) Theodore Janeczko 2012 <flutterguy317@gmail.com>
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glibmm.h>
+#include <gtkmm/cellrendererpixbuf.h>
+#include <gtkmm/widget.h>
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+class InsertOrderIcon : public Gtk::CellRendererPixbuf {
+public:
+ InsertOrderIcon();
+ virtual ~InsertOrderIcon() {};
+
+ Glib::PropertyProxy<int> property_active() { return _property_active.get_proxy(); }
+ Glib::PropertyProxy< Glib::RefPtr<Gdk::Pixbuf> > property_pixbuf_on();
+ Glib::PropertyProxy< Glib::RefPtr<Gdk::Pixbuf> > property_pixbuf_off();
+
+protected:
+
+#if WITH_GTKMM_3_0
+ virtual void render_vfunc( const Cairo::RefPtr<Cairo::Context>& cr,
+ Gtk::Widget& widget,
+ const Gdk::Rectangle& background_area,
+ const Gdk::Rectangle& cell_area,
+ Gtk::CellRendererState flags );
+
+ virtual void get_preferred_width_vfunc(Gtk::Widget& widget,
+ int& min_w,
+ int& nat_w) const;
+
+ virtual void get_preferred_height_vfunc(Gtk::Widget& widget,
+ int& min_h,
+ int& nat_h) const;
+#else
+ virtual void render_vfunc( const Glib::RefPtr<Gdk::Drawable>& window,
+ Gtk::Widget& widget,
+ const Gdk::Rectangle& background_area,
+ const Gdk::Rectangle& cell_area,
+ const Gdk::Rectangle& expose_area,
+ Gtk::CellRendererState flags );
+
+ virtual void get_size_vfunc( Gtk::Widget &widget,
+ Gdk::Rectangle const *cell_area,
+ int *x_offset, int *y_offset, int *width, int *height ) const;
+#endif
+
+ virtual bool activate_vfunc(GdkEvent *event,
+ Gtk::Widget &widget,
+ const Glib::ustring &path,
+ const Gdk::Rectangle &background_area,
+ const Gdk::Rectangle &cell_area,
+ Gtk::CellRendererState flags);
+
+
+private:
+ int phys;
+
+ Glib::ustring _pixTopName;
+ Glib::ustring _pixBottomName;
+
+ Glib::Property<int> _property_active;
+ Glib::Property< Glib::RefPtr<Gdk::Pixbuf> > _property_pixbuf_top;
+ Glib::Property< Glib::RefPtr<Gdk::Pixbuf> > _property_pixbuf_bottom;
+
+};
+
+
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+
+#endif /* __UI_DIALOG_IMAGETOGGLER_H__ */
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/ui/widget/layertypeicon.cpp b/src/ui/widget/layertypeicon.cpp
new file mode 100644
index 000000000..3d6182bf8
--- /dev/null
+++ b/src/ui/widget/layertypeicon.cpp
@@ -0,0 +1,174 @@
+/*
+ * Authors:
+ * Theodore Janeczko
+ *
+ * Copyright (C) Theodore Janeczko 2012 <flutterguy317@gmail.com>
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#if GLIBMM_DISABLE_DEPRECATED && HAVE_GLIBMM_THREADS_H
+# include <glibmm/threads.h>
+#endif
+
+#include "ui/widget/layertypeicon.h"
+
+#include <gtkmm/icontheme.h>
+
+#include "widgets/icon.h"
+#include "widgets/toolbox.h"
+#include "ui/icon-names.h"
+#include "layertypeicon.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+LayerTypeIcon::LayerTypeIcon() :
+ Glib::ObjectBase(typeid(LayerTypeIcon)),
+ Gtk::CellRendererPixbuf(),
+ _pixLayerName(INKSCAPE_ICON("dialog-layers")),
+ _pixGroupName(INKSCAPE_ICON("layer-duplicate")),
+ _pixPathName(INKSCAPE_ICON("layer-rename")),
+ _property_active(*this, "active", false),
+ _property_activatable(*this, "activatable", true),
+ _property_pixbuf_layer(*this, "pixbuf_on", Glib::RefPtr<Gdk::Pixbuf>(0)),
+ _property_pixbuf_group(*this, "pixbuf_off", Glib::RefPtr<Gdk::Pixbuf>(0)),
+ _property_pixbuf_path(*this, "pixbuf_off", Glib::RefPtr<Gdk::Pixbuf>(0))
+{
+
+ property_mode() = Gtk::CELL_RENDERER_MODE_ACTIVATABLE;
+ int phys = sp_icon_get_phys_size((int)Inkscape::ICON_SIZE_DECORATION);
+ Glib::RefPtr<Gtk::IconTheme> icon_theme = Gtk::IconTheme::get_default();
+
+ if (!icon_theme->has_icon(_pixLayerName)) {
+ Inkscape::queueIconPrerender( INKSCAPE_ICON(_pixLayerName.data()), Inkscape::ICON_SIZE_DECORATION );
+ }
+ if (!icon_theme->has_icon(_pixGroupName)) {
+ Inkscape::queueIconPrerender( INKSCAPE_ICON(_pixGroupName.data()), Inkscape::ICON_SIZE_DECORATION );
+ }
+ if (!icon_theme->has_icon(_pixPathName)) {
+ Inkscape::queueIconPrerender( INKSCAPE_ICON(_pixPathName.data()), Inkscape::ICON_SIZE_DECORATION );
+ }
+
+ if (icon_theme->has_icon(_pixLayerName)) {
+ _property_pixbuf_layer = icon_theme->load_icon(_pixLayerName, phys, (Gtk::IconLookupFlags)0);
+ }
+ if (icon_theme->has_icon(_pixGroupName)) {
+ _property_pixbuf_group = icon_theme->load_icon(_pixGroupName, phys, (Gtk::IconLookupFlags)0);
+ }
+ if (icon_theme->has_icon(_pixPathName)) {
+ _property_pixbuf_path = icon_theme->load_icon(_pixPathName, phys, (Gtk::IconLookupFlags)0);
+ }
+
+ property_pixbuf() = _property_pixbuf_path.get_value();
+}
+
+
+#if WITH_GTKMM_3_0
+void LayerTypeIcon::get_preferred_height_vfunc(Gtk::Widget& widget,
+ int& min_h,
+ int& nat_h) const
+{
+ Gtk::CellRendererPixbuf::get_preferred_height_vfunc(widget, min_h, nat_h);
+
+ if (min_h) {
+ min_h += (min_h) >> 1;
+ }
+
+ if (nat_h) {
+ nat_h += (nat_h) >> 1;
+ }
+}
+
+void LayerTypeIcon::get_preferred_width_vfunc(Gtk::Widget& widget,
+ int& min_w,
+ int& nat_w) const
+{
+ Gtk::CellRendererPixbuf::get_preferred_width_vfunc(widget, min_w, nat_w);
+
+ if (min_w) {
+ min_w += (min_w) >> 1;
+ }
+
+ if (nat_w) {
+ nat_w += (nat_w) >> 1;
+ }
+}
+#else
+void LayerTypeIcon::get_size_vfunc(Gtk::Widget& widget,
+ const Gdk::Rectangle* cell_area,
+ int* x_offset,
+ int* y_offset,
+ int* width,
+ int* height ) const
+{
+ Gtk::CellRendererPixbuf::get_size_vfunc( widget, cell_area, x_offset, y_offset, width, height );
+
+ if ( width ) {
+ *width += (*width) >> 1;
+ }
+ if ( height ) {
+ *height += (*height) >> 1;
+ }
+}
+#endif
+
+#if WITH_GTKMM_3_0
+void LayerTypeIcon::render_vfunc( const Cairo::RefPtr<Cairo::Context>& cr,
+ Gtk::Widget& widget,
+ const Gdk::Rectangle& background_area,
+ const Gdk::Rectangle& cell_area,
+ Gtk::CellRendererState flags )
+#else
+void LayerTypeIcon::render_vfunc( const Glib::RefPtr<Gdk::Drawable>& window,
+ Gtk::Widget& widget,
+ const Gdk::Rectangle& background_area,
+ const Gdk::Rectangle& cell_area,
+ const Gdk::Rectangle& expose_area,
+ Gtk::CellRendererState flags )
+#endif
+{
+ property_pixbuf() = _property_active.get_value() == 1 ? _property_pixbuf_group : (_property_active.get_value() == 2 ? _property_pixbuf_layer : _property_pixbuf_path);
+#if WITH_GTKMM_3_0
+ Gtk::CellRendererPixbuf::render_vfunc( cr, widget, background_area, cell_area, flags );
+#else
+ Gtk::CellRendererPixbuf::render_vfunc( window, widget, background_area, cell_area, expose_area, flags );
+#endif
+}
+
+bool
+LayerTypeIcon::activate_vfunc(GdkEvent* event,
+ Gtk::Widget& /*widget*/,
+ const Glib::ustring& path,
+ const Gdk::Rectangle& /*background_area*/,
+ const Gdk::Rectangle& /*cell_area*/,
+ Gtk::CellRendererState /*flags*/)
+{
+ _signal_pre_toggle.emit(event);
+ _signal_toggled.emit(path);
+
+ return false;
+}
+
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
+
+
diff --git a/src/ui/widget/layertypeicon.h b/src/ui/widget/layertypeicon.h
new file mode 100644
index 000000000..6c71ce361
--- /dev/null
+++ b/src/ui/widget/layertypeicon.h
@@ -0,0 +1,108 @@
+#ifndef __UI_DIALOG_LAYERTYPEICON_H__
+#define __UI_DIALOG_LAYERTYPEICON_H__
+/*
+ * Authors:
+ * Theodore Janeczko
+ *
+ * Copyright (C) Theodore Janeczko 2012 <flutterguy317@gmail.com>
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gtkmm/cellrendererpixbuf.h>
+#include <gtkmm/widget.h>
+#include <glibmm/property.h>
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+class LayerTypeIcon : public Gtk::CellRendererPixbuf {
+public:
+ LayerTypeIcon();
+ virtual ~LayerTypeIcon() {};
+
+ sigc::signal<void, const Glib::ustring&> signal_toggled() { return _signal_toggled;}
+ sigc::signal<void, GdkEvent const *> signal_pre_toggle() { return _signal_pre_toggle; }
+
+ Glib::PropertyProxy<int> property_active() { return _property_active.get_proxy(); }
+ Glib::PropertyProxy<int> property_activatable() { return _property_activatable.get_proxy(); }
+ Glib::PropertyProxy< Glib::RefPtr<Gdk::Pixbuf> > property_pixbuf_on();
+ Glib::PropertyProxy< Glib::RefPtr<Gdk::Pixbuf> > property_pixbuf_off();
+
+protected:
+
+#if WITH_GTKMM_3_0
+ virtual void render_vfunc( const Cairo::RefPtr<Cairo::Context>& cr,
+ Gtk::Widget& widget,
+ const Gdk::Rectangle& background_area,
+ const Gdk::Rectangle& cell_area,
+ Gtk::CellRendererState flags );
+
+ virtual void get_preferred_width_vfunc(Gtk::Widget& widget,
+ int& min_w,
+ int& nat_w) const;
+
+ virtual void get_preferred_height_vfunc(Gtk::Widget& widget,
+ int& min_h,
+ int& nat_h) const;
+#else
+ virtual void render_vfunc( const Glib::RefPtr<Gdk::Drawable>& window,
+ Gtk::Widget& widget,
+ const Gdk::Rectangle& background_area,
+ const Gdk::Rectangle& cell_area,
+ const Gdk::Rectangle& expose_area,
+ Gtk::CellRendererState flags );
+
+ virtual void get_size_vfunc( Gtk::Widget &widget,
+ Gdk::Rectangle const *cell_area,
+ int *x_offset, int *y_offset, int *width, int *height ) const;
+#endif
+
+ virtual bool activate_vfunc(GdkEvent *event,
+ Gtk::Widget &widget,
+ const Glib::ustring &path,
+ const Gdk::Rectangle &background_area,
+ const Gdk::Rectangle &cell_area,
+ Gtk::CellRendererState flags);
+
+
+private:
+ Glib::ustring _pixLayerName;
+ Glib::ustring _pixGroupName;
+ Glib::ustring _pixPathName;
+
+ Glib::Property<int> _property_active;
+ Glib::Property<int> _property_activatable;
+ Glib::Property< Glib::RefPtr<Gdk::Pixbuf> > _property_pixbuf_layer;
+ Glib::Property< Glib::RefPtr<Gdk::Pixbuf> > _property_pixbuf_group;
+ Glib::Property< Glib::RefPtr<Gdk::Pixbuf> > _property_pixbuf_path;
+
+ sigc::signal<void, const Glib::ustring&> _signal_toggled;
+ sigc::signal<void, GdkEvent const *> _signal_pre_toggle;
+
+};
+
+
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+
+#endif /* __UI_DIALOG_IMAGETOGGLER_H__ */
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/ui/widget/licensor.cpp b/src/ui/widget/licensor.cpp
index 42f352e3c..7429bb07e 100644
--- a/src/ui/widget/licensor.cpp
+++ b/src/ui/widget/licensor.cpp
@@ -160,9 +160,9 @@ void Licensor::update (SPDocument *doc)
Local Variables:
mode:c++
c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0))
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
indent-tabs-mode:nil
fill-column:99
End:
*/
-// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/ui/widget/licensor.h b/src/ui/widget/licensor.h
index 0ac3e5ab8..c75c5fe9e 100644
--- a/src/ui/widget/licensor.h
+++ b/src/ui/widget/licensor.h
@@ -56,9 +56,9 @@ protected:
Local Variables:
mode:c++
c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0))
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
indent-tabs-mode:nil
fill-column:99
End:
*/
-// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/ui/widget/notebook-page.cpp b/src/ui/widget/notebook-page.cpp
index 6653499b8..2f03ed23b 100644
--- a/src/ui/widget/notebook-page.cpp
+++ b/src/ui/widget/notebook-page.cpp
@@ -44,13 +44,13 @@ NotebookPage::NotebookPage(int n_rows, int n_columns, bool expand, bool fill, gu
} // namespace UI
} // namespace Inkscape
-/*
+/*
Local Variables:
mode:c++
c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0))
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
indent-tabs-mode:nil
fill-column:99
End:
*/
-// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/ui/widget/notebook-page.h b/src/ui/widget/notebook-page.h
index 38ae9e054..4f7915423 100644
--- a/src/ui/widget/notebook-page.h
+++ b/src/ui/widget/notebook-page.h
@@ -67,13 +67,13 @@ protected:
#endif // INKSCAPE_UI_WIDGET_NOTEBOOK_PAGE_H
-/*
+/*
Local Variables:
mode:c++
c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0))
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
indent-tabs-mode:nil
fill-column:99
End:
*/
-// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/ui/widget/object-composite-settings.cpp b/src/ui/widget/object-composite-settings.cpp
index 537db0fdd..e4cd76345 100644
--- a/src/ui/widget/object-composite-settings.cpp
+++ b/src/ui/widget/object-composite-settings.cpp
@@ -40,7 +40,7 @@ namespace UI {
namespace Widget {
/*void ObjectCompositeSettings::_on_desktop_activate(
- Inkscape::Application *application,
+ InkscapeApplication *application,
SPDesktop *desktop,
ObjectCompositeSettings *w
) {
@@ -50,7 +50,7 @@ namespace Widget {
}
void ObjectCompositeSettings::_on_desktop_deactivate(
- Inkscape::Application *application,
+ InkscapeApplication *application,
SPDesktop *desktop,
ObjectCompositeSettings *w
) {
diff --git a/src/ui/widget/object-composite-settings.h b/src/ui/widget/object-composite-settings.h
index 19a6cb2a5..e375bf24a 100644
--- a/src/ui/widget/object-composite-settings.h
+++ b/src/ui/widget/object-composite-settings.h
@@ -30,9 +30,9 @@
#include "ui/widget/spinbutton.h"
class SPDesktop;
+struct InkscapeApplication;
namespace Inkscape {
-struct Application;
namespace UI {
namespace Widget {
@@ -66,8 +66,8 @@ private:
gulong _desktop_activated;
sigc::connection _subject_changed;
- static void _on_desktop_activate(Inkscape::Application *application, SPDesktop *desktop, ObjectCompositeSettings *w);
- static void _on_desktop_deactivate(Inkscape::Application *application, SPDesktop *desktop, ObjectCompositeSettings *w);
+ static void _on_desktop_activate(InkscapeApplication *application, SPDesktop *desktop, ObjectCompositeSettings *w);
+ static void _on_desktop_deactivate(InkscapeApplication *application, SPDesktop *desktop, ObjectCompositeSettings *w);
void _subjectChanged();
void _blendBlurValueChanged();
void _opacityValueChanged();
diff --git a/src/ui/widget/page-sizer.cpp b/src/ui/widget/page-sizer.cpp
index eae0d4a95..32e357c57 100644
--- a/src/ui/widget/page-sizer.cpp
+++ b/src/ui/widget/page-sizer.cpp
@@ -311,8 +311,8 @@ PageSizer::PageSizer(Registry & _wr)
SPDesktop *dt = SP_ACTIVE_DESKTOP;
SPNamedView *nv = sp_desktop_namedview(dt);
_wr.setUpdating (true);
- if (nv->units) {
- _dimensionUnits.setUnit(nv->units->abbr);
+ if (nv->page_size_units) {
+ _dimensionUnits.setUnit(nv->page_size_units->abbr);
} else if (nv->doc_units) {
_dimensionUnits.setUnit(nv->doc_units->abbr);
}
@@ -728,9 +728,9 @@ PageSizer::on_units_changed()
Local Variables:
mode:c++
c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0))
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
indent-tabs-mode:nil
fill-column:99
End:
*/
-// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/ui/widget/page-sizer.h b/src/ui/widget/page-sizer.h
index dc8e34d82..f4bcae4b6 100644
--- a/src/ui/widget/page-sizer.h
+++ b/src/ui/widget/page-sizer.h
@@ -277,9 +277,9 @@ protected:
Local Variables:
mode:c++
c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0))
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
indent-tabs-mode:nil
fill-column:99
End:
*/
-// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/ui/widget/panel.cpp b/src/ui/widget/panel.cpp
index b37137228..0abd81b16 100644
--- a/src/ui/widget/panel.cpp
+++ b/src/ui/widget/panel.cpp
@@ -643,13 +643,13 @@ Panel::signalDocumentReplaced()
return _signal_document_replaced;
}
-sigc::signal<void, Inkscape::Application *, SPDesktop *> &
+sigc::signal<void, InkscapeApplication *, SPDesktop *> &
Panel::signalActivateDesktop()
{
return _signal_activate_desktop;
}
-sigc::signal<void, Inkscape::Application *, SPDesktop *> &
+sigc::signal<void, InkscapeApplication *, SPDesktop *> &
Panel::signalDeactiveDesktop()
{
return _signal_deactive_desktop;
diff --git a/src/ui/widget/panel.h b/src/ui/widget/panel.h
index 0c3d822b8..177314797 100644
--- a/src/ui/widget/panel.h
+++ b/src/ui/widget/panel.h
@@ -45,9 +45,9 @@ namespace Gtk {
class MenuItem;
}
-namespace Inkscape {
+struct InkscapeApplication;
-struct Application;
+namespace Inkscape {
class Selection;
namespace UI {
@@ -116,8 +116,8 @@ public:
void setResponseSensitive(int response_id, bool setting);
virtual sigc::signal<void, SPDesktop *, SPDocument *> &signalDocumentReplaced();
- virtual sigc::signal<void, Inkscape::Application *, SPDesktop *> &signalActivateDesktop();
- virtual sigc::signal<void, Inkscape::Application *, SPDesktop *> &signalDeactiveDesktop();
+ virtual sigc::signal<void, InkscapeApplication *, SPDesktop *> &signalActivateDesktop();
+ virtual sigc::signal<void, InkscapeApplication *, SPDesktop *> &signalDeactiveDesktop();
protected:
/**
@@ -147,8 +147,8 @@ protected:
sigc::signal<void, int> _signal_response;
sigc::signal<void> _signal_present;
sigc::signal<void, SPDesktop *, SPDocument *> _signal_document_replaced;
- sigc::signal<void, Inkscape::Application *, SPDesktop *> _signal_activate_desktop;
- sigc::signal<void, Inkscape::Application *, SPDesktop *> _signal_deactive_desktop;
+ sigc::signal<void, InkscapeApplication *, SPDesktop *> _signal_activate_desktop;
+ sigc::signal<void, InkscapeApplication *, SPDesktop *> _signal_deactive_desktop;
private:
void _init();
diff --git a/src/ui/widget/preferences-widget.cpp b/src/ui/widget/preferences-widget.cpp
index 3ba00c083..7f3e6cd47 100644
--- a/src/ui/widget/preferences-widget.cpp
+++ b/src/ui/widget/preferences-widget.cpp
@@ -14,10 +14,6 @@
# include <config.h>
#endif
-#ifdef WIN32
-#include <windows.h>
-#endif
-
#if GLIBMM_DISABLE_DEPRECATED && HAVE_GLIBMM_THREADS_H
#include <glibmm/threads.h>
#endif
@@ -49,6 +45,10 @@
#include <glibmm/convert.h>
#include <glibmm/i18n.h>
+#ifdef WIN32
+#include <windows.h>
+#endif
+
using namespace Inkscape::UI::Widget;
namespace Inkscape {
diff --git a/src/ui/widget/preferences-widget.h b/src/ui/widget/preferences-widget.h
index cb4ce17d1..5d9816e74 100644
--- a/src/ui/widget/preferences-widget.h
+++ b/src/ui/widget/preferences-widget.h
@@ -306,9 +306,9 @@ public:
Local Variables:
mode:c++
c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0))
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
indent-tabs-mode:nil
fill-column:99
End:
*/
-// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/ui/widget/registered-widget.cpp b/src/ui/widget/registered-widget.cpp
index 92cb3f03d..e97285de4 100644
--- a/src/ui/widget/registered-widget.cpp
+++ b/src/ui/widget/registered-widget.cpp
@@ -99,6 +99,59 @@ RegisteredCheckButton::on_toggled()
_wr->setUpdating (false);
}
+/*#########################################
+ * Registered TOGGLEBUTTON
+ */
+
+RegisteredToggleButton::~RegisteredToggleButton()
+{
+ _toggled_connection.disconnect();
+}
+
+RegisteredToggleButton::RegisteredToggleButton (const Glib::ustring& /*label*/, const Glib::ustring& tip, const Glib::ustring& key, Registry& wr, bool right, Inkscape::XML::Node* repr_in, SPDocument *doc_in, char const *active_str, char const *inactive_str)
+ : RegisteredWidget<Gtk::ToggleButton>()
+ , _active_str(active_str)
+ , _inactive_str(inactive_str)
+{
+ init_parent(key, wr, repr_in, doc_in);
+ setProgrammatically = false;
+ set_tooltip_text (tip);
+ set_alignment (right? 1.0 : 0.0, 0.5);
+ _toggled_connection = signal_toggled().connect (sigc::mem_fun (*this, &RegisteredToggleButton::on_toggled));
+}
+
+void
+RegisteredToggleButton::setActive (bool b)
+{
+ setProgrammatically = true;
+ set_active (b);
+ //The slave button is greyed out if the master button is untoggled
+ for (std::list<Gtk::Widget*>::const_iterator i = _slavewidgets.begin(); i != _slavewidgets.end(); ++i) {
+ (*i)->set_sensitive(b);
+ }
+ setProgrammatically = false;
+}
+
+void
+RegisteredToggleButton::on_toggled()
+{
+ if (setProgrammatically) {
+ setProgrammatically = false;
+ return;
+ }
+
+ if (_wr->isUpdating())
+ return;
+ _wr->setUpdating (true);
+
+ write_to_xml(get_active() ? _active_str : _inactive_str);
+ //The slave button is greyed out if the master button is untoggled
+ for (std::list<Gtk::Widget*>::const_iterator i = _slavewidgets.begin(); i != _slavewidgets.end(); ++i) {
+ (*i)->set_sensitive(get_active());
+ }
+
+ _wr->setUpdating (false);
+}
/*#########################################
* Registered UNITMENU
@@ -735,9 +788,9 @@ RegisteredRandom::on_value_changed()
Local Variables:
mode:c++
c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0))
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
indent-tabs-mode:nil
fill-column:99
End:
*/
-// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/ui/widget/registered-widget.h b/src/ui/widget/registered-widget.h
index d64c09c16..1f505a3cd 100644
--- a/src/ui/widget/registered-widget.h
+++ b/src/ui/widget/registered-widget.h
@@ -163,6 +163,31 @@ protected:
void on_toggled();
};
+class RegisteredToggleButton : public RegisteredWidget<Gtk::ToggleButton> {
+public:
+ virtual ~RegisteredToggleButton();
+ RegisteredToggleButton (const Glib::ustring& label, const Glib::ustring& tip, const Glib::ustring& key, Registry& wr, bool right=true, Inkscape::XML::Node* repr_in=NULL, SPDocument *doc_in=NULL, char const *active_str = "true", char const *inactive_str = "false");
+
+ void setActive (bool);
+
+ std::list<Gtk::Widget*> _slavewidgets;
+
+ // a slave button is only sensitive when the master button is active
+ // i.e. a slave button is greyed-out when the master button is not checked
+
+ void setSlaveWidgets(std::list<Gtk::Widget*> btns) {
+ _slavewidgets = btns;
+ }
+
+ bool setProgrammatically; // true if the value was set by setActive, not changed by the user;
+ // if a callback checks it, it must reset it back to false
+
+protected:
+ char const *_active_str, *_inactive_str;
+ sigc::connection _toggled_connection;
+ void on_toggled();
+};
+
class RegisteredUnitMenu : public RegisteredWidget<Labelled> {
public:
~RegisteredUnitMenu();
@@ -394,9 +419,9 @@ protected:
Local Variables:
mode:c++
c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0))
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
indent-tabs-mode:nil
fill-column:99
End:
*/
-// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/ui/widget/registry.cpp b/src/ui/widget/registry.cpp
index 725e52791..ea8198422 100644
--- a/src/ui/widget/registry.cpp
+++ b/src/ui/widget/registry.cpp
@@ -48,9 +48,9 @@ Registry::setUpdating (bool upd)
Local Variables:
mode:c++
c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0))
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
indent-tabs-mode:nil
fill-column:99
End:
*/
-// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/ui/widget/registry.h b/src/ui/widget/registry.h
index 2da29735c..a236b96ad 100644
--- a/src/ui/widget/registry.h
+++ b/src/ui/widget/registry.h
@@ -39,9 +39,9 @@ protected:
Local Variables:
mode:c++
c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0))
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
indent-tabs-mode:nil
fill-column:99
End:
*/
-// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/ui/widget/rendering-options.cpp b/src/ui/widget/rendering-options.cpp
index d6248df69..837387f7b 100644
--- a/src/ui/widget/rendering-options.cpp
+++ b/src/ui/widget/rendering-options.cpp
@@ -12,6 +12,9 @@
# include <config.h>
#endif
+#include <gtkmm.h>
+
+#include "preferences.h"
#include "rendering-options.h"
#include "util/units.h"
#include <glibmm/i18n.h>
@@ -38,6 +41,7 @@ RenderingOptions::RenderingOptions () :
Glib::ustring(""), Glib::ustring(""),
false)
{
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
// set up tooltips
_radio_vector.set_tooltip_text(
_("Render using Cairo vector operations. "
@@ -52,15 +56,21 @@ RenderingOptions::RenderingOptions () :
set_border_width(2);
- // default to vector operations
- _radio_vector.set_active (true);
Gtk::RadioButtonGroup group = _radio_vector.get_group ();
_radio_bitmap.set_group (group);
_radio_bitmap.signal_toggled().connect(sigc::mem_fun(*this, &RenderingOptions::_toggled));
-
+
+ // default to vector operations
+ if (prefs->getBool("/dialogs/printing/asbitmap", false)) {
+ _radio_bitmap.set_active();
+ } else {
+ _radio_vector.set_active();
+ }
+
// configure default DPI
_dpi.setRange(Inkscape::Util::Quantity::convert(1, "in", "pt"),2400.0);
- _dpi.setValue(Inkscape::Util::Quantity::convert(1, "in", "pt"));
+ _dpi.setValue(prefs->getDouble("/dialogs/printing/dpi",
+ Inkscape::Util::Quantity::convert(1, "in", "pt")));
_dpi.setIncrements(1.0,10.0);
_dpi.setDigits(0);
_dpi.update();
diff --git a/src/ui/widget/rotateable.cpp b/src/ui/widget/rotateable.cpp
index 72ec69362..2d7597d7c 100644
--- a/src/ui/widget/rotateable.cpp
+++ b/src/ui/widget/rotateable.cpp
@@ -173,13 +173,13 @@ Rotateable::~Rotateable() {
} // namespace UI
} // namespace Inkscape
-/*
+/*
Local Variables:
mode:c++
c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0))
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
indent-tabs-mode:nil
fill-column:99
End:
*/
-// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/ui/widget/rotateable.h b/src/ui/widget/rotateable.h
index 52fb5306c..6404c3550 100644
--- a/src/ui/widget/rotateable.h
+++ b/src/ui/widget/rotateable.h
@@ -62,9 +62,9 @@ private:
Local Variables:
mode:c++
c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0))
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
indent-tabs-mode:nil
fill-column:99
End:
*/
-// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/ui/widget/selected-style.cpp b/src/ui/widget/selected-style.cpp
index 042a6614e..d22c59aa4 100644
--- a/src/ui/widget/selected-style.cpp
+++ b/src/ui/widget/selected-style.cpp
@@ -25,6 +25,7 @@
#include "desktop-style.h"
#include "sp-namedview.h"
#include "sp-linear-gradient.h"
+#include "sp-mesh-gradient.h"
#include "sp-radial-gradient.h"
#include "sp-pattern.h"
#include "ui/dialog/dialog-manager.h"
@@ -179,7 +180,11 @@ SelectedStyle::SelectedStyle(bool /*layout*/)
_na[i].show_all();
__na[i] = (_("Nothing selected"));
- _none[i].set_markup (C_("Fill and stroke", "<i>None</i>"));
+ if (i == SS_FILL) {
+ _none[i].set_markup (C_("Fill", "<i>None</i>"));
+ } else {
+ _none[i].set_markup (C_("Stroke", "<i>None</i>"));
+ }
sp_set_font_size_smaller (GTK_WIDGET(_none[i].gobj()));
_none[i].show_all();
__none[i] = (i == SS_FILL)? (C_("Fill and stroke", "No fill")) : (C_("Fill and stroke", "No stroke"));
@@ -209,6 +214,18 @@ SelectedStyle::SelectedStyle(bool /*layout*/)
_gradient_box_r[i].pack_start(*(Glib::wrap(_gradient_preview_r[i])));
_gradient_box_r[i].show_all();
+#ifdef WITH_MESH
+ _mgradient[i].set_markup (_("<b>M</b>"));
+ sp_set_font_size_smaller (GTK_WIDGET(_mgradient[i].gobj()));
+ _mgradient[i].show_all();
+ __mgradient[i] = (i == SS_FILL)? (_("Mesh gradient fill")) : (_("Mesh gradient stroke"));
+
+ _gradient_preview_m[i] = GTK_WIDGET(sp_gradient_image_new (NULL));
+ _gradient_box_m[i].pack_start(_mgradient[i]);
+ _gradient_box_m[i].pack_start(*(Glib::wrap(_gradient_preview_m[i])));
+ _gradient_box_m[i].show_all();
+#endif
+
_many[i].set_markup (_("Different"));
sp_set_font_size_smaller (GTK_WIDGET(_many[i].gobj()));
_many[i].show_all();
@@ -1028,6 +1045,14 @@ SelectedStyle::update()
place->add(_gradient_box_r[i]);
place->set_tooltip_text(__rgradient[i]);
_mode[i] = SS_RGRADIENT;
+#ifdef WITH_MESH
+ } else if (SP_IS_MESHGRADIENT(server)) {
+ SPGradient *vector = SP_GRADIENT(server)->getVector();
+ sp_gradient_image_set_gradient(SP_GRADIENT_IMAGE(_gradient_preview_m[i]), vector);
+ place->add(_gradient_box_m[i]);
+ place->set_tooltip_text(__mgradient[i]);
+ _mode[i] = SS_MGRADIENT;
+#endif
} else if (SP_IS_PATTERN (server)) {
place->add(_pattern[i]);
place->set_tooltip_text(__pattern[i]);
@@ -1195,7 +1220,9 @@ void SelectedStyle::on_opacity_menu (Gtk::Menu *menu) {
menu->show_all();
}
-void SelectedStyle::on_opacity_changed () {
+void SelectedStyle::on_opacity_changed ()
+{
+ g_return_if_fail(_desktop); // TODO this shouldn't happen!
if (_opacity_blocked)
return;
_opacity_blocked = true;
@@ -1550,9 +1577,9 @@ Dialog::FillAndStroke *get_fill_and_stroke_panel(SPDesktop *desktop)
Local Variables:
mode:c++
c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0))
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
indent-tabs-mode:nil
fill-column:99
End:
*/
-// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/ui/widget/selected-style.h b/src/ui/widget/selected-style.h
index 9557a8d74..0b6a14762 100644
--- a/src/ui/widget/selected-style.h
+++ b/src/ui/widget/selected-style.h
@@ -60,6 +60,9 @@ enum {
SS_PATTERN,
SS_LGRADIENT,
SS_RGRADIENT,
+#ifdef WITH_MESH
+ SS_MGRADIENT,
+#endif
SS_MANY,
SS_COLOR
};
@@ -186,6 +189,14 @@ protected:
GtkWidget *_gradient_preview_r[2];
Gtk::HBox _gradient_box_r[2];
+#ifdef WITH_MESH
+ Gtk::Label _mgradient[2];
+ Glib::ustring __mgradient[2];
+
+ GtkWidget *_gradient_preview_m[2];
+ Gtk::HBox _gradient_box_m[2];
+#endif
+
Gtk::Label _many[2];
Glib::ustring __many[2];
@@ -290,13 +301,13 @@ protected:
#endif // INKSCAPE_UI_WIDGET_BUTTON_H
-/*
+/*
Local Variables:
mode:c++
c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0))
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
indent-tabs-mode:nil
fill-column:99
End:
*/
-// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/ui/widget/spin-scale.cpp b/src/ui/widget/spin-scale.cpp
index ade3d1e60..bb08d67df 100644
--- a/src/ui/widget/spin-scale.cpp
+++ b/src/ui/widget/spin-scale.cpp
@@ -235,13 +235,13 @@ void DualSpinScale::update_linked()
} // namespace UI
} // namespace Inkscape
-/*
+/*
Local Variables:
mode:c++
c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0))
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
indent-tabs-mode:nil
fill-column:99
End:
*/
-// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/ui/widget/spin-scale.h b/src/ui/widget/spin-scale.h
index 5fec8b1d8..d0447e4a6 100644
--- a/src/ui/widget/spin-scale.h
+++ b/src/ui/widget/spin-scale.h
@@ -113,13 +113,13 @@ private:
#endif // INKSCAPE_UI_WIDGET_SPIN_SCALE_H
-/*
+/*
Local Variables:
mode:c++
c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0))
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
indent-tabs-mode:nil
fill-column:99
End:
*/
-// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/ui/widget/spin-slider.cpp b/src/ui/widget/spin-slider.cpp
index 1cb59a7b3..9b361ae78 100644
--- a/src/ui/widget/spin-slider.cpp
+++ b/src/ui/widget/spin-slider.cpp
@@ -262,13 +262,13 @@ void DualSpinSlider::update_linked()
} // namespace UI
} // namespace Inkscape
-/*
+/*
Local Variables:
mode:c++
c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0))
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
indent-tabs-mode:nil
fill-column:99
End:
*/
-// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/ui/widget/spin-slider.h b/src/ui/widget/spin-slider.h
index 5f86fd15a..74982ea58 100644
--- a/src/ui/widget/spin-slider.h
+++ b/src/ui/widget/spin-slider.h
@@ -111,13 +111,13 @@ private:
#endif // INKSCAPE_UI_WIDGET_SPIN_SLIDER_H
-/*
+/*
Local Variables:
mode:c++
c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0))
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
indent-tabs-mode:nil
fill-column:99
End:
*/
-// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/ui/widget/spinbutton.cpp b/src/ui/widget/spinbutton.cpp
index 7709a837b..d7669d4e5 100644
--- a/src/ui/widget/spinbutton.cpp
+++ b/src/ui/widget/spinbutton.cpp
@@ -100,13 +100,13 @@ void SpinButton::undo()
} // namespace UI
} // namespace Inkscape
-/*
+/*
Local Variables:
mode:c++
c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0))
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
indent-tabs-mode:nil
fill-column:99
End:
*/
-// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/ui/widget/spinbutton.h b/src/ui/widget/spinbutton.h
index 812b5f515..cbe33e8ea 100644
--- a/src/ui/widget/spinbutton.h
+++ b/src/ui/widget/spinbutton.h
@@ -111,13 +111,13 @@ private:
#endif // INKSCAPE_UI_WIDGET_SPINBUTTON_H
-/*
+/*
Local Variables:
mode:c++
c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0))
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
indent-tabs-mode:nil
fill-column:99
End:
*/
-// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/ui/widget/style-subject.h b/src/ui/widget/style-subject.h
index c2941d995..47da91732 100644
--- a/src/ui/widget/style-subject.h
+++ b/src/ui/widget/style-subject.h
@@ -20,7 +20,7 @@
class SPDesktop;
class SPObject;
class SPCSSAttr;
-struct SPStyle;
+class SPStyle;
namespace Inkscape {
class Selection;
diff --git a/src/ui/widget/style-swatch.cpp b/src/ui/widget/style-swatch.cpp
index a33c1d09f..157fd2ad9 100644
--- a/src/ui/widget/style-swatch.cpp
+++ b/src/ui/widget/style-swatch.cpp
@@ -261,7 +261,7 @@ void StyleSwatch::setStyle(SPCSSAttr *css)
Glib::ustring css_string;
sp_repr_css_write_string (_css, css_string);
SPStyle *temp_spstyle = sp_style_new(SP_ACTIVE_DOCUMENT);
- if (~css_string.empty()) {
+ if (!css_string.empty()) {
sp_style_merge_from_style_string (temp_spstyle, css_string.c_str());
}
@@ -386,9 +386,9 @@ void StyleSwatch::setStyle(SPStyle *query)
Local Variables:
mode:c++
c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0))
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
indent-tabs-mode:nil
fill-column:99
End:
*/
-// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/ui/widget/style-swatch.h b/src/ui/widget/style-swatch.h
index 23ecbdfda..582d2ebb3 100644
--- a/src/ui/widget/style-swatch.h
+++ b/src/ui/widget/style-swatch.h
@@ -29,7 +29,7 @@
#include "desktop.h"
#include "preferences.h"
-struct SPStyle;
+class SPStyle;
class SPCSSAttr;
namespace Gtk {
@@ -108,13 +108,13 @@ friend class ToolObserver;
#endif // INKSCAPE_UI_WIDGET_BUTTON_H
-/*
+/*
Local Variables:
mode:c++
c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0))
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
indent-tabs-mode:nil
fill-column:99
End:
*/
-// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/ui/widget/tolerance-slider.cpp b/src/ui/widget/tolerance-slider.cpp
index 5fc588fdc..aac7451f4 100644
--- a/src/ui/widget/tolerance-slider.cpp
+++ b/src/ui/widget/tolerance-slider.cpp
@@ -216,9 +216,9 @@ void ToleranceSlider::update (double val)
Local Variables:
mode:c++
c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0))
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
indent-tabs-mode:nil
fill-column:99
End:
*/
-// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/ui/widget/tolerance-slider.h b/src/ui/widget/tolerance-slider.h
index 2184cd52b..7ae8e4712 100644
--- a/src/ui/widget/tolerance-slider.h
+++ b/src/ui/widget/tolerance-slider.h
@@ -88,9 +88,9 @@ protected:
Local Variables:
mode:c++
c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0))
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
indent-tabs-mode:nil
fill-column:99
End:
*/
-// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/ui/widget/unit-menu.cpp b/src/ui/widget/unit-menu.cpp
index 7416a2f02..423313a1f 100644
--- a/src/ui/widget/unit-menu.cpp
+++ b/src/ui/widget/unit-menu.cpp
@@ -140,13 +140,13 @@ bool UnitMenu::isRadial() const
} // namespace UI
} // namespace Inkscape
-/*
+/*
Local Variables:
mode:c++
c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0))
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
indent-tabs-mode:nil
fill-column:99
End:
*/
-// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/ui/widget/unit-menu.h b/src/ui/widget/unit-menu.h
index 114c536c9..2fd25a6a9 100644
--- a/src/ui/widget/unit-menu.h
+++ b/src/ui/widget/unit-menu.h
@@ -141,9 +141,9 @@ protected:
Local Variables:
mode:c++
c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0))
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
indent-tabs-mode:nil
fill-column:99
End:
*/
-// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/ui/widget/unit-tracker.cpp b/src/ui/widget/unit-tracker.cpp
index 67eb1f48d..c6318db25 100644
--- a/src/ui/widget/unit-tracker.cpp
+++ b/src/ui/widget/unit-tracker.cpp
@@ -13,7 +13,7 @@
*/
#include "unit-tracker.h"
-#include "ege-select-one-action.h"
+#include "widgets/ege-select-one-action.h"
#define COLUMN_STRING 0
diff --git a/src/ui/widget/unit-tracker.h b/src/ui/widget/unit-tracker.h
index 61bb556ef..06245930e 100644
--- a/src/ui/widget/unit-tracker.h
+++ b/src/ui/widget/unit-tracker.h
@@ -16,13 +16,16 @@
#define INKSCAPE_UI_WIDGET_UNIT_TRACKER_H
#include <map>
-#include <gtk/gtk.h>
-
#include "util/units.h"
using Inkscape::Util::Unit;
using Inkscape::Util::UnitType;
+typedef struct _GObject GObject;
+typedef struct _GtkAction GtkAction;
+typedef struct _GtkAdjustment GtkAdjustment;
+typedef struct _GtkListStore GtkListStore;
+
namespace Inkscape {
namespace UI {
namespace Widget {
diff --git a/src/unclump.cpp b/src/unclump.cpp
index 1427e8eab..940369d7a 100644
--- a/src/unclump.cpp
+++ b/src/unclump.cpp
@@ -17,6 +17,7 @@
#include "sp-item.h"
#include "unclump.h"
+#include <glib.h>
// Taking bbox of an item is an expensive operation, and we need to do it many times, so here we
// cache the centers, widths, and heights of items
diff --git a/src/unclump.h b/src/unclump.h
index 18148b215..2411cb713 100644
--- a/src/unclump.h
+++ b/src/unclump.h
@@ -11,7 +11,7 @@
#ifndef SEEN_DIALOGS_UNCLUMP_H
#define SEEN_DIALOGS_UNCLUMP_H
-#include <glib.h>
+typedef struct _GSList GSList;
void unclump(GSList *items);
diff --git a/src/unicoderange.h b/src/unicoderange.h
index 2f73f7b47..342b3fa3e 100644
--- a/src/unicoderange.h
+++ b/src/unicoderange.h
@@ -1,17 +1,19 @@
#include <glibmm/ustring.h>
-#include <glib-object.h>
#include <vector>
+// A type which can hold any UTF-32 or UCS-4 character code.
+typedef unsigned int gunichar;
+
struct Urange{
- gchar* start;
- gchar* end;
+ char* start;
+ char* end;
};
class UnicodeRange{
public:
-UnicodeRange(const gchar* val);
-int add_range(gchar* val);
-bool contains(gchar unicode);
+UnicodeRange(const char* val);
+int add_range(char* val);
+bool contains(char unicode);
Glib::ustring attribute_string();
gunichar sample_glyph();
diff --git a/src/uri-references.cpp b/src/uri-references.cpp
index 6db2ed21f..b23bed74a 100644
--- a/src/uri-references.cpp
+++ b/src/uri-references.cpp
@@ -1,6 +1,4 @@
-#define __SP_URI_REFERENCES_C__
-
-/*
+/**
* Helper methods for resolving URI References
*
* Authors:
@@ -206,4 +204,4 @@ sp_uri_reference_resolve (SPDocument *document, const gchar *uri)
fill-column:99
End:
*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8 :
diff --git a/src/uri-references.h b/src/uri-references.h
index 631d440da..0c51481cc 100644
--- a/src/uri-references.h
+++ b/src/uri-references.h
@@ -14,7 +14,7 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include <stddef.h>
+#include <cstddef>
#include <sigc++/connection.h>
#include <sigc++/trackable.h>
@@ -62,7 +62,7 @@ public:
* @param rel_document document for relative URIs
* @param uri the URI to watch
*/
- void attach(const URI &uri) throw(BadURIException);
+ void attach(URI const& uri) throw(BadURIException);
/**
* Detaches from the currently attached URI target, if any;
@@ -105,7 +105,7 @@ public:
*
* @returns the currently attached URI, or NULL
*/
- const URI *getURI() const {
+ URI const* getURI() const {
return _uri;
}
@@ -140,7 +140,7 @@ private:
void _setObject(SPObject *object);
void _release(SPObject *object);
- void operator=(const URIReference &ref);
+ void operator=(URIReference const& ref);
/* Private and definition-less to prevent accidental use. */
};
@@ -149,9 +149,9 @@ private:
/**
* Resolves an item referenced by a URI in CSS form contained in "url(...)"
*/
-SPObject* sp_css_uri_reference_resolve( SPDocument *document, const gchar *uri );
+SPObject* sp_css_uri_reference_resolve( SPDocument *document, const char *uri );
-SPObject *sp_uri_reference_resolve (SPDocument *document, const gchar *uri);
+SPObject *sp_uri_reference_resolve (SPDocument *document, const char *uri);
#endif // SEEN_SP_URI_REFERENCES_H
@@ -164,4 +164,4 @@ SPObject *sp_uri_reference_resolve (SPDocument *document, const gchar *uri);
fill-column:99
End:
*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8 :
diff --git a/src/uri.h b/src/uri.h
index c6c2264cc..cee1baa09 100644
--- a/src/uri.h
+++ b/src/uri.h
@@ -11,7 +11,6 @@
#ifndef INKSCAPE_URI_H
#define INKSCAPE_URI_H
-#include <glib.h>
#include <exception>
#include <libxml/uri.h>
#include "bad-uri-exception.h"
@@ -38,7 +37,7 @@ public:
*
* @param preformed Properly quoted C-style string to be represented.
*/
- explicit URI(gchar const *preformed) throw(BadURIException);
+ explicit URI(char const *preformed) throw(BadURIException);
/**
* Destructor.
@@ -89,25 +88,25 @@ public:
*/
bool isAbsolutePath() const { return _impl->isAbsolutePath(); }
- const gchar *getScheme() const { return _impl->getScheme(); }
+ const char *getScheme() const { return _impl->getScheme(); }
- const gchar *getPath() const { return _impl->getPath(); }
+ const char *getPath() const { return _impl->getPath(); }
- const gchar *getQuery() const { return _impl->getQuery(); }
+ const char *getQuery() const { return _impl->getQuery(); }
- const gchar *getFragment() const { return _impl->getFragment(); }
+ const char *getFragment() const { return _impl->getFragment(); }
- const gchar *getOpaque() const { return _impl->getOpaque(); }
+ const char *getOpaque() const { return _impl->getOpaque(); }
- static URI fromUtf8( gchar const* path ) throw (BadURIException);
+ static URI fromUtf8( char const* path ) throw (BadURIException);
- static URI from_native_filename(gchar const *path) throw(BadURIException);
+ static URI from_native_filename(char const *path) throw(BadURIException);
- static gchar *to_native_filename(gchar const* uri) throw(BadURIException);
+ static char *to_native_filename(char const* uri) throw(BadURIException);
const std::string getFullPath(std::string const base) const;
- gchar *toNativeFilename() const throw(BadURIException);
+ char *toNativeFilename() const throw(BadURIException);
/**
* Returns a glib string version of this URI.
@@ -116,7 +115,7 @@ public:
*
* @return a glib string version of this URI.
*/
- gchar *toString() const { return _impl->toString(); }
+ char *toString() const { return _impl->toString(); }
/**
* Assignment operator.
@@ -135,12 +134,12 @@ private:
bool isNetPath() const;
bool isRelativePath() const;
bool isAbsolutePath() const;
- const gchar *getScheme() const;
- const gchar *getPath() const;
- const gchar *getQuery() const;
- const gchar *getFragment() const;
- const gchar *getOpaque() const;
- gchar *toString() const;
+ const char *getScheme() const;
+ const char *getPath() const;
+ const char *getQuery() const;
+ const char *getFragment() const;
+ const char *getOpaque() const;
+ char *toString() const;
private:
Impl(xmlURIPtr uri);
~Impl();
diff --git a/src/util/CMakeLists.txt b/src/util/CMakeLists.txt
index cfccfa94d..732e01b0c 100644
--- a/src/util/CMakeLists.txt
+++ b/src/util/CMakeLists.txt
@@ -5,6 +5,7 @@ set(util_SRC
expression-evaluator.cpp
share.cpp
units.cpp
+ ziptool.cpp
# -------
@@ -34,10 +35,12 @@ set(util_SRC
reference.h
reverse-list.h
share.h
+ signal-blocker.h
tuple.h
ucompose.hpp
units.h
unordered-containers.h
+ ziptool.h
)
# add_inkscape_lib(util_LIB "${util_SRC}")
diff --git a/src/util/Makefile_insert b/src/util/Makefile_insert
index 7169fa8f7..6d2e63278 100644
--- a/src/util/Makefile_insert
+++ b/src/util/Makefile_insert
@@ -31,6 +31,7 @@ ink_common_sources += \
util/reverse-list.h \
util/share.h \
util/share.cpp \
+ util/signal-blocker.h \
util/tuple.h \
util/ucompose.hpp \
util/units.cpp \
diff --git a/src/util/units.cpp b/src/util/units.cpp
index d2053f60b..3d635e2d2 100644
--- a/src/util/units.cpp
+++ b/src/util/units.cpp
@@ -206,7 +206,6 @@ bool Unit::compatibleWith(Unit const *u) const
}
bool Unit::compatibleWith(Glib::ustring const &u) const
{
- static UnitTable unit_table;
return compatibleWith(unit_table.getUnit(u));
}
@@ -291,11 +290,15 @@ Quantity UnitTable::parseQuantity(Glib::ustring const &q) const
std::istringstream tmp_v(match_info.fetch(0));
tmp_v >> value;
}
+ int start_pos, end_pos;
+ match_info.fetch_pos(0, end_pos, start_pos);
+ end_pos = q.size() - start_pos;
+ Glib::ustring u = q.substr(start_pos, end_pos);
// Extract unit abbreviation
Glib::ustring abbr;
Glib::RefPtr<Glib::Regex> unit_regex = Glib::Regex::create("[A-z%]+");
- if (unit_regex->match(q, match_info)) {
+ if (unit_regex->match(u, match_info)) {
abbr = match_info.fetch(0);
}
diff --git a/src/vanishing-point.cpp b/src/vanishing-point.cpp
index bb6a2c4d7..13dd03ee3 100644
--- a/src/vanishing-point.cpp
+++ b/src/vanishing-point.cpp
@@ -6,6 +6,7 @@
* Johan Engelen <j.b.c.engelen@ewi.utwente.nl>
* Maximilian Albert <Anhalter42@gmx.de>
* Abhishek Sharma
+ * Jon A. Cruz <jon@joncruz.org>
*
* Copyright (C) 2005-2007 authors
*
@@ -22,7 +23,7 @@
#include "ui/tools/tool-base.h"
#include "xml/repr.h"
#include "perspective-line.h"
-#include "shape-editor.h"
+#include "ui/shape-editor.h"
#include "snap.h"
#include "sp-namedview.h"
#include "ui/control-manager.h"
@@ -256,11 +257,10 @@ std::list<SPBox3D *>
VanishingPoint::selectedBoxes(Inkscape::Selection *sel) {
std::list<SPBox3D *> sel_boxes;
for (GSList const* i = sel->itemList(); i != NULL; i = i->next) {
- if (!SP_IS_BOX3D(i->data))
- continue;
- SPBox3D *box = SP_BOX3D(i->data);
- if (this->hasBox(box)) {
- sel_boxes.push_back (box);
+ SPItem *item = static_cast<SPItem *>(i->data);
+ SPBox3D *box = dynamic_cast<SPBox3D *>(item);
+ if (box && this->hasBox(box)) {
+ sel_boxes.push_back(box);
}
}
return sel_boxes;
@@ -396,12 +396,13 @@ VPDragger::VPsOfSelectedBoxes() {
// FIXME: Should we take the selection from the parent VPDrag? I guess it shouldn't make a difference.
Inkscape::Selection *sel = sp_desktop_selection(inkscape_active_desktop());
for (GSList const* i = sel->itemList(); i != NULL; i = i->next) {
- if (!SP_IS_BOX3D(i->data))
- continue;
- SPBox3D *box = SP_BOX3D(i->data);
- vp = this->findVPWithBox(box);
- if (vp) {
- sel_vps.insert (vp);
+ SPItem *item = static_cast<SPItem *>(i->data);
+ SPBox3D *box = dynamic_cast<SPBox3D *>(item);
+ if (box) {
+ vp = this->findVPWithBox(box);
+ if (vp) {
+ sel_vps.insert (vp);
+ }
}
}
return sel_vps;
@@ -577,14 +578,14 @@ VPDrag::updateDraggers ()
g_return_if_fail (this->selection != NULL);
for (GSList const* i = this->selection->itemList(); i != NULL; i = i->next) {
- SPItem *item = SP_ITEM(i->data);
- if (!SP_IS_BOX3D (item)) continue;
- SPBox3D *box = SP_BOX3D (item);
-
- VanishingPoint vp;
- for (int i = 0; i < 3; ++i) {
- vp.set(box3d_get_perspective(box), Proj::axes[i]);
- addDragger (vp);
+ SPItem *item = static_cast<SPItem *>(i->data);
+ SPBox3D *box = dynamic_cast<SPBox3D *>(item);
+ if (box) {
+ VanishingPoint vp;
+ for (int i = 0; i < 3; ++i) {
+ vp.set(box3d_get_perspective(box), Proj::axes[i]);
+ addDragger (vp);
+ }
}
}
}
@@ -609,12 +610,13 @@ VPDrag::updateLines ()
g_return_if_fail (this->selection != NULL);
for (GSList const* i = this->selection->itemList(); i != NULL; i = i->next) {
- if (!SP_IS_BOX3D(i->data)) continue;
- SPBox3D *box = SP_BOX3D (i->data);
-
- this->drawLinesForFace (box, Proj::X);
- this->drawLinesForFace (box, Proj::Y);
- this->drawLinesForFace (box, Proj::Z);
+ SPItem *item = static_cast<SPItem *>(i->data);
+ SPBox3D *box = dynamic_cast<SPBox3D *>(item);
+ if (box) {
+ this->drawLinesForFace (box, Proj::X);
+ this->drawLinesForFace (box, Proj::Y);
+ this->drawLinesForFace (box, Proj::Z);
+ }
}
}
diff --git a/src/vanishing-point.h b/src/vanishing-point.h
index ca34d9118..7242a94ee 100644
--- a/src/vanishing-point.h
+++ b/src/vanishing-point.h
@@ -12,8 +12,10 @@
#ifndef SEEN_VANISHING_POINT_H
#define SEEN_VANISHING_POINT_H
-#include <set>
#include <2geom/point.h>
+#include <list>
+#include <set>
+
#include "knot.h"
#include "selection.h"
#include "persp3d.h"
@@ -21,6 +23,8 @@
#include "ui/control-manager.h" // TODO break enums out separately
class SPBox3D;
+typedef struct _GList GList;
+typedef struct _GSList GSList;
namespace Box3D {
@@ -101,7 +105,7 @@ public:
g_return_if_fail (_persp);
persp3d_get_VP (_persp, _axis).print("");
}
- inline gchar const *axisString () { return Proj::string_from_axis(_axis); }
+ inline char const *axisString () { return Proj::string_from_axis(_axis); }
unsigned int my_counter;
static unsigned int global_counter; // FIXME: Only to implement operator< so that we can merge lists. Do this in a better way!!
@@ -140,7 +144,7 @@ public:
void updateTip();
- guint numberOfBoxes(); // the number of boxes linked to all VPs of the dragger
+ unsigned int numberOfBoxes(); // the number of boxes linked to all VPs of the dragger
VanishingPoint *findVPWithBox(SPBox3D *box);
std::set<VanishingPoint*, less_ptr> VPsOfSelectedBoxes();
@@ -185,7 +189,7 @@ public:
void updateBoxDisplays ();
void drawLinesForFace (const SPBox3D *box, Proj::Axis axis); //, guint corner1, guint corner2, guint corner3, guint corner4);
bool show_lines; /* whether perspective lines are drawn at all */
- guint front_or_rear_lines; /* whether we draw perspective lines from all corners or only the
+ unsigned int front_or_rear_lines; /* whether we draw perspective lines from all corners or only the
front/rear corners (indicated by the first/second bit, respectively */
diff --git a/src/verbs.cpp b/src/verbs.cpp
index fad090852..b4743751e 100644
--- a/src/verbs.cpp
+++ b/src/verbs.cpp
@@ -53,7 +53,7 @@
#include "helper/action-context.h"
#include "help.h"
#include "inkscape-private.h"
-#include "interface.h"
+#include "ui/interface.h"
#include "layer-fns.h"
#include "layer-manager.h"
#include "message-stack.h"
@@ -62,14 +62,15 @@
#include "ui/tools/select-tool.h"
#include "selection-chemistry.h"
#include "seltrans.h"
-#include "shape-editor.h"
+#include "ui/shape-editor.h"
#include "shortcuts.h"
+#include "sp-defs.h"
#include "sp-flowtext.h"
#include "sp-guide.h"
#include "splivarot.h"
#include "sp-namedview.h"
#include "text-chemistry.h"
-#include "tools-switch.h"
+#include "ui/tools-switch.h"
#include "ui/dialog/align-and-distribute.h"
#include "ui/dialog/clonetiler.h"
#include "ui/dialog/dialog-manager.h"
@@ -215,6 +216,25 @@ public:
}; // ObjectVerb class
/**
+ * A class to encompass all of the verbs which deal with operations related to tags.
+ */
+class TagVerb : public Verb {
+private:
+ static void perform(SPAction *action, void *mydata);
+protected:
+ virtual SPAction *make_action(Inkscape::ActionContext const & context);
+public:
+ /** Use the Verb initializer with the same parameters. */
+ TagVerb(unsigned int const code,
+ gchar const *id,
+ gchar const *name,
+ gchar const *tip,
+ gchar const *image) :
+ Verb(code, id, name, tip, image, _("Tag"))
+ { }
+}; // TagVerb class
+
+/**
* A class to encompass all of the verbs which deal with operations relative to context.
*/
class ContextVerb : public Verb {
@@ -460,6 +480,19 @@ SPAction *ObjectVerb::make_action(Inkscape::ActionContext const & context)
}
/**
+ * Create an action for a \c TagVerb.
+ *
+ * Calls \c make_action_helper with the \c vector.
+ *
+ * @param view Which view the action should be created for.
+ * @return The built action.
+ */
+SPAction *TagVerb::make_action(Inkscape::ActionContext const & context)
+{
+ return make_action_helper(context, &perform);
+}
+
+/**
* Create an action for a \c ContextVerb.
*
* Calls \c make_action_helper with the \c vector.
@@ -1372,6 +1405,10 @@ void LayerVerb::perform(SPAction *action, void *data)
survivor = Inkscape::previous_layer(dt->currentRoot(), old_layer);
}
+ if (survivor == old_layer->lastChild()) {
+ //oops: layer_fns messed up. BADLY.
+ survivor = NULL;
+ }
// Deleting the old layer before switching layers is a hack to trigger the
// listeners of the deletion event (as happens when old_layer is deleted using the
// xml editor). See
@@ -1398,7 +1435,7 @@ void LayerVerb::perform(SPAction *action, void *data)
dt->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("No current layer."));
} else {
dt->toggleLayerSolo( dt->currentLayer() );
- DocumentUndo::maybeDone(sp_desktop_document(dt), "layer:solo", SP_VERB_LAYER_SOLO, _("Toggle layer solo"));
+ DocumentUndo::done(sp_desktop_document(dt), SP_VERB_LAYER_SOLO, _("Toggle layer solo"));
}
break;
}
@@ -1422,7 +1459,7 @@ void LayerVerb::perform(SPAction *action, void *data)
dt->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("No current layer."));
} else {
dt->toggleLockOtherLayers( dt->currentLayer() );
- DocumentUndo::maybeDone(sp_desktop_document(dt), "layer:lockothers", SP_VERB_LAYER_LOCK_OTHERS, _("Lock other layers"));
+ DocumentUndo::done(sp_desktop_document(dt), SP_VERB_LAYER_LOCK_OTHERS, _("Lock other layers"));
}
break;
}
@@ -1531,6 +1568,9 @@ void ObjectVerb::perform( SPAction *action, void *data)
case SP_VERB_OBJECT_SET_CLIPPATH:
sp_selection_set_mask(dt, true, false);
break;
+ case SP_VERB_OBJECT_CREATE_CLIP_GROUP:
+ sp_selection_set_clipgroup(dt);
+ break;
case SP_VERB_OBJECT_EDIT_CLIPPATH:
sp_selection_edit_clip_or_mask(dt, true);
break;
@@ -1546,6 +1586,47 @@ void ObjectVerb::perform( SPAction *action, void *data)
/**
* Decode the verb code and take appropriate action.
*/
+void TagVerb::perform( SPAction *action, void *data)
+{
+ SPDesktop *dt = static_cast<SPDesktop*>(sp_action_get_view(action));
+ if (!dt)
+ return;
+
+ //Inkscape::UI::Tools::ToolBase *ec = dt->event_context;
+
+ Inkscape::Selection *sel = sp_desktop_selection(dt);
+
+ Inkscape::XML::Document * doc;
+ Inkscape::XML::Node * repr;
+ gchar *id;
+
+ switch (reinterpret_cast<std::size_t>(data)) {
+ case SP_VERB_TAG_NEW:
+ static int tag_suffix=1;
+ id=NULL;
+ do {
+ g_free(id);
+ id = g_strdup_printf("Set %d", tag_suffix++);
+ } while (dt->doc()->getObjectById(id));
+
+ doc = dt->doc()->getReprDoc();
+ repr = doc->createElement("inkscape:tag");
+ repr->setAttribute("id", id);
+ g_free(id);
+
+ dt->doc()->getDefs()->addChild(repr, NULL);
+ Inkscape::DocumentUndo::done(dt->doc(), SP_VERB_DIALOG_TAGS, _("Create new selection set"));
+ break;
+ default:
+ break;
+ }
+
+} // end of sp_verb_action_tag_perform()
+
+
+/**
+ * Decode the verb code and take appropriate action.
+ */
void ContextVerb::perform(SPAction *action, void *data)
{
SPDesktop *dt;
@@ -1777,6 +1858,13 @@ void ZoomVerb::perform(SPAction *action, void *data)
gdouble zoom_inc =
prefs->getDoubleLimited( "/options/zoomincrement/value", 1.414213562, 1.01, 10 );
+ double zcorr = 1.0;
+ Glib::ustring abbr = prefs->getString("/options/zoomcorrection/unit");
+ if (dt->namedview->doc_units && dt->namedview->doc_units->abbr == abbr)
+ zcorr = prefs->getDouble("/options/zoomcorrection/value", 1.0);
+
+ Geom::Rect const d = dt->get_display_area();
+
switch (reinterpret_cast<std::size_t>(data)) {
case SP_VERB_ZOOM_IN:
{
@@ -1792,7 +1880,6 @@ void ZoomVerb::perform(SPAction *action, void *data)
}
}
- Geom::Rect const d = dt->get_display_area();
dt->zoom_relative( d.midpoint()[Geom::X], d.midpoint()[Geom::Y], mul*zoom_inc);
break;
}
@@ -1810,31 +1897,18 @@ void ZoomVerb::perform(SPAction *action, void *data)
}
}
- Geom::Rect const d = dt->get_display_area();
dt->zoom_relative( d.midpoint()[Geom::X], d.midpoint()[Geom::Y], 1 / (mul*zoom_inc) );
break;
}
case SP_VERB_ZOOM_1_1:
- {
- double zcorr = prefs->getDouble("/options/zoomcorrection/value", 1.0);
- Geom::Rect const d = dt->get_display_area();
dt->zoom_absolute( d.midpoint()[Geom::X], d.midpoint()[Geom::Y], 1.0 * zcorr );
break;
- }
case SP_VERB_ZOOM_1_2:
- {
- double zcorr = prefs->getDouble("/options/zoomcorrection/value", 1.0);
- Geom::Rect const d = dt->get_display_area();
dt->zoom_absolute( d.midpoint()[Geom::X], d.midpoint()[Geom::Y], 0.5 * zcorr );
break;
- }
case SP_VERB_ZOOM_2_1:
- {
- double zcorr = prefs->getDouble("/options/zoomcorrection/value", 1.0);
- Geom::Rect const d = dt->get_display_area();
dt->zoom_absolute( d.midpoint()[Geom::X], d.midpoint()[Geom::Y], 2.0 * zcorr );
break;
- }
case SP_VERB_ZOOM_PAGE:
dt->zoom_page();
break;
@@ -2040,6 +2114,12 @@ void DialogVerb::perform(SPAction *action, void *data)
case SP_VERB_DIALOG_LAYERS:
dt->_dlg_mgr->showDialog("LayersPanel");
break;
+ case SP_VERB_DIALOG_OBJECTS:
+ dt->_dlg_mgr->showDialog("ObjectsPanel");
+ break;
+ case SP_VERB_DIALOG_TAGS:
+ dt->_dlg_mgr->showDialog("TagsPanel");
+ break;
case SP_VERB_DIALOG_LIVE_PATH_EFFECT:
dt->_dlg_mgr->showDialog("LivePathEffect");
break;
@@ -2349,7 +2429,7 @@ void LockAndHideVerb::perform(SPAction *action, void *data)
Verb *Verb::_base_verbs[] = {
// Header
new Verb(SP_VERB_INVALID, NULL, NULL, NULL, NULL, NULL),
- new Verb(SP_VERB_NONE, "None", N_("None"), N_("Does nothing"), NULL, NULL),
+ new Verb(SP_VERB_NONE, "None", NC_("Verb", "None"), N_("Does nothing"), NULL, NULL),
// File
new FileVerb(SP_VERB_FILE_NEW, "FileNew", N_("Default"), N_("Create new document from the default template"),
@@ -2371,8 +2451,7 @@ Verb *Verb::_base_verbs[] = {
INKSCAPE_ICON("document-cleanup") ),
new FileVerb(SP_VERB_FILE_IMPORT, "FileImport", N_("_Import..."),
N_("Import a bitmap or SVG image into this document"), INKSCAPE_ICON("document-import")),
- new FileVerb(SP_VERB_FILE_EXPORT, "FileExport", N_("_Export Bitmap..."),
- N_("Export this document or a selection as a bitmap image"), INKSCAPE_ICON("document-export")),
+// new FileVerb(SP_VERB_FILE_EXPORT, "FileExport", N_("_Export Bitmap..."), N_("Export this document or a selection as a bitmap image"), INKSCAPE_ICON("document-export")),
new FileVerb(SP_VERB_FILE_IMPORT_FROM_OCAL, "FileImportFromOCAL", N_("Import Clip Art..."),
N_("Import clipart from Open Clip Art Library"), INKSCAPE_ICON("document-import-ocal")),
// new FileVerb(SP_VERB_FILE_EXPORT_TO_OCAL, "FileExportToOCAL", N_("Export To Open Clip Art Library"), N_("Export this document to Open Clip Art Library"), INKSCAPE_ICON_DOCUMENT_EXPORT_OCAL),
@@ -2641,11 +2720,15 @@ Verb *Verb::_base_verbs[] = {
N_("Remove mask from selection"), NULL),
new ObjectVerb(SP_VERB_OBJECT_SET_CLIPPATH, "ObjectSetClipPath", N_("_Set"),
N_("Apply clipping path to selection (using the topmost object as clipping path)"), NULL),
+ new ObjectVerb(SP_VERB_OBJECT_CREATE_CLIP_GROUP, "ObjectCreateClipGroup", N_("Create Cl_ip Group"),
+ N_("Creates a clip group using the selected objects as a base"), NULL),
new ObjectVerb(SP_VERB_OBJECT_EDIT_CLIPPATH, "ObjectEditClipPath", N_("_Edit"),
N_("Edit clipping path"), INKSCAPE_ICON("path-clip-edit")),
new ObjectVerb(SP_VERB_OBJECT_UNSET_CLIPPATH, "ObjectUnSetClipPath", N_("_Release"),
N_("Remove clipping path from selection"), NULL),
-
+ // Tag
+ new TagVerb(SP_VERB_TAG_NEW, "TagNew", N_("_New"),
+ N_("Create new selection set"), NULL),
// Tools
new ContextVerb(SP_VERB_CONTEXT_SELECT, "ToolSelector", NC_("ContextVerb", "Select"),
N_("Select and transform objects"), INKSCAPE_ICON("tool-pointer")),
@@ -2858,6 +2941,10 @@ Verb *Verb::_base_verbs[] = {
N_("Query information about extensions"), NULL),
new DialogVerb(SP_VERB_DIALOG_LAYERS, "DialogLayers", N_("Layer_s..."),
N_("View Layers"), INKSCAPE_ICON("dialog-layers")),
+ new DialogVerb(SP_VERB_DIALOG_OBJECTS, "DialogObjects", N_("Object_s..."),
+ N_("View Objects"), INKSCAPE_ICON("dialog-layers")),
+ new DialogVerb(SP_VERB_DIALOG_TAGS, "DialogTags", N_("Selection se_ts..."),
+ N_("View Tags"), INKSCAPE_ICON("edit-select-all-layers")),
new DialogVerb(SP_VERB_DIALOG_LIVE_PATH_EFFECT, "DialogLivePathEffect", N_("Path E_ffects ..."),
N_("Manage, edit, and apply path effects"), NULL),
new DialogVerb(SP_VERB_DIALOG_FILTER_EFFECTS, "DialogFilterEffects", N_("Filter _Editor..."),
diff --git a/src/verbs.h b/src/verbs.h
index 297ef1655..06fc4fb05 100644
--- a/src/verbs.h
+++ b/src/verbs.h
@@ -13,10 +13,13 @@
* This code is GPL if done by Ted or David
*/
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
#include <cstring>
#include <string>
-#include "config.h"
-#include "require-config.h" /* HAVE_GTK_WINDOW_FULLSCREEN */
+//#include "require-config.h" /* HAVE_GTK_WINDOW_FULLSCREEN */
#include <glibmm/ustring.h>
struct SPAction;
@@ -52,7 +55,7 @@ enum {
SP_VERB_FILE_PRINT,
SP_VERB_FILE_VACUUM,
SP_VERB_FILE_IMPORT,
- SP_VERB_FILE_EXPORT,
+// SP_VERB_FILE_EXPORT,
SP_VERB_FILE_IMPORT_FROM_OCAL, /**< Import the file from Open Clip Art Library */
// SP_VERB_FILE_EXPORT_TO_OCAL, /**< Export the file to Open Clip Art Library */
SP_VERB_FILE_NEXT_DESKTOP,
@@ -175,8 +178,11 @@ enum {
SP_VERB_OBJECT_EDIT_MASK,
SP_VERB_OBJECT_UNSET_MASK,
SP_VERB_OBJECT_SET_CLIPPATH,
+ SP_VERB_OBJECT_CREATE_CLIP_GROUP,
SP_VERB_OBJECT_EDIT_CLIPPATH,
SP_VERB_OBJECT_UNSET_CLIPPATH,
+ /* Tag */
+ SP_VERB_TAG_NEW,
/* Tools */
SP_VERB_CONTEXT_SELECT,
SP_VERB_CONTEXT_NODE,
@@ -289,6 +295,8 @@ enum {
SP_VERB_DIALOG_INPUT,
SP_VERB_DIALOG_EXTENSIONEDITOR,
SP_VERB_DIALOG_LAYERS,
+ SP_VERB_DIALOG_OBJECTS,
+ SP_VERB_DIALOG_TAGS,
SP_VERB_DIALOG_LIVE_PATH_EFFECT,
SP_VERB_DIALOG_FILTER_EFFECTS,
SP_VERB_DIALOG_SVG_FONTS,
@@ -347,7 +355,7 @@ enum {
SP_VERB_LAST
};
-gchar *sp_action_get_title (const SPAction *action);
+char *sp_action_get_title (const SPAction *action);
#include <map>
#include <vector>
@@ -399,20 +407,20 @@ private:
ActionTable * _actions;
/** A unique textual ID for the verb. */
- gchar const * _id;
+ char const * _id;
/** The full name of the verb. (shown on menu entries) */
- gchar const * _name;
+ char const * _name;
/** Tooltip for the verb. */
- gchar const * _tip;
+ char const * _tip;
- gchar * _full_tip; // includes shortcut
+ char * _full_tip; // includes shortcut
unsigned int _shortcut;
/** Name of the image that represents the verb. */
- gchar const * _image;
+ char const * _image;
/**
* Unique numerical representation of the verb. In most cases
@@ -422,7 +430,7 @@ private:
unsigned int _code;
/** Name of the group the verb belongs to. */
- gchar const * _group;
+ char const * _group;
/**
* Whether this verb is set to default to sensitive or
@@ -452,28 +460,28 @@ public:
unsigned int get_code (void) { return _code; }
/** Accessor to get the internal variable. */
- gchar const * get_id (void) { return _id; }
+ char const * get_id (void) { return _id; }
/** Accessor to get the internal variable. */
- gchar const * get_name (void) { return _name; }
+ char const * get_name (void) { return _name; }
/** Accessor to get the internal variable. */
- gchar const * get_short_tip (void) { return _tip; };
+ char const * get_short_tip (void) { return _tip; };
/** Accessor to get the internal variable. */
- gchar const * get_tip (void) ;
+ char const * get_tip (void) ;
/** Accessor to get the internal variable. */
- gchar const * get_image (void) { return _image; }
+ char const * get_image (void) { return _image; }
/** Get the verbs group */
- gchar const * get_group (void) { return _group; }
+ char const * get_group (void) { return _group; }
/** Set the name after initialization. */
- gchar const * set_name (gchar const * name) { _name = name; return _name; }
+ char const * set_name (char const * name) { _name = name; return _name; }
/** Set the tooltip after initialization. */
- gchar const * set_tip (gchar const * tip) { _tip = tip; return _tip; }
+ char const * set_tip (char const * tip) { _tip = tip; return _tip; }
protected:
@@ -504,11 +512,11 @@ public:
* @param image Goes to \c _image.
*/
Verb(const unsigned int code,
- gchar const * id,
- gchar const * name,
- gchar const * tip,
- gchar const * image,
- gchar const * group) :
+ char const * id,
+ char const * name,
+ char const * tip,
+ char const * image,
+ char const * group) :
_actions(0),
_id(id),
_name(name),
@@ -523,7 +531,7 @@ public:
_verbs.insert(VerbTable::value_type(_code, this));
_verb_ids.insert(VerbIDTable::value_type(_id, this));
}
- Verb (gchar const * id, gchar const * name, gchar const * tip, gchar const * image, gchar const * group);
+ Verb (char const * id, char const * name, char const * tip, char const * image, char const * group);
virtual ~Verb (void);
SPAction * get_action(Inkscape::ActionContext const & context);
diff --git a/src/version.cpp b/src/version.cpp
index 68729c62e..abe855ee7 100644
--- a/src/version.cpp
+++ b/src/version.cpp
@@ -12,14 +12,14 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
+#include <glib.h>
#include <sstream>
-
#include "version.h"
-gboolean sp_version_from_string(const gchar *string, Inkscape::Version *version)
+bool sp_version_from_string(const char *string, Inkscape::Version *version)
{
if (!string) {
- return FALSE;
+ return false;
}
try
@@ -40,27 +40,27 @@ gboolean sp_version_from_string(const gchar *string, Inkscape::Version *version)
}
}
-gchar *sp_version_to_string(Inkscape::Version version)
+char *sp_version_to_string(Inkscape::Version version)
{
return g_strdup_printf("%u.%u", version._major, version._minor);
}
-gboolean sp_version_inside_range(Inkscape::Version version,
- unsigned major_min, unsigned minor_min,
- unsigned major_max, unsigned minor_max)
+bool sp_version_inside_range(Inkscape::Version version,
+ unsigned major_min, unsigned minor_min,
+ unsigned major_max, unsigned minor_max)
{
if ( version._major < major_min || version._major > major_max ) {
- return FALSE;
+ return false;
} else if ( version._major == major_min &&
version._minor <= minor_min )
{
- return FALSE;
+ return false;
} else if ( version._major == major_max &&
version._minor >= minor_max )
{
- return FALSE;
+ return false;
} else {
- return TRUE;
+ return true;
}
}
diff --git a/src/version.h b/src/version.h
index 26fbc11a3..e17688b6d 100644
--- a/src/version.h
+++ b/src/version.h
@@ -11,8 +11,6 @@
#ifndef SEEN_INKSCAPE_VERSION_H
#define SEEN_INKSCAPE_VERSION_H
-#include <glib.h>
-
#define SVG_VERSION "1.1"
namespace Inkscape {
@@ -49,13 +47,13 @@ public:
}
-gboolean sp_version_from_string(const gchar *string, Inkscape::Version *version);
+bool sp_version_from_string(const char *string, Inkscape::Version *version);
-gchar *sp_version_to_string(Inkscape::Version version);
+char *sp_version_to_string(Inkscape::Version version);
-gboolean sp_version_inside_range(Inkscape::Version version,
- unsigned major_min, unsigned minor_min,
- unsigned major_max, unsigned minor_max);
+bool sp_version_inside_range(Inkscape::Version version,
+ unsigned major_min, unsigned minor_min,
+ unsigned major_max, unsigned minor_max);
#endif // SEEN_INKSCAPE_VERSION_H
/*
diff --git a/src/viewbox.cpp b/src/viewbox.cpp
index f59909abc..662b05686 100644
--- a/src/viewbox.cpp
+++ b/src/viewbox.cpp
@@ -164,16 +164,17 @@ void SPViewBox::set_preserveAspectRatio(const gchar* value) {
void SPViewBox::apply_viewbox(const Geom::Rect& in) {
/* Determine actual viewbox in viewport coordinates */
- double x = 0.0;
- double y = 0.0;
- double width = in.width();
- double height = in.height();
+ /* These are floats since SVGLength is a float: See bug 1374614 */
+ float x = 0.0;
+ float y = 0.0;
+ float width = in.width();
+ float height = in.height();
// std::cout << " width: " << width << " height: " << height << std::endl;
if (this->aspect_align != SP_ASPECT_NONE) {
/* Things are getting interesting */
- double scalex = in.width() / this->viewBox.width();
- double scaley = in.height() / this->viewBox.height();
+ double scalex = in.width() / ((float) this->viewBox.width());
+ double scaley = in.height() / ((float) this->viewBox.height());
double scale = (this->aspect_clip == SP_ASPECT_MEET) ? MIN (scalex, scaley) : MAX (scalex, scaley);
width = this->viewBox.width() * scale;
height = this->viewBox.height() * scale;
@@ -217,12 +218,12 @@ void SPViewBox::apply_viewbox(const Geom::Rect& in) {
/* Viewbox transform from scale and position */
Geom::Affine q;
- q[0] = width / this->viewBox.width();
+ q[0] = width / ((float) this->viewBox.width());
q[1] = 0.0;
q[2] = 0.0;
- q[3] = height / this->viewBox.height();
- q[4] = x - q[0] * this->viewBox.left();
- q[5] = y - q[3] * this->viewBox.top();
+ q[3] = height / ((float) this->viewBox.height());
+ q[4] = x - q[0] * ((float) this->viewBox.left());
+ q[5] = y - q[3] * ((float) this->viewBox.top());
// std::cout << " q\n" << q << std::endl;
diff --git a/src/widgets/CMakeLists.txt b/src/widgets/CMakeLists.txt
index fe4433153..072b905a2 100644
--- a/src/widgets/CMakeLists.txt
+++ b/src/widgets/CMakeLists.txt
@@ -24,6 +24,9 @@ set(widgets_SRC
desktop-widget.cpp
eek-preview.cpp
ege-paint-def.cpp
+ ege-adjustment-action.cpp
+ ege-output-action.cpp
+ ege-select-one-action.cpp
fill-style.cpp
font-selector.cpp
gradient-image.cpp
@@ -31,6 +34,8 @@ set(widgets_SRC
gradient-toolbar.cpp
gradient-vector.cpp
icon.cpp
+ ink-action.cpp
+ ink-comboboxentry-action.cpp
paint-selector.cpp
ruler.cpp
select-toolbar.cpp
@@ -80,6 +85,9 @@ set(widgets_SRC
desktop-widget.h
eek-preview.h
ege-paint-def.h
+ ege-adjustment-action.h
+ ege-output-action.h
+ ege-select-one-action.h
fill-n-stroke-factory.h
fill-style.h
font-selector.h
@@ -88,6 +96,8 @@ set(widgets_SRC
gradient-toolbar.h
gradient-vector.h
icon.h
+ ink-action.h
+ ink-comboboxentry-action.h
paint-selector.h
ruler.h
select-toolbar.h
diff --git a/src/widgets/Makefile_insert b/src/widgets/Makefile_insert
index 97713cbee..dc4c12967 100644
--- a/src/widgets/Makefile_insert
+++ b/src/widgets/Makefile_insert
@@ -19,8 +19,14 @@ ink_common_sources += \
widgets/dropper-toolbar.h \
widgets/eek-preview.cpp \
widgets/eek-preview.h \
+ widgets/ege-adjustment-action.cpp \
+ widgets/ege-adjustment-action.h \
widgets/ege-paint-def.cpp \
widgets/ege-paint-def.h \
+ widgets/ege-output-action.cpp \
+ widgets/ege-output-action.h \
+ widgets/ege-select-one-action.cpp \
+ widgets/ege-select-one-action.h \
widgets/eraser-toolbar.cpp \
widgets/eraser-toolbar.h \
widgets/fill-style.cpp \
@@ -38,6 +44,10 @@ ink_common_sources += \
widgets/gradient-vector.h \
widgets/icon.cpp \
widgets/icon.h \
+ widgets/ink-action.cpp \
+ widgets/ink-action.h \
+ widgets/ink-comboboxentry-action.cpp \
+ widgets/ink-comboboxentry-action.h \
widgets/lpe-toolbar.cpp \
widgets/lpe-toolbar.h \
widgets/measure-toolbar.cpp \
diff --git a/src/widgets/arc-toolbar.cpp b/src/widgets/arc-toolbar.cpp
index ca6810c81..ca582924b 100644
--- a/src/widgets/arc-toolbar.cpp
+++ b/src/widgets/arc-toolbar.cpp
@@ -34,10 +34,10 @@
#include "desktop-handles.h"
#include "desktop.h"
#include "document-undo.h"
-#include "ege-adjustment-action.h"
-#include "ege-output-action.h"
-#include "ege-select-one-action.h"
-#include "ink-action.h"
+#include "widgets/ege-adjustment-action.h"
+#include "widgets/ege-output-action.h"
+#include "widgets/ege-select-one-action.h"
+#include "widgets/ink-action.h"
#include "mod360.h"
#include "preferences.h"
#include "selection.h"
@@ -45,6 +45,7 @@
#include "toolbox.h"
#include "ui/icon-names.h"
#include "ui/uxmanager.h"
+#include "ui/tools/arc-tool.h"
#include "verbs.h"
#include "widgets/spinbutton-events.h"
#include "xml/node-event-vector.h"
@@ -304,6 +305,7 @@ static void sp_arc_toolbox_selection_changed(Inkscape::Selection *selection, GOb
}
}
+static void arc_toolbox_check_ec(SPDesktop* dt, Inkscape::UI::Tools::ToolBase* ec, GObject* holder);
void sp_arc_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder)
{
@@ -402,14 +404,22 @@ void sp_arc_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObjec
sp_arctb_sensitivize( holder, gtk_adjustment_get_value(adj1), gtk_adjustment_get_value(adj2) );
}
-
- sigc::connection *connection = new sigc::connection(
- sp_desktop_selection(desktop)->connectChanged(sigc::bind(sigc::ptr_fun(sp_arc_toolbox_selection_changed), G_OBJECT(holder)))
- );
- g_signal_connect( holder, "destroy", G_CALLBACK(delete_connection), connection );
+ desktop->connectEventContextChanged(sigc::bind(sigc::ptr_fun(arc_toolbox_check_ec), holder));
g_signal_connect( holder, "destroy", G_CALLBACK(purge_repr_listener), holder );
}
+static void arc_toolbox_check_ec(SPDesktop* desktop, Inkscape::UI::Tools::ToolBase* ec, GObject* holder)
+{
+ static sigc::connection changed;
+
+ if (SP_IS_ARC_CONTEXT(ec)) {
+ changed = sp_desktop_selection(desktop)->connectChanged(sigc::bind(sigc::ptr_fun(sp_arc_toolbox_selection_changed), holder));
+ sp_arc_toolbox_selection_changed(sp_desktop_selection(desktop), holder);
+ } else {
+ if (changed)
+ changed.disconnect();
+ }
+}
/*
Local Variables:
diff --git a/src/widgets/box3d-toolbar.cpp b/src/widgets/box3d-toolbar.cpp
index 6d6b86c4d..02d102a11 100644
--- a/src/widgets/box3d-toolbar.cpp
+++ b/src/widgets/box3d-toolbar.cpp
@@ -36,13 +36,14 @@
#include "desktop.h"
#include "document-undo.h"
#include "document.h"
-#include "ege-adjustment-action.h"
-#include "ink-action.h"
+#include "widgets/ege-adjustment-action.h"
+#include "widgets/ink-action.h"
#include "inkscape.h"
#include "persp3d.h"
#include "selection.h"
#include "toolbox.h"
#include "ui/icon-names.h"
+#include "ui/tools/box3d-tool.h"
#include "ui/uxmanager.h"
#include "verbs.h"
#include "xml/node-event-vector.h"
@@ -182,9 +183,9 @@ static void box3d_toolbox_selection_changed(Inkscape::Selection *selection, GObj
purge_repr_listener(tbl, tbl);
SPItem *item = selection->singleItem();
- if (item && SP_IS_BOX3D(item)) {
+ SPBox3D *box = dynamic_cast<SPBox3D *>(item);
+ if (box) {
// FIXME: Also deal with multiple selected boxes
- SPBox3D *box = SP_BOX3D(item);
Persp3D *persp = box3d_get_perspective(box);
persp_repr = persp->getRepr();
if (persp_repr) {
@@ -280,6 +281,8 @@ static void box3d_vp_z_state_changed( GtkToggleAction *act, GtkAction *box3d_ang
box3d_vp_state_changed(act, box3d_angle, Proj::Z);
}
+static void box3d_toolbox_check_ec(SPDesktop* dt, Inkscape::UI::Tools::ToolBase* ec, GObject* holder);
+
void box3d_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder)
{
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
@@ -409,13 +412,22 @@ void box3d_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject
gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs->getBool("/tools/shapes/3dbox/vp_z_state", true) );
}
- sigc::connection *connection = new sigc::connection(
- sp_desktop_selection(desktop)->connectChanged(sigc::bind(sigc::ptr_fun(box3d_toolbox_selection_changed), G_OBJECT(holder)))
- );
- g_signal_connect(holder, "destroy", G_CALLBACK(delete_connection), connection);
+ desktop->connectEventContextChanged(sigc::bind(sigc::ptr_fun(box3d_toolbox_check_ec), holder));
g_signal_connect(holder, "destroy", G_CALLBACK(purge_repr_listener), holder);
}
+static void box3d_toolbox_check_ec(SPDesktop* desktop, Inkscape::UI::Tools::ToolBase* ec, GObject* holder)
+{
+ static sigc::connection changed;
+ if (SP_IS_BOX3D_CONTEXT(ec)) {
+ changed = sp_desktop_selection(desktop)->connectChanged(sigc::bind(sigc::ptr_fun(box3d_toolbox_selection_changed), holder));
+ box3d_toolbox_selection_changed(sp_desktop_selection(desktop), holder);
+ } else {
+ if (changed)
+ changed.disconnect();
+ }
+}
+
/*
Local Variables:
mode:c++
diff --git a/src/widgets/button.cpp b/src/widgets/button.cpp
index a1bd9b792..1776e28c4 100644
--- a/src/widgets/button.cpp
+++ b/src/widgets/button.cpp
@@ -1,6 +1,4 @@
-#define __SP_BUTTON_C__
-
-/*
+/**
* Generic button widget
*
* Authors:
@@ -13,282 +11,257 @@
* This code is in public domain
*/
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
+#include <glibmm.h>
#include "icon.h"
-#include "shortcuts.h"
-#include "interface.h"
+
+#include "button.h"
#include "helper/action-context.h"
+#include "ui/interface.h"
+#include "shortcuts.h"
+#include "helper/action.h"
#include <gdk/gdkkeysyms.h>
-#include "button.h"
-
static void sp_button_dispose(GObject *object);
-#if GTK_CHECK_VERSION(3,0,0)
-static void sp_button_get_preferred_width(GtkWidget *widget,
- gint *minimal_width,
- gint *natural_width);
+#if GTK_CHECK_VERSION(3, 0, 0)
+static void sp_button_get_preferred_width(GtkWidget *widget, gint *minimal_width, gint *natural_width);
-static void sp_button_get_preferred_height(GtkWidget *widget,
- gint *minimal_height,
- gint *natural_height);
+static void sp_button_get_preferred_height(GtkWidget *widget, gint *minimal_height, gint *natural_height);
#else
-static void sp_button_size_request (GtkWidget *widget, GtkRequisition *requisition);
+static void sp_button_size_request(GtkWidget *widget, GtkRequisition *requisition);
#endif
-static void sp_button_clicked (GtkButton *button);
-static void sp_button_perform_action (SPButton *button, gpointer data);
-static gint sp_button_process_event (SPButton *button, GdkEvent *event);
+static void sp_button_clicked(GtkButton *button);
+static void sp_button_perform_action(SPButton *button, gpointer data);
+static gint sp_button_process_event(SPButton *button, GdkEvent *event);
-static void sp_button_set_action (SPButton *button, SPAction *action);
-static void sp_button_set_doubleclick_action (SPButton *button, SPAction *action);
-static void sp_button_action_set_active (SPButton *button, bool active);
-static void sp_button_set_composed_tooltip (GtkWidget *widget, SPAction *action);
+static void sp_button_set_action(SPButton *button, SPAction *action);
+static void sp_button_set_doubleclick_action(SPButton *button, SPAction *action);
+static void sp_button_action_set_active(SPButton *button, bool active);
+static void sp_button_set_composed_tooltip(GtkWidget *widget, SPAction *action);
G_DEFINE_TYPE(SPButton, sp_button, GTK_TYPE_TOGGLE_BUTTON);
-static void
-sp_button_class_init (SPButtonClass *klass)
+static void sp_button_class_init(SPButtonClass *klass)
{
- GObjectClass *object_class=G_OBJECT_CLASS(klass);
- GtkWidgetClass *widget_class=GTK_WIDGET_CLASS(klass);
- GtkButtonClass *button_class=GTK_BUTTON_CLASS(klass);
-
- object_class->dispose = sp_button_dispose;
-#if GTK_CHECK_VERSION(3,0,0)
- widget_class->get_preferred_width = sp_button_get_preferred_width;
- widget_class->get_preferred_height = sp_button_get_preferred_height;
+ GObjectClass *object_class = G_OBJECT_CLASS(klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass);
+ GtkButtonClass *button_class = GTK_BUTTON_CLASS(klass);
+
+ object_class->dispose = sp_button_dispose;
+#if GTK_CHECK_VERSION(3, 0, 0)
+ widget_class->get_preferred_width = sp_button_get_preferred_width;
+ widget_class->get_preferred_height = sp_button_get_preferred_height;
#else
- widget_class->size_request = sp_button_size_request;
+ widget_class->size_request = sp_button_size_request;
#endif
- button_class->clicked = sp_button_clicked;
+ button_class->clicked = sp_button_clicked;
}
-static void
-sp_button_init (SPButton *button)
+static void sp_button_init(SPButton *button)
{
- button->action = NULL;
- button->doubleclick_action = NULL;
- new (&button->c_set_active) sigc::connection();
- new (&button->c_set_sensitive) sigc::connection();
+ button->action = NULL;
+ button->doubleclick_action = NULL;
+ new (&button->c_set_active) sigc::connection();
+ new (&button->c_set_sensitive) sigc::connection();
- gtk_container_set_border_width (GTK_CONTAINER (button), 0);
+ gtk_container_set_border_width(GTK_CONTAINER(button), 0);
- gtk_widget_set_can_focus (GTK_WIDGET (button), FALSE);
- gtk_widget_set_can_default (GTK_WIDGET (button), FALSE);
+ gtk_widget_set_can_focus(GTK_WIDGET(button), FALSE);
+ gtk_widget_set_can_default(GTK_WIDGET(button), FALSE);
- g_signal_connect_after (G_OBJECT (button), "clicked", G_CALLBACK (sp_button_perform_action), NULL);
- g_signal_connect_after (G_OBJECT (button), "event", G_CALLBACK (sp_button_process_event), NULL);
+ g_signal_connect_after(G_OBJECT(button), "clicked", G_CALLBACK(sp_button_perform_action), NULL);
+ g_signal_connect_after(G_OBJECT(button), "event", G_CALLBACK(sp_button_process_event), NULL);
}
static void sp_button_dispose(GObject *object)
{
- SPButton *button = SP_BUTTON (object);
+ SPButton *button = SP_BUTTON(object);
- if (button->action) {
- sp_button_set_action (button, NULL);
- }
- if (button->doubleclick_action) {
- sp_button_set_doubleclick_action (button, NULL);
- }
+ if (button->action) {
+ sp_button_set_action(button, NULL);
+ }
+ if (button->doubleclick_action) {
+ sp_button_set_doubleclick_action(button, NULL);
+ }
- button->c_set_active.~connection();
- button->c_set_sensitive.~connection();
+ button->c_set_active.~connection();
+ button->c_set_sensitive.~connection();
- (G_OBJECT_CLASS(sp_button_parent_class))->dispose(object);
+ (G_OBJECT_CLASS(sp_button_parent_class))->dispose(object);
}
-
-
-#if GTK_CHECK_VERSION(3,0,0)
+#if GTK_CHECK_VERSION(3, 0, 0)
static void sp_button_get_preferred_width(GtkWidget *widget, gint *minimal_width, gint *natural_width)
{
- GtkWidget *child = gtk_bin_get_child(GTK_BIN (widget));
- GtkStyle *style = gtk_widget_get_style(widget);
-
- if (child) {
- gtk_widget_get_preferred_width(GTK_WIDGET(child), minimal_width, natural_width);
- } else {
- *minimal_width = 0;
- *natural_width = 0;
- }
-
- *minimal_width += 2 + 2 * MAX(2, style->xthickness);
- *natural_width += 2 + 2 * MAX(2, style->xthickness);
+ GtkWidget *child = gtk_bin_get_child(GTK_BIN(widget));
+ GtkStyle *style = gtk_widget_get_style(widget);
+
+ if (child) {
+ gtk_widget_get_preferred_width(GTK_WIDGET(child), minimal_width, natural_width);
+ } else {
+ *minimal_width = 0;
+ *natural_width = 0;
+ }
+
+ *minimal_width += 2 + 2 * MAX(2, style->xthickness);
+ *natural_width += 2 + 2 * MAX(2, style->xthickness);
}
static void sp_button_get_preferred_height(GtkWidget *widget, gint *minimal_height, gint *natural_height)
{
- GtkWidget *child = gtk_bin_get_child(GTK_BIN (widget));
- GtkStyle *style = gtk_widget_get_style(widget);
-
- if (child) {
- gtk_widget_get_preferred_height(GTK_WIDGET(child), minimal_height, natural_height);
- } else {
- *minimal_height = 0;
- *natural_height = 0;
- }
+ GtkWidget *child = gtk_bin_get_child(GTK_BIN(widget));
+ GtkStyle *style = gtk_widget_get_style(widget);
- *minimal_height += 2 + 2 * MAX(2, style->ythickness);
- *natural_height += 2 + 2 * MAX(2, style->ythickness);
+ if (child) {
+ gtk_widget_get_preferred_height(GTK_WIDGET(child), minimal_height, natural_height);
+ } else {
+ *minimal_height = 0;
+ *natural_height = 0;
+ }
+ *minimal_height += 2 + 2 * MAX(2, style->ythickness);
+ *natural_height += 2 + 2 * MAX(2, style->ythickness);
}
#else
static void sp_button_size_request(GtkWidget *widget, GtkRequisition *requisition)
{
- GtkWidget *child = gtk_bin_get_child (GTK_BIN (widget));
- GtkStyle *style = gtk_widget_get_style (widget);
-
- if (child) {
- gtk_widget_size_request (GTK_WIDGET (child), requisition);
- } else {
- requisition->width = 0;
- requisition->height = 0;
- }
-
- requisition->width += 2 + 2 * MAX (2, style->xthickness);
- requisition->height += 2 + 2 * MAX (2, style->ythickness);
+ GtkWidget *child = gtk_bin_get_child(GTK_BIN(widget));
+ GtkStyle *style = gtk_widget_get_style(widget);
+
+ if (child) {
+ gtk_widget_size_request(GTK_WIDGET(child), requisition);
+ } else {
+ requisition->width = 0;
+ requisition->height = 0;
+ }
+
+ requisition->width += 2 + 2 * MAX(2, style->xthickness);
+ requisition->height += 2 + 2 * MAX(2, style->ythickness);
}
#endif
-static void
-sp_button_clicked (GtkButton *button)
+static void sp_button_clicked(GtkButton *button)
{
- SPButton *sp_button=SP_BUTTON (button);
+ SPButton *sp_button = SP_BUTTON(button);
- if (sp_button->type == SP_BUTTON_TYPE_TOGGLE) {
- (GTK_BUTTON_CLASS(sp_button_parent_class))->clicked (button);
- }
+ if (sp_button->type == SP_BUTTON_TYPE_TOGGLE) {
+ (GTK_BUTTON_CLASS(sp_button_parent_class))->clicked(button);
+ }
}
-static gint
-sp_button_process_event (SPButton *button, GdkEvent *event)
+static gint sp_button_process_event(SPButton *button, GdkEvent *event)
{
- switch (event->type) {
- case GDK_2BUTTON_PRESS:
- if (button->doubleclick_action) {
- sp_action_perform (button->doubleclick_action, NULL);
- }
- return TRUE;
- break;
- default:
- break;
- }
-
- return FALSE;
+ switch (event->type) {
+ case GDK_2BUTTON_PRESS:
+ if (button->doubleclick_action) {
+ sp_action_perform(button->doubleclick_action, NULL);
+ }
+ return TRUE;
+ break;
+ default:
+ break;
+ }
+
+ return FALSE;
}
-static void
-sp_button_perform_action (SPButton *button, gpointer /*data*/)
+static void sp_button_perform_action(SPButton *button, gpointer /*data*/)
{
- if (button->action) {
- sp_action_perform (button->action, NULL);
- }
+ if (button->action) {
+ sp_action_perform(button->action, NULL);
+ }
}
-
-GtkWidget *
-sp_button_new( Inkscape::IconSize size, SPButtonType type, SPAction *action, SPAction *doubleclick_action )
+GtkWidget *sp_button_new(Inkscape::IconSize size, SPButtonType type, SPAction *action, SPAction *doubleclick_action)
{
- SPButton *button = SP_BUTTON(g_object_new(SP_TYPE_BUTTON, NULL));
+ SPButton *button = SP_BUTTON(g_object_new(SP_TYPE_BUTTON, NULL));
- button->type = type;
- button->lsize = CLAMP( size, Inkscape::ICON_SIZE_MENU, Inkscape::ICON_SIZE_DECORATION );
+ button->type = type;
+ button->lsize = CLAMP(size, Inkscape::ICON_SIZE_MENU, Inkscape::ICON_SIZE_DECORATION);
- sp_button_set_action (button, action);
- if (doubleclick_action)
- sp_button_set_doubleclick_action (button, doubleclick_action);
+ sp_button_set_action(button, action);
+ if (doubleclick_action)
+ sp_button_set_doubleclick_action(button, doubleclick_action);
- // The Inkscape style is no-relief buttons
- gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
+ // The Inkscape style is no-relief buttons
+ gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE);
- return GTK_WIDGET(button);
+ return GTK_WIDGET(button);
}
-void
-sp_button_toggle_set_down (SPButton *button, gboolean down)
+void sp_button_toggle_set_down(SPButton *button, gboolean down)
{
- g_return_if_fail (button->type == SP_BUTTON_TYPE_TOGGLE);
- g_signal_handlers_block_by_func (G_OBJECT (button), (gpointer)G_CALLBACK (sp_button_perform_action), NULL);
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), (unsigned int)down);
- g_signal_handlers_unblock_by_func (G_OBJECT (button), (gpointer)G_CALLBACK (sp_button_perform_action), NULL);
+ g_return_if_fail(button->type == SP_BUTTON_TYPE_TOGGLE);
+ g_signal_handlers_block_by_func(G_OBJECT(button), (gpointer)G_CALLBACK(sp_button_perform_action), NULL);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), (unsigned int)down);
+ g_signal_handlers_unblock_by_func(G_OBJECT(button), (gpointer)G_CALLBACK(sp_button_perform_action), NULL);
}
-static void
-sp_button_set_doubleclick_action (SPButton *button, SPAction *action)
+static void sp_button_set_doubleclick_action(SPButton *button, SPAction *action)
{
- if (button->doubleclick_action) {
- g_object_unref (button->doubleclick_action);
- }
- button->doubleclick_action = action;
- if (action) {
- g_object_ref(action);
- }
-
+ if (button->doubleclick_action) {
+ g_object_unref(button->doubleclick_action);
+ }
+ button->doubleclick_action = action;
+ if (action) {
+ g_object_ref(action);
+ }
}
-static void
-sp_button_set_action (SPButton *button, SPAction *action)
+static void sp_button_set_action(SPButton *button, SPAction *action)
{
- GtkWidget *child;
-
- if (button->action) {
- button->c_set_active.disconnect();
- button->c_set_sensitive.disconnect();
- child = gtk_bin_get_child (GTK_BIN (button));
- if (child) {
- gtk_container_remove (GTK_CONTAINER (button), child);
- }
- g_object_unref(button->action);
- }
- button->action = action;
- if (action) {
- g_object_ref(action);
- button->c_set_active = action->signal_set_active.connect(
- sigc::bind<0>(
- sigc::ptr_fun(&sp_button_action_set_active),
- SP_BUTTON(button)));
- button->c_set_sensitive = action->signal_set_sensitive.connect(
- sigc::bind<0>(
- sigc::ptr_fun(&gtk_widget_set_sensitive),
- GTK_WIDGET(button)));
- if (action->image) {
- child = sp_icon_new (button->lsize, action->image);
- gtk_widget_show (child);
- gtk_container_add (GTK_CONTAINER (button), child);
- }
- }
-
- sp_button_set_composed_tooltip(GTK_WIDGET(button), action);
+ GtkWidget *child;
+
+ if (button->action) {
+ button->c_set_active.disconnect();
+ button->c_set_sensitive.disconnect();
+ child = gtk_bin_get_child(GTK_BIN(button));
+ if (child) {
+ gtk_container_remove(GTK_CONTAINER(button), child);
+ }
+ g_object_unref(button->action);
+ }
+ button->action = action;
+ if (action) {
+ g_object_ref(action);
+ button->c_set_active = action->signal_set_active.connect(
+ sigc::bind<0>(sigc::ptr_fun(&sp_button_action_set_active), SP_BUTTON(button)));
+ button->c_set_sensitive = action->signal_set_sensitive.connect(
+ sigc::bind<0>(sigc::ptr_fun(&gtk_widget_set_sensitive), GTK_WIDGET(button)));
+ if (action->image) {
+ child = sp_icon_new(button->lsize, action->image);
+ gtk_widget_show(child);
+ gtk_container_add(GTK_CONTAINER(button), child);
+ }
+ }
+
+ sp_button_set_composed_tooltip(GTK_WIDGET(button), action);
}
-static void
-sp_button_action_set_active (SPButton *button, bool active)
+static void sp_button_action_set_active(SPButton *button, bool active)
{
- if (button->type != SP_BUTTON_TYPE_TOGGLE) {
- return;
- }
-
- /* temporarily lobotomized until SPActions are per-view */
- if (0 && !active != !SP_BUTTON_IS_DOWN (button)) {
- sp_button_toggle_set_down (button, active);
- }
+ if (button->type != SP_BUTTON_TYPE_TOGGLE) {
+ return;
+ }
+
+ /* temporarily lobotomized until SPActions are per-view */
+ if (0 && !active != !SP_BUTTON_IS_DOWN(button)) {
+ sp_button_toggle_set_down(button, active);
+ }
}
static void sp_button_set_composed_tooltip(GtkWidget *widget, SPAction *action)
{
if (action) {
- unsigned int shortcut = sp_shortcut_get_primary (action->verb);
+ unsigned int shortcut = sp_shortcut_get_primary(action->verb);
if (shortcut != GDK_KEY_VoidSymbol) {
// there's both action and shortcut
gchar *key = sp_shortcut_get_label(shortcut);
- gchar *tip = g_strdup_printf ("%s (%s)", action->tip, key);
+ gchar *tip = g_strdup_printf("%s (%s)", action->tip, key);
gtk_widget_set_tooltip_text(widget, tip);
g_free(tip);
g_free(key);
@@ -302,18 +275,14 @@ static void sp_button_set_composed_tooltip(GtkWidget *widget, SPAction *action)
}
}
-GtkWidget *
-sp_button_new_from_data( Inkscape::IconSize size,
- SPButtonType type,
- Inkscape::UI::View::View *view,
- const gchar *name,
- const gchar *tip )
+GtkWidget *sp_button_new_from_data(Inkscape::IconSize size, SPButtonType type, Inkscape::UI::View::View *view,
+ const gchar *name, const gchar *tip)
{
- GtkWidget *button;
- SPAction *action=sp_action_new(Inkscape::ActionContext(view), name, name, tip, name, 0);
- button = sp_button_new (size, type, action, NULL);
- g_object_unref(action);
- return button;
+ GtkWidget *button;
+ SPAction *action = sp_action_new(Inkscape::ActionContext(view), name, name, tip, name, 0);
+ button = sp_button_new(size, type, action, NULL);
+ g_object_unref(action);
+ return button;
}
/*
@@ -325,4 +294,4 @@ sp_button_new_from_data( Inkscape::IconSize size,
fill-column:99
End:
*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8 :
diff --git a/src/widgets/button.h b/src/widgets/button.h
index 41863357d..2bceb5e97 100644
--- a/src/widgets/button.h
+++ b/src/widgets/button.h
@@ -1,7 +1,7 @@
-#ifndef __SP_BUTTON_H__
-#define __SP_BUTTON_H__
+#ifndef SEEN_SP_BUTTON_H
+#define SEEN_SP_BUTTON_H
-/*
+/**
* Generic button widget
*
* Author:
@@ -17,10 +17,18 @@
#define SP_IS_BUTTON(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), SP_TYPE_BUTTON))
#include <gtk/gtk.h>
-#include <sigc++/sigc++.h>
-#include "helper/action.h"
+#include <sigc++/connection.h>
#include "icon-size.h"
+struct SPAction;
+
+namespace Inkscape {
+namespace UI {
+namespace View {
+class View;
+}
+}
+}
typedef enum {
SP_BUTTON_TYPE_NORMAL,
@@ -61,6 +69,15 @@ GtkWidget *sp_button_new_from_data (Inkscape::IconSize size,
const gchar *name,
const gchar *tip);
+#endif // !SEEN_SP_BUTTON_H
-
-#endif
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8 :
diff --git a/src/widgets/calligraphy-toolbar.cpp b/src/widgets/calligraphy-toolbar.cpp
index 9c0393cd9..4ae6427ad 100644
--- a/src/widgets/calligraphy-toolbar.cpp
+++ b/src/widgets/calligraphy-toolbar.cpp
@@ -34,9 +34,9 @@
#include "desktop.h"
#include "document-undo.h"
-#include "ege-adjustment-action.h"
-#include "ege-select-one-action.h"
-#include "ink-action.h"
+#include "widgets/ege-adjustment-action.h"
+#include "widgets/ege-select-one-action.h"
+#include "widgets/ink-action.h"
#include "preferences.h"
#include "toolbox.h"
#include "ui/icon-names.h"
diff --git a/src/widgets/connector-toolbar.cpp b/src/widgets/connector-toolbar.cpp
index 9bbc1bbb4..6ce926dc1 100644
--- a/src/widgets/connector-toolbar.cpp
+++ b/src/widgets/connector-toolbar.cpp
@@ -35,10 +35,10 @@
#include "desktop-handles.h"
#include "desktop.h"
#include "document-undo.h"
-#include "ege-adjustment-action.h"
+#include "widgets/ege-adjustment-action.h"
#include "enums.h"
#include "graphlayout.h"
-#include "ink-action.h"
+#include "widgets/ink-action.h"
#include "inkscape.h"
#include "preferences.h"
#include "selection.h"
diff --git a/src/widgets/dash-selector.cpp b/src/widgets/dash-selector.cpp
index fce7a9d9f..479895022 100644
--- a/src/widgets/dash-selector.cpp
+++ b/src/widgets/dash-selector.cpp
@@ -25,7 +25,7 @@
#include <2geom/coord.h>
#include "style.h"
-#include "dialogs/dialog-events.h"
+#include "ui/dialog-events.h"
#include "preferences.h"
#include "ui/widget/spinbutton.h"
#include "display/cairo-utils.h"
diff --git a/src/widgets/desktop-widget.cpp b/src/widgets/desktop-widget.cpp
index 583dbec85..9c8dac7dc 100644
--- a/src/widgets/desktop-widget.cpp
+++ b/src/widgets/desktop-widget.cpp
@@ -38,7 +38,7 @@
#include "display/canvas-arena.h"
#include "document.h"
#include "ege-color-prof-tracker.h"
-#include "ege-select-one-action.h"
+#include "widgets/ege-select-one-action.h"
#include <extension/db.h>
#include "file.h"
#include "helper/action.h"
@@ -46,7 +46,7 @@
#include "util/units.h"
#include "ui/widget/unit-tracker.h"
#include "inkscape-private.h"
-#include "interface.h"
+#include "ui/interface.h"
#include "macros.h"
#include "preferences.h"
#include "sp-image.h"
@@ -358,7 +358,7 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw )
{
using Inkscape::UI::Dialogs::SwatchesPanel;
- dtw->panels = new SwatchesPanel("/embedded/swatches");
+ dtw->panels = new SwatchesPanel("/embedded/swatches" /*false*/);
dtw->panels->setOrientation(SP_ANCHOR_SOUTH);
#if GTK_CHECK_VERSION(3,0,0)
@@ -1246,6 +1246,9 @@ SPDesktopWidget::shutdown()
*/
void
SPDesktopWidget::requestCanvasUpdate() {
+ // ^^ also this->desktop != 0
+ g_return_if_fail(this->desktop != NULL);
+ g_return_if_fail(this->desktop->main != NULL);
gtk_widget_queue_draw (GTK_WIDGET (SP_CANVAS_ITEM (this->desktop->main)->canvas));
}
diff --git a/src/widgets/dropper-toolbar.cpp b/src/widgets/dropper-toolbar.cpp
index 478d0c1a4..45ed9ead4 100644
--- a/src/widgets/dropper-toolbar.cpp
+++ b/src/widgets/dropper-toolbar.cpp
@@ -32,8 +32,8 @@
#include "dropper-toolbar.h"
#include "document-undo.h"
-#include "ege-output-action.h"
-#include "ink-action.h"
+#include "widgets/ege-output-action.h"
+#include "widgets/ink-action.h"
#include "preferences.h"
#include "widgets/spinbutton-events.h"
diff --git a/src/widgets/eek-preview.h b/src/widgets/eek-preview.h
index e4c724cc5..883ce713e 100644
--- a/src/widgets/eek-preview.h
+++ b/src/widgets/eek-preview.h
@@ -37,7 +37,6 @@
#ifndef SEEN_EEK_PREVIEW_H
#define SEEN_EEK_PREVIEW_H
-#include <gdk/gdk.h>
#include <gtk/gtk.h>
/**
diff --git a/src/ege-adjustment-action.cpp b/src/widgets/ege-adjustment-action.cpp
index 9491468dc..d89a6e3f1 100644
--- a/src/ege-adjustment-action.cpp
+++ b/src/widgets/ege-adjustment-action.cpp
@@ -46,7 +46,7 @@
#include <gdk/gdkkeysyms.h>
#include "icon-size.h"
-#include "ege-adjustment-action.h"
+#include "widgets/ege-adjustment-action.h"
#include "ui/widget/gimpspinscale.h"
#include "ui/icon-names.h"
diff --git a/src/ege-adjustment-action.h b/src/widgets/ege-adjustment-action.h
index 590035eb3..8cfaa3e52 100644
--- a/src/ege-adjustment-action.h
+++ b/src/widgets/ege-adjustment-action.h
@@ -45,9 +45,7 @@
/* Note: this file should be kept compilable as both .cpp and .c */
-#include <glib.h>
#include <gtk/gtk.h>
-#include <glib-object.h>
G_BEGIN_DECLS
diff --git a/src/ege-output-action.cpp b/src/widgets/ege-output-action.cpp
index 9a7d7e318..5dece8e91 100644
--- a/src/ege-output-action.cpp
+++ b/src/widgets/ege-output-action.cpp
@@ -43,7 +43,7 @@
#include <gtk/gtk.h>
-#include "ege-output-action.h"
+#include "widgets/ege-output-action.h"
static void ege_output_action_get_property( GObject* obj, guint propId, GValue* value, GParamSpec * pspec );
diff --git a/src/ege-output-action.h b/src/widgets/ege-output-action.h
index fc21c2f27..0f4e21805 100644
--- a/src/ege-output-action.h
+++ b/src/widgets/ege-output-action.h
@@ -45,9 +45,7 @@
/* Note: this file should be kept compilable as both .cpp and .c */
-#include <glib.h>
#include <gtk/gtk.h>
-#include <glib-object.h>
G_BEGIN_DECLS
diff --git a/src/widgets/ege-paint-def.cpp b/src/widgets/ege-paint-def.cpp
index 542205b53..1a8ad041a 100644
--- a/src/widgets/ege-paint-def.cpp
+++ b/src/widgets/ege-paint-def.cpp
@@ -44,7 +44,6 @@
#include <string>
#include <iostream>
#include <sstream>
-#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <glibmm/i18n.h>
diff --git a/src/ege-select-one-action.cpp b/src/widgets/ege-select-one-action.cpp
index 3facf7242..ab86c49f8 100644
--- a/src/ege-select-one-action.cpp
+++ b/src/widgets/ege-select-one-action.cpp
@@ -43,7 +43,7 @@
#include <gtk/gtk.h>
-#include "ege-select-one-action.h"
+#include "widgets/ege-select-one-action.h"
enum {
CHANGED = 0,
diff --git a/src/ege-select-one-action.h b/src/widgets/ege-select-one-action.h
index d605f4a67..0c5cecaa3 100644
--- a/src/ege-select-one-action.h
+++ b/src/widgets/ege-select-one-action.h
@@ -48,9 +48,7 @@
/* Note: this file should be kept compilable as both .cpp and .c */
-#include <glib.h>
#include <gtk/gtk.h>
-#include <glib-object.h>
G_BEGIN_DECLS
diff --git a/src/widgets/eraser-toolbar.cpp b/src/widgets/eraser-toolbar.cpp
index 14e7cbf4e..f547cbd8b 100644
--- a/src/widgets/eraser-toolbar.cpp
+++ b/src/widgets/eraser-toolbar.cpp
@@ -35,9 +35,9 @@
#include "desktop-handles.h"
#include "desktop.h"
#include "document-undo.h"
-#include "ege-adjustment-action.h"
-#include "ege-select-one-action.h"
-#include "ink-action.h"
+#include "widgets/ege-adjustment-action.h"
+#include "widgets/ege-select-one-action.h"
+#include "widgets/ink-action.h"
#include "preferences.h"
#include "toolbox.h"
#include "ui/icon-names.h"
diff --git a/src/widgets/font-selector.cpp b/src/widgets/font-selector.cpp
index 0e862638c..943434868 100644
--- a/src/widgets/font-selector.cpp
+++ b/src/widgets/font-selector.cpp
@@ -1,6 +1,4 @@
-#define __SP_FONT_SELECTOR_C__
-
-/*
+/**
* Font selection widgets
*
* Authors:
@@ -38,7 +36,11 @@
struct SPFontSelector
{
+#if GTK_CHECK_VERSION(3,0,0)
+ GtkBox hbox;
+#else
GtkHBox hbox;
+#endif
unsigned int block_emit : 1;
@@ -59,7 +61,11 @@ struct SPFontSelector
struct SPFontSelectorClass
{
+#if GTK_CHECK_VERSION(3,0,0)
+ GtkBoxClass parent_class;
+#else
GtkHBoxClass parent_class;
+#endif
void (* font_set) (SPFontSelector *fsel, gchar *fontspec);
};
@@ -69,8 +75,6 @@ enum {
LAST_SIGNAL
};
-static void sp_font_selector_class_init (SPFontSelectorClass *c);
-static void sp_font_selector_init (SPFontSelector *fsel);
static void sp_font_selector_dispose (GObject *object);
static void sp_font_selector_family_select_row (GtkTreeSelection *selection,
@@ -85,36 +89,18 @@ static void sp_font_selector_size_changed (GtkComboBox *combobo
static void sp_font_selector_emit_set (SPFontSelector *fsel);
static void sp_font_selector_set_sizes( SPFontSelector *fsel );
-static GtkHBoxClass *fs_parent_class = NULL;
static guint fs_signals[LAST_SIGNAL] = { 0 };
-GType sp_font_selector_get_type()
-{
- static GType type = 0;
- if (!type) {
- GTypeInfo info = {
- sizeof(SPFontSelectorClass),
- 0, // base_init
- 0, // base_finalize
- (GClassInitFunc)sp_font_selector_class_init,
- 0, // class_finalize
- 0, // class_data
- sizeof(SPFontSelector),
- 0, // n_preallocs
- (GInstanceInitFunc)sp_font_selector_init,
- 0 // value_table
- };
- type = g_type_register_static(GTK_TYPE_HBOX, "SPFontSelector", &info, static_cast<GTypeFlags>(0));
- }
- return type;
-}
+#if GTK_CHECK_VERSION(3,0,0)
+G_DEFINE_TYPE(SPFontSelector, sp_font_selector, GTK_TYPE_BOX);
+#else
+G_DEFINE_TYPE(SPFontSelector, sp_font_selector, GTK_TYPE_HBOX);
+#endif
static void sp_font_selector_class_init(SPFontSelectorClass *c)
{
GObjectClass *object_class = G_OBJECT_CLASS(c);
- fs_parent_class = (GtkHBoxClass* )g_type_class_peek_parent (c);
-
fs_signals[FONT_SET] = g_signal_new ("font_set",
G_TYPE_FROM_CLASS(object_class),
(GSignalFlags)G_SIGNAL_RUN_FIRST,
@@ -157,6 +143,10 @@ static void sp_font_selector_init(SPFontSelector *fsel)
gtk_container_add(GTK_CONTAINER(f), sw);
fsel->family_treeview = gtk_tree_view_new ();
+ gtk_tree_view_set_row_separator_func( GTK_TREE_VIEW(fsel->family_treeview),
+ GtkTreeViewRowSeparatorFunc ((gpointer)font_lister_separator_func),
+ NULL, NULL );
+ gtk_widget_show_all(GTK_WIDGET (fsel->family_treeview));
GtkTreeViewColumn *column = gtk_tree_view_column_new ();
GtkCellRenderer *cell = gtk_cell_renderer_text_new ();
gtk_tree_view_column_pack_start (column, cell, FALSE);
@@ -166,9 +156,6 @@ static void sp_font_selector_init(SPFontSelector *fsel)
NULL, NULL );
gtk_tree_view_append_column (GTK_TREE_VIEW(fsel->family_treeview), column);
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(fsel->family_treeview), FALSE);
- gtk_tree_view_set_row_separator_func( GTK_TREE_VIEW(fsel->family_treeview),
- GtkTreeViewRowSeparatorFunc ((gpointer)font_lister_separator_func),
- NULL, NULL );
/* Muck with style, see text-toolbar.cpp */
gtk_widget_set_name( GTK_WIDGET(fsel->family_treeview), "font_selector_family" );
@@ -179,6 +166,7 @@ static void sp_font_selector_init(SPFontSelector *fsel)
Inkscape::FontLister* fontlister = Inkscape::FontLister::get_instance();
Glib::RefPtr<Gtk::ListStore> store = fontlister->get_font_list();
gtk_tree_view_set_model (GTK_TREE_VIEW(fsel->family_treeview), GTK_TREE_MODEL (Glib::unwrap (store)));
+ //gtk_tree_view_set_tooltip_column(GTK_TREE_VIEW(fsel->family_treeview),2);
gtk_container_add(GTK_CONTAINER(sw), fsel->family_treeview);
gtk_widget_show_all (sw);
@@ -210,12 +198,22 @@ static void sp_font_selector_init(SPFontSelector *fsel)
gtk_box_pack_start(GTK_BOX (vb), sw, TRUE, TRUE, 0);
fsel->style_treeview = gtk_tree_view_new ();
- column = gtk_tree_view_column_new ();
+
+ // CSS Style name
cell = gtk_cell_renderer_text_new ();
- gtk_tree_view_column_pack_start (column, cell, FALSE);
- gtk_tree_view_column_set_attributes (column, cell, "text", 0, NULL);
+ column = gtk_tree_view_column_new_with_attributes ("CSS", cell, "text", 0, NULL );
+ //gtk_tree_view_column_pack_start (column, cell, FALSE);
+ gtk_tree_view_column_set_resizable (column, TRUE);
gtk_tree_view_append_column (GTK_TREE_VIEW(fsel->style_treeview), column);
- gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(fsel->style_treeview), FALSE);
+
+ // Display Style name
+ cell = gtk_cell_renderer_text_new ();
+ column = gtk_tree_view_column_new_with_attributes (_("Face"), cell, "text", 1, NULL );
+ //gtk_tree_view_column_pack_start (column, cell, FALSE);
+ gtk_tree_view_append_column (GTK_TREE_VIEW(fsel->style_treeview), column);
+
+ //gtk_tree_view_set_tooltip_column(GTK_TREE_VIEW(fsel->style_treeview), 1);
+ gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(fsel->style_treeview), TRUE);
gtk_container_add(GTK_CONTAINER(sw), fsel->style_treeview);
gtk_widget_show_all (sw);
@@ -273,8 +271,8 @@ static void sp_font_selector_dispose(GObject *object)
fsel->styles.length = 0;
}
- if (G_OBJECT_CLASS(fs_parent_class)->dispose) {
- G_OBJECT_CLASS(fs_parent_class)->dispose(object);
+ if (G_OBJECT_CLASS(sp_font_selector_parent_class)->dispose) {
+ G_OBJECT_CLASS(sp_font_selector_parent_class)->dispose(object);
}
}
@@ -292,6 +290,9 @@ static void sp_font_selector_family_select_row(GtkTreeSelection *selection,
GtkTreeModel *model;
GtkTreeIter iter;
if (!gtk_tree_selection_get_selected (selection, &model, &iter)) return;
+
+ Inkscape::FontLister *fontlister = Inkscape::FontLister::get_instance();
+ fontlister->ensureRowStyles(model, &iter);
// Next get family name with its style list
gchar *family;
@@ -299,20 +300,21 @@ static void sp_font_selector_family_select_row(GtkTreeSelection *selection,
gtk_tree_model_get (model, &iter, 0, &family, 1, &list, -1);
// Find best style match for selected family with current style (e.g. of selected text).
- Inkscape::FontLister *fontlister = Inkscape::FontLister::get_instance();
Glib::ustring style = fontlister->get_font_style();
Glib::ustring best = fontlister->get_best_style_match (family, style);
// Create our own store of styles for selected font-family and find index of best style match
int path_index = 0;
int index = 0;
- GtkListStore *store = gtk_list_store_new (1, G_TYPE_STRING); // Where is this deleted?
+ GtkListStore *store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING); // Where is this deleted?
for ( ; list ; list = list->next )
{
gtk_list_store_append (store, &iter);
- gtk_list_store_set (store, &iter, 0, (char*)list->data, -1);
-
- if( best.compare( (char*)list->data ) == 0 ) {
+ gtk_list_store_set (store, &iter,
+ 0, ((StyleNames*)list->data)->CssName.c_str(),
+ 1, ((StyleNames*)list->data)->DisplayName.c_str(),
+ -1);
+ if( best.compare( ((StyleNames*)list->data)->CssName ) == 0 ) {
path_index = index;
}
++index;
@@ -320,6 +322,7 @@ static void sp_font_selector_family_select_row(GtkTreeSelection *selection,
// Attach store to tree view. Can trigger style changed signal (but not FONT_SET):
gtk_tree_view_set_model (GTK_TREE_VIEW (fsel->style_treeview), GTK_TREE_MODEL (store));
+ //gtk_tree_view_set_tooltip_column(GTK_TREE_VIEW(fsel->style_treeview),1);
// Get path to best style
GtkTreePath *path = gtk_tree_path_new ();
@@ -537,4 +540,4 @@ double sp_font_selector_get_size(SPFontSelector *fsel)
fill-column:99
End:
*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8 :
diff --git a/src/widgets/font-selector.h b/src/widgets/font-selector.h
index 66715f048..ff5472d2d 100644
--- a/src/widgets/font-selector.h
+++ b/src/widgets/font-selector.h
@@ -54,7 +54,7 @@ Glib::ustring sp_font_selector_get_fontspec (SPFontSelector *fsel);
double sp_font_selector_get_size (SPFontSelector *fsel);
-#endif // SP_FONT_SELECTOR_H
+#endif // !SP_FONT_SELECTOR_H
/*
Local Variables:
@@ -65,4 +65,4 @@ double sp_font_selector_get_size (SPFontSelector *fsel);
fill-column:99
End:
*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8 :
diff --git a/src/widgets/gradient-image.cpp b/src/widgets/gradient-image.cpp
index 64b058f62..6901b8549 100644
--- a/src/widgets/gradient-image.cpp
+++ b/src/widgets/gradient-image.cpp
@@ -1,6 +1,4 @@
-#define __SP_GRADIENT_IMAGE_C__
-
-/*
+/**
* A simple gradient preview
*
* Author:
@@ -12,18 +10,15 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include "macros.h"
+#include <sigc++/sigc++.h>
+
#include "display/cairo-utils.h"
#include "gradient-image.h"
+#include "macros.h"
#include "sp-gradient.h"
-#include <sigc++/functors/ptr_fun.h>
-#include <sigc++/adaptors/bind.h>
-
#define VBLOCK 16
-static void sp_gradient_image_class_init (SPGradientImageClass *klass);
-static void sp_gradient_image_init (SPGradientImage *image);
static void sp_gradient_image_size_request (GtkWidget *widget, GtkRequisition *requisition);
#if GTK_CHECK_VERSION(3,0,0)
@@ -45,35 +40,13 @@ static void sp_gradient_image_gradient_release (SPObject *, SPGradientImage *im)
static void sp_gradient_image_gradient_modified (SPObject *, guint flags, SPGradientImage *im);
static void sp_gradient_image_update (SPGradientImage *img);
-static GtkWidgetClass *parent_class;
-
-GType sp_gradient_image_get_type(void)
-{
- static GType type = 0;
- if (!type) {
- GTypeInfo info = {
- sizeof (SPGradientImageClass),
- NULL, NULL,
- (GClassInitFunc) sp_gradient_image_class_init,
- NULL, NULL,
- sizeof (SPGradientImage),
- 0,
- (GInstanceInitFunc) sp_gradient_image_init,
- NULL
- };
- type = g_type_register_static (GTK_TYPE_WIDGET, "SPGradientImage", &info, (GTypeFlags)0);
- }
- return type;
-}
+G_DEFINE_TYPE(SPGradientImage, sp_gradient_image, GTK_TYPE_WIDGET);
static void sp_gradient_image_class_init(SPGradientImageClass *klass)
{
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass);
- parent_class = GTK_WIDGET_CLASS(g_type_class_peek_parent (klass));
#if GTK_CHECK_VERSION(3,0,0)
-// GObjectClass *object_class = G_OBJECT_CLASS(klass);
-
widget_class->get_preferred_width = sp_gradient_image_get_preferred_width;
widget_class->get_preferred_height = sp_gradient_image_get_preferred_height;
widget_class->draw = sp_gradient_image_draw;
@@ -116,11 +89,11 @@ static void sp_gradient_image_destroy(GtkObject *object)
image->modified_connection.~connection();
#if GTK_CHECK_VERSION(3,0,0)
- if (parent_class->destroy)
- (* (parent_class)->destroy) (object);
+ if (GTK_WIDGET_CLASS(sp_gradient_image_parent_class)->destroy)
+ GTK_WIDGET_CLASS(sp_gradient_image_parent_class)->destroy(object);
#else
- if ((GTK_OBJECT_CLASS(parent_class))->destroy)
- (* (GTK_OBJECT_CLASS(parent_class))->destroy) (object);
+ if (GTK_OBJECT_CLASS(sp_gradient_image_parent_class)->destroy)
+ GTK_OBJECT_CLASS(sp_gradient_image_parent_class)->destroy(object);
#endif
}
@@ -269,3 +242,14 @@ sp_gradient_image_update (SPGradientImage *image)
gtk_widget_queue_draw (GTK_WIDGET (image));
}
}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8 :
diff --git a/src/widgets/gradient-image.h b/src/widgets/gradient-image.h
index 904ce4cac..0d3833441 100644
--- a/src/widgets/gradient-image.h
+++ b/src/widgets/gradient-image.h
@@ -1,7 +1,7 @@
-#ifndef __SP_GRADIENT_IMAGE_H__
-#define __SP_GRADIENT_IMAGE_H__
+#ifndef SEEN_SP_GRADIENT_IMAGE_H
+#define SEEN_SP_GRADIENT_IMAGE_H
-/*
+/**
* A simple gradient preview
*
* Author:
@@ -17,9 +17,6 @@
class SPGradient;
-#include <glib.h>
-
-#include <stddef.h>
#include <sigc++/connection.h>
#define SP_TYPE_GRADIENT_IMAGE (sp_gradient_image_get_type ())
@@ -29,15 +26,15 @@ class SPGradient;
#define SP_IS_GRADIENT_IMAGE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), SP_TYPE_GRADIENT_IMAGE))
struct SPGradientImage {
- GtkWidget widget;
- SPGradient *gradient;
+ GtkWidget widget;
+ SPGradient *gradient;
- sigc::connection release_connection;
- sigc::connection modified_connection;
+ sigc::connection release_connection;
+ sigc::connection modified_connection;
};
struct SPGradientImageClass {
- GtkWidgetClass parent_class;
+ GtkWidgetClass parent_class;
};
GType sp_gradient_image_get_type (void);
@@ -47,3 +44,14 @@ GdkPixbuf *sp_gradient_to_pixbuf (SPGradient *gr, int width, int height);
void sp_gradient_image_set_gradient (SPGradientImage *gi, SPGradient *gr);
#endif
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8 :
diff --git a/src/widgets/gradient-selector.cpp b/src/widgets/gradient-selector.cpp
index 871d1ee4c..a5e16aed2 100644
--- a/src/widgets/gradient-selector.cpp
+++ b/src/widgets/gradient-selector.cpp
@@ -16,13 +16,15 @@
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
+
+#include <gtkmm/treeview.h>
+
#include "gradient-vector.h"
-#include <gtk/gtk.h>
#include "document.h"
-#include "../document-undo.h"
-#include "../document-private.h"
-#include "../gradient-chemistry.h"
+#include "document-undo.h"
+#include "document-private.h"
+#include "gradient-chemistry.h"
#include "inkscape.h"
#include "verbs.h"
#include "helper/action.h"
@@ -47,8 +49,6 @@ enum {
};
-static void sp_gradient_selector_class_init (SPGradientSelectorClass *klass);
-static void sp_gradient_selector_init (SPGradientSelector *selector);
static void sp_gradient_selector_dispose(GObject *object);
/* Signal handlers */
@@ -57,41 +57,18 @@ static void sp_gradient_selector_edit_vector_clicked (GtkWidget *w, SPGradientSe
static void sp_gradient_selector_add_vector_clicked (GtkWidget *w, SPGradientSelector *sel);
static void sp_gradient_selector_delete_vector_clicked (GtkWidget *w, SPGradientSelector *sel);
-
-static GtkVBoxClass *parent_class;
static guint signals[LAST_SIGNAL] = {0};
-GType sp_gradient_selector_get_type(void)
-{
- static GType type = 0;
- if (!type) {
- static const GTypeInfo info = {
- sizeof(SPGradientSelectorClass),
- NULL, /* base_init */
- NULL, /* base_finalize */
- (GClassInitFunc) sp_gradient_selector_class_init,
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof(SPGradientSelector),
- 0, /* n_preallocs */
- (GInstanceInitFunc) sp_gradient_selector_init,
- 0, /* value_table */
- };
-
- type = g_type_register_static( GTK_TYPE_VBOX,
- "SPGradientSelector",
- &info,
- static_cast< GTypeFlags > (0) );
- }
- return type;
-}
+#if GTK_CHECK_VERSION(3,0,0)
+G_DEFINE_TYPE(SPGradientSelector, sp_gradient_selector, GTK_TYPE_BOX);
+#else
+G_DEFINE_TYPE(SPGradientSelector, sp_gradient_selector, GTK_TYPE_VBOX);
+#endif
static void sp_gradient_selector_class_init(SPGradientSelectorClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS(klass);
- parent_class = GTK_VBOX_CLASS(g_type_class_peek_parent (klass));
-
signals[GRABBED] = g_signal_new ("grabbed",
G_TYPE_FROM_CLASS(object_class),
(GSignalFlags)(G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE),
@@ -128,6 +105,11 @@ static void sp_gradient_selector_init(SPGradientSelector *sel)
{
sel->safelyInit = true;
sel->blocked = false;
+
+#if GTK_CHECK_VERSION(3,0,0)
+ gtk_orientable_set_orientation(GTK_ORIENTABLE(sel), GTK_ORIENTATION_VERTICAL);
+#endif
+
new (&sel->nonsolid) std::vector<GtkWidget*>();
new (&sel->swatch_widgets) std::vector<GtkWidget*>();
@@ -269,8 +251,8 @@ static void sp_gradient_selector_dispose(GObject *object)
sel->text_renderer = NULL;
}
- if ((G_OBJECT_CLASS(parent_class))->dispose) {
- (* (G_OBJECT_CLASS(parent_class))->dispose) (object);
+ if ((G_OBJECT_CLASS(sp_gradient_selector_parent_class))->dispose) {
+ (G_OBJECT_CLASS(sp_gradient_selector_parent_class))->dispose(object);
}
}
diff --git a/src/widgets/gradient-selector.h b/src/widgets/gradient-selector.h
index 1f58de2e4..e090d7cbd 100644
--- a/src/widgets/gradient-selector.h
+++ b/src/widgets/gradient-selector.h
@@ -19,27 +19,23 @@
# include <config.h>
#endif
-#if GLIBMM_DISABLE_DEPRECATED && HAVE_GLIBMM_THREADS_H
-#include <glibmm/threads.h>
-#endif
-
-#include <glib.h>
-#include <gtk/gtk.h>
-
-#include <gtkmm/entry.h>
-#include <gtkmm/label.h>
-#include <gtkmm/table.h>
#include <gtkmm/liststore.h>
-#include <gtkmm/treeview.h>
#include <gtkmm/scrolledwindow.h>
#include <vector>
-#include "sp-gradient.h"
#include "sp-gradient-spread.h"
#include "sp-gradient-units.h"
+class SPDocument;
class SPGradient;
+namespace Gtk {
+class CellRendererPixbuf;
+class CellRendererText;
+class ScrolledWindow;
+class TreeView;
+}
+
#define SP_TYPE_GRADIENT_SELECTOR (sp_gradient_selector_get_type ())
#define SP_GRADIENT_SELECTOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), SP_TYPE_GRADIENT_SELECTOR, SPGradientSelector))
#define SP_GRADIENT_SELECTOR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), SP_TYPE_GRADIENT_SELECTOR, SPGradientSelectorClass))
@@ -49,11 +45,18 @@ class SPGradient;
struct SPGradientSelector {
+#if GTK_CHECK_VERSION(3,0,0)
+ GtkBox vbox;
+#else
GtkVBox vbox;
+#endif
enum SelectorMode {
MODE_LINEAR,
MODE_RADIAL,
+#ifdef WITH_MESH
+ MODE_MESH,
+#endif
MODE_SWATCH
};
@@ -128,7 +131,11 @@ struct SPGradientSelector {
};
struct SPGradientSelectorClass {
+#if GTK_CHECK_VERSION(3,0,0)
+ GtkBoxClass parent_class;
+#else
GtkVBoxClass parent_class;
+#endif
void (* grabbed) (SPGradientSelector *sel);
void (* dragged) (SPGradientSelector *sel);
diff --git a/src/widgets/gradient-toolbar.cpp b/src/widgets/gradient-toolbar.cpp
index 4fda44c8d..b6378b251 100644
--- a/src/widgets/gradient-toolbar.cpp
+++ b/src/widgets/gradient-toolbar.cpp
@@ -22,12 +22,12 @@
#include "desktop.h"
#include "document-undo.h"
#include "document.h"
-#include "ege-adjustment-action.h"
-#include "ege-select-one-action.h"
+#include "widgets/ege-adjustment-action.h"
+#include "widgets/ege-select-one-action.h"
#include "gradient-chemistry.h"
#include "gradient-drag.h"
#include "gradient-toolbar.h"
-#include "ink-action.h"
+#include "widgets/ink-action.h"
#include "macros.h"
#include "preferences.h"
#include "selection.h"
@@ -448,11 +448,6 @@ static void gr_defs_modified(SPObject * /*defs*/, guint /*flags*/, GtkWidget *wi
gr_tb_selection_changed(NULL, (gpointer) widget);
}
-static void gr_disconnect_sigc(GObject * /*obj*/, sigc::connection *connection) {
- connection->disconnect();
- delete connection;
-}
-
static SPStop *get_selected_stop( GtkWidget *vb)
{
SPStop *stop = NULL;
@@ -1018,6 +1013,9 @@ void check_renderer(GtkWidget *combo)
g_object_set_data(G_OBJECT(combo), "renderers", renderer);
}
}
+
+static void gradient_toolbox_check_ec(SPDesktop* dt, Inkscape::UI::Tools::ToolBase* ec, GObject* holder);
+
/**
* Gradient auxiliary toolbar construction and setup.
*
@@ -1111,7 +1109,7 @@ void sp_gradient_toolbox_prep(SPDesktop * desktop, GtkActionGroup* mainActions,
GtkTreeIter iter;
gtk_list_store_append( model, &iter );
- gtk_list_store_set( model, &iter, 0, _("None"), 1, SP_GRADIENT_SPREAD_PAD, -1 );
+ gtk_list_store_set( model, &iter, 0, C_("Gradient repeat type", "None"), 1, SP_GRADIENT_SPREAD_PAD, -1 );
gtk_list_store_append( model, &iter );
gtk_list_store_set( model, &iter, 0, _("Reflected"), 1, SP_GRADIENT_SPREAD_REFLECT, -1 );
@@ -1229,34 +1227,51 @@ void sp_gradient_toolbox_prep(SPDesktop * desktop, GtkActionGroup* mainActions,
gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(itact), !linkedmode );
}
- Inkscape::Selection *selection = sp_desktop_selection(desktop);
- SPDocument *document = sp_desktop_document(desktop);
-
g_object_set_data(holder, "desktop", desktop);
- // connect to selection modified and changed signals
- sigc::connection *conn1 = new sigc::connection(
- selection->connectChanged(sigc::bind(sigc::ptr_fun(&gr_tb_selection_changed), (gpointer) holder)));
- sigc::connection *conn2 = new sigc::connection(
- selection->connectModified(sigc::bind(sigc::ptr_fun(&gr_tb_selection_modified), (gpointer) holder)));
- sigc::connection *conn3 = new sigc::connection(
- desktop->connectToolSubselectionChanged( sigc::bind(sigc::ptr_fun(&gr_drag_selection_changed), (gpointer) holder)));
-
- // when holder is destroyed, disconnect
- g_signal_connect(G_OBJECT(holder), "destroy", G_CALLBACK(gr_disconnect_sigc), conn1);
- g_signal_connect(G_OBJECT(holder), "destroy", G_CALLBACK(gr_disconnect_sigc), conn2);
- g_signal_connect(G_OBJECT(holder), "destroy", G_CALLBACK(gr_disconnect_sigc), conn3);
-
- // connect to release and modified signals of the defs (i.e. when someone changes gradient)
- sigc::connection *release_connection = new sigc::connection();
- *release_connection = document->getDefs()->connectRelease(sigc::bind<1>(sigc::ptr_fun(&gr_defs_release), GTK_WIDGET(holder)));
- sigc::connection *modified_connection = new sigc::connection();
- *modified_connection = document->getDefs()->connectModified(sigc::bind<2>(sigc::ptr_fun(&gr_defs_modified), GTK_WIDGET(holder)));
-
- // when holder is destroyed, disconnect
- g_signal_connect(G_OBJECT(holder), "destroy", G_CALLBACK(gr_disconnect_sigc), release_connection);
- g_signal_connect(G_OBJECT(holder), "destroy", G_CALLBACK(gr_disconnect_sigc), modified_connection);
+ desktop->connectEventContextChanged(sigc::bind(sigc::ptr_fun(&gradient_toolbox_check_ec), holder));
+}
+
+// lp:1327267
+/**
+ * Checks the current tool and connects gradient aux toolbox signals if it happens to be the gradient tool.
+ * Called every time the current tool changes by signal emission.
+ */
+static void gradient_toolbox_check_ec(SPDesktop* desktop, Inkscape::UI::Tools::ToolBase* ec, GObject* holder)
+{
+ static sigc::connection connChanged;
+ static sigc::connection connModified;
+ static sigc::connection connSubselectionChanged;
+ static sigc::connection connDefsRelease;
+ static sigc::connection connDefsModified;
+
+ if (SP_IS_GRADIENT_CONTEXT(ec)) {
+ Inkscape::Selection *selection = sp_desktop_selection(desktop);
+ SPDocument *document = sp_desktop_document(desktop);
+ // connect to selection modified and changed signals
+ connChanged = selection->connectChanged(sigc::bind(sigc::ptr_fun(&gr_tb_selection_changed), holder));
+ connModified = selection->connectModified(sigc::bind(sigc::ptr_fun(&gr_tb_selection_modified), holder));
+ connSubselectionChanged = desktop->connectToolSubselectionChanged(sigc::bind(sigc::ptr_fun(&gr_drag_selection_changed), holder));
+
+ // Is this necessary? Couldn't hurt.
+ gr_tb_selection_changed(selection, holder);
+
+ // connect to release and modified signals of the defs (i.e. when someone changes gradient)
+ connDefsRelease = document->getDefs()->connectRelease(sigc::bind<1>(sigc::ptr_fun(&gr_defs_release), GTK_WIDGET(holder)));
+ connDefsModified = document->getDefs()->connectModified(sigc::bind<2>(sigc::ptr_fun(&gr_defs_modified), GTK_WIDGET(holder)));
+ } else {
+ if (connChanged)
+ connChanged.disconnect();
+ if (connModified)
+ connModified.disconnect();
+ if (connSubselectionChanged)
+ connSubselectionChanged.disconnect();
+ if (connDefsRelease)
+ connDefsRelease.disconnect();
+ if (connDefsModified)
+ connDefsModified.disconnect();
+ }
}
/*
diff --git a/src/widgets/gradient-vector.cpp b/src/widgets/gradient-vector.cpp
index 17ac887c4..6607c90d2 100644
--- a/src/widgets/gradient-vector.cpp
+++ b/src/widgets/gradient-vector.cpp
@@ -23,6 +23,7 @@
# include "config.h"
#endif
+#include <glibmm.h>
#include "gradient-vector.h"
#include "ui/widget/color-preview.h"
#include "verbs.h"
@@ -30,17 +31,17 @@
#include "macros.h"
#include <glibmm/i18n.h>
#include <set>
-#include "../widgets/gradient-image.h"
-#include "../inkscape.h"
-#include "../document-private.h"
-#include "../gradient-chemistry.h"
-#include "../helper/window.h"
+#include "widgets/gradient-image.h"
+#include "inkscape.h"
+#include "document-private.h"
+#include "gradient-chemistry.h"
+#include "helper/window.h"
#include "io/resource.h"
#include "xml/repr.h"
-#include "../dialogs/dialog-events.h"
-#include "../preferences.h"
+#include "ui/dialog-events.h"
+#include "preferences.h"
#include "svg/css-ostringstream.h"
#include "sp-stop.h"
#include "selection-chemistry.h"
@@ -50,8 +51,7 @@
#include "desktop.h"
#include "layer-manager.h"
-#include <sigc++/functors/ptr_fun.h>
-#include <sigc++/adaptors/bind.h>
+#include <sigc++/sigc++.h>
#include "document-undo.h"
using Inkscape::DocumentUndo;
@@ -61,9 +61,6 @@ enum {
LAST_SIGNAL
};
-static void sp_gradient_vector_selector_class_init(SPGradientVectorSelectorClass *klass);
-static void sp_gradient_vector_selector_init(SPGradientVectorSelector *gvs);
-
#if GTK_CHECK_VERSION(3,0,0)
static void sp_gradient_vector_selector_destroy(GtkWidget *object);
#else
@@ -79,7 +76,6 @@ static SPStop *get_selected_stop( GtkWidget *vb);
void gr_get_usage_counts(SPDocument *doc, std::map<SPGradient *, gint> *mapUsageCount );
unsigned long sp_gradient_to_hhssll(SPGradient *gr);
-static GtkVBoxClass *parent_class;
static guint signals[LAST_SIGNAL] = {0};
// TODO FIXME kill these globals!!!
@@ -88,35 +84,15 @@ static win_data wd;
static gint x = -1000, y = -1000, w = 0, h = 0; // impossible original values to make sure they are read from prefs
static Glib::ustring const prefs_path = "/dialogs/gradienteditor/";
-GType sp_gradient_vector_selector_get_type(void)
-{
- static GType type = 0;
- if (!type) {
- static const GTypeInfo info = {
- sizeof(SPGradientVectorSelectorClass),
- NULL, /* base_init */
- NULL, /* base_finalize */
- reinterpret_cast<GClassInitFunc>(sp_gradient_vector_selector_class_init),
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof(SPGradientVectorSelector),
- 0, /* n_preallocs */
- reinterpret_cast<GInstanceInitFunc>(sp_gradient_vector_selector_init),
- 0, /* value_table */
- };
-
- type = g_type_register_static( GTK_TYPE_VBOX,
- "SPGradientVectorSelector",
- &info,
- static_cast< GTypeFlags >(0) );
- }
- return type;
-}
+#if GTK_CHECK_VERSION(3,0,0)
+G_DEFINE_TYPE(SPGradientVectorSelector, sp_gradient_vector_selector, GTK_TYPE_BOX);
+#else
+G_DEFINE_TYPE(SPGradientVectorSelector, sp_gradient_vector_selector, GTK_TYPE_VBOX);
+#endif
static void sp_gradient_vector_selector_class_init(SPGradientVectorSelectorClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
- parent_class = static_cast<GtkVBoxClass*>(g_type_class_peek_parent(klass));
signals[VECTOR_SET] = g_signal_new( "vector_set",
G_TYPE_FROM_CLASS(gobject_class),
@@ -138,6 +114,10 @@ static void sp_gradient_vector_selector_class_init(SPGradientVectorSelectorClass
static void sp_gradient_vector_selector_init(SPGradientVectorSelector *gvs)
{
+#if GTK_CHECK_VERSION(3,0,0)
+ gtk_orientable_set_orientation(GTK_ORIENTABLE(gvs), GTK_ORIENTATION_VERTICAL);
+#endif
+
gvs->idlabel = TRUE;
gvs->swatched = false;
@@ -181,12 +161,12 @@ static void sp_gradient_vector_selector_destroy(GtkObject *object)
gvs->tree_select_connection.~connection();
#if GTK_CHECK_VERSION(3,0,0)
- if ((reinterpret_cast<GtkWidgetClass *>(parent_class))->destroy) {
- (* (reinterpret_cast<GtkWidgetClass *>(parent_class))->destroy) (object);
+ if ((GTK_WIDGET_CLASS(sp_gradient_vector_selector_parent_class))->destroy) {
+ (GTK_WIDGET_CLASS(sp_gradient_vector_selector_parent_class))->destroy(object);
}
#else
- if ((reinterpret_cast<GtkObjectClass *>(parent_class))->destroy) {
- (* (reinterpret_cast<GtkObjectClass *>(parent_class))->destroy) (object);
+ if ((GTK_OBJECT_CLASS(sp_gradient_vector_selector_parent_class))->destroy) {
+ (GTK_OBJECT_CLASS(sp_gradient_vector_selector_parent_class))->destroy(object);
}
#endif
}
@@ -488,10 +468,10 @@ void SPGradientVectorSelector::setSwatched()
### Vector Editing Widget
##################################################################*/
-#include "../widgets/sp-color-notebook.h"
-#include "../widgets/widget-sizes.h"
-#include "../xml/node-event-vector.h"
-#include "../svg/svg-color.h"
+#include "widgets/sp-color-notebook.h"
+#include "widgets/widget-sizes.h"
+#include "xml/node-event-vector.h"
+#include "svg/svg-color.h"
#define PAD 4
diff --git a/src/widgets/gradient-vector.h b/src/widgets/gradient-vector.h
index b63120a6e..5ae90b28f 100644
--- a/src/widgets/gradient-vector.h
+++ b/src/widgets/gradient-vector.h
@@ -19,16 +19,8 @@
# include "config.h"
#endif
-#if GLIBMM_DISABLE_DEPRECATED && HAVE_GLIBMM_THREADS_H
-#include <glibmm/threads.h>
-#endif
-
#include <gtkmm/liststore.h>
-
-#include <stddef.h>
#include <sigc++/connection.h>
-
-#include <gtk/gtk.h>
#include "gradient-selector.h"
#define SP_TYPE_GRADIENT_VECTOR_SELECTOR (sp_gradient_vector_selector_get_type ())
@@ -43,7 +35,11 @@ class SPGradient;
class SPStop;
struct SPGradientVectorSelector {
+#if GTK_CHECK_VERSION(3,0,0)
+ GtkBox vbox;
+#else
GtkVBox vbox;
+#endif
guint idlabel : 1;
@@ -65,7 +61,11 @@ struct SPGradientVectorSelector {
};
struct SPGradientVectorSelectorClass {
+#if GTK_CHECK_VERSION(3,0,0)
+ GtkBoxClass parent_class;
+#else
GtkVBoxClass parent_class;
+#endif
void (* vector_set) (SPGradientVectorSelector *gvs, SPGradient *gr);
};
diff --git a/src/widgets/icon.cpp b/src/widgets/icon.cpp
index eb16cfece..a6e53d638 100644
--- a/src/widgets/icon.cpp
+++ b/src/widgets/icon.cpp
@@ -247,7 +247,11 @@ gboolean IconImpl::draw(GtkWidget *widget, cairo_t* cr)
bool unref_image = false;
/* copied from the expose function of GtkImage */
+#if GTK_CHECK_VERSION(3,0,0)
+ if (gtk_widget_get_state_flags (GTK_WIDGET(icon)) != GTK_STATE_FLAG_NORMAL && image) {
+#else
if (gtk_widget_get_state (GTK_WIDGET(icon)) != GTK_STATE_NORMAL && image) {
+#endif
GtkIconSource *source = gtk_icon_source_new();
gtk_icon_source_set_pixbuf(source, icon->pb);
gtk_icon_source_set_size(source, GTK_ICON_SIZE_SMALL_TOOLBAR); // note: this is boilerplate and not used
@@ -685,6 +689,7 @@ void IconImpl::setupLegacyNaming() {
legacyNames["draw-star"] ="star_angled";
legacyNames["path-mode-bezier"] ="bezier_mode";
legacyNames["path-mode-spiro"] ="spiro_splines_mode";
+ legacyNames["path-mode-bspline"] ="bspline_mode";
legacyNames["path-mode-polyline"] ="polylines_mode";
legacyNames["path-mode-polyline-paraxial"] ="paraxial_lines_mode";
legacyNames["draw-use-tilt"] ="guse_tilt";
diff --git a/src/widgets/icon.h b/src/widgets/icon.h
index e1dae0d6a..5838d8de4 100644
--- a/src/widgets/icon.h
+++ b/src/widgets/icon.h
@@ -14,14 +14,6 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#if GLIBMM_DISABLE_DEPRECATED && HAVE_GLIBMM_THREADS_H
-#include <glibmm/threads.h>
-#endif
-
#include <gtkmm/widget.h>
#include "icon-size.h"
diff --git a/src/ink-action.cpp b/src/widgets/ink-action.cpp
index dd1fe5484..5941c31e4 100644
--- a/src/ink-action.cpp
+++ b/src/widgets/ink-action.cpp
@@ -3,7 +3,7 @@
#include <glib/gi18n.h>
#include <gtk/gtk.h>
-#include "ink-action.h"
+#include "widgets/ink-action.h"
#include "widgets/button.h"
diff --git a/src/ink-action.h b/src/widgets/ink-action.h
index 1d4106681..ac5cb9873 100644
--- a/src/ink-action.h
+++ b/src/widgets/ink-action.h
@@ -2,9 +2,7 @@
#define SEEN_INK_ACTION
-#include <glib.h>
#include <gtk/gtk.h>
-#include <glib-object.h>
#include "icon-size.h"
#include "attributes.h"
diff --git a/src/ink-comboboxentry-action.cpp b/src/widgets/ink-comboboxentry-action.cpp
index 06ccc3739..1114d2cdb 100644
--- a/src/ink-comboboxentry-action.cpp
+++ b/src/widgets/ink-comboboxentry-action.cpp
@@ -30,7 +30,7 @@
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
-#include "ink-comboboxentry-action.h"
+#include "widgets/ink-comboboxentry-action.h"
#include "ui/icon-names.h"
// Must handle both tool and menu items!
@@ -38,7 +38,7 @@ static GtkWidget* create_tool_item( GtkAction* action );
static GtkWidget* create_menu_item( GtkAction* action );
// Internal
-static gint get_active_row_from_text( Ink_ComboBoxEntry_Action* action, const gchar* target_text, gboolean exclude = false );
+static gint get_active_row_from_text( Ink_ComboBoxEntry_Action* action, const gchar* target_text, gboolean exclude = false, gboolean ignore_case = false );
static Glib::ustring check_comma_separated_text( Ink_ComboBoxEntry_Action* action );
// Callbacks
@@ -383,6 +383,17 @@ GtkWidget* create_tool_item( GtkAction* action )
g_signal_connect( G_OBJECT(comboBoxEntry), "changed", G_CALLBACK(combo_box_changed_cb), action );
+ // Optionally add separator function...
+ if( ink_comboboxentry_action->separator_func != NULL ) {
+ gtk_combo_box_set_row_separator_func( ink_comboboxentry_action->combobox,
+ GtkTreeViewRowSeparatorFunc (ink_comboboxentry_action->separator_func),
+ NULL, NULL );
+ }
+
+ // FIXME: once gtk3 migration is done this can be removed
+ // https://bugzilla.gnome.org/show_bug.cgi?id=734915
+ gtk_widget_show_all (comboBoxEntry);
+
// Optionally add formatting...
if( ink_comboboxentry_action->cell_data_func != NULL ) {
GtkCellRenderer *cell = gtk_cell_renderer_text_new();
@@ -393,13 +404,6 @@ GtkWidget* create_tool_item( GtkAction* action )
NULL, NULL );
}
- // Optionally add separator function...
- if( ink_comboboxentry_action->separator_func != NULL ) {
- gtk_combo_box_set_row_separator_func( ink_comboboxentry_action->combobox,
- GtkTreeViewRowSeparatorFunc (ink_comboboxentry_action->separator_func),
- NULL, NULL );
- }
-
// Optionally widen the combobox width... which widens the drop-down list in list mode.
if( ink_comboboxentry_action->extra_width > 0 ) {
GtkRequisition req;
@@ -732,7 +736,8 @@ void ink_comboboxentry_action_set_altx_name( Ink_ComboBoxEntry_Action* actio
// use 3d colunm if available to exclude row from checking (useful to
// skip rows added for font-families included in doc and not on
// system)
-gint get_active_row_from_text( Ink_ComboBoxEntry_Action* action, const gchar* target_text, gboolean exclude ) {
+gint get_active_row_from_text( Ink_ComboBoxEntry_Action* action, const gchar* target_text,
+ gboolean exclude, gboolean ignore_case ) {
// Check if text in list
gint row = 0;
@@ -752,10 +757,23 @@ gint get_active_row_from_text( Ink_ComboBoxEntry_Action* action, const gchar* ta
gchar* text = 0;
gtk_tree_model_get( action->model, &iter, 0, &text, -1 ); // Column 0
- // Check for match
- if( strcmp( target_text, text ) == 0 ){
- found = true;
- break;
+ if( !ignore_case ) {
+ // Case sensitive compare
+ if( strcmp( target_text, text ) == 0 ){
+ found = true;
+ break;
+ }
+ } else {
+ // Case insensitive compare
+ gchar* target_text_casefolded = g_utf8_casefold( target_text, -1 );
+ gchar* text_casefolded = g_utf8_casefold( text, -1 );
+ gboolean equal = (strcmp( target_text_casefolded, text_casefolded ) == 0 );
+ g_free( text_casefolded );
+ g_free( target_text_casefolded );
+ if( equal ) {
+ found = true;
+ break;
+ }
}
}
@@ -794,7 +812,7 @@ static Glib::ustring check_comma_separated_text( Ink_ComboBoxEntry_Action* actio
// Remove any surrounding white space.
g_strstrip( tokens[i] );
- if( get_active_row_from_text( action, tokens[i], true ) == -1 ) {
+ if( get_active_row_from_text( action, tokens[i], true, true ) == -1 ) {
missing += tokens[i];
missing += ", ";
}
diff --git a/src/ink-comboboxentry-action.h b/src/widgets/ink-comboboxentry-action.h
index a66f0790e..04b66e8fe 100644
--- a/src/ink-comboboxentry-action.h
+++ b/src/widgets/ink-comboboxentry-action.h
@@ -19,12 +19,8 @@
#ifndef SEEN_INK_COMBOBOXENTRY_ACTION
#define SEEN_INK_COMBOBOXENTRY_ACTION
-#include <glib.h>
-#include <glib-object.h>
-
#include <gtk/gtk.h>
-
#define INK_COMBOBOXENTRY_TYPE_ACTION (ink_comboboxentry_action_get_type())
#define INK_COMBOBOXENTRY_ACTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), INK_COMBOBOXENTRY_TYPE_ACTION, Ink_ComboBoxEntry_Action))
#define INK_COMBOBOXENTRY_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), INK_COMBOBOXENTRY_TYPE_ACTION, Ink_ComboBoxEntry_ActionClass))
diff --git a/src/widgets/lpe-toolbar.cpp b/src/widgets/lpe-toolbar.cpp
index e9e5af912..a85f3ae78 100644
--- a/src/widgets/lpe-toolbar.cpp
+++ b/src/widgets/lpe-toolbar.cpp
@@ -30,19 +30,18 @@
#include "live_effects/lpe-line_segment.h"
#include "lpe-toolbar.h"
-#include "connection-pool.h"
#include "desktop-handles.h"
#include "desktop.h"
#include "document-undo.h"
-#include "ege-select-one-action.h"
+#include "widgets/ege-select-one-action.h"
#include "helper/action-context.h"
#include "helper/action.h"
-#include "ink-action.h"
+#include "widgets/ink-action.h"
#include "live_effects/effect.h"
#include "preferences.h"
#include "selection.h"
#include "sp-namedview.h"
-#include "tools-switch.h"
+#include "ui/tools-switch.h"
#include "ui/tools/lpe-tool.h"
#include "ui/widget/unit-tracker.h"
#include "util/units.h"
@@ -180,6 +179,7 @@ static void lpetool_unit_changed(GtkAction* /*act*/, GObject* tbl)
{
UnitTracker* tracker = reinterpret_cast<UnitTracker*>(g_object_get_data(tbl, "tracker"));
Unit const *unit = tracker->getActiveUnit();
+ g_return_if_fail(unit != NULL);
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
prefs->setString("/tools/lpetool/unit", unit->abbr);
@@ -275,12 +275,15 @@ static void lpetool_open_lpe_dialog(GtkToggleAction *act, gpointer data)
gtk_toggle_action_set_active(act, false);
}
+static void lpetool_toolbox_watch_ec(SPDesktop* dt, Inkscape::UI::Tools::ToolBase* ec, GObject* holder);
+
void sp_lpetool_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder)
{
UnitTracker* tracker = new UnitTracker(Inkscape::Util::UNIT_TYPE_LINEAR);
tracker->setActiveUnit(sp_desktop_namedview(desktop)->doc_units);
g_object_set_data(holder, "tracker", tracker);
Unit const *unit = tracker->getActiveUnit();
+ g_return_if_fail(unit != NULL);
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
prefs->setString("/tools/lpetool/unit", unit->abbr);
@@ -400,21 +403,27 @@ void sp_lpetool_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GO
gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), FALSE );
}
- //watch selection
- Inkscape::ConnectionPool* pool = Inkscape::ConnectionPool::new_connection_pool ("ISNodeToolbox");
+ desktop->connectEventContextChanged(sigc::bind(sigc::ptr_fun(lpetool_toolbox_watch_ec), holder));
+}
- sigc::connection *c_selection_modified =
- new sigc::connection (sp_desktop_selection (desktop)->connectModified
- (sigc::bind (sigc::ptr_fun (sp_lpetool_toolbox_sel_modified), holder)));
- pool->add_connection ("selection-modified", c_selection_modified);
+static void lpetool_toolbox_watch_ec(SPDesktop* desktop, Inkscape::UI::Tools::ToolBase* ec, GObject* holder)
+{
+ static sigc::connection c_selection_modified;
+ static sigc::connection c_selection_changed;
- sigc::connection *c_selection_changed =
- new sigc::connection (sp_desktop_selection (desktop)->connectChanged
- (sigc::bind (sigc::ptr_fun(sp_lpetool_toolbox_sel_changed), holder)));
- pool->add_connection ("selection-changed", c_selection_changed);
+ if (SP_IS_LPETOOL_CONTEXT(ec)) {
+ // Watch selection
+ c_selection_modified = sp_desktop_selection(desktop)->connectModified(sigc::bind(sigc::ptr_fun(sp_lpetool_toolbox_sel_modified), holder));
+ c_selection_changed = sp_desktop_selection(desktop)->connectChanged(sigc::bind(sigc::ptr_fun(sp_lpetool_toolbox_sel_changed), holder));
+ sp_lpetool_toolbox_sel_changed(sp_desktop_selection(desktop), holder);
+ } else {
+ if (c_selection_modified)
+ c_selection_modified.disconnect();
+ if (c_selection_changed)
+ c_selection_changed.disconnect();
+ }
}
-
/*
Local Variables:
mode:c++
@@ -424,4 +433,4 @@ void sp_lpetool_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GO
fill-column:99
End:
*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8 :
diff --git a/src/widgets/mappings.xml b/src/widgets/mappings.xml
index 2de3ff545..089bf76ea 100644
--- a/src/widgets/mappings.xml
+++ b/src/widgets/mappings.xml
@@ -197,6 +197,7 @@
<!-- bezier toolbar -->
<remap id='bezier_mode' newid='path-mode-bezier'/>
<remap id='spiro_splines_mode' newid='path-mode-spiro'/>
+ <remap id='bspline_mode' newid='path-mode-bspline'/>
<remap id='polylines_mode' newid='path-mode-polyline'/>
<remap id='paraxial_lines_mode' newid='path-mode-polyline-paraxial'/>
diff --git a/src/widgets/measure-toolbar.cpp b/src/widgets/measure-toolbar.cpp
index 46d3bd4e0..1a4678332 100644
--- a/src/widgets/measure-toolbar.cpp
+++ b/src/widgets/measure-toolbar.cpp
@@ -34,8 +34,8 @@
#include "desktop-handles.h"
#include "desktop.h"
#include "document-undo.h"
-#include "ege-adjustment-action.h"
-#include "ege-output-action.h"
+#include "widgets/ege-adjustment-action.h"
+#include "widgets/ege-output-action.h"
#include "preferences.h"
#include "toolbox.h"
#include "ui/widget/unit-tracker.h"
diff --git a/src/widgets/mesh-toolbar.cpp b/src/widgets/mesh-toolbar.cpp
index 15dda94f0..897d84278 100644
--- a/src/widgets/mesh-toolbar.cpp
+++ b/src/widgets/mesh-toolbar.cpp
@@ -42,6 +42,7 @@
#include <glibmm/i18n.h>
#include "ui/tools/gradient-tool.h"
+#include "ui/tools/mesh-tool.h"
#include "gradient-drag.h"
#include "sp-mesh-gradient.h"
#include "gradient-chemistry.h"
@@ -49,17 +50,16 @@
#include "selection.h"
#include "ui/icon-names.h"
-#include "../ege-adjustment-action.h"
-#include "../ege-output-action.h"
-#include "../ege-select-one-action.h"
-#include "../ink-action.h"
-#include "../ink-comboboxentry-action.h"
+#include "widgets/ege-adjustment-action.h"
+#include "widgets/ege-output-action.h"
+#include "widgets/ege-select-one-action.h"
+#include "widgets/ink-action.h"
+#include "widgets/ink-comboboxentry-action.h"
#include "sp-stop.h"
#include "svg/css-ostringstream.h"
#include "svg/svg-color.h"
#include "desktop-style.h"
-#include "ui/tools/gradient-tool.h"
#include "toolbox.h"
@@ -67,7 +67,7 @@ using Inkscape::DocumentUndo;
using Inkscape::UI::ToolboxFactory;
using Inkscape::UI::PrefPusher;
-static gboolean blocked = FALSE;
+static bool blocked = false;
//########################
//## Mesh ##
@@ -116,22 +116,16 @@ static void ms_drag_selection_changed(gpointer /*dragger*/, gpointer data)
}
-static void ms_defs_release(SPObject * /*defs*/, GtkWidget *widget)
+static void ms_defs_release(SPObject * /*defs*/, GObject *widget)
{
ms_tb_selection_changed(NULL, widget);
}
-static void ms_defs_modified(SPObject * /*defs*/, guint /*flags*/, GtkWidget *widget)
+static void ms_defs_modified(SPObject * /*defs*/, guint /*flags*/, GObject *widget)
{
- ms_tb_selection_changed(NULL, (gpointer) widget);
-}
-
-static void ms_disconnect_sigc(GObject * /*obj*/, sigc::connection *connection) {
- connection->disconnect();
- delete connection;
+ ms_tb_selection_changed(NULL, widget);
}
-
/*
* Callback functions for user actions
*/
@@ -184,6 +178,8 @@ static void ms_col_changed(GtkAdjustment *adj, GObject * /*tbl*/ )
blocked = FALSE;
}
+static void mesh_toolbox_watch_ec(SPDesktop* dt, Inkscape::UI::Tools::ToolBase* ec, GObject* holder);
+
/**
* Mesh auxiliary toolbar construction and setup.
*
@@ -323,35 +319,43 @@ void sp_mesh_toolbox_prep(SPDesktop * desktop, GtkActionGroup* mainActions, GObj
g_signal_connect( holder, "destroy", G_CALLBACK(delete_prefspusher), pusher);
}
-
- Inkscape::Selection *selection = sp_desktop_selection (desktop);
- SPDocument *document = sp_desktop_document (desktop);
-
g_object_set_data(holder, "desktop", desktop);
- // connect to selection modified and changed signals
- sigc::connection *conn1 = new sigc::connection(
- selection->connectChanged(sigc::bind(sigc::ptr_fun(&ms_tb_selection_changed), (gpointer) holder)));
- sigc::connection *conn2 = new sigc::connection(
- selection->connectModified(sigc::bind(sigc::ptr_fun(&ms_tb_selection_modified), (gpointer) holder)));
- sigc::connection *conn3 = new sigc::connection(
- desktop->connectToolSubselectionChanged( sigc::bind(sigc::ptr_fun(&ms_drag_selection_changed), (gpointer) holder)));
-
- // when holder is destroyed, disconnect
- g_signal_connect(G_OBJECT(holder), "destroy", G_CALLBACK(ms_disconnect_sigc), conn1);
- g_signal_connect(G_OBJECT(holder), "destroy", G_CALLBACK(ms_disconnect_sigc), conn2);
- g_signal_connect(G_OBJECT(holder), "destroy", G_CALLBACK(ms_disconnect_sigc), conn3);
-
- // connect to release and modified signals of the defs (i.e. when someone changes mesh)
- sigc::connection *release_connection = new sigc::connection();
- *release_connection = document->getDefs()->connectRelease(sigc::bind<1>(sigc::ptr_fun(&ms_defs_release), GTK_WIDGET(holder)));
- sigc::connection *modified_connection = new sigc::connection();
- *modified_connection = document->getDefs()->connectModified(sigc::bind<2>(sigc::ptr_fun(&ms_defs_modified), GTK_WIDGET(holder)));
-
- // when holder is destroyed, disconnect
- g_signal_connect(G_OBJECT(holder), "destroy", G_CALLBACK(ms_disconnect_sigc), release_connection);
- g_signal_connect(G_OBJECT(holder), "destroy", G_CALLBACK(ms_disconnect_sigc), modified_connection);
+ desktop->connectEventContextChanged(sigc::bind(sigc::ptr_fun(mesh_toolbox_watch_ec), holder));
+}
+static void mesh_toolbox_watch_ec(SPDesktop* desktop, Inkscape::UI::Tools::ToolBase* ec, GObject* holder)
+{
+ static sigc::connection c_selection_changed;
+ static sigc::connection c_selection_modified;
+ static sigc::connection c_subselection_changed;
+ static sigc::connection c_defs_release;
+ static sigc::connection c_defs_modified;
+
+ if (SP_IS_MESH_CONTEXT(ec)) {
+ // connect to selection modified and changed signals
+ Inkscape::Selection *selection = sp_desktop_selection (desktop);
+ SPDocument *document = sp_desktop_document (desktop);
+
+ c_selection_changed = selection->connectChanged(sigc::bind(sigc::ptr_fun(&ms_tb_selection_changed), holder));
+ c_selection_modified = selection->connectModified(sigc::bind(sigc::ptr_fun(&ms_tb_selection_modified), holder));
+ c_subselection_changed = desktop->connectToolSubselectionChanged(sigc::bind(sigc::ptr_fun(&ms_drag_selection_changed), holder));
+
+ c_defs_release = document->getDefs()->connectRelease(sigc::bind<1>(sigc::ptr_fun(&ms_defs_release), holder));
+ c_defs_modified = document->getDefs()->connectModified(sigc::bind<2>(sigc::ptr_fun(&ms_defs_modified), holder));
+ ms_tb_selection_changed(selection, holder);
+ } else {
+ if (c_selection_changed)
+ c_selection_changed.disconnect();
+ if (c_selection_modified)
+ c_selection_modified.disconnect();
+ if (c_subselection_changed)
+ c_subselection_changed.disconnect();
+ if (c_defs_release)
+ c_defs_release.disconnect();
+ if (c_defs_modified)
+ c_defs_modified.disconnect();
+ }
}
/*
diff --git a/src/widgets/node-toolbar.cpp b/src/widgets/node-toolbar.cpp
index 53161857a..467325d08 100644
--- a/src/widgets/node-toolbar.cpp
+++ b/src/widgets/node-toolbar.cpp
@@ -31,12 +31,11 @@
#include "ui/tool/multi-path-manipulator.h"
#include <glibmm/i18n.h>
#include "node-toolbar.h"
-#include "connection-pool.h"
#include "desktop-handles.h"
#include "desktop.h"
#include "document-undo.h"
-#include "ege-adjustment-action.h"
-#include "ink-action.h"
+#include "widgets/ege-adjustment-action.h"
+#include "widgets/ink-action.h"
#include "inkscape.h"
#include "preferences.h"
#include "selection-chemistry.h"
@@ -229,6 +228,7 @@ static void sp_node_toolbox_coord_changed(gpointer /*shape_editor*/, GObject *tb
return;
}
Unit const *unit = tracker->getActiveUnit();
+ g_return_if_fail(unit != NULL);
NodeTool *nt = get_node_tool();
if (!nt || !(nt->_selected_nodes) ||nt->_selected_nodes->empty()) {
@@ -270,7 +270,7 @@ static void sp_node_path_value_changed(GtkAdjustment *adj, GObject *tbl, Geom::D
}
// quit if run by the attr_changed listener
- if (g_object_get_data( tbl, "freeze" )) {
+ if (g_object_get_data( tbl, "freeze" ) || tracker->isUpdating()) {
return;
}
@@ -321,7 +321,7 @@ static void sp_node_toolbox_sel_modified(Inkscape::Selection *selection, guint /
sp_node_toolbox_sel_changed (selection, tbl);
}
-
+static void node_toolbox_watch_ec(SPDesktop* dt, Inkscape::UI::Tools::ToolBase* ec, GObject* holder);
//################################
//## Node Editing Toolbox ##
@@ -614,32 +614,33 @@ void sp_node_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObje
gtk_action_group_add_action( mainActions, act );
}
-
sp_node_toolbox_sel_changed(sp_desktop_selection(desktop), holder);
+ desktop->connectEventContextChanged(sigc::bind(sigc::ptr_fun(node_toolbox_watch_ec), holder));
- //watch selection
- Inkscape::ConnectionPool* pool = Inkscape::ConnectionPool::new_connection_pool ("ISNodeToolbox");
-
- sigc::connection *c_selection_changed =
- new sigc::connection (sp_desktop_selection (desktop)->connectChanged
- (sigc::bind (sigc::ptr_fun (sp_node_toolbox_sel_changed), holder)));
- pool->add_connection ("selection-changed", c_selection_changed);
-
- sigc::connection *c_selection_modified =
- new sigc::connection (sp_desktop_selection (desktop)->connectModified
- (sigc::bind (sigc::ptr_fun (sp_node_toolbox_sel_modified), holder)));
- pool->add_connection ("selection-modified", c_selection_modified);
-
- sigc::connection *c_subselection_changed =
- new sigc::connection (desktop->connectToolSubselectionChanged
- (sigc::bind (sigc::ptr_fun (sp_node_toolbox_coord_changed), holder)));
- pool->add_connection ("tool-subselection-changed", c_subselection_changed);
+} // end of sp_node_toolbox_prep()
- Inkscape::ConnectionPool::connect_destroy (G_OBJECT (holder), pool);
+static void node_toolbox_watch_ec(SPDesktop* desktop, Inkscape::UI::Tools::ToolBase* ec, GObject* holder)
+{
+ static sigc::connection c_selection_changed;
+ static sigc::connection c_selection_modified;
+ static sigc::connection c_subselection_changed;
- g_signal_connect( holder, "destroy", G_CALLBACK(purge_repr_listener), holder );
-} // end of sp_node_toolbox_prep()
+ if (INK_IS_NODE_TOOL(ec)) {
+ // watch selection
+ c_selection_changed = sp_desktop_selection(desktop)->connectChanged(sigc::bind(sigc::ptr_fun(sp_node_toolbox_sel_changed), holder));
+ c_selection_modified = sp_desktop_selection(desktop)->connectModified(sigc::bind(sigc::ptr_fun(sp_node_toolbox_sel_modified), holder));
+ c_subselection_changed = desktop->connectToolSubselectionChanged(sigc::bind(sigc::ptr_fun(sp_node_toolbox_coord_changed), holder));
+ sp_node_toolbox_sel_changed(sp_desktop_selection(desktop), holder);
+ } else {
+ if (c_selection_changed)
+ c_selection_changed.disconnect();
+ if (c_selection_modified)
+ c_selection_modified.disconnect();
+ if (c_subselection_changed)
+ c_subselection_changed.disconnect();
+ }
+}
/*
diff --git a/src/widgets/paint-selector.cpp b/src/widgets/paint-selector.cpp
index 9466c875e..6ef910f61 100644
--- a/src/widgets/paint-selector.cpp
+++ b/src/widgets/paint-selector.cpp
@@ -29,14 +29,15 @@
#endif
#include "widgets/swatch-selector.h"
-#include "../sp-pattern.h"
+#include "sp-pattern.h"
#include <glibmm/i18n.h>
-#include "../widgets/icon.h"
+#include "widgets/icon.h"
#include "widgets/widget-sizes.h"
#include "xml/repr.h"
#include "sp-color-notebook.h"
#include "sp-linear-gradient.h"
+#include "sp-mesh-gradient.h"
#include "sp-radial-gradient.h"
/* fixme: Move it from dialogs to here */
#include "gradient-selector.h"
@@ -71,8 +72,6 @@ enum {
LAST_SIGNAL
};
-static void sp_paint_selector_class_init(SPPaintSelectorClass *klass);
-static void sp_paint_selector_init(SPPaintSelector *slider);
static void sp_paint_selector_dispose(GObject *object);
static GtkWidget *sp_paint_selector_style_button_add(SPPaintSelector *psel, gchar const *px, SPPaintSelector::Mode mode, gchar const *tip);
@@ -91,7 +90,6 @@ static void sp_paint_selector_set_mode_unset(SPPaintSelector *psel);
static void sp_paint_selector_set_style_buttons(SPPaintSelector *psel, GtkWidget *active);
-static GtkVBoxClass *parent_class;
static guint psel_signals[LAST_SIGNAL] = {0};
#ifdef SP_PS_VERBOSE
@@ -113,10 +111,13 @@ static gchar const* modeStrings[] = {
#endif
-static bool isPaintModeGradient( SPPaintSelector::Mode mode )
+static bool isPaintModeGradient(SPPaintSelector::Mode mode)
{
bool isGrad = (mode == SPPaintSelector::MODE_GRADIENT_LINEAR) ||
(mode == SPPaintSelector::MODE_GRADIENT_RADIAL) ||
+#ifdef WITH_MESH
+ (mode == SPPaintSelector::MODE_GRADIENT_MESH) ||
+#endif
(mode == SPPaintSelector::MODE_SWATCH);
return isGrad;
@@ -136,34 +137,17 @@ static SPGradientSelector *getGradientFromData(SPPaintSelector const *psel)
return grad;
}
-GType sp_paint_selector_get_type(void)
-{
- static GType type = 0;
- if (!type) {
- GTypeInfo info = {
- sizeof(SPPaintSelectorClass),
- 0, // base_init
- 0, // base_finalize
- (GClassInitFunc)sp_paint_selector_class_init,
- 0, // class_finalize
- 0, // class_data
- sizeof(SPPaintSelector),
- 0, // n_preallocs
- (GInstanceInitFunc)sp_paint_selector_init,
- 0 // value_table
- };
- type = g_type_register_static(GTK_TYPE_VBOX, "SPPaintSelector", &info, static_cast<GTypeFlags>(0));
- }
- return type;
-}
+#if GTK_CHECK_VERSION(3,0,0)
+G_DEFINE_TYPE(SPPaintSelector, sp_paint_selector, GTK_TYPE_BOX);
+#else
+G_DEFINE_TYPE(SPPaintSelector, sp_paint_selector, GTK_TYPE_VBOX);
+#endif
static void
sp_paint_selector_class_init(SPPaintSelectorClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS(klass);
- parent_class = GTK_VBOX_CLASS(g_type_class_peek_parent(klass));
-
psel_signals[MODE_CHANGED] = g_signal_new("mode_changed",
G_TYPE_FROM_CLASS(object_class),
(GSignalFlags)(G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE),
@@ -216,6 +200,10 @@ sp_paint_selector_class_init(SPPaintSelectorClass *klass)
static void
sp_paint_selector_init(SPPaintSelector *psel)
{
+#if GTK_CHECK_VERSION(3,0,0)
+ gtk_orientable_set_orientation(GTK_ORIENTABLE(psel), GTK_ORIENTATION_VERTICAL);
+#endif
+
psel->mode = static_cast<SPPaintSelector::Mode>(-1); // huh? do you mean 0xff? -- I think this means "not in the enum"
/* Paint style button box */
@@ -238,6 +226,10 @@ sp_paint_selector_init(SPPaintSelector *psel)
SPPaintSelector::MODE_GRADIENT_LINEAR, _("Linear gradient"));
psel->radial = sp_paint_selector_style_button_add(psel, INKSCAPE_ICON("paint-gradient-radial"),
SPPaintSelector::MODE_GRADIENT_RADIAL, _("Radial gradient"));
+#ifdef WITH_MESH
+ psel->mesh = sp_paint_selector_style_button_add(psel, INKSCAPE_ICON("paint-gradient-mesh"),
+ SPPaintSelector::MODE_GRADIENT_MESH, _("Mesh gradient"));
+#endif
psel->pattern = sp_paint_selector_style_button_add(psel, INKSCAPE_ICON("paint-pattern"),
SPPaintSelector::MODE_PATTERN, _("Pattern"));
psel->swatch = sp_paint_selector_style_button_add(psel, INKSCAPE_ICON("paint-swatch"),
@@ -314,8 +306,8 @@ static void sp_paint_selector_dispose(GObject *object)
// clean up our long-living pattern menu
g_object_set_data(G_OBJECT(psel),"patternmenu",NULL);
- if ((G_OBJECT_CLASS(parent_class))->dispose)
- (* (G_OBJECT_CLASS(parent_class))->dispose)(object);
+ if ((G_OBJECT_CLASS(sp_paint_selector_parent_class))->dispose)
+ (G_OBJECT_CLASS(sp_paint_selector_parent_class))->dispose(object);
}
static GtkWidget *sp_paint_selector_style_button_add(SPPaintSelector *psel,
@@ -413,6 +405,9 @@ void SPPaintSelector::setMode(Mode mode)
break;
case MODE_GRADIENT_LINEAR:
case MODE_GRADIENT_RADIAL:
+#ifdef WITH_MESH
+ case MODE_GRADIENT_MESH:
+#endif
sp_paint_selector_set_mode_gradient(this, mode);
break;
case MODE_PATTERN:
@@ -511,6 +506,21 @@ void SPPaintSelector::setGradientRadial(SPGradient *vector)
gsel->setVector((vector) ? vector->document : 0, vector);
}
+#ifdef WITH_MESH
+void SPPaintSelector::setGradientMesh(SPGradient *vector)
+{
+#ifdef SP_PS_VERBOSE
+ g_print("PaintSelector set GRADIENT MESH\n");
+#endif
+ setMode(MODE_GRADIENT_RADIAL);
+
+ SPGradientSelector *gsel = getGradientFromData(this);
+
+ gsel->setMode(SPGradientSelector::MODE_MESH);
+ gsel->setVector((vector) ? vector->document : 0, vector);
+}
+#endif
+
void SPPaintSelector::setGradientProperties( SPGradientUnits units, SPGradientSpread spread )
{
g_return_if_fail(isPaintModeGradient(mode));
@@ -665,8 +675,8 @@ static void sp_paint_selector_set_mode_color(SPPaintSelector *psel, SPPaintSelec
/* Create new color selector */
/* Create vbox */
#if GTK_CHECK_VERSION(3,0,0)
- GtkWidget *vb = gtk_box_new(GTK_ORIENTATION_VERTICAL, 4);
- gtk_box_set_homogeneous(GTK_BOX(vb), FALSE);
+ GtkWidget *vb = gtk_box_new(GTK_ORIENTATION_VERTICAL, 4);
+ gtk_box_set_homogeneous(GTK_BOX(vb), FALSE);
#else
GtkWidget *vb = gtk_vbox_new(FALSE, 4);
#endif
@@ -728,9 +738,14 @@ static void sp_paint_selector_set_mode_gradient(SPPaintSelector *psel, SPPaintSe
if (mode == SPPaintSelector::MODE_GRADIENT_LINEAR) {
sp_paint_selector_set_style_buttons(psel, psel->gradient);
- } else {
+ } else if (mode == SPPaintSelector::MODE_GRADIENT_RADIAL) {
sp_paint_selector_set_style_buttons(psel, psel->radial);
}
+#ifdef WITH_MESH
+ else {
+ sp_paint_selector_set_style_buttons(psel, psel->mesh);
+ }
+#endif
gtk_widget_set_sensitive(psel->style, TRUE);
if ((psel->mode == SPPaintSelector::MODE_GRADIENT_LINEAR) || (psel->mode == SPPaintSelector::MODE_GRADIENT_RADIAL)) {
@@ -756,10 +771,17 @@ static void sp_paint_selector_set_mode_gradient(SPPaintSelector *psel, SPPaintSe
SP_GRADIENT_SELECTOR(gsel)->setMode(SPGradientSelector::MODE_LINEAR);
//sp_gradient_selector_set_mode(SP_GRADIENT_SELECTOR(gsel), SP_GRADIENT_SELECTOR_MODE_LINEAR);
gtk_label_set_markup(GTK_LABEL(psel->label), _("<b>Linear gradient</b>"));
- } else {
+ } else if (mode == SPPaintSelector::MODE_GRADIENT_LINEAR) {
SP_GRADIENT_SELECTOR(gsel)->setMode(SPGradientSelector::MODE_RADIAL);
gtk_label_set_markup(GTK_LABEL(psel->label), _("<b>Radial gradient</b>"));
}
+#ifdef WITH_MESH
+ else {
+ SP_GRADIENT_SELECTOR(gsel)->setMode(SPGradientSelector::MODE_RADIAL);
+ gtk_label_set_markup(GTK_LABEL(psel->label), _("<b>Mesh gradient</b>"));
+ }
+#endif
+
#ifdef SP_PS_VERBOSE
g_print("Gradient req\n");
#endif
@@ -772,6 +794,9 @@ sp_paint_selector_set_style_buttons(SPPaintSelector *psel, GtkWidget *active)
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(psel->solid), (active == psel->solid));
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(psel->gradient), (active == psel->gradient));
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(psel->radial), (active == psel->radial));
+#ifdef WITH_MESH
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(psel->mesh), (active == psel->mesh));
+#endif
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(psel->pattern), (active == psel->pattern));
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(psel->swatch), (active == psel->swatch));
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(psel->unset), (active == psel->unset));
@@ -1004,8 +1029,8 @@ static void sp_paint_selector_set_mode_pattern(SPPaintSelector *psel, SPPaintSel
/* Create vbox */
#if GTK_CHECK_VERSION(3,0,0)
- tbl = gtk_box_new(GTK_ORIENTATION_VERTICAL, 4);
- gtk_box_set_homogeneous(GTK_BOX(tbl), FALSE);
+ tbl = gtk_box_new(GTK_ORIENTATION_VERTICAL, 4);
+ gtk_box_set_homogeneous(GTK_BOX(tbl), FALSE);
#else
tbl = gtk_vbox_new(FALSE, 4);
#endif
@@ -1218,6 +1243,10 @@ SPPaintSelector::Mode SPPaintSelector::getModeForStyle(SPStyle const & style, Fi
mode = MODE_GRADIENT_LINEAR;
} else if (SP_IS_RADIALGRADIENT(server)) {
mode = MODE_GRADIENT_RADIAL;
+#ifdef WITH_MESH
+ } else if (SP_IS_MESHGRADIENT(server)) {
+ mode = MODE_GRADIENT_MESH;
+#endif
} else if (SP_IS_PATTERN(server)) {
mode = MODE_PATTERN;
} else {
diff --git a/src/widgets/paint-selector.h b/src/widgets/paint-selector.h
index d3b3f4116..788aa673e 100644
--- a/src/widgets/paint-selector.h
+++ b/src/widgets/paint-selector.h
@@ -12,7 +12,6 @@
*
*/
-#include <glib.h>
#include <gtk/gtk.h>
#include "color.h"
@@ -23,7 +22,7 @@
class SPGradient;
class SPDesktop;
class SPPattern;
-struct SPStyle;
+class SPStyle;
#define SP_TYPE_PAINT_SELECTOR (sp_paint_selector_get_type ())
#define SP_PAINT_SELECTOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), SP_TYPE_PAINT_SELECTOR, SPPaintSelector))
@@ -35,7 +34,11 @@ struct SPStyle;
* Generic paint selector widget.
*/
struct SPPaintSelector {
+#if GTK_CHECK_VERSION(3,0,0)
+ GtkBox vbox;
+#else
GtkVBox vbox;
+#endif
enum Mode {
MODE_EMPTY,
@@ -45,6 +48,9 @@ struct SPPaintSelector {
MODE_COLOR_CMYK,
MODE_GRADIENT_LINEAR,
MODE_GRADIENT_RADIAL,
+#ifdef WITH_MESH
+ MODE_GRADIENT_MESH,
+#endif
MODE_PATTERN,
MODE_SWATCH,
MODE_UNSET
@@ -64,6 +70,9 @@ struct SPPaintSelector {
GtkWidget *solid;
GtkWidget *gradient;
GtkWidget *radial;
+#ifdef WITH_MESH
+ GtkWidget *mesh;
+#endif
GtkWidget *pattern;
GtkWidget *swatch;
GtkWidget *unset;
@@ -88,6 +97,9 @@ struct SPPaintSelector {
void setGradientLinear( SPGradient *vector );
void setGradientRadial( SPGradient *vector );
+#ifdef WITH_MESH
+ void setGradientMesh(SPGradient *vector);
+#endif
void setSwatch( SPGradient *vector );
void setGradientProperties( SPGradientUnits units, SPGradientSpread spread );
@@ -109,7 +121,11 @@ enum {COMBO_COL_LABEL=0, COMBO_COL_STOCK=1, COMBO_COL_PATTERN=2, COMBO_COL_SEP=3
/// The SPPaintSelector vtable
struct SPPaintSelectorClass {
+#if GTK_CHECK_VERSION(3,0,0)
+ GtkBoxClass parent_class;
+#else
GtkVBoxClass parent_class;
+#endif
void (* mode_changed) (SPPaintSelector *psel, SPPaintSelector::Mode mode);
diff --git a/src/widgets/paintbucket-toolbar.cpp b/src/widgets/paintbucket-toolbar.cpp
index e20811de8..d8edeb9f6 100644
--- a/src/widgets/paintbucket-toolbar.cpp
+++ b/src/widgets/paintbucket-toolbar.cpp
@@ -33,8 +33,8 @@
#include "paintbucket-toolbar.h"
#include "desktop.h"
#include "document-undo.h"
-#include "ege-adjustment-action.h"
-#include "ege-select-one-action.h"
+#include "widgets/ege-adjustment-action.h"
+#include "widgets/ege-select-one-action.h"
#include "preferences.h"
#include "toolbox.h"
#include "ui/icon-names.h"
@@ -83,6 +83,8 @@ static void paintbucket_offset_changed(GtkAdjustment *adj, GObject *tbl)
// Don't adjust the offset value because we're saving the
// unit and it'll be correctly handled on load.
prefs->setDouble("/tools/paintbucket/offset", (gdouble)gtk_adjustment_get_value(adj));
+
+ g_return_if_fail(unit != NULL);
prefs->setString("/tools/paintbucket/offsetunits", unit->abbr);
}
diff --git a/src/widgets/pencil-toolbar.cpp b/src/widgets/pencil-toolbar.cpp
index 1e69e2f42..404f62848 100644
--- a/src/widgets/pencil-toolbar.cpp
+++ b/src/widgets/pencil-toolbar.cpp
@@ -33,12 +33,12 @@
#include "pencil-toolbar.h"
#include "desktop.h"
#include "document-undo.h"
-#include "ege-adjustment-action.h"
-#include "ege-select-one-action.h"
-#include "ink-action.h"
+#include "widgets/ege-adjustment-action.h"
+#include "widgets/ege-select-one-action.h"
+#include "widgets/ink-action.h"
#include "preferences.h"
#include "toolbox.h"
-#include "tools-switch.h"
+#include "ui/tools-switch.h"
#include "ui/icon-names.h"
#include "ui/tools/pen-tool.h"
#include "ui/uxmanager.h"
@@ -104,7 +104,12 @@ static void sp_add_freehand_mode_toggle(GtkActionGroup* mainActions, GObject* ho
1, _("Create Spiro path"),
2, INKSCAPE_ICON("path-mode-spiro"),
-1 );
-
+ gtk_list_store_append( model, &iter );
+ gtk_list_store_set( model, &iter,
+ 0, _("BSpline"),
+ 1, _("Create BSpline path"),
+ 2, INKSCAPE_ICON("path-mode-bspline"),
+ -1 );
if (!tool_is_pencil) {
gtk_list_store_append( model, &iter );
gtk_list_store_set( model, &iter,
@@ -152,7 +157,7 @@ static void freehand_change_shape(EgeSelectOneAction* act, GObject *dataKludge)
static GList * freehand_shape_dropdown_items_list() {
GList *glist = NULL;
- glist = g_list_append (glist, _("None"));
+ glist = g_list_append (glist, const_cast<gchar *>(C_("Freehand shape", "None")));
glist = g_list_append (glist, _("Triangle in"));
glist = g_list_append (glist, _("Triangle out"));
glist = g_list_append (glist, _("Ellipse"));
diff --git a/src/widgets/rect-toolbar.cpp b/src/widgets/rect-toolbar.cpp
index 6996786e3..b6b7e435d 100644
--- a/src/widgets/rect-toolbar.cpp
+++ b/src/widgets/rect-toolbar.cpp
@@ -34,9 +34,9 @@
#include "desktop-handles.h"
#include "desktop.h"
#include "document-undo.h"
-#include "ege-adjustment-action.h"
-#include "ege-output-action.h"
-#include "ink-action.h"
+#include "widgets/ege-adjustment-action.h"
+#include "widgets/ege-output-action.h"
+#include "widgets/ink-action.h"
#include "inkscape.h"
#include "preferences.h"
#include "selection.h"
@@ -44,6 +44,7 @@
#include "sp-rect.h"
#include "toolbox.h"
#include "ui/icon-names.h"
+#include "ui/tools/rect-tool.h"
#include "ui/uxmanager.h"
#include "ui/widget/unit-tracker.h"
#include "util/units.h"
@@ -87,6 +88,7 @@ static void sp_rtb_value_changed(GtkAdjustment *adj, GObject *tbl, gchar const *
UnitTracker* tracker = reinterpret_cast<UnitTracker*>(g_object_get_data( tbl, "tracker" ));
Unit const *unit = tracker->getActiveUnit();
+ g_return_if_fail(unit != NULL);
if (DocumentUndo::getUndoSensitive(sp_desktop_document(desktop))) {
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
@@ -95,7 +97,7 @@ static void sp_rtb_value_changed(GtkAdjustment *adj, GObject *tbl, gchar const *
}
// quit if run by the attr_changed listener
- if (g_object_get_data( tbl, "freeze" )) {
+ if (g_object_get_data( tbl, "freeze" ) || tracker->isUpdating()) {
return;
}
@@ -180,6 +182,7 @@ static void rect_tb_event_attr_changed(Inkscape::XML::Node * /*repr*/, gchar con
UnitTracker* tracker = reinterpret_cast<UnitTracker*>( g_object_get_data( tbl, "tracker" ) );
Unit const *unit = tracker->getActiveUnit();
Unit const *doc_unit = sp_desktop_namedview(SP_ACTIVE_DESKTOP)->doc_units;
+ g_return_if_fail(unit != NULL);
gpointer item = g_object_get_data( tbl, "item" );
if (item && SP_IS_RECT(item)) {
@@ -286,6 +289,7 @@ static void sp_rect_toolbox_selection_changed(Inkscape::Selection *selection, GO
}
}
+static void rect_toolbox_watch_ec(SPDesktop* dt, Inkscape::UI::Tools::ToolBase* ec, GObject* holder);
void sp_rect_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder)
{
@@ -392,13 +396,22 @@ void sp_rect_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObje
g_object_set_data( holder, "single", GINT_TO_POINTER(TRUE) );
sp_rtb_sensitivize( holder );
- sigc::connection *connection = new sigc::connection(
- sp_desktop_selection(desktop)->connectChanged(sigc::bind(sigc::ptr_fun(sp_rect_toolbox_selection_changed), holder))
- );
- g_signal_connect( holder, "destroy", G_CALLBACK(delete_connection), connection );
+ desktop->connectEventContextChanged(sigc::bind(sigc::ptr_fun(rect_toolbox_watch_ec), holder));
g_signal_connect( holder, "destroy", G_CALLBACK(purge_repr_listener), holder );
}
+static void rect_toolbox_watch_ec(SPDesktop* desktop, Inkscape::UI::Tools::ToolBase* ec, GObject* holder)
+{
+ static sigc::connection changed;
+
+ // TODO fixme: use of dynamic_cast<> seems wrong here.
+ if (dynamic_cast<Inkscape::UI::Tools::RectTool *>(ec)) {
+ changed = sp_desktop_selection(desktop)->connectChanged(sigc::bind(sigc::ptr_fun(sp_rect_toolbox_selection_changed), holder));
+ } else {
+ if (changed)
+ changed.disconnect();
+ }
+}
/*
Local Variables:
@@ -409,4 +422,4 @@ void sp_rect_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObje
fill-column:99
End:
*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8 :
diff --git a/src/widgets/ruler.cpp b/src/widgets/ruler.cpp
index 5d5151343..8e818843d 100644
--- a/src/widgets/ruler.cpp
+++ b/src/widgets/ruler.cpp
@@ -1394,7 +1394,7 @@ sp_ruler_draw_ticks (SPRuler *ruler)
(label_spacing_px > 6*digit_height || tick_index%2 == 0 || cur == 0) &&
(label_spacing_px > 3*digit_height || tick_index%4 == 0 || cur == 0))
{
- if (fabs((int)cur) >= 2000 && (((int) cur)/1000)*1000 == ((int) cur))
+ if (std::abs((int)cur) >= 2000 && (((int) cur)/1000)*1000 == ((int) cur))
sprintf (unit_str, "%dk", ((int) cur)/1000);
else
sprintf (unit_str, "%d", (int) cur);
diff --git a/src/widgets/select-toolbar.cpp b/src/widgets/select-toolbar.cpp
index 284e436bf..08a46354e 100644
--- a/src/widgets/select-toolbar.cpp
+++ b/src/widgets/select-toolbar.cpp
@@ -26,10 +26,10 @@
#include "display/sp-canvas.h"
#include "document-undo.h"
#include "document.h"
-#include "ege-adjustment-action.h"
+#include "widgets/ege-adjustment-action.h"
#include "helper/action-context.h"
#include "helper/action.h"
-#include "ink-action.h"
+#include "widgets/ink-action.h"
#include "inkscape.h"
#include "message-stack.h"
#include "preferences.h"
@@ -73,6 +73,7 @@ sp_selection_layout_widget_update(SPWidget *spw, Inkscape::Selection *sel)
if ( bbox ) {
UnitTracker *tracker = reinterpret_cast<UnitTracker*>(g_object_get_data(G_OBJECT(spw), "tracker"));
Unit const *unit = tracker->getActiveUnit();
+ g_return_if_fail(unit != NULL);
struct { char const *key; double val; } const keyval[] = {
{ "X", bbox->min()[X] },
@@ -178,6 +179,7 @@ sp_object_layout_any_value_changed(GtkAdjustment *adj, SPWidget *spw)
gdouble xrel = 0;
gdouble yrel = 0;
Unit const *unit = tracker->getActiveUnit();
+ g_return_if_fail(unit != NULL);
GtkAdjustment* a_x = GTK_ADJUSTMENT( g_object_get_data( G_OBJECT(spw), "X" ) );
GtkAdjustment* a_y = GTK_ADJUSTMENT( g_object_get_data( G_OBJECT(spw), "Y" ) );
diff --git a/src/widgets/sp-color-icc-selector.cpp b/src/widgets/sp-color-icc-selector.cpp
index 53e73dd57..6e910c582 100644
--- a/src/widgets/sp-color-icc-selector.cpp
+++ b/src/widgets/sp-color-icc-selector.cpp
@@ -10,7 +10,7 @@
#include <set>
#include <vector>
-#include "../dialogs/dialog-events.h"
+#include "ui/dialog-events.h"
#include "sp-color-icc-selector.h"
#include "sp-color-scales.h"
#include "sp-color-slider.h"
@@ -67,10 +67,7 @@ extern guint update_in_progress;
G_BEGIN_DECLS
-static void sp_color_icc_selector_class_init (SPColorICCSelectorClass *klass);
-static void sp_color_icc_selector_init (SPColorICCSelector *cs);
static void sp_color_icc_selector_dispose(GObject *object);
-
static void sp_color_icc_selector_show_all (GtkWidget *widget);
static void sp_color_icc_selector_hide(GtkWidget *widget);
@@ -161,9 +158,6 @@ public:
#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
};
-
-static SPColorSelectorClass *parent_class;
-
#define XPAD 4
#define YPAD 1
@@ -205,8 +199,14 @@ void attachToGridOrTable(GtkWidget *parent,
guint ypadding = YPAD)
{
#if GTK_CHECK_VERSION(3,0,0)
+ #if GTK_CHECK_VERSION(3,12,0)
+ gtk_widget_set_margin_start( child, xpadding );
+ gtk_widget_set_margin_end( child, xpadding );
+ #else
gtk_widget_set_margin_left( child, xpadding );
gtk_widget_set_margin_right( child, xpadding );
+ #endif
+
gtk_widget_set_margin_top( child, ypadding );
gtk_widget_set_margin_bottom( child, ypadding );
if (hexpand) {
@@ -227,30 +227,7 @@ void attachToGridOrTable(GtkWidget *parent,
} // namespace
-GType sp_color_icc_selector_get_type(void)
-{
- static GType type = 0;
- if (!type) {
- static const GTypeInfo info = {
- sizeof (SPColorICCSelectorClass),
- NULL, // base_init
- NULL, // base_finalize
- (GClassInitFunc) sp_color_icc_selector_class_init,
- NULL, // class_finalize
- NULL, // class_data
- sizeof (SPColorICCSelector),
- 0, // n_preallocs
- (GInstanceInitFunc) sp_color_icc_selector_init,
- 0, // value_table
- };
-
- type = g_type_register_static (SP_TYPE_COLOR_SELECTOR,
- "SPColorICCSelector",
- &info,
- static_cast< GTypeFlags > (0) );
- }
- return type;
-}
+G_DEFINE_TYPE(SPColorICCSelector, sp_color_icc_selector, SP_TYPE_COLOR_SELECTOR);
static void sp_color_icc_selector_class_init(SPColorICCSelectorClass *klass)
{
@@ -259,8 +236,6 @@ static void sp_color_icc_selector_class_init(SPColorICCSelectorClass *klass)
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass);
SPColorSelectorClass *selector_class = SP_COLOR_SELECTOR_CLASS (klass);
- parent_class = SP_COLOR_SELECTOR_CLASS (g_type_class_peek_parent (klass));
-
selector_class->name = nameset;
selector_class->submode_count = 1;
@@ -599,8 +574,8 @@ void ColorICCSelector::init()
static void sp_color_icc_selector_dispose(GObject *object)
{
- if ((G_OBJECT_CLASS(parent_class))->dispose) {
- (* (G_OBJECT_CLASS(parent_class))->dispose)(object);
+ if (G_OBJECT_CLASS(sp_color_icc_selector_parent_class)->dispose) {
+ G_OBJECT_CLASS(sp_color_icc_selector_parent_class)->dispose(object);
}
}
diff --git a/src/widgets/sp-color-icc-selector.h b/src/widgets/sp-color-icc-selector.h
index f63ab0853..6cdaff639 100644
--- a/src/widgets/sp-color-icc-selector.h
+++ b/src/widgets/sp-color-icc-selector.h
@@ -2,8 +2,6 @@
#define SEEN_SP_COLOR_ICC_SELECTOR_H
#include <glib.h>
-#include <gtk/gtk.h>
-
#include "sp-color-selector.h"
namespace Inkscape {
diff --git a/src/widgets/sp-color-notebook.cpp b/src/widgets/sp-color-notebook.cpp
index e081f98e0..c7fa96efd 100644
--- a/src/widgets/sp-color-notebook.cpp
+++ b/src/widgets/sp-color-notebook.cpp
@@ -25,7 +25,7 @@
#include <gtk/gtk.h>
#include <glibmm/i18n.h>
-#include "../dialogs/dialog-events.h"
+#include "ui/dialog-events.h"
#include "../preferences.h"
#include "sp-color-notebook.h"
#include "spw-utilities.h"
@@ -38,7 +38,7 @@
#include "../profile-manager.h"
#include "color-profile.h"
#include "cms-system.h"
-#include "tools-switch.h"
+#include "ui/tools-switch.h"
#include "ui/tools/tool-base.h"
using Inkscape::CMSSystem;
@@ -53,46 +53,21 @@ struct SPColorNotebookTracker {
SPColorNotebook *backPointer;
};
-static void sp_color_notebook_class_init (SPColorNotebookClass *klass);
-static void sp_color_notebook_init (SPColorNotebook *colorbook);
static void sp_color_notebook_dispose(GObject *object);
static void sp_color_notebook_show_all (GtkWidget *widget);
static void sp_color_notebook_hide(GtkWidget *widget);
-static SPColorSelectorClass *parent_class;
-
#define XPAD 4
#define YPAD 1
-GType sp_color_notebook_get_type(void)
-{
- static GType type = 0;
- if (!type) {
- GTypeInfo info = {
- sizeof(SPColorNotebookClass),
- 0, // base_init
- 0, // base_finalize
- (GClassInitFunc)sp_color_notebook_class_init,
- 0, // class_finalize
- 0, // class_data
- sizeof(SPColorNotebook),
- 0, // n_preallocs
- (GInstanceInitFunc)sp_color_notebook_init,
- 0 // value_table
- };
- type = g_type_register_static(SP_TYPE_COLOR_SELECTOR, "SPColorNotebook", &info, static_cast<GTypeFlags>(0));
- }
- return type;
-}
+G_DEFINE_TYPE(SPColorNotebook, sp_color_notebook, SP_TYPE_COLOR_SELECTOR);
static void sp_color_notebook_class_init(SPColorNotebookClass *klass)
{
GObjectClass *object_class = reinterpret_cast<GObjectClass *>(klass);
GtkWidgetClass *widget_class = reinterpret_cast<GtkWidgetClass *>(klass);
- parent_class = SP_COLOR_SELECTOR_CLASS(g_type_class_peek_parent(klass));
-
object_class->dispose = sp_color_notebook_dispose;
widget_class->show_all = sp_color_notebook_show_all;
@@ -289,8 +264,13 @@ void ColorNotebook::init()
sp_set_font_size_smaller (_buttonbox);
#if GTK_CHECK_VERSION(3,0,0)
+ #if GTK_CHECK_VERSION(3,12,0)
+ gtk_widget_set_margin_start(_buttonbox, XPAD);
+ gtk_widget_set_margin_end(_buttonbox, XPAD);
+ #else
gtk_widget_set_margin_left(_buttonbox, XPAD);
gtk_widget_set_margin_right(_buttonbox, XPAD);
+ #endif
gtk_widget_set_margin_top(_buttonbox, YPAD);
gtk_widget_set_margin_bottom(_buttonbox, YPAD);
gtk_widget_set_hexpand(_buttonbox, TRUE);
@@ -306,8 +286,13 @@ void ColorNotebook::init()
row++;
#if GTK_CHECK_VERSION(3,0,0)
+ #if GTK_CHECK_VERSION(3,12,0)
+ gtk_widget_set_margin_start(_book, XPAD*2);
+ gtk_widget_set_margin_end(_book, XPAD*2);
+ #else
gtk_widget_set_margin_left(_book, XPAD*2);
gtk_widget_set_margin_right(_book, XPAD*2);
+ #endif
gtk_widget_set_margin_top(_book, YPAD);
gtk_widget_set_margin_bottom(_book, YPAD);
gtk_widget_set_hexpand(_book, TRUE);
@@ -434,8 +419,13 @@ void ColorNotebook::init()
#endif //defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
#if GTK_CHECK_VERSION(3,0,0)
+ #if GTK_CHECK_VERSION(3,12,0)
+ gtk_widget_set_margin_start(rgbabox, XPAD);
+ gtk_widget_set_margin_end(rgbabox, XPAD);
+ #else
gtk_widget_set_margin_left(rgbabox, XPAD);
gtk_widget_set_margin_right(rgbabox, XPAD);
+ #endif
gtk_widget_set_margin_top(rgbabox, YPAD);
gtk_widget_set_margin_bottom(rgbabox, YPAD);
gtk_grid_attach(GTK_GRID(table), rgbabox, 0, row, 2, 1);
@@ -457,8 +447,8 @@ void ColorNotebook::init()
static void sp_color_notebook_dispose(GObject *object)
{
- if (((GObjectClass *) (parent_class))->dispose)
- (* ((GObjectClass *) (parent_class))->dispose) (object);
+ if (G_OBJECT_CLASS(sp_color_notebook_parent_class)->dispose)
+ G_OBJECT_CLASS(sp_color_notebook_parent_class)->dispose(object);
}
ColorNotebook::~ColorNotebook()
diff --git a/src/widgets/sp-color-notebook.h b/src/widgets/sp-color-notebook.h
index 6e5111132..469bb56e8 100644
--- a/src/widgets/sp-color-notebook.h
+++ b/src/widgets/sp-color-notebook.h
@@ -12,14 +12,10 @@
* This code is in public domain
*/
-#include <gtk/gtk.h>
-#include "../color.h"
#include "sp-color-selector.h"
#include <glib.h>
-
-
struct SPColorNotebook;
class ColorNotebook: public ColorSelector
diff --git a/src/widgets/sp-color-scales.cpp b/src/widgets/sp-color-scales.cpp
index c3f9d511c..60ba62ec5 100644
--- a/src/widgets/sp-color-scales.cpp
+++ b/src/widgets/sp-color-scales.cpp
@@ -8,8 +8,9 @@
#include <math.h>
#include <gtk/gtk.h>
#include <glibmm/i18n.h>
-#include "../dialogs/dialog-events.h"
+#include "ui/dialog-events.h"
#include "sp-color-scales.h"
+#include "sp-color-slider.h"
#include "svg/svg-icc-color.h"
#define CSC_CHANNEL_R (1 << 0)
@@ -30,8 +31,6 @@
G_BEGIN_DECLS
-static void sp_color_scales_class_init (SPColorScalesClass *klass);
-static void sp_color_scales_init (SPColorScales *cs);
static void sp_color_scales_dispose(GObject *object);
static void sp_color_scales_show_all (GtkWidget *widget);
@@ -41,38 +40,12 @@ static const gchar *sp_color_scales_hue_map (void);
G_END_DECLS
-static SPColorSelectorClass *parent_class;
-
#define XPAD 4
#define YPAD 1
#define noDUMP_CHANGE_INFO 1
-GType
-sp_color_scales_get_type (void)
-{
- static GType type = 0;
- if (!type) {
- static const GTypeInfo info = {
- sizeof (SPColorScalesClass),
- NULL, /* base_init */
- NULL, /* base_finalize */
- (GClassInitFunc) sp_color_scales_class_init,
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof (SPColorScales),
- 0, /* n_preallocs */
- (GInstanceInitFunc) sp_color_scales_init,
- NULL
- };
-
- type = g_type_register_static (SP_TYPE_COLOR_SELECTOR,
- "SPColorScales",
- &info,
- static_cast< GTypeFlags > (0) );
- }
- return type;
-}
+G_DEFINE_TYPE(SPColorScales, sp_color_scales, SP_TYPE_COLOR_SELECTOR);
static void
sp_color_scales_class_init (SPColorScalesClass *klass)
@@ -82,8 +55,6 @@ sp_color_scales_class_init (SPColorScalesClass *klass)
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass);
SPColorSelectorClass *selector_class = SP_COLOR_SELECTOR_CLASS (klass);
- parent_class = SP_COLOR_SELECTOR_CLASS (g_type_class_peek_parent (klass));
-
selector_class->name = nameset;
selector_class->submode_count = 3;
@@ -151,8 +122,13 @@ void ColorScales::init()
gtk_widget_show (_l[i]);
#if GTK_CHECK_VERSION(3,0,0)
+ #if GTK_CHECK_VERSION(3,12,0)
+ gtk_widget_set_margin_start(_l[i], XPAD);
+ gtk_widget_set_margin_end(_l[i], XPAD);
+ #else
gtk_widget_set_margin_left(_l[i], XPAD);
gtk_widget_set_margin_right(_l[i], XPAD);
+ #endif
gtk_widget_set_margin_top(_l[i], YPAD);
gtk_widget_set_margin_bottom(_l[i], YPAD);
gtk_grid_attach(GTK_GRID(t), _l[i], 0, i, 1, 1);
@@ -167,8 +143,13 @@ void ColorScales::init()
gtk_widget_show (_s[i]);
#if GTK_CHECK_VERSION(3,0,0)
+ #if GTK_CHECK_VERSION(3,12,0)
+ gtk_widget_set_margin_start(_s[i], XPAD);
+ gtk_widget_set_margin_end(_s[i], XPAD);
+ #else
gtk_widget_set_margin_left(_s[i], XPAD);
gtk_widget_set_margin_right(_s[i], XPAD);
+ #endif
gtk_widget_set_margin_top(_s[i], YPAD);
gtk_widget_set_margin_bottom(_s[i], YPAD);
gtk_widget_set_hexpand(_s[i], TRUE);
@@ -184,8 +165,13 @@ void ColorScales::init()
gtk_widget_show (_b[i]);
#if GTK_CHECK_VERSION(3,0,0)
+ #if GTK_CHECK_VERSION(3,12,0)
+ gtk_widget_set_margin_start(_b[i], XPAD);
+ gtk_widget_set_margin_end(_b[i], XPAD);
+ #else
gtk_widget_set_margin_left(_b[i], XPAD);
gtk_widget_set_margin_right(_b[i], XPAD);
+ #endif
gtk_widget_set_margin_top(_b[i], YPAD);
gtk_widget_set_margin_bottom(_b[i], YPAD);
gtk_widget_set_halign(_b[i], GTK_ALIGN_CENTER);
@@ -214,8 +200,8 @@ void ColorScales::init()
static void sp_color_scales_dispose(GObject *object)
{
- if ((G_OBJECT_CLASS(parent_class))->dispose)
- (* (G_OBJECT_CLASS(parent_class))->dispose) (object);
+ if (G_OBJECT_CLASS(sp_color_scales_parent_class)->dispose)
+ G_OBJECT_CLASS(sp_color_scales_parent_class)->dispose(object);
}
static void
diff --git a/src/widgets/sp-color-scales.h b/src/widgets/sp-color-scales.h
index 3b11bc05e..72cbafa2f 100644
--- a/src/widgets/sp-color-scales.h
+++ b/src/widgets/sp-color-scales.h
@@ -2,15 +2,12 @@
#define SEEN_SP_COLOR_SCALES_H
#include <glib.h>
-#include <gtk/gtk.h>
-#include <color.h>
-#include <widgets/sp-color-slider.h>
#include <widgets/sp-color-selector.h>
-
struct SPColorScales;
struct SPColorScalesClass;
+struct SPColorSlider;
typedef enum {
SP_COLOR_SCALES_MODE_NONE = 0,
diff --git a/src/widgets/sp-color-selector.cpp b/src/widgets/sp-color-selector.cpp
index 6d62acecd..e97c36431 100644
--- a/src/widgets/sp-color-selector.cpp
+++ b/src/widgets/sp-color-selector.cpp
@@ -22,42 +22,20 @@ enum {
#define noDUMP_CHANGE_INFO
#define FOO_NAME(x) g_type_name( G_TYPE_FROM_INSTANCE(x) )
-static void sp_color_selector_class_init( SPColorSelectorClass *klass );
-static void sp_color_selector_init( SPColorSelector *csel );
static void sp_color_selector_dispose(GObject *object);
static void sp_color_selector_show_all( GtkWidget *widget );
static void sp_color_selector_hide( GtkWidget *widget );
-static GtkVBoxClass *parent_class;
static guint csel_signals[LAST_SIGNAL] = {0};
double ColorSelector::_epsilon = 1e-4;
-GType sp_color_selector_get_type( void )
-{
- static GType type = 0;
- if (!type) {
- static const GTypeInfo info = {
- sizeof(SPColorSelectorClass),
- NULL, /* base_init */
- NULL, /* base_finalize */
- (GClassInitFunc) sp_color_selector_class_init,
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof(SPColorSelector),
- 0, /* n_preallocs */
- (GInstanceInitFunc) sp_color_selector_init,
- NULL
- };
-
- type = g_type_register_static( GTK_TYPE_VBOX,
- "SPColorSelector",
- &info,
- static_cast<GTypeFlags>(0) );
- }
- return type;
-}
+#if GTK_CHECK_VERSION(3,0,0)
+G_DEFINE_TYPE(SPColorSelector, sp_color_selector, GTK_TYPE_BOX);
+#else
+G_DEFINE_TYPE(SPColorSelector, sp_color_selector, GTK_TYPE_VBOX);
+#endif
void sp_color_selector_class_init( SPColorSelectorClass *klass )
{
@@ -66,8 +44,6 @@ void sp_color_selector_class_init( SPColorSelectorClass *klass )
GtkWidgetClass *widget_class;
widget_class = GTK_WIDGET_CLASS(klass);
- parent_class = GTK_VBOX_CLASS( g_type_class_peek_parent(klass) );
-
csel_signals[GRABBED] = g_signal_new( "grabbed",
G_TYPE_FROM_CLASS(object_class),
(GSignalFlags)(G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE),
@@ -109,6 +85,10 @@ void sp_color_selector_class_init( SPColorSelectorClass *klass )
void sp_color_selector_init( SPColorSelector *csel )
{
+#if GTK_CHECK_VERSION(3,0,0)
+ gtk_orientable_set_orientation(GTK_ORIENTABLE(csel), GTK_ORIENTATION_VERTICAL);
+#endif
+
if ( csel->base )
{
csel->base->init();
@@ -125,8 +105,8 @@ void sp_color_selector_dispose(GObject *object)
csel->base = 0;
}
- if ( (G_OBJECT_CLASS(parent_class))->dispose ) {
- (* (G_OBJECT_CLASS(parent_class))->dispose)(object);
+ if ((G_OBJECT_CLASS(sp_color_selector_parent_class))->dispose ) {
+ (G_OBJECT_CLASS(sp_color_selector_parent_class))->dispose(object);
}
}
diff --git a/src/widgets/sp-color-selector.h b/src/widgets/sp-color-selector.h
index 616d5a9e7..30061774a 100644
--- a/src/widgets/sp-color-selector.h
+++ b/src/widgets/sp-color-selector.h
@@ -2,9 +2,7 @@
#define SEEN_SP_COLOR_SELECTOR_H
#include <gtk/gtk.h>
-#include "../color.h"
-
-#include <glib.h>
+#include "color.h"
struct SPColorSelector;
@@ -62,13 +60,21 @@ private:
#define SP_COLOR_SELECTOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SP_TYPE_COLOR_SELECTOR, SPColorSelectorClass))
struct SPColorSelector {
+#if GTK_CHECK_VERSION(3,0,0)
+ GtkBox vbox;
+#else
GtkVBox vbox;
+#endif
ColorSelector* base;
};
struct SPColorSelectorClass {
+#if GTK_CHECK_VERSION(3,0,0)
+ GtkBoxClass parent_class;
+#else
GtkVBoxClass parent_class;
+#endif
const gchar **name;
guint submode_count;
diff --git a/src/widgets/sp-color-slider.cpp b/src/widgets/sp-color-slider.cpp
index 9b13ba1c5..ab7e2cd84 100644
--- a/src/widgets/sp-color-slider.cpp
+++ b/src/widgets/sp-color-slider.cpp
@@ -12,6 +12,7 @@
#include <gtk/gtk.h>
#include "sp-color-scales.h"
+#include "sp-color-slider.h"
#include "preferences.h"
#define SLIDER_WIDTH 96
@@ -26,8 +27,6 @@ enum {
LAST_SIGNAL
};
-static void sp_color_slider_class_init (SPColorSliderClass *klass);
-static void sp_color_slider_init (SPColorSlider *slider);
static void sp_color_slider_dispose(GObject *object);
static void sp_color_slider_realize (GtkWidget *widget);
@@ -61,36 +60,15 @@ static const guchar *sp_color_slider_render_gradient (gint x0, gint y0, gint wid
static const guchar *sp_color_slider_render_map (gint x0, gint y0, gint width, gint height,
guchar *map, gint start, gint step, guint b0, guint b1, guint mask);
-static GtkWidgetClass *parent_class;
static guint slider_signals[LAST_SIGNAL] = {0};
-GType
-sp_color_slider_get_type (void)
-{
- static GType type = 0;
- if (!type) {
- GTypeInfo info = {
- sizeof (SPColorSliderClass),
- NULL, NULL,
- (GClassInitFunc) sp_color_slider_class_init,
- NULL, NULL,
- sizeof (SPColorSlider),
- 0,
- (GInstanceInitFunc) sp_color_slider_init,
- NULL
- };
- type = g_type_register_static (GTK_TYPE_WIDGET, "SPColorSlider", &info, (GTypeFlags)0);
- }
- return type;
-}
+G_DEFINE_TYPE(SPColorSlider, sp_color_slider, GTK_TYPE_WIDGET);
static void sp_color_slider_class_init(SPColorSliderClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS(klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass);
- parent_class = GTK_WIDGET_CLASS(g_type_class_peek_parent(klass));
-
slider_signals[GRABBED] = g_signal_new ("grabbed",
G_TYPE_FROM_CLASS(object_class),
(GSignalFlags)(G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE),
@@ -183,8 +161,8 @@ static void sp_color_slider_dispose(GObject *object)
slider->adjustment = NULL;
}
- if ((G_OBJECT_CLASS(parent_class))->dispose)
- (* (G_OBJECT_CLASS(parent_class))->dispose) (object);
+ if (G_OBJECT_CLASS(sp_color_slider_parent_class)->dispose)
+ G_OBJECT_CLASS(sp_color_slider_parent_class)->dispose (object);
}
static void
diff --git a/src/widgets/sp-color-slider.h b/src/widgets/sp-color-slider.h
index 591d8368a..b81d62e41 100644
--- a/src/widgets/sp-color-slider.h
+++ b/src/widgets/sp-color-slider.h
@@ -14,13 +14,6 @@
#include <gtk/gtk.h>
-#include <glib.h>
-
-
-
-struct SPColorSlider;
-struct SPColorSliderClass;
-
#define SP_TYPE_COLOR_SLIDER (sp_color_slider_get_type ())
#define SP_COLOR_SLIDER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), SP_TYPE_COLOR_SLIDER, SPColorSlider))
#define SP_COLOR_SLIDER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), SP_TYPE_COLOR_SLIDER, SPColorSliderClass))
diff --git a/src/widgets/sp-color-wheel-selector.cpp b/src/widgets/sp-color-wheel-selector.cpp
index 7c8bb1df7..6cfa7c14d 100644
--- a/src/widgets/sp-color-wheel-selector.cpp
+++ b/src/widgets/sp-color-wheel-selector.cpp
@@ -4,17 +4,16 @@
#include <math.h>
#include <gtk/gtk.h>
#include <glibmm/i18n.h>
-#include "../dialogs/dialog-events.h"
+#include "ui/dialog-events.h"
#include "sp-color-wheel-selector.h"
#include "sp-color-scales.h"
+#include "sp-color-slider.h"
#include "sp-color-icc-selector.h"
#include "../svg/svg-icc-color.h"
#include "ui/widget/gimpcolorwheel.h"
G_BEGIN_DECLS
-static void sp_color_wheel_selector_class_init (SPColorWheelSelectorClass *klass);
-static void sp_color_wheel_selector_init (SPColorWheelSelector *cs);
static void sp_color_wheel_selector_dispose(GObject *object);
static void sp_color_wheel_selector_show_all (GtkWidget *widget);
@@ -23,36 +22,10 @@ static void sp_color_wheel_selector_hide(GtkWidget *widget);
G_END_DECLS
-static SPColorSelectorClass *parent_class;
-
#define XPAD 4
#define YPAD 1
-GType
-sp_color_wheel_selector_get_type (void)
-{
- static GType type = 0;
- if (!type) {
- static const GTypeInfo info = {
- sizeof (SPColorWheelSelectorClass),
- NULL, /* base_init */
- NULL, /* base_finalize */
- (GClassInitFunc) sp_color_wheel_selector_class_init,
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof (SPColorWheelSelector),
- 0, /* n_preallocs */
- (GInstanceInitFunc) sp_color_wheel_selector_init,
- 0, /* value_table */
- };
-
- type = g_type_register_static (SP_TYPE_COLOR_SELECTOR,
- "SPColorWheelSelector",
- &info,
- static_cast< GTypeFlags > (0) );
- }
- return type;
-}
+G_DEFINE_TYPE(SPColorWheelSelector, sp_color_wheel_selector, SP_TYPE_COLOR_SELECTOR);
static void sp_color_wheel_selector_class_init(SPColorWheelSelectorClass *klass)
{
@@ -61,8 +34,6 @@ static void sp_color_wheel_selector_class_init(SPColorWheelSelectorClass *klass)
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass);
SPColorSelectorClass *selector_class = SP_COLOR_SELECTOR_CLASS (klass);
- parent_class = SP_COLOR_SELECTOR_CLASS (g_type_class_peek_parent (klass));
-
selector_class->name = nameset;
selector_class->submode_count = 1;
@@ -142,8 +113,13 @@ void ColorWheelSelector::init()
gtk_widget_show (_label);
#if GTK_CHECK_VERSION(3,0,0)
+ #if GTK_CHECK_VERSION(3,12,0)
+ gtk_widget_set_margin_start(_label, XPAD);
+ gtk_widget_set_margin_end(_label, XPAD);
+ #else
gtk_widget_set_margin_left(_label, XPAD);
gtk_widget_set_margin_right(_label, XPAD);
+ #endif
gtk_widget_set_margin_top(_label, YPAD);
gtk_widget_set_margin_bottom(_label, YPAD);
gtk_widget_set_halign(_label, GTK_ALIGN_FILL);
@@ -162,8 +138,13 @@ void ColorWheelSelector::init()
gtk_widget_show (_slider);
#if GTK_CHECK_VERSION(3,0,0)
+ #if GTK_CHECK_VERSION(3,12,0)
+ gtk_widget_set_margin_start(_slider, XPAD);
+ gtk_widget_set_margin_end(_slider, XPAD);
+ #else
gtk_widget_set_margin_left(_slider, XPAD);
gtk_widget_set_margin_right(_slider, XPAD);
+ #endif
gtk_widget_set_margin_top(_slider, YPAD);
gtk_widget_set_margin_bottom(_slider, YPAD);
gtk_widget_set_hexpand(_slider, TRUE);
@@ -188,8 +169,13 @@ void ColorWheelSelector::init()
gtk_widget_show (_sbtn);
#if GTK_CHECK_VERSION(3,0,0)
+ #if GTK_CHECK_VERSION(3,12,0)
+ gtk_widget_set_margin_start(_sbtn, XPAD);
+ gtk_widget_set_margin_end(_sbtn, XPAD);
+ #else
gtk_widget_set_margin_left(_sbtn, XPAD);
gtk_widget_set_margin_right(_sbtn, XPAD);
+ #endif
gtk_widget_set_margin_top(_sbtn, YPAD);
gtk_widget_set_margin_bottom(_sbtn, YPAD);
gtk_widget_set_halign(_sbtn, GTK_ALIGN_CENTER);
@@ -216,8 +202,8 @@ void ColorWheelSelector::init()
static void sp_color_wheel_selector_dispose(GObject *object)
{
- if ((G_OBJECT_CLASS(parent_class))->dispose)
- (* (G_OBJECT_CLASS(parent_class))->dispose) (object);
+ if (G_OBJECT_CLASS(sp_color_wheel_selector_parent_class)->dispose)
+ G_OBJECT_CLASS(sp_color_wheel_selector_parent_class)->dispose(object);
}
static void
diff --git a/src/widgets/sp-color-wheel-selector.h b/src/widgets/sp-color-wheel-selector.h
index bbd377422..12b060dbe 100644
--- a/src/widgets/sp-color-wheel-selector.h
+++ b/src/widgets/sp-color-wheel-selector.h
@@ -1,15 +1,12 @@
#ifndef SEEN_SP_COLOR_WHEEL_SELECTOR_H
#define SEEN_SP_COLOR_WHEEL_SELECTOR_H
-#include <glib.h>
#include <gtk/gtk.h>
-#include "sp-color-slider.h"
#include "sp-color-selector.h"
-
-
typedef struct _GimpColorWheel GimpColorWheel;
+struct SPColorSlider;
struct SPColorWheelSelector;
struct SPColorWheelSelectorClass;
diff --git a/src/widgets/sp-widget.cpp b/src/widgets/sp-widget.cpp
index 0e2295e36..fdf5ec500 100644
--- a/src/widgets/sp-widget.cpp
+++ b/src/widgets/sp-widget.cpp
@@ -36,8 +36,6 @@ public:
SPWidgetImpl(SPWidget &target);
~SPWidgetImpl();
- static void classInit(SPWidgetClass *klass);
- static void init(SPWidget *widget);
static void dispose(GObject *object);
static void show(GtkWidget *widget);
static void hide(GtkWidget *widget);
@@ -61,64 +59,27 @@ public:
static void changeSelectionCB(Application *inkscape, Selection *selection, SPWidget *spw);
static void setSelectionCB(Application *inkscape, Selection *selection, SPWidget *spw);
- static GtkWidget *constructGlobal(SPWidget *spw, Inkscape::Application *inkscape);
+ static GtkWidget *constructGlobal(SPWidget *spw, InkscapeApplication *inkscape);
void modifySelection(Application *inkscape, Selection *selection, guint flags);
void changeSelection(Application *inkscape, Selection *selection);
void setSelection(Application *inkscape, Selection *selection);
private:
- static GtkBinClass *parentClass;
- static guint signals[LAST_SIGNAL];
-
SPWidget &_target;
};
-
-GtkBinClass *SPWidgetImpl::parentClass = 0;
-guint SPWidgetImpl::signals[LAST_SIGNAL] = {0};
-
} // namespace Inkscape
-GType SPWidget::getType()
-{
- static GType type = 0;
- if (!type) {
- static GTypeInfo const info = {
- sizeof(SPWidgetClass),
- NULL, NULL,
- reinterpret_cast<GClassInitFunc>(SPWidgetImpl::classInit),
- NULL, NULL,
- sizeof(SPWidget),
- 0,
- reinterpret_cast<GInstanceInitFunc>(SPWidgetImpl::init),
- NULL
- };
- type = g_type_register_static(GTK_TYPE_BIN,
- "SPWidget",
- &info,
- static_cast<GTypeFlags>(0));
- }
- return type;
-}
+G_DEFINE_TYPE(SPWidget, sp_widget, GTK_TYPE_BIN);
-namespace Inkscape {
+static guint signals[LAST_SIGNAL] = {0};
-SPWidgetImpl::SPWidgetImpl(SPWidget &target) :
- _target(target)
-{
-}
-
-SPWidgetImpl::~SPWidgetImpl()
-{
-}
-
-void SPWidgetImpl::classInit(SPWidgetClass *klass)
+static void
+sp_widget_class_init(SPWidgetClass *klass)
{
GObjectClass *object_class = reinterpret_cast<GObjectClass *>(klass);
GtkWidgetClass *widget_class = reinterpret_cast<GtkWidgetClass *>(klass);
- parentClass = reinterpret_cast<GtkBinClass *>(g_type_class_peek_parent(klass));
-
object_class->dispose = SPWidgetImpl::dispose;
signals[CONSTRUCT] = g_signal_new ("construct",
@@ -169,13 +130,23 @@ void SPWidgetImpl::classInit(SPWidgetClass *klass)
widget_class->size_allocate = SPWidgetImpl::sizeAllocate;
}
-void SPWidgetImpl::init(SPWidget *spw)
+static void sp_widget_init(SPWidget *spw)
{
spw->inkscape = NULL;
-
spw->_impl = new SPWidgetImpl(*spw); // ctor invoked after all other init
}
+namespace Inkscape {
+
+SPWidgetImpl::SPWidgetImpl(SPWidget &target) :
+ _target(target)
+{
+}
+
+SPWidgetImpl::~SPWidgetImpl()
+{
+}
+
void SPWidgetImpl::dispose(GObject *object)
{
SPWidget *spw = reinterpret_cast<SPWidget *>(object);
@@ -194,8 +165,8 @@ void SPWidgetImpl::dispose(GObject *object)
delete spw->_impl;
spw->_impl = 0;
- if (reinterpret_cast<GObjectClass *>(parentClass)->dispose) {
- (*reinterpret_cast<GObjectClass *>(parentClass)->dispose)(object);
+ if (G_OBJECT_CLASS(sp_widget_parent_class)->dispose) {
+ G_OBJECT_CLASS(sp_widget_parent_class)->dispose(object);
}
}
@@ -210,8 +181,8 @@ void SPWidgetImpl::show(GtkWidget *widget)
g_signal_connect(spw->inkscape, "set_selection", G_CALLBACK(SPWidgetImpl::setSelectionCB), spw);
}
- if (reinterpret_cast<GtkWidgetClass *>(parentClass)->show) {
- (*reinterpret_cast<GtkWidgetClass *>(parentClass)->show)(widget);
+ if (GTK_WIDGET_CLASS(sp_widget_parent_class)->show) {
+ GTK_WIDGET_CLASS(sp_widget_parent_class)->show(widget);
}
}
@@ -224,8 +195,8 @@ void SPWidgetImpl::hide(GtkWidget *widget)
sp_signal_disconnect_by_data(spw->inkscape, spw);
}
- if (reinterpret_cast<GtkWidgetClass *>(parentClass)->hide) {
- (*reinterpret_cast<GtkWidgetClass *>(parentClass)->hide)(widget);
+ if (GTK_WIDGET_CLASS(sp_widget_parent_class)->hide) {
+ GTK_WIDGET_CLASS(sp_widget_parent_class)->hide(widget);
}
}
@@ -293,7 +264,7 @@ void SPWidgetImpl::sizeAllocate(GtkWidget *widget, GtkAllocation *allocation)
}
}
-GtkWidget *SPWidgetImpl::constructGlobal(SPWidget *spw, Inkscape::Application *inkscape)
+GtkWidget *SPWidgetImpl::constructGlobal(SPWidget *spw, InkscapeApplication *inkscape)
{
g_return_val_if_fail(!spw->inkscape, NULL);
@@ -345,7 +316,7 @@ void SPWidgetImpl::setSelection(Application * /*inkscape*/, Selection *selection
// Methods
-GtkWidget *sp_widget_new_global(Inkscape::Application *inkscape)
+GtkWidget *sp_widget_new_global(InkscapeApplication *inkscape)
{
SPWidget *spw = reinterpret_cast<SPWidget*>(g_object_new(SP_TYPE_WIDGET, NULL));
diff --git a/src/widgets/sp-widget.h b/src/widgets/sp-widget.h
index 3a23a92c5..6227c3a72 100644
--- a/src/widgets/sp-widget.h
+++ b/src/widgets/sp-widget.h
@@ -15,35 +15,27 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include <glib.h>
#include <gtk/gtk.h>
-#define SP_TYPE_WIDGET (SPWidget::getType())
+#define SP_TYPE_WIDGET (sp_widget_get_type())
#define SP_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SP_TYPE_WIDGET, SPWidget))
#define SP_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SP_TYPE_WIDGET, SPWidgetClass))
#define SP_IS_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SP_TYPE_WIDGET))
#define SP_IS_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SP_TYPE_WIDGET))
+struct InkscapeApplication;
namespace Inkscape {
-
-struct Application;
class Selection;
class SPWidgetImpl;
-
}
struct SPWidget {
friend class Inkscape::SPWidgetImpl;
- static GType getType();
-
- //
-
GtkBin bin;
- Inkscape::Application *inkscape;
+ InkscapeApplication *inkscape;
-private:
Inkscape::SPWidgetImpl *_impl;
};
@@ -58,10 +50,10 @@ struct SPWidgetClass {
void (* set_selection) (SPWidget *spw, Inkscape::Selection *selection);
};
-/* fixme: Think (Lauris) */
+GType sp_widget_get_type();
/** Generic constructor for global widget. */
-GtkWidget *sp_widget_new_global(Inkscape::Application *inkscape);
+GtkWidget *sp_widget_new_global(InkscapeApplication *inkscape);
#endif // SEEN_SP_WIDGET_H
/*
diff --git a/src/widgets/sp-xmlview-attr-list.cpp b/src/widgets/sp-xmlview-attr-list.cpp
index 47b0ebb9d..dd763aea5 100644
--- a/src/widgets/sp-xmlview-attr-list.cpp
+++ b/src/widgets/sp-xmlview-attr-list.cpp
@@ -20,9 +20,6 @@
#include "../xml/node-event-vector.h"
#include "sp-xmlview-attr-list.h"
-static void sp_xmlview_attr_list_class_init (SPXMLViewAttrListClass * klass);
-static void sp_xmlview_attr_list_init (SPXMLViewAttrList * list);
-
#if GTK_CHECK_VERSION(3,0,0)
static void sp_xmlview_attr_list_destroy(GtkWidget * object);
#else
@@ -31,8 +28,6 @@ static void sp_xmlview_attr_list_destroy(GtkObject * object);
static void event_attr_changed (Inkscape::XML::Node * repr, const gchar * name, const gchar * old_value, const gchar * new_value, bool is_interactive, gpointer data);
-static GtkTreeViewClass * parent_class = NULL;
-
static Inkscape::XML::NodeEventVector repr_events = {
NULL, /* child_added */
NULL, /* child_removed */
@@ -88,28 +83,7 @@ sp_xmlview_attr_list_set_repr (SPXMLViewAttrList * list, Inkscape::XML::Node * r
}
}
-GType sp_xmlview_attr_list_get_type(void)
-{
- static GType type = 0;
-
- if (!type) {
- GTypeInfo info = {
- sizeof(SPXMLViewAttrListClass),
- 0, // base_init
- 0, // base_finalize
- (GClassInitFunc)sp_xmlview_attr_list_class_init,
- 0, // class_finalize
- 0, // class_data
- sizeof(SPXMLViewAttrList),
- 0, // n_preallocs
- (GInstanceInitFunc)sp_xmlview_attr_list_init,
- 0 // value_table
- };
- type = g_type_register_static(GTK_TYPE_TREE_VIEW, "SPXMLViewAttrList", &info, static_cast<GTypeFlags>(0));
- }
-
- return type;
-}
+G_DEFINE_TYPE(SPXMLViewAttrList, sp_xmlview_attr_list, GTK_TYPE_TREE_VIEW);
void sp_xmlview_attr_list_class_init (SPXMLViewAttrListClass * klass)
{
@@ -121,8 +95,6 @@ void sp_xmlview_attr_list_class_init (SPXMLViewAttrListClass * klass)
object_class->destroy = sp_xmlview_attr_list_destroy;
#endif
- parent_class = GTK_TREE_VIEW_CLASS(g_type_class_peek_parent (klass));
-
g_signal_new("row-value-changed",
G_TYPE_FROM_CLASS(klass),
G_SIGNAL_RUN_FIRST,
@@ -154,9 +126,9 @@ void sp_xmlview_attr_list_destroy(GtkObject * object)
sp_xmlview_attr_list_set_repr (list, NULL);
#if GTK_CHECK_VERSION(3,0,0)
- GTK_WIDGET_CLASS(parent_class)->destroy (object);
+ GTK_WIDGET_CLASS(sp_xmlview_attr_list_parent_class)->destroy (object);
#else
- GTK_OBJECT_CLASS(parent_class)->destroy (object);
+ GTK_OBJECT_CLASS(sp_xmlview_attr_list_parent_class)->destroy (object);
#endif
}
diff --git a/src/widgets/sp-xmlview-attr-list.h b/src/widgets/sp-xmlview-attr-list.h
index 367ef1a12..08b115bfa 100644
--- a/src/widgets/sp-xmlview-attr-list.h
+++ b/src/widgets/sp-xmlview-attr-list.h
@@ -12,10 +12,8 @@
* Released under the GNU GPL; see COPYING for details
*/
-#include <stdio.h>
#include <gtk/gtk.h>
-
#define SP_TYPE_XMLVIEW_ATTR_LIST (sp_xmlview_attr_list_get_type ())
#define SP_XMLVIEW_ATTR_LIST(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), SP_TYPE_XMLVIEW_ATTR_LIST, SPXMLViewAttrList))
#define SP_IS_XMLVIEW_ATTR_LIST(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), SP_TYPE_XMLVIEW_ATTR_LIST))
@@ -23,7 +21,6 @@
struct SPXMLViewAttrList
{
-
GtkTreeView list;
GtkListStore *store;
diff --git a/src/widgets/sp-xmlview-content.cpp b/src/widgets/sp-xmlview-content.cpp
index ac64dabdb..9243760bd 100644
--- a/src/widgets/sp-xmlview-content.cpp
+++ b/src/widgets/sp-xmlview-content.cpp
@@ -23,9 +23,6 @@
using Inkscape::DocumentUndo;
-static void sp_xmlview_content_class_init (SPXMLViewContentClass * klass);
-static void sp_xmlview_content_init (SPXMLViewContent * text);
-
#if GTK_CHECK_VERSION(3,0,0)
static void sp_xmlview_content_destroy(GtkWidget * object);
#else
@@ -36,8 +33,6 @@ void sp_xmlview_content_changed (GtkTextBuffer *tb, SPXMLViewContent *text);
static void event_content_changed (Inkscape::XML::Node * repr, const gchar * old_content, const gchar * new_content, gpointer data);
-static GtkTextViewClass * parent_class = NULL;
-
static Inkscape::XML::NodeEventVector repr_events = {
NULL, /* child_added */
NULL, /* child_removed */
@@ -81,28 +76,7 @@ sp_xmlview_content_set_repr (SPXMLViewContent * text, Inkscape::XML::Node * repr
}
}
-GType sp_xmlview_content_get_type(void)
-{
- static GType type = 0;
-
- if (!type) {
- GTypeInfo info = {
- sizeof(SPXMLViewContentClass),
- 0, // base_init
- 0, // base_finalize
- (GClassInitFunc)sp_xmlview_content_class_init,
- 0, // class_finalize
- 0, // class_data
- sizeof(SPXMLViewContent),
- 0, // n_preallocs
- (GInstanceInitFunc)sp_xmlview_content_init,
- 0 // value_table
- };
- type = g_type_register_static(GTK_TYPE_TEXT_VIEW, "SPXMLViewContent", &info, static_cast<GTypeFlags>(0));
- }
-
- return type;
-}
+G_DEFINE_TYPE(SPXMLViewContent, sp_xmlview_content, GTK_TYPE_TEXT_VIEW);
void sp_xmlview_content_class_init(SPXMLViewContentClass * klass)
{
@@ -113,8 +87,6 @@ void sp_xmlview_content_class_init(SPXMLViewContentClass * klass)
GtkObjectClass * object_class = GTK_OBJECT_CLASS(klass);
object_class->destroy = sp_xmlview_content_destroy;
#endif
-
- parent_class = GTK_TEXT_VIEW_CLASS(g_type_class_peek_parent (klass));
}
void
@@ -135,9 +107,9 @@ void sp_xmlview_content_destroy(GtkObject * object)
sp_xmlview_content_set_repr (text, NULL);
#if GTK_CHECK_VERSION(3,0,0)
- GTK_WIDGET_CLASS (parent_class)->destroy (object);
+ GTK_WIDGET_CLASS (sp_xmlview_content_parent_class)->destroy (object);
#else
- GTK_OBJECT_CLASS (parent_class)->destroy (object);
+ GTK_OBJECT_CLASS (sp_xmlview_content_parent_class)->destroy (object);
#endif
}
diff --git a/src/widgets/sp-xmlview-content.h b/src/widgets/sp-xmlview-content.h
index 8b1342c5e..140eacf46 100644
--- a/src/widgets/sp-xmlview-content.h
+++ b/src/widgets/sp-xmlview-content.h
@@ -13,10 +13,7 @@
*/
#include <config.h>
-#include <stdio.h>
#include <gtk/gtk.h>
-#include <glib.h>
-
#define SP_TYPE_XMLVIEW_CONTENT (sp_xmlview_content_get_type ())
#define SP_XMLVIEW_CONTENT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), SP_TYPE_XMLVIEW_CONTENT, SPXMLViewContent))
diff --git a/src/widgets/sp-xmlview-tree.cpp b/src/widgets/sp-xmlview-tree.cpp
index 43b7dc289..5dff9adf3 100644
--- a/src/widgets/sp-xmlview-tree.cpp
+++ b/src/widgets/sp-xmlview-tree.cpp
@@ -1,6 +1,4 @@
-#define __SP_XMLVIEW_TREE_C__
-
-/*
+/**
* Specialization of GtkTreeView for the XML tree view
*
* Authors:
@@ -14,7 +12,7 @@
#include <cstring>
#include <string>
-#include "../xml/node-event-vector.h"
+#include "xml/node-event-vector.h"
#include "sp-xmlview-tree.h"
struct NodeData {
@@ -25,9 +23,6 @@ struct NodeData {
enum { STORE_TEXT_COL = 0, STORE_DATA_COL, STORE_REPR_COL, STORE_N_COLS };
-static void sp_xmlview_tree_class_init (SPXMLViewTreeClass * klass);
-static void sp_xmlview_tree_init (SPXMLViewTree * tree);
-
#if GTK_CHECK_VERSION(3,0,0)
static void sp_xmlview_tree_destroy(GtkWidget * object);
#else
@@ -92,8 +87,6 @@ static const Inkscape::XML::NodeEventVector pi_repr_events = {
NULL /* order_changed */
};
-static GtkTreeViewClass * parent_class = NULL;
-
GtkWidget *sp_xmlview_tree_new(Inkscape::XML::Node * repr, void * /*factory*/, void * /*data*/)
{
SPXMLViewTree *tree = SP_XMLVIEW_TREE(g_object_new (SP_TYPE_XMLVIEW_TREE, NULL));
@@ -124,28 +117,7 @@ GtkWidget *sp_xmlview_tree_new(Inkscape::XML::Node * repr, void * /*factory*/, v
return GTK_WIDGET(tree);
}
-GType
-sp_xmlview_tree_get_type (void)
-{
- static GType type = 0;
-
- if (!type) {
- static const GTypeInfo info = {
- sizeof (SPXMLViewTreeClass),
- NULL, NULL,
- (GClassInitFunc) sp_xmlview_tree_class_init,
- NULL, NULL,
- sizeof (SPXMLViewTree),
- 0,
- (GInstanceInitFunc) sp_xmlview_tree_init,
- NULL
- };
- type = g_type_register_static (GTK_TYPE_TREE_VIEW, "SPXMLViewTree", &info, (GTypeFlags)0);
- }
-
-
- return type;
-}
+G_DEFINE_TYPE(SPXMLViewTree, sp_xmlview_tree, GTK_TYPE_TREE_VIEW);
void sp_xmlview_tree_class_init(SPXMLViewTreeClass * klass)
{
@@ -157,8 +129,6 @@ void sp_xmlview_tree_class_init(SPXMLViewTreeClass * klass)
object_class->destroy = sp_xmlview_tree_destroy;
#endif
- parent_class = GTK_TREE_VIEW_CLASS(g_type_class_peek_parent (klass));
-
// Signal for when a tree drag and drop has completed
g_signal_new ( "tree_move",
G_TYPE_FROM_CLASS(klass),
@@ -190,9 +160,9 @@ void sp_xmlview_tree_destroy(GtkObject * object)
sp_xmlview_tree_set_repr (tree, NULL);
#if GTK_CHECK_VERSION(3,0,0)
- GTK_WIDGET_CLASS(parent_class)->destroy (object);
+ GTK_WIDGET_CLASS(sp_xmlview_tree_parent_class)->destroy (object);
#else
- GTK_OBJECT_CLASS(parent_class)->destroy (object);
+ GTK_OBJECT_CLASS(sp_xmlview_tree_parent_class)->destroy (object);
#endif
}
@@ -734,4 +704,4 @@ gboolean search_equal_func(GtkTreeModel *model, gint /*column*/, const gchar *ke
fill-column:99
End:
*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8 :
diff --git a/src/widgets/sp-xmlview-tree.h b/src/widgets/sp-xmlview-tree.h
index 69228fa88..7ecbcb471 100644
--- a/src/widgets/sp-xmlview-tree.h
+++ b/src/widgets/sp-xmlview-tree.h
@@ -1,9 +1,4 @@
-#ifndef __SP_XMLVIEW_TREE_H__
-#define __SP_XMLVIEW_TREE_H__
-
-/*
- * Specialization of GtkTreeView for the XML editor
- *
+/**
* Authors:
* MenTaLguY <mental@rydia.net>
*
@@ -12,9 +7,15 @@
* Released under the GNU GPL; see COPYING for details
*/
+#ifndef SEEN_SP_XMLVIEW_TREE_H
+#define SEEN_SP_XMLVIEW_TREE_H
+
#include <gtk/gtk.h>
#include <glib.h>
+/**
+ * Specialization of GtkTreeView for the XML editor
+ */
#define SP_TYPE_XMLVIEW_TREE (sp_xmlview_tree_get_type ())
#define SP_XMLVIEW_TREE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), SP_TYPE_XMLVIEW_TREE, SPXMLViewTree))
@@ -49,7 +50,7 @@ Inkscape::XML::Node * sp_xmlview_tree_node_get_repr (GtkTreeModel *model, GtkTre
gboolean sp_xmlview_tree_get_repr_node (SPXMLViewTree * tree, Inkscape::XML::Node * repr, GtkTreeIter *node);
-#endif
+#endif // !SEEN_SP_XMLVIEW_TREE_H
/*
Local Variables:
@@ -60,4 +61,4 @@ gboolean sp_xmlview_tree_get_repr_node (SPXMLViewTree * tree, Inkscape::XML::Nod
fill-column:99
End:
*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8 :
diff --git a/src/widgets/spinbutton-events.h b/src/widgets/spinbutton-events.h
index c1df88c8a..9bf50d87c 100644
--- a/src/widgets/spinbutton-events.h
+++ b/src/widgets/spinbutton-events.h
@@ -10,7 +10,9 @@
*/
#include <glib.h>
-#include <gtk/gtk.h> /* GtkWidget */
+
+typedef struct _GdkEventKey GdkEventKey;
+typedef struct _GtkWidget GtkWidget;
gboolean spinbutton_focus_in (GtkWidget *w, GdkEventKey *event, gpointer data);
void spinbutton_undo (GtkWidget *w);
diff --git a/src/widgets/spiral-toolbar.cpp b/src/widgets/spiral-toolbar.cpp
index 710be9440..e85b024ed 100644
--- a/src/widgets/spiral-toolbar.cpp
+++ b/src/widgets/spiral-toolbar.cpp
@@ -34,9 +34,9 @@
#include "desktop-handles.h"
#include "desktop.h"
#include "document-undo.h"
-#include "ege-adjustment-action.h"
-#include "ege-output-action.h"
-#include "ink-action.h"
+#include "widgets/ege-adjustment-action.h"
+#include "widgets/ege-output-action.h"
+#include "widgets/ink-action.h"
#include "preferences.h"
#include "selection.h"
#include "sp-spiral.h"
diff --git a/src/widgets/spray-toolbar.cpp b/src/widgets/spray-toolbar.cpp
index 788ce6475..183814b7e 100644
--- a/src/widgets/spray-toolbar.cpp
+++ b/src/widgets/spray-toolbar.cpp
@@ -33,9 +33,9 @@
#include "spray-toolbar.h"
#include "desktop.h"
#include "document-undo.h"
-#include "ege-adjustment-action.h"
-#include "ege-select-one-action.h"
-#include "ink-action.h"
+#include "widgets/ege-adjustment-action.h"
+#include "widgets/ege-select-one-action.h"
+#include "widgets/ink-action.h"
#include "preferences.h"
#include "toolbox.h"
#include "ui/icon-names.h"
diff --git a/src/widgets/spw-utilities.cpp b/src/widgets/spw-utilities.cpp
index 9c0c8d7c6..f87889bb1 100644
--- a/src/widgets/spw-utilities.cpp
+++ b/src/widgets/spw-utilities.cpp
@@ -64,8 +64,15 @@ Gtk::Label * spw_label(Gtk::Table *table, const gchar *label_text, int col, int
label_widget->set_hexpand();
label_widget->set_halign(Gtk::ALIGN_FILL);
label_widget->set_valign(Gtk::ALIGN_CENTER);
+
+ #if GTK_CHECK_VERSION(3,12,0)
+ label_widget->set_margin_start(4);
+ label_widget->set_margin_end(4);
+ #else
label_widget->set_margin_left(4);
label_widget->set_margin_right(4);
+ #endif
+
table->attach(*label_widget, col, row, 1, 1);
#else
table->attach(*label_widget, col, col+1, row, row+1, (Gtk::EXPAND | Gtk::FILL), static_cast<Gtk::AttachOptions>(0), 4, 0);
@@ -238,7 +245,11 @@ sp_set_font_size_recursive (GtkWidget *w, gpointer font)
PangoFontDescription* pan = pango_font_description_new ();
pango_font_description_set_size (pan, size);
+#if GTK_CHECK_VERSION(3,0,0)
+ gtk_widget_override_font (w, pan);
+#else
gtk_widget_modify_font (w, pan);
+#endif
if (GTK_IS_CONTAINER(w)) {
gtk_container_foreach (GTK_CONTAINER(w), (GtkCallback) sp_set_font_size_recursive, font);
diff --git a/src/widgets/star-toolbar.cpp b/src/widgets/star-toolbar.cpp
index 7a7d0dc71..6213263fc 100644
--- a/src/widgets/star-toolbar.cpp
+++ b/src/widgets/star-toolbar.cpp
@@ -34,14 +34,15 @@
#include "desktop-handles.h"
#include "desktop.h"
#include "document-undo.h"
-#include "ege-adjustment-action.h"
-#include "ege-output-action.h"
-#include "ege-select-one-action.h"
-#include "ink-action.h"
+#include "widgets/ege-adjustment-action.h"
+#include "widgets/ege-output-action.h"
+#include "widgets/ege-select-one-action.h"
+#include "widgets/ink-action.h"
#include "selection.h"
#include "sp-star.h"
#include "toolbox.h"
#include "ui/icon-names.h"
+#include "ui/tools/star-tool.h"
#include "ui/uxmanager.h"
#include "verbs.h"
#include "widgets/../preferences.h"
@@ -435,6 +436,7 @@ static void sp_stb_defaults( GtkWidget * /*widget*/, GObject *dataKludge )
gtk_adjustment_value_changed(adj);
}
+static void star_toolbox_watch_ec(SPDesktop* dt, Inkscape::UI::Tools::ToolBase* ec, GObject* holder);
void sp_star_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder)
{
@@ -571,15 +573,22 @@ void sp_star_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObje
}
}
- sigc::connection *connection = new sigc::connection(
- sp_desktop_selection(desktop)->connectChanged(sigc::bind(sigc::ptr_fun(sp_star_toolbox_selection_changed), holder))
- );
- g_signal_connect( holder, "destroy", G_CALLBACK(delete_connection), connection );
- g_signal_connect( holder, "destroy", G_CALLBACK(purge_repr_listener), holder );
+ desktop->connectEventContextChanged(sigc::bind(sigc::ptr_fun(star_toolbox_watch_ec), holder));
+ g_signal_connect(holder, "destroy", G_CALLBACK(purge_repr_listener), holder);
}
+static void star_toolbox_watch_ec(SPDesktop* desktop, Inkscape::UI::Tools::ToolBase* ec, GObject* holder)
+{
+ static sigc::connection changed;
-
+ if (dynamic_cast<Inkscape::UI::Tools::StarTool const*>(ec) != NULL) {
+ changed = sp_desktop_selection(desktop)->connectChanged(sigc::bind(sigc::ptr_fun(sp_star_toolbox_selection_changed), holder));
+ sp_star_toolbox_selection_changed(sp_desktop_selection(desktop), holder);
+ } else {
+ if (changed)
+ changed.disconnect();
+ }
+}
/*
Local Variables:
@@ -590,4 +599,4 @@ void sp_star_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObje
fill-column:99
End:
*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8 :
diff --git a/src/widgets/stroke-marker-selector.cpp b/src/widgets/stroke-marker-selector.cpp
index 00b6b5c91..23da54e94 100644
--- a/src/widgets/stroke-marker-selector.cpp
+++ b/src/widgets/stroke-marker-selector.cpp
@@ -25,13 +25,13 @@
#include "style.h"
-#include "dialogs/dialog-events.h"
+#include "ui/dialog-events.h"
#include "desktop-handles.h"
#include "desktop-style.h"
#include "preferences.h"
#include "path-prefix.h"
#include "io/sys.h"
-#include "marker.h"
+#include "sp-marker.h"
#include "sp-defs.h"
#include "sp-root.h"
#include "ui/cache/svg_preview_cache.h"
@@ -385,7 +385,7 @@ void MarkerComboBox::add_markers (GSList *marker_list, SPDocument *source, gbool
if (history) {
// add "None"
Gtk::TreeModel::Row row = *(marker_store->prepend());
- row[marker_columns.label] = _("None");
+ row[marker_columns.label] = C_("Marker", "None");
row[marker_columns.stock] = false;
row[marker_columns.marker] = g_strdup("None");
row[marker_columns.image] = NULL;
diff --git a/src/widgets/stroke-style.cpp b/src/widgets/stroke-style.cpp
index a4cca9472..02dd5df6e 100644
--- a/src/widgets/stroke-style.cpp
+++ b/src/widgets/stroke-style.cpp
@@ -18,7 +18,7 @@
#define noSP_SS_VERBOSE
#include "stroke-style.h"
-#include "../gradient-chemistry.h"
+#include "gradient-chemistry.h"
#include "sp-gradient.h"
#include "sp-stop.h"
#include "svg/svg-color.h"
@@ -581,7 +581,8 @@ StrokeStyle::forkMarker(SPObject *marker, int loc, SPItem *item)
Glib::ustring urlId = Glib::ustring::format("url(#", marker->getRepr()->attribute("id"), ")");
unsigned int refs = 0;
for (int i = SP_MARKER_LOC_START; i < SP_MARKER_LOC_QTY; i++) {
- if (item->style->marker[i].set && !strcmp(urlId.c_str(), item->style->marker[i].value)) {
+ if (item->style->marker_ptrs[i]->set &&
+ !strcmp(urlId.c_str(), item->style->marker_ptrs[i]->value)) {
refs++;
}
}
@@ -762,6 +763,9 @@ StrokeStyle::setJoinType (unsigned const jointype)
tb = joinBevel;
break;
default:
+ // Should not happen
+ std::cerr << "StrokeStyle::setJoinType(): Invalid value: " << jointype << std::endl;
+ tb = joinMiter;
break;
}
setJoinButtons(tb);
@@ -785,6 +789,9 @@ StrokeStyle::setCapType (unsigned const captype)
tb = capSquare;
break;
default:
+ // Should not happen
+ std::cerr << "StrokeStyle::setCapType(): Invalid value: " << captype << std::endl;
+ tb = capButt;
break;
}
setCapButtons(tb);
@@ -877,13 +884,15 @@ StrokeStyle::updateLine()
miterLimitAdj->set_value(query->stroke_miterlimit.value); // TODO: reflect averagedness?
#endif
- if (result_join != QUERY_STYLE_MULTIPLE_DIFFERENT) {
+ if (result_join != QUERY_STYLE_MULTIPLE_DIFFERENT &&
+ result_join != QUERY_STYLE_NOTHING ) {
setJoinType(query->stroke_linejoin.value);
} else {
setJoinButtons(NULL);
}
- if (result_cap != QUERY_STYLE_MULTIPLE_DIFFERENT) {
+ if (result_cap != QUERY_STYLE_MULTIPLE_DIFFERENT &&
+ result_cap != QUERY_STYLE_NOTHING ) {
setCapType (query->stroke_linecap.value);
} else {
setCapButtons(NULL);
@@ -1176,11 +1185,11 @@ StrokeStyle::updateAllMarkers(GSList const *objects)
combo->setDesktop(desktop);
- if (object->style->marker[keyloc[i].loc].value != NULL && !all_texts) {
+ if (object->style->marker_ptrs[keyloc[i].loc]->value != NULL && !all_texts) {
// If the object has this type of markers,
// Extract the name of the marker that the object uses
- SPObject *marker = getMarkerObj(object->style->marker[keyloc[i].loc].value, object->document);
+ SPObject *marker = getMarkerObj(object->style->marker_ptrs[keyloc[i].loc]->value, object->document);
// Scroll the combobox to that marker
combo->set_current(marker);
diff --git a/src/widgets/stroke-style.h b/src/widgets/stroke-style.h
index 6f0fe583b..15e394097 100644
--- a/src/widgets/stroke-style.h
+++ b/src/widgets/stroke-style.h
@@ -12,6 +12,8 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
+// WHOA! talk about header bloat!
+
#ifndef SEEN_DIALOGS_STROKE_STYLE_H
#define SEEN_DIALOGS_STROKE_STYLE_H
@@ -33,7 +35,7 @@
#include "desktop.h"
#include "desktop-handles.h"
#include "desktop-style.h"
-#include "dialogs/dialog-events.h"
+#include "ui/dialog-events.h"
#include "display/canvas-bpath.h" // for SP_STROKE_LINEJOIN_*
#include "display/drawing.h"
#include "document-private.h"
@@ -42,7 +44,7 @@
#include "helper/stock-items.h"
#include "inkscape.h"
#include "io/sys.h"
-#include "marker.h"
+#include "sp-marker.h"
#include "preferences.h"
#include "path-prefix.h"
#include "selection.h"
diff --git a/src/widgets/text-toolbar.cpp b/src/widgets/text-toolbar.cpp
index 349fefa12..d62bb8027 100644
--- a/src/widgets/text-toolbar.cpp
+++ b/src/widgets/text-toolbar.cpp
@@ -31,16 +31,15 @@
#include "libnrtype/font-lister.h"
#include <glibmm/i18n.h>
#include "text-toolbar.h"
-#include "connection-pool.h"
#include "desktop-handles.h"
#include "desktop-style.h"
#include "desktop.h"
#include "document-undo.h"
#include "document.h"
-#include "ege-adjustment-action.h"
-#include "ege-select-one-action.h"
-#include "ink-action.h"
-#include "ink-comboboxentry-action.h"
+#include "widgets/ege-adjustment-action.h"
+#include "widgets/ege-select-one-action.h"
+#include "widgets/ink-action.h"
+#include "widgets/ink-comboboxentry-action.h"
#include "inkscape.h"
#include "preferences.h"
#include "selection-chemistry.h"
@@ -54,6 +53,7 @@
#include "toolbox.h"
#include "ui/icon-names.h"
#include "ui/tools/text-tool.h"
+#include "ui/tools/tool-base.h"
#include "verbs.h"
#include "xml/repr.h"
@@ -72,20 +72,20 @@ using Inkscape::UI::PrefPusher;
static void sp_print_font( SPStyle *query ) {
- bool family_set = query->text->font_family.set;
+ bool family_set = query->font_family.set;
bool style_set = query->font_style.set;
- bool fontspec_set = query->text->font_specification.set;
+ bool fontspec_set = query->font_specification.set;
std::cout << " Family set? " << family_set
<< " Style set? " << style_set
<< " FontSpec set? " << fontspec_set
<< std::endl;
std::cout << " Family: "
- << (query->text->font_family.value ? query->text->font_family.value : "No value")
+ << (query->font_family.value ? query->font_family.value : "No value")
<< " Style: " << query->font_style.computed
<< " Weight: " << query->font_weight.computed
<< " FontSpec: "
- << (query->text->font_specification.value ? query->text->font_specification.value : "No value")
+ << (query->font_specification.value ? query->font_specification.value : "No value")
<< std::endl;
std::cout << " LineHeight: " << query->line_height.computed
<< " WordSpacing: " << query->word_spacing.computed
@@ -134,6 +134,7 @@ static void sp_text_fontfamily_value_changed( Ink_ComboBoxEntry_Action *act, GOb
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE) );
Glib::ustring new_family = ink_comboboxentry_action_get_active_text( act );
+ css_font_family_unquote( new_family ); // Remove quotes around font family names.
// TODO: Think about how to handle handle multiple selections. While
// the font-family may be the same for all, the styles might be different.
@@ -146,6 +147,13 @@ static void sp_text_fontfamily_value_changed( Ink_ComboBoxEntry_Action *act, GOb
std::cout << " New active: " << act->active << std::endl;
#endif
if( new_family.compare( fontlister->get_font_family() ) != 0 ) {
+ // Changed font-family
+
+ if( act->active == -1 ) {
+ // New font-family, not in document, not on system (could be fallback list)
+ fontlister->insert_font_family( new_family );
+ act->active = 0; // New family is always at top of list.
+ }
std::pair<Glib::ustring,Glib::ustring> ui = fontlister->set_font_family( act->active );
// active text set in sp_text_toolbox_selection_changed()
@@ -811,7 +819,7 @@ static void sp_text_set_sizes(GtkListStore* model_size, int unit)
* It is called whenever a text selection is changed, including stepping cursor
* through text, or setting focus to text.
*/
-static void sp_text_toolbox_selection_changed(Inkscape::Selection */*selection*/, GObject *tbl)
+static void sp_text_toolbox_selection_changed(Inkscape::Selection */*selection*/, GObject *tbl, bool subselection = false) // don't bother to update font list if subsel changed
{
#ifdef DEBUG_TEXT
static int count = 0;
@@ -851,7 +859,9 @@ static void sp_text_toolbox_selection_changed(Inkscape::Selection */*selection*/
INK_COMBOBOXENTRY_ACTION( g_object_get_data( tbl, "TextFontStyleAction" ) );
Inkscape::FontLister* fontlister = Inkscape::FontLister::get_instance();
- fontlister->update_font_list( sp_desktop_document( SP_ACTIVE_DESKTOP ));
+ if (!subselection) {
+ fontlister->update_font_list( sp_desktop_document( SP_ACTIVE_DESKTOP ));
+ }
fontlister->selection_update();
// Update font list, but only if widget already created.
@@ -923,7 +933,6 @@ static void sp_text_toolbox_selection_changed(Inkscape::Selection */*selection*/
}
// If we have valid query data for text (font-family, font-specification) set toolbar accordingly.
- if (query->text)
{
// Size (average of text selected)
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
@@ -1051,11 +1060,11 @@ static void sp_text_toolbox_selection_changed(Inkscape::Selection */*selection*/
ege_select_one_action_set_active( textOrientationAction, activeButton2 );
- } // if( query->text )
+ }
#ifdef DEBUG_TEXT
std::cout << " GUI: fontfamily.value: "
- << (query->text->font_family.value ? query->text->font_family.value : "No value")
+ << (query->font_family.value ? query->font_family.value : "No value")
<< std::endl;
std::cout << " GUI: font_size.computed: " << query->font_size.computed << std::endl;
std::cout << " GUI: font_weight.computed: " << query->font_weight.computed << std::endl;
@@ -1147,7 +1156,7 @@ static void sp_text_toolbox_selection_modified(Inkscape::Selection *selection, g
static void
sp_text_toolbox_subselection_changed (gpointer /*tc*/, GObject *tbl)
{
- sp_text_toolbox_selection_changed (NULL, tbl);
+ sp_text_toolbox_selection_changed (NULL, tbl, true);
}
// TODO: possibly share with font-selector by moving most code to font-lister (passing family name)
@@ -1167,15 +1176,15 @@ static void sp_text_toolbox_select_cb( GtkEntry* entry, GtkEntryIconPosition /*p
SPItem *item = SP_ITEM(i->data);
SPStyle *style = item->style;
- if (style && style->text) {
+ if (style) {
Glib::ustring family_style;
- if (style->text->font_family.set) {
- family_style = style->text->font_family.value;
+ if (style->font_family.set) {
+ family_style = style->font_family.value;
//std::cout << " family style from font_family: " << family_style << std::endl;
}
- else if (style->text->font_specification.set) {
- family_style = style->text->font_specification.value;
+ else if (style->font_specification.set) {
+ family_style = style->font_specification.value;
//std::cout << " family style from font_spec: " << family_style << std::endl;
}
@@ -1193,6 +1202,7 @@ static void sp_text_toolbox_select_cb( GtkEntry* entry, GtkEntryIconPosition /*p
selection->setList(selectList);
}
+static void text_toolbox_watch_ec(SPDesktop* dt, Inkscape::UI::Tools::ToolBase* ec, GObject* holder);
// Define all the "widgets" in the toolbar.
void sp_text_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder)
@@ -1615,31 +1625,35 @@ void sp_text_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObje
// Is this necessary to call? Shouldn't hurt.
sp_text_toolbox_selection_changed(sp_desktop_selection(desktop), holder);
- // Watch selection
- Inkscape::ConnectionPool* pool = Inkscape::ConnectionPool::new_connection_pool ("ISTextToolboxGTK");
-
- sigc::connection *c_selection_changed =
- new sigc::connection (sp_desktop_selection (desktop)->connectChanged
- (sigc::bind (sigc::ptr_fun (sp_text_toolbox_selection_changed), holder)));
- pool->add_connection ("selection-changed", c_selection_changed);
-
- sigc::connection *c_selection_modified =
- new sigc::connection (sp_desktop_selection (desktop)->connectModified
- (sigc::bind (sigc::ptr_fun (sp_text_toolbox_selection_modified), holder)));
- pool->add_connection ("selection-modified", c_selection_modified);
-
- sigc::connection *c_subselection_changed =
- new sigc::connection (desktop->connectToolSubselectionChanged
- (sigc::bind (sigc::ptr_fun (sp_text_toolbox_subselection_changed), holder)));
- pool->add_connection ("tool-subselection-changed", c_subselection_changed);
-
- Inkscape::ConnectionPool::connect_destroy (G_OBJECT (holder), pool);
+ desktop->connectEventContextChanged(sigc::bind(sigc::ptr_fun(text_toolbox_watch_ec), holder));
g_signal_connect( holder, "destroy", G_CALLBACK(purge_repr_listener), holder );
}
+static void text_toolbox_watch_ec(SPDesktop* desktop, Inkscape::UI::Tools::ToolBase* ec, GObject* holder) {
+ using sigc::connection;
+ using sigc::bind;
+ using sigc::ptr_fun;
+
+ static connection c_selection_changed;
+ static connection c_selection_modified;
+ static connection c_subselection_changed;
+ if (SP_IS_TEXT_CONTEXT(ec)) {
+ // Watch selection
+ c_selection_changed = sp_desktop_selection(desktop)->connectChanged(bind(ptr_fun(sp_text_toolbox_selection_changed), holder, false));
+ c_selection_modified = sp_desktop_selection (desktop)->connectModified(bind(ptr_fun(sp_text_toolbox_selection_modified), holder));
+ c_subselection_changed = desktop->connectToolSubselectionChanged(bind(ptr_fun(sp_text_toolbox_subselection_changed), holder));
+ } else {
+ if (c_selection_changed)
+ c_selection_changed.disconnect();
+ if (c_selection_modified)
+ c_selection_modified.disconnect();
+ if (c_subselection_changed)
+ c_subselection_changed.disconnect();
+ }
+}
/*
Local Variables:
mode:c++
@@ -1649,4 +1663,4 @@ void sp_text_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObje
fill-column:99
End:
*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8 :
diff --git a/src/widgets/toolbox.cpp b/src/widgets/toolbox.cpp
index 02da805bf..9e55d1cf6 100644
--- a/src/widgets/toolbox.cpp
+++ b/src/widgets/toolbox.cpp
@@ -43,20 +43,20 @@
#include "../desktop-handles.h"
#include "../desktop-style.h"
#include "document-undo.h"
-#include "../ege-adjustment-action.h"
-#include "../ege-output-action.h"
-#include "../ege-select-one-action.h"
+#include "widgets/ege-adjustment-action.h"
+#include "widgets/ege-output-action.h"
+#include "widgets/ege-select-one-action.h"
#include "../graphlayout.h"
#include "../helper/action.h"
#include "../helper/action-context.h"
#include "icon.h"
-#include "../ink-action.h"
-#include "../ink-comboboxentry-action.h"
+#include "ink-action.h"
+#include "ink-comboboxentry-action.h"
#include "../inkscape.h"
-#include "../interface.h"
+#include "ui/interface.h"
#include "../shortcuts.h"
#include "../sp-namedview.h"
-#include "../tools-switch.h"
+#include "ui/tools-switch.h"
#include "../ui/icon-names.h"
#include "../ui/widget/style-swatch.h"
#include "../verbs.h"
@@ -314,8 +314,8 @@ static gchar const * ui_descr =
" <toolitem action='SprayModeAction' />"
" <separator />"
" <toolitem action='SprayWidthAction' />"
- " <toolitem action='SprayPressureAction' />"
" <toolitem action='SprayPopulationAction' />"
+ " <toolitem action='SprayPressureAction' />"
" <separator />"
" <toolitem action='SprayRotationAction' />"
" <toolitem action='SprayScaleAction' />"
@@ -1301,8 +1301,9 @@ void setup_tool_toolbox(GtkWidget *toolbox, SPDesktop *desktop)
" <toolitem action='ToolDropper' />"
" <toolitem action='ToolConnector' />"
-
-// " <toolitem action='ToolLPETool' />"
+#ifdef WITH_LPETOOL
+ " <toolitem action='ToolLPETool' />"
+#endif
" </toolbar>"
"</ui>";
diff --git a/src/widgets/toolbox.h b/src/widgets/toolbox.h
index fb749bfb5..db9130034 100644
--- a/src/widgets/toolbox.h
+++ b/src/widgets/toolbox.h
@@ -13,15 +13,15 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include <gtk/gtk.h>
#include <glibmm/ustring.h>
#include "icon-size.h"
-#include "../ege-adjustment-action.h"
-#include "../preferences.h"
+#include "preferences.h"
#define TOOLBAR_SLIDER_HINT "full"
+typedef struct _EgeAdjustmentAction EgeAdjustmentAction;
+
class SPDesktop;
namespace Inkscape {
diff --git a/src/widgets/tweak-toolbar.cpp b/src/widgets/tweak-toolbar.cpp
index 050d7fb5e..a5d90fc3d 100644
--- a/src/widgets/tweak-toolbar.cpp
+++ b/src/widgets/tweak-toolbar.cpp
@@ -33,10 +33,10 @@
#include "tweak-toolbar.h"
#include "desktop.h"
#include "document-undo.h"
-#include "ege-adjustment-action.h"
-#include "ege-output-action.h"
-#include "ege-select-one-action.h"
-#include "ink-action.h"
+#include "widgets/ege-adjustment-action.h"
+#include "widgets/ege-output-action.h"
+#include "widgets/ege-select-one-action.h"
+#include "widgets/ink-action.h"
#include "preferences.h"
#include "toolbox.h"
#include "ui/icon-names.h"
diff --git a/src/xml/event.h b/src/xml/event.h
index 55e2add88..d25ea0e07 100644
--- a/src/xml/event.h
+++ b/src/xml/event.h
@@ -18,7 +18,7 @@
#ifndef SEEN_INKSCAPE_XML_SP_REPR_ACTION_H
#define SEEN_INKSCAPE_XML_SP_REPR_ACTION_H
-#include <glib.h>
+typedef unsigned int GQuark;
#include <glibmm/ustring.h>
#include <iterator>
diff --git a/src/xml/helper-observer.cpp b/src/xml/helper-observer.cpp
index c54dd8e74..957f3df0a 100644
--- a/src/xml/helper-observer.cpp
+++ b/src/xml/helper-observer.cpp
@@ -5,25 +5,34 @@ namespace XML {
// Very simple observer that just emits a signal if anything happens to a node
SignalObserver::SignalObserver()
- : _oldsel(0)
+ : _oldsel(NULL)
{}
+SignalObserver::~SignalObserver()
+{
+ set(NULL); // if _oldsel!=nullptr, remove observer and decrease refcount
+}
+
// Add this observer to the SPObject and remove it from any previous object
void SignalObserver::set(SPObject* o)
{
// XML Tree being used direcly in this function in the following code
// while it shouldn't be
+ // Pointer to object is stored, so refcounting should be increased/decreased
if(_oldsel) {
if (_oldsel->getRepr()) {
_oldsel->getRepr()->removeObserver(*this);
}
+ sp_object_unref(_oldsel);
+ _oldsel = NULL;
}
if(o) {
if (o->getRepr()) {
o->getRepr()->addObserver(*this);
+ sp_object_ref(o);
+ _oldsel = o;
}
}
- _oldsel = o;
}
void SignalObserver::notifyChildAdded(XML::Node&, XML::Node&, XML::Node*)
diff --git a/src/xml/helper-observer.h b/src/xml/helper-observer.h
index e7881cd4d..b4c0aba41 100644
--- a/src/xml/helper-observer.h
+++ b/src/xml/helper-observer.h
@@ -1,36 +1,49 @@
-#ifndef __XML_HELPER_OBSERVER__
-#define __XML_HELPER_OBSERVER__
+#ifndef SEEN_XML_HELPER_OBSERVER
+#define SEEN_XML_HELPER_OBSERVER
+
+#include <cstddef>
+#include <sigc++/sigc++.h>
#include "node-observer.h"
#include "node.h"
-#include "../sp-object.h"
-//#include "../sp-object-repr.h"
-#include <stddef.h>
-#include <sigc++/sigc++.h>
+#include "sp-object.h"
namespace Inkscape {
- namespace XML {
- class Node;
-
- // Very simple observer that just emits a signal if anything happens to a node
- class SignalObserver : public NodeObserver
- {
- public:
- SignalObserver();
-
- // Add this observer to the SPObject and remove it from any previous object
- void set(SPObject* o);
- void notifyChildAdded(Node&, Node&, Node*);
- void notifyChildRemoved(Node&, Node&, Node*);
- void notifyChildOrderChanged(Node&, Node&, Node*, Node*);
- void notifyContentChanged(Node&, Util::ptr_shared<char>, Util::ptr_shared<char>);
- void notifyAttributeChanged(Node&, GQuark, Util::ptr_shared<char>, Util::ptr_shared<char>);
- sigc::signal<void>& signal_changed();
- private:
- sigc::signal<void> _signal_changed;
- SPObject* _oldsel;
- };
- }
+namespace XML {
+
+class Node;
+
+// Very simple observer that just emits a signal if anything happens to a node
+class SignalObserver : public NodeObserver {
+public:
+ SignalObserver();
+ ~SignalObserver();
+
+ // Add this observer to the SPObject and remove it from any previous object
+ void set(SPObject* o);
+ void notifyChildAdded(Node&, Node&, Node*);
+ void notifyChildRemoved(Node&, Node&, Node*);
+ void notifyChildOrderChanged(Node&, Node&, Node*, Node*);
+ void notifyContentChanged(Node&, Util::ptr_shared<char>, Util::ptr_shared<char>);
+ void notifyAttributeChanged(Node&, GQuark, Util::ptr_shared<char>, Util::ptr_shared<char>);
+ sigc::signal<void>& signal_changed();
+private:
+ sigc::signal<void> _signal_changed;
+ SPObject* _oldsel;
+};
+
+}
}
#endif //#ifndef __XML_HELPER_OBSERVER__
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8 :
diff --git a/src/xml/node-event-vector.h b/src/xml/node-event-vector.h
index e6396877d..16add2960 100644
--- a/src/xml/node-event-vector.h
+++ b/src/xml/node-event-vector.h
@@ -14,26 +14,11 @@
#ifndef SEEN_INKSCAPE_XML_SP_REPR_EVENT_VECTOR
#define SEEN_INKSCAPE_XML_SP_REPR_EVENT_VECTOR
-#include <glib.h>
-
#include "xml/node.h"
namespace Inkscape {
namespace XML {
-
-/**
- * @brief Structure holding callbacks for node state changes
- * @deprecated Derive an observer object from the NodeObserver class instead
- */
-struct NodeEventVector {
- /* Immediate signals */
- void (* child_added) (Node *repr, Node *child, Node *ref, void * data);
- void (* child_removed) (Node *repr, Node *child, Node *ref, void * data);
- void (* attr_changed) (Node *repr, const gchar *key, const gchar *oldval, const gchar *newval, bool is_interactive, void * data);
- void (* content_changed) (Node *repr, const gchar *oldcontent, const gchar *newcontent, void * data);
- void (* order_changed) (Node *repr, Node *child, Node *oldref, Node *newref, void * data);
-};
-
+struct NodeEventVector;
}
}
@@ -41,22 +26,41 @@ struct NodeEventVector {
* @brief Generate events corresponding to the node's state
* @deprecated Use Node::synthesizeEvents(NodeObserver &) instead
*/
-inline void sp_repr_synthesize_events (Inkscape::XML::Node *repr, const Inkscape::XML::NodeEventVector *vector, void * data) {
+inline void sp_repr_synthesize_events (Inkscape::XML::Node *repr, const Inkscape::XML::NodeEventVector *vector, void* data) {
repr->synthesizeEvents(vector, data);
}
/**
* @brief Add a set of callbacks for node state changes and its associated data
* @deprecated Use Node::addObserver() instead
*/
-inline void sp_repr_add_listener (Inkscape::XML::Node *repr, const Inkscape::XML::NodeEventVector *vector, void * data) {
+inline void sp_repr_add_listener (Inkscape::XML::Node *repr, const Inkscape::XML::NodeEventVector *vector, void* data) {
repr->addListener(vector, data);
}
/**
* @brief Remove a set of callbacks based on associated data
* @deprecated Use Node::removeObserver() instead
*/
-inline void sp_repr_remove_listener_by_data (Inkscape::XML::Node *repr, void * data) {
+inline void sp_repr_remove_listener_by_data (Inkscape::XML::Node *repr, void* data) {
repr->removeListenerByData(data);
}
+namespace Inkscape {
+namespace XML {
+
+/**
+ * @brief Structure holding callbacks for node state changes
+ * @deprecated Derive an observer object from the NodeObserver class instead
+ */
+struct NodeEventVector {
+ /* Immediate signals */
+ void (* child_added) (Node *repr, Node *child, Node *ref, void* data);
+ void (* child_removed) (Node *repr, Node *child, Node *ref, void* data);
+ void (* attr_changed) (Node *repr, char const *key, char const *oldval, char const *newval, bool is_interactive, void* data);
+ void (* content_changed) (Node *repr, char const *oldcontent, char const *newcontent, void * data);
+ void (* order_changed) (Node *repr, Node *child, Node *oldref, Node *newref, void* data);
+};
+
+}
+}
+
#endif
diff --git a/src/xml/node-observer.h b/src/xml/node-observer.h
index d0c85d1dd..9c7e096e5 100644
--- a/src/xml/node-observer.h
+++ b/src/xml/node-observer.h
@@ -18,8 +18,8 @@
#ifndef SEEN_INKSCAPE_XML_NODE_OBSERVER_H
#define SEEN_INKSCAPE_XML_NODE_OBSERVER_H
-#include <glib.h>
#include "util/share.h"
+typedef unsigned int GQuark;
#ifndef INK_UNUSED
#define INK_UNUSED(x) ((void)(x))
@@ -56,7 +56,9 @@ protected:
NodeObserver() {}
public:
virtual ~NodeObserver() {}
-
+
+ // FIXME: somebody needs to learn what "pure virtual" means
+
/**
* @brief Child addition callback
*
diff --git a/src/xml/node.h b/src/xml/node.h
index c1977b0a8..8bb70acc0 100644
--- a/src/xml/node.h
+++ b/src/xml/node.h
@@ -18,7 +18,6 @@
#ifndef SEEN_INKSCAPE_XML_NODE_H
#define SEEN_INKSCAPE_XML_NODE_H
-#include <glibmm/value.h>
#include <glibmm/ustring.h>
#include "gc-anchored.h"
#include "util/list.h"
@@ -100,7 +99,7 @@ public:
*
* @return Name for element nodes, NULL for others
*/
- virtual gchar const *name() const=0;
+ virtual char const *name() const=0;
/**
* @brief Get the integer code corresponding to the node's name
* @return GQuark code corresponding to the name
@@ -131,7 +130,7 @@ public:
*
* @return The node's content
*/
- virtual gchar const *content() const=0;
+ virtual char const *content() const=0;
/**
* @brief Get the string representation of a node's attribute
@@ -144,7 +143,7 @@ public:
*
* @param key The name of the node's attribute
*/
- virtual gchar const *attribute(gchar const *key) const=0;
+ virtual char const *attribute(char const *key) const=0;
/**
* @brief Get a list of the node's attributes
@@ -168,7 +167,7 @@ public:
* @param partial_name The string to match against all attributes
* @return true if there is such an attribute, false otherwise
*/
- virtual bool matchAttributeName(gchar const *partial_name) const=0;
+ virtual bool matchAttributeName(char const *partial_name) const=0;
/*@}*/
@@ -193,7 +192,7 @@ public:
*
* @param value The node's new content
*/
- virtual void setContent(gchar const *value)=0;
+ virtual void setContent(char const *value)=0;
//@{
/**
@@ -205,7 +204,7 @@ public:
* @param value The new value of the attribute
* @param is_interactive Ignored
*/
- virtual void setAttribute(gchar const *key, gchar const *value, bool is_interactive=false)=0;
+ virtual void setAttribute(char const *key, char const *value, bool is_interactive=false)=0;
void setAttribute(char const *key, Glib::ustring const &value, bool is_interactive=false)
{
@@ -399,7 +398,7 @@ public:
* @param src The node to merge into this node
* @param key The attribute to use as the identity attribute
*/
- virtual void mergeFrom(Node const *src, gchar const *key)=0;
+ virtual void mergeFrom(Node const *src, char const *key)=0;
/*@}*/
diff --git a/src/xml/pi-node.h b/src/xml/pi-node.h
index 1f892f97a..76a3dc741 100644
--- a/src/xml/pi-node.h
+++ b/src/xml/pi-node.h
@@ -14,7 +14,6 @@
#ifndef SEEN_INKSCAPE_XML_PI_NODE_H
#define SEEN_INKSCAPE_XML_PI_NODE_H
-#include <glib.h>
#include "xml/simple-node.h"
namespace Inkscape {
diff --git a/src/xml/quote.h b/src/xml/quote.h
index 8e3bca0eb..393bdf46e 100644
--- a/src/xml/quote.h
+++ b/src/xml/quote.h
@@ -1,7 +1,7 @@
#ifndef SEEN_XML_QUOTE_H
#define SEEN_XML_QUOTE_H
-#include <stddef.h>
+#include <cstddef>
size_t xml_quoted_strlen(char const *val);
char *xml_quote_strdup(char const *src);
diff --git a/src/xml/rebase-hrefs.h b/src/xml/rebase-hrefs.h
index 5baf96516..34afe6076 100644
--- a/src/xml/rebase-hrefs.h
+++ b/src/xml/rebase-hrefs.h
@@ -1,7 +1,6 @@
#ifndef REBASE_HREFS_H_SEEN
#define REBASE_HREFS_H_SEEN
-#include <glib.h>
#include "util/list.h"
#include "xml/attribute-record.h"
class SPDocument;
@@ -9,7 +8,7 @@ class SPDocument;
namespace Inkscape {
namespace XML {
-std::string calc_abs_doc_base(gchar const *doc_base);
+std::string calc_abs_doc_base(char const *doc_base);
/**
* Change relative hrefs in doc to be relative to \a new_base instead of doc.base.
@@ -18,7 +17,7 @@ std::string calc_abs_doc_base(gchar const *doc_base);
*
* @param spns True if doc should contain sodipodi:absref attributes.
*/
-void rebase_hrefs(SPDocument *doc, gchar const *new_base, bool spns);
+void rebase_hrefs(SPDocument *doc, char const *new_base, bool spns);
/**
* Change relative xlink:href attributes to be relative to \a new_abs_base instead of old_abs_base.
@@ -26,8 +25,8 @@ void rebase_hrefs(SPDocument *doc, gchar const *new_base, bool spns);
* Note that old_abs_base and new_abs_base must each be non-NULL, absolute directory paths.
*/
Inkscape::Util::List<AttributeRecord const> rebase_href_attrs(
- gchar const *old_abs_base,
- gchar const *new_abs_base,
+ char const *old_abs_base,
+ char const *new_abs_base,
Inkscape::Util::List<AttributeRecord const> attributes);
diff --git a/src/xml/repr-css.cpp b/src/xml/repr-css.cpp
index 24e2db9e1..c043904a7 100644
--- a/src/xml/repr-css.cpp
+++ b/src/xml/repr-css.cpp
@@ -12,7 +12,7 @@
* changing an item in the List. Utility functions are provided to go back and forth between the
* two ways of representing properties (by a string or by a list).
*
- * Use sp_repr_write_string to go from a property list to a style string.
+ * Use sp_repr_css_write_string to go from a property list to a style string.
*
*/
@@ -283,14 +283,7 @@ void sp_repr_css_write_string(SPCSSAttr *css, Glib::ustring &str)
str.append(g_quark_to_string(iter->key));
str.push_back(':');
- if (!strcmp(g_quark_to_string(iter->key), "font-family")
- || !strcmp(g_quark_to_string(iter->key), "-inkscape-font-specification")) {
- // we only quote font-family/font-specification, as SPStyle does
- Glib::ustring val_quoted = css2_escape_quote (iter->value);
- str.append(val_quoted);
- } else {
- str.append(iter->value); // unquoted
- }
+ str.append(iter->value); // Any necessary quoting to be done by calling routine.
if (rest(iter)) {
str.push_back(';');
@@ -346,13 +339,24 @@ void sp_repr_css_merge(SPCSSAttr *dst, SPCSSAttr *src)
/**
* Merges style properties as parsed by libcroco into an existing SPCSSAttr.
+ * libcroco converts all single quotes to double quotes, which needs to be
+ * undone as we always use single quotes inside our 'style' strings since
+ * double quotes are used outside: e.g.:
+ * style="font-family:'DejaVu Sans'"
*/
static void sp_repr_css_merge_from_decl(SPCSSAttr *css, CRDeclaration const *const decl)
{
guchar *const str_value_unsigned = cr_term_to_string(decl->value);
- gchar *const str_value = reinterpret_cast<gchar *>(str_value_unsigned);
- gchar *value_unquoted = attribute_unquote (str_value); // libcroco returns strings quoted in ""
- Glib::ustring value_unquoted2 = value_unquoted ? value_unquoted : Glib::ustring();
+
+ Glib::ustring value( reinterpret_cast<gchar *>(str_value_unsigned ) );
+ g_free(str_value_unsigned);
+
+ Glib::ustring::size_type pos = 0;
+ while( (pos=value.find("\"",pos)) != Glib::ustring::npos) {
+ value.replace(pos,1,"'");
+ ++pos;
+ }
+
Glib::ustring units;
/*
@@ -362,11 +366,11 @@ static void sp_repr_css_merge_from_decl(SPCSSAttr *css, CRDeclaration const *con
*
* HACK for now is to strip off em and ex units and add them back at the end
*/
- int le = value_unquoted2.length();
+ int le = value.length();
if (le > 2) {
- units = value_unquoted2.substr(le-2, 2);
+ units = value.substr(le-2, 2);
if ((units == "em") || (units == "ex")) {
- value_unquoted2 = value_unquoted2.substr(0, le-2);
+ value = value.substr(0, le-2);
}
else {
units.clear();
@@ -377,12 +381,15 @@ static void sp_repr_css_merge_from_decl(SPCSSAttr *css, CRDeclaration const *con
// CSSOStringStream is used here to write valid CSS (as in sp_style_write_string). This has
// the additional benefit of respecting the numerical precission set in the SVG Output
// preferences. We assume any numerical part comes first (if not, the whole string is copied).
- std::stringstream ss( value_unquoted2 );
+ std::stringstream ss( value );
double number = 0;
std::string characters;
std::string temp;
bool number_valid = !(ss >> number).fail();
- if( !number_valid ) ss.clear();
+ if (!number_valid) {
+ ss.clear();
+ ss.seekg(0); // work-around for a bug in libc++ (see lp:1300271)
+ }
while( !(ss >> temp).eof() ) {
characters += temp;
characters += " ";
@@ -396,8 +403,6 @@ static void sp_repr_css_merge_from_decl(SPCSSAttr *css, CRDeclaration const *con
//g_message("sp_repr_css_merge_from_decl looks like em or ex units %s --> %s", str_value, os.str().c_str());
}
((Node *) css)->setAttribute(decl->property->stryng->str, os.str().c_str(), false);
- g_free(value_unquoted);
- g_free(str_value);
}
/**
diff --git a/src/xml/repr-io.cpp b/src/xml/repr-io.cpp
index 0319bb5e3..a4146f215 100644
--- a/src/xml/repr-io.cpp
+++ b/src/xml/repr-io.cpp
@@ -623,7 +623,6 @@ static Node *sp_repr_svg_read_node (Document *xml_doc, xmlNodePtr node, const gc
repr->setContent(reinterpret_cast<gchar*>(node->content));
}
- child = node->xmlChildrenNode;
for (child = node->xmlChildrenNode; child != NULL; child = child->next) {
Node *crepr = sp_repr_svg_read_node (xml_doc, child, default_ns, prefix_map);
if (crepr) {
diff --git a/src/xml/repr.h b/src/xml/repr.h
index e691eaa7f..e1d7fdfd6 100644
--- a/src/xml/repr.h
+++ b/src/xml/repr.h
@@ -14,7 +14,6 @@
#ifndef SEEN_SP_REPR_H
#define SEEN_SP_REPR_H
-#include <glib.h>
#include <glibmm/quark.h>
#include "xml/node.h"
@@ -43,55 +42,55 @@ class Point;
}
/* SPXMLNs */
-char const *sp_xml_ns_uri_prefix(gchar const *uri, gchar const *suggested);
-char const *sp_xml_ns_prefix_uri(gchar const *prefix);
+char const *sp_xml_ns_uri_prefix(char const *uri, char const *suggested);
+char const *sp_xml_ns_prefix_uri(char const *prefix);
-Inkscape::XML::Document *sp_repr_document_new(gchar const *rootname);
+Inkscape::XML::Document *sp_repr_document_new(char const *rootname);
/* IO */
-Inkscape::XML::Document *sp_repr_read_file(gchar const *filename, gchar const *default_ns);
-Inkscape::XML::Document *sp_repr_read_mem(gchar const *buffer, int length, gchar const *default_ns);
+Inkscape::XML::Document *sp_repr_read_file(char const *filename, char const *default_ns);
+Inkscape::XML::Document *sp_repr_read_mem(char const *buffer, int length, char const *default_ns);
void sp_repr_write_stream(Inkscape::XML::Node *repr, Inkscape::IO::Writer &out,
- gint indent_level, bool add_whitespace, Glib::QueryQuark elide_prefix,
+ int indent_level, bool add_whitespace, Glib::QueryQuark elide_prefix,
int inlineattrs, int indent,
- gchar const *old_href_base = NULL,
- gchar const *new_href_base = NULL);
-Inkscape::XML::Document *sp_repr_read_buf (const Glib::ustring &buf, const gchar *default_ns);
+ char const *old_href_base = NULL,
+ char const *new_href_base = NULL);
+Inkscape::XML::Document *sp_repr_read_buf (const Glib::ustring &buf, const char *default_ns);
Glib::ustring sp_repr_save_buf(Inkscape::XML::Document *doc);
// TODO convert to std::string
void sp_repr_save_stream(Inkscape::XML::Document *doc, FILE *to_file,
- gchar const *default_ns = NULL, bool compress = false,
- gchar const *old_href_base = NULL,
- gchar const *new_href_base = NULL);
+ char const *default_ns = NULL, bool compress = false,
+ char const *old_href_base = NULL,
+ char const *new_href_base = NULL);
-bool sp_repr_save_file(Inkscape::XML::Document *doc, gchar const *filename, gchar const *default_ns=NULL);
-bool sp_repr_save_rebased_file(Inkscape::XML::Document *doc, gchar const *filename_utf8,
- gchar const *default_ns,
- gchar const *old_base, gchar const *new_base_filename);
+bool sp_repr_save_file(Inkscape::XML::Document *doc, char const *filename, char const *default_ns=NULL);
+bool sp_repr_save_rebased_file(Inkscape::XML::Document *doc, char const *filename_utf8,
+ char const *default_ns,
+ char const *old_base, char const *new_base_filename);
/* CSS stuff */
SPCSSAttr *sp_repr_css_attr_new(void);
void sp_repr_css_attr_unref(SPCSSAttr *css);
-SPCSSAttr *sp_repr_css_attr(Inkscape::XML::Node *repr, gchar const *attr);
+SPCSSAttr *sp_repr_css_attr(Inkscape::XML::Node *repr, char const *attr);
SPCSSAttr *sp_repr_css_attr_parse_color_to_fill(const Glib::ustring &text);
-SPCSSAttr *sp_repr_css_attr_inherited(Inkscape::XML::Node *repr, gchar const *attr);
+SPCSSAttr *sp_repr_css_attr_inherited(Inkscape::XML::Node *repr, char const *attr);
-gchar const *sp_repr_css_property(SPCSSAttr *css, gchar const *name, gchar const *defval);
-void sp_repr_css_set_property(SPCSSAttr *css, gchar const *name, gchar const *value);
-void sp_repr_css_unset_property(SPCSSAttr *css, gchar const *name);
-bool sp_repr_css_property_is_unset(SPCSSAttr *css, gchar const *name);
-double sp_repr_css_double_property(SPCSSAttr *css, gchar const *name, double defval);
+char const *sp_repr_css_property(SPCSSAttr *css, char const *name, char const *defval);
+void sp_repr_css_set_property(SPCSSAttr *css, char const *name, char const *value);
+void sp_repr_css_unset_property(SPCSSAttr *css, char const *name);
+bool sp_repr_css_property_is_unset(SPCSSAttr *css, char const *name);
+double sp_repr_css_double_property(SPCSSAttr *css, char const *name, double defval);
void sp_repr_css_write_string(SPCSSAttr *css, Glib::ustring &str);
-void sp_repr_css_set(Inkscape::XML::Node *repr, SPCSSAttr *css, gchar const *key);
+void sp_repr_css_set(Inkscape::XML::Node *repr, SPCSSAttr *css, char const *key);
void sp_repr_css_merge(SPCSSAttr *dst, SPCSSAttr *src);
-void sp_repr_css_attr_add_from_string(SPCSSAttr *css, const gchar *data);
-void sp_repr_css_change(Inkscape::XML::Node *repr, SPCSSAttr *css, gchar const *key);
-void sp_repr_css_change_recursive(Inkscape::XML::Node *repr, SPCSSAttr *css, gchar const *key);
+void sp_repr_css_attr_add_from_string(SPCSSAttr *css, const char *data);
+void sp_repr_css_change(Inkscape::XML::Node *repr, SPCSSAttr *css, char const *key);
+void sp_repr_css_change_recursive(Inkscape::XML::Node *repr, SPCSSAttr *css, char const *key);
void sp_repr_css_print(SPCSSAttr *css);
@@ -109,15 +108,15 @@ inline void sp_repr_unparent(Inkscape::XML::Node *repr) {
bool sp_repr_is_meta_element(const Inkscape::XML::Node *node);
/* Convenience */
-unsigned sp_repr_get_boolean(Inkscape::XML::Node *repr, gchar const *key, unsigned *val);
-unsigned sp_repr_get_int(Inkscape::XML::Node *repr, gchar const *key, int *val);
-unsigned sp_repr_get_double(Inkscape::XML::Node *repr, gchar const *key, double *val);
-unsigned sp_repr_set_boolean(Inkscape::XML::Node *repr, gchar const *key, unsigned val);
-unsigned sp_repr_set_int(Inkscape::XML::Node *repr, gchar const *key, int val);
-unsigned sp_repr_set_css_double(Inkscape::XML::Node *repr, gchar const *key, double val);
-unsigned sp_repr_set_svg_double(Inkscape::XML::Node *repr, gchar const *key, double val);
-unsigned sp_repr_set_point(Inkscape::XML::Node *repr, gchar const *key, Geom::Point const & val);
-unsigned sp_repr_get_point(Inkscape::XML::Node *repr, gchar const *key, Geom::Point *val);
+unsigned sp_repr_get_boolean(Inkscape::XML::Node *repr, char const *key, unsigned *val);
+unsigned sp_repr_get_int(Inkscape::XML::Node *repr, char const *key, int *val);
+unsigned sp_repr_get_double(Inkscape::XML::Node *repr, char const *key, double *val);
+unsigned sp_repr_set_boolean(Inkscape::XML::Node *repr, char const *key, unsigned val);
+unsigned sp_repr_set_int(Inkscape::XML::Node *repr, char const *key, int val);
+unsigned sp_repr_set_css_double(Inkscape::XML::Node *repr, char const *key, double val);
+unsigned sp_repr_set_svg_double(Inkscape::XML::Node *repr, char const *key, double val);
+unsigned sp_repr_set_point(Inkscape::XML::Node *repr, char const *key, Geom::Point const & val);
+unsigned sp_repr_get_point(Inkscape::XML::Node *repr, char const *key, Geom::Point *val);
int sp_repr_compare_position(Inkscape::XML::Node const *first, Inkscape::XML::Node const *second);
@@ -135,16 +134,16 @@ int sp_repr_compare_position(Inkscape::XML::Node const *first, Inkscape::XML::No
* @relatesalso Inkscape::XML::Node
*/
Inkscape::XML::Node *sp_repr_lookup_name(Inkscape::XML::Node *repr,
- gchar const *name,
- gint maxdepth = -1);
+ char const *name,
+ int maxdepth = -1);
Inkscape::XML::Node const *sp_repr_lookup_name(Inkscape::XML::Node const *repr,
- gchar const *name,
- gint maxdepth = -1);
+ char const *name,
+ int maxdepth = -1);
Inkscape::XML::Node *sp_repr_lookup_child(Inkscape::XML::Node *repr,
- gchar const *key,
- gchar const *value);
+ char const *key,
+ char const *value);
inline Inkscape::XML::Node *sp_repr_document_first_child(Inkscape::XML::Document const *doc) {
diff --git a/src/xml/simple-node.h b/src/xml/simple-node.h
index 7c5eb8fbd..1fcb9193b 100644
--- a/src/xml/simple-node.h
+++ b/src/xml/simple-node.h
@@ -18,7 +18,7 @@
#ifndef SEEN_INKSCAPE_XML_SIMPLE_NODE_H
#define SEEN_INKSCAPE_XML_SIMPLE_NODE_H
-#include <glib.h> // g_assert()
+#include <cassert>
#include "xml/node.h"
#include "xml/attribute-record.h"
@@ -38,7 +38,7 @@ class SimpleNode
: virtual public Node, public Inkscape::GC::Managed<>
{
public:
- gchar const *name() const;
+ char const *name() const;
int code() const { return _name; }
void setCodeUnsafe(int code) {
_name = code;
@@ -83,14 +83,14 @@ public:
unsigned position() const;
void setPosition(int pos);
- gchar const *attribute(gchar const *key) const;
- void setAttribute(gchar const *key, gchar const *value, bool is_interactive=false);
- bool matchAttributeName(gchar const *partial_name) const;
+ char const *attribute(char const *key) const;
+ void setAttribute(char const *key, char const *value, bool is_interactive=false);
+ bool matchAttributeName(char const *partial_name) const;
- gchar const *content() const;
- void setContent(gchar const *value);
+ char const *content() const;
+ void setContent(char const *value);
- void mergeFrom(Node const *src, gchar const *key);
+ void mergeFrom(Node const *src, char const *key);
Inkscape::Util::List<AttributeRecord const> attributeList() const {
return _attributes;
@@ -100,7 +100,7 @@ public:
void synthesizeEvents(NodeObserver &observer);
void addListener(NodeEventVector const *vector, void *data) {
- g_assert(vector != NULL);
+ assert(vector != NULL);
_observers.addListener(*vector, data);
}
void addObserver(NodeObserver &observer) {