fixes #2773 improve composable filters
diff --git a/player/js/elements/svgElements/SVGEffects.js b/player/js/elements/svgElements/SVGEffects.js
index 7a43d79..ef22f3a 100644
--- a/player/js/elements/svgElements/SVGEffects.js
+++ b/player/js/elements/svgElements/SVGEffects.js
@@ -3,19 +3,13 @@
   createElementID,
 } from '../../utils/common';
 import filtersFactory from '../../utils/filters';
-import SVGTintFilter from './effects/SVGTintEffect';
-import SVGFillFilter from './effects/SVGFillFilter';
-import SVGStrokeEffect from './effects/SVGStrokeEffect';
-import SVGTritoneFilter from './effects/SVGTritoneFilter';
-import SVGProLevelsFilter from './effects/SVGProLevelsFilter';
-import SVGDropShadowEffect from './effects/SVGDropShadowEffect';
-import SVGMatte3Effect from './effects/SVGMatte3Effect';
-import SVGGaussianBlurEffect from './effects/SVGGaussianBlurEffect';
 
 var registeredEffects = {};
+var idPrefix = 'filter_result_';
 
 function SVGEffects(elem) {
   var i;
+  var source = 'SourceGraphic';
   var len = elem.data.ef ? elem.data.ef.length : 0;
   var filId = createElementID();
   var fil = filtersFactory.createFilter(filId, true);
@@ -27,35 +21,12 @@
     var type = elem.data.ef[i].ty;
     if (registeredEffects[type]) {
       var Effect = registeredEffects[type].effect;
-      filterManager = new Effect(fil, elem.effectsManager.effectElements[i], elem);
+      filterManager = new Effect(fil, elem.effectsManager.effectElements[i], elem, idPrefix + count, source);
+      source = idPrefix + count;
       if (registeredEffects[type].countsAsEffect) {
         count += 1;
       }
     }
-    if (elem.data.ef[i].ty === 20) {
-      count += 1;
-      filterManager = new SVGTintFilter(fil, elem.effectsManager.effectElements[i]);
-    } else if (elem.data.ef[i].ty === 21) {
-      count += 1;
-      filterManager = new SVGFillFilter(fil, elem.effectsManager.effectElements[i]);
-    } else if (elem.data.ef[i].ty === 22) {
-      filterManager = new SVGStrokeEffect(elem, elem.effectsManager.effectElements[i]);
-    } else if (elem.data.ef[i].ty === 23) {
-      count += 1;
-      filterManager = new SVGTritoneFilter(fil, elem.effectsManager.effectElements[i]);
-    } else if (elem.data.ef[i].ty === 24) {
-      count += 1;
-      filterManager = new SVGProLevelsFilter(fil, elem.effectsManager.effectElements[i]);
-    } else if (elem.data.ef[i].ty === 25) {
-      count += 1;
-      filterManager = new SVGDropShadowEffect(fil, elem.effectsManager.effectElements[i]);
-    } else if (elem.data.ef[i].ty === 28) {
-      // count += 1;
-      filterManager = new SVGMatte3Effect(fil, elem.effectsManager.effectElements[i], elem);
-    } else if (elem.data.ef[i].ty === 29) {
-      count += 1;
-      filterManager = new SVGGaussianBlurEffect(fil, elem.effectsManager.effectElements[i]);
-    }
     if (filterManager) {
       this.filters.push(filterManager);
     }
diff --git a/player/js/elements/svgElements/effects/SVGComposableEffect.js b/player/js/elements/svgElements/effects/SVGComposableEffect.js
new file mode 100644
index 0000000..689b378
--- /dev/null
+++ b/player/js/elements/svgElements/effects/SVGComposableEffect.js
@@ -0,0 +1,22 @@
+import createNS from '../../../utils/helpers/svg_elements';
+
+function SVGComposableEffect() {
+
+}
+SVGComposableEffect.prototype = {
+  createMergeNode: (resultId, ins) => {
+    var feMerge = createNS('feMerge');
+    feMerge.setAttribute('result', resultId);
+    var feMergeNode;
+    var i;
+    for (i = 0; i < ins.length; i += 1) {
+      feMergeNode = createNS('feMergeNode');
+      feMergeNode.setAttribute('in', ins[i]);
+      feMerge.appendChild(feMergeNode);
+      feMerge.appendChild(feMergeNode);
+    }
+    return feMerge;
+  },
+};
+
+export default SVGComposableEffect;
diff --git a/player/js/elements/svgElements/effects/SVGDropShadowEffect.js b/player/js/elements/svgElements/effects/SVGDropShadowEffect.js
index fc72c1c..db10b7f 100644
--- a/player/js/elements/svgElements/effects/SVGDropShadowEffect.js
+++ b/player/js/elements/svgElements/effects/SVGDropShadowEffect.js
@@ -3,8 +3,12 @@
   rgbToHex,
 } from '../../../utils/common';
 import createNS from '../../../utils/helpers/svg_elements';
