2023-10-27 13:19:54 +02:00
/ * *
* @ licstart The following is the entire license notice for the
* JavaScript code in this page
*
* Copyright 2023 Mozilla Foundation
2013-02-21 14:09:23 +00:00
*
* 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 .
2023-10-27 13:19:54 +02:00
*
* @ licend The above is the entire license notice for the
* JavaScript code in this page
2013-02-21 14:09:23 +00:00
* /
2016-04-04 15:49:28 +02:00
2024-06-18 20:06:52 +02:00
/******/ var _ _webpack _modules _ _ = ( {
/***/ 9306 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var isCallable = _ _webpack _require _ _ ( 4901 ) ;
var tryToString = _ _webpack _require _ _ ( 6823 ) ;
var $TypeError = TypeError ;
// `Assert: IsCallable(argument) is true`
module . exports = function ( argument ) {
if ( isCallable ( argument ) ) return argument ;
throw new $TypeError ( tryToString ( argument ) + ' is not a function' ) ;
} ;
/***/ } ) ,
/***/ 3506 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var isPossiblePrototype = _ _webpack _require _ _ ( 3925 ) ;
var $String = String ;
var $TypeError = TypeError ;
module . exports = function ( argument ) {
if ( isPossiblePrototype ( argument ) ) return argument ;
throw new $TypeError ( "Can't set " + $String ( argument ) + ' as a prototype' ) ;
} ;
/***/ } ) ,
/***/ 7080 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var has = ( _ _webpack _require _ _ ( 4402 ) . has ) ;
// Perform ? RequireInternalSlot(M, [[SetData]])
module . exports = function ( it ) {
has ( it ) ;
return it ;
} ;
/***/ } ) ,
/***/ 679 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var isPrototypeOf = _ _webpack _require _ _ ( 1625 ) ;
var $TypeError = TypeError ;
module . exports = function ( it , Prototype ) {
if ( isPrototypeOf ( Prototype , it ) ) return it ;
throw new $TypeError ( 'Incorrect invocation' ) ;
} ;
/***/ } ) ,
/***/ 8551 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var isObject = _ _webpack _require _ _ ( 34 ) ;
var $String = String ;
var $TypeError = TypeError ;
// `Assert: Type(argument) is Object`
module . exports = function ( argument ) {
if ( isObject ( argument ) ) return argument ;
throw new $TypeError ( $String ( argument ) + ' is not an object' ) ;
} ;
/***/ } ) ,
/***/ 7811 :
/***/ ( ( module ) => {
// eslint-disable-next-line es/no-typed-arrays -- safe
module . exports = typeof ArrayBuffer != 'undefined' && typeof DataView != 'undefined' ;
/***/ } ) ,
/***/ 7394 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var uncurryThisAccessor = _ _webpack _require _ _ ( 6706 ) ;
var classof = _ _webpack _require _ _ ( 4576 ) ;
var $TypeError = TypeError ;
// Includes
// - Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
// - If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
module . exports = uncurryThisAccessor ( ArrayBuffer . prototype , 'byteLength' , 'get' ) || function ( O ) {
if ( classof ( O ) !== 'ArrayBuffer' ) throw new $TypeError ( 'ArrayBuffer expected' ) ;
return O . byteLength ;
} ;
/***/ } ) ,
/***/ 3238 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var uncurryThis = _ _webpack _require _ _ ( 9504 ) ;
var arrayBufferByteLength = _ _webpack _require _ _ ( 7394 ) ;
var slice = uncurryThis ( ArrayBuffer . prototype . slice ) ;
module . exports = function ( O ) {
if ( arrayBufferByteLength ( O ) !== 0 ) return false ;
try {
slice ( O , 0 , 0 ) ;
return false ;
} catch ( error ) {
return true ;
}
} ;
/***/ } ) ,
/***/ 5636 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var global = _ _webpack _require _ _ ( 4475 ) ;
var uncurryThis = _ _webpack _require _ _ ( 9504 ) ;
var uncurryThisAccessor = _ _webpack _require _ _ ( 6706 ) ;
var toIndex = _ _webpack _require _ _ ( 7696 ) ;
var isDetached = _ _webpack _require _ _ ( 3238 ) ;
var arrayBufferByteLength = _ _webpack _require _ _ ( 7394 ) ;
var detachTransferable = _ _webpack _require _ _ ( 4483 ) ;
var PROPER _STRUCTURED _CLONE _TRANSFER = _ _webpack _require _ _ ( 1548 ) ;
var structuredClone = global . structuredClone ;
var ArrayBuffer = global . ArrayBuffer ;
var DataView = global . DataView ;
var TypeError = global . TypeError ;
var min = Math . min ;
var ArrayBufferPrototype = ArrayBuffer . prototype ;
var DataViewPrototype = DataView . prototype ;
var slice = uncurryThis ( ArrayBufferPrototype . slice ) ;
var isResizable = uncurryThisAccessor ( ArrayBufferPrototype , 'resizable' , 'get' ) ;
var maxByteLength = uncurryThisAccessor ( ArrayBufferPrototype , 'maxByteLength' , 'get' ) ;
var getInt8 = uncurryThis ( DataViewPrototype . getInt8 ) ;
var setInt8 = uncurryThis ( DataViewPrototype . setInt8 ) ;
module . exports = ( PROPER _STRUCTURED _CLONE _TRANSFER || detachTransferable ) && function ( arrayBuffer , newLength , preserveResizability ) {
var byteLength = arrayBufferByteLength ( arrayBuffer ) ;
var newByteLength = newLength === undefined ? byteLength : toIndex ( newLength ) ;
var fixedLength = ! isResizable || ! isResizable ( arrayBuffer ) ;
var newBuffer ;
if ( isDetached ( arrayBuffer ) ) throw new TypeError ( 'ArrayBuffer is detached' ) ;
if ( PROPER _STRUCTURED _CLONE _TRANSFER ) {
arrayBuffer = structuredClone ( arrayBuffer , { transfer : [ arrayBuffer ] } ) ;
if ( byteLength === newByteLength && ( preserveResizability || fixedLength ) ) return arrayBuffer ;
}
if ( byteLength >= newByteLength && ( ! preserveResizability || fixedLength ) ) {
newBuffer = slice ( arrayBuffer , 0 , newByteLength ) ;
} else {
var options = preserveResizability && ! fixedLength && maxByteLength ? { maxByteLength : maxByteLength ( arrayBuffer ) } : undefined ;
newBuffer = new ArrayBuffer ( newByteLength , options ) ;
var a = new DataView ( arrayBuffer ) ;
var b = new DataView ( newBuffer ) ;
var copyLength = min ( newByteLength , byteLength ) ;
for ( var i = 0 ; i < copyLength ; i ++ ) setInt8 ( b , i , getInt8 ( a , i ) ) ;
}
if ( ! PROPER _STRUCTURED _CLONE _TRANSFER ) detachTransferable ( arrayBuffer ) ;
return newBuffer ;
} ;
/***/ } ) ,
/***/ 4644 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var NATIVE _ARRAY _BUFFER = _ _webpack _require _ _ ( 7811 ) ;
var DESCRIPTORS = _ _webpack _require _ _ ( 3724 ) ;
var global = _ _webpack _require _ _ ( 4475 ) ;
var isCallable = _ _webpack _require _ _ ( 4901 ) ;
var isObject = _ _webpack _require _ _ ( 34 ) ;
var hasOwn = _ _webpack _require _ _ ( 9297 ) ;
var classof = _ _webpack _require _ _ ( 6955 ) ;
var tryToString = _ _webpack _require _ _ ( 6823 ) ;
var createNonEnumerableProperty = _ _webpack _require _ _ ( 6699 ) ;
var defineBuiltIn = _ _webpack _require _ _ ( 6840 ) ;
var defineBuiltInAccessor = _ _webpack _require _ _ ( 2106 ) ;
var isPrototypeOf = _ _webpack _require _ _ ( 1625 ) ;
var getPrototypeOf = _ _webpack _require _ _ ( 2787 ) ;
var setPrototypeOf = _ _webpack _require _ _ ( 2967 ) ;
var wellKnownSymbol = _ _webpack _require _ _ ( 8227 ) ;
var uid = _ _webpack _require _ _ ( 3392 ) ;
var InternalStateModule = _ _webpack _require _ _ ( 1181 ) ;
var enforceInternalState = InternalStateModule . enforce ;
var getInternalState = InternalStateModule . get ;
var Int8Array = global . Int8Array ;
var Int8ArrayPrototype = Int8Array && Int8Array . prototype ;
var Uint8ClampedArray = global . Uint8ClampedArray ;
var Uint8ClampedArrayPrototype = Uint8ClampedArray && Uint8ClampedArray . prototype ;
var TypedArray = Int8Array && getPrototypeOf ( Int8Array ) ;
var TypedArrayPrototype = Int8ArrayPrototype && getPrototypeOf ( Int8ArrayPrototype ) ;
var ObjectPrototype = Object . prototype ;
var TypeError = global . TypeError ;
var TO _STRING _TAG = wellKnownSymbol ( 'toStringTag' ) ;
var TYPED _ARRAY _TAG = uid ( 'TYPED_ARRAY_TAG' ) ;
var TYPED _ARRAY _CONSTRUCTOR = 'TypedArrayConstructor' ;
// Fixing native typed arrays in Opera Presto crashes the browser, see #595
var NATIVE _ARRAY _BUFFER _VIEWS = NATIVE _ARRAY _BUFFER && ! ! setPrototypeOf && classof ( global . opera ) !== 'Opera' ;
var TYPED _ARRAY _TAG _REQUIRED = false ;
var NAME , Constructor , Prototype ;
var TypedArrayConstructorsList = {
Int8Array : 1 ,
Uint8Array : 1 ,
Uint8ClampedArray : 1 ,
Int16Array : 2 ,
Uint16Array : 2 ,
Int32Array : 4 ,
Uint32Array : 4 ,
Float32Array : 4 ,
Float64Array : 8
} ;
var BigIntArrayConstructorsList = {
BigInt64Array : 8 ,
BigUint64Array : 8
} ;
var isView = function isView ( it ) {
if ( ! isObject ( it ) ) return false ;
var klass = classof ( it ) ;
return klass === 'DataView'
|| hasOwn ( TypedArrayConstructorsList , klass )
|| hasOwn ( BigIntArrayConstructorsList , klass ) ;
} ;
var getTypedArrayConstructor = function ( it ) {
var proto = getPrototypeOf ( it ) ;
if ( ! isObject ( proto ) ) return ;
var state = getInternalState ( proto ) ;
return ( state && hasOwn ( state , TYPED _ARRAY _CONSTRUCTOR ) ) ? state [ TYPED _ARRAY _CONSTRUCTOR ] : getTypedArrayConstructor ( proto ) ;
} ;
var isTypedArray = function ( it ) {
if ( ! isObject ( it ) ) return false ;
var klass = classof ( it ) ;
return hasOwn ( TypedArrayConstructorsList , klass )
|| hasOwn ( BigIntArrayConstructorsList , klass ) ;
} ;
var aTypedArray = function ( it ) {
if ( isTypedArray ( it ) ) return it ;
throw new TypeError ( 'Target is not a typed array' ) ;
} ;
var aTypedArrayConstructor = function ( C ) {
if ( isCallable ( C ) && ( ! setPrototypeOf || isPrototypeOf ( TypedArray , C ) ) ) return C ;
throw new TypeError ( tryToString ( C ) + ' is not a typed array constructor' ) ;
} ;
var exportTypedArrayMethod = function ( KEY , property , forced , options ) {
if ( ! DESCRIPTORS ) return ;
if ( forced ) for ( var ARRAY in TypedArrayConstructorsList ) {
var TypedArrayConstructor = global [ ARRAY ] ;
if ( TypedArrayConstructor && hasOwn ( TypedArrayConstructor . prototype , KEY ) ) try {
delete TypedArrayConstructor . prototype [ KEY ] ;
} catch ( error ) {
// old WebKit bug - some methods are non-configurable
try {
TypedArrayConstructor . prototype [ KEY ] = property ;
} catch ( error2 ) { /* empty */ }
}
}
if ( ! TypedArrayPrototype [ KEY ] || forced ) {
defineBuiltIn ( TypedArrayPrototype , KEY , forced ? property
: NATIVE _ARRAY _BUFFER _VIEWS && Int8ArrayPrototype [ KEY ] || property , options ) ;
}
} ;
var exportTypedArrayStaticMethod = function ( KEY , property , forced ) {
var ARRAY , TypedArrayConstructor ;
if ( ! DESCRIPTORS ) return ;
if ( setPrototypeOf ) {
if ( forced ) for ( ARRAY in TypedArrayConstructorsList ) {
TypedArrayConstructor = global [ ARRAY ] ;
if ( TypedArrayConstructor && hasOwn ( TypedArrayConstructor , KEY ) ) try {
delete TypedArrayConstructor [ KEY ] ;
} catch ( error ) { /* empty */ }
}
if ( ! TypedArray [ KEY ] || forced ) {
// V8 ~ Chrome 49-50 `%TypedArray%` methods are non-writable non-configurable
try {
return defineBuiltIn ( TypedArray , KEY , forced ? property : NATIVE _ARRAY _BUFFER _VIEWS && TypedArray [ KEY ] || property ) ;
} catch ( error ) { /* empty */ }
} else return ;
}
for ( ARRAY in TypedArrayConstructorsList ) {
TypedArrayConstructor = global [ ARRAY ] ;
if ( TypedArrayConstructor && ( ! TypedArrayConstructor [ KEY ] || forced ) ) {
defineBuiltIn ( TypedArrayConstructor , KEY , property ) ;
}
}
} ;
for ( NAME in TypedArrayConstructorsList ) {
Constructor = global [ NAME ] ;
Prototype = Constructor && Constructor . prototype ;
if ( Prototype ) enforceInternalState ( Prototype ) [ TYPED _ARRAY _CONSTRUCTOR ] = Constructor ;
else NATIVE _ARRAY _BUFFER _VIEWS = false ;
}
for ( NAME in BigIntArrayConstructorsList ) {
Constructor = global [ NAME ] ;
Prototype = Constructor && Constructor . prototype ;
if ( Prototype ) enforceInternalState ( Prototype ) [ TYPED _ARRAY _CONSTRUCTOR ] = Constructor ;
}
// WebKit bug - typed arrays constructors prototype is Object.prototype
if ( ! NATIVE _ARRAY _BUFFER _VIEWS || ! isCallable ( TypedArray ) || TypedArray === Function . prototype ) {
// eslint-disable-next-line no-shadow -- safe
TypedArray = function TypedArray ( ) {
throw new TypeError ( 'Incorrect invocation' ) ;
} ;
if ( NATIVE _ARRAY _BUFFER _VIEWS ) for ( NAME in TypedArrayConstructorsList ) {
if ( global [ NAME ] ) setPrototypeOf ( global [ NAME ] , TypedArray ) ;
}
}
if ( ! NATIVE _ARRAY _BUFFER _VIEWS || ! TypedArrayPrototype || TypedArrayPrototype === ObjectPrototype ) {
TypedArrayPrototype = TypedArray . prototype ;
if ( NATIVE _ARRAY _BUFFER _VIEWS ) for ( NAME in TypedArrayConstructorsList ) {
if ( global [ NAME ] ) setPrototypeOf ( global [ NAME ] . prototype , TypedArrayPrototype ) ;
}
}
// WebKit bug - one more object in Uint8ClampedArray prototype chain
if ( NATIVE _ARRAY _BUFFER _VIEWS && getPrototypeOf ( Uint8ClampedArrayPrototype ) !== TypedArrayPrototype ) {
setPrototypeOf ( Uint8ClampedArrayPrototype , TypedArrayPrototype ) ;
}
if ( DESCRIPTORS && ! hasOwn ( TypedArrayPrototype , TO _STRING _TAG ) ) {
TYPED _ARRAY _TAG _REQUIRED = true ;
defineBuiltInAccessor ( TypedArrayPrototype , TO _STRING _TAG , {
configurable : true ,
get : function ( ) {
return isObject ( this ) ? this [ TYPED _ARRAY _TAG ] : undefined ;
}
} ) ;
for ( NAME in TypedArrayConstructorsList ) if ( global [ NAME ] ) {
createNonEnumerableProperty ( global [ NAME ] , TYPED _ARRAY _TAG , NAME ) ;
}
}
module . exports = {
NATIVE _ARRAY _BUFFER _VIEWS : NATIVE _ARRAY _BUFFER _VIEWS ,
TYPED _ARRAY _TAG : TYPED _ARRAY _TAG _REQUIRED && TYPED _ARRAY _TAG ,
aTypedArray : aTypedArray ,
aTypedArrayConstructor : aTypedArrayConstructor ,
exportTypedArrayMethod : exportTypedArrayMethod ,
exportTypedArrayStaticMethod : exportTypedArrayStaticMethod ,
getTypedArrayConstructor : getTypedArrayConstructor ,
isView : isView ,
isTypedArray : isTypedArray ,
TypedArray : TypedArray ,
TypedArrayPrototype : TypedArrayPrototype
} ;
/***/ } ) ,
/***/ 5370 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var lengthOfArrayLike = _ _webpack _require _ _ ( 6198 ) ;
module . exports = function ( Constructor , list , $length ) {
var index = 0 ;
var length = arguments . length > 2 ? $length : lengthOfArrayLike ( list ) ;
var result = new Constructor ( length ) ;
while ( length > index ) result [ index ] = list [ index ++ ] ;
return result ;
} ;
/***/ } ) ,
/***/ 9617 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var toIndexedObject = _ _webpack _require _ _ ( 5397 ) ;
var toAbsoluteIndex = _ _webpack _require _ _ ( 5610 ) ;
var lengthOfArrayLike = _ _webpack _require _ _ ( 6198 ) ;
// `Array.prototype.{ indexOf, includes }` methods implementation
var createMethod = function ( IS _INCLUDES ) {
return function ( $this , el , fromIndex ) {
var O = toIndexedObject ( $this ) ;
var length = lengthOfArrayLike ( O ) ;
if ( length === 0 ) return ! IS _INCLUDES && - 1 ;
var index = toAbsoluteIndex ( fromIndex , length ) ;
var value ;
// Array#includes uses SameValueZero equality algorithm
// eslint-disable-next-line no-self-compare -- NaN check
if ( IS _INCLUDES && el !== el ) while ( length > index ) {
value = O [ index ++ ] ;
// eslint-disable-next-line no-self-compare -- NaN check
if ( value !== value ) return true ;
// Array#indexOf ignores holes, Array#includes - not
} else for ( ; length > index ; index ++ ) {
if ( ( IS _INCLUDES || index in O ) && O [ index ] === el ) return IS _INCLUDES || index || 0 ;
} return ! IS _INCLUDES && - 1 ;
} ;
} ;
module . exports = {
// `Array.prototype.includes` method
// https://tc39.es/ecma262/#sec-array.prototype.includes
includes : createMethod ( true ) ,
// `Array.prototype.indexOf` method
// https://tc39.es/ecma262/#sec-array.prototype.indexof
indexOf : createMethod ( false )
} ;
/***/ } ) ,
/***/ 4527 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var DESCRIPTORS = _ _webpack _require _ _ ( 3724 ) ;
var isArray = _ _webpack _require _ _ ( 4376 ) ;
var $TypeError = TypeError ;
// eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
var getOwnPropertyDescriptor = Object . getOwnPropertyDescriptor ;
// Safari < 13 does not throw an error in this case
var SILENT _ON _NON _WRITABLE _LENGTH _SET = DESCRIPTORS && ! function ( ) {
// makes no sense without proper strict mode support
if ( this !== undefined ) return true ;
try {
// eslint-disable-next-line es/no-object-defineproperty -- safe
Object . defineProperty ( [ ] , 'length' , { writable : false } ) . length = 1 ;
} catch ( error ) {
return error instanceof TypeError ;
}
} ( ) ;
module . exports = SILENT _ON _NON _WRITABLE _LENGTH _SET ? function ( O , length ) {
if ( isArray ( O ) && ! getOwnPropertyDescriptor ( O , 'length' ) . writable ) {
throw new $TypeError ( 'Cannot set read only .length' ) ;
} return O . length = length ;
} : function ( O , length ) {
return O . length = length ;
} ;
/***/ } ) ,
/***/ 7628 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var lengthOfArrayLike = _ _webpack _require _ _ ( 6198 ) ;
// https://tc39.es/proposal-change-array-by-copy/#sec-array.prototype.toReversed
// https://tc39.es/proposal-change-array-by-copy/#sec-%typedarray%.prototype.toReversed
module . exports = function ( O , C ) {
var len = lengthOfArrayLike ( O ) ;
var A = new C ( len ) ;
var k = 0 ;
for ( ; k < len ; k ++ ) A [ k ] = O [ len - k - 1 ] ;
return A ;
} ;
/***/ } ) ,
/***/ 9928 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var lengthOfArrayLike = _ _webpack _require _ _ ( 6198 ) ;
var toIntegerOrInfinity = _ _webpack _require _ _ ( 1291 ) ;
var $RangeError = RangeError ;
// https://tc39.es/proposal-change-array-by-copy/#sec-array.prototype.with
// https://tc39.es/proposal-change-array-by-copy/#sec-%typedarray%.prototype.with
module . exports = function ( O , C , index , value ) {
var len = lengthOfArrayLike ( O ) ;
var relativeIndex = toIntegerOrInfinity ( index ) ;
var actualIndex = relativeIndex < 0 ? len + relativeIndex : relativeIndex ;
if ( actualIndex >= len || actualIndex < 0 ) throw new $RangeError ( 'Incorrect index' ) ;
var A = new C ( len ) ;
var k = 0 ;
for ( ; k < len ; k ++ ) A [ k ] = k === actualIndex ? value : O [ k ] ;
return A ;
} ;
/***/ } ) ,
/***/ 6319 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var anObject = _ _webpack _require _ _ ( 8551 ) ;
var iteratorClose = _ _webpack _require _ _ ( 9539 ) ;
// call something on iterator step with safe closing on error
module . exports = function ( iterator , fn , value , ENTRIES ) {
try {
return ENTRIES ? fn ( anObject ( value ) [ 0 ] , value [ 1 ] ) : fn ( value ) ;
} catch ( error ) {
iteratorClose ( iterator , 'throw' , error ) ;
}
} ;
/***/ } ) ,
/***/ 4576 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var uncurryThis = _ _webpack _require _ _ ( 9504 ) ;
var toString = uncurryThis ( { } . toString ) ;
var stringSlice = uncurryThis ( '' . slice ) ;
module . exports = function ( it ) {
return stringSlice ( toString ( it ) , 8 , - 1 ) ;
} ;
/***/ } ) ,
/***/ 6955 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var TO _STRING _TAG _SUPPORT = _ _webpack _require _ _ ( 2140 ) ;
var isCallable = _ _webpack _require _ _ ( 4901 ) ;
var classofRaw = _ _webpack _require _ _ ( 4576 ) ;
var wellKnownSymbol = _ _webpack _require _ _ ( 8227 ) ;
var TO _STRING _TAG = wellKnownSymbol ( 'toStringTag' ) ;
var $Object = Object ;
// ES3 wrong here
var CORRECT _ARGUMENTS = classofRaw ( function ( ) { return arguments ; } ( ) ) === 'Arguments' ;
// fallback for IE11 Script Access Denied error
var tryGet = function ( it , key ) {
try {
return it [ key ] ;
} catch ( error ) { /* empty */ }
} ;
// getting tag from ES6+ `Object.prototype.toString`
module . exports = TO _STRING _TAG _SUPPORT ? classofRaw : function ( it ) {
var O , tag , result ;
return it === undefined ? 'Undefined' : it === null ? 'Null'
// @@toStringTag case
: typeof ( tag = tryGet ( O = $Object ( it ) , TO _STRING _TAG ) ) == 'string' ? tag
// builtinTag case
: CORRECT _ARGUMENTS ? classofRaw ( O )
// ES3 arguments fallback
: ( result = classofRaw ( O ) ) === 'Object' && isCallable ( O . callee ) ? 'Arguments' : result ;
} ;
/***/ } ) ,
/***/ 7740 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var hasOwn = _ _webpack _require _ _ ( 9297 ) ;
var ownKeys = _ _webpack _require _ _ ( 5031 ) ;
var getOwnPropertyDescriptorModule = _ _webpack _require _ _ ( 7347 ) ;
var definePropertyModule = _ _webpack _require _ _ ( 4913 ) ;
module . exports = function ( target , source , exceptions ) {
var keys = ownKeys ( source ) ;
var defineProperty = definePropertyModule . f ;
var getOwnPropertyDescriptor = getOwnPropertyDescriptorModule . f ;
for ( var i = 0 ; i < keys . length ; i ++ ) {
var key = keys [ i ] ;
if ( ! hasOwn ( target , key ) && ! ( exceptions && hasOwn ( exceptions , key ) ) ) {
defineProperty ( target , key , getOwnPropertyDescriptor ( source , key ) ) ;
}
}
} ;
/***/ } ) ,
/***/ 2211 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var fails = _ _webpack _require _ _ ( 9039 ) ;
module . exports = ! fails ( function ( ) {
function F ( ) { /* empty */ }
F . prototype . constructor = null ;
// eslint-disable-next-line es/no-object-getprototypeof -- required for testing
return Object . getPrototypeOf ( new F ( ) ) !== F . prototype ;
} ) ;
/***/ } ) ,
/***/ 2529 :
/***/ ( ( module ) => {
// `CreateIterResultObject` abstract operation
// https://tc39.es/ecma262/#sec-createiterresultobject
module . exports = function ( value , done ) {
return { value : value , done : done } ;
} ;
/***/ } ) ,
/***/ 6699 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var DESCRIPTORS = _ _webpack _require _ _ ( 3724 ) ;
var definePropertyModule = _ _webpack _require _ _ ( 4913 ) ;
var createPropertyDescriptor = _ _webpack _require _ _ ( 6980 ) ;
module . exports = DESCRIPTORS ? function ( object , key , value ) {
return definePropertyModule . f ( object , key , createPropertyDescriptor ( 1 , value ) ) ;
} : function ( object , key , value ) {
object [ key ] = value ;
return object ;
} ;
/***/ } ) ,
/***/ 6980 :
/***/ ( ( module ) => {
module . exports = function ( bitmap , value ) {
return {
enumerable : ! ( bitmap & 1 ) ,
configurable : ! ( bitmap & 2 ) ,
writable : ! ( bitmap & 4 ) ,
value : value
} ;
} ;
/***/ } ) ,
/***/ 4659 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var DESCRIPTORS = _ _webpack _require _ _ ( 3724 ) ;
var definePropertyModule = _ _webpack _require _ _ ( 4913 ) ;
var createPropertyDescriptor = _ _webpack _require _ _ ( 6980 ) ;
module . exports = function ( object , key , value ) {
if ( DESCRIPTORS ) definePropertyModule . f ( object , key , createPropertyDescriptor ( 0 , value ) ) ;
else object [ key ] = value ;
} ;
/***/ } ) ,
/***/ 2106 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var makeBuiltIn = _ _webpack _require _ _ ( 283 ) ;
var defineProperty = _ _webpack _require _ _ ( 4913 ) ;
module . exports = function ( target , name , descriptor ) {
if ( descriptor . get ) makeBuiltIn ( descriptor . get , name , { getter : true } ) ;
if ( descriptor . set ) makeBuiltIn ( descriptor . set , name , { setter : true } ) ;
return defineProperty . f ( target , name , descriptor ) ;
} ;
/***/ } ) ,
/***/ 6840 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var isCallable = _ _webpack _require _ _ ( 4901 ) ;
var definePropertyModule = _ _webpack _require _ _ ( 4913 ) ;
var makeBuiltIn = _ _webpack _require _ _ ( 283 ) ;
var defineGlobalProperty = _ _webpack _require _ _ ( 9433 ) ;
module . exports = function ( O , key , value , options ) {
if ( ! options ) options = { } ;
var simple = options . enumerable ;
var name = options . name !== undefined ? options . name : key ;
if ( isCallable ( value ) ) makeBuiltIn ( value , name , options ) ;
if ( options . global ) {
if ( simple ) O [ key ] = value ;
else defineGlobalProperty ( key , value ) ;
} else {
try {
if ( ! options . unsafe ) delete O [ key ] ;
else if ( O [ key ] ) simple = true ;
} catch ( error ) { /* empty */ }
if ( simple ) O [ key ] = value ;
else definePropertyModule . f ( O , key , {
value : value ,
enumerable : false ,
configurable : ! options . nonConfigurable ,
writable : ! options . nonWritable
} ) ;
} return O ;
} ;
/***/ } ) ,
/***/ 6279 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var defineBuiltIn = _ _webpack _require _ _ ( 6840 ) ;
module . exports = function ( target , src , options ) {
for ( var key in src ) defineBuiltIn ( target , key , src [ key ] , options ) ;
return target ;
} ;
/***/ } ) ,
/***/ 9433 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var global = _ _webpack _require _ _ ( 4475 ) ;
// eslint-disable-next-line es/no-object-defineproperty -- safe
var defineProperty = Object . defineProperty ;
module . exports = function ( key , value ) {
try {
defineProperty ( global , key , { value : value , configurable : true , writable : true } ) ;
} catch ( error ) {
global [ key ] = value ;
} return value ;
} ;
/***/ } ) ,
/***/ 3724 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var fails = _ _webpack _require _ _ ( 9039 ) ;
// Detect IE8's incomplete defineProperty implementation
module . exports = ! fails ( function ( ) {
// eslint-disable-next-line es/no-object-defineproperty -- required for testing
return Object . defineProperty ( { } , 1 , { get : function ( ) { return 7 ; } } ) [ 1 ] !== 7 ;
} ) ;
/***/ } ) ,
/***/ 4483 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var global = _ _webpack _require _ _ ( 4475 ) ;
var tryNodeRequire = _ _webpack _require _ _ ( 9714 ) ;
var PROPER _STRUCTURED _CLONE _TRANSFER = _ _webpack _require _ _ ( 1548 ) ;
var structuredClone = global . structuredClone ;
var $ArrayBuffer = global . ArrayBuffer ;
var $MessageChannel = global . MessageChannel ;
var detach = false ;
var WorkerThreads , channel , buffer , $detach ;
if ( PROPER _STRUCTURED _CLONE _TRANSFER ) {
detach = function ( transferable ) {
structuredClone ( transferable , { transfer : [ transferable ] } ) ;
} ;
} else if ( $ArrayBuffer ) try {
if ( ! $MessageChannel ) {
WorkerThreads = tryNodeRequire ( 'worker_threads' ) ;
if ( WorkerThreads ) $MessageChannel = WorkerThreads . MessageChannel ;
}
if ( $MessageChannel ) {
channel = new $MessageChannel ( ) ;
buffer = new $ArrayBuffer ( 2 ) ;
$detach = function ( transferable ) {
channel . port1 . postMessage ( null , [ transferable ] ) ;
} ;
if ( buffer . byteLength === 2 ) {
$detach ( buffer ) ;
if ( buffer . byteLength === 0 ) detach = $detach ;
}
}
} catch ( error ) { /* empty */ }
module . exports = detach ;
/***/ } ) ,
/***/ 4055 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var global = _ _webpack _require _ _ ( 4475 ) ;
var isObject = _ _webpack _require _ _ ( 34 ) ;
var document = global . document ;
// typeof document.createElement is 'object' in old IE
var EXISTS = isObject ( document ) && isObject ( document . createElement ) ;
module . exports = function ( it ) {
return EXISTS ? document . createElement ( it ) : { } ;
} ;
/***/ } ) ,
/***/ 6837 :
/***/ ( ( module ) => {
var $TypeError = TypeError ;
var MAX _SAFE _INTEGER = 0x1FFFFFFFFFFFFF ; // 2 ** 53 - 1 == 9007199254740991
module . exports = function ( it ) {
if ( it > MAX _SAFE _INTEGER ) throw $TypeError ( 'Maximum allowed index exceeded' ) ;
return it ;
} ;
/***/ } ) ,
/***/ 5002 :
/***/ ( ( module ) => {
module . exports = {
IndexSizeError : { s : 'INDEX_SIZE_ERR' , c : 1 , m : 1 } ,
DOMStringSizeError : { s : 'DOMSTRING_SIZE_ERR' , c : 2 , m : 0 } ,
HierarchyRequestError : { s : 'HIERARCHY_REQUEST_ERR' , c : 3 , m : 1 } ,
WrongDocumentError : { s : 'WRONG_DOCUMENT_ERR' , c : 4 , m : 1 } ,
InvalidCharacterError : { s : 'INVALID_CHARACTER_ERR' , c : 5 , m : 1 } ,
NoDataAllowedError : { s : 'NO_DATA_ALLOWED_ERR' , c : 6 , m : 0 } ,
NoModificationAllowedError : { s : 'NO_MODIFICATION_ALLOWED_ERR' , c : 7 , m : 1 } ,
NotFoundError : { s : 'NOT_FOUND_ERR' , c : 8 , m : 1 } ,
NotSupportedError : { s : 'NOT_SUPPORTED_ERR' , c : 9 , m : 1 } ,
InUseAttributeError : { s : 'INUSE_ATTRIBUTE_ERR' , c : 10 , m : 1 } ,
InvalidStateError : { s : 'INVALID_STATE_ERR' , c : 11 , m : 1 } ,
SyntaxError : { s : 'SYNTAX_ERR' , c : 12 , m : 1 } ,
InvalidModificationError : { s : 'INVALID_MODIFICATION_ERR' , c : 13 , m : 1 } ,
NamespaceError : { s : 'NAMESPACE_ERR' , c : 14 , m : 1 } ,
InvalidAccessError : { s : 'INVALID_ACCESS_ERR' , c : 15 , m : 1 } ,
ValidationError : { s : 'VALIDATION_ERR' , c : 16 , m : 0 } ,
TypeMismatchError : { s : 'TYPE_MISMATCH_ERR' , c : 17 , m : 1 } ,
SecurityError : { s : 'SECURITY_ERR' , c : 18 , m : 1 } ,
NetworkError : { s : 'NETWORK_ERR' , c : 19 , m : 1 } ,
AbortError : { s : 'ABORT_ERR' , c : 20 , m : 1 } ,
URLMismatchError : { s : 'URL_MISMATCH_ERR' , c : 21 , m : 1 } ,
QuotaExceededError : { s : 'QUOTA_EXCEEDED_ERR' , c : 22 , m : 1 } ,
TimeoutError : { s : 'TIMEOUT_ERR' , c : 23 , m : 1 } ,
InvalidNodeTypeError : { s : 'INVALID_NODE_TYPE_ERR' , c : 24 , m : 1 } ,
DataCloneError : { s : 'DATA_CLONE_ERR' , c : 25 , m : 1 }
} ;
/***/ } ) ,
/***/ 7290 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var IS _DENO = _ _webpack _require _ _ ( 516 ) ;
var IS _NODE = _ _webpack _require _ _ ( 9088 ) ;
module . exports = ! IS _DENO && ! IS _NODE
&& typeof window == 'object'
&& typeof document == 'object' ;
/***/ } ) ,
/***/ 516 :
/***/ ( ( module ) => {
/* global Deno -- Deno case */
module . exports = typeof Deno == 'object' && Deno && typeof Deno . version == 'object' ;
/***/ } ) ,
/***/ 9088 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var global = _ _webpack _require _ _ ( 4475 ) ;
var classof = _ _webpack _require _ _ ( 4576 ) ;
module . exports = classof ( global . process ) === 'process' ;
/***/ } ) ,
/***/ 9392 :
/***/ ( ( module ) => {
module . exports = typeof navigator != 'undefined' && String ( navigator . userAgent ) || '' ;
/***/ } ) ,
/***/ 7388 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var global = _ _webpack _require _ _ ( 4475 ) ;
var userAgent = _ _webpack _require _ _ ( 9392 ) ;
var process = global . process ;
var Deno = global . Deno ;
var versions = process && process . versions || Deno && Deno . version ;
var v8 = versions && versions . v8 ;
var match , version ;
if ( v8 ) {
match = v8 . split ( '.' ) ;
// in old Chrome, versions of V8 isn't V8 = Chrome / 10
// but their correct versions are not interesting for us
version = match [ 0 ] > 0 && match [ 0 ] < 4 ? 1 : + ( match [ 0 ] + match [ 1 ] ) ;
}
// BrowserFS NodeJS `process` polyfill incorrectly set `.v8` to `0.0`
// so check `userAgent` even if `.v8` exists, but 0
if ( ! version && userAgent ) {
match = userAgent . match ( /Edge\/(\d+)/ ) ;
if ( ! match || match [ 1 ] >= 74 ) {
match = userAgent . match ( /Chrome\/(\d+)/ ) ;
if ( match ) version = + match [ 1 ] ;
}
}
module . exports = version ;
/***/ } ) ,
/***/ 8727 :
/***/ ( ( module ) => {
// IE8- don't enum bug keys
module . exports = [
'constructor' ,
'hasOwnProperty' ,
'isPrototypeOf' ,
'propertyIsEnumerable' ,
'toLocaleString' ,
'toString' ,
'valueOf'
] ;
/***/ } ) ,
/***/ 6193 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var uncurryThis = _ _webpack _require _ _ ( 9504 ) ;
var $Error = Error ;
var replace = uncurryThis ( '' . replace ) ;
var TEST = ( function ( arg ) { return String ( new $Error ( arg ) . stack ) ; } ) ( 'zxcasd' ) ;
// eslint-disable-next-line redos/no-vulnerable -- safe
var V8 _OR _CHAKRA _STACK _ENTRY = /\n\s*at [^:]*:[^\n]*/ ;
var IS _V8 _OR _CHAKRA _STACK = V8 _OR _CHAKRA _STACK _ENTRY . test ( TEST ) ;
module . exports = function ( stack , dropEntries ) {
if ( IS _V8 _OR _CHAKRA _STACK && typeof stack == 'string' && ! $Error . prepareStackTrace ) {
while ( dropEntries -- ) stack = replace ( stack , V8 _OR _CHAKRA _STACK _ENTRY , '' ) ;
} return stack ;
} ;
/***/ } ) ,
/***/ 6518 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var global = _ _webpack _require _ _ ( 4475 ) ;
var getOwnPropertyDescriptor = ( _ _webpack _require _ _ ( 7347 ) . f ) ;
var createNonEnumerableProperty = _ _webpack _require _ _ ( 6699 ) ;
var defineBuiltIn = _ _webpack _require _ _ ( 6840 ) ;
var defineGlobalProperty = _ _webpack _require _ _ ( 9433 ) ;
var copyConstructorProperties = _ _webpack _require _ _ ( 7740 ) ;
var isForced = _ _webpack _require _ _ ( 2796 ) ;
/ *
options . target - name of the target object
options . global - target is the global object
options . stat - export as static methods of target
options . proto - export as prototype methods of target
options . real - real prototype method for the ` pure ` version
options . forced - export even if the native feature is available
options . bind - bind methods to the target , required for the ` pure ` version
options . wrap - wrap constructors to preventing global pollution , required for the ` pure ` version
options . unsafe - use the simple assignment of property instead of delete + defineProperty
options . sham - add a flag to not completely full polyfills
options . enumerable - export as enumerable property
options . dontCallGetSet - prevent calling a getter on target
options . name - the . name of the function if it does not match the key
* /
module . exports = function ( options , source ) {
var TARGET = options . target ;
var GLOBAL = options . global ;
var STATIC = options . stat ;
var FORCED , target , key , targetProperty , sourceProperty , descriptor ;
if ( GLOBAL ) {
target = global ;
} else if ( STATIC ) {
target = global [ TARGET ] || defineGlobalProperty ( TARGET , { } ) ;
} else {
target = global [ TARGET ] && global [ TARGET ] . prototype ;
}
if ( target ) for ( key in source ) {
sourceProperty = source [ key ] ;
if ( options . dontCallGetSet ) {
descriptor = getOwnPropertyDescriptor ( target , key ) ;
targetProperty = descriptor && descriptor . value ;
} else targetProperty = target [ key ] ;
FORCED = isForced ( GLOBAL ? key : TARGET + ( STATIC ? '.' : '#' ) + key , options . forced ) ;
// contained in target
if ( ! FORCED && targetProperty !== undefined ) {
if ( typeof sourceProperty == typeof targetProperty ) continue ;
copyConstructorProperties ( sourceProperty , targetProperty ) ;
}
// add a flag to not completely full polyfills
if ( options . sham || ( targetProperty && targetProperty . sham ) ) {
createNonEnumerableProperty ( sourceProperty , 'sham' , true ) ;
}
defineBuiltIn ( target , key , sourceProperty , options ) ;
}
} ;
/***/ } ) ,
/***/ 9039 :
/***/ ( ( module ) => {
module . exports = function ( exec ) {
try {
return ! ! exec ( ) ;
} catch ( error ) {
return true ;
}
} ;
/***/ } ) ,
/***/ 6080 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var uncurryThis = _ _webpack _require _ _ ( 7476 ) ;
var aCallable = _ _webpack _require _ _ ( 9306 ) ;
var NATIVE _BIND = _ _webpack _require _ _ ( 616 ) ;
var bind = uncurryThis ( uncurryThis . bind ) ;
// optional / simple context binding
module . exports = function ( fn , that ) {
aCallable ( fn ) ;
return that === undefined ? fn : NATIVE _BIND ? bind ( fn , that ) : function ( /* ...args */ ) {
return fn . apply ( that , arguments ) ;
} ;
} ;
/***/ } ) ,
/***/ 616 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var fails = _ _webpack _require _ _ ( 9039 ) ;
module . exports = ! fails ( function ( ) {
// eslint-disable-next-line es/no-function-prototype-bind -- safe
var test = ( function ( ) { /* empty */ } ) . bind ( ) ;
// eslint-disable-next-line no-prototype-builtins -- safe
return typeof test != 'function' || test . hasOwnProperty ( 'prototype' ) ;
} ) ;
/***/ } ) ,
/***/ 9565 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var NATIVE _BIND = _ _webpack _require _ _ ( 616 ) ;
var call = Function . prototype . call ;
module . exports = NATIVE _BIND ? call . bind ( call ) : function ( ) {
return call . apply ( call , arguments ) ;
} ;
/***/ } ) ,
/***/ 350 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var DESCRIPTORS = _ _webpack _require _ _ ( 3724 ) ;
var hasOwn = _ _webpack _require _ _ ( 9297 ) ;
var FunctionPrototype = Function . prototype ;
// eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
var getDescriptor = DESCRIPTORS && Object . getOwnPropertyDescriptor ;
var EXISTS = hasOwn ( FunctionPrototype , 'name' ) ;
// additional protection from minified / mangled / dropped function names
var PROPER = EXISTS && ( function something ( ) { /* empty */ } ) . name === 'something' ;
var CONFIGURABLE = EXISTS && ( ! DESCRIPTORS || ( DESCRIPTORS && getDescriptor ( FunctionPrototype , 'name' ) . configurable ) ) ;
module . exports = {
EXISTS : EXISTS ,
PROPER : PROPER ,
CONFIGURABLE : CONFIGURABLE
} ;
/***/ } ) ,
/***/ 6706 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var uncurryThis = _ _webpack _require _ _ ( 9504 ) ;
var aCallable = _ _webpack _require _ _ ( 9306 ) ;
module . exports = function ( object , key , method ) {
try {
// eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
return uncurryThis ( aCallable ( Object . getOwnPropertyDescriptor ( object , key ) [ method ] ) ) ;
} catch ( error ) { /* empty */ }
} ;
/***/ } ) ,
/***/ 7476 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var classofRaw = _ _webpack _require _ _ ( 4576 ) ;
var uncurryThis = _ _webpack _require _ _ ( 9504 ) ;
module . exports = function ( fn ) {
// Nashorn bug:
// https://github.com/zloirock/core-js/issues/1128
// https://github.com/zloirock/core-js/issues/1130
if ( classofRaw ( fn ) === 'Function' ) return uncurryThis ( fn ) ;
} ;
/***/ } ) ,
/***/ 9504 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var NATIVE _BIND = _ _webpack _require _ _ ( 616 ) ;
var FunctionPrototype = Function . prototype ;
var call = FunctionPrototype . call ;
var uncurryThisWithBind = NATIVE _BIND && FunctionPrototype . bind . bind ( call , call ) ;
module . exports = NATIVE _BIND ? uncurryThisWithBind : function ( fn ) {
return function ( ) {
return call . apply ( fn , arguments ) ;
} ;
} ;
/***/ } ) ,
/***/ 7751 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var global = _ _webpack _require _ _ ( 4475 ) ;
var isCallable = _ _webpack _require _ _ ( 4901 ) ;
var aFunction = function ( argument ) {
return isCallable ( argument ) ? argument : undefined ;
} ;
module . exports = function ( namespace , method ) {
return arguments . length < 2 ? aFunction ( global [ namespace ] ) : global [ namespace ] && global [ namespace ] [ method ] ;
} ;
/***/ } ) ,
/***/ 1767 :
/***/ ( ( module ) => {
// `GetIteratorDirect(obj)` abstract operation
// https://tc39.es/proposal-iterator-helpers/#sec-getiteratordirect
module . exports = function ( obj ) {
return {
iterator : obj ,
next : obj . next ,
done : false
} ;
} ;
/***/ } ) ,
/***/ 8646 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var call = _ _webpack _require _ _ ( 9565 ) ;
var anObject = _ _webpack _require _ _ ( 8551 ) ;
var getIteratorDirect = _ _webpack _require _ _ ( 1767 ) ;
var getIteratorMethod = _ _webpack _require _ _ ( 851 ) ;
module . exports = function ( obj , stringHandling ) {
if ( ! stringHandling || typeof obj !== 'string' ) anObject ( obj ) ;
var method = getIteratorMethod ( obj ) ;
return getIteratorDirect ( anObject ( method !== undefined ? call ( method , obj ) : obj ) ) ;
} ;
/***/ } ) ,
/***/ 851 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var classof = _ _webpack _require _ _ ( 6955 ) ;
var getMethod = _ _webpack _require _ _ ( 5966 ) ;
var isNullOrUndefined = _ _webpack _require _ _ ( 4117 ) ;
var Iterators = _ _webpack _require _ _ ( 6269 ) ;
var wellKnownSymbol = _ _webpack _require _ _ ( 8227 ) ;
var ITERATOR = wellKnownSymbol ( 'iterator' ) ;
module . exports = function ( it ) {
if ( ! isNullOrUndefined ( it ) ) return getMethod ( it , ITERATOR )
|| getMethod ( it , '@@iterator' )
|| Iterators [ classof ( it ) ] ;
} ;
/***/ } ) ,
/***/ 81 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var call = _ _webpack _require _ _ ( 9565 ) ;
var aCallable = _ _webpack _require _ _ ( 9306 ) ;
var anObject = _ _webpack _require _ _ ( 8551 ) ;
var tryToString = _ _webpack _require _ _ ( 6823 ) ;
var getIteratorMethod = _ _webpack _require _ _ ( 851 ) ;
var $TypeError = TypeError ;
module . exports = function ( argument , usingIterator ) {
var iteratorMethod = arguments . length < 2 ? getIteratorMethod ( argument ) : usingIterator ;
if ( aCallable ( iteratorMethod ) ) return anObject ( call ( iteratorMethod , argument ) ) ;
throw new $TypeError ( tryToString ( argument ) + ' is not iterable' ) ;
} ;
/***/ } ) ,
/***/ 5966 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var aCallable = _ _webpack _require _ _ ( 9306 ) ;
var isNullOrUndefined = _ _webpack _require _ _ ( 4117 ) ;
// `GetMethod` abstract operation
// https://tc39.es/ecma262/#sec-getmethod
module . exports = function ( V , P ) {
var func = V [ P ] ;
return isNullOrUndefined ( func ) ? undefined : aCallable ( func ) ;
} ;
/***/ } ) ,
/***/ 3789 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var aCallable = _ _webpack _require _ _ ( 9306 ) ;
var anObject = _ _webpack _require _ _ ( 8551 ) ;
var call = _ _webpack _require _ _ ( 9565 ) ;
var toIntegerOrInfinity = _ _webpack _require _ _ ( 1291 ) ;
var getIteratorDirect = _ _webpack _require _ _ ( 1767 ) ;
var INVALID _SIZE = 'Invalid size' ;
var $RangeError = RangeError ;
var $TypeError = TypeError ;
var max = Math . max ;
var SetRecord = function ( set , intSize ) {
this . set = set ;
this . size = max ( intSize , 0 ) ;
this . has = aCallable ( set . has ) ;
this . keys = aCallable ( set . keys ) ;
} ;
SetRecord . prototype = {
getIterator : function ( ) {
return getIteratorDirect ( anObject ( call ( this . keys , this . set ) ) ) ;
} ,
includes : function ( it ) {
return call ( this . has , this . set , it ) ;
}
} ;
// `GetSetRecord` abstract operation
// https://tc39.es/proposal-set-methods/#sec-getsetrecord
module . exports = function ( obj ) {
anObject ( obj ) ;
var numSize = + obj . size ;
// NOTE: If size is undefined, then numSize will be NaN
// eslint-disable-next-line no-self-compare -- NaN check
if ( numSize !== numSize ) throw new $TypeError ( INVALID _SIZE ) ;
var intSize = toIntegerOrInfinity ( numSize ) ;
if ( intSize < 0 ) throw new $RangeError ( INVALID _SIZE ) ;
return new SetRecord ( obj , intSize ) ;
} ;
/***/ } ) ,
/***/ 4475 :
/***/ ( function ( module ) {
var check = function ( it ) {
return it && it . Math === Math && it ;
} ;
// https://github.com/zloirock/core-js/issues/86#issuecomment-115759028
module . exports =
// eslint-disable-next-line es/no-global-this -- safe
check ( typeof globalThis == 'object' && globalThis ) ||
check ( typeof window == 'object' && window ) ||
// eslint-disable-next-line no-restricted-globals -- safe
check ( typeof self == 'object' && self ) ||
check ( typeof global == 'object' && global ) ||
check ( typeof this == 'object' && this ) ||
// eslint-disable-next-line no-new-func -- fallback
( function ( ) { return this ; } ) ( ) || Function ( 'return this' ) ( ) ;
/***/ } ) ,
/***/ 9297 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var uncurryThis = _ _webpack _require _ _ ( 9504 ) ;
var toObject = _ _webpack _require _ _ ( 8981 ) ;
var hasOwnProperty = uncurryThis ( { } . hasOwnProperty ) ;
// `HasOwnProperty` abstract operation
// https://tc39.es/ecma262/#sec-hasownproperty
// eslint-disable-next-line es/no-object-hasown -- safe
module . exports = Object . hasOwn || function hasOwn ( it , key ) {
return hasOwnProperty ( toObject ( it ) , key ) ;
} ;
/***/ } ) ,
/***/ 421 :
/***/ ( ( module ) => {
module . exports = { } ;
/***/ } ) ,
/***/ 397 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var getBuiltIn = _ _webpack _require _ _ ( 7751 ) ;
module . exports = getBuiltIn ( 'document' , 'documentElement' ) ;
/***/ } ) ,
/***/ 5917 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var DESCRIPTORS = _ _webpack _require _ _ ( 3724 ) ;
var fails = _ _webpack _require _ _ ( 9039 ) ;
var createElement = _ _webpack _require _ _ ( 4055 ) ;
// Thanks to IE8 for its funny defineProperty
module . exports = ! DESCRIPTORS && ! fails ( function ( ) {
// eslint-disable-next-line es/no-object-defineproperty -- required for testing
return Object . defineProperty ( createElement ( 'div' ) , 'a' , {
get : function ( ) { return 7 ; }
} ) . a !== 7 ;
} ) ;
/***/ } ) ,
/***/ 7055 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var uncurryThis = _ _webpack _require _ _ ( 9504 ) ;
var fails = _ _webpack _require _ _ ( 9039 ) ;
var classof = _ _webpack _require _ _ ( 4576 ) ;
var $Object = Object ;
var split = uncurryThis ( '' . split ) ;
// fallback for non-array-like ES3 and non-enumerable old V8 strings
module . exports = fails ( function ( ) {
// throws an error in rhino, see https://github.com/mozilla/rhino/issues/346
// eslint-disable-next-line no-prototype-builtins -- safe
return ! $Object ( 'z' ) . propertyIsEnumerable ( 0 ) ;
} ) ? function ( it ) {
return classof ( it ) === 'String' ? split ( it , '' ) : $Object ( it ) ;
} : $Object ;
/***/ } ) ,
/***/ 3167 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var isCallable = _ _webpack _require _ _ ( 4901 ) ;
var isObject = _ _webpack _require _ _ ( 34 ) ;
var setPrototypeOf = _ _webpack _require _ _ ( 2967 ) ;
// makes subclassing work correct for wrapped built-ins
module . exports = function ( $this , dummy , Wrapper ) {
var NewTarget , NewTargetPrototype ;
if (
// it can work only with native `setPrototypeOf`
setPrototypeOf &&
// we haven't completely correct pre-ES6 way for getting `new.target`, so use this
isCallable ( NewTarget = dummy . constructor ) &&
NewTarget !== Wrapper &&
isObject ( NewTargetPrototype = NewTarget . prototype ) &&
NewTargetPrototype !== Wrapper . prototype
) setPrototypeOf ( $this , NewTargetPrototype ) ;
return $this ;
} ;
/***/ } ) ,
/***/ 3706 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var uncurryThis = _ _webpack _require _ _ ( 9504 ) ;
var isCallable = _ _webpack _require _ _ ( 4901 ) ;
var store = _ _webpack _require _ _ ( 7629 ) ;
var functionToString = uncurryThis ( Function . toString ) ;
// this helper broken in `core-js@3.4.1-3.4.4`, so we can't use `shared` helper
if ( ! isCallable ( store . inspectSource ) ) {
store . inspectSource = function ( it ) {
return functionToString ( it ) ;
} ;
}
module . exports = store . inspectSource ;
/***/ } ) ,
/***/ 1181 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var NATIVE _WEAK _MAP = _ _webpack _require _ _ ( 8622 ) ;
var global = _ _webpack _require _ _ ( 4475 ) ;
var isObject = _ _webpack _require _ _ ( 34 ) ;
var createNonEnumerableProperty = _ _webpack _require _ _ ( 6699 ) ;
var hasOwn = _ _webpack _require _ _ ( 9297 ) ;
var shared = _ _webpack _require _ _ ( 7629 ) ;
var sharedKey = _ _webpack _require _ _ ( 6119 ) ;
var hiddenKeys = _ _webpack _require _ _ ( 421 ) ;
var OBJECT _ALREADY _INITIALIZED = 'Object already initialized' ;
var TypeError = global . TypeError ;
var WeakMap = global . WeakMap ;
var set , get , has ;
var enforce = function ( it ) {
return has ( it ) ? get ( it ) : set ( it , { } ) ;
} ;
var getterFor = function ( TYPE ) {
return function ( it ) {
var state ;
if ( ! isObject ( it ) || ( state = get ( it ) ) . type !== TYPE ) {
throw new TypeError ( 'Incompatible receiver, ' + TYPE + ' required' ) ;
} return state ;
} ;
} ;
if ( NATIVE _WEAK _MAP || shared . state ) {
var store = shared . state || ( shared . state = new WeakMap ( ) ) ;
/* eslint-disable no-self-assign -- prototype methods protection */
store . get = store . get ;
store . has = store . has ;
store . set = store . set ;
/* eslint-enable no-self-assign -- prototype methods protection */
set = function ( it , metadata ) {
if ( store . has ( it ) ) throw new TypeError ( OBJECT _ALREADY _INITIALIZED ) ;
metadata . facade = it ;
store . set ( it , metadata ) ;
return metadata ;
} ;
get = function ( it ) {
return store . get ( it ) || { } ;
} ;
has = function ( it ) {
return store . has ( it ) ;
} ;
} else {
var STATE = sharedKey ( 'state' ) ;
hiddenKeys [ STATE ] = true ;
set = function ( it , metadata ) {
if ( hasOwn ( it , STATE ) ) throw new TypeError ( OBJECT _ALREADY _INITIALIZED ) ;
metadata . facade = it ;
createNonEnumerableProperty ( it , STATE , metadata ) ;
return metadata ;
} ;
get = function ( it ) {
return hasOwn ( it , STATE ) ? it [ STATE ] : { } ;
} ;
has = function ( it ) {
return hasOwn ( it , STATE ) ;
} ;
}
module . exports = {
set : set ,
get : get ,
has : has ,
enforce : enforce ,
getterFor : getterFor
} ;
/***/ } ) ,
/***/ 4209 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var wellKnownSymbol = _ _webpack _require _ _ ( 8227 ) ;
var Iterators = _ _webpack _require _ _ ( 6269 ) ;
var ITERATOR = wellKnownSymbol ( 'iterator' ) ;
var ArrayPrototype = Array . prototype ;
// check on default Array iterator
module . exports = function ( it ) {
return it !== undefined && ( Iterators . Array === it || ArrayPrototype [ ITERATOR ] === it ) ;
} ;
/***/ } ) ,
/***/ 4376 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var classof = _ _webpack _require _ _ ( 4576 ) ;
// `IsArray` abstract operation
// https://tc39.es/ecma262/#sec-isarray
// eslint-disable-next-line es/no-array-isarray -- safe
module . exports = Array . isArray || function isArray ( argument ) {
return classof ( argument ) === 'Array' ;
} ;
/***/ } ) ,
/***/ 1108 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var classof = _ _webpack _require _ _ ( 6955 ) ;
module . exports = function ( it ) {
var klass = classof ( it ) ;
return klass === 'BigInt64Array' || klass === 'BigUint64Array' ;
} ;
/***/ } ) ,
/***/ 4901 :
/***/ ( ( module ) => {
// https://tc39.es/ecma262/#sec-IsHTMLDDA-internal-slot
var documentAll = typeof document == 'object' && document . all ;
// `IsCallable` abstract operation
// https://tc39.es/ecma262/#sec-iscallable
// eslint-disable-next-line unicorn/no-typeof-undefined -- required for testing
module . exports = typeof documentAll == 'undefined' && documentAll !== undefined ? function ( argument ) {
return typeof argument == 'function' || argument === documentAll ;
} : function ( argument ) {
return typeof argument == 'function' ;
} ;
/***/ } ) ,
/***/ 2796 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var fails = _ _webpack _require _ _ ( 9039 ) ;
var isCallable = _ _webpack _require _ _ ( 4901 ) ;
var replacement = /#|\.prototype\./ ;
var isForced = function ( feature , detection ) {
var value = data [ normalize ( feature ) ] ;
return value === POLYFILL ? true
: value === NATIVE ? false
: isCallable ( detection ) ? fails ( detection )
: ! ! detection ;
} ;
var normalize = isForced . normalize = function ( string ) {
return String ( string ) . replace ( replacement , '.' ) . toLowerCase ( ) ;
} ;
var data = isForced . data = { } ;
var NATIVE = isForced . NATIVE = 'N' ;
var POLYFILL = isForced . POLYFILL = 'P' ;
module . exports = isForced ;
/***/ } ) ,
/***/ 4117 :
/***/ ( ( module ) => {
// we can't use just `it == null` since of `document.all` special case
// https://tc39.es/ecma262/#sec-IsHTMLDDA-internal-slot-aec
module . exports = function ( it ) {
return it === null || it === undefined ;
} ;
/***/ } ) ,
/***/ 34 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var isCallable = _ _webpack _require _ _ ( 4901 ) ;
module . exports = function ( it ) {
return typeof it == 'object' ? it !== null : isCallable ( it ) ;
} ;
/***/ } ) ,
/***/ 3925 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var isObject = _ _webpack _require _ _ ( 34 ) ;
module . exports = function ( argument ) {
return isObject ( argument ) || argument === null ;
} ;
/***/ } ) ,
/***/ 6395 :
/***/ ( ( module ) => {
module . exports = false ;
/***/ } ) ,
/***/ 757 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var getBuiltIn = _ _webpack _require _ _ ( 7751 ) ;
var isCallable = _ _webpack _require _ _ ( 4901 ) ;
var isPrototypeOf = _ _webpack _require _ _ ( 1625 ) ;
var USE _SYMBOL _AS _UID = _ _webpack _require _ _ ( 7040 ) ;
var $Object = Object ;
module . exports = USE _SYMBOL _AS _UID ? function ( it ) {
return typeof it == 'symbol' ;
} : function ( it ) {
var $Symbol = getBuiltIn ( 'Symbol' ) ;
return isCallable ( $Symbol ) && isPrototypeOf ( $Symbol . prototype , $Object ( it ) ) ;
} ;
/***/ } ) ,
/***/ 507 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var call = _ _webpack _require _ _ ( 9565 ) ;
module . exports = function ( record , fn , ITERATOR _INSTEAD _OF _RECORD ) {
var iterator = ITERATOR _INSTEAD _OF _RECORD ? record : record . iterator ;
var next = record . next ;
var step , result ;
while ( ! ( step = call ( next , iterator ) ) . done ) {
result = fn ( step . value ) ;
if ( result !== undefined ) return result ;
}
} ;
/***/ } ) ,
/***/ 2652 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var bind = _ _webpack _require _ _ ( 6080 ) ;
var call = _ _webpack _require _ _ ( 9565 ) ;
var anObject = _ _webpack _require _ _ ( 8551 ) ;
var tryToString = _ _webpack _require _ _ ( 6823 ) ;
var isArrayIteratorMethod = _ _webpack _require _ _ ( 4209 ) ;
var lengthOfArrayLike = _ _webpack _require _ _ ( 6198 ) ;
var isPrototypeOf = _ _webpack _require _ _ ( 1625 ) ;
var getIterator = _ _webpack _require _ _ ( 81 ) ;
var getIteratorMethod = _ _webpack _require _ _ ( 851 ) ;
var iteratorClose = _ _webpack _require _ _ ( 9539 ) ;
var $TypeError = TypeError ;
var Result = function ( stopped , result ) {
this . stopped = stopped ;
this . result = result ;
} ;
var ResultPrototype = Result . prototype ;
module . exports = function ( iterable , unboundFunction , options ) {
var that = options && options . that ;
var AS _ENTRIES = ! ! ( options && options . AS _ENTRIES ) ;
var IS _RECORD = ! ! ( options && options . IS _RECORD ) ;
var IS _ITERATOR = ! ! ( options && options . IS _ITERATOR ) ;
var INTERRUPTED = ! ! ( options && options . INTERRUPTED ) ;
var fn = bind ( unboundFunction , that ) ;
var iterator , iterFn , index , length , result , next , step ;
var stop = function ( condition ) {
if ( iterator ) iteratorClose ( iterator , 'normal' , condition ) ;
return new Result ( true , condition ) ;
} ;
var callFn = function ( value ) {
if ( AS _ENTRIES ) {
anObject ( value ) ;
return INTERRUPTED ? fn ( value [ 0 ] , value [ 1 ] , stop ) : fn ( value [ 0 ] , value [ 1 ] ) ;
} return INTERRUPTED ? fn ( value , stop ) : fn ( value ) ;
} ;
if ( IS _RECORD ) {
iterator = iterable . iterator ;
} else if ( IS _ITERATOR ) {
iterator = iterable ;
} else {
iterFn = getIteratorMethod ( iterable ) ;
if ( ! iterFn ) throw new $TypeError ( tryToString ( iterable ) + ' is not iterable' ) ;
// optimisation for array iterators
if ( isArrayIteratorMethod ( iterFn ) ) {
for ( index = 0 , length = lengthOfArrayLike ( iterable ) ; length > index ; index ++ ) {
result = callFn ( iterable [ index ] ) ;
if ( result && isPrototypeOf ( ResultPrototype , result ) ) return result ;
} return new Result ( false ) ;
}
iterator = getIterator ( iterable , iterFn ) ;
}
next = IS _RECORD ? iterable . next : iterator . next ;
while ( ! ( step = call ( next , iterator ) ) . done ) {
try {
result = callFn ( step . value ) ;
} catch ( error ) {
iteratorClose ( iterator , 'throw' , error ) ;
}
if ( typeof result == 'object' && result && isPrototypeOf ( ResultPrototype , result ) ) return result ;
} return new Result ( false ) ;
} ;
/***/ } ) ,
/***/ 9539 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var call = _ _webpack _require _ _ ( 9565 ) ;
var anObject = _ _webpack _require _ _ ( 8551 ) ;
var getMethod = _ _webpack _require _ _ ( 5966 ) ;
module . exports = function ( iterator , kind , value ) {
var innerResult , innerError ;
anObject ( iterator ) ;
try {
innerResult = getMethod ( iterator , 'return' ) ;
if ( ! innerResult ) {
if ( kind === 'throw' ) throw value ;
return value ;
}
innerResult = call ( innerResult , iterator ) ;
} catch ( error ) {
innerError = true ;
innerResult = error ;
}
if ( kind === 'throw' ) throw value ;
if ( innerError ) throw innerResult ;
anObject ( innerResult ) ;
return value ;
} ;
/***/ } ) ,
/***/ 9462 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var call = _ _webpack _require _ _ ( 9565 ) ;
var create = _ _webpack _require _ _ ( 2360 ) ;
var createNonEnumerableProperty = _ _webpack _require _ _ ( 6699 ) ;
var defineBuiltIns = _ _webpack _require _ _ ( 6279 ) ;
var wellKnownSymbol = _ _webpack _require _ _ ( 8227 ) ;
var InternalStateModule = _ _webpack _require _ _ ( 1181 ) ;
var getMethod = _ _webpack _require _ _ ( 5966 ) ;
var IteratorPrototype = ( _ _webpack _require _ _ ( 7657 ) . IteratorPrototype ) ;
var createIterResultObject = _ _webpack _require _ _ ( 2529 ) ;
var iteratorClose = _ _webpack _require _ _ ( 9539 ) ;
var TO _STRING _TAG = wellKnownSymbol ( 'toStringTag' ) ;
var ITERATOR _HELPER = 'IteratorHelper' ;
var WRAP _FOR _VALID _ITERATOR = 'WrapForValidIterator' ;
var setInternalState = InternalStateModule . set ;
var createIteratorProxyPrototype = function ( IS _ITERATOR ) {
var getInternalState = InternalStateModule . getterFor ( IS _ITERATOR ? WRAP _FOR _VALID _ITERATOR : ITERATOR _HELPER ) ;
return defineBuiltIns ( create ( IteratorPrototype ) , {
next : function next ( ) {
var state = getInternalState ( this ) ;
// for simplification:
// for `%WrapForValidIteratorPrototype%.next` our `nextHandler` returns `IterResultObject`
// for `%IteratorHelperPrototype%.next` - just a value
if ( IS _ITERATOR ) return state . nextHandler ( ) ;
try {
var result = state . done ? undefined : state . nextHandler ( ) ;
return createIterResultObject ( result , state . done ) ;
} catch ( error ) {
state . done = true ;
throw error ;
}
} ,
'return' : function ( ) {
var state = getInternalState ( this ) ;
var iterator = state . iterator ;
state . done = true ;
if ( IS _ITERATOR ) {
var returnMethod = getMethod ( iterator , 'return' ) ;
return returnMethod ? call ( returnMethod , iterator ) : createIterResultObject ( undefined , true ) ;
}
if ( state . inner ) try {
iteratorClose ( state . inner . iterator , 'normal' ) ;
} catch ( error ) {
return iteratorClose ( iterator , 'throw' , error ) ;
}
iteratorClose ( iterator , 'normal' ) ;
return createIterResultObject ( undefined , true ) ;
}
} ) ;
} ;
var WrapForValidIteratorPrototype = createIteratorProxyPrototype ( true ) ;
var IteratorHelperPrototype = createIteratorProxyPrototype ( false ) ;
createNonEnumerableProperty ( IteratorHelperPrototype , TO _STRING _TAG , 'Iterator Helper' ) ;
module . exports = function ( nextHandler , IS _ITERATOR ) {
var IteratorProxy = function Iterator ( record , state ) {
if ( state ) {
state . iterator = record . iterator ;
state . next = record . next ;
} else state = record ;
state . type = IS _ITERATOR ? WRAP _FOR _VALID _ITERATOR : ITERATOR _HELPER ;
state . nextHandler = nextHandler ;
state . counter = 0 ;
state . done = false ;
setInternalState ( this , state ) ;
} ;
IteratorProxy . prototype = IS _ITERATOR ? WrapForValidIteratorPrototype : IteratorHelperPrototype ;
return IteratorProxy ;
} ;
/***/ } ) ,
/***/ 713 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var call = _ _webpack _require _ _ ( 9565 ) ;
var aCallable = _ _webpack _require _ _ ( 9306 ) ;
var anObject = _ _webpack _require _ _ ( 8551 ) ;
var getIteratorDirect = _ _webpack _require _ _ ( 1767 ) ;
var createIteratorProxy = _ _webpack _require _ _ ( 9462 ) ;
var callWithSafeIterationClosing = _ _webpack _require _ _ ( 6319 ) ;
var IteratorProxy = createIteratorProxy ( function ( ) {
var iterator = this . iterator ;
var result = anObject ( call ( this . next , iterator ) ) ;
var done = this . done = ! ! result . done ;
if ( ! done ) return callWithSafeIterationClosing ( iterator , this . mapper , [ result . value , this . counter ++ ] , true ) ;
} ) ;
// `Iterator.prototype.map` method
// https://github.com/tc39/proposal-iterator-helpers
module . exports = function map ( mapper ) {
anObject ( this ) ;
aCallable ( mapper ) ;
return new IteratorProxy ( getIteratorDirect ( this ) , {
mapper : mapper
} ) ;
} ;
/***/ } ) ,
/***/ 7657 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var fails = _ _webpack _require _ _ ( 9039 ) ;
var isCallable = _ _webpack _require _ _ ( 4901 ) ;
var isObject = _ _webpack _require _ _ ( 34 ) ;
var create = _ _webpack _require _ _ ( 2360 ) ;
var getPrototypeOf = _ _webpack _require _ _ ( 2787 ) ;
var defineBuiltIn = _ _webpack _require _ _ ( 6840 ) ;
var wellKnownSymbol = _ _webpack _require _ _ ( 8227 ) ;
var IS _PURE = _ _webpack _require _ _ ( 6395 ) ;
var ITERATOR = wellKnownSymbol ( 'iterator' ) ;
var BUGGY _SAFARI _ITERATORS = false ;
// `%IteratorPrototype%` object
// https://tc39.es/ecma262/#sec-%iteratorprototype%-object
var IteratorPrototype , PrototypeOfArrayIteratorPrototype , arrayIterator ;
/* eslint-disable es/no-array-prototype-keys -- safe */
if ( [ ] . keys ) {
arrayIterator = [ ] . keys ( ) ;
// Safari 8 has buggy iterators w/o `next`
if ( ! ( 'next' in arrayIterator ) ) BUGGY _SAFARI _ITERATORS = true ;
else {
PrototypeOfArrayIteratorPrototype = getPrototypeOf ( getPrototypeOf ( arrayIterator ) ) ;
if ( PrototypeOfArrayIteratorPrototype !== Object . prototype ) IteratorPrototype = PrototypeOfArrayIteratorPrototype ;
}
}
var NEW _ITERATOR _PROTOTYPE = ! isObject ( IteratorPrototype ) || fails ( function ( ) {
var test = { } ;
// FF44- legacy iterators case
return IteratorPrototype [ ITERATOR ] . call ( test ) !== test ;
} ) ;
if ( NEW _ITERATOR _PROTOTYPE ) IteratorPrototype = { } ;
else if ( IS _PURE ) IteratorPrototype = create ( IteratorPrototype ) ;
// `%IteratorPrototype%[@@iterator]()` method
// https://tc39.es/ecma262/#sec-%iteratorprototype%-@@iterator
if ( ! isCallable ( IteratorPrototype [ ITERATOR ] ) ) {
defineBuiltIn ( IteratorPrototype , ITERATOR , function ( ) {
return this ;
} ) ;
}
module . exports = {
IteratorPrototype : IteratorPrototype ,
BUGGY _SAFARI _ITERATORS : BUGGY _SAFARI _ITERATORS
} ;
/***/ } ) ,
/***/ 6269 :
/***/ ( ( module ) => {
module . exports = { } ;
/***/ } ) ,
/***/ 6198 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var toLength = _ _webpack _require _ _ ( 8014 ) ;
// `LengthOfArrayLike` abstract operation
// https://tc39.es/ecma262/#sec-lengthofarraylike
module . exports = function ( obj ) {
return toLength ( obj . length ) ;
} ;
/***/ } ) ,
/***/ 283 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var uncurryThis = _ _webpack _require _ _ ( 9504 ) ;
var fails = _ _webpack _require _ _ ( 9039 ) ;
var isCallable = _ _webpack _require _ _ ( 4901 ) ;
var hasOwn = _ _webpack _require _ _ ( 9297 ) ;
var DESCRIPTORS = _ _webpack _require _ _ ( 3724 ) ;
var CONFIGURABLE _FUNCTION _NAME = ( _ _webpack _require _ _ ( 350 ) . CONFIGURABLE ) ;
var inspectSource = _ _webpack _require _ _ ( 3706 ) ;
var InternalStateModule = _ _webpack _require _ _ ( 1181 ) ;
var enforceInternalState = InternalStateModule . enforce ;
var getInternalState = InternalStateModule . get ;
var $String = String ;
// eslint-disable-next-line es/no-object-defineproperty -- safe
var defineProperty = Object . defineProperty ;
var stringSlice = uncurryThis ( '' . slice ) ;
var replace = uncurryThis ( '' . replace ) ;
var join = uncurryThis ( [ ] . join ) ;
var CONFIGURABLE _LENGTH = DESCRIPTORS && ! fails ( function ( ) {
return defineProperty ( function ( ) { /* empty */ } , 'length' , { value : 8 } ) . length !== 8 ;
} ) ;
var TEMPLATE = String ( String ) . split ( 'String' ) ;
var makeBuiltIn = module . exports = function ( value , name , options ) {
if ( stringSlice ( $String ( name ) , 0 , 7 ) === 'Symbol(' ) {
name = '[' + replace ( $String ( name ) , /^Symbol\(([^)]*)\).*$/ , '$1' ) + ']' ;
}
if ( options && options . getter ) name = 'get ' + name ;
if ( options && options . setter ) name = 'set ' + name ;
if ( ! hasOwn ( value , 'name' ) || ( CONFIGURABLE _FUNCTION _NAME && value . name !== name ) ) {
if ( DESCRIPTORS ) defineProperty ( value , 'name' , { value : name , configurable : true } ) ;
else value . name = name ;
}
if ( CONFIGURABLE _LENGTH && options && hasOwn ( options , 'arity' ) && value . length !== options . arity ) {
defineProperty ( value , 'length' , { value : options . arity } ) ;
}
try {
if ( options && hasOwn ( options , 'constructor' ) && options . constructor ) {
if ( DESCRIPTORS ) defineProperty ( value , 'prototype' , { writable : false } ) ;
// in V8 ~ Chrome 53, prototypes of some methods, like `Array.prototype.values`, are non-writable
} else if ( value . prototype ) value . prototype = undefined ;
} catch ( error ) { /* empty */ }
var state = enforceInternalState ( value ) ;
if ( ! hasOwn ( state , 'source' ) ) {
state . source = join ( TEMPLATE , typeof name == 'string' ? name : '' ) ;
} return value ;
} ;
// add fake Function#toString for correct work wrapped methods / constructors with methods like LoDash isNative
// eslint-disable-next-line no-extend-native -- required
Function . prototype . toString = makeBuiltIn ( function toString ( ) {
return isCallable ( this ) && getInternalState ( this ) . source || inspectSource ( this ) ;
} , 'toString' ) ;
/***/ } ) ,
/***/ 741 :
/***/ ( ( module ) => {
var ceil = Math . ceil ;
var floor = Math . floor ;
// `Math.trunc` method
// https://tc39.es/ecma262/#sec-math.trunc
// eslint-disable-next-line es/no-math-trunc -- safe
module . exports = Math . trunc || function trunc ( x ) {
var n = + x ;
return ( n > 0 ? floor : ceil ) ( n ) ;
} ;
/***/ } ) ,
/***/ 6043 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var aCallable = _ _webpack _require _ _ ( 9306 ) ;
var $TypeError = TypeError ;
var PromiseCapability = function ( C ) {
var resolve , reject ;
this . promise = new C ( function ( $$resolve , $$reject ) {
if ( resolve !== undefined || reject !== undefined ) throw new $TypeError ( 'Bad Promise constructor' ) ;
resolve = $$resolve ;
reject = $$reject ;
} ) ;
this . resolve = aCallable ( resolve ) ;
this . reject = aCallable ( reject ) ;
} ;
// `NewPromiseCapability` abstract operation
// https://tc39.es/ecma262/#sec-newpromisecapability
module . exports . f = function ( C ) {
return new PromiseCapability ( C ) ;
} ;
/***/ } ) ,
/***/ 2603 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var toString = _ _webpack _require _ _ ( 655 ) ;
module . exports = function ( argument , $default ) {
return argument === undefined ? arguments . length < 2 ? '' : $default : toString ( argument ) ;
} ;
/***/ } ) ,
/***/ 4149 :
/***/ ( ( module ) => {
var $RangeError = RangeError ;
module . exports = function ( it ) {
// eslint-disable-next-line no-self-compare -- NaN check
if ( it === it ) return it ;
throw new $RangeError ( 'NaN is not allowed' ) ;
} ;
/***/ } ) ,
/***/ 2360 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
/* global ActiveXObject -- old IE, WSH */
var anObject = _ _webpack _require _ _ ( 8551 ) ;
var definePropertiesModule = _ _webpack _require _ _ ( 6801 ) ;
var enumBugKeys = _ _webpack _require _ _ ( 8727 ) ;
var hiddenKeys = _ _webpack _require _ _ ( 421 ) ;
var html = _ _webpack _require _ _ ( 397 ) ;
var documentCreateElement = _ _webpack _require _ _ ( 4055 ) ;
var sharedKey = _ _webpack _require _ _ ( 6119 ) ;
var GT = '>' ;
var LT = '<' ;
var PROTOTYPE = 'prototype' ;
var SCRIPT = 'script' ;
var IE _PROTO = sharedKey ( 'IE_PROTO' ) ;
var EmptyConstructor = function ( ) { /* empty */ } ;
var scriptTag = function ( content ) {
return LT + SCRIPT + GT + content + LT + '/' + SCRIPT + GT ;
} ;
// Create object with fake `null` prototype: use ActiveX Object with cleared prototype
var NullProtoObjectViaActiveX = function ( activeXDocument ) {
activeXDocument . write ( scriptTag ( '' ) ) ;
activeXDocument . close ( ) ;
var temp = activeXDocument . parentWindow . Object ;
activeXDocument = null ; // avoid memory leak
return temp ;
} ;
// Create object with fake `null` prototype: use iframe Object with cleared prototype
var NullProtoObjectViaIFrame = function ( ) {
// Thrash, waste and sodomy: IE GC bug
var iframe = documentCreateElement ( 'iframe' ) ;
var JS = 'java' + SCRIPT + ':' ;
var iframeDocument ;
iframe . style . display = 'none' ;
html . appendChild ( iframe ) ;
// https://github.com/zloirock/core-js/issues/475
iframe . src = String ( JS ) ;
iframeDocument = iframe . contentWindow . document ;
iframeDocument . open ( ) ;
iframeDocument . write ( scriptTag ( 'document.F=Object' ) ) ;
iframeDocument . close ( ) ;
return iframeDocument . F ;
} ;
// Check for document.domain and active x support
// No need to use active x approach when document.domain is not set
// see https://github.com/es-shims/es5-shim/issues/150
// variation of https://github.com/kitcambridge/es5-shim/commit/4f738ac066346
// avoid IE GC bug
var activeXDocument ;
var NullProtoObject = function ( ) {
try {
activeXDocument = new ActiveXObject ( 'htmlfile' ) ;
} catch ( error ) { /* ignore */ }
NullProtoObject = typeof document != 'undefined'
? document . domain && activeXDocument
? NullProtoObjectViaActiveX ( activeXDocument ) // old IE
: NullProtoObjectViaIFrame ( )
: NullProtoObjectViaActiveX ( activeXDocument ) ; // WSH
var length = enumBugKeys . length ;
while ( length -- ) delete NullProtoObject [ PROTOTYPE ] [ enumBugKeys [ length ] ] ;
return NullProtoObject ( ) ;
} ;
hiddenKeys [ IE _PROTO ] = true ;
// `Object.create` method
// https://tc39.es/ecma262/#sec-object.create
// eslint-disable-next-line es/no-object-create -- safe
module . exports = Object . create || function create ( O , Properties ) {
var result ;
if ( O !== null ) {
EmptyConstructor [ PROTOTYPE ] = anObject ( O ) ;
result = new EmptyConstructor ( ) ;
EmptyConstructor [ PROTOTYPE ] = null ;
// add "__proto__" for Object.getPrototypeOf polyfill
result [ IE _PROTO ] = O ;
} else result = NullProtoObject ( ) ;
return Properties === undefined ? result : definePropertiesModule . f ( result , Properties ) ;
} ;
/***/ } ) ,
/***/ 6801 :
/***/ ( ( _ _unused _webpack _module , exports , _ _webpack _require _ _ ) => {
var DESCRIPTORS = _ _webpack _require _ _ ( 3724 ) ;
var V8 _PROTOTYPE _DEFINE _BUG = _ _webpack _require _ _ ( 8686 ) ;
var definePropertyModule = _ _webpack _require _ _ ( 4913 ) ;
var anObject = _ _webpack _require _ _ ( 8551 ) ;
var toIndexedObject = _ _webpack _require _ _ ( 5397 ) ;
var objectKeys = _ _webpack _require _ _ ( 1072 ) ;
// `Object.defineProperties` method
// https://tc39.es/ecma262/#sec-object.defineproperties
// eslint-disable-next-line es/no-object-defineproperties -- safe
exports . f = DESCRIPTORS && ! V8 _PROTOTYPE _DEFINE _BUG ? Object . defineProperties : function defineProperties ( O , Properties ) {
anObject ( O ) ;
var props = toIndexedObject ( Properties ) ;
var keys = objectKeys ( Properties ) ;
var length = keys . length ;
var index = 0 ;
var key ;
while ( length > index ) definePropertyModule . f ( O , key = keys [ index ++ ] , props [ key ] ) ;
return O ;
} ;
/***/ } ) ,
/***/ 4913 :
/***/ ( ( _ _unused _webpack _module , exports , _ _webpack _require _ _ ) => {
var DESCRIPTORS = _ _webpack _require _ _ ( 3724 ) ;
var IE8 _DOM _DEFINE = _ _webpack _require _ _ ( 5917 ) ;
var V8 _PROTOTYPE _DEFINE _BUG = _ _webpack _require _ _ ( 8686 ) ;
var anObject = _ _webpack _require _ _ ( 8551 ) ;
var toPropertyKey = _ _webpack _require _ _ ( 6969 ) ;
var $TypeError = TypeError ;
// eslint-disable-next-line es/no-object-defineproperty -- safe
var $defineProperty = Object . defineProperty ;
// eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
var $getOwnPropertyDescriptor = Object . getOwnPropertyDescriptor ;
var ENUMERABLE = 'enumerable' ;
var CONFIGURABLE = 'configurable' ;
var WRITABLE = 'writable' ;
// `Object.defineProperty` method
// https://tc39.es/ecma262/#sec-object.defineproperty
exports . f = DESCRIPTORS ? V8 _PROTOTYPE _DEFINE _BUG ? function defineProperty ( O , P , Attributes ) {
anObject ( O ) ;
P = toPropertyKey ( P ) ;
anObject ( Attributes ) ;
if ( typeof O === 'function' && P === 'prototype' && 'value' in Attributes && WRITABLE in Attributes && ! Attributes [ WRITABLE ] ) {
var current = $getOwnPropertyDescriptor ( O , P ) ;
if ( current && current [ WRITABLE ] ) {
O [ P ] = Attributes . value ;
Attributes = {
configurable : CONFIGURABLE in Attributes ? Attributes [ CONFIGURABLE ] : current [ CONFIGURABLE ] ,
enumerable : ENUMERABLE in Attributes ? Attributes [ ENUMERABLE ] : current [ ENUMERABLE ] ,
writable : false
} ;
}
} return $defineProperty ( O , P , Attributes ) ;
} : $defineProperty : function defineProperty ( O , P , Attributes ) {
anObject ( O ) ;
P = toPropertyKey ( P ) ;
anObject ( Attributes ) ;
if ( IE8 _DOM _DEFINE ) try {
return $defineProperty ( O , P , Attributes ) ;
} catch ( error ) { /* empty */ }
if ( 'get' in Attributes || 'set' in Attributes ) throw new $TypeError ( 'Accessors not supported' ) ;
if ( 'value' in Attributes ) O [ P ] = Attributes . value ;
return O ;
} ;
/***/ } ) ,
/***/ 7347 :
/***/ ( ( _ _unused _webpack _module , exports , _ _webpack _require _ _ ) => {
var DESCRIPTORS = _ _webpack _require _ _ ( 3724 ) ;
var call = _ _webpack _require _ _ ( 9565 ) ;
var propertyIsEnumerableModule = _ _webpack _require _ _ ( 8773 ) ;
var createPropertyDescriptor = _ _webpack _require _ _ ( 6980 ) ;
var toIndexedObject = _ _webpack _require _ _ ( 5397 ) ;
var toPropertyKey = _ _webpack _require _ _ ( 6969 ) ;
var hasOwn = _ _webpack _require _ _ ( 9297 ) ;
var IE8 _DOM _DEFINE = _ _webpack _require _ _ ( 5917 ) ;
// eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
var $getOwnPropertyDescriptor = Object . getOwnPropertyDescriptor ;
// `Object.getOwnPropertyDescriptor` method
// https://tc39.es/ecma262/#sec-object.getownpropertydescriptor
exports . f = DESCRIPTORS ? $getOwnPropertyDescriptor : function getOwnPropertyDescriptor ( O , P ) {
O = toIndexedObject ( O ) ;
P = toPropertyKey ( P ) ;
if ( IE8 _DOM _DEFINE ) try {
return $getOwnPropertyDescriptor ( O , P ) ;
} catch ( error ) { /* empty */ }
if ( hasOwn ( O , P ) ) return createPropertyDescriptor ( ! call ( propertyIsEnumerableModule . f , O , P ) , O [ P ] ) ;
} ;
/***/ } ) ,
/***/ 8480 :
/***/ ( ( _ _unused _webpack _module , exports , _ _webpack _require _ _ ) => {
var internalObjectKeys = _ _webpack _require _ _ ( 1828 ) ;
var enumBugKeys = _ _webpack _require _ _ ( 8727 ) ;
var hiddenKeys = enumBugKeys . concat ( 'length' , 'prototype' ) ;
// `Object.getOwnPropertyNames` method
// https://tc39.es/ecma262/#sec-object.getownpropertynames
// eslint-disable-next-line es/no-object-getownpropertynames -- safe
exports . f = Object . getOwnPropertyNames || function getOwnPropertyNames ( O ) {
return internalObjectKeys ( O , hiddenKeys ) ;
} ;
/***/ } ) ,
/***/ 3717 :
/***/ ( ( _ _unused _webpack _module , exports ) => {
// eslint-disable-next-line es/no-object-getownpropertysymbols -- safe
exports . f = Object . getOwnPropertySymbols ;
/***/ } ) ,
/***/ 2787 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var hasOwn = _ _webpack _require _ _ ( 9297 ) ;
var isCallable = _ _webpack _require _ _ ( 4901 ) ;
var toObject = _ _webpack _require _ _ ( 8981 ) ;
var sharedKey = _ _webpack _require _ _ ( 6119 ) ;
var CORRECT _PROTOTYPE _GETTER = _ _webpack _require _ _ ( 2211 ) ;
var IE _PROTO = sharedKey ( 'IE_PROTO' ) ;
var $Object = Object ;
var ObjectPrototype = $Object . prototype ;
// `Object.getPrototypeOf` method
// https://tc39.es/ecma262/#sec-object.getprototypeof
// eslint-disable-next-line es/no-object-getprototypeof -- safe
module . exports = CORRECT _PROTOTYPE _GETTER ? $Object . getPrototypeOf : function ( O ) {
var object = toObject ( O ) ;
if ( hasOwn ( object , IE _PROTO ) ) return object [ IE _PROTO ] ;
var constructor = object . constructor ;
if ( isCallable ( constructor ) && object instanceof constructor ) {
return constructor . prototype ;
} return object instanceof $Object ? ObjectPrototype : null ;
} ;
/***/ } ) ,
/***/ 1625 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var uncurryThis = _ _webpack _require _ _ ( 9504 ) ;
module . exports = uncurryThis ( { } . isPrototypeOf ) ;
/***/ } ) ,
/***/ 1828 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var uncurryThis = _ _webpack _require _ _ ( 9504 ) ;
var hasOwn = _ _webpack _require _ _ ( 9297 ) ;
var toIndexedObject = _ _webpack _require _ _ ( 5397 ) ;
var indexOf = ( _ _webpack _require _ _ ( 9617 ) . indexOf ) ;
var hiddenKeys = _ _webpack _require _ _ ( 421 ) ;
var push = uncurryThis ( [ ] . push ) ;
module . exports = function ( object , names ) {
var O = toIndexedObject ( object ) ;
var i = 0 ;
var result = [ ] ;
var key ;
for ( key in O ) ! hasOwn ( hiddenKeys , key ) && hasOwn ( O , key ) && push ( result , key ) ;
// Don't enum bug & hidden keys
while ( names . length > i ) if ( hasOwn ( O , key = names [ i ++ ] ) ) {
~ indexOf ( result , key ) || push ( result , key ) ;
}
return result ;
} ;
/***/ } ) ,
/***/ 1072 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var internalObjectKeys = _ _webpack _require _ _ ( 1828 ) ;
var enumBugKeys = _ _webpack _require _ _ ( 8727 ) ;
// `Object.keys` method
// https://tc39.es/ecma262/#sec-object.keys
// eslint-disable-next-line es/no-object-keys -- safe
module . exports = Object . keys || function keys ( O ) {
return internalObjectKeys ( O , enumBugKeys ) ;
} ;
/***/ } ) ,
/***/ 8773 :
/***/ ( ( _ _unused _webpack _module , exports ) => {
var $propertyIsEnumerable = { } . propertyIsEnumerable ;
// eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
var getOwnPropertyDescriptor = Object . getOwnPropertyDescriptor ;
// Nashorn ~ JDK8 bug
var NASHORN _BUG = getOwnPropertyDescriptor && ! $propertyIsEnumerable . call ( { 1 : 2 } , 1 ) ;
// `Object.prototype.propertyIsEnumerable` method implementation
// https://tc39.es/ecma262/#sec-object.prototype.propertyisenumerable
exports . f = NASHORN _BUG ? function propertyIsEnumerable ( V ) {
var descriptor = getOwnPropertyDescriptor ( this , V ) ;
return ! ! descriptor && descriptor . enumerable ;
} : $propertyIsEnumerable ;
/***/ } ) ,
/***/ 2967 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
/* eslint-disable no-proto -- safe */
var uncurryThisAccessor = _ _webpack _require _ _ ( 6706 ) ;
var isObject = _ _webpack _require _ _ ( 34 ) ;
var requireObjectCoercible = _ _webpack _require _ _ ( 7750 ) ;
var aPossiblePrototype = _ _webpack _require _ _ ( 3506 ) ;
// `Object.setPrototypeOf` method
// https://tc39.es/ecma262/#sec-object.setprototypeof
// Works with __proto__ only. Old v8 can't work with null proto objects.
// eslint-disable-next-line es/no-object-setprototypeof -- safe
module . exports = Object . setPrototypeOf || ( '__proto__' in { } ? function ( ) {
var CORRECT _SETTER = false ;
var test = { } ;
var setter ;
try {
setter = uncurryThisAccessor ( Object . prototype , '__proto__' , 'set' ) ;
setter ( test , [ ] ) ;
CORRECT _SETTER = test instanceof Array ;
} catch ( error ) { /* empty */ }
return function setPrototypeOf ( O , proto ) {
requireObjectCoercible ( O ) ;
aPossiblePrototype ( proto ) ;
if ( ! isObject ( O ) ) return O ;
if ( CORRECT _SETTER ) setter ( O , proto ) ;
else O . _ _proto _ _ = proto ;
return O ;
} ;
} ( ) : undefined ) ;
/***/ } ) ,
/***/ 4270 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var call = _ _webpack _require _ _ ( 9565 ) ;
var isCallable = _ _webpack _require _ _ ( 4901 ) ;
var isObject = _ _webpack _require _ _ ( 34 ) ;
var $TypeError = TypeError ;
// `OrdinaryToPrimitive` abstract operation
// https://tc39.es/ecma262/#sec-ordinarytoprimitive
module . exports = function ( input , pref ) {
var fn , val ;
if ( pref === 'string' && isCallable ( fn = input . toString ) && ! isObject ( val = call ( fn , input ) ) ) return val ;
if ( isCallable ( fn = input . valueOf ) && ! isObject ( val = call ( fn , input ) ) ) return val ;
if ( pref !== 'string' && isCallable ( fn = input . toString ) && ! isObject ( val = call ( fn , input ) ) ) return val ;
throw new $TypeError ( "Can't convert object to primitive value" ) ;
} ;
/***/ } ) ,
/***/ 5031 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var getBuiltIn = _ _webpack _require _ _ ( 7751 ) ;
var uncurryThis = _ _webpack _require _ _ ( 9504 ) ;
var getOwnPropertyNamesModule = _ _webpack _require _ _ ( 8480 ) ;
var getOwnPropertySymbolsModule = _ _webpack _require _ _ ( 3717 ) ;
var anObject = _ _webpack _require _ _ ( 8551 ) ;
var concat = uncurryThis ( [ ] . concat ) ;
// all object keys, includes non-enumerable and symbols
module . exports = getBuiltIn ( 'Reflect' , 'ownKeys' ) || function ownKeys ( it ) {
var keys = getOwnPropertyNamesModule . f ( anObject ( it ) ) ;
var getOwnPropertySymbols = getOwnPropertySymbolsModule . f ;
return getOwnPropertySymbols ? concat ( keys , getOwnPropertySymbols ( it ) ) : keys ;
} ;
/***/ } ) ,
/***/ 8235 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var uncurryThis = _ _webpack _require _ _ ( 9504 ) ;
var hasOwn = _ _webpack _require _ _ ( 9297 ) ;
var $SyntaxError = SyntaxError ;
var $parseInt = parseInt ;
var fromCharCode = String . fromCharCode ;
var at = uncurryThis ( '' . charAt ) ;
var slice = uncurryThis ( '' . slice ) ;
var exec = uncurryThis ( /./ . exec ) ;
var codePoints = {
'\\"' : '"' ,
'\\\\' : '\\' ,
'\\/' : '/' ,
'\\b' : '\b' ,
'\\f' : '\f' ,
'\\n' : '\n' ,
'\\r' : '\r' ,
'\\t' : '\t'
} ;
var IS _4 _HEX _DIGITS = /^[\da-f]{4}$/i ;
// eslint-disable-next-line regexp/no-control-character -- safe
var IS _C0 _CONTROL _CODE = /^[\u0000-\u001F]$/ ;
module . exports = function ( source , i ) {
var unterminated = true ;
var value = '' ;
while ( i < source . length ) {
var chr = at ( source , i ) ;
if ( chr === '\\' ) {
var twoChars = slice ( source , i , i + 2 ) ;
if ( hasOwn ( codePoints , twoChars ) ) {
value += codePoints [ twoChars ] ;
i += 2 ;
} else if ( twoChars === '\\u' ) {
i += 2 ;
var fourHexDigits = slice ( source , i , i + 4 ) ;
if ( ! exec ( IS _4 _HEX _DIGITS , fourHexDigits ) ) throw new $SyntaxError ( 'Bad Unicode escape at: ' + i ) ;
value += fromCharCode ( $parseInt ( fourHexDigits , 16 ) ) ;
i += 4 ;
} else throw new $SyntaxError ( 'Unknown escape sequence: "' + twoChars + '"' ) ;
} else if ( chr === '"' ) {
unterminated = false ;
i ++ ;
break ;
} else {
if ( exec ( IS _C0 _CONTROL _CODE , chr ) ) throw new $SyntaxError ( 'Bad control character in string literal at: ' + i ) ;
value += chr ;
i ++ ;
}
}
if ( unterminated ) throw new $SyntaxError ( 'Unterminated string at: ' + i ) ;
return { value : value , end : i } ;
} ;
/***/ } ) ,
/***/ 7750 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var isNullOrUndefined = _ _webpack _require _ _ ( 4117 ) ;
var $TypeError = TypeError ;
// `RequireObjectCoercible` abstract operation
// https://tc39.es/ecma262/#sec-requireobjectcoercible
module . exports = function ( it ) {
if ( isNullOrUndefined ( it ) ) throw new $TypeError ( "Can't call method on " + it ) ;
return it ;
} ;
/***/ } ) ,
/***/ 9286 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var SetHelpers = _ _webpack _require _ _ ( 4402 ) ;
var iterate = _ _webpack _require _ _ ( 8469 ) ;
var Set = SetHelpers . Set ;
var add = SetHelpers . add ;
module . exports = function ( set ) {
var result = new Set ( ) ;
iterate ( set , function ( it ) {
add ( result , it ) ;
} ) ;
return result ;
} ;
/***/ } ) ,
/***/ 3440 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var aSet = _ _webpack _require _ _ ( 7080 ) ;
var SetHelpers = _ _webpack _require _ _ ( 4402 ) ;
var clone = _ _webpack _require _ _ ( 9286 ) ;
var size = _ _webpack _require _ _ ( 5170 ) ;
var getSetRecord = _ _webpack _require _ _ ( 3789 ) ;
var iterateSet = _ _webpack _require _ _ ( 8469 ) ;
var iterateSimple = _ _webpack _require _ _ ( 507 ) ;
var has = SetHelpers . has ;
var remove = SetHelpers . remove ;
// `Set.prototype.difference` method
// https://github.com/tc39/proposal-set-methods
module . exports = function difference ( other ) {
var O = aSet ( this ) ;
var otherRec = getSetRecord ( other ) ;
var result = clone ( O ) ;
if ( size ( O ) <= otherRec . size ) iterateSet ( O , function ( e ) {
if ( otherRec . includes ( e ) ) remove ( result , e ) ;
} ) ;
else iterateSimple ( otherRec . getIterator ( ) , function ( e ) {
if ( has ( O , e ) ) remove ( result , e ) ;
} ) ;
return result ;
} ;
/***/ } ) ,
/***/ 4402 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var uncurryThis = _ _webpack _require _ _ ( 9504 ) ;
// eslint-disable-next-line es/no-set -- safe
var SetPrototype = Set . prototype ;
module . exports = {
// eslint-disable-next-line es/no-set -- safe
Set : Set ,
add : uncurryThis ( SetPrototype . add ) ,
has : uncurryThis ( SetPrototype . has ) ,
remove : uncurryThis ( SetPrototype [ 'delete' ] ) ,
proto : SetPrototype
} ;
/***/ } ) ,
/***/ 8750 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var aSet = _ _webpack _require _ _ ( 7080 ) ;
var SetHelpers = _ _webpack _require _ _ ( 4402 ) ;
var size = _ _webpack _require _ _ ( 5170 ) ;
var getSetRecord = _ _webpack _require _ _ ( 3789 ) ;
var iterateSet = _ _webpack _require _ _ ( 8469 ) ;
var iterateSimple = _ _webpack _require _ _ ( 507 ) ;
var Set = SetHelpers . Set ;
var add = SetHelpers . add ;
var has = SetHelpers . has ;
// `Set.prototype.intersection` method
// https://github.com/tc39/proposal-set-methods
module . exports = function intersection ( other ) {
var O = aSet ( this ) ;
var otherRec = getSetRecord ( other ) ;
var result = new Set ( ) ;
if ( size ( O ) > otherRec . size ) {
iterateSimple ( otherRec . getIterator ( ) , function ( e ) {
if ( has ( O , e ) ) add ( result , e ) ;
} ) ;
} else {
iterateSet ( O , function ( e ) {
if ( otherRec . includes ( e ) ) add ( result , e ) ;
} ) ;
}
return result ;
} ;
/***/ } ) ,
/***/ 4449 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var aSet = _ _webpack _require _ _ ( 7080 ) ;
var has = ( _ _webpack _require _ _ ( 4402 ) . has ) ;
var size = _ _webpack _require _ _ ( 5170 ) ;
var getSetRecord = _ _webpack _require _ _ ( 3789 ) ;
var iterateSet = _ _webpack _require _ _ ( 8469 ) ;
var iterateSimple = _ _webpack _require _ _ ( 507 ) ;
var iteratorClose = _ _webpack _require _ _ ( 9539 ) ;
// `Set.prototype.isDisjointFrom` method
// https://tc39.github.io/proposal-set-methods/#Set.prototype.isDisjointFrom
module . exports = function isDisjointFrom ( other ) {
var O = aSet ( this ) ;
var otherRec = getSetRecord ( other ) ;
if ( size ( O ) <= otherRec . size ) return iterateSet ( O , function ( e ) {
if ( otherRec . includes ( e ) ) return false ;
} , true ) !== false ;
var iterator = otherRec . getIterator ( ) ;
return iterateSimple ( iterator , function ( e ) {
if ( has ( O , e ) ) return iteratorClose ( iterator , 'normal' , false ) ;
} ) !== false ;
} ;
/***/ } ) ,
/***/ 3838 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var aSet = _ _webpack _require _ _ ( 7080 ) ;
var size = _ _webpack _require _ _ ( 5170 ) ;
var iterate = _ _webpack _require _ _ ( 8469 ) ;
var getSetRecord = _ _webpack _require _ _ ( 3789 ) ;
// `Set.prototype.isSubsetOf` method
// https://tc39.github.io/proposal-set-methods/#Set.prototype.isSubsetOf
module . exports = function isSubsetOf ( other ) {
var O = aSet ( this ) ;
var otherRec = getSetRecord ( other ) ;
if ( size ( O ) > otherRec . size ) return false ;
return iterate ( O , function ( e ) {
if ( ! otherRec . includes ( e ) ) return false ;
} , true ) !== false ;
} ;
/***/ } ) ,
/***/ 8527 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var aSet = _ _webpack _require _ _ ( 7080 ) ;
var has = ( _ _webpack _require _ _ ( 4402 ) . has ) ;
var size = _ _webpack _require _ _ ( 5170 ) ;
var getSetRecord = _ _webpack _require _ _ ( 3789 ) ;
var iterateSimple = _ _webpack _require _ _ ( 507 ) ;
var iteratorClose = _ _webpack _require _ _ ( 9539 ) ;
// `Set.prototype.isSupersetOf` method
// https://tc39.github.io/proposal-set-methods/#Set.prototype.isSupersetOf
module . exports = function isSupersetOf ( other ) {
var O = aSet ( this ) ;
var otherRec = getSetRecord ( other ) ;
if ( size ( O ) < otherRec . size ) return false ;
var iterator = otherRec . getIterator ( ) ;
return iterateSimple ( iterator , function ( e ) {
if ( ! has ( O , e ) ) return iteratorClose ( iterator , 'normal' , false ) ;
} ) !== false ;
} ;
/***/ } ) ,
/***/ 8469 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var uncurryThis = _ _webpack _require _ _ ( 9504 ) ;
var iterateSimple = _ _webpack _require _ _ ( 507 ) ;
var SetHelpers = _ _webpack _require _ _ ( 4402 ) ;
var Set = SetHelpers . Set ;
var SetPrototype = SetHelpers . proto ;
var forEach = uncurryThis ( SetPrototype . forEach ) ;
var keys = uncurryThis ( SetPrototype . keys ) ;
var next = keys ( new Set ( ) ) . next ;
module . exports = function ( set , fn , interruptible ) {
return interruptible ? iterateSimple ( { iterator : keys ( set ) , next : next } , fn ) : forEach ( set , fn ) ;
} ;
/***/ } ) ,
/***/ 4916 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var getBuiltIn = _ _webpack _require _ _ ( 7751 ) ;
var createSetLike = function ( size ) {
return {
size : size ,
has : function ( ) {
return false ;
} ,
keys : function ( ) {
return {
next : function ( ) {
return { done : true } ;
}
} ;
}
} ;
} ;
module . exports = function ( name ) {
var Set = getBuiltIn ( 'Set' ) ;
try {
new Set ( ) [ name ] ( createSetLike ( 0 ) ) ;
try {
// late spec change, early WebKit ~ Safari 17.0 beta implementation does not pass it
// https://github.com/tc39/proposal-set-methods/pull/88
new Set ( ) [ name ] ( createSetLike ( - 1 ) ) ;
return false ;
} catch ( error2 ) {
return true ;
}
} catch ( error ) {
return false ;
}
} ;
/***/ } ) ,
/***/ 5170 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var uncurryThisAccessor = _ _webpack _require _ _ ( 6706 ) ;
var SetHelpers = _ _webpack _require _ _ ( 4402 ) ;
module . exports = uncurryThisAccessor ( SetHelpers . proto , 'size' , 'get' ) || function ( set ) {
return set . size ;
} ;
/***/ } ) ,
/***/ 3650 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var aSet = _ _webpack _require _ _ ( 7080 ) ;
var SetHelpers = _ _webpack _require _ _ ( 4402 ) ;
var clone = _ _webpack _require _ _ ( 9286 ) ;
var getSetRecord = _ _webpack _require _ _ ( 3789 ) ;
var iterateSimple = _ _webpack _require _ _ ( 507 ) ;
var add = SetHelpers . add ;
var has = SetHelpers . has ;
var remove = SetHelpers . remove ;
// `Set.prototype.symmetricDifference` method
// https://github.com/tc39/proposal-set-methods
module . exports = function symmetricDifference ( other ) {
var O = aSet ( this ) ;
var keysIter = getSetRecord ( other ) . getIterator ( ) ;
var result = clone ( O ) ;
iterateSimple ( keysIter , function ( e ) {
if ( has ( O , e ) ) remove ( result , e ) ;
else add ( result , e ) ;
} ) ;
return result ;
} ;
/***/ } ) ,
/***/ 4204 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var aSet = _ _webpack _require _ _ ( 7080 ) ;
var add = ( _ _webpack _require _ _ ( 4402 ) . add ) ;
var clone = _ _webpack _require _ _ ( 9286 ) ;
var getSetRecord = _ _webpack _require _ _ ( 3789 ) ;
var iterateSimple = _ _webpack _require _ _ ( 507 ) ;
// `Set.prototype.union` method
// https://github.com/tc39/proposal-set-methods
module . exports = function union ( other ) {
var O = aSet ( this ) ;
var keysIter = getSetRecord ( other ) . getIterator ( ) ;
var result = clone ( O ) ;
iterateSimple ( keysIter , function ( it ) {
add ( result , it ) ;
} ) ;
return result ;
} ;
/***/ } ) ,
/***/ 6119 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var shared = _ _webpack _require _ _ ( 5745 ) ;
var uid = _ _webpack _require _ _ ( 3392 ) ;
var keys = shared ( 'keys' ) ;
module . exports = function ( key ) {
return keys [ key ] || ( keys [ key ] = uid ( key ) ) ;
} ;
/***/ } ) ,
/***/ 7629 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var IS _PURE = _ _webpack _require _ _ ( 6395 ) ;
var globalThis = _ _webpack _require _ _ ( 4475 ) ;
var defineGlobalProperty = _ _webpack _require _ _ ( 9433 ) ;
var SHARED = '__core-js_shared__' ;
var store = module . exports = globalThis [ SHARED ] || defineGlobalProperty ( SHARED , { } ) ;
( store . versions || ( store . versions = [ ] ) ) . push ( {
version : '3.37.1' ,
mode : IS _PURE ? 'pure' : 'global' ,
copyright : '© 2014-2024 Denis Pushkarev (zloirock.ru)' ,
license : 'https://github.com/zloirock/core-js/blob/v3.37.1/LICENSE' ,
source : 'https://github.com/zloirock/core-js'
} ) ;
/***/ } ) ,
/***/ 5745 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var store = _ _webpack _require _ _ ( 7629 ) ;
module . exports = function ( key , value ) {
return store [ key ] || ( store [ key ] = value || { } ) ;
} ;
/***/ } ) ,
/***/ 1548 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var global = _ _webpack _require _ _ ( 4475 ) ;
var fails = _ _webpack _require _ _ ( 9039 ) ;
var V8 = _ _webpack _require _ _ ( 7388 ) ;
var IS _BROWSER = _ _webpack _require _ _ ( 7290 ) ;
var IS _DENO = _ _webpack _require _ _ ( 516 ) ;
var IS _NODE = _ _webpack _require _ _ ( 9088 ) ;
var structuredClone = global . structuredClone ;
module . exports = ! ! structuredClone && ! fails ( function ( ) {
// prevent V8 ArrayBufferDetaching protector cell invalidation and performance degradation
// https://github.com/zloirock/core-js/issues/679
if ( ( IS _DENO && V8 > 92 ) || ( IS _NODE && V8 > 94 ) || ( IS _BROWSER && V8 > 97 ) ) return false ;
var buffer = new ArrayBuffer ( 8 ) ;
var clone = structuredClone ( buffer , { transfer : [ buffer ] } ) ;
return buffer . byteLength !== 0 || clone . byteLength !== 8 ;
} ) ;
/***/ } ) ,
/***/ 4495 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
/* eslint-disable es/no-symbol -- required for testing */
var V8 _VERSION = _ _webpack _require _ _ ( 7388 ) ;
var fails = _ _webpack _require _ _ ( 9039 ) ;
var global = _ _webpack _require _ _ ( 4475 ) ;
var $String = global . String ;
// eslint-disable-next-line es/no-object-getownpropertysymbols -- required for testing
module . exports = ! ! Object . getOwnPropertySymbols && ! fails ( function ( ) {
var symbol = Symbol ( 'symbol detection' ) ;
// Chrome 38 Symbol has incorrect toString conversion
// `get-own-property-symbols` polyfill symbols converted to object are not Symbol instances
// nb: Do not call `String` directly to avoid this being optimized out to `symbol+''` which will,
// of course, fail.
return ! $String ( symbol ) || ! ( Object ( symbol ) instanceof Symbol ) ||
// Chrome 38-40 symbols are not inherited from DOM collections prototypes to instances
! Symbol . sham && V8 _VERSION && V8 _VERSION < 41 ;
} ) ;
/***/ } ) ,
/***/ 5610 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var toIntegerOrInfinity = _ _webpack _require _ _ ( 1291 ) ;
var max = Math . max ;
var min = Math . min ;
// Helper for a popular repeating case of the spec:
// Let integer be ? ToInteger(index).
// If integer < 0, let result be max((length + integer), 0); else let result be min(integer, length).
module . exports = function ( index , length ) {
var integer = toIntegerOrInfinity ( index ) ;
return integer < 0 ? max ( integer + length , 0 ) : min ( integer , length ) ;
} ;
/***/ } ) ,
/***/ 5854 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var toPrimitive = _ _webpack _require _ _ ( 2777 ) ;
var $TypeError = TypeError ;
// `ToBigInt` abstract operation
// https://tc39.es/ecma262/#sec-tobigint
module . exports = function ( argument ) {
var prim = toPrimitive ( argument , 'number' ) ;
if ( typeof prim == 'number' ) throw new $TypeError ( "Can't convert number to bigint" ) ;
// eslint-disable-next-line es/no-bigint -- safe
return BigInt ( prim ) ;
} ;
/***/ } ) ,
/***/ 7696 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var toIntegerOrInfinity = _ _webpack _require _ _ ( 1291 ) ;
var toLength = _ _webpack _require _ _ ( 8014 ) ;
var $RangeError = RangeError ;
// `ToIndex` abstract operation
// https://tc39.es/ecma262/#sec-toindex
module . exports = function ( it ) {
if ( it === undefined ) return 0 ;
var number = toIntegerOrInfinity ( it ) ;
var length = toLength ( number ) ;
if ( number !== length ) throw new $RangeError ( 'Wrong length or index' ) ;
return length ;
} ;
/***/ } ) ,
/***/ 5397 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
// toObject with fallback for non-array-like ES3 strings
var IndexedObject = _ _webpack _require _ _ ( 7055 ) ;
var requireObjectCoercible = _ _webpack _require _ _ ( 7750 ) ;
module . exports = function ( it ) {
return IndexedObject ( requireObjectCoercible ( it ) ) ;
} ;
/***/ } ) ,
/***/ 1291 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var trunc = _ _webpack _require _ _ ( 741 ) ;
// `ToIntegerOrInfinity` abstract operation
// https://tc39.es/ecma262/#sec-tointegerorinfinity
module . exports = function ( argument ) {
var number = + argument ;
// eslint-disable-next-line no-self-compare -- NaN check
return number !== number || number === 0 ? 0 : trunc ( number ) ;
} ;
/***/ } ) ,
/***/ 8014 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var toIntegerOrInfinity = _ _webpack _require _ _ ( 1291 ) ;
var min = Math . min ;
// `ToLength` abstract operation
// https://tc39.es/ecma262/#sec-tolength
module . exports = function ( argument ) {
var len = toIntegerOrInfinity ( argument ) ;
return len > 0 ? min ( len , 0x1FFFFFFFFFFFFF ) : 0 ; // 2 ** 53 - 1 == 9007199254740991
} ;
/***/ } ) ,
/***/ 8981 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var requireObjectCoercible = _ _webpack _require _ _ ( 7750 ) ;
var $Object = Object ;
// `ToObject` abstract operation
// https://tc39.es/ecma262/#sec-toobject
module . exports = function ( argument ) {
return $Object ( requireObjectCoercible ( argument ) ) ;
} ;
/***/ } ) ,
/***/ 9590 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var toIntegerOrInfinity = _ _webpack _require _ _ ( 1291 ) ;
var $RangeError = RangeError ;
module . exports = function ( it ) {
var result = toIntegerOrInfinity ( it ) ;
if ( result < 0 ) throw new $RangeError ( "The argument can't be less than 0" ) ;
return result ;
} ;
/***/ } ) ,
/***/ 2777 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var call = _ _webpack _require _ _ ( 9565 ) ;
var isObject = _ _webpack _require _ _ ( 34 ) ;
var isSymbol = _ _webpack _require _ _ ( 757 ) ;
var getMethod = _ _webpack _require _ _ ( 5966 ) ;
var ordinaryToPrimitive = _ _webpack _require _ _ ( 4270 ) ;
var wellKnownSymbol = _ _webpack _require _ _ ( 8227 ) ;
var $TypeError = TypeError ;
var TO _PRIMITIVE = wellKnownSymbol ( 'toPrimitive' ) ;
// `ToPrimitive` abstract operation
// https://tc39.es/ecma262/#sec-toprimitive
module . exports = function ( input , pref ) {
if ( ! isObject ( input ) || isSymbol ( input ) ) return input ;
var exoticToPrim = getMethod ( input , TO _PRIMITIVE ) ;
var result ;
if ( exoticToPrim ) {
if ( pref === undefined ) pref = 'default' ;
result = call ( exoticToPrim , input , pref ) ;
if ( ! isObject ( result ) || isSymbol ( result ) ) return result ;
throw new $TypeError ( "Can't convert object to primitive value" ) ;
}
if ( pref === undefined ) pref = 'number' ;
return ordinaryToPrimitive ( input , pref ) ;
} ;
/***/ } ) ,
/***/ 6969 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var toPrimitive = _ _webpack _require _ _ ( 2777 ) ;
var isSymbol = _ _webpack _require _ _ ( 757 ) ;
// `ToPropertyKey` abstract operation
// https://tc39.es/ecma262/#sec-topropertykey
module . exports = function ( argument ) {
var key = toPrimitive ( argument , 'string' ) ;
return isSymbol ( key ) ? key : key + '' ;
} ;
/***/ } ) ,
/***/ 2140 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var wellKnownSymbol = _ _webpack _require _ _ ( 8227 ) ;
var TO _STRING _TAG = wellKnownSymbol ( 'toStringTag' ) ;
var test = { } ;
test [ TO _STRING _TAG ] = 'z' ;
module . exports = String ( test ) === '[object z]' ;
/***/ } ) ,
/***/ 655 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var classof = _ _webpack _require _ _ ( 6955 ) ;
var $String = String ;
module . exports = function ( argument ) {
if ( classof ( argument ) === 'Symbol' ) throw new TypeError ( 'Cannot convert a Symbol value to a string' ) ;
return $String ( argument ) ;
} ;
/***/ } ) ,
/***/ 9714 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var IS _NODE = _ _webpack _require _ _ ( 9088 ) ;
module . exports = function ( name ) {
try {
// eslint-disable-next-line no-new-func -- safe
if ( IS _NODE ) return Function ( 'return require("' + name + '")' ) ( ) ;
} catch ( error ) { /* empty */ }
} ;
/***/ } ) ,
/***/ 6823 :
/***/ ( ( module ) => {
var $String = String ;
module . exports = function ( argument ) {
try {
return $String ( argument ) ;
} catch ( error ) {
return 'Object' ;
}
} ;
/***/ } ) ,
/***/ 3392 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var uncurryThis = _ _webpack _require _ _ ( 9504 ) ;
var id = 0 ;
var postfix = Math . random ( ) ;
var toString = uncurryThis ( 1.0 . toString ) ;
module . exports = function ( key ) {
return 'Symbol(' + ( key === undefined ? '' : key ) + ')_' + toString ( ++ id + postfix , 36 ) ;
} ;
/***/ } ) ,
/***/ 7040 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
/* eslint-disable es/no-symbol -- required for testing */
var NATIVE _SYMBOL = _ _webpack _require _ _ ( 4495 ) ;
module . exports = NATIVE _SYMBOL
&& ! Symbol . sham
&& typeof Symbol . iterator == 'symbol' ;
/***/ } ) ,
/***/ 8686 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var DESCRIPTORS = _ _webpack _require _ _ ( 3724 ) ;
var fails = _ _webpack _require _ _ ( 9039 ) ;
// V8 ~ Chrome 36-
// https://bugs.chromium.org/p/v8/issues/detail?id=3334
module . exports = DESCRIPTORS && fails ( function ( ) {
// eslint-disable-next-line es/no-object-defineproperty -- required for testing
return Object . defineProperty ( function ( ) { /* empty */ } , 'prototype' , {
value : 42 ,
writable : false
} ) . prototype !== 42 ;
} ) ;
/***/ } ) ,
/***/ 2812 :
/***/ ( ( module ) => {
var $TypeError = TypeError ;
module . exports = function ( passed , required ) {
if ( passed < required ) throw new $TypeError ( 'Not enough arguments' ) ;
return passed ;
} ;
/***/ } ) ,
/***/ 8622 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var global = _ _webpack _require _ _ ( 4475 ) ;
var isCallable = _ _webpack _require _ _ ( 4901 ) ;
var WeakMap = global . WeakMap ;
module . exports = isCallable ( WeakMap ) && /native code/ . test ( String ( WeakMap ) ) ;
/***/ } ) ,
/***/ 8227 :
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var global = _ _webpack _require _ _ ( 4475 ) ;
var shared = _ _webpack _require _ _ ( 5745 ) ;
var hasOwn = _ _webpack _require _ _ ( 9297 ) ;
var uid = _ _webpack _require _ _ ( 3392 ) ;
var NATIVE _SYMBOL = _ _webpack _require _ _ ( 4495 ) ;
var USE _SYMBOL _AS _UID = _ _webpack _require _ _ ( 7040 ) ;
var Symbol = global . Symbol ;
var WellKnownSymbolsStore = shared ( 'wks' ) ;
var createWellKnownSymbol = USE _SYMBOL _AS _UID ? Symbol [ 'for' ] || Symbol : Symbol && Symbol . withoutSetter || uid ;
module . exports = function ( name ) {
if ( ! hasOwn ( WellKnownSymbolsStore , name ) ) {
WellKnownSymbolsStore [ name ] = NATIVE _SYMBOL && hasOwn ( Symbol , name )
? Symbol [ name ]
: createWellKnownSymbol ( 'Symbol.' + name ) ;
} return WellKnownSymbolsStore [ name ] ;
} ;
/***/ } ) ,
/***/ 6573 :
/***/ ( ( _ _unused _webpack _module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var DESCRIPTORS = _ _webpack _require _ _ ( 3724 ) ;
var defineBuiltInAccessor = _ _webpack _require _ _ ( 2106 ) ;
var isDetached = _ _webpack _require _ _ ( 3238 ) ;
var ArrayBufferPrototype = ArrayBuffer . prototype ;
if ( DESCRIPTORS && ! ( 'detached' in ArrayBufferPrototype ) ) {
defineBuiltInAccessor ( ArrayBufferPrototype , 'detached' , {
configurable : true ,
get : function detached ( ) {
return isDetached ( this ) ;
}
} ) ;
}
/***/ } ) ,
/***/ 7936 :
/***/ ( ( _ _unused _webpack _module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var $ = _ _webpack _require _ _ ( 6518 ) ;
var $transfer = _ _webpack _require _ _ ( 5636 ) ;
// `ArrayBuffer.prototype.transferToFixedLength` method
// https://tc39.es/proposal-arraybuffer-transfer/#sec-arraybuffer.prototype.transfertofixedlength
if ( $transfer ) $ ( { target : 'ArrayBuffer' , proto : true } , {
transferToFixedLength : function transferToFixedLength ( ) {
return $transfer ( this , arguments . length ? arguments [ 0 ] : undefined , false ) ;
}
} ) ;
/***/ } ) ,
/***/ 8100 :
/***/ ( ( _ _unused _webpack _module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var $ = _ _webpack _require _ _ ( 6518 ) ;
var $transfer = _ _webpack _require _ _ ( 5636 ) ;
// `ArrayBuffer.prototype.transfer` method
// https://tc39.es/proposal-arraybuffer-transfer/#sec-arraybuffer.prototype.transfer
if ( $transfer ) $ ( { target : 'ArrayBuffer' , proto : true } , {
transfer : function transfer ( ) {
return $transfer ( this , arguments . length ? arguments [ 0 ] : undefined , true ) ;
}
} ) ;
/***/ } ) ,
/***/ 4114 :
/***/ ( ( _ _unused _webpack _module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var $ = _ _webpack _require _ _ ( 6518 ) ;
var toObject = _ _webpack _require _ _ ( 8981 ) ;
var lengthOfArrayLike = _ _webpack _require _ _ ( 6198 ) ;
var setArrayLength = _ _webpack _require _ _ ( 4527 ) ;
var doesNotExceedSafeInteger = _ _webpack _require _ _ ( 6837 ) ;
var fails = _ _webpack _require _ _ ( 9039 ) ;
var INCORRECT _TO _LENGTH = fails ( function ( ) {
return [ ] . push . call ( { length : 0x100000000 } , 1 ) !== 4294967297 ;
} ) ;
// V8 <= 121 and Safari <= 15.4; FF < 23 throws InternalError
// https://bugs.chromium.org/p/v8/issues/detail?id=12681
var properErrorOnNonWritableLength = function ( ) {
try {
// eslint-disable-next-line es/no-object-defineproperty -- safe
Object . defineProperty ( [ ] , 'length' , { writable : false } ) . push ( ) ;
} catch ( error ) {
return error instanceof TypeError ;
}
} ;
var FORCED = INCORRECT _TO _LENGTH || ! properErrorOnNonWritableLength ( ) ;
// `Array.prototype.push` method
// https://tc39.es/ecma262/#sec-array.prototype.push
$ ( { target : 'Array' , proto : true , arity : 1 , forced : FORCED } , {
// eslint-disable-next-line no-unused-vars -- required for `.length`
push : function push ( item ) {
var O = toObject ( this ) ;
var len = lengthOfArrayLike ( O ) ;
var argCount = arguments . length ;
doesNotExceedSafeInteger ( len + argCount ) ;
for ( var i = 0 ; i < argCount ; i ++ ) {
O [ len ] = arguments [ i ] ;
len ++ ;
}
setArrayLength ( O , len ) ;
return len ;
}
} ) ;
/***/ } ) ,
/***/ 4628 :
/***/ ( ( _ _unused _webpack _module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var $ = _ _webpack _require _ _ ( 6518 ) ;
var newPromiseCapabilityModule = _ _webpack _require _ _ ( 6043 ) ;
// `Promise.withResolvers` method
// https://github.com/tc39/proposal-promise-with-resolvers
$ ( { target : 'Promise' , stat : true } , {
withResolvers : function withResolvers ( ) {
var promiseCapability = newPromiseCapabilityModule . f ( this ) ;
return {
promise : promiseCapability . promise ,
resolve : promiseCapability . resolve ,
reject : promiseCapability . reject
} ;
}
} ) ;
/***/ } ) ,
/***/ 7642 :
/***/ ( ( _ _unused _webpack _module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var $ = _ _webpack _require _ _ ( 6518 ) ;
var difference = _ _webpack _require _ _ ( 3440 ) ;
var setMethodAcceptSetLike = _ _webpack _require _ _ ( 4916 ) ;
// `Set.prototype.difference` method
// https://github.com/tc39/proposal-set-methods
$ ( { target : 'Set' , proto : true , real : true , forced : ! setMethodAcceptSetLike ( 'difference' ) } , {
difference : difference
} ) ;
/***/ } ) ,
/***/ 8004 :
/***/ ( ( _ _unused _webpack _module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var $ = _ _webpack _require _ _ ( 6518 ) ;
var fails = _ _webpack _require _ _ ( 9039 ) ;
var intersection = _ _webpack _require _ _ ( 8750 ) ;
var setMethodAcceptSetLike = _ _webpack _require _ _ ( 4916 ) ;
var INCORRECT = ! setMethodAcceptSetLike ( 'intersection' ) || fails ( function ( ) {
// eslint-disable-next-line es/no-array-from, es/no-set -- testing
return String ( Array . from ( new Set ( [ 1 , 2 , 3 ] ) . intersection ( new Set ( [ 3 , 2 ] ) ) ) ) !== '3,2' ;
} ) ;
// `Set.prototype.intersection` method
// https://github.com/tc39/proposal-set-methods
$ ( { target : 'Set' , proto : true , real : true , forced : INCORRECT } , {
intersection : intersection
} ) ;
/***/ } ) ,
/***/ 3853 :
/***/ ( ( _ _unused _webpack _module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var $ = _ _webpack _require _ _ ( 6518 ) ;
var isDisjointFrom = _ _webpack _require _ _ ( 4449 ) ;
var setMethodAcceptSetLike = _ _webpack _require _ _ ( 4916 ) ;
// `Set.prototype.isDisjointFrom` method
// https://github.com/tc39/proposal-set-methods
$ ( { target : 'Set' , proto : true , real : true , forced : ! setMethodAcceptSetLike ( 'isDisjointFrom' ) } , {
isDisjointFrom : isDisjointFrom
} ) ;
/***/ } ) ,
/***/ 5876 :
/***/ ( ( _ _unused _webpack _module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var $ = _ _webpack _require _ _ ( 6518 ) ;
var isSubsetOf = _ _webpack _require _ _ ( 3838 ) ;
var setMethodAcceptSetLike = _ _webpack _require _ _ ( 4916 ) ;
// `Set.prototype.isSubsetOf` method
// https://github.com/tc39/proposal-set-methods
$ ( { target : 'Set' , proto : true , real : true , forced : ! setMethodAcceptSetLike ( 'isSubsetOf' ) } , {
isSubsetOf : isSubsetOf
} ) ;
/***/ } ) ,
/***/ 2475 :
/***/ ( ( _ _unused _webpack _module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var $ = _ _webpack _require _ _ ( 6518 ) ;
var isSupersetOf = _ _webpack _require _ _ ( 8527 ) ;
var setMethodAcceptSetLike = _ _webpack _require _ _ ( 4916 ) ;
// `Set.prototype.isSupersetOf` method
// https://github.com/tc39/proposal-set-methods
$ ( { target : 'Set' , proto : true , real : true , forced : ! setMethodAcceptSetLike ( 'isSupersetOf' ) } , {
isSupersetOf : isSupersetOf
} ) ;
/***/ } ) ,
/***/ 5024 :
/***/ ( ( _ _unused _webpack _module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var $ = _ _webpack _require _ _ ( 6518 ) ;
var symmetricDifference = _ _webpack _require _ _ ( 3650 ) ;
var setMethodAcceptSetLike = _ _webpack _require _ _ ( 4916 ) ;
// `Set.prototype.symmetricDifference` method
// https://github.com/tc39/proposal-set-methods
$ ( { target : 'Set' , proto : true , real : true , forced : ! setMethodAcceptSetLike ( 'symmetricDifference' ) } , {
symmetricDifference : symmetricDifference
} ) ;
/***/ } ) ,
/***/ 1698 :
/***/ ( ( _ _unused _webpack _module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var $ = _ _webpack _require _ _ ( 6518 ) ;
var union = _ _webpack _require _ _ ( 4204 ) ;
var setMethodAcceptSetLike = _ _webpack _require _ _ ( 4916 ) ;
// `Set.prototype.union` method
// https://github.com/tc39/proposal-set-methods
$ ( { target : 'Set' , proto : true , real : true , forced : ! setMethodAcceptSetLike ( 'union' ) } , {
union : union
} ) ;
/***/ } ) ,
/***/ 7467 :
/***/ ( ( _ _unused _webpack _module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var arrayToReversed = _ _webpack _require _ _ ( 7628 ) ;
var ArrayBufferViewCore = _ _webpack _require _ _ ( 4644 ) ;
var aTypedArray = ArrayBufferViewCore . aTypedArray ;
var exportTypedArrayMethod = ArrayBufferViewCore . exportTypedArrayMethod ;
var getTypedArrayConstructor = ArrayBufferViewCore . getTypedArrayConstructor ;
// `%TypedArray%.prototype.toReversed` method
// https://tc39.es/ecma262/#sec-%typedarray%.prototype.toreversed
exportTypedArrayMethod ( 'toReversed' , function toReversed ( ) {
return arrayToReversed ( aTypedArray ( this ) , getTypedArrayConstructor ( this ) ) ;
} ) ;
/***/ } ) ,
/***/ 4732 :
/***/ ( ( _ _unused _webpack _module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var ArrayBufferViewCore = _ _webpack _require _ _ ( 4644 ) ;
var uncurryThis = _ _webpack _require _ _ ( 9504 ) ;
var aCallable = _ _webpack _require _ _ ( 9306 ) ;
var arrayFromConstructorAndList = _ _webpack _require _ _ ( 5370 ) ;
var aTypedArray = ArrayBufferViewCore . aTypedArray ;
var getTypedArrayConstructor = ArrayBufferViewCore . getTypedArrayConstructor ;
var exportTypedArrayMethod = ArrayBufferViewCore . exportTypedArrayMethod ;
var sort = uncurryThis ( ArrayBufferViewCore . TypedArrayPrototype . sort ) ;
// `%TypedArray%.prototype.toSorted` method
// https://tc39.es/ecma262/#sec-%typedarray%.prototype.tosorted
exportTypedArrayMethod ( 'toSorted' , function toSorted ( compareFn ) {
if ( compareFn !== undefined ) aCallable ( compareFn ) ;
var O = aTypedArray ( this ) ;
var A = arrayFromConstructorAndList ( getTypedArrayConstructor ( O ) , O ) ;
return sort ( A , compareFn ) ;
} ) ;
/***/ } ) ,
/***/ 9577 :
/***/ ( ( _ _unused _webpack _module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var arrayWith = _ _webpack _require _ _ ( 9928 ) ;
var ArrayBufferViewCore = _ _webpack _require _ _ ( 4644 ) ;
var isBigIntArray = _ _webpack _require _ _ ( 1108 ) ;
var toIntegerOrInfinity = _ _webpack _require _ _ ( 1291 ) ;
var toBigInt = _ _webpack _require _ _ ( 5854 ) ;
var aTypedArray = ArrayBufferViewCore . aTypedArray ;
var getTypedArrayConstructor = ArrayBufferViewCore . getTypedArrayConstructor ;
var exportTypedArrayMethod = ArrayBufferViewCore . exportTypedArrayMethod ;
var PROPER _ORDER = ! ! function ( ) {
try {
// eslint-disable-next-line no-throw-literal, es/no-typed-arrays, es/no-array-prototype-with -- required for testing
new Int8Array ( 1 ) [ 'with' ] ( 2 , { valueOf : function ( ) { throw 8 ; } } ) ;
} catch ( error ) {
// some early implementations, like WebKit, does not follow the final semantic
// https://github.com/tc39/proposal-change-array-by-copy/pull/86
return error === 8 ;
}
} ( ) ;
// `%TypedArray%.prototype.with` method
// https://tc39.es/ecma262/#sec-%typedarray%.prototype.with
exportTypedArrayMethod ( 'with' , { 'with' : function ( index , value ) {
var O = aTypedArray ( this ) ;
var relativeIndex = toIntegerOrInfinity ( index ) ;
var actualValue = isBigIntArray ( O ) ? toBigInt ( value ) : + value ;
return arrayWith ( O , getTypedArrayConstructor ( O ) , relativeIndex , actualValue ) ;
} } [ 'with' ] , ! PROPER _ORDER ) ;
/***/ } ) ,
/***/ 8992 :
/***/ ( ( _ _unused _webpack _module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var $ = _ _webpack _require _ _ ( 6518 ) ;
var global = _ _webpack _require _ _ ( 4475 ) ;
var anInstance = _ _webpack _require _ _ ( 679 ) ;
var anObject = _ _webpack _require _ _ ( 8551 ) ;
var isCallable = _ _webpack _require _ _ ( 4901 ) ;
var getPrototypeOf = _ _webpack _require _ _ ( 2787 ) ;
var defineBuiltInAccessor = _ _webpack _require _ _ ( 2106 ) ;
var createProperty = _ _webpack _require _ _ ( 4659 ) ;
var fails = _ _webpack _require _ _ ( 9039 ) ;
var hasOwn = _ _webpack _require _ _ ( 9297 ) ;
var wellKnownSymbol = _ _webpack _require _ _ ( 8227 ) ;
var IteratorPrototype = ( _ _webpack _require _ _ ( 7657 ) . IteratorPrototype ) ;
var DESCRIPTORS = _ _webpack _require _ _ ( 3724 ) ;
var IS _PURE = _ _webpack _require _ _ ( 6395 ) ;
var CONSTRUCTOR = 'constructor' ;
var ITERATOR = 'Iterator' ;
var TO _STRING _TAG = wellKnownSymbol ( 'toStringTag' ) ;
var $TypeError = TypeError ;
var NativeIterator = global [ ITERATOR ] ;
// FF56- have non-standard global helper `Iterator`
var FORCED = IS _PURE
|| ! isCallable ( NativeIterator )
|| NativeIterator . prototype !== IteratorPrototype
// FF44- non-standard `Iterator` passes previous tests
|| ! fails ( function ( ) { NativeIterator ( { } ) ; } ) ;
var IteratorConstructor = function Iterator ( ) {
anInstance ( this , IteratorPrototype ) ;
if ( getPrototypeOf ( this ) === IteratorPrototype ) throw new $TypeError ( 'Abstract class Iterator not directly constructable' ) ;
} ;
var defineIteratorPrototypeAccessor = function ( key , value ) {
if ( DESCRIPTORS ) {
defineBuiltInAccessor ( IteratorPrototype , key , {
configurable : true ,
get : function ( ) {
return value ;
} ,
set : function ( replacement ) {
anObject ( this ) ;
if ( this === IteratorPrototype ) throw new $TypeError ( "You can't redefine this property" ) ;
if ( hasOwn ( this , key ) ) this [ key ] = replacement ;
else createProperty ( this , key , replacement ) ;
}
} ) ;
} else IteratorPrototype [ key ] = value ;
} ;
if ( ! hasOwn ( IteratorPrototype , TO _STRING _TAG ) ) defineIteratorPrototypeAccessor ( TO _STRING _TAG , ITERATOR ) ;
if ( FORCED || ! hasOwn ( IteratorPrototype , CONSTRUCTOR ) || IteratorPrototype [ CONSTRUCTOR ] === Object ) {
defineIteratorPrototypeAccessor ( CONSTRUCTOR , IteratorConstructor ) ;
}
IteratorConstructor . prototype = IteratorPrototype ;
// `Iterator` constructor
// https://github.com/tc39/proposal-iterator-helpers
$ ( { global : true , constructor : true , forced : FORCED } , {
Iterator : IteratorConstructor
} ) ;
/***/ } ) ,
/***/ 4743 :
/***/ ( ( _ _unused _webpack _module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var $ = _ _webpack _require _ _ ( 6518 ) ;
var call = _ _webpack _require _ _ ( 9565 ) ;
var anObject = _ _webpack _require _ _ ( 8551 ) ;
var getIteratorDirect = _ _webpack _require _ _ ( 1767 ) ;
var notANaN = _ _webpack _require _ _ ( 4149 ) ;
var toPositiveInteger = _ _webpack _require _ _ ( 9590 ) ;
var createIteratorProxy = _ _webpack _require _ _ ( 9462 ) ;
var IS _PURE = _ _webpack _require _ _ ( 6395 ) ;
var IteratorProxy = createIteratorProxy ( function ( ) {
var iterator = this . iterator ;
var next = this . next ;
var result , done ;
while ( this . remaining ) {
this . remaining -- ;
result = anObject ( call ( next , iterator ) ) ;
done = this . done = ! ! result . done ;
if ( done ) return ;
}
result = anObject ( call ( next , iterator ) ) ;
done = this . done = ! ! result . done ;
if ( ! done ) return result . value ;
} ) ;
// `Iterator.prototype.drop` method
// https://github.com/tc39/proposal-iterator-helpers
$ ( { target : 'Iterator' , proto : true , real : true , forced : IS _PURE } , {
drop : function drop ( limit ) {
anObject ( this ) ;
var remaining = toPositiveInteger ( notANaN ( + limit ) ) ;
return new IteratorProxy ( getIteratorDirect ( this ) , {
remaining : remaining
} ) ;
}
} ) ;
/***/ } ) ,
/***/ 3215 :
/***/ ( ( _ _unused _webpack _module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var $ = _ _webpack _require _ _ ( 6518 ) ;
var iterate = _ _webpack _require _ _ ( 2652 ) ;
var aCallable = _ _webpack _require _ _ ( 9306 ) ;
var anObject = _ _webpack _require _ _ ( 8551 ) ;
var getIteratorDirect = _ _webpack _require _ _ ( 1767 ) ;
// `Iterator.prototype.every` method
// https://github.com/tc39/proposal-iterator-helpers
$ ( { target : 'Iterator' , proto : true , real : true } , {
every : function every ( predicate ) {
anObject ( this ) ;
aCallable ( predicate ) ;
var record = getIteratorDirect ( this ) ;
var counter = 0 ;
return ! iterate ( record , function ( value , stop ) {
if ( ! predicate ( value , counter ++ ) ) return stop ( ) ;
} , { IS _RECORD : true , INTERRUPTED : true } ) . stopped ;
}
} ) ;
/***/ } ) ,
/***/ 4520 :
/***/ ( ( _ _unused _webpack _module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var $ = _ _webpack _require _ _ ( 6518 ) ;
var call = _ _webpack _require _ _ ( 9565 ) ;
var aCallable = _ _webpack _require _ _ ( 9306 ) ;
var anObject = _ _webpack _require _ _ ( 8551 ) ;
var getIteratorDirect = _ _webpack _require _ _ ( 1767 ) ;
var createIteratorProxy = _ _webpack _require _ _ ( 9462 ) ;
var callWithSafeIterationClosing = _ _webpack _require _ _ ( 6319 ) ;
var IS _PURE = _ _webpack _require _ _ ( 6395 ) ;
var IteratorProxy = createIteratorProxy ( function ( ) {
var iterator = this . iterator ;
var predicate = this . predicate ;
var next = this . next ;
var result , done , value ;
while ( true ) {
result = anObject ( call ( next , iterator ) ) ;
done = this . done = ! ! result . done ;
if ( done ) return ;
value = result . value ;
if ( callWithSafeIterationClosing ( iterator , predicate , [ value , this . counter ++ ] , true ) ) return value ;
}
} ) ;
// `Iterator.prototype.filter` method
// https://github.com/tc39/proposal-iterator-helpers
$ ( { target : 'Iterator' , proto : true , real : true , forced : IS _PURE } , {
filter : function filter ( predicate ) {
anObject ( this ) ;
aCallable ( predicate ) ;
return new IteratorProxy ( getIteratorDirect ( this ) , {
predicate : predicate
} ) ;
}
} ) ;
/***/ } ) ,
/***/ 670 :
/***/ ( ( _ _unused _webpack _module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var $ = _ _webpack _require _ _ ( 6518 ) ;
var call = _ _webpack _require _ _ ( 9565 ) ;
var aCallable = _ _webpack _require _ _ ( 9306 ) ;
var anObject = _ _webpack _require _ _ ( 8551 ) ;
var getIteratorDirect = _ _webpack _require _ _ ( 1767 ) ;
var getIteratorFlattenable = _ _webpack _require _ _ ( 8646 ) ;
var createIteratorProxy = _ _webpack _require _ _ ( 9462 ) ;
var iteratorClose = _ _webpack _require _ _ ( 9539 ) ;
var IS _PURE = _ _webpack _require _ _ ( 6395 ) ;
var IteratorProxy = createIteratorProxy ( function ( ) {
var iterator = this . iterator ;
var mapper = this . mapper ;
var result , inner ;
while ( true ) {
if ( inner = this . inner ) try {
result = anObject ( call ( inner . next , inner . iterator ) ) ;
if ( ! result . done ) return result . value ;
this . inner = null ;
} catch ( error ) { iteratorClose ( iterator , 'throw' , error ) ; }
result = anObject ( call ( this . next , iterator ) ) ;
if ( this . done = ! ! result . done ) return ;
try {
this . inner = getIteratorFlattenable ( mapper ( result . value , this . counter ++ ) , false ) ;
} catch ( error ) { iteratorClose ( iterator , 'throw' , error ) ; }
}
} ) ;
// `Iterator.prototype.flatMap` method
// https://github.com/tc39/proposal-iterator-helpers
$ ( { target : 'Iterator' , proto : true , real : true , forced : IS _PURE } , {
flatMap : function flatMap ( mapper ) {
anObject ( this ) ;
aCallable ( mapper ) ;
return new IteratorProxy ( getIteratorDirect ( this ) , {
mapper : mapper ,
inner : null
} ) ;
}
} ) ;
/***/ } ) ,
/***/ 1454 :
/***/ ( ( _ _unused _webpack _module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var $ = _ _webpack _require _ _ ( 6518 ) ;
var map = _ _webpack _require _ _ ( 713 ) ;
var IS _PURE = _ _webpack _require _ _ ( 6395 ) ;
// `Iterator.prototype.map` method
// https://github.com/tc39/proposal-iterator-helpers
$ ( { target : 'Iterator' , proto : true , real : true , forced : IS _PURE } , {
map : map
} ) ;
/***/ } ) ,
/***/ 7550 :
/***/ ( ( _ _unused _webpack _module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var $ = _ _webpack _require _ _ ( 6518 ) ;
var iterate = _ _webpack _require _ _ ( 2652 ) ;
var aCallable = _ _webpack _require _ _ ( 9306 ) ;
var anObject = _ _webpack _require _ _ ( 8551 ) ;
var getIteratorDirect = _ _webpack _require _ _ ( 1767 ) ;
// `Iterator.prototype.some` method
// https://github.com/tc39/proposal-iterator-helpers
$ ( { target : 'Iterator' , proto : true , real : true } , {
some : function some ( predicate ) {
anObject ( this ) ;
aCallable ( predicate ) ;
var record = getIteratorDirect ( this ) ;
var counter = 0 ;
return iterate ( record , function ( value , stop ) {
if ( predicate ( value , counter ++ ) ) return stop ( ) ;
} , { IS _RECORD : true , INTERRUPTED : true } ) . stopped ;
}
} ) ;
/***/ } ) ,
/***/ 8335 :
/***/ ( ( _ _unused _webpack _module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var $ = _ _webpack _require _ _ ( 6518 ) ;
var DESCRIPTORS = _ _webpack _require _ _ ( 3724 ) ;
var global = _ _webpack _require _ _ ( 4475 ) ;
var getBuiltIn = _ _webpack _require _ _ ( 7751 ) ;
var uncurryThis = _ _webpack _require _ _ ( 9504 ) ;
var call = _ _webpack _require _ _ ( 9565 ) ;
var isCallable = _ _webpack _require _ _ ( 4901 ) ;
var isObject = _ _webpack _require _ _ ( 34 ) ;
var isArray = _ _webpack _require _ _ ( 4376 ) ;
var hasOwn = _ _webpack _require _ _ ( 9297 ) ;
var toString = _ _webpack _require _ _ ( 655 ) ;
var lengthOfArrayLike = _ _webpack _require _ _ ( 6198 ) ;
var createProperty = _ _webpack _require _ _ ( 4659 ) ;
var fails = _ _webpack _require _ _ ( 9039 ) ;
var parseJSONString = _ _webpack _require _ _ ( 8235 ) ;
var NATIVE _SYMBOL = _ _webpack _require _ _ ( 4495 ) ;
var JSON = global . JSON ;
var Number = global . Number ;
var SyntaxError = global . SyntaxError ;
var nativeParse = JSON && JSON . parse ;
var enumerableOwnProperties = getBuiltIn ( 'Object' , 'keys' ) ;
// eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
var getOwnPropertyDescriptor = Object . getOwnPropertyDescriptor ;
var at = uncurryThis ( '' . charAt ) ;
var slice = uncurryThis ( '' . slice ) ;
var exec = uncurryThis ( /./ . exec ) ;
var push = uncurryThis ( [ ] . push ) ;
var IS _DIGIT = /^\d$/ ;
var IS _NON _ZERO _DIGIT = /^[1-9]$/ ;
var IS _NUMBER _START = /^(?:-|\d)$/ ;
var IS _WHITESPACE = /^[\t\n\r ]$/ ;
var PRIMITIVE = 0 ;
var OBJECT = 1 ;
var $parse = function ( source , reviver ) {
source = toString ( source ) ;
var context = new Context ( source , 0 , '' ) ;
var root = context . parse ( ) ;
var value = root . value ;
var endIndex = context . skip ( IS _WHITESPACE , root . end ) ;
if ( endIndex < source . length ) {
throw new SyntaxError ( 'Unexpected extra character: "' + at ( source , endIndex ) + '" after the parsed data at: ' + endIndex ) ;
}
return isCallable ( reviver ) ? internalize ( { '' : value } , '' , reviver , root ) : value ;
} ;
var internalize = function ( holder , name , reviver , node ) {
var val = holder [ name ] ;
var unmodified = node && val === node . value ;
var context = unmodified && typeof node . source == 'string' ? { source : node . source } : { } ;
var elementRecordsLen , keys , len , i , P ;
if ( isObject ( val ) ) {
var nodeIsArray = isArray ( val ) ;
var nodes = unmodified ? node . nodes : nodeIsArray ? [ ] : { } ;
if ( nodeIsArray ) {
elementRecordsLen = nodes . length ;
len = lengthOfArrayLike ( val ) ;
for ( i = 0 ; i < len ; i ++ ) {
internalizeProperty ( val , i , internalize ( val , '' + i , reviver , i < elementRecordsLen ? nodes [ i ] : undefined ) ) ;
}
} else {
keys = enumerableOwnProperties ( val ) ;
len = lengthOfArrayLike ( keys ) ;
for ( i = 0 ; i < len ; i ++ ) {
P = keys [ i ] ;
internalizeProperty ( val , P , internalize ( val , P , reviver , hasOwn ( nodes , P ) ? nodes [ P ] : undefined ) ) ;
}
}
}
return call ( reviver , holder , name , val , context ) ;
} ;
var internalizeProperty = function ( object , key , value ) {
if ( DESCRIPTORS ) {
var descriptor = getOwnPropertyDescriptor ( object , key ) ;
if ( descriptor && ! descriptor . configurable ) return ;
}
if ( value === undefined ) delete object [ key ] ;
else createProperty ( object , key , value ) ;
} ;
var Node = function ( value , end , source , nodes ) {
this . value = value ;
this . end = end ;
this . source = source ;
this . nodes = nodes ;
} ;
var Context = function ( source , index ) {
this . source = source ;
this . index = index ;
} ;
// https://www.json.org/json-en.html
Context . prototype = {
fork : function ( nextIndex ) {
return new Context ( this . source , nextIndex ) ;
} ,
parse : function ( ) {
var source = this . source ;
var i = this . skip ( IS _WHITESPACE , this . index ) ;
var fork = this . fork ( i ) ;
var chr = at ( source , i ) ;
if ( exec ( IS _NUMBER _START , chr ) ) return fork . number ( ) ;
switch ( chr ) {
case '{' :
return fork . object ( ) ;
case '[' :
return fork . array ( ) ;
case '"' :
return fork . string ( ) ;
case 't' :
return fork . keyword ( true ) ;
case 'f' :
return fork . keyword ( false ) ;
case 'n' :
return fork . keyword ( null ) ;
} throw new SyntaxError ( 'Unexpected character: "' + chr + '" at: ' + i ) ;
} ,
node : function ( type , value , start , end , nodes ) {
return new Node ( value , end , type ? null : slice ( this . source , start , end ) , nodes ) ;
} ,
object : function ( ) {
var source = this . source ;
var i = this . index + 1 ;
var expectKeypair = false ;
var object = { } ;
var nodes = { } ;
while ( i < source . length ) {
i = this . until ( [ '"' , '}' ] , i ) ;
if ( at ( source , i ) === '}' && ! expectKeypair ) {
i ++ ;
break ;
}
// Parsing the key
var result = this . fork ( i ) . string ( ) ;
var key = result . value ;
i = result . end ;
i = this . until ( [ ':' ] , i ) + 1 ;
// Parsing value
i = this . skip ( IS _WHITESPACE , i ) ;
result = this . fork ( i ) . parse ( ) ;
createProperty ( nodes , key , result ) ;
createProperty ( object , key , result . value ) ;
i = this . until ( [ ',' , '}' ] , result . end ) ;
var chr = at ( source , i ) ;
if ( chr === ',' ) {
expectKeypair = true ;
i ++ ;
} else if ( chr === '}' ) {
i ++ ;
break ;
}
}
return this . node ( OBJECT , object , this . index , i , nodes ) ;
} ,
array : function ( ) {
var source = this . source ;
var i = this . index + 1 ;
var expectElement = false ;
var array = [ ] ;
var nodes = [ ] ;
while ( i < source . length ) {
i = this . skip ( IS _WHITESPACE , i ) ;
if ( at ( source , i ) === ']' && ! expectElement ) {
i ++ ;
break ;
}
var result = this . fork ( i ) . parse ( ) ;
push ( nodes , result ) ;
push ( array , result . value ) ;
i = this . until ( [ ',' , ']' ] , result . end ) ;
if ( at ( source , i ) === ',' ) {
expectElement = true ;
i ++ ;
} else if ( at ( source , i ) === ']' ) {
i ++ ;
break ;
}
}
return this . node ( OBJECT , array , this . index , i , nodes ) ;
} ,
string : function ( ) {
var index = this . index ;
var parsed = parseJSONString ( this . source , this . index + 1 ) ;
return this . node ( PRIMITIVE , parsed . value , index , parsed . end ) ;
} ,
number : function ( ) {
var source = this . source ;
var startIndex = this . index ;
var i = startIndex ;
if ( at ( source , i ) === '-' ) i ++ ;
if ( at ( source , i ) === '0' ) i ++ ;
else if ( exec ( IS _NON _ZERO _DIGIT , at ( source , i ) ) ) i = this . skip ( IS _DIGIT , ++ i ) ;
else throw new SyntaxError ( 'Failed to parse number at: ' + i ) ;
if ( at ( source , i ) === '.' ) i = this . skip ( IS _DIGIT , ++ i ) ;
if ( at ( source , i ) === 'e' || at ( source , i ) === 'E' ) {
i ++ ;
if ( at ( source , i ) === '+' || at ( source , i ) === '-' ) i ++ ;
var exponentStartIndex = i ;
i = this . skip ( IS _DIGIT , i ) ;
if ( exponentStartIndex === i ) throw new SyntaxError ( "Failed to parse number's exponent value at: " + i ) ;
}
return this . node ( PRIMITIVE , Number ( slice ( source , startIndex , i ) ) , startIndex , i ) ;
} ,
keyword : function ( value ) {
var keyword = '' + value ;
var index = this . index ;
var endIndex = index + keyword . length ;
if ( slice ( this . source , index , endIndex ) !== keyword ) throw new SyntaxError ( 'Failed to parse value at: ' + index ) ;
return this . node ( PRIMITIVE , value , index , endIndex ) ;
} ,
skip : function ( regex , i ) {
var source = this . source ;
for ( ; i < source . length ; i ++ ) if ( ! exec ( regex , at ( source , i ) ) ) break ;
return i ;
} ,
until : function ( array , i ) {
i = this . skip ( IS _WHITESPACE , i ) ;
var chr = at ( this . source , i ) ;
for ( var j = 0 ; j < array . length ; j ++ ) if ( array [ j ] === chr ) return i ;
throw new SyntaxError ( 'Unexpected character: "' + chr + '" at: ' + i ) ;
}
} ;
var NO _SOURCE _SUPPORT = fails ( function ( ) {
var unsafeInt = '9007199254740993' ;
var source ;
nativeParse ( unsafeInt , function ( key , value , context ) {
source = context . source ;
} ) ;
return source !== unsafeInt ;
} ) ;
var PROPER _BASE _PARSE = NATIVE _SYMBOL && ! fails ( function ( ) {
// Safari 9 bug
return 1 / nativeParse ( '-0 \t' ) !== - Infinity ;
} ) ;
// `JSON.parse` method
// https://tc39.es/ecma262/#sec-json.parse
// https://github.com/tc39/proposal-json-parse-with-source
$ ( { target : 'JSON' , stat : true , forced : NO _SOURCE _SUPPORT } , {
parse : function parse ( text , reviver ) {
return PROPER _BASE _PARSE && ! isCallable ( reviver ) ? nativeParse ( text ) : $parse ( text , reviver ) ;
}
} ) ;
/***/ } ) ,
/***/ 3375 :
/***/ ( ( _ _unused _webpack _module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
// TODO: Remove from `core-js@4`
_ _webpack _require _ _ ( 7642 ) ;
/***/ } ) ,
/***/ 9225 :
/***/ ( ( _ _unused _webpack _module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
// TODO: Remove from `core-js@4`
_ _webpack _require _ _ ( 8004 ) ;
/***/ } ) ,
/***/ 3972 :
/***/ ( ( _ _unused _webpack _module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
// TODO: Remove from `core-js@4`
_ _webpack _require _ _ ( 3853 ) ;
/***/ } ) ,
/***/ 9209 :
/***/ ( ( _ _unused _webpack _module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
// TODO: Remove from `core-js@4`
_ _webpack _require _ _ ( 5876 ) ;
/***/ } ) ,
/***/ 5714 :
/***/ ( ( _ _unused _webpack _module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
// TODO: Remove from `core-js@4`
_ _webpack _require _ _ ( 2475 ) ;
/***/ } ) ,
/***/ 7561 :
/***/ ( ( _ _unused _webpack _module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
// TODO: Remove from `core-js@4`
_ _webpack _require _ _ ( 5024 ) ;
/***/ } ) ,
/***/ 6197 :
/***/ ( ( _ _unused _webpack _module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
// TODO: Remove from `core-js@4`
_ _webpack _require _ _ ( 1698 ) ;
/***/ } ) ,
/***/ 4979 :
/***/ ( ( _ _unused _webpack _module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var $ = _ _webpack _require _ _ ( 6518 ) ;
var global = _ _webpack _require _ _ ( 4475 ) ;
var getBuiltIn = _ _webpack _require _ _ ( 7751 ) ;
var createPropertyDescriptor = _ _webpack _require _ _ ( 6980 ) ;
var defineProperty = ( _ _webpack _require _ _ ( 4913 ) . f ) ;
var hasOwn = _ _webpack _require _ _ ( 9297 ) ;
var anInstance = _ _webpack _require _ _ ( 679 ) ;
var inheritIfRequired = _ _webpack _require _ _ ( 3167 ) ;
var normalizeStringArgument = _ _webpack _require _ _ ( 2603 ) ;
var DOMExceptionConstants = _ _webpack _require _ _ ( 5002 ) ;
var clearErrorStack = _ _webpack _require _ _ ( 6193 ) ;
var DESCRIPTORS = _ _webpack _require _ _ ( 3724 ) ;
var IS _PURE = _ _webpack _require _ _ ( 6395 ) ;
var DOM _EXCEPTION = 'DOMException' ;
var Error = getBuiltIn ( 'Error' ) ;
var NativeDOMException = getBuiltIn ( DOM _EXCEPTION ) ;
var $DOMException = function DOMException ( ) {
anInstance ( this , DOMExceptionPrototype ) ;
var argumentsLength = arguments . length ;
var message = normalizeStringArgument ( argumentsLength < 1 ? undefined : arguments [ 0 ] ) ;
var name = normalizeStringArgument ( argumentsLength < 2 ? undefined : arguments [ 1 ] , 'Error' ) ;
var that = new NativeDOMException ( message , name ) ;
var error = new Error ( message ) ;
error . name = DOM _EXCEPTION ;
defineProperty ( that , 'stack' , createPropertyDescriptor ( 1 , clearErrorStack ( error . stack , 1 ) ) ) ;
inheritIfRequired ( that , this , $DOMException ) ;
return that ;
} ;
var DOMExceptionPrototype = $DOMException . prototype = NativeDOMException . prototype ;
var ERROR _HAS _STACK = 'stack' in new Error ( DOM _EXCEPTION ) ;
var DOM _EXCEPTION _HAS _STACK = 'stack' in new NativeDOMException ( 1 , 2 ) ;
// eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
var descriptor = NativeDOMException && DESCRIPTORS && Object . getOwnPropertyDescriptor ( global , DOM _EXCEPTION ) ;
// Bun ~ 0.1.1 DOMException have incorrect descriptor and we can't redefine it
// https://github.com/Jarred-Sumner/bun/issues/399
var BUGGY _DESCRIPTOR = ! ! descriptor && ! ( descriptor . writable && descriptor . configurable ) ;
var FORCED _CONSTRUCTOR = ERROR _HAS _STACK && ! BUGGY _DESCRIPTOR && ! DOM _EXCEPTION _HAS _STACK ;
// `DOMException` constructor patch for `.stack` where it's required
// https://webidl.spec.whatwg.org/#es-DOMException-specialness
$ ( { global : true , constructor : true , forced : IS _PURE || FORCED _CONSTRUCTOR } , { // TODO: fix export logic
DOMException : FORCED _CONSTRUCTOR ? $DOMException : NativeDOMException
} ) ;
var PolyfilledDOMException = getBuiltIn ( DOM _EXCEPTION ) ;
var PolyfilledDOMExceptionPrototype = PolyfilledDOMException . prototype ;
if ( PolyfilledDOMExceptionPrototype . constructor !== PolyfilledDOMException ) {
if ( ! IS _PURE ) {
defineProperty ( PolyfilledDOMExceptionPrototype , 'constructor' , createPropertyDescriptor ( 1 , PolyfilledDOMException ) ) ;
}
for ( var key in DOMExceptionConstants ) if ( hasOwn ( DOMExceptionConstants , key ) ) {
var constant = DOMExceptionConstants [ key ] ;
var constantName = constant . s ;
if ( ! hasOwn ( PolyfilledDOMException , constantName ) ) {
defineProperty ( PolyfilledDOMException , constantName , createPropertyDescriptor ( 6 , constant . c ) ) ;
}
}
}
/***/ } ) ,
/***/ 4603 :
/***/ ( ( _ _unused _webpack _module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var defineBuiltIn = _ _webpack _require _ _ ( 6840 ) ;
var uncurryThis = _ _webpack _require _ _ ( 9504 ) ;
var toString = _ _webpack _require _ _ ( 655 ) ;
var validateArgumentsLength = _ _webpack _require _ _ ( 2812 ) ;
var $URLSearchParams = URLSearchParams ;
var URLSearchParamsPrototype = $URLSearchParams . prototype ;
var append = uncurryThis ( URLSearchParamsPrototype . append ) ;
var $delete = uncurryThis ( URLSearchParamsPrototype [ 'delete' ] ) ;
var forEach = uncurryThis ( URLSearchParamsPrototype . forEach ) ;
var push = uncurryThis ( [ ] . push ) ;
var params = new $URLSearchParams ( 'a=1&a=2&b=3' ) ;
params [ 'delete' ] ( 'a' , 1 ) ;
// `undefined` case is a Chromium 117 bug
// https://bugs.chromium.org/p/v8/issues/detail?id=14222
params [ 'delete' ] ( 'b' , undefined ) ;
if ( params + '' !== 'a=2' ) {
defineBuiltIn ( URLSearchParamsPrototype , 'delete' , function ( name /* , value */ ) {
var length = arguments . length ;
var $value = length < 2 ? undefined : arguments [ 1 ] ;
if ( length && $value === undefined ) return $delete ( this , name ) ;
var entries = [ ] ;
forEach ( this , function ( v , k ) { // also validates `this`
push ( entries , { key : k , value : v } ) ;
} ) ;
validateArgumentsLength ( length , 1 ) ;
var key = toString ( name ) ;
var value = toString ( $value ) ;
var index = 0 ;
var dindex = 0 ;
var found = false ;
var entriesLength = entries . length ;
var entry ;
while ( index < entriesLength ) {
entry = entries [ index ++ ] ;
if ( found || entry . key === key ) {
found = true ;
$delete ( this , entry . key ) ;
} else dindex ++ ;
}
while ( dindex < entriesLength ) {
entry = entries [ dindex ++ ] ;
if ( ! ( entry . key === key && entry . value === value ) ) append ( this , entry . key , entry . value ) ;
}
} , { enumerable : true , unsafe : true } ) ;
}
/***/ } ) ,
/***/ 7566 :
/***/ ( ( _ _unused _webpack _module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var defineBuiltIn = _ _webpack _require _ _ ( 6840 ) ;
var uncurryThis = _ _webpack _require _ _ ( 9504 ) ;
var toString = _ _webpack _require _ _ ( 655 ) ;
var validateArgumentsLength = _ _webpack _require _ _ ( 2812 ) ;
var $URLSearchParams = URLSearchParams ;
var URLSearchParamsPrototype = $URLSearchParams . prototype ;
var getAll = uncurryThis ( URLSearchParamsPrototype . getAll ) ;
var $has = uncurryThis ( URLSearchParamsPrototype . has ) ;
var params = new $URLSearchParams ( 'a=1' ) ;
// `undefined` case is a Chromium 117 bug
// https://bugs.chromium.org/p/v8/issues/detail?id=14222
if ( params . has ( 'a' , 2 ) || ! params . has ( 'a' , undefined ) ) {
defineBuiltIn ( URLSearchParamsPrototype , 'has' , function has ( name /* , value */ ) {
var length = arguments . length ;
var $value = length < 2 ? undefined : arguments [ 1 ] ;
if ( length && $value === undefined ) return $has ( this , name ) ;
var values = getAll ( this , name ) ; // also validates `this`
validateArgumentsLength ( length , 1 ) ;
var value = toString ( $value ) ;
var index = 0 ;
while ( index < values . length ) {
if ( values [ index ++ ] === value ) return true ;
} return false ;
} , { enumerable : true , unsafe : true } ) ;
}
/***/ } ) ,
/***/ 8721 :
/***/ ( ( _ _unused _webpack _module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
var DESCRIPTORS = _ _webpack _require _ _ ( 3724 ) ;
var uncurryThis = _ _webpack _require _ _ ( 9504 ) ;
var defineBuiltInAccessor = _ _webpack _require _ _ ( 2106 ) ;
var URLSearchParamsPrototype = URLSearchParams . prototype ;
var forEach = uncurryThis ( URLSearchParamsPrototype . forEach ) ;
// `URLSearchParams.prototype.size` getter
// https://github.com/whatwg/url/pull/734
if ( DESCRIPTORS && ! ( 'size' in URLSearchParamsPrototype ) ) {
defineBuiltInAccessor ( URLSearchParamsPrototype , 'size' , {
get : function size ( ) {
var count = 0 ;
forEach ( this , function ( ) { count ++ ; } ) ;
return count ;
} ,
configurable : true ,
enumerable : true
} ) ;
}
/***/ } )
/******/ } ) ;
/************************************************************************/
/******/ // The module cache
/******/ var _ _webpack _module _cache _ _ = { } ;
/******/
/******/ // The require function
/******/ function _ _webpack _require _ _ ( moduleId ) {
/******/ // Check if module is in cache
/******/ var cachedModule = _ _webpack _module _cache _ _ [ moduleId ] ;
/******/ if ( cachedModule !== undefined ) {
/******/ return cachedModule . exports ;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = _ _webpack _module _cache _ _ [ moduleId ] = {
/******/ // no module.id needed
/******/ // no module.loaded needed
/******/ exports : { }
/******/ } ;
/******/
/******/ // Execute the module function
/******/ _ _webpack _modules _ _ [ moduleId ] . call ( module . exports , module , module . exports , _ _webpack _require _ _ ) ;
/******/
/******/ // Return the exports of the module
/******/ return module . exports ;
/******/ }
2024-06-01 11:00:27 +01:00
/******/
/************************************************************************/
/******/ /* webpack/runtime/define property getters */
/******/ ( ( ) => {
/******/ // define getter functions for harmony exports
/******/ _ _webpack _require _ _ . d = ( exports , definition ) => {
/******/ for ( var key in definition ) {
/******/ if ( _ _webpack _require _ _ . o ( definition , key ) && ! _ _webpack _require _ _ . o ( exports , key ) ) {
/******/ Object . defineProperty ( exports , key , { enumerable : true , get : definition [ key ] } ) ;
/******/ }
/******/ }
/******/ } ;
/******/ } ) ( ) ;
/******/
/******/ /* webpack/runtime/hasOwnProperty shorthand */
/******/ ( ( ) => {
/******/ _ _webpack _require _ _ . o = ( obj , prop ) => ( Object . prototype . hasOwnProperty . call ( obj , prop ) )
/******/ } ) ( ) ;
/******/
/************************************************************************/
var _ _webpack _exports _ _ = globalThis . pdfjsLib = { } ;
2024-06-18 20:06:52 +02:00
// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk.
( ( ) => {
2023-10-27 13:19:54 +02:00
2024-06-01 11:00:27 +01:00
// EXPORTS
_ _webpack _require _ _ . d ( _ _webpack _exports _ _ , {
AbortException : ( ) => ( /* reexport */ AbortException ) ,
AnnotationEditorLayer : ( ) => ( /* reexport */ AnnotationEditorLayer ) ,
AnnotationEditorParamsType : ( ) => ( /* reexport */ AnnotationEditorParamsType ) ,
AnnotationEditorType : ( ) => ( /* reexport */ AnnotationEditorType ) ,
AnnotationEditorUIManager : ( ) => ( /* reexport */ AnnotationEditorUIManager ) ,
AnnotationLayer : ( ) => ( /* reexport */ AnnotationLayer ) ,
AnnotationMode : ( ) => ( /* reexport */ AnnotationMode ) ,
CMapCompressionType : ( ) => ( /* reexport */ CMapCompressionType ) ,
ColorPicker : ( ) => ( /* reexport */ ColorPicker ) ,
DOMSVGFactory : ( ) => ( /* reexport */ DOMSVGFactory ) ,
DrawLayer : ( ) => ( /* reexport */ DrawLayer ) ,
FeatureTest : ( ) => ( /* reexport */ util _FeatureTest ) ,
GlobalWorkerOptions : ( ) => ( /* reexport */ GlobalWorkerOptions ) ,
ImageKind : ( ) => ( /* reexport */ util _ImageKind ) ,
InvalidPDFException : ( ) => ( /* reexport */ InvalidPDFException ) ,
MissingPDFException : ( ) => ( /* reexport */ MissingPDFException ) ,
OPS : ( ) => ( /* reexport */ OPS ) ,
Outliner : ( ) => ( /* reexport */ Outliner ) ,
PDFDataRangeTransport : ( ) => ( /* reexport */ PDFDataRangeTransport ) ,
PDFDateString : ( ) => ( /* reexport */ PDFDateString ) ,
PDFWorker : ( ) => ( /* reexport */ PDFWorker ) ,
PasswordResponses : ( ) => ( /* reexport */ PasswordResponses ) ,
PermissionFlag : ( ) => ( /* reexport */ PermissionFlag ) ,
PixelsPerInch : ( ) => ( /* reexport */ PixelsPerInch ) ,
RenderingCancelledException : ( ) => ( /* reexport */ RenderingCancelledException ) ,
TextLayer : ( ) => ( /* reexport */ TextLayer ) ,
UnexpectedResponseException : ( ) => ( /* reexport */ UnexpectedResponseException ) ,
Util : ( ) => ( /* reexport */ Util ) ,
VerbosityLevel : ( ) => ( /* reexport */ VerbosityLevel ) ,
XfaLayer : ( ) => ( /* reexport */ XfaLayer ) ,
build : ( ) => ( /* reexport */ build ) ,
createValidAbsoluteUrl : ( ) => ( /* reexport */ createValidAbsoluteUrl ) ,
fetchData : ( ) => ( /* reexport */ fetchData ) ,
getDocument : ( ) => ( /* reexport */ getDocument ) ,
getFilenameFromUrl : ( ) => ( /* reexport */ getFilenameFromUrl ) ,
getPdfFilenameFromUrl : ( ) => ( /* reexport */ getPdfFilenameFromUrl ) ,
getXfaPageViewport : ( ) => ( /* reexport */ getXfaPageViewport ) ,
isDataScheme : ( ) => ( /* reexport */ isDataScheme ) ,
isPdfFile : ( ) => ( /* reexport */ isPdfFile ) ,
noContextMenu : ( ) => ( /* reexport */ noContextMenu ) ,
normalizeUnicode : ( ) => ( /* reexport */ normalizeUnicode ) ,
renderTextLayer : ( ) => ( /* reexport */ renderTextLayer ) ,
setLayerDimensions : ( ) => ( /* reexport */ setLayerDimensions ) ,
shadow : ( ) => ( /* reexport */ shadow ) ,
updateTextLayer : ( ) => ( /* reexport */ updateTextLayer ) ,
version : ( ) => ( /* reexport */ version )
} ) ;
2023-10-27 13:19:54 +02:00
2024-06-18 20:06:52 +02:00
// EXTERNAL MODULE: ./node_modules/core-js/modules/es.array.push.js
var es _array _push = _ _webpack _require _ _ ( 4114 ) ;
// EXTERNAL MODULE: ./node_modules/core-js/modules/es.array-buffer.detached.js
var es _array _buffer _detached = _ _webpack _require _ _ ( 6573 ) ;
// EXTERNAL MODULE: ./node_modules/core-js/modules/es.array-buffer.transfer.js
var es _array _buffer _transfer = _ _webpack _require _ _ ( 8100 ) ;
// EXTERNAL MODULE: ./node_modules/core-js/modules/es.array-buffer.transfer-to-fixed-length.js
var es _array _buffer _transfer _to _fixed _length = _ _webpack _require _ _ ( 7936 ) ;
// EXTERNAL MODULE: ./node_modules/core-js/modules/es.typed-array.to-reversed.js
var es _typed _array _to _reversed = _ _webpack _require _ _ ( 7467 ) ;
// EXTERNAL MODULE: ./node_modules/core-js/modules/es.typed-array.to-sorted.js
var es _typed _array _to _sorted = _ _webpack _require _ _ ( 4732 ) ;
// EXTERNAL MODULE: ./node_modules/core-js/modules/es.typed-array.with.js
var es _typed _array _with = _ _webpack _require _ _ ( 9577 ) ;
// EXTERNAL MODULE: ./node_modules/core-js/modules/web.url-search-params.delete.js
var web _url _search _params _delete = _ _webpack _require _ _ ( 4603 ) ;
// EXTERNAL MODULE: ./node_modules/core-js/modules/web.url-search-params.has.js
var web _url _search _params _has = _ _webpack _require _ _ ( 7566 ) ;
// EXTERNAL MODULE: ./node_modules/core-js/modules/web.url-search-params.size.js
var web _url _search _params _size = _ _webpack _require _ _ ( 8721 ) ;
2024-06-01 11:00:27 +01:00
; // CONCATENATED MODULE: ./src/shared/util.js
2024-06-18 20:06:52 +02:00
2024-06-01 11:00:27 +01:00
const isNodeJS = typeof process === "object" && process + "" === "[object process]" && ! process . versions . nw && ! ( process . versions . electron && process . type && process . type !== "browser" ) ;
const IDENTITY _MATRIX = [ 1 , 0 , 0 , 1 , 0 , 0 ] ;
const FONT _IDENTITY _MATRIX = [ 0.001 , 0 , 0 , 0.001 , 0 , 0 ] ;
const MAX _IMAGE _SIZE _TO _CACHE = 10e6 ;
const LINE _FACTOR = 1.35 ;
const LINE _DESCENT _FACTOR = 0.35 ;
const BASELINE _FACTOR = LINE _DESCENT _FACTOR / LINE _FACTOR ;
const RenderingIntentFlag = {
2023-10-27 13:19:54 +02:00
ANY : 0x01 ,
DISPLAY : 0x02 ,
PRINT : 0x04 ,
SAVE : 0x08 ,
ANNOTATIONS _FORMS : 0x10 ,
ANNOTATIONS _STORAGE : 0x20 ,
ANNOTATIONS _DISABLE : 0x40 ,
OPLIST : 0x100
} ;
2024-06-01 11:00:27 +01:00
const AnnotationMode = {
2023-10-27 13:19:54 +02:00
DISABLE : 0 ,
ENABLE : 1 ,
ENABLE _FORMS : 2 ,
ENABLE _STORAGE : 3
} ;
2024-06-01 11:00:27 +01:00
const AnnotationEditorPrefix = "pdfjs_internal_editor_" ;
const AnnotationEditorType = {
2023-10-27 13:19:54 +02:00
DISABLE : - 1 ,
NONE : 0 ,
FREETEXT : 3 ,
2024-06-01 11:00:27 +01:00
HIGHLIGHT : 9 ,
2023-10-27 13:19:54 +02:00
STAMP : 13 ,
INK : 15
} ;
2024-06-01 11:00:27 +01:00
const AnnotationEditorParamsType = {
2023-10-27 13:19:54 +02:00
RESIZE : 1 ,
CREATE : 2 ,
FREETEXT _SIZE : 11 ,
FREETEXT _COLOR : 12 ,
FREETEXT _OPACITY : 13 ,
INK _COLOR : 21 ,
INK _THICKNESS : 22 ,
2024-06-01 11:00:27 +01:00
INK _OPACITY : 23 ,
HIGHLIGHT _COLOR : 31 ,
HIGHLIGHT _DEFAULT _COLOR : 32 ,
HIGHLIGHT _THICKNESS : 33 ,
HIGHLIGHT _FREE : 34 ,
HIGHLIGHT _SHOW _ALL : 35
2023-10-27 13:19:54 +02:00
} ;
2024-06-01 11:00:27 +01:00
const PermissionFlag = {
2023-10-27 13:19:54 +02:00
PRINT : 0x04 ,
MODIFY _CONTENTS : 0x08 ,
COPY : 0x10 ,
MODIFY _ANNOTATIONS : 0x20 ,
FILL _INTERACTIVE _FORMS : 0x100 ,
COPY _FOR _ACCESSIBILITY : 0x200 ,
ASSEMBLE : 0x400 ,
PRINT _HIGH _QUALITY : 0x800
} ;
2024-06-01 11:00:27 +01:00
const TextRenderingMode = {
2013-12-31 16:34:23 +05:30
FILL : 0 ,
STROKE : 1 ,
FILL _STROKE : 2 ,
INVISIBLE : 3 ,
FILL _ADD _TO _PATH : 4 ,
STROKE _ADD _TO _PATH : 5 ,
FILL _STROKE _ADD _TO _PATH : 6 ,
ADD _TO _PATH : 7 ,
FILL _STROKE _MASK : 3 ,
ADD _TO _PATH _FLAG : 4
} ;
2024-06-01 11:00:27 +01:00
const util _ImageKind = {
2014-11-24 00:56:52 +01:00
GRAYSCALE _1BPP : 1 ,
RGB _24BPP : 2 ,
RGBA _32BPP : 3
} ;
2024-06-01 11:00:27 +01:00
const AnnotationType = {
2016-04-04 15:49:28 +02:00
TEXT : 1 ,
LINK : 2 ,
FREETEXT : 3 ,
LINE : 4 ,
SQUARE : 5 ,
CIRCLE : 6 ,
POLYGON : 7 ,
POLYLINE : 8 ,
HIGHLIGHT : 9 ,
UNDERLINE : 10 ,
SQUIGGLY : 11 ,
STRIKEOUT : 12 ,
STAMP : 13 ,
CARET : 14 ,
INK : 15 ,
POPUP : 16 ,
FILEATTACHMENT : 17 ,
SOUND : 18 ,
MOVIE : 19 ,
WIDGET : 20 ,
SCREEN : 21 ,
PRINTERMARK : 22 ,
TRAPNET : 23 ,
WATERMARK : 24 ,
THREED : 25 ,
REDACT : 26
} ;
2024-06-01 11:00:27 +01:00
const AnnotationReplyType = {
2023-10-27 13:19:54 +02:00
GROUP : "Group" ,
REPLY : "R"
} ;
2024-06-01 11:00:27 +01:00
const AnnotationFlag = {
2016-04-04 15:49:28 +02:00
INVISIBLE : 0x01 ,
HIDDEN : 0x02 ,
PRINT : 0x04 ,
NOZOOM : 0x08 ,
NOROTATE : 0x10 ,
NOVIEW : 0x20 ,
READONLY : 0x40 ,
LOCKED : 0x80 ,
TOGGLENOVIEW : 0x100 ,
LOCKEDCONTENTS : 0x200
} ;
2024-06-01 11:00:27 +01:00
const AnnotationFieldFlag = {
2023-10-27 13:19:54 +02:00
READONLY : 0x0000001 ,
REQUIRED : 0x0000002 ,
NOEXPORT : 0x0000004 ,
MULTILINE : 0x0001000 ,
PASSWORD : 0x0002000 ,
NOTOGGLETOOFF : 0x0004000 ,
RADIO : 0x0008000 ,
PUSHBUTTON : 0x0010000 ,
COMBO : 0x0020000 ,
EDIT : 0x0040000 ,
SORT : 0x0080000 ,
FILESELECT : 0x0100000 ,
MULTISELECT : 0x0200000 ,
DONOTSPELLCHECK : 0x0400000 ,
DONOTSCROLL : 0x0800000 ,
COMB : 0x1000000 ,
RICHTEXT : 0x2000000 ,
RADIOSINUNISON : 0x2000000 ,
COMMITONSELCHANGE : 0x4000000
} ;
2024-06-01 11:00:27 +01:00
const AnnotationBorderStyleType = {
2016-04-04 15:49:28 +02:00
SOLID : 1 ,
DASHED : 2 ,
BEVELED : 3 ,
INSET : 4 ,
UNDERLINE : 5
2014-11-24 00:56:52 +01:00
} ;
2024-06-01 11:00:27 +01:00
const AnnotationActionEventType = {
2023-10-27 13:19:54 +02:00
E : "Mouse Enter" ,
X : "Mouse Exit" ,
D : "Mouse Down" ,
U : "Mouse Up" ,
Fo : "Focus" ,
Bl : "Blur" ,
PO : "PageOpen" ,
PC : "PageClose" ,
PV : "PageVisible" ,
PI : "PageInvisible" ,
K : "Keystroke" ,
F : "Format" ,
V : "Validate" ,
C : "Calculate"
2014-11-24 00:56:52 +01:00
} ;
2024-06-01 11:00:27 +01:00
const DocumentActionEventType = {
2023-10-27 13:19:54 +02:00
WC : "WillClose" ,
WS : "WillSave" ,
DS : "DidSave" ,
WP : "WillPrint" ,
DP : "DidPrint"
2014-11-24 00:56:52 +01:00
} ;
2024-06-01 11:00:27 +01:00
const PageActionEventType = {
2023-10-27 13:19:54 +02:00
O : "PageOpen" ,
C : "PageClose"
2014-01-09 14:05:57 +05:30
} ;
2024-06-01 11:00:27 +01:00
const VerbosityLevel = {
2023-10-27 13:19:54 +02:00
ERRORS : 0 ,
WARNINGS : 1 ,
INFOS : 5
} ;
2024-06-01 11:00:27 +01:00
const CMapCompressionType = {
2023-10-27 13:19:54 +02:00
NONE : 0 ,
BINARY : 1
} ;
2024-06-01 11:00:27 +01:00
const OPS = {
2013-12-31 16:34:23 +05:30
dependency : 1 ,
setLineWidth : 2 ,
setLineCap : 3 ,
setLineJoin : 4 ,
setMiterLimit : 5 ,
setDash : 6 ,
setRenderingIntent : 7 ,
setFlatness : 8 ,
setGState : 9 ,
save : 10 ,
restore : 11 ,
transform : 12 ,
moveTo : 13 ,
lineTo : 14 ,
curveTo : 15 ,
curveTo2 : 16 ,
curveTo3 : 17 ,
closePath : 18 ,
rectangle : 19 ,
stroke : 20 ,
closeStroke : 21 ,
fill : 22 ,
eoFill : 23 ,
fillStroke : 24 ,
eoFillStroke : 25 ,
closeFillStroke : 26 ,
closeEOFillStroke : 27 ,
endPath : 28 ,
clip : 29 ,
eoClip : 30 ,
beginText : 31 ,
endText : 32 ,
setCharSpacing : 33 ,
setWordSpacing : 34 ,
setHScale : 35 ,
setLeading : 36 ,
setFont : 37 ,
setTextRenderingMode : 38 ,
setTextRise : 39 ,
moveText : 40 ,
setLeadingMoveText : 41 ,
setTextMatrix : 42 ,
nextLine : 43 ,
showText : 44 ,
showSpacedText : 45 ,
nextLineShowText : 46 ,
nextLineSetSpacingShowText : 47 ,
setCharWidth : 48 ,
setCharWidthAndBounds : 49 ,
setStrokeColorSpace : 50 ,
setFillColorSpace : 51 ,
setStrokeColor : 52 ,
setStrokeColorN : 53 ,
setFillColor : 54 ,
setFillColorN : 55 ,
setStrokeGray : 56 ,
setFillGray : 57 ,
setStrokeRGBColor : 58 ,
setFillRGBColor : 59 ,
setStrokeCMYKColor : 60 ,
setFillCMYKColor : 61 ,
shadingFill : 62 ,
beginInlineImage : 63 ,
beginImageData : 64 ,
endInlineImage : 65 ,
paintXObject : 66 ,
markPoint : 67 ,
markPointProps : 68 ,
beginMarkedContent : 69 ,
beginMarkedContentProps : 70 ,
endMarkedContent : 71 ,
beginCompat : 72 ,
endCompat : 73 ,
paintFormXObjectBegin : 74 ,
paintFormXObjectEnd : 75 ,
beginGroup : 76 ,
endGroup : 77 ,
beginAnnotation : 80 ,
endAnnotation : 81 ,
paintImageMaskXObject : 83 ,
paintImageMaskXObjectGroup : 84 ,
paintImageXObject : 85 ,
paintInlineImageXObject : 86 ,
2014-11-24 00:56:52 +01:00
paintInlineImageXObjectGroup : 87 ,
paintImageXObjectRepeat : 88 ,
paintImageMaskXObjectRepeat : 89 ,
paintSolidColorImageMask : 90 ,
constructPath : 91
2013-12-31 16:34:23 +05:30
} ;
2024-06-01 11:00:27 +01:00
const PasswordResponses = {
2023-10-27 13:19:54 +02:00
NEED _PASSWORD : 1 ,
INCORRECT _PASSWORD : 2
} ;
let verbosity = VerbosityLevel . WARNINGS ;
2016-04-04 15:49:28 +02:00
function setVerbosityLevel ( level ) {
2023-10-27 13:19:54 +02:00
if ( Number . isInteger ( level ) ) {
verbosity = level ;
}
2016-04-04 15:49:28 +02:00
}
function getVerbosityLevel ( ) {
return verbosity ;
}
2013-02-21 14:09:23 +00:00
function info ( msg ) {
2023-10-27 13:19:54 +02:00
if ( verbosity >= VerbosityLevel . INFOS ) {
console . log ( ` Info: ${ msg } ` ) ;
2013-02-21 14:09:23 +00:00
}
}
function warn ( msg ) {
2023-10-27 13:19:54 +02:00
if ( verbosity >= VerbosityLevel . WARNINGS ) {
console . log ( ` Warning: ${ msg } ` ) ;
2013-02-21 14:09:23 +00:00
}
}
2023-10-27 13:19:54 +02:00
function unreachable ( msg ) {
2013-02-21 14:09:23 +00:00
throw new Error ( msg ) ;
}
function assert ( cond , msg ) {
2014-11-24 00:56:52 +01:00
if ( ! cond ) {
2023-10-27 13:19:54 +02:00
unreachable ( msg ) ;
2013-02-21 14:09:23 +00:00
}
}
2023-10-27 13:19:54 +02:00
function _isValidProtocol ( url ) {
switch ( url ? . protocol ) {
case "http:" :
case "https:" :
case "ftp:" :
case "mailto:" :
case "tel:" :
2013-12-31 16:34:23 +05:30
return true ;
default :
return false ;
}
}
2023-10-27 13:19:54 +02:00
function createValidAbsoluteUrl ( url , baseUrl = null , options = null ) {
if ( ! url ) {
return null ;
}
try {
if ( options && typeof url === "string" ) {
if ( options . addDefaultProtocol && url . startsWith ( "www." ) ) {
const dots = url . match ( /\./g ) ;
if ( dots ? . length >= 2 ) {
url = ` http:// ${ url } ` ;
}
}
if ( options . tryConvertEncoding ) {
try {
url = stringToUTF8String ( url ) ;
} catch { }
}
}
const absoluteUrl = baseUrl ? new URL ( url , baseUrl ) : new URL ( url ) ;
if ( _isValidProtocol ( absoluteUrl ) ) {
return absoluteUrl ;
}
} catch { }
return null ;
}
function shadow ( obj , prop , value , nonSerializable = false ) {
Object . defineProperty ( obj , prop , {
value ,
enumerable : ! nonSerializable ,
configurable : true ,
writable : false
} ) ;
2013-02-21 14:09:23 +00:00
return value ;
}
2024-06-01 11:00:27 +01:00
const BaseException = function BaseExceptionClosure ( ) {
2023-10-27 13:19:54 +02:00
function BaseException ( message , name ) {
if ( this . constructor === BaseException ) {
unreachable ( "Cannot initialize BaseException." ) ;
2016-04-04 15:49:28 +02:00
}
2023-10-27 13:19:54 +02:00
this . message = message ;
this . name = name ;
}
BaseException . prototype = new Error ( ) ;
BaseException . constructor = BaseException ;
return BaseException ;
} ( ) ;
class PasswordException extends BaseException {
constructor ( msg , code ) {
super ( msg , "PasswordException" ) ;
2013-02-21 14:09:23 +00:00
this . code = code ;
}
2023-10-27 13:19:54 +02:00
}
class UnknownErrorException extends BaseException {
constructor ( msg , details ) {
super ( msg , "UnknownErrorException" ) ;
2013-02-21 14:09:23 +00:00
this . details = details ;
}
2023-10-27 13:19:54 +02:00
}
class InvalidPDFException extends BaseException {
constructor ( msg ) {
super ( msg , "InvalidPDFException" ) ;
2013-02-21 14:09:23 +00:00
}
2023-10-27 13:19:54 +02:00
}
class MissingPDFException extends BaseException {
constructor ( msg ) {
super ( msg , "MissingPDFException" ) ;
2013-02-21 14:09:23 +00:00
}
2023-10-27 13:19:54 +02:00
}
class UnexpectedResponseException extends BaseException {
constructor ( msg , status ) {
super ( msg , "UnexpectedResponseException" ) ;
2014-11-24 00:56:52 +01:00
this . status = status ;
}
2023-10-27 13:19:54 +02:00
}
class FormatError extends BaseException {
constructor ( msg ) {
super ( msg , "FormatError" ) ;
2013-03-03 08:22:46 +00:00
}
2023-10-27 13:19:54 +02:00
}
class AbortException extends BaseException {
constructor ( msg ) {
super ( msg , "AbortException" ) ;
2016-04-04 15:49:28 +02:00
}
}
2013-02-21 14:09:23 +00:00
function bytesToString ( bytes ) {
2023-10-27 13:19:54 +02:00
if ( typeof bytes !== "object" || bytes ? . length === undefined ) {
unreachable ( "Invalid argument for bytesToString" ) ;
}
const length = bytes . length ;
const MAX _ARGUMENT _COUNT = 8192 ;
2014-11-24 00:56:52 +01:00
if ( length < MAX _ARGUMENT _COUNT ) {
return String . fromCharCode . apply ( null , bytes ) ;
}
2023-10-27 13:19:54 +02:00
const strBuf = [ ] ;
for ( let i = 0 ; i < length ; i += MAX _ARGUMENT _COUNT ) {
const chunkEnd = Math . min ( i + MAX _ARGUMENT _COUNT , length ) ;
const chunk = bytes . subarray ( i , chunkEnd ) ;
2014-11-24 00:56:52 +01:00
strBuf . push ( String . fromCharCode . apply ( null , chunk ) ) ;
}
2023-10-27 13:19:54 +02:00
return strBuf . join ( "" ) ;
2013-02-21 14:09:23 +00:00
}
function stringToBytes ( str ) {
2023-10-27 13:19:54 +02:00
if ( typeof str !== "string" ) {
unreachable ( "Invalid argument for stringToBytes" ) ;
2016-04-04 15:49:28 +02:00
}
2023-10-27 13:19:54 +02:00
const length = str . length ;
const bytes = new Uint8Array ( length ) ;
for ( let i = 0 ; i < length ; ++ i ) {
bytes [ i ] = str . charCodeAt ( i ) & 0xff ;
2016-04-04 15:49:28 +02:00
}
2023-10-27 13:19:54 +02:00
return bytes ;
2016-04-04 15:49:28 +02:00
}
2014-11-24 00:56:52 +01:00
function string32 ( value ) {
2023-10-27 13:19:54 +02:00
return String . fromCharCode ( value >> 24 & 0xff , value >> 16 & 0xff , value >> 8 & 0xff , value & 0xff ) ;
2014-11-24 00:56:52 +01:00
}
2023-10-27 13:19:54 +02:00
function objectSize ( obj ) {
return Object . keys ( obj ) . length ;
2014-11-24 00:56:52 +01:00
}
2023-10-27 13:19:54 +02:00
function objectFromMap ( map ) {
const obj = Object . create ( null ) ;
for ( const [ key , value ] of map ) {
obj [ key ] = value ;
}
return obj ;
2014-11-24 00:56:52 +01:00
}
function isLittleEndian ( ) {
2023-10-27 13:19:54 +02:00
const buffer8 = new Uint8Array ( 4 ) ;
2014-11-24 00:56:52 +01:00
buffer8 [ 0 ] = 1 ;
2023-10-27 13:19:54 +02:00
const view32 = new Uint32Array ( buffer8 . buffer , 0 , 1 ) ;
return view32 [ 0 ] === 1 ;
2014-11-24 00:56:52 +01:00
}
2023-10-27 13:19:54 +02:00
function isEvalSupported ( ) {
try {
new Function ( "" ) ;
return true ;
} catch {
return false ;
2014-11-24 00:56:52 +01:00
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
class util _FeatureTest {
2023-10-27 13:19:54 +02:00
static get isLittleEndian ( ) {
return shadow ( this , "isLittleEndian" , isLittleEndian ( ) ) ;
2014-11-24 00:56:52 +01:00
}
2023-10-27 13:19:54 +02:00
static get isEvalSupported ( ) {
return shadow ( this , "isEvalSupported" , isEvalSupported ( ) ) ;
}
static get isOffscreenCanvasSupported ( ) {
return shadow ( this , "isOffscreenCanvasSupported" , typeof OffscreenCanvas !== "undefined" ) ;
}
static get platform ( ) {
2024-06-01 11:00:27 +01:00
if ( typeof navigator !== "undefined" && typeof navigator ? . platform === "string" ) {
2023-10-27 13:19:54 +02:00
return shadow ( this , "platform" , {
2024-06-01 11:00:27 +01:00
isMac : navigator . platform . includes ( "Mac" )
2023-10-27 13:19:54 +02:00
} ) ;
2014-11-24 00:56:52 +01:00
}
2023-10-27 13:19:54 +02:00
return shadow ( this , "platform" , {
2024-06-01 11:00:27 +01:00
isMac : false
2023-10-27 13:19:54 +02:00
} ) ;
2014-11-24 00:56:52 +01:00
}
2023-10-27 13:19:54 +02:00
static get isCSSRoundSupported ( ) {
return shadow ( this , "isCSSRoundSupported" , globalThis . CSS ? . supports ? . ( "width: round(1.5px, 1px)" ) ) ;
}
}
2024-06-01 11:00:27 +01:00
const hexNumbers = Array . from ( Array ( 256 ) . keys ( ) , n => n . toString ( 16 ) . padStart ( 2 , "0" ) ) ;
2023-10-27 13:19:54 +02:00
class Util {
static makeHexColor ( r , g , b ) {
return ` # ${ hexNumbers [ r ] } ${ hexNumbers [ g ] } ${ hexNumbers [ b ] } ` ;
}
static scaleMinMax ( transform , minMax ) {
let temp ;
if ( transform [ 0 ] ) {
if ( transform [ 0 ] < 0 ) {
temp = minMax [ 0 ] ;
2024-06-01 11:00:27 +01:00
minMax [ 0 ] = minMax [ 2 ] ;
minMax [ 2 ] = temp ;
2023-10-27 13:19:54 +02:00
}
minMax [ 0 ] *= transform [ 0 ] ;
2024-06-01 11:00:27 +01:00
minMax [ 2 ] *= transform [ 0 ] ;
2023-10-27 13:19:54 +02:00
if ( transform [ 3 ] < 0 ) {
2024-06-01 11:00:27 +01:00
temp = minMax [ 1 ] ;
minMax [ 1 ] = minMax [ 3 ] ;
2023-10-27 13:19:54 +02:00
minMax [ 3 ] = temp ;
}
2024-06-01 11:00:27 +01:00
minMax [ 1 ] *= transform [ 3 ] ;
2023-10-27 13:19:54 +02:00
minMax [ 3 ] *= transform [ 3 ] ;
} else {
temp = minMax [ 0 ] ;
2024-06-01 11:00:27 +01:00
minMax [ 0 ] = minMax [ 1 ] ;
minMax [ 1 ] = temp ;
temp = minMax [ 2 ] ;
minMax [ 2 ] = minMax [ 3 ] ;
2023-10-27 13:19:54 +02:00
minMax [ 3 ] = temp ;
if ( transform [ 1 ] < 0 ) {
2024-06-01 11:00:27 +01:00
temp = minMax [ 1 ] ;
minMax [ 1 ] = minMax [ 3 ] ;
2023-10-27 13:19:54 +02:00
minMax [ 3 ] = temp ;
}
2024-06-01 11:00:27 +01:00
minMax [ 1 ] *= transform [ 1 ] ;
2023-10-27 13:19:54 +02:00
minMax [ 3 ] *= transform [ 1 ] ;
if ( transform [ 2 ] < 0 ) {
temp = minMax [ 0 ] ;
2024-06-01 11:00:27 +01:00
minMax [ 0 ] = minMax [ 2 ] ;
minMax [ 2 ] = temp ;
2023-10-27 13:19:54 +02:00
}
minMax [ 0 ] *= transform [ 2 ] ;
2024-06-01 11:00:27 +01:00
minMax [ 2 ] *= transform [ 2 ] ;
2023-10-27 13:19:54 +02:00
}
minMax [ 0 ] += transform [ 4 ] ;
2024-06-01 11:00:27 +01:00
minMax [ 1 ] += transform [ 5 ] ;
minMax [ 2 ] += transform [ 4 ] ;
2023-10-27 13:19:54 +02:00
minMax [ 3 ] += transform [ 5 ] ;
}
static transform ( m1 , m2 ) {
return [ m1 [ 0 ] * m2 [ 0 ] + m1 [ 2 ] * m2 [ 1 ] , m1 [ 1 ] * m2 [ 0 ] + m1 [ 3 ] * m2 [ 1 ] , m1 [ 0 ] * m2 [ 2 ] + m1 [ 2 ] * m2 [ 3 ] , m1 [ 1 ] * m2 [ 2 ] + m1 [ 3 ] * m2 [ 3 ] , m1 [ 0 ] * m2 [ 4 ] + m1 [ 2 ] * m2 [ 5 ] + m1 [ 4 ] , m1 [ 1 ] * m2 [ 4 ] + m1 [ 3 ] * m2 [ 5 ] + m1 [ 5 ] ] ;
}
static applyTransform ( p , m ) {
const xt = p [ 0 ] * m [ 0 ] + p [ 1 ] * m [ 2 ] + m [ 4 ] ;
const yt = p [ 0 ] * m [ 1 ] + p [ 1 ] * m [ 3 ] + m [ 5 ] ;
2013-02-21 14:09:23 +00:00
return [ xt , yt ] ;
2023-10-27 13:19:54 +02:00
}
static applyInverseTransform ( p , m ) {
const d = m [ 0 ] * m [ 3 ] - m [ 1 ] * m [ 2 ] ;
const xt = ( p [ 0 ] * m [ 3 ] - p [ 1 ] * m [ 2 ] + m [ 2 ] * m [ 5 ] - m [ 4 ] * m [ 3 ] ) / d ;
const yt = ( - p [ 0 ] * m [ 1 ] + p [ 1 ] * m [ 0 ] + m [ 4 ] * m [ 1 ] - m [ 5 ] * m [ 0 ] ) / d ;
2013-02-21 14:09:23 +00:00
return [ xt , yt ] ;
2023-10-27 13:19:54 +02:00
}
static getAxialAlignedBoundingBox ( r , m ) {
const p1 = this . applyTransform ( r , m ) ;
const p2 = this . applyTransform ( r . slice ( 2 , 4 ) , m ) ;
const p3 = this . applyTransform ( [ r [ 0 ] , r [ 3 ] ] , m ) ;
const p4 = this . applyTransform ( [ r [ 2 ] , r [ 1 ] ] , m ) ;
return [ Math . min ( p1 [ 0 ] , p2 [ 0 ] , p3 [ 0 ] , p4 [ 0 ] ) , Math . min ( p1 [ 1 ] , p2 [ 1 ] , p3 [ 1 ] , p4 [ 1 ] ) , Math . max ( p1 [ 0 ] , p2 [ 0 ] , p3 [ 0 ] , p4 [ 0 ] ) , Math . max ( p1 [ 1 ] , p2 [ 1 ] , p3 [ 1 ] , p4 [ 1 ] ) ] ;
}
static inverseTransform ( m ) {
const d = m [ 0 ] * m [ 3 ] - m [ 1 ] * m [ 2 ] ;
return [ m [ 3 ] / d , - m [ 1 ] / d , - m [ 2 ] / d , m [ 0 ] / d , ( m [ 2 ] * m [ 5 ] - m [ 4 ] * m [ 3 ] ) / d , ( m [ 4 ] * m [ 1 ] - m [ 5 ] * m [ 0 ] ) / d ] ;
}
static singularValueDecompose2dScale ( m ) {
const transpose = [ m [ 0 ] , m [ 2 ] , m [ 1 ] , m [ 3 ] ] ;
const a = m [ 0 ] * transpose [ 0 ] + m [ 1 ] * transpose [ 2 ] ;
const b = m [ 0 ] * transpose [ 1 ] + m [ 1 ] * transpose [ 3 ] ;
const c = m [ 2 ] * transpose [ 0 ] + m [ 3 ] * transpose [ 2 ] ;
const d = m [ 2 ] * transpose [ 1 ] + m [ 3 ] * transpose [ 3 ] ;
const first = ( a + d ) / 2 ;
const second = Math . sqrt ( ( a + d ) * * 2 - 4 * ( a * d - c * b ) ) / 2 ;
const sx = first + second || 1 ;
const sy = first - second || 1 ;
2013-12-31 16:34:23 +05:30
return [ Math . sqrt ( sx ) , Math . sqrt ( sy ) ] ;
2023-10-27 13:19:54 +02:00
}
static normalizeRect ( rect ) {
const r = rect . slice ( 0 ) ;
2013-02-21 14:09:23 +00:00
if ( rect [ 0 ] > rect [ 2 ] ) {
r [ 0 ] = rect [ 2 ] ;
r [ 2 ] = rect [ 0 ] ;
}
if ( rect [ 1 ] > rect [ 3 ] ) {
r [ 1 ] = rect [ 3 ] ;
r [ 3 ] = rect [ 1 ] ;
}
return r ;
2023-10-27 13:19:54 +02:00
}
static intersect ( rect1 , rect2 ) {
const xLow = Math . max ( Math . min ( rect1 [ 0 ] , rect1 [ 2 ] ) , Math . min ( rect2 [ 0 ] , rect2 [ 2 ] ) ) ;
const xHigh = Math . min ( Math . max ( rect1 [ 0 ] , rect1 [ 2 ] ) , Math . max ( rect2 [ 0 ] , rect2 [ 2 ] ) ) ;
if ( xLow > xHigh ) {
return null ;
2013-02-21 14:09:23 +00:00
}
2023-10-27 13:19:54 +02:00
const yLow = Math . max ( Math . min ( rect1 [ 1 ] , rect1 [ 3 ] ) , Math . min ( rect2 [ 1 ] , rect2 [ 3 ] ) ) ;
const yHigh = Math . min ( Math . max ( rect1 [ 1 ] , rect1 [ 3 ] ) , Math . max ( rect2 [ 1 ] , rect2 [ 3 ] ) ) ;
if ( yLow > yHigh ) {
return null ;
2013-02-21 14:09:23 +00:00
}
2023-10-27 13:19:54 +02:00
return [ xLow , yLow , xHigh , yHigh ] ;
}
2024-06-01 11:00:27 +01:00
static # getExtremumOnCurve ( x0 , x1 , x2 , x3 , y0 , y1 , y2 , y3 , t , minMax ) {
if ( t <= 0 || t >= 1 ) {
return ;
}
const mt = 1 - t ;
const tt = t * t ;
const ttt = tt * t ;
const x = mt * ( mt * ( mt * x0 + 3 * t * x1 ) + 3 * tt * x2 ) + ttt * x3 ;
const y = mt * ( mt * ( mt * y0 + 3 * t * y1 ) + 3 * tt * y2 ) + ttt * y3 ;
minMax [ 0 ] = Math . min ( minMax [ 0 ] , x ) ;
minMax [ 1 ] = Math . min ( minMax [ 1 ] , y ) ;
minMax [ 2 ] = Math . max ( minMax [ 2 ] , x ) ;
minMax [ 3 ] = Math . max ( minMax [ 3 ] , y ) ;
}
static # getExtremum ( x0 , x1 , x2 , x3 , y0 , y1 , y2 , y3 , a , b , c , minMax ) {
if ( Math . abs ( a ) < 1e-12 ) {
if ( Math . abs ( b ) >= 1e-12 ) {
this . # getExtremumOnCurve ( x0 , x1 , x2 , x3 , y0 , y1 , y2 , y3 , - c / b , minMax ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
return ;
2013-12-31 16:34:23 +05:30
}
2024-06-01 11:00:27 +01:00
const delta = b * * 2 - 4 * c * a ;
if ( delta < 0 ) {
return ;
}
const sqrtDelta = Math . sqrt ( delta ) ;
const a2 = 2 * a ;
this . # getExtremumOnCurve ( x0 , x1 , x2 , x3 , y0 , y1 , y2 , y3 , ( - b + sqrtDelta ) / a2 , minMax ) ;
this . # getExtremumOnCurve ( x0 , x1 , x2 , x3 , y0 , y1 , y2 , y3 , ( - b - sqrtDelta ) / a2 , minMax ) ;
}
static bezierBoundingBox ( x0 , y0 , x1 , y1 , x2 , y2 , x3 , y3 , minMax ) {
if ( minMax ) {
minMax [ 0 ] = Math . min ( minMax [ 0 ] , x0 , x3 ) ;
minMax [ 1 ] = Math . min ( minMax [ 1 ] , y0 , y3 ) ;
minMax [ 2 ] = Math . max ( minMax [ 2 ] , x0 , x3 ) ;
minMax [ 3 ] = Math . max ( minMax [ 3 ] , y0 , y3 ) ;
} else {
minMax = [ Math . min ( x0 , x3 ) , Math . min ( y0 , y3 ) , Math . max ( x0 , x3 ) , Math . max ( y0 , y3 ) ] ;
2013-02-21 14:09:23 +00:00
}
2024-06-01 11:00:27 +01:00
this . # getExtremum ( x0 , x1 , x2 , x3 , y0 , y1 , y2 , y3 , 3 * ( - x0 + 3 * ( x1 - x2 ) + x3 ) , 6 * ( x0 - 2 * x1 + x2 ) , 3 * ( x1 - x0 ) , minMax ) ;
this . # getExtremum ( x0 , x1 , x2 , x3 , y0 , y1 , y2 , y3 , 3 * ( - y0 + 3 * ( y1 - y2 ) + y3 ) , 6 * ( y0 - 2 * y1 + y2 ) , 3 * ( y1 - y0 ) , minMax ) ;
return minMax ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
const PDFStringTranslateTable = ( /* unused pure expression or super */ null && ( [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0x2d8 , 0x2c7 , 0x2c6 , 0x2d9 , 0x2dd , 0x2db , 0x2da , 0x2dc , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0x2022 , 0x2020 , 0x2021 , 0x2026 , 0x2014 , 0x2013 , 0x192 , 0x2044 , 0x2039 , 0x203a , 0x2212 , 0x2030 , 0x201e , 0x201c , 0x201d , 0x2018 , 0x2019 , 0x201a , 0x2122 , 0xfb01 , 0xfb02 , 0x141 , 0x152 , 0x160 , 0x178 , 0x17d , 0x131 , 0x142 , 0x153 , 0x161 , 0x17e , 0 , 0x20ac ] ) ) ;
2013-02-21 14:09:23 +00:00
function stringToPDFString ( str ) {
2023-10-27 13:19:54 +02:00
if ( str [ 0 ] >= "\xEF" ) {
let encoding ;
if ( str [ 0 ] === "\xFE" && str [ 1 ] === "\xFF" ) {
encoding = "utf-16be" ;
2024-06-01 11:00:27 +01:00
if ( str . length % 2 === 1 ) {
str = str . slice ( 0 , - 1 ) ;
}
2023-10-27 13:19:54 +02:00
} else if ( str [ 0 ] === "\xFF" && str [ 1 ] === "\xFE" ) {
encoding = "utf-16le" ;
2024-06-01 11:00:27 +01:00
if ( str . length % 2 === 1 ) {
str = str . slice ( 0 , - 1 ) ;
}
2023-10-27 13:19:54 +02:00
} else if ( str [ 0 ] === "\xEF" && str [ 1 ] === "\xBB" && str [ 2 ] === "\xBF" ) {
encoding = "utf-8" ;
2014-11-24 00:56:52 +01:00
}
2023-10-27 13:19:54 +02:00
if ( encoding ) {
try {
const decoder = new TextDecoder ( encoding , {
fatal : true
} ) ;
const buffer = stringToBytes ( str ) ;
2024-06-01 11:00:27 +01:00
const decoded = decoder . decode ( buffer ) ;
if ( ! decoded . includes ( "\x1b" ) ) {
return decoded ;
}
return decoded . replaceAll ( /\x1b[^\x1b]*(?:\x1b|$)/g , "" ) ;
2023-10-27 13:19:54 +02:00
} catch ( ex ) {
warn ( ` stringToPDFString: " ${ ex } ". ` ) ;
}
2013-02-21 14:09:23 +00:00
}
}
2023-10-27 13:19:54 +02:00
const strBuf = [ ] ;
for ( let i = 0 , ii = str . length ; i < ii ; i ++ ) {
2024-06-01 11:00:27 +01:00
const charCode = str . charCodeAt ( i ) ;
if ( charCode === 0x1b ) {
while ( ++ i < ii && str . charCodeAt ( i ) !== 0x1b ) { }
continue ;
}
const code = PDFStringTranslateTable [ charCode ] ;
2023-10-27 13:19:54 +02:00
strBuf . push ( code ? String . fromCharCode ( code ) : str . charAt ( i ) ) ;
}
return strBuf . join ( "" ) ;
2013-02-21 14:09:23 +00:00
}
function stringToUTF8String ( str ) {
return decodeURIComponent ( escape ( str ) ) ;
}
2016-04-04 15:49:28 +02:00
function utf8StringToString ( str ) {
return unescape ( encodeURIComponent ( str ) ) ;
}
2023-10-27 13:19:54 +02:00
function isArrayEqual ( arr1 , arr2 ) {
if ( arr1 . length !== arr2 . length ) {
2013-03-03 08:22:46 +00:00
return false ;
}
2023-10-27 13:19:54 +02:00
for ( let i = 0 , ii = arr1 . length ; i < ii ; i ++ ) {
if ( arr1 [ i ] !== arr2 [ i ] ) {
return false ;
}
}
2013-03-03 08:22:46 +00:00
return true ;
}
2023-10-27 13:19:54 +02:00
function getModificationDate ( date = new Date ( ) ) {
const buffer = [ date . getUTCFullYear ( ) . toString ( ) , ( date . getUTCMonth ( ) + 1 ) . toString ( ) . padStart ( 2 , "0" ) , date . getUTCDate ( ) . toString ( ) . padStart ( 2 , "0" ) , date . getUTCHours ( ) . toString ( ) . padStart ( 2 , "0" ) , date . getUTCMinutes ( ) . toString ( ) . padStart ( 2 , "0" ) , date . getUTCSeconds ( ) . toString ( ) . padStart ( 2 , "0" ) ] ;
return buffer . join ( "" ) ;
2013-02-21 14:09:23 +00:00
}
2023-10-27 13:19:54 +02:00
let NormalizeRegex = null ;
let NormalizationMap = null ;
function normalizeUnicode ( str ) {
if ( ! NormalizeRegex ) {
NormalizeRegex = /([\u00a0\u00b5\u037e\u0eb3\u2000-\u200a\u202f\u2126\ufb00-\ufb04\ufb06\ufb20-\ufb36\ufb38-\ufb3c\ufb3e\ufb40-\ufb41\ufb43-\ufb44\ufb46-\ufba1\ufba4-\ufba9\ufbae-\ufbb1\ufbd3-\ufbdc\ufbde-\ufbe7\ufbea-\ufbf8\ufbfc-\ufbfd\ufc00-\ufc5d\ufc64-\ufcf1\ufcf5-\ufd3d\ufd88\ufdf4\ufdfa-\ufdfb\ufe71\ufe77\ufe79\ufe7b\ufe7d]+)|(\ufb05+)/gu ;
NormalizationMap = new Map ( [ [ "ſt" , "ſ t" ] ] ) ;
}
2024-06-01 11:00:27 +01:00
return str . replaceAll ( NormalizeRegex , ( _ , p1 , p2 ) => p1 ? p1 . normalize ( "NFKC" ) : NormalizationMap . get ( p2 ) ) ;
2013-02-21 14:09:23 +00:00
}
2023-10-27 13:19:54 +02:00
function getUuid ( ) {
if ( typeof crypto !== "undefined" && typeof crypto ? . randomUUID === "function" ) {
return crypto . randomUUID ( ) ;
}
const buf = new Uint8Array ( 32 ) ;
if ( typeof crypto !== "undefined" && typeof crypto ? . getRandomValues === "function" ) {
crypto . getRandomValues ( buf ) ;
} else {
for ( let i = 0 ; i < 32 ; i ++ ) {
buf [ i ] = Math . floor ( Math . random ( ) * 255 ) ;
}
}
return bytesToString ( buf ) ;
2013-02-21 14:09:23 +00:00
}
2024-06-01 11:00:27 +01:00
const AnnotationPrefix = "pdfjs_internal_id_" ;
const FontRenderOps = {
BEZIER _CURVE _TO : 0 ,
MOVE _TO : 1 ,
LINE _TO : 2 ,
QUADRATIC _CURVE _TO : 3 ,
RESTORE : 4 ,
SAVE : 5 ,
SCALE : 6 ,
TRANSFORM : 7 ,
TRANSLATE : 8
} ;
2013-02-21 14:09:23 +00:00
2024-06-18 20:06:52 +02:00
// EXTERNAL MODULE: ./node_modules/core-js/modules/es.promise.with-resolvers.js
var es _promise _with _resolvers = _ _webpack _require _ _ ( 4628 ) ;
// EXTERNAL MODULE: ./node_modules/core-js/modules/esnext.iterator.map.js
var esnext _iterator _map = _ _webpack _require _ _ ( 1454 ) ;
// EXTERNAL MODULE: ./node_modules/core-js/modules/esnext.set.difference.v2.js
var esnext _set _difference _v2 = _ _webpack _require _ _ ( 3375 ) ;
// EXTERNAL MODULE: ./node_modules/core-js/modules/esnext.set.intersection.v2.js
var esnext _set _intersection _v2 = _ _webpack _require _ _ ( 9225 ) ;
// EXTERNAL MODULE: ./node_modules/core-js/modules/esnext.set.is-disjoint-from.v2.js
var esnext _set _is _disjoint _from _v2 = _ _webpack _require _ _ ( 3972 ) ;
// EXTERNAL MODULE: ./node_modules/core-js/modules/esnext.set.is-subset-of.v2.js
var esnext _set _is _subset _of _v2 = _ _webpack _require _ _ ( 9209 ) ;
// EXTERNAL MODULE: ./node_modules/core-js/modules/esnext.set.is-superset-of.v2.js
var esnext _set _is _superset _of _v2 = _ _webpack _require _ _ ( 5714 ) ;
// EXTERNAL MODULE: ./node_modules/core-js/modules/esnext.set.symmetric-difference.v2.js
var esnext _set _symmetric _difference _v2 = _ _webpack _require _ _ ( 7561 ) ;
// EXTERNAL MODULE: ./node_modules/core-js/modules/esnext.set.union.v2.js
var esnext _set _union _v2 = _ _webpack _require _ _ ( 6197 ) ;
// EXTERNAL MODULE: ./node_modules/core-js/modules/web.dom-exception.stack.js
var web _dom _exception _stack = _ _webpack _require _ _ ( 4979 ) ;
// EXTERNAL MODULE: ./node_modules/core-js/modules/esnext.iterator.constructor.js
var esnext _iterator _constructor = _ _webpack _require _ _ ( 8992 ) ;
// EXTERNAL MODULE: ./node_modules/core-js/modules/esnext.iterator.drop.js
var esnext _iterator _drop = _ _webpack _require _ _ ( 4743 ) ;
// EXTERNAL MODULE: ./node_modules/core-js/modules/esnext.iterator.every.js
var esnext _iterator _every = _ _webpack _require _ _ ( 3215 ) ;
// EXTERNAL MODULE: ./node_modules/core-js/modules/esnext.iterator.some.js
var esnext _iterator _some = _ _webpack _require _ _ ( 7550 ) ;
// EXTERNAL MODULE: ./node_modules/core-js/modules/esnext.json.parse.js
var esnext _json _parse = _ _webpack _require _ _ ( 8335 ) ;
// EXTERNAL MODULE: ./node_modules/core-js/modules/esnext.iterator.filter.js
var esnext _iterator _filter = _ _webpack _require _ _ ( 4520 ) ;
2024-06-01 11:00:27 +01:00
; // CONCATENATED MODULE: ./src/display/base_factory.js
2013-02-21 14:09:23 +00:00
2024-06-01 11:00:27 +01:00
class BaseFilterFactory {
constructor ( ) {
if ( this . constructor === BaseFilterFactory ) {
unreachable ( "Cannot initialize BaseFilterFactory." ) ;
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
addFilter ( maps ) {
return "none" ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
addHCMFilter ( fgColor , bgColor ) {
return "none" ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
addAlphaFilter ( map ) {
return "none" ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
addLuminosityFilter ( map ) {
return "none" ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
addHighlightHCMFilter ( filterName , fgColor , bgColor , newFgColor , newBgColor ) {
return "none" ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
destroy ( keepHCM = false ) { }
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
class BaseCanvasFactory {
2024-06-18 20:06:52 +02:00
# enableHWA = false ;
constructor ( {
enableHWA = false
} = { } ) {
2024-06-01 11:00:27 +01:00
if ( this . constructor === BaseCanvasFactory ) {
unreachable ( "Cannot initialize BaseCanvasFactory." ) ;
2014-01-09 14:05:57 +05:30
}
2024-06-18 20:06:52 +02:00
this . # enableHWA = enableHWA ;
2014-01-09 14:05:57 +05:30
}
2024-06-01 11:00:27 +01:00
create ( width , height ) {
if ( width <= 0 || height <= 0 ) {
throw new Error ( "Invalid canvas size" ) ;
}
const canvas = this . _createCanvas ( width , height ) ;
return {
canvas ,
2024-06-18 20:06:52 +02:00
context : canvas . getContext ( "2d" , {
willReadFrequently : ! this . # enableHWA
} )
2024-06-01 11:00:27 +01:00
} ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
reset ( canvasAndContext , width , height ) {
if ( ! canvasAndContext . canvas ) {
throw new Error ( "Canvas is not specified" ) ;
}
if ( width <= 0 || height <= 0 ) {
throw new Error ( "Invalid canvas size" ) ;
}
canvasAndContext . canvas . width = width ;
canvasAndContext . canvas . height = height ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
destroy ( canvasAndContext ) {
if ( ! canvasAndContext . canvas ) {
throw new Error ( "Canvas is not specified" ) ;
}
canvasAndContext . canvas . width = 0 ;
canvasAndContext . canvas . height = 0 ;
canvasAndContext . canvas = null ;
canvasAndContext . context = null ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
_createCanvas ( width , height ) {
unreachable ( "Abstract method `_createCanvas` called." ) ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
class BaseCMapReaderFactory {
constructor ( {
baseUrl = null ,
isCompressed = true
} ) {
if ( this . constructor === BaseCMapReaderFactory ) {
unreachable ( "Cannot initialize BaseCMapReaderFactory." ) ;
}
this . baseUrl = baseUrl ;
this . isCompressed = isCompressed ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
async fetch ( {
name
} ) {
if ( ! this . baseUrl ) {
throw new Error ( 'The CMap "baseUrl" parameter must be specified, ensure that ' + 'the "cMapUrl" and "cMapPacked" API parameters are provided.' ) ;
}
if ( ! name ) {
throw new Error ( "CMap name must be specified." ) ;
}
const url = this . baseUrl + name + ( this . isCompressed ? ".bcmap" : "" ) ;
const compressionType = this . isCompressed ? CMapCompressionType . BINARY : CMapCompressionType . NONE ;
return this . _fetchData ( url , compressionType ) . catch ( reason => {
throw new Error ( ` Unable to load ${ this . isCompressed ? "binary " : "" } CMap at: ${ url } ` ) ;
} ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
_fetchData ( url , compressionType ) {
unreachable ( "Abstract method `_fetchData` called." ) ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
class BaseStandardFontDataFactory {
constructor ( {
baseUrl = null
} ) {
if ( this . constructor === BaseStandardFontDataFactory ) {
unreachable ( "Cannot initialize BaseStandardFontDataFactory." ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
this . baseUrl = baseUrl ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
async fetch ( {
filename
} ) {
if ( ! this . baseUrl ) {
throw new Error ( 'The standard font "baseUrl" parameter must be specified, ensure that ' + 'the "standardFontDataUrl" API parameter is provided.' ) ;
}
if ( ! filename ) {
throw new Error ( "Font filename must be specified." ) ;
}
const url = ` ${ this . baseUrl } ${ filename } ` ;
return this . _fetchData ( url ) . catch ( reason => {
throw new Error ( ` Unable to load font data at: ${ url } ` ) ;
2023-10-27 13:19:54 +02:00
} ) ;
}
2024-06-01 11:00:27 +01:00
_fetchData ( url ) {
unreachable ( "Abstract method `_fetchData` called." ) ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
class BaseSVGFactory {
constructor ( ) {
if ( this . constructor === BaseSVGFactory ) {
unreachable ( "Cannot initialize BaseSVGFactory." ) ;
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
create ( width , height , skipDimensions = false ) {
if ( width <= 0 || height <= 0 ) {
throw new Error ( "Invalid SVG dimensions" ) ;
}
const svg = this . _createSVG ( "svg:svg" ) ;
svg . setAttribute ( "version" , "1.1" ) ;
if ( ! skipDimensions ) {
svg . setAttribute ( "width" , ` ${ width } px ` ) ;
svg . setAttribute ( "height" , ` ${ height } px ` ) ;
}
svg . setAttribute ( "preserveAspectRatio" , "none" ) ;
svg . setAttribute ( "viewBox" , ` 0 0 ${ width } ${ height } ` ) ;
return svg ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
createElement ( type ) {
if ( typeof type !== "string" ) {
throw new Error ( "Invalid SVG element type" ) ;
}
return this . _createSVG ( type ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
_createSVG ( type ) {
unreachable ( "Abstract method `_createSVG` called." ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
}
; // CONCATENATED MODULE: ./src/display/display_utils.js
2024-06-18 20:06:52 +02:00
2024-06-01 11:00:27 +01:00
const SVG _NS = "http://www.w3.org/2000/svg" ;
class PixelsPerInch {
static CSS = 96.0 ;
static PDF = 72.0 ;
static PDF _TO _CSS _UNITS = this . CSS / this . PDF ;
}
class DOMFilterFactory extends BaseFilterFactory {
# _cache ;
# _defs ;
# docId ;
# document ;
# _hcmCache ;
# id = 0 ;
constructor ( {
docId ,
ownerDocument = globalThis . document
} = { } ) {
super ( ) ;
this . # docId = docId ;
this . # document = ownerDocument ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
get # cache ( ) {
return this . # _cache || = new Map ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
get # hcmCache ( ) {
return this . # _hcmCache || = new Map ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
get # defs ( ) {
if ( ! this . # _defs ) {
const div = this . # document . createElement ( "div" ) ;
const {
style
} = div ;
style . visibility = "hidden" ;
style . contain = "strict" ;
style . width = style . height = 0 ;
style . position = "absolute" ;
style . top = style . left = 0 ;
style . zIndex = - 1 ;
const svg = this . # document . createElementNS ( SVG _NS , "svg" ) ;
svg . setAttribute ( "width" , 0 ) ;
svg . setAttribute ( "height" , 0 ) ;
this . # _defs = this . # document . createElementNS ( SVG _NS , "defs" ) ;
div . append ( svg ) ;
svg . append ( this . # _defs ) ;
this . # document . body . append ( div ) ;
}
return this . # _defs ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
# createTables ( maps ) {
if ( maps . length === 1 ) {
const mapR = maps [ 0 ] ;
const buffer = new Array ( 256 ) ;
for ( let i = 0 ; i < 256 ; i ++ ) {
buffer [ i ] = mapR [ i ] / 255 ;
}
const table = buffer . join ( "," ) ;
return [ table , table , table ] ;
}
const [ mapR , mapG , mapB ] = maps ;
const bufferR = new Array ( 256 ) ;
const bufferG = new Array ( 256 ) ;
const bufferB = new Array ( 256 ) ;
for ( let i = 0 ; i < 256 ; i ++ ) {
bufferR [ i ] = mapR [ i ] / 255 ;
bufferG [ i ] = mapG [ i ] / 255 ;
bufferB [ i ] = mapB [ i ] / 255 ;
}
return [ bufferR . join ( "," ) , bufferG . join ( "," ) , bufferB . join ( "," ) ] ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
addFilter ( maps ) {
if ( ! maps ) {
return "none" ;
}
let value = this . # cache . get ( maps ) ;
if ( value ) {
return value ;
}
const [ tableR , tableG , tableB ] = this . # createTables ( maps ) ;
const key = maps . length === 1 ? tableR : ` ${ tableR } ${ tableG } ${ tableB } ` ;
value = this . # cache . get ( key ) ;
if ( value ) {
this . # cache . set ( maps , value ) ;
return value ;
}
const id = ` g_ ${ this . # docId } _transfer_map_ ${ this . # id ++ } ` ;
const url = ` url(# ${ id } ) ` ;
this . # cache . set ( maps , url ) ;
this . # cache . set ( key , url ) ;
const filter = this . # createFilter ( id ) ;
this . # addTransferMapConversion ( tableR , tableG , tableB , filter ) ;
return url ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
addHCMFilter ( fgColor , bgColor ) {
const key = ` ${ fgColor } - ${ bgColor } ` ;
const filterName = "base" ;
let info = this . # hcmCache . get ( filterName ) ;
if ( info ? . key === key ) {
return info . url ;
}
if ( info ) {
info . filter ? . remove ( ) ;
info . key = key ;
info . url = "none" ;
info . filter = null ;
} else {
info = {
key ,
url : "none" ,
filter : null
} ;
this . # hcmCache . set ( filterName , info ) ;
}
if ( ! fgColor || ! bgColor ) {
return info . url ;
}
const fgRGB = this . # getRGB ( fgColor ) ;
fgColor = Util . makeHexColor ( ... fgRGB ) ;
const bgRGB = this . # getRGB ( bgColor ) ;
bgColor = Util . makeHexColor ( ... bgRGB ) ;
this . # defs . style . color = "" ;
if ( fgColor === "#000000" && bgColor === "#ffffff" || fgColor === bgColor ) {
return info . url ;
}
const map = new Array ( 256 ) ;
for ( let i = 0 ; i <= 255 ; i ++ ) {
const x = i / 255 ;
map [ i ] = x <= 0.03928 ? x / 12.92 : ( ( x + 0.055 ) / 1.055 ) * * 2.4 ;
}
const table = map . join ( "," ) ;
const id = ` g_ ${ this . # docId } _hcm_filter ` ;
const filter = info . filter = this . # createFilter ( id ) ;
this . # addTransferMapConversion ( table , table , table , filter ) ;
this . # addGrayConversion ( filter ) ;
const getSteps = ( c , n ) => {
const start = fgRGB [ c ] / 255 ;
const end = bgRGB [ c ] / 255 ;
const arr = new Array ( n + 1 ) ;
for ( let i = 0 ; i <= n ; i ++ ) {
arr [ i ] = start + i / n * ( end - start ) ;
}
return arr . join ( "," ) ;
} ;
this . # addTransferMapConversion ( getSteps ( 0 , 5 ) , getSteps ( 1 , 5 ) , getSteps ( 2 , 5 ) , filter ) ;
info . url = ` url(# ${ id } ) ` ;
return info . url ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
addAlphaFilter ( map ) {
let value = this . # cache . get ( map ) ;
if ( value ) {
return value ;
}
const [ tableA ] = this . # createTables ( [ map ] ) ;
const key = ` alpha_ ${ tableA } ` ;
value = this . # cache . get ( key ) ;
if ( value ) {
this . # cache . set ( map , value ) ;
return value ;
}
const id = ` g_ ${ this . # docId } _alpha_map_ ${ this . # id ++ } ` ;
const url = ` url(# ${ id } ) ` ;
this . # cache . set ( map , url ) ;
this . # cache . set ( key , url ) ;
const filter = this . # createFilter ( id ) ;
this . # addTransferMapAlphaConversion ( tableA , filter ) ;
return url ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
addLuminosityFilter ( map ) {
let value = this . # cache . get ( map || "luminosity" ) ;
if ( value ) {
return value ;
}
let tableA , key ;
if ( map ) {
[ tableA ] = this . # createTables ( [ map ] ) ;
key = ` luminosity_ ${ tableA } ` ;
} else {
key = "luminosity" ;
}
value = this . # cache . get ( key ) ;
if ( value ) {
this . # cache . set ( map , value ) ;
return value ;
}
const id = ` g_ ${ this . # docId } _luminosity_map_ ${ this . # id ++ } ` ;
const url = ` url(# ${ id } ) ` ;
this . # cache . set ( map , url ) ;
this . # cache . set ( key , url ) ;
const filter = this . # createFilter ( id ) ;
this . # addLuminosityConversion ( filter ) ;
if ( map ) {
this . # addTransferMapAlphaConversion ( tableA , filter ) ;
}
return url ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
addHighlightHCMFilter ( filterName , fgColor , bgColor , newFgColor , newBgColor ) {
const key = ` ${ fgColor } - ${ bgColor } - ${ newFgColor } - ${ newBgColor } ` ;
let info = this . # hcmCache . get ( filterName ) ;
if ( info ? . key === key ) {
return info . url ;
}
if ( info ) {
info . filter ? . remove ( ) ;
info . key = key ;
info . url = "none" ;
info . filter = null ;
} else {
info = {
key ,
url : "none" ,
filter : null
} ;
this . # hcmCache . set ( filterName , info ) ;
}
if ( ! fgColor || ! bgColor ) {
return info . url ;
}
const [ fgRGB , bgRGB ] = [ fgColor , bgColor ] . map ( this . # getRGB . bind ( this ) ) ;
let fgGray = Math . round ( 0.2126 * fgRGB [ 0 ] + 0.7152 * fgRGB [ 1 ] + 0.0722 * fgRGB [ 2 ] ) ;
let bgGray = Math . round ( 0.2126 * bgRGB [ 0 ] + 0.7152 * bgRGB [ 1 ] + 0.0722 * bgRGB [ 2 ] ) ;
let [ newFgRGB , newBgRGB ] = [ newFgColor , newBgColor ] . map ( this . # getRGB . bind ( this ) ) ;
if ( bgGray < fgGray ) {
[ fgGray , bgGray , newFgRGB , newBgRGB ] = [ bgGray , fgGray , newBgRGB , newFgRGB ] ;
}
this . # defs . style . color = "" ;
const getSteps = ( fg , bg , n ) => {
const arr = new Array ( 256 ) ;
const step = ( bgGray - fgGray ) / n ;
const newStart = fg / 255 ;
const newStep = ( bg - fg ) / ( 255 * n ) ;
let prev = 0 ;
for ( let i = 0 ; i <= n ; i ++ ) {
const k = Math . round ( fgGray + i * step ) ;
const value = newStart + i * newStep ;
for ( let j = prev ; j <= k ; j ++ ) {
arr [ j ] = value ;
}
prev = k + 1 ;
}
for ( let i = prev ; i < 256 ; i ++ ) {
arr [ i ] = arr [ prev - 1 ] ;
}
return arr . join ( "," ) ;
} ;
const id = ` g_ ${ this . # docId } _hcm_ ${ filterName } _filter ` ;
const filter = info . filter = this . # createFilter ( id ) ;
this . # addGrayConversion ( filter ) ;
this . # addTransferMapConversion ( getSteps ( newFgRGB [ 0 ] , newBgRGB [ 0 ] , 5 ) , getSteps ( newFgRGB [ 1 ] , newBgRGB [ 1 ] , 5 ) , getSteps ( newFgRGB [ 2 ] , newBgRGB [ 2 ] , 5 ) , filter ) ;
info . url = ` url(# ${ id } ) ` ;
return info . url ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
destroy ( keepHCM = false ) {
if ( keepHCM && this . # hcmCache . size !== 0 ) {
return ;
}
if ( this . # _defs ) {
this . # _defs . parentNode . parentNode . remove ( ) ;
this . # _defs = null ;
}
if ( this . # _cache ) {
this . # _cache . clear ( ) ;
this . # _cache = null ;
}
this . # id = 0 ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
# addLuminosityConversion ( filter ) {
const feColorMatrix = this . # document . createElementNS ( SVG _NS , "feColorMatrix" ) ;
feColorMatrix . setAttribute ( "type" , "matrix" ) ;
feColorMatrix . setAttribute ( "values" , "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.3 0.59 0.11 0 0" ) ;
filter . append ( feColorMatrix ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
# addGrayConversion ( filter ) {
const feColorMatrix = this . # document . createElementNS ( SVG _NS , "feColorMatrix" ) ;
feColorMatrix . setAttribute ( "type" , "matrix" ) ;
feColorMatrix . setAttribute ( "values" , "0.2126 0.7152 0.0722 0 0 0.2126 0.7152 0.0722 0 0 0.2126 0.7152 0.0722 0 0 0 0 0 1 0" ) ;
filter . append ( feColorMatrix ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
# createFilter ( id ) {
const filter = this . # document . createElementNS ( SVG _NS , "filter" ) ;
filter . setAttribute ( "color-interpolation-filters" , "sRGB" ) ;
filter . setAttribute ( "id" , id ) ;
this . # defs . append ( filter ) ;
return filter ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
# appendFeFunc ( feComponentTransfer , func , table ) {
const feFunc = this . # document . createElementNS ( SVG _NS , func ) ;
feFunc . setAttribute ( "type" , "discrete" ) ;
feFunc . setAttribute ( "tableValues" , table ) ;
feComponentTransfer . append ( feFunc ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
# addTransferMapConversion ( rTable , gTable , bTable , filter ) {
const feComponentTransfer = this . # document . createElementNS ( SVG _NS , "feComponentTransfer" ) ;
filter . append ( feComponentTransfer ) ;
this . # appendFeFunc ( feComponentTransfer , "feFuncR" , rTable ) ;
this . # appendFeFunc ( feComponentTransfer , "feFuncG" , gTable ) ;
this . # appendFeFunc ( feComponentTransfer , "feFuncB" , bTable ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
# addTransferMapAlphaConversion ( aTable , filter ) {
const feComponentTransfer = this . # document . createElementNS ( SVG _NS , "feComponentTransfer" ) ;
filter . append ( feComponentTransfer ) ;
this . # appendFeFunc ( feComponentTransfer , "feFuncA" , aTable ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
# getRGB ( color ) {
this . # defs . style . color = color ;
return getRGB ( getComputedStyle ( this . # defs ) . getPropertyValue ( "color" ) ) ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
class DOMCanvasFactory extends BaseCanvasFactory {
constructor ( {
2024-06-18 20:06:52 +02:00
ownerDocument = globalThis . document ,
enableHWA = false
2024-06-01 11:00:27 +01:00
} = { } ) {
2024-06-18 20:06:52 +02:00
super ( {
enableHWA
} ) ;
2024-06-01 11:00:27 +01:00
this . _document = ownerDocument ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
_createCanvas ( width , height ) {
const canvas = this . _document . createElement ( "canvas" ) ;
canvas . width = width ;
canvas . height = height ;
return canvas ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
}
async function fetchData ( url , type = "text" ) {
if ( isValidFetchUrl ( url , document . baseURI ) ) {
const response = await fetch ( url ) ;
if ( ! response . ok ) {
throw new Error ( response . statusText ) ;
}
switch ( type ) {
case "arraybuffer" :
return response . arrayBuffer ( ) ;
case "blob" :
return response . blob ( ) ;
case "json" :
return response . json ( ) ;
}
return response . text ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
return new Promise ( ( resolve , reject ) => {
const request = new XMLHttpRequest ( ) ;
request . open ( "GET" , url , true ) ;
request . responseType = type ;
request . onreadystatechange = ( ) => {
if ( request . readyState !== XMLHttpRequest . DONE ) {
return ;
}
if ( request . status === 200 || request . status === 0 ) {
switch ( type ) {
case "arraybuffer" :
case "blob" :
case "json" :
resolve ( request . response ) ;
return ;
}
resolve ( request . responseText ) ;
return ;
}
reject ( new Error ( request . statusText ) ) ;
} ;
request . send ( null ) ;
} ) ;
}
class DOMCMapReaderFactory extends BaseCMapReaderFactory {
_fetchData ( url , compressionType ) {
return fetchData ( url , this . isCompressed ? "arraybuffer" : "text" ) . then ( data => ( {
cMapData : data instanceof ArrayBuffer ? new Uint8Array ( data ) : stringToBytes ( data ) ,
compressionType
} ) ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
}
class DOMStandardFontDataFactory extends BaseStandardFontDataFactory {
_fetchData ( url ) {
return fetchData ( url , "arraybuffer" ) . then ( data => new Uint8Array ( data ) ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
}
class DOMSVGFactory extends BaseSVGFactory {
_createSVG ( type ) {
return document . createElementNS ( SVG _NS , type ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
}
class PageViewport {
constructor ( {
viewBox ,
2023-10-27 13:19:54 +02:00
scale ,
2024-06-01 11:00:27 +01:00
rotation ,
2023-10-27 13:19:54 +02:00
offsetX = 0 ,
offsetY = 0 ,
dontFlip = false
} ) {
2024-06-01 11:00:27 +01:00
this . viewBox = viewBox ;
this . scale = scale ;
this . rotation = rotation ;
this . offsetX = offsetX ;
this . offsetY = offsetY ;
const centerX = ( viewBox [ 2 ] + viewBox [ 0 ] ) / 2 ;
const centerY = ( viewBox [ 3 ] + viewBox [ 1 ] ) / 2 ;
let rotateA , rotateB , rotateC , rotateD ;
rotation %= 360 ;
if ( rotation < 0 ) {
rotation += 360 ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
switch ( rotation ) {
case 180 :
rotateA = - 1 ;
rotateB = 0 ;
rotateC = 0 ;
rotateD = 1 ;
break ;
case 90 :
rotateA = 0 ;
rotateB = 1 ;
rotateC = 1 ;
rotateD = 0 ;
break ;
case 270 :
rotateA = 0 ;
rotateB = - 1 ;
rotateC = - 1 ;
rotateD = 0 ;
break ;
case 0 :
rotateA = 1 ;
rotateB = 0 ;
rotateC = 0 ;
rotateD = - 1 ;
break ;
default :
throw new Error ( "PageViewport: Invalid rotation, must be a multiple of 90 degrees." ) ;
2013-02-21 14:09:23 +00:00
}
2024-06-01 11:00:27 +01:00
if ( dontFlip ) {
rotateC = - rotateC ;
rotateD = - rotateD ;
2014-11-24 00:56:52 +01:00
}
2024-06-01 11:00:27 +01:00
let offsetCanvasX , offsetCanvasY ;
let width , height ;
if ( rotateA === 0 ) {
offsetCanvasX = Math . abs ( centerY - viewBox [ 1 ] ) * scale + offsetX ;
offsetCanvasY = Math . abs ( centerX - viewBox [ 0 ] ) * scale + offsetY ;
width = ( viewBox [ 3 ] - viewBox [ 1 ] ) * scale ;
height = ( viewBox [ 2 ] - viewBox [ 0 ] ) * scale ;
} else {
offsetCanvasX = Math . abs ( centerX - viewBox [ 0 ] ) * scale + offsetX ;
offsetCanvasY = Math . abs ( centerY - viewBox [ 1 ] ) * scale + offsetY ;
width = ( viewBox [ 2 ] - viewBox [ 0 ] ) * scale ;
height = ( viewBox [ 3 ] - viewBox [ 1 ] ) * scale ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
this . transform = [ rotateA * scale , rotateB * scale , rotateC * scale , rotateD * scale , offsetCanvasX - rotateA * scale * centerX - rotateC * scale * centerY , offsetCanvasY - rotateB * scale * centerX - rotateD * scale * centerY ] ;
this . width = width ;
this . height = height ;
2013-02-21 14:09:23 +00:00
}
2024-06-01 11:00:27 +01:00
get rawDims ( ) {
const {
viewBox
} = this ;
return shadow ( this , "rawDims" , {
pageWidth : viewBox [ 2 ] - viewBox [ 0 ] ,
pageHeight : viewBox [ 3 ] - viewBox [ 1 ] ,
pageX : viewBox [ 0 ] ,
pageY : viewBox [ 1 ]
2023-10-27 13:19:54 +02:00
} ) ;
}
2024-06-01 11:00:27 +01:00
clone ( {
scale = this . scale ,
rotation = this . rotation ,
offsetX = this . offsetX ,
offsetY = this . offsetY ,
dontFlip = false
} = { } ) {
return new PageViewport ( {
viewBox : this . viewBox . slice ( ) ,
scale ,
rotation ,
offsetX ,
offsetY ,
dontFlip
2023-10-27 13:19:54 +02:00
} ) ;
}
2024-06-01 11:00:27 +01:00
convertToViewportPoint ( x , y ) {
return Util . applyTransform ( [ x , y ] , this . transform ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
convertToViewportRectangle ( rect ) {
const topLeft = Util . applyTransform ( [ rect [ 0 ] , rect [ 1 ] ] , this . transform ) ;
const bottomRight = Util . applyTransform ( [ rect [ 2 ] , rect [ 3 ] ] , this . transform ) ;
return [ topLeft [ 0 ] , topLeft [ 1 ] , bottomRight [ 0 ] , bottomRight [ 1 ] ] ;
2014-11-24 00:56:52 +01:00
}
2024-06-01 11:00:27 +01:00
convertToPdfPoint ( x , y ) {
return Util . applyInverseTransform ( [ x , y ] , this . transform ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
}
class RenderingCancelledException extends BaseException {
constructor ( msg , extraDelay = 0 ) {
super ( msg , "RenderingCancelledException" ) ;
this . extraDelay = extraDelay ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
}
function isDataScheme ( url ) {
const ii = url . length ;
let i = 0 ;
while ( i < ii && url [ i ] . trim ( ) === "" ) {
i ++ ;
}
return url . substring ( i , i + 5 ) . toLowerCase ( ) === "data:" ;
}
function isPdfFile ( filename ) {
return typeof filename === "string" && /\.pdf$/i . test ( filename ) ;
}
function getFilenameFromUrl ( url ) {
[ url ] = url . split ( /[#?]/ , 1 ) ;
return url . substring ( url . lastIndexOf ( "/" ) + 1 ) ;
}
function getPdfFilenameFromUrl ( url , defaultFilename = "document.pdf" ) {
if ( typeof url !== "string" ) {
return defaultFilename ;
}
if ( isDataScheme ( url ) ) {
warn ( 'getPdfFilenameFromUrl: ignore "data:"-URL for performance reasons.' ) ;
return defaultFilename ;
}
const reURI = /^(?:(?:[^:]+:)?\/\/[^/]+)?([^?#]*)(\?[^#]*)?(#.*)?$/ ;
const reFilename = /[^/?#=]+\.pdf\b(?!.*\.pdf\b)/i ;
const splitURI = reURI . exec ( url ) ;
let suggestedFilename = reFilename . exec ( splitURI [ 1 ] ) || reFilename . exec ( splitURI [ 2 ] ) || reFilename . exec ( splitURI [ 3 ] ) ;
if ( suggestedFilename ) {
suggestedFilename = suggestedFilename [ 0 ] ;
if ( suggestedFilename . includes ( "%" ) ) {
try {
suggestedFilename = reFilename . exec ( decodeURIComponent ( suggestedFilename ) ) [ 0 ] ;
} catch { }
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
return suggestedFilename || defaultFilename ;
}
class StatTimer {
started = Object . create ( null ) ;
times = [ ] ;
time ( name ) {
if ( name in this . started ) {
warn ( ` Timer is already running for ${ name } ` ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
this . started [ name ] = Date . now ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
timeEnd ( name ) {
if ( ! ( name in this . started ) ) {
warn ( ` Timer has not been started for ${ name } ` ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
this . times . push ( {
name ,
start : this . started [ name ] ,
end : Date . now ( )
} ) ;
delete this . started [ name ] ;
}
toString ( ) {
const outBuf = [ ] ;
let longest = 0 ;
for ( const {
name
} of this . times ) {
longest = Math . max ( name . length , longest ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
for ( const {
name ,
start ,
end
} of this . times ) {
outBuf . push ( ` ${ name . padEnd ( longest ) } ${ end - start } ms \n ` ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
return outBuf . join ( "" ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
}
function isValidFetchUrl ( url , baseUrl ) {
try {
2023-10-27 13:19:54 +02:00
const {
2024-06-01 11:00:27 +01:00
protocol
} = baseUrl ? new URL ( url , baseUrl ) : new URL ( url ) ;
return protocol === "http:" || protocol === "https:" ;
} catch {
return false ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
}
function noContextMenu ( e ) {
e . preventDefault ( ) ;
}
function deprecated ( details ) {
console . log ( "Deprecated API usage: " + details ) ;
}
let pdfDateStringRegex ;
class PDFDateString {
static toDateObject ( input ) {
if ( ! input || typeof input !== "string" ) {
return null ;
2013-12-31 16:34:23 +05:30
}
2024-06-01 11:00:27 +01:00
pdfDateStringRegex || = new RegExp ( "^D:" + "(\\d{4})" + "(\\d{2})?" + "(\\d{2})?" + "(\\d{2})?" + "(\\d{2})?" + "(\\d{2})?" + "([Z|+|-])?" + "(\\d{2})?" + "'?" + "(\\d{2})?" + "'?" ) ;
const matches = pdfDateStringRegex . exec ( input ) ;
if ( ! matches ) {
return null ;
2013-12-31 16:34:23 +05:30
}
2024-06-01 11:00:27 +01:00
const year = parseInt ( matches [ 1 ] , 10 ) ;
let month = parseInt ( matches [ 2 ] , 10 ) ;
month = month >= 1 && month <= 12 ? month - 1 : 0 ;
let day = parseInt ( matches [ 3 ] , 10 ) ;
day = day >= 1 && day <= 31 ? day : 1 ;
let hour = parseInt ( matches [ 4 ] , 10 ) ;
hour = hour >= 0 && hour <= 23 ? hour : 0 ;
let minute = parseInt ( matches [ 5 ] , 10 ) ;
minute = minute >= 0 && minute <= 59 ? minute : 0 ;
let second = parseInt ( matches [ 6 ] , 10 ) ;
second = second >= 0 && second <= 59 ? second : 0 ;
const universalTimeRelation = matches [ 7 ] || "Z" ;
let offsetHour = parseInt ( matches [ 8 ] , 10 ) ;
offsetHour = offsetHour >= 0 && offsetHour <= 23 ? offsetHour : 0 ;
let offsetMinute = parseInt ( matches [ 9 ] , 10 ) || 0 ;
offsetMinute = offsetMinute >= 0 && offsetMinute <= 59 ? offsetMinute : 0 ;
if ( universalTimeRelation === "-" ) {
hour += offsetHour ;
minute += offsetMinute ;
} else if ( universalTimeRelation === "+" ) {
hour -= offsetHour ;
minute -= offsetMinute ;
2013-02-21 14:09:23 +00:00
}
2024-06-01 11:00:27 +01:00
return new Date ( Date . UTC ( year , month , day , hour , minute , second ) ) ;
2013-02-21 14:09:23 +00:00
}
2013-12-31 16:34:23 +05:30
}
2024-06-01 11:00:27 +01:00
function getXfaPageViewport ( xfaPage , {
scale = 1 ,
rotation = 0
} ) {
const {
width ,
height
} = xfaPage . attributes . style ;
const viewBox = [ 0 , 0 , parseInt ( width ) , parseInt ( height ) ] ;
return new PageViewport ( {
viewBox ,
scale ,
rotation
} ) ;
}
function getRGB ( color ) {
if ( color . startsWith ( "#" ) ) {
const colorRGB = parseInt ( color . slice ( 1 ) , 16 ) ;
return [ ( colorRGB & 0xff0000 ) >> 16 , ( colorRGB & 0x00ff00 ) >> 8 , colorRGB & 0x0000ff ] ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
if ( color . startsWith ( "rgb(" ) ) {
return color . slice ( 4 , - 1 ) . split ( "," ) . map ( x => parseInt ( x ) ) ;
}
if ( color . startsWith ( "rgba(" ) ) {
return color . slice ( 5 , - 1 ) . split ( "," ) . map ( x => parseInt ( x ) ) . slice ( 0 , 3 ) ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
warn ( ` Not a valid color format: " ${ color } " ` ) ;
return [ 0 , 0 , 0 ] ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
function getColorValues ( colors ) {
const span = document . createElement ( "span" ) ;
span . style . visibility = "hidden" ;
document . body . append ( span ) ;
for ( const name of colors . keys ( ) ) {
span . style . color = name ;
const computedColor = window . getComputedStyle ( span ) . color ;
colors . set ( name , getRGB ( computedColor ) ) ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
span . remove ( ) ;
}
function getCurrentTransform ( ctx ) {
const {
a ,
b ,
c ,
d ,
e ,
f
} = ctx . getTransform ( ) ;
return [ a , b , c , d , e , f ] ;
}
function getCurrentTransformInverse ( ctx ) {
const {
a ,
b ,
c ,
d ,
e ,
f
} = ctx . getTransform ( ) . invertSelf ( ) ;
return [ a , b , c , d , e , f ] ;
}
function setLayerDimensions ( div , viewport , mustFlip = false , mustRotate = true ) {
if ( viewport instanceof PageViewport ) {
const {
pageWidth ,
pageHeight
} = viewport . rawDims ;
const {
style
} = div ;
const useRound = util _FeatureTest . isCSSRoundSupported ;
const w = ` var(--scale-factor) * ${ pageWidth } px ` ,
h = ` var(--scale-factor) * ${ pageHeight } px ` ;
const widthStr = useRound ? ` round( ${ w } , 1px) ` : ` calc( ${ w } ) ` ,
heightStr = useRound ? ` round( ${ h } , 1px) ` : ` calc( ${ h } ) ` ;
if ( ! mustFlip || viewport . rotation % 180 === 0 ) {
style . width = widthStr ;
style . height = heightStr ;
} else {
style . width = heightStr ;
style . height = widthStr ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
}
if ( mustRotate ) {
div . setAttribute ( "data-main-rotation" , viewport . rotation ) ;
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
; // CONCATENATED MODULE: ./src/display/editor/toolbar.js
class EditorToolbar {
# toolbar = null ;
# colorPicker = null ;
# editor ;
# buttons = null ;
constructor ( editor ) {
this . # editor = editor ;
}
render ( ) {
const editToolbar = this . # toolbar = document . createElement ( "div" ) ;
editToolbar . className = "editToolbar" ;
editToolbar . setAttribute ( "role" , "toolbar" ) ;
editToolbar . addEventListener ( "contextmenu" , noContextMenu ) ;
editToolbar . addEventListener ( "pointerdown" , EditorToolbar . # pointerDown ) ;
const buttons = this . # buttons = document . createElement ( "div" ) ;
buttons . className = "buttons" ;
editToolbar . append ( buttons ) ;
const position = this . # editor . toolbarPosition ;
if ( position ) {
const {
style
} = editToolbar ;
const x = this . # editor . _uiManager . direction === "ltr" ? 1 - position [ 0 ] : position [ 0 ] ;
style . insetInlineEnd = ` ${ 100 * x } % ` ;
style . top = ` calc( ${ 100 * position [ 1 ] } % + var(--editor-toolbar-vert-offset)) ` ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
this . # addDeleteButton ( ) ;
return editToolbar ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
static # pointerDown ( e ) {
e . stopPropagation ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
# focusIn ( e ) {
this . # editor . _focusEventsAllowed = false ;
e . preventDefault ( ) ;
e . stopPropagation ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
# focusOut ( e ) {
this . # editor . _focusEventsAllowed = true ;
e . preventDefault ( ) ;
e . stopPropagation ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
# addListenersToElement ( element ) {
element . addEventListener ( "focusin" , this . # focusIn . bind ( this ) , {
capture : true
} ) ;
element . addEventListener ( "focusout" , this . # focusOut . bind ( this ) , {
capture : true
2023-10-27 13:19:54 +02:00
} ) ;
2024-06-01 11:00:27 +01:00
element . addEventListener ( "contextmenu" , noContextMenu ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
hide ( ) {
this . # toolbar . classList . add ( "hidden" ) ;
this . # colorPicker ? . hideDropdown ( ) ;
}
show ( ) {
this . # toolbar . classList . remove ( "hidden" ) ;
}
# addDeleteButton ( ) {
const button = document . createElement ( "button" ) ;
button . className = "delete" ;
button . tabIndex = 0 ;
button . setAttribute ( "data-l10n-id" , ` pdfjs-editor-remove- ${ this . # editor . editorType } -button ` ) ;
this . # addListenersToElement ( button ) ;
button . addEventListener ( "click" , e => {
this . # editor . _uiManager . delete ( ) ;
} ) ;
this . # buttons . append ( button ) ;
}
get # divider ( ) {
const divider = document . createElement ( "div" ) ;
divider . className = "divider" ;
return divider ;
}
addAltTextButton ( button ) {
this . # addListenersToElement ( button ) ;
this . # buttons . prepend ( button , this . # divider ) ;
}
addColorPicker ( colorPicker ) {
this . # colorPicker = colorPicker ;
const button = colorPicker . renderButton ( ) ;
this . # addListenersToElement ( button ) ;
this . # buttons . prepend ( button , this . # divider ) ;
}
remove ( ) {
this . # toolbar . remove ( ) ;
this . # colorPicker ? . destroy ( ) ;
this . # colorPicker = null ;
}
}
class HighlightToolbar {
# buttons = null ;
# toolbar = null ;
# uiManager ;
constructor ( uiManager ) {
this . # uiManager = uiManager ;
}
# render ( ) {
const editToolbar = this . # toolbar = document . createElement ( "div" ) ;
editToolbar . className = "editToolbar" ;
editToolbar . setAttribute ( "role" , "toolbar" ) ;
editToolbar . addEventListener ( "contextmenu" , noContextMenu ) ;
const buttons = this . # buttons = document . createElement ( "div" ) ;
buttons . className = "buttons" ;
editToolbar . append ( buttons ) ;
this . # addHighlightButton ( ) ;
return editToolbar ;
}
# getLastPoint ( boxes , isLTR ) {
let lastY = 0 ;
let lastX = 0 ;
for ( const box of boxes ) {
const y = box . y + box . height ;
if ( y < lastY ) {
continue ;
}
const x = box . x + ( isLTR ? box . width : 0 ) ;
if ( y > lastY ) {
lastX = x ;
lastY = y ;
continue ;
}
if ( isLTR ) {
if ( x > lastX ) {
lastX = x ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
} else if ( x < lastX ) {
lastX = x ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
return [ isLTR ? 1 - lastX : lastX , lastY ] ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
show ( parent , boxes , isLTR ) {
const [ x , y ] = this . # getLastPoint ( boxes , isLTR ) ;
const {
style
} = this . # toolbar || = this . # render ( ) ;
parent . append ( this . # toolbar ) ;
style . insetInlineEnd = ` ${ 100 * x } % ` ;
style . top = ` calc( ${ 100 * y } % + var(--editor-toolbar-vert-offset)) ` ;
}
hide ( ) {
this . # toolbar . remove ( ) ;
}
# addHighlightButton ( ) {
const button = document . createElement ( "button" ) ;
button . className = "highlightButton" ;
button . tabIndex = 0 ;
button . setAttribute ( "data-l10n-id" , ` pdfjs-highlight-floating-button1 ` ) ;
const span = document . createElement ( "span" ) ;
button . append ( span ) ;
span . className = "visuallyHidden" ;
span . setAttribute ( "data-l10n-id" , "pdfjs-highlight-floating-button-label" ) ;
button . addEventListener ( "contextmenu" , noContextMenu ) ;
button . addEventListener ( "click" , ( ) => {
this . # uiManager . highlightSelection ( "floating_button" ) ;
2023-10-27 13:19:54 +02:00
} ) ;
2024-06-01 11:00:27 +01:00
this . # buttons . append ( button ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
}
2024-06-18 20:06:52 +02:00
; // CONCATENATED MODULE: ./src/display/editor/tools.js
2024-06-01 11:00:27 +01:00
function bindEvents ( obj , element , names ) {
for ( const name of names ) {
element . addEventListener ( name , obj [ name ] . bind ( obj ) ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
}
function opacityToHex ( opacity ) {
return Math . round ( Math . min ( 255 , Math . max ( 1 , 255 * opacity ) ) ) . toString ( 16 ) . padStart ( 2 , "0" ) ;
}
class IdManager {
# id = 0 ;
get id ( ) {
return ` ${ AnnotationEditorPrefix } ${ this . # id ++ } ` ;
}
}
class ImageManager {
# baseId = getUuid ( ) ;
# id = 0 ;
# cache = null ;
static get _isSVGFittingCanvas ( ) {
const svg = ` data:image/svg+xml;charset=UTF-8,<svg viewBox="0 0 1 1" width="1" height="1" xmlns="http://www.w3.org/2000/svg"><rect width="1" height="1" style="fill:red;"/></svg> ` ;
const canvas = new OffscreenCanvas ( 1 , 3 ) ;
2024-06-18 20:06:52 +02:00
const ctx = canvas . getContext ( "2d" , {
willReadFrequently : true
} ) ;
2024-06-01 11:00:27 +01:00
const image = new Image ( ) ;
image . src = svg ;
const promise = image . decode ( ) . then ( ( ) => {
ctx . drawImage ( image , 0 , 0 , 1 , 1 , 0 , 0 , 1 , 3 ) ;
return new Uint32Array ( ctx . getImageData ( 0 , 0 , 1 , 1 ) . data . buffer ) [ 0 ] === 0 ;
} ) ;
return shadow ( this , "_isSVGFittingCanvas" , promise ) ;
}
async # get ( key , rawData ) {
this . # cache || = new Map ( ) ;
let data = this . # cache . get ( key ) ;
if ( data === null ) {
return null ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
if ( data ? . bitmap ) {
data . refCounter += 1 ;
return data ;
}
try {
data || = {
bitmap : null ,
id : ` image_ ${ this . # baseId } _ ${ this . # id ++ } ` ,
refCounter : 0 ,
isSvg : false
} ;
let image ;
if ( typeof rawData === "string" ) {
data . url = rawData ;
image = await fetchData ( rawData , "blob" ) ;
} else {
image = data . file = rawData ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
if ( image . type === "image/svg+xml" ) {
const mustRemoveAspectRatioPromise = ImageManager . _isSVGFittingCanvas ;
const fileReader = new FileReader ( ) ;
const imageElement = new Image ( ) ;
const imagePromise = new Promise ( ( resolve , reject ) => {
imageElement . onload = ( ) => {
data . bitmap = imageElement ;
data . isSvg = true ;
resolve ( ) ;
} ;
fileReader . onload = async ( ) => {
const url = data . svgUrl = fileReader . result ;
imageElement . src = ( await mustRemoveAspectRatioPromise ) ? ` ${ url } #svgView(preserveAspectRatio(none)) ` : url ;
} ;
imageElement . onerror = fileReader . onerror = reject ;
} ) ;
fileReader . readAsDataURL ( image ) ;
await imagePromise ;
} else {
data . bitmap = await createImageBitmap ( image ) ;
}
data . refCounter = 1 ;
} catch ( e ) {
console . error ( e ) ;
data = null ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
this . # cache . set ( key , data ) ;
if ( data ) {
this . # cache . set ( data . id , data ) ;
}
return data ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
async getFromFile ( file ) {
const {
lastModified ,
name ,
size ,
type
} = file ;
return this . # get ( ` ${ lastModified } _ ${ name } _ ${ size } _ ${ type } ` , file ) ;
}
async getFromUrl ( url ) {
return this . # get ( url , url ) ;
}
async getFromId ( id ) {
this . # cache || = new Map ( ) ;
const data = this . # cache . get ( id ) ;
if ( ! data ) {
return null ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
if ( data . bitmap ) {
data . refCounter += 1 ;
return data ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
if ( data . file ) {
return this . getFromFile ( data . file ) ;
}
return this . getFromUrl ( data . url ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
getSvgUrl ( id ) {
const data = this . # cache . get ( id ) ;
if ( ! data ? . isSvg ) {
2023-10-27 13:19:54 +02:00
return null ;
}
2024-06-01 11:00:27 +01:00
return data . svgUrl ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
deleteId ( id ) {
this . # cache || = new Map ( ) ;
const data = this . # cache . get ( id ) ;
if ( ! data ) {
return ;
}
data . refCounter -= 1 ;
if ( data . refCounter !== 0 ) {
return ;
}
data . bitmap = null ;
}
isValidId ( id ) {
return id . startsWith ( ` image_ ${ this . # baseId } _ ` ) ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
class CommandManager {
# commands = [ ] ;
# locked = false ;
# maxSize ;
# position = - 1 ;
constructor ( maxSize = 128 ) {
this . # maxSize = maxSize ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
add ( {
cmd ,
undo ,
post ,
mustExec ,
type = NaN ,
overwriteIfSameType = false ,
keepUndo = false
} ) {
if ( mustExec ) {
cmd ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
if ( this . # locked ) {
return ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
const save = {
cmd ,
undo ,
post ,
type
} ;
if ( this . # position === - 1 ) {
if ( this . # commands . length > 0 ) {
this . # commands . length = 0 ;
}
this . # position = 0 ;
this . # commands . push ( save ) ;
return ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
if ( overwriteIfSameType && this . # commands [ this . # position ] . type === type ) {
if ( keepUndo ) {
save . undo = this . # commands [ this . # position ] . undo ;
}
this . # commands [ this . # position ] = save ;
return ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
const next = this . # position + 1 ;
if ( next === this . # maxSize ) {
this . # commands . splice ( 0 , 1 ) ;
} else {
this . # position = next ;
if ( next < this . # commands . length ) {
this . # commands . splice ( next ) ;
}
}
this . # commands . push ( save ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
undo ( ) {
if ( this . # position === - 1 ) {
return ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
this . # locked = true ;
const {
undo ,
post
} = this . # commands [ this . # position ] ;
undo ( ) ;
post ? . ( ) ;
this . # locked = false ;
this . # position -= 1 ;
}
redo ( ) {
if ( this . # position < this . # commands . length - 1 ) {
this . # position += 1 ;
this . # locked = true ;
const {
cmd ,
post
} = this . # commands [ this . # position ] ;
cmd ( ) ;
post ? . ( ) ;
this . # locked = false ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
hasSomethingToUndo ( ) {
return this . # position !== - 1 ;
}
hasSomethingToRedo ( ) {
return this . # position < this . # commands . length - 1 ;
}
destroy ( ) {
this . # commands = null ;
}
}
class KeyboardManager {
constructor ( callbacks ) {
this . buffer = [ ] ;
this . callbacks = new Map ( ) ;
this . allKeys = new Set ( ) ;
2023-10-27 13:19:54 +02:00
const {
2024-06-01 11:00:27 +01:00
isMac
} = util _FeatureTest . platform ;
for ( const [ keys , callback , options = { } ] of callbacks ) {
for ( const key of keys ) {
const isMacKey = key . startsWith ( "mac+" ) ;
if ( isMac && isMacKey ) {
this . callbacks . set ( key . slice ( 4 ) , {
callback ,
options
} ) ;
this . allKeys . add ( key . split ( "+" ) . at ( - 1 ) ) ;
} else if ( ! isMac && ! isMacKey ) {
this . callbacks . set ( key , {
callback ,
options
} ) ;
this . allKeys . add ( key . split ( "+" ) . at ( - 1 ) ) ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
}
}
# serialize ( event ) {
if ( event . altKey ) {
this . buffer . push ( "alt" ) ;
}
if ( event . ctrlKey ) {
this . buffer . push ( "ctrl" ) ;
}
if ( event . metaKey ) {
this . buffer . push ( "meta" ) ;
}
if ( event . shiftKey ) {
this . buffer . push ( "shift" ) ;
}
this . buffer . push ( event . key ) ;
const str = this . buffer . join ( "+" ) ;
this . buffer . length = 0 ;
return str ;
}
exec ( self , event ) {
if ( ! this . allKeys . has ( event . key ) ) {
return ;
}
const info = this . callbacks . get ( this . # serialize ( event ) ) ;
if ( ! info ) {
return ;
}
const {
callback ,
options : {
bubbles = false ,
args = [ ] ,
checker = null
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
} = info ;
if ( checker && ! checker ( self , event ) ) {
return ;
}
callback . bind ( self , ... args , event ) ( ) ;
if ( ! bubbles ) {
event . stopPropagation ( ) ;
event . preventDefault ( ) ;
}
}
}
class ColorManager {
static _colorsMapping = new Map ( [ [ "CanvasText" , [ 0 , 0 , 0 ] ] , [ "Canvas" , [ 255 , 255 , 255 ] ] ] ) ;
get _colors ( ) {
const colors = new Map ( [ [ "CanvasText" , null ] , [ "Canvas" , null ] ] ) ;
getColorValues ( colors ) ;
return shadow ( this , "_colors" , colors ) ;
}
convert ( color ) {
const rgb = getRGB ( color ) ;
if ( ! window . matchMedia ( "(forced-colors: active)" ) . matches ) {
return rgb ;
}
for ( const [ name , RGB ] of this . _colors ) {
if ( RGB . every ( ( x , i ) => x === rgb [ i ] ) ) {
return ColorManager . _colorsMapping . get ( name ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
}
return rgb ;
}
getHexCode ( name ) {
const rgb = this . _colors . get ( name ) ;
if ( ! rgb ) {
return name ;
}
return Util . makeHexColor ( ... rgb ) ;
}
}
class AnnotationEditorUIManager {
# activeEditor = null ;
# allEditors = new Map ( ) ;
# allLayers = new Map ( ) ;
# altTextManager = null ;
# annotationStorage = null ;
# changedExistingAnnotations = null ;
# commandManager = new CommandManager ( ) ;
# currentPageIndex = 0 ;
# deletedAnnotationsElementIds = new Set ( ) ;
# draggingEditors = null ;
# editorTypes = null ;
# editorsToRescale = new Set ( ) ;
# enableHighlightFloatingButton = false ;
# filterFactory = null ;
# focusMainContainerTimeoutId = null ;
# highlightColors = null ;
# highlightWhenShiftUp = false ;
# highlightToolbar = null ;
# idManager = new IdManager ( ) ;
# isEnabled = false ;
# isWaiting = false ;
# lastActiveElement = null ;
# mainHighlightColorPicker = null ;
# mlManager = null ;
# mode = AnnotationEditorType . NONE ;
# selectedEditors = new Set ( ) ;
# selectedTextNode = null ;
# pageColors = null ;
# showAllStates = null ;
# boundBlur = this . blur . bind ( this ) ;
# boundFocus = this . focus . bind ( this ) ;
# boundCopy = this . copy . bind ( this ) ;
# boundCut = this . cut . bind ( this ) ;
2024-06-18 20:06:52 +02:00
# boundDragOver = this . dragOver . bind ( this ) ;
# boundDrop = this . drop . bind ( this ) ;
2024-06-01 11:00:27 +01:00
# boundPaste = this . paste . bind ( this ) ;
# boundKeydown = this . keydown . bind ( this ) ;
# boundKeyup = this . keyup . bind ( this ) ;
# boundOnEditingAction = this . onEditingAction . bind ( this ) ;
# boundOnPageChanging = this . onPageChanging . bind ( this ) ;
# boundOnScaleChanging = this . onScaleChanging . bind ( this ) ;
# boundSelectionChange = this . # selectionChange . bind ( this ) ;
# boundOnRotationChanging = this . onRotationChanging . bind ( this ) ;
# previousStates = {
isEditing : false ,
isEmpty : true ,
hasSomethingToUndo : false ,
hasSomethingToRedo : false ,
hasSelectedEditor : false ,
hasSelectedText : false
} ;
# translation = [ 0 , 0 ] ;
# translationTimeoutId = null ;
# container = null ;
# viewer = null ;
static TRANSLATE _SMALL = 1 ;
static TRANSLATE _BIG = 10 ;
static get _keyboardManager ( ) {
const proto = AnnotationEditorUIManager . prototype ;
const arrowChecker = self => self . # container . contains ( document . activeElement ) && document . activeElement . tagName !== "BUTTON" && self . hasSomethingToControl ( ) ;
const textInputChecker = ( _self , {
target : el
} ) => {
if ( el instanceof HTMLInputElement ) {
const {
type
} = el ;
return type !== "text" && type !== "number" ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
return true ;
} ;
const small = this . TRANSLATE _SMALL ;
const big = this . TRANSLATE _BIG ;
return shadow ( this , "_keyboardManager" , new KeyboardManager ( [ [ [ "ctrl+a" , "mac+meta+a" ] , proto . selectAll , {
checker : textInputChecker
} ] , [ [ "ctrl+z" , "mac+meta+z" ] , proto . undo , {
checker : textInputChecker
} ] , [ [ "ctrl+y" , "ctrl+shift+z" , "mac+meta+shift+z" , "ctrl+shift+Z" , "mac+meta+shift+Z" ] , proto . redo , {
checker : textInputChecker
} ] , [ [ "Backspace" , "alt+Backspace" , "ctrl+Backspace" , "shift+Backspace" , "mac+Backspace" , "mac+alt+Backspace" , "mac+ctrl+Backspace" , "Delete" , "ctrl+Delete" , "shift+Delete" , "mac+Delete" ] , proto . delete , {
checker : textInputChecker
} ] , [ [ "Enter" , "mac+Enter" ] , proto . addNewEditorFromKeyboard , {
checker : ( self , {
target : el
} ) => ! ( el instanceof HTMLButtonElement ) && self . # container . contains ( el ) && ! self . isEnterHandled
} ] , [ [ " " , "mac+ " ] , proto . addNewEditorFromKeyboard , {
checker : ( self , {
target : el
} ) => ! ( el instanceof HTMLButtonElement ) && self . # container . contains ( document . activeElement )
} ] , [ [ "Escape" , "mac+Escape" ] , proto . unselectAll ] , [ [ "ArrowLeft" , "mac+ArrowLeft" ] , proto . translateSelectedEditors , {
args : [ - small , 0 ] ,
checker : arrowChecker
} ] , [ [ "ctrl+ArrowLeft" , "mac+shift+ArrowLeft" ] , proto . translateSelectedEditors , {
args : [ - big , 0 ] ,
checker : arrowChecker
} ] , [ [ "ArrowRight" , "mac+ArrowRight" ] , proto . translateSelectedEditors , {
args : [ small , 0 ] ,
checker : arrowChecker
} ] , [ [ "ctrl+ArrowRight" , "mac+shift+ArrowRight" ] , proto . translateSelectedEditors , {
args : [ big , 0 ] ,
checker : arrowChecker
} ] , [ [ "ArrowUp" , "mac+ArrowUp" ] , proto . translateSelectedEditors , {
args : [ 0 , - small ] ,
checker : arrowChecker
} ] , [ [ "ctrl+ArrowUp" , "mac+shift+ArrowUp" ] , proto . translateSelectedEditors , {
args : [ 0 , - big ] ,
checker : arrowChecker
} ] , [ [ "ArrowDown" , "mac+ArrowDown" ] , proto . translateSelectedEditors , {
args : [ 0 , small ] ,
checker : arrowChecker
} ] , [ [ "ctrl+ArrowDown" , "mac+shift+ArrowDown" ] , proto . translateSelectedEditors , {
args : [ 0 , big ] ,
checker : arrowChecker
} ] ] ) ) ;
2013-12-31 16:34:23 +05:30
}
2024-06-01 11:00:27 +01:00
constructor ( container , viewer , altTextManager , eventBus , pdfDocument , pageColors , highlightColors , enableHighlightFloatingButton , mlManager ) {
this . # container = container ;
this . # viewer = viewer ;
this . # altTextManager = altTextManager ;
this . _eventBus = eventBus ;
this . _eventBus . _on ( "editingaction" , this . # boundOnEditingAction ) ;
this . _eventBus . _on ( "pagechanging" , this . # boundOnPageChanging ) ;
this . _eventBus . _on ( "scalechanging" , this . # boundOnScaleChanging ) ;
this . _eventBus . _on ( "rotationchanging" , this . # boundOnRotationChanging ) ;
this . # addSelectionListener ( ) ;
2024-06-18 20:06:52 +02:00
this . # addDragAndDropListeners ( ) ;
2024-06-01 11:00:27 +01:00
this . # addKeyboardManager ( ) ;
this . # annotationStorage = pdfDocument . annotationStorage ;
this . # filterFactory = pdfDocument . filterFactory ;
this . # pageColors = pageColors ;
this . # highlightColors = highlightColors || null ;
this . # enableHighlightFloatingButton = enableHighlightFloatingButton ;
this . # mlManager = mlManager || null ;
this . viewParameters = {
realScale : PixelsPerInch . PDF _TO _CSS _UNITS ,
rotation : 0
} ;
this . isShiftKeyDown = false ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
destroy ( ) {
2024-06-18 20:06:52 +02:00
this . # removeDragAndDropListeners ( ) ;
2024-06-01 11:00:27 +01:00
this . # removeKeyboardManager ( ) ;
this . # removeFocusManager ( ) ;
this . _eventBus . _off ( "editingaction" , this . # boundOnEditingAction ) ;
this . _eventBus . _off ( "pagechanging" , this . # boundOnPageChanging ) ;
this . _eventBus . _off ( "scalechanging" , this . # boundOnScaleChanging ) ;
this . _eventBus . _off ( "rotationchanging" , this . # boundOnRotationChanging ) ;
for ( const layer of this . # allLayers . values ( ) ) {
layer . destroy ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
this . # allLayers . clear ( ) ;
this . # allEditors . clear ( ) ;
this . # editorsToRescale . clear ( ) ;
this . # activeEditor = null ;
this . # selectedEditors . clear ( ) ;
this . # commandManager . destroy ( ) ;
this . # altTextManager ? . destroy ( ) ;
this . # highlightToolbar ? . hide ( ) ;
this . # highlightToolbar = null ;
if ( this . # focusMainContainerTimeoutId ) {
clearTimeout ( this . # focusMainContainerTimeoutId ) ;
this . # focusMainContainerTimeoutId = null ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
if ( this . # translationTimeoutId ) {
clearTimeout ( this . # translationTimeoutId ) ;
this . # translationTimeoutId = null ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
this . # removeSelectionListener ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
async mlGuess ( data ) {
return this . # mlManager ? . guess ( data ) || null ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
get hasMLManager ( ) {
return ! ! this . # mlManager ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
get hcmFilter ( ) {
return shadow ( this , "hcmFilter" , this . # pageColors ? this . # filterFactory . addHCMFilter ( this . # pageColors . foreground , this . # pageColors . background ) : "none" ) ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
get direction ( ) {
return shadow ( this , "direction" , getComputedStyle ( this . # container ) . direction ) ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
get highlightColors ( ) {
return shadow ( this , "highlightColors" , this . # highlightColors ? new Map ( this . # highlightColors . split ( "," ) . map ( pair => pair . split ( "=" ) . map ( x => x . trim ( ) ) ) ) : null ) ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
get highlightColorNames ( ) {
return shadow ( this , "highlightColorNames" , this . highlightColors ? new Map ( Array . from ( this . highlightColors , e => e . reverse ( ) ) ) : null ) ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
setMainHighlightColorPicker ( colorPicker ) {
this . # mainHighlightColorPicker = colorPicker ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
editAltText ( editor ) {
this . # altTextManager ? . editAltText ( this , editor ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
onPageChanging ( {
pageNumber
} ) {
this . # currentPageIndex = pageNumber - 1 ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
focusMainContainer ( ) {
this . # container . focus ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
findParent ( x , y ) {
for ( const layer of this . # allLayers . values ( ) ) {
const {
x : layerX ,
y : layerY ,
width ,
height
} = layer . div . getBoundingClientRect ( ) ;
if ( x >= layerX && x <= layerX + width && y >= layerY && y <= layerY + height ) {
return layer ;
}
}
return null ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
disableUserSelect ( value = false ) {
this . # viewer . classList . toggle ( "noUserSelect" , value ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
addShouldRescale ( editor ) {
this . # editorsToRescale . add ( editor ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
removeShouldRescale ( editor ) {
this . # editorsToRescale . delete ( editor ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
onScaleChanging ( {
scale
} ) {
this . commitOrRemove ( ) ;
this . viewParameters . realScale = scale * PixelsPerInch . PDF _TO _CSS _UNITS ;
for ( const editor of this . # editorsToRescale ) {
editor . onScaleChanging ( ) ;
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
onRotationChanging ( {
pagesRotation
} ) {
this . commitOrRemove ( ) ;
this . viewParameters . rotation = pagesRotation ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
# getAnchorElementForSelection ( {
anchorNode
} ) {
return anchorNode . nodeType === Node . TEXT _NODE ? anchorNode . parentElement : anchorNode ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
highlightSelection ( methodOfCreation = "" ) {
const selection = document . getSelection ( ) ;
if ( ! selection || selection . isCollapsed ) {
return ;
}
const {
anchorNode ,
anchorOffset ,
focusNode ,
focusOffset
} = selection ;
const text = selection . toString ( ) ;
const anchorElement = this . # getAnchorElementForSelection ( selection ) ;
const textLayer = anchorElement . closest ( ".textLayer" ) ;
const boxes = this . getSelectionBoxes ( textLayer ) ;
if ( ! boxes ) {
return ;
}
selection . empty ( ) ;
if ( this . # mode === AnnotationEditorType . NONE ) {
this . _eventBus . dispatch ( "showannotationeditorui" , {
source : this ,
mode : AnnotationEditorType . HIGHLIGHT
} ) ;
this . showAllEditors ( "highlight" , true , true ) ;
}
for ( const layer of this . # allLayers . values ( ) ) {
if ( layer . hasTextLayer ( textLayer ) ) {
layer . createAndAddNewEditor ( {
x : 0 ,
y : 0
} , false , {
methodOfCreation ,
boxes ,
anchorNode ,
anchorOffset ,
focusNode ,
focusOffset ,
text
} ) ;
break ;
}
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
# displayHighlightToolbar ( ) {
const selection = document . getSelection ( ) ;
if ( ! selection || selection . isCollapsed ) {
return ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
const anchorElement = this . # getAnchorElementForSelection ( selection ) ;
const textLayer = anchorElement . closest ( ".textLayer" ) ;
const boxes = this . getSelectionBoxes ( textLayer ) ;
if ( ! boxes ) {
return ;
}
this . # highlightToolbar || = new HighlightToolbar ( this ) ;
this . # highlightToolbar . show ( textLayer , boxes , this . direction === "ltr" ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
addToAnnotationStorage ( editor ) {
if ( ! editor . isEmpty ( ) && this . # annotationStorage && ! this . # annotationStorage . has ( editor . id ) ) {
this . # annotationStorage . setValue ( editor . id , editor ) ;
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
# selectionChange ( ) {
const selection = document . getSelection ( ) ;
if ( ! selection || selection . isCollapsed ) {
if ( this . # selectedTextNode ) {
this . # highlightToolbar ? . hide ( ) ;
this . # selectedTextNode = null ;
this . # dispatchUpdateStates ( {
hasSelectedText : false
} ) ;
}
2023-10-27 13:19:54 +02:00
return ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
const {
anchorNode
} = selection ;
if ( anchorNode === this . # selectedTextNode ) {
return ;
}
const anchorElement = this . # getAnchorElementForSelection ( selection ) ;
const textLayer = anchorElement . closest ( ".textLayer" ) ;
if ( ! textLayer ) {
if ( this . # selectedTextNode ) {
this . # highlightToolbar ? . hide ( ) ;
this . # selectedTextNode = null ;
this . # dispatchUpdateStates ( {
hasSelectedText : false
} ) ;
2013-12-31 16:34:23 +05:30
}
2024-06-01 11:00:27 +01:00
return ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
this . # highlightToolbar ? . hide ( ) ;
this . # selectedTextNode = anchorNode ;
this . # dispatchUpdateStates ( {
hasSelectedText : true
} ) ;
if ( this . # mode !== AnnotationEditorType . HIGHLIGHT && this . # mode !== AnnotationEditorType . NONE ) {
return ;
}
if ( this . # mode === AnnotationEditorType . HIGHLIGHT ) {
this . showAllEditors ( "highlight" , true , true ) ;
}
this . # highlightWhenShiftUp = this . isShiftKeyDown ;
if ( ! this . isShiftKeyDown ) {
const pointerup = e => {
if ( e . type === "pointerup" && e . button !== 0 ) {
return ;
}
window . removeEventListener ( "pointerup" , pointerup ) ;
window . removeEventListener ( "blur" , pointerup ) ;
if ( e . type === "pointerup" ) {
this . # onSelectEnd ( "main_toolbar" ) ;
}
} ;
window . addEventListener ( "pointerup" , pointerup ) ;
window . addEventListener ( "blur" , pointerup ) ;
2016-04-04 15:49:28 +02:00
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
# onSelectEnd ( methodOfCreation = "" ) {
if ( this . # mode === AnnotationEditorType . HIGHLIGHT ) {
this . highlightSelection ( methodOfCreation ) ;
} else if ( this . # enableHighlightFloatingButton ) {
this . # displayHighlightToolbar ( ) ;
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
# addSelectionListener ( ) {
document . addEventListener ( "selectionchange" , this . # boundSelectionChange ) ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
# removeSelectionListener ( ) {
document . removeEventListener ( "selectionchange" , this . # boundSelectionChange ) ;
}
# addFocusManager ( ) {
window . addEventListener ( "focus" , this . # boundFocus ) ;
window . addEventListener ( "blur" , this . # boundBlur ) ;
}
# removeFocusManager ( ) {
window . removeEventListener ( "focus" , this . # boundFocus ) ;
window . removeEventListener ( "blur" , this . # boundBlur ) ;
}
blur ( ) {
this . isShiftKeyDown = false ;
if ( this . # highlightWhenShiftUp ) {
this . # highlightWhenShiftUp = false ;
this . # onSelectEnd ( "main_toolbar" ) ;
2014-11-24 00:56:52 +01:00
}
2024-06-01 11:00:27 +01:00
if ( ! this . hasSelection ) {
return ;
}
const {
activeElement
} = document ;
for ( const editor of this . # selectedEditors ) {
if ( editor . div . contains ( activeElement ) ) {
this . # lastActiveElement = [ editor , activeElement ] ;
editor . _focusEventsAllowed = false ;
break ;
}
2023-10-27 13:19:54 +02:00
}
2014-11-24 00:56:52 +01:00
}
2024-06-01 11:00:27 +01:00
focus ( ) {
if ( ! this . # lastActiveElement ) {
return ;
}
const [ lastEditor , lastActiveElement ] = this . # lastActiveElement ;
this . # lastActiveElement = null ;
lastActiveElement . addEventListener ( "focusin" , ( ) => {
lastEditor . _focusEventsAllowed = true ;
} , {
once : true
} ) ;
lastActiveElement . focus ( ) ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
# addKeyboardManager ( ) {
window . addEventListener ( "keydown" , this . # boundKeydown ) ;
window . addEventListener ( "keyup" , this . # boundKeyup ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
# removeKeyboardManager ( ) {
window . removeEventListener ( "keydown" , this . # boundKeydown ) ;
window . removeEventListener ( "keyup" , this . # boundKeyup ) ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
# addCopyPasteListeners ( ) {
document . addEventListener ( "copy" , this . # boundCopy ) ;
document . addEventListener ( "cut" , this . # boundCut ) ;
document . addEventListener ( "paste" , this . # boundPaste ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
# removeCopyPasteListeners ( ) {
document . removeEventListener ( "copy" , this . # boundCopy ) ;
document . removeEventListener ( "cut" , this . # boundCut ) ;
document . removeEventListener ( "paste" , this . # boundPaste ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-18 20:06:52 +02:00
# addDragAndDropListeners ( ) {
document . addEventListener ( "dragover" , this . # boundDragOver ) ;
document . addEventListener ( "drop" , this . # boundDrop ) ;
}
# removeDragAndDropListeners ( ) {
document . removeEventListener ( "dragover" , this . # boundDragOver ) ;
document . removeEventListener ( "drop" , this . # boundDrop ) ;
}
2024-06-01 11:00:27 +01:00
addEditListeners ( ) {
this . # addKeyboardManager ( ) ;
this . # addCopyPasteListeners ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
removeEditListeners ( ) {
this . # removeKeyboardManager ( ) ;
this . # removeCopyPasteListeners ( ) ;
2016-04-04 15:49:28 +02:00
}
2024-06-18 20:06:52 +02:00
dragOver ( event ) {
for ( const {
type
} of event . dataTransfer . items ) {
for ( const editorType of this . # editorTypes ) {
if ( editorType . isHandlingMimeForPasting ( type ) ) {
event . dataTransfer . dropEffect = "copy" ;
event . preventDefault ( ) ;
return ;
}
}
}
}
drop ( event ) {
for ( const item of event . dataTransfer . items ) {
for ( const editorType of this . # editorTypes ) {
if ( editorType . isHandlingMimeForPasting ( item . type ) ) {
editorType . paste ( item , this . currentLayer ) ;
event . preventDefault ( ) ;
return ;
}
}
}
}
2024-06-01 11:00:27 +01:00
copy ( event ) {
event . preventDefault ( ) ;
this . # activeEditor ? . commitOrRemove ( ) ;
if ( ! this . hasSelection ) {
2023-10-27 13:19:54 +02:00
return ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
const editors = [ ] ;
for ( const editor of this . # selectedEditors ) {
const serialized = editor . serialize ( true ) ;
if ( serialized ) {
editors . push ( serialized ) ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
if ( editors . length === 0 ) {
return ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
event . clipboardData . setData ( "application/pdfjs" , JSON . stringify ( editors ) ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
cut ( event ) {
this . copy ( event ) ;
this . delete ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
paste ( event ) {
event . preventDefault ( ) ;
const {
clipboardData
} = event ;
for ( const item of clipboardData . items ) {
for ( const editorType of this . # editorTypes ) {
if ( editorType . isHandlingMimeForPasting ( item . type ) ) {
editorType . paste ( item , this . currentLayer ) ;
return ;
}
}
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
let data = clipboardData . getData ( "application/pdfjs" ) ;
if ( ! data ) {
2023-10-27 13:19:54 +02:00
return ;
}
2024-06-01 11:00:27 +01:00
try {
data = JSON . parse ( data ) ;
} catch ( ex ) {
warn ( ` paste: " ${ ex . message } ". ` ) ;
2023-10-27 13:19:54 +02:00
return ;
}
2024-06-01 11:00:27 +01:00
if ( ! Array . isArray ( data ) ) {
2023-10-27 13:19:54 +02:00
return ;
}
2024-06-01 11:00:27 +01:00
this . unselectAll ( ) ;
const layer = this . currentLayer ;
try {
const newEditors = [ ] ;
for ( const editor of data ) {
const deserializedEditor = layer . deserialize ( editor ) ;
if ( ! deserializedEditor ) {
2023-10-27 13:19:54 +02:00
return ;
}
2024-06-01 11:00:27 +01:00
newEditors . push ( deserializedEditor ) ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
const cmd = ( ) => {
for ( const editor of newEditors ) {
this . # addEditorToLayer ( editor ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
this . # selectEditors ( newEditors ) ;
} ;
const undo = ( ) => {
for ( const editor of newEditors ) {
editor . remove ( ) ;
}
} ;
this . addCommands ( {
cmd ,
undo ,
mustExec : true
} ) ;
} catch ( ex ) {
warn ( ` paste: " ${ ex . message } ". ` ) ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
}
keydown ( event ) {
if ( ! this . isShiftKeyDown && event . key === "Shift" ) {
this . isShiftKeyDown = true ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
if ( this . # mode !== AnnotationEditorType . NONE && ! this . isEditorHandlingKeyboard ) {
AnnotationEditorUIManager . _keyboardManager . exec ( this , event ) ;
2016-04-04 15:49:28 +02:00
}
}
2024-06-01 11:00:27 +01:00
keyup ( event ) {
if ( this . isShiftKeyDown && event . key === "Shift" ) {
this . isShiftKeyDown = false ;
if ( this . # highlightWhenShiftUp ) {
this . # highlightWhenShiftUp = false ;
this . # onSelectEnd ( "main_toolbar" ) ;
}
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
onEditingAction ( {
name
} ) {
switch ( name ) {
case "undo" :
case "redo" :
case "delete" :
case "selectAll" :
this [ name ] ( ) ;
break ;
case "highlightSelection" :
this . highlightSelection ( "context_menu" ) ;
break ;
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
# dispatchUpdateStates ( details ) {
const hasChanged = Object . entries ( details ) . some ( ( [ key , value ] ) => this . # previousStates [ key ] !== value ) ;
if ( hasChanged ) {
this . _eventBus . dispatch ( "annotationeditorstateschanged" , {
source : this ,
details : Object . assign ( this . # previousStates , details )
} ) ;
if ( this . # mode === AnnotationEditorType . HIGHLIGHT && details . hasSelectedEditor === false ) {
this . # dispatchUpdateUI ( [ [ AnnotationEditorParamsType . HIGHLIGHT _FREE , true ] ] ) ;
2016-04-04 15:49:28 +02:00
}
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
# dispatchUpdateUI ( details ) {
this . _eventBus . dispatch ( "annotationeditorparamschanged" , {
source : this ,
details
} ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
setEditingState ( isEditing ) {
if ( isEditing ) {
this . # addFocusManager ( ) ;
this . # addCopyPasteListeners ( ) ;
this . # dispatchUpdateStates ( {
isEditing : this . # mode !== AnnotationEditorType . NONE ,
isEmpty : this . # isEmpty ( ) ,
hasSomethingToUndo : this . # commandManager . hasSomethingToUndo ( ) ,
hasSomethingToRedo : this . # commandManager . hasSomethingToRedo ( ) ,
hasSelectedEditor : false
} ) ;
} else {
this . # removeFocusManager ( ) ;
this . # removeCopyPasteListeners ( ) ;
this . # dispatchUpdateStates ( {
isEditing : false
} ) ;
this . disableUserSelect ( false ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
}
registerEditorTypes ( types ) {
if ( this . # editorTypes ) {
return ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
this . # editorTypes = types ;
for ( const editorType of this . # editorTypes ) {
this . # dispatchUpdateUI ( editorType . defaultPropertiesToUpdate ) ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
getId ( ) {
return this . # idManager . id ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
get currentLayer ( ) {
return this . # allLayers . get ( this . # currentPageIndex ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
getLayer ( pageIndex ) {
return this . # allLayers . get ( pageIndex ) ;
2013-12-31 16:34:23 +05:30
}
2024-06-01 11:00:27 +01:00
get currentPageIndex ( ) {
return this . # currentPageIndex ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
addLayer ( layer ) {
this . # allLayers . set ( layer . pageIndex , layer ) ;
if ( this . # isEnabled ) {
layer . enable ( ) ;
} else {
layer . disable ( ) ;
}
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
removeLayer ( layer ) {
this . # allLayers . delete ( layer . pageIndex ) ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
updateMode ( mode , editId = null , isFromKeyboard = false ) {
if ( this . # mode === mode ) {
return ;
2013-02-21 14:09:23 +00:00
}
2024-06-01 11:00:27 +01:00
this . # mode = mode ;
if ( mode === AnnotationEditorType . NONE ) {
this . setEditingState ( false ) ;
this . # disableAll ( ) ;
2023-10-27 13:19:54 +02:00
return ;
2014-11-24 00:56:52 +01:00
}
2024-06-01 11:00:27 +01:00
this . setEditingState ( true ) ;
this . # enableAll ( ) ;
this . unselectAll ( ) ;
for ( const layer of this . # allLayers . values ( ) ) {
layer . updateMode ( mode ) ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
if ( ! editId && isFromKeyboard ) {
this . addNewEditorFromKeyboard ( ) ;
return ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
if ( ! editId ) {
2023-10-27 13:19:54 +02:00
return ;
2014-11-24 00:56:52 +01:00
}
2024-06-01 11:00:27 +01:00
for ( const editor of this . # allEditors . values ( ) ) {
if ( editor . annotationElementId === editId ) {
this . setSelected ( editor ) ;
editor . enterInEditMode ( ) ;
break ;
}
2013-12-31 16:34:23 +05:30
}
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
addNewEditorFromKeyboard ( ) {
if ( this . currentLayer . canCreateNewEmptyEditor ( ) ) {
this . currentLayer . addNewEditor ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
}
updateToolbar ( mode ) {
if ( mode === this . # mode ) {
2023-10-27 13:19:54 +02:00
return ;
}
2024-06-01 11:00:27 +01:00
this . _eventBus . dispatch ( "switchannotationeditormode" , {
source : this ,
mode
} ) ;
}
updateParams ( type , value ) {
if ( ! this . # editorTypes ) {
2023-10-27 13:19:54 +02:00
return ;
}
2024-06-01 11:00:27 +01:00
switch ( type ) {
case AnnotationEditorParamsType . CREATE :
this . currentLayer . addNewEditor ( ) ;
return ;
case AnnotationEditorParamsType . HIGHLIGHT _DEFAULT _COLOR :
this . # mainHighlightColorPicker ? . updateColor ( value ) ;
break ;
case AnnotationEditorParamsType . HIGHLIGHT _SHOW _ALL :
this . _eventBus . dispatch ( "reporttelemetry" , {
source : this ,
details : {
type : "editing" ,
data : {
type : "highlight" ,
action : "toggle_visibility"
}
}
} ) ;
( this . # showAllStates || = new Map ( ) ) . set ( type , value ) ;
this . showAllEditors ( "highlight" , value ) ;
break ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
for ( const editor of this . # selectedEditors ) {
editor . updateParams ( type , value ) ;
}
for ( const editorType of this . # editorTypes ) {
editorType . updateDefaultParams ( type , value ) ;
2016-04-04 15:49:28 +02:00
}
}
2024-06-01 11:00:27 +01:00
showAllEditors ( type , visible , updateButton = false ) {
for ( const editor of this . # allEditors . values ( ) ) {
if ( editor . editorType === type ) {
editor . show ( visible ) ;
}
}
const state = this . # showAllStates ? . get ( AnnotationEditorParamsType . HIGHLIGHT _SHOW _ALL ) ? ? true ;
if ( state !== visible ) {
this . # dispatchUpdateUI ( [ [ AnnotationEditorParamsType . HIGHLIGHT _SHOW _ALL , visible ] ] ) ;
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
enableWaiting ( mustWait = false ) {
if ( this . # isWaiting === mustWait ) {
return ;
}
this . # isWaiting = mustWait ;
for ( const layer of this . # allLayers . values ( ) ) {
if ( mustWait ) {
layer . disableClick ( ) ;
} else {
layer . enableClick ( ) ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
layer . div . classList . toggle ( "waiting" , mustWait ) ;
2016-04-04 15:49:28 +02:00
}
}
2024-06-01 11:00:27 +01:00
# enableAll ( ) {
if ( ! this . # isEnabled ) {
this . # isEnabled = true ;
for ( const layer of this . # allLayers . values ( ) ) {
layer . enable ( ) ;
}
for ( const editor of this . # allEditors . values ( ) ) {
editor . enable ( ) ;
}
2016-04-04 15:49:28 +02:00
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
# disableAll ( ) {
this . unselectAll ( ) ;
if ( this . # isEnabled ) {
this . # isEnabled = false ;
for ( const layer of this . # allLayers . values ( ) ) {
layer . disable ( ) ;
}
for ( const editor of this . # allEditors . values ( ) ) {
editor . disable ( ) ;
}
2016-04-04 15:49:28 +02:00
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
getEditors ( pageIndex ) {
const editors = [ ] ;
for ( const editor of this . # allEditors . values ( ) ) {
if ( editor . pageIndex === pageIndex ) {
editors . push ( editor ) ;
}
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
return editors ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
getEditor ( id ) {
return this . # allEditors . get ( id ) ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
addEditor ( editor ) {
this . # allEditors . set ( editor . id , editor ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
removeEditor ( editor ) {
if ( editor . div . contains ( document . activeElement ) ) {
if ( this . # focusMainContainerTimeoutId ) {
clearTimeout ( this . # focusMainContainerTimeoutId ) ;
}
this . # focusMainContainerTimeoutId = setTimeout ( ( ) => {
this . focusMainContainer ( ) ;
this . # focusMainContainerTimeoutId = null ;
} , 0 ) ;
}
this . # allEditors . delete ( editor . id ) ;
this . unselect ( editor ) ;
if ( ! editor . annotationElementId || ! this . # deletedAnnotationsElementIds . has ( editor . annotationElementId ) ) {
this . # annotationStorage ? . remove ( editor . id ) ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
addDeletedAnnotationElement ( editor ) {
this . # deletedAnnotationsElementIds . add ( editor . annotationElementId ) ;
this . addChangedExistingAnnotation ( editor ) ;
editor . deleted = true ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
isDeletedAnnotationElement ( annotationElementId ) {
return this . # deletedAnnotationsElementIds . has ( annotationElementId ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
removeDeletedAnnotationElement ( editor ) {
this . # deletedAnnotationsElementIds . delete ( editor . annotationElementId ) ;
this . removeChangedExistingAnnotation ( editor ) ;
editor . deleted = false ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
# addEditorToLayer ( editor ) {
const layer = this . # allLayers . get ( editor . pageIndex ) ;
if ( layer ) {
layer . addOrRebuild ( editor ) ;
} else {
this . addEditor ( editor ) ;
this . addToAnnotationStorage ( editor ) ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
setActiveEditor ( editor ) {
if ( this . # activeEditor === editor ) {
2023-10-27 13:19:54 +02:00
return ;
}
2024-06-01 11:00:27 +01:00
this . # activeEditor = editor ;
if ( editor ) {
this . # dispatchUpdateUI ( editor . propertiesToUpdate ) ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
get # lastSelectedEditor ( ) {
let ed = null ;
for ( ed of this . # selectedEditors ) { }
return ed ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
updateUI ( editor ) {
if ( this . # lastSelectedEditor === editor ) {
this . # dispatchUpdateUI ( editor . propertiesToUpdate ) ;
}
}
toggleSelected ( editor ) {
if ( this . # selectedEditors . has ( editor ) ) {
this . # selectedEditors . delete ( editor ) ;
editor . unselect ( ) ;
this . # dispatchUpdateStates ( {
hasSelectedEditor : this . hasSelection
} ) ;
2023-10-27 13:19:54 +02:00
return ;
}
2024-06-01 11:00:27 +01:00
this . # selectedEditors . add ( editor ) ;
editor . select ( ) ;
this . # dispatchUpdateUI ( editor . propertiesToUpdate ) ;
this . # dispatchUpdateStates ( {
hasSelectedEditor : true
} ) ;
}
setSelected ( editor ) {
for ( const ed of this . # selectedEditors ) {
if ( ed !== editor ) {
ed . unselect ( ) ;
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
this . # selectedEditors . clear ( ) ;
this . # selectedEditors . add ( editor ) ;
editor . select ( ) ;
this . # dispatchUpdateUI ( editor . propertiesToUpdate ) ;
this . # dispatchUpdateStates ( {
hasSelectedEditor : true
} ) ;
}
isSelected ( editor ) {
return this . # selectedEditors . has ( editor ) ;
}
get firstSelectedEditor ( ) {
return this . # selectedEditors . values ( ) . next ( ) . value ;
}
unselect ( editor ) {
editor . unselect ( ) ;
this . # selectedEditors . delete ( editor ) ;
this . # dispatchUpdateStates ( {
hasSelectedEditor : this . hasSelection
} ) ;
}
get hasSelection ( ) {
return this . # selectedEditors . size !== 0 ;
}
get isEnterHandled ( ) {
return this . # selectedEditors . size === 1 && this . firstSelectedEditor . isEnterHandled ;
}
undo ( ) {
this . # commandManager . undo ( ) ;
this . # dispatchUpdateStates ( {
hasSomethingToUndo : this . # commandManager . hasSomethingToUndo ( ) ,
hasSomethingToRedo : true ,
isEmpty : this . # isEmpty ( )
} ) ;
}
redo ( ) {
this . # commandManager . redo ( ) ;
this . # dispatchUpdateStates ( {
hasSomethingToUndo : true ,
hasSomethingToRedo : this . # commandManager . hasSomethingToRedo ( ) ,
isEmpty : this . # isEmpty ( )
} ) ;
}
addCommands ( params ) {
this . # commandManager . add ( params ) ;
this . # dispatchUpdateStates ( {
hasSomethingToUndo : true ,
hasSomethingToRedo : false ,
isEmpty : this . # isEmpty ( )
} ) ;
}
# isEmpty ( ) {
if ( this . # allEditors . size === 0 ) {
return true ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
if ( this . # allEditors . size === 1 ) {
for ( const editor of this . # allEditors . values ( ) ) {
return editor . isEmpty ( ) ;
}
}
return false ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
delete ( ) {
this . commitOrRemove ( ) ;
if ( ! this . hasSelection ) {
2023-10-27 13:19:54 +02:00
return ;
}
2024-06-01 11:00:27 +01:00
const editors = [ ... this . # selectedEditors ] ;
const cmd = ( ) => {
for ( const editor of editors ) {
editor . remove ( ) ;
}
2023-10-27 13:19:54 +02:00
} ;
2024-06-01 11:00:27 +01:00
const undo = ( ) => {
for ( const editor of editors ) {
this . # addEditorToLayer ( editor ) ;
}
} ;
this . addCommands ( {
cmd ,
undo ,
mustExec : true
} ) ;
}
commitOrRemove ( ) {
this . # activeEditor ? . commitOrRemove ( ) ;
}
hasSomethingToControl ( ) {
return this . # activeEditor || this . hasSelection ;
}
# selectEditors ( editors ) {
for ( const editor of this . # selectedEditors ) {
editor . unselect ( ) ;
}
this . # selectedEditors . clear ( ) ;
for ( const editor of editors ) {
if ( editor . isEmpty ( ) ) {
continue ;
}
this . # selectedEditors . add ( editor ) ;
editor . select ( ) ;
}
this . # dispatchUpdateStates ( {
hasSelectedEditor : this . hasSelection
} ) ;
}
selectAll ( ) {
for ( const editor of this . # selectedEditors ) {
editor . commit ( ) ;
}
this . # selectEditors ( this . # allEditors . values ( ) ) ;
}
unselectAll ( ) {
if ( this . # activeEditor ) {
this . # activeEditor . commitOrRemove ( ) ;
if ( this . # mode !== AnnotationEditorType . NONE ) {
2016-04-04 15:49:28 +02:00
return ;
}
2024-06-01 11:00:27 +01:00
}
if ( ! this . hasSelection ) {
return ;
}
for ( const editor of this . # selectedEditors ) {
editor . unselect ( ) ;
}
this . # selectedEditors . clear ( ) ;
this . # dispatchUpdateStates ( {
hasSelectedEditor : false
} ) ;
}
translateSelectedEditors ( x , y , noCommit = false ) {
if ( ! noCommit ) {
this . commitOrRemove ( ) ;
}
if ( ! this . hasSelection ) {
return ;
}
this . # translation [ 0 ] += x ;
this . # translation [ 1 ] += y ;
const [ totalX , totalY ] = this . # translation ;
const editors = [ ... this . # selectedEditors ] ;
const TIME _TO _WAIT = 1000 ;
if ( this . # translationTimeoutId ) {
clearTimeout ( this . # translationTimeoutId ) ;
}
this . # translationTimeoutId = setTimeout ( ( ) => {
this . # translationTimeoutId = null ;
this . # translation [ 0 ] = this . # translation [ 1 ] = 0 ;
2023-10-27 13:19:54 +02:00
this . addCommands ( {
cmd : ( ) => {
2024-06-01 11:00:27 +01:00
for ( const editor of editors ) {
if ( this . # allEditors . has ( editor . id ) ) {
editor . translateInPage ( totalX , totalY ) ;
}
}
2023-10-27 13:19:54 +02:00
} ,
undo : ( ) => {
2024-06-01 11:00:27 +01:00
for ( const editor of editors ) {
if ( this . # allEditors . has ( editor . id ) ) {
editor . translateInPage ( - totalX , - totalY ) ;
}
}
2023-10-27 13:19:54 +02:00
} ,
2024-06-01 11:00:27 +01:00
mustExec : false
2023-10-27 13:19:54 +02:00
} ) ;
2024-06-01 11:00:27 +01:00
} , TIME _TO _WAIT ) ;
for ( const editor of editors ) {
editor . translateInPage ( x , y ) ;
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
setUpDragSession ( ) {
if ( ! this . hasSelection ) {
return ;
}
this . disableUserSelect ( true ) ;
this . # draggingEditors = new Map ( ) ;
for ( const editor of this . # selectedEditors ) {
this . # draggingEditors . set ( editor , {
savedX : editor . x ,
savedY : editor . y ,
savedPageIndex : editor . pageIndex ,
newX : 0 ,
newY : 0 ,
newPageIndex : - 1
} ) ;
}
}
endDragSession ( ) {
if ( ! this . # draggingEditors ) {
return false ;
}
this . disableUserSelect ( false ) ;
const map = this . # draggingEditors ;
this . # draggingEditors = null ;
let mustBeAddedInUndoStack = false ;
for ( const [ {
x ,
y ,
pageIndex
} , value ] of map ) {
value . newX = x ;
value . newY = y ;
value . newPageIndex = pageIndex ;
mustBeAddedInUndoStack || = x !== value . savedX || y !== value . savedY || pageIndex !== value . savedPageIndex ;
}
if ( ! mustBeAddedInUndoStack ) {
return false ;
}
const move = ( editor , x , y , pageIndex ) => {
if ( this . # allEditors . has ( editor . id ) ) {
const parent = this . # allLayers . get ( pageIndex ) ;
if ( parent ) {
editor . _setParentAndPosition ( parent , x , y ) ;
} else {
editor . pageIndex = pageIndex ;
editor . x = x ;
editor . y = y ;
}
}
} ;
this . addCommands ( {
cmd : ( ) => {
for ( const [ editor , {
newX ,
newY ,
newPageIndex
} ] of map ) {
move ( editor , newX , newY , newPageIndex ) ;
}
} ,
undo : ( ) => {
for ( const [ editor , {
savedX ,
savedY ,
savedPageIndex
} ] of map ) {
move ( editor , savedX , savedY , savedPageIndex ) ;
}
} ,
mustExec : true
} ) ;
return true ;
}
dragSelectedEditors ( tx , ty ) {
if ( ! this . # draggingEditors ) {
return ;
}
for ( const editor of this . # draggingEditors . keys ( ) ) {
editor . drag ( tx , ty ) ;
}
}
rebuild ( editor ) {
if ( editor . parent === null ) {
const parent = this . getLayer ( editor . pageIndex ) ;
if ( parent ) {
parent . changeParent ( editor ) ;
parent . addOrRebuild ( editor ) ;
} else {
this . addEditor ( editor ) ;
this . addToAnnotationStorage ( editor ) ;
editor . rebuild ( ) ;
}
} else {
editor . parent . addOrRebuild ( editor ) ;
}
}
get isEditorHandlingKeyboard ( ) {
return this . getActive ( ) ? . shouldGetKeyboardEvents ( ) || this . # selectedEditors . size === 1 && this . firstSelectedEditor . shouldGetKeyboardEvents ( ) ;
}
isActive ( editor ) {
return this . # activeEditor === editor ;
}
getActive ( ) {
return this . # activeEditor ;
}
getMode ( ) {
return this . # mode ;
}
get imageManager ( ) {
return shadow ( this , "imageManager" , new ImageManager ( ) ) ;
}
getSelectionBoxes ( textLayer ) {
if ( ! textLayer ) {
return null ;
}
const selection = document . getSelection ( ) ;
for ( let i = 0 , ii = selection . rangeCount ; i < ii ; i ++ ) {
if ( ! textLayer . contains ( selection . getRangeAt ( i ) . commonAncestorContainer ) ) {
return null ;
}
}
const {
x : layerX ,
y : layerY ,
width : parentWidth ,
height : parentHeight
} = textLayer . getBoundingClientRect ( ) ;
let rotator ;
switch ( textLayer . getAttribute ( "data-main-rotation" ) ) {
case "90" :
rotator = ( x , y , w , h ) => ( {
x : ( y - layerY ) / parentHeight ,
y : 1 - ( x + w - layerX ) / parentWidth ,
width : h / parentHeight ,
height : w / parentWidth
} ) ;
2023-10-27 13:19:54 +02:00
break ;
2024-06-01 11:00:27 +01:00
case "180" :
rotator = ( x , y , w , h ) => ( {
x : 1 - ( x + w - layerX ) / parentWidth ,
y : 1 - ( y + h - layerY ) / parentHeight ,
width : w / parentWidth ,
height : h / parentHeight
} ) ;
2023-10-27 13:19:54 +02:00
break ;
2024-06-01 11:00:27 +01:00
case "270" :
rotator = ( x , y , w , h ) => ( {
x : 1 - ( y + h - layerY ) / parentHeight ,
y : ( x - layerX ) / parentWidth ,
width : h / parentHeight ,
height : w / parentWidth
} ) ;
2023-10-27 13:19:54 +02:00
break ;
2024-06-01 11:00:27 +01:00
default :
rotator = ( x , y , w , h ) => ( {
x : ( x - layerX ) / parentWidth ,
y : ( y - layerY ) / parentHeight ,
width : w / parentWidth ,
height : h / parentHeight
} ) ;
2023-10-27 13:19:54 +02:00
break ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
const boxes = [ ] ;
for ( let i = 0 , ii = selection . rangeCount ; i < ii ; i ++ ) {
const range = selection . getRangeAt ( i ) ;
if ( range . collapsed ) {
continue ;
}
for ( const {
x ,
y ,
width ,
height
} of range . getClientRects ( ) ) {
if ( width === 0 || height === 0 ) {
continue ;
}
boxes . push ( rotator ( x , y , width , height ) ) ;
}
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
return boxes . length === 0 ? null : boxes ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
addChangedExistingAnnotation ( {
annotationElementId ,
id
} ) {
( this . # changedExistingAnnotations || = new Map ( ) ) . set ( annotationElementId , id ) ;
}
removeChangedExistingAnnotation ( {
annotationElementId
} ) {
this . # changedExistingAnnotations ? . delete ( annotationElementId ) ;
}
renderAnnotationElement ( annotation ) {
const editorId = this . # changedExistingAnnotations ? . get ( annotation . data . id ) ;
if ( ! editorId ) {
2023-10-27 13:19:54 +02:00
return ;
}
2024-06-01 11:00:27 +01:00
const editor = this . # annotationStorage . getRawValue ( editorId ) ;
if ( ! editor ) {
return ;
}
if ( this . # mode === AnnotationEditorType . NONE && ! editor . hasBeenModified ) {
return ;
}
editor . renderAnnotationElement ( annotation ) ;
}
}
; // CONCATENATED MODULE: ./src/display/editor/alt_text.js
class AltText {
# altText = "" ;
# altTextDecorative = false ;
# altTextButton = null ;
# altTextTooltip = null ;
# altTextTooltipTimeout = null ;
# altTextWasFromKeyBoard = false ;
# editor = null ;
static _l10nPromise = null ;
constructor ( editor ) {
this . # editor = editor ;
}
static initialize ( l10nPromise ) {
AltText . _l10nPromise || = l10nPromise ;
}
async render ( ) {
2023-10-27 13:19:54 +02:00
const altText = this . # altTextButton = document . createElement ( "button" ) ;
altText . className = "altText" ;
2024-06-01 11:00:27 +01:00
const msg = await AltText . _l10nPromise . get ( "pdfjs-editor-alt-text-button-label" ) ;
2023-10-27 13:19:54 +02:00
altText . textContent = msg ;
altText . setAttribute ( "aria-label" , msg ) ;
altText . tabIndex = "0" ;
2024-06-01 11:00:27 +01:00
altText . addEventListener ( "contextmenu" , noContextMenu ) ;
2023-10-27 13:19:54 +02:00
altText . addEventListener ( "pointerdown" , event => event . stopPropagation ( ) ) ;
2024-06-01 11:00:27 +01:00
const onClick = event => {
2023-10-27 13:19:54 +02:00
event . preventDefault ( ) ;
2024-06-01 11:00:27 +01:00
this . # editor . _uiManager . editAltText ( this . # editor ) ;
} ;
altText . addEventListener ( "click" , onClick , {
2023-10-27 13:19:54 +02:00
capture : true
} ) ;
altText . addEventListener ( "keydown" , event => {
if ( event . target === altText && event . key === "Enter" ) {
2024-06-01 11:00:27 +01:00
this . # altTextWasFromKeyBoard = true ;
onClick ( event ) ;
2016-04-04 15:49:28 +02:00
}
2023-10-27 13:19:54 +02:00
} ) ;
2024-06-01 11:00:27 +01:00
await this . # setState ( ) ;
return altText ;
}
finish ( ) {
if ( ! this . # altTextButton ) {
return ;
}
this . # altTextButton . focus ( {
focusVisible : this . # altTextWasFromKeyBoard
} ) ;
this . # altTextWasFromKeyBoard = false ;
}
isEmpty ( ) {
return ! this . # altText && ! this . # altTextDecorative ;
}
get data ( ) {
return {
altText : this . # altText ,
decorative : this . # altTextDecorative
} ;
}
set data ( {
altText ,
decorative
} ) {
if ( this . # altText === altText && this . # altTextDecorative === decorative ) {
return ;
}
this . # altText = altText ;
this . # altTextDecorative = decorative ;
this . # setState ( ) ;
}
toggle ( enabled = false ) {
if ( ! this . # altTextButton ) {
return ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
if ( ! enabled && this . # altTextTooltipTimeout ) {
clearTimeout ( this . # altTextTooltipTimeout ) ;
this . # altTextTooltipTimeout = null ;
}
this . # altTextButton . disabled = ! enabled ;
}
destroy ( ) {
this . # altTextButton ? . remove ( ) ;
this . # altTextButton = null ;
this . # altTextTooltip = null ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
async # setState ( ) {
2023-10-27 13:19:54 +02:00
const button = this . # altTextButton ;
if ( ! button ) {
return ;
}
if ( ! this . # altText && ! this . # altTextDecorative ) {
button . classList . remove ( "done" ) ;
this . # altTextTooltip ? . remove ( ) ;
return ;
}
2024-06-01 11:00:27 +01:00
button . classList . add ( "done" ) ;
AltText . _l10nPromise . get ( "pdfjs-editor-alt-text-edit-button-label" ) . then ( msg => {
2023-10-27 13:19:54 +02:00
button . setAttribute ( "aria-label" , msg ) ;
} ) ;
let tooltip = this . # altTextTooltip ;
if ( ! tooltip ) {
this . # altTextTooltip = tooltip = document . createElement ( "span" ) ;
tooltip . className = "tooltip" ;
tooltip . setAttribute ( "role" , "tooltip" ) ;
2024-06-01 11:00:27 +01:00
const id = tooltip . id = ` alt-text-tooltip- ${ this . # editor . id } ` ;
2023-10-27 13:19:54 +02:00
button . setAttribute ( "aria-describedby" , id ) ;
const DELAY _TO _SHOW _TOOLTIP = 100 ;
button . addEventListener ( "mouseenter" , ( ) => {
this . # altTextTooltipTimeout = setTimeout ( ( ) => {
this . # altTextTooltipTimeout = null ;
this . # altTextTooltip . classList . add ( "show" ) ;
2024-06-01 11:00:27 +01:00
this . # editor . _reportTelemetry ( {
action : "alt_text_tooltip"
2023-10-27 13:19:54 +02:00
} ) ;
} , DELAY _TO _SHOW _TOOLTIP ) ;
} ) ;
button . addEventListener ( "mouseleave" , ( ) => {
2024-06-01 11:00:27 +01:00
if ( this . # altTextTooltipTimeout ) {
clearTimeout ( this . # altTextTooltipTimeout ) ;
this . # altTextTooltipTimeout = null ;
}
2023-10-27 13:19:54 +02:00
this . # altTextTooltip ? . classList . remove ( "show" ) ;
} ) ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
tooltip . innerText = this . # altTextDecorative ? await AltText . _l10nPromise . get ( "pdfjs-editor-alt-text-decorative-tooltip" ) : this . # altText ;
2023-10-27 13:19:54 +02:00
if ( ! tooltip . parentNode ) {
button . append ( tooltip ) ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
const element = this . # editor . getImageForAltText ( ) ;
element ? . setAttribute ( "aria-describedby" , tooltip . id ) ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
}
; // CONCATENATED MODULE: ./src/display/editor/editor.js
class AnnotationEditor {
# allResizerDivs = null ;
# altText = null ;
# disabled = false ;
# keepAspectRatio = false ;
# resizersDiv = null ;
# savedDimensions = null ;
# boundFocusin = this . focusin . bind ( this ) ;
# boundFocusout = this . focusout . bind ( this ) ;
# editToolbar = null ;
# focusedResizerName = "" ;
# hasBeenClicked = false ;
# initialPosition = null ;
# isEditing = false ;
# isInEditMode = false ;
# isResizerEnabledForKeyboard = false ;
# moveInDOMTimeout = null ;
# prevDragX = 0 ;
# prevDragY = 0 ;
# telemetryTimeouts = null ;
_initialOptions = Object . create ( null ) ;
_isVisible = true ;
_uiManager = null ;
_focusEventsAllowed = true ;
_l10nPromise = null ;
# isDraggable = false ;
# zIndex = AnnotationEditor . _zIndex ++ ;
static _borderLineWidth = - 1 ;
static _colorManager = new ColorManager ( ) ;
static _zIndex = 1 ;
static _telemetryTimeout = 1000 ;
static get _resizerKeyboardManager ( ) {
const resize = AnnotationEditor . prototype . _resizeWithKeyboard ;
const small = AnnotationEditorUIManager . TRANSLATE _SMALL ;
const big = AnnotationEditorUIManager . TRANSLATE _BIG ;
return shadow ( this , "_resizerKeyboardManager" , new KeyboardManager ( [ [ [ "ArrowLeft" , "mac+ArrowLeft" ] , resize , {
args : [ - small , 0 ]
} ] , [ [ "ctrl+ArrowLeft" , "mac+shift+ArrowLeft" ] , resize , {
args : [ - big , 0 ]
} ] , [ [ "ArrowRight" , "mac+ArrowRight" ] , resize , {
args : [ small , 0 ]
} ] , [ [ "ctrl+ArrowRight" , "mac+shift+ArrowRight" ] , resize , {
args : [ big , 0 ]
} ] , [ [ "ArrowUp" , "mac+ArrowUp" ] , resize , {
args : [ 0 , - small ]
} ] , [ [ "ctrl+ArrowUp" , "mac+shift+ArrowUp" ] , resize , {
args : [ 0 , - big ]
} ] , [ [ "ArrowDown" , "mac+ArrowDown" ] , resize , {
args : [ 0 , small ]
} ] , [ [ "ctrl+ArrowDown" , "mac+shift+ArrowDown" ] , resize , {
args : [ 0 , big ]
} ] , [ [ "Escape" , "mac+Escape" ] , AnnotationEditor . prototype . _stopResizingWithKeyboard ] ] ) ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
constructor ( parameters ) {
if ( this . constructor === AnnotationEditor ) {
unreachable ( "Cannot initialize AnnotationEditor." ) ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
this . parent = parameters . parent ;
this . id = parameters . id ;
this . width = this . height = null ;
this . pageIndex = parameters . parent . pageIndex ;
this . name = parameters . name ;
this . div = null ;
this . _uiManager = parameters . uiManager ;
this . annotationElementId = null ;
this . _willKeepAspectRatio = false ;
this . _initialOptions . isCentered = parameters . isCentered ;
this . _structTreeParentId = null ;
const {
rotation ,
rawDims : {
pageWidth ,
pageHeight ,
pageX ,
pageY
}
} = this . parent . viewport ;
this . rotation = rotation ;
this . pageRotation = ( 360 + rotation - this . _uiManager . viewParameters . rotation ) % 360 ;
this . pageDimensions = [ pageWidth , pageHeight ] ;
this . pageTranslation = [ pageX , pageY ] ;
const [ width , height ] = this . parentDimensions ;
this . x = parameters . x / width ;
this . y = parameters . y / height ;
this . isAttachedToDOM = false ;
this . deleted = false ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
get editorType ( ) {
return Object . getPrototypeOf ( this ) . constructor . _type ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
static get _defaultLineColor ( ) {
return shadow ( this , "_defaultLineColor" , this . _colorManager . getHexCode ( "CanvasText" ) ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
static deleteAnnotationElement ( editor ) {
const fakeEditor = new FakeEditor ( {
id : editor . parent . getNextId ( ) ,
parent : editor . parent ,
uiManager : editor . _uiManager
} ) ;
fakeEditor . annotationElementId = editor . annotationElementId ;
fakeEditor . deleted = true ;
fakeEditor . _uiManager . addToAnnotationStorage ( fakeEditor ) ;
}
static initialize ( l10n , _uiManager , options ) {
AnnotationEditor . _l10nPromise || = new Map ( [ "pdfjs-editor-alt-text-button-label" , "pdfjs-editor-alt-text-edit-button-label" , "pdfjs-editor-alt-text-decorative-tooltip" , "pdfjs-editor-resizer-label-topLeft" , "pdfjs-editor-resizer-label-topMiddle" , "pdfjs-editor-resizer-label-topRight" , "pdfjs-editor-resizer-label-middleRight" , "pdfjs-editor-resizer-label-bottomRight" , "pdfjs-editor-resizer-label-bottomMiddle" , "pdfjs-editor-resizer-label-bottomLeft" , "pdfjs-editor-resizer-label-middleLeft" ] . map ( str => [ str , l10n . get ( str . replaceAll ( /([A-Z])/g , c => ` - ${ c . toLowerCase ( ) } ` ) ) ] ) ) ;
if ( options ? . strings ) {
for ( const str of options . strings ) {
AnnotationEditor . _l10nPromise . set ( str , l10n . get ( str ) ) ;
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
if ( AnnotationEditor . _borderLineWidth !== - 1 ) {
return ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
const style = getComputedStyle ( document . documentElement ) ;
AnnotationEditor . _borderLineWidth = parseFloat ( style . getPropertyValue ( "--outline-width" ) ) || 0 ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
static updateDefaultParams ( _type , _value ) { }
static get defaultPropertiesToUpdate ( ) {
return [ ] ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
static isHandlingMimeForPasting ( mime ) {
return false ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
static paste ( item , parent ) {
unreachable ( "Not implemented" ) ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
get propertiesToUpdate ( ) {
return [ ] ;
}
get _isDraggable ( ) {
return this . # isDraggable ;
}
set _isDraggable ( value ) {
this . # isDraggable = value ;
this . div ? . classList . toggle ( "draggable" , value ) ;
}
get isEnterHandled ( ) {
return true ;
}
center ( ) {
const [ pageWidth , pageHeight ] = this . pageDimensions ;
switch ( this . parentRotation ) {
2023-10-27 13:19:54 +02:00
case 90 :
2024-06-01 11:00:27 +01:00
this . x -= this . height * pageHeight / ( pageWidth * 2 ) ;
this . y += this . width * pageWidth / ( pageHeight * 2 ) ;
break ;
2023-10-27 13:19:54 +02:00
case 180 :
2024-06-01 11:00:27 +01:00
this . x += this . width / 2 ;
this . y += this . height / 2 ;
break ;
2023-10-27 13:19:54 +02:00
case 270 :
2024-06-01 11:00:27 +01:00
this . x += this . height * pageHeight / ( pageWidth * 2 ) ;
this . y -= this . width * pageWidth / ( pageHeight * 2 ) ;
break ;
2023-10-27 13:19:54 +02:00
default :
2024-06-01 11:00:27 +01:00
this . x -= this . width / 2 ;
this . y -= this . height / 2 ;
break ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
this . fixAndSetPosition ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
addCommands ( params ) {
this . _uiManager . addCommands ( params ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
get currentLayer ( ) {
return this . _uiManager . currentLayer ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
setInBackground ( ) {
this . div . style . zIndex = 0 ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
setInForeground ( ) {
this . div . style . zIndex = this . # zIndex ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
setParent ( parent ) {
if ( parent !== null ) {
this . pageIndex = parent . pageIndex ;
this . pageDimensions = parent . pageDimensions ;
} else {
this . # stopResizing ( ) ;
}
this . parent = parent ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
focusin ( event ) {
if ( ! this . _focusEventsAllowed ) {
return ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
if ( ! this . # hasBeenClicked ) {
this . parent . setSelected ( this ) ;
2023-10-27 13:19:54 +02:00
} else {
2024-06-01 11:00:27 +01:00
this . # hasBeenClicked = false ;
2016-04-04 15:49:28 +02:00
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
focusout ( event ) {
if ( ! this . _focusEventsAllowed ) {
return ;
}
if ( ! this . isAttachedToDOM ) {
return ;
}
const target = event . relatedTarget ;
if ( target ? . closest ( ` # ${ this . id } ` ) ) {
return ;
}
event . preventDefault ( ) ;
if ( ! this . parent ? . isMultipleSelection ) {
this . commitOrRemove ( ) ;
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
commitOrRemove ( ) {
if ( this . isEmpty ( ) ) {
this . remove ( ) ;
} else {
this . commit ( ) ;
2016-04-04 15:49:28 +02:00
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
commit ( ) {
this . addToAnnotationStorage ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
addToAnnotationStorage ( ) {
this . _uiManager . addToAnnotationStorage ( this ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
setAt ( x , y , tx , ty ) {
const [ width , height ] = this . parentDimensions ;
[ tx , ty ] = this . screenToPageTranslation ( tx , ty ) ;
this . x = ( x + tx ) / width ;
this . y = ( y + ty ) / height ;
this . fixAndSetPosition ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
# translate ( [ width , height ] , x , y ) {
[ x , y ] = this . screenToPageTranslation ( x , y ) ;
this . x += x / width ;
this . y += y / height ;
this . fixAndSetPosition ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
translate ( x , y ) {
this . # translate ( this . parentDimensions , x , y ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
translateInPage ( x , y ) {
this . # initialPosition || = [ this . x , this . y ] ;
this . # translate ( this . pageDimensions , x , y ) ;
this . div . scrollIntoView ( {
block : "nearest"
} ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
drag ( tx , ty ) {
this . # initialPosition || = [ this . x , this . y ] ;
const [ parentWidth , parentHeight ] = this . parentDimensions ;
this . x += tx / parentWidth ;
this . y += ty / parentHeight ;
if ( this . parent && ( this . x < 0 || this . x > 1 || this . y < 0 || this . y > 1 ) ) {
const {
x ,
y
} = this . div . getBoundingClientRect ( ) ;
if ( this . parent . findNewParent ( this , x , y ) ) {
this . x -= Math . floor ( this . x ) ;
this . y -= Math . floor ( this . y ) ;
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
let {
x ,
y
} = this ;
const [ bx , by ] = this . getBaseTranslation ( ) ;
x += bx ;
y += by ;
this . div . style . left = ` ${ ( 100 * x ) . toFixed ( 2 ) } % ` ;
this . div . style . top = ` ${ ( 100 * y ) . toFixed ( 2 ) } % ` ;
this . div . scrollIntoView ( {
block : "nearest"
} ) ;
}
get _hasBeenMoved ( ) {
return ! ! this . # initialPosition && ( this . # initialPosition [ 0 ] !== this . x || this . # initialPosition [ 1 ] !== this . y ) ;
}
getBaseTranslation ( ) {
const [ parentWidth , parentHeight ] = this . parentDimensions ;
const {
_borderLineWidth
} = AnnotationEditor ;
const x = _borderLineWidth / parentWidth ;
const y = _borderLineWidth / parentHeight ;
switch ( this . rotation ) {
case 90 :
return [ - x , y ] ;
case 180 :
return [ x , y ] ;
case 270 :
return [ x , - y ] ;
default :
return [ - x , - y ] ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
get _mustFixPosition ( ) {
return true ;
}
fixAndSetPosition ( rotation = this . rotation ) {
const [ pageWidth , pageHeight ] = this . pageDimensions ;
let {
x ,
y ,
width ,
height
} = this ;
width *= pageWidth ;
height *= pageHeight ;
x *= pageWidth ;
y *= pageHeight ;
if ( this . _mustFixPosition ) {
switch ( rotation ) {
case 0 :
x = Math . max ( 0 , Math . min ( pageWidth - width , x ) ) ;
y = Math . max ( 0 , Math . min ( pageHeight - height , y ) ) ;
break ;
case 90 :
x = Math . max ( 0 , Math . min ( pageWidth - height , x ) ) ;
y = Math . min ( pageHeight , Math . max ( width , y ) ) ;
break ;
case 180 :
x = Math . min ( pageWidth , Math . max ( width , x ) ) ;
y = Math . min ( pageHeight , Math . max ( height , y ) ) ;
break ;
case 270 :
x = Math . min ( pageWidth , Math . max ( height , x ) ) ;
y = Math . max ( 0 , Math . min ( pageHeight - width , y ) ) ;
break ;
}
}
this . x = x /= pageWidth ;
this . y = y /= pageHeight ;
const [ bx , by ] = this . getBaseTranslation ( ) ;
x += bx ;
y += by ;
2023-10-27 13:19:54 +02:00
const {
style
} = this . div ;
2024-06-01 11:00:27 +01:00
style . left = ` ${ ( 100 * x ) . toFixed ( 2 ) } % ` ;
style . top = ` ${ ( 100 * y ) . toFixed ( 2 ) } % ` ;
this . moveInDOM ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
static # rotatePoint ( x , y , angle ) {
switch ( angle ) {
case 90 :
return [ y , - x ] ;
case 180 :
return [ - x , - y ] ;
case 270 :
return [ - y , x ] ;
default :
return [ x , y ] ;
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
screenToPageTranslation ( x , y ) {
return AnnotationEditor . # rotatePoint ( x , y , this . parentRotation ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
pageTranslationToScreen ( x , y ) {
return AnnotationEditor . # rotatePoint ( x , y , 360 - this . parentRotation ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
# getRotationMatrix ( rotation ) {
switch ( rotation ) {
case 90 :
{
const [ pageWidth , pageHeight ] = this . pageDimensions ;
return [ 0 , - pageWidth / pageHeight , pageHeight / pageWidth , 0 ] ;
}
case 180 :
return [ - 1 , 0 , 0 , - 1 ] ;
case 270 :
{
const [ pageWidth , pageHeight ] = this . pageDimensions ;
return [ 0 , pageWidth / pageHeight , - pageHeight / pageWidth , 0 ] ;
}
default :
return [ 1 , 0 , 0 , 1 ] ;
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
get parentScale ( ) {
return this . _uiManager . viewParameters . realScale ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
get parentRotation ( ) {
return ( this . _uiManager . viewParameters . rotation + this . pageRotation ) % 360 ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
get parentDimensions ( ) {
const {
parentScale ,
pageDimensions : [ pageWidth , pageHeight ]
} = this ;
const scaledWidth = pageWidth * parentScale ;
const scaledHeight = pageHeight * parentScale ;
return util _FeatureTest . isCSSRoundSupported ? [ Math . round ( scaledWidth ) , Math . round ( scaledHeight ) ] : [ scaledWidth , scaledHeight ] ;
}
setDims ( width , height ) {
const [ parentWidth , parentHeight ] = this . parentDimensions ;
this . div . style . width = ` ${ ( 100 * width / parentWidth ) . toFixed ( 2 ) } % ` ;
if ( ! this . # keepAspectRatio ) {
this . div . style . height = ` ${ ( 100 * height / parentHeight ) . toFixed ( 2 ) } % ` ;
2023-10-27 13:19:54 +02:00
}
2014-11-24 00:56:52 +01:00
}
2024-06-01 11:00:27 +01:00
fixDims ( ) {
2023-10-27 13:19:54 +02:00
const {
2024-06-01 11:00:27 +01:00
style
} = this . div ;
const {
height ,
width
} = style ;
const widthPercent = width . endsWith ( "%" ) ;
const heightPercent = ! this . # keepAspectRatio && height . endsWith ( "%" ) ;
if ( widthPercent && heightPercent ) {
return ;
2013-12-31 16:34:23 +05:30
}
2024-06-01 11:00:27 +01:00
const [ parentWidth , parentHeight ] = this . parentDimensions ;
if ( ! widthPercent ) {
style . width = ` ${ ( 100 * parseFloat ( width ) / parentWidth ) . toFixed ( 2 ) } % ` ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
if ( ! this . # keepAspectRatio && ! heightPercent ) {
style . height = ` ${ ( 100 * parseFloat ( height ) / parentHeight ) . toFixed ( 2 ) } % ` ;
2023-10-27 13:19:54 +02:00
}
2014-11-24 00:56:52 +01:00
}
2024-06-01 11:00:27 +01:00
getInitialTranslation ( ) {
return [ 0 , 0 ] ;
2014-11-24 00:56:52 +01:00
}
2024-06-01 11:00:27 +01:00
# createResizers ( ) {
if ( this . # resizersDiv ) {
2023-10-27 13:19:54 +02:00
return ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
this . # resizersDiv = document . createElement ( "div" ) ;
this . # resizersDiv . classList . add ( "resizers" ) ;
const classes = this . _willKeepAspectRatio ? [ "topLeft" , "topRight" , "bottomRight" , "bottomLeft" ] : [ "topLeft" , "topMiddle" , "topRight" , "middleRight" , "bottomRight" , "bottomMiddle" , "bottomLeft" , "middleLeft" ] ;
for ( const name of classes ) {
const div = document . createElement ( "div" ) ;
this . # resizersDiv . append ( div ) ;
div . classList . add ( "resizer" , name ) ;
div . setAttribute ( "data-resizer-name" , name ) ;
div . addEventListener ( "pointerdown" , this . # resizerPointerdown . bind ( this , name ) ) ;
div . addEventListener ( "contextmenu" , noContextMenu ) ;
div . tabIndex = - 1 ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
this . div . prepend ( this . # resizersDiv ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
# resizerPointerdown ( name , event ) {
event . preventDefault ( ) ;
const {
isMac
} = util _FeatureTest . platform ;
if ( event . button !== 0 || event . ctrlKey && isMac ) {
2023-10-27 13:19:54 +02:00
return ;
}
2024-06-01 11:00:27 +01:00
this . # altText ? . toggle ( false ) ;
const boundResizerPointermove = this . # resizerPointermove . bind ( this , name ) ;
const savedDraggable = this . _isDraggable ;
this . _isDraggable = false ;
const pointerMoveOptions = {
passive : true ,
capture : true
2023-10-27 13:19:54 +02:00
} ;
2024-06-01 11:00:27 +01:00
this . parent . togglePointerEvents ( false ) ;
window . addEventListener ( "pointermove" , boundResizerPointermove , pointerMoveOptions ) ;
window . addEventListener ( "contextmenu" , noContextMenu ) ;
const savedX = this . x ;
const savedY = this . y ;
const savedWidth = this . width ;
const savedHeight = this . height ;
const savedParentCursor = this . parent . div . style . cursor ;
const savedCursor = this . div . style . cursor ;
this . div . style . cursor = this . parent . div . style . cursor = window . getComputedStyle ( event . target ) . cursor ;
const pointerUpCallback = ( ) => {
this . parent . togglePointerEvents ( true ) ;
this . # altText ? . toggle ( true ) ;
this . _isDraggable = savedDraggable ;
window . removeEventListener ( "pointerup" , pointerUpCallback ) ;
window . removeEventListener ( "blur" , pointerUpCallback ) ;
window . removeEventListener ( "pointermove" , boundResizerPointermove , pointerMoveOptions ) ;
window . removeEventListener ( "contextmenu" , noContextMenu ) ;
this . parent . div . style . cursor = savedParentCursor ;
this . div . style . cursor = savedCursor ;
this . # addResizeToUndoStack ( savedX , savedY , savedWidth , savedHeight ) ;
} ;
window . addEventListener ( "pointerup" , pointerUpCallback ) ;
window . addEventListener ( "blur" , pointerUpCallback ) ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
# addResizeToUndoStack ( savedX , savedY , savedWidth , savedHeight ) {
const newX = this . x ;
const newY = this . y ;
const newWidth = this . width ;
const newHeight = this . height ;
if ( newX === savedX && newY === savedY && newWidth === savedWidth && newHeight === savedHeight ) {
2023-10-27 13:19:54 +02:00
return ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
this . addCommands ( {
cmd : ( ) => {
this . width = newWidth ;
this . height = newHeight ;
this . x = newX ;
this . y = newY ;
const [ parentWidth , parentHeight ] = this . parentDimensions ;
this . setDims ( parentWidth * newWidth , parentHeight * newHeight ) ;
this . fixAndSetPosition ( ) ;
} ,
undo : ( ) => {
this . width = savedWidth ;
this . height = savedHeight ;
this . x = savedX ;
this . y = savedY ;
const [ parentWidth , parentHeight ] = this . parentDimensions ;
this . setDims ( parentWidth * savedWidth , parentHeight * savedHeight ) ;
this . fixAndSetPosition ( ) ;
} ,
mustExec : true
} ) ;
2013-12-31 16:34:23 +05:30
}
2024-06-01 11:00:27 +01:00
# resizerPointermove ( name , event ) {
const [ parentWidth , parentHeight ] = this . parentDimensions ;
const savedX = this . x ;
const savedY = this . y ;
const savedWidth = this . width ;
const savedHeight = this . height ;
const minWidth = AnnotationEditor . MIN _SIZE / parentWidth ;
const minHeight = AnnotationEditor . MIN _SIZE / parentHeight ;
const round = x => Math . round ( x * 10000 ) / 10000 ;
const rotationMatrix = this . # getRotationMatrix ( this . rotation ) ;
const transf = ( x , y ) => [ rotationMatrix [ 0 ] * x + rotationMatrix [ 2 ] * y , rotationMatrix [ 1 ] * x + rotationMatrix [ 3 ] * y ] ;
const invRotationMatrix = this . # getRotationMatrix ( 360 - this . rotation ) ;
const invTransf = ( x , y ) => [ invRotationMatrix [ 0 ] * x + invRotationMatrix [ 2 ] * y , invRotationMatrix [ 1 ] * x + invRotationMatrix [ 3 ] * y ] ;
let getPoint ;
let getOpposite ;
let isDiagonal = false ;
let isHorizontal = false ;
switch ( name ) {
case "topLeft" :
isDiagonal = true ;
getPoint = ( w , h ) => [ 0 , 0 ] ;
getOpposite = ( w , h ) => [ w , h ] ;
break ;
case "topMiddle" :
getPoint = ( w , h ) => [ w / 2 , 0 ] ;
getOpposite = ( w , h ) => [ w / 2 , h ] ;
break ;
case "topRight" :
isDiagonal = true ;
getPoint = ( w , h ) => [ w , 0 ] ;
getOpposite = ( w , h ) => [ 0 , h ] ;
break ;
case "middleRight" :
isHorizontal = true ;
getPoint = ( w , h ) => [ w , h / 2 ] ;
getOpposite = ( w , h ) => [ 0 , h / 2 ] ;
break ;
case "bottomRight" :
isDiagonal = true ;
getPoint = ( w , h ) => [ w , h ] ;
getOpposite = ( w , h ) => [ 0 , 0 ] ;
break ;
case "bottomMiddle" :
getPoint = ( w , h ) => [ w / 2 , h ] ;
getOpposite = ( w , h ) => [ w / 2 , 0 ] ;
break ;
case "bottomLeft" :
isDiagonal = true ;
getPoint = ( w , h ) => [ 0 , h ] ;
getOpposite = ( w , h ) => [ w , 0 ] ;
break ;
case "middleLeft" :
isHorizontal = true ;
getPoint = ( w , h ) => [ 0 , h / 2 ] ;
getOpposite = ( w , h ) => [ w , h / 2 ] ;
break ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
const point = getPoint ( savedWidth , savedHeight ) ;
const oppositePoint = getOpposite ( savedWidth , savedHeight ) ;
let transfOppositePoint = transf ( ... oppositePoint ) ;
const oppositeX = round ( savedX + transfOppositePoint [ 0 ] ) ;
const oppositeY = round ( savedY + transfOppositePoint [ 1 ] ) ;
let ratioX = 1 ;
let ratioY = 1 ;
let [ deltaX , deltaY ] = this . screenToPageTranslation ( event . movementX , event . movementY ) ;
[ deltaX , deltaY ] = invTransf ( deltaX / parentWidth , deltaY / parentHeight ) ;
if ( isDiagonal ) {
const oldDiag = Math . hypot ( savedWidth , savedHeight ) ;
ratioX = ratioY = Math . max ( Math . min ( Math . hypot ( oppositePoint [ 0 ] - point [ 0 ] - deltaX , oppositePoint [ 1 ] - point [ 1 ] - deltaY ) / oldDiag , 1 / savedWidth , 1 / savedHeight ) , minWidth / savedWidth , minHeight / savedHeight ) ;
} else if ( isHorizontal ) {
ratioX = Math . max ( minWidth , Math . min ( 1 , Math . abs ( oppositePoint [ 0 ] - point [ 0 ] - deltaX ) ) ) / savedWidth ;
} else {
ratioY = Math . max ( minHeight , Math . min ( 1 , Math . abs ( oppositePoint [ 1 ] - point [ 1 ] - deltaY ) ) ) / savedHeight ;
}
const newWidth = round ( savedWidth * ratioX ) ;
const newHeight = round ( savedHeight * ratioY ) ;
transfOppositePoint = transf ( ... getOpposite ( newWidth , newHeight ) ) ;
const newX = oppositeX - transfOppositePoint [ 0 ] ;
const newY = oppositeY - transfOppositePoint [ 1 ] ;
this . width = newWidth ;
this . height = newHeight ;
this . x = newX ;
this . y = newY ;
this . setDims ( parentWidth * newWidth , parentHeight * newHeight ) ;
this . fixAndSetPosition ( ) ;
2014-11-24 00:56:52 +01:00
}
2024-06-01 11:00:27 +01:00
altTextFinish ( ) {
this . # altText ? . finish ( ) ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
async addEditToolbar ( ) {
if ( this . # editToolbar || this . # isInEditMode ) {
return this . # editToolbar ;
}
this . # editToolbar = new EditorToolbar ( this ) ;
this . div . append ( this . # editToolbar . render ( ) ) ;
if ( this . # altText ) {
this . # editToolbar . addAltTextButton ( await this . # altText . render ( ) ) ;
}
return this . # editToolbar ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
removeEditToolbar ( ) {
if ( ! this . # editToolbar ) {
return ;
2014-11-24 00:56:52 +01:00
}
2024-06-01 11:00:27 +01:00
this . # editToolbar . remove ( ) ;
this . # editToolbar = null ;
this . # altText ? . destroy ( ) ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
getClientDimensions ( ) {
return this . div . getBoundingClientRect ( ) ;
}
async addAltTextButton ( ) {
if ( this . # altText ) {
return ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
AltText . initialize ( AnnotationEditor . _l10nPromise ) ;
this . # altText = new AltText ( this ) ;
await this . addEditToolbar ( ) ;
}
get altTextData ( ) {
return this . # altText ? . data ;
}
set altTextData ( data ) {
if ( ! this . # altText ) {
return ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
this . # altText . data = data ;
}
hasAltText ( ) {
return ! this . # altText ? . isEmpty ( ) ;
}
render ( ) {
this . div = document . createElement ( "div" ) ;
this . div . setAttribute ( "data-editor-rotation" , ( 360 - this . rotation ) % 360 ) ;
this . div . className = this . name ;
this . div . setAttribute ( "id" , this . id ) ;
this . div . tabIndex = this . # disabled ? - 1 : 0 ;
if ( ! this . _isVisible ) {
this . div . classList . add ( "hidden" ) ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
this . setInForeground ( ) ;
this . div . addEventListener ( "focusin" , this . # boundFocusin ) ;
this . div . addEventListener ( "focusout" , this . # boundFocusout ) ;
const [ parentWidth , parentHeight ] = this . parentDimensions ;
if ( this . parentRotation % 180 !== 0 ) {
this . div . style . maxWidth = ` ${ ( 100 * parentHeight / parentWidth ) . toFixed ( 2 ) } % ` ;
this . div . style . maxHeight = ` ${ ( 100 * parentWidth / parentHeight ) . toFixed ( 2 ) } % ` ;
2014-11-24 00:56:52 +01:00
}
2024-06-01 11:00:27 +01:00
const [ tx , ty ] = this . getInitialTranslation ( ) ;
this . translate ( tx , ty ) ;
bindEvents ( this , this . div , [ "pointerdown" ] ) ;
return this . div ;
2014-11-24 00:56:52 +01:00
}
2024-06-01 11:00:27 +01:00
pointerdown ( event ) {
const {
isMac
} = util _FeatureTest . platform ;
if ( event . button !== 0 || event . ctrlKey && isMac ) {
event . preventDefault ( ) ;
2016-04-04 15:49:28 +02:00
return ;
}
2024-06-01 11:00:27 +01:00
this . # hasBeenClicked = true ;
if ( this . _isDraggable ) {
this . # setUpDragSession ( event ) ;
2016-04-04 15:49:28 +02:00
return ;
}
2024-06-01 11:00:27 +01:00
this . # selectOnPointerEvent ( event ) ;
}
# selectOnPointerEvent ( event ) {
2023-10-27 13:19:54 +02:00
const {
2024-06-01 11:00:27 +01:00
isMac
} = util _FeatureTest . platform ;
if ( event . ctrlKey && ! isMac || event . shiftKey || event . metaKey && isMac ) {
this . parent . toggleSelected ( this ) ;
} else {
this . parent . setSelected ( this ) ;
2014-11-24 00:56:52 +01:00
}
2013-02-21 14:09:23 +00:00
}
2024-06-01 11:00:27 +01:00
# setUpDragSession ( event ) {
const isSelected = this . _uiManager . isSelected ( this ) ;
this . _uiManager . setUpDragSession ( ) ;
let pointerMoveOptions , pointerMoveCallback ;
if ( isSelected ) {
this . div . classList . add ( "moving" ) ;
pointerMoveOptions = {
passive : true ,
capture : true
} ;
this . # prevDragX = event . clientX ;
this . # prevDragY = event . clientY ;
pointerMoveCallback = e => {
const {
clientX : x ,
clientY : y
} = e ;
const [ tx , ty ] = this . screenToPageTranslation ( x - this . # prevDragX , y - this . # prevDragY ) ;
this . # prevDragX = x ;
this . # prevDragY = y ;
this . _uiManager . dragSelectedEditors ( tx , ty ) ;
} ;
window . addEventListener ( "pointermove" , pointerMoveCallback , pointerMoveOptions ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
const pointerUpCallback = ( ) => {
window . removeEventListener ( "pointerup" , pointerUpCallback ) ;
window . removeEventListener ( "blur" , pointerUpCallback ) ;
if ( isSelected ) {
this . div . classList . remove ( "moving" ) ;
window . removeEventListener ( "pointermove" , pointerMoveCallback , pointerMoveOptions ) ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
this . # hasBeenClicked = false ;
if ( ! this . _uiManager . endDragSession ( ) ) {
this . # selectOnPointerEvent ( event ) ;
}
} ;
window . addEventListener ( "pointerup" , pointerUpCallback ) ;
window . addEventListener ( "blur" , pointerUpCallback ) ;
2013-12-31 16:34:23 +05:30
}
2024-06-01 11:00:27 +01:00
moveInDOM ( ) {
if ( this . # moveInDOMTimeout ) {
clearTimeout ( this . # moveInDOMTimeout ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
this . # moveInDOMTimeout = setTimeout ( ( ) => {
this . # moveInDOMTimeout = null ;
this . parent ? . moveEditorInDOM ( this ) ;
} , 0 ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
_setParentAndPosition ( parent , x , y ) {
parent . changeParent ( this ) ;
this . x = x ;
this . y = y ;
this . fixAndSetPosition ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
getRect ( tx , ty , rotation = this . rotation ) {
const scale = this . parentScale ;
const [ pageWidth , pageHeight ] = this . pageDimensions ;
const [ pageX , pageY ] = this . pageTranslation ;
const shiftX = tx / scale ;
const shiftY = ty / scale ;
const x = this . x * pageWidth ;
const y = this . y * pageHeight ;
const width = this . width * pageWidth ;
const height = this . height * pageHeight ;
switch ( rotation ) {
case 0 :
return [ x + shiftX + pageX , pageHeight - y - shiftY - height + pageY , x + shiftX + width + pageX , pageHeight - y - shiftY + pageY ] ;
case 90 :
return [ x + shiftY + pageX , pageHeight - y + shiftX + pageY , x + shiftY + height + pageX , pageHeight - y + shiftX + width + pageY ] ;
case 180 :
return [ x - shiftX - width + pageX , pageHeight - y + shiftY + pageY , x - shiftX + pageX , pageHeight - y + shiftY + height + pageY ] ;
case 270 :
return [ x - shiftY - height + pageX , pageHeight - y - shiftX - width + pageY , x - shiftY + pageX , pageHeight - y - shiftX + pageY ] ;
default :
throw new Error ( "Invalid rotation" ) ;
}
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
getRectInCurrentCoords ( rect , pageHeight ) {
const [ x1 , y1 , x2 , y2 ] = rect ;
const width = x2 - x1 ;
const height = y2 - y1 ;
switch ( this . rotation ) {
case 0 :
return [ x1 , pageHeight - y2 , width , height ] ;
case 90 :
return [ x1 , pageHeight - y1 , height , width ] ;
case 180 :
return [ x2 , pageHeight - y1 , width , height ] ;
case 270 :
return [ x2 , pageHeight - y2 , height , width ] ;
default :
throw new Error ( "Invalid rotation" ) ;
2023-10-27 13:19:54 +02:00
}
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
onceAdded ( ) { }
isEmpty ( ) {
return false ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
enableEditMode ( ) {
this . # isInEditMode = true ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
disableEditMode ( ) {
this . # isInEditMode = false ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
isInEditMode ( ) {
return this . # isInEditMode ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
shouldGetKeyboardEvents ( ) {
return this . # isResizerEnabledForKeyboard ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
needsToBeRebuilt ( ) {
return this . div && ! this . isAttachedToDOM ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
rebuild ( ) {
this . div ? . addEventListener ( "focusin" , this . # boundFocusin ) ;
this . div ? . addEventListener ( "focusout" , this . # boundFocusout ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
rotate ( _angle ) { }
serialize ( isForCopying = false , context = null ) {
unreachable ( "An editor must be serializable" ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
static deserialize ( data , parent , uiManager ) {
const editor = new this . prototype . constructor ( {
parent ,
id : parent . getNextId ( ) ,
uiManager
} ) ;
editor . rotation = data . rotation ;
const [ pageWidth , pageHeight ] = editor . pageDimensions ;
const [ x , y , width , height ] = editor . getRectInCurrentCoords ( data . rect , pageHeight ) ;
editor . x = x / pageWidth ;
editor . y = y / pageHeight ;
editor . width = width / pageWidth ;
editor . height = height / pageHeight ;
return editor ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
get hasBeenModified ( ) {
return ! ! this . annotationElementId && ( this . deleted || this . serialize ( ) !== null ) ;
}
remove ( ) {
this . div . removeEventListener ( "focusin" , this . # boundFocusin ) ;
this . div . removeEventListener ( "focusout" , this . # boundFocusout ) ;
if ( ! this . isEmpty ( ) ) {
this . commit ( ) ;
}
if ( this . parent ) {
this . parent . remove ( this ) ;
} else {
this . _uiManager . removeEditor ( this ) ;
}
if ( this . # moveInDOMTimeout ) {
clearTimeout ( this . # moveInDOMTimeout ) ;
this . # moveInDOMTimeout = null ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
this . # stopResizing ( ) ;
this . removeEditToolbar ( ) ;
if ( this . # telemetryTimeouts ) {
for ( const timeout of this . # telemetryTimeouts . values ( ) ) {
clearTimeout ( timeout ) ;
}
this . # telemetryTimeouts = null ;
}
this . parent = null ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
get isResizable ( ) {
return false ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
makeResizable ( ) {
if ( this . isResizable ) {
this . # createResizers ( ) ;
this . # resizersDiv . classList . remove ( "hidden" ) ;
bindEvents ( this , this . div , [ "keydown" ] ) ;
2016-04-04 15:49:28 +02:00
}
}
2024-06-01 11:00:27 +01:00
get toolbarPosition ( ) {
return null ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
keydown ( event ) {
if ( ! this . isResizable || event . target !== this . div || event . key !== "Enter" ) {
2023-10-27 13:19:54 +02:00
return ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
this . _uiManager . setSelected ( this ) ;
this . # savedDimensions = {
savedX : this . x ,
savedY : this . y ,
savedWidth : this . width ,
savedHeight : this . height
} ;
const children = this . # resizersDiv . children ;
if ( ! this . # allResizerDivs ) {
this . # allResizerDivs = Array . from ( children ) ;
const boundResizerKeydown = this . # resizerKeydown . bind ( this ) ;
const boundResizerBlur = this . # resizerBlur . bind ( this ) ;
for ( const div of this . # allResizerDivs ) {
const name = div . getAttribute ( "data-resizer-name" ) ;
div . setAttribute ( "role" , "spinbutton" ) ;
div . addEventListener ( "keydown" , boundResizerKeydown ) ;
div . addEventListener ( "blur" , boundResizerBlur ) ;
div . addEventListener ( "focus" , this . # resizerFocus . bind ( this , name ) ) ;
AnnotationEditor . _l10nPromise . get ( ` pdfjs-editor-resizer-label- ${ name } ` ) . then ( msg => div . setAttribute ( "aria-label" , msg ) ) ;
}
}
const first = this . # allResizerDivs [ 0 ] ;
let firstPosition = 0 ;
for ( const div of children ) {
if ( div === first ) {
2023-10-27 13:19:54 +02:00
break ;
2013-02-21 14:09:23 +00:00
}
2024-06-01 11:00:27 +01:00
firstPosition ++ ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
const nextFirstPosition = ( 360 - this . rotation + this . parentRotation ) % 360 / 90 * ( this . # allResizerDivs . length / 4 ) ;
if ( nextFirstPosition !== firstPosition ) {
if ( nextFirstPosition < firstPosition ) {
for ( let i = 0 ; i < firstPosition - nextFirstPosition ; i ++ ) {
this . # resizersDiv . append ( this . # resizersDiv . firstChild ) ;
}
} else if ( nextFirstPosition > firstPosition ) {
for ( let i = 0 ; i < nextFirstPosition - firstPosition ; i ++ ) {
this . # resizersDiv . firstChild . before ( this . # resizersDiv . lastChild ) ;
}
}
let i = 0 ;
for ( const child of children ) {
const div = this . # allResizerDivs [ i ++ ] ;
const name = div . getAttribute ( "data-resizer-name" ) ;
AnnotationEditor . _l10nPromise . get ( ` pdfjs-editor-resizer-label- ${ name } ` ) . then ( msg => child . setAttribute ( "aria-label" , msg ) ) ;
}
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
this . # setResizerTabIndex ( 0 ) ;
this . # isResizerEnabledForKeyboard = true ;
this . # resizersDiv . firstChild . focus ( {
focusVisible : true
2023-10-27 13:19:54 +02:00
} ) ;
2024-06-01 11:00:27 +01:00
event . preventDefault ( ) ;
event . stopImmediatePropagation ( ) ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
# resizerKeydown ( event ) {
AnnotationEditor . _resizerKeyboardManager . exec ( this , event ) ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
# resizerBlur ( event ) {
if ( this . # isResizerEnabledForKeyboard && event . relatedTarget ? . parentNode !== this . # resizersDiv ) {
this . # stopResizing ( ) ;
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
# resizerFocus ( name ) {
this . # focusedResizerName = this . # isResizerEnabledForKeyboard ? name : "" ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
# setResizerTabIndex ( value ) {
if ( ! this . # allResizerDivs ) {
2023-10-27 13:19:54 +02:00
return ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
for ( const div of this . # allResizerDivs ) {
div . tabIndex = value ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
}
_resizeWithKeyboard ( x , y ) {
if ( ! this . # isResizerEnabledForKeyboard ) {
2023-10-27 13:19:54 +02:00
return ;
}
2024-06-01 11:00:27 +01:00
this . # resizerPointermove ( this . # focusedResizerName , {
movementX : x ,
movementY : y
} ) ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
# stopResizing ( ) {
this . # isResizerEnabledForKeyboard = false ;
this . # setResizerTabIndex ( - 1 ) ;
if ( this . # savedDimensions ) {
const {
savedX ,
savedY ,
savedWidth ,
savedHeight
} = this . # savedDimensions ;
this . # addResizeToUndoStack ( savedX , savedY , savedWidth , savedHeight ) ;
this . # savedDimensions = null ;
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
_stopResizingWithKeyboard ( ) {
this . # stopResizing ( ) ;
this . div . focus ( ) ;
}
select ( ) {
this . makeResizable ( ) ;
this . div ? . classList . add ( "selectedEditor" ) ;
if ( ! this . # editToolbar ) {
this . addEditToolbar ( ) . then ( ( ) => {
if ( this . div ? . classList . contains ( "selectedEditor" ) ) {
this . # editToolbar ? . show ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
} ) ;
2023-10-27 13:19:54 +02:00
return ;
}
2024-06-01 11:00:27 +01:00
this . # editToolbar ? . show ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
unselect ( ) {
this . # resizersDiv ? . classList . add ( "hidden" ) ;
this . div ? . classList . remove ( "selectedEditor" ) ;
if ( this . div ? . contains ( document . activeElement ) ) {
this . _uiManager . currentLayer . div . focus ( {
preventScroll : true
2023-10-27 13:19:54 +02:00
} ) ;
}
2024-06-01 11:00:27 +01:00
this . # editToolbar ? . hide ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
updateParams ( type , value ) { }
disableEditing ( ) { }
enableEditing ( ) { }
enterInEditMode ( ) { }
getImageForAltText ( ) {
return null ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
get contentDiv ( ) {
return this . div ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
get isEditing ( ) {
return this . # isEditing ;
}
set isEditing ( value ) {
this . # isEditing = value ;
if ( ! this . parent ) {
2023-10-27 13:19:54 +02:00
return ;
}
2024-06-01 11:00:27 +01:00
if ( value ) {
this . parent . setSelected ( this ) ;
this . parent . setActiveEditor ( this ) ;
} else {
this . parent . setActiveEditor ( null ) ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
setAspectRatio ( width , height ) {
this . # keepAspectRatio = true ;
const aspectRatio = width / height ;
const {
style
} = this . div ;
style . aspectRatio = aspectRatio ;
style . height = "auto" ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
static get MIN _SIZE ( ) {
return 16 ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
static canCreateNewEmptyEditor ( ) {
return true ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
get telemetryInitialData ( ) {
return {
action : "added"
} ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
get telemetryFinalData ( ) {
return null ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
_reportTelemetry ( data , mustWait = false ) {
if ( mustWait ) {
this . # telemetryTimeouts || = new Map ( ) ;
const {
action
} = data ;
let timeout = this . # telemetryTimeouts . get ( action ) ;
if ( timeout ) {
clearTimeout ( timeout ) ;
}
timeout = setTimeout ( ( ) => {
this . _reportTelemetry ( data ) ;
this . # telemetryTimeouts . delete ( action ) ;
if ( this . # telemetryTimeouts . size === 0 ) {
this . # telemetryTimeouts = null ;
}
} , AnnotationEditor . _telemetryTimeout ) ;
this . # telemetryTimeouts . set ( action , timeout ) ;
2023-10-27 13:19:54 +02:00
return ;
}
2024-06-01 11:00:27 +01:00
data . type || = this . editorType ;
this . _uiManager . _eventBus . dispatch ( "reporttelemetry" , {
2023-10-27 13:19:54 +02:00
source : this ,
2024-06-01 11:00:27 +01:00
details : {
type : "editing" ,
data
}
2023-10-27 13:19:54 +02:00
} ) ;
}
2024-06-01 11:00:27 +01:00
show ( visible = this . _isVisible ) {
this . div . classList . toggle ( "hidden" , ! visible ) ;
this . _isVisible = visible ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
enable ( ) {
if ( this . div ) {
this . div . tabIndex = 0 ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
this . # disabled = false ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
disable ( ) {
if ( this . div ) {
this . div . tabIndex = - 1 ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
this . # disabled = true ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
renderAnnotationElement ( annotation ) {
let content = annotation . container . querySelector ( ".annotationContent" ) ;
if ( ! content ) {
content = document . createElement ( "div" ) ;
content . classList . add ( "annotationContent" , this . editorType ) ;
annotation . container . prepend ( content ) ;
} else if ( content . nodeName === "CANVAS" ) {
const canvas = content ;
content = document . createElement ( "div" ) ;
content . classList . add ( "annotationContent" , this . editorType ) ;
canvas . before ( content ) ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
return content ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
resetAnnotationElement ( annotation ) {
const {
firstChild
} = annotation . container ;
if ( firstChild . nodeName === "DIV" && firstChild . classList . contains ( "annotationContent" ) ) {
firstChild . remove ( ) ;
2016-04-04 15:49:28 +02:00
}
}
2024-06-01 11:00:27 +01:00
}
class FakeEditor extends AnnotationEditor {
constructor ( params ) {
super ( params ) ;
this . annotationElementId = params . annotationElementId ;
this . deleted = true ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
serialize ( ) {
return {
id : this . annotationElementId ,
deleted : true ,
pageIndex : this . pageIndex
} ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
}
; // CONCATENATED MODULE: ./src/shared/murmurhash3.js
2024-06-18 20:06:52 +02:00
2024-06-01 11:00:27 +01:00
const SEED = 0xc3d2e1f0 ;
const MASK _HIGH = 0xffff0000 ;
const MASK _LOW = 0xffff ;
class MurmurHash3 _64 {
constructor ( seed ) {
this . h1 = seed ? seed & 0xffffffff : SEED ;
this . h2 = seed ? seed & 0xffffffff : SEED ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
update ( input ) {
let data , length ;
if ( typeof input === "string" ) {
data = new Uint8Array ( input . length * 2 ) ;
length = 0 ;
for ( let i = 0 , ii = input . length ; i < ii ; i ++ ) {
const code = input . charCodeAt ( i ) ;
if ( code <= 0xff ) {
data [ length ++ ] = code ;
} else {
data [ length ++ ] = code >>> 8 ;
data [ length ++ ] = code & 0xff ;
}
}
} else if ( ArrayBuffer . isView ( input ) ) {
data = input . slice ( ) ;
length = data . byteLength ;
} else {
throw new Error ( "Invalid data format, must be a string or TypedArray." ) ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
const blockCounts = length >> 2 ;
const tailLength = length - blockCounts * 4 ;
const dataUint32 = new Uint32Array ( data . buffer , 0 , blockCounts ) ;
let k1 = 0 ,
k2 = 0 ;
let h1 = this . h1 ,
h2 = this . h2 ;
const C1 = 0xcc9e2d51 ,
C2 = 0x1b873593 ;
const C1 _LOW = C1 & MASK _LOW ,
C2 _LOW = C2 & MASK _LOW ;
for ( let i = 0 ; i < blockCounts ; i ++ ) {
if ( i & 1 ) {
k1 = dataUint32 [ i ] ;
k1 = k1 * C1 & MASK _HIGH | k1 * C1 _LOW & MASK _LOW ;
k1 = k1 << 15 | k1 >>> 17 ;
k1 = k1 * C2 & MASK _HIGH | k1 * C2 _LOW & MASK _LOW ;
h1 ^= k1 ;
h1 = h1 << 13 | h1 >>> 19 ;
h1 = h1 * 5 + 0xe6546b64 ;
} else {
k2 = dataUint32 [ i ] ;
k2 = k2 * C1 & MASK _HIGH | k2 * C1 _LOW & MASK _LOW ;
k2 = k2 << 15 | k2 >>> 17 ;
k2 = k2 * C2 & MASK _HIGH | k2 * C2 _LOW & MASK _LOW ;
h2 ^= k2 ;
h2 = h2 << 13 | h2 >>> 19 ;
h2 = h2 * 5 + 0xe6546b64 ;
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
k1 = 0 ;
switch ( tailLength ) {
case 3 :
k1 ^= data [ blockCounts * 4 + 2 ] << 16 ;
case 2 :
k1 ^= data [ blockCounts * 4 + 1 ] << 8 ;
case 1 :
k1 ^= data [ blockCounts * 4 ] ;
k1 = k1 * C1 & MASK _HIGH | k1 * C1 _LOW & MASK _LOW ;
k1 = k1 << 15 | k1 >>> 17 ;
k1 = k1 * C2 & MASK _HIGH | k1 * C2 _LOW & MASK _LOW ;
if ( blockCounts & 1 ) {
h1 ^= k1 ;
} else {
h2 ^= k1 ;
}
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
this . h1 = h1 ;
this . h2 = h2 ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
hexdigest ( ) {
let h1 = this . h1 ,
h2 = this . h2 ;
h1 ^= h2 >>> 1 ;
h1 = h1 * 0xed558ccd & MASK _HIGH | h1 * 0x8ccd & MASK _LOW ;
h2 = h2 * 0xff51afd7 & MASK _HIGH | ( ( h2 << 16 | h1 >>> 16 ) * 0xafd7ed55 & MASK _HIGH ) >>> 16 ;
h1 ^= h2 >>> 1 ;
h1 = h1 * 0x1a85ec53 & MASK _HIGH | h1 * 0xec53 & MASK _LOW ;
h2 = h2 * 0xc4ceb9fe & MASK _HIGH | ( ( h2 << 16 | h1 >>> 16 ) * 0xb9fe1a85 & MASK _HIGH ) >>> 16 ;
h1 ^= h2 >>> 1 ;
return ( h1 >>> 0 ) . toString ( 16 ) . padStart ( 8 , "0" ) + ( h2 >>> 0 ) . toString ( 16 ) . padStart ( 8 , "0" ) ;
}
}
; // CONCATENATED MODULE: ./src/display/annotation_storage.js
2024-06-18 20:06:52 +02:00
2024-06-01 11:00:27 +01:00
const SerializableEmpty = Object . freeze ( {
map : null ,
hash : "" ,
transfer : undefined
} ) ;
class AnnotationStorage {
# modified = false ;
# storage = new Map ( ) ;
constructor ( ) {
this . onSetModified = null ;
this . onResetModified = null ;
this . onAnnotationEditor = null ;
}
getValue ( key , defaultValue ) {
const value = this . # storage . get ( key ) ;
if ( value === undefined ) {
return defaultValue ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
return Object . assign ( defaultValue , value ) ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
getRawValue ( key ) {
return this . # storage . get ( key ) ;
}
remove ( key ) {
this . # storage . delete ( key ) ;
if ( this . # storage . size === 0 ) {
this . resetModified ( ) ;
}
if ( typeof this . onAnnotationEditor === "function" ) {
for ( const value of this . # storage . values ( ) ) {
if ( value instanceof AnnotationEditor ) {
return ;
}
2014-11-24 00:56:52 +01:00
}
2024-06-01 11:00:27 +01:00
this . onAnnotationEditor ( null ) ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
setValue ( key , value ) {
const obj = this . # storage . get ( key ) ;
let modified = false ;
if ( obj !== undefined ) {
for ( const [ entry , val ] of Object . entries ( value ) ) {
if ( obj [ entry ] !== val ) {
modified = true ;
obj [ entry ] = val ;
}
}
} else {
modified = true ;
this . # storage . set ( key , value ) ;
}
if ( modified ) {
this . # setModified ( ) ;
}
if ( value instanceof AnnotationEditor && typeof this . onAnnotationEditor === "function" ) {
this . onAnnotationEditor ( value . constructor . _type ) ;
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
has ( key ) {
return this . # storage . has ( key ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
getAll ( ) {
return this . # storage . size > 0 ? objectFromMap ( this . # storage ) : null ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
setAll ( obj ) {
for ( const [ key , val ] of Object . entries ( obj ) ) {
this . setValue ( key , val ) ;
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
get size ( ) {
return this . # storage . size ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
# setModified ( ) {
if ( ! this . # modified ) {
this . # modified = true ;
if ( typeof this . onSetModified === "function" ) {
this . onSetModified ( ) ;
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
}
resetModified ( ) {
if ( this . # modified ) {
this . # modified = false ;
if ( typeof this . onResetModified === "function" ) {
this . onResetModified ( ) ;
2013-03-03 08:22:46 +00:00
}
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
get print ( ) {
return new PrintAnnotationStorage ( this ) ;
}
get serializable ( ) {
if ( this . # storage . size === 0 ) {
return SerializableEmpty ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
const map = new Map ( ) ,
hash = new MurmurHash3 _64 ( ) ,
transfer = [ ] ;
const context = Object . create ( null ) ;
let hasBitmap = false ;
for ( const [ key , val ] of this . # storage ) {
const serialized = val instanceof AnnotationEditor ? val . serialize ( false , context ) : val ;
if ( serialized ) {
map . set ( key , serialized ) ;
hash . update ( ` ${ key } : ${ JSON . stringify ( serialized ) } ` ) ;
hasBitmap || = ! ! serialized . bitmap ;
2014-11-24 00:56:52 +01:00
}
2024-06-01 11:00:27 +01:00
}
if ( hasBitmap ) {
for ( const value of map . values ( ) ) {
if ( value . bitmap ) {
transfer . push ( value . bitmap ) ;
}
2013-12-31 16:34:23 +05:30
}
2024-06-01 11:00:27 +01:00
}
return map . size > 0 ? {
map ,
hash : hash . hexdigest ( ) ,
transfer
} : SerializableEmpty ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
get editorStats ( ) {
let stats = null ;
const typeToEditor = new Map ( ) ;
for ( const value of this . # storage . values ( ) ) {
if ( ! ( value instanceof AnnotationEditor ) ) {
2023-10-27 13:19:54 +02:00
continue ;
}
2024-06-01 11:00:27 +01:00
const editorStats = value . telemetryFinalData ;
if ( ! editorStats ) {
continue ;
}
const {
type
} = editorStats ;
if ( ! typeToEditor . has ( type ) ) {
typeToEditor . set ( type , Object . getPrototypeOf ( value ) . constructor ) ;
}
stats || = Object . create ( null ) ;
const map = stats [ type ] || = new Map ( ) ;
for ( const [ key , val ] of Object . entries ( editorStats ) ) {
if ( key === "type" ) {
continue ;
}
let counters = map . get ( key ) ;
if ( ! counters ) {
counters = new Map ( ) ;
map . set ( key , counters ) ;
}
const count = counters . get ( val ) ? ? 0 ;
counters . set ( val , count + 1 ) ;
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
for ( const [ type , editor ] of typeToEditor ) {
stats [ type ] = editor . computeTelemetryFinalData ( stats [ type ] ) ;
}
return stats ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
}
class PrintAnnotationStorage extends AnnotationStorage {
# serializable ;
constructor ( parent ) {
super ( ) ;
const {
map ,
hash ,
transfer
} = parent . serializable ;
const clone = structuredClone ( map , transfer ? {
transfer
} : null ) ;
this . # serializable = {
map : clone ,
hash ,
transfer
} ;
}
get print ( ) {
unreachable ( "Should not call PrintAnnotationStorage.print" ) ;
}
get serializable ( ) {
return this . # serializable ;
}
}
; // CONCATENATED MODULE: ./src/display/font_loader.js
2024-06-18 20:06:52 +02:00
2024-06-01 11:00:27 +01:00
class FontLoader {
# systemFonts = new Set ( ) ;
constructor ( {
ownerDocument = globalThis . document ,
styleElement = null
} ) {
this . _document = ownerDocument ;
this . nativeFontFaces = new Set ( ) ;
this . styleElement = null ;
this . loadingRequests = [ ] ;
this . loadTestFontId = 0 ;
}
addNativeFontFace ( nativeFontFace ) {
this . nativeFontFaces . add ( nativeFontFace ) ;
this . _document . fonts . add ( nativeFontFace ) ;
}
removeNativeFontFace ( nativeFontFace ) {
this . nativeFontFaces . delete ( nativeFontFace ) ;
this . _document . fonts . delete ( nativeFontFace ) ;
}
insertRule ( rule ) {
if ( ! this . styleElement ) {
this . styleElement = this . _document . createElement ( "style" ) ;
this . _document . documentElement . getElementsByTagName ( "head" ) [ 0 ] . append ( this . styleElement ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
const styleSheet = this . styleElement . sheet ;
styleSheet . insertRule ( rule , styleSheet . cssRules . length ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
clear ( ) {
for ( const nativeFontFace of this . nativeFontFaces ) {
this . _document . fonts . delete ( nativeFontFace ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
this . nativeFontFaces . clear ( ) ;
this . # systemFonts . clear ( ) ;
if ( this . styleElement ) {
this . styleElement . remove ( ) ;
this . styleElement = null ;
}
}
async loadSystemFont ( {
systemFontInfo : info ,
_inspectFont
} ) {
if ( ! info || this . # systemFonts . has ( info . loadedName ) ) {
2023-10-27 13:19:54 +02:00
return ;
}
2024-06-01 11:00:27 +01:00
assert ( ! this . disableFontFace , "loadSystemFont shouldn't be called when `disableFontFace` is set." ) ;
if ( this . isFontLoadingAPISupported ) {
const {
loadedName ,
src ,
style
} = info ;
const fontFace = new FontFace ( loadedName , src , style ) ;
this . addNativeFontFace ( fontFace ) ;
try {
await fontFace . load ( ) ;
this . # systemFonts . add ( loadedName ) ;
_inspectFont ? . ( info ) ;
} catch {
warn ( ` Cannot load system font: ${ info . baseFontName } , installing it could help to improve PDF rendering. ` ) ;
this . removeNativeFontFace ( fontFace ) ;
}
return ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
unreachable ( "Not implemented: loadSystemFont without the Font Loading API." ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
async bind ( font ) {
if ( font . attached || font . missingFile && ! font . systemFontInfo ) {
return ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
font . attached = true ;
if ( font . systemFontInfo ) {
await this . loadSystemFont ( font ) ;
2023-10-27 13:19:54 +02:00
return ;
}
2024-06-01 11:00:27 +01:00
if ( this . isFontLoadingAPISupported ) {
const nativeFontFace = font . createNativeFontFace ( ) ;
if ( nativeFontFace ) {
this . addNativeFontFace ( nativeFontFace ) ;
try {
await nativeFontFace . loaded ;
} catch ( ex ) {
warn ( ` Failed to load font ' ${ nativeFontFace . family } ': ' ${ ex } '. ` ) ;
font . disableFontFace = true ;
throw ex ;
}
}
return ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
const rule = font . createFontFaceRule ( ) ;
if ( rule ) {
this . insertRule ( rule ) ;
if ( this . isSyncFontLoadingSupported ) {
return ;
}
await new Promise ( resolve => {
const request = this . _queueLoadingCallback ( resolve ) ;
this . _prepareFontLoadEvent ( font , request ) ;
2023-10-27 13:19:54 +02:00
} ) ;
}
}
2024-06-01 11:00:27 +01:00
get isFontLoadingAPISupported ( ) {
const hasFonts = ! ! this . _document ? . fonts ;
return shadow ( this , "isFontLoadingAPISupported" , hasFonts ) ;
}
get isSyncFontLoadingSupported ( ) {
let supported = false ;
if ( isNodeJS ) {
supported = true ;
} else if ( typeof navigator !== "undefined" && typeof navigator ? . userAgent === "string" && /Mozilla\/5.0.*?rv:\d+.*? Gecko/ . test ( navigator . userAgent ) ) {
supported = true ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
return shadow ( this , "isSyncFontLoadingSupported" , supported ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
_queueLoadingCallback ( callback ) {
function completeRequest ( ) {
assert ( ! request . done , "completeRequest() cannot be called twice." ) ;
request . done = true ;
while ( loadingRequests . length > 0 && loadingRequests [ 0 ] . done ) {
const otherRequest = loadingRequests . shift ( ) ;
setTimeout ( otherRequest . callback , 0 ) ;
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
const {
loadingRequests
} = this ;
const request = {
done : false ,
complete : completeRequest ,
callback
} ;
loadingRequests . push ( request ) ;
return request ;
}
get _loadTestFont ( ) {
const testFont = atob ( "T1RUTwALAIAAAwAwQ0ZGIDHtZg4AAAOYAAAAgUZGVE1lkzZwAAAEHAAAABxHREVGABQA" + "FQAABDgAAAAeT1MvMlYNYwkAAAEgAAAAYGNtYXABDQLUAAACNAAAAUJoZWFk/xVFDQAA" + "ALwAAAA2aGhlYQdkA+oAAAD0AAAAJGhtdHgD6AAAAAAEWAAAAAZtYXhwAAJQAAAAARgA" + "AAAGbmFtZVjmdH4AAAGAAAAAsXBvc3T/hgAzAAADeAAAACAAAQAAAAEAALZRFsRfDzz1" + "AAsD6AAAAADOBOTLAAAAAM4KHDwAAAAAA+gDIQAAAAgAAgAAAAAAAAABAAADIQAAAFoD" + "6AAAAAAD6AABAAAAAAAAAAAAAAAAAAAAAQAAUAAAAgAAAAQD6AH0AAUAAAKKArwAAACM" + "AooCvAAAAeAAMQECAAACAAYJAAAAAAAAAAAAAQAAAAAAAAAAAAAAAFBmRWQAwAAuAC4D" + "IP84AFoDIQAAAAAAAQAAAAAAAAAAACAAIAABAAAADgCuAAEAAAAAAAAAAQAAAAEAAAAA" + "AAEAAQAAAAEAAAAAAAIAAQAAAAEAAAAAAAMAAQAAAAEAAAAAAAQAAQAAAAEAAAAAAAUA" + "AQAAAAEAAAAAAAYAAQAAAAMAAQQJAAAAAgABAAMAAQQJAAEAAgABAAMAAQQJAAIAAgAB" + "AAMAAQQJAAMAAgABAAMAAQQJAAQAAgABAAMAAQQJAAUAAgABAAMAAQQJAAYAAgABWABY" + "AAAAAAAAAwAAAAMAAAAcAAEAAAAAADwAAwABAAAAHAAEACAAAAAEAAQAAQAAAC7//wAA" + "AC7////TAAEAAAAAAAABBgAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAD/gwAyAAAAAQAAAAAAAAAAAAAAAAAA" + "AAABAAQEAAEBAQJYAAEBASH4DwD4GwHEAvgcA/gXBIwMAYuL+nz5tQXkD5j3CBLnEQAC" + "AQEBIVhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYAAABAQAADwACAQEEE/t3" + "Dov6fAH6fAT+fPp8+nwHDosMCvm1Cvm1DAz6fBQAAAAAAAABAAAAAMmJbzEAAAAAzgTj" + "FQAAAADOBOQpAAEAAAAAAAAADAAUAAQAAAABAAAAAgABAAAAAAAAAAAD6AAAAAAAAA==" ) ;
return shadow ( this , "_loadTestFont" , testFont ) ;
}
_prepareFontLoadEvent ( font , request ) {
function int32 ( data , offset ) {
return data . charCodeAt ( offset ) << 24 | data . charCodeAt ( offset + 1 ) << 16 | data . charCodeAt ( offset + 2 ) << 8 | data . charCodeAt ( offset + 3 ) & 0xff ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
function spliceString ( s , offset , remove , insert ) {
const chunk1 = s . substring ( 0 , offset ) ;
const chunk2 = s . substring ( offset + remove ) ;
return chunk1 + insert + chunk2 ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
let i , ii ;
const canvas = this . _document . createElement ( "canvas" ) ;
canvas . width = 1 ;
canvas . height = 1 ;
const ctx = canvas . getContext ( "2d" ) ;
let called = 0 ;
function isFontReady ( name , callback ) {
if ( ++ called > 30 ) {
warn ( "Load test font never loaded." ) ;
callback ( ) ;
return ;
2014-11-24 00:56:52 +01:00
}
2024-06-01 11:00:27 +01:00
ctx . font = "30px " + name ;
ctx . fillText ( "." , 0 , 20 ) ;
const imageData = ctx . getImageData ( 0 , 0 , 1 , 1 ) ;
if ( imageData . data [ 3 ] > 0 ) {
callback ( ) ;
return ;
}
setTimeout ( isFontReady . bind ( null , name , callback ) ) ;
}
const loadTestFontId = ` lt ${ Date . now ( ) } ${ this . loadTestFontId ++ } ` ;
let data = this . _loadTestFont ;
const COMMENT _OFFSET = 976 ;
data = spliceString ( data , COMMENT _OFFSET , loadTestFontId . length , loadTestFontId ) ;
const CFF _CHECKSUM _OFFSET = 16 ;
const XXXX _VALUE = 0x58585858 ;
let checksum = int32 ( data , CFF _CHECKSUM _OFFSET ) ;
for ( i = 0 , ii = loadTestFontId . length - 3 ; i < ii ; i += 4 ) {
checksum = checksum - XXXX _VALUE + int32 ( loadTestFontId , i ) | 0 ;
}
if ( i < loadTestFontId . length ) {
checksum = checksum - XXXX _VALUE + int32 ( loadTestFontId + "XXX" , i ) | 0 ;
}
data = spliceString ( data , CFF _CHECKSUM _OFFSET , 4 , string32 ( checksum ) ) ;
const url = ` url(data:font/opentype;base64, ${ btoa ( data ) } ); ` ;
const rule = ` @font-face {font-family:" ${ loadTestFontId } ";src: ${ url } } ` ;
this . insertRule ( rule ) ;
const div = this . _document . createElement ( "div" ) ;
div . style . visibility = "hidden" ;
div . style . width = div . style . height = "10px" ;
div . style . position = "absolute" ;
div . style . top = div . style . left = "0px" ;
for ( const name of [ font . loadedName , loadTestFontId ] ) {
const span = this . _document . createElement ( "span" ) ;
span . textContent = "Hi" ;
span . style . fontFamily = name ;
div . append ( span ) ;
}
this . _document . body . append ( div ) ;
isFontReady ( loadTestFontId , ( ) => {
div . remove ( ) ;
request . complete ( ) ;
2023-10-27 13:19:54 +02:00
} ) ;
}
2024-06-01 11:00:27 +01:00
}
class FontFaceObject {
constructor ( translatedData , {
disableFontFace = false ,
inspectFont = null
} ) {
this . compiledGlyphs = Object . create ( null ) ;
for ( const i in translatedData ) {
this [ i ] = translatedData [ i ] ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
this . disableFontFace = disableFontFace === true ;
this . _inspectFont = inspectFont ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
createNativeFontFace ( ) {
if ( ! this . data || this . disableFontFace ) {
return null ;
}
let nativeFontFace ;
if ( ! this . cssFontInfo ) {
nativeFontFace = new FontFace ( this . loadedName , this . data , { } ) ;
} else {
const css = {
weight : this . cssFontInfo . fontWeight
} ;
if ( this . cssFontInfo . italicAngle ) {
css . style = ` oblique ${ this . cssFontInfo . italicAngle } deg ` ;
2014-11-24 00:56:52 +01:00
}
2024-06-01 11:00:27 +01:00
nativeFontFace = new FontFace ( this . cssFontInfo . fontFamily , this . data , css ) ;
}
this . _inspectFont ? . ( this ) ;
return nativeFontFace ;
}
createFontFaceRule ( ) {
if ( ! this . data || this . disableFontFace ) {
return null ;
}
const data = bytesToString ( this . data ) ;
const url = ` url(data: ${ this . mimetype } ;base64, ${ btoa ( data ) } ); ` ;
let rule ;
if ( ! this . cssFontInfo ) {
rule = ` @font-face {font-family:" ${ this . loadedName } ";src: ${ url } } ` ;
2023-10-27 13:19:54 +02:00
} else {
2024-06-01 11:00:27 +01:00
let css = ` font-weight: ${ this . cssFontInfo . fontWeight } ; ` ;
if ( this . cssFontInfo . italicAngle ) {
css += ` font-style: oblique ${ this . cssFontInfo . italicAngle } deg; ` ;
}
rule = ` @font-face {font-family:" ${ this . cssFontInfo . fontFamily } "; ${ css } src: ${ url } } ` ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
this . _inspectFont ? . ( this , url ) ;
return rule ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
getPathGenerator ( objs , character ) {
if ( this . compiledGlyphs [ character ] !== undefined ) {
return this . compiledGlyphs [ character ] ;
}
let cmds ;
try {
cmds = objs . get ( this . loadedName + "_path_" + character ) ;
} catch ( ex ) {
warn ( ` getPathGenerator - ignoring character: " ${ ex } ". ` ) ;
}
if ( ! Array . isArray ( cmds ) || cmds . length === 0 ) {
return this . compiledGlyphs [ character ] = function ( c , size ) { } ;
}
const commands = [ ] ;
for ( let i = 0 , ii = cmds . length ; i < ii ; ) {
switch ( cmds [ i ++ ] ) {
case FontRenderOps . BEZIER _CURVE _TO :
{
const [ a , b , c , d , e , f ] = cmds . slice ( i , i + 6 ) ;
commands . push ( ctx => ctx . bezierCurveTo ( a , b , c , d , e , f ) ) ;
i += 6 ;
}
break ;
case FontRenderOps . MOVE _TO :
{
const [ a , b ] = cmds . slice ( i , i + 2 ) ;
commands . push ( ctx => ctx . moveTo ( a , b ) ) ;
i += 2 ;
}
break ;
case FontRenderOps . LINE _TO :
{
const [ a , b ] = cmds . slice ( i , i + 2 ) ;
commands . push ( ctx => ctx . lineTo ( a , b ) ) ;
i += 2 ;
}
break ;
case FontRenderOps . QUADRATIC _CURVE _TO :
{
const [ a , b , c , d ] = cmds . slice ( i , i + 4 ) ;
commands . push ( ctx => ctx . quadraticCurveTo ( a , b , c , d ) ) ;
i += 4 ;
}
break ;
case FontRenderOps . RESTORE :
commands . push ( ctx => ctx . restore ( ) ) ;
break ;
case FontRenderOps . SAVE :
commands . push ( ctx => ctx . save ( ) ) ;
break ;
case FontRenderOps . SCALE :
assert ( commands . length === 2 , "Scale command is only valid at the third position." ) ;
break ;
case FontRenderOps . TRANSFORM :
{
const [ a , b , c , d , e , f ] = cmds . slice ( i , i + 6 ) ;
commands . push ( ctx => ctx . transform ( a , b , c , d , e , f ) ) ;
i += 6 ;
}
break ;
case FontRenderOps . TRANSLATE :
{
const [ a , b ] = cmds . slice ( i , i + 2 ) ;
commands . push ( ctx => ctx . translate ( a , b ) ) ;
i += 2 ;
}
break ;
}
}
return this . compiledGlyphs [ character ] = function glyphDrawer ( ctx , size ) {
commands [ 0 ] ( ctx ) ;
commands [ 1 ] ( ctx ) ;
ctx . scale ( size , - size ) ;
for ( let i = 2 , ii = commands . length ; i < ii ; i ++ ) {
commands [ i ] ( ctx ) ;
}
} ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
}
; // CONCATENATED MODULE: ./src/display/node_utils.js
2024-06-18 20:06:52 +02:00
2024-06-01 11:00:27 +01:00
if ( isNodeJS ) {
var packageCapability = Promise . withResolvers ( ) ;
var packageMap = null ;
const loadPackages = async ( ) => {
const fs = await import ( /*webpackIgnore: true*/ "fs" ) ,
http = await import ( /*webpackIgnore: true*/ "http" ) ,
https = await import ( /*webpackIgnore: true*/ "https" ) ,
url = await import ( /*webpackIgnore: true*/ "url" ) ;
let canvas , path2d ;
2024-06-18 20:06:52 +02:00
try {
canvas = await import ( /*webpackIgnore: true*/ "canvas" ) ;
} catch { }
try {
path2d = await import ( /*webpackIgnore: true*/ "path2d" ) ;
} catch { }
2024-06-01 11:00:27 +01:00
return new Map ( Object . entries ( {
fs ,
http ,
https ,
url ,
canvas ,
path2d
} ) ) ;
} ;
loadPackages ( ) . then ( map => {
packageMap = map ;
packageCapability . resolve ( ) ;
2024-06-18 20:06:52 +02:00
if ( ! globalThis . DOMMatrix ) {
const DOMMatrix = map . get ( "canvas" ) ? . DOMMatrix ;
if ( DOMMatrix ) {
globalThis . DOMMatrix = DOMMatrix ;
} else {
warn ( "Cannot polyfill `DOMMatrix`, rendering may be broken." ) ;
}
}
if ( ! globalThis . Path2D ) {
const CanvasRenderingContext2D = map . get ( "canvas" ) ? . CanvasRenderingContext2D ;
const applyPath2DToCanvasRenderingContext = map . get ( "path2d" ) ? . applyPath2DToCanvasRenderingContext ;
const Path2D = map . get ( "path2d" ) ? . Path2D ;
if ( CanvasRenderingContext2D && applyPath2DToCanvasRenderingContext && Path2D ) {
applyPath2DToCanvasRenderingContext ( CanvasRenderingContext2D ) ;
globalThis . Path2D = Path2D ;
} else {
warn ( "Cannot polyfill `Path2D`, rendering may be broken." ) ;
}
}
2024-06-01 11:00:27 +01:00
} , reason => {
warn ( ` loadPackages: ${ reason } ` ) ;
packageMap = new Map ( ) ;
packageCapability . resolve ( ) ;
} ) ;
}
class NodePackages {
static get promise ( ) {
return packageCapability . promise ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
static get ( name ) {
return packageMap ? . get ( name ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
}
const node _utils _fetchData = function ( url ) {
const fs = NodePackages . get ( "fs" ) ;
return fs . promises . readFile ( url ) . then ( data => new Uint8Array ( data ) ) ;
} ;
class NodeFilterFactory extends BaseFilterFactory { }
class NodeCanvasFactory extends BaseCanvasFactory {
_createCanvas ( width , height ) {
const canvas = NodePackages . get ( "canvas" ) ;
return canvas . createCanvas ( width , height ) ;
}
}
class NodeCMapReaderFactory extends BaseCMapReaderFactory {
_fetchData ( url , compressionType ) {
return node _utils _fetchData ( url ) . then ( data => ( {
cMapData : data ,
compressionType
} ) ) ;
}
}
class NodeStandardFontDataFactory extends BaseStandardFontDataFactory {
_fetchData ( url ) {
return node _utils _fetchData ( url ) ;
2023-10-27 13:19:54 +02:00
}
}
2013-12-31 16:34:23 +05:30
2024-06-01 11:00:27 +01:00
; // CONCATENATED MODULE: ./src/display/pattern_helper.js
2013-02-21 14:09:23 +00:00
2024-06-01 11:00:27 +01:00
const PathType = {
FILL : "Fill" ,
STROKE : "Stroke" ,
SHADING : "Shading"
} ;
function applyBoundingBox ( ctx , bbox ) {
if ( ! bbox ) {
return ;
}
const width = bbox [ 2 ] - bbox [ 0 ] ;
const height = bbox [ 3 ] - bbox [ 1 ] ;
const region = new Path2D ( ) ;
region . rect ( bbox [ 0 ] , bbox [ 1 ] , width , height ) ;
ctx . clip ( region ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
class BaseShadingPattern {
constructor ( ) {
if ( this . constructor === BaseShadingPattern ) {
unreachable ( "Cannot initialize BaseShadingPattern." ) ;
}
}
getPattern ( ) {
unreachable ( "Abstract method `getPattern` called." ) ;
}
}
class RadialAxialShadingPattern extends BaseShadingPattern {
constructor ( IR ) {
2023-10-27 13:19:54 +02:00
super ( ) ;
2024-06-01 11:00:27 +01:00
this . _type = IR [ 1 ] ;
this . _bbox = IR [ 2 ] ;
this . _colorStops = IR [ 3 ] ;
this . _p0 = IR [ 4 ] ;
this . _p1 = IR [ 5 ] ;
this . _r0 = IR [ 6 ] ;
this . _r1 = IR [ 7 ] ;
this . matrix = null ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
_createGradient ( ctx ) {
let grad ;
if ( this . _type === "axial" ) {
grad = ctx . createLinearGradient ( this . _p0 [ 0 ] , this . _p0 [ 1 ] , this . _p1 [ 0 ] , this . _p1 [ 1 ] ) ;
} else if ( this . _type === "radial" ) {
grad = ctx . createRadialGradient ( this . _p0 [ 0 ] , this . _p0 [ 1 ] , this . _r0 , this . _p1 [ 0 ] , this . _p1 [ 1 ] , this . _r1 ) ;
}
for ( const colorStop of this . _colorStops ) {
grad . addColorStop ( colorStop [ 0 ] , colorStop [ 1 ] ) ;
}
return grad ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
getPattern ( ctx , owner , inverse , pathType ) {
let pattern ;
if ( pathType === PathType . STROKE || pathType === PathType . FILL ) {
const ownerBBox = owner . current . getClippedPathBoundingBox ( pathType , getCurrentTransform ( ctx ) ) || [ 0 , 0 , 0 , 0 ] ;
const width = Math . ceil ( ownerBBox [ 2 ] - ownerBBox [ 0 ] ) || 1 ;
const height = Math . ceil ( ownerBBox [ 3 ] - ownerBBox [ 1 ] ) || 1 ;
const tmpCanvas = owner . cachedCanvases . getCanvas ( "pattern" , width , height , true ) ;
const tmpCtx = tmpCanvas . context ;
tmpCtx . clearRect ( 0 , 0 , tmpCtx . canvas . width , tmpCtx . canvas . height ) ;
tmpCtx . beginPath ( ) ;
tmpCtx . rect ( 0 , 0 , tmpCtx . canvas . width , tmpCtx . canvas . height ) ;
tmpCtx . translate ( - ownerBBox [ 0 ] , - ownerBBox [ 1 ] ) ;
inverse = Util . transform ( inverse , [ 1 , 0 , 0 , 1 , ownerBBox [ 0 ] , ownerBBox [ 1 ] ] ) ;
tmpCtx . transform ( ... owner . baseTransform ) ;
if ( this . matrix ) {
tmpCtx . transform ( ... this . matrix ) ;
2014-11-24 00:56:52 +01:00
}
2024-06-01 11:00:27 +01:00
applyBoundingBox ( tmpCtx , this . _bbox ) ;
tmpCtx . fillStyle = this . _createGradient ( tmpCtx ) ;
tmpCtx . fill ( ) ;
pattern = ctx . createPattern ( tmpCanvas . canvas , "no-repeat" ) ;
const domMatrix = new DOMMatrix ( inverse ) ;
pattern . setTransform ( domMatrix ) ;
2023-10-27 13:19:54 +02:00
} else {
2024-06-01 11:00:27 +01:00
applyBoundingBox ( ctx , this . _bbox ) ;
pattern = this . _createGradient ( ctx ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
return pattern ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
}
function drawTriangle ( data , context , p1 , p2 , p3 , c1 , c2 , c3 ) {
const coords = context . coords ,
colors = context . colors ;
const bytes = data . data ,
rowSize = data . width * 4 ;
let tmp ;
if ( coords [ p1 + 1 ] > coords [ p2 + 1 ] ) {
tmp = p1 ;
p1 = p2 ;
p2 = tmp ;
tmp = c1 ;
c1 = c2 ;
c2 = tmp ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
if ( coords [ p2 + 1 ] > coords [ p3 + 1 ] ) {
tmp = p2 ;
p2 = p3 ;
p3 = tmp ;
tmp = c2 ;
c2 = c3 ;
c3 = tmp ;
}
if ( coords [ p1 + 1 ] > coords [ p2 + 1 ] ) {
tmp = p1 ;
p1 = p2 ;
p2 = tmp ;
tmp = c1 ;
c1 = c2 ;
c2 = tmp ;
}
const x1 = ( coords [ p1 ] + context . offsetX ) * context . scaleX ;
const y1 = ( coords [ p1 + 1 ] + context . offsetY ) * context . scaleY ;
const x2 = ( coords [ p2 ] + context . offsetX ) * context . scaleX ;
const y2 = ( coords [ p2 + 1 ] + context . offsetY ) * context . scaleY ;
const x3 = ( coords [ p3 ] + context . offsetX ) * context . scaleX ;
const y3 = ( coords [ p3 + 1 ] + context . offsetY ) * context . scaleY ;
if ( y1 >= y3 ) {
return ;
}
const c1r = colors [ c1 ] ,
c1g = colors [ c1 + 1 ] ,
c1b = colors [ c1 + 2 ] ;
const c2r = colors [ c2 ] ,
c2g = colors [ c2 + 1 ] ,
c2b = colors [ c2 + 2 ] ;
const c3r = colors [ c3 ] ,
c3g = colors [ c3 + 1 ] ,
c3b = colors [ c3 + 2 ] ;
const minY = Math . round ( y1 ) ,
maxY = Math . round ( y3 ) ;
let xa , car , cag , cab ;
let xb , cbr , cbg , cbb ;
for ( let y = minY ; y <= maxY ; y ++ ) {
if ( y < y2 ) {
const k = y < y1 ? 0 : ( y1 - y ) / ( y1 - y2 ) ;
xa = x1 - ( x1 - x2 ) * k ;
car = c1r - ( c1r - c2r ) * k ;
cag = c1g - ( c1g - c2g ) * k ;
cab = c1b - ( c1b - c2b ) * k ;
} else {
let k ;
if ( y > y3 ) {
k = 1 ;
} else if ( y2 === y3 ) {
k = 0 ;
} else {
k = ( y2 - y ) / ( y2 - y3 ) ;
}
xa = x2 - ( x2 - x3 ) * k ;
car = c2r - ( c2r - c3r ) * k ;
cag = c2g - ( c2g - c3g ) * k ;
cab = c2b - ( c2b - c3b ) * k ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
let k ;
if ( y < y1 ) {
k = 0 ;
} else if ( y > y3 ) {
k = 1 ;
} else {
k = ( y1 - y ) / ( y1 - y3 ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
xb = x1 - ( x1 - x3 ) * k ;
cbr = c1r - ( c1r - c3r ) * k ;
cbg = c1g - ( c1g - c3g ) * k ;
cbb = c1b - ( c1b - c3b ) * k ;
const x1 _ = Math . round ( Math . min ( xa , xb ) ) ;
const x2 _ = Math . round ( Math . max ( xa , xb ) ) ;
let j = rowSize * y + x1 _ * 4 ;
for ( let x = x1 _ ; x <= x2 _ ; x ++ ) {
k = ( xa - x ) / ( xa - xb ) ;
if ( k < 0 ) {
k = 0 ;
} else if ( k > 1 ) {
k = 1 ;
}
bytes [ j ++ ] = car - ( car - cbr ) * k | 0 ;
bytes [ j ++ ] = cag - ( cag - cbg ) * k | 0 ;
bytes [ j ++ ] = cab - ( cab - cbb ) * k | 0 ;
bytes [ j ++ ] = 255 ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
}
}
function drawFigure ( data , figure , context ) {
const ps = figure . coords ;
const cs = figure . colors ;
let i , ii ;
switch ( figure . type ) {
case "lattice" :
const verticesPerRow = figure . verticesPerRow ;
const rows = Math . floor ( ps . length / verticesPerRow ) - 1 ;
const cols = verticesPerRow - 1 ;
for ( i = 0 ; i < rows ; i ++ ) {
let q = i * verticesPerRow ;
for ( let j = 0 ; j < cols ; j ++ , q ++ ) {
drawTriangle ( data , context , ps [ q ] , ps [ q + 1 ] , ps [ q + verticesPerRow ] , cs [ q ] , cs [ q + 1 ] , cs [ q + verticesPerRow ] ) ;
drawTriangle ( data , context , ps [ q + verticesPerRow + 1 ] , ps [ q + 1 ] , ps [ q + verticesPerRow ] , cs [ q + verticesPerRow + 1 ] , cs [ q + 1 ] , cs [ q + verticesPerRow ] ) ;
2016-04-04 15:49:28 +02:00
}
2013-02-21 14:09:23 +00:00
}
2024-06-01 11:00:27 +01:00
break ;
case "triangles" :
for ( i = 0 , ii = ps . length ; i < ii ; i += 3 ) {
drawTriangle ( data , context , ps [ i ] , ps [ i + 1 ] , ps [ i + 2 ] , cs [ i ] , cs [ i + 1 ] , cs [ i + 2 ] ) ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
break ;
default :
throw new Error ( "illegal figure" ) ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
class MeshShadingPattern extends BaseShadingPattern {
constructor ( IR ) {
2023-10-27 13:19:54 +02:00
super ( ) ;
2024-06-01 11:00:27 +01:00
this . _coords = IR [ 2 ] ;
this . _colors = IR [ 3 ] ;
this . _figures = IR [ 4 ] ;
this . _bounds = IR [ 5 ] ;
this . _bbox = IR [ 7 ] ;
this . _background = IR [ 8 ] ;
this . matrix = null ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
_createMeshCanvas ( combinedScale , backgroundColor , cachedCanvases ) {
const EXPECTED _SCALE = 1.1 ;
const MAX _PATTERN _SIZE = 3000 ;
const BORDER _SIZE = 2 ;
const offsetX = Math . floor ( this . _bounds [ 0 ] ) ;
const offsetY = Math . floor ( this . _bounds [ 1 ] ) ;
const boundsWidth = Math . ceil ( this . _bounds [ 2 ] ) - offsetX ;
const boundsHeight = Math . ceil ( this . _bounds [ 3 ] ) - offsetY ;
const width = Math . min ( Math . ceil ( Math . abs ( boundsWidth * combinedScale [ 0 ] * EXPECTED _SCALE ) ) , MAX _PATTERN _SIZE ) ;
const height = Math . min ( Math . ceil ( Math . abs ( boundsHeight * combinedScale [ 1 ] * EXPECTED _SCALE ) ) , MAX _PATTERN _SIZE ) ;
const scaleX = boundsWidth / width ;
const scaleY = boundsHeight / height ;
const context = {
coords : this . _coords ,
colors : this . _colors ,
offsetX : - offsetX ,
offsetY : - offsetY ,
scaleX : 1 / scaleX ,
scaleY : 1 / scaleY
} ;
const paddedWidth = width + BORDER _SIZE * 2 ;
const paddedHeight = height + BORDER _SIZE * 2 ;
const tmpCanvas = cachedCanvases . getCanvas ( "mesh" , paddedWidth , paddedHeight , false ) ;
const tmpCtx = tmpCanvas . context ;
const data = tmpCtx . createImageData ( width , height ) ;
if ( backgroundColor ) {
const bytes = data . data ;
for ( let i = 0 , ii = bytes . length ; i < ii ; i += 4 ) {
bytes [ i ] = backgroundColor [ 0 ] ;
bytes [ i + 1 ] = backgroundColor [ 1 ] ;
bytes [ i + 2 ] = backgroundColor [ 2 ] ;
bytes [ i + 3 ] = 255 ;
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
for ( const figure of this . _figures ) {
drawFigure ( data , figure , context ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
tmpCtx . putImageData ( data , BORDER _SIZE , BORDER _SIZE ) ;
const canvas = tmpCanvas . canvas ;
return {
canvas ,
offsetX : offsetX - BORDER _SIZE * scaleX ,
offsetY : offsetY - BORDER _SIZE * scaleY ,
scaleX ,
scaleY
} ;
}
getPattern ( ctx , owner , inverse , pathType ) {
applyBoundingBox ( ctx , this . _bbox ) ;
let scale ;
if ( pathType === PathType . SHADING ) {
scale = Util . singularValueDecompose2dScale ( getCurrentTransform ( ctx ) ) ;
} else {
scale = Util . singularValueDecompose2dScale ( owner . baseTransform ) ;
if ( this . matrix ) {
const matrixScale = Util . singularValueDecompose2dScale ( this . matrix ) ;
scale = [ scale [ 0 ] * matrixScale [ 0 ] , scale [ 1 ] * matrixScale [ 1 ] ] ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
}
const temporaryPatternCanvas = this . _createMeshCanvas ( scale , pathType === PathType . SHADING ? null : this . _background , owner . cachedCanvases ) ;
if ( pathType !== PathType . SHADING ) {
ctx . setTransform ( ... owner . baseTransform ) ;
if ( this . matrix ) {
ctx . transform ( ... this . matrix ) ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
}
ctx . translate ( temporaryPatternCanvas . offsetX , temporaryPatternCanvas . offsetY ) ;
ctx . scale ( temporaryPatternCanvas . scaleX , temporaryPatternCanvas . scaleY ) ;
return ctx . createPattern ( temporaryPatternCanvas . canvas , "no-repeat" ) ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
class DummyShadingPattern extends BaseShadingPattern {
getPattern ( ) {
return "hotpink" ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
function getShadingPattern ( IR ) {
switch ( IR [ 0 ] ) {
case "RadialAxial" :
return new RadialAxialShadingPattern ( IR ) ;
case "Mesh" :
return new MeshShadingPattern ( IR ) ;
case "Dummy" :
return new DummyShadingPattern ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
throw new Error ( ` Unknown IR type: ${ IR [ 0 ] } ` ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
const PaintType = {
COLORED : 1 ,
UNCOLORED : 2
} ;
class TilingPattern {
static MAX _PATTERN _SIZE = 3000 ;
constructor ( IR , color , ctx , canvasGraphicsFactory , baseTransform ) {
this . operatorList = IR [ 2 ] ;
this . matrix = IR [ 3 ] ;
this . bbox = IR [ 4 ] ;
this . xstep = IR [ 5 ] ;
this . ystep = IR [ 6 ] ;
this . paintType = IR [ 7 ] ;
this . tilingType = IR [ 8 ] ;
this . color = color ;
this . ctx = ctx ;
this . canvasGraphicsFactory = canvasGraphicsFactory ;
this . baseTransform = baseTransform ;
}
createPatternCanvas ( owner ) {
const operatorList = this . operatorList ;
const bbox = this . bbox ;
const xstep = this . xstep ;
const ystep = this . ystep ;
const paintType = this . paintType ;
const tilingType = this . tilingType ;
const color = this . color ;
const canvasGraphicsFactory = this . canvasGraphicsFactory ;
info ( "TilingType: " + tilingType ) ;
const x0 = bbox [ 0 ] ,
y0 = bbox [ 1 ] ,
x1 = bbox [ 2 ] ,
y1 = bbox [ 3 ] ;
const matrixScale = Util . singularValueDecompose2dScale ( this . matrix ) ;
const curMatrixScale = Util . singularValueDecompose2dScale ( this . baseTransform ) ;
const combinedScale = [ matrixScale [ 0 ] * curMatrixScale [ 0 ] , matrixScale [ 1 ] * curMatrixScale [ 1 ] ] ;
const dimx = this . getSizeAndScale ( xstep , this . ctx . canvas . width , combinedScale [ 0 ] ) ;
const dimy = this . getSizeAndScale ( ystep , this . ctx . canvas . height , combinedScale [ 1 ] ) ;
const tmpCanvas = owner . cachedCanvases . getCanvas ( "pattern" , dimx . size , dimy . size , true ) ;
const tmpCtx = tmpCanvas . context ;
const graphics = canvasGraphicsFactory . createCanvasGraphics ( tmpCtx ) ;
graphics . groupLevel = owner . groupLevel ;
this . setFillAndStrokeStyleToContext ( graphics , paintType , color ) ;
let adjustedX0 = x0 ;
let adjustedY0 = y0 ;
let adjustedX1 = x1 ;
let adjustedY1 = y1 ;
if ( x0 < 0 ) {
adjustedX0 = 0 ;
adjustedX1 += Math . abs ( x0 ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
if ( y0 < 0 ) {
adjustedY0 = 0 ;
adjustedY1 += Math . abs ( y0 ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
tmpCtx . translate ( - ( dimx . scale * adjustedX0 ) , - ( dimy . scale * adjustedY0 ) ) ;
graphics . transform ( dimx . scale , 0 , 0 , dimy . scale , 0 , 0 ) ;
tmpCtx . save ( ) ;
this . clipBbox ( graphics , adjustedX0 , adjustedY0 , adjustedX1 , adjustedY1 ) ;
graphics . baseTransform = getCurrentTransform ( graphics . ctx ) ;
graphics . executeOperatorList ( operatorList ) ;
graphics . endDrawing ( ) ;
return {
canvas : tmpCanvas . canvas ,
scaleX : dimx . scale ,
scaleY : dimy . scale ,
offsetX : adjustedX0 ,
offsetY : adjustedY0
} ;
}
getSizeAndScale ( step , realOutputSize , scale ) {
step = Math . abs ( step ) ;
const maxSize = Math . max ( TilingPattern . MAX _PATTERN _SIZE , realOutputSize ) ;
let size = Math . ceil ( step * scale ) ;
if ( size >= maxSize ) {
size = maxSize ;
2023-10-27 13:19:54 +02:00
} else {
2024-06-01 11:00:27 +01:00
scale = size / step ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
return {
2023-10-27 13:19:54 +02:00
scale ,
2024-06-01 11:00:27 +01:00
size
} ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
clipBbox ( graphics , x0 , y0 , x1 , y1 ) {
const bboxWidth = x1 - x0 ;
const bboxHeight = y1 - y0 ;
graphics . ctx . rect ( x0 , y0 , bboxWidth , bboxHeight ) ;
graphics . current . updateRectMinMax ( getCurrentTransform ( graphics . ctx ) , [ x0 , y0 , x1 , y1 ] ) ;
graphics . clip ( ) ;
graphics . endPath ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
setFillAndStrokeStyleToContext ( graphics , paintType , color ) {
const context = graphics . ctx ,
current = graphics . current ;
switch ( paintType ) {
case PaintType . COLORED :
const ctx = this . ctx ;
context . fillStyle = ctx . fillStyle ;
context . strokeStyle = ctx . strokeStyle ;
current . fillColor = ctx . fillStyle ;
current . strokeColor = ctx . strokeStyle ;
break ;
case PaintType . UNCOLORED :
const cssColor = Util . makeHexColor ( color [ 0 ] , color [ 1 ] , color [ 2 ] ) ;
context . fillStyle = cssColor ;
context . strokeStyle = cssColor ;
current . fillColor = cssColor ;
current . strokeColor = cssColor ;
break ;
default :
throw new FormatError ( ` Unsupported paint type: ${ paintType } ` ) ;
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
getPattern ( ctx , owner , inverse , pathType ) {
let matrix = inverse ;
if ( pathType !== PathType . SHADING ) {
matrix = Util . transform ( matrix , owner . baseTransform ) ;
if ( this . matrix ) {
matrix = Util . transform ( matrix , this . matrix ) ;
}
}
const temporaryPatternCanvas = this . createPatternCanvas ( owner ) ;
let domMatrix = new DOMMatrix ( matrix ) ;
domMatrix = domMatrix . translate ( temporaryPatternCanvas . offsetX , temporaryPatternCanvas . offsetY ) ;
domMatrix = domMatrix . scale ( 1 / temporaryPatternCanvas . scaleX , 1 / temporaryPatternCanvas . scaleY ) ;
const pattern = ctx . createPattern ( temporaryPatternCanvas . canvas , "repeat" ) ;
pattern . setTransform ( domMatrix ) ;
return pattern ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
; // CONCATENATED MODULE: ./src/shared/image_utils.js
2024-06-18 20:06:52 +02:00
2024-06-01 11:00:27 +01:00
function convertToRGBA ( params ) {
switch ( params . kind ) {
case ImageKind . GRAYSCALE _1BPP :
return convertBlackAndWhiteToRGBA ( params ) ;
case ImageKind . RGB _24BPP :
return convertRGBToRGBA ( params ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
return null ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
function convertBlackAndWhiteToRGBA ( {
src ,
srcPos = 0 ,
dest ,
width ,
height ,
nonBlackColor = 0xffffffff ,
inverseDecode = false
} ) {
const black = util _FeatureTest . isLittleEndian ? 0xff000000 : 0x000000ff ;
const [ zeroMapping , oneMapping ] = inverseDecode ? [ nonBlackColor , black ] : [ black , nonBlackColor ] ;
const widthInSource = width >> 3 ;
const widthRemainder = width & 7 ;
const srcLength = src . length ;
dest = new Uint32Array ( dest . buffer ) ;
let destPos = 0 ;
for ( let i = 0 ; i < height ; i ++ ) {
for ( const max = srcPos + widthInSource ; srcPos < max ; srcPos ++ ) {
const elem = srcPos < srcLength ? src [ srcPos ] : 255 ;
dest [ destPos ++ ] = elem & 0b10000000 ? oneMapping : zeroMapping ;
dest [ destPos ++ ] = elem & 0b1000000 ? oneMapping : zeroMapping ;
dest [ destPos ++ ] = elem & 0b100000 ? oneMapping : zeroMapping ;
dest [ destPos ++ ] = elem & 0b10000 ? oneMapping : zeroMapping ;
dest [ destPos ++ ] = elem & 0b1000 ? oneMapping : zeroMapping ;
dest [ destPos ++ ] = elem & 0b100 ? oneMapping : zeroMapping ;
dest [ destPos ++ ] = elem & 0b10 ? oneMapping : zeroMapping ;
dest [ destPos ++ ] = elem & 0b1 ? oneMapping : zeroMapping ;
}
if ( widthRemainder === 0 ) {
continue ;
}
const elem = srcPos < srcLength ? src [ srcPos ++ ] : 255 ;
for ( let j = 0 ; j < widthRemainder ; j ++ ) {
dest [ destPos ++ ] = elem & 1 << 7 - j ? oneMapping : zeroMapping ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
return {
srcPos ,
destPos
} ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
function convertRGBToRGBA ( {
src ,
srcPos = 0 ,
dest ,
destPos = 0 ,
width ,
height
} ) {
let i = 0 ;
const len32 = src . length >> 2 ;
const src32 = new Uint32Array ( src . buffer , srcPos , len32 ) ;
if ( FeatureTest . isLittleEndian ) {
for ( ; i < len32 - 2 ; i += 3 , destPos += 4 ) {
const s1 = src32 [ i ] ;
const s2 = src32 [ i + 1 ] ;
const s3 = src32 [ i + 2 ] ;
dest [ destPos ] = s1 | 0xff000000 ;
dest [ destPos + 1 ] = s1 >>> 24 | s2 << 8 | 0xff000000 ;
dest [ destPos + 2 ] = s2 >>> 16 | s3 << 16 | 0xff000000 ;
dest [ destPos + 3 ] = s3 >>> 8 | 0xff000000 ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
for ( let j = i * 4 , jj = src . length ; j < jj ; j += 3 ) {
dest [ destPos ++ ] = src [ j ] | src [ j + 1 ] << 8 | src [ j + 2 ] << 16 | 0xff000000 ;
}
} else {
for ( ; i < len32 - 2 ; i += 3 , destPos += 4 ) {
const s1 = src32 [ i ] ;
const s2 = src32 [ i + 1 ] ;
const s3 = src32 [ i + 2 ] ;
dest [ destPos ] = s1 | 0xff ;
dest [ destPos + 1 ] = s1 << 24 | s2 >>> 8 | 0xff ;
dest [ destPos + 2 ] = s2 << 16 | s3 >>> 16 | 0xff ;
dest [ destPos + 3 ] = s3 << 8 | 0xff ;
}
for ( let j = i * 4 , jj = src . length ; j < jj ; j += 3 ) {
dest [ destPos ++ ] = src [ j ] << 24 | src [ j + 1 ] << 16 | src [ j + 2 ] << 8 | 0xff ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
return {
srcPos ,
destPos
} ;
}
function grayToRGBA ( src , dest ) {
if ( FeatureTest . isLittleEndian ) {
for ( let i = 0 , ii = src . length ; i < ii ; i ++ ) {
dest [ i ] = src [ i ] * 0x10101 | 0xff000000 ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
} else {
for ( let i = 0 , ii = src . length ; i < ii ; i ++ ) {
dest [ i ] = src [ i ] * 0x1010100 | 0x000000ff ;
2023-10-27 13:19:54 +02:00
}
}
}
2024-06-01 11:00:27 +01:00
; // CONCATENATED MODULE: ./src/display/canvas.js
2024-06-18 20:06:52 +02:00
2024-06-01 11:00:27 +01:00
const MIN _FONT _SIZE = 16 ;
const MAX _FONT _SIZE = 100 ;
const EXECUTION _TIME = 15 ;
const EXECUTION _STEPS = 10 ;
const MAX _SIZE _TO _COMPILE = 1000 ;
const FULL _CHUNK _HEIGHT = 16 ;
function mirrorContextOperations ( ctx , destCtx ) {
if ( ctx . _removeMirroring ) {
throw new Error ( "Context is already forwarding operations." ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
ctx . _ _originalSave = ctx . save ;
ctx . _ _originalRestore = ctx . restore ;
ctx . _ _originalRotate = ctx . rotate ;
ctx . _ _originalScale = ctx . scale ;
ctx . _ _originalTranslate = ctx . translate ;
ctx . _ _originalTransform = ctx . transform ;
ctx . _ _originalSetTransform = ctx . setTransform ;
ctx . _ _originalResetTransform = ctx . resetTransform ;
ctx . _ _originalClip = ctx . clip ;
ctx . _ _originalMoveTo = ctx . moveTo ;
ctx . _ _originalLineTo = ctx . lineTo ;
ctx . _ _originalBezierCurveTo = ctx . bezierCurveTo ;
ctx . _ _originalRect = ctx . rect ;
ctx . _ _originalClosePath = ctx . closePath ;
ctx . _ _originalBeginPath = ctx . beginPath ;
ctx . _removeMirroring = ( ) => {
ctx . save = ctx . _ _originalSave ;
ctx . restore = ctx . _ _originalRestore ;
ctx . rotate = ctx . _ _originalRotate ;
ctx . scale = ctx . _ _originalScale ;
ctx . translate = ctx . _ _originalTranslate ;
ctx . transform = ctx . _ _originalTransform ;
ctx . setTransform = ctx . _ _originalSetTransform ;
ctx . resetTransform = ctx . _ _originalResetTransform ;
ctx . clip = ctx . _ _originalClip ;
ctx . moveTo = ctx . _ _originalMoveTo ;
ctx . lineTo = ctx . _ _originalLineTo ;
ctx . bezierCurveTo = ctx . _ _originalBezierCurveTo ;
ctx . rect = ctx . _ _originalRect ;
ctx . closePath = ctx . _ _originalClosePath ;
ctx . beginPath = ctx . _ _originalBeginPath ;
delete ctx . _removeMirroring ;
} ;
ctx . save = function ctxSave ( ) {
destCtx . save ( ) ;
this . _ _originalSave ( ) ;
} ;
ctx . restore = function ctxRestore ( ) {
destCtx . restore ( ) ;
this . _ _originalRestore ( ) ;
} ;
ctx . translate = function ctxTranslate ( x , y ) {
destCtx . translate ( x , y ) ;
this . _ _originalTranslate ( x , y ) ;
} ;
ctx . scale = function ctxScale ( x , y ) {
destCtx . scale ( x , y ) ;
this . _ _originalScale ( x , y ) ;
} ;
ctx . transform = function ctxTransform ( a , b , c , d , e , f ) {
destCtx . transform ( a , b , c , d , e , f ) ;
this . _ _originalTransform ( a , b , c , d , e , f ) ;
} ;
ctx . setTransform = function ctxSetTransform ( a , b , c , d , e , f ) {
destCtx . setTransform ( a , b , c , d , e , f ) ;
this . _ _originalSetTransform ( a , b , c , d , e , f ) ;
} ;
ctx . resetTransform = function ctxResetTransform ( ) {
destCtx . resetTransform ( ) ;
this . _ _originalResetTransform ( ) ;
} ;
ctx . rotate = function ctxRotate ( angle ) {
destCtx . rotate ( angle ) ;
this . _ _originalRotate ( angle ) ;
} ;
ctx . clip = function ctxRotate ( rule ) {
destCtx . clip ( rule ) ;
this . _ _originalClip ( rule ) ;
} ;
ctx . moveTo = function ( x , y ) {
destCtx . moveTo ( x , y ) ;
this . _ _originalMoveTo ( x , y ) ;
} ;
ctx . lineTo = function ( x , y ) {
destCtx . lineTo ( x , y ) ;
this . _ _originalLineTo ( x , y ) ;
} ;
ctx . bezierCurveTo = function ( cp1x , cp1y , cp2x , cp2y , x , y ) {
destCtx . bezierCurveTo ( cp1x , cp1y , cp2x , cp2y , x , y ) ;
this . _ _originalBezierCurveTo ( cp1x , cp1y , cp2x , cp2y , x , y ) ;
} ;
ctx . rect = function ( x , y , width , height ) {
destCtx . rect ( x , y , width , height ) ;
this . _ _originalRect ( x , y , width , height ) ;
} ;
ctx . closePath = function ( ) {
destCtx . closePath ( ) ;
this . _ _originalClosePath ( ) ;
} ;
ctx . beginPath = function ( ) {
destCtx . beginPath ( ) ;
this . _ _originalBeginPath ( ) ;
} ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
class CachedCanvases {
constructor ( canvasFactory ) {
this . canvasFactory = canvasFactory ;
this . cache = Object . create ( null ) ;
}
getCanvas ( id , width , height ) {
let canvasEntry ;
if ( this . cache [ id ] !== undefined ) {
canvasEntry = this . cache [ id ] ;
this . canvasFactory . reset ( canvasEntry , width , height ) ;
} else {
canvasEntry = this . canvasFactory . create ( width , height ) ;
this . cache [ id ] = canvasEntry ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
return canvasEntry ;
}
delete ( id ) {
delete this . cache [ id ] ;
}
clear ( ) {
for ( const id in this . cache ) {
const canvasEntry = this . cache [ id ] ;
this . canvasFactory . destroy ( canvasEntry ) ;
delete this . cache [ id ] ;
2023-10-27 13:19:54 +02:00
}
}
}
2024-06-01 11:00:27 +01:00
function drawImageAtIntegerCoords ( ctx , srcImg , srcX , srcY , srcW , srcH , destX , destY , destW , destH ) {
const [ a , b , c , d , tx , ty ] = getCurrentTransform ( ctx ) ;
if ( b === 0 && c === 0 ) {
const tlX = destX * a + tx ;
const rTlX = Math . round ( tlX ) ;
const tlY = destY * d + ty ;
const rTlY = Math . round ( tlY ) ;
const brX = ( destX + destW ) * a + tx ;
const rWidth = Math . abs ( Math . round ( brX ) - rTlX ) || 1 ;
const brY = ( destY + destH ) * d + ty ;
const rHeight = Math . abs ( Math . round ( brY ) - rTlY ) || 1 ;
ctx . setTransform ( Math . sign ( a ) , 0 , 0 , Math . sign ( d ) , rTlX , rTlY ) ;
ctx . drawImage ( srcImg , srcX , srcY , srcW , srcH , 0 , 0 , rWidth , rHeight ) ;
ctx . setTransform ( a , b , c , d , tx , ty ) ;
return [ rWidth , rHeight ] ;
}
if ( a === 0 && d === 0 ) {
const tlX = destY * c + tx ;
const rTlX = Math . round ( tlX ) ;
const tlY = destX * b + ty ;
const rTlY = Math . round ( tlY ) ;
const brX = ( destY + destH ) * c + tx ;
const rWidth = Math . abs ( Math . round ( brX ) - rTlX ) || 1 ;
const brY = ( destX + destW ) * b + ty ;
const rHeight = Math . abs ( Math . round ( brY ) - rTlY ) || 1 ;
ctx . setTransform ( 0 , Math . sign ( b ) , Math . sign ( c ) , 0 , rTlX , rTlY ) ;
ctx . drawImage ( srcImg , srcX , srcY , srcW , srcH , 0 , 0 , rHeight , rWidth ) ;
ctx . setTransform ( a , b , c , d , tx , ty ) ;
return [ rHeight , rWidth ] ;
}
ctx . drawImage ( srcImg , srcX , srcY , srcW , srcH , destX , destY , destW , destH ) ;
const scaleX = Math . hypot ( a , b ) ;
const scaleY = Math . hypot ( c , d ) ;
return [ scaleX * destW , scaleY * destH ] ;
}
function compileType3Glyph ( imgData ) {
2023-10-27 13:19:54 +02:00
const {
width ,
height
2024-06-01 11:00:27 +01:00
} = imgData ;
if ( width > MAX _SIZE _TO _COMPILE || height > MAX _SIZE _TO _COMPILE ) {
return null ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
const POINT _TO _PROCESS _LIMIT = 1000 ;
const POINT _TYPES = new Uint8Array ( [ 0 , 2 , 4 , 0 , 1 , 0 , 5 , 4 , 8 , 10 , 0 , 8 , 0 , 2 , 1 , 0 ] ) ;
const width1 = width + 1 ;
let points = new Uint8Array ( width1 * ( height + 1 ) ) ;
let i , j , j0 ;
const lineSize = width + 7 & ~ 7 ;
let data = new Uint8Array ( lineSize * height ) ,
pos = 0 ;
for ( const elem of imgData . data ) {
let mask = 128 ;
while ( mask > 0 ) {
data [ pos ++ ] = elem & mask ? 0 : 255 ;
mask >>= 1 ;
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
let count = 0 ;
pos = 0 ;
if ( data [ pos ] !== 0 ) {
points [ 0 ] = 1 ;
++ count ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
for ( j = 1 ; j < width ; j ++ ) {
if ( data [ pos ] !== data [ pos + 1 ] ) {
points [ j ] = data [ pos ] ? 2 : 1 ;
++ count ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
pos ++ ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
if ( data [ pos ] !== 0 ) {
points [ j ] = 2 ;
++ count ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
for ( i = 1 ; i < height ; i ++ ) {
pos = i * lineSize ;
j0 = i * width1 ;
if ( data [ pos - lineSize ] !== data [ pos ] ) {
points [ j0 ] = data [ pos ] ? 1 : 8 ;
++ count ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
let sum = ( data [ pos ] ? 4 : 0 ) + ( data [ pos - lineSize ] ? 8 : 0 ) ;
for ( j = 1 ; j < width ; j ++ ) {
sum = ( sum >> 2 ) + ( data [ pos + 1 ] ? 4 : 0 ) + ( data [ pos - lineSize + 1 ] ? 8 : 0 ) ;
if ( POINT _TYPES [ sum ] ) {
points [ j0 + j ] = POINT _TYPES [ sum ] ;
++ count ;
}
pos ++ ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
if ( data [ pos - lineSize ] !== data [ pos ] ) {
points [ j0 + j ] = data [ pos ] ? 2 : 4 ;
++ count ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
if ( count > POINT _TO _PROCESS _LIMIT ) {
return null ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
pos = lineSize * ( height - 1 ) ;
j0 = i * width1 ;
if ( data [ pos ] !== 0 ) {
points [ j0 ] = 8 ;
++ count ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
for ( j = 1 ; j < width ; j ++ ) {
if ( data [ pos ] !== data [ pos + 1 ] ) {
points [ j0 + j ] = data [ pos ] ? 4 : 8 ;
++ count ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
pos ++ ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
if ( data [ pos ] !== 0 ) {
points [ j0 + j ] = 4 ;
++ count ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
if ( count > POINT _TO _PROCESS _LIMIT ) {
return null ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
const steps = new Int32Array ( [ 0 , width1 , - 1 , 0 , - width1 , 0 , 0 , 0 , 1 ] ) ;
const path = new Path2D ( ) ;
for ( i = 0 ; count && i <= height ; i ++ ) {
let p = i * width1 ;
const end = p + width ;
while ( p < end && ! points [ p ] ) {
p ++ ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
if ( p === end ) {
continue ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
path . moveTo ( p % width1 , i ) ;
const p0 = p ;
let type = points [ p ] ;
do {
const step = steps [ type ] ;
do {
p += step ;
} while ( ! points [ p ] ) ;
const pp = points [ p ] ;
if ( pp !== 5 && pp !== 10 ) {
type = pp ;
points [ p ] = 0 ;
} else {
type = pp & 0x33 * type >> 4 ;
points [ p ] &= type >> 2 | type << 2 ;
}
path . lineTo ( p % width1 , p / width1 | 0 ) ;
if ( ! points [ p ] ) {
-- count ;
}
} while ( p0 !== p ) ;
-- i ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
data = null ;
points = null ;
const drawOutline = function ( c ) {
c . save ( ) ;
c . scale ( 1 / width , - 1 / height ) ;
c . translate ( 0 , - height ) ;
c . fill ( path ) ;
c . beginPath ( ) ;
c . restore ( ) ;
} ;
return drawOutline ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
class CanvasExtraState {
constructor ( width , height ) {
this . alphaIsShape = false ;
this . fontSize = 0 ;
this . fontSizeScale = 1 ;
this . textMatrix = IDENTITY _MATRIX ;
this . textMatrixScale = 1 ;
this . fontMatrix = FONT _IDENTITY _MATRIX ;
this . leading = 0 ;
this . x = 0 ;
this . y = 0 ;
this . lineX = 0 ;
this . lineY = 0 ;
this . charSpacing = 0 ;
this . wordSpacing = 0 ;
this . textHScale = 1 ;
this . textRenderingMode = TextRenderingMode . FILL ;
this . textRise = 0 ;
this . fillColor = "#000000" ;
this . strokeColor = "#000000" ;
this . patternFill = false ;
this . fillAlpha = 1 ;
this . strokeAlpha = 1 ;
this . lineWidth = 1 ;
this . activeSMask = null ;
this . transferMaps = "none" ;
this . startNewPathAndClipBox ( [ 0 , 0 , width , height ] ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
clone ( ) {
const clone = Object . create ( this ) ;
clone . clipBox = this . clipBox . slice ( ) ;
return clone ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
setCurrentPoint ( x , y ) {
this . x = x ;
this . y = y ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
updatePathMinMax ( transform , x , y ) {
[ x , y ] = Util . applyTransform ( [ x , y ] , transform ) ;
this . minX = Math . min ( this . minX , x ) ;
this . minY = Math . min ( this . minY , y ) ;
this . maxX = Math . max ( this . maxX , x ) ;
this . maxY = Math . max ( this . maxY , y ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
updateRectMinMax ( transform , rect ) {
const p1 = Util . applyTransform ( rect , transform ) ;
const p2 = Util . applyTransform ( rect . slice ( 2 ) , transform ) ;
const p3 = Util . applyTransform ( [ rect [ 0 ] , rect [ 3 ] ] , transform ) ;
const p4 = Util . applyTransform ( [ rect [ 2 ] , rect [ 1 ] ] , transform ) ;
this . minX = Math . min ( this . minX , p1 [ 0 ] , p2 [ 0 ] , p3 [ 0 ] , p4 [ 0 ] ) ;
this . minY = Math . min ( this . minY , p1 [ 1 ] , p2 [ 1 ] , p3 [ 1 ] , p4 [ 1 ] ) ;
this . maxX = Math . max ( this . maxX , p1 [ 0 ] , p2 [ 0 ] , p3 [ 0 ] , p4 [ 0 ] ) ;
this . maxY = Math . max ( this . maxY , p1 [ 1 ] , p2 [ 1 ] , p3 [ 1 ] , p4 [ 1 ] ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
updateScalingPathMinMax ( transform , minMax ) {
Util . scaleMinMax ( transform , minMax ) ;
this . minX = Math . min ( this . minX , minMax [ 0 ] ) ;
this . minY = Math . min ( this . minY , minMax [ 1 ] ) ;
this . maxX = Math . max ( this . maxX , minMax [ 2 ] ) ;
this . maxY = Math . max ( this . maxY , minMax [ 3 ] ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
updateCurvePathMinMax ( transform , x0 , y0 , x1 , y1 , x2 , y2 , x3 , y3 , minMax ) {
const box = Util . bezierBoundingBox ( x0 , y0 , x1 , y1 , x2 , y2 , x3 , y3 , minMax ) ;
if ( minMax ) {
2023-10-27 13:19:54 +02:00
return ;
}
2024-06-01 11:00:27 +01:00
this . updateRectMinMax ( transform , box ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
getPathBoundingBox ( pathType = PathType . FILL , transform = null ) {
const box = [ this . minX , this . minY , this . maxX , this . maxY ] ;
if ( pathType === PathType . STROKE ) {
if ( ! transform ) {
unreachable ( "Stroke bounding box must include transform." ) ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
const scale = Util . singularValueDecompose2dScale ( transform ) ;
const xStrokePad = scale [ 0 ] * this . lineWidth / 2 ;
const yStrokePad = scale [ 1 ] * this . lineWidth / 2 ;
box [ 0 ] -= xStrokePad ;
box [ 1 ] -= yStrokePad ;
box [ 2 ] += xStrokePad ;
box [ 3 ] += yStrokePad ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
return box ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
updateClipFromPath ( ) {
const intersect = Util . intersect ( this . clipBox , this . getPathBoundingBox ( ) ) ;
this . startNewPathAndClipBox ( intersect || [ 0 , 0 , 0 , 0 ] ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
isEmptyClip ( ) {
return this . minX === Infinity ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
startNewPathAndClipBox ( box ) {
this . clipBox = box ;
this . minX = Infinity ;
this . minY = Infinity ;
this . maxX = 0 ;
this . maxY = 0 ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
getClippedPathBoundingBox ( pathType = PathType . FILL , transform = null ) {
return Util . intersect ( this . clipBox , this . getPathBoundingBox ( pathType , transform ) ) ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
}
function putBinaryImageData ( ctx , imgData ) {
if ( typeof ImageData !== "undefined" && imgData instanceof ImageData ) {
ctx . putImageData ( imgData , 0 , 0 ) ;
return ;
}
const height = imgData . height ,
width = imgData . width ;
const partialChunkHeight = height % FULL _CHUNK _HEIGHT ;
const fullChunks = ( height - partialChunkHeight ) / FULL _CHUNK _HEIGHT ;
const totalChunks = partialChunkHeight === 0 ? fullChunks : fullChunks + 1 ;
const chunkImgData = ctx . createImageData ( width , FULL _CHUNK _HEIGHT ) ;
let srcPos = 0 ,
destPos ;
const src = imgData . data ;
const dest = chunkImgData . data ;
let i , j , thisChunkHeight , elemsInThisChunk ;
if ( imgData . kind === util _ImageKind . GRAYSCALE _1BPP ) {
const srcLength = src . byteLength ;
const dest32 = new Uint32Array ( dest . buffer , 0 , dest . byteLength >> 2 ) ;
const dest32DataLength = dest32 . length ;
const fullSrcDiff = width + 7 >> 3 ;
const white = 0xffffffff ;
const black = util _FeatureTest . isLittleEndian ? 0xff000000 : 0x000000ff ;
for ( i = 0 ; i < totalChunks ; i ++ ) {
thisChunkHeight = i < fullChunks ? FULL _CHUNK _HEIGHT : partialChunkHeight ;
destPos = 0 ;
for ( j = 0 ; j < thisChunkHeight ; j ++ ) {
const srcDiff = srcLength - srcPos ;
let k = 0 ;
const kEnd = srcDiff > fullSrcDiff ? width : srcDiff * 8 - 7 ;
const kEndUnrolled = kEnd & ~ 7 ;
let mask = 0 ;
let srcByte = 0 ;
for ( ; k < kEndUnrolled ; k += 8 ) {
srcByte = src [ srcPos ++ ] ;
dest32 [ destPos ++ ] = srcByte & 128 ? white : black ;
dest32 [ destPos ++ ] = srcByte & 64 ? white : black ;
dest32 [ destPos ++ ] = srcByte & 32 ? white : black ;
dest32 [ destPos ++ ] = srcByte & 16 ? white : black ;
dest32 [ destPos ++ ] = srcByte & 8 ? white : black ;
dest32 [ destPos ++ ] = srcByte & 4 ? white : black ;
dest32 [ destPos ++ ] = srcByte & 2 ? white : black ;
dest32 [ destPos ++ ] = srcByte & 1 ? white : black ;
}
for ( ; k < kEnd ; k ++ ) {
if ( mask === 0 ) {
srcByte = src [ srcPos ++ ] ;
mask = 128 ;
}
dest32 [ destPos ++ ] = srcByte & mask ? white : black ;
mask >>= 1 ;
}
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
while ( destPos < dest32DataLength ) {
dest32 [ destPos ++ ] = 0 ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
ctx . putImageData ( chunkImgData , 0 , i * FULL _CHUNK _HEIGHT ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
} else if ( imgData . kind === util _ImageKind . RGBA _32BPP ) {
j = 0 ;
elemsInThisChunk = width * FULL _CHUNK _HEIGHT * 4 ;
for ( i = 0 ; i < fullChunks ; i ++ ) {
dest . set ( src . subarray ( srcPos , srcPos + elemsInThisChunk ) ) ;
srcPos += elemsInThisChunk ;
ctx . putImageData ( chunkImgData , 0 , j ) ;
j += FULL _CHUNK _HEIGHT ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
if ( i < totalChunks ) {
elemsInThisChunk = width * partialChunkHeight * 4 ;
dest . set ( src . subarray ( srcPos , srcPos + elemsInThisChunk ) ) ;
ctx . putImageData ( chunkImgData , 0 , j ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
} else if ( imgData . kind === util _ImageKind . RGB _24BPP ) {
thisChunkHeight = FULL _CHUNK _HEIGHT ;
elemsInThisChunk = width * thisChunkHeight ;
for ( i = 0 ; i < totalChunks ; i ++ ) {
if ( i >= fullChunks ) {
thisChunkHeight = partialChunkHeight ;
elemsInThisChunk = width * thisChunkHeight ;
}
destPos = 0 ;
for ( j = elemsInThisChunk ; j -- ; ) {
dest [ destPos ++ ] = src [ srcPos ++ ] ;
dest [ destPos ++ ] = src [ srcPos ++ ] ;
dest [ destPos ++ ] = src [ srcPos ++ ] ;
dest [ destPos ++ ] = 255 ;
}
ctx . putImageData ( chunkImgData , 0 , i * FULL _CHUNK _HEIGHT ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
} else {
throw new Error ( ` bad image kind: ${ imgData . kind } ` ) ;
2023-10-27 13:19:54 +02:00
}
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
function putBinaryImageMask ( ctx , imgData ) {
if ( imgData . bitmap ) {
ctx . drawImage ( imgData . bitmap , 0 , 0 ) ;
return ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
const height = imgData . height ,
width = imgData . width ;
const partialChunkHeight = height % FULL _CHUNK _HEIGHT ;
const fullChunks = ( height - partialChunkHeight ) / FULL _CHUNK _HEIGHT ;
const totalChunks = partialChunkHeight === 0 ? fullChunks : fullChunks + 1 ;
const chunkImgData = ctx . createImageData ( width , FULL _CHUNK _HEIGHT ) ;
let srcPos = 0 ;
const src = imgData . data ;
const dest = chunkImgData . data ;
for ( let i = 0 ; i < totalChunks ; i ++ ) {
const thisChunkHeight = i < fullChunks ? FULL _CHUNK _HEIGHT : partialChunkHeight ;
( {
srcPos
} = convertBlackAndWhiteToRGBA ( {
src ,
srcPos ,
dest ,
width ,
height : thisChunkHeight ,
nonBlackColor : 0
} ) ) ;
ctx . putImageData ( chunkImgData , 0 , i * FULL _CHUNK _HEIGHT ) ;
2014-11-24 00:56:52 +01:00
}
2024-06-01 11:00:27 +01:00
}
function copyCtxState ( sourceCtx , destCtx ) {
const properties = [ "strokeStyle" , "fillStyle" , "fillRule" , "globalAlpha" , "lineWidth" , "lineCap" , "lineJoin" , "miterLimit" , "globalCompositeOperation" , "font" , "filter" ] ;
for ( const property of properties ) {
if ( sourceCtx [ property ] !== undefined ) {
destCtx [ property ] = sourceCtx [ property ] ;
2023-10-27 13:19:54 +02:00
}
2014-11-24 00:56:52 +01:00
}
2024-06-01 11:00:27 +01:00
if ( sourceCtx . setLineDash !== undefined ) {
destCtx . setLineDash ( sourceCtx . getLineDash ( ) ) ;
destCtx . lineDashOffset = sourceCtx . lineDashOffset ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
function resetCtxToDefault ( ctx ) {
ctx . strokeStyle = ctx . fillStyle = "#000000" ;
ctx . fillRule = "nonzero" ;
ctx . globalAlpha = 1 ;
ctx . lineWidth = 1 ;
ctx . lineCap = "butt" ;
ctx . lineJoin = "miter" ;
ctx . miterLimit = 10 ;
ctx . globalCompositeOperation = "source-over" ;
ctx . font = "10px sans-serif" ;
if ( ctx . setLineDash !== undefined ) {
ctx . setLineDash ( [ ] ) ;
ctx . lineDashOffset = 0 ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
if ( ! isNodeJS ) {
const {
filter
} = ctx ;
if ( filter !== "none" && filter !== "" ) {
ctx . filter = "none" ;
}
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
function getImageSmoothingEnabled ( transform , interpolate ) {
if ( interpolate ) {
return true ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
const scale = Util . singularValueDecompose2dScale ( transform ) ;
scale [ 0 ] = Math . fround ( scale [ 0 ] ) ;
scale [ 1 ] = Math . fround ( scale [ 1 ] ) ;
const actualScale = Math . fround ( ( globalThis . devicePixelRatio || 1 ) * PixelsPerInch . PDF _TO _CSS _UNITS ) ;
return scale [ 0 ] <= actualScale && scale [ 1 ] <= actualScale ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
const LINE _CAP _STYLES = [ "butt" , "round" , "square" ] ;
const LINE _JOIN _STYLES = [ "miter" , "round" , "bevel" ] ;
const NORMAL _CLIP = { } ;
const EO _CLIP = { } ;
class CanvasGraphics {
constructor ( canvasCtx , commonObjs , objs , canvasFactory , filterFactory , {
optionalContentConfig ,
markedContentStack = null
} , annotationCanvasMap , pageColors ) {
this . ctx = canvasCtx ;
this . current = new CanvasExtraState ( this . ctx . canvas . width , this . ctx . canvas . height ) ;
this . stateStack = [ ] ;
this . pendingClip = null ;
this . pendingEOFill = false ;
this . res = null ;
this . xobjs = null ;
this . commonObjs = commonObjs ;
this . objs = objs ;
2023-10-27 13:19:54 +02:00
this . canvasFactory = canvasFactory ;
2024-06-01 11:00:27 +01:00
this . filterFactory = filterFactory ;
this . groupStack = [ ] ;
this . processingType3 = null ;
this . baseTransform = null ;
this . baseTransformStack = [ ] ;
this . groupLevel = 0 ;
this . smaskStack = [ ] ;
this . smaskCounter = 0 ;
this . tempSMask = null ;
this . suspendedCtx = null ;
this . contentVisible = true ;
this . markedContentStack = markedContentStack || [ ] ;
this . optionalContentConfig = optionalContentConfig ;
this . cachedCanvases = new CachedCanvases ( this . canvasFactory ) ;
this . cachedPatterns = new Map ( ) ;
this . annotationCanvasMap = annotationCanvasMap ;
this . viewportScale = 1 ;
this . outputScaleX = 1 ;
this . outputScaleY = 1 ;
this . pageColors = pageColors ;
this . _cachedScaleForStroking = [ - 1 , 0 ] ;
this . _cachedGetSinglePixelWidth = null ;
this . _cachedBitmapsMap = new Map ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
getObject ( data , fallback = null ) {
if ( typeof data === "string" ) {
return data . startsWith ( "g_" ) ? this . commonObjs . get ( data ) : this . objs . get ( data ) ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
return fallback ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
beginDrawing ( {
transform ,
viewport ,
transparency = false ,
background = null
} ) {
const width = this . ctx . canvas . width ;
const height = this . ctx . canvas . height ;
const savedFillStyle = this . ctx . fillStyle ;
this . ctx . fillStyle = background || "#ffffff" ;
this . ctx . fillRect ( 0 , 0 , width , height ) ;
this . ctx . fillStyle = savedFillStyle ;
if ( transparency ) {
const transparentCanvas = this . cachedCanvases . getCanvas ( "transparent" , width , height ) ;
this . compositeCtx = this . ctx ;
this . transparentCanvas = transparentCanvas . canvas ;
this . ctx = transparentCanvas . context ;
this . ctx . save ( ) ;
this . ctx . transform ( ... getCurrentTransform ( this . compositeCtx ) ) ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
this . ctx . save ( ) ;
resetCtxToDefault ( this . ctx ) ;
if ( transform ) {
this . ctx . transform ( ... transform ) ;
this . outputScaleX = transform [ 0 ] ;
this . outputScaleY = transform [ 0 ] ;
}
this . ctx . transform ( ... viewport . transform ) ;
this . viewportScale = viewport . scale ;
this . baseTransform = getCurrentTransform ( this . ctx ) ;
2014-11-24 00:56:52 +01:00
}
2024-06-01 11:00:27 +01:00
executeOperatorList ( operatorList , executionStartIdx , continueCallback , stepper ) {
const argsArray = operatorList . argsArray ;
const fnArray = operatorList . fnArray ;
let i = executionStartIdx || 0 ;
const argsArrayLen = argsArray . length ;
if ( argsArrayLen === i ) {
return i ;
}
const chunkOperations = argsArrayLen - i > EXECUTION _STEPS && typeof continueCallback === "function" ;
const endTime = chunkOperations ? Date . now ( ) + EXECUTION _TIME : 0 ;
let steps = 0 ;
const commonObjs = this . commonObjs ;
const objs = this . objs ;
let fnId ;
while ( true ) {
if ( stepper !== undefined && i === stepper . nextBreakPoint ) {
stepper . breakIt ( i , continueCallback ) ;
return i ;
}
fnId = fnArray [ i ] ;
if ( fnId !== OPS . dependency ) {
this [ fnId ] . apply ( this , argsArray [ i ] ) ;
} else {
for ( const depObjId of argsArray [ i ] ) {
const objsPool = depObjId . startsWith ( "g_" ) ? commonObjs : objs ;
if ( ! objsPool . has ( depObjId ) ) {
objsPool . get ( depObjId , continueCallback ) ;
return i ;
}
}
}
i ++ ;
if ( i === argsArrayLen ) {
return i ;
}
if ( chunkOperations && ++ steps > EXECUTION _STEPS ) {
if ( Date . now ( ) > endTime ) {
continueCallback ( ) ;
return i ;
}
steps = 0 ;
}
2014-11-24 00:56:52 +01:00
}
}
2024-06-01 11:00:27 +01:00
# restoreInitialState ( ) {
while ( this . stateStack . length || this . inSMaskMode ) {
this . restore ( ) ;
}
this . ctx . restore ( ) ;
if ( this . transparentCanvas ) {
this . ctx = this . compositeCtx ;
this . ctx . save ( ) ;
this . ctx . setTransform ( 1 , 0 , 0 , 1 , 0 , 0 ) ;
this . ctx . drawImage ( this . transparentCanvas , 0 , 0 ) ;
this . ctx . restore ( ) ;
this . transparentCanvas = null ;
}
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
endDrawing ( ) {
this . # restoreInitialState ( ) ;
this . cachedCanvases . clear ( ) ;
this . cachedPatterns . clear ( ) ;
for ( const cache of this . _cachedBitmapsMap . values ( ) ) {
for ( const canvas of cache . values ( ) ) {
if ( typeof HTMLCanvasElement !== "undefined" && canvas instanceof HTMLCanvasElement ) {
canvas . width = canvas . height = 0 ;
}
}
cache . clear ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
this . _cachedBitmapsMap . clear ( ) ;
this . # drawFilter ( ) ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
# drawFilter ( ) {
if ( this . pageColors ) {
const hcmFilterId = this . filterFactory . addHCMFilter ( this . pageColors . foreground , this . pageColors . background ) ;
if ( hcmFilterId !== "none" ) {
const savedFilter = this . ctx . filter ;
this . ctx . filter = hcmFilterId ;
this . ctx . drawImage ( this . ctx . canvas , 0 , 0 ) ;
this . ctx . filter = savedFilter ;
}
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
_scaleImage ( img , inverseTransform ) {
const width = img . width ;
const height = img . height ;
let widthScale = Math . max ( Math . hypot ( inverseTransform [ 0 ] , inverseTransform [ 1 ] ) , 1 ) ;
let heightScale = Math . max ( Math . hypot ( inverseTransform [ 2 ] , inverseTransform [ 3 ] ) , 1 ) ;
let paintWidth = width ,
paintHeight = height ;
let tmpCanvasId = "prescale1" ;
let tmpCanvas , tmpCtx ;
while ( widthScale > 2 && paintWidth > 1 || heightScale > 2 && paintHeight > 1 ) {
let newWidth = paintWidth ,
newHeight = paintHeight ;
if ( widthScale > 2 && paintWidth > 1 ) {
newWidth = paintWidth >= 16384 ? Math . floor ( paintWidth / 2 ) - 1 || 1 : Math . ceil ( paintWidth / 2 ) ;
widthScale /= paintWidth / newWidth ;
}
if ( heightScale > 2 && paintHeight > 1 ) {
newHeight = paintHeight >= 16384 ? Math . floor ( paintHeight / 2 ) - 1 || 1 : Math . ceil ( paintHeight ) / 2 ;
heightScale /= paintHeight / newHeight ;
}
tmpCanvas = this . cachedCanvases . getCanvas ( tmpCanvasId , newWidth , newHeight ) ;
tmpCtx = tmpCanvas . context ;
tmpCtx . clearRect ( 0 , 0 , newWidth , newHeight ) ;
tmpCtx . drawImage ( img , 0 , 0 , paintWidth , paintHeight , 0 , 0 , newWidth , newHeight ) ;
img = tmpCanvas . canvas ;
paintWidth = newWidth ;
paintHeight = newHeight ;
tmpCanvasId = tmpCanvasId === "prescale1" ? "prescale2" : "prescale1" ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
return {
img ,
paintWidth ,
paintHeight
} ;
}
_createMaskCanvas ( img ) {
const ctx = this . ctx ;
const {
width ,
height
} = img ;
const fillColor = this . current . fillColor ;
const isPatternFill = this . current . patternFill ;
const currentTransform = getCurrentTransform ( ctx ) ;
let cache , cacheKey , scaled , maskCanvas ;
if ( ( img . bitmap || img . data ) && img . count > 1 ) {
const mainKey = img . bitmap || img . data . buffer ;
cacheKey = JSON . stringify ( isPatternFill ? currentTransform : [ currentTransform . slice ( 0 , 4 ) , fillColor ] ) ;
cache = this . _cachedBitmapsMap . get ( mainKey ) ;
if ( ! cache ) {
cache = new Map ( ) ;
this . _cachedBitmapsMap . set ( mainKey , cache ) ;
2014-11-24 00:56:52 +01:00
}
2024-06-01 11:00:27 +01:00
const cachedImage = cache . get ( cacheKey ) ;
if ( cachedImage && ! isPatternFill ) {
const offsetX = Math . round ( Math . min ( currentTransform [ 0 ] , currentTransform [ 2 ] ) + currentTransform [ 4 ] ) ;
const offsetY = Math . round ( Math . min ( currentTransform [ 1 ] , currentTransform [ 3 ] ) + currentTransform [ 5 ] ) ;
return {
canvas : cachedImage ,
offsetX ,
offsetY
} ;
}
scaled = cachedImage ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
if ( ! scaled ) {
maskCanvas = this . cachedCanvases . getCanvas ( "maskCanvas" , width , height ) ;
putBinaryImageMask ( maskCanvas . context , img ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
let maskToCanvas = Util . transform ( currentTransform , [ 1 / width , 0 , 0 , - 1 / height , 0 , 0 ] ) ;
maskToCanvas = Util . transform ( maskToCanvas , [ 1 , 0 , 0 , 1 , 0 , - height ] ) ;
const [ minX , minY , maxX , maxY ] = Util . getAxialAlignedBoundingBox ( [ 0 , 0 , width , height ] , maskToCanvas ) ;
const drawnWidth = Math . round ( maxX - minX ) || 1 ;
const drawnHeight = Math . round ( maxY - minY ) || 1 ;
const fillCanvas = this . cachedCanvases . getCanvas ( "fillCanvas" , drawnWidth , drawnHeight ) ;
const fillCtx = fillCanvas . context ;
const offsetX = minX ;
const offsetY = minY ;
fillCtx . translate ( - offsetX , - offsetY ) ;
fillCtx . transform ( ... maskToCanvas ) ;
if ( ! scaled ) {
scaled = this . _scaleImage ( maskCanvas . canvas , getCurrentTransformInverse ( fillCtx ) ) ;
scaled = scaled . img ;
if ( cache && isPatternFill ) {
cache . set ( cacheKey , scaled ) ;
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
fillCtx . imageSmoothingEnabled = getImageSmoothingEnabled ( getCurrentTransform ( fillCtx ) , img . interpolate ) ;
drawImageAtIntegerCoords ( fillCtx , scaled , 0 , 0 , scaled . width , scaled . height , 0 , 0 , width , height ) ;
fillCtx . globalCompositeOperation = "source-in" ;
const inverse = Util . transform ( getCurrentTransformInverse ( fillCtx ) , [ 1 , 0 , 0 , 1 , - offsetX , - offsetY ] ) ;
fillCtx . fillStyle = isPatternFill ? fillColor . getPattern ( ctx , this , inverse , PathType . FILL ) : fillColor ;
fillCtx . fillRect ( 0 , 0 , width , height ) ;
if ( cache && ! isPatternFill ) {
this . cachedCanvases . delete ( "fillCanvas" ) ;
cache . set ( cacheKey , fillCanvas . canvas ) ;
}
return {
canvas : fillCanvas . canvas ,
offsetX : Math . round ( offsetX ) ,
offsetY : Math . round ( offsetY )
} ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
setLineWidth ( width ) {
if ( width !== this . current . lineWidth ) {
this . _cachedScaleForStroking [ 0 ] = - 1 ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
this . current . lineWidth = width ;
this . ctx . lineWidth = width ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
setLineCap ( style ) {
this . ctx . lineCap = LINE _CAP _STYLES [ style ] ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
setLineJoin ( style ) {
this . ctx . lineJoin = LINE _JOIN _STYLES [ style ] ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
setMiterLimit ( limit ) {
this . ctx . miterLimit = limit ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
setDash ( dashArray , dashPhase ) {
const ctx = this . ctx ;
if ( ctx . setLineDash !== undefined ) {
ctx . setLineDash ( dashArray ) ;
ctx . lineDashOffset = dashPhase ;
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
setRenderingIntent ( intent ) { }
setFlatness ( flatness ) { }
setGState ( states ) {
for ( const [ key , value ] of states ) {
switch ( key ) {
case "LW" :
this . setLineWidth ( value ) ;
break ;
case "LC" :
this . setLineCap ( value ) ;
break ;
case "LJ" :
this . setLineJoin ( value ) ;
break ;
case "ML" :
this . setMiterLimit ( value ) ;
break ;
case "D" :
this . setDash ( value [ 0 ] , value [ 1 ] ) ;
break ;
case "RI" :
this . setRenderingIntent ( value ) ;
break ;
case "FL" :
this . setFlatness ( value ) ;
break ;
case "Font" :
this . setFont ( value [ 0 ] , value [ 1 ] ) ;
break ;
case "CA" :
this . current . strokeAlpha = value ;
break ;
case "ca" :
this . current . fillAlpha = value ;
this . ctx . globalAlpha = value ;
break ;
case "BM" :
this . ctx . globalCompositeOperation = value ;
break ;
case "SMask" :
this . current . activeSMask = value ? this . tempSMask : null ;
this . tempSMask = null ;
this . checkSMaskState ( ) ;
break ;
case "TR" :
this . ctx . filter = this . current . transferMaps = this . filterFactory . addFilter ( value ) ;
break ;
}
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
get inSMaskMode ( ) {
return ! ! this . suspendedCtx ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
checkSMaskState ( ) {
const inSMaskMode = this . inSMaskMode ;
if ( this . current . activeSMask && ! inSMaskMode ) {
this . beginSMaskMode ( ) ;
} else if ( ! this . current . activeSMask && inSMaskMode ) {
this . endSMaskMode ( ) ;
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
beginSMaskMode ( ) {
if ( this . inSMaskMode ) {
throw new Error ( "beginSMaskMode called while already in smask mode" ) ;
}
const drawnWidth = this . ctx . canvas . width ;
const drawnHeight = this . ctx . canvas . height ;
const cacheId = "smaskGroupAt" + this . groupLevel ;
const scratchCanvas = this . cachedCanvases . getCanvas ( cacheId , drawnWidth , drawnHeight ) ;
this . suspendedCtx = this . ctx ;
this . ctx = scratchCanvas . context ;
const ctx = this . ctx ;
ctx . setTransform ( ... getCurrentTransform ( this . suspendedCtx ) ) ;
copyCtxState ( this . suspendedCtx , ctx ) ;
mirrorContextOperations ( ctx , this . suspendedCtx ) ;
this . setGState ( [ [ "BM" , "source-over" ] , [ "ca" , 1 ] , [ "CA" , 1 ] ] ) ;
2014-11-24 00:56:52 +01:00
}
2024-06-01 11:00:27 +01:00
endSMaskMode ( ) {
if ( ! this . inSMaskMode ) {
throw new Error ( "endSMaskMode called while not in smask mode" ) ;
}
this . ctx . _removeMirroring ( ) ;
copyCtxState ( this . ctx , this . suspendedCtx ) ;
this . ctx = this . suspendedCtx ;
this . suspendedCtx = null ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
compose ( dirtyBox ) {
if ( ! this . current . activeSMask ) {
2023-10-27 13:19:54 +02:00
return ;
}
2024-06-01 11:00:27 +01:00
if ( ! dirtyBox ) {
dirtyBox = [ 0 , 0 , this . ctx . canvas . width , this . ctx . canvas . height ] ;
} else {
dirtyBox [ 0 ] = Math . floor ( dirtyBox [ 0 ] ) ;
dirtyBox [ 1 ] = Math . floor ( dirtyBox [ 1 ] ) ;
dirtyBox [ 2 ] = Math . ceil ( dirtyBox [ 2 ] ) ;
dirtyBox [ 3 ] = Math . ceil ( dirtyBox [ 3 ] ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
const smask = this . current . activeSMask ;
const suspendedCtx = this . suspendedCtx ;
this . composeSMask ( suspendedCtx , smask , this . ctx , dirtyBox ) ;
this . ctx . save ( ) ;
this . ctx . setTransform ( 1 , 0 , 0 , 1 , 0 , 0 ) ;
this . ctx . clearRect ( 0 , 0 , this . ctx . canvas . width , this . ctx . canvas . height ) ;
this . ctx . restore ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
composeSMask ( ctx , smask , layerCtx , layerBox ) {
const layerOffsetX = layerBox [ 0 ] ;
const layerOffsetY = layerBox [ 1 ] ;
const layerWidth = layerBox [ 2 ] - layerOffsetX ;
const layerHeight = layerBox [ 3 ] - layerOffsetY ;
if ( layerWidth === 0 || layerHeight === 0 ) {
return ;
}
this . genericComposeSMask ( smask . context , layerCtx , layerWidth , layerHeight , smask . subtype , smask . backdrop , smask . transferMap , layerOffsetX , layerOffsetY , smask . offsetX , smask . offsetY ) ;
ctx . save ( ) ;
ctx . globalAlpha = 1 ;
ctx . globalCompositeOperation = "source-over" ;
ctx . setTransform ( 1 , 0 , 0 , 1 , 0 , 0 ) ;
ctx . drawImage ( layerCtx . canvas , 0 , 0 ) ;
ctx . restore ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
genericComposeSMask ( maskCtx , layerCtx , width , height , subtype , backdrop , transferMap , layerOffsetX , layerOffsetY , maskOffsetX , maskOffsetY ) {
let maskCanvas = maskCtx . canvas ;
let maskX = layerOffsetX - maskOffsetX ;
let maskY = layerOffsetY - maskOffsetY ;
if ( backdrop ) {
if ( maskX < 0 || maskY < 0 || maskX + width > maskCanvas . width || maskY + height > maskCanvas . height ) {
const canvas = this . cachedCanvases . getCanvas ( "maskExtension" , width , height ) ;
const ctx = canvas . context ;
ctx . drawImage ( maskCanvas , - maskX , - maskY ) ;
if ( backdrop . some ( c => c !== 0 ) ) {
ctx . globalCompositeOperation = "destination-atop" ;
ctx . fillStyle = Util . makeHexColor ( ... backdrop ) ;
ctx . fillRect ( 0 , 0 , width , height ) ;
ctx . globalCompositeOperation = "source-over" ;
}
maskCanvas = canvas . canvas ;
maskX = maskY = 0 ;
} else if ( backdrop . some ( c => c !== 0 ) ) {
maskCtx . save ( ) ;
maskCtx . globalAlpha = 1 ;
maskCtx . setTransform ( 1 , 0 , 0 , 1 , 0 , 0 ) ;
const clip = new Path2D ( ) ;
clip . rect ( maskX , maskY , width , height ) ;
maskCtx . clip ( clip ) ;
maskCtx . globalCompositeOperation = "destination-atop" ;
maskCtx . fillStyle = Util . makeHexColor ( ... backdrop ) ;
maskCtx . fillRect ( maskX , maskY , width , height ) ;
maskCtx . restore ( ) ;
}
}
layerCtx . save ( ) ;
layerCtx . globalAlpha = 1 ;
layerCtx . setTransform ( 1 , 0 , 0 , 1 , 0 , 0 ) ;
if ( subtype === "Alpha" && transferMap ) {
layerCtx . filter = this . filterFactory . addAlphaFilter ( transferMap ) ;
} else if ( subtype === "Luminosity" ) {
layerCtx . filter = this . filterFactory . addLuminosityFilter ( transferMap ) ;
}
const clip = new Path2D ( ) ;
clip . rect ( layerOffsetX , layerOffsetY , width , height ) ;
layerCtx . clip ( clip ) ;
layerCtx . globalCompositeOperation = "destination-in" ;
layerCtx . drawImage ( maskCanvas , maskX , maskY , width , height , layerOffsetX , layerOffsetY , width , height ) ;
layerCtx . restore ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
save ( ) {
if ( this . inSMaskMode ) {
copyCtxState ( this . ctx , this . suspendedCtx ) ;
this . suspendedCtx . save ( ) ;
} else {
this . ctx . save ( ) ;
}
const old = this . current ;
this . stateStack . push ( old ) ;
this . current = old . clone ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
restore ( ) {
if ( this . stateStack . length === 0 && this . inSMaskMode ) {
this . endSMaskMode ( ) ;
}
if ( this . stateStack . length !== 0 ) {
this . current = this . stateStack . pop ( ) ;
if ( this . inSMaskMode ) {
this . suspendedCtx . restore ( ) ;
copyCtxState ( this . suspendedCtx , this . ctx ) ;
} else {
this . ctx . restore ( ) ;
}
this . checkSMaskState ( ) ;
this . pendingClip = null ;
this . _cachedScaleForStroking [ 0 ] = - 1 ;
this . _cachedGetSinglePixelWidth = null ;
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
transform ( a , b , c , d , e , f ) {
this . ctx . transform ( a , b , c , d , e , f ) ;
this . _cachedScaleForStroking [ 0 ] = - 1 ;
this . _cachedGetSinglePixelWidth = null ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
constructPath ( ops , args , minMax ) {
const ctx = this . ctx ;
const current = this . current ;
let x = current . x ,
y = current . y ;
let startX , startY ;
const currentTransform = getCurrentTransform ( ctx ) ;
const isScalingMatrix = currentTransform [ 0 ] === 0 && currentTransform [ 3 ] === 0 || currentTransform [ 1 ] === 0 && currentTransform [ 2 ] === 0 ;
const minMaxForBezier = isScalingMatrix ? minMax . slice ( 0 ) : null ;
for ( let i = 0 , j = 0 , ii = ops . length ; i < ii ; i ++ ) {
switch ( ops [ i ] | 0 ) {
case OPS . rectangle :
x = args [ j ++ ] ;
y = args [ j ++ ] ;
const width = args [ j ++ ] ;
const height = args [ j ++ ] ;
const xw = x + width ;
const yh = y + height ;
ctx . moveTo ( x , y ) ;
if ( width === 0 || height === 0 ) {
ctx . lineTo ( xw , yh ) ;
} else {
ctx . lineTo ( xw , y ) ;
ctx . lineTo ( xw , yh ) ;
ctx . lineTo ( x , yh ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
if ( ! isScalingMatrix ) {
current . updateRectMinMax ( currentTransform , [ x , y , xw , yh ] ) ;
}
ctx . closePath ( ) ;
break ;
case OPS . moveTo :
x = args [ j ++ ] ;
y = args [ j ++ ] ;
ctx . moveTo ( x , y ) ;
if ( ! isScalingMatrix ) {
current . updatePathMinMax ( currentTransform , x , y ) ;
}
break ;
case OPS . lineTo :
x = args [ j ++ ] ;
y = args [ j ++ ] ;
ctx . lineTo ( x , y ) ;
if ( ! isScalingMatrix ) {
current . updatePathMinMax ( currentTransform , x , y ) ;
}
break ;
case OPS . curveTo :
startX = x ;
startY = y ;
x = args [ j + 4 ] ;
y = args [ j + 5 ] ;
ctx . bezierCurveTo ( args [ j ] , args [ j + 1 ] , args [ j + 2 ] , args [ j + 3 ] , x , y ) ;
current . updateCurvePathMinMax ( currentTransform , startX , startY , args [ j ] , args [ j + 1 ] , args [ j + 2 ] , args [ j + 3 ] , x , y , minMaxForBezier ) ;
j += 6 ;
break ;
case OPS . curveTo2 :
startX = x ;
startY = y ;
ctx . bezierCurveTo ( x , y , args [ j ] , args [ j + 1 ] , args [ j + 2 ] , args [ j + 3 ] ) ;
current . updateCurvePathMinMax ( currentTransform , startX , startY , x , y , args [ j ] , args [ j + 1 ] , args [ j + 2 ] , args [ j + 3 ] , minMaxForBezier ) ;
x = args [ j + 2 ] ;
y = args [ j + 3 ] ;
j += 4 ;
break ;
case OPS . curveTo3 :
startX = x ;
startY = y ;
x = args [ j + 2 ] ;
y = args [ j + 3 ] ;
ctx . bezierCurveTo ( args [ j ] , args [ j + 1 ] , x , y , x , y ) ;
current . updateCurvePathMinMax ( currentTransform , startX , startY , args [ j ] , args [ j + 1 ] , x , y , x , y , minMaxForBezier ) ;
j += 4 ;
break ;
case OPS . closePath :
ctx . closePath ( ) ;
break ;
2016-04-04 15:49:28 +02:00
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
if ( isScalingMatrix ) {
current . updateScalingPathMinMax ( currentTransform , minMaxForBezier ) ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
current . setCurrentPoint ( x , y ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
closePath ( ) {
this . ctx . closePath ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
stroke ( consumePath = true ) {
const ctx = this . ctx ;
const strokeColor = this . current . strokeColor ;
ctx . globalAlpha = this . current . strokeAlpha ;
if ( this . contentVisible ) {
if ( typeof strokeColor === "object" && strokeColor ? . getPattern ) {
ctx . save ( ) ;
ctx . strokeStyle = strokeColor . getPattern ( ctx , this , getCurrentTransformInverse ( ctx ) , PathType . STROKE ) ;
this . rescaleAndStroke ( false ) ;
ctx . restore ( ) ;
} else {
this . rescaleAndStroke ( true ) ;
}
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
if ( consumePath ) {
this . consumePath ( this . current . getClippedPathBoundingBox ( ) ) ;
}
ctx . globalAlpha = this . current . fillAlpha ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
closeStroke ( ) {
this . closePath ( ) ;
this . stroke ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
fill ( consumePath = true ) {
const ctx = this . ctx ;
const fillColor = this . current . fillColor ;
const isPatternFill = this . current . patternFill ;
let needRestore = false ;
if ( isPatternFill ) {
ctx . save ( ) ;
ctx . fillStyle = fillColor . getPattern ( ctx , this , getCurrentTransformInverse ( ctx ) , PathType . FILL ) ;
needRestore = true ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
const intersect = this . current . getClippedPathBoundingBox ( ) ;
if ( this . contentVisible && intersect !== null ) {
if ( this . pendingEOFill ) {
ctx . fill ( "evenodd" ) ;
this . pendingEOFill = false ;
} else {
ctx . fill ( ) ;
}
}
if ( needRestore ) {
ctx . restore ( ) ;
}
if ( consumePath ) {
this . consumePath ( intersect ) ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
eoFill ( ) {
this . pendingEOFill = true ;
this . fill ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
fillStroke ( ) {
this . fill ( false ) ;
this . stroke ( false ) ;
this . consumePath ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
eoFillStroke ( ) {
this . pendingEOFill = true ;
this . fillStroke ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
closeFillStroke ( ) {
this . closePath ( ) ;
this . fillStroke ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
closeEOFillStroke ( ) {
this . pendingEOFill = true ;
this . closePath ( ) ;
this . fillStroke ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
endPath ( ) {
this . consumePath ( ) ;
2016-04-04 15:49:28 +02:00
}
2024-06-01 11:00:27 +01:00
clip ( ) {
this . pendingClip = NORMAL _CLIP ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
eoClip ( ) {
this . pendingClip = EO _CLIP ;
}
beginText ( ) {
this . current . textMatrix = IDENTITY _MATRIX ;
this . current . textMatrixScale = 1 ;
this . current . x = this . current . lineX = 0 ;
this . current . y = this . current . lineY = 0 ;
}
endText ( ) {
const paths = this . pendingTextPaths ;
const ctx = this . ctx ;
if ( paths === undefined ) {
ctx . beginPath ( ) ;
return ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
ctx . save ( ) ;
ctx . beginPath ( ) ;
for ( const path of paths ) {
ctx . setTransform ( ... path . transform ) ;
ctx . translate ( path . x , path . y ) ;
path . addToPath ( ctx , path . fontSize ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
ctx . restore ( ) ;
ctx . clip ( ) ;
ctx . beginPath ( ) ;
delete this . pendingTextPaths ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
setCharSpacing ( spacing ) {
this . current . charSpacing = spacing ;
}
setWordSpacing ( spacing ) {
this . current . wordSpacing = spacing ;
}
setHScale ( scale ) {
this . current . textHScale = scale / 100 ;
}
setLeading ( leading ) {
this . current . leading = - leading ;
}
setFont ( fontRefName , size ) {
const fontObj = this . commonObjs . get ( fontRefName ) ;
const current = this . current ;
if ( ! fontObj ) {
throw new Error ( ` Can't find font for ${ fontRefName } ` ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
current . fontMatrix = fontObj . fontMatrix || FONT _IDENTITY _MATRIX ;
if ( current . fontMatrix [ 0 ] === 0 || current . fontMatrix [ 3 ] === 0 ) {
warn ( "Invalid font matrix for font " + fontRefName ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
if ( size < 0 ) {
size = - size ;
current . fontDirection = - 1 ;
} else {
current . fontDirection = 1 ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
this . current . font = fontObj ;
this . current . fontSize = size ;
if ( fontObj . isType3Font ) {
return ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
const name = fontObj . loadedName || "sans-serif" ;
const typeface = fontObj . systemFontInfo ? . css || ` " ${ name } ", ${ fontObj . fallbackName } ` ;
let bold = "normal" ;
if ( fontObj . black ) {
bold = "900" ;
} else if ( fontObj . bold ) {
bold = "bold" ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
const italic = fontObj . italic ? "italic" : "normal" ;
let browserFontSize = size ;
if ( size < MIN _FONT _SIZE ) {
browserFontSize = MIN _FONT _SIZE ;
} else if ( size > MAX _FONT _SIZE ) {
browserFontSize = MAX _FONT _SIZE ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
this . current . fontSizeScale = size / browserFontSize ;
this . ctx . font = ` ${ italic } ${ bold } ${ browserFontSize } px ${ typeface } ` ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
setTextRenderingMode ( mode ) {
this . current . textRenderingMode = mode ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
setTextRise ( rise ) {
this . current . textRise = rise ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
moveText ( x , y ) {
this . current . x = this . current . lineX += x ;
this . current . y = this . current . lineY += y ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
setLeadingMoveText ( x , y ) {
this . setLeading ( - y ) ;
this . moveText ( x , y ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
setTextMatrix ( a , b , c , d , e , f ) {
this . current . textMatrix = [ a , b , c , d , e , f ] ;
this . current . textMatrixScale = Math . hypot ( a , b ) ;
this . current . x = this . current . lineX = 0 ;
this . current . y = this . current . lineY = 0 ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
nextLine ( ) {
this . moveText ( 0 , this . current . leading ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
paintChar ( character , x , y , patternTransform ) {
2023-10-27 13:19:54 +02:00
const ctx = this . ctx ;
2024-06-01 11:00:27 +01:00
const current = this . current ;
const font = current . font ;
const textRenderingMode = current . textRenderingMode ;
const fontSize = current . fontSize / current . fontSizeScale ;
const fillStrokeMode = textRenderingMode & TextRenderingMode . FILL _STROKE _MASK ;
const isAddToPathSet = ! ! ( textRenderingMode & TextRenderingMode . ADD _TO _PATH _FLAG ) ;
const patternFill = current . patternFill && ! font . missingFile ;
let addToPath ;
if ( font . disableFontFace || isAddToPathSet || patternFill ) {
addToPath = font . getPathGenerator ( this . commonObjs , character ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
if ( font . disableFontFace || patternFill ) {
ctx . save ( ) ;
ctx . translate ( x , y ) ;
ctx . beginPath ( ) ;
addToPath ( ctx , fontSize ) ;
if ( patternTransform ) {
ctx . setTransform ( ... patternTransform ) ;
}
if ( fillStrokeMode === TextRenderingMode . FILL || fillStrokeMode === TextRenderingMode . FILL _STROKE ) {
ctx . fill ( ) ;
}
if ( fillStrokeMode === TextRenderingMode . STROKE || fillStrokeMode === TextRenderingMode . FILL _STROKE ) {
ctx . stroke ( ) ;
}
ctx . restore ( ) ;
} else {
if ( fillStrokeMode === TextRenderingMode . FILL || fillStrokeMode === TextRenderingMode . FILL _STROKE ) {
ctx . fillText ( character , x , y ) ;
}
if ( fillStrokeMode === TextRenderingMode . STROKE || fillStrokeMode === TextRenderingMode . FILL _STROKE ) {
ctx . strokeText ( character , x , y ) ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
if ( isAddToPathSet ) {
const paths = this . pendingTextPaths || = [ ] ;
paths . push ( {
transform : getCurrentTransform ( ctx ) ,
x ,
y ,
fontSize ,
addToPath
} ) ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
get isFontSubpixelAAEnabled ( ) {
const {
context : ctx
} = this . cachedCanvases . getCanvas ( "isFontSubpixelAAEnabled" , 10 , 10 ) ;
ctx . scale ( 1.5 , 1 ) ;
ctx . fillText ( "I" , 0 , 10 ) ;
const data = ctx . getImageData ( 0 , 0 , 10 , 10 ) . data ;
let enabled = false ;
for ( let i = 3 ; i < data . length ; i += 4 ) {
if ( data [ i ] > 0 && data [ i ] < 255 ) {
enabled = true ;
break ;
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
return shadow ( this , "isFontSubpixelAAEnabled" , enabled ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
showText ( glyphs ) {
const current = this . current ;
const font = current . font ;
if ( font . isType3Font ) {
return this . showType3Text ( glyphs ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
const fontSize = current . fontSize ;
if ( fontSize === 0 ) {
return undefined ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
const ctx = this . ctx ;
const fontSizeScale = current . fontSizeScale ;
const charSpacing = current . charSpacing ;
const wordSpacing = current . wordSpacing ;
const fontDirection = current . fontDirection ;
const textHScale = current . textHScale * fontDirection ;
const glyphsLength = glyphs . length ;
const vertical = font . vertical ;
const spacingDir = vertical ? 1 : - 1 ;
const defaultVMetrics = font . defaultVMetrics ;
const widthAdvanceScale = fontSize * current . fontMatrix [ 0 ] ;
const simpleFillText = current . textRenderingMode === TextRenderingMode . FILL && ! font . disableFontFace && ! current . patternFill ;
ctx . save ( ) ;
ctx . transform ( ... current . textMatrix ) ;
ctx . translate ( current . x , current . y + current . textRise ) ;
if ( fontDirection > 0 ) {
ctx . scale ( textHScale , - 1 ) ;
2023-10-27 13:19:54 +02:00
} else {
2024-06-01 11:00:27 +01:00
ctx . scale ( textHScale , 1 ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
let patternTransform ;
if ( current . patternFill ) {
ctx . save ( ) ;
const pattern = current . fillColor . getPattern ( ctx , this , getCurrentTransformInverse ( ctx ) , PathType . FILL ) ;
patternTransform = getCurrentTransform ( ctx ) ;
ctx . restore ( ) ;
ctx . fillStyle = pattern ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
let lineWidth = current . lineWidth ;
const scale = current . textMatrixScale ;
if ( scale === 0 || lineWidth === 0 ) {
const fillStrokeMode = current . textRenderingMode & TextRenderingMode . FILL _STROKE _MASK ;
if ( fillStrokeMode === TextRenderingMode . STROKE || fillStrokeMode === TextRenderingMode . FILL _STROKE ) {
lineWidth = this . getSinglePixelWidth ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
} else {
lineWidth /= scale ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
if ( fontSizeScale !== 1.0 ) {
ctx . scale ( fontSizeScale , fontSizeScale ) ;
lineWidth /= fontSizeScale ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
ctx . lineWidth = lineWidth ;
if ( font . isInvalidPDFjsFont ) {
const chars = [ ] ;
let width = 0 ;
for ( const glyph of glyphs ) {
chars . push ( glyph . unicode ) ;
width += glyph . width ;
}
ctx . fillText ( chars . join ( "" ) , 0 , 0 ) ;
current . x += width * widthAdvanceScale * textHScale ;
ctx . restore ( ) ;
this . compose ( ) ;
return undefined ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
let x = 0 ,
i ;
for ( i = 0 ; i < glyphsLength ; ++ i ) {
const glyph = glyphs [ i ] ;
if ( typeof glyph === "number" ) {
x += spacingDir * glyph * fontSize / 1000 ;
continue ;
}
let restoreNeeded = false ;
const spacing = ( glyph . isSpace ? wordSpacing : 0 ) + charSpacing ;
const character = glyph . fontChar ;
const accent = glyph . accent ;
let scaledX , scaledY ;
let width = glyph . width ;
if ( vertical ) {
const vmetric = glyph . vmetric || defaultVMetrics ;
const vx = - ( glyph . vmetric ? vmetric [ 1 ] : width * 0.5 ) * widthAdvanceScale ;
const vy = vmetric [ 2 ] * widthAdvanceScale ;
width = vmetric ? - vmetric [ 0 ] : width ;
scaledX = vx / fontSizeScale ;
scaledY = ( x + vy ) / fontSizeScale ;
2023-10-27 13:19:54 +02:00
} else {
2024-06-01 11:00:27 +01:00
scaledX = x / fontSizeScale ;
scaledY = 0 ;
}
if ( font . remeasure && width > 0 ) {
const measuredWidth = ctx . measureText ( character ) . width * 1000 / fontSize * fontSizeScale ;
if ( width < measuredWidth && this . isFontSubpixelAAEnabled ) {
const characterScaleX = width / measuredWidth ;
restoreNeeded = true ;
ctx . save ( ) ;
ctx . scale ( characterScaleX , 1 ) ;
scaledX /= characterScaleX ;
} else if ( width !== measuredWidth ) {
scaledX += ( width - measuredWidth ) / 2000 * fontSize / fontSizeScale ;
}
}
if ( this . contentVisible && ( glyph . isInFont || font . missingFile ) ) {
if ( simpleFillText && ! accent ) {
ctx . fillText ( character , scaledX , scaledY ) ;
} else {
this . paintChar ( character , scaledX , scaledY , patternTransform ) ;
if ( accent ) {
const scaledAccentX = scaledX + fontSize * accent . offset . x / fontSizeScale ;
const scaledAccentY = scaledY - fontSize * accent . offset . y / fontSizeScale ;
this . paintChar ( accent . fontChar , scaledAccentX , scaledAccentY , patternTransform ) ;
}
}
}
const charWidth = vertical ? width * widthAdvanceScale - spacing * fontDirection : width * widthAdvanceScale + spacing * fontDirection ;
x += charWidth ;
if ( restoreNeeded ) {
ctx . restore ( ) ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
if ( vertical ) {
current . y -= x ;
} else {
current . x += x * textHScale ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
ctx . restore ( ) ;
this . compose ( ) ;
return undefined ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
showType3Text ( glyphs ) {
2023-10-27 13:19:54 +02:00
const ctx = this . ctx ;
2024-06-01 11:00:27 +01:00
const current = this . current ;
const font = current . font ;
const fontSize = current . fontSize ;
const fontDirection = current . fontDirection ;
const spacingDir = font . vertical ? 1 : - 1 ;
const charSpacing = current . charSpacing ;
const wordSpacing = current . wordSpacing ;
const textHScale = current . textHScale * fontDirection ;
const fontMatrix = current . fontMatrix || FONT _IDENTITY _MATRIX ;
const glyphsLength = glyphs . length ;
const isTextInvisible = current . textRenderingMode === TextRenderingMode . INVISIBLE ;
let i , glyph , width , spacingLength ;
if ( isTextInvisible || fontSize === 0 ) {
return ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
this . _cachedScaleForStroking [ 0 ] = - 1 ;
this . _cachedGetSinglePixelWidth = null ;
ctx . save ( ) ;
ctx . transform ( ... current . textMatrix ) ;
ctx . translate ( current . x , current . y ) ;
ctx . scale ( textHScale , fontDirection ) ;
for ( i = 0 ; i < glyphsLength ; ++ i ) {
glyph = glyphs [ i ] ;
if ( typeof glyph === "number" ) {
spacingLength = spacingDir * glyph * fontSize / 1000 ;
this . ctx . translate ( spacingLength , 0 ) ;
current . x += spacingLength * textHScale ;
continue ;
}
const spacing = ( glyph . isSpace ? wordSpacing : 0 ) + charSpacing ;
const operatorList = font . charProcOperatorList [ glyph . operatorListId ] ;
if ( ! operatorList ) {
warn ( ` Type3 character " ${ glyph . operatorListId } " is not available. ` ) ;
continue ;
}
if ( this . contentVisible ) {
this . processingType3 = glyph ;
this . save ( ) ;
ctx . scale ( fontSize , fontSize ) ;
ctx . transform ( ... fontMatrix ) ;
this . executeOperatorList ( operatorList ) ;
this . restore ( ) ;
}
const transformed = Util . applyTransform ( [ glyph . width , 0 ] , fontMatrix ) ;
width = transformed [ 0 ] * fontSize + spacing ;
ctx . translate ( width , 0 ) ;
current . x += width * textHScale ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
ctx . restore ( ) ;
this . processingType3 = null ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
setCharWidth ( xWidth , yWidth ) { }
setCharWidthAndBounds ( xWidth , yWidth , llx , lly , urx , ury ) {
this . ctx . rect ( llx , lly , urx - llx , ury - lly ) ;
this . ctx . clip ( ) ;
this . endPath ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
getColorN _Pattern ( IR ) {
let pattern ;
if ( IR [ 0 ] === "TilingPattern" ) {
const color = IR [ 1 ] ;
const baseTransform = this . baseTransform || getCurrentTransform ( this . ctx ) ;
const canvasGraphicsFactory = {
createCanvasGraphics : ctx => new CanvasGraphics ( ctx , this . commonObjs , this . objs , this . canvasFactory , this . filterFactory , {
optionalContentConfig : this . optionalContentConfig ,
markedContentStack : this . markedContentStack
} )
} ;
pattern = new TilingPattern ( IR , color , this . ctx , canvasGraphicsFactory , baseTransform ) ;
} else {
pattern = this . _getPattern ( IR [ 1 ] , IR [ 2 ] ) ;
}
return pattern ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
setStrokeColorN ( ) {
this . current . strokeColor = this . getColorN _Pattern ( arguments ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
setFillColorN ( ) {
this . current . fillColor = this . getColorN _Pattern ( arguments ) ;
this . current . patternFill = true ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
setStrokeRGBColor ( r , g , b ) {
const color = Util . makeHexColor ( r , g , b ) ;
this . ctx . strokeStyle = color ;
this . current . strokeColor = color ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
setFillRGBColor ( r , g , b ) {
const color = Util . makeHexColor ( r , g , b ) ;
this . ctx . fillStyle = color ;
this . current . fillColor = color ;
this . current . patternFill = false ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
_getPattern ( objId , matrix = null ) {
let pattern ;
if ( this . cachedPatterns . has ( objId ) ) {
pattern = this . cachedPatterns . get ( objId ) ;
} else {
pattern = getShadingPattern ( this . getObject ( objId ) ) ;
this . cachedPatterns . set ( objId , pattern ) ;
}
if ( matrix ) {
pattern . matrix = matrix ;
}
return pattern ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
shadingFill ( objId ) {
if ( ! this . contentVisible ) {
2023-10-27 13:19:54 +02:00
return ;
}
2024-06-01 11:00:27 +01:00
const ctx = this . ctx ;
this . save ( ) ;
const pattern = this . _getPattern ( objId ) ;
ctx . fillStyle = pattern . getPattern ( ctx , this , getCurrentTransformInverse ( ctx ) , PathType . SHADING ) ;
const inv = getCurrentTransformInverse ( ctx ) ;
if ( inv ) {
const {
width ,
height
} = ctx . canvas ;
const [ x0 , y0 , x1 , y1 ] = Util . getAxialAlignedBoundingBox ( [ 0 , 0 , width , height ] , inv ) ;
this . ctx . fillRect ( x0 , y0 , x1 - x0 , y1 - y0 ) ;
} else {
this . ctx . fillRect ( - 1e10 , - 1e10 , 2e10 , 2e10 ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
this . compose ( this . current . getClippedPathBoundingBox ( ) ) ;
this . restore ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
beginInlineImage ( ) {
unreachable ( "Should not call beginInlineImage" ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
beginImageData ( ) {
unreachable ( "Should not call beginImageData" ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
paintFormXObjectBegin ( matrix , bbox ) {
if ( ! this . contentVisible ) {
return ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
this . save ( ) ;
this . baseTransformStack . push ( this . baseTransform ) ;
if ( matrix ) {
this . transform ( ... matrix ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
this . baseTransform = getCurrentTransform ( this . ctx ) ;
if ( bbox ) {
const width = bbox [ 2 ] - bbox [ 0 ] ;
const height = bbox [ 3 ] - bbox [ 1 ] ;
this . ctx . rect ( bbox [ 0 ] , bbox [ 1 ] , width , height ) ;
this . current . updateRectMinMax ( getCurrentTransform ( this . ctx ) , bbox ) ;
this . clip ( ) ;
this . endPath ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
}
paintFormXObjectEnd ( ) {
if ( ! this . contentVisible ) {
2023-10-27 13:19:54 +02:00
return ;
}
2024-06-01 11:00:27 +01:00
this . restore ( ) ;
this . baseTransform = this . baseTransformStack . pop ( ) ;
}
beginGroup ( group ) {
if ( ! this . contentVisible ) {
return ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
this . save ( ) ;
if ( this . inSMaskMode ) {
this . endSMaskMode ( ) ;
this . current . activeSMask = null ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
const currentCtx = this . ctx ;
if ( ! group . isolated ) {
info ( "TODO: Support non-isolated groups." ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
if ( group . knockout ) {
warn ( "Knockout groups not supported." ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
const currentTransform = getCurrentTransform ( currentCtx ) ;
if ( group . matrix ) {
currentCtx . transform ( ... group . matrix ) ;
}
if ( ! group . bbox ) {
throw new Error ( "Bounding box is required." ) ;
}
let bounds = Util . getAxialAlignedBoundingBox ( group . bbox , getCurrentTransform ( currentCtx ) ) ;
const canvasBounds = [ 0 , 0 , currentCtx . canvas . width , currentCtx . canvas . height ] ;
bounds = Util . intersect ( bounds , canvasBounds ) || [ 0 , 0 , 0 , 0 ] ;
const offsetX = Math . floor ( bounds [ 0 ] ) ;
const offsetY = Math . floor ( bounds [ 1 ] ) ;
const drawnWidth = Math . max ( Math . ceil ( bounds [ 2 ] ) - offsetX , 1 ) ;
const drawnHeight = Math . max ( Math . ceil ( bounds [ 3 ] ) - offsetY , 1 ) ;
this . current . startNewPathAndClipBox ( [ 0 , 0 , drawnWidth , drawnHeight ] ) ;
let cacheId = "groupAt" + this . groupLevel ;
if ( group . smask ) {
cacheId += "_smask_" + this . smaskCounter ++ % 2 ;
}
const scratchCanvas = this . cachedCanvases . getCanvas ( cacheId , drawnWidth , drawnHeight ) ;
const groupCtx = scratchCanvas . context ;
groupCtx . translate ( - offsetX , - offsetY ) ;
groupCtx . transform ( ... currentTransform ) ;
if ( group . smask ) {
this . smaskStack . push ( {
canvas : scratchCanvas . canvas ,
context : groupCtx ,
offsetX ,
offsetY ,
subtype : group . smask . subtype ,
backdrop : group . smask . backdrop ,
transferMap : group . smask . transferMap || null ,
startTransformInverse : null
2023-10-27 13:19:54 +02:00
} ) ;
2024-06-01 11:00:27 +01:00
} else {
currentCtx . setTransform ( 1 , 0 , 0 , 1 , 0 , 0 ) ;
currentCtx . translate ( offsetX , offsetY ) ;
currentCtx . save ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
copyCtxState ( currentCtx , groupCtx ) ;
this . ctx = groupCtx ;
this . setGState ( [ [ "BM" , "source-over" ] , [ "ca" , 1 ] , [ "CA" , 1 ] ] ) ;
this . groupStack . push ( currentCtx ) ;
this . groupLevel ++ ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
endGroup ( group ) {
if ( ! this . contentVisible ) {
return ;
}
this . groupLevel -- ;
const groupCtx = this . ctx ;
const ctx = this . groupStack . pop ( ) ;
this . ctx = ctx ;
this . ctx . imageSmoothingEnabled = false ;
if ( group . smask ) {
this . tempSMask = this . smaskStack . pop ( ) ;
this . restore ( ) ;
} else {
this . ctx . restore ( ) ;
const currentMtx = getCurrentTransform ( this . ctx ) ;
this . restore ( ) ;
this . ctx . save ( ) ;
this . ctx . setTransform ( ... currentMtx ) ;
const dirtyBox = Util . getAxialAlignedBoundingBox ( [ 0 , 0 , groupCtx . canvas . width , groupCtx . canvas . height ] , currentMtx ) ;
this . ctx . drawImage ( groupCtx . canvas , 0 , 0 ) ;
this . ctx . restore ( ) ;
this . compose ( dirtyBox ) ;
}
}
beginAnnotation ( id , rect , transform , matrix , hasOwnCanvas ) {
this . # restoreInitialState ( ) ;
resetCtxToDefault ( this . ctx ) ;
this . ctx . save ( ) ;
this . save ( ) ;
if ( this . baseTransform ) {
this . ctx . setTransform ( ... this . baseTransform ) ;
}
if ( rect ) {
const width = rect [ 2 ] - rect [ 0 ] ;
const height = rect [ 3 ] - rect [ 1 ] ;
if ( hasOwnCanvas && this . annotationCanvasMap ) {
transform = transform . slice ( ) ;
transform [ 4 ] -= rect [ 0 ] ;
transform [ 5 ] -= rect [ 1 ] ;
rect = rect . slice ( ) ;
rect [ 0 ] = rect [ 1 ] = 0 ;
rect [ 2 ] = width ;
rect [ 3 ] = height ;
const [ scaleX , scaleY ] = Util . singularValueDecompose2dScale ( getCurrentTransform ( this . ctx ) ) ;
const {
viewportScale
} = this ;
const canvasWidth = Math . ceil ( width * this . outputScaleX * viewportScale ) ;
const canvasHeight = Math . ceil ( height * this . outputScaleY * viewportScale ) ;
this . annotationCanvas = this . canvasFactory . create ( canvasWidth , canvasHeight ) ;
const {
canvas ,
context
} = this . annotationCanvas ;
this . annotationCanvasMap . set ( id , canvas ) ;
this . annotationCanvas . savedCtx = this . ctx ;
this . ctx = context ;
this . ctx . save ( ) ;
this . ctx . setTransform ( scaleX , 0 , 0 , - scaleY , 0 , height * scaleY ) ;
resetCtxToDefault ( this . ctx ) ;
} else {
resetCtxToDefault ( this . ctx ) ;
this . ctx . rect ( rect [ 0 ] , rect [ 1 ] , width , height ) ;
this . ctx . clip ( ) ;
this . endPath ( ) ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
this . current = new CanvasExtraState ( this . ctx . canvas . width , this . ctx . canvas . height ) ;
this . transform ( ... transform ) ;
this . transform ( ... matrix ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
endAnnotation ( ) {
if ( this . annotationCanvas ) {
this . ctx . restore ( ) ;
this . # drawFilter ( ) ;
this . ctx = this . annotationCanvas . savedCtx ;
delete this . annotationCanvas . savedCtx ;
delete this . annotationCanvas ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
}
paintImageMaskXObject ( img ) {
if ( ! this . contentVisible ) {
return ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
const count = img . count ;
img = this . getObject ( img . data , img ) ;
img . count = count ;
2023-10-27 13:19:54 +02:00
const ctx = this . ctx ;
2024-06-01 11:00:27 +01:00
const glyph = this . processingType3 ;
if ( glyph ) {
if ( glyph . compiled === undefined ) {
glyph . compiled = compileType3Glyph ( img ) ;
}
if ( glyph . compiled ) {
glyph . compiled ( ctx ) ;
return ;
}
}
const mask = this . _createMaskCanvas ( img ) ;
const maskCanvas = mask . canvas ;
2023-10-27 13:19:54 +02:00
ctx . save ( ) ;
2024-06-01 11:00:27 +01:00
ctx . setTransform ( 1 , 0 , 0 , 1 , 0 , 0 ) ;
ctx . drawImage ( maskCanvas , mask . offsetX , mask . offsetY ) ;
ctx . restore ( ) ;
this . compose ( ) ;
}
paintImageMaskXObjectRepeat ( img , scaleX , skewX = 0 , skewY = 0 , scaleY , positions ) {
if ( ! this . contentVisible ) {
return ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
img = this . getObject ( img . data , img ) ;
const ctx = this . ctx ;
ctx . save ( ) ;
const currentTransform = getCurrentTransform ( ctx ) ;
ctx . transform ( scaleX , skewX , skewY , scaleY , 0 , 0 ) ;
const mask = this . _createMaskCanvas ( img ) ;
ctx . setTransform ( 1 , 0 , 0 , 1 , mask . offsetX - currentTransform [ 4 ] , mask . offsetY - currentTransform [ 5 ] ) ;
for ( let i = 0 , ii = positions . length ; i < ii ; i += 2 ) {
const trans = Util . transform ( currentTransform , [ scaleX , skewX , skewY , scaleY , positions [ i ] , positions [ i + 1 ] ] ) ;
const [ x , y ] = Util . applyTransform ( [ 0 , 0 ] , trans ) ;
ctx . drawImage ( mask . canvas , x , y ) ;
}
ctx . restore ( ) ;
this . compose ( ) ;
}
paintImageMaskXObjectGroup ( images ) {
if ( ! this . contentVisible ) {
return ;
}
const ctx = this . ctx ;
const fillColor = this . current . fillColor ;
const isPatternFill = this . current . patternFill ;
for ( const image of images ) {
const {
data ,
width ,
height ,
transform
} = image ;
const maskCanvas = this . cachedCanvases . getCanvas ( "maskCanvas" , width , height ) ;
const maskCtx = maskCanvas . context ;
maskCtx . save ( ) ;
const img = this . getObject ( data , image ) ;
putBinaryImageMask ( maskCtx , img ) ;
maskCtx . globalCompositeOperation = "source-in" ;
maskCtx . fillStyle = isPatternFill ? fillColor . getPattern ( maskCtx , this , getCurrentTransformInverse ( ctx ) , PathType . FILL ) : fillColor ;
maskCtx . fillRect ( 0 , 0 , width , height ) ;
maskCtx . restore ( ) ;
2023-10-27 13:19:54 +02:00
ctx . save ( ) ;
2024-06-01 11:00:27 +01:00
ctx . transform ( ... transform ) ;
ctx . scale ( 1 , - 1 ) ;
drawImageAtIntegerCoords ( ctx , maskCanvas . canvas , 0 , 0 , width , height , 0 , - 1 , 1 , 1 ) ;
2023-10-27 13:19:54 +02:00
ctx . restore ( ) ;
}
2024-06-01 11:00:27 +01:00
this . compose ( ) ;
}
paintImageXObject ( objId ) {
if ( ! this . contentVisible ) {
return ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
const imgData = this . getObject ( objId ) ;
if ( ! imgData ) {
warn ( "Dependent image isn't ready yet" ) ;
return ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
this . paintInlineImageXObject ( imgData ) ;
}
paintImageXObjectRepeat ( objId , scaleX , scaleY , positions ) {
if ( ! this . contentVisible ) {
return ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
const imgData = this . getObject ( objId ) ;
if ( ! imgData ) {
warn ( "Dependent image isn't ready yet" ) ;
2023-10-27 13:19:54 +02:00
return ;
}
2024-06-01 11:00:27 +01:00
const width = imgData . width ;
const height = imgData . height ;
const map = [ ] ;
for ( let i = 0 , ii = positions . length ; i < ii ; i += 2 ) {
map . push ( {
transform : [ scaleX , 0 , 0 , scaleY , positions [ i ] , positions [ i + 1 ] ] ,
x : 0 ,
y : 0 ,
w : width ,
h : height
} ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
this . paintInlineImageXObjectGroup ( imgData , map ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
applyTransferMapsToCanvas ( ctx ) {
if ( this . current . transferMaps !== "none" ) {
ctx . filter = this . current . transferMaps ;
ctx . drawImage ( ctx . canvas , 0 , 0 ) ;
ctx . filter = "none" ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
return ctx . canvas ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
applyTransferMapsToBitmap ( imgData ) {
if ( this . current . transferMaps === "none" ) {
return imgData . bitmap ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
const {
bitmap ,
width ,
height
} = imgData ;
const tmpCanvas = this . cachedCanvases . getCanvas ( "inlineImage" , width , height ) ;
const tmpCtx = tmpCanvas . context ;
tmpCtx . filter = this . current . transferMaps ;
tmpCtx . drawImage ( bitmap , 0 , 0 ) ;
tmpCtx . filter = "none" ;
return tmpCanvas . canvas ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
paintInlineImageXObject ( imgData ) {
2023-10-27 13:19:54 +02:00
if ( ! this . contentVisible ) {
return ;
}
2024-06-01 11:00:27 +01:00
const width = imgData . width ;
const height = imgData . height ;
2023-10-27 13:19:54 +02:00
const ctx = this . ctx ;
this . save ( ) ;
2024-06-01 11:00:27 +01:00
if ( ! isNodeJS ) {
2023-10-27 13:19:54 +02:00
const {
2024-06-01 11:00:27 +01:00
filter
} = ctx ;
if ( filter !== "none" && filter !== "" ) {
ctx . filter = "none" ;
}
}
ctx . scale ( 1 / width , - 1 / height ) ;
let imgToPaint ;
if ( imgData . bitmap ) {
imgToPaint = this . applyTransferMapsToBitmap ( imgData ) ;
} else if ( typeof HTMLElement === "function" && imgData instanceof HTMLElement || ! imgData . data ) {
imgToPaint = imgData ;
2023-10-27 13:19:54 +02:00
} else {
2024-06-01 11:00:27 +01:00
const tmpCanvas = this . cachedCanvases . getCanvas ( "inlineImage" , width , height ) ;
const tmpCtx = tmpCanvas . context ;
putBinaryImageData ( tmpCtx , imgData ) ;
imgToPaint = this . applyTransferMapsToCanvas ( tmpCtx ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
const scaled = this . _scaleImage ( imgToPaint , getCurrentTransformInverse ( ctx ) ) ;
ctx . imageSmoothingEnabled = getImageSmoothingEnabled ( getCurrentTransform ( ctx ) , imgData . interpolate ) ;
drawImageAtIntegerCoords ( ctx , scaled . img , 0 , 0 , scaled . paintWidth , scaled . paintHeight , 0 , - height , width , height ) ;
this . compose ( ) ;
2023-10-27 13:19:54 +02:00
this . restore ( ) ;
}
2024-06-01 11:00:27 +01:00
paintInlineImageXObjectGroup ( imgData , map ) {
2023-10-27 13:19:54 +02:00
if ( ! this . contentVisible ) {
return ;
}
2024-06-01 11:00:27 +01:00
const ctx = this . ctx ;
let imgToPaint ;
if ( imgData . bitmap ) {
imgToPaint = imgData . bitmap ;
} else {
const w = imgData . width ;
const h = imgData . height ;
const tmpCanvas = this . cachedCanvases . getCanvas ( "inlineImage" , w , h ) ;
const tmpCtx = tmpCanvas . context ;
putBinaryImageData ( tmpCtx , imgData ) ;
imgToPaint = this . applyTransferMapsToCanvas ( tmpCtx ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
for ( const entry of map ) {
ctx . save ( ) ;
ctx . transform ( ... entry . transform ) ;
ctx . scale ( 1 , - 1 ) ;
drawImageAtIntegerCoords ( ctx , imgToPaint , entry . x , entry . y , entry . w , entry . h , 0 , - 1 , 1 , 1 ) ;
ctx . restore ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
this . compose ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
paintSolidColorImageMask ( ) {
2023-10-27 13:19:54 +02:00
if ( ! this . contentVisible ) {
return ;
}
2024-06-01 11:00:27 +01:00
this . ctx . fillRect ( 0 , 0 , 1 , 1 ) ;
this . compose ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
markPoint ( tag ) { }
markPointProps ( tag , properties ) { }
beginMarkedContent ( tag ) {
this . markedContentStack . push ( {
visible : true
} ) ;
}
beginMarkedContentProps ( tag , properties ) {
if ( tag === "OC" ) {
this . markedContentStack . push ( {
visible : this . optionalContentConfig . isVisible ( properties )
2023-10-27 13:19:54 +02:00
} ) ;
} else {
2024-06-01 11:00:27 +01:00
this . markedContentStack . push ( {
visible : true
} ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
this . contentVisible = this . isContentVisible ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
endMarkedContent ( ) {
this . markedContentStack . pop ( ) ;
this . contentVisible = this . isContentVisible ( ) ;
}
beginCompat ( ) { }
endCompat ( ) { }
consumePath ( clipBox ) {
const isEmpty = this . current . isEmptyClip ( ) ;
if ( this . pendingClip ) {
this . current . updateClipFromPath ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
if ( ! this . pendingClip ) {
this . compose ( clipBox ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
const ctx = this . ctx ;
if ( this . pendingClip ) {
if ( ! isEmpty ) {
if ( this . pendingClip === EO _CLIP ) {
ctx . clip ( "evenodd" ) ;
} else {
ctx . clip ( ) ;
}
}
this . pendingClip = null ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
this . current . startNewPathAndClipBox ( this . current . clipBox ) ;
ctx . beginPath ( ) ;
}
getSinglePixelWidth ( ) {
if ( ! this . _cachedGetSinglePixelWidth ) {
const m = getCurrentTransform ( this . ctx ) ;
if ( m [ 1 ] === 0 && m [ 2 ] === 0 ) {
this . _cachedGetSinglePixelWidth = 1 / Math . min ( Math . abs ( m [ 0 ] ) , Math . abs ( m [ 3 ] ) ) ;
2023-10-27 13:19:54 +02:00
} else {
2024-06-01 11:00:27 +01:00
const absDet = Math . abs ( m [ 0 ] * m [ 3 ] - m [ 2 ] * m [ 1 ] ) ;
const normX = Math . hypot ( m [ 0 ] , m [ 2 ] ) ;
const normY = Math . hypot ( m [ 1 ] , m [ 3 ] ) ;
this . _cachedGetSinglePixelWidth = Math . max ( normX , normY ) / absDet ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
return this . _cachedGetSinglePixelWidth ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
getScaleForStroking ( ) {
if ( this . _cachedScaleForStroking [ 0 ] === - 1 ) {
const {
lineWidth
} = this . current ;
const {
a ,
b ,
c ,
d
} = this . ctx . getTransform ( ) ;
let scaleX , scaleY ;
if ( b === 0 && c === 0 ) {
const normX = Math . abs ( a ) ;
const normY = Math . abs ( d ) ;
if ( normX === normY ) {
if ( lineWidth === 0 ) {
scaleX = scaleY = 1 / normX ;
} else {
const scaledLineWidth = normX * lineWidth ;
scaleX = scaleY = scaledLineWidth < 1 ? 1 / scaledLineWidth : 1 ;
}
} else if ( lineWidth === 0 ) {
scaleX = 1 / normX ;
scaleY = 1 / normY ;
} else {
const scaledXLineWidth = normX * lineWidth ;
const scaledYLineWidth = normY * lineWidth ;
scaleX = scaledXLineWidth < 1 ? 1 / scaledXLineWidth : 1 ;
scaleY = scaledYLineWidth < 1 ? 1 / scaledYLineWidth : 1 ;
}
} else {
const absDet = Math . abs ( a * d - b * c ) ;
const normX = Math . hypot ( a , b ) ;
const normY = Math . hypot ( c , d ) ;
if ( lineWidth === 0 ) {
scaleX = normY / absDet ;
scaleY = normX / absDet ;
} else {
const baseArea = lineWidth * absDet ;
scaleX = normY > baseArea ? normY / baseArea : 1 ;
scaleY = normX > baseArea ? normX / baseArea : 1 ;
}
}
this . _cachedScaleForStroking [ 0 ] = scaleX ;
this . _cachedScaleForStroking [ 1 ] = scaleY ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
return this . _cachedScaleForStroking ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
rescaleAndStroke ( saveRestore ) {
const {
ctx
} = this ;
const {
lineWidth
} = this . current ;
const [ scaleX , scaleY ] = this . getScaleForStroking ( ) ;
ctx . lineWidth = lineWidth || 1 ;
if ( scaleX === 1 && scaleY === 1 ) {
ctx . stroke ( ) ;
2023-10-27 13:19:54 +02:00
return ;
}
2024-06-01 11:00:27 +01:00
const dashes = ctx . getLineDash ( ) ;
if ( saveRestore ) {
ctx . save ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
ctx . scale ( scaleX , scaleY ) ;
if ( dashes . length > 0 ) {
const scale = Math . max ( scaleX , scaleY ) ;
ctx . setLineDash ( dashes . map ( x => x / scale ) ) ;
ctx . lineDashOffset /= scale ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
ctx . stroke ( ) ;
if ( saveRestore ) {
2023-10-27 13:19:54 +02:00
ctx . restore ( ) ;
}
}
2024-06-01 11:00:27 +01:00
isContentVisible ( ) {
for ( let i = this . markedContentStack . length - 1 ; i >= 0 ; i -- ) {
if ( ! this . markedContentStack [ i ] . visible ) {
return false ;
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
return true ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
}
for ( const op in OPS ) {
if ( CanvasGraphics . prototype [ op ] !== undefined ) {
CanvasGraphics . prototype [ OPS [ op ] ] = CanvasGraphics . prototype [ op ] ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
}
; // CONCATENATED MODULE: ./src/display/worker_options.js
class GlobalWorkerOptions {
static # port = null ;
static # src = "" ;
static get workerPort ( ) {
return this . # port ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
static set workerPort ( val ) {
if ( ! ( typeof Worker !== "undefined" && val instanceof Worker ) && val !== null ) {
throw new Error ( "Invalid `workerPort` type." ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
this . # port = val ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
static get workerSrc ( ) {
return this . # src ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
static set workerSrc ( val ) {
if ( typeof val !== "string" ) {
throw new Error ( "Invalid `workerSrc` type." ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
this . # src = val ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
}
; // CONCATENATED MODULE: ./src/shared/message_handler.js
2024-06-18 20:06:52 +02:00
2024-06-01 11:00:27 +01:00
const CallbackKind = {
UNKNOWN : 0 ,
DATA : 1 ,
ERROR : 2
} ;
const StreamKind = {
UNKNOWN : 0 ,
CANCEL : 1 ,
CANCEL _COMPLETE : 2 ,
CLOSE : 3 ,
ENQUEUE : 4 ,
ERROR : 5 ,
PULL : 6 ,
PULL _COMPLETE : 7 ,
START _COMPLETE : 8
} ;
function wrapReason ( reason ) {
if ( ! ( reason instanceof Error || typeof reason === "object" && reason !== null ) ) {
unreachable ( 'wrapReason: Expected "reason" to be a (possibly cloned) Error.' ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
switch ( reason . name ) {
case "AbortException" :
return new AbortException ( reason . message ) ;
case "MissingPDFException" :
return new MissingPDFException ( reason . message ) ;
case "PasswordException" :
return new PasswordException ( reason . message , reason . code ) ;
case "UnexpectedResponseException" :
return new UnexpectedResponseException ( reason . message , reason . status ) ;
case "UnknownErrorException" :
return new UnknownErrorException ( reason . message , reason . details ) ;
default :
return new UnknownErrorException ( reason . message , reason . toString ( ) ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
}
class MessageHandler {
constructor ( sourceName , targetName , comObj ) {
this . sourceName = sourceName ;
this . targetName = targetName ;
this . comObj = comObj ;
this . callbackId = 1 ;
this . streamId = 1 ;
this . streamSinks = Object . create ( null ) ;
this . streamControllers = Object . create ( null ) ;
this . callbackCapabilities = Object . create ( null ) ;
this . actionHandler = Object . create ( null ) ;
this . _onComObjOnMessage = event => {
const data = event . data ;
if ( data . targetName !== this . sourceName ) {
return ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
if ( data . stream ) {
this . # processStreamMessage ( data ) ;
return ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
if ( data . callback ) {
const callbackId = data . callbackId ;
const capability = this . callbackCapabilities [ callbackId ] ;
if ( ! capability ) {
throw new Error ( ` Cannot resolve callback ${ callbackId } ` ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
delete this . callbackCapabilities [ callbackId ] ;
if ( data . callback === CallbackKind . DATA ) {
capability . resolve ( data . data ) ;
} else if ( data . callback === CallbackKind . ERROR ) {
capability . reject ( wrapReason ( data . reason ) ) ;
2023-10-27 13:19:54 +02:00
} else {
2024-06-01 11:00:27 +01:00
throw new Error ( "Unexpected callback case" ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
return ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
const action = this . actionHandler [ data . action ] ;
if ( ! action ) {
throw new Error ( ` Unknown action from worker: ${ data . action } ` ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
if ( data . callbackId ) {
const cbSourceName = this . sourceName ;
const cbTargetName = data . sourceName ;
new Promise ( function ( resolve ) {
resolve ( action ( data . data ) ) ;
} ) . then ( function ( result ) {
comObj . postMessage ( {
sourceName : cbSourceName ,
targetName : cbTargetName ,
callback : CallbackKind . DATA ,
callbackId : data . callbackId ,
data : result
} ) ;
} , function ( reason ) {
comObj . postMessage ( {
sourceName : cbSourceName ,
targetName : cbTargetName ,
callback : CallbackKind . ERROR ,
callbackId : data . callbackId ,
reason : wrapReason ( reason )
} ) ;
} ) ;
return ;
}
if ( data . streamId ) {
this . # createStreamSink ( data ) ;
return ;
}
action ( data . data ) ;
} ;
comObj . addEventListener ( "message" , this . _onComObjOnMessage ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
on ( actionName , handler ) {
const ah = this . actionHandler ;
if ( ah [ actionName ] ) {
throw new Error ( ` There is already an actionName called " ${ actionName } " ` ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
ah [ actionName ] = handler ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
send ( actionName , data , transfers ) {
this . comObj . postMessage ( {
sourceName : this . sourceName ,
targetName : this . targetName ,
action : actionName ,
data
} , transfers ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
sendWithPromise ( actionName , data , transfers ) {
const callbackId = this . callbackId ++ ;
const capability = Promise . withResolvers ( ) ;
this . callbackCapabilities [ callbackId ] = capability ;
try {
this . comObj . postMessage ( {
sourceName : this . sourceName ,
targetName : this . targetName ,
action : actionName ,
callbackId ,
data
} , transfers ) ;
} catch ( ex ) {
capability . reject ( ex ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
return capability . promise ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
sendWithStream ( actionName , data , queueingStrategy , transfers ) {
const streamId = this . streamId ++ ,
sourceName = this . sourceName ,
targetName = this . targetName ,
comObj = this . comObj ;
return new ReadableStream ( {
start : controller => {
const startCapability = Promise . withResolvers ( ) ;
this . streamControllers [ streamId ] = {
controller ,
startCall : startCapability ,
pullCall : null ,
cancelCall : null ,
isClosed : false
} ;
comObj . postMessage ( {
sourceName ,
targetName ,
action : actionName ,
streamId ,
data ,
desiredSize : controller . desiredSize
} , transfers ) ;
return startCapability . promise ;
} ,
pull : controller => {
const pullCapability = Promise . withResolvers ( ) ;
this . streamControllers [ streamId ] . pullCall = pullCapability ;
comObj . postMessage ( {
sourceName ,
targetName ,
stream : StreamKind . PULL ,
streamId ,
desiredSize : controller . desiredSize
} ) ;
return pullCapability . promise ;
} ,
cancel : reason => {
assert ( reason instanceof Error , "cancel must have a valid reason" ) ;
const cancelCapability = Promise . withResolvers ( ) ;
this . streamControllers [ streamId ] . cancelCall = cancelCapability ;
this . streamControllers [ streamId ] . isClosed = true ;
comObj . postMessage ( {
sourceName ,
targetName ,
stream : StreamKind . CANCEL ,
streamId ,
reason : wrapReason ( reason )
} ) ;
return cancelCapability . promise ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
} , queueingStrategy ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
# createStreamSink ( data ) {
const streamId = data . streamId ,
sourceName = this . sourceName ,
targetName = data . sourceName ,
comObj = this . comObj ;
const self = this ,
action = this . actionHandler [ data . action ] ;
const streamSink = {
enqueue ( chunk , size = 1 , transfers ) {
if ( this . isCancelled ) {
return ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
const lastDesiredSize = this . desiredSize ;
this . desiredSize -= size ;
if ( lastDesiredSize > 0 && this . desiredSize <= 0 ) {
this . sinkCapability = Promise . withResolvers ( ) ;
this . ready = this . sinkCapability . promise ;
}
comObj . postMessage ( {
sourceName ,
targetName ,
stream : StreamKind . ENQUEUE ,
streamId ,
chunk
} , transfers ) ;
} ,
close ( ) {
if ( this . isCancelled ) {
return ;
}
this . isCancelled = true ;
comObj . postMessage ( {
sourceName ,
targetName ,
stream : StreamKind . CLOSE ,
streamId
} ) ;
delete self . streamSinks [ streamId ] ;
} ,
error ( reason ) {
assert ( reason instanceof Error , "error must have a valid reason" ) ;
if ( this . isCancelled ) {
return ;
}
this . isCancelled = true ;
comObj . postMessage ( {
sourceName ,
targetName ,
stream : StreamKind . ERROR ,
streamId ,
reason : wrapReason ( reason )
} ) ;
} ,
sinkCapability : Promise . withResolvers ( ) ,
onPull : null ,
onCancel : null ,
isCancelled : false ,
desiredSize : data . desiredSize ,
ready : null
2023-10-27 13:19:54 +02:00
} ;
2024-06-01 11:00:27 +01:00
streamSink . sinkCapability . resolve ( ) ;
streamSink . ready = streamSink . sinkCapability . promise ;
this . streamSinks [ streamId ] = streamSink ;
new Promise ( function ( resolve ) {
resolve ( action ( data . data , streamSink ) ) ;
} ) . then ( function ( ) {
comObj . postMessage ( {
sourceName ,
targetName ,
stream : StreamKind . START _COMPLETE ,
streamId ,
success : true
} ) ;
} , function ( reason ) {
comObj . postMessage ( {
sourceName ,
targetName ,
stream : StreamKind . START _COMPLETE ,
streamId ,
reason : wrapReason ( reason )
} ) ;
} ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
# processStreamMessage ( data ) {
const streamId = data . streamId ,
sourceName = this . sourceName ,
targetName = data . sourceName ,
comObj = this . comObj ;
const streamController = this . streamControllers [ streamId ] ,
streamSink = this . streamSinks [ streamId ] ;
switch ( data . stream ) {
case StreamKind . START _COMPLETE :
if ( data . success ) {
streamController . startCall . resolve ( ) ;
} else {
streamController . startCall . reject ( wrapReason ( data . reason ) ) ;
}
break ;
case StreamKind . PULL _COMPLETE :
if ( data . success ) {
streamController . pullCall . resolve ( ) ;
} else {
streamController . pullCall . reject ( wrapReason ( data . reason ) ) ;
}
break ;
case StreamKind . PULL :
if ( ! streamSink ) {
comObj . postMessage ( {
sourceName ,
targetName ,
stream : StreamKind . PULL _COMPLETE ,
streamId ,
success : true
} ) ;
break ;
}
if ( streamSink . desiredSize <= 0 && data . desiredSize > 0 ) {
streamSink . sinkCapability . resolve ( ) ;
}
streamSink . desiredSize = data . desiredSize ;
new Promise ( function ( resolve ) {
resolve ( streamSink . onPull ? . ( ) ) ;
} ) . then ( function ( ) {
comObj . postMessage ( {
sourceName ,
targetName ,
stream : StreamKind . PULL _COMPLETE ,
streamId ,
success : true
} ) ;
} , function ( reason ) {
comObj . postMessage ( {
sourceName ,
targetName ,
stream : StreamKind . PULL _COMPLETE ,
streamId ,
reason : wrapReason ( reason )
} ) ;
} ) ;
break ;
case StreamKind . ENQUEUE :
assert ( streamController , "enqueue should have stream controller" ) ;
if ( streamController . isClosed ) {
break ;
}
streamController . controller . enqueue ( data . chunk ) ;
break ;
case StreamKind . CLOSE :
assert ( streamController , "close should have stream controller" ) ;
if ( streamController . isClosed ) {
break ;
}
streamController . isClosed = true ;
streamController . controller . close ( ) ;
this . # deleteStreamController ( streamController , streamId ) ;
break ;
case StreamKind . ERROR :
assert ( streamController , "error should have stream controller" ) ;
streamController . controller . error ( wrapReason ( data . reason ) ) ;
this . # deleteStreamController ( streamController , streamId ) ;
break ;
case StreamKind . CANCEL _COMPLETE :
if ( data . success ) {
streamController . cancelCall . resolve ( ) ;
} else {
streamController . cancelCall . reject ( wrapReason ( data . reason ) ) ;
}
this . # deleteStreamController ( streamController , streamId ) ;
break ;
case StreamKind . CANCEL :
if ( ! streamSink ) {
break ;
}
new Promise ( function ( resolve ) {
resolve ( streamSink . onCancel ? . ( wrapReason ( data . reason ) ) ) ;
} ) . then ( function ( ) {
comObj . postMessage ( {
sourceName ,
targetName ,
stream : StreamKind . CANCEL _COMPLETE ,
streamId ,
success : true
} ) ;
} , function ( reason ) {
comObj . postMessage ( {
sourceName ,
targetName ,
stream : StreamKind . CANCEL _COMPLETE ,
streamId ,
reason : wrapReason ( reason )
} ) ;
} ) ;
streamSink . sinkCapability . reject ( wrapReason ( data . reason ) ) ;
streamSink . isCancelled = true ;
delete this . streamSinks [ streamId ] ;
break ;
default :
throw new Error ( "Unexpected stream case" ) ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
async # deleteStreamController ( streamController , streamId ) {
await Promise . allSettled ( [ streamController . startCall ? . promise , streamController . pullCall ? . promise , streamController . cancelCall ? . promise ] ) ;
delete this . streamControllers [ streamId ] ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
destroy ( ) {
this . comObj . removeEventListener ( "message" , this . _onComObjOnMessage ) ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
; // CONCATENATED MODULE: ./src/display/metadata.js
class Metadata {
# metadataMap ;
# data ;
constructor ( {
parsedData ,
rawData
} ) {
this . # metadataMap = parsedData ;
this . # data = rawData ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
getRaw ( ) {
return this . # data ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
get ( name ) {
return this . # metadataMap . get ( name ) ? ? null ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
getAll ( ) {
return objectFromMap ( this . # metadataMap ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
has ( name ) {
return this . # metadataMap . has ( name ) ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
; // CONCATENATED MODULE: ./src/display/optional_content_config.js
2023-10-27 13:19:54 +02:00
2024-06-01 11:00:27 +01:00
const INTERNAL = Symbol ( "INTERNAL" ) ;
class OptionalContentGroup {
# isDisplay = false ;
# isPrint = false ;
# userSet = false ;
# visible = true ;
constructor ( renderingIntent , {
name ,
intent ,
usage
} ) {
this . # isDisplay = ! ! ( renderingIntent & RenderingIntentFlag . DISPLAY ) ;
this . # isPrint = ! ! ( renderingIntent & RenderingIntentFlag . PRINT ) ;
this . name = name ;
this . intent = intent ;
this . usage = usage ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
get visible ( ) {
if ( this . # userSet ) {
return this . # visible ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
if ( ! this . # visible ) {
return false ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
const {
print ,
view
} = this . usage ;
if ( this . # isDisplay ) {
return view ? . viewState !== "OFF" ;
} else if ( this . # isPrint ) {
return print ? . printState !== "OFF" ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
return true ;
}
_setVisible ( internal , visible , userSet = false ) {
if ( internal !== INTERNAL ) {
unreachable ( "Internal method `_setVisible` called." ) ;
}
this . # userSet = userSet ;
this . # visible = visible ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
class OptionalContentConfig {
# cachedGetHash = null ;
# groups = new Map ( ) ;
# initialHash = null ;
# order = null ;
constructor ( data , renderingIntent = RenderingIntentFlag . DISPLAY ) {
this . renderingIntent = renderingIntent ;
this . name = null ;
this . creator = null ;
if ( data === null ) {
return ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
this . name = data . name ;
this . creator = data . creator ;
this . # order = data . order ;
for ( const group of data . groups ) {
this . # groups . set ( group . id , new OptionalContentGroup ( renderingIntent , group ) ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
if ( data . baseState === "OFF" ) {
for ( const group of this . # groups . values ( ) ) {
group . _setVisible ( INTERNAL , false ) ;
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
for ( const on of data . on ) {
this . # groups . get ( on ) . _setVisible ( INTERNAL , true ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
for ( const off of data . off ) {
this . # groups . get ( off ) . _setVisible ( INTERNAL , false ) ;
}
this . # initialHash = this . getHash ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
# evaluateVisibilityExpression ( array ) {
const length = array . length ;
if ( length < 2 ) {
return true ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
const operator = array [ 0 ] ;
for ( let i = 1 ; i < length ; i ++ ) {
const element = array [ i ] ;
let state ;
if ( Array . isArray ( element ) ) {
state = this . # evaluateVisibilityExpression ( element ) ;
} else if ( this . # groups . has ( element ) ) {
state = this . # groups . get ( element ) . visible ;
} else {
warn ( ` Optional content group not found: ${ element } ` ) ;
return true ;
}
switch ( operator ) {
case "And" :
if ( ! state ) {
return false ;
}
break ;
case "Or" :
if ( state ) {
return true ;
}
break ;
case "Not" :
return ! state ;
default :
return true ;
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
return operator === "And" ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
isVisible ( group ) {
if ( this . # groups . size === 0 ) {
return true ;
}
if ( ! group ) {
info ( "Optional content group not defined." ) ;
return true ;
}
if ( group . type === "OCG" ) {
if ( ! this . # groups . has ( group . id ) ) {
warn ( ` Optional content group not found: ${ group . id } ` ) ;
return true ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
return this . # groups . get ( group . id ) . visible ;
} else if ( group . type === "OCMD" ) {
if ( group . expression ) {
return this . # evaluateVisibilityExpression ( group . expression ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
if ( ! group . policy || group . policy === "AnyOn" ) {
for ( const id of group . ids ) {
if ( ! this . # groups . has ( id ) ) {
warn ( ` Optional content group not found: ${ id } ` ) ;
return true ;
}
if ( this . # groups . get ( id ) . visible ) {
return true ;
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
return false ;
} else if ( group . policy === "AllOn" ) {
for ( const id of group . ids ) {
if ( ! this . # groups . has ( id ) ) {
warn ( ` Optional content group not found: ${ id } ` ) ;
return true ;
}
if ( ! this . # groups . get ( id ) . visible ) {
return false ;
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
return true ;
} else if ( group . policy === "AnyOff" ) {
for ( const id of group . ids ) {
if ( ! this . # groups . has ( id ) ) {
warn ( ` Optional content group not found: ${ id } ` ) ;
return true ;
}
if ( ! this . # groups . get ( id ) . visible ) {
return true ;
}
}
return false ;
} else if ( group . policy === "AllOff" ) {
for ( const id of group . ids ) {
if ( ! this . # groups . has ( id ) ) {
warn ( ` Optional content group not found: ${ id } ` ) ;
return true ;
}
if ( this . # groups . get ( id ) . visible ) {
return false ;
}
}
return true ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
warn ( ` Unknown optional content policy ${ group . policy } . ` ) ;
return true ;
}
warn ( ` Unknown group type ${ group . type } . ` ) ;
return true ;
}
setVisibility ( id , visible = true ) {
const group = this . # groups . get ( id ) ;
if ( ! group ) {
warn ( ` Optional content group not found: ${ id } ` ) ;
return ;
}
group . _setVisible ( INTERNAL , ! ! visible , true ) ;
this . # cachedGetHash = null ;
}
setOCGState ( {
state ,
preserveRB
} ) {
let operator ;
for ( const elem of state ) {
switch ( elem ) {
case "ON" :
case "OFF" :
case "Toggle" :
operator = elem ;
continue ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
const group = this . # groups . get ( elem ) ;
if ( ! group ) {
continue ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
switch ( operator ) {
case "ON" :
group . _setVisible ( INTERNAL , true ) ;
break ;
case "OFF" :
group . _setVisible ( INTERNAL , false ) ;
break ;
case "Toggle" :
group . _setVisible ( INTERNAL , ! group . visible ) ;
break ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
this . # cachedGetHash = null ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
get hasInitialVisibility ( ) {
return this . # initialHash === null || this . getHash ( ) === this . # initialHash ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
getOrder ( ) {
if ( ! this . # groups . size ) {
return null ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
if ( this . # order ) {
return this . # order . slice ( ) ;
}
return [ ... this . # groups . keys ( ) ] ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
getGroups ( ) {
return this . # groups . size > 0 ? objectFromMap ( this . # groups ) : null ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
getGroup ( id ) {
return this . # groups . get ( id ) || null ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
getHash ( ) {
if ( this . # cachedGetHash !== null ) {
return this . # cachedGetHash ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
const hash = new MurmurHash3 _64 ( ) ;
for ( const [ id , group ] of this . # groups ) {
hash . update ( ` ${ id } : ${ group . visible } ` ) ;
}
return this . # cachedGetHash = hash . hexdigest ( ) ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
; // CONCATENATED MODULE: ./src/display/transport_stream.js
2023-10-27 13:19:54 +02:00
2024-06-18 20:06:52 +02:00
2024-06-01 11:00:27 +01:00
class PDFDataTransportStream {
constructor ( pdfDataRangeTransport , {
disableRange = false ,
disableStream = false
2023-10-27 13:19:54 +02:00
} ) {
2024-06-01 11:00:27 +01:00
assert ( pdfDataRangeTransport , 'PDFDataTransportStream - missing required "pdfDataRangeTransport" argument.' ) ;
const {
length ,
initialData ,
progressiveDone ,
contentDispositionFilename
} = pdfDataRangeTransport ;
this . _queuedChunks = [ ] ;
this . _progressiveDone = progressiveDone ;
this . _contentDispositionFilename = contentDispositionFilename ;
if ( initialData ? . length > 0 ) {
const buffer = initialData instanceof Uint8Array && initialData . byteLength === initialData . buffer . byteLength ? initialData . buffer : new Uint8Array ( initialData ) . buffer ;
this . _queuedChunks . push ( buffer ) ;
}
this . _pdfDataRangeTransport = pdfDataRangeTransport ;
this . _isStreamingSupported = ! disableStream ;
this . _isRangeSupported = ! disableRange ;
this . _contentLength = length ;
this . _fullRequestReader = null ;
this . _rangeReaders = [ ] ;
pdfDataRangeTransport . addRangeListener ( ( begin , chunk ) => {
this . _onReceiveData ( {
begin ,
chunk
} ) ;
} ) ;
pdfDataRangeTransport . addProgressListener ( ( loaded , total ) => {
this . _onProgress ( {
loaded ,
total
} ) ;
} ) ;
pdfDataRangeTransport . addProgressiveReadListener ( chunk => {
this . _onReceiveData ( {
chunk
} ) ;
} ) ;
pdfDataRangeTransport . addProgressiveDoneListener ( ( ) => {
this . _onProgressiveDone ( ) ;
} ) ;
pdfDataRangeTransport . transportReady ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
_onReceiveData ( {
begin ,
chunk
} ) {
const buffer = chunk instanceof Uint8Array && chunk . byteLength === chunk . buffer . byteLength ? chunk . buffer : new Uint8Array ( chunk ) . buffer ;
if ( begin === undefined ) {
if ( this . _fullRequestReader ) {
this . _fullRequestReader . _enqueue ( buffer ) ;
} else {
this . _queuedChunks . push ( buffer ) ;
}
} else {
const found = this . _rangeReaders . some ( function ( rangeReader ) {
if ( rangeReader . _begin !== begin ) {
return false ;
}
rangeReader . _enqueue ( buffer ) ;
return true ;
} ) ;
assert ( found , "_onReceiveData - no `PDFDataTransportStreamRangeReader` instance found." ) ;
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
get _progressiveDataLength ( ) {
return this . _fullRequestReader ? . _loaded ? ? 0 ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
_onProgress ( evt ) {
if ( evt . total === undefined ) {
this . _rangeReaders [ 0 ] ? . onProgress ? . ( {
loaded : evt . loaded
} ) ;
} else {
this . _fullRequestReader ? . onProgress ? . ( {
loaded : evt . loaded ,
total : evt . total
} ) ;
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
_onProgressiveDone ( ) {
this . _fullRequestReader ? . progressiveDone ( ) ;
this . _progressiveDone = true ;
2023-10-27 13:19:54 +02:00
}
_removeRangeReader ( reader ) {
const i = this . _rangeReaders . indexOf ( reader ) ;
if ( i >= 0 ) {
this . _rangeReaders . splice ( i , 1 ) ;
}
}
getFullReader ( ) {
2024-06-01 11:00:27 +01:00
assert ( ! this . _fullRequestReader , "PDFDataTransportStream.getFullReader can only be called once." ) ;
2023-10-27 13:19:54 +02:00
const queuedChunks = this . _queuedChunks ;
this . _queuedChunks = null ;
return new PDFDataTransportStreamReader ( this , queuedChunks , this . _progressiveDone , this . _contentDispositionFilename ) ;
}
getRangeReader ( begin , end ) {
if ( end <= this . _progressiveDataLength ) {
return null ;
}
const reader = new PDFDataTransportStreamRangeReader ( this , begin , end ) ;
this . _pdfDataRangeTransport . requestDataRange ( begin , end ) ;
this . _rangeReaders . push ( reader ) ;
return reader ;
}
cancelAllRequests ( reason ) {
this . _fullRequestReader ? . cancel ( reason ) ;
for ( const reader of this . _rangeReaders . slice ( 0 ) ) {
reader . cancel ( reason ) ;
}
this . _pdfDataRangeTransport . abort ( ) ;
}
}
class PDFDataTransportStreamReader {
constructor ( stream , queuedChunks , progressiveDone = false , contentDispositionFilename = null ) {
this . _stream = stream ;
this . _done = progressiveDone || false ;
2024-06-01 11:00:27 +01:00
this . _filename = isPdfFile ( contentDispositionFilename ) ? contentDispositionFilename : null ;
2023-10-27 13:19:54 +02:00
this . _queuedChunks = queuedChunks || [ ] ;
this . _loaded = 0 ;
for ( const chunk of this . _queuedChunks ) {
this . _loaded += chunk . byteLength ;
}
this . _requests = [ ] ;
this . _headersReady = Promise . resolve ( ) ;
stream . _fullRequestReader = this ;
this . onProgress = null ;
}
_enqueue ( chunk ) {
if ( this . _done ) {
return ;
}
if ( this . _requests . length > 0 ) {
const requestCapability = this . _requests . shift ( ) ;
requestCapability . resolve ( {
value : chunk ,
done : false
} ) ;
} else {
this . _queuedChunks . push ( chunk ) ;
}
this . _loaded += chunk . byteLength ;
}
get headersReady ( ) {
return this . _headersReady ;
}
get filename ( ) {
return this . _filename ;
}
get isRangeSupported ( ) {
return this . _stream . _isRangeSupported ;
}
get isStreamingSupported ( ) {
return this . _stream . _isStreamingSupported ;
}
get contentLength ( ) {
return this . _stream . _contentLength ;
}
async read ( ) {
if ( this . _queuedChunks . length > 0 ) {
const chunk = this . _queuedChunks . shift ( ) ;
return {
value : chunk ,
done : false
} ;
}
if ( this . _done ) {
return {
value : undefined ,
done : true
} ;
}
2024-06-01 11:00:27 +01:00
const requestCapability = Promise . withResolvers ( ) ;
2023-10-27 13:19:54 +02:00
this . _requests . push ( requestCapability ) ;
return requestCapability . promise ;
}
cancel ( reason ) {
this . _done = true ;
for ( const requestCapability of this . _requests ) {
requestCapability . resolve ( {
value : undefined ,
done : true
} ) ;
}
this . _requests . length = 0 ;
}
progressiveDone ( ) {
if ( this . _done ) {
return ;
}
this . _done = true ;
}
}
class PDFDataTransportStreamRangeReader {
constructor ( stream , begin , end ) {
this . _stream = stream ;
this . _begin = begin ;
this . _end = end ;
this . _queuedChunk = null ;
this . _requests = [ ] ;
this . _done = false ;
this . onProgress = null ;
}
_enqueue ( chunk ) {
if ( this . _done ) {
return ;
}
if ( this . _requests . length === 0 ) {
this . _queuedChunk = chunk ;
} else {
const requestsCapability = this . _requests . shift ( ) ;
requestsCapability . resolve ( {
value : chunk ,
done : false
} ) ;
for ( const requestCapability of this . _requests ) {
requestCapability . resolve ( {
value : undefined ,
done : true
} ) ;
}
this . _requests . length = 0 ;
}
this . _done = true ;
this . _stream . _removeRangeReader ( this ) ;
}
get isStreamingSupported ( ) {
return false ;
}
async read ( ) {
if ( this . _queuedChunk ) {
const chunk = this . _queuedChunk ;
this . _queuedChunk = null ;
return {
value : chunk ,
done : false
} ;
}
if ( this . _done ) {
return {
value : undefined ,
done : true
} ;
}
2024-06-01 11:00:27 +01:00
const requestCapability = Promise . withResolvers ( ) ;
2023-10-27 13:19:54 +02:00
this . _requests . push ( requestCapability ) ;
return requestCapability . promise ;
}
cancel ( reason ) {
this . _done = true ;
for ( const requestCapability of this . _requests ) {
requestCapability . resolve ( {
value : undefined ,
done : true
} ) ;
}
this . _requests . length = 0 ;
this . _stream . _removeRangeReader ( this ) ;
}
}
2024-06-01 11:00:27 +01:00
; // CONCATENATED MODULE: ./src/display/content_disposition.js
2023-10-27 13:19:54 +02:00
2024-06-18 20:06:52 +02:00
2024-06-01 11:00:27 +01:00
function getFilenameFromContentDispositionHeader ( contentDisposition ) {
let needsEncodingFixup = true ;
let tmp = toParamRegExp ( "filename\\*" , "i" ) . exec ( contentDisposition ) ;
if ( tmp ) {
tmp = tmp [ 1 ] ;
let filename = rfc2616unquote ( tmp ) ;
filename = unescape ( filename ) ;
filename = rfc5987decode ( filename ) ;
filename = rfc2047decode ( filename ) ;
return fixupEncoding ( filename ) ;
}
tmp = rfc2231getparam ( contentDisposition ) ;
if ( tmp ) {
const filename = rfc2047decode ( tmp ) ;
return fixupEncoding ( filename ) ;
}
tmp = toParamRegExp ( "filename" , "i" ) . exec ( contentDisposition ) ;
if ( tmp ) {
tmp = tmp [ 1 ] ;
let filename = rfc2616unquote ( tmp ) ;
filename = rfc2047decode ( filename ) ;
return fixupEncoding ( filename ) ;
}
function toParamRegExp ( attributePattern , flags ) {
return new RegExp ( "(?:^|;)\\s*" + attributePattern + "\\s*=\\s*" + "(" + '[^";\\s][^;\\s]*' + "|" + '"(?:[^"\\\\]|\\\\"?)+"?' + ")" , flags ) ;
}
function textdecode ( encoding , value ) {
if ( encoding ) {
if ( ! /^[\x00-\xFF]+$/ . test ( value ) ) {
return value ;
}
try {
const decoder = new TextDecoder ( encoding , {
fatal : true
} ) ;
const buffer = stringToBytes ( value ) ;
value = decoder . decode ( buffer ) ;
needsEncodingFixup = false ;
} catch { }
}
return value ;
}
function fixupEncoding ( value ) {
if ( needsEncodingFixup && /[\x80-\xff]/ . test ( value ) ) {
value = textdecode ( "utf-8" , value ) ;
if ( needsEncodingFixup ) {
value = textdecode ( "iso-8859-1" , value ) ;
}
}
return value ;
}
function rfc2231getparam ( contentDispositionStr ) {
const matches = [ ] ;
let match ;
const iter = toParamRegExp ( "filename\\*((?!0\\d)\\d+)(\\*?)" , "ig" ) ;
while ( ( match = iter . exec ( contentDispositionStr ) ) !== null ) {
let [ , n , quot , part ] = match ;
n = parseInt ( n , 10 ) ;
if ( n in matches ) {
if ( n === 0 ) {
break ;
}
continue ;
}
matches [ n ] = [ quot , part ] ;
}
const parts = [ ] ;
for ( let n = 0 ; n < matches . length ; ++ n ) {
if ( ! ( n in matches ) ) {
break ;
}
let [ quot , part ] = matches [ n ] ;
part = rfc2616unquote ( part ) ;
if ( quot ) {
part = unescape ( part ) ;
if ( n === 0 ) {
part = rfc5987decode ( part ) ;
}
}
parts . push ( part ) ;
}
return parts . join ( "" ) ;
}
function rfc2616unquote ( value ) {
if ( value . startsWith ( '"' ) ) {
const parts = value . slice ( 1 ) . split ( '\\"' ) ;
for ( let i = 0 ; i < parts . length ; ++ i ) {
const quotindex = parts [ i ] . indexOf ( '"' ) ;
if ( quotindex !== - 1 ) {
parts [ i ] = parts [ i ] . slice ( 0 , quotindex ) ;
parts . length = i + 1 ;
}
parts [ i ] = parts [ i ] . replaceAll ( /\\(.)/g , "$1" ) ;
}
value = parts . join ( '"' ) ;
}
return value ;
}
function rfc5987decode ( extvalue ) {
const encodingend = extvalue . indexOf ( "'" ) ;
if ( encodingend === - 1 ) {
return extvalue ;
}
const encoding = extvalue . slice ( 0 , encodingend ) ;
const langvalue = extvalue . slice ( encodingend + 1 ) ;
const value = langvalue . replace ( /^[^']*'/ , "" ) ;
return textdecode ( encoding , value ) ;
}
function rfc2047decode ( value ) {
if ( ! value . startsWith ( "=?" ) || /[\x00-\x19\x80-\xff]/ . test ( value ) ) {
return value ;
}
return value . replaceAll ( /=\?([\w-]*)\?([QqBb])\?((?:[^?]|\?(?!=))*)\?=/g , function ( matches , charset , encoding , text ) {
if ( encoding === "q" || encoding === "Q" ) {
text = text . replaceAll ( "_" , " " ) ;
text = text . replaceAll ( /=([0-9a-fA-F]{2})/g , function ( match , hex ) {
return String . fromCharCode ( parseInt ( hex , 16 ) ) ;
} ) ;
return textdecode ( charset , text ) ;
}
try {
text = atob ( text ) ;
} catch { }
return textdecode ( charset , text ) ;
} ) ;
}
return "" ;
}
; // CONCATENATED MODULE: ./src/display/network_utils.js
function validateRangeRequestCapabilities ( {
getResponseHeader ,
isHttp ,
rangeChunkSize ,
disableRange
} ) {
const returnValues = {
allowRangeRequests : false ,
suggestedLength : undefined
} ;
const length = parseInt ( getResponseHeader ( "Content-Length" ) , 10 ) ;
if ( ! Number . isInteger ( length ) ) {
return returnValues ;
}
returnValues . suggestedLength = length ;
if ( length <= 2 * rangeChunkSize ) {
return returnValues ;
}
if ( disableRange || ! isHttp ) {
return returnValues ;
}
if ( getResponseHeader ( "Accept-Ranges" ) !== "bytes" ) {
return returnValues ;
}
const contentEncoding = getResponseHeader ( "Content-Encoding" ) || "identity" ;
if ( contentEncoding !== "identity" ) {
return returnValues ;
}
returnValues . allowRangeRequests = true ;
return returnValues ;
}
function extractFilenameFromHeader ( getResponseHeader ) {
const contentDisposition = getResponseHeader ( "Content-Disposition" ) ;
if ( contentDisposition ) {
let filename = getFilenameFromContentDispositionHeader ( contentDisposition ) ;
if ( filename . includes ( "%" ) ) {
try {
filename = decodeURIComponent ( filename ) ;
} catch { }
}
if ( isPdfFile ( filename ) ) {
return filename ;
}
}
return null ;
}
function createResponseStatusError ( status , url ) {
if ( status === 404 || status === 0 && url . startsWith ( "file:" ) ) {
return new MissingPDFException ( 'Missing PDF "' + url + '".' ) ;
}
return new UnexpectedResponseException ( ` Unexpected server response ( ${ status } ) while retrieving PDF " ${ url } ". ` , status ) ;
}
function validateResponseStatus ( status ) {
return status === 200 || status === 206 ;
}
; // CONCATENATED MODULE: ./src/display/fetch_stream.js
2024-06-18 20:06:52 +02:00
2024-06-01 11:00:27 +01:00
function createFetchOptions ( headers , withCredentials , abortController ) {
return {
method : "GET" ,
headers ,
signal : abortController . signal ,
mode : "cors" ,
credentials : withCredentials ? "include" : "same-origin" ,
redirect : "follow"
} ;
}
function createHeaders ( httpHeaders ) {
2023-10-27 13:19:54 +02:00
const headers = new Headers ( ) ;
for ( const property in httpHeaders ) {
const value = httpHeaders [ property ] ;
if ( value === undefined ) {
continue ;
}
headers . append ( property , value ) ;
}
return headers ;
}
function getArrayBuffer ( val ) {
if ( val instanceof Uint8Array ) {
return val . buffer ;
}
if ( val instanceof ArrayBuffer ) {
return val ;
}
2024-06-01 11:00:27 +01:00
warn ( ` getArrayBuffer - unexpected data format: ${ val } ` ) ;
2023-10-27 13:19:54 +02:00
return new Uint8Array ( val ) . buffer ;
}
class PDFFetchStream {
constructor ( source ) {
this . source = source ;
this . isHttp = /^https?:/i . test ( source . url ) ;
this . httpHeaders = this . isHttp && source . httpHeaders || { } ;
this . _fullRequestReader = null ;
this . _rangeRequestReaders = [ ] ;
}
get _progressiveDataLength ( ) {
return this . _fullRequestReader ? . _loaded ? ? 0 ;
}
getFullReader ( ) {
2024-06-01 11:00:27 +01:00
assert ( ! this . _fullRequestReader , "PDFFetchStream.getFullReader can only be called once." ) ;
2023-10-27 13:19:54 +02:00
this . _fullRequestReader = new PDFFetchStreamReader ( this ) ;
return this . _fullRequestReader ;
}
getRangeReader ( begin , end ) {
if ( end <= this . _progressiveDataLength ) {
return null ;
}
const reader = new PDFFetchStreamRangeReader ( this , begin , end ) ;
this . _rangeRequestReaders . push ( reader ) ;
return reader ;
}
cancelAllRequests ( reason ) {
this . _fullRequestReader ? . cancel ( reason ) ;
for ( const reader of this . _rangeRequestReaders . slice ( 0 ) ) {
reader . cancel ( reason ) ;
}
}
}
class PDFFetchStreamReader {
constructor ( stream ) {
this . _stream = stream ;
this . _reader = null ;
this . _loaded = 0 ;
this . _filename = null ;
const source = stream . source ;
this . _withCredentials = source . withCredentials || false ;
this . _contentLength = source . length ;
2024-06-01 11:00:27 +01:00
this . _headersCapability = Promise . withResolvers ( ) ;
2023-10-27 13:19:54 +02:00
this . _disableRange = source . disableRange || false ;
this . _rangeChunkSize = source . rangeChunkSize ;
if ( ! this . _rangeChunkSize && ! this . _disableRange ) {
this . _disableRange = true ;
}
this . _abortController = new AbortController ( ) ;
this . _isStreamingSupported = ! source . disableStream ;
this . _isRangeSupported = ! source . disableRange ;
this . _headers = createHeaders ( this . _stream . httpHeaders ) ;
const url = source . url ;
fetch ( url , createFetchOptions ( this . _headers , this . _withCredentials , this . _abortController ) ) . then ( response => {
2024-06-01 11:00:27 +01:00
if ( ! validateResponseStatus ( response . status ) ) {
throw createResponseStatusError ( response . status , url ) ;
2023-10-27 13:19:54 +02:00
}
this . _reader = response . body . getReader ( ) ;
this . _headersCapability . resolve ( ) ;
2024-06-01 11:00:27 +01:00
const getResponseHeader = name => response . headers . get ( name ) ;
2023-10-27 13:19:54 +02:00
const {
allowRangeRequests ,
suggestedLength
2024-06-01 11:00:27 +01:00
} = validateRangeRequestCapabilities ( {
2023-10-27 13:19:54 +02:00
getResponseHeader ,
isHttp : this . _stream . isHttp ,
rangeChunkSize : this . _rangeChunkSize ,
disableRange : this . _disableRange
} ) ;
this . _isRangeSupported = allowRangeRequests ;
this . _contentLength = suggestedLength || this . _contentLength ;
2024-06-01 11:00:27 +01:00
this . _filename = extractFilenameFromHeader ( getResponseHeader ) ;
2023-10-27 13:19:54 +02:00
if ( ! this . _isStreamingSupported && this . _isRangeSupported ) {
2024-06-01 11:00:27 +01:00
this . cancel ( new AbortException ( "Streaming is disabled." ) ) ;
2023-10-27 13:19:54 +02:00
}
} ) . catch ( this . _headersCapability . reject ) ;
this . onProgress = null ;
}
get headersReady ( ) {
return this . _headersCapability . promise ;
}
get filename ( ) {
return this . _filename ;
}
get contentLength ( ) {
return this . _contentLength ;
}
get isRangeSupported ( ) {
return this . _isRangeSupported ;
}
get isStreamingSupported ( ) {
return this . _isStreamingSupported ;
}
async read ( ) {
await this . _headersCapability . promise ;
const {
value ,
done
} = await this . _reader . read ( ) ;
if ( done ) {
return {
value ,
done
} ;
}
this . _loaded += value . byteLength ;
this . onProgress ? . ( {
loaded : this . _loaded ,
total : this . _contentLength
} ) ;
return {
value : getArrayBuffer ( value ) ,
done : false
} ;
}
cancel ( reason ) {
this . _reader ? . cancel ( reason ) ;
this . _abortController . abort ( ) ;
}
}
class PDFFetchStreamRangeReader {
constructor ( stream , begin , end ) {
this . _stream = stream ;
this . _reader = null ;
this . _loaded = 0 ;
const source = stream . source ;
this . _withCredentials = source . withCredentials || false ;
2024-06-01 11:00:27 +01:00
this . _readCapability = Promise . withResolvers ( ) ;
2023-10-27 13:19:54 +02:00
this . _isStreamingSupported = ! source . disableStream ;
this . _abortController = new AbortController ( ) ;
this . _headers = createHeaders ( this . _stream . httpHeaders ) ;
this . _headers . append ( "Range" , ` bytes= ${ begin } - ${ end - 1 } ` ) ;
const url = source . url ;
fetch ( url , createFetchOptions ( this . _headers , this . _withCredentials , this . _abortController ) ) . then ( response => {
2024-06-01 11:00:27 +01:00
if ( ! validateResponseStatus ( response . status ) ) {
throw createResponseStatusError ( response . status , url ) ;
2023-10-27 13:19:54 +02:00
}
this . _readCapability . resolve ( ) ;
this . _reader = response . body . getReader ( ) ;
} ) . catch ( this . _readCapability . reject ) ;
this . onProgress = null ;
}
get isStreamingSupported ( ) {
return this . _isStreamingSupported ;
}
async read ( ) {
await this . _readCapability . promise ;
const {
value ,
done
} = await this . _reader . read ( ) ;
if ( done ) {
return {
value ,
done
} ;
}
this . _loaded += value . byteLength ;
this . onProgress ? . ( {
loaded : this . _loaded
} ) ;
return {
value : getArrayBuffer ( value ) ,
done : false
} ;
}
cancel ( reason ) {
this . _reader ? . cancel ( reason ) ;
this . _abortController . abort ( ) ;
}
}
2024-06-01 11:00:27 +01:00
; // CONCATENATED MODULE: ./src/display/network.js
2023-10-27 13:19:54 +02:00
2024-06-18 20:06:52 +02:00
2024-06-01 11:00:27 +01:00
const OK _RESPONSE = 200 ;
const PARTIAL _CONTENT _RESPONSE = 206 ;
function network _getArrayBuffer ( xhr ) {
const data = xhr . response ;
if ( typeof data !== "string" ) {
return data ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
return stringToBytes ( data ) . buffer ;
}
class NetworkManager {
constructor ( url , args = { } ) {
this . url = url ;
this . isHttp = /^https?:/i . test ( url ) ;
this . httpHeaders = this . isHttp && args . httpHeaders || Object . create ( null ) ;
this . withCredentials = args . withCredentials || false ;
this . currXhrId = 0 ;
this . pendingRequests = Object . create ( null ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
requestRange ( begin , end , listeners ) {
const args = {
begin ,
end
} ;
for ( const prop in listeners ) {
args [ prop ] = listeners [ prop ] ;
}
return this . request ( args ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
requestFull ( listeners ) {
return this . request ( listeners ) ;
2023-10-27 13:19:54 +02:00
}
request ( args ) {
const xhr = new XMLHttpRequest ( ) ;
const xhrId = this . currXhrId ++ ;
const pendingRequest = this . pendingRequests [ xhrId ] = {
xhr
} ;
xhr . open ( "GET" , this . url ) ;
xhr . withCredentials = this . withCredentials ;
for ( const property in this . httpHeaders ) {
const value = this . httpHeaders [ property ] ;
if ( value === undefined ) {
continue ;
}
xhr . setRequestHeader ( property , value ) ;
}
if ( this . isHttp && "begin" in args && "end" in args ) {
xhr . setRequestHeader ( "Range" , ` bytes= ${ args . begin } - ${ args . end - 1 } ` ) ;
pendingRequest . expectedStatus = PARTIAL _CONTENT _RESPONSE ;
} else {
pendingRequest . expectedStatus = OK _RESPONSE ;
}
xhr . responseType = "arraybuffer" ;
if ( args . onError ) {
xhr . onerror = function ( evt ) {
args . onError ( xhr . status ) ;
} ;
}
xhr . onreadystatechange = this . onStateChange . bind ( this , xhrId ) ;
xhr . onprogress = this . onProgress . bind ( this , xhrId ) ;
pendingRequest . onHeadersReceived = args . onHeadersReceived ;
pendingRequest . onDone = args . onDone ;
pendingRequest . onError = args . onError ;
pendingRequest . onProgress = args . onProgress ;
xhr . send ( null ) ;
return xhrId ;
}
onProgress ( xhrId , evt ) {
const pendingRequest = this . pendingRequests [ xhrId ] ;
if ( ! pendingRequest ) {
return ;
}
pendingRequest . onProgress ? . ( evt ) ;
}
onStateChange ( xhrId , evt ) {
const pendingRequest = this . pendingRequests [ xhrId ] ;
if ( ! pendingRequest ) {
return ;
}
const xhr = pendingRequest . xhr ;
if ( xhr . readyState >= 2 && pendingRequest . onHeadersReceived ) {
pendingRequest . onHeadersReceived ( ) ;
delete pendingRequest . onHeadersReceived ;
}
if ( xhr . readyState !== 4 ) {
return ;
}
if ( ! ( xhrId in this . pendingRequests ) ) {
return ;
}
delete this . pendingRequests [ xhrId ] ;
if ( xhr . status === 0 && this . isHttp ) {
pendingRequest . onError ? . ( xhr . status ) ;
return ;
}
const xhrStatus = xhr . status || OK _RESPONSE ;
const ok _response _on _range _request = xhrStatus === OK _RESPONSE && pendingRequest . expectedStatus === PARTIAL _CONTENT _RESPONSE ;
if ( ! ok _response _on _range _request && xhrStatus !== pendingRequest . expectedStatus ) {
pendingRequest . onError ? . ( xhr . status ) ;
return ;
}
2024-06-01 11:00:27 +01:00
const chunk = network _getArrayBuffer ( xhr ) ;
2023-10-27 13:19:54 +02:00
if ( xhrStatus === PARTIAL _CONTENT _RESPONSE ) {
const rangeHeader = xhr . getResponseHeader ( "Content-Range" ) ;
const matches = /bytes (\d+)-(\d+)\/(\d+)/ . exec ( rangeHeader ) ;
pendingRequest . onDone ( {
begin : parseInt ( matches [ 1 ] , 10 ) ,
chunk
} ) ;
} else if ( chunk ) {
pendingRequest . onDone ( {
begin : 0 ,
chunk
} ) ;
} else {
pendingRequest . onError ? . ( xhr . status ) ;
}
}
getRequestXhr ( xhrId ) {
return this . pendingRequests [ xhrId ] . xhr ;
}
isPendingRequest ( xhrId ) {
return xhrId in this . pendingRequests ;
}
abortRequest ( xhrId ) {
const xhr = this . pendingRequests [ xhrId ] . xhr ;
delete this . pendingRequests [ xhrId ] ;
xhr . abort ( ) ;
}
}
class PDFNetworkStream {
constructor ( source ) {
this . _source = source ;
this . _manager = new NetworkManager ( source . url , {
httpHeaders : source . httpHeaders ,
withCredentials : source . withCredentials
} ) ;
this . _rangeChunkSize = source . rangeChunkSize ;
this . _fullRequestReader = null ;
this . _rangeRequestReaders = [ ] ;
}
_onRangeRequestReaderClosed ( reader ) {
const i = this . _rangeRequestReaders . indexOf ( reader ) ;
if ( i >= 0 ) {
this . _rangeRequestReaders . splice ( i , 1 ) ;
}
}
getFullReader ( ) {
2024-06-01 11:00:27 +01:00
assert ( ! this . _fullRequestReader , "PDFNetworkStream.getFullReader can only be called once." ) ;
2023-10-27 13:19:54 +02:00
this . _fullRequestReader = new PDFNetworkStreamFullRequestReader ( this . _manager , this . _source ) ;
return this . _fullRequestReader ;
}
getRangeReader ( begin , end ) {
const reader = new PDFNetworkStreamRangeRequestReader ( this . _manager , begin , end ) ;
reader . onClosed = this . _onRangeRequestReaderClosed . bind ( this ) ;
this . _rangeRequestReaders . push ( reader ) ;
return reader ;
}
cancelAllRequests ( reason ) {
this . _fullRequestReader ? . cancel ( reason ) ;
for ( const reader of this . _rangeRequestReaders . slice ( 0 ) ) {
reader . cancel ( reason ) ;
}
}
}
class PDFNetworkStreamFullRequestReader {
constructor ( manager , source ) {
this . _manager = manager ;
const args = {
onHeadersReceived : this . _onHeadersReceived . bind ( this ) ,
onDone : this . _onDone . bind ( this ) ,
onError : this . _onError . bind ( this ) ,
onProgress : this . _onProgress . bind ( this )
} ;
this . _url = source . url ;
this . _fullRequestId = manager . requestFull ( args ) ;
2024-06-01 11:00:27 +01:00
this . _headersReceivedCapability = Promise . withResolvers ( ) ;
2023-10-27 13:19:54 +02:00
this . _disableRange = source . disableRange || false ;
this . _contentLength = source . length ;
this . _rangeChunkSize = source . rangeChunkSize ;
if ( ! this . _rangeChunkSize && ! this . _disableRange ) {
this . _disableRange = true ;
}
this . _isStreamingSupported = false ;
this . _isRangeSupported = false ;
this . _cachedChunks = [ ] ;
this . _requests = [ ] ;
this . _done = false ;
this . _storedError = undefined ;
this . _filename = null ;
this . onProgress = null ;
}
_onHeadersReceived ( ) {
const fullRequestXhrId = this . _fullRequestId ;
const fullRequestXhr = this . _manager . getRequestXhr ( fullRequestXhrId ) ;
2024-06-01 11:00:27 +01:00
const getResponseHeader = name => fullRequestXhr . getResponseHeader ( name ) ;
2023-10-27 13:19:54 +02:00
const {
allowRangeRequests ,
suggestedLength
2024-06-01 11:00:27 +01:00
} = validateRangeRequestCapabilities ( {
2023-10-27 13:19:54 +02:00
getResponseHeader ,
isHttp : this . _manager . isHttp ,
rangeChunkSize : this . _rangeChunkSize ,
disableRange : this . _disableRange
} ) ;
if ( allowRangeRequests ) {
this . _isRangeSupported = true ;
}
this . _contentLength = suggestedLength || this . _contentLength ;
2024-06-01 11:00:27 +01:00
this . _filename = extractFilenameFromHeader ( getResponseHeader ) ;
2023-10-27 13:19:54 +02:00
if ( this . _isRangeSupported ) {
this . _manager . abortRequest ( fullRequestXhrId ) ;
}
this . _headersReceivedCapability . resolve ( ) ;
}
_onDone ( data ) {
if ( data ) {
if ( this . _requests . length > 0 ) {
const requestCapability = this . _requests . shift ( ) ;
requestCapability . resolve ( {
value : data . chunk ,
done : false
} ) ;
} else {
this . _cachedChunks . push ( data . chunk ) ;
}
}
this . _done = true ;
if ( this . _cachedChunks . length > 0 ) {
return ;
}
for ( const requestCapability of this . _requests ) {
requestCapability . resolve ( {
value : undefined ,
done : true
} ) ;
}
this . _requests . length = 0 ;
}
_onError ( status ) {
2024-06-01 11:00:27 +01:00
this . _storedError = createResponseStatusError ( status , this . _url ) ;
2023-10-27 13:19:54 +02:00
this . _headersReceivedCapability . reject ( this . _storedError ) ;
for ( const requestCapability of this . _requests ) {
requestCapability . reject ( this . _storedError ) ;
}
this . _requests . length = 0 ;
this . _cachedChunks . length = 0 ;
}
_onProgress ( evt ) {
this . onProgress ? . ( {
loaded : evt . loaded ,
total : evt . lengthComputable ? evt . total : this . _contentLength
} ) ;
}
get filename ( ) {
return this . _filename ;
}
get isRangeSupported ( ) {
return this . _isRangeSupported ;
}
get isStreamingSupported ( ) {
return this . _isStreamingSupported ;
}
get contentLength ( ) {
return this . _contentLength ;
}
get headersReady ( ) {
return this . _headersReceivedCapability . promise ;
}
async read ( ) {
if ( this . _storedError ) {
throw this . _storedError ;
}
if ( this . _cachedChunks . length > 0 ) {
const chunk = this . _cachedChunks . shift ( ) ;
return {
value : chunk ,
done : false
} ;
}
if ( this . _done ) {
return {
value : undefined ,
done : true
} ;
}
2024-06-01 11:00:27 +01:00
const requestCapability = Promise . withResolvers ( ) ;
2023-10-27 13:19:54 +02:00
this . _requests . push ( requestCapability ) ;
return requestCapability . promise ;
}
cancel ( reason ) {
this . _done = true ;
this . _headersReceivedCapability . reject ( reason ) ;
for ( const requestCapability of this . _requests ) {
requestCapability . resolve ( {
value : undefined ,
done : true
} ) ;
}
this . _requests . length = 0 ;
if ( this . _manager . isPendingRequest ( this . _fullRequestId ) ) {
this . _manager . abortRequest ( this . _fullRequestId ) ;
}
this . _fullRequestReader = null ;
}
}
class PDFNetworkStreamRangeRequestReader {
constructor ( manager , begin , end ) {
this . _manager = manager ;
const args = {
onDone : this . _onDone . bind ( this ) ,
onError : this . _onError . bind ( this ) ,
onProgress : this . _onProgress . bind ( this )
} ;
this . _url = manager . url ;
this . _requestId = manager . requestRange ( begin , end , args ) ;
this . _requests = [ ] ;
this . _queuedChunk = null ;
this . _done = false ;
this . _storedError = undefined ;
this . onProgress = null ;
this . onClosed = null ;
}
_close ( ) {
this . onClosed ? . ( this ) ;
}
_onDone ( data ) {
const chunk = data . chunk ;
if ( this . _requests . length > 0 ) {
const requestCapability = this . _requests . shift ( ) ;
requestCapability . resolve ( {
value : chunk ,
done : false
} ) ;
} else {
this . _queuedChunk = chunk ;
}
this . _done = true ;
for ( const requestCapability of this . _requests ) {
requestCapability . resolve ( {
value : undefined ,
done : true
} ) ;
}
this . _requests . length = 0 ;
this . _close ( ) ;
}
_onError ( status ) {
2024-06-01 11:00:27 +01:00
this . _storedError = createResponseStatusError ( status , this . _url ) ;
2023-10-27 13:19:54 +02:00
for ( const requestCapability of this . _requests ) {
requestCapability . reject ( this . _storedError ) ;
}
this . _requests . length = 0 ;
this . _queuedChunk = null ;
}
_onProgress ( evt ) {
if ( ! this . isStreamingSupported ) {
this . onProgress ? . ( {
loaded : evt . loaded
} ) ;
}
}
get isStreamingSupported ( ) {
return false ;
}
async read ( ) {
if ( this . _storedError ) {
throw this . _storedError ;
}
if ( this . _queuedChunk !== null ) {
const chunk = this . _queuedChunk ;
this . _queuedChunk = null ;
return {
value : chunk ,
done : false
} ;
}
if ( this . _done ) {
return {
value : undefined ,
done : true
} ;
}
2024-06-01 11:00:27 +01:00
const requestCapability = Promise . withResolvers ( ) ;
2023-10-27 13:19:54 +02:00
this . _requests . push ( requestCapability ) ;
return requestCapability . promise ;
}
cancel ( reason ) {
this . _done = true ;
for ( const requestCapability of this . _requests ) {
requestCapability . resolve ( {
value : undefined ,
done : true
} ) ;
}
this . _requests . length = 0 ;
if ( this . _manager . isPendingRequest ( this . _requestId ) ) {
this . _manager . abortRequest ( this . _requestId ) ;
}
this . _close ( ) ;
}
}
2024-06-01 11:00:27 +01:00
; // CONCATENATED MODULE: ./src/display/node_stream.js
2023-10-27 13:19:54 +02:00
2024-06-18 20:06:52 +02:00
2023-10-27 13:19:54 +02:00
const fileUriRegex = /^file:\/\/\/[a-zA-Z]:\// ;
function parseUrl ( sourceUrl ) {
2024-06-01 11:00:27 +01:00
const url = NodePackages . get ( "url" ) ;
2023-10-27 13:19:54 +02:00
const parsedUrl = url . parse ( sourceUrl ) ;
if ( parsedUrl . protocol === "file:" || parsedUrl . host ) {
return parsedUrl ;
}
if ( /^[a-z]:[/\\]/i . test ( sourceUrl ) ) {
return url . parse ( ` file:/// ${ sourceUrl } ` ) ;
}
if ( ! parsedUrl . host ) {
parsedUrl . protocol = "file:" ;
}
return parsedUrl ;
}
class PDFNodeStream {
constructor ( source ) {
this . source = source ;
this . url = parseUrl ( source . url ) ;
this . isHttp = this . url . protocol === "http:" || this . url . protocol === "https:" ;
this . isFsUrl = this . url . protocol === "file:" ;
this . httpHeaders = this . isHttp && source . httpHeaders || { } ;
this . _fullRequestReader = null ;
this . _rangeRequestReaders = [ ] ;
}
get _progressiveDataLength ( ) {
return this . _fullRequestReader ? . _loaded ? ? 0 ;
}
getFullReader ( ) {
2024-06-01 11:00:27 +01:00
assert ( ! this . _fullRequestReader , "PDFNodeStream.getFullReader can only be called once." ) ;
2023-10-27 13:19:54 +02:00
this . _fullRequestReader = this . isFsUrl ? new PDFNodeStreamFsFullReader ( this ) : new PDFNodeStreamFullReader ( this ) ;
return this . _fullRequestReader ;
}
getRangeReader ( start , end ) {
if ( end <= this . _progressiveDataLength ) {
return null ;
}
const rangeReader = this . isFsUrl ? new PDFNodeStreamFsRangeReader ( this , start , end ) : new PDFNodeStreamRangeReader ( this , start , end ) ;
this . _rangeRequestReaders . push ( rangeReader ) ;
return rangeReader ;
}
cancelAllRequests ( reason ) {
this . _fullRequestReader ? . cancel ( reason ) ;
for ( const reader of this . _rangeRequestReaders . slice ( 0 ) ) {
reader . cancel ( reason ) ;
}
}
}
class BaseFullReader {
constructor ( stream ) {
this . _url = stream . url ;
this . _done = false ;
this . _storedError = null ;
this . onProgress = null ;
const source = stream . source ;
this . _contentLength = source . length ;
this . _loaded = 0 ;
this . _filename = null ;
this . _disableRange = source . disableRange || false ;
this . _rangeChunkSize = source . rangeChunkSize ;
if ( ! this . _rangeChunkSize && ! this . _disableRange ) {
this . _disableRange = true ;
}
this . _isStreamingSupported = ! source . disableStream ;
this . _isRangeSupported = ! source . disableRange ;
this . _readableStream = null ;
2024-06-01 11:00:27 +01:00
this . _readCapability = Promise . withResolvers ( ) ;
this . _headersCapability = Promise . withResolvers ( ) ;
2023-10-27 13:19:54 +02:00
}
get headersReady ( ) {
return this . _headersCapability . promise ;
}
get filename ( ) {
return this . _filename ;
}
get contentLength ( ) {
return this . _contentLength ;
}
get isRangeSupported ( ) {
return this . _isRangeSupported ;
}
get isStreamingSupported ( ) {
return this . _isStreamingSupported ;
}
async read ( ) {
await this . _readCapability . promise ;
if ( this . _done ) {
return {
value : undefined ,
done : true
} ;
}
if ( this . _storedError ) {
throw this . _storedError ;
}
const chunk = this . _readableStream . read ( ) ;
if ( chunk === null ) {
2024-06-01 11:00:27 +01:00
this . _readCapability = Promise . withResolvers ( ) ;
2023-10-27 13:19:54 +02:00
return this . read ( ) ;
}
this . _loaded += chunk . length ;
this . onProgress ? . ( {
loaded : this . _loaded ,
total : this . _contentLength
} ) ;
const buffer = new Uint8Array ( chunk ) . buffer ;
return {
value : buffer ,
done : false
} ;
}
cancel ( reason ) {
if ( ! this . _readableStream ) {
this . _error ( reason ) ;
return ;
}
this . _readableStream . destroy ( reason ) ;
}
_error ( reason ) {
this . _storedError = reason ;
this . _readCapability . resolve ( ) ;
}
_setReadableStream ( readableStream ) {
this . _readableStream = readableStream ;
readableStream . on ( "readable" , ( ) => {
this . _readCapability . resolve ( ) ;
} ) ;
readableStream . on ( "end" , ( ) => {
readableStream . destroy ( ) ;
this . _done = true ;
this . _readCapability . resolve ( ) ;
} ) ;
readableStream . on ( "error" , reason => {
this . _error ( reason ) ;
} ) ;
if ( ! this . _isStreamingSupported && this . _isRangeSupported ) {
2024-06-01 11:00:27 +01:00
this . _error ( new AbortException ( "streaming is disabled" ) ) ;
2023-10-27 13:19:54 +02:00
}
if ( this . _storedError ) {
this . _readableStream . destroy ( this . _storedError ) ;
}
}
}
class BaseRangeReader {
constructor ( stream ) {
this . _url = stream . url ;
this . _done = false ;
this . _storedError = null ;
this . onProgress = null ;
this . _loaded = 0 ;
this . _readableStream = null ;
2024-06-01 11:00:27 +01:00
this . _readCapability = Promise . withResolvers ( ) ;
2023-10-27 13:19:54 +02:00
const source = stream . source ;
this . _isStreamingSupported = ! source . disableStream ;
}
get isStreamingSupported ( ) {
return this . _isStreamingSupported ;
}
async read ( ) {
await this . _readCapability . promise ;
if ( this . _done ) {
return {
value : undefined ,
done : true
} ;
}
if ( this . _storedError ) {
throw this . _storedError ;
}
const chunk = this . _readableStream . read ( ) ;
if ( chunk === null ) {
2024-06-01 11:00:27 +01:00
this . _readCapability = Promise . withResolvers ( ) ;
2023-10-27 13:19:54 +02:00
return this . read ( ) ;
}
this . _loaded += chunk . length ;
this . onProgress ? . ( {
loaded : this . _loaded
} ) ;
const buffer = new Uint8Array ( chunk ) . buffer ;
return {
value : buffer ,
done : false
} ;
}
cancel ( reason ) {
if ( ! this . _readableStream ) {
this . _error ( reason ) ;
return ;
}
this . _readableStream . destroy ( reason ) ;
}
_error ( reason ) {
this . _storedError = reason ;
this . _readCapability . resolve ( ) ;
}
_setReadableStream ( readableStream ) {
this . _readableStream = readableStream ;
readableStream . on ( "readable" , ( ) => {
this . _readCapability . resolve ( ) ;
} ) ;
readableStream . on ( "end" , ( ) => {
readableStream . destroy ( ) ;
this . _done = true ;
this . _readCapability . resolve ( ) ;
} ) ;
readableStream . on ( "error" , reason => {
this . _error ( reason ) ;
} ) ;
if ( this . _storedError ) {
this . _readableStream . destroy ( this . _storedError ) ;
}
}
}
function createRequestOptions ( parsedUrl , headers ) {
return {
protocol : parsedUrl . protocol ,
auth : parsedUrl . auth ,
host : parsedUrl . hostname ,
port : parsedUrl . port ,
path : parsedUrl . path ,
method : "GET" ,
headers
} ;
}
class PDFNodeStreamFullReader extends BaseFullReader {
constructor ( stream ) {
super ( stream ) ;
const handleResponse = response => {
if ( response . statusCode === 404 ) {
2024-06-01 11:00:27 +01:00
const error = new MissingPDFException ( ` Missing PDF " ${ this . _url } ". ` ) ;
2023-10-27 13:19:54 +02:00
this . _storedError = error ;
this . _headersCapability . reject ( error ) ;
return ;
}
this . _headersCapability . resolve ( ) ;
this . _setReadableStream ( response ) ;
2024-06-01 11:00:27 +01:00
const getResponseHeader = name => this . _readableStream . headers [ name . toLowerCase ( ) ] ;
2023-10-27 13:19:54 +02:00
const {
allowRangeRequests ,
suggestedLength
2024-06-01 11:00:27 +01:00
} = validateRangeRequestCapabilities ( {
2023-10-27 13:19:54 +02:00
getResponseHeader ,
isHttp : stream . isHttp ,
rangeChunkSize : this . _rangeChunkSize ,
disableRange : this . _disableRange
} ) ;
this . _isRangeSupported = allowRangeRequests ;
this . _contentLength = suggestedLength || this . _contentLength ;
2024-06-01 11:00:27 +01:00
this . _filename = extractFilenameFromHeader ( getResponseHeader ) ;
2023-10-27 13:19:54 +02:00
} ;
this . _request = null ;
if ( this . _url . protocol === "http:" ) {
2024-06-01 11:00:27 +01:00
const http = NodePackages . get ( "http" ) ;
2023-10-27 13:19:54 +02:00
this . _request = http . request ( createRequestOptions ( this . _url , stream . httpHeaders ) , handleResponse ) ;
} else {
2024-06-01 11:00:27 +01:00
const https = NodePackages . get ( "https" ) ;
2023-10-27 13:19:54 +02:00
this . _request = https . request ( createRequestOptions ( this . _url , stream . httpHeaders ) , handleResponse ) ;
}
this . _request . on ( "error" , reason => {
this . _storedError = reason ;
this . _headersCapability . reject ( reason ) ;
} ) ;
this . _request . end ( ) ;
}
}
class PDFNodeStreamRangeReader extends BaseRangeReader {
constructor ( stream , start , end ) {
super ( stream ) ;
this . _httpHeaders = { } ;
for ( const property in stream . httpHeaders ) {
const value = stream . httpHeaders [ property ] ;
if ( value === undefined ) {
continue ;
}
this . _httpHeaders [ property ] = value ;
}
this . _httpHeaders . Range = ` bytes= ${ start } - ${ end - 1 } ` ;
const handleResponse = response => {
if ( response . statusCode === 404 ) {
2024-06-01 11:00:27 +01:00
const error = new MissingPDFException ( ` Missing PDF " ${ this . _url } ". ` ) ;
2023-10-27 13:19:54 +02:00
this . _storedError = error ;
return ;
}
this . _setReadableStream ( response ) ;
} ;
this . _request = null ;
if ( this . _url . protocol === "http:" ) {
2024-06-01 11:00:27 +01:00
const http = NodePackages . get ( "http" ) ;
2023-10-27 13:19:54 +02:00
this . _request = http . request ( createRequestOptions ( this . _url , this . _httpHeaders ) , handleResponse ) ;
} else {
2024-06-01 11:00:27 +01:00
const https = NodePackages . get ( "https" ) ;
2023-10-27 13:19:54 +02:00
this . _request = https . request ( createRequestOptions ( this . _url , this . _httpHeaders ) , handleResponse ) ;
}
this . _request . on ( "error" , reason => {
this . _storedError = reason ;
} ) ;
this . _request . end ( ) ;
}
}
class PDFNodeStreamFsFullReader extends BaseFullReader {
constructor ( stream ) {
super ( stream ) ;
let path = decodeURIComponent ( this . _url . path ) ;
if ( fileUriRegex . test ( this . _url . href ) ) {
path = path . replace ( /^\// , "" ) ;
}
2024-06-01 11:00:27 +01:00
const fs = NodePackages . get ( "fs" ) ;
fs . promises . lstat ( path ) . then ( stat => {
2023-10-27 13:19:54 +02:00
this . _contentLength = stat . size ;
this . _setReadableStream ( fs . createReadStream ( path ) ) ;
this . _headersCapability . resolve ( ) ;
2024-06-01 11:00:27 +01:00
} , error => {
if ( error . code === "ENOENT" ) {
error = new MissingPDFException ( ` Missing PDF " ${ path } ". ` ) ;
}
this . _storedError = error ;
this . _headersCapability . reject ( error ) ;
2023-10-27 13:19:54 +02:00
} ) ;
}
}
class PDFNodeStreamFsRangeReader extends BaseRangeReader {
constructor ( stream , start , end ) {
super ( stream ) ;
let path = decodeURIComponent ( this . _url . path ) ;
if ( fileUriRegex . test ( this . _url . href ) ) {
path = path . replace ( /^\// , "" ) ;
}
2024-06-01 11:00:27 +01:00
const fs = NodePackages . get ( "fs" ) ;
2023-10-27 13:19:54 +02:00
this . _setReadableStream ( fs . createReadStream ( path , {
start ,
end : end - 1
} ) ) ;
}
}
2024-06-01 11:00:27 +01:00
; // CONCATENATED MODULE: ./src/display/text_layer.js
2023-10-27 13:19:54 +02:00
2024-06-18 20:06:52 +02:00
2024-06-01 11:00:27 +01:00
const MAX _TEXT _DIVS _TO _RENDER = 100000 ;
const DEFAULT _FONT _SIZE = 30 ;
const DEFAULT _FONT _ASCENT = 0.8 ;
class TextLayer {
# capability = Promise . withResolvers ( ) ;
# container = null ;
# disableProcessItems = false ;
# fontInspectorEnabled = ! ! globalThis . FontInspector ? . enabled ;
# lang = null ;
# layoutTextParams = null ;
# pageHeight = 0 ;
# pageWidth = 0 ;
# reader = null ;
# rootContainer = null ;
# rotation = 0 ;
# scale = 0 ;
# styleCache = Object . create ( null ) ;
# textContentItemsStr = [ ] ;
# textContentSource = null ;
# textDivs = [ ] ;
# textDivProperties = new WeakMap ( ) ;
# transform = null ;
static # ascentCache = new Map ( ) ;
2024-06-02 09:12:22 +01:00
static # canvasContexts = new Map ( ) ;
2024-06-01 11:00:27 +01:00
static # pendingTextLayers = new Set ( ) ;
constructor ( {
textContentSource ,
container ,
viewport
} ) {
if ( textContentSource instanceof ReadableStream ) {
this . # textContentSource = textContentSource ;
} else if ( typeof textContentSource === "object" ) {
this . # textContentSource = new ReadableStream ( {
start ( controller ) {
controller . enqueue ( textContentSource ) ;
controller . close ( ) ;
2023-10-27 13:19:54 +02:00
}
} ) ;
} else {
2024-06-01 11:00:27 +01:00
throw new Error ( 'No "textContentSource" parameter specified.' ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
this . # container = this . # rootContainer = container ;
this . # scale = viewport . scale * ( globalThis . devicePixelRatio || 1 ) ;
this . # rotation = viewport . rotation ;
this . # layoutTextParams = {
prevFontSize : null ,
prevFontFamily : null ,
div : null ,
properties : null ,
ctx : null
} ;
const {
pageWidth ,
pageHeight ,
pageX ,
pageY
} = viewport . rawDims ;
this . # transform = [ 1 , 0 , 0 , - 1 , - pageX , pageY + pageHeight ] ;
this . # pageWidth = pageWidth ;
this . # pageHeight = pageHeight ;
setLayerDimensions ( container , viewport ) ;
this . # capability . promise . catch ( ( ) => { } ) . then ( ( ) => {
TextLayer . # pendingTextLayers . delete ( this ) ;
this . # layoutTextParams = null ;
this . # styleCache = null ;
2023-10-27 13:19:54 +02:00
} ) ;
}
2024-06-01 11:00:27 +01:00
render ( ) {
const pump = ( ) => {
this . # reader . read ( ) . then ( ( {
value ,
done
} ) => {
if ( done ) {
this . # capability . resolve ( ) ;
return ;
}
this . # lang ? ? = value . lang ;
Object . assign ( this . # styleCache , value . styles ) ;
this . # processItems ( value . items ) ;
pump ( ) ;
} , this . # capability . reject ) ;
} ;
this . # reader = this . # textContentSource . getReader ( ) ;
2024-06-02 09:12:22 +01:00
TextLayer . # pendingTextLayers . add ( this ) ;
2024-06-01 11:00:27 +01:00
pump ( ) ;
return this . # capability . promise ;
}
update ( {
viewport ,
onBefore = null
} ) {
const scale = viewport . scale * ( globalThis . devicePixelRatio || 1 ) ;
const rotation = viewport . rotation ;
if ( rotation !== this . # rotation ) {
onBefore ? . ( ) ;
this . # rotation = rotation ;
setLayerDimensions ( this . # rootContainer , {
rotation
2023-10-27 13:19:54 +02:00
} ) ;
}
2024-06-01 11:00:27 +01:00
if ( scale !== this . # scale ) {
onBefore ? . ( ) ;
this . # scale = scale ;
const params = {
prevFontSize : null ,
prevFontFamily : null ,
div : null ,
properties : null ,
ctx : TextLayer . # getCtx ( this . # lang )
} ;
for ( const div of this . # textDivs ) {
params . properties = this . # textDivProperties . get ( div ) ;
params . div = div ;
this . # layout ( params ) ;
2023-10-27 13:19:54 +02:00
}
}
}
2024-06-01 11:00:27 +01:00
cancel ( ) {
const abortEx = new AbortException ( "TextLayer task cancelled." ) ;
this . # reader ? . cancel ( abortEx ) . catch ( ( ) => { } ) ;
this . # reader = null ;
this . # capability . reject ( abortEx ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
get textDivs ( ) {
return this . # textDivs ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
get textContentItemsStr ( ) {
return this . # textContentItemsStr ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
# processItems ( items ) {
if ( this . # disableProcessItems ) {
2023-10-27 13:19:54 +02:00
return ;
}
2024-06-01 11:00:27 +01:00
this . # layoutTextParams . ctx || = TextLayer . # getCtx ( this . # lang ) ;
const textDivs = this . # textDivs ,
textContentItemsStr = this . # textContentItemsStr ;
for ( const item of items ) {
if ( textDivs . length > MAX _TEXT _DIVS _TO _RENDER ) {
warn ( "Ignoring additional textDivs for performance reasons." ) ;
this . # disableProcessItems = true ;
return ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
if ( item . str === undefined ) {
if ( item . type === "beginMarkedContentProps" || item . type === "beginMarkedContent" ) {
const parent = this . # container ;
this . # container = document . createElement ( "span" ) ;
this . # container . classList . add ( "markedContent" ) ;
if ( item . id !== null ) {
this . # container . setAttribute ( "id" , ` ${ item . id } ` ) ;
}
parent . append ( this . # container ) ;
} else if ( item . type === "endMarkedContent" ) {
this . # container = this . # container . parentNode ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
continue ;
}
textContentItemsStr . push ( item . str ) ;
this . # appendText ( item ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
}
# appendText ( geom ) {
const textDiv = document . createElement ( "span" ) ;
const textDivProperties = {
angle : 0 ,
canvasWidth : 0 ,
hasText : geom . str !== "" ,
hasEOL : geom . hasEOL ,
fontSize : 0
} ;
this . # textDivs . push ( textDiv ) ;
const tx = Util . transform ( this . # transform , geom . transform ) ;
let angle = Math . atan2 ( tx [ 1 ] , tx [ 0 ] ) ;
const style = this . # styleCache [ geom . fontName ] ;
if ( style . vertical ) {
angle += Math . PI / 2 ;
}
const fontFamily = this . # fontInspectorEnabled && style . fontSubstitution || style . fontFamily ;
const fontHeight = Math . hypot ( tx [ 2 ] , tx [ 3 ] ) ;
const fontAscent = fontHeight * TextLayer . # getAscent ( fontFamily , this . # lang ) ;
let left , top ;
if ( angle === 0 ) {
left = tx [ 4 ] ;
top = tx [ 5 ] - fontAscent ;
2023-10-27 13:19:54 +02:00
} else {
2024-06-01 11:00:27 +01:00
left = tx [ 4 ] + fontAscent * Math . sin ( angle ) ;
top = tx [ 5 ] - fontAscent * Math . cos ( angle ) ;
}
const scaleFactorStr = "calc(var(--scale-factor)*" ;
const divStyle = textDiv . style ;
if ( this . # container === this . # rootContainer ) {
divStyle . left = ` ${ ( 100 * left / this . # pageWidth ) . toFixed ( 2 ) } % ` ;
divStyle . top = ` ${ ( 100 * top / this . # pageHeight ) . toFixed ( 2 ) } % ` ;
2023-10-27 13:19:54 +02:00
} else {
2024-06-01 11:00:27 +01:00
divStyle . left = ` ${ scaleFactorStr } ${ left . toFixed ( 2 ) } px) ` ;
divStyle . top = ` ${ scaleFactorStr } ${ top . toFixed ( 2 ) } px) ` ;
}
divStyle . fontSize = ` ${ scaleFactorStr } ${ fontHeight . toFixed ( 2 ) } px) ` ;
divStyle . fontFamily = fontFamily ;
textDivProperties . fontSize = fontHeight ;
textDiv . setAttribute ( "role" , "presentation" ) ;
textDiv . textContent = geom . str ;
textDiv . dir = geom . dir ;
if ( this . # fontInspectorEnabled ) {
textDiv . dataset . fontName = style . fontSubstitutionLoadedName || geom . fontName ;
}
if ( angle !== 0 ) {
textDivProperties . angle = angle * ( 180 / Math . PI ) ;
}
let shouldScaleText = false ;
if ( geom . str . length > 1 ) {
shouldScaleText = true ;
} else if ( geom . str !== " " && geom . transform [ 0 ] !== geom . transform [ 3 ] ) {
const absScaleX = Math . abs ( geom . transform [ 0 ] ) ,
absScaleY = Math . abs ( geom . transform [ 3 ] ) ;
if ( absScaleX !== absScaleY && Math . max ( absScaleX , absScaleY ) / Math . min ( absScaleX , absScaleY ) > 1.5 ) {
shouldScaleText = true ;
}
}
if ( shouldScaleText ) {
textDivProperties . canvasWidth = style . vertical ? geom . height : geom . width ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
this . # textDivProperties . set ( textDiv , textDivProperties ) ;
this . # layoutTextParams . div = textDiv ;
this . # layoutTextParams . properties = textDivProperties ;
this . # layout ( this . # layoutTextParams ) ;
if ( textDivProperties . hasText ) {
this . # container . append ( textDiv ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
if ( textDivProperties . hasEOL ) {
const br = document . createElement ( "br" ) ;
br . setAttribute ( "role" , "presentation" ) ;
this . # container . append ( br ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
}
# layout ( params ) {
const {
div ,
properties ,
ctx ,
prevFontSize ,
prevFontFamily
} = params ;
const {
style
} = div ;
let transform = "" ;
if ( properties . canvasWidth !== 0 && properties . hasText ) {
const {
fontFamily
} = style ;
const {
canvasWidth ,
fontSize
} = properties ;
if ( prevFontSize !== fontSize || prevFontFamily !== fontFamily ) {
ctx . font = ` ${ fontSize * this . # scale } px ${ fontFamily } ` ;
params . prevFontSize = fontSize ;
params . prevFontFamily = fontFamily ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
const {
width
} = ctx . measureText ( div . textContent ) ;
if ( width > 0 ) {
transform = ` scaleX( ${ canvasWidth * this . # scale / width } ) ` ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
if ( properties . angle !== 0 ) {
transform = ` rotate( ${ properties . angle } deg) ${ transform } ` ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
if ( transform . length > 0 ) {
style . transform = transform ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
static cleanup ( ) {
if ( this . # pendingTextLayers . size > 0 ) {
return ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
this . # ascentCache . clear ( ) ;
2024-06-02 09:12:22 +01:00
for ( const {
canvas
} of this . # canvasContexts . values ( ) ) {
canvas . remove ( ) ;
}
this . # canvasContexts . clear ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
static # getCtx ( lang = null ) {
2024-06-02 09:12:22 +01:00
let canvasContext = this . # canvasContexts . get ( lang || = "" ) ;
if ( ! canvasContext ) {
2024-06-01 11:00:27 +01:00
const canvas = document . createElement ( "canvas" ) ;
canvas . className = "hiddenCanvasElement" ;
2024-06-02 09:12:22 +01:00
canvas . lang = lang ;
2024-06-01 11:00:27 +01:00
document . body . append ( canvas ) ;
2024-06-02 09:12:22 +01:00
canvasContext = canvas . getContext ( "2d" , {
2024-06-18 20:06:52 +02:00
alpha : false ,
willReadFrequently : true
2024-06-01 11:00:27 +01:00
} ) ;
2024-06-02 09:12:22 +01:00
this . # canvasContexts . set ( lang , canvasContext ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-02 09:12:22 +01:00
return canvasContext ;
2024-06-01 11:00:27 +01:00
}
static # getAscent ( fontFamily , lang ) {
const cachedAscent = this . # ascentCache . get ( fontFamily ) ;
if ( cachedAscent ) {
return cachedAscent ;
}
const ctx = this . # getCtx ( lang ) ;
const savedFont = ctx . font ;
ctx . canvas . width = ctx . canvas . height = DEFAULT _FONT _SIZE ;
ctx . font = ` ${ DEFAULT _FONT _SIZE } px ${ fontFamily } ` ;
const metrics = ctx . measureText ( "" ) ;
let ascent = metrics . fontBoundingBoxAscent ;
let descent = Math . abs ( metrics . fontBoundingBoxDescent ) ;
if ( ascent ) {
const ratio = ascent / ( ascent + descent ) ;
this . # ascentCache . set ( fontFamily , ratio ) ;
ctx . canvas . width = ctx . canvas . height = 0 ;
ctx . font = savedFont ;
return ratio ;
}
ctx . strokeStyle = "red" ;
ctx . clearRect ( 0 , 0 , DEFAULT _FONT _SIZE , DEFAULT _FONT _SIZE ) ;
ctx . strokeText ( "g" , 0 , 0 ) ;
let pixels = ctx . getImageData ( 0 , 0 , DEFAULT _FONT _SIZE , DEFAULT _FONT _SIZE ) . data ;
descent = 0 ;
for ( let i = pixels . length - 1 - 3 ; i >= 0 ; i -= 4 ) {
if ( pixels [ i ] > 0 ) {
descent = Math . ceil ( i / 4 / DEFAULT _FONT _SIZE ) ;
break ;
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
ctx . clearRect ( 0 , 0 , DEFAULT _FONT _SIZE , DEFAULT _FONT _SIZE ) ;
ctx . strokeText ( "A" , 0 , DEFAULT _FONT _SIZE ) ;
pixels = ctx . getImageData ( 0 , 0 , DEFAULT _FONT _SIZE , DEFAULT _FONT _SIZE ) . data ;
ascent = 0 ;
for ( let i = 0 , ii = pixels . length ; i < ii ; i += 4 ) {
if ( pixels [ i ] > 0 ) {
ascent = DEFAULT _FONT _SIZE - Math . floor ( i / 4 / DEFAULT _FONT _SIZE ) ;
break ;
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
ctx . canvas . width = ctx . canvas . height = 0 ;
ctx . font = savedFont ;
const ratio = ascent ? ascent / ( ascent + descent ) : DEFAULT _FONT _ASCENT ;
this . # ascentCache . set ( fontFamily , ratio ) ;
return ratio ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
}
function renderTextLayer ( ) {
deprecated ( "`renderTextLayer`, please use `TextLayer` instead." ) ;
const {
textContentSource ,
container ,
viewport ,
... rest
} = arguments [ 0 ] ;
const restKeys = Object . keys ( rest ) ;
if ( restKeys . length > 0 ) {
warn ( "Ignoring `renderTextLayer` parameters: " + restKeys . join ( ", " ) ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
const textLayer = new TextLayer ( {
textContentSource ,
container ,
viewport
} ) ;
const {
textDivs ,
textContentItemsStr
} = textLayer ;
const promise = textLayer . render ( ) ;
return {
promise ,
textDivs ,
textContentItemsStr
} ;
}
function updateTextLayer ( ) {
deprecated ( "`updateTextLayer`, please use `TextLayer` instead." ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
; // CONCATENATED MODULE: ./src/display/xfa_text.js
2024-06-18 20:06:52 +02:00
2023-10-27 13:19:54 +02:00
class XfaText {
static textContent ( xfa ) {
const items = [ ] ;
const output = {
items ,
styles : Object . create ( null )
} ;
function walk ( node ) {
if ( ! node ) {
return ;
}
let str = null ;
const name = node . name ;
if ( name === "#text" ) {
str = node . value ;
} else if ( ! XfaText . shouldBuildText ( name ) ) {
return ;
} else if ( node ? . attributes ? . textContent ) {
str = node . attributes . textContent ;
} else if ( node . value ) {
str = node . value ;
}
if ( str !== null ) {
items . push ( {
str
} ) ;
}
if ( ! node . children ) {
return ;
}
for ( const child of node . children ) {
walk ( child ) ;
}
}
walk ( xfa ) ;
return output ;
}
static shouldBuildText ( name ) {
return ! ( name === "textarea" || name === "input" || name === "option" || name === "select" ) ;
}
}
2024-06-01 11:00:27 +01:00
; // CONCATENATED MODULE: ./src/display/api.js
2023-10-27 13:19:54 +02:00
2024-06-01 11:00:27 +01:00
2024-06-18 20:06:52 +02:00
2024-06-01 11:00:27 +01:00
const DEFAULT _RANGE _CHUNK _SIZE = 65536 ;
const RENDERING _CANCELLED _TIMEOUT = 100 ;
const DELAYED _CLEANUP _TIMEOUT = 5000 ;
const DefaultCanvasFactory = isNodeJS ? NodeCanvasFactory : DOMCanvasFactory ;
const DefaultCMapReaderFactory = isNodeJS ? NodeCMapReaderFactory : DOMCMapReaderFactory ;
const DefaultFilterFactory = isNodeJS ? NodeFilterFactory : DOMFilterFactory ;
const DefaultStandardFontDataFactory = isNodeJS ? NodeStandardFontDataFactory : DOMStandardFontDataFactory ;
2024-06-18 20:06:52 +02:00
function getDocument ( src = { } ) {
2024-06-01 11:00:27 +01:00
if ( typeof src === "string" || src instanceof URL ) {
src = {
url : src
} ;
} else if ( src instanceof ArrayBuffer || ArrayBuffer . isView ( src ) ) {
src = {
data : src
} ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
const task = new PDFDocumentLoadingTask ( ) ;
2023-10-27 13:19:54 +02:00
const {
2024-06-01 11:00:27 +01:00
docId
} = task ;
const url = src . url ? getUrlProp ( src . url ) : null ;
const data = src . data ? getDataProp ( src . data ) : null ;
const httpHeaders = src . httpHeaders || null ;
const withCredentials = src . withCredentials === true ;
const password = src . password ? ? null ;
const rangeTransport = src . range instanceof PDFDataRangeTransport ? src . range : null ;
const rangeChunkSize = Number . isInteger ( src . rangeChunkSize ) && src . rangeChunkSize > 0 ? src . rangeChunkSize : DEFAULT _RANGE _CHUNK _SIZE ;
let worker = src . worker instanceof PDFWorker ? src . worker : null ;
const verbosity = src . verbosity ;
const docBaseUrl = typeof src . docBaseUrl === "string" && ! isDataScheme ( src . docBaseUrl ) ? src . docBaseUrl : null ;
const cMapUrl = typeof src . cMapUrl === "string" ? src . cMapUrl : null ;
const cMapPacked = src . cMapPacked !== false ;
const CMapReaderFactory = src . CMapReaderFactory || DefaultCMapReaderFactory ;
const standardFontDataUrl = typeof src . standardFontDataUrl === "string" ? src . standardFontDataUrl : null ;
const StandardFontDataFactory = src . StandardFontDataFactory || DefaultStandardFontDataFactory ;
const ignoreErrors = src . stopAtErrors !== true ;
const maxImageSize = Number . isInteger ( src . maxImageSize ) && src . maxImageSize > - 1 ? src . maxImageSize : - 1 ;
const isEvalSupported = src . isEvalSupported !== false ;
const isOffscreenCanvasSupported = typeof src . isOffscreenCanvasSupported === "boolean" ? src . isOffscreenCanvasSupported : ! isNodeJS ;
const canvasMaxAreaInBytes = Number . isInteger ( src . canvasMaxAreaInBytes ) ? src . canvasMaxAreaInBytes : - 1 ;
const disableFontFace = typeof src . disableFontFace === "boolean" ? src . disableFontFace : isNodeJS ;
const fontExtraProperties = src . fontExtraProperties === true ;
const enableXfa = src . enableXfa === true ;
const ownerDocument = src . ownerDocument || globalThis . document ;
const disableRange = src . disableRange === true ;
const disableStream = src . disableStream === true ;
const disableAutoFetch = src . disableAutoFetch === true ;
const pdfBug = src . pdfBug === true ;
2024-06-18 20:06:52 +02:00
const enableHWA = src . enableHWA === true ;
2024-06-01 11:00:27 +01:00
const length = rangeTransport ? rangeTransport . length : src . length ? ? NaN ;
const useSystemFonts = typeof src . useSystemFonts === "boolean" ? src . useSystemFonts : ! isNodeJS && ! disableFontFace ;
const useWorkerFetch = typeof src . useWorkerFetch === "boolean" ? src . useWorkerFetch : CMapReaderFactory === DOMCMapReaderFactory && StandardFontDataFactory === DOMStandardFontDataFactory && cMapUrl && standardFontDataUrl && isValidFetchUrl ( cMapUrl , document . baseURI ) && isValidFetchUrl ( standardFontDataUrl , document . baseURI ) ;
const canvasFactory = src . canvasFactory || new DefaultCanvasFactory ( {
2024-06-18 20:06:52 +02:00
ownerDocument ,
enableHWA
2024-06-01 11:00:27 +01:00
} ) ;
const filterFactory = src . filterFactory || new DefaultFilterFactory ( {
docId ,
ownerDocument
} ) ;
const styleElement = null ;
setVerbosityLevel ( verbosity ) ;
const transportFactory = {
canvasFactory ,
filterFactory
} ;
if ( ! useWorkerFetch ) {
transportFactory . cMapReaderFactory = new CMapReaderFactory ( {
baseUrl : cMapUrl ,
isCompressed : cMapPacked
} ) ;
transportFactory . standardFontDataFactory = new StandardFontDataFactory ( {
baseUrl : standardFontDataUrl
} ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
if ( ! worker ) {
const workerParams = {
verbosity ,
port : GlobalWorkerOptions . workerPort
2023-10-27 13:19:54 +02:00
} ;
2024-06-01 11:00:27 +01:00
worker = workerParams . port ? PDFWorker . fromPort ( workerParams ) : new PDFWorker ( workerParams ) ;
task . _worker = worker ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
const docParams = {
docId ,
2024-06-18 20:06:52 +02:00
apiVersion : "4.4.82" ,
2024-06-01 11:00:27 +01:00
data ,
password ,
disableAutoFetch ,
rangeChunkSize ,
length ,
docBaseUrl ,
enableXfa ,
evaluatorOptions : {
maxImageSize ,
disableFontFace ,
ignoreErrors ,
isEvalSupported ,
isOffscreenCanvasSupported ,
canvasMaxAreaInBytes ,
fontExtraProperties ,
useSystemFonts ,
cMapUrl : useWorkerFetch ? cMapUrl : null ,
standardFontDataUrl : useWorkerFetch ? standardFontDataUrl : null
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
} ;
const transportParams = {
disableFontFace ,
fontExtraProperties ,
ownerDocument ,
pdfBug ,
2024-06-02 09:12:22 +01:00
styleElement ,
loadingParams : {
disableAutoFetch ,
enableXfa
}
2024-06-01 11:00:27 +01:00
} ;
worker . promise . then ( function ( ) {
if ( task . destroyed ) {
throw new Error ( "Loading aborted" ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
if ( worker . destroyed ) {
throw new Error ( "Worker was destroyed" ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
const workerIdPromise = worker . messageHandler . sendWithPromise ( "GetDocRequest" , docParams , data ? [ data . buffer ] : null ) ;
let networkStream ;
if ( rangeTransport ) {
networkStream = new PDFDataTransportStream ( rangeTransport , {
disableRange ,
disableStream
} ) ;
} else if ( ! data ) {
2024-06-18 20:06:52 +02:00
if ( ! url ) {
throw new Error ( "getDocument - no `url` parameter provided." ) ;
}
2024-06-01 11:00:27 +01:00
const createPDFNetworkStream = params => {
if ( isNodeJS ) {
const isFetchSupported = function ( ) {
return typeof fetch !== "undefined" && typeof Response !== "undefined" && "body" in Response . prototype ;
} ;
return isFetchSupported ( ) && isValidFetchUrl ( params . url ) ? new PDFFetchStream ( params ) : new PDFNodeStream ( params ) ;
}
return isValidFetchUrl ( params . url ) ? new PDFFetchStream ( params ) : new PDFNetworkStream ( params ) ;
2023-10-27 13:19:54 +02:00
} ;
2024-06-01 11:00:27 +01:00
networkStream = createPDFNetworkStream ( {
url ,
length ,
httpHeaders ,
withCredentials ,
rangeChunkSize ,
disableRange ,
disableStream
} ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
return workerIdPromise . then ( workerId => {
if ( task . destroyed ) {
throw new Error ( "Loading aborted" ) ;
}
if ( worker . destroyed ) {
throw new Error ( "Worker was destroyed" ) ;
}
const messageHandler = new MessageHandler ( docId , workerId , worker . port ) ;
const transport = new WorkerTransport ( messageHandler , task , networkStream , transportParams , transportFactory ) ;
task . _transport = transport ;
messageHandler . send ( "Ready" , null ) ;
} ) ;
} ) . catch ( task . _capability . reject ) ;
2023-10-27 13:19:54 +02:00
return task ;
}
2024-06-01 11:00:27 +01:00
function getUrlProp ( val ) {
if ( val instanceof URL ) {
return val . href ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
try {
return new URL ( val , window . location ) . href ;
} catch {
if ( isNodeJS && typeof val === "string" ) {
return val ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
throw new Error ( "Invalid PDF url data: " + "either string or URL-object is expected in the url property." ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
function getDataProp ( val ) {
if ( isNodeJS && typeof Buffer !== "undefined" && val instanceof Buffer ) {
throw new Error ( "Please provide binary data as `Uint8Array`, rather than `Buffer`." ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
if ( val instanceof Uint8Array && val . byteLength === val . buffer . byteLength ) {
return val ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
if ( typeof val === "string" ) {
return stringToBytes ( val ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
if ( val instanceof ArrayBuffer || ArrayBuffer . isView ( val ) || typeof val === "object" && ! isNaN ( val ? . length ) ) {
return new Uint8Array ( val ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
throw new Error ( "Invalid PDF binary data: either TypedArray, " + "string, or array-like object is expected in the data property." ) ;
}
function isRefProxy ( ref ) {
return typeof ref === "object" && Number . isInteger ( ref ? . num ) && ref . num >= 0 && Number . isInteger ( ref ? . gen ) && ref . gen >= 0 ;
}
class PDFDocumentLoadingTask {
static # docId = 0 ;
constructor ( ) {
this . _capability = Promise . withResolvers ( ) ;
this . _transport = null ;
this . _worker = null ;
this . docId = ` d ${ PDFDocumentLoadingTask . # docId ++ } ` ;
this . destroyed = false ;
this . onPassword = null ;
this . onProgress = null ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
get promise ( ) {
return this . _capability . promise ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
async destroy ( ) {
this . destroyed = true ;
try {
if ( this . _worker ? . port ) {
this . _worker . _pendingDestroy = true ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
await this . _transport ? . destroy ( ) ;
} catch ( ex ) {
if ( this . _worker ? . port ) {
delete this . _worker . _pendingDestroy ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
throw ex ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
this . _transport = null ;
if ( this . _worker ) {
this . _worker . destroy ( ) ;
this . _worker = null ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
}
class PDFDataRangeTransport {
constructor ( length , initialData , progressiveDone = false , contentDispositionFilename = null ) {
this . length = length ;
this . initialData = initialData ;
this . progressiveDone = progressiveDone ;
this . contentDispositionFilename = contentDispositionFilename ;
this . _rangeListeners = [ ] ;
this . _progressListeners = [ ] ;
this . _progressiveReadListeners = [ ] ;
this . _progressiveDoneListeners = [ ] ;
this . _readyCapability = Promise . withResolvers ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
addRangeListener ( listener ) {
this . _rangeListeners . push ( listener ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
addProgressListener ( listener ) {
this . _progressListeners . push ( listener ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
addProgressiveReadListener ( listener ) {
this . _progressiveReadListeners . push ( listener ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
addProgressiveDoneListener ( listener ) {
this . _progressiveDoneListeners . push ( listener ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
onDataRange ( begin , chunk ) {
for ( const listener of this . _rangeListeners ) {
listener ( begin , chunk ) ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
onDataProgress ( loaded , total ) {
this . _readyCapability . promise . then ( ( ) => {
for ( const listener of this . _progressListeners ) {
listener ( loaded , total ) ;
}
} ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
onDataProgressiveRead ( chunk ) {
this . _readyCapability . promise . then ( ( ) => {
for ( const listener of this . _progressiveReadListeners ) {
listener ( chunk ) ;
}
} ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
onDataProgressiveDone ( ) {
this . _readyCapability . promise . then ( ( ) => {
for ( const listener of this . _progressiveDoneListeners ) {
listener ( ) ;
}
} ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
transportReady ( ) {
this . _readyCapability . resolve ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
requestDataRange ( begin , end ) {
unreachable ( "Abstract method PDFDataRangeTransport.requestDataRange" ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
abort ( ) { }
}
class PDFDocumentProxy {
constructor ( pdfInfo , transport ) {
this . _pdfInfo = pdfInfo ;
this . _transport = transport ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
get annotationStorage ( ) {
return this . _transport . annotationStorage ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
get filterFactory ( ) {
return this . _transport . filterFactory ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
get numPages ( ) {
return this . _pdfInfo . numPages ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
get fingerprints ( ) {
return this . _pdfInfo . fingerprints ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
get isPureXfa ( ) {
return shadow ( this , "isPureXfa" , ! ! this . _transport . _htmlForXfa ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
get allXfaHtml ( ) {
return this . _transport . _htmlForXfa ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
getPage ( pageNumber ) {
return this . _transport . getPage ( pageNumber ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
getPageIndex ( ref ) {
return this . _transport . getPageIndex ( ref ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
getDestinations ( ) {
return this . _transport . getDestinations ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
getDestination ( id ) {
return this . _transport . getDestination ( id ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
getPageLabels ( ) {
return this . _transport . getPageLabels ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
getPageLayout ( ) {
return this . _transport . getPageLayout ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
getPageMode ( ) {
return this . _transport . getPageMode ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
getViewerPreferences ( ) {
return this . _transport . getViewerPreferences ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
getOpenAction ( ) {
return this . _transport . getOpenAction ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
getAttachments ( ) {
return this . _transport . getAttachments ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
getJSActions ( ) {
return this . _transport . getDocJSActions ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
getOutline ( ) {
return this . _transport . getOutline ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
getOptionalContentConfig ( {
intent = "display"
} = { } ) {
2023-10-27 13:19:54 +02:00
const {
2024-06-01 11:00:27 +01:00
renderingIntent
} = this . _transport . getRenderingIntent ( intent ) ;
return this . _transport . getOptionalContentConfig ( renderingIntent ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
getPermissions ( ) {
return this . _transport . getPermissions ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
getMetadata ( ) {
return this . _transport . getMetadata ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
getMarkInfo ( ) {
return this . _transport . getMarkInfo ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
getData ( ) {
return this . _transport . getData ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
saveDocument ( ) {
return this . _transport . saveDocument ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
getDownloadInfo ( ) {
return this . _transport . downloadInfoCapability . promise ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
cleanup ( keepLoadedFonts = false ) {
return this . _transport . startCleanup ( keepLoadedFonts || this . isPureXfa ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
destroy ( ) {
return this . loadingTask . destroy ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
cachedPageNumber ( ref ) {
return this . _transport . cachedPageNumber ( ref ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
get loadingParams ( ) {
return this . _transport . loadingParams ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
get loadingTask ( ) {
return this . _transport . loadingTask ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
getFieldObjects ( ) {
return this . _transport . getFieldObjects ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
hasJSActions ( ) {
return this . _transport . hasJSActions ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
getCalculationOrderIds ( ) {
return this . _transport . getCalculationOrderIds ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
}
class PDFPageProxy {
# delayedCleanupTimeout = null ;
# pendingCleanup = false ;
constructor ( pageIndex , pageInfo , transport , pdfBug = false ) {
this . _pageIndex = pageIndex ;
this . _pageInfo = pageInfo ;
this . _transport = transport ;
this . _stats = pdfBug ? new StatTimer ( ) : null ;
this . _pdfBug = pdfBug ;
this . commonObjs = transport . commonObjs ;
this . objs = new PDFObjects ( ) ;
this . _maybeCleanupAfterRender = false ;
this . _intentStates = new Map ( ) ;
this . destroyed = false ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
get pageNumber ( ) {
return this . _pageIndex + 1 ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
get rotate ( ) {
return this . _pageInfo . rotate ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
get ref ( ) {
return this . _pageInfo . ref ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
get userUnit ( ) {
return this . _pageInfo . userUnit ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
get view ( ) {
return this . _pageInfo . view ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
getViewport ( {
scale ,
rotation = this . rotate ,
offsetX = 0 ,
offsetY = 0 ,
dontFlip = false
} = { } ) {
return new PageViewport ( {
viewBox : this . view ,
scale ,
rotation ,
offsetX ,
offsetY ,
dontFlip
2023-10-27 13:19:54 +02:00
} ) ;
}
2024-06-01 11:00:27 +01:00
getAnnotations ( {
intent = "display"
} = { } ) {
const {
renderingIntent
} = this . _transport . getRenderingIntent ( intent ) ;
return this . _transport . getAnnotations ( this . _pageIndex , renderingIntent ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
getJSActions ( ) {
return this . _transport . getPageJSActions ( this . _pageIndex ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
get filterFactory ( ) {
return this . _transport . filterFactory ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
get isPureXfa ( ) {
return shadow ( this , "isPureXfa" , ! ! this . _transport . _htmlForXfa ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
async getXfa ( ) {
return this . _transport . _htmlForXfa ? . children [ this . _pageIndex ] || null ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
render ( {
canvasContext ,
viewport ,
intent = "display" ,
annotationMode = AnnotationMode . ENABLE ,
transform = null ,
background = null ,
optionalContentConfigPromise = null ,
annotationCanvasMap = null ,
pageColors = null ,
printAnnotationStorage = null
} ) {
this . _stats ? . time ( "Overall" ) ;
const intentArgs = this . _transport . getRenderingIntent ( intent , annotationMode , printAnnotationStorage ) ;
const {
renderingIntent ,
cacheKey
} = intentArgs ;
this . # pendingCleanup = false ;
this . # abortDelayedCleanup ( ) ;
optionalContentConfigPromise || = this . _transport . getOptionalContentConfig ( renderingIntent ) ;
let intentState = this . _intentStates . get ( cacheKey ) ;
if ( ! intentState ) {
intentState = Object . create ( null ) ;
this . _intentStates . set ( cacheKey , intentState ) ;
}
if ( intentState . streamReaderCancelTimeout ) {
clearTimeout ( intentState . streamReaderCancelTimeout ) ;
intentState . streamReaderCancelTimeout = null ;
}
const intentPrint = ! ! ( renderingIntent & RenderingIntentFlag . PRINT ) ;
if ( ! intentState . displayReadyCapability ) {
intentState . displayReadyCapability = Promise . withResolvers ( ) ;
intentState . operatorList = {
fnArray : [ ] ,
argsArray : [ ] ,
lastChunk : false ,
separateAnnots : null
} ;
this . _stats ? . time ( "Page Request" ) ;
this . _pumpOperatorList ( intentArgs ) ;
}
const complete = error => {
intentState . renderTasks . delete ( internalRenderTask ) ;
if ( this . _maybeCleanupAfterRender || intentPrint ) {
this . # pendingCleanup = true ;
}
this . # tryCleanup ( ! intentPrint ) ;
if ( error ) {
internalRenderTask . capability . reject ( error ) ;
this . _abortOperatorList ( {
intentState ,
reason : error instanceof Error ? error : new Error ( error )
} ) ;
2023-10-27 13:19:54 +02:00
} else {
2024-06-01 11:00:27 +01:00
internalRenderTask . capability . resolve ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
if ( this . _stats ) {
this . _stats . timeEnd ( "Rendering" ) ;
this . _stats . timeEnd ( "Overall" ) ;
if ( globalThis . Stats ? . enabled ) {
globalThis . Stats . add ( this . pageNumber , this . _stats ) ;
}
}
} ;
const internalRenderTask = new InternalRenderTask ( {
callback : complete ,
params : {
canvasContext ,
viewport ,
transform ,
background
} ,
objs : this . objs ,
commonObjs : this . commonObjs ,
annotationCanvasMap ,
operatorList : intentState . operatorList ,
pageIndex : this . _pageIndex ,
canvasFactory : this . _transport . canvasFactory ,
filterFactory : this . _transport . filterFactory ,
useRequestAnimationFrame : ! intentPrint ,
pdfBug : this . _pdfBug ,
pageColors
} ) ;
( intentState . renderTasks || = new Set ( ) ) . add ( internalRenderTask ) ;
const renderTask = internalRenderTask . task ;
Promise . all ( [ intentState . displayReadyCapability . promise , optionalContentConfigPromise ] ) . then ( ( [ transparency , optionalContentConfig ] ) => {
if ( this . destroyed ) {
complete ( ) ;
return ;
}
this . _stats ? . time ( "Rendering" ) ;
if ( ! ( optionalContentConfig . renderingIntent & renderingIntent ) ) {
throw new Error ( "Must use the same `intent`-argument when calling the `PDFPageProxy.render` " + "and `PDFDocumentProxy.getOptionalContentConfig` methods." ) ;
}
internalRenderTask . initializeGraphics ( {
transparency ,
optionalContentConfig
} ) ;
internalRenderTask . operatorListChanged ( ) ;
} ) . catch ( complete ) ;
return renderTask ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
getOperatorList ( {
intent = "display" ,
annotationMode = AnnotationMode . ENABLE ,
printAnnotationStorage = null
} = { } ) {
function operatorListChanged ( ) {
if ( intentState . operatorList . lastChunk ) {
intentState . opListReadCapability . resolve ( intentState . operatorList ) ;
intentState . renderTasks . delete ( opListTask ) ;
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
const intentArgs = this . _transport . getRenderingIntent ( intent , annotationMode , printAnnotationStorage , true ) ;
let intentState = this . _intentStates . get ( intentArgs . cacheKey ) ;
if ( ! intentState ) {
intentState = Object . create ( null ) ;
this . _intentStates . set ( intentArgs . cacheKey , intentState ) ;
}
let opListTask ;
if ( ! intentState . opListReadCapability ) {
opListTask = Object . create ( null ) ;
opListTask . operatorListChanged = operatorListChanged ;
intentState . opListReadCapability = Promise . withResolvers ( ) ;
( intentState . renderTasks || = new Set ( ) ) . add ( opListTask ) ;
intentState . operatorList = {
fnArray : [ ] ,
argsArray : [ ] ,
lastChunk : false ,
separateAnnots : null
} ;
this . _stats ? . time ( "Page Request" ) ;
this . _pumpOperatorList ( intentArgs ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
return intentState . opListReadCapability . promise ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
streamTextContent ( {
includeMarkedContent = false ,
disableNormalization = false
} = { } ) {
const TEXT _CONTENT _CHUNK _SIZE = 100 ;
return this . _transport . messageHandler . sendWithStream ( "GetTextContent" , {
pageIndex : this . _pageIndex ,
includeMarkedContent : includeMarkedContent === true ,
disableNormalization : disableNormalization === true
} , {
highWaterMark : TEXT _CONTENT _CHUNK _SIZE ,
size ( textContent ) {
return textContent . items . length ;
}
} ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
getTextContent ( params = { } ) {
if ( this . _transport . _htmlForXfa ) {
return this . getXfa ( ) . then ( xfa => XfaText . textContent ( xfa ) ) ;
}
const readableStream = this . streamTextContent ( params ) ;
return new Promise ( function ( resolve , reject ) {
function pump ( ) {
reader . read ( ) . then ( function ( {
value ,
done
} ) {
if ( done ) {
resolve ( textContent ) ;
return ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
textContent . lang ? ? = value . lang ;
Object . assign ( textContent . styles , value . styles ) ;
textContent . items . push ( ... value . items ) ;
pump ( ) ;
} , reject ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
const reader = readableStream . getReader ( ) ;
const textContent = {
items : [ ] ,
styles : Object . create ( null ) ,
lang : null
2023-10-27 13:19:54 +02:00
} ;
2024-06-01 11:00:27 +01:00
pump ( ) ;
} ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
getStructTree ( ) {
return this . _transport . getStructTree ( this . _pageIndex ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
_destroy ( ) {
this . destroyed = true ;
const waitOn = [ ] ;
for ( const intentState of this . _intentStates . values ( ) ) {
this . _abortOperatorList ( {
intentState ,
reason : new Error ( "Page was destroyed." ) ,
force : true
} ) ;
if ( intentState . opListReadCapability ) {
continue ;
}
for ( const internalRenderTask of intentState . renderTasks ) {
waitOn . push ( internalRenderTask . completed ) ;
internalRenderTask . cancel ( ) ;
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
this . objs . clear ( ) ;
this . # pendingCleanup = false ;
this . # abortDelayedCleanup ( ) ;
return Promise . all ( waitOn ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
cleanup ( resetStats = false ) {
this . # pendingCleanup = true ;
const success = this . # tryCleanup ( false ) ;
if ( resetStats && success ) {
this . _stats && = new StatTimer ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
return success ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
# tryCleanup ( delayed = false ) {
this . # abortDelayedCleanup ( ) ;
if ( ! this . # pendingCleanup || this . destroyed ) {
return false ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
if ( delayed ) {
this . # delayedCleanupTimeout = setTimeout ( ( ) => {
this . # delayedCleanupTimeout = null ;
this . # tryCleanup ( false ) ;
} , DELAYED _CLEANUP _TIMEOUT ) ;
return false ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
for ( const {
renderTasks ,
operatorList
} of this . _intentStates . values ( ) ) {
if ( renderTasks . size > 0 || ! operatorList . lastChunk ) {
return false ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
this . _intentStates . clear ( ) ;
this . objs . clear ( ) ;
this . # pendingCleanup = false ;
return true ;
}
# abortDelayedCleanup ( ) {
if ( this . # delayedCleanupTimeout ) {
clearTimeout ( this . # delayedCleanupTimeout ) ;
this . # delayedCleanupTimeout = null ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
}
_startRenderPage ( transparency , cacheKey ) {
const intentState = this . _intentStates . get ( cacheKey ) ;
if ( ! intentState ) {
return ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
this . _stats ? . timeEnd ( "Page Request" ) ;
intentState . displayReadyCapability ? . resolve ( transparency ) ;
}
_renderPageChunk ( operatorListChunk , intentState ) {
for ( let i = 0 , ii = operatorListChunk . length ; i < ii ; i ++ ) {
intentState . operatorList . fnArray . push ( operatorListChunk . fnArray [ i ] ) ;
intentState . operatorList . argsArray . push ( operatorListChunk . argsArray [ i ] ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
intentState . operatorList . lastChunk = operatorListChunk . lastChunk ;
intentState . operatorList . separateAnnots = operatorListChunk . separateAnnots ;
for ( const internalRenderTask of intentState . renderTasks ) {
internalRenderTask . operatorListChanged ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
if ( operatorListChunk . lastChunk ) {
this . # tryCleanup ( true ) ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
_pumpOperatorList ( {
renderingIntent ,
cacheKey ,
annotationStorageSerializable
} ) {
2023-10-27 13:19:54 +02:00
const {
2024-06-01 11:00:27 +01:00
map ,
transfer
} = annotationStorageSerializable ;
const readableStream = this . _transport . messageHandler . sendWithStream ( "GetOperatorList" , {
pageIndex : this . _pageIndex ,
intent : renderingIntent ,
cacheKey ,
annotationStorage : map
} , transfer ) ;
const reader = readableStream . getReader ( ) ;
const intentState = this . _intentStates . get ( cacheKey ) ;
intentState . streamReader = reader ;
const pump = ( ) => {
reader . read ( ) . then ( ( {
value ,
done
} ) => {
if ( done ) {
intentState . streamReader = null ;
return ;
}
if ( this . _transport . destroyed ) {
return ;
}
this . _renderPageChunk ( value , intentState ) ;
pump ( ) ;
} , reason => {
intentState . streamReader = null ;
if ( this . _transport . destroyed ) {
return ;
}
if ( intentState . operatorList ) {
intentState . operatorList . lastChunk = true ;
for ( const internalRenderTask of intentState . renderTasks ) {
internalRenderTask . operatorListChanged ( ) ;
}
this . # tryCleanup ( true ) ;
}
if ( intentState . displayReadyCapability ) {
intentState . displayReadyCapability . reject ( reason ) ;
} else if ( intentState . opListReadCapability ) {
intentState . opListReadCapability . reject ( reason ) ;
} else {
throw reason ;
}
2023-10-27 13:19:54 +02:00
} ) ;
} ;
2024-06-01 11:00:27 +01:00
pump ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
_abortOperatorList ( {
intentState ,
reason ,
force = false
} ) {
if ( ! intentState . streamReader ) {
2023-10-27 13:19:54 +02:00
return ;
}
2024-06-01 11:00:27 +01:00
if ( intentState . streamReaderCancelTimeout ) {
clearTimeout ( intentState . streamReaderCancelTimeout ) ;
intentState . streamReaderCancelTimeout = null ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
if ( ! force ) {
if ( intentState . renderTasks . size > 0 ) {
return ;
}
if ( reason instanceof RenderingCancelledException ) {
let delay = RENDERING _CANCELLED _TIMEOUT ;
if ( reason . extraDelay > 0 && reason . extraDelay < 1000 ) {
delay += reason . extraDelay ;
}
intentState . streamReaderCancelTimeout = setTimeout ( ( ) => {
intentState . streamReaderCancelTimeout = null ;
this . _abortOperatorList ( {
intentState ,
reason ,
force : true
} ) ;
} , delay ) ;
return ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
intentState . streamReader . cancel ( new AbortException ( reason . message ) ) . catch ( ( ) => { } ) ;
intentState . streamReader = null ;
if ( this . _transport . destroyed ) {
2023-10-27 13:19:54 +02:00
return ;
}
2024-06-01 11:00:27 +01:00
for ( const [ curCacheKey , curIntentState ] of this . _intentStates ) {
if ( curIntentState === intentState ) {
this . _intentStates . delete ( curCacheKey ) ;
break ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
this . cleanup ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
get stats ( ) {
return this . _stats ;
}
}
class LoopbackPort {
# listeners = new Set ( ) ;
# deferred = Promise . resolve ( ) ;
postMessage ( obj , transfer ) {
const event = {
data : structuredClone ( obj , transfer ? {
transfer
} : null )
} ;
this . # deferred . then ( ( ) => {
for ( const listener of this . # listeners ) {
listener . call ( this , event ) ;
}
2023-10-27 13:19:54 +02:00
} ) ;
}
2024-06-01 11:00:27 +01:00
addEventListener ( name , listener ) {
this . # listeners . add ( listener ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
removeEventListener ( name , listener ) {
this . # listeners . delete ( listener ) ;
}
terminate ( ) {
this . # listeners . clear ( ) ;
}
}
const PDFWorkerUtil = {
isWorkerDisabled : false ,
fakeWorkerId : 0
} ;
{
if ( isNodeJS ) {
PDFWorkerUtil . isWorkerDisabled = true ;
GlobalWorkerOptions . workerSrc || = "./pdf.worker.mjs" ;
}
PDFWorkerUtil . isSameOrigin = function ( baseUrl , otherUrl ) {
let base ;
try {
base = new URL ( baseUrl ) ;
if ( ! base . origin || base . origin === "null" ) {
return false ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
} catch {
return false ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
const other = new URL ( otherUrl , base ) ;
return base . origin === other . origin ;
} ;
PDFWorkerUtil . createCDNWrapper = function ( url ) {
const wrapper = ` await import(" ${ url } "); ` ;
return URL . createObjectURL ( new Blob ( [ wrapper ] , {
type : "text/javascript"
} ) ) ;
} ;
}
class PDFWorker {
static # workerPorts ;
constructor ( {
name = null ,
port = null ,
verbosity = getVerbosityLevel ( )
} = { } ) {
this . name = name ;
this . destroyed = false ;
this . verbosity = verbosity ;
this . _readyCapability = Promise . withResolvers ( ) ;
this . _port = null ;
this . _webWorker = null ;
this . _messageHandler = null ;
if ( port ) {
if ( PDFWorker . # workerPorts ? . has ( port ) ) {
throw new Error ( "Cannot use more than one PDFWorker per port." ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
( PDFWorker . # workerPorts || = new WeakMap ( ) ) . set ( port , this ) ;
this . _initializeFromPort ( port ) ;
return ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
this . _initialize ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
get promise ( ) {
if ( isNodeJS ) {
return Promise . all ( [ NodePackages . promise , this . _readyCapability . promise ] ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
return this . _readyCapability . promise ;
2023-10-27 13:19:54 +02:00
}
2024-06-18 20:06:52 +02:00
# resolve ( ) {
this . _readyCapability . resolve ( ) ;
this . _messageHandler . send ( "configure" , {
verbosity : this . verbosity
} ) ;
}
2024-06-01 11:00:27 +01:00
get port ( ) {
return this . _port ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
get messageHandler ( ) {
return this . _messageHandler ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
_initializeFromPort ( port ) {
this . _port = port ;
this . _messageHandler = new MessageHandler ( "main" , "worker" , port ) ;
this . _messageHandler . on ( "ready" , function ( ) { } ) ;
2024-06-18 20:06:52 +02:00
this . # resolve ( ) ;
2024-06-01 11:00:27 +01:00
}
_initialize ( ) {
2024-06-18 20:06:52 +02:00
if ( PDFWorkerUtil . isWorkerDisabled || PDFWorker . # mainThreadWorkerMessageHandler ) {
this . _setupFakeWorker ( ) ;
return ;
}
let {
workerSrc
} = PDFWorker ;
try {
if ( ! PDFWorkerUtil . isSameOrigin ( window . location . href , workerSrc ) ) {
workerSrc = PDFWorkerUtil . createCDNWrapper ( new URL ( workerSrc , window . location ) . href ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-18 20:06:52 +02:00
const worker = new Worker ( workerSrc , {
type : "module"
} ) ;
const messageHandler = new MessageHandler ( "main" , "worker" , worker ) ;
const terminateEarly = ( ) => {
ac . abort ( ) ;
messageHandler . destroy ( ) ;
worker . terminate ( ) ;
if ( this . destroyed ) {
this . _readyCapability . reject ( new Error ( "Worker was destroyed" ) ) ;
} else {
this . _setupFakeWorker ( ) ;
}
} ;
const ac = new AbortController ( ) ;
worker . addEventListener ( "error" , ( ) => {
if ( ! this . _webWorker ) {
terminateEarly ( ) ;
}
} , {
signal : ac . signal
} ) ;
messageHandler . on ( "test" , data => {
ac . abort ( ) ;
if ( this . destroyed || ! data ) {
terminateEarly ( ) ;
return ;
}
this . _messageHandler = messageHandler ;
this . _port = worker ;
this . _webWorker = worker ;
this . # resolve ( ) ;
} ) ;
messageHandler . on ( "ready" , data => {
ac . abort ( ) ;
if ( this . destroyed ) {
terminateEarly ( ) ;
return ;
}
try {
sendTest ( ) ;
} catch {
this . _setupFakeWorker ( ) ;
}
} ) ;
const sendTest = ( ) => {
const testObj = new Uint8Array ( ) ;
messageHandler . send ( "test" , testObj , [ testObj . buffer ] ) ;
} ;
sendTest ( ) ;
return ;
} catch {
info ( "The worker has been disabled." ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
this . _setupFakeWorker ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
_setupFakeWorker ( ) {
if ( ! PDFWorkerUtil . isWorkerDisabled ) {
warn ( "Setting up fake worker." ) ;
PDFWorkerUtil . isWorkerDisabled = true ;
}
PDFWorker . _setupFakeWorkerGlobal . then ( WorkerMessageHandler => {
if ( this . destroyed ) {
this . _readyCapability . reject ( new Error ( "Worker was destroyed" ) ) ;
return ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
const port = new LoopbackPort ( ) ;
this . _port = port ;
const id = ` fake ${ PDFWorkerUtil . fakeWorkerId ++ } ` ;
const workerHandler = new MessageHandler ( id + "_worker" , id , port ) ;
WorkerMessageHandler . setup ( workerHandler , port ) ;
2024-06-18 20:06:52 +02:00
this . _messageHandler = new MessageHandler ( id , id + "_worker" , port ) ;
this . # resolve ( ) ;
2024-06-01 11:00:27 +01:00
} ) . catch ( reason => {
this . _readyCapability . reject ( new Error ( ` Setting up fake worker failed: " ${ reason . message } ". ` ) ) ;
2023-10-27 13:19:54 +02:00
} ) ;
}
2024-06-01 11:00:27 +01:00
destroy ( ) {
this . destroyed = true ;
if ( this . _webWorker ) {
this . _webWorker . terminate ( ) ;
this . _webWorker = null ;
}
PDFWorker . # workerPorts ? . delete ( this . _port ) ;
this . _port = null ;
if ( this . _messageHandler ) {
this . _messageHandler . destroy ( ) ;
this . _messageHandler = null ;
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
static fromPort ( params ) {
if ( ! params ? . port ) {
throw new Error ( "PDFWorker.fromPort - invalid method signature." ) ;
}
const cachedPort = this . # workerPorts ? . get ( params . port ) ;
if ( cachedPort ) {
if ( cachedPort . _pendingDestroy ) {
throw new Error ( "PDFWorker.fromPort - the worker is being destroyed.\n" + "Please remember to await `PDFDocumentLoadingTask.destroy()`-calls." ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
return cachedPort ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
return new PDFWorker ( params ) ;
}
static get workerSrc ( ) {
if ( GlobalWorkerOptions . workerSrc ) {
return GlobalWorkerOptions . workerSrc ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
throw new Error ( 'No "GlobalWorkerOptions.workerSrc" specified.' ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
static get # mainThreadWorkerMessageHandler ( ) {
try {
return globalThis . pdfjsWorker ? . WorkerMessageHandler || null ;
} catch {
return null ;
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
static get _setupFakeWorkerGlobal ( ) {
const loader = async ( ) => {
if ( this . # mainThreadWorkerMessageHandler ) {
return this . # mainThreadWorkerMessageHandler ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
const worker = await import ( /*webpackIgnore: true*/ this . workerSrc ) ;
return worker . WorkerMessageHandler ;
2023-10-27 13:19:54 +02:00
} ;
2024-06-01 11:00:27 +01:00
return shadow ( this , "_setupFakeWorkerGlobal" , loader ( ) ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
}
class WorkerTransport {
# methodPromises = new Map ( ) ;
# pageCache = new Map ( ) ;
# pagePromises = new Map ( ) ;
# pageRefCache = new Map ( ) ;
# passwordCapability = null ;
constructor ( messageHandler , loadingTask , networkStream , params , factory ) {
this . messageHandler = messageHandler ;
this . loadingTask = loadingTask ;
this . commonObjs = new PDFObjects ( ) ;
this . fontLoader = new FontLoader ( {
ownerDocument : params . ownerDocument ,
styleElement : params . styleElement
} ) ;
2024-06-02 09:12:22 +01:00
this . loadingParams = params . loadingParams ;
2024-06-01 11:00:27 +01:00
this . _params = params ;
this . canvasFactory = factory . canvasFactory ;
this . filterFactory = factory . filterFactory ;
this . cMapReaderFactory = factory . cMapReaderFactory ;
this . standardFontDataFactory = factory . standardFontDataFactory ;
this . destroyed = false ;
this . destroyCapability = null ;
this . _networkStream = networkStream ;
this . _fullReader = null ;
this . _lastProgress = null ;
this . downloadInfoCapability = Promise . withResolvers ( ) ;
this . setupMessageHandler ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
# cacheSimpleMethod ( name , data = null ) {
const cachedPromise = this . # methodPromises . get ( name ) ;
if ( cachedPromise ) {
return cachedPromise ;
}
const promise = this . messageHandler . sendWithPromise ( name , data ) ;
this . # methodPromises . set ( name , promise ) ;
return promise ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
get annotationStorage ( ) {
return shadow ( this , "annotationStorage" , new AnnotationStorage ( ) ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
getRenderingIntent ( intent , annotationMode = AnnotationMode . ENABLE , printAnnotationStorage = null , isOpList = false ) {
let renderingIntent = RenderingIntentFlag . DISPLAY ;
let annotationStorageSerializable = SerializableEmpty ;
switch ( intent ) {
case "any" :
renderingIntent = RenderingIntentFlag . ANY ;
break ;
case "display" :
break ;
case "print" :
renderingIntent = RenderingIntentFlag . PRINT ;
break ;
default :
warn ( ` getRenderingIntent - invalid intent: ${ intent } ` ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
switch ( annotationMode ) {
case AnnotationMode . DISABLE :
renderingIntent += RenderingIntentFlag . ANNOTATIONS _DISABLE ;
break ;
case AnnotationMode . ENABLE :
break ;
case AnnotationMode . ENABLE _FORMS :
renderingIntent += RenderingIntentFlag . ANNOTATIONS _FORMS ;
break ;
case AnnotationMode . ENABLE _STORAGE :
renderingIntent += RenderingIntentFlag . ANNOTATIONS _STORAGE ;
const annotationStorage = renderingIntent & RenderingIntentFlag . PRINT && printAnnotationStorage instanceof PrintAnnotationStorage ? printAnnotationStorage : this . annotationStorage ;
annotationStorageSerializable = annotationStorage . serializable ;
break ;
default :
warn ( ` getRenderingIntent - invalid annotationMode: ${ annotationMode } ` ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
if ( isOpList ) {
renderingIntent += RenderingIntentFlag . OPLIST ;
}
return {
renderingIntent ,
cacheKey : ` ${ renderingIntent } _ ${ annotationStorageSerializable . hash } ` ,
annotationStorageSerializable
} ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
destroy ( ) {
if ( this . destroyCapability ) {
return this . destroyCapability . promise ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
this . destroyed = true ;
this . destroyCapability = Promise . withResolvers ( ) ;
this . # passwordCapability ? . reject ( new Error ( "Worker was destroyed during onPassword callback" ) ) ;
const waitOn = [ ] ;
for ( const page of this . # pageCache . values ( ) ) {
waitOn . push ( page . _destroy ( ) ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
this . # pageCache . clear ( ) ;
this . # pagePromises . clear ( ) ;
this . # pageRefCache . clear ( ) ;
if ( this . hasOwnProperty ( "annotationStorage" ) ) {
this . annotationStorage . resetModified ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
const terminated = this . messageHandler . sendWithPromise ( "Terminate" , null ) ;
waitOn . push ( terminated ) ;
Promise . all ( waitOn ) . then ( ( ) => {
this . commonObjs . clear ( ) ;
this . fontLoader . clear ( ) ;
this . # methodPromises . clear ( ) ;
this . filterFactory . destroy ( ) ;
TextLayer . cleanup ( ) ;
this . _networkStream ? . cancelAllRequests ( new AbortException ( "Worker was terminated." ) ) ;
if ( this . messageHandler ) {
this . messageHandler . destroy ( ) ;
this . messageHandler = null ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
this . destroyCapability . resolve ( ) ;
} , this . destroyCapability . reject ) ;
return this . destroyCapability . promise ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
setupMessageHandler ( ) {
2023-10-27 13:19:54 +02:00
const {
2024-06-01 11:00:27 +01:00
messageHandler ,
loadingTask
} = this ;
messageHandler . on ( "GetReader" , ( data , sink ) => {
assert ( this . _networkStream , "GetReader - no `IPDFStream` instance available." ) ;
this . _fullReader = this . _networkStream . getFullReader ( ) ;
this . _fullReader . onProgress = evt => {
this . _lastProgress = {
loaded : evt . loaded ,
total : evt . total
} ;
} ;
sink . onPull = ( ) => {
this . _fullReader . read ( ) . then ( function ( {
value ,
done
} ) {
if ( done ) {
sink . close ( ) ;
2023-10-27 13:19:54 +02:00
return ;
}
2024-06-01 11:00:27 +01:00
assert ( value instanceof ArrayBuffer , "GetReader - expected an ArrayBuffer." ) ;
sink . enqueue ( new Uint8Array ( value ) , 1 , [ value ] ) ;
} ) . catch ( reason => {
sink . error ( reason ) ;
} ) ;
} ;
sink . onCancel = reason => {
this . _fullReader . cancel ( reason ) ;
sink . ready . catch ( readyReason => {
if ( this . destroyed ) {
2023-10-27 13:19:54 +02:00
return ;
}
2024-06-01 11:00:27 +01:00
throw readyReason ;
2023-10-27 13:19:54 +02:00
} ) ;
2024-06-01 11:00:27 +01:00
} ;
} ) ;
messageHandler . on ( "ReaderHeadersReady" , data => {
const headersCapability = Promise . withResolvers ( ) ;
const fullReader = this . _fullReader ;
fullReader . headersReady . then ( ( ) => {
if ( ! fullReader . isStreamingSupported || ! fullReader . isRangeSupported ) {
if ( this . _lastProgress ) {
loadingTask . onProgress ? . ( this . _lastProgress ) ;
}
fullReader . onProgress = evt => {
loadingTask . onProgress ? . ( {
loaded : evt . loaded ,
total : evt . total
} ) ;
2023-10-27 13:19:54 +02:00
} ;
}
2024-06-01 11:00:27 +01:00
headersCapability . resolve ( {
isStreamingSupported : fullReader . isStreamingSupported ,
isRangeSupported : fullReader . isRangeSupported ,
contentLength : fullReader . contentLength
} ) ;
} , headersCapability . reject ) ;
return headersCapability . promise ;
2023-10-27 13:19:54 +02:00
} ) ;
2024-06-01 11:00:27 +01:00
messageHandler . on ( "GetRangeReader" , ( data , sink ) => {
assert ( this . _networkStream , "GetRangeReader - no `IPDFStream` instance available." ) ;
const rangeReader = this . _networkStream . getRangeReader ( data . begin , data . end ) ;
if ( ! rangeReader ) {
sink . close ( ) ;
return ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
sink . onPull = ( ) => {
rangeReader . read ( ) . then ( function ( {
value ,
done
} ) {
if ( done ) {
sink . close ( ) ;
return ;
}
assert ( value instanceof ArrayBuffer , "GetRangeReader - expected an ArrayBuffer." ) ;
sink . enqueue ( new Uint8Array ( value ) , 1 , [ value ] ) ;
} ) . catch ( reason => {
sink . error ( reason ) ;
} ) ;
2023-10-27 13:19:54 +02:00
} ;
2024-06-01 11:00:27 +01:00
sink . onCancel = reason => {
rangeReader . cancel ( reason ) ;
sink . ready . catch ( readyReason => {
if ( this . destroyed ) {
return ;
}
throw readyReason ;
} ) ;
} ;
} ) ;
messageHandler . on ( "GetDoc" , ( {
pdfInfo
} ) => {
this . _numPages = pdfInfo . numPages ;
this . _htmlForXfa = pdfInfo . htmlForXfa ;
delete pdfInfo . htmlForXfa ;
loadingTask . _capability . resolve ( new PDFDocumentProxy ( pdfInfo , this ) ) ;
} ) ;
messageHandler . on ( "DocException" , function ( ex ) {
let reason ;
switch ( ex . name ) {
case "PasswordException" :
reason = new PasswordException ( ex . message , ex . code ) ;
break ;
case "InvalidPDFException" :
reason = new InvalidPDFException ( ex . message ) ;
break ;
case "MissingPDFException" :
reason = new MissingPDFException ( ex . message ) ;
break ;
case "UnexpectedResponseException" :
reason = new UnexpectedResponseException ( ex . message , ex . status ) ;
break ;
case "UnknownErrorException" :
reason = new UnknownErrorException ( ex . message , ex . details ) ;
break ;
default :
unreachable ( "DocException - expected a valid Error." ) ;
}
loadingTask . _capability . reject ( reason ) ;
} ) ;
messageHandler . on ( "PasswordRequest" , exception => {
this . # passwordCapability = Promise . withResolvers ( ) ;
if ( loadingTask . onPassword ) {
const updatePassword = password => {
if ( password instanceof Error ) {
this . # passwordCapability . reject ( password ) ;
} else {
this . # passwordCapability . resolve ( {
password
} ) ;
}
} ;
try {
loadingTask . onPassword ( updatePassword , exception . code ) ;
} catch ( ex ) {
this . # passwordCapability . reject ( ex ) ;
2023-10-27 13:19:54 +02:00
}
} else {
2024-06-01 11:00:27 +01:00
this . # passwordCapability . reject ( new PasswordException ( exception . message , exception . code ) ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
return this . # passwordCapability . promise ;
} ) ;
messageHandler . on ( "DataLoaded" , data => {
loadingTask . onProgress ? . ( {
loaded : data . length ,
total : data . length
} ) ;
this . downloadInfoCapability . resolve ( data ) ;
} ) ;
messageHandler . on ( "StartRenderPage" , data => {
if ( this . destroyed ) {
return ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
const page = this . # pageCache . get ( data . pageIndex ) ;
page . _startRenderPage ( data . transparency , data . cacheKey ) ;
} ) ;
messageHandler . on ( "commonobj" , ( [ id , type , exportedData ] ) => {
if ( this . destroyed ) {
return null ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
if ( this . commonObjs . has ( id ) ) {
return null ;
}
switch ( type ) {
case "Font" :
2023-10-27 13:19:54 +02:00
const {
2024-06-01 11:00:27 +01:00
disableFontFace ,
fontExtraProperties ,
pdfBug
} = this . _params ;
if ( "error" in exportedData ) {
const exportedError = exportedData . error ;
warn ( ` Error during font loading: ${ exportedError } ` ) ;
this . commonObjs . resolve ( id , exportedError ) ;
break ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
const inspectFont = pdfBug && globalThis . FontInspector ? . enabled ? ( font , url ) => globalThis . FontInspector . fontAdded ( font , url ) : null ;
const font = new FontFaceObject ( exportedData , {
disableFontFace ,
inspectFont
} ) ;
this . fontLoader . bind ( font ) . catch ( ( ) => messageHandler . sendWithPromise ( "FontFallback" , {
id
} ) ) . finally ( ( ) => {
if ( ! fontExtraProperties && font . data ) {
font . data = null ;
}
this . commonObjs . resolve ( id , font ) ;
} ) ;
break ;
case "CopyLocalImage" :
const {
imageRef
} = exportedData ;
assert ( imageRef , "The imageRef must be defined." ) ;
for ( const pageProxy of this . # pageCache . values ( ) ) {
for ( const [ , data ] of pageProxy . objs ) {
if ( data ? . ref !== imageRef ) {
continue ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
if ( ! data . dataLen ) {
return null ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
this . commonObjs . resolve ( id , structuredClone ( data ) ) ;
return data . dataLen ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
break ;
case "FontPath" :
case "Image" :
case "Pattern" :
this . commonObjs . resolve ( id , exportedData ) ;
break ;
default :
throw new Error ( ` Got unknown common object type ${ type } ` ) ;
}
return null ;
} ) ;
messageHandler . on ( "obj" , ( [ id , pageIndex , type , imageData ] ) => {
if ( this . destroyed ) {
return ;
}
const pageProxy = this . # pageCache . get ( pageIndex ) ;
if ( pageProxy . objs . has ( id ) ) {
return ;
}
if ( pageProxy . _intentStates . size === 0 ) {
imageData ? . bitmap ? . close ( ) ;
return ;
}
switch ( type ) {
case "Image" :
pageProxy . objs . resolve ( id , imageData ) ;
if ( imageData ? . dataLen > MAX _IMAGE _SIZE _TO _CACHE ) {
pageProxy . _maybeCleanupAfterRender = true ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
break ;
case "Pattern" :
pageProxy . objs . resolve ( id , imageData ) ;
break ;
default :
throw new Error ( ` Got unknown object type ${ type } ` ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
} ) ;
messageHandler . on ( "DocProgress" , data => {
if ( this . destroyed ) {
return ;
}
loadingTask . onProgress ? . ( {
loaded : data . loaded ,
total : data . total
} ) ;
} ) ;
messageHandler . on ( "FetchBuiltInCMap" , data => {
if ( this . destroyed ) {
return Promise . reject ( new Error ( "Worker was destroyed." ) ) ;
}
if ( ! this . cMapReaderFactory ) {
return Promise . reject ( new Error ( "CMapReaderFactory not initialized, see the `useWorkerFetch` parameter." ) ) ;
}
return this . cMapReaderFactory . fetch ( data ) ;
} ) ;
messageHandler . on ( "FetchStandardFontData" , data => {
if ( this . destroyed ) {
return Promise . reject ( new Error ( "Worker was destroyed." ) ) ;
}
if ( ! this . standardFontDataFactory ) {
return Promise . reject ( new Error ( "StandardFontDataFactory not initialized, see the `useWorkerFetch` parameter." ) ) ;
}
return this . standardFontDataFactory . fetch ( data ) ;
} ) ;
}
getData ( ) {
return this . messageHandler . sendWithPromise ( "GetData" , null ) ;
}
saveDocument ( ) {
if ( this . annotationStorage . size <= 0 ) {
warn ( "saveDocument called while `annotationStorage` is empty, " + "please use the getData-method instead." ) ;
}
const {
map ,
transfer
} = this . annotationStorage . serializable ;
return this . messageHandler . sendWithPromise ( "SaveDocument" , {
isPureXfa : ! ! this . _htmlForXfa ,
numPages : this . _numPages ,
annotationStorage : map ,
filename : this . _fullReader ? . filename ? ? null
} , transfer ) . finally ( ( ) => {
this . annotationStorage . resetModified ( ) ;
} ) ;
}
getPage ( pageNumber ) {
if ( ! Number . isInteger ( pageNumber ) || pageNumber <= 0 || pageNumber > this . _numPages ) {
return Promise . reject ( new Error ( "Invalid page request." ) ) ;
}
const pageIndex = pageNumber - 1 ,
cachedPromise = this . # pagePromises . get ( pageIndex ) ;
if ( cachedPromise ) {
return cachedPromise ;
}
const promise = this . messageHandler . sendWithPromise ( "GetPage" , {
pageIndex
} ) . then ( pageInfo => {
if ( this . destroyed ) {
throw new Error ( "Transport destroyed" ) ;
}
if ( pageInfo . refStr ) {
this . # pageRefCache . set ( pageInfo . refStr , pageNumber ) ;
}
const page = new PDFPageProxy ( pageIndex , pageInfo , this , this . _params . pdfBug ) ;
this . # pageCache . set ( pageIndex , page ) ;
return page ;
} ) ;
this . # pagePromises . set ( pageIndex , promise ) ;
return promise ;
}
getPageIndex ( ref ) {
if ( ! isRefProxy ( ref ) ) {
return Promise . reject ( new Error ( "Invalid pageIndex request." ) ) ;
}
return this . messageHandler . sendWithPromise ( "GetPageIndex" , {
num : ref . num ,
gen : ref . gen
} ) ;
}
getAnnotations ( pageIndex , intent ) {
return this . messageHandler . sendWithPromise ( "GetAnnotations" , {
pageIndex ,
intent
} ) ;
}
getFieldObjects ( ) {
return this . # cacheSimpleMethod ( "GetFieldObjects" ) ;
}
hasJSActions ( ) {
return this . # cacheSimpleMethod ( "HasJSActions" ) ;
}
getCalculationOrderIds ( ) {
return this . messageHandler . sendWithPromise ( "GetCalculationOrderIds" , null ) ;
}
getDestinations ( ) {
return this . messageHandler . sendWithPromise ( "GetDestinations" , null ) ;
}
getDestination ( id ) {
if ( typeof id !== "string" ) {
return Promise . reject ( new Error ( "Invalid destination request." ) ) ;
}
return this . messageHandler . sendWithPromise ( "GetDestination" , {
id
} ) ;
}
getPageLabels ( ) {
return this . messageHandler . sendWithPromise ( "GetPageLabels" , null ) ;
}
getPageLayout ( ) {
return this . messageHandler . sendWithPromise ( "GetPageLayout" , null ) ;
}
getPageMode ( ) {
return this . messageHandler . sendWithPromise ( "GetPageMode" , null ) ;
}
getViewerPreferences ( ) {
return this . messageHandler . sendWithPromise ( "GetViewerPreferences" , null ) ;
}
getOpenAction ( ) {
return this . messageHandler . sendWithPromise ( "GetOpenAction" , null ) ;
}
getAttachments ( ) {
return this . messageHandler . sendWithPromise ( "GetAttachments" , null ) ;
}
getDocJSActions ( ) {
return this . # cacheSimpleMethod ( "GetDocJSActions" ) ;
}
getPageJSActions ( pageIndex ) {
return this . messageHandler . sendWithPromise ( "GetPageJSActions" , {
pageIndex
} ) ;
}
getStructTree ( pageIndex ) {
return this . messageHandler . sendWithPromise ( "GetStructTree" , {
pageIndex
} ) ;
}
getOutline ( ) {
return this . messageHandler . sendWithPromise ( "GetOutline" , null ) ;
}
getOptionalContentConfig ( renderingIntent ) {
return this . # cacheSimpleMethod ( "GetOptionalContentConfig" ) . then ( data => new OptionalContentConfig ( data , renderingIntent ) ) ;
}
getPermissions ( ) {
return this . messageHandler . sendWithPromise ( "GetPermissions" , null ) ;
}
getMetadata ( ) {
const name = "GetMetadata" ,
cachedPromise = this . # methodPromises . get ( name ) ;
if ( cachedPromise ) {
return cachedPromise ;
}
const promise = this . messageHandler . sendWithPromise ( name , null ) . then ( results => ( {
info : results [ 0 ] ,
metadata : results [ 1 ] ? new Metadata ( results [ 1 ] ) : null ,
contentDispositionFilename : this . _fullReader ? . filename ? ? null ,
contentLength : this . _fullReader ? . contentLength ? ? null
} ) ) ;
this . # methodPromises . set ( name , promise ) ;
return promise ;
}
getMarkInfo ( ) {
return this . messageHandler . sendWithPromise ( "GetMarkInfo" , null ) ;
}
async startCleanup ( keepLoadedFonts = false ) {
if ( this . destroyed ) {
return ;
}
await this . messageHandler . sendWithPromise ( "Cleanup" , null ) ;
for ( const page of this . # pageCache . values ( ) ) {
const cleanupSuccessful = page . cleanup ( ) ;
if ( ! cleanupSuccessful ) {
throw new Error ( ` startCleanup: Page ${ page . pageNumber } is currently rendering. ` ) ;
}
}
this . commonObjs . clear ( ) ;
if ( ! keepLoadedFonts ) {
this . fontLoader . clear ( ) ;
}
this . # methodPromises . clear ( ) ;
this . filterFactory . destroy ( true ) ;
TextLayer . cleanup ( ) ;
}
cachedPageNumber ( ref ) {
if ( ! isRefProxy ( ref ) ) {
return null ;
}
const refStr = ref . gen === 0 ? ` ${ ref . num } R ` : ` ${ ref . num } R ${ ref . gen } ` ;
return this . # pageRefCache . get ( refStr ) ? ? null ;
}
}
const INITIAL _DATA = Symbol ( "INITIAL_DATA" ) ;
class PDFObjects {
# objs = Object . create ( null ) ;
# ensureObj ( objId ) {
return this . # objs [ objId ] || = {
... Promise . withResolvers ( ) ,
data : INITIAL _DATA
} ;
}
get ( objId , callback = null ) {
if ( callback ) {
const obj = this . # ensureObj ( objId ) ;
obj . promise . then ( ( ) => callback ( obj . data ) ) ;
return null ;
}
const obj = this . # objs [ objId ] ;
if ( ! obj || obj . data === INITIAL _DATA ) {
throw new Error ( ` Requesting object that isn't resolved yet ${ objId } . ` ) ;
}
return obj . data ;
}
has ( objId ) {
const obj = this . # objs [ objId ] ;
return ! ! obj && obj . data !== INITIAL _DATA ;
}
resolve ( objId , data = null ) {
const obj = this . # ensureObj ( objId ) ;
obj . data = data ;
obj . resolve ( ) ;
}
clear ( ) {
for ( const objId in this . # objs ) {
const {
data
} = this . # objs [ objId ] ;
data ? . bitmap ? . close ( ) ;
}
this . # objs = Object . create ( null ) ;
}
* [ Symbol . iterator ] ( ) {
for ( const objId in this . # objs ) {
const {
data
} = this . # objs [ objId ] ;
if ( data === INITIAL _DATA ) {
continue ;
}
yield [ objId , data ] ;
}
}
}
class RenderTask {
# internalRenderTask = null ;
constructor ( internalRenderTask ) {
this . # internalRenderTask = internalRenderTask ;
this . onContinue = null ;
}
get promise ( ) {
return this . # internalRenderTask . capability . promise ;
}
cancel ( extraDelay = 0 ) {
this . # internalRenderTask . cancel ( null , extraDelay ) ;
}
get separateAnnots ( ) {
const {
separateAnnots
} = this . # internalRenderTask . operatorList ;
if ( ! separateAnnots ) {
return false ;
}
const {
annotationCanvasMap
} = this . # internalRenderTask ;
return separateAnnots . form || separateAnnots . canvas && annotationCanvasMap ? . size > 0 ;
}
}
class InternalRenderTask {
static # canvasInUse = new WeakSet ( ) ;
constructor ( {
callback ,
params ,
objs ,
commonObjs ,
annotationCanvasMap ,
operatorList ,
pageIndex ,
canvasFactory ,
filterFactory ,
useRequestAnimationFrame = false ,
pdfBug = false ,
pageColors = null
} ) {
this . callback = callback ;
this . params = params ;
this . objs = objs ;
this . commonObjs = commonObjs ;
this . annotationCanvasMap = annotationCanvasMap ;
this . operatorListIdx = null ;
this . operatorList = operatorList ;
this . _pageIndex = pageIndex ;
this . canvasFactory = canvasFactory ;
this . filterFactory = filterFactory ;
this . _pdfBug = pdfBug ;
this . pageColors = pageColors ;
this . running = false ;
this . graphicsReadyCallback = null ;
this . graphicsReady = false ;
this . _useRequestAnimationFrame = useRequestAnimationFrame === true && typeof window !== "undefined" ;
this . cancelled = false ;
this . capability = Promise . withResolvers ( ) ;
this . task = new RenderTask ( this ) ;
this . _cancelBound = this . cancel . bind ( this ) ;
this . _continueBound = this . _continue . bind ( this ) ;
this . _scheduleNextBound = this . _scheduleNext . bind ( this ) ;
this . _nextBound = this . _next . bind ( this ) ;
this . _canvas = params . canvasContext . canvas ;
}
get completed ( ) {
return this . capability . promise . catch ( function ( ) { } ) ;
}
initializeGraphics ( {
transparency = false ,
optionalContentConfig
} ) {
if ( this . cancelled ) {
return ;
}
if ( this . _canvas ) {
if ( InternalRenderTask . # canvasInUse . has ( this . _canvas ) ) {
throw new Error ( "Cannot use the same canvas during multiple render() operations. " + "Use different canvas or ensure previous operations were " + "cancelled or completed." ) ;
}
InternalRenderTask . # canvasInUse . add ( this . _canvas ) ;
}
if ( this . _pdfBug && globalThis . StepperManager ? . enabled ) {
this . stepper = globalThis . StepperManager . create ( this . _pageIndex ) ;
this . stepper . init ( this . operatorList ) ;
this . stepper . nextBreakPoint = this . stepper . getNextBreakPoint ( ) ;
}
const {
canvasContext ,
viewport ,
transform ,
background
} = this . params ;
this . gfx = new CanvasGraphics ( canvasContext , this . commonObjs , this . objs , this . canvasFactory , this . filterFactory , {
optionalContentConfig
} , this . annotationCanvasMap , this . pageColors ) ;
this . gfx . beginDrawing ( {
transform ,
viewport ,
transparency ,
background
} ) ;
this . operatorListIdx = 0 ;
this . graphicsReady = true ;
this . graphicsReadyCallback ? . ( ) ;
}
cancel ( error = null , extraDelay = 0 ) {
this . running = false ;
this . cancelled = true ;
this . gfx ? . endDrawing ( ) ;
InternalRenderTask . # canvasInUse . delete ( this . _canvas ) ;
this . callback ( error || new RenderingCancelledException ( ` Rendering cancelled, page ${ this . _pageIndex + 1 } ` , extraDelay ) ) ;
}
operatorListChanged ( ) {
if ( ! this . graphicsReady ) {
this . graphicsReadyCallback || = this . _continueBound ;
return ;
}
this . stepper ? . updateOperatorList ( this . operatorList ) ;
if ( this . running ) {
return ;
}
this . _continue ( ) ;
}
_continue ( ) {
this . running = true ;
if ( this . cancelled ) {
return ;
}
if ( this . task . onContinue ) {
this . task . onContinue ( this . _scheduleNextBound ) ;
} else {
this . _scheduleNext ( ) ;
}
}
_scheduleNext ( ) {
if ( this . _useRequestAnimationFrame ) {
window . requestAnimationFrame ( ( ) => {
this . _nextBound ( ) . catch ( this . _cancelBound ) ;
} ) ;
} else {
Promise . resolve ( ) . then ( this . _nextBound ) . catch ( this . _cancelBound ) ;
}
}
async _next ( ) {
if ( this . cancelled ) {
return ;
}
this . operatorListIdx = this . gfx . executeOperatorList ( this . operatorList , this . operatorListIdx , this . _continueBound , this . stepper ) ;
if ( this . operatorListIdx === this . operatorList . argsArray . length ) {
this . running = false ;
if ( this . operatorList . lastChunk ) {
this . gfx . endDrawing ( ) ;
InternalRenderTask . # canvasInUse . delete ( this . _canvas ) ;
this . callback ( ) ;
}
}
}
}
2024-06-18 20:06:52 +02:00
const version = "4.4.82" ;
const build = "8c6cee28e" ;
2024-06-01 11:00:27 +01:00
2024-06-18 20:06:52 +02:00
// EXTERNAL MODULE: ./node_modules/core-js/modules/esnext.iterator.flat-map.js
var esnext _iterator _flat _map = _ _webpack _require _ _ ( 670 ) ;
2024-06-01 11:00:27 +01:00
; // CONCATENATED MODULE: ./src/shared/scripting_utils.js
2024-06-18 20:06:52 +02:00
2024-06-01 11:00:27 +01:00
function makeColorComp ( n ) {
return Math . floor ( Math . max ( 0 , Math . min ( 1 , n ) ) * 255 ) . toString ( 16 ) . padStart ( 2 , "0" ) ;
}
function scaleAndClamp ( x ) {
return Math . max ( 0 , Math . min ( 255 , 255 * x ) ) ;
}
class ColorConverters {
static CMYK _G ( [ c , y , m , k ] ) {
return [ "G" , 1 - Math . min ( 1 , 0.3 * c + 0.59 * m + 0.11 * y + k ) ] ;
}
static G _CMYK ( [ g ] ) {
return [ "CMYK" , 0 , 0 , 0 , 1 - g ] ;
}
static G _RGB ( [ g ] ) {
return [ "RGB" , g , g , g ] ;
}
static G _rgb ( [ g ] ) {
g = scaleAndClamp ( g ) ;
return [ g , g , g ] ;
}
static G _HTML ( [ g ] ) {
const G = makeColorComp ( g ) ;
return ` # ${ G } ${ G } ${ G } ` ;
}
static RGB _G ( [ r , g , b ] ) {
return [ "G" , 0.3 * r + 0.59 * g + 0.11 * b ] ;
}
static RGB _rgb ( color ) {
return color . map ( scaleAndClamp ) ;
}
static RGB _HTML ( color ) {
return ` # ${ color . map ( makeColorComp ) . join ( "" ) } ` ;
}
static T _HTML ( ) {
return "#00000000" ;
}
static T _rgb ( ) {
return [ null ] ;
}
static CMYK _RGB ( [ c , y , m , k ] ) {
return [ "RGB" , 1 - Math . min ( 1 , c + k ) , 1 - Math . min ( 1 , m + k ) , 1 - Math . min ( 1 , y + k ) ] ;
}
static CMYK _rgb ( [ c , y , m , k ] ) {
return [ scaleAndClamp ( 1 - Math . min ( 1 , c + k ) ) , scaleAndClamp ( 1 - Math . min ( 1 , m + k ) ) , scaleAndClamp ( 1 - Math . min ( 1 , y + k ) ) ] ;
}
static CMYK _HTML ( components ) {
const rgb = this . CMYK _RGB ( components ) . slice ( 1 ) ;
return this . RGB _HTML ( rgb ) ;
}
static RGB _CMYK ( [ r , g , b ] ) {
const c = 1 - r ;
const m = 1 - g ;
const y = 1 - b ;
const k = Math . min ( c , m , y ) ;
return [ "CMYK" , c , m , y , k ] ;
}
}
; // CONCATENATED MODULE: ./src/display/xfa_layer.js
2024-06-18 20:06:52 +02:00
2024-06-01 11:00:27 +01:00
class XfaLayer {
static setupStorage ( html , id , element , storage , intent ) {
const storedData = storage . getValue ( id , {
value : null
} ) ;
switch ( element . name ) {
case "textarea" :
if ( storedData . value !== null ) {
html . textContent = storedData . value ;
}
if ( intent === "print" ) {
break ;
}
html . addEventListener ( "input" , event => {
storage . setValue ( id , {
value : event . target . value
} ) ;
} ) ;
break ;
case "input" :
if ( element . attributes . type === "radio" || element . attributes . type === "checkbox" ) {
if ( storedData . value === element . attributes . xfaOn ) {
html . setAttribute ( "checked" , true ) ;
} else if ( storedData . value === element . attributes . xfaOff ) {
html . removeAttribute ( "checked" ) ;
}
if ( intent === "print" ) {
break ;
}
html . addEventListener ( "change" , event => {
storage . setValue ( id , {
value : event . target . checked ? event . target . getAttribute ( "xfaOn" ) : event . target . getAttribute ( "xfaOff" )
} ) ;
} ) ;
} else {
if ( storedData . value !== null ) {
html . setAttribute ( "value" , storedData . value ) ;
}
if ( intent === "print" ) {
break ;
}
html . addEventListener ( "input" , event => {
storage . setValue ( id , {
value : event . target . value
} ) ;
} ) ;
}
break ;
case "select" :
if ( storedData . value !== null ) {
html . setAttribute ( "value" , storedData . value ) ;
for ( const option of element . children ) {
if ( option . attributes . value === storedData . value ) {
option . attributes . selected = true ;
} else if ( option . attributes . hasOwnProperty ( "selected" ) ) {
delete option . attributes . selected ;
}
}
}
html . addEventListener ( "input" , event => {
const options = event . target . options ;
const value = options . selectedIndex === - 1 ? "" : options [ options . selectedIndex ] . value ;
storage . setValue ( id , {
value
} ) ;
} ) ;
break ;
}
}
static setAttributes ( {
html ,
element ,
storage = null ,
intent ,
linkService
} ) {
const {
attributes
} = element ;
const isHTMLAnchorElement = html instanceof HTMLAnchorElement ;
if ( attributes . type === "radio" ) {
attributes . name = ` ${ attributes . name } - ${ intent } ` ;
}
for ( const [ key , value ] of Object . entries ( attributes ) ) {
if ( value === null || value === undefined ) {
continue ;
}
switch ( key ) {
case "class" :
if ( value . length ) {
html . setAttribute ( key , value . join ( " " ) ) ;
}
break ;
case "dataId" :
break ;
case "id" :
html . setAttribute ( "data-element-id" , value ) ;
break ;
case "style" :
Object . assign ( html . style , value ) ;
break ;
case "textContent" :
html . textContent = value ;
break ;
default :
if ( ! isHTMLAnchorElement || key !== "href" && key !== "newWindow" ) {
html . setAttribute ( key , value ) ;
}
}
}
if ( isHTMLAnchorElement ) {
linkService . addLinkAttributes ( html , attributes . href , attributes . newWindow ) ;
}
if ( storage && attributes . dataId ) {
this . setupStorage ( html , attributes . dataId , element , storage ) ;
}
}
static render ( parameters ) {
const storage = parameters . annotationStorage ;
const linkService = parameters . linkService ;
const root = parameters . xfaHtml ;
const intent = parameters . intent || "display" ;
const rootHtml = document . createElement ( root . name ) ;
if ( root . attributes ) {
this . setAttributes ( {
html : rootHtml ,
element : root ,
intent ,
linkService
} ) ;
}
const isNotForRichText = intent !== "richText" ;
const rootDiv = parameters . div ;
rootDiv . append ( rootHtml ) ;
if ( parameters . viewport ) {
const transform = ` matrix( ${ parameters . viewport . transform . join ( "," ) } ) ` ;
rootDiv . style . transform = transform ;
}
if ( isNotForRichText ) {
rootDiv . setAttribute ( "class" , "xfaLayer xfaFont" ) ;
}
const textDivs = [ ] ;
if ( root . children . length === 0 ) {
if ( root . value ) {
const node = document . createTextNode ( root . value ) ;
rootHtml . append ( node ) ;
if ( isNotForRichText && XfaText . shouldBuildText ( root . name ) ) {
textDivs . push ( node ) ;
}
}
return {
textDivs
} ;
}
const stack = [ [ root , - 1 , rootHtml ] ] ;
while ( stack . length > 0 ) {
const [ parent , i , html ] = stack . at ( - 1 ) ;
if ( i + 1 === parent . children . length ) {
stack . pop ( ) ;
continue ;
}
const child = parent . children [ ++ stack . at ( - 1 ) [ 1 ] ] ;
if ( child === null ) {
continue ;
}
const {
name
} = child ;
if ( name === "#text" ) {
const node = document . createTextNode ( child . value ) ;
textDivs . push ( node ) ;
html . append ( node ) ;
continue ;
}
const childHtml = child ? . attributes ? . xmlns ? document . createElementNS ( child . attributes . xmlns , name ) : document . createElement ( name ) ;
html . append ( childHtml ) ;
if ( child . attributes ) {
this . setAttributes ( {
html : childHtml ,
element : child ,
storage ,
intent ,
linkService
} ) ;
}
if ( child . children ? . length > 0 ) {
stack . push ( [ child , - 1 , childHtml ] ) ;
} else if ( child . value ) {
const node = document . createTextNode ( child . value ) ;
if ( isNotForRichText && XfaText . shouldBuildText ( name ) ) {
textDivs . push ( node ) ;
}
childHtml . append ( node ) ;
}
}
for ( const el of rootDiv . querySelectorAll ( ".xfaNonInteractive input, .xfaNonInteractive textarea" ) ) {
el . setAttribute ( "readOnly" , true ) ;
}
return {
textDivs
} ;
}
static update ( parameters ) {
const transform = ` matrix( ${ parameters . viewport . transform . join ( "," ) } ) ` ;
parameters . div . style . transform = transform ;
parameters . div . hidden = false ;
}
}
; // CONCATENATED MODULE: ./src/display/annotation_layer.js
2024-06-18 20:06:52 +02:00
2024-06-01 11:00:27 +01:00
const DEFAULT _TAB _INDEX = 1000 ;
const annotation _layer _DEFAULT _FONT _SIZE = 9 ;
const GetElementsByNameSet = new WeakSet ( ) ;
function getRectDims ( rect ) {
return {
width : rect [ 2 ] - rect [ 0 ] ,
height : rect [ 3 ] - rect [ 1 ]
} ;
}
class AnnotationElementFactory {
static create ( parameters ) {
const subtype = parameters . data . annotationType ;
switch ( subtype ) {
case AnnotationType . LINK :
return new LinkAnnotationElement ( parameters ) ;
case AnnotationType . TEXT :
return new TextAnnotationElement ( parameters ) ;
case AnnotationType . WIDGET :
const fieldType = parameters . data . fieldType ;
switch ( fieldType ) {
case "Tx" :
return new TextWidgetAnnotationElement ( parameters ) ;
case "Btn" :
if ( parameters . data . radioButton ) {
return new RadioButtonWidgetAnnotationElement ( parameters ) ;
} else if ( parameters . data . checkBox ) {
return new CheckboxWidgetAnnotationElement ( parameters ) ;
}
return new PushButtonWidgetAnnotationElement ( parameters ) ;
case "Ch" :
return new ChoiceWidgetAnnotationElement ( parameters ) ;
case "Sig" :
return new SignatureWidgetAnnotationElement ( parameters ) ;
}
return new WidgetAnnotationElement ( parameters ) ;
case AnnotationType . POPUP :
return new PopupAnnotationElement ( parameters ) ;
case AnnotationType . FREETEXT :
return new FreeTextAnnotationElement ( parameters ) ;
case AnnotationType . LINE :
return new LineAnnotationElement ( parameters ) ;
case AnnotationType . SQUARE :
return new SquareAnnotationElement ( parameters ) ;
case AnnotationType . CIRCLE :
return new CircleAnnotationElement ( parameters ) ;
case AnnotationType . POLYLINE :
return new PolylineAnnotationElement ( parameters ) ;
case AnnotationType . CARET :
return new CaretAnnotationElement ( parameters ) ;
case AnnotationType . INK :
return new InkAnnotationElement ( parameters ) ;
case AnnotationType . POLYGON :
return new PolygonAnnotationElement ( parameters ) ;
case AnnotationType . HIGHLIGHT :
return new HighlightAnnotationElement ( parameters ) ;
case AnnotationType . UNDERLINE :
return new UnderlineAnnotationElement ( parameters ) ;
case AnnotationType . SQUIGGLY :
return new SquigglyAnnotationElement ( parameters ) ;
case AnnotationType . STRIKEOUT :
return new StrikeOutAnnotationElement ( parameters ) ;
case AnnotationType . STAMP :
return new StampAnnotationElement ( parameters ) ;
case AnnotationType . FILEATTACHMENT :
return new FileAttachmentAnnotationElement ( parameters ) ;
default :
return new AnnotationElement ( parameters ) ;
}
}
}
class AnnotationElement {
# updates = null ;
# hasBorder = false ;
# popupElement = null ;
constructor ( parameters , {
isRenderable = false ,
ignoreBorder = false ,
createQuadrilaterals = false
} = { } ) {
this . isRenderable = isRenderable ;
this . data = parameters . data ;
this . layer = parameters . layer ;
this . linkService = parameters . linkService ;
this . downloadManager = parameters . downloadManager ;
this . imageResourcesPath = parameters . imageResourcesPath ;
this . renderForms = parameters . renderForms ;
this . svgFactory = parameters . svgFactory ;
this . annotationStorage = parameters . annotationStorage ;
this . enableScripting = parameters . enableScripting ;
this . hasJSActions = parameters . hasJSActions ;
this . _fieldObjects = parameters . fieldObjects ;
this . parent = parameters . parent ;
if ( isRenderable ) {
this . container = this . _createContainer ( ignoreBorder ) ;
}
if ( createQuadrilaterals ) {
this . _createQuadrilaterals ( ) ;
}
}
static _hasPopupData ( {
titleObj ,
contentsObj ,
richText
} ) {
return ! ! ( titleObj ? . str || contentsObj ? . str || richText ? . str ) ;
}
get hasPopupData ( ) {
return AnnotationElement . _hasPopupData ( this . data ) ;
}
updateEdited ( params ) {
if ( ! this . container ) {
return ;
}
this . # updates || = {
rect : this . data . rect . slice ( 0 )
} ;
const {
rect
} = params ;
if ( rect ) {
this . # setRectEdited ( rect ) ;
}
this . # popupElement ? . popup . updateEdited ( params ) ;
}
resetEdited ( ) {
if ( ! this . # updates ) {
return ;
}
this . # setRectEdited ( this . # updates . rect ) ;
this . # popupElement ? . popup . resetEdited ( ) ;
this . # updates = null ;
}
# setRectEdited ( rect ) {
const {
container : {
style
} ,
data : {
rect : currentRect ,
rotation
} ,
parent : {
viewport : {
rawDims : {
pageWidth ,
pageHeight ,
pageX ,
pageY
}
}
}
} = this ;
currentRect ? . splice ( 0 , 4 , ... rect ) ;
const {
width ,
height
} = getRectDims ( rect ) ;
style . left = ` ${ 100 * ( rect [ 0 ] - pageX ) / pageWidth } % ` ;
style . top = ` ${ 100 * ( pageHeight - rect [ 3 ] + pageY ) / pageHeight } % ` ;
if ( rotation === 0 ) {
style . width = ` ${ 100 * width / pageWidth } % ` ;
style . height = ` ${ 100 * height / pageHeight } % ` ;
} else {
this . setRotation ( rotation ) ;
}
}
_createContainer ( ignoreBorder ) {
const {
data ,
parent : {
page ,
viewport
}
} = this ;
const container = document . createElement ( "section" ) ;
container . setAttribute ( "data-annotation-id" , data . id ) ;
if ( ! ( this instanceof WidgetAnnotationElement ) ) {
container . tabIndex = DEFAULT _TAB _INDEX ;
}
const {
style
} = container ;
style . zIndex = this . parent . zIndex ++ ;
if ( data . popupRef ) {
container . setAttribute ( "aria-haspopup" , "dialog" ) ;
}
if ( data . alternativeText ) {
container . title = data . alternativeText ;
}
if ( data . noRotate ) {
container . classList . add ( "norotate" ) ;
}
if ( ! data . rect || this instanceof PopupAnnotationElement ) {
const {
rotation
} = data ;
if ( ! data . hasOwnCanvas && rotation !== 0 ) {
this . setRotation ( rotation , container ) ;
}
return container ;
}
const {
width ,
height
} = getRectDims ( data . rect ) ;
if ( ! ignoreBorder && data . borderStyle . width > 0 ) {
style . borderWidth = ` ${ data . borderStyle . width } px ` ;
const horizontalRadius = data . borderStyle . horizontalCornerRadius ;
const verticalRadius = data . borderStyle . verticalCornerRadius ;
if ( horizontalRadius > 0 || verticalRadius > 0 ) {
const radius = ` calc( ${ horizontalRadius } px * var(--scale-factor)) / calc( ${ verticalRadius } px * var(--scale-factor)) ` ;
style . borderRadius = radius ;
} else if ( this instanceof RadioButtonWidgetAnnotationElement ) {
const radius = ` calc( ${ width } px * var(--scale-factor)) / calc( ${ height } px * var(--scale-factor)) ` ;
style . borderRadius = radius ;
}
switch ( data . borderStyle . style ) {
case AnnotationBorderStyleType . SOLID :
style . borderStyle = "solid" ;
break ;
case AnnotationBorderStyleType . DASHED :
style . borderStyle = "dashed" ;
break ;
case AnnotationBorderStyleType . BEVELED :
warn ( "Unimplemented border style: beveled" ) ;
break ;
case AnnotationBorderStyleType . INSET :
warn ( "Unimplemented border style: inset" ) ;
break ;
case AnnotationBorderStyleType . UNDERLINE :
style . borderBottomStyle = "solid" ;
break ;
default :
break ;
}
const borderColor = data . borderColor || null ;
if ( borderColor ) {
this . # hasBorder = true ;
style . borderColor = Util . makeHexColor ( borderColor [ 0 ] | 0 , borderColor [ 1 ] | 0 , borderColor [ 2 ] | 0 ) ;
} else {
style . borderWidth = 0 ;
}
}
const rect = Util . normalizeRect ( [ data . rect [ 0 ] , page . view [ 3 ] - data . rect [ 1 ] + page . view [ 1 ] , data . rect [ 2 ] , page . view [ 3 ] - data . rect [ 3 ] + page . view [ 1 ] ] ) ;
const {
pageWidth ,
pageHeight ,
pageX ,
pageY
} = viewport . rawDims ;
style . left = ` ${ 100 * ( rect [ 0 ] - pageX ) / pageWidth } % ` ;
style . top = ` ${ 100 * ( rect [ 1 ] - pageY ) / pageHeight } % ` ;
const {
rotation
} = data ;
if ( data . hasOwnCanvas || rotation === 0 ) {
style . width = ` ${ 100 * width / pageWidth } % ` ;
style . height = ` ${ 100 * height / pageHeight } % ` ;
} else {
this . setRotation ( rotation , container ) ;
}
return container ;
}
setRotation ( angle , container = this . container ) {
if ( ! this . data . rect ) {
return ;
}
const {
pageWidth ,
pageHeight
} = this . parent . viewport . rawDims ;
const {
width ,
height
} = getRectDims ( this . data . rect ) ;
let elementWidth , elementHeight ;
if ( angle % 180 === 0 ) {
elementWidth = 100 * width / pageWidth ;
elementHeight = 100 * height / pageHeight ;
} else {
elementWidth = 100 * height / pageWidth ;
elementHeight = 100 * width / pageHeight ;
}
container . style . width = ` ${ elementWidth } % ` ;
container . style . height = ` ${ elementHeight } % ` ;
container . setAttribute ( "data-main-rotation" , ( 360 - angle ) % 360 ) ;
}
get _commonActions ( ) {
const setColor = ( jsName , styleName , event ) => {
const color = event . detail [ jsName ] ;
const colorType = color [ 0 ] ;
const colorArray = color . slice ( 1 ) ;
event . target . style [ styleName ] = ColorConverters [ ` ${ colorType } _HTML ` ] ( colorArray ) ;
this . annotationStorage . setValue ( this . data . id , {
[ styleName ] : ColorConverters [ ` ${ colorType } _rgb ` ] ( colorArray )
} ) ;
} ;
return shadow ( this , "_commonActions" , {
display : event => {
const {
display
} = event . detail ;
const hidden = display % 2 === 1 ;
this . container . style . visibility = hidden ? "hidden" : "visible" ;
this . annotationStorage . setValue ( this . data . id , {
noView : hidden ,
noPrint : display === 1 || display === 2
} ) ;
} ,
print : event => {
this . annotationStorage . setValue ( this . data . id , {
noPrint : ! event . detail . print
} ) ;
} ,
hidden : event => {
const {
hidden
} = event . detail ;
this . container . style . visibility = hidden ? "hidden" : "visible" ;
this . annotationStorage . setValue ( this . data . id , {
noPrint : hidden ,
noView : hidden
} ) ;
} ,
focus : event => {
setTimeout ( ( ) => event . target . focus ( {
preventScroll : false
} ) , 0 ) ;
} ,
userName : event => {
event . target . title = event . detail . userName ;
} ,
readonly : event => {
event . target . disabled = event . detail . readonly ;
} ,
required : event => {
this . _setRequired ( event . target , event . detail . required ) ;
} ,
bgColor : event => {
setColor ( "bgColor" , "backgroundColor" , event ) ;
} ,
fillColor : event => {
setColor ( "fillColor" , "backgroundColor" , event ) ;
} ,
fgColor : event => {
setColor ( "fgColor" , "color" , event ) ;
} ,
textColor : event => {
setColor ( "textColor" , "color" , event ) ;
} ,
borderColor : event => {
setColor ( "borderColor" , "borderColor" , event ) ;
} ,
strokeColor : event => {
setColor ( "strokeColor" , "borderColor" , event ) ;
} ,
rotation : event => {
const angle = event . detail . rotation ;
this . setRotation ( angle ) ;
this . annotationStorage . setValue ( this . data . id , {
rotation : angle
} ) ;
}
} ) ;
}
_dispatchEventFromSandbox ( actions , jsEvent ) {
const commonActions = this . _commonActions ;
for ( const name of Object . keys ( jsEvent . detail ) ) {
const action = actions [ name ] || commonActions [ name ] ;
action ? . ( jsEvent ) ;
}
}
_setDefaultPropertiesFromJS ( element ) {
if ( ! this . enableScripting ) {
return ;
}
const storedData = this . annotationStorage . getRawValue ( this . data . id ) ;
if ( ! storedData ) {
return ;
}
const commonActions = this . _commonActions ;
for ( const [ actionName , detail ] of Object . entries ( storedData ) ) {
const action = commonActions [ actionName ] ;
if ( action ) {
const eventProxy = {
detail : {
[ actionName ] : detail
} ,
target : element
} ;
action ( eventProxy ) ;
delete storedData [ actionName ] ;
}
}
}
_createQuadrilaterals ( ) {
if ( ! this . container ) {
return ;
}
const {
quadPoints
} = this . data ;
if ( ! quadPoints ) {
return ;
}
2024-06-02 09:12:22 +01:00
const [ rectBlX , rectBlY , rectTrX , rectTrY ] = this . data . rect . map ( x => Math . fround ( x ) ) ;
if ( quadPoints . length === 8 ) {
const [ trX , trY , blX , blY ] = quadPoints . subarray ( 2 , 6 ) ;
2024-06-01 11:00:27 +01:00
if ( rectTrX === trX && rectTrY === trY && rectBlX === blX && rectBlY === blY ) {
return ;
}
}
const {
style
} = this . container ;
let svgBuffer ;
if ( this . # hasBorder ) {
const {
borderColor ,
borderWidth
} = style ;
style . borderWidth = 0 ;
svgBuffer = [ "url('data:image/svg+xml;utf8," , ` <svg xmlns="http://www.w3.org/2000/svg" ` , ` preserveAspectRatio="none" viewBox="0 0 1 1"> ` , ` <g fill="transparent" stroke=" ${ borderColor } " stroke-width=" ${ borderWidth } "> ` ] ;
this . container . classList . add ( "hasBorder" ) ;
}
const width = rectTrX - rectBlX ;
const height = rectTrY - rectBlY ;
const {
svgFactory
} = this ;
const svg = svgFactory . createElement ( "svg" ) ;
svg . classList . add ( "quadrilateralsContainer" ) ;
svg . setAttribute ( "width" , 0 ) ;
svg . setAttribute ( "height" , 0 ) ;
const defs = svgFactory . createElement ( "defs" ) ;
svg . append ( defs ) ;
const clipPath = svgFactory . createElement ( "clipPath" ) ;
const id = ` clippath_ ${ this . data . id } ` ;
clipPath . setAttribute ( "id" , id ) ;
clipPath . setAttribute ( "clipPathUnits" , "objectBoundingBox" ) ;
defs . append ( clipPath ) ;
2024-06-02 09:12:22 +01:00
for ( let i = 2 , ii = quadPoints . length ; i < ii ; i += 8 ) {
const trX = quadPoints [ i ] ;
const trY = quadPoints [ i + 1 ] ;
const blX = quadPoints [ i + 2 ] ;
const blY = quadPoints [ i + 3 ] ;
2024-06-01 11:00:27 +01:00
const rect = svgFactory . createElement ( "rect" ) ;
const x = ( blX - rectBlX ) / width ;
const y = ( rectTrY - trY ) / height ;
const rectWidth = ( trX - blX ) / width ;
const rectHeight = ( trY - blY ) / height ;
rect . setAttribute ( "x" , x ) ;
rect . setAttribute ( "y" , y ) ;
rect . setAttribute ( "width" , rectWidth ) ;
rect . setAttribute ( "height" , rectHeight ) ;
clipPath . append ( rect ) ;
svgBuffer ? . push ( ` <rect vector-effect="non-scaling-stroke" x=" ${ x } " y=" ${ y } " width=" ${ rectWidth } " height=" ${ rectHeight } "/> ` ) ;
}
if ( this . # hasBorder ) {
svgBuffer . push ( ` </g></svg>') ` ) ;
style . backgroundImage = svgBuffer . join ( "" ) ;
}
this . container . append ( svg ) ;
this . container . style . clipPath = ` url(# ${ id } ) ` ;
}
_createPopup ( ) {
const {
container ,
data
} = this ;
container . setAttribute ( "aria-haspopup" , "dialog" ) ;
const popup = this . # popupElement = new PopupAnnotationElement ( {
data : {
color : data . color ,
titleObj : data . titleObj ,
modificationDate : data . modificationDate ,
contentsObj : data . contentsObj ,
richText : data . richText ,
parentRect : data . rect ,
borderStyle : 0 ,
id : ` popup_ ${ data . id } ` ,
rotation : data . rotation
} ,
parent : this . parent ,
elements : [ this ]
} ) ;
this . parent . div . append ( popup . render ( ) ) ;
}
render ( ) {
unreachable ( "Abstract method `AnnotationElement.render` called" ) ;
}
_getElementsByName ( name , skipId = null ) {
const fields = [ ] ;
if ( this . _fieldObjects ) {
const fieldObj = this . _fieldObjects [ name ] ;
if ( fieldObj ) {
for ( const {
page ,
id ,
exportValues
} of fieldObj ) {
if ( page === - 1 ) {
continue ;
}
if ( id === skipId ) {
continue ;
}
const exportValue = typeof exportValues === "string" ? exportValues : null ;
const domElement = document . querySelector ( ` [data-element-id=" ${ id } "] ` ) ;
if ( domElement && ! GetElementsByNameSet . has ( domElement ) ) {
warn ( ` _getElementsByName - element not allowed: ${ id } ` ) ;
continue ;
}
fields . push ( {
id ,
exportValue ,
domElement
} ) ;
}
}
return fields ;
}
for ( const domElement of document . getElementsByName ( name ) ) {
const {
exportValue
} = domElement ;
const id = domElement . getAttribute ( "data-element-id" ) ;
if ( id === skipId ) {
continue ;
}
if ( ! GetElementsByNameSet . has ( domElement ) ) {
continue ;
}
fields . push ( {
id ,
exportValue ,
domElement
} ) ;
}
return fields ;
}
show ( ) {
if ( this . container ) {
this . container . hidden = false ;
}
this . popup ? . maybeShow ( ) ;
}
hide ( ) {
if ( this . container ) {
this . container . hidden = true ;
}
this . popup ? . forceHide ( ) ;
}
getElementsToTriggerPopup ( ) {
return this . container ;
}
addHighlightArea ( ) {
const triggers = this . getElementsToTriggerPopup ( ) ;
if ( Array . isArray ( triggers ) ) {
for ( const element of triggers ) {
element . classList . add ( "highlightArea" ) ;
}
} else {
triggers . classList . add ( "highlightArea" ) ;
}
}
get _isEditable ( ) {
return false ;
}
_editOnDoubleClick ( ) {
if ( ! this . _isEditable ) {
return ;
}
const {
annotationEditorType : mode ,
data : {
id : editId
}
} = this ;
this . container . addEventListener ( "dblclick" , ( ) => {
this . linkService . eventBus ? . dispatch ( "switchannotationeditormode" , {
source : this ,
mode ,
editId
} ) ;
} ) ;
}
}
class LinkAnnotationElement extends AnnotationElement {
constructor ( parameters , options = null ) {
super ( parameters , {
isRenderable : true ,
ignoreBorder : ! ! options ? . ignoreBorder ,
createQuadrilaterals : true
} ) ;
this . isTooltipOnly = parameters . data . isTooltipOnly ;
}
render ( ) {
const {
data ,
linkService
} = this ;
const link = document . createElement ( "a" ) ;
link . setAttribute ( "data-element-id" , data . id ) ;
let isBound = false ;
if ( data . url ) {
linkService . addLinkAttributes ( link , data . url , data . newWindow ) ;
isBound = true ;
} else if ( data . action ) {
this . _bindNamedAction ( link , data . action ) ;
isBound = true ;
} else if ( data . attachment ) {
this . # bindAttachment ( link , data . attachment , data . attachmentDest ) ;
isBound = true ;
} else if ( data . setOCGState ) {
this . # bindSetOCGState ( link , data . setOCGState ) ;
isBound = true ;
} else if ( data . dest ) {
this . _bindLink ( link , data . dest ) ;
isBound = true ;
} else {
if ( data . actions && ( data . actions . Action || data . actions [ "Mouse Up" ] || data . actions [ "Mouse Down" ] ) && this . enableScripting && this . hasJSActions ) {
this . _bindJSAction ( link , data ) ;
isBound = true ;
}
if ( data . resetForm ) {
this . _bindResetFormAction ( link , data . resetForm ) ;
isBound = true ;
} else if ( this . isTooltipOnly && ! isBound ) {
this . _bindLink ( link , "" ) ;
isBound = true ;
}
}
this . container . classList . add ( "linkAnnotation" ) ;
if ( isBound ) {
this . container . append ( link ) ;
}
return this . container ;
}
# setInternalLink ( ) {
this . container . setAttribute ( "data-internal-link" , "" ) ;
}
_bindLink ( link , destination ) {
link . href = this . linkService . getDestinationHash ( destination ) ;
link . onclick = ( ) => {
if ( destination ) {
this . linkService . goToDestination ( destination ) ;
}
return false ;
} ;
if ( destination || destination === "" ) {
this . # setInternalLink ( ) ;
}
}
_bindNamedAction ( link , action ) {
link . href = this . linkService . getAnchorUrl ( "" ) ;
link . onclick = ( ) => {
this . linkService . executeNamedAction ( action ) ;
return false ;
} ;
this . # setInternalLink ( ) ;
}
# bindAttachment ( link , attachment , dest = null ) {
link . href = this . linkService . getAnchorUrl ( "" ) ;
if ( attachment . description ) {
link . title = attachment . description ;
}
link . onclick = ( ) => {
this . downloadManager ? . openOrDownloadData ( attachment . content , attachment . filename , dest ) ;
return false ;
} ;
this . # setInternalLink ( ) ;
}
# bindSetOCGState ( link , action ) {
link . href = this . linkService . getAnchorUrl ( "" ) ;
link . onclick = ( ) => {
this . linkService . executeSetOCGState ( action ) ;
return false ;
} ;
this . # setInternalLink ( ) ;
}
_bindJSAction ( link , data ) {
link . href = this . linkService . getAnchorUrl ( "" ) ;
const map = new Map ( [ [ "Action" , "onclick" ] , [ "Mouse Up" , "onmouseup" ] , [ "Mouse Down" , "onmousedown" ] ] ) ;
for ( const name of Object . keys ( data . actions ) ) {
const jsName = map . get ( name ) ;
if ( ! jsName ) {
continue ;
}
link [ jsName ] = ( ) => {
this . linkService . eventBus ? . dispatch ( "dispatcheventinsandbox" , {
source : this ,
detail : {
id : data . id ,
name
}
} ) ;
return false ;
} ;
}
if ( ! link . onclick ) {
link . onclick = ( ) => false ;
}
this . # setInternalLink ( ) ;
}
_bindResetFormAction ( link , resetForm ) {
const otherClickAction = link . onclick ;
if ( ! otherClickAction ) {
link . href = this . linkService . getAnchorUrl ( "" ) ;
}
this . # setInternalLink ( ) ;
if ( ! this . _fieldObjects ) {
warn ( ` _bindResetFormAction - "resetForm" action not supported, ` + "ensure that the `fieldObjects` parameter is provided." ) ;
if ( ! otherClickAction ) {
link . onclick = ( ) => false ;
}
return ;
}
link . onclick = ( ) => {
otherClickAction ? . ( ) ;
const {
fields : resetFormFields ,
refs : resetFormRefs ,
include
} = resetForm ;
const allFields = [ ] ;
if ( resetFormFields . length !== 0 || resetFormRefs . length !== 0 ) {
const fieldIds = new Set ( resetFormRefs ) ;
for ( const fieldName of resetFormFields ) {
const fields = this . _fieldObjects [ fieldName ] || [ ] ;
for ( const {
id
} of fields ) {
fieldIds . add ( id ) ;
}
}
for ( const fields of Object . values ( this . _fieldObjects ) ) {
for ( const field of fields ) {
if ( fieldIds . has ( field . id ) === include ) {
allFields . push ( field ) ;
}
}
}
} else {
for ( const fields of Object . values ( this . _fieldObjects ) ) {
allFields . push ( ... fields ) ;
}
}
const storage = this . annotationStorage ;
const allIds = [ ] ;
for ( const field of allFields ) {
const {
id
} = field ;
allIds . push ( id ) ;
switch ( field . type ) {
case "text" :
{
const value = field . defaultValue || "" ;
storage . setValue ( id , {
value
} ) ;
break ;
}
case "checkbox" :
case "radiobutton" :
{
const value = field . defaultValue === field . exportValues ;
storage . setValue ( id , {
value
} ) ;
break ;
}
case "combobox" :
case "listbox" :
{
const value = field . defaultValue || "" ;
storage . setValue ( id , {
value
} ) ;
break ;
}
default :
continue ;
}
const domElement = document . querySelector ( ` [data-element-id=" ${ id } "] ` ) ;
if ( ! domElement ) {
continue ;
} else if ( ! GetElementsByNameSet . has ( domElement ) ) {
warn ( ` _bindResetFormAction - element not allowed: ${ id } ` ) ;
continue ;
}
domElement . dispatchEvent ( new Event ( "resetform" ) ) ;
}
if ( this . enableScripting ) {
this . linkService . eventBus ? . dispatch ( "dispatcheventinsandbox" , {
source : this ,
detail : {
id : "app" ,
ids : allIds ,
name : "ResetForm"
}
} ) ;
}
return false ;
} ;
}
}
class TextAnnotationElement extends AnnotationElement {
constructor ( parameters ) {
super ( parameters , {
isRenderable : true
} ) ;
}
render ( ) {
this . container . classList . add ( "textAnnotation" ) ;
const image = document . createElement ( "img" ) ;
image . src = this . imageResourcesPath + "annotation-" + this . data . name . toLowerCase ( ) + ".svg" ;
image . setAttribute ( "data-l10n-id" , "pdfjs-text-annotation-type" ) ;
image . setAttribute ( "data-l10n-args" , JSON . stringify ( {
type : this . data . name
} ) ) ;
if ( ! this . data . popupRef && this . hasPopupData ) {
this . _createPopup ( ) ;
}
this . container . append ( image ) ;
return this . container ;
}
}
class WidgetAnnotationElement extends AnnotationElement {
render ( ) {
return this . container ;
}
showElementAndHideCanvas ( element ) {
if ( this . data . hasOwnCanvas ) {
if ( element . previousSibling ? . nodeName === "CANVAS" ) {
element . previousSibling . hidden = true ;
}
element . hidden = false ;
}
}
_getKeyModifier ( event ) {
return util _FeatureTest . platform . isMac ? event . metaKey : event . ctrlKey ;
}
_setEventListener ( element , elementData , baseName , eventName , valueGetter ) {
if ( baseName . includes ( "mouse" ) ) {
element . addEventListener ( baseName , event => {
this . linkService . eventBus ? . dispatch ( "dispatcheventinsandbox" , {
source : this ,
detail : {
id : this . data . id ,
name : eventName ,
value : valueGetter ( event ) ,
shift : event . shiftKey ,
modifier : this . _getKeyModifier ( event )
}
} ) ;
} ) ;
} else {
element . addEventListener ( baseName , event => {
if ( baseName === "blur" ) {
if ( ! elementData . focused || ! event . relatedTarget ) {
return ;
}
elementData . focused = false ;
} else if ( baseName === "focus" ) {
if ( elementData . focused ) {
return ;
}
elementData . focused = true ;
}
if ( ! valueGetter ) {
return ;
}
this . linkService . eventBus ? . dispatch ( "dispatcheventinsandbox" , {
source : this ,
detail : {
id : this . data . id ,
name : eventName ,
value : valueGetter ( event )
}
} ) ;
} ) ;
}
}
_setEventListeners ( element , elementData , names , getter ) {
for ( const [ baseName , eventName ] of names ) {
if ( eventName === "Action" || this . data . actions ? . [ eventName ] ) {
if ( eventName === "Focus" || eventName === "Blur" ) {
elementData || = {
focused : false
} ;
}
this . _setEventListener ( element , elementData , baseName , eventName , getter ) ;
if ( eventName === "Focus" && ! this . data . actions ? . Blur ) {
this . _setEventListener ( element , elementData , "blur" , "Blur" , null ) ;
} else if ( eventName === "Blur" && ! this . data . actions ? . Focus ) {
this . _setEventListener ( element , elementData , "focus" , "Focus" , null ) ;
}
}
}
}
_setBackgroundColor ( element ) {
const color = this . data . backgroundColor || null ;
element . style . backgroundColor = color === null ? "transparent" : Util . makeHexColor ( color [ 0 ] , color [ 1 ] , color [ 2 ] ) ;
}
_setTextStyle ( element ) {
const TEXT _ALIGNMENT = [ "left" , "center" , "right" ] ;
const {
fontColor
} = this . data . defaultAppearanceData ;
const fontSize = this . data . defaultAppearanceData . fontSize || annotation _layer _DEFAULT _FONT _SIZE ;
const style = element . style ;
let computedFontSize ;
const BORDER _SIZE = 2 ;
const roundToOneDecimal = x => Math . round ( 10 * x ) / 10 ;
if ( this . data . multiLine ) {
const height = Math . abs ( this . data . rect [ 3 ] - this . data . rect [ 1 ] - BORDER _SIZE ) ;
const numberOfLines = Math . round ( height / ( LINE _FACTOR * fontSize ) ) || 1 ;
const lineHeight = height / numberOfLines ;
computedFontSize = Math . min ( fontSize , roundToOneDecimal ( lineHeight / LINE _FACTOR ) ) ;
} else {
const height = Math . abs ( this . data . rect [ 3 ] - this . data . rect [ 1 ] - BORDER _SIZE ) ;
computedFontSize = Math . min ( fontSize , roundToOneDecimal ( height / LINE _FACTOR ) ) ;
}
style . fontSize = ` calc( ${ computedFontSize } px * var(--scale-factor)) ` ;
style . color = Util . makeHexColor ( fontColor [ 0 ] , fontColor [ 1 ] , fontColor [ 2 ] ) ;
if ( this . data . textAlignment !== null ) {
style . textAlign = TEXT _ALIGNMENT [ this . data . textAlignment ] ;
}
}
_setRequired ( element , isRequired ) {
if ( isRequired ) {
element . setAttribute ( "required" , true ) ;
} else {
element . removeAttribute ( "required" ) ;
}
element . setAttribute ( "aria-required" , isRequired ) ;
}
}
class TextWidgetAnnotationElement extends WidgetAnnotationElement {
constructor ( parameters ) {
const isRenderable = parameters . renderForms || parameters . data . hasOwnCanvas || ! parameters . data . hasAppearance && ! ! parameters . data . fieldValue ;
super ( parameters , {
isRenderable
} ) ;
}
setPropertyOnSiblings ( base , key , value , keyInStorage ) {
const storage = this . annotationStorage ;
for ( const element of this . _getElementsByName ( base . name , base . id ) ) {
if ( element . domElement ) {
element . domElement [ key ] = value ;
}
storage . setValue ( element . id , {
[ keyInStorage ] : value
} ) ;
}
}
render ( ) {
const storage = this . annotationStorage ;
const id = this . data . id ;
this . container . classList . add ( "textWidgetAnnotation" ) ;
let element = null ;
if ( this . renderForms ) {
const storedData = storage . getValue ( id , {
value : this . data . fieldValue
} ) ;
let textContent = storedData . value || "" ;
const maxLen = storage . getValue ( id , {
charLimit : this . data . maxLen
} ) . charLimit ;
if ( maxLen && textContent . length > maxLen ) {
textContent = textContent . slice ( 0 , maxLen ) ;
}
let fieldFormattedValues = storedData . formattedValue || this . data . textContent ? . join ( "\n" ) || null ;
if ( fieldFormattedValues && this . data . comb ) {
fieldFormattedValues = fieldFormattedValues . replaceAll ( /\s+/g , "" ) ;
}
const elementData = {
userValue : textContent ,
formattedValue : fieldFormattedValues ,
lastCommittedValue : null ,
commitKey : 1 ,
focused : false
} ;
if ( this . data . multiLine ) {
element = document . createElement ( "textarea" ) ;
element . textContent = fieldFormattedValues ? ? textContent ;
if ( this . data . doNotScroll ) {
element . style . overflowY = "hidden" ;
}
} else {
element = document . createElement ( "input" ) ;
element . type = "text" ;
element . setAttribute ( "value" , fieldFormattedValues ? ? textContent ) ;
if ( this . data . doNotScroll ) {
element . style . overflowX = "hidden" ;
}
}
if ( this . data . hasOwnCanvas ) {
element . hidden = true ;
}
GetElementsByNameSet . add ( element ) ;
element . setAttribute ( "data-element-id" , id ) ;
element . disabled = this . data . readOnly ;
element . name = this . data . fieldName ;
element . tabIndex = DEFAULT _TAB _INDEX ;
this . _setRequired ( element , this . data . required ) ;
if ( maxLen ) {
element . maxLength = maxLen ;
}
element . addEventListener ( "input" , event => {
storage . setValue ( id , {
value : event . target . value
} ) ;
this . setPropertyOnSiblings ( element , "value" , event . target . value , "value" ) ;
elementData . formattedValue = null ;
} ) ;
element . addEventListener ( "resetform" , event => {
const defaultValue = this . data . defaultFieldValue ? ? "" ;
element . value = elementData . userValue = defaultValue ;
elementData . formattedValue = null ;
} ) ;
let blurListener = event => {
const {
formattedValue
} = elementData ;
if ( formattedValue !== null && formattedValue !== undefined ) {
event . target . value = formattedValue ;
}
event . target . scrollLeft = 0 ;
} ;
if ( this . enableScripting && this . hasJSActions ) {
element . addEventListener ( "focus" , event => {
if ( elementData . focused ) {
return ;
}
const {
target
} = event ;
if ( elementData . userValue ) {
target . value = elementData . userValue ;
}
elementData . lastCommittedValue = target . value ;
elementData . commitKey = 1 ;
if ( ! this . data . actions ? . Focus ) {
elementData . focused = true ;
}
} ) ;
element . addEventListener ( "updatefromsandbox" , jsEvent => {
this . showElementAndHideCanvas ( jsEvent . target ) ;
const actions = {
value ( event ) {
elementData . userValue = event . detail . value ? ? "" ;
storage . setValue ( id , {
value : elementData . userValue . toString ( )
} ) ;
event . target . value = elementData . userValue ;
} ,
formattedValue ( event ) {
const {
formattedValue
} = event . detail ;
elementData . formattedValue = formattedValue ;
if ( formattedValue !== null && formattedValue !== undefined && event . target !== document . activeElement ) {
event . target . value = formattedValue ;
}
storage . setValue ( id , {
formattedValue
} ) ;
} ,
selRange ( event ) {
event . target . setSelectionRange ( ... event . detail . selRange ) ;
} ,
charLimit : event => {
const {
charLimit
} = event . detail ;
const {
target
} = event ;
if ( charLimit === 0 ) {
target . removeAttribute ( "maxLength" ) ;
return ;
}
target . setAttribute ( "maxLength" , charLimit ) ;
let value = elementData . userValue ;
if ( ! value || value . length <= charLimit ) {
return ;
}
value = value . slice ( 0 , charLimit ) ;
target . value = elementData . userValue = value ;
storage . setValue ( id , {
value
} ) ;
this . linkService . eventBus ? . dispatch ( "dispatcheventinsandbox" , {
source : this ,
detail : {
id ,
name : "Keystroke" ,
value ,
willCommit : true ,
commitKey : 1 ,
selStart : target . selectionStart ,
selEnd : target . selectionEnd
}
} ) ;
}
} ;
this . _dispatchEventFromSandbox ( actions , jsEvent ) ;
} ) ;
element . addEventListener ( "keydown" , event => {
elementData . commitKey = 1 ;
let commitKey = - 1 ;
if ( event . key === "Escape" ) {
commitKey = 0 ;
} else if ( event . key === "Enter" && ! this . data . multiLine ) {
commitKey = 2 ;
} else if ( event . key === "Tab" ) {
elementData . commitKey = 3 ;
}
if ( commitKey === - 1 ) {
return ;
}
const {
value
} = event . target ;
if ( elementData . lastCommittedValue === value ) {
return ;
}
elementData . lastCommittedValue = value ;
elementData . userValue = value ;
this . linkService . eventBus ? . dispatch ( "dispatcheventinsandbox" , {
source : this ,
detail : {
id ,
name : "Keystroke" ,
value ,
willCommit : true ,
commitKey ,
selStart : event . target . selectionStart ,
selEnd : event . target . selectionEnd
}
} ) ;
} ) ;
const _blurListener = blurListener ;
blurListener = null ;
element . addEventListener ( "blur" , event => {
if ( ! elementData . focused || ! event . relatedTarget ) {
return ;
}
if ( ! this . data . actions ? . Blur ) {
elementData . focused = false ;
}
const {
value
} = event . target ;
elementData . userValue = value ;
if ( elementData . lastCommittedValue !== value ) {
this . linkService . eventBus ? . dispatch ( "dispatcheventinsandbox" , {
source : this ,
detail : {
id ,
name : "Keystroke" ,
value ,
willCommit : true ,
commitKey : elementData . commitKey ,
selStart : event . target . selectionStart ,
selEnd : event . target . selectionEnd
}
} ) ;
}
_blurListener ( event ) ;
} ) ;
if ( this . data . actions ? . Keystroke ) {
element . addEventListener ( "beforeinput" , event => {
elementData . lastCommittedValue = null ;
const {
data ,
target
} = event ;
const {
value ,
selectionStart ,
selectionEnd
} = target ;
let selStart = selectionStart ,
selEnd = selectionEnd ;
switch ( event . inputType ) {
case "deleteWordBackward" :
{
const match = value . substring ( 0 , selectionStart ) . match ( /\w*[^\w]*$/ ) ;
if ( match ) {
selStart -= match [ 0 ] . length ;
}
break ;
}
case "deleteWordForward" :
{
const match = value . substring ( selectionStart ) . match ( /^[^\w]*\w*/ ) ;
if ( match ) {
selEnd += match [ 0 ] . length ;
}
break ;
}
case "deleteContentBackward" :
if ( selectionStart === selectionEnd ) {
selStart -= 1 ;
}
break ;
case "deleteContentForward" :
if ( selectionStart === selectionEnd ) {
selEnd += 1 ;
}
break ;
}
event . preventDefault ( ) ;
this . linkService . eventBus ? . dispatch ( "dispatcheventinsandbox" , {
source : this ,
detail : {
id ,
name : "Keystroke" ,
value ,
change : data || "" ,
willCommit : false ,
selStart ,
selEnd
}
} ) ;
} ) ;
}
this . _setEventListeners ( element , elementData , [ [ "focus" , "Focus" ] , [ "blur" , "Blur" ] , [ "mousedown" , "Mouse Down" ] , [ "mouseenter" , "Mouse Enter" ] , [ "mouseleave" , "Mouse Exit" ] , [ "mouseup" , "Mouse Up" ] ] , event => event . target . value ) ;
}
if ( blurListener ) {
element . addEventListener ( "blur" , blurListener ) ;
}
if ( this . data . comb ) {
const fieldWidth = this . data . rect [ 2 ] - this . data . rect [ 0 ] ;
const combWidth = fieldWidth / maxLen ;
element . classList . add ( "comb" ) ;
element . style . letterSpacing = ` calc( ${ combWidth } px * var(--scale-factor) - 1ch) ` ;
}
} else {
element = document . createElement ( "div" ) ;
element . textContent = this . data . fieldValue ;
element . style . verticalAlign = "middle" ;
element . style . display = "table-cell" ;
if ( this . data . hasOwnCanvas ) {
element . hidden = true ;
}
}
this . _setTextStyle ( element ) ;
this . _setBackgroundColor ( element ) ;
this . _setDefaultPropertiesFromJS ( element ) ;
this . container . append ( element ) ;
return this . container ;
}
}
class SignatureWidgetAnnotationElement extends WidgetAnnotationElement {
constructor ( parameters ) {
super ( parameters , {
isRenderable : ! ! parameters . data . hasOwnCanvas
} ) ;
}
}
class CheckboxWidgetAnnotationElement extends WidgetAnnotationElement {
constructor ( parameters ) {
super ( parameters , {
isRenderable : parameters . renderForms
} ) ;
}
render ( ) {
const storage = this . annotationStorage ;
const data = this . data ;
const id = data . id ;
let value = storage . getValue ( id , {
value : data . exportValue === data . fieldValue
} ) . value ;
if ( typeof value === "string" ) {
value = value !== "Off" ;
storage . setValue ( id , {
value
} ) ;
}
this . container . classList . add ( "buttonWidgetAnnotation" , "checkBox" ) ;
const element = document . createElement ( "input" ) ;
GetElementsByNameSet . add ( element ) ;
element . setAttribute ( "data-element-id" , id ) ;
element . disabled = data . readOnly ;
this . _setRequired ( element , this . data . required ) ;
element . type = "checkbox" ;
element . name = data . fieldName ;
if ( value ) {
element . setAttribute ( "checked" , true ) ;
}
element . setAttribute ( "exportValue" , data . exportValue ) ;
element . tabIndex = DEFAULT _TAB _INDEX ;
element . addEventListener ( "change" , event => {
const {
name ,
checked
} = event . target ;
for ( const checkbox of this . _getElementsByName ( name , id ) ) {
const curChecked = checked && checkbox . exportValue === data . exportValue ;
if ( checkbox . domElement ) {
checkbox . domElement . checked = curChecked ;
}
storage . setValue ( checkbox . id , {
value : curChecked
} ) ;
}
storage . setValue ( id , {
value : checked
} ) ;
} ) ;
element . addEventListener ( "resetform" , event => {
const defaultValue = data . defaultFieldValue || "Off" ;
event . target . checked = defaultValue === data . exportValue ;
} ) ;
if ( this . enableScripting && this . hasJSActions ) {
element . addEventListener ( "updatefromsandbox" , jsEvent => {
const actions = {
value ( event ) {
event . target . checked = event . detail . value !== "Off" ;
storage . setValue ( id , {
value : event . target . checked
} ) ;
}
} ;
this . _dispatchEventFromSandbox ( actions , jsEvent ) ;
} ) ;
this . _setEventListeners ( element , null , [ [ "change" , "Validate" ] , [ "change" , "Action" ] , [ "focus" , "Focus" ] , [ "blur" , "Blur" ] , [ "mousedown" , "Mouse Down" ] , [ "mouseenter" , "Mouse Enter" ] , [ "mouseleave" , "Mouse Exit" ] , [ "mouseup" , "Mouse Up" ] ] , event => event . target . checked ) ;
}
this . _setBackgroundColor ( element ) ;
this . _setDefaultPropertiesFromJS ( element ) ;
this . container . append ( element ) ;
return this . container ;
}
}
class RadioButtonWidgetAnnotationElement extends WidgetAnnotationElement {
constructor ( parameters ) {
super ( parameters , {
isRenderable : parameters . renderForms
} ) ;
}
render ( ) {
this . container . classList . add ( "buttonWidgetAnnotation" , "radioButton" ) ;
const storage = this . annotationStorage ;
const data = this . data ;
const id = data . id ;
let value = storage . getValue ( id , {
value : data . fieldValue === data . buttonValue
} ) . value ;
if ( typeof value === "string" ) {
value = value !== data . buttonValue ;
storage . setValue ( id , {
value
} ) ;
}
if ( value ) {
for ( const radio of this . _getElementsByName ( data . fieldName , id ) ) {
storage . setValue ( radio . id , {
value : false
} ) ;
}
}
const element = document . createElement ( "input" ) ;
GetElementsByNameSet . add ( element ) ;
element . setAttribute ( "data-element-id" , id ) ;
element . disabled = data . readOnly ;
this . _setRequired ( element , this . data . required ) ;
element . type = "radio" ;
element . name = data . fieldName ;
if ( value ) {
element . setAttribute ( "checked" , true ) ;
}
element . tabIndex = DEFAULT _TAB _INDEX ;
element . addEventListener ( "change" , event => {
const {
name ,
checked
} = event . target ;
for ( const radio of this . _getElementsByName ( name , id ) ) {
storage . setValue ( radio . id , {
value : false
} ) ;
}
storage . setValue ( id , {
value : checked
} ) ;
} ) ;
element . addEventListener ( "resetform" , event => {
const defaultValue = data . defaultFieldValue ;
event . target . checked = defaultValue !== null && defaultValue !== undefined && defaultValue === data . buttonValue ;
} ) ;
if ( this . enableScripting && this . hasJSActions ) {
const pdfButtonValue = data . buttonValue ;
element . addEventListener ( "updatefromsandbox" , jsEvent => {
const actions = {
value : event => {
const checked = pdfButtonValue === event . detail . value ;
for ( const radio of this . _getElementsByName ( event . target . name ) ) {
const curChecked = checked && radio . id === id ;
if ( radio . domElement ) {
radio . domElement . checked = curChecked ;
}
storage . setValue ( radio . id , {
value : curChecked
} ) ;
}
}
} ;
this . _dispatchEventFromSandbox ( actions , jsEvent ) ;
} ) ;
this . _setEventListeners ( element , null , [ [ "change" , "Validate" ] , [ "change" , "Action" ] , [ "focus" , "Focus" ] , [ "blur" , "Blur" ] , [ "mousedown" , "Mouse Down" ] , [ "mouseenter" , "Mouse Enter" ] , [ "mouseleave" , "Mouse Exit" ] , [ "mouseup" , "Mouse Up" ] ] , event => event . target . checked ) ;
}
this . _setBackgroundColor ( element ) ;
this . _setDefaultPropertiesFromJS ( element ) ;
this . container . append ( element ) ;
return this . container ;
}
}
class PushButtonWidgetAnnotationElement extends LinkAnnotationElement {
constructor ( parameters ) {
super ( parameters , {
ignoreBorder : parameters . data . hasAppearance
} ) ;
}
render ( ) {
const container = super . render ( ) ;
container . classList . add ( "buttonWidgetAnnotation" , "pushButton" ) ;
const linkElement = container . lastChild ;
if ( this . enableScripting && this . hasJSActions && linkElement ) {
this . _setDefaultPropertiesFromJS ( linkElement ) ;
linkElement . addEventListener ( "updatefromsandbox" , jsEvent => {
this . _dispatchEventFromSandbox ( { } , jsEvent ) ;
} ) ;
}
return container ;
}
}
class ChoiceWidgetAnnotationElement extends WidgetAnnotationElement {
constructor ( parameters ) {
super ( parameters , {
isRenderable : parameters . renderForms
} ) ;
}
render ( ) {
this . container . classList . add ( "choiceWidgetAnnotation" ) ;
const storage = this . annotationStorage ;
const id = this . data . id ;
const storedData = storage . getValue ( id , {
value : this . data . fieldValue
} ) ;
const selectElement = document . createElement ( "select" ) ;
GetElementsByNameSet . add ( selectElement ) ;
selectElement . setAttribute ( "data-element-id" , id ) ;
selectElement . disabled = this . data . readOnly ;
this . _setRequired ( selectElement , this . data . required ) ;
selectElement . name = this . data . fieldName ;
selectElement . tabIndex = DEFAULT _TAB _INDEX ;
let addAnEmptyEntry = this . data . combo && this . data . options . length > 0 ;
if ( ! this . data . combo ) {
selectElement . size = this . data . options . length ;
if ( this . data . multiSelect ) {
selectElement . multiple = true ;
}
}
selectElement . addEventListener ( "resetform" , event => {
const defaultValue = this . data . defaultFieldValue ;
for ( const option of selectElement . options ) {
option . selected = option . value === defaultValue ;
}
} ) ;
for ( const option of this . data . options ) {
const optionElement = document . createElement ( "option" ) ;
optionElement . textContent = option . displayValue ;
optionElement . value = option . exportValue ;
if ( storedData . value . includes ( option . exportValue ) ) {
optionElement . setAttribute ( "selected" , true ) ;
addAnEmptyEntry = false ;
}
selectElement . append ( optionElement ) ;
}
let removeEmptyEntry = null ;
if ( addAnEmptyEntry ) {
const noneOptionElement = document . createElement ( "option" ) ;
noneOptionElement . value = " " ;
noneOptionElement . setAttribute ( "hidden" , true ) ;
noneOptionElement . setAttribute ( "selected" , true ) ;
selectElement . prepend ( noneOptionElement ) ;
removeEmptyEntry = ( ) => {
noneOptionElement . remove ( ) ;
selectElement . removeEventListener ( "input" , removeEmptyEntry ) ;
removeEmptyEntry = null ;
} ;
selectElement . addEventListener ( "input" , removeEmptyEntry ) ;
}
const getValue = isExport => {
const name = isExport ? "value" : "textContent" ;
const {
options ,
multiple
} = selectElement ;
if ( ! multiple ) {
return options . selectedIndex === - 1 ? null : options [ options . selectedIndex ] [ name ] ;
}
return Array . prototype . filter . call ( options , option => option . selected ) . map ( option => option [ name ] ) ;
} ;
let selectedValues = getValue ( false ) ;
const getItems = event => {
const options = event . target . options ;
return Array . prototype . map . call ( options , option => ( {
displayValue : option . textContent ,
exportValue : option . value
} ) ) ;
} ;
if ( this . enableScripting && this . hasJSActions ) {
selectElement . addEventListener ( "updatefromsandbox" , jsEvent => {
const actions = {
value ( event ) {
removeEmptyEntry ? . ( ) ;
const value = event . detail . value ;
const values = new Set ( Array . isArray ( value ) ? value : [ value ] ) ;
for ( const option of selectElement . options ) {
option . selected = values . has ( option . value ) ;
}
storage . setValue ( id , {
value : getValue ( true )
} ) ;
selectedValues = getValue ( false ) ;
} ,
multipleSelection ( event ) {
selectElement . multiple = true ;
} ,
remove ( event ) {
const options = selectElement . options ;
const index = event . detail . remove ;
options [ index ] . selected = false ;
selectElement . remove ( index ) ;
if ( options . length > 0 ) {
const i = Array . prototype . findIndex . call ( options , option => option . selected ) ;
if ( i === - 1 ) {
options [ 0 ] . selected = true ;
}
}
storage . setValue ( id , {
value : getValue ( true ) ,
items : getItems ( event )
} ) ;
selectedValues = getValue ( false ) ;
} ,
clear ( event ) {
while ( selectElement . length !== 0 ) {
selectElement . remove ( 0 ) ;
}
storage . setValue ( id , {
value : null ,
items : [ ]
} ) ;
selectedValues = getValue ( false ) ;
} ,
insert ( event ) {
const {
index ,
displayValue ,
exportValue
} = event . detail . insert ;
const selectChild = selectElement . children [ index ] ;
const optionElement = document . createElement ( "option" ) ;
optionElement . textContent = displayValue ;
optionElement . value = exportValue ;
if ( selectChild ) {
selectChild . before ( optionElement ) ;
} else {
selectElement . append ( optionElement ) ;
}
storage . setValue ( id , {
value : getValue ( true ) ,
items : getItems ( event )
} ) ;
selectedValues = getValue ( false ) ;
} ,
items ( event ) {
const {
items
} = event . detail ;
while ( selectElement . length !== 0 ) {
selectElement . remove ( 0 ) ;
}
for ( const item of items ) {
const {
displayValue ,
exportValue
} = item ;
const optionElement = document . createElement ( "option" ) ;
optionElement . textContent = displayValue ;
optionElement . value = exportValue ;
selectElement . append ( optionElement ) ;
}
if ( selectElement . options . length > 0 ) {
selectElement . options [ 0 ] . selected = true ;
}
storage . setValue ( id , {
value : getValue ( true ) ,
items : getItems ( event )
} ) ;
selectedValues = getValue ( false ) ;
} ,
indices ( event ) {
const indices = new Set ( event . detail . indices ) ;
for ( const option of event . target . options ) {
option . selected = indices . has ( option . index ) ;
}
storage . setValue ( id , {
value : getValue ( true )
} ) ;
selectedValues = getValue ( false ) ;
} ,
editable ( event ) {
event . target . disabled = ! event . detail . editable ;
}
} ;
this . _dispatchEventFromSandbox ( actions , jsEvent ) ;
} ) ;
selectElement . addEventListener ( "input" , event => {
const exportValue = getValue ( true ) ;
const change = getValue ( false ) ;
storage . setValue ( id , {
value : exportValue
} ) ;
event . preventDefault ( ) ;
this . linkService . eventBus ? . dispatch ( "dispatcheventinsandbox" , {
source : this ,
detail : {
id ,
name : "Keystroke" ,
value : selectedValues ,
change ,
changeEx : exportValue ,
willCommit : false ,
commitKey : 1 ,
keyDown : false
}
} ) ;
} ) ;
this . _setEventListeners ( selectElement , null , [ [ "focus" , "Focus" ] , [ "blur" , "Blur" ] , [ "mousedown" , "Mouse Down" ] , [ "mouseenter" , "Mouse Enter" ] , [ "mouseleave" , "Mouse Exit" ] , [ "mouseup" , "Mouse Up" ] , [ "input" , "Action" ] , [ "input" , "Validate" ] ] , event => event . target . value ) ;
} else {
selectElement . addEventListener ( "input" , function ( event ) {
storage . setValue ( id , {
value : getValue ( true )
} ) ;
} ) ;
}
if ( this . data . combo ) {
this . _setTextStyle ( selectElement ) ;
} else { }
this . _setBackgroundColor ( selectElement ) ;
this . _setDefaultPropertiesFromJS ( selectElement ) ;
this . container . append ( selectElement ) ;
return this . container ;
}
}
class PopupAnnotationElement extends AnnotationElement {
constructor ( parameters ) {
const {
data ,
elements
} = parameters ;
super ( parameters , {
isRenderable : AnnotationElement . _hasPopupData ( data )
} ) ;
this . elements = elements ;
this . popup = null ;
}
render ( ) {
this . container . classList . add ( "popupAnnotation" ) ;
const popup = this . popup = new PopupElement ( {
container : this . container ,
color : this . data . color ,
titleObj : this . data . titleObj ,
modificationDate : this . data . modificationDate ,
contentsObj : this . data . contentsObj ,
richText : this . data . richText ,
rect : this . data . rect ,
parentRect : this . data . parentRect || null ,
parent : this . parent ,
elements : this . elements ,
open : this . data . open
} ) ;
const elementIds = [ ] ;
for ( const element of this . elements ) {
element . popup = popup ;
elementIds . push ( element . data . id ) ;
element . addHighlightArea ( ) ;
}
this . container . setAttribute ( "aria-controls" , elementIds . map ( id => ` ${ AnnotationPrefix } ${ id } ` ) . join ( "," ) ) ;
return this . container ;
}
}
class PopupElement {
# boundKeyDown = this . # keyDown . bind ( this ) ;
# boundHide = this . # hide . bind ( this ) ;
# boundShow = this . # show . bind ( this ) ;
# boundToggle = this . # toggle . bind ( this ) ;
# color = null ;
# container = null ;
# contentsObj = null ;
# dateObj = null ;
# elements = null ;
# parent = null ;
# parentRect = null ;
# pinned = false ;
# popup = null ;
# position = null ;
# rect = null ;
# richText = null ;
# titleObj = null ;
# updates = null ;
# wasVisible = false ;
constructor ( {
container ,
color ,
elements ,
titleObj ,
modificationDate ,
contentsObj ,
richText ,
parent ,
rect ,
parentRect ,
open
} ) {
this . # container = container ;
this . # titleObj = titleObj ;
this . # contentsObj = contentsObj ;
this . # richText = richText ;
this . # parent = parent ;
this . # color = color ;
this . # rect = rect ;
this . # parentRect = parentRect ;
this . # elements = elements ;
this . # dateObj = PDFDateString . toDateObject ( modificationDate ) ;
this . trigger = elements . flatMap ( e => e . getElementsToTriggerPopup ( ) ) ;
for ( const element of this . trigger ) {
element . addEventListener ( "click" , this . # boundToggle ) ;
element . addEventListener ( "mouseenter" , this . # boundShow ) ;
element . addEventListener ( "mouseleave" , this . # boundHide ) ;
element . classList . add ( "popupTriggerArea" ) ;
}
for ( const element of elements ) {
element . container ? . addEventListener ( "keydown" , this . # boundKeyDown ) ;
}
this . # container . hidden = true ;
if ( open ) {
this . # toggle ( ) ;
}
}
render ( ) {
if ( this . # popup ) {
return ;
}
const popup = this . # popup = document . createElement ( "div" ) ;
popup . className = "popup" ;
if ( this . # color ) {
const baseColor = popup . style . outlineColor = Util . makeHexColor ( ... this . # color ) ;
if ( CSS . supports ( "background-color" , "color-mix(in srgb, red 30%, white)" ) ) {
popup . style . backgroundColor = ` color-mix(in srgb, ${ baseColor } 30%, white) ` ;
} else {
const BACKGROUND _ENLIGHT = 0.7 ;
popup . style . backgroundColor = Util . makeHexColor ( ... this . # color . map ( c => Math . floor ( BACKGROUND _ENLIGHT * ( 255 - c ) + c ) ) ) ;
}
}
const header = document . createElement ( "span" ) ;
header . className = "header" ;
const title = document . createElement ( "h1" ) ;
header . append ( title ) ;
( {
dir : title . dir ,
str : title . textContent
} = this . # titleObj ) ;
popup . append ( header ) ;
if ( this . # dateObj ) {
const modificationDate = document . createElement ( "span" ) ;
modificationDate . classList . add ( "popupDate" ) ;
modificationDate . setAttribute ( "data-l10n-id" , "pdfjs-annotation-date-string" ) ;
modificationDate . setAttribute ( "data-l10n-args" , JSON . stringify ( {
date : this . # dateObj . toLocaleDateString ( ) ,
time : this . # dateObj . toLocaleTimeString ( )
} ) ) ;
header . append ( modificationDate ) ;
}
const html = this . # html ;
if ( html ) {
XfaLayer . render ( {
xfaHtml : html ,
intent : "richText" ,
div : popup
} ) ;
popup . lastChild . classList . add ( "richText" , "popupContent" ) ;
} else {
const contents = this . _formatContents ( this . # contentsObj ) ;
popup . append ( contents ) ;
}
this . # container . append ( popup ) ;
}
get # html ( ) {
const richText = this . # richText ;
const contentsObj = this . # contentsObj ;
if ( richText ? . str && ( ! contentsObj ? . str || contentsObj . str === richText . str ) ) {
return this . # richText . html || null ;
}
return null ;
}
get # fontSize ( ) {
return this . # html ? . attributes ? . style ? . fontSize || 0 ;
}
get # fontColor ( ) {
return this . # html ? . attributes ? . style ? . color || null ;
}
# makePopupContent ( text ) {
const popupLines = [ ] ;
const popupContent = {
str : text ,
html : {
name : "div" ,
attributes : {
dir : "auto"
} ,
children : [ {
name : "p" ,
children : popupLines
} ]
}
} ;
const lineAttributes = {
style : {
color : this . # fontColor ,
fontSize : this . # fontSize ? ` calc( ${ this . # fontSize } px * var(--scale-factor)) ` : ""
}
} ;
for ( const line of text . split ( "\n" ) ) {
popupLines . push ( {
name : "span" ,
value : line ,
attributes : lineAttributes
} ) ;
}
return popupContent ;
}
_formatContents ( {
str ,
dir
} ) {
const p = document . createElement ( "p" ) ;
p . classList . add ( "popupContent" ) ;
p . dir = dir ;
const lines = str . split ( /(?:\r\n?|\n)/ ) ;
for ( let i = 0 , ii = lines . length ; i < ii ; ++ i ) {
const line = lines [ i ] ;
p . append ( document . createTextNode ( line ) ) ;
if ( i < ii - 1 ) {
p . append ( document . createElement ( "br" ) ) ;
}
}
return p ;
}
# keyDown ( event ) {
if ( event . altKey || event . shiftKey || event . ctrlKey || event . metaKey ) {
return ;
}
if ( event . key === "Enter" || event . key === "Escape" && this . # pinned ) {
this . # toggle ( ) ;
}
}
updateEdited ( {
rect ,
popupContent
} ) {
this . # updates || = {
contentsObj : this . # contentsObj ,
richText : this . # richText
} ;
if ( rect ) {
this . # position = null ;
}
if ( popupContent ) {
this . # richText = this . # makePopupContent ( popupContent ) ;
this . # contentsObj = null ;
}
this . # popup ? . remove ( ) ;
this . # popup = null ;
}
resetEdited ( ) {
if ( ! this . # updates ) {
return ;
}
( {
contentsObj : this . # contentsObj ,
richText : this . # richText
} = this . # updates ) ;
this . # updates = null ;
this . # popup ? . remove ( ) ;
this . # popup = null ;
this . # position = null ;
}
# setPosition ( ) {
if ( this . # position !== null ) {
return ;
}
const {
page : {
view
} ,
viewport : {
rawDims : {
pageWidth ,
pageHeight ,
pageX ,
pageY
}
}
} = this . # parent ;
let useParentRect = ! ! this . # parentRect ;
let rect = useParentRect ? this . # parentRect : this . # rect ;
for ( const element of this . # elements ) {
if ( ! rect || Util . intersect ( element . data . rect , rect ) !== null ) {
rect = element . data . rect ;
useParentRect = true ;
break ;
}
}
const normalizedRect = Util . normalizeRect ( [ rect [ 0 ] , view [ 3 ] - rect [ 1 ] + view [ 1 ] , rect [ 2 ] , view [ 3 ] - rect [ 3 ] + view [ 1 ] ] ) ;
const HORIZONTAL _SPACE _AFTER _ANNOTATION = 5 ;
const parentWidth = useParentRect ? rect [ 2 ] - rect [ 0 ] + HORIZONTAL _SPACE _AFTER _ANNOTATION : 0 ;
const popupLeft = normalizedRect [ 0 ] + parentWidth ;
const popupTop = normalizedRect [ 1 ] ;
this . # position = [ 100 * ( popupLeft - pageX ) / pageWidth , 100 * ( popupTop - pageY ) / pageHeight ] ;
const {
style
} = this . # container ;
style . left = ` ${ this . # position [ 0 ] } % ` ;
style . top = ` ${ this . # position [ 1 ] } % ` ;
}
# toggle ( ) {
this . # pinned = ! this . # pinned ;
if ( this . # pinned ) {
this . # show ( ) ;
this . # container . addEventListener ( "click" , this . # boundToggle ) ;
this . # container . addEventListener ( "keydown" , this . # boundKeyDown ) ;
} else {
this . # hide ( ) ;
this . # container . removeEventListener ( "click" , this . # boundToggle ) ;
this . # container . removeEventListener ( "keydown" , this . # boundKeyDown ) ;
}
}
# show ( ) {
if ( ! this . # popup ) {
this . render ( ) ;
}
if ( ! this . isVisible ) {
this . # setPosition ( ) ;
this . # container . hidden = false ;
this . # container . style . zIndex = parseInt ( this . # container . style . zIndex ) + 1000 ;
} else if ( this . # pinned ) {
this . # container . classList . add ( "focused" ) ;
}
}
# hide ( ) {
this . # container . classList . remove ( "focused" ) ;
if ( this . # pinned || ! this . isVisible ) {
return ;
}
this . # container . hidden = true ;
this . # container . style . zIndex = parseInt ( this . # container . style . zIndex ) - 1000 ;
}
forceHide ( ) {
this . # wasVisible = this . isVisible ;
if ( ! this . # wasVisible ) {
return ;
}
this . # container . hidden = true ;
}
maybeShow ( ) {
if ( ! this . # wasVisible ) {
return ;
}
if ( ! this . # popup ) {
this . # show ( ) ;
}
this . # wasVisible = false ;
this . # container . hidden = false ;
}
get isVisible ( ) {
return this . # container . hidden === false ;
}
}
class FreeTextAnnotationElement extends AnnotationElement {
constructor ( parameters ) {
super ( parameters , {
isRenderable : true ,
ignoreBorder : true
} ) ;
this . textContent = parameters . data . textContent ;
this . textPosition = parameters . data . textPosition ;
this . annotationEditorType = AnnotationEditorType . FREETEXT ;
}
render ( ) {
this . container . classList . add ( "freeTextAnnotation" ) ;
if ( this . textContent ) {
const content = document . createElement ( "div" ) ;
content . classList . add ( "annotationTextContent" ) ;
content . setAttribute ( "role" , "comment" ) ;
for ( const line of this . textContent ) {
const lineSpan = document . createElement ( "span" ) ;
lineSpan . textContent = line ;
content . append ( lineSpan ) ;
}
this . container . append ( content ) ;
}
if ( ! this . data . popupRef && this . hasPopupData ) {
this . _createPopup ( ) ;
}
this . _editOnDoubleClick ( ) ;
return this . container ;
}
get _isEditable ( ) {
return this . data . hasOwnCanvas ;
}
}
class LineAnnotationElement extends AnnotationElement {
# line = null ;
constructor ( parameters ) {
super ( parameters , {
isRenderable : true ,
ignoreBorder : true
} ) ;
}
render ( ) {
this . container . classList . add ( "lineAnnotation" ) ;
const data = this . data ;
const {
width ,
height
} = getRectDims ( data . rect ) ;
const svg = this . svgFactory . create ( width , height , true ) ;
const line = this . # line = this . svgFactory . createElement ( "svg:line" ) ;
line . setAttribute ( "x1" , data . rect [ 2 ] - data . lineCoordinates [ 0 ] ) ;
line . setAttribute ( "y1" , data . rect [ 3 ] - data . lineCoordinates [ 1 ] ) ;
line . setAttribute ( "x2" , data . rect [ 2 ] - data . lineCoordinates [ 2 ] ) ;
line . setAttribute ( "y2" , data . rect [ 3 ] - data . lineCoordinates [ 3 ] ) ;
line . setAttribute ( "stroke-width" , data . borderStyle . width || 1 ) ;
line . setAttribute ( "stroke" , "transparent" ) ;
line . setAttribute ( "fill" , "transparent" ) ;
svg . append ( line ) ;
this . container . append ( svg ) ;
if ( ! data . popupRef && this . hasPopupData ) {
this . _createPopup ( ) ;
}
return this . container ;
}
getElementsToTriggerPopup ( ) {
return this . # line ;
}
addHighlightArea ( ) {
this . container . classList . add ( "highlightArea" ) ;
}
}
class SquareAnnotationElement extends AnnotationElement {
# square = null ;
constructor ( parameters ) {
super ( parameters , {
isRenderable : true ,
ignoreBorder : true
} ) ;
}
render ( ) {
this . container . classList . add ( "squareAnnotation" ) ;
const data = this . data ;
const {
width ,
height
} = getRectDims ( data . rect ) ;
const svg = this . svgFactory . create ( width , height , true ) ;
const borderWidth = data . borderStyle . width ;
const square = this . # square = this . svgFactory . createElement ( "svg:rect" ) ;
square . setAttribute ( "x" , borderWidth / 2 ) ;
square . setAttribute ( "y" , borderWidth / 2 ) ;
square . setAttribute ( "width" , width - borderWidth ) ;
square . setAttribute ( "height" , height - borderWidth ) ;
square . setAttribute ( "stroke-width" , borderWidth || 1 ) ;
square . setAttribute ( "stroke" , "transparent" ) ;
square . setAttribute ( "fill" , "transparent" ) ;
svg . append ( square ) ;
this . container . append ( svg ) ;
if ( ! data . popupRef && this . hasPopupData ) {
this . _createPopup ( ) ;
}
return this . container ;
}
getElementsToTriggerPopup ( ) {
return this . # square ;
}
addHighlightArea ( ) {
this . container . classList . add ( "highlightArea" ) ;
}
}
class CircleAnnotationElement extends AnnotationElement {
# circle = null ;
constructor ( parameters ) {
super ( parameters , {
isRenderable : true ,
ignoreBorder : true
} ) ;
}
render ( ) {
this . container . classList . add ( "circleAnnotation" ) ;
const data = this . data ;
const {
width ,
height
} = getRectDims ( data . rect ) ;
const svg = this . svgFactory . create ( width , height , true ) ;
const borderWidth = data . borderStyle . width ;
const circle = this . # circle = this . svgFactory . createElement ( "svg:ellipse" ) ;
circle . setAttribute ( "cx" , width / 2 ) ;
circle . setAttribute ( "cy" , height / 2 ) ;
circle . setAttribute ( "rx" , width / 2 - borderWidth / 2 ) ;
circle . setAttribute ( "ry" , height / 2 - borderWidth / 2 ) ;
circle . setAttribute ( "stroke-width" , borderWidth || 1 ) ;
circle . setAttribute ( "stroke" , "transparent" ) ;
circle . setAttribute ( "fill" , "transparent" ) ;
svg . append ( circle ) ;
this . container . append ( svg ) ;
if ( ! data . popupRef && this . hasPopupData ) {
this . _createPopup ( ) ;
}
return this . container ;
}
getElementsToTriggerPopup ( ) {
return this . # circle ;
}
addHighlightArea ( ) {
this . container . classList . add ( "highlightArea" ) ;
}
}
class PolylineAnnotationElement extends AnnotationElement {
# polyline = null ;
constructor ( parameters ) {
super ( parameters , {
isRenderable : true ,
ignoreBorder : true
} ) ;
this . containerClassName = "polylineAnnotation" ;
this . svgElementName = "svg:polyline" ;
}
render ( ) {
this . container . classList . add ( this . containerClassName ) ;
2024-06-02 09:12:22 +01:00
const {
data : {
rect ,
vertices ,
borderStyle ,
popupRef
}
} = this ;
if ( ! vertices ) {
return this . container ;
}
2024-06-01 11:00:27 +01:00
const {
width ,
height
2024-06-02 09:12:22 +01:00
} = getRectDims ( rect ) ;
2024-06-01 11:00:27 +01:00
const svg = this . svgFactory . create ( width , height , true ) ;
let points = [ ] ;
2024-06-02 09:12:22 +01:00
for ( let i = 0 , ii = vertices . length ; i < ii ; i += 2 ) {
const x = vertices [ i ] - rect [ 0 ] ;
const y = rect [ 3 ] - vertices [ i + 1 ] ;
points . push ( ` ${ x } , ${ y } ` ) ;
2024-06-01 11:00:27 +01:00
}
points = points . join ( " " ) ;
const polyline = this . # polyline = this . svgFactory . createElement ( this . svgElementName ) ;
polyline . setAttribute ( "points" , points ) ;
2024-06-02 09:12:22 +01:00
polyline . setAttribute ( "stroke-width" , borderStyle . width || 1 ) ;
2024-06-01 11:00:27 +01:00
polyline . setAttribute ( "stroke" , "transparent" ) ;
polyline . setAttribute ( "fill" , "transparent" ) ;
svg . append ( polyline ) ;
this . container . append ( svg ) ;
2024-06-02 09:12:22 +01:00
if ( ! popupRef && this . hasPopupData ) {
2024-06-01 11:00:27 +01:00
this . _createPopup ( ) ;
}
return this . container ;
}
getElementsToTriggerPopup ( ) {
return this . # polyline ;
}
addHighlightArea ( ) {
this . container . classList . add ( "highlightArea" ) ;
}
}
class PolygonAnnotationElement extends PolylineAnnotationElement {
constructor ( parameters ) {
super ( parameters ) ;
this . containerClassName = "polygonAnnotation" ;
this . svgElementName = "svg:polygon" ;
}
}
class CaretAnnotationElement extends AnnotationElement {
constructor ( parameters ) {
super ( parameters , {
isRenderable : true ,
ignoreBorder : true
} ) ;
}
render ( ) {
this . container . classList . add ( "caretAnnotation" ) ;
if ( ! this . data . popupRef && this . hasPopupData ) {
this . _createPopup ( ) ;
}
return this . container ;
}
}
class InkAnnotationElement extends AnnotationElement {
# polylines = [ ] ;
constructor ( parameters ) {
super ( parameters , {
isRenderable : true ,
ignoreBorder : true
} ) ;
this . containerClassName = "inkAnnotation" ;
this . svgElementName = "svg:polyline" ;
this . annotationEditorType = AnnotationEditorType . INK ;
}
render ( ) {
this . container . classList . add ( this . containerClassName ) ;
2024-06-02 09:12:22 +01:00
const {
data : {
rect ,
inkLists ,
borderStyle ,
popupRef
}
} = this ;
2024-06-01 11:00:27 +01:00
const {
width ,
height
2024-06-02 09:12:22 +01:00
} = getRectDims ( rect ) ;
2024-06-01 11:00:27 +01:00
const svg = this . svgFactory . create ( width , height , true ) ;
2024-06-02 09:12:22 +01:00
for ( const inkList of inkLists ) {
2024-06-01 11:00:27 +01:00
let points = [ ] ;
2024-06-02 09:12:22 +01:00
for ( let i = 0 , ii = inkList . length ; i < ii ; i += 2 ) {
const x = inkList [ i ] - rect [ 0 ] ;
const y = rect [ 3 ] - inkList [ i + 1 ] ;
2024-06-01 11:00:27 +01:00
points . push ( ` ${ x } , ${ y } ` ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
points = points . join ( " " ) ;
const polyline = this . svgFactory . createElement ( this . svgElementName ) ;
this . # polylines . push ( polyline ) ;
polyline . setAttribute ( "points" , points ) ;
2024-06-02 09:12:22 +01:00
polyline . setAttribute ( "stroke-width" , borderStyle . width || 1 ) ;
2024-06-01 11:00:27 +01:00
polyline . setAttribute ( "stroke" , "transparent" ) ;
polyline . setAttribute ( "fill" , "transparent" ) ;
2024-06-02 09:12:22 +01:00
if ( ! popupRef && this . hasPopupData ) {
2024-06-01 11:00:27 +01:00
this . _createPopup ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
svg . append ( polyline ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
this . container . append ( svg ) ;
2023-10-27 13:19:54 +02:00
return this . container ;
}
2024-06-01 11:00:27 +01:00
getElementsToTriggerPopup ( ) {
return this . # polylines ;
}
addHighlightArea ( ) {
this . container . classList . add ( "highlightArea" ) ;
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
class HighlightAnnotationElement extends AnnotationElement {
2023-10-27 13:19:54 +02:00
constructor ( parameters ) {
super ( parameters , {
2024-06-01 11:00:27 +01:00
isRenderable : true ,
ignoreBorder : true ,
createQuadrilaterals : true
} ) ;
}
render ( ) {
if ( ! this . data . popupRef && this . hasPopupData ) {
this . _createPopup ( ) ;
}
this . container . classList . add ( "highlightAnnotation" ) ;
return this . container ;
}
}
class UnderlineAnnotationElement extends AnnotationElement {
constructor ( parameters ) {
super ( parameters , {
isRenderable : true ,
ignoreBorder : true ,
createQuadrilaterals : true
} ) ;
}
render ( ) {
if ( ! this . data . popupRef && this . hasPopupData ) {
this . _createPopup ( ) ;
}
this . container . classList . add ( "underlineAnnotation" ) ;
return this . container ;
}
}
class SquigglyAnnotationElement extends AnnotationElement {
constructor ( parameters ) {
super ( parameters , {
isRenderable : true ,
ignoreBorder : true ,
createQuadrilaterals : true
} ) ;
}
render ( ) {
if ( ! this . data . popupRef && this . hasPopupData ) {
this . _createPopup ( ) ;
}
this . container . classList . add ( "squigglyAnnotation" ) ;
return this . container ;
}
}
class StrikeOutAnnotationElement extends AnnotationElement {
constructor ( parameters ) {
super ( parameters , {
isRenderable : true ,
ignoreBorder : true ,
createQuadrilaterals : true
} ) ;
}
render ( ) {
if ( ! this . data . popupRef && this . hasPopupData ) {
this . _createPopup ( ) ;
}
this . container . classList . add ( "strikeoutAnnotation" ) ;
return this . container ;
}
}
class StampAnnotationElement extends AnnotationElement {
constructor ( parameters ) {
super ( parameters , {
isRenderable : true ,
ignoreBorder : true
} ) ;
}
render ( ) {
this . container . classList . add ( "stampAnnotation" ) ;
if ( ! this . data . popupRef && this . hasPopupData ) {
this . _createPopup ( ) ;
}
return this . container ;
}
}
class FileAttachmentAnnotationElement extends AnnotationElement {
# trigger = null ;
constructor ( parameters ) {
super ( parameters , {
isRenderable : true
} ) ;
const {
file
} = this . data ;
this . filename = file . filename ;
this . content = file . content ;
this . linkService . eventBus ? . dispatch ( "fileattachmentannotation" , {
source : this ,
... file
} ) ;
}
render ( ) {
this . container . classList . add ( "fileAttachmentAnnotation" ) ;
const {
container ,
data
} = this ;
let trigger ;
if ( data . hasAppearance || data . fillAlpha === 0 ) {
trigger = document . createElement ( "div" ) ;
} else {
trigger = document . createElement ( "img" ) ;
trigger . src = ` ${ this . imageResourcesPath } annotation- ${ / paperclip / i . test ( data . name ) ? "paperclip" : "pushpin" } .svg ` ;
if ( data . fillAlpha && data . fillAlpha < 1 ) {
trigger . style = ` filter: opacity( ${ Math . round ( data . fillAlpha * 100 ) } %); ` ;
}
}
trigger . addEventListener ( "dblclick" , this . # download . bind ( this ) ) ;
this . # trigger = trigger ;
const {
isMac
} = util _FeatureTest . platform ;
container . addEventListener ( "keydown" , evt => {
if ( evt . key === "Enter" && ( isMac ? evt . metaKey : evt . ctrlKey ) ) {
this . # download ( ) ;
}
2023-10-27 13:19:54 +02:00
} ) ;
2024-06-01 11:00:27 +01:00
if ( ! data . popupRef && this . hasPopupData ) {
this . _createPopup ( ) ;
} else {
trigger . classList . add ( "popupTriggerArea" ) ;
}
container . append ( trigger ) ;
return container ;
}
getElementsToTriggerPopup ( ) {
return this . # trigger ;
}
addHighlightArea ( ) {
this . container . classList . add ( "highlightArea" ) ;
}
# download ( ) {
this . downloadManager ? . openOrDownloadData ( this . content , this . filename ) ;
}
}
class AnnotationLayer {
# accessibilityManager = null ;
# annotationCanvasMap = null ;
# editableAnnotations = new Map ( ) ;
constructor ( {
div ,
accessibilityManager ,
annotationCanvasMap ,
annotationEditorUIManager ,
page ,
viewport
} ) {
this . div = div ;
this . # accessibilityManager = accessibilityManager ;
this . # annotationCanvasMap = annotationCanvasMap ;
this . page = page ;
this . viewport = viewport ;
this . zIndex = 0 ;
this . _annotationEditorUIManager = annotationEditorUIManager ;
}
# appendElement ( element , id ) {
const contentElement = element . firstChild || element ;
contentElement . id = ` ${ AnnotationPrefix } ${ id } ` ;
this . div . append ( element ) ;
this . # accessibilityManager ? . moveElementInDOM ( this . div , element , contentElement , false ) ;
}
async render ( params ) {
const {
annotations
} = params ;
const layer = this . div ;
setLayerDimensions ( layer , this . viewport ) ;
const popupToElements = new Map ( ) ;
const elementParams = {
data : null ,
layer ,
linkService : params . linkService ,
downloadManager : params . downloadManager ,
imageResourcesPath : params . imageResourcesPath || "" ,
renderForms : params . renderForms !== false ,
svgFactory : new DOMSVGFactory ( ) ,
annotationStorage : params . annotationStorage || new AnnotationStorage ( ) ,
enableScripting : params . enableScripting === true ,
hasJSActions : params . hasJSActions ,
fieldObjects : params . fieldObjects ,
parent : this ,
elements : null
} ;
for ( const data of annotations ) {
if ( data . noHTML ) {
continue ;
}
const isPopupAnnotation = data . annotationType === AnnotationType . POPUP ;
if ( ! isPopupAnnotation ) {
const {
width ,
height
} = getRectDims ( data . rect ) ;
if ( width <= 0 || height <= 0 ) {
continue ;
}
} else {
const elements = popupToElements . get ( data . id ) ;
if ( ! elements ) {
continue ;
}
elementParams . elements = elements ;
}
elementParams . data = data ;
const element = AnnotationElementFactory . create ( elementParams ) ;
if ( ! element . isRenderable ) {
continue ;
}
if ( ! isPopupAnnotation && data . popupRef ) {
const elements = popupToElements . get ( data . popupRef ) ;
if ( ! elements ) {
popupToElements . set ( data . popupRef , [ element ] ) ;
} else {
elements . push ( element ) ;
}
}
const rendered = element . render ( ) ;
if ( data . hidden ) {
rendered . style . visibility = "hidden" ;
}
this . # appendElement ( rendered , data . id ) ;
if ( element . annotationEditorType > 0 ) {
this . # editableAnnotations . set ( element . data . id , element ) ;
this . _annotationEditorUIManager ? . renderAnnotationElement ( element ) ;
}
}
this . # setAnnotationCanvasMap ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
update ( {
viewport
} ) {
const layer = this . div ;
this . viewport = viewport ;
setLayerDimensions ( layer , {
rotation : viewport . rotation
2023-10-27 13:19:54 +02:00
} ) ;
2024-06-01 11:00:27 +01:00
this . # setAnnotationCanvasMap ( ) ;
layer . hidden = false ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
# setAnnotationCanvasMap ( ) {
if ( ! this . # annotationCanvasMap ) {
return ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
const layer = this . div ;
for ( const [ id , canvas ] of this . # annotationCanvasMap ) {
const element = layer . querySelector ( ` [data-annotation-id=" ${ id } "] ` ) ;
if ( ! element ) {
continue ;
}
canvas . className = "annotationContent" ;
2023-10-27 13:19:54 +02:00
const {
2024-06-01 11:00:27 +01:00
firstChild
} = element ;
if ( ! firstChild ) {
element . append ( canvas ) ;
} else if ( firstChild . nodeName === "CANVAS" ) {
firstChild . replaceWith ( canvas ) ;
} else if ( ! firstChild . classList . contains ( "annotationContent" ) ) {
firstChild . before ( canvas ) ;
} else {
firstChild . after ( canvas ) ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
this . # annotationCanvasMap . clear ( ) ;
}
getEditableAnnotations ( ) {
return Array . from ( this . # editableAnnotations . values ( ) ) ;
}
getEditableAnnotation ( id ) {
return this . # editableAnnotations . get ( id ) ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
; // CONCATENATED MODULE: ./src/display/editor/freetext.js
2024-06-18 20:06:52 +02:00
2024-06-01 11:00:27 +01:00
const EOL _PATTERN = /\r\n?|\n/g ;
class FreeTextEditor extends AnnotationEditor {
# boundEditorDivBlur = this . editorDivBlur . bind ( this ) ;
# boundEditorDivFocus = this . editorDivFocus . bind ( this ) ;
# boundEditorDivInput = this . editorDivInput . bind ( this ) ;
# boundEditorDivKeydown = this . editorDivKeydown . bind ( this ) ;
# boundEditorDivPaste = this . editorDivPaste . bind ( this ) ;
# color ;
# content = "" ;
# editorDivId = ` ${ this . id } -editor ` ;
# fontSize ;
# initialData = null ;
static _freeTextDefaultContent = "" ;
static _internalPadding = 0 ;
static _defaultColor = null ;
static _defaultFontSize = 10 ;
static get _keyboardManager ( ) {
const proto = FreeTextEditor . prototype ;
const arrowChecker = self => self . isEmpty ( ) ;
const small = AnnotationEditorUIManager . TRANSLATE _SMALL ;
const big = AnnotationEditorUIManager . TRANSLATE _BIG ;
return shadow ( this , "_keyboardManager" , new KeyboardManager ( [ [ [ "ctrl+s" , "mac+meta+s" , "ctrl+p" , "mac+meta+p" ] , proto . commitOrRemove , {
bubbles : true
} ] , [ [ "ctrl+Enter" , "mac+meta+Enter" , "Escape" , "mac+Escape" ] , proto . commitOrRemove ] , [ [ "ArrowLeft" , "mac+ArrowLeft" ] , proto . _translateEmpty , {
args : [ - small , 0 ] ,
checker : arrowChecker
} ] , [ [ "ctrl+ArrowLeft" , "mac+shift+ArrowLeft" ] , proto . _translateEmpty , {
args : [ - big , 0 ] ,
checker : arrowChecker
} ] , [ [ "ArrowRight" , "mac+ArrowRight" ] , proto . _translateEmpty , {
args : [ small , 0 ] ,
checker : arrowChecker
} ] , [ [ "ctrl+ArrowRight" , "mac+shift+ArrowRight" ] , proto . _translateEmpty , {
args : [ big , 0 ] ,
checker : arrowChecker
} ] , [ [ "ArrowUp" , "mac+ArrowUp" ] , proto . _translateEmpty , {
args : [ 0 , - small ] ,
checker : arrowChecker
} ] , [ [ "ctrl+ArrowUp" , "mac+shift+ArrowUp" ] , proto . _translateEmpty , {
args : [ 0 , - big ] ,
checker : arrowChecker
} ] , [ [ "ArrowDown" , "mac+ArrowDown" ] , proto . _translateEmpty , {
args : [ 0 , small ] ,
checker : arrowChecker
} ] , [ [ "ctrl+ArrowDown" , "mac+shift+ArrowDown" ] , proto . _translateEmpty , {
args : [ 0 , big ] ,
checker : arrowChecker
} ] ] ) ) ;
}
static _type = "freetext" ;
static _editorType = AnnotationEditorType . FREETEXT ;
constructor ( params ) {
super ( {
... params ,
name : "freeTextEditor"
2023-10-27 13:19:54 +02:00
} ) ;
2024-06-01 11:00:27 +01:00
this . # color = params . color || FreeTextEditor . _defaultColor || AnnotationEditor . _defaultLineColor ;
this . # fontSize = params . fontSize || FreeTextEditor . _defaultFontSize ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
static initialize ( l10n , uiManager ) {
AnnotationEditor . initialize ( l10n , uiManager , {
strings : [ "pdfjs-free-text-default-content" ]
} ) ;
const style = getComputedStyle ( document . documentElement ) ;
this . _internalPadding = parseFloat ( style . getPropertyValue ( "--freetext-padding" ) ) ;
}
static updateDefaultParams ( type , value ) {
switch ( type ) {
case AnnotationEditorParamsType . FREETEXT _SIZE :
FreeTextEditor . _defaultFontSize = value ;
break ;
case AnnotationEditorParamsType . FREETEXT _COLOR :
FreeTextEditor . _defaultColor = value ;
break ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
}
updateParams ( type , value ) {
switch ( type ) {
case AnnotationEditorParamsType . FREETEXT _SIZE :
this . # updateFontSize ( value ) ;
break ;
case AnnotationEditorParamsType . FREETEXT _COLOR :
this . # updateColor ( value ) ;
break ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
}
static get defaultPropertiesToUpdate ( ) {
return [ [ AnnotationEditorParamsType . FREETEXT _SIZE , FreeTextEditor . _defaultFontSize ] , [ AnnotationEditorParamsType . FREETEXT _COLOR , FreeTextEditor . _defaultColor || AnnotationEditor . _defaultLineColor ] ] ;
}
get propertiesToUpdate ( ) {
return [ [ AnnotationEditorParamsType . FREETEXT _SIZE , this . # fontSize ] , [ AnnotationEditorParamsType . FREETEXT _COLOR , this . # color ] ] ;
}
# updateFontSize ( fontSize ) {
const setFontsize = size => {
this . editorDiv . style . fontSize = ` calc( ${ size } px * var(--scale-factor)) ` ;
this . translate ( 0 , - ( size - this . # fontSize ) * this . parentScale ) ;
this . # fontSize = size ;
this . # setEditorDimensions ( ) ;
} ;
const savedFontsize = this . # fontSize ;
this . addCommands ( {
cmd : setFontsize . bind ( this , fontSize ) ,
undo : setFontsize . bind ( this , savedFontsize ) ,
post : this . _uiManager . updateUI . bind ( this . _uiManager , this ) ,
mustExec : true ,
type : AnnotationEditorParamsType . FREETEXT _SIZE ,
overwriteIfSameType : true ,
keepUndo : true
2023-10-27 13:19:54 +02:00
} ) ;
}
2024-06-01 11:00:27 +01:00
# updateColor ( color ) {
const setColor = col => {
this . # color = this . editorDiv . style . color = col ;
} ;
const savedColor = this . # color ;
this . addCommands ( {
cmd : setColor . bind ( this , color ) ,
undo : setColor . bind ( this , savedColor ) ,
post : this . _uiManager . updateUI . bind ( this . _uiManager , this ) ,
mustExec : true ,
type : AnnotationEditorParamsType . FREETEXT _COLOR ,
overwriteIfSameType : true ,
keepUndo : true
2023-10-27 13:19:54 +02:00
} ) ;
}
2024-06-01 11:00:27 +01:00
_translateEmpty ( x , y ) {
this . _uiManager . translateSelectedEditors ( x , y , true ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
getInitialTranslation ( ) {
const scale = this . parentScale ;
return [ - FreeTextEditor . _internalPadding * scale , - ( FreeTextEditor . _internalPadding + this . # fontSize ) * scale ] ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
rebuild ( ) {
if ( ! this . parent ) {
return ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
super . rebuild ( ) ;
if ( this . div === null ) {
return ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
if ( ! this . isAttachedToDOM ) {
this . parent . add ( this ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
}
enableEditMode ( ) {
if ( this . isInEditMode ( ) ) {
return ;
}
this . parent . setEditingState ( false ) ;
this . parent . updateToolbar ( AnnotationEditorType . FREETEXT ) ;
super . enableEditMode ( ) ;
this . overlayDiv . classList . remove ( "enabled" ) ;
this . editorDiv . contentEditable = true ;
this . _isDraggable = false ;
this . div . removeAttribute ( "aria-activedescendant" ) ;
this . editorDiv . addEventListener ( "keydown" , this . # boundEditorDivKeydown ) ;
this . editorDiv . addEventListener ( "focus" , this . # boundEditorDivFocus ) ;
this . editorDiv . addEventListener ( "blur" , this . # boundEditorDivBlur ) ;
this . editorDiv . addEventListener ( "input" , this . # boundEditorDivInput ) ;
this . editorDiv . addEventListener ( "paste" , this . # boundEditorDivPaste ) ;
}
disableEditMode ( ) {
if ( ! this . isInEditMode ( ) ) {
return ;
}
this . parent . setEditingState ( true ) ;
super . disableEditMode ( ) ;
this . overlayDiv . classList . add ( "enabled" ) ;
this . editorDiv . contentEditable = false ;
this . div . setAttribute ( "aria-activedescendant" , this . # editorDivId ) ;
this . _isDraggable = true ;
this . editorDiv . removeEventListener ( "keydown" , this . # boundEditorDivKeydown ) ;
this . editorDiv . removeEventListener ( "focus" , this . # boundEditorDivFocus ) ;
this . editorDiv . removeEventListener ( "blur" , this . # boundEditorDivBlur ) ;
this . editorDiv . removeEventListener ( "input" , this . # boundEditorDivInput ) ;
this . editorDiv . removeEventListener ( "paste" , this . # boundEditorDivPaste ) ;
this . div . focus ( {
preventScroll : true
} ) ;
this . isEditing = false ;
this . parent . div . classList . add ( "freetextEditing" ) ;
}
focusin ( event ) {
if ( ! this . _focusEventsAllowed ) {
return ;
}
super . focusin ( event ) ;
if ( event . target !== this . editorDiv ) {
this . editorDiv . focus ( ) ;
}
}
onceAdded ( ) {
if ( this . width ) {
return ;
}
this . enableEditMode ( ) ;
this . editorDiv . focus ( ) ;
if ( this . _initialOptions ? . isCentered ) {
this . center ( ) ;
}
this . _initialOptions = null ;
}
isEmpty ( ) {
return ! this . editorDiv || this . editorDiv . innerText . trim ( ) === "" ;
}
remove ( ) {
this . isEditing = false ;
if ( this . parent ) {
this . parent . setEditingState ( true ) ;
this . parent . div . classList . add ( "freetextEditing" ) ;
}
super . remove ( ) ;
}
# extractText ( ) {
const buffer = [ ] ;
this . editorDiv . normalize ( ) ;
for ( const child of this . editorDiv . childNodes ) {
buffer . push ( FreeTextEditor . # getNodeContent ( child ) ) ;
}
return buffer . join ( "\n" ) ;
}
# setEditorDimensions ( ) {
const [ parentWidth , parentHeight ] = this . parentDimensions ;
let rect ;
if ( this . isAttachedToDOM ) {
rect = this . div . getBoundingClientRect ( ) ;
2023-10-27 13:19:54 +02:00
} else {
2024-06-01 11:00:27 +01:00
const {
currentLayer ,
div
} = this ;
const savedDisplay = div . style . display ;
const savedVisibility = div . classList . contains ( "hidden" ) ;
div . classList . remove ( "hidden" ) ;
div . style . display = "hidden" ;
currentLayer . div . append ( this . div ) ;
rect = div . getBoundingClientRect ( ) ;
div . remove ( ) ;
div . style . display = savedDisplay ;
div . classList . toggle ( "hidden" , savedVisibility ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
if ( this . rotation % 180 === this . parentRotation % 180 ) {
this . width = rect . width / parentWidth ;
this . height = rect . height / parentHeight ;
} else {
this . width = rect . height / parentWidth ;
this . height = rect . width / parentHeight ;
}
this . fixAndSetPosition ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
commit ( ) {
if ( ! this . isInEditMode ( ) ) {
return ;
}
super . commit ( ) ;
this . disableEditMode ( ) ;
const savedText = this . # content ;
const newText = this . # content = this . # extractText ( ) . trimEnd ( ) ;
if ( savedText === newText ) {
return ;
}
const setText = text => {
this . # content = text ;
if ( ! text ) {
this . remove ( ) ;
return ;
}
this . # setContent ( ) ;
this . _uiManager . rebuild ( this ) ;
this . # setEditorDimensions ( ) ;
} ;
this . addCommands ( {
cmd : ( ) => {
setText ( newText ) ;
} ,
undo : ( ) => {
setText ( savedText ) ;
} ,
mustExec : false
2023-10-27 13:19:54 +02:00
} ) ;
2024-06-01 11:00:27 +01:00
this . # setEditorDimensions ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
shouldGetKeyboardEvents ( ) {
return this . isInEditMode ( ) ;
}
enterInEditMode ( ) {
this . enableEditMode ( ) ;
this . editorDiv . focus ( ) ;
}
dblclick ( event ) {
this . enterInEditMode ( ) ;
}
keydown ( event ) {
if ( event . target === this . div && event . key === "Enter" ) {
this . enterInEditMode ( ) ;
event . preventDefault ( ) ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
editorDivKeydown ( event ) {
FreeTextEditor . _keyboardManager . exec ( this , event ) ;
}
editorDivFocus ( event ) {
this . isEditing = true ;
}
editorDivBlur ( event ) {
this . isEditing = false ;
}
editorDivInput ( event ) {
this . parent . div . classList . toggle ( "freetextEditing" , this . isEmpty ( ) ) ;
}
disableEditing ( ) {
this . editorDiv . setAttribute ( "role" , "comment" ) ;
this . editorDiv . removeAttribute ( "aria-multiline" ) ;
}
enableEditing ( ) {
this . editorDiv . setAttribute ( "role" , "textbox" ) ;
this . editorDiv . setAttribute ( "aria-multiline" , true ) ;
}
render ( ) {
if ( this . div ) {
return this . div ;
}
let baseX , baseY ;
if ( this . width ) {
baseX = this . x ;
baseY = this . y ;
}
super . render ( ) ;
this . editorDiv = document . createElement ( "div" ) ;
this . editorDiv . className = "internal" ;
this . editorDiv . setAttribute ( "id" , this . # editorDivId ) ;
this . editorDiv . setAttribute ( "data-l10n-id" , "pdfjs-free-text" ) ;
this . enableEditing ( ) ;
AnnotationEditor . _l10nPromise . get ( "pdfjs-free-text-default-content" ) . then ( msg => this . editorDiv ? . setAttribute ( "default-content" , msg ) ) ;
this . editorDiv . contentEditable = true ;
const {
style
} = this . editorDiv ;
style . fontSize = ` calc( ${ this . # fontSize } px * var(--scale-factor)) ` ;
style . color = this . # color ;
this . div . append ( this . editorDiv ) ;
this . overlayDiv = document . createElement ( "div" ) ;
this . overlayDiv . classList . add ( "overlay" , "enabled" ) ;
this . div . append ( this . overlayDiv ) ;
bindEvents ( this , this . div , [ "dblclick" , "keydown" ] ) ;
if ( this . width ) {
const [ parentWidth , parentHeight ] = this . parentDimensions ;
if ( this . annotationElementId ) {
const {
position
} = this . # initialData ;
let [ tx , ty ] = this . getInitialTranslation ( ) ;
[ tx , ty ] = this . pageTranslationToScreen ( tx , ty ) ;
const [ pageWidth , pageHeight ] = this . pageDimensions ;
const [ pageX , pageY ] = this . pageTranslation ;
let posX , posY ;
switch ( this . rotation ) {
case 0 :
posX = baseX + ( position [ 0 ] - pageX ) / pageWidth ;
posY = baseY + this . height - ( position [ 1 ] - pageY ) / pageHeight ;
break ;
case 90 :
posX = baseX + ( position [ 0 ] - pageX ) / pageWidth ;
posY = baseY - ( position [ 1 ] - pageY ) / pageHeight ;
[ tx , ty ] = [ ty , - tx ] ;
break ;
case 180 :
posX = baseX - this . width + ( position [ 0 ] - pageX ) / pageWidth ;
posY = baseY - ( position [ 1 ] - pageY ) / pageHeight ;
[ tx , ty ] = [ - tx , - ty ] ;
break ;
case 270 :
posX = baseX + ( position [ 0 ] - pageX - this . height * pageHeight ) / pageWidth ;
posY = baseY + ( position [ 1 ] - pageY - this . width * pageWidth ) / pageHeight ;
[ tx , ty ] = [ - ty , tx ] ;
break ;
}
this . setAt ( posX * parentWidth , posY * parentHeight , tx , ty ) ;
} else {
this . setAt ( baseX * parentWidth , baseY * parentHeight , this . width * parentWidth , this . height * parentHeight ) ;
}
this . # setContent ( ) ;
this . _isDraggable = true ;
this . editorDiv . contentEditable = false ;
} else {
this . _isDraggable = false ;
this . editorDiv . contentEditable = true ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
return this . div ;
}
static # getNodeContent ( node ) {
return ( node . nodeType === Node . TEXT _NODE ? node . nodeValue : node . innerText ) . replaceAll ( EOL _PATTERN , "" ) ;
}
editorDivPaste ( event ) {
const clipboardData = event . clipboardData || window . clipboardData ;
const {
types
} = clipboardData ;
if ( types . length === 1 && types [ 0 ] === "text/plain" ) {
return ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
event . preventDefault ( ) ;
const paste = FreeTextEditor . # deserializeContent ( clipboardData . getData ( "text" ) || "" ) . replaceAll ( EOL _PATTERN , "\n" ) ;
if ( ! paste ) {
return ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
const selection = window . getSelection ( ) ;
if ( ! selection . rangeCount ) {
return ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
this . editorDiv . normalize ( ) ;
selection . deleteFromDocument ( ) ;
const range = selection . getRangeAt ( 0 ) ;
if ( ! paste . includes ( "\n" ) ) {
range . insertNode ( document . createTextNode ( paste ) ) ;
this . editorDiv . normalize ( ) ;
selection . collapseToStart ( ) ;
2023-10-27 13:19:54 +02:00
return ;
}
const {
2024-06-01 11:00:27 +01:00
startContainer ,
startOffset
} = range ;
const bufferBefore = [ ] ;
const bufferAfter = [ ] ;
if ( startContainer . nodeType === Node . TEXT _NODE ) {
const parent = startContainer . parentElement ;
bufferAfter . push ( startContainer . nodeValue . slice ( startOffset ) . replaceAll ( EOL _PATTERN , "" ) ) ;
if ( parent !== this . editorDiv ) {
let buffer = bufferBefore ;
for ( const child of this . editorDiv . childNodes ) {
if ( child === parent ) {
buffer = bufferAfter ;
continue ;
}
buffer . push ( FreeTextEditor . # getNodeContent ( child ) ) ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
bufferBefore . push ( startContainer . nodeValue . slice ( 0 , startOffset ) . replaceAll ( EOL _PATTERN , "" ) ) ;
} else if ( startContainer === this . editorDiv ) {
let buffer = bufferBefore ;
let i = 0 ;
for ( const child of this . editorDiv . childNodes ) {
if ( i ++ === startOffset ) {
buffer = bufferAfter ;
}
buffer . push ( FreeTextEditor . # getNodeContent ( child ) ) ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
this . # content = ` ${ bufferBefore . join ( "\n" ) } ${ paste } ${ bufferAfter . join ( "\n" ) } ` ;
this . # setContent ( ) ;
const newRange = new Range ( ) ;
let beforeLength = bufferBefore . reduce ( ( acc , line ) => acc + line . length , 0 ) ;
for ( const {
firstChild
} of this . editorDiv . childNodes ) {
if ( firstChild . nodeType === Node . TEXT _NODE ) {
const length = firstChild . nodeValue . length ;
if ( beforeLength <= length ) {
newRange . setStart ( firstChild , beforeLength ) ;
newRange . setEnd ( firstChild , beforeLength ) ;
break ;
}
beforeLength -= length ;
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
selection . removeAllRanges ( ) ;
selection . addRange ( newRange ) ;
}
# setContent ( ) {
this . editorDiv . replaceChildren ( ) ;
if ( ! this . # content ) {
return ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
for ( const line of this . # content . split ( "\n" ) ) {
const div = document . createElement ( "div" ) ;
div . append ( line ? document . createTextNode ( line ) : document . createElement ( "br" ) ) ;
this . editorDiv . append ( div ) ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
# serializeContent ( ) {
return this . # content . replaceAll ( "\xa0" , " " ) ;
}
static # deserializeContent ( content ) {
return content . replaceAll ( " " , "\xa0" ) ;
}
get contentDiv ( ) {
return this . editorDiv ;
}
static deserialize ( data , parent , uiManager ) {
let initialData = null ;
if ( data instanceof FreeTextAnnotationElement ) {
const {
data : {
defaultAppearanceData : {
fontSize ,
fontColor
} ,
rect ,
rotation ,
id
} ,
textContent ,
textPosition ,
parent : {
page : {
pageNumber
}
}
} = data ;
if ( ! textContent || textContent . length === 0 ) {
return null ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
initialData = data = {
annotationType : AnnotationEditorType . FREETEXT ,
color : Array . from ( fontColor ) ,
fontSize ,
value : textContent . join ( "\n" ) ,
position : textPosition ,
pageIndex : pageNumber - 1 ,
rect : rect . slice ( 0 ) ,
rotation ,
id ,
deleted : false
} ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
const editor = super . deserialize ( data , parent , uiManager ) ;
editor . # fontSize = data . fontSize ;
editor . # color = Util . makeHexColor ( ... data . color ) ;
editor . # content = FreeTextEditor . # deserializeContent ( data . value ) ;
editor . annotationElementId = data . id || null ;
editor . # initialData = initialData ;
return editor ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
serialize ( isForCopying = false ) {
if ( this . isEmpty ( ) ) {
return null ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
if ( this . deleted ) {
return {
pageIndex : this . pageIndex ,
id : this . annotationElementId ,
deleted : true
} ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
const padding = FreeTextEditor . _internalPadding * this . parentScale ;
const rect = this . getRect ( padding , padding ) ;
const color = AnnotationEditor . _colorManager . convert ( this . isAttachedToDOM ? getComputedStyle ( this . editorDiv ) . color : this . # color ) ;
const serialized = {
annotationType : AnnotationEditorType . FREETEXT ,
color ,
fontSize : this . # fontSize ,
value : this . # serializeContent ( ) ,
pageIndex : this . pageIndex ,
rect ,
rotation : this . rotation ,
structTreeParentId : this . _structTreeParentId
} ;
if ( isForCopying ) {
return serialized ;
}
if ( this . annotationElementId && ! this . # hasElementChanged ( serialized ) ) {
return null ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
serialized . id = this . annotationElementId ;
return serialized ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
# hasElementChanged ( serialized ) {
const {
value ,
fontSize ,
color ,
pageIndex
} = this . # initialData ;
return this . _hasBeenMoved || serialized . value !== value || serialized . fontSize !== fontSize || serialized . color . some ( ( c , i ) => c !== color [ i ] ) || serialized . pageIndex !== pageIndex ;
}
renderAnnotationElement ( annotation ) {
const content = super . renderAnnotationElement ( annotation ) ;
if ( this . deleted ) {
return content ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
const {
style
} = content ;
style . fontSize = ` calc( ${ this . # fontSize } px * var(--scale-factor)) ` ;
style . color = this . # color ;
content . replaceChildren ( ) ;
for ( const line of this . # content . split ( "\n" ) ) {
const div = document . createElement ( "div" ) ;
div . append ( line ? document . createTextNode ( line ) : document . createElement ( "br" ) ) ;
content . append ( div ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
const padding = FreeTextEditor . _internalPadding * this . parentScale ;
annotation . updateEdited ( {
rect : this . getRect ( padding , padding ) ,
popupContent : this . # content
} ) ;
return content ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
resetAnnotationElement ( annotation ) {
super . resetAnnotationElement ( annotation ) ;
annotation . resetEdited ( ) ;
}
}
; // CONCATENATED MODULE: ./src/display/editor/outliner.js
2024-06-18 20:06:52 +02:00
2024-06-01 11:00:27 +01:00
class Outliner {
# box ;
# verticalEdges = [ ] ;
# intervals = [ ] ;
constructor ( boxes , borderWidth = 0 , innerMargin = 0 , isLTR = true ) {
let minX = Infinity ;
let maxX = - Infinity ;
let minY = Infinity ;
let maxY = - Infinity ;
const NUMBER _OF _DIGITS = 4 ;
const EPSILON = 10 * * - NUMBER _OF _DIGITS ;
for ( const {
x ,
y ,
width ,
height
} of boxes ) {
const x1 = Math . floor ( ( x - borderWidth ) / EPSILON ) * EPSILON ;
const x2 = Math . ceil ( ( x + width + borderWidth ) / EPSILON ) * EPSILON ;
const y1 = Math . floor ( ( y - borderWidth ) / EPSILON ) * EPSILON ;
const y2 = Math . ceil ( ( y + height + borderWidth ) / EPSILON ) * EPSILON ;
const left = [ x1 , y1 , y2 , true ] ;
const right = [ x2 , y1 , y2 , false ] ;
this . # verticalEdges . push ( left , right ) ;
minX = Math . min ( minX , x1 ) ;
maxX = Math . max ( maxX , x2 ) ;
minY = Math . min ( minY , y1 ) ;
maxY = Math . max ( maxY , y2 ) ;
}
const bboxWidth = maxX - minX + 2 * innerMargin ;
const bboxHeight = maxY - minY + 2 * innerMargin ;
const shiftedMinX = minX - innerMargin ;
const shiftedMinY = minY - innerMargin ;
const lastEdge = this . # verticalEdges . at ( isLTR ? - 1 : - 2 ) ;
const lastPoint = [ lastEdge [ 0 ] , lastEdge [ 2 ] ] ;
for ( const edge of this . # verticalEdges ) {
const [ x , y1 , y2 ] = edge ;
edge [ 0 ] = ( x - shiftedMinX ) / bboxWidth ;
edge [ 1 ] = ( y1 - shiftedMinY ) / bboxHeight ;
edge [ 2 ] = ( y2 - shiftedMinY ) / bboxHeight ;
}
this . # box = {
x : shiftedMinX ,
y : shiftedMinY ,
width : bboxWidth ,
height : bboxHeight ,
lastPoint
} ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
getOutlines ( ) {
this . # verticalEdges . sort ( ( a , b ) => a [ 0 ] - b [ 0 ] || a [ 1 ] - b [ 1 ] || a [ 2 ] - b [ 2 ] ) ;
const outlineVerticalEdges = [ ] ;
for ( const edge of this . # verticalEdges ) {
if ( edge [ 3 ] ) {
outlineVerticalEdges . push ( ... this . # breakEdge ( edge ) ) ;
this . # insert ( edge ) ;
} else {
this . # remove ( edge ) ;
outlineVerticalEdges . push ( ... this . # breakEdge ( edge ) ) ;
}
}
return this . # getOutlines ( outlineVerticalEdges ) ;
}
# getOutlines ( outlineVerticalEdges ) {
const edges = [ ] ;
const allEdges = new Set ( ) ;
for ( const edge of outlineVerticalEdges ) {
const [ x , y1 , y2 ] = edge ;
edges . push ( [ x , y1 , edge ] , [ x , y2 , edge ] ) ;
}
edges . sort ( ( a , b ) => a [ 1 ] - b [ 1 ] || a [ 0 ] - b [ 0 ] ) ;
for ( let i = 0 , ii = edges . length ; i < ii ; i += 2 ) {
const edge1 = edges [ i ] [ 2 ] ;
const edge2 = edges [ i + 1 ] [ 2 ] ;
edge1 . push ( edge2 ) ;
edge2 . push ( edge1 ) ;
allEdges . add ( edge1 ) ;
allEdges . add ( edge2 ) ;
}
const outlines = [ ] ;
let outline ;
while ( allEdges . size > 0 ) {
const edge = allEdges . values ( ) . next ( ) . value ;
let [ x , y1 , y2 , edge1 , edge2 ] = edge ;
allEdges . delete ( edge ) ;
let lastPointX = x ;
let lastPointY = y1 ;
outline = [ x , y2 ] ;
outlines . push ( outline ) ;
while ( true ) {
let e ;
if ( allEdges . has ( edge1 ) ) {
e = edge1 ;
} else if ( allEdges . has ( edge2 ) ) {
e = edge2 ;
} else {
break ;
}
allEdges . delete ( e ) ;
[ x , y1 , y2 , edge1 , edge2 ] = e ;
if ( lastPointX !== x ) {
outline . push ( lastPointX , lastPointY , x , lastPointY === y1 ? y1 : y2 ) ;
lastPointX = x ;
}
lastPointY = lastPointY === y1 ? y2 : y1 ;
}
outline . push ( lastPointX , lastPointY ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
return new HighlightOutline ( outlines , this . # box ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
# binarySearch ( y ) {
const array = this . # intervals ;
let start = 0 ;
let end = array . length - 1 ;
while ( start <= end ) {
const middle = start + end >> 1 ;
const y1 = array [ middle ] [ 0 ] ;
if ( y1 === y ) {
return middle ;
}
if ( y1 < y ) {
start = middle + 1 ;
} else {
end = middle - 1 ;
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
return end + 1 ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
# insert ( [ , y1 , y2 ] ) {
const index = this . # binarySearch ( y1 ) ;
this . # intervals . splice ( index , 0 , [ y1 , y2 ] ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
# remove ( [ , y1 , y2 ] ) {
const index = this . # binarySearch ( y1 ) ;
for ( let i = index ; i < this . # intervals . length ; i ++ ) {
const [ start , end ] = this . # intervals [ i ] ;
if ( start !== y1 ) {
break ;
}
if ( start === y1 && end === y2 ) {
this . # intervals . splice ( i , 1 ) ;
return ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
for ( let i = index - 1 ; i >= 0 ; i -- ) {
const [ start , end ] = this . # intervals [ i ] ;
if ( start !== y1 ) {
break ;
}
if ( start === y1 && end === y2 ) {
this . # intervals . splice ( i , 1 ) ;
return ;
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
}
# breakEdge ( edge ) {
const [ x , y1 , y2 ] = edge ;
const results = [ [ x , y1 , y2 ] ] ;
const index = this . # binarySearch ( y2 ) ;
for ( let i = 0 ; i < index ; i ++ ) {
const [ start , end ] = this . # intervals [ i ] ;
for ( let j = 0 , jj = results . length ; j < jj ; j ++ ) {
const [ , y3 , y4 ] = results [ j ] ;
if ( end <= y3 || y4 <= start ) {
continue ;
}
if ( y3 >= start ) {
if ( y4 > end ) {
results [ j ] [ 1 ] = end ;
} else {
if ( jj === 1 ) {
return [ ] ;
}
results . splice ( j , 1 ) ;
j -- ;
jj -- ;
}
continue ;
}
results [ j ] [ 2 ] = start ;
if ( y4 > end ) {
results . push ( [ x , end , y4 ] ) ;
}
}
}
return results ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
class Outline {
toSVGPath ( ) {
throw new Error ( "Abstract method `toSVGPath` must be implemented." ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
get box ( ) {
throw new Error ( "Abstract getter `box` must be implemented." ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
serialize ( _bbox , _rotation ) {
throw new Error ( "Abstract method `serialize` must be implemented." ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
get free ( ) {
return this instanceof FreeHighlightOutline ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
class HighlightOutline extends Outline {
# box ;
# outlines ;
constructor ( outlines , box ) {
super ( ) ;
this . # outlines = outlines ;
this . # box = box ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
toSVGPath ( ) {
const buffer = [ ] ;
for ( const polygon of this . # outlines ) {
let [ prevX , prevY ] = polygon ;
buffer . push ( ` M ${ prevX } ${ prevY } ` ) ;
for ( let i = 2 ; i < polygon . length ; i += 2 ) {
const x = polygon [ i ] ;
const y = polygon [ i + 1 ] ;
if ( x === prevX ) {
buffer . push ( ` V ${ y } ` ) ;
prevY = y ;
} else if ( y === prevY ) {
buffer . push ( ` H ${ x } ` ) ;
prevX = x ;
}
}
buffer . push ( "Z" ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
return buffer . join ( " " ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
serialize ( [ blX , blY , trX , trY ] , _rotation ) {
const outlines = [ ] ;
const width = trX - blX ;
const height = trY - blY ;
for ( const outline of this . # outlines ) {
const points = new Array ( outline . length ) ;
for ( let i = 0 ; i < outline . length ; i += 2 ) {
points [ i ] = blX + outline [ i ] * width ;
points [ i + 1 ] = trY - outline [ i + 1 ] * height ;
}
outlines . push ( points ) ;
}
return outlines ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
get box ( ) {
return this . # box ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
class FreeOutliner {
# box ;
# bottom = [ ] ;
# innerMargin ;
# isLTR ;
# top = [ ] ;
# last = new Float64Array ( 18 ) ;
# lastX ;
# lastY ;
# min ;
# min _dist ;
# scaleFactor ;
# thickness ;
# points = [ ] ;
static # MIN _DIST = 8 ;
static # MIN _DIFF = 2 ;
static # MIN = FreeOutliner . # MIN _DIST + FreeOutliner . # MIN _DIFF ;
constructor ( {
x ,
y
} , box , scaleFactor , thickness , isLTR , innerMargin = 0 ) {
this . # box = box ;
this . # thickness = thickness * scaleFactor ;
this . # isLTR = isLTR ;
this . # last . set ( [ NaN , NaN , NaN , NaN , x , y ] , 6 ) ;
this . # innerMargin = innerMargin ;
this . # min _dist = FreeOutliner . # MIN _DIST * scaleFactor ;
this . # min = FreeOutliner . # MIN * scaleFactor ;
this . # scaleFactor = scaleFactor ;
this . # points . push ( x , y ) ;
}
get free ( ) {
return true ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
isEmpty ( ) {
return isNaN ( this . # last [ 8 ] ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
# getLastCoords ( ) {
const lastTop = this . # last . subarray ( 4 , 6 ) ;
const lastBottom = this . # last . subarray ( 16 , 18 ) ;
const [ x , y , width , height ] = this . # box ;
return [ ( this . # lastX + ( lastTop [ 0 ] - lastBottom [ 0 ] ) / 2 - x ) / width , ( this . # lastY + ( lastTop [ 1 ] - lastBottom [ 1 ] ) / 2 - y ) / height , ( this . # lastX + ( lastBottom [ 0 ] - lastTop [ 0 ] ) / 2 - x ) / width , ( this . # lastY + ( lastBottom [ 1 ] - lastTop [ 1 ] ) / 2 - y ) / height ] ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
add ( {
x ,
y
} ) {
this . # lastX = x ;
this . # lastY = y ;
const [ layerX , layerY , layerWidth , layerHeight ] = this . # box ;
let [ x1 , y1 , x2 , y2 ] = this . # last . subarray ( 8 , 12 ) ;
const diffX = x - x2 ;
const diffY = y - y2 ;
const d = Math . hypot ( diffX , diffY ) ;
if ( d < this . # min ) {
return false ;
}
const diffD = d - this . # min _dist ;
const K = diffD / d ;
const shiftX = K * diffX ;
const shiftY = K * diffY ;
let x0 = x1 ;
let y0 = y1 ;
x1 = x2 ;
y1 = y2 ;
x2 += shiftX ;
y2 += shiftY ;
this . # points ? . push ( x , y ) ;
const nX = - shiftY / diffD ;
const nY = shiftX / diffD ;
const thX = nX * this . # thickness ;
const thY = nY * this . # thickness ;
this . # last . set ( this . # last . subarray ( 2 , 8 ) , 0 ) ;
this . # last . set ( [ x2 + thX , y2 + thY ] , 4 ) ;
this . # last . set ( this . # last . subarray ( 14 , 18 ) , 12 ) ;
this . # last . set ( [ x2 - thX , y2 - thY ] , 16 ) ;
if ( isNaN ( this . # last [ 6 ] ) ) {
if ( this . # top . length === 0 ) {
this . # last . set ( [ x1 + thX , y1 + thY ] , 2 ) ;
this . # top . push ( NaN , NaN , NaN , NaN , ( x1 + thX - layerX ) / layerWidth , ( y1 + thY - layerY ) / layerHeight ) ;
this . # last . set ( [ x1 - thX , y1 - thY ] , 14 ) ;
this . # bottom . push ( NaN , NaN , NaN , NaN , ( x1 - thX - layerX ) / layerWidth , ( y1 - thY - layerY ) / layerHeight ) ;
}
this . # last . set ( [ x0 , y0 , x1 , y1 , x2 , y2 ] , 6 ) ;
return ! this . isEmpty ( ) ;
}
this . # last . set ( [ x0 , y0 , x1 , y1 , x2 , y2 ] , 6 ) ;
const angle = Math . abs ( Math . atan2 ( y0 - y1 , x0 - x1 ) - Math . atan2 ( shiftY , shiftX ) ) ;
if ( angle < Math . PI / 2 ) {
[ x1 , y1 , x2 , y2 ] = this . # last . subarray ( 2 , 6 ) ;
this . # top . push ( NaN , NaN , NaN , NaN , ( ( x1 + x2 ) / 2 - layerX ) / layerWidth , ( ( y1 + y2 ) / 2 - layerY ) / layerHeight ) ;
[ x1 , y1 , x0 , y0 ] = this . # last . subarray ( 14 , 18 ) ;
this . # bottom . push ( NaN , NaN , NaN , NaN , ( ( x0 + x1 ) / 2 - layerX ) / layerWidth , ( ( y0 + y1 ) / 2 - layerY ) / layerHeight ) ;
return true ;
}
[ x0 , y0 , x1 , y1 , x2 , y2 ] = this . # last . subarray ( 0 , 6 ) ;
this . # top . push ( ( ( x0 + 5 * x1 ) / 6 - layerX ) / layerWidth , ( ( y0 + 5 * y1 ) / 6 - layerY ) / layerHeight , ( ( 5 * x1 + x2 ) / 6 - layerX ) / layerWidth , ( ( 5 * y1 + y2 ) / 6 - layerY ) / layerHeight , ( ( x1 + x2 ) / 2 - layerX ) / layerWidth , ( ( y1 + y2 ) / 2 - layerY ) / layerHeight ) ;
[ x2 , y2 , x1 , y1 , x0 , y0 ] = this . # last . subarray ( 12 , 18 ) ;
this . # bottom . push ( ( ( x0 + 5 * x1 ) / 6 - layerX ) / layerWidth , ( ( y0 + 5 * y1 ) / 6 - layerY ) / layerHeight , ( ( 5 * x1 + x2 ) / 6 - layerX ) / layerWidth , ( ( 5 * y1 + y2 ) / 6 - layerY ) / layerHeight , ( ( x1 + x2 ) / 2 - layerX ) / layerWidth , ( ( y1 + y2 ) / 2 - layerY ) / layerHeight ) ;
return true ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
toSVGPath ( ) {
if ( this . isEmpty ( ) ) {
return "" ;
}
const top = this . # top ;
const bottom = this . # bottom ;
const lastTop = this . # last . subarray ( 4 , 6 ) ;
const lastBottom = this . # last . subarray ( 16 , 18 ) ;
const [ x , y , width , height ] = this . # box ;
const [ lastTopX , lastTopY , lastBottomX , lastBottomY ] = this . # getLastCoords ( ) ;
if ( isNaN ( this . # last [ 6 ] ) && ! this . isEmpty ( ) ) {
return ` M ${ ( this . # last [ 2 ] - x ) / width } ${ ( this . # last [ 3 ] - y ) / height } L ${ ( this . # last [ 4 ] - x ) / width } ${ ( this . # last [ 5 ] - y ) / height } L ${ lastTopX } ${ lastTopY } L ${ lastBottomX } ${ lastBottomY } L ${ ( this . # last [ 16 ] - x ) / width } ${ ( this . # last [ 17 ] - y ) / height } L ${ ( this . # last [ 14 ] - x ) / width } ${ ( this . # last [ 15 ] - y ) / height } Z ` ;
}
const buffer = [ ] ;
buffer . push ( ` M ${ top [ 4 ] } ${ top [ 5 ] } ` ) ;
for ( let i = 6 ; i < top . length ; i += 6 ) {
if ( isNaN ( top [ i ] ) ) {
buffer . push ( ` L ${ top [ i + 4 ] } ${ top [ i + 5 ] } ` ) ;
} else {
buffer . push ( ` C ${ top [ i ] } ${ top [ i + 1 ] } ${ top [ i + 2 ] } ${ top [ i + 3 ] } ${ top [ i + 4 ] } ${ top [ i + 5 ] } ` ) ;
}
}
buffer . push ( ` L ${ ( lastTop [ 0 ] - x ) / width } ${ ( lastTop [ 1 ] - y ) / height } L ${ lastTopX } ${ lastTopY } L ${ lastBottomX } ${ lastBottomY } L ${ ( lastBottom [ 0 ] - x ) / width } ${ ( lastBottom [ 1 ] - y ) / height } ` ) ;
for ( let i = bottom . length - 6 ; i >= 6 ; i -= 6 ) {
if ( isNaN ( bottom [ i ] ) ) {
buffer . push ( ` L ${ bottom [ i + 4 ] } ${ bottom [ i + 5 ] } ` ) ;
} else {
buffer . push ( ` C ${ bottom [ i ] } ${ bottom [ i + 1 ] } ${ bottom [ i + 2 ] } ${ bottom [ i + 3 ] } ${ bottom [ i + 4 ] } ${ bottom [ i + 5 ] } ` ) ;
}
}
buffer . push ( ` L ${ bottom [ 4 ] } ${ bottom [ 5 ] } Z ` ) ;
return buffer . join ( " " ) ;
}
getOutlines ( ) {
const top = this . # top ;
const bottom = this . # bottom ;
const last = this . # last ;
const lastTop = last . subarray ( 4 , 6 ) ;
const lastBottom = last . subarray ( 16 , 18 ) ;
const [ layerX , layerY , layerWidth , layerHeight ] = this . # box ;
const points = new Float64Array ( ( this . # points ? . length ? ? 0 ) + 2 ) ;
for ( let i = 0 , ii = points . length - 2 ; i < ii ; i += 2 ) {
points [ i ] = ( this . # points [ i ] - layerX ) / layerWidth ;
points [ i + 1 ] = ( this . # points [ i + 1 ] - layerY ) / layerHeight ;
}
points [ points . length - 2 ] = ( this . # lastX - layerX ) / layerWidth ;
points [ points . length - 1 ] = ( this . # lastY - layerY ) / layerHeight ;
const [ lastTopX , lastTopY , lastBottomX , lastBottomY ] = this . # getLastCoords ( ) ;
if ( isNaN ( last [ 6 ] ) && ! this . isEmpty ( ) ) {
const outline = new Float64Array ( 36 ) ;
outline . set ( [ NaN , NaN , NaN , NaN , ( last [ 2 ] - layerX ) / layerWidth , ( last [ 3 ] - layerY ) / layerHeight , NaN , NaN , NaN , NaN , ( last [ 4 ] - layerX ) / layerWidth , ( last [ 5 ] - layerY ) / layerHeight , NaN , NaN , NaN , NaN , lastTopX , lastTopY , NaN , NaN , NaN , NaN , lastBottomX , lastBottomY , NaN , NaN , NaN , NaN , ( last [ 16 ] - layerX ) / layerWidth , ( last [ 17 ] - layerY ) / layerHeight , NaN , NaN , NaN , NaN , ( last [ 14 ] - layerX ) / layerWidth , ( last [ 15 ] - layerY ) / layerHeight ] , 0 ) ;
return new FreeHighlightOutline ( outline , points , this . # box , this . # scaleFactor , this . # innerMargin , this . # isLTR ) ;
}
const outline = new Float64Array ( this . # top . length + 24 + this . # bottom . length ) ;
let N = top . length ;
for ( let i = 0 ; i < N ; i += 2 ) {
if ( isNaN ( top [ i ] ) ) {
outline [ i ] = outline [ i + 1 ] = NaN ;
continue ;
}
outline [ i ] = top [ i ] ;
outline [ i + 1 ] = top [ i + 1 ] ;
}
outline . set ( [ NaN , NaN , NaN , NaN , ( lastTop [ 0 ] - layerX ) / layerWidth , ( lastTop [ 1 ] - layerY ) / layerHeight , NaN , NaN , NaN , NaN , lastTopX , lastTopY , NaN , NaN , NaN , NaN , lastBottomX , lastBottomY , NaN , NaN , NaN , NaN , ( lastBottom [ 0 ] - layerX ) / layerWidth , ( lastBottom [ 1 ] - layerY ) / layerHeight ] , N ) ;
N += 24 ;
for ( let i = bottom . length - 6 ; i >= 6 ; i -= 6 ) {
for ( let j = 0 ; j < 6 ; j += 2 ) {
if ( isNaN ( bottom [ i + j ] ) ) {
outline [ N ] = outline [ N + 1 ] = NaN ;
N += 2 ;
continue ;
}
outline [ N ] = bottom [ i + j ] ;
outline [ N + 1 ] = bottom [ i + j + 1 ] ;
N += 2 ;
}
}
outline . set ( [ NaN , NaN , NaN , NaN , bottom [ 4 ] , bottom [ 5 ] ] , N ) ;
return new FreeHighlightOutline ( outline , points , this . # box , this . # scaleFactor , this . # innerMargin , this . # isLTR ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
}
class FreeHighlightOutline extends Outline {
# box ;
# bbox = null ;
# innerMargin ;
# isLTR ;
# points ;
# scaleFactor ;
# outline ;
constructor ( outline , points , box , scaleFactor , innerMargin , isLTR ) {
super ( ) ;
this . # outline = outline ;
this . # points = points ;
this . # box = box ;
this . # scaleFactor = scaleFactor ;
this . # innerMargin = innerMargin ;
this . # isLTR = isLTR ;
this . # computeMinMax ( isLTR ) ;
2023-10-27 13:19:54 +02:00
const {
2024-06-01 11:00:27 +01:00
x ,
y ,
2023-10-27 13:19:54 +02:00
width ,
height
2024-06-01 11:00:27 +01:00
} = this . # bbox ;
for ( let i = 0 , ii = outline . length ; i < ii ; i += 2 ) {
outline [ i ] = ( outline [ i ] - x ) / width ;
outline [ i + 1 ] = ( outline [ i + 1 ] - y ) / height ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
for ( let i = 0 , ii = points . length ; i < ii ; i += 2 ) {
points [ i ] = ( points [ i ] - x ) / width ;
points [ i + 1 ] = ( points [ i + 1 ] - y ) / height ;
}
}
toSVGPath ( ) {
const buffer = [ ` M ${ this . # outline [ 4 ] } ${ this . # outline [ 5 ] } ` ] ;
for ( let i = 6 , ii = this . # outline . length ; i < ii ; i += 6 ) {
if ( isNaN ( this . # outline [ i ] ) ) {
buffer . push ( ` L ${ this . # outline [ i + 4 ] } ${ this . # outline [ i + 5 ] } ` ) ;
continue ;
}
buffer . push ( ` C ${ this . # outline [ i ] } ${ this . # outline [ i + 1 ] } ${ this . # outline [ i + 2 ] } ${ this . # outline [ i + 3 ] } ${ this . # outline [ i + 4 ] } ${ this . # outline [ i + 5 ] } ` ) ;
}
buffer . push ( "Z" ) ;
return buffer . join ( " " ) ;
}
serialize ( [ blX , blY , trX , trY ] , rotation ) {
const width = trX - blX ;
const height = trY - blY ;
let outline ;
let points ;
switch ( rotation ) {
case 0 :
outline = this . # rescale ( this . # outline , blX , trY , width , - height ) ;
points = this . # rescale ( this . # points , blX , trY , width , - height ) ;
break ;
case 90 :
outline = this . # rescaleAndSwap ( this . # outline , blX , blY , width , height ) ;
points = this . # rescaleAndSwap ( this . # points , blX , blY , width , height ) ;
break ;
case 180 :
outline = this . # rescale ( this . # outline , trX , blY , - width , height ) ;
points = this . # rescale ( this . # points , trX , blY , - width , height ) ;
break ;
case 270 :
outline = this . # rescaleAndSwap ( this . # outline , trX , trY , - width , - height ) ;
points = this . # rescaleAndSwap ( this . # points , trX , trY , - width , - height ) ;
break ;
}
return {
outline : Array . from ( outline ) ,
points : [ Array . from ( points ) ]
} ;
}
# rescale ( src , tx , ty , sx , sy ) {
const dest = new Float64Array ( src . length ) ;
for ( let i = 0 , ii = src . length ; i < ii ; i += 2 ) {
dest [ i ] = tx + src [ i ] * sx ;
dest [ i + 1 ] = ty + src [ i + 1 ] * sy ;
}
return dest ;
}
# rescaleAndSwap ( src , tx , ty , sx , sy ) {
const dest = new Float64Array ( src . length ) ;
for ( let i = 0 , ii = src . length ; i < ii ; i += 2 ) {
dest [ i ] = tx + src [ i + 1 ] * sx ;
dest [ i + 1 ] = ty + src [ i ] * sy ;
}
return dest ;
}
# computeMinMax ( isLTR ) {
const outline = this . # outline ;
let lastX = outline [ 4 ] ;
let lastY = outline [ 5 ] ;
let minX = lastX ;
let minY = lastY ;
let maxX = lastX ;
let maxY = lastY ;
let lastPointX = lastX ;
let lastPointY = lastY ;
const ltrCallback = isLTR ? Math . max : Math . min ;
for ( let i = 6 , ii = outline . length ; i < ii ; i += 6 ) {
if ( isNaN ( outline [ i ] ) ) {
minX = Math . min ( minX , outline [ i + 4 ] ) ;
minY = Math . min ( minY , outline [ i + 5 ] ) ;
maxX = Math . max ( maxX , outline [ i + 4 ] ) ;
maxY = Math . max ( maxY , outline [ i + 5 ] ) ;
if ( lastPointY < outline [ i + 5 ] ) {
lastPointX = outline [ i + 4 ] ;
lastPointY = outline [ i + 5 ] ;
} else if ( lastPointY === outline [ i + 5 ] ) {
lastPointX = ltrCallback ( lastPointX , outline [ i + 4 ] ) ;
}
} else {
const bbox = Util . bezierBoundingBox ( lastX , lastY , ... outline . slice ( i , i + 6 ) ) ;
minX = Math . min ( minX , bbox [ 0 ] ) ;
minY = Math . min ( minY , bbox [ 1 ] ) ;
maxX = Math . max ( maxX , bbox [ 2 ] ) ;
maxY = Math . max ( maxY , bbox [ 3 ] ) ;
if ( lastPointY < bbox [ 3 ] ) {
lastPointX = bbox [ 2 ] ;
lastPointY = bbox [ 3 ] ;
} else if ( lastPointY === bbox [ 3 ] ) {
lastPointX = ltrCallback ( lastPointX , bbox [ 2 ] ) ;
}
}
lastX = outline [ i + 4 ] ;
lastY = outline [ i + 5 ] ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
const x = minX - this . # innerMargin ,
y = minY - this . # innerMargin ,
width = maxX - minX + 2 * this . # innerMargin ,
height = maxY - minY + 2 * this . # innerMargin ;
this . # bbox = {
x ,
y ,
width ,
height ,
lastPoint : [ lastPointX , lastPointY ]
} ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
get box ( ) {
return this . # bbox ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
getNewOutline ( thickness , innerMargin ) {
const {
x ,
y ,
width ,
height
} = this . # bbox ;
const [ layerX , layerY , layerWidth , layerHeight ] = this . # box ;
const sx = width * layerWidth ;
const sy = height * layerHeight ;
const tx = x * layerWidth + layerX ;
const ty = y * layerHeight + layerY ;
const outliner = new FreeOutliner ( {
x : this . # points [ 0 ] * sx + tx ,
y : this . # points [ 1 ] * sy + ty
} , this . # box , this . # scaleFactor , thickness , this . # isLTR , innerMargin ? ? this . # innerMargin ) ;
for ( let i = 2 ; i < this . # points . length ; i += 2 ) {
outliner . add ( {
x : this . # points [ i ] * sx + tx ,
y : this . # points [ i + 1 ] * sy + ty
} ) ;
}
return outliner . getOutlines ( ) ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
; // CONCATENATED MODULE: ./src/display/editor/color_picker.js
class ColorPicker {
# boundKeyDown = this . # keyDown . bind ( this ) ;
# boundPointerDown = this . # pointerDown . bind ( this ) ;
# button = null ;
# buttonSwatch = null ;
# defaultColor ;
# dropdown = null ;
# dropdownWasFromKeyboard = false ;
# isMainColorPicker = false ;
# editor = null ;
# eventBus ;
# uiManager = null ;
# type ;
static get _keyboardManager ( ) {
return shadow ( this , "_keyboardManager" , new KeyboardManager ( [ [ [ "Escape" , "mac+Escape" ] , ColorPicker . prototype . _hideDropdownFromKeyboard ] , [ [ " " , "mac+ " ] , ColorPicker . prototype . _colorSelectFromKeyboard ] , [ [ "ArrowDown" , "ArrowRight" , "mac+ArrowDown" , "mac+ArrowRight" ] , ColorPicker . prototype . _moveToNext ] , [ [ "ArrowUp" , "ArrowLeft" , "mac+ArrowUp" , "mac+ArrowLeft" ] , ColorPicker . prototype . _moveToPrevious ] , [ [ "Home" , "mac+Home" ] , ColorPicker . prototype . _moveToBeginning ] , [ [ "End" , "mac+End" ] , ColorPicker . prototype . _moveToEnd ] ] ) ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
constructor ( {
editor = null ,
uiManager = null
} ) {
if ( editor ) {
this . # isMainColorPicker = false ;
this . # type = AnnotationEditorParamsType . HIGHLIGHT _COLOR ;
this . # editor = editor ;
} else {
this . # isMainColorPicker = true ;
this . # type = AnnotationEditorParamsType . HIGHLIGHT _DEFAULT _COLOR ;
}
this . # uiManager = editor ? . _uiManager || uiManager ;
this . # eventBus = this . # uiManager . _eventBus ;
this . # defaultColor = editor ? . color || this . # uiManager ? . highlightColors . values ( ) . next ( ) . value || "#FFFF98" ;
}
renderButton ( ) {
const button = this . # button = document . createElement ( "button" ) ;
button . className = "colorPicker" ;
button . tabIndex = "0" ;
button . setAttribute ( "data-l10n-id" , "pdfjs-editor-colorpicker-button" ) ;
button . setAttribute ( "aria-haspopup" , true ) ;
button . addEventListener ( "click" , this . # openDropdown . bind ( this ) ) ;
button . addEventListener ( "keydown" , this . # boundKeyDown ) ;
const swatch = this . # buttonSwatch = document . createElement ( "span" ) ;
swatch . className = "swatch" ;
swatch . setAttribute ( "aria-hidden" , true ) ;
swatch . style . backgroundColor = this . # defaultColor ;
button . append ( swatch ) ;
return button ;
}
renderMainDropdown ( ) {
const dropdown = this . # dropdown = this . # getDropdownRoot ( ) ;
dropdown . setAttribute ( "aria-orientation" , "horizontal" ) ;
dropdown . setAttribute ( "aria-labelledby" , "highlightColorPickerLabel" ) ;
return dropdown ;
}
# getDropdownRoot ( ) {
const div = document . createElement ( "div" ) ;
div . addEventListener ( "contextmenu" , noContextMenu ) ;
div . className = "dropdown" ;
div . role = "listbox" ;
div . setAttribute ( "aria-multiselectable" , false ) ;
div . setAttribute ( "aria-orientation" , "vertical" ) ;
div . setAttribute ( "data-l10n-id" , "pdfjs-editor-colorpicker-dropdown" ) ;
for ( const [ name , color ] of this . # uiManager . highlightColors ) {
const button = document . createElement ( "button" ) ;
button . tabIndex = "0" ;
button . role = "option" ;
button . setAttribute ( "data-color" , color ) ;
button . title = name ;
button . setAttribute ( "data-l10n-id" , ` pdfjs-editor-colorpicker- ${ name } ` ) ;
const swatch = document . createElement ( "span" ) ;
button . append ( swatch ) ;
swatch . className = "swatch" ;
swatch . style . backgroundColor = color ;
button . setAttribute ( "aria-selected" , color === this . # defaultColor ) ;
button . addEventListener ( "click" , this . # colorSelect . bind ( this , color ) ) ;
div . append ( button ) ;
}
div . addEventListener ( "keydown" , this . # boundKeyDown ) ;
return div ;
}
# colorSelect ( color , event ) {
event . stopPropagation ( ) ;
this . # eventBus . dispatch ( "switchannotationeditorparams" , {
source : this ,
type : this . # type ,
value : color
2023-10-27 13:19:54 +02:00
} ) ;
}
2024-06-01 11:00:27 +01:00
_colorSelectFromKeyboard ( event ) {
if ( event . target === this . # button ) {
this . # openDropdown ( event ) ;
return ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
const color = event . target . getAttribute ( "data-color" ) ;
if ( ! color ) {
return ;
}
this . # colorSelect ( color , event ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
_moveToNext ( event ) {
if ( ! this . # isDropdownVisible ) {
this . # openDropdown ( event ) ;
return ;
}
if ( event . target === this . # button ) {
this . # dropdown . firstChild ? . focus ( ) ;
return ;
}
event . target . nextSibling ? . focus ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
_moveToPrevious ( event ) {
if ( event . target === this . # dropdown ? . firstChild || event . target === this . # button ) {
if ( this . # isDropdownVisible ) {
this . _hideDropdownFromKeyboard ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
return ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
if ( ! this . # isDropdownVisible ) {
this . # openDropdown ( event ) ;
}
event . target . previousSibling ? . focus ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
_moveToBeginning ( event ) {
if ( ! this . # isDropdownVisible ) {
this . # openDropdown ( event ) ;
return ;
}
this . # dropdown . firstChild ? . focus ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
_moveToEnd ( event ) {
if ( ! this . # isDropdownVisible ) {
this . # openDropdown ( event ) ;
return ;
}
this . # dropdown . lastChild ? . focus ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
# keyDown ( event ) {
ColorPicker . _keyboardManager . exec ( this , event ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
# openDropdown ( event ) {
if ( this . # isDropdownVisible ) {
this . hideDropdown ( ) ;
return ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
this . # dropdownWasFromKeyboard = event . detail === 0 ;
window . addEventListener ( "pointerdown" , this . # boundPointerDown ) ;
if ( this . # dropdown ) {
this . # dropdown . classList . remove ( "hidden" ) ;
return ;
}
const root = this . # dropdown = this . # getDropdownRoot ( ) ;
this . # button . append ( root ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
# pointerDown ( event ) {
if ( this . # dropdown ? . contains ( event . target ) ) {
return ;
}
this . hideDropdown ( ) ;
}
hideDropdown ( ) {
this . # dropdown ? . classList . add ( "hidden" ) ;
window . removeEventListener ( "pointerdown" , this . # boundPointerDown ) ;
}
get # isDropdownVisible ( ) {
return this . # dropdown && ! this . # dropdown . classList . contains ( "hidden" ) ;
}
_hideDropdownFromKeyboard ( ) {
if ( this . # isMainColorPicker ) {
return ;
}
if ( ! this . # isDropdownVisible ) {
this . # editor ? . unselect ( ) ;
return ;
}
this . hideDropdown ( ) ;
this . # button . focus ( {
preventScroll : true ,
focusVisible : this . # dropdownWasFromKeyboard
2023-10-27 13:19:54 +02:00
} ) ;
}
2024-06-01 11:00:27 +01:00
updateColor ( color ) {
if ( this . # buttonSwatch ) {
this . # buttonSwatch . style . backgroundColor = color ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
if ( ! this . # dropdown ) {
return ;
}
const i = this . # uiManager . highlightColors . values ( ) ;
for ( const child of this . # dropdown . children ) {
child . setAttribute ( "aria-selected" , i . next ( ) . value === color ) ;
}
}
destroy ( ) {
this . # button ? . remove ( ) ;
this . # button = null ;
this . # buttonSwatch = null ;
this . # dropdown ? . remove ( ) ;
this . # dropdown = null ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
; // CONCATENATED MODULE: ./src/display/editor/highlight.js
2024-06-18 20:06:52 +02:00
2024-06-01 11:00:27 +01:00
class HighlightEditor extends AnnotationEditor {
# anchorNode = null ;
# anchorOffset = 0 ;
# boxes ;
# clipPathId = null ;
# colorPicker = null ;
# focusOutlines = null ;
# focusNode = null ;
# focusOffset = 0 ;
# highlightDiv = null ;
# highlightOutlines = null ;
# id = null ;
# isFreeHighlight = false ;
# boundKeydown = this . # keydown . bind ( this ) ;
# lastPoint = null ;
# opacity ;
# outlineId = null ;
# text = "" ;
# thickness ;
# methodOfCreation = "" ;
static _defaultColor = null ;
static _defaultOpacity = 1 ;
static _defaultThickness = 12 ;
static _l10nPromise ;
static _type = "highlight" ;
static _editorType = AnnotationEditorType . HIGHLIGHT ;
static _freeHighlightId = - 1 ;
static _freeHighlight = null ;
static _freeHighlightClipId = "" ;
static get _keyboardManager ( ) {
const proto = HighlightEditor . prototype ;
return shadow ( this , "_keyboardManager" , new KeyboardManager ( [ [ [ "ArrowLeft" , "mac+ArrowLeft" ] , proto . _moveCaret , {
args : [ 0 ]
} ] , [ [ "ArrowRight" , "mac+ArrowRight" ] , proto . _moveCaret , {
args : [ 1 ]
} ] , [ [ "ArrowUp" , "mac+ArrowUp" ] , proto . _moveCaret , {
args : [ 2 ]
} ] , [ [ "ArrowDown" , "mac+ArrowDown" ] , proto . _moveCaret , {
args : [ 3 ]
} ] ] ) ) ;
}
constructor ( params ) {
super ( {
... params ,
name : "highlightEditor"
2023-10-27 13:19:54 +02:00
} ) ;
2024-06-01 11:00:27 +01:00
this . color = params . color || HighlightEditor . _defaultColor ;
this . # thickness = params . thickness || HighlightEditor . _defaultThickness ;
this . # opacity = params . opacity || HighlightEditor . _defaultOpacity ;
this . # boxes = params . boxes || null ;
this . # methodOfCreation = params . methodOfCreation || "" ;
this . # text = params . text || "" ;
this . _isDraggable = false ;
if ( params . highlightId > - 1 ) {
this . # isFreeHighlight = true ;
this . # createFreeOutlines ( params ) ;
this . # addToDrawLayer ( ) ;
} else {
this . # anchorNode = params . anchorNode ;
this . # anchorOffset = params . anchorOffset ;
this . # focusNode = params . focusNode ;
this . # focusOffset = params . focusOffset ;
this . # createOutlines ( ) ;
this . # addToDrawLayer ( ) ;
this . rotate ( this . rotation ) ;
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
get telemetryInitialData ( ) {
return {
action : "added" ,
type : this . # isFreeHighlight ? "free_highlight" : "highlight" ,
color : this . _uiManager . highlightColorNames . get ( this . color ) ,
thickness : this . # thickness ,
methodOfCreation : this . # methodOfCreation
} ;
}
get telemetryFinalData ( ) {
return {
type : "highlight" ,
color : this . _uiManager . highlightColorNames . get ( this . color )
} ;
}
static computeTelemetryFinalData ( data ) {
return {
numberOfColors : data . get ( "color" ) . size
} ;
}
# createOutlines ( ) {
const outliner = new Outliner ( this . # boxes , 0.001 ) ;
this . # highlightOutlines = outliner . getOutlines ( ) ;
( {
x : this . x ,
y : this . y ,
width : this . width ,
height : this . height
} = this . # highlightOutlines . box ) ;
const outlinerForOutline = new Outliner ( this . # boxes , 0.0025 , 0.001 , this . _uiManager . direction === "ltr" ) ;
this . # focusOutlines = outlinerForOutline . getOutlines ( ) ;
const {
lastPoint
} = this . # focusOutlines . box ;
this . # lastPoint = [ ( lastPoint [ 0 ] - this . x ) / this . width , ( lastPoint [ 1 ] - this . y ) / this . height ] ;
}
# createFreeOutlines ( {
highlightOutlines ,
highlightId ,
clipPathId
} ) {
this . # highlightOutlines = highlightOutlines ;
const extraThickness = 1.5 ;
this . # focusOutlines = highlightOutlines . getNewOutline ( this . # thickness / 2 + extraThickness , 0.0025 ) ;
if ( highlightId >= 0 ) {
this . # id = highlightId ;
this . # clipPathId = clipPathId ;
this . parent . drawLayer . finalizeLine ( highlightId , highlightOutlines ) ;
this . # outlineId = this . parent . drawLayer . highlightOutline ( this . # focusOutlines ) ;
} else if ( this . parent ) {
const angle = this . parent . viewport . rotation ;
this . parent . drawLayer . updateLine ( this . # id , highlightOutlines ) ;
this . parent . drawLayer . updateBox ( this . # id , HighlightEditor . # rotateBbox ( this . # highlightOutlines . box , ( angle - this . rotation + 360 ) % 360 ) ) ;
this . parent . drawLayer . updateLine ( this . # outlineId , this . # focusOutlines ) ;
this . parent . drawLayer . updateBox ( this . # outlineId , HighlightEditor . # rotateBbox ( this . # focusOutlines . box , angle ) ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
const {
x ,
y ,
width ,
height
} = highlightOutlines . box ;
switch ( this . rotation ) {
case 0 :
this . x = x ;
this . y = y ;
this . width = width ;
this . height = height ;
break ;
case 90 :
{
const [ pageWidth , pageHeight ] = this . parentDimensions ;
this . x = y ;
this . y = 1 - x ;
this . width = width * pageHeight / pageWidth ;
this . height = height * pageWidth / pageHeight ;
break ;
}
case 180 :
this . x = 1 - x ;
this . y = 1 - y ;
this . width = width ;
this . height = height ;
break ;
case 270 :
{
const [ pageWidth , pageHeight ] = this . parentDimensions ;
this . x = 1 - y ;
this . y = x ;
this . width = width * pageHeight / pageWidth ;
this . height = height * pageWidth / pageHeight ;
break ;
}
}
const {
lastPoint
} = this . # focusOutlines . box ;
this . # lastPoint = [ ( lastPoint [ 0 ] - x ) / width , ( lastPoint [ 1 ] - y ) / height ] ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
static initialize ( l10n , uiManager ) {
AnnotationEditor . initialize ( l10n , uiManager ) ;
HighlightEditor . _defaultColor || = uiManager . highlightColors ? . values ( ) . next ( ) . value || "#fff066" ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
static updateDefaultParams ( type , value ) {
switch ( type ) {
case AnnotationEditorParamsType . HIGHLIGHT _DEFAULT _COLOR :
HighlightEditor . _defaultColor = value ;
break ;
case AnnotationEditorParamsType . HIGHLIGHT _THICKNESS :
HighlightEditor . _defaultThickness = value ;
break ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
translateInPage ( x , y ) { }
get toolbarPosition ( ) {
return this . # lastPoint ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
updateParams ( type , value ) {
switch ( type ) {
case AnnotationEditorParamsType . HIGHLIGHT _COLOR :
this . # updateColor ( value ) ;
break ;
case AnnotationEditorParamsType . HIGHLIGHT _THICKNESS :
this . # updateThickness ( value ) ;
break ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
static get defaultPropertiesToUpdate ( ) {
return [ [ AnnotationEditorParamsType . HIGHLIGHT _DEFAULT _COLOR , HighlightEditor . _defaultColor ] , [ AnnotationEditorParamsType . HIGHLIGHT _THICKNESS , HighlightEditor . _defaultThickness ] ] ;
}
get propertiesToUpdate ( ) {
return [ [ AnnotationEditorParamsType . HIGHLIGHT _COLOR , this . color || HighlightEditor . _defaultColor ] , [ AnnotationEditorParamsType . HIGHLIGHT _THICKNESS , this . # thickness || HighlightEditor . _defaultThickness ] , [ AnnotationEditorParamsType . HIGHLIGHT _FREE , this . # isFreeHighlight ] ] ;
}
# updateColor ( color ) {
const setColor = col => {
this . color = col ;
this . parent ? . drawLayer . changeColor ( this . # id , col ) ;
this . # colorPicker ? . updateColor ( col ) ;
} ;
const savedColor = this . color ;
this . addCommands ( {
cmd : setColor . bind ( this , color ) ,
undo : setColor . bind ( this , savedColor ) ,
post : this . _uiManager . updateUI . bind ( this . _uiManager , this ) ,
mustExec : true ,
type : AnnotationEditorParamsType . HIGHLIGHT _COLOR ,
overwriteIfSameType : true ,
keepUndo : true
2023-10-27 13:19:54 +02:00
} ) ;
2024-06-01 11:00:27 +01:00
this . _reportTelemetry ( {
action : "color_changed" ,
color : this . _uiManager . highlightColorNames . get ( color )
} , true ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
# updateThickness ( thickness ) {
const savedThickness = this . # thickness ;
const setThickness = th => {
this . # thickness = th ;
this . # changeThickness ( th ) ;
} ;
this . addCommands ( {
cmd : setThickness . bind ( this , thickness ) ,
undo : setThickness . bind ( this , savedThickness ) ,
post : this . _uiManager . updateUI . bind ( this . _uiManager , this ) ,
mustExec : true ,
type : AnnotationEditorParamsType . INK _THICKNESS ,
overwriteIfSameType : true ,
keepUndo : true
2023-10-27 13:19:54 +02:00
} ) ;
2024-06-01 11:00:27 +01:00
this . _reportTelemetry ( {
action : "thickness_changed" ,
thickness
} , true ) ;
}
async addEditToolbar ( ) {
const toolbar = await super . addEditToolbar ( ) ;
if ( ! toolbar ) {
return null ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
if ( this . _uiManager . highlightColors ) {
this . # colorPicker = new ColorPicker ( {
editor : this
} ) ;
toolbar . addColorPicker ( this . # colorPicker ) ;
}
return toolbar ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
disableEditing ( ) {
super . disableEditing ( ) ;
this . div . classList . toggle ( "disabled" , true ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
enableEditing ( ) {
super . enableEditing ( ) ;
this . div . classList . toggle ( "disabled" , false ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
fixAndSetPosition ( ) {
return super . fixAndSetPosition ( this . # getRotation ( ) ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
getBaseTranslation ( ) {
return [ 0 , 0 ] ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
getRect ( tx , ty ) {
return super . getRect ( tx , ty , this . # getRotation ( ) ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
onceAdded ( ) {
this . parent . addUndoableEditor ( this ) ;
this . div . focus ( ) ;
}
remove ( ) {
this . # cleanDrawLayer ( ) ;
this . _reportTelemetry ( {
action : "deleted"
} ) ;
super . remove ( ) ;
}
rebuild ( ) {
if ( ! this . parent ) {
return ;
}
super . rebuild ( ) ;
if ( this . div === null ) {
return ;
}
this . # addToDrawLayer ( ) ;
if ( ! this . isAttachedToDOM ) {
this . parent . add ( this ) ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
setParent ( parent ) {
let mustBeSelected = false ;
if ( this . parent && ! parent ) {
this . # cleanDrawLayer ( ) ;
} else if ( parent ) {
this . # addToDrawLayer ( parent ) ;
mustBeSelected = ! this . parent && this . div ? . classList . contains ( "selectedEditor" ) ;
}
super . setParent ( parent ) ;
this . show ( this . _isVisible ) ;
if ( mustBeSelected ) {
this . select ( ) ;
}
}
# changeThickness ( thickness ) {
if ( ! this . # isFreeHighlight ) {
return ;
}
this . # createFreeOutlines ( {
highlightOutlines : this . # highlightOutlines . getNewOutline ( thickness / 2 )
2023-10-27 13:19:54 +02:00
} ) ;
2024-06-01 11:00:27 +01:00
this . fixAndSetPosition ( ) ;
const [ parentWidth , parentHeight ] = this . parentDimensions ;
this . setDims ( this . width * parentWidth , this . height * parentHeight ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
# cleanDrawLayer ( ) {
if ( this . # id === null || ! this . parent ) {
2023-10-27 13:19:54 +02:00
return ;
}
2024-06-01 11:00:27 +01:00
this . parent . drawLayer . remove ( this . # id ) ;
this . # id = null ;
this . parent . drawLayer . remove ( this . # outlineId ) ;
this . # outlineId = null ;
}
# addToDrawLayer ( parent = this . parent ) {
if ( this . # id !== null ) {
return ;
}
( {
id : this . # id ,
clipPathId : this . # clipPathId
} = parent . drawLayer . highlight ( this . # highlightOutlines , this . color , this . # opacity ) ) ;
this . # outlineId = parent . drawLayer . highlightOutline ( this . # focusOutlines ) ;
if ( this . # highlightDiv ) {
this . # highlightDiv . style . clipPath = this . # clipPathId ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
static # rotateBbox ( {
x ,
y ,
width ,
height
} , angle ) {
switch ( angle ) {
case 90 :
return {
x : 1 - y - height ,
y : x ,
width : height ,
height : width
} ;
case 180 :
return {
x : 1 - x - width ,
y : 1 - y - height ,
width ,
height
} ;
case 270 :
return {
x : y ,
y : 1 - x - width ,
width : height ,
height : width
} ;
}
return {
x ,
y ,
width ,
height
} ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
rotate ( angle ) {
const {
drawLayer
} = this . parent ;
let box ;
if ( this . # isFreeHighlight ) {
angle = ( angle - this . rotation + 360 ) % 360 ;
box = HighlightEditor . # rotateBbox ( this . # highlightOutlines . box , angle ) ;
} else {
box = HighlightEditor . # rotateBbox ( this , angle ) ;
}
drawLayer . rotate ( this . # id , angle ) ;
drawLayer . rotate ( this . # outlineId , angle ) ;
drawLayer . updateBox ( this . # id , box ) ;
drawLayer . updateBox ( this . # outlineId , HighlightEditor . # rotateBbox ( this . # focusOutlines . box , angle ) ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
render ( ) {
if ( this . div ) {
return this . div ;
}
const div = super . render ( ) ;
if ( this . # text ) {
div . setAttribute ( "aria-label" , this . # text ) ;
div . setAttribute ( "role" , "mark" ) ;
}
if ( this . # isFreeHighlight ) {
div . classList . add ( "free" ) ;
} else {
this . div . addEventListener ( "keydown" , this . # boundKeydown ) ;
}
const highlightDiv = this . # highlightDiv = document . createElement ( "div" ) ;
div . append ( highlightDiv ) ;
highlightDiv . setAttribute ( "aria-hidden" , "true" ) ;
highlightDiv . className = "internal" ;
highlightDiv . style . clipPath = this . # clipPathId ;
const [ parentWidth , parentHeight ] = this . parentDimensions ;
this . setDims ( this . width * parentWidth , this . height * parentHeight ) ;
bindEvents ( this , this . # highlightDiv , [ "pointerover" , "pointerleave" ] ) ;
this . enableEditing ( ) ;
return div ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
pointerover ( ) {
this . parent . drawLayer . addClass ( this . # outlineId , "hovered" ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
pointerleave ( ) {
this . parent . drawLayer . removeClass ( this . # outlineId , "hovered" ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
# keydown ( event ) {
HighlightEditor . _keyboardManager . exec ( this , event ) ;
}
_moveCaret ( direction ) {
this . parent . unselect ( this ) ;
switch ( direction ) {
case 0 :
case 2 :
this . # setCaret ( true ) ;
break ;
case 1 :
case 3 :
this . # setCaret ( false ) ;
break ;
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
# setCaret ( start ) {
if ( ! this . # anchorNode ) {
return ;
}
const selection = window . getSelection ( ) ;
if ( start ) {
selection . setPosition ( this . # anchorNode , this . # anchorOffset ) ;
} else {
selection . setPosition ( this . # focusNode , this . # focusOffset ) ;
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
select ( ) {
super . select ( ) ;
if ( ! this . # outlineId ) {
return ;
}
this . parent ? . drawLayer . removeClass ( this . # outlineId , "hovered" ) ;
this . parent ? . drawLayer . addClass ( this . # outlineId , "selected" ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
unselect ( ) {
super . unselect ( ) ;
if ( ! this . # outlineId ) {
return ;
}
this . parent ? . drawLayer . removeClass ( this . # outlineId , "selected" ) ;
if ( ! this . # isFreeHighlight ) {
this . # setCaret ( false ) ;
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
get _mustFixPosition ( ) {
return ! this . # isFreeHighlight ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
show ( visible = this . _isVisible ) {
super . show ( visible ) ;
if ( this . parent ) {
this . parent . drawLayer . show ( this . # id , visible ) ;
this . parent . drawLayer . show ( this . # outlineId , visible ) ;
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
# getRotation ( ) {
return this . # isFreeHighlight ? this . rotation : 0 ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
# serializeBoxes ( ) {
if ( this . # isFreeHighlight ) {
return null ;
}
const [ pageWidth , pageHeight ] = this . pageDimensions ;
const boxes = this . # boxes ;
2024-06-02 09:12:22 +01:00
const quadPoints = new Float32Array ( boxes . length * 8 ) ;
2024-06-01 11:00:27 +01:00
let i = 0 ;
for ( const {
x ,
y ,
width ,
height
} of boxes ) {
const sx = x * pageWidth ;
const sy = ( 1 - y - height ) * pageHeight ;
quadPoints [ i ] = quadPoints [ i + 4 ] = sx ;
quadPoints [ i + 1 ] = quadPoints [ i + 3 ] = sy ;
quadPoints [ i + 2 ] = quadPoints [ i + 6 ] = sx + width * pageWidth ;
quadPoints [ i + 5 ] = quadPoints [ i + 7 ] = sy + height * pageHeight ;
i += 8 ;
}
return quadPoints ;
}
# serializeOutlines ( rect ) {
return this . # highlightOutlines . serialize ( rect , this . # getRotation ( ) ) ;
}
static startHighlighting ( parent , isLTR , {
target : textLayer ,
x ,
y
} ) {
const {
x : layerX ,
y : layerY ,
width : parentWidth ,
height : parentHeight
} = textLayer . getBoundingClientRect ( ) ;
const pointerMove = e => {
this . # highlightMove ( parent , e ) ;
} ;
const pointerDownOptions = {
capture : true ,
passive : false
} ;
const pointerDown = e => {
e . preventDefault ( ) ;
e . stopPropagation ( ) ;
} ;
const pointerUpCallback = e => {
textLayer . removeEventListener ( "pointermove" , pointerMove ) ;
window . removeEventListener ( "blur" , pointerUpCallback ) ;
window . removeEventListener ( "pointerup" , pointerUpCallback ) ;
window . removeEventListener ( "pointerdown" , pointerDown , pointerDownOptions ) ;
window . removeEventListener ( "contextmenu" , noContextMenu ) ;
this . # endHighlight ( parent , e ) ;
} ;
window . addEventListener ( "blur" , pointerUpCallback ) ;
window . addEventListener ( "pointerup" , pointerUpCallback ) ;
window . addEventListener ( "pointerdown" , pointerDown , pointerDownOptions ) ;
window . addEventListener ( "contextmenu" , noContextMenu ) ;
textLayer . addEventListener ( "pointermove" , pointerMove ) ;
this . _freeHighlight = new FreeOutliner ( {
x ,
y
} , [ layerX , layerY , parentWidth , parentHeight ] , parent . scale , this . _defaultThickness / 2 , isLTR , 0.001 ) ;
( {
id : this . _freeHighlightId ,
clipPathId : this . _freeHighlightClipId
} = parent . drawLayer . highlight ( this . _freeHighlight , this . _defaultColor , this . _defaultOpacity , true ) ) ;
}
static # highlightMove ( parent , event ) {
if ( this . _freeHighlight . add ( event ) ) {
parent . drawLayer . updatePath ( this . _freeHighlightId , this . _freeHighlight ) ;
}
}
static # endHighlight ( parent , event ) {
if ( ! this . _freeHighlight . isEmpty ( ) ) {
parent . createAndAddNewEditor ( event , false , {
highlightId : this . _freeHighlightId ,
highlightOutlines : this . _freeHighlight . getOutlines ( ) ,
clipPathId : this . _freeHighlightClipId ,
methodOfCreation : "main_toolbar"
} ) ;
} else {
parent . drawLayer . removeFreeHighlight ( this . _freeHighlightId ) ;
}
this . _freeHighlightId = - 1 ;
this . _freeHighlight = null ;
this . _freeHighlightClipId = "" ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
static deserialize ( data , parent , uiManager ) {
const editor = super . deserialize ( data , parent , uiManager ) ;
const {
rect : [ blX , blY , trX , trY ] ,
color ,
quadPoints
} = data ;
editor . color = Util . makeHexColor ( ... color ) ;
editor . # opacity = data . opacity ;
const [ pageWidth , pageHeight ] = editor . pageDimensions ;
editor . width = ( trX - blX ) / pageWidth ;
editor . height = ( trY - blY ) / pageHeight ;
const boxes = editor . # boxes = [ ] ;
for ( let i = 0 ; i < quadPoints . length ; i += 8 ) {
boxes . push ( {
x : ( quadPoints [ 4 ] - trX ) / pageWidth ,
y : ( trY - ( 1 - quadPoints [ i + 5 ] ) ) / pageHeight ,
width : ( quadPoints [ i + 2 ] - quadPoints [ i ] ) / pageWidth ,
height : ( quadPoints [ i + 5 ] - quadPoints [ i + 1 ] ) / pageHeight
} ) ;
}
editor . # createOutlines ( ) ;
return editor ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
serialize ( isForCopying = false ) {
if ( this . isEmpty ( ) || isForCopying ) {
return null ;
}
const rect = this . getRect ( 0 , 0 ) ;
const color = AnnotationEditor . _colorManager . convert ( this . color ) ;
return {
annotationType : AnnotationEditorType . HIGHLIGHT ,
color ,
opacity : this . # opacity ,
thickness : this . # thickness ,
quadPoints : this . # serializeBoxes ( ) ,
outlines : this . # serializeOutlines ( rect ) ,
pageIndex : this . pageIndex ,
rect ,
rotation : this . # getRotation ( ) ,
structTreeParentId : this . _structTreeParentId
} ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
static canCreateNewEmptyEditor ( ) {
return false ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
; // CONCATENATED MODULE: ./src/display/editor/ink.js
2023-10-27 13:19:54 +02:00
2024-06-18 20:06:52 +02:00
2024-06-01 11:00:27 +01:00
class InkEditor extends AnnotationEditor {
# baseHeight = 0 ;
# baseWidth = 0 ;
# boundCanvasPointermove = this . canvasPointermove . bind ( this ) ;
# boundCanvasPointerleave = this . canvasPointerleave . bind ( this ) ;
# boundCanvasPointerup = this . canvasPointerup . bind ( this ) ;
# boundCanvasPointerdown = this . canvasPointerdown . bind ( this ) ;
# canvasContextMenuTimeoutId = null ;
# currentPath2D = new Path2D ( ) ;
# disableEditing = false ;
# hasSomethingToDraw = false ;
# isCanvasInitialized = false ;
# observer = null ;
# realWidth = 0 ;
# realHeight = 0 ;
# requestFrameCallback = null ;
static _defaultColor = null ;
static _defaultOpacity = 1 ;
static _defaultThickness = 1 ;
static _type = "ink" ;
static _editorType = AnnotationEditorType . INK ;
constructor ( params ) {
super ( {
... params ,
name : "inkEditor"
2023-10-27 13:19:54 +02:00
} ) ;
2024-06-01 11:00:27 +01:00
this . color = params . color || null ;
this . thickness = params . thickness || null ;
this . opacity = params . opacity || null ;
this . paths = [ ] ;
this . bezierPath2D = [ ] ;
this . allRawPaths = [ ] ;
this . currentPath = [ ] ;
this . scaleFactor = 1 ;
this . translationX = this . translationY = 0 ;
this . x = 0 ;
this . y = 0 ;
this . _willKeepAspectRatio = true ;
}
static initialize ( l10n , uiManager ) {
AnnotationEditor . initialize ( l10n , uiManager ) ;
}
static updateDefaultParams ( type , value ) {
switch ( type ) {
case AnnotationEditorParamsType . INK _THICKNESS :
InkEditor . _defaultThickness = value ;
2023-10-27 13:19:54 +02:00
break ;
2024-06-01 11:00:27 +01:00
case AnnotationEditorParamsType . INK _COLOR :
InkEditor . _defaultColor = value ;
2023-10-27 13:19:54 +02:00
break ;
2024-06-01 11:00:27 +01:00
case AnnotationEditorParamsType . INK _OPACITY :
InkEditor . _defaultOpacity = value / 100 ;
break ;
}
}
updateParams ( type , value ) {
switch ( type ) {
case AnnotationEditorParamsType . INK _THICKNESS :
this . # updateThickness ( value ) ;
break ;
case AnnotationEditorParamsType . INK _COLOR :
this . # updateColor ( value ) ;
2023-10-27 13:19:54 +02:00
break ;
2024-06-01 11:00:27 +01:00
case AnnotationEditorParamsType . INK _OPACITY :
this . # updateOpacity ( value ) ;
break ;
}
}
static get defaultPropertiesToUpdate ( ) {
return [ [ AnnotationEditorParamsType . INK _THICKNESS , InkEditor . _defaultThickness ] , [ AnnotationEditorParamsType . INK _COLOR , InkEditor . _defaultColor || AnnotationEditor . _defaultLineColor ] , [ AnnotationEditorParamsType . INK _OPACITY , Math . round ( InkEditor . _defaultOpacity * 100 ) ] ] ;
}
get propertiesToUpdate ( ) {
return [ [ AnnotationEditorParamsType . INK _THICKNESS , this . thickness || InkEditor . _defaultThickness ] , [ AnnotationEditorParamsType . INK _COLOR , this . color || InkEditor . _defaultColor || AnnotationEditor . _defaultLineColor ] , [ AnnotationEditorParamsType . INK _OPACITY , Math . round ( 100 * ( this . opacity ? ? InkEditor . _defaultOpacity ) ) ] ] ;
}
# updateThickness ( thickness ) {
const setThickness = th => {
this . thickness = th ;
this . # fitToContent ( ) ;
} ;
const savedThickness = this . thickness ;
this . addCommands ( {
cmd : setThickness . bind ( this , thickness ) ,
undo : setThickness . bind ( this , savedThickness ) ,
post : this . _uiManager . updateUI . bind ( this . _uiManager , this ) ,
mustExec : true ,
type : AnnotationEditorParamsType . INK _THICKNESS ,
overwriteIfSameType : true ,
keepUndo : true
} ) ;
}
# updateColor ( color ) {
const setColor = col => {
this . color = col ;
this . # redraw ( ) ;
} ;
const savedColor = this . color ;
this . addCommands ( {
cmd : setColor . bind ( this , color ) ,
undo : setColor . bind ( this , savedColor ) ,
post : this . _uiManager . updateUI . bind ( this . _uiManager , this ) ,
mustExec : true ,
type : AnnotationEditorParamsType . INK _COLOR ,
overwriteIfSameType : true ,
keepUndo : true
} ) ;
}
# updateOpacity ( opacity ) {
const setOpacity = op => {
this . opacity = op ;
this . # redraw ( ) ;
} ;
opacity /= 100 ;
const savedOpacity = this . opacity ;
this . addCommands ( {
cmd : setOpacity . bind ( this , opacity ) ,
undo : setOpacity . bind ( this , savedOpacity ) ,
post : this . _uiManager . updateUI . bind ( this . _uiManager , this ) ,
mustExec : true ,
type : AnnotationEditorParamsType . INK _OPACITY ,
overwriteIfSameType : true ,
keepUndo : true
} ) ;
}
rebuild ( ) {
if ( ! this . parent ) {
return ;
}
super . rebuild ( ) ;
if ( this . div === null ) {
return ;
}
if ( ! this . canvas ) {
this . # createCanvas ( ) ;
this . # createObserver ( ) ;
}
if ( ! this . isAttachedToDOM ) {
this . parent . add ( this ) ;
this . # setCanvasDims ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
this . # fitToContent ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
remove ( ) {
if ( this . canvas === null ) {
return ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
if ( ! this . isEmpty ( ) ) {
this . commit ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
this . canvas . width = this . canvas . height = 0 ;
this . canvas . remove ( ) ;
this . canvas = null ;
if ( this . # canvasContextMenuTimeoutId ) {
clearTimeout ( this . # canvasContextMenuTimeoutId ) ;
this . # canvasContextMenuTimeoutId = null ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
this . # observer . disconnect ( ) ;
this . # observer = null ;
super . remove ( ) ;
}
setParent ( parent ) {
if ( ! this . parent && parent ) {
this . _uiManager . removeShouldRescale ( this ) ;
} else if ( this . parent && parent === null ) {
this . _uiManager . addShouldRescale ( this ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
super . setParent ( parent ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
onScaleChanging ( ) {
const [ parentWidth , parentHeight ] = this . parentDimensions ;
const width = this . width * parentWidth ;
const height = this . height * parentHeight ;
this . setDimensions ( width , height ) ;
}
enableEditMode ( ) {
if ( this . # disableEditing || this . canvas === null ) {
return ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
super . enableEditMode ( ) ;
this . _isDraggable = false ;
this . canvas . addEventListener ( "pointerdown" , this . # boundCanvasPointerdown ) ;
}
disableEditMode ( ) {
if ( ! this . isInEditMode ( ) || this . canvas === null ) {
return ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
super . disableEditMode ( ) ;
this . _isDraggable = ! this . isEmpty ( ) ;
this . div . classList . remove ( "editing" ) ;
this . canvas . removeEventListener ( "pointerdown" , this . # boundCanvasPointerdown ) ;
}
onceAdded ( ) {
this . _isDraggable = ! this . isEmpty ( ) ;
}
isEmpty ( ) {
return this . paths . length === 0 || this . paths . length === 1 && this . paths [ 0 ] . length === 0 ;
}
# getInitialBBox ( ) {
const {
parentRotation ,
parentDimensions : [ width , height ]
} = this ;
switch ( parentRotation ) {
case 90 :
return [ 0 , height , height , width ] ;
case 180 :
return [ width , height , width , height ] ;
case 270 :
return [ width , 0 , height , width ] ;
default :
return [ 0 , 0 , width , height ] ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
}
# setStroke ( ) {
const {
ctx ,
color ,
opacity ,
thickness ,
parentScale ,
scaleFactor
} = this ;
ctx . lineWidth = thickness * parentScale / scaleFactor ;
ctx . lineCap = "round" ;
ctx . lineJoin = "round" ;
ctx . miterLimit = 10 ;
ctx . strokeStyle = ` ${ color } ${ opacityToHex ( opacity ) } ` ;
}
# startDrawing ( x , y ) {
this . canvas . addEventListener ( "contextmenu" , noContextMenu ) ;
this . canvas . addEventListener ( "pointerleave" , this . # boundCanvasPointerleave ) ;
this . canvas . addEventListener ( "pointermove" , this . # boundCanvasPointermove ) ;
this . canvas . addEventListener ( "pointerup" , this . # boundCanvasPointerup ) ;
this . canvas . removeEventListener ( "pointerdown" , this . # boundCanvasPointerdown ) ;
this . isEditing = true ;
if ( ! this . # isCanvasInitialized ) {
this . # isCanvasInitialized = true ;
this . # setCanvasDims ( ) ;
this . thickness || = InkEditor . _defaultThickness ;
this . color || = InkEditor . _defaultColor || AnnotationEditor . _defaultLineColor ;
this . opacity ? ? = InkEditor . _defaultOpacity ;
}
this . currentPath . push ( [ x , y ] ) ;
this . # hasSomethingToDraw = false ;
this . # setStroke ( ) ;
this . # requestFrameCallback = ( ) => {
this . # drawPoints ( ) ;
if ( this . # requestFrameCallback ) {
window . requestAnimationFrame ( this . # requestFrameCallback ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
} ;
window . requestAnimationFrame ( this . # requestFrameCallback ) ;
}
# draw ( x , y ) {
const [ lastX , lastY ] = this . currentPath . at ( - 1 ) ;
if ( this . currentPath . length > 1 && x === lastX && y === lastY ) {
return ;
}
const currentPath = this . currentPath ;
let path2D = this . # currentPath2D ;
currentPath . push ( [ x , y ] ) ;
this . # hasSomethingToDraw = true ;
if ( currentPath . length <= 2 ) {
path2D . moveTo ( ... currentPath [ 0 ] ) ;
path2D . lineTo ( x , y ) ;
return ;
}
if ( currentPath . length === 3 ) {
this . # currentPath2D = path2D = new Path2D ( ) ;
path2D . moveTo ( ... currentPath [ 0 ] ) ;
}
this . # makeBezierCurve ( path2D , ... currentPath . at ( - 3 ) , ... currentPath . at ( - 2 ) , x , y ) ;
}
# endPath ( ) {
if ( this . currentPath . length === 0 ) {
return ;
}
const lastPoint = this . currentPath . at ( - 1 ) ;
this . # currentPath2D . lineTo ( ... lastPoint ) ;
}
# stopDrawing ( x , y ) {
this . # requestFrameCallback = null ;
x = Math . min ( Math . max ( x , 0 ) , this . canvas . width ) ;
y = Math . min ( Math . max ( y , 0 ) , this . canvas . height ) ;
this . # draw ( x , y ) ;
this . # endPath ( ) ;
let bezier ;
if ( this . currentPath . length !== 1 ) {
bezier = this . # generateBezierPoints ( ) ;
} else {
const xy = [ x , y ] ;
bezier = [ [ xy , xy . slice ( ) , xy . slice ( ) , xy ] ] ;
}
const path2D = this . # currentPath2D ;
const currentPath = this . currentPath ;
this . currentPath = [ ] ;
this . # currentPath2D = new Path2D ( ) ;
const cmd = ( ) => {
this . allRawPaths . push ( currentPath ) ;
this . paths . push ( bezier ) ;
this . bezierPath2D . push ( path2D ) ;
this . _uiManager . rebuild ( this ) ;
} ;
const undo = ( ) => {
this . allRawPaths . pop ( ) ;
this . paths . pop ( ) ;
this . bezierPath2D . pop ( ) ;
if ( this . paths . length === 0 ) {
this . remove ( ) ;
} else {
if ( ! this . canvas ) {
this . # createCanvas ( ) ;
this . # createObserver ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
this . # fitToContent ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
} ;
this . addCommands ( {
cmd ,
undo ,
mustExec : true
} ) ;
}
# drawPoints ( ) {
if ( ! this . # hasSomethingToDraw ) {
return ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
this . # hasSomethingToDraw = false ;
const thickness = Math . ceil ( this . thickness * this . parentScale ) ;
const lastPoints = this . currentPath . slice ( - 3 ) ;
const x = lastPoints . map ( xy => xy [ 0 ] ) ;
const y = lastPoints . map ( xy => xy [ 1 ] ) ;
const xMin = Math . min ( ... x ) - thickness ;
const xMax = Math . max ( ... x ) + thickness ;
const yMin = Math . min ( ... y ) - thickness ;
const yMax = Math . max ( ... y ) + thickness ;
const {
ctx
} = this ;
ctx . save ( ) ;
ctx . clearRect ( 0 , 0 , this . canvas . width , this . canvas . height ) ;
for ( const path of this . bezierPath2D ) {
ctx . stroke ( path ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
ctx . stroke ( this . # currentPath2D ) ;
ctx . restore ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
# makeBezierCurve ( path2D , x0 , y0 , x1 , y1 , x2 , y2 ) {
const prevX = ( x0 + x1 ) / 2 ;
const prevY = ( y0 + y1 ) / 2 ;
const x3 = ( x1 + x2 ) / 2 ;
const y3 = ( y1 + y2 ) / 2 ;
path2D . bezierCurveTo ( prevX + 2 * ( x1 - prevX ) / 3 , prevY + 2 * ( y1 - prevY ) / 3 , x3 + 2 * ( x1 - x3 ) / 3 , y3 + 2 * ( y1 - y3 ) / 3 , x3 , y3 ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
# generateBezierPoints ( ) {
const path = this . currentPath ;
if ( path . length <= 2 ) {
return [ [ path [ 0 ] , path [ 0 ] , path . at ( - 1 ) , path . at ( - 1 ) ] ] ;
}
const bezierPoints = [ ] ;
let i ;
let [ x0 , y0 ] = path [ 0 ] ;
for ( i = 1 ; i < path . length - 2 ; i ++ ) {
const [ x1 , y1 ] = path [ i ] ;
const [ x2 , y2 ] = path [ i + 1 ] ;
const x3 = ( x1 + x2 ) / 2 ;
const y3 = ( y1 + y2 ) / 2 ;
const control1 = [ x0 + 2 * ( x1 - x0 ) / 3 , y0 + 2 * ( y1 - y0 ) / 3 ] ;
const control2 = [ x3 + 2 * ( x1 - x3 ) / 3 , y3 + 2 * ( y1 - y3 ) / 3 ] ;
bezierPoints . push ( [ [ x0 , y0 ] , control1 , control2 , [ x3 , y3 ] ] ) ;
[ x0 , y0 ] = [ x3 , y3 ] ;
}
const [ x1 , y1 ] = path [ i ] ;
const [ x2 , y2 ] = path [ i + 1 ] ;
const control1 = [ x0 + 2 * ( x1 - x0 ) / 3 , y0 + 2 * ( y1 - y0 ) / 3 ] ;
const control2 = [ x2 + 2 * ( x1 - x2 ) / 3 , y2 + 2 * ( y1 - y2 ) / 3 ] ;
bezierPoints . push ( [ [ x0 , y0 ] , control1 , control2 , [ x2 , y2 ] ] ) ;
return bezierPoints ;
}
# redraw ( ) {
if ( this . isEmpty ( ) ) {
this . # updateTransform ( ) ;
return ;
}
this . # setStroke ( ) ;
const {
canvas ,
ctx
} = this ;
ctx . setTransform ( 1 , 0 , 0 , 1 , 0 , 0 ) ;
ctx . clearRect ( 0 , 0 , canvas . width , canvas . height ) ;
this . # updateTransform ( ) ;
for ( const path of this . bezierPath2D ) {
ctx . stroke ( path ) ;
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
commit ( ) {
if ( this . # disableEditing ) {
return ;
}
super . commit ( ) ;
this . isEditing = false ;
this . disableEditMode ( ) ;
this . setInForeground ( ) ;
this . # disableEditing = true ;
this . div . classList . add ( "disabled" ) ;
this . # fitToContent ( true ) ;
this . select ( ) ;
this . parent . addInkEditorIfNeeded ( true ) ;
this . moveInDOM ( ) ;
this . div . focus ( {
preventScroll : true
2023-10-27 13:19:54 +02:00
} ) ;
}
2024-06-01 11:00:27 +01:00
focusin ( event ) {
if ( ! this . _focusEventsAllowed ) {
return ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
super . focusin ( event ) ;
this . enableEditMode ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
canvasPointerdown ( event ) {
if ( event . button !== 0 || ! this . isInEditMode ( ) || this . # disableEditing ) {
return ;
}
this . setInForeground ( ) ;
event . preventDefault ( ) ;
if ( ! this . div . contains ( document . activeElement ) ) {
this . div . focus ( {
preventScroll : true
} ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
this . # startDrawing ( event . offsetX , event . offsetY ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
canvasPointermove ( event ) {
event . preventDefault ( ) ;
this . # draw ( event . offsetX , event . offsetY ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
canvasPointerup ( event ) {
event . preventDefault ( ) ;
this . # endDrawing ( event ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
canvasPointerleave ( event ) {
this . # endDrawing ( event ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
# endDrawing ( event ) {
this . canvas . removeEventListener ( "pointerleave" , this . # boundCanvasPointerleave ) ;
this . canvas . removeEventListener ( "pointermove" , this . # boundCanvasPointermove ) ;
this . canvas . removeEventListener ( "pointerup" , this . # boundCanvasPointerup ) ;
this . canvas . addEventListener ( "pointerdown" , this . # boundCanvasPointerdown ) ;
if ( this . # canvasContextMenuTimeoutId ) {
clearTimeout ( this . # canvasContextMenuTimeoutId ) ;
}
this . # canvasContextMenuTimeoutId = setTimeout ( ( ) => {
this . # canvasContextMenuTimeoutId = null ;
this . canvas . removeEventListener ( "contextmenu" , noContextMenu ) ;
} , 10 ) ;
this . # stopDrawing ( event . offsetX , event . offsetY ) ;
this . addToAnnotationStorage ( ) ;
this . setInBackground ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
# createCanvas ( ) {
this . canvas = document . createElement ( "canvas" ) ;
this . canvas . width = this . canvas . height = 0 ;
this . canvas . className = "inkEditorCanvas" ;
this . canvas . setAttribute ( "data-l10n-id" , "pdfjs-ink-canvas" ) ;
this . div . append ( this . canvas ) ;
this . ctx = this . canvas . getContext ( "2d" ) ;
}
# createObserver ( ) {
this . # observer = new ResizeObserver ( entries => {
const rect = entries [ 0 ] . contentRect ;
if ( rect . width && rect . height ) {
this . setDimensions ( rect . width , rect . height ) ;
}
2023-10-27 13:19:54 +02:00
} ) ;
2024-06-01 11:00:27 +01:00
this . # observer . observe ( this . div ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
get isResizable ( ) {
return ! this . isEmpty ( ) && this . # disableEditing ;
}
render ( ) {
if ( this . div ) {
return this . div ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
let baseX , baseY ;
if ( this . width ) {
baseX = this . x ;
baseY = this . y ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
super . render ( ) ;
this . div . setAttribute ( "data-l10n-id" , "pdfjs-ink" ) ;
const [ x , y , w , h ] = this . # getInitialBBox ( ) ;
this . setAt ( x , y , 0 , 0 ) ;
this . setDims ( w , h ) ;
this . # createCanvas ( ) ;
if ( this . width ) {
const [ parentWidth , parentHeight ] = this . parentDimensions ;
this . setAspectRatio ( this . width * parentWidth , this . height * parentHeight ) ;
this . setAt ( baseX * parentWidth , baseY * parentHeight , this . width * parentWidth , this . height * parentHeight ) ;
this . # isCanvasInitialized = true ;
2023-10-27 13:19:54 +02:00
this . # setCanvasDims ( ) ;
2024-06-01 11:00:27 +01:00
this . setDims ( this . width * parentWidth , this . height * parentHeight ) ;
this . # redraw ( ) ;
this . div . classList . add ( "disabled" ) ;
} else {
this . div . classList . add ( "editing" ) ;
this . enableEditMode ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
this . # createObserver ( ) ;
return this . div ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
# setCanvasDims ( ) {
if ( ! this . # isCanvasInitialized ) {
2023-10-27 13:19:54 +02:00
return ;
}
const [ parentWidth , parentHeight ] = this . parentDimensions ;
2024-06-01 11:00:27 +01:00
this . canvas . width = Math . ceil ( this . width * parentWidth ) ;
this . canvas . height = Math . ceil ( this . height * parentHeight ) ;
this . # updateTransform ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
setDimensions ( width , height ) {
const roundedWidth = Math . round ( width ) ;
const roundedHeight = Math . round ( height ) ;
if ( this . # realWidth === roundedWidth && this . # realHeight === roundedHeight ) {
2023-10-27 13:19:54 +02:00
return ;
}
2024-06-01 11:00:27 +01:00
this . # realWidth = roundedWidth ;
this . # realHeight = roundedHeight ;
this . canvas . style . visibility = "hidden" ;
const [ parentWidth , parentHeight ] = this . parentDimensions ;
this . width = width / parentWidth ;
this . height = height / parentHeight ;
this . fixAndSetPosition ( ) ;
if ( this . # disableEditing ) {
this . # setScaleFactor ( width , height ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
this . # setCanvasDims ( ) ;
this . # redraw ( ) ;
this . canvas . style . visibility = "visible" ;
this . fixDims ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
# setScaleFactor ( width , height ) {
const padding = this . # getPadding ( ) ;
const scaleFactorW = ( width - padding ) / this . # baseWidth ;
const scaleFactorH = ( height - padding ) / this . # baseHeight ;
this . scaleFactor = Math . min ( scaleFactorW , scaleFactorH ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
# updateTransform ( ) {
const padding = this . # getPadding ( ) / 2 ;
this . ctx . setTransform ( this . scaleFactor , 0 , 0 , this . scaleFactor , this . translationX * this . scaleFactor + padding , this . translationY * this . scaleFactor + padding ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
static # buildPath2D ( bezier ) {
const path2D = new Path2D ( ) ;
for ( let i = 0 , ii = bezier . length ; i < ii ; i ++ ) {
const [ first , control1 , control2 , second ] = bezier [ i ] ;
if ( i === 0 ) {
path2D . moveTo ( ... first ) ;
}
path2D . bezierCurveTo ( control1 [ 0 ] , control1 [ 1 ] , control2 [ 0 ] , control2 [ 1 ] , second [ 0 ] , second [ 1 ] ) ;
}
return path2D ;
}
static # toPDFCoordinates ( points , rect , rotation ) {
const [ blX , blY , trX , trY ] = rect ;
switch ( rotation ) {
case 0 :
for ( let i = 0 , ii = points . length ; i < ii ; i += 2 ) {
points [ i ] += blX ;
points [ i + 1 ] = trY - points [ i + 1 ] ;
}
break ;
2023-10-27 13:19:54 +02:00
case 90 :
2024-06-01 11:00:27 +01:00
for ( let i = 0 , ii = points . length ; i < ii ; i += 2 ) {
const x = points [ i ] ;
points [ i ] = points [ i + 1 ] + blX ;
points [ i + 1 ] = x + blY ;
}
break ;
2023-10-27 13:19:54 +02:00
case 180 :
2024-06-01 11:00:27 +01:00
for ( let i = 0 , ii = points . length ; i < ii ; i += 2 ) {
points [ i ] = trX - points [ i ] ;
points [ i + 1 ] += blY ;
}
break ;
2023-10-27 13:19:54 +02:00
case 270 :
2024-06-01 11:00:27 +01:00
for ( let i = 0 , ii = points . length ; i < ii ; i += 2 ) {
const x = points [ i ] ;
points [ i ] = trX - points [ i + 1 ] ;
points [ i + 1 ] = trY - x ;
}
break ;
2023-10-27 13:19:54 +02:00
default :
2024-06-01 11:00:27 +01:00
throw new Error ( "Invalid rotation" ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
return points ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
static # fromPDFCoordinates ( points , rect , rotation ) {
const [ blX , blY , trX , trY ] = rect ;
switch ( rotation ) {
case 0 :
for ( let i = 0 , ii = points . length ; i < ii ; i += 2 ) {
points [ i ] -= blX ;
points [ i + 1 ] = trY - points [ i + 1 ] ;
}
break ;
case 90 :
for ( let i = 0 , ii = points . length ; i < ii ; i += 2 ) {
const x = points [ i ] ;
points [ i ] = points [ i + 1 ] - blY ;
points [ i + 1 ] = x - blX ;
}
break ;
case 180 :
for ( let i = 0 , ii = points . length ; i < ii ; i += 2 ) {
points [ i ] = trX - points [ i ] ;
points [ i + 1 ] -= blY ;
}
break ;
case 270 :
for ( let i = 0 , ii = points . length ; i < ii ; i += 2 ) {
const x = points [ i ] ;
points [ i ] = trY - points [ i + 1 ] ;
points [ i + 1 ] = trX - x ;
}
break ;
default :
throw new Error ( "Invalid rotation" ) ;
}
return points ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
# serializePaths ( s , tx , ty , rect ) {
const paths = [ ] ;
const padding = this . thickness / 2 ;
const shiftX = s * tx + padding ;
const shiftY = s * ty + padding ;
for ( const bezier of this . paths ) {
const buffer = [ ] ;
const points = [ ] ;
for ( let j = 0 , jj = bezier . length ; j < jj ; j ++ ) {
const [ first , control1 , control2 , second ] = bezier [ j ] ;
if ( first [ 0 ] === second [ 0 ] && first [ 1 ] === second [ 1 ] && jj === 1 ) {
const p0 = s * first [ 0 ] + shiftX ;
const p1 = s * first [ 1 ] + shiftY ;
buffer . push ( p0 , p1 ) ;
points . push ( p0 , p1 ) ;
break ;
}
const p10 = s * first [ 0 ] + shiftX ;
const p11 = s * first [ 1 ] + shiftY ;
const p20 = s * control1 [ 0 ] + shiftX ;
const p21 = s * control1 [ 1 ] + shiftY ;
const p30 = s * control2 [ 0 ] + shiftX ;
const p31 = s * control2 [ 1 ] + shiftY ;
const p40 = s * second [ 0 ] + shiftX ;
const p41 = s * second [ 1 ] + shiftY ;
if ( j === 0 ) {
buffer . push ( p10 , p11 ) ;
points . push ( p10 , p11 ) ;
}
buffer . push ( p20 , p21 , p30 , p31 , p40 , p41 ) ;
points . push ( p20 , p21 ) ;
if ( j === jj - 1 ) {
points . push ( p40 , p41 ) ;
}
}
paths . push ( {
bezier : InkEditor . # toPDFCoordinates ( buffer , rect , this . rotation ) ,
points : InkEditor . # toPDFCoordinates ( points , rect , this . rotation )
} ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
return paths ;
}
# getBbox ( ) {
let xMin = Infinity ;
let xMax = - Infinity ;
let yMin = Infinity ;
let yMax = - Infinity ;
for ( const path of this . paths ) {
for ( const [ first , control1 , control2 , second ] of path ) {
const bbox = Util . bezierBoundingBox ( ... first , ... control1 , ... control2 , ... second ) ;
xMin = Math . min ( xMin , bbox [ 0 ] ) ;
yMin = Math . min ( yMin , bbox [ 1 ] ) ;
xMax = Math . max ( xMax , bbox [ 2 ] ) ;
yMax = Math . max ( yMax , bbox [ 3 ] ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
}
return [ xMin , yMin , xMax , yMax ] ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
# getPadding ( ) {
return this . # disableEditing ? Math . ceil ( this . thickness * this . parentScale ) : 0 ;
}
# fitToContent ( firstTime = false ) {
if ( this . isEmpty ( ) ) {
2023-10-27 13:19:54 +02:00
return ;
}
2024-06-01 11:00:27 +01:00
if ( ! this . # disableEditing ) {
this . # redraw ( ) ;
2023-10-27 13:19:54 +02:00
return ;
}
2024-06-01 11:00:27 +01:00
const bbox = this . # getBbox ( ) ;
const padding = this . # getPadding ( ) ;
this . # baseWidth = Math . max ( AnnotationEditor . MIN _SIZE , bbox [ 2 ] - bbox [ 0 ] ) ;
this . # baseHeight = Math . max ( AnnotationEditor . MIN _SIZE , bbox [ 3 ] - bbox [ 1 ] ) ;
const width = Math . ceil ( padding + this . # baseWidth * this . scaleFactor ) ;
const height = Math . ceil ( padding + this . # baseHeight * this . scaleFactor ) ;
const [ parentWidth , parentHeight ] = this . parentDimensions ;
this . width = width / parentWidth ;
this . height = height / parentHeight ;
this . setAspectRatio ( width , height ) ;
const prevTranslationX = this . translationX ;
const prevTranslationY = this . translationY ;
this . translationX = - bbox [ 0 ] ;
this . translationY = - bbox [ 1 ] ;
this . # setCanvasDims ( ) ;
this . # redraw ( ) ;
this . # realWidth = width ;
this . # realHeight = height ;
this . setDims ( width , height ) ;
const unscaledPadding = firstTime ? padding / this . scaleFactor / 2 : 0 ;
this . translate ( prevTranslationX - this . translationX - unscaledPadding , prevTranslationY - this . translationY - unscaledPadding ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
static deserialize ( data , parent , uiManager ) {
if ( data instanceof InkAnnotationElement ) {
return null ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
const editor = super . deserialize ( data , parent , uiManager ) ;
editor . thickness = data . thickness ;
editor . color = Util . makeHexColor ( ... data . color ) ;
editor . opacity = data . opacity ;
const [ pageWidth , pageHeight ] = editor . pageDimensions ;
const width = editor . width * pageWidth ;
const height = editor . height * pageHeight ;
const scaleFactor = editor . parentScale ;
const padding = data . thickness / 2 ;
editor . # disableEditing = true ;
editor . # realWidth = Math . round ( width ) ;
editor . # realHeight = Math . round ( height ) ;
const {
paths ,
rect ,
rotation
} = data ;
for ( let {
bezier
} of paths ) {
bezier = InkEditor . # fromPDFCoordinates ( bezier , rect , rotation ) ;
const path = [ ] ;
editor . paths . push ( path ) ;
let p0 = scaleFactor * ( bezier [ 0 ] - padding ) ;
let p1 = scaleFactor * ( bezier [ 1 ] - padding ) ;
for ( let i = 2 , ii = bezier . length ; i < ii ; i += 6 ) {
const p10 = scaleFactor * ( bezier [ i ] - padding ) ;
const p11 = scaleFactor * ( bezier [ i + 1 ] - padding ) ;
const p20 = scaleFactor * ( bezier [ i + 2 ] - padding ) ;
const p21 = scaleFactor * ( bezier [ i + 3 ] - padding ) ;
const p30 = scaleFactor * ( bezier [ i + 4 ] - padding ) ;
const p31 = scaleFactor * ( bezier [ i + 5 ] - padding ) ;
path . push ( [ [ p0 , p1 ] , [ p10 , p11 ] , [ p20 , p21 ] , [ p30 , p31 ] ] ) ;
p0 = p30 ;
p1 = p31 ;
}
const path2D = this . # buildPath2D ( path ) ;
editor . bezierPath2D . push ( path2D ) ;
}
const bbox = editor . # getBbox ( ) ;
editor . # baseWidth = Math . max ( AnnotationEditor . MIN _SIZE , bbox [ 2 ] - bbox [ 0 ] ) ;
editor . # baseHeight = Math . max ( AnnotationEditor . MIN _SIZE , bbox [ 3 ] - bbox [ 1 ] ) ;
editor . # setScaleFactor ( width , height ) ;
return editor ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
serialize ( ) {
if ( this . isEmpty ( ) ) {
return null ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
const rect = this . getRect ( 0 , 0 ) ;
const color = AnnotationEditor . _colorManager . convert ( this . ctx . strokeStyle ) ;
return {
annotationType : AnnotationEditorType . INK ,
color ,
thickness : this . thickness ,
opacity : this . opacity ,
paths : this . # serializePaths ( this . scaleFactor / this . parentScale , this . translationX , this . translationY , rect ) ,
pageIndex : this . pageIndex ,
rect ,
rotation : this . rotation ,
structTreeParentId : this . _structTreeParentId
2023-10-27 13:19:54 +02:00
} ;
2024-06-01 11:00:27 +01:00
}
}
; // CONCATENATED MODULE: ./src/display/editor/stamp.js
2024-06-18 20:06:52 +02:00
2024-06-01 11:00:27 +01:00
class StampEditor extends AnnotationEditor {
# bitmap = null ;
# bitmapId = null ;
# bitmapPromise = null ;
# bitmapUrl = null ;
# bitmapFile = null ;
# bitmapFileName = "" ;
# canvas = null ;
# observer = null ;
# resizeTimeoutId = null ;
# isSvg = false ;
# hasBeenAddedInUndoStack = false ;
static _type = "stamp" ;
static _editorType = AnnotationEditorType . STAMP ;
constructor ( params ) {
super ( {
... params ,
name : "stampEditor"
2023-10-27 13:19:54 +02:00
} ) ;
2024-06-01 11:00:27 +01:00
this . # bitmapUrl = params . bitmapUrl ;
this . # bitmapFile = params . bitmapFile ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
static initialize ( l10n , uiManager ) {
AnnotationEditor . initialize ( l10n , uiManager ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
static get supportedTypes ( ) {
const types = [ "apng" , "avif" , "bmp" , "gif" , "jpeg" , "png" , "svg+xml" , "webp" , "x-icon" ] ;
return shadow ( this , "supportedTypes" , types . map ( type => ` image/ ${ type } ` ) ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
static get supportedTypesStr ( ) {
return shadow ( this , "supportedTypesStr" , this . supportedTypes . join ( "," ) ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
static isHandlingMimeForPasting ( mime ) {
return this . supportedTypes . includes ( mime ) ;
}
static paste ( item , parent ) {
parent . pasteEditor ( AnnotationEditorType . STAMP , {
bitmapFile : item . getAsFile ( )
} ) ;
}
# getBitmapFetched ( data , fromId = false ) {
if ( ! data ) {
this . remove ( ) ;
2023-10-27 13:19:54 +02:00
return ;
}
2024-06-01 11:00:27 +01:00
this . # bitmap = data . bitmap ;
if ( ! fromId ) {
this . # bitmapId = data . id ;
this . # isSvg = data . isSvg ;
}
if ( data . file ) {
this . # bitmapFileName = data . file . name ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
this . # createCanvas ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
# getBitmapDone ( ) {
this . # bitmapPromise = null ;
this . _uiManager . enableWaiting ( false ) ;
if ( this . # canvas ) {
this . div . focus ( ) ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
# getBitmap ( ) {
if ( this . # bitmapId ) {
this . _uiManager . enableWaiting ( true ) ;
this . _uiManager . imageManager . getFromId ( this . # bitmapId ) . then ( data => this . # getBitmapFetched ( data , true ) ) . finally ( ( ) => this . # getBitmapDone ( ) ) ;
2023-10-27 13:19:54 +02:00
return ;
}
2024-06-01 11:00:27 +01:00
if ( this . # bitmapUrl ) {
const url = this . # bitmapUrl ;
this . # bitmapUrl = null ;
this . _uiManager . enableWaiting ( true ) ;
this . # bitmapPromise = this . _uiManager . imageManager . getFromUrl ( url ) . then ( data => this . # getBitmapFetched ( data ) ) . finally ( ( ) => this . # getBitmapDone ( ) ) ;
2023-10-27 13:19:54 +02:00
return ;
}
2024-06-01 11:00:27 +01:00
if ( this . # bitmapFile ) {
const file = this . # bitmapFile ;
this . # bitmapFile = null ;
this . _uiManager . enableWaiting ( true ) ;
this . # bitmapPromise = this . _uiManager . imageManager . getFromFile ( file ) . then ( data => this . # getBitmapFetched ( data ) ) . finally ( ( ) => this . # getBitmapDone ( ) ) ;
return ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
const input = document . createElement ( "input" ) ;
input . type = "file" ;
input . accept = StampEditor . supportedTypesStr ;
this . # bitmapPromise = new Promise ( resolve => {
input . addEventListener ( "change" , async ( ) => {
if ( ! input . files || input . files . length === 0 ) {
this . remove ( ) ;
} else {
this . _uiManager . enableWaiting ( true ) ;
const data = await this . _uiManager . imageManager . getFromFile ( input . files [ 0 ] ) ;
this . # getBitmapFetched ( data ) ;
}
resolve ( ) ;
} ) ;
input . addEventListener ( "cancel" , ( ) => {
this . remove ( ) ;
resolve ( ) ;
} ) ;
} ) . finally ( ( ) => this . # getBitmapDone ( ) ) ;
input . click ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
remove ( ) {
if ( this . # bitmapId ) {
this . # bitmap = null ;
this . _uiManager . imageManager . deleteId ( this . # bitmapId ) ;
this . # canvas ? . remove ( ) ;
this . # canvas = null ;
this . # observer ? . disconnect ( ) ;
this . # observer = null ;
if ( this . # resizeTimeoutId ) {
clearTimeout ( this . # resizeTimeoutId ) ;
this . # resizeTimeoutId = null ;
}
}
super . remove ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
rebuild ( ) {
if ( ! this . parent ) {
if ( this . # bitmapId ) {
this . # getBitmap ( ) ;
}
return ;
}
super . rebuild ( ) ;
if ( this . div === null ) {
return ;
}
if ( this . # bitmapId && this . # canvas === null ) {
this . # getBitmap ( ) ;
}
if ( ! this . isAttachedToDOM ) {
this . parent . add ( this ) ;
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
onceAdded ( ) {
this . _isDraggable = true ;
this . div . focus ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
isEmpty ( ) {
return ! ( this . # bitmapPromise || this . # bitmap || this . # bitmapUrl || this . # bitmapFile || this . # bitmapId ) ;
2023-10-27 13:19:54 +02:00
}
get isResizable ( ) {
2024-06-01 11:00:27 +01:00
return true ;
2023-10-27 13:19:54 +02:00
}
render ( ) {
if ( this . div ) {
return this . div ;
}
let baseX , baseY ;
if ( this . width ) {
baseX = this . x ;
baseY = this . y ;
}
super . render ( ) ;
2024-06-01 11:00:27 +01:00
this . div . hidden = true ;
this . addAltTextButton ( ) ;
if ( this . # bitmap ) {
this . # createCanvas ( ) ;
} else {
this . # getBitmap ( ) ;
}
2023-10-27 13:19:54 +02:00
if ( this . width ) {
const [ parentWidth , parentHeight ] = this . parentDimensions ;
this . setAt ( baseX * parentWidth , baseY * parentHeight , this . width * parentWidth , this . height * parentHeight ) ;
}
return this . div ;
}
2024-06-01 11:00:27 +01:00
# createCanvas ( ) {
const {
div
} = this ;
let {
width ,
height
} = this . # bitmap ;
const [ pageWidth , pageHeight ] = this . pageDimensions ;
const MAX _RATIO = 0.75 ;
if ( this . width ) {
width = this . width * pageWidth ;
height = this . height * pageHeight ;
} else if ( width > MAX _RATIO * pageWidth || height > MAX _RATIO * pageHeight ) {
const factor = Math . min ( MAX _RATIO * pageWidth / width , MAX _RATIO * pageHeight / height ) ;
width *= factor ;
height *= factor ;
2023-10-27 13:19:54 +02:00
}
const [ parentWidth , parentHeight ] = this . parentDimensions ;
2024-06-01 11:00:27 +01:00
this . setDims ( width * parentWidth / pageWidth , height * parentHeight / pageHeight ) ;
this . _uiManager . enableWaiting ( false ) ;
const canvas = this . # canvas = document . createElement ( "canvas" ) ;
div . append ( canvas ) ;
div . hidden = false ;
this . # drawBitmap ( width , height ) ;
this . # createObserver ( ) ;
if ( ! this . # hasBeenAddedInUndoStack ) {
this . parent . addUndoableEditor ( this ) ;
this . # hasBeenAddedInUndoStack = true ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
this . _reportTelemetry ( {
action : "inserted_image"
} ) ;
if ( this . # bitmapFileName ) {
canvas . setAttribute ( "aria-label" , this . # bitmapFileName ) ;
}
}
# setDimensions ( width , height ) {
2023-10-27 13:19:54 +02:00
const [ parentWidth , parentHeight ] = this . parentDimensions ;
this . width = width / parentWidth ;
this . height = height / parentHeight ;
2024-06-01 11:00:27 +01:00
this . setDims ( width , height ) ;
if ( this . _initialOptions ? . isCentered ) {
this . center ( ) ;
} else {
this . fixAndSetPosition ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
this . _initialOptions = null ;
if ( this . # resizeTimeoutId !== null ) {
clearTimeout ( this . # resizeTimeoutId ) ;
}
const TIME _TO _WAIT = 200 ;
this . # resizeTimeoutId = setTimeout ( ( ) => {
this . # resizeTimeoutId = null ;
this . # drawBitmap ( width , height ) ;
} , TIME _TO _WAIT ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
# scaleBitmap ( width , height ) {
const {
width : bitmapWidth ,
height : bitmapHeight
} = this . # bitmap ;
let newWidth = bitmapWidth ;
let newHeight = bitmapHeight ;
let bitmap = this . # bitmap ;
while ( newWidth > 2 * width || newHeight > 2 * height ) {
const prevWidth = newWidth ;
const prevHeight = newHeight ;
if ( newWidth > 2 * width ) {
newWidth = newWidth >= 16384 ? Math . floor ( newWidth / 2 ) - 1 : Math . ceil ( newWidth / 2 ) ;
}
if ( newHeight > 2 * height ) {
newHeight = newHeight >= 16384 ? Math . floor ( newHeight / 2 ) - 1 : Math . ceil ( newHeight / 2 ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
const offscreen = new OffscreenCanvas ( newWidth , newHeight ) ;
const ctx = offscreen . getContext ( "2d" ) ;
ctx . drawImage ( bitmap , 0 , 0 , prevWidth , prevHeight , 0 , 0 , newWidth , newHeight ) ;
bitmap = offscreen . transferToImageBitmap ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
return bitmap ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
# drawBitmap ( width , height ) {
width = Math . ceil ( width ) ;
height = Math . ceil ( height ) ;
const canvas = this . # canvas ;
if ( ! canvas || canvas . width === width && canvas . height === height ) {
return ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
canvas . width = width ;
canvas . height = height ;
const bitmap = this . # isSvg ? this . # bitmap : this . # scaleBitmap ( width , height ) ;
if ( this . _uiManager . hasMLManager && ! this . hasAltText ( ) ) {
const offscreen = new OffscreenCanvas ( width , height ) ;
const ctx = offscreen . getContext ( "2d" ) ;
ctx . drawImage ( bitmap , 0 , 0 , bitmap . width , bitmap . height , 0 , 0 , width , height ) ;
this . _uiManager . mlGuess ( {
service : "image-to-text" ,
request : {
data : ctx . getImageData ( 0 , 0 , width , height ) . data ,
width ,
height ,
channels : 4
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
} ) . then ( response => {
const altText = response ? . output || "" ;
if ( this . parent && altText && ! this . hasAltText ( ) ) {
this . altTextData = {
altText ,
decorative : false
} ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
} ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
const ctx = canvas . getContext ( "2d" ) ;
ctx . filter = this . _uiManager . hcmFilter ;
ctx . drawImage ( bitmap , 0 , 0 , bitmap . width , bitmap . height , 0 , 0 , width , height ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
getImageForAltText ( ) {
return this . # canvas ;
}
# serializeBitmap ( toUrl ) {
if ( toUrl ) {
if ( this . # isSvg ) {
const url = this . _uiManager . imageManager . getSvgUrl ( this . # bitmapId ) ;
if ( url ) {
return url ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
const canvas = document . createElement ( "canvas" ) ;
( {
width : canvas . width ,
height : canvas . height
} = this . # bitmap ) ;
const ctx = canvas . getContext ( "2d" ) ;
ctx . drawImage ( this . # bitmap , 0 , 0 ) ;
return canvas . toDataURL ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
if ( this . # isSvg ) {
const [ pageWidth , pageHeight ] = this . pageDimensions ;
const width = Math . round ( this . width * pageWidth * PixelsPerInch . PDF _TO _CSS _UNITS ) ;
const height = Math . round ( this . height * pageHeight * PixelsPerInch . PDF _TO _CSS _UNITS ) ;
const offscreen = new OffscreenCanvas ( width , height ) ;
const ctx = offscreen . getContext ( "2d" ) ;
ctx . drawImage ( this . # bitmap , 0 , 0 , this . # bitmap . width , this . # bitmap . height , 0 , 0 , width , height ) ;
return offscreen . transferToImageBitmap ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
return structuredClone ( this . # bitmap ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
# createObserver ( ) {
this . # observer = new ResizeObserver ( entries => {
const rect = entries [ 0 ] . contentRect ;
if ( rect . width && rect . height ) {
this . # setDimensions ( rect . width , rect . height ) ;
}
} ) ;
this . # observer . observe ( this . div ) ;
2023-10-27 13:19:54 +02:00
}
static deserialize ( data , parent , uiManager ) {
2024-06-01 11:00:27 +01:00
if ( data instanceof StampAnnotationElement ) {
2023-10-27 13:19:54 +02:00
return null ;
}
const editor = super . deserialize ( data , parent , uiManager ) ;
const {
rect ,
2024-06-01 11:00:27 +01:00
bitmapUrl ,
bitmapId ,
isSvg ,
accessibilityData
2023-10-27 13:19:54 +02:00
} = data ;
2024-06-01 11:00:27 +01:00
if ( bitmapId && uiManager . imageManager . isValidId ( bitmapId ) ) {
editor . # bitmapId = bitmapId ;
} else {
editor . # bitmapUrl = bitmapUrl ;
}
editor . # isSvg = isSvg ;
const [ parentWidth , parentHeight ] = editor . pageDimensions ;
editor . width = ( rect [ 2 ] - rect [ 0 ] ) / parentWidth ;
editor . height = ( rect [ 3 ] - rect [ 1 ] ) / parentHeight ;
if ( accessibilityData ) {
editor . altTextData = accessibilityData ;
2023-10-27 13:19:54 +02:00
}
return editor ;
}
2024-06-01 11:00:27 +01:00
serialize ( isForCopying = false , context = null ) {
2023-10-27 13:19:54 +02:00
if ( this . isEmpty ( ) ) {
return null ;
}
2024-06-01 11:00:27 +01:00
const serialized = {
annotationType : AnnotationEditorType . STAMP ,
bitmapId : this . # bitmapId ,
2023-10-27 13:19:54 +02:00
pageIndex : this . pageIndex ,
2024-06-01 11:00:27 +01:00
rect : this . getRect ( 0 , 0 ) ,
2023-10-27 13:19:54 +02:00
rotation : this . rotation ,
2024-06-01 11:00:27 +01:00
isSvg : this . # isSvg ,
2023-10-27 13:19:54 +02:00
structTreeParentId : this . _structTreeParentId
} ;
2024-06-01 11:00:27 +01:00
if ( isForCopying ) {
serialized . bitmapUrl = this . # serializeBitmap ( true ) ;
serialized . accessibilityData = this . altTextData ;
return serialized ;
}
const {
decorative ,
altText
} = this . altTextData ;
if ( ! decorative && altText ) {
serialized . accessibilityData = {
type : "Figure" ,
alt : altText
} ;
}
if ( context === null ) {
return serialized ;
}
context . stamps || = new Map ( ) ;
const area = this . # isSvg ? ( serialized . rect [ 2 ] - serialized . rect [ 0 ] ) * ( serialized . rect [ 3 ] - serialized . rect [ 1 ] ) : null ;
if ( ! context . stamps . has ( this . # bitmapId ) ) {
context . stamps . set ( this . # bitmapId , {
area ,
serialized
} ) ;
serialized . bitmap = this . # serializeBitmap ( false ) ;
} else if ( this . # isSvg ) {
const prevData = context . stamps . get ( this . # bitmapId ) ;
if ( area > prevData . area ) {
prevData . area = area ;
prevData . serialized . bitmap . close ( ) ;
prevData . serialized . bitmap = this . # serializeBitmap ( false ) ;
}
}
return serialized ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
; // CONCATENATED MODULE: ./src/display/editor/annotation_editor_layer.js
2023-10-27 13:19:54 +02:00
2024-06-01 11:00:27 +01:00
2024-06-18 20:06:52 +02:00
2024-06-01 11:00:27 +01:00
class AnnotationEditorLayer {
# accessibilityManager ;
# allowClick = false ;
# annotationLayer = null ;
# boundPointerup = null ;
# boundPointerdown = null ;
# boundTextLayerPointerDown = null ;
# editorFocusTimeoutId = null ;
# editors = new Map ( ) ;
# hadPointerDown = false ;
# isCleaningUp = false ;
# isDisabling = false ;
# textLayer = null ;
# uiManager ;
static _initialized = false ;
static # editorTypes = new Map ( [ FreeTextEditor , InkEditor , StampEditor , HighlightEditor ] . map ( type => [ type . _editorType , type ] ) ) ;
constructor ( {
uiManager ,
pageIndex ,
div ,
accessibilityManager ,
annotationLayer ,
drawLayer ,
textLayer ,
viewport ,
l10n
} ) {
const editorTypes = [ ... AnnotationEditorLayer . # editorTypes . values ( ) ] ;
if ( ! AnnotationEditorLayer . _initialized ) {
AnnotationEditorLayer . _initialized = true ;
for ( const editorType of editorTypes ) {
editorType . initialize ( l10n , uiManager ) ;
}
}
uiManager . registerEditorTypes ( editorTypes ) ;
this . # uiManager = uiManager ;
this . pageIndex = pageIndex ;
this . div = div ;
this . # accessibilityManager = accessibilityManager ;
this . # annotationLayer = annotationLayer ;
this . viewport = viewport ;
this . # textLayer = textLayer ;
this . drawLayer = drawLayer ;
this . # uiManager . addLayer ( this ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
get isEmpty ( ) {
return this . # editors . size === 0 ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
get isInvisible ( ) {
return this . isEmpty && this . # uiManager . getMode ( ) === AnnotationEditorType . NONE ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
updateToolbar ( mode ) {
this . # uiManager . updateToolbar ( mode ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
updateMode ( mode = this . # uiManager . getMode ( ) ) {
this . # cleanup ( ) ;
switch ( mode ) {
case AnnotationEditorType . NONE :
this . disableTextSelection ( ) ;
this . togglePointerEvents ( false ) ;
this . toggleAnnotationLayerPointerEvents ( true ) ;
this . disableClick ( ) ;
return ;
case AnnotationEditorType . INK :
this . addInkEditorIfNeeded ( false ) ;
this . disableTextSelection ( ) ;
this . togglePointerEvents ( true ) ;
this . disableClick ( ) ;
break ;
case AnnotationEditorType . HIGHLIGHT :
this . enableTextSelection ( ) ;
this . togglePointerEvents ( false ) ;
this . disableClick ( ) ;
break ;
default :
this . disableTextSelection ( ) ;
this . togglePointerEvents ( true ) ;
this . enableClick ( ) ;
}
this . toggleAnnotationLayerPointerEvents ( false ) ;
const {
classList
} = this . div ;
for ( const editorType of AnnotationEditorLayer . # editorTypes . values ( ) ) {
classList . toggle ( ` ${ editorType . _type } Editing ` , mode === editorType . _editorType ) ;
}
this . div . hidden = false ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
hasTextLayer ( textLayer ) {
return textLayer === this . # textLayer ? . div ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
addInkEditorIfNeeded ( isCommitting ) {
if ( this . # uiManager . getMode ( ) !== AnnotationEditorType . INK ) {
2023-10-27 13:19:54 +02:00
return ;
}
2024-06-01 11:00:27 +01:00
if ( ! isCommitting ) {
for ( const editor of this . # editors . values ( ) ) {
if ( editor . isEmpty ( ) ) {
editor . setInBackground ( ) ;
return ;
}
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
const editor = this . createAndAddNewEditor ( {
offsetX : 0 ,
offsetY : 0
} , false ) ;
editor . setInBackground ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
setEditingState ( isEditing ) {
this . # uiManager . setEditingState ( isEditing ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
addCommands ( params ) {
this . # uiManager . addCommands ( params ) ;
}
togglePointerEvents ( enabled = false ) {
this . div . classList . toggle ( "disabled" , ! enabled ) ;
}
toggleAnnotationLayerPointerEvents ( enabled = false ) {
this . # annotationLayer ? . div . classList . toggle ( "disabled" , ! enabled ) ;
}
enable ( ) {
this . div . tabIndex = 0 ;
this . togglePointerEvents ( true ) ;
const annotationElementIds = new Set ( ) ;
for ( const editor of this . # editors . values ( ) ) {
editor . enableEditing ( ) ;
editor . show ( true ) ;
if ( editor . annotationElementId ) {
this . # uiManager . removeChangedExistingAnnotation ( editor ) ;
annotationElementIds . add ( editor . annotationElementId ) ;
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
if ( ! this . # annotationLayer ) {
2023-10-27 13:19:54 +02:00
return ;
}
2024-06-01 11:00:27 +01:00
const editables = this . # annotationLayer . getEditableAnnotations ( ) ;
for ( const editable of editables ) {
editable . hide ( ) ;
if ( this . # uiManager . isDeletedAnnotationElement ( editable . data . id ) ) {
continue ;
}
if ( annotationElementIds . has ( editable . data . id ) ) {
continue ;
}
const editor = this . deserialize ( editable ) ;
if ( ! editor ) {
continue ;
}
this . addOrRebuild ( editor ) ;
editor . enableEditing ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
}
disable ( ) {
this . # isDisabling = true ;
this . div . tabIndex = - 1 ;
this . togglePointerEvents ( false ) ;
const changedAnnotations = new Map ( ) ;
const resetAnnotations = new Map ( ) ;
for ( const editor of this . # editors . values ( ) ) {
editor . disableEditing ( ) ;
if ( ! editor . annotationElementId ) {
continue ;
}
if ( editor . serialize ( ) !== null ) {
changedAnnotations . set ( editor . annotationElementId , editor ) ;
continue ;
} else {
resetAnnotations . set ( editor . annotationElementId , editor ) ;
}
this . getEditableAnnotation ( editor . annotationElementId ) ? . show ( ) ;
editor . remove ( ) ;
}
if ( this . # annotationLayer ) {
const editables = this . # annotationLayer . getEditableAnnotations ( ) ;
for ( const editable of editables ) {
const {
id
} = editable . data ;
if ( this . # uiManager . isDeletedAnnotationElement ( id ) ) {
continue ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
let editor = resetAnnotations . get ( id ) ;
if ( editor ) {
editor . resetAnnotationElement ( editable ) ;
editor . show ( false ) ;
editable . show ( ) ;
continue ;
}
editor = changedAnnotations . get ( id ) ;
if ( editor ) {
this . # uiManager . addChangedExistingAnnotation ( editor ) ;
editor . renderAnnotationElement ( editable ) ;
editor . show ( false ) ;
}
editable . show ( ) ;
}
}
this . # cleanup ( ) ;
if ( this . isEmpty ) {
this . div . hidden = true ;
}
const {
classList
} = this . div ;
for ( const editorType of AnnotationEditorLayer . # editorTypes . values ( ) ) {
classList . remove ( ` ${ editorType . _type } Editing ` ) ;
}
this . disableTextSelection ( ) ;
this . toggleAnnotationLayerPointerEvents ( true ) ;
this . # isDisabling = false ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
getEditableAnnotation ( id ) {
return this . # annotationLayer ? . getEditableAnnotation ( id ) || null ;
}
setActiveEditor ( editor ) {
const currentActive = this . # uiManager . getActive ( ) ;
if ( currentActive === editor ) {
return ;
}
this . # uiManager . setActiveEditor ( editor ) ;
}
enableTextSelection ( ) {
this . div . tabIndex = - 1 ;
if ( this . # textLayer ? . div && ! this . # boundTextLayerPointerDown ) {
this . # boundTextLayerPointerDown = this . # textLayerPointerDown . bind ( this ) ;
this . # textLayer . div . addEventListener ( "pointerdown" , this . # boundTextLayerPointerDown ) ;
this . # textLayer . div . classList . add ( "highlighting" ) ;
}
}
disableTextSelection ( ) {
this . div . tabIndex = 0 ;
if ( this . # textLayer ? . div && this . # boundTextLayerPointerDown ) {
this . # textLayer . div . removeEventListener ( "pointerdown" , this . # boundTextLayerPointerDown ) ;
this . # boundTextLayerPointerDown = null ;
this . # textLayer . div . classList . remove ( "highlighting" ) ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
# textLayerPointerDown ( event ) {
this . # uiManager . unselectAll ( ) ;
if ( event . target === this . # textLayer . div ) {
const {
isMac
} = util _FeatureTest . platform ;
if ( event . button !== 0 || event . ctrlKey && isMac ) {
return ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
this . # uiManager . showAllEditors ( "highlight" , true , true ) ;
this . # textLayer . div . classList . add ( "free" ) ;
HighlightEditor . startHighlighting ( this , this . # uiManager . direction === "ltr" , event ) ;
this . # textLayer . div . addEventListener ( "pointerup" , ( ) => {
this . # textLayer . div . classList . remove ( "free" ) ;
} , {
once : true
} ) ;
event . preventDefault ( ) ;
}
}
enableClick ( ) {
if ( this . # boundPointerdown ) {
2023-10-27 13:19:54 +02:00
return ;
}
2024-06-01 11:00:27 +01:00
this . # boundPointerdown = this . pointerdown . bind ( this ) ;
this . # boundPointerup = this . pointerup . bind ( this ) ;
this . div . addEventListener ( "pointerdown" , this . # boundPointerdown ) ;
this . div . addEventListener ( "pointerup" , this . # boundPointerup ) ;
}
disableClick ( ) {
if ( ! this . # boundPointerdown ) {
2023-10-27 13:19:54 +02:00
return ;
}
2024-06-01 11:00:27 +01:00
this . div . removeEventListener ( "pointerdown" , this . # boundPointerdown ) ;
this . div . removeEventListener ( "pointerup" , this . # boundPointerup ) ;
this . # boundPointerdown = null ;
this . # boundPointerup = null ;
}
attach ( editor ) {
this . # editors . set ( editor . id , editor ) ;
const {
annotationElementId
} = editor ;
if ( annotationElementId && this . # uiManager . isDeletedAnnotationElement ( annotationElementId ) ) {
this . # uiManager . removeDeletedAnnotationElement ( editor ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
}
detach ( editor ) {
this . # editors . delete ( editor . id ) ;
this . # accessibilityManager ? . removePointerInTextLayer ( editor . contentDiv ) ;
if ( ! this . # isDisabling && editor . annotationElementId ) {
this . # uiManager . addDeletedAnnotationElement ( editor ) ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
remove ( editor ) {
this . detach ( editor ) ;
this . # uiManager . removeEditor ( editor ) ;
editor . div . remove ( ) ;
editor . isAttachedToDOM = false ;
if ( ! this . # isCleaningUp ) {
this . addInkEditorIfNeeded ( false ) ;
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
changeParent ( editor ) {
if ( editor . parent === this ) {
return ;
}
if ( editor . parent && editor . annotationElementId ) {
this . # uiManager . addDeletedAnnotationElement ( editor . annotationElementId ) ;
AnnotationEditor . deleteAnnotationElement ( editor ) ;
editor . annotationElementId = null ;
}
this . attach ( editor ) ;
editor . parent ? . detach ( editor ) ;
editor . setParent ( this ) ;
if ( editor . div && editor . isAttachedToDOM ) {
editor . div . remove ( ) ;
this . div . append ( editor . div ) ;
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
add ( editor ) {
if ( editor . parent === this && editor . isAttachedToDOM ) {
return ;
}
this . changeParent ( editor ) ;
this . # uiManager . addEditor ( editor ) ;
this . attach ( editor ) ;
if ( ! editor . isAttachedToDOM ) {
const div = editor . render ( ) ;
this . div . append ( div ) ;
editor . isAttachedToDOM = true ;
}
editor . fixAndSetPosition ( ) ;
editor . onceAdded ( ) ;
this . # uiManager . addToAnnotationStorage ( editor ) ;
editor . _reportTelemetry ( editor . telemetryInitialData ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
moveEditorInDOM ( editor ) {
if ( ! editor . isAttachedToDOM ) {
return ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
const {
activeElement
} = document ;
if ( editor . div . contains ( activeElement ) && ! this . # editorFocusTimeoutId ) {
editor . _focusEventsAllowed = false ;
this . # editorFocusTimeoutId = setTimeout ( ( ) => {
this . # editorFocusTimeoutId = null ;
if ( ! editor . div . contains ( document . activeElement ) ) {
editor . div . addEventListener ( "focusin" , ( ) => {
editor . _focusEventsAllowed = true ;
} , {
once : true
} ) ;
activeElement . focus ( ) ;
} else {
editor . _focusEventsAllowed = true ;
}
} , 0 ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
editor . _structTreeParentId = this . # accessibilityManager ? . moveElementInDOM ( this . div , editor . div , editor . contentDiv , true ) ;
}
addOrRebuild ( editor ) {
if ( editor . needsToBeRebuilt ( ) ) {
editor . parent || = this ;
editor . rebuild ( ) ;
editor . show ( ) ;
2023-10-27 13:19:54 +02:00
} else {
2024-06-01 11:00:27 +01:00
this . add ( editor ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
}
addUndoableEditor ( editor ) {
const cmd = ( ) => editor . _uiManager . rebuild ( editor ) ;
const undo = ( ) => {
editor . remove ( ) ;
} ;
this . addCommands ( {
cmd ,
undo ,
mustExec : false
} ) ;
}
getNextId ( ) {
return this . # uiManager . getId ( ) ;
}
get # currentEditorType ( ) {
return AnnotationEditorLayer . # editorTypes . get ( this . # uiManager . getMode ( ) ) ;
}
# createNewEditor ( params ) {
const editorType = this . # currentEditorType ;
return editorType ? new editorType . prototype . constructor ( params ) : null ;
}
canCreateNewEmptyEditor ( ) {
return this . # currentEditorType ? . canCreateNewEmptyEditor ( ) ;
}
pasteEditor ( mode , params ) {
this . # uiManager . updateToolbar ( mode ) ;
this . # uiManager . updateMode ( mode ) ;
const {
offsetX ,
offsetY
} = this . # getCenterPoint ( ) ;
const id = this . getNextId ( ) ;
const editor = this . # createNewEditor ( {
parent : this ,
id ,
x : offsetX ,
y : offsetY ,
uiManager : this . # uiManager ,
isCentered : true ,
... params
} ) ;
if ( editor ) {
this . add ( editor ) ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
deserialize ( data ) {
return AnnotationEditorLayer . # editorTypes . get ( data . annotationType ? ? data . annotationEditorType ) ? . deserialize ( data , this , this . # uiManager ) || null ;
}
createAndAddNewEditor ( event , isCentered , data = { } ) {
const id = this . getNextId ( ) ;
const editor = this . # createNewEditor ( {
parent : this ,
id ,
x : event . offsetX ,
y : event . offsetY ,
uiManager : this . # uiManager ,
isCentered ,
... data
} ) ;
if ( editor ) {
this . add ( editor ) ;
}
return editor ;
}
# getCenterPoint ( ) {
2023-10-27 13:19:54 +02:00
const {
2024-06-01 11:00:27 +01:00
x ,
y ,
2023-10-27 13:19:54 +02:00
width ,
height
2024-06-01 11:00:27 +01:00
} = this . div . getBoundingClientRect ( ) ;
const tlX = Math . max ( 0 , x ) ;
const tlY = Math . max ( 0 , y ) ;
const brX = Math . min ( window . innerWidth , x + width ) ;
const brY = Math . min ( window . innerHeight , y + height ) ;
const centerX = ( tlX + brX ) / 2 - x ;
const centerY = ( tlY + brY ) / 2 - y ;
const [ offsetX , offsetY ] = this . viewport . rotation % 180 === 0 ? [ centerX , centerY ] : [ centerY , centerX ] ;
return {
offsetX ,
offsetY
} ;
}
addNewEditor ( ) {
this . createAndAddNewEditor ( this . # getCenterPoint ( ) , true ) ;
}
setSelected ( editor ) {
this . # uiManager . setSelected ( editor ) ;
}
toggleSelected ( editor ) {
this . # uiManager . toggleSelected ( editor ) ;
}
isSelected ( editor ) {
return this . # uiManager . isSelected ( editor ) ;
}
unselect ( editor ) {
this . # uiManager . unselect ( editor ) ;
}
pointerup ( event ) {
const {
isMac
} = util _FeatureTest . platform ;
if ( event . button !== 0 || event . ctrlKey && isMac ) {
return ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
if ( event . target !== this . div ) {
return ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
if ( ! this . # hadPointerDown ) {
return ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
this . # hadPointerDown = false ;
if ( ! this . # allowClick ) {
this . # allowClick = true ;
return ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
if ( this . # uiManager . getMode ( ) === AnnotationEditorType . STAMP ) {
this . # uiManager . unselectAll ( ) ;
return ;
}
this . createAndAddNewEditor ( event , false ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
pointerdown ( event ) {
if ( this . # uiManager . getMode ( ) === AnnotationEditorType . HIGHLIGHT ) {
this . enableTextSelection ( ) ;
}
if ( this . # hadPointerDown ) {
this . # hadPointerDown = false ;
return ;
}
2023-10-27 13:19:54 +02:00
const {
2024-06-01 11:00:27 +01:00
isMac
} = util _FeatureTest . platform ;
if ( event . button !== 0 || event . ctrlKey && isMac ) {
return ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
if ( event . target !== this . div ) {
2023-10-27 13:19:54 +02:00
return ;
}
2024-06-01 11:00:27 +01:00
this . # hadPointerDown = true ;
const editor = this . # uiManager . getActive ( ) ;
this . # allowClick = ! editor || editor . isEmpty ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
findNewParent ( editor , x , y ) {
const layer = this . # uiManager . findParent ( x , y ) ;
if ( layer === null || layer === this ) {
return false ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
layer . changeParent ( editor ) ;
return true ;
}
destroy ( ) {
if ( this . # uiManager . getActive ( ) ? . parent === this ) {
this . # uiManager . commitOrRemove ( ) ;
this . # uiManager . setActiveEditor ( null ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
if ( this . # editorFocusTimeoutId ) {
clearTimeout ( this . # editorFocusTimeoutId ) ;
this . # editorFocusTimeoutId = null ;
}
for ( const editor of this . # editors . values ( ) ) {
this . # accessibilityManager ? . removePointerInTextLayer ( editor . contentDiv ) ;
editor . setParent ( null ) ;
editor . isAttachedToDOM = false ;
editor . div . remove ( ) ;
}
this . div = null ;
this . # editors . clear ( ) ;
this . # uiManager . removeLayer ( this ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
# cleanup ( ) {
this . # isCleaningUp = true ;
for ( const editor of this . # editors . values ( ) ) {
if ( editor . isEmpty ( ) ) {
editor . remove ( ) ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
this . # isCleaningUp = false ;
}
render ( {
viewport
} ) {
this . viewport = viewport ;
setLayerDimensions ( this . div , viewport ) ;
for ( const editor of this . # uiManager . getEditors ( this . pageIndex ) ) {
this . add ( editor ) ;
editor . rebuild ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
this . updateMode ( ) ;
}
update ( {
viewport
} ) {
this . # uiManager . commitOrRemove ( ) ;
this . # cleanup ( ) ;
const oldRotation = this . viewport . rotation ;
const rotation = viewport . rotation ;
this . viewport = viewport ;
setLayerDimensions ( this . div , {
rotation
} ) ;
if ( oldRotation !== rotation ) {
for ( const editor of this . # editors . values ( ) ) {
editor . rotate ( rotation ) ;
}
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
this . addInkEditorIfNeeded ( false ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
get pageDimensions ( ) {
const {
pageWidth ,
pageHeight
} = this . viewport . rawDims ;
return [ pageWidth , pageHeight ] ;
}
get scale ( ) {
return this . # uiManager . viewParameters . realScale ;
}
}
; // CONCATENATED MODULE: ./src/display/draw_layer.js
class DrawLayer {
# parent = null ;
# id = 0 ;
# mapping = new Map ( ) ;
# toUpdate = new Map ( ) ;
constructor ( {
pageIndex
} ) {
this . pageIndex = pageIndex ;
}
setParent ( parent ) {
if ( ! this . # parent ) {
this . # parent = parent ;
return ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
if ( this . # parent !== parent ) {
if ( this . # mapping . size > 0 ) {
for ( const root of this . # mapping . values ( ) ) {
root . remove ( ) ;
parent . append ( root ) ;
}
}
this . # parent = parent ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
}
static get _svgFactory ( ) {
return shadow ( this , "_svgFactory" , new DOMSVGFactory ( ) ) ;
}
static # setBox ( element , {
x = 0 ,
y = 0 ,
width = 1 ,
height = 1
} = { } ) {
2023-10-27 13:19:54 +02:00
const {
2024-06-01 11:00:27 +01:00
style
} = element ;
style . top = ` ${ 100 * y } % ` ;
style . left = ` ${ 100 * x } % ` ;
style . width = ` ${ 100 * width } % ` ;
style . height = ` ${ 100 * height } % ` ;
}
# createSVG ( box ) {
const svg = DrawLayer . _svgFactory . create ( 1 , 1 , true ) ;
this . # parent . append ( svg ) ;
svg . setAttribute ( "aria-hidden" , true ) ;
DrawLayer . # setBox ( svg , box ) ;
return svg ;
}
# createClipPath ( defs , pathId ) {
const clipPath = DrawLayer . _svgFactory . createElement ( "clipPath" ) ;
defs . append ( clipPath ) ;
const clipPathId = ` clip_ ${ pathId } ` ;
clipPath . setAttribute ( "id" , clipPathId ) ;
clipPath . setAttribute ( "clipPathUnits" , "objectBoundingBox" ) ;
const clipPathUse = DrawLayer . _svgFactory . createElement ( "use" ) ;
clipPath . append ( clipPathUse ) ;
clipPathUse . setAttribute ( "href" , ` # ${ pathId } ` ) ;
clipPathUse . classList . add ( "clip" ) ;
return clipPathId ;
}
highlight ( outlines , color , opacity , isPathUpdatable = false ) {
const id = this . # id ++ ;
const root = this . # createSVG ( outlines . box ) ;
root . classList . add ( "highlight" ) ;
if ( outlines . free ) {
root . classList . add ( "free" ) ;
}
const defs = DrawLayer . _svgFactory . createElement ( "defs" ) ;
root . append ( defs ) ;
const path = DrawLayer . _svgFactory . createElement ( "path" ) ;
defs . append ( path ) ;
const pathId = ` path_p ${ this . pageIndex } _ ${ id } ` ;
path . setAttribute ( "id" , pathId ) ;
path . setAttribute ( "d" , outlines . toSVGPath ( ) ) ;
if ( isPathUpdatable ) {
this . # toUpdate . set ( id , path ) ;
}
const clipPathId = this . # createClipPath ( defs , pathId ) ;
const use = DrawLayer . _svgFactory . createElement ( "use" ) ;
root . append ( use ) ;
root . setAttribute ( "fill" , color ) ;
root . setAttribute ( "fill-opacity" , opacity ) ;
use . setAttribute ( "href" , ` # ${ pathId } ` ) ;
this . # mapping . set ( id , root ) ;
return {
id ,
clipPathId : ` url(# ${ clipPathId } ) `
} ;
}
highlightOutline ( outlines ) {
const id = this . # id ++ ;
const root = this . # createSVG ( outlines . box ) ;
root . classList . add ( "highlightOutline" ) ;
const defs = DrawLayer . _svgFactory . createElement ( "defs" ) ;
root . append ( defs ) ;
const path = DrawLayer . _svgFactory . createElement ( "path" ) ;
defs . append ( path ) ;
const pathId = ` path_p ${ this . pageIndex } _ ${ id } ` ;
path . setAttribute ( "id" , pathId ) ;
path . setAttribute ( "d" , outlines . toSVGPath ( ) ) ;
path . setAttribute ( "vector-effect" , "non-scaling-stroke" ) ;
let maskId ;
if ( outlines . free ) {
root . classList . add ( "free" ) ;
const mask = DrawLayer . _svgFactory . createElement ( "mask" ) ;
defs . append ( mask ) ;
maskId = ` mask_p ${ this . pageIndex } _ ${ id } ` ;
mask . setAttribute ( "id" , maskId ) ;
mask . setAttribute ( "maskUnits" , "objectBoundingBox" ) ;
const rect = DrawLayer . _svgFactory . createElement ( "rect" ) ;
mask . append ( rect ) ;
rect . setAttribute ( "width" , "1" ) ;
rect . setAttribute ( "height" , "1" ) ;
rect . setAttribute ( "fill" , "white" ) ;
const use = DrawLayer . _svgFactory . createElement ( "use" ) ;
mask . append ( use ) ;
use . setAttribute ( "href" , ` # ${ pathId } ` ) ;
use . setAttribute ( "stroke" , "none" ) ;
use . setAttribute ( "fill" , "black" ) ;
use . setAttribute ( "fill-rule" , "nonzero" ) ;
use . classList . add ( "mask" ) ;
}
const use1 = DrawLayer . _svgFactory . createElement ( "use" ) ;
root . append ( use1 ) ;
use1 . setAttribute ( "href" , ` # ${ pathId } ` ) ;
if ( maskId ) {
use1 . setAttribute ( "mask" , ` url(# ${ maskId } ) ` ) ;
}
const use2 = use1 . cloneNode ( ) ;
root . append ( use2 ) ;
use1 . classList . add ( "mainOutline" ) ;
use2 . classList . add ( "secondaryOutline" ) ;
this . # mapping . set ( id , root ) ;
return id ;
}
finalizeLine ( id , line ) {
const path = this . # toUpdate . get ( id ) ;
this . # toUpdate . delete ( id ) ;
this . updateBox ( id , line . box ) ;
path . setAttribute ( "d" , line . toSVGPath ( ) ) ;
}
updateLine ( id , line ) {
const root = this . # mapping . get ( id ) ;
const defs = root . firstChild ;
const path = defs . firstChild ;
path . setAttribute ( "d" , line . toSVGPath ( ) ) ;
}
removeFreeHighlight ( id ) {
this . remove ( id ) ;
this . # toUpdate . delete ( id ) ;
}
updatePath ( id , line ) {
this . # toUpdate . get ( id ) . setAttribute ( "d" , line . toSVGPath ( ) ) ;
}
updateBox ( id , box ) {
DrawLayer . # setBox ( this . # mapping . get ( id ) , box ) ;
}
show ( id , visible ) {
this . # mapping . get ( id ) . classList . toggle ( "hidden" , ! visible ) ;
}
rotate ( id , angle ) {
this . # mapping . get ( id ) . setAttribute ( "data-main-rotation" , angle ) ;
}
changeColor ( id , color ) {
this . # mapping . get ( id ) . setAttribute ( "fill" , color ) ;
}
changeOpacity ( id , opacity ) {
this . # mapping . get ( id ) . setAttribute ( "fill-opacity" , opacity ) ;
}
addClass ( id , className ) {
this . # mapping . get ( id ) . classList . add ( className ) ;
}
removeClass ( id , className ) {
this . # mapping . get ( id ) . classList . remove ( className ) ;
}
remove ( id ) {
if ( this . # parent === null ) {
return ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
this . # mapping . get ( id ) . remove ( ) ;
this . # mapping . delete ( id ) ;
}
destroy ( ) {
this . # parent = null ;
for ( const root of this . # mapping . values ( ) ) {
root . remove ( ) ;
2023-10-27 13:19:54 +02:00
}
2024-06-01 11:00:27 +01:00
this . # mapping . clear ( ) ;
2023-10-27 13:19:54 +02:00
}
}
2024-06-01 11:00:27 +01:00
; // CONCATENATED MODULE: ./src/pdf.js
2023-10-27 13:19:54 +02:00
2013-12-31 16:34:23 +05:30
2024-06-01 11:00:27 +01:00
2024-06-18 20:06:52 +02:00
const pdfjsVersion = "4.4.82" ;
const pdfjsBuild = "8c6cee28e" ;
} ) ( ) ;
2024-06-01 11:00:27 +01:00
var _ _webpack _exports _ _AbortException = _ _webpack _exports _ _ . AbortException ;
var _ _webpack _exports _ _AnnotationEditorLayer = _ _webpack _exports _ _ . AnnotationEditorLayer ;
var _ _webpack _exports _ _AnnotationEditorParamsType = _ _webpack _exports _ _ . AnnotationEditorParamsType ;
var _ _webpack _exports _ _AnnotationEditorType = _ _webpack _exports _ _ . AnnotationEditorType ;
var _ _webpack _exports _ _AnnotationEditorUIManager = _ _webpack _exports _ _ . AnnotationEditorUIManager ;
var _ _webpack _exports _ _AnnotationLayer = _ _webpack _exports _ _ . AnnotationLayer ;
var _ _webpack _exports _ _AnnotationMode = _ _webpack _exports _ _ . AnnotationMode ;
var _ _webpack _exports _ _CMapCompressionType = _ _webpack _exports _ _ . CMapCompressionType ;
var _ _webpack _exports _ _ColorPicker = _ _webpack _exports _ _ . ColorPicker ;
var _ _webpack _exports _ _DOMSVGFactory = _ _webpack _exports _ _ . DOMSVGFactory ;
var _ _webpack _exports _ _DrawLayer = _ _webpack _exports _ _ . DrawLayer ;
var _ _webpack _exports _ _FeatureTest = _ _webpack _exports _ _ . FeatureTest ;
var _ _webpack _exports _ _GlobalWorkerOptions = _ _webpack _exports _ _ . GlobalWorkerOptions ;
var _ _webpack _exports _ _ImageKind = _ _webpack _exports _ _ . ImageKind ;
var _ _webpack _exports _ _InvalidPDFException = _ _webpack _exports _ _ . InvalidPDFException ;
var _ _webpack _exports _ _MissingPDFException = _ _webpack _exports _ _ . MissingPDFException ;
var _ _webpack _exports _ _OPS = _ _webpack _exports _ _ . OPS ;
var _ _webpack _exports _ _Outliner = _ _webpack _exports _ _ . Outliner ;
var _ _webpack _exports _ _PDFDataRangeTransport = _ _webpack _exports _ _ . PDFDataRangeTransport ;
var _ _webpack _exports _ _PDFDateString = _ _webpack _exports _ _ . PDFDateString ;
var _ _webpack _exports _ _PDFWorker = _ _webpack _exports _ _ . PDFWorker ;
var _ _webpack _exports _ _PasswordResponses = _ _webpack _exports _ _ . PasswordResponses ;
var _ _webpack _exports _ _PermissionFlag = _ _webpack _exports _ _ . PermissionFlag ;
var _ _webpack _exports _ _PixelsPerInch = _ _webpack _exports _ _ . PixelsPerInch ;
var _ _webpack _exports _ _RenderingCancelledException = _ _webpack _exports _ _ . RenderingCancelledException ;
var _ _webpack _exports _ _TextLayer = _ _webpack _exports _ _ . TextLayer ;
var _ _webpack _exports _ _UnexpectedResponseException = _ _webpack _exports _ _ . UnexpectedResponseException ;
var _ _webpack _exports _ _Util = _ _webpack _exports _ _ . Util ;
var _ _webpack _exports _ _VerbosityLevel = _ _webpack _exports _ _ . VerbosityLevel ;
var _ _webpack _exports _ _XfaLayer = _ _webpack _exports _ _ . XfaLayer ;
var _ _webpack _exports _ _build = _ _webpack _exports _ _ . build ;
var _ _webpack _exports _ _createValidAbsoluteUrl = _ _webpack _exports _ _ . createValidAbsoluteUrl ;
var _ _webpack _exports _ _fetchData = _ _webpack _exports _ _ . fetchData ;
var _ _webpack _exports _ _getDocument = _ _webpack _exports _ _ . getDocument ;
var _ _webpack _exports _ _getFilenameFromUrl = _ _webpack _exports _ _ . getFilenameFromUrl ;
var _ _webpack _exports _ _getPdfFilenameFromUrl = _ _webpack _exports _ _ . getPdfFilenameFromUrl ;
var _ _webpack _exports _ _getXfaPageViewport = _ _webpack _exports _ _ . getXfaPageViewport ;
var _ _webpack _exports _ _isDataScheme = _ _webpack _exports _ _ . isDataScheme ;
var _ _webpack _exports _ _isPdfFile = _ _webpack _exports _ _ . isPdfFile ;
var _ _webpack _exports _ _noContextMenu = _ _webpack _exports _ _ . noContextMenu ;
var _ _webpack _exports _ _normalizeUnicode = _ _webpack _exports _ _ . normalizeUnicode ;
var _ _webpack _exports _ _renderTextLayer = _ _webpack _exports _ _ . renderTextLayer ;
var _ _webpack _exports _ _setLayerDimensions = _ _webpack _exports _ _ . setLayerDimensions ;
var _ _webpack _exports _ _shadow = _ _webpack _exports _ _ . shadow ;
var _ _webpack _exports _ _updateTextLayer = _ _webpack _exports _ _ . updateTextLayer ;
var _ _webpack _exports _ _version = _ _webpack _exports _ _ . version ;
export { _ _webpack _exports _ _AbortException as AbortException , _ _webpack _exports _ _AnnotationEditorLayer as AnnotationEditorLayer , _ _webpack _exports _ _AnnotationEditorParamsType as AnnotationEditorParamsType , _ _webpack _exports _ _AnnotationEditorType as AnnotationEditorType , _ _webpack _exports _ _AnnotationEditorUIManager as AnnotationEditorUIManager , _ _webpack _exports _ _AnnotationLayer as AnnotationLayer , _ _webpack _exports _ _AnnotationMode as AnnotationMode , _ _webpack _exports _ _CMapCompressionType as CMapCompressionType , _ _webpack _exports _ _ColorPicker as ColorPicker , _ _webpack _exports _ _DOMSVGFactory as DOMSVGFactory , _ _webpack _exports _ _DrawLayer as DrawLayer , _ _webpack _exports _ _FeatureTest as FeatureTest , _ _webpack _exports _ _GlobalWorkerOptions as GlobalWorkerOptions , _ _webpack _exports _ _ImageKind as ImageKind , _ _webpack _exports _ _InvalidPDFException as InvalidPDFException , _ _webpack _exports _ _MissingPDFException as MissingPDFException , _ _webpack _exports _ _OPS as OPS , _ _webpack _exports _ _Outliner as Outliner , _ _webpack _exports _ _PDFDataRangeTransport as PDFDataRangeTransport , _ _webpack _exports _ _PDFDateString as PDFDateString , _ _webpack _exports _ _PDFWorker as PDFWorker , _ _webpack _exports _ _PasswordResponses as PasswordResponses , _ _webpack _exports _ _PermissionFlag as PermissionFlag , _ _webpack _exports _ _PixelsPerInch as PixelsPerInch , _ _webpack _exports _ _RenderingCancelledException as RenderingCancelledException , _ _webpack _exports _ _TextLayer as TextLayer , _ _webpack _exports _ _UnexpectedResponseException as UnexpectedResponseException , _ _webpack _exports _ _Util as Util , _ _webpack _exports _ _VerbosityLevel as VerbosityLevel , _ _webpack _exports _ _XfaLayer as XfaLayer , _ _webpack _exports _ _build as build , _ _webpack _exports _ _createValidAbsoluteUrl as createValidAbsoluteUrl , _ _webpack _exports _ _fetchData as fetchData , _ _webpack _exports _ _getDocument as getDocument , _ _webpack _exports _ _getFilenameFromUrl as getFilenameFromUrl , _ _webpack _exports _ _getPdfFilenameFromUrl as getPdfFilenameFromUrl , _ _webpack _exports _ _getXfaPageViewport as getXfaPageViewport , _ _webpack _exports _ _isDataScheme as isDataScheme , _ _webpack _exports _ _isPdfFile as isPdfFile , _ _webpack _exports _ _noContextMenu as noContextMenu , _ _webpack _exports _ _normalizeUnicode as normalizeUnicode , _ _webpack _exports _ _renderTextLayer as renderTextLayer , _ _webpack _exports _ _setLayerDimensions as setLayerDimensions , _ _webpack _exports _ _shadow as shadow , _ _webpack _exports _ _updateTextLayer as updateTextLayer , _ _webpack _exports _ _version as version } ;
//# sourceMappingURL=pdf.mjs.map