@knoopx/react-pdf
Version:
<p align="center"> <img src="https://user-images.githubusercontent.com/5600341/27505816-c8bc37aa-587f-11e7-9a86-08a2d081a8b9.png" height="280px"> <p align="center">React renderer for creating PDF files on the browser and server<p> <p align="center">
1,615 lines (1,371 loc) • 162 kB
JavaScript
import _inheritsLoose from '@babel/runtime/helpers/inheritsLoose';
import _objectWithoutPropertiesLoose from '@babel/runtime/helpers/objectWithoutPropertiesLoose';
import _extends from '@babel/runtime/helpers/extends';
import React, { Fragment } from 'react';
import _regeneratorRuntime from '@babel/runtime/regenerator';
import _asyncToGenerator from '@babel/runtime/helpers/asyncToGenerator';
import BlobStream from 'blob-stream';
import ReactFiberReconciler from 'react-reconciler';
import _createClass from '@babel/runtime/helpers/createClass';
import PDFDocument, { PDFFont } from '@react-pdf/pdfkit';
import Yoga from 'yoga-layout-prebuilt';
import { mergeDeepWith, isNil, compose, equals, type, toPairsIn, pick, pathOr, last, propEq, complement, prop } from 'ramda';
import matchMedia from 'media-engine';
import _assertThisInitialized from '@babel/runtime/helpers/assertThisInitialized';
import PDFRenderer$1 from '@react-pdf/textkit/renderers/pdf';
import AttributedString from '@react-pdf/textkit/attributedString';
import 'is-url';
import fontkit from '@react-pdf/fontkit';
import fetch from 'cross-fetch';
import layoutEngine from '@react-pdf/textkit/layout';
import linebreaker from '@react-pdf/textkit/engines/linebreaker';
import justification from '@react-pdf/textkit/engines/justification';
import textDecoration from '@react-pdf/textkit/engines/textDecoration';
import scriptItemizer from '@react-pdf/textkit/engines/scriptItemizer';
import wordHyphenation from '@react-pdf/textkit/engines/wordHyphenation';
import emojiRegex from 'emoji-regex';
import PNG from '@react-pdf/png-js';
import _wrapPages from 'page-wrapping';
function printWarning(format) {
for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
args[_key - 1] = arguments[_key];
}
var argIndex = 0;
var message = 'Warning: ' + format.replace(/%s/g, function () {
return args[argIndex++];
});
if (typeof console !== 'undefined') {
console.error(message);
}
try {
throw new Error(message);
} catch (x) {}
}
var __DEV__ = process.env.NODE_ENV !== 'production';
var warning = __DEV__ ? function (condition, format) {
if (format === undefined) {
throw new Error('`warning(condition, format, ...args)` requires a warning ' + 'message argument');
}
if (!condition) {
for (var _len2 = arguments.length, args = new Array(_len2 > 2 ? _len2 - 2 : 0), _key2 = 2; _key2 < _len2; _key2++) {
args[_key2 - 2] = arguments[_key2];
}
printWarning.apply(void 0, [format].concat(args));
}
} : function () {};
var Root =
/*#__PURE__*/
function () {
function Root() {
this.isDirty = false;
this.document = null;
this.instance = null;
}
var _proto = Root.prototype;
_proto.appendChild = function appendChild(child) {
this.document = child;
};
_proto.removeChild = function removeChild() {
this.document.cleanup();
this.document = null;
};
_proto.markDirty = function markDirty() {
this.isDirty = true;
};
_proto.cleanup = function cleanup() {
this.document.cleanup();
};
_proto.finish = function finish() {
this.document.finish();
};
_proto.render =
/*#__PURE__*/
function () {
var _render = _asyncToGenerator(
/*#__PURE__*/
_regeneratorRuntime.mark(function _callee() {
return _regeneratorRuntime.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
this.instance = new PDFDocument({
autoFirstPage: false
});
_context.next = 3;
return this.document.render();
case 3:
this.cleanup();
this.isDirty = false;
case 5:
case "end":
return _context.stop();
}
}
}, _callee, this);
}));
function render() {
return _render.apply(this, arguments);
}
return render;
}();
_createClass(Root, [{
key: "name",
get: function get() {
return 'Root';
}
}]);
return Root;
}();
var upperFirst = function upperFirst(value) {
return value.charAt(0).toUpperCase() + value.slice(1);
};
var isPercent = function isPercent(value) {
return /((-)?\d+\.?\d*)%/g.exec(value);
};
var matchPercent = function matchPercent(value) {
var match = isPercent(value);
if (match) {
var _value = parseFloat(match[1], 10);
var percent = _value / 100;
return {
value: _value,
percent: percent,
absValue: Math.abs(_value),
absPercent: Math.abs(percent)
};
}
return null;
};
var Node =
/*#__PURE__*/
function () {
function Node() {
this.parent = null;
this.children = [];
this.computed = false;
this.layout = Yoga.Node.createDefault();
}
var _proto = Node.prototype;
_proto.appendChild = function appendChild(child) {
if (child) {
child.parent = this;
this.children.push(child);
this.layout.insertChild(child.layout, this.layout.getChildCount());
}
};
_proto.appendChildBefore = function appendChildBefore(child, beforeChild) {
var index = this.children.indexOf(beforeChild);
if (index !== -1 && child) {
child.parent = this;
this.children.splice(index, 0, child);
this.layout.insertChild(child.layout, index);
}
};
_proto.removeChild = function removeChild(child) {
var index = this.children.indexOf(child);
if (index !== -1) {
child.parent = null;
this.children.splice(index, 1);
this.layout.removeChild(child.layout);
}
child.cleanup();
};
_proto.removeAllChilds = function removeAllChilds() {
var children = [].concat(this.children);
for (var i = 0; i < children.length; i++) {
children[i].remove();
}
};
_proto.remove = function remove() {
this.parent.removeChild(this);
};
_proto.setDimension = function setDimension(attr, value) {
var fixedMethod = "set" + upperFirst(attr);
var percentMethod = fixedMethod + "Percent";
var percent = matchPercent(value);
if (percent) {
this.layout[percentMethod](percent.value);
} else {
this.layout[fixedMethod](value);
}
};
_proto.setPosition = function setPosition(edge, value) {
var percent = matchPercent(value);
if (percent) {
this.layout.setPositionPercent(edge, percent.value);
} else {
this.layout.setPosition(edge, value);
}
};
_proto.setPadding = function setPadding(edge, value) {
var percent = matchPercent(value);
if (percent) {
this.layout.setPaddingPercent(edge, percent.value);
} else {
this.layout.setPadding(edge, value);
}
};
_proto.setMargin = function setMargin(edge, value) {
var percent = matchPercent(value);
if (percent) {
this.layout.setMarginPercent(edge, percent.value);
} else {
this.layout.setMargin(edge, value);
}
};
_proto.setBorder = function setBorder(edge, value) {
if (matchPercent(value)) {
throw new Error('Node: You cannot set percentage border widths');
}
this.layout.setBorder(edge, value);
};
_proto.getAbsoluteLayout = function getAbsoluteLayout() {
var parent = this.parent;
var parentLayout = parent && parent.getAbsoluteLayout ? parent.getAbsoluteLayout() : {
left: 0,
top: 0
};
return {
left: this.left + parentLayout.left,
top: this.top + parentLayout.top,
height: this.height,
width: this.width
};
};
_proto.copyStyle = function copyStyle(node) {
this.layout.copyStyle(node.layout);
};
_proto.calculateLayout = function calculateLayout() {
this.layout.calculateLayout();
this.computed = true;
};
_proto.isEmpty = function isEmpty() {
return this.children.length === 0;
};
_proto.markDirty = function markDirty() {
return this.layout.markDirty();
};
_proto.onAppendDynamically = function onAppendDynamically() {};
_proto.cleanup = function cleanup() {
this.children.forEach(function (c) {
return c.cleanup();
});
this.layout.unsetMeasureFunc();
Yoga.Node.destroy(this.layout);
};
_createClass(Node, [{
key: "position",
get: function get() {
return this.layout.getPositionType() === Yoga.POSITION_TYPE_ABSOLUTE ? 'absolute' : 'relative';
},
set: function set(value) {
this.layout.setPositionType(value === 'absolute' ? Yoga.POSITION_TYPE_ABSOLUTE : Yoga.POSITION_TYPE_RELATIVE);
}
}, {
key: "top",
get: function get() {
return this.layout.getComputedTop() || 0;
},
set: function set(value) {
this.setPosition(Yoga.EDGE_TOP, value);
}
}, {
key: "left",
get: function get() {
return this.layout.getComputedLeft() || 0;
},
set: function set(value) {
this.setPosition(Yoga.EDGE_LEFT, value);
}
}, {
key: "right",
get: function get() {
return this.layout.getComputedRight() || 0;
},
set: function set(value) {
this.setPosition(Yoga.EDGE_RIGHT, value);
}
}, {
key: "bottom",
get: function get() {
return this.layout.getComputedBottom() || 0;
},
set: function set(value) {
this.setPosition(Yoga.EDGE_BOTTOM, value);
}
}, {
key: "width",
get: function get() {
return this.layout.getComputedWidth();
},
set: function set(value) {
this.setDimension('width', value);
}
}, {
key: "minWidth",
get: function get() {
return this.layout.getMinWidth().value;
},
set: function set(value) {
this.setDimension('minWidth', value);
}
}, {
key: "maxWidth",
get: function get() {
return this.layout.getMaxWidth().value;
},
set: function set(value) {
this.setDimension('maxWidth', value);
}
}, {
key: "height",
get: function get() {
return this.layout.getComputedHeight();
},
set: function set(value) {
this.setDimension('height', value);
}
}, {
key: "minHeight",
get: function get() {
return this.layout.getMinHeight().value;
},
set: function set(value) {
this.setDimension('minHeight', value);
}
}, {
key: "maxHeight",
get: function get() {
return this.layout.getMaxHeight().value;
},
set: function set(value) {
this.setDimension('maxHeight', value);
}
}, {
key: "paddingTop",
get: function get() {
return this.layout.getComputedPadding(Yoga.EDGE_TOP) || 0;
},
set: function set(value) {
this.setPadding(Yoga.EDGE_TOP, value);
}
}, {
key: "paddingRight",
get: function get() {
return this.layout.getComputedPadding(Yoga.EDGE_RIGHT) || 0;
},
set: function set(value) {
this.setPadding(Yoga.EDGE_RIGHT, value);
}
}, {
key: "paddingBottom",
get: function get() {
return this.layout.getComputedPadding(Yoga.EDGE_BOTTOM) || 0;
},
set: function set(value) {
this.setPadding(Yoga.EDGE_BOTTOM, value);
}
}, {
key: "paddingLeft",
get: function get() {
return this.layout.getComputedPadding(Yoga.EDGE_LEFT) || 0;
},
set: function set(value) {
this.setPadding(Yoga.EDGE_LEFT, value);
}
}, {
key: "marginTop",
get: function get() {
return this.layout.getComputedMargin(Yoga.EDGE_TOP) || 0;
},
set: function set(value) {
this.setMargin(Yoga.EDGE_TOP, value);
}
}, {
key: "marginRight",
get: function get() {
return this.layout.getComputedMargin(Yoga.EDGE_RIGHT) || 0;
},
set: function set(value) {
this.setMargin(Yoga.EDGE_RIGHT, value);
}
}, {
key: "marginBottom",
get: function get() {
return this.layout.getComputedMargin(Yoga.EDGE_BOTTOM) || 0;
},
set: function set(value) {
this.setMargin(Yoga.EDGE_BOTTOM, value);
}
}, {
key: "marginLeft",
get: function get() {
return this.layout.getComputedMargin(Yoga.EDGE_LEFT) || 0;
},
set: function set(value) {
this.setMargin(Yoga.EDGE_LEFT, value);
}
}, {
key: "borderTopWidth",
get: function get() {
return this.layout.getComputedBorder(Yoga.EDGE_TOP) || 0;
},
set: function set(value) {
this.setBorder(Yoga.EDGE_TOP, value);
}
}, {
key: "borderRightWidth",
get: function get() {
return this.layout.getComputedBorder(Yoga.EDGE_RIGHT) || 0;
},
set: function set(value) {
this.setBorder(Yoga.EDGE_RIGHT, value);
}
}, {
key: "borderBottomWidth",
get: function get() {
return this.layout.getComputedBorder(Yoga.EDGE_BOTTOM) || 0;
},
set: function set(value) {
this.setBorder(Yoga.EDGE_BOTTOM, value);
}
}, {
key: "borderLeftWidth",
get: function get() {
return this.layout.getComputedBorder(Yoga.EDGE_LEFT) || 0;
},
set: function set(value) {
this.setBorder(Yoga.EDGE_LEFT, value);
}
}, {
key: "padding",
get: function get() {
return {
top: this.paddingTop,
right: this.paddingRight,
bottom: this.paddingBottom,
left: this.paddingLeft
};
},
set: function set(value) {
this.paddingTop = value;
this.paddingRight = value;
this.paddingBottom = value;
this.paddingLeft = value;
}
}, {
key: "margin",
get: function get() {
return {
top: this.marginTop,
right: this.marginRight,
bottom: this.marginBottom,
left: this.marginLeft
};
},
set: function set(value) {
this.marginTop = value;
this.marginRight = value;
this.marginBottom = value;
this.marginLeft = value;
}
}]);
return Node;
}();
var yogaValue = function yogaValue(prop, value) {
var isAlignType = function isAlignType(prop) {
return prop === 'alignItems' || prop === 'alignContent' || prop === 'alignSelf';
};
switch (value) {
case 'auto':
if (prop === 'alignSelf') {
return Yoga.ALIGN_AUTO;
}
break;
case 'flex':
return Yoga.DISPLAY_FLEX;
case 'none':
return Yoga.DISPLAY_NONE;
case 'row':
return Yoga.FLEX_DIRECTION_ROW;
case 'row-reverse':
return Yoga.FLEX_DIRECTION_ROW_REVERSE;
case 'column':
return Yoga.FLEX_DIRECTION_COLUMN;
case 'column-reverse':
return Yoga.FLEX_DIRECTION_COLUMN_REVERSE;
case 'stretch':
return Yoga.ALIGN_STRETCH;
case 'baseline':
return Yoga.ALIGN_BASELINE;
case 'space-around':
if (prop === 'justifyContent') {
return Yoga.JUSTIFY_SPACE_AROUND;
} else if (isAlignType(prop)) {
return Yoga.ALIGN_SPACE_AROUND;
}
break;
case 'space-between':
if (prop === 'justifyContent') {
return Yoga.JUSTIFY_SPACE_BETWEEN;
} else if (isAlignType(prop)) {
return Yoga.ALIGN_SPACE_BETWEEN;
}
break;
case 'around':
return Yoga.JUSTIFY_SPACE_AROUND;
case 'between':
return Yoga.JUSTIFY_SPACE_BETWEEN;
case 'wrap':
return Yoga.WRAP_WRAP;
case 'wrap-reverse':
return Yoga.WRAP_WRAP_REVERSE;
case 'nowrap':
return Yoga.WRAP_NO_WRAP;
case 'flex-start':
if (prop === 'justifyContent') {
return Yoga.JUSTIFY_FLEX_START;
} else if (isAlignType(prop)) {
return Yoga.ALIGN_FLEX_START;
}
break;
case 'flex-end':
if (prop === 'justifyContent') {
return Yoga.JUSTIFY_FLEX_END;
} else if (isAlignType(prop)) {
return Yoga.ALIGN_FLEX_END;
}
break;
case 'center':
if (prop === 'justifyContent') {
return Yoga.JUSTIFY_CENTER;
} else if (isAlignType(prop)) {
return Yoga.ALIGN_CENTER;
}
break;
default:
return value;
}
}; // These are not supported yet
var DPI = 72; // 72pt per inch.
var parseValue = function parseValue(value) {
var match = /^(-?\d*\.?\d+)(in|mm|cm|pt|vh|vw)?$/g.exec(value);
if (match) {
return {
value: parseFloat(match[1], 10),
unit: match[2] || 'pt'
};
}
return {
value: value,
unit: undefined
};
};
var parseScalar = function parseScalar(value, container) {
var scalar = parseValue(value);
switch (scalar.unit) {
case 'in':
return scalar.value * DPI;
case 'mm':
return scalar.value * (1 / 25.4) * DPI;
case 'cm':
return scalar.value * (1 / 2.54) * DPI;
case 'vh':
if (container.isAutoHeight) {
throw new Error('vh unit not supported in auto-height pages. Please specify page height if you want to use vh.');
}
return scalar.value * (container.height / 100);
case 'vw':
return scalar.value * (container.width / 100);
default:
return scalar.value;
}
};
var isBorderStyle = function isBorderStyle(key, value) {
return key.match(/^border/) && typeof value === 'string';
};
var matchBorderShorthand = function matchBorderShorthand(value) {
return value.match(/(\d+(px|in|mm|cm|pt|vw|vh)?)\s(\S+)\s(\S+)/);
}; // Transforms shorthand border values
var processBorders = function processBorders(key, value) {
var match = matchBorderShorthand(value);
if (match) {
if (key.match(/.Color/)) {
return match[4];
} else if (key.match(/.Style/)) {
return match[3];
} else if (key.match(/.Width/)) {
return match[1];
} else {
throw new Error("StyleSheet: Invalid '" + value + "' for '" + key + "'");
}
}
return value;
};
var isBoxModelStyle = function isBoxModelStyle(key, value) {
return key.match(/^(margin)|(padding)/) && typeof value === 'string';
};
var matchBoxModel = function matchBoxModel(value) {
return value.match(/\d+(px|in|mm|cm|pt|%|vw|vh)?/g);
}; // Transforms shorthand margin and padding values
var processBoxModel = function processBoxModel(key, value) {
var match = matchBoxModel(value);
if (match) {
if (key.match(/.Top/)) {
return match[0];
} else if (key.match(/.Right/)) {
return match[1] || match[0];
} else if (key.match(/.Bottom/)) {
return match[2] || match[0];
} else if (key.match(/.Left/)) {
return match[3] || match[1] || match[0];
} else {
throw new Error("StyleSheet: Invalid '" + value + "' for '" + key + "'");
}
}
return value;
};
// https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight#Common_weight_name_mapping
var FONT_WEIGHTS = {
thin: 100,
hairline: 100,
ultralight: 200,
extralight: 200,
light: 300,
normal: 400,
medium: 500,
semibold: 600,
demibold: 600,
bold: 700,
ultrabold: 800,
extrabold: 800,
heavy: 900,
black: 900
};
var isFontWeightStyle = function isFontWeightStyle(key) {
return key.match(/^fontWeight/);
};
var processFontWeight = function processFontWeight(value) {
if (!value) return FONT_WEIGHTS.normal;
if (typeof value === 'number') return value;
return FONT_WEIGHTS[value.toLowerCase()];
};
var isObjectPositionStyle = function isObjectPositionStyle(key, value) {
return key.match(/^objectPosition/) && typeof value === 'string';
};
var matchObjectPosition = function matchObjectPosition(value) {
return value.match(/\d+(px|in|mm|cm|pt|%|vw|vh)?/g);
}; // Transforms shorthand objectPosition values
var processObjectPosition = function processObjectPosition(key, value) {
var match = matchObjectPosition(value);
if (match) {
if (key.match(/.X/)) {
return match[0];
} else if (key.match(/.Y/)) {
return match[1];
} else {
throw new Error("StyleSheet: Invalid '" + value + "' for '" + key + "'");
}
}
return value;
};
var isTransformOriginStyle = function isTransformOriginStyle(key, value) {
return key.match(/^transformOrigin/) && typeof value === 'string';
};
var matchTransformOrigin = function matchTransformOrigin(value) {
return value.match(/(-?\d+(px|in|mm|cm|pt|%|vw|vh)?)|top|right|bottom|left|center/g);
};
var transformOffsetKeywords = function transformOffsetKeywords(value) {
switch (value) {
case 'top':
case 'left':
return '0%';
case 'right':
case 'bottom':
return '100%';
case 'center':
return '50%';
default:
return value;
}
}; // Transforms shorthand transformOrigin values
var processTransformOrigin = function processTransformOrigin(key, value) {
var match = matchTransformOrigin(value);
if (match) {
var result;
if (key.match(/.X/)) {
result = match[0];
} else if (key.match(/.Y/)) {
result = match[1] || match[0];
} else {
throw new Error("StyleSheet: Invalid '" + value + "' for '" + key + "'");
}
return transformOffsetKeywords(result);
}
return value;
};
var hasOwnProperty = Object.prototype.hasOwnProperty;
var styleShorthands = {
margin: {
marginTop: true,
marginRight: true,
marginBottom: true,
marginLeft: true
},
marginHorizontal: {
marginLeft: true,
marginRight: true
},
marginVertical: {
marginTop: true,
marginBottom: true
},
padding: {
paddingTop: true,
paddingRight: true,
paddingBottom: true,
paddingLeft: true
},
paddingHorizontal: {
paddingLeft: true,
paddingRight: true
},
paddingVertical: {
paddingTop: true,
paddingBottom: true
},
border: {
borderTopColor: true,
borderTopStyle: true,
borderTopWidth: true,
borderRightColor: true,
borderRightStyle: true,
borderRightWidth: true,
borderBottomColor: true,
borderBottomStyle: true,
borderBottomWidth: true,
borderLeftColor: true,
borderLeftStyle: true,
borderLeftWidth: true
},
borderTop: {
borderTopColor: true,
borderTopStyle: true,
borderTopWidth: true
},
borderRight: {
borderRightColor: true,
borderRightStyle: true,
borderRightWidth: true
},
borderBottom: {
borderBottomColor: true,
borderBottomStyle: true,
borderBottomWidth: true
},
borderLeft: {
borderLeftColor: true,
borderLeftStyle: true,
borderLeftWidth: true
},
borderColor: {
borderTopColor: true,
borderRightColor: true,
borderBottomColor: true,
borderLeftColor: true
},
borderRadius: {
borderTopLeftRadius: true,
borderTopRightRadius: true,
borderBottomRightRadius: true,
borderBottomLeftRadius: true
},
borderStyle: {
borderTopStyle: true,
borderRightStyle: true,
borderBottomStyle: true,
borderLeftStyle: true
},
borderWidth: {
borderTopWidth: true,
borderRightWidth: true,
borderBottomWidth: true,
borderLeftWidth: true
},
objectPosition: {
objectPositionX: true,
objectPositionY: true
},
transformOrigin: {
transformOriginX: true,
transformOriginY: true
}
}; // Expand the shorthand properties to isolate every declaration from the others.
var expandStyles = function expandStyles(style) {
if (!style) return style;
var propsArray = Object.keys(style);
var resolvedStyle = {};
for (var i = 0; i < propsArray.length; i++) {
var key = propsArray[i];
var value = style[key];
switch (key) {
case 'display':
case 'flex':
case 'flexDirection':
case 'flexWrap':
case 'flexFlow':
case 'flexGrow':
case 'flexShrink':
case 'flexBasis':
case 'justifyContent':
case 'alignSelf':
case 'alignItems':
case 'alignContent':
case 'order':
resolvedStyle[key] = yogaValue(key, value);
break;
case 'textAlignVertical':
resolvedStyle.verticalAlign = value === 'center' ? 'middle' : value;
break;
case 'margin':
case 'marginHorizontal':
case 'marginVertical':
case 'padding':
case 'paddingHorizontal':
case 'paddingVertical':
case 'border':
case 'borderTop':
case 'borderRight':
case 'borderBottom':
case 'borderLeft':
case 'borderColor':
case 'borderRadius':
case 'borderStyle':
case 'borderWidth':
case 'objectPosition':
case 'transformOrigin':
{
var expandedProps = styleShorthands[key];
for (var propName in expandedProps) {
if (hasOwnProperty.call(expandedProps, propName)) {
resolvedStyle[propName] = value;
}
}
}
break;
default:
resolvedStyle[key] = value;
break;
}
}
return resolvedStyle;
};
var transformStyles = function transformStyles(style, container) {
var expandedStyles = expandStyles(style);
var propsArray = Object.keys(expandedStyles);
var resolvedStyle = {};
for (var i = 0; i < propsArray.length; i++) {
var key = propsArray[i];
var value = expandedStyles[key];
var resolved = void 0;
if (isBorderStyle(key, value)) {
resolved = processBorders(key, value);
} else if (isBoxModelStyle(key, value)) {
resolved = processBoxModel(key, value);
} else if (isObjectPositionStyle(key, value)) {
resolved = processObjectPosition(key, value);
} else if (isTransformOriginStyle(key, value)) {
resolved = processTransformOrigin(key, value);
} else if (isFontWeightStyle(key)) {
resolved = processFontWeight(value);
} else {
resolved = value;
}
resolvedStyle[key] = parseScalar(resolved, container);
}
return resolvedStyle;
};
var create = function create(styles) {
return styles;
};
var flatten = function flatten(input) {
if (!Array.isArray(input)) {
input = [input];
}
var result = input.reduce(function (acc, style) {
if (style) {
var s = Array.isArray(style) ? flatten(style) : style;
Object.keys(s).forEach(function (key) {
if (s[key] !== null && s[key] !== undefined) {
acc[key] = s[key];
}
});
}
return acc;
}, {});
return result;
};
var resolveMediaQueries = function resolveMediaQueries(input, container) {
var result = Object.keys(input).reduce(function (acc, key) {
var _extends2;
if (/@media/.test(key)) {
var _matchMedia;
return _extends({}, acc, {}, matchMedia((_matchMedia = {}, _matchMedia[key] = input[key], _matchMedia), container));
}
return _extends({}, acc, (_extends2 = {}, _extends2[key] = input[key], _extends2));
}, {});
return result;
};
var resolve = function resolve(styles, container) {
if (!styles) return null;
styles = flatten(styles);
styles = resolveMediaQueries(styles, container);
styles = transformStyles(styles, container);
return styles;
};
var absoluteFillObject = {
position: 'absolute',
top: 0,
left: 0,
bottom: 0,
right: 0
};
var StyleSheet = {
hairlineWidth: 1,
create: create,
resolve: resolve,
flatten: flatten,
absoluteFillObject: absoluteFillObject
};
var Debug = {
debug: function debug() {
var layout = this.getAbsoluteLayout();
var padding = this.padding;
var margin = this.margin;
this.root.instance.save();
this.debugContent(layout, margin, padding);
this.debugPadding(layout, margin, padding);
this.debugMargin(layout, margin);
this.debugText(layout, margin);
this.debugOrigin();
this.root.instance.restore();
},
debugOrigin: function debugOrigin() {
if (this.style.transform) {
var origin = this.origin;
this.root.instance.circle(origin[0], origin[1], 3).fill('red').circle(origin[0], origin[1], 5).stroke('red');
}
},
debugText: function debugText(layout, margin) {
var roundedWidth = Math.round(this.width + margin.left + margin.right);
var roundedHeight = Math.round(this.height + margin.top + margin.bottom);
this.root.instance.fontSize(4).opacity(1).fillColor('black').text(roundedWidth + " x " + roundedHeight, layout.left - margin.left, Math.max(layout.top - margin.top - 4, 1));
},
debugContent: function debugContent(layout, margin, padding) {
this.root.instance.fillColor('#a1c6e7').opacity(0.5).rect(layout.left + padding.left, layout.top + padding.top, layout.width - padding.left - padding.right, layout.height - padding.top - padding.bottom).fill();
},
debugPadding: function debugPadding(layout, margin, padding) {
this.root.instance.fillColor('#c4deb9').opacity(0.5); // Padding top
this.root.instance.rect(layout.left + padding.left, layout.top, layout.width - padding.right - padding.left, padding.top).fill(); // Padding left
this.root.instance.rect(layout.left, layout.top, padding.left, layout.height).fill(); // Padding right
this.root.instance.rect(layout.left + layout.width - padding.right, layout.top, padding.right, layout.height).fill(); // Padding bottom
this.root.instance.rect(layout.left + padding.left, layout.top + layout.height - padding.bottom, layout.width - padding.right - padding.left, padding.bottom).fill();
},
debugMargin: function debugMargin(layout, margin) {
this.root.instance.fillColor('#f8cca1').opacity(0.5); // Margin top
this.root.instance.rect(layout.left, layout.top - margin.top, layout.width, margin.top).fill(); // Margin left
this.root.instance.rect(layout.left - margin.left, layout.top - margin.top, margin.left, layout.height + margin.top + margin.bottom).fill(); // Margin right
this.root.instance.rect(layout.left + layout.width, layout.top - margin.top, margin.right, layout.height + margin.top + margin.bottom).fill(); // Margin bottom
this.root.instance.rect(layout.left, layout.top + layout.height, layout.width, margin.bottom).fill();
}
};
// Ref: https://www.w3.org/TR/css-backgrounds-3/#borders
// This constant is used to approximate a symmetrical arc using a cubic Bezier curve.
var KAPPA = 4.0 * ((Math.sqrt(2) - 1.0) / 3.0);
function drawBorders() {
var instance = this.root.instance;
var layout = this.getAbsoluteLayout();
var borderTopWidth = this.borderTopWidth,
borderLeftWidth = this.borderLeftWidth,
borderRightWidth = this.borderRightWidth,
borderBottomWidth = this.borderBottomWidth;
var _this$style = this.style,
opacity = _this$style.opacity,
_this$style$borderTop = _this$style.borderTopLeftRadius,
borderTopLeftRadius = _this$style$borderTop === void 0 ? 0 : _this$style$borderTop,
_this$style$borderTop2 = _this$style.borderTopRightRadius,
borderTopRightRadius = _this$style$borderTop2 === void 0 ? 0 : _this$style$borderTop2,
_this$style$borderBot = _this$style.borderBottomLeftRadius,
borderBottomLeftRadius = _this$style$borderBot === void 0 ? 0 : _this$style$borderBot,
_this$style$borderBot2 = _this$style.borderBottomRightRadius,
borderBottomRightRadius = _this$style$borderBot2 === void 0 ? 0 : _this$style$borderBot2,
_this$style$borderTop3 = _this$style.borderTopColor,
borderTopColor = _this$style$borderTop3 === void 0 ? 'black' : _this$style$borderTop3,
_this$style$borderTop4 = _this$style.borderTopStyle,
borderTopStyle = _this$style$borderTop4 === void 0 ? 'solid' : _this$style$borderTop4,
_this$style$borderLef = _this$style.borderLeftColor,
borderLeftColor = _this$style$borderLef === void 0 ? 'black' : _this$style$borderLef,
_this$style$borderLef2 = _this$style.borderLeftStyle,
borderLeftStyle = _this$style$borderLef2 === void 0 ? 'solid' : _this$style$borderLef2,
_this$style$borderRig = _this$style.borderRightColor,
borderRightColor = _this$style$borderRig === void 0 ? 'black' : _this$style$borderRig,
_this$style$borderRig2 = _this$style.borderRightStyle,
borderRightStyle = _this$style$borderRig2 === void 0 ? 'solid' : _this$style$borderRig2,
_this$style$borderBot3 = _this$style.borderBottomColor,
borderBottomColor = _this$style$borderBot3 === void 0 ? 'black' : _this$style$borderBot3,
_this$style$borderBot4 = _this$style.borderBottomStyle,
borderBottomStyle = _this$style$borderBot4 === void 0 ? 'solid' : _this$style$borderBot4;
var style = {
borderTopColor: borderTopColor,
borderTopWidth: borderTopWidth,
borderTopStyle: borderTopStyle,
borderLeftColor: borderLeftColor,
borderLeftWidth: borderLeftWidth,
borderLeftStyle: borderLeftStyle,
borderRightColor: borderRightColor,
borderRightWidth: borderRightWidth,
borderRightStyle: borderRightStyle,
borderBottomColor: borderBottomColor,
borderBottomWidth: borderBottomWidth,
borderBottomStyle: borderBottomStyle,
borderTopLeftRadius: borderTopLeftRadius,
borderTopRightRadius: borderTopRightRadius,
borderBottomLeftRadius: borderBottomLeftRadius,
borderBottomRightRadius: borderBottomRightRadius
};
var width = layout.width,
height = layout.height;
var rtr = Math.min(borderTopRightRadius, 0.5 * width, 0.5 * height);
var rtl = Math.min(borderTopLeftRadius, 0.5 * width, 0.5 * height);
var rbr = Math.min(borderBottomRightRadius, 0.5 * width, 0.5 * height);
var rbl = Math.min(borderBottomLeftRadius, 0.5 * width, 0.5 * height);
instance.save();
instance.strokeOpacity(opacity);
if (borderTopWidth) {
instance.save();
clipBorderTop(instance, layout, style, rtr, rtl);
fillBorderTop(instance, layout, style, rtr, rtl);
instance.restore();
}
if (borderRightWidth) {
instance.save();
clipBorderRight(instance, layout, style, rtr, rbr);
fillBorderRight(instance, layout, style, rtr, rbr);
instance.restore();
}
if (borderBottomWidth) {
instance.save();
clipBorderBottom(instance, layout, style, rbl, rbr);
fillBorderBottom(instance, layout, style, rbl, rbr);
instance.restore();
}
if (borderLeftWidth) {
instance.save();
clipBorderLeft(instance, layout, style, rbl, rtl);
fillBorderLeft(instance, layout, style, rbl, rtl);
instance.restore();
}
instance.restore();
}
var clipBorderTop = function clipBorderTop(ctx, layout, style, rtr, rtl) {
var top = layout.top,
left = layout.left,
width = layout.width,
height = layout.height;
var borderTopWidth = style.borderTopWidth,
borderRightWidth = style.borderRightWidth,
borderLeftWidth = style.borderLeftWidth; // Clip outer top border edge
ctx.moveTo(left + rtl, top);
ctx.lineTo(left + width - rtr, top); // Ellipse coefficients outer top right cap
var c0 = rtr * (1.0 - KAPPA); // Clip outer top right cap
ctx.bezierCurveTo(left + width - c0, top, left + width, top + c0, left + width, top + rtr); // Move down in case the margin exceedes the radius
var topRightYCoord = top + Math.max(borderTopWidth, rtr);
ctx.lineTo(left + width, topRightYCoord); // Clip inner top right cap
ctx.lineTo(left + width - borderRightWidth, topRightYCoord); // Ellipse coefficients inner top right cap
var innerTopRightRadiusX = Math.max(rtr - borderRightWidth, 0);
var innerTopRightRadiusY = Math.max(rtr - borderTopWidth, 0);
var c1 = innerTopRightRadiusX * (1.0 - KAPPA);
var c2 = innerTopRightRadiusY * (1.0 - KAPPA); // Clip inner top right cap
ctx.bezierCurveTo(left + width - borderRightWidth, top + borderTopWidth + c2, left + width - borderRightWidth - c1, top + borderTopWidth, left + width - borderRightWidth - innerTopRightRadiusX, top + borderTopWidth); // Clip inner top border edge
ctx.lineTo(left + Math.max(rtl, borderLeftWidth), top + borderTopWidth); // Ellipse coefficients inner top left cap
var innerTopLeftRadiusX = Math.max(rtl - borderLeftWidth, 0);
var innerTopLeftRadiusY = Math.max(rtl - borderTopWidth, 0);
var c3 = innerTopLeftRadiusX * (1.0 - KAPPA);
var c4 = innerTopLeftRadiusY * (1.0 - KAPPA);
var topLeftYCoord = top + Math.max(borderTopWidth, rtl); // Clip inner top left cap
ctx.bezierCurveTo(left + borderLeftWidth + c3, top + borderTopWidth, left + borderLeftWidth, top + borderTopWidth + c4, left + borderLeftWidth, topLeftYCoord);
ctx.lineTo(left, topLeftYCoord); // Move down in case the margin exceedes the radius
ctx.lineTo(left, top + rtl); // Ellipse coefficients outer top left cap
var c5 = rtl * (1.0 - KAPPA); // Clip outer top left cap
ctx.bezierCurveTo(left, top + c5, left + c5, top, left + rtl, top);
ctx.closePath();
ctx.clip(); // Clip border top cap joins
if (borderRightWidth) {
var trSlope = -borderTopWidth / borderRightWidth;
ctx.moveTo(left + width / 2, trSlope * (-width / 2) + top);
ctx.lineTo(left + width, top);
ctx.lineTo(left, top);
ctx.lineTo(left, top + height);
ctx.closePath();
ctx.clip();
}
if (borderLeftWidth) {
var _trSlope = -borderTopWidth / borderLeftWidth;
ctx.moveTo(left + width / 2, _trSlope * (-width / 2) + top);
ctx.lineTo(left, top);
ctx.lineTo(left + width, top);
ctx.lineTo(left + width, top + height);
ctx.closePath();
ctx.clip();
}
};
var fillBorderTop = function fillBorderTop(ctx, layout, style, rtr, rtl) {
var top = layout.top,
left = layout.left,
width = layout.width;
var borderTopColor = style.borderTopColor,
borderTopWidth = style.borderTopWidth,
borderTopStyle = style.borderTopStyle,
borderRightWidth = style.borderRightWidth,
borderLeftWidth = style.borderLeftWidth;
var c0 = rtl * (1.0 - KAPPA);
var c1 = rtr * (1.0 - KAPPA);
ctx.moveTo(left, top + Math.max(rtl, borderTopWidth));
ctx.bezierCurveTo(left, top + c0, left + c0, top, left + rtl, top);
ctx.lineTo(left + width - rtr, top);
ctx.bezierCurveTo(left + width - c1, top, left + width, top + c1, left + width, top + rtr);
ctx.strokeColor(borderTopColor);
ctx.lineWidth(Math.max(borderRightWidth, borderTopWidth, borderLeftWidth) * 2);
if (borderTopStyle === 'dashed') {
ctx.dash(borderTopWidth * 2, {
space: borderTopWidth * 1.2
});
} else if (borderTopStyle === 'dotted') {
ctx.dash(borderTopWidth, {
space: borderTopWidth * 1.2
});
}
ctx.stroke();
ctx.undash();
};
var clipBorderRight = function clipBorderRight(ctx, layout, style, rtr, rbr) {
var top = layout.top,
left = layout.left,
width = layout.width,
height = layout.height;
var borderTopWidth = style.borderTopWidth,
borderRightWidth = style.borderRightWidth,
borderBottomWidth = style.borderBottomWidth; // Clip outer right border edge
ctx.moveTo(left + width, top + rtr);
ctx.lineTo(left + width, top + height - rbr); // Ellipse coefficients outer bottom right cap
var c0 = rbr * (1.0 - KAPPA); // Clip outer top right cap
ctx.bezierCurveTo(left + width, top + height - c0, left + width - c0, top + height, left + width - rbr, top + height); // Move left in case the margin exceedes the radius
var topBottomXCoord = left + width - Math.max(borderRightWidth, rbr);
ctx.lineTo(topBottomXCoord, top + height); // Clip inner bottom right cap
ctx.lineTo(topBottomXCoord, top + height - borderBottomWidth); // Ellipse coefficients inner bottom right cap
var innerBottomRightRadiusX = Math.max(rbr - borderRightWidth, 0);
var innerBottomRightRadiusY = Math.max(rbr - borderBottomWidth, 0);
var c1 = innerBottomRightRadiusX * (1.0 - KAPPA);
var c2 = innerBottomRightRadiusY * (1.0 - KAPPA); // Clip inner top right cap
ctx.bezierCurveTo(left + width - borderRightWidth - c1, top + height - borderBottomWidth, left + width - borderRightWidth, top + height - borderBottomWidth - c2, left + width - borderRightWidth, top + height - Math.max(rbr, borderBottomWidth)); // Clip inner right border edge
ctx.lineTo(left + width - borderRightWidth, top + Math.max(rtr, borderTopWidth)); // Ellipse coefficients inner top right cap
var innerTopRightRadiusX = Math.max(rtr - borderRightWidth, 0);
var innerTopRightRadiusY = Math.max(rtr - borderTopWidth, 0);
var c3 = innerTopRightRadiusX * (1.0 - KAPPA);
var c4 = innerTopRightRadiusY * (1.0 - KAPPA);
var topRightXCoord = left + width - Math.max(rtr, borderRightWidth); // Clip inner top left cap
ctx.bezierCurveTo(left + width - borderRightWidth, top + borderTopWidth + c4, left + width - borderRightWidth - c3, top + borderTopWidth, topRightXCoord, top + borderTopWidth);
ctx.lineTo(topRightXCoord, top); // Move right in case the margin exceedes the radius
ctx.lineTo(left + width - rtr, top); // Ellipse coefficients outer top right cap
var c5 = rtr * (1.0 - KAPPA); // Clip outer top right cap
ctx.bezierCurveTo(left + width - c5, top, left + width, top + c5, left + width, top + rtr);
ctx.closePath();
ctx.clip(); // Clip border right cap joins
if (borderTopWidth) {
var trSlope = -borderTopWidth / borderRightWidth;
ctx.moveTo(left + width / 2, trSlope * (-width / 2) + top);
ctx.lineTo(left + width, top);
ctx.lineTo(left + width, top + height);
ctx.lineTo(left, top + height);
ctx.closePath();
ctx.clip();
}
if (borderBottomWidth) {
var brSlope = borderBottomWidth / borderRightWidth;
ctx.moveTo(left + width / 2, brSlope * (-width / 2) + top + height);
ctx.lineTo(left + width, top + height);
ctx.lineTo(left + width, top);
ctx.lineTo(left, top);
ctx.closePath();
ctx.clip();
}
};
var fillBorderRight = function fillBorderRight(ctx, layout, style, rtr, rbr) {
var top = layout.top,
left = layout.left,
width = layout.width,
height = layout.height;
var borderRightColor = style.borderRightColor,
borderRightStyle = style.borderRightStyle,
borderRightWidth = style.borderRightWidth,
borderTopWidth = style.borderTopWidth,
borderBottomWidth = style.borderBottomWidth;
var c0 = rbr * (1.0 - KAPPA);
var c1 = rtr * (1.0 - KAPPA);
ctx.moveTo(left + width - rtr, top);
ctx.bezierCurveTo(left + width - c1, top, left + width, top + c1, left + width, top + rtr);
ctx.lineTo(left + width, top + height - rbr);
ctx.bezierCurveTo(left + width, top + height - c0, left + width - c0, top + height, left + width - rbr, top + height);
ctx.strokeColor(borderRightColor);
ctx.lineWidth(Math.max(borderRightWidth, borderTopWidth, borderBottomWidth) * 2);
if (borderRightStyle === 'dashed') {
ctx.dash(borderRightWidth * 2, {
space: borderRightWidth * 1.2
});
} else if (borderRightStyle === 'dotted') {
ctx.dash(borderRightWidth, {
space: borderRightWidth * 1.2
});
}
ctx.stroke();
ctx.undash();
};
var clipBorderBottom = function clipBorderBottom(ctx, layout, style, rbl, rbr) {
var top = layout.top,
left = layout.left,
width = layout.width,
height = layout.height;
var borderBottomWidth = style.borderBottomWidth,
borderRightWidth = style.borderRightWidth,
borderLeftWidth = style.borderLeftWidth; // Clip outer top border edge
ctx.moveTo(left + width - rbr, top + height);
ctx.lineTo(left + rbl, top + height); // Ellipse coefficients outer top right cap
var c0 = rbl * (1.0 - KAPPA); // Clip outer top right cap
ctx.bezierCurveTo(left + c0, top + height, left, top + height - c0, left, top + height - rbl); // Move up in case the margin exceedes the radius
var bottomLeftYCoord = top + height - Math.max(borderBottomWidth, rbl);
ctx.lineTo(left, bottomLeftYCoord); // Clip inner bottom left cap
ctx.lineTo(left + borderLeftWidth, bottomLeftYCoord); // Ellipse coefficients inner top right cap
var innerBottomLeftRadiusX = Math.max(rbl - borderLeftWidth, 0);
var innerBottomLeftRadiusY = Math.max(rbl - borderBottomWidth, 0);
var c1 = innerBottomLeftRadiusX * (1.0 - KAPPA);
var c2 = innerBottomLeftRadiusY * (1.0 - KAPPA); // Clip inner bottom left cap
ctx.bezierCurveTo(left + borderLeftWidth, top + height - borderBottomWidth - c2, left + borderLeftWidth + c1, top + height - borderBottomWidth, left + borderLeftWidth + innerBottomLeftRadiusX, top + height - borderBottomWidth); // Clip inner bottom border edge
ctx.lineTo(left + width - Math.max(rbr, borderRightWidth), top + height - borderBottomWidth); // Ellipse coefficients inner top left cap
var innerBottomRightRadiusX = Math.max(rbr - borderRightWidth, 0);
var innerBottomRightRadiusY = Math.max(rbr - borderBottomWidth, 0);
var c3 = innerBottomRightRadiusX * (1.0 - KAPPA);
var c4 = innerBottomRightRadiusY * (1.0 - KAPPA);
var bottomRightYCoord = top + height - Math.max(borderBottomWidth, rbr); // Clip inner top left cap
ctx.bezierCurveTo(left + width - borderRightWidth - c3, top + height - borderBottomWidth, left + width - borderRightWidth, top + height - borderBottomWidth - c4, left + width - borderRightWidth, bottomRightYCoord);
ctx.lineTo(left + width, bottomRightYCoord); // Move down in case the margin exceedes the radius
ctx.lineTo(left + width, top + height - rbr); // Ellipse coefficients outer top left cap
var c5 = rbr * (1.0 - KAPPA); // Clip outer top left cap
ctx.bezierCurveTo(left + width, top + height - c5, left + width - c5, top + height, left + width - rbr, top + height);
ctx.closePath();
ctx.clip(); // Clip border bottom cap joins
if (borderRightWidth) {
var brSlope = borderBottomWidth / borderRightWidth;
ctx.moveTo(left + width / 2, brSlope * (-width / 2) + top + height);
ctx.lineTo(left + width, top + height);
ctx.lineTo(left, top + height);
ctx.lineTo(left, top);
ctx.closePath();
ctx.clip();
}
if (borderLeftWidth) {
var trSlope = -borderBottomWidth / borderLeftWidth;
ctx.moveTo(left + width / 2, trSlope * (width / 2) + top + height);
ctx.lineTo(left, top + height);
ctx.lineTo(left + width, top + height);
ctx.lineTo(left + width, top);
ctx.closePath();
ctx.clip();
}
};
var fillBorderBottom = function fillBorderBottom(ctx, layout, style, rbl, rbr) {
var top = layout.top,
left = layout.left,
width = layout.width,
height = layout.height;
var borderBottomColor = style.borderBottomColor,
borderBottomStyle = style.borderBottomStyle,
borderBottomWidth = style.borderBottomWidth,
borderRightWidth = style.borderRightWidth,
borderLeftWidth = style.borderLeftWidth;
var c0 = rbl * (1.0 - KAPPA);
var c1 = rbr * (1.0 - KAPPA);
ctx.moveTo(left + width, top + height - rbr);
ctx.bezierCurveTo(left + width, top + height - c1, left + width - c1, top + height, left + width - rbr, top + height);
ctx.lineTo(left + rbl, top + height);
ctx.bezierCurveTo(left + c0, top + height, left, top + height - c0, left, top + height - rbl);
ctx.strokeColor(borderBottomColor);
ctx.lineWidth(Math.max(borderBottomWidth, borderRightWidth, borderLeftWidth) * 2);
if (borderBottomStyle === 'dashed') {
ctx.dash(borderBottomWidth * 2, {
space: borderBottomWidth * 1.2
});
} else if (borderBottomStyle === 'dotted') {
ctx.dash(borderBottomWidth, {
space: borderBottomWidth * 1.2
});
}
ctx.stroke();
ctx.undash();
};
var clipBorderLeft = function clipBorderLeft(ctx, layout, style, rbl, rtl) {
var top = layout.top,
left = layout.left,
width = layout.width,
height = layout.height;
var borderTopWidth = style.borderTopWidth,
borderLeftWidth = style.borderLeftWidth,
borderBottomWidth = style.borderBottomWidth; // Clip outer left border edge
ctx.moveTo(left, top + height - rbl);
ctx.lineTo(left, top + rtl); // Ellipse coefficients outer top left cap
var c0 = rtl * (1.0 - KAPPA); // Clip outer top left cap
ctx.bezierCurveTo(left, top + c0, left + c0, top, left + rtl, top); // Move right in case the margin exceedes the radius
var topLeftCoordX = left + Math.max(borderLeftWidth, rtl);
ctx.lineTo(topLeftCoordX, top); // Clip inner top left cap
ctx.lineTo(topLeftCoordX, top + borderTopWidth); // Ellipse coefficients inner top left cap
var innerTopLeftRadiusX = Math.max(rtl - borderLeftWidth, 0);
var innerTopLeftRadiusY = Math.max(rtl - borderTopWidth, 0);
var c1 = innerTopLeftRadiusX * (1.0 - KAPPA);
var c2 = innerTopLeftRadiusY * (1.0 - KAPPA); // Clip inner top right cap
ctx.bezierCurveTo(left + borderLeftWidth + c1, top + borderTopWidth, left + borderLeftWidth, top + borderTopWidth + c2, left + borderLeftWidth, top + Math.max(rtl, borderTopWidth)); // Clip inner left border edge
ctx.lineTo(left + borderLeftWidth, top + height - Math.max(rbl, borderBottomWidth)); // Ellipse coefficients inner bottom left cap
var innerBottomLeftRadiusX = Math.max(rbl - borderLeftWidth, 0);
var innerBottomLeftRadiusY = Math.max(rbl - borderBottomWidth, 0);
var c3 = innerBottomLeftRadiusX * (1.0 - KAPPA);
var c4 = innerBottomLeftRadiusY * (1.0 - KAPPA);
var bottomLeftXCoord = left + Math.max(rbl, borderLeftWidth); // Clip inner top left cap
ctx.bezierCurveTo(left + borderLeftWidth, top + height - borderBottomWidth - c4, left + borderLeftWidth + c3, top + height - borderBottomWidth, bottomLeftXCoord, top + height - borderBottomWidth);
ctx.lineTo(bottomLeftXCoord, top + height); // Move left in case the margin exceedes the radius
ctx.lineTo(left + rbl, top + height); // Ellipse coefficients outer top right cap
var c5 = rbl * (1.0 - KAPPA); // Clip outer top right cap
ctx.bezierCurveTo(left + c5, top + height, left, top + height - c5, left, top + height - rbl);
ctx.closePath();
ctx.clip(); // Clip border right cap joins
if (borderBottomWidth) {
var trSlope = -borderBottomWidth / borderLeftWidth;
ctx.moveTo(left + width / 2, trSlope * (width / 2) + top + height);
ctx.lineTo(left, top + height);
ctx.lineTo(left, top);
ctx.lineTo(left + width, top);
ctx.closePath();
ctx.clip();
}
if (borderBottomWidth) {
var _trSlope2 = -borderTopWidth / borderLeftWidth;
ctx.moveTo(left + width / 2, _trSlope2 * (-width / 2) + top);
ctx.lineTo(left, top);
ctx.lineTo(left, top + height);
ctx.lineTo(left + width, top + height);
ctx.closePath();
ctx.clip();
}
};
var fillBorderLeft = function fillBorderLeft(ctx, layout, style, rbl, rtl) {
var top = layout.top,
left = layout.left,
height = layout.height;
var borderLeftCo