+import SVGComposableEffect from './SVGComposableEffect';
+import {
+  extendPrototype,
+} from '../../../utils/functionExtensions';
 
-function SVGDropShadowEffect(filter, filterManager) {
+function SVGDropShadowEffect(filter, filterManager, elem, id, source) {
   var filterSize = filterManager.container.globalData.renderConfig.filterSize;
   filter.setAttribute('x', filterSize.x);
   filter.setAttribute('y', filterSize.y);
@@ -14,7 +18,7 @@
 
   var feGaussianBlur = createNS('feGaussianBlur');
   feGaussianBlur.setAttribute('in', 'SourceAlpha');
-  feGaussianBlur.setAttribute('result', 'drop_shadow_1');
+  feGaussianBlur.setAttribute('result', id + '_drop_shadow_1');
   feGaussianBlur.setAttribute('stdDeviation', '0');
   this.feGaussianBlur = feGaussianBlur;
   filter.appendChild(feGaussianBlur);
@@ -22,36 +26,35 @@
   var feOffset = createNS('feOffset');
   feOffset.setAttribute('dx', '25');
   feOffset.setAttribute('dy', '0');
-  feOffset.setAttribute('in', 'drop_shadow_1');
-  feOffset.setAttribute('result', 'drop_shadow_2');
+  feOffset.setAttribute('in', id + '_drop_shadow_1');
+  feOffset.setAttribute('result', id + '_drop_shadow_2');
   this.feOffset = feOffset;
   filter.appendChild(feOffset);
   var feFlood = createNS('feFlood');
   feFlood.setAttribute('flood-color', '#00ff00');
   feFlood.setAttribute('flood-opacity', '1');
-  feFlood.setAttribute('result', 'drop_shadow_3');
+  feFlood.setAttribute('result', id + '_drop_shadow_3');
   this.feFlood = feFlood;
   filter.appendChild(feFlood);
 
   var feComposite = createNS('feComposite');
-  feComposite.setAttribute('in', 'drop_shadow_3');
-  feComposite.setAttribute('in2', 'drop_shadow_2');
+  feComposite.setAttribute('in', id + '_drop_shadow_3');
+  feComposite.setAttribute('in2', id + '_drop_shadow_2');
   feComposite.setAttribute('operator', 'in');
-  feComposite.setAttribute('result', 'drop_shadow_4');
+  feComposite.setAttribute('result', id + '_drop_shadow_4');
   filter.appendChild(feComposite);
 
-  var feMerge = createNS('feMerge');
+  var feMerge = this.createMergeNode(
+    id,
+    [
+      id + '_drop_shadow_4',
+      source,
+    ]
+  );
   filter.appendChild(feMerge);
-  var feMergeNode;
-  feMergeNode = createNS('feMergeNode');
-  feMerge.appendChild(feMergeNode);
-  feMergeNode = createNS('feMergeNode');
-  feMergeNode.setAttribute('in', 'SourceGraphic');
-  this.feMergeNode = feMergeNode;
-  this.feMerge = feMerge;
-  this.originalNodeAdded = false;
-  feMerge.appendChild(feMergeNode);
+  //
 }
+extendPrototype([SVGComposableEffect], SVGDropShadowEffect);
 
 SVGDropShadowEffect.prototype.renderFrame = function (forceRender) {
   if (forceRender || this.filterManager._mdf) {
@@ -73,15 +76,6 @@
       this.feOffset.setAttribute('dx', x);
       this.feOffset.setAttribute('dy', y);
     }
-    /* if(forceRender || this.filterManager.effectElements[5].p._mdf){
-            if(this.filterManager.effectElements[5].p.v === 1 && this.originalNodeAdded) {
-                this.feMerge.removeChild(this.feMergeNode);
-                this.originalNodeAdded = false;
-            } else if(this.filterManager.effectElements[5].p.v === 0 && !this.originalNodeAdded) {
-                this.feMerge.appendChild(this.feMergeNode);
-                this.originalNodeAdded = true;
-            }
-        } */
   }
 };
 
