@@ -8,6 +8,7 @@ import Font from './font.mjs';
88import Glyph from './glyph.mjs' ;
99import { CmapEncoding , GlyphNames , addGlyphNames } from './encoding.mjs' ;
1010import parse from './parse.mjs' ;
11+ import { encode } from './types.mjs' ;
1112import BoundingBox from './bbox.mjs' ;
1213import Path from './path.mjs' ;
1314import cpal from './tables/cpal.mjs' ;
@@ -38,7 +39,6 @@ import meta from './tables/meta.mjs';
3839import gasp from './tables/gasp.mjs' ;
3940import svg from './tables/svg.mjs' ;
4041import { PaletteManager } from './palettes.mjs' ;
41- import { woff_to_otf } from './woff-to-otf.mjs' ;
4242/**
4343 * The opentype library.
4444 * @namespace opentype
@@ -467,6 +467,87 @@ function loadSync() {
467467 console . error ( 'DEPRECATED! migrate to: opentype.parse(require("fs").readFileSync(url), opt)' ) ;
468468}
469469
470+ /**
471+ * Convert/Uncompress a buffer of a woff font to otf/ttf without parsing
472+ * table contents.
473+ * @param {ArrayBuffer }
474+ * @return {ArrayBuffer }
475+ */
476+ function woff_to_otf ( buffer ) {
477+ if ( buffer . constructor !== ArrayBuffer )
478+ buffer = new Uint8Array ( buffer ) . buffer ;
479+ const data = new DataView ( buffer , 0 )
480+ , out = [ ]
481+ , signature = parse . getTag ( data , 0 )
482+ ;
483+
484+ if ( signature !== 'wOFF' )
485+ throw new Error ( `TYPE ERROR signature must be wOFF but is: "${ signature } "` ) ;
486+
487+ const flavor = parse . getTag ( data , 4 )
488+ , numTables = parse . getUShort ( data , 12 )
489+ , tableEntries = parseWOFFTableEntries ( data , numTables )
490+ , max = [ ]
491+ ;
492+ for ( let n = 0 ; n < 64 ; n ++ ) {
493+ if ( Math . pow ( 2 , n ) > numTables )
494+ break ;
495+ max . splice ( 0 , Infinity , n , 2 ** n ) ;
496+ }
497+ const searchRange = max [ 1 ] * 16
498+ , entrySelector = max [ 0 ]
499+ , rangeShift = numTables * 16 - searchRange
500+ ;
501+
502+ out . push (
503+ ...encode . TAG ( flavor )
504+ , ...encode . USHORT ( numTables )
505+ , ...encode . USHORT ( searchRange )
506+ , ...encode . USHORT ( entrySelector )
507+ , ...encode . USHORT ( rangeShift )
508+ ) ;
509+ let offset = out . length + numTables * 16 ;
510+
511+ for ( let i = 0 ; i < numTables ; i ++ ) {
512+ const tableEntry = tableEntries [ i ] ;
513+ out . push (
514+ ...encode . TAG ( tableEntry . tag )
515+ , ...encode . ULONG ( tableEntry . checksum )
516+ , ...encode . ULONG ( offset )
517+ , ...encode . ULONG ( tableEntry . length )
518+ ) ;
519+ tableEntry . outOffset = offset ;
520+ offset += tableEntry . length ;
521+ if ( ( offset % 4 ) !== 0 )
522+ offset += 4 - ( offset % 4 ) ;
523+ }
524+ const initialData = new Uint8Array ( out . length )
525+ , buffers = [ initialData ]
526+ ;
527+ for ( let i = 0 , l = out . length ; i < l ; i ++ )
528+ initialData [ i ] = out [ i ] ;
529+
530+ for ( let i = 0 ; i < numTables ; i ++ ) {
531+ const tableEntry = tableEntries [ i ]
532+ , table = uncompressTable ( data , tableEntry ) // => {data: view, offset: 0};
533+ , offset = tableEntry . outOffset + tableEntry . length
534+ , padding = ( offset % 4 ) !== 0
535+ ? 4 - ( offset % 4 )
536+ : 0
537+ ;
538+ buffers . push (
539+ new Uint8Array ( table . data . buffer , table . offset , tableEntry . length )
540+ , new Uint8Array ( padding )
541+ ) ;
542+ }
543+ const result = new Uint8Array ( buffers . reduce ( ( accum , buffer ) => accum + buffer . byteLength , 0 ) ) ;
544+ buffers . reduce ( ( offset , buffer ) => {
545+ result . set ( buffer , offset ) ;
546+ return offset + buffer . byteLength ;
547+ } , 0 ) ;
548+ return result . buffer ;
549+ }
550+
470551export {
471552 Font ,
472553 Glyph ,
@@ -476,7 +557,5 @@ export {
476557 parseBuffer as parse ,
477558 load ,
478559 loadSync ,
479- parseWOFFTableEntries ,
480- uncompressTable ,
481560 woff_to_otf
482561} ;
0 commit comments