descargar pdf y fotos
This commit is contained in:
+215
@@ -0,0 +1,215 @@
|
||||
import r from 'restructure';
|
||||
import brotli from 'brotli/decompress.js';
|
||||
import TTFFont from './TTFFont';
|
||||
import TTFGlyph, { Point } from './glyph/TTFGlyph';
|
||||
import WOFF2Glyph from './glyph/WOFF2Glyph';
|
||||
import WOFF2Directory from './tables/WOFF2Directory';
|
||||
|
||||
/**
|
||||
* Subclass of TTFFont that represents a TTF/OTF font compressed by WOFF2
|
||||
* See spec here: http://www.w3.org/TR/WOFF2/
|
||||
*/
|
||||
export default class WOFF2Font extends TTFFont {
|
||||
type = 'WOFF2';
|
||||
|
||||
static probe(buffer) {
|
||||
return buffer.toString('ascii', 0, 4) === 'wOF2';
|
||||
}
|
||||
|
||||
_decodeDirectory() {
|
||||
this.directory = WOFF2Directory.decode(this.stream);
|
||||
this._dataPos = this.stream.pos;
|
||||
}
|
||||
|
||||
_decompress() {
|
||||
// decompress data and setup table offsets if we haven't already
|
||||
if (!this._decompressed) {
|
||||
this.stream.pos = this._dataPos;
|
||||
let buffer = this.stream.readBuffer(this.directory.totalCompressedSize);
|
||||
|
||||
let decompressedSize = 0;
|
||||
for (let tag in this.directory.tables) {
|
||||
let entry = this.directory.tables[tag];
|
||||
entry.offset = decompressedSize;
|
||||
decompressedSize += (entry.transformLength != null) ? entry.transformLength : entry.length;
|
||||
}
|
||||
|
||||
let decompressed = brotli(buffer, decompressedSize);
|
||||
if (!decompressed) {
|
||||
throw new Error('Error decoding compressed data in WOFF2');
|
||||
}
|
||||
|
||||
this.stream = new r.DecodeStream(Buffer.from(decompressed));
|
||||
this._decompressed = true;
|
||||
}
|
||||
}
|
||||
|
||||
_decodeTable(table) {
|
||||
this._decompress();
|
||||
return super._decodeTable(table);
|
||||
}
|
||||
|
||||
// Override this method to get a glyph and return our
|
||||
// custom subclass if there is a glyf table.
|
||||
_getBaseGlyph(glyph, characters = []) {
|
||||
if (!this._glyphs[glyph]) {
|
||||
if (this.directory.tables.glyf && this.directory.tables.glyf.transformed) {
|
||||
if (!this._transformedGlyphs) { this._transformGlyfTable(); }
|
||||
return this._glyphs[glyph] = new WOFF2Glyph(glyph, characters, this);
|
||||
|
||||
} else {
|
||||
return super._getBaseGlyph(glyph, characters);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_transformGlyfTable() {
|
||||
this._decompress();
|
||||
this.stream.pos = this.directory.tables.glyf.offset;
|
||||
let table = GlyfTable.decode(this.stream);
|
||||
let glyphs = [];
|
||||
|
||||
for (let index = 0; index < table.numGlyphs; index++) {
|
||||
let glyph = {};
|
||||
let nContours = table.nContours.readInt16BE();
|
||||
glyph.numberOfContours = nContours;
|
||||
|
||||
if (nContours > 0) { // simple glyph
|
||||
let nPoints = [];
|
||||
let totalPoints = 0;
|
||||
|
||||
for (let i = 0; i < nContours; i++) {
|
||||
let r = read255UInt16(table.nPoints);
|
||||
totalPoints += r;
|
||||
nPoints.push(totalPoints);
|
||||
}
|
||||
|
||||
glyph.points = decodeTriplet(table.flags, table.glyphs, totalPoints);
|
||||
for (let i = 0; i < nContours; i++) {
|
||||
glyph.points[nPoints[i] - 1].endContour = true;
|
||||
}
|
||||
|
||||
var instructionSize = read255UInt16(table.glyphs);
|
||||
|
||||
} else if (nContours < 0) { // composite glyph
|
||||
let haveInstructions = TTFGlyph.prototype._decodeComposite.call({ _font: this }, glyph, table.composites);
|
||||
if (haveInstructions) {
|
||||
var instructionSize = read255UInt16(table.glyphs);
|
||||
}
|
||||
}
|
||||
|
||||
glyphs.push(glyph);
|
||||
}
|
||||
|
||||
this._transformedGlyphs = glyphs;
|
||||
}
|
||||
}
|
||||
|
||||
// Special class that accepts a length and returns a sub-stream for that data
|
||||
class Substream {
|
||||
constructor(length) {
|
||||
this.length = length;
|
||||
this._buf = new r.Buffer(length);
|
||||
}
|
||||
|
||||
decode(stream, parent) {
|
||||
return new r.DecodeStream(this._buf.decode(stream, parent));
|
||||
}
|
||||
}
|
||||
|
||||
// This struct represents the entire glyf table
|
||||
let GlyfTable = new r.Struct({
|
||||
version: r.uint32,
|
||||
numGlyphs: r.uint16,
|
||||
indexFormat: r.uint16,
|
||||
nContourStreamSize: r.uint32,
|
||||
nPointsStreamSize: r.uint32,
|
||||
flagStreamSize: r.uint32,
|
||||
glyphStreamSize: r.uint32,
|
||||
compositeStreamSize: r.uint32,
|
||||
bboxStreamSize: r.uint32,
|
||||
instructionStreamSize: r.uint32,
|
||||
nContours: new Substream('nContourStreamSize'),
|
||||
nPoints: new Substream('nPointsStreamSize'),
|
||||
flags: new Substream('flagStreamSize'),
|
||||
glyphs: new Substream('glyphStreamSize'),
|
||||
composites: new Substream('compositeStreamSize'),
|
||||
bboxes: new Substream('bboxStreamSize'),
|
||||
instructions: new Substream('instructionStreamSize')
|
||||
});
|
||||
|
||||
const WORD_CODE = 253;
|
||||
const ONE_MORE_BYTE_CODE2 = 254;
|
||||
const ONE_MORE_BYTE_CODE1 = 255;
|
||||
const LOWEST_U_CODE = 253;
|
||||
|
||||
function read255UInt16(stream) {
|
||||
let code = stream.readUInt8();
|
||||
|
||||
if (code === WORD_CODE) {
|
||||
return stream.readUInt16BE();
|
||||
}
|
||||
|
||||
if (code === ONE_MORE_BYTE_CODE1) {
|
||||
return stream.readUInt8() + LOWEST_U_CODE;
|
||||
}
|
||||
|
||||
if (code === ONE_MORE_BYTE_CODE2) {
|
||||
return stream.readUInt8() + LOWEST_U_CODE * 2;
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
function withSign(flag, baseval) {
|
||||
return flag & 1 ? baseval : -baseval;
|
||||
}
|
||||
|
||||
function decodeTriplet(flags, glyphs, nPoints) {
|
||||
let y;
|
||||
let x = y = 0;
|
||||
let res = [];
|
||||
|
||||
for (let i = 0; i < nPoints; i++) {
|
||||
let dx = 0, dy = 0;
|
||||
let flag = flags.readUInt8();
|
||||
let onCurve = !(flag >> 7);
|
||||
flag &= 0x7f;
|
||||
|
||||
if (flag < 10) {
|
||||
dx = 0;
|
||||
dy = withSign(flag, ((flag & 14) << 7) + glyphs.readUInt8());
|
||||
|
||||
} else if (flag < 20) {
|
||||
dx = withSign(flag, (((flag - 10) & 14) << 7) + glyphs.readUInt8());
|
||||
dy = 0;
|
||||
|
||||
} else if (flag < 84) {
|
||||
var b0 = flag - 20;
|
||||
var b1 = glyphs.readUInt8();
|
||||
dx = withSign(flag, 1 + (b0 & 0x30) + (b1 >> 4));
|
||||
dy = withSign(flag >> 1, 1 + ((b0 & 0x0c) << 2) + (b1 & 0x0f));
|
||||
|
||||
} else if (flag < 120) {
|
||||
var b0 = flag - 84;
|
||||
dx = withSign(flag, 1 + ((b0 / 12) << 8) + glyphs.readUInt8());
|
||||
dy = withSign(flag >> 1, 1 + (((b0 % 12) >> 2) << 8) + glyphs.readUInt8());
|
||||
|
||||
} else if (flag < 124) {
|
||||
var b1 = glyphs.readUInt8();
|
||||
let b2 = glyphs.readUInt8();
|
||||
dx = withSign(flag, (b1 << 4) + (b2 >> 4));
|
||||
dy = withSign(flag >> 1, ((b2 & 0x0f) << 8) + glyphs.readUInt8());
|
||||
|
||||
} else {
|
||||
dx = withSign(flag, glyphs.readUInt16BE());
|
||||
dy = withSign(flag >> 1, glyphs.readUInt16BE());
|
||||
}
|
||||
|
||||
x += dx;
|
||||
y += dy;
|
||||
res.push(new Point(onCurve, false, x, y));
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
Reference in New Issue
Block a user