import PDFArray from 'src/core/objects/PDFArray' ; import PDFBool from 'src/core/objects/PDFBool' ; import PDFHexString from 'src/core/objects/PDFHexString' ; import PDFName from 'src/core/objects/PDFName' ; import PDFNull from 'src/core/objects/PDFNull' ; import PDFNumber from 'src/core/objects/PDFNumber' ; import PDFObject from 'src/core/objects/PDFObject' ; import PDFRef from 'src/core/objects/PDFRef' ; import PDFStream from 'src/core/objects/PDFStream' ; import PDFString from 'src/core/objects/PDFString' ; import PDFContext from 'src/core/PDFContext' ; import CharCodes from 'src/core/syntax/CharCodes' ; export type DictMap = Map < PDFName , PDFObject > ; class PDFDict extends PDFObject { static withContext = ( context ) => new PDFDict ( new Map ( ) , context ) ; static fromMapWithContext = ( map , context ) => new PDFDict ( map , context ) ; readonly context : PDFContext ; private readonly dict : DictMap ; protected constructor ( map , context ) { super ( ) ; this . dict = map ; this . context = context ; } keys ( ) { return Array . from ( this . dict . keys ( ) ) ; } values ( ) { return Array . from ( this . dict . values ( ) ) ; } entries ( ) { return Array . from ( this . dict . entries ( ) ) ; } set ( key , value ) { this . dict . set ( key , value ) ; } get ( key , preservePDFNull = false ) { const value = this . dict . get ( key ) ; if ( value === PDFNull && ! preservePDFNull ) return undefined ; return value ; } has ( key ) { const value = this . dict . get ( key ) ; return value !== undefined && value !== PDFNull ; } lookupMaybe ( key , type ) ; lookupMaybe ( key , type ) ; lookupMaybe ( key , type ) ; lookupMaybe ( key , type ) ; lookupMaybe ( key , type ) ; lookupMaybe ( key , type ) ; lookupMaybe ( key , type ) ; lookupMaybe ( key , type ) ; lookupMaybe ( key , type ) ; lookupMaybe ( key , type ) ; lookupMaybe ( ref , type1 , type2 ) ; lookupMaybe ( ref , type1 , type2 ) ; lookupMaybe ( ref , type1 , type2 , type3 ) ; lookupMaybe ( key , ... types ) { const preservePDFNull = types . includes ( PDFNull ) ; const value = this . context . lookupMaybe ( this . get ( key , preservePDFNull ) , ... types ) as any ; if ( value === PDFNull && ! preservePDFNull ) return undefined ; return value ; } lookup ( key ) ; lookup ( key , type ) ; lookup ( key , type ) ; lookup ( key , type ) ; lookup ( key , type ) ; lookup ( key , type ) ; lookup ( key , type ) ; lookup ( key , type ) ; lookup ( key , type ) ; lookup ( key , type ) ; lookup ( key , type ) ; lookup ( ref , type1 , type2 ) ; lookup ( ref , type1 , type2 ) ; lookup ( ref , type1 , type2 , type3 ) ; lookup ( key , ... types ) { const preservePDFNull = types . includes ( PDFNull ) ; const value = this . context . lookup ( this . get ( key , preservePDFNull ) , ... types ) as any ; if ( value === PDFNull && ! preservePDFNull ) return undefined ; return value ; } delete ( key ) { return this . dict . delete ( key ) ; } asMap ( ) { return new Map ( this . dict ) ; } /** Generate a random key that doesn't exist in current key set */ uniqueKey ( tag = '' ) { const existingKeys = this . keys ( ) ; let key = PDFName . of ( this . context . addRandomSuffix ( tag , 10 ) ) ; while ( existingKeys . includes ( key ) ) { key = PDFName . of ( this . context . addRandomSuffix ( tag , 10 ) ) ; } return key ; } clone ( context ? ) { const clone = PDFDict . withContext ( context || this . context ) ; const entries = this . entries ( ) ; for ( let idx = 0 , len = entries . length ; idx < len ; idx ++ ) { const [ key , value ] = entries [ idx ] ; clone . set ( key , value ) ; } return clone ; } toString ( ) { let dictString = '<<\n' ; const entries = this . entries ( ) ; for ( let idx = 0 , len = entries . length ; idx < len ; idx ++ ) { const [ key , value ] = entries [ idx ] ; dictString += key . toString ( ) + ' ' + value . toString ( ) + '\n' ; } dictString += '>>' ; return dictString ; } sizeInBytes ( ) { let size = 5 ; const entries = this . entries ( ) ; for ( let idx = 0 , len = entries . length ; idx < len ; idx ++ ) { const [ key , value ] = entries [ idx ] ; size += key . sizeInBytes ( ) + value . sizeInBytes ( ) + 2 ; } return size ; } copyBytesInto ( buffer , offset ) { const initialOffset = offset ; buffer [ offset ++ ] = CharCodes . LessThan ; buffer [ offset ++ ] = CharCodes . LessThan ; buffer [ offset ++ ] = CharCodes . Newline ; const entries = this . entries ( ) ; for ( let idx = 0 , len = entries . length ; idx < len ; idx ++ ) { const [ key , value ] = entries [ idx ] ; offset += key . copyBytesInto ( buffer , offset ) ; buffer [ offset ++ ] = CharCodes . Space ; offset += value . copyBytesInto ( buffer , offset ) ; buffer [ offset ++ ] = CharCodes . Newline ; } buffer [ offset ++ ] = CharCodes . GreaterThan ; buffer [ offset ++ ] = CharCodes . GreaterThan ; return offset - initialOffset ; } } export default PDFDict ;