diff --git a/player/js/elements/svgElements/effects/SVGFillFilter.js b/player/js/elements/svgElements/effects/SVGFillFilter.js
index b77b48d..1d174e3 100644
--- a/player/js/elements/svgElements/effects/SVGFillFilter.js
+++ b/player/js/elements/svgElements/effects/SVGFillFilter.js
@@ -1,14 +1,16 @@
 import createNS from '../../../utils/helpers/svg_elements';
 
-function SVGFillFilter(filter, filterManager) {
+function SVGFillFilter(filter, filterManager, elem, id) {
   this.filterManager = filterManager;
   var feColorMatrix = createNS('feColorMatrix');
   feColorMatrix.setAttribute('type', 'matrix');
   feColorMatrix.setAttribute('color-interpolation-filters', 'sRGB');
   feColorMatrix.setAttribute('values', '1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0');
+  feColorMatrix.setAttribute('result', id);
   filter.appendChild(feColorMatrix);
   this.matrixFilter = feColorMatrix;
 }
+
 SVGFillFilter.prototype.renderFrame = function (forceRender) {
   if (forceRender || this.filterManager._mdf) {
     var color = this.filterManager.effectElements[2].p.v;
diff --git a/player/js/elements/svgElements/effects/SVGGaussianBlurEffect.js b/player/js/elements/svgElements/effects/SVGGaussianBlurEffect.js
index 45b8f2c..599ace1 100644
--- a/player/js/elements/svgElements/effects/SVGGaussianBlurEffect.js
+++ b/player/js/elements/svgElements/effects/SVGGaussianBlurEffect.js
@@ -1,6 +1,6 @@
 import createNS from '../../../utils/helpers/svg_elements';
 
-function SVGGaussianBlurEffect(filter, filterManager) {
+function SVGGaussianBlurEffect(filter, filterManager, elem, id) {
   // Outset the filter region by 100% on all sides to accommodate blur expansion.
   filter.setAttribute('x', '-100%');
   filter.setAttribute('y', '-100%');
@@ -9,6 +9,7 @@
 
   this.filterManager = filterManager;
   var feGaussianBlur = createNS('feGaussianBlur');
+  feGaussianBlur.setAttribute('result', id);
   filter.appendChild(feGaussianBlur);
   this.feGaussianBlur = feGaussianBlur;
 }
diff --git a/player/js/elements/svgElements/effects/SVGProLevelsFilter.js b/player/js/elements/svgElements/effects/SVGProLevelsFilter.js
index 12270bf..dad722e 100644
--- a/player/js/elements/svgElements/effects/SVGProLevelsFilter.js
+++ b/player/js/elements/svgElements/effects/SVGProLevelsFilter.js
@@ -1,31 +1,36 @@
 import createNS from '../../../utils/helpers/svg_elements';
 
-function SVGProLevelsFilter(filter, filterManager) {
+function SVGProLevelsFilter(filter, filterManager, elem, id) {
   this.filterManager = filterManager;
   var effectElements = this.filterManager.effectElements;
   var feComponentTransfer = createNS('feComponentTransfer');
 
+  // Red
   if (effectElements[10].p.k || effectElements[10].p.v !== 0 || effectElements[11].p.k || effectElements[11].p.v !== 1 || effectElements[12].p.k || effectElements[12].p.v !== 1 || effectElements[13].p.k || effectElements[13].p.v !== 0 || effectElements[14].p.k || effectElements[14].p.v !== 1) {
     this.feFuncR = this.createFeFunc('feFuncR', feComponentTransfer);
   }
+  // Green
   if (effectElements[17].p.k || effectElements[17].p.v !== 0 || effectElements[18].p.k || effectElements[18].p.v !== 1 || effectElements[19].p.k || effectElements[19].p.v !== 1 || effectElements[20].p.k || effectElements[20].p.v !== 0 || effectElements[21].p.k || effectElements[21].p.v !== 1) {
     this.feFuncG = this.createFeFunc('feFuncG', feComponentTransfer);
   }
+  // Blue
   if (effectElements[24].p.k || effectElements[24].p.v !== 0 || effectElements[25].p.k || effectElements[25].p.v !== 1 || effectElements[26].p.k || effectElements[26].p.v !== 1 || effectElements[27].p.k || effectElements[27].p.v !== 0 || effectElements[28].p.k || effectElements[28].p.v !== 1) {
     this.feFuncB = this.createFeFunc('feFuncB', feComponentTransfer);
   }
+  // Alpha
   if (effectElements[31].p.k || effectElements[31].p.v !== 0 || effectElements[32].p.k || effectElements[32].p.v !== 1 || effectElements[33].p.k || effectElements[33].p.v !== 1 || effectElements[34].p.k || effectElements[34].p.v !== 0 || effectElements[35].p.k || effectElements[35].p.v !== 1) {
     this.feFuncA = this.createFeFunc('feFuncA', feComponentTransfer);
   }
-
+  // RGB
   if (this.feFuncR || this.feFuncG || this.feFuncB || this.feFuncA) {
     feComponentTransfer.setAttribute('color-interpolation-filters', 'sRGB');
     filter.appendChild(feComponentTransfer);
-    feComponentTransfer = createNS('feComponentTransfer');
   }
 
   if (effectElements[3].p.k || effectElements[3].p.v !== 0 || effectElements[4].p.k || effectElements[4].p.v !== 1 || effectElements[5].p.k || effectElements[5].p.v !== 1 || effectElements[6].p.k || effectElements[6].p.v !== 0 || effectElements[7].p.k || effectElements[7].p.v !== 1) {
+    feComponentTransfer = createNS('feComponentTransfer');
     feComponentTransfer.setAttribute('color-interpolation-filters', 'sRGB');
+    feComponentTransfer.setAttribute('result', id);
     filter.appendChild(feComponentTransfer);
     this.feFuncRComposed = this.createFeFunc('feFuncR', feComponentTransfer);
     this.feFuncGComposed = this.createFeFunc('feFuncG', feComponentTransfer);
diff --git a/player/js/elements/svgElements/effects/SVGTintEffect.js b/player/js/elements/svgElements/effects/SVGTintEffect.js
index b1175b5..5b0d3df 100644
--- a/player/js/elements/svgElements/effects/SVGTintEffect.js
+++ b/player/js/elements/svgElements/effects/SVGTintEffect.js
@@ -1,32 +1,35 @@
 import createNS from '../../../utils/helpers/svg_elements';
+import SVGComposableEffect from './SVGComposableEffect';
+import {
+  extendPrototype,
+} from '../../../utils/functionExtensions';
 
-function SVGTintFilter(filter, filterManager) {
+function SVGTintFilter(filter, filterManager, elem, id, source) {
   this.filterManager = filterManager;
   var feColorMatrix = createNS('feColorMatrix');
   feColorMatrix.setAttribute('type', 'matrix');
   feColorMatrix.setAttribute('color-interpolation-filters', 'linearRGB');
   feColorMatrix.setAttribute('values', '0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0');
-  feColorMatrix.setAttribute('result', 'f1');
+  feColorMatrix.setAttribute('result', id + '_tint_1');
   filter.appendChild(feColorMatrix);
   feColorMatrix = createNS('feColorMatrix');
   feColorMatrix.setAttribute('type', 'matrix');
   feColorMatrix.setAttribute('color-interpolation-filters', 'sRGB');
   feColorMatrix.setAttribute('values', '1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0');
-  feColorMatrix.setAttribute('result', 'f2');
+  feColorMatrix.setAttribute('result', id + '_tint_2');
   filter.appendChild(feColorMatrix);
   this.matrixFilter = feColorMatrix;
-  if (filterManager.effectElements[2].p.v !== 100 || filterManager.effectElements[2].p.k) {
-    var feMerge = createNS('feMerge');
-    filter.appendChild(feMerge);
-    var feMergeNode;
-    feMergeNode = createNS('feMergeNode');
-    feMergeNode.setAttribute('in', 'SourceGraphic');
-    feMerge.appendChild(feMergeNode);
-    feMergeNode = createNS('feMergeNode');
-    feMergeNode.setAttribute('in', 'f2');
-    feMerge.appendChild(feMergeNode);
-  }
+  var feMerge = this.createMergeNode(
+    id,
+    [
+      source,
+      id + '_tint_1',
+      id + '_tint_2',
+    ]
+  );
+  filter.appendChild(feMerge);
 }
+extendPrototype([SVGComposableEffect], SVGTintFilter);
 
 SVGTintFilter.prototype.renderFrame = function (forceRender) {
   if (forceRender || this.filterManager._mdf) {
diff --git a/player/js/elements/svgElements/effects/SVGTritoneFilter.js b/player/js/elements/svgElements/effects/SVGTritoneFilter.js
index 9433b60..8c76001 100644
--- a/player/js/elements/svgElements/effects/SVGTritoneFilter.js
+++ b/player/js/elements/svgElements/effects/SVGTritoneFilter.js
@@ -1,16 +1,15 @@
 import createNS from '../../../utils/helpers/svg_elements';
 
-function SVGTritoneFilter(filter, filterManager) {
+function SVGTritoneFilter(filter, filterManager, elem, id) {
   this.filterManager = filterManager;
   var feColorMatrix = createNS('feColorMatrix');
   feColorMatrix.setAttribute('type', 'matrix');
   feColorMatrix.setAttribute('color-interpolation-filters', 'linearRGB');
   feColorMatrix.setAttribute('values', '0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0');
-  feColorMatrix.setAttribute('result', 'f1');
   filter.appendChild(feColorMatrix);
   var feComponentTransfer = createNS('feComponentTransfer');
   feComponentTransfer.setAttribute('color-interpolation-filters', 'sRGB');
-  filter.appendChild(feComponentTransfer);
+  feComponentTransfer.setAttribute('result', id);
   this.matrixFilter = feComponentTransfer;
   var feFuncR = createNS('feFuncR');
   feFuncR.setAttribute('type', 'table');
@@ -24,6 +23,7 @@
   feFuncB.setAttribute('type', 'table');
   feComponentTransfer.appendChild(feFuncB);
   this.feFuncB = feFuncB;
+  filter.appendChild(feComponentTransfer);
 }
 
 SVGTritoneFilter.prototype.renderFrame = function (forceRender) {
@@ -37,8 +37,6 @@
     this.feFuncR.setAttribute('tableValues', tableR);
     this.feFuncG.setAttribute('tableValues', tableG);
     this.feFuncB.setAttribute('tableValues', tableB);
-    // var opacity = this.filterManager.effectElements[2].p.v/100;
-    // this.matrixFilter.setAttribute('values',(colorWhite[0]- colorBlack[0])+' 0 0 0 '+ colorBlack[0] +' '+ (colorWhite[1]- colorBlack[1]) +' 0 0 0 '+ colorBlack[1] +' '+ (colorWhite[2]- colorBlack[2]) +' 0 0 0 '+ colorBlack[2] +' 0 0 0 ' + opacity + ' 0');
   }
 };