/*! Fabric.js Copyright 2008-2015, Printio (Juriy Zaytsev, Maxim Chernyak) */ var fabric = fabric || { version: '5.3.0' }; if (typeof exports !== 'undefined') { exports.fabric = fabric; } /* _AMD_START_ */ else if (typeof define === 'function' && define.amd) { define([], function() { return fabric; }); } /* _AMD_END_ */ if (typeof document !== 'undefined' && typeof window !== 'undefined') { if (document instanceof (typeof HTMLDocument !== 'undefined' ? HTMLDocument : Document)) { fabric.document = document; } else { fabric.document = document.implementation.createHTMLDocument(''); } fabric.window = window; } else { // assume we're running under node.js when document/window are not present var jsdom = require('jsdom'); var virtualWindow = new jsdom.JSDOM( decodeURIComponent('%3C!DOCTYPE%20html%3E%3Chtml%3E%3Chead%3E%3C%2Fhead%3E%3Cbody%3E%3C%2Fbody%3E%3C%2Fhtml%3E'), { features: { FetchExternalResources: ['img'] }, resources: 'usable' }).window; fabric.document = virtualWindow.document; fabric.jsdomImplForWrapper = require('jsdom/lib/jsdom/living/generated/utils').implForWrapper; fabric.nodeCanvas = require('jsdom/lib/jsdom/utils').Canvas; fabric.window = virtualWindow; DOMParser = fabric.window.DOMParser; } /** * True when in environment that supports touch events * @type boolean */ fabric.isTouchSupported = 'ontouchstart' in fabric.window || 'ontouchstart' in fabric.document || (fabric.window && fabric.window.navigator && fabric.window.navigator.maxTouchPoints > 0); /** * True when in environment that's probably Node.js * @type boolean */ fabric.isLikelyNode = typeof Buffer !== 'undefined' && typeof window === 'undefined'; /* _FROM_SVG_START_ */ /** * Attributes parsed from all SVG elements * @type array */ fabric.SHARED_ATTRIBUTES = [ 'display', 'transform', 'fill', 'fill-opacity', 'fill-rule', 'opacity', 'stroke', 'stroke-dasharray', 'stroke-linecap', 'stroke-dashoffset', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'id', 'paint-order', 'vector-effect', 'instantiated_by_use', 'clip-path', ]; /* _FROM_SVG_END_ */ /** * Pixel per Inch as a default value set to 96. Can be changed for more realistic conversion. */ fabric.DPI = 96; fabric.reNum = '(?:[-+]?(?:\\d+|\\d*\\.\\d+)(?:[eE][-+]?\\d+)?)'; fabric.commaWsp = '(?:\\s+,?\\s*|,\\s*)'; fabric.rePathCommand = /([-+]?((\d+\.\d+)|((\d+)|(\.\d+)))(?:[eE][-+]?\d+)?)/ig; fabric.reNonWord = /[ \n\.,;!\?\-]/; fabric.fontPaths = { }; fabric.iMatrix = [1, 0, 0, 1, 0, 0]; fabric.svgNS = 'http://www.w3.org/2000/svg'; /** * Pixel limit for cache canvases. 1Mpx , 4Mpx should be fine. * @since 1.7.14 * @type Number * @default */ fabric.perfLimitSizeTotal = 2097152; /** * Pixel limit for cache canvases width or height. IE fixes the maximum at 5000 * @since 1.7.14 * @type Number * @default */ fabric.maxCacheSideLimit = 4096; /** * Lowest pixel limit for cache canvases, set at 256PX * @since 1.7.14 * @type Number * @default */ fabric.minCacheSideLimit = 256; /** * Cache Object for widths of chars in text rendering. */ fabric.charWidthsCache = { }; /** * if webgl is enabled and available, textureSize will determine the size * of the canvas backend * @since 2.0.0 * @type Number * @default */ fabric.textureSize = 2048; /** * When 'true', style information is not retained when copy/pasting text, making * pasted text use destination style. * Defaults to 'false'. * @type Boolean * @default */ fabric.disableStyleCopyPaste = false; /** * Enable webgl for filtering picture is available * A filtering backend will be initialized, this will both take memory and * time since a default 2048x2048 canvas will be created for the gl context * @since 2.0.0 * @type Boolean * @default */ fabric.enableGLFiltering = true; /** * Device Pixel Ratio * @see https://developer.apple.com/library/safari/documentation/AudioVideo/Conceptual/HTML-canvas-guide/SettingUptheCanvas/SettingUptheCanvas.html */ fabric.devicePixelRatio = fabric.window.devicePixelRatio || fabric.window.webkitDevicePixelRatio || fabric.window.mozDevicePixelRatio || 1; /** * Browser-specific constant to adjust CanvasRenderingContext2D.shadowBlur value, * which is unitless and not rendered equally across browsers. * * Values that work quite well (as of October 2017) are: * - Chrome: 1.5 * - Edge: 1.75 * - Firefox: 0.9 * - Safari: 0.95 * * @since 2.0.0 * @type Number * @default 1 */ fabric.browserShadowBlurConstant = 1; /** * This object contains the result of arc to bezier conversion for faster retrieving if the same arc needs to be converted again. * It was an internal variable, is accessible since version 2.3.4 */ fabric.arcToSegmentsCache = { }; /** * This object keeps the results of the boundsOfCurve calculation mapped by the joined arguments necessary to calculate it. * It does speed up calculation, if you parse and add always the same paths, but in case of heavy usage of freedrawing * you do not get any speed benefit and you get a big object in memory. * The object was a private variable before, while now is appended to the lib so that you have access to it and you * can eventually clear it. * It was an internal variable, is accessible since version 2.3.4 */ fabric.boundsOfCurveCache = { }; /** * If disabled boundsOfCurveCache is not used. For apps that make heavy usage of pencil drawing probably disabling it is better * @default true */ fabric.cachesBoundsOfCurve = true; /** * Skip performance testing of setupGLContext and force the use of putImageData that seems to be the one that works best on * Chrome + old hardware. if your users are experiencing empty images after filtering you may try to force this to true * this has to be set before instantiating the filtering backend ( before filtering the first image ) * @type Boolean * @default false */ fabric.forceGLPutImageData = false; fabric.initFilterBackend = function() { if (fabric.enableGLFiltering && fabric.isWebglSupported && fabric.isWebglSupported(fabric.textureSize)) { console.log('max texture size: ' + fabric.maxTextureSize); return (new fabric.WebglFilterBackend({ tileSize: fabric.textureSize })); } else if (fabric.Canvas2dFilterBackend) { return (new fabric.Canvas2dFilterBackend()); } };