ag-grid-enterprise
Version:
AG Grid Enterprise Features
355 lines • 14 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.HdpiCanvas = void 0;
var userAgent_1 = require("../util/userAgent");
/**
* Wraps the native Canvas element and overrides its CanvasRenderingContext2D to
* provide resolution independent rendering based on `window.devicePixelRatio`.
*/
var HdpiCanvas = /** @class */ (function () {
// The width/height attributes of the Canvas element default to
// 300/150 according to w3.org.
function HdpiCanvas(_a) {
var _b = _a.document, document = _b === void 0 ? window.document : _b, _c = _a.width, width = _c === void 0 ? 600 : _c, _d = _a.height, height = _d === void 0 ? 300 : _d, _e = _a.domLayer, domLayer = _e === void 0 ? false : _e, _f = _a.zIndex, zIndex = _f === void 0 ? 0 : _f, _g = _a.name, name = _g === void 0 ? undefined : _g, _h = _a.overrideDevicePixelRatio, overrideDevicePixelRatio = _h === void 0 ? undefined : _h;
this._container = undefined;
this._enabled = true;
// `NaN` is deliberate here, so that overrides are always applied
// and the `resetTransform` inside the `resize` method works in IE11.
this._pixelRatio = NaN;
this._width = 0;
this._height = 0;
this.document = document;
// Create canvas and immediately apply width + height to avoid out-of-memory
// errors on iOS/iPadOS Safari.
this.element = document.createElement('canvas');
this.element.width = width;
this.element.height = height;
this.context = this.element.getContext('2d');
this.imageSource = this.context.canvas;
var style = this.element.style;
style.userSelect = 'none';
style.display = 'block';
if (domLayer) {
style.position = 'absolute';
style.zIndex = String(zIndex);
style.top = '0';
style.left = '0';
style.pointerEvents = 'none';
style.opacity = "1";
if (name) {
this.element.id = name;
}
}
this.setPixelRatio(overrideDevicePixelRatio);
this.resize(width, height);
}
Object.defineProperty(HdpiCanvas.prototype, "container", {
get: function () {
return this._container;
},
set: function (value) {
if (this._container !== value) {
this.remove();
if (value) {
value.appendChild(this.element);
}
this._container = value;
}
},
enumerable: false,
configurable: true
});
Object.defineProperty(HdpiCanvas.prototype, "enabled", {
get: function () {
return this._enabled;
},
set: function (value) {
this.element.style.display = value ? 'block' : 'none';
this._enabled = !!value;
},
enumerable: false,
configurable: true
});
HdpiCanvas.prototype.remove = function () {
var parentNode = this.element.parentNode;
if (parentNode != null) {
parentNode.removeChild(this.element);
}
};
HdpiCanvas.prototype.destroy = function () {
this.element.remove();
// Workaround memory allocation quirks in iOS Safari by resizing to 0x0 and clearing.
// See https://bugs.webkit.org/show_bug.cgi?id=195325.
this.element.width = 0;
this.element.height = 0;
this.context.clearRect(0, 0, 0, 0);
Object.freeze(this);
};
HdpiCanvas.prototype.snapshot = function () {
// No-op for compatibility with HdpiOffscreenCanvas.
};
HdpiCanvas.prototype.clear = function () {
this.context.save();
this.context.resetTransform();
this.context.clearRect(0, 0, this.width, this.height);
this.context.restore();
};
HdpiCanvas.prototype.toImage = function () {
var img = this.document.createElement('img');
img.src = this.getDataURL();
return img;
};
HdpiCanvas.prototype.getDataURL = function (type) {
return this.element.toDataURL(type);
};
/**
* @param fileName The name of the downloaded file.
* @param fileFormat The file format, the default is `image/png`
*/
HdpiCanvas.prototype.download = function (fileName, fileFormat) {
if (fileFormat === void 0) { fileFormat = 'image/png'; }
fileName = (fileName !== null && fileName !== void 0 ? fileName : '').trim() || 'image';
var dataUrl = this.getDataURL(fileFormat);
var document = this.document;
var a = document.createElement('a');
a.href = dataUrl;
a.download = fileName;
a.style.display = 'none';
document.body.appendChild(a); // required for the `click` to work in Firefox
a.click();
document.body.removeChild(a);
};
Object.defineProperty(HdpiCanvas.prototype, "pixelRatio", {
get: function () {
return this._pixelRatio;
},
enumerable: false,
configurable: true
});
/**
* Changes the pixel ratio of the Canvas element to the given value,
* or uses the window.devicePixelRatio (default), then resizes the Canvas
* element accordingly (default).
*/
HdpiCanvas.prototype.setPixelRatio = function (ratio) {
var pixelRatio = ratio !== null && ratio !== void 0 ? ratio : window.devicePixelRatio;
if (!userAgent_1.isDesktop()) {
// Mobile browsers have stricter memory limits, we reduce rendering resolution to
// improve stability on mobile browsers. iOS Safari 12->16 are pain-points since they
// have memory allocation quirks - see https://bugs.webkit.org/show_bug.cgi?id=195325.
pixelRatio = 1;
}
HdpiCanvas.overrideScale(this.context, pixelRatio);
this._pixelRatio = pixelRatio;
};
Object.defineProperty(HdpiCanvas.prototype, "pixelated", {
get: function () {
return this.element.style.imageRendering === 'pixelated';
},
set: function (value) {
this.element.style.imageRendering = value ? 'pixelated' : 'auto';
},
enumerable: false,
configurable: true
});
Object.defineProperty(HdpiCanvas.prototype, "width", {
get: function () {
return this._width;
},
enumerable: false,
configurable: true
});
Object.defineProperty(HdpiCanvas.prototype, "height", {
get: function () {
return this._height;
},
enumerable: false,
configurable: true
});
HdpiCanvas.prototype.resize = function (width, height) {
if (!(width > 0 && height > 0)) {
return;
}
var _a = this, element = _a.element, context = _a.context, pixelRatio = _a.pixelRatio;
element.width = Math.round(width * pixelRatio);
element.height = Math.round(height * pixelRatio);
element.style.width = width + 'px';
element.style.height = height + 'px';
context.resetTransform();
this._width = width;
this._height = height;
};
Object.defineProperty(HdpiCanvas, "textMeasuringContext", {
get: function () {
if (this._textMeasuringContext) {
return this._textMeasuringContext;
}
var canvas = document.createElement('canvas');
this._textMeasuringContext = canvas.getContext('2d');
return this._textMeasuringContext;
},
enumerable: false,
configurable: true
});
Object.defineProperty(HdpiCanvas, "svgText", {
get: function () {
if (this._svgText) {
return this._svgText;
}
var xmlns = 'http://www.w3.org/2000/svg';
var svg = document.createElementNS(xmlns, 'svg');
svg.setAttribute('width', '100');
svg.setAttribute('height', '100');
// Add a descriptive class name in case someone sees this SVG element
// in devtools and wonders about its purpose:
if (svg.classList) {
svg.classList.add('text-measuring-svg');
}
else {
svg.setAttribute('class', 'text-measuring-svg');
}
svg.style.position = 'absolute';
svg.style.top = '-1000px';
svg.style.visibility = 'hidden';
var svgText = document.createElementNS(xmlns, 'text');
svgText.setAttribute('x', '0');
svgText.setAttribute('y', '30');
svgText.setAttribute('text', 'black');
svg.appendChild(svgText);
document.body.appendChild(svg);
this._svgText = svgText;
return svgText;
},
enumerable: false,
configurable: true
});
Object.defineProperty(HdpiCanvas, "has", {
get: function () {
if (this._has) {
return this._has;
}
var isChrome = navigator.userAgent.indexOf('Chrome') > -1;
var isFirefox = navigator.userAgent.indexOf('Firefox') > -1;
var isSafari = !isChrome && navigator.userAgent.indexOf('Safari') > -1;
this._has = Object.freeze({
textMetrics: this.textMeasuringContext.measureText('test').actualBoundingBoxDescent !== undefined &&
// Firefox implemented advanced TextMetrics object in v74:
// https://bugzilla.mozilla.org/show_bug.cgi?id=1102584
// but it's buggy, so we'll keep using the SVG for text measurement in Firefox for now.
!isFirefox &&
!isSafari,
getTransform: this.textMeasuringContext.getTransform !== undefined,
});
return this._has;
},
enumerable: false,
configurable: true
});
HdpiCanvas.measureText = function (text, font, textBaseline, textAlign) {
var ctx = this.textMeasuringContext;
ctx.font = font;
ctx.textBaseline = textBaseline;
ctx.textAlign = textAlign;
return ctx.measureText(text);
};
/**
* Returns the width and height of the measured text.
* @param text The single-line text to measure.
* @param font The font shorthand string.
*/
HdpiCanvas.getTextSize = function (text, font) {
if (this.has.textMetrics) {
var ctx = this.textMeasuringContext;
ctx.font = font;
var metrics = ctx.measureText(text);
return {
width: metrics.width,
height: metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent,
};
}
else {
return this.measureSvgText(text, font);
}
};
HdpiCanvas.measureSvgText = function (text, font) {
var cache = this.textSizeCache;
var fontCache = cache[font];
// Note: consider not caching the size of numeric strings.
// For example: if (isNaN(+text)) { // skip
if (fontCache) {
var size_1 = fontCache[text];
if (size_1) {
return size_1;
}
}
else {
cache[font] = {};
}
var svgText = this.svgText;
svgText.style.font = font;
svgText.textContent = text;
// `getBBox` returns an instance of `SVGRect` with the same `width` and `height`
// measurements as `DOMRect` instance returned by the `getBoundingClientRect`.
// But the `SVGRect` instance has half the properties of the `DOMRect`,
// so we use the `getBBox` method.
var bbox = svgText.getBBox();
var size = {
width: bbox.width,
height: bbox.height,
};
cache[font][text] = size;
return size;
};
HdpiCanvas.overrideScale = function (ctx, scale) {
var depth = 0;
var overrides = {
save: function () {
this.$save();
depth++;
},
restore: function () {
if (depth > 0) {
this.$restore();
depth--;
}
else {
throw new Error('AG Charts - Unable to restore() past depth 0');
}
},
setTransform: function (a, b, c, d, e, f) {
if (typeof a === 'object') {
this.$setTransform(a);
}
else {
this.$setTransform(a * scale, b * scale, c * scale, d * scale, e * scale, f * scale);
}
},
resetTransform: function () {
// As of Jan 8, 2019, `resetTransform` is still an "experimental technology",
// and doesn't work in IE11 and Edge 44.
this.$setTransform(scale, 0, 0, scale, 0, 0);
},
verifyDepthZero: function () {
if (depth !== 0) {
throw new Error('AG Charts - Save/restore depth is non-zero: ' + depth);
}
},
};
for (var name_1 in overrides) {
if (Object.prototype.hasOwnProperty.call(overrides, name_1)) {
// Save native methods under prefixed names,
// if this hasn't been done by the previous overrides already.
if (!ctx['$' + name_1]) {
ctx['$' + name_1] = ctx[name_1];
}
// Replace native methods with overrides,
// or previous overrides with the new ones.
ctx[name_1] = overrides[name_1];
}
}
};
HdpiCanvas.textSizeCache = {};
return HdpiCanvas;
}());
exports.HdpiCanvas = HdpiCanvas;
//# sourceMappingURL=hdpiCanvas.js.map