summaryrefslogtreecommitdiff
path: root/Source/WebInspectorUI/UserInterface/ImageUtilities.js
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebInspectorUI/UserInterface/ImageUtilities.js')
-rw-r--r--Source/WebInspectorUI/UserInterface/ImageUtilities.js730
1 files changed, 0 insertions, 730 deletions
diff --git a/Source/WebInspectorUI/UserInterface/ImageUtilities.js b/Source/WebInspectorUI/UserInterface/ImageUtilities.js
deleted file mode 100644
index e5e8774c1..000000000
--- a/Source/WebInspectorUI/UserInterface/ImageUtilities.js
+++ /dev/null
@@ -1,730 +0,0 @@
-/*
- * Copyright (C) 2013 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-// Bump this version when making changes that affect the storage format.
-const _imageStorageFormatVersion = 1;
-
-try {
- var _generatedImageCacheDatabase = openDatabase("com.apple.WebInspector", 1, "Web Inspector Storage Database", 5 * 1024 * 1024);
-} catch (e) {
- // If we can't open the database it isn't the end of the world, we just will always generate
- // the images and not cache them for better load times.
- console.warn("Can't open database due to: " + e + ". Images will be generated instead of loaded from cache.");
-}
-
-var _initialPrefetchComplete = false;
-var _fetchedCachedImages = {};
-
-var _generatedImageUpdateFunctions = [];
-
-_prefetchCachedImagesAndUpdate();
-
-// Updates each image when the device pixel ratio changes to redraw at the new resolution.
-window.matchMedia("(-webkit-device-pixel-ratio: 1)").addListener(_devicePixelRatioChanged);
-
-// Delete old cached images from localStorage to free up space.
-// FIXME: Remove this once it has been in the builds for a while.
-try {
- const processedFlagKey = "com.apple.WebInspector.deleted-generated-images";
-
- if (!window.localStorage[processedFlagKey]) {
- for (var key in window.localStorage) {
- if (/^com\.apple\.WebInspector\.generated-(?:colored|embossed)-image-/.test(key))
- delete window.localStorage[key];
- }
-
- window.localStorage[processedFlagKey] = true;
- }
-} catch (e) {
- // Ignore.
-}
-
-function _devicePixelRatioChanged()
-{
- _prefetchCachedImagesAndUpdate();
-}
-
-function _registerGeneratedImageUpdateFunction(update)
-{
- console.assert(typeof update === "function");
-
- _generatedImageUpdateFunctions.push(update);
-
- if (_initialPrefetchComplete)
- update();
-}
-
-function _logSQLError(tx, error)
-{
- console.error(error.code, error.message);
-}
-
-function _logSQLTransactionError(error)
-{
- console.error(error.code, error.message);
-}
-
-function _prefetchCachedImagesAndUpdate()
-{
- _fetchedCachedImages = {};
-
- function complete()
- {
- _initialPrefetchComplete = true;
-
- for (var i = 0; i < _generatedImageUpdateFunctions.length; ++i)
- _generatedImageUpdateFunctions[i]();
- }
-
- if (!_generatedImageCacheDatabase) {
- complete();
- return;
- }
-
- _generatedImageCacheDatabase.transaction(function(tx) {
- tx.executeSql("SELECT key, imageVersion, data FROM CachedImages WHERE pixelRatio = ? AND formatVersion = ?", [window.devicePixelRatio, _imageStorageFormatVersion], function(tx, result) {
- for (var i = 0; i < result.rows.length; ++i) {
- var row = result.rows.item(i);
- _fetchedCachedImages[row.key] = {data: row.data, imageVersion: row.imageVersion};
- }
-
- complete();
- }, function(tx, error) {
- // The select failed. That could be because the schema changed or this is the first time.
- // Drop the table and recreate it fresh.
-
- tx.executeSql("DROP TABLE IF EXISTS CachedImages");
- tx.executeSql("CREATE TABLE CachedImages (key TEXT, pixelRatio INTEGER, formatVersion NUMERIC, imageVersion NUMERIC, data BLOB, UNIQUE(key, pixelRatio))", [], null, _logSQLError);
-
- complete();
- });
- }, _logSQLTransactionError);
-}
-
-function saveImageToStorage(storageKey, context, width, height, imageVersion)
-{
- console.assert(storageKey);
- console.assert(context);
- console.assert(typeof width === "number");
- console.assert(typeof height === "number");
- console.assert(typeof imageVersion === "number");
-
- if (!_generatedImageCacheDatabase)
- return;
-
- var imageData = context.getImageData(0, 0, width, height);
- var imageDataPixels = new Uint32Array(imageData.data.buffer);
-
- var imageDataString = "";
- for (var i = 0; i < imageDataPixels.length; ++i)
- imageDataString += (i ? ":" : "") + (imageDataPixels[i] ? imageDataPixels[i].toString(36) : "");
-
- _generatedImageCacheDatabase.transaction(function(tx) {
- tx.executeSql("INSERT OR REPLACE INTO CachedImages (key, pixelRatio, imageVersion, formatVersion, data) VALUES (?, ?, ?, ?, ?)", [storageKey, window.devicePixelRatio, imageVersion, _imageStorageFormatVersion, imageDataString], null, _logSQLError);
- }, _logSQLTransactionError);
-}
-
-function restoreImageFromStorage(storageKey, context, width, height, imageVersion, generateCallback)
-{
- console.assert(storageKey);
- console.assert(context);
- console.assert(typeof width === "number");
- console.assert(typeof height === "number");
- console.assert(typeof imageVersion === "number");
- console.assert(typeof generateCallback === "function");
-
- if (!_generatedImageCacheDatabase) {
- generateCallback();
- return;
- }
-
- var imageInfo = _fetchedCachedImages[storageKey];
-
- if (imageInfo) {
- // We only want to keep the data around for the first use. These images
- // are typically only used in one place. This keeps performance good
- // during page load and frees memory that typically won't be reused.
- delete _fetchedCachedImages[storageKey];
- }
-
- if (imageInfo && (!imageInfo.data || imageInfo.imageVersion !== imageVersion)) {
- generateCallback();
- return;
- }
-
- if (imageInfo) {
- // Restore the image from the memory cache.
- restoreImageData(imageInfo.data);
- } else {
- // Try fetching the image data from the database.
- _generatedImageCacheDatabase.readTransaction(function(tx) {
- tx.executeSql("SELECT data FROM CachedImages WHERE key = ? AND pixelRatio = ? AND imageVersion = ? AND formatVersion = ?", [storageKey, window.devicePixelRatio, imageVersion, _imageStorageFormatVersion], function(tx, result) {
- if (!result.rows.length) {
- generateCallback();
- return;
- }
-
- console.assert(result.rows.length === 1);
-
- restoreImageData(result.rows.item(0).data);
- }, function(tx, error) {
- _logSQLError(tx, error);
-
- generateCallback();
- });
- }, _logSQLTransactionError);
- }
-
- function restoreImageData(imageDataString)
- {
- var imageData = context.createImageData(width, height);
- var imageDataPixels = new Uint32Array(imageData.data.buffer);
-
- var imageDataArray = imageDataString.split(":");
- if (imageDataArray.length !== imageDataPixels.length) {
- generateCallback();
- return;
- }
-
- for (var i = 0; i < imageDataArray.length; ++i) {
- var pixelString = imageDataArray[i];
- imageDataPixels[i] = pixelString ? parseInt(pixelString, 36) : 0;
- }
-
- context.putImageData(imageData, 0, 0);
- }
-}
-
-function generateColoredImage(inputImage, red, green, blue, alpha, width, height)
-{
- console.assert(inputImage);
-
- if (alpha === undefined)
- alpha = 1;
-
- if (width === undefined)
- width = inputImage.width;
-
- if (height === undefined)
- height = inputImage.height;
-
- if (inputImage instanceof HTMLCanvasElement) {
- // The input is already a canvas, so we can use its context directly.
- var inputContext = inputImage.getContext("2d");
- } else {
- console.assert(inputImage instanceof HTMLImageElement || inputImage instanceof HTMLVideoElement);
-
- // The input is an image/video element, so we need to draw it into
- // a canvas to get the pixel data.
- var inputCanvas = document.createElement("canvas");
- inputCanvas.width = width;
- inputCanvas.height = height;
-
- var inputContext = inputCanvas.getContext("2d");
- inputContext.drawImage(inputImage, 0, 0, width, height);
- }
-
- var imageData = inputContext.getImageData(0, 0, width, height);
- var imageDataPixels = new Uint32Array(imageData.data.buffer);
-
- var isLittleEndian = Uint32Array.isLittleEndian();
-
- // Loop over the image data and set the color channels while preserving the alpha.
- for (var i = 0; i < imageDataPixels.length; ++i) {
- if (isLittleEndian) {
- var existingAlpha = 0xff & (imageDataPixels[i] >> 24);
- imageDataPixels[i] = red | green << 8 | blue << 16 | (existingAlpha * alpha) << 24;
- } else {
- var existingAlpha = 0xff & imageDataPixels[i];
- imageDataPixels[i] = red << 24 | green << 16 | blue << 8 | existingAlpha * alpha;
- }
- }
-
- // Make a canvas that will be returned as the result.
- var resultCanvas = document.createElement("canvas");
- resultCanvas.width = width;
- resultCanvas.height = height;
-
- var resultContext = resultCanvas.getContext("2d");
-
- resultContext.putImageData(imageData, 0, 0);
-
- return resultCanvas;
-}
-
-function generateColoredImagesForCSS(imagePath, specifications, width, height, canvasIdentifierPrefix)
-{
- console.assert(imagePath);
- console.assert(specifications);
- console.assert(typeof width === "number");
- console.assert(typeof height === "number");
-
- var scaleFactor = window.devicePixelRatio;
- var scaledWidth = width * scaleFactor;
- var scaledHeight = height * scaleFactor;
-
- canvasIdentifierPrefix = canvasIdentifierPrefix || "";
-
- const storageKeyPrefix = "generated-colored-image-";
-
- var imageElement = null;
- var pendingImageLoadCallbacks = [];
-
- _registerGeneratedImageUpdateFunction(update);
-
- function imageLoaded()
- {
- console.assert(imageElement);
- console.assert(imageElement.complete);
- for (var i = 0; i < pendingImageLoadCallbacks.length; ++i)
- pendingImageLoadCallbacks[i]();
- pendingImageLoadCallbacks = null;
- }
-
- function ensureImageIsLoaded(callback)
- {
- if (imageElement && imageElement.complete) {
- callback();
- return;
- }
-
- console.assert(pendingImageLoadCallbacks);
- pendingImageLoadCallbacks.push(callback);
-
- if (imageElement)
- return;
-
- imageElement = document.createElement("img");
- imageElement.addEventListener("load", imageLoaded);
- imageElement.width = width;
- imageElement.height = height;
- imageElement.src = imagePath;
- }
-
- function restoreImages()
- {
- for (var canvasIdentifier in specifications) {
- // Don't restore active images yet.
- if (canvasIdentifier.indexOf("active") !== -1)
- continue;
-
- var specification = specifications[canvasIdentifier];
- restoreImage(canvasIdentifier, specification);
- }
-
- function restoreActiveImages()
- {
- for (var canvasIdentifier in specifications) {
- // Only restore active images here.
- if (canvasIdentifier.indexOf("active") === -1)
- continue;
-
- var specification = specifications[canvasIdentifier];
- restoreImage(canvasIdentifier, specification);
- }
- }
-
- // Delay restoring the active states until later to improve the initial page load time.
- setTimeout(restoreActiveImages, 500);
- }
-
- function restoreImage(canvasIdentifier, specification)
- {
- const storageKey = storageKeyPrefix + canvasIdentifierPrefix + canvasIdentifier;
- const context = document.getCSSCanvasContext("2d", canvasIdentifierPrefix + canvasIdentifier, scaledWidth, scaledHeight);
- restoreImageFromStorage(storageKey, context, scaledWidth, scaledHeight, specification.imageVersion || 0, function() {
- ensureImageIsLoaded(generateImage.bind(null, canvasIdentifier, specification));
- });
- }
-
- function update()
- {
- restoreImages();
- }
-
- function generateImage(canvasIdentifier, specification)
- {
- console.assert(specification.fillColor instanceof Array);
- console.assert(specification.fillColor.length === 3 || specification.fillColor.length === 4);
-
- const context = document.getCSSCanvasContext("2d", canvasIdentifierPrefix + canvasIdentifier, scaledWidth, scaledHeight);
- context.save();
- context.scale(scaleFactor, scaleFactor);
-
- if (specification.shadowColor) {
- context.shadowOffsetX = specification.shadowOffsetX || 0;
- context.shadowOffsetY = specification.shadowOffsetY || 0;
- context.shadowBlur = specification.shadowBlur || 0;
-
- if (specification.shadowColor instanceof Array) {
- if (specification.shadowColor.length === 3)
- context.shadowColor = "rgb(" + specification.shadowColor.join(", ") + ")";
- else if (specification.shadowColor.length === 4)
- context.shadowColor = "rgba(" + specification.shadowColor.join(", ") + ")";
- } else
- context.shadowColor = specification.shadowColor;
- }
-
- var coloredImage = generateColoredImage(imageElement, specification.fillColor[0], specification.fillColor[1], specification.fillColor[2], specification.fillColor[3], scaledWidth, scaledHeight);
- context.drawImage(coloredImage, 0, 0, width, height);
-
- const storageKey = storageKeyPrefix + canvasIdentifierPrefix + canvasIdentifier;
- saveImageToStorage(storageKey, context, scaledWidth, scaledHeight, specification.imageVersion || 0);
- context.restore();
- }
-}
-
-function generateEmbossedImages(src, width, height, states, canvasIdentifierCallback, ignoreCache)
-{
- console.assert(src);
- console.assert(typeof width === "number");
- console.assert(typeof height === "number");
- console.assert(states);
- console.assert(states.Normal);
- console.assert(states.Active);
- console.assert(typeof canvasIdentifierCallback === "function");
-
- var scaleFactor = window.devicePixelRatio;
- var scaledWidth = width * scaleFactor;
- var scaledHeight = height * scaleFactor;
-
- // Bump this version when making changes that affect the result image.
- const imageVersion = 2;
-
- const storageKeyPrefix = "generated-embossed-image-";
-
- var image = null;
- var pendingImageLoadCallbacks = [];
-
- _registerGeneratedImageUpdateFunction(update);
-
- function imageLoaded()
- {
- console.assert(image);
- console.assert(image.complete);
- for (var i = 0; i < pendingImageLoadCallbacks.length; ++i)
- pendingImageLoadCallbacks[i]();
- pendingImageLoadCallbacks = null;
- }
-
- function ensureImageIsLoaded(callback)
- {
- if (image && image.complete) {
- callback();
- return;
- }
-
- console.assert(pendingImageLoadCallbacks);
- pendingImageLoadCallbacks.push(callback);
-
- if (image)
- return;
-
- image = document.createElement("img");
- image.addEventListener("load", imageLoaded);
- image.width = width;
- image.height = height;
- image.src = src;
- }
-
- function restoreImages()
- {
- restoreImage(states.Normal);
- if (states.Focus)
- restoreImage(states.Focus);
-
- function restoreActiveImages()
- {
- restoreImage(states.Active);
- if (states.ActiveFocus)
- restoreImage(states.ActiveFocus);
- }
-
- // Delay restoring the active states until later to improve the initial page load time.
- setTimeout(restoreActiveImages, 500);
- }
-
- function restoreImage(state)
- {
- const storageKey = storageKeyPrefix + canvasIdentifierCallback(state);
- const context = document.getCSSCanvasContext("2d", canvasIdentifierCallback(state), scaledWidth, scaledHeight);
- restoreImageFromStorage(storageKey, context, scaledWidth, scaledHeight, imageVersion, function() {
- ensureImageIsLoaded(generateImage.bind(null, state));
- });
- }
-
- function update()
- {
- if (ignoreCache)
- generateImages();
- else
- restoreImages();
- }
-
- function generateImages()
- {
- ensureImageIsLoaded(generateImage.bind(null, states.Normal));
-
- if (states.Focus)
- ensureImageIsLoaded(generateImage.bind(null, states.Focus));
-
- function generateActiveImages()
- {
- ensureImageIsLoaded(generateImage.bind(null, states.Active));
-
- if (states.ActiveFocus)
- ensureImageIsLoaded(generateImage.bind(null, states.ActiveFocus));
- }
-
- // Delay generating the active states until later to improve the initial page load time.
- setTimeout(generateActiveImages, 500);
- }
-
- function generateImage(state)
- {
- const depth = 1 * scaleFactor;
- const shadowDepth = depth;
- const shadowBlur = depth - 1;
- const glowBlur = 2;
-
- const context = document.getCSSCanvasContext("2d", canvasIdentifierCallback(state), scaledWidth, scaledHeight);
- context.save();
- context.scale(scaleFactor, scaleFactor);
-
- context.clearRect(0, 0, width, height);
-
- if (depth > 0) {
- // Use scratch canvas so we can apply the draw the white drop shadow
- // to the whole glyph at the end.
-
- var scratchCanvas = document.createElement("canvas");
- scratchCanvas.width = scaledWidth;
- scratchCanvas.height = scaledHeight;
-
- var scratchContext = scratchCanvas.getContext("2d");
- scratchContext.scale(scaleFactor, scaleFactor);
- } else
- var scratchContext = context;
-
- var gradient = scratchContext.createLinearGradient(0, 0, 0, height);
- if (state === states.Active) {
- gradient.addColorStop(0, "rgb(60, 60, 60)");
- gradient.addColorStop(1, "rgb(100, 100, 100)");
- } else if (state === states.Focus) {
- gradient.addColorStop(0, "rgb(50, 135, 200)");
- gradient.addColorStop(1, "rgb(60, 155, 225)");
- } else if (state === states.ActiveFocus) {
- gradient.addColorStop(0, "rgb(30, 115, 185)");
- gradient.addColorStop(1, "rgb(40, 135, 200)");
- } else {
- gradient.addColorStop(0, "rgb(90, 90, 90)");
- gradient.addColorStop(1, "rgb(145, 145, 145)");
- }
-
- scratchContext.fillStyle = gradient;
- scratchContext.fillRect(0, 0, width, height);
-
- if (depth > 0) {
- // Invert the image to use as a reverse image mask for the inner shadows.
- // Pass in the color to use for the opaque areas to prevent "black halos"
- // later when applying the final image mask.
-
- if (state === states.Active)
- var invertedImage = _invertMaskImage(image, 60, 60, 60);
- else if (state === states.Focus)
- var invertedImage = _invertMaskImage(image, 45, 145, 210);
- else if (state === states.ActiveFocus)
- var invertedImage = _invertMaskImage(image, 35, 125, 195);
- else
- var invertedImage = _invertMaskImage(image, 90, 90, 90);
-
- if (state === states.Focus) {
- // Double draw the blurry inner shadow to get the right effect.
- _drawImageShadow(scratchContext, 0, 0, shadowDepth, "rgb(10, 95, 150)", invertedImage);
- _drawImageShadow(scratchContext, 0, 0, shadowDepth, "rgb(10, 95, 150)", invertedImage);
-
- // Draw the inner shadow.
- _drawImageShadow(scratchContext, 0, shadowDepth, shadowBlur, "rgb(0, 80, 170)", invertedImage);
- } else if (state === states.ActiveFocus) {
- // Double draw the blurry inner shadow to get the right effect.
- _drawImageShadow(scratchContext, 0, 0, shadowDepth, "rgb(0, 80, 100)", invertedImage);
- _drawImageShadow(scratchContext, 0, 0, shadowDepth, "rgb(0, 80, 100)", invertedImage);
-
- // Draw the inner shadow.
- _drawImageShadow(scratchContext, 0, shadowDepth, shadowBlur, "rgb(0, 65, 150)", invertedImage);
- } else {
- // Double draw the blurry inner shadow to get the right effect.
- _drawImageShadow(scratchContext, 0, 0, shadowDepth, "rgba(0, 0, 0, 1)", invertedImage);
- _drawImageShadow(scratchContext, 0, 0, shadowDepth, "rgba(0, 0, 0, 1)", invertedImage);
-
- // Draw the inner shadow.
- _drawImageShadow(scratchContext, 0, shadowDepth, shadowBlur, "rgba(0, 0, 0, 0.6)", invertedImage);
- }
- }
-
- // Apply the mask to keep just the inner shape of the glyph.
- _applyImageMask(scratchContext, image);
-
- // Draw the white drop shadow.
- if (depth > 0)
- _drawImageShadow(context, 0, shadowDepth, shadowBlur, "rgba(255, 255, 255, 0.6)", scratchCanvas);
-
- // Draw a subtle glow for the focus states.
- if (state === states.Focus || state === states.ActiveFocus)
- _drawImageShadow(context, 0, 0, glowBlur, "rgba(20, 100, 220, 0.4)", scratchCanvas);
-
- if (!ignoreCache) {
- const storageKey = storageKeyPrefix + canvasIdentifierCallback(state);
- saveImageToStorage(storageKey, context, scaledWidth, scaledHeight, imageVersion);
- }
-
- context.restore();
- }
-
- function _drawImageShadow(context, xOffset, yOffset, blur, color, image) {
- context.save();
-
- context.shadowOffsetX = xOffset || 0;
- context.shadowOffsetY = yOffset || 0;
- context.shadowBlur = blur || 0;
- context.shadowColor = color || "black";
-
- context.drawImage(image, 0, 0, width, height);
-
- context.restore();
- }
-
- function _invertMaskImage(image, red, green, blue) {
- var bufferCanvas = document.createElement("canvas");
- bufferCanvas.width = scaledWidth;
- bufferCanvas.height = scaledHeight;
-
- var buffer = bufferCanvas.getContext("2d");
- buffer.scale(scaleFactor, scaleFactor);
- buffer.drawImage(image, 0, 0, width, height);
-
- var imageData = buffer.getImageData(0, 0, scaledWidth, scaledHeight);
- var imageDataPixels = new Uint32Array(imageData.data.buffer);
-
- red = red || 0;
- green = green || 0;
- blue = blue || 0;
-
- var isLittleEndian = Uint32Array.isLittleEndian();
-
- for (var i = 0; i < imageDataPixels.length; ++i) {
- if (isLittleEndian) {
- var existingAlpha = 0xff & (imageDataPixels[i] >> 24);
- imageDataPixels[i] = red | green << 8 | blue << 16 | (255 - existingAlpha) << 24;
- } else {
- var existingAlpha = 0xff & imageDataPixels[i];
- imageDataPixels[i] = red << 24 | green << 16 | blue << 8 | 255 - existingAlpha;
- }
- }
-
- buffer.putImageData(imageData, 0, 0);
-
- return bufferCanvas;
- }
-
- function _applyImageMask(context, image) {
- var maskCanvas = document.createElement("canvas");
- maskCanvas.width = scaledWidth;
- maskCanvas.height = scaledHeight;
-
- var mask = maskCanvas.getContext("2d");
- mask.scale(scaleFactor, scaleFactor);
- mask.drawImage(image, 0, 0, width, height);
-
- var imageData = context.getImageData(0, 0, scaledWidth, scaledHeight);
- var imageDataPixels = imageData.data;
-
- var maskImageDataPixels = mask.getImageData(0, 0, scaledWidth, scaledHeight).data;
-
- for (var i = 3; i < imageDataPixels.length; i += 4)
- imageDataPixels[i] = maskImageDataPixels[i] * (imageDataPixels[i] / 255);
-
- context.putImageData(imageData, 0, 0);
- }
-}
-
-
-var svgImageCache = {};
-
-function loadSVGImageDocumentElement(url, callback)
-{
- function invokeCallbackWithDocument(svgText) {
- var parser = new DOMParser;
- var doc = parser.parseFromString(svgText, "image/svg+xml");
- callback(doc.documentElement);
- }
-
- function imageLoad(event) {
- if (xhr.status === 0 || xhr.status === 200) {
- var svgText = xhr.responseText;
- svgImageCache[url] = svgText;
- invokeCallbackWithDocument(svgText);
- } else {
- console.error("Unexpected XHR status (" + xhr.status + ") loading SVG image: " + url);
- callback(null);
- }
- }
-
- function imageError(event) {
- console.error("Unexpected failure loading SVG image: " + url);
- callback(null);
- }
-
- var cachedSVGText = svgImageCache[url];
- if (cachedSVGText) {
- invokeCallbackWithDocument(cachedSVGText);
- return;
- }
-
- var xhr = new XMLHttpRequest;
- xhr.open("GET", url, true);
- xhr.addEventListener("load", imageLoad);
- xhr.addEventListener("error", imageError);
- xhr.send();
-}
-
-function wrappedSVGDocument(url, className, title, callback)
-{
- loadSVGImageDocumentElement(url, function(svgDocument) {
- if (!svgDocument) {
- callback(null);
- return;
- }
-
- var wrapper = document.createElement("div");
- if (className)
- wrapper.className = className;
- if (title)
- wrapper.title = title;
- wrapper.appendChild(svgDocument);
-
- callback(wrapper);
- });
-}