You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1024 lines
29 KiB
1024 lines
29 KiB
/** |
|
* @licstart The following is the entire license notice for the |
|
* Javascript code in this page |
|
* |
|
* Copyright 2018 Mozilla Foundation |
|
* |
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
* you may not use this file except in compliance with the License. |
|
* You may obtain a copy of the License at |
|
* |
|
* http://www.apache.org/licenses/LICENSE-2.0 |
|
* |
|
* Unless required by applicable law or agreed to in writing, software |
|
* distributed under the License is distributed on an "AS IS" BASIS, |
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
* See the License for the specific language governing permissions and |
|
* limitations under the License. |
|
* |
|
* @licend The above is the entire license notice for the |
|
* Javascript code in this page |
|
*/ |
|
"use strict"; |
|
|
|
Object.defineProperty(exports, "__esModule", { |
|
value: true |
|
}); |
|
exports.FontRendererFactory = void 0; |
|
|
|
var _util = require("../shared/util"); |
|
|
|
var _cff_parser = require("./cff_parser"); |
|
|
|
var _glyphlist = require("./glyphlist"); |
|
|
|
var _encodings = require("./encodings"); |
|
|
|
var _stream = require("./stream"); |
|
|
|
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } |
|
|
|
function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); } |
|
|
|
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } |
|
|
|
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } |
|
|
|
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); } |
|
|
|
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } |
|
|
|
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } |
|
|
|
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } |
|
|
|
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } |
|
|
|
var FontRendererFactory = function FontRendererFactoryClosure() { |
|
function getLong(data, offset) { |
|
return data[offset] << 24 | data[offset + 1] << 16 | data[offset + 2] << 8 | data[offset + 3]; |
|
} |
|
|
|
function getUshort(data, offset) { |
|
return data[offset] << 8 | data[offset + 1]; |
|
} |
|
|
|
function parseCmap(data, start, end) { |
|
var offset = getUshort(data, start + 2) === 1 ? getLong(data, start + 8) : getLong(data, start + 16); |
|
var format = getUshort(data, start + offset); |
|
var ranges, p, i; |
|
|
|
if (format === 4) { |
|
getUshort(data, start + offset + 2); |
|
var segCount = getUshort(data, start + offset + 6) >> 1; |
|
p = start + offset + 14; |
|
ranges = []; |
|
|
|
for (i = 0; i < segCount; i++, p += 2) { |
|
ranges[i] = { |
|
end: getUshort(data, p) |
|
}; |
|
} |
|
|
|
p += 2; |
|
|
|
for (i = 0; i < segCount; i++, p += 2) { |
|
ranges[i].start = getUshort(data, p); |
|
} |
|
|
|
for (i = 0; i < segCount; i++, p += 2) { |
|
ranges[i].idDelta = getUshort(data, p); |
|
} |
|
|
|
for (i = 0; i < segCount; i++, p += 2) { |
|
var idOffset = getUshort(data, p); |
|
|
|
if (idOffset === 0) { |
|
continue; |
|
} |
|
|
|
ranges[i].ids = []; |
|
|
|
for (var j = 0, jj = ranges[i].end - ranges[i].start + 1; j < jj; j++) { |
|
ranges[i].ids[j] = getUshort(data, p + idOffset); |
|
idOffset += 2; |
|
} |
|
} |
|
|
|
return ranges; |
|
} else if (format === 12) { |
|
getLong(data, start + offset + 4); |
|
var groups = getLong(data, start + offset + 12); |
|
p = start + offset + 16; |
|
ranges = []; |
|
|
|
for (i = 0; i < groups; i++) { |
|
ranges.push({ |
|
start: getLong(data, p), |
|
end: getLong(data, p + 4), |
|
idDelta: getLong(data, p + 8) - getLong(data, p) |
|
}); |
|
p += 12; |
|
} |
|
|
|
return ranges; |
|
} |
|
|
|
throw new _util.FormatError("unsupported cmap: ".concat(format)); |
|
} |
|
|
|
function parseCff(data, start, end, seacAnalysisEnabled) { |
|
var properties = {}; |
|
var parser = new _cff_parser.CFFParser(new _stream.Stream(data, start, end - start), properties, seacAnalysisEnabled); |
|
var cff = parser.parse(); |
|
return { |
|
glyphs: cff.charStrings.objects, |
|
subrs: cff.topDict.privateDict && cff.topDict.privateDict.subrsIndex && cff.topDict.privateDict.subrsIndex.objects, |
|
gsubrs: cff.globalSubrIndex && cff.globalSubrIndex.objects, |
|
isCFFCIDFont: cff.isCIDFont, |
|
fdSelect: cff.fdSelect, |
|
fdArray: cff.fdArray |
|
}; |
|
} |
|
|
|
function parseGlyfTable(glyf, loca, isGlyphLocationsLong) { |
|
var itemSize, itemDecode; |
|
|
|
if (isGlyphLocationsLong) { |
|
itemSize = 4; |
|
|
|
itemDecode = function fontItemDecodeLong(data, offset) { |
|
return data[offset] << 24 | data[offset + 1] << 16 | data[offset + 2] << 8 | data[offset + 3]; |
|
}; |
|
} else { |
|
itemSize = 2; |
|
|
|
itemDecode = function fontItemDecode(data, offset) { |
|
return data[offset] << 9 | data[offset + 1] << 1; |
|
}; |
|
} |
|
|
|
var glyphs = []; |
|
var startOffset = itemDecode(loca, 0); |
|
|
|
for (var j = itemSize; j < loca.length; j += itemSize) { |
|
var endOffset = itemDecode(loca, j); |
|
glyphs.push(glyf.subarray(startOffset, endOffset)); |
|
startOffset = endOffset; |
|
} |
|
|
|
return glyphs; |
|
} |
|
|
|
function lookupCmap(ranges, unicode) { |
|
var code = unicode.codePointAt(0), |
|
gid = 0; |
|
var l = 0, |
|
r = ranges.length - 1; |
|
|
|
while (l < r) { |
|
var c = l + r + 1 >> 1; |
|
|
|
if (code < ranges[c].start) { |
|
r = c - 1; |
|
} else { |
|
l = c; |
|
} |
|
} |
|
|
|
if (ranges[l].start <= code && code <= ranges[l].end) { |
|
gid = ranges[l].idDelta + (ranges[l].ids ? ranges[l].ids[code - ranges[l].start] : code) & 0xFFFF; |
|
} |
|
|
|
return { |
|
charCode: code, |
|
glyphId: gid |
|
}; |
|
} |
|
|
|
function compileGlyf(code, cmds, font) { |
|
function moveTo(x, y) { |
|
cmds.push({ |
|
cmd: 'moveTo', |
|
args: [x, y] |
|
}); |
|
} |
|
|
|
function lineTo(x, y) { |
|
cmds.push({ |
|
cmd: 'lineTo', |
|
args: [x, y] |
|
}); |
|
} |
|
|
|
function quadraticCurveTo(xa, ya, x, y) { |
|
cmds.push({ |
|
cmd: 'quadraticCurveTo', |
|
args: [xa, ya, x, y] |
|
}); |
|
} |
|
|
|
var i = 0; |
|
var numberOfContours = (code[i] << 24 | code[i + 1] << 16) >> 16; |
|
var flags; |
|
var x = 0, |
|
y = 0; |
|
i += 10; |
|
|
|
if (numberOfContours < 0) { |
|
do { |
|
flags = code[i] << 8 | code[i + 1]; |
|
var glyphIndex = code[i + 2] << 8 | code[i + 3]; |
|
i += 4; |
|
var arg1, arg2; |
|
|
|
if (flags & 0x01) { |
|
arg1 = (code[i] << 24 | code[i + 1] << 16) >> 16; |
|
arg2 = (code[i + 2] << 24 | code[i + 3] << 16) >> 16; |
|
i += 4; |
|
} else { |
|
arg1 = code[i++]; |
|
arg2 = code[i++]; |
|
} |
|
|
|
if (flags & 0x02) { |
|
x = arg1; |
|
y = arg2; |
|
} else { |
|
x = 0; |
|
y = 0; |
|
} |
|
|
|
var scaleX = 1, |
|
scaleY = 1, |
|
scale01 = 0, |
|
scale10 = 0; |
|
|
|
if (flags & 0x08) { |
|
scaleX = scaleY = (code[i] << 24 | code[i + 1] << 16) / 1073741824; |
|
i += 2; |
|
} else if (flags & 0x40) { |
|
scaleX = (code[i] << 24 | code[i + 1] << 16) / 1073741824; |
|
scaleY = (code[i + 2] << 24 | code[i + 3] << 16) / 1073741824; |
|
i += 4; |
|
} else if (flags & 0x80) { |
|
scaleX = (code[i] << 24 | code[i + 1] << 16) / 1073741824; |
|
scale01 = (code[i + 2] << 24 | code[i + 3] << 16) / 1073741824; |
|
scale10 = (code[i + 4] << 24 | code[i + 5] << 16) / 1073741824; |
|
scaleY = (code[i + 6] << 24 | code[i + 7] << 16) / 1073741824; |
|
i += 8; |
|
} |
|
|
|
var subglyph = font.glyphs[glyphIndex]; |
|
|
|
if (subglyph) { |
|
cmds.push({ |
|
cmd: 'save' |
|
}); |
|
cmds.push({ |
|
cmd: 'transform', |
|
args: [scaleX, scale01, scale10, scaleY, x, y] |
|
}); |
|
compileGlyf(subglyph, cmds, font); |
|
cmds.push({ |
|
cmd: 'restore' |
|
}); |
|
} |
|
} while (flags & 0x20); |
|
} else { |
|
var endPtsOfContours = []; |
|
var j, jj; |
|
|
|
for (j = 0; j < numberOfContours; j++) { |
|
endPtsOfContours.push(code[i] << 8 | code[i + 1]); |
|
i += 2; |
|
} |
|
|
|
var instructionLength = code[i] << 8 | code[i + 1]; |
|
i += 2 + instructionLength; |
|
var numberOfPoints = endPtsOfContours[endPtsOfContours.length - 1] + 1; |
|
var points = []; |
|
|
|
while (points.length < numberOfPoints) { |
|
flags = code[i++]; |
|
var repeat = 1; |
|
|
|
if (flags & 0x08) { |
|
repeat += code[i++]; |
|
} |
|
|
|
while (repeat-- > 0) { |
|
points.push({ |
|
flags: flags |
|
}); |
|
} |
|
} |
|
|
|
for (j = 0; j < numberOfPoints; j++) { |
|
switch (points[j].flags & 0x12) { |
|
case 0x00: |
|
x += (code[i] << 24 | code[i + 1] << 16) >> 16; |
|
i += 2; |
|
break; |
|
|
|
case 0x02: |
|
x -= code[i++]; |
|
break; |
|
|
|
case 0x12: |
|
x += code[i++]; |
|
break; |
|
} |
|
|
|
points[j].x = x; |
|
} |
|
|
|
for (j = 0; j < numberOfPoints; j++) { |
|
switch (points[j].flags & 0x24) { |
|
case 0x00: |
|
y += (code[i] << 24 | code[i + 1] << 16) >> 16; |
|
i += 2; |
|
break; |
|
|
|
case 0x04: |
|
y -= code[i++]; |
|
break; |
|
|
|
case 0x24: |
|
y += code[i++]; |
|
break; |
|
} |
|
|
|
points[j].y = y; |
|
} |
|
|
|
var startPoint = 0; |
|
|
|
for (i = 0; i < numberOfContours; i++) { |
|
var endPoint = endPtsOfContours[i]; |
|
var contour = points.slice(startPoint, endPoint + 1); |
|
|
|
if (contour[0].flags & 1) { |
|
contour.push(contour[0]); |
|
} else if (contour[contour.length - 1].flags & 1) { |
|
contour.unshift(contour[contour.length - 1]); |
|
} else { |
|
var p = { |
|
flags: 1, |
|
x: (contour[0].x + contour[contour.length - 1].x) / 2, |
|
y: (contour[0].y + contour[contour.length - 1].y) / 2 |
|
}; |
|
contour.unshift(p); |
|
contour.push(p); |
|
} |
|
|
|
moveTo(contour[0].x, contour[0].y); |
|
|
|
for (j = 1, jj = contour.length; j < jj; j++) { |
|
if (contour[j].flags & 1) { |
|
lineTo(contour[j].x, contour[j].y); |
|
} else if (contour[j + 1].flags & 1) { |
|
quadraticCurveTo(contour[j].x, contour[j].y, contour[j + 1].x, contour[j + 1].y); |
|
j++; |
|
} else { |
|
quadraticCurveTo(contour[j].x, contour[j].y, (contour[j].x + contour[j + 1].x) / 2, (contour[j].y + contour[j + 1].y) / 2); |
|
} |
|
} |
|
|
|
startPoint = endPoint + 1; |
|
} |
|
} |
|
} |
|
|
|
function compileCharString(code, cmds, font, glyphId) { |
|
var stack = []; |
|
var x = 0, |
|
y = 0; |
|
var stems = 0; |
|
|
|
function moveTo(x, y) { |
|
cmds.push({ |
|
cmd: 'moveTo', |
|
args: [x, y] |
|
}); |
|
} |
|
|
|
function lineTo(x, y) { |
|
cmds.push({ |
|
cmd: 'lineTo', |
|
args: [x, y] |
|
}); |
|
} |
|
|
|
function bezierCurveTo(x1, y1, x2, y2, x, y) { |
|
cmds.push({ |
|
cmd: 'bezierCurveTo', |
|
args: [x1, y1, x2, y2, x, y] |
|
}); |
|
} |
|
|
|
function parse(code) { |
|
var i = 0; |
|
|
|
while (i < code.length) { |
|
var stackClean = false; |
|
var v = code[i++]; |
|
var xa, xb, ya, yb, y1, y2, y3, n, subrCode; |
|
|
|
switch (v) { |
|
case 1: |
|
stems += stack.length >> 1; |
|
stackClean = true; |
|
break; |
|
|
|
case 3: |
|
stems += stack.length >> 1; |
|
stackClean = true; |
|
break; |
|
|
|
case 4: |
|
y += stack.pop(); |
|
moveTo(x, y); |
|
stackClean = true; |
|
break; |
|
|
|
case 5: |
|
while (stack.length > 0) { |
|
x += stack.shift(); |
|
y += stack.shift(); |
|
lineTo(x, y); |
|
} |
|
|
|
break; |
|
|
|
case 6: |
|
while (stack.length > 0) { |
|
x += stack.shift(); |
|
lineTo(x, y); |
|
|
|
if (stack.length === 0) { |
|
break; |
|
} |
|
|
|
y += stack.shift(); |
|
lineTo(x, y); |
|
} |
|
|
|
break; |
|
|
|
case 7: |
|
while (stack.length > 0) { |
|
y += stack.shift(); |
|
lineTo(x, y); |
|
|
|
if (stack.length === 0) { |
|
break; |
|
} |
|
|
|
x += stack.shift(); |
|
lineTo(x, y); |
|
} |
|
|
|
break; |
|
|
|
case 8: |
|
while (stack.length > 0) { |
|
xa = x + stack.shift(); |
|
ya = y + stack.shift(); |
|
xb = xa + stack.shift(); |
|
yb = ya + stack.shift(); |
|
x = xb + stack.shift(); |
|
y = yb + stack.shift(); |
|
bezierCurveTo(xa, ya, xb, yb, x, y); |
|
} |
|
|
|
break; |
|
|
|
case 10: |
|
n = stack.pop(); |
|
subrCode = null; |
|
|
|
if (font.isCFFCIDFont) { |
|
var fdIndex = font.fdSelect.getFDIndex(glyphId); |
|
|
|
if (fdIndex >= 0 && fdIndex < font.fdArray.length) { |
|
var fontDict = font.fdArray[fdIndex], |
|
subrs = void 0; |
|
|
|
if (fontDict.privateDict && fontDict.privateDict.subrsIndex) { |
|
subrs = fontDict.privateDict.subrsIndex.objects; |
|
} |
|
|
|
if (subrs) { |
|
var numSubrs = subrs.length; |
|
n += numSubrs < 1240 ? 107 : numSubrs < 33900 ? 1131 : 32768; |
|
subrCode = subrs[n]; |
|
} |
|
} else { |
|
(0, _util.warn)('Invalid fd index for glyph index.'); |
|
} |
|
} else { |
|
subrCode = font.subrs[n + font.subrsBias]; |
|
} |
|
|
|
if (subrCode) { |
|
parse(subrCode); |
|
} |
|
|
|
break; |
|
|
|
case 11: |
|
return; |
|
|
|
case 12: |
|
v = code[i++]; |
|
|
|
switch (v) { |
|
case 34: |
|
xa = x + stack.shift(); |
|
xb = xa + stack.shift(); |
|
y1 = y + stack.shift(); |
|
x = xb + stack.shift(); |
|
bezierCurveTo(xa, y, xb, y1, x, y1); |
|
xa = x + stack.shift(); |
|
xb = xa + stack.shift(); |
|
x = xb + stack.shift(); |
|
bezierCurveTo(xa, y1, xb, y, x, y); |
|
break; |
|
|
|
case 35: |
|
xa = x + stack.shift(); |
|
ya = y + stack.shift(); |
|
xb = xa + stack.shift(); |
|
yb = ya + stack.shift(); |
|
x = xb + stack.shift(); |
|
y = yb + stack.shift(); |
|
bezierCurveTo(xa, ya, xb, yb, x, y); |
|
xa = x + stack.shift(); |
|
ya = y + stack.shift(); |
|
xb = xa + stack.shift(); |
|
yb = ya + stack.shift(); |
|
x = xb + stack.shift(); |
|
y = yb + stack.shift(); |
|
bezierCurveTo(xa, ya, xb, yb, x, y); |
|
stack.pop(); |
|
break; |
|
|
|
case 36: |
|
xa = x + stack.shift(); |
|
y1 = y + stack.shift(); |
|
xb = xa + stack.shift(); |
|
y2 = y1 + stack.shift(); |
|
x = xb + stack.shift(); |
|
bezierCurveTo(xa, y1, xb, y2, x, y2); |
|
xa = x + stack.shift(); |
|
xb = xa + stack.shift(); |
|
y3 = y2 + stack.shift(); |
|
x = xb + stack.shift(); |
|
bezierCurveTo(xa, y2, xb, y3, x, y); |
|
break; |
|
|
|
case 37: |
|
var x0 = x, |
|
y0 = y; |
|
xa = x + stack.shift(); |
|
ya = y + stack.shift(); |
|
xb = xa + stack.shift(); |
|
yb = ya + stack.shift(); |
|
x = xb + stack.shift(); |
|
y = yb + stack.shift(); |
|
bezierCurveTo(xa, ya, xb, yb, x, y); |
|
xa = x + stack.shift(); |
|
ya = y + stack.shift(); |
|
xb = xa + stack.shift(); |
|
yb = ya + stack.shift(); |
|
x = xb; |
|
y = yb; |
|
|
|
if (Math.abs(x - x0) > Math.abs(y - y0)) { |
|
x += stack.shift(); |
|
} else { |
|
y += stack.shift(); |
|
} |
|
|
|
bezierCurveTo(xa, ya, xb, yb, x, y); |
|
break; |
|
|
|
default: |
|
throw new _util.FormatError("unknown operator: 12 ".concat(v)); |
|
} |
|
|
|
break; |
|
|
|
case 14: |
|
if (stack.length >= 4) { |
|
var achar = stack.pop(); |
|
var bchar = stack.pop(); |
|
y = stack.pop(); |
|
x = stack.pop(); |
|
cmds.push({ |
|
cmd: 'save' |
|
}); |
|
cmds.push({ |
|
cmd: 'translate', |
|
args: [x, y] |
|
}); |
|
var cmap = lookupCmap(font.cmap, String.fromCharCode(font.glyphNameMap[_encodings.StandardEncoding[achar]])); |
|
compileCharString(font.glyphs[cmap.glyphId], cmds, font, cmap.glyphId); |
|
cmds.push({ |
|
cmd: 'restore' |
|
}); |
|
cmap = lookupCmap(font.cmap, String.fromCharCode(font.glyphNameMap[_encodings.StandardEncoding[bchar]])); |
|
compileCharString(font.glyphs[cmap.glyphId], cmds, font, cmap.glyphId); |
|
} |
|
|
|
return; |
|
|
|
case 18: |
|
stems += stack.length >> 1; |
|
stackClean = true; |
|
break; |
|
|
|
case 19: |
|
stems += stack.length >> 1; |
|
i += stems + 7 >> 3; |
|
stackClean = true; |
|
break; |
|
|
|
case 20: |
|
stems += stack.length >> 1; |
|
i += stems + 7 >> 3; |
|
stackClean = true; |
|
break; |
|
|
|
case 21: |
|
y += stack.pop(); |
|
x += stack.pop(); |
|
moveTo(x, y); |
|
stackClean = true; |
|
break; |
|
|
|
case 22: |
|
x += stack.pop(); |
|
moveTo(x, y); |
|
stackClean = true; |
|
break; |
|
|
|
case 23: |
|
stems += stack.length >> 1; |
|
stackClean = true; |
|
break; |
|
|
|
case 24: |
|
while (stack.length > 2) { |
|
xa = x + stack.shift(); |
|
ya = y + stack.shift(); |
|
xb = xa + stack.shift(); |
|
yb = ya + stack.shift(); |
|
x = xb + stack.shift(); |
|
y = yb + stack.shift(); |
|
bezierCurveTo(xa, ya, xb, yb, x, y); |
|
} |
|
|
|
x += stack.shift(); |
|
y += stack.shift(); |
|
lineTo(x, y); |
|
break; |
|
|
|
case 25: |
|
while (stack.length > 6) { |
|
x += stack.shift(); |
|
y += stack.shift(); |
|
lineTo(x, y); |
|
} |
|
|
|
xa = x + stack.shift(); |
|
ya = y + stack.shift(); |
|
xb = xa + stack.shift(); |
|
yb = ya + stack.shift(); |
|
x = xb + stack.shift(); |
|
y = yb + stack.shift(); |
|
bezierCurveTo(xa, ya, xb, yb, x, y); |
|
break; |
|
|
|
case 26: |
|
if (stack.length % 2) { |
|
x += stack.shift(); |
|
} |
|
|
|
while (stack.length > 0) { |
|
xa = x; |
|
ya = y + stack.shift(); |
|
xb = xa + stack.shift(); |
|
yb = ya + stack.shift(); |
|
x = xb; |
|
y = yb + stack.shift(); |
|
bezierCurveTo(xa, ya, xb, yb, x, y); |
|
} |
|
|
|
break; |
|
|
|
case 27: |
|
if (stack.length % 2) { |
|
y += stack.shift(); |
|
} |
|
|
|
while (stack.length > 0) { |
|
xa = x + stack.shift(); |
|
ya = y; |
|
xb = xa + stack.shift(); |
|
yb = ya + stack.shift(); |
|
x = xb + stack.shift(); |
|
y = yb; |
|
bezierCurveTo(xa, ya, xb, yb, x, y); |
|
} |
|
|
|
break; |
|
|
|
case 28: |
|
stack.push((code[i] << 24 | code[i + 1] << 16) >> 16); |
|
i += 2; |
|
break; |
|
|
|
case 29: |
|
n = stack.pop() + font.gsubrsBias; |
|
subrCode = font.gsubrs[n]; |
|
|
|
if (subrCode) { |
|
parse(subrCode); |
|
} |
|
|
|
break; |
|
|
|
case 30: |
|
while (stack.length > 0) { |
|
xa = x; |
|
ya = y + stack.shift(); |
|
xb = xa + stack.shift(); |
|
yb = ya + stack.shift(); |
|
x = xb + stack.shift(); |
|
y = yb + (stack.length === 1 ? stack.shift() : 0); |
|
bezierCurveTo(xa, ya, xb, yb, x, y); |
|
|
|
if (stack.length === 0) { |
|
break; |
|
} |
|
|
|
xa = x + stack.shift(); |
|
ya = y; |
|
xb = xa + stack.shift(); |
|
yb = ya + stack.shift(); |
|
y = yb + stack.shift(); |
|
x = xb + (stack.length === 1 ? stack.shift() : 0); |
|
bezierCurveTo(xa, ya, xb, yb, x, y); |
|
} |
|
|
|
break; |
|
|
|
case 31: |
|
while (stack.length > 0) { |
|
xa = x + stack.shift(); |
|
ya = y; |
|
xb = xa + stack.shift(); |
|
yb = ya + stack.shift(); |
|
y = yb + stack.shift(); |
|
x = xb + (stack.length === 1 ? stack.shift() : 0); |
|
bezierCurveTo(xa, ya, xb, yb, x, y); |
|
|
|
if (stack.length === 0) { |
|
break; |
|
} |
|
|
|
xa = x; |
|
ya = y + stack.shift(); |
|
xb = xa + stack.shift(); |
|
yb = ya + stack.shift(); |
|
x = xb + stack.shift(); |
|
y = yb + (stack.length === 1 ? stack.shift() : 0); |
|
bezierCurveTo(xa, ya, xb, yb, x, y); |
|
} |
|
|
|
break; |
|
|
|
default: |
|
if (v < 32) { |
|
throw new _util.FormatError("unknown operator: ".concat(v)); |
|
} |
|
|
|
if (v < 247) { |
|
stack.push(v - 139); |
|
} else if (v < 251) { |
|
stack.push((v - 247) * 256 + code[i++] + 108); |
|
} else if (v < 255) { |
|
stack.push(-(v - 251) * 256 - code[i++] - 108); |
|
} else { |
|
stack.push((code[i] << 24 | code[i + 1] << 16 | code[i + 2] << 8 | code[i + 3]) / 65536); |
|
i += 4; |
|
} |
|
|
|
break; |
|
} |
|
|
|
if (stackClean) { |
|
stack.length = 0; |
|
} |
|
} |
|
} |
|
|
|
parse(code); |
|
} |
|
|
|
var NOOP = []; |
|
|
|
var CompiledFont = |
|
/*#__PURE__*/ |
|
function () { |
|
function CompiledFont(fontMatrix) { |
|
_classCallCheck(this, CompiledFont); |
|
|
|
if (this.constructor === CompiledFont) { |
|
(0, _util.unreachable)('Cannot initialize CompiledFont.'); |
|
} |
|
|
|
this.fontMatrix = fontMatrix; |
|
this.compiledGlyphs = Object.create(null); |
|
this.compiledCharCodeToGlyphId = Object.create(null); |
|
} |
|
|
|
_createClass(CompiledFont, [{ |
|
key: "getPathJs", |
|
value: function getPathJs(unicode) { |
|
var cmap = lookupCmap(this.cmap, unicode); |
|
var fn = this.compiledGlyphs[cmap.glyphId]; |
|
|
|
if (!fn) { |
|
fn = this.compileGlyph(this.glyphs[cmap.glyphId], cmap.glyphId); |
|
this.compiledGlyphs[cmap.glyphId] = fn; |
|
} |
|
|
|
if (this.compiledCharCodeToGlyphId[cmap.charCode] === undefined) { |
|
this.compiledCharCodeToGlyphId[cmap.charCode] = cmap.glyphId; |
|
} |
|
|
|
return fn; |
|
} |
|
}, { |
|
key: "compileGlyph", |
|
value: function compileGlyph(code, glyphId) { |
|
if (!code || code.length === 0 || code[0] === 14) { |
|
return NOOP; |
|
} |
|
|
|
var fontMatrix = this.fontMatrix; |
|
|
|
if (this.isCFFCIDFont) { |
|
var fdIndex = this.fdSelect.getFDIndex(glyphId); |
|
|
|
if (fdIndex >= 0 && fdIndex < this.fdArray.length) { |
|
var fontDict = this.fdArray[fdIndex]; |
|
fontMatrix = fontDict.getByName('FontMatrix') || _util.FONT_IDENTITY_MATRIX; |
|
} else { |
|
(0, _util.warn)('Invalid fd index for glyph index.'); |
|
} |
|
} |
|
|
|
var cmds = []; |
|
cmds.push({ |
|
cmd: 'save' |
|
}); |
|
cmds.push({ |
|
cmd: 'transform', |
|
args: fontMatrix.slice() |
|
}); |
|
cmds.push({ |
|
cmd: 'scale', |
|
args: ['size', '-size'] |
|
}); |
|
this.compileGlyphImpl(code, cmds, glyphId); |
|
cmds.push({ |
|
cmd: 'restore' |
|
}); |
|
return cmds; |
|
} |
|
}, { |
|
key: "compileGlyphImpl", |
|
value: function compileGlyphImpl() { |
|
(0, _util.unreachable)('Children classes should implement this.'); |
|
} |
|
}, { |
|
key: "hasBuiltPath", |
|
value: function hasBuiltPath(unicode) { |
|
var cmap = lookupCmap(this.cmap, unicode); |
|
return this.compiledGlyphs[cmap.glyphId] !== undefined && this.compiledCharCodeToGlyphId[cmap.charCode] !== undefined; |
|
} |
|
}]); |
|
|
|
return CompiledFont; |
|
}(); |
|
|
|
var TrueTypeCompiled = |
|
/*#__PURE__*/ |
|
function (_CompiledFont) { |
|
_inherits(TrueTypeCompiled, _CompiledFont); |
|
|
|
function TrueTypeCompiled(glyphs, cmap, fontMatrix) { |
|
var _this; |
|
|
|
_classCallCheck(this, TrueTypeCompiled); |
|
|
|
_this = _possibleConstructorReturn(this, _getPrototypeOf(TrueTypeCompiled).call(this, fontMatrix || [0.000488, 0, 0, 0.000488, 0, 0])); |
|
_this.glyphs = glyphs; |
|
_this.cmap = cmap; |
|
return _this; |
|
} |
|
|
|
_createClass(TrueTypeCompiled, [{ |
|
key: "compileGlyphImpl", |
|
value: function compileGlyphImpl(code, cmds) { |
|
compileGlyf(code, cmds, this); |
|
} |
|
}]); |
|
|
|
return TrueTypeCompiled; |
|
}(CompiledFont); |
|
|
|
var Type2Compiled = |
|
/*#__PURE__*/ |
|
function (_CompiledFont2) { |
|
_inherits(Type2Compiled, _CompiledFont2); |
|
|
|
function Type2Compiled(cffInfo, cmap, fontMatrix, glyphNameMap) { |
|
var _this2; |
|
|
|
_classCallCheck(this, Type2Compiled); |
|
|
|
_this2 = _possibleConstructorReturn(this, _getPrototypeOf(Type2Compiled).call(this, fontMatrix || [0.001, 0, 0, 0.001, 0, 0])); |
|
_this2.glyphs = cffInfo.glyphs; |
|
_this2.gsubrs = cffInfo.gsubrs || []; |
|
_this2.subrs = cffInfo.subrs || []; |
|
_this2.cmap = cmap; |
|
_this2.glyphNameMap = glyphNameMap || (0, _glyphlist.getGlyphsUnicode)(); |
|
_this2.gsubrsBias = _this2.gsubrs.length < 1240 ? 107 : _this2.gsubrs.length < 33900 ? 1131 : 32768; |
|
_this2.subrsBias = _this2.subrs.length < 1240 ? 107 : _this2.subrs.length < 33900 ? 1131 : 32768; |
|
_this2.isCFFCIDFont = cffInfo.isCFFCIDFont; |
|
_this2.fdSelect = cffInfo.fdSelect; |
|
_this2.fdArray = cffInfo.fdArray; |
|
return _this2; |
|
} |
|
|
|
_createClass(Type2Compiled, [{ |
|
key: "compileGlyphImpl", |
|
value: function compileGlyphImpl(code, cmds, glyphId) { |
|
compileCharString(code, cmds, this, glyphId); |
|
} |
|
}]); |
|
|
|
return Type2Compiled; |
|
}(CompiledFont); |
|
|
|
return { |
|
create: function FontRendererFactory_create(font, seacAnalysisEnabled) { |
|
var data = new Uint8Array(font.data); |
|
var cmap, glyf, loca, cff, indexToLocFormat, unitsPerEm; |
|
var numTables = getUshort(data, 4); |
|
|
|
for (var i = 0, p = 12; i < numTables; i++, p += 16) { |
|
var tag = (0, _util.bytesToString)(data.subarray(p, p + 4)); |
|
var offset = getLong(data, p + 8); |
|
var length = getLong(data, p + 12); |
|
|
|
switch (tag) { |
|
case 'cmap': |
|
cmap = parseCmap(data, offset, offset + length); |
|
break; |
|
|
|
case 'glyf': |
|
glyf = data.subarray(offset, offset + length); |
|
break; |
|
|
|
case 'loca': |
|
loca = data.subarray(offset, offset + length); |
|
break; |
|
|
|
case 'head': |
|
unitsPerEm = getUshort(data, offset + 18); |
|
indexToLocFormat = getUshort(data, offset + 50); |
|
break; |
|
|
|
case 'CFF ': |
|
cff = parseCff(data, offset, offset + length, seacAnalysisEnabled); |
|
break; |
|
} |
|
} |
|
|
|
if (glyf) { |
|
var fontMatrix = !unitsPerEm ? font.fontMatrix : [1 / unitsPerEm, 0, 0, 1 / unitsPerEm, 0, 0]; |
|
return new TrueTypeCompiled(parseGlyfTable(glyf, loca, indexToLocFormat), cmap, fontMatrix); |
|
} |
|
|
|
return new Type2Compiled(cff, cmap, font.fontMatrix, font.glyphNameMap); |
|
} |
|
}; |
|
}(); |
|
|
|
exports.FontRendererFactory = FontRendererFactory; |