@peergrade/react-pdf
Version:
Display PDFs in your React app as easily as if they were images.
334 lines (258 loc) • 10.3 kB
JavaScript
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.TextLayerItemInternal = undefined;
var _extends2 = require('babel-runtime/helpers/extends');
var _extends3 = _interopRequireDefault(_extends2);
var _slicedToArray2 = require('babel-runtime/helpers/slicedToArray');
var _slicedToArray3 = _interopRequireDefault(_slicedToArray2);
var _regenerator = require('babel-runtime/regenerator');
var _regenerator2 = _interopRequireDefault(_regenerator);
var _asyncToGenerator2 = require('babel-runtime/helpers/asyncToGenerator');
var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2);
var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of');
var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf);
var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
var _createClass2 = require('babel-runtime/helpers/createClass');
var _createClass3 = _interopRequireDefault(_createClass2);
var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');
var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
var _inherits2 = require('babel-runtime/helpers/inherits');
var _inherits3 = _interopRequireDefault(_inherits2);
var _react = require('react');
var _react2 = _interopRequireDefault(_react);
var _propTypes = require('prop-types');
var _propTypes2 = _interopRequireDefault(_propTypes);
var _PageContext = require('../PageContext');
var _PageContext2 = _interopRequireDefault(_PageContext);
var _propTypes3 = require('../shared/propTypes');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
// Render disproportion above which font will be considered broken and fallback will be used
var BROKEN_FONT_ALARM_THRESHOLD = 0.1;
var TextLayerItemInternal = exports.TextLayerItemInternal = function (_PureComponent) {
(0, _inherits3.default)(TextLayerItemInternal, _PureComponent);
function TextLayerItemInternal() {
var _ref;
var _temp, _this, _ret;
(0, _classCallCheck3.default)(this, TextLayerItemInternal);
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
return _ret = (_temp = (_this = (0, _possibleConstructorReturn3.default)(this, (_ref = TextLayerItemInternal.__proto__ || (0, _getPrototypeOf2.default)(TextLayerItemInternal)).call.apply(_ref, [this].concat(args))), _this), _this.state = {
transform: null
}, _this.getElementWidth = function (element) {
var _this2 = _this,
sideways = _this2.sideways;
return element.getBoundingClientRect()[sideways ? 'height' : 'width'];
}, _temp), (0, _possibleConstructorReturn3.default)(_this, _ret);
}
(0, _createClass3.default)(TextLayerItemInternal, [{
key: 'componentDidMount',
value: function componentDidMount() {
this.alignTextItem();
}
}, {
key: 'getFontData',
value: function () {
var _ref2 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee(fontFamily) {
var page, font;
return _regenerator2.default.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
page = this.props.page;
_context.next = 3;
return page.commonObjs.ensureObj(fontFamily);
case 3:
font = _context.sent;
return _context.abrupt('return', font.data);
case 5:
case 'end':
return _context.stop();
}
}
}, _callee, this);
}));
function getFontData(_x) {
return _ref2.apply(this, arguments);
}
return getFontData;
}()
}, {
key: 'alignTextItem',
value: function () {
var _ref3 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee2() {
var element, _props, fontName, scale, width, targetWidth, fontData, actualWidth, widthDisproportion, repairsNeeded, fallbackFontName, ascent;
return _regenerator2.default.wrap(function _callee2$(_context2) {
while (1) {
switch (_context2.prev = _context2.next) {
case 0:
if (this.item) {
_context2.next = 2;
break;
}
return _context2.abrupt('return');
case 2:
element = this.item;
element.style.transform = '';
_props = this.props, fontName = _props.fontName, scale = _props.scale, width = _props.width;
targetWidth = width * scale;
_context2.next = 8;
return this.getFontData(fontName);
case 8:
fontData = _context2.sent;
actualWidth = this.getElementWidth(element);
widthDisproportion = Math.abs(targetWidth / actualWidth - 1);
repairsNeeded = widthDisproportion > BROKEN_FONT_ALARM_THRESHOLD;
if (repairsNeeded) {
fallbackFontName = fontData ? fontData.fallbackName : 'sans-serif';
element.style.fontFamily = fallbackFontName;
actualWidth = this.getElementWidth(element);
}
ascent = fontData ? fontData.ascent : 1;
this.setState({
transform: 'scaleX(' + targetWidth / actualWidth + ') translateY(' + (1 - ascent) * 100 + '%)'
});
case 15:
case 'end':
return _context2.stop();
}
}
}, _callee2, this);
}));
function alignTextItem() {
return _ref3.apply(this, arguments);
}
return alignTextItem;
}()
}, {
key: 'render',
value: function render() {
var _this3 = this;
var fontSize = this.fontSize,
top = this.top,
left = this.left;
var _props2 = this.props,
fontName = _props2.fontName,
scale = _props2.scale,
text = _props2.str;
var transform = this.state.transform;
return _react2.default.createElement(
'div',
{
style: {
height: '1em',
fontFamily: fontName,
fontSize: fontSize * scale + 'px',
position: 'absolute',
top: top * scale + 'px',
left: left * scale + 'px',
transformOrigin: 'left bottom',
whiteSpace: 'pre',
pointerEvents: 'all',
transform: transform
},
ref: function ref(_ref4) {
_this3.item = _ref4;
}
},
this.props.customTextRenderer ? this.props.customTextRenderer(this.props) : text
);
}
}, {
key: 'unrotatedViewport',
get: function get() {
var _props3 = this.props,
page = _props3.page,
scale = _props3.scale;
return page.getViewport(scale);
}
/**
* It might happen that the page is rotated by default. In such cases, we shouldn't rotate
* text content.
*/
}, {
key: 'rotate',
get: function get() {
var _props4 = this.props,
page = _props4.page,
rotate = _props4.rotate;
return rotate - page.rotate;
}
}, {
key: 'sideways',
get: function get() {
var rotate = this.rotate;
return rotate % 180 !== 0;
}
}, {
key: 'defaultSideways',
get: function get() {
var rotation = this.unrotatedViewport.rotation;
return rotation % 180 !== 0;
}
}, {
key: 'fontSize',
get: function get() {
var transform = this.props.transform;
var defaultSideways = this.defaultSideways;
var _transform = (0, _slicedToArray3.default)(transform, 2),
fontHeightPx = _transform[0],
fontWidthPx = _transform[1];
return defaultSideways ? fontWidthPx : fontHeightPx;
}
}, {
key: 'top',
get: function get() {
var transform = this.props.transform;
var viewport = this.unrotatedViewport,
defaultSideways = this.defaultSideways;
var _transform2 = (0, _slicedToArray3.default)(transform, 6),
/* fontHeightPx */offsetX = _transform2[2],
offsetY = _transform2[3],
x = _transform2[4],
y = _transform2[5];
var _viewport$viewBox = (0, _slicedToArray3.default)(viewport.viewBox, 4),
/* xMin */yMin = _viewport$viewBox[1],
/* xMax */yMax = _viewport$viewBox[3];
return defaultSideways ? x + offsetX + yMin : yMax - (y + offsetY);
}
}, {
key: 'left',
get: function get() {
var transform = this.props.transform;
var viewport = this.unrotatedViewport,
defaultSideways = this.defaultSideways;
var _transform3 = (0, _slicedToArray3.default)(transform, 6),
/* fontHeightPx */ /* fontWidthPx */ /* offsetX */x = _transform3[4],
y = _transform3[5];
var _viewport$viewBox2 = (0, _slicedToArray3.default)(viewport.viewBox, 1),
xMin = _viewport$viewBox2[0];
return defaultSideways ? y - xMin : x - xMin;
}
}]);
return TextLayerItemInternal;
}(_react.PureComponent);
TextLayerItemInternal.propTypes = {
customTextRenderer: _propTypes2.default.func,
fontName: _propTypes2.default.string.isRequired,
itemIndex: _propTypes2.default.number.isRequired, // eslint-disable-line react/no-unused-prop-types
page: _propTypes3.isPage.isRequired,
rotate: _propTypes3.isRotate,
scale: _propTypes2.default.number,
str: _propTypes2.default.string.isRequired,
transform: _propTypes2.default.arrayOf(_propTypes2.default.number).isRequired,
width: _propTypes2.default.number.isRequired
};
var TextLayerItem = function TextLayerItem(props) {
return _react2.default.createElement(
_PageContext2.default.Consumer,
null,
function (context) {
return _react2.default.createElement(TextLayerItemInternal, (0, _extends3.default)({}, context, props));
}
);
};
exports.default = TextLayerItem;