summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorKrzysztof Kosi??ski <tweenk.pl@gmail.com>2011-06-20 19:33:57 +0000
committerKrzysztof KosiƄski <tweenk.pl@gmail.com>2011-06-20 19:33:57 +0000
commita39e3c37a508f9a389fc55270ae0336ad2f76f0e (patch)
tree952db81c3238005e975f21845734444bba28ff40 /src
parentMeasure Tool: support measuring of text elements (without having to manually ... (diff)
parentFix outline view (diff)
downloadinkscape-a39e3c37a508f9a389fc55270ae0336ad2f76f0e.tar.gz
inkscape-a39e3c37a508f9a389fc55270ae0336ad2f76f0e.zip
Merge Cairo rendering branch
(bzr r10326)
Diffstat (limited to 'src')
-rw-r--r--src/2geom/Makefile_insert2
-rw-r--r--src/Makefile.am4
-rw-r--r--src/Makefile_insert3
-rw-r--r--src/box3d.cpp6
-rw-r--r--src/color-profile-fns.h1
-rw-r--r--src/color-profile.cpp73
-rw-r--r--src/color-rgba.h11
-rw-r--r--src/desktop-style.cpp6
-rw-r--r--src/desktop.cpp2
-rw-r--r--src/dialogs/clonetiler.cpp88
-rw-r--r--src/dialogs/text-edit.cpp74
-rw-r--r--src/display/Makefile_insert108
-rw-r--r--src/display/cairo-templates.h689
-rw-r--r--src/display/cairo-utils.cpp700
-rw-r--r--src/display/cairo-utils.h153
-rw-r--r--src/display/canvas-arena.cpp51
-rw-r--r--src/display/canvas-arena.h9
-rw-r--r--src/display/canvas-axonomgrid.cpp96
-rw-r--r--src/display/canvas-bpath.cpp38
-rw-r--r--src/display/canvas-grid.cpp148
-rw-r--r--src/display/canvas-text.cpp24
-rw-r--r--src/display/display-forward.h32
-rw-r--r--src/display/grayscale.cpp14
-rw-r--r--src/display/grayscale.h4
-rw-r--r--src/display/guideline.cpp181
-rw-r--r--src/display/inkscape-cairo.cpp248
-rw-r--r--src/display/inkscape-cairo.h37
-rw-r--r--src/display/nr-3dutils.cpp125
-rw-r--r--src/display/nr-3dutils.h32
-rw-r--r--src/display/nr-arena-glyphs.cpp404
-rw-r--r--src/display/nr-arena-glyphs.h20
-rw-r--r--src/display/nr-arena-group.cpp8
-rw-r--r--src/display/nr-arena-image.cpp270
-rw-r--r--src/display/nr-arena-image.h32
-rw-r--r--src/display/nr-arena-item.cpp418
-rw-r--r--src/display/nr-arena-item.h79
-rw-r--r--src/display/nr-arena-shape.cpp1098
-rw-r--r--src/display/nr-arena-shape.h166
-rw-r--r--src/display/nr-arena.cpp37
-rw-r--r--src/display/nr-arena.h2
-rw-r--r--src/display/nr-filter-blend.cpp274
-rw-r--r--src/display/nr-filter-blend.h5
-rw-r--r--src/display/nr-filter-colormatrix.cpp307
-rw-r--r--src/display/nr-filter-colormatrix.h13
-rw-r--r--src/display/nr-filter-component-transfer.cpp426
-rw-r--r--src/display/nr-filter-component-transfer.h9
-rw-r--r--src/display/nr-filter-composite.cpp186
-rw-r--r--src/display/nr-filter-composite.h3
-rw-r--r--src/display/nr-filter-convolve-matrix.cpp262
-rw-r--r--src/display/nr-filter-convolve-matrix.h7
-rw-r--r--src/display/nr-filter-diffuselighting.cpp255
-rw-r--r--src/display/nr-filter-diffuselighting.h21
-rw-r--r--src/display/nr-filter-displacement-map.cpp91
-rw-r--r--src/display/nr-filter-displacement-map.h6
-rw-r--r--src/display/nr-filter-flood.cpp91
-rw-r--r--src/display/nr-filter-flood.h10
-rw-r--r--src/display/nr-filter-gaussian.cpp569
-rw-r--r--src/display/nr-filter-gaussian.h10
-rw-r--r--src/display/nr-filter-getalpha.cpp56
-rw-r--r--src/display/nr-filter-getalpha.h35
-rw-r--r--src/display/nr-filter-image.cpp361
-rw-r--r--src/display/nr-filter-image.h14
-rw-r--r--src/display/nr-filter-merge.cpp101
-rw-r--r--src/display/nr-filter-merge.h7
-rw-r--r--src/display/nr-filter-morphology.cpp189
-rw-r--r--src/display/nr-filter-morphology.h7
-rw-r--r--src/display/nr-filter-offset.cpp47
-rw-r--r--src/display/nr-filter-offset.h3
-rw-r--r--src/display/nr-filter-pixops.h104
-rw-r--r--src/display/nr-filter-primitive.cpp9
-rw-r--r--src/display/nr-filter-primitive.h31
-rw-r--r--src/display/nr-filter-skeleton.cpp18
-rw-r--r--src/display/nr-filter-skeleton.h2
-rw-r--r--src/display/nr-filter-slot.cpp429
-rw-r--r--src/display/nr-filter-slot.h82
-rw-r--r--src/display/nr-filter-specularlighting.cpp169
-rw-r--r--src/display/nr-filter-specularlighting.h27
-rw-r--r--src/display/nr-filter-tile.cpp36
-rw-r--r--src/display/nr-filter-tile.h8
-rw-r--r--src/display/nr-filter-turbulence.cpp601
-rw-r--r--src/display/nr-filter-turbulence.h46
-rw-r--r--src/display/nr-filter-units.h14
-rw-r--r--src/display/nr-filter.cpp188
-rw-r--r--src/display/nr-filter.h24
-rw-r--r--src/display/nr-light.cpp20
-rw-r--r--src/display/nr-plain-stuff-gdk.cpp46
-rw-r--r--src/display/nr-plain-stuff-gdk.h32
-rw-r--r--src/display/nr-plain-stuff.cpp94
-rw-r--r--src/display/nr-plain-stuff.h33
-rw-r--r--src/display/nr-style.cpp218
-rw-r--r--src/display/nr-style.h81
-rw-r--r--src/display/nr-svgfonts.cpp18
-rw-r--r--src/display/pixblock-scaler.cpp299
-rw-r--r--src/display/pixblock-scaler.h40
-rw-r--r--src/display/pixblock-transform.cpp279
-rw-r--r--src/display/pixblock-transform.h35
-rw-r--r--src/display/sodipodi-ctrl.cpp238
-rw-r--r--src/display/sodipodi-ctrl.h2
-rw-r--r--src/display/sodipodi-ctrlrect.cpp35
-rw-r--r--src/display/sp-canvas-util.cpp39
-rw-r--r--src/display/sp-canvas-util.h5
-rw-r--r--src/display/sp-canvas.cpp184
-rw-r--r--src/display/sp-canvas.h14
-rw-r--r--src/display/sp-ctrlline.cpp17
-rw-r--r--src/display/sp-ctrlpoint.cpp2
-rw-r--r--src/display/sp-ctrlquadr.cpp7
-rw-r--r--src/display/testnr.cpp24
-rw-r--r--src/draw-context.cpp1
-rw-r--r--src/dropper-context.cpp74
-rw-r--r--src/dyna-draw-context.cpp21
-rw-r--r--src/extension/extension.h9
-rw-r--r--src/extension/init.cpp2
-rw-r--r--src/extension/internal/Makefile_insert2
-rw-r--r--src/extension/internal/cairo-render-context.cpp2
-rw-r--r--src/extension/internal/cairo-render-context.h1
-rw-r--r--src/extension/internal/emf-win32-inout.cpp61
-rw-r--r--src/extension/internal/emf-win32-print.cpp118
-rw-r--r--src/extension/internal/emf-win32-print.h3
-rw-r--r--src/extension/internal/win32.cpp510
-rw-r--r--src/extension/internal/win32.h96
-rw-r--r--src/file.cpp15
-rw-r--r--src/file.h5
-rw-r--r--src/filter-chemistry.cpp3
-rw-r--r--src/filter-chemistry.h11
-rw-r--r--src/filters/Makefile_insert91
-rw-r--r--src/filters/blend-fns.h38
-rw-r--r--src/filters/blend.cpp3
-rw-r--r--src/filters/blend.h23
-rw-r--r--src/filters/colormatrix-fns.h38
-rw-r--r--src/filters/colormatrix.cpp1
-rw-r--r--src/filters/colormatrix.h26
-rw-r--r--src/filters/componenttransfer-fns.h38
-rw-r--r--src/filters/componenttransfer.cpp5
-rw-r--r--src/filters/componenttransfer.h31
-rw-r--r--src/filters/composite-fns.h38
-rw-r--r--src/filters/composite.cpp4
-rw-r--r--src/filters/composite.h23
-rw-r--r--src/filters/convolvematrix-fns.h38
-rw-r--r--src/filters/convolvematrix.cpp6
-rw-r--r--src/filters/convolvematrix.h25
-rw-r--r--src/filters/diffuselighting-fns.h38
-rw-r--r--src/filters/diffuselighting.cpp6
-rw-r--r--src/filters/diffuselighting.h43
-rw-r--r--src/filters/displacementmap-fns.h38
-rw-r--r--src/filters/displacementmap.cpp6
-rw-r--r--src/filters/displacementmap.h23
-rw-r--r--src/filters/distantlight.cpp6
-rw-r--r--src/filters/flood-fns.h38
-rw-r--r--src/filters/flood.cpp5
-rw-r--r--src/filters/flood.h25
-rw-r--r--src/filters/gaussian-blur.cpp (renamed from src/sp-gaussian-blur.cpp)2
-rw-r--r--src/filters/gaussian-blur.h (renamed from src/sp-gaussian-blur-fns.h)41
-rw-r--r--src/filters/image-fns.h38
-rw-r--r--src/filters/image.h25
-rw-r--r--src/filters/merge-fns.h38
-rw-r--r--src/filters/merge.cpp1
-rw-r--r--src/filters/merge.h21
-rw-r--r--src/filters/mergenode.cpp5
-rw-r--r--src/filters/morphology-fns.h38
-rw-r--r--src/filters/morphology.cpp1
-rw-r--r--src/filters/morphology.h22
-rw-r--r--src/filters/offset-fns.h38
-rw-r--r--src/filters/offset.cpp3
-rw-r--r--src/filters/offset.h24
-rw-r--r--src/filters/pointlight.cpp6
-rw-r--r--src/filters/specularlighting-fns.h38
-rw-r--r--src/filters/specularlighting.cpp6
-rw-r--r--src/filters/specularlighting.h30
-rw-r--r--src/filters/spotlight.cpp6
-rw-r--r--src/filters/tile-fns.h38
-rw-r--r--src/filters/tile.cpp5
-rw-r--r--src/filters/tile.h25
-rw-r--r--src/filters/turbulence-fns.h38
-rw-r--r--src/filters/turbulence.h22
-rw-r--r--src/flood-context.cpp157
-rw-r--r--src/gradient-chemistry.cpp5
-rw-r--r--src/gradient-context.cpp3
-rw-r--r--src/helper/geom.cpp4
-rw-r--r--src/helper/pixbuf-ops.cpp87
-rw-r--r--src/helper/png-write.cpp88
-rw-r--r--src/inkscape.cpp14
-rw-r--r--src/interface.cpp4
-rw-r--r--src/io/sys.cpp6
-rw-r--r--src/io/uristream.cpp17
-rw-r--r--src/knot-holder-entity.cpp1
-rw-r--r--src/libnr/Makefile_insert72
-rw-r--r--src/libnr/nr-blit.cpp300
-rw-r--r--src/libnr/nr-blit.h32
-rw-r--r--src/libnr/nr-compose-reference.cpp266
-rw-r--r--src/libnr/nr-compose-reference.h69
-rw-r--r--src/libnr/nr-compose-test.h457
-rw-r--r--src/libnr/nr-compose-transform.cpp367
-rw-r--r--src/libnr/nr-compose-transform.h43
-rw-r--r--src/libnr/nr-compose.cpp1197
-rw-r--r--src/libnr/nr-compose.h69
-rw-r--r--src/libnr/nr-convert2geom.h21
-rw-r--r--src/libnr/nr-convex-hull-ops.h29
-rw-r--r--src/libnr/nr-convex-hull.h59
-rw-r--r--src/libnr/nr-gradient.cpp554
-rw-r--r--src/libnr/nr-gradient.h81
-rw-r--r--src/libnr/nr-matrix-div.cpp22
-rw-r--r--src/libnr/nr-matrix-div.h21
-rw-r--r--src/libnr/nr-matrix-fns.cpp55
-rw-r--r--src/libnr/nr-matrix-fns.h53
-rw-r--r--src/libnr/nr-matrix-ops.h41
-rw-r--r--src/libnr/nr-matrix-rotate-ops.cpp18
-rw-r--r--src/libnr/nr-matrix-rotate-ops.h20
-rw-r--r--src/libnr/nr-matrix-scale-ops.h31
-rw-r--r--src/libnr/nr-matrix-test.h191
-rw-r--r--src/libnr/nr-matrix-translate-ops.h37
-rw-r--r--src/libnr/nr-matrix.cpp291
-rw-r--r--src/libnr/nr-matrix.h313
-rw-r--r--src/libnr/nr-maybe.h201
-rw-r--r--src/libnr/nr-path-code.h28
-rw-r--r--src/libnr/nr-pixblock-line.cpp92
-rw-r--r--src/libnr/nr-pixblock-line.h28
-rw-r--r--src/libnr/nr-pixblock-pattern.cpp127
-rw-r--r--src/libnr/nr-pixblock-pattern.h28
-rw-r--r--src/libnr/nr-pixblock-pixel.cpp230
-rw-r--r--src/libnr/nr-pixblock-pixel.h28
-rw-r--r--src/libnr/nr-pixblock.cpp465
-rw-r--r--src/libnr/nr-pixblock.h103
-rw-r--r--src/libnr/nr-pixops.h148
-rw-r--r--src/libnr/nr-point-matrix-ops.h49
-rw-r--r--src/libnr/nr-rect.cpp5
-rw-r--r--src/libnr/nr-rect.h11
-rw-r--r--src/libnr/nr-rotate-fns-test.h54
-rw-r--r--src/libnr/nr-rotate-fns.cpp66
-rw-r--r--src/libnr/nr-rotate-fns.h29
-rw-r--r--src/libnr/nr-rotate-matrix-ops.cpp19
-rw-r--r--src/libnr/nr-rotate-matrix-ops.h21
-rw-r--r--src/libnr/nr-rotate-ops.h43
-rw-r--r--src/libnr/nr-rotate-test.h110
-rw-r--r--src/libnr/nr-rotate.h66
-rw-r--r--src/libnr/nr-scale-matrix-ops.cpp25
-rw-r--r--src/libnr/nr-scale-matrix-ops.h13
-rw-r--r--src/libnr/nr-scale-ops.h40
-rw-r--r--src/libnr/nr-scale-test.h90
-rw-r--r--src/libnr/nr-scale-translate-ops.cpp19
-rw-r--r--src/libnr/nr-scale-translate-ops.h20
-rw-r--r--src/libnr/nr-scale.h55
-rw-r--r--src/libnr/nr-translate-matrix-ops.cpp26
-rw-r--r--src/libnr/nr-translate-matrix-ops.h22
-rw-r--r--src/libnr/nr-translate-ops.h43
-rw-r--r--src/libnr/nr-translate-rotate-ops.cpp20
-rw-r--r--src/libnr/nr-translate-rotate-ops.h21
-rw-r--r--src/libnr/nr-translate-scale-ops.cpp24
-rw-r--r--src/libnr/nr-translate-scale-ops.h20
-rw-r--r--src/libnr/nr-translate-test.h85
-rw-r--r--src/libnr/nr-translate.h34
-rw-r--r--src/libnr/nr-types.h1
-rw-r--r--src/libnr/nr-values.cpp4
-rw-r--r--src/libnr/nr-values.h1
-rw-r--r--src/libnr/testnr.cpp94
-rw-r--r--src/libnrtype/FontInstance.cpp251
-rw-r--r--src/libnrtype/Layout-TNG-Output.cpp5
-rw-r--r--src/libnrtype/Layout-TNG.h2
-rw-r--r--src/libnrtype/Makefile_insert4
-rw-r--r--src/libnrtype/RasterFont.cpp435
-rw-r--r--src/libnrtype/RasterFont.h66
-rw-r--r--src/libnrtype/font-glyph.h1
-rw-r--r--src/libnrtype/font-instance.h15
-rw-r--r--src/libnrtype/font-lister.cpp3
-rw-r--r--src/libnrtype/nrtype-forward.h3
-rw-r--r--src/libnrtype/raster-glyph.h49
-rw-r--r--src/libnrtype/raster-position.h46
-rw-r--r--src/livarot/Path.cpp1
-rw-r--r--src/livarot/PathConversion.cpp2
-rw-r--r--src/livarot/PathCutting.cpp5
-rw-r--r--src/livarot/PathSimplify.cpp3
-rw-r--r--src/livarot/ShapeMisc.cpp4
-rw-r--r--src/livarot/ShapeSweep.cpp4
-rw-r--r--src/livarot/path-description.cpp2
-rw-r--r--src/live_effects/lpe-curvestitch.cpp2
-rw-r--r--src/live_effects/lpe-dynastroke.cpp6
-rw-r--r--src/live_effects/lpe-interpolate.cpp2
-rw-r--r--src/live_effects/lpe-patternalongpath.cpp4
-rw-r--r--src/live_effects/lpe-rough-hatches.cpp12
-rw-r--r--src/live_effects/lpe-sketch.cpp12
-rw-r--r--src/live_effects/lpe-vonkoch.cpp4
-rw-r--r--src/live_effects/parameter/parameter.cpp4
-rw-r--r--src/live_effects/parameter/random.cpp4
-rw-r--r--src/main.cpp6
-rw-r--r--src/marker.cpp13
-rw-r--r--src/object-edit.cpp7
-rw-r--r--src/preferences-skeleton.h1
-rw-r--r--src/print.cpp37
-rw-r--r--src/print.h1
-rw-r--r--src/proj_pt.cpp2
-rw-r--r--src/proj_pt.h9
-rw-r--r--src/selection-chemistry.cpp36
-rw-r--r--src/selection.h2
-rw-r--r--src/seltrans.cpp8
-rw-r--r--src/shape-editor.h1
-rw-r--r--src/snap.cpp19
-rw-r--r--src/snapped-curve.cpp12
-rw-r--r--src/snapped-line.cpp16
-rw-r--r--src/snapped-point.cpp26
-rw-r--r--src/snapped-point.h3
-rw-r--r--src/sp-clippath.cpp9
-rw-r--r--src/sp-conn-end.cpp1
-rw-r--r--src/sp-ellipse.cpp2
-rw-r--r--src/sp-filter-fns.h53
-rw-r--r--src/sp-filter-primitive.h10
-rw-r--r--src/sp-filter-reference.cpp1
-rw-r--r--src/sp-filter-reference.h5
-rw-r--r--src/sp-filter.cpp1
-rw-r--r--src/sp-filter.h67
-rw-r--r--src/sp-flowdiv.cpp1
-rw-r--r--src/sp-gaussian-blur.h45
-rw-r--r--src/sp-gradient-fns.h3
-rw-r--r--src/sp-gradient.cpp633
-rw-r--r--src/sp-gradient.h7
-rw-r--r--src/sp-image.cpp225
-rw-r--r--src/sp-image.h8
-rw-r--r--src/sp-item-group.cpp4
-rw-r--r--src/sp-item-transform.cpp6
-rw-r--r--src/sp-item.cpp15
-rw-r--r--src/sp-line.cpp5
-rw-r--r--src/sp-mask.cpp9
-rw-r--r--src/sp-object-repr.cpp2
-rw-r--r--src/sp-offset.cpp2
-rw-r--r--src/sp-paint-server.cpp117
-rw-r--r--src/sp-paint-server.h32
-rw-r--r--src/sp-path.cpp3
-rw-r--r--src/sp-pattern.cpp564
-rw-r--r--src/sp-pattern.h1
-rw-r--r--src/sp-rect.cpp4
-rw-r--r--src/sp-root.cpp5
-rw-r--r--src/sp-shape.cpp12
-rw-r--r--src/sp-star.cpp9
-rw-r--r--src/sp-symbol.cpp2
-rw-r--r--src/sp-symbol.h1
-rw-r--r--src/sp-text.cpp3
-rw-r--r--src/sp-tref.cpp1
-rw-r--r--src/sp-tspan.cpp8
-rw-r--r--src/sp-use.cpp2
-rw-r--r--src/splivarot.cpp1
-rw-r--r--src/spray-context.cpp4
-rw-r--r--src/star-context.cpp4
-rw-r--r--src/svg/svg-affine.cpp3
-rw-r--r--src/text-chemistry.cpp13
-rw-r--r--src/text-editing.cpp2
-rw-r--r--src/trace/trace.cpp27
-rw-r--r--src/transf_mat_3x4.h2
-rw-r--r--src/tweak-context.cpp5
-rw-r--r--src/ui/cache/svg_preview_cache.cpp43
-rw-r--r--src/ui/dialog/color-item.cpp93
-rw-r--r--src/ui/dialog/color-item.h7
-rw-r--r--src/ui/dialog/filedialogimpl-win32.cpp21
-rw-r--r--src/ui/dialog/filter-effects-dialog.cpp2
-rw-r--r--src/ui/dialog/icon-preview.cpp17
-rw-r--r--src/ui/dialog/swatches.cpp58
-rw-r--r--src/ui/dialog/transformation.cpp1
-rw-r--r--src/ui/widget/color-preview.cpp31
-rw-r--r--src/vanishing-point.h2
-rw-r--r--src/verbs.cpp5
-rw-r--r--src/verbs.h1
-rw-r--r--src/widgets/Makefile_insert2
-rw-r--r--src/widgets/font-selector.cpp362
-rw-r--r--src/widgets/font-selector.h21
-rw-r--r--src/widgets/gradient-image.cpp148
-rw-r--r--src/widgets/gradient-image.h5
-rw-r--r--src/widgets/gradient-vector.cpp9
-rw-r--r--src/widgets/icon.cpp52
-rw-r--r--src/widgets/sp-color-preview.cpp211
-rw-r--r--src/widgets/sp-color-preview.h55
-rw-r--r--src/widgets/stroke-style.cpp2
-rw-r--r--src/widgets/toolbox.cpp2
369 files changed, 6849 insertions, 19602 deletions
diff --git a/src/2geom/Makefile_insert b/src/2geom/Makefile_insert
index 174f56433..4f7c3b6ef 100644
--- a/src/2geom/Makefile_insert
+++ b/src/2geom/Makefile_insert
@@ -6,6 +6,7 @@
rm -f 2geom/lib2geom.a $(2geom_lib2geom_a_OBJECTS)
2geom_lib2geom_a_SOURCES = \
+ 2geom/affine.h \
2geom/affine.cpp \
2geom/angle.h \
2geom/basic-intersection.cpp \
@@ -50,7 +51,6 @@
2geom/linear.h \
2geom/line.cpp \
2geom/line.h \
- 2geom/matrix.h \
2geom/nearest-point.cpp \
2geom/nearest-point.h \
2geom/numeric/fitting-model.h \
diff --git a/src/Makefile.am b/src/Makefile.am
index 731e9bfd6..40ecc1ec7 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -185,8 +185,6 @@ EXTRA_DIST += \
widgets/makefile.in \
xml/makefile.in \
2geom/makefile.in \
- extension/internal/win32.cpp \
- extension/internal/win32.h \
extension/internal/emf-win32-inout.cpp \
extension/internal/emf-win32-inout.h \
extension/internal/emf-win32-print.cpp \
@@ -270,7 +268,7 @@ TESTS = $(check_PROGRAMS) ../share/extensions/test/run-all-extension-tests
XFAIL_TESTS = $(check_PROGRAMS) ../share/extensions/test/run-all-extension-tests
# including the the testsuites here ensures that they get distributed
-cxxtests_SOURCES = cxxtests.cpp libnr/nr-compose-reference.cpp $(CXXTEST_TESTSUITES)
+cxxtests_SOURCES = cxxtests.cpp $(CXXTEST_TESTSUITES)
cxxtests_LDADD = $(all_libs)
cxxtests.cpp: $(CXXTEST_TESTSUITES) $(CXXTEST_TEMPLATE)
diff --git a/src/Makefile_insert b/src/Makefile_insert
index aadf9d404..7d48dba93 100644
--- a/src/Makefile_insert
+++ b/src/Makefile_insert
@@ -153,7 +153,6 @@ ink_common_sources += \
sp-desc.cpp sp-desc.h \
sp-ellipse.cpp sp-ellipse.h \
sp-filter.cpp sp-filter.h number-opt-number.h \
- sp-filter-fns.h \
sp-filter-primitive.cpp sp-filter-primitive.h \
sp-filter-reference.cpp sp-filter-reference.h \
sp-filter-units.h \
@@ -162,8 +161,6 @@ ink_common_sources += \
sp-flowtext.h sp-flowtext.cpp \
sp-font.cpp sp-font.h \
sp-font-face.cpp sp-font-face.h \
- sp-gaussian-blur.cpp sp-gaussian-blur.h \
- sp-gaussian-blur-fns.h \
sp-glyph.cpp sp-glyph.h \
sp-glyph-kerning.cpp sp-glyph-kerning.h \
sp-gradient.cpp sp-gradient.h \
diff --git a/src/box3d.cpp b/src/box3d.cpp
index a1ac84f14..ac5814e4d 100644
--- a/src/box3d.cpp
+++ b/src/box3d.cpp
@@ -386,7 +386,7 @@ Geom::Point
box3d_get_corner_screen (SPBox3D const *box, guint id, bool item_coords) {
Proj::Pt3 proj_corner (box3d_get_proj_corner (box, id));
if (!box3d_get_perspective(box)) {
- return Geom::Point (NR_HUGE, NR_HUGE);
+ return Geom::Point (Geom::infinity(), Geom::infinity());
}
Geom::Affine const i2d (SP_ITEM(box)->i2d_affine ());
if (item_coords) {
@@ -410,7 +410,7 @@ Geom::Point
box3d_get_center_screen (SPBox3D *box) {
Proj::Pt3 proj_center (box3d_get_proj_center (box));
if (!box3d_get_perspective(box)) {
- return Geom::Point (NR_HUGE, NR_HUGE);
+ return Geom::Point (Geom::infinity(), Geom::infinity());
}
Geom::Affine const i2d (SP_ITEM(box)->i2d_affine ());
return box3d_get_perspective(box)->perspective_impl->tmat.image(proj_center).affine() * i2d.inverse();
@@ -484,7 +484,7 @@ box3d_snap (SPBox3D *box, int id, Proj::Pt3 const &pt_proj, Proj::Pt3 const &sta
// find the closest snapping point
int snap_index = -1;
- double snap_dist = NR_HUGE;
+ double snap_dist = Geom::infinity();
for (int i = 0; i < num_snap_lines; ++i) {
if (snap_dists[i] < snap_dist) {
snap_index = i;
diff --git a/src/color-profile-fns.h b/src/color-profile-fns.h
index 3d22417f6..defc58f2c 100644
--- a/src/color-profile-fns.h
+++ b/src/color-profile-fns.h
@@ -38,6 +38,7 @@ std::vector<Glib::ustring> colorprofile_get_display_names();
std::vector<Glib::ustring> colorprofile_get_softproof_names();
Glib::ustring get_path_for_profile(Glib::ustring const& name);
+void colorprofile_load_profiles(bool force_refresh = false);
#endif
diff --git a/src/color-profile.cpp b/src/color-profile.cpp
index 9ba49d488..4dc4d5bd8 100644
--- a/src/color-profile.cpp
+++ b/src/color-profile.cpp
@@ -86,6 +86,9 @@ extern guint update_in_progress;
g_message( __VA_ARGS__ );\
}
+#else
+#define DEBUG_MESSAGE_SCISLAC(key, ...)
+#define DEBUG_MESSAGE(key, ...)
#endif // DEBUG_LCMS
static SPObjectClass *cprof_parent_class;
@@ -312,9 +315,7 @@ void ColorProfile::set( SPObject *object, unsigned key, gchar const *value )
cprof->_profileSpace = cmsGetColorSpace( cprof->profHandle );
cprof->_profileClass = cmsGetDeviceClass( cprof->profHandle );
}
-#ifdef DEBUG_LCMS
DEBUG_MESSAGE( lcmsOne, "cmsOpenProfileFromFile( '%s'...) = %p", fullname, (void*)cprof->profHandle );
-#endif // DEBUG_LCMS
g_free(escaped);
escaped = 0;
g_free(fullname);
@@ -339,9 +340,7 @@ void ColorProfile::set( SPObject *object, unsigned key, gchar const *value )
cprof->name = 0;
}
cprof->name = g_strdup( value );
-#ifdef DEBUG_LCMS
DEBUG_MESSAGE( lcmsTwo, "<color-profile> name set to '%s'", cprof->name );
-#endif // DEBUG_LCMS
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
break;
@@ -506,9 +505,7 @@ cmsHPROFILE Inkscape::colorprofile_get_handle( SPDocument* document, guint* inte
*intent = thing ? COLORPROFILE(thing)->rendering_intent : (guint)RENDERING_INTENT_UNKNOWN;
}
-#ifdef DEBUG_LCMS
DEBUG_MESSAGE( lcmsThree, "<color-profile> queried for profile of '%s'. Returning %p with intent of %d", name, prof, (intent? *intent:0) );
-#endif // DEBUG_LCMS
return prof;
}
@@ -517,7 +514,7 @@ cmsHTRANSFORM ColorProfile::getTransfToSRGB8()
{
if ( !_transf && profHandle ) {
int intent = getLcmsIntent(rendering_intent);
- _transf = cmsCreateTransform( profHandle, _getInputFormat(_profileSpace), getSRGBProfile(), TYPE_RGBA_8, intent, 0 );
+ _transf = cmsCreateTransform( profHandle, _getInputFormat(_profileSpace), getSRGBProfile(), TYPE_BGRA_8, intent, 0 );
}
return _transf;
}
@@ -526,7 +523,7 @@ cmsHTRANSFORM ColorProfile::getTransfFromSRGB8()
{
if ( !_revTransf && profHandle ) {
int intent = getLcmsIntent(rendering_intent);
- _revTransf = cmsCreateTransform( getSRGBProfile(), TYPE_RGBA_8, profHandle, _getInputFormat(_profileSpace), intent, 0 );
+ _revTransf = cmsCreateTransform( getSRGBProfile(), TYPE_BGRA_8, profHandle, _getInputFormat(_profileSpace), intent, 0 );
}
return _revTransf;
}
@@ -534,7 +531,7 @@ cmsHTRANSFORM ColorProfile::getTransfFromSRGB8()
cmsHTRANSFORM ColorProfile::getTransfGamutCheck()
{
if ( !_gamutTransf ) {
- _gamutTransf = cmsCreateProofingTransform(getSRGBProfile(), TYPE_RGBA_8, getNULLProfile(), TYPE_GRAY_8, profHandle, INTENT_RELATIVE_COLORIMETRIC, INTENT_RELATIVE_COLORIMETRIC, (cmsFLAGS_GAMUTCHECK|cmsFLAGS_SOFTPROOFING));
+ _gamutTransf = cmsCreateProofingTransform(getSRGBProfile(), TYPE_BGRA_8, getNULLProfile(), TYPE_GRAY_8, profHandle, INTENT_RELATIVE_COLORIMETRIC, INTENT_RELATIVE_COLORIMETRIC, (cmsFLAGS_GAMUTCHECK|cmsFLAGS_SOFTPROOFING));
}
return _gamutTransf;
}
@@ -589,6 +586,7 @@ static std::vector<ProfileInfo> knownProfiles;
std::vector<Glib::ustring> Inkscape::colorprofile_get_display_names()
{
+ colorprofile_load_profiles();
std::vector<Glib::ustring> result;
for ( std::vector<ProfileInfo>::iterator it = knownProfiles.begin(); it != knownProfiles.end(); ++it ) {
@@ -602,6 +600,7 @@ std::vector<Glib::ustring> Inkscape::colorprofile_get_display_names()
std::vector<Glib::ustring> Inkscape::colorprofile_get_softproof_names()
{
+ colorprofile_load_profiles();
std::vector<Glib::ustring> result;
for ( std::vector<ProfileInfo>::iterator it = knownProfiles.begin(); it != knownProfiles.end(); ++it ) {
@@ -615,6 +614,7 @@ std::vector<Glib::ustring> Inkscape::colorprofile_get_softproof_names()
Glib::ustring Inkscape::get_path_for_profile(Glib::ustring const& name)
{
+ colorprofile_load_profiles();
Glib::ustring result;
for ( std::vector<ProfileInfo>::iterator it = knownProfiles.begin(); it != knownProfiles.end(); ++it ) {
@@ -775,7 +775,28 @@ std::list<Glib::ustring> ColorProfile::getProfileFiles()
}
#if ENABLE_LCMS
-static void findThings() {
+
+int errorHandlerCB(int ErrorCode, const char *ErrorText)
+{
+ g_message("lcms: Error %d; %s", ErrorCode, ErrorText);
+
+ return 1;
+}
+
+/* This function loads or refreshes data in knownProfiles.
+ * Call it at the start of every call that requires this data. */
+void Inkscape::colorprofile_load_profiles(bool force_refresh)
+{
+ static bool error_handler_set = false;
+ if (!error_handler_set) {
+ cmsSetErrorHandler(errorHandlerCB);
+ error_handler_set = true;
+ }
+
+ static bool profiles_searched = false;
+ if (profiles_searched && !force_refresh) return;
+
+ knownProfiles.clear();
std::list<Glib::ustring> files = ColorProfile::getProfileFiles();
for ( std::list<Glib::ustring>::const_iterator it = files.begin(); it != files.end(); ++it ) {
@@ -797,13 +818,7 @@ static void findThings() {
}
}
}
-}
-
-int errorHandlerCB(int ErrorCode, const char *ErrorText)
-{
- g_message("lcms: Error %d; %s", ErrorCode, ErrorText);
-
- return 1;
+ profiles_searched = true;
}
static bool gamutWarn = false;
@@ -821,13 +836,7 @@ cmsHPROFILE Inkscape::colorprofile_get_system_profile_handle()
static cmsHPROFILE theOne = 0;
static Glib::ustring lastURI;
- static bool init = false;
- if ( !init ) {
- cmsSetErrorHandler(errorHandlerCB);
-
- findThings();
- init = true;
- }
+ colorprofile_load_profiles();
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
Glib::ustring uri = prefs->getString("/options/displayprofile/uri");
@@ -880,13 +889,7 @@ cmsHPROFILE Inkscape::colorprofile_get_proof_profile_handle()
static cmsHPROFILE theOne = 0;
static Glib::ustring lastURI;
- static bool init = false;
- if ( !init ) {
- cmsSetErrorHandler(errorHandlerCB);
-
- findThings();
- init = true;
- }
+ colorprofile_load_profiles();
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
bool which = prefs->getBool( "/options/softproof/enable");
@@ -1003,9 +1006,9 @@ cmsHTRANSFORM Inkscape::colorprofile_get_display_transform()
dwFlags |= cmsFLAGS_PRESERVEBLACK;
}
#endif // defined(cmsFLAGS_PRESERVEBLACK)
- transf = cmsCreateProofingTransform( ColorProfile::getSRGBProfile(), TYPE_RGBA_8, hprof, TYPE_RGBA_8, proofProf, intent, proofIntent, dwFlags );
+ transf = cmsCreateProofingTransform( ColorProfile::getSRGBProfile(), TYPE_BGRA_8, hprof, TYPE_BGRA_8, proofProf, intent, proofIntent, dwFlags );
} else if ( hprof ) {
- transf = cmsCreateTransform( ColorProfile::getSRGBProfile(), TYPE_RGBA_8, hprof, TYPE_RGBA_8, intent, 0 );
+ transf = cmsCreateTransform( ColorProfile::getSRGBProfile(), TYPE_BGRA_8, hprof, TYPE_BGRA_8, intent, 0 );
}
}
@@ -1163,9 +1166,9 @@ cmsHTRANSFORM Inkscape::colorprofile_get_display_per( Glib::ustring const& id )
dwFlags |= cmsFLAGS_PRESERVEBLACK;
}
#endif // defined(cmsFLAGS_PRESERVEBLACK)
- item.transf = cmsCreateProofingTransform( ColorProfile::getSRGBProfile(), TYPE_RGBA_8, item.hprof, TYPE_RGBA_8, proofProf, intent, proofIntent, dwFlags );
+ item.transf = cmsCreateProofingTransform( ColorProfile::getSRGBProfile(), TYPE_BGRA_8, item.hprof, TYPE_BGRA_8, proofProf, intent, proofIntent, dwFlags );
} else if ( item.hprof ) {
- item.transf = cmsCreateTransform( ColorProfile::getSRGBProfile(), TYPE_RGBA_8, item.hprof, TYPE_RGBA_8, intent, 0 );
+ item.transf = cmsCreateTransform( ColorProfile::getSRGBProfile(), TYPE_BGRA_8, item.hprof, TYPE_BGRA_8, intent, 0 );
}
}
diff --git a/src/color-rgba.h b/src/color-rgba.h
index fc52b193d..8c21d5e52 100644
--- a/src/color-rgba.h
+++ b/src/color-rgba.h
@@ -14,7 +14,6 @@
#include <glib.h> // g_assert()
#include <glib/gmessages.h>
-#include "libnr/nr-pixops.h"
#include "decimal-round.h"
/**
@@ -56,12 +55,12 @@ public:
TODO : maybe get rid of the NR_RGBA32_x C-style functions and replace
the calls with the bitshifting they do
*/
- ColorRGBA(unsigned int intcolor)
+ ColorRGBA(guint32 intcolor)
{
- _c[0] = NR_RGBA32_R(intcolor)/255.0;
- _c[1] = NR_RGBA32_G(intcolor)/255.0;
- _c[2] = NR_RGBA32_B(intcolor)/255.0;
- _c[3] = NR_RGBA32_A(intcolor)/255.0;
+ _c[0] = ((intcolor & 0xff000000) >> 24) / 255.0;
+ _c[1] = ((intcolor & 0x00ff0000) >> 16) / 255.0;
+ _c[2] = ((intcolor & 0x0000ff00) >> 8) / 255.0;
+ _c[3] = ((intcolor & 0x000000ff) >> 0) / 255.0;
}
diff --git a/src/desktop-style.cpp b/src/desktop-style.cpp
index 2c20964aa..88ad9ca57 100644
--- a/src/desktop-style.cpp
+++ b/src/desktop-style.cpp
@@ -28,7 +28,7 @@
#include "filters/blend.h"
#include "sp-filter.h"
#include "sp-filter-reference.h"
-#include "sp-gaussian-blur.h"
+#include "filters/gaussian-blur.h"
#include "sp-flowtext.h"
#include "sp-flowregion.h"
#include "sp-flowdiv.h"
@@ -410,7 +410,7 @@ gdouble
stroke_average_width (GSList const *objects)
{
if (g_slist_length ((GSList *) objects) == 0)
- return NR_HUGE;
+ return Geom::infinity();
gdouble avgwidth = 0.0;
bool notstroked = true;
@@ -435,7 +435,7 @@ stroke_average_width (GSList const *objects)
}
if (notstroked)
- return NR_HUGE;
+ return Geom::infinity();
return avgwidth / (g_slist_length ((GSList *) objects) - n_notstroked);
}
diff --git a/src/desktop.cpp b/src/desktop.cpp
index cfd3dddd0..f12f83ca6 100644
--- a/src/desktop.cpp
+++ b/src/desktop.cpp
@@ -824,7 +824,7 @@ SPDesktop::set_display_area (double x0, double y0, double x1, double y1, double
newscale = CLAMP(newscale, SP_DESKTOP_ZOOM_MIN, SP_DESKTOP_ZOOM_MAX); // unit: 'screen pixels' per 'document pixels'
int clear = FALSE;
- if (!NR_DF_TEST_CLOSE (newscale, scale, 1e-4 * scale)) {
+ if (!Geom::are_near(newscale, scale, Geom::EPSILON * scale)) {
// zoom changed - set new zoom factors
_d2w = Geom::Scale(newscale, -newscale);
_w2d = Geom::Scale(1/newscale, 1/-newscale);
diff --git a/src/dialogs/clonetiler.cpp b/src/dialogs/clonetiler.cpp
index 0cfa1d3c9..60ec4f9f7 100644
--- a/src/dialogs/clonetiler.cpp
+++ b/src/dialogs/clonetiler.cpp
@@ -18,32 +18,33 @@
#include <gtk/gtk.h>
#include <glibmm/i18n.h>
-#include "../desktop.h"
-#include "../desktop-handles.h"
+#include "desktop.h"
+#include "desktop-handles.h"
#include "dialog-events.h"
+#include "display/cairo-utils.h"
#include "display/nr-arena.h"
#include "display/nr-arena-item.h"
-#include "../document.h"
-#include "../filter-chemistry.h"
+#include "document.h"
+#include "filter-chemistry.h"
#include "helper/unit-menu.h"
#include "helper/units.h"
#include "helper/window.h"
-#include "../inkscape.h"
-#include "../interface.h"
-#include "../macros.h"
-#include "../message-stack.h"
+#include "inkscape.h"
+#include "interface.h"
+#include "macros.h"
+#include "message-stack.h"
#include "preferences.h"
-#include "../selection.h"
-#include "../sp-filter.h"
-#include "../sp-namedview.h"
-#include "../sp-use.h"
-#include "../style.h"
+#include "selection.h"
+#include "sp-filter.h"
+#include "sp-namedview.h"
+#include "sp-use.h"
+#include "style.h"
#include "svg/svg-color.h"
#include "svg/svg.h"
#include "ui/icon-names.h"
#include "ui/widget/color-picker.h"
#include "unclump.h"
-#include "../verbs.h"
+#include "verbs.h"
#include "widgets/icon.h"
#include "xml/repr.h"
#include "sp-root.h"
@@ -879,60 +880,25 @@ static guint32 clonetiler_trace_pick(Geom::Rect box)
/* Item integer bbox in points */
NRRectL ibox;
- ibox.x0 = (int) floor(trace_zoom * box[Geom::X].min() + 0.5);
- ibox.y0 = (int) floor(trace_zoom * box[Geom::Y].min() + 0.5);
- ibox.x1 = (int) floor(trace_zoom * box[Geom::X].max() + 0.5);
- ibox.y1 = (int) floor(trace_zoom * box[Geom::Y].max() + 0.5);
+ ibox.x0 = floor(trace_zoom * box[Geom::X].min());
+ ibox.y0 = floor(trace_zoom * box[Geom::Y].min());
+ ibox.x1 = ceil(trace_zoom * box[Geom::X].max());
+ ibox.y1 = ceil(trace_zoom * box[Geom::Y].max());
/* Find visible area */
int width = ibox.x1 - ibox.x0;
int height = ibox.y1 - ibox.y0;
+ double R = 0, G = 0, B = 0, A = 0;
- /* Set up pixblock */
- guchar *px = g_new(guchar, 4 * width * height);
-
- if (px == NULL) {
- return 0; // buffer is too big or too small, cannot pick, so return 0
- }
-
- memset(px, 0x00, 4 * width * height);
-
+ cairo_surface_t *s = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
+ cairo_t *ct = cairo_create(s);
+ cairo_translate(ct, -ibox.x0, -ibox.y0);
/* Render */
- NRPixBlock pb;
- nr_pixblock_setup_extern( &pb, NR_PIXBLOCK_MODE_R8G8B8A8N,
- ibox.x0, ibox.y0, ibox.x1, ibox.y1,
- px, 4 * width, FALSE, FALSE );
- nr_arena_item_invoke_render(NULL, trace_root, &ibox, &pb,
+ nr_arena_item_invoke_render(ct, trace_root, &ibox, NULL,
NR_ARENA_ITEM_RENDER_NO_CACHE );
-
- double R = 0, G = 0, B = 0, A = 0;
- double count = 0;
- double weight = 0;
-
- for (int y = ibox.y0; y < ibox.y1; y++) {
- const unsigned char *s = NR_PIXBLOCK_PX (&pb) + (y - ibox.y0) * pb.rs;
- for (int x = ibox.x0; x < ibox.x1; x++) {
- count += 1;
- weight += s[3] / 255.0;
- R += s[0] / 255.0;
- G += s[1] / 255.0;
- B += s[2] / 255.0;
- A += s[3] / 255.0;
- s += 4;
- }
- }
-
- nr_pixblock_release(&pb);
-
- R = R / weight;
- G = G / weight;
- B = B / weight;
- A = A / count;
-
- R = CLAMP (R, 0.0, 1.0);
- G = CLAMP (G, 0.0, 1.0);
- B = CLAMP (B, 0.0, 1.0);
- A = CLAMP (A, 0.0, 1.0);
+ cairo_destroy(ct);
+ ink_cairo_surface_average_color(s, R, G, B, A);
+ cairo_surface_destroy(s);
return SP_RGBA32_F_COMPOSE (R, G, B, A);
}
diff --git a/src/dialogs/text-edit.cpp b/src/dialogs/text-edit.cpp
index 2e49cae8f..81bd0f5d2 100644
--- a/src/dialogs/text-edit.cpp
+++ b/src/dialogs/text-edit.cpp
@@ -369,8 +369,11 @@ sp_text_edit_dialog (void)
}
/* Font preview */
- GtkWidget *preview = sp_font_preview_new ();
- gtk_box_pack_start (GTK_BOX (vb), preview, TRUE, TRUE, 4);
+ GtkLabel *preview = (GtkLabel*) gtk_label_new(NULL);
+ gtk_label_set_ellipsize(preview, PANGO_ELLIPSIZE_END);
+ gtk_label_set_justify(preview, GTK_JUSTIFY_CENTER);
+ gtk_label_set_line_wrap(preview, FALSE);
+ gtk_box_pack_start (GTK_BOX (vb), (GtkWidget*) preview, TRUE, TRUE, 4);
g_object_set_data (G_OBJECT (dlg), "preview", preview);
}
@@ -697,7 +700,7 @@ sp_text_edit_dialog_read_selection ( GtkWidget *dlg,
g_object_set_data (G_OBJECT (dlg), "blocked", GINT_TO_POINTER (TRUE));
- GtkWidget *notebook = (GtkWidget*)g_object_get_data (G_OBJECT (dlg), "notebook");
+ //GtkWidget *notebook = (GtkWidget*)g_object_get_data (G_OBJECT (dlg), "notebook");
GtkWidget *textw = (GtkWidget*)g_object_get_data (G_OBJECT (dlg), "textw");
GtkWidget *fontsel = (GtkWidget*)g_object_get_data (G_OBJECT (dlg), "fontsel");
GtkWidget *preview = (GtkWidget*)g_object_get_data (G_OBJECT (dlg), "preview");
@@ -708,6 +711,12 @@ sp_text_edit_dialog_read_selection ( GtkWidget *dlg,
SPItem *text = sp_ted_get_selected_text_item ();
+ /* TRANSLATORS: Test string used in text and font dialog (when no
+ * text has been entered) to get a preview of the font. Choose
+ * some representative characters that users of your locale will be
+ * interested in. */
+ gchar *phrase = g_strdup(_("AaBbCcIiPpQq12369$\342\202\254\302\242?.;/()"));
+
Inkscape::XML::Node *repr;
if (text)
{
@@ -732,12 +741,10 @@ sp_text_edit_dialog_read_selection ( GtkWidget *dlg,
gtk_text_buffer_set_text (tb, str, strlen (str));
gtk_text_buffer_set_modified (tb, FALSE);
}
- sp_font_preview_set_phrase (SP_FONT_PREVIEW (preview), str);
- g_free (str);
+ phrase = str;
} else {
gtk_text_buffer_set_text (tb, "", 0);
- sp_font_preview_set_phrase (SP_FONT_PREVIEW (preview), NULL);
}
} // end of if (docontent)
repr = text->getRepr();
@@ -774,7 +781,13 @@ sp_text_edit_dialog_read_selection ( GtkWidget *dlg,
if (font) {
// the font is oversized, so we need to pass the true size separately
sp_font_selector_set_font (SP_FONT_SELECTOR (fontsel), font, query->font_size.computed);
- sp_font_preview_set_font (SP_FONT_PREVIEW (preview), font, SP_FONT_SELECTOR(fontsel));
+ char *desc = pango_font_description_to_string(font->descr);
+ double size = sp_font_selector_get_size(SP_FONT_SELECTOR(fontsel));
+ gchar *markup = g_strdup_printf("<span font=\"%s\" size=\"%d\">%s</span>",
+ desc, (int) size * PANGO_SCALE, phrase);
+ gtk_label_set_markup(GTK_LABEL(preview), markup);
+ g_free(desc);
+ g_free(markup);
font->Unref();
font=NULL;
}
@@ -812,7 +825,7 @@ sp_text_edit_dialog_read_selection ( GtkWidget *dlg,
sp_style_unref(query);
}
-
+ g_free(phrase);
g_object_set_data (G_OBJECT (dlg), "blocked", NULL);
}
@@ -820,7 +833,7 @@ sp_text_edit_dialog_read_selection ( GtkWidget *dlg,
static void
sp_text_edit_dialog_text_changed (GtkTextBuffer *tb, GtkWidget *dlg)
{
- GtkWidget *textw, *preview, *apply, *def;
+ GtkWidget *textw, *preview, *apply, *def, *fontsel;
GtkTextIter start, end;
gchar *str;
@@ -833,14 +846,23 @@ sp_text_edit_dialog_text_changed (GtkTextBuffer *tb, GtkWidget *dlg)
preview = (GtkWidget*)g_object_get_data (G_OBJECT (dlg), "preview");
apply = (GtkWidget*)g_object_get_data (G_OBJECT (dlg), "apply");
def = (GtkWidget*)g_object_get_data (G_OBJECT (dlg), "default");
+ fontsel = (GtkWidget*)g_object_get_data (G_OBJECT (dlg), "fontsel");
gtk_text_buffer_get_bounds (tb, &start, &end);
str = gtk_text_buffer_get_text (tb, &start, &end, TRUE);
-
- if (str && *str) {
- sp_font_preview_set_phrase (SP_FONT_PREVIEW (preview), str);
+ font_instance *font = sp_font_selector_get_font(SP_FONT_SELECTOR(fontsel));
+
+ if (font) {
+ gchar *phrase = str && *str ? str : _("AaBbCcIiPpQq12369$\342\202\254\302\242?.;/()");
+ char *desc = pango_font_description_to_string(font->descr);
+ double size = sp_font_selector_get_size(SP_FONT_SELECTOR(fontsel));
+ gchar *markup = g_strdup_printf("<span font=\"%s\" size=\"%d\">%s</span>",
+ desc, (int) size * PANGO_SCALE, phrase);
+ gtk_label_set_markup(GTK_LABEL(preview), markup);
+ g_free(desc);
+ g_free(markup);
} else {
- sp_font_preview_set_phrase (SP_FONT_PREVIEW (preview), NULL);
+ gtk_label_set_markup(GTK_LABEL(preview), NULL);
}
g_free (str);
@@ -865,7 +887,9 @@ sp_text_edit_dialog_font_changed ( SPFontSelector *fsel,
font_instance *font,
GtkWidget *dlg )
{
- GtkWidget *preview, *apply, *def;
+ GtkWidget *preview, *apply, *def, *fontsel;
+ GtkTextIter start, end;
+ gchar *str;
if (g_object_get_data (G_OBJECT (dlg), "blocked"))
return;
@@ -875,11 +899,27 @@ sp_text_edit_dialog_font_changed ( SPFontSelector *fsel,
preview = (GtkWidget*)g_object_get_data (G_OBJECT (dlg), "preview");
apply = (GtkWidget*)g_object_get_data (G_OBJECT (dlg), "apply");
def = (GtkWidget*)g_object_get_data (G_OBJECT (dlg), "default");
+ fontsel = (GtkWidget*)g_object_get_data (G_OBJECT (dlg), "fontsel");
+
+ GtkTextBuffer *tb = (GtkTextBuffer*)g_object_get_data (G_OBJECT (dlg), "text");
+ gtk_text_buffer_get_bounds (tb, &start, &end);
+ str = gtk_text_buffer_get_text (tb, &start, &end, TRUE);
- sp_font_preview_set_font (SP_FONT_PREVIEW (preview), font, SP_FONT_SELECTOR(fsel));
+ if (font) {
+ gchar *phrase = str && *str ? str : _("AaBbCcIiPpQq12369$\342\202\254\302\242?.;/()");
+ char *desc = pango_font_description_to_string(font->descr);
+ double size = sp_font_selector_get_size(SP_FONT_SELECTOR(fontsel));
+ gchar *markup = g_strdup_printf("<span font=\"%s\" size=\"%d\">%s</span>",
+ desc, (int) size * PANGO_SCALE, phrase);
+ gtk_label_set_markup(GTK_LABEL(preview), markup);
+ g_free(desc);
+ g_free(markup);
+ } else {
+ gtk_label_set_markup(GTK_LABEL(preview), NULL);
+ }
+ g_free(str);
- if (text)
- {
+ if (text) {
gtk_widget_set_sensitive (apply, TRUE);
}
gtk_widget_set_sensitive (def, TRUE);
diff --git a/src/display/Makefile_insert b/src/display/Makefile_insert
index 370e28d6d..fc7c8e9ab 100644
--- a/src/display/Makefile_insert
+++ b/src/display/Makefile_insert
@@ -4,35 +4,23 @@ display/canvas-arena.$(OBJEXT): helper/sp-marshal.h
display/sp-canvas.$(OBJEXT): helper/sp-marshal.h
ink_common_sources += \
- display/nr-3dutils.h \
- display/nr-3dutils.cpp \
- display/nr-arena-forward.h \
- display/nr-arena.cpp \
- display/nr-arena.h \
- display/nr-arena-item.cpp \
- display/nr-arena-item.h \
- display/nr-arena-group.cpp \
- display/nr-arena-group.h \
- display/nr-arena-image.cpp \
- display/nr-arena-image.h \
- display/nr-arena-shape.cpp \
- display/nr-arena-shape.h \
- display/nr-arena-glyphs.cpp \
- display/nr-arena-glyphs.h \
+ display/cairo-templates.h \
+ display/cairo-utils.cpp \
+ display/cairo-utils.h \
display/canvas-arena.cpp \
display/canvas-arena.h \
+ display/canvas-axonomgrid.cpp \
+ display/canvas-axonomgrid.h \
display/canvas-bpath.cpp \
display/canvas-bpath.h \
display/canvas-grid.cpp \
display/canvas-grid.h \
- display/canvas-axonomgrid.cpp \
- display/canvas-axonomgrid.h \
display/canvas-temporary-item.cpp \
display/canvas-temporary-item.h \
display/canvas-temporary-item-list.cpp \
display/canvas-temporary-item-list.h \
- display/canvas-text.h \
display/canvas-text.cpp \
+ display/canvas-text.h \
display/curve.cpp \
display/curve.h \
display/gnome-canvas-acetate.cpp \
@@ -41,43 +29,32 @@ ink_common_sources += \
display/grayscale.h \
display/guideline.cpp \
display/guideline.h \
- display/nr-plain-stuff-gdk.cpp \
- display/nr-plain-stuff-gdk.h \
- display/nr-plain-stuff.cpp \
- display/nr-plain-stuff.h \
- display/nr-svgfonts.cpp \
- display/nr-svgfonts.h \
- display/rendermode.h \
- display/snap-indicator.cpp \
- display/snap-indicator.h \
- display/sodipodi-ctrl.cpp \
- display/sodipodi-ctrl.h \
- display/sodipodi-ctrlrect.cpp \
- display/sodipodi-ctrlrect.h \
- display/sp-canvas-group.h \
- display/sp-canvas-item.h \
- display/sp-canvas-util.cpp \
- display/sp-canvas-util.h \
- display/sp-canvas.cpp \
- display/sp-canvas.h \
- display/sp-ctrlline.cpp \
- display/sp-ctrlline.h \
- display/sp-ctrlpoint.cpp \
- display/sp-ctrlpoint.h \
- display/sp-ctrlquadr.cpp \
- display/sp-ctrlquadr.h \
- display/nr-filter.cpp \
- display/nr-filter.h \
+ display/nr-3dutils.cpp \
+ display/nr-3dutils.h \
+ display/nr-arena.cpp \
+ display/nr-arena-forward.h \
+ display/nr-arena-glyphs.cpp \
+ display/nr-arena-glyphs.h \
+ display/nr-arena-group.cpp \
+ display/nr-arena-group.h \
+ display/nr-arena.h \
+ display/nr-arena-image.cpp \
+ display/nr-arena-image.h \
+ display/nr-arena-item.cpp \
+ display/nr-arena-item.h \
+ display/nr-arena-shape.cpp \
+ display/nr-arena-shape.h \
display/nr-filter-blend.cpp \
display/nr-filter-blend.h \
display/nr-filter-colormatrix.cpp \
display/nr-filter-colormatrix.h \
display/nr-filter-component-transfer.cpp \
display/nr-filter-component-transfer.h \
- display/nr-filter-composite.h \
display/nr-filter-composite.cpp \
+ display/nr-filter-composite.h \
display/nr-filter-convolve-matrix.cpp \
display/nr-filter-convolve-matrix.h \
+ display/nr-filter.cpp \
display/nr-filter-diffuselighting.cpp \
display/nr-filter-diffuselighting.h \
display/nr-filter-displacement-map.cpp \
@@ -86,8 +63,7 @@ ink_common_sources += \
display/nr-filter-flood.h \
display/nr-filter-gaussian.cpp \
display/nr-filter-gaussian.h \
- display/nr-filter-getalpha.cpp \
- display/nr-filter-getalpha.h \
+ display/nr-filter.h \
display/nr-filter-image.cpp \
display/nr-filter-image.h \
display/nr-filter-merge.cpp \
@@ -106,21 +82,35 @@ ink_common_sources += \
display/nr-filter-tile.h \
display/nr-filter-turbulence.cpp \
display/nr-filter-turbulence.h \
- display/nr-filter-pixops.h \
display/nr-filter-types.h \
- display/nr-filter-units.h \
display/nr-filter-units.cpp \
- display/nr-filter-utils.h \
+ display/nr-filter-units.h \
display/nr-filter-utils.cpp \
- display/pixblock-scaler.cpp \
- display/pixblock-scaler.h \
- display/pixblock-transform.cpp \
- display/pixblock-transform.h \
- display/inkscape-cairo.cpp \
- display/inkscape-cairo.h \
- display/nr-light.h \
+ display/nr-filter-utils.h \
display/nr-light.cpp \
- display/nr-light-types.h
+ display/nr-light.h \
+ display/nr-light-types.h \
+ display/nr-style.cpp \
+ display/nr-style.h \
+ display/nr-svgfonts.cpp \
+ display/nr-svgfonts.h \
+ display/rendermode.h \
+ display/snap-indicator.cpp \
+ display/snap-indicator.h \
+ display/sodipodi-ctrl.cpp \
+ display/sodipodi-ctrl.h \
+ display/sodipodi-ctrlrect.cpp \
+ display/sodipodi-ctrlrect.h \
+ display/sp-canvas.cpp \
+ display/sp-canvas.h \
+ display/sp-canvas-util.cpp \
+ display/sp-canvas-util.h \
+ display/sp-ctrlline.cpp \
+ display/sp-ctrlline.h \
+ display/sp-ctrlpoint.cpp \
+ display/sp-ctrlpoint.h \
+ display/sp-ctrlquadr.cpp \
+ display/sp-ctrlquadr.h
# ######################
# ### CxxTest stuff ####
diff --git a/src/display/cairo-templates.h b/src/display/cairo-templates.h
new file mode 100644
index 000000000..a79f58548
--- /dev/null
+++ b/src/display/cairo-templates.h
@@ -0,0 +1,689 @@
+/**
+ * @file
+ * @brief Cairo software blending templates
+ *//*
+ * Authors:
+ * Krzysztof KosiƄski <tweenk.pl@gmail.com>
+ *
+ * Copyright (C) 2010 Authors
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifndef SEEN_INKSCAPE_DISPLAY_CAIRO_TEMPLATES_H
+#define SEEN_INKSCAPE_DISPLAY_CAIRO_TEMPLATES_H
+
+#ifdef HAVE_OPENMP
+#include <omp.h>
+#include "preferences.h"
+// single-threaded operation if the number of pixels is below this threshold
+static const int OPENMP_THRESHOLD = 2048;
+#endif
+
+#include <algorithm>
+#include <cairo.h>
+#include <glib.h>
+#include <math.h>
+#include "display/nr-3dutils.h"
+#include "display/cairo-utils.h"
+
+/**
+ * @brief Blend two surfaces using the supplied functor.
+ * This template blends two Cairo image surfaces using a blending functor that takes
+ * two 32-bit ARGB pixel values and returns a modified 32-bit pixel value.
+ * Differences in input surface formats are handled transparently. In future, this template
+ * will also handle software fallback for GL surfaces. */
+template <typename Blend>
+void ink_cairo_surface_blend(cairo_surface_t *in1, cairo_surface_t *in2, cairo_surface_t *out, Blend blend)
+{
+ cairo_surface_flush(in1);
+ cairo_surface_flush(in2);
+
+ // ASSUMPTIONS
+ // 1. Cairo ARGB32 surface strides are always divisible by 4
+ // 2. We can only receive CAIRO_FORMAT_ARGB32 or CAIRO_FORMAT_A8 surfaces
+ // 3. Both surfaces are of the same size
+ // 4. Output surface is ARGB32 if at least one input is ARGB32
+
+ int w = cairo_image_surface_get_width(in2);
+ int h = cairo_image_surface_get_height(in2);
+ int stride1 = cairo_image_surface_get_stride(in1);
+ int stride2 = cairo_image_surface_get_stride(in2);
+ int strideout = cairo_image_surface_get_stride(out);
+ int bpp1 = cairo_image_surface_get_format(in1) == CAIRO_FORMAT_A8 ? 1 : 4;
+ int bpp2 = cairo_image_surface_get_format(in2) == CAIRO_FORMAT_A8 ? 1 : 4;
+ int bppout = std::max(bpp1, bpp2);
+
+ // Check whether we can loop over pixels without taking stride into account.
+ bool fast_path = true;
+ fast_path &= (stride1 == w * bpp1);
+ fast_path &= (stride2 == w * bpp2);
+ fast_path &= (strideout == w * bppout);
+
+ int limit = w * h;
+
+ guint32 *const in1_data = (guint32*) cairo_image_surface_get_data(in1);
+ guint32 *const in2_data = (guint32*) cairo_image_surface_get_data(in2);
+ guint32 *const out_data = (guint32*) cairo_image_surface_get_data(out);
+
+ // NOTE
+ // OpenMP probably doesn't help much here.
+ // It would be better to render more than 1 tile at a time.
+ #if HAVE_OPENMP
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ int num_threads = prefs->getIntLimited("/options/threading/numthreads", omp_get_num_procs(), 1, 256);
+ #endif
+
+ // The number of code paths here is evil.
+ if (bpp1 == 4) {
+ if (bpp2 == 4) {
+ if (fast_path) {
+ #if HAVE_OPENMP
+ #pragma omp parallel for if(limit > OPENMP_THRESHOLD) num_threads(num_threads)
+ #endif
+ for (int i = 0; i < limit; ++i) {
+ *(out_data + i) = blend(*(in1_data + i), *(in2_data + i));
+ }
+ } else {
+ #if HAVE_OPENMP
+ #pragma omp parallel for if(limit > OPENMP_THRESHOLD) num_threads(num_threads)
+ #endif
+ for (int i = 0; i < h; ++i) {
+ guint32 *in1_p = in1_data + i * stride1/4;
+ guint32 *in2_p = in2_data + i * stride2/4;
+ guint32 *out_p = out_data + i * strideout/4;
+ for (int j = 0; j < w; ++j) {
+ *out_p = blend(*in1_p, *in2_p);
+ ++in1_p; ++in2_p; ++out_p;
+ }
+ }
+ }
+ } else {
+ // bpp2 == 1
+ #if HAVE_OPENMP
+ #pragma omp parallel for if(limit > OPENMP_THRESHOLD) num_threads(num_threads)
+ #endif
+ for (int i = 0; i < h; ++i) {
+ guint32 *in1_p = in1_data + i * stride1/4;
+ guint8 *in2_p = reinterpret_cast<guint8*>(in2_data) + i * stride2;
+ guint32 *out_p = out_data + i * strideout/4;
+ for (int j = 0; j < w; ++j) {
+ guint32 in2_px = *in2_p;
+ in2_px <<= 24;
+ *out_p = blend(*in1_p, in2_px);
+ ++in1_p; ++in2_p; ++out_p;
+ }
+ }
+ }
+ } else {
+ if (bpp2 == 4) {
+ // bpp1 == 1
+ #if HAVE_OPENMP
+ #pragma omp parallel for if(limit > OPENMP_THRESHOLD) num_threads(num_threads)
+ #endif
+ for (int i = 0; i < h; ++i) {
+ guint8 *in1_p = reinterpret_cast<guint8*>(in1_data) + i * stride1;
+ guint32 *in2_p = in2_data + i * stride2/4;
+ guint32 *out_p = out_data + i * strideout/4;
+ for (int j = 0; j < w; ++j) {
+ guint32 in1_px = *in1_p;
+ in1_px <<= 24;
+ *out_p = blend(in1_px, *in2_p);
+ ++in1_p; ++in2_p; ++out_p;
+ }
+ }
+ } else {
+ // bpp1 == 1 && bpp2 == 1
+ if (fast_path) {
+ #if HAVE_OPENMP
+ #pragma omp parallel for if(limit > OPENMP_THRESHOLD) num_threads(num_threads)
+ #endif
+ for (int i = 0; i < limit; ++i) {
+ guint8 *in1_p = reinterpret_cast<guint8*>(in1_data) + i;
+ guint8 *in2_p = reinterpret_cast<guint8*>(in2_data) + i;
+ guint8 *out_p = reinterpret_cast<guint8*>(out_data) + i;
+ guint32 in1_px = *in1_p; in1_px <<= 24;
+ guint32 in2_px = *in2_p; in2_px <<= 24;
+ guint32 out_px = blend(in1_px, in2_px);
+ *out_p = out_px >> 24;
+ }
+ } else {
+ #if HAVE_OPENMP
+ #pragma omp parallel for if(limit > OPENMP_THRESHOLD) num_threads(num_threads)
+ #endif
+ for (int i = 0; i < h; ++i) {
+ guint8 *in1_p = reinterpret_cast<guint8*>(in1_data) + i * stride1;
+ guint8 *in2_p = reinterpret_cast<guint8*>(in2_data) + i * stride2;
+ guint8 *out_p = reinterpret_cast<guint8*>(out_data) + i * strideout;
+ for (int j = 0; j < w; ++j) {
+ guint32 in1_px = *in1_p; in1_px <<= 24;
+ guint32 in2_px = *in2_p; in2_px <<= 24;
+ guint32 out_px = blend(in1_px, in2_px);
+ *out_p = out_px >> 24;
+ ++in1_p; ++in2_p; ++out_p;
+ }
+ }
+ }
+ }
+ }
+
+ cairo_surface_mark_dirty(out);
+}
+
+template <typename Filter>
+void ink_cairo_surface_filter(cairo_surface_t *in, cairo_surface_t *out, Filter filter)
+{
+ cairo_surface_flush(in);
+
+ // ASSUMPTIONS
+ // 1. Cairo ARGB32 surface strides are always divisible by 4
+ // 2. We can only receive CAIRO_FORMAT_ARGB32 or CAIRO_FORMAT_A8 surfaces
+ // 3. Surfaces have the same dimensions
+ // 4. Output surface is A8 if input is A8
+
+ int w = cairo_image_surface_get_width(in);
+ int h = cairo_image_surface_get_height(in);
+ int stridein = cairo_image_surface_get_stride(in);
+ int strideout = cairo_image_surface_get_stride(out);
+ int bppin = cairo_image_surface_get_format(in) == CAIRO_FORMAT_A8 ? 1 : 4;
+ int bppout = cairo_image_surface_get_format(out) == CAIRO_FORMAT_A8 ? 1 : 4;
+ int limit = w * h;
+
+ // Check whether we can loop over pixels without taking stride into account.
+ bool fast_path = true;
+ fast_path &= (stridein == w * bppin);
+ fast_path &= (strideout == w * bppout);
+
+ guint32 *const in_data = (guint32*) cairo_image_surface_get_data(in);
+ guint32 *const out_data = (guint32*) cairo_image_surface_get_data(out);
+
+ #if HAVE_OPENMP
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ int num_threads = prefs->getIntLimited("/options/threading/numthreads", omp_get_num_procs(), 1, 256);
+ #endif
+
+ // this is provided just in case, to avoid problems with strict aliasing rules
+ if (in == out) {
+ if (bppin == 4) {
+ #if HAVE_OPENMP
+ #pragma omp parallel for if(limit > OPENMP_THRESHOLD) num_threads(num_threads)
+ #endif
+ for (int i = 0; i < limit; ++i) {
+ *(in_data + i) = filter(*(in_data + i));
+ }
+ } else {
+ #if HAVE_OPENMP
+ #pragma omp parallel for if(limit > OPENMP_THRESHOLD) num_threads(num_threads)
+ #endif
+ for (int i = 0; i < limit; ++i) {
+ guint8 *in_p = reinterpret_cast<guint8*>(in_data) + i;
+ guint32 in_px = *in_p; in_px <<= 24;
+ guint32 out_px = filter(in_px);
+ *in_p = out_px >> 24;
+ }
+ }
+ cairo_surface_mark_dirty(out);
+ return;
+ }
+
+ if (bppin == 4) {
+ if (bppout == 4) {
+ // bppin == 4, bppout == 4
+ if (fast_path) {
+ #if HAVE_OPENMP
+ #pragma omp parallel for if(limit > OPENMP_THRESHOLD) num_threads(num_threads)
+ #endif
+ for (int i = 0; i < limit; ++i) {
+ *(out_data + i) = filter(*(in_data + i));
+ }
+ } else {
+ #if HAVE_OPENMP
+ #pragma omp parallel for if(limit > OPENMP_THRESHOLD) num_threads(num_threads)
+ #endif
+ for (int i = 0; i < h; ++i) {
+ guint32 *in_p = in_data + i * stridein/4;
+ guint32 *out_p = out_data + i * strideout/4;
+ for (int j = 0; j < w; ++j) {
+ *out_p = filter(*in_p);
+ ++in_p; ++out_p;
+ }
+ }
+ }
+ } else {
+ // bppin == 4, bppout == 1
+ // we use this path with COLORMATRIX_LUMINANCETOALPHA
+ #if HAVE_OPENMP
+ #pragma omp parallel for if(limit > OPENMP_THRESHOLD) num_threads(num_threads)
+ #endif
+ for (int i = 0; i < h; ++i) {
+ guint32 *in_p = in_data + i * stridein/4;
+ guint8 *out_p = reinterpret_cast<guint8*>(out_data) + i * strideout;
+ for (int j = 0; j < w; ++j) {
+ guint32 out_px = filter(*in_p);
+ *out_p = out_px >> 24;
+ ++in_p; ++out_p;
+ }
+ }
+ }
+ } else {
+ // bppin == 1, bppout == 1
+ // Note: there is no path for bppin == 1, bppout == 4 because it is useless
+ if (fast_path) {
+ #if HAVE_OPENMP
+ #pragma omp parallel for if(limit > OPENMP_THRESHOLD) num_threads(num_threads)
+ #endif
+ for (int i = 0; i < limit; ++i) {
+ guint8 *in_p = reinterpret_cast<guint8*>(in_data) + i;
+ guint8 *out_p = reinterpret_cast<guint8*>(out_data) + i;
+ guint32 in_px = *in_p; in_px <<= 24;
+ guint32 out_px = filter(in_px);
+ *out_p = out_px >> 24;
+ }
+ } else {
+ #if HAVE_OPENMP
+ #pragma omp parallel for if(limit > OPENMP_THRESHOLD) num_threads(num_threads)
+ #endif
+ for (int i = 0; i < h; ++i) {
+ guint8 *in_p = reinterpret_cast<guint8*>(in_data) + i * stridein;
+ guint8 *out_p = reinterpret_cast<guint8*>(out_data) + i * strideout;
+ for (int j = 0; j < w; ++j) {
+ guint32 in_px = *in_p; in_px <<= 24;
+ guint32 out_px = filter(in_px);
+ *out_p = out_px >> 24;
+ ++in_p; ++out_p;
+ }
+ }
+ }
+ }
+ cairo_surface_mark_dirty(out);
+}
+
+
+/**
+ * @brief Synthesize surface pixels based on their position.
+ * This template accepts a functor that gets called with the x and y coordinates of the pixels,
+ * given as integers.
+ * @param out Output surface
+ * @param out_area The region of the output surface that should be synthesized
+ * @param synth Synthesis functor */
+template <typename Synth>
+void ink_cairo_surface_synthesize(cairo_surface_t *out, cairo_rectangle_t const &out_area, Synth synth)
+{
+ // ASSUMPTIONS
+ // 1. Cairo ARGB32 surface strides are always divisible by 4
+ // 2. We can only receive CAIRO_FORMAT_ARGB32 or CAIRO_FORMAT_A8 surfaces
+
+ int w = out_area.width;
+ int h = out_area.height;
+ int strideout = cairo_image_surface_get_stride(out);
+ int bppout = cairo_image_surface_get_format(out) == CAIRO_FORMAT_A8 ? 1 : 4;
+ // NOTE: fast path is not used, because we would need 2 divisions to get pixel indices
+
+ unsigned char *out_data = cairo_image_surface_get_data(out);
+
+ #if HAVE_OPENMP
+ int limit = w * h;
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ int num_threads = prefs->getIntLimited("/options/threading/numthreads", omp_get_num_procs(), 1, 256);
+ #endif
+
+ if (bppout == 4) {
+ #if HAVE_OPENMP
+ #pragma omp parallel for if(limit > OPENMP_THRESHOLD) num_threads(num_threads)
+ #endif
+ for (int i = out_area.y; i < h; ++i) {
+ guint32 *out_p = reinterpret_cast<guint32*>(out_data + i * strideout);
+ for (int j = out_area.x; j < w; ++j) {
+ *out_p = synth(j, i);
+ ++out_p;
+ }
+ }
+ } else {
+ // bppout == 1
+ #if HAVE_OPENMP
+ #pragma omp parallel for if(limit > OPENMP_THRESHOLD) num_threads(num_threads)
+ #endif
+ for (int i = out_area.y; i < h; ++i) {
+ guint8 *out_p = out_data + i * strideout;
+ for (int j = out_area.x; j < w; ++j) {
+ guint32 out_px = synth(j, i);
+ *out_p = out_px >> 24;
+ ++out_p;
+ }
+ }
+ }
+ cairo_surface_mark_dirty(out);
+}
+
+template <typename Synth>
+void ink_cairo_surface_synthesize(cairo_surface_t *out, Synth synth)
+{
+ int w = cairo_image_surface_get_width(out);
+ int h = cairo_image_surface_get_height(out);
+
+ cairo_rectangle_t area;
+ area.x = 0;
+ area.y = 0;
+ area.width = w;
+ area.height = h;
+
+ ink_cairo_surface_synthesize(out, area, synth);
+}
+
+struct SurfaceSynth {
+ SurfaceSynth(cairo_surface_t *surface)
+ : _px(cairo_image_surface_get_data(surface))
+ , _w(cairo_image_surface_get_width(surface))
+ , _h(cairo_image_surface_get_height(surface))
+ , _stride(cairo_image_surface_get_stride(surface))
+ , _alpha(cairo_surface_get_content(surface) == CAIRO_CONTENT_ALPHA)
+ {
+ cairo_surface_flush(surface);
+ }
+
+ guint32 pixelAt(int x, int y) const {
+ if (_alpha) {
+ unsigned char *px = _px + y*_stride + x;
+ return *px << 24;
+ } else {
+ unsigned char *px = _px + y*_stride + x*4;
+ return *reinterpret_cast<guint32*>(px);
+ }
+ }
+ guint32 alphaAt(int x, int y) const {
+ if (_alpha) {
+ unsigned char *px = _px + y*_stride + x;
+ return *px;
+ } else {
+ unsigned char *px = _px + y*_stride + x*4;
+ guint32 p = *reinterpret_cast<guint32*>(px);
+ return (p & 0xff000000) >> 24;
+ }
+ }
+
+ // retrieve a pixel value with bilinear interpolation
+ guint32 pixelAt(double x, double y) const {
+ if (_alpha) {
+ return alphaAt(x, y) << 24;
+ }
+
+ double xf = floor(x), yf = floor(y);
+ int xi = xf, yi = yf;
+ guint32 xif = round((x - xf) * 255), yif = round((y - yf) * 255);
+ guint32 p00, p01, p10, p11;
+
+ unsigned char *pxi = _px + yi*_stride + xi*4;
+ guint32 *pxu = reinterpret_cast<guint32*>(pxi);
+ guint32 *pxl = reinterpret_cast<guint32*>(pxi + _stride);
+ p00 = *pxu; p10 = *(pxu + 1);
+ p01 = *pxl; p11 = *(pxl + 1);
+
+ guint32 comp[4];
+
+ for (unsigned i = 0; i < 4; ++i) {
+ guint32 shift = i*8;
+ guint32 mask = 0xff << shift;
+ guint32 c00 = (p00 & mask) >> shift;
+ guint32 c10 = (p10 & mask) >> shift;
+ guint32 c01 = (p01 & mask) >> shift;
+ guint32 c11 = (p11 & mask) >> shift;
+
+ guint32 iu = (255-xif) * c00 + xif * c10;
+ guint32 il = (255-xif) * c01 + xif * c11;
+ comp[i] = (255-yif) * iu + yif * il;
+ comp[i] = (comp[i] + (255*255/2)) / (255*255);
+ }
+
+ guint32 result = comp[0] | (comp[1] << 8) | (comp[2] << 16) | (comp[3] << 24);
+ return result;
+ }
+
+ // retrieve an alpha value with bilinear interpolation
+ guint32 alphaAt(double x, double y) const {
+ double xf = floor(x), yf = floor(y);
+ int xi = xf, yi = yf;
+ guint32 xif = round((x - xf) * 255), yif = round((y - yf) * 255);
+ guint32 p00, p01, p10, p11;
+ if (_alpha) {
+ unsigned char *pxu = _px + yi*_stride + xi;
+ unsigned char *pxl = pxu + _stride;
+ p00 = *pxu; p10 = *(pxu + 1);
+ p01 = *pxl; p11 = *(pxl + 1);
+ } else {
+ unsigned char *pxi = _px + yi*_stride + xi*4;
+ guint32 *pxu = reinterpret_cast<guint32*>(pxi);
+ guint32 *pxl = reinterpret_cast<guint32*>(pxi + _stride);
+ p00 = (*pxu & 0xff000000) >> 24; p10 = (*(pxu + 1) & 0xff000000) >> 24;
+ p01 = (*pxl & 0xff000000) >> 24; p11 = (*(pxl + 1) & 0xff000000) >> 24;
+ }
+ guint32 iu = (255-xif) * p00 + xif * p10;
+ guint32 il = (255-xif) * p01 + xif * p11;
+ guint32 result = (255-yif) * iu + yif * il;
+ result = (result + (255*255/2)) / (255*255);
+ return result;
+ }
+
+ // compute surface normal at given coordinates using 3x3 Sobel gradient filter
+ NR::Fvector surfaceNormalAt(int x, int y, double scale) const {
+ // Below there are some multiplies by zero. They will be optimized out.
+ // Do not remove them, because they improve readability.
+ // NOTE: fetching using alphaAt is slightly lazy.
+ NR::Fvector normal;
+ double fx = -scale/255.0, fy = -scale/255.0;
+ normal[Z_3D] = 1.0;
+ if (G_UNLIKELY(x == 0)) {
+ // leftmost column
+ if (G_UNLIKELY(y == 0)) {
+ // upper left corner
+ fx *= (2.0/3.0);
+ fy *= (2.0/3.0);
+ double p00 = alphaAt(x,y), p10 = alphaAt(x+1, y),
+ p01 = alphaAt(x,y+1), p11 = alphaAt(x+1, y+1);
+ normal[X_3D] =
+ -2.0 * p00 +2.0 * p10
+ -1.0 * p01 +1.0 * p11;
+ normal[Y_3D] =
+ -2.0 * p00 -1.0 * p10
+ +2.0 * p01 +1.0 * p11;
+ } else if (G_UNLIKELY(y == (_h - 1))) {
+ // lower left corner
+ fx *= (2.0/3.0);
+ fy *= (2.0/3.0);
+ double p00 = alphaAt(x,y-1), p10 = alphaAt(x+1, y-1),
+ p01 = alphaAt(x,y ), p11 = alphaAt(x+1, y);
+ normal[X_3D] =
+ -1.0 * p00 +1.0 * p10
+ -2.0 * p01 +2.0 * p11;
+ normal[Y_3D] =
+ -2.0 * p00 -1.0 * p10
+ +2.0 * p01 +1.0 * p11;
+ } else {
+ // leftmost column
+ fx *= (1.0/2.0);
+ fy *= (1.0/3.0);
+ double p00 = alphaAt(x, y-1), p10 = alphaAt(x+1, y-1),
+ p01 = alphaAt(x, y ), p11 = alphaAt(x+1, y ),
+ p02 = alphaAt(x, y+1), p12 = alphaAt(x+1, y+1);
+ normal[X_3D] =
+ -1.0 * p00 +1.0 * p10
+ -2.0 * p01 +2.0 * p11
+ -1.0 * p02 +1.0 * p12;
+ normal[Y_3D] =
+ -2.0 * p00 -1.0 * p10
+ +0.0 * p01 +0.0 * p11 // this will be optimized out
+ +2.0 * p02 +1.0 * p12;
+ }
+ } else if (G_UNLIKELY(x == (_w - 1))) {
+ // rightmost column
+ if (G_UNLIKELY(y == 0)) {
+ // top right corner
+ fx *= (2.0/3.0);
+ fy *= (2.0/3.0);
+ double p00 = alphaAt(x-1,y), p10 = alphaAt(x, y),
+ p01 = alphaAt(x-1,y+1), p11 = alphaAt(x, y+1);
+ normal[X_3D] =
+ -2.0 * p00 +2.0 * p10
+ -1.0 * p01 +1.0 * p11;
+ normal[Y_3D] =
+ -1.0 * p00 -2.0 * p10
+ +1.0 * p01 +2.0 * p11;
+ } else if (G_UNLIKELY(y == (_h - 1))) {
+ // bottom right corner
+ fx *= (2.0/3.0);
+ fy *= (2.0/3.0);
+ double p00 = alphaAt(x-1,y-1), p10 = alphaAt(x, y-1),
+ p01 = alphaAt(x-1,y ), p11 = alphaAt(x, y);
+ normal[X_3D] =
+ -1.0 * p00 +1.0 * p10
+ -2.0 * p01 +2.0 * p11;
+ normal[Y_3D] =
+ -1.0 * p00 -2.0 * p10
+ +1.0 * p01 +2.0 * p11;
+ } else {
+ // rightmost column
+ fx *= (1.0/2.0);
+ fy *= (1.0/3.0);
+ double p00 = alphaAt(x-1, y-1), p10 = alphaAt(x, y-1),
+ p01 = alphaAt(x-1, y ), p11 = alphaAt(x, y ),
+ p02 = alphaAt(x-1, y+1), p12 = alphaAt(x, y+1);
+ normal[X_3D] =
+ -1.0 * p00 +1.0 * p10
+ -2.0 * p01 +2.0 * p11
+ -1.0 * p02 +1.0 * p12;
+ normal[Y_3D] =
+ -1.0 * p00 -2.0 * p10
+ +0.0 * p01 +0.0 * p11
+ +1.0 * p02 +2.0 * p12;
+ }
+ } else {
+ // interior
+ if (G_UNLIKELY(y == 0)) {
+ // top row
+ fx *= (1.0/3.0);
+ fy *= (1.0/2.0);
+ double p00 = alphaAt(x-1, y ), p10 = alphaAt(x, y ), p20 = alphaAt(x+1, y ),
+ p01 = alphaAt(x-1, y+1), p11 = alphaAt(x, y+1), p21 = alphaAt(x+1, y+1);
+ normal[X_3D] =
+ -2.0 * p00 +0.0 * p10 +2.0 * p20
+ -1.0 * p01 +0.0 * p11 +1.0 * p21;
+ normal[Y_3D] =
+ -1.0 * p00 -2.0 * p10 -1.0 * p20
+ +1.0 * p01 +2.0 * p11 +1.0 * p21;
+ } else if (G_UNLIKELY(y == (_h - 1))) {
+ // bottom row
+ fx *= (1.0/3.0);
+ fy *= (1.0/2.0);
+ double p00 = alphaAt(x-1, y-1), p10 = alphaAt(x, y-1), p20 = alphaAt(x+1, y-1),
+ p01 = alphaAt(x-1, y ), p11 = alphaAt(x, y ), p21 = alphaAt(x+1, y );
+ normal[X_3D] =
+ -1.0 * p00 +0.0 * p10 +1.0 * p20
+ -2.0 * p01 +0.0 * p11 +2.0 * p21;
+ normal[Y_3D] =
+ -1.0 * p00 -2.0 * p10 -1.0 * p20
+ +1.0 * p01 +2.0 * p11 +1.0 * p21;
+ } else {
+ // interior pixels
+ // note: p11 is actually unused, so we don't fetch its value
+ fx *= (1.0/4.0);
+ fy *= (1.0/4.0);
+ double p00 = alphaAt(x-1, y-1), p10 = alphaAt(x, y-1), p20 = alphaAt(x+1, y-1),
+ p01 = alphaAt(x-1, y ), p11 = 0.0, p21 = alphaAt(x+1, y ),
+ p02 = alphaAt(x-1, y+1), p12 = alphaAt(x, y+1), p22 = alphaAt(x+1, y+1);
+ normal[X_3D] =
+ -1.0 * p00 +0.0 * p10 +1.0 * p20
+ -2.0 * p01 +0.0 * p11 +2.0 * p21
+ -1.0 * p02 +0.0 * p12 +1.0 * p22;
+ normal[Y_3D] =
+ -1.0 * p00 -2.0 * p10 -1.0 * p20
+ +0.0 * p01 +0.0 * p11 +0.0 * p21
+ +1.0 * p02 +2.0 * p12 +1.0 * p22;
+ }
+ }
+ normal[X_3D] *= fx;
+ normal[Y_3D] *= fy;
+ NR::normalize_vector(normal);
+ return normal;
+ }
+
+ unsigned char *_px;
+ int _w, _h, _stride;
+ bool _alpha;
+};
+
+/*
+// simple pixel accessor for image surface that handles different edge wrapping modes
+class PixelAccessor {
+public:
+ typedef PixelAccessor self;
+ enum EdgeMode {
+ EDGE_PAD,
+ EDGE_WRAP,
+ EDGE_ZERO
+ };
+
+ PixelAccessor(cairo_surface_t *s, EdgeMode e)
+ : _surface(s)
+ , _px(cairo_image_surface_get_data(s))
+ , _x(0), _y(0)
+ , _w(cairo_image_surface_get_width(s))
+ , _h(cairo_image_surface_get_height(s))
+ , _stride(cairo_image_surface_get_stride(s))
+ , _edge_mode(e)
+ , _alpha(cairo_image_surface_get_format(s) == CAIRO_FORMAT_A8)
+ {}
+
+ guint32 pixelAt(int x, int y) {
+ // This is a lot of ifs for a single pixel access. However, branch prediction
+ // should help us a lot, as the result of ifs is always the same for a single image.
+ int real_x = x, real_y = y;
+ switch (_edge_mode) {
+ case EDGE_PAD:
+ real_x = CLAMP(x, 0, _w-1);
+ real_y = CLAMP(y, 0, _h-1);
+ break;
+ case EDGE_WRAP:
+ real_x %= _w;
+ real_y %= _h;
+ break;
+ case EDGE_ZERO:
+ default:
+ if (x < 0 || x >= _w || y < 0 || y >= _h)
+ return 0;
+ break;
+ }
+ if (_alpha) {
+ return *(_px + real_y*_stride + real_x) << 24;
+ } else {
+ guint32 *px = reinterpret_cast<guint32*>(_px +real_y*_stride + real_x*4);
+ return *px;
+ }
+ }
+private:
+ cairo_surface_t *_surface;
+ guint8 *_px;
+ int _x, _y, _w, _h, _stride;
+ EdgeMode _edge_mode;
+ bool _alpha;
+};*/
+
+// Some helpers for pixel manipulation
+G_GNUC_CONST inline gint32
+pxclamp(gint32 v, gint32 low, gint32 high) {
+ // NOTE: it is possible to write a "branchless" clamping operation.
+ // However, it will be slower than this function, because the code below
+ // is compiled to conditional moves.
+ if (v < low) return low;
+ if (v > high) return high;
+ return v;
+}
+
+#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:encoding=utf-8:textwidth=99 :
diff --git a/src/display/cairo-utils.cpp b/src/display/cairo-utils.cpp
new file mode 100644
index 000000000..90f65c33e
--- /dev/null
+++ b/src/display/cairo-utils.cpp
@@ -0,0 +1,700 @@
+/*
+ * Helper functions to use cairo with inkscape
+ *
+ * Copyright (C) 2007 bulia byak
+ * Copyright (C) 2008 Johan Engelen
+ *
+ * Released under GNU GPL
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "display/cairo-utils.h"
+
+#include <stdexcept>
+#include <2geom/pathvector.h>
+#include <2geom/bezier-curve.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 "color.h"
+#include "helper/geom-curves.h"
+
+namespace Inkscape {
+
+CairoGroup::CairoGroup(cairo_t *_ct) : ct(_ct), pushed(false) {}
+CairoGroup::~CairoGroup() {
+ if (pushed) {
+ cairo_pattern_t *p = cairo_pop_group(ct);
+ cairo_pattern_destroy(p);
+ }
+}
+void CairoGroup::push() {
+ cairo_push_group(ct);
+ pushed = true;
+}
+void CairoGroup::push_with_content(cairo_content_t content) {
+ cairo_push_group_with_content(ct, content);
+ pushed = true;
+}
+cairo_pattern_t *CairoGroup::pop() {
+ if (pushed) {
+ cairo_pattern_t *ret = cairo_pop_group(ct);
+ pushed = false;
+ return ret;
+ } else {
+ throw std::logic_error("Cairo group popped without pushing it first");
+ }
+}
+Cairo::RefPtr<Cairo::Pattern> CairoGroup::popmm() {
+ if (pushed) {
+ cairo_pattern_t *ret = cairo_pop_group(ct);
+ Cairo::RefPtr<Cairo::Pattern> retmm(new Cairo::Pattern(ret, true));
+ pushed = false;
+ return retmm;
+ } else {
+ throw std::logic_error("Cairo group popped without pushing it first");
+ }
+}
+void CairoGroup::pop_to_source() {
+ if (pushed) {
+ cairo_pop_group_to_source(ct);
+ pushed = false;
+ }
+}
+
+CairoContext::CairoContext(cairo_t *obj, bool ref)
+ : Cairo::Context(obj, ref)
+{}
+
+void CairoContext::transform(Geom::Affine const &m)
+{
+ cairo_matrix_t cm;
+ cm.xx = m[0];
+ cm.xy = m[2];
+ cm.x0 = m[4];
+ cm.yx = m[1];
+ cm.yy = m[3];
+ cm.y0 = m[5];
+ cairo_transform(cobj(), &cm);
+}
+
+void CairoContext::set_source_rgba32(guint32 color)
+{
+ double red = SP_RGBA32_R_F(color);
+ double gre = SP_RGBA32_G_F(color);
+ double blu = SP_RGBA32_B_F(color);
+ double alp = SP_RGBA32_A_F(color);
+ cairo_set_source_rgba(cobj(), red, gre, blu, alp);
+}
+
+void CairoContext::append_path(Geom::PathVector const &pv)
+{
+ feed_pathvector_to_cairo(cobj(), pv);
+}
+
+Cairo::RefPtr<CairoContext> CairoContext::create(Cairo::RefPtr<Cairo::Surface> const &target)
+{
+ cairo_t *ct = cairo_create(target->cobj());
+ Cairo::RefPtr<CairoContext> ret(new CairoContext(ct, true));
+ return ret;
+}
+
+} // namespace Inkscape
+
+/*
+ * Can be called recursively.
+ * If optimize_stroke == false, the view Rect is not used.
+ */
+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) )
+ {
+ Geom::Point end_tr = c.finalPoint() * trans;
+ if (!optimize_stroke) {
+ cairo_line_to(cr, end_tr[0], end_tr[1]);
+ } else {
+ Geom::Rect swept(c.initialPoint()*trans, end_tr);
+ if (swept.intersects(view)) {
+ cairo_line_to(cr, end_tr[0], end_tr[1]);
+ } else {
+ cairo_move_to(cr, end_tr[0], end_tr[1]);
+ }
+ }
+ }
+ else if(Geom::QuadraticBezier const *quadratic_bezier = dynamic_cast<Geom::QuadraticBezier const*>(&c)) {
+ std::vector<Geom::Point> points = quadratic_bezier->points();
+ points[0] *= trans;
+ points[1] *= trans;
+ points[2] *= trans;
+ 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]);
+ } 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]);
+ } else {
+ cairo_move_to(cr, points[2][0], points[2][1]);
+ }
+ }
+ }
+ else if(Geom::CubicBezier const *cubic_bezier = dynamic_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]);
+ } 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]);
+ } else {
+ cairo_move_to(cr, points[3][0], points[3][1]);
+ }
+ }
+ }
+// 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);
+ }
+ }
+}
+
+
+/** Feeds path-creating calls to the cairo context translating them from the Path */
+static void
+feed_path_to_cairo (cairo_t *ct, Geom::Path const &path)
+{
+ if (path.empty())
+ return;
+
+ cairo_move_to(ct, path.initialPoint()[0], path.initialPoint()[1] );
+
+ 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
+ }
+
+ if (path.closed()) {
+ cairo_close_path(ct);
+ }
+}
+
+/** Feeds path-creating calls to the cairo context translating them from the Path, with the given transform and shift */
+static void
+feed_path_to_cairo (cairo_t *ct, Geom::Path const &path, Geom::Affine trans, Geom::OptRect area, bool optimize_stroke, double stroke_width)
+{
+ if (!area)
+ return;
+ if (path.empty())
+ return;
+
+ // Transform all coordinates to coords within "area"
+ Geom::Point shift = area->min();
+ Geom::Rect view = *area;
+ view.expandBy (stroke_width);
+ view = view * (Geom::Affine)Geom::Translate(-shift);
+ // Pass transformation to feed_curve, so that we don't need to create a whole new path.
+ Geom::Affine transshift(trans * Geom::Translate(-shift));
+
+ Geom::Point initial = path.initialPoint() * transshift;
+ cairo_move_to(ct, initial[0], initial[1] );
+
+ for(Geom::Path::const_iterator cit = path.begin(); cit != path.end_open(); ++cit) {
+ feed_curve_to_cairo(ct, *cit, transshift, view, optimize_stroke);
+ }
+
+ if (path.closed()) {
+ if (!optimize_stroke) {
+ cairo_close_path(ct);
+ } else {
+ cairo_line_to(ct, initial[0], initial[1]);
+ /* We cannot use cairo_close_path(ct) here because some parts of the path may have been
+ clipped and not drawn (maybe the before last segment was outside view area), which
+ would result in closing the "subpath" after the last interruption, not the entire path.
+
+ However, according to cairo documentation:
+ The behavior of cairo_close_path() is distinct from simply calling cairo_line_to() with the equivalent coordinate
+ in the case of stroking. When a closed sub-path is stroked, there are no caps on the ends of the sub-path. Instead,
+ there is a line join connecting the final and initial segments of the sub-path.
+
+ The correct fix will be possible when cairo introduces methods for moving without
+ ending/starting subpaths, which we will use for skipping invisible segments; then we
+ will be able to use cairo_close_path here. This issue also affects ps/eps/pdf export,
+ see bug 168129
+ */
+ }
+ }
+}
+
+/** Feeds path-creating calls to the cairo context translating them from the PathVector, with the given transform and shift
+ * One must have done cairo_new_path(ct); before calling this function. */
+void
+feed_pathvector_to_cairo (cairo_t *ct, Geom::PathVector const &pathv, Geom::Affine trans, Geom::OptRect area, bool optimize_stroke, double stroke_width)
+{
+ if (!area)
+ return;
+ if (pathv.empty())
+ return;
+
+ for(Geom::PathVector::const_iterator it = pathv.begin(); it != pathv.end(); ++it) {
+ feed_path_to_cairo(ct, *it, trans, area, optimize_stroke, stroke_width);
+ }
+}
+
+/** Feeds path-creating calls to the cairo context translating them from the PathVector
+ * One must have done cairo_new_path(ct); before calling this function. */
+void
+feed_pathvector_to_cairo (cairo_t *ct, Geom::PathVector const &pathv)
+{
+ if (pathv.empty())
+ return;
+
+ for(Geom::PathVector::const_iterator it = pathv.begin(); it != pathv.end(); ++it) {
+ feed_path_to_cairo(ct, *it);
+ }
+}
+
+void
+ink_cairo_set_source_rgba32(cairo_t *ct, guint32 rgba)
+{
+ cairo_set_source_rgba(ct, SP_RGBA32_R_F(rgba), SP_RGBA32_G_F(rgba), SP_RGBA32_B_F(rgba), SP_RGBA32_A_F(rgba));
+}
+
+void
+ink_cairo_set_source_color(cairo_t *ct, SPColor const &c, double opacity)
+{
+ cairo_set_source_rgba(ct, c.v.c[0], c.v.c[1], c.v.c[2], opacity);
+}
+
+void ink_matrix_to_2geom(Geom::Affine &m, cairo_matrix_t const &cm)
+{
+ m[0] = cm.xx;
+ m[2] = cm.xy;
+ m[4] = cm.x0;
+ m[1] = cm.yx;
+ m[3] = cm.yy;
+ m[5] = cm.y0;
+}
+
+void ink_matrix_to_cairo(cairo_matrix_t &cm, Geom::Affine const &m)
+{
+ cm.xx = m[0];
+ cm.xy = m[2];
+ cm.x0 = m[4];
+ cm.yx = m[1];
+ cm.yy = m[3];
+ cm.y0 = m[5];
+}
+
+void
+ink_cairo_transform(cairo_t *ct, Geom::Affine const &m)
+{
+ cairo_matrix_t cm;
+ ink_matrix_to_cairo(cm, m);
+ cairo_transform(ct, &cm);
+}
+
+void
+ink_cairo_pattern_set_matrix(cairo_pattern_t *cp, Geom::Affine const &m)
+{
+ cairo_matrix_t cm;
+ ink_matrix_to_cairo(cm, m);
+ cairo_pattern_set_matrix(cp, &cm);
+}
+
+void
+ink_cairo_set_source_argb32_pixbuf(cairo_t *ct, GdkPixbuf *pb, double x, double y)
+{
+ cairo_surface_t *pbs = ink_cairo_surface_create_for_argb32_pixbuf(pb);
+ cairo_set_source_surface(ct, pbs, x, y);
+ cairo_surface_destroy(pbs);
+}
+
+cairo_surface_t *
+ink_cairo_surface_create_for_argb32_pixbuf(GdkPixbuf *pb)
+{
+ guchar *data = gdk_pixbuf_get_pixels(pb);
+ int w = gdk_pixbuf_get_width(pb);
+ int h = gdk_pixbuf_get_height(pb);
+ int stride = gdk_pixbuf_get_rowstride(pb);
+
+ cairo_surface_t *pbs = cairo_image_surface_create_for_data(
+ data, CAIRO_FORMAT_ARGB32, w, h, stride);
+ return pbs;
+}
+
+/** @brief Create an exact copy of a surface.
+ * Creates a surface that has the same type, content type, dimensions and contents
+ * as the specified surface. */
+cairo_surface_t *
+ink_cairo_surface_copy(cairo_surface_t *s)
+{
+ cairo_surface_t *ns = ink_cairo_surface_create_identical(s);
+
+ if (cairo_surface_get_type(s) == CAIRO_SURFACE_TYPE_IMAGE) {
+ // use memory copy instead of using a Cairo context
+ cairo_surface_flush(s);
+ int stride = cairo_image_surface_get_stride(s);
+ int h = cairo_image_surface_get_height(s);
+ memcpy(cairo_image_surface_get_data(ns), cairo_image_surface_get_data(s), stride * h);
+ cairo_surface_mark_dirty(ns);
+ } else {
+ // generic implementation
+ cairo_t *ct = cairo_create(ns);
+ cairo_set_source_surface(ct, s, 0, 0);
+ cairo_set_operator(ct, CAIRO_OPERATOR_SOURCE);
+ cairo_paint(ct);
+ cairo_destroy(ct);
+ }
+
+ return ns;
+}
+
+/** @brief Create a surface that differs only in pixel content.
+ * Creates a surface that has the same type, content type and dimensions
+ * as the specified surface. Pixel contents are not copied. */
+cairo_surface_t *
+ink_cairo_surface_create_identical(cairo_surface_t *s)
+{
+ cairo_surface_t *ns = ink_cairo_surface_create_same_size(s, cairo_surface_get_content(s));
+ return ns;
+}
+
+cairo_surface_t *
+ink_cairo_surface_create_same_size(cairo_surface_t *s, cairo_content_t c)
+{
+ cairo_surface_t *ns = cairo_surface_create_similar(s, c,
+ ink_cairo_surface_get_width(s), ink_cairo_surface_get_height(s));
+ return ns;
+}
+
+/** @brief Extract the alpha channel into a new surface.
+ * Creates a surface with a content type of CAIRO_CONTENT_ALPHA that contains
+ * the alpha values of pixels from @a s. */
+cairo_surface_t *
+ink_cairo_extract_alpha(cairo_surface_t *s)
+{
+ cairo_surface_t *alpha = ink_cairo_surface_create_same_size(s, CAIRO_CONTENT_ALPHA);
+
+ cairo_t *ct = cairo_create(alpha);
+ cairo_set_source_surface(ct, s, 0, 0);
+ cairo_set_operator(ct, CAIRO_OPERATOR_SOURCE);
+ cairo_paint(ct);
+ cairo_destroy(ct);
+
+ return alpha;
+}
+
+cairo_surface_t *
+ink_cairo_surface_create_output(cairo_surface_t *image, cairo_surface_t *bg)
+{
+ cairo_content_t imgt = cairo_surface_get_content(image);
+ cairo_content_t bgt = cairo_surface_get_content(bg);
+ cairo_surface_t *out = NULL;
+
+ if (bgt == CAIRO_CONTENT_ALPHA && imgt == CAIRO_CONTENT_ALPHA) {
+ out = ink_cairo_surface_create_identical(bg);
+ } else {
+ out = ink_cairo_surface_create_same_size(bg, CAIRO_CONTENT_COLOR_ALPHA);
+ }
+
+ return out;
+}
+
+void
+ink_cairo_surface_blit(cairo_surface_t *src, cairo_surface_t *dest)
+{
+ if (cairo_surface_get_type(src) == CAIRO_SURFACE_TYPE_IMAGE &&
+ cairo_surface_get_type(dest) == CAIRO_SURFACE_TYPE_IMAGE &&
+ cairo_image_surface_get_format(src) == cairo_image_surface_get_format(dest) &&
+ cairo_image_surface_get_height(src) == cairo_image_surface_get_height(dest) &&
+ cairo_image_surface_get_width(src) == cairo_image_surface_get_width(dest) &&
+ cairo_image_surface_get_stride(src) == cairo_image_surface_get_stride(dest))
+ {
+ // use memory copy instead of using a Cairo context
+ cairo_surface_flush(src);
+ int stride = cairo_image_surface_get_stride(src);
+ int h = cairo_image_surface_get_height(src);
+ memcpy(cairo_image_surface_get_data(dest), cairo_image_surface_get_data(src), stride * h);
+ cairo_surface_mark_dirty(dest);
+ } else {
+ // generic implementation
+ cairo_t *ct = cairo_create(dest);
+ cairo_set_source_surface(ct, src, 0, 0);
+ cairo_set_operator(ct, CAIRO_OPERATOR_SOURCE);
+ cairo_paint(ct);
+ cairo_destroy(ct);
+ }
+}
+
+int
+ink_cairo_surface_get_width(cairo_surface_t *surface)
+{
+ // For now only image surface is handled.
+ // Later add others, e.g. cairo-gl
+ assert(cairo_surface_get_type(surface) == CAIRO_SURFACE_TYPE_IMAGE);
+ return cairo_image_surface_get_width(surface);
+}
+int
+ink_cairo_surface_get_height(cairo_surface_t *surface)
+{
+ assert(cairo_surface_get_type(surface) == CAIRO_SURFACE_TYPE_IMAGE);
+ return cairo_image_surface_get_height(surface);
+}
+
+static int ink_cairo_surface_average_color_internal(cairo_surface_t *surface, double &rf, double &gf, double &bf, double &af)
+{
+ rf = gf = bf = af = 0.0;
+ cairo_surface_flush(surface);
+ int width = cairo_image_surface_get_width(surface);
+ int height = cairo_image_surface_get_height(surface);
+ int stride = cairo_image_surface_get_stride(surface);
+ unsigned char *data = cairo_image_surface_get_data(surface);
+
+ /* TODO convert this to OpenMP somehow */
+ for (int y = 0; y < height; ++y, data += stride) {
+ for (int x = 0; x < width; ++x) {
+ guint32 px = *reinterpret_cast<guint32*>(data + 4*x);
+ EXTRACT_ARGB32(px, a,r,g,b)
+ rf += r / 255.0;
+ gf += g / 255.0;
+ bf += b / 255.0;
+ af += a / 255.0;
+ }
+ }
+ return width * height;
+}
+
+guint32 ink_cairo_surface_average_color(cairo_surface_t *surface)
+{
+ double rf,gf,bf,af;
+ ink_cairo_surface_average_color_premul(surface, rf,gf,bf,af);
+ guint32 r = round(rf * 255);
+ guint32 g = round(gf * 255);
+ guint32 b = round(bf * 255);
+ guint32 a = round(af * 255);
+ ASSEMBLE_ARGB32(px, a,r,g,b);
+ return px;
+}
+
+void ink_cairo_surface_average_color(cairo_surface_t *surface, double &r, double &g, double &b, double &a)
+{
+ int count = ink_cairo_surface_average_color_internal(surface, r,g,b,a);
+
+ r /= a;
+ g /= a;
+ b /= a;
+ a /= count;
+
+ r = CLAMP(r, 0.0, 1.0);
+ g = CLAMP(g, 0.0, 1.0);
+ b = CLAMP(b, 0.0, 1.0);
+ a = CLAMP(a, 0.0, 1.0);
+}
+
+void ink_cairo_surface_average_color_premul(cairo_surface_t *surface, double &r, double &g, double &b, double &a)
+{
+ int count = ink_cairo_surface_average_color_internal(surface, r,g,b,a);
+
+ r /= count;
+ g /= count;
+ b /= count;
+ a /= count;
+
+ r = CLAMP(r, 0.0, 1.0);
+ g = CLAMP(g, 0.0, 1.0);
+ b = CLAMP(b, 0.0, 1.0);
+ a = CLAMP(a, 0.0, 1.0);
+}
+
+cairo_pattern_t *
+ink_cairo_pattern_create_checkerboard()
+{
+ int const w = 6;
+ int const h = 6;
+
+ cairo_surface_t *s = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 2*w, 2*h);
+
+ cairo_t *ct = cairo_create(s);
+ cairo_set_operator(ct, CAIRO_OPERATOR_SOURCE);
+ cairo_set_source_rgb(ct, 0.75, 0.75, 0.75);
+ cairo_paint(ct);
+ cairo_set_source_rgb(ct, 0.5, 0.5, 0.5);
+ cairo_rectangle(ct, 0, 0, w, h);
+ cairo_rectangle(ct, w, h, w, h);
+ cairo_fill(ct);
+ cairo_destroy(ct);
+
+ cairo_pattern_t *p = cairo_pattern_create_for_surface(s);
+ cairo_pattern_set_extend(p, CAIRO_EXTEND_REPEAT);
+ cairo_pattern_set_filter(p, CAIRO_FILTER_NEAREST);
+
+ cairo_surface_destroy(s);
+ return p;
+}
+
+/* The following two functions use "from" instead of "to", because when you write:
+ val1 = argb32_from_pixbuf(val1);
+ the name of the format is closer to the value in that format. */
+
+guint32 argb32_from_pixbuf(guint32 c)
+{
+ guint32 o = 0;
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+ guint32 a = (c & 0xff000000) >> 24;
+#else
+ guint32 a = (c & 0x000000ff);
+#endif
+ if (a != 0) {
+ // extract color components
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+ guint32 r = (c & 0x000000ff);
+ guint32 g = (c & 0x0000ff00) >> 8;
+ guint32 b = (c & 0x00ff0000) >> 16;
+#else
+ guint32 r = (c & 0xff000000) >> 24;
+ guint32 g = (c & 0x00ff0000) >> 16;
+ guint32 b = (c & 0x0000ff00) >> 8;
+#endif
+ // premultiply
+ r = premul_alpha(r, a);
+ b = premul_alpha(b, a);
+ g = premul_alpha(g, a);
+ // combine into output
+ o = (a << 24) | (r << 16) | (g << 8) | (b);
+ }
+ return o;
+}
+
+guint32 pixbuf_from_argb32(guint32 c)
+{
+ guint32 a = (c & 0xff000000) >> 24;
+ if (a == 0) return 0;
+
+ // extract color components
+ guint32 r = (c & 0x00ff0000) >> 16;
+ guint32 g = (c & 0x0000ff00) >> 8;
+ guint32 b = (c & 0x000000ff);
+ // unpremultiply; adding a/2 gives correct rounding
+ // (taken from Cairo sources)
+ r = (r * 255 + a/2) / a;
+ b = (b * 255 + a/2) / a;
+ g = (g * 255 + a/2) / a;
+ // combine into output
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+ guint32 o = (r) | (g << 8) | (b << 16) | (a << 24);
+#else
+ guint32 o = (r << 24) | (g << 16) | (b << 8) | (a);
+#endif
+ return o;
+}
+
+/**
+ * @brief Convert pixel data from GdkPixbuf format to ARGB.
+ * This will convert pixel data from GdkPixbuf format to Cairo's native pixel format.
+ * This involves premultiplying alpha and shuffling around the channels.
+ * Pixbuf data must have an alpha channel, otherwise the results are undefined
+ * (usually a segfault).
+ */
+void
+convert_pixels_pixbuf_to_argb32(guchar *data, int w, int h, int stride)
+{
+ for (int i = 0; i < h; ++i) {
+ guint32 *px = reinterpret_cast<guint32*>(data + i*stride);
+ for (int j = 0; j < w; ++j) {
+ *px = argb32_from_pixbuf(*px);
+ ++px;
+ }
+ }
+}
+
+/**
+ * @brief Convert pixel data from ARGB to GdkPixbuf format.
+ * This will convert pixel data from GdkPixbuf format to Cairo's native pixel format.
+ * This involves premultiplying alpha and shuffling around the channels.
+ */
+void
+convert_pixels_argb32_to_pixbuf(guchar *data, int w, int h, int stride)
+{
+ for (int i = 0; i < h; ++i) {
+ guint32 *px = reinterpret_cast<guint32*>(data + i*stride);
+ for (int j = 0; j < w; ++j) {
+ *px = pixbuf_from_argb32(*px);
+ ++px;
+ }
+ }
+}
+
+/**
+ * @brief 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));
+}
+
+/**
+ * @brief 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));
+}
+
+guint32 argb32_from_rgba(guint32 in)
+{
+ guint32 r, g, b, a;
+ a = (in & 0x000000ff);
+ r = premul_alpha((in & 0xff000000) >> 24, a);
+ g = premul_alpha((in & 0x00ff0000) >> 16, a);
+ b = premul_alpha((in & 0x0000ff00) >> 8, a);
+ ASSEMBLE_ARGB32(px, a, r, g, b)
+ return px;
+}
+
+/*
+ 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:textwidth=99 :
diff --git a/src/display/cairo-utils.h b/src/display/cairo-utils.h
new file mode 100644
index 000000000..0c2ac2dd6
--- /dev/null
+++ b/src/display/cairo-utils.h
@@ -0,0 +1,153 @@
+/**
+ * @file
+ * @brief Cairo integration helpers
+ *//*
+ * Authors:
+ * Krzysztof KosiƄski <tweenk.pl@gmail.com>
+ *
+ * Copyright (C) 2010 Authors
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifndef SEEN_INKSCAPE_DISPLAY_CAIRO_UTILS_H
+#define SEEN_INKSCAPE_DISPLAY_CAIRO_UTILS_H
+
+#include <glib.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <cairomm/cairomm.h>
+#include <2geom/forward.h>
+
+struct SPColor;
+
+namespace Inkscape {
+
+/** @brief RAII idiom for Cairo groups.
+ * Groups are temporary surfaces used when rendering e.g. masks and opacity.
+ * Use this class to ensure that each group push is matched with a pop. */
+class CairoGroup {
+public:
+ CairoGroup(cairo_t *_ct);
+ ~CairoGroup();
+ void push();
+ void push_with_content(cairo_content_t content);
+ cairo_pattern_t *pop();
+ Cairo::RefPtr<Cairo::Pattern> popmm();
+ void pop_to_source();
+private:
+ cairo_t *ct;
+ bool pushed;
+};
+
+/** @brief RAII idiom for Cairo state saving */
+class CairoSave {
+public:
+ CairoSave(cairo_t *_ct, bool save=false)
+ : ct(_ct)
+ , saved(save)
+ {
+ if (save) {
+ cairo_save(ct);
+ }
+ }
+ void save() {
+ if (!saved) {
+ cairo_save(ct);
+ saved = true;
+ }
+ }
+ ~CairoSave() {
+ if (saved)
+ cairo_restore(ct);
+ }
+private:
+ cairo_t *ct;
+ bool saved;
+};
+
+/** @brief Cairo context with Inkscape-specific operations */
+class CairoContext : public Cairo::Context {
+public:
+ CairoContext(cairo_t *obj, bool ref = false);
+
+ void transform(Geom::Affine const &m);
+ void set_source_rgba32(guint32 color);
+ void append_path(Geom::PathVector const &pv);
+
+ static Cairo::RefPtr<CairoContext> create(Cairo::RefPtr<Cairo::Surface> const &target);
+};
+
+} // namespace Inkscape
+
+void ink_cairo_set_source_color(cairo_t *ct, SPColor const &color, double opacity);
+void ink_cairo_set_source_rgba32(cairo_t *ct, guint32 rgba);
+void ink_cairo_transform(cairo_t *ct, Geom::Affine const &m);
+void ink_cairo_pattern_set_matrix(cairo_pattern_t *cp, Geom::Affine const &m);
+void ink_cairo_set_source_argb32_pixbuf(cairo_t *ct, GdkPixbuf *pb, double x, double y);
+
+void ink_matrix_to_2geom(Geom::Affine &, cairo_matrix_t const &);
+void ink_matrix_to_cairo(cairo_matrix_t &, Geom::Affine const &);
+
+cairo_surface_t *ink_cairo_surface_copy(cairo_surface_t *s);
+cairo_surface_t *ink_cairo_surface_create_identical(cairo_surface_t *s);
+cairo_surface_t *ink_cairo_surface_create_same_size(cairo_surface_t *s, cairo_content_t c);
+cairo_surface_t *ink_cairo_extract_alpha(cairo_surface_t *s);
+cairo_surface_t *ink_cairo_surface_create_output(cairo_surface_t *image, cairo_surface_t *bg);
+void ink_cairo_surface_blit(cairo_surface_t *src, cairo_surface_t *dest);
+int ink_cairo_surface_get_width(cairo_surface_t *surface);
+int ink_cairo_surface_get_height(cairo_surface_t *surface);
+guint32 ink_cairo_surface_average_color(cairo_surface_t *surface);
+void ink_cairo_surface_average_color(cairo_surface_t *surface, double &r, double &g, double &b, double &a);
+void ink_cairo_surface_average_color_premul(cairo_surface_t *surface, double &r, double &g, double &b, double &a);
+
+cairo_pattern_t *ink_cairo_pattern_create_checkerboard();
+
+void convert_pixels_pixbuf_to_argb32(guchar *data, int w, int h, int rs);
+void convert_pixels_argb32_to_pixbuf(guchar *data, int w, int h, int rs);
+void convert_pixbuf_normal_to_argb32(GdkPixbuf *);
+void convert_pixbuf_argb32_to_normal(GdkPixbuf *);
+cairo_surface_t *ink_cairo_surface_create_for_argb32_pixbuf(GdkPixbuf *pb);
+
+G_GNUC_CONST guint32 argb32_from_pixbuf(guint32 in);
+G_GNUC_CONST guint32 pixbuf_from_argb32(guint32 in);
+/** Convert a pixel in 0xRRGGBBAA format to Cairo ARGB32 format. */
+G_GNUC_CONST guint32 argb32_from_rgba(guint32 in);
+
+
+G_GNUC_CONST inline guint32
+premul_alpha(guint32 color, guint32 alpha)
+{
+ guint32 temp = alpha * color + 128;
+ return (temp + (temp >> 8)) >> 8;
+}
+G_GNUC_CONST inline guint32
+unpremul_alpha(guint32 color, guint32 alpha)
+{
+ // NOTE: you must check for alpha != 0 yourself.
+ return (255 * color + alpha/2) / alpha;
+}
+
+// TODO: move those to 2Geom
+void feed_pathvector_to_cairo (cairo_t *ct, Geom::PathVector const &pathv, Geom::Affine trans, Geom::OptRect area, bool optimize_stroke, double stroke_width);
+void feed_pathvector_to_cairo (cairo_t *ct, Geom::PathVector const &pathv);
+
+#define EXTRACT_ARGB32(px,a,r,g,b) \
+ guint32 a, r, g, b; \
+ a = ((px) & 0xff000000) >> 24; \
+ r = ((px) & 0x00ff0000) >> 16; \
+ g = ((px) & 0x0000ff00) >> 8; \
+ b = ((px) & 0x000000ff);
+
+#define ASSEMBLE_ARGB32(px,a,r,g,b) \
+ guint32 px = (a << 24) | (r << 16) | (g << 8) | b;
+
+#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:encoding=utf-8:textwidth=99 :
diff --git a/src/display/canvas-arena.cpp b/src/display/canvas-arena.cpp
index 8436a3b99..72062ce99 100644
--- a/src/display/canvas-arena.cpp
+++ b/src/display/canvas-arena.cpp
@@ -10,15 +10,15 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include <libnr/nr-blit.h>
#include <gtk/gtk.h>
-#include <display/sp-canvas-util.h>
+#include "display/display-forward.h"
+#include "display/sp-canvas-util.h"
#include "helper/sp-marshal.h"
-#include <display/nr-arena.h>
-#include <display/nr-arena-group.h>
-#include <display/canvas-arena.h>
-#include <display/inkscape-cairo.h>
+#include "display/nr-arena.h"
+#include "display/nr-arena-group.h"
+#include "display/canvas-arena.h"
+#include "display/cairo-utils.h"
enum {
ARENA_EVENT,
@@ -188,6 +188,7 @@ sp_canvas_arena_render (SPCanvasItem *item, SPCanvasBuf *buf)
gint bw, bh;
SPCanvasArena *arena = SP_CANVAS_ARENA (item);
+ //SPCanvas *canvas = item->canvas;
nr_arena_item_invoke_update (arena->root, NULL, &arena->gc,
NR_ARENA_ITEM_STATE_BBOX | NR_ARENA_ITEM_STATE_RENDER,
@@ -200,28 +201,17 @@ sp_canvas_arena_render (SPCanvasItem *item, SPCanvasBuf *buf)
if ((bw < 1) || (bh < 1)) return;
NRRectL area;
- NRPixBlock cb;
area.x0 = buf->rect.x0;
area.y0 = buf->rect.y0;
area.x1 = buf->rect.x1;
area.y1 = buf->rect.y1;
- nr_pixblock_setup_extern (&cb, NR_PIXBLOCK_MODE_R8G8B8A8P, area.x0, area.y0, area.x1, area.y1,
- buf->buf,
- buf->buf_rowstride,
- FALSE, FALSE);
-
- cb.visible_area = buf->visible_rect;
- cairo_t *ct = nr_create_cairo_context (&area, &cb);
- nr_arena_item_invoke_render (ct, arena->root, &area, &cb, 0);
-
- cairo_surface_t *cst = cairo_get_target(ct);
- cairo_destroy (ct);
- cairo_surface_finish (cst);
- cairo_surface_destroy (cst);
-
- nr_pixblock_release (&cb);
+ sp_canvas_prepare_buffer(buf);
+ cairo_save(buf->ct);
+ cairo_translate(buf->ct, -area.x0, -area.y0);
+ nr_arena_item_invoke_render (buf->ct, arena->root, &area, NULL, 0);
+ cairo_restore(buf->ct);
}
static double
@@ -368,22 +358,15 @@ sp_canvas_arena_set_sticky (SPCanvasArena *ca, gboolean sticky)
}
void
-sp_canvas_arena_render_pixblock (SPCanvasArena *ca, NRPixBlock *pb)
+sp_canvas_arena_render_surface (SPCanvasArena *ca, cairo_surface_t *surface, NRRectL const &r)
{
- NRRectL area;
-
g_return_if_fail (ca != NULL);
g_return_if_fail (SP_IS_CANVAS_ARENA (ca));
- /* fixme: */
- pb->empty = FALSE;
-
- area.x0 = pb->area.x0;
- area.y0 = pb->area.y0;
- area.x1 = pb->area.x1;
- area.y1 = pb->area.y1;
-
- nr_arena_item_invoke_render (NULL, ca->root, &area, pb, 0);
+ cairo_t *ct = cairo_create(surface);
+ cairo_translate(ct, -r.x0, -r.y0);
+ nr_arena_item_invoke_render (ct, ca->root, &r, NULL, 0);
+ cairo_destroy(ct);
}
diff --git a/src/display/canvas-arena.h b/src/display/canvas-arena.h
index 90be5f9e3..ef065a03b 100644
--- a/src/display/canvas-arena.h
+++ b/src/display/canvas-arena.h
@@ -13,8 +13,11 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include "sp-canvas-item.h"
-#include "nr-arena-item.h"
+#include <cairo.h>
+#include <2geom/rect.h>
+#include "display/sp-canvas.h"
+#include "display/sp-canvas-item.h"
+#include "display/nr-arena-item.h"
G_BEGIN_DECLS
@@ -55,7 +58,7 @@ GtkType sp_canvas_arena_get_type (void);
void sp_canvas_arena_set_pick_delta (SPCanvasArena *ca, gdouble delta);
void sp_canvas_arena_set_sticky (SPCanvasArena *ca, gboolean sticky);
-void sp_canvas_arena_render_pixblock (SPCanvasArena *ca, NRPixBlock *pb);
+void sp_canvas_arena_render_surface (SPCanvasArena *ca, cairo_surface_t *surface, NRRectL const &area);
G_END_DECLS
diff --git a/src/display/canvas-axonomgrid.cpp b/src/display/canvas-axonomgrid.cpp
index 845c4e077..a9893f09d 100644
--- a/src/display/canvas-axonomgrid.cpp
+++ b/src/display/canvas-axonomgrid.cpp
@@ -15,25 +15,24 @@
* For example: the line drawing code should not be here. There _must_ be a function somewhere else that can provide this functionality...
*/
-#include "sp-canvas-util.h"
-#include "canvas-axonomgrid.h"
-#include "util/mathfns.h"
#include "2geom/line.h"
-#include <libnr/nr-pixops.h>
-
+#include "desktop.h"
#include "canvas-grid.h"
#include "desktop-handles.h"
+#include "display/cairo-utils.h"
+#include "display/canvas-axonomgrid.h"
+#include "display/canvas-grid.h"
+#include "display/display-forward.h"
+#include "display/sp-canvas-util.h"
+#include "document.h"
#include "helper/units.h"
-#include "svg/svg-color.h"
-#include "xml/node-event-vector.h"
-#include "sp-object.h"
-
-#include "sp-namedview.h"
#include "inkscape.h"
-#include "desktop.h"
-
-#include "document.h"
#include "preferences.h"
+#include "sp-namedview.h"
+#include "sp-object.h"
+#include "svg/svg-color.h"
+#include "util/mathfns.h"
+#include "xml/node-event-vector.h"
#define SAFE_SETPIXEL //undefine this when it is certain that setpixel is never called with invalid params
@@ -45,37 +44,6 @@ enum Dim3 { X=0, Y, Z };
static double deg_to_rad(double deg) { return deg*M_PI/180.0;}
-
-/**
- \brief This function renders a pixel on a particular buffer.
-
- The topleft of the buffer equals
- ( rect.x0 , rect.y0 ) in screen coordinates
- ( 0 , 0 ) in setpixel coordinates
- The bottomright of the buffer equals
- ( rect.x1 , rect,y1 ) in screen coordinates
- ( rect.x1 - rect.x0 , rect.y1 - rect.y0 ) in setpixel coordinates
-*/
-static void
-sp_caxonomgrid_setpixel (SPCanvasBuf *buf, gint x, gint y, guint32 rgba)
-{
-#ifdef SAFE_SETPIXEL
- if ( (x >= buf->rect.x0) && (x < buf->rect.x1) && (y >= buf->rect.y0) && (y < buf->rect.y1) ) {
-#endif
- guint r, g, b, a;
- r = NR_RGBA32_R (rgba);
- g = NR_RGBA32_G (rgba);
- b = NR_RGBA32_B (rgba);
- a = NR_RGBA32_A (rgba);
- guchar * p = buf->buf + (y - buf->rect.y0) * buf->buf_rowstride + (x - buf->rect.x0) * 4;
- p[0] = NR_COMPOSEN11_1111 (r, a, p[0]);
- p[1] = NR_COMPOSEN11_1111 (g, a, p[1]);
- p[2] = NR_COMPOSEN11_1111 (b, a, p[2]);
-#ifdef SAFE_SETPIXEL
- }
-#endif
-}
-
/**
\brief This function renders a line on a particular canvas buffer,
using Bresenham's line drawing function.
@@ -85,6 +53,12 @@ sp_caxonomgrid_setpixel (SPCanvasBuf *buf, gint x, gint y, guint32 rgba)
static void
sp_caxonomgrid_drawline (SPCanvasBuf *buf, gint x0, gint y0, gint x1, gint y1, guint32 rgba)
{
+ cairo_move_to(buf->ct, 0.5 + x0, 0.5 + y0);
+ cairo_line_to(buf->ct, 0.5 + x1, 0.5 + y1);
+ ink_cairo_set_source_rgba32(buf->ct, rgba);
+ cairo_stroke(buf->ct);
+
+#if 0
int dy = y1 - y0;
int dx = x1 - x0;
int stepx, stepy;
@@ -118,30 +92,19 @@ sp_caxonomgrid_drawline (SPCanvasBuf *buf, gint x0, gint y0, gint x1, gint y1, g
sp_caxonomgrid_setpixel(buf, x0, y0, rgba);
}
}
-
+#endif
}
static void
sp_grid_vline (SPCanvasBuf *buf, gint x, gint ys, gint ye, guint32 rgba)
{
- if ((x >= buf->rect.x0) && (x < buf->rect.x1)) {
- guint r, g, b, a;
- gint y0, y1, y;
- guchar *p;
- r = NR_RGBA32_R(rgba);
- g = NR_RGBA32_G (rgba);
- b = NR_RGBA32_B (rgba);
- a = NR_RGBA32_A (rgba);
- y0 = MAX (buf->rect.y0, ys);
- y1 = MIN (buf->rect.y1, ye + 1);
- p = buf->buf + (y0 - buf->rect.y0) * buf->buf_rowstride + (x - buf->rect.x0) * 4;
- for (y = y0; y < y1; y++) {
- p[0] = NR_COMPOSEN11_1111 (r, a, p[0]);
- p[1] = NR_COMPOSEN11_1111 (g, a, p[1]);
- p[2] = NR_COMPOSEN11_1111 (b, a, p[2]);
- p += buf->buf_rowstride;
- }
- }
+ if ((x < buf->rect.x0) || (x >= buf->rect.x1))
+ return;
+
+ cairo_move_to(buf->ct, 0.5 + x, 0.5 + ys);
+ cairo_line_to(buf->ct, 0.5 + x, 0.5 + ye);
+ ink_cairo_set_source_rgba32(buf->ct, rgba);
+ cairo_stroke(buf->ct);
}
namespace Inkscape {
@@ -561,6 +524,11 @@ CanvasAxonomGrid::Render (SPCanvasBuf *buf)
_empcolor = empcolor;
}
+ cairo_save(buf->ct);
+ cairo_translate(buf->ct, -buf->rect.x0, -buf->rect.y0);
+ cairo_set_line_width(buf->ct, 1.0);
+ cairo_set_line_cap(buf->ct, CAIRO_LINE_CAP_SQUARE);
+
// gc = gridcoordinates (the coordinates calculated from the grids origin 'grid->ow'.
// sc = screencoordinates ( for example "buf->rect.x0" is in screencoordinates )
// bc = buffer patch coordinates
@@ -658,6 +626,8 @@ CanvasAxonomGrid::Render (SPCanvasBuf *buf)
sp_caxonomgrid_drawline (buf, x0, y0, x1, y1, _empcolor);
}
}
+
+ cairo_restore(buf->ct);
}
CanvasAxonomGridSnapper::CanvasAxonomGridSnapper(CanvasAxonomGrid *grid, SnapManager *sm, Geom::Coord const d) : LineSnapper(sm, d)
diff --git a/src/display/canvas-bpath.cpp b/src/display/canvas-bpath.cpp
index 725a1d0ff..f86743744 100644
--- a/src/display/canvas-bpath.cpp
+++ b/src/display/canvas-bpath.cpp
@@ -15,19 +15,17 @@
#endif
#include <sstream>
#include <string.h>
-#include <desktop.h>
+#include "desktop.h"
#include "color.h"
-#include "sp-canvas-util.h"
-#include "inkscape-cairo.h"
-#include "canvas-bpath.h"
#include "display/sp-canvas-group.h"
+#include "display/sp-canvas-util.h"
+#include "display/canvas-bpath.h"
+#include "display/display-forward.h"
#include "display/curve.h"
-#include "display/inkscape-cairo.h"
-#include "libnr/nr-pixops.h"
+#include "display/cairo-utils.h"
#include "helper/geom.h"
-
void nr_pixblock_render_bpath_rgba (Shape* theS,uint32_t color,NRRectL &area,char* destBuf,int stride);
static void sp_canvas_bpath_class_init (SPCanvasBPathClass *klass);
@@ -139,8 +137,6 @@ sp_canvas_bpath_render (SPCanvasItem *item, SPCanvasBuf *buf)
{
SPCanvasBPath *cbp = SP_CANVAS_BPATH (item);
- sp_canvas_prepare_buffer(buf);
-
Geom::Rect area (Geom::Point(buf->rect.x0, buf->rect.y0), Geom::Point(buf->rect.x1, buf->rect.y1));
if ( !cbp->curve ||
@@ -154,33 +150,29 @@ sp_canvas_bpath_render (SPCanvasItem *item, SPCanvasBuf *buf)
bool dofill = ((cbp->fill_rgba & 0xff) != 0);
bool dostroke = ((cbp->stroke_rgba & 0xff) != 0);
- cairo_set_tolerance(buf->ct, 1.25); // low quality, but good enough for canvas items
+ cairo_set_tolerance(buf->ct, 0.5);
cairo_new_path(buf->ct);
- if (!dofill)
- feed_pathvector_to_cairo (buf->ct, cbp->curve->get_pathvector(), cbp->affine, area, true, 1);
- else
- feed_pathvector_to_cairo (buf->ct, cbp->curve->get_pathvector(), cbp->affine, area, false, 1);
+ feed_pathvector_to_cairo (buf->ct, cbp->curve->get_pathvector(), cbp->affine, area,
+ /* optimized_stroke = */ !dofill, 1);
if (dofill) {
// RGB / BGR
- cairo_set_source_rgba(buf->ct, SP_RGBA32_B_F(cbp->fill_rgba), SP_RGBA32_G_F(cbp->fill_rgba), SP_RGBA32_R_F(cbp->fill_rgba), SP_RGBA32_A_F(cbp->fill_rgba));
+ ink_cairo_set_source_rgba32(buf->ct, cbp->fill_rgba);
cairo_set_fill_rule(buf->ct, cbp->fill_rule == SP_WIND_RULE_EVENODD? CAIRO_FILL_RULE_EVEN_ODD
: CAIRO_FILL_RULE_WINDING);
- if (dostroke)
- cairo_fill_preserve(buf->ct);
- else
- cairo_fill(buf->ct);
+ cairo_fill_preserve(buf->ct);
}
if (dostroke) {
- // RGB / BGR
- cairo_set_source_rgba(buf->ct, SP_RGBA32_B_F(cbp->stroke_rgba), SP_RGBA32_G_F(cbp->stroke_rgba), SP_RGBA32_R_F(cbp->stroke_rgba), SP_RGBA32_A_F(cbp->stroke_rgba));
+ ink_cairo_set_source_rgba32(buf->ct, cbp->stroke_rgba);
cairo_set_line_width(buf->ct, 1);
if (cbp->dashes[0] != 0 && cbp->dashes[1] != 0) {
cairo_set_dash (buf->ct, cbp->dashes, 2, 0);
}
cairo_stroke(buf->ct);
+ } else {
+ cairo_new_path(buf->ct);
}
}
@@ -192,12 +184,12 @@ sp_canvas_bpath_point (SPCanvasItem *item, Geom::Point p, SPCanvasItem **actual_
if ( !cbp->curve ||
((cbp->stroke_rgba & 0xff) == 0 && (cbp->fill_rgba & 0xff) == 0 ) ||
cbp->curve->get_segment_count() < 1)
- return NR_HUGE;
+ return Geom::infinity();
double width = 0.5;
Geom::Rect viewbox = item->canvas->getViewbox();
viewbox.expandBy (width);
- double dist = NR_HUGE;
+ double dist = Geom::infinity();
pathv_matrix_point_bbox_wind_distance(cbp->curve->get_pathvector(), cbp->affine, p, NULL, NULL, &dist, 0.5, &viewbox);
if (dist <= 1.0) {
diff --git a/src/display/canvas-grid.cpp b/src/display/canvas-grid.cpp
index 79bfc31ad..82ea036f6 100644
--- a/src/display/canvas-grid.cpp
+++ b/src/display/canvas-grid.cpp
@@ -12,25 +12,26 @@
* Don't be shy to correct things.
*/
-#include "sp-canvas-group.h"
+#include "desktop.h"
#include "sp-canvas-util.h"
#include "util/mathfns.h"
-#include "libnr/nr-pixops.h"
+#include "display-forward.h"
#include "desktop-handles.h"
+#include "display/cairo-utils.h"
+#include "display/canvas-axonomgrid.h"
+#include "display/canvas-grid.h"
+#include "display/display-forward.h"
+#include "display/sp-canvas-util.h"
+#include "display/sp-canvas-group.h"
+#include "document.h"
#include "helper/units.h"
-#include "svg/svg-color.h"
-#include "xml/node-event-vector.h"
-#include "sp-object.h"
-
-#include "sp-namedview.h"
#include "inkscape.h"
-#include "desktop.h"
-
-#include "../document.h"
#include "preferences.h"
-
-#include "canvas-grid.h"
-#include "canvas-axonomgrid.h"
+#include "sp-namedview.h"
+#include "sp-object.h"
+#include "svg/svg-color.h"
+#include "util/mathfns.h"
+#include "xml/node-event-vector.h"
using Inkscape::DocumentUndo;
@@ -831,65 +832,86 @@ CanvasXYGrid::Update (Geom::Affine const &affine, unsigned int /*flags*/)
static void
grid_hline (SPCanvasBuf *buf, gint y, gint xs, gint xe, guint32 rgba)
{
- if ((y >= buf->rect.y0) && (y < buf->rect.y1)) {
- guint r, g, b, a;
- gint x0, x1, x;
- guchar *p;
- r = NR_RGBA32_R (rgba);
- g = NR_RGBA32_G (rgba);
- b = NR_RGBA32_B (rgba);
- a = NR_RGBA32_A (rgba);
- x0 = MAX (buf->rect.x0, xs);
- x1 = MIN (buf->rect.x1, xe + 1);
- p = buf->buf + (y - buf->rect.y0) * buf->buf_rowstride + (x0 - buf->rect.x0) * 4;
- for (x = x0; x < x1; x++) {
- p[0] = NR_COMPOSEN11_1111 (r, a, p[0]);
- p[1] = NR_COMPOSEN11_1111 (g, a, p[1]);
- p[2] = NR_COMPOSEN11_1111 (b, a, p[2]);
- p += 4;
- }
+ if ((y < buf->rect.y0) || (y >= buf->rect.y1))
+ return;
+
+ cairo_move_to(buf->ct, 0.5 + xs, 0.5 + y);
+ cairo_line_to(buf->ct, 0.5 + xe, 0.5 + y);
+ ink_cairo_set_source_rgba32(buf->ct, rgba);
+ cairo_stroke(buf->ct);
+#if 0
+ guint r, g, b, a;
+ gint x0, x1, x;
+ guchar *p;
+ r = NR_RGBA32_R (rgba);
+ g = NR_RGBA32_G (rgba);
+ b = NR_RGBA32_B (rgba);
+ a = NR_RGBA32_A (rgba);
+ x0 = MAX (buf->rect.x0, xs);
+ x1 = MIN (buf->rect.x1, xe + 1);
+ p = buf->buf + (y - buf->rect.y0) * buf->buf_rowstride + (x0 - buf->rect.x0) * 4;
+ for (x = x0; x < x1; x++) {
+ p[0] = NR_COMPOSEN11_1111 (r, a, p[0]);
+ p[1] = NR_COMPOSEN11_1111 (g, a, p[1]);
+ p[2] = NR_COMPOSEN11_1111 (b, a, p[2]);
+ p += 4;
}
+#endif
}
static void
grid_vline (SPCanvasBuf *buf, gint x, gint ys, gint ye, guint32 rgba)
{
- if ((x >= buf->rect.x0) && (x < buf->rect.x1)) {
- guint r, g, b, a;
- gint y0, y1, y;
- guchar *p;
- r = NR_RGBA32_R(rgba);
- g = NR_RGBA32_G (rgba);
- b = NR_RGBA32_B (rgba);
- a = NR_RGBA32_A (rgba);
- y0 = MAX (buf->rect.y0, ys);
- y1 = MIN (buf->rect.y1, ye + 1);
- p = buf->buf + (y0 - buf->rect.y0) * buf->buf_rowstride + (x - buf->rect.x0) * 4;
- for (y = y0; y < y1; y++) {
- p[0] = NR_COMPOSEN11_1111 (r, a, p[0]);
- p[1] = NR_COMPOSEN11_1111 (g, a, p[1]);
- p[2] = NR_COMPOSEN11_1111 (b, a, p[2]);
- p += buf->buf_rowstride;
- }
+ if ((x < buf->rect.x0) || (x >= buf->rect.x1))
+ return;
+
+ cairo_move_to(buf->ct, 0.5 + x, 0.5 + ys);
+ cairo_line_to(buf->ct, 0.5 + x, 0.5 + ye);
+ ink_cairo_set_source_rgba32(buf->ct, rgba);
+ cairo_stroke(buf->ct);
+ #if 0
+ guint r, g, b, a;
+ gint y0, y1, y;
+ guchar *p;
+ r = NR_RGBA32_R(rgba);
+ g = NR_RGBA32_G (rgba);
+ b = NR_RGBA32_B (rgba);
+ a = NR_RGBA32_A (rgba);
+ y0 = MAX (buf->rect.y0, ys);
+ y1 = MIN (buf->rect.y1, ye + 1);
+ p = buf->buf + (y0 - buf->rect.y0) * buf->buf_rowstride + (x - buf->rect.x0) * 4;
+ for (y = y0; y < y1; y++) {
+ p[0] = NR_COMPOSEN11_1111 (r, a, p[0]);
+ p[1] = NR_COMPOSEN11_1111 (g, a, p[1]);
+ p[2] = NR_COMPOSEN11_1111 (b, a, p[2]);
+ p += buf->buf_rowstride;
}
+ #endif
}
static void
grid_dot (SPCanvasBuf *buf, gint x, gint y, guint32 rgba)
{
- if ( (y >= buf->rect.y0) && (y < buf->rect.y1)
- && (x >= buf->rect.x0) && (x < buf->rect.x1) ) {
- guint r, g, b, a;
- guchar *p;
- r = NR_RGBA32_R (rgba);
- g = NR_RGBA32_G (rgba);
- b = NR_RGBA32_B (rgba);
- a = NR_RGBA32_A (rgba);
- p = buf->buf + (y - buf->rect.y0) * buf->buf_rowstride + (x - buf->rect.x0) * 4;
- p[0] = NR_COMPOSEN11_1111 (r, a, p[0]);
- p[1] = NR_COMPOSEN11_1111 (g, a, p[1]);
- p[2] = NR_COMPOSEN11_1111 (b, a, p[2]);
- }
+ if ( (y < buf->rect.y0) || (y >= buf->rect.y1)
+ || (x < buf->rect.x0) || (x >= buf->rect.x1) )
+ return;
+
+ cairo_rectangle(buf->ct, x, y, 1, 1);
+ ink_cairo_set_source_rgba32(buf->ct, rgba);
+ cairo_fill(buf->ct);
+
+#if 0
+ guint r, g, b, a;
+ guchar *p;
+ r = NR_RGBA32_R (rgba);
+ g = NR_RGBA32_G (rgba);
+ b = NR_RGBA32_B (rgba);
+ a = NR_RGBA32_A (rgba);
+ p = buf->buf + (y - buf->rect.y0) * buf->buf_rowstride + (x - buf->rect.x0) * 4;
+ p[0] = NR_COMPOSEN11_1111 (r, a, p[0]);
+ p[1] = NR_COMPOSEN11_1111 (g, a, p[1]);
+ p[2] = NR_COMPOSEN11_1111 (b, a, p[2]);
+#endif
}
void
@@ -910,6 +932,11 @@ CanvasXYGrid::Render (SPCanvasBuf *buf)
_empcolor = empcolor;
}
+ cairo_save(buf->ct);
+ cairo_translate(buf->ct, -buf->rect.x0, -buf->rect.y0);
+ cairo_set_line_width(buf->ct, 1.0);
+ cairo_set_line_cap(buf->ct, CAIRO_LINE_CAP_SQUARE);
+
if (!render_dotted) {
gint ylinenum;
gdouble y;
@@ -961,6 +988,7 @@ CanvasXYGrid::Render (SPCanvasBuf *buf)
}
}
+ cairo_restore(buf->ct);
}
CanvasXYGridSnapper::CanvasXYGridSnapper(CanvasXYGrid *grid, SnapManager *sm, Geom::Coord const d) : LineSnapper(sm, d)
diff --git a/src/display/canvas-text.cpp b/src/display/canvas-text.cpp
index 70196b307..54cbe5da8 100644
--- a/src/display/canvas-text.cpp
+++ b/src/display/canvas-text.cpp
@@ -13,19 +13,19 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include "sp-canvas-util.h"
-#include "canvas-text.h"
-#include "display/inkscape-cairo.h"
-#include <sstream>
-#include <string.h>
-#include "desktop.h"
-
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
-#include <color.h>
-#include <libnr/nr-pixops.h>
+#include <sstream>
+#include <string.h>
+
+#include "display-forward.h"
+#include "sp-canvas-util.h"
+#include "canvas-text.h"
+#include "display/cairo-utils.h"
+#include "desktop.h"
+#include "color.h"
static void sp_canvastext_class_init (SPCanvasTextClass *klass);
static void sp_canvastext_init (SPCanvasText *canvastext);
@@ -123,13 +123,11 @@ sp_canvastext_render (SPCanvasItem *item, SPCanvasBuf *buf)
cairo_set_font_size(buf->ct, cl->fontsize);
cairo_text_path(buf->ct, cl->text);
- cairo_set_source_rgba(buf->ct, SP_RGBA32_B_F(cl->rgba_stroke), SP_RGBA32_G_F(cl->rgba_stroke), SP_RGBA32_R_F(cl->rgba_stroke), SP_RGBA32_A_F(cl->rgba_stroke));
+ ink_cairo_set_source_rgba32(buf->ct, cl->rgba_stroke);
cairo_set_line_width (buf->ct, 2.0);
cairo_stroke_preserve(buf->ct);
- cairo_set_source_rgba(buf->ct, SP_RGBA32_B_F(cl->rgba), SP_RGBA32_G_F(cl->rgba), SP_RGBA32_R_F(cl->rgba), SP_RGBA32_A_F(cl->rgba));
+ ink_cairo_set_source_rgba32(buf->ct, cl->rgba);
cairo_fill(buf->ct);
-
- cairo_new_path(buf->ct);
}
static void
diff --git a/src/display/display-forward.h b/src/display/display-forward.h
new file mode 100644
index 000000000..bc7013214
--- /dev/null
+++ b/src/display/display-forward.h
@@ -0,0 +1,32 @@
+#ifndef SEEN_DISPLAY_DISPLAY_FORWARD_H
+#define SEEN_DISPLAY_DISPLAY_FORWARD_H
+
+#include <glib-object.h>
+
+struct SPCanvas;
+struct SPCanvasClass;
+struct SPCanvasItem;
+typedef struct _SPCanvasItemClass SPCanvasItemClass;
+struct SPCanvasGroup;
+struct SPCanvasGroupClass;
+class SPCurve;
+
+namespace Inkscape {
+namespace Display {
+ class TemporaryItem;
+ class TemporaryItemList;
+}
+}
+
+#endif /* !SEEN_DISPLAY_DISPLAY_FORWARD_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/display/grayscale.cpp b/src/display/grayscale.cpp
index 37f2b255c..745a08c1e 100644
--- a/src/display/grayscale.cpp
+++ b/src/display/grayscale.cpp
@@ -21,14 +21,22 @@
namespace Grayscale {
+/* Original values from Johan:
+const float red_factor = 0.3;
+const float green_factor = 0.59;
+const float blue_factor = 0.11;
+*/
+
+// Values below are from the SVG specification
+const float red_factor = 0.2125;
+const float green_factor = 0.7154;
+const float blue_factor = 0.0721;
+
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) {
- float red_factor = 0.3;
- float green_factor = 0.59;
- float blue_factor = 0.11;
/** To reduce banding in gradients, this calculation is tweaked a bit
* by outputing blue+1 or red+1 or both. The luminance is calculated
diff --git a/src/display/grayscale.h b/src/display/grayscale.h
index d7092687c..fe0d75cad 100644
--- a/src/display/grayscale.h
+++ b/src/display/grayscale.h
@@ -19,10 +19,6 @@ namespace Grayscale {
guint32 process(guchar r, guchar g, guchar b, guchar a);
guchar luminance(guchar r, guchar g, guchar b);
- const float red_factor = 0.3;
- const float green_factor = 0.59;
- const float blue_factor = 0.11;
-
bool activeDesktopIsGrayscale();
};
diff --git a/src/display/guideline.cpp b/src/display/guideline.cpp
index abfec250f..c761fa74e 100644
--- a/src/display/guideline.cpp
+++ b/src/display/guideline.cpp
@@ -13,15 +13,11 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-
-#include <libnr/nr-pixops.h>
#include <2geom/transforms.h>
#include "sp-canvas-util.h"
#include "sp-ctrlpoint.h"
#include "guideline.h"
-#include "cairo.h"
-#include "inkscape-cairo.h"
-#include "color.h"
+#include "display/cairo-utils.h"
static void sp_guideline_class_init(SPGuideLineClass *c);
static void sp_guideline_init(SPGuideLine *guideline);
@@ -109,74 +105,37 @@ static void sp_guideline_render(SPCanvasItem *item, SPCanvasBuf *buf)
SPGuideLine const *gl = SP_GUIDELINE (item);
- sp_canvas_prepare_buffer(buf);
- cairo_t* ctx = nr_create_cairo_context_canvasbuf (NULL /*area*/, buf); //this function ignores the "area" parameter
- cairo_set_font_size (ctx, 10);
- cairo_set_line_width (ctx, 10);
- /// @todo uh??! why must the order of these arguments be reversed? bgra instead of rgba!
- cairo_set_source_rgba (ctx, SP_RGBA32_B_F(gl->rgba), SP_RGBA32_G_F(gl->rgba), SP_RGBA32_R_F(gl->rgba), SP_RGBA32_A_F(gl->rgba));
-
- unsigned int const r = NR_RGBA32_R (gl->rgba);
- unsigned int const g = NR_RGBA32_G (gl->rgba);
- unsigned int const b = NR_RGBA32_B (gl->rgba);
- unsigned int const a = NR_RGBA32_A (gl->rgba);
+ cairo_save(buf->ct);
+ cairo_translate(buf->ct, -buf->rect.x0, -buf->rect.y0);
+ ink_cairo_set_source_rgba32(buf->ct, gl->rgba);
+ cairo_set_line_width(buf->ct, 1);
+ cairo_set_line_cap(buf->ct, CAIRO_LINE_CAP_SQUARE);
+ cairo_set_font_size(buf->ct, 10);
int px = (int) Inkscape::round(gl->point_on_line[Geom::X]);
int py = (int) Inkscape::round(gl->point_on_line[Geom::Y]);
- if (gl->is_vertical()) {
- if (px < buf->rect.x0 || px >= buf->rect.x1) {
- return;
- }
-
- int p0 = buf->rect.y0;
- int p1 = buf->rect.y1;
- int step = buf->buf_rowstride;
- unsigned char *d = buf->buf + 4 * (px - buf->rect.x0);
-
- for (int p = p0; p < p1; p++) {
- d[0] = NR_COMPOSEN11_1111(r, a, d[0]);
- d[1] = NR_COMPOSEN11_1111(g, a, d[1]);
- d[2] = NR_COMPOSEN11_1111(b, a, d[2]);
- d += step;
- }
-
- if (gl->label){
- cairo_move_to(ctx, px - buf->rect.x0 + 5, py - buf->rect.y0);
- cairo_rotate(ctx, 3.1415/2);
- cairo_show_text(ctx, gl->label);
- }
+ if (gl->label) {
+ cairo_save(buf->ct);
+ cairo_translate(buf->ct, px, py);
+ cairo_rotate(buf->ct, atan2(gl->normal_to_line[Geom::X], gl->normal_to_line[Geom::Y]));
+ cairo_translate(buf->ct, 0, -5);
+ cairo_move_to(buf->ct, 0, 0);
+ cairo_show_text(buf->ct, gl->label);
+ cairo_restore(buf->ct);
+ }
+ if (gl->is_vertical()) {
+ int position = (int) Inkscape::round(gl->point_on_line[Geom::X]);
+ cairo_move_to(buf->ct, position + 0.5, buf->rect.y0 + 0.5);
+ cairo_line_to(buf->ct, position + 0.5, buf->rect.y1 - 0.5);
+ cairo_stroke(buf->ct);
} else if (gl->is_horizontal()) {
- if (py < buf->rect.y0 || py >= buf->rect.y1) {
- return;
- }
-
- int p0 = buf->rect.x0;
- int p1 = buf->rect.x1;
- int step = 4;
- unsigned char *d = buf->buf + (py - buf->rect.y0) * buf->buf_rowstride;
-
- for (int p = p0; p < p1; p++) {
- d[0] = NR_COMPOSEN11_1111(r, a, d[0]);
- d[1] = NR_COMPOSEN11_1111(g, a, d[1]);
- d[2] = NR_COMPOSEN11_1111(b, a, d[2]);
- d += step;
- }
-
- if (gl->label){
- cairo_move_to(ctx, px - buf->rect.x0, py - buf->rect.y0 - 5);
- cairo_show_text(ctx, gl->label);
- }
-
+ int position = (int) Inkscape::round(gl->point_on_line[Geom::Y]);
+ cairo_move_to(buf->ct, buf->rect.x0 + 0.5, position + 0.5);
+ cairo_line_to(buf->ct, buf->rect.x1 - 0.5, position + 0.5);
+ cairo_stroke(buf->ct);
} else {
-
- if (gl->label){
- cairo_move_to(ctx, px - buf->rect.x0 + 5, py - buf->rect.y0);
- cairo_rotate(ctx, atan2(gl->normal_to_line[Geom::X], gl->normal_to_line[Geom::Y]));
- cairo_show_text(ctx, gl->label);
- }
-
// render angled line, once intersection has been detected, draw from there.
Geom::Point parallel_to_line( gl->normal_to_line[Geom::Y],
/*should be minus, but inverted y axis*/ gl->normal_to_line[Geom::X]);
@@ -187,7 +146,7 @@ static void sp_guideline_render(SPCanvasItem *item, SPCanvasBuf *buf)
// intersects with left vertical!
double y_intersect_right = (buf->rect.x1 - gl->point_on_line[Geom::X]) * parallel_to_line[Geom::Y] / parallel_to_line[Geom::X] + gl->point_on_line[Geom::Y];
sp_guideline_drawline (buf, buf->rect.x0, static_cast<gint>(round(y_intersect_left)), buf->rect.x1, static_cast<gint>(round(y_intersect_right)), gl->rgba);
- return;
+ goto end;
}
//try to intersect with right vertical of rect
@@ -195,7 +154,7 @@ static void sp_guideline_render(SPCanvasItem *item, SPCanvasBuf *buf)
if ( (y_intersect_right >= buf->rect.y0) && (y_intersect_right <= buf->rect.y1) ) {
// intersects with right vertical!
sp_guideline_drawline (buf, buf->rect.x1, static_cast<gint>(round(y_intersect_right)), buf->rect.x0, static_cast<gint>(round(y_intersect_left)), gl->rgba);
- return;
+ goto end;
}
//try to intersect with top horizontal of rect
@@ -204,7 +163,7 @@ static void sp_guideline_render(SPCanvasItem *item, SPCanvasBuf *buf)
// intersects with top horizontal!
double x_intersect_bottom = (buf->rect.y1 - gl->point_on_line[Geom::Y]) * parallel_to_line[Geom::X] / parallel_to_line[Geom::Y] + gl->point_on_line[Geom::X];
sp_guideline_drawline (buf, static_cast<gint>(round(x_intersect_top)), buf->rect.y0, static_cast<gint>(round(x_intersect_bottom)), buf->rect.y1, gl->rgba);
- return;
+ goto end;
}
//try to intersect with bottom horizontal of rect
@@ -212,9 +171,11 @@ static void sp_guideline_render(SPCanvasItem *item, SPCanvasBuf *buf)
if ( (x_intersect_top >= buf->rect.x0) && (x_intersect_top <= buf->rect.x1) ) {
// intersects with bottom horizontal!
sp_guideline_drawline (buf, static_cast<gint>(round(x_intersect_bottom)), buf->rect.y1, static_cast<gint>(round(x_intersect_top)), buf->rect.y0, gl->rgba);
- return;
+ goto end;
}
}
+ end:
+ cairo_restore(buf->ct);
}
static void sp_guideline_update(SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags)
@@ -247,7 +208,7 @@ static double sp_guideline_point(SPCanvasItem *item, Geom::Point p, SPCanvasItem
SPGuideLine *gl = SP_GUIDELINE (item);
if (!gl->sensitive) {
- return NR_HUGE;
+ return Geom::infinity();
}
*actual_item = item;
@@ -320,82 +281,12 @@ void sp_guideline_delete(SPGuideLine *gl)
gtk_object_destroy(GTK_OBJECT(gl));
}
-//##########################################################
-// Line rendering
-#define SAFE_SETPIXEL //undefine this when it is certain that setpixel is never called with invalid params
-
-/**
- \brief This function renders a pixel on a particular buffer.
-
- The topleft of the buffer equals
- ( rect.x0 , rect.y0 ) in screen coordinates
- ( 0 , 0 ) in setpixel coordinates
- The bottomright of the buffer equals
- ( rect.x1 , rect,y1 ) in screen coordinates
- ( rect.x1 - rect.x0 , rect.y1 - rect.y0 ) in setpixel coordinates
-*/
static void
-sp_guideline_setpixel (SPCanvasBuf *buf, gint x, gint y, guint32 rgba)
+sp_guideline_drawline (SPCanvasBuf *buf, gint x0, gint y0, gint x1, gint y1, guint32 /*rgba*/)
{
-#ifdef SAFE_SETPIXEL
- if ( (x >= buf->rect.x0) && (x < buf->rect.x1) && (y >= buf->rect.y0) && (y < buf->rect.y1) ) {
-#endif
- guint r, g, b, a;
- r = NR_RGBA32_R (rgba);
- g = NR_RGBA32_G (rgba);
- b = NR_RGBA32_B (rgba);
- a = NR_RGBA32_A (rgba);
- guchar * p = buf->buf + (y - buf->rect.y0) * buf->buf_rowstride + (x - buf->rect.x0) * 4;
- p[0] = NR_COMPOSEN11_1111 (r, a, p[0]);
- p[1] = NR_COMPOSEN11_1111 (g, a, p[1]);
- p[2] = NR_COMPOSEN11_1111 (b, a, p[2]);
-#ifdef SAFE_SETPIXEL
- }
-#endif
-}
-
-/**
- \brief This function renders a line on a particular canvas buffer,
- using Bresenham's line drawing function.
- http://www.cs.unc.edu/~mcmillan/comp136/Lecture6/Lines.html
- Coordinates are interpreted as SCREENcoordinates
-*/
-static void
-sp_guideline_drawline (SPCanvasBuf *buf, gint x0, gint y0, gint x1, gint y1, guint32 rgba)
-{
- int dy = y1 - y0;
- int dx = x1 - x0;
- int stepx, stepy;
-
- if (dy < 0) { dy = -dy; stepy = -1; } else { stepy = 1; }
- if (dx < 0) { dx = -dx; stepx = -1; } else { stepx = 1; }
- dy <<= 1; // dy is now 2*dy
- dx <<= 1; // dx is now 2*dx
-
- sp_guideline_setpixel(buf, x0, y0, rgba);
- if (dx > dy) {
- int fraction = dy - (dx >> 1); // same as 2*dy - dx
- while (x0 != x1) {
- if (fraction >= 0) {
- y0 += stepy;
- fraction -= dx; // same as fraction -= 2*dx
- }
- x0 += stepx;
- fraction += dy; // same as fraction -= 2*dy
- sp_guideline_setpixel(buf, x0, y0, rgba);
- }
- } else {
- int fraction = dx - (dy >> 1);
- while (y0 != y1) {
- if (fraction >= 0) {
- x0 += stepx;
- fraction -= dy;
- }
- y0 += stepy;
- fraction += dx;
- sp_guideline_setpixel(buf, x0, y0, rgba);
- }
- }
+ cairo_move_to(buf->ct, x0 + 0.5, y0 + 0.5);
+ cairo_line_to(buf->ct, x1 + 0.5, y1 + 0.5);
+ cairo_stroke(buf->ct);
}
/*
diff --git a/src/display/inkscape-cairo.cpp b/src/display/inkscape-cairo.cpp
deleted file mode 100644
index 4fc492ba8..000000000
--- a/src/display/inkscape-cairo.cpp
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
- * Helper functions to use cairo with inkscape
- *
- * Copyright (C) 2007 bulia byak
- * Copyright (C) 2008 Johan Engelen
- *
- * Released under GNU GPL
- *
- */
-
-#include <cairo.h>
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <libnr/nr-pixblock.h>
-#include <libnr/nr-convert2geom.h>
-#include "../style.h"
-#include "nr-arena.h"
-#include "sp-canvas.h"
-#include <2geom/pathvector.h>
-#include <2geom/bezier-curve.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 "helper/geom-curves.h"
-
-/** Creates a cairo context to render to the given pixblock on the given area */
-cairo_t *
-nr_create_cairo_context_for_data (NRRectL *area, NRRectL *buf_area, unsigned char *px, unsigned int rowstride)
-{
- if (!nr_rect_l_test_intersect_ptr(buf_area, area))
- return NULL;
-
- NRRectL clip;
- nr_rect_l_intersect (&clip, buf_area, area);
- unsigned char *dpx = px + (clip.y0 - buf_area->y0) * rowstride + 4 * (clip.x0 - buf_area->x0);
- int width = area->x1 - area->x0;
- int height = area->y1 - area->y0;
- // even though cairo cannot draw in nonpremul mode, select ARGB32 for R8G8B8A8N as the closest; later eliminate R8G8B8A8N everywhere
- cairo_surface_t* cst = cairo_image_surface_create_for_data
- (dpx,
- CAIRO_FORMAT_ARGB32,
- width,
- height,
- rowstride);
- cairo_t *ct = cairo_create (cst);
-
- return ct;
-}
-
-/** Creates a cairo context to render to the given SPCanvasBuf on the given area */
-cairo_t *
-nr_create_cairo_context_canvasbuf (NRRectL */*area*/, SPCanvasBuf *b)
-{
- return nr_create_cairo_context_for_data (&(b->rect), &(b->rect), b->buf, b->buf_rowstride);
-}
-
-
-/** Creates a cairo context to render to the given NRPixBlock on the given area */
-cairo_t *
-nr_create_cairo_context (NRRectL *area, NRPixBlock *pb)
-{
- return nr_create_cairo_context_for_data (area, &(pb->area), NR_PIXBLOCK_PX (pb), pb->rs);
-}
-
-/*
- * Can be called recursively.
- * If optimize_stroke == false, the view Rect is not used.
- */
-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) )
- {
- Geom::Point end_tr = c.finalPoint() * trans;
- if (!optimize_stroke) {
- cairo_line_to(cr, end_tr[0], end_tr[1]);
- } else {
- Geom::Rect swept(c.initialPoint()*trans, end_tr);
- if (swept.intersects(view)) {
- cairo_line_to(cr, end_tr[0], end_tr[1]);
- } else {
- cairo_move_to(cr, end_tr[0], end_tr[1]);
- }
- }
- }
- else if(Geom::QuadraticBezier const *quadratic_bezier = dynamic_cast<Geom::QuadraticBezier const*>(&c)) {
- std::vector<Geom::Point> points = quadratic_bezier->points();
- points[0] *= trans;
- points[1] *= trans;
- points[2] *= trans;
- 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]);
- } 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]);
- } else {
- cairo_move_to(cr, points[2][0], points[2][1]);
- }
- }
- }
- else if(Geom::CubicBezier const *cubic_bezier = dynamic_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]);
- } 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]);
- } else {
- cairo_move_to(cr, points[3][0], points[3][1]);
- }
- }
- }
-// 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);
- }
- }
-}
-
-
-/** Feeds path-creating calls to the cairo context translating them from the Path */
-static void
-feed_path_to_cairo (cairo_t *ct, Geom::Path const &path)
-{
- if (path.empty())
- return;
-
- cairo_move_to(ct, path.initialPoint()[0], path.initialPoint()[1] );
-
- 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
- }
-
- if (path.closed()) {
- cairo_close_path(ct);
- }
-}
-
-/** Feeds path-creating calls to the cairo context translating them from the Path, with the given transform and shift */
-static void
-feed_path_to_cairo (cairo_t *ct, Geom::Path const &path, Geom::Affine trans, Geom::OptRect area, bool optimize_stroke, double stroke_width)
-{
- if (!area)
- return;
- if (path.empty())
- return;
-
- // Transform all coordinates to coords within "area"
- Geom::Point shift = area->min();
- Geom::Rect view = *area;
- view.expandBy (stroke_width);
- view = view * (Geom::Affine)Geom::Translate(-shift);
- // Pass transformation to feed_curve, so that we don't need to create a whole new path.
- Geom::Affine transshift(trans * Geom::Translate(-shift));
-
- Geom::Point initial = path.initialPoint() * transshift;
- cairo_move_to(ct, initial[0], initial[1] );
-
- for(Geom::Path::const_iterator cit = path.begin(); cit != path.end_open(); ++cit) {
- feed_curve_to_cairo(ct, *cit, transshift, view, optimize_stroke);
- }
-
- if (path.closed()) {
- if (!optimize_stroke) {
- cairo_close_path(ct);
- } else {
- cairo_line_to(ct, initial[0], initial[1]);
- /* We cannot use cairo_close_path(ct) here because some parts of the path may have been
- clipped and not drawn (maybe the before last segment was outside view area), which
- would result in closing the "subpath" after the last interruption, not the entire path.
-
- However, according to cairo documentation:
- The behavior of cairo_close_path() is distinct from simply calling cairo_line_to() with the equivalent coordinate
- in the case of stroking. When a closed sub-path is stroked, there are no caps on the ends of the sub-path. Instead,
- there is a line join connecting the final and initial segments of the sub-path.
-
- The correct fix will be possible when cairo introduces methods for moving without
- ending/starting subpaths, which we will use for skipping invisible segments; then we
- will be able to use cairo_close_path here. This issue also affects ps/eps/pdf export,
- see bug 168129
- */
- }
- }
-}
-
-/** Feeds path-creating calls to the cairo context translating them from the PathVector, with the given transform and shift
- * One must have done cairo_new_path(ct); before calling this function. */
-void
-feed_pathvector_to_cairo (cairo_t *ct, Geom::PathVector const &pathv, Geom::Affine trans, Geom::OptRect area, bool optimize_stroke, double stroke_width)
-{
- if (!area)
- return;
- if (pathv.empty())
- return;
-
- for(Geom::PathVector::const_iterator it = pathv.begin(); it != pathv.end(); ++it) {
- feed_path_to_cairo(ct, *it, trans, area, optimize_stroke, stroke_width);
- }
-}
-
-/** Feeds path-creating calls to the cairo context translating them from the PathVector
- * One must have done cairo_new_path(ct); before calling this function. */
-void
-feed_pathvector_to_cairo (cairo_t *ct, Geom::PathVector const &pathv)
-{
- if (pathv.empty())
- return;
-
- for(Geom::PathVector::const_iterator it = pathv.begin(); it != pathv.end(); ++it) {
- feed_path_to_cairo(ct, *it);
- }
-}
-
-/*
- 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/inkscape-cairo.h b/src/display/inkscape-cairo.h
deleted file mode 100644
index 4133661fe..000000000
--- a/src/display/inkscape-cairo.h
+++ /dev/null
@@ -1,37 +0,0 @@
-#ifndef __INKSCAPE_CAIRO_H__
-#define __INKSCAPE_CAIRO_H__
-
-/*
- * Helper functions to use cairo with inkscape
- *
- * Copyright (C) 2007 bulia byak
- * Copyright (C) 2008 Johan Engelen
- *
- * Released under GNU GPL
- *
- */
-
-#include <2geom/forward.h>
-#include <cairo/cairo.h>
-#include <boost/optional.hpp>
-#include "libnr/nr-rect.h"
-
-struct NRPixBlock;
-class SPCanvasBuf;
-
-cairo_t *nr_create_cairo_context_canvasbuf (NRRectL *area, SPCanvasBuf *b);
-cairo_t *nr_create_cairo_context (NRRectL *area, NRPixBlock *pb);
-void feed_pathvector_to_cairo (cairo_t *ct, Geom::PathVector const &pathv, Geom::Affine trans, Geom::OptRect area, bool optimize_stroke, double stroke_width);
-void feed_pathvector_to_cairo (cairo_t *ct, Geom::PathVector const &pathv);
-
-#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:textwidth=99 :
diff --git a/src/display/nr-3dutils.cpp b/src/display/nr-3dutils.cpp
index c5e7b4c1b..eb6858374 100644
--- a/src/display/nr-3dutils.cpp
+++ b/src/display/nr-3dutils.cpp
@@ -11,134 +11,15 @@
#include <glib/gmessages.h>
-#include "libnr/nr-pixblock.h"
#include "display/nr-3dutils.h"
#include <cmath>
+#include <2geom/point.h>
+#include <2geom/affine.h>
namespace NR {
-#define BEGIN 0 // TOP or LEFT
-#define MIDDLE 1
-#define END 2 // BOTTOM or RIGHT
-
-#define START(v) ((v)==BEGIN? 1 : 0)
-#define FINISH(v) ((v)==END? 1 : 2)
-
-signed char K_X[3][3][3][3] = {
- //K_X[TOP]
- {
- //K_X[TOP][LEFT]
- {
- { 0, 0, 0},
- { 0, -2, 2},
- { 0, -1, 1}
- },
- {
- { 0, 0, 0},
- {-2, 0, 2},
- {-1, 0, 1}
- },
- {
- { 0, 0, 0},
- {-2, 2, 0},
- {-1, 1, 0}
- }
- },
- //K_X[MIDDLE]
- {
- //K_X[MIDDLE][LEFT]
- {
- { 0, -1, 1},
- { 0, -2, 2},
- { 0, -1, 1}
- },
- {
- {-1, 0, 1},
- {-2, 0, 2},
- {-1, 0, 1}
- },
- {
- {-1, 1, 0},
- {-2, 2, 0},
- {-1, 1, 0}
- }
- },
- //K_X[BOTTOM]
- {
- //K_X[BOTTOM][LEFT]
- {
- { 0, -1, 1},
- { 0, -2, 2},
- { 0, 0, 0}
- },
- {
- {-1, 0, 1},
- {-2, 0, 2},
- { 0, 0, 0}
- },
- {
- {-1, 1, 0},
- {-2, 2, 0},
- { 0, 0, 0}
- }
- }
-};
-
-//K_Y is obtained by transposing K_X globally and each of its components
-
-gdouble FACTOR_X[3][3] = {
- {2./3, 1./3, 2./3},
- {1./2, 1./4, 1./2},
- {2./3, 1./3, 2./3}
-};
-
-//FACTOR_Y is obtained by transposing FACTOR_X
-
-inline
-int get_carac(int i, int len, int delta) {
- if (i < delta)
- return BEGIN;
- else if (i > len - 1 - delta)
- return END;
- else
- return MIDDLE;
-}
-
-//assumes in is RGBA
-//should be made more resistant
-void compute_surface_normal(Fvector &N, gdouble ss, NRPixBlock *in, int i, int j, int dx, int dy) {
- int w = in->area.x1 - in->area.x0;
- int h = in->area.y1 - in->area.y0;
- int k, l, alpha_idx, alpha_idx_y;
- int x_carac, y_carac;
- gdouble alpha;
- gdouble accu_x;
- gdouble accu_y;
- unsigned char *data = NR_PIXBLOCK_PX (in);
- g_assert(NR_PIXBLOCK_BPP(in) == 4);
- x_carac = get_carac(j, w, dx); //LEFT, MIDDLE or RIGHT
- y_carac = get_carac(i, h, dy); //TOP, MIDDLE or BOTTOM
- alpha_idx = 4*(i*w + j);
- accu_x = 0;
- accu_y = 0;
- for (k = START(y_carac); k <= FINISH(y_carac); k++) {
- alpha_idx_y = alpha_idx + 4*(k-1)*dy*w;
- for (l = START(x_carac); l <= FINISH(x_carac); l++) {
- alpha = (data + alpha_idx_y + 4*dx*(l-1))[3];
- accu_x += K_X[y_carac][x_carac][k][l] * alpha;
- accu_y += K_X[x_carac][y_carac][l][k] * alpha;
- }
- }
- ss /= 255.0; // Correction for scale of pixel values
- N[X_3D] = -ss * FACTOR_X[y_carac][x_carac] * accu_x / dx;
- N[Y_3D] = -ss * FACTOR_X[x_carac][y_carac] * accu_y / dy;
- N[Z_3D] = 1.0;
- normalize_vector(N);
- //std::cout << "(" << N[X_3D] << ", " << N[Y_3D] << ", " << N[Z_3D] << ")" << std::endl;
-}
-
void convert_coord(gdouble &x, gdouble &y, gdouble &z, Geom::Affine const &trans) {
- Point p = Point(x, y);
+ Geom::Point p = Geom::Point(x, y);
p *= trans;
x = p[Geom::X];
y = p[Geom::Y];
diff --git a/src/display/nr-3dutils.h b/src/display/nr-3dutils.h
index e19651ac8..44cb371e6 100644
--- a/src/display/nr-3dutils.h
+++ b/src/display/nr-3dutils.h
@@ -28,12 +28,24 @@ namespace NR {
/**
* a type of 3 gdouble components vectors
*/
-typedef gdouble Fvector[3];
+struct Fvector {
+ Fvector() {
+ v[0] = v[1] = v[2] = 0.0;
+ }
+ Fvector(double x, double y, double z) {
+ v[0] = x;
+ v[1] = y;
+ v[2] = z;
+ }
+ double v[3];
+ double &operator[](unsigned i) { return v[i]; }
+ double operator[](unsigned i) const { return v[i]; }
+};
/**
* The eye vector
*/
-const static Fvector EYE_VECTOR = {0, 0, 1};
+const static Fvector EYE_VECTOR(0, 0, 1);
/**
* returns the euclidian norm of the vector v
@@ -69,22 +81,6 @@ gdouble scalar_product(const Fvector &a, const Fvector &b);
void normalized_sum(Fvector &r, const Fvector &a, const Fvector &b);
/**
- * Computes the unit suface normal vector of surface given by "in" at (i, j)
- * and store it into N. "in" is a (NRPixBlock *) in mode RGBA but only the alpha
- * channel is considered as a bump map. ss is the altitude when for the alpha
- * value 255. dx and dy are the deltas used to compute in our discrete setting
- *
- * \param N a reference to a Fvector in which we store the unit surface normal
- * \param ss the surface scale
- * \param in a NRPixBlock * whose alpha channel codes the surface
- * \param i the x coordinate of the point at which we compute the normal
- * \param j the y coordinate of the point at which we compute the normal
- * \param dx the delta used in the x coordinate
- * \param dy the delta used in the y coordinate
- */
-void compute_surface_normal(Fvector &N, gdouble ss, NRPixBlock *in, int i, int j, int dx, int dy);
-
-/**
* Applies the transformation matrix to (x, y, z). This function assumes that
* trans[0] = trans[3]. x and y are transformed according to trans, z is
* multiplied by trans[0].
diff --git a/src/display/nr-arena-glyphs.cpp b/src/display/nr-arena-glyphs.cpp
index a67812d8f..facb5e9c6 100644
--- a/src/display/nr-arena-glyphs.cpp
+++ b/src/display/nr-arena-glyphs.cpp
@@ -1,5 +1,3 @@
-#define __NR_ARENA_GLYPHS_C__
-
/*
* RGBA display list system for inkscape
*
@@ -16,22 +14,18 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
-#include <libnr/nr-blit.h>
-#include <libnr/nr-convert2geom.h>
+#include "libnr/nr-convert2geom.h"
#include <2geom/affine.h>
-#include "../style.h"
-#include "nr-arena.h"
-#include "nr-arena-glyphs.h"
+#include "style.h"
+#include "display/nr-arena.h"
+#include "display/nr-arena-glyphs.h"
#include <cairo.h>
-#include "inkscape-cairo.h"
-#include "display/grayscale.h"
-#include "sp-paint-server.h"
+#include "display/cairo-utils.h"
+#include "helper/geom.h"
#ifdef test_glyph_liv
#include "../display/canvas-bpath.h"
-#include <libnrtype/font-instance.h>
-#include <libnrtype/raster-glyph.h>
-#include <libnrtype/RasterFont.h>
+#include "libnrtype/font-instance.h"
// defined in nr-arena-shape.cpp
void nr_pixblock_render_shape_mask_or(NRPixBlock &m, Shape *theS);
@@ -46,7 +40,7 @@ static void nr_arena_glyphs_init(NRArenaGlyphs *glyphs);
static void nr_arena_glyphs_finalize(NRObject *object);
static guint nr_arena_glyphs_update(NRArenaItem *item, NRRectL *area, NRGC *gc, guint state, guint reset);
-static guint nr_arena_glyphs_clip(NRArenaItem *item, NRRectL *area, NRPixBlock *pb);
+static guint nr_arena_glyphs_clip(cairo_t *ct, NRArenaItem *item, NRRectL *area);
static NRArenaItem *nr_arena_glyphs_pick(NRArenaItem *item, Geom::Point p, double delta, unsigned int sticky);
static NRArenaItemClass *glyphs_parent_class;
@@ -88,13 +82,9 @@ nr_arena_glyphs_class_init(NRArenaGlyphsClass *klass)
static void
nr_arena_glyphs_init(NRArenaGlyphs *glyphs)
{
- glyphs->style = NULL;
glyphs->g_transform.setIdentity();
glyphs->font = NULL;
glyphs->glyph = 0;
-
- glyphs->rfont = NULL;
- glyphs->sfont = NULL;
glyphs->x = glyphs->y = 0.0;
}
@@ -103,132 +93,70 @@ nr_arena_glyphs_finalize(NRObject *object)
{
NRArenaGlyphs *glyphs = static_cast<NRArenaGlyphs *>(object);
- if (glyphs->rfont) {
- glyphs->rfont->Unref();
- glyphs->rfont=NULL;
- }
- if (glyphs->sfont) {
- glyphs->sfont->Unref();
- glyphs->sfont=NULL;
- }
-
if (glyphs->font) {
glyphs->font->Unref();
glyphs->font=NULL;
}
- if (glyphs->style) {
- sp_style_unref(glyphs->style);
- glyphs->style = NULL;
- }
-
((NRObjectClass *) glyphs_parent_class)->finalize(object);
}
static guint
nr_arena_glyphs_update(NRArenaItem *item, NRRectL */*area*/, NRGC *gc, guint /*state*/, guint /*reset*/)
{
- NRArenaGlyphs *glyphs;
- raster_font *rfont;
-
- glyphs = NR_ARENA_GLYPHS(item);
+ NRArenaGlyphs *glyphs = NR_ARENA_GLYPHS(item);
+ NRArenaGlyphsGroup *ggroup = NR_ARENA_GLYPHS_GROUP(item->parent);
- if (!glyphs->font || !glyphs->style)
+ if (!glyphs->font || !ggroup->style)
return NR_ARENA_ITEM_STATE_ALL;
- if ((glyphs->style->fill.isNone()) && (glyphs->style->stroke.isNone()))
+ if (ggroup->nrstyle.fill.type == NRStyle::PAINT_NONE && ggroup->nrstyle.stroke.type == NRStyle::PAINT_NONE)
return NR_ARENA_ITEM_STATE_ALL;
- NRRect bbox;
- bbox.x0 = bbox.y0 = NR_HUGE;
- bbox.x1 = bbox.y1 = -NR_HUGE;
-
- float const scale = gc->transform.descrim();
-
- if (!glyphs->style->fill.isNone()) {
- Geom::Affine t;
- t = glyphs->g_transform * gc->transform;
- glyphs->x = t[4];
- glyphs->y = t[5];
- t[4]=0;
- t[5]=0;
- rfont = glyphs->font->RasterFont(t, 0);
- if (glyphs->rfont) glyphs->rfont->Unref();
- glyphs->rfont = rfont;
-
- if (glyphs->style->stroke.isNone() || fabs(glyphs->style->stroke_width.computed * scale) <= 0.01) { // Optimization: do fill bbox only if there's no stroke
- NRRect narea;
- if ( glyphs->rfont ) glyphs->rfont->BBox(glyphs->glyph, &narea);
- bbox.x0 = narea.x0 + glyphs->x;
- bbox.y0 = narea.y0 + glyphs->y;
- bbox.x1 = narea.x1 + glyphs->x;
- bbox.y1 = narea.y1 + glyphs->y;
+ Geom::OptRect b;
+ Geom::Affine t = glyphs->g_transform * gc->transform;
+ glyphs->x = t[4];
+ glyphs->y = t[5];
+
+ b = bounds_exact_transformed(*glyphs->font->PathVector(glyphs->glyph), t);
+ if (b && ggroup->nrstyle.stroke.type != NRStyle::PAINT_NONE) {
+ float width, scale;
+ scale = gc->transform.descrim();
+ 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(width);
}
- }
-
- if (!glyphs->style->stroke.isNone()) {
- /* Build state data */
- Geom::Affine t;
- t = glyphs->g_transform * gc->transform;
- glyphs->x = t[4];
- glyphs->y = t[5];
- t[4]=0;
- t[5]=0;
-
- if ( fabs(glyphs->style->stroke_width.computed * scale) > 0.01 ) { // sinon c'est 0=oon veut pas de bord
- font_style nstyl;
- nstyl.transform = t;
- nstyl.stroke_width=MAX(0.125, glyphs->style->stroke_width.computed * scale);
- if ( glyphs->style->stroke_linecap.computed == SP_STROKE_LINECAP_BUTT ) nstyl.stroke_cap=butt_straight;
- if ( glyphs->style->stroke_linecap.computed == SP_STROKE_LINECAP_ROUND ) nstyl.stroke_cap=butt_round;
- if ( glyphs->style->stroke_linecap.computed == SP_STROKE_LINECAP_SQUARE ) nstyl.stroke_cap=butt_square;
- if ( glyphs->style->stroke_linejoin.computed == SP_STROKE_LINEJOIN_MITER ) nstyl.stroke_join=join_pointy;
- if ( glyphs->style->stroke_linejoin.computed == SP_STROKE_LINEJOIN_ROUND ) nstyl.stroke_join=join_round;
- if ( glyphs->style->stroke_linejoin.computed == SP_STROKE_LINEJOIN_BEVEL ) nstyl.stroke_join=join_straight;
- nstyl.stroke_miter_limit = glyphs->style->stroke_miterlimit.value;
- nstyl.nbDash=0;
- nstyl.dash_offset = 0;
- nstyl.dashes=NULL;
- if ( glyphs->style->stroke_dash.n_dash > 0 ) {
- nstyl.dash_offset = glyphs->style->stroke_dash.offset * scale;
- nstyl.nbDash=glyphs->style->stroke_dash.n_dash;
- nstyl.dashes=(double*)malloc(nstyl.nbDash*sizeof(double));
- for (int i = 0; i < nstyl.nbDash; i++) nstyl.dashes[i]= glyphs->style->stroke_dash.dash[i] * scale;
- }
- rfont = glyphs->font->RasterFont( nstyl);
- if ( nstyl.dashes ) free(nstyl.dashes);
- if (glyphs->sfont) glyphs->sfont->Unref();
- glyphs->sfont = rfont;
-
- NRRect narea;
- if ( glyphs->sfont ) glyphs->sfont->BBox(glyphs->glyph, &narea);
- narea.x0-=nstyl.stroke_width;
- narea.y0-=nstyl.stroke_width;
- narea.x1+=nstyl.stroke_width;
- narea.y1+=nstyl.stroke_width;
- bbox.x0 = narea.x0 + glyphs->x;
- bbox.y0 = narea.y0 + glyphs->y;
- bbox.x1 = narea.x1 + glyphs->x;
- bbox.y1 = narea.y1 + glyphs->y;
+ // those pesky miters, now
+ float miterMax = width * ggroup->nrstyle.miter_limit;
+ if ( miterMax > 0.01 ) {
+ // grunt mode. we should compute the various miters instead
+ // (one for each point on the curve)
+ b->expandBy(miterMax);
}
}
- if (nr_rect_d_test_empty(bbox)) return NR_ARENA_ITEM_STATE_ALL;
- item->bbox.x0 = static_cast<NR::ICoord>(floor(bbox.x0));
- item->bbox.y0 = static_cast<NR::ICoord>(floor(bbox.y0));
- item->bbox.x1 = static_cast<NR::ICoord>(ceil (bbox.x1));
- item->bbox.y1 = static_cast<NR::ICoord>(ceil (bbox.y1));
+ if (b) {
+ item->bbox.x0 = static_cast<NR::ICoord>(floor(b->left()));
+ item->bbox.y0 = static_cast<NR::ICoord>(floor(b->top()));
+ item->bbox.x1 = static_cast<NR::ICoord>(ceil (b->right()));
+ item->bbox.y1 = static_cast<NR::ICoord>(ceil (b->bottom()));
+ } else {
+ item->bbox.x0 = 0;
+ item->bbox.y0 = 0;
+ item->bbox.x1 = -1;
+ item->bbox.y1 = -1;
+ }
return NR_ARENA_ITEM_STATE_ALL;
}
static guint
-nr_arena_glyphs_clip(NRArenaItem *item, NRRectL */*area*/, NRPixBlock */*pb*/)
+nr_arena_glyphs_clip(cairo_t *ct, NRArenaItem *item, NRRectL */*area*/)
{
NRArenaGlyphs *glyphs;
glyphs = NR_ARENA_GLYPHS(item);
- if (!glyphs->font ) return item->state;
+ if (!glyphs->font) return item->state;
/* TODO : render to greyscale pixblock provided for clipping */
@@ -243,7 +171,6 @@ nr_arena_glyphs_pick(NRArenaItem *item, Geom::Point p, gdouble delta, unsigned i
glyphs = NR_ARENA_GLYPHS(item);
if (!glyphs->font ) return NULL;
- if (!glyphs->style) return NULL;
double const x = p[Geom::X];
double const y = p[Geom::Y];
@@ -275,53 +202,13 @@ nr_arena_glyphs_set_path(NRArenaGlyphs *glyphs, SPCurve */*curve*/, unsigned int
nr_arena_item_request_update(NR_ARENA_ITEM(glyphs), NR_ARENA_ITEM_STATE_ALL, FALSE);
}
-void
-nr_arena_glyphs_set_style(NRArenaGlyphs *glyphs, SPStyle *style)
-{
- nr_return_if_fail(glyphs != NULL);
- nr_return_if_fail(NR_IS_ARENA_GLYPHS(glyphs));
-
- if (style) sp_style_ref(style);
- if (glyphs->style) sp_style_unref(glyphs->style);
- glyphs->style = style;
-
- nr_arena_item_request_update(NR_ARENA_ITEM(glyphs), NR_ARENA_ITEM_STATE_ALL, FALSE);
-}
-
-static guint
-nr_arena_glyphs_fill_mask(NRArenaGlyphs *glyphs, NRRectL *area, NRPixBlock *m)
-{
- /* fixme: area == m->area, so merge these */
-
- NRArenaItem *item = NR_ARENA_ITEM(glyphs);
-
- if (glyphs->rfont && nr_rect_l_test_intersect_ptr(area, &item->bbox)) {
- raster_glyph *g = glyphs->rfont->GetGlyph(glyphs->glyph);
- if ( g ) g->Blit(Geom::Point(glyphs->x, glyphs->y), *m);
- }
-
- return item->state;
-}
-
-static guint
-nr_arena_glyphs_stroke_mask(NRArenaGlyphs *glyphs, NRRectL *area, NRPixBlock *m)
-{
- NRArenaItem *item = NR_ARENA_ITEM(glyphs);
- if (glyphs->sfont && nr_rect_l_test_intersect_ptr(area, &item->bbox)) {
- raster_glyph *g=glyphs->sfont->GetGlyph(glyphs->glyph);
- if ( g ) g->Blit(Geom::Point(glyphs->x, glyphs->y),*m);
- }
-
- return item->state;
-}
-
static void nr_arena_glyphs_group_class_init(NRArenaGlyphsGroupClass *klass);
static void nr_arena_glyphs_group_init(NRArenaGlyphsGroup *group);
static void nr_arena_glyphs_group_finalize(NRObject *object);
static guint nr_arena_glyphs_group_update(NRArenaItem *item, NRRectL *area, NRGC *gc, guint state, guint reset);
static unsigned int nr_arena_glyphs_group_render(cairo_t *ct, NRArenaItem *item, NRRectL *area, NRPixBlock *pb, unsigned int flags);
-static unsigned int nr_arena_glyphs_group_clip(NRArenaItem *item, NRRectL *area, NRPixBlock *pb);
+static unsigned int nr_arena_glyphs_group_clip(cairo_t *ct, NRArenaItem *item, NRRectL *area);
static NRArenaItem *nr_arena_glyphs_group_pick(NRArenaItem *item, Geom::Point p, gdouble delta, unsigned int sticky);
static NRArenaGroupClass *group_parent_class;
@@ -366,10 +253,7 @@ nr_arena_glyphs_group_init(NRArenaGlyphsGroup *group)
{
group->style = NULL;
group->paintbox.x0 = group->paintbox.y0 = 0.0F;
- group->paintbox.x1 = group->paintbox.y1 = 1.0F;
-
- group->fill_painter = NULL;
- group->stroke_painter = NULL;
+ group->paintbox.x1 = group->paintbox.y1 = -1.0F;
}
static void
@@ -377,16 +261,6 @@ nr_arena_glyphs_group_finalize(NRObject *object)
{
NRArenaGlyphsGroup *group=static_cast<NRArenaGlyphsGroup *>(object);
- if (group->fill_painter) {
- sp_painter_free(group->fill_painter);
- group->fill_painter = NULL;
- }
-
- if (group->stroke_painter) {
- sp_painter_free(group->stroke_painter);
- group->stroke_painter = NULL;
- }
-
if (group->style) {
sp_style_unref(group->style);
group->style = NULL;
@@ -400,34 +274,7 @@ nr_arena_glyphs_group_update(NRArenaItem *item, NRRectL *area, NRGC *gc, guint s
{
NRArenaGlyphsGroup *group = NR_ARENA_GLYPHS_GROUP(item);
- if (group->fill_painter) {
- sp_painter_free(group->fill_painter);
- group->fill_painter = NULL;
- }
-
- if (group->stroke_painter) {
- sp_painter_free(group->stroke_painter);
- group->stroke_painter = NULL;
- }
-
- item->render_opacity = TRUE;
- if (group->style->fill.isPaintserver()) {
- group->fill_painter = sp_paint_server_painter_new(SP_STYLE_FILL_SERVER(group->style),
- gc->transform, gc->parent->transform,
- &group->paintbox);
- item->render_opacity = FALSE;
- }
-
- if (group->style->stroke.isPaintserver()) {
- group->stroke_painter = sp_paint_server_painter_new(SP_STYLE_STROKE_SERVER(group->style),
- gc->transform, gc->parent->transform,
- &group->paintbox);
- item->render_opacity = FALSE;
- }
-
- if ( item->render_opacity == TRUE && !group->style->stroke.isNone() && !group->style->fill.isNone() ) {
- item->render_opacity=FALSE;
- }
+ group->nrstyle.update();
if (((NRArenaItemClass *) group_parent_class)->update)
return ((NRArenaItemClass *) group_parent_class)->update(item, area, gc, state, reset);
@@ -443,155 +290,81 @@ nr_arena_glyphs_group_render(cairo_t *ct, NRArenaItem *item, NRRectL *area, NRPi
NRArenaGroup *group = NR_ARENA_GROUP(item);
NRArenaGlyphsGroup *ggroup = NR_ARENA_GLYPHS_GROUP(item);
- SPStyle const *style = ggroup->style;
- guint ret = item->state;
- bool print_colors_preview = (item->arena->colorrendermode == Inkscape::COLORRENDERMODE_PRINT_COLORS_PREVIEW);
- bool grayscale = (item->arena->colorrendermode == Inkscape::COLORRENDERMODE_GRAYSCALE);
+ if (!ct) return item->state;
if (item->arena->rendermode == Inkscape::RENDERMODE_OUTLINE) {
- if (!ct)
- return item->state;
-
guint32 rgba = item->arena->outlinecolor;
- // FIXME: we use RGBA buffers but cairo writes BGRA (on i386), so we must cheat
- // by setting color channels in the "wrong" order
- cairo_set_source_rgba(ct, SP_RGBA32_B_F(rgba), SP_RGBA32_G_F(rgba), SP_RGBA32_R_F(rgba), SP_RGBA32_A_F(rgba));
+ ink_cairo_set_source_rgba32(ct, rgba);
cairo_set_tolerance(ct, 1.25); // low quality, but good enough for outline mode
+ NRRect temp(area->x0, area->y0, area->x1, area->y1);
+ Geom::OptRect area_2geom = temp.upgrade_2geom();
+
for (child = group->children; child != NULL; child = child->next) {
NRArenaGlyphs *g = NR_ARENA_GLYPHS(child);
Geom::PathVector const * pathv = g->font->PathVector(g->glyph);
+ Geom::Affine transform = g->g_transform * group->ctm;
cairo_new_path(ct);
- Geom::Affine transform = g->g_transform * group->ctm;
- feed_pathvector_to_cairo (ct, *pathv, transform, to_2geom((pb->area).upgrade()), false, 0);
+ ink_cairo_transform(ct, transform);
+ feed_pathvector_to_cairo (ct, *pathv);
cairo_fill(ct);
- pb->empty = FALSE;
}
- return ret;
+ return item->state;
}
+ // NOTE: this is very similar to nr-arena-shape.cpp; the only difference is path feeding
+ bool has_stroke, has_fill;
+ cairo_save(ct);
+ ink_cairo_transform(ct, ggroup->ctm);
- /* Fill */
- if (!style->fill.isNone() || item->arena->rendermode == Inkscape::RENDERMODE_OUTLINE) {
- NRPixBlock m;
- nr_pixblock_setup_fast(&m, NR_PIXBLOCK_MODE_A8, area->x0, area->y0, area->x1, area->y1, TRUE);
-
- // if memory allocation failed, abort
- if (m.size != NR_PIXBLOCK_SIZE_TINY && m.data.px == NULL) {
- nr_pixblock_release (&m);
- return (item->state);
- }
-
- m.visible_area = pb->visible_area;
-
- /* Render children fill mask */
- for (child = group->children; child != NULL; child = child->next) {
- ret = nr_arena_glyphs_fill_mask(NR_ARENA_GLYPHS(child), area, &m);
- if (!(ret & NR_ARENA_ITEM_STATE_RENDER)) {
- nr_pixblock_release(&m);
- return ret;
- }
- }
+ has_fill = ggroup->nrstyle.prepareFill(ct, &ggroup->paintbox);
+ has_stroke = ggroup->nrstyle.prepareStroke(ct, &ggroup->paintbox);
- /* Composite into buffer */
- if (style->fill.isPaintserver()) {
- if (ggroup->fill_painter) {
- nr_arena_render_paintserver_fill(pb, area, ggroup->fill_painter, SP_SCALE24_TO_FLOAT(style->fill_opacity.value), &m);
- }
- } else if (style->fill.isColor() || item->arena->rendermode == Inkscape::RENDERMODE_OUTLINE) {
- guint32 rgba;
- if (item->arena->rendermode == Inkscape::RENDERMODE_OUTLINE) {
- // In outline mode, render fill only, using outlinecolor
- rgba = item->arena->outlinecolor;
- } else if ( item->render_opacity ) {
- rgba = style->fill.value.color.toRGBA32( SP_SCALE24_TO_FLOAT(style->fill_opacity.value) *
- SP_SCALE24_TO_FLOAT(style->opacity.value) );
- } else {
- rgba = style->fill.value.color.toRGBA32( SP_SCALE24_TO_FLOAT(style->fill_opacity.value) );
- }
-
- if (print_colors_preview) {
- nr_arena_separate_color_plates(&rgba);
- } else if (grayscale) {
- rgba = Grayscale::process(rgba);
- }
-
- nr_blit_pixblock_mask_rgba32(pb, &m, rgba);
- pb->empty = FALSE;
- }
-
- nr_pixblock_release(&m);
- }
-
- /* Stroke */
- if (!style->stroke.isNone() && !(item->arena->rendermode == Inkscape::RENDERMODE_OUTLINE)) {
- NRPixBlock m;
- guint32 rgba;
- nr_pixblock_setup_fast(&m, NR_PIXBLOCK_MODE_A8, area->x0, area->y0, area->x1, area->y1, TRUE);
+ if (has_fill || has_stroke) {
+ for (NRArenaItem *child = ggroup->children; child != NULL; child = child->next) {
+ NRArenaGlyphs *g = NR_ARENA_GLYPHS(child);
+ Geom::PathVector const &pathv = *g->font->PathVector(g->glyph);
- // if memory allocation failed, abort
- if (m.size != NR_PIXBLOCK_SIZE_TINY && m.data.px == NULL) {
- nr_pixblock_release (&m);
- return (item->state);
+ cairo_save(ct);
+ ink_cairo_transform(ct, g->g_transform);
+ feed_pathvector_to_cairo(ct, pathv);
+ cairo_restore(ct);
}
- m.visible_area = pb->visible_area;
- /* Render children stroke mask */
- for (child = group->children; child != NULL; child = child->next) {
- ret = nr_arena_glyphs_stroke_mask(NR_ARENA_GLYPHS(child), area, &m);
- if (!(ret & NR_ARENA_ITEM_STATE_RENDER)) {
- nr_pixblock_release(&m);
- return ret;
- }
+ if (has_fill) {
+ ggroup->nrstyle.applyFill(ct);
+ cairo_fill_preserve(ct);
}
- /* Composite into buffer */
- if (style->stroke.isPaintserver()) {
- if (ggroup->stroke_painter) {
- nr_arena_render_paintserver_fill(pb, area, ggroup->stroke_painter, SP_SCALE24_TO_FLOAT(style->stroke_opacity.value), &m);
- }
- } else if (style->stroke.isColor()) {
- if ( item->render_opacity ) {
- rgba = style->stroke.value.color.toRGBA32( SP_SCALE24_TO_FLOAT(style->stroke_opacity.value) *
- SP_SCALE24_TO_FLOAT(style->opacity.value) );
- } else {
- rgba = style->stroke.value.color.toRGBA32( SP_SCALE24_TO_FLOAT(style->stroke_opacity.value) );
- }
-
- if (print_colors_preview) {
- nr_arena_separate_color_plates(&rgba);
- } else if (grayscale) {
- rgba = Grayscale::process(rgba);
- }
-
- nr_blit_pixblock_mask_rgba32(pb, &m, rgba);
- pb->empty = FALSE;
- } else {
- // nothing
+ if (has_stroke) {
+ ggroup->nrstyle.applyStroke(ct);
+ cairo_stroke_preserve(ct);
}
- nr_pixblock_release(&m);
- }
+ cairo_new_path(ct); // clear path
+ } // has fill or stroke pattern
+ cairo_restore(ct);
- return ret;
+ return item->state;
}
static unsigned int
-nr_arena_glyphs_group_clip(NRArenaItem *item, NRRectL *area, NRPixBlock *pb)
+nr_arena_glyphs_group_clip(cairo_t *ct, NRArenaItem *item, NRRectL *area)
{
- NRArenaGroup *group = NR_ARENA_GROUP(item);
+ //NRArenaGroup *group = NR_ARENA_GROUP(item);
guint ret = item->state;
/* Render children fill mask */
+ /*
for (NRArenaItem *child = group->children; child != NULL; child = child->next) {
ret = nr_arena_glyphs_fill_mask(NR_ARENA_GLYPHS(child), area, pb);
if (!(ret & NR_ARENA_ITEM_STATE_RENDER)) return ret;
- }
+ }*/
return ret;
}
@@ -638,7 +411,6 @@ nr_arena_glyphs_group_add_component(NRArenaGlyphsGroup *sg, font_instance *font,
nr_arena_item_append_child(NR_ARENA_ITEM(group), new_arena);
nr_arena_item_unref(new_arena);
nr_arena_glyphs_set_path(NR_ARENA_GLYPHS(new_arena), NULL, FALSE, font, glyph, &transform);
- nr_arena_glyphs_set_style(NR_ARENA_GLYPHS(new_arena), sg->style);
}
}
@@ -648,16 +420,11 @@ nr_arena_glyphs_group_set_style(NRArenaGlyphsGroup *sg, SPStyle *style)
nr_return_if_fail(sg != NULL);
nr_return_if_fail(NR_IS_ARENA_GLYPHS_GROUP(sg));
- NRArenaGroup *group = NR_ARENA_GROUP(sg);
-
if (style) sp_style_ref(style);
if (sg->style) sp_style_unref(sg->style);
sg->style = style;
- for (NRArenaItem *child = group->children; child != NULL; child = child->next) {
- nr_return_if_fail(NR_IS_ARENA_GLYPHS(child));
- nr_arena_glyphs_set_style(NR_ARENA_GLYPHS(child), sg->style);
- }
+ sg->nrstyle.set(style);
nr_arena_item_request_update(NR_ARENA_ITEM(sg), NR_ARENA_ITEM_STATE_ALL, FALSE);
}
@@ -675,9 +442,8 @@ nr_arena_glyphs_group_set_paintbox(NRArenaGlyphsGroup *gg, NRRect const *pbox)
gg->paintbox.x1 = pbox->x1;
gg->paintbox.y1 = pbox->y1;
} else {
- /* fixme: We kill warning, although not sure what to do here (Lauris) */
gg->paintbox.x0 = gg->paintbox.y0 = 0.0F;
- gg->paintbox.x1 = gg->paintbox.y1 = 256.0F;
+ gg->paintbox.x1 = gg->paintbox.y1 = -1.0F;
}
nr_arena_item_request_update(NR_ARENA_ITEM(gg), NR_ARENA_ITEM_STATE_ALL, FALSE);
diff --git a/src/display/nr-arena-glyphs.h b/src/display/nr-arena-glyphs.h
index b56a9f56c..c43095cb2 100644
--- a/src/display/nr-arena-glyphs.h
+++ b/src/display/nr-arena-glyphs.h
@@ -18,9 +18,10 @@
#define NR_IS_ARENA_GLYPHS(obj) (NR_CHECK_INSTANCE_TYPE ((obj), NR_TYPE_ARENA_GLYPHS))
#include "libnrtype/nrtype-forward.h"
-
+#include "display/display-forward.h"
#include "forward.h"
#include "display/nr-arena-item.h"
+#include "display/nr-style.h"
#define test_glyph_liv
@@ -32,22 +33,12 @@ NRType nr_arena_glyphs_get_type (void);
struct NRArenaGlyphs : public NRArenaItem {
/* Glyphs data */
- SPStyle *style;
Geom::Affine g_transform;
+
font_instance *font;
gint glyph;
-
- raster_font *rfont;
- raster_font *sfont;
float x, y;
-// Geom::Affine cached_tr;
-// Shape *cached_shp;
-// bool cached_shp_dirty;
-// bool cached_style_dirty;
-
-// Shape *stroke_shp;
-
static NRArenaGlyphs *create(NRArena *arena) {
NRArenaGlyphs *obj=reinterpret_cast<NRArenaGlyphs *>(nr_object_new(NR_TYPE_ARENA_GLYPHS));
obj->init(arena);
@@ -79,11 +70,8 @@ typedef struct NRArenaGlyphsGroupClass NRArenaGlyphsGroupClass;
NRType nr_arena_glyphs_group_get_type (void);
struct NRArenaGlyphsGroup : public NRArenaGroup {
- //SPStyle *style;
NRRect paintbox;
- /* State data */
- SPPainter *fill_painter;
- SPPainter *stroke_painter;
+ NRStyle nrstyle;
static NRArenaGlyphsGroup *create(NRArena *arena) {
NRArenaGlyphsGroup *obj=reinterpret_cast<NRArenaGlyphsGroup *>(nr_object_new(NR_TYPE_ARENA_GLYPHS_GROUP));
diff --git a/src/display/nr-arena-group.cpp b/src/display/nr-arena-group.cpp
index 6c6043b2c..97f92d02d 100644
--- a/src/display/nr-arena-group.cpp
+++ b/src/display/nr-arena-group.cpp
@@ -14,12 +14,10 @@
#include "display/nr-arena-group.h"
#include "display/nr-filter.h"
-#include "display/nr-filter-gaussian.h"
#include "display/nr-filter-types.h"
#include "style.h"
#include "sp-filter.h"
#include "sp-filter-reference.h"
-#include "sp-gaussian-blur.h"
#include "filters/blend.h"
#include "display/nr-filter-blend.h"
#include "helper/geom.h"
@@ -35,7 +33,7 @@ static void nr_arena_group_set_child_position (NRArenaItem *item, NRArenaItem *c
static unsigned int nr_arena_group_update (NRArenaItem *item, NRRectL *area, NRGC *gc, unsigned int state, unsigned int reset);
static unsigned int nr_arena_group_render (cairo_t *ct, NRArenaItem *item, NRRectL *area, NRPixBlock *pb, unsigned int flags);
-static unsigned int nr_arena_group_clip (NRArenaItem *item, NRRectL *area, NRPixBlock *pb);
+static unsigned int nr_arena_group_clip (cairo_t *ct, NRArenaItem *item, NRRectL *area);
static NRArenaItem *nr_arena_group_pick (NRArenaItem *item, Geom::Point p, double delta, unsigned int sticky);
static NRArenaItemClass *parent_class;
@@ -233,7 +231,7 @@ nr_arena_group_render (cairo_t *ct, NRArenaItem *item, NRRectL *area, NRPixBlock
}
static unsigned int
-nr_arena_group_clip (NRArenaItem *item, NRRectL *area, NRPixBlock *pb)
+nr_arena_group_clip (cairo_t *ct, NRArenaItem *item, NRRectL *area)
{
NRArenaGroup *group = NR_ARENA_GROUP (item);
@@ -241,7 +239,7 @@ nr_arena_group_clip (NRArenaItem *item, NRRectL *area, NRPixBlock *pb)
/* Just compose children into parent buffer */
for (NRArenaItem *child = group->children; child != NULL; child = child->next) {
- ret = nr_arena_item_invoke_clip (child, area, pb);
+ ret = nr_arena_item_invoke_clip (ct, child, area);
if (ret & NR_ARENA_ITEM_STATE_INVALID) break;
}
diff --git a/src/display/nr-arena-image.cpp b/src/display/nr-arena-image.cpp
index 6539ae4d2..cb1bc5849 100644
--- a/src/display/nr-arena-image.cpp
+++ b/src/display/nr-arena-image.cpp
@@ -12,20 +12,15 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include <libnr/nr-compose-transform.h>
#include <2geom/transforms.h>
-#include <libnr/nr-blit.h>
#include "../preferences.h"
#include "nr-arena-image.h"
#include "style.h"
+#include "display/cairo-utils.h"
#include "display/nr-arena.h"
#include "display/nr-filter.h"
-#include "display/nr-filter-gaussian.h"
#include "sp-filter.h"
#include "sp-filter-reference.h"
-#include "sp-gaussian-blur.h"
-#include "filters/blend.h"
-#include "display/nr-filter-blend.h"
int nr_arena_image_x_sample = 1;
int nr_arena_image_y_sample = 1;
@@ -42,6 +37,7 @@ static void nr_arena_image_finalize (NRObject *object);
static unsigned int nr_arena_image_update (NRArenaItem *item, NRRectL *area, NRGC *gc, unsigned int state, unsigned int reset);
static unsigned int nr_arena_image_render (cairo_t *ct, NRArenaItem *item, NRRectL *area, NRPixBlock *pb, unsigned int flags);
static NRArenaItem *nr_arena_image_pick (NRArenaItem *item, Geom::Point p, double delta, unsigned int sticky);
+static Geom::Rect nr_arena_image_rect (NRArenaImage *image);
static NRArenaItemClass *parent_class;
@@ -82,14 +78,11 @@ nr_arena_image_class_init (NRArenaImageClass *klass)
static void
nr_arena_image_init (NRArenaImage *image)
{
- image->px = NULL;
-
- image->pxw = image->pxh = image->pxrs = 0;
- image->x = image->y = 0.0;
- image->width = 256.0;
- image->height = 256.0;
-
- image->grid2px.setIdentity();
+ image->pixbuf = NULL;
+ image->ctm.setIdentity();
+ image->clipbox = Geom::Rect();
+ image->ox = image->oy = 0.0;
+ image->sx = image->sy = 1.0;
image->style = 0;
image->render_opacity = TRUE;
@@ -100,7 +93,12 @@ nr_arena_image_finalize (NRObject *object)
{
NRArenaImage *image = NR_ARENA_IMAGE (object);
- image->px = NULL;
+ if (image->pixbuf != NULL) {
+ g_object_unref(image->pixbuf);
+ cairo_surface_destroy(image->surface);
+ }
+ if (image->style)
+ sp_style_unref(image->style);
((NRObjectClass *) parent_class)->finalize (object);
}
@@ -108,54 +106,24 @@ nr_arena_image_finalize (NRObject *object)
static unsigned int
nr_arena_image_update( NRArenaItem *item, NRRectL */*area*/, NRGC *gc, unsigned int /*state*/, unsigned int /*reset*/ )
{
- Geom::Affine grid2px;
-
// clear old bbox
nr_arena_item_request_render(item);
NRArenaImage *image = NR_ARENA_IMAGE (item);
/* Copy affine */
- grid2px = gc->transform.inverse();
- double hscale, vscale; // todo: replace with Geom::Scale
- if (image->px) {
- hscale = image->pxw / image->width;
- vscale = image->pxh / image->height;
- } else {
- hscale = 1.0;
- vscale = 1.0;
- }
-
- image->grid2px[0] = grid2px[0] * hscale;
- image->grid2px[2] = grid2px[2] * hscale;
- image->grid2px[4] = grid2px[4] * hscale;
- image->grid2px[1] = grid2px[1] * vscale;
- image->grid2px[3] = grid2px[3] * vscale;
- image->grid2px[5] = grid2px[5] * vscale;
-
- image->grid2px[4] -= image->x * hscale;
- image->grid2px[5] -= image->y * vscale;
+ image->ctm = gc->transform;
/* Calculate bbox */
- if (image->px) {
+ if (image->pixbuf) {
NRRect bbox;
- bbox.x0 = image->x;
- bbox.y0 = image->y;
- bbox.x1 = image->x + image->width;
- bbox.y1 = image->y + image->height;
-
- image->c00 = (Geom::Point(bbox.x0, bbox.y0) * gc->transform);
- image->c01 = (Geom::Point(bbox.x0, bbox.y1) * gc->transform);
- image->c10 = (Geom::Point(bbox.x1, bbox.y0) * gc->transform);
- image->c11 = (Geom::Point(bbox.x1, bbox.y1) * gc->transform);
+ Geom::Rect r = nr_arena_image_rect(image) * gc->transform;
- nr_rect_d_matrix_transform (&bbox, &bbox, gc->transform);
-
- item->bbox.x0 = static_cast<NR::ICoord>(floor(bbox.x0)); // Floor gives the coordinate in which the point resides
- item->bbox.y0 = static_cast<NR::ICoord>(floor(bbox.y0));
- item->bbox.x1 = static_cast<NR::ICoord>(ceil (bbox.x1)); // Ceil gives the first coordinate beyond the point
- item->bbox.y1 = static_cast<NR::ICoord>(ceil (bbox.y1));
+ item->bbox.x0 = floor(r.left()); // Floor gives the coordinate in which the point resides
+ item->bbox.y0 = floor(r.top());
+ item->bbox.x1 = ceil(r.right()); // Ceil gives the first coordinate beyond the point
+ item->bbox.y1 = ceil(r.bottom());
} else {
item->bbox.x0 = (int) gc->transform[4];
item->bbox.y0 = (int) gc->transform[5];
@@ -166,78 +134,63 @@ nr_arena_image_update( NRArenaItem *item, NRRectL */*area*/, NRGC *gc, unsigned
return NR_ARENA_ITEM_STATE_ALL;
}
-#define FBITS 12
-#define b2i (image->grid2px)
-
static unsigned int
-nr_arena_image_render( cairo_t *ct, NRArenaItem *item, NRRectL */*area*/, NRPixBlock *pb, unsigned int /*flags*/ )
+nr_arena_image_render( cairo_t *ct, NRArenaItem *item, NRRectL *area, NRPixBlock *pb, unsigned int /*flags*/ )
{
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- nr_arena_image_x_sample = prefs->getInt("/options/bitmapoversample/value", 1);
- nr_arena_image_y_sample = nr_arena_image_x_sample;
+ if (!ct)
+ return item->state;
bool outline = (item->arena->rendermode == Inkscape::RENDERMODE_OUTLINE);
NRArenaImage *image = NR_ARENA_IMAGE (item);
- Geom::Affine d2s;
-
- d2s[0] = b2i[0];
- d2s[1] = b2i[1];
- d2s[2] = b2i[2];
- d2s[3] = b2i[3];
- d2s[4] = b2i[0] * pb->area.x0 + b2i[2] * pb->area.y0 + b2i[4];
- d2s[5] = b2i[1] * pb->area.x0 + b2i[3] * pb->area.y0 + b2i[5];
-
if (!outline) {
+ if (!image->pixbuf) return item->state;
- if (!image->px) return item->state;
+ // FIXME: at the moment gdk_cairo_set_source_pixbuf creates an ARGB copy
+ // of the pixbuf. Fix this in Cairo and/or GDK.
+ cairo_save(ct);
+ ink_cairo_transform(ct, image->ctm);
- guint32 Falpha = item->opacity;
- if (Falpha < 1) return item->state;
+ cairo_new_path(ct);
+ cairo_rectangle(ct, image->clipbox.left(), image->clipbox.top(),
+ image->clipbox.width(), image->clipbox.height());
+ cairo_clip(ct);
- unsigned char * dpx = NR_PIXBLOCK_PX (pb);
- int const drs = pb->rs;
- int const dw = pb->area.x1 - pb->area.x0;
- int const dh = pb->area.y1 - pb->area.y0;
+ cairo_translate(ct, image->ox, image->oy);
+ cairo_scale(ct, image->sx, image->sy);
- unsigned char * spx = image->px;
- int const srs = image->pxrs;
- int const sw = image->pxw;
- int const sh = image->pxh;
+ cairo_set_source_surface(ct, image->surface, 0, 0);
- if (pb->mode == NR_PIXBLOCK_MODE_R8G8B8) {
- /* fixme: This is not implemented yet (Lauris) */
- /* nr_R8G8B8_R8G8B8_R8G8B8A8_N_TRANSFORM (dpx, dw, dh, drs, spx, sw, sh, srs, d2s, Falpha, nr_arena_image_x_sample, nr_arena_image_y_sample); */
- } else if (pb->mode == NR_PIXBLOCK_MODE_R8G8B8A8P) {
- nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_N_TRANSFORM (dpx, dw, dh, drs, spx, sw, sh, srs, d2s, Falpha, nr_arena_image_x_sample, nr_arena_image_y_sample);
- } else if (pb->mode == NR_PIXBLOCK_MODE_R8G8B8A8N) {
- nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_N_TRANSFORM (dpx, dw, dh, drs, spx, sw, sh, srs, d2s, Falpha, nr_arena_image_x_sample, nr_arena_image_y_sample);
+ cairo_matrix_t tt;
+ Geom::Affine total;
+ cairo_get_matrix(ct, &tt);
+ ink_matrix_to_2geom(total, tt);
+
+ if (total.expansionX() > 1.0 || total.expansionY() > 1.0) {
+ cairo_pattern_t *p = cairo_get_source(ct);
+ cairo_pattern_set_filter(p, CAIRO_FILTER_NEAREST);
}
- pb->empty = FALSE;
+ cairo_paint_with_alpha(ct, ((double) item->opacity) / 255.0);
+ cairo_restore(ct);
} else { // outline; draw a rect instead
-
- if (!ct)
- return item->state;
-
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
guint32 rgba = prefs->getInt("/options/wireframecolors/images", 0xff0000ff);
- // FIXME: we use RGBA buffers but cairo writes BGRA (on i386), so we must cheat
- // by setting color channels in the "wrong" order
- cairo_set_source_rgba(ct, SP_RGBA32_B_F(rgba), SP_RGBA32_G_F(rgba), SP_RGBA32_R_F(rgba), SP_RGBA32_A_F(rgba));
- cairo_set_line_width(ct, 0.5);
+ cairo_save(ct);
+ ink_cairo_transform(ct, image->ctm);
+
cairo_new_path(ct);
- Geom::Point shift(pb->area.x0, pb->area.y0);
- Geom::Point c00 = image->c00 - shift;
- Geom::Point c01 = image->c01 - shift;
- Geom::Point c11 = image->c11 - shift;
- Geom::Point c10 = image->c10 - shift;
+ Geom::Rect r = nr_arena_image_rect (image);
+ Geom::Point c00 = r.corner(0);
+ Geom::Point c01 = r.corner(3);
+ Geom::Point c11 = r.corner(2);
+ Geom::Point c10 = r.corner(1);
cairo_move_to (ct, c00[Geom::X], c00[Geom::Y]);
-
// the box
cairo_line_to (ct, c10[Geom::X], c10[Geom::Y]);
cairo_line_to (ct, c11[Geom::X], c11[Geom::Y]);
@@ -247,12 +200,12 @@ nr_arena_image_render( cairo_t *ct, NRArenaItem *item, NRRectL */*area*/, NRPixB
cairo_line_to (ct, c11[Geom::X], c11[Geom::Y]);
cairo_move_to (ct, c10[Geom::X], c10[Geom::Y]);
cairo_line_to (ct, c01[Geom::X], c01[Geom::Y]);
+ cairo_restore(ct);
+ cairo_set_line_width(ct, 0.5);
+ ink_cairo_set_source_rgba32(ct, rgba);
cairo_stroke(ct);
-
- pb->empty = FALSE;
}
-
return item->state;
}
@@ -282,33 +235,47 @@ nr_arena_image_pick( NRArenaItem *item, Geom::Point p, double delta, unsigned in
{
NRArenaImage *image = NR_ARENA_IMAGE (item);
- if (!image->px) return NULL;
+ if (!image->pixbuf) return NULL;
bool outline = (item->arena->rendermode == Inkscape::RENDERMODE_OUTLINE);
if (outline) {
+ Geom::Rect r = nr_arena_image_rect (image);
+
+ Geom::Point c00 = r.corner(0);
+ Geom::Point c01 = r.corner(3);
+ Geom::Point c11 = r.corner(2);
+ Geom::Point c10 = r.corner(1);
// frame
- if (distance_to_segment (p, image->c00, image->c10) < delta) return item;
- if (distance_to_segment (p, image->c10, image->c11) < delta) return item;
- if (distance_to_segment (p, image->c11, image->c01) < delta) return item;
- if (distance_to_segment (p, image->c01, image->c00) < delta) return item;
+ if (distance_to_segment (p, c00, c10) < delta) return item;
+ if (distance_to_segment (p, c10, c11) < delta) return item;
+ if (distance_to_segment (p, c11, c01) < delta) return item;
+ if (distance_to_segment (p, c01, c00) < delta) return item;
// diagonals
- if (distance_to_segment (p, image->c00, image->c11) < delta) return item;
- if (distance_to_segment (p, image->c10, image->c01) < delta) return item;
+ if (distance_to_segment (p, c00, c11) < delta) return item;
+ if (distance_to_segment (p, c10, c01) < delta) return item;
return NULL;
} else {
- unsigned char *const pixels = image->px;
- int const width = image->pxw;
- int const height = image->pxh;
- int const rowstride = image->pxrs;
- Geom::Point tp = p * image->grid2px;
- int const ix = (int)(tp[Geom::X]);
- int const iy = (int)(tp[Geom::Y]);
+ unsigned char *const pixels = gdk_pixbuf_get_pixels(image->pixbuf);
+ int const width = gdk_pixbuf_get_width(image->pixbuf);
+ int const height = gdk_pixbuf_get_height(image->pixbuf);
+ int const rowstride = gdk_pixbuf_get_rowstride(image->pixbuf);
+
+ Geom::Point tp = p * image->ctm.inverse();
+ Geom::Rect r = nr_arena_image_rect(image);
+
+ if (!r.contains(tp))
+ return NULL;
+
+ double vw = width * image->sx;
+ double vh = height * image->sy;
+ int ix = floor((tp[Geom::X] - image->ox) / vw * width);
+ int iy = floor((tp[Geom::Y] - image->oy) / vh * height);
if ((ix < 0) || (iy < 0) || (ix >= width) || (iy >= height))
return NULL;
@@ -319,32 +286,79 @@ nr_arena_image_pick( NRArenaItem *item, Geom::Point p, double delta, unsigned in
}
}
+Geom::Rect
+nr_arena_image_rect (NRArenaImage *image)
+{
+ Geom::Rect r = image->clipbox;
+
+ if (image->pixbuf) {
+ double pw = gdk_pixbuf_get_width(image->pixbuf);
+ double ph = gdk_pixbuf_get_height(image->pixbuf);
+ double vw = pw * image->sx;
+ double vh = ph * image->sy;
+ Geom::Point p(image->ox, image->oy);
+ Geom::Point wh(vw, vh);
+ Geom::Rect view(p, p+wh);
+ Geom::OptRect res = Geom::intersect(r, view);
+ r = res ? *res : r;
+ }
+
+ return r;
+}
+
/* Utility */
void
-nr_arena_image_set_pixels (NRArenaImage *image, unsigned char const *px, unsigned int pxw, unsigned int pxh, unsigned int pxrs)
+nr_arena_image_set_argb32_pixbuf (NRArenaImage *image, GdkPixbuf *pb)
+{
+ nr_return_if_fail (image != NULL);
+ nr_return_if_fail (NR_IS_ARENA_IMAGE (image));
+
+ // when done in this order, it won't break if pb == image->pixbuf and the refcount is 1
+ if (pb != NULL) {
+ g_object_ref (pb);
+ }
+ if (image->pixbuf != NULL) {
+ g_object_unref(image->pixbuf);
+ cairo_surface_destroy(image->surface);
+ }
+ image->pixbuf = pb;
+ image->surface = pb ? ink_cairo_surface_create_for_argb32_pixbuf(pb) : NULL;
+
+ nr_arena_item_request_update (NR_ARENA_ITEM (image), NR_ARENA_ITEM_STATE_ALL, FALSE);
+}
+
+void
+nr_arena_image_set_clipbox (NRArenaImage *image, Geom::Rect const &clip)
+{
+ nr_return_if_fail (image != NULL);
+ nr_return_if_fail (NR_IS_ARENA_IMAGE (image));
+
+ image->clipbox = clip;
+
+ nr_arena_item_request_update (NR_ARENA_ITEM (image), NR_ARENA_ITEM_STATE_ALL, FALSE);
+}
+
+void
+nr_arena_image_set_origin (NRArenaImage *image, Geom::Point const &origin)
{
nr_return_if_fail (image != NULL);
nr_return_if_fail (NR_IS_ARENA_IMAGE (image));
- image->px = (unsigned char *) px;
- image->pxw = pxw;
- image->pxh = pxh;
- image->pxrs = pxrs;
+ image->ox = origin[Geom::X];
+ image->oy = origin[Geom::Y];
nr_arena_item_request_update (NR_ARENA_ITEM (image), NR_ARENA_ITEM_STATE_ALL, FALSE);
}
void
-nr_arena_image_set_geometry (NRArenaImage *image, double x, double y, double width, double height)
+nr_arena_image_set_scale (NRArenaImage *image, double sx, double sy)
{
nr_return_if_fail (image != NULL);
nr_return_if_fail (NR_IS_ARENA_IMAGE (image));
- image->x = x;
- image->y = y;
- image->width = width;
- image->height = height;
+ image->sx = sx;
+ image->sy = sy;
nr_arena_item_request_update (NR_ARENA_ITEM (image), NR_ARENA_ITEM_STATE_ALL, FALSE);
}
diff --git a/src/display/nr-arena-image.h b/src/display/nr-arena-image.h
index c8d1525dc..6fa9223dd 100644
--- a/src/display/nr-arena-image.h
+++ b/src/display/nr-arena-image.h
@@ -13,28 +13,25 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <2geom/rect.h>
+#include "nr-arena-item.h"
+#include "style.h"
+
#define NR_TYPE_ARENA_IMAGE (nr_arena_image_get_type ())
#define NR_ARENA_IMAGE(o) (NR_CHECK_INSTANCE_CAST ((o), NR_TYPE_ARENA_IMAGE, NRArenaImage))
#define NR_IS_ARENA_IMAGE(o) (NR_CHECK_INSTANCE_TYPE ((o), NR_TYPE_ARENA_IMAGE))
-#include "nr-arena-item.h"
-#include "style.h"
-
NRType nr_arena_image_get_type (void);
struct NRArenaImage : public NRArenaItem {
- unsigned char *px;
- unsigned int pxw;
- unsigned int pxh;
- unsigned int pxrs;
-
- double x, y;
- double width, height;
+ GdkPixbuf *pixbuf;
+ cairo_surface_t *surface;
- Geom::Point c00, c01, c11, c10; // all 4 corners of the image, for outline mode rect
-
- /* From GRID to PIXELS */
- Geom::Affine grid2px;
+ Geom::Affine ctm;
+ Geom::Rect clipbox;
+ double ox, oy;
+ double sx, sy;
SPStyle *style;
@@ -49,10 +46,11 @@ struct NRArenaImageClass {
NRArenaItemClass parent_class;
};
-void nr_arena_image_set_pixels (NRArenaImage *image, unsigned char const *px, unsigned int pxw, unsigned int pxh, unsigned int pxrs);
-void nr_arena_image_set_geometry (NRArenaImage *image, double x, double y, double width, double height);
+void nr_arena_image_set_argb32_pixbuf (NRArenaImage *image, GdkPixbuf *pb);
void nr_arena_image_set_style (NRArenaImage *image, SPStyle *style);
-
+void nr_arena_image_set_clipbox (NRArenaImage *image, Geom::Rect const &clip);
+void nr_arena_image_set_origin (NRArenaImage *image, Geom::Point const &origin);
+void nr_arena_image_set_scale (NRArenaImage *image, double sx, double sy);
#endif
diff --git a/src/display/nr-arena-item.cpp b/src/display/nr-arena-item.cpp
index 6a5b7b5ba..8787c1033 100644
--- a/src/display/nr-arena-item.cpp
+++ b/src/display/nr-arena-item.cpp
@@ -17,9 +17,10 @@
#include <cstring>
#include <string>
+#include <cairomm/cairomm.h>
-#include <libnr/nr-blit.h>
-#include <libnr/nr-pixops.h>
+#include "display/cairo-utils.h"
+#include "display/cairo-templates.h"
#include "nr-arena.h"
#include "nr-arena-item.h"
#include "gc-core.h"
@@ -83,6 +84,7 @@ nr_arena_item_init (NRArenaItem *item)
memset (&item->bbox, 0, sizeof (item->bbox));
memset (&item->drawbox, 0, sizeof (item->drawbox));
item->transform = NULL;
+ item->ctm.setIdentity();
item->opacity = 255;
item->render_opacity = FALSE;
@@ -104,6 +106,11 @@ nr_arena_item_private_finalize (NRObject *object)
item->px = NULL;
item->transform = NULL;
+ if (item->clip)
+ nr_arena_item_detach(item, item->clip);
+ if (item->mask)
+ nr_arena_item_detach(item, item->mask);
+
((NRObjectClass *) (parent_class))->finalize (object);
}
@@ -258,12 +265,15 @@ nr_arena_item_invoke_update (NRArenaItem *item, NRRectL *area, NRGC *gc,
if (item->state & NR_ARENA_ITEM_STATE_INVALID)
return item->state;
- // get a copy of bbox
- memcpy(&item->drawbox, &item->bbox, sizeof(item->bbox));
-
/* Enlarge the drawbox to contain filter effects */
- if (item->filter && filter) {
- item->filter->bbox_enlarge (item->drawbox);
+ if (item->filter && filter && item->item_bbox) {
+ item->drawbox.x0 = item->item_bbox->min()[Geom::X];
+ item->drawbox.y0 = item->item_bbox->min()[Geom::Y];
+ item->drawbox.x1 = item->item_bbox->max()[Geom::X];
+ item->drawbox.y1 = item->item_bbox->max()[Geom::Y];
+ item->filter->compute_drawbox (item, item->drawbox);
+ } else {
+ memcpy(&item->drawbox, &item->bbox, sizeof(item->bbox));
}
// fixme: to fix the display glitches, in outline mode bbox must be a combination of
// full item bbox and its clip and mask (after we have the API to get these)
@@ -301,11 +311,16 @@ nr_arena_item_invoke_update (NRArenaItem *item, NRRectL *area, NRGC *gc,
return item->state;
}
-/**
- * Render item to pixblock.
- *
- * \return Has NR_ARENA_ITEM_STATE_RENDER set on success.
- */
+struct MaskLuminanceToAlpha {
+ guint32 operator()(guint32 in) {
+ EXTRACT_ARGB32(in, a, r, g, b)
+ // the operation of unpremul -> luminance-to-alpha -> multiply by alpha
+ // is equivalent to luminance-to-alpha on premultiplied color values
+ // original computation in double: r*0.2125 + g*0.7154 + b*0.0721
+ guint32 ao = r*109 + g*366 + b*37; // coeffs add up to 512
+ return ((ao + 256) << 15) & 0xff000000; // equivalent to ((ao + 256) / 512) << 24
+ }
+};
unsigned int
nr_arena_item_invoke_render (cairo_t *ct, NRArenaItem *item, NRRectL const *area,
@@ -314,13 +329,13 @@ nr_arena_item_invoke_render (cairo_t *ct, NRArenaItem *item, NRRectL const *area
bool outline = (item->arena->rendermode == Inkscape::RENDERMODE_OUTLINE);
bool filter = (item->arena->rendermode != Inkscape::RENDERMODE_OUTLINE &&
item->arena->rendermode != Inkscape::RENDERMODE_NO_FILTERS);
- bool print_colors = (item->arena->colorrendermode == Inkscape::COLORRENDERMODE_PRINT_COLORS_PREVIEW);
nr_return_val_if_fail (item != NULL, NR_ARENA_ITEM_STATE_INVALID);
nr_return_val_if_fail (NR_IS_ARENA_ITEM (item),
NR_ARENA_ITEM_STATE_INVALID);
nr_return_val_if_fail (item->state & NR_ARENA_ITEM_STATE_BBOX,
item->state);
+ if (!ct) return item->state;
#ifdef NR_ARENA_ITEM_VERBOSE
g_message ("Invoke render %p on %p: %d %d - %d %d, %d %d - %d %d", item, pb,
@@ -334,6 +349,8 @@ nr_arena_item_invoke_render (cairo_t *ct, NRArenaItem *item, NRRectL const *area
if (!item->visible)
return item->state | NR_ARENA_ITEM_STATE_RENDER;
+ // carea is the bounding box for intermediate rendering.
+ // NOTE: carea might be larger than area, because of filter effects.
NRRectL carea;
nr_rect_l_intersect (&carea, area, &item->drawbox);
if (nr_rect_l_test_empty(carea))
@@ -344,272 +361,152 @@ nr_arena_item_invoke_render (cairo_t *ct, NRArenaItem *item, NRRectL const *area
}
if (outline) {
- // No caching in outline mode for now; investigate if it really gives any advantage with cairo.
- // Also no attempts to clip anything; just render everything: item, clip, mask
- // First, render the object itself
- unsigned int state = NR_ARENA_ITEM_VIRTUAL (item, render) (ct, item, &carea, pb, flags);
- if (state & NR_ARENA_ITEM_STATE_INVALID) {
- /* Clean up and return error */
- item->state |= NR_ARENA_ITEM_STATE_INVALID;
- return item->state;
- }
-
- // render clip and mask, if any
- guint32 saved_rgba = item->arena->outlinecolor; // save current outline color
- // render clippath as an object, using a different color
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- if (item->clip) {
- item->arena->outlinecolor = prefs->getInt("/options/wireframecolors/clips", 0x00ff00ff); // green clips
- NR_ARENA_ITEM_VIRTUAL (item->clip, render) (ct, item->clip, &carea, pb, flags);
- }
- // render mask as an object, using a different color
- if (item->mask) {
- item->arena->outlinecolor = prefs->getInt("/options/wireframecolors/masks", 0x0000ffff); // blue masks
- NR_ARENA_ITEM_VIRTUAL (item->mask, render) (ct, item->mask, &carea, pb, flags);
- }
- item->arena->outlinecolor = saved_rgba; // restore outline color
+ // No caching in outline mode for now; investigate if it really gives any advantage with cairo.
+ // Also no attempts to clip anything; just render everything: item, clip, mask
+ // First, render the object itself
+ unsigned int state = NR_ARENA_ITEM_VIRTUAL (item, render) (ct, item, &carea, pb, flags);
+ if (state & NR_ARENA_ITEM_STATE_INVALID) {
+ /* Clean up and return error */
+ item->state |= NR_ARENA_ITEM_STATE_INVALID;
+ return item->state;
+ }
- return item->state | NR_ARENA_ITEM_STATE_RENDER;
- }
+ // render clip and mask, if any
+ guint32 saved_rgba = item->arena->outlinecolor; // save current outline color
+ // render clippath as an object, using a different color
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ if (item->clip) {
+ item->arena->outlinecolor = prefs->getInt("/options/wireframecolors/clips", 0x00ff00ff); // green clips
+ NR_ARENA_ITEM_VIRTUAL (item->clip, render) (ct, item->clip, &carea, pb, flags);
+ }
+ // render mask as an object, using a different color
+ if (item->mask) {
+ item->arena->outlinecolor = prefs->getInt("/options/wireframecolors/masks", 0x0000ffff); // blue masks
+ NR_ARENA_ITEM_VIRTUAL (item->mask, render) (ct, item->mask, &carea, pb, flags);
+ }
+ item->arena->outlinecolor = saved_rgba; // restore outline color
- NRPixBlock cpb;
- if (item->px) {
- /* Has cache pixblock, render this and return */
- nr_pixblock_setup_extern (&cpb, NR_PIXBLOCK_MODE_R8G8B8A8P,
- /* fixme: This probably cannot overflow, because we render only if visible */
- /* fixme: and pixel cache is there only for small items */
- /* fixme: But this still needs extra check (Lauris) */
- item->drawbox.x0, item->drawbox.y0,
- item->drawbox.x1, item->drawbox.y1,
- item->px,
- 4 * (item->drawbox.x1 - item->drawbox.x0), FALSE,
- FALSE);
- nr_blit_pixblock_pixblock (pb, &cpb);
- nr_pixblock_release (&cpb);
- pb->empty = FALSE;
return item->state | NR_ARENA_ITEM_STATE_RENDER;
}
- NRPixBlock *dpb = pb;
-
- /* Setup cache if we can */
- if ((!(flags & NR_ARENA_ITEM_RENDER_NO_CACHE)) &&
- (carea.x0 <= item->drawbox.x0) && (carea.y0 <= item->drawbox.y0) &&
- (carea.x1 >= item->drawbox.x1) && (carea.y1 >= item->drawbox.y1) &&
- (((item->drawbox.x1 - item->drawbox.x0) * (item->drawbox.y1 -
- item->drawbox.y0)) <= 4096)) {
- // Item drawbox is fully in renderable area and size is acceptable
- carea.x0 = item->drawbox.x0;
- carea.y0 = item->drawbox.y0;
- carea.x1 = item->drawbox.x1;
- carea.y1 = item->drawbox.y1;
- item->px =
- new (GC::ATOMIC) unsigned char[4 * (carea.x1 - carea.x0) *
- (carea.y1 - carea.y0)];
- nr_pixblock_setup_extern (&cpb, NR_PIXBLOCK_MODE_R8G8B8A8P, carea.x0,
- carea.y0, carea.x1, carea.y1, item->px,
- 4 * (carea.x1 - carea.x0), TRUE, TRUE);
- cpb.visible_area = pb->visible_area;
- dpb = &cpb;
- // Set nocache flag for downstream rendering
- flags |= NR_ARENA_ITEM_RENDER_NO_CACHE;
- }
+ using namespace Inkscape;
- /* Determine, whether we need temporary buffer */
- if (item->clip || item->mask
- || ((item->opacity != 255) && !item->render_opacity)
- || (item->filter && filter) || item->background_new) {
-
- /* Setup and render item buffer */
- NRPixBlock ipb;
- nr_pixblock_setup_fast (&ipb, NR_PIXBLOCK_MODE_R8G8B8A8P,
- carea.x0, carea.y0, carea.x1, carea.y1,
- TRUE);
-
- // if memory allocation failed, abort render
- if (ipb.size != NR_PIXBLOCK_SIZE_TINY && ipb.data.px == NULL) {
- nr_pixblock_release (&ipb);
- return (item->state);
- }
+ // clipping and masks
+ unsigned int state;
- /* If background access is used, save the pixblock address.
- * This address is set to NULL at the end of this block */
- if (item->background_new) {
- item->background_pb = &ipb;
- }
+ cairo_t *this_ct = ct;
+ NRRectL *this_area = const_cast<NRRectL*>(area);
- ipb.visible_area = pb->visible_area;
- if (item->filter && filter) {
- item->filter->area_enlarge (ipb.visible_area, item);
- }
+ bool needs_intermediate_rendering = false;
+ bool &nir = needs_intermediate_rendering;
+ bool needs_opacity = (item->opacity != 255 && !item->render_opacity);
+
+ // this item needs an intermediate rendering if:
+ nir |= (item->mask != NULL); // 1. it has a mask
+ nir |= (item->filter != NULL && filter); // 2. it has a filter
+ nir |= needs_opacity; // 3. it is non-opaque
+
+ double opacity = static_cast<double>(item->opacity) / 255.0;
+
+ if (needs_intermediate_rendering) {
+ cairo_surface_t *intermediate = cairo_surface_create_similar(
+ cairo_get_target(ct), CAIRO_CONTENT_COLOR_ALPHA,
+ carea.x1 - carea.x0, carea.y1 - carea.y0);
+ this_ct = cairo_create(intermediate);
+ cairo_translate(this_ct, -carea.x0, -carea.y0);
+ this_area = &carea;
+ cairo_surface_destroy(intermediate); // the surface will be held in memory by this_ct
+ } else {
+ cairo_reference(this_ct);
+ }
+
+ // The pipeline needs to be different for filters.
+ // First we render the item into an intermediate surface. Then the filter rotates
+ // the surface to user coordinates (if necessary) and runs the rendering.
+ // Once that's done we retrieve the result, rotating it back to screen coords.
+ // Clipping and masking happens after the filter result is ready.
+ if (item->filter && filter) {
+ }
+
+ Cairo::Context cct(this_ct, true);
+ Cairo::Context base_ct(ct);
+ Cairo::RefPtr<Cairo::Pattern> mask;
+ CairoSave clipsave(ct); // RAII for save / restore
+ CairoGroup maskgroup(this_ct); // RAII for push_group / pop_group
+ CairoGroup drawgroup(this_ct);
+ CairoGroup maskopacitygroup(this_ct);
- unsigned int state = NR_ARENA_ITEM_VIRTUAL (item, render) (ct, item, &carea, &ipb, flags);
+ // always clip the base context, not the one on the intermediate surface
+ // this is because filters must be done before clipping
+ if (item->clip) {
+ clipsave.save();
+ state = nr_arena_item_invoke_clip(ct, item->clip, const_cast<NRRectL*>(area));
if (state & NR_ARENA_ITEM_STATE_INVALID) {
- /* Clean up and return error */
- nr_pixblock_release (&ipb);
- if (dpb != pb)
- nr_pixblock_release (dpb);
item->state |= NR_ARENA_ITEM_STATE_INVALID;
return item->state;
}
- ipb.empty = FALSE;
-
- /* Run filtering, if a filter is set for this object */
- if (item->filter && filter) {
- item->filter->render (item, &ipb);
- }
+ base_ct.clip();
+ }
- if (item->clip || item->mask) {
- /* Setup mask pixblock */
- NRPixBlock mpb;
- nr_pixblock_setup_fast (&mpb, NR_PIXBLOCK_MODE_A8, carea.x0,
- carea.y0, carea.x1, carea.y1, TRUE);
-
- if (mpb.data.px != NULL) { // if memory allocation was successful
-
- mpb.visible_area = pb->visible_area;
- /* Do clip if needed */
- if (item->clip) {
- state = nr_arena_item_invoke_clip (item->clip, &carea, &mpb);
- if (state & NR_ARENA_ITEM_STATE_INVALID) {
- /* Clean up and return error */
- nr_pixblock_release (&mpb);
- nr_pixblock_release (&ipb);
- if (dpb != pb)
- nr_pixblock_release (dpb);
- item->state |= NR_ARENA_ITEM_STATE_INVALID;
- return item->state;
- }
- mpb.empty = FALSE;
- }
- /* Do mask if needed */
- if (item->mask) {
- NRPixBlock tpb;
- /* Set up yet another temporary pixblock */
- nr_pixblock_setup_fast (&tpb, NR_PIXBLOCK_MODE_R8G8B8A8N,
- carea.x0, carea.y0, carea.x1,
- carea.y1, TRUE);
-
- if (tpb.data.px != NULL) { // if memory allocation was successful
-
- tpb.visible_area = pb->visible_area;
- unsigned int state = NR_ARENA_ITEM_VIRTUAL (item->mask, render) (ct, item->mask, &carea, &tpb, flags);
- if (state & NR_ARENA_ITEM_STATE_INVALID) {
- /* Clean up and return error */
- nr_pixblock_release (&tpb);
- nr_pixblock_release (&mpb);
- nr_pixblock_release (&ipb);
- if (dpb != pb)
- nr_pixblock_release (dpb);
- item->state |= NR_ARENA_ITEM_STATE_INVALID;
- return item->state;
- }
- /* Composite with clip */
- if (item->clip) {
- int x, y;
- for (y = carea.y0; y < carea.y1; y++) {
- unsigned char *s, *d;
- s = NR_PIXBLOCK_PX (&tpb) + (y -
- carea.y0) * tpb.rs;
- d = NR_PIXBLOCK_PX (&mpb) + (y -
- carea.y0) * mpb.rs;
- for (x = carea.x0; x < carea.x1; x++) {
- // See below for calculation
- unsigned int m;
- m = NR_PREMUL_112 ( (NR_PREMUL_112 (s[0], 54) +
- NR_PREMUL_112 (s[1], 183) +
- NR_PREMUL_112 (s[2], 19) ) >> 8, s[3]);
- d[0] = FAST_DIV_ROUND < 255 * 255 > ( NR_PREMUL_123 (d[0], m));
- s += 4;
- d += 1;
- }
- }
- } else {
- int x, y;
- for (y = carea.y0; y < carea.y1; y++) {
- unsigned char *s, *d;
- s = NR_PIXBLOCK_PX (&tpb) + (y -
- carea.y0) * tpb.rs;
- d = NR_PIXBLOCK_PX (&mpb) + (y -
- carea.y0) * mpb.rs;
- for (x = carea.x0; x < carea.x1; x++) {
- unsigned int m;
- // m = NR_PREMUL_112 (s[0] + s[1] + s[2], s[3]);
- // d[0] = FAST_DIV_ROUND < 3 * 255 > (m);
- // Must use luminance to alpha from feColorMatrix.
- // This is an approximation, optimized(?) for speed.
- // 0.2125 * 256 = 54.4000
- // 0.7154 * 256 = 183.1424
- // 0.0721 * 256 = 18.4576
- m = NR_PREMUL_112 ( (NR_PREMUL_112 (s[0], 54) +
- NR_PREMUL_112 (s[1], 183) +
- NR_PREMUL_112 (s[2], 19) ) >> 8, s[3]);
- d[0] = FAST_DIV_ROUND < 255 > (m);
- s += 4;
- d += 1;
- }
- }
- mpb.empty = FALSE;
- }
- }
- nr_pixblock_release (&tpb);
- }
- /* Multiply with opacity if needed */
- if ((item->opacity != 255) && !item->render_opacity
- ) {
- int x, y;
- unsigned int a;
- a = item->opacity;
- for (y = carea.y0; y < carea.y1; y++) {
- unsigned char *d;
- d = NR_PIXBLOCK_PX (&mpb) + (y - carea.y0) * mpb.rs;
- for (x = carea.x0; x < carea.x1; x++) {
- d[0] = NR_PREMUL_111 (d[0], a);
- d += 1;
- }
- }
- }
- /* Compose rendering pixblock int destination */
- nr_blit_pixblock_pixblock_mask (dpb, &ipb, &mpb);
- }
- nr_pixblock_release (&mpb);
- } else {
- if (item->render_opacity) { // opacity was already rendered in, just copy to dpb here
- nr_blit_pixblock_pixblock(dpb, &ipb);
- } else { // copy while multiplying by opacity
- nr_blit_pixblock_pixblock_alpha (dpb, &ipb, item->opacity);
- }
+ // render mask on the intermediate context and store it
+ if (item->mask) {
+ maskgroup.push_with_content(CAIRO_CONTENT_COLOR_ALPHA);
+ // handle opacity of a masked object by composing it with the mask
+ if (needs_opacity) {
+ maskopacitygroup.push();
}
- nr_pixblock_release (&ipb);
- dpb->empty = FALSE;
- /* This pointer wouldn't be valid outside this block, so clear it */
- item->background_pb = NULL;
- } else {
- /* Just render */
- unsigned int state = NR_ARENA_ITEM_VIRTUAL (item, render) (ct, item, &carea, dpb, flags);
+ state = NR_ARENA_ITEM_VIRTUAL (item->mask, render) (this_ct, item->mask, this_area, pb, flags);
if (state & NR_ARENA_ITEM_STATE_INVALID) {
- /* Clean up and return error */
- if (dpb != pb)
- nr_pixblock_release (dpb);
item->state |= NR_ARENA_ITEM_STATE_INVALID;
return item->state;
}
- dpb->empty = FALSE;
+ if (needs_opacity) {
+ maskopacitygroup.pop_to_source();
+ cct.paint_with_alpha(opacity);
+ }
+ mask = maskgroup.popmm();
+ // convert luminance to alpha
+ cairo_pattern_t *p = mask->cobj();
+ cairo_surface_t *s;
+ cairo_pattern_get_surface(p, &s);
+ ink_cairo_surface_filter(s, s, MaskLuminanceToAlpha());
}
- if (dpb != pb) {
- /* Have to blit from cache */
- nr_blit_pixblock_pixblock (pb, dpb);
- nr_pixblock_release (dpb);
- pb->empty = FALSE;
- item->state |= NR_ARENA_ITEM_STATE_IMAGE;
+ // render the object (possibly to the intermediate surface)
+ state = NR_ARENA_ITEM_VIRTUAL (item, render) (this_ct, item, this_area, pb, flags);
+ if (state & NR_ARENA_ITEM_STATE_INVALID) {
+ /* Clean up and return error */
+ item->state |= NR_ARENA_ITEM_STATE_INVALID;
+ return item->state;
+ }
+
+ // apply filter
+ if (item->filter && filter) {
+ item->filter->render(item, ct, area, this_ct, &carea);
+ }
+
+ if (needs_intermediate_rendering) {
+ cairo_surface_t *intermediate = cairo_get_target(this_ct);
+ cairo_set_source_surface(ct, intermediate, carea.x0, carea.y0);
+ if (mask) {
+ cairo_mask(ct, mask->cobj());
+ // opacity of masked objects is handled by premultiplying the mask
+ } else {
+ // opacity of non-masked objects must be rendered explicitly
+ if (needs_opacity) {
+ cairo_paint_with_alpha(ct, opacity);
+ } else {
+ cairo_paint(ct);
+ }
+ }
+ cairo_set_source_rgba(ct,0,0,0,0);
}
return item->state | NR_ARENA_ITEM_STATE_RENDER;
}
unsigned int
-nr_arena_item_invoke_clip (NRArenaItem *item, NRRectL *area, NRPixBlock *pb)
+nr_arena_item_invoke_clip (cairo_t *ct, NRArenaItem *item, NRRectL *area)
{
nr_return_val_if_fail (item != NULL, NR_ARENA_ITEM_STATE_INVALID);
nr_return_val_if_fail (NR_IS_ARENA_ITEM (item),
@@ -618,12 +515,12 @@ nr_arena_item_invoke_clip (NRArenaItem *item, NRRectL *area, NRPixBlock *pb)
* NR_ARENA_ITEM_STATE_CLIP (and showed a warning on the console);
* anyone know why we stopped doing so?
*/
- nr_return_val_if_fail ((pb->area.x1 - pb->area.x0) >=
+ /*nr_return_val_if_fail ((pb->area.x1 - pb->area.x0) >=
(area->x1 - area->x0),
NR_ARENA_ITEM_STATE_INVALID);
nr_return_val_if_fail ((pb->area.y1 - pb->area.y0) >=
(area->y1 - area->y0),
- NR_ARENA_ITEM_STATE_INVALID);
+ NR_ARENA_ITEM_STATE_INVALID);*/
#ifdef NR_ARENA_ITEM_VERBOSE
printf ("Invoke clip by %p: %d %d - %d %d, item bbox %d %d - %d %d\n",
@@ -635,7 +532,7 @@ nr_arena_item_invoke_clip (NRArenaItem *item, NRRectL *area, NRPixBlock *pb)
/* Need render that item */
if (((NRArenaItemClass *) NR_OBJECT_GET_CLASS (item))->clip) {
return ((NRArenaItemClass *) NR_OBJECT_GET_CLASS (item))->
- clip (item, area, pb);
+ clip (ct, item, area);
}
}
@@ -663,7 +560,8 @@ nr_arena_item_invoke_pick (NRArenaItem *item, Geom::Point p, double delta,
if (((x + delta) >= item->bbox.x0) &&
((x - delta) < item->bbox.x1) &&
- ((y + delta) >= item->bbox.y0) && ((y - delta) < item->bbox.y1)) {
+ ((y + delta) >= item->bbox.y0) && ((y - delta) < item->bbox.y1))
+ {
if (((NRArenaItemClass *) NR_OBJECT_GET_CLASS (item))->pick)
return ((NRArenaItemClass *) NR_OBJECT_GET_CLASS (item))->
pick (item, p, delta, sticky);
@@ -872,13 +770,7 @@ nr_arena_item_set_item_bbox (NRArenaItem *item, Geom::OptRect &bbox)
NRPixBlock *
nr_arena_item_get_background (NRArenaItem const *item)
{
- if (item->background_new) {
- return item->background_pb;
- } else if (item->parent) {
- return nr_arena_item_get_background (item->parent);
- } else {
- return NULL;
- }
+ return NULL;
}
/* Helpers */
diff --git a/src/display/nr-arena-item.h b/src/display/nr-arena-item.h
index ff9965b85..0fc4cbe48 100644
--- a/src/display/nr-arena-item.h
+++ b/src/display/nr-arena-item.h
@@ -1,6 +1,3 @@
-#ifndef __NR_ARENA_ITEM_H__
-#define __NR_ARENA_ITEM_H__
-
/*
* RGBA display list system for inkscape
*
@@ -13,6 +10,21 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
+#ifndef SEEN_DISPLAY_NR_ARENA_ITEM_H
+#define SEEN_DISPLAY_NR_ARENA_ITEM_H
+
+#include <cairo.h>
+#include <2geom/affine.h>
+#include "libnr/nr-rect-l.h"
+#include "libnr/nr-object.h"
+#include "gc-soft-ptr.h"
+#include "nr-arena-forward.h"
+
+namespace Inkscape {
+namespace Filters {
+class Filter;
+} }
+
#define NR_TYPE_ARENA_ITEM (nr_arena_item_get_type ())
#define NR_ARENA_ITEM(o) (NR_CHECK_INSTANCE_CAST ((o), NR_TYPE_ARENA_ITEM, NRArenaItem))
#define NR_IS_ARENA_ITEM(o) (NR_CHECK_INSTANCE_TYPE ((o), NR_TYPE_ARENA_ITEM))
@@ -52,15 +64,6 @@
#define NR_ARENA_ITEM_RENDER_NO_CACHE (1 << 0)
-#include <2geom/affine.h>
-#include <libnr/nr-rect-l.h>
-#include <libnr/nr-pixblock.h>
-#include <libnr/nr-object.h>
-#include "gc-soft-ptr.h"
-#include "nr-arena-forward.h"
-#include "display/nr-filter.h"
-#include <cairo.h>
-
struct NRGC {
NRGC(NRGC const *p) : parent(p) {}
NRGC const *parent;
@@ -84,35 +87,22 @@ struct NRArenaItem : public NRObject {
/* Opacity itself */
unsigned int opacity : 8;
- /* Key for secondary rendering */
- unsigned int key;
-
- /* BBox in grid coordinates */
- NRRectL bbox;
- /* Redraw area in grid coordinates = bbox filter-enlarged and clipped/masked */
- NRRectL drawbox;
- /* BBox in item coordinates - this should be a bounding box as
- * specified in SVG standard. Required by filters. */
- Geom::OptRect item_bbox;
- /* Our affine */
- Geom::Affine *transform;
- /* Clip item */
- NRArenaItem *clip;
- /* Mask item */
- NRArenaItem *mask;
- /* Filter to be applied after rendering this object, NULL if none */
- Inkscape::Filters::Filter *filter;
- /* Rendered buffer */
- unsigned char *px;
-
- /* Single data member */
- void *data;
-
- /* Current Transformation Matrix */
- Geom::Affine ctm;
-
- /* These hold background buffer state for filter rendering */
- NRPixBlock *background_pb;
+ unsigned int key; ///< Some SPItems can have more than one NRArenaItem,
+ ///this value is a hack used to distinguish between them
+
+ NRRectL bbox; ///< Bounding box in pixel grid coordinates; (0,0) is at page origin
+ NRRectL drawbox; ///< Bounding box enlarged by filters, shrinked by clips and masks
+ Geom::OptRect item_bbox; ///< Bounding box in item coordinates, required by filters
+ Geom::Affine *transform; ///< Incremental transform of this item, as given by the transform= attribute
+ Geom::Affine ctm; ///< Total transform from pixel grid to item coords
+ NRArenaItem *clip; ///< Clipping path
+ NRArenaItem *mask; ///< Mask
+ Inkscape::Filters::Filter *filter; ///< Filter
+ unsigned char *px; ///< Render cache; unused
+
+ void *data; ///< Anonymous data member - this is used to associate SPItems with arena items
+
+ NRPixBlock *background_pb; ///< Background for filters; unused
bool background_new;
void init(NRArena *arena) {
@@ -129,7 +119,7 @@ struct NRArenaItemClass : public NRObjectClass {
unsigned int (* update) (NRArenaItem *item, NRRectL *area, NRGC *gc, unsigned int state, unsigned int reset);
unsigned int (* render) (cairo_t *ct, NRArenaItem *item, NRRectL *area, NRPixBlock *pb, unsigned int flags);
- unsigned int (* clip) (NRArenaItem *item, NRRectL *area, NRPixBlock *pb);
+ unsigned int (* clip) (cairo_t *ct, NRArenaItem *item, NRRectL *area);
NRArenaItem * (* pick) (NRArenaItem *item, Geom::Point p, double delta, unsigned int sticky);
};
@@ -159,7 +149,7 @@ unsigned int nr_arena_item_invoke_update (NRArenaItem *item, NRRectL *area, NRGC
unsigned int nr_arena_item_invoke_render(cairo_t *ct, NRArenaItem *item, NRRectL const *area, NRPixBlock *pb, unsigned int flags);
-unsigned int nr_arena_item_invoke_clip (NRArenaItem *item, NRRectL *area, NRPixBlock *pb);
+unsigned int nr_arena_item_invoke_clip (cairo_t *ct, NRArenaItem *item, NRRectL *area);
NRArenaItem *nr_arena_item_invoke_pick (NRArenaItem *item, Geom::Point p, double delta, unsigned int sticky);
void nr_arena_item_request_update (NRArenaItem *item, unsigned int reset, unsigned int propagate);
@@ -194,8 +184,7 @@ NRArenaItem *nr_arena_item_detach (NRArenaItem *parent, NRArenaItem *child);
#define NR_ARENA_ITEM_SET_KEY(i,k) (((NRArenaItem *) (i))->key = (k))
#define NR_ARENA_ITEM_GET_KEY(i) (((NRArenaItem *) (i))->key)
-
-#endif /* !__NR_ARENA_ITEM_H__ */
+#endif /* !SEEN_DISPLAY_NR_ARENA_ITEM_H */
/*
Local Variables:
diff --git a/src/display/nr-arena-shape.cpp b/src/display/nr-arena-shape.cpp
index 33a218e99..f278413b2 100644
--- a/src/display/nr-arena-shape.cpp
+++ b/src/display/nr-arena-shape.cpp
@@ -10,41 +10,30 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
+#include <cairo.h>
#include <glib.h>
#include <fenv.h>
#include <typeinfo>
-#include <cairo.h>
+#include <2geom/curves.h>
+#include <2geom/pathvector.h>
#include <2geom/svg-path.h>
#include <2geom/svg-path-parser.h>
-#include <2geom/pathvector.h>
-#include <2geom/curves.h>
-#include "display/sp-canvas.h"
+#include "display/cairo-utils.h"
#include "display/canvas-arena.h"
+#include "display/curve.h"
#include "display/nr-arena.h"
#include "display/nr-arena-shape.h"
-#include "display/curve.h"
-#include "display/grayscale.h"
-#include "libnr/nr-pixops.h"
-#include "libnr/nr-blit.h"
-#include "libnr/nr-convert2geom.h"
-#include "livarot/Path.h"
-#include "livarot/float-line.h"
-#include "livarot/int-line.h"
-#include "style.h"
-#include "inkscape-cairo.h"
-#include "helper/geom.h"
+#include "display/nr-filter.h"
#include "helper/geom-curves.h"
+#include "helper/geom.h"
+#include "libnr/nr-convert2geom.h"
+#include "preferences.h"
#include "sp-filter.h"
#include "sp-filter-reference.h"
-#include "display/nr-filter.h"
-#include "preferences.h"
-
+#include "style.h"
#include "svg/svg.h"
-//int showRuns=0;
-void nr_pixblock_render_shape_mask_or(NRPixBlock &m,Shape* theS);
-
static void nr_arena_shape_class_init(NRArenaShapeClass *klass);
static void nr_arena_shape_init(NRArenaShape *shape);
static void nr_arena_shape_finalize(NRObject *object);
@@ -56,7 +45,7 @@ static void nr_arena_shape_set_child_position(NRArenaItem *item, NRArenaItem *ch
static guint nr_arena_shape_update(NRArenaItem *item, NRRectL *area, NRGC *gc, guint state, guint reset);
static unsigned int nr_arena_shape_render(cairo_t *ct, NRArenaItem *item, NRRectL *area, NRPixBlock *pb, unsigned int flags);
-static guint nr_arena_shape_clip(NRArenaItem *item, NRRectL *area, NRPixBlock *pb);
+static guint nr_arena_shape_clip(cairo_t *ct, NRArenaItem *item, NRRectL *area);
static NRArenaItem *nr_arena_shape_pick(NRArenaItem *item, Geom::Point p, double delta, unsigned int sticky);
static NRArenaItemClass *shape_parent_class;
@@ -111,26 +100,13 @@ nr_arena_shape_init(NRArenaShape *shape)
shape->style = NULL;
shape->paintbox.x0 = shape->paintbox.y0 = 0.0F;
shape->paintbox.x1 = shape->paintbox.y1 = 256.0F;
-
- shape->ctm.setIdentity();
- shape->fill_painter = NULL;
- shape->stroke_painter = NULL;
- shape->cached_fill = NULL;
- shape->cached_stroke = NULL;
- shape->cached_fpartialy = false;
- shape->cached_spartialy = false;
- shape->fill_shp = NULL;
- shape->stroke_shp = NULL;
-
shape->delayed_shp = false;
+ shape->path = NULL;
shape->approx_bbox.x0 = shape->approx_bbox.y0 = 0;
shape->approx_bbox.x1 = shape->approx_bbox.y1 = 0;
- shape->cached_fctm.setIdentity();
- shape->cached_sctm.setIdentity();
shape->markers = NULL;
-
shape->last_pick = NULL;
shape->repick_after = 0;
}
@@ -140,15 +116,10 @@ nr_arena_shape_finalize(NRObject *object)
{
NRArenaShape *shape = (NRArenaShape *) object;
- if (shape->fill_shp) delete shape->fill_shp;
- if (shape->stroke_shp) delete shape->stroke_shp;
- if (shape->cached_fill) delete shape->cached_fill;
- if (shape->cached_stroke) delete shape->cached_stroke;
- if (shape->fill_painter) sp_painter_free(shape->fill_painter);
- if (shape->stroke_painter) sp_painter_free(shape->stroke_painter);
-
+ if (shape->path) cairo_path_destroy(shape->path);
if (shape->style) sp_style_unref(shape->style);
if (shape->curve) shape->curve->unref();
+ shape->last_pick = NULL;
((NRObjectClass *) shape_parent_class)->finalize(object);
}
@@ -227,10 +198,6 @@ nr_arena_shape_set_child_position(NRArenaItem *item, NRArenaItem *child, NRArena
nr_arena_item_request_render(child);
}
-void nr_arena_shape_update_stroke(NRArenaShape *shape, NRGC* gc, NRRectL *area);
-void nr_arena_shape_update_fill(NRArenaShape *shape, NRGC *gc, NRRectL *area, bool force_shape = false);
-void nr_arena_shape_add_bboxes(NRArenaShape* shape, Geom::OptRect &bbox);
-
/**
* Updates the arena shape 'item' and all of its children, including the markers.
*/
@@ -243,6 +210,7 @@ nr_arena_shape_update(NRArenaItem *item, NRRectL *area, NRGC *gc, guint state, g
unsigned int beststate = NR_ARENA_ITEM_STATE_ALL;
+ // update markers
unsigned int newstate;
for (NRArenaItem *child = shape->markers; child != NULL; child = child->next) {
newstate = nr_arena_item_invoke_update(child, area, gc, state, reset);
@@ -251,7 +219,6 @@ nr_arena_shape_update(NRArenaItem *item, NRRectL *area, NRGC *gc, guint state, g
if (!(state & NR_ARENA_ITEM_STATE_RENDER)) {
/* We do not have to create rendering structures */
- shape->ctm = gc->transform;
if (state & NR_ARENA_ITEM_STATE_BBOX) {
if (shape->curve) {
boundingbox = bounds_exact_transformed(shape->curve->get_pathvector(), gc->transform);
@@ -274,29 +241,36 @@ nr_arena_shape_update(NRArenaItem *item, NRRectL *area, NRGC *gc, guint state, g
}
shape->delayed_shp=true;
- shape->ctm = gc->transform;
boundingbox = Geom::OptRect();
bool outline = (NR_ARENA_ITEM(shape)->arena->rendermode == Inkscape::RENDERMODE_OUTLINE);
+ // clear Cairo data to force update
+ shape->nrstyle.update();
+ if (shape->path) {
+ cairo_path_destroy(shape->path);
+ shape->path = NULL;
+ }
+
if (shape->curve) {
boundingbox = bounds_exact_transformed(shape->curve->get_pathvector(), gc->transform);
- if (boundingbox && (shape->_stroke.paint.type() != NRArenaShape::Paint::NONE || outline)) {
+ if (boundingbox && (shape->nrstyle.stroke.type != NRStyle::PAINT_NONE || outline)) {
float width, scale;
scale = gc->transform.descrim();
- width = MAX(0.125, shape->_stroke.width * scale);
- if ( fabs(shape->_stroke.width * scale) > 0.01 ) { // sinon c'est 0=oon veut pas de bord
+ width = MAX(0.125, shape->nrstyle.stroke_width * scale);
+ if ( fabs(shape->nrstyle.stroke_width * scale) > 0.01 ) { // FIXME: this is always true
boundingbox->expandBy(width);
}
// those pesky miters, now
- float miterMax=width*shape->_stroke.mitre_limit;
+ float miterMax = width * shape->nrstyle.miter_limit;
if ( miterMax > 0.01 ) {
- // grunt mode. we should compute the various miters instead (one for each point on the curve)
+ // grunt mode. we should compute the various miters instead
+ // (one for each point on the curve)
boundingbox->expandBy(miterMax);
}
}
- }
+ }
/// \todo just write item->bbox = boundingbox
if (boundingbox) {
@@ -309,88 +283,17 @@ nr_arena_shape_update(NRArenaItem *item, NRRectL *area, NRGC *gc, guint state, g
}
if ( area && nr_rect_l_test_intersect_ptr(area, &shape->approx_bbox) ) shape->delayed_shp=false;
- /* Release state data */
- if (shape->fill_shp) {
- delete shape->fill_shp;
- shape->fill_shp = NULL;
- }
- if (shape->stroke_shp) {
- delete shape->stroke_shp;
- shape->stroke_shp = NULL;
- }
- if (shape->fill_painter) {
- sp_painter_free(shape->fill_painter);
- shape->fill_painter = NULL;
- }
- if (shape->stroke_painter) {
- sp_painter_free(shape->stroke_painter);
- shape->stroke_painter = NULL;
- }
+ // TODO: compute a better bounding box that respects miters
+ item->bbox = shape->approx_bbox;
if (!shape->curve ||
!shape->style ||
shape->curve->is_empty() ||
- (( shape->_fill.paint.type() == NRArenaShape::Paint::NONE ) &&
- ( shape->_stroke.paint.type() == NRArenaShape::Paint::NONE && !outline) ))
+ (( shape->nrstyle.fill.type != NRStyle::PAINT_NONE ) &&
+ ( shape->nrstyle.stroke.type != NRStyle::PAINT_NONE && !outline) ))
{
- item->bbox = shape->approx_bbox;
- return NR_ARENA_ITEM_STATE_ALL;
- }
-
- /* Build state data */
- if ( shape->delayed_shp ) {
- item->bbox=shape->approx_bbox;
- } else {
- nr_arena_shape_update_stroke(shape, gc, area);
- nr_arena_shape_update_fill(shape, gc, area);
-
- boundingbox = Geom::OptRect();
- nr_arena_shape_add_bboxes(shape, boundingbox);
-
- /// \todo just write shape->approx_bbox = boundingbox
- if (boundingbox) {
- shape->approx_bbox.x0 = static_cast<NR::ICoord>(floor((*boundingbox)[0][0]));
- shape->approx_bbox.y0 = static_cast<NR::ICoord>(floor((*boundingbox)[1][0]));
- shape->approx_bbox.x1 = static_cast<NR::ICoord>(ceil ((*boundingbox)[0][1]));
- shape->approx_bbox.y1 = static_cast<NR::ICoord>(ceil ((*boundingbox)[1][1]));
- } else {
- shape->approx_bbox = NR_RECT_L_EMPTY;
- }
- }
-
- if (!boundingbox)
+ //item->bbox = shape->approx_bbox;
return NR_ARENA_ITEM_STATE_ALL;
-
- /// \todo just write item->bbox = boundingbox
- item->bbox.x0 = static_cast<NR::ICoord>(floor((*boundingbox)[0][0]));
- item->bbox.y0 = static_cast<NR::ICoord>(floor((*boundingbox)[1][0]));
- item->bbox.x1 = static_cast<NR::ICoord>(ceil ((*boundingbox)[0][1]));
- item->bbox.y1 = static_cast<NR::ICoord>(ceil ((*boundingbox)[1][1]));
-
- item->render_opacity = TRUE;
- if ( shape->_fill.paint.type() == NRArenaShape::Paint::SERVER ) {
- if (gc && gc->parent) {
- shape->fill_painter = sp_paint_server_painter_new(shape->_fill.paint.server(),
- gc->transform, gc->parent->transform,
- &shape->paintbox);
- }
- item->render_opacity = FALSE;
- }
- if ( shape->_stroke.paint.type() == NRArenaShape::Paint::SERVER ) {
- if (gc && gc->parent) {
- shape->stroke_painter = sp_paint_server_painter_new(shape->_stroke.paint.server(),
- gc->transform, gc->parent->transform,
- &shape->paintbox);
- }
- item->render_opacity = FALSE;
- }
- if ( (shape->_fill.paint.type() != NRArenaShape::Paint::NONE &&
- shape->_stroke.paint.type() != NRArenaShape::Paint::NONE)
- || (shape->markers)
- )
- {
- // don't merge item opacity with paint opacity if there is a stroke on the fill, or markers on stroke
- item->render_opacity = FALSE;
}
if (beststate & NR_ARENA_ITEM_STATE_BBOX) {
@@ -402,328 +305,9 @@ nr_arena_shape_update(NRArenaItem *item, NRRectL *area, NRGC *gc, guint state, g
return NR_ARENA_ITEM_STATE_ALL;
}
-int matrix_is_isometry(Geom::Affine p) {
- Geom::Affine tp;
- // transposition
- tp[0]=p[0];
- tp[1]=p[2];
- tp[2]=p[1];
- tp[3]=p[3];
- for (int i = 4; i < 6; i++) // shut valgrind up :)
- tp[i] = p[i] = 0;
- Geom::Affine isom = tp*p; // A^T * A = adjunct?
- // Is the adjunct nearly an identity function?
- if (isom.isTranslation(0.01)) {
- // the transformation is an isometry -> no need to recompute
- // the uncrossed polygon
- if ( p.det() < 0 )
- return -1;
- else
- return 1;
- }
- return 0;
-}
-
-static bool is_inner_area(NRRectL const &outer, NRRectL const &inner) {
- return (outer.x0 <= inner.x0 && outer.y0 <= inner.y0 && outer.x1 >= inner.x1 && outer.y1 >= inner.y1);
-}
-
-/* returns true if the pathvector has a region that needs fill.
- * is for optimizing purposes, so should be fast and can falsely return true.
- * CANNOT falsely return false. */
-static bool has_inner_area(Geom::PathVector const & pv) {
- // return false for the cases where there is surely no region to be filled
- if (pv.empty())
- return false;
-
- if ( (pv.size() == 1) && (pv.front().size() <= 1) ) {
- // vector has only one path with only one segment, see if that's a non-curve segment: that would mean no internal region
- if ( is_straight_curve(pv.front().front()) )
- {
- return false;
- }
- }
-
- return true; //too costly to see if it has region to be filled, so return true.
-}
-
-/** force_shape is used for clipping paths, when we need the shape for clipping even if it's not filled */
-void
-nr_arena_shape_update_fill(NRArenaShape *shape, NRGC *gc, NRRectL *area, bool force_shape)
-{
- if ((shape->_fill.paint.type() != NRArenaShape::Paint::NONE || force_shape) &&
- has_inner_area(shape->curve->get_pathvector()) ) {
-
- Geom::Affine cached_to_new = Geom::identity();
- int isometry = 0;
- if ( shape->cached_fill ) {
- if (shape->cached_fctm == gc->transform) {
- isometry = 2; // identity
- } else {
- cached_to_new = shape->cached_fctm.inverse() * gc->transform;
- isometry = matrix_is_isometry(cached_to_new);
- }
- if (0 != isometry && !is_inner_area(shape->cached_farea, *area))
- isometry = 0;
- }
- if ( isometry == 0 ) {
- if ( shape->cached_fill == NULL ) shape->cached_fill=new Shape;
- shape->cached_fill->Reset();
-
- Path* thePath=new Path;
- Shape* theShape=new Shape;
- {
- Geom::Affine tempMat(gc->transform);
- thePath->LoadPathVector(shape->curve->get_pathvector(), tempMat, true);
- }
-
- if (is_inner_area(*area, NR_ARENA_ITEM(shape)->bbox)) {
- thePath->Convert(1.0);
- shape->cached_fpartialy = false;
- } else {
- thePath->Convert(area, 1.0);
- shape->cached_fpartialy = true;
- }
-
- thePath->Fill(theShape, 0);
-
- if ( shape->_fill.rule == NRArenaShape::EVEN_ODD ) {
- shape->cached_fill->ConvertToShape(theShape, fill_oddEven);
- // alternatively, this speeds up rendering of oddeven shapes but disables AA :(
- //shape->cached_fill->Copy(theShape);
- } else {
- shape->cached_fill->ConvertToShape(theShape, fill_nonZero);
- }
- shape->cached_fctm=gc->transform;
- shape->cached_farea = *area;
- delete theShape;
- delete thePath;
- if ( shape->fill_shp == NULL )
- shape->fill_shp = new Shape;
-
- shape->fill_shp->Copy(shape->cached_fill);
-
- } else if ( 2 == isometry ) {
- if ( shape->fill_shp == NULL ) {
- shape->fill_shp = new Shape;
- shape->fill_shp->Copy(shape->cached_fill);
- }
- } else {
-
- if ( shape->fill_shp == NULL )
- shape->fill_shp = new Shape;
-
- shape->fill_shp->Reset(shape->cached_fill->numberOfPoints(),
- shape->cached_fill->numberOfEdges());
- for (int i = 0; i < shape->cached_fill->numberOfPoints(); i++)
- shape->fill_shp->AddPoint(to_2geom(shape->cached_fill->getPoint(i).x) * cached_to_new);
- if ( isometry == 1 ) {
- for (int i = 0; i < shape->cached_fill->numberOfEdges(); i++)
- shape->fill_shp->AddEdge(shape->cached_fill->getEdge(i).st,
- shape->cached_fill->getEdge(i).en);
- } else if ( isometry == -1 ) { // need to flip poly.
- for (int i = 0; i < shape->cached_fill->numberOfEdges(); i++)
- shape->fill_shp->AddEdge(shape->cached_fill->getEdge(i).en,
- shape->cached_fill->getEdge(i).st);
- }
- shape->fill_shp->ForceToPolygon();
- shape->fill_shp->needPointsSorting();
- shape->fill_shp->needEdgesSorting();
- }
- shape->delayed_shp |= shape->cached_fpartialy;
- }
-}
-
-void
-nr_arena_shape_update_stroke(NRArenaShape *shape,NRGC* gc, NRRectL *area)
-{
- SPStyle* style = shape->style;
-
- float const scale = gc->transform.descrim();
-
- bool outline = (NR_ARENA_ITEM(shape)->arena->rendermode == Inkscape::RENDERMODE_OUTLINE);
-
- if (outline) {
- // cairo does not need the livarot path for rendering
- return;
- }
-
- // after switching normal stroke rendering to cairo too, optimize this: lower tolerance, disregard dashes
- // (since it will only be used for picking, not for rendering)
-
- if (outline ||
- ((shape->_stroke.paint.type() != NRArenaShape::Paint::NONE) &&
- ( fabs(shape->_stroke.width * scale) > 0.01 ))) { // sinon c'est 0=oon veut pas de bord
-
- float style_width = MAX(0.125, shape->_stroke.width * scale);
- float width;
- if (outline) {
- width = 0.5; // 1 pixel wide, independent of zoom
- } else {
- width = style_width;
- }
-
- Geom::Affine cached_to_new = Geom::identity();
-
- int isometry = 0;
- if ( shape->cached_stroke ) {
- if (shape->cached_sctm == gc->transform) {
- isometry = 2; // identity
- } else {
- cached_to_new = shape->cached_sctm.inverse() * gc->transform;
- isometry = matrix_is_isometry(cached_to_new);
- }
- if (0 != isometry && !is_inner_area(shape->cached_sarea, *area))
- isometry = 0;
- if (0 != isometry && width != shape->cached_width) {
- // if this happens without setting style, we have just switched to outline or back
- isometry = 0;
- }
- }
-
- if ( isometry == 0 ) {
- if ( shape->cached_stroke == NULL ) shape->cached_stroke=new Shape;
- shape->cached_stroke->Reset();
- Path* thePath = new Path;
- Shape* theShape = new Shape;
- {
- Geom::Affine tempMat( gc->transform );
- thePath->LoadPathVector(shape->curve->get_pathvector(), tempMat, true);
- }
-
- // add some padding to the rendering area, so clipped path does not go into a render area
- NRRectL padded_area = *area;
- padded_area.x0 -= (NR::ICoord)width;
- padded_area.x1 += (NR::ICoord)width;
- padded_area.y0 -= (NR::ICoord)width;
- padded_area.y1 += (NR::ICoord)width;
- if ((style->stroke_dash.n_dash && !outline) || is_inner_area(padded_area, NR_ARENA_ITEM(shape)->bbox)) {
- thePath->Convert((outline) ? 4.0 : 1.0);
- shape->cached_spartialy = false;
- }
- else {
- thePath->Convert(&padded_area, (outline) ? 4.0 : 1.0);
- shape->cached_spartialy = true;
- }
-
- if (style->stroke_dash.n_dash && !outline) {
- thePath->DashPolylineFromStyle(style, scale, 1.0);
- }
-
- ButtType butt=butt_straight;
- switch (shape->_stroke.cap) {
- case NRArenaShape::BUTT_CAP:
- butt = butt_straight;
- break;
- case NRArenaShape::ROUND_CAP:
- butt = butt_round;
- break;
- case NRArenaShape::SQUARE_CAP:
- butt = butt_square;
- break;
- }
- JoinType join=join_straight;
- switch (shape->_stroke.join) {
- case NRArenaShape::MITRE_JOIN:
- join = join_pointy;
- break;
- case NRArenaShape::ROUND_JOIN:
- join = join_round;
- break;
- case NRArenaShape::BEVEL_JOIN:
- join = join_straight;
- break;
- }
-
- if (outline) {
- butt = butt_straight;
- join = join_straight;
- }
-
- thePath->Stroke(theShape, false, 0.5*width, join, butt,
- 0.5*width*shape->_stroke.mitre_limit);
-
-
- if (outline) {
- // speeds it up, but uses evenodd for the stroke shape (which does not matter for 1-pixel wide outline)
- shape->cached_stroke->Copy(theShape);
- } else {
- shape->cached_stroke->ConvertToShape(theShape, fill_nonZero);
- }
-
- shape->cached_width = width;
-
- shape->cached_sctm=gc->transform;
- shape->cached_sarea = *area;
- delete thePath;
- delete theShape;
- if ( shape->stroke_shp == NULL ) shape->stroke_shp=new Shape;
-
- shape->stroke_shp->Copy(shape->cached_stroke);
-
- } else if ( 2 == isometry ) {
- if ( shape->stroke_shp == NULL ) {
- shape->stroke_shp=new Shape;
- shape->stroke_shp->Copy(shape->cached_stroke);
- }
- } else {
- if ( shape->stroke_shp == NULL )
- shape->stroke_shp=new Shape;
- shape->stroke_shp->Reset(shape->cached_stroke->numberOfPoints(), shape->cached_stroke->numberOfEdges());
- for (int i = 0; i < shape->cached_stroke->numberOfPoints(); i++)
- shape->stroke_shp->AddPoint(to_2geom(shape->cached_stroke->getPoint(i).x) * cached_to_new);
- if ( isometry == 1 ) {
- for (int i = 0; i < shape->cached_stroke->numberOfEdges(); i++)
- shape->stroke_shp->AddEdge(shape->cached_stroke->getEdge(i).st,
- shape->cached_stroke->getEdge(i).en);
- } else if ( isometry == -1 ) {
- for (int i = 0; i < shape->cached_stroke->numberOfEdges(); i++)
- shape->stroke_shp->AddEdge(shape->cached_stroke->getEdge(i).en,
- shape->cached_stroke->getEdge(i).st);
- }
- shape->stroke_shp->ForceToPolygon();
- shape->stroke_shp->needPointsSorting();
- shape->stroke_shp->needEdgesSorting();
- }
- shape->delayed_shp |= shape->cached_spartialy;
- }
-}
-
-
-void
-nr_arena_shape_add_bboxes(NRArenaShape* shape, Geom::OptRect &bbox)
-{
- /* TODO: are these two if's mutually exclusive? ( i.e. "shape->stroke_shp <=> !shape->fill_shp" )
- * if so, then this can be written much more compact ! */
-
- if ( shape->stroke_shp ) {
- Shape *larger = shape->stroke_shp;
- larger->CalcBBox();
- larger->leftX = floor(larger->leftX);
- larger->rightX = ceil(larger->rightX);
- larger->topY = floor(larger->topY);
- larger->bottomY = ceil(larger->bottomY);
- Geom::Rect stroke_bbox( Geom::Interval(larger->leftX, larger->rightX),
- Geom::Interval(larger->topY, larger->bottomY) );
- bbox.unionWith(stroke_bbox);
- }
-
- if ( shape->fill_shp ) {
- Shape *larger = shape->fill_shp;
- larger->CalcBBox();
- larger->leftX = floor(larger->leftX);
- larger->rightX = ceil(larger->rightX);
- larger->topY = floor(larger->topY);
- larger->bottomY = ceil(larger->bottomY);
- Geom::Rect fill_bbox( Geom::Interval(larger->leftX, larger->rightX),
- Geom::Interval(larger->topY, larger->bottomY) );
- bbox.unionWith(fill_bbox);
- }
-}
-
// cairo outline rendering:
static unsigned int
-cairo_arena_shape_render_outline(cairo_t *ct, NRArenaItem *item, Geom::OptRect area)
+cairo_arena_shape_render_outline(cairo_t *ct, NRArenaItem *item, Geom::OptRect /*area*/)
{
NRArenaShape *shape = NR_ARENA_SHAPE(item);
@@ -731,107 +315,21 @@ cairo_arena_shape_render_outline(cairo_t *ct, NRArenaItem *item, Geom::OptRect a
return item->state;
guint32 rgba = NR_ARENA_ITEM(shape)->arena->outlinecolor;
- // FIXME: we use RGBA buffers but cairo writes BGRA (on i386), so we must cheat
- // by setting color channels in the "wrong" order
- cairo_set_source_rgba(ct, SP_RGBA32_B_F(rgba), SP_RGBA32_G_F(rgba), SP_RGBA32_R_F(rgba), SP_RGBA32_A_F(rgba));
+ cairo_save(ct);
+ ink_cairo_transform(ct, shape->ctm);
+ feed_pathvector_to_cairo (ct, shape->curve->get_pathvector());
+ cairo_restore(ct);
+ cairo_save(ct);
+ ink_cairo_set_source_rgba32(ct, rgba);
cairo_set_line_width(ct, 0.5);
cairo_set_tolerance(ct, 1.25); // low quality, but good enough for outline mode
- cairo_new_path(ct);
-
- feed_pathvector_to_cairo (ct, shape->curve->get_pathvector(), shape->ctm, area, true, 0);
-
cairo_stroke(ct);
+ cairo_restore(ct);
return item->state;
}
-// cairo stroke rendering (flat color only so far!):
-// works on canvas, but wrongs the colors in nonpremul buffers: icons and png export
-// (need to switch them to premul before this can be enabled)
-void
-cairo_arena_shape_render_stroke(NRArenaItem *item, NRRectL *area, NRPixBlock *pb)
-{
- NRArenaShape *shape = NR_ARENA_SHAPE(item);
- SPStyle const *style = shape->style;
-
- float const scale = shape->ctm.descrim();
-
- if (fabs(shape->_stroke.width * scale) < 0.01)
- return;
-
- cairo_t *ct = nr_create_cairo_context (area, pb);
-
- if (!ct)
- return;
-
- guint32 rgba;
- if ( item->render_opacity ) {
- rgba = shape->_stroke.paint.color().toRGBA32( shape->_stroke.opacity *
- SP_SCALE24_TO_FLOAT(style->opacity.value) );
- } else {
- rgba = shape->_stroke.paint.color().toRGBA32( shape->_stroke.opacity );
- }
-
- // FIXME: we use RGBA buffers but cairo writes BGRA (on i386), so we must cheat
- // by setting color channels in the "wrong" order
- cairo_set_source_rgba(ct, SP_RGBA32_B_F(rgba), SP_RGBA32_G_F(rgba), SP_RGBA32_R_F(rgba), SP_RGBA32_A_F(rgba));
-
- float style_width = MAX(0.125, shape->_stroke.width * scale);
- cairo_set_line_width(ct, style_width);
-
- switch (shape->_stroke.cap) {
- case NRArenaShape::BUTT_CAP:
- cairo_set_line_cap(ct, CAIRO_LINE_CAP_BUTT);
- break;
- case NRArenaShape::ROUND_CAP:
- cairo_set_line_cap(ct, CAIRO_LINE_CAP_ROUND);
- break;
- case NRArenaShape::SQUARE_CAP:
- cairo_set_line_cap(ct, CAIRO_LINE_CAP_SQUARE);
- break;
- }
- switch (shape->_stroke.join) {
- case NRArenaShape::MITRE_JOIN:
- cairo_set_line_join(ct, CAIRO_LINE_JOIN_MITER);
- break;
- case NRArenaShape::ROUND_JOIN:
- cairo_set_line_join(ct, CAIRO_LINE_JOIN_ROUND);
- break;
- case NRArenaShape::BEVEL_JOIN:
- cairo_set_line_join(ct, CAIRO_LINE_JOIN_BEVEL);
- break;
- }
-
- cairo_set_miter_limit (ct, style->stroke_miterlimit.value);
-
- if (style->stroke_dash.n_dash) {
- NRVpathDash dash;
- dash.offset = style->stroke_dash.offset * scale;
- dash.n_dash = style->stroke_dash.n_dash;
- dash.dash = g_new(double, dash.n_dash);
- for (int i = 0; i < dash.n_dash; i++) {
- dash.dash[i] = style->stroke_dash.dash[i] * scale;
- }
- cairo_set_dash (ct, dash.dash, dash.n_dash, dash.offset);
- g_free(dash.dash);
- }
-
- cairo_set_tolerance(ct, 0.1);
- cairo_new_path(ct);
-
- feed_pathvector_to_cairo (ct, shape->curve->get_pathvector(), shape->ctm, to_2geom(area->upgrade()), true, style_width);
-
- cairo_stroke(ct);
-
- cairo_surface_t *cst = cairo_get_target(ct);
- cairo_destroy (ct);
- cairo_surface_finish (cst);
- cairo_surface_destroy (cst);
-
- pb->empty = FALSE;
-}
-
/**
* Renders the item. Markers are just composed into the parent buffer.
*/
@@ -842,150 +340,51 @@ nr_arena_shape_render(cairo_t *ct, NRArenaItem *item, NRRectL *area, NRPixBlock
if (!shape->curve) return item->state;
if (!shape->style) return item->state;
+ if (!ct) return item->state;
+
+ // skip if not within bounding box
+ if (!nr_rect_l_test_intersect_ptr(area, &item->bbox)) {
+ return item->state;
+ }
bool outline = (NR_ARENA_ITEM(shape)->arena->rendermode == Inkscape::RENDERMODE_OUTLINE);
- bool print_colors_preview = (NR_ARENA_ITEM(shape)->arena->colorrendermode == Inkscape::COLORRENDERMODE_PRINT_COLORS_PREVIEW);
- bool grayscale = (NR_ARENA_ITEM(shape)->arena->colorrendermode == Inkscape::COLORRENDERMODE_GRAYSCALE);
if (outline) { // cairo outline rendering
- pb->empty = FALSE;
- unsigned int ret = cairo_arena_shape_render_outline (ct, item, to_2geom((&pb->area)->upgrade()));
+ NRRect temp(area->x0, area->y0, area->x1, area->y1);
+ unsigned int ret = cairo_arena_shape_render_outline (ct, item, temp.upgrade_2geom());
if (ret & NR_ARENA_ITEM_STATE_INVALID) return ret;
} else {
-
- if ( shape->delayed_shp ) {
- if ( nr_rect_l_test_intersect_ptr(area, &item->bbox) ) {
- NRGC tempGC(NULL);
- tempGC.transform=shape->ctm;
- shape->delayed_shp = false;
- nr_arena_shape_update_stroke(shape,&tempGC,&pb->visible_area);
- nr_arena_shape_update_fill(shape,&tempGC,&pb->visible_area);
-/* NRRect bbox;
- bbox.x0 = bbox.y0 = bbox.x1 = bbox.y1 = 0.0;
- nr_arena_shape_add_bboxes(shape,bbox);
- item->bbox.x0 = (gint32)(bbox.x0 - 1.0F);
- item->bbox.y0 = (gint32)(bbox.y0 - 1.0F);
- item->bbox.x1 = (gint32)(bbox.x1 + 1.0F);
- item->bbox.y1 = (gint32)(bbox.y1 + 1.0F);
- shape->approx_bbox=item->bbox;*/
- } else {
- return item->state;
- }
- }
-
- SPStyle const *style = shape->style;
-
- if (shape->fill_shp) {
- NRPixBlock m;
- guint32 rgba;
-
- nr_pixblock_setup_fast(&m, NR_PIXBLOCK_MODE_A8, area->x0, area->y0, area->x1, area->y1, TRUE);
-
- // if memory allocation failed, abort render
- if (m.size != NR_PIXBLOCK_SIZE_TINY && m.data.px == NULL) {
- nr_pixblock_release (&m);
- return (item->state);
- }
-
- m.visible_area = pb->visible_area;
- nr_pixblock_render_shape_mask_or(m,shape->fill_shp);
- m.empty = FALSE;
-
- if (shape->_fill.paint.type() == NRArenaShape::Paint::NONE) {
- // do not render fill in any way
- } else if (shape->_fill.paint.type() == NRArenaShape::Paint::COLOR) {
-
- const SPColor* fill_color = &shape->_fill.paint.color();
- if ( item->render_opacity ) {
- rgba = fill_color->toRGBA32( shape->_fill.opacity *
- SP_SCALE24_TO_FLOAT(style->opacity.value) );
- } else {
- rgba = fill_color->toRGBA32( shape->_fill.opacity );
+ bool has_stroke, has_fill;
+ // we assume the context has no path
+ cairo_save(ct);
+ ink_cairo_transform(ct, shape->ctm);
+
+ // update fill and stroke paints.
+ // this cannot be done during nr_arena_shape_update, because we need a Cairo context
+ // to render svg:pattern
+ has_fill = shape->nrstyle.prepareFill(ct, &shape->paintbox);
+ has_stroke = shape->nrstyle.prepareStroke(ct, &shape->paintbox);
+ has_stroke &= (shape->nrstyle.stroke_width != 0);
+
+ if (has_fill || has_stroke) {
+ // TODO: remove segments outside of bbox when no dashes present
+ feed_pathvector_to_cairo(ct, shape->curve->get_pathvector());
+ if (has_fill) {
+ shape->nrstyle.applyFill(ct);
+ cairo_fill_preserve(ct);
}
-
- if (print_colors_preview) {
- nr_arena_separate_color_plates(&rgba);
- } else if (grayscale) {
- rgba = Grayscale::process(rgba);
- }
-
- nr_blit_pixblock_mask_rgba32(pb, &m, rgba);
- pb->empty = FALSE;
- } else if (shape->_fill.paint.type() == NRArenaShape::Paint::SERVER) {
- if (shape->fill_painter) {
- nr_arena_render_paintserver_fill(pb, area, shape->fill_painter, shape->_fill.opacity, &m);
+ if (has_stroke) {
+ shape->nrstyle.applyStroke(ct);
+ cairo_stroke_preserve(ct);
}
- }
-
- nr_pixblock_release(&m);
+ cairo_new_path(ct); // clear path
+ } // has fill or stroke pattern
+ cairo_restore(ct);
}
- if (shape->stroke_shp && shape->_stroke.paint.type() == NRArenaShape::Paint::COLOR) {
-
- // cairo_arena_shape_render_stroke(item, area, pb);
-
- guint32 rgba;
- NRPixBlock m;
-
- nr_pixblock_setup_fast(&m, NR_PIXBLOCK_MODE_A8, area->x0, area->y0, area->x1, area->y1, TRUE);
-
- // if memory allocation failed, abort render
- if (m.size != NR_PIXBLOCK_SIZE_TINY && m.data.px == NULL) {
- nr_pixblock_release (&m);
- return (item->state);
- }
-
- m.visible_area = pb->visible_area;
- nr_pixblock_render_shape_mask_or(m, shape->stroke_shp);
- m.empty = FALSE;
-
- const SPColor* stroke_color = &shape->_stroke.paint.color();
- if ( item->render_opacity ) {
- rgba = stroke_color->toRGBA32( shape->_stroke.opacity *
- SP_SCALE24_TO_FLOAT(style->opacity.value) );
- } else {
- rgba = stroke_color->toRGBA32( shape->_stroke.opacity );
- }
-
- if (print_colors_preview) {
- nr_arena_separate_color_plates(&rgba);
- } else if (grayscale) {
- rgba = Grayscale::process(rgba);
- }
-
- nr_blit_pixblock_mask_rgba32(pb, &m, rgba);
- pb->empty = FALSE;
-
- nr_pixblock_release(&m);
-
- } else if (shape->stroke_shp && shape->_stroke.paint.type() == NRArenaShape::Paint::SERVER) {
-
- NRPixBlock m;
-
- nr_pixblock_setup_fast(&m, NR_PIXBLOCK_MODE_A8, area->x0, area->y0, area->x1, area->y1, TRUE);
-
- // if memory allocation failed, abort render
- if (m.size != NR_PIXBLOCK_SIZE_TINY && m.data.px == NULL) {
- nr_pixblock_release (&m);
- return (item->state);
- }
-
- m.visible_area = pb->visible_area;
- nr_pixblock_render_shape_mask_or(m, shape->stroke_shp);
- m.empty = FALSE;
-
- if (shape->stroke_painter) {
- nr_arena_render_paintserver_fill(pb, area, shape->stroke_painter, shape->_stroke.opacity, &m);
- }
-
- nr_pixblock_release(&m);
- }
-
- } // non-cairo non-outline branch
-
- /* Render markers into parent buffer */
+ // marker rendering
for (NRArenaItem *child = shape->markers; child != NULL; child = child->next) {
unsigned int ret = nr_arena_item_invoke_render(ct, child, area, pb, flags);
if (ret & NR_ARENA_ITEM_STATE_INVALID) return ret;
@@ -995,88 +394,18 @@ nr_arena_shape_render(cairo_t *ct, NRArenaItem *item, NRRectL *area, NRPixBlock
}
-// cairo clipping: this basically works except for the stride-must-be-divisible-by-4 cairo bug;
-// reenable this when the bug is fixed and remove the rest of this function
-// TODO
-#if defined(DEADCODE) && !defined(DEADCODE)
-static guint
-cairo_arena_shape_clip(NRArenaItem *item, NRRectL *area, NRPixBlock *pb)
-{
- NRArenaShape *shape = NR_ARENA_SHAPE(item);
- if (!shape->curve) return item->state;
-
- cairo_t *ct = nr_create_cairo_context (area, pb);
-
- if (!ct)
- return item->state;
-
- cairo_set_source_rgba(ct, 0, 0, 0, 1);
-
- cairo_new_path(ct);
-
- feed_pathvector_to_cairo (ct, shape->curve->get_pathvector(), shape->ctm, (area)->upgrade(), false, 0);
-
- cairo_fill(ct);
-
- cairo_surface_t *cst = cairo_get_target(ct);
- cairo_destroy (ct);
- cairo_surface_finish (cst);
- cairo_surface_destroy (cst);
-
- pb->empty = FALSE;
-
- return item->state;
-}
-#endif //defined(DEADCODE) && !defined(DEADCODE)
-
-
static guint
-nr_arena_shape_clip(NRArenaItem *item, NRRectL *area, NRPixBlock *pb)
+nr_arena_shape_clip(cairo_t *ct, NRArenaItem *item, NRRectL *area)
{
- //return cairo_arena_shape_clip(item, area, pb);
-
+ // NOTE: for now this is incorrect, because it doesn't honor clip-rule,
+ // and will be incorrect for nested clipping paths.
NRArenaShape *shape = NR_ARENA_SHAPE(item);
if (!shape->curve) return item->state;
- if ( shape->delayed_shp || shape->fill_shp == NULL) { // we need a fill shape no matter what
- if ( nr_rect_l_test_intersect_ptr(area, &item->bbox) ) {
- NRGC tempGC(NULL);
- tempGC.transform=shape->ctm;
- shape->delayed_shp = false;
- nr_arena_shape_update_fill(shape, &tempGC, &pb->visible_area, true);
- } else {
- return item->state;
- }
- }
-
- if ( shape->fill_shp ) {
- NRPixBlock m;
-
- /* fixme: We can OR in one step (Lauris) */
- nr_pixblock_setup_fast(&m, NR_PIXBLOCK_MODE_A8, area->x0, area->y0, area->x1, area->y1, TRUE);
-
- // if memory allocation failed, abort
- if (m.size != NR_PIXBLOCK_SIZE_TINY && m.data.px == NULL) {
- nr_pixblock_release (&m);
- return (item->state);
- }
-
- m.visible_area = pb->visible_area;
- nr_pixblock_render_shape_mask_or(m,shape->fill_shp);
-
- for (int y = area->y0; y < area->y1; y++) {
- unsigned char *s, *d;
- s = NR_PIXBLOCK_PX(&m) + (y - area->y0) * m.rs;
- d = NR_PIXBLOCK_PX(pb) + (y - area->y0) * pb->rs;
- for (int x = area->x0; x < area->x1; x++) {
- *d = NR_COMPOSEA_111(*s, *d);
- d ++;
- s ++;
- }
- }
- nr_pixblock_release(&m);
- pb->empty = FALSE;
- }
+ cairo_save(ct);
+ ink_cairo_transform(ct, shape->ctm);
+ feed_pathvector_to_cairo(ct, shape->curve->get_pathvector());
+ cairo_restore(ct);
return item->state;
}
@@ -1107,17 +436,17 @@ nr_arena_shape_pick(NRArenaItem *item, Geom::Point p, double delta, unsigned int
double width;
if (outline) {
width = 0.5;
- } else if (shape->_stroke.paint.type() != NRArenaShape::Paint::NONE && shape->_stroke.opacity > 1e-3) {
+ } else if (shape->nrstyle.stroke.type != NRStyle::PAINT_NONE && shape->nrstyle.stroke.opacity > 1e-3) {
float const scale = shape->ctm.descrim();
- width = MAX(0.125, shape->_stroke.width * scale) / 2;
+ width = MAX(0.125, shape->nrstyle.stroke_width * scale) / 2;
} else {
width = 0;
}
- double dist = NR_HUGE;
+ double dist = Geom::infinity();
int wind = 0;
- bool needfill = (shape->_fill.paint.type() != NRArenaShape::Paint::NONE
- && shape->_fill.opacity > 1e-3 && !outline);
+ bool needfill = (shape->nrstyle.fill.type != NRStyle::PAINT_NONE
+ && shape->nrstyle.fill.opacity > 1e-3 && !outline);
if (item->arena->canvasarena) {
Geom::Rect viewbox = item->arena->canvasarena->item.canvas->getViewbox();
@@ -1184,18 +513,6 @@ void nr_arena_shape_set_path(NRArenaShape *shape, SPCurve *curve,bool justTrans)
g_return_if_fail(shape != NULL);
g_return_if_fail(NR_IS_ARENA_SHAPE(shape));
- if ( justTrans == false ) {
- // dirty cached versions
- if ( shape->cached_fill ) {
- delete shape->cached_fill;
- shape->cached_fill=NULL;
- }
- if ( shape->cached_stroke ) {
- delete shape->cached_stroke;
- shape->cached_stroke=NULL;
- }
- }
-
nr_arena_item_request_render(NR_ARENA_ITEM(shape));
if (shape->curve) {
@@ -1211,61 +528,6 @@ void nr_arena_shape_set_path(NRArenaShape *shape, SPCurve *curve,bool justTrans)
nr_arena_item_request_update(NR_ARENA_ITEM(shape), NR_ARENA_ITEM_STATE_ALL, FALSE);
}
-void NRArenaShape::setFill(SPPaintServer *server) {
- _fill.paint.set(server);
- _invalidateCachedFill();
-}
-
-void NRArenaShape::setFill(SPColor const &color) {
- _fill.paint.set(color);
- _invalidateCachedFill();
-}
-
-void NRArenaShape::setFillOpacity(double opacity) {
- _fill.opacity = opacity;
- _invalidateCachedFill();
-}
-
-void NRArenaShape::setFillRule(NRArenaShape::FillRule rule) {
- _fill.rule = rule;
- _invalidateCachedFill();
-}
-
-void NRArenaShape::setStroke(SPPaintServer *server) {
- _stroke.paint.set(server);
- _invalidateCachedStroke();
-}
-
-void NRArenaShape::setStroke(SPColor const &color) {
- _stroke.paint.set(color);
- _invalidateCachedStroke();
-}
-
-void NRArenaShape::setStrokeOpacity(double opacity) {
- _stroke.opacity = opacity;
- _invalidateCachedStroke();
-}
-
-void NRArenaShape::setStrokeWidth(double width) {
- _stroke.width = width;
- _invalidateCachedStroke();
-}
-
-void NRArenaShape::setMitreLimit(double limit) {
- _stroke.mitre_limit = limit;
- _invalidateCachedStroke();
-}
-
-void NRArenaShape::setLineCap(NRArenaShape::CapType cap) {
- _stroke.cap = cap;
- _invalidateCachedStroke();
-}
-
-void NRArenaShape::setLineJoin(NRArenaShape::JoinType join) {
- _stroke.join = join;
- _invalidateCachedStroke();
-}
-
/** nr_arena_shape_set_style
*
* Unrefs any existing style and ref's to the given one, then requests an update of the arena
@@ -1275,81 +537,13 @@ nr_arena_shape_set_style(NRArenaShape *shape, SPStyle *style)
{
g_return_if_fail(shape != NULL);
g_return_if_fail(NR_IS_ARENA_SHAPE(shape));
+ g_return_if_fail(style != NULL);
- if (style) sp_style_ref(style);
+ sp_style_ref(style);
if (shape->style) sp_style_unref(shape->style);
shape->style = style;
- if ( style->fill.isPaintserver() ) {
- shape->setFill(style->getFillPaintServer());
- } else if ( style->fill.isColor() ) {
- shape->setFill(style->fill.value.color);
- } else if ( style->fill.isNone() ) {
- shape->setFill(NULL);
- } else {
- g_assert_not_reached();
- }
- shape->setFillOpacity(SP_SCALE24_TO_FLOAT(style->fill_opacity.value));
- switch (style->fill_rule.computed) {
- case SP_WIND_RULE_EVENODD: {
- shape->setFillRule(NRArenaShape::EVEN_ODD);
- break;
- }
- case SP_WIND_RULE_NONZERO: {
- shape->setFillRule(NRArenaShape::NONZERO);
- break;
- }
- default: {
- g_assert_not_reached();
- }
- }
-
- if ( style->stroke.isPaintserver() ) {
- shape->setStroke(style->getStrokePaintServer());
- } else if ( style->stroke.isColor() ) {
- shape->setStroke(style->stroke.value.color);
- } else if ( style->stroke.isNone() ) {
- shape->setStroke(NULL);
- } else {
- g_assert_not_reached();
- }
- shape->setStrokeWidth(style->stroke_width.computed);
- shape->setStrokeOpacity(SP_SCALE24_TO_FLOAT(style->stroke_opacity.value));
- switch (style->stroke_linecap.computed) {
- case SP_STROKE_LINECAP_ROUND: {
- shape->setLineCap(NRArenaShape::ROUND_CAP);
- break;
- }
- case SP_STROKE_LINECAP_SQUARE: {
- shape->setLineCap(NRArenaShape::SQUARE_CAP);
- break;
- }
- case SP_STROKE_LINECAP_BUTT: {
- shape->setLineCap(NRArenaShape::BUTT_CAP);
- break;
- }
- default: {
- g_assert_not_reached();
- }
- }
- switch (style->stroke_linejoin.computed) {
- case SP_STROKE_LINEJOIN_ROUND: {
- shape->setLineJoin(NRArenaShape::ROUND_JOIN);
- break;
- }
- case SP_STROKE_LINEJOIN_BEVEL: {
- shape->setLineJoin(NRArenaShape::BEVEL_JOIN);
- break;
- }
- case SP_STROKE_LINEJOIN_MITER: {
- shape->setLineJoin(NRArenaShape::MITRE_JOIN);
- break;
- }
- default: {
- g_assert_not_reached();
- }
- }
- shape->setMitreLimit(style->stroke_miterlimit.value);
+ shape->nrstyle.set(style);
//if shape has a filter
if (style->filter.set && style->getFilter()) {
@@ -1395,118 +589,6 @@ void NRArenaShape::setPaintBox(Geom::Rect const &pbox)
nr_arena_item_request_update(this, NR_ARENA_ITEM_STATE_ALL, FALSE);
}
-static void
-shape_run_A8_OR(raster_info &dest,void */*data*/,int st,float vst,int en,float ven)
-{
- if ( st >= en ) return;
- if ( vst < 0 ) vst=0;
- if ( vst > 1 ) vst=1;
- if ( ven < 0 ) ven=0;
- if ( ven > 1 ) ven=1;
- float sv=vst;
- float dv=ven-vst;
- int len=en-st;
- unsigned char* d=(unsigned char*)dest.buffer;
- d+=(st-dest.startPix);
- if ( fabs(dv) < 0.001 ) {
- if ( vst > 0.999 ) {
- /* Simple copy */
- while (len > 0) {
- d[0] = 255;
- d += 1;
- len -= 1;
- }
- } else {
- sv*=256;
- unsigned int c0_24=(int)sv;
- c0_24&=0xFF;
- while (len > 0) {
- /* Draw */
- d[0] = NR_COMPOSEA_111(c0_24,d[0]);
- d += 1;
- len -= 1;
- }
- }
- } else {
- if ( en <= st+1 ) {
- sv=0.5*(vst+ven);
- sv*=256;
- unsigned int c0_24=(int)sv;
- c0_24&=0xFF;
- /* Draw */
- d[0] = NR_COMPOSEA_111(c0_24,d[0]);
- } else {
- dv/=len;
- sv+=0.5*dv; // correction trapezoidale
- sv*=16777216;
- dv*=16777216;
- int c0_24 = static_cast<int>(CLAMP(sv, 0, 16777216));
- int s0_24 = static_cast<int>(dv);
- while (len > 0) {
- unsigned int ca;
- /* Draw */
- ca = c0_24 >> 16;
- if ( ca > 255 ) ca=255;
- d[0] = NR_COMPOSEA_111(ca,d[0]);
- d += 1;
- c0_24 += s0_24;
- c0_24 = CLAMP(c0_24, 0, 16777216);
- len -= 1;
- }
- }
- }
-}
-
-void nr_pixblock_render_shape_mask_or(NRPixBlock &m,Shape* theS)
-{
- theS->CalcBBox();
- float l = theS->leftX, r = theS->rightX, t = theS->topY, b = theS->bottomY;
- int il,ir,it,ib;
- il=(int)floor(l);
- ir=(int)ceil(r);
- it=(int)floor(t);
- ib=(int)ceil(b);
-
- if ( il >= m.area.x1 || ir <= m.area.x0 || it >= m.area.y1 || ib <= m.area.y0 ) return;
- if ( il < m.area.x0 ) il=m.area.x0;
- if ( it < m.area.y0 ) it=m.area.y0;
- if ( ir > m.area.x1 ) ir=m.area.x1;
- if ( ib > m.area.y1 ) ib=m.area.y1;
-
- /* This is the FloatLigne version. See svn (prior to Apr 2006) for versions using BitLigne or direct BitLigne. */
- int curPt;
- float curY;
- theS->BeginQuickRaster(curY, curPt);
-
- FloatLigne *theI = new FloatLigne();
- IntLigne *theIL = new IntLigne();
-
- theS->DirectQuickScan(curY, curPt, (float) it, true, 1.0);
-
- char *mdata = (char*)m.data.px;
- if ( m.size == NR_PIXBLOCK_SIZE_TINY ) mdata=(char*)m.data.p;
- uint32_t *ligStart = ((uint32_t*)(mdata + ((il - m.area.x0) + m.rs * (it - m.area.y0))));
- for (int y = it; y < ib; y++) {
- theI->Reset();
- theS->QuickScan(curY, curPt, ((float)(y+1)), theI, 1.0);
- theI->Flatten();
- theIL->Copy(theI);
-
- raster_info dest;
- dest.startPix=il;
- dest.endPix=ir;
- dest.sth=il;
- dest.stv=y;
- dest.buffer=ligStart;
- theIL->Raster(dest, NULL, shape_run_A8_OR);
- ligStart=((uint32_t*)(((char*)ligStart)+m.rs));
- }
- theS->EndQuickRaster();
- delete theI;
- delete theIL;
-}
-
-
/*
Local Variables:
mode:c++
diff --git a/src/display/nr-arena-shape.h b/src/display/nr-arena-shape.h
index e00993901..2ee0d24c8 100644
--- a/src/display/nr-arena-shape.h
+++ b/src/display/nr-arena-shape.h
@@ -17,133 +17,30 @@
#define NR_ARENA_SHAPE(obj) (NR_CHECK_INSTANCE_CAST ((obj), NR_TYPE_ARENA_SHAPE, NRArenaShape))
#define NR_IS_ARENA_SHAPE(obj) (NR_CHECK_INSTANCE_TYPE ((obj), NR_TYPE_ARENA_SHAPE))
-#include "display/canvas-bpath.h"
+#include <cairo.h>
+#include "display/display-forward.h"
#include "forward.h"
-#include "sp-paint-server.h"
#include "nr-arena-item.h"
-
-#include "../color.h"
-
-#include "../livarot/Shape.h"
+#include "nr-style.h"
NRType nr_arena_shape_get_type (void);
struct NRArenaShape : public NRArenaItem {
- class Paint {
- public:
- enum Type {
- NONE,
- COLOR,
- SERVER
- };
-
- Paint() : _type(NONE), _color(0), _server(NULL) {}
- Paint(Paint const &p) { _assign(p); }
- virtual ~Paint() { clear(); }
-
- Type type() const { return _type; }
- SPPaintServer *server() const { return _server; }
- SPColor const &color() const { return _color; }
-
- Paint &operator=(Paint const &p) {
- set(p);
- return *this;
- }
-
- void set(Paint const &p) {
- clear();
- _assign(p);
- }
- void set(SPColor const &color) {
- clear();
- _type = COLOR;
- _color = color;
- }
- void set(SPPaintServer *server) {
- clear();
- if (server) {
- _type = SERVER;
- _server = server;
- sp_object_ref(_server, NULL);
- }
- }
- void clear() {
- if ( _type == SERVER ) {
- sp_object_unref(_server, NULL);
- _server = NULL;
- }
- _type = NONE;
- }
-
- private:
- Type _type;
- SPColor _color;
- SPPaintServer *_server;
-
- void _assign(Paint const &p) {
- _type = p._type;
- _server = p._server;
- _color = p._color;
- if (_server) {
- sp_object_ref(_server, NULL);
- }
- }
- };
-
- enum FillRule {
- EVEN_ODD,
- NONZERO
- };
-
- enum CapType {
- ROUND_CAP,
- SQUARE_CAP,
- BUTT_CAP
- };
-
- enum JoinType {
- ROUND_JOIN,
- BEVEL_JOIN,
- MITRE_JOIN
- };
-
/* Shape data */
SPCurve *curve;
SPStyle *style;
+ NRStyle nrstyle;
NRRect paintbox;
- /* State data */
- Geom::Affine ctm;
-
- SPPainter *fill_painter;
- SPPainter *stroke_painter;
- // the 2 cached polygons, for rasterizations uses
- Shape *fill_shp;
- Shape *stroke_shp;
- // the stroke width of stroke_shp, to detect when it changes (on normal/outline switching) and rebuild
- float cached_width;
+
+ cairo_path_t *path;
+
// delayed_shp=true means the *_shp polygons are not computed yet
// they'll be computed on demand in *_render(), *_pick() or *_clip()
// the goal is to not uncross polygons that are outside the viewing region
bool delayed_shp;
// approximate bounding box, for the case when the polygons have been delayed
NRRectL approx_bbox;
- // cache for transformations: cached_fill and cached_stroke are
- // polygons computed for the cached_fctm and cache_sctm respectively
- // when the transformation changes interactively (tracked by the
- // SP_OBJECT_USER_MODIFIED_FLAG_B), we check if it's an isometry wrt
- // the cached ctm. if it's an isometry, just apply it to the cached
- // polygon to get the *_shp polygon. Otherwise, recompute so this
- // works fine for translation and rotation, but not scaling and
- // skewing
- Geom::Affine cached_fctm;
- Geom::Affine cached_sctm;
- NRRectL cached_farea;
- NRRectL cached_sarea;
- bool cached_fpartialy;
- bool cached_spartialy;
-
- Shape *cached_fill;
- Shape *cached_stroke;
+
/* Markers */
NRArenaItem *markers;
@@ -157,54 +54,7 @@ struct NRArenaShape : public NRArenaItem {
return obj;
}
- void setFill(SPPaintServer *server);
- void setFill(SPColor const &color);
- void setFillOpacity(double opacity);
- void setFillRule(FillRule rule);
-
- void setStroke(SPPaintServer *server);
- void setStroke(SPColor const &color);
- void setStrokeOpacity(double opacity);
- void setStrokeWidth(double width);
- void setLineCap(CapType cap);
- void setLineJoin(JoinType join);
- void setMitreLimit(double limit);
-
void setPaintBox(Geom::Rect const &pbox);
-
- void _invalidateCachedFill() {
- if (cached_fill) {
- delete cached_fill;
- cached_fill = NULL;
- }
- }
- void _invalidateCachedStroke() {
- if (cached_stroke) {
- delete cached_stroke;
- cached_stroke = NULL;
- }
- }
-
- struct Style {
- Style() : opacity(0.0) {}
- Paint paint;
- double opacity;
- };
- struct FillStyle : public Style {
- FillStyle() : rule(EVEN_ODD) {}
- FillRule rule;
- } _fill;
- struct StrokeStyle : public Style {
- StrokeStyle()
- : cap(ROUND_CAP), join(ROUND_JOIN),
- width(0.0), mitre_limit(0.0)
- {}
-
- CapType cap;
- JoinType join;
- double width;
- double mitre_limit;
- } _stroke;
};
struct NRArenaShapeClass {
diff --git a/src/display/nr-arena.cpp b/src/display/nr-arena.cpp
index 147269727..43edb6918 100644
--- a/src/display/nr-arena.cpp
+++ b/src/display/nr-arena.cpp
@@ -16,8 +16,6 @@
#include "nr-arena.h"
#include "nr-filter-gaussian.h"
#include "nr-filter-types.h"
-#include <libnr/nr-blit.h>
-#include "sp-paint-server.h"
#include "preferences.h"
#include "color.h"
@@ -135,41 +133,6 @@ nr_arena_request_render_rect (NRArena *arena, NRRectL *area)
}
}
-void
-nr_arena_render_paintserver_fill (NRPixBlock *pb, NRRectL *area, SPPainter *painter, float opacity, NRPixBlock *mask)
-{
- NRPixBlock cb, cb_opa;
- nr_pixblock_setup_fast (&cb, NR_PIXBLOCK_MODE_R8G8B8A8N, area->x0, area->y0, area->x1, area->y1, TRUE);
- nr_pixblock_setup_fast (&cb_opa, NR_PIXBLOCK_MODE_R8G8B8A8N, area->x0, area->y0, area->x1, area->y1, TRUE);
-
- // if memory allocation failed, abort
- if ((cb.size != NR_PIXBLOCK_SIZE_TINY && cb.data.px == NULL) || (cb_opa.size != NR_PIXBLOCK_SIZE_TINY && cb_opa.data.px == NULL)) {
- return;
- }
-
- cb.visible_area = pb->visible_area;
- cb_opa.visible_area = pb->visible_area;
-
- /* Need separate gradient buffer (lauris)*/
- // do the filling
- painter->fill (painter, &cb);
- cb.empty = FALSE;
-
- // do the fill-opacity and mask composite
- if (opacity < 1.0) {
- nr_blit_pixblock_pixblock_alpha (&cb_opa, &cb, (int) floor (255 * opacity));
- cb_opa.empty = FALSE;
- nr_blit_pixblock_pixblock_mask (pb, &cb_opa, mask);
- } else {
- nr_blit_pixblock_pixblock_mask (pb, &cb, mask);
- }
-
- pb->empty = FALSE;
-
- nr_pixblock_release (&cb);
- nr_pixblock_release (&cb_opa);
-}
-
/**
set arena to offscreen mode
rendering will be exact
diff --git a/src/display/nr-arena.h b/src/display/nr-arena.h
index 402bc198f..1c8216434 100644
--- a/src/display/nr-arena.h
+++ b/src/display/nr-arena.h
@@ -64,8 +64,6 @@ void nr_arena_request_update (NRArena *arena, NRArenaItem *item);
void nr_arena_request_render_rect (NRArena *arena, NRRectL *area);
void nr_arena_set_renderoffscreen (NRArena *arena);
-void nr_arena_render_paintserver_fill (NRPixBlock *pb, NRRectL *area, SPPainter *painter, float opacity, NRPixBlock *mask);
-
void nr_arena_separate_color_plates(guint32* rgba);
#endif
diff --git a/src/display/nr-filter-blend.cpp b/src/display/nr-filter-blend.cpp
index a0f074dc9..3cec479fa 100644
--- a/src/display/nr-filter-blend.cpp
+++ b/src/display/nr-filter-blend.cpp
@@ -15,15 +15,17 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "display/cairo-templates.h"
+#include "display/cairo-utils.h"
#include "display/nr-filter-blend.h"
-#include "display/nr-filter-pixops.h"
#include "display/nr-filter-primitive.h"
#include "display/nr-filter-slot.h"
#include "display/nr-filter-types.h"
-#include "display/nr-filter-units.h"
-#include "libnr/nr-pixblock.h"
-#include "libnr/nr-blit.h"
-#include "libnr/nr-pixops.h"
+#include "preferences.h"
namespace Inkscape {
namespace Filters {
@@ -42,77 +44,6 @@ namespace Filters {
* cb = Color (RGB) at a given pixel for image B - premultiplied
*/
-/*
- * These blending equations given in SVG standard are for color values
- * in the range 0..1. As these values are stored as unsigned char values,
- * they need some reworking. An unsigned char value can be thought as
- * 0.8 fixed point representation of color value. This is how I've
- * ended up with these equations here.
- */
-
-// Set alpha / opacity. This line is same for all the blending modes,
-// so let's save some copy-pasting.
-#define SET_ALPHA r[3] = NR_NORMALIZE_21((255 * 255) - (255 - a[3]) * (255 - b[3]))
-
-// cr = (1 - qa) * cb + ca
-inline void
-blend_normal(unsigned char *r, unsigned char const *a, unsigned char const *b)
-{
- r[0] = NR_COMPOSEPPP_1111(a[0],a[3],b[0]);
- r[1] = NR_COMPOSEPPP_1111(a[1],a[3],b[1]);
- r[2] = NR_COMPOSEPPP_1111(a[2],a[3],b[2]);
- SET_ALPHA;
-}
-
-// cr = (1-qa)*cb + (1-qb)*ca + ca*cb
-inline void
-blend_multiply(unsigned char *r, unsigned char const *a, unsigned char const *b)
-{
- r[0] = NR_NORMALIZE_21((255 - a[3]) * b[0] + (255 - b[3]) * a[0]
- + a[0] * b[0]);
- r[1] = NR_NORMALIZE_21((255 - a[3]) * b[1] + (255 - b[3]) * a[1]
- + a[1] * b[1]);
- r[2] = NR_NORMALIZE_21((255 - a[3]) * b[2] + (255 - b[3]) * a[2]
- + a[2] * b[2]);
- SET_ALPHA;
-}
-
-// cr = cb + ca - ca * cb
-inline void
-blend_screen(unsigned char *r, unsigned char const *a, unsigned char const *b)
-{
- r[0] = NR_NORMALIZE_21((b[0] + a[0]) * 255 - a[0] * b[0]);
- r[1] = NR_NORMALIZE_21((b[1] + a[1]) * 255 - a[1] * b[1]);
- r[2] = NR_NORMALIZE_21((b[2] + a[2]) * 255 - a[2] * b[2]);
- SET_ALPHA;
-}
-
-// cr = Min ((1 - qa) * cb + ca, (1 - qb) * ca + cb)
-inline void
-blend_darken(unsigned char *r, unsigned char const *a, unsigned char const *b)
-{
- r[0] = NR_NORMALIZE_21(std::min(NR_COMPOSEPPP_1112(a[0],a[3],b[0]),
- NR_COMPOSEPPP_1112(b[0],b[3],a[0])));
- r[1] = NR_NORMALIZE_21(std::min(NR_COMPOSEPPP_1112(a[1],a[3],b[1]),
- NR_COMPOSEPPP_1112(b[1],b[3],a[1])));
- r[2] = NR_NORMALIZE_21(std::min(NR_COMPOSEPPP_1112(a[2],a[3],b[2]),
- NR_COMPOSEPPP_1112(b[2],b[3],a[2])));
- SET_ALPHA;
-}
-
-// cr = Max ((1 - qa) * cb + ca, (1 - qb) * ca + cb)
-inline void
-blend_lighten(unsigned char *r, unsigned char const *a, unsigned char const *b)
-{
- r[0] = NR_NORMALIZE_21(std::max(NR_COMPOSEPPP_1112(a[0],a[3],b[0]),
- NR_COMPOSEPPP_1112(b[0],b[3],a[0])));
- r[1] = NR_NORMALIZE_21(std::max(NR_COMPOSEPPP_1112(a[1],a[3],b[1]),
- NR_COMPOSEPPP_1112(b[1],b[3],a[1])));
- r[2] = NR_NORMALIZE_21(std::max(NR_COMPOSEPPP_1112(a[2],a[3],b[2]),
- NR_COMPOSEPPP_1112(b[2],b[3],a[2])));
- SET_ALPHA;
-}
-
FilterBlend::FilterBlend()
: _blend_mode(BLEND_NORMAL),
_input2(NR_FILTER_SLOT_NOT_SET)
@@ -125,81 +56,144 @@ FilterPrimitive * FilterBlend::create() {
FilterBlend::~FilterBlend()
{}
-int FilterBlend::render(FilterSlot &slot, FilterUnits const & /*units*/) {
- NRPixBlock *in1 = slot.get(_input);
- NRPixBlock *in2 = slot.get(_input2);
- NRPixBlock *original_in1 = in1;
- NRPixBlock *original_in2 = in2;
- NRPixBlock *out;
-
- // Bail out if either one of source images is missing
- if (!in1 || !in2) {
- g_warning("Missing source image for feBlend (in=%d in2=%d)", _input, _input2);
- return 1;
- }
+// cr = (1-qa)*cb + (1-qb)*ca + ca*cb
+struct BlendMultiply {
+ guint32 operator()(guint32 in1, guint32 in2)
+ {
+ EXTRACT_ARGB32(in1, aa, ra, ga, ba)
+ EXTRACT_ARGB32(in2, ab, rb, gb, bb)
+
+ guint32 ao = 255*255 - (255-aa)*(255-ab); ao = (ao + 127) / 255;
+ guint32 ro = (255-aa)*rb + (255-ab)*ra + ra*rb; ro = (ro + 127) / 255;
+ guint32 go = (255-aa)*gb + (255-ab)*ga + ga*gb; go = (go + 127) / 255;
+ guint32 bo = (255-aa)*bb + (255-ab)*ba + ba*bb; bo = (bo + 127) / 255;
- out = new NRPixBlock;
- NRRectL out_area;
- nr_rect_l_union(&out_area, &in1->area, &in2->area);
- nr_pixblock_setup_fast(out, NR_PIXBLOCK_MODE_R8G8B8A8P,
- out_area.x0, out_area.y0, out_area.x1, out_area.y1,
- true);
-
- // Blending modes are defined for premultiplied RGBA values,
- // thus convert them to that format before blending
- if (in1->mode != NR_PIXBLOCK_MODE_R8G8B8A8P) {
- in1 = new NRPixBlock;
- nr_pixblock_setup_fast(in1, NR_PIXBLOCK_MODE_R8G8B8A8P,
- original_in1->area.x0, original_in1->area.y0,
- original_in1->area.x1, original_in1->area.y1,
- false);
- nr_blit_pixblock_pixblock(in1, original_in1);
+ ASSEMBLE_ARGB32(pxout, ao, ro, go, bo)
+ return pxout;
}
- if (in2->mode != NR_PIXBLOCK_MODE_R8G8B8A8P) {
- in2 = new NRPixBlock;
- nr_pixblock_setup_fast(in2, NR_PIXBLOCK_MODE_R8G8B8A8P,
- original_in2->area.x0, original_in2->area.y0,
- original_in2->area.x1, original_in2->area.y1,
- false);
- nr_blit_pixblock_pixblock(in2, original_in2);
+};
+
+// cr = cb + ca - ca * cb
+struct BlendScreen {
+ guint32 operator()(guint32 in1, guint32 in2)
+ {
+ EXTRACT_ARGB32(in1, aa, ra, ga, ba)
+ EXTRACT_ARGB32(in2, ab, rb, gb, bb)
+
+ guint32 ao = 255*255 - (255-aa)*(255-ab); ao = (ao + 127) / 255;
+ guint32 ro = 255*(rb + ra) - ra * rb; ro = (ro + 127) / 255;
+ guint32 go = 255*(gb + ga) - ga * gb; go = (go + 127) / 255;
+ guint32 bo = 255*(bb + ba) - ba * bb; bo = (bo + 127) / 255;
+
+ ASSEMBLE_ARGB32(pxout, ao, ro, go, bo)
+ return pxout;
}
+};
+
+// cr = Min ((1 - qa) * cb + ca, (1 - qb) * ca + cb)
+struct BlendDarken {
+ guint32 operator()(guint32 in1, guint32 in2)
+ {
+ EXTRACT_ARGB32(in1, aa, ra, ga, ba)
+ EXTRACT_ARGB32(in2, ab, rb, gb, bb)
+
+ guint32 ao = 255*255 - (255-aa)*(255-ab); ao = (ao + 127) / 255;
+ guint32 ro = std::min((255-aa)*rb + 255*ra, (255-ab)*ra + 255*rb); ro = (ro + 127) / 255;
+ guint32 go = std::min((255-aa)*gb + 255*ga, (255-ab)*ga + 255*gb); go = (go + 127) / 255;
+ guint32 bo = std::min((255-aa)*bb + 255*ba, (255-ab)*ba + 255*bb); bo = (bo + 127) / 255;
- /* pixops_mix is defined in display/nr-filter-pixops.h
- * It mixes the two input images with the function given as template
- * and places the result in output image.
- */
- switch (_blend_mode) {
- case BLEND_MULTIPLY:
- pixops_mix<blend_multiply>(*out, *in1, *in2);
- break;
- case BLEND_SCREEN:
- pixops_mix<blend_screen>(*out, *in1, *in2);
- break;
- case BLEND_DARKEN:
- pixops_mix<blend_darken>(*out, *in1, *in2);
- break;
- case BLEND_LIGHTEN:
- pixops_mix<blend_lighten>(*out, *in1, *in2);
- break;
- case BLEND_NORMAL:
- default:
- pixops_mix<blend_normal>(*out, *in1, *in2);
- break;
+ ASSEMBLE_ARGB32(pxout, ao, ro, go, bo)
+ return pxout;
}
+};
- if (in1 != original_in1) {
- nr_pixblock_release(in1);
- delete in1;
+// cr = Max ((1 - qa) * cb + ca, (1 - qb) * ca + cb)
+struct BlendLighten {
+ guint32 operator()(guint32 in1, guint32 in2)
+ {
+ EXTRACT_ARGB32(in1, aa, ra, ga, ba)
+ EXTRACT_ARGB32(in2, ab, rb, gb, bb)
+
+ guint32 ao = 255*255 - (255-aa)*(255-ab); ao = (ao + 127) / 255;
+ guint32 ro = std::max((255-aa)*rb + 255*ra, (255-ab)*ra + 255*rb); ro = (ro + 127) / 255;
+ guint32 go = std::max((255-aa)*gb + 255*ga, (255-ab)*ga + 255*gb); go = (go + 127) / 255;
+ guint32 bo = std::max((255-aa)*bb + 255*ba, (255-ab)*ba + 255*bb); bo = (bo + 127) / 255;
+
+ ASSEMBLE_ARGB32(pxout, ao, ro, go, bo)
+ return pxout;
}
- if (in2 != original_in2) {
- nr_pixblock_release(in2);
- delete in2;
+};
+
+/*
+struct BlendAlpha
+static inline void blend_alpha(guint32 in1, guint32 in2, guint32 *out)
+{
+ EXTRACT_ARGB32(in1, a1, a2, a3, a4);
+ EXTRACT_ARGB32(in2, b1, b2, b3, b4);
+
+ guint32 o1 = 255*255 - (255-a1)*(255-b1); o1 = (o1+127) / 255;
+ guint32 o2 = 255*255 - (255-a2)*(255-b2); o2 = (o2+127) / 255;
+ guint32 o3 = 255*255 - (255-a3)*(255-b3); o3 = (o3+127) / 255;
+ guint32 o4 = 255*255 - (255-a4)*(255-b4); o4 = (o4+127) / 255;
+
+ ASSEMBLE_ARGB32(pxout, o1, o2, o3, o4);
+ *out = pxout;
+}
+*/
+
+void FilterBlend::render_cairo(FilterSlot &slot)
+{
+ cairo_surface_t *input1 = slot.getcairo(_input);
+ cairo_surface_t *input2 = slot.getcairo(_input2);
+
+ cairo_content_t ct1 = cairo_surface_get_content(input1);
+ cairo_content_t ct2 = cairo_surface_get_content(input2);
+
+ // input2 is the "background" image
+ // out should be ARGB32 if any of the inputs is ARGB32
+ cairo_surface_t *out = ink_cairo_surface_create_output(input1, input2);
+
+ if ((ct1 == CAIRO_CONTENT_ALPHA && ct2 == CAIRO_CONTENT_ALPHA)
+ || _blend_mode == BLEND_NORMAL)
+ {
+ ink_cairo_surface_blit(input2, out);
+ cairo_t *out_ct = cairo_create(out);
+ cairo_set_source_surface(out_ct, input1, 0, 0);
+ cairo_paint(out_ct);
+ cairo_destroy(out_ct);
+ } else {
+ // blend mode != normal and at least 1 surface is not pure alpha
+
+ // TODO: convert to Cairo blending operators once we start using the 1.10 series
+ switch (_blend_mode) {
+ case BLEND_MULTIPLY:
+ ink_cairo_surface_blend(input1, input2, out, BlendMultiply());
+ break;
+ case BLEND_SCREEN:
+ ink_cairo_surface_blend(input1, input2, out, BlendScreen());
+ break;
+ case BLEND_DARKEN:
+ ink_cairo_surface_blend(input1, input2, out, BlendDarken());
+ break;
+ case BLEND_LIGHTEN:
+ ink_cairo_surface_blend(input1, input2, out, BlendLighten());
+ break;
+ case BLEND_NORMAL:
+ default:
+ // this was handled before
+ g_assert_not_reached();
+ break;
+ }
}
- out->empty = FALSE;
slot.set(_output, out);
+ cairo_surface_destroy(out);
+}
- return 0;
+bool FilterBlend::can_handle_affine(Geom::Affine const &)
+{
+ // blend is a per-pixel primitive and is immutable under transformations
+ return true;
}
void FilterBlend::set_input(int slot) {
diff --git a/src/display/nr-filter-blend.h b/src/display/nr-filter-blend.h
index 254653566..64b3c9284 100644
--- a/src/display/nr-filter-blend.h
+++ b/src/display/nr-filter-blend.h
@@ -18,8 +18,6 @@
*/
#include "display/nr-filter-primitive.h"
-#include "display/nr-filter-slot.h"
-#include "display/nr-filter-units.h"
namespace Inkscape {
namespace Filters {
@@ -39,7 +37,8 @@ public:
static FilterPrimitive *create();
virtual ~FilterBlend();
- virtual int render(FilterSlot &slot, FilterUnits const &units);
+ virtual void render_cairo(FilterSlot &slot);
+ virtual bool can_handle_affine(Geom::Affine const &);
virtual void set_input(int slot);
virtual void set_input(int input, int slot);
diff --git a/src/display/nr-filter-colormatrix.cpp b/src/display/nr-filter-colormatrix.cpp
index 54d5dfd69..7eb2fa2e9 100644
--- a/src/display/nr-filter-colormatrix.cpp
+++ b/src/display/nr-filter-colormatrix.cpp
@@ -10,11 +10,13 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include "display/nr-filter-colormatrix.h"
-#include "display/nr-filter-units.h"
-#include "display/nr-filter-utils.h"
-#include "libnr/nr-blit.h"
#include <math.h>
+#include <algorithm>
+#include "display/cairo-templates.h"
+#include "display/cairo-utils.h"
+#include "display/nr-filter-colormatrix.h"
+#include "display/nr-filter-slot.h"
+#include <2geom/math-utils.h>
namespace Inkscape {
namespace Filters {
@@ -30,169 +32,160 @@ FilterPrimitive * FilterColorMatrix::create() {
FilterColorMatrix::~FilterColorMatrix()
{}
-int FilterColorMatrix::render(FilterSlot &slot, FilterUnits const &/*units*/) {
- NRPixBlock *in = slot.get(_input);
- if (!in) {
- g_warning("Missing source image for feColorMatrix (in=%d)", _input);
- return 1;
+struct ColorMatrixMatrix {
+ ColorMatrixMatrix(std::vector<double> const &values) {
+ unsigned limit = std::min(static_cast<size_t>(20), values.size());
+ for (unsigned i = 0; i < limit; ++i) {
+ if (i % 5 == 4) {
+ _v[i] = round(values[i]*255*255);
+ } else {
+ _v[i] = round(values[i]*255);
+ }
+ }
+ for (unsigned i = limit; i < 20; ++i) {
+ _v[i] = 0;
+ }
}
- NRPixBlock *out = new NRPixBlock;
- if ((type==COLORMATRIX_SATURATE || type==COLORMATRIX_HUEROTATE) && in->mode != NR_PIXBLOCK_MODE_R8G8B8A8N) {
- // saturate and hueRotate do not touch the alpha channel and are linear (per-pixel) operations, so no premultiplied -> non-premultiplied operation is necessary
- nr_pixblock_setup_fast(out, NR_PIXBLOCK_MODE_R8G8B8A8P,
- in->area.x0, in->area.y0, in->area.x1, in->area.y1,
- true);
- } else {
- nr_pixblock_setup_fast(out, NR_PIXBLOCK_MODE_R8G8B8A8N,
- in->area.x0, in->area.y0, in->area.x1, in->area.y1,
- true);
+ guint32 operator()(guint32 in) {
+ EXTRACT_ARGB32(in, a, r, g, b)
+ // we need to un-premultiply alpha values for this type of matrix
+ // TODO: unpremul can be ignored if there is an identity mapping on the alpha channel
+ if (a != 0) {
+ r = unpremul_alpha(r, a);
+ g = unpremul_alpha(g, a);
+ b = unpremul_alpha(b, a);
+ }
+
+ gint32 ro = r*_v[0] + g*_v[1] + b*_v[2] + a*_v[3] + _v[4];
+ gint32 go = r*_v[5] + g*_v[6] + b*_v[7] + a*_v[8] + _v[9];
+ gint32 bo = r*_v[10] + g*_v[11] + b*_v[12] + a*_v[13] + _v[14];
+ gint32 ao = r*_v[15] + g*_v[16] + b*_v[17] + a*_v[18] + _v[19];
+ ro = (pxclamp(ro, 0, 255*255) + 127) / 255;
+ go = (pxclamp(go, 0, 255*255) + 127) / 255;
+ bo = (pxclamp(bo, 0, 255*255) + 127) / 255;
+ ao = (pxclamp(ao, 0, 255*255) + 127) / 255;
+
+ ro = premul_alpha(ro, ao);
+ go = premul_alpha(go, ao);
+ bo = premul_alpha(bo, ao);
+
+ ASSEMBLE_ARGB32(pxout, ao, ro, go, bo)
+ return pxout;
+ }
+private:
+ gint32 _v[20];
+};
+
+struct ColorMatrixSaturate {
+ ColorMatrixSaturate(double v_in) {
+ // clamp parameter instead of clamping color values
+ double v = CLAMP(v_in, 0.0, 1.0);
+ _v[0] = 0.213+0.787*v; _v[1] = 0.715-0.715*v; _v[2] = 0.072-0.072*v;
+ _v[3] = 0.213-0.213*v; _v[4] = 0.715+0.285*v; _v[5] = 0.072-0.072*v;
+ _v[6] = 0.213-0.213*v; _v[7] = 0.715-0.715*v; _v[8] = 0.072+0.928*v;
}
- // this primitive is defined for non-premultiplied RGBA values,
- // thus convert them to that format
- // However, since not all operations care, the input is only transformed if necessary.
- bool free_in_on_exit = false;
- if (in->mode != out->mode) {
- NRPixBlock *original_in = in;
- in = new NRPixBlock;
- nr_pixblock_setup_fast(in, out->mode,
- original_in->area.x0, original_in->area.y0,
- original_in->area.x1, original_in->area.y1,
- true);
- nr_blit_pixblock_pixblock(in, original_in);
- free_in_on_exit = true;
+ guint32 operator()(guint32 in) {
+ EXTRACT_ARGB32(in, a, r, g, b)
+
+ // Note: this cannot be done in fixed point, because the loss of precision
+ // causes overflow for some values of v
+ guint32 ro = r*_v[0] + g*_v[1] + b*_v[2] + 0.5;
+ guint32 go = r*_v[3] + g*_v[4] + b*_v[5] + 0.5;
+ guint32 bo = r*_v[6] + g*_v[7] + b*_v[8] + 0.5;
+
+ ASSEMBLE_ARGB32(pxout, a, ro, go, bo)
+ return pxout;
+ }
+private:
+ double _v[9];
+};
+
+struct ColorMatrixHueRotate {
+ ColorMatrixHueRotate(double v) {
+ double sinhue, coshue;
+ Geom::sincos(v * M_PI/180.0, sinhue, coshue);
+
+ _v[0] = round((0.213 +0.787*coshue -0.213*sinhue)*255);
+ _v[1] = round((0.715 -0.715*coshue -0.715*sinhue)*255);
+ _v[2] = round((0.072 -0.072*coshue +0.928*sinhue)*255);
+
+ _v[3] = round((0.213 -0.213*coshue +0.143*sinhue)*255);
+ _v[4] = round((0.715 +0.285*coshue +0.140*sinhue)*255);
+ _v[5] = round((0.072 -0.072*coshue -0.283*sinhue)*255);
+
+ _v[6] = round((0.213 -0.213*coshue -0.787*sinhue)*255);
+ _v[7] = round((0.715 -0.715*coshue +0.715*sinhue)*255);
+ _v[8] = round((0.072 +0.928*coshue +0.072*sinhue)*255);
+ }
+ guint32 operator()(guint32 in) {
+ EXTRACT_ARGB32(in, a, r, g, b)
+ gint32 maxpx = a*255;
+ gint32 ro = r*_v[0] + g*_v[1] + b*_v[2];
+ gint32 go = r*_v[3] + g*_v[4] + b*_v[5];
+ gint32 bo = r*_v[6] + g*_v[7] + b*_v[8];
+ ro = (pxclamp(ro, 0, maxpx) + 127) / 255;
+ go = (pxclamp(go, 0, maxpx) + 127) / 255;
+ bo = (pxclamp(bo, 0, maxpx) + 127) / 255;
+
+ ASSEMBLE_ARGB32(pxout, a, ro, go, bo)
+ return pxout;
+ }
+private:
+ gint32 _v[9];
+};
+
+struct ColorMatrixLuminanceToAlpha {
+ guint32 operator()(guint32 in) {
+ // original computation in double: r*0.2125 + g*0.7154 + b*0.0721
+ EXTRACT_ARGB32(in, a, r, g, b)
+ // unpremultiply color values
+ if (a != 0) {
+ r = unpremul_alpha(r, a);
+ g = unpremul_alpha(g, a);
+ b = unpremul_alpha(b, a);
+ }
+ guint32 ao = r*54 + g*182 + b*18;
+ return ((ao + 127) / 255) << 24;
}
+};
- unsigned char *in_data = NR_PIXBLOCK_PX(in);
- unsigned char *out_data = NR_PIXBLOCK_PX(out);
- unsigned char r,g,b,a;
- int x,y,x0,y0,x1,y1,i;
- x0=in->area.x0;
- y0=in->area.y0;
- x1=in->area.x1;
- y1=in->area.y1;
-
- switch(type){
- case COLORMATRIX_MATRIX:
- {
- if (values.size()!=20) {
- g_warning("ColorMatrix: values parameter error. Wrong size: %i.", static_cast<int>(values.size()));
- return -1;
- }
- double a04 = 255*values[4];
- double a14 = 255*values[9];
- double a24 = 255*values[14];
- double a34 = 255*values[19];
- for (x=x0;x<x1;x++){
- for (y=y0;y<y1;y++){
- i = ((x-x0) + (x1-x0)*(y-y0))*4;
- r = in_data[i];
- g = in_data[i+1];
- b = in_data[i+2];
- a = in_data[i+3];
- out_data[i] = CLAMP_D_TO_U8( r*values[0] + g*values[1] + b*values[2] + a*values[3] + a04 ); // CLAMP includes rounding!
- out_data[i+1] = CLAMP_D_TO_U8( r*values[5] + g*values[6] + b*values[7] + a*values[8] + a14 );
- out_data[i+2] = CLAMP_D_TO_U8( r*values[10] + g*values[11] + b*values[12] + a*values[13] + a24 );
- out_data[i+3] = CLAMP_D_TO_U8( r*values[15] + g*values[16] + b*values[17] + a*values[18] + a34 );
- }
- }
- }
- break;
- case COLORMATRIX_SATURATE:
- {
- double v = std::max(0.0,std::min(1.0,value)); // The standard says it should be between 0 and 1, and clamping it here makes it unnecessary to clamp the color values.
- double a00 = 0.213+0.787*v, a01 = 0.715-0.715*v, a02 = 0.072-0.072*v;
- double a10 = 0.213-0.213*v, a11 = 0.715+0.285*v, a12 = 0.072-0.072*v;
- double a20 = 0.213-0.213*v, a21 = 0.715-0.715*v, a22 = 0.072+0.928*v;
- for (x=x0;x<x1;x++){
- for (y=y0;y<y1;y++){
- i = ((x-x0) + (x1-x0)*(y-y0))*4;
- r = in_data[i];
- g = in_data[i+1];
- b = in_data[i+2];
- a = in_data[i+3];
- out_data[i] = static_cast<unsigned char>( r*a00 + g*a01 + b*a02 + .5 );
- out_data[i+1] = static_cast<unsigned char>( r*a10 + g*a11 + b*a12 + .5 );
- out_data[i+2] = static_cast<unsigned char>( r*a20 + g*a21 + b*a22 + .5 );
- out_data[i+3] = a;
- }
- }
- }
- break;
- case COLORMATRIX_HUEROTATE:
- {
- double coshue = cos(value * M_PI/180.0);
- double sinhue = sin(value * M_PI/180.0);
- double a00 = 0.213 + coshue*( 0.787) + sinhue*(-0.213);
- double a01 = 0.715 + coshue*(-0.715) + sinhue*(-0.715);
- double a02 = 0.072 + coshue*(-0.072) + sinhue*( 0.928);
- double a10 = 0.213 + coshue*(-0.213) + sinhue*( 0.143);
- double a11 = 0.715 + coshue*( 0.285) + sinhue*( 0.140);
- double a12 = 0.072 + coshue*(-0.072) + sinhue*(-0.283);
- double a20 = 0.213 + coshue*(-0.213) + sinhue*(-0.787);
- double a21 = 0.715 + coshue*(-0.715) + sinhue*( 0.715);
- double a22 = 0.072 + coshue*( 0.928) + sinhue*( 0.072);
- if (in->mode==NR_PIXBLOCK_MODE_R8G8B8A8P) {
- // Although it does not change the alpha channel, it can give "out-of-bound" results, and in this case the bound is determined by the alpha channel
- for (x=x0;x<x1;x++){
- for (y=y0;y<y1;y++){
- i = ((x-x0) + (x1-x0)*(y-y0))*4;
- r = in_data[i];
- g = in_data[i+1];
- b = in_data[i+2];
- a = in_data[i+3];
-
- out_data[i] = static_cast<unsigned char>(std::max(0.0,std::min((double)a, r*a00 + g*a01 + b*a02 + .5 )));
- out_data[i+1] = static_cast<unsigned char>(std::max(0.0,std::min((double)a, r*a10 + g*a11 + b*a12 + .5 )));
- out_data[i+2] = static_cast<unsigned char>(std::max(0.0,std::min((double)a, r*a20 + g*a21 + b*a22 + .5 )));
- out_data[i+3] = a;
- }
- }
- } else {
- for (x=x0;x<x1;x++){
- for (y=y0;y<y1;y++){
- i = ((x-x0) + (x1-x0)*(y-y0))*4;
- r = in_data[i];
- g = in_data[i+1];
- b = in_data[i+2];
- a = in_data[i+3];
-
- out_data[i] = CLAMP_D_TO_U8( r*a00 + g*a01 + b*a02);
- out_data[i+1] = CLAMP_D_TO_U8( r*a10 + g*a11 + b*a12);
- out_data[i+2] = CLAMP_D_TO_U8( r*a20 + g*a21 + b*a22);
- out_data[i+3] = a;
- }
- }
- }
- }
- break;
- case COLORMATRIX_LUMINANCETOALPHA:
- for (x=x0;x<x1;x++){
- for (y=y0;y<y1;y++){
- i = ((x-x0) + (x1-x0)*(y-y0))*4;
- r = in_data[i];
- g = in_data[i+1];
- b = in_data[i+2];
- out_data[i] = 0;
- out_data[i+1] = 0;
- out_data[i+2] = 0;
- out_data[i+3] = static_cast<unsigned char>( r*0.2125 + g*0.7154 + b*0.0721 + .5 );
- }
- }
- break;
- case COLORMATRIX_ENDTYPE:
- break;
+void FilterColorMatrix::render_cairo(FilterSlot &slot)
+{
+ cairo_surface_t *input = slot.getcairo(_input);
+ cairo_surface_t *out = NULL;
+ if (type == COLORMATRIX_LUMINANCETOALPHA) {
+ out = ink_cairo_surface_create_same_size(input, CAIRO_CONTENT_ALPHA);
+ } else {
+ out = ink_cairo_surface_create_identical(input);
}
- if (free_in_on_exit) {
- nr_pixblock_release(in);
- delete in;
+ switch (type) {
+ case COLORMATRIX_MATRIX:
+ ink_cairo_surface_filter(input, out, ColorMatrixMatrix(values));
+ break;
+ case COLORMATRIX_SATURATE:
+ ink_cairo_surface_filter(input, out, ColorMatrixSaturate(value));
+ break;
+ case COLORMATRIX_HUEROTATE:
+ ink_cairo_surface_filter(input, out, ColorMatrixHueRotate(value));
+ break;
+ case COLORMATRIX_LUMINANCETOALPHA:
+ ink_cairo_surface_filter(input, out, ColorMatrixLuminanceToAlpha());
+ break;
+ case COLORMATRIX_ENDTYPE:
+ default:
+ break;
}
- out->empty = FALSE;
slot.set(_output, out);
- return 0;
+ cairo_surface_destroy(out);
+}
+
+bool FilterColorMatrix::can_handle_affine(Geom::Affine const &)
+{
+ return true;
}
void FilterColorMatrix::area_enlarge(NRRectL &/*area*/, Geom::Affine const &/*trans*/)
@@ -207,7 +200,7 @@ void FilterColorMatrix::set_value(gdouble v){
value = v;
}
-void FilterColorMatrix::set_values(std::vector<gdouble> &v){
+void FilterColorMatrix::set_values(std::vector<gdouble> const &v){
values = v;
}
diff --git a/src/display/nr-filter-colormatrix.h b/src/display/nr-filter-colormatrix.h
index 7a2395f5d..df851e0aa 100644
--- a/src/display/nr-filter-colormatrix.h
+++ b/src/display/nr-filter-colormatrix.h
@@ -12,14 +12,15 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
+#include <vector>
+#include <2geom/forward.h>
#include "display/nr-filter-primitive.h"
-#include "display/nr-filter-slot.h"
-#include "display/nr-filter-units.h"
-#include<vector>
namespace Inkscape {
namespace Filters {
+class FilterSlot;
+
enum FilterColorMatrixType {
COLORMATRIX_MATRIX,
COLORMATRIX_SATURATE,
@@ -34,11 +35,13 @@ public:
static FilterPrimitive *create();
virtual ~FilterColorMatrix();
- virtual int render(FilterSlot &slot, FilterUnits const &units);
+ virtual void render_cairo(FilterSlot &slot);
+ virtual bool can_handle_affine(Geom::Affine const &);
virtual void area_enlarge(NRRectL &area, Geom::Affine const &trans);
+
virtual void set_type(FilterColorMatrixType type);
virtual void set_value(gdouble value);
- virtual void set_values(std::vector<gdouble> &values);
+ virtual void set_values(std::vector<gdouble> const &values);
private:
std::vector<gdouble> values;
gdouble value;
diff --git a/src/display/nr-filter-component-transfer.cpp b/src/display/nr-filter-component-transfer.cpp
index 3fe8cbf4a..80bc07df8 100644
--- a/src/display/nr-filter-component-transfer.cpp
+++ b/src/display/nr-filter-component-transfer.cpp
@@ -10,13 +10,11 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include "display/nr-filter-component-transfer.h"
-#include "display/nr-filter-units.h"
-#include "display/nr-filter-utils.h"
-#include "libnr/nr-pixblock.h"
-#include "libnr/nr-blit.h"
-#include "libnr/nr-pixops.h"
#include <math.h>
+#include "display/cairo-templates.h"
+#include "display/cairo-utils.h"
+#include "display/nr-filter-component-transfer.h"
+#include "display/nr-filter-slot.h"
namespace Inkscape {
namespace Filters {
@@ -32,170 +30,278 @@ FilterPrimitive * FilterComponentTransfer::create() {
FilterComponentTransfer::~FilterComponentTransfer()
{}
-int FilterComponentTransfer::render(FilterSlot &slot, FilterUnits const &/*units*/) {
- NRPixBlock *in = slot.get(_input);
+struct ComponentTransfer {
+ ComponentTransfer(guint32 color)
+ : _shift(color * 8)
+ , _mask(0xff << _shift)
+ {}
+protected:
+ guint32 _shift;
+ guint32 _mask;
+};
+
+template <bool alpha>
+struct ComponentTransferTable;
+
+template <>
+struct ComponentTransferTable<false> : public ComponentTransfer {
+ ComponentTransferTable(guint32 color, std::vector<double> const &values)
+ : ComponentTransfer(color)
+ , _v(values.size())
+ {
+ for (unsigned i = 0; i< values.size(); ++i) {
+ _v[i] = round(CLAMP(values[i], 0.0, 1.0) * 255);
+ }
+ }
+ guint32 operator()(guint32 in) {
+ guint32 component = (in & _mask) >> _shift;
+ guint32 alpha = (in & 0xff000000) >> 24;
+ if (alpha == 0) return in;
+
+ component = (255 * component + alpha/2) / alpha;
+ guint32 k = (_v.size() - 1) * component;
+ guint32 dx = k % 255; k /= 255;
+ component = _v[k]*255 + (_v[k+1] - _v[k])*dx;
+ component = (component + 127) / 255;
+ component = premul_alpha(component, alpha);
+ return (in & ~_mask) | (component << _shift);
+ }
+private:
+ std::vector<guint32> _v;
+};
+
+template <>
+struct ComponentTransferTable<true> {
+ ComponentTransferTable(std::vector<double> const &values)
+ : _v(values.size())
+ {
+ for (unsigned i = 0; i< values.size(); ++i) {
+ _v[i] = round(CLAMP(values[i], 0.0, 1.0) * 255);
+ }
+ }
+ guint32 operator()(guint32 in) {
+ guint32 alpha = (in & 0xff000000) >> 24;
+ if (alpha == 0) return in;
+
+ guint32 k = (_v.size() - 1) * alpha;
+ guint32 dx = k % 255; k /= 255;
+ alpha = _v[k]*255 + (_v[k+1] - _v[k])*dx;
+ alpha = (alpha + 127) / 255;
+ return (in & 0x00ffffff) | (alpha << 24);
+ }
+private:
+ std::vector<guint32> _v;
+};
+
+template <bool alpha>
+struct ComponentTransferDiscrete;
+
+template <>
+struct ComponentTransferDiscrete<false> : public ComponentTransfer {
+ ComponentTransferDiscrete(guint32 color, std::vector<double> const &values)
+ : ComponentTransfer(color)
+ , _v(values.size())
+ {
+ for (unsigned i = 0; i< values.size(); ++i) {
+ _v[i] = round(CLAMP(values[i], 0.0, 1.0) * 255);
+ }
+ }
+ guint32 operator()(guint32 in) {
+ guint32 component = (in & _mask) >> _shift;
+ guint32 alpha = (in & 0xff000000) >> 24;
+ if (alpha == 0) return in;
+
+ component = (255 * component + alpha/2) / alpha;
+ guint32 k = (_v.size() - 1) * component / 255;
+ component = _v[k];
+ component = premul_alpha(component, alpha);
+ return (in & ~_mask) | (component << _shift);
+ }
+private:
+ std::vector<guint32> _v;
+};
+
+template <>
+struct ComponentTransferDiscrete<true> {
+ ComponentTransferDiscrete(std::vector<double> const &values)
+ : _v(values.size())
+ {
+ for (unsigned i = 0; i< values.size(); ++i) {
+ _v[i] = round(CLAMP(values[i], 0.0, 1.0) * 255);
+ }
+ }
+ guint32 operator()(guint32 in) {
+ guint32 alpha = (in & 0xff000000) >> 24;
+ if (alpha == 0) return in;
+
+ guint32 k = (_v.size() - 1) * alpha / 255;
+ alpha = _v[k];
+ return (in & 0x00ffffff) | (alpha << 24);
+ }
+private:
+ std::vector<guint32> _v;
+};
+
+template <bool alpha>
+struct ComponentTransferLinear;
+
+template <>
+struct ComponentTransferLinear<false> : public ComponentTransfer {
+ ComponentTransferLinear(guint32 color, double intercept, double slope)
+ : ComponentTransfer(color)
+ , _intercept(round(intercept*255*255))
+ , _slope(round(slope*255))
+ {}
+ guint32 operator()(guint32 in) {
+ gint32 component = (in & _mask) >> _shift;
+ guint32 alpha = (in & 0xff000000) >> 24;
+ if (alpha == 0) return 0;
- if (!in) {
- g_warning("Missing source image for feComponentTransfer (in=%d)", _input);
- return 1;
+ // TODO: this can probably be reduced to something simpler
+ component = (255 * component + alpha/2) / alpha;
+ component = pxclamp(_slope * component + _intercept, 0, 255*255);
+ component = (component + 127) / 255;
+ component = premul_alpha(component, alpha);
+ return (in & ~_mask) | (component << _shift);
}
+private:
+ gint32 _intercept;
+ gint32 _slope;
+};
- int x0=in->area.x0;
- int x1=in->area.x1;
- int y0=in->area.y0;
- int y1=in->area.y1;
-
- // this primitive is defined for RGBA values,
- // thus convert them to that format before blending
- bool free_in_on_exit = false;
- if (in->mode != NR_PIXBLOCK_MODE_R8G8B8A8N && in->mode != NR_PIXBLOCK_MODE_R8G8B8A8P) {
- NRPixBlock *original_in = in;
- in = new NRPixBlock;
- nr_pixblock_setup_fast(in, NR_PIXBLOCK_MODE_R8G8B8A8N,
- original_in->area.x0, original_in->area.y0,
- original_in->area.x1, original_in->area.y1,
- false);
- nr_blit_pixblock_pixblock(in, original_in);
- free_in_on_exit = true;
+template <>
+struct ComponentTransferLinear<true> {
+ ComponentTransferLinear(double intercept, double slope)
+ : _intercept(round(intercept*255*255))
+ , _slope(round(slope*255))
+ {}
+ guint32 operator()(guint32 in) {
+ gint32 alpha = (in & 0xff000000) >> 24;
+ alpha = pxclamp(_slope * alpha + _intercept, 0, 255*255);
+ alpha = (alpha + 127) / 255;
+ return (in & 0x00ffffff) | (alpha << 24);
}
- bool premultiplied = in->mode == NR_PIXBLOCK_MODE_R8G8B8A8P;
-
- NRPixBlock *out = new NRPixBlock;
- nr_pixblock_setup_fast(out, in->mode, x0, y0, x1, y1, true);
-
- unsigned char *in_data = NR_PIXBLOCK_PX(in);
- unsigned char *out_data = NR_PIXBLOCK_PX(out);
-
- (void)in_data;
- (void)out_data;
-
- int size = 4 * (y1-y0) * (x1-x0);
- int i;
-
- int color=4;
- while(color-->0) {
- int _vsize = tableValues[color].size();
- double _intercept = intercept[color];
- double _slope = slope[color];
- double _amplitude = amplitude[color];
- double _exponent = exponent[color];
- double _offset = offset[color];
- switch(type[color]){
- case COMPONENTTRANSFER_TYPE_IDENTITY:
- for(i=color;i<size;i+=4){
- out_data[i]=in_data[i];
- }
- break;
- case COMPONENTTRANSFER_TYPE_TABLE:
- if (_vsize<=1){
- if (_vsize==1) {
- g_warning("A component transfer table has to have at least two values.");
- }
- for(i=color;i<size;i+=4){
- out_data[i]=in_data[i];
- }
- } else {
- if (!premultiplied || color==3) {
- std::vector<gdouble> _tableValues(tableValues[color]);
- // Scale by 255 and add .5 to avoid having to add it later for rounding purposes
- // Note that this means that CLAMP_D_TO_U8 cannot be used here (as it includes rounding!)
- for(i=0;i<_vsize;i++) {
- _tableValues[i] = std::max(0.,std::min(255.,255*_tableValues[i])) + .5;
- }
- for(i=color;i<size;i+=4){
- int k = FAST_DIVIDE<255>((_vsize-1) * in_data[i]);
- double dx = ((_vsize-1) * in_data[i])/255.0 - k;
- out_data[i] = static_cast<unsigned char>(_tableValues[k] + dx * (_tableValues[k+1] - _tableValues[k]));
- }
- } else {
- std::vector<gdouble> _tableValues(tableValues[color]);
- for(i=0;i<_vsize;i++) {
- _tableValues[i] = std::max(0.,std::min(1.,_tableValues[i]));
- }
- for(i=color;i<size;i+=4){
- if (in_data[i+3-color]==0) continue;
- int k = ((_vsize-1) * in_data[i]) / in_data[i+3-color];
- double dx = ((_vsize-1) * in_data[i]) / (double)in_data[i+3-color] - k;
- out_data[i] = CLAMP_D_TO_U8_ALPHA(out_data[i+3-color] * (_tableValues[k] + dx * (_tableValues[k+1] - _tableValues[k])), out_data[i+3-color]); // CLAMP includes rounding!
- }
- }
- }
- break;
- case COMPONENTTRANSFER_TYPE_DISCRETE:
- if (_vsize==0){
- for(i=color;i<size;i+=4){
- out_data[i] = in_data[i];
- }
- } else {
- if (!premultiplied || color==3) {
- std::vector<unsigned char> _tableValues(_vsize);
- // Convert to unsigned char
- for(i=0;i<_vsize;i++) {
- _tableValues[i] = CLAMP_D_TO_U8(255*tableValues[color][i]);
- }
- for(i=color;i<size;i+=4){
- int k = FAST_DIVIDE<255>((_vsize-1) * in_data[i]);
- out_data[i] = _tableValues[k];
- }
- } else {
- std::vector<gdouble> _tableValues(tableValues[color]);
- for(i=0;i<_vsize;i++) {
- _tableValues[i] = std::max(0.,std::min(1.,_tableValues[i]));
- }
- for(i=color;i<size;i+=4){
- if (in_data[i+3-color]==0) continue;
- int k = ((_vsize-1) * in_data[i]) / in_data[i+3-color];
- out_data[i] = CLAMP_D_TO_U8_ALPHA(out_data[i+3-color] * _tableValues[k], out_data[i+3-color]);
- }
- }
- }
- break;
- case COMPONENTTRANSFER_TYPE_LINEAR:
- if (!premultiplied || color==3) {
- _intercept = 255*_intercept;
- for(i=color;i<size;i+=4){
- out_data[i] = CLAMP_D_TO_U8(_slope * in_data[i] + _intercept); // CLAMP includes rounding!
- }
- } else {
- for(i=color;i<size;i+=4){
- if (in_data[i+3-color]==0) continue;
- double out = _slope * in_data[i] / in_data[i+3-color] + _intercept;
- out_data[i] = CLAMP_D_TO_U8_ALPHA(out_data[i+3-color] * out, out_data[i+3-color]);
- }
- }
- break;
- case COMPONENTTRANSFER_TYPE_GAMMA:
- if (!premultiplied || color==3) {
- _amplitude *= pow(255.0, -_exponent+1); // The input should be divided by 255, then exponentiated and then multiplied by 255 again, instead the amplitude is modified accordingly.
- _offset = 255*_offset;
- for(i=color;i<size;i+=4){
- out_data[i] = CLAMP_D_TO_U8(_amplitude * pow((double)in_data[i], _exponent) + _offset);
- }
- } else {
- for(i=color;i<size;i+=4){
- if (in_data[i+3-color]==0) continue;
- double out = _amplitude * pow((double)in_data[i] / in_data[i+3-color], _exponent) + _offset;
- out_data[i] = CLAMP_D_TO_U8_ALPHA(out_data[i+3-color] * out, out_data[i+3-color]);
- }
- }
- break;
- case COMPONENTTRANSFER_TYPE_ERROR:
- //TODO: report an error here
- g_warning("Component tranfer type \"error\".");
- break;
- default:
- g_warning("Invalid tranfer type %d.", type[color]);
+private:
+ gint32 _intercept;
+ gint32 _slope;
+};
+
+template <bool alpha>
+struct ComponentTransferGamma;
+
+template <>
+struct ComponentTransferGamma<false> : public ComponentTransfer {
+ ComponentTransferGamma(guint32 color, double amplitude, double exponent, double offset)
+ : ComponentTransfer(color)
+ , _amplitude(amplitude)
+ , _exponent(exponent)
+ , _offset(offset)
+ {}
+ guint32 operator()(guint32 in) {
+ double component = (in & _mask) >> _shift;
+ guint32 alpha = (in & 0xff000000) >> 24;
+ if (alpha == 0) return 0;
+
+ double alphaf = alpha;
+ component /= alphaf;
+ component = _amplitude * pow(component, _exponent) + _offset;
+ guint32 cpx = pxclamp(component * alphaf, 0, 255);
+ return (in & ~_mask) | (cpx << _shift);
+ }
+private:
+ double _amplitude;
+ double _exponent;
+ double _offset;
+};
+
+template <>
+struct ComponentTransferGamma<true> {
+ ComponentTransferGamma(double amplitude, double exponent, double offset)
+ : _amplitude(amplitude)
+ , _exponent(exponent)
+ , _offset(offset)
+ {}
+ guint32 operator()(guint32 in) {
+ double alpha = (in & 0xff000000) >> 24;
+ alpha /= 255.0;
+ alpha = _amplitude * pow(alpha, _exponent) + _offset;
+ guint32 cpx = pxclamp(alpha * 255.0, 0, 255);
+ return (in & 0x00ffffff) | (cpx << 24);
+ }
+private:
+ double _amplitude;
+ double _exponent;
+ double _offset;
+};
+
+void FilterComponentTransfer::render_cairo(FilterSlot &slot)
+{
+ cairo_surface_t *input = slot.getcairo(_input);
+ cairo_surface_t *out = ink_cairo_surface_create_same_size(input, CAIRO_CONTENT_COLOR_ALPHA);
+ //cairo_surface_t *outtemp = ink_cairo_surface_create_identical(out);
+ ink_cairo_surface_blit(input, out);
+
+ // parameters: R = 0, G = 1, B = 2, A = 3
+ // Cairo: R = 2, G = 1, B = 0, A = 3
+ for (unsigned i = 0; i < 3; ++i) {
+ guint32 color = 2 - i;
+ switch (type[i]) {
+ case COMPONENTTRANSFER_TYPE_TABLE:
+ ink_cairo_surface_filter(out, out,
+ ComponentTransferTable<false>(color, tableValues[i]));
+ break;
+ case COMPONENTTRANSFER_TYPE_DISCRETE:
+ ink_cairo_surface_filter(out, out,
+ ComponentTransferDiscrete<false>(color, tableValues[i]));
+ break;
+ case COMPONENTTRANSFER_TYPE_LINEAR:
+ ink_cairo_surface_filter(out, out,
+ ComponentTransferLinear<false>(color, intercept[i], slope[i]));
+ break;
+ case COMPONENTTRANSFER_TYPE_GAMMA:
+ ink_cairo_surface_filter(out, out,
+ ComponentTransferGamma<false>(color, amplitude[i], exponent[i], offset[i]));
+ break;
+ case COMPONENTTRANSFER_TYPE_ERROR:
+ case COMPONENTTRANSFER_TYPE_IDENTITY:
+ default:
+ break;
}
+ //ink_cairo_surface_blit(out, outtemp);
}
- if (free_in_on_exit) {
- nr_pixblock_release(in);
- delete in;
+ // fast paths for alpha channel
+ switch (type[3]) {
+ case COMPONENTTRANSFER_TYPE_TABLE:
+ ink_cairo_surface_filter(out, out,
+ ComponentTransferTable<true>(tableValues[3]));
+ break;
+ case COMPONENTTRANSFER_TYPE_DISCRETE:
+ ink_cairo_surface_filter(out, out,
+ ComponentTransferDiscrete<true>(tableValues[3]));
+ break;
+ case COMPONENTTRANSFER_TYPE_LINEAR:
+ ink_cairo_surface_filter(out, out,
+ ComponentTransferLinear<true>(intercept[3], slope[3]));
+ break;
+ case COMPONENTTRANSFER_TYPE_GAMMA:
+ ink_cairo_surface_filter(out, out,
+ ComponentTransferGamma<true>(amplitude[3], exponent[3], offset[3]));
+ break;
+ case COMPONENTTRANSFER_TYPE_ERROR:
+ case COMPONENTTRANSFER_TYPE_IDENTITY:
+ default:
+ break;
}
- out->empty = FALSE;
slot.set(_output, out);
- return 0;
+ cairo_surface_destroy(out);
+ //cairo_surface_destroy(outtemp);
+}
+
+bool FilterComponentTransfer::can_handle_affine(Geom::Affine const &)
+{
+ return true;
}
void FilterComponentTransfer::area_enlarge(NRRectL &/*area*/, Geom::Affine const &/*trans*/)
diff --git a/src/display/nr-filter-component-transfer.h b/src/display/nr-filter-component-transfer.h
index 65b4d4079..89bc61403 100644
--- a/src/display/nr-filter-component-transfer.h
+++ b/src/display/nr-filter-component-transfer.h
@@ -12,14 +12,14 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include "display/nr-filter-primitive.h"
-#include "display/nr-filter-slot.h"
-#include "display/nr-filter-units.h"
#include <vector>
+#include "display/nr-filter-primitive.h"
namespace Inkscape {
namespace Filters {
+class FilterSlot;
+
enum FilterComponentTransferType {
COMPONENTTRANSFER_TYPE_IDENTITY,
COMPONENTTRANSFER_TYPE_TABLE,
@@ -35,7 +35,8 @@ public:
static FilterPrimitive *create();
virtual ~FilterComponentTransfer();
- virtual int render(FilterSlot &slot, FilterUnits const &units);
+ virtual void render_cairo(FilterSlot &slot);
+ virtual bool can_handle_affine(Geom::Affine const &);
virtual void area_enlarge(NRRectL &area, Geom::Affine const &trans);
FilterComponentTransferType type[4];
diff --git a/src/display/nr-filter-composite.cpp b/src/display/nr-filter-composite.cpp
index 41175ee07..d4cf47af4 100644
--- a/src/display/nr-filter-composite.cpp
+++ b/src/display/nr-filter-composite.cpp
@@ -12,77 +12,11 @@
#include <cmath>
#include "2geom/isnan.h"
-#include "filters/composite.h"
+#include "display/cairo-templates.h"
+#include "display/cairo-utils.h"
#include "display/nr-filter-composite.h"
-#include "display/nr-filter-pixops.h"
#include "display/nr-filter-slot.h"
#include "display/nr-filter-units.h"
-#include "display/nr-filter-utils.h"
-#include "libnr/nr-blit.h"
-#include "libnr/nr-pixblock.h"
-#include "libnr/nr-pixops.h"
-
-inline void
-composite_over(unsigned char *r, unsigned char const *a, unsigned char const *b)
-{
- r[0] = NR_COMPOSEPPP_1111(a[0],a[3],b[0]);
- r[1] = NR_COMPOSEPPP_1111(a[1],a[3],b[1]);
- r[2] = NR_COMPOSEPPP_1111(a[2],a[3],b[2]);
- r[3] = NR_COMPOSEPPP_1111(a[3],a[3],b[3]);
-}
-
-inline void
-composite_in(unsigned char *r, unsigned char const *a, unsigned char const *b)
-{
- r[0] = NR_NORMALIZE_21(a[0] * b[3]);
- r[1] = NR_NORMALIZE_21(a[1] * b[3]);
- r[2] = NR_NORMALIZE_21(a[2] * b[3]);
- r[3] = NR_NORMALIZE_21(a[3] * b[3]);
-}
-
-inline void
-composite_out(unsigned char *r, unsigned char const *a, unsigned char const *b)
-{
- r[0] = NR_NORMALIZE_21(a[0] * (255 - b[3]));
- r[1] = NR_NORMALIZE_21(a[1] * (255 - b[3]));
- r[2] = NR_NORMALIZE_21(a[2] * (255 - b[3]));
- r[3] = NR_NORMALIZE_21(a[3] * (255 - b[3]));
-}
-
-inline void
-composite_atop(unsigned char *r, unsigned char const *a, unsigned char const *b)
-{
- r[0] = NR_NORMALIZE_21(a[0] * b[3] + b[0] * (255 - a[3]));
- r[1] = NR_NORMALIZE_21(a[1] * b[3] + b[1] * (255 - a[3]));
- r[2] = NR_NORMALIZE_21(a[2] * b[3] + b[2] * (255 - a[3]));
- r[3] = b[3];
-}
-
-inline void
-composite_xor(unsigned char *r, unsigned char const *a, unsigned char const *b)
-{
- r[0] = NR_NORMALIZE_21(a[0] * (255 - b[3]) + b[0] * (255 - a[3]));
- r[1] = NR_NORMALIZE_21(a[1] * (255 - b[3]) + b[1] * (255 - a[3]));
- r[2] = NR_NORMALIZE_21(a[2] * (255 - b[3]) + b[2] * (255 - a[3]));
- r[3] = NR_NORMALIZE_21(a[3] * (255 - b[3]) + b[3] * (255 - a[3]));
-}
-
-// BUGBUG / TODO
-// This makes arithmetic compositing non re-entrant and non thread safe.
-static int arith_k1, arith_k2, arith_k3, arith_k4;
-inline void
-composite_arithmetic(unsigned char *r, unsigned char const *a, unsigned char const *b)
-{
- using Inkscape::Filters::clamp3;
- r[0] = NR_NORMALIZE_31(clamp3(arith_k1 * a[0] * b[0]
- + arith_k2 * a[0] + arith_k3 * b[0] + arith_k4));
- r[1] = NR_NORMALIZE_31(clamp3(arith_k1 * a[1] * b[1]
- + arith_k2 * a[1] + arith_k3 * b[1] + arith_k4));
- r[2] = NR_NORMALIZE_31(clamp3(arith_k1 * a[2] * b[2]
- + arith_k2 * a[2] + arith_k3 * b[2] + arith_k4));
- r[3] = NR_NORMALIZE_31(clamp3(arith_k1 * a[3] * b[3]
- + arith_k2 * a[3] + arith_k3 * b[3] + arith_k4));
-}
namespace Inkscape {
namespace Filters {
@@ -99,85 +33,77 @@ FilterPrimitive * FilterComposite::create() {
FilterComposite::~FilterComposite()
{}
-int FilterComposite::render(FilterSlot &slot, FilterUnits const &/*units*/) {
- NRPixBlock *in1 = slot.get(_input);
- NRPixBlock *in2 = slot.get(_input2);
- NRPixBlock *original_in1 = in1;
- NRPixBlock *original_in2 = in2;
- NRPixBlock *out;
-
- // Bail out if either one of source images is missing
- if (!in1 || !in2) {
- g_warning("Missing source image for feComposite (in=%d in2=%d)", _input, _input2);
- return 1;
- }
-
- out = new NRPixBlock;
- NRRectL out_area;
- nr_rect_l_union(&out_area, &in1->area, &in2->area);
- nr_pixblock_setup_fast(out, NR_PIXBLOCK_MODE_R8G8B8A8P,
- out_area.x0, out_area.y0, out_area.x1, out_area.y1,
- true);
-
- // Blending modes are defined for premultiplied RGBA values,
- // thus convert them to that format before blending
- if (in1->mode != NR_PIXBLOCK_MODE_R8G8B8A8P) {
- in1 = nr_pixblock_new_fast(NR_PIXBLOCK_MODE_R8G8B8A8P,
- original_in1->area.x0, original_in1->area.y0,
- original_in1->area.x1, original_in1->area.y1,
- false);
- nr_blit_pixblock_pixblock(in1, original_in1);
- }
- if (in2->mode != NR_PIXBLOCK_MODE_R8G8B8A8P) {
- in2 = nr_pixblock_new_fast(NR_PIXBLOCK_MODE_R8G8B8A8P,
- original_in2->area.x0, original_in2->area.y0,
- original_in2->area.x1, original_in2->area.y1,
- false);
- nr_blit_pixblock_pixblock(in2, original_in2);
+struct ComposeArithmetic {
+ ComposeArithmetic(double k1, double k2, double k3, double k4)
+ : _k1(round(k1 * 255))
+ , _k2(round(k2 * 255*255))
+ , _k3(round(k3 * 255*255))
+ , _k4(round(k4 * 255*255*255))
+ {}
+ guint32 operator()(guint32 in1, guint32 in2) {
+ EXTRACT_ARGB32(in1, aa, ra, ga, ba)
+ EXTRACT_ARGB32(in2, ab, rb, gb, bb)
+
+ gint32 ao = _k1*aa*ab + _k2*aa + _k3*ab + _k4;
+ gint32 ro = _k1*ra*rb + _k2*ra + _k3*rb + _k4;
+ gint32 go = _k1*ga*gb + _k2*ga + _k3*gb + _k4;
+ gint32 bo = _k1*ba*bb + _k2*ba + _k3*bb + _k4;
+
+ ao = (pxclamp(ao, 0, 255*255*255) + (255*255/2)) / (255*255);
+ ro = (pxclamp(ro, 0, 255*255*255) + (255*255/2)) / (255*255);
+ go = (pxclamp(go, 0, 255*255*255) + (255*255/2)) / (255*255);
+ bo = (pxclamp(bo, 0, 255*255*255) + (255*255/2)) / (255*255);
+
+ ASSEMBLE_ARGB32(pxout, ao, ro, go, bo)
+ return pxout;
}
+private:
+ gint32 _k1, _k2, _k3, _k4;
+};
- /* pixops_mix is defined in display/nr-filter-pixops.h
- * It mixes the two input images with the function given as template
- * and places the result in output image.
- */
- switch (op) {
+void FilterComposite::render_cairo(FilterSlot &slot)
+{
+ cairo_surface_t *input1 = slot.getcairo(_input);
+ cairo_surface_t *input2 = slot.getcairo(_input2);
+
+ cairo_surface_t *out = ink_cairo_surface_create_output(input1, input2);
+
+ if (op == COMPOSITE_ARITHMETIC) {
+ ink_cairo_surface_blend(input1, input2, out, ComposeArithmetic(k1, k2, k3, k4));
+ } else {
+ ink_cairo_surface_blit(input2, out);
+ cairo_t *ct = cairo_create(out);
+ cairo_set_source_surface(ct, input1, 0, 0);
+ switch(op) {
case COMPOSITE_IN:
- pixops_mix<composite_in>(*out, *in1, *in2);
+ cairo_set_operator(ct, CAIRO_OPERATOR_IN);
break;
case COMPOSITE_OUT:
- pixops_mix<composite_out>(*out, *in1, *in2);
+ cairo_set_operator(ct, CAIRO_OPERATOR_OUT);
break;
case COMPOSITE_ATOP:
- pixops_mix<composite_atop>(*out, *in1, *in2);
+ cairo_set_operator(ct, CAIRO_OPERATOR_ATOP);
break;
case COMPOSITE_XOR:
- pixops_mix<composite_xor>(*out, *in1, *in2);
- break;
- case COMPOSITE_ARITHMETIC:
- arith_k1 = (int)round(k1 * 255);
- arith_k2 = (int)round(k2 * 255 * 255);
- arith_k3 = (int)round(k3 * 255 * 255);
- arith_k4 = (int)round(k4 * 255 * 255 * 255);
- pixops_mix<composite_arithmetic>(*out, *in1, *in2);
+ cairo_set_operator(ct, CAIRO_OPERATOR_XOR);
break;
- case COMPOSITE_DEFAULT:
case COMPOSITE_OVER:
+ case COMPOSITE_DEFAULT:
default:
- pixops_mix<composite_over>(*out, *in1, *in2);
+ // OVER is the default operator
break;
+ }
+ cairo_paint(ct);
+ cairo_destroy(ct);
}
- if (in1 != original_in1) {
- nr_pixblock_free(in1);
- }
- if (in2 != original_in2) {
- nr_pixblock_free(in2);
- }
-
- out->empty = FALSE;
slot.set(_output, out);
+ cairo_surface_destroy(out);
+}
- return 0;
+bool FilterComposite::can_handle_affine(Geom::Affine const &)
+{
+ return true;
}
void FilterComposite::set_input(int input) {
diff --git a/src/display/nr-filter-composite.h b/src/display/nr-filter-composite.h
index 45114a92c..930898830 100644
--- a/src/display/nr-filter-composite.h
+++ b/src/display/nr-filter-composite.h
@@ -26,7 +26,8 @@ public:
static FilterPrimitive *create();
virtual ~FilterComposite();
- virtual int render(FilterSlot &slot, FilterUnits const &units);
+ virtual void render_cairo(FilterSlot &);
+ virtual bool can_handle_affine(Geom::Affine const &);
virtual void set_input(int input);
virtual void set_input(int input, int slot);
diff --git a/src/display/nr-filter-convolve-matrix.cpp b/src/display/nr-filter-convolve-matrix.cpp
index f5cc7175a..06e28b074 100644
--- a/src/display/nr-filter-convolve-matrix.cpp
+++ b/src/display/nr-filter-convolve-matrix.cpp
@@ -10,10 +10,13 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
+#include <vector>
+#include "display/cairo-templates.h"
+#include "display/cairo-utils.h"
#include "display/nr-filter-convolve-matrix.h"
+#include "display/nr-filter-slot.h"
#include "display/nr-filter-units.h"
#include "display/nr-filter-utils.h"
-#include <vector>
namespace Inkscape {
namespace Filters {
@@ -28,186 +31,139 @@ FilterPrimitive * FilterConvolveMatrix::create() {
FilterConvolveMatrix::~FilterConvolveMatrix()
{}
-template<bool PREMULTIPLIED, bool PRESERVE_ALPHA, bool X_LOWER, bool X_UPPER, bool Y_LOWER, bool Y_UPPER>
-static inline void convolve2D_XY(unsigned int const x, unsigned int const y, unsigned char *const out_data, unsigned char const *const in_data, unsigned int const width, unsigned int const height, double const *const kernel, unsigned int const orderX, unsigned int const orderY, unsigned int const targetX, unsigned int const targetY, double const bias) {
- double result_R = 0;
- double result_G = 0;
- double result_B = 0;
- double result_A = 0;
-
- unsigned int iBegin = Y_LOWER ? targetY-y : 0; // Note that to prevent signed/unsigned problems this requires that y<=targetY (which is true)
- unsigned int iEnd = Y_UPPER ? height+targetY-y : orderY; // And this requires that y<=height+targetY (which is trivially true), in addition it should be true that height+targetY-y<=orderY (or equivalently y>=height+targetY-orderY, which is true)
- unsigned int jBegin = X_LOWER ? targetX-x : 0;
- unsigned int jEnd = X_UPPER ? width+targetX-x : orderX;
-
- for (unsigned int i=iBegin; i<iEnd; i++){
- for (unsigned int j=jBegin; j<jEnd; j++){
- unsigned int index = 4*( x - targetX + j + width*(y - targetY + i) );
- unsigned int kernel_index = orderX-j-1 + orderX*(orderY-i-1);
- double k = PREMULTIPLIED ? kernel[kernel_index] : in_data[index+3] * kernel[kernel_index];
- result_R += in_data[index+0] * k;
- result_G += in_data[index+1] * k;
- result_B += in_data[index+2] * k;
- result_A += in_data[index+3] * kernel[kernel_index];
+enum PreserveAlphaMode {
+ PRESERVE_ALPHA,
+ NO_PRESERVE_ALPHA
+};
+
+template <PreserveAlphaMode preserve_alpha>
+struct ConvolveMatrix : public SurfaceSynth {
+ ConvolveMatrix(cairo_surface_t *s, int targetX, int targetY, int orderX, int orderY,
+ double divisor, double bias, std::vector<double> const &kernel)
+ : SurfaceSynth(s)
+ , _kernel(kernel.size())
+ , _targetX(targetX)
+ , _targetY(targetY)
+ , _orderX(orderX)
+ , _orderY(orderY)
+ , _bias(bias)
+ {
+ for (unsigned i = 0; i < _kernel.size(); ++i) {
+ _kernel[i] = kernel[i] / divisor;
}
- }
-
- unsigned int const out_index = 4*( x + width*y );
- if (PRESERVE_ALPHA) {
- out_data[out_index+3] = in_data[out_index+3];
- } else if (PREMULTIPLIED) {
- out_data[out_index+3] = CLAMP_D_TO_U8(result_A + 255*bias);
- } else {
- out_data[out_index+3] = CLAMP_D_TO_U8(result_A + bias);
- }
- if (PREMULTIPLIED) {
- out_data[out_index+0] = CLAMP_D_TO_U8_ALPHA(result_R + out_data[out_index+3]*bias, out_data[out_index+3]); // CLAMP includes rounding!
- out_data[out_index+1] = CLAMP_D_TO_U8_ALPHA(result_G + out_data[out_index+3]*bias, out_data[out_index+3]);
- out_data[out_index+2] = CLAMP_D_TO_U8_ALPHA(result_B + out_data[out_index+3]*bias, out_data[out_index+3]);
- } else if (out_data[out_index+3]==0) {
- out_data[out_index+0] = 0; // TODO: Is there a more sensible value that can be used here?
- out_data[out_index+1] = 0;
- out_data[out_index+2] = 0;
- } else {
- out_data[out_index+0] = CLAMP_D_TO_U8(result_R / out_data[out_index+3] + bias); // CLAMP includes rounding!
- out_data[out_index+1] = CLAMP_D_TO_U8(result_G / out_data[out_index+3] + bias);
- out_data[out_index+2] = CLAMP_D_TO_U8(result_B / out_data[out_index+3] + bias);
- }
-}
-
-template<bool PREMULTIPLIED, bool PRESERVE_ALPHA, bool Y_LOWER, bool Y_UPPER>
-static inline void convolve2D_Y(unsigned int const y, unsigned char *const out_data, unsigned char const *const in_data, unsigned int const width, unsigned int const height, double const *const kernel, unsigned int const orderX, unsigned int const orderY, unsigned int const targetX, unsigned int const targetY, double const bias) {
- // See convolve2D below for rationale.
-
- unsigned int const lowerEnd = std::min(targetX,width);
- unsigned int const upperBegin = width - std::min<unsigned int>(width,orderX - 1u - targetX);
- unsigned int const midXBegin = std::min(lowerEnd,upperBegin);
- unsigned int const midXEnd = std::max(lowerEnd,upperBegin);
-
- for (unsigned int x=0; x<midXBegin; x++) {
- convolve2D_XY<PREMULTIPLIED,PRESERVE_ALPHA,true,false,Y_LOWER,Y_UPPER>(x, y, out_data, in_data, width, height, kernel, orderX, orderY, targetX, targetY, bias);
- }
- if (lowerEnd==upperBegin) {
- // Do nothing, empty mid section
- } else if (lowerEnd<upperBegin) {
- // In the middle no bounds have to be adjusted
- for (unsigned int x=midXBegin; x<midXEnd; x++) {
- convolve2D_XY<PREMULTIPLIED,PRESERVE_ALPHA,false,false,Y_LOWER,Y_UPPER>(x, y, out_data, in_data, width, height, kernel, orderX, orderY, targetX, targetY, bias);
+ // the matrix is given rotated 180 degrees
+ // which corresponds to reverse element order
+ std::reverse(_kernel.begin(), _kernel.end());
+ }
+
+ guint32 operator()(int x, int y) const {
+ int startx = std::max(0, x - _targetX);
+ int starty = std::max(0, y - _targetY);
+ int endx = std::min(_w, startx + _orderX);
+ int endy = std::min(_h, starty + _orderY);
+ int limitx = endx - startx;
+ int limity = endy - starty;
+ double suma = 0.0, sumr = 0.0, sumg = 0.0, sumb = 0.0;
+
+ for (int i = 0; i < limity; ++i) {
+ for (int j = 0; j < limitx; ++j) {
+ guint32 px = pixelAt(startx + j, starty + i);
+ double coeff = _kernel[i * _orderX + j];
+ EXTRACT_ARGB32(px, a,r,g,b)
+
+ sumr += r * coeff;
+ sumg += g * coeff;
+ sumb += b * coeff;
+ if (preserve_alpha == NO_PRESERVE_ALPHA) {
+ suma += a * coeff;
+ }
+ }
}
- } else {
- // In the middle both bounds have to be adjusted
- for (unsigned int x=midXBegin; x<midXEnd; x++) {
- convolve2D_XY<PREMULTIPLIED,PRESERVE_ALPHA,true,true,Y_LOWER,Y_UPPER>(x, y, out_data, in_data, width, height, kernel, orderX, orderY, targetX, targetY, bias);
+ if (preserve_alpha == PRESERVE_ALPHA) {
+ suma = alphaAt(x, y);
+ } else {
+ suma += _bias * 255;
}
+
+ guint32 ao = pxclamp(round(suma), 0, 255);
+ guint32 ro = pxclamp(round(sumr + ao * _bias), 0, ao);
+ guint32 go = pxclamp(round(sumg + ao * _bias), 0, ao);
+ guint32 bo = pxclamp(round(sumb + ao * _bias), 0, ao);
+ ASSEMBLE_ARGB32(pxout, ao,ro,go,bo);
+ return pxout;
}
- for (unsigned int x=midXEnd; x<width; x++) {
- convolve2D_XY<PREMULTIPLIED,PRESERVE_ALPHA,false,true,Y_LOWER,Y_UPPER>(x, y, out_data, in_data, width, height, kernel, orderX, orderY, targetX, targetY, bias);
- }
-}
-template<bool PREMULTIPLIED, bool PRESERVE_ALPHA>
-static void convolve2D(unsigned char *const out_data, unsigned char const *const in_data, unsigned int const width, unsigned int const height, double const *const kernel, unsigned int const orderX, unsigned int const orderY, unsigned int const targetX, unsigned int const targetY, double const _bias) {
- double const bias = PREMULTIPLIED ? _bias : 255*_bias; // If we're using non-premultiplied values the bias is always multiplied by 255.
+private:
+ std::vector<double> _kernel;
+ int _targetX, _targetY, _orderX, _orderY;
+ double _bias;
+};
- // For the middle section it should hold that (for all i such that 0<=i<orderY):
- // 0 <= y - targetY + i < height
- // targetY <= y && y < height + targetY - orderY + 1
- // In other words, for y<targetY i's lower bound needs to be adjusted and for y>=height+targetY-orderY+1 i's upper bound needs to be adjusted.
+void FilterConvolveMatrix::render_cairo(FilterSlot &slot)
+{
+ static bool bias_warning = false;
+ static bool edge_warning = false;
- unsigned int const lowerEnd = std::min(targetY,height);
- unsigned int const upperBegin = height - std::min<unsigned int>(height,orderY - 1u - targetY);
- unsigned int const midYBegin = std::min(lowerEnd,upperBegin);
- unsigned int const midYEnd = std::max(lowerEnd,upperBegin);
+ cairo_surface_t *input = slot.getcairo(_input);
- for (unsigned int y=0; y<midYBegin; y++) {
- convolve2D_Y<PREMULTIPLIED,PRESERVE_ALPHA,true,false>(y, out_data, in_data, width, height, kernel, orderX, orderY, targetX, targetY, bias);
- }
- if (lowerEnd==upperBegin) {
- // Do nothing, empty mid section
- } else if (lowerEnd<upperBegin) {
- // In the middle no bounds have to be adjusted
- for (unsigned int y=midYBegin; y<midYEnd; y++) {
- convolve2D_Y<PREMULTIPLIED,PRESERVE_ALPHA,false,false>(y, out_data, in_data, width, height, kernel, orderX, orderY, targetX, targetY, bias);
- }
- } else {
- // In the middle both bounds have to be adjusted
- for (unsigned int y=midYBegin; y<midYEnd; y++) {
- convolve2D_Y<PREMULTIPLIED,PRESERVE_ALPHA,true,true>(y, out_data, in_data, width, height, kernel, orderX, orderY, targetX, targetY, bias);
- }
- }
- for (unsigned int y=midYEnd; y<height; y++) {
- convolve2D_Y<PREMULTIPLIED,PRESERVE_ALPHA,false,true>(y, out_data, in_data, width, height, kernel, orderX, orderY, targetX, targetY, bias);
- }
-}
-
-int FilterConvolveMatrix::render(FilterSlot &slot, FilterUnits const &/*units*/) {
- NRPixBlock *in = slot.get(_input);
- if (!in) {
- g_warning("Missing source image for feConvolveMatrix (in=%d)", _input);
- return 1;
- }
if (orderX<=0 || orderY<=0) {
g_warning("Empty kernel!");
- return 1;
+ return;
}
if (targetX<0 || targetX>=orderX || targetY<0 || targetY>=orderY) {
g_warning("Invalid target!");
- return 1;
+ return;
}
if (kernelMatrix.size()!=(unsigned int)(orderX*orderY)) {
- g_warning("kernelMatrix does not have orderX*orderY elements!");
- return 1;
- }
-
- if (bias!=0) {
- g_warning("It is unknown whether Inkscape's implementation of bias in feConvolveMatrix is correct!");
- // The SVG specification implies that feConvolveMatrix is defined for premultiplied colors (which makes sense).
- // It also says that bias should simply be added to the result for each color (without taking the alpha into account)
- // However, it also says that one purpose of bias is "to have .5 gray value be the zero response of the filter".
- // It seems sensible to indeed support the latter behaviour instead of the former, but this does appear to go against the standard.
+ //g_warning("kernelMatrix does not have orderX*orderY elements!");
+ return;
+ }
+
+ cairo_surface_t *out = ink_cairo_surface_create_identical(input);
+
+ if (bias!=0 && !bias_warning) {
+ g_warning("It is unknown whether Inkscape's implementation of bias in feConvolveMatrix "
+ "is correct!");
+ bias_warning = true;
+ // The SVG specification implies that feConvolveMatrix is defined for premultiplied
+ // colors (which makes sense). It also says that bias should simply be added to the result
+ // for each color (without taking the alpha into account). However, it also says that one
+ // purpose of bias is "to have .5 gray value be the zero response of the filter".
+ // It seems sensible to indeed support the latter behaviour instead of the former,
+ // but this does appear to go against the standard.
// Note that Batik simply does not support bias!=0
}
- if (edgeMode!=CONVOLVEMATRIX_EDGEMODE_NONE) {
+ if (edgeMode!=CONVOLVEMATRIX_EDGEMODE_NONE && !edge_warning) {
g_warning("Inkscape only supports edgeMode=\"none\" (and a filter uses a different one)!");
- // Note that to properly support edgeMode the interaction with area_enlarge should be well understood (and probably something needs to change)
- // area_enlarge should NOT let Inkscape enlarge the area beyond the filter area, it should only enlarge the rendered area if a part of the object is rendered to make it overlapping (enough) with adjacent parts.
+ edge_warning = true;
}
- NRPixBlock *out = new NRPixBlock;
+ //guint32 *in_data = reinterpret_cast<guint32*>(cairo_image_surface_get_data(input));
+ //guint32 *out_data = reinterpret_cast<guint32*>(cairo_image_surface_get_data(out));
- nr_pixblock_setup_fast(out, in->mode,
- in->area.x0, in->area.y0, in->area.x1, in->area.y1,
- true);
-
- unsigned char *in_data = NR_PIXBLOCK_PX(in);
- unsigned char *out_data = NR_PIXBLOCK_PX(out);
-
- unsigned int const width = in->area.x1 - in->area.x0;
- unsigned int const height = in->area.y1 - in->area.y0;
+ //int width = cairo_image_surface_get_width(input);
+ //int height = cairo_image_surface_get_height(input);
// Set up predivided kernel matrix
- std::vector<double> kernel(kernelMatrix);
+ /*std::vector<double> kernel(kernelMatrix);
for(size_t i=0; i<kernel.size(); i++) {
kernel[i] /= divisor; // The code that creates this object makes sure that divisor != 0
- }
+ }*/
- if (in->mode==NR_PIXBLOCK_MODE_R8G8B8A8P) {
- if (preserveAlpha) {
- convolve2D<true,true>(out_data, in_data, width, height, &kernel.front(), orderX, orderY, targetX, targetY, bias);
- } else {
- convolve2D<true,false>(out_data, in_data, width, height, &kernel.front(), orderX, orderY, targetX, targetY, bias);
- }
+ if (preserveAlpha) {
+ //convolve2D<true>(out_data, in_data, width, height, &kernel.front(), orderX, orderY,
+ // targetX, targetY, bias);
+ ink_cairo_surface_synthesize(out, ConvolveMatrix<PRESERVE_ALPHA>(input,
+ targetX, targetY, orderX, orderY, divisor, bias, kernelMatrix));
} else {
- if (preserveAlpha) {
- convolve2D<false,true>(out_data, in_data, width, height, &kernel.front(), orderX, orderY, targetX, targetY, bias);
- } else {
- convolve2D<false,false>(out_data, in_data, width, height, &kernel.front(), orderX, orderY, targetX, targetY, bias);
- }
+ //convolve2D<false>(out_data, in_data, width, height, &kernel.front(), orderX, orderY,
+ // targetX, targetY, bias);
+ ink_cairo_surface_synthesize(out, ConvolveMatrix<NO_PRESERVE_ALPHA>(input,
+ targetX, targetY, orderX, orderY, divisor, bias, kernelMatrix));
}
- out->empty = FALSE;
slot.set(_output, out);
- return 0;
+ cairo_surface_destroy(out);
}
void FilterConvolveMatrix::set_targetX(int coord) {
@@ -256,10 +212,6 @@ void FilterConvolveMatrix::area_enlarge(NRRectL &area, Geom::Affine const &/*tra
area.y1 += orderY - targetY - 1;
}
-FilterTraits FilterConvolveMatrix::get_input_traits() {
- return TRAIT_PARALLER;
-}
-
} /* namespace Filters */
} /* namespace Inkscape */
diff --git a/src/display/nr-filter-convolve-matrix.h b/src/display/nr-filter-convolve-matrix.h
index 50d97f1a0..d13738260 100644
--- a/src/display/nr-filter-convolve-matrix.h
+++ b/src/display/nr-filter-convolve-matrix.h
@@ -13,14 +13,14 @@
*/
#include "display/nr-filter-primitive.h"
-#include "display/nr-filter-slot.h"
-#include "display/nr-filter-units.h"
#include "libnr/nr-rect-l.h"
#include <vector>
namespace Inkscape {
namespace Filters {
+class FilterSlot;
+
enum FilterConvolveMatrixEdgeMode {
CONVOLVEMATRIX_EDGEMODE_DUPLICATE,
CONVOLVEMATRIX_EDGEMODE_WRAP,
@@ -34,9 +34,8 @@ public:
static FilterPrimitive *create();
virtual ~FilterConvolveMatrix();
- virtual int render(FilterSlot &slot, FilterUnits const &units);
+ virtual void render_cairo(FilterSlot &slot);
virtual void area_enlarge(NRRectL &area, Geom::Affine const &trans);
- virtual FilterTraits get_input_traits();
void set_targetY(int coord);
void set_targetX(int coord);
diff --git a/src/display/nr-filter-diffuselighting.cpp b/src/display/nr-filter-diffuselighting.cpp
index 8e764f6d4..0a46a5c86 100644
--- a/src/display/nr-filter-diffuselighting.cpp
+++ b/src/display/nr-filter-diffuselighting.cpp
@@ -4,26 +4,25 @@
* Authors:
* Niko Kiirala <niko@kiirala.com>
* Jean-Rene Reinhard <jr@komite.net>
+ * Krzysztof KosiƄski <tweenk.pl@gmail.com>
*
- * Copyright (C) 2007 authors
+ * Copyright (C) 2007-2010 Authors
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
#include <glib/gmessages.h>
+#include "display/cairo-templates.h"
+#include "display/cairo-utils.h"
#include "display/nr-3dutils.h"
#include "display/nr-arena-item.h"
#include "display/nr-filter-diffuselighting.h"
-#include "display/nr-filter-getalpha.h"
#include "display/nr-filter-slot.h"
#include "display/nr-filter-units.h"
#include "display/nr-filter-utils.h"
#include "display/nr-light.h"
-#include "libnr/nr-blit.h"
-#include "libnr/nr-pixblock.h"
#include "libnr/nr-rect-l.h"
-#include "color.h"
namespace Inkscape {
namespace Filters {
@@ -43,146 +42,134 @@ FilterPrimitive * FilterDiffuseLighting::create() {
FilterDiffuseLighting::~FilterDiffuseLighting()
{}
-int FilterDiffuseLighting::render(FilterSlot &slot, FilterUnits const &units) {
- NRPixBlock *in = slot.get(_input);
- if (!in) {
- g_warning("Missing source image for feDiffuseLighting (in=%d)", _input);
- return 1;
+struct DiffuseLight : public SurfaceSynth {
+ DiffuseLight(cairo_surface_t *bumpmap, double scale, double kd)
+ : SurfaceSynth(bumpmap)
+ , _scale(scale)
+ , _kd(kd)
+ {}
+
+protected:
+ guint32 diffuseLighting(int x, int y, NR::Fvector const &light, NR::Fvector const &light_components) {
+ NR::Fvector normal = surfaceNormalAt(x, y, _scale);
+ double k = _kd * NR::scalar_product(normal, light);
+
+ guint32 r = CLAMP_D_TO_U8(k * light_components[LIGHT_RED]);
+ guint32 g = CLAMP_D_TO_U8(k * light_components[LIGHT_GREEN]);
+ guint32 b = CLAMP_D_TO_U8(k * light_components[LIGHT_BLUE]);
+
+ ASSEMBLE_ARGB32(pxout, 255,r,g,b)
+ return pxout;
+ }
+ double _scale, _kd;
+};
+
+struct DiffuseDistantLight : public DiffuseLight {
+ DiffuseDistantLight(cairo_surface_t *bumpmap, SPFeDistantLight *light, guint32 color,
+ double scale, double diffuse_constant)
+ : DiffuseLight(bumpmap, scale, diffuse_constant)
+ {
+ DistantLight dl(light, color);
+ dl.light_vector(_lightv);
+ dl.light_components(_light_components);
}
- NRPixBlock *out = new NRPixBlock;
-
- int w = in->area.x1 - in->area.x0;
- int h = in->area.y1 - in->area.y0;
- int x0 = in->area.x0;
- int y0 = in->area.y0;
- int i, j;
- //As long as FilterRes and kernel unit is not supported we hardcode the
- //default value
- int dx = 1; //TODO setup
- int dy = 1; //TODO setup
- //surface scale
- Geom::Affine trans = units.get_matrix_primitiveunits2pb();
- gdouble ss = surfaceScale * trans[0];
- gdouble kd = diffuseConstant; //diffuse lighting constant
-
- NR::Fvector L, N, LC;
- gdouble inter;
-
- nr_pixblock_setup_fast(out, in->mode,
- in->area.x0, in->area.y0, in->area.x1, in->area.y1,
- true);
- unsigned char *data_i = NR_PIXBLOCK_PX (in);
- unsigned char *data_o = NR_PIXBLOCK_PX (out);
- //No light, nothing to do
+ guint32 operator()(int x, int y) {
+ return diffuseLighting(x, y, _lightv, _light_components);
+ }
+private:
+ NR::Fvector _lightv, _light_components;
+};
+
+struct DiffusePointLight : public DiffuseLight {
+ DiffusePointLight(cairo_surface_t *bumpmap, SPFePointLight *light, guint32 color,
+ Geom::Affine const &trans, double scale, double diffuse_constant, double x0, double y0)
+ : DiffuseLight(bumpmap, scale, diffuse_constant)
+ , _light(light, color, trans)
+ , _x0(x0)
+ , _y0(y0)
+ {
+ _light.light_components(_light_components);
+ }
+
+ guint32 operator()(int x, int y) {
+ NR::Fvector light;
+ _light.light_vector(light, _x0 + x, _y0 + y, _scale * alphaAt(x, y)/255.0);
+ return diffuseLighting(x, y, light, _light_components);
+ }
+private:
+ PointLight _light;
+ NR::Fvector _light_components;
+ double _x0, _y0;
+};
+
+struct DiffuseSpotLight : public DiffuseLight {
+ DiffuseSpotLight(cairo_surface_t *bumpmap, SPFeSpotLight *light, guint32 color,
+ Geom::Affine const &trans, double scale, double diffuse_constant, double x0, double y0)
+ : DiffuseLight(bumpmap, scale, diffuse_constant)
+ , _light(light, color, trans)
+ , _x0(x0)
+ , _y0(y0)
+ {}
+
+ guint32 operator()(int x, int y) {
+ NR::Fvector light, light_components;
+ _light.light_vector(light, _x0 + x, _y0 + y, _scale * alphaAt(x, y)/255.0);
+ _light.light_components(light_components, light);
+ return diffuseLighting(x, y, light, light_components);
+ }
+private:
+ SpotLight _light;
+ double _x0, _y0;
+};
+
+void FilterDiffuseLighting::render_cairo(FilterSlot &slot)
+{
+ cairo_surface_t *input = slot.getcairo(_input);
+ cairo_surface_t *out = ink_cairo_surface_create_same_size(input, CAIRO_CONTENT_COLOR_ALPHA);
+
+ Geom::Rect slot_area = slot.get_slot_area();
+ Geom::Point p = slot_area.min();
+ Geom::Affine trans = slot.get_units().get_matrix_primitiveunits2pb();
+ double x0 = p[Geom::X], y0 = p[Geom::Y];
+ double scale = surfaceScale * trans.descrim();
+
switch (light_type) {
- case DISTANT_LIGHT:
- //the light vector is constant
- {
- DistantLight *dl = new DistantLight(light.distant, lighting_color);
- dl->light_vector(L);
- dl->light_components(LC);
- //finish the work
- for (i = 0, j = 0; i < w*h; i++) {
- NR::compute_surface_normal(N, ss, in, i / w, i % w, dx, dy);
- inter = kd * NR::scalar_product(N, L);
-
- data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_RED]); // CLAMP includes rounding!
- data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_GREEN]);
- data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_BLUE]);
- data_o[j++] = 255;
- }
- out->empty = FALSE;
- delete dl;
- }
- break;
- case POINT_LIGHT:
- {
- PointLight *pl = new PointLight(light.point, lighting_color, trans);
- pl->light_components(LC);
- //TODO we need a reference to the filter to determine primitiveUnits
- //if objectBoundingBox is used, use a different matrix for light_vector
- // UPDATE: trans is now correct matrix from primitiveUnits to
- // pixblock coordinates
- //finish the work
- for (i = 0, j = 0; i < w*h; i++) {
- NR::compute_surface_normal(N, ss, in, i / w, i % w, dx, dy);
- pl->light_vector(L,
- i % w + x0,
- i / w + y0,
- ss * (double) data_i[4*i+3]/ 255);
- inter = kd * NR::scalar_product(N, L);
-
- data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_RED]);
- data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_GREEN]);
- data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_BLUE]);
- data_o[j++] = 255;
- }
- out->empty = FALSE;
- delete pl;
- }
- break;
- case SPOT_LIGHT:
- {
- SpotLight *sl = new SpotLight(light.spot, lighting_color, trans);
- //TODO we need a reference to the filter to determine primitiveUnits
- //if objectBoundingBox is used, use a different matrix for light_vector
- // UPDATE: trans is now correct matrix from primitiveUnits to
- // pixblock coordinates
- //finish the work
- for (i = 0, j = 0; i < w*h; i++) {
- NR::compute_surface_normal(N, ss, in, i / w, i % w, dx, dy);
- sl->light_vector(L,
- i % w + x0,
- i / w + y0,
- ss * (double) data_i[4*i+3]/ 255);
- sl->light_components(LC, L);
- inter = kd * NR::scalar_product(N, L);
-
- data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_RED]);
- data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_GREEN]);
- data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_BLUE]);
- data_o[j++] = 255;
- }
- out->empty = FALSE;
- delete sl;
- }
- break;
- //else unknown light source, doing nothing
- case NO_LIGHT:
- default:
- {
- if (light_type != NO_LIGHT)
- g_warning("unknown light source %d", light_type);
- for (i = 0; i < w*h; i++) {
- data_o[4*i+3] = 255;
- }
- out->empty = false;
- }
+ case DISTANT_LIGHT:
+ ink_cairo_surface_synthesize(out,
+ DiffuseDistantLight(input, light.distant, lighting_color, scale, diffuseConstant));
+ break;
+ case POINT_LIGHT:
+ ink_cairo_surface_synthesize(out,
+ DiffusePointLight(input, light.point, lighting_color, trans, scale, diffuseConstant, x0, y0));
+ break;
+ case SPOT_LIGHT:
+ ink_cairo_surface_synthesize(out,
+ DiffuseSpotLight(input, light.spot, lighting_color, trans, scale, diffuseConstant, x0, y0));
+ break;
+ default: {
+ cairo_t *ct = cairo_create(out);
+ cairo_set_source_rgba(ct, 0,0,0,1);
+ cairo_set_operator(ct, CAIRO_OPERATOR_SOURCE);
+ cairo_paint(ct);
+ cairo_destroy(ct);
+ } break;
}
-
- //finishing
+
slot.set(_output, out);
- //nr_pixblock_release(in);
- //delete in;
- return 0;
+ cairo_surface_destroy(out);
}
void FilterDiffuseLighting::area_enlarge(NRRectL &area, Geom::Affine const &trans)
{
// TODO: support kernelUnitLength
- double scalex = std::fabs(trans[0]) + std::fabs(trans[1]);
- double scaley = std::fabs(trans[2]) + std::fabs(trans[3]);
-
- //FIXME: no +2 should be there!... (noticable only for big scales at big zoom factor)
- area.x0 -= (int)(scalex) + 2;
- area.x1 += (int)(scalex) + 2;
- area.y0 -= (int)(scaley) + 2;
- area.y1 += (int)(scaley) + 2;
-}
-FilterTraits FilterDiffuseLighting::get_input_traits() {
- return TRAIT_PARALLER;
+ // We expand the area by 1 in every direction to avoid artifacts on tile edges.
+ // However, it means that edge pixels will be incorrect.
+ area.x0 -= 1;
+ area.x1 += 1;
+ area.y0 -= 1;
+ area.y1 += 1;
}
} /* namespace Filters */
diff --git a/src/display/nr-filter-diffuselighting.h b/src/display/nr-filter-diffuselighting.h
index f540bf4a5..6e39242f6 100644
--- a/src/display/nr-filter-diffuselighting.h
+++ b/src/display/nr-filter-diffuselighting.h
@@ -18,16 +18,22 @@
#include "display/nr-filter-primitive.h"
#include "display/nr-filter-slot.h"
#include "display/nr-filter-units.h"
-#include "filters/distantlight.h"
-#include "filters/pointlight.h"
-#include "filters/spotlight.h"
-#include "color.h"
+
+class SPFeDistantLight;
+class SPFePointLight;
+class SPFeSpotLight;
namespace Inkscape {
namespace Filters {
class FilterDiffuseLighting : public FilterPrimitive {
public:
+ FilterDiffuseLighting();
+ static FilterPrimitive *create();
+ virtual ~FilterDiffuseLighting();
+ virtual void render_cairo(FilterSlot &slot);
+ virtual void area_enlarge(NRRectL &area, Geom::Affine const &trans);
+
union {
SPFeDistantLight *distant;
SPFePointLight *point;
@@ -37,13 +43,6 @@ public:
gdouble diffuseConstant;
gdouble surfaceScale;
guint32 lighting_color;
-
- FilterDiffuseLighting();
- static FilterPrimitive *create();
- virtual ~FilterDiffuseLighting();
- virtual int render(FilterSlot &slot, FilterUnits const &units);
- virtual void area_enlarge(NRRectL &area, Geom::Affine const &trans);
- virtual FilterTraits get_input_traits();
private:
};
diff --git a/src/display/nr-filter-displacement-map.cpp b/src/display/nr-filter-displacement-map.cpp
index d71a691ef..fdaf2c887 100644
--- a/src/display/nr-filter-displacement-map.cpp
+++ b/src/display/nr-filter-displacement-map.cpp
@@ -9,11 +9,11 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
+#include "display/cairo-templates.h"
+#include "display/cairo-utils.h"
#include "display/nr-filter-displacement-map.h"
#include "display/nr-filter-types.h"
#include "display/nr-filter-units.h"
-#include "libnr/nr-blit.h"
-#include "libnr/nr-pixops.h"
namespace Inkscape {
namespace Filters {
@@ -28,6 +28,7 @@ FilterPrimitive * FilterDisplacementMap::create() {
FilterDisplacementMap::~FilterDisplacementMap()
{}
+#if 0
struct pixel_t {
unsigned char channels[4];
inline unsigned char operator[](int c) const { return channels[c]; }
@@ -147,7 +148,65 @@ static void performDisplacement(NRPixBlock const* texture, NRPixBlock const* map
}
}
}
+#endif
+
+struct Displace {
+ Displace(cairo_surface_t *texture, cairo_surface_t *map,
+ unsigned xch, unsigned ych, double scalex, double scaley)
+ : _texture(texture)
+ , _map(map)
+ , _xch(xch)
+ , _ych(ych)
+ , _scalex(scalex/255.0)
+ , _scaley(scaley/255.0)
+ {}
+ guint32 operator()(int x, int y) {
+ guint32 mappx = _map.pixelAt(x, y);
+ guint32 a = (mappx & 0xff000000) >> 24;
+ guint32 xpx = 0, ypx = 0;
+ double xtex = x, ytex = y;
+ if (a) {
+ guint32 xshift = _xch * 8, yshift = _ych * 8;
+ xpx = (mappx & (0xff << xshift)) >> xshift;
+ ypx = (mappx & (0xff << yshift)) >> yshift;
+ if (_xch != 3) xpx = unpremul_alpha(xpx, a);
+ if (_ych != 3) ypx = unpremul_alpha(ypx, a);
+ xtex += _scalex * (xpx - 127.5);
+ ytex += _scaley * (ypx - 127.5);
+ }
+
+ if (xtex >= 0 && xtex < (_texture._w - 1) &&
+ ytex >= 0 && ytex < (_texture._h - 1))
+ {
+ return _texture.pixelAt(xtex, ytex);
+ } else {
+ return 0;
+ }
+ }
+private:
+ SurfaceSynth _texture;
+ SurfaceSynth _map;
+ unsigned _xch, _ych;
+ double _scalex, _scaley;
+};
+
+void FilterDisplacementMap::render_cairo(FilterSlot &slot)
+{
+ cairo_surface_t *texture = slot.getcairo(_input);
+ cairo_surface_t *map = slot.getcairo(_input2);
+ cairo_surface_t *out = ink_cairo_surface_create_identical(texture);
+
+ Geom::Affine trans = slot.get_units().get_matrix_primitiveunits2pb();
+ double scalex = scale * trans.expansionX();
+ double scaley = scale * trans.expansionY();
+
+ ink_cairo_surface_synthesize(out, Displace(texture, map, Xchannel, Ychannel, scalex, scaley));
+
+ slot.set(_output, out);
+ cairo_surface_destroy(out);
+}
+/*
int FilterDisplacementMap::render(FilterSlot &slot, FilterUnits const &units) {
NRPixBlock *texture = slot.get(_input);
NRPixBlock *map = slot.get(_input2);
@@ -212,7 +271,7 @@ int FilterDisplacementMap::render(FilterSlot &slot, FilterUnits const &units) {
out->empty = FALSE;
slot.set(_output, out);
return 0;
-}
+}*/
void FilterDisplacementMap::set_input(int slot) {
_input = slot;
@@ -233,8 +292,26 @@ void FilterDisplacementMap::set_channel_selector(int s, FilterDisplacementMapCha
return;
}
- if (s == 0) Xchannel = channel;
- if (s == 1) Ychannel = channel;
+ // channel numbering:
+ // a = 3, r = 2, g = 1, b = 0
+ // this way we can get the component value using:
+ // component = (color & (ch*8)) >> (ch*8)
+ unsigned ch = 4;
+ switch (channel) {
+ case DISPLACEMENTMAP_CHANNEL_ALPHA:
+ ch = 3; break;
+ case DISPLACEMENTMAP_CHANNEL_RED:
+ ch = 2; break;
+ case DISPLACEMENTMAP_CHANNEL_GREEN:
+ ch = 1; break;
+ case DISPLACEMENTMAP_CHANNEL_BLUE:
+ ch = 0; break;
+ default: break;
+ }
+ if (ch == 4) return;
+
+ if (s == 0) Xchannel = ch;
+ if (s == 1) Ychannel = ch;
}
void FilterDisplacementMap::area_enlarge(NRRectL &area, Geom::Affine const &trans)
@@ -252,10 +329,6 @@ void FilterDisplacementMap::area_enlarge(NRRectL &area, Geom::Affine const &tran
area.y1 += (int)(scaley)+2;
}
-FilterTraits FilterDisplacementMap::get_input_traits() {
- return TRAIT_PARALLER;
-}
-
} /* namespace Filters */
} /* namespace Inkscape */
diff --git a/src/display/nr-filter-displacement-map.h b/src/display/nr-filter-displacement-map.h
index 1dad1873a..aec4b7eb6 100644
--- a/src/display/nr-filter-displacement-map.h
+++ b/src/display/nr-filter-displacement-map.h
@@ -31,15 +31,13 @@ public:
virtual void set_input(int input, int slot);
virtual void set_scale(double s);
virtual void set_channel_selector(int s, FilterDisplacementMapChannelSelector channel);
- virtual int render(FilterSlot &slot, FilterUnits const &units);
+ virtual void render_cairo(FilterSlot &slot);
virtual void area_enlarge(NRRectL &area, Geom::Affine const &trans);
- virtual FilterTraits get_input_traits();
private:
double scale;
int _input2;
- FilterDisplacementMapChannelSelector Xchannel;
- FilterDisplacementMapChannelSelector Ychannel;
+ unsigned Xchannel, Ychannel;
};
} /* namespace Filters */
diff --git a/src/display/nr-filter-flood.cpp b/src/display/nr-filter-flood.cpp
index eb1cf13a6..a015d3f1f 100644
--- a/src/display/nr-filter-flood.cpp
+++ b/src/display/nr-filter-flood.cpp
@@ -14,10 +14,12 @@
# include "config.h"
#endif
+#include "display/cairo-utils.h"
#include "display/nr-filter-flood.h"
-#include "display/nr-filter-utils.h"
+#include "display/nr-filter-slot.h"
#include "svg/svg-icc-color.h"
#include "svg/svg-color.h"
+#include "color.h"
namespace Inkscape {
namespace Filters {
@@ -32,67 +34,40 @@ FilterPrimitive * FilterFlood::create() {
FilterFlood::~FilterFlood()
{}
-int FilterFlood::render(FilterSlot &slot, FilterUnits const &units) {
-//g_message("rendering feflood");
- NRPixBlock *in = slot.get(_input);
- if (!in) {
- g_warning("Missing source image for feFlood (in=%d)", _input);
- return 1;
+void FilterFlood::render_cairo(FilterSlot &slot)
+{
+ cairo_surface_t *input = slot.getcairo(_input);
+
+ double r = SP_RGBA32_R_F(color);
+ double g = SP_RGBA32_G_F(color);
+ double b = SP_RGBA32_B_F(color);
+ double a = opacity;
+
+ #if ENABLE_LCMS
+ if (icc) {
+ guchar ru, gu, bu;
+ icc_color_to_sRGB(icc, &ru, &gu, &bu);
+ r = SP_COLOR_U_TO_F(ru);
+ g = SP_COLOR_U_TO_F(gu);
+ b = SP_COLOR_U_TO_F(bu);
}
+ #endif
- // Region being drawn on screen in screen coordinates.
- int x0 = in->area.x0, y0 = in->area.y0;
- int x1 = in->area.x1, y1 = in->area.y1;
- int w = x1 - x0;
-
- // Set up pix block
- NRPixBlock *out = new NRPixBlock;
- nr_pixblock_setup_fast(out, NR_PIXBLOCK_MODE_R8G8B8A8N, x0, y0, x1, y1, true);
- unsigned char *out_data = NR_PIXBLOCK_PX(out);
-
- // Get RGBA values.
- unsigned char r,g,b,a;
- r = CLAMP_D_TO_U8((color >> 24) % 256);
- g = CLAMP_D_TO_U8((color >> 16) % 256);
- b = CLAMP_D_TO_U8((color >> 8) % 256);
- a = CLAMP_D_TO_U8(opacity*255);
-
-#if ENABLE_LCMS
- icc_color_to_sRGB(icc, &r, &g, &b);
- //g_message("result: r:%d g:%d b:%d", r, g, b);
-#endif //ENABLE_LCMS
-
- // Only fill primitive subregion
-
- // Get subregion in user units
- Geom::Rect fp = filter_primitive_area( units );
-
- // Need to convert to pixbuff units
- Geom::Rect fp_pb = fp * units.get_matrix_user2pb();
-
- // Make sure we are in pixbuff area
- int fp_x0 = fp_pb.min()[Geom::X];
- int fp_x1 = fp_pb.max()[Geom::X];
- int fp_y0 = fp_pb.min()[Geom::Y];
- int fp_y1 = fp_pb.max()[Geom::Y];
- if( fp_x0 < x0 ) fp_x0 = x0;
- if( fp_x1 > x1 ) fp_x1 = x1;
- if( fp_y0 < y0 ) fp_y0 = y0;
- if( fp_y1 > y1 ) fp_y1 = y1;
-
- // Do fill
- for (int x=fp_x0; x < fp_x1; x++){
- for (int y=fp_y0; y < fp_y1; y++){
- out_data[ 4*((x - x0) + w*(y - y0)) ] = r;
- out_data[ 4*((x - x0) + w*(y - y0)) + 1 ] = g;
- out_data[ 4*((x - x0) + w*(y - y0)) + 2 ] = b;
- out_data[ 4*((x - x0) + w*(y - y0)) + 3 ] = a;
- }
- }
+ cairo_surface_t *out = ink_cairo_surface_create_same_size(input, CAIRO_CONTENT_COLOR_ALPHA);
+ cairo_t *ct = cairo_create(out);
+ cairo_set_source_rgba(ct, r, g, b, a);
+ cairo_set_operator(ct, CAIRO_OPERATOR_SOURCE);
+ cairo_paint(ct);
+ cairo_destroy(ct);
- out->empty = FALSE;
slot.set(_output, out);
- return 0;
+ cairo_surface_destroy(out);
+}
+
+bool FilterFlood::can_handle_affine(Geom::Affine const &)
+{
+ // flood is a per-pixel primitive and is immutable under transformations
+ return true;
}
void FilterFlood::set_color(guint32 c) {
diff --git a/src/display/nr-filter-flood.h b/src/display/nr-filter-flood.h
index ebb7d4506..6db90d439 100644
--- a/src/display/nr-filter-flood.h
+++ b/src/display/nr-filter-flood.h
@@ -13,9 +13,8 @@
*/
#include "display/nr-filter-primitive.h"
-#include "display/nr-filter-slot.h"
-#include "display/nr-filter-units.h"
-#include "svg/svg-color.h"
+
+class SVGICCColor;
namespace Inkscape {
namespace Filters {
@@ -25,11 +24,12 @@ public:
FilterFlood();
static FilterPrimitive *create();
virtual ~FilterFlood();
-
+
+ virtual void render_cairo(FilterSlot &slot);
+ virtual bool can_handle_affine(Geom::Affine const &);
virtual void set_opacity(double o);
virtual void set_color(guint32 c);
virtual void set_icc(SVGICCColor *icc_color);
- virtual int render(FilterSlot &slot, FilterUnits const &units);
virtual void area_enlarge(NRRectL &area, Geom::Affine const &trans);
private:
double opacity;
diff --git a/src/display/nr-filter-gaussian.cpp b/src/display/nr-filter-gaussian.cpp
index 9b83c8647..326c37160 100644
--- a/src/display/nr-filter-gaussian.cpp
+++ b/src/display/nr-filter-gaussian.cpp
@@ -27,12 +27,12 @@
#include "2geom/isnan.h"
+#include "display/cairo-utils.h"
#include "display/nr-filter-primitive.h"
#include "display/nr-filter-gaussian.h"
#include "display/nr-filter-types.h"
#include "display/nr-filter-units.h"
-#include "libnr/nr-blit.h"
-#include "libnr/nr-pixblock.h"
+#include "display/nr-filter-slot.h"
#include <2geom/affine.h>
#include "util/fixed_point.h"
#include "preferences.h"
@@ -82,24 +82,24 @@ static inline Tt round_cast(Ts v) {
static Ts const rndoffset(.5);
return static_cast<Tt>(v+rndoffset);
}
-
+/*
template<>
inline unsigned char round_cast(double v) {
// This (fast) rounding method is based on:
// http://stereopsis.com/sree/fpu2006.html
-#if G_BYTE_ORDER==G_LITTLE_ENDIAN
- double const dmr = 6755399441055744.0;
- v = v + dmr;
+#if G_BYTE_ORDER==G_LITTLE_ENDIAN
+ double const dmr = 6755399441055744.0;
+ v = v + dmr;
return ((unsigned char*)&v)[0];
#elif G_BYTE_ORDER==G_BIG_ENDIAN
- double const dmr = 6755399441055744.0;
- v = v + dmr;
+ double const dmr = 6755399441055744.0;
+ v = v + dmr;
return ((unsigned char*)&v)[7];
#else
static double const rndoffset(.5);
- return static_cast<unsigned char>(v+rndoffset);
-#endif
-}
+ return static_cast<unsigned char>(v+rndoffset);
+#endif
+}*/
template<typename Tt, typename Ts>
static inline Tt clip_round_cast(Ts const v) {
@@ -142,7 +142,7 @@ FilterGaussian::~FilterGaussian()
static int
_effect_area_scr(double const deviation)
{
- return (int)std::ceil(deviation * 3.0);
+ return (int)std::ceil(std::fabs(deviation) * 3.0);
}
static void
@@ -223,21 +223,6 @@ _effect_subsample_step_log2(double const deviation, int const quality)
return stepsize_l2;
}
-/**
- * Sanity check function for indexing pixblocks.
- * Catches reading and writing outside the pixblock area.
- * When enabled, decreases filter rendering speed massively.
- */
-static inline void
-_check_index(NRPixBlock const * const pb, int const location, int const line)
-{
- if (false) {
- int max_loc = pb->rs * (pb->area.y1 - pb->area.y0);
- if (location < 0 || location >= max_loc)
- g_warning("Location %d out of bounds (0 ... %d) at line %d", location, max_loc, line);
- }
-}
-
static void calcFilter(double const sigma, double b[N]) {
assert(N==3);
std::complex<double> const d1_org(1.40098, 1.00236);
@@ -315,6 +300,14 @@ filter2D_IIR(PT *const dest, int const dstr1, int const dstr2,
int const n1, int const n2, IIRValue const b[N+1], double const M[N*N],
IIRValue *const tmpdata[], int const num_threads)
{
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+ static unsigned int const alpha_PC = PC-1;
+ #define PREMUL_ALPHA_LOOP for(unsigned int c=0; c<PC-1; ++c)
+#else
+ static unsigned int const alpha_PC = 0;
+ #define PREMUL_ALPHA_LOOP for(unsigned int c=1; c<PC; ++c)
+#endif
+
#if HAVE_OPENMP
#pragma omp parallel for num_threads(num_threads)
#else
@@ -350,8 +343,8 @@ filter2D_IIR(PT *const dest, int const dstr1, int const dstr2,
calcTriggsSdikaInitialization<PC>(M, u, iplus, iplus, b[0], v);
dstimg -= dstr1;
if ( PREMULTIPLIED_ALPHA ) {
- dstimg[PC-1] = clip_round_cast<PT>(v[0][PC-1]);
- for(unsigned int c=0; c<PC-1; c++) dstimg[c] = clip_round_cast_varmax<PT>(v[0][c], v[0][PC-1], dstimg[PC-1]);
+ dstimg[alpha_PC] = clip_round_cast<PT>(v[0][alpha_PC]);
+ PREMUL_ALPHA_LOOP dstimg[c] = clip_round_cast_varmax<PT>(v[0][c], v[0][alpha_PC], dstimg[alpha_PC]);
} else {
for(unsigned int c=0; c<PC; c++) dstimg[c] = clip_round_cast<PT>(v[0][c]);
}
@@ -365,8 +358,8 @@ filter2D_IIR(PT *const dest, int const dstr1, int const dstr2,
}
dstimg -= dstr1;
if ( PREMULTIPLIED_ALPHA ) {
- dstimg[PC-1] = clip_round_cast<PT>(v[0][PC-1]);
- for(unsigned int c=0; c<PC-1; c++) dstimg[c] = clip_round_cast_varmax<PT>(v[0][c], v[0][PC-1], dstimg[PC-1]);
+ dstimg[alpha_PC] = clip_round_cast<PT>(v[0][alpha_PC]);
+ PREMUL_ALPHA_LOOP dstimg[c] = clip_round_cast_varmax<PT>(v[0][c], v[0][alpha_PC], dstimg[alpha_PC]);
} else {
for(unsigned int c=0; c<PC; c++) dstimg[c] = clip_round_cast<PT>(v[0][c]);
}
@@ -481,401 +474,196 @@ filter2D_FIR(PT *const dst, int const dstr1, int const dstr2,
}
}
-template<typename PT, unsigned int PC>
static void
-downsample(PT *const dst, int const dstr1, int const dstr2, int const dn1, int const dn2,
- PT const *const src, int const sstr1, int const sstr2, int const sn1, int const sn2,
- int const step1_l2, int const step2_l2)
+gaussian_pass_IIR(Geom::Dim2 d, double deviation, cairo_surface_t *src, cairo_surface_t *dest,
+ IIRValue **tmpdata, int num_threads)
{
- unsigned int const divisor_l2 = step1_l2+step2_l2; // step1*step2=2^(step1_l2+step2_l2)
- unsigned int const round_offset = (1<<divisor_l2)/2;
- int const step1 = 1<<step1_l2;
- int const step2 = 1<<step2_l2;
- int const step1_2 = step1/2;
- int const step2_2 = step2/2;
- for(int dc2 = 0 ; dc2 < dn2 ; dc2++) {
- int const sc2_begin = (dc2<<step2_l2)-step2_2;
- int const sc2_end = sc2_begin+step2;
- for(int dc1 = 0 ; dc1 < dn1 ; dc1++) {
- int const sc1_begin = (dc1<<step1_l2)-step1_2;
- int const sc1_end = sc1_begin+step1;
- unsigned int sum[PC];
- std::fill_n(sum, PC, 0);
- for(int sc2 = sc2_begin ; sc2 < sc2_end ; sc2++) {
- for(int sc1 = sc1_begin ; sc1 < sc1_end ; sc1++) {
- for(unsigned int ch = 0 ; ch < PC ; ch++) {
- sum[ch] += src[clip(sc2,0,sn2-1)*sstr2+clip(sc1,0,sn1-1)*sstr1+ch];
- }
- }
- }
- for(unsigned int ch = 0 ; ch < PC ; ch++) {
- dst[dc2*dstr2+dc1*dstr1+ch] = static_cast<PT>((sum[ch]+round_offset)>>divisor_l2);
- }
- }
+ // Filter variables
+ IIRValue b[N+1]; // scaling coefficient + filter coefficients (can be 10.21 fixed point)
+ double bf[N]; // computed filter coefficients
+ double M[N*N]; // matrix used for initialization procedure (has to be double)
+
+ // Compute filter
+ calcFilter(deviation, bf);
+ for(size_t i=0; i<N; i++) bf[i] = -bf[i];
+ b[0] = 1; // b[0] == alpha (scaling coefficient)
+ for(size_t i=0; i<N; i++) {
+ b[i+1] = bf[i];
+ b[0] -= b[i+1];
}
+
+ // Compute initialization matrix
+ calcTriggsSdikaM(bf, M);
+
+ int stride = cairo_image_surface_get_stride(src);
+ int w = cairo_image_surface_get_width(src);
+ int h = cairo_image_surface_get_height(src);
+ if (d != Geom::X) std::swap(w, h);
+
+ // Filter
+ switch (cairo_image_surface_get_format(src)) {
+ case CAIRO_FORMAT_A8: ///< Grayscale
+ filter2D_IIR<unsigned char,1,false>(
+ cairo_image_surface_get_data(dest), d == Geom::X ? 1 : stride, d == Geom::X ? stride : 1,
+ cairo_image_surface_get_data(src), d == Geom::X ? 1 : stride, d == Geom::X ? stride : 1,
+ w, h, b, M, tmpdata, num_threads);
+ break;
+ case CAIRO_FORMAT_ARGB32: ///< Premultiplied 8 bit RGBA
+ filter2D_IIR<unsigned char,4,true>(
+ cairo_image_surface_get_data(dest), d == Geom::X ? 4 : stride, d == Geom::X ? stride : 4,
+ cairo_image_surface_get_data(src), d == Geom::X ? 4 : stride, d == Geom::X ? stride : 4,
+ w, h, b, M, tmpdata, num_threads);
+ break;
+ default:
+ assert(false);
+ };
}
-template<typename PT, unsigned int PC>
static void
-upsample(PT *const dst, int const dstr1, int const dstr2, unsigned int const dn1, unsigned int const dn2,
- PT const *const src, int const sstr1, int const sstr2, unsigned int const sn1, unsigned int const sn2,
- unsigned int const step1_l2, unsigned int const step2_l2)
+gaussian_pass_FIR(Geom::Dim2 d, double deviation, cairo_surface_t *src, cairo_surface_t *dest,
+ int num_threads)
{
- assert(((sn1-1)<<step1_l2)>=dn1 && ((sn2-1)<<step2_l2)>=dn2); // The last pixel of the source image should fall outside the destination image
- unsigned int const divisor_l2 = step1_l2+step2_l2; // step1*step2=2^(step1_l2+step2_l2)
- unsigned int const round_offset = (1<<divisor_l2)/2;
- unsigned int const step1 = 1<<step1_l2;
- unsigned int const step2 = 1<<step2_l2;
- for ( unsigned int sc2 = 0 ; sc2 < sn2-1 ; sc2++ ) {
- unsigned int const dc2_begin = (sc2 << step2_l2);
- unsigned int const dc2_end = std::min(dn2, dc2_begin+step2);
- for ( unsigned int sc1 = 0 ; sc1 < sn1-1 ; sc1++ ) {
- unsigned int const dc1_begin = (sc1 << step1_l2);
- unsigned int const dc1_end = std::min(dn1, dc1_begin+step1);
- for ( unsigned int byte = 0 ; byte < PC ; byte++) {
-
- // get 4 values at the corners of the pixel from src
- PT a00 = src[sstr2* sc2 + sstr1* sc1 + byte];
- PT a10 = src[sstr2* sc2 + sstr1*(sc1+1) + byte];
- PT a01 = src[sstr2*(sc2+1) + sstr1* sc1 + byte];
- PT a11 = src[sstr2*(sc2+1) + sstr1*(sc1+1) + byte];
-
- // initialize values for linear interpolation
- unsigned int a0 = a00*step2/*+a01*0*/;
- unsigned int a1 = a10*step2/*+a11*0*/;
-
- // iterate over the rectangle to be interpolated
- for ( unsigned int dc2 = dc2_begin ; dc2 < dc2_end ; dc2++ ) {
-
- // prepare linear interpolation for this row
- unsigned int a = a0*step1/*+a1*0*/+round_offset;
-
- for ( unsigned int dc1 = dc1_begin ; dc1 < dc1_end ; dc1++ ) {
-
- // simple linear interpolation
- dst[dstr2*dc2 + dstr1*dc1 + byte] = static_cast<PT>(a>>divisor_l2);
-
- // compute a = a0*(ix-1)+a1*(xi+1)+round_offset
- a = a - a0 + a1;
- }
-
- // compute a0 = a00*(iy-1)+a01*(yi+1) and similar for a1
- a0 = a0 - a00 + a01;
- a1 = a1 - a10 + a11;
- }
- }
- }
- }
+ int scr_len = _effect_area_scr(deviation);
+ // Filter kernel for x direction
+ FIRValue kernel[scr_len+1];
+ _make_kernel(kernel, deviation);
+
+ int stride = cairo_image_surface_get_stride(src);
+ int w = cairo_image_surface_get_width(src);
+ int h = cairo_image_surface_get_height(src);
+ if (d != Geom::X) std::swap(w, h);
+
+ // Filter (x)
+ switch (cairo_image_surface_get_format(src)) {
+ case CAIRO_FORMAT_A8: ///< Grayscale
+ filter2D_FIR<unsigned char,1>(
+ cairo_image_surface_get_data(dest), d == Geom::X ? 1 : stride, d == Geom::X ? stride : 1,
+ cairo_image_surface_get_data(src), d == Geom::X ? 1 : stride, d == Geom::X ? stride : 1,
+ w, h, kernel, scr_len, num_threads);
+ break;
+ case CAIRO_FORMAT_ARGB32: ///< Premultiplied 8 bit RGBA
+ filter2D_FIR<unsigned char,4>(
+ cairo_image_surface_get_data(dest), d == Geom::X ? 4 : stride, d == Geom::X ? stride : 4,
+ cairo_image_surface_get_data(src), d == Geom::X ? 4 : stride, d == Geom::X ? stride : 4,
+ w, h, kernel, scr_len, num_threads);
+ break;
+ default:
+ assert(false);
+ };
}
-int FilterGaussian::render(FilterSlot &slot, FilterUnits const &units)
+void FilterGaussian::render_cairo(FilterSlot &slot)
{
- // TODO: Meaningful return values? (If they're checked at all.)
-
- /* in holds the input pixblock */
- NRPixBlock *original_in = slot.get(_input);
-
- /* If to either direction, the standard deviation is zero or
- * input image is not defined,
- * a transparent black image should be returned. */
- if (_deviation_x <= 0 || _deviation_y <= 0 || original_in == NULL) {
- NRPixBlock *src = original_in;
- if (src == NULL) {
- g_warning("Missing source image for feGaussianBlur (in=%d)", _input);
- // A bit guessing here, but source graphic is likely to be of
- // right size
- src = slot.get(NR_FILTER_SOURCEGRAPHIC);
- }
- NRPixBlock *out = new NRPixBlock;
- nr_pixblock_setup_fast(out, src->mode, src->area.x0, src->area.y0,
- src->area.x1, src->area.y1, true);
- if (out->size != NR_PIXBLOCK_SIZE_TINY && out->data.px != NULL) {
- out->empty = false;
- slot.set(_output, out);
- }
- return 0;
+ cairo_surface_t *in = slot.getcairo(_input);
+ if (!in) return;
+
+ // zero deviation = transparent black as output
+ if (_deviation_x <= 0 || _deviation_y <= 0) {
+ cairo_surface_t *blank = ink_cairo_surface_create_identical(in);
+ slot.set(_output, blank);
+ cairo_surface_destroy(blank);
+ return;
}
- // Gaussian blur is defined to operate on non-premultiplied color values.
- // So, convert the input first it uses non-premultiplied color values.
- // And please note that this should not be done AFTER resampling, as resampling a non-premultiplied image
- // does not simply yield a non-premultiplied version of the resampled premultiplied image!!!
- NRPixBlock *in = original_in;
- if (in->mode == NR_PIXBLOCK_MODE_R8G8B8A8N) {
- in = nr_pixblock_new_fast(NR_PIXBLOCK_MODE_R8G8B8A8P,
- original_in->area.x0, original_in->area.y0,
- original_in->area.x1, original_in->area.y1,
- false);
- if (!in) {
- // ran out of memory
- return 0;
- }
- nr_blit_pixblock_pixblock(in, original_in);
+ Geom::Affine trans = slot.get_units().get_matrix_primitiveunits2pb();
+
+ int w_orig = ink_cairo_surface_get_width(in);
+ int h_orig = ink_cairo_surface_get_height(in);
+ double deviation_x_orig = _deviation_x * trans.expansionX();
+ double deviation_y_orig = _deviation_y * trans.expansionY();
+ cairo_format_t fmt = cairo_image_surface_get_format(in);
+ int bytes_per_pixel = 0;
+ switch (fmt) {
+ case CAIRO_FORMAT_A8:
+ bytes_per_pixel = 1; break;
+ case CAIRO_FORMAT_ARGB32:
+ default:
+ bytes_per_pixel = 4; break;
}
- Geom::Affine trans = units.get_matrix_primitiveunits2pb();
-
- // Some common constants
- int const width_org = in->area.x1-in->area.x0, height_org = in->area.y1-in->area.y0;
- double const deviation_x_org = _deviation_x * trans.expansionX();
- double const deviation_y_org = _deviation_y * trans.expansionY();
- int const PC = NR_PIXBLOCK_BPP(in);
#if HAVE_OPENMP
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- int const NTHREADS = prefs->getIntLimited("/options/threading/numthreads", omp_get_num_procs(), 1, 256);
+ int threads = prefs->getIntLimited("/options/threading/numthreads", omp_get_num_procs(), 1, 256);
#else
- int const NTHREADS = 1;
-#endif // HAVE_OPENMP
+ int threads = 1;
+#endif
- // Subsampling constants
- int const quality = slot.get_blurquality();
- int const x_step_l2 = _effect_subsample_step_log2(deviation_x_org, quality);
- int const y_step_l2 = _effect_subsample_step_log2(deviation_y_org, quality);
- int const x_step = 1<<x_step_l2;
- int const y_step = 1<<y_step_l2;
- bool const resampling = x_step > 1 || y_step > 1;
- int const width = resampling ? static_cast<int>(ceil(static_cast<double>(width_org)/x_step))+1 : width_org;
- int const height = resampling ? static_cast<int>(ceil(static_cast<double>(height_org)/y_step))+1 : height_org;
- double const deviation_x = deviation_x_org / x_step;
- double const deviation_y = deviation_y_org / y_step;
- int const scr_len_x = _effect_area_scr(deviation_x);
- int const scr_len_y = _effect_area_scr(deviation_y);
+ int quality = slot.get_blurquality();
+ int x_step = 1 << _effect_subsample_step_log2(deviation_x_orig, quality);
+ int y_step = 1 << _effect_subsample_step_log2(deviation_y_orig, quality);
+ bool resampling = x_step > 1 || y_step > 1;
+ int w_downsampled = resampling ? static_cast<int>(ceil(static_cast<double>(w_orig)/x_step))+1 : w_orig;
+ int h_downsampled = resampling ? static_cast<int>(ceil(static_cast<double>(h_orig)/y_step))+1 : h_orig;
+ double deviation_x = deviation_x_orig / x_step;
+ double deviation_y = deviation_y_orig / y_step;
+ int scr_len_x = _effect_area_scr(deviation_x);
+ int scr_len_y = _effect_area_scr(deviation_y);
// Decide which filter to use for X and Y
// This threshold was determined by trial-and-error for one specific machine,
// so there's a good chance that it's not optimal.
// Whatever you do, don't go below 1 (and preferrably not even below 2), as
// the IIR filter gets unstable there.
- bool const use_IIR_x = deviation_x > 3;
- bool const use_IIR_y = deviation_y > 3;
-
- // new buffer for the subsampled output
- NRPixBlock *out = new NRPixBlock;
- nr_pixblock_setup_fast(out, in->mode, in->area.x0/x_step, in->area.y0/y_step,
- in->area.x0/x_step+width, in->area.y0/y_step+height, true);
- if (out->size != NR_PIXBLOCK_SIZE_TINY && out->data.px == NULL) {
- // alas, we've accomplished a lot, but ran out of memory - so abort
- if (in != original_in) nr_pixblock_free(in);
- delete out;
- return 0;
- }
+ bool use_IIR_x = deviation_x > 3;
+ bool use_IIR_y = deviation_y > 3;
+
// Temporary storage for IIR filter
// NOTE: This can be eliminated, but it reduces the precision a bit
- IIRValue * tmpdata[NTHREADS];
- std::fill_n(tmpdata, NTHREADS, (IIRValue*)0);
+ IIRValue * tmpdata[threads];
+ std::fill_n(tmpdata, threads, (IIRValue*)0);
if ( use_IIR_x || use_IIR_y ) {
- for(int i=0; i<NTHREADS; i++) {
- tmpdata[i] = new IIRValue[std::max(width,height)*PC];
- if (tmpdata[i] == NULL) {
- if (in != original_in) nr_pixblock_free(in);
- nr_pixblock_release(out);
- while(i-->0) {
- delete[] tmpdata[i];
- }
- delete out;
- return 0;
- }
+ for(int i = 0; i < threads; ++i) {
+ tmpdata[i] = new IIRValue[std::max(w_downsampled,h_downsampled)*bytes_per_pixel];
}
}
- // Resampling (if necessary), goes from in -> out (setting ssin to out if used)
- NRPixBlock *ssin = in;
- if ( resampling ) {
- ssin = out;
- // Downsample
- switch(in->mode) {
- case NR_PIXBLOCK_MODE_A8: ///< Grayscale
- downsample<unsigned char,1>(NR_PIXBLOCK_PX(out), 1, out->rs, width, height, NR_PIXBLOCK_PX(in), 1, in->rs, width_org, height_org, x_step_l2, y_step_l2);
- break;
- case NR_PIXBLOCK_MODE_R8G8B8: ///< 8 bit RGB
- downsample<unsigned char,3>(NR_PIXBLOCK_PX(out), 3, out->rs, width, height, NR_PIXBLOCK_PX(in), 3, in->rs, width_org, height_org, x_step_l2, y_step_l2);
- break;
- //case NR_PIXBLOCK_MODE_R8G8B8A8N: ///< Normal 8 bit RGBA
- // downsample<unsigned char,4>(NR_PIXBLOCK_PX(out), 4, out->rs, width, height, NR_PIXBLOCK_PX(in), 4, in->rs, width_org, height_org, x_step_l2, y_step_l2);
- // break;
- case NR_PIXBLOCK_MODE_R8G8B8A8P: ///< Premultiplied 8 bit RGBA
- downsample<unsigned char,4>(NR_PIXBLOCK_PX(out), 4, out->rs, width, height, NR_PIXBLOCK_PX(in), 4, in->rs, width_org, height_org, x_step_l2, y_step_l2);
- break;
- default:
- assert(false);
- };
+ cairo_surface_t *downsampled = NULL;
+ if (resampling) {
+ downsampled = cairo_surface_create_similar(in, cairo_surface_get_content(in),
+ w_downsampled, h_downsampled);
+ cairo_t *ct = cairo_create(downsampled);
+ cairo_scale(ct, static_cast<double>(w_downsampled)/w_orig, static_cast<double>(h_downsampled)/h_orig);
+ cairo_set_source_surface(ct, in, 0, 0);
+ cairo_paint(ct);
+ cairo_destroy(ct);
+ } else {
+ downsampled = ink_cairo_surface_copy(in);
}
+ cairo_surface_flush(downsampled);
- // Horizontal filtering, goes from ssin -> out (ssin might be equal to out, but these algorithms can be used in-place)
- if (use_IIR_x) {
- // Filter variables
- IIRValue b[N+1]; // scaling coefficient + filter coefficients (can be 10.21 fixed point)
- double bf[N]; // computed filter coefficients
- double M[N*N]; // matrix used for initialization procedure (has to be double)
-
- // Compute filter (x)
- calcFilter(deviation_x, bf);
- for(size_t i=0; i<N; i++) bf[i] = -bf[i];
- b[0] = 1; // b[0] == alpha (scaling coefficient)
- for(size_t i=0; i<N; i++) {
- b[i+1] = bf[i];
- b[0] -= b[i+1];
+ if (scr_len_x > 0) {
+ if (use_IIR_x) {
+ gaussian_pass_IIR(Geom::X, deviation_x, downsampled, downsampled, tmpdata, threads);
+ } else {
+ gaussian_pass_FIR(Geom::X, deviation_x, downsampled, downsampled, threads);
}
-
- // Compute initialization matrix (x)
- calcTriggsSdikaM(bf, M);
-
- // Filter (x)
- switch(in->mode) {
- case NR_PIXBLOCK_MODE_A8: ///< Grayscale
- filter2D_IIR<unsigned char,1,false>(NR_PIXBLOCK_PX(out), 1, out->rs, NR_PIXBLOCK_PX(ssin), 1, ssin->rs, width, height, b, M, tmpdata, NTHREADS);
- break;
- case NR_PIXBLOCK_MODE_R8G8B8: ///< 8 bit RGB
- filter2D_IIR<unsigned char,3,false>(NR_PIXBLOCK_PX(out), 3, out->rs, NR_PIXBLOCK_PX(ssin), 3, ssin->rs, width, height, b, M, tmpdata, NTHREADS);
- break;
- //case NR_PIXBLOCK_MODE_R8G8B8A8N: ///< Normal 8 bit RGBA
- // filter2D_IIR<unsigned char,4,false>(NR_PIXBLOCK_PX(out), 4, out->rs, NR_PIXBLOCK_PX(ssin), 4, ssin->rs, width, height, b, M, tmpdata, NTHREADS);
- // break;
- case NR_PIXBLOCK_MODE_R8G8B8A8P: ///< Premultiplied 8 bit RGBA
- filter2D_IIR<unsigned char,4,true >(NR_PIXBLOCK_PX(out), 4, out->rs, NR_PIXBLOCK_PX(ssin), 4, ssin->rs, width, height, b, M, tmpdata, NTHREADS);
- break;
- default:
- assert(false);
- };
- } else if ( scr_len_x > 0 ) { // !use_IIR_x
- // Filter kernel for x direction
- FIRValue kernel[scr_len_x+1];
- _make_kernel(kernel, deviation_x);
-
- // Filter (x)
- switch(in->mode) {
- case NR_PIXBLOCK_MODE_A8: ///< Grayscale
- filter2D_FIR<unsigned char,1>(NR_PIXBLOCK_PX(out), 1, out->rs, NR_PIXBLOCK_PX(ssin), 1, ssin->rs, width, height, kernel, scr_len_x, NTHREADS);
- break;
- case NR_PIXBLOCK_MODE_R8G8B8: ///< 8 bit RGB
- filter2D_FIR<unsigned char,3>(NR_PIXBLOCK_PX(out), 3, out->rs, NR_PIXBLOCK_PX(ssin), 3, ssin->rs, width, height, kernel, scr_len_x, NTHREADS);
- break;
- //case NR_PIXBLOCK_MODE_R8G8B8A8N: ///< Normal 8 bit RGBA
- // filter2D_FIR<unsigned char,4>(NR_PIXBLOCK_PX(out), 4, out->rs, NR_PIXBLOCK_PX(ssin), 4, ssin->rs, width, height, kernel, scr_len_x, NTHREADS);
- // break;
- case NR_PIXBLOCK_MODE_R8G8B8A8P: ///< Premultiplied 8 bit RGBA
- filter2D_FIR<unsigned char,4>(NR_PIXBLOCK_PX(out), 4, out->rs, NR_PIXBLOCK_PX(ssin), 4, ssin->rs, width, height, kernel, scr_len_x, NTHREADS);
- break;
- default:
- assert(false);
- };
- } else if ( out != ssin ) { // out can be equal to ssin if resampling is used
- nr_blit_pixblock_pixblock(out, ssin);
}
- // Vertical filtering, goes from out -> out
- if (use_IIR_y) {
- // Filter variables
- IIRValue b[N+1]; // scaling coefficient + filter coefficients (can be 10.21 fixed point)
- double bf[N]; // computed filter coefficients
- double M[N*N]; // matrix used for initialization procedure (has to be double)
-
- // Compute filter (y)
- calcFilter(deviation_y, bf);
- for(size_t i=0; i<N; i++) bf[i] = -bf[i];
- b[0] = 1; // b[0] == alpha (scaling coefficient)
- for(size_t i=0; i<N; i++) {
- b[i+1] = bf[i];
- b[0] -= b[i+1];
+ if (scr_len_y > 0) {
+ if (use_IIR_y) {
+ gaussian_pass_IIR(Geom::Y, deviation_y, downsampled, downsampled, tmpdata, threads);
+ } else {
+ gaussian_pass_FIR(Geom::Y, deviation_y, downsampled, downsampled, threads);
}
-
- // Compute initialization matrix (y)
- calcTriggsSdikaM(bf, M);
-
- // Filter (y)
- switch(in->mode) {
- case NR_PIXBLOCK_MODE_A8: ///< Grayscale
- filter2D_IIR<unsigned char,1,false>(NR_PIXBLOCK_PX(out), out->rs, 1, NR_PIXBLOCK_PX(out), out->rs, 1, height, width, b, M, tmpdata, NTHREADS);
- break;
- case NR_PIXBLOCK_MODE_R8G8B8: ///< 8 bit RGB
- filter2D_IIR<unsigned char,3,false>(NR_PIXBLOCK_PX(out), out->rs, 3, NR_PIXBLOCK_PX(out), out->rs, 3, height, width, b, M, tmpdata, NTHREADS);
- break;
- //case NR_PIXBLOCK_MODE_R8G8B8A8N: ///< Normal 8 bit RGBA
- // filter2D_IIR<unsigned char,4,false>(NR_PIXBLOCK_PX(out), out->rs, 4, NR_PIXBLOCK_PX(out), out->rs, 4, height, width, b, M, tmpdata, NTHREADS);
- // break;
- case NR_PIXBLOCK_MODE_R8G8B8A8P: ///< Premultiplied 8 bit RGBA
- filter2D_IIR<unsigned char,4,true >(NR_PIXBLOCK_PX(out), out->rs, 4, NR_PIXBLOCK_PX(out), out->rs, 4, height, width, b, M, tmpdata, NTHREADS);
- break;
- default:
- assert(false);
- };
- } else if ( scr_len_y > 0 ) { // !use_IIR_y
- // Filter kernel for y direction
- FIRValue kernel[scr_len_y+1];
- _make_kernel(kernel, deviation_y);
-
- // Filter (y)
- switch(in->mode) {
- case NR_PIXBLOCK_MODE_A8: ///< Grayscale
- filter2D_FIR<unsigned char,1>(NR_PIXBLOCK_PX(out), out->rs, 1, NR_PIXBLOCK_PX(out), out->rs, 1, height, width, kernel, scr_len_y, NTHREADS);
- break;
- case NR_PIXBLOCK_MODE_R8G8B8: ///< 8 bit RGB
- filter2D_FIR<unsigned char,3>(NR_PIXBLOCK_PX(out), out->rs, 3, NR_PIXBLOCK_PX(out), out->rs, 3, height, width, kernel, scr_len_y, NTHREADS);
- break;
- //case NR_PIXBLOCK_MODE_R8G8B8A8N: ///< Normal 8 bit RGBA
- // filter2D_FIR<unsigned char,4>(NR_PIXBLOCK_PX(out), out->rs, 4, NR_PIXBLOCK_PX(out), out->rs, 4, height, width, kernel, scr_len_y, NTHREADS);
- // break;
- case NR_PIXBLOCK_MODE_R8G8B8A8P: ///< Premultiplied 8 bit RGBA
- filter2D_FIR<unsigned char,4>(NR_PIXBLOCK_PX(out), out->rs, 4, NR_PIXBLOCK_PX(out), out->rs, 4, height, width, kernel, scr_len_y, NTHREADS);
- break;
- default:
- assert(false);
- };
}
- for(int i=0; i<NTHREADS; i++) {
- delete[] tmpdata[i]; // deleting a nullptr has no effect, so this is safe
- }
-
- // Upsampling, stores (the upsampled) out using slot.set(_output, ...)
- if ( !resampling ) {
- // No upsampling needed
- out->empty = FALSE;
- slot.set(_output, out);
+ cairo_surface_mark_dirty(downsampled);
+ if (resampling) {
+ cairo_surface_t *upsampled = cairo_surface_create_similar(downsampled, cairo_surface_get_content(downsampled),
+ w_orig, h_orig);
+ cairo_t *ct = cairo_create(upsampled);
+ cairo_scale(ct, static_cast<double>(w_orig)/w_downsampled, static_cast<double>(h_orig)/h_downsampled);
+ cairo_set_source_surface(ct, downsampled, 0, 0);
+ cairo_paint(ct);
+ cairo_destroy(ct);
+
+ slot.set(_output, upsampled);
+ cairo_surface_destroy(upsampled);
+ cairo_surface_destroy(downsampled);
} else {
- // New buffer for the final output, same resolution as the in buffer
- NRPixBlock *finalout = new NRPixBlock;
- nr_pixblock_setup_fast(finalout, in->mode, in->area.x0, in->area.y0,
- in->area.x1, in->area.y1, true);
- if (finalout->size != NR_PIXBLOCK_SIZE_TINY && finalout->data.px == NULL) {
- // alas, we've accomplished a lot, but ran out of memory - so abort
- if (in != original_in) nr_pixblock_free(in);
- nr_pixblock_release(out);
- delete out;
- return 0;
- }
-
- // Upsample
- switch(in->mode) {
- case NR_PIXBLOCK_MODE_A8: ///< Grayscale
- upsample<unsigned char,1>(NR_PIXBLOCK_PX(finalout), 1, finalout->rs, width_org, height_org, NR_PIXBLOCK_PX(out), 1, out->rs, width, height, x_step_l2, y_step_l2);
- break;
- case NR_PIXBLOCK_MODE_R8G8B8: ///< 8 bit RGB
- upsample<unsigned char,3>(NR_PIXBLOCK_PX(finalout), 3, finalout->rs, width_org, height_org, NR_PIXBLOCK_PX(out), 3, out->rs, width, height, x_step_l2, y_step_l2);
- break;
- //case NR_PIXBLOCK_MODE_R8G8B8A8N: ///< Normal 8 bit RGBA
- // upsample<unsigned char,4>(NR_PIXBLOCK_PX(finalout), 4, finalout->rs, width_org, height_org, NR_PIXBLOCK_PX(out), 4, out->rs, width, height, x_step_l2, y_step_l2);
- // break;
- case NR_PIXBLOCK_MODE_R8G8B8A8P: ///< Premultiplied 8 bit RGBA
- upsample<unsigned char,4>(NR_PIXBLOCK_PX(finalout), 4, finalout->rs, width_org, height_org, NR_PIXBLOCK_PX(out), 4, out->rs, width, height, x_step_l2, y_step_l2);
- break;
- default:
- assert(false);
- };
-
- // We don't need the out buffer anymore
- nr_pixblock_release(out);
- delete out;
-
- // The final out buffer gets returned
- finalout->empty = FALSE;
- slot.set(_output, finalout);
+ slot.set(_output, downsampled);
+ cairo_surface_destroy(downsampled);
}
-
- // If we downsampled the input, clean up the downsampled data
- if (in != original_in) nr_pixblock_free(in);
-
- return 0;
}
void FilterGaussian::area_enlarge(NRRectL &area, Geom::Affine const &trans)
@@ -891,8 +679,13 @@ void FilterGaussian::area_enlarge(NRRectL &area, Geom::Affine const &trans)
area.y1 += area_max;
}
-FilterTraits FilterGaussian::get_input_traits() {
- return TRAIT_PARALLER;
+bool FilterGaussian::can_handle_affine(Geom::Affine const &)
+{
+ // Previously we tried to be smart and return true for rotations.
+ // However, the transform passed here is NOT the total transform
+ // from filter user space to screen.
+ // TODO: fix this, or replace can_handle_affine() with isotropic().
+ return false;
}
void FilterGaussian::set_deviation(double deviation)
diff --git a/src/display/nr-filter-gaussian.h b/src/display/nr-filter-gaussian.h
index 87d74ac63..811502016 100644
--- a/src/display/nr-filter-gaussian.h
+++ b/src/display/nr-filter-gaussian.h
@@ -14,12 +14,8 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include "display/nr-filter-primitive.h"
-#include "display/nr-filter-slot.h"
-#include "display/nr-filter-units.h"
-#include "libnr/nr-pixblock.h"
#include <2geom/forward.h>
-#include "libnr/nr-rect-l.h"
+#include "display/nr-filter-primitive.h"
enum {
BLUR_QUALITY_BEST = 2,
@@ -38,9 +34,9 @@ public:
static FilterPrimitive *create();
virtual ~FilterGaussian();
- virtual int render(FilterSlot &slot, FilterUnits const &units);
+ virtual void render_cairo(FilterSlot &slot);
virtual void area_enlarge(NRRectL &area, Geom::Affine const &m);
- virtual FilterTraits get_input_traits();
+ virtual bool can_handle_affine(Geom::Affine const &m);
/**
* Set the standard deviation value for gaussian blur. Deviation along
diff --git a/src/display/nr-filter-getalpha.cpp b/src/display/nr-filter-getalpha.cpp
deleted file mode 100644
index 7b5e2a101..000000000
--- a/src/display/nr-filter-getalpha.cpp
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Functions for extracting alpha channel from NRPixBlocks.
- *
- * Author:
- * Niko Kiirala <niko@kiirala.com>
- *
- * Copyright (C) 2007 Niko Kiirala
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#include "display/nr-filter-getalpha.h"
-#include "libnr/nr-blit.h"
-#include "libnr/nr-pixblock.h"
-
-namespace Inkscape {
-namespace Filters {
-
-NRPixBlock *filter_get_alpha(NRPixBlock *src)
-{
- NRPixBlock *dst = new NRPixBlock;
- nr_pixblock_setup_fast(dst, NR_PIXBLOCK_MODE_R8G8B8A8P,
- src->area.x0, src->area.y0,
- src->area.x1, src->area.y1, false);
- if (!dst || (dst->size != NR_PIXBLOCK_SIZE_TINY && dst->data.px == NULL)) {
- g_warning("Memory allocation failed in filter_get_alpha");
- delete dst;
- return NULL;
- }
- nr_blit_pixblock_pixblock(dst, src);
-
- unsigned char *data = NR_PIXBLOCK_PX(dst);
- int end = dst->rs * (dst->area.y1 - dst->area.y0);
- for (int i = 0 ; i < end ; i += 4) {
- data[i + 0] = 0;
- data[i + 1] = 0;
- data[i + 2] = 0;
- }
- dst->empty = false;
-
- return dst;
-}
-
-} /* namespace Filters */
-} /* 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/nr-filter-getalpha.h b/src/display/nr-filter-getalpha.h
deleted file mode 100644
index e279494b1..000000000
--- a/src/display/nr-filter-getalpha.h
+++ /dev/null
@@ -1,35 +0,0 @@
-#ifndef __NR_FILTER_GETALPHA_H__
-#define __NR_FILTER_GETALPHA_H__
-
-/*
- * Functions for extracting alpha channel from NRPixBlocks.
- *
- * Author:
- * Niko Kiirala <niko@kiirala.com>
- *
- * Copyright (C) 2007 Niko Kiirala
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#include "libnr/nr-pixblock.h"
-
-namespace Inkscape {
-namespace Filters {
-
-NRPixBlock *filter_get_alpha(NRPixBlock *src);
-
-} /* namespace Filters */
-} /* namespace Inkscape */
-
-#endif /* __NR_FILTER_GETALPHA_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/nr-filter-image.cpp b/src/display/nr-filter-image.cpp
index 9ecec69bf..0cb7901b3 100644
--- a/src/display/nr-filter-image.cpp
+++ b/src/display/nr-filter-image.cpp
@@ -12,25 +12,23 @@
*/
#include "document.h"
#include "sp-item.h"
+#include "display/cairo-utils.h"
#include "display/nr-arena.h"
#include "display/nr-arena-item.h"
#include "display/nr-filter.h"
#include "display/nr-filter-image.h"
#include "display/nr-filter-units.h"
-#include "libnr/nr-compose-transform.h"
#include "libnr/nr-rect-l.h"
-#include "preferences.h"
-#include "svg/svg-length.h"
-#include "enums.h"
namespace Inkscape {
namespace Filters {
-FilterImage::FilterImage() :
- SVGElem(0),
- document(0),
- feImageHref(0),
- image_pixbuf(0)
+FilterImage::FilterImage()
+ : SVGElem(0)
+ , document(0)
+ , feImageHref(0)
+ , image_surface(0)
+ , broken_ref(false)
{ }
FilterPrimitive * FilterImage::create() {
@@ -39,76 +37,95 @@ FilterPrimitive * FilterImage::create() {
FilterImage::~FilterImage()
{
- if (feImageHref) g_free(feImageHref);
+ if (feImageHref)
+ g_free(feImageHref);
}
-int FilterImage::render(FilterSlot &slot, FilterUnits const &units) {
- if (!feImageHref) return 0;
-
- NRPixBlock* pb = NULL;
- bool free_pb_on_exit = false;
-
- if(from_element){
- if (!SVGElem) return 0;
-
- // prep the document
+void FilterImage::render_cairo(FilterSlot &slot)
+{
+ if (!feImageHref)
+ return;
+
+ //cairo_surface_t *input = slot.getcairo(_input);
+
+ Geom::Affine m = slot.get_units().get_matrix_user2filterunits().inverse();
+ Geom::Point bbox_00 = Geom::Point(0,0) * m;
+ Geom::Point bbox_w0 = Geom::Point(1,0) * m;
+ Geom::Point bbox_0h = Geom::Point(0,1) * m;
+ double bbox_width = Geom::distance(bbox_00, bbox_w0);
+ double bbox_height = Geom::distance(bbox_00, bbox_0h);
+
+
+ // feImage is suppose to use the same parameters as a normal SVG image.
+ // If a width or height is set to zero, the image is not suppose to be displayed.
+ // This does not seem to be what Firefox or Opera does, nor does the W3C displacement
+ // filter test expect this behavior. If the width and/or height are zero, we use
+ // the width and height of the object bounding box.
+ if( feImageWidth == 0 ) feImageWidth = bbox_width;
+ if( feImageHeight == 0 ) feImageHeight = bbox_height;
+
+ if (from_element) {
+ if (!SVGElem) return;
+
+ // TODO: do not recreate the rendering tree every time
+ // TODO: the entire thing is a hack, we should give filter primitives an "update" method
+ // like the one for NRArenaItems
document->ensureUpToDate();
+
NRArena* arena = NRArena::create();
+ Geom::OptRect optarea = SVGElem->getBounds(Geom::identity());
+ if (!optarea) return;
+
unsigned const key = SPItem::display_key_new(1);
NRArenaItem* ai = SVGElem->invoke_show(arena, key, SP_ITEM_SHOW_DISPLAY);
+
if (!ai) {
g_warning("feImage renderer: error creating NRArenaItem for SVG Element");
nr_object_unref((NRObject *) arena);
- return 0;
+ return;
}
- pb = new NRPixBlock;
- free_pb_on_exit = true;
-
- Geom::OptRect area = SVGElem->getBounds(Geom::identity());
-
- NRRectL rect;
- rect.x0=area->min()[Geom::X];
- rect.x1=area->max()[Geom::X];
- rect.y0=area->min()[Geom::Y];
- rect.y1=area->max()[Geom::Y];
-
- width = (int)(rect.x1-rect.x0);
- height = (int)(rect.y1-rect.y0);
- rowstride = 4*width;
- has_alpha = true;
-
- if (image_pixbuf) g_free(image_pixbuf);
- image_pixbuf = g_try_new(unsigned char, 4L * width * height);
- if(image_pixbuf != NULL)
- {
- memset(image_pixbuf, 0x00, 4 * width * height);
-
- NRGC gc(NULL);
- /* Update to renderable state */
- double sf = 1.0;
- Geom::Affine t(Geom::Scale(sf, sf));
- nr_arena_item_set_transform(ai, &t);
- gc.transform.setIdentity();
- nr_arena_item_invoke_update( ai, NULL, &gc,
- NR_ARENA_ITEM_STATE_ALL,
- NR_ARENA_ITEM_STATE_NONE );
- nr_pixblock_setup_extern(pb, NR_PIXBLOCK_MODE_R8G8B8A8N,
- (int)rect.x0, (int)rect.y0, (int)rect.x1, (int)rect.y1,
- image_pixbuf, 4 * width, FALSE, FALSE );
-
- nr_arena_item_invoke_render(NULL, ai, &rect, pb, NR_ARENA_ITEM_RENDER_NO_CACHE);
- }
- else
- {
- g_warning("FilterImage::render: not enough memory to create pixel buffer. Need %ld.", 4L * width * height);
- }
+ Geom::Rect area = *optarea;
+ Geom::Affine pu2pb = slot.get_units().get_matrix_primitiveunits2pb();
+
+ double scaleX = feImageWidth / area.width();
+ double scaleY = feImageHeight / area.height();
+
+ Geom::Rect sa = slot.get_slot_area();
+ cairo_surface_t *out = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
+ sa.width(), sa.height());
+ cairo_t *ct = cairo_create(out);
+ cairo_translate(ct, -sa.min()[Geom::X], -sa.min()[Geom::Y]);
+ ink_cairo_transform(ct, pu2pb); // we are now in primitive units
+ cairo_translate(ct, feImageX, feImageY);
+ cairo_scale(ct, scaleX, scaleY);
+
+ NRRectL render_rect;
+ render_rect.x0 = floor(area.left());
+ render_rect.y0 = floor(area.top());
+ render_rect.x1 = ceil(area.right());
+ render_rect.y1 = ceil(area.bottom());
+ cairo_translate(ct, render_rect.x0, render_rect.y0);
+
+ // Update to renderable state
+ NRGC gc(NULL);
+ Geom::Affine t = Geom::identity();
+ nr_arena_item_set_transform(ai, &t);
+ gc.transform.setIdentity();
+ nr_arena_item_invoke_update(ai, NULL, &gc,
+ NR_ARENA_ITEM_STATE_ALL,
+ NR_ARENA_ITEM_STATE_NONE);
+ nr_arena_item_invoke_render(ct, ai, &render_rect, NULL, NR_ARENA_ITEM_RENDER_NO_CACHE);
SVGElem->invoke_hide(key);
- nr_object_unref((NRObject *) arena);
- }
+ nr_object_unref((NRObject*) arena);
+ slot.set(_output, out);
+ cairo_surface_destroy(out);
+ return;
+ }
- if (!image_pixbuf){
+ if (!image && !broken_ref) {
+ broken_ref = true;
try {
/* TODO: If feImageHref is absolute, then use that (preferably handling the
* case that it's not a file URI). Otherwise, go up the tree looking
@@ -127,190 +144,92 @@ int FilterImage::render(FilterSlot &slot, FilterUnits const &units) {
if ( !g_file_test( fullname, G_FILE_TEST_EXISTS ) ) {
// Should display Broken Image png.
g_warning("FilterImage::render: Can not find: %s", feImageHref );
+ return;
}
image = Gdk::Pixbuf::create_from_file(fullname);
if( fullname != feImageHref ) g_free( fullname );
}
catch (const Glib::FileError & e)
{
- g_warning("caught Glib::FileError in FilterImage::render %i", e.code() );
- return 0;
+ g_warning("caught Glib::FileError in FilterImage::render: %s", e.what().data() );
+ return;
}
catch (const Gdk::PixbufError & e)
{
- g_warning("Gdk::PixbufError in FilterImage::render: %i", e.code() );
- return 0;
+ g_warning("Gdk::PixbufError in FilterImage::render: %s", e.what().data() );
+ return;
}
- if ( !image ) return 0;
+ if ( !image ) return;
- // Native size of image
- width = image->get_width();
- height = image->get_height();
- rowstride = image->get_rowstride();
- image_pixbuf = image->get_pixels();
- has_alpha = image->get_has_alpha();
- }
+ broken_ref = false;
- // Viewport is filter primitive area (in user coordinates).
- Geom::Rect vp = filter_primitive_area( units );
- double feImageX = vp.min()[Geom::X];
- double feImageY = vp.min()[Geom::Y];
- double feImageWidth = vp.width();
- double feImageHeight = vp.height();
-
- // Now that we have the viewport, we must map image inside.
- // Partially copied from sp-image.cpp.
-
- // Do nothing if preserveAspectRatio is "none".
- if( aspect_align != SP_ASPECT_NONE ) {
-
- // Check aspect ratio of image vs. viewport
- double feAspect = feImageHeight/feImageWidth;
- double aspect = (double)height/(double)width;
- bool ratio = (feAspect < aspect);
-
- double ax, ay; // Align side
- switch( aspect_align ) {
- case SP_ASPECT_XMIN_YMIN:
- ax = 0.0;
- ay = 0.0;
- break;
- case SP_ASPECT_XMID_YMIN:
- ax = 0.5;
- ay = 0.0;
- break;
- case SP_ASPECT_XMAX_YMIN:
- ax = 1.0;
- ay = 0.0;
- break;
- case SP_ASPECT_XMIN_YMID:
- ax = 0.0;
- ay = 0.5;
- break;
- case SP_ASPECT_XMID_YMID:
- ax = 0.5;
- ay = 0.5;
- break;
- case SP_ASPECT_XMAX_YMID:
- ax = 1.0;
- ay = 0.5;
- break;
- case SP_ASPECT_XMIN_YMAX:
- ax = 0.0;
- ay = 1.0;
- break;
- case SP_ASPECT_XMID_YMAX:
- ax = 0.5;
- ay = 1.0;
- break;
- case SP_ASPECT_XMAX_YMAX:
- ax = 1.0;
- ay = 1.0;
- break;
- default:
- ax = 0.0;
- ay = 0.0;
- break;
+ bool has_alpha = image->get_has_alpha();
+ if (!has_alpha) {
+ image = image->add_alpha(false, 0, 0, 0);
}
- if( aspect_clip == SP_ASPECT_SLICE ) {
- // image clipped by viewbox
-
- if( ratio ) {
- // clip top/bottom
- feImageY -= ay * (feImageWidth * aspect - feImageHeight);
- feImageHeight = feImageWidth * aspect;
- } else {
- // clip sides
- feImageX -= ax * (feImageHeight / aspect - feImageWidth);
- feImageWidth = feImageHeight / aspect;
- }
+ // Native size of image
+ //width = image->get_width();
+ //height = image->get_height();
+ //rowstride = image->get_rowstride();
- } else {
- // image fits into viewbox
-
- if( ratio ) {
- // fit to height
- feImageX += ax * (feImageWidth - feImageHeight / aspect );
- feImageWidth = feImageHeight / aspect;
- } else {
- // fit to width
- feImageY += ay * (feImageHeight - feImageWidth * aspect);
- feImageHeight = feImageWidth * aspect;
- }
- }
- }
+ convert_pixbuf_normal_to_argb32(image->gobj());
- // Set up user coordinates to pix block transforms
- double scaleX = width/feImageWidth;
- double scaleY = height/feImageHeight;
- Geom::Affine unit_trans = units.get_matrix_user2pb().inverse();
-
- // Region being drawn on screen. Corresponds to Filter Region in current screen coordinates.
- // Note, that the screen is refreshed in horizontal slices with y-axis inverted.
- NRPixBlock *in = slot.get(_input);
- if (!in) {
- g_warning("Missing source image for feImage (in=%d)", _input);
- return 1;
- }
- int x0 = in->area.x0, y0 = in->area.y0;
- int x1 = in->area.x1, y1 = in->area.y1;
- int w = x1 - x0;
-
- Geom::Affine d2s = Geom::Translate(x0, y0) * unit_trans * Geom::Translate(-feImageX,-feImageY) * Geom::Scale(scaleX, scaleY);
-
- // Set up pix block
- NRPixBlock *out = new NRPixBlock;
- nr_pixblock_setup_fast(out, NR_PIXBLOCK_MODE_R8G8B8A8P, x0, y0, x1, y1, true);
- unsigned char *out_data = NR_PIXBLOCK_PX(out);
-
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- int nr_arena_image_x_sample = prefs->getInt("/options/bitmapoversample/value", 1);
- int nr_arena_image_y_sample = nr_arena_image_x_sample;
-
-
- if (has_alpha) {
- nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_N_TRANSFORM(out_data, x1-x0, y1-y0, 4*w, image_pixbuf, width, height, rowstride, d2s, 255, nr_arena_image_x_sample, nr_arena_image_y_sample);
- } else {
- for (int x=x0; x < x1; x++){
- for (int y=y0; y < y1; y++){
- //TODO: use interpolation
- // Temporarily add 0.5 so we sample center of "cell"
- double indexX = scaleX * (((x+0.5) * unit_trans[0] + unit_trans[4]) - feImageX);
- double indexY = scaleY * (((y+0.5) * unit_trans[3] + unit_trans[5]) - feImageY);
-
- // coordx == 0 and coordy == 0 must be included, but we protect
- // against negative numbers which round up to 0 with (int).
- int coordx = ( indexX >= 0 ? int( indexX ) : -1 );
- int coordy = ( indexY >= 0 ? int( indexY ) : -1 );
- if (coordx >= 0 && coordx < width && coordy >= 0 && coordy < height){
- out_data[4*((x - x0)+w*(y - y0)) ] = (unsigned char) image_pixbuf[3*coordx + rowstride*coordy ]; //Red
- out_data[4*((x - x0)+w*(y - y0)) + 1] = (unsigned char) image_pixbuf[3*coordx + rowstride*coordy + 1]; //Green
- out_data[4*((x - x0)+w*(y - y0)) + 2] = (unsigned char) image_pixbuf[3*coordx + rowstride*coordy + 2]; //Blue
- out_data[4*((x - x0)+w*(y - y0)) + 3] = 255; //Alpha
- }
- }
- }
- }
- if (free_pb_on_exit) {
- nr_pixblock_release(pb);
- delete pb;
+ image_surface = cairo_image_surface_create_for_data(image->get_pixels(),
+ CAIRO_FORMAT_ARGB32, image->get_width(), image->get_height(), image->get_rowstride());
}
- out->empty = FALSE;
+ Geom::Rect sa = slot.get_slot_area();
+ cairo_surface_t *out = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
+ sa.width(), sa.height());
+
+ cairo_t *ct = cairo_create(out);
+ cairo_translate(ct, -sa.min()[Geom::X], -sa.min()[Geom::Y]);
+ // now ct is in pb coordinates
+ ink_cairo_transform(ct, slot.get_units().get_matrix_primitiveunits2pb());
+ // now ct is in the coordinates of feImageX etc.
+
+ // TODO: add preserveAspectRatio support here
+
+ double scaleX = feImageWidth / image->get_width();
+ double scaleY = feImageHeight / image->get_height();
+
+ cairo_translate(ct, feImageX, feImageY);
+ cairo_scale(ct, scaleX, scaleY);
+ cairo_set_source_surface(ct, image_surface, 0, 0);
+ cairo_paint(ct);
+ cairo_destroy(ct);
+
slot.set(_output, out);
- return 0;
+}
+
+bool FilterImage::can_handle_affine(Geom::Affine const &)
+{
+ return true;
}
void FilterImage::set_href(const gchar *href){
if (feImageHref) g_free (feImageHref);
feImageHref = (href) ? g_strdup (href) : NULL;
+
+ if (image_surface) {
+ cairo_surface_destroy(image_surface);
+ }
+ image.reset();
+ broken_ref = false;
}
void FilterImage::set_document(SPDocument *doc){
document = doc;
}
+void FilterImage::set_region(SVGLength x, SVGLength y, SVGLength width, SVGLength height) {
+ feImageX=x.computed;
+ feImageY=y.computed;
+ feImageWidth=width.computed;
+ feImageHeight=height.computed;
+}
+
void FilterImage::set_align( unsigned int align ) {
aspect_align = align;
}
@@ -319,10 +238,6 @@ void FilterImage::set_clip( unsigned int clip ) {
aspect_clip = clip;
}
-FilterTraits FilterImage::get_input_traits() {
- return TRAIT_PARALLER;
-}
-
} /* namespace Filters */
} /* namespace Inkscape */
diff --git a/src/display/nr-filter-image.h b/src/display/nr-filter-image.h
index ecbc9597d..0651109ec 100644
--- a/src/display/nr-filter-image.h
+++ b/src/display/nr-filter-image.h
@@ -27,10 +27,11 @@ public:
static FilterPrimitive *create();
virtual ~FilterImage();
- virtual int render(FilterSlot &slot, FilterUnits const &units);
- virtual FilterTraits get_input_traits();
+ virtual void render_cairo(FilterSlot &slot);
+ virtual bool can_handle_affine(Geom::Affine const &);
void set_document( SPDocument *document );
void set_href(const gchar *href);
+ void set_region(SVGLength x, SVGLength y, SVGLength width, SVGLength height);
void set_align( unsigned int align );
void set_clip( unsigned int clip );
bool from_element;
@@ -39,12 +40,11 @@ public:
private:
SPDocument *document;
gchar *feImageHref;
- guint8* image_pixbuf;
Glib::RefPtr<Gdk::Pixbuf> image;
- int width, height, rowstride;
- unsigned int aspect_align : 4;
- unsigned int aspect_clip : 1;
- bool has_alpha;
+ cairo_surface_t *image_surface;
+ float feImageX, feImageY, feImageWidth, feImageHeight;
+ unsigned int aspect_align, aspect_clip;
+ bool broken_ref;
};
} /* namespace Filters */
diff --git a/src/display/nr-filter-merge.cpp b/src/display/nr-filter-merge.cpp
index 971dcb80f..51d3975cb 100644
--- a/src/display/nr-filter-merge.cpp
+++ b/src/display/nr-filter-merge.cpp
@@ -9,28 +9,11 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include <cmath>
#include <vector>
-
-#include "2geom/isnan.h"
-#include "filters/merge.h"
+#include "display/cairo-utils.h"
#include "display/nr-filter-merge.h"
-#include "display/nr-filter-pixops.h"
#include "display/nr-filter-slot.h"
-#include "display/nr-filter-units.h"
#include "display/nr-filter-utils.h"
-#include "libnr/nr-blit.h"
-#include "libnr/nr-pixblock.h"
-#include "libnr/nr-pixops.h"
-
-inline void
-composite_over(unsigned char *r, unsigned char const *a, unsigned char const *b)
-{
- r[0] = a[0] + NR_NORMALIZE_21(b[0] * (255 - a[3]));
- r[1] = a[1] + NR_NORMALIZE_21(b[1] * (255 - a[3]));
- r[2] = a[2] + NR_NORMALIZE_21(b[2] * (255 - a[3]));
- r[3] = a[3] + NR_NORMALIZE_21(b[3] * (255 - a[3]));
-}
namespace Inkscape {
namespace Filters {
@@ -46,70 +29,42 @@ FilterPrimitive * FilterMerge::create() {
FilterMerge::~FilterMerge()
{}
-int FilterMerge::render(FilterSlot &slot, FilterUnits const &/*units*/) {
- NRPixBlock *in[_input_image.size()];
- NRPixBlock *original_in[_input_image.size()];
-
- for (unsigned int i = 0 ; i < _input_image.size() ; i++) {
- in[i] = slot.get(_input_image[i]);
- original_in[i] = in[i];
- }
-
- NRPixBlock *out;
-
- // Bail out if one of source images is missing
- for (unsigned int i = 0 ; i < _input_image.size() ; i++) {
- bool missing = false;
- if (!in[i]) {
- g_warning("Missing source image for feMerge (number=%d slot=%d)", i, _input_image[i]);
- missing = true;
- }
- if (missing) return 1;
- }
-
- out = new NRPixBlock;
- NRRectL out_area = in[0]->area;
- for (unsigned int i = 1 ; i < _input_image.size() ; i++) {
- nr_rect_l_union(&out_area, &out_area, &in[i]->area);
- }
- nr_pixblock_setup_fast(out, NR_PIXBLOCK_MODE_R8G8B8A8P,
- out_area.x0, out_area.y0, out_area.x1, out_area.y1,
- true);
-
- // Merge is defined for premultiplied RGBA values, thus convert them to
- // that format before blending
- for (unsigned int i = 0 ; i < _input_image.size() ; i++) {
- if (in[i]->mode != NR_PIXBLOCK_MODE_R8G8B8A8P) {
- in[i] = new NRPixBlock;
- nr_pixblock_setup_fast(in[i], NR_PIXBLOCK_MODE_R8G8B8A8P,
- original_in[i]->area.x0,
- original_in[i]->area.y0,
- original_in[i]->area.x1,
- original_in[i]->area.y1,
- false);
- nr_blit_pixblock_pixblock(in[i], original_in[i]);
+void FilterMerge::render_cairo(FilterSlot &slot)
+{
+ if (_input_image.size() == 0) return;
+
+ // output is RGBA if at least one input is RGBA
+ bool rgba32 = false;
+ cairo_surface_t *out = NULL;
+ for (std::vector<int>::iterator i = _input_image.begin(); i != _input_image.end(); ++i) {
+ cairo_surface_t *in = slot.getcairo(*i);
+ if (cairo_surface_get_content(in) == CAIRO_CONTENT_COLOR_ALPHA) {
+ out = ink_cairo_surface_create_identical(in);
+ rgba32 = true;
+ break;
}
}
- /* pixops_mix is defined in display/nr-filter-pixops.h
- * It mixes the two input images with the function given as template
- * and places the result in output image.
- */
- for (unsigned int i = 0 ; i < _input_image.size() ; i++) {
- pixops_mix<composite_over>(*out, *in[i], *out);
+ if (!rgba32) {
+ out = ink_cairo_surface_create_identical(slot.getcairo(_input_image[0]));
}
+ cairo_t *out_ct = cairo_create(out);
- for (unsigned int i = 0 ; i < _input_image.size() ; i++) {
- if (in[i] != original_in[i]) {
- nr_pixblock_release(in[i]);
- delete in[i];
- }
+ for (std::vector<int>::iterator i = _input_image.begin(); i != _input_image.end(); ++i) {
+ cairo_surface_t *in = slot.getcairo(*i);
+ cairo_set_source_surface(out_ct, in, 0, 0);
+ cairo_paint(out_ct);
}
- out->empty = FALSE;
+ cairo_destroy(out_ct);
slot.set(_output, out);
+ cairo_surface_destroy(out);
+}
- return 0;
+bool FilterMerge::can_handle_affine(Geom::Affine const &)
+{
+ // Merge is a per-pixel primitive and is immutable under transformations
+ return true;
}
void FilterMerge::set_input(int slot) {
diff --git a/src/display/nr-filter-merge.h b/src/display/nr-filter-merge.h
index 715f20d83..263fc8026 100644
--- a/src/display/nr-filter-merge.h
+++ b/src/display/nr-filter-merge.h
@@ -13,11 +13,7 @@
*/
#include <vector>
-
-#include "filters/merge.h"
#include "display/nr-filter-primitive.h"
-#include "display/nr-filter-slot.h"
-#include "display/nr-filter-units.h"
namespace Inkscape {
namespace Filters {
@@ -28,7 +24,8 @@ public:
static FilterPrimitive *create();
virtual ~FilterMerge();
- virtual int render(FilterSlot &slot, FilterUnits const &units);
+ virtual void render_cairo(FilterSlot &);
+ virtual bool can_handle_affine(Geom::Affine const &);
virtual void set_input(int input);
virtual void set_input(int input, int slot);
diff --git a/src/display/nr-filter-morphology.cpp b/src/display/nr-filter-morphology.cpp
index ceb2a2b9d..c79667d3e 100644
--- a/src/display/nr-filter-morphology.cpp
+++ b/src/display/nr-filter-morphology.cpp
@@ -10,9 +10,12 @@
*/
#include <cmath>
+#include <algorithm>
+#include "display/cairo-templates.h"
+#include "display/cairo-utils.h"
#include "display/nr-filter-morphology.h"
+#include "display/nr-filter-slot.h"
#include "display/nr-filter-units.h"
-#include "libnr/nr-blit.h"
namespace Inkscape {
namespace Filters {
@@ -28,94 +31,126 @@ FilterPrimitive * FilterMorphology::create() {
FilterMorphology::~FilterMorphology()
{}
-int FilterMorphology::render(FilterSlot &slot, FilterUnits const &units) {
- NRPixBlock *in = slot.get(_input);
- if (!in) {
- g_warning("Missing source image for feMorphology (in=%d)", _input);
- return 1;
- }
-
- NRPixBlock *out = new NRPixBlock;
-
- // this primitive is defined for premultiplied RGBA values,
- // thus convert them to that format
- bool free_in_on_exit = false;
- if (in->mode != NR_PIXBLOCK_MODE_R8G8B8A8P) {
- NRPixBlock *original_in = in;
- in = new NRPixBlock;
- nr_pixblock_setup_fast(in, NR_PIXBLOCK_MODE_R8G8B8A8P,
- original_in->area.x0, original_in->area.y0,
- original_in->area.x1, original_in->area.y1,
- true);
- nr_blit_pixblock_pixblock(in, original_in);
- free_in_on_exit = true;
- }
+enum MorphologyOp {
+ ERODE,
+ DILATE
+};
+
+namespace {
+
+/* This performs one "half" of the morphology operation by calculating
+ * the componentwise extreme in the specified axis with the given radius.
+ * Performing the operation one axis at a time gives us a MASSIVE performance boost
+ * at large morphology radii. Extreme of row extremes is equal to the extreme
+ * of components, so this doesn't change the result. */
+template <MorphologyOp OP, Geom::Dim2 axis>
+struct Morphology : public SurfaceSynth {
+ Morphology(cairo_surface_t *in, double xradius)
+ : SurfaceSynth(in)
+ , _radius(round(xradius))
+ {}
+ guint32 operator()(int x, int y) {
+ int start, end;
+ if (axis == Geom::X) {
+ start = std::max(0, x - _radius);
+ end = std::min(x + _radius + 1, _w);
+ } else {
+ start = std::max(0, y - _radius);
+ end = std::min(y + _radius + 1, _h);
+ }
- Geom::Affine p2pb = units.get_matrix_primitiveunits2pb();
- int const xradius = (int)round(this->xradius * p2pb.expansionX());
- int const yradius = (int)round(this->yradius * p2pb.expansionY());
-
- int x0=in->area.x0;
- int y0=in->area.y0;
- int x1=in->area.x1;
- int y1=in->area.y1;
- int w=x1-x0, h=y1-y0;
- int x, y, i, j;
- int rmax,gmax,bmax,amax;
- int rmin,gmin,bmin,amin;
-
- nr_pixblock_setup_fast(out, in->mode, x0, y0, x1, y1, true);
-
- unsigned char *in_data = NR_PIXBLOCK_PX(in);
- unsigned char *out_data = NR_PIXBLOCK_PX(out);
-
- for(x = 0 ; x < w ; x++){
- for(y = 0 ; y < h ; y++){
- rmin = gmin = bmin = amin = 255;
- rmax = gmax = bmax = amax = 0;
- for(i = x - xradius ; i < x + xradius ; i++){
- if (i < 0 || i >= w) continue;
- for(j = y - yradius ; j < y + yradius ; j++){
- if (j < 0 || j >= h) continue;
- if(in_data[4*(i + w*j)]>rmax) rmax = in_data[4*(i + w*j)];
- if(in_data[4*(i + w*j)+1]>gmax) gmax = in_data[4*(i + w*j)+1];
- if(in_data[4*(i + w*j)+2]>bmax) bmax = in_data[4*(i + w*j)+2];
- if(in_data[4*(i + w*j)+3]>amax) amax = in_data[4*(i + w*j)+3];
-
- if(in_data[4*(i + w*j)]<rmin) rmin = in_data[4*(i + w*j)];
- if(in_data[4*(i + w*j)+1]<gmin) gmin = in_data[4*(i + w*j)+1];
- if(in_data[4*(i + w*j)+2]<bmin) bmin = in_data[4*(i + w*j)+2];
- if(in_data[4*(i + w*j)+3]<amin) amin = in_data[4*(i + w*j)+3];
+ guint32 ao = (OP == DILATE ? 0 : 255);
+ guint32 ro = (OP == DILATE ? 0 : 255);
+ guint32 go = (OP == DILATE ? 0 : 255);
+ guint32 bo = (OP == DILATE ? 0 : 255);
+
+ if (_alpha) {
+ ao = (OP == DILATE ? 0 : 0xff000000);
+ for (int i = start; i < end; ++i) {
+ guint32 px = (axis == Geom::X ? pixelAt(i, y) : pixelAt(x, i));
+ if (OP == DILATE) {
+ if (px > ao) ao = px;
+ } else {
+ if (px < ao) ao = px;
}
}
- if (Operator==MORPHOLOGY_OPERATOR_DILATE){
- out_data[4*(x + w*y)]=rmax;
- out_data[4*(x + w*y)+1]=gmax;
- out_data[4*(x + w*y)+2]=bmax;
- out_data[4*(x + w*y)+3]=amax;
- } else {
- out_data[4*(x + w*y)]=rmin;
- out_data[4*(x + w*y)+1]=gmin;
- out_data[4*(x + w*y)+2]=bmin;
- out_data[4*(x + w*y)+3]=amin;
+ return ao;
+ } else {
+ for (int i = start; i < end; ++i) {
+ guint32 px = (axis == Geom::X ? pixelAt(i, y) : pixelAt(x, i));
+ EXTRACT_ARGB32(px, a,r,g,b);
+
+ // this will be compiled to conditional moves;
+ // the operator comparison will be evaluated at compile time.
+ // therefore there will be no branching in this loop
+ if (OP == DILATE) {
+ if (a > ao) ao = a;
+ if (r > ro) ro = r;
+ if (g > go) go = g;
+ if (b > bo) bo = b;
+ } else {
+ if (a < ao) ao = a;
+ if (r < ro) ro = r;
+ if (g < go) go = g;
+ if (b < bo) bo = b;
+ }
+
+ // TODO: verify whether this check gives any speedup.
+ if (OP == ERODE && a == 0) break;
}
+
+ ASSEMBLE_ARGB32(pxout, ao,ro,go,bo)
+ return pxout;
}
}
+private:
+ int _radius;
+};
+
+} // end anonymous namespace
- if (free_in_on_exit) {
- nr_pixblock_release(in);
- delete in;
+void FilterMorphology::render_cairo(FilterSlot &slot)
+{
+ cairo_surface_t *input = slot.getcairo(_input);
+
+ if (xradius == 0.0 || yradius == 0.0) {
+ // output is transparent black
+ cairo_surface_t *out = ink_cairo_surface_create_identical(input);
+ slot.set(_output, out);
+ cairo_surface_destroy(out);
+ return;
}
- out->empty = FALSE;
+ Geom::Affine p2pb = slot.get_units().get_matrix_primitiveunits2pb();
+ double xr = xradius * p2pb.expansionX();
+ double yr = yradius * p2pb.expansionY();
+
+ cairo_surface_t *interm = ink_cairo_surface_create_identical(input);
+
+ if (Operator == MORPHOLOGY_OPERATOR_DILATE) {
+ ink_cairo_surface_synthesize(interm, Morphology<DILATE, Geom::X>(input, xr));
+ } else {
+ ink_cairo_surface_synthesize(interm, Morphology<ERODE, Geom::X>(input, xr));
+ }
+
+ cairo_surface_t *out = ink_cairo_surface_create_identical(input);
+
+ if (Operator == MORPHOLOGY_OPERATOR_DILATE) {
+ ink_cairo_surface_synthesize(out, Morphology<DILATE, Geom::Y>(interm, yr));
+ } else {
+ ink_cairo_surface_synthesize(out, Morphology<ERODE, Geom::Y>(interm, yr));
+ }
+
+ cairo_surface_destroy(interm);
+
slot.set(_output, out);
- return 0;
+ cairo_surface_destroy(out);
}
void FilterMorphology::area_enlarge(NRRectL &area, Geom::Affine const &trans)
{
- int const enlarge_x = (int)std::ceil(this->xradius * (std::fabs(trans[0]) + std::fabs(trans[1])));
- int const enlarge_y = (int)std::ceil(this->yradius * (std::fabs(trans[2]) + std::fabs(trans[3])));
+ int enlarge_x = ceil(xradius * trans.expansionX());
+ int enlarge_y = ceil(yradius * trans.expansionY());
area.x0 -= enlarge_x;
area.x1 += enlarge_x;
@@ -135,10 +170,6 @@ void FilterMorphology::set_yradius(double y){
yradius = y;
}
-FilterTraits FilterMorphology::get_input_traits() {
- return TRAIT_PARALLER;
-}
-
} /* namespace Filters */
} /* namespace Inkscape */
diff --git a/src/display/nr-filter-morphology.h b/src/display/nr-filter-morphology.h
index c8d8b2f50..5924085d9 100644
--- a/src/display/nr-filter-morphology.h
+++ b/src/display/nr-filter-morphology.h
@@ -13,12 +13,12 @@
*/
#include "display/nr-filter-primitive.h"
-#include "display/nr-filter-slot.h"
-#include "display/nr-filter-units.h"
namespace Inkscape {
namespace Filters {
+class FilterSlot;
+
enum FilterMorphologyOperator {
MORPHOLOGY_OPERATOR_ERODE,
MORPHOLOGY_OPERATOR_DILATE,
@@ -31,9 +31,8 @@ public:
static FilterPrimitive *create();
virtual ~FilterMorphology();
- virtual int render(FilterSlot &slot, FilterUnits const &units);
+ virtual void render_cairo(FilterSlot &slot);
virtual void area_enlarge(NRRectL &area, Geom::Affine const &trans);
- virtual FilterTraits get_input_traits();
void set_operator(FilterMorphologyOperator &o);
void set_xradius(double x);
void set_yradius(double y);
diff --git a/src/display/nr-filter-offset.cpp b/src/display/nr-filter-offset.cpp
index 7c924b7b7..3b0f83841 100644
--- a/src/display/nr-filter-offset.cpp
+++ b/src/display/nr-filter-offset.cpp
@@ -9,11 +9,10 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
+#include "display/cairo-utils.h"
#include "display/nr-filter-offset.h"
#include "display/nr-filter-slot.h"
#include "display/nr-filter-units.h"
-#include "libnr/nr-blit.h"
-#include "libnr/nr-pixblock.h"
#include "libnr/nr-rect-l.h"
namespace Inkscape {
@@ -33,37 +32,29 @@ FilterPrimitive * FilterOffset::create() {
FilterOffset::~FilterOffset()
{}
-int FilterOffset::render(FilterSlot &slot, FilterUnits const &units) {
- NRPixBlock *in = slot.get(_input);
- // Bail out if source image is missing
- if (!in) {
- g_warning("Missing source image for feOffset (in=%d)", _input);
- return 1;
- }
-
- NRPixBlock *out = new NRPixBlock;
+void FilterOffset::render_cairo(FilterSlot &slot)
+{
+ cairo_surface_t *in = slot.getcairo(_input);
+ cairo_surface_t *out = ink_cairo_surface_create_identical(in);
+ cairo_t *ct = cairo_create(out);
- Geom::Affine trans = units.get_matrix_primitiveunits2pb();
+ Geom::Affine trans = slot.get_units().get_matrix_primitiveunits2pb();
Geom::Point offset(dx, dy);
offset *= trans;
offset[X] -= trans[4];
offset[Y] -= trans[5];
- nr_pixblock_setup_fast(out, in->mode,
- in->area.x0, in->area.y0, in->area.x1, in->area.y1,
- true);
- nr_blit_pixblock_pixblock(out, in);
+ cairo_set_source_surface(ct, in, offset[X], offset[Y]);
+ cairo_paint(ct);
+ cairo_destroy(ct);
- out->area.x0 += static_cast<NR::ICoord>(offset[X]);
- out->area.y0 += static_cast<NR::ICoord>(offset[Y]);
- out->area.x1 += static_cast<NR::ICoord>(offset[X]);
- out->area.y1 += static_cast<NR::ICoord>(offset[Y]);
- out->visible_area = out->area;
-
- out->empty = FALSE;
slot.set(_output, out);
+ cairo_surface_destroy(out);
+}
- return 0;
+bool FilterOffset::can_handle_affine(Geom::Affine const &)
+{
+ return true;
}
void FilterOffset::set_dx(double amount) {
@@ -82,15 +73,15 @@ void FilterOffset::area_enlarge(NRRectL &area, Geom::Affine const &trans)
offset[Y] -= trans[5];
if (offset[X] > 0) {
- area.x0 -= static_cast<NR::ICoord>(offset[X]);
+ area.x0 -= ceil(offset[X]);
} else {
- area.x1 -= static_cast<NR::ICoord>(offset[X]);
+ area.x1 -= floor(offset[X]);
}
if (offset[Y] > 0) {
- area.y0 -= static_cast<NR::ICoord>(offset[Y]);
+ area.y0 -= ceil(offset[Y]);
} else {
- area.y1 -= static_cast<NR::ICoord>(offset[Y]);
+ area.y1 -= floor(offset[Y]);
}
}
diff --git a/src/display/nr-filter-offset.h b/src/display/nr-filter-offset.h
index a78450e17..09c57f803 100644
--- a/src/display/nr-filter-offset.h
+++ b/src/display/nr-filter-offset.h
@@ -26,8 +26,9 @@ public:
static FilterPrimitive *create();
virtual ~FilterOffset();
- virtual int render(FilterSlot &slot, FilterUnits const &units);
+ virtual void render_cairo(FilterSlot &slot);
virtual void area_enlarge(NRRectL &area, Geom::Affine const &trans);
+ virtual bool can_handle_affine(Geom::Affine const &);
void set_dx(double amount);
void set_dy(double amount);
diff --git a/src/display/nr-filter-pixops.h b/src/display/nr-filter-pixops.h
deleted file mode 100644
index afd9e98bd..000000000
--- a/src/display/nr-filter-pixops.h
+++ /dev/null
@@ -1,104 +0,0 @@
-#ifndef __NR_FILTER_PIXOPS_H__
-#define __NR_FILTER_PIXOPS_H__
-
-#include "libnr/nr-pixblock.h"
-#include <algorithm>
-
-/*
- * Per-pixel image manipulation functions.
- * These can be used by all filter primitives, which combine two images on
- * per-pixel basis. These are at least feBlend, feComposite and feMerge.
- *
- * Authors:
- * Niko Kiirala <niko@kiirala.com>
- *
- * Copyright (C) 2007 authors
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-namespace Inkscape {
-namespace Filters {
-
-/**
- * Mixes the two input images using the function given as template.
- * The result is placed in out.
- * The mixing function should have the following type:
- * void mix(unsigned char *result, unsigned char const *in1,
- * unsigned char const *in2);
- * Each of the parameters for mix-function is a pointer to four bytes of data,
- * giving the RGBA values for that pixel. The mix function must only access
- * the four bytes beginning at a pointer given as parameter.
- */
-/*
- * The implementation is in a header file because of the template. It has to
- * be in the same compilation unit as the code using it. Otherwise, linking
- * the program will not succeed.
- */
-template <void(*blend)(unsigned char *cr, unsigned char const *ca, unsigned char const *cb)>
-void pixops_mix(NRPixBlock &out, NRPixBlock &in1, NRPixBlock &in2) {
- unsigned char *in1_data = NR_PIXBLOCK_PX(&in1);
- unsigned char *in2_data = NR_PIXBLOCK_PX(&in2);
- unsigned char *out_data = NR_PIXBLOCK_PX(&out);
- unsigned char zero_rgba[4] = {0, 0, 0, 0};
-
- // Possible scenarios (omitting cases where an interval is empty and those which are the same by interchanging 1 and 2):
- // 01020, 01320, 01310 (no overlap, partial overlap, full overlap)
- int out_y0 = out.area.y0;
- int out_y1 = std::max(out.area.y1,out_y0); // Enforce sanity
- int in1_y0 = std::min(std::max(in1.area.y0,out_y0),out_y1);
- int in2_y0 = std::min(std::max(in2.area.y0,out_y0),out_y1);
- int in1_y1 = std::min(std::max(in1.area.y1,in1_y0),out_y1);
- int in2_y1 = std::min(std::max(in2.area.y1,in2_y0),out_y1);
- int min_in_y0 = std::min(in1_y0,in2_y0);
- int max_in_y0 = std::max(in1_y0,in2_y0);
- int min_in_y1 = std::min(in1_y1,in2_y1);
- int max_in_y1 = std::max(in1_y1,in2_y1);
- int const yBound[6] = {out_y0, min_in_y0, std::min(max_in_y0,min_in_y1), std::max(max_in_y0,min_in_y1), max_in_y1, out_y1};
- bool const in1_zero_y[5] = {true, in1_y0>yBound[1], in1_y0>yBound[2] || in1_y1<=yBound[2], in1_y1<=yBound[3], true};
- bool const in2_zero_y[5] = {true, in2_y0>yBound[1], in2_y0>yBound[2] || in2_y1<=yBound[2], in2_y1<=yBound[3], true};
-
- int out_x0 = out.area.x0;
- int out_x1 = std::max(out.area.x1,out_x0);
- int in1_x0 = std::min(std::max(in1.area.x0,out_x0),out_x1);
- int in2_x0 = std::min(std::max(in2.area.x0,out_x0),out_x1);
- int in1_x1 = std::min(std::max(in1.area.x1,in1_x0),out_x1);
- int in2_x1 = std::min(std::max(in2.area.x1,in2_x0),out_x1);
- int min_in_x0 = std::min(in1_x0,in2_x0);
- int max_in_x0 = std::max(in1_x0,in2_x0);
- int min_in_x1 = std::min(in1_x1,in2_x1);
- int max_in_x1 = std::max(in1_x1,in2_x1);
- int const xBound[6] = {out_x0, min_in_x0, std::min(max_in_x0,min_in_x1), std::max(max_in_x0,min_in_x1), max_in_x1, out_x1};
- bool const in1_zero_x[5] = {true, in1_x0>xBound[1], in1_x0>xBound[2] || in1_x1<=xBound[2], in1_x1<=xBound[3], true};
- bool const in2_zero_x[5] = {true, in2_x0>xBound[1], in2_x0>xBound[2] || in2_x1<=xBound[2], in2_x1<=xBound[3], true};
-
- for (int yr = 0 ; yr < 5 ; yr++) {
- for(int y = yBound[yr] ; y < yBound[yr+1] ; y++) {
- int out_line = (y - out.area.y0) * out.rs;
- int in1_line = (y - in1.area.y0) * in1.rs;
- int in2_line = (y - in2.area.y0) * in2.rs;
- for (int xr = 0 ; xr < 5 ; xr++) {
- for(int x = xBound[xr] ; x < xBound[xr+1] ; x++) {
- blend(out_data + out_line + 4 * (x - out.area.x0),
- (in1_zero_x[xr]||in1_zero_y[yr]) ? zero_rgba : (in1_data + in1_line + 4 * (x - in1.area.x0)),
- (in2_zero_x[xr]||in2_zero_y[yr]) ? zero_rgba : (in2_data + in2_line + 4 * (x - in2.area.x0)));
- }
- }
- }
- }
-}
-
-} /* namespace Filters */
-} /* namespace Inkscape */
-
-#endif // __NR_FILTER_PIXOPS_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/nr-filter-primitive.cpp b/src/display/nr-filter-primitive.cpp
index 1af86ec3e..b544d6df0 100644
--- a/src/display/nr-filter-primitive.cpp
+++ b/src/display/nr-filter-primitive.cpp
@@ -13,8 +13,8 @@
*/
#include "display/nr-filter-primitive.h"
+#include "display/nr-filter-slot.h"
#include "display/nr-filter-types.h"
-#include "libnr/nr-pixblock.h"
#include "svg/svg-length.h"
namespace Inkscape {
@@ -48,6 +48,13 @@ FilterPrimitive::~FilterPrimitive()
// Nothing to do here
}
+void FilterPrimitive::render_cairo(FilterSlot &slot)
+{
+ // passthrough
+ cairo_surface_t *in = slot.getcairo(_input);
+ slot.set(_output, in);
+}
+
void FilterPrimitive::area_enlarge(NRRectL &/*area*/, Geom::Affine const &/*m*/)
{
// This doesn't need to do anything by default
diff --git a/src/display/nr-filter-primitive.h b/src/display/nr-filter-primitive.h
index 0e8df3813..dd7363d76 100644
--- a/src/display/nr-filter-primitive.h
+++ b/src/display/nr-filter-primitive.h
@@ -1,6 +1,3 @@
-#ifndef __NR_FILTER_PRIMITIVE_H__
-#define __NR_FILTER_PRIMITIVE_H__
-
/*
* SVG filters rendering
*
@@ -11,15 +8,20 @@
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
+#ifndef SEEN_NR_FILTER_PRIMITIVE_H
+#define SEEN_NR_FILTER_PRIMITIVE_H
-#include "display/nr-filter-slot.h"
-#include "libnr/nr-pixblock.h"
-#include "libnr/nr-rect-l.h"
+#include <2geom/forward.h>
#include "svg/svg-length.h"
+struct NRRectL;
+
namespace Inkscape {
namespace Filters {
+class FilterSlot;
+class FilterUnits;
+
/*
* Different filter effects need different types of inputs. This is what
* traits are used for: one can specify, what special restrictions
@@ -43,7 +45,8 @@ public:
FilterPrimitive();
virtual ~FilterPrimitive();
- virtual int render(FilterSlot &slot, FilterUnits const &units) = 0;
+ virtual void render_cairo(FilterSlot &slot);
+ virtual int render(FilterSlot &slot, FilterUnits const &units) { return 0; }
virtual void area_enlarge(NRRectL &area, Geom::Affine const &m);
/**
@@ -108,6 +111,20 @@ public:
*/
virtual FilterTraits get_input_traits();
+ /** @brief Indicate whether the filter primitive can handle the given affine.
+ *
+ * Results of some filter primitives depend on the coordinate system used when rendering.
+ * A gaussian blur with equal x and y deviation will remain unchanged by rotations.
+ * Per-pixel filters like color matrix and blend will not change regardless of
+ * the transformation.
+ *
+ * When any filter returns false, filter rendering is performed on an intermediate surface
+ * with edges parallel to the axes of the user coordinate system. This means
+ * the matrices from FilterUnits will contain at most a (possibly non-uniform) scale
+ * and a translation. When all primitives of the filter return false, the rendering is
+ * performed in display coordinate space and no intermediate surface is used. */
+ virtual bool can_handle_affine(Geom::Affine const &) { return false; }
+
protected:
int _input;
int _output;
diff --git a/src/display/nr-filter-skeleton.cpp b/src/display/nr-filter-skeleton.cpp
index c17bee1d4..0c455a818 100644
--- a/src/display/nr-filter-skeleton.cpp
+++ b/src/display/nr-filter-skeleton.cpp
@@ -22,9 +22,9 @@
*/
#include "display/nr-filter-skeleton.h"
+#include "display/cairo-utils.h"
#include "display/nr-filter-slot.h"
#include "display/nr-filter-units.h"
-#include "libnr/nr-pixblock.h"
namespace Inkscape {
namespace Filters {
@@ -39,17 +39,17 @@ FilterPrimitive * FilterSkeleton::create() {
FilterSkeleton::~FilterSkeleton()
{}
-int FilterSkeleton::render(FilterSlot &slot,
- FilterUnits const &/*units*/) {
- //NRPixBlock *in = slot.get(_input);
- NRPixBlock *out = new NRPixBlock();
+void FilterSkeleton::render_cairo(FilterSlot &slot) {
+ cairo_surface_t *in = slot.getcairo(_input);
+ cairo_surface_t *out = ink_cairo_surface_create_identical(in);
+ cairo_t *ct = cairo_create(out);
- /* Insert rendering code here */
+// cairo_set_source_surface(ct, in, offset[X], offset[Y]);
+// cairo_paint(ct);
+// cairo_destroy(ct);
- out->empty = FALSE;
slot.set(_output, out);
-
- return 0;
+ cairo_surface_destroy(out);
}
} /* namespace Filters */
diff --git a/src/display/nr-filter-skeleton.h b/src/display/nr-filter-skeleton.h
index a03004be1..049c0df80 100644
--- a/src/display/nr-filter-skeleton.h
+++ b/src/display/nr-filter-skeleton.h
@@ -37,7 +37,7 @@ public:
static FilterPrimitive *create();
virtual ~FilterSkeleton();
- virtual int render(FilterSlot &slot, FilterUnits const &units);
+ virtual void render_cairo(FilterSlot &slot);
private:
diff --git a/src/display/nr-filter-slot.cpp b/src/display/nr-filter-slot.cpp
index b019b194f..ce07ff086 100644
--- a/src/display/nr-filter-slot.cpp
+++ b/src/display/nr-filter-slot.cpp
@@ -14,317 +14,219 @@
#include <assert.h>
#include <string.h>
+#include <2geom/transforms.h>
+#include "display/cairo-utils.h"
#include "display/nr-arena-item.h"
#include "display/nr-filter-types.h"
#include "display/nr-filter-gaussian.h"
#include "display/nr-filter-slot.h"
-#include "display/nr-filter-getalpha.h"
#include "display/nr-filter-units.h"
-#include "display/pixblock-scaler.h"
-#include "display/pixblock-transform.h"
-#include "libnr/nr-pixblock.h"
-#include "libnr/nr-blit.h"
-
-__attribute__ ((const))
-inline static int _max4(const double a, const double b,
- const double c, const double d) {
- double ret = a;
- if (b > ret) ret = b;
- if (c > ret) ret = c;
- if (d > ret) ret = d;
- return (int)round(ret);
-}
-
-__attribute__ ((const))
-inline static int _min4(const double a, const double b,
- const double c, const double d) {
- double ret = a;
- if (b < ret) ret = b;
- if (c < ret) ret = c;
- if (d < ret) ret = d;
- return (int)round(ret);
-}
-
-__attribute__ ((const))
-inline static int _max2(const double a, const double b) {
- if (a > b)
- return (int)round(a);
- else
- return (int)round(b);
-}
-
-__attribute__ ((const))
-inline static int _min2(const double a, const double b) {
- if (a > b)
- return (int)round(b);
- else
- return (int)round(a);
-}
namespace Inkscape {
namespace Filters {
-FilterSlot::FilterSlot(int slots, NRArenaItem const *item)
- : _last_out(-1),
- filterquality(FILTER_QUALITY_BEST),
- blurquality(BLUR_QUALITY_BEST),
- _arena_item(item)
+FilterSlot::FilterSlot(NRArenaItem *item, cairo_t *bgct, NRRectL const *bgarea,
+ cairo_surface_t *graphic, NRRectL const *graphicarea, FilterUnits const &u)
+ : _item(item)
+ , _source_graphic(graphic)
+ , _background_ct(bgct)
+ , _source_graphic_area(graphicarea)
+ , _background_area(bgarea)
+ , _units(u)
+ , _last_out(NR_FILTER_SOURCEGRAPHIC)
+ , filterquality(FILTER_QUALITY_BEST)
+ , blurquality(BLUR_QUALITY_BEST)
{
- _slots.reserve((slots > 0) ? slots : 2);
+ using Geom::X;
+ using Geom::Y;
+
+ // compute slot bbox
+ Geom::Rect bbox(
+ Geom::Point(_source_graphic_area->x0, _source_graphic_area->y0),
+ Geom::Point(_source_graphic_area->x1, _source_graphic_area->y1));
+
+ Geom::Affine trans = _units.get_matrix_display2pb();
+ Geom::Rect bbox_trans = bbox * trans;
+ Geom::Point min = bbox_trans.min();
+ _slot_x = min[X];
+ _slot_y = min[Y];
+
+ if (trans.isTranslation()) {
+ _slot_w = _source_graphic_area->x1 - _source_graphic_area->x0;
+ _slot_h = _source_graphic_area->y1 - _source_graphic_area->y0;
+ } else {
+ _slot_w = ceil(bbox_trans.width());
+ _slot_h = ceil(bbox_trans.height());
+ }
}
FilterSlot::~FilterSlot()
{
- for (unsigned int i = 0 ; i < _slots.size() ; i++) {
- if (_slots[i].owned) {
- nr_pixblock_release(_slots[i].pb);
- delete _slots[i].pb;
- }
+ for (SlotMap::iterator i = _slots.begin(); i != _slots.end(); ++i) {
+ cairo_surface_destroy(i->second);
}
}
-FilterSlot::slot_entry_t::~slot_entry_t()
+cairo_surface_t *FilterSlot::getcairo(int slot_nr)
{
- // It's a bad idea to destruct pixblocks here, as this will also be called upon resizing _slots
-}
+ if (slot_nr == NR_FILTER_SLOT_NOT_SET)
+ slot_nr = _last_out;
-NRPixBlock *FilterSlot::get(int slot_nr)
-{
- int index = _get_index(slot_nr);
- assert(index >= 0);
+ SlotMap::iterator s = _slots.find(slot_nr);
/* If we didn't have the specified image, but we could create it
* from the other information we have, let's do that */
- if (_slots[index].pb == NULL
- && (slot_nr == NR_FILTER_SOURCEALPHA
+ if (s == _slots.end()
+ && (slot_nr == NR_FILTER_SOURCEGRAPHIC
+ || slot_nr == NR_FILTER_SOURCEALPHA
|| slot_nr == NR_FILTER_BACKGROUNDIMAGE
|| slot_nr == NR_FILTER_BACKGROUNDALPHA
|| slot_nr == NR_FILTER_FILLPAINT
|| slot_nr == NR_FILTER_STROKEPAINT))
{
- /* If needed, fetch background */
- if (slot_nr == NR_FILTER_BACKGROUNDIMAGE) {
- NRPixBlock *pb;
- pb = nr_arena_item_get_background(_arena_item);
- if (pb) {
- pb->empty = false;
- this->set(NR_FILTER_BACKGROUNDIMAGE, pb, false);
- } else {
- NRPixBlock *source = this->get(NR_FILTER_SOURCEGRAPHIC);
- pb = new NRPixBlock();
- if (!pb) return NULL; // Allocation failed
- nr_pixblock_setup_fast(pb, source->mode,
- source->area.x0, source->area.y0,
- source->area.x1, source->area.y1, true);
- if (pb->size != NR_PIXBLOCK_SIZE_TINY && pb->data.px == NULL) {
- // allocation failed
- delete pb;
- return NULL;
- }
- pb->empty = FALSE;
- this->set(NR_FILTER_BACKGROUNDIMAGE, pb);
- }
- } else if (slot_nr == NR_FILTER_SOURCEALPHA) {
- /* If only a alpha channel is needed, strip it from full image */
- NRPixBlock *src = get(NR_FILTER_SOURCEGRAPHIC);
- NRPixBlock *sa = filter_get_alpha(src);
- set(NR_FILTER_SOURCEALPHA, sa);
- } else if (slot_nr == NR_FILTER_BACKGROUNDALPHA) {
- NRPixBlock *src = get(NR_FILTER_BACKGROUNDIMAGE);
- NRPixBlock *ba = filter_get_alpha(src);
- set(NR_FILTER_BACKGROUNDALPHA, ba);
- } else if (slot_nr == NR_FILTER_FILLPAINT) {
- /* When a paint is needed, fetch it from arena item */
- // TODO
- } else if (slot_nr == NR_FILTER_STROKEPAINT) {
- // TODO
+ switch (slot_nr) {
+ case NR_FILTER_SOURCEGRAPHIC: {
+ cairo_surface_t *tr = _get_transformed_source_graphic();
+ _set_internal(NR_FILTER_SOURCEGRAPHIC, tr);
+ cairo_surface_destroy(tr);
+ } break;
+ case NR_FILTER_BACKGROUNDIMAGE: {
+ cairo_surface_t *bg = _get_transformed_background();
+ _set_internal(NR_FILTER_BACKGROUNDIMAGE, bg);
+ cairo_surface_destroy(bg);
+ } break;
+ case NR_FILTER_SOURCEALPHA: {
+ cairo_surface_t *src = getcairo(NR_FILTER_SOURCEGRAPHIC);
+ cairo_surface_t *alpha = ink_cairo_extract_alpha(src);
+ _set_internal(NR_FILTER_SOURCEALPHA, alpha);
+ cairo_surface_destroy(alpha);
+ } break;
+ case NR_FILTER_BACKGROUNDALPHA: {
+ cairo_surface_t *src = getcairo(NR_FILTER_BACKGROUNDIMAGE);
+ cairo_surface_t *ba = ink_cairo_extract_alpha(src);
+ _set_internal(NR_FILTER_BACKGROUNDALPHA, ba);
+ cairo_surface_destroy(ba);
+ } break;
+ case NR_FILTER_FILLPAINT: //TODO
+ case NR_FILTER_STROKEPAINT: //TODO
+ default:
+ break;
}
+ s = _slots.find(slot_nr);
}
- if (_slots[index].pb) {
- _slots[index].pb->empty = false;
+ if (s == _slots.end()) {
+ // create empty surface
+ cairo_surface_t *empty = cairo_surface_create_similar(
+ _source_graphic, cairo_surface_get_content(_source_graphic),
+ _slot_w, _slot_h);
+ _set_internal(slot_nr, empty);
+ cairo_surface_destroy(empty);
+ s = _slots.find(slot_nr);
}
-
- assert(slot_nr == NR_FILTER_SLOT_NOT_SET ||_slots[index].number == slot_nr);
- return _slots[index].pb;
+ return s->second;
}
-void FilterSlot::get_final(int slot_nr, NRPixBlock *result) {
- NRPixBlock *final_usr = get(slot_nr);
- Geom::Affine trans = units.get_matrix_pb2display();
-
- int size = (result->area.x1 - result->area.x0)
- * (result->area.y1 - result->area.y0)
- * NR_PIXBLOCK_BPP(result);
- memset(NR_PIXBLOCK_PX(result), 0, size);
+cairo_surface_t *FilterSlot::_get_transformed_source_graphic()
+{
+ Geom::Affine trans = _units.get_matrix_display2pb();
- if (fabs(trans[1]) > 1e-6 || fabs(trans[2]) > 1e-6) {
- if (filterquality == FILTER_QUALITY_BEST) {
- NR::transform_bicubic(result, final_usr, trans);
- } else {
- NR::transform_nearest(result, final_usr, trans);
- }
- } else if (fabs(trans[0] - 1) > 1e-6 || fabs(trans[3] - 1) > 1e-6) {
- NR::scale_bicubic(result, final_usr, trans);
- } else {
- nr_blit_pixblock_pixblock(result, final_usr);
+ if (trans.isTranslation()) {
+ cairo_surface_reference(_source_graphic);
+ return _source_graphic;
}
-}
-void FilterSlot::set(int slot_nr, NRPixBlock *pb, bool takeOwnership)
-{
- /* Unnamed slot is for saving filter primitive results, when parameter
- * 'result' is not set. Only the filter immediately after this one
- * can access unnamed results, so we don't have to worry about overwriting
- * previous results in filter chain. On the other hand, we may not
- * overwrite any other image with this one, because they might be
- * accessed later on. */
- int index = ((slot_nr != NR_FILTER_SLOT_NOT_SET)
- ? _get_index(slot_nr)
- : _get_index(NR_FILTER_UNNAMED_SLOT));
- assert(index >= 0);
- // Unnamed slot is only for Inkscape::Filters::FilterSlot internal use.
- assert(slot_nr != NR_FILTER_UNNAMED_SLOT);
- assert(slot_nr == NR_FILTER_SLOT_NOT_SET ||_slots[index].number == slot_nr);
-
- if (slot_nr == NR_FILTER_SOURCEGRAPHIC || slot_nr == NR_FILTER_BACKGROUNDIMAGE) {
- Geom::Affine trans = units.get_matrix_display2pb();
- if (fabs(trans[1]) > 1e-6 || fabs(trans[2]) > 1e-6) {
- NRPixBlock *trans_pb = new NRPixBlock;
- int x0 = pb->area.x0;
- int y0 = pb->area.y0;
- int x1 = pb->area.x1;
- int y1 = pb->area.y1;
- int min_x = _min4(trans[0] * x0 + trans[2] * y0 + trans[4],
- trans[0] * x0 + trans[2] * y1 + trans[4],
- trans[0] * x1 + trans[2] * y0 + trans[4],
- trans[0] * x1 + trans[2] * y1 + trans[4]);
- int max_x = _max4(trans[0] * x0 + trans[2] * y0 + trans[4],
- trans[0] * x0 + trans[2] * y1 + trans[4],
- trans[0] * x1 + trans[2] * y0 + trans[4],
- trans[0] * x1 + trans[2] * y1 + trans[4]);
- int min_y = _min4(trans[1] * x0 + trans[3] * y0 + trans[5],
- trans[1] * x0 + trans[3] * y1 + trans[5],
- trans[1] * x1 + trans[3] * y0 + trans[5],
- trans[1] * x1 + trans[3] * y1 + trans[5]);
- int max_y = _max4(trans[1] * x0 + trans[3] * y0 + trans[5],
- trans[1] * x0 + trans[3] * y1 + trans[5],
- trans[1] * x1 + trans[3] * y0 + trans[5],
- trans[1] * x1 + trans[3] * y1 + trans[5]);
-
- nr_pixblock_setup_fast(trans_pb, pb->mode,
- min_x, min_y,
- max_x, max_y, true);
- if (trans_pb->size != NR_PIXBLOCK_SIZE_TINY && trans_pb->data.px == NULL) {
- /* TODO: this gets hit occasionally. Worst case scenario:
- * images are exported in horizontal stripes. One stripe
- * is not too high, but can get thousands of pixels wide.
- * Rotate this 45 degrees -> _huge_ image */
- g_warning("Memory allocation failed in Inkscape::Filters::FilterSlot::set (transform)");
- if (takeOwnership) {
- nr_pixblock_release(pb);
- delete pb;
- }
- return;
- }
- if (filterquality == FILTER_QUALITY_BEST) {
- NR::transform_bicubic(trans_pb, pb, trans);
- } else {
- NR::transform_nearest(trans_pb, pb, trans);
- }
- if (takeOwnership) {
- nr_pixblock_release(pb);
- delete pb;
- }
- takeOwnership = true;
- pb = trans_pb;
- } else if (fabs(trans[0] - 1) > 1e-6 || fabs(trans[3] - 1) > 1e-6) {
- NRPixBlock *trans_pb = new NRPixBlock;
-
- int x0 = pb->area.x0;
- int y0 = pb->area.y0;
- int x1 = pb->area.x1;
- int y1 = pb->area.y1;
- int min_x = _min2(trans[0] * x0 + trans[4],
- trans[0] * x1 + trans[4]);
- int max_x = _max2(trans[0] * x0 + trans[4],
- trans[0] * x1 + trans[4]);
- int min_y = _min2(trans[3] * y0 + trans[5],
- trans[3] * y1 + trans[5]);
- int max_y = _max2(trans[3] * y0 + trans[5],
- trans[3] * y1 + trans[5]);
-
- nr_pixblock_setup_fast(trans_pb, pb->mode,
- min_x, min_y, max_x, max_y, true);
- if (trans_pb->size != NR_PIXBLOCK_SIZE_TINY && trans_pb->data.px == NULL) {
- g_warning("Memory allocation failed in Inkscape::Filters::FilterSlot::set (scaling)");
- if (takeOwnership) {
- nr_pixblock_release(pb);
- delete pb;
- }
- return;
- }
- NR::scale_bicubic(trans_pb, pb, trans);
- if (takeOwnership) {
- nr_pixblock_release(pb);
- delete pb;
- }
- takeOwnership = true;
- pb = trans_pb;
- }
- }
+ cairo_surface_t *tsg = cairo_surface_create_similar(
+ _source_graphic, cairo_surface_get_content(_source_graphic),
+ _slot_w, _slot_h);
+ cairo_t *tsg_ct = cairo_create(tsg);
- if(_slots[index].owned) {
- nr_pixblock_release(_slots[index].pb);
- delete _slots[index].pb;
- }
- _slots[index].pb = pb;
- _slots[index].owned = takeOwnership;
- _last_out = index;
+ cairo_translate(tsg_ct, -_slot_x, -_slot_y);
+ ink_cairo_transform(tsg_ct, trans);
+ cairo_translate(tsg_ct, _source_graphic_area->x0, _source_graphic_area->y0);
+ cairo_set_source_surface(tsg_ct, _source_graphic, 0, 0);
+ cairo_set_operator(tsg_ct, CAIRO_OPERATOR_SOURCE);
+ cairo_paint(tsg_ct);
+ cairo_destroy(tsg_ct);
+
+ return tsg;
}
-int FilterSlot::get_slot_count()
+cairo_surface_t *FilterSlot::_get_transformed_background()
{
- return _slots.size();
+ Geom::Affine trans = _units.get_matrix_display2pb();
+
+ cairo_surface_t *bg = cairo_get_target(_background_ct);
+ cairo_surface_t *tbg = cairo_surface_create_similar(
+ bg, cairo_surface_get_content(bg),
+ _slot_w, _slot_h);
+ cairo_t *tbg_ct = cairo_create(tbg);
+
+ cairo_translate(tbg_ct, -_slot_x, -_slot_y);
+ ink_cairo_transform(tbg_ct, trans);
+ cairo_translate(tbg_ct, _background_area->x0, _background_area->y0);
+ cairo_set_source_surface(tbg_ct, bg, 0, 0);
+ cairo_set_operator(tbg_ct, CAIRO_OPERATOR_SOURCE);
+ cairo_paint(tbg_ct);
+ cairo_destroy(tbg_ct);
+
+ return tbg;
}
-NRArenaItem const* FilterSlot::get_arenaitem()
+cairo_surface_t *FilterSlot::get_result(int res)
{
- return _arena_item;
+ Geom::Affine trans = _units.get_matrix_pb2display();
+ if (trans.isIdentity()) {
+ cairo_surface_t *result = getcairo(res);
+ cairo_surface_reference(result);
+ return result;
+ }
+
+ cairo_surface_t *r = cairo_surface_create_similar(_source_graphic,
+ cairo_surface_get_content(_source_graphic),
+ _source_graphic_area->x1 - _source_graphic_area->x0,
+ _source_graphic_area->y1 - _source_graphic_area->y0);
+ cairo_t *r_ct = cairo_create(r);
+
+ cairo_translate(r_ct, -_source_graphic_area->x0, -_source_graphic_area->y0);
+ ink_cairo_transform(r_ct, trans);
+ cairo_translate(r_ct, _slot_x, _slot_y);
+ cairo_set_source_surface(r_ct, getcairo(res), 0, 0);
+ cairo_set_operator(r_ct, CAIRO_OPERATOR_SOURCE);
+ cairo_paint(r_ct);
+ cairo_destroy(r_ct);
+
+ return r;
}
-int FilterSlot::_get_index(int slot_nr)
+void FilterSlot::_set_internal(int slot_nr, cairo_surface_t *surface)
{
- assert(slot_nr >= 0 ||
- slot_nr == NR_FILTER_SLOT_NOT_SET ||
- slot_nr == NR_FILTER_SOURCEGRAPHIC ||
- slot_nr == NR_FILTER_SOURCEALPHA ||
- slot_nr == NR_FILTER_BACKGROUNDIMAGE ||
- slot_nr == NR_FILTER_BACKGROUNDALPHA ||
- slot_nr == NR_FILTER_FILLPAINT ||
- slot_nr == NR_FILTER_STROKEPAINT ||
- slot_nr == NR_FILTER_UNNAMED_SLOT);
-
- if (slot_nr == NR_FILTER_SLOT_NOT_SET) {
- return _last_out;
- }
+ // destroy after referencing
+ // this way assigning a surface to a slot it already occupies will not cause errors
+ cairo_surface_reference(surface);
- /* Search, if the slot already exists */
- for (int i = 0 ; i < (int)_slots.size() ; i++) {
- if (_slots[i].number == slot_nr) {
- return i;
- }
+ SlotMap::iterator s = _slots.find(slot_nr);
+ if (s != _slots.end()) {
+ cairo_surface_destroy(s->second);
}
- /* If the slot doesn't already exist, create it */
- slot_entry_t entry;
- entry.number = slot_nr;
- _slots.push_back(entry);
- return (int)_slots.size()-1;
+ _slots[slot_nr] = surface;
}
-void FilterSlot::set_units(FilterUnits const &units) {
- this->units = units;
+void FilterSlot::set(int slot_nr, cairo_surface_t *surface)
+{
+ g_return_if_fail(surface != NULL);
+
+ if (slot_nr == NR_FILTER_SLOT_NOT_SET)
+ slot_nr = NR_FILTER_UNNAMED_SLOT;
+
+ _set_internal(slot_nr, surface);
+ _last_out = slot_nr;
+}
+
+int FilterSlot::get_slot_count()
+{
+ return _slots.size();
}
void FilterSlot::set_quality(FilterQuality const q) {
@@ -339,6 +241,13 @@ int FilterSlot::get_blurquality(void) {
return blurquality;
}
+Geom::Rect FilterSlot::get_slot_area() const {
+ Geom::Point p(_slot_x, _slot_y);
+ Geom::Point dim(_slot_w, _slot_h);
+ Geom::Rect r(p, p+dim);
+ return r;
+}
+
} /* namespace Filters */
} /* namespace Inkscape */
diff --git a/src/display/nr-filter-slot.h b/src/display/nr-filter-slot.h
index 871d80a8e..3b08743ed 100644
--- a/src/display/nr-filter-slot.h
+++ b/src/display/nr-filter-slot.h
@@ -14,10 +14,10 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include "libnr/nr-pixblock.h"
+#include <map>
+#include <cairo.h>
#include "display/nr-filter-types.h"
#include "display/nr-filter-units.h"
-#include <vector>
struct NRArenaItem;
@@ -26,14 +26,9 @@ namespace Filters {
class FilterSlot {
public:
- /** Creates a new FilterSlot object.
- * First parameter specifies the amount of slots this SilterSlot
- * should reserve beforehand. If a negative number is given,
- * two slots will be reserved.
- * Second parameter specifies the arena item, which should be used
- * for background accesses from filters.
- */
- FilterSlot(int slots, NRArenaItem const *item);
+ /** Creates a new FilterSlot object. */
+ FilterSlot(NRArenaItem *item, cairo_t *bgct, NRRectL const *bgarea,
+ cairo_surface_t *graphic, NRRectL const *graphicarea, FilterUnits const &u);
/** Destroys the FilterSlot object and all its contents */
virtual ~FilterSlot();
@@ -43,37 +38,22 @@ public:
* NR_FILTER_SOURCEGRAPHIC, NR_FILTER_SOURCEALPHA,
* NR_FILTER_BACKGROUNDIMAGE, NR_FILTER_BACKGROUNDALPHA,
* NR_FILTER_FILLPAINT, NR_FILTER_SOURCEPAINT.
- * If the defined filter slot is not set before, this function
- * returns NULL. Also, that filter slot is created in process.
- */
- NRPixBlock *get(int slot);
-
- /** Gets the final result from this filter.
- * The result is fetched from the specified slot, see description of
- * method get for valid values. The pixblock 'result' will be modified
- * to contain the result image, ready to be used in the rest of rendering
- * pipeline
*/
- void get_final(int slot, NRPixBlock *result);
+ cairo_surface_t *getcairo(int slot);
/** Sets or re-sets the pixblock associated with given slot.
* If there was a pixblock already assigned with this slot,
* that pixblock is destroyed.
- * Pixblocks passed to this function should be considered
- * managed by this FilterSlot object if takeOwnership==true.
- * Pixblocks passed to this function should be reserved with
- * c++ -style new-operator (if managed by FilterSlot).
*/
- void set(int slot, NRPixBlock *pb, bool takeOwnership=true);
+ void set(int slot, cairo_surface_t *s);
+
+ cairo_surface_t *get_result(int slot_nr);
/** Returns the number of slots in use. */
int get_slot_count();
- /** arenaitem getter method*/
- NRArenaItem const* get_arenaitem();
-
/** Sets the unit system to be used for the internal images. */
- void set_units(FilterUnits const &units);
+ //void set_units(FilterUnits const &units);
/** Sets the filtering quality. Affects used interpolation methods */
void set_quality(FilterQuality const q);
@@ -84,30 +64,36 @@ public:
/** Gets the gaussian filtering quality. Affects used interpolation methods */
int get_blurquality(void);
-private:
- struct slot_entry_t {
- NRPixBlock* pb;
- int number;
- bool owned;
- slot_entry_t() : pb(0), number(NR_FILTER_SLOT_NOT_SET), owned(false) {}
- ~slot_entry_t();
- };
- std::vector<slot_entry_t> _slots;
+ FilterUnits const &get_units() const { return _units; }
+ Geom::Rect get_slot_area() const;
+ NRRectL const &get_sg_area() const { return *_source_graphic_area; }
+private:
+ typedef std::map<int, cairo_surface_t *> SlotMap;
+ SlotMap _slots;
+ NRArenaItem *_item;
+
+ //Geom::Rect _source_bbox; ///< bounding box of source graphic surface
+ //Geom::Rect _intermediate_bbox; ///< bounding box of intermediate surfaces
+
+// NRRectL _slot_area;
+ int _slot_w, _slot_h;
+ double _slot_x, _slot_y;
+ cairo_surface_t *_source_graphic;
+ cairo_t *_background_ct;
+ NRRectL const *_source_graphic_area;
+ NRRectL const *_background_area; ///< needed to extract background
+ FilterUnits const &_units;
int _last_out;
-
FilterQuality filterquality;
-
int blurquality;
- NRArenaItem const *_arena_item;
-
- FilterUnits units;
+ cairo_surface_t *_get_transformed_source_graphic();
+ cairo_surface_t *_get_transformed_background();
+ cairo_surface_t *_get_fill_paint();
+ cairo_surface_t *_get_stroke_paint();
- /** Returns the table index of given slot. If that slot does not exist,
- * it is created. Table index can be used to read the correct
- * pixblock from _slot */
- int _get_index(int slot);
+ void _set_internal(int slot, cairo_surface_t *s);
};
} /* namespace Filters */
diff --git a/src/display/nr-filter-specularlighting.cpp b/src/display/nr-filter-specularlighting.cpp
index 8ecee24e6..eddab36a1 100644
--- a/src/display/nr-filter-specularlighting.cpp
+++ b/src/display/nr-filter-specularlighting.cpp
@@ -13,18 +13,15 @@
#include <glib/gmessages.h>
#include <cmath>
+#include "display/cairo-templates.h"
+#include "display/cairo-utils.h"
#include "display/nr-3dutils.h"
-#include "display/nr-arena-item.h"
#include "display/nr-filter-specularlighting.h"
-#include "display/nr-filter-getalpha.h"
#include "display/nr-filter-slot.h"
#include "display/nr-filter-units.h"
#include "display/nr-filter-utils.h"
#include "display/nr-light.h"
-#include "libnr/nr-blit.h"
-#include "libnr/nr-pixblock.h"
#include "libnr/nr-rect-l.h"
-#include "color.h"
namespace Inkscape {
namespace Filters {
@@ -45,20 +42,139 @@ FilterPrimitive * FilterSpecularLighting::create() {
FilterSpecularLighting::~FilterSpecularLighting()
{}
-//Investigating Phong Lighting model we should not take N.H but
-//R.E which equals to 2*N.H^2 - 1
-//replace the second line by
-//gdouble scal = scalar_product((N), (H)); scal = 2 * scal * scal - 1;
-//to get the expected formula
-#define COMPUTE_INTER(inter, H, N, ks, speculaExponent) \
-do {\
- gdouble scal = NR::scalar_product((N), (H)); \
- if (scal <= 0)\
- (inter) = 0;\
- else\
- (inter) = (ks) * std::pow(scal, (specularExponent));\
-}while(0)
+struct SpecularLight : public SurfaceSynth {
+ SpecularLight(cairo_surface_t *bumpmap, double scale, double specular_constant,
+ double specular_exponent)
+ : SurfaceSynth(bumpmap)
+ , _scale(scale)
+ , _ks(specular_constant)
+ , _exp(specular_exponent)
+ {}
+protected:
+ guint32 specularLighting(int x, int y, NR::Fvector const &halfway, NR::Fvector const &light_components) {
+ NR::Fvector normal = surfaceNormalAt(x, y, _scale);
+ double sp = NR::scalar_product(normal, halfway);
+ double k = sp <= 0.0 ? 0.0 : _ks * pow(sp, _exp);
+ guint32 r = CLAMP_D_TO_U8(k * light_components[LIGHT_RED]);
+ guint32 g = CLAMP_D_TO_U8(k * light_components[LIGHT_GREEN]);
+ guint32 b = CLAMP_D_TO_U8(k * light_components[LIGHT_BLUE]);
+ guint32 a = std::max(std::max(r, g), b);
+
+ r = premul_alpha(r, a);
+ g = premul_alpha(g, a);
+ b = premul_alpha(b, a);
+
+ ASSEMBLE_ARGB32(pxout, a,r,g,b)
+ return pxout;
+ }
+ double _scale, _ks, _exp;
+};
+
+struct SpecularDistantLight : public SpecularLight {
+ SpecularDistantLight(cairo_surface_t *bumpmap, SPFeDistantLight *light, guint32 color,
+ double scale, double specular_constant, double specular_exponent)
+ : SpecularLight(bumpmap, scale, specular_constant, specular_exponent)
+ {
+ DistantLight dl(light, color);
+ NR::Fvector lv;
+ dl.light_vector(lv);
+ dl.light_components(_light_components);
+ NR::normalized_sum(_halfway, lv, NR::EYE_VECTOR);
+ }
+ guint32 operator()(int x, int y) {
+ return specularLighting(x, y, _halfway, _light_components);
+ }
+private:
+ NR::Fvector _halfway, _light_components;
+};
+
+struct SpecularPointLight : public SpecularLight {
+ SpecularPointLight(cairo_surface_t *bumpmap, SPFePointLight *light, guint32 color,
+ Geom::Affine const &trans, double scale, double specular_constant,
+ double specular_exponent, double x0, double y0)
+ : SpecularLight(bumpmap, scale, specular_constant, specular_exponent)
+ , _light(light, color, trans)
+ , _x0(x0)
+ , _y0(y0)
+ {
+ _light.light_components(_light_components);
+ }
+
+ guint32 operator()(int x, int y) {
+ NR::Fvector light, halfway;
+ _light.light_vector(light, _x0 + x, _y0 + y, _scale * alphaAt(x, y)/255.0);
+ NR::normalized_sum(halfway, light, NR::EYE_VECTOR);
+ return specularLighting(x, y, halfway, _light_components);
+ }
+private:
+ PointLight _light;
+ NR::Fvector _light_components;
+ double _x0, _y0;
+};
+
+struct SpecularSpotLight : public SpecularLight {
+ SpecularSpotLight(cairo_surface_t *bumpmap, SPFeSpotLight *light, guint32 color,
+ Geom::Affine const &trans, double scale, double specular_constant,
+ double specular_exponent, double x0, double y0)
+ : SpecularLight(bumpmap, scale, specular_constant, specular_exponent)
+ , _light(light, color, trans)
+ , _x0(x0)
+ , _y0(y0)
+ {}
+
+ guint32 operator()(int x, int y) {
+ NR::Fvector light, halfway, light_components;
+ _light.light_vector(light, _x0 + x, _y0 + y, _scale * alphaAt(x, y)/255.0);
+ _light.light_components(light_components, light);
+ NR::normalized_sum(halfway, light, NR::EYE_VECTOR);
+ return specularLighting(x, y, halfway, light_components);
+ }
+private:
+ SpotLight _light;
+ double _x0, _y0;
+};
+
+void FilterSpecularLighting::render_cairo(FilterSlot &slot)
+{
+ cairo_surface_t *input = slot.getcairo(_input);
+ cairo_surface_t *out = ink_cairo_surface_create_same_size(input, CAIRO_CONTENT_COLOR_ALPHA);
+
+ Geom::Affine trans = slot.get_units().get_matrix_primitiveunits2pb();
+ Geom::Point p = slot.get_slot_area().min();
+ double x0 = p[Geom::X];
+ double y0 = p[Geom::Y];
+ double scale = surfaceScale * trans.descrim();
+ double ks = specularConstant;
+ double se = specularExponent;
+
+ switch (light_type) {
+ case DISTANT_LIGHT:
+ ink_cairo_surface_synthesize(out,
+ SpecularDistantLight(input, light.distant, lighting_color, scale, ks, se));
+ break;
+ case POINT_LIGHT:
+ ink_cairo_surface_synthesize(out,
+ SpecularPointLight(input, light.point, lighting_color, trans, scale, ks, se, x0, y0));
+ break;
+ case SPOT_LIGHT:
+ ink_cairo_surface_synthesize(out,
+ SpecularSpotLight(input, light.spot, lighting_color, trans, scale, ks, se, x0, y0));
+ break;
+ default: {
+ cairo_t *ct = cairo_create(out);
+ cairo_set_source_rgba(ct, 0,0,0,1);
+ cairo_set_operator(ct, CAIRO_OPERATOR_SOURCE);
+ cairo_paint(ct);
+ cairo_destroy(ct);
+ } break;
+ }
+
+ slot.set(_output, out);
+ cairo_surface_destroy(out);
+}
+
+/*
int FilterSpecularLighting::render(FilterSlot &slot, FilterUnits const &units) {
NRPixBlock *in = slot.get(_input);
if (!in) {
@@ -186,23 +302,16 @@ int FilterSpecularLighting::render(FilterSlot &slot, FilterUnits const &units) {
//nr_pixblock_release(in);
//delete in;
return 0;
-}
+}*/
void FilterSpecularLighting::area_enlarge(NRRectL &area, Geom::Affine const &trans)
{
// TODO: support kernelUnitLength
- double scalex = std::fabs(trans[0]) + std::fabs(trans[1]);
- double scaley = std::fabs(trans[2]) + std::fabs(trans[3]);
-
- //FIXME: no +2 should be there!... (noticable only for big scales at big zoom factor)
- area.x0 -= (int)(scalex) + 2;
- area.x1 += (int)(scalex) + 2;
- area.y0 -= (int)(scaley) + 2;
- area.y1 += (int)(scaley) + 2;
-}
-FilterTraits FilterSpecularLighting::get_input_traits() {
- return TRAIT_PARALLER;
+ area.x0 -= 1;
+ area.x1 += 1;
+ area.y0 -= 1;
+ area.y1 += 1;
}
} /* namespace Filters */
diff --git a/src/display/nr-filter-specularlighting.h b/src/display/nr-filter-specularlighting.h
index 7c278df89..2fcb02588 100644
--- a/src/display/nr-filter-specularlighting.h
+++ b/src/display/nr-filter-specularlighting.h
@@ -16,18 +16,24 @@
#include <gdk/gdk.h>
#include "display/nr-light-types.h"
#include "display/nr-filter-primitive.h"
-#include "display/nr-filter-slot.h"
-#include "display/nr-filter-units.h"
-#include "filters/distantlight.h"
-#include "filters/pointlight.h"
-#include "filters/spotlight.h"
-#include "color.h"
+
+class SPFeDistantLight;
+class SPFePointLight;
+class SPFeSpotLight;
namespace Inkscape {
namespace Filters {
-
+
+class FilterSlot;
+
class FilterSpecularLighting : public FilterPrimitive {
public:
+ FilterSpecularLighting();
+ static FilterPrimitive *create();
+ virtual ~FilterSpecularLighting();
+ virtual void render_cairo(FilterSlot &slot);
+ virtual void area_enlarge(NRRectL &area, Geom::Affine const &trans);
+
union {
SPFeDistantLight *distant;
SPFePointLight *point;
@@ -38,13 +44,6 @@ public:
gdouble specularConstant;
gdouble specularExponent;
guint32 lighting_color;
-
- FilterSpecularLighting();
- static FilterPrimitive *create();
- virtual ~FilterSpecularLighting();
- virtual int render(FilterSlot &slot, FilterUnits const &units);
- virtual void area_enlarge(NRRectL &area, Geom::Affine const &trans);
- virtual FilterTraits get_input_traits();
private:
};
diff --git a/src/display/nr-filter-tile.cpp b/src/display/nr-filter-tile.cpp
index b1ca5d191..b88386638 100644
--- a/src/display/nr-filter-tile.cpp
+++ b/src/display/nr-filter-tile.cpp
@@ -10,6 +10,7 @@
*/
#include "display/nr-filter-tile.h"
+#include "display/nr-filter-slot.h"
#include "display/nr-filter-units.h"
namespace Inkscape {
@@ -17,7 +18,6 @@ namespace Filters {
FilterTile::FilterTile()
{
- g_warning("FilterTile::render not implemented.");
}
FilterPrimitive * FilterTile::create() {
@@ -27,40 +27,24 @@ FilterPrimitive * FilterTile::create() {
FilterTile::~FilterTile()
{}
-int FilterTile::render(FilterSlot &slot, FilterUnits const &/*units*/) {
- NRPixBlock *in = slot.get(_input);
- if (!in) {
- g_warning("Missing source image for feTile (in=%d)", _input);
- return 1;
- }
-
- NRPixBlock *out = new NRPixBlock;
-
- nr_pixblock_setup_fast(out, in->mode,
- in->area.x0, in->area.y0, in->area.x1, in->area.y1,
- true);
-
- unsigned char *in_data = NR_PIXBLOCK_PX(in);
- unsigned char *out_data = NR_PIXBLOCK_PX(out);
+void FilterTile::render_cairo(FilterSlot &slot)
+{
+ static bool tile_warning = false;
//IMPLEMENT ME!
- g_warning("Renderer for feTile is not implemented.");
- (void)in_data;
- (void)out_data;
+ if (!tile_warning) {
+ g_warning("Renderer for feTile is not implemented.");
+ tile_warning = true;
+ }
- out->empty = FALSE;
- slot.set(_output, out);
- return 0;
+ cairo_surface_t *in = slot.getcairo(_input);
+ slot.set(_output, in);
}
void FilterTile::area_enlarge(NRRectL &/*area*/, Geom::Affine const &/*trans*/)
{
}
-FilterTraits FilterTile::get_input_traits() {
- return TRAIT_PARALLER;
-}
-
} /* namespace Filters */
} /* namespace Inkscape */
diff --git a/src/display/nr-filter-tile.h b/src/display/nr-filter-tile.h
index 4a2a0dddc..5c0a3e553 100644
--- a/src/display/nr-filter-tile.h
+++ b/src/display/nr-filter-tile.h
@@ -13,22 +13,20 @@
*/
#include "display/nr-filter-primitive.h"
-#include "display/nr-filter-slot.h"
-#include "display/nr-filter-units.h"
-#include "libnr/nr-rect-l.h"
namespace Inkscape {
namespace Filters {
+class FilterSlot;
+
class FilterTile : public FilterPrimitive {
public:
FilterTile();
static FilterPrimitive *create();
virtual ~FilterTile();
- virtual int render(FilterSlot &slot, FilterUnits const &units);
+ virtual void render_cairo(FilterSlot &slot);
virtual void area_enlarge(NRRectL &area, Geom::Affine const &trans);
- virtual FilterTraits get_input_traits();
};
} /* namespace Filters */
diff --git a/src/display/nr-filter-turbulence.cpp b/src/display/nr-filter-turbulence.cpp
index a91de0460..6aa435715 100644
--- a/src/display/nr-filter-turbulence.cpp
+++ b/src/display/nr-filter-turbulence.cpp
@@ -17,30 +17,293 @@
* Released under GNU GPL version 2 (or later), read the file 'COPYING' for more information
*/
-#include "display/nr-arena-item.h"
+#include "display/cairo-templates.h"
+#include "display/cairo-utils.h"
#include "display/nr-filter.h"
#include "display/nr-filter-turbulence.h"
#include "display/nr-filter-units.h"
#include "display/nr-filter-utils.h"
#include "libnr/nr-rect-l.h"
-#include "libnr/nr-blit.h"
#include <math.h>
namespace Inkscape {
namespace Filters{
+class TurbulenceGenerator {
+public:
+ TurbulenceGenerator()
+ : _wrapx(0)
+ , _wrapy(0)
+ , _wrapw(0)
+ , _wraph(0)
+ , _inited(false)
+ {}
+
+ void init(long seed, Geom::Rect const &tile, Geom::Point const &freq, bool stitch,
+ bool fractalnoise, int octaves)
+ {
+ // setup random number generator
+ _setupSeed(seed);
+
+ // set values
+ _tile = tile;
+ _baseFreq = freq;
+ _stitchTiles = stitch;
+ _fractalnoise = fractalnoise;
+ _octaves = octaves;
+
+ int i;
+ for (int k = 0; k < 4; ++k) {
+ for (i = 0; i < BSize; ++i) {
+ _latticeSelector[i] = i;
+
+ _gradient[i][k][0] = static_cast<double>(_random() % (BSize*2) - BSize) / BSize;
+ _gradient[i][k][1] = static_cast<double>(_random() % (BSize*2) - BSize) / BSize;
+
+ // normalize gradient
+ double s = hypot(_gradient[i][k][0], _gradient[i][k][1]);
+ _gradient[i][k][0] /= s;
+ _gradient[i][k][1] /= s;
+ }
+ }
+ while (--i) {
+ // shuffle lattice selectors
+ int j = _random() % BSize;
+ std::swap(_latticeSelector[i], _latticeSelector[j]);
+ }
+
+ // fill out the remaining part of the gradient
+ for (i = 0; i < BSize + 2; ++i)
+ {
+ _latticeSelector[BSize + i] = _latticeSelector[i];
+
+ for(int k = 0; k < 4; ++k) {
+ _gradient[BSize + i][k][0] = _gradient[i][k][0];
+ _gradient[BSize + i][k][1] = _gradient[i][k][1];
+ }
+ }
+
+ // When stitching tiled turbulence, the frequencies must be adjusted
+ // so that the tile borders will be continuous.
+ if (_stitchTiles) {
+ if (_baseFreq[Geom::X] != 0.0)
+ {
+ double freq = _baseFreq[Geom::X];
+ double lo = floor(_tile.width() * freq) / _tile.width();
+ double hi = ceil(_tile.width() * freq) / _tile.width();
+ _baseFreq[Geom::X] = freq / lo < hi / freq ? lo : hi;
+ }
+ if (_baseFreq[Geom::Y] != 0.0)
+ {
+ double freq = _baseFreq[Geom::Y];
+ double lo = floor(_tile.height() * freq) / _tile.height();
+ double hi = ceil(_tile.height() * freq) / _tile.height();
+ _baseFreq[Geom::Y] = freq / lo < hi / freq ? lo : hi;
+ }
+
+ _wrapw = _tile.width() * _baseFreq[Geom::X] + 0.5;
+ _wraph = _tile.height() * _baseFreq[Geom::Y] + 0.5;
+ _wrapx = _tile.left() * _baseFreq[Geom::X] + PerlinOffset + _wrapw;
+ _wrapy = _tile.top() * _baseFreq[Geom::Y] + PerlinOffset + _wraph;
+ }
+ _inited = true;
+ }
+
+ G_GNUC_PURE
+ guint32 turbulencePixel(Geom::Point const &p) const {
+ int wrapx = _wrapx, wrapy = _wrapy, wrapw = _wrapw, wraph = _wraph;
+
+ double pixel[4];
+ double x = p[Geom::X] * _baseFreq[Geom::X];
+ double y = p[Geom::Y] * _baseFreq[Geom::Y];
+ double ratio = 1.0;
+
+ for (int k = 0; k < 4; ++k)
+ pixel[k] = 0.0;
+
+ for(int octave = 0; octave < _octaves; ++octave)
+ {
+ double tx = x + PerlinOffset;
+ double bx = floor(tx);
+ double rx0 = tx - bx, rx1 = rx0 - 1.0;
+ int bx0 = bx, bx1 = bx0 + 1;
+
+ double ty = y + PerlinOffset;
+ double by = floor(ty);
+ double ry0 = ty - by, ry1 = ry0 - 1.0;
+ int by0 = by, by1 = by0 + 1;
+
+ if (_stitchTiles) {
+ if (bx0 >= wrapx) bx0 -= wrapw;
+ if (bx1 >= wrapx) bx1 -= wrapw;
+ if (by0 >= wrapy) by0 -= wraph;
+ if (by1 >= wrapy) by1 -= wraph;
+ }
+ bx0 &= BMask;
+ bx1 &= BMask;
+ by0 &= BMask;
+ by1 &= BMask;
+
+ int i = _latticeSelector[bx0];
+ int j = _latticeSelector[bx1];
+ int b00 = _latticeSelector[i + by0];
+ int b01 = _latticeSelector[i + by1];
+ int b10 = _latticeSelector[j + by0];
+ int b11 = _latticeSelector[j + by1];
+
+ double sx = _scurve(rx0);
+ double sy = _scurve(ry0);
+
+ double result[4];
+ // channel numbering: R=0, G=1, B=2, A=3
+ for (int k = 0; k < 4; ++k) {
+ double const *qxa = _gradient[b00][k];
+ double const *qxb = _gradient[b10][k];
+ double a = _lerp(sx, rx0 * qxa[0] + ry0 * qxa[1],
+ rx1 * qxb[0] + ry0 * qxb[1]);
+ double const *qya = _gradient[b01][k];
+ double const *qyb = _gradient[b11][k];
+ double b = _lerp(sx, rx0 * qya[0] + ry1 * qya[1],
+ rx1 * qyb[0] + ry1 * qyb[1]);
+ result[k] = _lerp(sy, a, b);
+ }
+
+ if (_fractalnoise) {
+ for (int k = 0; k < 4; ++k)
+ pixel[k] += result[k] / ratio;
+ } else {
+ for (int k = 0; k < 4; ++k)
+ pixel[k] += fabs(result[k]) / ratio;
+ }
+
+ x *= 2;
+ y *= 2;
+ ratio *= 2;
+
+ if(_stitchTiles)
+ {
+ // Update stitch values. Subtracting PerlinOffset before the multiplication and
+ // adding it afterward simplifies to subtracting it once.
+ wrapw *= 2;
+ wraph *= 2;
+ wrapx = wrapx*2 - PerlinOffset;
+ wrapy = wrapy*2 - PerlinOffset;
+ }
+ }
+
+ if (_fractalnoise) {
+ guint32 r = CLAMP_D_TO_U8((pixel[0]*255.0 + 255.0) / 2);
+ guint32 g = CLAMP_D_TO_U8((pixel[1]*255.0 + 255.0) / 2);
+ guint32 b = CLAMP_D_TO_U8((pixel[2]*255.0 + 255.0) / 2);
+ guint32 a = CLAMP_D_TO_U8((pixel[3]*255.0 + 255.0) / 2);
+ r = premul_alpha(r, a);
+ g = premul_alpha(g, a);
+ b = premul_alpha(b, a);
+ ASSEMBLE_ARGB32(pxout, a,r,g,b);
+ return pxout;
+ } else {
+ guint32 r = CLAMP_D_TO_U8(pixel[0]*255.0);
+ guint32 g = CLAMP_D_TO_U8(pixel[1]*255.0);
+ guint32 b = CLAMP_D_TO_U8(pixel[2]*255.0);
+ guint32 a = CLAMP_D_TO_U8(pixel[3]*255.0);
+ r = premul_alpha(r, a);
+ g = premul_alpha(g, a);
+ b = premul_alpha(b, a);
+ ASSEMBLE_ARGB32(pxout, a,r,g,b);
+ return pxout;
+ }
+ }
+
+ //G_GNUC_PURE
+ /*guint32 turbulencePixel(Geom::Point const &p) const {
+ if (!_fractalnoise) {
+ guint32 r = CLAMP_D_TO_U8(turbulence(0, p)*255.0);
+ guint32 g = CLAMP_D_TO_U8(turbulence(1, p)*255.0);
+ guint32 b = CLAMP_D_TO_U8(turbulence(2, p)*255.0);
+ guint32 a = CLAMP_D_TO_U8(turbulence(3, p)*255.0);
+ r = premul_alpha(r, a);
+ g = premul_alpha(g, a);
+ b = premul_alpha(b, a);
+ ASSEMBLE_ARGB32(pxout, a,r,g,b);
+ return pxout;
+ } else {
+ guint32 r = CLAMP_D_TO_U8((turbulence(0, p)*255.0 + 255.0) / 2);
+ guint32 g = CLAMP_D_TO_U8((turbulence(1, p)*255.0 + 255.0) / 2);
+ guint32 b = CLAMP_D_TO_U8((turbulence(2, p)*255.0 + 255.0) / 2);
+ guint32 a = CLAMP_D_TO_U8((turbulence(3, p)*255.0 + 255.0) / 2);
+ r = premul_alpha(r, a);
+ g = premul_alpha(g, a);
+ b = premul_alpha(b, a);
+ ASSEMBLE_ARGB32(pxout, a,r,g,b);
+ return pxout;
+ }
+ }*/
+
+ bool ready() const { return _inited; }
+ void dirty() { _inited = false; }
+
+private:
+ void _setupSeed(long seed) {
+ _seed = seed;
+ if (_seed <= 0) _seed = -(_seed % (RAND_m - 1)) + 1;
+ if (_seed > RAND_m - 1) _seed = RAND_m - 1;
+ }
+ long _random() {
+ /* Produces results in the range [1, 2**31 - 2].
+ * Algorithm is: r = (a * r) mod m
+ * where a = 16807 and m = 2**31 - 1 = 2147483647
+ * See [Park & Miller], CACM vol. 31 no. 10 p. 1195, Oct. 1988
+ * To test: the algorithm should produce the result 1043618065
+ * as the 10,000th generated number if the original seed is 1. */
+ _seed = RAND_a * (_seed % RAND_q) - RAND_r * (_seed / RAND_q);
+ if (_seed <= 0) _seed += RAND_m;
+ return _seed;
+ }
+ static inline double _scurve(double t) {
+ return t * t * (3.0 - 2.0*t);
+ }
+ static inline double _lerp(double t, double a, double b) {
+ return a + t * (b-a);
+ }
+
+ // random number generator constants
+ static long const
+ RAND_m = 2147483647, // 2**31 - 1
+ RAND_a = 16807, // 7**5; primitive root of m
+ RAND_q = 127773, // m / a
+ RAND_r = 2836; // m % a
+
+ // other constants
+ static int const
+ BSize = 0x100,
+ BMask = 0xff;
+ static double const
+ PerlinOffset = 4096.0;
+
+ Geom::Rect _tile;
+ Geom::Point _baseFreq;
+ int _latticeSelector[2*BSize + 2];
+ double _gradient[2*BSize + 2][4][2];
+ long _seed;
+ int _octaves;
+ bool _stitchTiles;
+ int _wrapx, _wrapy, _wrapw, _wraph;
+ bool _inited;
+ bool _fractalnoise;
+};
+
FilterTurbulence::FilterTurbulence()
-: XbaseFrequency(0),
- YbaseFrequency(0),
- numOctaves(1),
- seed(0),
- updated(false),
- updated_area(NR::IPoint(), NR::IPoint()),
- pix(NULL),
- fTileWidth(10), //guessed
- fTileHeight(10), //guessed
- fTileX(1), //guessed
- fTileY(1) //guessed
+ : gen(new TurbulenceGenerator())
+ , XbaseFrequency(0)
+ , YbaseFrequency(0)
+ , numOctaves(1)
+ , seed(0)
+ , updated(false)
+ , updated_area(NR::IPoint(), NR::IPoint())
+ , fTileWidth(10) //guessed
+ , fTileHeight(10) //guessed
+ , fTileX(1) //guessed
+ , fTileY(1) //guessed
{
}
@@ -50,305 +313,79 @@ FilterPrimitive * FilterTurbulence::create() {
FilterTurbulence::~FilterTurbulence()
{
- if (pix) {
- nr_pixblock_release(pix);
- delete pix;
- }
+ delete gen;
}
void FilterTurbulence::set_baseFrequency(int axis, double freq){
if (axis==0) XbaseFrequency=freq;
if (axis==1) YbaseFrequency=freq;
+ gen->dirty();
}
void FilterTurbulence::set_numOctaves(int num){
- numOctaves=num;
+ numOctaves = num;
+ gen->dirty();
}
void FilterTurbulence::set_seed(double s){
- seed=s;
+ seed = s;
+ gen->dirty();
}
void FilterTurbulence::set_stitchTiles(bool st){
- stitchTiles=st;
+ stitchTiles = st;
+ gen->dirty();
}
void FilterTurbulence::set_type(FilterTurbulenceType t){
- type=t;
+ type = t;
+ gen->dirty();
}
void FilterTurbulence::set_updated(bool u){
- updated=u;
}
-void FilterTurbulence::render_area(NRPixBlock *pix, NR::IRect &full_area, FilterUnits const &units) {
- const int bbox_x0 = full_area.min()[NR::X];
- const int bbox_y0 = full_area.min()[NR::Y];
- const int bbox_x1 = full_area.max()[NR::X];
- const int bbox_y1 = full_area.max()[NR::Y];
-
- Geom::Affine unit_trans = units.get_matrix_primitiveunits2pb().inverse();
-
- double point[2];
-
- unsigned char *pb = NR_PIXBLOCK_PX(pix);
-
- if (type==TURBULENCE_TURBULENCE){
- for (int y = std::max(bbox_y0, pix->area.y0); y < std::min(bbox_y1, pix->area.y1); y++){
- int out_line = (y - pix->area.y0) * pix->rs;
- point[1] = y * unit_trans[3] + unit_trans[5];
- for (int x = std::max(bbox_x0, pix->area.x0); x < std::min(bbox_x1, pix->area.x1); x++){
- int out_pos = out_line + 4 * (x - pix->area.x0);
- point[0] = x * unit_trans[0] + unit_trans[4];
- pb[out_pos] = CLAMP_D_TO_U8( turbulence(0,point)*255 ); // CLAMP includes rounding!
- pb[out_pos + 1] = CLAMP_D_TO_U8( turbulence(1,point)*255 );
- pb[out_pos + 2] = CLAMP_D_TO_U8( turbulence(2,point)*255 );
- pb[out_pos + 3] = CLAMP_D_TO_U8( turbulence(3,point)*255 );
- }
- }
- } else {
- for (int y = std::max(bbox_y0, pix->area.y0); y < std::min(bbox_y1, pix->area.y1); y++){
- int out_line = (y - pix->area.y0) * pix->rs;
- point[1] = y * unit_trans[3] + unit_trans[5];
- for (int x = std::max(bbox_x0, pix->area.x0); x < std::min(bbox_x1, pix->area.x1); x++){
- int out_pos = out_line + 4 * (x - pix->area.x0);
- point[0] = x * unit_trans[0] + unit_trans[4];
- pb[out_pos] = CLAMP_D_TO_U8( ((turbulence(0,point)*255) +255)/2 );
- pb[out_pos + 1] = CLAMP_D_TO_U8( ((turbulence(1,point)*255)+255)/2 );
- pb[out_pos + 2] = CLAMP_D_TO_U8( ((turbulence(2,point)*255) +255)/2 );
- pb[out_pos + 3] = CLAMP_D_TO_U8( ((turbulence(3,point)*255) +255)/2 );
- }
- }
+struct Turbulence {
+ Turbulence(TurbulenceGenerator const &gen, Geom::Affine const &trans, int x0, int y0)
+ : _gen(gen)
+ , _trans(trans)
+ , _x0(x0), _y0(y0)
+ {}
+ guint32 operator()(int x, int y) {
+ Geom::Point point(x + _x0, y + _y0);
+ point *= _trans;
+ return _gen.turbulencePixel(point);
}
+private:
+ TurbulenceGenerator const &_gen;
+ Geom::Affine _trans;
+ int _x0, _y0;
+};
- pix->empty = FALSE;
-}
-
-void FilterTurbulence::update_pixbuffer(NR::IRect &area, FilterUnits const &units) {
- int bbox_x0 = area.min()[NR::X];
- int bbox_y0 = area.min()[NR::Y];
- int bbox_x1 = area.max()[NR::X];
- int bbox_y1 = area.max()[NR::Y];
-
- TurbulenceInit((long)seed);
-
- if (!pix){
- pix = new NRPixBlock;
- nr_pixblock_setup_fast(pix, NR_PIXBLOCK_MODE_R8G8B8A8N, bbox_x0, bbox_y0, bbox_x1, bbox_y1, true);
- }
- else if (bbox_x0 != pix->area.x0 || bbox_y0 != pix->area.y0 ||
- bbox_x1 != pix->area.x1 || bbox_y1 != pix->area.y1)
- {
- /* TODO: release-setup cycle not actually needed, if pixblock
- * width and height don't change */
- nr_pixblock_release(pix);
- nr_pixblock_setup_fast(pix, NR_PIXBLOCK_MODE_R8G8B8A8N, bbox_x0, bbox_y0, bbox_x1, bbox_y1, true);
- }
-
- /* This limits pre-rendered turbulence to two megapixels. This is
- * arbitary limit and could be something other, too.
- * If bigger area is needed, visible area is rendered on demand. */
- if (!pix || (pix->size != NR_PIXBLOCK_SIZE_TINY && pix->data.px == NULL) ||
- ((bbox_x1 - bbox_x0) * (bbox_y1 - bbox_y0) > 2*1024*1024)) {
- pix_data = NULL;
- return;
+void FilterTurbulence::render_cairo(FilterSlot &slot)
+{
+ cairo_surface_t *input = slot.getcairo(_input);
+ cairo_surface_t *out = ink_cairo_surface_create_same_size(input, CAIRO_CONTENT_COLOR_ALPHA);
+
+ if (!gen->ready()) {
+ Geom::Point ta(fTileX, fTileY);
+ Geom::Point tb(fTileX + fTileWidth, fTileY + fTileHeight);
+ gen->init(seed, Geom::Rect(ta, tb),
+ Geom::Point(XbaseFrequency, YbaseFrequency), stitchTiles,
+ type == TURBULENCE_FRACTALNOISE, numOctaves);
}
- render_area(pix, area, units);
-
- pix_data = NR_PIXBLOCK_PX(pix);
-
- updated=true;
- updated_area = area;
-}
+ Geom::Affine unit_trans = slot.get_units().get_matrix_primitiveunits2pb().inverse();
+ Geom::Rect slot_area = slot.get_slot_area();
+ double x0 = slot_area.min()[Geom::X];
+ double y0 = slot_area.min()[Geom::Y];
-int FilterTurbulence::render(FilterSlot &slot, FilterUnits const &units) {
- NR::IRect area = units.get_pixblock_filterarea_paraller();
- // TODO: could be faster - updated_area only has to be same size as area
- if (!updated || updated_area != area) update_pixbuffer(area, units);
+ ink_cairo_surface_synthesize(out, Turbulence(*gen, unit_trans, x0, y0));
- NRPixBlock *in = slot.get(_input);
- if (!in) {
- g_warning("Missing source image for feTurbulence (in=%d)", _input);
- return 1;
- }
+ cairo_surface_mark_dirty(out);
- NRPixBlock *out = new NRPixBlock;
- int x0 = in->area.x0, y0 = in->area.y0;
- int x1 = in->area.x1, y1 = in->area.y1;
- nr_pixblock_setup_fast(out, NR_PIXBLOCK_MODE_R8G8B8A8N, x0, y0, x1, y1, true);
-
- if (pix_data) {
- /* If pre-rendered output of whole filter area exists, just copy it. */
- nr_blit_pixblock_pixblock(out, pix);
- } else {
- /* No pre-rendered output, render the required area here. */
- render_area(out, area, units);
- }
-
- out->empty = FALSE;
slot.set(_output, out);
- return 0;
-}
-
-long FilterTurbulence::Turbulence_setup_seed(long lSeed)
-{
- if (lSeed <= 0) lSeed = -(lSeed % (RAND_m - 1)) + 1;
- if (lSeed > RAND_m - 1) lSeed = RAND_m - 1;
- return lSeed;
-}
-
-long FilterTurbulence::TurbulenceRandom(long lSeed)
-{
- long result;
- result = RAND_a * (lSeed % RAND_q) - RAND_r * (lSeed / RAND_q);
- if (result <= 0) result += RAND_m;
- return result;
-}
-
-void FilterTurbulence::TurbulenceInit(long lSeed)
-{
- double s;
- int i, j, k;
- lSeed = Turbulence_setup_seed(lSeed);
- for(k = 0; k < 4; k++)
- {
- for(i = 0; i < BSize; i++)
- {
- uLatticeSelector[i] = i;
- for (j = 0; j < 2; j++)
- fGradient[k][i][j] = (double)(((lSeed = TurbulenceRandom(lSeed)) % (BSize + BSize)) - BSize) / BSize;
- s = double(sqrt(fGradient[k][i][0] * fGradient[k][i][0] + fGradient[k][i][1] * fGradient[k][i][1]));
- fGradient[k][i][0] /= s;
- fGradient[k][i][1] /= s;
- }
- }
- while(--i)
- {
- k = uLatticeSelector[i];
- uLatticeSelector[i] = uLatticeSelector[j = (lSeed = TurbulenceRandom(lSeed)) % BSize];
- uLatticeSelector[j] = k;
- }
- for(i = 0; i < BSize + 2; i++)
- {
- uLatticeSelector[BSize + i] = uLatticeSelector[i];
- for(k = 0; k < 4; k++)
- for(j = 0; j < 2; j++)
- fGradient[k][BSize + i][j] = fGradient[k][i][j];
- }
-}
-
-double FilterTurbulence::TurbulenceNoise2(int nColorChannel, double vec[2], StitchInfo *pStitchInfo)
-{
- int bx0, bx1, by0, by1, b00, b10, b01, b11;
- double rx0, rx1, ry0, ry1, *q, sx, sy, a, b, t, u, v;
- int i, j;
- t = vec[0] + PerlinN;
- bx0 = (int)t;
- bx1 = bx0+1;
- rx0 = t - (int)t;
- rx1 = rx0 - 1.0f;
- t = vec[1] + PerlinN;
- by0 = (int)t;
- by1 = by0+1;
- ry0 = t - (int)t;
- ry1 = ry0 - 1.0f;
- // If stitching, adjust lattice points accordingly.
- if(pStitchInfo != NULL)
- {
- if(bx0 >= pStitchInfo->nWrapX)
- bx0 -= pStitchInfo->nWidth;
- if(bx1 >= pStitchInfo->nWrapX)
- bx1 -= pStitchInfo->nWidth;
- if(by0 >= pStitchInfo->nWrapY)
- by0 -= pStitchInfo->nHeight;
- if(by1 >= pStitchInfo->nWrapY)
- by1 -= pStitchInfo->nHeight;
- }
- bx0 &= BM;
- bx1 &= BM;
- by0 &= BM;
- by1 &= BM;
- i = uLatticeSelector[bx0];
- j = uLatticeSelector[bx1];
- b00 = uLatticeSelector[i + by0];
- b10 = uLatticeSelector[j + by0];
- b01 = uLatticeSelector[i + by1];
- b11 = uLatticeSelector[j + by1];
- sx = double(s_curve(rx0));
- sy = double(s_curve(ry0));
- q = fGradient[nColorChannel][b00]; u = rx0 * q[0] + ry0 * q[1];
- q = fGradient[nColorChannel][b10]; v = rx1 * q[0] + ry0 * q[1];
- a = turb_lerp(sx, u, v);
- q = fGradient[nColorChannel][b01]; u = rx0 * q[0] + ry1 * q[1];
- q = fGradient[nColorChannel][b11]; v = rx1 * q[0] + ry1 * q[1];
- b = turb_lerp(sx, u, v);
- return turb_lerp(sy, a, b);
-}
-
-double FilterTurbulence::turbulence(int nColorChannel, double *point)
-{
- StitchInfo stitch;
- StitchInfo *pStitchInfo = NULL; // Not stitching when NULL.
- // Adjust the base frequencies if necessary for stitching.
- if(stitchTiles)
- {
- // When stitching tiled turbulence, the frequencies must be adjusted
- // so that the tile borders will be continuous.
- if(XbaseFrequency != 0.0)
- {
- double fLoFreq = double(floor(fTileWidth * XbaseFrequency)) / fTileWidth;
- double fHiFreq = double(ceil(fTileWidth * XbaseFrequency)) / fTileWidth;
- if(XbaseFrequency / fLoFreq < fHiFreq / XbaseFrequency)
- XbaseFrequency = fLoFreq;
- else
- XbaseFrequency = fHiFreq;
- }
- if(YbaseFrequency != 0.0)
- {
- double fLoFreq = double(floor(fTileHeight * YbaseFrequency)) / fTileHeight;
- double fHiFreq = double(ceil(fTileHeight * YbaseFrequency)) / fTileHeight;
- if(YbaseFrequency / fLoFreq < fHiFreq / YbaseFrequency)
- YbaseFrequency = fLoFreq;
- else
- YbaseFrequency = fHiFreq;
- }
- // Set up TurbulenceInitial stitch values.
- pStitchInfo = &stitch;
- stitch.nWidth = int(fTileWidth * XbaseFrequency + 0.5f);
- stitch.nWrapX = int(fTileX * XbaseFrequency + PerlinN + stitch.nWidth);
- stitch.nHeight = int(fTileHeight * YbaseFrequency + 0.5f);
- stitch.nWrapY = int(fTileY * YbaseFrequency + PerlinN + stitch.nHeight);
- }
- double fSum = 0.0f;
- double vec[2];
- vec[0] = point[0] * XbaseFrequency;
- vec[1] = point[1] * YbaseFrequency;
- double ratio = 1;
- for(int nOctave = 0; nOctave < numOctaves; nOctave++)
- {
- if(type==TURBULENCE_FRACTALNOISE)
- fSum += double(TurbulenceNoise2(nColorChannel, vec, pStitchInfo) / ratio);
- else
- fSum += double(fabs(TurbulenceNoise2(nColorChannel, vec, pStitchInfo)) / ratio);
- vec[0] *= 2;
- vec[1] *= 2;
- ratio *= 2;
- if(pStitchInfo != NULL)
- {
- // Update stitch values. Subtracting PerlinN before the multiplication and
- // adding it afterward simplifies to subtracting it once.
- stitch.nWidth *= 2;
- stitch.nWrapX = 2 * stitch.nWrapX - PerlinN;
- stitch.nHeight *= 2;
- stitch.nWrapY = 2 * stitch.nWrapY - PerlinN;
- }
- }
- return fSum;
-}
-
-FilterTraits FilterTurbulence::get_input_traits() {
- return TRAIT_PARALLER;
+ cairo_surface_destroy(out);
}
} /* namespace Filters */
diff --git a/src/display/nr-filter-turbulence.h b/src/display/nr-filter-turbulence.h
index ee870f758..50161b6be 100644
--- a/src/display/nr-filter-turbulence.h
+++ b/src/display/nr-filter-turbulence.h
@@ -21,6 +21,7 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
+#include <2geom/point.h>
#include "display/nr-filter-primitive.h"
#include "display/nr-filter-slot.h"
#include "display/nr-filter-units.h"
@@ -35,32 +36,7 @@ enum FilterTurbulenceType {
TURBULENCE_ENDTYPE
};
-struct StitchInfo
-{
- int nWidth; // How much to subtract to wrap for stitching.
- int nHeight;
- int nWrapX; // Minimum value to wrap.
- int nWrapY;
-};
-
-/* Produces results in the range [1, 2**31 - 2].
-Algorithm is: r = (a * r) mod m
-where a = 16807 and m = 2**31 - 1 = 2147483647
-See [Park & Miller], CACM vol. 31 no. 10 p. 1195, Oct. 1988
-To test: the algorithm should produce the result 1043618065
-as the 10,000th generated number if the original seed is 1.
-*/
-#define RAND_m 2147483647 /* 2**31 - 1 */
-#define RAND_a 16807 /* 7**5; primitive root of m */
-#define RAND_q 127773 /* m / a */
-#define RAND_r 2836 /* m % a */
-#define BSize 0x100
-#define BM 0xff
-#define PerlinN 0x1000
-#define NP 12 /* 2^PerlinN */
-#define NM 0xfff
-#define s_curve(t) ( t * t * (3. - 2. * t) )
-#define turb_lerp(t, a, b) ( a + t * (b - a) )
+class TurbulenceGenerator;
class FilterTurbulence : public FilterPrimitive {
public:
@@ -68,9 +44,7 @@ public:
static FilterPrimitive *create();
virtual ~FilterTurbulence();
- virtual int render(FilterSlot &slot, FilterUnits const &units);
- void update_pixbuffer(NR::IRect &area, FilterUnits const &units);
- void render_area(NRPixBlock *pix, NR::IRect &full_area, FilterUnits const &units);
+ virtual void render_cairo(FilterSlot &slot);
void set_baseFrequency(int axis, double freq);
void set_numOctaves(int num);
@@ -78,14 +52,11 @@ public:
void set_stitchTiles(bool st);
void set_type(FilterTurbulenceType t);
void set_updated(bool u);
- virtual FilterTraits get_input_traits();
private:
- long Turbulence_setup_seed(long lSeed);
- long TurbulenceRandom(long lSeed);
- void TurbulenceInit(long lSeed);
- double TurbulenceNoise2(int nColorChannel, double vec[2], StitchInfo *pStitchInfo);
- double turbulence(int nColorChannel, double *point);
+ TurbulenceGenerator *gen;
+
+ void turbulenceInit(long seed);
double XbaseFrequency, YbaseFrequency;
int numOctaves;
@@ -94,17 +65,14 @@ private:
FilterTurbulenceType type;
bool updated;
NR::IRect updated_area;
- NRPixBlock *pix;
unsigned char *pix_data;
- int uLatticeSelector[BSize + BSize + 2];
- double fGradient[4][BSize + BSize + 2][2];
-
double fTileWidth;
double fTileHeight;
double fTileX;
double fTileY;
+
};
} /* namespace Filters */
diff --git a/src/display/nr-filter-units.h b/src/display/nr-filter-units.h
index b78e102cd..2fc3e5533 100644
--- a/src/display/nr-filter-units.h
+++ b/src/display/nr-filter-units.h
@@ -13,8 +13,6 @@
*/
#include "sp-filter-units.h"
-#include "libnr/nr-matrix.h"
-#include "libnr/nr-rect.h"
#include "libnr/nr-rect-l.h"
#include <2geom/affine.h>
#include <2geom/rect.h>
@@ -22,6 +20,18 @@
namespace Inkscape {
namespace Filters {
+/* Notes:
+ * - "filter units" is a coordinate system where the filter region is contained
+ * between (0,0) and (1,1). Do not confuse this with the filterUnits property
+ * - "primitive units" is the coordinate system in which all lengths and distances
+ * in the filter definition should be interpreted. They are affected by the value
+ * of the primitiveUnits attribute
+ * - "pb" is the coordinate system in which filter rendering happens.
+ * It might be aligned with user or screen coordinates depending on
+ * the filter primitives used in the filter.
+ * - "display" are world coordinates of the canvas - pixel grid coordinates
+ * of the drawing area translated so that (0,0) corresponds to the document origin
+ */
class FilterUnits {
public:
FilterUnits();
diff --git a/src/display/nr-filter.cpp b/src/display/nr-filter.cpp
index 85815c31a..55190b00c 100644
--- a/src/display/nr-filter.cpp
+++ b/src/display/nr-filter.cpp
@@ -15,6 +15,7 @@
#include <cmath>
#include <cstring>
#include <string>
+#include <cairo.h>
#include "display/nr-filter.h"
#include "display/nr-filter-primitive.h"
@@ -41,8 +42,6 @@
#include "display/nr-arena.h"
#include "display/nr-arena-item.h"
-#include "libnr/nr-pixblock.h"
-#include "libnr/nr-blit.h"
#include <2geom/affine.h>
#include <2geom/rect.h>
#include "svg/svg-length.h"
@@ -60,43 +59,14 @@ namespace Filters {
using Geom::X;
using Geom::Y;
-static Geom::OptRect get_item_bbox(NRArenaItem const *item) {
- Geom::Rect item_bbox;
- if (item->item_bbox) {
- item_bbox = *(item->item_bbox);
- } else {
- // Bounding box might not exist, so create a dummy one.
- Geom::Point zero(0, 0);
- item_bbox = Geom::Rect(zero, zero);
- }
- if (item_bbox.min()[X] > item_bbox.max()[X]
- || item_bbox.min()[Y] > item_bbox.max()[Y])
- {
- // In case of negative-size bbox, return an empty OptRect
- return Geom::OptRect();
- }
- return Geom::OptRect(item_bbox);
-}
-
Filter::Filter()
{
- _primitive_count = 0;
- _primitive_table_size = 1;
- _primitive = new FilterPrimitive*[1];
- _primitive[0] = NULL;
- //_primitive_count = 1;
- //_primitive[0] = new FilterGaussian;
_common_init();
}
Filter::Filter(int n)
{
- _primitive_count = 0;
- _primitive_table_size = (n > 0) ? n : 1; // we guarantee there is at least 1(one) filter slot
- _primitive = new FilterPrimitive*[_primitive_table_size];
- for ( int i = 0 ; i < _primitive_table_size ; i++ ) {
- _primitive[i] = NULL;
- }
+ if (n > 0) _primitive.reserve(n);
_common_init();
}
@@ -125,51 +95,56 @@ void Filter::_common_init() {
Filter::~Filter()
{
clear_primitives();
- delete[] _primitive;
}
-int Filter::render(NRArenaItem const *item, NRPixBlock *pb)
+int Filter::render(NRArenaItem const *item, cairo_t *bgct, NRRectL const *bgarea, cairo_t *graphic, NRRectL const *area)
{
- if (!_primitive[0]) {
- // TODO: Should clear the input buffer instead of just returning
- return 1;
+ if (_primitive.empty()) {
+ // when no primitives are defined, clear source graphic
+ cairo_set_source_rgba(graphic, 0,0,0,0);
+ cairo_set_operator(graphic, CAIRO_OPERATOR_SOURCE);
+ cairo_paint(graphic);
+ cairo_set_operator(graphic, CAIRO_OPERATOR_OVER);
+ return 1;
}
FilterQuality const filterquality = (FilterQuality)item->arena->filterquality;
int const blurquality = item->arena->blurquality;
Geom::Affine trans = item->ctm;
- FilterSlot slot(_slot_count, item);
- slot.set_quality(filterquality);
- slot.set_blurquality(blurquality);
Geom::Rect item_bbox;
{
- Geom::OptRect maybe_bbox = get_item_bbox(item);
+ Geom::OptRect maybe_bbox = item->item_bbox;
if (maybe_bbox.isEmpty()) {
// Code below needs a bounding box
return 1;
}
item_bbox = *maybe_bbox;
}
-
- Geom::Rect filter_area = filter_effect_area(item_bbox);
if (item_bbox.hasZeroArea()) {
// It's no use to try and filter an empty object.
return 1;
}
+ Geom::Rect filter_area = filter_effect_area(item_bbox);
FilterUnits units(_filter_units, _primitive_units);
units.set_ctm(trans);
units.set_item_bbox(item_bbox);
units.set_filter_area(filter_area);
- // TODO: with filterRes of 0x0 should return an empty image
std::pair<double,double> resolution
= _filter_resolution(filter_area, trans, filterquality);
- if(!(resolution.first > 0 && resolution.second > 0))
- return 1;
+ if (!(resolution.first > 0 && resolution.second > 0)) {
+ // zero resolution - clear source graphic and return
+ cairo_set_source_rgba(graphic, 0,0,0,0);
+ cairo_set_operator(graphic, CAIRO_OPERATOR_SOURCE);
+ cairo_paint(graphic);
+ cairo_set_operator(graphic, CAIRO_OPERATOR_OVER);
+ return 1;
+ }
+
units.set_resolution(resolution.first, resolution.second);
if (_x_pixels > 0) {
units.set_automatic_resolution(false);
@@ -179,47 +154,29 @@ int Filter::render(NRArenaItem const *item, NRPixBlock *pb)
}
units.set_paraller(false);
- for (int i = 0 ; i < _primitive_count ; i++) {
- if (_primitive[i]->get_input_traits() & TRAIT_PARALLER) {
+ Geom::Affine pbtrans = units.get_matrix_display2pb();
+ for (unsigned i = 0 ; i < _primitive.size() ; i++) {
+ if (!_primitive[i]->can_handle_affine(pbtrans)) {
units.set_paraller(true);
break;
}
}
- slot.set_units(units);
-
- NRPixBlock *in = new NRPixBlock;
- nr_pixblock_setup_fast(in, pb->mode, pb->area.x0, pb->area.y0,
- pb->area.x1, pb->area.y1, true);
- if (in->size != NR_PIXBLOCK_SIZE_TINY && in->data.px == NULL) {
- g_warning("Inkscape::Filters::Filter::render: failed to reserve temporary buffer");
- return 0;
- }
- nr_blit_pixblock_pixblock(in, pb);
- in->empty = FALSE;
- slot.set(NR_FILTER_SOURCEGRAPHIC, in);
-
- // Check that we are rendering a non-empty area
- in = slot.get(NR_FILTER_SOURCEGRAPHIC);
- if (in->area.x1 - in->area.x0 <= 0 || in->area.y1 - in->area.y0 <= 0) {
- if (in->area.x1 - in->area.x0 < 0 || in->area.y1 - in->area.y0 < 0) {
- g_warning("Inkscape::Filters::Filter::render: negative area! (%d, %d) (%d, %d)",
- in->area.x0, in->area.y0, in->area.x1, in->area.y1);
- }
- return 0;
- }
- in = NULL; // in is now handled by FilterSlot, we should not touch it
+ FilterSlot slot(const_cast<NRArenaItem*>(item), bgct, bgarea, cairo_get_target(graphic), area, units);
+ slot.set_quality(filterquality);
+ slot.set_blurquality(blurquality);
- for (int i = 0 ; i < _primitive_count ; i++) {
- _primitive[i]->render(slot, units);
+ for (unsigned i = 0 ; i < _primitive.size() ; i++) {
+ _primitive[i]->render_cairo(slot);
}
- slot.get_final(_output_slot, pb);
+ cairo_surface_t *result = slot.get_result(_output_slot);
+ cairo_set_source_surface(graphic, result, area->x0, area->y0);
+ cairo_set_operator(graphic, CAIRO_OPERATOR_SOURCE);
+ cairo_paint(graphic);
+ cairo_set_operator(graphic, CAIRO_OPERATOR_OVER);
+ cairo_surface_destroy(result);
- // Take note of the amount of used image slots
- // -> next time this filter is rendered, we can reserve enough slots
- // immediately
- _slot_count = slot.get_slot_count();
return 0;
}
@@ -232,9 +189,10 @@ void Filter::set_primitive_units(SPFilterUnits unit) {
}
void Filter::area_enlarge(NRRectL &bbox, NRArenaItem const *item) const {
- for (int i = 0 ; i < _primitive_count ; i++) {
+ for (unsigned i = 0 ; i < _primitive.size() ; i++) {
if (_primitive[i]) _primitive[i]->area_enlarge(bbox, item->ctm);
}
+
/*
TODO: something. See images at the bottom of filters.svg with medium-low
filtering quality.
@@ -248,7 +206,7 @@ void Filter::area_enlarge(NRRectL &bbox, NRArenaItem const *item) const {
}
Geom::Rect item_bbox;
- Geom::OptRect maybe_bbox = get_item_bbox(item);
+ Geom::OptRect maybe_bbox = item->item_bbox;
if (maybe_bbox.isEmpty()) {
// Code below needs a bounding box
return;
@@ -268,30 +226,29 @@ void Filter::area_enlarge(NRRectL &bbox, NRArenaItem const *item) const {
*/
}
-void Filter::bbox_enlarge(NRRectL &bbox) {
+void Filter::compute_drawbox(NRArenaItem const *item, NRRectL &item_bbox) {
// Modifying empty bounding boxes confuses rest of the renderer, so
// let's not do that.
- if (bbox.x0 > bbox.x1 || bbox.y0 > bbox.y1) return;
+ if (item_bbox.x0 > item_bbox.x1 || item_bbox.y0 > item_bbox.y1) return;
- /* TODO: this is wrong. Should use bounding box in user coordinates
- * and find its extents in display coordinates. */
- Geom::Point min(bbox.x0, bbox.y0);
- Geom::Point max(bbox.x1, bbox.y1);
+ Geom::Point min(item_bbox.x0, item_bbox.y0);
+ Geom::Point max(item_bbox.x1, item_bbox.y1);
Geom::Rect tmp_bbox(min, max);
Geom::Rect enlarged = filter_effect_area(tmp_bbox);
+ enlarged = enlarged * item->ctm;
- bbox.x0 = (NR::ICoord)enlarged.min()[X];
- bbox.y0 = (NR::ICoord)enlarged.min()[Y];
- bbox.x1 = (NR::ICoord)enlarged.max()[X];
- bbox.y1 = (NR::ICoord)enlarged.max()[Y];
+ item_bbox.x0 = (NR::ICoord) floor(enlarged.min()[X]);
+ item_bbox.y0 = (NR::ICoord) floor(enlarged.min()[Y]);
+ item_bbox.x1 = (NR::ICoord) ceil(enlarged.max()[X]);
+ item_bbox.y1 = (NR::ICoord) ceil(enlarged.max()[Y]);
}
Geom::Rect Filter::filter_effect_area(Geom::Rect const &bbox)
{
Geom::Point minp, maxp;
- double len_x = bbox.max()[X] - bbox.min()[X];
- double len_y = bbox.max()[Y] - bbox.min()[Y];
+ double len_x = bbox.width();
+ double len_y = bbox.height();
/* TODO: fetch somehow the object ex and em lengths */
_region_x.update(12, 6, len_x);
_region_y.update(12, 6, len_y);
@@ -367,27 +324,6 @@ void Filter::_create_constructor_table()
created = true;
}
-/** Helper method for enlarging table of filter primitives. When new
- * primitives are added, but we have no space for them, this function
- * makes some more space.
- */
-void Filter::_enlarge_primitive_table() {
- FilterPrimitive **new_tbl = new FilterPrimitive*[_primitive_table_size * 2];
- for (int i = 0 ; i < _primitive_count ; i++) {
- new_tbl[i] = _primitive[i];
- }
- _primitive_table_size *= 2;
- for (int i = _primitive_count ; i < _primitive_table_size ; i++) {
- new_tbl[i] = NULL;
- }
- if(_primitive != NULL) {
- delete[] _primitive;
- } else {
- g_warning("oh oh");
- }
- _primitive = new_tbl;
-}
-
int Filter::add_primitive(FilterPrimitiveType type)
{
_create_constructor_table();
@@ -398,14 +334,8 @@ int Filter::add_primitive(FilterPrimitiveType type)
if (!_constructor[type]) return -1;
FilterPrimitive *created = _constructor[type]();
- // If there is no space for new filter primitive, enlarge the table
- if (_primitive_count >= _primitive_table_size) {
- _enlarge_primitive_table();
- }
-
- _primitive[_primitive_count] = created;
- int handle = _primitive_count;
- _primitive_count++;
+ int handle = _primitive.size();
+ _primitive.push_back(created);
return handle;
}
@@ -415,8 +345,7 @@ int Filter::replace_primitive(int target, FilterPrimitiveType type)
// Check that target is valid primitive inside this filter
if (target < 0) return -1;
- if (target >= _primitive_count) return -1;
- if (!_primitive[target]) return -1;
+ if (static_cast<unsigned>(target) >= _primitive.size()) return -1;
// Check that we can create a new filter of specified type
if (type < 0 || type >= NR_FILTER_ENDPRIMITIVETYPE)
@@ -424,27 +353,22 @@ int Filter::replace_primitive(int target, FilterPrimitiveType type)
if (!_constructor[type]) return -1;
FilterPrimitive *created = _constructor[type]();
- // If there is no space for new filter primitive, enlarge the table
- if (_primitive_count >= _primitive_table_size) {
- _enlarge_primitive_table();
- }
-
delete _primitive[target];
_primitive[target] = created;
return target;
}
FilterPrimitive *Filter::get_primitive(int handle) {
- if (handle < 0 || handle >= _primitive_count) return NULL;
+ if (handle < 0 || handle >= static_cast<int>(_primitive.size())) return NULL;
return _primitive[handle];
}
void Filter::clear_primitives()
{
- for (int i = 0 ; i < _primitive_count ; i++) {
- if (_primitive[i]) delete _primitive[i];
+ for (unsigned i = 0 ; i < _primitive.size() ; i++) {
+ delete _primitive[i];
}
- _primitive_count = 0;
+ _primitive.clear();
}
void Filter::set_x(SVGLength const &length)
diff --git a/src/display/nr-filter.h b/src/display/nr-filter.h
index ae5f96420..e1d4c10e5 100644
--- a/src/display/nr-filter.h
+++ b/src/display/nr-filter.h
@@ -13,10 +13,9 @@
*/
//#include "display/nr-arena-item.h"
+#include <cairo.h>
#include "display/nr-filter-primitive.h"
#include "display/nr-filter-types.h"
-#include "libnr/nr-pixblock.h"
-#include "libnr/nr-matrix.h"
#include "libnr/nr-rect.h"
#include "svg/svg-length.h"
#include "sp-filter-units.h"
@@ -29,7 +28,12 @@ namespace Filters {
class Filter : public Inkscape::GC::Managed<> {
public:
- int render(NRArenaItem const *item, NRPixBlock *pb);
+ /** Given background state from @a bgct and an intermediate rendering from the surface
+ * backing @a graphic, modify the contents of the surface backing @a graphic to represent
+ * the results of filter rendering. @a bgarea and @a area specify bounding boxes
+ * of both surfaces in world coordinates; Cairo contexts are assumed to be in default state
+ * (0,0 = surface origin, no path, OVER operator) */
+ int render(NRArenaItem const *item, cairo_t *bgct, NRRectL const *bgarea, cairo_t *graphic, NRRectL const *area);
/**
* Creates a new filter primitive under this filter object.
@@ -147,10 +151,11 @@ public:
*/
void area_enlarge(NRRectL &area, NRArenaItem const *item) const;
/**
- * Given an object bounding box, this function enlarges it so that
- * it contains the filter effect area.
+ * Given an item bounding box (in user coords), this function enlarges it
+ * to contain the filter effects region and transforms it to screen
+ * coordinates
*/
- void bbox_enlarge(NRRectL &bbox);
+ void compute_drawbox(NRArenaItem const *item, NRRectL &item_bbox);
/**
* Returns the filter effects area in user coordinate system.
* The given bounding box should be a bounding box as specified in
@@ -170,9 +175,7 @@ public:
virtual ~Filter();
private:
- int _primitive_count;
- int _primitive_table_size;
-
+ std::vector<FilterPrimitive*> _primitive;
/** Amount of image slots used, when this filter was rendered last time */
int _slot_count;
@@ -194,10 +197,7 @@ private:
SPFilterUnits _filter_units;
SPFilterUnits _primitive_units;
- FilterPrimitive ** _primitive;
-
void _create_constructor_table();
- void _enlarge_primitive_table();
void _common_init();
int _resolution_limit(FilterQuality const quality) const;
std::pair<double,double> _filter_resolution(Geom::Rect const &area,
diff --git a/src/display/nr-light.cpp b/src/display/nr-light.cpp
index 74d83da70..65912470d 100644
--- a/src/display/nr-light.cpp
+++ b/src/display/nr-light.cpp
@@ -13,12 +13,12 @@
#include <cmath>
-#include "libnr/nr-pixops.h"
#include "display/nr-light.h"
#include "display/nr-3dutils.h"
#include "filters/distantlight.h"
#include "filters/pointlight.h"
#include "filters/spotlight.h"
+#include "color.h"
namespace Inkscape {
namespace Filters {
@@ -38,9 +38,9 @@ void DistantLight::light_vector(NR::Fvector &v) {
}
void DistantLight::light_components(NR::Fvector &lc) {
- lc[LIGHT_RED] = NR_RGBA32_R(color);
- lc[LIGHT_GREEN] = NR_RGBA32_G(color);
- lc[LIGHT_BLUE] = NR_RGBA32_B(color);
+ lc[LIGHT_RED] = SP_RGBA32_R_U(color);
+ lc[LIGHT_GREEN] = SP_RGBA32_G_U(color);
+ lc[LIGHT_BLUE] = SP_RGBA32_B_U(color);
}
PointLight::PointLight(SPFePointLight *light, guint32 lighting_color, const Geom::Affine &trans) {
@@ -61,9 +61,9 @@ void PointLight::light_vector(NR::Fvector &v, gdouble x, gdouble y, gdouble z) {
}
void PointLight::light_components(NR::Fvector &lc) {
- lc[LIGHT_RED] = NR_RGBA32_R(color);
- lc[LIGHT_GREEN] = NR_RGBA32_G(color);
- lc[LIGHT_BLUE] = NR_RGBA32_B(color);
+ lc[LIGHT_RED] = SP_RGBA32_R_U(color);
+ lc[LIGHT_GREEN] = SP_RGBA32_G_U(color);
+ lc[LIGHT_BLUE] = SP_RGBA32_B_U(color);
}
SpotLight::SpotLight(SPFeSpotLight *light, guint32 lighting_color, const Geom::Affine &trans) {
@@ -101,9 +101,9 @@ void SpotLight::light_components(NR::Fvector &lc, const NR::Fvector &L) {
spmod = 0;
else
spmod = std::pow(spmod, speExp);
- lc[LIGHT_RED] = spmod * NR_RGBA32_R(color);
- lc[LIGHT_GREEN] = spmod * NR_RGBA32_G(color);
- lc[LIGHT_BLUE] = spmod * NR_RGBA32_B(color);
+ lc[LIGHT_RED] = spmod * SP_RGBA32_R_U(color);
+ lc[LIGHT_GREEN] = spmod * SP_RGBA32_G_U(color);
+ lc[LIGHT_BLUE] = spmod * SP_RGBA32_B_U(color);
}
} /* namespace Filters */
diff --git a/src/display/nr-plain-stuff-gdk.cpp b/src/display/nr-plain-stuff-gdk.cpp
deleted file mode 100644
index d5b43f4ea..000000000
--- a/src/display/nr-plain-stuff-gdk.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-#define __NR_PLAIN_STUFF_GDK_C__
-
-/*
- * Miscellaneous simple rendering utilities
- *
- * Author:
- * Lauris Kaplinski <lauris@ximian.com>
- *
- * Copyright (C) 2001 Lauris Kaplinski and Ximian, Inc.
- *
- * Released under GNU GPL
- */
-
-#include <libnr/nr-pixblock-pattern.h>
-#include "nr-plain-stuff.h"
-#include "nr-plain-stuff-gdk.h"
-
-void
-nr_gdk_draw_rgba32_solid (GdkDrawable *drawable, GdkGC *gc, gint x, gint y, gint w, gint h, guint32 rgba)
-{
- NRPixBlock pb;
-
- nr_pixblock_setup_fast (&pb, NR_PIXBLOCK_MODE_R8G8B8A8N, 0, 0, w, h, FALSE);
-
- nr_render_rgba32_rgb (NR_PIXBLOCK_PX (&pb), w, h, pb.rs, x, y, rgba);
- gdk_draw_rgb_image (drawable, gc, x, y, w, h, GDK_RGB_DITHER_MAX, NR_PIXBLOCK_PX (&pb), pb.rs);
-
- nr_pixblock_release (&pb);
-}
-
-void
-nr_gdk_draw_gray_garbage (GdkDrawable *drawable, GdkGC *gc, gint x, gint y, gint w, gint h)
-{
- for (gint yy = y; yy < y + h; yy += 64) {
- for (gint xx = x; xx < x + w; xx += 64) {
- NRPixBlock pb;
- gint ex = MIN (xx + 64, x + w);
- gint ey = MIN (yy + 64, y + h);
- nr_pixblock_setup_fast (&pb, NR_PIXBLOCK_MODE_R8G8B8, xx, yy, ex, ey, FALSE);
- nr_pixblock_render_gray_noise (&pb, NULL);
- gdk_draw_rgb_image (drawable, gc, xx, yy, ex - xx, ey - yy, GDK_RGB_DITHER_NONE, NR_PIXBLOCK_PX (&pb), pb.rs);
- nr_pixblock_release (&pb);
- }
- }
-}
-
diff --git a/src/display/nr-plain-stuff-gdk.h b/src/display/nr-plain-stuff-gdk.h
deleted file mode 100644
index bff54a81f..000000000
--- a/src/display/nr-plain-stuff-gdk.h
+++ /dev/null
@@ -1,32 +0,0 @@
-#ifndef __NR_PLAIN_STUFF_GDK_H__
-#define __NR_PLAIN_STUFF_GDK_H__
-
-/*
- * Miscellaneous simple rendering utilities
- *
- * Author:
- * Lauris Kaplinski <lauris@ximian.com>
- *
- * Copyright (C) 2001 Lauris Kaplinski and Ximian, Inc.
- *
- * Released under GNU GPL
- */
-
-#include <gdk/gdk.h>
-
-void nr_gdk_draw_rgba32_solid (GdkDrawable *drawable, GdkGC *gc, gint x, gint y, gint w, gint h, guint32 rgba);
-
-void nr_gdk_draw_gray_garbage (GdkDrawable *drawable, GdkGC *gc, gint x, gint y, gint w, gint 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:textwidth=99 :
diff --git a/src/display/nr-plain-stuff.cpp b/src/display/nr-plain-stuff.cpp
deleted file mode 100644
index 62a61102e..000000000
--- a/src/display/nr-plain-stuff.cpp
+++ /dev/null
@@ -1,94 +0,0 @@
-#define __NR_PLAIN_STUFF_C__
-
-/*
- * Miscellaneous simple rendering utilities
- *
- * Author:
- * Lauris Kaplinski <lauris@ximian.com>
- *
- * Copyright (C) 2001 Lauris Kaplinski and Ximian, Inc.
- *
- * Released under GNU GPL
- */
-
-#include <glib/gmessages.h>
-#include <libnr/nr-pixops.h>
-#include "nr-plain-stuff.h"
-
-#define NR_DEFAULT_CHECKERSIZEP2 2
-#define NR_DEFAULT_CHECKERCOLOR0 0xbfbfbfff
-#define NR_DEFAULT_CHECKERCOLOR1 0x808080ff
-
-void
-nr_render_checkerboard_rgb (guchar *px, gint w, gint h, gint rs, gint xoff, gint yoff)
-{
- g_return_if_fail (px != NULL);
-
- nr_render_checkerboard_rgb_custom (px, w, h, rs, xoff, yoff, NR_DEFAULT_CHECKERCOLOR0, NR_DEFAULT_CHECKERCOLOR1, NR_DEFAULT_CHECKERSIZEP2);
-}
-
-void
-nr_render_checkerboard_rgb_custom (guchar *px, gint w, gint h, gint rs, gint xoff, gint yoff, guint32 c0, guint32 c1, gint sizep2)
-{
- gint x, y, m;
- guint r0, g0, b0;
- guint r1, g1, b1;
-
- g_return_if_fail (px != NULL);
- g_return_if_fail (sizep2 >= 0);
- g_return_if_fail (sizep2 <= 8);
-
- xoff &= 0x1ff;
- yoff &= 0x1ff;
- m = 0x1 << sizep2;
- r0 = NR_RGBA32_R (c0);
- g0 = NR_RGBA32_G (c0);
- b0 = NR_RGBA32_B (c0);
- r1 = NR_RGBA32_R (c1);
- g1 = NR_RGBA32_G (c1);
- b1 = NR_RGBA32_B (c1);
-
- for (y = 0; y < h; y++) {
- guchar *p;
- p = px;
- for (x = 0; x < w; x++) {
- if (((x + xoff) ^ (y + yoff)) & m) {
- *p++ = r0;
- *p++ = g0;
- *p++ = b0;
- } else {
- *p++ = r1;
- *p++ = g1;
- *p++ = b1;
- }
- }
- px += rs;
- }
-}
-
-void
-nr_render_rgba32_rgb (guchar *px, gint w, gint h, gint rs, gint xoff, gint yoff, guint32 c)
-{
- guint32 c0, c1;
- gint a, r, g, b, cr, cg, cb;
-
- g_return_if_fail (px != NULL);
-
- r = NR_RGBA32_R (c);
- g = NR_RGBA32_G (c);
- b = NR_RGBA32_B (c);
- a = NR_RGBA32_A (c);
-
- cr = NR_COMPOSEN11_1111 (r, a, NR_RGBA32_R (NR_DEFAULT_CHECKERCOLOR0));
- cg = NR_COMPOSEN11_1111 (g, a, NR_RGBA32_G (NR_DEFAULT_CHECKERCOLOR0));
- cb = NR_COMPOSEN11_1111 (b, a, NR_RGBA32_B (NR_DEFAULT_CHECKERCOLOR0));
- c0 = (cr << 24) | (cg << 16) | (cb << 8) | 0xff;
-
- cr = NR_COMPOSEN11_1111 (r, a, NR_RGBA32_R (NR_DEFAULT_CHECKERCOLOR1));
- cg = NR_COMPOSEN11_1111 (g, a, NR_RGBA32_G (NR_DEFAULT_CHECKERCOLOR1));
- cb = NR_COMPOSEN11_1111 (b, a, NR_RGBA32_B (NR_DEFAULT_CHECKERCOLOR1));
- c1 = (cr << 24) | (cg << 16) | (cb << 8) | 0xff;
-
- nr_render_checkerboard_rgb_custom (px, w, h, rs, xoff, yoff, c0, c1, NR_DEFAULT_CHECKERSIZEP2);
-}
-
diff --git a/src/display/nr-plain-stuff.h b/src/display/nr-plain-stuff.h
deleted file mode 100644
index 457442312..000000000
--- a/src/display/nr-plain-stuff.h
+++ /dev/null
@@ -1,33 +0,0 @@
-#ifndef __NR_PLAIN_STUFF_H__
-#define __NR_PLAIN_STUFF_H__
-
-/*
- * Miscellaneous simple rendering utilities
- *
- * Author:
- * Lauris Kaplinski <lauris@ximian.com>
- *
- * Copyright (C) 2001 Lauris Kaplinski and Ximian, Inc.
- *
- * Released under GNU GPL
- */
-
-#include <glib/gtypes.h>
-
-void nr_render_checkerboard_rgb (guchar *px, gint w, gint h, gint rs, gint xoff, gint yoff);
-void nr_render_checkerboard_rgb_custom (guchar *px, gint w, gint h, gint rs, gint xoff, gint yoff, guint32 c0, guint32 c1, gint sizep2);
-
-void nr_render_rgba32_rgb (guchar *px, gint w, gint h, gint rs, gint xoff, gint yoff, guint32 c);
-
-#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:textwidth=99 :
diff --git a/src/display/nr-style.cpp b/src/display/nr-style.cpp
new file mode 100644
index 000000000..72fa0c444
--- /dev/null
+++ b/src/display/nr-style.cpp
@@ -0,0 +1,218 @@
+/**
+ * @file
+ * @brief Style information for rendering
+ *//*
+ * Authors:
+ * Krzysztof KosiƄski <tweenk.pl@gmail.com>
+ *
+ * Copyright (C) 2010 Authors
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "display/nr-style.h"
+#include "style.h"
+#include "sp-paint-server.h"
+#include "display/canvas-bpath.h" // contains SPStrokeJoinType, SPStrokeCapType etc. (WTF!)
+
+void NRStyle::Paint::clear()
+{
+ if (server) {
+ sp_object_unref(server, NULL);
+ server = NULL;
+ }
+ type = PAINT_NONE;
+}
+
+void NRStyle::Paint::set(SPColor const &c)
+{
+ clear();
+ type = PAINT_COLOR;
+ color = c;
+}
+
+void NRStyle::Paint::set(SPPaintServer *ps)
+{
+ clear();
+ if (ps) {
+ type = PAINT_SERVER;
+ server = ps;
+ sp_object_ref(server, NULL);
+ }
+}
+
+NRStyle::NRStyle()
+ : fill()
+ , stroke()
+ , stroke_width(0.0)
+ , miter_limit(0.0)
+ , n_dash(0)
+ , dash(NULL)
+ , dash_offset(0.0)
+ , fill_rule(CAIRO_FILL_RULE_EVEN_ODD)
+ , line_cap(CAIRO_LINE_CAP_BUTT)
+ , line_join(CAIRO_LINE_JOIN_MITER)
+ , fill_pattern(NULL)
+ , stroke_pattern(NULL)
+{}
+
+NRStyle::~NRStyle()
+{
+ if (fill_pattern) cairo_pattern_destroy(fill_pattern);
+ if (stroke_pattern) cairo_pattern_destroy(stroke_pattern);
+ if (dash) delete dash;
+}
+
+void NRStyle::set(SPStyle *style)
+{
+ if ( style->fill.isPaintserver() ) {
+ fill.set(style->getFillPaintServer());
+ } else if ( style->fill.isColor() ) {
+ fill.set(style->fill.value.color);
+ } else if ( style->fill.isNone() ) {
+ fill.clear();
+ } else {
+ g_assert_not_reached();
+ }
+ fill.opacity = SP_SCALE24_TO_FLOAT(style->fill_opacity.value);
+
+ switch (style->fill_rule.computed) {
+ case SP_WIND_RULE_EVENODD:
+ fill_rule = CAIRO_FILL_RULE_EVEN_ODD;
+ break;
+ case SP_WIND_RULE_NONZERO:
+ fill_rule = CAIRO_FILL_RULE_WINDING;
+ break;
+ default:
+ g_assert_not_reached();
+ }
+
+ if ( style->stroke.isPaintserver() ) {
+ stroke.set(style->getStrokePaintServer());
+ } else if ( style->stroke.isColor() ) {
+ stroke.set(style->stroke.value.color);
+ } else if ( style->stroke.isNone() ) {
+ stroke.clear();
+ } else {
+ g_assert_not_reached();
+ }
+ stroke.opacity = SP_SCALE24_TO_FLOAT(style->stroke_opacity.value);
+ stroke_width = style->stroke_width.computed;
+ switch (style->stroke_linecap.computed) {
+ case SP_STROKE_LINECAP_ROUND:
+ line_cap = CAIRO_LINE_CAP_ROUND;
+ break;
+ case SP_STROKE_LINECAP_SQUARE:
+ line_cap = CAIRO_LINE_CAP_SQUARE;
+ break;
+ case SP_STROKE_LINECAP_BUTT:
+ line_cap = CAIRO_LINE_CAP_BUTT;
+ break;
+ default:
+ g_assert_not_reached();
+ }
+ switch (style->stroke_linejoin.computed) {
+ case SP_STROKE_LINEJOIN_ROUND:
+ line_join = CAIRO_LINE_JOIN_ROUND;
+ break;
+ case SP_STROKE_LINEJOIN_BEVEL:
+ line_join = CAIRO_LINE_JOIN_BEVEL;
+ break;
+ case SP_STROKE_LINEJOIN_MITER:
+ line_join = CAIRO_LINE_JOIN_MITER;
+ break;
+ default:
+ g_assert_not_reached();
+ }
+ miter_limit = style->stroke_miterlimit.value;
+
+ if (dash) delete [] dash;
+
+ n_dash = style->stroke_dash.n_dash;
+ if (n_dash != 0) {
+ dash_offset = style->stroke_dash.offset;
+ dash = new double[n_dash];
+ for (unsigned int i = 0; i < n_dash; ++i) {
+ dash[i] = style->stroke_dash.dash[i];
+ }
+ } else {
+ dash_offset = 0.0;
+ dash = NULL;
+ }
+
+ update();
+}
+
+bool NRStyle::prepareFill(cairo_t *ct, NRRect *paintbox)
+{
+ // update fill pattern
+ if (!fill_pattern) {
+ switch (fill.type) {
+ case PAINT_SERVER:
+ fill_pattern = sp_paint_server_create_pattern(fill.server, ct, paintbox, fill.opacity);
+ break;
+ case PAINT_COLOR: {
+ SPColor const &c = fill.color;
+ fill_pattern = cairo_pattern_create_rgba(
+ c.v.c[0], c.v.c[1], c.v.c[2], fill.opacity);
+ } break;
+ default: break;
+ }
+ }
+ if (!fill_pattern) return false;
+ return true;
+}
+
+void NRStyle::applyFill(cairo_t *ct)
+{
+ cairo_set_source(ct, fill_pattern);
+ cairo_set_fill_rule(ct, fill_rule);
+}
+
+bool NRStyle::prepareStroke(cairo_t *ct, NRRect *paintbox)
+{
+ if (!stroke_pattern) {
+ switch (stroke.type) {
+ case PAINT_SERVER:
+ stroke_pattern = sp_paint_server_create_pattern(stroke.server, ct, 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;
+ }
+ }
+ if (!stroke_pattern) return false;
+ return true;
+}
+
+void NRStyle::applyStroke(cairo_t *ct)
+{
+ cairo_set_source(ct, stroke_pattern);
+ cairo_set_line_width(ct, stroke_width);
+ cairo_set_line_cap(ct, line_cap);
+ cairo_set_line_join(ct, line_join);
+ cairo_set_miter_limit(ct, miter_limit);
+ cairo_set_dash(ct, dash, n_dash, dash_offset);
+}
+
+void NRStyle::update()
+{
+ // force pattern update
+ if (fill_pattern) cairo_pattern_destroy(fill_pattern);
+ if (stroke_pattern) cairo_pattern_destroy(stroke_pattern);
+ fill_pattern = NULL;
+ stroke_pattern = 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:encoding=utf-8:textwidth=99 :
diff --git a/src/display/nr-style.h b/src/display/nr-style.h
new file mode 100644
index 000000000..e741e46b4
--- /dev/null
+++ b/src/display/nr-style.h
@@ -0,0 +1,81 @@
+/**
+ * @file
+ * @brief Style information for rendering
+ *//*
+ * Authors:
+ * Krzysztof KosiƄski <tweenk.pl@gmail.com>
+ *
+ * Copyright (C) 2010 Authors
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifndef SEEN_INKSCAPE_DISPLAY_NR_ARENA_STYLE_H
+#define SEEN_INKSCAPE_DISPLAY_NR_ARENA_STYLE_H
+
+#include <cairo.h>
+#include "color.h"
+
+class SPColor;
+class SPPaintServer;
+class SPStyle;
+struct NRRect;
+
+struct NRStyle {
+ NRStyle();
+ ~NRStyle();
+
+ void set(SPStyle *);
+ bool prepareFill(cairo_t *ct, NRRect *paintbox);
+ bool prepareStroke(cairo_t *ct, NRRect *paintbox);
+ void applyFill(cairo_t *ct);
+ void applyStroke(cairo_t *ct);
+ void update();
+
+ enum PaintType {
+ PAINT_NONE,
+ PAINT_COLOR,
+ PAINT_SERVER
+ };
+
+ struct Paint {
+ Paint() : type(PAINT_NONE), color(0), server(NULL), opacity(1.0) {}
+ ~Paint() { clear(); }
+
+ PaintType type;
+ SPColor color;
+ SPPaintServer *server;
+ float opacity;
+
+ void clear();
+ void set(SPColor const &c);
+ void set(SPPaintServer *ps);
+ };
+
+ Paint fill;
+ Paint stroke;
+ float stroke_width;
+ float miter_limit;
+ unsigned int n_dash;
+ double *dash;
+ float dash_offset;
+ cairo_fill_rule_t fill_rule;
+ cairo_line_cap_t line_cap;
+ cairo_line_join_t line_join;
+
+ cairo_pattern_t *fill_pattern;
+ cairo_pattern_t *stroke_pattern;
+};
+
+#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:encoding=utf-8:textwidth=99 :
diff --git a/src/display/nr-svgfonts.cpp b/src/display/nr-svgfonts.cpp
index cf23ee5d5..8869274d4 100644
--- a/src/display/nr-svgfonts.cpp
+++ b/src/display/nr-svgfonts.cpp
@@ -14,21 +14,21 @@
#include <2geom/pathvector.h>
#include <2geom/transforms.h>
-#include "../style.h"
#include <cairo.h>
#include <vector>
+#include "style.h"
#include "svg/svg.h"
-#include "inkscape-cairo.h"
-#include "nr-svgfonts.h"
-#include "../sp-path.h"
-#include "../sp-object-group.h"
-#include "../sp-use.h"
-#include "../sp-use-reference.h"
-#include "curve.h"
+#include "display/cairo-utils.h"
+#include "display/nr-svgfonts.h"
+#include "display/nr-svgfonts.h"
+#include "sp-path.h"
+#include "sp-object-group.h"
+#include "sp-use.h"
+#include "sp-use-reference.h"
+#include "display/curve.h"
#include "xml/repr.h"
#include "sp-font-face.h"
-
//*************************//
// UserFont Implementation //
//*************************//
diff --git a/src/display/pixblock-scaler.cpp b/src/display/pixblock-scaler.cpp
deleted file mode 100644
index 5af5230d8..000000000
--- a/src/display/pixblock-scaler.cpp
+++ /dev/null
@@ -1,299 +0,0 @@
-#define __NR_PIXBLOCK_SCALER_CPP__
-
-/*
- * Functions for blitting pixblocks using scaling
- *
- * Author:
- * Niko Kiirala <niko@kiirala.com>
- *
- * Copyright (C) 2006,2009 Niko Kiirala
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#include <glib.h>
-#include <cmath>
-#if defined (SOLARIS) && (SOLARIS == 8)
-#include "round.h"
-using Inkscape::round;
-#endif
-using std::floor;
-
-#include "display/nr-filter-utils.h"
-#include "libnr/nr-pixblock.h"
-#include "libnr/nr-blit.h"
-#include <2geom/forward.h>
-
-namespace NR {
-
-struct RGBA {
- double r, g, b, a;
-};
-
-/** Calculates cubically interpolated value of the four given pixel values.
- * The pixel values should be from four adjacent pixels in source image or
- * four adjacent interpolated values. len should be the x- or y-coordinate
- * (depending on interpolation direction) of the center of the target pixel
- * in source image coordinates.
- */
-__attribute__ ((const))
-inline static double sample(double const a, double const b,
- double const c, double const d,
- double const len)
-{
- double lena = 1.5 + (len - round(len));
- double lenb = 0.5 + (len - round(len));
- double lenc = 0.5 - (len - round(len));
- double lend = 1.5 - (len - round(len));
- double const f = -0.5; // corresponds to cubic Hermite spline
- double sum = 0;
- sum += ((((f * lena) - 5.0 * f) * lena + 8.0 * f) * lena - 4 * f) * a;
- sum += (((f + 2.0) * lenb - (f + 3.0)) * lenb * lenb + 1.0) * b;
- sum += (((f + 2.0) * lenc - (f + 3.0)) * lenc * lenc + 1.0) * c;
- sum += ((((f * lend) - 5.0 * f) * lend + 8.0 * f) * lend - 4 * f) * d;
-
- return sum;
-}
-
-/**
- * Sanity check function for indexing pixblocks.
- * Catches reading and writing outside the pixblock area.
- * When enabled, decreases filter rendering speed massively.
- */
-inline static void _check_index(NRPixBlock const * const pb, int const location, int const line)
-{
- if(false) {
- int max_loc = pb->rs * (pb->area.y1 - pb->area.y0);
- if (location < 0 || (location + 4) > max_loc)
- g_warning("Location %d out of bounds (0 ... %d) at line %d", location, max_loc, line);
- }
-}
-
-static void scale_bicubic_rgba(NRPixBlock *to, NRPixBlock *from,
- Geom::Affine const &trans)
-{
- if (NR_PIXBLOCK_BPP(from) != 4 || NR_PIXBLOCK_BPP(to) != 4) {
- g_warning("A non-32-bpp image passed to scale_bicubic_rgba: scaling aborted.");
- return;
- }
-
- bool free_from_on_exit = false;
- if (from->mode != to->mode){
- NRPixBlock *o_from = from;
- from = new NRPixBlock;
- nr_pixblock_setup_fast(from, to->mode, o_from->area.x0, o_from->area.y0, o_from->area.x1, o_from->area.y1, false);
- nr_blit_pixblock_pixblock(from, o_from);
- free_from_on_exit = true;
- }
-
- // Precalculate sizes of source and destination pixblocks
- int from_width = from->area.x1 - from->area.x0;
- int from_height = from->area.y1 - from->area.y0;
- int to_width = to->area.x1 - to->area.x0;
- int to_height = to->area.y1 - to->area.y0;
-
- // from_step: when advancing one pixel in destination image,
- // how much we should advance in source image
- double from_stepx = 1.0 / trans[0];
- double from_stepy = 1.0 / trans[3];
- double from_diffx = from_stepx * (-trans[4]);
- double from_diffy = from_stepy * (-trans[5]);
- from_diffx = (to->area.x0 * from_stepx + from_diffx) - from->area.x0;
- from_diffy = (to->area.y0 * from_stepy + from_diffy) - from->area.y0;
-
- // Loop through every pixel of destination image, a line at a time
- for (int to_y = 0 ; to_y < to_height ; to_y++) {
- double from_y = (to_y + 0.5) * from_stepy + from_diffy;
- // Pre-calculate beginning of the four horizontal lines, from
- // which we should read
- int from_line[4];
- for (int i = 0 ; i < 4 ; i++) {
- int fy_line = (int)round(from_y) + i - 2;
- if (fy_line >= 0) {
- if (fy_line < from_height) {
- from_line[i] = fy_line * from->rs;
- } else {
- from_line[i] = (from_height - 1) * from->rs;
- }
- } else {
- from_line[i] = 0;
- }
- }
- // Loop through this horizontal line in destination image
- // For every pixel, calculate the color of pixel with
- // bicubic interpolation and set the pixel value in destination image
- for (int to_x = 0 ; to_x < to_width ; to_x++) {
- double from_x = (to_x + 0.5) * from_stepx + from_diffx;
- RGBA line[4];
- for (int i = 0 ; i < 4 ; i++) {
- int k = (int)round(from_x) + i - 2;
- if (k < 0) k = 0;
- if (k >= from_width) k = from_width - 1;
- k *= 4;
- _check_index(from, from_line[0] + k, __LINE__);
- _check_index(from, from_line[1] + k, __LINE__);
- _check_index(from, from_line[2] + k, __LINE__);
- _check_index(from, from_line[3] + k, __LINE__);
- line[i].r = sample(NR_PIXBLOCK_PX(from)[from_line[0] + k],
- NR_PIXBLOCK_PX(from)[from_line[1] + k],
- NR_PIXBLOCK_PX(from)[from_line[2] + k],
- NR_PIXBLOCK_PX(from)[from_line[3] + k],
- from_y);
- line[i].g = sample(NR_PIXBLOCK_PX(from)[from_line[0] + k + 1],
- NR_PIXBLOCK_PX(from)[from_line[1] + k + 1],
- NR_PIXBLOCK_PX(from)[from_line[2] + k + 1],
- NR_PIXBLOCK_PX(from)[from_line[3] + k + 1],
- from_y);
- line[i].b = sample(NR_PIXBLOCK_PX(from)[from_line[0] + k + 2],
- NR_PIXBLOCK_PX(from)[from_line[1] + k + 2],
- NR_PIXBLOCK_PX(from)[from_line[2] + k + 2],
- NR_PIXBLOCK_PX(from)[from_line[3] + k + 2],
- from_y);
- line[i].a = sample(NR_PIXBLOCK_PX(from)[from_line[0] + k + 3],
- NR_PIXBLOCK_PX(from)[from_line[1] + k + 3],
- NR_PIXBLOCK_PX(from)[from_line[2] + k + 3],
- NR_PIXBLOCK_PX(from)[from_line[3] + k + 3],
- from_y);
- }
- RGBA result;
- result.r = round(sample(line[0].r, line[1].r, line[2].r, line[3].r,
- from_x));
- result.g = round(sample(line[0].g, line[1].g, line[2].g, line[3].g,
- from_x));
- result.b = round(sample(line[0].b, line[1].b, line[2].b, line[3].b,
- from_x));
- result.a = round(sample(line[0].a, line[1].a, line[2].a, line[3].a,
- from_x));
-
- _check_index(to, to_y * to->rs + to_x * 4, __LINE__);
-
- using Inkscape::Filters::clamp;
- using Inkscape::Filters::clamp_alpha;
- if (to->mode == NR_PIXBLOCK_MODE_R8G8B8A8P) {
- /* Clamp the colour channels to range from 0 to result.a to
- * make sure, we don't exceed 100% per colour channel with
- * images that have premultiplied alpha */
-
- int const alpha = clamp((int)result.a);
-
- NR_PIXBLOCK_PX(to)[to_y * to->rs + to_x * 4]
- = clamp_alpha((int)result.r, alpha);
- NR_PIXBLOCK_PX(to)[to_y * to->rs + to_x * 4 + 1]
- = clamp_alpha((int)result.g, alpha);
- NR_PIXBLOCK_PX(to)[to_y * to->rs + to_x * 4 + 2]
- = clamp_alpha((int)result.b, alpha);
- NR_PIXBLOCK_PX(to)[to_y * to->rs + to_x * 4 + 3] = alpha;
- } else {
- NR_PIXBLOCK_PX(to)[to_y * to->rs + to_x * 4]
- = clamp((int)result.r);
- NR_PIXBLOCK_PX(to)[to_y * to->rs + to_x * 4 + 1]
- = clamp((int)result.g);
- NR_PIXBLOCK_PX(to)[to_y * to->rs + to_x * 4 + 2]
- = clamp((int)result.b);
- NR_PIXBLOCK_PX(to)[to_y * to->rs + to_x * 4 + 3]
- = clamp((int)result.a);
- }
- }
- }
- if (free_from_on_exit) {
- nr_pixblock_release(from);
- delete from;
- }
-
-}
-
-void scale_bicubic_alpha(NRPixBlock *to, NRPixBlock *from,
- Geom::Affine const &trans)
-{
- if (NR_PIXBLOCK_BPP(from) != 1 || NR_PIXBLOCK_BPP(to) != 1) {
- g_warning("A non-8-bpp image passed to scale_bicubic_alpha: scaling aborted.");
- return;
- }
-
- // Precalculate sizes of source and destination pixblocks
- int from_width = from->area.x1 - from->area.x0;
- int from_height = from->area.y1 - from->area.y0;
- int to_width = to->area.x1 - to->area.x0;
- int to_height = to->area.y1 - to->area.y0;
-
- // from_step: when advancing one pixel in destination image,
- // how much we should advance in source image
- double from_stepx = 1.0 / trans[0];
- double from_stepy = 1.0 / trans[3];
- double from_diffx = from_stepx * (-trans[4]);
- double from_diffy = from_stepy * (-trans[5]);
- from_diffx = (to->area.x0 * from_stepx + from_diffx) - from->area.x0;
- from_diffy = (to->area.y0 * from_stepy + from_diffy) - from->area.y0;
-
- // Loop through every pixel of destination image, a line at a time
- for (int to_y = 0 ; to_y < to_height ; to_y++) {
- double from_y = (to_y + 0.5) * from_stepy - from_diffy;
- // Pre-calculate beginning of the four horizontal lines, from
- // which we should read
- int from_line[4];
- for (int i = 0 ; i < 4 ; i++) {
- int fy_line = (int)round(from_y) + i - 2;
- if (fy_line >= 0) {
- if (fy_line < from_height) {
- from_line[i] = fy_line * from->rs;
- } else {
- from_line[i] = (from_height - 1) * from->rs;
- }
- } else {
- from_line[i] = 0;
- }
- }
- // Loop through this horizontal line in destination image
- // For every pixel, calculate the color of pixel with
- // bicubic interpolation and set the pixel value in destination image
- for (int to_x = 0 ; to_x < to_width ; to_x++) {
- double from_x = (to_x + 0.5) * from_stepx - from_diffx;
- double line[4];
- for (int i = 0 ; i < 4 ; i++) {
- int k = (int)round(from_x) + i - 2;
- if (k < 0) k = 0;
- if (k >= from_width) k = from_width - 1;
- _check_index(from, from_line[0] + k, __LINE__);
- _check_index(from, from_line[1] + k, __LINE__);
- _check_index(from, from_line[2] + k, __LINE__);
- _check_index(from, from_line[3] + k, __LINE__);
- line[i] = sample(NR_PIXBLOCK_PX(from)[from_line[0] + k],
- NR_PIXBLOCK_PX(from)[from_line[1] + k],
- NR_PIXBLOCK_PX(from)[from_line[2] + k],
- NR_PIXBLOCK_PX(from)[from_line[3] + k],
- from_y);
- }
- int result;
- result = (int)round(sample(line[0], line[1], line[2], line[3],
- from_x));
-
- _check_index(to, to_y * to->rs + to_x, __LINE__);
-
- NR_PIXBLOCK_PX(to)[to_y * to->rs + to_x]
- = Inkscape::Filters::clamp(result);
- }
- }
-}
-
-void scale_bicubic(NRPixBlock *to, NRPixBlock *from, Geom::Affine const &trans)
-{
- if (NR_PIXBLOCK_BPP(to) == 4 && NR_PIXBLOCK_BPP(from) == 4) {
- scale_bicubic_rgba(to, from, trans);
- } else if (NR_PIXBLOCK_BPP(to) == 1 && NR_PIXBLOCK_BPP(from) == 1) {
- scale_bicubic_alpha(to, from, trans);
- } else {
- g_warning("NR::scale_bicubic: unsupported bitdepths for scaling: to %d, from %d", NR_PIXBLOCK_BPP(to), NR_PIXBLOCK_BPP(from));
- }
-}
-
-} /* namespace NR */
-/*
- 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/pixblock-scaler.h b/src/display/pixblock-scaler.h
deleted file mode 100644
index ff9613ab8..000000000
--- a/src/display/pixblock-scaler.h
+++ /dev/null
@@ -1,40 +0,0 @@
-#ifndef __NR_PIXBLOCK_SCALER_H__
-#define __NR_PIXBLOCK_SCALER_H__
-
-/*
- * Functions for blitting pixblocks using scaling
- *
- * Author:
- * Niko Kiirala <niko@kiirala.com>
- *
- * Copyright (C) 2006 Niko Kiirala
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#include "libnr/nr-pixblock.h"
-#include <2geom/forward.h>
-
-namespace NR {
-
-/** Blits the second pixblock to the first.
- * Image in source pixblock is scaled to the size of destination pixblock
- * using bicubic interpolation.
- * Source pixblock is not modified in process.
- * Only works for 32-bpp images.
- */
-void scale_bicubic(NRPixBlock *to, NRPixBlock *from, Geom::Affine const &trans);
-
-} /* namespace NR */
-
-#endif // __NR_PIXBLOCK_SCALER_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/pixblock-transform.cpp b/src/display/pixblock-transform.cpp
deleted file mode 100644
index 5d5b8a9cf..000000000
--- a/src/display/pixblock-transform.cpp
+++ /dev/null
@@ -1,279 +0,0 @@
-#define __NR_PIXBLOCK_SCALER_CPP__
-
-/*
- * Functions for blitting pixblocks using matrix transformation
- *
- * Author:
- * Niko Kiirala <niko@kiirala.com>
- *
- * Copyright (C) 2006,2009 Niko Kiirala
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#include <glib.h>
-#include <cmath>
-#if defined (SOLARIS) && (SOLARIS == 8)
-#include "round.h"
-using Inkscape::round;
-#endif
-using std::floor;
-
-#include "display/nr-filter-utils.h"
-
-#include "libnr/nr-blit.h"
-#include "libnr/nr-pixblock.h"
-#include <2geom/affine.h>
-
-namespace NR {
-
-struct RGBA {
- double r, g, b, a;
-};
-struct RGBAi {
- int r, g, b, a;
-};
-
-/**
- * Sanity check function for indexing pixblocks.
- * Catches reading and writing outside the pixblock area.
- * When enabled, decreases filter rendering speed massively.
- */
-inline void _check_index(NRPixBlock const * const pb, int const location, int const line)
-{
- if(false) {
- int max_loc = pb->rs * (pb->area.y1 - pb->area.y0);
- if (location < 0 || (location + 4) > max_loc)
- g_warning("Location %d out of bounds (0 ... %d) at line %d", location, max_loc, line);
- }
-}
-
-void transform_nearest(NRPixBlock *to, NRPixBlock *from, Geom::Affine const &trans)
-{
- if (NR_PIXBLOCK_BPP(from) != 4 || NR_PIXBLOCK_BPP(to) != 4) {
- g_warning("A non-32-bpp image passed to transform_nearest: scaling aborted.");
- return;
- }
-
- bool free_from_on_exit = false;
- if (from->mode != to->mode){
- NRPixBlock *o_from = from;
- from = new NRPixBlock;
- nr_pixblock_setup_fast(from, to->mode, o_from->area.x0, o_from->area.y0, o_from->area.x1, o_from->area.y1, false);
- nr_blit_pixblock_pixblock(from, o_from);
- free_from_on_exit = true;
- }
-
- // Precalculate sizes of source and destination pixblocks
- int from_width = from->area.x1 - from->area.x0;
- int from_height = from->area.y1 - from->area.y0;
- int to_width = to->area.x1 - to->area.x0;
- int to_height = to->area.y1 - to->area.y0;
-
- Geom::Affine itrans = trans.inverse();
-
- // Loop through every pixel of destination image, a line at a time
- for (int to_y = 0 ; to_y < to_height ; to_y++) {
- for (int to_x = 0 ; to_x < to_width ; to_x++) {
- RGBAi result = {0,0,0,0};
-
- int from_x = (int)floor(itrans[0] * (to_x + 0.5 + to->area.x0)
- + itrans[2] * (to_y + 0.5 + to->area.y0)
- + itrans[4]);
- from_x -= from->area.x0;
- int from_y = (int)floor(itrans[1] * (to_x + 0.5 + to->area.x0)
- + itrans[3] * (to_y + 0.5 + to->area.y0)
- + itrans[5]);
- from_y -= from->area.y0;
-
- if (from_x >= 0 && from_x < from_width
- && from_y >= 0 && from_y < from_height) {
- _check_index(from, from_y * from->rs + from_x * 4, __LINE__);
- result.r = NR_PIXBLOCK_PX(from)[from_y * from->rs + from_x * 4];
- result.g = NR_PIXBLOCK_PX(from)[from_y * from->rs + from_x * 4 + 1];
- result.b = NR_PIXBLOCK_PX(from)[from_y * from->rs + from_x * 4 + 2];
- result.a = NR_PIXBLOCK_PX(from)[from_y * from->rs + from_x * 4 + 3];
- }
-
- _check_index(to, to_y * to->rs + to_x * 4, __LINE__);
- NR_PIXBLOCK_PX(to)[to_y * to->rs + to_x * 4] = result.r;
- NR_PIXBLOCK_PX(to)[to_y * to->rs + to_x * 4 + 1] = result.g;
- NR_PIXBLOCK_PX(to)[to_y * to->rs + to_x * 4 + 2] = result.b;
- NR_PIXBLOCK_PX(to)[to_y * to->rs + to_x * 4 + 3] = result.a;
- }
- }
- if (free_from_on_exit) {
- nr_pixblock_release(from);
- delete from;
- }
-}
-
-/** Calculates cubically interpolated value of the four given pixel values.
- * The pixel values should be from four adjacent pixels in source image or
- * four adjacent interpolated values. len should be the x- or y-coordinate
- * (depending on interpolation direction) of the center of the target pixel
- * in source image coordinates.
- */
-__attribute__ ((const))
-inline static double sample(double const a, double const b,
- double const c, double const d,
- double const len)
-{
- double lena = 1.5 + (len - round(len));
- double lenb = 0.5 + (len - round(len));
- double lenc = 0.5 - (len - round(len));
- double lend = 1.5 - (len - round(len));
- double const f = -0.5; // corresponds to cubic Hermite spline
- double sum = 0;
- sum += ((((f * lena) - 5.0 * f) * lena + 8.0 * f) * lena - 4 * f) * a;
- sum += (((f + 2.0) * lenb - (f + 3.0)) * lenb * lenb + 1.0) * b;
- sum += (((f + 2.0) * lenc - (f + 3.0)) * lenc * lenc + 1.0) * c;
- sum += ((((f * lend) - 5.0 * f) * lend + 8.0 * f) * lend - 4 * f) * d;
-
- return sum;
-}
-
-void transform_bicubic(NRPixBlock *to, NRPixBlock *from, Geom::Affine const &trans)
-{
- if (NR_PIXBLOCK_BPP(from) != 4 || NR_PIXBLOCK_BPP(to) != 4) {
- g_warning("A non-32-bpp image passed to transform_bicubic: scaling aborted.");
- return;
- }
-
- bool free_from_on_exit = false;
- if (from->mode != to->mode){
- NRPixBlock *o_from = from;
- from = new NRPixBlock;
- nr_pixblock_setup_fast(from, to->mode, o_from->area.x0, o_from->area.y0, o_from->area.x1, o_from->area.y1, false);
- nr_blit_pixblock_pixblock(from, o_from);
- free_from_on_exit = true;
- }
-
- if (from->mode != NR_PIXBLOCK_MODE_R8G8B8A8P) {
- // TODO: Fix this... (The problem is that for interpolation non-premultiplied colors should be premultiplied...)
- g_warning("transform_bicubic does not properly support non-premultiplied images");
- }
-
- // Precalculate sizes of source and destination pixblocks
- int from_width = from->area.x1 - from->area.x0;
- int from_height = from->area.y1 - from->area.y0;
- int to_width = to->area.x1 - to->area.x0;
- int to_height = to->area.y1 - to->area.y0;
-
- Geom::Affine itrans = trans.inverse();
-
- // Loop through every pixel of destination image, a line at a time
- for (int to_y = 0 ; to_y < to_height ; to_y++) {
- for (int to_x = 0 ; to_x < to_width ; to_x++) {
- double from_x = itrans[0] * (to_x + 0.5 + to->area.x0)
- + itrans[2] * (to_y + 0.5 + to->area.y0)
- + itrans[4] - from->area.x0;
- double from_y = itrans[1] * (to_x + 0.5 + to->area.x0)
- + itrans[3] * (to_y + 0.5 + to->area.y0)
- + itrans[5] - from->area.y0;
-
- if (from_x < 0 || from_x >= from_width ||
- from_y < 0 || from_y >= from_height) {
- continue;
- }
-
- RGBA line[4];
-
- int from_line[4];
- for (int i = 0 ; i < 4 ; i++) {
- int fy_line = (int)round(from_y) + i - 2;
- if (fy_line >= 0) {
- if (fy_line < from_height) {
- from_line[i] = fy_line * from->rs;
- } else {
- from_line[i] = (from_height - 1) * from->rs;
- }
- } else {
- from_line[i] = 0;
- }
- }
-
- for (int i = 0 ; i < 4 ; i++) {
- int k = (int)round(from_x) + i - 2;
- if (k < 0) k = 0;
- if (k >= from_width) k = from_width - 1;
- k *= 4;
- _check_index(from, from_line[0] + k, __LINE__);
- _check_index(from, from_line[1] + k, __LINE__);
- _check_index(from, from_line[2] + k, __LINE__);
- _check_index(from, from_line[3] + k, __LINE__);
- line[i].r = sample(NR_PIXBLOCK_PX(from)[from_line[0] + k],
- NR_PIXBLOCK_PX(from)[from_line[1] + k],
- NR_PIXBLOCK_PX(from)[from_line[2] + k],
- NR_PIXBLOCK_PX(from)[from_line[3] + k],
- from_y);
- line[i].g = sample(NR_PIXBLOCK_PX(from)[from_line[0] + k + 1],
- NR_PIXBLOCK_PX(from)[from_line[1] + k + 1],
- NR_PIXBLOCK_PX(from)[from_line[2] + k + 1],
- NR_PIXBLOCK_PX(from)[from_line[3] + k + 1],
- from_y);
- line[i].b = sample(NR_PIXBLOCK_PX(from)[from_line[0] + k + 2],
- NR_PIXBLOCK_PX(from)[from_line[1] + k + 2],
- NR_PIXBLOCK_PX(from)[from_line[2] + k + 2],
- NR_PIXBLOCK_PX(from)[from_line[3] + k + 2],
- from_y);
- line[i].a = sample(NR_PIXBLOCK_PX(from)[from_line[0] + k + 3],
- NR_PIXBLOCK_PX(from)[from_line[1] + k + 3],
- NR_PIXBLOCK_PX(from)[from_line[2] + k + 3],
- NR_PIXBLOCK_PX(from)[from_line[3] + k + 3],
- from_y);
- }
- RGBA result;
- result.r = round(sample(line[0].r, line[1].r, line[2].r, line[3].r,
- from_x));
- result.g = round(sample(line[0].g, line[1].g, line[2].g, line[3].g,
- from_x));
- result.b = round(sample(line[0].b, line[1].b, line[2].b, line[3].b,
- from_x));
- result.a = round(sample(line[0].a, line[1].a, line[2].a, line[3].a,
- from_x));
-
- using Inkscape::Filters::clamp;
- using Inkscape::Filters::clamp_alpha;
- _check_index(to, to_y * to->rs + to_x * 4, __LINE__);
- if (to->mode == NR_PIXBLOCK_MODE_R8G8B8A8P) {
- /* Make sure, none of the RGB channels exceeds 100% intensity
- * in premultiplied output */
- int const alpha = clamp((int)result.a);
- NR_PIXBLOCK_PX(to)[to_y * to->rs + to_x * 4] =
- clamp_alpha((int)result.r, alpha);
- NR_PIXBLOCK_PX(to)[to_y * to->rs + to_x * 4 + 1] =
- clamp_alpha((int)result.g, alpha);
- NR_PIXBLOCK_PX(to)[to_y * to->rs + to_x * 4 + 2] =
- clamp_alpha((int)result.b, alpha);
- NR_PIXBLOCK_PX(to)[to_y * to->rs + to_x * 4 + 3] = alpha;
- } else {
- /* Clamp the output to unsigned char range */
- NR_PIXBLOCK_PX(to)[to_y * to->rs + to_x * 4]
- = clamp((int)result.r);
- NR_PIXBLOCK_PX(to)[to_y * to->rs + to_x * 4 + 1]
- = clamp((int)result.g);
- NR_PIXBLOCK_PX(to)[to_y * to->rs + to_x * 4 + 2]
- = clamp((int)result.b);
- NR_PIXBLOCK_PX(to)[to_y * to->rs + to_x * 4 + 3]
- = clamp((int)result.a);
- }
- }
- }
- if (free_from_on_exit) {
- nr_pixblock_release(from);
- delete from;
- }
-}
-
-} /* namespace NR */
-/*
- 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/pixblock-transform.h b/src/display/pixblock-transform.h
deleted file mode 100644
index b73435fdf..000000000
--- a/src/display/pixblock-transform.h
+++ /dev/null
@@ -1,35 +0,0 @@
-#ifndef __NR_PIXBLOCK_TRANSFORM_H__
-#define __NR_PIXBLOCK_TRANSFORM_H__
-
-/*
- * Functions for blitting pixblocks using matrix transfomation
- *
- * Author:
- * Niko Kiirala <niko@kiirala.com>
- *
- * Copyright (C) 2006 Niko Kiirala
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#include "libnr/nr-pixblock.h"
-#include <2geom/forward.h>
-
-namespace NR {
-
-void transform_nearest(NRPixBlock *to, NRPixBlock *from, Geom::Affine const &trans);
-void transform_bicubic(NRPixBlock *to, NRPixBlock *from, Geom::Affine const &trans);
-
-} /* namespace NR */
-
-#endif // __NR_PIXBLOCK_TRANSFORM_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/sodipodi-ctrl.cpp b/src/display/sodipodi-ctrl.cpp
index 202fc206e..5e939ffee 100644
--- a/src/display/sodipodi-ctrl.cpp
+++ b/src/display/sodipodi-ctrl.cpp
@@ -11,7 +11,7 @@
#include <2geom/transforms.h>
#include "sp-canvas-util.h"
#include "sodipodi-ctrl.h"
-#include "libnr/nr-pixops.h"
+#include "display/cairo-utils.h"
enum {
ARG_0,
@@ -125,7 +125,7 @@ sp_ctrl_destroy (GtkObject *object)
ctrl = SP_CTRL (object);
if (ctrl->cache) {
- g_free(ctrl->cache);
+ delete[] ctrl->cache;
ctrl->cache = NULL;
}
@@ -175,11 +175,12 @@ sp_ctrl_set_arg (GtkObject *object, GtkArg *arg, guint arg_id)
sp_canvas_item_request_update (item);
break;
- case ARG_FILL_COLOR:
- ctrl->fill_color = GTK_VALUE_INT (*arg);
+ case ARG_FILL_COLOR: {
+ guint32 fill = GTK_VALUE_INT (*arg);
+ ctrl->fill_color = fill;
ctrl->build = FALSE;
sp_canvas_item_request_update (item);
- break;
+ } break;
case ARG_STROKED:
ctrl->stroked = GTK_VALUE_BOOL (*arg);
@@ -187,11 +188,12 @@ sp_ctrl_set_arg (GtkObject *object, GtkArg *arg, guint arg_id)
sp_canvas_item_request_update (item);
break;
- case ARG_STROKE_COLOR:
- ctrl->stroke_color = GTK_VALUE_INT (*arg);
+ case ARG_STROKE_COLOR: {
+ guint32 stroke = GTK_VALUE_INT (*arg);
+ ctrl->stroke_color = stroke;
ctrl->build = FALSE;
sp_canvas_item_request_update (item);
- break;
+ } break;
case ARG_PIXBUF:
pixbuf = (GdkPixbuf*)(GTK_VALUE_POINTER (*arg));
@@ -297,52 +299,56 @@ sp_ctrl_point (SPCanvasItem *item, Geom::Point p, SPCanvasItem **actual_item)
static void
sp_ctrl_build_cache (SPCtrl *ctrl)
{
- guchar * p, *q;
+ guint32 *p, *q;
gint size, x, y, z, s, a, side, c;
- guint8 fr, fg, fb, fa, sr, sg, sb, sa;
+ guint32 stroke_color, fill_color;
if (ctrl->filled) {
- fr = (ctrl->fill_color >> 24) & 0xff;
- fg = (ctrl->fill_color >> 16) & 0xff;
- fb = (ctrl->fill_color >> 8) & 0xff;
- fa = (ctrl->fill_color) & 0xff;
+ if (ctrl->mode == SP_CTRL_MODE_XOR) {
+ fill_color = ctrl->fill_color;
+ } else {
+ fill_color = argb32_from_rgba(ctrl->fill_color);
+ }
} else {
- fr = 0x00; fg = 0x00; fb = 0x00; fa = 0x00;
+ fill_color = 0;
}
if (ctrl->stroked) {
- sr = (ctrl->stroke_color >> 24) & 0xff;
- sg = (ctrl->stroke_color >> 16) & 0xff;
- sb = (ctrl->stroke_color >> 8) & 0xff;
- sa = (ctrl->stroke_color) & 0xff;
+ if (ctrl->mode == SP_CTRL_MODE_XOR) {
+ stroke_color = ctrl->stroke_color;
+ } else {
+ stroke_color = argb32_from_rgba(ctrl->stroke_color);
+ }
} else {
- sr = fr; sg = fg; sb = fb; sa = fa;
+ stroke_color = fill_color;
}
side = (ctrl->span * 2 +1);
- c = ctrl->span ;
- size = (side) * (side) * 4;
+ c = ctrl->span;
+ size = side * side;
if (side < 2) return;
- if (ctrl->cache)
- g_free (ctrl->cache);
- ctrl->cache = (guchar*)g_malloc (size);
+ if (ctrl->cache) delete[] ctrl->cache;
+ ctrl->cache = new guint32[size];
switch (ctrl->shape) {
case SP_CTRL_SHAPE_SQUARE:
p = ctrl->cache;
+ // top edge
for (x=0; x < side; x++) {
- *p++ = sr; *p++ = sg; *p++ = sb; *p++ = sa;
+ *p++ = stroke_color;
}
+ // middle
for (y = 2; y < side; y++) {
- *p++ = sr; *p++ = sg; *p++ = sb; *p++ = sa;
+ *p++ = stroke_color; // stroke at first and last pixel
for (x=2; x < side; x++) {
- *p++ = fr; *p++ = fg; *p++ = fb; *p++ = fa;
+ *p++ = fill_color; // fill in the middle
}
- *p++ = sr; *p++ = sg; *p++ = sb; *p++ = sa;
+ *p++ = stroke_color;
}
+ // bottom edge
for (x=0; x < side; x++) {
- *p++ = sr; *p++ = sg; *p++ = sb; *p++ = sa;
+ *p++ = stroke_color;
}
ctrl->build = TRUE;
break;
@@ -352,19 +358,20 @@ sp_ctrl_build_cache (SPCtrl *ctrl)
for (y = 0; y < side; y++) {
z = abs (c - y);
for (x = 0; x < z; x++) {
- *p++ = 0x00; *p++ = 0x00; *p++ = 0x00; *p++ = 0x00;
+ *p++ = 0;
}
- *p++ = sr; *p++ = sg; *p++ = sb; *p++ = sa; x++;
+ *p++ = stroke_color; x++;
for (; x < side - z -1; x++) {
- *p++ = fr; *p++ = fg; *p++ = fb; *p++ = fa;
+ *p++ = fill_color;
}
if (z != c) {
- *p++ = sr; *p++ = sg; *p++ = sb; *p++ = sa; x++;
+ *p++ = stroke_color; x++;
}
for (; x < side; x++) {
- *p++ = 0x00; *p++ = 0x00; *p++ = 0x00; *p++ = 0x00;
+ *p++ = 0;
}
}
+ ctrl->build = TRUE;
break;
case SP_CTRL_SHAPE_CIRCLE:
@@ -376,28 +383,28 @@ sp_ctrl_build_cache (SPCtrl *ctrl)
z = (gint)(0.0 + sqrt ((c+.4)*(c+.4) - a*a));
x = 0;
while (x < c-z) {
- *p++ = 0x00; *p++ = 0x00; *p++ = 0x00; *p++ = 0x00;
- *q-- = 0x00; *q-- = 0x00; *q-- = 0x00; *q-- = 0x00;
+ *p++ = 0;
+ *q-- = 0;
x++;
}
do {
- *p++ = sr; *p++ = sg; *p++ = sb; *p++ = sa;
- *q-- = sa; *q-- = sb; *q-- = sg; *q-- = sr;
+ *p++ = stroke_color;
+ *q-- = stroke_color;
x++;
} while (x < c-s);
while (x < MIN(c+s+1, c+z)) {
- *p++ = fr; *p++ = fg; *p++ = fb; *p++ = fa;
- *q-- = fa; *q-- = fb; *q-- = fg; *q-- = fr;
+ *p++ = fill_color;
+ *q-- = fill_color;
x++;
}
do {
- *p++ = sr; *p++ = sg; *p++ = sb; *p++ = sa;
- *q-- = sa; *q-- = sb; *q-- = sg; *q-- = sr;
+ *p++ = stroke_color;
+ *q-- = stroke_color;
x++;
} while (x <= c+z);
while (x < side) {
- *p++ = 0x00; *p++ = 0x00; *p++ = 0x00; *p++ = 0x00;
- *q-- = 0x00; *q-- = 0x00; *q-- = 0x00; *q-- = 0x00;
+ *p++ = 0;
+ *q-- = 0;
x++;
}
s = z;
@@ -410,17 +417,17 @@ sp_ctrl_build_cache (SPCtrl *ctrl)
for (y = 0; y < side; y++) {
z = abs (c - y);
for (x = 0; x < c-z; x++) {
- *p++ = 0x00; *p++ = 0x00; *p++ = 0x00; *p++ = 0x00;
+ *p++ = 0;
}
- *p++ = sr; *p++ = sg; *p++ = sb; *p++ = sa; x++;
+ *p++ = stroke_color; x++;
for (; x < c + z; x++) {
- *p++ = 0x00; *p++ = 0x00; *p++ = 0x00; *p++ = 0x00;
+ *p++ = 0;
}
if (z != 0) {
- *p++ = sr; *p++ = sg; *p++ = sb; *p++ = sa; x++;
+ *p++ = stroke_color; x++;
}
for (; x < side; x++) {
- *p++ = 0x00; *p++ = 0x00; *p++ = 0x00; *p++ = 0x00;
+ *p++ = 0;
}
}
ctrl->build = TRUE;
@@ -433,28 +440,19 @@ sp_ctrl_build_cache (SPCtrl *ctrl)
px = gdk_pixbuf_get_pixels (ctrl->pixbuf);
rs = gdk_pixbuf_get_rowstride (ctrl->pixbuf);
for (y = 0; y < side; y++){
- unsigned char *s, *d;
+ guint32 *d;
+ unsigned char *s;
s = px + y * rs;
- d = ctrl->cache + 4 * side * y;
+ d = ctrl->cache + side * y;
for (x = 0; x < side; x++) {
if (s[3] < 0x80) {
- d[0] = 0x00;
- d[1] = 0x00;
- d[2] = 0x00;
- d[3] = 0x00;
+ *d++ = 0;
} else if (s[0] < 0x80) {
- d[0] = sr;
- d[1] = sg;
- d[2] = sb;
- d[3] = sa;
+ *d++ = stroke_color;
} else {
- d[0] = fr;
- d[1] = fg;
- d[2] = fb;
- d[3] = fa;
+ *d++ = fill_color;
}
s += 4;
- d += 4;
}
}
} else {
@@ -466,16 +464,13 @@ sp_ctrl_build_cache (SPCtrl *ctrl)
case SP_CTRL_SHAPE_IMAGE:
if (ctrl->pixbuf) {
guint r = gdk_pixbuf_get_rowstride (ctrl->pixbuf);
- guchar * pix;
- q = gdk_pixbuf_get_pixels (ctrl->pixbuf);
+ guint32 *px;
+ guchar *data = gdk_pixbuf_get_pixels (ctrl->pixbuf);
p = ctrl->cache;
for (y = 0; y < side; y++){
- pix = q + (y * r);
+ px = reinterpret_cast<guint32*>(data + y * r);
for (x = 0; x < side; x++) {
- *p++ = *pix++;
- *p++ = *pix++;
- *p++ = *pix++;
- *p++ = *pix++;
+ *p++ = *px++;
}
}
} else {
@@ -487,65 +482,84 @@ sp_ctrl_build_cache (SPCtrl *ctrl)
default:
break;
}
-
}
-// composite background, foreground, alpha for xor mode
-#define COMPOSE_X(b,f,a) ( FAST_DIVIDE<255>( ((guchar) b) * ((guchar) (0xff - a)) + ((guchar) ((b ^ ~f) + b/4 - (b>127? 63 : 0))) * ((guchar) a) ) )
-// composite background, foreground, alpha for color mode
-#define COMPOSE_N(b,f,a) ( FAST_DIVIDE<255>( ((guchar) b) * ((guchar) (0xff - a)) + ((guchar) f) * ((guchar) a) ) )
+static inline guint32 compose_xor(guint32 bg, guint32 fg, guint32 a)
+{
+ guint32 c = bg * (255-a) + (((bg ^ ~fg) + (bg >> 2) - (bg > 127 ? 63 : 0)) & 255) * a;
+ return (c + 127) / 255;
+}
static void
sp_ctrl_render (SPCanvasItem *item, SPCanvasBuf *buf)
{
- gint y0, y1, y, x0,x1,x;
- guchar *p, *q, a;
+ //gint y0, y1, y, x0,x1,x;
+ //guchar *p, *q, a;
SPCtrl *ctrl = SP_CTRL (item);
if (!ctrl->defined) return;
if ((!ctrl->filled) && (!ctrl->stroked)) return;
- sp_canvas_prepare_buffer (buf);
-
// the control-image is rendered into ctrl->cache
if (!ctrl->build) {
sp_ctrl_build_cache (ctrl);
}
- // then we render from ctrl->cache
- y0 = MAX (ctrl->box.y0, buf->rect.y0);
- y1 = MIN (ctrl->box.y1, buf->rect.y1 - 1);
- x0 = MAX (ctrl->box.x0, buf->rect.x0);
- x1 = MIN (ctrl->box.x1, buf->rect.x1 - 1);
-
- bool colormode;
-
- for (y = y0; y <= y1; y++) {
- p = buf->buf + (y - buf->rect.y0) * buf->buf_rowstride + (x0 - buf->rect.x0) * 4;
- q = ctrl->cache + ((y - ctrl->box.y0) * (ctrl->span*2+1) + (x0 - ctrl->box.x0)) * 4;
- for (x = x0; x <= x1; x++) {
- a = *(q + 3);
- // 00000000 is the only way to get invisible; all other colors with alpha 00 are treated as mode_color with alpha ff
- colormode = false;
- if (a == 0x00 && !(q[0] == 0x00 && q[1] == 0x00 && q[2] == 0x00)) {
- a = 0xff;
- colormode = true;
- }
- if (ctrl->mode == SP_CTRL_MODE_COLOR || colormode) {
- p[0] = COMPOSE_N (p[0], q[0], a);
- p[1] = COMPOSE_N (p[1], q[1], a);
- p[2] = COMPOSE_N (p[2], q[2], a);
- q += 4;
- p += 4;
- } else if (ctrl->mode == SP_CTRL_MODE_XOR) {
- p[0] = COMPOSE_X (p[0], q[0], a);
- p[1] = COMPOSE_X (p[1], q[1], a);
- p[2] = COMPOSE_X (p[2], q[2], a);
- q += 4;
- p += 4;
+ int w, h;
+ w = h = (ctrl->span * 2 +1);
+
+ // The code below works even when the target is not an image surface
+ if (ctrl->mode == SP_CTRL_MODE_XOR) {
+ // 1. Copy the affected part of output to a temporary surface
+ cairo_surface_t *work = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, w, h);
+ cairo_t *cr = cairo_create(work);
+ cairo_translate(cr, -ctrl->box.x0, -ctrl->box.y0);
+ cairo_set_source_surface(cr, cairo_get_target(buf->ct), buf->rect.x0, buf->rect.y0);
+ cairo_paint(cr);
+ cairo_destroy(cr);
+
+ // 2. Composite the control on a temporary surface
+ cairo_surface_flush(work);
+ int strideb = cairo_image_surface_get_stride(work);
+ unsigned char *pxb = cairo_image_surface_get_data(work);
+ guint32 *p = ctrl->cache;
+ for (int i=0; i<h; ++i) {
+ guint32 *pb = reinterpret_cast<guint32*>(pxb + i*strideb);
+ for (int j=0; j<w; ++j) {
+ guint32 cc = *p++;
+ guint32 ac = cc & 0xff;
+ if (ac == 0 && cc != 0) {
+ *pb++ = argb32_from_rgba(cc | 0x000000ff);
+ } else {
+ EXTRACT_ARGB32(*pb, ab,rb,gb,bb)
+ guint32 ro = compose_xor(rb, (cc & 0xff000000) >> 24, ac);
+ guint32 go = compose_xor(gb, (cc & 0x00ff0000) >> 16, ac);
+ guint32 bo = compose_xor(bb, (cc & 0x0000ff00) >> 8, ac);
+ ASSEMBLE_ARGB32(px, ab,ro,go,bo)
+ *pb++ = px;
+ }
}
}
+ cairo_surface_mark_dirty(work);
+
+ // 3. Replace the affected part of output with contents of temporary surface
+ cairo_save(buf->ct);
+ cairo_set_source_surface(buf->ct, work,
+ ctrl->box.x0 - buf->rect.x0, ctrl->box.y0 - buf->rect.y0);
+ cairo_rectangle(buf->ct, ctrl->box.x0 - buf->rect.x0, ctrl->box.y0 - buf->rect.y0, w, h);
+ cairo_clip(buf->ct);
+ cairo_set_operator(buf->ct, CAIRO_OPERATOR_SOURCE);
+ cairo_paint(buf->ct);
+ cairo_restore(buf->ct);
+ cairo_surface_destroy(work);
+ } else {
+ cairo_surface_t *cache = cairo_image_surface_create_for_data(
+ reinterpret_cast<unsigned char*>(ctrl->cache), CAIRO_FORMAT_ARGB32, w, h, w*4);
+ cairo_set_source_surface(buf->ct, cache,
+ ctrl->box.x0 - buf->rect.x0, ctrl->box.y0 - buf->rect.y0);
+ cairo_paint(buf->ct);
+ cairo_surface_destroy(cache);
}
ctrl->shown = TRUE;
}
diff --git a/src/display/sodipodi-ctrl.h b/src/display/sodipodi-ctrl.h
index 71061b450..3bf0889c7 100644
--- a/src/display/sodipodi-ctrl.h
+++ b/src/display/sodipodi-ctrl.h
@@ -49,7 +49,7 @@ struct SPCtrl : public SPCanvasItem {
bool _moved;
NRRectL box; /* NB! x1 & y1 are included */
- guchar *cache;
+ guint32 *cache;
GdkPixbuf * pixbuf;
void moveto(Geom::Point const p);
diff --git a/src/display/sodipodi-ctrlrect.cpp b/src/display/sodipodi-ctrlrect.cpp
index 380039798..592d45bc0 100644
--- a/src/display/sodipodi-ctrlrect.cpp
+++ b/src/display/sodipodi-ctrlrect.cpp
@@ -17,7 +17,7 @@
#include "sp-canvas-util.h"
#include "sodipodi-ctrlrect.h"
-#include "libnr/nr-pixops.h"
+#include "display/cairo-utils.h"
/*
* Currently we do not have point method, as it should always be painted
@@ -83,7 +83,7 @@ static void sp_ctrlrect_destroy(GtkObject *object)
(* GTK_OBJECT_CLASS(parent_class)->destroy)(object);
}
}
-
+#if 0
/* FIXME: use definitions from somewhere else */
#define RGBA_R(v) ((v) >> 24)
#define RGBA_G(v) (((v) >> 16) & 0xff)
@@ -153,6 +153,7 @@ static void sp_ctrlrect_area(SPCanvasBuf *buf, gint xs, gint ys, gint xe, gint y
}
}
}
+#endif
static void sp_ctrlrect_render(SPCanvasItem *item, SPCanvasBuf *buf)
{
@@ -188,13 +189,38 @@ void CtrlRect::init()
void CtrlRect::render(SPCanvasBuf *buf)
{
+ static double const dashes[2] = {4.0, 4.0};
+
if ((_area.x0 != 0 || _area.x1 != 0 || _area.y0 != 0 || _area.y1 != 0) &&
(_area.x0 < buf->rect.x1) &&
(_area.y0 < buf->rect.y1) &&
((_area.x1 + _shadow_size) >= buf->rect.x0) &&
- ((_area.y1 + _shadow_size) >= buf->rect.y0)) {
- sp_canvas_prepare_buffer(buf);
+ ((_area.y1 + _shadow_size) >= buf->rect.y0))
+ {
+ cairo_save(buf->ct);
+ cairo_translate(buf->ct, -buf->rect.x0, -buf->rect.y0);
+ cairo_set_line_width(buf->ct, 1);
+ if (_dashed) cairo_set_dash(buf->ct, dashes, 2, 0);
+ cairo_rectangle(buf->ct, 0.5 + _area.x0, 0.5 + _area.y0,
+ _area.x1 - _area.x0, _area.y1 - _area.y0);
+ if (_has_fill) {
+ ink_cairo_set_source_rgba32(buf->ct, _fill_color);
+ cairo_fill_preserve(buf->ct);
+ }
+ ink_cairo_set_source_rgba32(buf->ct, _border_color);
+ cairo_stroke(buf->ct);
+
+ if (_shadow_size > 0) {
+ ink_cairo_set_source_rgba32(buf->ct, _shadow_color);
+ cairo_rectangle(buf->ct, 1 + _area.x1, _area.y0 + _shadow_size,
+ _shadow_size, _area.y1 - _area.y0 + 1); // right shadow
+ cairo_rectangle(buf->ct, _area.x0 + _shadow_size, 1 + _area.y1,
+ _area.x1 - _area.x0 - _shadow_size + 1, _shadow_size);
+ cairo_fill(buf->ct);
+ }
+ cairo_restore(buf->ct);
+#if 0
/* Top */
sp_ctrlrect_hline(buf, _area.y0, _area.x0, _area.x1, _border_color, _dashed);
/* Bottom */
@@ -216,6 +242,7 @@ void CtrlRect::render(SPCanvasBuf *buf)
sp_ctrlrect_area(buf, _area.x0 + 1, _area.y0 + 1,
_area.x1 - 1, _area.y1 - 1, _fill_color);
}
+#endif
}
}
diff --git a/src/display/sp-canvas-util.cpp b/src/display/sp-canvas-util.cpp
index 7eac32e2d..186609e49 100644
--- a/src/display/sp-canvas-util.cpp
+++ b/src/display/sp-canvas-util.cpp
@@ -13,12 +13,10 @@
*/
-#include <string.h> // for memset
#include <2geom/affine.h>
-#include "libnr/nr-pixops.h"
-#include "sp-canvas-item.h"
#include "sp-canvas-util.h"
-
+#include "sp-canvas-item.h"
+#include "sp-canvas.h"
void
sp_canvas_update_bbox (SPCanvasItem *item, int x1, int y1, int x2, int y2)
@@ -43,38 +41,13 @@ sp_canvas_item_reset_bounds (SPCanvasItem *item)
void
sp_canvas_prepare_buffer (SPCanvasBuf *buf)
{
- if (buf->is_empty) {
- sp_canvas_clear_buffer(buf);
- buf->is_empty = false;
- }
-}
-
-void
-sp_canvas_clear_buffer (SPCanvasBuf *buf)
-{
- unsigned char r, g, b;
-
- r = (buf->bg_color >> 16) & 0xff;
- g = (buf->bg_color >> 8) & 0xff;
- b = buf->bg_color & 0xff;
-
- if ((r != g) || (r != b)) {
- int x, y;
- for (y = buf->rect.y0; y < buf->rect.y1; y++) {
- unsigned char *p;
- p = buf->buf + (y - buf->rect.y0) * buf->buf_rowstride;
- for (x = buf->rect.x0; x < buf->rect.x1; x++) {
- *p++ = r;
- *p++ = g;
- *p++ = b;
- }
- }
- } else {
+ /*if (buf->is_empty) {
int y;
for (y = buf->rect.y0; y < buf->rect.y1; y++) {
- memset (buf->buf + (y - buf->rect.y0) * buf->buf_rowstride, r, 4 * (buf->rect.x1 - buf->rect.x0));
+ memset (buf->buf + (y - buf->rect.y0) * buf->buf_rowstride, 0, 4 * (buf->rect.x1 - buf->rect.x0));
}
- }
+ buf->is_empty = false;
+ }*/
}
Geom::Affine sp_canvas_item_i2p_affine (SPCanvasItem * item)
diff --git a/src/display/sp-canvas-util.h b/src/display/sp-canvas-util.h
index f0aa15cb9..41e085a5c 100644
--- a/src/display/sp-canvas-util.h
+++ b/src/display/sp-canvas-util.h
@@ -21,11 +21,6 @@ void sp_canvas_update_bbox (SPCanvasItem *item, int x1, int y1, int x2, int y2);
void sp_canvas_item_reset_bounds (SPCanvasItem *item);
void sp_canvas_prepare_buffer (SPCanvasBuf *buf);
-/* fill buffer with background color */
-
-void
-sp_canvas_clear_buffer (SPCanvasBuf * buf);
-
/* get i2p (item to parent) affine transformation as general 6-element array */
Geom::Affine sp_canvas_item_i2p_affine (SPCanvasItem * item);
diff --git a/src/display/sp-canvas.cpp b/src/display/sp-canvas.cpp
index e2220282d..c84452c07 100644
--- a/src/display/sp-canvas.cpp
+++ b/src/display/sp-canvas.cpp
@@ -15,21 +15,18 @@
*/
#ifdef HAVE_CONFIG_H
-# include "config.h"
+# include <config.h>
#endif
-#include <libnr/nr-pixblock.h>
-
#include <gtk/gtk.h>
-
#include <gtkmm.h>
#include "helper/sp-marshal.h"
#include <helper/recthull.h>
+#include "display-forward.h"
+#include <2geom/affine.h>
#include "display/sp-canvas.h"
#include "display/sp-canvas-group.h"
-#include <2geom/affine.h>
-#include "libnr/nr-convex-hull.h"
#include "preferences.h"
#include "inkscape.h"
#include "sodipodi-ctrlrect.h"
@@ -37,8 +34,7 @@
#include "color-profile-fns.h"
#endif // ENABLE_LCMS
#include "display/rendermode.h"
-#include "libnr/nr-blit.h"
-#include "display/inkscape-cairo.h"
+#include "display/cairo-utils.h"
#include "debug/gdk-event-latency-tracker.h"
#include "desktop.h"
#include "sp-namedview.h"
@@ -315,7 +311,7 @@ sp_canvas_item_invoke_point (SPCanvasItem *item, Geom::Point p, SPCanvasItem **a
if (SP_CANVAS_ITEM_GET_CLASS (item)->point)
return SP_CANVAS_ITEM_GET_CLASS (item)->point (item, p, actual_item);
- return NR_HUGE;
+ return Geom::infinity();
}
/**
@@ -1629,17 +1625,12 @@ sp_canvas_paint_single_buffer (SPCanvas *canvas, int x0, int y0, int x1, int y1,
{
GtkWidget *widget = GTK_WIDGET (canvas);
- SPCanvasBuf buf;
- if (canvas->rendermode != Inkscape::RENDERMODE_OUTLINE) {
- buf.buf = nr_pixelstore_256K_new (FALSE, 0);
- } else {
- buf.buf = nr_pixelstore_1M_new (FALSE, 0);
- }
-
// Mark the region clean
sp_canvas_mark_rect(canvas, x0, y0, x1, y1, 0);
- buf.buf_rowstride = sw * 4;
+ SPCanvasBuf buf;
+ buf.buf = NULL;
+ buf.buf_rowstride = 0;
buf.rect.x0 = x0;
buf.rect.y0 = y0;
buf.rect.x1 = x1;
@@ -1648,114 +1639,75 @@ sp_canvas_paint_single_buffer (SPCanvas *canvas, int x0, int y0, int x1, int y1,
buf.visible_rect.y0 = draw_y1;
buf.visible_rect.x1 = draw_x2;
buf.visible_rect.y1 = draw_y2;
- GdkColor *color = &widget->style->bg[GTK_STATE_NORMAL];
- buf.bg_color = (((color->red & 0xff00) << 8)
- | (color->green & 0xff00)
- | (color->blue >> 8));
buf.is_empty = true;
-
- buf.ct = nr_create_cairo_context_canvasbuf (&(buf.visible_rect), &buf);
+ //buf.ct = gdk_cairo_create(widget->window);
+
+ // create temporary surface
+ int w = x1 - x0;
+ int h = y1 - y0;
+ cairo_surface_t *imgs = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, x1 - x0, y1 - y0);
+ buf.ct = cairo_create(imgs);
+ //cairo_translate(buf.ct, -x0, -y0);
+
+ // fix coordinates, clip all drawing to the tile and clear the background
+ //cairo_translate(buf.ct, x0 - canvas->x0, y0 - canvas->y0);
+ //cairo_rectangle(buf.ct, 0, 0, x1 - x0, y1 - y0);
+ //cairo_set_line_width(buf.ct, 3);
+ //cairo_set_source_rgba(buf.ct, 1.0, 0.0, 0.0, 0.1);
+ //cairo_stroke_preserve(buf.ct);
+ //cairo_clip(buf.ct);
+
+ gdk_cairo_set_source_color(buf.ct, &widget->style->bg[GTK_STATE_NORMAL]);
+ cairo_set_operator(buf.ct, CAIRO_OPERATOR_SOURCE);
+ //cairo_rectangle(buf.ct, 0, 0, x1 - x0, y1 - y0);
+ cairo_paint(buf.ct);
+ cairo_set_operator(buf.ct, CAIRO_OPERATOR_OVER);
if (canvas->root->flags & SP_CANVAS_ITEM_VISIBLE) {
SP_CANVAS_ITEM_GET_CLASS (canvas->root)->render (canvas->root, &buf);
}
-#if ENABLE_LCMS
- cmsHTRANSFORM transf = 0;
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- bool fromDisplay = prefs->getBool( "/options/displayprofile/from_display");
- if ( fromDisplay ) {
- transf = Inkscape::colorprofile_get_display_per( canvas->cms_key ? *(canvas->cms_key) : "" );
- } else {
- transf = Inkscape::colorprofile_get_display_transform();
- }
-#endif // ENABLE_LCMS
+ // output to X
+ cairo_destroy(buf.ct);
- if (buf.is_empty) {
#if ENABLE_LCMS
- if ( transf && canvas->enable_cms_display_adj ) {
- cmsDoTransform( transf, &buf.bg_color, &buf.bg_color, 1 );
+ if (canvas->enable_cms_display_adj) {
+ cmsHTRANSFORM transf = 0;
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ bool fromDisplay = prefs->getBool( "/options/displayprofile/from_display");
+ if ( fromDisplay ) {
+ transf = Inkscape::colorprofile_get_display_per( canvas->cms_key ? *(canvas->cms_key) : "" );
+ } else {
+ transf = Inkscape::colorprofile_get_display_transform();
}
-#endif // ENABLE_LCMS
- gdk_rgb_gc_set_foreground (canvas->pixmap_gc, buf.bg_color);
- gdk_draw_rectangle (SP_CANVAS_WINDOW (canvas),
- canvas->pixmap_gc,
- TRUE,
- x0 - canvas->x0, y0 - canvas->y0,
- x1 - x0, y1 - y0);
- } else {
-
-#if ENABLE_LCMS
- if ( transf && canvas->enable_cms_display_adj ) {
- for ( gint yy = 0; yy < (y1 - y0); yy++ ) {
- guchar* p = buf.buf + (buf.buf_rowstride * yy);
- cmsDoTransform( transf, p, p, (x1 - x0) );
+
+ if (transf) {
+ cairo_surface_flush(imgs);
+ unsigned char *px = cairo_image_surface_get_data(imgs);
+ int stride = cairo_image_surface_get_stride(imgs);
+ for (int i=0; i<h; ++i) {
+ unsigned char *row = px + i*stride;
+ cmsDoTransform(transf, row, row, w);
}
+ cairo_surface_mark_dirty(imgs);
}
-#endif // ENABLE_LCMS
-
-// Now we only need to output the prepared pixmap to the actual screen, and this define chooses one
-// of the two ways to do it. The cairo way is direct and straightforward, but unfortunately
-// noticeably slower. I asked Carl Worth but he was unable so far to suggest any specific reason
-// for this slowness. So, for now we use the oldish method: squeeze out 32bpp buffer to 24bpp and
-// use gdk_draw_rgb_image_dithalign, for unfortunately gdk can only handle 24 bpp, which cairo
-// cannot handle at all. Still, this way is currently faster even despite the blit with squeeze.
-
-///#define CANVAS_OUTPUT_VIA_CAIRO
-
-#ifdef CANVAS_OUTPUT_VIA_CAIRO
-
- buf.cst = cairo_image_surface_create_for_data (
- buf.buf,
- CAIRO_FORMAT_ARGB32, // unpacked, i.e. 32 bits! one byte is unused
- x1 - x0, y1 - y0,
- buf.buf_rowstride
- );
- cairo_t *window_ct = gdk_cairo_create(SP_CANVAS_WINDOW (canvas));
- cairo_set_source_surface (window_ct, buf.cst, x0 - canvas->x0, y0 - canvas->y0);
- cairo_paint (window_ct);
- cairo_destroy (window_ct);
- cairo_surface_finish (buf.cst);
- cairo_surface_destroy (buf.cst);
-
-#else
-
- NRPixBlock b3;
- nr_pixblock_setup_fast (&b3, NR_PIXBLOCK_MODE_R8G8B8, x0, y0, x1, y1, TRUE);
-
- NRPixBlock b4;
- nr_pixblock_setup_extern (&b4, NR_PIXBLOCK_MODE_R8G8B8A8P, x0, y0, x1, y1,
- buf.buf,
- buf.buf_rowstride,
- FALSE, FALSE);
-
- // this does the 32->24 squishing, using an assembler routine:
- nr_blit_pixblock_pixblock (&b3, &b4);
-
- gdk_draw_rgb_image_dithalign (SP_CANVAS_WINDOW (canvas),
- canvas->pixmap_gc,
- x0 - canvas->x0, y0 - canvas->y0,
- x1 - x0, y1 - y0,
- GDK_RGB_DITHER_MAX,
- NR_PIXBLOCK_PX(&b3),
- sw * 3,
- x0 - canvas->x0, y0 - canvas->y0);
-
- nr_pixblock_release (&b3);
- nr_pixblock_release (&b4);
-#endif
}
+#endif // ENABLE_LCMS
- cairo_surface_t *cst = cairo_get_target(buf.ct);
- cairo_destroy (buf.ct);
- cairo_surface_finish (cst);
- cairo_surface_destroy (cst);
+ cairo_t *xct = gdk_cairo_create(widget->window);
+ cairo_translate(xct, x0 - canvas->x0, y0 - canvas->y0);
+ cairo_rectangle(xct, 0, 0, x1-x0, y1-y0);
+ cairo_clip(xct);
+ cairo_set_source_surface(xct, imgs, 0, 0);
+ cairo_set_operator(xct, CAIRO_OPERATOR_SOURCE);
+ cairo_paint(xct);
+ cairo_destroy(xct);
+ cairo_surface_destroy(imgs);
- if (canvas->rendermode != Inkscape::RENDERMODE_OUTLINE) {
- nr_pixelstore_256K_free (buf.buf);
- } else {
- nr_pixelstore_1M_free (buf.buf);
- }
+ //cairo_surface_t *cst = cairo_get_target(buf.ct);
+ //cairo_destroy (buf.ct);
+ //cairo_surface_finish (cst);
+ //cairo_surface_destroy (cst);
}
struct PaintRectSetup {
@@ -1815,11 +1767,21 @@ sp_canvas_paint_rect_internal (PaintRectSetup const *setup, NRRectL this_rect)
if (bw * bh < setup->max_pixels) {
// We are small enough
+ /*GdkRectangle r;
+ r.x = this_rect.x0 - setup->canvas->x0;
+ r.y = this_rect.y0 - setup->canvas->y0;
+ r.width = this_rect.x1 - this_rect.x0;
+ r.height = this_rect.y1 - this_rect.y0;
+
+ GdkWindow *window = GTK_WIDGET(setup->canvas)->window;
+ gdk_window_begin_paint_rect(window, &r);*/
+
sp_canvas_paint_single_buffer (setup->canvas,
this_rect.x0, this_rect.y0,
this_rect.x1, this_rect.y1,
setup->big_rect.x0, setup->big_rect.y0,
setup->big_rect.x1, setup->big_rect.y1, bw);
+ //gdk_window_end_paint(window);
return 1;
}
diff --git a/src/display/sp-canvas.h b/src/display/sp-canvas.h
index e151911dc..7a6b3295e 100644
--- a/src/display/sp-canvas.h
+++ b/src/display/sp-canvas.h
@@ -56,18 +56,16 @@ enum {
};
/**
- * The canvas buf contains the actual pixels.
+ * Structure used when rendering canvas items.
*/
-struct SPCanvasBuf{
- guchar *buf;
- int buf_rowstride;
+struct SPCanvasBuf {
+ cairo_t *ct;
NRRectL rect;
NRRectL visible_rect;
- /// Background color, given as 0xrrggbb
- guint32 bg_color;
- // If empty, ignore contents of buffer and use a solid area of bg_color
+
+ unsigned char *buf;
+ int buf_rowstride;
bool is_empty;
- cairo_t *ct;
};
G_END_DECLS
diff --git a/src/display/sp-ctrlline.cpp b/src/display/sp-ctrlline.cpp
index ef71c0a16..6c763abdf 100644
--- a/src/display/sp-ctrlline.cpp
+++ b/src/display/sp-ctrlline.cpp
@@ -19,14 +19,15 @@
*
*/
-#include "sp-canvas-util.h"
-#include "sp-ctrlline.h"
-
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
-#include <color.h>
-#include "display/inkscape-cairo.h"
+
+#include "display/sp-ctrlline.h"
+#include "display/display-forward.h"
+#include "display/sp-canvas-util.h"
+#include "display/cairo-utils.h"
+#include "color.h"
static void sp_ctrlline_class_init (SPCtrlLineClass *klass);
@@ -105,11 +106,7 @@ sp_ctrlline_render (SPCanvasItem *item, SPCanvasBuf *buf)
if (cl->s == cl->e)
return;
- sp_canvas_prepare_buffer (buf);
-
- guint32 rgba = cl->rgba;
- cairo_set_source_rgba(buf->ct, SP_RGBA32_B_F(rgba), SP_RGBA32_G_F(rgba), SP_RGBA32_R_F(rgba), SP_RGBA32_A_F(rgba));
-
+ ink_cairo_set_source_rgba32(buf->ct, cl->rgba);
cairo_set_line_width(buf->ct, 1);
cairo_new_path(buf->ct);
diff --git a/src/display/sp-ctrlpoint.cpp b/src/display/sp-ctrlpoint.cpp
index 9f2ecb937..c33cdeeb9 100644
--- a/src/display/sp-ctrlpoint.cpp
+++ b/src/display/sp-ctrlpoint.cpp
@@ -18,7 +18,7 @@
# include "config.h"
#endif
#include <color.h>
-#include "display/inkscape-cairo.h"
+#include "display/cairo-utils.h"
static void sp_ctrlpoint_class_init (SPCtrlPointClass *klass);
diff --git a/src/display/sp-ctrlquadr.cpp b/src/display/sp-ctrlquadr.cpp
index 1ed8d62b8..0701d0b10 100644
--- a/src/display/sp-ctrlquadr.cpp
+++ b/src/display/sp-ctrlquadr.cpp
@@ -12,10 +12,13 @@
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
-#include "sp-canvas-util.h"
+
+#include "display-forward.h"
#include "sp-canvas-item.h"
+#include "sp-canvas.h"
+#include "sp-canvas-util.h"
#include "sp-ctrlquadr.h"
-#include "display/inkscape-cairo.h"
+#include "display/cairo-utils.h"
#include "color.h"
struct SPCtrlQuadr : public SPCanvasItem{
diff --git a/src/display/testnr.cpp b/src/display/testnr.cpp
deleted file mode 100644
index 3a3478d28..000000000
--- a/src/display/testnr.cpp
+++ /dev/null
@@ -1,24 +0,0 @@
-#include <gtk/gtk.h>
-#include "sp-arena.h"
-
-int
-main (int argc, char ** argv)
-{
- GtkWidget * w, * c;
-
- gtk_init (&argc, &argv);
-
- w = gtk_window_new (GTK_WINDOW_TOPLEVEL);
-
- c = sp_arena_new ();
- gtk_widget_show (c);
-
- gtk_container_add (GTK_CONTAINER (w), c);
-
- gtk_widget_show (w);
-
- gtk_main ();
-
- return 0;
-}
-
diff --git a/src/draw-context.cpp b/src/draw-context.cpp
index 774fca62d..4dd58afa7 100644
--- a/src/draw-context.cpp
+++ b/src/draw-context.cpp
@@ -477,6 +477,7 @@ void spdc_endpoint_snap_rotation(SPEventContext const *const ec, Geom::Point &p,
{
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
unsigned const snaps = abs(prefs->getInt("/options/rotationsnapsperpi/value", 12));
+
SnapManager &m = SP_EVENT_CONTEXT_DESKTOP(ec)->namedview->snap_manager;
m.setup(SP_EVENT_CONTEXT_DESKTOP(ec));
diff --git a/src/dropper-context.cpp b/src/dropper-context.cpp
index a2515c5f0..e30d6b1e8 100644
--- a/src/dropper-context.cpp
+++ b/src/dropper-context.cpp
@@ -25,6 +25,7 @@
#include "display/canvas-bpath.h"
#include "display/canvas-arena.h"
#include "display/curve.h"
+#include "display/cairo-utils.h"
#include "svg/svg-color.h"
#include "color.h"
#include "color-rgba.h"
@@ -40,7 +41,6 @@
#include "dropper-context.h"
#include "message-context.h"
-//#include "libnr/nr-scale-translate-ops.h"
using Inkscape::DocumentUndo;
@@ -203,7 +203,7 @@ static gint sp_dropper_context_root_handler(SPEventContext *event_context, GdkEv
// otherwise, constantly calculate color no matter is any button pressed or not
double rw = 0.0;
- double W(0), R(0), G(0), B(0), A(0);
+ double R(0), G(0), B(0), A(0);
if (dc->dragging) {
// calculate average
@@ -223,56 +223,32 @@ static gint sp_dropper_context_root_handler(SPEventContext *event_context, GdkEv
sp_canvas_item_show(dc->area);
/* Get buffer */
- const int x0 = (int) floor(dc->centre[Geom::X] - rw);
- const int y0 = (int) floor(dc->centre[Geom::Y] - rw);
- const int x1 = (int) ceil(dc->centre[Geom::X] + rw);
- const int y1 = (int) ceil(dc->centre[Geom::Y] + rw);
-
- if ((x1 > x0) && (y1 > y0)) {
- NRPixBlock pb;
- nr_pixblock_setup_fast(&pb, NR_PIXBLOCK_MODE_R8G8B8A8P, x0, y0, x1, y1, TRUE);
- /* fixme: (Lauris) */
- sp_canvas_arena_render_pixblock(SP_CANVAS_ARENA(sp_desktop_drawing(desktop)), &pb);
- for (int y = y0; y < y1; y++) {
- const unsigned char *s = NR_PIXBLOCK_PX(&pb) + (y - y0) * pb.rs;
- for (int x = x0; x < x1; x++) {
- const double dx = x - dc->centre[Geom::X];
- const double dy = y - dc->centre[Geom::Y];
- const double w = exp(-((dx * dx) + (dy * dy)) / (rw * rw));
- W += w;
- R += w * s[0];
- G += w * s[1];
- B += w * s[2];
- A += w * s[3];
- s += 4;
- }
- }
- nr_pixblock_release(&pb);
-
- R = (R + 0.001) / (255.0 * W);
- G = (G + 0.001) / (255.0 * W);
- B = (B + 0.001) / (255.0 * W);
- A = (A + 0.001) / (255.0 * W);
-
- R = CLAMP(R, 0.0, 1.0);
- G = CLAMP(G, 0.0, 1.0);
- B = CLAMP(B, 0.0, 1.0);
- A = CLAMP(A, 0.0, 1.0);
+ Geom::Rect r(dc->centre, dc->centre);
+ r.expandBy(rw);
+ if (!r.hasZeroArea()) {
+ NRRectL area;
+ area.x0 = r[Geom::X].min();
+ area.y0 = r[Geom::Y].min();
+ area.x1 = r[Geom::X].max();
+ area.y1 = r[Geom::Y].max();
+ int w = area.x1 - area.x0;
+ int h = area.y1 - area.y0;
+ cairo_surface_t *s = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, w, h);
+ sp_canvas_arena_render_surface(SP_CANVAS_ARENA(sp_desktop_drawing(desktop)), s, area);
+ ink_cairo_surface_average_color_premul(s, R, G, B, A);
+ cairo_surface_destroy(s);
}
-
} else {
// pick single pixel
- NRPixBlock pb;
- int x = (int) floor(event->button.x);
- int y = (int) floor(event->button.y);
- nr_pixblock_setup_fast(&pb, NR_PIXBLOCK_MODE_R8G8B8A8P, x, y, x+1, y+1, TRUE);
- sp_canvas_arena_render_pixblock(SP_CANVAS_ARENA(sp_desktop_drawing(desktop)), &pb);
- const unsigned char *s = NR_PIXBLOCK_PX(&pb);
-
- R = s[0] / 255.0;
- G = s[1] / 255.0;
- B = s[2] / 255.0;
- A = s[3] / 255.0;
+ NRRectL area;
+ area.x0 = floor(event->button.x);
+ area.y0 = floor(event->button.y);
+ area.x1 = area.x0 + 1;
+ area.y1 = area.y0 + 1;
+ cairo_surface_t *s = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 1, 1);
+ sp_canvas_arena_render_surface(SP_CANVAS_ARENA(sp_desktop_drawing(desktop)), s, area);
+ ink_cairo_surface_average_color_premul(s, R, G, B, A);
+ cairo_surface_destroy(s);
}
if (pick == SP_DROPPER_PICK_VISIBLE) {
diff --git a/src/dyna-draw-context.cpp b/src/dyna-draw-context.cpp
index 2988aea49..aa7d840bc 100644
--- a/src/dyna-draw-context.cpp
+++ b/src/dyna-draw-context.cpp
@@ -33,6 +33,7 @@
#include "svg/svg.h"
#include "display/canvas-bpath.h"
+#include "display/cairo-utils.h"
#include <2geom/isnan.h>
#include <2geom/pathvector.h>
#include <2geom/bezier-utils.h>
@@ -439,16 +440,16 @@ sp_dyna_draw_brush(SPDynaDrawContext *dc)
double trace_thick = 1;
if (dc->trace_bg) {
// pick single pixel
- NRPixBlock pb;
- int x = (int) floor(brush_w[Geom::X]);
- int y = (int) floor(brush_w[Geom::Y]);
- nr_pixblock_setup_fast(&pb, NR_PIXBLOCK_MODE_R8G8B8A8P, x, y, x+1, y+1, TRUE);
- sp_canvas_arena_render_pixblock(SP_CANVAS_ARENA(sp_desktop_drawing(SP_EVENT_CONTEXT(dc)->desktop)), &pb);
- const unsigned char *s = NR_PIXBLOCK_PX(&pb);
- double R = s[0] / 255.0;
- double G = s[1] / 255.0;
- double B = s[2] / 255.0;
- double A = s[3] / 255.0;
+ double R, G, B, A;
+ NRRectL area;
+ area.x0 = floor(brush_w[Geom::X]);
+ area.y0 = floor(brush_w[Geom::Y]);
+ area.x1 = area.x0 + 1;
+ area.y1 = area.y0 + 1;
+ cairo_surface_t *s = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 1, 1);
+ sp_canvas_arena_render_surface(SP_CANVAS_ARENA(sp_desktop_drawing(SP_EVENT_CONTEXT(dc)->desktop)), s, area);
+ ink_cairo_surface_average_color_premul(s, R, G, B, A);
+ cairo_surface_destroy(s);
double max = MAX (MAX (R, G), B);
double min = MIN (MIN (R, G), B);
double L = A * (max + min)/2 + (1 - A); // blend with white bg
diff --git a/src/extension/extension.h b/src/extension/extension.h
index dba8eeb45..eddddf62c 100644
--- a/src/extension/extension.h
+++ b/src/extension/extension.h
@@ -51,15 +51,6 @@
#define SP_MODULE_KEY_PRINT_LATEX "org.inkscape.print.latex"
/** Defines the key for printing with GNOME Print */
#define SP_MODULE_KEY_PRINT_GNOME "org.inkscape.print.gnome"
-/** Defines the key for printing under Win32 */
-#define SP_MODULE_KEY_PRINT_WIN32 "org.inkscape.print.win32"
-#ifdef WIN32
-/** Defines the default printing to use */
-#define SP_MODULE_KEY_PRINT_DEFAULT SP_MODULE_KEY_PRINT_WIN32
-#else
-/** Defines the default printing to use */
-#define SP_MODULE_KEY_PRINT_DEFAULT SP_MODULE_KEY_PRINT_PS
-#endif
/** Mime type for SVG */
#define MIME_SVG "image/svg+xml"
diff --git a/src/extension/init.cpp b/src/extension/init.cpp
index 230d4b50f..355922bc5 100644
--- a/src/extension/init.cpp
+++ b/src/extension/init.cpp
@@ -26,7 +26,6 @@
#include "db.h"
#include "internal/svgz.h"
#ifdef WIN32
-# include "internal/win32.h"
# include "internal/emf-win32-inout.h"
# include "internal/emf-win32-print.h"
#endif
@@ -171,7 +170,6 @@ init()
}
#endif
#ifdef WIN32
- Internal::PrintWin32::init();
Internal::PrintEmfWin32::init();
Internal::EmfWin32::init();
#endif
diff --git a/src/extension/internal/Makefile_insert b/src/extension/internal/Makefile_insert
index 3c1ce7f43..36a80712d 100644
--- a/src/extension/internal/Makefile_insert
+++ b/src/extension/internal/Makefile_insert
@@ -131,8 +131,6 @@ ink_common_sources += \
extension/internal/filter/filter.h \
extension/internal/filter/drop-shadow.h \
extension/internal/filter/snow.h \
- extension/internal/win32.h \
- extension/internal/win32.cpp \
extension/internal/emf-win32-print.h \
extension/internal/emf-win32-print.cpp \
extension/internal/emf-win32-inout.h \
diff --git a/src/extension/internal/cairo-render-context.cpp b/src/extension/internal/cairo-render-context.cpp
index 4eecb5ecc..b9c2a4488 100644
--- a/src/extension/internal/cairo-render-context.cpp
+++ b/src/extension/internal/cairo-render-context.cpp
@@ -37,7 +37,7 @@
#include "display/nr-arena-group.h"
#include "display/curve.h"
#include "display/canvas-bpath.h"
-#include "display/inkscape-cairo.h"
+#include "display/cairo-utils.h"
#include "sp-item.h"
#include "sp-item-group.h"
#include "style.h"
diff --git a/src/extension/internal/cairo-render-context.h b/src/extension/internal/cairo-render-context.h
index d663a82fd..68a3c6537 100644
--- a/src/extension/internal/cairo-render-context.h
+++ b/src/extension/internal/cairo-render-context.h
@@ -22,6 +22,7 @@
#include <string>
#include <2geom/forward.h>
+#include <2geom/affine.h>
#include "style.h"
diff --git a/src/extension/internal/emf-win32-inout.cpp b/src/extension/internal/emf-win32-inout.cpp
index 2d97174b1..646b33507 100644
--- a/src/extension/internal/emf-win32-inout.cpp
+++ b/src/extension/internal/emf-win32-inout.cpp
@@ -31,41 +31,19 @@
#include "sp-root.h"
#include "sp-path.h"
#include "style.h"
-//#include "color.h"
-//#include "display/curve.h"
-//#include "libnr/nr-point-matrix-ops.h"
-//#include "gtk/gtk.h"
#include "print.h"
-//#include "glibmm/i18n.h"
-//#include "extension/extension.h"
#include "extension/system.h"
#include "extension/print.h"
#include "extension/db.h"
#include "extension/output.h"
-//#include "document.h"
#include "display/nr-arena.h"
#include "display/nr-arena-item.h"
-
-//#include "libnr/nr-rect.h"
-//#include "libnr/nr-matrix.h"
-//#include "libnr/nr-pixblock.h"
-
-//#include <stdio.h>
-//#include <string.h>
-
-//#include <vector>
-//#include <string>
-
-//#include "io/sys.h"
-
#include "unit-constants.h"
-
#include "clear-n_.h"
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
-#include "win32.h"
#include "emf-win32-print.h"
#include "emf-win32-inout.h"
@@ -2321,12 +2299,7 @@ EmfWin32::open( Inkscape::Extension::Input * /*mod*/, const gchar *uri )
HMETAFILE hmf;
HENHMETAFILE hemf;
- if (PrintWin32::is_os_wide()) {
- fp = CreateFileW(unicode_uri, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
- }
- else {
- fp = CreateFileA(ansi_uri, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
- }
+ fp = CreateFileW(unicode_uri, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if ( fp != INVALID_HANDLE_VALUE ) {
filesize = GetFileSize(fp, NULL);
@@ -2334,36 +2307,21 @@ EmfWin32::open( Inkscape::Extension::Input * /*mod*/, const gchar *uri )
}
// Try open as Enhanced Metafile
- if (PrintWin32::is_os_wide())
- hemf = GetEnhMetaFileW(unicode_uri);
- else
- hemf = GetEnhMetaFileA(ansi_uri);
+ hemf = GetEnhMetaFileW(unicode_uri);
if (!hemf) {
// Try open as Windows Metafile
- if (PrintWin32::is_os_wide())
- hmf = GetMetaFileW(unicode_uri);
- else
- hmf = GetMetaFileA(ansi_uri);
+ hmf = GetMetaFileW(unicode_uri);
METAFILEPICT mp;
HDC hDC;
if (!hmf) {
- if (PrintWin32::is_os_wide()) {
- WCHAR szTemp[MAX_PATH];
-
- DWORD dw = GetShortPathNameW( unicode_uri, szTemp, MAX_PATH );
- if (dw) {
- hmf = GetMetaFileW( szTemp );
- }
- } else {
- CHAR szTemp[MAX_PATH];
+ WCHAR szTemp[MAX_PATH];
- DWORD dw = GetShortPathNameA( ansi_uri, szTemp, MAX_PATH );
- if (dw) {
- hmf = GetMetaFileA( szTemp );
- }
+ DWORD dw = GetShortPathNameW( unicode_uri, szTemp, MAX_PATH );
+ if (dw) {
+ hmf = GetMetaFileW( szTemp );
}
}
@@ -2410,10 +2368,7 @@ EmfWin32::open( Inkscape::Extension::Input * /*mod*/, const gchar *uri )
else {
// Try open as Aldus Placeable Metafile
HANDLE hFile;
- if (PrintWin32::is_os_wide())
- hFile = CreateFileW( unicode_uri, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
- else
- hFile = CreateFileA( ansi_uri, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
+ hFile = CreateFileW( unicode_uri, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
if (hFile != INVALID_HANDLE_VALUE) {
DWORD nSize = GetFileSize( hFile, NULL );
diff --git a/src/extension/internal/emf-win32-print.cpp b/src/extension/internal/emf-win32-print.cpp
index 38db43091..e5d1b0681 100644
--- a/src/extension/internal/emf-win32-print.cpp
+++ b/src/extension/internal/emf-win32-print.cpp
@@ -56,10 +56,6 @@
//#include "libnrtype/font-instance.h"
//#include "libnrtype/font-style-to-pos.h"
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-
-#include "win32.h"
#include "emf-win32-print.h"
#include "unit-constants.h"
@@ -185,15 +181,12 @@ PrintEmfWin32::begin (Inkscape::Extension::Print *mod, SPDocument *doc)
snprintf(buff+len+1, sizeof(buff)-len-2, "%s", p);
// Create the Metafile
- if (PrintWin32::is_os_wide()) {
+ {
WCHAR wbuff[1024];
ZeroMemory(wbuff, sizeof(wbuff));
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, buff, sizeof(buff)/sizeof(buff[0]), wbuff, sizeof(wbuff)/sizeof(wbuff[0]));
hdc = CreateEnhMetaFileW( hScreenDC, unicode_uri, &rc, wbuff );
}
- else {
- hdc = CreateEnhMetaFileA( hScreenDC, ansi_uri, &rc, buff );
- }
// Release the reference DC
ReleaseDC( NULL, hScreenDC );
@@ -878,76 +871,40 @@ PrintEmfWin32::text(Inkscape::Extension::Print * /*mod*/, char const *text, Geom
#endif
if (!hfont) {
- if (PrintWin32::is_os_wide()) {
- LOGFONTW *lf = (LOGFONTW*)g_malloc(sizeof(LOGFONTW));
- g_assert(lf != NULL);
-
- lf->lfHeight = style->font_size.computed * IN_PER_PX * dwDPI;
- lf->lfWidth = 0;
- lf->lfEscapement = rot;
- lf->lfOrientation = rot;
- lf->lfWeight =
- style->font_weight.computed == SP_CSS_FONT_WEIGHT_100 ? FW_THIN :
- style->font_weight.computed == SP_CSS_FONT_WEIGHT_200 ? FW_EXTRALIGHT :
- style->font_weight.computed == SP_CSS_FONT_WEIGHT_300 ? FW_LIGHT :
- style->font_weight.computed == SP_CSS_FONT_WEIGHT_400 ? FW_NORMAL :
- style->font_weight.computed == SP_CSS_FONT_WEIGHT_500 ? FW_MEDIUM :
- style->font_weight.computed == SP_CSS_FONT_WEIGHT_600 ? FW_SEMIBOLD :
- style->font_weight.computed == SP_CSS_FONT_WEIGHT_700 ? FW_BOLD :
- style->font_weight.computed == SP_CSS_FONT_WEIGHT_800 ? FW_EXTRABOLD :
- style->font_weight.computed == SP_CSS_FONT_WEIGHT_900 ? FW_HEAVY :
- FW_NORMAL;
- lf->lfItalic = (style->font_style.computed == SP_CSS_FONT_STYLE_ITALIC);
- lf->lfUnderline = style->text_decoration.underline;
- lf->lfStrikeOut = style->text_decoration.line_through;
- lf->lfCharSet = DEFAULT_CHARSET;
- lf->lfOutPrecision = OUT_DEFAULT_PRECIS;
- lf->lfClipPrecision = CLIP_DEFAULT_PRECIS;
- lf->lfQuality = DEFAULT_QUALITY;
- lf->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
-
- gunichar2 *unicode_name = g_utf8_to_utf16( style->text->font_family.value, -1, NULL, NULL, NULL );
- wcsncpy(lf->lfFaceName, (wchar_t*) unicode_name, LF_FACESIZE-1);
- g_free(unicode_name);
-
- hfont = CreateFontIndirectW(lf);
-
- g_free(lf);
- }
- else {
- LOGFONTA *lf = (LOGFONTA*)g_malloc(sizeof(LOGFONTA));
- g_assert(lf != NULL);
-
- lf->lfHeight = style->font_size.computed * IN_PER_PX * dwDPI;
- lf->lfWidth = 0;
- lf->lfEscapement = rot;
- lf->lfOrientation = rot;
- lf->lfWeight =
- style->font_weight.computed == SP_CSS_FONT_WEIGHT_100 ? FW_THIN :
- style->font_weight.computed == SP_CSS_FONT_WEIGHT_200 ? FW_EXTRALIGHT :
- style->font_weight.computed == SP_CSS_FONT_WEIGHT_300 ? FW_LIGHT :
- style->font_weight.computed == SP_CSS_FONT_WEIGHT_400 ? FW_NORMAL :
- style->font_weight.computed == SP_CSS_FONT_WEIGHT_500 ? FW_MEDIUM :
- style->font_weight.computed == SP_CSS_FONT_WEIGHT_600 ? FW_SEMIBOLD :
- style->font_weight.computed == SP_CSS_FONT_WEIGHT_700 ? FW_BOLD :
- style->font_weight.computed == SP_CSS_FONT_WEIGHT_800 ? FW_EXTRABOLD :
- style->font_weight.computed == SP_CSS_FONT_WEIGHT_900 ? FW_HEAVY :
- FW_NORMAL;
- lf->lfItalic = (style->font_style.computed == SP_CSS_FONT_STYLE_ITALIC);
- lf->lfUnderline = style->text_decoration.underline;
- lf->lfStrikeOut = style->text_decoration.line_through;
- lf->lfCharSet = DEFAULT_CHARSET;
- lf->lfOutPrecision = OUT_DEFAULT_PRECIS;
- lf->lfClipPrecision = CLIP_DEFAULT_PRECIS;
- lf->lfQuality = DEFAULT_QUALITY;
- lf->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
-
- strncpy(lf->lfFaceName, (char*) style->text->font_family.value, LF_FACESIZE-1);
-
- hfont = CreateFontIndirectA(lf);
-
- g_free(lf);
- }
+ LOGFONTW *lf = (LOGFONTW*)g_malloc(sizeof(LOGFONTW));
+ g_assert(lf != NULL);
+
+ lf->lfHeight = style->font_size.computed * IN_PER_PX * dwDPI;
+ lf->lfWidth = 0;
+ lf->lfEscapement = rot;
+ lf->lfOrientation = rot;
+ lf->lfWeight =
+ style->font_weight.computed == SP_CSS_FONT_WEIGHT_100 ? FW_THIN :
+ style->font_weight.computed == SP_CSS_FONT_WEIGHT_200 ? FW_EXTRALIGHT :
+ style->font_weight.computed == SP_CSS_FONT_WEIGHT_300 ? FW_LIGHT :
+ style->font_weight.computed == SP_CSS_FONT_WEIGHT_400 ? FW_NORMAL :
+ style->font_weight.computed == SP_CSS_FONT_WEIGHT_500 ? FW_MEDIUM :
+ style->font_weight.computed == SP_CSS_FONT_WEIGHT_600 ? FW_SEMIBOLD :
+ style->font_weight.computed == SP_CSS_FONT_WEIGHT_700 ? FW_BOLD :
+ style->font_weight.computed == SP_CSS_FONT_WEIGHT_800 ? FW_EXTRABOLD :
+ style->font_weight.computed == SP_CSS_FONT_WEIGHT_900 ? FW_HEAVY :
+ FW_NORMAL;
+ lf->lfItalic = (style->font_style.computed == SP_CSS_FONT_STYLE_ITALIC);
+ lf->lfUnderline = style->text_decoration.underline;
+ lf->lfStrikeOut = style->text_decoration.line_through;
+ lf->lfCharSet = DEFAULT_CHARSET;
+ lf->lfOutPrecision = OUT_DEFAULT_PRECIS;
+ lf->lfClipPrecision = CLIP_DEFAULT_PRECIS;
+ lf->lfQuality = DEFAULT_QUALITY;
+ lf->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
+
+ gunichar2 *unicode_name = g_utf8_to_utf16( style->text->font_family.value, -1, NULL, NULL, NULL );
+ wcsncpy(lf->lfFaceName, (wchar_t*) unicode_name, LF_FACESIZE-1);
+ g_free(unicode_name);
+
+ hfont = CreateFontIndirectW(lf);
+
+ g_free(lf);
}
HFONT hfontOld = (HFONT) SelectObject(hdc, hfont);
@@ -972,13 +929,10 @@ PrintEmfWin32::text(Inkscape::Extension::Print * /*mod*/, char const *text, Geom
LONG const xpos = (LONG) round(p[Geom::X]);
LONG const ypos = (LONG) round(rc.bottom-p[Geom::Y]);
- if (PrintWin32::is_os_wide()) {
+ {
gunichar2 *unicode_text = g_utf8_to_utf16( text, -1, NULL, NULL, NULL );
TextOutW(hdc, xpos, ypos, (WCHAR*)unicode_text, wcslen((wchar_t*)unicode_text));
}
- else {
- TextOutA(hdc, xpos, ypos, (CHAR*)text, strlen((char*)text));
- }
SelectObject(hdc, hfontOld);
DeleteObject(hfont);
diff --git a/src/extension/internal/emf-win32-print.h b/src/extension/internal/emf-win32-print.h
index a9f639bcd..44327d35e 100644
--- a/src/extension/internal/emf-win32-print.h
+++ b/src/extension/internal/emf-win32-print.h
@@ -17,6 +17,9 @@
# include "config.h"
#endif
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
#include "extension/implementation/implementation.h"
//#include "extension/extension.h"
diff --git a/src/extension/internal/win32.cpp b/src/extension/internal/win32.cpp
deleted file mode 100644
index 537c91a2c..000000000
--- a/src/extension/internal/win32.cpp
+++ /dev/null
@@ -1,510 +0,0 @@
-/** @file
- * @brief Windows-specific stuff
- */
-/* Author:
- * Lauris Kaplinski <lauris@kaplinski.com>
- * Abhishek Sharma
- *
- * This code is in public domain
- */
-
-#ifdef WIN32
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include <glib/gmem.h>
-#include <libnr/nr-macros.h>
-#include <2geom/transforms.h>
-
-#include "display/nr-arena-item.h"
-#include "display/nr-arena.h"
-#include "document.h"
-
-#include "win32.h"
-#include "extension/system.h"
-#include "extension/print.h"
-#include <gtk/gtk.h>
-
-/* Initialization */
-
-namespace Inkscape {
-namespace Extension {
-namespace Internal {
-
-static unsigned int SPWin32Modal = FALSE;
-
-/**
- * Callback function.. not a method
- */
-static void
-my_gdk_event_handler (GdkEvent *event)
-{
- if (SPWin32Modal) {
- /* Win32 widget is modal, filter events */
- switch (event->type) {
- case GDK_NOTHING:
- case GDK_DELETE:
- case GDK_SCROLL:
- case GDK_BUTTON_PRESS:
- case GDK_2BUTTON_PRESS:
- case GDK_3BUTTON_PRESS:
- case GDK_BUTTON_RELEASE:
- case GDK_KEY_PRESS:
- case GDK_KEY_RELEASE:
- case GDK_DRAG_STATUS:
- case GDK_DRAG_ENTER:
- case GDK_DRAG_LEAVE:
- case GDK_DRAG_MOTION:
- case GDK_DROP_START:
- case GDK_DROP_FINISHED:
- return;
- break;
- default:
- break;
- }
- }
- gtk_main_do_event (event);
-}
-
-void
-PrintWin32::main_init (int argc, char **argv, const char *name)
-{
- gdk_event_handler_set ((GdkEventFunc) my_gdk_event_handler, NULL, NULL);
-}
-
-void
-PrintWin32::finish (void)
-{
-}
-
-#define SP_FOREIGN_MAX_ITER 10
-
-
-/**
- * Callback function.. not a method
- */
-static VOID CALLBACK
-my_timer (HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
-{
- int cdown = 0;
- while ((cdown++ < SP_FOREIGN_MAX_ITER) && gdk_events_pending ()) {
- gtk_main_iteration_do (FALSE);
- }
- gtk_main_iteration_do (FALSE);
-}
-
-
-/* Platform detection */
-
-gboolean
-PrintWin32::is_os_wide()
-{
- static gboolean initialized = FALSE;
- static gboolean is_wide = FALSE;
- static OSVERSIONINFOA osver;
-
- if ( !initialized )
- {
- BOOL result;
-
- initialized = TRUE;
-
- memset (&osver, 0, sizeof(OSVERSIONINFOA));
- osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
- result = GetVersionExA (&osver);
- if (result)
- {
- if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT)
- is_wide = TRUE;
- }
- // If we can't even call to get the version, fall back to ANSI API
- }
-
- return is_wide;
-}
-
-
-/* Printing */
-
-PrintWin32::PrintWin32 (void)
-{
- /* Nothing here */
-}
-
-
-PrintWin32::~PrintWin32 (void)
-{
- DeleteDC (_hDC);
-}
-
-
-/**
- * Callback function.. not a method
- */
-static UINT_PTR CALLBACK
-print_hook (HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
-{
-#if 0
- int cdown = 0;
- while ((cdown++ < SP_FOREIGN_MAX_ITER) && gdk_events_pending ()) {
- gtk_main_iteration_do (FALSE);
- }
- gtk_main_iteration_do (FALSE);
-#endif
- return 0;
-}
-
-unsigned int
-PrintWin32::setup (Inkscape::Extension::Print *mod)
-{
- HRESULT res;
- PRINTDLG pd = {
- sizeof (PRINTDLG),
- NULL, /* hwndOwner */
- NULL, /* hDevMode */
- NULL, /* hDevNames */
- NULL, /* hDC */
- PD_NOPAGENUMS | PD_NOSELECTION | PD_RETURNDC | PD_USEDEVMODECOPIESANDCOLLATE, /* Flags */
- 1, 1, 1, 1, /* nFromPage, nToPage, nMinPage, nMaxPage */
- 1, /* nCoies */
- NULL, /* hInstance */
- 0, /* lCustData */
- NULL, NULL, NULL, NULL, NULL, NULL
- };
- UINT_PTR timer;
-
- SPWin32Modal = TRUE;
- pd.Flags |= PD_ENABLEPRINTHOOK;
- pd.lpfnPrintHook = print_hook;
- timer = SetTimer (NULL, 0, 40, my_timer);
-
- res = PrintDlg (&pd);
-
- KillTimer (NULL, timer);
- SPWin32Modal = FALSE;
-
- if (!res) return FALSE;
-
- _hDC = pd.hDC;
-
-#if 0
- caps = GetDeviceCaps (_hDC, RASTERCAPS);
- if (caps & RC_BANDING) {
- printf ("needs banding\n");
- }
- if (caps & RC_BITBLT) {
- printf ("does bitblt\n");
- }
- if (caps & RC_DIBTODEV) {
- printf ("does dibtodev\n");
- }
- if (caps & RC_STRETCHDIB) {
- printf ("does stretchdib\n");
- }
-#endif
- if (pd.hDevMode) {
- DEVMODE *devmodep;
- devmodep = (DEVMODE *)pd.hDevMode;
- if (devmodep->dmFields & DM_ORIENTATION) {
- _landscape = (devmodep->dmOrientation == DMORIENT_LANDSCAPE);
- }
- }
-
- return TRUE;
-}
-
-unsigned int
-PrintWin32::begin (Inkscape::Extension::Print *mod, SPDocument *doc)
-{
- DOCINFO di = {
- sizeof (DOCINFO),
- NULL, /* lpszDocName */
- NULL, /* lpszOutput */
- NULL, /* lpszDatatype */
- 0 /* DI_APPBANDING */ /* fwType */
- };
- int res;
-
- _PageWidth = doc->getWidth ();
- _PageHeight = doc->getHeight ();
-
- di.lpszDocName = doc->getName();
-
- SPWin32Modal = TRUE;
-
- res = StartDoc (_hDC, &di);
- res = StartPage (_hDC);
-
- SPWin32Modal = FALSE;
-
- return 0;
-}
-
-unsigned int
-PrintWin32::finish (Inkscape::Extension::Print *mod)
-{
- int dpiX, dpiY;
- int pPhysicalWidth, pPhysicalHeight;
- int pPhysicalOffsetX, pPhysicalOffsetY;
- int pPrintableWidth, pPrintableHeight;
- float scalex, scaley;
- int x0, y0, x1, y1;
- int width, height;
- unsigned char *px;
- int sheight, row;
- BITMAPINFO bmInfo = {
- {
- sizeof (BITMAPINFOHEADER), // bV4Size
- 64, // biWidth
- 64, // biHeight
- 1, // biPlanes
- 32, // biBitCount
- BI_RGB, // biCompression
- 0, // biSizeImage
- 2835, // biXPelsPerMeter
- 2835, // biYPelsPerMeter
- 0, // biClrUsed
- 0 // biClrImportant
- },
- { { 0, 0, 0, 0 } } // bmiColors
- };
- //RECT wrect;
- int res;
-
- SPWin32Modal = TRUE;
-
- // Number of pixels per logical inch
- dpiX = (int) GetDeviceCaps (_hDC, LOGPIXELSX);
- dpiY = (int) GetDeviceCaps (_hDC, LOGPIXELSY);
- // Size in pixels of the printable area
- pPhysicalWidth = GetDeviceCaps (_hDC, PHYSICALWIDTH);
- pPhysicalHeight = GetDeviceCaps (_hDC, PHYSICALHEIGHT);
- // Top left corner of prontable area
- pPhysicalOffsetX = GetDeviceCaps (_hDC, PHYSICALOFFSETX);
- pPhysicalOffsetY = GetDeviceCaps (_hDC, PHYSICALOFFSETY);
- // Size in pixels of the printable area
- pPrintableWidth = GetDeviceCaps (_hDC, HORZRES);
- pPrintableHeight = GetDeviceCaps (_hDC, VERTRES);
-
- // Scaling from document to device
- scalex = dpiX / 72.0;
- scaley = dpiY / 72.0;
-
- // We simply map document 0,0 to physical page 0,0
- Geom::Affine affine = Geom::Scale(scalex / 1.25, scaley / 1.25);
-
- nr_arena_item_set_transform (mod->root, affine);
-
- // Calculate printable area in device coordinates
- x0 = pPhysicalOffsetX;
- y0 = pPhysicalOffsetY;
- x1 = x0 + pPrintableWidth;
- y1 = y0 + pPrintableHeight;
- x1 = MIN (x1, (int) (_PageWidth * scalex));
- y1 = MIN (y1, (int) (_PageHeight * scaley));
-
- width = x1 - x0;
- height = y1 - y0;
-
- px = g_new (unsigned char, 4 * 64 * width);
- sheight = 64;
-
- /* Printing goes here */
- for (row = 0; row < height; row += 64) {
- NRPixBlock pb;
- NRRectL bbox;
- NRGC gc(NULL);
- int num_rows;
- int i;
-
- num_rows = sheight;
- if ((row + num_rows) > height) num_rows = height - row;
-
- /* Set area of interest */
- bbox.x0 = x0;
- bbox.y0 = y0 + row;
- bbox.x1 = bbox.x0 + width;
- bbox.y1 = bbox.y0 + num_rows;
- /* Update to renderable state */
- gc.transform.setIdentity();
- nr_arena_item_invoke_update (mod->root, &bbox, &gc, NR_ARENA_ITEM_STATE_ALL, NR_ARENA_ITEM_STATE_NONE);
-
- nr_pixblock_setup_extern (&pb, NR_PIXBLOCK_MODE_R8G8B8A8N, bbox.x0, bbox.y0, bbox.x1, bbox.y1, px, 4 * (bbox.x1 - bbox.x0), FALSE, FALSE);
-
- /* Blitter goes here */
- bmInfo.bmiHeader.biWidth = bbox.x1 - bbox.x0;
- bmInfo.bmiHeader.biHeight = -(bbox.y1 - bbox.y0);
-
- memset (px, 0xff, 4 * num_rows * width);
- /* Render */
- nr_arena_item_invoke_render (NULL, mod->root, &bbox, &pb, 0);
-
- /* Swap red and blue channels; we use RGBA, whereas
- * the Win32 GDI uses BGRx.
- */
- for ( i = 0 ; i < num_rows * width ; i++ ) {
- unsigned char temp=px[i*4];
- px[i*4] = px[i*4+2];
- px[i*4+2] = temp;
- }
-
- SetStretchBltMode(_hDC, COLORONCOLOR);
- res = StretchDIBits (_hDC,
- bbox.x0 - x0, bbox.y0 - y0, bbox.x1 - bbox.x0, bbox.y1 - bbox.y0,
- 0, 0, bbox.x1 - bbox.x0, bbox.y1 - bbox.y0,
- px,
- &bmInfo,
- DIB_RGB_COLORS,
- SRCCOPY);
-
- /* Blitter ends here */
-
- nr_pixblock_release (&pb);
- }
-
- g_free (px);
-
- res = EndPage (_hDC);
- res = EndDoc (_hDC);
-
- SPWin32Modal = FALSE;
-
- return 0;
-}
-
-/* File dialogs */
-
-char *
-PrintWin32::get_open_filename (unsigned char *dir, unsigned char *filter, unsigned char *title)
-{
- char fnbuf[4096] = {0};
- OPENFILENAME ofn = {
- sizeof (OPENFILENAME),
- NULL, /* hwndOwner */
- NULL, /* hInstance */
- (const CHAR *)filter, /* lpstrFilter */
- NULL, /* lpstrCustomFilter */
- 0, /* nMaxCustFilter */
- 1, /* nFilterIndex */
- fnbuf, /* lpstrFile */
- sizeof (fnbuf), /* nMaxFile */
- NULL, /* lpstrFileTitle */
- 0, /* nMaxFileTitle */
- (const CHAR *)dir, /* lpstrInitialDir */
- (const CHAR *)title, /* lpstrTitle */
- OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY, /* Flags */
- 0, /* nFileOffset */
- 0, /* nFileExtension */
- NULL, /* lpstrDefExt */
- 0, /* lCustData */
- NULL, /* lpfnHook */
- NULL /* lpTemplateName */
- };
- int retval;
- UINT_PTR timer;
-
- SPWin32Modal = TRUE;
- timer = SetTimer (NULL, 0, 40, my_timer);
-
- retval = GetOpenFileName (&ofn);
-
- KillTimer (NULL, timer);
- SPWin32Modal = FALSE;
-
- if (!retval) {
- int errcode;
- errcode = CommDlgExtendedError();
- return NULL;
- }
- return g_strdup (fnbuf);
-}
-
-char *
-PrintWin32::get_write_filename (unsigned char *dir, unsigned char *filter, unsigned char *title)
-{
- return NULL;
-}
-
-char *
-PrintWin32::get_save_filename (unsigned char *dir, unsigned int *spns)
-{
- char fnbuf[4096] = {0};
- OPENFILENAME ofn = {
- sizeof (OPENFILENAME),
- NULL, /* hwndOwner */
- NULL, /* hInstance */
- "Inkscape SVG (*.svg)\0*\0Plain SVG (*.svg)\0*\0", /* lpstrFilter */
- NULL, /* lpstrCustomFilter */
- 0, /* nMaxCustFilter */
- 1, /* nFilterIndex */
- fnbuf, /* lpstrFile */
- sizeof (fnbuf), /* nMaxFile */
- NULL, /* lpstrFileTitle */
- 0, /* nMaxFileTitle */
- (const CHAR *)dir, /* lpstrInitialDir */
- "Save document to file", /* lpstrTitle */
- OFN_HIDEREADONLY, /* Flags */
- 0, /* nFileOffset */
- 0, /* nFileExtension */
- NULL, /* lpstrDefExt */
- 0, /* lCustData */
- NULL, /* lpfnHook */
- NULL /* lpTemplateName */
- };
- int retval;
- UINT_PTR timer;
-
- SPWin32Modal = TRUE;
- timer = SetTimer (NULL, 0, 40, my_timer);
-
- retval = GetSaveFileName (&ofn);
-
- KillTimer (NULL, timer);
- SPWin32Modal = FALSE;
-
- if (!retval) {
- int errcode;
- errcode = CommDlgExtendedError();
- return NULL;
- }
- *spns = (ofn.nFilterIndex != 2);
- return g_strdup (fnbuf);
-}
-
-#include "clear-n_.h"
-
-void
-PrintWin32::init (void)
-{
- Inkscape::Extension::Extension * ext;
-
- /* SVG in */
- ext = Inkscape::Extension::build_from_mem(
- "<inkscape-extension xmlns=\"" INKSCAPE_EXTENSION_URI "\">\n"
- "<name>" N_("Windows 32-bit Print") "</name>\n"
- "<id>" SP_MODULE_KEY_PRINT_WIN32 "</id>\n"
- "<param name=\"textToPath\" type=\"boolean\">true</param>\n"
- "<print/>\n"
- "</inkscape-extension>", new PrintWin32());
-
- return;
-}
-
-} /* namespace Internal */
-} /* namespace Extension */
-} /* namespace Inkscape */
-
-#endif // ifdef WIN32
-
-/*
- 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/extension/internal/win32.h b/src/extension/internal/win32.h
deleted file mode 100644
index 4a913bb05..000000000
--- a/src/extension/internal/win32.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/** @file
- * @brief Windows-specific stuff
- */
-/* Author:
- * Lauris Kaplinski <lauris@kaplinski.com>
- * Ted Gould <ted@gould.cx>
- *
- * Lauris: This code is in public domain
- * Ted: This code is released under the GNU GPL
- */
-
-#ifndef __INKSCAPE_EXTENSION_INTERNAL_PRINT_WIN32_H__
-#define __INKSCAPE_EXTENSION_INTERNAL_PRINT_WIN32_H__
-#ifdef WIN32
-
-#ifdef HAVE_CONFIG_H
- #include <config.h>
-#endif
-
-#ifdef DATADIR
-#undef DATADIR
-#endif
-#include <windows.h>
-
-#include "extension/extension.h"
-#include "extension/implementation/implementation.h"
-
-namespace Inkscape {
-namespace Extension {
-namespace Internal {
-
-/* Initialization */
-
-class PrintWin32 : public Inkscape::Extension::Implementation::Implementation {
- /* Document dimensions */
- float _PageWidth;
- float _PageHeight;
-
- HDC _hDC;
-
- unsigned int _landscape;
-
- void main_init (int argc, char **argv, const char *name);
- void finish (void);
-
- /* File dialogs */
- char *get_open_filename (unsigned char *dir, unsigned char *filter, unsigned char *title);
- char *get_write_filename (unsigned char *dir, unsigned char *filter, unsigned char *title);
- char *get_save_filename (unsigned char *dir, unsigned int *spns);
-
- VOID CALLBACK timer (HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime);
-
-
-public:
- PrintWin32 (void);
- virtual ~PrintWin32 (void);
-
- /* Tell modules about me */
- static void init (void);
-
- /* Platform detection */
- static gboolean is_os_wide();
-
- /* Print functions */
- virtual unsigned int setup (Inkscape::Extension::Print * module);
- //virtual unsigned int set_preview (Inkscape::Extension::Print * module);
-
- virtual unsigned int begin (Inkscape::Extension::Print * module, SPDocument *doc);
- virtual unsigned int finish (Inkscape::Extension::Print * module);
-
- /* Rendering methods */
- /*
- virtual unsigned int bind (Inkscape::Extension::Print * module, const Geom::Affine *transform, float opacity);
- virtual unsigned int release (Inkscape::Extension::Print * module);
- virtual unsigned int comment (Inkscape::Extension::Print * module, const char * comment);
- virtual unsigned int image (Inkscape::Extension::Print * module, unsigned char *px, unsigned int w, unsigned int h, unsigned int rs,
- const Geom::Affine *transform, const SPStyle *style);
- */
-};
-
-} /* namespace Internal */
-} /* namespace Extension */
-} /* namespace Inkscape */
-
-#endif // ifdef WIN32
-#endif /* __INKSCAPE_EXTENSION_INTERNAL_PRINT_WIN32_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/file.cpp b/src/file.cpp
index 2e7e74610..43d1ddaaa 100644
--- a/src/file.cpp
+++ b/src/file.cpp
@@ -31,7 +31,6 @@
#include <gtk/gtk.h>
#include <glib/gmem.h>
#include <glibmm/i18n.h>
-#include <libnr/nr-pixops.h>
#include "desktop.h"
#include "desktop-handles.h"
@@ -1523,20 +1522,6 @@ sp_file_print(Gtk::Window& parentWindow)
sp_print_document(parentWindow, doc);
}
-/**
- * Display what the drawing would look like, if
- * printed.
- */
-void
-sp_file_print_preview(gpointer /*object*/, gpointer /*data*/)
-{
-
- SPDocument *doc = SP_ACTIVE_DOCUMENT;
- if (doc)
- sp_print_preview_document(doc);
-
-}
-
/*
Local Variables:
diff --git a/src/file.h b/src/file.h
index dec7e3f14..0041af81f 100644
--- a/src/file.h
+++ b/src/file.h
@@ -183,11 +183,6 @@ would be useful as instance methods
*/
void sp_file_print (Gtk::Window& parentWindow);
-/**
- *
- */
-void sp_file_print_preview (gpointer object, gpointer data);
-
/*#####################
## U T I L I T Y
#####################*/
diff --git a/src/filter-chemistry.cpp b/src/filter-chemistry.cpp
index 18a31f0d7..b78b96c02 100644
--- a/src/filter-chemistry.cpp
+++ b/src/filter-chemistry.cpp
@@ -22,11 +22,10 @@
#include "filter-enums.h"
#include "filters/blend.h"
+#include "filters/gaussian-blur.h"
#include "sp-filter.h"
#include "sp-filter-reference.h"
-#include "sp-gaussian-blur.h"
#include "svg/css-ostringstream.h"
-#include "libnr/nr-matrix-fns.h"
#include "xml/repr.h"
diff --git a/src/filter-chemistry.h b/src/filter-chemistry.h
index 9e97d6f80..9f16419fd 100644
--- a/src/filter-chemistry.h
+++ b/src/filter-chemistry.h
@@ -1,6 +1,3 @@
-#ifndef __SP_FILTER_CHEMISTRY_H__
-#define __SP_FILTER_CHEMISTRY_H__
-
/*
* Various utility methods for filters
*
@@ -14,8 +11,14 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
+#ifndef SEEN_SP_FILTER_CHEMISTRY_H
+#define SEEN_SP_FILTER_CHEMISTRY_H
+
#include "forward.h"
-#include "sp-filter.h"
+#include "display/nr-filter-types.h"
+
+class SPFilter;
+class SPFilterPrimitive;
SPFilterPrimitive *filter_add_primitive(SPFilter *filter, Inkscape::Filters::FilterPrimitiveType);
SPFilter *new_filter (SPDocument *document);
diff --git a/src/filters/Makefile_insert b/src/filters/Makefile_insert
index dde7cdb68..ea9ff4b56 100644
--- a/src/filters/Makefile_insert
+++ b/src/filters/Makefile_insert
@@ -1,59 +1,46 @@
## Makefile.am fragment sourced by src/Makefile.am.
ink_common_sources += \
- filters/blend.cpp \
- filters/blend-fns.h \
- filters/blend.h \
- filters/colormatrix.cpp \
- filters/colormatrix-fns.h \
- filters/colormatrix.h \
- filters/componenttransfer.cpp \
- filters/componenttransfer-fns.h \
+ filters/blend.cpp \
+ filters/blend.h \
+ filters/colormatrix.cpp \
+ filters/colormatrix.h \
+ filters/componenttransfer.cpp \
filters/componenttransfer-funcnode.cpp \
filters/componenttransfer-funcnode.h \
- filters/componenttransfer.h \
- filters/composite.cpp \
- filters/composite-fns.h \
- filters/composite.h \
- filters/convolvematrix.cpp \
- filters/convolvematrix-fns.h \
- filters/convolvematrix.h \
- filters/diffuselighting.cpp \
- filters/diffuselighting-fns.h \
- filters/diffuselighting.h \
- filters/displacementmap.cpp \
- filters/displacementmap-fns.h \
- filters/displacementmap.h \
- filters/distantlight.cpp \
- filters/distantlight.h \
- filters/flood.cpp \
- filters/flood-fns.h \
- filters/flood.h \
- filters/image.cpp \
- filters/image-fns.h \
- filters/image.h \
- filters/merge.cpp \
- filters/merge-fns.h \
- filters/merge.h \
- filters/mergenode.cpp \
- filters/mergenode.h \
- filters/morphology.cpp \
- filters/morphology-fns.h \
- filters/morphology.h \
- filters/offset.cpp \
- filters/offset-fns.h \
- filters/offset.h \
- filters/pointlight.cpp \
- filters/pointlight.h \
- filters/specularlighting.cpp \
- filters/specularlighting-fns.h \
- filters/specularlighting.h \
- filters/spotlight.cpp \
- filters/spotlight.h \
- filters/tile.cpp \
- filters/tile-fns.h \
- filters/tile.h \
- filters/turbulence.cpp \
- filters/turbulence-fns.h \
+ filters/componenttransfer.h \
+ filters/composite.cpp \
+ filters/composite.h \
+ filters/convolvematrix.cpp \
+ filters/convolvematrix.h \
+ filters/diffuselighting.cpp \
+ filters/diffuselighting.h \
+ filters/displacementmap.cpp \
+ filters/displacementmap.h \
+ filters/distantlight.cpp \
+ filters/distantlight.h \
+ filters/flood.cpp \
+ filters/flood.h \
+ filters/gaussian-blur.cpp \
+ filters/gaussian-blur.h \
+ filters/image.cpp \
+ filters/image.h \
+ filters/merge.cpp \
+ filters/merge.h \
+ filters/mergenode.cpp \
+ filters/mergenode.h \
+ filters/morphology.cpp \
+ filters/morphology.h \
+ filters/offset.cpp \
+ filters/offset.h \
+ filters/pointlight.cpp \
+ filters/pointlight.h \
+ filters/specularlighting.cpp \
+ filters/specularlighting.h \
+ filters/spotlight.cpp \
+ filters/spotlight.h \
+ filters/tile.cpp \
+ filters/tile.h \
+ filters/turbulence.cpp \
filters/turbulence.h
diff --git a/src/filters/blend-fns.h b/src/filters/blend-fns.h
deleted file mode 100644
index 94456e0dd..000000000
--- a/src/filters/blend-fns.h
+++ /dev/null
@@ -1,38 +0,0 @@
-#ifndef SP_FEBLEND_FNS_H
-#define SP_FEBLEND_FNS_H
-
-/** \file
- * Macros and fn declarations related to gaussian blur filter.
- */
-
-#include <glib-object.h>
-#include <glib/gtypes.h>
-
-namespace Inkscape {
-namespace XML {
-class Node;
-}
-}
-
-class SPFeBlend;
-
-#define SP_TYPE_FEBLEND (sp_feBlend_get_type())
-#define SP_FEBLEND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SP_TYPE_FEBLEND, SPFeBlend))
-#define SP_FEBLEND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), SP_TYPE_FEBLEND, SPFeBlendClass))
-#define SP_IS_FEBLEND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), SP_TYPE_FEBLEND))
-#define SP_IS_FEBLEND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), SP_TYPE_FEBLEND))
-
-GType sp_feBlend_get_type();
-
-#endif /* !SP_FEBLEND_FNS_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/filters/blend.cpp b/src/filters/blend.cpp
index 9a52d86f7..809bd6c00 100644
--- a/src/filters/blend.cpp
+++ b/src/filters/blend.cpp
@@ -19,9 +19,10 @@
#include <string.h>
+#include "sp-filter.h"
+#include "filters/blend.h"
#include "attributes.h"
#include "svg/svg.h"
-#include "blend.h"
#include "xml/repr.h"
#include "display/nr-filter.h"
diff --git a/src/filters/blend.h b/src/filters/blend.h
index 62c6faaee..e7fc410e7 100644
--- a/src/filters/blend.h
+++ b/src/filters/blend.h
@@ -1,10 +1,6 @@
-#ifndef SP_FEBLEND_H_SEEN
-#define SP_FEBLEND_H_SEEN
-
-/** \file
- * SVG <feBlend> implementation, see Blend.cpp.
- */
-/*
+/** @file
+ * @brief SVG blend filter effect
+ *//*
* Authors:
* Hugo Rodrigues <haa.rodrigues@gmail.com>
* Niko Kiirala <niko@kiirala.com>
@@ -14,16 +10,21 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include "sp-filter.h"
-#include "blend-fns.h"
+#ifndef SP_FEBLEND_H_SEEN
+#define SP_FEBLEND_H_SEEN
+#include "sp-filter-primitive.h"
#include "display/nr-filter-blend.h"
-/* FeBlend base class */
+#define SP_TYPE_FEBLEND (sp_feBlend_get_type())
+#define SP_FEBLEND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SP_TYPE_FEBLEND, SPFeBlend))
+#define SP_FEBLEND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), SP_TYPE_FEBLEND, SPFeBlendClass))
+#define SP_IS_FEBLEND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), SP_TYPE_FEBLEND))
+#define SP_IS_FEBLEND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), SP_TYPE_FEBLEND))
+
class SPFeBlendClass;
struct SPFeBlend : public SPFilterPrimitive {
- /** BLEND ATTRIBUTES HERE */
Inkscape::Filters::FilterBlendMode blend_mode;
int in2;
};
diff --git a/src/filters/colormatrix-fns.h b/src/filters/colormatrix-fns.h
deleted file mode 100644
index 62f7a190d..000000000
--- a/src/filters/colormatrix-fns.h
+++ /dev/null
@@ -1,38 +0,0 @@
-#ifndef SP_FECOLORMATRIX_FNS_H
-#define SP_FECOLORMATRIX_FNS_H
-
-/** \file
- * Macros and fn declarations related to gaussian blur filter.
- */
-
-#include <glib-object.h>
-#include <glib/gtypes.h>
-
-namespace Inkscape {
-namespace XML {
-class Node;
-}
-}
-
-class SPFeColorMatrix;
-
-#define SP_TYPE_FECOLORMATRIX (sp_feColorMatrix_get_type())
-#define SP_FECOLORMATRIX(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SP_TYPE_FECOLORMATRIX, SPFeColorMatrix))
-#define SP_FECOLORMATRIX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), SP_TYPE_FECOLORMATRIX, SPFeColorMatrixClass))
-#define SP_IS_FECOLORMATRIX(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), SP_TYPE_FECOLORMATRIX))
-#define SP_IS_FECOLORMATRIX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), SP_TYPE_FECOLORMATRIX))
-
-GType sp_feColorMatrix_get_type();
-
-#endif /* !SP_FECOLORMATRIX_FNS_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/filters/colormatrix.cpp b/src/filters/colormatrix.cpp
index 34e730c65..b110e2766 100644
--- a/src/filters/colormatrix.cpp
+++ b/src/filters/colormatrix.cpp
@@ -26,6 +26,7 @@
#include "xml/repr.h"
#include "helper-fns.h"
+#include "display/nr-filter.h"
#include "display/nr-filter-colormatrix.h"
/* FeColorMatrix base class */
diff --git a/src/filters/colormatrix.h b/src/filters/colormatrix.h
index 754607608..8eb750ac1 100644
--- a/src/filters/colormatrix.h
+++ b/src/filters/colormatrix.h
@@ -1,10 +1,6 @@
-#ifndef SP_FECOLORMATRIX_H_SEEN
-#define SP_FECOLORMATRIX_H_SEEN
-
-/** \file
- * SVG <feColorMatrix> implementation, see ColorMatrix.cpp.
- */
-/*
+/** @file
+ * @brief SVG color matrix filter effect
+ *//*
* Authors:
* Hugo Rodrigues <haa.rodrigues@gmail.com>
*
@@ -12,17 +8,22 @@
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
+#ifndef SP_FECOLORMATRIX_H_SEEN
+#define SP_FECOLORMATRIX_H_SEEN
-#include "sp-filter.h"
-#include "colormatrix-fns.h"
-#include "display/nr-filter-colormatrix.h"
#include <vector>
+#include "sp-filter-primitive.h"
+#include "display/nr-filter-colormatrix.h"
+
+#define SP_TYPE_FECOLORMATRIX (sp_feColorMatrix_get_type())
+#define SP_FECOLORMATRIX(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SP_TYPE_FECOLORMATRIX, SPFeColorMatrix))
+#define SP_FECOLORMATRIX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), SP_TYPE_FECOLORMATRIX, SPFeColorMatrixClass))
+#define SP_IS_FECOLORMATRIX(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), SP_TYPE_FECOLORMATRIX))
+#define SP_IS_FECOLORMATRIX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), SP_TYPE_FECOLORMATRIX))
-/* FeColorMatrix base class */
class SPFeColorMatrixClass;
struct SPFeColorMatrix : public SPFilterPrimitive {
- /** COLORMATRIX ATTRIBUTES HERE */
Inkscape::Filters::FilterColorMatrixType type;
gdouble value;
std::vector<gdouble> values;
@@ -34,7 +35,6 @@ struct SPFeColorMatrixClass {
GType sp_feColorMatrix_get_type();
-
#endif /* !SP_FECOLORMATRIX_H_SEEN */
/*
diff --git a/src/filters/componenttransfer-fns.h b/src/filters/componenttransfer-fns.h
deleted file mode 100644
index 65120fefa..000000000
--- a/src/filters/componenttransfer-fns.h
+++ /dev/null
@@ -1,38 +0,0 @@
-#ifndef SP_FECOMPONENTTRANSFER_FNS_H
-#define SP_FECOMPONENTTRANSFER_FNS_H
-
-/** \file
- * Macros and fn declarations related to gaussian blur filter.
- */
-
-#include <glib-object.h>
-#include <glib/gtypes.h>
-
-namespace Inkscape {
-namespace XML {
-class Node;
-}
-}
-
-class SPFeComponentTransfer;
-
-#define SP_TYPE_FECOMPONENTTRANSFER (sp_feComponentTransfer_get_type())
-#define SP_FECOMPONENTTRANSFER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SP_TYPE_FECOMPONENTTRANSFER, SPFeComponentTransfer))
-#define SP_FECOMPONENTTRANSFER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), SP_TYPE_FECOMPONENTTRANSFER, SPFeComponentTransferClass))
-#define SP_IS_FECOMPONENTTRANSFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), SP_TYPE_FECOMPONENTTRANSFER))
-#define SP_IS_FECOMPONENTTRANSFER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), SP_TYPE_FECOMPONENTTRANSFER))
-
-GType sp_feComponentTransfer_get_type();
-
-#endif /* !SP_FECOMPONENTTRANSFER_FNS_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/filters/componenttransfer.cpp b/src/filters/componenttransfer.cpp
index 48d9c3212..99d8616f4 100644
--- a/src/filters/componenttransfer.cpp
+++ b/src/filters/componenttransfer.cpp
@@ -21,9 +21,10 @@
#include "document.h"
#include "attributes.h"
#include "svg/svg.h"
-#include "componenttransfer.h"
-#include "componenttransfer-funcnode.h"
+#include "filters/componenttransfer.h"
+#include "filters/componenttransfer-funcnode.h"
#include "xml/repr.h"
+#include "display/nr-filter.h"
#include "display/nr-filter-component-transfer.h"
/* FeComponentTransfer base class */
diff --git a/src/filters/componenttransfer.h b/src/filters/componenttransfer.h
index 8a9c3c682..2df64009f 100644
--- a/src/filters/componenttransfer.h
+++ b/src/filters/componenttransfer.h
@@ -1,10 +1,6 @@
-#ifndef SP_FECOMPONENTTRANSFER_H_SEEN
-#define SP_FECOMPONENTTRANSFER_H_SEEN
-
-/** \file
- * SVG <feComponentTransfer> implementation, see ComponentTransfer.cpp.
- */
-/*
+/** @file
+ * @brief SVG component transferfilter effect
+ *//*
* Authors:
* Hugo Rodrigues <haa.rodrigues@gmail.com>
*
@@ -12,18 +8,25 @@
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
+#ifndef SP_FECOMPONENTTRANSFER_H_SEEN
+#define SP_FECOMPONENTTRANSFER_H_SEEN
+
+#include "sp-filter-primitive.h"
-#include "sp-filter.h"
-#include "componenttransfer-fns.h"
-#include "display/nr-filter-component-transfer.h"
-#include <vector>
+#define SP_TYPE_FECOMPONENTTRANSFER (sp_feComponentTransfer_get_type())
+#define SP_FECOMPONENTTRANSFER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SP_TYPE_FECOMPONENTTRANSFER, SPFeComponentTransfer))
+#define SP_FECOMPONENTTRANSFER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), SP_TYPE_FECOMPONENTTRANSFER, SPFeComponentTransferClass))
+#define SP_IS_FECOMPONENTTRANSFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), SP_TYPE_FECOMPONENTTRANSFER))
+#define SP_IS_FECOMPONENTTRANSFER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), SP_TYPE_FECOMPONENTTRANSFER))
+
+namespace Inkscape {
+namespace Filters {
+class FilterComponentTransfer;
+} }
-/* FeComponentTransfer base class */
class SPFeComponentTransferClass;
struct SPFeComponentTransfer : public SPFilterPrimitive {
- /** COMPONENTTRANSFER ATTRIBUTES HERE */
-
Inkscape::Filters::FilterComponentTransfer *renderer;
};
diff --git a/src/filters/composite-fns.h b/src/filters/composite-fns.h
deleted file mode 100644
index 04530b152..000000000
--- a/src/filters/composite-fns.h
+++ /dev/null
@@ -1,38 +0,0 @@
-#ifndef SP_FECOMPOSITE_FNS_H
-#define SP_FECOMPOSITE_FNS_H
-
-/** \file
- * Macros and fn declarations related to gaussian blur filter.
- */
-
-#include <glib-object.h>
-#include <glib/gtypes.h>
-
-namespace Inkscape {
-namespace XML {
-class Node;
-}
-}
-
-class SPFeComposite;
-
-#define SP_TYPE_FECOMPOSITE (sp_feComposite_get_type())
-#define SP_FECOMPOSITE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SP_TYPE_FECOMPOSITE, SPFeComposite))
-#define SP_FECOMPOSITE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), SP_TYPE_FECOMPOSITE, SPFeCompositeClass))
-#define SP_IS_FECOMPOSITE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), SP_TYPE_FECOMPOSITE))
-#define SP_IS_FECOMPOSITE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), SP_TYPE_FECOMPOSITE))
-
-GType sp_feComposite_get_type();
-
-#endif /* !SP_FECOMPOSITE_FNS_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/filters/composite.cpp b/src/filters/composite.cpp
index c2b47c4c2..66e8e3415 100644
--- a/src/filters/composite.cpp
+++ b/src/filters/composite.cpp
@@ -18,10 +18,12 @@
#include "attributes.h"
#include "svg/svg.h"
-#include "composite.h"
+#include "filters/composite.h"
#include "helper-fns.h"
#include "xml/repr.h"
+#include "display/nr-filter.h"
#include "display/nr-filter-composite.h"
+#include "sp-filter.h"
/* FeComposite base class */
diff --git a/src/filters/composite.h b/src/filters/composite.h
index 0fa1b5665..3eb62716f 100644
--- a/src/filters/composite.h
+++ b/src/filters/composite.h
@@ -1,10 +1,6 @@
-#ifndef SP_FECOMPOSITE_H_SEEN
-#define SP_FECOMPOSITE_H_SEEN
-
-/** \file
- * SVG <feComposite> implementation, see Composite.cpp.
- */
-/*
+/** @file
+ * @brief SVG composite filter effect
+ *//*
* Authors:
* Hugo Rodrigues <haa.rodrigues@gmail.com>
*
@@ -12,9 +8,16 @@
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
+#ifndef SP_FECOMPOSITE_H_SEEN
+#define SP_FECOMPOSITE_H_SEEN
-#include "sp-filter.h"
-#include "composite-fns.h"
+#include "sp-filter-primitive.h"
+
+#define SP_TYPE_FECOMPOSITE (sp_feComposite_get_type())
+#define SP_FECOMPOSITE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SP_TYPE_FECOMPOSITE, SPFeComposite))
+#define SP_FECOMPOSITE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), SP_TYPE_FECOMPOSITE, SPFeCompositeClass))
+#define SP_IS_FECOMPOSITE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), SP_TYPE_FECOMPOSITE))
+#define SP_IS_FECOMPOSITE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), SP_TYPE_FECOMPOSITE))
enum FeCompositeOperator {
// Default value is 'over', but let's distinquish specifying the
@@ -29,7 +32,6 @@ enum FeCompositeOperator {
COMPOSITE_ENDOPERATOR
};
-/* FeComposite base class */
class SPFeCompositeClass;
struct SPFeComposite : public SPFilterPrimitive {
@@ -44,7 +46,6 @@ struct SPFeCompositeClass {
GType sp_feComposite_get_type();
-
#endif /* !SP_FECOMPOSITE_H_SEEN */
/*
diff --git a/src/filters/convolvematrix-fns.h b/src/filters/convolvematrix-fns.h
deleted file mode 100644
index f6a4c846a..000000000
--- a/src/filters/convolvematrix-fns.h
+++ /dev/null
@@ -1,38 +0,0 @@
-#ifndef SP_FECONVOLVEMATRIX_FNS_H
-#define SP_FECONVOLVEMATRIX_FNS_H
-
-/** \file
- * Macros and fn declarations related to gaussian blur filter.
- */
-
-#include <glib-object.h>
-#include <glib/gtypes.h>
-
-namespace Inkscape {
-namespace XML {
-class Node;
-}
-}
-
-class SPFeConvolveMatrix;
-
-#define SP_TYPE_FECONVOLVEMATRIX (sp_feConvolveMatrix_get_type())
-#define SP_FECONVOLVEMATRIX(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SP_TYPE_FECONVOLVEMATRIX, SPFeConvolveMatrix))
-#define SP_FECONVOLVEMATRIX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), SP_TYPE_FECONVOLVEMATRIX, SPFeConvolveMatrixClass))
-#define SP_IS_FECONVOLVEMATRIX(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), SP_TYPE_FECONVOLVEMATRIX))
-#define SP_IS_FECONVOLVEMATRIX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), SP_TYPE_FECONVOLVEMATRIX))
-
-GType sp_feConvolveMatrix_get_type();
-
-#endif /* !SP_FECONVOLVEMATRIX_FNS_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/filters/convolvematrix.cpp b/src/filters/convolvematrix.cpp
index 99c6ca413..20d652bee 100644
--- a/src/filters/convolvematrix.cpp
+++ b/src/filters/convolvematrix.cpp
@@ -18,15 +18,15 @@
#endif
#include <string.h>
-
+#include <math.h>
#include <vector>
#include "attributes.h"
#include "svg/svg.h"
-#include "convolvematrix.h"
+#include "filters/convolvematrix.h"
#include "helper-fns.h"
#include "xml/repr.h"
+#include "display/nr-filter.h"
#include "display/nr-filter-convolve-matrix.h"
-#include <math.h>
/* FeConvolveMatrix base class */
diff --git a/src/filters/convolvematrix.h b/src/filters/convolvematrix.h
index 1d085fd6c..4c5261e05 100644
--- a/src/filters/convolvematrix.h
+++ b/src/filters/convolvematrix.h
@@ -1,8 +1,5 @@
-#ifndef SP_FECONVOLVEMATRIX_H_SEEN
-#define SP_FECONVOLVEMATRIX_H_SEEN
-
-/** \file
- * SVG <feConvolveMatrix> implementation, see ConvolveMatrix.cpp.
+/** @file
+ * @brief SVG matrix convolution filter effect
*/
/*
* Authors:
@@ -13,18 +10,23 @@
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
+#ifndef SP_FECONVOLVEMATRIX_H_SEEN
+#define SP_FECONVOLVEMATRIX_H_SEEN
-#include "sp-filter.h"
-#include "convolvematrix-fns.h"
+#include <vector>
+#include "sp-filter-primitive.h"
#include "number-opt-number.h"
#include "display/nr-filter-convolve-matrix.h"
-#include <vector>
-/* FeConvolveMatrix base class */
+#define SP_TYPE_FECONVOLVEMATRIX (sp_feConvolveMatrix_get_type())
+#define SP_FECONVOLVEMATRIX(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SP_TYPE_FECONVOLVEMATRIX, SPFeConvolveMatrix))
+#define SP_FECONVOLVEMATRIX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), SP_TYPE_FECONVOLVEMATRIX, SPFeConvolveMatrixClass))
+#define SP_IS_FECONVOLVEMATRIX(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), SP_TYPE_FECONVOLVEMATRIX))
+#define SP_IS_FECONVOLVEMATRIX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), SP_TYPE_FECONVOLVEMATRIX))
+
class SPFeConvolveMatrixClass;
struct SPFeConvolveMatrix : public SPFilterPrimitive {
- /* CONVOLVEMATRIX ATTRIBUTES */
NumberOptNumber order;
std::vector<gdouble> kernelMatrix;
double divisor, bias;
@@ -32,7 +34,7 @@ struct SPFeConvolveMatrix : public SPFilterPrimitive {
Inkscape::Filters::FilterConvolveMatrixEdgeMode edgeMode;
NumberOptNumber kernelUnitLength;
bool preserveAlpha;
- //some helper variables:
+
bool targetXIsSet;
bool targetYIsSet;
bool divisorIsSet;
@@ -45,7 +47,6 @@ struct SPFeConvolveMatrixClass {
GType sp_feConvolveMatrix_get_type();
-
#endif /* !SP_FECONVOLVEMATRIX_H_SEEN */
/*
diff --git a/src/filters/diffuselighting-fns.h b/src/filters/diffuselighting-fns.h
deleted file mode 100644
index 27ea77358..000000000
--- a/src/filters/diffuselighting-fns.h
+++ /dev/null
@@ -1,38 +0,0 @@
-#ifndef SP_FEDIFFUSELIGHTING_FNS_H
-#define SP_FEDIFFUSELIGHTING_FNS_H
-
-/** \file
- * Macros and fn declarations related to gaussian blur filter.
- */
-
-#include <glib-object.h>
-#include <glib/gtypes.h>
-
-namespace Inkscape {
-namespace XML {
-class Node;
-}
-}
-
-class SPFeDiffuseLighting;
-
-#define SP_TYPE_FEDIFFUSELIGHTING (sp_feDiffuseLighting_get_type())
-#define SP_FEDIFFUSELIGHTING(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SP_TYPE_FEDIFFUSELIGHTING, SPFeDiffuseLighting))
-#define SP_FEDIFFUSELIGHTING_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), SP_TYPE_FEDIFFUSELIGHTING, SPFeDiffuseLightingClass))
-#define SP_IS_FEDIFFUSELIGHTING(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), SP_TYPE_FEDIFFUSELIGHTING))
-#define SP_IS_FEDIFFUSELIGHTING_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), SP_TYPE_FEDIFFUSELIGHTING))
-
-GType sp_feDiffuseLighting_get_type();
-
-#endif /* !SP_FEDIFFUSELIGHTING_FNS_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/filters/diffuselighting.cpp b/src/filters/diffuselighting.cpp
index 5c55a3d20..0f2f29d67 100644
--- a/src/filters/diffuselighting.cpp
+++ b/src/filters/diffuselighting.cpp
@@ -22,7 +22,11 @@
#include "svg/svg.h"
#include "sp-object.h"
#include "svg/svg-color.h"
-#include "diffuselighting.h"
+#include "filters/diffuselighting.h"
+#include "filters/distantlight.h"
+#include "filters/pointlight.h"
+#include "filters/spotlight.h"
+#include "display/nr-filter.h"
#include "xml/repr.h"
#include "display/nr-filter-diffuselighting.h"
diff --git a/src/filters/diffuselighting.h b/src/filters/diffuselighting.h
index 7f0d8bc7a..a23346622 100644
--- a/src/filters/diffuselighting.h
+++ b/src/filters/diffuselighting.h
@@ -1,46 +1,46 @@
-#ifndef SP_FEDIFFUSELIGHTING_H_SEEN
-#define SP_FEDIFFUSELIGHTING_H_SEEN
-
-/** \file
- * SVG <feDiffuseLighting> implementation, see DiffuseLighting.cpp.
- */
-/*
+/** @file
+ * @brief SVG diffuse lighting filter effect
+ *//*
* Authors:
* Hugo Rodrigues <haa.rodrigues@gmail.com>
* Jean-Rene Reinhard <jr@komite.net>
*
- * Copyright (C) 2006 Hugo Rodrigues
- * 2007 authors
- *
+ * Copyright (C) 2006-2007 Authors
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include "sp-filter.h"
-#include "diffuselighting-fns.h"
+#ifndef SP_FEDIFFUSELIGHTING_H_SEEN
+#define SP_FEDIFFUSELIGHTING_H_SEEN
+
+#include "sp-filter-primitive.h"
+#include "number-opt-number.h"
namespace Inkscape {
namespace Filters {
class FilterDiffuseLighting;
-}
-}
+} }
+
+#define SP_TYPE_FEDIFFUSELIGHTING (sp_feDiffuseLighting_get_type())
+#define SP_FEDIFFUSELIGHTING(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SP_TYPE_FEDIFFUSELIGHTING, SPFeDiffuseLighting))
+#define SP_FEDIFFUSELIGHTING_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), SP_TYPE_FEDIFFUSELIGHTING, SPFeDiffuseLightingClass))
+#define SP_IS_FEDIFFUSELIGHTING(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), SP_TYPE_FEDIFFUSELIGHTING))
+#define SP_IS_FEDIFFUSELIGHTING_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), SP_TYPE_FEDIFFUSELIGHTING))
+
+namespace Inkscape {
+namespace Filters {
+class FilterDiffuseLighting;
+} }
-/* FeDiffuseLighting base class */
class SPFeDiffuseLightingClass;
struct SPFeDiffuseLighting : public SPFilterPrimitive {
- /** DIFFUSELIGHTING ATTRIBUTES HERE */
- /** surfaceScale attribute */
gfloat surfaceScale;
guint surfaceScale_set : 1;
- /** diffuseConstant attribute */
gfloat diffuseConstant;
guint diffuseConstant_set : 1;
- /** kernelUnitLength attribute */
NumberOptNumber kernelUnitLength;
- /** lighting-color property */
guint32 lighting_color;
guint lighting_color_set : 1;
- /** pointer to the associated renderer */
Inkscape::Filters::FilterDiffuseLighting *renderer;
};
@@ -50,7 +50,6 @@ struct SPFeDiffuseLightingClass {
GType sp_feDiffuseLighting_get_type();
-
#endif /* !SP_FEDIFFUSELIGHTING_H_SEEN */
/*
diff --git a/src/filters/displacementmap-fns.h b/src/filters/displacementmap-fns.h
deleted file mode 100644
index 2fc115bb8..000000000
--- a/src/filters/displacementmap-fns.h
+++ /dev/null
@@ -1,38 +0,0 @@
-#ifndef SP_FEDISPLACEMENTMAP_FNS_H
-#define SP_FEDISPLACEMENTMAP_FNS_H
-
-/** \file
- * Macros and fn declarations related to gaussian blur filter.
- */
-
-#include <glib-object.h>
-#include <glib/gtypes.h>
-
-namespace Inkscape {
-namespace XML {
-class Node;
-}
-}
-
-class SPFeDisplacementMap;
-
-#define SP_TYPE_FEDISPLACEMENTMAP (sp_feDisplacementMap_get_type())
-#define SP_FEDISPLACEMENTMAP(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SP_TYPE_FEDISPLACEMENTMAP, SPFeDisplacementMap))
-#define SP_FEDISPLACEMENTMAP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), SP_TYPE_FEDISPLACEMENTMAP, SPFeDisplacementMapClass))
-#define SP_IS_FEDISPLACEMENTMAP(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), SP_TYPE_FEDISPLACEMENTMAP))
-#define SP_IS_FEDISPLACEMENTMAP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), SP_TYPE_FEDISPLACEMENTMAP))
-
-GType sp_feDisplacementMap_get_type();
-
-#endif /* !SP_FEDISPLACEMENTMAP_FNS_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/filters/displacementmap.cpp b/src/filters/displacementmap.cpp
index a6ad8b81a..69a678c26 100644
--- a/src/filters/displacementmap.cpp
+++ b/src/filters/displacementmap.cpp
@@ -18,10 +18,12 @@
#include "attributes.h"
#include "svg/svg.h"
-#include "displacementmap.h"
+#include "filters/displacementmap.h"
#include "xml/repr.h"
-#include "display/nr-filter-displacement-map.h"
+#include "sp-filter.h"
#include "helper-fns.h"
+#include "display/nr-filter.h"
+#include "display/nr-filter-displacement-map.h"
/* FeDisplacementMap base class */
diff --git a/src/filters/displacementmap.h b/src/filters/displacementmap.h
index f3c596f11..6232f0937 100644
--- a/src/filters/displacementmap.h
+++ b/src/filters/displacementmap.h
@@ -1,10 +1,6 @@
-#ifndef SP_FEDISPLACEMENTMAP_H_SEEN
-#define SP_FEDISPLACEMENTMAP_H_SEEN
-
/** \file
- * SVG <feDisplacementMap> implementation, see DisplacementMap.cpp.
- */
-/*
+ * SVG displacement map filter effect
+ *//*
* Authors:
* Hugo Rodrigues <haa.rodrigues@gmail.com>
*
@@ -13,8 +9,16 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include "sp-filter.h"
-#include "displacementmap-fns.h"
+#ifndef SP_FEDISPLACEMENTMAP_H_SEEN
+#define SP_FEDISPLACEMENTMAP_H_SEEN
+
+#include "sp-filter-primitive.h"
+
+#define SP_TYPE_FEDISPLACEMENTMAP (sp_feDisplacementMap_get_type())
+#define SP_FEDISPLACEMENTMAP(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SP_TYPE_FEDISPLACEMENTMAP, SPFeDisplacementMap))
+#define SP_FEDISPLACEMENTMAP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), SP_TYPE_FEDISPLACEMENTMAP, SPFeDisplacementMapClass))
+#define SP_IS_FEDISPLACEMENTMAP(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), SP_TYPE_FEDISPLACEMENTMAP))
+#define SP_IS_FEDISPLACEMENTMAP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), SP_TYPE_FEDISPLACEMENTMAP))
enum FilterDisplacementMapChannelSelector {
DISPLACEMENTMAP_CHANNEL_RED,
@@ -24,11 +28,9 @@ enum FilterDisplacementMapChannelSelector {
DISPLACEMENTMAP_CHANNEL_ENDTYPE
};
-/* FeDisplacementMap base class */
class SPFeDisplacementMapClass;
struct SPFeDisplacementMap : public SPFilterPrimitive {
- /** DISPLACEMENTMAP ATTRIBUTES HERE */
int in2;
double scale;
FilterDisplacementMapChannelSelector xChannelSelector;
@@ -41,7 +43,6 @@ struct SPFeDisplacementMapClass {
GType sp_feDisplacementMap_get_type();
-
#endif /* !SP_FEDISPLACEMENTMAP_H_SEEN */
/*
diff --git a/src/filters/distantlight.cpp b/src/filters/distantlight.cpp
index 88c2a21ff..891049415 100644
--- a/src/filters/distantlight.cpp
+++ b/src/filters/distantlight.cpp
@@ -21,9 +21,9 @@
#include "attributes.h"
#include "document.h"
-#include "distantlight.h"
-#include "diffuselighting-fns.h"
-#include "specularlighting-fns.h"
+#include "filters/distantlight.h"
+#include "filters/diffuselighting.h"
+#include "filters/specularlighting.h"
#include "xml/repr.h"
#define SP_MACROS_SILENT
diff --git a/src/filters/flood-fns.h b/src/filters/flood-fns.h
deleted file mode 100644
index 55130a7ba..000000000
--- a/src/filters/flood-fns.h
+++ /dev/null
@@ -1,38 +0,0 @@
-#ifndef SP_FEFLOOD_FNS_H
-#define SP_FEFLOOD_FNS_H
-
-/** \file
- * Macros and fn declarations related to gaussian blur filter.
- */
-
-#include <glib-object.h>
-#include <glib/gtypes.h>
-
-namespace Inkscape {
-namespace XML {
-class Node;
-}
-}
-
-class SPFeFlood;
-
-#define SP_TYPE_FEFLOOD (sp_feFlood_get_type())
-#define SP_FEFLOOD(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SP_TYPE_FEFLOOD, SPFeFlood))
-#define SP_FEFLOOD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), SP_TYPE_FEFLOOD, SPFeFloodClass))
-#define SP_IS_FEFLOOD(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), SP_TYPE_FEFLOOD))
-#define SP_IS_FEFLOOD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), SP_TYPE_FEFLOOD))
-
-GType sp_feFlood_get_type();
-
-#endif /* !SP_FEFLOOD_FNS_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/filters/flood.cpp b/src/filters/flood.cpp
index 741c9e984..3de1eb527 100644
--- a/src/filters/flood.cpp
+++ b/src/filters/flood.cpp
@@ -20,9 +20,12 @@
#include "attributes.h"
#include "svg/svg.h"
-#include "flood.h"
+#include "svg/svg-color.h"
+#include "filters/flood.h"
#include "xml/repr.h"
#include "helper-fns.h"
+#include "display/nr-filter.h"
+#include "display/nr-filter-flood.h"
/* FeFlood base class */
diff --git a/src/filters/flood.h b/src/filters/flood.h
index 66b5dd96a..0083def70 100644
--- a/src/filters/flood.h
+++ b/src/filters/flood.h
@@ -1,10 +1,6 @@
-#ifndef SP_FEFLOOD_H_SEEN
-#define SP_FEFLOOD_H_SEEN
-
-/** \file
- * SVG <feFlood> implementation, see Flood.cpp.
- */
-/*
+/** @file
+ * @brief SVG flood filter effect
+ *//*
* Authors:
* Hugo Rodrigues <haa.rodrigues@gmail.com>
*
@@ -13,18 +9,21 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include "sp-filter.h"
-#include "flood-fns.h"
+#ifndef SP_FEFLOOD_H_SEEN
+#define SP_FEFLOOD_H_SEEN
+
+#include "sp-filter-primitive.h"
#include "svg/svg-icc-color.h"
-#include "display/nr-filter.h"
-#include "display/nr-filter-flood.h"
+#define SP_TYPE_FEFLOOD (sp_feFlood_get_type())
+#define SP_FEFLOOD(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SP_TYPE_FEFLOOD, SPFeFlood))
+#define SP_FEFLOOD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), SP_TYPE_FEFLOOD, SPFeFloodClass))
+#define SP_IS_FEFLOOD(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), SP_TYPE_FEFLOOD))
+#define SP_IS_FEFLOOD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), SP_TYPE_FEFLOOD))
-/* FeFlood base class */
class SPFeFloodClass;
struct SPFeFlood : public SPFilterPrimitive {
- /** FLOOD ATTRIBUTES HERE */
guint32 color;
SVGICCColor *icc;
double opacity;
diff --git a/src/sp-gaussian-blur.cpp b/src/filters/gaussian-blur.cpp
index 3786d9094..ee1af8904 100644
--- a/src/sp-gaussian-blur.cpp
+++ b/src/filters/gaussian-blur.cpp
@@ -19,7 +19,7 @@
#include "attributes.h"
#include "svg/svg.h"
-#include "sp-gaussian-blur.h"
+#include "filters/gaussian-blur.h"
#include "xml/repr.h"
#include "display/nr-filter.h"
diff --git a/src/sp-gaussian-blur-fns.h b/src/filters/gaussian-blur.h
index ab2c851cf..417f8a6f4 100644
--- a/src/sp-gaussian-blur-fns.h
+++ b/src/filters/gaussian-blur.h
@@ -1,20 +1,19 @@
-#ifndef SP_GAUSSIANBLUR_FNS_H
-#define SP_GAUSSIANBLUR_FNS_H
-
-/** \file
- * Macros and fn declarations related to gaussian blur filter.
+/** @file
+ * @brief SVG Gaussian blur filter effect
+ *//*
+ * Authors:
+ * Hugo Rodrigues <haa.rodrigues@gmail.com>
+ *
+ * Copyright (C) 2006 Hugo Rodrigues
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include <glib-object.h>
-#include <glib/gtypes.h>
-
-namespace Inkscape {
-namespace XML {
-class Node;
-}
-}
+#ifndef SP_GAUSSIANBLUR_H_SEEN
+#define SP_GAUSSIANBLUR_H_SEEN
-class SPGaussianBlur;
+#include "sp-filter-primitive.h"
+#include "number-opt-number.h"
#define SP_TYPE_GAUSSIANBLUR (sp_gaussianBlur_get_type())
#define SP_GAUSSIANBLUR(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SP_TYPE_GAUSSIANBLUR, SPGaussianBlur))
@@ -22,11 +21,23 @@ class SPGaussianBlur;
#define SP_IS_GAUSSIANBLUR(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), SP_TYPE_GAUSSIANBLUR))
#define SP_IS_GAUSSIANBLUR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), SP_TYPE_GAUSSIANBLUR))
+/* GaussianBlur base class */
+class SPGaussianBlurClass;
+
+struct SPGaussianBlur : public SPFilterPrimitive {
+ /** stdDeviation attribute */
+ NumberOptNumber stdDeviation;
+};
+
+struct SPGaussianBlurClass {
+ SPFilterPrimitiveClass parent_class;
+};
+
GType sp_gaussianBlur_get_type();
void sp_gaussianBlur_setDeviation(SPGaussianBlur *blur, float num);
void sp_gaussianBlur_setDeviation(SPGaussianBlur *blur, float num, float optnum);
-#endif /* !SP_GAUSSIANBLUR_FNS_H */
+#endif /* !SP_GAUSSIANBLUR_H_SEEN */
/*
Local Variables:
diff --git a/src/filters/image-fns.h b/src/filters/image-fns.h
deleted file mode 100644
index d9de38342..000000000
--- a/src/filters/image-fns.h
+++ /dev/null
@@ -1,38 +0,0 @@
-#ifndef SP_FEIMAGE_FNS_H
-#define SP_FEIMAGE_FNS_H
-
-/** \file
- * Macros and fn declarations related to gaussian blur filter.
- */
-
-#include <glib-object.h>
-#include <glib/gtypes.h>
-
-namespace Inkscape {
-namespace XML {
-class Node;
-}
-}
-
-class SPFeImage;
-
-#define SP_TYPE_FEIMAGE (sp_feImage_get_type())
-#define SP_FEIMAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SP_TYPE_FEIMAGE, SPFeImage))
-#define SP_FEIMAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), SP_TYPE_FEIMAGE, SPFeImageClass))
-#define SP_IS_FEIMAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), SP_TYPE_FEIMAGE))
-#define SP_IS_FEIMAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), SP_TYPE_FEIMAGE))
-
-GType sp_feImage_get_type();
-
-#endif /* !SP_FEIMAGE_FNS_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/filters/image.h b/src/filters/image.h
index 535dd80fa..b4081602a 100644
--- a/src/filters/image.h
+++ b/src/filters/image.h
@@ -1,10 +1,6 @@
-#ifndef SP_FEIMAGE_H_SEEN
-#define SP_FEIMAGE_H_SEEN
-
-/** \file
- * SVG <feImage> implementation, see Image.cpp.
- */
-/*
+/** @file
+ * @brief SVG image filter effect
+ *//*
* Authors:
* Felipe CorrĂȘa da Silva Sanches <juca@members.fsf.org>
* Hugo Rodrigues <haa.rodrigues@gmail.com>
@@ -14,17 +10,23 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include "sp-filter.h"
-#include "image-fns.h"
+#ifndef SP_FEIMAGE_H_SEEN
+#define SP_FEIMAGE_H_SEEN
+
+#include "sp-filter-primitive.h"
#include "svg/svg-length.h"
#include "sp-item.h"
#include "uri-references.h"
-/* FeImage base class */
+#define SP_TYPE_FEIMAGE (sp_feImage_get_type())
+#define SP_FEIMAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SP_TYPE_FEIMAGE, SPFeImage))
+#define SP_FEIMAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), SP_TYPE_FEIMAGE, SPFeImageClass))
+#define SP_IS_FEIMAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), SP_TYPE_FEIMAGE))
+#define SP_IS_FEIMAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), SP_TYPE_FEIMAGE))
+
class SPFeImageClass;
struct SPFeImage : public SPFilterPrimitive {
- /** IMAGE ATTRIBUTES HERE */
gchar *href;
/* preserveAspectRatio */
@@ -45,7 +47,6 @@ struct SPFeImageClass {
GType sp_feImage_get_type();
-
#endif /* !SP_FEIMAGE_H_SEEN */
/*
diff --git a/src/filters/merge-fns.h b/src/filters/merge-fns.h
deleted file mode 100644
index e3674a391..000000000
--- a/src/filters/merge-fns.h
+++ /dev/null
@@ -1,38 +0,0 @@
-#ifndef SP_FEMERGE_FNS_H
-#define SP_FEMERGE_FNS_H
-
-/** \file
- * Macros and fn declarations related to gaussian blur filter.
- */
-
-#include <glib-object.h>
-#include <glib/gtypes.h>
-
-namespace Inkscape {
-namespace XML {
-class Node;
-}
-}
-
-class SPFeMerge;
-
-#define SP_TYPE_FEMERGE (sp_feMerge_get_type())
-#define SP_FEMERGE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SP_TYPE_FEMERGE, SPFeMerge))
-#define SP_FEMERGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), SP_TYPE_FEMERGE, SPFeMergeClass))
-#define SP_IS_FEMERGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), SP_TYPE_FEMERGE))
-#define SP_IS_FEMERGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), SP_TYPE_FEMERGE))
-
-GType sp_feMerge_get_type();
-
-#endif /* !SP_FEMERGE_FNS_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/filters/merge.cpp b/src/filters/merge.cpp
index 226c82a72..47830c38b 100644
--- a/src/filters/merge.cpp
+++ b/src/filters/merge.cpp
@@ -23,6 +23,7 @@
#include "merge.h"
#include "mergenode.h"
+#include "display/nr-filter.h"
#include "display/nr-filter-merge.h"
/* FeMerge base class */
diff --git a/src/filters/merge.h b/src/filters/merge.h
index 93374d134..3243073ca 100644
--- a/src/filters/merge.h
+++ b/src/filters/merge.h
@@ -1,22 +1,23 @@
-#ifndef SP_FEMERGE_H_SEEN
-#define SP_FEMERGE_H_SEEN
-
/** \file
- * SVG <feMerge> implementation, see Merge.cpp.
- */
-/*
+ * SVG merge filter effect
+ *//*
* Authors:
* Hugo Rodrigues <haa.rodrigues@gmail.com>
*
* Copyright (C) 2006 Hugo Rodrigues
- *
* Released under GNU GPL, read the file 'COPYING' for more information
*/
+#ifndef SP_FEMERGE_H_SEEN
+#define SP_FEMERGE_H_SEEN
+
+#include "sp-filter-primitive.h"
-#include "sp-filter.h"
-#include "merge-fns.h"
+#define SP_TYPE_FEMERGE (sp_feMerge_get_type())
+#define SP_FEMERGE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SP_TYPE_FEMERGE, SPFeMerge))
+#define SP_FEMERGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), SP_TYPE_FEMERGE, SPFeMergeClass))
+#define SP_IS_FEMERGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), SP_TYPE_FEMERGE))
+#define SP_IS_FEMERGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), SP_TYPE_FEMERGE))
-/* FeMerge base class */
class SPFeMergeClass;
struct SPFeMerge : public SPFilterPrimitive {
diff --git a/src/filters/mergenode.cpp b/src/filters/mergenode.cpp
index b2aea5cca..639928305 100644
--- a/src/filters/mergenode.cpp
+++ b/src/filters/mergenode.cpp
@@ -19,8 +19,9 @@
#include "attributes.h"
#include "xml/repr.h"
-#include "mergenode.h"
-#include "merge.h"
+#include "filters/mergenode.h"
+#include "filters/merge.h"
+#include "display/nr-filter-types.h"
static void sp_feMergeNode_class_init(SPFeMergeNodeClass *klass);
static void sp_feMergeNode_init(SPFeMergeNode *skeleton);
diff --git a/src/filters/morphology-fns.h b/src/filters/morphology-fns.h
deleted file mode 100644
index dd023b607..000000000
--- a/src/filters/morphology-fns.h
+++ /dev/null
@@ -1,38 +0,0 @@
-#ifndef SP_FEMORPHOLOGY_FNS_H
-#define SP_FEMORPHOLOGY_FNS_H
-
-/** \file
- * Macros and fn declarations related to gaussian blur filter.
- */
-
-#include <glib-object.h>
-#include <glib/gtypes.h>
-
-namespace Inkscape {
-namespace XML {
-class Node;
-}
-}
-
-class SPFeMorphology;
-
-#define SP_TYPE_FEMORPHOLOGY (sp_feMorphology_get_type())
-#define SP_FEMORPHOLOGY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SP_TYPE_FEMORPHOLOGY, SPFeMorphology))
-#define SP_FEMORPHOLOGY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), SP_TYPE_FEMORPHOLOGY, SPFeMorphologyClass))
-#define SP_IS_FEMORPHOLOGY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), SP_TYPE_FEMORPHOLOGY))
-#define SP_IS_FEMORPHOLOGY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), SP_TYPE_FEMORPHOLOGY))
-
-GType sp_feMorphology_get_type();
-
-#endif /* !SP_FEMORPHOLOGY_FNS_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/filters/morphology.cpp b/src/filters/morphology.cpp
index c6a7f9993..42327d59f 100644
--- a/src/filters/morphology.cpp
+++ b/src/filters/morphology.cpp
@@ -23,6 +23,7 @@
#include "svg/svg.h"
#include "morphology.h"
#include "xml/repr.h"
+#include "display/nr-filter.h"
#include "display/nr-filter-morphology.h"
/* FeMorphology base class */
diff --git a/src/filters/morphology.h b/src/filters/morphology.h
index 4a493d16c..b7005a3d9 100644
--- a/src/filters/morphology.h
+++ b/src/filters/morphology.h
@@ -1,10 +1,6 @@
-#ifndef SP_FEMORPHOLOGY_H_SEEN
-#define SP_FEMORPHOLOGY_H_SEEN
-
/** \file
- * SVG <feMorphology> implementation, see Morphology.cpp.
- */
-/*
+ * @brief SVG morphology filter effect
+ *//*
* Authors:
* Hugo Rodrigues <haa.rodrigues@gmail.com>
*
@@ -13,18 +9,22 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include "sp-filter.h"
-#include "morphology-fns.h"
+#ifndef SP_FEMORPHOLOGY_H_SEEN
+#define SP_FEMORPHOLOGY_H_SEEN
+
+#include "sp-filter-primitive.h"
#include "number-opt-number.h"
-#include "display/nr-filter.h"
#include "display/nr-filter-morphology.h"
+#define SP_TYPE_FEMORPHOLOGY (sp_feMorphology_get_type())
+#define SP_FEMORPHOLOGY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SP_TYPE_FEMORPHOLOGY, SPFeMorphology))
+#define SP_FEMORPHOLOGY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), SP_TYPE_FEMORPHOLOGY, SPFeMorphologyClass))
+#define SP_IS_FEMORPHOLOGY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), SP_TYPE_FEMORPHOLOGY))
+#define SP_IS_FEMORPHOLOGY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), SP_TYPE_FEMORPHOLOGY))
-/* FeMorphology base class */
class SPFeMorphologyClass;
struct SPFeMorphology : public SPFilterPrimitive {
- /** MORPHOLOGY ATTRIBUTES HERE */
Inkscape::Filters::FilterMorphologyOperator Operator;
NumberOptNumber radius;
};
diff --git a/src/filters/offset-fns.h b/src/filters/offset-fns.h
deleted file mode 100644
index d9d2a2fc4..000000000
--- a/src/filters/offset-fns.h
+++ /dev/null
@@ -1,38 +0,0 @@
-#ifndef SP_FEOFFSET_FNS_H
-#define SP_FEOFFSET_FNS_H
-
-/** \file
- * Macros and fn declarations related to gaussian blur filter.
- */
-
-#include <glib-object.h>
-#include <glib/gtypes.h>
-
-namespace Inkscape {
-namespace XML {
-class Node;
-}
-}
-
-class SPFeOffset;
-
-#define SP_TYPE_FEOFFSET (sp_feOffset_get_type())
-#define SP_FEOFFSET(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SP_TYPE_FEOFFSET, SPFeOffset))
-#define SP_FEOFFSET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), SP_TYPE_FEOFFSET, SPFeOffsetClass))
-#define SP_IS_FEOFFSET(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), SP_TYPE_FEOFFSET))
-#define SP_IS_FEOFFSET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), SP_TYPE_FEOFFSET))
-
-GType sp_feOffset_get_type();
-
-#endif /* !SP_FEOFFSET_FNS_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/filters/offset.cpp b/src/filters/offset.cpp
index 263e5bf06..f45169aba 100644
--- a/src/filters/offset.cpp
+++ b/src/filters/offset.cpp
@@ -19,9 +19,10 @@
#include "attributes.h"
#include "svg/svg.h"
-#include "offset.h"
+#include "filters/offset.h"
#include "helper-fns.h"
#include "xml/repr.h"
+#include "display/nr-filter.h"
#include "display/nr-filter-offset.h"
/* FeOffset base class */
diff --git a/src/filters/offset.h b/src/filters/offset.h
index 49f8108ef..dba7ed8ef 100644
--- a/src/filters/offset.h
+++ b/src/filters/offset.h
@@ -1,10 +1,6 @@
-#ifndef SP_FEOFFSET_H_SEEN
-#define SP_FEOFFSET_H_SEEN
-
-/** \file
- * SVG <feOffset> implementation, see Offset.cpp.
- */
-/*
+/** @file
+ * @brief SVG offset filter effect
+ *//*
* Authors:
* Hugo Rodrigues <haa.rodrigues@gmail.com>
*
@@ -13,14 +9,20 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include "sp-filter.h"
-#include "offset-fns.h"
+#ifndef SP_FEOFFSET_H_SEEN
+#define SP_FEOFFSET_H_SEEN
+
+#include "sp-filter-primitive.h"
+
+#define SP_TYPE_FEOFFSET (sp_feOffset_get_type())
+#define SP_FEOFFSET(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SP_TYPE_FEOFFSET, SPFeOffset))
+#define SP_FEOFFSET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), SP_TYPE_FEOFFSET, SPFeOffsetClass))
+#define SP_IS_FEOFFSET(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), SP_TYPE_FEOFFSET))
+#define SP_IS_FEOFFSET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), SP_TYPE_FEOFFSET))
-/* FeOffset base class */
class SPFeOffsetClass;
struct SPFeOffset : public SPFilterPrimitive {
- /** OFFSET ATTRIBUTES HERE */
double dx, dy;
};
diff --git a/src/filters/pointlight.cpp b/src/filters/pointlight.cpp
index 28b3ee165..ee6824d00 100644
--- a/src/filters/pointlight.cpp
+++ b/src/filters/pointlight.cpp
@@ -21,9 +21,9 @@
#include "attributes.h"
#include "document.h"
-#include "pointlight.h"
-#include "diffuselighting-fns.h"
-#include "specularlighting-fns.h"
+#include "filters/pointlight.h"
+#include "filters/diffuselighting.h"
+#include "filters/specularlighting.h"
#include "xml/repr.h"
#define SP_MACROS_SILENT
diff --git a/src/filters/specularlighting-fns.h b/src/filters/specularlighting-fns.h
deleted file mode 100644
index 9fd5f46b3..000000000
--- a/src/filters/specularlighting-fns.h
+++ /dev/null
@@ -1,38 +0,0 @@
-#ifndef SP_FESPECULARLIGHTING_FNS_H
-#define SP_FESPECULARLIGHTING_FNS_H
-
-/** \file
- * Macros and fn declarations related to gaussian blur filter.
- */
-
-#include <glib-object.h>
-#include <glib/gtypes.h>
-
-namespace Inkscape {
-namespace XML {
-class Node;
-}
-}
-
-class SPFeSpecularLighting;
-
-#define SP_TYPE_FESPECULARLIGHTING (sp_feSpecularLighting_get_type())
-#define SP_FESPECULARLIGHTING(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SP_TYPE_FESPECULARLIGHTING, SPFeSpecularLighting))
-#define SP_FESPECULARLIGHTING_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), SP_TYPE_FESPECULARLIGHTING, SPFeSpecularLightingClass))
-#define SP_IS_FESPECULARLIGHTING(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), SP_TYPE_FESPECULARLIGHTING))
-#define SP_IS_FESPECULARLIGHTING_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), SP_TYPE_FESPECULARLIGHTING))
-
-GType sp_feSpecularLighting_get_type();
-
-#endif /* !SP_FESPECULARLIGHTING_FNS_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/filters/specularlighting.cpp b/src/filters/specularlighting.cpp
index 27d2a8c02..71a705c94 100644
--- a/src/filters/specularlighting.cpp
+++ b/src/filters/specularlighting.cpp
@@ -22,8 +22,12 @@
#include "svg/svg.h"
#include "sp-object.h"
#include "svg/svg-color.h"
-#include "specularlighting.h"
+#include "filters/specularlighting.h"
+#include "filters/distantlight.h"
+#include "filters/pointlight.h"
+#include "filters/spotlight.h"
#include "xml/repr.h"
+#include "display/nr-filter.h"
#include "display/nr-filter-specularlighting.h"
/* FeSpecularLighting base class */
diff --git a/src/filters/specularlighting.h b/src/filters/specularlighting.h
index 692ec9bf9..90d1f9f62 100644
--- a/src/filters/specularlighting.h
+++ b/src/filters/specularlighting.h
@@ -1,10 +1,6 @@
-#ifndef SP_FESPECULARLIGHTING_H_SEEN
-#define SP_FESPECULARLIGHTING_H_SEEN
-
-/** \file
- * SVG <feSpecularLighting> implementation, see SpecularLighting.cpp.
- */
-/*
+/** @file
+ * @brief SVG specular lighting filter effect
+ *//*
* Authors:
* Hugo Rodrigues <haa.rodrigues@gmail.com>
* Jean-Rene Reinhard <jr@komite.net>
@@ -15,8 +11,17 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include "sp-filter.h"
-#include "specularlighting-fns.h"
+#ifndef SP_FESPECULARLIGHTING_H_SEEN
+#define SP_FESPECULARLIGHTING_H_SEEN
+
+#include "sp-filter-primitive.h"
+#include "number-opt-number.h"
+
+#define SP_TYPE_FESPECULARLIGHTING (sp_feSpecularLighting_get_type())
+#define SP_FESPECULARLIGHTING(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SP_TYPE_FESPECULARLIGHTING, SPFeSpecularLighting))
+#define SP_FESPECULARLIGHTING_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), SP_TYPE_FESPECULARLIGHTING, SPFeSpecularLightingClass))
+#define SP_IS_FESPECULARLIGHTING(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), SP_TYPE_FESPECULARLIGHTING))
+#define SP_IS_FESPECULARLIGHTING_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), SP_TYPE_FESPECULARLIGHTING))
namespace Inkscape {
namespace Filters {
@@ -24,23 +29,16 @@ class FilterSpecularLighting;
}
}
-/* FeSpecularLighting base class */
class SPFeSpecularLightingClass;
struct SPFeSpecularLighting : public SPFilterPrimitive {
- /** SPECULARLIGHTING ATTRIBUTES HERE */
- /** surfaceScale attribute */
gfloat surfaceScale;
guint surfaceScale_set : 1;
- /** specularConstant attribute */
gfloat specularConstant;
guint specularConstant_set : 1;
- /** specularConstant attribute */
gfloat specularExponent;
guint specularExponent_set : 1;
- /** kernelUnitLenght attribute */
NumberOptNumber kernelUnitLength;
- /** lighting-color property */
guint32 lighting_color;
guint lighting_color_set : 1;
diff --git a/src/filters/spotlight.cpp b/src/filters/spotlight.cpp
index b6753a1f1..7be83ed00 100644
--- a/src/filters/spotlight.cpp
+++ b/src/filters/spotlight.cpp
@@ -21,9 +21,9 @@
#include "attributes.h"
#include "document.h"
-#include "spotlight.h"
-#include "diffuselighting-fns.h"
-#include "specularlighting-fns.h"
+#include "filters/spotlight.h"
+#include "filters/diffuselighting.h"
+#include "filters/specularlighting.h"
#include "xml/repr.h"
#define SP_MACROS_SILENT
diff --git a/src/filters/tile-fns.h b/src/filters/tile-fns.h
deleted file mode 100644
index 5f8393a7b..000000000
--- a/src/filters/tile-fns.h
+++ /dev/null
@@ -1,38 +0,0 @@
-#ifndef SP_FETILE_FNS_H
-#define SP_FETILE_FNS_H
-
-/** \file
- * Macros and fn declarations related to gaussian blur filter.
- */
-
-#include <glib-object.h>
-#include <glib/gtypes.h>
-
-namespace Inkscape {
-namespace XML {
-class Node;
-}
-}
-
-class SPFeTile;
-
-#define SP_TYPE_FETILE (sp_feTile_get_type())
-#define SP_FETILE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SP_TYPE_FETILE, SPFeTile))
-#define SP_FETILE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), SP_TYPE_FETILE, SPFeTileClass))
-#define SP_IS_FETILE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), SP_TYPE_FETILE))
-#define SP_IS_FETILE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), SP_TYPE_FETILE))
-
-GType sp_feTile_get_type();
-
-#endif /* !SP_FETILE_FNS_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/filters/tile.cpp b/src/filters/tile.cpp
index f42ec1de5..c3555ee7c 100644
--- a/src/filters/tile.cpp
+++ b/src/filters/tile.cpp
@@ -19,9 +19,10 @@
#include "attributes.h"
#include "svg/svg.h"
-#include "tile.h"
+#include "filters/tile.h"
#include "xml/repr.h"
-
+#include "display/nr-filter.h"
+#include "display/nr-filter-tile.h"
/* FeTile base class */
diff --git a/src/filters/tile.h b/src/filters/tile.h
index 747be7aa1..a376a6e10 100644
--- a/src/filters/tile.h
+++ b/src/filters/tile.h
@@ -1,10 +1,6 @@
-#ifndef SP_FETILE_H_SEEN
-#define SP_FETILE_H_SEEN
-
-/** \file
- * SVG <feTile> implementation, see Tile.cpp.
- */
-/*
+/** @file
+ * @brief SVG tile filter effect
+ *//*
* Authors:
* Hugo Rodrigues <haa.rodrigues@gmail.com>
*
@@ -13,17 +9,21 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include "sp-filter.h"
-#include "tile-fns.h"
+#ifndef SP_FETILE_H_SEEN
+#define SP_FETILE_H_SEEN
-#include "display/nr-filter.h"
-#include "display/nr-filter-tile.h"
+#include "sp-filter-primitive.h"
+
+#define SP_TYPE_FETILE (sp_feTile_get_type())
+#define SP_FETILE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SP_TYPE_FETILE, SPFeTile))
+#define SP_FETILE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), SP_TYPE_FETILE, SPFeTileClass))
+#define SP_IS_FETILE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), SP_TYPE_FETILE))
+#define SP_IS_FETILE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), SP_TYPE_FETILE))
/* FeTile base class */
class SPFeTileClass;
struct SPFeTile : public SPFilterPrimitive {
- /** TILE ATTRIBUTES HERE */
};
@@ -33,7 +33,6 @@ struct SPFeTileClass {
GType sp_feTile_get_type();
-
#endif /* !SP_FETILE_H_SEEN */
/*
diff --git a/src/filters/turbulence-fns.h b/src/filters/turbulence-fns.h
deleted file mode 100644
index 33946e3da..000000000
--- a/src/filters/turbulence-fns.h
+++ /dev/null
@@ -1,38 +0,0 @@
-#ifndef SP_FETURBULENCE_FNS_H
-#define SP_FETURBULENCE_FNS_H
-
-/** \file
- * Macros and fn declarations related to gaussian blur filter.
- */
-
-#include <glib-object.h>
-#include <glib/gtypes.h>
-
-namespace Inkscape {
-namespace XML {
-class Node;
-}
-}
-
-class SPFeTurbulence;
-
-#define SP_TYPE_FETURBULENCE (sp_feTurbulence_get_type())
-#define SP_FETURBULENCE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SP_TYPE_FETURBULENCE, SPFeTurbulence))
-#define SP_FETURBULENCE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), SP_TYPE_FETURBULENCE, SPFeTurbulenceClass))
-#define SP_IS_FETURBULENCE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), SP_TYPE_FETURBULENCE))
-#define SP_IS_FETURBULENCE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), SP_TYPE_FETURBULENCE))
-
-GType sp_feTurbulence_get_type();
-
-#endif /* !SP_FETURBULENCE_FNS_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/filters/turbulence.h b/src/filters/turbulence.h
index a19b8df57..cbc4fb082 100644
--- a/src/filters/turbulence.h
+++ b/src/filters/turbulence.h
@@ -1,10 +1,6 @@
-#ifndef SP_FETURBULENCE_H_SEEN
-#define SP_FETURBULENCE_H_SEEN
-
-/** \file
- * SVG <feTurbulence> implementation, see Turbulence.cpp.
- */
-/*
+/** @file
+ * @brief SVG turbulence filter effect
+ *//*
* Authors:
* Felipe CorrĂȘa da Silva Sanches <juca@members.fsf.org>
* Hugo Rodrigues <haa.rodrigues@gmail.com>
@@ -14,11 +10,19 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include "sp-filter.h"
-#include "turbulence-fns.h"
+#ifndef SP_FETURBULENCE_H_SEEN
+#define SP_FETURBULENCE_H_SEEN
+
+#include "sp-filter-primitive.h"
#include "number-opt-number.h"
#include "display/nr-filter-turbulence.h"
+#define SP_TYPE_FETURBULENCE (sp_feTurbulence_get_type())
+#define SP_FETURBULENCE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SP_TYPE_FETURBULENCE, SPFeTurbulence))
+#define SP_FETURBULENCE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), SP_TYPE_FETURBULENCE, SPFeTurbulenceClass))
+#define SP_IS_FETURBULENCE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), SP_TYPE_FETURBULENCE))
+#define SP_IS_FETURBULENCE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), SP_TYPE_FETURBULENCE))
+
/* FeTurbulence base class */
class SPFeTurbulenceClass;
diff --git a/src/flood-context.cpp b/src/flood-context.cpp
index 4bec2f292..73e82607a 100644
--- a/src/flood-context.cpp
+++ b/src/flood-context.cpp
@@ -52,13 +52,7 @@
#include "display/nr-arena.h"
#include "display/nr-arena-image.h"
#include "display/canvas-arena.h"
-#include "libnr/nr-pixops.h"
-#include "libnr/nr-matrix-translate-ops.h"
-#include "libnr/nr-scale-ops.h"
-#include "libnr/nr-scale-translate-ops.h"
-#include "libnr/nr-translate-matrix-ops.h"
-#include "libnr/nr-translate-scale-ops.h"
-#include "libnr/nr-matrix-ops.h"
+#include "display/cairo-utils.h"
#include <2geom/pathvector.h>
#include "sp-item.h"
#include "sp-root.h"
@@ -206,22 +200,20 @@ static void sp_flood_context_setup(SPEventContext *ec)
}
}
-/**
- * \brief Merge a pixel with the background color.
- * \param orig The pixel to merge with the background.
- * \param bg The background color.
- * \param base The pixel to merge the original and background into.
- */
-inline static void
-merge_pixel_with_background (unsigned char *orig, unsigned char *bg,
- unsigned char *base)
+inline static guint32
+compose_onto (guint32 px, guint32 bg)
{
- int precalc_bg_alpha = (255 * (255 - bg[3])) / 255;
-
- for (int i = 0; i < 3; i++) {
- base[i] = precalc_bg_alpha + (bg[i] * bg[3]) / 255;
- base[i] = (base[i] * (255 - orig[3])) / 255 + (orig[i] * orig[3]) / 255;
- }
+ EXTRACT_ARGB32(px, ap,rp,gp,bp)
+ EXTRACT_ARGB32(bg, ab,rb,gb,bb)
+ guint32 ao,ro,bo,go;
+
+ ao = 255*255 - (255-ap)*(255-bp); ao = (ao + 127) / 255;
+ ro = (255-ap)*rb + rp; ro = (ro + 127) / 255;
+ go = (255-ap)*gb + gp; go = (go + 127) / 255;
+ bo = (255-ap)*bb + bp; bo = (bo + 127) / 255;
+
+ ASSEMBLE_ARGB32(pxout, ao,ro,go,bo)
+ return pxout;
}
/**
@@ -229,10 +221,10 @@ merge_pixel_with_background (unsigned char *orig, unsigned char *bg,
* \param px The pixel buffer.
* \param x The X coordinate.
* \param y The Y coordinate.
- * \param width The width of the pixel buffer.
+ * \param stride The rowstride of the pixel buffer.
*/
-inline unsigned char * get_pixel(guchar *px, int x, int y, int width) {
- return px + (x + y * width) * 4;
+inline guint32 get_pixel(guchar *px, int x, int y, int stride) {
+ return *reinterpret_cast<guint32*>(px + y * stride + x * 4);
}
inline unsigned char * get_trace_pixel(guchar *trace_px, int x, int y, int width) {
@@ -280,34 +272,44 @@ GList * flood_autogap_dropdown_items_list() {
* \param threshold The fill threshold.
* \param method The fill method to use as defined in PaintBucketChannels.
*/
-static bool compare_pixels(unsigned char *check, unsigned char *orig, unsigned char *merged_orig_pixel, unsigned char *dtc, int threshold, PaintBucketChannels method) {
+static bool compare_pixels(guint32 check, guint32 orig, guint32 merged_orig_pixel, guint32 dtc, int threshold, PaintBucketChannels method)
+{
int diff = 0;
- float hsl_check[3], hsl_orig[3];
-
+ float hsl_check[3] = {0,0,0}, hsl_orig[3] = {0,0,0};
+
+ EXTRACT_ARGB32(check, ac,rc,gc,bc)
+ EXTRACT_ARGB32(orig, ao,ro,go,bo)
+ EXTRACT_ARGB32(dtc, ad,rd,gd,bd)
+ EXTRACT_ARGB32(merged_orig_pixel, amop,rmop,gmop,bmop)
+
if ((method == FLOOD_CHANNELS_H) ||
(method == FLOOD_CHANNELS_S) ||
(method == FLOOD_CHANNELS_L)) {
- sp_color_rgb_to_hsl_floatv(hsl_check, check[0] / 255.0, check[1] / 255.0, check[2] / 255.0);
- sp_color_rgb_to_hsl_floatv(hsl_orig, orig[0] / 255.0, orig[1] / 255.0, orig[2] / 255.0);
+ double dac = ac;
+ double dao = ao;
+ sp_color_rgb_to_hsl_floatv(hsl_check, rc / dac, gc / dac, bc / dac);
+ sp_color_rgb_to_hsl_floatv(hsl_orig, ro / dao, go / dao, bo / dao);
}
switch (method) {
case FLOOD_CHANNELS_ALPHA:
- return ((int)abs(check[3] - orig[3]) <= threshold);
+ return abs(static_cast<int>(ac) - ao) <= threshold;
case FLOOD_CHANNELS_R:
- return ((int)abs(check[0] - orig[0]) <= threshold);
+ return abs(static_cast<int>(ac ? unpremul_alpha(rc, ac) : 0) - (ao ? unpremul_alpha(ro, ao) : 0)) <= threshold;
case FLOOD_CHANNELS_G:
- return ((int)abs(check[1] - orig[1]) <= threshold);
+ return abs(static_cast<int>(ac ? unpremul_alpha(gc, ac) : 0) - (ao ? unpremul_alpha(go, ao) : 0)) <= threshold;
case FLOOD_CHANNELS_B:
- return ((int)abs(check[2] - orig[2]) <= threshold);
+ return abs(static_cast<int>(ac ? unpremul_alpha(bc, ac) : 0) - (ao ? unpremul_alpha(bo, ao) : 0)) <= threshold;
case FLOOD_CHANNELS_RGB:
- unsigned char merged_check[3];
-
- merge_pixel_with_background(check, dtc, merged_check);
-
- for (int i = 0; i < 3; i++) {
- diff += (int)abs(merged_check[i] - merged_orig_pixel[i]);
- }
+ guint32 amc, rmc, bmc, gmc;
+ amc = 255*255 - (255-ac)*(255-ad); amc = (amc + 127) / 255;
+ rmc = (255-ac)*rd + rc; rmc = (rmc + 127) / 255;
+ gmc = (255-ac)*gd + gc; gmc = (gmc + 127) / 255;
+ bmc = (255-ac)*bd + bc; bmc = (bmc + 127) / 255;
+
+ diff += abs(static_cast<int>(amc ? unpremul_alpha(rmc, amc) : 0) - (amop ? unpremul_alpha(rmop, amop) : 0));
+ diff += abs(static_cast<int>(amc ? unpremul_alpha(gmc, amc) : 0) - (amop ? unpremul_alpha(gmop, amop) : 0));
+ diff += abs(static_cast<int>(amc ? unpremul_alpha(bmc, amc) : 0) - (amop ? unpremul_alpha(bmop, amop) : 0));
return ((diff / 3) <= ((threshold * 3) / 4));
case FLOOD_CHANNELS_H:
@@ -353,11 +355,12 @@ struct bitmap_coords_info {
int y_limit;
unsigned int width;
unsigned int height;
+ unsigned int stride;
unsigned int threshold;
unsigned int radius;
PaintBucketChannels method;
- unsigned char *dtc;
- unsigned char *merged_orig_pixel;
+ guint32 dtc;
+ guint32 merged_orig_pixel;
Geom::Rect bbox;
Geom::Rect screen;
unsigned int max_queue_size;
@@ -373,12 +376,12 @@ struct bitmap_coords_info {
* \param orig_color The original selected pixel to use as the fill target color.
* \param bci The bitmap_coords_info structure.
*/
-inline static bool check_if_pixel_is_paintable(guchar *px, unsigned char *trace_t, int x, int y, unsigned char *orig_color, bitmap_coords_info bci) {
+inline static bool check_if_pixel_is_paintable(guchar *px, unsigned char *trace_t, int x, int y, guint32 orig_color, bitmap_coords_info bci) {
if (is_pixel_paintability_checked(trace_t)) {
return is_pixel_paintable(trace_t);
} else {
- unsigned char *t = get_pixel(px, x, y, bci.width);
- if (compare_pixels(t, orig_color, bci.merged_orig_pixel, bci.dtc, bci.threshold, bci.method)) {
+ guint32 pixel = get_pixel(px, x, y, bci.stride);
+ if (compare_pixels(pixel, orig_color, bci.merged_orig_pixel, bci.dtc, bci.threshold, bci.method)) {
mark_pixel_paintable(trace_t);
return true;
} else {
@@ -557,7 +560,7 @@ inline static bool coords_in_range(unsigned int x, unsigned int y, bitmap_coords
* \param bci The bitmap_coords_info structure.
* \param original_point_trace_t The original pixel in the trace pixel buffer to check.
*/
-inline static unsigned int paint_pixel(guchar *px, guchar *trace_px, unsigned char *orig_color, bitmap_coords_info bci, unsigned char *original_point_trace_t) {
+inline static unsigned int paint_pixel(guchar *px, guchar *trace_px, guint32 orig_color, bitmap_coords_info bci, unsigned char *original_point_trace_t) {
if (bci.radius == 0) {
mark_pixel_colored(original_point_trace_t);
return PAINT_DIRECTION_ALL;
@@ -639,7 +642,7 @@ static void shift_point_onto_queue(std::deque<Geom::Point> *fill_queue, unsigned
* \param orig_color The original selected pixel to use as the fill target color.
* \param bci The bitmap_coords_info structure.
*/
-static ScanlineCheckResult perform_bitmap_scanline_check(std::deque<Geom::Point> *fill_queue, guchar *px, guchar *trace_px, unsigned char *orig_color, bitmap_coords_info bci, unsigned int *min_x, unsigned int *max_x) {
+static ScanlineCheckResult perform_bitmap_scanline_check(std::deque<Geom::Point> *fill_queue, guchar *px, guchar *trace_px, guint32 orig_color, bitmap_coords_info bci, unsigned int *min_x, unsigned int *max_x) {
bool aborted = false;
bool reached_screen_boundary = false;
bool ok;
@@ -823,37 +826,33 @@ static void sp_flood_do_flood_fill(SPEventContext *event_context, GdkEvent *even
nr_arena_item_invoke_update(root, &final_bbox, &gc, NR_ARENA_ITEM_STATE_ALL, NR_ARENA_ITEM_STATE_NONE);
- guchar *px = g_new(guchar, 4 * width * height);
-
- NRPixBlock B;
- nr_pixblock_setup_extern( &B, NR_PIXBLOCK_MODE_R8G8B8A8N,
- final_bbox.x0, final_bbox.y0, final_bbox.x1, final_bbox.y1,
- px, 4 * width, FALSE, FALSE );
+ int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width);
+ guchar *px = g_new(guchar, stride * height);
+ cairo_surface_t *s = cairo_image_surface_create_for_data(
+ px, CAIRO_FORMAT_ARGB32, width, height, stride);
+ cairo_t *ct = cairo_create(s);
+ // cairo_translate not necessary here - surface origin is at 0,0
+
SPNamedView *nv = sp_desktop_namedview(desktop);
- unsigned long bgcolor = nv->pagecolor;
-
- unsigned char dtc[4];
- dtc[0] = NR_RGBA32_R(bgcolor);
- dtc[1] = NR_RGBA32_G(bgcolor);
- dtc[2] = NR_RGBA32_B(bgcolor);
- dtc[3] = NR_RGBA32_A(bgcolor);
-
- for (unsigned int fy = 0; fy < height; fy++) {
- guchar *p = NR_PIXBLOCK_PX(&B) + fy * B.rs;
- for (unsigned int fx = 0; fx < width; fx++) {
- for (int i = 0; i < 4; i++) {
- *p++ = dtc[i];
- }
- }
- }
+ guint32 bgcolor = nv->pagecolor;
+ // bgcolor is 0xrrggbbaa, we need 0xaarrggbb
+ guint32 dtc = (bgcolor >> 8) | (bgcolor << 24);
+
+ ink_cairo_set_source_rgba32(ct, bgcolor);
+ cairo_set_operator(ct, CAIRO_OPERATOR_SOURCE);
+ cairo_paint(ct);
+ cairo_set_operator(ct, CAIRO_OPERATOR_OVER);
- nr_arena_item_invoke_render(NULL, root, &final_bbox, &B, NR_ARENA_ITEM_RENDER_NO_CACHE );
- nr_pixblock_release(&B);
+ nr_arena_item_invoke_render(ct, root, &final_bbox, NULL, NR_ARENA_ITEM_RENDER_NO_CACHE );
+
+ cairo_surface_flush(s);
+ cairo_destroy(ct);
+ cairo_surface_destroy(s);
// Hide items
SP_ITEM(document->getRoot())->invoke_hide(dkey);
-
+
nr_object_unref((NRObject *) arena);
guchar *trace_px = g_new(guchar, width * height);
@@ -890,6 +889,7 @@ static void sp_flood_do_flood_fill(SPEventContext *event_context, GdkEvent *even
bci.y_limit = y_limit;
bci.width = width;
bci.height = height;
+ bci.stride = stride;
bci.threshold = threshold;
bci.method = method;
bci.bbox = *bbox;
@@ -942,15 +942,8 @@ static void sp_flood_do_flood_fill(SPEventContext *event_context, GdkEvent *even
int cx = (int)color_point[Geom::X];
int cy = (int)color_point[Geom::Y];
- unsigned char *orig_px = get_pixel(px, cx, cy, width);
- unsigned char orig_color[4];
- for (int i = 0; i < 4; i++) { orig_color[i] = orig_px[i]; }
-
- unsigned char merged_orig[3];
-
- merge_pixel_with_background(orig_color, dtc, merged_orig);
-
- bci.merged_orig_pixel = merged_orig;
+ guint32 orig_color = get_pixel(px, cx, cy, stride);
+ bci.merged_orig_pixel = compose_onto(orig_color, dtc);
unsigned char *trace_t = get_trace_pixel(trace_px, cx, cy, width);
if (!is_pixel_checked(trace_t) && !is_pixel_colored(trace_t)) {
diff --git a/src/gradient-chemistry.cpp b/src/gradient-chemistry.cpp
index 889e319b2..676e9aa94 100644
--- a/src/gradient-chemistry.cpp
+++ b/src/gradient-chemistry.cpp
@@ -30,10 +30,6 @@
#include "sp-text.h"
#include "sp-tspan.h"
-#include <libnr/nr-matrix-fns.h>
-#include <libnr/nr-point-fns.h>
-#include <libnr/nr-matrix-ops.h>
-#include <libnr/nr-rotate-ops.h>
#include <2geom/transforms.h>
#include "xml/repr.h"
#include "svg/svg.h"
@@ -41,6 +37,7 @@
#include "svg/css-ostringstream.h"
#include "preferences.h"
+#include "libnr/nr-point-fns.h"
#define noSP_GR_VERBOSE
// Terminology:
diff --git a/src/gradient-context.cpp b/src/gradient-context.cpp
index 007fa549a..922a9b16e 100644
--- a/src/gradient-context.cpp
+++ b/src/gradient-context.cpp
@@ -46,8 +46,9 @@
#include "sp-namedview.h"
#include "rubberband.h"
-using Inkscape::DocumentUndo;
+#include "libnr/nr-point-fns.h"
+using Inkscape::DocumentUndo;
static void sp_gradient_context_class_init(SPGradientContextClass *klass);
static void sp_gradient_context_init(SPGradientContext *gr_context);
diff --git a/src/helper/geom.cpp b/src/helper/geom.cpp
index 2420b43b4..64aa8bc48 100644
--- a/src/helper/geom.cpp
+++ b/src/helper/geom.cpp
@@ -28,8 +28,6 @@
using Geom::X;
using Geom::Y;
-#define NR_HUGE 1e18
-
//#################################################################################
// BOUNDING BOX CALCULATIONS
@@ -423,7 +421,7 @@ pathv_matrix_point_bbox_wind_distance (Geom::PathVector const & pathv, Geom::Aff
{
if (pathv.empty()) {
if (wind) *wind = 0;
- if (dist) *dist = NR_HUGE;
+ if (dist) *dist = Geom::infinity();
return;
}
diff --git a/src/helper/pixbuf-ops.cpp b/src/helper/pixbuf-ops.cpp
index acd2568af..f6796f2ad 100644
--- a/src/helper/pixbuf-ops.cpp
+++ b/src/helper/pixbuf-ops.cpp
@@ -15,28 +15,23 @@
# include "config.h"
#endif
-#include <interface.h>
-#include <libnr/nr-pixops.h>
#include <glib.h>
#include <glib/gmessages.h>
#include <png.h>
-#include "png-write.h"
-#include <display/nr-arena-item.h>
-#include <display/nr-arena.h>
-#include <document.h>
-#include <sp-item.h>
-#include <sp-root.h>
-#include <sp-use.h>
-#include <sp-defs.h>
-#include "unit-constants.h"
-#include "libnr/nr-matrix-translate-ops.h"
-#include "libnr/nr-scale-ops.h"
-#include "libnr/nr-scale-translate-ops.h"
-#include "libnr/nr-translate-matrix-ops.h"
-#include "libnr/nr-translate-scale-ops.h"
+#include "interface.h"
+#include "helper/png-write.h"
+#include "display/cairo-utils.h"
+#include "display/nr-arena-item.h"
+#include "display/nr-arena.h"
+#include "document.h"
+#include "sp-item.h"
+#include "sp-root.h"
+#include "sp-use.h"
+#include "sp-defs.h"
+#include "unit-constants.h"
-#include "pixbuf-ops.h"
+#include "helper/pixbuf-ops.h"
// TODO look for copy-n-past duplication of this function:
/**
@@ -155,50 +150,32 @@ sp_generate_internal_bitmap(SPDocument *doc, gchar const */*filename*/,
nr_arena_item_invoke_update(root, &final_bbox, &gc, NR_ARENA_ITEM_STATE_ALL, NR_ARENA_ITEM_STATE_NONE);
- guchar *px = NULL;
- guint64 size = 4L * (guint64)width * (guint64)height;
- if(size < (guint64)G_MAXSIZE) {
- // g_try_new is limited to g_size type which is defined as unisgned int. Need to test for very large nubers
- px = g_try_new(guchar, size);
- }
+ cairo_surface_t *surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
- if(px != NULL)
- {
+ if (cairo_surface_status(surface) == CAIRO_STATUS_SUCCESS) {
+ cairo_t *ct = cairo_create(surface);
+
+ // clear to background
+ ink_cairo_set_source_rgba32(ct, bgcolor);
+ cairo_set_operator(ct, CAIRO_OPERATOR_SOURCE);
+ cairo_paint(ct);
+ cairo_set_operator(ct, CAIRO_OPERATOR_OVER);
+
+ // render items
+ nr_arena_item_invoke_render(ct, root, &final_bbox, NULL, NR_ARENA_ITEM_RENDER_NO_CACHE );
- NRPixBlock B;
- //g_warning("sp_generate_internal_bitmap: nr_pixblock_setup_extern.");
- nr_pixblock_setup_extern( &B, NR_PIXBLOCK_MODE_R8G8B8A8N,
- final_bbox.x0, final_bbox.y0, final_bbox.x1, final_bbox.y1,
- px, 4 * width, FALSE, FALSE );
-
- unsigned char dtc[4];
- dtc[0] = NR_RGBA32_R(bgcolor);
- dtc[1] = NR_RGBA32_G(bgcolor);
- dtc[2] = NR_RGBA32_B(bgcolor);
- dtc[3] = NR_RGBA32_A(bgcolor);
-
- // fill pixelblock using background colour
- for (gsize fy = 0; fy < height; fy++) {
- guchar *p = NR_PIXBLOCK_PX(&B) + fy * (gsize)B.rs;
- for (unsigned int fx = 0; fx < width; fx++) {
- for (int i = 0; i < 4; i++) {
- *p++ = dtc[i];
- }
- }
- }
-
-
- nr_arena_item_invoke_render(NULL, root, &final_bbox, &B, NR_ARENA_ITEM_RENDER_NO_CACHE );
-
- pixbuf = gdk_pixbuf_new_from_data(px, GDK_COLORSPACE_RGB,
- TRUE,
- 8, width, height, width * 4,
- (GdkPixbufDestroyNotify)g_free,
- NULL);
+ pixbuf = gdk_pixbuf_new_from_data(cairo_image_surface_get_data(surface),
+ GDK_COLORSPACE_RGB, TRUE,
+ 8, width, height, cairo_image_surface_get_stride(surface),
+ (GdkPixbufDestroyNotify) cairo_surface_destroy,
+ NULL);
+ convert_pixbuf_argb32_to_normal(pixbuf);
}
else
{
+ long long size = (long long) height * (long long) cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width);
g_warning("sp_generate_internal_bitmap: not enough memory to create pixel buffer. Need %lld.", size);
+ cairo_surface_destroy(surface);
}
SP_ITEM(doc->getRoot())->invoke_hide(dkey);
nr_object_unref((NRObject *) arena);
diff --git a/src/helper/png-write.cpp b/src/helper/png-write.cpp
index 2df543c6d..4667f631b 100644
--- a/src/helper/png-write.cpp
+++ b/src/helper/png-write.cpp
@@ -16,22 +16,21 @@
# include "config.h"
#endif
-#include <interface.h>
-#include <libnr/nr-pixops.h>
-#include <libnr/nr-translate-scale-ops.h>
+#include "interface.h"
#include <2geom/rect.h>
#include <glib/gmessages.h>
#include <png.h>
#include "png-write.h"
#include "io/sys.h"
-#include <display/nr-arena-item.h>
-#include <display/nr-arena.h>
-#include <document.h>
-#include <sp-item.h>
-#include <sp-root.h>
-#include <sp-defs.h>
+#include "display/nr-arena-item.h"
+#include "display/nr-arena.h"
+#include "document.h"
+#include "sp-item.h"
+#include "sp-root.h"
+#include "sp-defs.h"
#include "preferences.h"
#include "rdf.h"
+#include "display/cairo-utils.h"
/* This is an example of how to use libpng to read and write PNG files.
* The file libpng.txt is much more verbose then this. If you have not
@@ -49,7 +48,7 @@ static unsigned int const MAX_STRIPE_SIZE = 1024*1024;
struct SPEBP {
unsigned long int width, height, sheight;
- guchar r, g, b, a;
+ guint32 background;
NRArenaItem *root; // the root arena item to show; it is assumed that all unneeded items are hidden
guchar *px;
unsigned (*status)(float, void *);
@@ -122,7 +121,7 @@ void PngTextList::add(gchar const* key, gchar const* text)
static bool
sp_png_write_rgba_striped(SPDocument *doc,
gchar const *filename, unsigned long int width, unsigned long int height, double xdpi, double ydpi,
- int (* get_rows)(guchar const **rows, int row, int num_rows, void *data),
+ int (* get_rows)(guchar const **rows, void **to_free, int row, int num_rows, void *data),
void *data)
{
struct SPEBP *ebp = (struct SPEBP *) data;
@@ -272,10 +271,12 @@ sp_png_write_rgba_striped(SPDocument *doc,
png_bytep* row_pointers = new png_bytep[ebp->sheight];
r = 0;
- while (r < static_cast< png_uint_32 > (height) ) {
- int n = get_rows((unsigned char const **) row_pointers, r, height-r, data);
+ while (r < static_cast<png_uint_32>(height)) {
+ void *to_free;
+ int n = get_rows((unsigned char const **) row_pointers, &to_free, r, height-r, data);
if (!n) break;
png_write_rows(png_ptr, row_pointers, n);
+ g_free(to_free);
r += n;
}
@@ -305,7 +306,7 @@ sp_png_write_rgba_striped(SPDocument *doc,
*
*/
static int
-sp_export_get_rows(guchar const **rows, int row, int num_rows, void *data)
+sp_export_get_rows(guchar const **rows, void **to_free, int row, int num_rows, void *data)
{
struct SPEBP *ebp = (struct SPEBP *) data;
@@ -332,30 +333,35 @@ sp_export_get_rows(guchar const **rows, int row, int num_rows, void *data)
nr_arena_item_invoke_update(ebp->root, &bbox, &gc,
NR_ARENA_ITEM_STATE_ALL, NR_ARENA_ITEM_STATE_NONE);
- NRPixBlock pb;
- nr_pixblock_setup_extern(&pb, NR_PIXBLOCK_MODE_R8G8B8A8N,
- bbox.x0, bbox.y0, bbox.x1, bbox.y1,
- ebp->px, 4 * ebp->width, FALSE, FALSE);
+ int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, ebp->width);
+ unsigned char *px = g_new(guchar, num_rows * stride);
- for (int r = 0; r < num_rows; r++) {
- guchar *p = NR_PIXBLOCK_PX(&pb) + r * pb.rs;
- for (int c = 0; c < static_cast<int>(ebp->width); c++) {
- *p++ = ebp->r;
- *p++ = ebp->g;
- *p++ = ebp->b;
- *p++ = ebp->a;
- }
- }
+ cairo_surface_t *s = cairo_image_surface_create_for_data(
+ px, CAIRO_FORMAT_ARGB32, ebp->width, num_rows, stride);
+ cairo_t *ct = cairo_create(s);
+ cairo_translate(ct, -bbox.x0, -bbox.y0);
+
+ ink_cairo_set_source_rgba32(ct, ebp->background);
+ cairo_set_operator(ct, CAIRO_OPERATOR_SOURCE);
+ cairo_paint(ct);
+ cairo_set_operator(ct, CAIRO_OPERATOR_OVER);
/* Render */
- nr_arena_item_invoke_render(NULL, ebp->root, &bbox, &pb, 0);
+ nr_arena_item_invoke_render(ct, ebp->root, &bbox, NULL, 0);
+
+ cairo_destroy(ct);
+ cairo_surface_destroy(s);
+
+ *to_free = px;
+
+ // PNG stores data as unpremultiplied big-endian RGBA, which means
+ // it's identical to the GdkPixbuf format.
+ convert_pixels_argb32_to_pixbuf(px, ebp->width, num_rows, stride);
for (int r = 0; r < num_rows; r++) {
- rows[r] = NR_PIXBLOCK_PX(&pb) + r * pb.rs;
+ rows[r] = px + r * stride;
}
- nr_pixblock_release(&pb);
-
return num_rows;
}
@@ -451,10 +457,7 @@ sp_export_png_file(SPDocument *doc, gchar const *filename,
struct SPEBP ebp;
ebp.width = width;
ebp.height = height;
- ebp.r = NR_RGBA32_R(bgcolor);
- ebp.g = NR_RGBA32_G(bgcolor);
- ebp.b = NR_RGBA32_B(bgcolor);
- ebp.a = NR_RGBA32_A(bgcolor);
+ ebp.background = bgcolor;
/* Create new arena */
NRArena *const arena = NRArena::create();
@@ -475,15 +478,12 @@ sp_export_png_file(SPDocument *doc, gchar const *filename,
ebp.status = status;
ebp.data = data;
- bool write_status;
- if ((width < 256) || ((width * height) < 32768)) {
- ebp.px = nr_pixelstore_64K_new(FALSE, 0);
- ebp.sheight = 65536 / (4 * width);
- write_status = sp_png_write_rgba_striped(doc, filename, width, height, xdpi, ydpi, sp_export_get_rows, &ebp);
- nr_pixelstore_64K_free(ebp.px);
- } else {
- ebp.sheight = 64;
- ebp.px = g_try_new(guchar, 4 * ebp.sheight * width);
+ bool write_status = false;;
+
+ ebp.sheight = 64;
+ ebp.px = g_try_new(guchar, 4 * ebp.sheight * width);
+
+ if (ebp.px) {
write_status = sp_png_write_rgba_striped(doc, filename, width, height, xdpi, ydpi, sp_export_get_rows, &ebp);
g_free(ebp.px);
}
diff --git a/src/inkscape.cpp b/src/inkscape.cpp
index e90c44c82..20084da54 100644
--- a/src/inkscape.cpp
+++ b/src/inkscape.cpp
@@ -25,10 +25,6 @@
# define HAS_PROC_SELF_EXE //to get path of executable
#else
-// For now to get at is_os_wide().
-# include "extension/internal/win32.h"
-using Inkscape::Extension::Internal::PrintWin32;
-
#define _WIN32_IE 0x0400
//#define HAS_SHGetSpecialFolderPath
#define HAS_SHGetSpecialFolderLocation
@@ -1351,24 +1347,18 @@ profile_path(const char *filename)
if ( SHGetSpecialFolderLocation( NULL, CSIDL_APPDATA, &pidl ) == NOERROR ) {
gchar * utf8Path = NULL;
- if ( PrintWin32::is_os_wide() ) {
+ {
wchar_t pathBuf[MAX_PATH+1];
g_assert(sizeof(wchar_t) == sizeof(gunichar2));
if ( SHGetPathFromIDListW( pidl, pathBuf ) ) {
utf8Path = g_utf16_to_utf8( (gunichar2*)(&pathBuf[0]), -1, NULL, NULL, NULL );
}
- } else {
- char pathBuf[MAX_PATH+1];
-
- if ( SHGetPathFromIDListA( pidl, pathBuf ) ) {
- utf8Path = g_filename_to_utf8( pathBuf, -1, NULL, NULL, NULL );
- }
}
if ( utf8Path ) {
if (!g_utf8_validate(utf8Path, -1, NULL)) {
- g_warning( "SHGetPathFromIDList%c() resulted in invalid UTF-8", (PrintWin32::is_os_wide() ? 'W' : 'A') );
+ g_warning( "SHGetPathFromIDListW() resulted in invalid UTF-8");
g_free( utf8Path );
utf8Path = 0;
} else {
diff --git a/src/interface.cpp b/src/interface.cpp
index f27700c25..11882ddf9 100644
--- a/src/interface.cpp
+++ b/src/interface.cpp
@@ -1267,7 +1267,7 @@ sp_ui_drag_data_received(GtkWidget *widget,
( !item->style->stroke.isNone() ?
desktop->current_zoom() *
item->style->stroke_width.computed *
- to_2geom(item->i2d_affine()).descrim() * 0.5
+ item->i2d_affine().descrim() * 0.5
: 0.0)
+ prefs->getIntLimited("/options/dragtolerance/value", 0, 0, 100);
@@ -1370,7 +1370,7 @@ sp_ui_drag_data_received(GtkWidget *widget,
( !item->style->stroke.isNone() ?
desktop->current_zoom() *
item->style->stroke_width.computed *
- to_2geom(item->i2d_affine()).descrim() * 0.5
+ item->i2d_affine().descrim() * 0.5
: 0.0)
+ prefs->getIntLimited("/options/dragtolerance/value", 0, 0, 100);
diff --git a/src/io/sys.cpp b/src/io/sys.cpp
index 85857c2f0..437a9d18c 100644
--- a/src/io/sys.cpp
+++ b/src/io/sys.cpp
@@ -26,12 +26,6 @@
#include "preferences.h"
#include "sys.h"
-#ifdef WIN32
-// For now to get at is_os_wide().
-#include "extension/internal/win32.h"
-using Inkscape::Extension::Internal::PrintWin32;
-#endif // WIN32
-
//#define INK_DUMP_FILENAME_CONV 1
#undef INK_DUMP_FILENAME_CONV
diff --git a/src/io/uristream.cpp b/src/io/uristream.cpp
index 05d7f020a..b5f884b29 100644
--- a/src/io/uristream.cpp
+++ b/src/io/uristream.cpp
@@ -16,12 +16,6 @@
#include <string>
#include <cstring>
-#ifdef WIN32
-// For now to get at is_os_wide().
-# include "extension/internal/win32.h"
-using Inkscape::Extension::Internal::PrintWin32;
-#endif
-
namespace Inkscape
{
@@ -65,7 +59,7 @@ static FILE *fopen_utf8name( char const *utf8name, int mode )
g_free(filename);
}
#else
- if ( PrintWin32::is_os_wide() ) {
+ {
gunichar2 *wideName = g_utf8_to_utf16( utf8name, -1, NULL, NULL, NULL );
if ( wideName ) {
if (mode == FILE_READ)
@@ -78,15 +72,6 @@ static FILE *fopen_utf8name( char const *utf8name, int mode )
g_message("Unable to convert filename from UTF-8 to UTF-16 [%s]", safe);
g_free(safe);
}
- } else {
- gchar *filename = g_filename_from_utf8( utf8name, -1, NULL, NULL, NULL );
- if ( filename ) {
- if (mode == FILE_READ)
- fp = std::fopen(filename, "rb");
- else
- fp = std::fopen(filename, "wb");
- g_free(filename);
- }
}
#endif
diff --git a/src/knot-holder-entity.cpp b/src/knot-holder-entity.cpp
index 81d845e99..7da3d0c0e 100644
--- a/src/knot-holder-entity.cpp
+++ b/src/knot-holder-entity.cpp
@@ -20,7 +20,6 @@
#include "style.h"
#include "preferences.h"
#include "macros.h"
-#include <libnr/nr-matrix-ops.h>
#include "sp-pattern.h"
#include "snap.h"
#include "desktop.h"
diff --git a/src/libnr/Makefile_insert b/src/libnr/Makefile_insert
index 8dd3c46e3..1027e0600 100644
--- a/src/libnr/Makefile_insert
+++ b/src/libnr/Makefile_insert
@@ -2,50 +2,17 @@
ink_common_sources += \
libnr/in-svg-plane.h \
- libnr/nr-blit.cpp \
- libnr/nr-blit.h \
- libnr/nr-compose-transform.cpp \
- libnr/nr-compose-transform.h \
- libnr/nr-compose-reference.h \
- libnr/nr-compose.cpp \
- libnr/nr-compose.h \
libnr/nr-convert2geom.h \
- libnr/nr-convex-hull.h \
libnr/nr-coord.h \
libnr/nr-dim2.h \
libnr/nr-forward.h \
- libnr/nr-gradient.cpp \
- libnr/nr-gradient.h \
libnr/nr-i-coord.h \
libnr/nr-macros.h \
- libnr/nr-matrix-div.cpp \
- libnr/nr-matrix-div.h \
- libnr/nr-matrix-fns.cpp \
- libnr/nr-matrix-fns.h \
- libnr/nr-matrix-ops.h \
- libnr/nr-matrix-rotate-ops.cpp \
- libnr/nr-matrix-rotate-ops.h \
- libnr/nr-matrix-scale-ops.h \
- libnr/nr-matrix-translate-ops.h \
- libnr/nr-matrix.cpp \
- libnr/nr-matrix.h \
- libnr/nr-maybe.h \
libnr/nr-object.cpp \
libnr/nr-object.h \
- libnr/nr-path-code.h \
- libnr/nr-pixblock-line.cpp \
- libnr/nr-pixblock-line.h \
- libnr/nr-pixblock-pattern.cpp \
- libnr/nr-pixblock-pattern.h \
- libnr/nr-pixblock-pixel.cpp \
- libnr/nr-pixblock-pixel.h \
- libnr/nr-pixblock.cpp \
- libnr/nr-pixblock.h \
- libnr/nr-pixops.h \
libnr/nr-point-fns.cpp \
libnr/nr-point-fns.h \
libnr/nr-point-l.h \
- libnr/nr-point-matrix-ops.h \
libnr/nr-point-ops.h \
libnr/nr-point.h \
libnr/nr-rect-l.cpp \
@@ -53,52 +20,15 @@ ink_common_sources += \
libnr/nr-rect.cpp \
libnr/nr-rect.h \
libnr/nr-rect-ops.h \
- libnr/nr-render.h \
- libnr/nr-rotate-fns.cpp \
- libnr/nr-rotate-fns.h \
- libnr/nr-rotate-ops.h \
- libnr/nr-rotate-matrix-ops.cpp \
- libnr/nr-rotate-matrix-ops.h \
- libnr/nr-rotate.h \
- libnr/nr-scale-matrix-ops.cpp \
- libnr/nr-scale-matrix-ops.h \
- libnr/nr-scale-translate-ops.cpp \
- libnr/nr-scale-translate-ops.h \
- libnr/nr-scale-ops.h \
- libnr/nr-scale.h \
- libnr/nr-translate-matrix-ops.cpp \
- libnr/nr-translate-matrix-ops.h \
- libnr/nr-translate-scale-ops.cpp \
- libnr/nr-translate-scale-ops.h \
- libnr/nr-translate-ops.h \
- libnr/nr-translate.h \
- libnr/nr-translate-rotate-ops.cpp \
- libnr/nr-translate-rotate-ops.h \
libnr/nr-types.cpp \
libnr/nr-types.h \
libnr/nr-values.cpp \
- libnr/nr-values.h \
- $(libnr_mmx_sources)
-
-# Ancient performance test (?)
-# Won't work anymore.
-#libnr_testnr_SOURCES = \
-# libnr/testnr.cpp
-
-#libnr_testnr_LDADD = \
-# libnr/libnr.a \
-# -lglib-2.0
+ libnr/nr-values.h
# ######################
# ### CxxTest stuff ####
# ######################
CXXTEST_TESTSUITES += \
$(srcdir)/libnr/in-svg-plane-test.h \
- $(srcdir)/libnr/nr-compose-test.h \
- $(srcdir)/libnr/nr-matrix-test.h \
$(srcdir)/libnr/nr-point-fns-test.h \
- $(srcdir)/libnr/nr-rotate-test.h \
- $(srcdir)/libnr/nr-rotate-fns-test.h \
- $(srcdir)/libnr/nr-scale-test.h \
- $(srcdir)/libnr/nr-translate-test.h \
$(srcdir)/libnr/nr-types-test.h
diff --git a/src/libnr/nr-blit.cpp b/src/libnr/nr-blit.cpp
deleted file mode 100644
index 144caa597..000000000
--- a/src/libnr/nr-blit.cpp
+++ /dev/null
@@ -1,300 +0,0 @@
-#define __NR_BLIT_C__
-
-/*
- * Pixel buffer rendering library
- *
- * Authors:
- * Lauris Kaplinski <lauris@kaplinski.com>
- *
- * This code is in public domain
- */
-
-#include "nr-pixops.h"
-#include "nr-compose.h"
-#include "nr-blit.h"
-
-void
-nr_blit_pixblock_pixblock_alpha (NRPixBlock *d, NRPixBlock *s, unsigned int alpha)
-{
- NRRectL clip;
- unsigned char *dpx, *spx;
- int dbpp, sbpp;
- int w, h;
-
- if (alpha == 0) return;
- if (s->empty) return;
- /* fixme: */
- if (s->mode == NR_PIXBLOCK_MODE_A8) return;
- /* fixme: */
- if (s->mode == NR_PIXBLOCK_MODE_R8G8B8) return;
-
- /*
- * Possible variants as of now:
- *
- * 0. SRC EP - DST EP *
- * 1. SRC EP - DST EN *
- * 2. SRC EP - DST P *
- * 3. SRC EP - DST N *
- * 4. SRC EN - DST EP *
- * 5. SRC EN - DST EN *
- * 6. SRC EN - DST P *
- * 7. SRC EN - DST N *
- * 8. SRC P - DST EP *
- * 9. SRC P - DST EN *
- * A. SRC P - DST P *
- * B. SRC P - DST N *
- * C. SRC N - DST EP *
- * D. SRC N - DST EN *
- * E. SRC N - DST P *
- * F. SRC N - DST N *
- *
- */
-
- nr_rect_l_intersect (&clip, &d->area, &s->area);
-
- if (nr_rect_l_test_empty(clip)) return;
-
- /* Pointers */
- dbpp = NR_PIXBLOCK_BPP (d);
- dpx = NR_PIXBLOCK_PX (d) + (clip.y0 - d->area.y0) * d->rs + dbpp * (clip.x0 - d->area.x0);
- sbpp = NR_PIXBLOCK_BPP (s);
- spx = NR_PIXBLOCK_PX (s) + (clip.y0 - s->area.y0) * s->rs + sbpp * (clip.x0 - s->area.x0);
- w = clip.x1 - clip.x0;
- h = clip.y1 - clip.y0;
-
- switch (d->mode) {
- case NR_PIXBLOCK_MODE_A8:
- /* No rendering into alpha at moment */
- break;
- case NR_PIXBLOCK_MODE_R8G8B8:
- if (s->mode == NR_PIXBLOCK_MODE_R8G8B8A8P) {
- nr_R8G8B8_R8G8B8_R8G8B8A8_P (dpx, w, h, d->rs, spx, s->rs, alpha);
- } else {
- nr_R8G8B8_R8G8B8_R8G8B8A8_N (dpx, w, h, d->rs, spx, s->rs, alpha);
- }
- break;
- case NR_PIXBLOCK_MODE_R8G8B8A8P:
- if (d->empty) {
- if (s->mode == NR_PIXBLOCK_MODE_R8G8B8A8P) {
- /* Case 8 */
- nr_R8G8B8A8_P_EMPTY_R8G8B8A8_P (dpx, w, h, d->rs, spx, s->rs, alpha);
- } else {
- /* Case C */
- nr_R8G8B8A8_P_EMPTY_R8G8B8A8_N (dpx, w, h, d->rs, spx, s->rs, alpha);
- }
- } else {
- if (s->mode == NR_PIXBLOCK_MODE_R8G8B8A8P) {
- /* case A */
- nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_P (dpx, w, h, d->rs, spx, s->rs, alpha);
- } else {
- /* case E */
- nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_N (dpx, w, h, d->rs, spx, s->rs, alpha);
- }
- }
- break;
- case NR_PIXBLOCK_MODE_R8G8B8A8N:
- if (d->empty) {
- if (s->mode == NR_PIXBLOCK_MODE_R8G8B8A8P) {
- /* Case 9 */
- nr_R8G8B8A8_N_EMPTY_R8G8B8A8_P (dpx, w, h, d->rs, spx, s->rs, alpha);
- } else {
- /* Case D */
- nr_R8G8B8A8_N_EMPTY_R8G8B8A8_N (dpx, w, h, d->rs, spx, s->rs, alpha);
- }
- } else {
- if (s->mode == NR_PIXBLOCK_MODE_R8G8B8A8P) {
- /* case B */
- nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_P (dpx, w, h, d->rs, spx, s->rs, alpha);
- } else {
- /* case F */
- nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_N (dpx, w, h, d->rs, spx, s->rs, alpha);
- }
- }
- break;
- }
-}
-
-void
-nr_blit_pixblock_pixblock_mask (NRPixBlock *d, NRPixBlock *s, NRPixBlock *m)
-{
- NRRectL clip;
- unsigned char *dpx, *spx, *mpx;
- int dbpp, sbpp;
- int w, h;
-
- if (s->empty) return;
- /* fixme: */
- if (s->mode == NR_PIXBLOCK_MODE_A8) return;
- /* fixme: */
- if (s->mode == NR_PIXBLOCK_MODE_R8G8B8) return;
-
- /*
- * Possible variants as of now:
- *
- * 0. SRC EP - DST EP *
- * 1. SRC EP - DST EN *
- * 2. SRC EP - DST P *
- * 3. SRC EP - DST N *
- * 4. SRC EN - DST EP *
- * 5. SRC EN - DST EN *
- * 6. SRC EN - DST P *
- * 7. SRC EN - DST N *
- * 8. SRC P - DST EP *
- * 9. SRC P - DST EN *
- * A. SRC P - DST P *
- * B. SRC P - DST N *
- * C. SRC N - DST EP *
- * D. SRC N - DST EN *
- * E. SRC N - DST P *
- * F. SRC N - DST N *
- *
- */
-
- nr_rect_l_intersect (&clip, &d->area, &s->area);
- nr_rect_l_intersect (&clip, &clip, &m->area);
-
- if (nr_rect_l_test_empty(clip)) return;
-
- /* Pointers */
- dbpp = NR_PIXBLOCK_BPP (d);
- dpx = NR_PIXBLOCK_PX (d) + (clip.y0 - d->area.y0) * d->rs + dbpp * (clip.x0 - d->area.x0);
- sbpp = NR_PIXBLOCK_BPP (s);
- spx = NR_PIXBLOCK_PX (s) + (clip.y0 - s->area.y0) * s->rs + sbpp * (clip.x0 - s->area.x0);
- mpx = NR_PIXBLOCK_PX (m) + (clip.y0 - m->area.y0) * m->rs + 1 * (clip.x0 - m->area.x0);
- w = clip.x1 - clip.x0;
- h = clip.y1 - clip.y0;
-
- switch (d->mode) {
- case NR_PIXBLOCK_MODE_A8:
- /* No rendering into alpha at moment */
- break;
- case NR_PIXBLOCK_MODE_R8G8B8:
- if (s->mode == NR_PIXBLOCK_MODE_R8G8B8A8P) {
- nr_R8G8B8_R8G8B8_R8G8B8A8_P_A8 (dpx, w, h, d->rs, spx, s->rs, mpx, m->rs);
- } else {
- nr_R8G8B8_R8G8B8_R8G8B8A8_N_A8 (dpx, w, h, d->rs, spx, s->rs, mpx, m->rs);
- }
- break;
- case NR_PIXBLOCK_MODE_R8G8B8A8P:
- if (d->empty) {
- if (s->mode == NR_PIXBLOCK_MODE_R8G8B8A8P) {
- /* Case 8 */
- nr_R8G8B8A8_P_EMPTY_R8G8B8A8_P_A8 (dpx, w, h, d->rs, spx, s->rs, mpx, m->rs);
- } else {
- /* Case C */
- nr_R8G8B8A8_P_EMPTY_R8G8B8A8_N_A8 (dpx, w, h, d->rs, spx, s->rs, mpx, m->rs);
- }
- } else {
- if (s->mode == NR_PIXBLOCK_MODE_R8G8B8A8P) {
- /* case A */
- nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_P_A8 (dpx, w, h, d->rs, spx, s->rs, mpx, m->rs);
- } else {
- /* case E */
- nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_N_A8 (dpx, w, h, d->rs, spx, s->rs, mpx, m->rs);
- }
- }
- break;
- case NR_PIXBLOCK_MODE_R8G8B8A8N:
- if (d->empty) {
- if (s->mode == NR_PIXBLOCK_MODE_R8G8B8A8P) {
- /* Case 9 */
- nr_R8G8B8A8_N_EMPTY_R8G8B8A8_P_A8 (dpx, w, h, d->rs, spx, s->rs, mpx, m->rs);
- } else {
- /* Case D */
- nr_R8G8B8A8_N_EMPTY_R8G8B8A8_N_A8 (dpx, w, h, d->rs, spx, s->rs, mpx, m->rs);
- }
- } else {
- if (s->mode == NR_PIXBLOCK_MODE_R8G8B8A8P) {
- /* case B */
- nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_P_A8 (dpx, w, h, d->rs, spx, s->rs, mpx, m->rs);
- } else {
- /* case F */
- nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_N_A8 (dpx, w, h, d->rs, spx, s->rs, mpx, m->rs);
- }
- }
- break;
- }
-}
-
-void
-nr_blit_pixblock_mask_rgba32 (NRPixBlock *d, NRPixBlock *m, unsigned long rgba)
-{
- if (!(rgba & 0xff)) return;
-
- if (m) {
- NRRectL clip;
- unsigned char *dpx, *mpx;
- int w, h;
-
- if (m->mode != NR_PIXBLOCK_MODE_A8) return;
-
- if (!nr_rect_l_test_intersect(d->area, m->area)) return;
-
- nr_rect_l_intersect (&clip, &d->area, &m->area);
-
- /* Pointers */
- dpx = NR_PIXBLOCK_PX (d) + (clip.y0 - d->area.y0) * d->rs + NR_PIXBLOCK_BPP (d) * (clip.x0 - d->area.x0);
- mpx = NR_PIXBLOCK_PX (m) + (clip.y0 - m->area.y0) * m->rs + (clip.x0 - m->area.x0);
- w = clip.x1 - clip.x0;
- h = clip.y1 - clip.y0;
-
- if (d->empty) {
- if (d->mode == NR_PIXBLOCK_MODE_R8G8B8) {
- nr_R8G8B8_R8G8B8_A8_RGBA32 (dpx, w, h, d->rs, mpx, m->rs, rgba);
- } else if (d->mode == NR_PIXBLOCK_MODE_R8G8B8A8P) {
- nr_R8G8B8A8_P_EMPTY_A8_RGBA32 (dpx, w, h, d->rs, mpx, m->rs, rgba);
- } else {
- nr_R8G8B8A8_N_EMPTY_A8_RGBA32 (dpx, w, h, d->rs, mpx, m->rs, rgba);
- }
- d->empty = 0;
- } else {
- if (d->mode == NR_PIXBLOCK_MODE_R8G8B8) {
- nr_R8G8B8_R8G8B8_A8_RGBA32 (dpx, w, h, d->rs, mpx, m->rs, rgba);
- } else if (d->mode == NR_PIXBLOCK_MODE_R8G8B8A8P) {
- nr_R8G8B8A8_P_R8G8B8A8_P_A8_RGBA32 (dpx, w, h, d->rs, mpx, m->rs, rgba);
- } else {
- nr_R8G8B8A8_N_R8G8B8A8_N_A8_RGBA32 (dpx, w, h, d->rs, mpx, m->rs, rgba);
- }
- }
- } else {
- unsigned int r, g, b, a;
- int x, y;
- r = NR_RGBA32_R (rgba);
- g = NR_RGBA32_G (rgba);
- b = NR_RGBA32_B (rgba);
- a = NR_RGBA32_A (rgba);
- for (y = d->area.y0; y < d->area.y1; y++) {
- unsigned char *p;
- p = NR_PIXBLOCK_PX (d) + (y - d->area.y0) * d->rs;
- for (x = d->area.x0; x < d->area.x1; x++) {
- unsigned int da;
- switch (d->mode) {
- case NR_PIXBLOCK_MODE_R8G8B8:
- p[0] = NR_COMPOSEN11_1111 (r, a, p[0]);
- p[1] = NR_COMPOSEN11_1111 (g, a, p[1]);
- p[2] = NR_COMPOSEN11_1111 (b, a, p[2]);
- p += 3;
- break;
- case NR_PIXBLOCK_MODE_R8G8B8A8P:
- p[0] = NR_COMPOSENPP_1111 (r, a, p[0]);
- p[1] = NR_COMPOSENPP_1111 (g, a, p[1]);
- p[2] = NR_COMPOSENPP_1111 (b, a, p[2]);
- p[3] = NR_COMPOSEA_111(a, p[3]);
- p += 4;
- break;
- case NR_PIXBLOCK_MODE_R8G8B8A8N:
- da = NR_COMPOSEA_112(a, p[3]);
- p[0] = NR_COMPOSENNN_111121 (r, a, p[0], p[3], da);
- p[1] = NR_COMPOSENNN_111121 (g, a, p[1], p[3], da);
- p[2] = NR_COMPOSENNN_111121 (b, a, p[2], p[3], da);
- p[3] = NR_NORMALIZE_21(da);
- p += 4;
- break;
- default:
- break;
- }
- }
- }
- }
-}
-
diff --git a/src/libnr/nr-blit.h b/src/libnr/nr-blit.h
deleted file mode 100644
index 9c2def114..000000000
--- a/src/libnr/nr-blit.h
+++ /dev/null
@@ -1,32 +0,0 @@
-#ifndef __NR_BLIT_H__
-#define __NR_BLIT_H__
-
-/*
- * Pixel buffer rendering library
- *
- * Authors:
- * Lauris Kaplinski <lauris@kaplinski.com>
- *
- * This code is in public domain
- */
-
-#include <libnr/nr-pixblock.h>
-
-#define nr_blit_pixblock_pixblock(d,s) nr_blit_pixblock_pixblock_alpha (d, s, 255)
-
-void nr_blit_pixblock_pixblock_alpha (NRPixBlock *d, NRPixBlock *s, unsigned int alpha);
-void nr_blit_pixblock_pixblock_mask (NRPixBlock *d, NRPixBlock *s, NRPixBlock *m);
-void nr_blit_pixblock_mask_rgba32 (NRPixBlock *d, NRPixBlock *m, unsigned long rgba32);
-
-#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:textwidth=99 :
diff --git a/src/libnr/nr-compose-reference.cpp b/src/libnr/nr-compose-reference.cpp
deleted file mode 100644
index b4ff5851a..000000000
--- a/src/libnr/nr-compose-reference.cpp
+++ /dev/null
@@ -1,266 +0,0 @@
-
-// This is a reference implementation of the compositing functions in nr-compose.cpp.
-
-#include "nr-compose-reference.h"
-
-#define NR_RGBA32_R(v) (unsigned char) (((v) >> 24) & 0xff)
-#define NR_RGBA32_G(v) (unsigned char) (((v) >> 16) & 0xff)
-#define NR_RGBA32_B(v) (unsigned char) (((v) >> 8) & 0xff)
-#define NR_RGBA32_A(v) (unsigned char) ((v) & 0xff)
-
-static inline unsigned int DIV_ROUND(unsigned int v, unsigned int divisor) { return (v+divisor/2)/divisor; }
-
-static unsigned int pixelSize[] = { 1, 3, 4, 4 };
-
-// Computes :
-// dc' = (1 - alpha*sa) * dc + alpha*sc
-// da' = 1 - (1 - alpha*sa) * (1 - da)
-// Assuming premultiplied color values
-template<PIXEL_FORMAT resultFormat, PIXEL_FORMAT backgroundFormat, PIXEL_FORMAT foregroundFormat>
-static void composePixel(unsigned char *d, const unsigned char *s, unsigned int alpha);
-
-template<> void composePixel<R8G8B8, R8G8B8, R8G8B8A8N>(unsigned char *d, const unsigned char *s, unsigned int alpha) {
- d[0] = DIV_ROUND((255*255 - alpha*s[3]) * d[0] + alpha*s[3]*s[0], 255*255);
- d[1] = DIV_ROUND((255*255 - alpha*s[3]) * d[1] + alpha*s[3]*s[1], 255*255);
- d[2] = DIV_ROUND((255*255 - alpha*s[3]) * d[2] + alpha*s[3]*s[2], 255*255);
-}
-
-template<> void composePixel<R8G8B8, R8G8B8, R8G8B8A8P>(unsigned char *d, const unsigned char *s, unsigned int alpha) {
- d[0] = DIV_ROUND((255*255 - alpha*s[3]) * d[0] + 255*alpha*s[0], 255*255);
- d[1] = DIV_ROUND((255*255 - alpha*s[3]) * d[1] + 255*alpha*s[1], 255*255);
- d[2] = DIV_ROUND((255*255 - alpha*s[3]) * d[2] + 255*alpha*s[2], 255*255);
-}
-
-template<> void composePixel<R8G8B8A8N, EMPTY, R8G8B8A8N>(unsigned char *d, const unsigned char *s, unsigned int alpha) {
- unsigned int newa = 255*255 - (255*255 - alpha*s[3]);
- d[0] = s[0];//newa == 0 ? 0 : DIV_ROUND(alpha*s[3]*s[0], newa);
- d[1] = s[1];//newa == 0 ? 0 : DIV_ROUND(alpha*s[3]*s[1], newa);
- d[2] = s[2];//newa == 0 ? 0 : DIV_ROUND(alpha*s[3]*s[2], newa);
- d[3] = DIV_ROUND(newa, 255);
-}
-
-template<> void composePixel<R8G8B8A8N, EMPTY, R8G8B8A8P>(unsigned char *d, const unsigned char *s, unsigned int alpha) {
- unsigned int newa = 255*255 - (255*255 - alpha*s[3]);
- d[0] = s[3] == 0 ? 0 : DIV_ROUND(255*s[0], s[3]);//newa == 0 ? 0 : DIV_ROUND(255*alpha*s[0], newa);
- d[1] = s[3] == 0 ? 0 : DIV_ROUND(255*s[1], s[3]);//newa == 0 ? 0 : DIV_ROUND(255*alpha*s[1], newa);
- d[2] = s[3] == 0 ? 0 : DIV_ROUND(255*s[2], s[3]);//newa == 0 ? 0 : DIV_ROUND(255*alpha*s[2], newa);
- d[3] = DIV_ROUND(newa, 255);
-}
-
-template<> void composePixel<R8G8B8A8N, R8G8B8A8N, R8G8B8A8N>(unsigned char *d, const unsigned char *s, unsigned int alpha) {
- if ( d[3] == 0 ) {
- composePixel<R8G8B8A8N, EMPTY, R8G8B8A8N>(d, s, alpha);
- } else if ( alpha*s[3] == 0 ) {
- /* NOP */
- } else {
- unsigned int newa = 255*255*255 - (255*255 - alpha*s[3]) * (255 - d[3]);
- d[0] = DIV_ROUND((255*255 - alpha*s[3]) * d[3]*d[0] + 255 * alpha*s[3]*s[0], newa);
- d[1] = DIV_ROUND((255*255 - alpha*s[3]) * d[3]*d[1] + 255 * alpha*s[3]*s[1], newa);
- d[2] = DIV_ROUND((255*255 - alpha*s[3]) * d[3]*d[2] + 255 * alpha*s[3]*s[2], newa);
- d[3] = DIV_ROUND(newa, 255*255);
- }
-}
-
-template<> void composePixel<R8G8B8A8N, R8G8B8A8N, R8G8B8A8P>(unsigned char *d, const unsigned char *s, unsigned int alpha) {
- if ( d[3] == 0 ) {
- composePixel<R8G8B8A8N, EMPTY, R8G8B8A8P>(d, s, alpha);
- } else if ( alpha*s[3] == 0 ) {
- /* NOP */
- } else {
- unsigned int newa = 255*255*255 - (255*255 - alpha*s[3]) * (255 - d[3]);
- d[0] = DIV_ROUND((255*255 - alpha*s[3]) * d[3]*d[0] + 255*255 * alpha*s[0], newa);
- d[1] = DIV_ROUND((255*255 - alpha*s[3]) * d[3]*d[1] + 255*255 * alpha*s[1], newa);
- d[2] = DIV_ROUND((255*255 - alpha*s[3]) * d[3]*d[2] + 255*255 * alpha*s[2], newa);
- d[3] = DIV_ROUND(newa, 255*255);
- }
-}
-
-template<> void composePixel<R8G8B8A8P, EMPTY, R8G8B8A8N>(unsigned char *d, const unsigned char *s, unsigned int alpha) {
- d[0] = DIV_ROUND(alpha*s[3]*s[0], 255*255);
- d[1] = DIV_ROUND(alpha*s[3]*s[1], 255*255);
- d[2] = DIV_ROUND(alpha*s[3]*s[2], 255*255);
- d[3] = DIV_ROUND(255*255 - (255*255 - alpha*s[3]), 255);
-}
-
-template<> void composePixel<R8G8B8A8P, EMPTY, R8G8B8A8P>(unsigned char *d, const unsigned char *s, unsigned int alpha) {
- d[0] = DIV_ROUND(alpha*s[0], 255);
- d[1] = DIV_ROUND(alpha*s[1], 255);
- d[2] = DIV_ROUND(alpha*s[2], 255);
- d[3] = DIV_ROUND(255*255 - (255*255 - alpha*s[3]), 255);
-}
-
-template<> void composePixel<R8G8B8A8P, R8G8B8A8P, R8G8B8A8N>(unsigned char *d, const unsigned char *s, unsigned int alpha) {
- d[0] = DIV_ROUND((255*255 - alpha*s[3]) * d[0] + alpha*s[3]*s[0], 255*255);
- d[1] = DIV_ROUND((255*255 - alpha*s[3]) * d[1] + alpha*s[3]*s[1], 255*255);
- d[2] = DIV_ROUND((255*255 - alpha*s[3]) * d[2] + alpha*s[3]*s[2], 255*255);
- d[3] = DIV_ROUND(255*255*255 - (255*255 - alpha*s[3]) * (255 - d[3]), 255*255);
-}
-
-template<> void composePixel<R8G8B8A8P, R8G8B8A8P, R8G8B8A8P>(unsigned char *d, const unsigned char *s, unsigned int alpha) {
- d[0] = DIV_ROUND((255*255 - alpha*s[3]) * d[0] + 255 * alpha*s[0], 255*255);
- d[1] = DIV_ROUND((255*255 - alpha*s[3]) * d[1] + 255 * alpha*s[1], 255*255);
- d[2] = DIV_ROUND((255*255 - alpha*s[3]) * d[2] + 255 * alpha*s[2], 255*255);
- d[3] = DIV_ROUND(255*255*255 - (255*255 - alpha*s[3]) * (255 - d[3]), 255*255);
-}
-
-
-// composeAlpha, iterates over all pixels and applies composePixel to each of them
-template<PIXEL_FORMAT resultFormat, PIXEL_FORMAT backgroundFormat, PIXEL_FORMAT foregroundFormat>
-static void composeAlpha(unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha) {
- for(int y=0; y<h; y++) {
- unsigned char* d = px;
- const unsigned char* s = spx;
- for(int x=0; x<w; x++) {
- composePixel<resultFormat, backgroundFormat, foregroundFormat>(d, s, alpha);
- d += pixelSize[resultFormat];
- s += pixelSize[foregroundFormat];
- }
- px += rs;
- spx += srs;
- }
-}
-
-template<PIXEL_FORMAT resultFormat, PIXEL_FORMAT backgroundFormat, PIXEL_FORMAT foregroundFormat>
-static void composeMask(unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, const unsigned char *mpx, int mrs) {
- for(int y=0; y<h; y++) {
- unsigned char* d = px;
- const unsigned char* s = spx;
- const unsigned char* m = mpx;
- for(int x=0; x<w; x++) {
- composePixel<resultFormat, backgroundFormat, foregroundFormat>(d, s, *m);
- d += pixelSize[resultFormat];
- s += pixelSize[foregroundFormat];
- m += 1;
- }
- px += rs;
- spx += srs;
- mpx += mrs;
- }
-}
-
-template<PIXEL_FORMAT resultFormat, PIXEL_FORMAT backgroundFormat>
-static void composeColor(unsigned char *px, int w, int h, int rs, const unsigned char *mpx, int mrs, unsigned long rgba) {
- const unsigned char rgba_array[4] = {NR_RGBA32_R(rgba), NR_RGBA32_G(rgba), NR_RGBA32_B(rgba), NR_RGBA32_A(rgba)};
- for(int y=0; y<h; y++) {
- unsigned char* d = px;
- const unsigned char* m = mpx;
- for(int x=0; x<w; x++) {
- composePixel<resultFormat, backgroundFormat, R8G8B8A8N>(d, rgba_array, *m);
- d += pixelSize[resultFormat];
- m += 1;
- }
- px += rs;
- mpx += mrs;
- }
-}
-
-/* FINAL DST SRC */
-
-void nr_R8G8B8A8_N_EMPTY_R8G8B8A8_N_ref (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha) {
- composeAlpha<R8G8B8A8N, EMPTY, R8G8B8A8N>(px, w, h, rs, spx, srs, alpha);
-}
-
-void nr_R8G8B8A8_N_EMPTY_R8G8B8A8_P_ref (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha) {
- composeAlpha<R8G8B8A8N, EMPTY, R8G8B8A8P>(px, w, h, rs, spx, srs, alpha);
-}
-
-void nr_R8G8B8A8_P_EMPTY_R8G8B8A8_N_ref (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha) {
- composeAlpha<R8G8B8A8P, EMPTY, R8G8B8A8N>(px, w, h, rs, spx, srs, alpha);
-}
-
-void nr_R8G8B8A8_P_EMPTY_R8G8B8A8_P_ref (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha) {
- composeAlpha<R8G8B8A8P, EMPTY, R8G8B8A8P>(px, w, h, rs, spx, srs, alpha);
-}
-
-
-void nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_N_ref (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha) {
- composeAlpha<R8G8B8A8N, R8G8B8A8N, R8G8B8A8N>(px, w, h, rs, spx, srs, alpha);
-}
-
-void nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_P_ref (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha) {
- composeAlpha<R8G8B8A8N, R8G8B8A8N, R8G8B8A8P>(px, w, h, rs, spx, srs, alpha);
-}
-
-void nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_N_ref (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha) {
- composeAlpha<R8G8B8A8P, R8G8B8A8P, R8G8B8A8N>(px, w, h, rs, spx, srs, alpha);
-}
-
-void nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_P_ref (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha) {
- composeAlpha<R8G8B8A8P, R8G8B8A8P, R8G8B8A8P>(px, w, h, rs, spx, srs, alpha);
-}
-
-/* FINAL DST SRC MASK */
-
-void nr_R8G8B8A8_N_EMPTY_R8G8B8A8_N_A8_ref (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, const unsigned char *mpx, int mrs) {
- composeMask<R8G8B8A8N, EMPTY, R8G8B8A8N>(px, w, h, rs, spx, srs, mpx, mrs);
-}
-
-void nr_R8G8B8A8_N_EMPTY_R8G8B8A8_P_A8_ref (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, const unsigned char *mpx, int mrs) {
- composeMask<R8G8B8A8N, EMPTY, R8G8B8A8P>(px, w, h, rs, spx, srs, mpx, mrs);
-}
-
-void nr_R8G8B8A8_P_EMPTY_R8G8B8A8_N_A8_ref (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, const unsigned char *mpx, int mrs) {
- composeMask<R8G8B8A8P, EMPTY, R8G8B8A8N>(px, w, h, rs, spx, srs, mpx, mrs);
-}
-
-void nr_R8G8B8A8_P_EMPTY_R8G8B8A8_P_A8_ref (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, const unsigned char *mpx, int mrs) {
- composeMask<R8G8B8A8P, EMPTY, R8G8B8A8P>(px, w, h, rs, spx, srs, mpx, mrs);
-}
-
-
-void nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_N_A8_ref (unsigned char *p, int w, int h, int rs, const unsigned char *s, int srs, const unsigned char *m, int mrs) {
- composeMask<R8G8B8A8N, R8G8B8A8N, R8G8B8A8N>(p, w, h, rs, s, srs, m, mrs);
-}
-
-void nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_P_A8_ref (unsigned char *p, int w, int h, int rs, const unsigned char *s, int srs, const unsigned char *m, int mrs) {
- composeMask<R8G8B8A8N, R8G8B8A8N, R8G8B8A8P>(p, w, h, rs, s, srs, m, mrs);
-}
-
-void nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_N_A8_ref (unsigned char *p, int w, int h, int rs, const unsigned char *s, int srs, const unsigned char *m, int mrs) {
- composeMask<R8G8B8A8P, R8G8B8A8P, R8G8B8A8N>(p, w, h, rs, s, srs, m, mrs);
-}
-
-void nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_P_A8_ref (unsigned char *p, int w, int h, int rs, const unsigned char *s, int srs, const unsigned char *m, int mrs) {
- composeMask<R8G8B8A8P, R8G8B8A8P, R8G8B8A8P>(p, w, h, rs, s, srs, m, mrs);
-}
-
-/* FINAL DST MASK COLOR */
-
-void nr_R8G8B8A8_N_EMPTY_A8_RGBA32_ref (unsigned char *px, int w, int h, int rs, const unsigned char *mpx, int mrs, unsigned long rgba) {
- composeColor<R8G8B8A8N, EMPTY>(px, w, h, rs, mpx, mrs, rgba);
-}
-
-void nr_R8G8B8A8_P_EMPTY_A8_RGBA32_ref (unsigned char *px, int w, int h, int rs, const unsigned char *mpx, int mrs, unsigned long rgba) {
- composeColor<R8G8B8A8P, EMPTY>(px, w, h, rs, mpx, mrs, rgba);
-}
-
-
-void nr_R8G8B8_R8G8B8_A8_RGBA32_ref (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned long rgba) {
- composeColor<R8G8B8, R8G8B8>(px, w, h, rs, spx, srs, rgba);
-}
-
-void nr_R8G8B8A8_N_R8G8B8A8_N_A8_RGBA32_ref (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned long rgba) {
- composeColor<R8G8B8A8N, R8G8B8A8N>(px, w, h, rs, spx, srs, rgba);
-}
-
-void nr_R8G8B8A8_P_R8G8B8A8_P_A8_RGBA32_ref (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned long rgba) {
- composeColor<R8G8B8A8P, R8G8B8A8P>(px, w, h, rs, spx, srs, rgba);
-}
-
-/* RGB */
-
-void nr_R8G8B8_R8G8B8_R8G8B8A8_P_ref (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha) {
- composeAlpha<R8G8B8, R8G8B8, R8G8B8A8P>(px, w, h, rs, spx, srs, alpha);
-}
-
-void nr_R8G8B8_R8G8B8_R8G8B8A8_N_ref (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha) {
- composeAlpha<R8G8B8, R8G8B8, R8G8B8A8N>(px, w, h, rs, spx, srs, alpha);
-}
-
-void nr_R8G8B8_R8G8B8_R8G8B8A8_P_A8_ref (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, const unsigned char *mpx, int mrs) {
- composeMask<R8G8B8, R8G8B8, R8G8B8A8P>(px, w, h, rs, spx, srs, mpx, mrs);
-}
-
-void nr_R8G8B8_R8G8B8_R8G8B8A8_N_A8_ref (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, const unsigned char *mpx, int mrs) {
- composeMask<R8G8B8, R8G8B8, R8G8B8A8N>(px, w, h, rs, spx, srs, mpx, mrs);
-}
diff --git a/src/libnr/nr-compose-reference.h b/src/libnr/nr-compose-reference.h
deleted file mode 100644
index 8d004a135..000000000
--- a/src/libnr/nr-compose-reference.h
+++ /dev/null
@@ -1,69 +0,0 @@
-#ifndef __NR_COMPOSE_REFERENCE_H__
-#define __NR_COMPOSE_REFERENCE_H__
-
-// Based on nr-pixblock.h
-typedef enum {
- A8 = 0,
- R8G8B8,
- R8G8B8A8N,
- R8G8B8A8P,
- EMPTY = -1
-} PIXEL_FORMAT;
-
-/* FINAL DST SRC */
-
-void nr_R8G8B8A8_N_EMPTY_R8G8B8A8_N_ref (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha);
-void nr_R8G8B8A8_N_EMPTY_R8G8B8A8_P_ref (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha);
-void nr_R8G8B8A8_P_EMPTY_R8G8B8A8_N_ref (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha);
-void nr_R8G8B8A8_P_EMPTY_R8G8B8A8_P_ref (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha);
-
-void nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_N_ref (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha);
-void nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_P_ref (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha);
-void nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_N_ref (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha);
-void nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_P_ref (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha);
-
-/* FINAL DST SRC MASK */
-
-void nr_R8G8B8A8_N_EMPTY_R8G8B8A8_N_A8_ref (unsigned char *px, int w, int h, int rs,
- const unsigned char *spx, int srs,
- const unsigned char *mpx, int mrs);
-void nr_R8G8B8A8_N_EMPTY_R8G8B8A8_P_A8_ref (unsigned char *px, int w, int h, int rs,
- const unsigned char *spx, int srs,
- const unsigned char *mpx, int mrs);
-void nr_R8G8B8A8_P_EMPTY_R8G8B8A8_N_A8_ref (unsigned char *px, int w, int h, int rs,
- const unsigned char *spx, int srs,
- const unsigned char *mpx, int mrs);
-void nr_R8G8B8A8_P_EMPTY_R8G8B8A8_P_A8_ref (unsigned char *px, int w, int h, int rs,
- const unsigned char *spx, int srs,
- const unsigned char *mpx, int mrs);
-
-void nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_N_A8_ref (unsigned char *p, int w, int h, int rs,
- const unsigned char *s, int srs,
- const unsigned char *m, int mrs);
-void nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_P_A8_ref (unsigned char *p, int w, int h, int rs,
- const unsigned char *s, int srs,
- const unsigned char *m, int mrs);
-void nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_N_A8_ref (unsigned char *p, int w, int h, int rs,
- const unsigned char *s, int srs,
- const unsigned char *m, int mrs);
-void nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_P_A8_ref (unsigned char *p, int w, int h, int rs,
- const unsigned char *s, int srs,
- const unsigned char *m, int mrs);
-
-/* FINAL DST MASK COLOR */
-
-void nr_R8G8B8A8_N_EMPTY_A8_RGBA32_ref (unsigned char *px, int w, int h, int rs, const unsigned char *mpx, int mrs, unsigned long rgba);
-void nr_R8G8B8A8_P_EMPTY_A8_RGBA32_ref (unsigned char *px, int w, int h, int rs, const unsigned char *mpx, int mrs, unsigned long rgba);
-
-void nr_R8G8B8_R8G8B8_A8_RGBA32_ref (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned long rgba);
-void nr_R8G8B8A8_N_R8G8B8A8_N_A8_RGBA32_ref (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned long rgba);
-void nr_R8G8B8A8_P_R8G8B8A8_P_A8_RGBA32_ref (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned long rgba);
-
-/* RGB */
-
-void nr_R8G8B8_R8G8B8_R8G8B8A8_P_ref (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha);
-void nr_R8G8B8_R8G8B8_R8G8B8A8_N_ref (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha);
-void nr_R8G8B8_R8G8B8_R8G8B8A8_P_A8_ref (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, const unsigned char *mpx, int mrs);
-void nr_R8G8B8_R8G8B8_R8G8B8A8_N_A8_ref (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, const unsigned char *mpx, int mrs);
-
-#endif//__NR_COMPOSE_REFERENCE_H__
diff --git a/src/libnr/nr-compose-test.h b/src/libnr/nr-compose-test.h
deleted file mode 100644
index 2164e1bf4..000000000
--- a/src/libnr/nr-compose-test.h
+++ /dev/null
@@ -1,457 +0,0 @@
-
-#include <cxxtest/TestSuite.h>
-
-#include "nr-compose.h"
-#include "nr-compose-reference.h"
-#include <glib.h>
-#include <memory.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-static inline unsigned int DIV_ROUND(unsigned int v, unsigned int divisor) { return (v+divisor/2)/divisor; }
-static inline unsigned char NR_PREMUL_111(unsigned int c, unsigned int a) { return static_cast<unsigned char>(DIV_ROUND(c*a, 255)); }
-
-template<PIXEL_FORMAT format>
-int IMGCMP(const unsigned char* a, const unsigned char* b, size_t n) { return memcmp(a, b, n); }
-
-template<>
-int IMGCMP<R8G8B8A8N>(const unsigned char* a, const unsigned char* b, size_t n)
-{
- // If two pixels each have their alpha channel set to zero they're equivalent
- // Note that this doesn't work for premultiplied values, as their color values should
- // be zero when alpha is zero.
- int cr = 0;
- while(n && cr == 0) {
- if ( a[3] != 0 || b[3] != 0 ) {
- cr = memcmp(a, b, 4);
- }
- a+=4;
- b+=4;
- n-=4;
- }
- return cr;
-}
-
-class NrComposeTest : public CxxTest::TestSuite {
-private:
- int const w, h;
-
- unsigned char* const dst_rgba_n_org;
- unsigned char* const dst_rgba_p_org;
- unsigned char* const dst_rgb_org;
-
- unsigned char* const dst1_rgba;
- unsigned char* const dst2_rgba;
- unsigned char* const src_rgba_n;
- unsigned char* const src_rgba_p;
- unsigned char* const dst1_rgb;
- unsigned char* const dst2_rgb;
- unsigned char* const src_rgb;
- unsigned char* const mask;
-
- static unsigned int const alpha_vals[7];
- static unsigned int const rgb_vals[3];
-
-public:
- NrComposeTest() :
- w(13),
- h(5),
-
- dst_rgba_n_org(new unsigned char[w*h*4]),
- dst_rgba_p_org(new unsigned char[w*h*4]),
- dst_rgb_org(new unsigned char[w*h*3]),
-
- dst1_rgba(new unsigned char[w*h*4]),
- dst2_rgba(new unsigned char[w*h*4]),
- src_rgba_n(new unsigned char[w*h*4]),
- src_rgba_p(new unsigned char[w*h*4]),
- dst1_rgb(new unsigned char[w*h*3]),
- dst2_rgb(new unsigned char[w*h*3]),
- src_rgb(new unsigned char[w*h*3]),
- mask(new unsigned char[w*h])
- {
- srand(23874683); // It shouldn't really matter what this is, as long as it's always the same (to be reproducible)
-
- for(int y=0; y<h; y++) {
- for(int x=0; x<w; x++) {
- dst_rgba_n_org[(x+y*w)*4+3] = 255*rand()/RAND_MAX;
- dst_rgba_p_org[(x+y*w)*4+3] = 255*rand()/RAND_MAX;
- src_rgba_n[(x+y*w)*4+3] = 255*rand()/RAND_MAX;
- src_rgba_p[(x+y*w)*4+3] = 255*rand()/RAND_MAX;
- for(int i=0; i<3; i++) {
- dst_rgba_n_org[(x+y*w)*4+i] = 255*rand()/RAND_MAX;
- dst_rgba_p_org[(x+y*w)*4+i] = NR_PREMUL_111(255*rand()/RAND_MAX, dst_rgba_p_org[(x+y*w)*4+3]);
- src_rgba_n[(x+y*w)*4+i] = 255*rand()/RAND_MAX;
- src_rgba_p[(x+y*w)*4+i] = NR_PREMUL_111(255*rand()/RAND_MAX, src_rgba_p[(x+y*w)*4+3]);
- dst_rgb_org[(x+y*w)*3+i] = 255*rand()/RAND_MAX;
- }
- mask[x+y*w] = 255*rand()/RAND_MAX;
- }
- }
- }
- virtual ~NrComposeTest()
- {
- delete[] dst_rgba_n_org;
- delete[] dst_rgba_p_org;
- delete[] dst_rgb_org;
-
- delete[] dst1_rgba;
- delete[] dst2_rgba;
- delete[] src_rgba_n;
- delete[] src_rgba_p;
- delete[] dst1_rgb;
- delete[] dst2_rgb;
- delete[] src_rgb;
- delete[] mask;
- }
-
-// createSuite and destroySuite get us per-suite setup and teardown
-// without us having to worry about static initialization order, etc.
- static NrComposeTest *createSuite() { return new NrComposeTest(); }
- static void destroySuite( NrComposeTest *suite ) { delete suite; }
-
- // FINAL DST SRC
-
- void testnr_R8G8B8A8_N_EMPTY_R8G8B8A8_N()
- {
- for(size_t i=0; i<G_N_ELEMENTS(alpha_vals); i++) {
- unsigned int alpha = alpha_vals[i];
- char msg[40];
- sprintf(msg, "alpha = %u", alpha);
- memcpy(dst1_rgba, dst_rgba_n_org, w*h*4);
- memcpy(dst2_rgba, dst_rgba_n_org, w*h*4);
- nr_R8G8B8A8_N_EMPTY_R8G8B8A8_N(dst1_rgba, w, h, w*4, src_rgba_n, w*4, alpha);
- nr_R8G8B8A8_N_EMPTY_R8G8B8A8_N_ref(dst2_rgba, w, h, w*4, src_rgba_n, w*4, alpha);
- TSM_ASSERT(msg, IMGCMP<R8G8B8A8N>(dst1_rgba, dst2_rgba, w*h*4) == 0 );
- }
- }
-
- void testnr_R8G8B8A8_N_EMPTY_R8G8B8A8_P()
- {
- for(size_t i=0; i<G_N_ELEMENTS(alpha_vals); i++) {
- unsigned int alpha = alpha_vals[i];
- char msg[40];
- sprintf(msg, "alpha = %u", alpha);
- memcpy(dst1_rgba, dst_rgba_n_org, w*h*4);
- memcpy(dst2_rgba, dst_rgba_n_org, w*h*4);
- nr_R8G8B8A8_N_EMPTY_R8G8B8A8_P(dst1_rgba, w, h, w*4, src_rgba_p, w*4, alpha);
- nr_R8G8B8A8_N_EMPTY_R8G8B8A8_P_ref(dst2_rgba, w, h, w*4, src_rgba_p, w*4, alpha);
- TSM_ASSERT(msg, IMGCMP<R8G8B8A8N>(dst1_rgba, dst2_rgba, w*h*4) == 0 );
- }
- }
-
- void testnr_R8G8B8A8_P_EMPTY_R8G8B8A8_N()
- {
- for(size_t i=0; i<G_N_ELEMENTS(alpha_vals); i++) {
- unsigned int alpha = alpha_vals[i];
- char msg[40];
- sprintf(msg, "alpha = %u", alpha);
- memcpy(dst1_rgba, dst_rgba_p_org, w*h*4);
- memcpy(dst2_rgba, dst_rgba_p_org, w*h*4);
- nr_R8G8B8A8_P_EMPTY_R8G8B8A8_N(dst1_rgba, w, h, w*4, src_rgba_n, w*4, alpha);
- nr_R8G8B8A8_P_EMPTY_R8G8B8A8_N_ref(dst2_rgba, w, h, w*4, src_rgba_n, w*4, alpha);
- TSM_ASSERT(msg, IMGCMP<R8G8B8A8P>(dst1_rgba, dst2_rgba, w*h*4) == 0 );
- }
- }
-
- void testnr_R8G8B8A8_P_EMPTY_R8G8B8A8_P()
- {
- for(size_t i=0; i<G_N_ELEMENTS(alpha_vals); i++) {
- unsigned int alpha = alpha_vals[i];
- char msg[40];
- sprintf(msg, "alpha = %u", alpha);
- memcpy(dst1_rgba, dst_rgba_p_org, w*h*4);
- memcpy(dst2_rgba, dst_rgba_p_org, w*h*4);
- nr_R8G8B8A8_P_EMPTY_R8G8B8A8_P(dst1_rgba, w, h, w*4, src_rgba_p, w*4, alpha);
- nr_R8G8B8A8_P_EMPTY_R8G8B8A8_P_ref(dst2_rgba, w, h, w*4, src_rgba_p, w*4, alpha);
- TSM_ASSERT(msg, IMGCMP<R8G8B8A8P>(dst1_rgba, dst2_rgba, w*h*4) == 0 );
- }
- }
-
- void testnr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_N()
- {
- for(size_t i=0; i<G_N_ELEMENTS(alpha_vals); i++) {
- unsigned int alpha = alpha_vals[i];
- char msg[40];
- sprintf(msg, "alpha = %u", alpha);
- memcpy(dst1_rgba, dst_rgba_n_org, w*h*4);
- memcpy(dst2_rgba, dst_rgba_n_org, w*h*4);
- nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_N(dst1_rgba, w, h, w*4, src_rgba_n, w*4, alpha);
- nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_N_ref(dst2_rgba, w, h, w*4, src_rgba_n, w*4, alpha);
- TSM_ASSERT(msg, IMGCMP<R8G8B8A8N>(dst1_rgba, dst2_rgba, w*h*4) == 0 );
- }
- }
-
- void testnr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_P()
- {
- for(size_t i=0; i<G_N_ELEMENTS(alpha_vals); i++) {
- unsigned int alpha = alpha_vals[i];
- char msg[40];
- sprintf(msg, "alpha = %u", alpha);
- memcpy(dst1_rgba, dst_rgba_n_org, w*h*4);
- memcpy(dst2_rgba, dst_rgba_n_org, w*h*4);
- nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_P(dst1_rgba, w, h, w*4, src_rgba_p, w*4, alpha);
- nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_P_ref(dst2_rgba, w, h, w*4, src_rgba_p, w*4, alpha);
- TSM_ASSERT(msg, IMGCMP<R8G8B8A8N>(dst1_rgba, dst2_rgba, w*h*4) == 0 );
- }
- }
-
- void testnr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_N()
- {
- for(size_t i=0; i<G_N_ELEMENTS(alpha_vals); i++) {
- unsigned int alpha = alpha_vals[i];
- char msg[40];
- sprintf(msg, "alpha = %u", alpha);
- memcpy(dst1_rgba, dst_rgba_p_org, w*h*4);
- memcpy(dst2_rgba, dst_rgba_p_org, w*h*4);
- nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_N(dst1_rgba, w, h, w*4, src_rgba_n, w*4, alpha);
- nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_N_ref(dst2_rgba, w, h, w*4, src_rgba_n, w*4, alpha);
- TSM_ASSERT(msg, IMGCMP<R8G8B8A8P>(dst1_rgba, dst2_rgba, w*h*4) == 0 );
- }
- }
-
- void testnr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_P()
- {
- for(size_t i=0; i<G_N_ELEMENTS(alpha_vals); i++) {
- unsigned int alpha = alpha_vals[i];
- char msg[40];
- sprintf(msg, "alpha = %u", alpha);
- memcpy(dst1_rgba, dst_rgba_p_org, w*h*4);
- memcpy(dst2_rgba, dst_rgba_p_org, w*h*4);
- nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_P(dst1_rgba, w, h, w*4, src_rgba_p, w*4, alpha);
- nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_P_ref(dst2_rgba, w, h, w*4, src_rgba_p, w*4, alpha);
- TSM_ASSERT(msg, IMGCMP<R8G8B8A8P>(dst1_rgba, dst2_rgba, w*h*4) == 0 );
- }
- }
-
- // FINAL DST SRC MASK
-
- void testnr_R8G8B8A8_N_EMPTY_R8G8B8A8_N_A8()
- {
- memcpy(dst1_rgba, dst_rgba_n_org, w*h*4);
- memcpy(dst2_rgba, dst_rgba_n_org, w*h*4);
- nr_R8G8B8A8_N_EMPTY_R8G8B8A8_N_A8(dst1_rgba, w, h, w*4, src_rgba_n, w*4, mask, w);
- nr_R8G8B8A8_N_EMPTY_R8G8B8A8_N_A8_ref(dst2_rgba, w, h, w*4, src_rgba_n, w*4, mask, w);
- TS_ASSERT( IMGCMP<R8G8B8A8N>(dst1_rgba, dst2_rgba, w*h*4) == 0 );
- }
-
- void testnr_R8G8B8A8_N_EMPTY_R8G8B8A8_P_A8()
- {
- memcpy(dst1_rgba, dst_rgba_n_org, w*h*4);
- memcpy(dst2_rgba, dst_rgba_n_org, w*h*4);
- nr_R8G8B8A8_N_EMPTY_R8G8B8A8_P_A8(dst1_rgba, w, h, w*4, src_rgba_p, w*4, mask, w);
- nr_R8G8B8A8_N_EMPTY_R8G8B8A8_P_A8_ref(dst2_rgba, w, h, w*4, src_rgba_p, w*4, mask, w);
- TS_ASSERT( IMGCMP<R8G8B8A8N>(dst1_rgba, dst2_rgba, w*h*4) == 0 );
- }
-
- void testnr_R8G8B8A8_P_EMPTY_R8G8B8A8_N_A8()
- {
- memcpy(dst1_rgba, dst_rgba_p_org, w*h*4);
- memcpy(dst2_rgba, dst_rgba_p_org, w*h*4);
- nr_R8G8B8A8_P_EMPTY_R8G8B8A8_N_A8(dst1_rgba, w, h, w*4, src_rgba_n, w*4, mask, w);
- nr_R8G8B8A8_P_EMPTY_R8G8B8A8_N_A8_ref(dst2_rgba, w, h, w*4, src_rgba_n, w*4, mask, w);
- TS_ASSERT( IMGCMP<R8G8B8A8P>(dst1_rgba, dst2_rgba, w*h*4) == 0 );
- }
-
- void testnr_R8G8B8A8_P_EMPTY_R8G8B8A8_P_A8()
- {
- memcpy(dst1_rgba, dst_rgba_p_org, w*h*4);
- memcpy(dst2_rgba, dst_rgba_p_org, w*h*4);
- nr_R8G8B8A8_P_EMPTY_R8G8B8A8_P_A8(dst1_rgba, w, h, w*4, src_rgba_p, w*4, mask, w);
- nr_R8G8B8A8_P_EMPTY_R8G8B8A8_P_A8_ref(dst2_rgba, w, h, w*4, src_rgba_p, w*4, mask, w);
- TS_ASSERT( IMGCMP<R8G8B8A8P>(dst1_rgba, dst2_rgba, w*h*4) == 0 );
- }
-
- void testnr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_N_A8()
- {
- memcpy(dst1_rgba, dst_rgba_n_org, w*h*4);
- memcpy(dst2_rgba, dst_rgba_n_org, w*h*4);
- nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_N_A8(dst1_rgba, w, h, w*4, src_rgba_n, w*4, mask, w);
- nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_N_A8_ref(dst2_rgba, w, h, w*4, src_rgba_n, w*4, mask, w);
- TS_ASSERT( IMGCMP<R8G8B8A8N>(dst1_rgba, dst2_rgba, w*h*4) == 0 );
- }
-
- void testnr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_P_A8()
- {
- memcpy(dst1_rgba, dst_rgba_n_org, w*h*4);
- memcpy(dst2_rgba, dst_rgba_n_org, w*h*4);
- nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_P_A8(dst1_rgba, w, h, w*4, src_rgba_p, w*4, mask, w);
- nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_P_A8_ref(dst2_rgba, w, h, w*4, src_rgba_p, w*4, mask, w);
- TS_ASSERT( IMGCMP<R8G8B8A8N>(dst1_rgba, dst2_rgba, w*h*4) == 0 );
- }
-
- void testnr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_N_A8()
- {
- memcpy(dst1_rgba, dst_rgba_p_org, w*h*4);
- memcpy(dst2_rgba, dst_rgba_p_org, w*h*4);
- nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_N_A8(dst1_rgba, w, h, w*4, src_rgba_n, w*4, mask, w);
- nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_N_A8_ref(dst2_rgba, w, h, w*4, src_rgba_n, w*4, mask, w);
- TS_ASSERT( IMGCMP<R8G8B8A8P>(dst1_rgba, dst2_rgba, w*h*4) == 0 );
- }
-
- void testnr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_P_A8()
- {
- memcpy(dst1_rgba, dst_rgba_p_org, w*h*4);
- memcpy(dst2_rgba, dst_rgba_p_org, w*h*4);
- nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_P_A8(dst1_rgba, w, h, w*4, src_rgba_p, w*4, mask, w);
- nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_P_A8_ref(dst2_rgba, w, h, w*4, src_rgba_p, w*4, mask, w);
- TS_ASSERT( IMGCMP<R8G8B8A8P>(dst1_rgba, dst2_rgba, w*h*4) == 0 );
- }
-
- // FINAL DST MASK COLOR
-
- void testnr_R8G8B8A8_N_EMPTY_A8_RGBA32()
- {
- for(size_t j=0; j<G_N_ELEMENTS(rgb_vals); j++) {
- for(size_t i=0; i<G_N_ELEMENTS(alpha_vals); i++) {
- unsigned int rgba = rgb_vals[j]+alpha_vals[i];
- char msg[100];
- sprintf(msg, "color = (%u,%u,%u,%u)", (rgba>>24u)&0xff, (rgba>>16u)&0xff, (rgba>>8u)&0xff, rgba&0xff);
- memcpy(dst1_rgba, dst_rgba_n_org, w*h*4);
- memcpy(dst2_rgba, dst_rgba_n_org, w*h*4);
- nr_R8G8B8A8_N_EMPTY_A8_RGBA32(dst1_rgba, w, h, w*4, mask, w, rgba);
- nr_R8G8B8A8_N_EMPTY_A8_RGBA32_ref(dst2_rgba, w, h, w*4, mask, w, rgba);
- TSM_ASSERT(msg, IMGCMP<R8G8B8A8N>(dst1_rgba, dst2_rgba, w*h*4) == 0 );
- }
- }
- }
-
- void testnr_R8G8B8A8_P_EMPTY_A8_RGBA32()
- {
- for(size_t j=0; j<G_N_ELEMENTS(rgb_vals); j++) {
- for(size_t i=0; i<G_N_ELEMENTS(alpha_vals); i++) {
- unsigned int rgba = rgb_vals[j]+alpha_vals[i];
- char msg[100];
- sprintf(msg, "color = (%u,%u,%u,%u)", (rgba>>24u)&0xff, (rgba>>16u)&0xff, (rgba>>8u)&0xff, rgba&0xff);
- memcpy(dst1_rgba, dst_rgba_p_org, w*h*4);
- memcpy(dst2_rgba, dst_rgba_p_org, w*h*4);
- nr_R8G8B8A8_P_EMPTY_A8_RGBA32(dst1_rgba, w, h, w*4, mask, w, rgba);
- nr_R8G8B8A8_P_EMPTY_A8_RGBA32_ref(dst2_rgba, w, h, w*4, mask, w, rgba);
- TSM_ASSERT(msg, IMGCMP<R8G8B8A8P>(dst1_rgba, dst2_rgba, w*h*4) == 0 );
- }
- }
- }
-
- void testnr_R8G8B8_R8G8B8_A8_RGBA32()
- {
- for(size_t j=0; j<G_N_ELEMENTS(rgb_vals); j++) {
- for(size_t i=0; i<G_N_ELEMENTS(alpha_vals); i++) {
- unsigned int rgba = rgb_vals[j]+alpha_vals[i];
- char msg[100];
- sprintf(msg, "color = (%u,%u,%u,%u)", (rgba>>24u)&0xff, (rgba>>16u)&0xff, (rgba>>8u)&0xff, rgba&0xff);
- memcpy(dst1_rgb, dst_rgb_org, w*h*3);
- memcpy(dst2_rgb, dst_rgb_org, w*h*3);
- nr_R8G8B8_R8G8B8_A8_RGBA32(dst1_rgb, w, h, w*3, mask, w, rgba);
- nr_R8G8B8_R8G8B8_A8_RGBA32_ref(dst2_rgb, w, h, w*3, mask, w, rgba);
- TSM_ASSERT(msg, IMGCMP<R8G8B8>(dst1_rgb, dst2_rgb, w*h*3) == 0 );
- }
- }
- }
-
- void testnr_R8G8B8A8_N_R8G8B8A8_N_A8_RGBA32()
- {
- for(size_t j=0; j<G_N_ELEMENTS(rgb_vals); j++) {
- for(size_t i=0; i<G_N_ELEMENTS(alpha_vals); i++) {
- unsigned int rgba = rgb_vals[j]+alpha_vals[i];
- char msg[100];
- sprintf(msg, "color = (%u,%u,%u,%u)", (rgba>>24u)&0xff, (rgba>>16u)&0xff, (rgba>>8u)&0xff, rgba&0xff);
- memcpy(dst1_rgba, dst_rgba_n_org, w*h*4);
- memcpy(dst2_rgba, dst_rgba_n_org, w*h*4);
- nr_R8G8B8A8_N_R8G8B8A8_N_A8_RGBA32(dst1_rgba, w, h, w*4, mask, w, rgba);
- nr_R8G8B8A8_N_R8G8B8A8_N_A8_RGBA32_ref(dst2_rgba, w, h, w*4, mask, w, rgba);
- TSM_ASSERT(msg, IMGCMP<R8G8B8A8N>(dst1_rgba, dst2_rgba, w*h*4) == 0 );
- }
- }
- }
-
- void testnr_R8G8B8A8_P_R8G8B8A8_P_A8_RGBA32()
- {
- for(size_t j=0; j<G_N_ELEMENTS(rgb_vals); j++) {
- for(size_t i=0; i<G_N_ELEMENTS(alpha_vals); i++) {
- unsigned int rgba = rgb_vals[j]+alpha_vals[i];
- char msg[100];
- sprintf(msg, "color = (%u,%u,%u,%u)", (rgba>>24u)&0xff, (rgba>>16u)&0xff, (rgba>>8u)&0xff, rgba&0xff);
- memcpy(dst1_rgba, dst_rgba_p_org, w*h*4);
- memcpy(dst2_rgba, dst_rgba_p_org, w*h*4);
- nr_R8G8B8A8_P_R8G8B8A8_P_A8_RGBA32(dst1_rgba, w, h, w*4, mask, w, rgba);
- nr_R8G8B8A8_P_R8G8B8A8_P_A8_RGBA32_ref(dst2_rgba, w, h, w*4, mask, w, rgba);
- TSM_ASSERT(msg, IMGCMP<R8G8B8A8P>(dst1_rgba, dst2_rgba, w*h*4) == 0 );
- }
- }
- }
-
- // RGB
-
- void testnr_R8G8B8_R8G8B8_R8G8B8A8_N()
- {
- for(size_t i=0; i<G_N_ELEMENTS(alpha_vals); i++) {
- unsigned int alpha = alpha_vals[i];
- char msg[40];
- sprintf(msg, "alpha = %u", alpha);
- memcpy(dst1_rgb, dst_rgb_org, w*h*3);
- memcpy(dst2_rgb, dst_rgb_org, w*h*3);
- nr_R8G8B8_R8G8B8_R8G8B8A8_N(dst1_rgb, w, h, w*3, src_rgba_n, w*4, alpha);
- nr_R8G8B8_R8G8B8_R8G8B8A8_N_ref(dst2_rgb, w, h, w*3, src_rgba_n, w*4, alpha);
- TSM_ASSERT(msg, IMGCMP<R8G8B8>(dst1_rgb, dst2_rgb, w*h*3) == 0 );
- }
- }
-
- void testnr_R8G8B8_R8G8B8_R8G8B8A8_P()
- {
- for(size_t i=0; i<G_N_ELEMENTS(alpha_vals); i++) {
- unsigned int alpha = alpha_vals[i];
- char msg[40];
- sprintf(msg, "alpha = %u", alpha);
- memcpy(dst1_rgb, dst_rgb_org, w*h*3);
- memcpy(dst2_rgb, dst_rgb_org, w*h*3);
- nr_R8G8B8_R8G8B8_R8G8B8A8_P(dst1_rgb, w, h, w*3, src_rgba_p, w*4, alpha);
- nr_R8G8B8_R8G8B8_R8G8B8A8_P_ref(dst2_rgb, w, h, w*3, src_rgba_p, w*4, alpha);
- TSM_ASSERT(msg, IMGCMP<R8G8B8>(dst1_rgb, dst2_rgb, w*h*3) == 0 );
- }
- }
-
- void testnr_R8G8B8_R8G8B8_R8G8B8A8_N_A8()
- {
- for(size_t i=0; i<G_N_ELEMENTS(alpha_vals); i++) {
- unsigned int alpha = alpha_vals[i];
- char msg[40];
- sprintf(msg, "alpha = %u", alpha);
- memcpy(dst1_rgb, dst_rgb_org, w*h*3);
- memcpy(dst2_rgb, dst_rgb_org, w*h*3);
- nr_R8G8B8_R8G8B8_R8G8B8A8_N_A8(dst1_rgb, w, h, w*3, src_rgba_n, w*4, mask, w);
- nr_R8G8B8_R8G8B8_R8G8B8A8_N_A8_ref(dst2_rgb, w, h, w*3, src_rgba_n, w*4, mask, w);
- TSM_ASSERT(msg, IMGCMP<R8G8B8>(dst1_rgb, dst2_rgb, w*h*3) == 0 );
- }
- }
-
- void testnr_R8G8B8_R8G8B8_R8G8B8A8_P_A8()
- {
- for(size_t i=0; i<G_N_ELEMENTS(alpha_vals); i++) {
- unsigned int alpha = alpha_vals[i];
- char msg[40];
- sprintf(msg, "alpha = %u", alpha);
- memcpy(dst1_rgb, dst_rgb_org, w*h*3);
- memcpy(dst2_rgb, dst_rgb_org, w*h*3);
- nr_R8G8B8_R8G8B8_R8G8B8A8_P_A8(dst1_rgb, w, h, w*3, src_rgba_p, w*4, mask, w);
- nr_R8G8B8_R8G8B8_R8G8B8A8_P_A8_ref(dst2_rgb, w, h, w*3, src_rgba_p, w*4, mask, w);
- TSM_ASSERT(msg, IMGCMP<R8G8B8>(dst1_rgb, dst2_rgb, w*h*3) == 0 );
- }
- }
-};
-
-unsigned int const NrComposeTest::alpha_vals[7] = {0, 1, 127, 128, 129, 254, 255};
-unsigned int const NrComposeTest::rgb_vals[3] = {
- ( 0u<<24u)+( 1u<<16u)+( 92u<<8u),
- (127u<<24u)+(128u<<16u)+(129u<<8u),
- (163u<<24u)+(254u<<16u)+(255u<<8u)};
-
-/*
-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/libnr/nr-compose-transform.cpp b/src/libnr/nr-compose-transform.cpp
deleted file mode 100644
index 05852bf07..000000000
--- a/src/libnr/nr-compose-transform.cpp
+++ /dev/null
@@ -1,367 +0,0 @@
-#define __NR_COMPOSE_TRANSFORM_C__
-
-/*
- * Pixel buffer rendering library
- *
- * Authors:
- * Lauris Kaplinski <lauris@kaplinski.com>
- *
- * This code is in public domain
- */
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include "nr-pixops.h"
-#include "nr-matrix.h"
-
-/*#ifdef WITH_MMX
-#ifdef __cplusplus
-extern "C" {
-#endif // __cplusplus
-/ * fixme: * /
-/ *int nr_have_mmx (void);
-#define NR_PIXOPS_MMX (1 && nr_have_mmx ())
-#ifdef __cplusplus
-}
-#endif //__cplusplus
-#endif
-*/
-
-/* fixme: Implement missing (Lauris) */
-/* fixme: PREMUL colors before calculating average (Lauris) */
-
-/* Fixed point precision */
-#define FBITS 12
-#define FBITS_HP 18 // In some places we need a higher precision
-
-void nr_R8G8B8A8_N_EMPTY_R8G8B8A8_N_TRANSFORM (unsigned char *px, int w, int h, int rs,
- const unsigned char *spx, int sw, int sh, int srs,
- const NR::Matrix &d2s, unsigned int alpha, int xd, int yd);
-void nr_R8G8B8A8_N_EMPTY_R8G8B8A8_P_TRANSFORM (unsigned char *px, int w, int h, int rs,
- const unsigned char *spx, int sw, int sh, int srs,
- const NR::Matrix &d2s, unsigned int alpha, int xd, int yd);
-void nr_R8G8B8A8_P_EMPTY_R8G8B8A8_N_TRANSFORM (unsigned char *px, int w, int h, int rs,
- const unsigned char *spx, int sw, int sh, int srs,
- const NR::Matrix &d2s, unsigned int alpha, int xd, int yd);
-void nr_R8G8B8A8_P_EMPTY_R8G8B8A8_P_TRANSFORM (unsigned char *px, int w, int h, int rs,
- const unsigned char *spx, int sw, int sh, int srs,
- const NR::Matrix &d2s, unsigned int alpha, int xd, int yd);
-
-void
-nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_N_TRANSFORM (unsigned char *px, int w, int h, int rs,
- const unsigned char *spx, int sw, int sh, int srs,
- const NR::Matrix &d2s, unsigned int alpha, int xd, int yd)
-{
- int xsize, ysize, size, dbits;
- long FFs_x_x, FFs_x_y, FFs_y_x, FFs_y_y, FFs__x, FFs__y;
- long FFs_x_x_S, FFs_x_y_S, FFs_y_x_S, FFs_y_y_S;
- /* Subpixel positions */
- int FF_sx_S[256];
- int FF_sy_S[256];
- unsigned char *d0;
- int FFsx0, FFsy0;
- int x, y;
-
- if (alpha == 0) return;
- if (alpha>255) {
- g_warning("In transform PPN alpha=%u>255",alpha);
- }
-
- // The color component is stored temporarily with a range of [0,255^3], so more supersampling and we get an overflow (fortunately Inkscape's preferences also doesn't allow a higher setting)
- if (xd+yd>8) {
- xd = 4;
- yd = 4;
- }
-
- xsize = (1 << xd);
- ysize = (1 << yd);
- size = xsize * ysize;
- dbits = xd + yd;
- unsigned int rounding_fix = size/2;
-
- /* Set up fixed point matrix */
- FFs_x_x = (long) floor(d2s[0] * (1 << FBITS) + 0.5);
- FFs_x_y = (long) floor(d2s[1] * (1 << FBITS) + 0.5);
- FFs_y_x = (long) floor(d2s[2] * (1 << FBITS) + 0.5);
- FFs_y_y = (long) floor(d2s[3] * (1 << FBITS) + 0.5);
- FFs__x = (long) floor(d2s[4] * (1 << FBITS) + 0.5);
- FFs__y = (long) floor(d2s[5] * (1 << FBITS) + 0.5);
-
- FFs_x_x_S = FFs_x_x >> xd;
- FFs_x_y_S = FFs_x_y >> xd;
- FFs_y_x_S = FFs_y_x >> yd;
- FFs_y_y_S = FFs_y_y >> yd;
-
- /* Set up subpixel matrix */
- /* fixme: We can calculate that in floating point (Lauris) */
- for (y = 0; y < ysize; y++) {
- for (x = 0; x < xsize; x++) {
- FF_sx_S[y * xsize + x] = FFs_x_x_S * x + FFs_y_x_S * y;
- FF_sy_S[y * xsize + x] = FFs_x_y_S * x + FFs_y_y_S * y;
- }
- }
-
- d0 = px;
- FFsx0 = FFs__x;
- FFsy0 = FFs__y;
-
- for (y = 0; y < h; y++) {
- unsigned char *d;
- long FFsx, FFsy;
- d = d0;
- FFsx = FFsx0;
- FFsy = FFsy0;
- for (x = 0; x < w; x++) {
- unsigned int r, g, b, a;
- long sx, sy;
- int i;
- r = g = b = a = 0;
- for (i = 0; i < size; i++) {
- sx = (FFsx + FF_sx_S[i]) >> FBITS;
- if ((sx >= 0) && (sx < sw)) {
- sy = (FFsy + FF_sy_S[i]) >> FBITS;
- if ((sy >= 0) && (sy < sh)) {
- const unsigned char *s;
- s = spx + sy * srs + sx * 4;
- r += NR_PREMUL_112 (s[0], s[3]); // s in [0,255]
- g += NR_PREMUL_112 (s[1], s[3]);
- b += NR_PREMUL_112 (s[2], s[3]);
- a += s[3];
- // a=sum(s3)
- // r,g,b in [0,sum(s3)*255]
- }
- }
- }
- a = (a*alpha + rounding_fix) >> dbits;
- // a=sum(s3)*alpha/size=avg(s3)*alpha
- // Compare to nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_P
- if (a != 0) {
- r = (r*alpha + rounding_fix) >> dbits;
- g = (g*alpha + rounding_fix) >> dbits;
- b = (b*alpha + rounding_fix) >> dbits;
- // r,g,b in [0,avg(s3)*alpha*255]=[0,a*255]
- if (a == 255*255) {
- /* Full coverage, demul src */
- d[0] = NR_NORMALIZE_31(r);
- d[1] = NR_NORMALIZE_31(g);
- d[2] = NR_NORMALIZE_31(b);
- d[3] = NR_NORMALIZE_21(a);
- } else if (d[3] == 0) {
- /* Only foreground, demul src */
- d[0] = NR_DEMUL_321(r,a);
- d[1] = NR_DEMUL_321(g,a);
- d[2] = NR_DEMUL_321(b,a);
- d[3] = NR_NORMALIZE_21(a);
- } else {
- unsigned int ca;
- /* Full composition */
- ca = NR_COMPOSEA_213(a, d[3]);
- d[0] = NR_COMPOSEPNN_321131 (r, a, d[0], d[3], ca);
- d[1] = NR_COMPOSEPNN_321131 (g, a, d[1], d[3], ca);
- d[2] = NR_COMPOSEPNN_321131 (b, a, d[2], d[3], ca);
- d[3] = NR_NORMALIZE_31(ca);
- }
- }
- /* Advance pointers */
- FFsx += FFs_x_x;
- FFsy += FFs_x_y;
- d += 4;
- }
- FFsx0 += FFs_y_x;
- FFsy0 += FFs_y_y;
- d0 += rs;
- }
-}
-
-void nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_P_TRANSFORM (unsigned char *px, int w, int h, int rs,
- const unsigned char *spx, int sw, int sh, int srs,
- const NR::Matrix &d2s, unsigned int alpha, int xd, int yd);
-
-static void
-nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_N_TRANSFORM_0 (unsigned char *px, int w, int h, int rs,
- const unsigned char *spx, int sw, int sh, int srs,
- const long long *FFd2s, unsigned int alpha)
-{
- unsigned char *d0;
- long long FFsx0, FFsy0;
- int x, y;
-
- d0 = px;
- FFsx0 = FFd2s[4];
- FFsy0 = FFd2s[5];
-
- for (y = 0; y < h; y++) {
- unsigned char *d;
- long long FFsx, FFsy;
- d = d0;
- FFsx = FFsx0;
- FFsy = FFsy0;
- for (x = 0; x < w; x++) {
- long sx, sy;
- sx = long(FFsx >> FBITS_HP);
- if ((sx >= 0) && (sx < sw)) {
- sy = long(FFsy >> FBITS_HP);
- if ((sy >= 0) && (sy < sh)) {
- const unsigned char *s;
- unsigned int a;
- s = spx + sy * srs + sx * 4;
- a = NR_PREMUL_112 (s[3], alpha);
- if (a != 0) {
- if ((a == 255*255) || (d[3] == 0)) {
- /* Transparent BG, premul src */
- d[0] = NR_PREMUL_121 (s[0], a);
- d[1] = NR_PREMUL_121 (s[1], a);
- d[2] = NR_PREMUL_121 (s[2], a);
- d[3] = NR_NORMALIZE_21(a);
- } else {
- d[0] = NR_COMPOSENPP_1211 (s[0], a, d[0]);
- d[1] = NR_COMPOSENPP_1211 (s[1], a, d[1]);
- d[2] = NR_COMPOSENPP_1211 (s[2], a, d[2]);
- d[3] = NR_COMPOSEA_211(a, d[3]);
- }
- }
- }
- }
- /* Advance pointers */
- FFsx += FFd2s[0];
- FFsy += FFd2s[1];
- d += 4;
- }
- FFsx0 += FFd2s[2];
- FFsy0 += FFd2s[3];
- d0 += rs;
- }
-}
-
-static void
-nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_N_TRANSFORM_n (unsigned char *px, int w, int h, int rs,
- const unsigned char *spx, int sw, int sh, int srs,
- const long long *FFd2s, const long *FF_S, unsigned int alpha, int dbits)
-{
- int size;
- unsigned char *d0;
- long long FFsx0, FFsy0;
- int x, y;
-
- size = (1 << dbits);
- unsigned int rounding_fix = size/2;
-
- d0 = px;
- FFsx0 = FFd2s[4];
- FFsy0 = FFd2s[5];
-
- for (y = 0; y < h; y++) {
- unsigned char *d;
- long long FFsx, FFsy;
- d = d0;
- FFsx = FFsx0;
- FFsy = FFsy0;
- for (x = 0; x < w; x++) {
- unsigned int r, g, b, a;
- int i;
- r = g = b = a = 0;
- for (i = 0; i < size; i++) {
- long sx, sy;
- sx = (long (FFsx >> (FBITS_HP - FBITS)) + FF_S[2 * i]) >> FBITS;
- if ((sx >= 0) && (sx < sw)) {
- sy = (long (FFsy >> (FBITS_HP - FBITS)) + FF_S[2 * i + 1]) >> FBITS;
- if ((sy >= 0) && (sy < sh)) {
- const unsigned char *s;
- s = spx + sy * srs + sx * 4;
- r += NR_PREMUL_112(s[0], s[3]);
- g += NR_PREMUL_112(s[1], s[3]);
- b += NR_PREMUL_112(s[2], s[3]);
- a += s[3];
- }
- }
- }
- a = (a*alpha + rounding_fix) >> dbits;
- if (a != 0) {
- r = (r*alpha + rounding_fix) >> dbits;
- g = (g*alpha + rounding_fix) >> dbits;
- b = (b*alpha + rounding_fix) >> dbits;
- if ((a == 255*255) || (d[3] == 0)) {
- /* Transparent BG, premul src */
- d[0] = NR_NORMALIZE_31(r);
- d[1] = NR_NORMALIZE_31(g);
- d[2] = NR_NORMALIZE_31(b);
- d[3] = NR_NORMALIZE_21(a);
- } else {
- d[0] = NR_COMPOSEPPP_3211 (r, a, d[0]);
- d[1] = NR_COMPOSEPPP_3211 (g, a, d[1]);
- d[2] = NR_COMPOSEPPP_3211 (b, a, d[2]);
- d[3] = NR_COMPOSEA_211(a, d[3]);
- }
- }
- /* Advance pointers */
- FFsx += FFd2s[0];
- FFsy += FFd2s[1];
- d += 4;
- }
- FFsx0 += FFd2s[2];
- FFsy0 += FFd2s[3];
- d0 += rs;
- }
-}
-
-void nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_N_TRANSFORM (unsigned char *px, int w, int h, int rs,
- const unsigned char *spx, int sw, int sh, int srs,
- const NR::Matrix &d2s, unsigned int alpha, int xd, int yd)
-{
- int dbits;
- long FFd2s[6];
- long long FFd2s_HP[6]; // with higher precision
- int i;
-
- if (alpha == 0) return;
- if (alpha>255) {
- g_warning("In transform PPN alpha=%u>255",alpha);
- }
-
- // The color component is stored temporarily with a range of [0,255^3], so more supersampling and we get an overflow (fortunately Inkscape's preferences also doesn't allow a higher setting)
- if (xd+yd>8) {
- xd = 4;
- yd = 4;
- }
-
- dbits = xd + yd;
-
- for (i = 0; i < 6; i++) {
- FFd2s[i] = (long) floor(d2s[i] * (1 << FBITS) + 0.5);
- FFd2s_HP[i] = (long long) floor(d2s[i] * (1 << FBITS_HP) + 0.5);;
- }
-
- if (dbits == 0) {
- nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_N_TRANSFORM_0 (px, w, h, rs, spx, sw, sh, srs, FFd2s_HP, alpha);
- } else {
- int xsize, ysize;
- long FFs_x_x_S, FFs_x_y_S, FFs_y_x_S, FFs_y_y_S;
- long FF_S[2 * 256];
- int x, y;
-
- xsize = (1 << xd);
- ysize = (1 << yd);
-
- FFs_x_x_S = FFd2s[0] >> xd;
- FFs_x_y_S = FFd2s[1] >> xd;
- FFs_y_x_S = FFd2s[2] >> yd;
- FFs_y_y_S = FFd2s[3] >> yd;
-
- /* Set up subpixel matrix */
- /* fixme: We can calculate that in floating point (Lauris) */
- for (y = 0; y < ysize; y++) {
- for (x = 0; x < xsize; x++) {
- FF_S[2 * (y * xsize + x)] = FFs_x_x_S * x + FFs_y_x_S * y;
- FF_S[2 * (y * xsize + x) + 1] = FFs_x_y_S * x + FFs_y_y_S * y;
- }
- }
-
- nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_N_TRANSFORM_n (px, w, h, rs, spx, sw, sh, srs, FFd2s_HP, FF_S, alpha, dbits);
- }
-}
-
-void nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_P_TRANSFORM (unsigned char *px, int w, int h, int rs,
- const unsigned char *spx, int sw, int sh, int srs,
- const NR::Matrix &d2s, unsigned int alpha, int xd, int yd);
diff --git a/src/libnr/nr-compose-transform.h b/src/libnr/nr-compose-transform.h
deleted file mode 100644
index 7ffb20074..000000000
--- a/src/libnr/nr-compose-transform.h
+++ /dev/null
@@ -1,43 +0,0 @@
-#ifndef __NR_COMPOSE_TRANSFORM_H__
-#define __NR_COMPOSE_TRANSFORM_H__
-
-/*
- * Pixel buffer rendering library
- *
- * Authors:
- * Lauris Kaplinski <lauris@kaplinski.com>
- *
- * This code is in public domain
- */
-
-#include <libnr/nr-forward.h>
-
-/* FINAL DST SRC */
-
-void nr_R8G8B8A8_N_EMPTY_R8G8B8A8_N_TRANSFORM (unsigned char *px, int w, int h, int rs,
- const unsigned char *spx, int sw, int sh, int srs,
- const NR::Matrix &d2s, unsigned int alpha, int xd, int yd);
-void nr_R8G8B8A8_N_EMPTY_R8G8B8A8_P_TRANSFORM (unsigned char *px, int w, int h, int rs,
- const unsigned char *spx, int sw, int sh, int srs,
- const NR::Matrix &d2s, unsigned int alpha, int xd, int yd);
-void nr_R8G8B8A8_P_EMPTY_R8G8B8A8_N_TRANSFORM (unsigned char *px, int w, int h, int rs,
- const unsigned char *spx, int sw, int sh, int srs,
- const NR::Matrix &d2s, unsigned int alpha, int xd, int yd);
-void nr_R8G8B8A8_P_EMPTY_R8G8B8A8_P_TRANSFORM (unsigned char *px, int w, int h, int rs,
- const unsigned char *spx, int sw, int sh, int srs,
- const NR::Matrix &d2s, unsigned int alpha, int xd, int yd);
-
-void nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_N_TRANSFORM (unsigned char *px, int w, int h, int rs,
- const unsigned char *spx, int sw, int sh, int srs,
- const NR::Matrix &d2s, unsigned int alpha, int xd, int yd);
-void nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_P_TRANSFORM (unsigned char *px, int w, int h, int rs,
- const unsigned char *spx, int sw, int sh, int srs,
- const NR::Matrix &d2s, unsigned int alpha, int xd, int yd);
-void nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_N_TRANSFORM (unsigned char *px, int w, int h, int rs,
- const unsigned char *spx, int sw, int sh, int srs,
- const NR::Matrix &d2s, unsigned int alpha, int xd, int yd);
-void nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_P_TRANSFORM (unsigned char *px, int w, int h, int rs,
- const unsigned char *spx, int sw, int sh, int srs,
- const NR::Matrix &d2s, unsigned int alpha, int xd, int yd);
-
-#endif
diff --git a/src/libnr/nr-compose.cpp b/src/libnr/nr-compose.cpp
deleted file mode 100644
index 74f9d036b..000000000
--- a/src/libnr/nr-compose.cpp
+++ /dev/null
@@ -1,1197 +0,0 @@
-#define __NR_COMPOSE_C__
-
-/*
- * Pixel buffer rendering library
- *
- * Authors:
- * Lauris Kaplinski <lauris@kaplinski.com>
- *
- * This code is in public domain
- */
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include <string.h>
-#include "nr-pixops.h"
-
-#ifdef WITH_MMX
-/* fixme: */
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-int nr_have_mmx (void);
-void nr_mmx_R8G8B8A8_P_EMPTY_A8_RGBAP (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned char *c);
-void nr_mmx_R8G8B8A8_P_R8G8B8A8_P_A8_RGBAP (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned char *c);
-void nr_mmx_R8G8B8_R8G8B8_R8G8B8A8_P (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha);
-#define NR_PIXOPS_MMX nr_have_mmx ()
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-#endif
-
-// Naming: nr_RESULT_BACKGROUND_FOREGROUND_extra
-
-void
-nr_R8G8B8A8_N_EMPTY_R8G8B8A8_N (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha)
-{
- unsigned int r, c;
-
- for (r = h; r > 0; r--) {
- if (alpha == 0) {
- memset(px, 0x0, 4 * w);
- } else if (alpha == 255) {
- memcpy(px, spx, 4 * w);
- } else {
- unsigned char *d = px;
- const unsigned char *s = spx;
- for (c = w; c > 0; c--) {
- *d++ = *s++;
- *d++ = *s++;
- *d++ = *s++;
- *d++ = NR_PREMUL_111(*s, alpha);
- s++;
- }
- }
- px += rs;
- spx += srs;
- }
-}
-
-void
-nr_R8G8B8A8_N_EMPTY_R8G8B8A8_P (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha)
-{
- unsigned int r, c;
-
- for (r = h; r > 0; r--) {
- if (alpha == 0) {
- memset(px, 0x0, 4 * w);
- } else {
- unsigned char *d = px;
- const unsigned char *s = spx;
- for (c = w; c > 0; c--) {
- if (s[3] == 0) {
- d[3] = 0;
- } else if (s[3] == 255) {
- memcpy(d, s, 4);
- } else {
- d[0] = NR_DEMUL_111(s[0], s[3]);
- d[1] = NR_DEMUL_111(s[1], s[3]);
- d[2] = NR_DEMUL_111(s[2], s[3]);
- d[3] = NR_PREMUL_111(s[3], alpha);
- }
- d += 4;
- s += 4;
- }
- }
- px += rs;
- spx += srs;
- }
-}
-
-void
-nr_R8G8B8A8_P_EMPTY_R8G8B8A8_N (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha)
-{
- unsigned int r, c;
-
- for (r = h; r > 0; r--) {
- unsigned char *d = px;
- const unsigned char *s = spx;
- if (alpha == 0) {
- memset(px, 0x0, 4 * w);
- } else if (alpha == 255) {
- for (c = w; c > 0; c--) {
- d[0] = NR_PREMUL_111(s[0], s[3]);
- d[1] = NR_PREMUL_111(s[1], s[3]);
- d[2] = NR_PREMUL_111(s[2], s[3]);
- d[3] = s[3];
- d += 4;
- s += 4;
- }
- } else {
- for (c = w; c > 0; c--) {
- if (s[3] == 0) {
- memset(d, 0, 4);
- } else {
- unsigned int a;
- a = NR_PREMUL_112(s[3], alpha);
- d[0] = NR_PREMUL_121(s[0], a);
- d[1] = NR_PREMUL_121(s[1], a);
- d[2] = NR_PREMUL_121(s[2], a);
- d[3] = NR_NORMALIZE_21(a);
- }
- d += 4;
- s += 4;
- }
- }
- px += rs;
- spx += srs;
- }
-}
-
-void
-nr_R8G8B8A8_P_EMPTY_R8G8B8A8_P (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha)
-{
- unsigned int r, c;
-
- for (r = h; r > 0; r--) {
- if (alpha == 0) {
- memset(px, 0x0, 4 * w);
- } else if (alpha == 255) {
- memcpy(px, spx, 4 * w);
- } else {
- unsigned char *d = px;
- const unsigned char *s = spx;
- for (c = w; c > 0; c--) {
- d[0] = NR_PREMUL_111(s[0], alpha);
- d[1] = NR_PREMUL_111(s[1], alpha);
- d[2] = NR_PREMUL_111(s[2], alpha);
- d[3] = NR_PREMUL_111(s[3], alpha);
- d += 4;
- s += 4;
- }
- }
- px += rs;
- spx += srs;
- }
-}
-
-void
-nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_N (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha)
-{
- unsigned int r, c;
-
- if (alpha == 0) {
- /* NOP */
- } else if (alpha == 255) {
- for (r = h; r > 0; r--) {
- unsigned char *d = px;
- const unsigned char *s = spx;
- for (c = w; c > 0; c--) {
- if (s[3] == 0) {
- /* Transparent FG, NOP */
- } else if ((s[3] == 255) || (d[3] == 0)) {
- /* Full coverage, COPY */
- memcpy(d, s, 4);
- } else {
- /* Full composition */
- unsigned int ca;
- ca = NR_COMPOSEA_112(s[3], d[3]);
- d[0] = NR_COMPOSENNN_111121(s[0], s[3], d[0], d[3], ca);
- d[1] = NR_COMPOSENNN_111121(s[1], s[3], d[1], d[3], ca);
- d[2] = NR_COMPOSENNN_111121(s[2], s[3], d[2], d[3], ca);
- d[3] = NR_NORMALIZE_21(ca);
- }
- d += 4;
- s += 4;
- }
- px += rs;
- spx += srs;
- }
- } else {
- for (r = h; r > 0; r--) {
- unsigned char *d = px;
- const unsigned char *s = spx;
- for (c = w; c > 0; c--) {
- unsigned int a;
- a = NR_PREMUL_112(s[3], alpha);
- if (a == 0) {
- /* Transparent FG, NOP */
- } else if ((a == 255*255) || (d[3] == 0)) {
- /* Full coverage, COPY */
- d[0] = s[0];
- d[1] = s[1];
- d[2] = s[2];
- d[3] = NR_NORMALIZE_21(a);
- } else {
- /* Full composition */
- unsigned int ca;
- ca = NR_COMPOSEA_213(a, d[3]);
- d[0] = NR_COMPOSENNN_121131(s[0], a, d[0], d[3], ca);
- d[1] = NR_COMPOSENNN_121131(s[1], a, d[1], d[3], ca);
- d[2] = NR_COMPOSENNN_121131(s[2], a, d[2], d[3], ca);
- d[3] = NR_NORMALIZE_31(ca);
- }
- d += 4;
- s += 4;
- }
- px += rs;
- spx += srs;
- }
- }
-}
-
-void
-nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_P (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha)
-{
- unsigned int r, c;
-
- if (alpha == 0) {
- /* NOP */
- } else if (alpha == 255) {
- for (r = h; r > 0; r--) {
- unsigned char *d = px;
- const unsigned char *s = spx;
- for (c = w; c > 0; c--) {
- if (s[3] == 0) {
- /* Transparent FG, NOP */
- } else if (s[3] == 255) {
- /* Full coverage, demul src */
- // dc' = ((1 - sa) * da*dc + sc)/da' = sc/da' = sc
- // da' = 1 - (1 - sa) * (1 - da) = 1 - 0 * (1 - da) = 1
- memcpy(d, s, 4);
- } else if (d[3] == 0) {
- /* Full coverage, demul src */
- // dc' = ((1 - sa) * da*dc + sc)/da' = sc/da' = sc/sa = sc/sa
- // da' = 1 - (1 - sa) * (1 - da) = 1 - (1 - sa) = sa
- d[0] = NR_DEMUL_111(s[0], s[3]);
- d[1] = NR_DEMUL_111(s[1], s[3]);
- d[2] = NR_DEMUL_111(s[2], s[3]);
- d[3] = s[3];
- } else {
- /* Full composition */
- // dc' = ((1 - sa) * da*dc + sc)/da' = ((1 - sa) * da*dc + sc)/da'
- // da' = 1 - (1 - sa) * (1 - da) = 1 - (1 - sa) * (1 - da)
- unsigned int da = NR_COMPOSEA_112(s[3], d[3]);
- d[0] = NR_COMPOSEPNN_111121(s[0], s[3], d[0], d[3], da);
- d[1] = NR_COMPOSEPNN_111121(s[1], s[3], d[1], d[3], da);
- d[2] = NR_COMPOSEPNN_111121(s[2], s[3], d[2], d[3], da);
- d[3] = NR_NORMALIZE_21(da);
- }
- d += 4;
- s += 4;
- }
- px += rs;
- spx += srs;
- }
- } else {
- for (r = h; r > 0; r--) {
- unsigned char *d = px;
- const unsigned char *s = spx;
- for (c = w; c > 0; c--) {
- unsigned int a;
- a = NR_PREMUL_112(s[3], alpha);
- if (a == 0) {
- /* Transparent FG, NOP */
- } else if (d[3] == 0) {
- /* Full coverage, demul src */
- // dc' = ((1 - alpha*sa) * da*dc + alpha*sc)/da' = alpha*sc/da' = alpha*sc/(alpha*sa) = sc/sa
- // da' = 1 - (1 - alpha*sa) * (1 - da) = 1 - (1 - alpha*sa) = alpha*sa
- d[0] = NR_DEMUL_111(s[0], s[3]);
- d[1] = NR_DEMUL_111(s[1], s[3]);
- d[2] = NR_DEMUL_111(s[2], s[3]);
- d[3] = NR_NORMALIZE_21(a);
- } else {
- // dc' = ((1 - alpha*sa) * da*dc + alpha*sc)/da'
- // da' = 1 - (1 - alpha*sa) * (1 - da)
- unsigned int da = NR_COMPOSEA_213(a, d[3]);
- d[0] = NR_COMPOSEPNN_221131(NR_PREMUL_112(s[0], alpha), a, d[0], d[3], da);
- d[1] = NR_COMPOSEPNN_221131(NR_PREMUL_112(s[1], alpha), a, d[1], d[3], da);
- d[2] = NR_COMPOSEPNN_221131(NR_PREMUL_112(s[2], alpha), a, d[2], d[3], da);
- d[3] = NR_NORMALIZE_31(da);
- }
- d += 4;
- s += 4;
- }
- px += rs;
- spx += srs;
- }
- }
-}
-
-void
-nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_N (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha)
-{
- unsigned int r, c;
-
- if (alpha == 0) {
- /* NOP */
- } else if (alpha == 255) {
- for (r = h; r > 0; r--) {
- unsigned char *d = px;
- const unsigned char *s = spx;
- for (c = w; c > 0; c--) {
- if (s[3] == 0) {
- /* Transparent FG, NOP */
- } else if (s[3] == 255) {
- /* Opaque FG, COPY */
- // dc' = (1 - sa) * dc + sa*sc = sa*sc = sc
- // da' = 1 - (1 - sa) * (1 - da) = 1 - 0 * (1 - da) = 1 (= sa)
- memcpy(d, s, 4);
- } else if (d[3] == 0) {
- /* Transparent BG, premul src */
- // dc' = (1 - sa) * dc + sa*sc = sa*sc
- // da' = 1 - (1 - sa) * (1 - da) = 1 - (1 - sa) = sa
- d[0] = NR_PREMUL_111(s[0], s[3]);
- d[1] = NR_PREMUL_111(s[1], s[3]);
- d[2] = NR_PREMUL_111(s[2], s[3]);
- d[3] = s[3];
- } else {
- // dc' = (1 - sa) * dc + sa*sc
- // da' = 1 - (1 - sa) * (1 - da)
- d[0] = NR_COMPOSENPP_1111(s[0], s[3], d[0]);
- d[1] = NR_COMPOSENPP_1111(s[1], s[3], d[1]);
- d[2] = NR_COMPOSENPP_1111(s[2], s[3], d[2]);
- d[3] = NR_COMPOSEA_111(s[3], d[3]);
- }
- d += 4;
- s += 4;
- }
- px += rs;
- spx += srs;
- }
- } else {
- for (r = h; r > 0; r--) {
- unsigned char *d = px;
- const unsigned char *s = spx;
- for (c = w; c > 0; c--) {
- unsigned int a;
- a = NR_PREMUL_112 (s[3], alpha);
- if (a == 0) {
- /* Transparent FG, NOP */
- } else if (d[3] == 0) {
- /* Transparent BG, premul src */
- // dc' = (1 - alpha*sa) * dc + alpha*sa*sc = alpha*sa*sc
- // da' = 1 - (1 - alpha*sa) * (1 - da) = 1 - (1 - alpha*sa) = alpha*sa
- d[0] = NR_PREMUL_121(s[0], a);
- d[1] = NR_PREMUL_121(s[1], a);
- d[2] = NR_PREMUL_121(s[2], a);
- d[3] = NR_NORMALIZE_21(a);
- } else {
- // dc' = (1 - alpha*sa) * dc + alpha*sa*sc
- // da' = 1 - (1 - alpha*sa) * (1 - da)
- d[0] = NR_COMPOSENPP_1211(s[0], a, d[0]);
- d[1] = NR_COMPOSENPP_1211(s[1], a, d[1]);
- d[2] = NR_COMPOSENPP_1211(s[2], a, d[2]);
- d[3] = NR_COMPOSEA_211(a, d[3]);
- }
- d += 4;
- s += 4;
- }
- px += rs;
- spx += srs;
- }
- }
-}
-
-void
-nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_P (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha)
-{
- unsigned int r, c;
-
- if (alpha == 0) {
- /* Transparent FG, NOP */
- } else if (alpha == 255) {
- /* Simple */
- for (r = h; r > 0; r--) {
- unsigned char *d = px;
- const unsigned char *s = spx;
- for (c = w; c > 0; c--) {
- if (s[3] == 0) {
- /* Transparent FG, NOP */
- } else if ((s[3] == 255) || (d[3] == 0)) {
- /* Transparent BG, COPY */
- memcpy(d, s, 4);
- } else {
- d[0] = NR_COMPOSEPPP_1111(s[0], s[3], d[0]);
- d[1] = NR_COMPOSEPPP_1111(s[1], s[3], d[1]);
- d[2] = NR_COMPOSEPPP_1111(s[2], s[3], d[2]);
- d[3] = NR_COMPOSEA_111(s[3], d[3]);
- }
- d += 4;
- s += 4;
- }
- px += rs;
- spx += srs;
- }
- } else {
- for (r = h; r > 0; r--) {
- unsigned char *d = px;
- const unsigned char *s = spx;
- for (c = w; c > 0; c--) {
- if (s[3] == 0) {
- /* Transparent FG, NOP */
- } else if (d[3] == 0) {
- /* Transparent BG, COPY */
- d[0] = NR_PREMUL_111(s[0], alpha);
- d[1] = NR_PREMUL_111(s[1], alpha);
- d[2] = NR_PREMUL_111(s[2], alpha);
- d[3] = NR_PREMUL_111(s[3], alpha);
- } else {
- // dc' = (1 - alpha*sa) * dc + alpha*sc
- // da' = 1 - (1 - alpha*sa) * (1 - da)
- unsigned int a;
- a = NR_PREMUL_112(s[3], alpha);
- d[0] = NR_COMPOSEPPP_2211(NR_PREMUL_112(alpha, s[0]), a, d[0]);
- d[1] = NR_COMPOSEPPP_2211(NR_PREMUL_112(alpha, s[1]), a, d[1]);
- d[2] = NR_COMPOSEPPP_2211(NR_PREMUL_112(alpha, s[2]), a, d[2]);
- d[3] = NR_COMPOSEA_211(a, d[3]);
- }
- d += 4;
- s += 4;
- }
- px += rs;
- spx += srs;
- }
- }
-}
-
-/* Masked operations */
-
-void
-nr_R8G8B8A8_N_EMPTY_R8G8B8A8_N_A8 (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, const unsigned char *mpx, int mrs)
-{
- unsigned int r, c;
-
- for (r = h; r > 0; r--) {
- unsigned char *d = px;
- const unsigned char *s = spx;
- const unsigned char *m = mpx;
- for (c = w; c > 0; c--) {
- d[0] = s[0];
- d[1] = s[1];
- d[2] = s[2];
- d[3] = NR_PREMUL_111(s[3], m[0]);
- d += 4;
- s += 4;
- m += 1;
- }
- px += rs;
- spx += srs;
- mpx += mrs;
- }
-}
-
-void
-nr_R8G8B8A8_N_EMPTY_R8G8B8A8_P_A8 (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, const unsigned char *mpx, int mrs)
-{
- unsigned int r, c;
-
- for (r = h; r > 0; r--) {
- unsigned char *d = px;
- const unsigned char *s = spx;
- const unsigned char *m = mpx;
- for (c = w; c > 0; c--) {
- unsigned int a;
- a = NR_PREMUL_112 (s[3], m[0]);
- if (a == 0) {
- d[3] = 0;
- } else if (a == 255*255) {
- memcpy(d, s, 4);
- } else {
- // dc' = ((1 - m*sa) * da*dc + m*sc)/da' = m*sc/da' = m*sc/(m*sa) = sc/sa
- // da' = 1 - (1 - m*sa) * (1 - da) = 1 - (1 - m*sa) = m*sa
- d[0] = NR_DEMUL_111(s[0], s[3]);
- d[1] = NR_DEMUL_111(s[1], s[3]);
- d[2] = NR_DEMUL_111(s[2], s[3]);
- d[3] = NR_NORMALIZE_21(a);
- }
- d += 4;
- s += 4;
- m += 1;
- }
- px += rs;
- spx += srs;
- mpx += mrs;
- }
-}
-
-void
-nr_R8G8B8A8_P_EMPTY_R8G8B8A8_N_A8 (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, const unsigned char *mpx, int mrs)
-{
- unsigned int r, c;
-
- for (r = h; r > 0; r--) {
- unsigned char *d = px;
- const unsigned char *s = spx;
- const unsigned char *m = mpx;
- for (c = w; c > 0; c--) {
- unsigned int a;
- a = NR_PREMUL_112(s[3], m[0]);
- if (a == 0) {
- memset(d, 0, 4);
- } else if (a == 255*255) {
- memcpy(d, s, 4);
- } else {
- d[0] = NR_PREMUL_121(s[0], a);
- d[1] = NR_PREMUL_121(s[1], a);
- d[2] = NR_PREMUL_121(s[2], a);
- d[3] = NR_NORMALIZE_21(a);
- }
- d += 4;
- s += 4;
- m += 1;
- }
- px += rs;
- spx += srs;
- mpx += mrs;
- }
-}
-
-void
-nr_R8G8B8A8_P_EMPTY_R8G8B8A8_P_A8 (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, const unsigned char *mpx, int mrs)
-{
- unsigned int r, c;
-
- for (r = h; r > 0; r--) {
- unsigned char *d = px;
- const unsigned char *s = spx;
- const unsigned char *m = mpx;
- for (c = w; c > 0; c--) {
- d[0] = NR_PREMUL_111(s[0], m[0]);
- d[1] = NR_PREMUL_111(s[1], m[0]);
- d[2] = NR_PREMUL_111(s[2], m[0]);
- d[3] = NR_PREMUL_111(s[3], m[0]);
- d += 4;
- s += 4;
- m += 1;
- }
- px += rs;
- spx += srs;
- mpx += mrs;
- }
-}
-
-void
-nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_N_A8 (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, const unsigned char *mpx, int mrs)
-{
- unsigned int r, c;
-
- for (r = h; r > 0; r--) {
- unsigned char *d = px;
- const unsigned char *s = spx;
- const unsigned char *m = mpx;
- for (c = w; c > 0; c--) {
- unsigned int a;
- a = NR_PREMUL_112(s[3], m[0]);
- if (a == 0) {
- /* Transparent FG, NOP */
- } else if ((a == 255*255) || (d[3] == 0)) {
- /* Full coverage, COPY */
- d[0] = s[0];
- d[1] = s[1];
- d[2] = s[2];
- d[3] = NR_NORMALIZE_21(a);
- } else {
- /* Full composition */
- unsigned int ca;
- ca = NR_COMPOSEA_213(a, d[3]);
- d[0] = NR_COMPOSENNN_121131(s[0], a, d[0], d[3], ca);
- d[1] = NR_COMPOSENNN_121131(s[1], a, d[1], d[3], ca);
- d[2] = NR_COMPOSENNN_121131(s[2], a, d[2], d[3], ca);
- d[3] = NR_NORMALIZE_31(ca);
- }
- d += 4;
- s += 4;
- m += 1;
- }
- px += rs;
- spx += srs;
- mpx += mrs;
- }
-}
-
-void
-nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_P_A8 (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, const unsigned char *mpx, int mrs)
-{
- unsigned int r, c;
-
- for (r = h; r > 0; r--) {
- unsigned char *d = px;
- const unsigned char *s = spx;
- const unsigned char *m = mpx;
- for (c = w; c > 0; c--) {
- unsigned int a;
- a = NR_PREMUL_112(s[3], m[0]);
- if (a == 0) {
- /* Transparent FG, NOP */
- } else if (a == 255*255) {
- /* Opaque FG, COPY */
- memcpy(d, s, 4);
- } else if (d[3] == 0) {
- /* Full coverage, demul src */
- // dc' = ((1 - m*sa) * da*dc + m*sc)/da' = m*sc/da' = m*sc/(m*sa) = sc/sa
- // da' = 1 - (1 - m*sa) * (1 - da) = 1 - (1 - m*sa) = m*sa
- d[0] = NR_DEMUL_111(s[0], s[3]);
- d[1] = NR_DEMUL_111(s[1], s[3]);
- d[2] = NR_DEMUL_111(s[2], s[3]);
- d[3] = NR_NORMALIZE_21(a);
- } else if (m[0] == 255) {
- /* Full composition */
- // dc' = ((1 - m*sa) * da*dc + m*sc)/da' = ((1 - sa) * da*dc + sc)/da'
- // da' = 1 - (1 - m*sa) * (1 - da) = 1 - (1 - sa) * (1 - da)
- unsigned int da = NR_COMPOSEA_112(s[3], d[3]);
- d[0] = NR_COMPOSEPNN_111121(s[0], s[3], d[0], d[3], da);
- d[1] = NR_COMPOSEPNN_111121(s[1], s[3], d[1], d[3], da);
- d[2] = NR_COMPOSEPNN_111121(s[2], s[3], d[2], d[3], da);
- d[3] = NR_NORMALIZE_21(da);
- } else {
- // dc' = ((1 - m*sa) * da*dc + m*sc)/da'
- // da' = 1 - (1 - m*sa) * (1 - da)
- unsigned int da = NR_COMPOSEA_213(a, d[3]);
- d[0] = NR_COMPOSEPNN_221131(NR_PREMUL_112(s[0], m[0]), a, d[0], d[3], da);
- d[1] = NR_COMPOSEPNN_221131(NR_PREMUL_112(s[1], m[0]), a, d[1], d[3], da);
- d[2] = NR_COMPOSEPNN_221131(NR_PREMUL_112(s[2], m[0]), a, d[2], d[3], da);
- d[3] = NR_NORMALIZE_31(da);
- }
- d += 4;
- s += 4;
- m += 1;
- }
- px += rs;
- spx += srs;
- mpx += mrs;
- }
-}
-
-void
-nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_N_A8 (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, const unsigned char *mpx, int mrs)
-{
- unsigned int r, c;
-
- for (r = h; r>0; r--) {
- unsigned char *d = px;
- const unsigned char *s = spx;
- const unsigned char *m = mpx;
- for (c = w; c>0; c--) {
- unsigned int a;
- a = NR_PREMUL_112(s[3], m[0]);
- if (a == 0) {
- /* Transparent FG, NOP */
- } else if (a == 255*255) {
- memcpy(d, s, 4);
- } else {
- d[0] = NR_COMPOSENPP_1211(s[0], a, d[0]);
- d[1] = NR_COMPOSENPP_1211(s[1], a, d[1]);
- d[2] = NR_COMPOSENPP_1211(s[2], a, d[2]);
- d[3] = NR_COMPOSEA_211(a, d[3]);
- }
- d += 4;
- s += 4;
- m += 1;
- }
- px += rs;
- spx += srs;
- mpx += mrs;
- }
-}
-
-void
-nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_P_A8 (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, const unsigned char *mpx, int mrs)
-{
- unsigned int r, c;
-
- for (r = h; r > 0; r--) {
- unsigned char *d = px;
- const unsigned char *s = spx;
- const unsigned char *m = mpx;
- for (c = w; c > 0; c--) {
- unsigned int a;
- a = NR_PREMUL_112 (s[3], m[0]);
- if (a == 0) {
- /* Transparent FG, NOP */
- } else if (a == 255*255) {
- /* Opaque FG, COPY */
- memcpy(d, s, 4);
- } else if (d[3] == 0) {
- /* Transparent BG, COPY */
- // dc' = (1 - m*sa) * dc + m*sc = m*sc
- // da' = 1 - (1 - m*sa) * (1 - da) = 1 - (1 - m*sa) = m*sa
- d[0] = NR_PREMUL_111 (s[0], m[0]);
- d[1] = NR_PREMUL_111 (s[1], m[0]);
- d[2] = NR_PREMUL_111 (s[2], m[0]);
- d[3] = NR_NORMALIZE_21(a);
- } else {
- // dc' = (1 - m*sa) * dc + m*sc
- // da' = 1 - (1 - m*sa) * (1 - da)
- d[0] = NR_COMPOSEPPP_2211 (NR_PREMUL_112 (s[0], m[0]), a, d[0]);
- d[1] = NR_COMPOSEPPP_2211 (NR_PREMUL_112 (s[1], m[0]), a, d[1]);
- d[2] = NR_COMPOSEPPP_2211 (NR_PREMUL_112 (s[2], m[0]), a, d[2]);
- d[3] = NR_COMPOSEA_211(a, d[3]);
- }
- d += 4;
- s += 4;
- m += 1;
- }
- px += rs;
- spx += srs;
- mpx += mrs;
- }
-}
-
-/* FINAL DST MASK COLOR */
-
-void
-nr_R8G8B8A8_N_EMPTY_A8_RGBA32 (unsigned char *px, int w, int h, int rs, const unsigned char *mpx, int mrs, unsigned long rgba)
-{
- unsigned int r, g, b, a;
- unsigned int x, y;
-
- r = NR_RGBA32_R (rgba);
- g = NR_RGBA32_G (rgba);
- b = NR_RGBA32_B (rgba);
- a = NR_RGBA32_A (rgba);
-
- for (y = h; y > 0; y--) {
- if (a == 0) {
- memset(px, 0, w*4);
- } else {
- unsigned char *d = px;
- const unsigned char *m = mpx;
- for (x = w; x > 0; x--) {
- d[0] = r;
- d[1] = g;
- d[2] = b;
- d[3] = NR_PREMUL_111 (m[0], a);
- d += 4;
- m += 1;
- }
- }
- px += rs;
- mpx += mrs;
- }
-}
-
-void
-nr_R8G8B8A8_P_EMPTY_A8_RGBA32 (unsigned char *px, int w, int h, int rs, const unsigned char *mpx, int mrs, unsigned long rgba)
-{
- unsigned int r, g, b, a;
- unsigned int x, y;
-
- r = NR_RGBA32_R (rgba);
- g = NR_RGBA32_G (rgba);
- b = NR_RGBA32_B (rgba);
- a = NR_RGBA32_A (rgba);
-
-#ifdef WITH_MMX
- if (NR_PIXOPS_MMX) {
- unsigned char c[4];
- c[0] = NR_PREMUL_111 (r, a);
- c[1] = NR_PREMUL_111 (g, a);
- c[2] = NR_PREMUL_111 (b, a);
- c[3] = a;
- /* WARNING: MMX composer REQUIRES w > 0 and h > 0 */
- nr_mmx_R8G8B8A8_P_EMPTY_A8_RGBAP (px, w, h, rs, mpx, mrs, c);
- // This mmx optimized code is approx. 2x faster than the non-optimized code below (Measured by Diederik van Lierop, 2009-12-17)
- return;
- }
-#endif
-
- if ( a != 255 ){
- // Pre-premultiply color values
- r *= a;
- g *= a;
- b *= a;
- }
-
- for (y = h; y > 0; y--) {
- unsigned char *d = px;
- const unsigned char *m = mpx;
- if (a == 0) {
- memset(px, 0, w*4);
- } else if (a == 255) {
- for (x = w; x > 0; x--) {
- d[0] = NR_PREMUL_111(m[0], r);
- d[1] = NR_PREMUL_111(m[0], g);
- d[2] = NR_PREMUL_111(m[0], b);
- d[3] = m[0];
- d += 4;
- m += 1;
- }
- } else {
- for (x = w; x > 0; x--) {
- // Color values are already premultiplied with a
- d[0] = NR_PREMUL_121(m[0], r);
- d[1] = NR_PREMUL_121(m[0], g);
- d[2] = NR_PREMUL_121(m[0], b);
- d[3] = NR_PREMUL_111(m[0], a);
- d += 4;
- m += 1;
- }
- }
- px += rs;
- mpx += mrs;
- }
-}
-
-void
-nr_R8G8B8_R8G8B8_A8_RGBA32 (unsigned char *px, int w, int h, int rs, const unsigned char *mpx, int mrs, unsigned long rgba)
-{
- unsigned int r, g, b, a;
- unsigned int x, y;
-
- r = NR_RGBA32_R (rgba);
- g = NR_RGBA32_G (rgba);
- b = NR_RGBA32_B (rgba);
- a = NR_RGBA32_A (rgba);
-
- if (a == 0) {
- /* NOP */
- } else if (a == 255) {
- for (y = h; y > 0; y--) {
- unsigned char *d = px;
- const unsigned char *m = mpx;
- for (x = w; x > 0; x--) {
- d[0] = NR_COMPOSEN11_1111 (r, m[0], d[0]);
- d[1] = NR_COMPOSEN11_1111 (g, m[0], d[1]);
- d[2] = NR_COMPOSEN11_1111 (b, m[0], d[2]);
- d += 3;
- m += 1;
- }
- px += rs;
- mpx += mrs;
- }
- } else {
- for (y = h; y > 0; y--) {
- unsigned char *d = px;
- const unsigned char *m = mpx;
- for (x = w; x > 0; x--) {
- // dc' = (1 - m*sa) * dc + m*sa*sc
- unsigned int alpha;
- alpha = NR_PREMUL_112 (a, m[0]);
- d[0] = NR_COMPOSEN11_1211 (r, alpha, d[0]);
- d[1] = NR_COMPOSEN11_1211 (g, alpha, d[1]);
- d[2] = NR_COMPOSEN11_1211 (b, alpha, d[2]);
- d += 3;
- m += 1;
- }
- px += rs;
- mpx += mrs;
- }
- }
-}
-
-void
-nr_R8G8B8A8_N_R8G8B8A8_N_A8_RGBA32 (unsigned char *px, int w, int h, int rs, const unsigned char *mpx, int mrs, unsigned long rgba)
-{
- unsigned int r, g, b, a;
- unsigned int x, y;
-
- r = NR_RGBA32_R (rgba);
- g = NR_RGBA32_G (rgba);
- b = NR_RGBA32_B (rgba);
- a = NR_RGBA32_A (rgba);
-
- if (a == 0) {
- /* NOP */
- } else if (a == 255) {
- for (y = h; y > 0; y--) {
- unsigned char *d = px;
- const unsigned char *m = mpx;
- for (x = w; x > 0; x--) {
- if (m[0] == 0) {
- /* Transparent FG, NOP */
- } else if (m[0] == 255 || d[3] == 0) {
- /* Full coverage, COPY */
- d[0] = r;
- d[1] = g;
- d[2] = b;
- d[3] = m[0];
- } else {
- /* Full composition */
- unsigned int da = NR_COMPOSEA_112(m[0], d[3]);
- d[0] = NR_COMPOSENNN_111121(r, m[0], d[0], d[3], da);
- d[1] = NR_COMPOSENNN_111121(g, m[0], d[1], d[3], da);
- d[2] = NR_COMPOSENNN_111121(b, m[0], d[2], d[3], da);
- d[3] = NR_NORMALIZE_21(da);
- }
- d += 4;
- m += 1;
- }
- px += rs;
- mpx += mrs;
- }
- } else {
- for (y = h; y > 0; y--) {
- unsigned char *d = px;
- const unsigned char *m = mpx;
- for (x = w; x > 0; x--) {
- unsigned int ca;
- ca = NR_PREMUL_112 (m[0], a);
- if (ca == 0) {
- /* Transparent FG, NOP */
- } else if (d[3] == 0) {
- /* Full coverage, COPY */
- d[0] = r;
- d[1] = g;
- d[2] = b;
- d[3] = NR_NORMALIZE_21(ca);
- } else {
- /* Full composition */
- unsigned int da = NR_COMPOSEA_213(ca, d[3]);
- d[0] = NR_COMPOSENNN_121131(r, ca, d[0], d[3], da);
- d[1] = NR_COMPOSENNN_121131(g, ca, d[1], d[3], da);
- d[2] = NR_COMPOSENNN_121131(b, ca, d[2], d[3], da);
- d[3] = NR_NORMALIZE_31(da);
- }
- d += 4;
- m += 1;
- }
- px += rs;
- mpx += mrs;
- }
- }
-}
-
-void
-nr_R8G8B8A8_P_R8G8B8A8_P_A8_RGBA32 (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned long rgba)
-{
- unsigned int r, g, b, a;
- unsigned int x, y;
-
- r = NR_RGBA32_R (rgba);
- g = NR_RGBA32_G (rgba);
- b = NR_RGBA32_B (rgba);
- a = NR_RGBA32_A (rgba);
-
-#ifdef WITH_MMX
- if (NR_PIXOPS_MMX && a != 0) {
- unsigned char c[4];
- c[0] = NR_PREMUL_111 (r, a);
- c[1] = NR_PREMUL_111 (g, a);
- c[2] = NR_PREMUL_111 (b, a);
- c[3] = a;
- /* WARNING: MMX composer REQUIRES w > 0 and h > 0 */
- nr_mmx_R8G8B8A8_P_R8G8B8A8_P_A8_RGBAP (px, w, h, rs, spx, srs, c);
- return;
- }
-#endif
-
- if (a == 0) {
- /* Transparent FG, NOP */
- } else if (a == 255) {
- /* Simple */
- for (y = h; y > 0; y--) {
- unsigned char *d, *s;
- d = (unsigned char *) px;
- s = (unsigned char *) spx;
- for (x = w; x > 0; x--) {
- if (s[0] == 0) {
- /* Transparent FG, NOP */
- } else {
- /* Full composition */
- unsigned int invca = 255-s[0]; // By swapping the arguments GCC can better optimize these calls
- d[0] = NR_COMPOSENPP_1111(d[0], invca, r);
- d[1] = NR_COMPOSENPP_1111(d[1], invca, g);
- d[2] = NR_COMPOSENPP_1111(d[2], invca, b);
- d[3] = NR_COMPOSEA_111(s[0], d[3]);
- }
- d += 4;
- s += 1;
- }
- px += rs;
- spx += srs;
- }
- } else {
- for (y = h; y > 0; y--) {
- unsigned char *d, *s;
- d = (unsigned char *) px;
- s = (unsigned char *) spx;
- for (x = w; x > 0; x--) {
- unsigned int ca;
- ca = NR_PREMUL_112 (s[0], a);
- if (ca == 0) {
- /* Transparent FG, NOP */
- } else {
- /* Full composition */
- unsigned int invca = 255*255-ca; // By swapping the arguments GCC can better optimize these calls
- d[0] = NR_COMPOSENPP_1211(d[0], invca, r);
- d[1] = NR_COMPOSENPP_1211(d[1], invca, g);
- d[2] = NR_COMPOSENPP_1211(d[2], invca, b);
- d[3] = NR_COMPOSEA_211(ca, d[3]);
- }
- d += 4;
- s += 1;
- }
- px += rs;
- spx += srs;
- }
- }
-}
-
-/* RGB */
-
-void
-nr_R8G8B8_R8G8B8_R8G8B8A8_P (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha)
-{
- unsigned int r, c;
-
-#ifdef WITH_MMX
- if (NR_PIXOPS_MMX && alpha != 0) {
- /* WARNING: MMX composer REQUIRES w > 0 and h > 0 */
- nr_mmx_R8G8B8_R8G8B8_R8G8B8A8_P (px, w, h, rs, spx, srs, alpha);
- return;
- }
-#endif
-
- if (alpha == 0) {
- /* NOP */
- } else if (alpha == 255) {
- for (r = h; r > 0; r--) {
- unsigned char *d = px;
- const unsigned char *s = spx;
- for (c = w; c > 0; c--) {
- // dc' = (1 - alpha*sa) * dc + alpha*sc = (1 - sa) * dc + sc
- if (s[3] == 0) {
- /* NOP */
- } else if (s[3] == 255) {
- d[0] = s[0];
- d[1] = s[1];
- d[2] = s[2];
- } else {
- d[0] = NR_COMPOSEP11_1111(s[0], s[3], d[0]);
- d[1] = NR_COMPOSEP11_1111(s[1], s[3], d[1]);
- d[2] = NR_COMPOSEP11_1111(s[2], s[3], d[2]);
- }
- d += 3;
- s += 4;
- }
- px += rs;
- spx += srs;
- }
- } else {
- for (r = h; r > 0; r--) {
- unsigned char *d = px;
- const unsigned char *s = spx;
- for (c = w; c > 0; c--) {
- unsigned int a;
- a = NR_PREMUL_112(s[3], alpha);
- // dc' = (1 - alpha*sa) * dc + alpha*sc
- if (a == 0) {
- /* NOP */
- } else {
- d[0] = NR_COMPOSEP11_2211(NR_PREMUL_112(s[0], alpha), a, d[0]);
- d[1] = NR_COMPOSEP11_2211(NR_PREMUL_112(s[1], alpha), a, d[1]);
- d[2] = NR_COMPOSEP11_2211(NR_PREMUL_112(s[2], alpha), a, d[2]);
- }
- /* a == 255 is impossible, because alpha < 255 */
- d += 3;
- s += 4;
- }
- px += rs;
- spx += srs;
- }
- }
-}
-
-void
-nr_R8G8B8_R8G8B8_R8G8B8A8_N (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha)
-{
- unsigned int r, c;
-
- if (alpha == 0) {
- /* NOP */
- } else if (alpha == 255) {
- for (r = h; r > 0; r--) {
- unsigned char *d = px;
- const unsigned char *s = spx;
- for (c = w; c > 0; c--) {
- // dc' = (1 - alpha*sa) * dc + alpha*sa*sc = (1 - sa) * dc + sa*sc
- if (s[3] == 0) {
- /* NOP */
- } else if (s[3] == 255) {
- d[0] = s[0];
- d[1] = s[1];
- d[2] = s[2];
- } else {
- d[0] = NR_COMPOSEN11_1111(s[0], s[3], d[0]);
- d[1] = NR_COMPOSEN11_1111(s[1], s[3], d[1]);
- d[2] = NR_COMPOSEN11_1111(s[2], s[3], d[2]);
- }
- d += 3;
- s += 4;
- }
- px += rs;
- spx += srs;
- }
- } else {
- for (r = h; r > 0; r--) {
- unsigned char *d = px;
- const unsigned char *s = spx;
- for (c = w; c > 0; c--) {
- unsigned int a;
- a = NR_PREMUL_112(s[3], alpha);
- // dc' = (1 - alpha*sa) * dc + alpha*sa*sc
- if (a == 0) {
- /* NOP */
- } else {
- d[0] = NR_COMPOSEN11_1211(s[0], a, d[0]);
- d[1] = NR_COMPOSEN11_1211(s[1], a, d[1]);
- d[2] = NR_COMPOSEN11_1211(s[2], a, d[2]);
- }
- /* a == 255 is impossible, because alpha < 255 */
- d += 3;
- s += 4;
- }
- px += rs;
- spx += srs;
- }
- }
-}
-
-void
-nr_R8G8B8_R8G8B8_R8G8B8A8_P_A8 (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, const unsigned char *mpx, int mrs)
-{
- unsigned int x, y;
-
- for (y = h; y > 0; y--) {
- unsigned char* d = px;
- const unsigned char* s = spx;
- const unsigned char* m = mpx;
- for (x = w; x > 0; x--) {
- unsigned int a;
- a = NR_PREMUL_112(s[3], m[0]);
- if (a == 0) {
- /* NOP */
- } else if (a == 255*255) {
- memcpy(d, s, 3);
- } else {
- // dc' = (1 - m*sa) * dc + m*sc
- d[0] = NR_COMPOSEP11_2211(NR_PREMUL_112(s[0], m[0]), a, d[0]);
- d[1] = NR_COMPOSEP11_2211(NR_PREMUL_112(s[1], m[0]), a, d[1]);
- d[2] = NR_COMPOSEP11_2211(NR_PREMUL_112(s[2], m[0]), a, d[2]);
- }
- d += 3;
- s += 4;
- m += 1;
- }
- px += rs;
- spx += srs;
- mpx += mrs;
- }
-}
-
-void
-nr_R8G8B8_R8G8B8_R8G8B8A8_N_A8 (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, const unsigned char *mpx, int mrs)
-{
- unsigned int x, y;
-
- for (y = h; y > 0; y--) {
- unsigned char* d = px;
- const unsigned char* s = spx;
- const unsigned char* m = mpx;
- for (x = w; x > 0; x--) {
- unsigned int a;
- a = NR_PREMUL_112(s[3], m[0]);
- if (a == 0) {
- /* NOP */
- } else if (a == 255*255) {
- memcpy(d, s, 3);
- } else {
- // dc' = (1 - m*sa) * dc + m*sa*sc
- d[0] = NR_COMPOSEN11_1211(s[0], a, d[0]);
- d[1] = NR_COMPOSEN11_1211(s[1], a, d[1]);
- d[2] = NR_COMPOSEN11_1211(s[2], a, d[2]);
- }
- d += 3;
- s += 4;
- m += 1;
- }
- px += rs;
- spx += srs;
- mpx += mrs;
- }
-}
-
-
diff --git a/src/libnr/nr-compose.h b/src/libnr/nr-compose.h
deleted file mode 100644
index 4cecfac60..000000000
--- a/src/libnr/nr-compose.h
+++ /dev/null
@@ -1,69 +0,0 @@
-#ifndef __NR_COMPOSE_H__
-#define __NR_COMPOSE_H__
-
-/*
- * Pixel buffer rendering library
- *
- * Authors:
- * Lauris Kaplinski <lauris@kaplinski.com>
- *
- * This code is in public domain
- */
-
-/* FINAL DST SRC */
-
-void nr_R8G8B8A8_N_EMPTY_R8G8B8A8_N (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha);
-void nr_R8G8B8A8_N_EMPTY_R8G8B8A8_P (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha);
-void nr_R8G8B8A8_P_EMPTY_R8G8B8A8_N (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha);
-void nr_R8G8B8A8_P_EMPTY_R8G8B8A8_P (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha);
-
-void nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_N (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha);
-void nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_P (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha);
-void nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_N (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha);
-void nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_P (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha);
-
-/* FINAL DST SRC MASK */
-
-void nr_R8G8B8A8_N_EMPTY_R8G8B8A8_N_A8 (unsigned char *px, int w, int h, int rs,
- const unsigned char *spx, int srs,
- const unsigned char *mpx, int mrs);
-void nr_R8G8B8A8_N_EMPTY_R8G8B8A8_P_A8 (unsigned char *px, int w, int h, int rs,
- const unsigned char *spx, int srs,
- const unsigned char *mpx, int mrs);
-void nr_R8G8B8A8_P_EMPTY_R8G8B8A8_N_A8 (unsigned char *px, int w, int h, int rs,
- const unsigned char *spx, int srs,
- const unsigned char *mpx, int mrs);
-void nr_R8G8B8A8_P_EMPTY_R8G8B8A8_P_A8 (unsigned char *px, int w, int h, int rs,
- const unsigned char *spx, int srs,
- const unsigned char *mpx, int mrs);
-
-void nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_N_A8 (unsigned char *p, int w, int h, int rs,
- const unsigned char *s, int srs,
- const unsigned char *m, int mrs);
-void nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_P_A8 (unsigned char *p, int w, int h, int rs,
- const unsigned char *s, int srs,
- const unsigned char *m, int mrs);
-void nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_N_A8 (unsigned char *p, int w, int h, int rs,
- const unsigned char *s, int srs,
- const unsigned char *m, int mrs);
-void nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_P_A8 (unsigned char *p, int w, int h, int rs,
- const unsigned char *s, int srs,
- const unsigned char *m, int mrs);
-
-/* FINAL DST MASK COLOR */
-
-void nr_R8G8B8A8_N_EMPTY_A8_RGBA32 (unsigned char *px, int w, int h, int rs, const unsigned char *mpx, int mrs, unsigned long rgba);
-void nr_R8G8B8A8_P_EMPTY_A8_RGBA32 (unsigned char *px, int w, int h, int rs, const unsigned char *mpx, int mrs, unsigned long rgba);
-
-void nr_R8G8B8_R8G8B8_A8_RGBA32 (unsigned char *px, int w, int h, int rs, const unsigned char *mpx, int mrs, unsigned long rgba);
-void nr_R8G8B8A8_N_R8G8B8A8_N_A8_RGBA32 (unsigned char *px, int w, int h, int rs, const unsigned char *mpx, int mrs, unsigned long rgba);
-void nr_R8G8B8A8_P_R8G8B8A8_P_A8_RGBA32 (unsigned char *px, int w, int h, int rs, const unsigned char *mpx, int mrs, unsigned long rgba);
-
-/* RGB */
-
-void nr_R8G8B8_R8G8B8_R8G8B8A8_P (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha);
-void nr_R8G8B8_R8G8B8_R8G8B8A8_N (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha);
-void nr_R8G8B8_R8G8B8_R8G8B8A8_P_A8 (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, const unsigned char *mpx, int mrs);
-void nr_R8G8B8_R8G8B8_R8G8B8A8_N_A8 (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, const unsigned char *mpx, int mrs);
-
-#endif
diff --git a/src/libnr/nr-convert2geom.h b/src/libnr/nr-convert2geom.h
index 2f87632fb..75098ce2b 100644
--- a/src/libnr/nr-convert2geom.h
+++ b/src/libnr/nr-convert2geom.h
@@ -9,7 +9,6 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include <libnr/nr-matrix.h>
#include <libnr/nr-rect.h>
#include <libnr/nr-point.h>
#include <2geom/affine.h>
@@ -24,19 +23,6 @@ inline NR::Point from_2geom(Geom::Point const & _pt) {
return NR::Point(_pt[0], _pt[1]);
}
-inline Geom::Affine to_2geom(NR::Matrix const & mat) {
- Geom::Affine mat2geom(mat[0], mat[1], mat[2], mat[3], mat[4], mat[5]);
- return mat2geom;
-}
-inline NR::Matrix from_2geom(Geom::Affine const & mat) {
- NR::Matrix mat2geom(mat[0], mat[1], mat[2], mat[3], mat[4], mat[5]);
- return mat2geom;
-}
-
-inline Geom::Translate to_2geom(NR::translate const & mat) {
- return Geom::Translate( mat.offset[0], mat.offset[1] );
-}
-
inline Geom::Rect to_2geom(NR::Rect const & rect) {
Geom::Rect rect2geom(to_2geom(rect.min()), to_2geom(rect.max()));
return rect2geom;
@@ -54,13 +40,6 @@ inline Geom::OptRect to_2geom(boost::optional<NR::Rect> const & rect) {
return rect2geom;
}
-inline NR::scale from_2geom(Geom::Scale const & in) {
- return NR::scale(in[Geom::X], in[Geom::Y]);
-}
-inline Geom::Scale to_2geom(NR::scale const & in) {
- return Geom::Scale(in[NR::X], in[NR::Y]);
-}
-
#endif
/*
diff --git a/src/libnr/nr-convex-hull-ops.h b/src/libnr/nr-convex-hull-ops.h
deleted file mode 100644
index 2e96bf367..000000000
--- a/src/libnr/nr-convex-hull-ops.h
+++ /dev/null
@@ -1,29 +0,0 @@
-#ifndef SEEN_NR_CONVEX_HULL_FNS_H
-#define SEEN_NR_CONVEX_HULL_FNS_H
-
-/* ex:set et ts=4 sw=4: */
-
-/*
- * A class representing the convex hull of a set of points.
- *
- * Copyright 2004 MenTaLguY <mental@rydia.net>
- *
- * This code is licensed under the GNU GPL; see COPYING for more information.
- */
-
-#include <libnr/nr-matrix-fns.h>
-#include <libnr/nr-convex-hull.h>
-
-namespace NR {
-
-ConvexHull operator*(const Rect &r, const Matrix &m) {
- ConvexHull points(r.corner(0));
- for ( unsigned i = 1 ; i < 4 ; i++ ) {
- points.add(r.corner(i));
- }
- return points;
-}
-
-} /* namespace NR */
-
-#endif
diff --git a/src/libnr/nr-convex-hull.h b/src/libnr/nr-convex-hull.h
deleted file mode 100644
index dafdd8840..000000000
--- a/src/libnr/nr-convex-hull.h
+++ /dev/null
@@ -1,59 +0,0 @@
-#ifndef SEEN_NR_CONVEX_HULL_H
-#define SEEN_NR_CONVEX_HULL_H
-
-/* ex:set et ts=4 sw=4: */
-
-/*
- * A class representing the convex hull of a set of points.
- *
- * Copyright 2004 MenTaLguY <mental@rydia.net>
- *
- * This code is licensed under the GNU GPL; see COPYING for more information.
- */
-
-#include <libnr/nr-rect.h>
-
-namespace NR {
-
-class ConvexHull {
-public:
- ConvexHull() : _bounds() {}
- explicit ConvexHull(Point const &p) : _bounds(Rect(p, p)) {}
-
- boost::optional<Point> midpoint() const {
- if (_bounds) {
- return _bounds->midpoint();
- } else {
- return boost::optional<Point>();
- }
- }
-
- void add(Point const &p) {
- if (_bounds) {
- _bounds->expandTo(p);
- } else {
- _bounds = Rect(p, p);
- }
- }
- void add(Rect const &r) {
- // Note that this is a hack. when convexhull actually works
- // you will need to add all four points.
- _bounds = union_bounds(_bounds, r);
- }
- void add(ConvexHull const &h) {
- if (h._bounds) {
- add(*h._bounds);
- }
- }
-
- boost::optional<Rect> const &bounds() const {
- return _bounds;
- }
-
-private:
- boost::optional<Rect> _bounds;
-};
-
-} /* namespace NR */
-
-#endif
diff --git a/src/libnr/nr-gradient.cpp b/src/libnr/nr-gradient.cpp
deleted file mode 100644
index cb03c048b..000000000
--- a/src/libnr/nr-gradient.cpp
+++ /dev/null
@@ -1,554 +0,0 @@
-#define __NR_GRADIENT_C__
-
-/*
- * Pixel buffer rendering library
- *
- * Authors:
- * Lauris Kaplinski <lauris@kaplinski.com>
- * MenTaLguY <mental@rydia.net>
- *...Jasper van de Gronde <th.v.d.gronde@hccnet.nl>
- *
- * Copyright (C) 2009 Jasper van de Gronde
- * Copyright (C) 2007 MenTaLguY
- * Copyright (C) 2001-2002 Lauris Kaplinski
- * Copyright (C) 2001-2002 Ximian, Inc.
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-/*
- * Derived in part from public domain code by Lauris Kaplinski
- */
-
-#include <cstring>
-#include <libnr/nr-pixops.h>
-#include <libnr/nr-pixblock-pixel.h>
-#include <libnr/nr-blit.h>
-#include <libnr/nr-gradient.h>
-#include <libnr/nr-matrix-ops.h>
-#include <glib/gtypes.h>
-#include <stdio.h>
-
-/* Common */
-
-#define NRG_MASK (NR_GRADIENT_VECTOR_LENGTH - 1)
-#define NRG_2MASK ((long long) ((NR_GRADIENT_VECTOR_LENGTH << 1) - 1))
-
-namespace {
-inline unsigned char const *vector_index(int idx,
- unsigned char const *vector)
-{
- return vector + 4 * idx;
-}
-
-template <NRGradientSpread spread> struct Spread;
-
-template <>
-struct Spread<NR_GRADIENT_SPREAD_PAD> {
-static double index_at(NR::Coord r, double const unity = 1.0) {
- return r<0.0?0.0:r>unity?unity:r;
-}
-static unsigned char const *color_at(NR::Coord r,
- unsigned char const *vector)
-{
- return vector_index((int)(index_at(r, NR_GRADIENT_VECTOR_LENGTH - 1)+.5), vector);
- //return vector_index((int)CLAMP(r, 0, (double)(NR_GRADIENT_VECTOR_LENGTH - 1)), vector);
-}
-};
-
-template <>
-struct Spread<NR_GRADIENT_SPREAD_REPEAT> {
-static double index_at(NR::Coord r, double const unity = 1.0) {
- return r<0.0?(unity+fmod(r,unity)):fmod(r,unity);
-}
-static unsigned char const *color_at(NR::Coord r,
- unsigned char const *vector)
-{
- return vector_index((int)(index_at(r, NR_GRADIENT_VECTOR_LENGTH - 1)+.5), vector);
- //return vector_index((int)((long long)r & NRG_MASK), vector);
-}
-};
-
-template <>
-struct Spread<NR_GRADIENT_SPREAD_REFLECT> {
-static double index_at(NR::Coord r, double const unity = 1.0) {
- r = r<0.0?(2*unity+fmod(r,2*unity)):fmod(r,2*unity);
- if (r>unity) r=2*unity-r;
- return r;
-}
-static unsigned char const *color_at(NR::Coord r,
- unsigned char const *vector)
-{
- return vector_index((int)(index_at(r, NR_GRADIENT_VECTOR_LENGTH - 1)+.5), vector);
- //int idx = (int) ((long long)r & NRG_2MASK);
- //if (idx > NRG_MASK) idx = NRG_2MASK - idx;
- //return vector_index(idx, vector);
-}
-};
-
-template <NR_PIXBLOCK_MODE mode> struct ModeTraits;
-
-template <>
-struct ModeTraits<NR_PIXBLOCK_MODE_R8G8B8A8N> {
-static const unsigned bpp=4;
-};
-
-template <>
-struct ModeTraits<NR_PIXBLOCK_MODE_R8G8B8A8P> {
-static const unsigned bpp=4;
-};
-
-template <>
-struct ModeTraits<NR_PIXBLOCK_MODE_R8G8B8> {
-static const unsigned bpp=3;
-};
-
-template <>
-struct ModeTraits<NR_PIXBLOCK_MODE_A8> {
-static const unsigned bpp=1;
-};
-
-template <NR_PIXBLOCK_MODE mode, bool empty>
-struct Compose {
-static const unsigned bpp=ModeTraits<mode>::bpp;
-static void compose(NRPixBlock *pb, unsigned char *dest,
- NRPixBlock *spb, unsigned char const *src)
-{
- nr_compose_pixblock_pixblock_pixel(pb, dest, spb, src);
-}
-};
-
-template <>
-struct Compose<NR_PIXBLOCK_MODE_R8G8B8A8N, true> {
-static const unsigned bpp=4;
-static void compose(NRPixBlock */*pb*/, unsigned char *dest,
- NRPixBlock */*spb*/, unsigned char const *src)
-{
- std::memcpy(dest, src, 4);
-}
-};
-
-template <>
-struct Compose<NR_PIXBLOCK_MODE_R8G8B8A8P, true> {
-static const unsigned bpp=4;
-static void compose(NRPixBlock */*pb*/, unsigned char *dest,
- NRPixBlock */*spb*/, unsigned char const *src)
-{
- dest[0] = NR_PREMUL_111(src[0], src[3]);
- dest[1] = NR_PREMUL_111(src[1], src[3]);
- dest[2] = NR_PREMUL_111(src[2], src[3]);
- dest[3] = src[3];
-}
-};
-
-template <>
-struct Compose<NR_PIXBLOCK_MODE_R8G8B8, true> {
-static const unsigned bpp=3;
-static void compose(NRPixBlock */*pb*/, unsigned char *dest,
- NRPixBlock */*spb*/, unsigned char const *src)
-{
- dest[0] = NR_COMPOSEN11_1111(src[0], src[3], 255);
- dest[1] = NR_COMPOSEN11_1111(src[1], src[3], 255);
- dest[2] = NR_COMPOSEN11_1111(src[2], src[3], 255);
-}
-};
-
-template <>
-struct Compose<NR_PIXBLOCK_MODE_A8, true> {
-static const unsigned bpp=1;
-static void compose(NRPixBlock */*pb*/, unsigned char *dest,
- NRPixBlock */*spb*/, unsigned char const *src)
-{
- dest[0] = src[3];
-}
-};
-
-template <>
-struct Compose<NR_PIXBLOCK_MODE_R8G8B8A8N, false> {
-static const unsigned bpp=4;
-static void compose(NRPixBlock */*pb*/, unsigned char *dest,
- NRPixBlock */*spb*/, unsigned char const *src)
-{
- unsigned int ca;
- ca = NR_COMPOSEA_112(src[3], dest[3]);
- dest[0] = NR_COMPOSENNN_111121(src[0], src[3], dest[0], dest[3], ca);
- dest[1] = NR_COMPOSENNN_111121(src[1], src[3], dest[1], dest[3], ca);
- dest[2] = NR_COMPOSENNN_111121(src[2], src[3], dest[2], dest[3], ca);
- dest[3] = NR_NORMALIZE_21(ca);
-}
-};
-
-template <>
-struct Compose<NR_PIXBLOCK_MODE_R8G8B8A8P, false> {
-static const unsigned bpp=4;
-static void compose(NRPixBlock */*pb*/, unsigned char *dest,
- NRPixBlock */*spb*/, unsigned char const *src)
-{
- dest[0] = NR_COMPOSENPP_1111(src[0], src[3], dest[0]);
- dest[1] = NR_COMPOSENPP_1111(src[1], src[3], dest[1]);
- dest[2] = NR_COMPOSENPP_1111(src[2], src[3], dest[2]);
- dest[3] = NR_COMPOSEA_111(src[3], dest[3]);
-}
-};
-
-template <>
-struct Compose<NR_PIXBLOCK_MODE_R8G8B8, false> {
-static const unsigned bpp=3;
-static void compose(NRPixBlock */*pb*/, unsigned char *dest,
- NRPixBlock */*spb*/, unsigned char const *src)
-{
- dest[0] = NR_COMPOSEN11_1111(src[0], src[3], dest[0]);
- dest[1] = NR_COMPOSEN11_1111(src[1], src[3], dest[1]);
- dest[2] = NR_COMPOSEN11_1111(src[2], src[3], dest[2]);
-}
-};
-
-template <typename Subtype, typename spread>
-static void
-render_spread(NRGradientRenderer *gr, NRPixBlock *pb)
-{
- switch (pb->mode) {
- case NR_PIXBLOCK_MODE_R8G8B8A8N:
- if (pb->empty) {
- typedef Compose<NR_PIXBLOCK_MODE_R8G8B8A8N, true> compose;
- Subtype::template render<compose, spread>(gr, pb);
- } else {
- typedef Compose<NR_PIXBLOCK_MODE_R8G8B8A8N, false> compose;
- Subtype::template render<compose, spread>(gr, pb);
- }
- break;
- case NR_PIXBLOCK_MODE_R8G8B8A8P:
- if (pb->empty) {
- typedef Compose<NR_PIXBLOCK_MODE_R8G8B8A8P, true> compose;
- Subtype::template render<compose, spread>(gr, pb);
- } else {
- typedef Compose<NR_PIXBLOCK_MODE_R8G8B8A8P, false> compose;
- Subtype::template render<compose, spread>(gr, pb);
- }
- break;
- case NR_PIXBLOCK_MODE_R8G8B8:
- if (pb->empty) {
- typedef Compose<NR_PIXBLOCK_MODE_R8G8B8, true> compose;
- Subtype::template render<compose, spread>(gr, pb);
- } else {
- typedef Compose<NR_PIXBLOCK_MODE_R8G8B8, false> compose;
- Subtype::template render<compose, spread>(gr, pb);
- }
- break;
- case NR_PIXBLOCK_MODE_A8:
- if (pb->empty) {
- typedef Compose<NR_PIXBLOCK_MODE_A8, true> compose;
- Subtype::template render<compose, spread>(gr, pb);
- } else {
- typedef Compose<NR_PIXBLOCK_MODE_A8, false> compose;
- Subtype::template render<compose, spread>(gr, pb);
- }
- break;
- }
-}
-
-template <typename Subtype>
-static void
-render(NRRenderer *r, NRPixBlock *pb, NRPixBlock */*m*/)
-{
- NRGradientRenderer *gr = static_cast<NRGradientRenderer *>(r);
-
- switch (gr->spread) {
- case NR_GRADIENT_SPREAD_REPEAT:
- render_spread<Subtype, Spread<NR_GRADIENT_SPREAD_REPEAT> >(gr, pb);
- break;
- case NR_GRADIENT_SPREAD_REFLECT:
- render_spread<Subtype, Spread<NR_GRADIENT_SPREAD_REFLECT> >(gr, pb);
- break;
- case NR_GRADIENT_SPREAD_PAD:
- default:
- render_spread<Subtype, Spread<NR_GRADIENT_SPREAD_PAD> >(gr, pb);
- }
-}
-}
-
-/* Linear */
-
-namespace {
-
-struct Linear {
-template <typename compose, typename spread>
-static void render(NRGradientRenderer *gr, NRPixBlock *pb) {
- NRLGradientRenderer *lgr = static_cast<NRLGradientRenderer *>(gr);
-
- int x, y;
- unsigned char *d;
- double pos;
- NRPixBlock spb;
- int x0, y0, width, height, rs;
-
- x0 = pb->area.x0;
- y0 = pb->area.y0;
- width = pb->area.x1 - pb->area.x0;
- height = pb->area.y1 - pb->area.y0;
- rs = pb->rs;
-
- nr_pixblock_setup_extern(&spb, NR_PIXBLOCK_MODE_R8G8B8A8N,
- 0, 0, NR_GRADIENT_VECTOR_LENGTH, 1,
- (unsigned char *) lgr->vector,
- 4 * NR_GRADIENT_VECTOR_LENGTH, 0, 0);
-
- for (y = 0; y < height; y++) {
- d = NR_PIXBLOCK_PX(pb) + y * rs;
- pos = (y + y0 - lgr->y0) * lgr->dy + (0 + x0 - lgr->x0) * lgr->dx;
- for (x = 0; x < width; x++) {
- unsigned char const *s=spread::color_at(pos, lgr->vector);
- compose::compose(pb, d, &spb, s);
- d += compose::bpp;
- pos += lgr->dx;
- }
- }
-
- nr_pixblock_release(&spb);
-}
-};
-
-}
-
-NRRenderer *
-nr_lgradient_renderer_setup (NRLGradientRenderer *lgr,
- const unsigned char *cv,
- unsigned int spread,
- const NR::Matrix *gs2px,
- float x0, float y0,
- float x1, float y1)
-{
- NR::Matrix n2gs, n2px, px2n;
-
- lgr->render = &render<Linear>;
-
- lgr->vector = cv;
- lgr->spread = spread;
-
- n2gs[0] = x1 - x0;
- n2gs[1] = y1 - y0;
- n2gs[2] = y1 - y0;
- n2gs[3] = x0 - x1;
- n2gs[4] = x0;
- n2gs[5] = y0;
-
- n2px = n2gs * (*gs2px);
- px2n = n2px.inverse();
-
- lgr->x0 = n2px[4] - 0.5; // These -0.5 offsets make sure that the gradient is sampled in the MIDDLE of each pixel.
- lgr->y0 = n2px[5] - 0.5;
- lgr->dx = px2n[0] * (NR_GRADIENT_VECTOR_LENGTH-1);
- lgr->dy = px2n[2] * (NR_GRADIENT_VECTOR_LENGTH-1);
-
- return (NRRenderer *) lgr;
-}
-
-/* Radial */
-
-/*
- * The archetype is following
- *
- * gx gy - pixel coordinates
- * Px Py - coordinates, where Fx Fy - gx gy line intersects with circle
- *
- * (1) (gx - fx) * (Py - fy) = (gy - fy) * (Px - fx)
- * (2) (Px - cx) * (Px - cx) + (Py - cy) * (Py - cy) = r * r
- *
- * (3) Py = (Px - fx) * (gy - fy) / (gx - fx) + fy
- * (4) (gy - fy) / (gx - fx) = D
- * (5) Py = D * Px - D * fx + fy
- *
- * (6) D * fx - fy + cy = N
- * (7) Px * Px - 2 * Px * cx + cx * cx + (D * Px) * (D * Px) - 2 * (D * Px) * N + N * N = r * r
- * (8) (D * D + 1) * (Px * Px) - 2 * (cx + D * N) * Px + cx * cx + N * N = r * r
- *
- * (9) A = D * D + 1
- * (10) B = -2 * (cx + D * N)
- * (11) C = cx * cx + N * N - r * r
- *
- * (12) Px = (-B +- SQRT(B * B - 4 * A * C)) / 2 * A
- */
-
-namespace {
-
-struct SymmetricRadial {
-template <typename compose, typename spread>
-static void render(NRGradientRenderer *gr, NRPixBlock *pb)
-{
- NRRGradientRenderer *rgr = static_cast<NRRGradientRenderer *>(gr);
-
- NR::Coord const dx = rgr->px2gs[0];
- NR::Coord const dy = rgr->px2gs[1];
-
- NRPixBlock spb;
- nr_pixblock_setup_extern(&spb, NR_PIXBLOCK_MODE_R8G8B8A8N,
- 0, 0, NR_GRADIENT_VECTOR_LENGTH, 1,
- (unsigned char *) rgr->vector,
- 4 * NR_GRADIENT_VECTOR_LENGTH,
- 0, 0);
-
- for (int y = pb->area.y0; y < pb->area.y1; y++) {
- unsigned char *d = NR_PIXBLOCK_PX(pb) + (y - pb->area.y0) * pb->rs;
- NR::Coord gx = rgr->px2gs[0] * pb->area.x0 + rgr->px2gs[2] * y + rgr->px2gs[4];
- NR::Coord gy = rgr->px2gs[1] * pb->area.x0 + rgr->px2gs[3] * y + rgr->px2gs[5];
- for (int x = pb->area.x0; x < pb->area.x1; x++) {
- NR::Coord const pos = sqrt(((gx*gx) + (gy*gy)));
- unsigned char const *s=spread::color_at(pos, rgr->vector);
- compose::compose(pb, d, &spb, s);
- d += compose::bpp;
- gx += dx;
- gy += dy;
- }
- }
-
- nr_pixblock_release(&spb);
-}
-};
-
-struct Radial {
-template <typename compose, typename spread>
-static void render(NRGradientRenderer *gr, NRPixBlock *pb)
-{
- NRRGradientRenderer *rgr = static_cast<NRRGradientRenderer *>(gr);
- int const x0 = pb->area.x0;
- int const y0 = pb->area.y0;
- int const x1 = pb->area.x1;
- int const y1 = pb->area.y1;
- int const rs = pb->rs;
-
- NRPixBlock spb;
- nr_pixblock_setup_extern(&spb, NR_PIXBLOCK_MODE_R8G8B8A8N,
- 0, 0, NR_GRADIENT_VECTOR_LENGTH, 1,
- (unsigned char *) rgr->vector,
- 4 * NR_GRADIENT_VECTOR_LENGTH,
- 0, 0);
-
- for (int y = y0; y < y1; y++) {
- unsigned char *d = NR_PIXBLOCK_PX(pb) + (y - y0) * rs;
- NR::Coord gx = rgr->px2gs[0] * x0 + rgr->px2gs[2] * y + rgr->px2gs[4];
- NR::Coord gy = rgr->px2gs[1] * x0 + rgr->px2gs[3] * y + rgr->px2gs[5];
- NR::Coord const dx = rgr->px2gs[0];
- NR::Coord const dy = rgr->px2gs[1];
- for (int x = x0; x < x1; x++) {
- NR::Coord const gx2 = gx * gx;
- NR::Coord const gxy2 = gx2 + gy * gy;
- NR::Coord const qgx2_4 = gx2 - rgr->C * gxy2;
- /* INVARIANT: qgx2_4 >= 0.0 */
- /* qgx2_4 = MAX(qgx2_4, 0.0); */
- NR::Coord const pxgx = gx + sqrt(qgx2_4);
- /* We can safely divide by 0 here */
- /* If we are sure pxgx cannot be -0 */
- NR::Coord const pos = gxy2 / pxgx * (NR_GRADIENT_VECTOR_LENGTH-1);
-
- unsigned char const *s;
- if (pos < (1U << 31)) {
- s = spread::color_at(pos, rgr->vector);
- } else {
- s = vector_index(NR_GRADIENT_VECTOR_LENGTH - 1, rgr->vector);
- }
-
- compose::compose(pb, d, &spb, s);
- d += compose::bpp;
-
- gx += dx;
- gy += dy;
- }
- }
-
- nr_pixblock_release(&spb);
-}
-};
-
-}
-
-static void nr_rgradient_render_block_end(NRRenderer *r, NRPixBlock *pb, NRPixBlock *m);
-
-NRRenderer *
-nr_rgradient_renderer_setup(NRRGradientRenderer *rgr,
- unsigned char const *cv,
- unsigned spread,
- NR::Matrix const *gs2px,
- float cx, float cy,
- float fx, float fy,
- float r)
-{
- rgr->vector = cv;
- rgr->spread = spread;
-
- if (r < NR_EPSILON) {
- rgr->render = nr_rgradient_render_block_end;
- } else if (NR_DF_TEST_CLOSE(cx, fx, NR_EPSILON) &&
- NR_DF_TEST_CLOSE(cy, fy, NR_EPSILON)) {
- rgr->render = render<SymmetricRadial>;
-
- rgr->px2gs = gs2px->inverse();
- rgr->px2gs[0] *= (NR_GRADIENT_VECTOR_LENGTH-1) / r;
- rgr->px2gs[1] *= (NR_GRADIENT_VECTOR_LENGTH-1) / r;
- rgr->px2gs[2] *= (NR_GRADIENT_VECTOR_LENGTH-1) / r;
- rgr->px2gs[3] *= (NR_GRADIENT_VECTOR_LENGTH-1) / r;
- rgr->px2gs[4] -= cx;
- rgr->px2gs[5] -= cy;
- rgr->px2gs[4] *= (NR_GRADIENT_VECTOR_LENGTH-1) / r;
- rgr->px2gs[5] *= (NR_GRADIENT_VECTOR_LENGTH-1) / r;
- rgr->px2gs[4] += 0.5*(rgr->px2gs[0]+rgr->px2gs[2]); // These offsets make sure the gradient is sampled in the MIDDLE of each pixel
- rgr->px2gs[5] += 0.5*(rgr->px2gs[1]+rgr->px2gs[3]);
-
- rgr->cx = 0.0;
- rgr->cy = 0.0;
- rgr->fx = rgr->cx;
- rgr->fy = rgr->cy;
- rgr->r = 1.0;
- } else {
- rgr->render = render<Radial>;
-
- NR::Coord const df = hypot(fx - cx, fy - cy);
- if (df >= r) {
- fx = cx + (fx - cx ) * r / (float) df;
- fy = cy + (fy - cy ) * r / (float) df;
- }
-
- NR::Matrix n2gs;
- n2gs[0] = cx - fx;
- n2gs[1] = cy - fy;
- n2gs[2] = cy - fy;
- n2gs[3] = fx - cx;
- n2gs[4] = fx;
- n2gs[5] = fy;
-
- NR::Matrix n2px;
- n2px = n2gs * (*gs2px);
- rgr->px2gs = n2px.inverse();
- rgr->px2gs[4] += 0.5*(rgr->px2gs[0]+rgr->px2gs[2]); // These offsets make sure the gradient is sampled in the MIDDLE of each pixel
- rgr->px2gs[5] += 0.5*(rgr->px2gs[1]+rgr->px2gs[3]);
-
- rgr->cx = 1.0;
- rgr->cy = 0.0;
- rgr->fx = 0.0;
- rgr->fy = 0.0;
- rgr->r = r / (float) hypot(fx - cx, fy - cy);
- rgr->C = 1.0F - rgr->r * rgr->r;
- /* INVARIANT: C < 0 */
- rgr->C = MIN(rgr->C, -NR_EPSILON);
- }
-
- return (NRRenderer *) rgr;
-}
-
-static void
-nr_rgradient_render_block_end(NRRenderer *r, NRPixBlock *pb, NRPixBlock *m)
-{
- unsigned char const *c = ((NRRGradientRenderer *) r)->vector + 4 * (NR_GRADIENT_VECTOR_LENGTH - 1);
-
- nr_blit_pixblock_mask_rgba32(pb, m, (c[0] << 24) | (c[1] << 16) | (c[2] << 8) | c[3]);
-}
-
-/*
- 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/libnr/nr-gradient.h b/src/libnr/nr-gradient.h
deleted file mode 100644
index f5afdc98d..000000000
--- a/src/libnr/nr-gradient.h
+++ /dev/null
@@ -1,81 +0,0 @@
-#ifndef __NR_GRADIENT_H__
-#define __NR_GRADIENT_H__
-
-/*
- * Pixel buffer rendering library
- *
- * Authors:
- * Lauris Kaplinski <lauris@kaplinski.com>
- *
- * Copyright (C) 2001-2002 Lauris Kaplinski
- * Copyright (C) 2001-2002 Ximian, Inc.
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-/*
- * Derived in part from public domain code by Lauris Kaplinski
- */
-
-#include <libnr/nr-matrix.h>
-#include <libnr/nr-render.h>
-
-#define NR_GRADIENT_VECTOR_BITS 10
-#define NR_GRADIENT_VECTOR_LENGTH (1<<NR_GRADIENT_VECTOR_BITS)
-
-enum NRGradientSpread {
- NR_GRADIENT_SPREAD_PAD,
- NR_GRADIENT_SPREAD_REFLECT,
- NR_GRADIENT_SPREAD_REPEAT
-};
-
-struct NRGradientRenderer : public NRRenderer {
- const unsigned char *vector;
- unsigned int spread;
-};
-
-/* Linear */
-
-struct NRLGradientRenderer : public NRGradientRenderer {
- double x0, y0;
- double dx, dy;
-};
-
-NRRenderer *nr_lgradient_renderer_setup (NRLGradientRenderer *lgr,
- const unsigned char *cv,
- unsigned int spread,
- const NR::Matrix *gs2px,
- float x0, float y0,
- float x1, float y1);
-
-/* Radial */
-
-struct NRRGradientRenderer : public NRGradientRenderer {
- NR::Matrix px2gs;
- float cx, cy;
- float fx, fy;
- float r;
- float C;
-};
-
-NRRenderer *nr_rgradient_renderer_setup (NRRGradientRenderer *rgr,
- const unsigned char *cv,
- unsigned int spread,
- const NR::Matrix *gs2px,
- float cx, float cy,
- float fx, float fy,
- float r);
-
-
-
-#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:textwidth=99 :
diff --git a/src/libnr/nr-matrix-div.cpp b/src/libnr/nr-matrix-div.cpp
deleted file mode 100644
index d6fb598b8..000000000
--- a/src/libnr/nr-matrix-div.cpp
+++ /dev/null
@@ -1,22 +0,0 @@
-#include "libnr/nr-matrix-ops.h"
-#include "libnr/nr-point-matrix-ops.h"
-
-NR::Point operator/(NR::Point const &p, NR::Matrix const &m) {
- return p * m.inverse();
-}
-
-NR::Matrix operator/(NR::Matrix const &a, NR::Matrix const &b) {
- return a * b.inverse();
-}
-
-
-/*
- 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/libnr/nr-matrix-div.h b/src/libnr/nr-matrix-div.h
deleted file mode 100644
index 8669e2ce2..000000000
--- a/src/libnr/nr-matrix-div.h
+++ /dev/null
@@ -1,21 +0,0 @@
-#ifndef SEEN_LIBNR_NR_MATRIX_DIV_H
-#define SEEN_LIBNR_NR_MATRIX_DIV_H
-
-#include "libnr/nr-forward.h"
-
-NR::Point operator/(NR::Point const &, NR::Matrix const &);
-
-NR::Matrix operator/(NR::Matrix const &, NR::Matrix const &);
-
-#endif /* !SEEN_LIBNR_NR_MATRIX_DIV_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/libnr/nr-matrix-fns.cpp b/src/libnr/nr-matrix-fns.cpp
deleted file mode 100644
index c8eb986fa..000000000
--- a/src/libnr/nr-matrix-fns.cpp
+++ /dev/null
@@ -1,55 +0,0 @@
-#include <libnr/nr-matrix-fns.h>
-#include <cstdio>
-
-namespace NR {
-
-Matrix elliptic_quadratic_form(Matrix const &m) {
- double const od = m[0] * m[1] + m[2] * m[3];
- return Matrix((m[0]*m[0] + m[1]*m[1]), od,
- od, (m[2]*m[2] + m[3]*m[3]),
- 0, 0);
-/* def quadratic_form((a, b), (c, d)):
- return ((a*a + c*c), a*c+b*d),(a*c+b*d, (b*b + d*d)) */
-}
-
-Eigen::Eigen(Matrix const &m) {
- double const B = -m[0] - m[3];
- double const C = m[0]*m[3] - m[1]*m[2];
- double const center = -B/2.0;
- double const delta = sqrt(B*B-4*C)/2.0;
- values = Point(center + delta, center - delta);
- for (int i = 0; i < 2; i++) {
- vectors[i] = unit_vector(rot90(Point(m[0]-values[i], m[1])));
- }
-}
-
-/** Returns just the scale/rotate/skew part of the matrix without the translation part. */
-Matrix transform(Matrix const &m) {
- Matrix const ret(m[0], m[1],
- m[2], m[3],
- 0, 0);
- return ret;
-}
-
-translate get_translation(Matrix const &m) {
- return translate(m[4], m[5]);
-}
-
-void matrix_print(const gchar *say, Matrix const &m)
-{
- printf ("%s %g %g %g %g %g %g\n", say, m[0], m[1], m[2], m[3], m[4], m[5]);
-}
-
-} // namespace NR
-
-
-/*
- 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/libnr/nr-matrix-fns.h b/src/libnr/nr-matrix-fns.h
deleted file mode 100644
index a46aca909..000000000
--- a/src/libnr/nr-matrix-fns.h
+++ /dev/null
@@ -1,53 +0,0 @@
-#ifndef SEEN_NR_MATRIX_FNS_H
-#define SEEN_NR_MATRIX_FNS_H
-
-#include "nr-matrix.h"
-#include <math.h>
-
-namespace NR {
-
-/** Given a matrix m such that unit_circle = m*x, this returns the
- * quadratic form x*A*x = 1. */
-Matrix elliptic_quadratic_form(Matrix const &m);
-
-/** Given a matrix (ignoring the translation) this returns the eigen
- * values and vectors. */
-class Eigen{
-public:
- Point vectors[2];
- Point values;
- Eigen(Matrix const &m);
-};
-
-// Matrix factories
-Matrix from_basis(const Point x_basis, const Point y_basis, const Point offset=Point(0,0));
-
-Matrix identity();
-
-double expansion(Matrix const &m);
-inline double expansionX(Matrix const &m) { return hypot(m[0], m[1]); }
-inline double expansionY(Matrix const &m) { return hypot(m[2], m[3]); }
-
-bool transform_equalp(Matrix const &m0, Matrix const &m1, NR::Coord const epsilon);
-bool translate_equalp(Matrix const &m0, Matrix const &m1, NR::Coord const epsilon);
-bool matrix_equalp(Matrix const &m0, Matrix const &m1, NR::Coord const epsilon);
-
-Matrix transform(Matrix const &m);
-translate get_translation(Matrix const &m);
-
-void matrix_print(const gchar *say, Matrix const &m);
-
-} // namespace NR
-
-#endif /* !SEEN_NR_MATRIX_FNS_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/libnr/nr-matrix-ops.h b/src/libnr/nr-matrix-ops.h
deleted file mode 100644
index 2c9c93124..000000000
--- a/src/libnr/nr-matrix-ops.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/* operator functions for NR::Matrix. */
-#ifndef SEEN_NR_MATRIX_OPS_H
-#define SEEN_NR_MATRIX_OPS_H
-
-#include <libnr/nr-matrix.h>
-
-namespace NR {
-
-inline bool operator==(Matrix const &a, Matrix const &b)
-{
- for(unsigned i = 0; i < 6; ++i) {
- if ( a[i] != b[i] ) {
- return false;
- }
- }
- return true;
-}
-
-inline bool operator!=(Matrix const &a, Matrix const &b)
-{
- return !( a == b );
-}
-
-Matrix operator*(Matrix const &a, Matrix const &b);
-
-inline Matrix &operator*=(Matrix &a, Matrix const &b) { a = a * b; return a; }
-
-} /* namespace NR */
-
-#endif /* !SEEN_NR_MATRIX_OPS_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/libnr/nr-matrix-rotate-ops.cpp b/src/libnr/nr-matrix-rotate-ops.cpp
deleted file mode 100644
index d16809318..000000000
--- a/src/libnr/nr-matrix-rotate-ops.cpp
+++ /dev/null
@@ -1,18 +0,0 @@
-#include "libnr/nr-matrix-ops.h"
-
-NR::Matrix operator*(NR::Matrix const &m, NR::rotate const &r)
-{
- return m * NR::Matrix(r);
-}
-
-
-/*
- 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/libnr/nr-matrix-rotate-ops.h b/src/libnr/nr-matrix-rotate-ops.h
deleted file mode 100644
index a3cc4c806..000000000
--- a/src/libnr/nr-matrix-rotate-ops.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef SEEN_LIBNR_NR_MATRIX_ROTATE_OPS_H
-#define SEEN_LIBNR_NR_MATRIX_ROTATE_OPS_H
-
-#include "libnr/nr-forward.h"
-
-NR::Matrix operator*(NR::Matrix const &m, NR::rotate const &r);
-
-
-#endif /* !SEEN_LIBNR_NR_MATRIX_ROTATE_OPS_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/libnr/nr-matrix-scale-ops.h b/src/libnr/nr-matrix-scale-ops.h
deleted file mode 100644
index d030bb66c..000000000
--- a/src/libnr/nr-matrix-scale-ops.h
+++ /dev/null
@@ -1,31 +0,0 @@
-#ifndef SEEN_LIBNR_NR_MATRIX_SCALE_OPS_H
-#define SEEN_LIBNR_NR_MATRIX_SCALE_OPS_H
-/** \file
- * Declarations (and definition if inline) of operator blah (NR::Matrix, NR::scale).
- */
-
-#include "libnr/nr-forward.h"
-
-namespace NR {
-
-inline Matrix &operator/=(Matrix &m, scale const &s) {
- m[0] /= s[X]; m[1] /= s[Y];
- m[2] /= s[X]; m[3] /= s[Y];
- m[4] /= s[X]; m[5] /= s[Y];
- return m;
-}
-
-inline Matrix &operator*=(Matrix &m, scale const &s) {
- m[0] *= s[X]; m[1] *= s[Y];
- m[2] *= s[X]; m[3] *= s[Y];
- m[4] *= s[X]; m[5] *= s[Y];
- return m;
-}
-
-inline Matrix operator/(Matrix const &m, scale const &s) { Matrix ret(m); ret /= s; return ret; }
-
-inline Matrix operator*(Matrix const &m, scale const &s) { Matrix ret(m); ret *= s; return ret; }
-
-}
-
-#endif /* !SEEN_LIBNR_NR_MATRIX_SCALE_OPS_H */
diff --git a/src/libnr/nr-matrix-test.h b/src/libnr/nr-matrix-test.h
deleted file mode 100644
index 6477523fc..000000000
--- a/src/libnr/nr-matrix-test.h
+++ /dev/null
@@ -1,191 +0,0 @@
-#include <cxxtest/TestSuite.h>
-
-#include <libnr/nr-matrix.h>
-#include <libnr/nr-matrix-fns.h>
-#include <libnr/nr-matrix-ops.h>
-#include <libnr/nr-matrix-rotate-ops.h>
-#include <libnr/nr-matrix-scale-ops.h>
-#include <libnr/nr-point-matrix-ops.h>
-#include <libnr/nr-rotate.h>
-#include <libnr/nr-rotate-ops.h>
-#include <libnr/nr-scale-ops.h>
-#include <libnr/nr-scale-translate-ops.h>
-#include <libnr/nr-translate.h>
-#include <libnr/nr-translate-ops.h>
-#include <libnr/nr-translate-scale-ops.h>
-
-inline bool point_equalp(NR::Point const &a, NR::Point const &b)
-{
- return ( NR_DF_TEST_CLOSE(a[NR::X], b[NR::X], 1e-5) &&
- NR_DF_TEST_CLOSE(a[NR::Y], b[NR::Y], 1e-5) );
-}
-
-class NrMatrixTest : public CxxTest::TestSuite
-{
-public:
-
- NrMatrixTest() :
- m_id( NR::identity() ),
- r_id( NR::Point(1, 0) ),
- t_id( 0, 0 ),
- c16( 1.0, 2.0,
- 3.0, 4.0,
- 5.0, 6.0),
- r86( NR::Point(.8, .6) ),
- mr86( r86 ),
- t23( 2.0, 3.0 ),
- s_id( 1.0, 1.0 )
- {
- }
- virtual ~NrMatrixTest() {}
-
-// createSuite and destroySuite get us per-suite setup and teardown
-// without us having to worry about static initialization order, etc.
- static NrMatrixTest *createSuite() { return new NrMatrixTest(); }
- static void destroySuite( NrMatrixTest *suite ) { delete suite; }
-
- NR::Matrix const m_id;
- NR::rotate const r_id;
- NR::translate const t_id;
- NR::Matrix const c16;
- NR::rotate const r86;
- NR::Matrix const mr86;
- NR::translate const t23;
- NR::scale const s_id;
-
-
-
-
- void testCtorsAssignmentOp(void)
- {
- NR::Matrix const c16_copy(c16);
- NR::Matrix c16_eq(m_id);
- c16_eq = c16;
- for(unsigned i = 0; i < 6; ++i) {
- TS_ASSERT_EQUALS( c16[i], 1.0 + i );
- TS_ASSERT_EQUALS( c16[i], c16_copy[i] );
- TS_ASSERT_EQUALS( c16[i], c16_eq[i] );
- TS_ASSERT_EQUALS( m_id[i], double( i == 0 || i == 3 ) );
- }
- }
-
- void testScaleCtor(void)
- {
- NR::scale const s(2.0, 3.0);
- NR::Matrix const ms(s);
- NR::Point const p(5.0, 7.0);
- TS_ASSERT_EQUALS( p * s, NR::Point(10.0, 21.0) );
- TS_ASSERT_EQUALS( p * ms, NR::Point(10.0, 21.0) );
- }
-
- void testRotateCtor(void)
- {
- NR::Point const p0(1.0, 0.0);
- NR::Point const p90(0.0, 1.0);
- TS_ASSERT_EQUALS( p0 * r86, NR::Point(.8, .6) );
- TS_ASSERT_EQUALS( p0 * mr86, NR::Point(.8, .6) );
- TS_ASSERT_EQUALS( p90 * r86, NR::Point(-.6, .8) );
- TS_ASSERT_EQUALS( p90 * mr86, NR::Point(-.6, .8) );
- TS_ASSERT( matrix_equalp(NR::Matrix( r86 * r86 ),
- mr86 * mr86,
- 1e-14) );
- }
-
- void testTranslateCtor(void)
- {
- NR::Matrix const mt23(t23);
- NR::Point const b(-2.0, 3.0);
- TS_ASSERT_EQUALS( b * t23, b * mt23 );
- }
-
- void testIdentity(void)
- {
- TS_ASSERT( m_id.test_identity() );
- TS_ASSERT( NR::Matrix(t_id).test_identity() );
- TS_ASSERT( !(NR::Matrix(NR::translate(-2, 3)).test_identity()) );
- TS_ASSERT( NR::Matrix(r_id).test_identity() );
- NR::rotate const rot180(NR::Point(-1, 0));
- TS_ASSERT( !(NR::Matrix(rot180).test_identity()) );
- TS_ASSERT( NR::Matrix(s_id).test_identity() );
- TS_ASSERT( !(NR::Matrix(NR::scale(1.0, 0.0)).test_identity()) );
- TS_ASSERT( !(NR::Matrix(NR::scale(0.0, 1.0)).test_identity()) );
- TS_ASSERT( !(NR::Matrix(NR::scale(1.0, -1.0)).test_identity()) );
- TS_ASSERT( !(NR::Matrix(NR::scale(-1.0, -1.0)).test_identity()) );
- }
-
- void testInverse(void)
- {
- TS_ASSERT_EQUALS( m_id.inverse(), m_id );
- TS_ASSERT_EQUALS( NR::Matrix(t23).inverse(), NR::Matrix(NR::translate(-2.0, -3.0)) );
- NR::scale const s2(-4.0, 2.0);
- NR::scale const sp5(-.25, .5);
- TS_ASSERT_EQUALS( NR::Matrix(s2).inverse(), NR::Matrix(sp5) );
- TS_ASSERT_EQUALS( NR::Matrix(sp5).inverse(), NR::Matrix(s2) );
- }
-
- void testEllipticQuadraticForm(void)
- {
- NR::Matrix const aff(1.0, 1.0,
- 0.0, 1.0,
- 5.0, 6.0);
- NR::Matrix const invaff = aff.inverse();
- TS_ASSERT_EQUALS( invaff[1], -1.0 );
-
- NR::Matrix const ef(elliptic_quadratic_form(invaff));
- NR::Matrix const exp_ef(2, -1,
- -1, 1,
- 0, 0);
- TS_ASSERT_EQUALS( ef, exp_ef );
- }
-
- void testMatrixStarRotate(void)
- {
- NR::Matrix const ma(2.0, -1.0,
- 4.0, 4.0,
- -0.5, 2.0);
- NR::Matrix const a_r86( ma * r86 );
- NR::Matrix const ma1( a_r86 * r86.inverse() );
- TS_ASSERT( matrix_equalp(ma1, ma, 1e-12) );
- NR::Matrix const exp_a_r86( 2*.8 + -1*-.6, 2*.6 + -1*.8,
- 4*.8 + 4*-.6, 4*.6 + 4*.8,
- -.5*.8 + 2*-.6, -.5*.6 + 2*.8 );
- TS_ASSERT( matrix_equalp(a_r86, exp_a_r86, 1e-12) );
- }
-
- void testTranslateStarScale_ScaleStarTranslate(void)
- {
- NR::translate const t2n4(2, -4);
- NR::scale const sn2_8(-2, 8);
- NR::Matrix const exp_ts(-2, 0,
- 0, 8,
- -4, -32);
- NR::Matrix const exp_st(-2, 0,
- 0, 8,
- 2, -4);
- TS_ASSERT_EQUALS( exp_ts, t2n4 * sn2_8 );
- TS_ASSERT_EQUALS( exp_st, sn2_8 * t2n4 );
- }
-
- void testMatrixStarScale(void)
- {
- NR::Matrix const ma(2.0, -1.0,
- 4.0, 4.0,
- -0.5, 2.0);
- NR::scale const sn2_8(-2, 8);
- NR::Matrix const exp_as(-4, -8,
- -8, 32,
- 1, 16);
- TS_ASSERT_EQUALS( ma * sn2_8, exp_as );
- }
-};
-
-/*
- 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/libnr/nr-matrix-translate-ops.h b/src/libnr/nr-matrix-translate-ops.h
deleted file mode 100644
index 3d944651f..000000000
--- a/src/libnr/nr-matrix-translate-ops.h
+++ /dev/null
@@ -1,37 +0,0 @@
-#ifndef SEEN_LIBNR_NR_MATRIX_TRANSLATE_OPS_H
-#define SEEN_LIBNR_NR_MATRIX_TRANSLATE_OPS_H
-
-/** \file
- * Declarations (and definition if inline) of operator
- * blah (NR::Matrix, NR::translate).
- */
-
-#include "libnr/nr-matrix.h"
-#include "libnr/nr-translate.h"
-
-namespace NR {
-
-inline Matrix &operator*=(Matrix &m, translate const &t) {
- m[4] += t[X];
- m[5] += t[Y];
- return m;
-}
-
-inline Matrix operator*(Matrix const &m, translate const &t) { Matrix ret(m); ret *= t; return ret; }
-
-inline Matrix operator/(Matrix const &numer, translate const &denom) { return numer * translate(-denom.offset); }
-
-}
-
-#endif /* !SEEN_LIBNR_NR_MATRIX_TRANSLATE_OPS_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/libnr/nr-matrix.cpp b/src/libnr/nr-matrix.cpp
deleted file mode 100644
index 4f94dd3df..000000000
--- a/src/libnr/nr-matrix.cpp
+++ /dev/null
@@ -1,291 +0,0 @@
-#define __NR_MATRIX_C__
-
-/** \file
- * Various matrix routines. Currently includes some NR::rotate etc. routines too.
- */
-
-/*
- * Authors:
- * Lauris Kaplinski <lauris@kaplinski.com>
- *
- * This code is in public domain
- */
-
-#include <cstdlib>
-#include "nr-matrix.h"
-#include "nr-matrix-fns.h"
-
-
-
-/**
- * Implement NR functions and methods
- */
-namespace NR {
-
-
-
-
-
-/**
- * Multiply two matrices together
- */
-Matrix operator*(Matrix const &m0, Matrix const &m1)
-{
- NR::Coord const d0 = m0[0] * m1[0] + m0[1] * m1[2];
- NR::Coord const d1 = m0[0] * m1[1] + m0[1] * m1[3];
- NR::Coord const d2 = m0[2] * m1[0] + m0[3] * m1[2];
- NR::Coord const d3 = m0[2] * m1[1] + m0[3] * m1[3];
- NR::Coord const d4 = m0[4] * m1[0] + m0[5] * m1[2] + m1[4];
- NR::Coord const d5 = m0[4] * m1[1] + m0[5] * m1[3] + m1[5];
-
- Matrix ret( d0, d1, d2, d3, d4, d5 );
-
- return ret;
-}
-
-
-
-
-
-/**
- * Return the inverse of this matrix. If an inverse is not defined,
- * then return the identity matrix.
- */
-Matrix Matrix::inverse() const
-{
- Matrix d(0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
-
- NR::Coord const det = _c[0] * _c[3] - _c[1] * _c[2];
- if (!NR_DF_TEST_CLOSE(det, 0.0, NR_EPSILON)) {
-
- NR::Coord const idet = 1.0 / det;
- NR::Coord *dest = d._c;
-
- /*0*/ *dest++ = _c[3] * idet;
- /*1*/ *dest++ = -_c[1] * idet;
- /*2*/ *dest++ = -_c[2] * idet;
- /*3*/ *dest++ = _c[0] * idet;
- /*4*/ *dest++ = -_c[4] * d._c[0] - _c[5] * d._c[2];
- /*5*/ *dest = -_c[4] * d._c[1] - _c[5] * d._c[3];
-
- } else {
- d.set_identity();
- }
-
- return d;
-}
-
-
-
-
-
-/**
- * Set this matrix to Identity
- */
-void Matrix::set_identity()
-{
- NR::Coord *dest = _c;
-
- *dest++ = 1.0; //0
- *dest++ = 0.0; //1
- *dest++ = 0.0; //2
- *dest++ = 1.0; //3
- // translation
- *dest++ = 0.0; //4
- *dest = 0.0; //5
-}
-
-
-
-
-
-/**
- * return an Identity matrix
- */
-Matrix identity()
-{
- Matrix ret(1.0, 0.0,
- 0.0, 1.0,
- 0.0, 0.0);
- return ret;
-}
-
-
-
-
-
-/**
- *
- */
-Matrix from_basis(Point const x_basis, Point const y_basis, Point const offset)
-{
- Matrix const ret(x_basis[X], y_basis[X],
- x_basis[Y], y_basis[Y],
- offset[X], offset[Y]);
- return ret;
-}
-
-
-
-
-/**
- * Returns a rotation matrix corresponding by the specified angle (in radians) about the origin.
- *
- * \see NR::rotate_degrees
- *
- * Angle direction in Inkscape code: If you use the traditional mathematics convention that y
- * increases upwards, then positive angles are anticlockwise as per the mathematics convention. If
- * you take the common non-mathematical convention that y increases downwards, then positive angles
- * are clockwise, as is common outside of mathematics.
- */
-rotate::rotate(NR::Coord const theta) :
- vec(cos(theta),
- sin(theta))
-{
-}
-
-
-
-
-
-/**
- * Return the determinant of the Matrix
- */
-NR::Coord Matrix::det() const
-{
- return _c[0] * _c[3] - _c[1] * _c[2];
-}
-
-
-
-
-
-/**
- * Return the scalar of the descriminant of the Matrix
- */
-NR::Coord Matrix::descrim2() const
-{
- return fabs(det());
-}
-
-
-
-
-
-/**
- * Return the descriminant of the Matrix
- */
-NR::Coord Matrix::descrim() const
-{
- return sqrt(descrim2());
-}
-
-
-
-
-
-/**
- *
- */
-bool Matrix::is_translation(Coord const eps) const {
- return ( fabs(_c[0] - 1.0) < eps &&
- fabs(_c[3] - 1.0) < eps &&
- fabs(_c[1]) < eps &&
- fabs(_c[2]) < eps );
-}
-
-
-/**
- *
- */
-bool Matrix::is_scale(Coord const eps) const {
- return ( (fabs(_c[0] - 1.0) > eps || fabs(_c[3] - 1.0) > eps) &&
- fabs(_c[1]) < eps &&
- fabs(_c[2]) < eps );
-}
-
-
-/**
- *
- */
-bool Matrix::is_rotation(Coord const eps) const {
- return ( fabs(_c[1]) > eps &&
- fabs(_c[2]) > eps &&
- fabs(_c[1] + _c[2]) < 2 * eps);
-}
-
-
-
-
-
-/**
- * test whether the matrix is the identity matrix (true). (2geom's Matrix::isIdentity() does the same)
- */
-bool Matrix::test_identity() const {
- return matrix_equalp(*this, NR_MATRIX_IDENTITY, NR_EPSILON);
-}
-
-
-
-
-
-/**
- * calculates the descriminant of the matrix. (Geom::Coord Matrix::descrim() does the same)
- */
-double expansion(Matrix const &m) {
- return sqrt(fabs(m.det()));
-}
-
-
-
-
-
-/**
- *
- */
-bool transform_equalp(Matrix const &m0, Matrix const &m1, NR::Coord const epsilon) {
- return
- NR_DF_TEST_CLOSE(m0[0], m1[0], epsilon) &&
- NR_DF_TEST_CLOSE(m0[1], m1[1], epsilon) &&
- NR_DF_TEST_CLOSE(m0[2], m1[2], epsilon) &&
- NR_DF_TEST_CLOSE(m0[3], m1[3], epsilon);
-}
-
-
-
-
-
-/**
- *
- */
-bool translate_equalp(Matrix const &m0, Matrix const &m1, NR::Coord const epsilon) {
- return NR_DF_TEST_CLOSE(m0[4], m1[4], epsilon) && NR_DF_TEST_CLOSE(m0[5], m1[5], epsilon);
-}
-
-
-
-
-
-/**
- *
- */
-bool matrix_equalp(Matrix const &m0, Matrix const &m1, NR::Coord const epsilon) {
- return transform_equalp(m0, m1, epsilon) && translate_equalp(m0, m1, epsilon);
-}
-
-
-
-} //namespace NR
-
-
-
-/*
- 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/libnr/nr-matrix.h b/src/libnr/nr-matrix.h
deleted file mode 100644
index 5d62dfafe..000000000
--- a/src/libnr/nr-matrix.h
+++ /dev/null
@@ -1,313 +0,0 @@
-#ifndef __NR_MATRIX_H__
-#define __NR_MATRIX_H__
-
-/** \file
- * Definition of NR::Matrix type.
- *
- * \note Operator functions (e.g. Matrix * Matrix etc.) are mostly in
- * libnr/nr-matrix-ops.h. See end of file for discussion.
- *
- * Main authors:
- * Lauris Kaplinski <lauris@kaplinski.com>:
- * Original NRMatrix definition and related macros.
- *
- * Nathan Hurst <njh@mail.csse.monash.edu.au>:
- * NR::Matrix class version of the above.
- *
- * This code is in public domain.
- */
-
-#include <glib.h> // g_assert()
-#include <glib/gmessages.h>
-
-#include "libnr/nr-coord.h"
-#include "libnr/nr-values.h"
-#include <libnr/nr-rotate.h>
-#include <libnr/nr-scale.h>
-#include <libnr/nr-translate.h>
-#include <2geom/affine.h>
-
-namespace NR {
-
-/**
- * The Matrix class.
- *
- * For purposes of multiplication, points should be thought of as row vectors
- *
- * p = ( p[X] p[Y] 1 )
- *
- * to be right-multiplied by transformation matrices
- * \verbatim
- c[] = | c[0] c[1] 0 |
- | c[2] c[3] 0 |
- | c[4] c[5] 1 | \endverbatim
- *
- * (so the columns of the matrix correspond to the columns (elements) of the result,
- * and the rows of the matrix correspond to columns (elements) of the "input").
- */
-class Matrix {
-
-
- public:
-
- /**
- * Various forms of constructor
- */
-
- /**
- *
- */
- explicit Matrix() { }
-
-
- /**
- *
- */
- Matrix(Matrix const &m) {
-
- NR::Coord const *src = m._c;
- NR::Coord *dest = _c;
-
- *dest++ = *src++; //0
- *dest++ = *src++; //1
- *dest++ = *src++; //2
- *dest++ = *src++; //3
- *dest++ = *src++; //4
- *dest = *src ; //5
-
- }
-
-
- Matrix(Geom::Affine const &m) {
- NR::Coord *dest = _c;
-
- *dest++ = m[0];
- *dest++ = m[1];
- *dest++ = m[2];
- *dest++ = m[3];
- *dest++ = m[4];
- *dest = m[5];
- }
-
- /**
- *
- */
- Matrix(double c0, double c1,
- double c2, double c3,
- double c4, double c5) {
-
- NR::Coord *dest = _c;
-
- *dest++ = c0; //0
- *dest++ = c1; //1
- *dest++ = c2; //2
- *dest++ = c3; //3
- *dest++ = c4; //4
- *dest = c5; //5
-
- }
-
-
-
- /**
- *
- */
- Matrix &operator=(Matrix const &m) {
-
- NR::Coord const *src = m._c;
- NR::Coord *dest = _c;
-
- *dest++ = *src++; //0
- *dest++ = *src++; //1
- *dest++ = *src++; //2
- *dest++ = *src++; //3
- *dest++ = *src++; //4
- *dest = *src ; //5
-
- return *this;
- }
-
-
-
-
- /**
- *
- */
- explicit Matrix(scale const &sm) {
-
- NR::Coord *dest = _c;
-
- *dest++ = sm[X]; //0
- *dest++ = 0.0; //1
- *dest++ = 0.0; //2
- *dest++ = sm[Y]; //3
- *dest++ = 0.0; //4
- *dest = 0.0; //5
-
- }
-
-
-
-
-
-
- /**
- *
- */
- explicit Matrix(rotate const &r) {
-
- NR::Coord *dest = _c;
-
- *dest++ = r.vec[X]; //0
- *dest++ = r.vec[Y]; //1
- *dest++ = -r.vec[Y]; //2
- *dest++ = r.vec[X]; //3
- *dest++ = 0.0; //4
- *dest = 0.0; //5
-
- }
-
-
-
-
- /**
- *
- */
- explicit Matrix(translate const &tm) {
-
- NR::Coord *dest = _c;
-
- *dest++ = 1.0; //0
- *dest++ = 0.0; //1
- *dest++ = 0.0; //2
- *dest++ = 1.0; //3
- *dest++ = tm[X]; //4
- *dest = tm[Y]; //5
- }
-
-
- /**
- *
- */
- bool test_identity() const;
-
-
- /**
- *
- */
- bool is_translation(Coord const eps = 1e-6) const;
-
- /**
- *
- */
- bool is_scale(Coord const eps = 1e-6) const;
-
- /**
- *
- */
- bool is_rotation(Coord const eps = 1e-6) const;
-
-
- /**
- *
- */
- Matrix inverse() const;
-
-
-
- /**
- *
- */
- inline Coord &operator[](int const i) {
- return _c[i];
- }
-
-
-
- /**
- *
- */
- inline Coord operator[](int const i) const {
- return _c[i];
- }
-
- inline operator Geom::Affine() const {
- return Geom::Affine(_c[0], _c[1], _c[2], _c[3], _c[4], _c[5]);
- }
-
- /**
- *
- */
- void set_identity();
-
- /**
- *
- */
- Coord det() const;
-
-
- /**
- *
- */
- Coord descrim2() const;
-
-
- /**
- *
- */
- Coord descrim() const;
-
-
- private:
-
-
- NR::Coord _c[6];
-};
-
-/** A function to print out the Matrix (for debugging) */
-inline std::ostream &operator<< (std::ostream &out_file, const NR::Matrix &m) {
- out_file << "A: " << m[0] << " C: " << m[2] << " E: " << m[4] << "\n";
- out_file << "B: " << m[1] << " D: " << m[3] << " F: " << m[5] << "\n";
- return out_file;
-}
-
-} /* namespace NR */
-
-
-
-
-
-
-
-/** \note
- * Discussion of splitting up nr-matrix.h into lots of little files:
- *
- * Advantages:
- *
- * - Reducing amount of recompilation necessary when anything changes.
- *
- * - Hopefully also reducing compilation time by reducing the number of inline
- * function definitions encountered by the compiler for a given .o file.
- * (No timing comparisons done yet. On systems without much memory available
- * for caching, this may be outweighed by additional I/O costs.)
- *
- * Disadvantages:
- *
- * - More #include lines necessary per file. If a compile fails due to
- * not having all the necessary #include lines, then the developer needs
- * to spend some time working out what #include to add.
- */
-
-#endif /* !__NR_MATRIX_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/libnr/nr-maybe.h b/src/libnr/nr-maybe.h
deleted file mode 100644
index 1413f69d2..000000000
--- a/src/libnr/nr-maybe.h
+++ /dev/null
@@ -1,201 +0,0 @@
-#ifndef __NR_MAYBE_H__
-#define __NR_MAYBE_H__
-
-/*
- * Nullable values for C++
- *
- * Copyright 2004, 2007 MenTaLguY <mental@rydia.net>
- *
- * This code is licensed under the GNU GPL; see COPYING for more information.
- */
-
-#if HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <stdexcept>
-#include <string>
-#include <algorithm>
-
-namespace NR {
-
-class IsNothing : public std::domain_error {
-public:
- IsNothing() : domain_error(std::string("Is nothing")) {}
-};
-
-struct Nothing {};
-
-template <typename T>
-class MaybeStorage {
-public:
- MaybeStorage() : _is_nothing(true) {}
- MaybeStorage(T const &value)
- : _value(value), _is_nothing(false) {}
-
- bool is_nothing() const { return _is_nothing; }
- T &value() { return _value; }
- T const &value() const { return _value; }
-
-private:
- T _value;
- bool _is_nothing;
-};
-
-template <typename T>
-class Maybe {
-public:
- Maybe() {}
- Maybe(Nothing) {}
- Maybe(T const &t) : _storage(t) {}
- Maybe(Maybe const &m) : _storage(m._storage) {}
-
- template <typename T2>
- Maybe(Maybe<T2> const &m) {
- if (m) {
- _storage = *m;
- }
- }
-
- template <typename T2>
- Maybe(Maybe<T2 const &> m) {
- if (m) {
- _storage = *m;
- }
- }
-
- operator bool() const { return !_storage.is_nothing(); }
-
- T const &operator*() const throw(IsNothing) {
- if (_storage.is_nothing()) {
- throw IsNothing();
- } else {
- return _storage.value();
- }
- }
- T &operator*() throw(IsNothing) {
- if (_storage.is_nothing()) {
- throw IsNothing();
- } else {
- return _storage.value();
- }
- }
-
- T const *operator->() const throw(IsNothing) {
- if (_storage.is_nothing()) {
- throw IsNothing();
- } else {
- return &_storage.value();
- }
- }
- T *operator->() throw(IsNothing) {
- if (_storage.is_nothing()) {
- throw IsNothing();
- } else {
- return &_storage.value();
- }
- }
-
- template <typename T2>
- bool operator==(Maybe<T2> const &other) const {
- bool is_nothing = _storage.is_nothing();
- if ( is_nothing || !other ) {
- return is_nothing && !other;
- } else {
- return _storage.value() == *other;
- }
- }
- template <typename T2>
- bool operator!=(Maybe<T2> const &other) const {
- bool is_nothing = _storage.is_nothing();
- if ( is_nothing || !other ) {
- return !is_nothing || other;
- } else {
- return _storage.value() != *other;
- }
- }
-
-private:
- MaybeStorage<T> _storage;
-};
-
-template <typename T>
-class Maybe<T &> {
-public:
- Maybe() : _ref(NULL) {}
- Maybe(Nothing) : _ref(NULL) {}
- Maybe(T &t) : _ref(&t) {}
-
- template <typename T2>
- Maybe(Maybe<T2> const &m) {
- if (m) {
- _ref = &*m;
- }
- }
-
- template <typename T2>
- Maybe(Maybe<T2 &> m) {
- if (m) {
- _ref = *m;
- }
- }
-
- template <typename T2>
- Maybe(Maybe<T2 const &> m) {
- if (m) {
- _ref = *m;
- }
- }
-
- operator bool() const { return _ref; }
-
- T &operator*() const throw(IsNothing) {
- if (!_ref) {
- throw IsNothing();
- } else {
- return *_ref;
- }
- }
- T *operator->() const throw(IsNothing) {
- if (!_ref) {
- throw IsNothing();
- } else {
- return _ref;
- }
- }
-
- template <typename T2>
- bool operator==(Maybe<T2> const &other) const {
- if ( !_ref || !other ) {
- return !_ref && !other;
- } else {
- return *_ref == *other;
- }
- }
- template <typename T2>
- bool operator!=(Maybe <T2> const &other) const {
- if ( !_ref || !other ) {
- return _ref || other;
- } else {
- return *_ref != *other;
- }
- }
-
-private:
- T *_ref;
-};
-
-} /* namespace NR */
-
-#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:textwidth=99 :
diff --git a/src/libnr/nr-path-code.h b/src/libnr/nr-path-code.h
deleted file mode 100644
index cc174d73b..000000000
--- a/src/libnr/nr-path-code.h
+++ /dev/null
@@ -1,28 +0,0 @@
-#ifndef SEEN_LIBNR_NR_PATH_CODE_H
-#define SEEN_LIBNR_NR_PATH_CODE_H
-
-/** \file
- * NRPathcode enum definition
- */
-
-typedef enum {
- NR_MOVETO, ///< Start of closed subpath
- NR_MOVETO_OPEN, ///< Start of open subpath
- NR_CURVETO, ///< Bezier curve segment
- NR_LINETO, ///< Line segment
- NR_END ///< End record
-} NRPathcode;
-
-
-#endif /* !SEEN_LIBNR_NR_PATH_CODE_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/libnr/nr-pixblock-line.cpp b/src/libnr/nr-pixblock-line.cpp
deleted file mode 100644
index eb8b404b4..000000000
--- a/src/libnr/nr-pixblock-line.cpp
+++ /dev/null
@@ -1,92 +0,0 @@
-#define __NR_PIXBLOCK_LINE_C__
-
-/*
- * Pixel buffer rendering library
- *
- * Authors:
- * Lauris Kaplinski <lauris@kaplinski.com>
- *
- * This code is in public domain
- */
-
-#include <libnr/nr-pixops.h>
-#include <libnr/nr-pixblock-pixel.h>
-
-void
-nr_pixblock_draw_line_rgba32 (NRPixBlock *d, long x0, long y0, long x1, long y1, short /*first*/, unsigned long rgba)
-{
- long deltax, deltay, xinc1, xinc2, yinc1, yinc2;
- long den, num, numadd, numpixels;
- long x, y, curpixel;
- /* Pixblock */
- int dbpp;
- NRPixBlock spb;
- unsigned char *spx;
-
- if (x1 >= x0) {
- deltax = x1 - x0;
- xinc1 = 1;
- xinc2 = 1;
- } else {
- deltax = x0 - x1;
- xinc1 = -1;
- xinc2 = -1;
- }
-
- if (y1 >= y0) {
- deltay = y1 - y0;
- yinc1 = 1;
- yinc2 = 1;
- } else {
- deltay = y0 - y1;
- yinc1 = -1;
- yinc2 = -1;
- }
-
- if (deltax >= deltay) {
- xinc1 = 0;
- yinc2 = 0;
- den = deltax;
- num = deltax / 2;
- numadd = deltay;
- numpixels = deltax;
- } else {
- xinc2 = 0;
- yinc1 = 0;
- den = deltay;
- num = deltay / 2;
- numadd = deltax;
- numpixels = deltay;
- }
-
- /* We can be quite sure 1x1 pixblock is TINY */
- nr_pixblock_setup_fast (&spb, NR_PIXBLOCK_MODE_R8G8B8A8N, 0, 0, 1, 1, 0);
- spb.empty = 0;
- spx = NR_PIXBLOCK_PX (&spb);
- spx[0] = NR_RGBA32_R (rgba);
- spx[1] = NR_RGBA32_G (rgba);
- spx[2] = NR_RGBA32_B (rgba);
- spx[3] = NR_RGBA32_A (rgba);
-
- dbpp = NR_PIXBLOCK_BPP (d);
-
- x = x0;
- y = y0;
-
- for (curpixel = 0; curpixel <= numpixels; curpixel++) {
- if ((x >= d->area.x0) && (y >= d->area.y0) && (x < d->area.x1) && (y < d->area.y1)) {
- nr_compose_pixblock_pixblock_pixel (d, NR_PIXBLOCK_PX (d) + (y - d->area.y0) * d->rs + (x - d->area.x0) * dbpp, &spb, spx);
- }
- num += numadd;
- if (num >= den) {
- num -= den;
- x += xinc1;
- y += yinc1;
- }
- x += xinc2;
- y += yinc2;
- }
-
- nr_pixblock_release (&spb);
-}
-
diff --git a/src/libnr/nr-pixblock-line.h b/src/libnr/nr-pixblock-line.h
deleted file mode 100644
index cebab31d8..000000000
--- a/src/libnr/nr-pixblock-line.h
+++ /dev/null
@@ -1,28 +0,0 @@
-#ifndef __NR_PIXBLOCK_LINE_H__
-#define __NR_PIXBLOCK_LINE_H__
-
-/*
- * Pixel buffer rendering library
- *
- * Authors:
- * Lauris Kaplinski <lauris@kaplinski.com>
- *
- * This code is in public domain
- */
-
-#include <libnr/nr-pixblock.h>
-
-void nr_pixblock_draw_line_rgba32 (NRPixBlock *d, long x0, long y0, long x1, long y1, short first, unsigned long rgba);
-
-#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:textwidth=99 :
diff --git a/src/libnr/nr-pixblock-pattern.cpp b/src/libnr/nr-pixblock-pattern.cpp
deleted file mode 100644
index aa3246297..000000000
--- a/src/libnr/nr-pixblock-pattern.cpp
+++ /dev/null
@@ -1,127 +0,0 @@
-#define __NR_PIXBLOCK_PATTERN_C__
-
-/*
- * Pixel buffer rendering library
- *
- * Authors:
- * Lauris Kaplinski <lauris@kaplinski.com>
- *
- * This code is in public domain
- */
-
-
-#include <glib/gmem.h>
-#include "nr-pixops.h"
-#include "nr-pixblock-pattern.h"
-
-#define NR_NOISE_SIZE 1024
-
-void
-nr_pixblock_render_gray_noise (NRPixBlock *pb, NRPixBlock *mask)
-{
- static unsigned char *noise = NULL;
- static unsigned int seed = 0;
- unsigned int v;
- NRRectL clip;
- int x, y, bpp;
-
- if (mask) {
- if (mask->empty) return;
- nr_rect_l_intersect (&clip, &pb->area, &mask->area);
- if (nr_rect_l_test_empty(clip)) return;
- } else {
- clip = pb->area;
- }
-
- if (!noise) {
- int i;
- noise = g_new (unsigned char, NR_NOISE_SIZE);
- for (i = 0; i < NR_NOISE_SIZE; i++) noise[i] = (rand () / (RAND_MAX >> 8)) & 0xff;
- }
-
- bpp = NR_PIXBLOCK_BPP (pb);
-
- v = (rand () / (RAND_MAX >> 8)) & 0xff;
-
- if (mask) {
- for (y = clip.y0; y < clip.y1; y++) {
- unsigned char *d, *m;
- d = NR_PIXBLOCK_PX (pb) + (y - pb->area.y0) * pb->rs + (clip.x0 - pb->area.x0) * bpp;
- m = NR_PIXBLOCK_PX (mask) + (y - mask->area.y0) * pb->rs + (clip.x0 - mask->area.x0);
- for (x = clip.x0; x < clip.x1; x++) {
- v = v ^ noise[seed];
- switch (pb->mode) {
- case NR_PIXBLOCK_MODE_A8:
- d[0] = NR_COMPOSEA_111(m[0], d[0]);
- break;
- case NR_PIXBLOCK_MODE_R8G8B8:
- d[0] = NR_COMPOSEN11_1111 (v, m[0], d[0]);
- d[1] = NR_COMPOSEN11_1111 (v, m[0], d[1]);
- d[2] = NR_COMPOSEN11_1111 (v, m[0], d[2]);
- break;
- case NR_PIXBLOCK_MODE_R8G8B8A8N:
- if (m[0] != 0) {
- unsigned int ca;
- ca = NR_COMPOSEA_112(m[0], d[3]);
- d[0] = NR_COMPOSENNN_111121 (v, m[0], d[0], d[3], ca);
- d[1] = NR_COMPOSENNN_111121 (v, m[0], d[1], d[3], ca);
- d[2] = NR_COMPOSENNN_111121 (v, m[0], d[2], d[3], ca);
- d[3] = NR_NORMALIZE_21(ca);
- }
- break;
- case NR_PIXBLOCK_MODE_R8G8B8A8P:
- d[0] = NR_COMPOSENPP_1111 (v, m[0], d[0]);
- d[1] = NR_COMPOSENPP_1111 (v, m[0], d[1]);
- d[2] = NR_COMPOSENPP_1111 (v, m[0], d[2]);
- d[3] = NR_COMPOSEA_111(d[3], m[0]);
- break;
- default:
- break;
- }
- d += bpp;
- m += 1;
- if (++seed >= NR_NOISE_SIZE) {
- int i;
- i = (rand () / (RAND_MAX / NR_NOISE_SIZE)) % NR_NOISE_SIZE;
- noise[i] ^= v;
- seed = i % (NR_NOISE_SIZE >> 2);
- }
- }
- }
- } else {
- for (y = clip.y0; y < clip.y1; y++) {
- unsigned char *d;
- d = NR_PIXBLOCK_PX (pb) + (y - pb->area.y0) * pb->rs + (clip.x0 - pb->area.x0) * bpp;
- for (x = clip.x0; x < clip.x1; x++) {
- v = v ^ noise[seed];
- switch (pb->mode) {
- case NR_PIXBLOCK_MODE_A8:
- d[0] = 255;
- break;
- case NR_PIXBLOCK_MODE_R8G8B8:
- d[0] = v;
- d[1] = v;
- d[2] = v;
- break;
- case NR_PIXBLOCK_MODE_R8G8B8A8N:
- case NR_PIXBLOCK_MODE_R8G8B8A8P:
- d[0] = v;
- d[1] = v;
- d[2] = v;
- d[3] = 255;
- default:
- break;
- }
- d += bpp;
- if (++seed >= NR_NOISE_SIZE) {
- int i;
- i = (rand () / (RAND_MAX / NR_NOISE_SIZE)) % NR_NOISE_SIZE;
- noise[i] ^= v;
- seed = i % (NR_NOISE_SIZE >> 2);
- }
- }
- }
- }
-
- pb->empty = 0;
-}
diff --git a/src/libnr/nr-pixblock-pattern.h b/src/libnr/nr-pixblock-pattern.h
deleted file mode 100644
index a79a39f13..000000000
--- a/src/libnr/nr-pixblock-pattern.h
+++ /dev/null
@@ -1,28 +0,0 @@
-#ifndef __NR_PIXBLOCK_PATTERN_H__
-#define __NR_PIXBLOCK_PATTERN_H__
-
-/*
- * Pixel buffer rendering library
- *
- * Authors:
- * Lauris Kaplinski <lauris@kaplinski.com>
- *
- * This code is in public domain
- */
-
-#include <libnr/nr-pixblock.h>
-
-void nr_pixblock_render_gray_noise (NRPixBlock *pb, NRPixBlock *mask);
-
-#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:textwidth=99 :
diff --git a/src/libnr/nr-pixblock-pixel.cpp b/src/libnr/nr-pixblock-pixel.cpp
deleted file mode 100644
index 109ed69dc..000000000
--- a/src/libnr/nr-pixblock-pixel.cpp
+++ /dev/null
@@ -1,230 +0,0 @@
-#define __NR_PIXBLOCK_PIXEL_C__
-
-/*
- * Pixel buffer rendering library
- *
- * Authors:
- * Lauris Kaplinski <lauris@kaplinski.com>
- *
- * This code is in public domain
- */
-
-#include "nr-pixops.h"
-#include "nr-pixblock-pixel.h"
-
-void
-nr_compose_pixblock_pixblock_pixel (NRPixBlock *dpb, unsigned char *d, const NRPixBlock *spb, const unsigned char *s)
-{
- if (spb->empty) return;
-
- if (dpb->empty) {
- /* Empty destination */
- switch (dpb->mode) {
- case NR_PIXBLOCK_MODE_A8:
- switch (spb->mode) {
- case NR_PIXBLOCK_MODE_A8:
- break;
- case NR_PIXBLOCK_MODE_R8G8B8:
- d[0] = 255;
- break;
- case NR_PIXBLOCK_MODE_R8G8B8A8N:
- d[0] = s[3];
- break;
- case NR_PIXBLOCK_MODE_R8G8B8A8P:
- d[0] = s[3];
- break;
- default:
- break;
- }
- break;
- case NR_PIXBLOCK_MODE_R8G8B8:
- switch (spb->mode) {
- case NR_PIXBLOCK_MODE_A8:
- break;
- case NR_PIXBLOCK_MODE_R8G8B8:
- d[0] = s[0];
- d[1] = s[1];
- d[2] = s[2];
- break;
- case NR_PIXBLOCK_MODE_R8G8B8A8N:
- d[0] = NR_COMPOSEN11_1111 (s[0], s[3], 255);
- d[1] = NR_COMPOSEN11_1111 (s[1], s[3], 255);
- d[2] = NR_COMPOSEN11_1111 (s[2], s[3], 255);
- break;
- case NR_PIXBLOCK_MODE_R8G8B8A8P:
- d[0] = NR_COMPOSEP11_1111 (s[0], s[3], 255);
- d[1] = NR_COMPOSEP11_1111 (s[1], s[3], 255);
- d[2] = NR_COMPOSEP11_1111 (s[2], s[3], 255);
- break;
- default:
- break;
- }
- break;
- case NR_PIXBLOCK_MODE_R8G8B8A8N:
- switch (spb->mode) {
- case NR_PIXBLOCK_MODE_A8:
- break;
- case NR_PIXBLOCK_MODE_R8G8B8:
- d[0] = s[0];
- d[1] = s[1];
- d[2] = s[2];
- d[3] = 255;
- break;
- case NR_PIXBLOCK_MODE_R8G8B8A8N:
- d[0] = s[0];
- d[1] = s[1];
- d[2] = s[2];
- d[3] = s[3];
- break;
- case NR_PIXBLOCK_MODE_R8G8B8A8P:
- if (s[3] == 0) {
- d[0] = 255;
- d[1] = 255;
- d[2] = 255;
- } else {
- d[0] = NR_DEMUL_111(s[0], s[3]);
- d[1] = NR_DEMUL_111(s[0], s[3]);
- d[2] = NR_DEMUL_111(s[0], s[3]);
- }
- d[3] = s[3];
- break;
- default:
- break;
- }
- break;
- case NR_PIXBLOCK_MODE_R8G8B8A8P:
- switch (spb->mode) {
- case NR_PIXBLOCK_MODE_A8:
- break;
- case NR_PIXBLOCK_MODE_R8G8B8:
- d[0] = s[0];
- d[1] = s[1];
- d[2] = s[2];
- d[3] = 255;
- break;
- case NR_PIXBLOCK_MODE_R8G8B8A8N:
- d[0] = NR_PREMUL_111 (s[0], s[3]);
- d[1] = NR_PREMUL_111 (s[1], s[3]);
- d[2] = NR_PREMUL_111 (s[2], s[3]);
- d[3] = s[3];
- break;
- case NR_PIXBLOCK_MODE_R8G8B8A8P:
- d[0] = s[0];
- d[1] = s[1];
- d[2] = s[2];
- d[3] = s[3];
- break;
- default:
- break;
- }
- break;
- default:
- break;
- }
- } else {
- /* Image destination */
- switch (dpb->mode) {
- case NR_PIXBLOCK_MODE_A8:
- switch (spb->mode) {
- case NR_PIXBLOCK_MODE_A8:
- break;
- case NR_PIXBLOCK_MODE_R8G8B8:
- d[0] = 255;
- break;
- case NR_PIXBLOCK_MODE_R8G8B8A8N:
- d[0] = NR_COMPOSEA_111(s[3], d[0]);
- break;
- case NR_PIXBLOCK_MODE_R8G8B8A8P:
- d[0] = NR_COMPOSEA_111(s[3], d[0]);
- break;
- default:
- break;
- }
- break;
- case NR_PIXBLOCK_MODE_R8G8B8:
- switch (spb->mode) {
- case NR_PIXBLOCK_MODE_A8:
- break;
- case NR_PIXBLOCK_MODE_R8G8B8:
- d[0] = s[0];
- d[1] = s[1];
- d[2] = s[2];
- break;
- case NR_PIXBLOCK_MODE_R8G8B8A8N:
- d[0] = NR_COMPOSEN11_1111 (s[0], s[3], d[0]);
- d[1] = NR_COMPOSEN11_1111 (s[1], s[3], d[1]);
- d[2] = NR_COMPOSEN11_1111 (s[2], s[3], d[2]);
- break;
- case NR_PIXBLOCK_MODE_R8G8B8A8P:
- d[0] = NR_COMPOSEP11_1111 (s[0], s[3], d[0]);
- d[1] = NR_COMPOSEP11_1111 (s[1], s[3], d[1]);
- d[2] = NR_COMPOSEP11_1111 (s[2], s[3], d[2]);
- break;
- default:
- break;
- }
- break;
- case NR_PIXBLOCK_MODE_R8G8B8A8N:
- switch (spb->mode) {
- case NR_PIXBLOCK_MODE_A8:
- break;
- case NR_PIXBLOCK_MODE_R8G8B8:
- d[0] = s[0];
- d[1] = s[1];
- d[2] = s[2];
- break;
- case NR_PIXBLOCK_MODE_R8G8B8A8N:
- if (s[3] != 0) {
- unsigned int ca;
- ca = NR_COMPOSEA_112(s[3], d[3]);
- d[0] = NR_COMPOSENNN_111121 (s[0], s[3], d[0], d[3], ca);
- d[1] = NR_COMPOSENNN_111121 (s[1], s[3], d[1], d[3], ca);
- d[2] = NR_COMPOSENNN_111121 (s[2], s[3], d[2], d[3], ca);
- d[3] = NR_NORMALIZE_21(ca);
- }
- break;
- case NR_PIXBLOCK_MODE_R8G8B8A8P:
- if (s[3] != 0) {
- unsigned int ca;
- ca = NR_COMPOSEA_112(s[3], d[3]);
- d[0] = NR_COMPOSEPNN_111121 (s[0], s[3], d[0], d[3], ca);
- d[1] = NR_COMPOSEPNN_111121 (s[1], s[3], d[0], d[3], ca);
- d[2] = NR_COMPOSEPNN_111121 (s[2], s[3], d[0], d[3], ca);
- d[3] = NR_NORMALIZE_21(ca);
- }
- break;
- default:
- break;
- }
- break;
- case NR_PIXBLOCK_MODE_R8G8B8A8P:
- switch (spb->mode) {
- case NR_PIXBLOCK_MODE_A8:
- break;
- case NR_PIXBLOCK_MODE_R8G8B8:
- d[0] = s[0];
- d[1] = s[1];
- d[2] = s[2];
- break;
- case NR_PIXBLOCK_MODE_R8G8B8A8N:
- d[0] = NR_COMPOSENPP_1111 (s[0], s[3], d[0]);
- d[1] = NR_COMPOSENPP_1111 (s[1], s[3], d[1]);
- d[2] = NR_COMPOSENPP_1111 (s[2], s[3], d[2]);
- d[3] = NR_COMPOSEA_111(s[3], d[3]);
- break;
- case NR_PIXBLOCK_MODE_R8G8B8A8P:
- d[0] = NR_COMPOSEPPP_1111 (s[0], s[3], d[0]);
- d[1] = NR_COMPOSEPPP_1111 (s[1], s[3], d[1]);
- d[2] = NR_COMPOSEPPP_1111 (s[2], s[3], d[2]);
- d[3] = NR_COMPOSEA_111(s[3], d[3]);
- break;
- default:
- break;
- }
- break;
- default:
- break;
- }
- }
-}
-
diff --git a/src/libnr/nr-pixblock-pixel.h b/src/libnr/nr-pixblock-pixel.h
deleted file mode 100644
index da64aee4c..000000000
--- a/src/libnr/nr-pixblock-pixel.h
+++ /dev/null
@@ -1,28 +0,0 @@
-#ifndef __NR_PIXBLOCK_PIXEL_H__
-#define __NR_PIXBLOCK_PIXEL_H__
-
-/*
- * Pixel buffer rendering library
- *
- * Authors:
- * Lauris Kaplinski <lauris@kaplinski.com>
- *
- * This code is in public domain
- */
-
-#include <libnr/nr-pixblock.h>
-
-void nr_compose_pixblock_pixblock_pixel (NRPixBlock *dpb, unsigned char *d, const NRPixBlock *spb, const unsigned char *s);
-
-#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:textwidth=99 :
diff --git a/src/libnr/nr-pixblock.cpp b/src/libnr/nr-pixblock.cpp
deleted file mode 100644
index b95d8db8d..000000000
--- a/src/libnr/nr-pixblock.cpp
+++ /dev/null
@@ -1,465 +0,0 @@
-#define __NR_PIXBLOCK_C__
-
-/** \file
- * \brief Allocation/Setup of NRPixBlock objects. Pixel store functions.
- *
- * Authors:
- * (C) 1999-2002 Lauris Kaplinski <lauris@kaplinski.com>
- * 2008, Jasper van de Gronde <th.v.d.gonde@hccnet.nl>
- *
- * This code is in the Public Domain
- */
-
-#include <cstring>
-#include <string>
-#include <string.h>
-#include <glib/gmem.h>
-#include "nr-pixblock.h"
-
-/// Size of buffer that needs no allocation (default 4).
-#define NR_TINY_MAX sizeof (unsigned char *)
-
-/**
- * Pixbuf initialisation using homegrown memory handling ("pixelstore").
- *
- * Pixbuf sizes are differentiated into tiny, <4K, <16K, <64K, and more,
- * with each type having its own method of memory handling. After allocating
- * memory, the buffer is cleared if the clear flag is set. Intended to
- * reduce memory fragmentation.
- * \param pb Pointer to the pixbuf struct.
- * \param mode Indicates grayscale/RGB/RGBA.
- * \param clear True if buffer should be cleared.
- * \pre x1>=x0 && y1>=y0 && pb!=NULL
- */
-void
-nr_pixblock_setup_fast (NRPixBlock *pb, NR_PIXBLOCK_MODE mode, int x0, int y0, int x1, int y1, bool clear)
-{
- int w, h, bpp;
- size_t size;
-
- w = x1 - x0;
- h = y1 - y0;
- bpp = (mode == NR_PIXBLOCK_MODE_A8) ? 1 : (mode == NR_PIXBLOCK_MODE_R8G8B8) ? 3 : 4;
-
- guint64 sizel = (guint64)bpp * (guint64)w * (guint64)h;
-
- if(sizel > (guint64)G_MAXSIZE) {
- g_warning ("the requested memory exceeds the system limit");
- return;
- }
-
- size = bpp * w * h;
-
- if (size <= NR_TINY_MAX) {
- pb->size = NR_PIXBLOCK_SIZE_TINY;
- if (clear) memset (pb->data.p, 0x0, size);
- } else if (size <= 4096) {
- pb->size = NR_PIXBLOCK_SIZE_4K;
- pb->data.px = nr_pixelstore_4K_new (clear, 0x0);
- } else if (size <= 16384) {
- pb->size = NR_PIXBLOCK_SIZE_16K;
- pb->data.px = nr_pixelstore_16K_new (clear, 0x0);
- } else if (size <= 65536) {
- pb->size = NR_PIXBLOCK_SIZE_64K;
- pb->data.px = nr_pixelstore_64K_new (clear, 0x0);
- } else if (size <= 262144) {
- pb->size = NR_PIXBLOCK_SIZE_256K;
- pb->data.px = nr_pixelstore_256K_new (clear, 0x0);
- } else if (size <= 1048576) {
- pb->size = NR_PIXBLOCK_SIZE_1M;
- pb->data.px = nr_pixelstore_1M_new (clear, 0x0);
- } else {
- pb->size = NR_PIXBLOCK_SIZE_BIG;
- pb->data.px = NULL;
- if (size > 100000000) { // Don't even try to allocate more than 100Mb (5000x5000 RGBA
- // pixels). It'll just bog the system down even if successful. FIXME:
- // Can anyone suggest something better than the magic number?
- g_warning ("%lu bytes requested for pixel buffer, this will slow down the system.", (long unsigned) size);
- // do not quit here, let the system decide for RAM usage
- // return;
- }
- pb->data.px = g_try_new (unsigned char, size);
- if (pb->data.px == NULL) { // memory allocation failed
- g_warning ("Could not allocate %lu bytes for pixel buffer!", (long unsigned) size);
- return;
- }
- if (clear) memset (pb->data.px, 0x0, size);
- }
-
- pb->mode = mode;
- pb->empty = 1;
- pb->visible_area.x0 = pb->area.x0 = x0;
- pb->visible_area.y0 = pb->area.y0 = y0;
- pb->visible_area.x1 = pb->area.x1 = x1;
- pb->visible_area.y1 = pb->area.y1 = y1;
- pb->rs = bpp * w;
-}
-
-/**
- * Pixbuf initialisation using g_new.
- *
- * After allocating memory, the buffer is cleared if the clear flag is set.
- * \param pb Pointer to the pixbuf struct.
- * \param mode Indicates grayscale/RGB/RGBA.
- * \param clear True if buffer should be cleared.
- * \pre x1>=x0 && y1>=y0 && pb!=NULL
- FIXME: currently unused except for nr_pixblock_new and pattern tiles, replace with _fast and delete?
- */
-void
-nr_pixblock_setup (NRPixBlock *pb, NR_PIXBLOCK_MODE mode, int x0, int y0, int x1, int y1, bool clear)
-{
- int w, h, bpp;
- size_t size;
-
- w = x1 - x0;
- h = y1 - y0;
- bpp = (mode == NR_PIXBLOCK_MODE_A8) ? 1 : (mode == NR_PIXBLOCK_MODE_R8G8B8) ? 3 : 4;
-
- size = bpp * w * h;
-
- if (size <= NR_TINY_MAX) {
- pb->size = NR_PIXBLOCK_SIZE_TINY;
- if (clear) memset (pb->data.p, 0x0, size);
- } else {
- pb->size = NR_PIXBLOCK_SIZE_BIG;
- pb->data.px = g_new (unsigned char, size);
- if (clear) memset (pb->data.px, 0x0, size);
- }
-
- pb->mode = mode;
- pb->empty = 1;
- pb->visible_area.x0 = pb->area.x0 = x0;
- pb->visible_area.y0 = pb->area.y0 = y0;
- pb->visible_area.x1 = pb->area.x1 = x1;
- pb->visible_area.y1 = pb->area.y1 = y1;
- pb->rs = bpp * w;
-}
-
-/**
- * Pixbuf initialisation with preset values.
- *
- * After copying all parameters into the NRPixBlock struct, the pixel buffer is cleared if the clear flag is set.
- * \param pb Pointer to the pixbuf struct.
- * \param mode Indicates grayscale/RGB/RGBA.
- * \param clear True if buffer should be cleared.
- * \pre x1>=x0 && y1>=y0 && pb!=NULL
- */
-void
-nr_pixblock_setup_extern (NRPixBlock *pb, NR_PIXBLOCK_MODE mode, int x0, int y0, int x1, int y1, unsigned char *px, int rs, bool empty, bool clear)
-{
- int w, bpp;
-
- w = x1 - x0;
- bpp = (mode == NR_PIXBLOCK_MODE_A8) ? 1 : (mode == NR_PIXBLOCK_MODE_R8G8B8) ? 3 : 4;
-
- pb->size = NR_PIXBLOCK_SIZE_STATIC;
- pb->mode = mode;
- pb->empty = empty;
- pb->visible_area.x0 = pb->area.x0 = x0;
- pb->visible_area.y0 = pb->area.y0 = y0;
- pb->visible_area.x1 = pb->area.x1 = x1;
- pb->visible_area.y1 = pb->area.y1 = y1;
- pb->data.px = px;
- pb->rs = rs;
-
- g_assert (pb->data.px != NULL);
- if (clear) {
- if (rs == bpp * w) {
- /// \todo How do you recognise if
- /// px was an uncleared tiny buffer?
- if (pb->data.px)
- memset (pb->data.px, 0x0, bpp * (y1 - y0) * w);
- } else {
- int y;
- for (y = y0; y < y1; y++) {
- memset (pb->data.px + (y - y0) * rs, 0x0, bpp * w);
- }
- }
- }
-}
-
-/**
- * Frees memory taken by pixel data in NRPixBlock.
- * \param pb Pointer to pixblock.
- * \pre pb and pb->data.px point to valid addresses.
- *
- * According to pb->size, one of the functions for freeing the pixelstore
- * is called. May be called regardless of how pixbuf was set up.
- */
-void
-nr_pixblock_release (NRPixBlock *pb)
-{
- switch (pb->size) {
- case NR_PIXBLOCK_SIZE_TINY:
- break;
- case NR_PIXBLOCK_SIZE_4K:
- nr_pixelstore_4K_free (pb->data.px);
- break;
- case NR_PIXBLOCK_SIZE_16K:
- nr_pixelstore_16K_free (pb->data.px);
- break;
- case NR_PIXBLOCK_SIZE_64K:
- nr_pixelstore_64K_free (pb->data.px);
- break;
- case NR_PIXBLOCK_SIZE_256K:
- nr_pixelstore_256K_free (pb->data.px);
- break;
- case NR_PIXBLOCK_SIZE_1M:
- nr_pixelstore_1M_free (pb->data.px);
- break;
- case NR_PIXBLOCK_SIZE_BIG:
- g_free (pb->data.px);
- break;
- case NR_PIXBLOCK_SIZE_STATIC:
- break;
- default:
- break;
- }
-}
-
-/**
- * Allocates NRPixBlock and sets it up.
- *
- * \return Pointer to fresh pixblock.
- * Calls g_new() and nr_pixblock_setup().
-FIXME: currently unused, delete? JG: Should be used more often! (To simplify memory management.)
- */
-NRPixBlock *
-nr_pixblock_new (NR_PIXBLOCK_MODE mode, int x0, int y0, int x1, int y1, bool clear)
-{
- NRPixBlock *pb;
-
- pb = g_new (NRPixBlock, 1);
- if (!pb) return 0;
-
- nr_pixblock_setup (pb, mode, x0, y0, x1, y1, clear);
- if (pb->size!=NR_PIXBLOCK_SIZE_TINY && !pb->data.px) {
- g_free(pb);
- return 0;
- }
-
- return pb;
-}
-
-/**
- * Allocates NRPixBlock and sets it up.
- *
- * \return Pointer to fresh pixblock.
- * Calls g_new() and nr_pixblock_setup().
- */
-NRPixBlock *
-nr_pixblock_new_fast (NR_PIXBLOCK_MODE mode, int x0, int y0, int x1, int y1, bool clear)
-{
- NRPixBlock *pb;
-
- pb = g_new (NRPixBlock, 1);
- if (!pb) return 0;
-
- nr_pixblock_setup_fast (pb, mode, x0, y0, x1, y1, clear);
- if (pb->size!=NR_PIXBLOCK_SIZE_TINY && !pb->data.px) {
- g_free(pb);
- return 0;
- }
-
- return pb;
-}
-
-/**
- * Frees all memory taken by pixblock.
- *
- * \return NULL
- */
-NRPixBlock *
-nr_pixblock_free (NRPixBlock *pb)
-{
- nr_pixblock_release (pb);
-
- g_free (pb);
-
- return NULL;
-}
-
-/* PixelStore operations */
-
-#define NR_4K_BLOCK 32
-static unsigned char **nr_4K_px = NULL;
-static unsigned int nr_4K_len = 0;
-static unsigned int nr_4K_size = 0;
-
-unsigned char *
-nr_pixelstore_4K_new (bool clear, unsigned char val)
-{
- unsigned char *px;
-
- if (nr_4K_len != 0) {
- nr_4K_len -= 1;
- px = nr_4K_px[nr_4K_len];
- } else {
- px = g_new (unsigned char, 4096);
- }
-
- if (clear) memset (px, val, 4096);
-
- return px;
-}
-
-void
-nr_pixelstore_4K_free (unsigned char *px)
-{
- if (nr_4K_len == nr_4K_size) {
- nr_4K_size += NR_4K_BLOCK;
- nr_4K_px = g_renew (unsigned char *, nr_4K_px, nr_4K_size);
- }
-
- nr_4K_px[nr_4K_len] = px;
- nr_4K_len += 1;
-}
-
-#define NR_16K_BLOCK 32
-static unsigned char **nr_16K_px = NULL;
-static unsigned int nr_16K_len = 0;
-static unsigned int nr_16K_size = 0;
-
-unsigned char *
-nr_pixelstore_16K_new (bool clear, unsigned char val)
-{
- unsigned char *px;
-
- if (nr_16K_len != 0) {
- nr_16K_len -= 1;
- px = nr_16K_px[nr_16K_len];
- } else {
- px = g_new (unsigned char, 16384);
- }
-
- if (clear) memset (px, val, 16384);
-
- return px;
-}
-
-void
-nr_pixelstore_16K_free (unsigned char *px)
-{
- if (nr_16K_len == nr_16K_size) {
- nr_16K_size += NR_16K_BLOCK;
- nr_16K_px = g_renew (unsigned char *, nr_16K_px, nr_16K_size);
- }
-
- nr_16K_px[nr_16K_len] = px;
- nr_16K_len += 1;
-}
-
-#define NR_64K_BLOCK 32
-static unsigned char **nr_64K_px = NULL;
-static unsigned int nr_64K_len = 0;
-static unsigned int nr_64K_size = 0;
-
-unsigned char *
-nr_pixelstore_64K_new (bool clear, unsigned char val)
-{
- unsigned char *px;
-
- if (nr_64K_len != 0) {
- nr_64K_len -= 1;
- px = nr_64K_px[nr_64K_len];
- } else {
- px = g_new (unsigned char, 65536);
- }
-
- if (clear) memset (px, val, 65536);
-
- return px;
-}
-
-void
-nr_pixelstore_64K_free (unsigned char *px)
-{
- if (nr_64K_len == nr_64K_size) {
- nr_64K_size += NR_64K_BLOCK;
- nr_64K_px = g_renew (unsigned char *, nr_64K_px, nr_64K_size);
- }
-
- nr_64K_px[nr_64K_len] = px;
- nr_64K_len += 1;
-}
-
-#define NR_256K_BLOCK 32
-#define NR_256K 262144
-static unsigned char **nr_256K_px = NULL;
-static unsigned int nr_256K_len = 0;
-static unsigned int nr_256K_size = 0;
-
-unsigned char *
-nr_pixelstore_256K_new (bool clear, unsigned char val)
-{
- unsigned char *px;
-
- if (nr_256K_len != 0) {
- nr_256K_len -= 1;
- px = nr_256K_px[nr_256K_len];
- } else {
- px = g_new (unsigned char, NR_256K);
- }
-
- if (clear) memset (px, val, NR_256K);
-
- return px;
-}
-
-void
-nr_pixelstore_256K_free (unsigned char *px)
-{
- if (nr_256K_len == nr_256K_size) {
- nr_256K_size += NR_256K_BLOCK;
- nr_256K_px = g_renew (unsigned char *, nr_256K_px, nr_256K_size);
- }
-
- nr_256K_px[nr_256K_len] = px;
- nr_256K_len += 1;
-}
-
-#define NR_1M_BLOCK 32
-#define NR_1M 1048576
-static unsigned char **nr_1M_px = NULL;
-static unsigned int nr_1M_len = 0;
-static unsigned int nr_1M_size = 0;
-
-unsigned char *
-nr_pixelstore_1M_new (bool clear, unsigned char val)
-{
- unsigned char *px;
-
- if (nr_1M_len != 0) {
- nr_1M_len -= 1;
- px = nr_1M_px[nr_1M_len];
- } else {
- px = g_new (unsigned char, NR_1M);
- }
-
- if (clear) memset (px, val, NR_1M);
-
- return px;
-}
-
-void
-nr_pixelstore_1M_free (unsigned char *px)
-{
- if (nr_1M_len == nr_1M_size) {
- nr_1M_size += NR_1M_BLOCK;
- nr_1M_px = g_renew (unsigned char *, nr_1M_px, nr_1M_size);
- }
-
- nr_1M_px[nr_1M_len] = px;
- nr_1M_len += 1;
-}
-
-/*
- 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/libnr/nr-pixblock.h b/src/libnr/nr-pixblock.h
deleted file mode 100644
index 404a0fd03..000000000
--- a/src/libnr/nr-pixblock.h
+++ /dev/null
@@ -1,103 +0,0 @@
-#ifndef __NR_PIXBLOCK_H__
-#define __NR_PIXBLOCK_H__
-
-/** \file
- * \brief Pixel block structure. Used for low-level rendering.
- *
- * Authors:
- * (C) 1999-2002 Lauris Kaplinski <lauris@kaplinski.com>
- * (C) 2005 Ralf Stephan <ralf@ark.in-berlin.de> (some cleanup)
- *
- * This code is in the Public Domain.
- */
-
-#include <libnr/nr-rect-l.h>
-#include <libnr/nr-forward.h>
-
-/// Size indicator. Hardcoded to max. 3 bits.
-typedef enum {
- NR_PIXBLOCK_SIZE_TINY, ///< Fits in (unsigned char *)
- NR_PIXBLOCK_SIZE_4K, ///< Pixelstore
- NR_PIXBLOCK_SIZE_16K, ///< Pixelstore
- NR_PIXBLOCK_SIZE_64K, ///< Pixelstore
- NR_PIXBLOCK_SIZE_256K, ///< Pixelstore
- NR_PIXBLOCK_SIZE_1M, ///< Pixelstore
- NR_PIXBLOCK_SIZE_BIG, ///< Normally allocated
- NR_PIXBLOCK_SIZE_STATIC ///< Externally managed
-} NR_PIXBLOCK_SIZE;
-
-/// Mode indicator. Hardcoded to max. 2 bits.
-typedef enum {
- NR_PIXBLOCK_MODE_A8, ///< Grayscale
- NR_PIXBLOCK_MODE_R8G8B8, ///< 8 bit RGB
- NR_PIXBLOCK_MODE_R8G8B8A8N, ///< Normal 8 bit RGBA
- NR_PIXBLOCK_MODE_R8G8B8A8P ///< Premultiplied 8 bit RGBA
-} NR_PIXBLOCK_MODE;
-
-/// The pixel block struct.
-struct NRPixBlock {
- NR_PIXBLOCK_SIZE size : 3; ///< Size indicator
- NR_PIXBLOCK_MODE mode : 2; ///< Mode indicator
- bool empty : 1; ///< Empty flag
- unsigned int rs; ///< Size of line in bytes
- NRRectL area;
- NRRectL visible_area;
- union {
- unsigned char *px; ///< Pointer to buffer
- unsigned char p[sizeof (unsigned char *)]; ///< Tiny buffer
- } data;
-};
-
-/// Returns number of bytes per pixel (1, 3, or 4).
-inline int
-NR_PIXBLOCK_BPP (NRPixBlock *pb)
-{
- return ((pb->mode == NR_PIXBLOCK_MODE_A8) ? 1 :
- (pb->mode == NR_PIXBLOCK_MODE_R8G8B8) ? 3 : 4);
-}
-
-/// Returns pointer to pixel data.
-inline unsigned char*
-NR_PIXBLOCK_PX (NRPixBlock *pb)
-{
- return ((pb->size == NR_PIXBLOCK_SIZE_TINY) ?
- pb->data.p : pb->data.px);
-}
-inline unsigned char const*
-NR_PIXBLOCK_PX (NRPixBlock const *pb)
-{
- return ((pb->size == NR_PIXBLOCK_SIZE_TINY) ?
- pb->data.p : pb->data.px);
-}
-
-void nr_pixblock_setup (NRPixBlock *pb, NR_PIXBLOCK_MODE mode, int x0, int y0, int x1, int y1, bool clear);
-void nr_pixblock_setup_fast (NRPixBlock *pb, NR_PIXBLOCK_MODE mode, int x0, int y0, int x1, int y1, bool clear);
-void nr_pixblock_setup_extern (NRPixBlock *pb, NR_PIXBLOCK_MODE mode, int x0, int y0, int x1, int y1, unsigned char *px, int rs, bool empty, bool clear);
-void nr_pixblock_release (NRPixBlock *pb);
-
-NRPixBlock *nr_pixblock_new (NR_PIXBLOCK_MODE mode, int x0, int y0, int x1, int y1, bool clear);
-NRPixBlock *nr_pixblock_new_fast (NR_PIXBLOCK_MODE mode, int x0, int y0, int x1, int y1, bool clear);
-NRPixBlock *nr_pixblock_free (NRPixBlock *pb);
-
-unsigned char *nr_pixelstore_4K_new (bool clear, unsigned char val);
-void nr_pixelstore_4K_free (unsigned char *px);
-unsigned char *nr_pixelstore_16K_new (bool clear, unsigned char val);
-void nr_pixelstore_16K_free (unsigned char *px);
-unsigned char *nr_pixelstore_64K_new (bool clear, unsigned char val);
-void nr_pixelstore_64K_free (unsigned char *px);
-unsigned char *nr_pixelstore_256K_new (bool clear, unsigned char val);
-void nr_pixelstore_256K_free (unsigned char *px);
-unsigned char *nr_pixelstore_1M_new (bool clear, unsigned char val);
-void nr_pixelstore_1M_free (unsigned char *px);
-
-#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:textwidth=99 :
diff --git a/src/libnr/nr-pixops.h b/src/libnr/nr-pixops.h
deleted file mode 100644
index 92196928a..000000000
--- a/src/libnr/nr-pixops.h
+++ /dev/null
@@ -1,148 +0,0 @@
-#ifndef __NR_PIXOPS_H__
-#define __NR_PIXOPS_H__
-
-/*
- * Pixel buffer rendering library
- *
- * Authors:
- * Lauris Kaplinski <lauris@kaplinski.com>
- * bulia byak <buliabyak@users.sf.net>
- *
- * This code is in public domain
- */
-
-#define NR_RGBA32_R(v) (unsigned char) (((v) >> 24) & 0xff)
-#define NR_RGBA32_G(v) (unsigned char) (((v) >> 16) & 0xff)
-#define NR_RGBA32_B(v) (unsigned char) (((v) >> 8) & 0xff)
-#define NR_RGBA32_A(v) (unsigned char) ((v) & 0xff)
-
-// FAST_DIVIDE assumes that 0<=num<=256*denom
-// (this covers the case that num=255*denom+denom/2, which is used by DIV_ROUND)
-template<unsigned int divisor> static inline unsigned int FAST_DIVIDE(unsigned int v) { return v/divisor; }
-template<> inline unsigned int FAST_DIVIDE<255>(unsigned int v) { return ((v+1)*0x101) >> 16; }
-template<> inline unsigned int FAST_DIVIDE<255*255>(unsigned int v) { v=(v+1)<<1; v=v+(v>>7)+((v*0x3)>>16)+(v>>22); return (v>>16)>>1; }
-// FAST_DIV_ROUND assumes that 0<=num<=255*denom (DIV_ROUND should work upto num=2^32-1-(denom/2),
-// but FAST_DIVIDE_BY_255 already fails at num=65790=258*255, which is not too far above 255.5*255)
-template<unsigned int divisor> static inline unsigned int FAST_DIV_ROUND(unsigned int v) { return FAST_DIVIDE<divisor>(v+(divisor)/2); }
-static inline unsigned int DIV_ROUND(unsigned int v, unsigned int divisor) { return (v+divisor/2)/divisor; }
-
-#define INK_COMPOSE(f,a,b) ( ( ((guchar) (b)) * ((guchar) (0xff - (a))) + ((guchar) (((b) ^ ~(f)) + (b)/4 - ((b)>127? 63 : 0))) * ((guchar) (a)) ) >>8)
-
-// Naming: OPb_i+o
-// OP = operation, for example: NORMALIZE, COMPOSEA, COMPOSENNN, PREMUL, etc.
-// i+o = range of input/output as powers of 2^8-1
-// for example, 213 means 0<=a<=255^2, 0<=b<=255, 0<=output<=255^3
-
-// Normalize
-static inline unsigned int NR_NORMALIZE_11(unsigned int v) { return v; }
-static inline unsigned int NR_NORMALIZE_21(unsigned int v) { return FAST_DIV_ROUND<255>(v); }
-static inline unsigned int NR_NORMALIZE_31(unsigned int v) { return FAST_DIV_ROUND<255*255>(v); }
-static inline unsigned int NR_NORMALIZE_41(unsigned int v) { return FAST_DIV_ROUND<255*255*255>(v); }
-
-// Compose alpha channel using (1 - (1-a)*(1-b))
-// Note that these can also be rewritten to NR_COMPOSENPP(255, a, b), slightly slower, but could help if someone
-// decides to use SSE or something similar (for allowing the four components to be treated the same way).
-static inline unsigned int NR_COMPOSEA_213(unsigned int a, unsigned int b) { return 255*255*255 - (255*255-a)*(255-b); }
-static inline unsigned int NR_COMPOSEA_112(unsigned int a, unsigned int b) { return 255*255 - (255-a)*(255-b); }
-static inline unsigned int NR_COMPOSEA_211(unsigned int a, unsigned int b) { return NR_NORMALIZE_31(NR_COMPOSEA_213(a, b)); }
-static inline unsigned int NR_COMPOSEA_111(unsigned int a, unsigned int b) { return NR_NORMALIZE_21(NR_COMPOSEA_112(a, b)); }
-
-// Operation: (1 - fa) * bc * ba + fa * fc
-static inline unsigned int NR_COMPOSENNP_12114(unsigned int fc, unsigned int fa, unsigned int bc, unsigned int ba) { return (255*255 - fa) * ba * bc + 255 * fa * fc; }
-static inline unsigned int NR_COMPOSENNP_11113(unsigned int fc, unsigned int fa, unsigned int bc, unsigned int ba) { return (255 - fa) * ba * bc + 255 * fa * fc; }
-static inline unsigned int NR_COMPOSENNP_11111(unsigned int fc, unsigned int fa, unsigned int bc, unsigned int ba) { return NR_NORMALIZE_31(NR_COMPOSENNP_11113(fc, fa, bc, ba)); }
-
-// Operation: (1 - fa) * bc * ba + fc
-static inline unsigned int NR_COMPOSEPNP_32114(unsigned int fc, unsigned int fa, unsigned int bc, unsigned int ba) { return (255*255 - fa) * ba * bc + 255 * fc; }
-static inline unsigned int NR_COMPOSEPNP_22114(unsigned int fc, unsigned int fa, unsigned int bc, unsigned int ba) { return (255*255 - fa) * ba * bc + 255*255 * fc; }
-static inline unsigned int NR_COMPOSEPNP_11113(unsigned int fc, unsigned int fa, unsigned int bc, unsigned int ba) { return (255 - fa) * ba * bc + 255*255 * fc; }
-static inline unsigned int NR_COMPOSEPNP_22111(unsigned int fc, unsigned int fa, unsigned int bc, unsigned int ba) { return NR_NORMALIZE_41(NR_COMPOSEPNP_22114(fc, fa, bc, ba)); }
-static inline unsigned int NR_COMPOSEPNP_11111(unsigned int fc, unsigned int fa, unsigned int bc, unsigned int ba) { return NR_NORMALIZE_31(NR_COMPOSEPNP_11113(fc, fa, bc, ba)); }
-
-// Operation: ((1 - fa) * bc * ba + fa * fc)/a
-// Reuses non-normalized versions of NR_COMPOSENNP
-static inline unsigned int NR_COMPOSENNN_121131(unsigned int fc, unsigned int fa, unsigned int bc, unsigned int ba, unsigned int a) { return DIV_ROUND(NR_COMPOSENNP_12114(fc, fa, bc, ba), a); }
-static inline unsigned int NR_COMPOSENNN_111121(unsigned int fc, unsigned int fa, unsigned int bc, unsigned int ba, unsigned int a) { return DIV_ROUND(NR_COMPOSENNP_11113(fc, fa, bc, ba), a); }
-
-// Operation: ((1 - fa) * bc * ba + fc)/a
-// Reuses non-normalized versions of NR_COMPOSEPNP
-static inline unsigned int NR_COMPOSEPNN_321131(unsigned int fc, unsigned int fa, unsigned int bc, unsigned int ba, unsigned int a) { return DIV_ROUND(NR_COMPOSEPNP_32114(fc, fa, bc, ba), a); }
-static inline unsigned int NR_COMPOSEPNN_221131(unsigned int fc, unsigned int fa, unsigned int bc, unsigned int ba, unsigned int a) { return DIV_ROUND(NR_COMPOSEPNP_22114(fc, fa, bc, ba), a); }
-static inline unsigned int NR_COMPOSEPNN_111121(unsigned int fc, unsigned int fa, unsigned int bc, unsigned int ba, unsigned int a) { return DIV_ROUND(NR_COMPOSEPNP_11113(fc, fa, bc, ba), a); }
-
-// Operation: (1 - fa) * bc + fa * fc
-// (1-fa)*bc+fa*fc = bc-fa*bc+fa*fc = bc+fa*(fc-bc)
-// For some reason it's faster to leave the initial 255*bc term in the non-normalized version instead of factoring it out...
-static inline unsigned int NR_COMPOSENPP_1213(unsigned int fc, unsigned int fa, unsigned int bc) { return 255*255*bc + fa*(fc-bc); }
-static inline unsigned int NR_COMPOSENPP_1123(unsigned int fc, unsigned int fa, unsigned int bc) { return 255*bc + fa*(255*fc-bc); }
-static inline unsigned int NR_COMPOSENPP_1112(unsigned int fc, unsigned int fa, unsigned int bc) { return 255*bc + fa*(fc-bc); }
-static inline unsigned int NR_COMPOSENPP_1211(unsigned int fc, unsigned int fa, unsigned int bc) { return NR_NORMALIZE_31(NR_COMPOSENPP_1213(fc, fa, bc)); }
-static inline unsigned int NR_COMPOSENPP_1121(unsigned int fc, unsigned int fa, unsigned int bc) { return NR_NORMALIZE_31(NR_COMPOSENPP_1123(fc, fa, bc)); }
-static inline unsigned int NR_COMPOSENPP_1111(unsigned int fc, unsigned int fa, unsigned int bc) { return NR_NORMALIZE_21(NR_COMPOSENPP_1112(fc, fa, bc)); }
-
-// Operation: (1 - fa) * bc + fc
-// (1-fa)*bc+fc = bc-fa*bc+fc = (bc+fc)-fa*bc
-// This rewritten form results in faster code (found out through testing)
-static inline unsigned int NR_COMPOSEPPP_2224(unsigned int fc, unsigned int fa, unsigned int bc) { return 255*255*(bc+fc) - fa*bc; } // Note that this can temporarily overflow (but it probably doesn't cause problems)
- // NR_COMPOSEPPP_2224 assumes that fa and fc have a common component (fa=a*x and fc=c*x), because then the maximum value is:
- // (255*255-255*x)*255*255 + 255*x*255*255 = 255*255*( (255*255-255*x) + 255*x ) = 255*255*255*( (255-x)+x ) = 255*255*255*255
-static inline unsigned int NR_COMPOSEPPP_3213(unsigned int fc, unsigned int fa, unsigned int bc) { return 255*255*bc + fc - fa*bc; }
-static inline unsigned int NR_COMPOSEPPP_2213(unsigned int fc, unsigned int fa, unsigned int bc) { return 255*(255*bc+fc) - fa*bc; }
-static inline unsigned int NR_COMPOSEPPP_1213(unsigned int fc, unsigned int fa, unsigned int bc) { return 255*255*(bc+fc) - fa*bc; }
-static inline unsigned int NR_COMPOSEPPP_1112(unsigned int fc, unsigned int fa, unsigned int bc) { return 255*(bc+fc) - fa*bc; }
-static inline unsigned int NR_COMPOSEPPP_2221(unsigned int fc, unsigned int fa, unsigned int bc) { return NR_NORMALIZE_41(NR_COMPOSEPPP_2224(fc, fa, bc)); }
-static inline unsigned int NR_COMPOSEPPP_3211(unsigned int fc, unsigned int fa, unsigned int bc) { return NR_NORMALIZE_31(NR_COMPOSEPPP_3213(fc, fa, bc)); }
-static inline unsigned int NR_COMPOSEPPP_2211(unsigned int fc, unsigned int fa, unsigned int bc) { return NR_NORMALIZE_31(NR_COMPOSEPPP_2213(fc, fa, bc)); }
-static inline unsigned int NR_COMPOSEPPP_1211(unsigned int fc, unsigned int fa, unsigned int bc) { return NR_NORMALIZE_21(NR_COMPOSEPPP_1213(fc, fa, bc)); }
-static inline unsigned int NR_COMPOSEPPP_1111(unsigned int fc, unsigned int fa, unsigned int bc) { return NR_NORMALIZE_21(NR_COMPOSEPPP_1112(fc, fa, bc)); }
-
-#define NR_COMPOSEN11_1211 NR_COMPOSENPP_1211
-#define NR_COMPOSEN11_1111 NR_COMPOSENPP_1111
-//inline unsigned int NR_COMPOSEN11_1111(unsigned int fc, unsigned int fa, unsigned int bc) { return NR_NORMALIZE_21((255 - fa) * bc + fa * fc ); }
-
-#define NR_COMPOSEP11_2211 NR_COMPOSEPPP_2211
-#define NR_COMPOSEP11_1211 NR_COMPOSEPPP_1211
-#define NR_COMPOSEP11_1111 NR_COMPOSEPPP_1111
-//inline unsigned int NR_COMPOSEP11_1111(unsigned int fc, unsigned int fa, unsigned int bc) { return NR_NORMALIZE_21((255 - fa) * bc + fc * 255); }
-
-// Premultiply using c*a
-static inline unsigned int NR_PREMUL_134(unsigned int c, unsigned int a) { return c * a; }
-static inline unsigned int NR_PREMUL_224(unsigned int c, unsigned int a) { return c * a; }
-static inline unsigned int NR_PREMUL_123(unsigned int c, unsigned int a) { return c * a; }
-static inline unsigned int NR_PREMUL_112(unsigned int c, unsigned int a) { return c * a; }
-static inline unsigned int NR_PREMUL_314(unsigned int c, unsigned int a) { return NR_PREMUL_134(c, a); }
-static inline unsigned int NR_PREMUL_213(unsigned int c, unsigned int a) { return NR_PREMUL_123(c, a); }
-static inline unsigned int NR_PREMUL_131(unsigned int c, unsigned int a) { return NR_NORMALIZE_41(NR_PREMUL_134(c, a)); }
-static inline unsigned int NR_PREMUL_221(unsigned int c, unsigned int a) { return NR_NORMALIZE_41(NR_PREMUL_224(c, a)); }
-static inline unsigned int NR_PREMUL_121(unsigned int c, unsigned int a) { return NR_NORMALIZE_31(NR_PREMUL_123(c, a)); }
-static inline unsigned int NR_PREMUL_111(unsigned int c, unsigned int a) { return NR_NORMALIZE_21(NR_PREMUL_112(c, a)); }
-static inline unsigned int NR_PREMUL_311(unsigned int c, unsigned int a) { return NR_NORMALIZE_41(NR_PREMUL_314(c, a)); }
-static inline unsigned int NR_PREMUL_211(unsigned int c, unsigned int a) { return NR_NORMALIZE_31(NR_PREMUL_213(c, a)); }
-
-// Demultiply using c/a
-static inline unsigned int NR_DEMUL_131(unsigned int c, unsigned int a) { return DIV_ROUND(255 * 255 * 255 * c, a); }
-static inline unsigned int NR_DEMUL_231(unsigned int c, unsigned int a) { return DIV_ROUND(255 * 255 * c, a); }
-static inline unsigned int NR_DEMUL_121(unsigned int c, unsigned int a) { return DIV_ROUND(255 * 255 * c, a); }
-static inline unsigned int NR_DEMUL_331(unsigned int c, unsigned int a) { return DIV_ROUND(255 * c, a); }
-static inline unsigned int NR_DEMUL_221(unsigned int c, unsigned int a) { return DIV_ROUND(255 * c, a); }
-static inline unsigned int NR_DEMUL_111(unsigned int c, unsigned int a) { return DIV_ROUND(255 * c, a); }
-static inline unsigned int NR_DEMUL_431(unsigned int c, unsigned int a) { return DIV_ROUND(c, a); }
-static inline unsigned int NR_DEMUL_321(unsigned int c, unsigned int a) { return DIV_ROUND(c, a); }
-static inline unsigned int NR_DEMUL_211(unsigned int c, unsigned int a) { return DIV_ROUND(c, a); }
-static inline unsigned int NR_DEMUL_421(unsigned int c, unsigned int a) { return DIV_ROUND(c, 255 * a); }
-static inline unsigned int NR_DEMUL_311(unsigned int c, unsigned int a) { return DIV_ROUND(c, 255 * a); }
-static inline unsigned int NR_DEMUL_411(unsigned int c, unsigned int a) { return DIV_ROUND(c, 255 * 255 * a); }
-
-
-#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:textwidth=99 :
diff --git a/src/libnr/nr-point-matrix-ops.h b/src/libnr/nr-point-matrix-ops.h
deleted file mode 100644
index 7bed71587..000000000
--- a/src/libnr/nr-point-matrix-ops.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/** @file
- * @brief Operator functions over (NR::Point, NR::Matrix)
- */
-#ifndef SEEN_NR_POINT_MATRIX_OPS_H
-#define SEEN_NR_POINT_MATRIX_OPS_H
-
-#include "libnr/nr-point.h"
-#include "libnr/nr-matrix.h"
-
-namespace NR {
-
-inline Point operator*(Point const &v, Matrix const &m)
-{
-#if 1 /* Which code makes it easier to see what's happening? */
- NR::Point const xform_col0(m[0],
- m[2]);
- NR::Point const xform_col1(m[1],
- m[3]);
- NR::Point const xlate(m[4], m[5]);
- return ( Point(dot(v, xform_col0),
- dot(v, xform_col1))
- + xlate );
-#else
- return Point(v[X] * m[0] + v[Y] * m[2] + m[4],
- v[X] * m[1] + v[Y] * m[3] + m[5]);
-#endif
-}
-
-inline Point &Point::operator*=(Matrix const &m)
-{
- *this = *this * m;
- return *this;
-}
-
-} /* namespace NR */
-
-
-#endif /* !SEEN_NR_POINT_MATRIX_OPS_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/libnr/nr-rect.cpp b/src/libnr/nr-rect.cpp
index 1e1f36104..58e16e963 100644
--- a/src/libnr/nr-rect.cpp
+++ b/src/libnr/nr-rect.cpp
@@ -11,6 +11,7 @@
#include "nr-rect-l.h"
#include <algorithm>
+#include "nr-point-ops.h"
NRRect::NRRect(NR::Rect const &rect)
: x0(rect.min()[NR::X]), y0(rect.min()[NR::Y]),
@@ -220,6 +221,8 @@ nr_rect_d_union_xy (NRRect *d, NR::Coord x, NR::Coord y)
NRRect *
nr_rect_d_matrix_transform(NRRect *d, NRRect const *const s, NR::Matrix const &m)
{
+ // defunct
+ /*
using NR::X;
using NR::Y;
@@ -238,7 +241,7 @@ nr_rect_d_matrix_transform(NRRect *d, NRRect const *const s, NR::Matrix const &m
std::max(c10[X], c11[X]));
d->y1 = std::max(std::max(c00[Y], c01[Y]),
std::max(c10[Y], c11[Y]));
- }
+ }*/
return d;
}
diff --git a/src/libnr/nr-rect.h b/src/libnr/nr-rect.h
index ea656c8e1..aa5921309 100644
--- a/src/libnr/nr-rect.h
+++ b/src/libnr/nr-rect.h
@@ -16,19 +16,23 @@
#include <stdexcept>
#include <limits>
+#include <glib.h>
#include "libnr/nr-values.h"
#include <libnr/nr-coord.h>
#include <libnr/nr-i-coord.h>
#include <libnr/nr-dim2.h>
#include <libnr/nr-point.h>
+#include "libnr/nr-point-ops.h"
+#include "libnr/nr-macros.h"
#include <boost/optional.hpp>
-#include <libnr/nr-point-matrix-ops.h>
#include <libnr/nr-forward.h>
#include <2geom/rect.h>
namespace NR {
+class Matrix;
+
/** A rectangle is always aligned to the X and Y axis. This means it
* can be defined using only 4 coordinates, and determining
* intersection is very efficient. The points inside a rectangle are
@@ -136,11 +140,6 @@ public:
return Rect(s * min(), s * max());
}
- /** Transforms the rect by m. Note that it gives correct results only for scales and translates */
- inline Rect operator*(Matrix const m) const {
- return Rect(_min * m, _max * m);
- }
-
inline bool operator==(Rect const &in_rect) {
return ((this->min() == in_rect.min()) && (this->max() == in_rect.max()));
}
diff --git a/src/libnr/nr-rotate-fns-test.h b/src/libnr/nr-rotate-fns-test.h
deleted file mode 100644
index 9d85da097..000000000
--- a/src/libnr/nr-rotate-fns-test.h
+++ /dev/null
@@ -1,54 +0,0 @@
-#include <cxxtest/TestSuite.h>
-
-#include <cmath>
-#include <glib/gmacros.h>
-
-#include <libnr/nr-rotate-fns.h>
-
-class NrRotateFnsTest : public CxxTest::TestSuite
-{
-public:
-
- NrRotateFnsTest()
- {
- }
- virtual ~NrRotateFnsTest() {}
-
-// createSuite and destroySuite get us per-suite setup and teardown
-// without us having to worry about static initialization order, etc.
- static NrRotateFnsTest *createSuite() { return new NrRotateFnsTest(); }
- static void destroySuite( NrRotateFnsTest *suite ) { delete suite; }
-
-
-
- void testRotateDegrees(void)
- {
- double const d[] = {
- 0, 90, 180, 270, 360, 45, 45.01, 44.99, 134, 135, 136, 314, 315, 317, 359, 361
- };
- for ( unsigned i = 0; i < G_N_ELEMENTS(d); ++i ) {
- double const degrees = d[i];
- NR::rotate const rot(rotate_degrees(degrees));
- NR::rotate const rot_approx( M_PI * ( degrees / 180. ) );
- TS_ASSERT( rotate_equalp(rot, rot_approx, 1e-12) );
-
- NR::rotate const rot_inv(rotate_degrees(-degrees));
- NR::rotate const rot_compl(rotate_degrees(360 - degrees));
- TS_ASSERT( rotate_equalp(rot_inv, rot_compl, 1e-12) );
-
- TS_ASSERT( !rotate_equalp(rot, rotate_degrees(degrees + 1), 1e-5) );
- }
- }
-
-};
-
-/*
- 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/libnr/nr-rotate-fns.cpp b/src/libnr/nr-rotate-fns.cpp
deleted file mode 100644
index f2669c20c..000000000
--- a/src/libnr/nr-rotate-fns.cpp
+++ /dev/null
@@ -1,66 +0,0 @@
-/** \file
- * Functions to/from NR::rotate.
- */
-#include <glib.h>
-#include "libnr/nr-rotate-ops.h"
-#include "libnr/nr-rotate-fns.h"
-
-/**
- * Returns a rotation matrix corresponding by the specified angle about the origin.
- *
- * Angle direction in Inkscape code: If you use the traditional mathematics convention that y
- * increases upwards, then positive angles are anticlockwise as per the mathematics convention. If
- * you take the common non-mathematical convention that y increases downwards, then positive angles
- * are clockwise, as is common outside of mathematics.
- */
-NR::rotate
-rotate_degrees(double degrees)
-{
- if (degrees < 0) {
- return rotate_degrees(-degrees).inverse();
- }
-
- double const degrees0 = degrees;
- if (degrees >= 360) {
- degrees = fmod(degrees, 360);
- }
-
- NR::rotate ret(1., 0.);
-
- if (degrees >= 180) {
- NR::rotate const rot180(-1., 0.);
- degrees -= 180;
- ret = rot180;
- }
-
- if (degrees >= 90) {
- NR::rotate const rot90(0., 1.);
- degrees -= 90;
- ret *= rot90;
- }
-
- if (degrees == 45) {
- NR::rotate const rot45(M_SQRT1_2, M_SQRT1_2);
- ret *= rot45;
- } else {
- double const radians = M_PI * ( degrees / 180 );
- ret *= NR::rotate(cos(radians), sin(radians));
- }
-
- NR::rotate const raw_ret( M_PI * ( degrees0 / 180 ) );
- g_return_val_if_fail(rotate_equalp(ret, raw_ret, 1e-8),
- raw_ret);
- return ret;
-}
-
-
-/*
- 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/libnr/nr-rotate-fns.h b/src/libnr/nr-rotate-fns.h
deleted file mode 100644
index bd075114c..000000000
--- a/src/libnr/nr-rotate-fns.h
+++ /dev/null
@@ -1,29 +0,0 @@
-#ifndef SEEN_NR_ROTATE_FNS_H
-#define SEEN_NR_ROTATE_FNS_H
-
-/** \file
- * Declarations for rotation functions.
- */
-
-#include <libnr/nr-rotate.h>
-#include <libnr/nr-point-fns.h>
-
-inline bool rotate_equalp(NR::rotate const &a, NR::rotate const &b, double const eps)
-{
- return point_equalp(a.vec, b.vec, eps);
-}
-
-NR::rotate rotate_degrees(double degrees);
-
-#endif /* !SEEN_NR_ROTATE_FNS_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/libnr/nr-rotate-matrix-ops.cpp b/src/libnr/nr-rotate-matrix-ops.cpp
deleted file mode 100644
index a2dd44b43..000000000
--- a/src/libnr/nr-rotate-matrix-ops.cpp
+++ /dev/null
@@ -1,19 +0,0 @@
-#include <libnr/nr-matrix-ops.h>
-
-NR::Matrix
-operator*(NR::rotate const &a, NR::Matrix const &b)
-{
- return NR::Matrix(a) * b;
-}
-
-
-/*
- 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/libnr/nr-rotate-matrix-ops.h b/src/libnr/nr-rotate-matrix-ops.h
deleted file mode 100644
index e34cc623b..000000000
--- a/src/libnr/nr-rotate-matrix-ops.h
+++ /dev/null
@@ -1,21 +0,0 @@
-#ifndef SEEN_LIBNR_NR_ROTATE_MATRIX_OPS_H
-#define SEEN_LIBNR_NR_ROTATE_MATRIX_OPS_H
-
-#include <libnr/nr-forward.h>
-
-
-NR::Matrix operator*(NR::rotate const &a, NR::Matrix const &b);
-
-
-#endif /* !SEEN_LIBNR_NR_ROTATE_MATRIX_OPS_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/libnr/nr-rotate-ops.h b/src/libnr/nr-rotate-ops.h
deleted file mode 100644
index 80eb57b9c..000000000
--- a/src/libnr/nr-rotate-ops.h
+++ /dev/null
@@ -1,43 +0,0 @@
-#ifndef SEEN_NR_ROTATE_OPS_H
-#define SEEN_NR_ROTATE_OPS_H
-#include <libnr/nr-rotate.h>
-
-namespace NR {
-
-inline Point operator*(Point const &v, rotate const &r)
-{
- return Point(r.vec[X] * v[X] - r.vec[Y] * v[Y],
- r.vec[Y] * v[X] + r.vec[X] * v[Y]);
-}
-
-inline rotate operator*(rotate const &a, rotate const &b)
-{
- return rotate( a.vec * b );
-}
-
-inline rotate &rotate::operator*=(rotate const &b)
-{
- *this = *this * b;
- return *this;
-}
-
-inline rotate operator/(rotate const &numer, rotate const &denom)
-{
- return numer * denom.inverse();
-}
-
-} /* namespace NR */
-
-
-#endif /* !SEEN_NR_ROTATE_OPS_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/libnr/nr-rotate-test.h b/src/libnr/nr-rotate-test.h
deleted file mode 100644
index 4b3501113..000000000
--- a/src/libnr/nr-rotate-test.h
+++ /dev/null
@@ -1,110 +0,0 @@
-#include <cxxtest/TestSuite.h>
-
-#include <cmath>
-#include <libnr/nr-matrix.h>
-#include <libnr/nr-matrix-ops.h>
-#include <libnr/nr-matrix-fns.h> /* identity, matrix_equalp */
-#include <libnr/nr-point-fns.h>
-#include <libnr/nr-rotate.h>
-#include <libnr/nr-rotate-fns.h>
-#include <libnr/nr-rotate-ops.h>
-
-
-class NrRotateTest : public CxxTest::TestSuite
-{
-public:
-
- NrRotateTest() :
- m_id( NR::identity() ),
- r_id( 0.0 ),
- rot234( .234 ),
- b( -2.0, 3.0 ),
- rot180( NR::Point(-1.0, 0.0) )
- {
- }
- virtual ~NrRotateTest() {}
-
-// createSuite and destroySuite get us per-suite setup and teardown
-// without us having to worry about static initialization order, etc.
- static NrRotateTest *createSuite() { return new NrRotateTest(); }
- static void destroySuite( NrRotateTest *suite ) { delete suite; }
-
- NR::Matrix const m_id;
- NR::rotate const r_id;
- NR::rotate const rot234;
- NR::Point const b;
- NR::rotate const rot180;
-
-
-
-
- void testCtorsCompares(void)
- {
- TS_ASSERT_EQUALS( r_id, r_id );
- TS_ASSERT_EQUALS( rot234, rot234 );
- TS_ASSERT_DIFFERS( rot234, r_id );
- TS_ASSERT_EQUALS( r_id, NR::rotate(NR::Point(1.0, 0.0)) );
- TS_ASSERT_EQUALS( NR::Matrix(r_id), m_id );
- TS_ASSERT( NR::Matrix(r_id).test_identity() );
-
- TS_ASSERT(rotate_equalp(rot234, NR::rotate(NR::Point(cos(.234), sin(.234))), 1e-12));
- }
-
- void testAssignmentOp(void)
- {
- NR::rotate rot234_eq(r_id);
- rot234_eq = rot234;
- TS_ASSERT_EQUALS( rot234, rot234_eq );
- TS_ASSERT_DIFFERS( rot234_eq, r_id );
- }
-
- void testInverse(void)
- {
- TS_ASSERT_EQUALS( r_id.inverse(), r_id );
- TS_ASSERT_EQUALS( rot234.inverse(), NR::rotate(-.234) );
- }
-
- void testOpStarPointRotate(void)
- {
- TS_ASSERT_EQUALS( b * r_id, b );
- TS_ASSERT_EQUALS( b * rot180, -b );
- TS_ASSERT_EQUALS( b * rot234, b * NR::Matrix(rot234) );
- TS_ASSERT(point_equalp(b * NR::rotate(M_PI / 2),
- NR::rot90(b),
- 1e-14));
- TS_ASSERT_EQUALS( b * rotate_degrees(90.), NR::rot90(b) );
- }
-
- void testOpStarRotateRotate(void)
- {
- TS_ASSERT_EQUALS( r_id * r_id, r_id );
- TS_ASSERT_EQUALS( rot180 * rot180, r_id );
- TS_ASSERT_EQUALS( rot234 * r_id, rot234 );
- TS_ASSERT_EQUALS( r_id * rot234, rot234 );
- TS_ASSERT( rotate_equalp(rot234 * rot234.inverse(), r_id, 1e-14) );
- TS_ASSERT( rotate_equalp(rot234.inverse() * rot234, r_id, 1e-14) );
- TS_ASSERT( rotate_equalp(( NR::rotate(0.25) * NR::rotate(.5) ),
- NR::rotate(.75),
- 1e-10) );
- }
-
- void testOpDivRotateRotate(void)
- {
- TS_ASSERT_EQUALS( rot234 / r_id, rot234 );
- TS_ASSERT_EQUALS( rot234 / rot180, rot234 * rot180 );
- TS_ASSERT( rotate_equalp(rot234 / rot234, r_id, 1e-14) );
- TS_ASSERT( rotate_equalp(r_id / rot234, rot234.inverse(), 1e-14) );
- }
-
-};
-
-/*
- 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/libnr/nr-rotate.h b/src/libnr/nr-rotate.h
deleted file mode 100644
index 6464983ab..000000000
--- a/src/libnr/nr-rotate.h
+++ /dev/null
@@ -1,66 +0,0 @@
-#ifndef SEEN_NR_ROTATE_H
-#define SEEN_NR_ROTATE_H
-
-/** \file
- * Rotation about the origin.
- */
-
-#include <libnr/nr-point.h>
-#include <libnr/nr-point-fns.h>
-#include <libnr/nr-point-ops.h>
-
-namespace NR {
-
-/** Notionally an NR::Matrix corresponding to rotation about the origin.
- Behaves like NR::Matrix for multiplication.
-**/
-class rotate {
-public:
- Point vec;
-
-private:
- rotate();
-
-public:
- explicit rotate(Coord theta);
- explicit rotate(Point const &p) : vec(p) {}
- explicit rotate(Coord const x, Coord const y) : vec(x, y) {}
-
- bool operator==(rotate const &o) const {
- return vec == o.vec;
- }
-
- bool operator!=(rotate const &o) const {
- return vec != o.vec;
- }
-
- inline rotate &operator*=(rotate const &b);
- /* Defined in nr-rotate-ops.h. */
-
- rotate inverse() const {
- /** \todo
- * In the usual case that vec is a unit vector (within rounding error),
- * dividing by len_sq is either a noop or numerically harmful.
- * Make a unit_rotate class (or the like) that knows its length is 1.
- */
- double const len_sq = dot(vec, vec);
- return rotate( Point(vec[X], -vec[Y])
- / len_sq );
- }
-};
-
-} /* namespace NR */
-
-
-#endif /* !SEEN_NR_ROTATE_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/libnr/nr-scale-matrix-ops.cpp b/src/libnr/nr-scale-matrix-ops.cpp
deleted file mode 100644
index 4bb90196e..000000000
--- a/src/libnr/nr-scale-matrix-ops.cpp
+++ /dev/null
@@ -1,25 +0,0 @@
-#include "libnr/nr-matrix-ops.h"
-
-NR::Matrix
-operator*(NR::scale const &s, NR::Matrix const &m)
-{
- using NR::X; using NR::Y;
- NR::Matrix ret(m);
- ret[0] *= s[X];
- ret[1] *= s[X];
- ret[2] *= s[Y];
- ret[3] *= s[Y];
- return ret;
-}
-
-
-/*
- 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/libnr/nr-scale-matrix-ops.h b/src/libnr/nr-scale-matrix-ops.h
deleted file mode 100644
index bf1b498c9..000000000
--- a/src/libnr/nr-scale-matrix-ops.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef SEEN_LIBNR_NR_SCALE_MATRIX_OPS_H
-#define SEEN_LIBNR_NR_SCALE_MATRIX_OPS_H
-/** \file
- * Declarations (and definition if inline) of operator
- * blah (NR::scale, NR::Matrix).
- */
-
-#include "libnr/nr-forward.h"
-
-NR::Matrix operator*(NR::scale const &s, NR::Matrix const &m);
-
-
-#endif /* !SEEN_LIBNR_NR_SCALE_MATRIX_OPS_H */
diff --git a/src/libnr/nr-scale-ops.h b/src/libnr/nr-scale-ops.h
deleted file mode 100644
index 63bfe222a..000000000
--- a/src/libnr/nr-scale-ops.h
+++ /dev/null
@@ -1,40 +0,0 @@
-#ifndef SEEN_NR_SCALE_OPS_H
-#define SEEN_NR_SCALE_OPS_H
-
-#include <libnr/nr-scale.h>
-
-namespace NR {
-
-inline Point operator*(Point const &p, scale const &s)
-{
- return Point(p[X] * s[X],
- p[Y] * s[Y]);
-}
-
-inline scale operator*(scale const &a, scale const &b)
-{
- return scale(a[X] * b[X],
- a[Y] * b[Y]);
-}
-
-inline scale operator/(scale const &numer, scale const &denom)
-{
- return scale(numer[X] / denom[X],
- numer[Y] / denom[Y]);
-}
-
-} /* namespace NR */
-
-
-#endif /* !SEEN_NR_SCALE_OPS_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/libnr/nr-scale-test.h b/src/libnr/nr-scale-test.h
deleted file mode 100644
index 55384c637..000000000
--- a/src/libnr/nr-scale-test.h
+++ /dev/null
@@ -1,90 +0,0 @@
-#include <cxxtest/TestSuite.h>
-
-#include <libnr/nr-scale.h>
-#include <libnr/nr-scale-ops.h>
-
-class NrScaleTest : public CxxTest::TestSuite
-{
-public:
-
- NrScaleTest() :
- sa( 1.5, 2.0 ),
- b( -2.0, 3.0 ),
- sb( b )
- {
- }
- virtual ~NrScaleTest() {}
-
-// createSuite and destroySuite get us per-suite setup and teardown
-// without us having to worry about static initialization order, etc.
- static NrScaleTest *createSuite() { return new NrScaleTest(); }
- static void destroySuite( NrScaleTest *suite ) { delete suite; }
-
- NR::scale const sa;
- NR::Point const b;
- NR::scale const sb;
-
-
-
- void testXY_CtorArrayOperator(void)
- {
- TS_ASSERT_EQUALS( sa[NR::X], 1.5 );
- TS_ASSERT_EQUALS( sa[NR::Y], 2.0 );
- TS_ASSERT_EQUALS( sa[0u], 1.5 );
- TS_ASSERT_EQUALS( sa[1u], 2.0 );
- }
-
-
- void testCopyCtor_AssignmentOp_NotEquals(void)
- {
- NR::scale const sa_copy(sa);
- TS_ASSERT_EQUALS( sa, sa_copy );
- TS_ASSERT(!( sa != sa_copy ));
- TS_ASSERT( sa != sb );
- }
-
- void testAssignmentOp(void)
- {
- NR::scale sa_eq(sb);
- sa_eq = sa;
- TS_ASSERT_EQUALS( sa, sa_eq );
- }
-
- void testPointCtor(void)
- {
- TS_ASSERT_EQUALS( sb[NR::X], b[NR::X] );
- TS_ASSERT_EQUALS( sb[NR::Y], b[NR::Y] );
- }
-
- void testOpStarPointScale(void)
- {
- NR::Point const ab( b * sa );
- TS_ASSERT_EQUALS( ab, NR::Point(-3.0, 6.0) );
- }
-
- void testOpStarScaleScale(void)
- {
- NR::scale const sab( sa * sb );
- TS_ASSERT_EQUALS( sab, NR::scale(-3.0, 6.0) );
- }
-
- void testOpDivScaleScale(void)
- {
- NR::scale const sa_b( sa / sb );
- NR::scale const exp_sa_b(-0.75, 2./3.);
- TS_ASSERT_EQUALS( sa_b[0], exp_sa_b[0] );
-// TS_ASSERT_EQUALS( fabs( sa_b[1] - exp_sa_b[1] ) < 1e-10 );
- TS_ASSERT_DELTA( sa_b[1], exp_sa_b[1], 1e-10 );
- }
-};
-
-/*
- 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/libnr/nr-scale-translate-ops.cpp b/src/libnr/nr-scale-translate-ops.cpp
deleted file mode 100644
index 579d071d8..000000000
--- a/src/libnr/nr-scale-translate-ops.cpp
+++ /dev/null
@@ -1,19 +0,0 @@
-#include "libnr/nr-matrix-translate-ops.h"
-
-NR::Matrix
-operator*(NR::scale const &s, NR::translate const &t)
-{
- return NR::Matrix(s) * t;
-}
-
-
-/*
- 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/libnr/nr-scale-translate-ops.h b/src/libnr/nr-scale-translate-ops.h
deleted file mode 100644
index 719b7b934..000000000
--- a/src/libnr/nr-scale-translate-ops.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef SEEN_LIBNR_NR_SCALE_TRANSLATE_OPS_H
-#define SEEN_LIBNR_NR_SCALE_TRANSLATE_OPS_H
-
-#include "libnr/nr-forward.h"
-
-NR::Matrix operator*(NR::scale const &s, NR::translate const &t);
-
-
-#endif /* !SEEN_LIBNR_NR_SCALE_TRANSLATE_OPS_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/libnr/nr-scale.h b/src/libnr/nr-scale.h
deleted file mode 100644
index fd59dc210..000000000
--- a/src/libnr/nr-scale.h
+++ /dev/null
@@ -1,55 +0,0 @@
-#ifndef SEEN_NR_SCALE_H
-#define SEEN_NR_SCALE_H
-#include <libnr/nr-point.h>
-#include <libnr/nr-point-ops.h>
-
-namespace NR {
-
-class scale {
-private:
- Point _p;
-
-private:
- scale();
-
-public:
- explicit scale(Point const &p) : _p(p) {}
- scale(double const x, double const y) : _p(x, y) {}
- explicit scale(double const s) : _p(s, s) {}
- inline Coord operator[](Dim2 const d) const { return _p[d]; }
- inline Coord operator[](unsigned const d) const { return _p[d]; }
- inline Coord &operator[](Dim2 const d) { return _p[d]; }
- inline Coord &operator[](unsigned const d) { return _p[d]; }
-
- bool operator==(scale const &o) const {
- return _p == o._p;
- }
-
- bool operator!=(scale const &o) const {
- return _p != o._p;
- }
-
- scale inverse() const {
- return scale(1/_p[0], 1/_p[1]);
- }
-
- NR::Point point() const {
- return _p;
- }
-};
-
-} /* namespace NR */
-
-
-#endif /* !SEEN_NR_SCALE_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/libnr/nr-translate-matrix-ops.cpp b/src/libnr/nr-translate-matrix-ops.cpp
deleted file mode 100644
index 80d08afa8..000000000
--- a/src/libnr/nr-translate-matrix-ops.cpp
+++ /dev/null
@@ -1,26 +0,0 @@
-#include "libnr/nr-matrix-ops.h"
-
-namespace NR {
-
-Matrix
-operator*(translate const &t, Matrix const &m)
-{
- Matrix ret(m);
- ret[4] += m[0] * t[X] + m[2] * t[Y];
- ret[5] += m[1] * t[X] + m[3] * t[Y];
- return ret;
-}
-
-} /* namespace NR */
-
-
-/*
- 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/libnr/nr-translate-matrix-ops.h b/src/libnr/nr-translate-matrix-ops.h
deleted file mode 100644
index cb939d5cf..000000000
--- a/src/libnr/nr-translate-matrix-ops.h
+++ /dev/null
@@ -1,22 +0,0 @@
-#ifndef SEEN_LIBNR_NR_TRANSLATE_MATRIX_OPS_H
-#define SEEN_LIBNR_NR_TRANSLATE_MATRIX_OPS_H
-
-#include "libnr/nr-forward.h"
-
-namespace NR {
-Matrix operator*(translate const &t, Matrix const &m);
-}
-
-
-#endif /* !SEEN_LIBNR_NR_TRANSLATE_MATRIX_OPS_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/libnr/nr-translate-ops.h b/src/libnr/nr-translate-ops.h
deleted file mode 100644
index 2812893fb..000000000
--- a/src/libnr/nr-translate-ops.h
+++ /dev/null
@@ -1,43 +0,0 @@
-#ifndef SEEN_NR_TRANSLATE_OPS_H
-#define SEEN_NR_TRANSLATE_OPS_H
-
-#include <libnr/nr-translate.h>
-#include <libnr/nr-point-ops.h>
-
-namespace NR {
-
-inline bool operator==(translate const &a, translate const &b)
-{
- return a.offset == b.offset;
-}
-
-inline bool operator!=(translate const &a, translate const &b)
-{
- return !( a == b );
-}
-
-inline translate operator*(translate const &a, translate const &b)
-{
- return translate( a.offset + b.offset );
-}
-
-inline Point operator*(Point const &v, translate const &t)
-{
- return t.offset + v;
-}
-
-} /* namespace NR */
-
-
-#endif /* !SEEN_NR_TRANSLATE_OPS_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/libnr/nr-translate-rotate-ops.cpp b/src/libnr/nr-translate-rotate-ops.cpp
deleted file mode 100644
index 3dbe31211..000000000
--- a/src/libnr/nr-translate-rotate-ops.cpp
+++ /dev/null
@@ -1,20 +0,0 @@
-#include <libnr/nr-matrix-translate-ops.h>
-#include <libnr/nr-rotate-ops.h>
-
-NR::Matrix
-operator*(NR::translate const &a, NR::rotate const &b)
-{
- return NR::Matrix(b) * NR::translate(a.offset * b);
-}
-
-
-/*
- 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/libnr/nr-translate-rotate-ops.h b/src/libnr/nr-translate-rotate-ops.h
deleted file mode 100644
index 286e5caa7..000000000
--- a/src/libnr/nr-translate-rotate-ops.h
+++ /dev/null
@@ -1,21 +0,0 @@
-#ifndef SEEN_LIBNR_NR_TRANSLATE_ROTATE_OPS_H
-#define SEEN_LIBNR_NR_TRANSLATE_ROTATE_OPS_H
-
-#include <libnr/nr-forward.h>
-
-
-NR::Matrix operator*(NR::translate const &a, NR::rotate const &b);
-
-
-#endif /* !SEEN_LIBNR_NR_TRANSLATE_ROTATE_OPS_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/libnr/nr-translate-scale-ops.cpp b/src/libnr/nr-translate-scale-ops.cpp
deleted file mode 100644
index 41e85c296..000000000
--- a/src/libnr/nr-translate-scale-ops.cpp
+++ /dev/null
@@ -1,24 +0,0 @@
-#include "libnr/nr-matrix-ops.h"
-
-NR::Matrix
-operator*(NR::translate const &t, NR::scale const &s)
-{
- using NR::X; using NR::Y;
-
- NR::Matrix ret(s);
- ret[4] = t[X] * s[X];
- ret[5] = t[Y] * s[Y];
- return ret;
-}
-
-
-/*
- 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/libnr/nr-translate-scale-ops.h b/src/libnr/nr-translate-scale-ops.h
deleted file mode 100644
index ad362a6a7..000000000
--- a/src/libnr/nr-translate-scale-ops.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef SEEN_LIBNR_NR_TRANSLATE_SCALE_OPS_H
-#define SEEN_LIBNR_NR_TRANSLATE_SCALE_OPS_H
-
-#include "libnr/nr-forward.h"
-
-NR::Matrix operator*(NR::translate const &t, NR::scale const &s);
-
-
-#endif /* !SEEN_LIBNR_NR_TRANSLATE_SCALE_OPS_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/libnr/nr-translate-test.h b/src/libnr/nr-translate-test.h
deleted file mode 100644
index 54d7c725f..000000000
--- a/src/libnr/nr-translate-test.h
+++ /dev/null
@@ -1,85 +0,0 @@
-#include <cxxtest/TestSuite.h>
-
-#include <libnr/nr-point-ops.h>
-#include <libnr/nr-matrix.h>
-#include <libnr/nr-matrix-fns.h>
-#include <libnr/nr-matrix-ops.h>
-#include <libnr/nr-point-matrix-ops.h>
-#include <libnr/nr-translate.h>
-#include <libnr/nr-translate-ops.h>
-
-class NrTranslateTest : public CxxTest::TestSuite
-{
-public:
-
- NrTranslateTest() :
- b( -2.0, 3.0 ),
- tb( b ),
- tc( -3.0, -2.0 ),
- tbc( tb * tc ),
- t_id( 0.0, 0.0 ),
- m_id( NR::identity() )
- {
- }
- virtual ~NrTranslateTest() {}
-
-// createSuite and destroySuite get us per-suite setup and teardown
-// without us having to worry about static initialization order, etc.
- static NrTranslateTest *createSuite() { return new NrTranslateTest(); }
- static void destroySuite( NrTranslateTest *suite ) { delete suite; }
-
- NR::Point const b;
- NR::translate const tb;
- NR::translate const tc;
- NR::translate const tbc;
- NR::translate const t_id;
- NR::Matrix const m_id;
-
-
- void testCtorsArrayOperator(void)
- {
- TS_ASSERT_EQUALS( tc[NR::X], -3.0 );
- TS_ASSERT_EQUALS( tc[NR::Y], -2.0 );
-
- TS_ASSERT_EQUALS( tb[0], b[NR::X] );
- TS_ASSERT_EQUALS( tb[1], b[NR::Y] );
- }
-
- void testAssignmentOperator(void)
- {
- NR::translate tb_eq(tc);
- tb_eq = tb;
- TS_ASSERT_EQUALS( tb, tb_eq );
- TS_ASSERT_DIFFERS( tb_eq, tc );
- }
-
- void testOpStarTranslateTranslate(void)
- {
- TS_ASSERT_EQUALS( tbc.offset, NR::Point(-5.0, 1.0) );
- TS_ASSERT_EQUALS( tbc.offset, ( tc * tb ).offset );
- TS_ASSERT_EQUALS( NR::Matrix(tbc), NR::Matrix(tb) * NR::Matrix(tc) );
- }
-
- void testOpStarPointTranslate(void)
- {
- TS_ASSERT_EQUALS( tbc.offset, b * tc );
- TS_ASSERT_EQUALS( b * tc, b * NR::Matrix(tc) );
- }
-
- void testIdentity(void)
- {
- TS_ASSERT_EQUALS( b * t_id, b );
- TS_ASSERT_EQUALS( NR::Matrix(t_id), m_id );
- }
-};
-
-/*
- 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/libnr/nr-translate.h b/src/libnr/nr-translate.h
deleted file mode 100644
index 65660099c..000000000
--- a/src/libnr/nr-translate.h
+++ /dev/null
@@ -1,34 +0,0 @@
-#ifndef SEEN_NR_TRANSLATE_H
-#define SEEN_NR_TRANSLATE_H
-
-#include <libnr/nr-point.h>
-
-namespace NR {
-
-class translate {
-public:
- Point offset;
-private:
- translate();
-public:
- explicit translate(Point const &p) : offset(p) {}
- explicit translate(Coord const x, Coord const y) : offset(x, y) {}
- Coord operator[](Dim2 const dim) const { return offset[dim]; }
- Coord operator[](unsigned const dim) const { return offset[dim]; }
-};
-
-} /* namespace NR */
-
-
-#endif /* !SEEN_NR_TRANSLATE_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/libnr/nr-types.h b/src/libnr/nr-types.h
index 8a1cb82cd..685c29342 100644
--- a/src/libnr/nr-types.h
+++ b/src/libnr/nr-types.h
@@ -18,7 +18,6 @@
#include <libnr/nr-coord.h>
#include <libnr/nr-dim2.h>
#include <libnr/nr-i-coord.h>
-#include <libnr/nr-matrix.h>
#include <libnr/nr-point.h>
#include <libnr/nr-point-l.h>
#include <libnr/nr-point-ops.h>
diff --git a/src/libnr/nr-values.cpp b/src/libnr/nr-values.cpp
index f828c1396..9193eff3b 100644
--- a/src/libnr/nr-values.cpp
+++ b/src/libnr/nr-values.cpp
@@ -1,14 +1,12 @@
#define __NR_VALUES_C__
#include <libnr/nr-rect-l.h>
-#include <libnr/nr-matrix-fns.h>
-
+#include "libnr/nr-rect.h"
/*
The following predefined objects are for reference
and comparison.
*/
-NR::Matrix NR_MATRIX_IDENTITY = NR::identity();
NRRect NR_RECT_EMPTY(NR_HUGE, NR_HUGE, -NR_HUGE, -NR_HUGE);
NRRectL NR_RECT_L_EMPTY =
{NR_HUGE_L, NR_HUGE_L, -NR_HUGE_L, -NR_HUGE_L};
diff --git a/src/libnr/nr-values.h b/src/libnr/nr-values.h
index 2a795e2c6..f85fca690 100644
--- a/src/libnr/nr-values.h
+++ b/src/libnr/nr-values.h
@@ -22,7 +22,6 @@
The following predefined objects are for reference
and comparison. They are defined in nr-values.cpp
*/
-extern NR::Matrix NR_MATRIX_IDENTITY;
extern NRRect NR_RECT_EMPTY;
extern NRRectL NR_RECT_L_EMPTY;
extern NRRectL NR_RECT_S_EMPTY;
diff --git a/src/libnr/testnr.cpp b/src/libnr/testnr.cpp
deleted file mode 100644
index 7ce01afab..000000000
--- a/src/libnr/testnr.cpp
+++ /dev/null
@@ -1,94 +0,0 @@
-#define __TESTNR_C__
-
-/*
- * Pixel buffer rendering library
- *
- * Authors:
- * Lauris Kaplinski <lauris@kaplinski.com>
- *
- * This code is in public domain
- */
-
-#include <stdio.h>
-
-#if defined (_WIN32) || defined (__WIN32__)
-# include <windows.h>
-#include <glib.h>
-#endif
-
-
-#include "nr-blit.h"
-
-static double
-get_time (void)
-{
- GTimeVal tv;
- g_get_current_time (&tv);
- return tv.tv_sec + 1e-6 * tv.tv_usec;
-}
-
-static unsigned int
-rand_byte (void)
-{
- return (int) (256.0 * rand () / (RAND_MAX + 1.0));
-}
-
-int
-main (int argc, const char **argv)
-{
- double start, end;
- NRPixBlock d, m[16];
- int count, i;
-
- srand (time (NULL));
-
- printf ("Initializing buffers\n");
-
- /* Destination */
- nr_pixblock_setup_fast (&d, NR_PIXBLOCK_MODE_R8G8B8A8P, 0, 0, 64, 64, 1);
- d.empty = 0;
-
- /* Masks */
- for (i = 0; i < 16; i++) {
- int r, b, c;
- nr_pixblock_setup_fast (&m[i], NR_PIXBLOCK_MODE_A8, 0, 0, 64, 64, 0);
- for (r = 0; r < 64; r++) {
- unsigned int q;
- unsigned char *p;
- p = NR_PIXBLOCK_PX (&m[i]) + r * m[i].rs;
- for (b = 0; b < 8; b++) {
- q = rand_byte ();
- if (q < 120) {
- for (c = 0; c < 8; c++) *p++ = 0;
- } else if (q < 240) {
- for (c = 0; c < 8; c++) *p++ = 255;
- } else {
- for (c = 0; c < 8; c++) *p++ = rand_byte ();
- }
- }
- }
- m[i].empty = 0;
- }
-
- printf ("Random transparency\n");
- count = 0;
- start = end = get_time ();
- while ((end - start) < 5.0) {
- unsigned char r, g, b, a;
- r = rand_byte ();
- g = rand_byte ();
- b = rand_byte ();
- a = rand_byte ();
-
- for (i = 0; i < 16; i++) {
- nr_blit_pixblock_mask_rgba32 (&d, &m[i], (a << 24) | (g << 16) | (b << 8) | a);
- count += 1;
- }
- end = get_time ();
- }
- printf ("Did %d [64x64] random buffers in %f sec\n", count, end - start); // localizing ok
- printf ("%f buffers per second\n", count / (end - start)); // localizing ok
- printf ("%f pixels per second\n", count * (64 * 64) / (end - start)); // localizing ok
-
- return 0;
-}
diff --git a/src/libnrtype/FontInstance.cpp b/src/libnrtype/FontInstance.cpp
index 6ba6440de..1b65dd88c 100644
--- a/src/libnrtype/FontInstance.cpp
+++ b/src/libnrtype/FontInstance.cpp
@@ -21,10 +21,10 @@
#include FT_TRUETYPE_TABLES_H
#include <pango/pangoft2.h>
#include <2geom/pathvector.h>
+#include <2geom/svg-path.h>
#include "libnr/nr-rect.h"
#include "libnrtype/font-glyph.h"
#include "libnrtype/font-instance.h"
-#include "libnrtype/RasterFont.h"
#include "livarot/Path.h"
#include "util/unordered-containers.h"
@@ -44,8 +44,6 @@ struct font_style_equal : public std::binary_function<font_style, font_style, bo
bool operator()(font_style const &a, font_style const &b) const;
};
-typedef INK_UNORDERED_MAP<font_style, raster_font*, font_style_hash, font_style_equal> StyleMap;
-
static const double STROKE_WIDTH_THREASHOLD = 0.01;
@@ -105,11 +103,17 @@ bool font_style_equal::operator()(const font_style &a,const font_style &b) const
/*
* Outline extraction
*/
-typedef struct ft2_to_liv {
- Path* theP;
- double scale;
- Geom::Point last;
-} ft2_to_liv;
+
+struct FT2GeomData {
+ FT2GeomData(Geom::PathBuilder &b, double s)
+ : builder(b)
+ , last(0, 0)
+ , scale(s)
+ {}
+ Geom::PathBuilder &builder;
+ Geom::Point last;
+ double scale;
+};
// Note: Freetype 2.2.1 redefined function signatures for functions to be placed in an
// FT_Outline_Funcs structure. This is needed to keep backwards compatibility with the
@@ -124,46 +128,46 @@ typedef FT_Vector FREETYPE_VECTOR;
// outline as returned by freetype -> livarot Path
// see nr-type-ft2.cpp for the freetype -> artBPath on which this code is based
-static int ft2_move_to(FREETYPE_VECTOR *to, void * i_user) {
- ft2_to_liv* user=(ft2_to_liv*)i_user;
- Geom::Point p(user->scale*to->x,user->scale*to->y);
+static int ft2_move_to(FREETYPE_VECTOR *to, void * i_user)
+{
+ FT2GeomData *user = (FT2GeomData*)i_user;
+ Geom::Point p(to->x, to->y);
// printf("m t=%f %f\n",p[0],p[1]);
- user->theP->MoveTo(p);
- user->last=p;
+ user->builder.moveTo(p * user->scale);
+ user->last = p;
return 0;
}
static int ft2_line_to(FREETYPE_VECTOR *to, void *i_user)
{
- ft2_to_liv* user=(ft2_to_liv*)i_user;
- Geom::Point p(user->scale*to->x,user->scale*to->y);
+ FT2GeomData *user = (FT2GeomData*)i_user;
+ Geom::Point p(to->x, to->y);
// printf("l t=%f %f\n",p[0],p[1]);
- user->theP->LineTo(p);
- user->last=p;
+ user->builder.lineTo(p * user->scale);
+ user->last = p;
return 0;
}
static int ft2_conic_to(FREETYPE_VECTOR *control, FREETYPE_VECTOR *to, void *i_user)
{
- ft2_to_liv* user=(ft2_to_liv*)i_user;
- Geom::Point p(user->scale*to->x,user->scale*to->y),c(user->scale*control->x,user->scale*control->y);
+ FT2GeomData *user = (FT2GeomData*)i_user;
+ Geom::Point p(to->x, to->y), c(control->x, control->y);
+ user->builder.quadTo(c * user->scale, p * user->scale);
// printf("b c=%f %f t=%f %f\n",c[0],c[1],p[0],p[1]);
- user->theP->BezierTo(p);
- user->theP->IntermBezierTo(c);
- user->theP->EndBezierTo();
- user->last=p;
+ user->last = p;
return 0;
}
static int ft2_cubic_to(FREETYPE_VECTOR *control1, FREETYPE_VECTOR *control2, FREETYPE_VECTOR *to, void *i_user)
{
- ft2_to_liv* user=(ft2_to_liv*)i_user;
- Geom::Point p(user->scale*to->x,user->scale*to->y);
- Geom::Point c1(user->scale*control1->x,user->scale*control1->y);
- Geom::Point c2(user->scale*control2->x,user->scale*control2->y);
+ FT2GeomData *user = (FT2GeomData*)i_user;
+ Geom::Point p(to->x, to->y);
+ Geom::Point c1(control1->x, control1->y);
+ Geom::Point c2(control2->x, control2->y);
// printf("c c1=%f %f c2=%f %f t=%f %f\n",c1[0],c1[1],c2[0],c2[1],p[0],p[1]);
- user->theP->CubicTo(p,3*(c1-user->last),3*(p-c2));
- user->last=p;
+ //user->theP->CubicTo(p,3*(c1-user->last),3*(p-c2));
+ user->builder.curveTo(c1 * user->scale, c2 * user->scale, p * user->scale);
+ user->last = p;
return 0;
}
#endif
@@ -182,7 +186,6 @@ font_instance::font_instance(void) :
nbGlyph(0),
maxGlyph(0),
glyphs(0),
- loadedPtr(new StyleMap()),
theFace(0)
{
//printf("font instance born\n");
@@ -190,12 +193,6 @@ font_instance::font_instance(void) :
font_instance::~font_instance(void)
{
- if ( loadedPtr ) {
- StyleMap* tmp = static_cast<StyleMap*>(loadedPtr);
- delete tmp;
- loadedPtr = 0;
- }
-
if ( daddy ) {
daddy->UnrefFace(this);
daddy = 0;
@@ -216,9 +213,6 @@ font_instance::~font_instance(void)
theFace = 0;
for (int i=0;i<nbGlyph;i++) {
- if ( glyphs[i].outline ) {
- delete glyphs[i].outline;
- }
if ( glyphs[i].pathvector ) {
delete glyphs[i].pathvector;
}
@@ -500,14 +494,19 @@ void font_instance::LoadGlyph(int glyph_id)
#endif
if ( id_to_no.find(glyph_id) == id_to_no.end() ) {
+ Geom::PathBuilder path_builder;
+
if ( nbGlyph >= maxGlyph ) {
maxGlyph=2*nbGlyph+1;
glyphs=(font_glyph*)realloc(glyphs,maxGlyph*sizeof(font_glyph));
}
font_glyph n_g;
- n_g.outline=NULL;
n_g.pathvector=NULL;
n_g.bbox[0]=n_g.bbox[1]=n_g.bbox[2]=n_g.bbox[3]=0;
+ n_g.h_advance = 0;
+ n_g.v_advance = 0;
+ n_g.h_width = 0;
+ n_g.v_width = 0;
bool doAdd=false;
#ifdef USE_PANGO_WIN32
@@ -526,7 +525,6 @@ void font_instance::LoadGlyph(int glyph_id)
n_g.v_advance=otm.otmTextMetrics.tmHeight*scale;
n_g.h_width=metrics.gmBlackBoxX*scale;
n_g.v_width=metrics.gmBlackBoxY*scale;
- n_g.outline=NULL;
if ( bufferSize == GDI_ERROR) {
// shit happened
} else if ( bufferSize == 0) {
@@ -538,14 +536,13 @@ void font_instance::LoadGlyph(int glyph_id)
// shit happened
} else {
// Platform SDK is rubbish, read KB87115 instead
- n_g.outline=new Path;
DWORD polyOffset=0;
while ( polyOffset < bufferSize ) {
TTPOLYGONHEADER const *polyHeader=(TTPOLYGONHEADER const *)(buffer+polyOffset);
if (polyOffset+polyHeader->cb > bufferSize) break;
if (polyHeader->dwType == TT_POLYGON_TYPE) {
- n_g.outline->MoveTo(pointfx_to_nrpoint(polyHeader->pfxStart, scale));
+ path_builder.moveTo(pointfx_to_nrpoint(polyHeader->pfxStart, scale));
DWORD curveOffset=polyOffset+sizeof(TTPOLYGONHEADER);
while ( curveOffset < polyOffset+polyHeader->cb ) {
@@ -554,41 +551,40 @@ void font_instance::LoadGlyph(int glyph_id)
POINTFX const *endp=p+polyCurve->cpfx;
switch (polyCurve->wType) {
- case TT_PRIM_LINE:
- while ( p != endp )
- n_g.outline->LineTo(pointfx_to_nrpoint(*p++, scale));
- break;
+ case TT_PRIM_LINE:
+ while ( p != endp )
+ path_builder.lineTo(pointfx_to_nrpoint(*p++, scale));
+ break;
- case TT_PRIM_QSPLINE:
+ case TT_PRIM_QSPLINE:
{
g_assert(polyCurve->cpfx >= 2);
- endp -= 2;
- Geom::Point this_mid=pointfx_to_nrpoint(p[0], scale);
- while ( p != endp ) {
- Geom::Point next_mid=pointfx_to_nrpoint(p[1], scale);
- n_g.outline->BezierTo((next_mid+this_mid)/2);
- n_g.outline->IntermBezierTo(this_mid);
- n_g.outline->EndBezierTo();
- ++p;
- this_mid=next_mid;
- }
- n_g.outline->BezierTo(pointfx_to_nrpoint(p[1], scale));
- n_g.outline->IntermBezierTo(this_mid);
- n_g.outline->EndBezierTo();
- break;
- }
- case 3: // TT_PRIM_CSPLINE
- g_assert(polyCurve->cpfx % 3 == 0);
- while ( p != endp ) {
- n_g.outline->CubicTo(pointfx_to_nrpoint(p[2], scale), pointfx_to_nrpoint(p[0], scale), pointfx_to_nrpoint(p[1], scale));
- p += 3;
+ // The list of points specifies one or more control points and ends with the end point.
+ // The intermediate points (on the curve) are the points between the control points.
+ Geom::Point this_control = pointfx_to_nrpoint(*p++, scale);
+ while ( p+1 != endp ) { // Process all "midpoints" (all points except the last)
+ Geom::Point new_control = pointfx_to_nrpoint(*p++, scale);
+ path_builder.quadTo(this_control, (new_control+this_control)/2);
+ this_control = new_control;
}
- break;
+ Geom::Point end = pointfx_to_nrpoint(*p++, scale);
+ path_builder.quadTo(this_control, end);
+ }
+ break;
+
+ case 3: // TT_PRIM_CSPLINE
+ g_assert(polyCurve->cpfx % 3 == 0);
+ while ( p != endp ) {
+ path_builder.curveTo(pointfx_to_nrpoint(p[0], scale),
+ pointfx_to_nrpoint(p[1], scale),
+ pointfx_to_nrpoint(p[2], scale));
+ p += 3;
+ }
+ break;
}
curveOffset += sizeof(TTPOLYCURVE)+sizeof(POINTFX)*(polyCurve->cpfx-1);
}
- n_g.outline->Close();
}
polyOffset += polyHeader->cb;
}
@@ -620,21 +616,29 @@ void font_instance::LoadGlyph(int glyph_id)
ft2_cubic_to,
0, 0
};
- n_g.outline=new Path;
- ft2_to_liv tData;
- tData.theP=n_g.outline;
- tData.scale=1.0/((double)theFace->units_per_EM);
- tData.last=Geom::Point(0,0);
- FT_Outline_Decompose (&theFace->glyph->outline, &ft2_outline_funcs, &tData);
+ FT2GeomData user(path_builder, 1.0/((double)theFace->units_per_EM));
+ FT_Outline_Decompose (&theFace->glyph->outline, &ft2_outline_funcs, &user);
}
doAdd=true;
}
#endif
+ path_builder.finish();
if ( doAdd ) {
- if ( n_g.outline ) {
- n_g.outline->FastBBox(n_g.bbox[0],n_g.bbox[1],n_g.bbox[2],n_g.bbox[3]);
- n_g.pathvector=n_g.outline->MakePathVector();
+ Geom::PathVector pv = path_builder.peek();
+ // close all paths
+ for (Geom::PathVector::iterator i = pv.begin(); i != pv.end(); ++i) {
+ i->close();
+ }
+ if ( !pv.empty() ) {
+ n_g.pathvector = new Geom::PathVector(pv);
+ Geom::OptRect bounds = bounds_exact(*n_g.pathvector);
+ if (bounds) {
+ n_g.bbox[0] = bounds->left();
+ n_g.bbox[1] = bounds->top();
+ n_g.bbox[2] = bounds->right();
+ n_g.bbox[3] = bounds->bottom();
+ }
}
glyphs[nbGlyph]=n_g;
id_to_no[glyph_id]=nbGlyph;
@@ -730,29 +734,6 @@ Geom::OptRect font_instance::BBox(int glyph_id)
}
}
-Path* font_instance::Outline(int glyph_id,Path* copyInto)
-{
- int no = -1;
- if ( id_to_no.find(glyph_id) == id_to_no.end() ) {
- LoadGlyph(glyph_id);
- if ( id_to_no.find(glyph_id) == id_to_no.end() ) {
- // didn't load
- } else {
- no = id_to_no[glyph_id];
- }
- } else {
- no = id_to_no[glyph_id];
- }
- if ( no < 0 ) return NULL;
- Path *src_o = glyphs[no].outline;
- if ( copyInto ) {
- copyInto->Reset();
- copyInto->Copy(src_o);
- return copyInto;
- }
- return src_o;
-}
-
Geom::PathVector* font_instance::PathVector(int glyph_id)
{
int no = -1;
@@ -793,72 +774,6 @@ double font_instance::Advance(int glyph_id,bool vertical)
return 0;
}
-
-raster_font* font_instance::RasterFont(const Geom::Affine &trs, double stroke_width, bool vertical, JoinType stroke_join, ButtType stroke_cap, float /*miter_limit*/)
-{
- font_style nStyle;
- nStyle.transform=trs;
- nStyle.vertical=vertical;
- nStyle.stroke_width=stroke_width;
- nStyle.stroke_cap=stroke_cap;
- nStyle.stroke_join=stroke_join;
- nStyle.nbDash=0;
- nStyle.dash_offset=0;
- nStyle.dashes=NULL;
- return RasterFont(nStyle);
-}
-
-raster_font* font_instance::RasterFont(const font_style &inStyle)
-{
- raster_font *res=NULL;
- double *savDashes=NULL;
- font_style nStyle=inStyle;
- // for some evil reason font_style doesn't have a copy ctor, so the
- // stuff that should be done there is done here instead (because the
- // raster_font ctor copies nStyle).
- if ( (nStyle.stroke_width > 0) && (nStyle.nbDash > 0) && nStyle.dashes ) {
- savDashes=nStyle.dashes;
- nStyle.dashes=(double*)malloc(nStyle.nbDash*sizeof(double));
- memcpy(nStyle.dashes,savDashes,nStyle.nbDash*sizeof(double));
- }
- StyleMap& loadedStyles = *static_cast<StyleMap*>(loadedPtr);
- if ( loadedStyles.find(nStyle) == loadedStyles.end() ) {
- raster_font *nR = new raster_font(nStyle);
- nR->Ref();
- nR->daddy=this;
- loadedStyles[nStyle]=nR;
- res=nR;
- if ( res ) {
- Ref();
- }
- } else {
- res=loadedStyles[nStyle];
- res->Ref();
- if ( nStyle.dashes ) {
- free(nStyle.dashes); // since they're not taken by a new rasterfont
- }
- }
- nStyle.dashes=savDashes;
- return res;
-}
-
-void font_instance::RemoveRasterFont(raster_font* who)
-{
- if ( who ) {
- StyleMap& loadedStyles = *static_cast<StyleMap*>(loadedPtr);
- if ( loadedStyles.find(who->style) == loadedStyles.end() ) {
- //g_print("RemoveRasterFont failed \n");
- // not found
- } else {
- loadedStyles.erase(loadedStyles.find(who->style));
- //g_print("RemoveRasterFont\n");
- Unref();
- }
- }
-}
-
-
-
/*
Local Variables:
mode:c++
diff --git a/src/libnrtype/Layout-TNG-Output.cpp b/src/libnrtype/Layout-TNG-Output.cpp
index 0d4d19a42..610f92582 100644
--- a/src/libnrtype/Layout-TNG-Output.cpp
+++ b/src/libnrtype/Layout-TNG-Output.cpp
@@ -15,9 +15,6 @@
#include "print.h"
#include "extension/print.h"
#include "livarot/Path.h"
-#include "libnr/nr-matrix-fns.h"
-#include "libnr/nr-scale-matrix-ops.h"
-#include "libnr/nr-convert2geom.h"
#include "font-instance.h"
#include "svg/svg-length.h"
#include "extension/internal/cairo-render-context.h"
@@ -288,7 +285,7 @@ void Layout::showGlyphs(CairoRenderContext *ctx) const
}
} while (glyph_index < _glyphs.size()
&& _path_fitted == NULL
- && NR::transform_equalp(font_matrix, glyph_matrix, NR_EPSILON)
+ && (font_matrix * glyph_matrix.inverse()).isIdentity()
&& _characters[_glyphs[glyph_index].in_character].in_span == this_span_index);
// remove vertical flip
diff --git a/src/libnrtype/Layout-TNG.h b/src/libnrtype/Layout-TNG.h
index 5ed922969..7d0c58c3e 100644
--- a/src/libnrtype/Layout-TNG.h
+++ b/src/libnrtype/Layout-TNG.h
@@ -14,8 +14,6 @@
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
-#include <libnr/nr-matrix-ops.h>
-#include <libnr/nr-rotate-ops.h>
#include <libnr/nr-rect.h>
#include <2geom/d2.h>
#include <2geom/affine.h>
diff --git a/src/libnrtype/Makefile_insert b/src/libnrtype/Makefile_insert
index 8f45dc94d..7cd99e1a8 100644
--- a/src/libnrtype/Makefile_insert
+++ b/src/libnrtype/Makefile_insert
@@ -20,10 +20,6 @@ ink_common_sources += \
libnrtype/one-box.h \
libnrtype/one-glyph.h \
libnrtype/one-para.h \
- libnrtype/RasterFont.cpp \
- libnrtype/RasterFont.h \
- libnrtype/raster-glyph.h \
- libnrtype/raster-position.h \
libnrtype/text-boundary.h \
libnrtype/TextWrapper.cpp \
libnrtype/TextWrapper.h \
diff --git a/src/libnrtype/RasterFont.cpp b/src/libnrtype/RasterFont.cpp
deleted file mode 100644
index 14f6c7afa..000000000
--- a/src/libnrtype/RasterFont.cpp
+++ /dev/null
@@ -1,435 +0,0 @@
-/*
- * RasterFont.cpp
- * testICU
- *
- */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-#include "RasterFont.h"
-
-#include <livarot/float-line.h>
-#include <livarot/int-line.h>
-#include <livarot/Path.h>
-#include <livarot/Shape.h>
-#include <libnr/nr-pixblock.h>
-#include <libnrtype/font-instance.h>
-#include <libnrtype/raster-glyph.h>
-#include <libnrtype/raster-position.h>
-
-
-static void glyph_run_A8_OR (raster_info &dest,void */*data*/,int st,float vst,int en,float ven);
-
-void font_style::Apply(Path* src,Shape* dest) {
- src->Convert(1);
- if ( stroke_width > 0 ) {
- if ( nbDash > 0 ) {
- double dlen = 0.0;
- const float scale = 1/*Geom::expansion(transform)*/;
- for (int i = 0; i < nbDash; i++) dlen += dashes[i] * scale;
- if (dlen >= 0.01) {
- float sc_offset = dash_offset * scale;
- float *tdashs=(float*)malloc((nbDash+1)*sizeof(float));
- while ( sc_offset >= dlen ) sc_offset-=dlen;
- tdashs[0]=dashes[0] * scale;
- for (int i=1;i<nbDash;i++) tdashs[i] = tdashs[i - 1] + dashes[i] * scale;
- src->DashPolyline(0.0,0.0,dlen,nbDash,tdashs,true,sc_offset);
- free(tdashs);
- }
- }
- src->Stroke(dest, false, 0.5*stroke_width, stroke_join, stroke_cap, 0.5*stroke_width*stroke_miter_limit);
- } else {
- src->Fill(dest,0);
- }
-}
-
-raster_font::raster_font(font_style const &fstyle) :
- daddy(NULL),
- refCount(0),
- style(fstyle),
- glyph_id_to_raster_glyph_no(),
- nbBase(0),
- maxBase(0),
- bases(NULL)
-{
- // printf("raster font born\n");
-}
-
-raster_font::~raster_font(void)
-{
-// printf("raster font death\n");
- if ( daddy ) daddy->RemoveRasterFont(this);
- daddy=NULL;
- if ( style.dashes ) free(style.dashes);
- style.dashes=NULL;
- for (int i=0;i<nbBase;i++) delete bases[i];
- if ( bases ) free(bases);
-}
-
-void raster_font::Unref(void)
-{
- refCount--;
-// printf("raster %x unref'd %i\n",this,refCount);
- if ( refCount <= 0 ) {
- if ( daddy ) daddy->RemoveRasterFont(this);
- daddy=NULL;
- delete this;
- }
-}
-void raster_font::Ref(void)
-{
- refCount++;
-// printf("raster %x ref'd %i\n",this,refCount);
-}
-raster_glyph* raster_font::GetGlyph(int glyph_id)
-{
- raster_glyph *res=NULL;
- if ( glyph_id_to_raster_glyph_no.find(glyph_id) == glyph_id_to_raster_glyph_no.end() ) {
- LoadRasterGlyph(glyph_id);
- if ( glyph_id_to_raster_glyph_no.find(glyph_id) == glyph_id_to_raster_glyph_no.end() ) { // recheck
- } else {
- res=bases[glyph_id_to_raster_glyph_no[glyph_id]];
- }
- } else {
- res=bases[glyph_id_to_raster_glyph_no[glyph_id]];
- }
- return res;
-}
-Geom::Point raster_font::Advance(int glyph_id)
-{
- if ( daddy == NULL ) return Geom::Point(0,0);
- double a=daddy->Advance(glyph_id,style.vertical);
- Geom::Point f_a=(style.vertical)?Geom::Point(0,a):Geom::Point(a,0);
- return f_a*style.transform;
-}
-void raster_font::BBox(int glyph_id,NRRect *area)
-{
- area->x0=area->y0=area->x1=area->y1=0;
- if ( daddy == NULL ) return;
- Geom::OptRect res=daddy->BBox(glyph_id);
- if (res) {
- Geom::Point bmi=res->min(),bma=res->max();
- Geom::Point tlp(bmi[0],bmi[1]),trp(bma[0],bmi[1]),blp(bmi[0],bma[1]),brp(bma[0],bma[1]);
- tlp=tlp*style.transform;
- trp=trp*style.transform;
- blp=blp*style.transform;
- brp=brp*style.transform;
- *res=Geom::Rect(tlp,trp);
- res->expandTo(blp);
- res->expandTo(brp);
- area->x0=(res->min())[0];
- area->y0=(res->min())[1];
- area->x1=(res->max())[0];
- area->y1=(res->max())[1];
- } else {
- nr_rect_d_set_empty(area);
- }
-}
-
-void raster_font::LoadRasterGlyph(int glyph_id)
-{
- raster_glyph *res=NULL;
- if ( glyph_id_to_raster_glyph_no.find(glyph_id) == glyph_id_to_raster_glyph_no.end() ) {
- res=new raster_glyph();
- res->daddy=this;
- res->glyph_id=glyph_id;
- if ( nbBase >= maxBase ) {
- maxBase=2*nbBase+1;
- bases=(raster_glyph**)realloc(bases,maxBase*sizeof(raster_glyph*));
- }
- bases[nbBase]=res;
- glyph_id_to_raster_glyph_no[glyph_id]=nbBase;
- nbBase++;
- } else {
- res=bases[glyph_id_to_raster_glyph_no[glyph_id]];
- }
- if ( res == NULL ) return;
- if ( res->polygon ) return;
- if ( res->outline == NULL ) {
- if ( daddy == NULL ) return;
- Path* outline=daddy->Outline(glyph_id,NULL);
- res->outline=new Path;
- if ( outline ) {
- res->outline->Copy(outline);
- }
- res->outline->Transform(style.transform);
- }
- Shape* temp=new Shape;
- res->polygon=new Shape;
- style.Apply(res->outline,temp);
- if ( style.stroke_width > 0 ) {
- res->polygon->ConvertToShape(temp,fill_nonZero);
- } else {
- res->polygon->ConvertToShape(temp,fill_oddEven);
- }
- delete temp;
-
- res->SetSubPixelPositionning(4);
-}
-void raster_font::RemoveRasterGlyph(raster_glyph* who)
-{
- if ( who == NULL ) return;
- int glyph_id=who->glyph_id;
- if ( glyph_id_to_raster_glyph_no.find(glyph_id) == glyph_id_to_raster_glyph_no.end() ) {
- int no=glyph_id_to_raster_glyph_no[glyph_id];
- if ( no >= nbBase-1 ) {
- } else {
- bases[no]=bases[--nbBase];
- glyph_id_to_raster_glyph_no[bases[no]->glyph_id]=no;
- }
- glyph_id_to_raster_glyph_no.erase(glyph_id_to_raster_glyph_no.find(glyph_id));
- } else {
- // not here
- }
-}
-
-/*int top,bottom; // baseline is y=0
- int* run_on_line; // array of size (bottom-top+1): run_on_line[i] gives the number of runs on line top+i
- int nbRun;
- float_ligne_run* runs;*/
-
-raster_position::raster_position(void)
-{
- top=0;
- bottom=-1;
- run_on_line=NULL;
- nbRun=0;
- runs=NULL;
-}
-raster_position::~raster_position(void)
-{
- if ( run_on_line ) free(run_on_line);
- if ( runs ) free(runs);
-}
-
-void raster_position::AppendRuns(std::vector<float_ligne_run> const &r,int y)
-{
- if ( top > bottom ) {
- top=bottom=y;
- if ( run_on_line ) free(run_on_line);
- run_on_line=(int*)malloc(sizeof(int));
- run_on_line[0]=0;
- } else {
- if ( y < top ) {
- // printf("wtf?\n");
- return;
- } else if ( y > bottom ) {
- int ob=bottom;
- bottom=y;
- run_on_line=(int*)realloc(run_on_line,(bottom-top+1)*sizeof(int));
- for (int i=ob+1;i<=bottom;i++) run_on_line[i-top]=0;
- }
- }
-
- if ( r.empty() == false) {
- run_on_line[y - top] = r.size();
- runs = (float_ligne_run *) realloc(runs, (nbRun + r.size()) * sizeof(float_ligne_run));
-
- for (int i = 0; i < int(r.size()); i++) {
- runs[nbRun + i] = r[i];
- }
-
- nbRun += r.size();
- }
-}
-void raster_position::Blit(float ph,int pv,NRPixBlock &over)
-{
- int base_y=top+pv;
- int first_y=top+pv,last_y=bottom+pv;
- if ( first_y < over.area.y0 ) first_y=over.area.y0;
- if ( last_y >= over.area.y1 ) last_y=over.area.y1-1;
- if ( first_y > last_y ) return;
- IntLigne *theIL=new IntLigne();
- FloatLigne *theI=new FloatLigne();
-
- char* mdata=(char*)over.data.px;
- if ( over.size == NR_PIXBLOCK_SIZE_TINY ) mdata=(char*)over.data.p;
-
- for (int y=first_y;y<=last_y;y++) {
- int first_r=0,last_r=0;
- for (int i=base_y;i<y;i++) first_r+=run_on_line[i-base_y];
- last_r=first_r+run_on_line[y-base_y]-1;
- if ( first_r <= last_r ) {
- theI->Reset();
- for (int i=first_r;i<=last_r;i++) theI->AddRun(runs[i].st+ph,runs[i].en+ph,runs[i].vst,runs[i].ven,runs[i].pente);
-// for (int i=first_r;i<=last_r;i++) {runs[i].st+=ph;runs[i].en+=ph;}
-// theI->nbRun=theI->maxRun=last_r-first_r+1;
-// theI->runs=runs+first_r;
-
- theIL->Copy(theI);
- raster_info dest;
- dest.startPix=over.area.x0;
- dest.endPix=over.area.x1;
- dest.sth=over.area.x0;
- dest.stv=y;
- dest.buffer=((uint32_t*)(mdata+(over.rs*(y-over.area.y0))));
- theIL->Raster(dest,NULL,glyph_run_A8_OR);
-
-// theI->nbRun=theI->maxRun=0;
-// theI->runs=NULL;
-// for (int i=first_r;i<=last_r;i++) {runs[i].st-=ph;runs[i].en-=ph;}
- }
- }
- delete theIL;
- delete theI;
-}
-
-
-/* raster_font* daddy;
- int glyph_id;
-
- Path* outline;
- Shape* polygon;
-
- int nb_sub_pixel;
- raster_position* sub_pixel;*/
-
-raster_glyph::raster_glyph(void)
-{
- daddy=NULL;
- glyph_id=0;
- outline=NULL;
- polygon=NULL;
- nb_sub_pixel=0;
- sub_pixel=NULL;
-}
-raster_glyph::~raster_glyph(void)
-{
- if ( outline ) delete outline;
- if ( polygon ) delete polygon;
- if ( sub_pixel ) delete [] sub_pixel;
-}
-
-
-void raster_glyph::SetSubPixelPositionning(int nb_pos)
-{
- nb_sub_pixel=nb_pos;
- if ( nb_sub_pixel <= 0 ) nb_sub_pixel=0;
- if ( sub_pixel ) delete [] sub_pixel;
- sub_pixel=NULL;
- if ( nb_sub_pixel > 0 ) {
- sub_pixel=new raster_position[nb_pos];
- if ( polygon ) {
- for (int i=0;i<nb_sub_pixel;i++) LoadSubPixelPosition(i);
- }
- }
-}
-void raster_glyph::LoadSubPixelPosition(int no)
-{
- if ( no < 0 || no >= nb_sub_pixel ) return;
- if ( sub_pixel[no].top <= sub_pixel[no].bottom ) return;
- if ( polygon == NULL ) {
- if ( daddy == NULL ) return;
- daddy->LoadRasterGlyph(glyph_id);
- if ( polygon == NULL ) return;
- }
-
- float sub_delta=((float)no)/((float)nb_sub_pixel);
-
- polygon->CalcBBox();
-
- float l=polygon->leftX,r=polygon->rightX,t=polygon->topY,b=polygon->bottomY;
- int il,ir,it,ib;
- il=(int)floor(l);
- ir=(int)ceil(r);
- it=(int)floor(t);
- ib=(int)ceil(b);
-
- // version par FloatLigne
- int curPt;
- float curY;
- polygon->BeginQuickRaster(curY, curPt);
-
- FloatLigne* theI=new FloatLigne();
-
- polygon->DirectQuickScan(curY,curPt,(float)(it-1)+sub_delta,true,1.0);
-
- for (int y=it-1;y<ib;y++) {
- theI->Reset();
- polygon->QuickScan(curY,curPt,((float)(y+1))+sub_delta,theI,1.0);
- theI->Flatten();
-
- sub_pixel[no].AppendRuns(theI->runs, y);
- }
- polygon->EndQuickRaster();
- delete theI;
-}
-
-void raster_glyph::Blit(const Geom::Point &at,NRPixBlock &over)
-{
- if ( nb_sub_pixel <= 0 ) return;
- int pv=(int)ceil(at[1]);
- double dec=4*(ceil(at[1])-at[1]);
- int no=(int)floor(dec);
- sub_pixel[no].Blit(at[0],pv,over);
-}
-
-
-
-static void
-glyph_run_A8_OR (raster_info &dest,void */*data*/,int st,float vst,int en,float ven)
-{
- if ( st >= en ) return;
- if ( vst < 0 ) vst=0;
- if ( vst > 1 ) vst=1;
- if ( ven < 0 ) ven=0;
- if ( ven > 1 ) ven=1;
- float sv=vst;
- float dv=ven-vst;
- int len=en-st;
- unsigned char* d=(unsigned char*)dest.buffer;
- d+=(st-dest.startPix);
- if ( fabs(dv) < 0.001 ) {
- if ( vst > 0.999 ) {
- /* Simple copy */
- while (len > 0) {
- d[0] = 255;
- d += 1;
- len -= 1;
- }
- } else {
- sv*=256;
- unsigned int c0_24=(int)sv;
- c0_24&=0xFF;
- while (len > 0) {
- unsigned int da;
- /* Draw */
- da = 65025 - (255 - c0_24) * (255 - d[0]);
- d[0] = (da + 127) / 255;
- d += 1;
- len -= 1;
- }
- }
- } else {
- if ( en <= st+1 ) {
- sv=0.5*(vst+ven);
- sv*=256;
- unsigned int c0_24=(int)sv;
- c0_24&=0xFF;
- unsigned int da;
- /* Draw */
- da = 65025 - (255 - c0_24) * (255 - d[0]);
- d[0] = (da + 127) / 255;
- } else {
- dv/=len;
- sv+=0.5*dv; // correction trapezoidale
- sv*=16777216;
- dv*=16777216;
- int c0_24 = static_cast<int>(CLAMP(sv, 0, 16777216));
- int s0_24 = static_cast<int>(dv);
- while (len > 0) {
- unsigned int ca, da;
- /* Draw */
- ca = c0_24 >> 16;
- if ( ca > 255 ) ca=255;
- da = 65025 - (255 - ca) * (255 - d[0]);
- d[0] = (da + 127) / 255;
- d += 1;
- c0_24 += s0_24;
- c0_24 = CLAMP (c0_24, 0, 16777216);
- len -= 1;
- }
- }
- }
-}
diff --git a/src/libnrtype/RasterFont.h b/src/libnrtype/RasterFont.h
deleted file mode 100644
index 015121b42..000000000
--- a/src/libnrtype/RasterFont.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * RasterFont.h
- * testICU
- *
- */
-
-#ifndef my_raster_font
-#define my_raster_font
-
-#include <map>
-
-#include <libnr/nr-forward.h>
-#include <libnrtype/nrtype-forward.h>
-#include <libnrtype/font-style.h>
-
-// one rasterfont is one way to draw a font on the screen
-// the way it's drawn is stored in style
-class raster_font {
-public:
- font_instance* daddy;
- int refCount;
-
- font_style style;
-
- std::map<int,int> glyph_id_to_raster_glyph_no;
- // an array of glyphs in this rasterfont.
- // it's a bit redundant with the one in the daddy font_instance, but these glyphs
- // contains the real rasterization data
- int nbBase,maxBase;
- raster_glyph** bases;
-
- explicit raster_font(font_style const &fstyle);
- virtual ~raster_font(void);
-
- void Unref(void);
- void Ref(void);
-
- // utility functions
- Geom::Point Advance(int glyph_id);
- void BBox(int glyph_id,NRRect *area);
-
- // attempts to load a glyph and return a raster_glyph on which you can call Blit
- raster_glyph* GetGlyph(int glyph_id);
- // utility
- void LoadRasterGlyph(int glyph_id); // refreshes outline/polygon if needed
- void RemoveRasterGlyph(raster_glyph* who);
-
-private:
- /* Disable the default copy constructor and operator=: they do the wrong thing for refCount. */
- raster_font(raster_font const &);
- raster_font &operator=(raster_font const &);
-};
-
-#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/libnrtype/font-glyph.h b/src/libnrtype/font-glyph.h
index 234502f9d..14da5025b 100644
--- a/src/libnrtype/font-glyph.h
+++ b/src/libnrtype/font-glyph.h
@@ -11,7 +11,6 @@ struct font_glyph {
double v_advance, v_width;
double bbox[4]; // bbox of the path (and the artbpath), not the bbox of the glyph
// as the fonts sometimes contain
- Path* outline; // outline as a livarot Path
Geom::PathVector* pathvector; // outline as 2geom pathvector, for text->curve stuff (should be unified with livarot)
};
diff --git a/src/libnrtype/font-instance.h b/src/libnrtype/font-instance.h
index 33085858b..392ac20bf 100644
--- a/src/libnrtype/font-instance.h
+++ b/src/libnrtype/font-instance.h
@@ -55,9 +55,6 @@ public:
// nota: all coordinates returned by these functions are on a [0..1] scale; you need to multiply
// by the fontsize to get the real sizes
- Path* Outline(int glyph_id, Path *copyInto=NULL);
- // queries the outline of the glyph (in livarot Path form), and copies it into copyInto instead
- // of allocating a new Path if copyInto != NULL
Geom::PathVector* PathVector(int glyph_id);
// returns the 2geom-type pathvector for this glyph. no refcounting needed, it's deallocated when the font_instance dies
double Advance(int glyph_id, bool vertical);
@@ -67,15 +64,6 @@ public:
// for generating slanted cursors for oblique fonts
Geom::OptRect BBox(int glyph_id);
- // creates a rasterfont for the given style
- raster_font* RasterFont(Geom::Affine const &trs, double stroke_width,
- bool vertical = false, JoinType stroke_join = join_straight,
- ButtType stroke_cap = butt_straight, float miter_limit = 4.0);
- // the dashes array in iStyle is copied
- raster_font* RasterFont(font_style const &iStyle);
- // private use: tells the font_instance that the raster_font 'who' has died
- void RemoveRasterFont(raster_font *who);
-
// attribute queries
unsigned Name(gchar *str, unsigned size);
unsigned PSName(gchar *str, unsigned size);
@@ -85,9 +73,6 @@ public:
private:
void FreeTheFace();
- // hashmap to get the raster_font for a given style
- void* loadedPtr;
-
#ifdef USE_PANGO_WIN32
HFONT theFace;
#else
diff --git a/src/libnrtype/font-lister.cpp b/src/libnrtype/font-lister.cpp
index a7160f5f0..bbed89b55 100644
--- a/src/libnrtype/font-lister.cpp
+++ b/src/libnrtype/font-lister.cpp
@@ -2,10 +2,7 @@
# include <config.h>
#endif
-#include <libnr/nr-blit.h>
#include <libnrtype/font-instance.h>
-#include <libnrtype/raster-glyph.h>
-#include <libnrtype/RasterFont.h>
#include <libnrtype/TextWrapper.h>
#include <libnrtype/one-glyph.h>
diff --git a/src/libnrtype/nrtype-forward.h b/src/libnrtype/nrtype-forward.h
index f3344f2fd..6050ffa6b 100644
--- a/src/libnrtype/nrtype-forward.h
+++ b/src/libnrtype/nrtype-forward.h
@@ -5,9 +5,6 @@ class font_factory;
struct font_glyph;
class font_instance;
struct font_style;
-class raster_font;
-class raster_glyph;
-class raster_position;
#endif /* !SEEN_LIBNRTYPE_NRTYPE_FORWARD_H */
diff --git a/src/libnrtype/raster-glyph.h b/src/libnrtype/raster-glyph.h
deleted file mode 100644
index 82a0b3f8e..000000000
--- a/src/libnrtype/raster-glyph.h
+++ /dev/null
@@ -1,49 +0,0 @@
-#ifndef SEEN_LIBNRTYPE_RASTER_GLYPH_H
-#define SEEN_LIBNRTYPE_RASTER_GLYPH_H
-
-#include <libnr/nr-forward.h>
-#include <libnrtype/nrtype-forward.h>
-#include <livarot/livarot-forward.h>
-
-// a little utility class that holds data to render a styled glyph
-// ie. it's like a polygon. its function is to wrap the subpixel positionning
-class raster_glyph {
-public:
- // raster_font that created me
- raster_font* daddy;
- // the glyph i am (the style is in daddy)
- int glyph_id;
- // internal structure: the styled path, and the associated uncrossed polygon
- // they could be removed after the raster_position have been computed
- Path* outline; // transformed by the matrix in style (may be factorized, but is small)
- Shape* polygon;
- // subpixel positions
- // nb_sub_pixel is set to 4 when the glyph is created (it's hardcoded)
- int nb_sub_pixel;
- raster_position* sub_pixel;
-
- raster_glyph(void);
- virtual ~raster_glyph(void);
-
- // utility
- void SetSubPixelPositionning(int nb_pos);
- void LoadSubPixelPosition(int no);
-
- // the interesting function: blits the glyph onto over
- // over should be a mask, ie a NRPixBlock with one 8bit plane
- void Blit(Geom::Point const &at, NRPixBlock &over); // alpha only
-};
-
-
-#endif /* !SEEN_LIBNRTYPE_RASTER_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 :
diff --git a/src/libnrtype/raster-position.h b/src/libnrtype/raster-position.h
deleted file mode 100644
index 744b6dddd..000000000
--- a/src/libnrtype/raster-position.h
+++ /dev/null
@@ -1,46 +0,0 @@
-#ifndef SEEN_LIBNRTYPE_RASTER_POSITION_H
-#define SEEN_LIBNRTYPE_RASTER_POSITION_H
-
-#include <vector>
-
-#include <libnr/nr-forward.h>
-#include <libnrtype/nrtype-forward.h>
-#include <livarot/livarot-forward.h>
-
-// one subpixel position
-// it's basically a set of trapezoids (=float_ligne_run) representing the black areas of the glyph
-// all trapezoids are in the same array, hence the run_on_line array to give the number of
-// trapezoids on each line
-// trapezoids store the x-positions as float, and are shifted to the x blit position
-// so it's "exact" in the x direction and subpixel in the y direction
-class raster_position {
-public:
- int top, bottom; // baseline is y=0
- // top is the first pixel, bottom is the last
- int* run_on_line; // array of size (bottom-top+1): run_on_line[i] gives the number of runs on line top+i
- int nbRun;
- float_ligne_run* runs;
-
-public:
- raster_position();
- virtual ~raster_position();
-
- // stuff runs into the structure
- void AppendRuns(std::vector<float_ligne_run> const &r, int y);
- // blits the trapezoids.
- void Blit(float ph, int pv, NRPixBlock &over);
-};
-
-
-#endif /* !SEEN_LIBNRTYPE_RASTER_POSITION_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/livarot/Path.cpp b/src/livarot/Path.cpp
index 1c04dbfb1..88d397864 100644
--- a/src/livarot/Path.cpp
+++ b/src/livarot/Path.cpp
@@ -9,7 +9,6 @@
#include <glib.h>
#include "Path.h"
#include "livarot/path-description.h"
-#include <libnr/nr-matrix-ops.h>
/*
* manipulation of the path data: path description and polyline
diff --git a/src/livarot/PathConversion.cpp b/src/livarot/PathConversion.cpp
index bf1e9c5c9..57609d1a2 100644
--- a/src/livarot/PathConversion.cpp
+++ b/src/livarot/PathConversion.cpp
@@ -9,8 +9,6 @@
#include "Path.h"
#include "Shape.h"
#include "livarot/path-description.h"
-
-#include <libnr/nr-matrix.h>
#include <2geom/transforms.h>
/*
diff --git a/src/livarot/PathCutting.cpp b/src/livarot/PathCutting.cpp
index ba81864a8..708d20f3f 100644
--- a/src/livarot/PathCutting.cpp
+++ b/src/livarot/PathCutting.cpp
@@ -20,7 +20,6 @@
#include "Path.h"
#include "style.h"
#include "livarot/path-description.h"
-#include "libnr/nr-point-matrix-ops.h"
#include "libnr/nr-convert2geom.h"
#include <2geom/pathvector.h>
#include <2geom/point.h>
@@ -511,10 +510,10 @@ double Path::Surface()
for (std::vector<path_lineto>::const_iterator i = pts.begin(); i != pts.end(); i++) {
if ( i->isMoveTo == polyline_moveto ) {
- surf += NR::cross(lastM - lastP, lastM);
+ surf += Geom::cross(lastM - lastP, lastM);
lastP = lastM = i->p;
} else {
- surf += NR::cross(i->p - lastP, i->p);
+ surf += Geom::cross(i->p - lastP, i->p);
lastP = i->p;
}
diff --git a/src/livarot/PathSimplify.cpp b/src/livarot/PathSimplify.cpp
index 7b04f028a..fb2aa55e2 100644
--- a/src/livarot/PathSimplify.cpp
+++ b/src/livarot/PathSimplify.cpp
@@ -7,7 +7,6 @@
*/
#include <glib/gmem.h>
-#include <libnr/nr-point-matrix-ops.h>
#include "livarot/Path.h"
#include "livarot/path-description.h"
@@ -127,7 +126,7 @@ double DistanceToCubic(Geom::Point const &start, PathDescrCubicTo res, Geom::Poi
}
Geom::Point seg = res.p - start;
- nnle = NR::cross(seg, sp);
+ nnle = Geom::cross(seg, sp);
nnle *= nnle;
nnle /= Geom::dot(seg, seg);
if ( nnle < nle ) {
diff --git a/src/livarot/ShapeMisc.cpp b/src/livarot/ShapeMisc.cpp
index 7d23913c3..da268910f 100644
--- a/src/livarot/ShapeMisc.cpp
+++ b/src/livarot/ShapeMisc.cpp
@@ -7,14 +7,14 @@
*/
#include "livarot/Shape.h"
-#include <libnr/nr-matrix-fns.h>
-#include <libnr/nr-point-fns.h>
#include "livarot/Path.h"
#include "livarot/path-description.h"
#include <glib.h>
#include <cstdio>
#include <cstdlib>
#include <cstring>
+#include <2geom/point.h>
+#include <2geom/affine.h>
/*
* polygon offset and polyline to path reassembling (when using back data)
diff --git a/src/livarot/ShapeSweep.cpp b/src/livarot/ShapeSweep.cpp
index a0b9dac1d..e3fb0296d 100644
--- a/src/livarot/ShapeSweep.cpp
+++ b/src/livarot/ShapeSweep.cpp
@@ -9,14 +9,14 @@
#include <cstdio>
#include <cstdlib>
#include <cstring>
+#include <glib.h>
#include <glib/gmem.h>
+#include <2geom/affine.h>
#include "Shape.h"
#include "livarot/sweep-event-queue.h"
#include "livarot/sweep-tree-list.h"
#include "livarot/sweep-tree.h"
-#include "libnr/nr-matrix.h"
-
//int doDebug=0;
/*
diff --git a/src/livarot/path-description.cpp b/src/livarot/path-description.cpp
index 95bd192d5..c34965a5c 100644
--- a/src/livarot/path-description.cpp
+++ b/src/livarot/path-description.cpp
@@ -1,5 +1,5 @@
-#include "libnr/nr-point-matrix-ops.h"
#include "livarot/path-description.h"
+#include <2geom/affine.h>
PathDescr *PathDescrMoveTo::clone() const
{
diff --git a/src/live_effects/lpe-curvestitch.cpp b/src/live_effects/lpe-curvestitch.cpp
index a2b4a591a..a002901b2 100644
--- a/src/live_effects/lpe-curvestitch.cpp
+++ b/src/live_effects/lpe-curvestitch.cpp
@@ -58,7 +58,7 @@ LPECurveStitch::LPECurveStitch(LivePathEffectObject *lpeobject) :
registerParameter( dynamic_cast<Parameter *>(&scale_y_rel) );
nrofpaths.param_make_integer();
- nrofpaths.param_set_range(2, NR_HUGE);
+ nrofpaths.param_set_range(2, Geom::infinity());
prop_scale.param_set_digits(3);
prop_scale.param_set_increments(0.01, 0.10);
diff --git a/src/live_effects/lpe-dynastroke.cpp b/src/live_effects/lpe-dynastroke.cpp
index 97d49d83d..0fd31dccf 100644
--- a/src/live_effects/lpe-dynastroke.cpp
+++ b/src/live_effects/lpe-dynastroke.cpp
@@ -97,11 +97,11 @@ LPEDynastroke::LPEDynastroke(LivePathEffectObject *lpeobject) :
registerParameter( dynamic_cast<Parameter *>(& round_ends) );
registerParameter( dynamic_cast<Parameter *>(& capping) );
- width.param_set_range(0, NR_HUGE);
+ width.param_set_range(0, Geom::infinity());
roundness.param_set_range(0.01, 1);
angle.param_set_range(-360, 360);
- growfor.param_set_range(0, NR_HUGE);
- fadefor.param_set_range(0, NR_HUGE);
+ growfor.param_set_range(0, Geom::infinity());
+ fadefor.param_set_range(0, Geom::infinity());
show_orig_path = true;
}
diff --git a/src/live_effects/lpe-interpolate.cpp b/src/live_effects/lpe-interpolate.cpp
index b8ce721a1..621823546 100644
--- a/src/live_effects/lpe-interpolate.cpp
+++ b/src/live_effects/lpe-interpolate.cpp
@@ -38,7 +38,7 @@ LPEInterpolate::LPEInterpolate(LivePathEffectObject *lpeobject) :
registerParameter( dynamic_cast<Parameter *>(&number_of_steps) );
number_of_steps.param_make_integer();
- number_of_steps.param_set_range(2, NR_HUGE);
+ number_of_steps.param_set_range(2, Geom::infinity());
}
LPEInterpolate::~LPEInterpolate()
diff --git a/src/live_effects/lpe-patternalongpath.cpp b/src/live_effects/lpe-patternalongpath.cpp
index b1af4c149..0a05228d2 100644
--- a/src/live_effects/lpe-patternalongpath.cpp
+++ b/src/live_effects/lpe-patternalongpath.cpp
@@ -139,9 +139,9 @@ LPEPatternAlongPath::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > con
}
//TODO: dynamical update of parameter ranges?
//if (prop_units.get_value()){
- // spacing.param_set_range(-.9, NR_HUGE);
+ // spacing.param_set_range(-.9, Geom::infinity());
// }else{
- // spacing.param_set_range(-pattBndsX.extent()*.9, NR_HUGE);
+ // spacing.param_set_range(-pattBndsX.extent()*.9, Geom::infinity());
// }
y0+=noffset;
diff --git a/src/live_effects/lpe-rough-hatches.cpp b/src/live_effects/lpe-rough-hatches.cpp
index 055b63661..671d88a8b 100644
--- a/src/live_effects/lpe-rough-hatches.cpp
+++ b/src/live_effects/lpe-rough-hatches.cpp
@@ -271,13 +271,13 @@ LPERoughHatches::LPERoughHatches(LivePathEffectObject *lpeobject) :
registerParameter( dynamic_cast<Parameter *>(&front_thickness) );
registerParameter( dynamic_cast<Parameter *>(&back_thickness) );
- //hatch_dist.param_set_range(0.1, NR_HUGE);
- growth.param_set_range(0, NR_HUGE);
+ //hatch_dist.param_set_range(0.1, Geom::infinity());
+ growth.param_set_range(0, Geom::infinity());
dist_rdm.param_set_range(0, 99.);
- stroke_width_top.param_set_range(0, NR_HUGE);
- stroke_width_bot.param_set_range(0, NR_HUGE);
- front_thickness.param_set_range(0, NR_HUGE);
- back_thickness.param_set_range(0, NR_HUGE);
+ stroke_width_top.param_set_range(0, Geom::infinity());
+ stroke_width_bot.param_set_range(0, Geom::infinity());
+ front_thickness.param_set_range(0, Geom::infinity());
+ back_thickness.param_set_range(0, Geom::infinity());
// hide the widgets for direction and bender vectorparams
direction.widget_is_visible = false;
diff --git a/src/live_effects/lpe-sketch.cpp b/src/live_effects/lpe-sketch.cpp
index 9488da84a..b621f6eca 100644
--- a/src/live_effects/lpe-sketch.cpp
+++ b/src/live_effects/lpe-sketch.cpp
@@ -89,24 +89,24 @@ LPESketch::LPESketch(LivePathEffectObject *lpeobject) :
#endif
nbiter_approxstrokes.param_make_integer();
- nbiter_approxstrokes.param_set_range(0, NR_HUGE);
- strokelength.param_set_range(1, NR_HUGE);
+ nbiter_approxstrokes.param_set_range(0, Geom::infinity());
+ strokelength.param_set_range(1, Geom::infinity());
strokelength.param_set_increments(1., 5.);
strokelength_rdm.param_set_range(0, 1.);
strokeoverlap.param_set_range(0, 1.);
strokeoverlap.param_set_increments(0.1, 0.30);
ends_tolerance.param_set_range(0., 1.);
- parallel_offset.param_set_range(0, NR_HUGE);
+ parallel_offset.param_set_range(0, Geom::infinity());
tremble_frequency.param_set_range(0.01, 100.);
tremble_frequency.param_set_increments(.5, 1.5);
strokeoverlap_rdm.param_set_range(0, 1.);
#ifdef LPE_SKETCH_USE_CONSTRUCTION_LINES
nbtangents.param_make_integer();
- nbtangents.param_set_range(0, NR_HUGE);
- tgtscale.param_set_range(0, NR_HUGE);
+ nbtangents.param_set_range(0, Geom::infinity());
+ tgtscale.param_set_range(0, Geom::infinity());
tgtscale.param_set_increments(.1, .5);
- tgtlength.param_set_range(0, NR_HUGE);
+ tgtlength.param_set_range(0, Geom::infinity());
tgtlength.param_set_increments(1., 5.);
tgtlength_rdm.param_set_range(0, 1.);
tgt_places_rdmness.param_set_range(0, 1.);
diff --git a/src/live_effects/lpe-vonkoch.cpp b/src/live_effects/lpe-vonkoch.cpp
index 050e4adc2..56e73e3a3 100644
--- a/src/live_effects/lpe-vonkoch.cpp
+++ b/src/live_effects/lpe-vonkoch.cpp
@@ -66,9 +66,9 @@ LPEVonKoch::LPEVonKoch(LivePathEffectObject *lpeobject) :
//registerParameter( dynamic_cast<Parameter *>(&draw_boxes) );
nbgenerations.param_make_integer();
- nbgenerations.param_set_range(0, NR_HUGE);
+ nbgenerations.param_set_range(0, Geom::infinity());
maxComplexity.param_make_integer();
- maxComplexity.param_set_range(0, NR_HUGE);
+ maxComplexity.param_set_range(0, Geom::infinity());
}
LPEVonKoch::~LPEVonKoch()
diff --git a/src/live_effects/parameter/parameter.cpp b/src/live_effects/parameter/parameter.cpp
index 57d583ba6..fc15ce1f5 100644
--- a/src/live_effects/parameter/parameter.cpp
+++ b/src/live_effects/parameter/parameter.cpp
@@ -53,8 +53,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(-NR_HUGE),
- max(NR_HUGE),
+ min(-Geom::infinity()),
+ max(Geom::infinity()),
integer(false),
defvalue(default_value),
digits(2),
diff --git a/src/live_effects/parameter/random.cpp b/src/live_effects/parameter/random.cpp
index 889e5375b..cdfb1fb50 100644
--- a/src/live_effects/parameter/random.cpp
+++ b/src/live_effects/parameter/random.cpp
@@ -32,8 +32,8 @@ RandomParam::RandomParam( const Glib::ustring& label, const Glib::ustring& tip,
{
defvalue = default_value;
value = defvalue;
- min = -NR_HUGE;
- max = NR_HUGE;
+ min = -Geom::infinity();
+ max = Geom::infinity();
integer = false;
defseed = default_seed;
diff --git a/src/main.cpp b/src/main.cpp
index 8ed6b4c03..26774fd66 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -96,9 +96,8 @@
#include <extension/input.h>
#ifdef WIN32
+#include <windows.h>
#include "registrytool.h"
-#include "extension/internal/win32.h"
-using Inkscape::Extension::Internal::PrintWin32;
#endif // WIN32
#include "extension/init.h"
@@ -698,9 +697,6 @@ main(int argc, char **argv)
}
#ifdef WIN32
-#ifndef REPLACEARGS_ANSI
- if ( PrintWin32::is_os_wide() )
-#endif // REPLACEARGS_ANSI
{
// If the call fails, we'll need to convert charsets
needToRecodeParams = !replaceArgs( argc, argv );
diff --git a/src/marker.cpp b/src/marker.cpp
index 5dd23fb1e..e82d3d952 100644
--- a/src/marker.cpp
+++ b/src/marker.cpp
@@ -17,12 +17,6 @@
#include <string>
#include "config.h"
-
-#include "libnr/nr-matrix-fns.h"
-#include "libnr/nr-matrix-ops.h"
-#include "libnr/nr-matrix-translate-ops.h"
-#include "libnr/nr-scale-matrix-ops.h"
-#include "libnr/nr-translate-matrix-ops.h"
#include "libnr/nr-convert2geom.h"
#include <2geom/affine.h>
#include "svg/svg.h"
@@ -621,6 +615,13 @@ sp_marker_show_instance ( SPMarker *marker, NRArenaItem *parent,
unsigned int key, unsigned int pos,
Geom::Affine const &base, float linewidth)
{
+ // do not show marker if linewidth == 0 and markerUnits == strokeWidth
+ // otherwise Cairo will fail to render anything on the tile
+ // that contains the "degenerate" marker
+ if (marker->markerUnits == SP_MARKER_UNITS_STROKEWIDTH && linewidth == 0) {
+ return NULL;
+ }
+
for (SPMarkerView *v = marker->views; v != NULL; v = v->next) {
if (v->key == key) {
if (pos >= v->items.size()) {
diff --git a/src/object-edit.cpp b/src/object-edit.cpp
index 2b03d7654..553c125a3 100644
--- a/src/object-edit.cpp
+++ b/src/object-edit.cpp
@@ -30,18 +30,11 @@
#include "desktop-handles.h"
#include "sp-namedview.h"
#include "live_effects/effect.h"
-
#include "sp-pattern.h"
#include "sp-path.h"
-
#include <glibmm/i18n.h>
-
#include "object-edit.h"
-
-#include <libnr/nr-scale-ops.h>
-
#include "xml/repr.h"
-
#include "2geom/isnan.h"
#define sp_round(v,m) (((v) < 0.0) ? ((ceil((v) / (m) - 0.5)) * (m)) : ((floor((v) / (m) + 0.5)) * (m)))
diff --git a/src/preferences-skeleton.h b/src/preferences-skeleton.h
index 62744bd53..16723170f 100644
--- a/src/preferences-skeleton.h
+++ b/src/preferences-skeleton.h
@@ -345,7 +345,6 @@ static char const preferences_skeleton[] =
" colorsontop=\"0\"\n"
" floatallowed=\"0\"\n"
" partialdynamic=\"0\"/>\n"
-" <group id=\"threading\" numthreads=\"1\"/>\n"
" </group>\n"
"\n"
" <group id=\"extensions\">"
diff --git a/src/print.cpp b/src/print.cpp
index fe52ea6dd..0774f5751 100644
--- a/src/print.cpp
+++ b/src/print.cpp
@@ -85,43 +85,6 @@ unsigned int sp_print_text(SPPrintContext *ctx, char const *text, Geom::Point p,
/* UI */
void
-sp_print_preview_document(SPDocument *doc)
-{
- Inkscape::Extension::Print *mod;
- unsigned int ret;
-
- doc->ensureUpToDate();
-
- mod = Inkscape::Extension::get_print(SP_MODULE_KEY_PRINT_DEFAULT);
-
- ret = mod->set_preview();
-
- if (ret) {
- SPPrintContext context;
- context.module = mod;
-
- /* fixme: This has to go into module constructor somehow */
- /* Create new arena */
- mod->base = SP_ITEM(doc->getRoot());
- mod->arena = NRArena::create();
- mod->dkey = SPItem::display_key_new(1);
- mod->root = (mod->base)->invoke_show(mod->arena, mod->dkey, SP_ITEM_SHOW_DISPLAY);
- /* Print document */
- ret = mod->begin(doc);
- (mod->base)->invoke_print(&context);
- ret = mod->finish();
- /* Release arena */
- (mod->base)->invoke_hide(mod->dkey);
- mod->base = NULL;
- mod->root = NULL;
- nr_object_unref((NRObject *) mod->arena);
- mod->arena = NULL;
- }
-
- return;
-}
-
-void
sp_print_document(Gtk::Window& parentWindow, SPDocument *doc)
{
doc->ensureUpToDate();
diff --git a/src/print.h b/src/print.h
index 70361fb14..caea6ae3a 100644
--- a/src/print.h
+++ b/src/print.h
@@ -41,7 +41,6 @@ void sp_print_get_param(SPPrintContext *ctx, gchar *name, bool *value);
/* UI */
-void sp_print_preview_document(SPDocument *doc);
void sp_print_document(Gtk::Window& parentWindow, SPDocument *doc);
void sp_print_document_to_file(SPDocument *doc, gchar const *filename);
diff --git a/src/proj_pt.cpp b/src/proj_pt.cpp
index 1d308f847..d9d4e06f1 100644
--- a/src/proj_pt.cpp
+++ b/src/proj_pt.cpp
@@ -48,7 +48,7 @@ Pt2::normalize() {
Geom::Point
Pt2::affine() {
if (fabs(pt[2]) < epsilon) {
- return Geom::Point (NR_HUGE, NR_HUGE);
+ return Geom::Point (Geom::infinity(), Geom::infinity());
}
return Geom::Point (pt[0]/pt[2], pt[1]/pt[2]);
}
diff --git a/src/proj_pt.h b/src/proj_pt.h
index 90f4af652..90b9df201 100644
--- a/src/proj_pt.h
+++ b/src/proj_pt.h
@@ -13,7 +13,6 @@
*/
#include <2geom/point.h>
-#include "libnr/nr-values.h"
#include <gtk/gtk.h>
namespace Proj {
@@ -29,12 +28,12 @@ public:
Pt2 (const gchar *coord_str);
inline double operator[] (unsigned int index) const {
- if (index > 2) { return NR_HUGE; }
+ if (index > 2) { return Geom::infinity(); }
return pt[index];
}
inline double &operator[] (unsigned int index) {
// FIXME: How should we handle wrong indices?
- //if (index > 2) { return NR_HUGE; }
+ //if (index > 2) { return Geom::infinity(); }
return pt[index];
}
inline bool operator== (Pt2 &rhs) {
@@ -137,12 +136,12 @@ public:
}
inline double operator[] (unsigned int index) const {
- if (index > 3) { return NR_HUGE; }
+ if (index > 3) { return Geom::infinity(); }
return pt[index];
}
inline double &operator[] (unsigned int index) {
// FIXME: How should we handle wrong indices?
- //if (index > 3) { return NR_HUGE; }
+ //if (index > 3) { return Geom::infinity(); }
return pt[index];
}
void normalize();
diff --git a/src/selection-chemistry.cpp b/src/selection-chemistry.cpp
index 0f756a9a3..6f385b8f5 100644
--- a/src/selection-chemistry.cpp
+++ b/src/selection-chemistry.cpp
@@ -53,10 +53,6 @@ SPCycleType SP_CYCLING = SP_CYCLE_FOCUS;
#include "sp-conn-end.h"
#include "dropper-context.h"
#include <glibmm/i18n.h>
-#include "libnr/nr-matrix-rotate-ops.h"
-#include "libnr/nr-matrix-translate-ops.h"
-#include "libnr/nr-scale-ops.h"
-#include <libnr/nr-matrix-ops.h>
#include <2geom/transforms.h>
#include "xml/repr.h"
#include "xml/rebase-hrefs.h"
@@ -1054,7 +1050,7 @@ take_style_from_item(SPItem *item)
}
// FIXME: also transform gradient/pattern fills, by forking? NO, this must be nondestructive
- double ex = to_2geom(item->i2doc_affine()).descrim();
+ double ex = item->i2doc_affine().descrim();
if (ex != 1.0) {
css = sp_css_attr_scale(css, ex);
}
@@ -2471,7 +2467,7 @@ sp_selection_tile(SPDesktop *desktop, bool apply)
gchar const *pat_id = pattern_tile(repr_copies, bounds, doc,
( Geom::Affine(Geom::Translate(desktop->dt2doc(Geom::Point(r->min()[Geom::X],
r->max()[Geom::Y]))))
- * to_2geom(parent_transform.inverse()) ),
+ * parent_transform.inverse() ),
parent_transform * move);
// restore compensation setting
@@ -2481,8 +2477,8 @@ sp_selection_tile(SPDesktop *desktop, bool apply)
Inkscape::XML::Node *rect = xml_doc->createElement("svg:rect");
rect->setAttribute("style", g_strdup_printf("stroke:none;fill:url(#%s)", pat_id));
- Geom::Point min = bounds.min() * to_2geom(parent_transform.inverse());
- Geom::Point max = bounds.max() * to_2geom(parent_transform.inverse());
+ Geom::Point min = bounds.min() * parent_transform.inverse();
+ Geom::Point max = bounds.max() * parent_transform.inverse();
sp_repr_set_svg_double(rect, "width", max[Geom::X] - min[Geom::X]);
sp_repr_set_svg_double(rect, "height", max[Geom::Y] - min[Geom::Y]);
@@ -2547,7 +2543,7 @@ void sp_selection_untile(SPDesktop *desktop)
SPPattern *pattern = pattern_getroot(SP_PATTERN(server));
- Geom::Affine pat_transform = to_2geom(pattern_patternTransform(SP_PATTERN(server)));
+ Geom::Affine pat_transform = pattern_patternTransform(SP_PATTERN(server));
pat_transform *= item->transform;
for (SPObject *child = pattern->firstChild() ; child != NULL; child = child->next ) {
@@ -2666,10 +2662,9 @@ void sp_selection_create_bitmap_copy(SPDesktop *desktop)
desktop->setWaitingCursor();
// Get the bounding box of the selection
- NRRect bbox;
document->ensureUpToDate();
- selection->bounds(&bbox);
- if (NR_RECT_DFLS_TEST_EMPTY(&bbox)) {
+ Geom::OptRect bbox = selection->bounds();
+ if (!bbox) {
desktop->clearWaitingCursor();
return; // exceptional situation, so not bother with a translatable error message, just quit quietly
}
@@ -2722,7 +2717,7 @@ void sp_selection_create_bitmap_copy(SPDesktop *desktop)
res = prefs_res;
} else if (0 < prefs_min) {
// If minsize is given, look up minimum bitmap size (default 250 pixels) and calculate resolution from it
- res = PX_PER_IN * prefs_min / MIN((bbox.x1 - bbox.x0), (bbox.y1 - bbox.y0));
+ res = PX_PER_IN * prefs_min / MIN(bbox->width(), bbox->height());
} else {
float hint_xdpi = 0, hint_ydpi = 0;
char const *hint_filename;
@@ -2743,8 +2738,8 @@ void sp_selection_create_bitmap_copy(SPDesktop *desktop)
}
// The width and height of the bitmap in pixels
- unsigned width = (unsigned) floor((bbox.x1 - bbox.x0) * res / PX_PER_IN);
- unsigned height =(unsigned) floor((bbox.y1 - bbox.y0) * res / PX_PER_IN);
+ unsigned width = (unsigned) floor(bbox->width() * res / PX_PER_IN);
+ unsigned height =(unsigned) floor(bbox->height() * res / PX_PER_IN);
// Find out if we have to run an external filter
gchar const *run = NULL;
@@ -2774,8 +2769,8 @@ void sp_selection_create_bitmap_copy(SPDesktop *desktop)
Geom::Affine eek(SP_ITEM(parent_object)->i2d_affine());
Geom::Affine t;
- double shift_x = bbox.x0;
- double shift_y = bbox.y1;
+ double shift_x = bbox->min()[Geom::X];
+ double shift_y = bbox->max()[Geom::Y];
if (res == PX_PER_IN) { // for default 90 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
@@ -2784,7 +2779,8 @@ void sp_selection_create_bitmap_copy(SPDesktop *desktop)
// Do the export
sp_export_png_file(document, filepath,
- bbox.x0, bbox.y0, bbox.x1, bbox.y1,
+ bbox->min()[Geom::X], bbox->min()[Geom::Y],
+ bbox->max()[Geom::X], bbox->max()[Geom::Y],
width, height, res, res,
(guint32) 0xffffff00,
NULL, NULL,
@@ -2810,8 +2806,8 @@ void sp_selection_create_bitmap_copy(SPDesktop *desktop)
sp_repr_set_svg_double(repr, "width", width);
sp_repr_set_svg_double(repr, "height", height);
} else {
- sp_repr_set_svg_double(repr, "width", (bbox.x1 - bbox.x0));
- sp_repr_set_svg_double(repr, "height", (bbox.y1 - bbox.y0));
+ sp_repr_set_svg_double(repr, "width", bbox->width());
+ sp_repr_set_svg_double(repr, "height", bbox->height());
}
// Write transform
diff --git a/src/selection.h b/src/selection.h
index de4294a63..00572a1c5 100644
--- a/src/selection.h
+++ b/src/selection.h
@@ -22,8 +22,6 @@
#include <stddef.h>
#include <sigc++/sigc++.h>
-//#include "libnr/nr-rect.h"
-#include "libnr/nr-convex-hull.h"
#include "forward.h"
#include "gc-managed.h"
#include "gc-finalized.h"
diff --git a/src/seltrans.cpp b/src/seltrans.cpp
index 061f60896..bb333caca 100644
--- a/src/seltrans.cpp
+++ b/src/seltrans.cpp
@@ -379,9 +379,9 @@ void Inkscape::SelTrans::grab(Geom::Point const &p, gdouble x, gdouble y, bool s
}
// Now let's reduce this to a single closest snappoint
- Geom::Coord dsp = _snap_points.size() == 1 ? Geom::L2((_snap_points.at(0)).getPoint() - p) : NR_HUGE;
- Geom::Coord dbbp = _bbox_points.size() == 1 ? Geom::L2((_bbox_points.at(0)).getPoint() - p) : NR_HUGE;
- Geom::Coord dbbpft = _bbox_points_for_translating.size() == 1 ? Geom::L2((_bbox_points_for_translating.at(0)).getPoint() - p) : NR_HUGE;
+ Geom::Coord dsp = _snap_points.size() == 1 ? Geom::L2((_snap_points.at(0)).getPoint() - p) : Geom::infinity();
+ Geom::Coord dbbp = _bbox_points.size() == 1 ? Geom::L2((_bbox_points.at(0)).getPoint() - p) : Geom::infinity();
+ Geom::Coord dbbpft = _bbox_points_for_translating.size() == 1 ? Geom::L2((_bbox_points_for_translating.at(0)).getPoint() - p) : Geom::infinity();
if (translating) {
_bbox_points.clear();
@@ -1219,7 +1219,7 @@ gboolean Inkscape::SelTrans::skewRequest(SPSelTransHandle const &handle, Geom::P
if (sn.getSnapped()) {
// We snapped something, so change the skew to reflect it
- Geom::Coord const sd = sn.getSnapped() ? sn.getTransformation()[0] : NR_HUGE;
+ Geom::Coord const sd = sn.getSnapped() ? sn.getTransformation()[0] : Geom::infinity();
_desktop->snapindicator->set_new_snaptarget(sn);
skew[dim_a] = sd;
} else {
diff --git a/src/shape-editor.h b/src/shape-editor.h
index f400244b3..1f0958a3e 100644
--- a/src/shape-editor.h
+++ b/src/shape-editor.h
@@ -24,7 +24,6 @@ class SPNodeContext;
class ShapeEditorsCollective;
class LivePathEffectObject;
-#include "libnr/nr-path-code.h"
#include <2geom/point.h>
#include <boost/optional.hpp>
#include <vector>
diff --git a/src/snap.cpp b/src/snap.cpp
index fb8f70c49..f8fe8e3fa 100644
--- a/src/snap.cpp
+++ b/src/snap.cpp
@@ -206,7 +206,7 @@ Inkscape::SnappedPoint SnapManager::freeSnap(Inkscape::SnapCandidatePoint const
Geom::OptRect const &bbox_to_snap) const
{
if (!someSnapperMightSnap()) {
- return Inkscape::SnappedPoint(p, Inkscape::SNAPTARGET_UNDEFINED, NR_HUGE, 0, false, false, false);
+ return Inkscape::SnappedPoint(p, Inkscape::SNAPTARGET_UNDEFINED, Geom::infinity(), 0, false, false, false);
}
SnappedConstraints sc;
@@ -263,7 +263,7 @@ Geom::Point SnapManager::multipleOfGridPitch(Geom::Point const &t, Geom::Point c
if (_desktop && _desktop->gridsEnabled()) {
bool success = false;
Geom::Point nearest_multiple;
- Geom::Coord nearest_distance = NR_HUGE;
+ Geom::Coord nearest_distance = Geom::infinity();
Inkscape::SnappedPoint bestSnappedPoint(t);
// It will snap to the grid for which we find the closest snap. This might be a different
@@ -717,10 +717,10 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed(
/* The current best transformation */
Geom::Point best_transformation = transformation;
- /* The current best metric for the best transformation; lower is better, NR_HUGE
+ /* The current best metric for the best transformation; lower is better, Geom::infinity()
** means that we haven't snapped anything.
*/
- Geom::Point best_scale_metric(NR_HUGE, NR_HUGE);
+ Geom::Point best_scale_metric(Geom::infinity(), Geom::infinity());
Inkscape::SnappedPoint best_snapped_point;
g_assert(best_snapped_point.getAlwaysSnap() == false); // Check initialization of snapped point
g_assert(best_snapped_point.getAtIntersection() == false);
@@ -929,10 +929,10 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed(
Geom::Coord best_metric;
if (transformation_type == SCALE) {
- // When scaling, don't ever exit with one of scaling components set to NR_HUGE
+ // When scaling, don't ever exit with one of scaling components set to Geom::infinity()
for (int index = 0; index < 2; index++) {
- if (best_transformation[index] == NR_HUGE) {
- if (uniform && best_transformation[1-index] < NR_HUGE) {
+ if (best_transformation[index] == Geom::infinity()) {
+ if (uniform && best_transformation[1-index] < Geom::infinity()) {
best_transformation[index] = best_transformation[1-index];
} else {
best_transformation[index] = transformation[index];
@@ -943,9 +943,9 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed(
best_metric = best_snapped_point.getSnapDistance();
best_snapped_point.setTransformation(best_transformation);
- // Using " < 1e6" instead of " < NR_HUGE" for catching some rounding errors
+ // Using " < 1e6" instead of " < Geom::infinity()" for catching some rounding errors
// These rounding errors might be caused by NRRects, see bug #1584301
- best_snapped_point.setSnapDistance(best_metric < 1e6 ? best_metric : NR_HUGE);
+ best_snapped_point.setSnapDistance(best_metric < 1e6 ? best_metric : Geom::infinity());
if (_snapindicator) {
if (best_snapped_point.getSnapped()) {
@@ -954,7 +954,6 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed(
_desktop->snapindicator->remove_snaptarget();
}
}
-
return best_snapped_point;
}
diff --git a/src/snapped-curve.cpp b/src/snapped-curve.cpp
index 25bde8105..4876b896d 100644
--- a/src/snapped-curve.cpp
+++ b/src/snapped-curve.cpp
@@ -20,7 +20,7 @@ Inkscape::SnappedCurve::SnappedCurve(Geom::Point const &snapped_point, int num_p
_tolerance = std::max(snapped_tolerance, 1.0);
_always_snap = always_snap;
_curve = curve;
- _second_distance = NR_HUGE;
+ _second_distance = Geom::infinity();
_second_tolerance = 1;
_second_always_snap = false;
_point = snapped_point;
@@ -36,11 +36,11 @@ Inkscape::SnappedCurve::SnappedCurve()
{
_num_path = 0;
_num_segm = 0;
- _distance = NR_HUGE;
+ _distance = Geom::infinity();
_tolerance = 1;
_always_snap = false;
_curve = NULL;
- _second_distance = NR_HUGE;
+ _second_distance = Geom::infinity();
_second_tolerance = 1;
_second_always_snap = false;
_point = Geom::Point(0,0);
@@ -67,8 +67,8 @@ Inkscape::SnappedPoint Inkscape::SnappedCurve::intersect(SnappedCurve const &cur
if (cs.size() > 0) {
// There might be multiple intersections: find the closest
- Geom::Coord best_dist = NR_HUGE;
- Geom::Point best_p = Geom::Point(NR_HUGE, NR_HUGE);
+ Geom::Coord best_dist = Geom::infinity();
+ Geom::Point best_p = Geom::Point(Geom::infinity(), Geom::infinity());
for (Geom::Crossings::const_iterator i = cs.begin(); i != cs.end(); i++) {
Geom::Point p_ix = this->_curve->pointAt((*i).ta);
Geom::Coord dist = Geom::distance(p_ix, p);
@@ -106,7 +106,7 @@ Inkscape::SnappedPoint Inkscape::SnappedCurve::intersect(SnappedCurve const &cur
}
// No intersection
- return SnappedPoint(Geom::Point(NR_HUGE, NR_HUGE), SNAPSOURCE_UNDEFINED, 0, SNAPTARGET_UNDEFINED, NR_HUGE, 0, false, false, false, false, NR_HUGE, 0, false);
+ return SnappedPoint(Geom::Point(Geom::infinity(), Geom::infinity()), SNAPSOURCE_UNDEFINED, 0, SNAPTARGET_UNDEFINED, Geom::infinity(), 0, false, false, false, false, Geom::infinity(), 0, false);
}
// search for the closest snapped line
diff --git a/src/snapped-line.cpp b/src/snapped-line.cpp
index 090eadf0a..525208f06 100644
--- a/src/snapped-line.cpp
+++ b/src/snapped-line.cpp
@@ -22,7 +22,7 @@ Inkscape::SnappedLineSegment::SnappedLineSegment(Geom::Point const &snapped_poin
_tolerance = std::max(snapped_tolerance, 1.0);
_always_snap = always_snap;
_at_intersection = false;
- _second_distance = NR_HUGE;
+ _second_distance = Geom::infinity();
_second_tolerance = 1;
_second_always_snap = false;
}
@@ -35,11 +35,11 @@ Inkscape::SnappedLineSegment::SnappedLineSegment()
_source = SNAPSOURCE_UNDEFINED;
_source_num = -1;
_target = SNAPTARGET_UNDEFINED;
- _distance = NR_HUGE;
+ _distance = Geom::infinity();
_tolerance = 1;
_always_snap = false;
_at_intersection = false;
- _second_distance = NR_HUGE;
+ _second_distance = Geom::infinity();
_second_tolerance = 1;
_second_always_snap = false;
}
@@ -85,7 +85,7 @@ Inkscape::SnappedPoint Inkscape::SnappedLineSegment::intersect(SnappedLineSegmen
}
// No intersection
- return SnappedPoint(Geom::Point(NR_HUGE, NR_HUGE), SNAPSOURCE_UNDEFINED, 0, SNAPTARGET_UNDEFINED, NR_HUGE, 0, false, false, false, false, NR_HUGE, 0, false);
+ return SnappedPoint(Geom::Point(Geom::infinity(), Geom::infinity()), SNAPSOURCE_UNDEFINED, 0, SNAPTARGET_UNDEFINED, Geom::infinity(), 0, false, false, false, false, Geom::infinity(), 0, false);
};
@@ -99,7 +99,7 @@ Inkscape::SnappedLine::SnappedLine(Geom::Point const &snapped_point, Geom::Coord
_distance = snapped_distance;
_tolerance = std::max(snapped_tolerance, 1.0);
_always_snap = always_snap;
- _second_distance = NR_HUGE;
+ _second_distance = Geom::infinity();
_second_tolerance = 1;
_second_always_snap = false;
_point = snapped_point;
@@ -113,10 +113,10 @@ Inkscape::SnappedLine::SnappedLine()
_source = SNAPSOURCE_UNDEFINED;
_source_num = -1;
_target = SNAPTARGET_UNDEFINED;
- _distance = NR_HUGE;
+ _distance = Geom::infinity();
_tolerance = 1;
_always_snap = false;
- _second_distance = NR_HUGE;
+ _second_distance = Geom::infinity();
_second_tolerance = 1;
_second_always_snap = false;
_point = Geom::Point(0,0);
@@ -168,7 +168,7 @@ Inkscape::SnappedPoint Inkscape::SnappedLine::intersect(SnappedLine const &line)
}
// No intersection
- return SnappedPoint(Geom::Point(NR_HUGE, NR_HUGE), SNAPSOURCE_UNDEFINED, 0, SNAPTARGET_UNDEFINED, NR_HUGE, 0, false, false, false, false, NR_HUGE, 0, false);
+ return SnappedPoint(Geom::Point(Geom::infinity(), Geom::infinity()), SNAPSOURCE_UNDEFINED, 0, SNAPTARGET_UNDEFINED, Geom::infinity(), 0, false, false, false, false, Geom::infinity(), 0, false);
}
// search for the closest snapped line segment
diff --git a/src/snapped-point.cpp b/src/snapped-point.cpp
index 52f0a7839..2db3d62e4 100644
--- a/src/snapped-point.cpp
+++ b/src/snapped-point.cpp
@@ -21,11 +21,11 @@ Inkscape::SnappedPoint::SnappedPoint(Geom::Point const &p, SnapSourceType const
_at_intersection = false;
_constrained_snap = constrained_snap;
_fully_constrained = fully_constrained;
- _second_distance = NR_HUGE;
+ _second_distance = Geom::infinity();
_second_tolerance = 1;
_second_always_snap = false;
_transformation = Geom::Point(1,1);
- _pointer_distance = NR_HUGE;
+ _pointer_distance = Geom::infinity();
}
Inkscape::SnappedPoint::SnappedPoint(Inkscape::SnapCandidatePoint const &p, SnapTargetType const &target, Geom::Coord const &d, Geom::Coord const &t, bool const &a, bool const &constrained_snap, bool const &fully_constrained)
@@ -37,11 +37,11 @@ Inkscape::SnappedPoint::SnappedPoint(Inkscape::SnapCandidatePoint const &p, Snap
_at_intersection = false;
_constrained_snap = constrained_snap;
_fully_constrained = fully_constrained;
- _second_distance = NR_HUGE;
+ _second_distance = Geom::infinity();
_second_tolerance = 1;
_second_always_snap = false;
_transformation = Geom::Point(1,1);
- _pointer_distance = NR_HUGE;
+ _pointer_distance = Geom::infinity();
_target_bbox = p.getTargetBBox();
}
@@ -53,7 +53,7 @@ Inkscape::SnappedPoint::SnappedPoint(Geom::Point const &p, SnapSourceType const
// tolerance should never be smaller than 1 px, as it is used for normalization in
// isOtherSnapBetter. We don't want a division by zero.
_transformation = Geom::Point(1,1);
- _pointer_distance = NR_HUGE;
+ _pointer_distance = Geom::infinity();
_target_bbox = Geom::OptRect();
}
@@ -66,14 +66,14 @@ Inkscape::SnappedPoint::SnappedPoint()
_at_intersection = false;
_constrained_snap = false;
_fully_constrained = false;
- _distance = NR_HUGE;
+ _distance = Geom::infinity();
_tolerance = 1;
_always_snap = false;
- _second_distance = NR_HUGE;
+ _second_distance = Geom::infinity();
_second_tolerance = 1;
_second_always_snap = false;
_transformation = Geom::Point(1,1);
- _pointer_distance = NR_HUGE;
+ _pointer_distance = Geom::infinity();
_target_bbox = Geom::OptRect();
}
@@ -85,14 +85,14 @@ Inkscape::SnappedPoint::SnappedPoint(Geom::Point const &p)
_target = SNAPTARGET_UNDEFINED,
_at_intersection = false;
_fully_constrained = false;
- _distance = NR_HUGE;
+ _distance = Geom::infinity();
_tolerance = 1;
_always_snap = false;
- _second_distance = NR_HUGE;
+ _second_distance = Geom::infinity();
_second_tolerance = 1;
_second_always_snap = false;
_transformation = Geom::Point(1,1);
- _pointer_distance = NR_HUGE;
+ _pointer_distance = Geom::infinity();
_target_bbox = Geom::OptRect();
}
@@ -152,7 +152,7 @@ bool Inkscape::SnappedPoint::isOtherSnapBetter(Inkscape::SnappedPoint const &oth
// When accounting for the distance to the mouse pointer, then at least one of the snapped points should
// have that distance set. If not, then this is a bug. Either "weighted" must be set to false, or the
// mouse pointer distance must be set.
- g_assert(dist_pointer_this != NR_HUGE || dist_pointer_other != NR_HUGE);
+ g_assert(dist_pointer_this != Geom::infinity() || dist_pointer_other != Geom::infinity());
// The snap distance will always be smaller than the tolerance set for the snapper. The pointer distance can
// however be very large. To compare these in a fair way, we will have to normalize these metrics first
// The closest pointer distance will be normalized to 1.0; the other one will be > 1.0
@@ -195,7 +195,7 @@ bool Inkscape::SnappedPoint::isOtherSnapBetter(Inkscape::SnappedPoint const &oth
// or, if it's just as close then consider the second distance ...
bool c5a = (dist_other == dist_this);
- bool c5b = (other_one.getSecondSnapDistance() < getSecondSnapDistance()) && (getSecondSnapDistance() < NR_HUGE);
+ bool c5b = (other_one.getSecondSnapDistance() < getSecondSnapDistance()) && (getSecondSnapDistance() < Geom::infinity());
// ... or prefer free snaps over constrained snaps
bool c5c = !other_one.getConstrainedSnap() && getConstrainedSnap();
diff --git a/src/snapped-point.h b/src/snapped-point.h
index b2a9fa1ce..7dc6edeca 100644
--- a/src/snapped-point.h
+++ b/src/snapped-point.h
@@ -14,7 +14,6 @@
#include <vector>
#include <list>
-#include <libnr/nr-values.h> //Because of NR_HUGE
#include <2geom/geom.h>
#include <snap-candidate.h>
@@ -64,7 +63,7 @@ public:
bool getAtIntersection() const {return _at_intersection;}
bool getFullyConstrained() const {return _fully_constrained;}
bool getConstrainedSnap() const {return _constrained_snap;}
- bool getSnapped() const {return _distance < NR_HUGE;}
+ bool getSnapped() const {return _distance < Geom::infinity();}
Geom::Point getTransformation() const {return _transformation;}
void setTransformation(Geom::Point const t) {_transformation = t;}
void setTarget(SnapTargetType const target) {_target = target;}
diff --git a/src/sp-clippath.cpp b/src/sp-clippath.cpp
index 89e140f12..147ece167 100644
--- a/src/sp-clippath.cpp
+++ b/src/sp-clippath.cpp
@@ -25,7 +25,6 @@
#include "document-private.h"
#include "sp-item.h"
-#include "libnr/nr-matrix-ops.h"
#include <2geom/transforms.h>
#include "sp-clippath.h"
@@ -286,10 +285,10 @@ void SPClipPath::setBBox(unsigned int key, NRRect *bbox)
{
for (SPClipPathView *v = display; v != NULL; v = v->next) {
if (v->key == key) {
- if (!NR_DF_TEST_CLOSE(v->bbox.x0, bbox->x0, NR_EPSILON) ||
- !NR_DF_TEST_CLOSE(v->bbox.y0, bbox->y0, NR_EPSILON) ||
- !NR_DF_TEST_CLOSE(v->bbox.x1, bbox->x1, NR_EPSILON) ||
- !NR_DF_TEST_CLOSE(v->bbox.y1, bbox->y1, NR_EPSILON)) {
+ if (!Geom::are_near(v->bbox.x0, bbox->x0) ||
+ !Geom::are_near(v->bbox.y0, bbox->y0) ||
+ !Geom::are_near(v->bbox.x1, bbox->x1) ||
+ !Geom::are_near(v->bbox.y1, bbox->y1)) {
v->bbox = *bbox;
}
break;
diff --git a/src/sp-conn-end.cpp b/src/sp-conn-end.cpp
index d11eca4c7..538638d7a 100644
--- a/src/sp-conn-end.cpp
+++ b/src/sp-conn-end.cpp
@@ -4,7 +4,6 @@
#include <limits>
#include "display/curve.h"
-#include "libnr/nr-matrix-fns.h"
#include "xml/repr.h"
#include "sp-conn-end.h"
#include "sp-path.h"
diff --git a/src/sp-ellipse.cpp b/src/sp-ellipse.cpp
index cb8c1699b..cf5927fc8 100644
--- a/src/sp-ellipse.cpp
+++ b/src/sp-ellipse.cpp
@@ -17,8 +17,6 @@
# include "config.h"
#endif
-
-#include "libnr/nr-matrix-fns.h"
#include "svg/svg.h"
#include "svg/path-string.h"
#include "xml/repr.h"
diff --git a/src/sp-filter-fns.h b/src/sp-filter-fns.h
deleted file mode 100644
index a5f08a41a..000000000
--- a/src/sp-filter-fns.h
+++ /dev/null
@@ -1,53 +0,0 @@
-#ifndef SEEN_SP_FILTER_FNS_H
-#define SEEN_SP_FILTER_FNS_H
-
-/** \file
- * Macros and fn declarations related to filters.
- */
-
-#include <glib/gtypes.h>
-#include <glib-object.h>
-#include "libnr/nr-forward.h"
-#include "sp-filter-units.h"
-#include "sp-filter-primitive.h"
-
-class SPFilter;
-
-namespace Inkscape {
-namespace XML {
-class Node;
-}
-}
-
-#define SP_TYPE_FILTER (sp_filter_get_type())
-#define SP_FILTER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SP_TYPE_FILTER, SPFilter))
-#define SP_FILTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), SP_TYPE_FILTER, SPFilterClass))
-#define SP_IS_FILTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), SP_TYPE_FILTER))
-#define SP_IS_FILTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), SP_TYPE_FILTER))
-
-#define SP_FILTER_FILTER_UNITS(f) (SP_FILTER(f)->filterUnits)
-#define SP_FILTER_PRIMITIVE_UNITS(f) (SP_FILTER(f)->primitiveUnits)
-
-GType sp_filter_get_type();
-
-//need to define function
-void sp_filter_set_filter_units(SPFilter *filter, SPFilterUnits filterUnits);
-//need to define function
-void sp_filter_set_primitive_units(SPFilter *filter, SPFilterUnits filterUnits);
-
-SPFilterPrimitive *add_primitive(SPFilter *filter, SPFilterPrimitive *primitive);
-SPFilterPrimitive *get_primitive(SPFilter *filter, int index);
-
-
-#endif /* !SEEN_SP_FILTER_FNS_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-filter-primitive.h b/src/sp-filter-primitive.h
index 8922ac20a..60104047e 100644
--- a/src/sp-filter-primitive.h
+++ b/src/sp-filter-primitive.h
@@ -15,9 +15,7 @@
*/
#include "sp-object.h"
-#include "display/nr-filter.h"
-#include "display/nr-filter-primitive.h"
-#include "display/nr-filter-types.h"
+#include "svg/svg-length.h"
#define SP_TYPE_FILTER_PRIMITIVE (sp_filter_primitive_get_type ())
#define SP_FILTER_PRIMITIVE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SP_TYPE_FILTER_PRIMITIVE, SPFilterPrimitive))
@@ -27,6 +25,12 @@
class SPFilterPrimitive;
class SPFilterPrimitiveClass;
+namespace Inkscape {
+namespace Filters {
+class Filter;
+class FilterPrimitive;
+} }
+
struct SPFilterPrimitive : public SPObject {
int image_in, image_out;
diff --git a/src/sp-filter-reference.cpp b/src/sp-filter-reference.cpp
index 41db865fc..57600ad39 100644
--- a/src/sp-filter-reference.cpp
+++ b/src/sp-filter-reference.cpp
@@ -1,3 +1,4 @@
+#include "sp-filter.h"
#include "sp-filter-reference.h"
bool
diff --git a/src/sp-filter-reference.h b/src/sp-filter-reference.h
index 2e1d4648e..168ec1c1d 100644
--- a/src/sp-filter-reference.h
+++ b/src/sp-filter-reference.h
@@ -2,8 +2,10 @@
#define SEEN_SP_FILTER_REFERENCE_H
#include "uri-references.h"
-#include "sp-filter-fns.h"
+
class SPObject;
+class SPDocument;
+class SPFilter;
class SPFilterReference : public Inkscape::URIReference {
public:
@@ -18,7 +20,6 @@ protected:
virtual bool _acceptObject(SPObject *obj) const;
};
-
#endif /* !SEEN_SP_FILTER_REFERENCE_H */
/*
diff --git a/src/sp-filter.cpp b/src/sp-filter.cpp
index fd4319320..a7c1aa1fb 100644
--- a/src/sp-filter.cpp
+++ b/src/sp-filter.cpp
@@ -28,6 +28,7 @@ using std::pair;
#include "document.h"
#include "sp-filter.h"
#include "sp-filter-reference.h"
+#include "sp-filter-primitive.h"
#include "uri.h"
#include "xml/repr.h"
#include <cstring>
diff --git a/src/sp-filter.h b/src/sp-filter.h
index 45586f1fb..4ba04ecf0 100644
--- a/src/sp-filter.h
+++ b/src/sp-filter.h
@@ -1,10 +1,6 @@
-#ifndef SP_FILTER_H_SEEN
-#define SP_FILTER_H_SEEN
-
/** \file
- * SVG <filter> implementation, see sp-filter.cpp.
- */
-/*
+ * SVG <filter> element
+ *//*
* Authors:
* Hugo Rodrigues <haa.rodrigues@gmail.com>
* Niko Kiirala <niko@kiirala.com>
@@ -13,6 +9,8 @@
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
+#ifndef SP_FILTER_H_SEEN
+#define SP_FILTER_H_SEEN
#include <map>
@@ -21,18 +19,24 @@
#include "number-opt-number.h"
#include "sp-object.h"
#include "sp-filter-units.h"
-#include "sp-filter-fns.h"
#include "svg/svg-length.h"
-#include "display/nr-filter.h"
-/* Filter base class */
+#define SP_TYPE_FILTER (sp_filter_get_type())
+#define SP_FILTER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SP_TYPE_FILTER, SPFilter))
+#define SP_FILTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), SP_TYPE_FILTER, SPFilterClass))
+#define SP_IS_FILTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), SP_TYPE_FILTER))
+#define SP_IS_FILTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), SP_TYPE_FILTER))
-/* MACROS DEFINED IN FILE sp-filter-fns.h */
+#define SP_FILTER_FILTER_UNITS(f) (SP_FILTER(f)->filterUnits)
+#define SP_FILTER_PRIMITIVE_UNITS(f) (SP_FILTER(f)->primitiveUnits)
-struct SPFilterReference;
+namespace Inkscape {
+namespace Filters {
+class Filter;
+} }
-class SPFilter;
-class SPFilterClass;
+struct SPFilterReference;
+class SPFilterPrimitive;
struct ltstr {
bool operator()(const char* s1, const char* s2) const;
@@ -70,34 +74,31 @@ struct SPFilterClass {
SPObjectClass parent_class;
};
-/*
- * Initializes the given Inkscape::Filters::Filter object as a renderer for this
- * SPFilter object.
- */
+GType sp_filter_get_type();
+
+void sp_filter_set_filter_units(SPFilter *filter, SPFilterUnits filterUnits);
+void sp_filter_set_primitive_units(SPFilter *filter, SPFilterUnits filterUnits);
+SPFilterPrimitive *add_primitive(SPFilter *filter, SPFilterPrimitive *primitive);
+SPFilterPrimitive *get_primitive(SPFilter *filter, int index);
+
+/* Initializes the given Inkscape::Filters::Filter object as a renderer for this
+ * SPFilter object. */
void sp_filter_build_renderer(SPFilter *sp_filter, Inkscape::Filters::Filter *nr_filter);
-/*
- * Returns the number of filter primitives in this SPFilter object.
- */
+/// Returns the number of filter primitives in this SPFilter object.
int sp_filter_primitive_count(SPFilter *filter);
-/**
- * Returns a slot number for given image name, or -1 for unknown name.
- */
+/// Returns a slot number for given image name, or -1 for unknown name.
int sp_filter_get_image_name(SPFilter *filter, gchar const *name);
-/**
- * Returns slot number for given image name, even if it's unknown.
- */
+
+/// Returns slot number for given image name, even if it's unknown.
int sp_filter_set_image_name(SPFilter *filter, gchar const *name);
-/**
- * Finds image name based on it's slot number. Returns 0 for unknown slot
- * numbers.
- */
+
+/** 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);
-/*
- * Returns a result image name that is not in use inside this filter.
- */
+/// Returns a result image name that is not in use inside this filter.
Glib::ustring sp_filter_get_new_result_name(SPFilter *filter);
#endif /* !SP_FILTER_H_SEEN */
diff --git a/src/sp-flowdiv.cpp b/src/sp-flowdiv.cpp
index 4dfdcbb9a..5cb258735 100644
--- a/src/sp-flowdiv.cpp
+++ b/src/sp-flowdiv.cpp
@@ -5,7 +5,6 @@
# include "config.h"
#endif
-#include "libnr/nr-matrix-ops.h"
#include "xml/repr.h"
//#include "svg/svg.h"
diff --git a/src/sp-gaussian-blur.h b/src/sp-gaussian-blur.h
deleted file mode 100644
index 9b6b9aa9b..000000000
--- a/src/sp-gaussian-blur.h
+++ /dev/null
@@ -1,45 +0,0 @@
-#ifndef SP_GAUSSIANBLUR_H_SEEN
-#define SP_GAUSSIANBLUR_H_SEEN
-
-/** \file
- * SVG <gaussianBlur> implementation, see sp-gaussianBlur.cpp.
- */
-/*
- * Authors:
- * Hugo Rodrigues <haa.rodrigues@gmail.com>
- *
- * Copyright (C) 2006 Hugo Rodrigues
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#include "sp-filter.h"
-#include "sp-gaussian-blur-fns.h"
-
-/* GaussianBlur base class */
-class SPGaussianBlurClass;
-
-struct SPGaussianBlur : public SPFilterPrimitive {
- /** stdDeviation attribute */
- NumberOptNumber stdDeviation;
-};
-
-struct SPGaussianBlurClass {
- SPFilterPrimitiveClass parent_class;
-};
-
-GType sp_gaussianBlur_get_type();
-
-
-#endif /* !SP_GAUSSIANBLUR_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-gradient-fns.h b/src/sp-gradient-fns.h
index be2caf5b0..5fb939905 100644
--- a/src/sp-gradient-fns.h
+++ b/src/sp-gradient-fns.h
@@ -19,8 +19,7 @@ SPGradientSpread sp_gradient_get_spread (SPGradient *gradient);
void sp_gradient_repr_write_vector(SPGradient *gr);
void sp_gradient_repr_clear_vector(SPGradient *gr);
-void sp_gradient_render_vector_block_rgba(SPGradient *gr, guchar *px, gint w, gint h, gint rs, gint pos, gint span, bool horizontal);
-void sp_gradient_render_vector_block_rgb(SPGradient *gr, guchar *px, gint w, gint h, gint rs, gint pos, gint span, bool horizontal);
+cairo_pattern_t *sp_gradient_create_preview_pattern(SPGradient *gradient, double width);
/** Transforms to/from gradient position space in given environment */
Geom::Affine sp_gradient_get_g2d_matrix(SPGradient const *gr, Geom::Affine const &ctm,
diff --git a/src/sp-gradient.cpp b/src/sp-gradient.cpp
index 82d62547a..3aa14dc45 100644
--- a/src/sp-gradient.cpp
+++ b/src/sp-gradient.cpp
@@ -23,16 +23,12 @@
#include <cstring>
#include <string>
-#include <libnr/nr-matrix-fns.h>
-#include <libnr/nr-matrix-ops.h>
-#include <libnr/nr-matrix-scale-ops.h>
#include <2geom/transforms.h>
#include <sigc++/functors/ptr_fun.h>
#include <sigc++/adaptors/bind.h>
-#include "libnr/nr-gradient.h"
-#include "libnr/nr-pixops.h"
+#include "display/cairo-utils.h"
#include "svg/svg.h"
#include "svg/svg-color.h"
#include "svg/css-ostringstream.h"
@@ -360,7 +356,7 @@ void SPGradientImpl::classInit(SPGradientClass *klass)
{
SPObjectClass *sp_object_class = (SPObjectClass *) klass;
- gradient_parent_class = SP_PAINT_SERVER_CLASS( g_type_class_ref(SP_TYPE_PAINT_SERVER) );
+ gradient_parent_class = (SPPaintServerClass *)g_type_class_ref(SP_TYPE_PAINT_SERVER);
sp_object_class->build = SPGradientImpl::build;
sp_object_class->release = SPGradientImpl::release;
@@ -399,8 +395,6 @@ void SPGradientImpl::init(SPGradient *gr)
gr->vector.built = false;
gr->vector.stops.clear();
- gr->color = NULL;
-
new (&gr->modified_connection) sigc::connection();
}
@@ -460,11 +454,6 @@ void SPGradientImpl::release(SPObject *object)
gradient->ref = NULL;
}
- if (gradient->color) {
- g_free(gradient->color);
- gradient->color = NULL;
- }
-
gradient->modified_connection.~connection();
if (((SPObjectClass *) gradient_parent_class)->release)
@@ -662,7 +651,7 @@ void SPGradientImpl::modified(SPObject *object, guint flags)
}
if (flags & SP_OBJECT_STYLE_MODIFIED_FLAG) {
- gr->ensureColors();
+ gr->ensureVector();
}
if (flags & SP_OBJECT_MODIFIED_FLAG) flags |= SP_OBJECT_PARENT_MODIFIED_FLAG;
@@ -1006,12 +995,6 @@ bool SPGradient::invalidateVector()
{
bool ret = false;
- if (color != NULL) {
- g_free(color);
- color = NULL;
- ret = true;
- }
-
if (vector.built) {
vector.built = false;
vector.stops.clear();
@@ -1119,303 +1102,6 @@ void SPGradient::rebuildVector()
vector.built = true;
}
-/**
- * The gradient's color array is newly created and set up from vector.
- * Also, the gradient's color_grayscale is created.
- */
-void SPGradient::ensureColors()
-{
- if (!vector.built) {
- rebuildVector();
- }
- g_return_if_fail(!vector.stops.empty());
-
- /// \todo Where is the memory freed?
- if (!color) {
- color = g_new(guchar, 4 * NCOLORS);
- }
- if (!color_grayscale) {
- color_grayscale = g_new(guchar, 4 * NCOLORS);
- }
-
- // This assumes that vector is a zero-order B-spline (box function) approximation of the "true" gradient.
- // This means that the "true" gradient must be prefiltered using a zero order B-spline and then sampled.
- // Furthermore, the first element corresponds to offset="0" and the last element to offset="1".
-
- double remainder[4] = {0,0,0,0};
- double remainder_for_end[4] = {0,0,0,0}; // Used at the end
- switch(spread) {
- case SP_GRADIENT_SPREAD_PAD:
- remainder[0] = 0.5*vector.stops[0].color.v.c[0]; // Half of the first cell uses the color of the first stop
- remainder[1] = 0.5*vector.stops[0].color.v.c[1];
- remainder[2] = 0.5*vector.stops[0].color.v.c[2];
- remainder[3] = 0.5*vector.stops[0].opacity;
- remainder_for_end[0] = 0.5*vector.stops[vector.stops.size() - 1].color.v.c[0]; // Half of the first cell uses the color of the last stop
- remainder_for_end[1] = 0.5*vector.stops[vector.stops.size() - 1].color.v.c[1];
- remainder_for_end[2] = 0.5*vector.stops[vector.stops.size() - 1].color.v.c[2];
- remainder_for_end[3] = 0.5*vector.stops[vector.stops.size() - 1].opacity;
- break;
- case SP_GRADIENT_SPREAD_REFLECT:
- case SP_GRADIENT_SPREAD_REPEAT:
- // These two are handled differently, see below.
- break;
- default:
- g_error("Spread type not supported!");
- };
- for (unsigned int i = 0; i < vector.stops.size() - 1; i++) {
- double r0 = vector.stops[i].color.v.c[0];
- double g0 = vector.stops[i].color.v.c[1];
- double b0 = vector.stops[i].color.v.c[2];
- double a0 = vector.stops[i].opacity;
- double r1 = vector.stops[i+1].color.v.c[0];
- double g1 = vector.stops[i+1].color.v.c[1];
- double b1 = vector.stops[i+1].color.v.c[2];
- double a1 = vector.stops[i+1].opacity;
- double o0 = vector.stops[i].offset * (NCOLORS-1);
- double o1 = vector.stops[i + 1].offset * (NCOLORS-1);
- unsigned int ob = (unsigned int) floor(o0+.5); // These are the first and last element that might be affected by this interval.
- unsigned int oe = (unsigned int) floor(o1+.5); // These need to be computed the same to ensure that ob will be covered by the next interval if oe==ob
-
- if (oe == ob) {
- // Simple case, this interval starts and stops within one cell
- // The contribution of this interval is:
- // (o1-o0)*(c(o0)+c(o1))/2
- // = (o1-o0)*(c0+c1)/2
- double dt = 0.5*(o1-o0);
- remainder[0] += dt*(r0 + r1);
- remainder[1] += dt*(g0 + g1);
- remainder[2] += dt*(b0 + b1);
- remainder[3] += dt*(a0 + a1);
- } else {
- // First compute colors for the cells which are fully covered by the current interval.
- // The prefiltered values are equal to the midpoint of each cell here.
- // f = (j-o0)/(o1-o0)
- // = j*(1/(o1-o0)) - o0/(o1-o0)
- double f = (ob-o0) / (o1-o0);
- double df = 1. / (o1-o0);
- for (unsigned int j = ob+1; j < oe; j++) {
- f += df;
- color[4 * j + 0] = (unsigned char) floor(255*(r0 + f*(r1-r0)) + .5);
- color[4 * j + 1] = (unsigned char) floor(255*(g0 + f*(g1-g0)) + .5);
- color[4 * j + 2] = (unsigned char) floor(255*(b0 + f*(b1-b0)) + .5);
- color[4 * j + 3] = (unsigned char) floor(255*(a0 + f*(a1-a0)) + .5);
- }
-
- // Now handle the beginning
- // The contribution of the last point is already in remainder.
- // The contribution of this point is:
- // (ob+.5-o0)*(c(o0)+c(ob+.5))/2
- // = (ob+.5-o0)*c((o0+ob+.5)/2)
- // = (ob+.5-o0)*(c0+((o0+ob+.5)/2-o0)*df*(c1-c0))
- // = (ob+.5-o0)*(c0+(ob+.5-o0)*df*(c1-c0)/2)
- double dt = ob+.5-o0;
- f = 0.5*dt*df;
- if (ob==0 && spread==SP_GRADIENT_SPREAD_REFLECT) {
- // The first half of the first cell is just a mirror image of the second half, so simply multiply it by 2.
- color[4 * ob + 0] = (unsigned char) floor(2*255*(remainder[0] + dt*(r0 + f*(r1-r0))) + .5);
- color[4 * ob + 1] = (unsigned char) floor(2*255*(remainder[1] + dt*(g0 + f*(g1-g0))) + .5);
- color[4 * ob + 2] = (unsigned char) floor(2*255*(remainder[2] + dt*(b0 + f*(b1-b0))) + .5);
- color[4 * ob + 3] = (unsigned char) floor(2*255*(remainder[3] + dt*(a0 + f*(a1-a0))) + .5);
- } else if (ob==0 && spread==SP_GRADIENT_SPREAD_REPEAT) {
- // The first cell is the same as the last cell, so save whatever is in the second half here and deal with the rest later.
- remainder_for_end[0] = remainder[0] + dt*(r0 + f*(r1-r0));
- remainder_for_end[1] = remainder[1] + dt*(g0 + f*(g1-g0));
- remainder_for_end[2] = remainder[2] + dt*(b0 + f*(b1-b0));
- remainder_for_end[3] = remainder[3] + dt*(a0 + f*(a1-a0));
- } else {
- // The first half of the cell was already in remainder.
- color[4 * ob + 0] = (unsigned char) floor(255*(remainder[0] + dt*(r0 + f*(r1-r0))) + .5);
- color[4 * ob + 1] = (unsigned char) floor(255*(remainder[1] + dt*(g0 + f*(g1-g0))) + .5);
- color[4 * ob + 2] = (unsigned char) floor(255*(remainder[2] + dt*(b0 + f*(b1-b0))) + .5);
- color[4 * ob + 3] = (unsigned char) floor(255*(remainder[3] + dt*(a0 + f*(a1-a0))) + .5);
- }
-
- // Now handle the end, which should end up in remainder
- // The contribution of this point is:
- // (o1-oe+.5)*(c(o1)+c(oe-.5))/2
- // = (o1-oe+.5)*c((o1+oe-.5)/2)
- // = (o1-oe+.5)*(c0+((o1+oe-.5)/2-o0)*df*(c1-c0))
- dt = o1-oe+.5;
- f = (0.5*(o1+oe-.5)-o0)*df;
- remainder[0] = dt*(r0 + f*(r1-r0));
- remainder[1] = dt*(g0 + f*(g1-g0));
- remainder[2] = dt*(b0 + f*(b1-b0));
- remainder[3] = dt*(a0 + f*(a1-a0));
- }
- }
- switch(spread) {
- case SP_GRADIENT_SPREAD_PAD:
- color[4 * (NCOLORS-1) + 0] = (unsigned char) floor(255*(remainder[0]+remainder_for_end[0]) + .5);
- color[4 * (NCOLORS-1) + 1] = (unsigned char) floor(255*(remainder[1]+remainder_for_end[1]) + .5);
- color[4 * (NCOLORS-1) + 2] = (unsigned char) floor(255*(remainder[2]+remainder_for_end[2]) + .5);
- color[4 * (NCOLORS-1) + 3] = (unsigned char) floor(255*(remainder[3]+remainder_for_end[3]) + .5);
- break;
- case SP_GRADIENT_SPREAD_REFLECT:
- // The second half is the same as the first half, so multiply by 2.
- color[4 * (NCOLORS-1) + 0] = (unsigned char) floor(2*255*remainder[0] + .5);
- color[4 * (NCOLORS-1) + 1] = (unsigned char) floor(2*255*remainder[1] + .5);
- color[4 * (NCOLORS-1) + 2] = (unsigned char) floor(2*255*remainder[2] + .5);
- color[4 * (NCOLORS-1) + 3] = (unsigned char) floor(2*255*remainder[3] + .5);
- break;
- case SP_GRADIENT_SPREAD_REPEAT:
- // The second half is the same as the second half of the first cell (which was saved in remainder_for_end).
- color[0] = color[4 * (NCOLORS-1) + 0] = (unsigned char) floor(255*(remainder[0]+remainder_for_end[0]) + .5);
- color[1] = color[4 * (NCOLORS-1) + 1] = (unsigned char) floor(255*(remainder[1]+remainder_for_end[1]) + .5);
- color[2] = color[4 * (NCOLORS-1) + 2] = (unsigned char) floor(255*(remainder[2]+remainder_for_end[2]) + .5);
- color[3] = color[4 * (NCOLORS-1) + 3] = (unsigned char) floor(255*(remainder[3]+remainder_for_end[3]) + .5);
- break;
- }
-
- // Fill color_grayscale array
- for (unsigned j = 0; j < NCOLORS; j++) {
- guint32 rgba = Grayscale::process(color[4 * j + 0], color[4 * j + 1], color[4 * j + 2], color[4 * j + 3]);
- color_grayscale[4 * j + 0] = SP_RGBA32_R_U(rgba);
- color_grayscale[4 * j + 1] = SP_RGBA32_G_U(rgba);
- color_grayscale[4 * j + 2] = SP_RGBA32_B_U(rgba);
- color_grayscale[4 * j + 3] = SP_RGBA32_A_U(rgba);
- }
-}
-
-/**
- * Renders gradient vector to buffer as line.
- *
- * RGB buffer background should be set up beforehand.
- *
- * @param len,width,height,rowstride Buffer parameters (1 or 2 dimensional).
- * @param span Full integer width of requested gradient.
- * @param pos Buffer starting position in span.
- */
-static void
-sp_gradient_render_vector_line_rgba(SPGradient *const gradient, guchar *buf,
- gint const len, gint const pos, gint const span)
-{
- g_return_if_fail(gradient != NULL);
- g_return_if_fail(SP_IS_GRADIENT(gradient));
- g_return_if_fail(buf != NULL);
- g_return_if_fail(len > 0);
- g_return_if_fail(pos >= 0);
- g_return_if_fail(pos + len <= span);
- g_return_if_fail(span > 0);
-
- if (!gradient->color) {
- gradient->ensureColors();
- }
-
- gint idx = (pos * 1024 << 8) / span;
- gint didx = (1024 << 8) / span;
-
- bool grayscale = false; // this rendering is for UI items, like the gradient edit dialog
- if (grayscale) {
- for (gint x = 0; x < len; x++) {
- guchar luminance = Grayscale::luminance( gradient->color[4 * (idx >> 8)], gradient->color[4 * (idx >> 8) + 1], gradient->color[4 * (idx >> 8) + 2] );
- *buf++ = luminance;
- *buf++ = luminance;
- *buf++ = luminance;
- *buf++ = gradient->color[4 * (idx >> 8) + 3];
- idx += didx;
- }
- } else {
- for (gint x = 0; x < len; x++) {
- /// \todo Can this be done with 4 byte copies?
- *buf++ = gradient->color[4 * (idx >> 8)];
- *buf++ = gradient->color[4 * (idx >> 8) + 1];
- *buf++ = gradient->color[4 * (idx >> 8) + 2];
- *buf++ = gradient->color[4 * (idx >> 8) + 3];
- idx += didx;
- }
- }
-}
-
-/**
- * Render rectangular RGBA area from gradient vector.
- */
-void
-sp_gradient_render_vector_block_rgba(SPGradient *const gradient, guchar *buf,
- gint const width, gint const height, gint const rowstride,
- gint const pos, gint const span, bool const horizontal)
-{
- g_return_if_fail(gradient != NULL);
- g_return_if_fail(SP_IS_GRADIENT(gradient));
- g_return_if_fail(buf != NULL);
- g_return_if_fail(width > 0);
- g_return_if_fail(height > 0);
- g_return_if_fail(pos >= 0);
- g_return_if_fail((horizontal && (pos + width <= span)) || (!horizontal && (pos + height <= span)));
- g_return_if_fail(span > 0);
-
- if (horizontal) {
- sp_gradient_render_vector_line_rgba(gradient, buf, width, pos, span);
- for (gint y = 1; y < height; y++) {
- memcpy(buf + y * rowstride, buf, 4 * width);
- }
- } else {
- guchar *tmp = (guchar *)alloca(4 * height);
- sp_gradient_render_vector_line_rgba(gradient, tmp, height, pos, span);
- for (gint y = 0; y < height; y++) {
- guchar *b = buf + y * rowstride;
- for (gint x = 0; x < width; x++) {
- *b++ = tmp[0];
- *b++ = tmp[1];
- *b++ = tmp[2];
- *b++ = tmp[3];
- }
- tmp += 4;
- }
- }
-}
-
-/**
- * Render rectangular RGB area from gradient vector.
- */
-void
-sp_gradient_render_vector_block_rgb(SPGradient *gradient, guchar *buf,
- gint const width, gint const height, gint const /*rowstride*/,
- gint const pos, gint const span, bool const horizontal)
-{
- g_return_if_fail(gradient != NULL);
- g_return_if_fail(SP_IS_GRADIENT(gradient));
- g_return_if_fail(buf != NULL);
- g_return_if_fail(width > 0);
- g_return_if_fail(height > 0);
- g_return_if_fail(pos >= 0);
- g_return_if_fail((horizontal && (pos + width <= span)) || (!horizontal && (pos + height <= span)));
- g_return_if_fail(span > 0);
-
- if (horizontal) {
- guchar *tmp = (guchar*)alloca(4 * width);
- sp_gradient_render_vector_line_rgba(gradient, tmp, width, pos, span);
- for (gint y = 0; y < height; y++) {
- guchar *t = tmp;
- for (gint x = 0; x < width; x++) {
- gint a = t[3];
- gint fc = (t[0] - buf[0]) * a;
- buf[0] = buf[0] + ((fc + (fc >> 8) + 0x80) >> 8);
- fc = (t[1] - buf[1]) * a;
- buf[1] = buf[1] + ((fc + (fc >> 8) + 0x80) >> 8);
- fc = (t[2] - buf[2]) * a;
- buf[2] = buf[2] + ((fc + (fc >> 8) + 0x80) >> 8);
- buf += 3;
- t += 4;
- }
- }
- } else {
- guchar *tmp = (guchar*)alloca(4 * height);
- sp_gradient_render_vector_line_rgba(gradient, tmp, height, pos, span);
- for (gint y = 0; y < height; y++) {
- guchar *t = tmp + 4 * y;
- for (gint x = 0; x < width; x++) {
- gint a = t[3];
- gint fc = (t[0] - buf[0]) * a;
- buf[0] = buf[0] + ((fc + (fc >> 8) + 0x80) >> 8);
- fc = (t[1] - buf[1]) * a;
- buf[1] = buf[1] + ((fc + (fc >> 8) + 0x80) >> 8);
- fc = (t[2] - buf[2]) * a;
- buf[2] = buf[2] + ((fc + (fc >> 8) + 0x80) >> 8);
- }
- }
- }
-}
-
Geom::Affine
sp_gradient_get_g2d_matrix(SPGradient const *gr, Geom::Affine const &ctm, Geom::Rect const &bbox)
{
@@ -1460,21 +1146,6 @@ sp_gradient_set_gs2d_matrix(SPGradient *gr, Geom::Affine const &ctm,
* Linear Gradient
*/
-class SPLGPainter;
-
-/// A context with linear gradient, painter, and gradient renderer.
-struct SPLGPainter {
- SPPainter painter;
- SPLinearGradient *lg;
-
- NRLGradientRenderer lgr;
-
- static SPPainter * painter_new(SPPaintServer *ps,
- Geom::Affine const &full_transform,
- Geom::Affine const &parent_transform,
- NRRect const *bbox);
-};
-
static void sp_lineargradient_class_init(SPLinearGradientClass *klass);
static void sp_lineargradient_init(SPLinearGradient *lg);
@@ -1484,10 +1155,7 @@ static void sp_lineargradient_build(SPObject *object,
static void sp_lineargradient_set(SPObject *object, unsigned key, gchar const *value);
static Inkscape::XML::Node *sp_lineargradient_write(SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr,
guint flags);
-
-static void sp_lineargradient_painter_free(SPPaintServer *ps, SPPainter *painter);
-
-static void sp_lg_fill(SPPainter *painter, NRPixBlock *pb);
+static cairo_pattern_t *sp_lineargradient_create_pattern(SPPaintServer *ps, cairo_t *ct, NRRect const *bbox, double opacity);
static SPGradientClass *lg_parent_class;
@@ -1520,7 +1188,7 @@ sp_lineargradient_get_type()
static void sp_lineargradient_class_init(SPLinearGradientClass *klass)
{
SPObjectClass *sp_object_class = (SPObjectClass *) klass;
- SPPaintServerClass *ps_class = SP_PAINT_SERVER_CLASS( klass );
+ SPPaintServerClass *ps_class = (SPPaintServerClass *) klass;
lg_parent_class = (SPGradientClass*)g_type_class_ref(SP_TYPE_GRADIENT);
@@ -1528,8 +1196,7 @@ static void sp_lineargradient_class_init(SPLinearGradientClass *klass)
sp_object_class->set = sp_lineargradient_set;
sp_object_class->write = sp_lineargradient_write;
- ps_class->painter_new = SPLGPainter::painter_new;
- ps_class->painter_free = sp_lineargradient_painter_free;
+ ps_class->pattern_new = sp_lineargradient_create_pattern;
}
/**
@@ -1619,86 +1286,6 @@ sp_lineargradient_write(SPObject *object, Inkscape::XML::Document *xml_doc, Inks
}
/**
- * Create linear gradient context.
- *
- * Basically we have to deal with transformations
- *
- * 1) color2norm - maps point in (0,NCOLORS) vector to (0,1) vector
- * 2) norm2pos - maps (0,1) vector to x1,y1 - x2,y2
- * 2) gradientTransform
- * 3) bbox2user
- * 4) ctm == userspace to pixel grid
- *
- * See also (*) in sp-pattern about why we may need parent_transform.
- *
- * \todo (point 1 above) fixme: I do not know how to deal with start > 0
- * and end < 1.
- */
-SPPainter * SPLGPainter::painter_new(SPPaintServer *ps,
- Geom::Affine const &full_transform,
- Geom::Affine const &/*parent_transform*/,
- NRRect const *bbox)
-{
- SPLinearGradient *lg = SP_LINEARGRADIENT(ps);
- SPGradient *gr = SP_GRADIENT(ps);
-
- if (!gr->color) {
- gr->ensureColors();
- }
-
- SPLGPainter *lgp = g_new(SPLGPainter, 1);
-
- lgp->painter.server_type = G_OBJECT_TYPE(ps);
- lgp->painter.fill = sp_lg_fill;
-
- lgp->lg = lg;
-
- /** \todo
- * Technically speaking, we map NCOLORS on line [start,end] onto line
- * [0,1]. I almost think we should fill color array start and end in
- * that case. The alternative would be to leave these just empty garbage
- * or something similar. Originally I had 1023.9999 here - not sure
- * whether we have really to cut out ceil int (Lauris).
- */
- Geom::Affine color2norm(Geom::identity());
- Geom::Affine color2px;
- if (gr->units == SP_GRADIENT_UNITS_OBJECTBOUNDINGBOX) {
- Geom::Affine norm2pos(Geom::identity());
-
- /* BBox to user coordinate system */
- Geom::Affine bbox2user(bbox->x1 - bbox->x0, 0, 0, bbox->y1 - bbox->y0, bbox->x0, bbox->y0);
-
- Geom::Affine color2pos = color2norm * norm2pos;
- Geom::Affine color2tpos = color2pos * gr->gradientTransform;
- Geom::Affine color2user = color2tpos * bbox2user;
- color2px = color2user * full_transform;
-
- } else {
- /* Problem: What to do, if we have mixed lengths and percentages? */
- /* Currently we do ignore percentages at all, but that is not good (lauris) */
-
- Geom::Affine norm2pos(Geom::identity());
- Geom::Affine color2pos = color2norm * norm2pos;
- Geom::Affine color2tpos = color2pos * gr->gradientTransform;
- color2px = color2tpos * full_transform;
-
- }
- // TODO: remove color2px_nr after converting to 2geom
- NR::Matrix color2px_nr = from_2geom(color2px);
- nr_lgradient_renderer_setup(&lgp->lgr, gr->color, gr->fetchSpread(), &color2px_nr,
- lg->x1.computed, lg->y1.computed,
- lg->x2.computed, lg->y2.computed);
-
- return (SPPainter *) lgp;
-}
-
-static void
-sp_lineargradient_painter_free(SPPaintServer */*ps*/, SPPainter *painter)
-{
- g_free(painter);
-}
-
-/**
* Directly set properties of linear gradient and request modified.
*/
void
@@ -1718,45 +1305,10 @@ sp_lineargradient_set_position(SPLinearGradient *lg,
lg->requestModified(SP_OBJECT_MODIFIED_FLAG);
}
-/**
- * Callback when linear gradient object is rendered.
- */
-static void
-sp_lg_fill(SPPainter *painter, NRPixBlock *pb)
-{
- SPLGPainter *lgp = (SPLGPainter *) painter;
-
- if (lgp->lg->color == NULL) {
- lgp->lg->ensureColors();
- }
- bool grayscale = Grayscale::activeDesktopIsGrayscale(); // TODO: find good way to access the current rendermode
- if (grayscale) {
- lgp->lgr.vector = lgp->lg->color_grayscale;
- } else {
- lgp->lgr.vector = lgp->lg->color;
- }
-
- nr_render((NRRenderer *) &lgp->lgr, pb, NULL);
-}
-
/*
* Radial Gradient
*/
-class SPRGPainter;
-
-/// A context with radial gradient, painter, and gradient renderer.
-struct SPRGPainter {
- SPPainter painter;
- SPRadialGradient *rg;
- NRRGradientRenderer rgr;
-
- static SPPainter *painter_new(SPPaintServer *ps,
- Geom::Affine const &full_transform,
- Geom::Affine const &parent_transform,
- NRRect const *bbox);
-};
-
static void sp_radialgradient_class_init(SPRadialGradientClass *klass);
static void sp_radialgradient_init(SPRadialGradient *rg);
@@ -1766,9 +1318,7 @@ static void sp_radialgradient_build(SPObject *object,
static void sp_radialgradient_set(SPObject *object, unsigned key, gchar const *value);
static Inkscape::XML::Node *sp_radialgradient_write(SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr,
guint flags);
-static void sp_radialgradient_painter_free(SPPaintServer *ps, SPPainter *painter);
-
-static void sp_rg_fill(SPPainter *painter, NRPixBlock *pb);
+static cairo_pattern_t *sp_radialgradient_create_pattern(SPPaintServer *ps, cairo_t *ct, NRRect const *bbox, double opacity);
static SPGradientClass *rg_parent_class;
@@ -1801,7 +1351,7 @@ sp_radialgradient_get_type()
static void sp_radialgradient_class_init(SPRadialGradientClass *klass)
{
SPObjectClass *sp_object_class = (SPObjectClass *) klass;
- SPPaintServerClass *ps_class = SP_PAINT_SERVER_CLASS( klass );
+ SPPaintServerClass *ps_class = (SPPaintServerClass *) klass;
rg_parent_class = (SPGradientClass*)g_type_class_ref(SP_TYPE_GRADIENT);
@@ -1809,8 +1359,7 @@ static void sp_radialgradient_class_init(SPRadialGradientClass *klass)
sp_object_class->set = sp_radialgradient_set;
sp_object_class->write = sp_radialgradient_write;
- ps_class->painter_new = SPRGPainter::painter_new;
- ps_class->painter_free = sp_radialgradient_painter_free;
+ ps_class->pattern_new = sp_radialgradient_create_pattern;
}
/**
@@ -1921,68 +1470,6 @@ sp_radialgradient_write(SPObject *object, Inkscape::XML::Document *xml_doc, Inks
}
/**
- * Create radial gradient context.
- */
-SPPainter *SPRGPainter::painter_new(SPPaintServer *ps,
- Geom::Affine const &full_transform,
- Geom::Affine const &/*parent_transform*/,
- NRRect const *bbox)
-{
- SPRadialGradient *rg = SP_RADIALGRADIENT(ps);
- SPGradient *gr = SP_GRADIENT(ps);
-
- if (!gr->color) {
- gr->ensureColors();
- }
-
- SPRGPainter *rgp = g_new(SPRGPainter, 1);
-
- rgp->painter.server_type = G_OBJECT_TYPE(ps);
- rgp->painter.fill = sp_rg_fill;
-
- rgp->rg = rg;
-
- Geom::Affine gs2px;
-
- if (gr->units == SP_GRADIENT_UNITS_OBJECTBOUNDINGBOX) {
- /** \todo
- * fixme: We may try to normalize here too, look at
- * linearGradient (Lauris)
- */
-
- /* BBox to user coordinate system */
- Geom::Affine bbox2user(bbox->x1 - bbox->x0, 0, 0, bbox->y1 - bbox->y0, bbox->x0, bbox->y0);
-
- Geom::Affine gs2user = gr->gradientTransform * bbox2user;
-
- gs2px = gs2user * full_transform;
- } else {
- /** \todo
- * Problem: What to do, if we have mixed lengths and percentages?
- * Currently we do ignore percentages at all, but that is not
- * good (lauris)
- */
-
- gs2px = gr->gradientTransform * full_transform;
- }
- // TODO: remove gs2px_nr after converting to 2geom
- NR::Matrix gs2px_nr = from_2geom(gs2px);
- nr_rgradient_renderer_setup(&rgp->rgr, gr->color, gr->fetchSpread(),
- &gs2px_nr,
- rg->cx.computed, rg->cy.computed,
- rg->fx.computed, rg->fy.computed,
- rg->r.computed);
-
- return (SPPainter *) rgp;
-}
-
-static void
-sp_radialgradient_painter_free(SPPaintServer */*ps*/, SPPainter *painter)
-{
- g_free(painter);
-}
-
-/**
* Directly set properties of radial gradient and request modified.
*/
void
@@ -2002,25 +1489,101 @@ sp_radialgradient_set_position(SPRadialGradient *rg,
rg->requestModified(SP_OBJECT_MODIFIED_FLAG);
}
-/**
- * Callback when radial gradient object is rendered.
- */
+/* CAIRO RENDERING STUFF */
+
static void
-sp_rg_fill(SPPainter *painter, NRPixBlock *pb)
+sp_gradient_pattern_common_setup(cairo_pattern_t *cp,
+ SPGradient *gr,
+ NRRect const *bbox,
+ double opacity)
{
- SPRGPainter *rgp = (SPRGPainter *) painter;
+ // set spread type
+ switch (gr->getSpread()) {
+ case SP_GRADIENT_SPREAD_REFLECT:
+ cairo_pattern_set_extend(cp, CAIRO_EXTEND_REFLECT);
+ break;
+ case SP_GRADIENT_SPREAD_REPEAT:
+ cairo_pattern_set_extend(cp, CAIRO_EXTEND_REPEAT);
+ break;
+ case SP_GRADIENT_SPREAD_PAD:
+ default:
+ cairo_pattern_set_extend(cp, CAIRO_EXTEND_PAD);
+ break;
+ }
- if (rgp->rg->color == NULL) {
- rgp->rg->ensureColors();
+ // add stops
+ for (std::vector<SPGradientStop>::iterator i = gr->vector.stops.begin();
+ i != gr->vector.stops.end(); ++i)
+ {
+ // multiply stop opacity by paint opacity
+ cairo_pattern_add_color_stop_rgba(cp, i->offset,
+ i->color.v.c[0], i->color.v.c[1], i->color.v.c[2], i->opacity * opacity);
}
- bool grayscale = Grayscale::activeDesktopIsGrayscale(); // TODO: find good way to access the current rendermode
- if (grayscale) {
- rgp->rgr.vector = rgp->rg->color_grayscale;
- } else {
- rgp->rgr.vector = rgp->rg->color;
+
+ // set pattern matrix
+ Geom::Affine gs2user = gr->gradientTransform;
+ if (gr->getUnits() == SP_GRADIENT_UNITS_OBJECTBOUNDINGBOX) {
+ Geom::Affine bbox2user(bbox->x1 - bbox->x0, 0, 0, bbox->y1 - bbox->y0, bbox->x0, bbox->y0);
+ gs2user *= bbox2user;
+ }
+ ink_cairo_pattern_set_matrix(cp, gs2user.inverse());
+}
+
+static cairo_pattern_t *
+sp_radialgradient_create_pattern(SPPaintServer *ps,
+ cairo_t */* ct */,
+ NRRect const *bbox,
+ double opacity)
+{
+ SPRadialGradient *rg = SP_RADIALGRADIENT(ps);
+ SPGradient *gr = SP_GRADIENT(ps);
+
+ gr->ensureVector();
+
+ cairo_pattern_t *cp = cairo_pattern_create_radial(
+ rg->fx.computed, rg->fy.computed, 0,
+ rg->cx.computed, rg->cy.computed, rg->r.computed);
+
+ sp_gradient_pattern_common_setup(cp, gr, bbox, opacity);
+
+ return cp;
+}
+
+static cairo_pattern_t *
+sp_lineargradient_create_pattern(SPPaintServer *ps,
+ cairo_t */* ct */,
+ NRRect const *bbox,
+ double opacity)
+{
+ SPLinearGradient *lg = SP_LINEARGRADIENT(ps);
+ SPGradient *gr = SP_GRADIENT(ps);
+
+ gr->ensureVector();
+
+ cairo_pattern_t *cp = cairo_pattern_create_linear(
+ lg->x1.computed, lg->y1.computed,
+ lg->x2.computed, lg->y2.computed);
+
+ sp_gradient_pattern_common_setup(cp, gr, bbox, opacity);
+
+ return cp;
+}
+
+cairo_pattern_t *
+sp_gradient_create_preview_pattern(SPGradient *gr, double width)
+{
+ gr->ensureVector();
+
+ cairo_pattern_t *pat = cairo_pattern_create_linear(0, 0, width, 0);
+
+ for (std::vector<SPGradientStop>::iterator i = gr->vector.stops.begin();
+ i != gr->vector.stops.end(); ++i)
+ {
+ cairo_pattern_add_color_stop_rgba(pat, i->offset,
+ i->color.v.c[0], i->color.v.c[1], i->color.v.c[2], i->opacity);
}
- nr_render((NRRenderer *) &rgp->rgr, pb, NULL);
+ return pat;
}
/*
diff --git a/src/sp-gradient.h b/src/sp-gradient.h
index 217b9f3ee..85eb70e9b 100644
--- a/src/sp-gradient.h
+++ b/src/sp-gradient.h
@@ -19,7 +19,7 @@
#include <gdk/gdk.h>
#include <glibmm/ustring.h>
-#include "libnr/nr-matrix.h"
+#include <2geom/affine.h>
#include "sp-paint-server.h"
#include "sp-gradient-spread.h"
#include "sp-gradient-units.h"
@@ -100,11 +100,6 @@ public:
/** Composed vector */
SPGradientVector vector;
- /** Rendered color array (4 * 1024 bytes) */
- guchar *color;
- /** Rendered color array in grayscale (for grayscale viewmode) (4 * 1024 bytes) */
- guchar *color_grayscale;
-
sigc::connection modified_connection;
bool hasStops() const;
diff --git a/src/sp-image.cpp b/src/sp-image.cpp
index 88daf31ba..f98a6c8e3 100644
--- a/src/sp-image.cpp
+++ b/src/sp-image.cpp
@@ -21,33 +21,26 @@
#include <png.h>
#include <cstring>
+#include <algorithm>
#include <string>
-#include <libnr/nr-matrix-fns.h>
-#include <libnr/nr-matrix-ops.h>
-#include <libnr/nr-translate-matrix-ops.h>
-#include <libnr/nr-scale-translate-ops.h>
-#include <libnr/nr-convert2geom.h>
-#include <2geom/rect.h>
-//#define GDK_PIXBUF_ENABLE_BACKEND 1
-//#include <gdk-pixbuf/gdk-pixbuf-io.h>
-#include "display/nr-arena-image.h"
-#include <display/curve.h>
#include <glib/gstdio.h>
+#include <2geom/rect.h>
+#include <glibmm/i18n.h>
+#include "display/nr-arena-image.h"
+#include "display/cairo-utils.h"
+#include "display/curve.h"
//Added for preserveAspectRatio support -- EAF
#include "enums.h"
#include "attributes.h"
-
#include "print.h"
#include "brokenimage.xpm"
#include "document.h"
#include "sp-image.h"
#include "sp-clippath.h"
-#include <glibmm/i18n.h>
#include "xml/quote.h"
-#include <xml/repr.h>
+#include "xml/repr.h"
#include "snap-candidate.h"
-#include "libnr/nr-matrix-fns.h"
#include "io/sys.h"
#if ENABLE_LCMS
@@ -96,6 +89,7 @@ static void sp_image_set_curve(SPImage *image);
static GdkPixbuf *sp_image_repr_read_image( time_t& modTime, gchar*& pixPath, const gchar *href, const gchar *absref, const gchar *base );
static GdkPixbuf *sp_image_pixbuf_force_rgba (GdkPixbuf * pixbuf);
+static void sp_image_update_arenaitem (SPImage *img, NRArenaImage *ai);
static void sp_image_update_canvas_image (SPImage *image);
static GdkPixbuf * sp_image_repr_read_dataURI (const gchar * uri_data);
static GdkPixbuf * sp_image_repr_read_b64 (const gchar * uri_data);
@@ -612,15 +606,9 @@ static void sp_image_init( SPImage *image )
image->width.unset();
image->height.unset();
image->aspect_align = SP_ASPECT_NONE;
-
- image->trimx = 0;
- image->trimy = 0;
- image->trimwidth = 0;
- image->trimheight = 0;
- image->viewx = 0;
- image->viewy = 0;
- image->viewwidth = 0;
- image->viewheight = 0;
+ image->clipbox = Geom::Rect();
+ image->sx = image->sy = 1.0;
+ image->ox = image->oy = 0.0;
image->curve = NULL;
@@ -924,16 +912,38 @@ static void sp_image_update( SPObject *object, SPCtx *ctx, unsigned int flags )
}
#endif // ENABLE_LCMS
image->pixbuf = pixbuf;
+ // convert to premultiplied native-endian ARGB for display with Cairo
+ convert_pixbuf_normal_to_argb32(image->pixbuf);
}
}
}
+
+ if (image->pixbuf) {
+ /* fixme: We are slightly violating spec here (Lauris) */
+ if (!image->width._set) {
+ image->width.computed = gdk_pixbuf_get_width(image->pixbuf);
+ }
+ if (!image->height._set) {
+ image->height.computed = gdk_pixbuf_get_height(image->pixbuf);
+ }
+ }
+
+ Geom::Point p(image->x.computed, image->y.computed);
+ Geom::Point wh(image->width.computed, image->height.computed);
+ image->clipbox = Geom::Rect(p, p + wh);
+
+ image->ox = image->x.computed;
+ image->oy = image->y.computed;
+
+ int pixwidth = gdk_pixbuf_get_width (image->pixbuf);
+ int pixheight = gdk_pixbuf_get_height (image->pixbuf);
+
+ image->sx = image->width.computed / pixwidth;
+ image->sy = image->height.computed / pixheight;
+
// preserveAspectRatio calculate bounds / clipping rectangle -- EAF
if (image->pixbuf && (image->aspect_align != SP_ASPECT_NONE)) {
- int imagewidth, imageheight;
- double x,y;
-
- imagewidth = gdk_pixbuf_get_width (image->pixbuf);
- imageheight = gdk_pixbuf_get_height (image->pixbuf);
+ double x, y;
switch (image->aspect_align) {
case SP_ASPECT_XMIN_YMIN:
@@ -979,43 +989,19 @@ static void sp_image_update( SPObject *object, SPCtx *ctx, unsigned int flags )
}
if (image->aspect_clip == SP_ASPECT_SLICE) {
- image->viewx = image->x.computed;
- image->viewy = image->y.computed;
- image->viewwidth = image->width.computed;
- image->viewheight = image->height.computed;
- if ((imagewidth*image->height.computed)>(image->width.computed*imageheight)) {
- // Pixels aspect is wider than bounding box
- image->trimheight = imageheight;
- image->trimwidth = static_cast<int>(static_cast<double>(imageheight) * image->width.computed / image->height.computed);
- image->trimy = 0;
- image->trimx = static_cast<int>(static_cast<double>(imagewidth - image->trimwidth) * x);
- } else {
- // Pixels aspect is taller than bounding box
- image->trimwidth = imagewidth;
- image->trimheight = static_cast<int>(static_cast<double>(imagewidth) * image->height.computed / image->width.computed);
- image->trimx = 0;
- image->trimy = static_cast<int>(static_cast<double>(imageheight - image->trimheight) * y);
- }
+ double scale = std::max(image->sx, image->sy);
+ image->sx = scale;
+ image->sy = scale;
} else {
- // Otherwise, assume SP_ASPECT_MEET
- image->trimx = 0;
- image->trimy = 0;
- image->trimwidth = imagewidth;
- image->trimheight = imageheight;
- if ((imagewidth*image->height.computed)>(image->width.computed*imageheight)) {
- // Pixels aspect is wider than bounding boz
- image->viewwidth = image->width.computed;
- image->viewheight = image->viewwidth * imageheight / imagewidth;
- image->viewx=image->x.computed;
- image->viewy=(image->height.computed - image->viewheight) * y + image->y.computed;
- } else {
- // Pixels aspect is taller than bounding box
- image->viewheight = image->height.computed;
- image->viewwidth = image->viewheight * imagewidth / imageheight;
- image->viewy=image->y.computed;
- image->viewx=(image->width.computed - image->viewwidth) * x + image->x.computed;
- }
+ double scale = std::min(image->sx, image->sy);
+ image->sx = scale;
+ image->sy = scale;
}
+
+ double vw = pixwidth * image->sx;
+ double vh = pixheight * image->sy;
+ image->ox += x * (image->width.computed - vw);
+ image->oy += y * (image->height.computed - vh);
}
sp_image_update_canvas_image ((SPImage *) object);
}
@@ -1095,32 +1081,44 @@ static void sp_image_print( SPItem *item, SPPrintContext *ctx )
SPImage *image = SP_IMAGE(item);
if (image->pixbuf && (image->width.computed > 0.0) && (image->height.computed > 0.0) ) {
- guchar *px = gdk_pixbuf_get_pixels(image->pixbuf);
- int w = gdk_pixbuf_get_width(image->pixbuf);
- int h = gdk_pixbuf_get_height(image->pixbuf);
- int rs = gdk_pixbuf_get_rowstride(image->pixbuf);
- int pixskip = gdk_pixbuf_get_n_channels(image->pixbuf) * gdk_pixbuf_get_bits_per_sample(image->pixbuf) / 8;
+ GdkPixbuf *pb = gdk_pixbuf_copy(image->pixbuf);
+ convert_pixbuf_argb32_to_normal(pb);
+
+ guchar *px = gdk_pixbuf_get_pixels(pb);
+ int w = gdk_pixbuf_get_width(pb);
+ int h = gdk_pixbuf_get_height(pb);
+ int rs = gdk_pixbuf_get_rowstride(pb);
+ int pixskip = gdk_pixbuf_get_n_channels(pb) * gdk_pixbuf_get_bits_per_sample(pb) / 8;
- Geom::Affine t;
if (image->aspect_align == SP_ASPECT_NONE) {
- /* fixme: (Lauris) */
+ Geom::Affine t;
Geom::Translate tp(image->x.computed, image->y.computed);
Geom::Scale s(image->width.computed, -image->height.computed);
Geom::Translate ti(0.0, -1.0);
t = s * tp;
t = ti * t;
+ sp_print_image_R8G8B8A8_N(ctx, px, w, h, rs, &t, item->style);
} else { // preserveAspectRatio
- Geom::Translate tp(image->viewx, image->viewy);
- Geom::Scale s(image->viewwidth, -image->viewheight);
+ double vw = image->width.computed / image->sx;
+ double vh = image->height.computed / image->sy;
+
+ int trimwidth = std::min<int>(w, ceil(image->width.computed / vw * w));
+ int trimheight = std::min<int>(h, ceil(image->height.computed / vh * h));
+ int trimx = std::max<int>(0, floor((image->x.computed - image->ox) / vw * w));
+ int trimy = std::max<int>(0, floor((image->y.computed - image->oy) / vh * h));
+
+ double vx = std::max<double>(image->ox, image->x.computed);
+ double vy = std::max<double>(image->oy, image->y.computed);
+ double vcw = std::min<double>(image->width.computed, vw);
+ double vch = std::min<double>(image->height.computed, vh);
+
+ Geom::Affine t;
+ Geom::Translate tp(vx, vy);
+ Geom::Scale s(vcw, -vch);
Geom::Translate ti(0.0, -1.0);
t = s * tp;
t = ti * t;
- }
-
- if (image->aspect_align == SP_ASPECT_NONE) {
- sp_print_image_R8G8B8A8_N(ctx, px, w, h, rs, &t, item->style);
- } else { // preserveAspectRatio
- sp_print_image_R8G8B8A8_N(ctx, px + image->trimx*pixskip + image->trimy*rs, image->trimwidth, image->trimheight, rs, &t, item->style);
+ sp_print_image_R8G8B8A8_N(ctx, px + trimx*pixskip + trimy*rs, trimwidth, trimheight, rs, &t, item->style);
}
}
}
@@ -1153,31 +1151,7 @@ static NRArenaItem *sp_image_show( SPItem *item, NRArena *arena, unsigned int /*
SPImage * image = SP_IMAGE(item);
NRArenaItem *ai = NRArenaImage::create(arena);
- if (image->pixbuf) {
- int pixskip = gdk_pixbuf_get_n_channels(image->pixbuf) * gdk_pixbuf_get_bits_per_sample(image->pixbuf) / 8;
- int rs = gdk_pixbuf_get_rowstride(image->pixbuf);
- nr_arena_image_set_style(NR_ARENA_IMAGE(ai), item->style);
- if (image->aspect_align == SP_ASPECT_NONE) {
- nr_arena_image_set_pixels(NR_ARENA_IMAGE(ai),
- gdk_pixbuf_get_pixels(image->pixbuf),
- gdk_pixbuf_get_width(image->pixbuf),
- gdk_pixbuf_get_height(image->pixbuf),
- rs);
- } else { // preserveAspectRatio
- nr_arena_image_set_pixels(NR_ARENA_IMAGE(ai),
- gdk_pixbuf_get_pixels(image->pixbuf) + image->trimx*pixskip + image->trimy*rs,
- image->trimwidth,
- image->trimheight,
- rs);
- }
- } else {
- nr_arena_image_set_pixels(NR_ARENA_IMAGE(ai), NULL, 0, 0, 0);
- }
- if (image->aspect_align == SP_ASPECT_NONE) {
- nr_arena_image_set_geometry(NR_ARENA_IMAGE(ai), image->x.computed, image->y.computed, image->width.computed, image->height.computed);
- } else { // preserveAspectRatio
- nr_arena_image_set_geometry(NR_ARENA_IMAGE(ai), image->viewx, image->viewy, image->viewwidth, image->viewheight);
- }
+ sp_image_update_arenaitem(image, NR_ARENA_IMAGE(ai));
return ai;
}
@@ -1287,44 +1261,23 @@ static GdkPixbuf *sp_image_pixbuf_force_rgba( GdkPixbuf * pixbuf )
}
/* We assert that realpixbuf is either NULL or identical size to pixbuf */
+static void
+sp_image_update_arenaitem (SPImage *image, NRArenaImage *ai)
+{
+ nr_arena_image_set_style(ai, SP_OBJECT(image)->style);
+ nr_arena_image_set_argb32_pixbuf(ai, image->pixbuf);
+ nr_arena_image_set_origin(ai, Geom::Point(image->ox, image->oy));
+ nr_arena_image_set_scale(ai, image->sx, image->sy);
+ nr_arena_image_set_clipbox(ai, image->clipbox);
+}
-static void sp_image_update_canvas_image( SPImage *image )
+static void
+sp_image_update_canvas_image (SPImage *image)
{
SPItem *item = SP_ITEM(image);
- if (image->pixbuf) {
- /* fixme: We are slightly violating spec here (Lauris) */
- if (!image->width._set) {
- image->width.computed = gdk_pixbuf_get_width(image->pixbuf);
- }
- if (!image->height._set) {
- image->height.computed = gdk_pixbuf_get_height(image->pixbuf);
- }
- }
-
for (SPItemView *v = item->display; v != NULL; v = v->next) {
- int pixskip = gdk_pixbuf_get_n_channels(image->pixbuf) * gdk_pixbuf_get_bits_per_sample(image->pixbuf) / 8;
- int rs = gdk_pixbuf_get_rowstride(image->pixbuf);
- nr_arena_image_set_style(NR_ARENA_IMAGE(v->arenaitem), image->style);
- if (image->aspect_align == SP_ASPECT_NONE) {
- nr_arena_image_set_pixels(NR_ARENA_IMAGE(v->arenaitem),
- gdk_pixbuf_get_pixels(image->pixbuf),
- gdk_pixbuf_get_width(image->pixbuf),
- gdk_pixbuf_get_height(image->pixbuf),
- rs);
- nr_arena_image_set_geometry(NR_ARENA_IMAGE(v->arenaitem),
- image->x.computed, image->y.computed,
- image->width.computed, image->height.computed);
- } else { // preserveAspectRatio
- nr_arena_image_set_pixels(NR_ARENA_IMAGE(v->arenaitem),
- gdk_pixbuf_get_pixels(image->pixbuf) + image->trimx*pixskip + image->trimy*rs,
- image->trimwidth,
- image->trimheight,
- rs);
- nr_arena_image_set_geometry(NR_ARENA_IMAGE(v->arenaitem),
- image->viewx, image->viewy,
- image->viewwidth, image->viewheight);
- }
+ sp_image_update_arenaitem(image, NR_ARENA_IMAGE(v->arenaitem));
}
}
diff --git a/src/sp-image.h b/src/sp-image.h
index 9618c9873..2b3940412 100644
--- a/src/sp-image.h
+++ b/src/sp-image.h
@@ -38,12 +38,16 @@ struct SPImage : public SPItem {
SVGLength width;
SVGLength height;
+ Geom::Rect clipbox;
+ double sx, sy;
+ double ox, oy;
+
// Added by EAF
/* preserveAspectRatio */
unsigned int aspect_align : 4;
unsigned int aspect_clip : 1;
- int trimx, trimy, trimwidth, trimheight;
- double viewx, viewy, viewwidth, viewheight;
+ //int trimx, trimy, trimwidth, trimheight;
+ //double viewx, viewy, viewwidth, viewheight;
SPCurve *curve; // This curve is at the image's boundary for snapping
diff --git a/src/sp-item-group.cpp b/src/sp-item-group.cpp
index 91342688a..8d38fee07 100644
--- a/src/sp-item-group.cpp
+++ b/src/sp-item-group.cpp
@@ -24,8 +24,6 @@
#include "display/nr-arena-group.h"
#include "display/curve.h"
-#include "libnr/nr-matrix-ops.h"
-#include "libnr/nr-matrix-fns.h"
#include "xml/repr.h"
#include "svg/svg.h"
#include "document.h"
@@ -707,7 +705,7 @@ void CGroup::calculateBBox(NRRect *bbox, Geom::Affine const &transform, unsigned
SPObject *o = SP_OBJECT (l->data);
if (SP_IS_ITEM(o) && !SP_ITEM(o)->isHidden()) {
SPItem *child = SP_ITEM(o);
- Geom::Affine const ct(to_2geom(child->transform) * transform);
+ Geom::Affine const ct(child->transform * transform);
child->invoke_bbox_full( dummy_bbox, ct, flags, FALSE);
}
l = g_slist_remove (l, o);
diff --git a/src/sp-item-transform.cpp b/src/sp-item-transform.cpp
index e91c80b5f..ae55a5c50 100644
--- a/src/sp-item-transform.cpp
+++ b/src/sp-item-transform.cpp
@@ -122,7 +122,7 @@ get_scale_transform_with_stroke (Geom::Rect const &bbox_param, gdouble strokewid
Geom::Affine direct_constant_r = Geom::Scale(flip_x * ratio_x, flip_y * ratio_y);
- if (transform_stroke && r0 != 0 && r0 != NR_HUGE) { // there's stroke, and we need to scale it
+ if (transform_stroke && r0 != 0 && r0 != Geom::infinity()) { // there's stroke, and we need to scale it
// These coefficients are obtained from the assumption that scaling applies to the
// non-stroked "shape proper" and that stroke scale is scaled by the expansion of that
// matrix. We're trying to solve this equation:
@@ -147,7 +147,7 @@ get_scale_transform_with_stroke (Geom::Rect const &bbox_param, gdouble strokewid
scale *= direct;
}
} else {
- if (r0 == 0 || r0 == NR_HUGE) { // no stroke to scale
+ if (r0 == 0 || r0 == Geom::infinity()) { // no stroke to scale
scale *= direct;
} else {// nonscaling strokewidth
scale *= direct_constant_r;
@@ -174,7 +174,7 @@ get_visual_bbox (Geom::OptRect const &initial_geom_bbox, Geom::Affine const &abs
}
Geom::Rect new_visual_bbox = new_geom_bbox;
- if (initial_strokewidth > 0 && initial_strokewidth < NR_HUGE) {
+ if (initial_strokewidth > 0 && initial_strokewidth < Geom::infinity()) {
if (transform_stroke) {
// scale stroke by: sqrt (((w1-r0)/(w0-r0))*((h1-r0)/(h0-r0))) (for visual bboxes, see get_scale_transform_with_stroke)
// equals scaling by: sqrt ((w1/w0)*(h1/h0)) for geometrical bboxes
diff --git a/src/sp-item.cpp b/src/sp-item.cpp
index 40c9b0233..7e5f5f96a 100644
--- a/src/sp-item.cpp
+++ b/src/sp-item.cpp
@@ -61,11 +61,6 @@
#include "sp-title.h"
#include "sp-desc.h"
-#include "libnr/nr-matrix-fns.h"
-#include "libnr/nr-matrix-scale-ops.h"
-#include "libnr/nr-matrix-translate-ops.h"
-#include "libnr/nr-scale-translate-ops.h"
-#include "libnr/nr-translate-scale-ops.h"
#include "libnr/nr-convert2geom.h"
#include "util/find-last-if.h"
#include "util/reverse-list.h"
@@ -743,8 +738,8 @@ void SPItem::invoke_bbox_full( Geom::OptRect &bbox, Geom::Affine const &transfor
// TODO: replace NRRect by Geom::Rect, for all SPItemClasses, and for SP_CLIPPATH
NRRect temp_bbox;
- temp_bbox.x0 = temp_bbox.y0 = NR_HUGE;
- temp_bbox.x1 = temp_bbox.y1 = -NR_HUGE;
+ temp_bbox.x0 = temp_bbox.y0 = Geom::infinity();
+ temp_bbox.x1 = temp_bbox.y1 = -Geom::infinity();
// call the subclass method
if (((SPItemClass *) G_OBJECT_GET_CLASS(this))->bbox) {
@@ -816,7 +811,7 @@ void SPItem::invoke_bbox_full( Geom::OptRect &bbox, Geom::Affine const &transfor
if (temp_bbox.x0 > temp_bbox.x1 || temp_bbox.y0 > temp_bbox.y1) {
// Either the bbox hasn't been touched by the SPItemClass' bbox method
- // (it still has its initial values, see above: x0 = y0 = NR_HUGE and x1 = y1 = -NR_HUGE)
+ // (it still has its initial values, see above: x0 = y0 = Geom::infinity() and x1 = y1 = -Geom::infinity())
// or it has explicitely been set to be like this (e.g. in sp_shape_bbox)
// When x0 > x1 or y0 > y1, the bbox is considered to be "nothing", although it has not been
@@ -1190,7 +1185,9 @@ void SPItem::adjust_gradient( Geom::Affine const &postmul, bool set )
void SPItem::adjust_stroke( gdouble ex )
{
- if ( style && !style->stroke.isNone() && !NR_DF_TEST_CLOSE(ex, 1.0, NR_EPSILON) ) {
+ SPStyle *style = this->style;
+
+ if (style && !style->stroke.isNone() && !Geom::are_near(ex, 1.0, Geom::EPSILON)) {
style->stroke_width.computed *= ex;
style->stroke_width.set = TRUE;
diff --git a/src/sp-line.cpp b/src/sp-line.cpp
index 72fe2cfa2..b21122566 100644
--- a/src/sp-line.cpp
+++ b/src/sp-line.cpp
@@ -12,7 +12,7 @@
*/
#ifdef HAVE_CONFIG_H
-# include <config.h>
+# include "config.h"
#endif
#include "attributes.h"
#include "style.h"
@@ -20,8 +20,7 @@
#include "sp-guide.h"
#include "display/curve.h"
#include <glibmm/i18n.h>
-#include <libnr/nr-matrix-fns.h>
-#include <xml/repr.h>
+#include "xml/repr.h"
#include "document.h"
#include "inkscape.h"
diff --git a/src/sp-mask.cpp b/src/sp-mask.cpp
index 513e52911..76efb6b4b 100644
--- a/src/sp-mask.cpp
+++ b/src/sp-mask.cpp
@@ -16,7 +16,6 @@
#include "display/nr-arena.h"
#include "display/nr-arena-group.h"
-#include "libnr/nr-matrix-ops.h"
#include <xml/repr.h>
#include "enums.h"
@@ -353,10 +352,10 @@ sp_mask_set_bbox (SPMask *mask, unsigned int key, NRRect *bbox)
{
for (SPMaskView *v = mask->display; v != NULL; v = v->next) {
if (v->key == key) {
- if (!NR_DF_TEST_CLOSE (v->bbox.x0, bbox->x0, NR_EPSILON) ||
- !NR_DF_TEST_CLOSE (v->bbox.y0, bbox->y0, NR_EPSILON) ||
- !NR_DF_TEST_CLOSE (v->bbox.x1, bbox->x1, NR_EPSILON) ||
- !NR_DF_TEST_CLOSE (v->bbox.y1, bbox->y1, NR_EPSILON)) {
+ if (!Geom::are_near(v->bbox.x0, bbox->x0) ||
+ !Geom::are_near(v->bbox.y0, bbox->y0) ||
+ !Geom::are_near(v->bbox.x1, bbox->x1) ||
+ !Geom::are_near(v->bbox.y1, bbox->y1)) {
v->bbox = *bbox;
}
break;
diff --git a/src/sp-object-repr.cpp b/src/sp-object-repr.cpp
index a995739b1..c6d6729cc 100644
--- a/src/sp-object-repr.cpp
+++ b/src/sp-object-repr.cpp
@@ -58,7 +58,6 @@
#include "color-profile-fns.h"
#include "xml/repr.h"
#include "sp-filter.h"
-#include "sp-gaussian-blur.h"
#include "filters/blend.h"
#include "filters/colormatrix.h"
#include "filters/componenttransfer.h"
@@ -69,6 +68,7 @@
#include "filters/distantlight.h"
#include "filters/displacementmap.h"
#include "filters/flood.h"
+#include "filters/gaussian-blur.h"
#include "filters/image.h"
#include "filters/merge.h"
#include "filters/morphology.h"
diff --git a/src/sp-offset.cpp b/src/sp-offset.cpp
index 3fb9441a3..460421492 100644
--- a/src/sp-offset.cpp
+++ b/src/sp-offset.cpp
@@ -36,7 +36,7 @@
#include "sp-use-reference.h"
#include "uri.h"
-#include <libnr/nr-matrix-fns.h>
+#include <2geom/affine.h>
#include <2geom/pathvector.h>
#include "xml/repr.h"
diff --git a/src/sp-paint-server.cpp b/src/sp-paint-server.cpp
index 18b1eea7d..dc99639c8 100644
--- a/src/sp-paint-server.cpp
+++ b/src/sp-paint-server.cpp
@@ -14,7 +14,6 @@
*/
#include <string.h>
-#include "libnr/nr-pixblock-pattern.h"
#include "sp-paint-server-reference.h"
#include "sp-paint-server.h"
@@ -23,13 +22,9 @@
static void sp_paint_server_class_init(SPPaintServerClass *psc);
-static void sp_paint_server_release(SPObject *object);
-
-static void sp_painter_stale_fill(SPPainter *painter, NRPixBlock *pb);
+static cairo_pattern_t *sp_paint_server_create_dummy_pattern(SPPaintServer *ps, cairo_t *ct, NRRect const *bbox, double opacity);
static SPObjectClass *parent_class;
-static GSList *stale_painters = NULL;
-
SPPaintServer *SPPaintServerReference::getObject() const
{
@@ -41,7 +36,7 @@ bool SPPaintServerReference::_acceptObject(SPObject *obj) const
return SP_IS_PAINT_SERVER(obj);
}
-GType SPPaintServer::getType(void)
+GType SPPaintServer::get_type(void)
{
static GType type = 0;
if (!type) {
@@ -64,108 +59,43 @@ GType SPPaintServer::getType(void)
static void sp_paint_server_class_init(SPPaintServerClass *psc)
{
- SPObjectClass *sp_object_class = (SPObjectClass *) psc;
- sp_object_class->release = sp_paint_server_release;
+ psc->pattern_new = sp_paint_server_create_dummy_pattern;
+
parent_class = (SPObjectClass *) g_type_class_ref(SP_TYPE_OBJECT);
}
void SPPaintServer::init(SPPaintServer *ps)
{
- ps->painters = NULL;
- ps->swatch = false;
}
-static void sp_paint_server_release(SPObject *object)
-{
- SPPaintServer *ps = SP_PAINT_SERVER(object);
-
- while (ps->painters) {
- SPPainter *painter = ps->painters;
- ps->painters = painter->next;
- stale_painters = g_slist_prepend(stale_painters, painter);
- painter->next = NULL;
- painter->server = NULL;
- painter->fill = sp_painter_stale_fill;
- }
-
- if (((SPObjectClass *) parent_class)->release) {
- ((SPObjectClass *) parent_class)->release(object);
- }
-}
-
-SPPainter *sp_paint_server_painter_new(SPPaintServer *ps,
- Geom::Affine const &full_transform,
- Geom::Affine const &parent_transform,
- const NRRect *bbox)
+cairo_pattern_t *sp_paint_server_create_pattern(SPPaintServer *ps,
+ cairo_t *ct,
+ NRRect const *bbox,
+ double opacity)
{
+ // NOTE: the ct argument is used for when rendering patterns
+ // to create a group, instead of explicitly creating a temporary surface
g_return_val_if_fail(ps != NULL, NULL);
g_return_val_if_fail(SP_IS_PAINT_SERVER(ps), NULL);
g_return_val_if_fail(bbox != NULL, NULL);
- SPPainter *painter = NULL;
- SPPaintServerClass *psc = SP_PAINT_SERVER_CLASS( G_OBJECT_GET_CLASS(ps) );
- if ( psc->painter_new ) {
- painter = (*psc->painter_new)(ps, full_transform, parent_transform, bbox);
- }
-
- if (painter) {
- painter->next = ps->painters;
- painter->server = ps;
- painter->server_type = G_OBJECT_TYPE(ps);
- ps->painters = painter;
- }
-
- return painter;
-}
-
-static void sp_paint_server_painter_free(SPPaintServer *ps, SPPainter *painter)
-{
- g_return_if_fail(ps != NULL);
- g_return_if_fail(SP_IS_PAINT_SERVER(ps));
- g_return_if_fail(painter != NULL);
-
- SPPaintServerClass *psc = SP_PAINT_SERVER_CLASS( G_OBJECT_GET_CLASS(ps) );
-
- SPPainter *r = NULL;
- for (SPPainter *p = ps->painters; p != NULL; p = p->next) {
- if (p == painter) {
- if (r) {
- r->next = p->next;
- } else {
- ps->painters = p->next;
- }
- p->next = NULL;
- if (psc->painter_free) {
- (*psc->painter_free) (ps, painter);
- }
- return;
- }
- r = p;
+ cairo_pattern_t *cp = NULL;
+ SPPaintServerClass *psc = (SPPaintServerClass *) G_OBJECT_GET_CLASS(ps);
+ if ( psc->pattern_new ) {
+ cp = (*psc->pattern_new)(ps, ct, bbox, opacity);
}
- g_assert_not_reached();
+ return cp;
}
-SPPainter *sp_painter_free(SPPainter *painter)
+static cairo_pattern_t *
+sp_paint_server_create_dummy_pattern(SPPaintServer */*ps*/,
+ cairo_t */* ct */,
+ NRRect const */*bbox*/,
+ double /* opacity */)
{
- g_return_val_if_fail(painter != NULL, NULL);
-
- if (painter->server) {
- sp_paint_server_painter_free(painter->server, painter);
- } else {
- SPPaintServerClass *psc = SP_PAINT_SERVER_CLASS( g_type_class_ref(painter->server_type) );
- if (psc->painter_free) {
- (*psc->painter_free)(NULL, painter);
- }
- stale_painters = g_slist_remove(stale_painters, painter);
- }
-
- return NULL;
-}
-
-static void sp_painter_stale_fill(SPPainter */*painter*/, NRPixBlock *pb)
-{
- nr_pixblock_render_gray_noise(pb, NULL);
+ cairo_pattern_t *cp = cairo_pattern_create_rgb(1.0, 0.0, 1.0);
+ return cp;
}
bool SPPaintServer::isSwatch() const
@@ -185,9 +115,6 @@ bool SPPaintServer::isSolid() const
return solid;
}
-
-
-
/*
Local Variables:
mode:c++
diff --git a/src/sp-paint-server.h b/src/sp-paint-server.h
index c77aad694..283a97210 100644
--- a/src/sp-paint-server.h
+++ b/src/sp-paint-server.h
@@ -15,40 +15,24 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include <libnr/nr-pixblock.h>
+#include <cairo.h>
#include "sp-object.h"
#include "uri-references.h"
-struct SPPainter;
-struct SPPaintServer;
+struct NRRect;
-#define SP_TYPE_PAINT_SERVER (SPPaintServer::getType())
+#define SP_TYPE_PAINT_SERVER (SPPaintServer::get_type())
#define SP_PAINT_SERVER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SP_TYPE_PAINT_SERVER, SPPaintServer))
#define SP_PAINT_SERVER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SP_TYPE_PAINT_SERVER, SPPaintServerClass))
#define SP_IS_PAINT_SERVER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SP_TYPE_PAINT_SERVER))
#define SP_IS_PAINT_SERVER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SP_TYPE_PAINT_SERVER))
-typedef void (* SPPainterFillFunc) (SPPainter *painter, NRPixBlock *pb);
-
-
-/* fixme: I do not like that class thingie (Lauris) */
-struct SPPainter {
- SPPainter *next;
- SPPaintServer *server;
- GType server_type;
-// SPPainterType type;
- SPPainterFillFunc fill;
-};
-
struct SPPaintServer : public SPObject {
- /** List of paints */
- SPPainter *painters;
-
protected:
bool swatch;
public:
- static GType getType(void);
+ static GType get_type(void);
bool isSwatch() const;
bool isSolid() const;
@@ -60,14 +44,10 @@ private:
struct SPPaintServerClass {
SPObjectClass sp_object_class;
/** Get SPPaint instance. */
- SPPainter * (* painter_new) (SPPaintServer *ps, Geom::Affine const &full_transform, Geom::Affine const &parent_transform, const NRRect *bbox);
- /** Free SPPaint instance. */
- void (* painter_free) (SPPaintServer *ps, SPPainter *painter);
+ cairo_pattern_t *(*pattern_new)(SPPaintServer *ps, cairo_t *ct, const NRRect *bbox, double opacity);
};
-SPPainter *sp_paint_server_painter_new (SPPaintServer *ps, Geom::Affine const &full_transform, Geom::Affine const &parent_transform, const NRRect *bbox);
-
-SPPainter *sp_painter_free (SPPainter *painter);
+cairo_pattern_t *sp_paint_server_create_pattern(SPPaintServer *ps, cairo_t *ct, NRRect const *bbox, double opacity);
#endif // SEEN_SP_PAINT_SERVER_H
diff --git a/src/sp-path.cpp b/src/sp-path.cpp
index 9a27af2f0..c8022d351 100644
--- a/src/sp-path.cpp
+++ b/src/sp-path.cpp
@@ -24,8 +24,7 @@
#include "live_effects/lpeobject-reference.h"
#include "sp-lpe-item.h"
-#include <display/curve.h>
-#include <libnr/nr-matrix-fns.h>
+#include "display/curve.h"
#include <2geom/pathvector.h>
#include <2geom/bezier-curve.h>
#include <2geom/hvlinesegment.h>
diff --git a/src/sp-pattern.cpp b/src/sp-pattern.cpp
index d7522fce8..d1e7671ed 100644
--- a/src/sp-pattern.cpp
+++ b/src/sp-pattern.cpp
@@ -18,11 +18,10 @@
#include <cstring>
#include <string>
-#include <libnr/nr-matrix-ops.h>
-#include "libnr/nr-matrix-fns.h"
#include <2geom/transforms.h>
#include "macros.h"
#include "svg/svg.h"
+#include "display/cairo-utils.h"
#include "display/nr-arena.h"
#include "display/nr-arena-group.h"
#include "attributes.h"
@@ -39,46 +38,21 @@
* Pattern
*/
-class SPPatPainter;
-
-struct SPPatPainter {
- SPPainter painter;
- SPPattern *pat;
-
- Geom::Affine ps2px;
- Geom::Affine px2ps;
- Geom::Affine pcs2px;
-
- NRArena *arena;
- unsigned int dkey;
- NRArenaItem *root;
-
- bool use_cached_tile;
- Geom::Affine ca2pa;
- Geom::Affine pa2ca;
- NRRectL cached_bbox;
- NRPixBlock cached_tile;
-
- std::map<SPObject *, sigc::connection> *_release_connections;
-};
-
static void sp_pattern_class_init (SPPatternClass *klass);
static void sp_pattern_init (SPPattern *gr);
static void sp_pattern_build (SPObject *object, SPDocument *document, Inkscape::XML::Node *repr);
static void sp_pattern_release (SPObject *object);
static void sp_pattern_set (SPObject *object, unsigned int key, const gchar *value);
-static void sp_pattern_child_added (SPObject *object, Inkscape::XML::Node *child, Inkscape::XML::Node *ref);
static void sp_pattern_update (SPObject *object, SPCtx *ctx, unsigned int flags);
static void sp_pattern_modified (SPObject *object, unsigned int flags);
static void pattern_ref_changed(SPObject *old_ref, SPObject *ref, SPPattern *pat);
static void pattern_ref_modified (SPObject *ref, guint flags, SPPattern *pattern);
-static SPPainter *sp_pattern_painter_new (SPPaintServer *ps, Geom::Affine const &full_transform, Geom::Affine const &parent_transform, const NRRect *bbox);
-static void sp_pattern_painter_free (SPPaintServer *ps, SPPainter *painter);
+static cairo_pattern_t *sp_pattern_create_pattern(SPPaintServer *ps, cairo_t *ct, NRRect const *bbox, double opacity);
-static SPPaintServerClass * pattern_parent_class = 0;
+static SPPaintServerClass * pattern_parent_class;
GType
sp_pattern_get_type (void)
@@ -105,22 +79,23 @@ sp_pattern_get_type (void)
static void
sp_pattern_class_init (SPPatternClass *klass)
{
- SPObjectClass *sp_object_class = SP_OBJECT_CLASS( klass );
- SPPaintServerClass *ps_class = SP_PAINT_SERVER_CLASS( klass );
+ SPObjectClass *sp_object_class;
+ SPPaintServerClass *ps_class;
- pattern_parent_class = SP_PAINT_SERVER_CLASS( g_type_class_ref(SP_TYPE_PAINT_SERVER) );
+ sp_object_class = (SPObjectClass *) klass;
+ ps_class = (SPPaintServerClass *) klass;
+
+ pattern_parent_class = (SPPaintServerClass*)g_type_class_ref (SP_TYPE_PAINT_SERVER);
sp_object_class->build = sp_pattern_build;
sp_object_class->release = sp_pattern_release;
sp_object_class->set = sp_pattern_set;
- sp_object_class->child_added = sp_pattern_child_added;
sp_object_class->update = sp_pattern_update;
sp_object_class->modified = sp_pattern_modified;
// do we need _write? seems to work without it
- ps_class->painter_new = sp_pattern_painter_new;
- ps_class->painter_free = sp_pattern_painter_free;
+ ps_class->pattern_new = sp_pattern_create_pattern;
}
static void
@@ -135,7 +110,7 @@ sp_pattern_init (SPPattern *pat)
pat->patternContentUnits = SP_PATTERN_UNITS_USERSPACEONUSE;
pat->patternContentUnits_set = FALSE;
- pat->patternTransform = NR::identity();
+ pat->patternTransform = Geom::identity();
pat->patternTransform_set = FALSE;
pat->x.unset();
@@ -229,7 +204,7 @@ sp_pattern_set (SPObject *object, unsigned int key, const gchar *value)
pat->patternTransform = t;
pat->patternTransform_set = TRUE;
} else {
- pat->patternTransform = NR::identity();
+ pat->patternTransform = Geom::identity();
pat->patternTransform_set = FALSE;
}
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
@@ -311,34 +286,6 @@ sp_pattern_set (SPObject *object, unsigned int key, const gchar *value)
}
}
-static void
-sp_pattern_child_added (SPObject *object, Inkscape::XML::Node *child, Inkscape::XML::Node *ref)
-{
- SPPattern *pat = SP_PATTERN (object);
-
- if (((SPObjectClass *) (pattern_parent_class))->child_added)
- (* ((SPObjectClass *) (pattern_parent_class))->child_added) (object, child, ref);
-
- SPObject *ochild = object->get_child_by_repr(child);
- if (SP_IS_ITEM (ochild)) {
-
- SPPaintServer *ps = SP_PAINT_SERVER (pat);
- unsigned position = SP_ITEM(ochild)->pos_in_parent();
-
- for (SPPainter *p = ps->painters; p != NULL; p = p->next) {
-
- SPPatPainter *pp = (SPPatPainter *) p;
- NRArenaItem *ai = SP_ITEM (ochild)->invoke_show (pp->arena, pp->dkey, SP_ITEM_REFERENCE_FLAGS);
-
- if (ai) {
- nr_arena_item_add_child (pp->root, ai, NULL);
- nr_arena_item_set_order (ai, position);
- nr_arena_item_unref (ai);
- }
- }
- }
-}
-
/* TODO: do we need a ::remove_child handler? */
/* fixme: We need ::order_changed handler too (Lauris) */
@@ -651,401 +598,134 @@ bool pattern_hasItemChildren (SPPattern *pat)
return hasChildren;
}
-
-
-/* Painter */
-
-static void sp_pat_fill (SPPainter *painter, NRPixBlock *pb);
-
-// item in this pattern is about to be deleted, hide it on our arena and disconnect
-void
-sp_pattern_painter_release (SPObject *obj, SPPatPainter *painter)
-{
- std::map<SPObject *, sigc::connection>::iterator iter = painter->_release_connections->find(obj);
- if (iter != painter->_release_connections->end()) {
- iter->second.disconnect();
- painter->_release_connections->erase(obj);
- }
-
- SP_ITEM(obj)->invoke_hide(painter->dkey);
-}
-
-/**
-Creates a painter (i.e. the thing that does actual filling at the given zoom).
-See (*) below for why the parent_transform may be necessary.
-*/
-static SPPainter *
-sp_pattern_painter_new (SPPaintServer *ps, Geom::Affine const &full_transform, Geom::Affine const &/*parent_transform*/, const NRRect *bbox)
+static cairo_pattern_t *
+sp_pattern_create_pattern(SPPaintServer *ps,
+ cairo_t *base_ct,
+ NRRect const *bbox,
+ double opacity)
{
- SPPattern *pat = SP_PATTERN (ps);
- SPPatPainter *pp = g_new (SPPatPainter, 1);
-
- pp->painter.server_type = G_OBJECT_TYPE(ps);
- pp->painter.fill = sp_pat_fill;
-
- pp->pat = pat;
-
- if (pattern_patternUnits (pat) == SP_PATTERN_UNITS_OBJECTBOUNDINGBOX) {
- /* BBox to user coordinate system */
- Geom::Affine bbox2user (bbox->x1 - bbox->x0, 0.0, 0.0, bbox->y1 - bbox->y0, bbox->x0, bbox->y0);
+ SPPattern *pat = SP_PATTERN (ps);
+ Geom::Affine ps2user;
+ Geom::Affine vb2ps = Geom::identity();
+ bool needs_opacity = (1.0 - opacity) >= 1e-3;
+ bool visible = opacity >= 1e-3;
- // the final patternTransform, taking into account bbox
- Geom::Affine const ps2user(pattern_patternTransform(pat) * bbox2user);
+ if (!visible)
+ return NULL;
- // see (*) comment below
- pp->ps2px = ps2user * full_transform;
- } else {
- /* Problem: What to do, if we have mixed lengths and percentages? */
- /* Currently we do ignore percentages at all, but that is not good (lauris) */
-
- /* fixme: We may try to normalize here too, look at linearGradient (Lauris) */
-
- // (*) The spec says, "This additional transformation matrix [patternTransform] is
- // post-multiplied to (i.e., inserted to the right of) any previously defined
- // transformations, including the implicit transformation necessary to convert from
- // object bounding box units to user space." To me, this means that the order should be:
- // item_transform * patternTransform * parent_transform
- // However both Batik and Adobe plugin use:
- // patternTransform * item_transform * parent_transform
- // So here I comply with the majority opinion, but leave my interpretation commented out below.
- // (To get item_transform, I subtract parent from full.)
-
- //pp->ps2px = (full_transform / parent_transform) * pattern_patternTransform(pat) * parent_transform;
- pp->ps2px = pattern_patternTransform(pat) * full_transform;
- }
+ /* Show items */
+ SPPattern *shown = NULL;
+ for (SPPattern *pat_i = pat; pat_i != NULL; pat_i = pat_i->ref ? pat_i->ref->getObject() : NULL) {
+ // find the first one with item children
+ if (pat_i && SP_IS_OBJECT (pat_i) && pattern_hasItemChildren(pat_i)) {
+ shown = pat_i;
+ break; // do not go further up the chain if children are found
+ }
+ }
- pp->px2ps = pp->ps2px.inverse();
+ if (!shown) {
+ return cairo_pattern_create_rgba(0,0,0,0);
+ }
- if (pat->viewBox_set) {
- gdouble tmp_x = pattern_width (pat) / (pattern_viewBox(pat)->x1 - pattern_viewBox(pat)->x0);
- gdouble tmp_y = pattern_height (pat) / (pattern_viewBox(pat)->y1 - pattern_viewBox(pat)->y0);
+ /* Create arena */
+ NRArena *arena = NRArena::create();
+ unsigned int dkey = SPItem::display_key_new (1);
+ NRArenaGroup *root = NRArenaGroup::create(arena);
+
+ for (SPObject *child = shown->firstChild(); child != NULL; child = child->getNext() ) {
+ if (SP_IS_ITEM (child)) {
+ // for each item in pattern, show it on our arena, add to the group,
+ // and connect to the release signal in case the item gets deleted
+ NRArenaItem *cai;
+ cai = SP_ITEM(child)->invoke_show (arena, dkey, SP_ITEM_SHOW_DISPLAY);
+ nr_arena_item_append_child (root, cai);
+ }
+ }
- // FIXME: preserveAspectRatio must be taken into account here too!
- Geom::Affine vb2ps (tmp_x, 0.0, 0.0, tmp_y, pattern_x(pat) - pattern_viewBox(pat)->x0 * tmp_x, pattern_y(pat) - pattern_viewBox(pat)->y0 * tmp_y);
+ if (pat->viewBox_set) {
+ gdouble tmp_x = pattern_width (pat) / (pattern_viewBox(pat)->x1 - pattern_viewBox(pat)->x0);
+ gdouble tmp_y = pattern_height (pat) / (pattern_viewBox(pat)->y1 - pattern_viewBox(pat)->y0);
- Geom::Affine vb2us = vb2ps * pattern_patternTransform(pat);
+ // FIXME: preserveAspectRatio must be taken into account here too!
+ vb2ps = Geom::Affine(tmp_x, 0.0, 0.0, tmp_y, pattern_x(pat) - pattern_viewBox(pat)->x0 * tmp_x, pattern_y(pat) - pattern_viewBox(pat)->y0 * tmp_y);
+ }
- // see (*)
- pp->pcs2px = vb2us * full_transform;
- } else {
- /* No viewbox, have to parse units */
- if (pattern_patternContentUnits (pat) == SP_PATTERN_UNITS_OBJECTBOUNDINGBOX) {
- /* BBox to user coordinate system */
- Geom::Affine bbox2user (bbox->x1 - bbox->x0, 0.0, 0.0, bbox->y1 - bbox->y0, bbox->x0, bbox->y0);
+ ps2user = pattern_patternTransform(pat);
+ if (!pat->viewBox_set && pattern_patternContentUnits (pat) == SP_PATTERN_UNITS_OBJECTBOUNDINGBOX) {
+ /* BBox to user coordinate system */
+ Geom::Affine bbox2user (bbox->x1 - bbox->x0, 0.0, 0.0, bbox->y1 - bbox->y0, bbox->x0, bbox->y0);
+ ps2user *= bbox2user;
+ }
+ ps2user = Geom::Translate (pattern_x (pat), pattern_y (pat)) * ps2user;
- Geom::Affine pcs2user = pattern_patternTransform(pat) * bbox2user;
+ Geom::Point p(pattern_x(pat), pattern_y(pat));
+ Geom::Point pd(pattern_width(pat), pattern_height(pat));
+ Geom::Rect pattern_tile(p, p + pd);
- // see (*)
- pp->pcs2px = pcs2user * full_transform;
- } else {
- // see (*)
- //pcs2px = (full_transform / parent_transform) * pattern_patternTransform(pat) * parent_transform;
- pp->pcs2px = pattern_patternTransform(pat) * full_transform;
- }
+ if (pattern_patternUnits(pat) == SP_PATTERN_UNITS_OBJECTBOUNDINGBOX) {
+ // interpret x, y, width, height in relation to bbox
+ Geom::Affine bbox2user(bbox->x1 - bbox->x0, 0,0, bbox->y1 - bbox->y0, bbox->x0, bbox->y0);
+ pattern_tile = pattern_tile * bbox2user;
+ }
- pp->pcs2px = Geom::Translate (pattern_x (pat), pattern_y (pat)) * pp->pcs2px;
- }
+ cairo_matrix_t cm;
+ cairo_get_matrix(base_ct, &cm);
+ Geom::Affine full(cm.xx, cm.yx, cm.xy, cm.yy, 0, 0);
+
+ // oversample the pattern slightly
+ // TODO: find optimum value
+ Geom::Point c(pattern_tile.dimensions()*ps2user.descrim()*full.descrim()*1.2);
+ c[Geom::X] = ceil(c[Geom::X]);
+ c[Geom::Y] = ceil(c[Geom::Y]);
+ Geom::Affine t = Geom::Scale(c) * Geom::Scale(pattern_tile.dimensions()).inverse();
+
+ NRRectL one_tile;
+ one_tile.x0 = (int) floor(pattern_tile[Geom::X].min());
+ one_tile.y0 = (int) floor(pattern_tile[Geom::Y].min());
+ one_tile.x1 = (int) ceil(pattern_tile[Geom::X].max());
+ one_tile.y1 = (int) ceil(pattern_tile[Geom::Y].max());
+
+ cairo_surface_t *target = cairo_get_target(base_ct);
+ cairo_surface_t *temp = cairo_surface_create_similar(target, CAIRO_CONTENT_COLOR_ALPHA,
+ c[Geom::X], c[Geom::Y]);
+ cairo_t *ct = cairo_create(temp);
+ // scale into a coord system where the surface w,h are equal to tile w,h
+ ink_cairo_transform(ct, t);
+
+ // render pattern.
+ if (needs_opacity) {
+ cairo_push_group(ct); // this group is for pattern + opacity
+ }
- /* Create arena */
- pp->arena = NRArena::create();
-
- pp->dkey = SPItem::display_key_new (1);
-
- /* Create group */
- pp->root = NRArenaGroup::create(pp->arena);
-
- /* Show items */
- pp->_release_connections = new std::map<SPObject *, sigc::connection>;
- for (SPPattern *pat_i = pat; pat_i != NULL; pat_i = pat_i->ref ? pat_i->ref->getObject() : NULL) {
- if (pat_i && SP_IS_OBJECT (pat_i) && pattern_hasItemChildren(pat_i)) { // find the first one with item children
- for (SPObject *child = pat_i->firstChild() ; child; child = child->getNext() ) {
- if (SP_IS_ITEM (child)) {
- // for each item in pattern,
- // show it on our arena,
- NRArenaItem *cai = SP_ITEM(child)->invoke_show(pp->arena, pp->dkey, SP_ITEM_REFERENCE_FLAGS);
- // add to the group,
- nr_arena_item_append_child (pp->root, cai);
- // and connect to the release signal in case the item gets deleted
- pp->_release_connections->insert(std::make_pair(child, child->connectRelease(sigc::bind<1>(sigc::ptr_fun(&sp_pattern_painter_release), pp))));
- }
- }
- break; // do not go further up the chain if children are found
- }
+ // TODO: make sure there are no leaks.
+ NRGC gc(NULL);
+ gc.transform = vb2ps;
+ nr_arena_item_invoke_update (root, NULL, &gc, NR_ARENA_ITEM_STATE_ALL, NR_ARENA_ITEM_STATE_ALL);
+ nr_arena_item_invoke_render (ct, root, &one_tile, NULL, 0);
+ for (SPObject *child = shown->firstChild() ; child != NULL; child = child->getNext() ) {
+ if (SP_IS_ITEM (child)) {
+ SP_ITEM(child)->invoke_hide(dkey);
}
+ }
+ nr_object_unref(root);
+ nr_object_unref(arena);
- {
- NRRect one_tile,tr_tile;
- one_tile.x0=pattern_x(pp->pat);
- one_tile.y0=pattern_y(pp->pat);
- one_tile.x1=one_tile.x0+pattern_width (pp->pat);
- one_tile.y1=one_tile.y0+pattern_height (pp->pat);
- // TODO: remove ps2px_nr after converting to 2geom
- NR::Matrix ps2px_nr = from_2geom(pp->ps2px);
- nr_rect_d_matrix_transform (&tr_tile, &one_tile, &ps2px_nr);
- int tr_width=(int)ceil(1.3*(tr_tile.x1-tr_tile.x0));
- int tr_height=(int)ceil(1.3*(tr_tile.y1-tr_tile.y0));
-// if ( tr_width < 10000 && tr_height < 10000 && tr_width*tr_height < 1000000 ) {
- pp->use_cached_tile=false;//true;
- if ( tr_width > 1000 ) tr_width=1000;
- if ( tr_height > 1000 ) tr_height=1000;
- pp->cached_bbox.x0=0;
- pp->cached_bbox.y0=0;
- pp->cached_bbox.x1=tr_width;
- pp->cached_bbox.y1=tr_height;
-
- if (pp->use_cached_tile) {
- nr_pixblock_setup (&pp->cached_tile,NR_PIXBLOCK_MODE_R8G8B8A8N, pp->cached_bbox.x0, pp->cached_bbox.y0, pp->cached_bbox.x1, pp->cached_bbox.y1,TRUE);
- }
-
- pp->pa2ca[0]=((double)tr_width)/(one_tile.x1-one_tile.x0);
- pp->pa2ca[1]=0;
- pp->pa2ca[2]=0;
- pp->pa2ca[3]=((double)tr_height)/(one_tile.y1-one_tile.y0);
- pp->pa2ca[4]=-one_tile.x0*pp->pa2ca[0];
- pp->pa2ca[5]=-one_tile.y0*pp->pa2ca[1];
- pp->ca2pa[0]=(one_tile.x1-one_tile.x0)/((double)tr_width);
- pp->ca2pa[1]=0;
- pp->ca2pa[2]=0;
- pp->ca2pa[3]=(one_tile.y1-one_tile.y0)/((double)tr_height);
- pp->ca2pa[4]=one_tile.x0;
- pp->ca2pa[5]=one_tile.y0;
-// } else {
-// pp->use_cached_tile=false;
-// }
- }
-
- NRGC gc(NULL);
- if ( pp->use_cached_tile ) {
- gc.transform=pp->pa2ca;
- } else {
- gc.transform = pp->pcs2px;
- }
- nr_arena_item_invoke_update (pp->root, NULL, &gc, NR_ARENA_ITEM_STATE_ALL, NR_ARENA_ITEM_STATE_ALL);
- if ( pp->use_cached_tile ) {
- nr_arena_item_invoke_render (NULL, pp->root, &pp->cached_bbox, &pp->cached_tile, 0);
- } else {
- // nothing to do now
- }
-
- return (SPPainter *) pp;
-}
-
-
-static void
-sp_pattern_painter_free (SPPaintServer */*ps*/, SPPainter *painter)
-{
- SPPatPainter *pp = (SPPatPainter *) painter;
- // free our arena
- if (pp->arena) {
- ((NRObject *) pp->arena)->unreference();
- pp->arena = NULL;
- }
-
- // disconnect all connections
- std::map<SPObject *, sigc::connection>::iterator iter;
- for (iter = pp->_release_connections->begin() ; iter!=pp->_release_connections->end() ; iter++) {
- iter->second.disconnect();
- }
- pp->_release_connections->clear();
- delete pp->_release_connections;
+ if (needs_opacity) {
+ cairo_pop_group_to_source(ct); // pop raw pattern
+ cairo_paint_with_alpha(ct, opacity); // apply opacity
+ }
- if ( pp->use_cached_tile ) nr_pixblock_release(&pp->cached_tile);
- g_free (pp);
-}
+ cairo_pattern_t *cp = cairo_pattern_create_for_surface(temp);
+ cairo_destroy(ct);
+ cairo_surface_destroy(temp);
-void
-get_cached_tile_pixel(SPPatPainter* pp,double x,double y,unsigned char &r,unsigned char &g,unsigned char &b,unsigned char &a)
-{
- int ca_h=(int)floor(x);
- int ca_v=(int)floor(y);
- int r_x=(int)floor(16*(x-floor(x)));
- int r_y=(int)floor(16*(y-floor(y)));
- unsigned int tl_m=(16-r_x)*(16-r_y);
- unsigned int bl_m=(16-r_x)*r_y;
- unsigned int tr_m=r_x*(16-r_y);
- unsigned int br_m=r_x*r_y;
- int cb_h=ca_h+1;
- int cb_v=ca_v+1;
- if ( cb_h >= pp->cached_bbox.x1 ) cb_h=0;
- if ( cb_v >= pp->cached_bbox.y1 ) cb_v=0;
-
- unsigned char* tlx=NR_PIXBLOCK_PX(&pp->cached_tile)+(ca_v*pp->cached_tile.rs)+4*ca_h;
- unsigned char* trx=NR_PIXBLOCK_PX(&pp->cached_tile)+(ca_v*pp->cached_tile.rs)+4*cb_h;
- unsigned char* blx=NR_PIXBLOCK_PX(&pp->cached_tile)+(cb_v*pp->cached_tile.rs)+4*ca_h;
- unsigned char* brx=NR_PIXBLOCK_PX(&pp->cached_tile)+(cb_v*pp->cached_tile.rs)+4*cb_h;
-
- unsigned int tl_c=tlx[0];
- unsigned int tr_c=trx[0];
- unsigned int bl_c=blx[0];
- unsigned int br_c=brx[0];
- unsigned int f_c=(tl_m*tl_c+tr_m*tr_c+bl_m*bl_c+br_m*br_c)>>8;
- r=f_c;
- tl_c=tlx[1];
- tr_c=trx[1];
- bl_c=blx[1];
- br_c=brx[1];
- f_c=(tl_m*tl_c+tr_m*tr_c+bl_m*bl_c+br_m*br_c)>>8;
- g=f_c;
- tl_c=tlx[2];
- tr_c=trx[2];
- bl_c=blx[2];
- br_c=brx[2];
- f_c=(tl_m*tl_c+tr_m*tr_c+bl_m*bl_c+br_m*br_c)>>8;
- b=f_c;
- tl_c=tlx[3];
- tr_c=trx[3];
- bl_c=blx[3];
- br_c=brx[3];
- f_c=(tl_m*tl_c+tr_m*tr_c+bl_m*bl_c+br_m*br_c)>>8;
- a=f_c;
-}
+ // Apply transformation to user space. Also compensate for oversampling.
+ ink_cairo_pattern_set_matrix(cp, ps2user.inverse() * t);
+ cairo_pattern_set_extend(cp, CAIRO_EXTEND_REPEAT);
-static void
-sp_pat_fill (SPPainter *painter, NRPixBlock *pb)
-{
- SPPatPainter *pp;
- NRRect ba, psa;
- NRRectL area;
- double x, y;
-
- pp = (SPPatPainter *) painter;
-
- if (pattern_width (pp->pat) < NR_EPSILON) return;
- if (pattern_height (pp->pat) < NR_EPSILON) return;
-
- bool grayscale = Grayscale::activeDesktopIsGrayscale(); // TODO: find good way to access the current rendermode
-
- /* Find buffer area in gradient space */
- /* fixme: This is suboptimal (Lauris) */
-
- if ( !grayscale && pp->use_cached_tile ) {
- double pat_w=pattern_width (pp->pat);
- double pat_h=pattern_height (pp->pat);
- if ( pb->mode == NR_PIXBLOCK_MODE_R8G8B8A8N || pb->mode == NR_PIXBLOCK_MODE_R8G8B8A8P ) { // same thing because it's filling an empty pixblock
- unsigned char* lpx=NR_PIXBLOCK_PX(pb);
- double px_y=pb->area.y0;
- for (int j=pb->area.y0;j<pb->area.y1;j++) {
- unsigned char* cpx=lpx;
- double px_x = pb->area.x0;
-
- double ps_x=pp->px2ps[0]*px_x+pp->px2ps[2]*px_y+pp->px2ps[4];
- double ps_y=pp->px2ps[1]*px_x+pp->px2ps[3]*px_y+pp->px2ps[5];
- for (int i=pb->area.x0;i<pb->area.x1;i++) {
- while ( ps_x > pat_w ) ps_x-=pat_w;
- while ( ps_x < 0 ) ps_x+=pat_w;
- while ( ps_y > pat_h ) ps_y-=pat_h;
- while ( ps_y < 0 ) ps_y+=pat_h;
- double ca_x=pp->pa2ca[0]*ps_x+pp->pa2ca[2]*ps_y+pp->pa2ca[4];
- double ca_y=pp->pa2ca[1]*ps_x+pp->pa2ca[3]*ps_y+pp->pa2ca[5];
- unsigned char n_a,n_r,n_g,n_b;
- get_cached_tile_pixel(pp,ca_x,ca_y,n_r,n_g,n_b,n_a);
- cpx[0]=n_r;
- cpx[1]=n_g;
- cpx[2]=n_b;
- cpx[3]=n_a;
-
- px_x+=1.0;
- ps_x+=pp->px2ps[0];
- ps_y+=pp->px2ps[1];
- cpx+=4;
- }
- px_y+=1.0;
- lpx+=pb->rs;
- }
- } else if ( pb->mode == NR_PIXBLOCK_MODE_R8G8B8 ) {
- unsigned char* lpx=NR_PIXBLOCK_PX(pb);
- double px_y=pb->area.y0;
- for (int j=pb->area.y0;j<pb->area.y1;j++) {
- unsigned char* cpx=lpx;
- double px_x = pb->area.x0;
-
- double ps_x=pp->px2ps[0]*px_x+pp->px2ps[2]*px_y+pp->px2ps[4];
- double ps_y=pp->px2ps[1]*px_x+pp->px2ps[3]*px_y+pp->px2ps[5];
- for (int i=pb->area.x0;i<pb->area.x1;i++) {
- while ( ps_x > pat_w ) ps_x-=pat_w;
- while ( ps_x < 0 ) ps_x+=pat_w;
- while ( ps_y > pat_h ) ps_y-=pat_h;
- while ( ps_y < 0 ) ps_y+=pat_h;
- double ca_x=pp->pa2ca[0]*ps_x+pp->pa2ca[2]*ps_y+pp->pa2ca[4];
- double ca_y=pp->pa2ca[1]*ps_x+pp->pa2ca[3]*ps_y+pp->pa2ca[5];
- unsigned char n_a,n_r,n_g,n_b;
- get_cached_tile_pixel(pp,ca_x,ca_y,n_r,n_g,n_b,n_a);
- cpx[0]=n_r;
- cpx[1]=n_g;
- cpx[2]=n_b;
-
- px_x+=1.0;
- ps_x+=pp->px2ps[0];
- ps_y+=pp->px2ps[1];
- cpx+=4;
- }
- px_y+=1.0;
- lpx+=pb->rs;
- }
- }
- } else {
- ba.x0 = pb->area.x0;
- ba.y0 = pb->area.y0;
- ba.x1 = pb->area.x1;
- ba.y1 = pb->area.y1;
-
- // Trying to solve this bug: https://bugs.launchpad.net/inkscape/+bug/167416
- // Bail out if the transformation matrix has extreme values. If we bail out
- // however, then something (which was meaningless anyway) won't be rendered,
- // which is better than getting stuck in a virtually infinite loop
- if (fabs(pp->px2ps[0]) < 1e6 &&
- fabs(pp->px2ps[3]) < 1e6 &&
- fabs(pp->px2ps[4]) < 1e6 &&
- fabs(pp->px2ps[5]) < 1e6)
- {
- // TODO: remove px2ps_nr after converting to 2geom
- NR::Matrix px2ps_nr = from_2geom(pp->px2ps);
- nr_rect_d_matrix_transform (&psa, &ba, &px2ps_nr);
-
- psa.x0 = floor ((psa.x0 - pattern_x (pp->pat)) / pattern_width (pp->pat)) -1;
- psa.y0 = floor ((psa.y0 - pattern_y (pp->pat)) / pattern_height (pp->pat)) -1;
- psa.x1 = ceil ((psa.x1 - pattern_x (pp->pat)) / pattern_width (pp->pat)) +1;
- psa.y1 = ceil ((psa.y1 - pattern_y (pp->pat)) / pattern_height (pp->pat)) +1;
-
- // If psa is too wide or tall, then something must be wrong! This is due to
- // nr_rect_d_matrix_transform (&psa, &ba, &pp->px2ps) using a weird transformation matrix pp->px2ps.
- g_assert(std::abs(psa.x1 - psa.x0) < 1e6);
- g_assert(std::abs(psa.y1 - psa.y0) < 1e6);
-
- for (y = psa.y0; y < psa.y1; y++) {
- for (x = psa.x0; x < psa.x1; x++) {
- NRPixBlock ppb;
- double psx, psy;
-
- psx = x * pattern_width (pp->pat);
- psy = y * pattern_height (pp->pat);
-
- area.x0 = (gint32)(pb->area.x0 - (pp->ps2px[0] * psx + pp->ps2px[2] * psy));
- area.y0 = (gint32)(pb->area.y0 - (pp->ps2px[1] * psx + pp->ps2px[3] * psy));
- area.x1 = area.x0 + pb->area.x1 - pb->area.x0;
- area.y1 = area.y0 + pb->area.y1 - pb->area.y0;
-
- // We do not update here anymore
-
- // Set up buffer
- // fixme: (Lauris)
- nr_pixblock_setup_extern (&ppb, pb->mode, area.x0, area.y0, area.x1, area.y1, NR_PIXBLOCK_PX (pb), pb->rs, FALSE, FALSE);
-
- Inkscape::ColorRenderMode saved_colormode = pp->root->arena->colorrendermode;
- if (grayscale) {
- pp->root->arena->colorrendermode = Inkscape::COLORRENDERMODE_GRAYSCALE;
- }
- nr_arena_item_invoke_render (NULL, pp->root, &area, &ppb, 0);
- pp->root->arena->colorrendermode = saved_colormode;
-
- nr_pixblock_release (&ppb);
- }
- }
- }
- }
+ return cp;
}
-
/*
Local Variables:
mode:c++
@@ -1055,4 +735,4 @@ sp_pat_fill (SPPainter *painter, NRPixBlock *pb)
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:encoding=utf-8:textwidth=99 :
diff --git a/src/sp-pattern.h b/src/sp-pattern.h
index 64544b3dc..1f545bfc4 100644
--- a/src/sp-pattern.h
+++ b/src/sp-pattern.h
@@ -28,7 +28,6 @@ GType sp_pattern_get_type (void);
class SPPatternClass;
#include <libnr/nr-rect.h>
-#include <libnr/nr-matrix.h>
#include "svg/svg-length.h"
#include "sp-paint-server.h"
#include "uri-references.h"
diff --git a/src/sp-rect.cpp b/src/sp-rect.cpp
index e8f79e6ed..94a453ae6 100644
--- a/src/sp-rect.cpp
+++ b/src/sp-rect.cpp
@@ -16,9 +16,7 @@
#endif
-#include <display/curve.h>
-#include <libnr/nr-matrix-ops.h>
-#include <libnr/nr-matrix-fns.h>
+#include "display/curve.h"
#include <2geom/rect.h>
#include "inkscape.h"
diff --git a/src/sp-root.cpp b/src/sp-root.cpp
index 8286bfc4f..b1eef65d2 100644
--- a/src/sp-root.cpp
+++ b/src/sp-root.cpp
@@ -27,11 +27,6 @@
#include "document.h"
#include "sp-defs.h"
#include "sp-root.h"
-#include <libnr/nr-matrix-fns.h>
-#include <libnr/nr-matrix-ops.h>
-#include <libnr/nr-matrix-translate-ops.h>
-#include <libnr/nr-scale-ops.h>
-#include <libnr/nr-translate-scale-ops.h>
#include <xml/repr.h>
#include "svg/stringstream.h"
#include "inkscape-version.h"
diff --git a/src/sp-shape.cpp b/src/sp-shape.cpp
index 358e2a595..ea79b6cee 100644
--- a/src/sp-shape.cpp
+++ b/src/sp-shape.cpp
@@ -18,10 +18,6 @@
# include "config.h"
#endif
-#include <libnr/nr-matrix-fns.h>
-#include <libnr/nr-matrix-ops.h>
-#include <libnr/nr-matrix-translate-ops.h>
-#include <libnr/nr-scale-matrix-ops.h>
#include <2geom/rect.h>
#include <2geom/transforms.h>
#include <2geom/pathvector.h>
@@ -249,7 +245,7 @@ void SPShape::sp_shape_update(SPObject *object, SPCtx *ctx, unsigned int flags)
SPStyle *style = object->style;
if (style->stroke_width.unit == SP_CSS_UNIT_PERCENT) {
SPItemCtx *ictx = (SPItemCtx *) ctx;
- double const aw = 1.0 / NR::expansion(ictx->i2vp);
+ double const aw = 1.0 / ictx->i2vp.descrim();
style->stroke_width.computed = style->stroke_width.value * aw;
for (SPItemView *v = ((SPItem *) (shape))->display; v != NULL; v = v->next) {
nr_arena_shape_set_style ((NRArenaShape *) v->arenaitem, style);
@@ -589,7 +585,7 @@ void SPShape::sp_shape_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const
// get bbox of the marker with that transform
NRRect marker_bbox;
- marker_item->invoke_bbox ( &marker_bbox, from_2geom(tr), true);
+ marker_item->invoke_bbox ( &marker_bbox, tr, true);
// union it with the shape bbox
nr_rect_d_union (&cbbox, &cbbox, &marker_bbox);
}
@@ -617,7 +613,7 @@ void SPShape::sp_shape_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const
}
tr = marker_item->transform * marker->c2p * tr * transform;
NRRect marker_bbox;
- marker_item->invoke_bbox ( &marker_bbox, from_2geom(tr), true);
+ marker_item->invoke_bbox ( &marker_bbox, tr, true);
nr_rect_d_union (&cbbox, &cbbox, &marker_bbox);
}
// MID position
@@ -644,7 +640,7 @@ void SPShape::sp_shape_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const
}
tr = marker_item->transform * marker->c2p * tr * transform;
NRRect marker_bbox;
- marker_item->invoke_bbox ( &marker_bbox, from_2geom(tr), true);
+ marker_item->invoke_bbox ( &marker_bbox, tr, true);
nr_rect_d_union (&cbbox, &cbbox, &marker_bbox);
}
diff --git a/src/sp-star.cpp b/src/sp-star.cpp
index 92d8cd7a5..39efe2537 100644
--- a/src/sp-star.cpp
+++ b/src/sp-star.cpp
@@ -19,6 +19,7 @@
#include <cstring>
#include <string>
+#include <glib.h>
#include <glibmm/i18n.h>
#include "svg/svg.h"
@@ -175,7 +176,7 @@ sp_star_set (SPObject *object, unsigned int key, const gchar *value)
case SP_ATTR_SODIPODI_SIDES:
if (value) {
star->sides = atoi (value);
- star->sides = NR_CLAMP(star->sides, 3, 1024);
+ star->sides = CLAMP(star->sides, 3, 1024);
} else {
star->sides = 5;
}
@@ -528,13 +529,13 @@ sp_star_position_set (SPStar *star, gint sides, Geom::Point center, gdouble r1,
g_return_if_fail (star != NULL);
g_return_if_fail (SP_IS_STAR (star));
- star->sides = NR_CLAMP(sides, 3, 1024);
+ star->sides = CLAMP(sides, 3, 1024);
star->center = center;
star->r[0] = MAX (r1, 0.001);
if (isflat == false) {
- star->r[1] = NR_CLAMP(r2, 0.0, star->r[0]);
+ star->r[1] = CLAMP(r2, 0.0, star->r[0]);
} else {
- star->r[1] = NR_CLAMP( r1*cos(M_PI/sides) ,0.0, star->r[0] );
+ star->r[1] = CLAMP( r1*cos(M_PI/sides) ,0.0, star->r[0] );
}
star->arg[0] = arg1;
star->arg[1] = arg2;
diff --git a/src/sp-symbol.cpp b/src/sp-symbol.cpp
index 70ab4d173..1d4bdec0f 100644
--- a/src/sp-symbol.cpp
+++ b/src/sp-symbol.cpp
@@ -17,8 +17,6 @@
#include <cstring>
#include <string>
-#include "libnr/nr-matrix-fns.h"
-#include "libnr/nr-matrix-ops.h"
#include <2geom/transforms.h>
#include "display/nr-arena-group.h"
#include "xml/repr.h"
diff --git a/src/sp-symbol.h b/src/sp-symbol.h
index 6c0a36d73..120591459 100644
--- a/src/sp-symbol.h
+++ b/src/sp-symbol.h
@@ -24,7 +24,6 @@
class SPSymbol;
class SPSymbolClass;
-#include <libnr/nr-matrix.h>
#include <2geom/affine.h>
#include <libnr/nr-rect.h>
#include "svg/svg-length.h"
diff --git a/src/sp-text.cpp b/src/sp-text.cpp
index 57f9dd14e..3f30c2422 100644
--- a/src/sp-text.cpp
+++ b/src/sp-text.cpp
@@ -28,7 +28,6 @@
#endif
#include <2geom/affine.h>
-#include <libnr/nr-matrix-fns.h>
#include <libnrtype/FontFactory.h>
#include <libnrtype/font-instance.h>
#include <libnrtype/font-style-to-pos.h>
@@ -624,7 +623,7 @@ void SPText::_adjustFontsizeRecursive(SPItem *item, double ex, bool is_root)
{
SPStyle *style = item->style;
- if (style && !NR_DF_TEST_CLOSE (ex, 1.0, NR_EPSILON)) {
+ if (style && !Geom::are_near(ex, 1.0)) {
if (!style->font_size.set && is_root) {
style->font_size.set = 1;
}
diff --git a/src/sp-tref.cpp b/src/sp-tref.cpp
index 7c4976a11..b301add7f 100644
--- a/src/sp-tref.cpp
+++ b/src/sp-tref.cpp
@@ -33,7 +33,6 @@
#include "uri.h"
#include "display/nr-arena-group.h"
-#include "libnr/nr-matrix-fns.h"
#include "xml/node.h"
#include "xml/repr.h"
diff --git a/src/sp-tspan.cpp b/src/sp-tspan.cpp
index 14e7452fe..199d82e1b 100644
--- a/src/sp-tspan.cpp
+++ b/src/sp-tspan.cpp
@@ -40,7 +40,6 @@
#include "sp-textpath.h"
#include "text-editing.h"
#include "style.h"
-#include "libnr/nr-matrix-fns.h"
#include "xml/repr.h"
#include "document.h"
@@ -593,9 +592,10 @@ sp_textpath_to_text(SPObject *tp)
{
SPObject *text = tp->parent;
- NRRect bbox;
- SP_ITEM(text)->invoke_bbox( &bbox, SP_ITEM(text)->i2doc_affine(), TRUE);
- Geom::Point xy(bbox.x0, bbox.y0);
+ Geom::OptRect bbox;
+ SP_ITEM(text)->invoke_bbox(bbox, SP_ITEM(text)->i2doc_affine(), TRUE);
+ if (!bbox) return;
+ Geom::Point xy = bbox->min();
// make a list of textpath children
GSList *tp_reprs = NULL;
diff --git a/src/sp-use.cpp b/src/sp-use.cpp
index a92dbcaa9..a05b28a5f 100644
--- a/src/sp-use.cpp
+++ b/src/sp-use.cpp
@@ -20,8 +20,6 @@
#include <cstring>
#include <string>
-#include <libnr/nr-matrix-ops.h>
-#include <libnr/nr-matrix-fns.h>
#include <2geom/transforms.h>
#include <glibmm/i18n.h>
#include "display/nr-arena-group.h"
diff --git a/src/splivarot.cpp b/src/splivarot.cpp
index 5ff394782..3d3027639 100644
--- a/src/splivarot.cpp
+++ b/src/splivarot.cpp
@@ -45,7 +45,6 @@
#include "xml/repr.h"
#include "xml/repr-sorting.h"
#include <2geom/pathvector.h>
-#include <libnr/nr-scale-matrix-ops.h>
#include "helper/geom.h"
#include "livarot/Path.h"
diff --git a/src/spray-context.cpp b/src/spray-context.cpp
index 553edf69b..36c135924 100644
--- a/src/spray-context.cpp
+++ b/src/spray-context.cpp
@@ -35,13 +35,9 @@
#include "desktop.h"
#include "desktop-events.h"
#include "desktop-handles.h"
-#include "unistd.h"
-//#include "desktop-style.h"
#include "message-context.h"
#include "pixmaps/cursor-spray.xpm"
#include <boost/optional.hpp>
-#include "libnr/nr-matrix-ops.h"
-#include "libnr/nr-scale-translate-ops.h"
#include "xml/repr.h"
#include "context-fns.h"
#include "sp-item.h"
diff --git a/src/star-context.cpp b/src/star-context.cpp
index 0fb20a2ab..9f4afb94c 100644
--- a/src/star-context.cpp
+++ b/src/star-context.cpp
@@ -457,14 +457,14 @@ static void sp_star_drag(SPStarContext *sc, Geom::Point p, guint state)
double const sides = (gdouble) sc->magnitude;
Geom::Point const d = p1 - p0;
Geom::Coord const r1 = Geom::L2(d);
- double arg1 = atan2(from_2geom(d));
+ double arg1 = atan2(d);
if (state & GDK_CONTROL_MASK) {
/* Snap angle */
arg1 = sp_round(arg1, M_PI / snaps);
}
- sp_star_position_set(star, sc->magnitude, from_2geom(p0), r1, r1 * sc->proportion,
+ sp_star_position_set(star, sc->magnitude, p0, r1, r1 * sc->proportion,
arg1, arg1 + M_PI / sides, sc->isflatsided, sc->rounded, sc->randomized);
/* status text */
diff --git a/src/svg/svg-affine.cpp b/src/svg/svg-affine.cpp
index 69685e04c..a986e5986 100644
--- a/src/svg/svg-affine.cpp
+++ b/src/svg/svg-affine.cpp
@@ -20,11 +20,8 @@
#include <cstdlib>
#include <cstdio>
#include <glib/gstrfuncs.h>
-#include <libnr/nr-matrix-fns.h>
-#include <libnr/nr-matrix-ops.h>
#include <2geom/transforms.h>
#include <2geom/angle.h>
-#include <libnr/nr-convert2geom.h>
#include "svg.h"
#include "preferences.h"
diff --git a/src/text-chemistry.cpp b/src/text-chemistry.cpp
index b1b31b6f6..873c214a7 100644
--- a/src/text-chemistry.cpp
+++ b/src/text-chemistry.cpp
@@ -19,7 +19,6 @@
#include <string>
#include <glibmm/i18n.h>
-#include "libnr/nr-matrix-fns.h"
#include "xml/repr.h"
#include "sp-rect.h"
#include "sp-textpath.h"
@@ -151,7 +150,7 @@ text_put_on_path()
Inkscape::Text::Layout::Alignment text_alignment = layout->paragraphAlignment(layout->begin());
// remove transform from text, but recursively scale text's fontsize by the expansion
- SP_TEXT(text)->_adjustFontsizeRecursive (text, NR::expansion(SP_ITEM(text)->transform));
+ SP_TEXT(text)->_adjustFontsizeRecursive (text, SP_ITEM(text)->transform.descrim());
text->getRepr()->setAttribute("transform", NULL);
// make a list of text children
@@ -317,7 +316,7 @@ text_flow_into_shape()
if (SP_IS_TEXT(text)) {
// remove transform from text, but recursively scale text's fontsize by the expansion
- SP_TEXT(text)->_adjustFontsizeRecursive(text, NR::expansion(SP_ITEM(text)->transform));
+ SP_TEXT(text)->_adjustFontsizeRecursive(text, SP_ITEM(text)->transform.descrim());
text->getRepr()->setAttribute("transform", NULL);
}
@@ -433,10 +432,10 @@ text_unflow ()
/* Set style */
rtext->setAttribute("style", flowtext->getRepr()->attribute("style")); // fixme: transfer style attrs too; and from descendants
- NRRect bbox;
- SP_ITEM(flowtext)->invoke_bbox( &bbox, SP_ITEM(flowtext)->i2doc_affine(), TRUE);
- Geom::Point xy(bbox.x0, bbox.y0);
- if (xy[Geom::X] != 1e18 && xy[Geom::Y] != 1e18) {
+ Geom::OptRect bbox;
+ SP_ITEM(flowtext)->invoke_bbox(bbox, SP_ITEM(flowtext)->i2doc_affine(), TRUE);
+ if (bbox) {
+ Geom::Point xy = bbox->min();
sp_repr_set_svg_double(rtext, "x", xy[Geom::X]);
sp_repr_set_svg_double(rtext, "y", xy[Geom::Y]);
}
diff --git a/src/text-editing.cpp b/src/text-editing.cpp
index 003af245d..18264fa56 100644
--- a/src/text-editing.cpp
+++ b/src/text-editing.cpp
@@ -1160,7 +1160,7 @@ sp_te_adjust_tspan_letterspacing_screen(SPItem *text, Inkscape::Text::Layout::it
gdouble const zoom = desktop->current_zoom();
gdouble const zby = (by
/ (zoom * (nb_let > 1 ? nb_let - 1 : 1))
- / to_2geom(SP_ITEM(source_obj)->i2doc_affine()).descrim());
+ / SP_ITEM(source_obj)->i2doc_affine().descrim());
val += zby;
if (start == end) {
diff --git a/src/trace/trace.cpp b/src/trace/trace.cpp
index 1ee32e6bf..813f532a4 100644
--- a/src/trace/trace.cpp
+++ b/src/trace/trace.cpp
@@ -16,24 +16,23 @@
#include "trace/potrace/inkscape-potrace.h"
-#include <inkscape.h>
-#include <desktop.h>
-#include <desktop-handles.h>
-#include <document.h>
-#include <message-stack.h>
+#include "inkscape.h"
+#include "desktop.h"
+#include "desktop-handles.h"
+#include "document.h"
+#include "message-stack.h"
#include <gtkmm.h>
#include <glibmm/i18n.h>
-#include <selection.h>
-#include <xml/repr.h>
-#include <xml/attribute-record.h>
-#include <sp-item.h>
-#include <sp-shape.h>
-#include <sp-image.h>
-#include <libnr/nr-matrix-ops.h>
+#include "selection.h"
+#include "xml/repr.h"
+#include "xml/attribute-record.h"
+#include "sp-item.h"
+#include "sp-shape.h"
+#include "sp-image.h"
#include <2geom/transforms.h>
-#include <display/nr-arena.h>
-#include <display/nr-arena-shape.h>
+#include "display/nr-arena.h"
+#include "display/nr-arena-shape.h"
#include "siox.h"
#include "imagemap-gdk.h"
diff --git a/src/transf_mat_3x4.h b/src/transf_mat_3x4.h
index 69174d9df..8542e5e00 100644
--- a/src/transf_mat_3x4.h
+++ b/src/transf_mat_3x4.h
@@ -29,7 +29,7 @@ public:
void toggle_finite (Proj::Axis axis);
double get_infinite_angle (Proj::Axis axis) {
if (has_finite_image(axis)) {
- return 1e18; //this used to be NR_HUGE before 2geom conversion
+ return Geom::infinity();
}
Pt2 vp(column(axis));
return Geom::atan2(Geom::Point(vp[0], vp[1])) * 180.0/M_PI;
diff --git a/src/tweak-context.cpp b/src/tweak-context.cpp
index aef7dfba9..faa08ee91 100644
--- a/src/tweak-context.cpp
+++ b/src/tweak-context.cpp
@@ -39,8 +39,6 @@
#include "pixmaps/cursor-roughen.xpm"
#include "pixmaps/cursor-color.xpm"
#include <boost/optional.hpp>
-#include "libnr/nr-matrix-ops.h"
-#include "libnr/nr-scale-translate-ops.h"
#include "xml/repr.h"
#include "context-fns.h"
#include "sp-item.h"
@@ -72,8 +70,7 @@
#include "box3d.h"
#include "sp-item-transform.h"
#include "filter-chemistry.h"
-#include "sp-gaussian-blur-fns.h"
-#include "sp-gaussian-blur.h"
+#include "filters/gaussian-blur.h"
#include "tweak-context.h"
diff --git a/src/ui/cache/svg_preview_cache.cpp b/src/ui/cache/svg_preview_cache.cpp
index a7ad1701d..fd7070bab 100644
--- a/src/ui/cache/svg_preview_cache.cpp
+++ b/src/ui/cache/svg_preview_cache.cpp
@@ -28,6 +28,7 @@
#include "document-private.h"
#include "display/nr-arena.h"
#include "display/nr-arena-item.h"
+#include "display/cairo-utils.h"
#include "ui/cache/svg_preview_cache.h"
@@ -44,10 +45,10 @@ GdkPixbuf* render_pixbuf(NRArenaItem* root, double scale_factor, const Geom::Rec
/* Item integer bbox in points */
NRRectL ibox;
- ibox.x0 = (int) floor(scale_factor * dbox.min()[Geom::X] + 0.5);
- ibox.y0 = (int) floor(scale_factor * dbox.min()[Geom::Y] + 0.5);
- ibox.x1 = (int) floor(scale_factor * dbox.max()[Geom::X] + 0.5);
- ibox.y1 = (int) floor(scale_factor * dbox.max()[Geom::Y] + 0.5);
+ ibox.x0 = floor(scale_factor * dbox.min()[Geom::X]);
+ ibox.y0 = floor(scale_factor * dbox.min()[Geom::Y]);
+ ibox.x1 = ceil(scale_factor * dbox.max()[Geom::X]);
+ ibox.y1 = ceil(scale_factor * dbox.max()[Geom::Y]);
/* Find visible area */
int width = ibox.x1 - ibox.x0;
@@ -63,34 +64,24 @@ GdkPixbuf* render_pixbuf(NRArenaItem* root, double scale_factor, const Geom::Rec
area.x1 = area.x0 + psize;
area.y1 = area.y0 + psize;
- /* Actual renderable area */
- NRRectL ua;
- ua.x0 = std::max(ibox.x0, area.x0);
- ua.y0 = std::max(ibox.y0, area.y0);
- ua.x1 = std::min(ibox.x1, area.x1);
- ua.y1 = std::min(ibox.y1, area.y1);
-
- /* Set up pixblock */
- guchar *px = g_new(guchar, 4 * psize * psize);
- memset(px, 0x00, 4 * psize * psize);
-
/* Render */
- NRPixBlock B;
- nr_pixblock_setup_extern( &B, NR_PIXBLOCK_MODE_R8G8B8A8N,
- ua.x0, ua.y0, ua.x1, ua.y1,
- px + 4 * psize * (ua.y0 - area.y0) +
- 4 * (ua.x0 - area.x0),
- 4 * psize, FALSE, FALSE );
- nr_arena_item_invoke_render(NULL, root, &ua, &B,
+ cairo_surface_t *s = cairo_image_surface_create(
+ CAIRO_FORMAT_ARGB32, psize, psize);
+ cairo_t *ct = cairo_create(s);
+ cairo_translate(ct, -area.x0, -area.y0);
+
+ nr_arena_item_invoke_render(ct, root, &area, NULL,
NR_ARENA_ITEM_RENDER_NO_CACHE );
- nr_pixblock_release(&B);
+ cairo_surface_flush(s);
+ cairo_destroy(ct);
- GdkPixbuf* pixbuf = gdk_pixbuf_new_from_data(px,
+ GdkPixbuf* pixbuf = gdk_pixbuf_new_from_data(cairo_image_surface_get_data(s),
GDK_COLORSPACE_RGB,
TRUE,
- 8, psize, psize, psize * 4,
- (GdkPixbufDestroyNotify)g_free,
+ 8, psize, psize, cairo_image_surface_get_stride(s),
+ (GdkPixbufDestroyNotify)cairo_surface_destroy,
NULL);
+ convert_pixbuf_argb32_to_normal(pixbuf);
return pixbuf;
}
diff --git a/src/ui/dialog/color-item.cpp b/src/ui/dialog/color-item.cpp
index da8393fc5..89245575c 100644
--- a/src/ui/dialog/color-item.cpp
+++ b/src/ui/dialog/color-item.cpp
@@ -13,6 +13,7 @@
#include <errno.h>
#include <glibmm/i18n.h>
#include <gtkmm/label.h>
+#include <cairo.h>
#include <gtk/gtk.h>
#include "color-item.h"
@@ -20,7 +21,7 @@
#include "desktop.h"
#include "desktop-handles.h"
#include "desktop-style.h"
-#include "display/nr-plain-stuff.h"
+#include "display/cairo-utils.h"
#include "document.h"
#include "inkscape.h" // for SP_ACTIVE_DESKTOP
#include "io/resource.h"
@@ -212,17 +213,20 @@ static void colorItemDragBegin( GtkWidget */*widget*/, GdkDragContext* dc, gpoin
} else {
GdkPixbuf* pixbuf = 0;
if ( item->getGradient() ){
- guchar* px = g_new( guchar, 3 * height * width );
- nr_render_checkerboard_rgb( px, width, height, 3 * width, 0, 0 );
-
- sp_gradient_render_vector_block_rgb( item->getGradient(),
- px, width, height, 3 * width,
- 0, width, TRUE );
-
- pixbuf = gdk_pixbuf_new_from_data( px, GDK_COLORSPACE_RGB, FALSE, 8,
- width, height, width * 3,
- 0, // add delete function
- 0 );
+ cairo_surface_t *s = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
+ cairo_pattern_t *gradient = sp_gradient_create_preview_pattern(item->getGradient(), width);
+ cairo_t *ct = cairo_create(s);
+ cairo_set_source(ct, gradient);
+ cairo_paint(ct);
+ cairo_destroy(ct);
+ cairo_pattern_destroy(gradient);
+ cairo_surface_flush(s);
+
+ pixbuf = gdk_pixbuf_new_from_data(cairo_image_surface_get_data(s),
+ GDK_COLORSPACE_RGB, TRUE, 8,
+ width, height, cairo_image_surface_get_stride(s),
+ (GdkPixbufDestroyNotify) cairo_surface_destroy, NULL);
+ convert_pixbuf_argb32_to_normal(pixbuf);
} else {
Glib::RefPtr<Gdk::Pixbuf> thumb = Gdk::Pixbuf::create( Gdk::COLORSPACE_RGB, false, 8, width, height );
guint32 fillWith = (0xff000000 & (item->def.getR() << 24))
@@ -252,10 +256,8 @@ static void colorItemDragBegin( GtkWidget */*widget*/, GdkDragContext* dc, gpoin
// }
-SwatchPage::SwatchPage() :
- _name(),
- _prefWidth(0),
- _colors()
+SwatchPage::SwatchPage()
+ : _prefWidth(0)
{
}
@@ -265,10 +267,7 @@ SwatchPage::~SwatchPage()
ColorItem::ColorItem(ege::PaintDef::ColorType type) :
- Previewable(),
def(type),
- tips(),
- _previews(),
_isFill(false),
_isStroke(false),
_isLive(false),
@@ -277,18 +276,12 @@ ColorItem::ColorItem(ege::PaintDef::ColorType type) :
_linkGray(0),
_linkSrc(0),
_grad(0),
- _pixData(0),
- _pixWidth(0),
- _pixHeight(0),
- _listeners()
+ _pattern(0)
{
}
ColorItem::ColorItem( unsigned int r, unsigned int g, unsigned int b, Glib::ustring& name ) :
- Previewable(),
def( r, g, b, name ),
- tips(),
- _previews(),
_isFill(false),
_isStroke(false),
_isLive(false),
@@ -297,15 +290,15 @@ ColorItem::ColorItem( unsigned int r, unsigned int g, unsigned int b, Glib::ustr
_linkGray(0),
_linkSrc(0),
_grad(0),
- _pixData(0),
- _pixWidth(0),
- _pixHeight(0),
- _listeners()
+ _pattern(0)
{
}
ColorItem::~ColorItem()
{
+ if (_pattern != NULL) {
+ cairo_pattern_destroy(_pattern);
+ }
}
ColorItem::ColorItem(ColorItem const &other) :
@@ -361,18 +354,16 @@ void ColorItem::setGradient(SPGradient *grad)
}
}
-void ColorItem::setPixData(guchar* px, int width, int height)
+void ColorItem::setPattern(cairo_pattern_t *pattern)
{
- if (px != _pixData) {
- if (_pixData) {
- g_free(_pixData);
- }
- _pixData = px;
- _pixWidth = width;
- _pixHeight = height;
-
- _updatePreviews();
+ if (pattern) {
+ cairo_pattern_reference(pattern);
+ }
+ if (_pattern) {
+ cairo_pattern_destroy(_pattern);
}
+ _pattern = pattern;
+ _updatePreviews();
}
void ColorItem::_dragGetColorData( GtkWidget */*widget*/,
@@ -520,16 +511,28 @@ void ColorItem::_regenPreview(EekPreview * preview)
eek_preview_set_pixbuf( preview, pixbuf );
}
- else if ( !_pixData ){
+ else if ( !_pattern ){
eek_preview_set_color( preview,
(def.getR() << 8) | def.getR(),
(def.getG() << 8) | def.getG(),
(def.getB() << 8) | def.getB() );
} else {
- GdkPixbuf* pixbuf = gdk_pixbuf_new_from_data( _pixData, GDK_COLORSPACE_RGB, FALSE, 8,
- _pixWidth, _pixHeight, _pixWidth * 3,
- 0, // add delete function
- 0 );
+ double w;
+ cairo_pattern_get_linear_points(_pattern, NULL, NULL, &w, NULL);
+ int width = ceil(w);
+
+ cairo_surface_t *s = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, 1);
+ cairo_t *ct = cairo_create(s);
+ cairo_set_source(ct, _pattern);
+ cairo_paint(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,
+ width, 1, cairo_image_surface_get_stride(s),
+ (GdkPixbufDestroyNotify) cairo_surface_destroy, NULL);
+ convert_pixbuf_argb32_to_normal(pixbuf);
eek_preview_set_pixbuf( preview, pixbuf );
}
diff --git a/src/ui/dialog/color-item.h b/src/ui/dialog/color-item.h
index a6e344ce3..9080498eb 100644
--- a/src/ui/dialog/color-item.h
+++ b/src/ui/dialog/color-item.h
@@ -58,8 +58,7 @@ public:
void setGradient(SPGradient *grad);
SPGradient * getGradient() const { return _grad; }
-
- void setPixData(guchar* px, int width, int height);
+ void setPattern(cairo_pattern_t *pattern);
void setState( bool fill, bool stroke );
bool isFill() { return _isFill; }
@@ -104,9 +103,7 @@ private:
int _linkGray;
ColorItem* _linkSrc;
SPGradient* _grad;
- guchar *_pixData;
- int _pixWidth;
- int _pixHeight;
+ cairo_pattern_t *_pattern;
std::vector<ColorItem*> _listeners;
};
diff --git a/src/ui/dialog/filedialogimpl-win32.cpp b/src/ui/dialog/filedialogimpl-win32.cpp
index 09c3d0a52..e83aeccad 100644
--- a/src/ui/dialog/filedialogimpl-win32.cpp
+++ b/src/ui/dialog/filedialogimpl-win32.cpp
@@ -29,15 +29,13 @@
//Inkscape includes
#include "inkscape.h"
-#include <dialogs/dialog-events.h>
-#include <extension/input.h>
-#include <extension/output.h>
-#include <extension/db.h>
-
-#include <libnr/nr-pixops.h>
-#include <libnr/nr-translate-scale-ops.h>
-#include <display/nr-arena-item.h>
-#include <display/nr-arena.h>
+#include "dialogs/dialog-events.h"
+#include "extension/input.h"
+#include "extension/output.h"
+#include "extension/db.h"
+
+#include "display/nr-arena-item.h"
+#include "display/nr-arena.h"
#include "sp-item.h"
#include "display/canvas-arena.h"
@@ -955,6 +953,10 @@ void FileOpenDialogImplWin32::free_preview()
bool FileOpenDialogImplWin32::set_svg_preview()
{
+ return false;
+ // NOTE: it's not worth the effort to fix this to use Cairo.
+ // Native file dialogs are unmaintainable and should be removed anyway.
+ #if 0
const int PreviewSize = 512;
gchar *utf8string = g_utf16_to_utf8((const gunichar2*)_path_string,
@@ -1055,6 +1057,7 @@ bool FileOpenDialogImplWin32::set_svg_preview()
_mutex->unlock();
return true;
+ #endif
}
void FileOpenDialogImplWin32::destroy_svg_rendering(const guint8 *buffer)
diff --git a/src/ui/dialog/filter-effects-dialog.cpp b/src/ui/dialog/filter-effects-dialog.cpp
index 2e17daa11..c6d81b070 100644
--- a/src/ui/dialog/filter-effects-dialog.cpp
+++ b/src/ui/dialog/filter-effects-dialog.cpp
@@ -48,13 +48,13 @@
#include "filters/convolvematrix.h"
#include "filters/displacementmap.h"
#include "filters/distantlight.h"
+#include "filters/gaussian-blur.h"
#include "filters/merge.h"
#include "filters/mergenode.h"
#include "filters/offset.h"
#include "filters/pointlight.h"
#include "filters/spotlight.h"
#include "sp-filter-primitive.h"
-#include "sp-gaussian-blur.h"
#include "style.h"
#include "svg/svg-color.h"
diff --git a/src/ui/dialog/icon-preview.cpp b/src/ui/dialog/icon-preview.cpp
index bb566fb7f..4d98793bb 100644
--- a/src/ui/dialog/icon-preview.cpp
+++ b/src/ui/dialog/icon-preview.cpp
@@ -39,7 +39,7 @@ extern "C" {
// takes doc, root, icon, and icon name to produce pixels
guchar *
sp_icon_doc_icon( SPDocument *doc, NRArenaItem *root,
- const gchar *name, unsigned int psize );
+ const gchar *name, unsigned int psize, unsigned &stride);
}
#define noICON_VERBOSE 1
@@ -167,10 +167,11 @@ IconPreviewPanel::IconPreviewPanel() :
int previous = 0;
int avail = 0;
for ( int i = numEntries - 1; i >= 0; --i ) {
- pixMem[i] = new guchar[4 * sizes[i] * sizes[i]];
- memset( pixMem[i], 0x00, 4 * sizes[i] * sizes[i] );
+ int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, sizes[i]);
+ pixMem[i] = new guchar[sizes[i] * stride];
+ memset( pixMem[i], 0x00, sizes[i] * stride );
- GdkPixbuf *pb = gdk_pixbuf_new_from_data( pixMem[i], GDK_COLORSPACE_RGB, TRUE, 8, sizes[i], sizes[i], sizes[i] * 4, /*(GdkPixbufDestroyNotify)g_free*/NULL, NULL );
+ GdkPixbuf *pb = gdk_pixbuf_new_from_data( pixMem[i], GDK_COLORSPACE_RGB, TRUE, 8, sizes[i], sizes[i], stride, /*(GdkPixbufDestroyNotify)g_free*/NULL, NULL );
GtkImage* img = GTK_IMAGE( gtk_image_new_from_pixbuf( pb ) );
images[i] = Glib::wrap(img);
Glib::ustring label(*labels[i]);
@@ -449,14 +450,16 @@ void IconPreviewPanel::renderPreview( SPObject* obj )
root = SP_ITEM( doc->getRoot() )->invoke_show( arena, visionkey, SP_ITEM_SHOW_DISPLAY );
for ( int i = 0; i < numEntries; i++ ) {
- guchar * px = sp_icon_doc_icon( doc, root, id, sizes[i] );
+ unsigned unused;
+ int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, sizes[i]);
+ guchar * px = sp_icon_doc_icon( doc, root, id, sizes[i], unused);
// g_message( " size %d %s", sizes[i], (px ? "worked" : "failed") );
if ( px ) {
- memcpy( pixMem[i], px, sizes[i] * sizes[i] * 4 );
+ memcpy( pixMem[i], px, sizes[i] * stride );
g_free( px );
px = 0;
} else {
- memset( pixMem[i], 0, sizes[i] * sizes[i] * 4 );
+ memset( pixMem[i], 0, sizes[i] * stride );
}
images[i]->queue_draw();
}
diff --git a/src/ui/dialog/swatches.cpp b/src/ui/dialog/swatches.cpp
index cbae7c26f..ad3b79630 100644
--- a/src/ui/dialog/swatches.cpp
+++ b/src/ui/dialog/swatches.cpp
@@ -46,7 +46,7 @@
#include "widgets/desktop-widget.h"
#include "widgets/gradient-vector.h"
#include "widgets/eek-preview.h"
-#include "display/nr-plain-stuff.h"
+#include "display/cairo-utils.h"
#include "sp-gradient-reference.h"
#include "dialog-manager.h"
@@ -886,7 +886,7 @@ void SwatchesPanel::_setDocument( SPDocument *document )
static void recalcSwatchContents(SPDocument* doc,
std::vector<ColorItem*> &tmpColors,
- std::map<ColorItem*, guchar*> &previewMappings,
+ std::map<ColorItem*, cairo_pattern_t*> &previewMappings,
std::map<ColorItem*, SPGradient*> &gradMappings)
{
std::vector<SPGradient*> newList;
@@ -904,30 +904,29 @@ static void recalcSwatchContents(SPDocument* doc,
for ( std::vector<SPGradient*>::iterator it = newList.begin(); it != newList.end(); ++it )
{
SPGradient* grad = *it;
- grad->ensureVector();
- SPGradientStop first = grad->vector.stops[0];
- SPColor color = first.color;
- guint32 together = color.toRGBA32(first.opacity);
- SPGradientStop second = (*it)->vector.stops[1];
- SPColor color2 = second.color;
+ cairo_surface_t *preview = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
+ PREVIEW_PIXBUF_WIDTH, VBLOCK);
+ cairo_t *ct = cairo_create(preview);
Glib::ustring name( grad->getId() );
- unsigned int r = SP_RGBA32_R_U(together);
- unsigned int g = SP_RGBA32_G_U(together);
- unsigned int b = SP_RGBA32_B_U(together);
- ColorItem* item = new ColorItem( r, g, b, name );
+ ColorItem* item = new ColorItem( 0, 0, 0, name );
- gint width = PREVIEW_PIXBUF_WIDTH;
- gint height = VBLOCK;
- guchar* px = g_new( guchar, 3 * height * width );
- nr_render_checkerboard_rgb( px, width, height, 3 * width, 0, 0 );
+ cairo_pattern_t *check = ink_cairo_pattern_create_checkerboard();
+ cairo_pattern_t *gradient = sp_gradient_create_preview_pattern(grad, PREVIEW_PIXBUF_WIDTH);
+ cairo_set_source(ct, check);
+ cairo_paint(ct);
+ cairo_set_source(ct, gradient);
+ cairo_paint(ct);
- sp_gradient_render_vector_block_rgb( grad,
- px, width, height, 3 * width,
- 0, width, TRUE );
+ cairo_destroy(ct);
+ cairo_pattern_destroy(gradient);
+ cairo_pattern_destroy(check);
- previewMappings[item] = px;
+ cairo_pattern_t *prevpat = cairo_pattern_create_for_surface(preview);
+ cairo_surface_destroy(preview);
+
+ previewMappings[item] = prevpat;
tmpColors.push_back(item);
gradMappings[item] = grad;
@@ -940,12 +939,13 @@ void SwatchesPanel::handleGradientsChange(SPDocument *document)
SwatchPage *docPalette = (docPalettes.find(document) != docPalettes.end()) ? docPalettes[document] : 0;
if (docPalette) {
std::vector<ColorItem*> tmpColors;
- std::map<ColorItem*, guchar*> tmpPrevs;
+ std::map<ColorItem*, cairo_pattern_t*> tmpPrevs;
std::map<ColorItem*, SPGradient*> tmpGrads;
recalcSwatchContents(document, tmpColors, tmpPrevs, tmpGrads);
- for (std::map<ColorItem*, guchar*>::iterator it = tmpPrevs.begin(); it != tmpPrevs.end(); ++it) {
- it->first->setPixData(it->second, PREVIEW_PIXBUF_WIDTH, VBLOCK);
+ for (std::map<ColorItem*, cairo_pattern_t*>::iterator it = tmpPrevs.begin(); it != tmpPrevs.end(); ++it) {
+ it->first->setPattern(it->second);
+ cairo_pattern_destroy(it->second);
}
for (std::map<ColorItem*, SPGradient*>::iterator it = tmpGrads.begin(); it != tmpGrads.end(); ++it) {
@@ -957,7 +957,6 @@ void SwatchesPanel::handleGradientsChange(SPDocument *document)
delete *it;
}
-
// Figure out which SwatchesPanel instances are affected and update them.
for (std::map<SwatchesPanel*, SPDocument*>::iterator it = docPerPanel.begin(); it != docPerPanel.end(); ++it) {
@@ -978,7 +977,7 @@ void SwatchesPanel::handleDefsModified(SPDocument *document)
SwatchPage *docPalette = (docPalettes.find(document) != docPalettes.end()) ? docPalettes[document] : 0;
if (docPalette && !DocTrack::queueUpdateIfNeeded(document) ) {
std::vector<ColorItem*> tmpColors;
- std::map<ColorItem*, guchar*> tmpPrevs;
+ std::map<ColorItem*, cairo_pattern_t*> tmpPrevs;
std::map<ColorItem*, SPGradient*> tmpGrads;
recalcSwatchContents(document, tmpColors, tmpPrevs, tmpGrads);
@@ -999,10 +998,17 @@ void SwatchesPanel::handleDefsModified(SPDocument *document)
oldColor->setGradient(tmpGrads[newColor]);
}
if ( tmpPrevs.find(newColor) != tmpPrevs.end() ) {
- oldColor->setPixData(tmpPrevs[newColor], PREVIEW_PIXBUF_WIDTH, VBLOCK);
+ oldColor->setPattern(tmpPrevs[newColor]);
}
}
}
+
+ for (std::map<ColorItem*, cairo_pattern_t*>::iterator it = tmpPrevs.begin(); it != tmpPrevs.end(); ++it) {
+ cairo_pattern_destroy(it->second);
+ }
+ for (std::vector<ColorItem*>::iterator it = tmpColors.begin(); it != tmpColors.end(); ++it) {
+ delete *it;
+ }
}
}
diff --git a/src/ui/dialog/transformation.cpp b/src/ui/dialog/transformation.cpp
index 38664fd3a..901d02240 100644
--- a/src/ui/dialog/transformation.cpp
+++ b/src/ui/dialog/transformation.cpp
@@ -21,7 +21,6 @@
#include "desktop-handles.h"
#include "transformation.h"
#include "align-and-distribute.h"
-#include "libnr/nr-matrix-ops.h"
#include "inkscape.h"
#include "selection.h"
#include "selection-chemistry.h"
diff --git a/src/ui/widget/color-preview.cpp b/src/ui/widget/color-preview.cpp
index add596444..a4212c7ba 100644
--- a/src/ui/widget/color-preview.cpp
+++ b/src/ui/widget/color-preview.cpp
@@ -11,8 +11,8 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include "display/nr-plain-stuff-gdk.h"
-#include "color-preview.h"
+#include "ui/widget/color-preview.h"
+#include "display/cairo-utils.h"
#define SPCP_DEFAULT_WIDTH 32
#define SPCP_DEFAULT_HEIGHT 12
@@ -76,6 +76,9 @@ ColorPreview::paint (GdkRectangle *area)
if (!gdk_rectangle_intersect (area, &warea, &wpaint))
return;
+ GtkWidget *widget = GTK_WIDGET(this->gobj());
+ cairo_t *ct = gdk_cairo_create(widget->window);
+
/* Transparent area */
w2 = warea.width / 2;
@@ -86,11 +89,15 @@ ColorPreview::paint (GdkRectangle *area)
carea.height = warea.height;
if (gdk_rectangle_intersect (area, &carea, &cpaint)) {
- nr_gdk_draw_rgba32_solid (get_window()->gobj(),
- get_style()->get_black_gc()->gobj(),
- cpaint.x, cpaint.y,
- cpaint.width, cpaint.height,
- _rgba);
+ cairo_pattern_t *checkers = ink_cairo_pattern_create_checkerboard();
+
+ cairo_rectangle(ct, carea.x, carea.y, carea.width, carea.height);
+ cairo_set_source(ct, checkers);
+ cairo_fill_preserve(ct);
+ ink_cairo_set_source_rgba32(ct, _rgba);
+ cairo_fill(ct);
+
+ cairo_pattern_destroy(checkers);
}
/* Solid area */
@@ -101,12 +108,12 @@ ColorPreview::paint (GdkRectangle *area)
carea.height = warea.height;
if (gdk_rectangle_intersect (area, &carea, &cpaint)) {
- nr_gdk_draw_rgba32_solid (get_window()->gobj(),
- get_style()->get_black_gc()->gobj(),
- cpaint.x, cpaint.y,
- cpaint.width, cpaint.height,
- _rgba | 0xff);
+ cairo_rectangle(ct, carea.x, carea.y, carea.width, carea.height);
+ ink_cairo_set_source_rgba32(ct, _rgba | 0xff);
+ cairo_fill(ct);
}
+
+ cairo_destroy(ct);
}
}}}
diff --git a/src/vanishing-point.h b/src/vanishing-point.h
index 9fcb6bb46..0551c87ba 100644
--- a/src/vanishing-point.h
+++ b/src/vanishing-point.h
@@ -67,7 +67,7 @@ public:
return persp3d_get_VP (_persp, _axis).is_finite();
}
inline Geom::Point get_pos() const {
- g_return_val_if_fail (_persp, Geom::Point (NR_HUGE, NR_HUGE));
+ g_return_val_if_fail (_persp, Geom::Point (Geom::infinity(), Geom::infinity()));
return persp3d_get_VP (_persp,_axis).affine();
}
inline Persp3D * get_perspective() const {
diff --git a/src/verbs.cpp b/src/verbs.cpp
index c332cc93d..1cdbd71d0 100644
--- a/src/verbs.cpp
+++ b/src/verbs.cpp
@@ -824,9 +824,6 @@ FileVerb::perform(SPAction *action, void *data, void */*pdata*/)
case SP_VERB_FILE_VACUUM:
sp_file_vacuum();
break;
- case SP_VERB_FILE_PRINT_PREVIEW:
- sp_file_print_preview(NULL, NULL);
- break;
case SP_VERB_FILE_IMPORT:
sp_file_import(*parent);
break;
@@ -2258,8 +2255,6 @@ Verb *Verb::_base_verbs[] = {
// TRANSLATORS: "Vacuum Defs" means "Clean up defs" (so as to remove unused definitions)
new FileVerb(SP_VERB_FILE_VACUUM, "FileVacuum", N_("Vac_uum Defs"), N_("Remove unused definitions (such as gradients or clipping paths) from the &lt;defs&gt; of the document"),
INKSCAPE_ICON_DOCUMENT_CLEANUP ),
- new FileVerb(SP_VERB_FILE_PRINT_PREVIEW, "FilePrintPreview", N_("Print Previe_w"),
- N_("Preview document printout"), GTK_STOCK_PRINT_PREVIEW ),
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..."),
diff --git a/src/verbs.h b/src/verbs.h
index dd5c4db35..5387b57c2 100644
--- a/src/verbs.h
+++ b/src/verbs.h
@@ -41,7 +41,6 @@ enum {
SP_VERB_FILE_SAVE_A_COPY, /**< Save a copy of the current file */
SP_VERB_FILE_PRINT,
SP_VERB_FILE_VACUUM,
- SP_VERB_FILE_PRINT_PREVIEW,
SP_VERB_FILE_IMPORT,
SP_VERB_FILE_EXPORT,
SP_VERB_FILE_IMPORT_FROM_OCAL, /**< Import the file from Open Clip Art Library */
diff --git a/src/widgets/Makefile_insert b/src/widgets/Makefile_insert
index af32ec700..86046b918 100644
--- a/src/widgets/Makefile_insert
+++ b/src/widgets/Makefile_insert
@@ -42,8 +42,6 @@ ink_common_sources += \
widgets/sp-color-icc-selector.h \
widgets/sp-color-notebook.cpp \
widgets/sp-color-notebook.h \
- widgets/sp-color-preview.cpp \
- widgets/sp-color-preview.h \
widgets/sp-color-scales.cpp \
widgets/sp-color-scales.h \
widgets/sp-color-selector.cpp \
diff --git a/src/widgets/font-selector.cpp b/src/widgets/font-selector.cpp
index 8c6afeb4c..965910ba2 100644
--- a/src/widgets/font-selector.cpp
+++ b/src/widgets/font-selector.cpp
@@ -20,24 +20,24 @@
# include "config.h"
#endif
-#include <libnr/nr-blit.h>
-#include <libnr/nr-convert2geom.h>
#include <libnrtype/font-instance.h>
-#include <libnrtype/raster-glyph.h>
-#include <libnrtype/RasterFont.h>
-#include <libnrtype/TextWrapper.h>
-#include <libnrtype/one-glyph.h>
#include <libnrtype/font-lister.h>
#include <2geom/transforms.h>
#include <gtk/gtk.h>
+#include <gtk/gtkframe.h>
+#include <gtk/gtkscrolledwindow.h>
+#include <gtk/gtkclist.h>
+#include <gtk/gtkvbox.h>
+#include <gtk/gtkcombo.h>
+#include <gtk/gtkentry.h>
+#include <gtk/gtkdrawingarea.h>
-#include "../display/nr-plain-stuff-gdk.h"
#include <glibmm/i18n.h>
-#include "../desktop.h"
-#include "font-selector.h"
+#include "desktop.h"
+#include "widgets/font-selector.h"
/* SPFontSelector */
@@ -130,13 +130,12 @@ static void sp_font_selector_class_init(SPFontSelectorClass *c)
fs_parent_class = (GtkHBoxClass* )gtk_type_class(GTK_TYPE_HBOX);
- fs_signals[FONT_SET] = g_signal_new ("font_set",
- G_TYPE_FROM_CLASS(object_class),
- G_SIGNAL_RUN_FIRST,
- G_STRUCT_OFFSET(SPFontSelectorClass, font_set),
- NULL, NULL,
+ fs_signals[FONT_SET] = gtk_signal_new ("font_set",
+ GTK_RUN_FIRST,
+ GTK_CLASS_TYPE(object_class),
+ GTK_SIGNAL_OFFSET(SPFontSelectorClass, font_set),
gtk_marshal_NONE__POINTER,
- G_TYPE_NONE,
+ GTK_TYPE_NONE,
1, GTK_TYPE_POINTER);
object_class->destroy = sp_font_selector_destroy;
@@ -148,10 +147,7 @@ static void sp_font_selector_init(SPFontSelector *fsel)
gtk_box_set_spacing(GTK_BOX(fsel), 4);
/* Family frame */
- GtkWidget *ft = gtk_label_new_with_mnemonic(_("F_ont family"));
- GtkWidget *f = gtk_frame_new(NULL);
- gtk_frame_set_label_widget ((GtkFrame*)f, ft);
-
+ GtkWidget *f = gtk_frame_new(_("Font family"));
gtk_widget_show (f);
gtk_box_pack_start (GTK_BOX(fsel), f, TRUE, TRUE, 0);
@@ -175,7 +171,6 @@ static void sp_font_selector_init(SPFontSelector *fsel)
gtk_tree_view_set_model (GTK_TREE_VIEW(fsel->family_treeview), GTK_TREE_MODEL (Glib::unwrap (store)));
gtk_container_add(GTK_CONTAINER(sw), fsel->family_treeview);
gtk_widget_show_all (sw);
- gtk_label_set_mnemonic_widget((GtkLabel*)ft, fsel->family_treeview);
GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(fsel->family_treeview));
g_signal_connect (G_OBJECT(selection), "changed", G_CALLBACK (sp_font_selector_family_select_row), fsel);
@@ -183,9 +178,7 @@ static void sp_font_selector_init(SPFontSelector *fsel)
/* Style frame */
- ft = gtk_label_new_with_mnemonic(C_("Font selector", "_Style"));
- f = gtk_frame_new(NULL);
- gtk_frame_set_label_widget ((GtkFrame*)f, ft);
+ f = gtk_frame_new(C_("Font selector", "Style"));
gtk_widget_show(f);
gtk_box_pack_start(GTK_BOX (fsel), f, TRUE, TRUE, 0);
@@ -210,7 +203,6 @@ static void sp_font_selector_init(SPFontSelector *fsel)
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(fsel->style_treeview), FALSE);
gtk_container_add(GTK_CONTAINER(sw), fsel->style_treeview);
gtk_widget_show_all (sw);
- gtk_label_set_mnemonic_widget((GtkLabel*)ft, fsel->style_treeview);
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(fsel->style_treeview));
g_signal_connect (G_OBJECT(selection), "changed", G_CALLBACK (sp_font_selector_style_select_row), fsel);
@@ -224,14 +216,13 @@ static void sp_font_selector_init(SPFontSelector *fsel)
g_signal_connect (G_OBJECT(fsel->size), "changed", G_CALLBACK (sp_font_selector_size_changed), fsel);
gtk_box_pack_end (GTK_BOX(hb), fsel->size, FALSE, FALSE, 0);
- GtkWidget *l = gtk_label_new_with_mnemonic(_("Font si_ze:"));
+ GtkWidget *l = gtk_label_new(_("Font size:"));
gtk_widget_show_all (l);
gtk_box_pack_end(GTK_BOX (hb), l, FALSE, FALSE, 0);
- gtk_label_set_mnemonic_widget((GtkLabel*)l, fsel->size);
for (unsigned int n = 0; sizes[n]; ++n)
{
- gtk_combo_box_append_text ((GtkComboBox *)fsel->size, sizes[n]);
+ gtk_combo_box_append_text (GTK_COMBO_BOX(fsel->size), sizes[n]);
}
gtk_widget_show_all (fsel->size);
@@ -389,7 +380,7 @@ static void sp_font_selector_emit_set (SPFontSelector *fsel)
fsel->font->Unref();
}
fsel->font = font;
- g_signal_emit(G_OBJECT(fsel), fs_signals[FONT_SET], 0, fsel->font);
+ gtk_signal_emit(GTK_OBJECT(fsel), fs_signals[FONT_SET], fsel->font);
}
fsel->fontsize_dirty = false;
if (font) {
@@ -521,321 +512,6 @@ double sp_font_selector_get_size(SPFontSelector *fsel)
return fsel->fontsize;
}
-/* SPFontPreview */
-
-struct SPFontPreview
-{
- GtkDrawingArea darea;
-
- font_instance *font;
- raster_font *rfont;
- gchar *phrase;
- unsigned long rgba;
-};
-
-struct SPFontPreviewClass
-{
- GtkDrawingAreaClass parent_class;
-};
-
-static void sp_font_preview_class_init(SPFontPreviewClass *c);
-static void sp_font_preview_init(SPFontPreview *fsel);
-static void sp_font_preview_destroy(GtkObject *object);
-
-void sp_font_preview_size_request(GtkWidget *widget, GtkRequisition *req);
-static gint sp_font_preview_expose(GtkWidget *widget, GdkEventExpose *event);
-
-static GtkDrawingAreaClass *fp_parent_class = NULL;
-
-GType sp_font_preview_get_type()
-{
- static GType type = 0;
- if (!type) {
- GTypeInfo info = {
- sizeof(SPFontPreviewClass),
- 0, // base_init
- 0, // base_finalize
- (GClassInitFunc)sp_font_preview_class_init,
- 0, // class_finalize
- 0, // class_data
- sizeof(SPFontPreview),
- 0, // n_preallocs
- (GInstanceInitFunc)sp_font_preview_init,
- 0 // value_table
- };
- type = g_type_register_static(GTK_TYPE_DRAWING_AREA, "SPFontPreview", &info, static_cast<GTypeFlags>(0));
- }
- return type;
-}
-
-static void sp_font_preview_class_init (SPFontPreviewClass *c)
-{
- GtkObjectClass *object_class = (GtkObjectClass *) c;
- GtkWidgetClass *widget_class = (GtkWidgetClass *) c;
-
- fp_parent_class = (GtkDrawingAreaClass*) gtk_type_class(GTK_TYPE_DRAWING_AREA);
-
- object_class->destroy = sp_font_preview_destroy;
-
- widget_class->size_request = sp_font_preview_size_request;
- widget_class->expose_event = sp_font_preview_expose;
-}
-
-static void sp_font_preview_init(SPFontPreview *fprev)
-{
- fprev->rgba = 0x000000ff;
-}
-
-static void sp_font_preview_destroy(GtkObject *object)
-{
- SPFontPreview *fprev = SP_FONT_PREVIEW (object);
-
- if (fprev->rfont) {
- fprev->rfont->Unref();
- fprev->rfont = NULL;
- }
-
- if (fprev->font) {
- fprev->font->Unref();
- fprev->font = NULL;
- }
-
- g_free(fprev->phrase);
- fprev->phrase = NULL;
-
- if (GTK_OBJECT_CLASS (fp_parent_class)->destroy) {
- GTK_OBJECT_CLASS (fp_parent_class)->destroy(object);
- }
-}
-
-void sp_font_preview_size_request(GtkWidget */*widget*/, GtkRequisition *req)
-{
- req->width = 256;
- req->height = 32;
-}
-
-#define SPFP_MAX_LEN 64
-
-static gint sp_font_preview_expose(GtkWidget *widget, GdkEventExpose *event)
-{
- SPFontPreview *fprev = SP_FONT_PREVIEW(widget);
-
- if (gtk_widget_is_drawable (widget)) {
- if (fprev->rfont) {
-
- int glyphs[SPFP_MAX_LEN];
- double hpos[SPFP_MAX_LEN];
-
- font_instance *tface = fprev->rfont->daddy;
-
- double theSize = fprev->rfont->style.transform.descrim();
-
- gchar const *p;
- if (fprev->phrase) {
- p = fprev->phrase;
- } else {
- /* TRANSLATORS: Test string used in text and font dialog (when no
- * text has been entered) to get a preview of the font. Choose
- * some representative characters that users of your locale will be
- * interested in. */
- p = _("AaBbCcIiPpQq12369$\342\202\254\302\242?.;/()");
- }
- int len = 0;
-
- NRRect bbox;
- bbox.x0 = bbox.y0 = bbox.x1 = bbox.y1 = 0.0;
-
- text_wrapper* str_text=new text_wrapper;
- str_text->SetDefaultFont(tface);
- str_text->AppendUTF8(p,-1);
- if ( str_text->uni32_length > 0 ) {
- str_text->DoLayout();
- if ( str_text->glyph_length > 0 ) {
- PangoFont *curPF = NULL;
- font_instance *curF = NULL;
- for (int i = 0; i < str_text->glyph_length && i < SPFP_MAX_LEN; i++) {
- if ( str_text->glyph_text[i].font != curPF ) {
- curPF = str_text->glyph_text[i].font;
- if (curF) {
- curF->Unref();
- }
- curF = NULL;
- if ( curPF ) {
- PangoFontDescription* pfd = pango_font_describe(curPF);
- curF = (font_factory::Default())->Face(pfd);
- pango_font_description_free(pfd);
- }
- }
- Geom::Point base_pt(str_text->glyph_text[i].x, str_text->glyph_text[i].y);
- base_pt *= theSize;
-
- glyphs[len] = str_text->glyph_text[i].gl;
- hpos[len] = base_pt[0];
- len++;
- if ( curF ) {
- Geom::OptRect nbbox = curF->BBox(str_text->glyph_text[i].gl);
- if (nbbox) {
- bbox.x0 = MIN(bbox.x0, base_pt[Geom::X] + theSize * (nbbox->min())[0]);
- bbox.y0 = MIN(bbox.y0, base_pt[Geom::Y] - theSize * (nbbox->max())[1]);
- bbox.x1 = MAX(bbox.x1, base_pt[Geom::X] + theSize * (nbbox->max())[0]);
- bbox.y1 = MAX(bbox.y1, base_pt[Geom::Y] - theSize * (nbbox->min())[1]);
- }
- }
- }
- if ( curF ) {
- curF->Unref();
- }
- }
- }
-
- // XXX: FIXME: why does this code ignore adv.y
- /* while (p && *p && (len < SPFP_MAX_LEN)) {
- unsigned int unival;
- NRRect gbox;
- unival = g_utf8_get_char (p);
- glyphs[len] = tface->MapUnicodeChar( unival);
- hpos[len] = (int)px;
- Geom::Point adv = fprev->rfont->Advance(glyphs[len]);
- fprev->rfont->BBox( glyphs[len], &gbox);
- bbox.x0 = MIN (px + gbox.x0, bbox.x0);
- bbox.y0 = MIN (py + gbox.y0, bbox.y0);
- bbox.x1 = MAX (px + gbox.x1, bbox.x1);
- bbox.y1 = MAX (py + gbox.y1, bbox.y1);
- px += adv[Geom::X];
- len += 1;
- p = g_utf8_next_char (p);
- }*/
-
- float startx = (widget->allocation.width - (bbox.x1 - bbox.x0)) / 2;
- float starty = widget->allocation.height - (widget->allocation.height - (bbox.y1 - bbox.y0)) / 2 - bbox.y1;
-
- for (int y = event->area.y; y < event->area.y + event->area.height; y += 64) {
- for (int x = event->area.x; x < event->area.x + event->area.width; x += 64) {
- NRPixBlock pb, m;
- int x0 = x;
- int y0 = y;
- int x1 = MIN(x0 + 64, event->area.x + event->area.width);
- int y1 = MIN(y0 + 64, event->area.y + event->area.height);
- guchar *ps = nr_pixelstore_16K_new (TRUE, 0xff);
- nr_pixblock_setup_extern(&pb, NR_PIXBLOCK_MODE_R8G8B8, x0, y0, x1, y1, ps, 3 * (x1 - x0), FALSE, FALSE);
- nr_pixblock_setup_fast(&m, NR_PIXBLOCK_MODE_A8, x0, y0, x1, y1, TRUE);
- pb.empty = FALSE;
-
- PangoFont *curPF = NULL;
- font_instance *curF = NULL;
- raster_font *curRF = NULL;
- for (int i=0; i < len; i++) {
- if ( str_text->glyph_text[i].font != curPF ) {
- curPF=str_text->glyph_text[i].font;
- if ( curF ) {
- curF->Unref();
- }
- curF = NULL;
- if ( curPF ) {
- PangoFontDescription* pfd = pango_font_describe(curPF);
- curF=(font_factory::Default())->Face(pfd);
- pango_font_description_free(pfd);
- }
- if ( curF ) {
- if ( curRF ) {
- curRF->Unref();
- }
- curRF = NULL;
- curRF = curF->RasterFont(fprev->rfont->style);
- }
- }
- raster_glyph *g = (curRF) ? curRF->GetGlyph(glyphs[i]) : NULL;
- if ( g ) {
- g->Blit(Geom::Point(hpos[i] + startx, starty), m);
- }
- }
- if (curRF) {
- curRF->Unref();
- }
- if (curF) {
- curF->Unref();
- }
-
- nr_blit_pixblock_mask_rgba32(&pb, &m, fprev->rgba);
- gdk_draw_rgb_image(widget->window, widget->style->black_gc,
- x0, y0, x1 - x0, y1 - y0,
- GDK_RGB_DITHER_NONE, NR_PIXBLOCK_PX (&pb), pb.rs);
- nr_pixblock_release(&m);
- nr_pixblock_release(&pb);
- nr_pixelstore_16K_free(ps);
- }
- }
-
- delete str_text;
-
- } else {
- nr_gdk_draw_gray_garbage(widget->window, widget->style->black_gc,
- event->area.x, event->area.y,
- event->area.width, event->area.height);
- }
- }
-
- return TRUE;
-}
-
-GtkWidget * sp_font_preview_new()
-{
- GtkWidget *w = (GtkWidget*) gtk_type_new(SP_TYPE_FONT_PREVIEW);
-
- return w;
-}
-
-void sp_font_preview_set_font(SPFontPreview *fprev, font_instance *font, SPFontSelector *fsel)
-{
- if (font)
- {
- font->Ref();
- }
-
- if (fprev->font)
- {
- fprev->font->Unref();
- }
-
- fprev->font = font;
-
- if (fprev->rfont)
- {
- fprev->rfont->Unref();
- fprev->rfont=NULL;
- }
-
- if (fprev->font)
- {
- Geom::Affine flip(Geom::Scale(fsel->fontsize, -fsel->fontsize));
- fprev->rfont = fprev->font->RasterFont(flip, 0);
- }
-
- if (gtk_widget_is_drawable (GTK_WIDGET (fprev))) gtk_widget_queue_draw (GTK_WIDGET (fprev));
-}
-
-void sp_font_preview_set_rgba32(SPFontPreview *fprev, guint32 rgba)
-{
- fprev->rgba = rgba;
- if (gtk_widget_is_drawable (GTK_WIDGET (fprev))) {
- gtk_widget_queue_draw (GTK_WIDGET (fprev));
- }
-}
-
-void sp_font_preview_set_phrase(SPFontPreview *fprev, const gchar *phrase)
-{
- g_free (fprev->phrase);
- if (phrase) {
- fprev->phrase = g_strdup (phrase);
- } else {
- fprev->phrase = NULL;
- }
- if (gtk_widget_is_drawable( GTK_WIDGET (fprev))) {
- gtk_widget_queue_draw (GTK_WIDGET (fprev));
- }
-}
-
-
/*
Local Variables:
mode:c++
diff --git a/src/widgets/font-selector.h b/src/widgets/font-selector.h
index 41a671bae..febd4a34a 100644
--- a/src/widgets/font-selector.h
+++ b/src/widgets/font-selector.h
@@ -17,18 +17,13 @@
#include <glib.h>
struct SPFontSelector;
-struct SPFontPreview;
#define SP_TYPE_FONT_SELECTOR (sp_font_selector_get_type ())
-#define SP_FONT_SELECTOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), SP_TYPE_FONT_SELECTOR, SPFontSelector))
-#define SP_IS_FONT_SELECTOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), SP_TYPE_FONT_SELECTOR))
-
-#define SP_TYPE_FONT_PREVIEW (sp_font_preview_get_type ())
-#define SP_FONT_PREVIEW(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), SP_TYPE_FONT_PREVIEW, SPFontPreview))
-#define SP_IS_FONT_PREVIEW(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), SP_TYPE_FONT_PREVIEW))
+#define SP_FONT_SELECTOR(o) (GTK_CHECK_CAST ((o), SP_TYPE_FONT_SELECTOR, SPFontSelector))
+#define SP_IS_FONT_SELECTOR(o) (GTK_CHECK_TYPE ((o), SP_TYPE_FONT_SELECTOR))
#include <libnrtype/nrtype-forward.h>
-#include <gtk/gtk.h>
+#include <gtk/gtkwidget.h>
/* SPFontSelector */
@@ -41,16 +36,6 @@ void sp_font_selector_set_font (SPFontSelector *fsel, font_instance *font, doubl
font_instance *sp_font_selector_get_font (SPFontSelector *fsel);
double sp_font_selector_get_size (SPFontSelector *fsel);
-/* SPFontPreview */
-
-GtkType sp_font_preview_get_type (void);
-
-GtkWidget *sp_font_preview_new (void);
-
-void sp_font_preview_set_font (SPFontPreview *fprev, font_instance *font, SPFontSelector *fsel);
-void sp_font_preview_set_rgba32 (SPFontPreview *fprev, guint32 rgba);
-void sp_font_preview_set_phrase (SPFontPreview *fprev, const gchar *phrase);
-
#endif
diff --git a/src/widgets/gradient-image.cpp b/src/widgets/gradient-image.cpp
index f3a471bfc..ef05ad381 100644
--- a/src/widgets/gradient-image.cpp
+++ b/src/widgets/gradient-image.cpp
@@ -12,10 +12,8 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include <libnr/nr-pixblock-pattern.h>
#include "macros.h"
-#include "../display/nr-plain-stuff.h"
-#include "../display/nr-plain-stuff-gdk.h"
+#include "display/cairo-utils.h"
#include "gradient-image.h"
#include "sp-gradient.h"
#include "sp-gradient-fns.h"
@@ -29,10 +27,7 @@ static void sp_gradient_image_class_init (SPGradientImageClass *klass);
static void sp_gradient_image_init (SPGradientImage *image);
static void sp_gradient_image_destroy (GtkObject *object);
-static void sp_gradient_image_realize (GtkWidget *widget);
-static void sp_gradient_image_unrealize (GtkWidget *widget);
static void sp_gradient_image_size_request (GtkWidget *widget, GtkRequisition *requisition);
-static void sp_gradient_image_size_allocate (GtkWidget *widget, GtkAllocation *allocation);
static gint sp_gradient_image_expose (GtkWidget *widget, GdkEventExpose *event);
static void sp_gradient_image_gradient_release (SPObject *, SPGradientImage *im);
@@ -76,20 +71,16 @@ sp_gradient_image_class_init (SPGradientImageClass *klass)
object_class->destroy = sp_gradient_image_destroy;
- widget_class->realize = sp_gradient_image_realize;
- widget_class->unrealize = sp_gradient_image_unrealize;
widget_class->size_request = sp_gradient_image_size_request;
- widget_class->size_allocate = sp_gradient_image_size_allocate;
widget_class->expose_event = sp_gradient_image_expose;
}
static void
sp_gradient_image_init (SPGradientImage *image)
{
- gtk_widget_set_has_window (GTK_WIDGET (image), FALSE);
+ GTK_WIDGET_SET_FLAGS (image, GTK_NO_WINDOW);
image->gradient = NULL;
- image->px = NULL;
new (&image->release_connection) sigc::connection();
new (&image->modified_connection) sigc::connection();
@@ -116,104 +107,39 @@ sp_gradient_image_destroy (GtkObject *object)
}
static void
-sp_gradient_image_realize (GtkWidget *widget)
-{
- SPGradientImage *image;
-
- image = SP_GRADIENT_IMAGE (widget);
-
- if (((GtkWidgetClass *) parent_class)->realize)
- (* ((GtkWidgetClass *) parent_class)->realize) (widget);
-
- g_assert (!image->px);
- image->px = g_new (guchar, 3 * VBLOCK * widget->allocation.width);
- sp_gradient_image_update (image);
-}
-
-static void
-sp_gradient_image_unrealize (GtkWidget *widget)
-{
- SPGradientImage *image;
-
- image = SP_GRADIENT_IMAGE (widget);
-
- if (((GtkWidgetClass *) parent_class)->unrealize)
- (* ((GtkWidgetClass *) parent_class)->unrealize) (widget);
-
- g_assert (image->px);
- g_free (image->px);
- image->px = NULL;
-}
-
-static void
sp_gradient_image_size_request (GtkWidget *widget, GtkRequisition *requisition)
{
- SPGradientImage *slider;
-
- slider = SP_GRADIENT_IMAGE (widget);
-
requisition->width = 64;
requisition->height = 12;
}
-static void
-sp_gradient_image_size_allocate (GtkWidget *widget, GtkAllocation *allocation)
-{
- SPGradientImage *image;
-
- image = SP_GRADIENT_IMAGE (widget);
-
- widget->allocation = *allocation;
-
- if (gtk_widget_get_realized (widget)) {
- g_free (image->px);
- image->px = g_new (guchar, 3 * VBLOCK * allocation->width);
- }
-
- sp_gradient_image_update (image);
-}
-
static gint
sp_gradient_image_expose (GtkWidget *widget, GdkEventExpose *event)
{
- SPGradientImage *image;
-
- image = SP_GRADIENT_IMAGE (widget);
-
- if (gtk_widget_is_drawable (widget)) {
- gint x0, y0, x1, y1;
- x0 = MAX (event->area.x, widget->allocation.x);
- y0 = MAX (event->area.y, widget->allocation.y);
- x1 = MIN (event->area.x + event->area.width, widget->allocation.x + widget->allocation.width);
- y1 = MIN (event->area.y + event->area.height, widget->allocation.y + widget->allocation.height);
- if ((x1 > x0) && (y1 > y0)) {
- if (image->px) {
- if (image->gradient) {
- gint y;
- guchar *p;
- p = image->px + 3 * (x0 - widget->allocation.x);
- for (y = y0; y < y1; y += VBLOCK) {
- gdk_draw_rgb_image (widget->window, widget->style->black_gc,
- x0, y,
- (x1 - x0), MIN (VBLOCK, y1 - y),
- GDK_RGB_DITHER_MAX,
- p, widget->allocation.width * 3);
- }
- } else {
- nr_gdk_draw_gray_garbage (widget->window, widget->style->black_gc,
- x0, y0,
- x1 - x0, y1 - y0);
- }
- } else {
- gdk_draw_rectangle (widget->window, widget->style->black_gc,
- x0, y0,
- (x1 - x0), (y1 - x0),
- TRUE);
- }
- }
- }
-
- return TRUE;
+ SPGradientImage *image = SP_GRADIENT_IMAGE (widget);
+ SPGradient *gr = image->gradient;
+
+ cairo_t *ct = gdk_cairo_create(widget->window);
+
+ cairo_rectangle(ct, event->area.x, event->area.y,
+ event->area.width, event->area.height);
+ cairo_clip(ct);
+ cairo_translate(ct, widget->allocation.x, widget->allocation.y);
+
+ cairo_pattern_t *check = ink_cairo_pattern_create_checkerboard();
+ cairo_set_source(ct, check);
+ cairo_paint(ct);
+ cairo_pattern_destroy(check);
+
+ if (gr) {
+ cairo_pattern_t *p = sp_gradient_create_preview_pattern(gr, widget->allocation.width);
+ cairo_set_source(ct, p);
+ cairo_paint(ct);
+ cairo_pattern_destroy(p);
+ }
+ cairo_destroy(ct);
+
+ return TRUE;
}
GtkWidget *
@@ -268,27 +194,7 @@ sp_gradient_image_gradient_modified (SPObject *, guint /*flags*/, SPGradientImag
static void
sp_gradient_image_update (SPGradientImage *image)
{
- GtkAllocation *allocation;
-
- if (!image->px) return;
-
- allocation = &((GtkWidget *) image)->allocation;
-
- if (image->gradient) {
- nr_render_checkerboard_rgb (image->px, allocation->width, VBLOCK, 3 * allocation->width, 0, 0);
- sp_gradient_render_vector_block_rgb (image->gradient,
- image->px, allocation->width, VBLOCK, 3 * allocation->width,
- 0, allocation->width, TRUE);
- } else {
- NRPixBlock pb;
- nr_pixblock_setup_extern (&pb, NR_PIXBLOCK_MODE_R8G8B8,
- 0, 0, allocation->width, VBLOCK,
- image->px, 3 * allocation->width, TRUE, FALSE);
- nr_pixblock_render_gray_noise (&pb, NULL);
- nr_pixblock_release (&pb);
- }
-
- if (gtk_widget_is_drawable (GTK_WIDGET (image))) {
+ if (GTK_WIDGET_DRAWABLE (image)) {
gtk_widget_queue_draw (GTK_WIDGET (image));
}
}
diff --git a/src/widgets/gradient-image.h b/src/widgets/gradient-image.h
index 0f911d4ef..ae5d40f56 100644
--- a/src/widgets/gradient-image.h
+++ b/src/widgets/gradient-image.h
@@ -14,7 +14,7 @@
*/
#include <gtk/gtk.h>
-#include "../libnr/nr-matrix.h"
+
class SPGradient;
#include <glib.h>
@@ -31,7 +31,6 @@ class SPGradient;
struct SPGradientImage {
GtkWidget widget;
SPGradient *gradient;
- guchar *px;
sigc::connection release_connection;
sigc::connection modified_connection;
@@ -46,6 +45,4 @@ GtkType sp_gradient_image_get_type (void);
GtkWidget *sp_gradient_image_new (SPGradient *gradient);
void sp_gradient_image_set_gradient (SPGradientImage *gi, SPGradient *gr);
-
-
#endif
diff --git a/src/widgets/gradient-vector.cpp b/src/widgets/gradient-vector.cpp
index bc29bc974..a58b22d7c 100644
--- a/src/widgets/gradient-vector.cpp
+++ b/src/widgets/gradient-vector.cpp
@@ -424,7 +424,7 @@ void SPGradientVectorSelector::setSwatched()
##################################################################*/
#include "../widgets/sp-color-notebook.h"
-#include "../widgets/sp-color-preview.h"
+#include "ui/widget/color-preview.h"
#include "../widgets/widget-sizes.h"
#include "../xml/node-event-vector.h"
#include "../svg/svg-color.h"
@@ -562,7 +562,8 @@ static void update_stop_list( GtkWidget *mnu, SPGradient *gradient, SPStop *new_
gtk_widget_show(i);
g_object_set_data(G_OBJECT(i), "stop", stop);
GtkWidget *hb = gtk_hbox_new(FALSE, 4);
- GtkWidget *cpv = sp_color_preview_new(sp_stop_get_rgba32(stop));
+ GtkWidget *cpv = GTK_WIDGET(Gtk::manage(
+ new Inkscape::UI::Widget::ColorPreview(sp_stop_get_rgba32(stop)))->gobj());
gtk_widget_show(cpv);
gtk_container_add( GTK_CONTAINER(hb), cpv );
g_object_set_data( G_OBJECT(i), "preview", cpv );
@@ -1188,8 +1189,8 @@ static void sp_gradient_vector_color_changed(SPColorSelector *csel, GtkObject *o
blocked = FALSE;
- SPColorPreview *cpv = static_cast<SPColorPreview *>(g_object_get_data(G_OBJECT(gtk_menu_get_active(GTK_MENU(gtk_option_menu_get_menu(mnu)))), "preview"));
- sp_color_preview_set_rgba32(cpv, sp_stop_get_rgba32(stop));
+ Inkscape::UI::Widget::ColorPreview *cpv = static_cast<Inkscape::UI::Widget::ColorPreview *>(g_object_get_data(G_OBJECT(gtk_menu_get_active(GTK_MENU(gtk_option_menu_get_menu(mnu)))), "preview"));
+ cpv->setRgba32(sp_stop_get_rgba32(stop));
}
/*
diff --git a/src/widgets/icon.cpp b/src/widgets/icon.cpp
index b1d5c73bb..450c5f0d9 100644
--- a/src/widgets/icon.cpp
+++ b/src/widgets/icon.cpp
@@ -29,6 +29,7 @@
#include "inkscape.h"
#include "document.h"
#include "sp-item.h"
+#include "display/cairo-utils.h"
#include "display/nr-arena.h"
#include "display/nr-arena-item.h"
#include "io/sys.h"
@@ -88,7 +89,7 @@ struct IconImpl {
static std::list<gchar*> &icons_svg_paths();
static guchar *load_svg_pixels(std::list<Glib::ustring> const &names,
- unsigned lsize, unsigned psize);
+ unsigned psize, unsigned &stride);
static std::string fileEscape( std::string const & str );
@@ -1072,8 +1073,10 @@ GdkPixbuf *IconImpl::loadPixmap(gchar const *name, unsigned /*lsize*/, unsigned
}
// takes doc, root, icon, and icon name to produce pixels
-extern "C" guchar *sp_icon_doc_icon( SPDocument *doc, NRArenaItem *root,
- gchar const *name, unsigned psize )
+extern "C" guchar *
+sp_icon_doc_icon( SPDocument *doc, NRArenaItem *root,
+ gchar const *name, unsigned psize,
+ unsigned &stride)
{
bool const dump = Inkscape::Preferences::get()->getBool("/debug/icons/dumpSvg");
guchar *px = NULL;
@@ -1174,22 +1177,29 @@ extern "C" guchar *sp_icon_doc_icon( SPDocument *doc, NRArenaItem *root,
g_message( " area --'%s' (%f,%f)-(%f,%f)", name, (double)area.x0, (double)area.y0, (double)area.x1, (double)area.y1 );
g_message( " ua --'%s' (%f,%f)-(%f,%f)", name, (double)ua.x0, (double)ua.y0, (double)ua.x1, (double)ua.y1 );
}
+
+ stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, psize);
+
/* Set up pixblock */
- px = g_new(guchar, 4 * psize * psize);
- memset(px, 0x00, 4 * psize * psize);
+ px = g_new(guchar, stride * psize);
+ memset(px, 0x00, stride * psize);
+
/* Render */
- NRPixBlock B;
- nr_pixblock_setup_extern( &B, NR_PIXBLOCK_MODE_R8G8B8A8N,
- ua.x0, ua.y0, ua.x1, ua.y1,
- px + 4 * psize * (ua.y0 - area.y0) +
- 4 * (ua.x0 - area.x0),
- 4 * psize, FALSE, FALSE );
- nr_arena_item_invoke_render(NULL, root, &ua, &B,
+ cairo_surface_t *s = cairo_image_surface_create_for_data(px,
+ CAIRO_FORMAT_ARGB32, psize, psize, stride);
+ cairo_t *ct = cairo_create(s);
+ cairo_translate(ct, -ua.x0, -ua.y0);
+
+ nr_arena_item_invoke_render(ct, root, &ua, NULL,
NR_ARENA_ITEM_RENDER_NO_CACHE );
- nr_pixblock_release(&B);
+ cairo_destroy(ct);
+ cairo_surface_destroy(s);
+
+ // convert to GdkPixbuf format
+ convert_pixels_argb32_to_pixbuf(px, psize, psize, stride);
if ( Inkscape::Preferences::get()->getBool("/debug/icons/overlaySvg") ) {
- IconImpl::overlayPixels( px, psize, psize, 4 * psize, 0x00, 0x00, 0xff );
+ IconImpl::overlayPixels( px, psize, psize, stride, 0x00, 0x00, 0xff );
}
}
}
@@ -1245,7 +1255,7 @@ std::list<gchar*> &IconImpl::icons_svg_paths()
// this function renders icons from icons.svg and returns the pixels.
guchar *IconImpl::load_svg_pixels(std::list<Glib::ustring> const &names,
- unsigned /*lsize*/, unsigned psize)
+ unsigned psize, unsigned &stride)
{
bool const dump = Inkscape::Preferences::get()->getBool("/debug/icons/dumpSvg");
std::list<gchar *> &sources = icons_svg_paths();
@@ -1292,7 +1302,7 @@ guchar *IconImpl::load_svg_pixels(std::list<Glib::ustring> const &names,
}
if (info) {
for (std::list<Glib::ustring>::const_iterator it = names.begin(); !px && (it != names.end()); ++it ) {
- px = sp_icon_doc_icon( info->doc, info->root, it->c_str(), psize );
+ px = sp_icon_doc_icon( info->doc, info->root, it->c_str(), psize, stride );
}
}
}
@@ -1416,10 +1426,11 @@ bool IconImpl::prerenderIcon(gchar const *name, GtkIconSize lsize, unsigned psiz
g_message("load_svg_pixels([%s] = %s, %d, %d)", name, legacyNames[name].c_str(), lsize, psize);
}
}
- guchar* px = load_svg_pixels(names, lsize, psize);
+ unsigned stride;
+ guchar* px = load_svg_pixels(names, psize, stride);
if (px) {
GdkPixbuf* pb = gdk_pixbuf_new_from_data( px, GDK_COLORSPACE_RGB, TRUE, 8,
- psize, psize, psize * 4,
+ psize, psize, stride,
reinterpret_cast<GdkPixbufDestroyNotify>(g_free), NULL );
pb_cache[key] = pb;
addToIconSet(pb, name, lsize, psize);
@@ -1457,10 +1468,11 @@ GdkPixbuf *IconImpl::loadSvg(std::list<Glib::ustring> const &names, GtkIconSize
// did we already load this icon at this scale/size?
GdkPixbuf* pb = get_cached_pixbuf(key);
if (!pb) {
- guchar *px = load_svg_pixels(names, lsize, psize);
+ unsigned stride;
+ guchar *px = load_svg_pixels(names, psize, stride);
if (px) {
pb = gdk_pixbuf_new_from_data(px, GDK_COLORSPACE_RGB, TRUE, 8,
- psize, psize, psize * 4,
+ psize, psize, stride,
(GdkPixbufDestroyNotify)g_free, NULL);
pb_cache[key] = pb;
addToIconSet(pb, names.begin()->c_str(), lsize, psize);
diff --git a/src/widgets/sp-color-preview.cpp b/src/widgets/sp-color-preview.cpp
deleted file mode 100644
index 433301f85..000000000
--- a/src/widgets/sp-color-preview.cpp
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * A simple color preview widget
- *
- * Author:
- * Lauris Kaplinski <lauris@kaplinski.com>
- *
- * Copyright (C) 2001-2002 Lauris Kaplinski
- * Copyright (C) 2001 Ximian, Inc.
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#include "../display/nr-plain-stuff-gdk.h"
-#include "sp-color-preview.h"
-
-#define SPCP_DEFAULT_WIDTH 32
-#define SPCP_DEFAULT_HEIGHT 11
-
-static void sp_color_preview_class_init (SPColorPreviewClass *klass);
-static void sp_color_preview_init (SPColorPreview *image);
-static void sp_color_preview_destroy (GtkObject *object);
-
-static void sp_color_preview_size_request (GtkWidget *widget, GtkRequisition *requisition);
-static void sp_color_preview_size_allocate (GtkWidget *widget, GtkAllocation *allocation);
-static gint sp_color_preview_expose (GtkWidget *widget, GdkEventExpose *event);
-
-static void sp_color_preview_paint (SPColorPreview *cp, GdkRectangle *area);
-
-static GtkWidgetClass *parent_class;
-
-GType sp_color_preview_get_type(void)
-{
- static GType type = 0;
- if (!type) {
- static const GTypeInfo info = {
- sizeof(SPColorPreviewClass),
- NULL, /* base_init */
- NULL, /* base_finalize */
- (GClassInitFunc) sp_color_preview_class_init,
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof(SPColorPreview),
- 0, /* n_preallocs */
- (GInstanceInitFunc) sp_color_preview_init,
- 0, /* value_table */
- };
-
- type = g_type_register_static( GTK_TYPE_WIDGET,
- "SPColorPreview",
- &info,
- static_cast< GTypeFlags > (0) );
- }
- return type;
-}
-
-static void
-sp_color_preview_class_init (SPColorPreviewClass *klass)
-{
- GtkObjectClass *object_class;
- GtkWidgetClass *widget_class;
-
- object_class = (GtkObjectClass *) klass;
- widget_class = (GtkWidgetClass *) klass;
-
- parent_class = (GtkWidgetClass*)gtk_type_class (GTK_TYPE_WIDGET);
-
- object_class->destroy = sp_color_preview_destroy;
-
- widget_class->size_request = sp_color_preview_size_request;
- widget_class->size_allocate = sp_color_preview_size_allocate;
- widget_class->expose_event = sp_color_preview_expose;
-}
-
-static void
-sp_color_preview_init (SPColorPreview *image)
-{
- gtk_widget_set_has_window (GTK_WIDGET (image), FALSE);
-
- image->rgba = 0xffffffff;
-}
-
-static void
-sp_color_preview_destroy (GtkObject *object)
-{
- SPColorPreview *image;
-
- image = SP_COLOR_PREVIEW (object);
-
- if (((GtkObjectClass *) (parent_class))->destroy)
- (* ((GtkObjectClass *) (parent_class))->destroy) (object);
-}
-
-static void
-sp_color_preview_size_request (GtkWidget *widget, GtkRequisition *requisition)
-{
- SPColorPreview *slider;
-
- slider = SP_COLOR_PREVIEW (widget);
-
- requisition->width = SPCP_DEFAULT_WIDTH;
- requisition->height = SPCP_DEFAULT_HEIGHT;
-}
-
-static void
-sp_color_preview_size_allocate (GtkWidget *widget, GtkAllocation *allocation)
-{
- SPColorPreview *image;
-
- image = SP_COLOR_PREVIEW (widget);
-
- widget->allocation = *allocation;
-
- if (gtk_widget_is_drawable (GTK_WIDGET (image))) {
- gtk_widget_queue_draw (GTK_WIDGET (image));
- }
-}
-
-static gint
-sp_color_preview_expose (GtkWidget *widget, GdkEventExpose *event)
-{
- SPColorPreview *cp;
-
- cp = SP_COLOR_PREVIEW (widget);
-
- if (gtk_widget_is_drawable (widget)) {
- sp_color_preview_paint (cp, &event->area);
- }
-
- return TRUE;
-}
-
-GtkWidget *
-sp_color_preview_new (guint32 rgba)
-{
- SPColorPreview *image;
-
- image = (SPColorPreview*)gtk_type_new (SP_TYPE_COLOR_PREVIEW);
-
- sp_color_preview_set_rgba32 (image, rgba);
-
- return (GtkWidget *) image;
-}
-
-void
-sp_color_preview_set_rgba32 (SPColorPreview *cp, guint32 rgba)
-{
- cp->rgba = rgba;
-
- if (gtk_widget_is_drawable (GTK_WIDGET (cp))) {
- gtk_widget_queue_draw (GTK_WIDGET (cp));
- }
-}
-
-static void
-sp_color_preview_paint (SPColorPreview *cp, GdkRectangle *area)
-{
- GtkWidget *widget;
- GdkRectangle warea, carea;
- GdkRectangle wpaint, cpaint;
- gint w2;
-
- widget = GTK_WIDGET (cp);
-
- warea.x = widget->allocation.x;
- warea.y = widget->allocation.y;
- warea.width = widget->allocation.width;
- warea.height = widget->allocation.height;
-
- if (!gdk_rectangle_intersect (area, &warea, &wpaint)) return;
-
- /* Transparent area */
-
- w2 = warea.width / 2;
-
- carea.x = warea.x;
- carea.y = warea.y;
- carea.width = w2;
- carea.height = warea.height;
-
- if (gdk_rectangle_intersect (area, &carea, &cpaint)) {
- nr_gdk_draw_rgba32_solid (widget->window, widget->style->black_gc,
- cpaint.x, cpaint.y,
- cpaint.width, cpaint.height,
- cp->rgba);
- }
-
- /* Solid area */
-
- carea.x = warea.x + w2;
- carea.y = warea.y;
- carea.width = warea.width - w2;
- carea.height = warea.height;
-
- if (gdk_rectangle_intersect (area, &carea, &cpaint)) {
- nr_gdk_draw_rgba32_solid (widget->window, widget->style->black_gc,
- cpaint.x, cpaint.y,
- cpaint.width, cpaint.height,
- cp->rgba | 0xff);
- }
-}
-
-/*
- 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/widgets/sp-color-preview.h b/src/widgets/sp-color-preview.h
deleted file mode 100644
index 43abdf11f..000000000
--- a/src/widgets/sp-color-preview.h
+++ /dev/null
@@ -1,55 +0,0 @@
-#ifndef SEEN_COLOR_PREVIEW_H
-#define SEEN_COLOR_PREVIEW_H
-
-/*
- * A simple color preview widget
- *
- * Author:
- * Lauris Kaplinski <lauris@kaplinski.com>
- *
- * Copyright (C) 2001-2002 Lauris Kaplinski
- * Copyright (C) 2001 Ximian, Inc.
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#include <gtk/gtk.h>
-
-#include <glib.h>
-
-
-
-#define SP_TYPE_COLOR_PREVIEW (sp_color_preview_get_type ())
-#define SP_COLOR_PREVIEW(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), SP_TYPE_COLOR_PREVIEW, SPColorPreview))
-#define SP_COLOR_PREVIEW_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), SP_TYPE_COLOR_PREVIEW, SPColorPreviewClass))
-#define SP_IS_COLOR_PREVIEW(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), SP_TYPE_COLOR_PREVIEW))
-#define SP_IS_COLOR_PREVIEW_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), SP_TYPE_COLOR_PREVIEW))
-
-struct SPColorPreview {
- GtkWidget widget;
-
- guint32 rgba;
-};
-
-struct SPColorPreviewClass {
- GtkWidgetClass parent_class;
-};
-
-GType sp_color_preview_get_type(void);
-
-GtkWidget *sp_color_preview_new(guint32 rgba);
-
-void sp_color_preview_set_rgba32(SPColorPreview *cp, guint32 color);
-
-
-#endif // SEEN_COLOR_PREVIEW_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/widgets/stroke-style.cpp b/src/widgets/stroke-style.cpp
index d2b280e44..9da39bac4 100644
--- a/src/widgets/stroke-style.cpp
+++ b/src/widgets/stroke-style.cpp
@@ -613,7 +613,7 @@ static gboolean stroke_width_set_unit(SPUnitSelector *,
gdouble average = stroke_average_width (objects);
- if (average == NR_HUGE || average == 0)
+ if (average == Geom::infinity() || average == 0)
return FALSE;
a->set_value (100.0 * w / average);
diff --git a/src/widgets/toolbox.cpp b/src/widgets/toolbox.cpp
index 8241f1941..01308104e 100644
--- a/src/widgets/toolbox.cpp
+++ b/src/widgets/toolbox.cpp
@@ -3454,7 +3454,7 @@ static void box3d_set_button_and_adjustment(Persp3D *persp,
gtk_action_set_sensitive(act, TRUE);
double angle = persp3d_get_infinite_angle(persp, axis);
- if (angle != NR_HUGE) { // FIXME: We should catch this error earlier (don't show the spinbutton at all)
+ if (angle != Geom::infinity()) { // FIXME: We should catch this error earlier (don't show the spinbutton at all)
gtk_adjustment_set_value(adj, box3d_normalize_angle(angle));
}
} else {