@ -481,7 +481,7 @@ var ProblematicCharRanges = new Int32Array([
@@ -481,7 +481,7 @@ var ProblematicCharRanges = new Int32Array([
* /
var Font = ( function FontClosure ( ) {
function Font ( name , file , properties ) {
var charCode , glyphName , unicode ;
var charCode ;
this . name = name ;
this . loadedName = properties . loadedName ;
@ -498,6 +498,7 @@ var Font = (function FontClosure() {
@@ -498,6 +498,7 @@ var Font = (function FontClosure() {
var type = properties . type ;
var subtype = properties . subtype ;
this . type = type ;
this . subtype = subtype ;
this . fallbackName = ( this . isMonospace ? 'monospace' :
( this . isSerifFont ? 'serif' : 'sans-serif' ) ) ;
@ -512,6 +513,7 @@ var Font = (function FontClosure() {
@@ -512,6 +513,7 @@ var Font = (function FontClosure() {
this . descent = properties . descent / PDF _GLYPH _SPACE _UNITS ;
this . fontMatrix = properties . fontMatrix ;
this . bbox = properties . bbox ;
this . defaultEncoding = properties . defaultEncoding ;
this . toUnicode = properties . toUnicode ;
@ -532,88 +534,14 @@ var Font = (function FontClosure() {
@@ -532,88 +534,14 @@ var Font = (function FontClosure() {
this . vmetrics = properties . vmetrics ;
this . defaultVMetrics = properties . defaultVMetrics ;
}
var glyphsUnicodeMap ;
if ( ! file || file . isEmpty ) {
if ( file ) {
// Some bad PDF generators will include empty font files,
// attempting to recover by assuming that no file exists.
warn ( 'Font file is empty in "' + name + '" (' + this . loadedName + ')' ) ;
}
this . missingFile = true ;
// The file data is not specified. Trying to fix the font name
// to be used with the canvas.font.
var fontName = name . replace ( /[,_]/g , '-' ) ;
var stdFontMap = getStdFontMap ( ) , nonStdFontMap = getNonStdFontMap ( ) ;
var isStandardFont = ! ! stdFontMap [ fontName ] ||
! ! ( nonStdFontMap [ fontName ] && stdFontMap [ nonStdFontMap [ fontName ] ] ) ;
fontName = stdFontMap [ fontName ] || nonStdFontMap [ fontName ] || fontName ;
this . bold = ( fontName . search ( /bold/gi ) !== - 1 ) ;
this . italic = ( ( fontName . search ( /oblique/gi ) !== - 1 ) ||
( fontName . search ( /italic/gi ) !== - 1 ) ) ;
// Use 'name' instead of 'fontName' here because the original
// name ArialBlack for example will be replaced by Helvetica.
this . black = ( name . search ( /Black/g ) !== - 1 ) ;
// if at least one width is present, remeasure all chars when exists
this . remeasure = Object . keys ( this . widths ) . length > 0 ;
if ( isStandardFont && type === 'CIDFontType2' &&
properties . cidEncoding . indexOf ( 'Identity-' ) === 0 ) {
var GlyphMapForStandardFonts = getGlyphMapForStandardFonts ( ) ;
// Standard fonts might be embedded as CID font without glyph mapping.
// Building one based on GlyphMapForStandardFonts.
var map = [ ] ;
for ( charCode in GlyphMapForStandardFonts ) {
map [ + charCode ] = GlyphMapForStandardFonts [ charCode ] ;
}
if ( /Arial-?Black/i . test ( name ) ) {
var SupplementalGlyphMapForArialBlack =
getSupplementalGlyphMapForArialBlack ( ) ;
for ( charCode in SupplementalGlyphMapForArialBlack ) {
map [ + charCode ] = SupplementalGlyphMapForArialBlack [ charCode ] ;
}
}
var isIdentityUnicode = this . toUnicode instanceof IdentityToUnicodeMap ;
if ( ! isIdentityUnicode ) {
this . toUnicode . forEach ( function ( charCode , unicodeCharCode ) {
map [ + charCode ] = unicodeCharCode ;
} ) ;
}
this . toFontChar = map ;
this . toUnicode = new ToUnicodeMap ( map ) ;
} else if ( /Symbol/i . test ( fontName ) ) {
this . toFontChar = buildToFontChar ( SymbolSetEncoding , getGlyphsUnicode ( ) ,
properties . differences ) ;
} else if ( /Dingbats/i . test ( fontName ) ) {
if ( /Wingdings/i . test ( name ) ) {
warn ( 'Non-embedded Wingdings font, falling back to ZapfDingbats.' ) ;
}
this . toFontChar = buildToFontChar ( ZapfDingbatsEncoding ,
getDingbatsGlyphsUnicode ( ) ,
properties . differences ) ;
} else if ( isStandardFont ) {
this . toFontChar = buildToFontChar ( properties . defaultEncoding ,
getGlyphsUnicode ( ) ,
properties . differences ) ;
} else {
glyphsUnicodeMap = getGlyphsUnicode ( ) ;
this . toUnicode . forEach ( ( charCode , unicodeCharCode ) => {
if ( ! this . composite ) {
glyphName = ( properties . differences [ charCode ] ||
properties . defaultEncoding [ charCode ] ) ;
unicode = getUnicodeForGlyph ( glyphName , glyphsUnicodeMap ) ;
if ( unicode !== - 1 ) {
unicodeCharCode = unicode ;
}
}
this . toFontChar [ charCode ] = unicodeCharCode ;
} ) ;
}
this . loadedName = fontName . split ( '-' ) [ 0 ] ;
this . loading = false ;
this . fontType = getFontType ( type , subtype ) ;
this . fallbackToSystemFont ( ) ;
return ;
}
@ -649,41 +577,51 @@ var Font = (function FontClosure() {
@@ -649,41 +577,51 @@ var Font = (function FontClosure() {
type = 'OpenType' ;
}
var data ;
switch ( type ) {
case 'MMType1' :
info ( 'MMType1 font (' + name + '), falling back to Type1.' ) ;
/* falls through */
case 'Type1' :
case 'CIDFontType0' :
this . mimetype = 'font/opentype' ;
var cff = ( subtype === 'Type1C' || subtype === 'CIDFontType0C' ) ?
new CFFFont ( file , properties ) : new Type1Font ( name , file , properties ) ;
try {
var data ;
switch ( type ) {
case 'MMType1' :
info ( 'MMType1 font (' + name + '), falling back to Type1.' ) ;
/* falls through */
case 'Type1' :
case 'CIDFontType0' :
this . mimetype = 'font/opentype' ;
var cff = ( subtype === 'Type1C' || subtype === 'CIDFontType0C' ) ?
new CFFFont ( file , properties ) :
new Type1Font ( name , file , properties ) ;
adjustWidths ( properties ) ;
adjustWidths ( properties ) ;
// Wrap the CFF data inside an OTF font file
data = this . convert ( name , cff , properties ) ;
break ;
// Wrap the CFF data inside an OTF font file
data = this . convert ( name , cff , properties ) ;
break ;
case 'OpenType' :
case 'TrueType' :
case 'CIDFontType2' :
this . mimetype = 'font/opentype' ;
case 'OpenType' :
case 'TrueType' :
case 'CIDFontType2' :
this . mimetype = 'font/opentype' ;
// Repair the TrueType file. It is can be damaged in the point of
// view of the sanitizer
data = this . checkAndRepair ( name , file , properties ) ;
if ( this . isOpenType ) {
adjustWidths ( properties ) ;
// Repair the TrueType file. It is can be damaged in the point of
// view of the sanitizer
data = this . checkAndRepair ( name , file , properties ) ;
if ( this . isOpenType ) {
adjustWidths ( properties ) ;
type = 'OpenType' ;
}
break ;
type = 'OpenType' ;
}
break ;
default :
throw new FormatError ( ` Font ${ type } is not supported ` ) ;
default :
throw new FormatError ( ` Font ${ type } is not supported ` ) ;
}
} catch ( e ) {
if ( ! ( e instanceof FormatError ) ) {
throw e ;
}
warn ( e ) ;
this . fallbackToSystemFont ( ) ;
return ;
}
this . data = data ;
@ -812,6 +750,11 @@ var Font = (function FontClosure() {
@@ -812,6 +750,11 @@ var Font = (function FontClosure() {
for ( var originalCharCode in charCodeToGlyphId ) {
originalCharCode |= 0 ;
var glyphId = charCodeToGlyphId [ originalCharCode ] ;
// For missing glyphs don't create the mappings so the glyph isn't
// drawn.
if ( missingGlyphs [ glyphId ] ) {
continue ;
}
var fontCharCode = originalCharCode ;
// First try to map the value to a unicode position if a non identity map
// was created.
@ -830,13 +773,15 @@ var Font = (function FontClosure() {
@@ -830,13 +773,15 @@ var Font = (function FontClosure() {
// font was symbolic and there is only an identity unicode map since the
// characters probably aren't in the correct position (fixes an issue
// with firefox and thuluthfont).
if ( ! missingGlyphs [ glyphId ] &&
( usedFontCharCodes [ fontCharCode ] !== undefined ||
if ( ( usedFontCharCodes [ fontCharCode ] !== undefined ||
isProblematicUnicodeLocation ( fontCharCode ) ||
( isSymbolic && ! hasUnicodeValue ) ) &&
nextAvailableFontCharCode <= PRIVATE _USE _OFFSET _END ) { // Room left.
( isSymbolic && ! hasUnicodeValue ) ) ) {
// Loop to try and find a free spot in the private use area.
do {
if ( nextAvailableFontCharCode > PRIVATE _USE _OFFSET _END ) {
warn ( 'Ran out of space in font private use area.' ) ;
break ;
}
fontCharCode = nextAvailableFontCharCode ++ ;
if ( SKIP _PRIVATE _USE _RANGE _F000 _TO _F01F && fontCharCode === 0xF000 ) {
@ -844,8 +789,7 @@ var Font = (function FontClosure() {
@@ -844,8 +789,7 @@ var Font = (function FontClosure() {
nextAvailableFontCharCode = fontCharCode + 1 ;
}
} while ( usedFontCharCodes [ fontCharCode ] !== undefined &&
nextAvailableFontCharCode <= PRIVATE _USE _OFFSET _END ) ;
} while ( usedFontCharCodes [ fontCharCode ] !== undefined ) ;
}
newMap [ fontCharCode ] = glyphId ;
@ -870,6 +814,11 @@ var Font = (function FontClosure() {
@@ -870,6 +814,11 @@ var Font = (function FontClosure() {
}
codes . push ( { fontCharCode : charCode | 0 , glyphId : glyphs [ charCode ] , } ) ;
}
// Some fonts have zero glyphs and are used only for text selection, but
// there needs to be at least one to build a valid cmap table.
if ( codes . length === 0 ) {
codes . push ( { fontCharCode : 0 , glyphId : 0 , } ) ;
}
codes . sort ( function fontGetRangesSort ( a , b ) {
return a . fontCharCode - b . fontCharCode ;
} ) ;
@ -1248,6 +1197,87 @@ var Font = (function FontClosure() {
@@ -1248,6 +1197,87 @@ var Font = (function FontClosure() {
return data ;
} ,
fallbackToSystemFont : function Font _fallbackToSystemFont ( ) {
this . missingFile = true ;
var charCode , unicode ;
// The file data is not specified. Trying to fix the font name
// to be used with the canvas.font.
var name = this . name ;
var type = this . type ;
var subtype = this . subtype ;
var fontName = name . replace ( /[,_]/g , '-' ) ;
var stdFontMap = getStdFontMap ( ) , nonStdFontMap = getNonStdFontMap ( ) ;
var isStandardFont = ! ! stdFontMap [ fontName ] ||
! ! ( nonStdFontMap [ fontName ] && stdFontMap [ nonStdFontMap [ fontName ] ] ) ;
fontName = stdFontMap [ fontName ] || nonStdFontMap [ fontName ] || fontName ;
this . bold = ( fontName . search ( /bold/gi ) !== - 1 ) ;
this . italic = ( ( fontName . search ( /oblique/gi ) !== - 1 ) ||
( fontName . search ( /italic/gi ) !== - 1 ) ) ;
// Use 'name' instead of 'fontName' here because the original
// name ArialBlack for example will be replaced by Helvetica.
this . black = ( name . search ( /Black/g ) !== - 1 ) ;
// if at least one width is present, remeasure all chars when exists
this . remeasure = Object . keys ( this . widths ) . length > 0 ;
if ( isStandardFont && type === 'CIDFontType2' &&
this . cidEncoding . indexOf ( 'Identity-' ) === 0 ) {
var GlyphMapForStandardFonts = getGlyphMapForStandardFonts ( ) ;
// Standard fonts might be embedded as CID font without glyph mapping.
// Building one based on GlyphMapForStandardFonts.
var map = [ ] ;
for ( charCode in GlyphMapForStandardFonts ) {
map [ + charCode ] = GlyphMapForStandardFonts [ charCode ] ;
}
if ( /Arial-?Black/i . test ( name ) ) {
var SupplementalGlyphMapForArialBlack =
getSupplementalGlyphMapForArialBlack ( ) ;
for ( charCode in SupplementalGlyphMapForArialBlack ) {
map [ + charCode ] = SupplementalGlyphMapForArialBlack [ charCode ] ;
}
}
var isIdentityUnicode = this . toUnicode instanceof IdentityToUnicodeMap ;
if ( ! isIdentityUnicode ) {
this . toUnicode . forEach ( function ( charCode , unicodeCharCode ) {
map [ + charCode ] = unicodeCharCode ;
} ) ;
}
this . toFontChar = map ;
this . toUnicode = new ToUnicodeMap ( map ) ;
} else if ( /Symbol/i . test ( fontName ) ) {
this . toFontChar = buildToFontChar ( SymbolSetEncoding , getGlyphsUnicode ( ) ,
this . differences ) ;
} else if ( /Dingbats/i . test ( fontName ) ) {
if ( /Wingdings/i . test ( name ) ) {
warn ( 'Non-embedded Wingdings font, falling back to ZapfDingbats.' ) ;
}
this . toFontChar = buildToFontChar ( ZapfDingbatsEncoding ,
getDingbatsGlyphsUnicode ( ) ,
this . differences ) ;
} else if ( isStandardFont ) {
this . toFontChar = buildToFontChar ( this . defaultEncoding ,
getGlyphsUnicode ( ) ,
this . differences ) ;
} else {
var glyphsUnicodeMap = getGlyphsUnicode ( ) ;
this . toUnicode . forEach ( ( charCode , unicodeCharCode ) => {
if ( ! this . composite ) {
var glyphName = ( this . differences [ charCode ] ||
this . defaultEncoding [ charCode ] ) ;
unicode = getUnicodeForGlyph ( glyphName , glyphsUnicodeMap ) ;
if ( unicode !== - 1 ) {
unicodeCharCode = unicode ;
}
}
this . toFontChar [ charCode ] = unicodeCharCode ;
} ) ;
}
this . loadedName = fontName . split ( '-' ) [ 0 ] ;
this . loading = false ;
this . fontType = getFontType ( type , subtype ) ;
} ,
checkAndRepair : function Font _checkAndRepair ( name , font , properties ) {
function readTableEntry ( file ) {
var tag = bytesToString ( file . getBytes ( 4 ) ) ;
@ -1641,7 +1671,8 @@ var Font = (function FontClosure() {
@@ -1641,7 +1671,8 @@ var Font = (function FontClosure() {
data [ 50 ] = 0 ;
data [ 51 ] = 1 ;
} else {
warn ( 'Could not fix indexToLocFormat: ' + indexToLocFormat ) ;
throw new FormatError ( 'Could not fix indexToLocFormat: ' +
indexToLocFormat ) ;
}
}
}
@ -1687,9 +1718,6 @@ var Font = (function FontClosure() {
@@ -1687,9 +1718,6 @@ var Font = (function FontClosure() {
var startOffset = itemDecode ( locaData , 0 ) ;
var writeOffset = 0 ;
var missingGlyphData = Object . create ( null ) ;
// Glyph zero should be notdef which isn't drawn. Sometimes this is a
// valid glyph but, then it is duplicated.
missingGlyphData [ 0 ] = true ;
itemEncode ( locaData , 0 , writeOffset ) ;
var i , j ;
// When called with dupFirstEntry the number of glyphs has already been
@ -2382,9 +2410,6 @@ var Font = (function FontClosure() {
@@ -2382,9 +2410,6 @@ var Font = (function FontClosure() {
found = true ;
}
}
if ( ! found ) {
charCodeToGlyphId [ charCode ] = 0 ; // notdef
}
}
} else if ( cmapPlatformId === 0 && cmapEncodingId === 0 ) {
// Default Unicode semantics, use the charcodes as is.