diff --git a/services/web/app/coffee/Features/Analytics/AnalyticsManager.coffee b/services/web/app/coffee/Features/Analytics/AnalyticsManager.coffee
index f906118b16..6840f8fa88 100644
--- a/services/web/app/coffee/Features/Analytics/AnalyticsManager.coffee
+++ b/services/web/app/coffee/Features/Analytics/AnalyticsManager.coffee
@@ -1,43 +1,48 @@
-Settings = require "settings-sharelatex"
+settings = require "settings-sharelatex"
logger = require "logger-sharelatex"
_ = require "underscore"
+request = require "request"
-if !Settings.analytics?.postgres?
- module.exports =
- recordEvent: (user_id, event, segmentation, callback = () ->) ->
- logger.log {user_id, event, segmentation}, "no event tracking configured, logging event"
- callback()
-else
- Sequelize = require "sequelize"
- options = _.extend {logging:false}, Settings.analytics.postgres
- sequelize = new Sequelize(
- Settings.analytics.postgres.database,
- Settings.analytics.postgres.username,
- Settings.analytics.postgres.password,
- options
- )
-
- Event = sequelize.define("Event", {
- user_id: Sequelize.STRING,
- event: Sequelize.STRING,
- segmentation: Sequelize.JSONB
- })
+makeRequest = (opts, callback)->
+ if settings.apis?.analytics?.url?
+ urlPath = opts.url
+ opts.url = "#{settings.apis.analytics.url}#{urlPath}"
+ request opts, callback
+ else
+ callback()
- module.exports =
- recordEvent: (user_id, event, segmentation = {}, callback = (error) ->) ->
- if user_id? and typeof(user_id) != "string"
- user_id = user_id.toString()
- if user_id == Settings.smokeTest?.userId
- # Don't record smoke tests analytics
- return callback()
- Event
- .create({ user_id, event, segmentation })
- .then(
- (result) -> callback(),
- (error) ->
- logger.err {err: error, user_id, event, segmentation}, "error recording analytics event"
- callback(error)
- )
-
- sync: () -> sequelize.sync()
\ No newline at end of file
+
+
+module.exports =
+
+
+ recordEvent: (user_id, event, segmentation = {}, callback = (error) ->) ->
+ if user_id == settings.smokeTest?.userId
+ return callback()
+ opts =
+ body:
+ event:event
+ segmentation:segmentation
+ json:true
+ method:"POST"
+ timeout:1000
+ url: "/user/#{user_id}/event"
+ makeRequest opts, callback
+
+
+ getLastOccurance: (user_id, event, callback = (error) ->) ->
+ opts =
+ body:
+ event:event
+ json:true
+ method:"POST"
+ timeout:1000
+ url: "/user/#{user_id}/event/last_occurnace"
+ makeRequest opts, (err, response, body)->
+ if err?
+ console.log response, opts
+ logger.err {user_id, err}, "error getting last occurance of event"
+ return callback err
+ else
+ return callback null, body
diff --git a/services/web/app/coffee/Features/Announcements/AnnouncementsController.coffee b/services/web/app/coffee/Features/Announcements/AnnouncementsController.coffee
new file mode 100644
index 0000000000..ed3d8eee1e
--- /dev/null
+++ b/services/web/app/coffee/Features/Announcements/AnnouncementsController.coffee
@@ -0,0 +1,24 @@
+AnnouncementsHandler = require("./AnnouncementsHandler")
+AuthenticationController = require("../Authentication/AuthenticationController")
+logger = require("logger-sharelatex")
+
+
+module.exports =
+
+ getUndreadAnnouncements: (req, res, next)->
+ if !settings?.apis?.analytics?.url? or !settings.apis.blog.url?
+ return res.json []
+
+ user_id = AuthenticationController.getLoggedInUserId(req)
+ logger.log {user_id}, "getting unread announcements"
+ AnnouncementsHandler.getUnreadAnnouncements user_id, (err, announcements)->
+ if err?
+ logger.err {err, user_id}, "unable to get unread announcements"
+ next(err)
+ else
+ res.json announcements
+
+
+
+
+
diff --git a/services/web/app/coffee/Features/Announcements/AnnouncementsHandler.coffee b/services/web/app/coffee/Features/Announcements/AnnouncementsHandler.coffee
new file mode 100644
index 0000000000..a27608343a
--- /dev/null
+++ b/services/web/app/coffee/Features/Announcements/AnnouncementsHandler.coffee
@@ -0,0 +1,33 @@
+AnalyticsManager = require("../Analytics/AnalyticsManager")
+BlogHandler = require("../Blog/BlogHandler")
+async = require("async")
+_ = require("lodash")
+logger = require("logger-sharelatex")
+settings = require("settings-sharelatex")
+
+module.exports =
+
+ getUnreadAnnouncements : (user_id, callback = (err, announcements)->)->
+ async.parallel {
+ lastEvent: (cb)->
+ AnalyticsManager.getLastOccurance user_id, "announcement-alert-dismissed", cb
+ announcements: (cb)->
+ BlogHandler.getLatestAnnouncements cb
+ }, (err, results)->
+ if err?
+ logger.err err:err, user_id:user_id, "error getting unread announcements"
+ return callback(err)
+
+ announcements = _.sortBy(results.announcements, "date").reverse()
+
+ lastSeenBlogId = results?.lastEvent?.segmentation?.blogPostId
+
+ announcementIndex = _.findIndex announcements, (announcement)->
+ announcement.id == lastSeenBlogId
+
+ if announcementIndex != -1
+ announcements = announcements.slice(0, announcementIndex)
+
+ logger.log announcementsLength:announcements?.length, user_id:user_id, "returning announcements"
+
+ callback null, announcements
diff --git a/services/web/app/coffee/Features/Authentication/AuthenticationController.coffee b/services/web/app/coffee/Features/Authentication/AuthenticationController.coffee
index f3faad6c69..3c19f0de25 100644
--- a/services/web/app/coffee/Features/Authentication/AuthenticationController.coffee
+++ b/services/web/app/coffee/Features/Authentication/AuthenticationController.coffee
@@ -32,21 +32,27 @@ module.exports = AuthenticationController =
afterLoginSessionSetup: (req, user, callback=(err)->) ->
req.login user, (err) ->
+ if err?
+ logger.err {user_id: user._id, err}, "error from req.login"
+ return callback(err)
# Regenerate the session to get a new sessionID (cookie value) to
# protect against session fixation attacks
oldSession = req.session
- req.session.destroy()
- req.sessionStore.generate(req)
- for key, value of oldSession
- req.session[key] = value
- # copy to the old `session.user` location, for backward-comptability
- req.session.user = req.session.passport.user
- req.session.save (err) ->
+ req.session.destroy (err) ->
if err?
- logger.err {user_id: user._id}, "error saving regenerated session after login"
+ logger.err {user_id: user._id, err}, "error when trying to destroy old session"
return callback(err)
- UserSessionsManager.trackSession(user, req.sessionID, () ->)
- callback(null)
+ req.sessionStore.generate(req)
+ for key, value of oldSession
+ req.session[key] = value
+ # copy to the old `session.user` location, for backward-comptability
+ req.session.user = req.session.passport.user
+ req.session.save (err) ->
+ if err?
+ logger.err {user_id: user._id}, "error saving regenerated session after login"
+ return callback(err)
+ UserSessionsManager.trackSession(user, req.sessionID, () ->)
+ callback(null)
passportLogin: (req, res, next) ->
# This function is middleware which wraps the passport.authenticate middleware,
diff --git a/services/web/app/coffee/Features/Blog/BlogHandler.coffee b/services/web/app/coffee/Features/Blog/BlogHandler.coffee
new file mode 100644
index 0000000000..6f8f41b5fd
--- /dev/null
+++ b/services/web/app/coffee/Features/Blog/BlogHandler.coffee
@@ -0,0 +1,24 @@
+request = require "request"
+settings = require "settings-sharelatex"
+_ = require("underscore")
+logger = require "logger-sharelatex"
+
+module.exports = BlogHandler =
+
+ getLatestAnnouncements: (callback)->
+ blogUrl = "#{settings.apis.blog.url}/blog/latestannouncements.json"
+ opts =
+ url:blogUrl
+ json:true
+ timeout:500
+ request.get opts, (err, res, announcements)->
+ if err?
+ return callback err
+ if res.statusCode != 200
+ return callback("blog announcement returned non 200")
+ logger.log announcementsLength: announcements?.length, "announcements returned"
+ announcements = _.map announcements, (announcement)->
+ announcement.url = "/blog#{announcement.url}"
+ announcement.date = new Date(announcement.date)
+ return announcement
+ callback(err, announcements)
diff --git a/services/web/app/coffee/Features/Email/EmailSender.coffee b/services/web/app/coffee/Features/Email/EmailSender.coffee
index 8210324747..a7bcc82ed7 100644
--- a/services/web/app/coffee/Features/Email/EmailSender.coffee
+++ b/services/web/app/coffee/Features/Email/EmailSender.coffee
@@ -25,7 +25,7 @@ else if Settings?.email?.parameters?.sendgridApiKey?
logger.log "using sendgrid for email"
nm_client = nodemailer.createTransport(sgTransport({auth:{api_key:Settings?.email?.parameters?.sendgridApiKey}}))
else if Settings?.email?.parameters?
- smtp = _.pick(Settings?.email?.parameters, "host", "port", "secure", "auth")
+ smtp = _.pick(Settings?.email?.parameters, "host", "port", "secure", "auth", "ignoreTLS")
logger.log "using smtp for email"
diff --git a/services/web/app/coffee/Features/HealthCheck/HealthCheckController.coffee b/services/web/app/coffee/Features/HealthCheck/HealthCheckController.coffee
index 9aec67e14e..51acdbd2f0 100644
--- a/services/web/app/coffee/Features/HealthCheck/HealthCheckController.coffee
+++ b/services/web/app/coffee/Features/HealthCheck/HealthCheckController.coffee
@@ -64,7 +64,7 @@ Reporter = (res) ->
res.contentType("application/json")
if failures.length > 0
logger.err failures:failures, "health check failed"
- res.send 500, JSON.stringify(results, null, 2)
+ res.status(500).send(JSON.stringify(results, null, 2))
else
- res.send 200, JSON.stringify(results, null, 2)
+ res.status(200).send(JSON.stringify(results, null, 2))
diff --git a/services/web/app/coffee/Features/Project/ProjectController.coffee b/services/web/app/coffee/Features/Project/ProjectController.coffee
index 440534bf11..1d975ea5b3 100644
--- a/services/web/app/coffee/Features/Project/ProjectController.coffee
+++ b/services/web/app/coffee/Features/Project/ProjectController.coffee
@@ -153,6 +153,8 @@ module.exports = ProjectController =
return next(err)
logger.log results:results, user_id:user_id, "rendering project list"
tags = results.tags[0]
+
+
notifications = require("underscore").map results.notifications, (notification)->
notification.html = req.i18n.translate(notification.templateKey, notification.messageOpts)
return notification
diff --git a/services/web/app/coffee/Features/Security/SessionInvalidator.coffee b/services/web/app/coffee/Features/Security/SessionInvalidator.coffee
deleted file mode 100644
index 668019f6f2..0000000000
--- a/services/web/app/coffee/Features/Security/SessionInvalidator.coffee
+++ /dev/null
@@ -1,26 +0,0 @@
-Settings = require("settings-sharelatex")
-redis = require("redis-sharelatex")
-rclient = redis.createClient(Settings.redis.web)
-crypto = require("crypto")
-async = require("async")
-
-
-module.exports =
-
- _getEmailKey : (email)->
- hash = crypto.createHash("md5").update(email).digest("hex")
- return "e_sess:#{hash}"
-
- tracksession:(sessionId, email, callback = ->)->
- session_lookup_key = @_getEmailKey(email)
- rclient.set session_lookup_key, sessionId, callback
-
- invalidateSession:(email, callback = ->)->
- session_lookup_key = @_getEmailKey(email)
- rclient.get session_lookup_key, (err, sessionId)->
- async.series [
- (cb)-> rclient.del sessionId, cb
- (cb)-> rclient.del session_lookup_key, cb
- ], callback
-
-
diff --git a/services/web/app/coffee/Features/User/UserController.coffee b/services/web/app/coffee/Features/User/UserController.coffee
index 47c093d590..27e37b91be 100644
--- a/services/web/app/coffee/Features/User/UserController.coffee
+++ b/services/web/app/coffee/Features/User/UserController.coffee
@@ -44,6 +44,7 @@ module.exports = UserController =
updateUserSettings : (req, res)->
user_id = AuthenticationController.getLoggedInUserId(req)
+ usingExternalAuth = settings.ldap? or settings.saml?
logger.log user_id: user_id, "updating account settings"
User.findById user_id, (err, user)->
if err? or !user?
@@ -74,12 +75,15 @@ module.exports = UserController =
user.ace.syntaxValidation = req.body.syntaxValidation
user.save (err)->
newEmail = req.body.email?.trim().toLowerCase()
- if !newEmail? or newEmail == user.email
+ if !newEmail? or newEmail == user.email or usingExternalAuth
+ # end here, don't update email
AuthenticationController.setInSessionUser(req, {first_name: user.first_name, last_name: user.last_name})
return res.sendStatus 200
else if newEmail.indexOf("@") == -1
+ # email invalid
return res.sendStatus(400)
else
+ # update the user email
UserUpdater.changeEmailAddress user_id, newEmail, (err)->
if err?
logger.err err:err, user_id:user_id, newEmail:newEmail, "problem updaing users email address"
diff --git a/services/web/app/coffee/Features/User/UserSessionsManager.coffee b/services/web/app/coffee/Features/User/UserSessionsManager.coffee
index 23a9bcbb36..78016e8a09 100644
--- a/services/web/app/coffee/Features/User/UserSessionsManager.coffee
+++ b/services/web/app/coffee/Features/User/UserSessionsManager.coffee
@@ -3,14 +3,11 @@ redis = require('redis-sharelatex')
logger = require("logger-sharelatex")
Async = require('async')
_ = require('underscore')
+UserSessionsRedis = require('./UserSessionsRedis')
-rclient = redis.createClient(Settings.redis.web)
+rclient = UserSessionsRedis.client()
module.exports = UserSessionsManager =
-
- _sessionSetKey: (user) ->
- return "UserSessions:#{user._id}"
-
# mimic the key used by the express sessions
_sessionKey: (sessionId) ->
return "sess:#{sessionId}"
@@ -23,7 +20,7 @@ module.exports = UserSessionsManager =
logger.log {user_id: user._id}, "no sessionId to track, returning"
return callback(null)
logger.log {user_id: user._id, sessionId}, "onLogin handler"
- sessionSetKey = UserSessionsManager._sessionSetKey(user)
+ sessionSetKey = UserSessionsRedis.sessionSetKey(user)
value = UserSessionsManager._sessionKey sessionId
rclient.multi()
.sadd(sessionSetKey, value)
@@ -43,7 +40,7 @@ module.exports = UserSessionsManager =
logger.log {user_id: user._id}, "no sessionId to untrack, returning"
return callback(null)
logger.log {user_id: user._id, sessionId}, "onLogout handler"
- sessionSetKey = UserSessionsManager._sessionSetKey(user)
+ sessionSetKey = UserSessionsRedis.sessionSetKey(user)
value = UserSessionsManager._sessionKey sessionId
rclient.multi()
.srem(sessionSetKey, value)
@@ -57,7 +54,7 @@ module.exports = UserSessionsManager =
getAllUserSessions: (user, exclude, callback=(err, sessionKeys)->) ->
exclude = _.map(exclude, UserSessionsManager._sessionKey)
- sessionSetKey = UserSessionsManager._sessionSetKey(user)
+ sessionSetKey = UserSessionsRedis.sessionSetKey(user)
rclient.smembers sessionSetKey, (err, sessionKeys) ->
if err?
logger.err user_id: user._id, "error getting all session keys for user from redis"
@@ -66,7 +63,8 @@ module.exports = UserSessionsManager =
if sessionKeys.length == 0
logger.log {user_id: user._id}, "no other sessions found, returning"
return callback(null, [])
- rclient.mget sessionKeys, (err, sessions) ->
+
+ Async.mapSeries sessionKeys, ((k, cb) -> rclient.get(k, cb)), (err, sessions) ->
if err?
logger.err {user_id: user._id}, "error getting all sessions for user from redis"
return callback(err)
@@ -92,7 +90,7 @@ module.exports = UserSessionsManager =
logger.log {}, "no user to revoke sessions for, returning"
return callback(null)
logger.log {user_id: user._id}, "revoking all existing sessions for user"
- sessionSetKey = UserSessionsManager._sessionSetKey(user)
+ sessionSetKey = UserSessionsRedis.sessionSetKey(user)
rclient.smembers sessionSetKey, (err, sessionKeys) ->
if err?
logger.err {err, user_id: user._id, sessionSetKey}, "error getting contents of UserSessions set"
@@ -102,12 +100,18 @@ module.exports = UserSessionsManager =
logger.log {user_id: user._id}, "no sessions in UserSessions set to delete, returning"
return callback(null)
logger.log {user_id: user._id, count: keysToDelete.length}, "deleting sessions for user"
- rclient.multi()
- .del(keysToDelete)
- .srem(sessionSetKey, keysToDelete)
- .exec (err, result) ->
+
+ deletions = keysToDelete.map (k) ->
+ (cb) ->
+ rclient.del k, cb
+
+ Async.series deletions, (err, _result) ->
+ if err?
+ logger.err {err, user_id: user._id, sessionSetKey}, "errror revoking all sessions for user"
+ return callback(err)
+ rclient.srem sessionSetKey, keysToDelete, (err) ->
if err?
- logger.err {err, user_id: user._id, sessionSetKey}, "error revoking all sessions for user"
+ logger.err {err, user_id: user._id, sessionSetKey}, "error removing session set for user"
return callback(err)
callback(null)
@@ -115,7 +119,7 @@ module.exports = UserSessionsManager =
if !user
logger.log {}, "no user to touch sessions for, returning"
return callback(null)
- sessionSetKey = UserSessionsManager._sessionSetKey(user)
+ sessionSetKey = UserSessionsRedis.sessionSetKey(user)
rclient.expire sessionSetKey, "#{Settings.cookieSessionLength}", (err, response) ->
if err?
logger.err {err, user_id: user._id}, "error while updating ttl on UserSessions set"
@@ -127,7 +131,7 @@ module.exports = UserSessionsManager =
logger.log {}, "no user, returning"
return callback(null)
logger.log {user_id: user._id}, "checking sessions for user"
- sessionSetKey = UserSessionsManager._sessionSetKey(user)
+ sessionSetKey = UserSessionsRedis.sessionSetKey(user)
rclient.smembers sessionSetKey, (err, sessionKeys) ->
if err?
logger.err {err, user_id: user._id, sessionSetKey}, "error getting contents of UserSessions set"
diff --git a/services/web/app/coffee/Features/User/UserSessionsRedis.coffee b/services/web/app/coffee/Features/User/UserSessionsRedis.coffee
new file mode 100644
index 0000000000..89ab7ed192
--- /dev/null
+++ b/services/web/app/coffee/Features/User/UserSessionsRedis.coffee
@@ -0,0 +1,21 @@
+Settings = require 'settings-sharelatex'
+redis = require 'redis-sharelatex'
+ioredis = require 'ioredis'
+logger = require 'logger-sharelatex'
+
+redisSessionsSettings = Settings.redis.websessions or Settings.redis.web
+
+module.exports = Redis =
+ client: () ->
+ if redisSessionsSettings?.cluster?
+ logger.log {}, "using redis cluster for web sessions"
+ rclient = new ioredis.Cluster(redisSessionsSettings.cluster)
+ else
+ rclient = redis.createClient(redisSessionsSettings)
+ return rclient
+
+ sessionSetKey: (user) ->
+ if redisSessionsSettings?.cluster?
+ return "UserSessions:{#{user._id}}"
+ else
+ return "UserSessions:#{user._id}"
diff --git a/services/web/app/coffee/infrastructure/ExpressLocals.coffee b/services/web/app/coffee/infrastructure/ExpressLocals.coffee
index c699332f46..e469df9422 100644
--- a/services/web/app/coffee/infrastructure/ExpressLocals.coffee
+++ b/services/web/app/coffee/infrastructure/ExpressLocals.coffee
@@ -210,7 +210,7 @@ module.exports = (app, webRouter, apiRouter)->
webRouter.use (req, res, next)->
res.locals.externalAuthenticationSystemUsed = ->
- Settings.ldap?
+ Settings.ldap? or Settings.saml?
next()
webRouter.use (req, res, next)->
diff --git a/services/web/app/coffee/infrastructure/Modules.coffee b/services/web/app/coffee/infrastructure/Modules.coffee
index 0dfbf3fa22..1b3c2ea9a5 100644
--- a/services/web/app/coffee/infrastructure/Modules.coffee
+++ b/services/web/app/coffee/infrastructure/Modules.coffee
@@ -18,6 +18,10 @@ module.exports = Modules =
applyRouter: (webRouter, apiRouter) ->
for module in @modules
module.router?.apply(webRouter, apiRouter)
+
+ applyNonCsrfRouter: (webRouter, apiRouter) ->
+ for module in @modules
+ module.nonCsrfRouter?.apply(webRouter, apiRouter)
viewIncludes: {}
loadViewIncludes: (app) ->
@@ -58,4 +62,4 @@ module.exports = Modules =
return callback(error) if error?
return callback null, results
-Modules.loadModules()
\ No newline at end of file
+Modules.loadModules()
diff --git a/services/web/app/coffee/infrastructure/PackageVersions.coffee b/services/web/app/coffee/infrastructure/PackageVersions.coffee
index 53c31e4345..7342814ec7 100644
--- a/services/web/app/coffee/infrastructure/PackageVersions.coffee
+++ b/services/web/app/coffee/infrastructure/PackageVersions.coffee
@@ -1,5 +1,5 @@
version = {
- "pdfjs": "1.6.210p1"
+ "pdfjs": "1.6.210p2"
"moment": "2.9.0"
"ace": "1.2.5"
}
diff --git a/services/web/app/coffee/infrastructure/Server.coffee b/services/web/app/coffee/infrastructure/Server.coffee
index e19d9c5ca8..6ee9390b93 100644
--- a/services/web/app/coffee/infrastructure/Server.coffee
+++ b/services/web/app/coffee/infrastructure/Server.coffee
@@ -8,7 +8,9 @@ expressLocals = require('./ExpressLocals')
Router = require('../router')
metrics.inc("startup")
redis = require("redis-sharelatex")
-rclient = redis.createClient(Settings.redis.web)
+UserSessionsRedis = require('../Features/User/UserSessionsRedis')
+
+sessionsRedisClient = UserSessionsRedis.client()
session = require("express-session")
RedisStore = require('connect-redis')(session)
@@ -19,7 +21,8 @@ csrf = require('csurf')
csrfProtection = csrf()
cookieParser = require('cookie-parser')
-sessionStore = new RedisStore(client:rclient)
+# Init the session store
+sessionStore = new RedisStore(client:sessionsRedisClient)
passport = require('passport')
LocalStrategy = require('passport-local').Strategy
@@ -87,9 +90,6 @@ webRouter.use session
secure: Settings.secureCookie
store: sessionStore
key: Settings.cookieName
-webRouter.use csrfProtection
-webRouter.use translations.expressMiddlewear
-webRouter.use translations.setLangBasedOnDomainMiddlewear
# passport
webRouter.use passport.initialize()
@@ -110,6 +110,12 @@ Modules.hooks.fire 'passportSetup', passport, (err) ->
if err?
logger.err {err}, "error setting up passport in modules"
+Modules.applyNonCsrfRouter(webRouter, apiRouter)
+
+webRouter.use csrfProtection
+webRouter.use translations.expressMiddlewear
+webRouter.use translations.setLangBasedOnDomainMiddlewear
+
# Measure expiry from last request, not last login
webRouter.use (req, res, next) ->
req.session.touch()
diff --git a/services/web/app/coffee/router.coffee b/services/web/app/coffee/router.coffee
index a027f6359e..14ac3b8d22 100644
--- a/services/web/app/coffee/router.coffee
+++ b/services/web/app/coffee/router.coffee
@@ -39,6 +39,7 @@ ReferencesController = require('./Features/References/ReferencesController')
AuthorizationMiddlewear = require('./Features/Authorization/AuthorizationMiddlewear')
BetaProgramController = require('./Features/BetaProgram/BetaProgramController')
AnalyticsRouter = require('./Features/Analytics/AnalyticsRouter')
+AnnouncementsController = require("./Features/Announcements/AnnouncementsController")
logger = require("logger-sharelatex")
_ = require("underscore")
@@ -187,6 +188,9 @@ module.exports = class Router
webRouter.get '/notifications', AuthenticationController.requireLogin(), NotificationsController.getAllUnreadNotifications
webRouter.delete '/notifications/:notification_id', AuthenticationController.requireLogin(), NotificationsController.markNotificationAsRead
+ webRouter.get '/announcements', AuthenticationController.requireLogin(), AnnouncementsController.getUndreadAnnouncements
+
+
# Deprecated in favour of /internal/project/:project_id but still used by versioning
apiRouter.get '/project/:project_id/details', AuthenticationController.httpAuth, ProjectApiController.getProjectDetails
diff --git a/services/web/app/views/general/500.jade b/services/web/app/views/general/500.jade
index ef74ed7435..8381ca6190 100644
--- a/services/web/app/views/general/500.jade
+++ b/services/web/app/views/general/500.jade
@@ -3,7 +3,8 @@ html(itemscope, itemtype='http://schema.org/Product')
head
title Something went wrong
link(rel="icon", href="/favicon.ico")
- link(rel='stylesheet', href=buildCssPath('/style.css'))
+ if buildCssPath
+ link(rel='stylesheet', href=buildCssPath('/style.css'))
link(href="//netdna.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css",rel="stylesheet")
body
.content
@@ -12,7 +13,9 @@ html(itemscope, itemtype='http://schema.org/Product')
.col-md-8.col-md-offset-2.text-center
.page-header
h2 Oh dear, something went wrong.
- p: img(src=buildImgPath("lion-sad-128.png"), alt="Sad Lion")
+ if buildImgPath
+ p
+ img(src=buildImgPath("lion-sad-128.png"), alt="Sad Lion")
p
| Something went wrong with your request, sorry. Our staff are probably looking into this, but if it continues, please contact us at #{settings.adminEmail}
p
diff --git a/services/web/app/views/project/editor/header.jade b/services/web/app/views/project/editor/header.jade
index 19f659ddc4..e4dc5788b3 100644
--- a/services/web/app/views/project/editor/header.jade
+++ b/services/web/app/views/project/editor/header.jade
@@ -1,388 +1,125 @@
-div(ng-if="!shouldABTestHeaderLabels")
- header.toolbar.toolbar-header(
- ng-cloak,
- ng-hide="state.loading"
- )
+header.toolbar.toolbar-header.toolbar-with-labels(
+ ng-cloak,
+ ng-hide="state.loading"
+)
+ .toolbar-left
a.btn.btn-full-height(
href,
- ng-click="ui.leftMenuShown = true"
- tooltip='#{translate("menu")}',
- tooltip-placement="bottom",
- tooltip-append-to-body="true",
+ ng-click="ui.leftMenuShown = true;",
)
i.fa.fa-fw.fa-bars
+ p.toolbar-label #{translate("menu")}
a(
href="/project"
- tooltip="#{translate('back_to_projects')}",
- tooltip-placement="bottom",
- tooltip-append-to-body="true"
)
i.fa.fa-fw.fa-level-up
-
- span(ng-controller="PdfViewToggleController")
- a(
- href,
- ng-show="ui.pdfLayout == 'flat' && fileTreeClosed",
- tooltip="PDF",
- tooltip-placement="bottom",
- tooltip-append-to-body="true",
- ng-click="togglePdfView()",
- ng-class="{ 'active': ui.view == 'pdf' }"
- )
- i.fa.fa-file-pdf-o
- .toolbar-center.project-name(ng-controller="ProjectNameController")
- span.name(
- ng-dblclick="!permissions.admin || startRenaming()",
- ng-show="!state.renaming"
- ) {{ project.name }}
-
- input.form-control(
- type="text"
- ng-model="inputs.name",
- ng-show="state.renaming",
- on-enter="finishRenaming()",
- ng-blur="finishRenaming()",
- select-name-when="state.renaming"
- )
-
- a.rename(
- ng-if="permissions.admin",
- href='#',
- tooltip-placement="bottom",
- tooltip="#{translate('rename')}",
- tooltip-append-to-body="true",
- ng-click="startRenaming()",
- ng-show="!state.renaming"
- )
- i.fa.fa-pencil
-
- .toolbar-right
- span.online-users(
- ng-show="onlineUsersArray.length > 0"
- ng-controller="OnlineUsersController"
- )
- span(ng-if="onlineUsersArray.length < 4")
- span.online-user(
- ng-repeat="user in onlineUsersArray",
- ng-style="{ 'background-color': 'hsl({{ getHueForUserId(user.user_id) }}, 70%, 50%)' }",
- popover="{{ user.name }}"
- popover-placement="bottom"
- popover-append-to-body="true"
- popover-trigger="mouseenter"
- ng-click="gotoUser(user)"
- ) {{ user.name.slice(0,1) }}
-
- span.dropdown(dropdown, ng-if="onlineUsersArray.length >= 4")
- span.online-user.online-user-multi(
- dropdown-toggle,
- tooltip="#{translate('connected_users')}",
- tooltip-placement="left"
- )
- strong {{ onlineUsersArray.length }}
- i.fa.fa-fw.fa-user
- ul.dropdown-menu.pull-right
- li.dropdown-header #{translate('connected_users')}
- li(ng-repeat="user in onlineUsersArray")
- a(href, ng-click="gotoUser(user)")
- span.online-user(
- ng-style="{ 'background-color': 'hsl({{ getHueForUserId(user.user_id) }}, 70%, 50%)' }"
- ) {{ user.name.slice(0,1) }}
- | {{ user.name }}
-
- a.btn.btn-full-height(
- href,
- ng-if="trackChangesFeatureFlag",
- ng-class="{ active: ui.reviewPanelOpen }"
- tooltip="#{translate('review')}",
- tooltip-placement="bottom",
- ng-click="toggleReviewPanel()"
- )
- | Review
- a.btn.btn-full-height(
- href,
- ng-if="permissions.admin",
- tooltip="#{translate('share')}",
- tooltip-placement="bottom",
- ng-click="openShareProjectModal()",
- ng-controller="ShareController",
- )
- i.fa.fa-fw.fa-group
- a.btn.btn-full-height(
- href,
- ng-click="toggleHistory()",
- ng-class="{ active: (ui.view == 'history') }"
- tooltip="#{translate('recent_changes')}",
- tooltip-placement="bottom",
- )
- i.fa.fa-fw.fa-history
- a.btn.btn-full-height(
- href,
- tooltip="#{translate('chat')}",
- tooltip-placement="bottom",
- ng-class="{ active: ui.chatOpen }",
- ng-click="toggleChat()",
- ng-controller="ChatButtonController",
- ng-show="!anonymous",
- )
- i.fa.fa-fw.fa-comment(
- ng-class="{ 'bounce': unreadMessages > 0 }"
- )
- span.label.label-info(
- ng-show="unreadMessages > 0"
- ) {{ unreadMessages }}
-
-div(ng-if="shouldABTestHeaderLabels")
- div(sixpack-switch="editor-header")
- header.toolbar.toolbar-header(
- ng-cloak,
- ng-hide="state.loading"
- sixpack-default
+ span(ng-controller="PdfViewToggleController")
+ a(
+ href,
+ ng-show="ui.pdfLayout == 'flat' && fileTreeClosed",
+ tooltip="PDF",
+ tooltip-placement="bottom",
+ tooltip-append-to-body="true",
+ ng-click="togglePdfView()",
+ ng-class="{ 'active': ui.view == 'pdf' }"
)
- a.btn.btn-full-height(
- href,
- ng-click="ui.leftMenuShown = true; trackABTestConversion('menu');"
- tooltip='#{translate("menu")}',
- tooltip-placement="bottom",
- tooltip-append-to-body="true",
- sixpack-convert="editor-header"
- )
- i.fa.fa-fw.fa-bars
- a(
- href="/project"
- tooltip="#{translate('back_to_projects')}",
- tooltip-placement="bottom",
- tooltip-append-to-body="true"
- )
- i.fa.fa-fw.fa-level-up
-
- span(ng-controller="PdfViewToggleController")
- a(
- href,
- ng-show="ui.pdfLayout == 'flat' && fileTreeClosed",
- tooltip="PDF",
- tooltip-placement="bottom",
- tooltip-append-to-body="true",
- ng-click="togglePdfView()",
- ng-class="{ 'active': ui.view == 'pdf' }"
- )
- i.fa.fa-file-pdf-o
+ i.fa.fa-file-pdf-o
- .toolbar-center.project-name(ng-controller="ProjectNameController")
- span.name(
- ng-dblclick="!permissions.admin || startRenaming()",
- ng-show="!state.renaming"
- ) {{ project.name }}
+ .toolbar-center.project-name(ng-controller="ProjectNameController")
+ span.name(
+ ng-dblclick="!permissions.admin || startRenaming()",
+ ng-show="!state.renaming"
+ ) {{ project.name }}
- input.form-control(
- type="text"
- ng-model="inputs.name",
- ng-show="state.renaming",
- on-enter="finishRenaming()",
- ng-blur="finishRenaming()",
- select-name-when="state.renaming"
- )
-
- a.rename(
- ng-if="permissions.admin",
- href='#',
- tooltip-placement="bottom",
- tooltip="#{translate('rename')}",
- tooltip-append-to-body="true",
- ng-click="startRenaming()",
- ng-show="!state.renaming"
- )
- i.fa.fa-pencil
-
- .toolbar-right
- span.online-users(
- ng-show="onlineUsersArray.length > 0"
- ng-controller="OnlineUsersController"
- )
- span(ng-if="onlineUsersArray.length < 4")
- span.online-user(
- ng-repeat="user in onlineUsersArray",
- ng-style="{ 'background-color': 'hsl({{ getHueForUserId(user.user_id) }}, 70%, 50%)' }",
- popover="{{ user.name }}"
- popover-placement="bottom"
- popover-append-to-body="true"
- popover-trigger="mouseenter"
- ng-click="gotoUser(user)"
- ) {{ user.name.slice(0,1) }}
-
- span.dropdown(dropdown, ng-if="onlineUsersArray.length >= 4")
- span.online-user.online-user-multi(
- dropdown-toggle,
- tooltip="#{translate('connected_users')}",
- tooltip-placement="left"
- )
- strong {{ onlineUsersArray.length }}
- i.fa.fa-fw.fa-user
- ul.dropdown-menu.pull-right
- li.dropdown-header #{translate('connected_users')}
- li(ng-repeat="user in onlineUsersArray")
- a(href, ng-click="gotoUser(user)")
- span.online-user(
- ng-style="{ 'background-color': 'hsl({{ getHueForUserId(user.user_id) }}, 70%, 50%)' }"
- ) {{ user.name.slice(0,1) }}
- | {{ user.name }}
-
-
- a.btn.btn-full-height(
- href,
- ng-if="permissions.admin",
- tooltip="#{translate('share')}",
- tooltip-placement="bottom",
- ng-click="openShareProjectModal(); trackABTestConversion('share');",
- ng-controller="ShareController",
- sixpack-convert="editor-header"
- )
- i.fa.fa-fw.fa-group
- a.btn.btn-full-height(
- href,
- ng-click="toggleHistory(); trackABTestConversion('history');",
- ng-class="{ active: (ui.view == 'history') }"
- tooltip="#{translate('recent_changes')}",
- tooltip-placement="bottom",
- sixpack-convert="editor-header"
- )
- i.fa.fa-fw.fa-history
- a.btn.btn-full-height(
- href,
- tooltip="#{translate('chat')}",
- tooltip-placement="bottom",
- ng-class="{ active: ui.chatOpen }",
- ng-click="toggleChat(); trackABTestConversion('chat');",
- ng-controller="ChatButtonController",
- ng-show="!anonymous",
- sixpack-convert="editor-header"
- )
- i.fa.fa-fw.fa-comment(
- ng-class="{ 'bounce': unreadMessages > 0 }"
- )
- span.label.label-info(
- ng-show="unreadMessages > 0"
- ) {{ unreadMessages }}
-
- header.toolbar.toolbar-header.toolbar-with-labels(
- ng-cloak,
- ng-hide="state.loading"
- sixpack-when="labels"
+ input.form-control(
+ type="text"
+ ng-model="inputs.name",
+ ng-show="state.renaming",
+ on-enter="finishRenaming()",
+ ng-blur="finishRenaming()",
+ select-name-when="state.renaming"
)
- .toolbar-left
- a.btn.btn-full-height(
- href,
- ng-click="ui.leftMenuShown = true; trackABTestConversion('menu');",
- sixpack-convert="editor-header"
- )
- i.fa.fa-fw.fa-bars
- p.toolbar-label #{translate("menu")}
- a(
- href="/project"
- )
- i.fa.fa-fw.fa-level-up
- span(ng-controller="PdfViewToggleController")
- a(
- href,
- ng-show="ui.pdfLayout == 'flat' && fileTreeClosed",
- tooltip="PDF",
- tooltip-placement="bottom",
- tooltip-append-to-body="true",
- ng-click="togglePdfView()",
- ng-class="{ 'active': ui.view == 'pdf' }"
- )
- i.fa.fa-file-pdf-o
-
- .toolbar-center.project-name(ng-controller="ProjectNameController")
- span.name(
- ng-dblclick="!permissions.admin || startRenaming()",
- ng-show="!state.renaming"
- ) {{ project.name }}
-
- input.form-control(
- type="text"
- ng-model="inputs.name",
- ng-show="state.renaming",
- on-enter="finishRenaming()",
- ng-blur="finishRenaming()",
- select-name-when="state.renaming"
- )
-
- a.rename(
- ng-if="permissions.admin",
- href='#',
- tooltip-placement="bottom",
- tooltip="#{translate('rename')}",
- tooltip-append-to-body="true",
- ng-click="startRenaming()",
- ng-show="!state.renaming"
- )
- i.fa.fa-pencil
-
- .toolbar-right
- span.online-users(
- ng-show="onlineUsersArray.length > 0"
- ng-controller="OnlineUsersController"
- )
- span(ng-if="onlineUsersArray.length < 4")
- span.online-user(
- ng-repeat="user in onlineUsersArray",
- ng-style="{ 'background-color': 'hsl({{ getHueForUserId(user.user_id) }}, 70%, 50%)' }",
- popover="{{ user.name }}"
- popover-placement="bottom"
- popover-append-to-body="true"
- popover-trigger="mouseenter"
- ng-click="gotoUser(user)"
- ) {{ user.name.slice(0,1) }}
-
- span.dropdown(dropdown, ng-if="onlineUsersArray.length >= 4")
- span.online-user.online-user-multi(
- dropdown-toggle,
- tooltip="#{translate('connected_users')}",
- tooltip-placement="left"
- )
- strong {{ onlineUsersArray.length }}
- i.fa.fa-fw.fa-user
- ul.dropdown-menu.pull-right
- li.dropdown-header #{translate('connected_users')}
- li(ng-repeat="user in onlineUsersArray")
- a(href, ng-click="gotoUser(user)")
- span.online-user(
- ng-style="{ 'background-color': 'hsl({{ getHueForUserId(user.user_id) }}, 70%, 50%)' }"
- ) {{ user.name.slice(0,1) }}
- | {{ user.name }}
+ a.rename(
+ ng-if="permissions.admin",
+ href='#',
+ tooltip-placement="bottom",
+ tooltip="#{translate('rename')}",
+ tooltip-append-to-body="true",
+ ng-click="startRenaming()",
+ ng-show="!state.renaming"
+ )
+ i.fa.fa-pencil
+ .toolbar-right
+ span.online-users(
+ ng-show="onlineUsersArray.length > 0"
+ ng-controller="OnlineUsersController"
+ )
+ span(ng-if="onlineUsersArray.length < 4")
+ span.online-user(
+ ng-repeat="user in onlineUsersArray",
+ ng-style="{ 'background-color': 'hsl({{ getHueForUserId(user.user_id) }}, 70%, 50%)' }",
+ popover="{{ user.name }}"
+ popover-placement="bottom"
+ popover-append-to-body="true"
+ popover-trigger="mouseenter"
+ ng-click="gotoUser(user)"
+ ) {{ user.name.slice(0,1) }}
- a.btn.btn-full-height(
- href,
- ng-if="permissions.admin",
- ng-click="openShareProjectModal(); trackABTestConversion('share');",
- ng-controller="ShareController",
- sixpack-convert="editor-header"
+ span.dropdown(dropdown, ng-if="onlineUsersArray.length >= 4")
+ span.online-user.online-user-multi(
+ dropdown-toggle,
+ tooltip="#{translate('connected_users')}",
+ tooltip-placement="left"
)
- i.fa.fa-fw.fa-group
- p.toolbar-label #{translate("share")}
- a.btn.btn-full-height(
- href,
- ng-click="toggleHistory(); trackABTestConversion('history');",
- ng-class="{ active: (ui.view == 'history') }",
- sixpack-convert="editor-header"
- )
- i.fa.fa-fw.fa-history
- p.toolbar-label #{translate("history")}
- a.btn.btn-full-height(
- href,
- ng-class="{ active: ui.chatOpen }",
- ng-click="toggleChat(); trackABTestConversion('chat');",
- ng-controller="ChatButtonController",
- ng-show="!anonymous",
- sixpack-convert="editor-header"
- )
- i.fa.fa-fw.fa-comment(
- ng-class="{ 'bounce': unreadMessages > 0 }"
- )
- span.label.label-info(
- ng-show="unreadMessages > 0"
- ) {{ unreadMessages }}
- p.toolbar-label #{translate("chat")}
\ No newline at end of file
+ strong {{ onlineUsersArray.length }}
+ i.fa.fa-fw.fa-user
+ ul.dropdown-menu.pull-right
+ li.dropdown-header #{translate('connected_users')}
+ li(ng-repeat="user in onlineUsersArray")
+ a(href, ng-click="gotoUser(user)")
+ span.online-user(
+ ng-style="{ 'background-color': 'hsl({{ getHueForUserId(user.user_id) }}, 70%, 50%)' }"
+ ) {{ user.name.slice(0,1) }}
+ | {{ user.name }}
+
+ a.btn.btn-full-height(
+ href,
+ ng-if="trackChangesFeatureFlag",
+ ng-class="{ active: ui.reviewPanelOpen }"
+ tooltip="#{translate('review')}",
+ tooltip-placement="bottom",
+ ng-click="toggleReviewPanel()"
+ )
+ | Review
+ a.btn.btn-full-height(
+ href,
+ ng-if="permissions.admin",
+ ng-click="openShareProjectModal();",
+ ng-controller="ShareController",
+ )
+ i.fa.fa-fw.fa-group
+ p.toolbar-label #{translate("share")}
+ a.btn.btn-full-height(
+ href,
+ ng-click="toggleHistory();",
+ ng-class="{ active: (ui.view == 'history') }",
+ )
+ i.fa.fa-fw.fa-history
+ p.toolbar-label #{translate("history")}
+ a.btn.btn-full-height(
+ href,
+ ng-class="{ active: ui.chatOpen }",
+ ng-click="toggleChat();",
+ ng-controller="ChatButtonController",
+ ng-show="!anonymous",
+ )
+ i.fa.fa-fw.fa-comment(
+ ng-class="{ 'bounce': unreadMessages > 0 }"
+ )
+ span.label.label-info(
+ ng-show="unreadMessages > 0"
+ ) {{ unreadMessages }}
+ p.toolbar-label #{translate("chat")}
\ No newline at end of file
diff --git a/services/web/app/views/project/list.jade b/services/web/app/views/project/list.jade
index a6a3957720..6f1d87424a 100644
--- a/services/web/app/views/project/list.jade
+++ b/services/web/app/views/project/list.jade
@@ -21,7 +21,11 @@ block content
.content.content-alt(ng-controller="ProjectPageController")
.container
-
+
+ //- div(ng-controller="AnnouncementsController", ng-cloak)
+ //- .alert.alert-success(ng-show="dataRecived")
+ //- a(href, ng-click="openLink()") {{title}} and {{totalAnnouncements}} others
+
.row(ng-cloak)
span(ng-if="projects.length > 0")
aside.col-md-2.col-xs-3
diff --git a/services/web/app/views/user/settings.jade b/services/web/app/views/user/settings.jade
index eb5bf671fa..14d6902899 100644
--- a/services/web/app/views/user/settings.jade
+++ b/services/web/app/views/user/settings.jade
@@ -33,6 +33,12 @@ block content
)
span.small.text-primary(ng-show="settingsForm.email.$invalid && settingsForm.email.$dirty")
| #{translate("must_be_email_address")}
+ else
+ // show the email, non-editable
+ .form-group
+ label.control-label #{translate("email")}
+ div.form-control(readonly="true") #{user.email}
+
.form-group
label(for='firstName').control-label #{translate("first_name")}
input.form-control(
diff --git a/services/web/config/settings.defaults.coffee b/services/web/config/settings.defaults.coffee
index daf16ae1f4..1e858253e4 100644
--- a/services/web/config/settings.defaults.coffee
+++ b/services/web/config/settings.defaults.coffee
@@ -38,6 +38,16 @@ module.exports = settings =
port: "6379"
password: ""
+ # websessions:
+ # cluster: [
+ # {host: 'localhost', port: 7000}
+ # {host: 'localhost', port: 7001}
+ # {host: 'localhost', port: 7002}
+ # {host: 'localhost', port: 7003}
+ # {host: 'localhost', port: 7004}
+ # {host: 'localhost', port: 7005}
+ # ]
+
api:
host: "localhost"
port: "6379"
@@ -107,8 +117,8 @@ module.exports = settings =
# references:
# url: "http://localhost:3040"
notifications:
- url: "http://localhost:3042"
-
+ url: "http://localhost:3042"
+
templates:
user_id: process.env.TEMPLATES_USER_ID or "5395eb7aad1f29a88756c7f2"
showSocialButtons: false
@@ -131,13 +141,13 @@ module.exports = settings =
# this is only used if cookies are used for clsi backend
#clsiCookieKey: "clsiserver"
-
+
# Same, but with http auth credentials.
httpAuthSiteUrl: 'http://#{httpAuthUser}:#{httpAuthPass}@localhost:3000'
maxEntitiesPerProject: 2000
-
+
# Security
# --------
security:
@@ -166,12 +176,12 @@ module.exports = settings =
price: 0
features: defaultFeatures
}]
-
+
enableSubscriptions:false
# i18n
# ------
- #
+ #
i18n:
subdomainLang:
www: {lngCode:"en", url: siteUrl}
@@ -180,7 +190,7 @@ module.exports = settings =
# Spelling languages
# ------------------
#
- # You must have the corresponding aspell package installed to
+ # You must have the corresponding aspell package installed to
# be able to use a language.
languages: [
{name: "English", code: "en"},
@@ -228,7 +238,7 @@ module.exports = settings =
# analytics:
# ga:
# token: ""
- #
+ #
# ShareLaTeX's help desk is provided by tenderapp.com
# tenderUrl: ""
#
@@ -262,10 +272,10 @@ module.exports = settings =
# then set this to true to allow it to correctly detect the forwarded IP
# address and http/https protocol information.
behindProxy: false
-
+
# Cookie max age (in milliseconds). Set to false for a browser session.
cookieSessionLength: 5 * 24 * 60 * 60 * 1000 # 5 days
-
+
# Should we allow access to any page without logging in? This includes
# public projects, /learn, /templates, about pages, etc.
allowPublicAccess: if process.env["SHARELATEX_ALLOW_PUBLIC_ACCESS"] == 'true' then true else false
@@ -273,10 +283,10 @@ module.exports = settings =
# Use a single compile directory for all users in a project
# (otherwise each user has their own directory)
# disablePerUserCompiles: true
-
+
# Maximum size of text documents in the real-time editing system.
max_doc_length: 2 * 1024 * 1024 # 2mb
-
+
# Internal configs
# ----------------
path:
@@ -285,11 +295,11 @@ module.exports = settings =
# them to disk here).
dumpFolder: Path.resolve __dirname + "/../data/dumpFolder"
uploadFolder: Path.resolve __dirname + "/../data/uploads"
-
+
# Automatic Snapshots
# -------------------
automaticSnapshots:
- # How long should we wait after the user last edited to
+ # How long should we wait after the user last edited to
# take a snapshot?
waitTimeAfterLastEdit: 5 * minutes
# Even if edits are still taking place, this is maximum
@@ -305,13 +315,13 @@ module.exports = settings =
# user: ""
# password: ""
# projectId: ""
-
+
appName: "ShareLaTeX (Community Edition)"
adminEmail: "placeholder@example.com"
nav:
title: "ShareLaTeX Community Edition"
-
+
left_footer: [{
text: "Powered by ShareLaTeX © 2016"
}]
@@ -377,11 +387,11 @@ module.exports = settings =
"/templates/index": "/templates/"
proxyUrls: {}
-
+
reloadModuleViewsOnEachRequest: true
domainLicences: [
-
+
]
sixpack:
@@ -390,12 +400,12 @@ module.exports = settings =
# ----------
-
+
# LDAP
# ----------
# Settings below use a working LDAP test server kindly provided by forumsys.com
# When testing with forumsys.com use username = einstein and password = password
-
+
# ldap :
# host: 'ldap://ldap.forumsys.com'
# dn: 'uid=:userKey,dc=example,dc=com'
@@ -406,13 +416,13 @@ module.exports = settings =
# placeholder: 'email@example.com'
# emailAtt: 'mail'
# anonymous: false
- # adminDN: 'cn=read-only-admin,dc=example,dc=com'
+ # adminDN: 'cn=read-only-admin,dc=example,dc=com'
# adminPW: 'password'
# starttls: true
# tlsOptions:
# rejectUnauthorized: false
# ca: ['/etc/ldap/ca_certs.pem']
-
+
#templateLinks: [{
# name : "CV projects",
# url : "/templates/cv"
@@ -420,5 +430,3 @@ module.exports = settings =
# name : "all projects",
# url: "/templates/all"
#}]
-
-
diff --git a/services/web/npm-shrinkwrap.json b/services/web/npm-shrinkwrap.json
index 0d3f663c33..04fdfc0142 100644
--- a/services/web/npm-shrinkwrap.json
+++ b/services/web/npm-shrinkwrap.json
@@ -274,12 +274,12 @@
"dependencies": {
"bytes": {
"version": "2.4.0",
- "from": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz",
+ "from": "bytes@2.4.0",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz"
},
"content-type": {
"version": "1.0.2",
- "from": "https://registry.npmjs.org/content-type/-/content-type-1.0.2.tgz",
+ "from": "content-type@~1.0.1",
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.2.tgz"
},
"debug": {
@@ -328,7 +328,7 @@
},
"on-finished": {
"version": "2.3.0",
- "from": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
+ "from": "on-finished@~2.3.0",
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
"dependencies": {
"ee-first": {
@@ -345,7 +345,7 @@
},
"raw-body": {
"version": "2.1.7",
- "from": "https://registry.npmjs.org/raw-body/-/raw-body-2.1.7.tgz",
+ "from": "raw-body@~2.1.5",
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.1.7.tgz",
"dependencies": {
"unpipe": {
@@ -357,7 +357,7 @@
},
"type-is": {
"version": "1.6.13",
- "from": "https://registry.npmjs.org/type-is/-/type-is-1.6.13.tgz",
+ "from": "type-is@~1.6.10",
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.13.tgz",
"dependencies": {
"media-typer": {
@@ -387,26 +387,42 @@
"resolved": "https://registry.npmjs.org/bufferedstream/-/bufferedstream-1.6.0.tgz"
},
"connect-redis": {
- "version": "2.3.0",
- "from": "https://registry.npmjs.org/connect-redis/-/connect-redis-2.3.0.tgz",
- "resolved": "https://registry.npmjs.org/connect-redis/-/connect-redis-2.3.0.tgz",
+ "version": "3.1.0",
+ "from": "connect-redis@3.1.0",
+ "resolved": "https://registry.npmjs.org/connect-redis/-/connect-redis-3.1.0.tgz",
"dependencies": {
"debug": {
- "version": "1.0.4",
- "from": "https://registry.npmjs.org/debug/-/debug-1.0.4.tgz",
- "resolved": "https://registry.npmjs.org/debug/-/debug-1.0.4.tgz",
+ "version": "2.3.0",
+ "from": "https://registry.npmjs.org/debug/-/debug-2.3.0.tgz",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.3.0.tgz",
"dependencies": {
"ms": {
- "version": "0.6.2",
- "from": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz",
- "resolved": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz"
+ "version": "0.7.2",
+ "from": "ms@0.7.2"
}
}
},
"redis": {
- "version": "0.12.1",
- "from": "https://registry.npmjs.org/redis/-/redis-0.12.1.tgz",
- "resolved": "https://registry.npmjs.org/redis/-/redis-0.12.1.tgz"
+ "version": "2.6.3",
+ "from": "https://registry.npmjs.org/redis/-/redis-2.6.3.tgz",
+ "resolved": "https://registry.npmjs.org/redis/-/redis-2.6.3.tgz",
+ "dependencies": {
+ "double-ended-queue": {
+ "version": "2.1.0-0",
+ "from": "https://registry.npmjs.org/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz",
+ "resolved": "https://registry.npmjs.org/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz"
+ },
+ "redis-commands": {
+ "version": "1.3.0",
+ "from": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.3.0.tgz",
+ "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.3.0.tgz"
+ },
+ "redis-parser": {
+ "version": "2.1.1",
+ "from": "https://registry.npmjs.org/redis-parser/-/redis-parser-2.1.1.tgz",
+ "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-2.1.1.tgz"
+ }
+ }
}
}
},
@@ -470,7 +486,7 @@
},
"json-stringify-safe": {
"version": "5.0.1",
- "from": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
+ "from": "json-stringify-safe@~5.0.0",
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz"
}
}
@@ -504,7 +520,7 @@
"dependencies": {
"cookie": {
"version": "0.3.1",
- "from": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz",
+ "from": "cookie@0.3.1",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz"
},
"cookie-signature": {
@@ -616,7 +632,7 @@
},
"content-type": {
"version": "1.0.2",
- "from": "https://registry.npmjs.org/content-type/-/content-type-1.0.2.tgz",
+ "from": "content-type@~1.0.1",
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.2.tgz"
},
"cookie": {
@@ -631,7 +647,7 @@
},
"debug": {
"version": "2.2.0",
- "from": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz",
+ "from": "debug@~2.2.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz",
"dependencies": {
"ms": {
@@ -685,7 +701,7 @@
},
"on-finished": {
"version": "2.3.0",
- "from": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
+ "from": "on-finished@~2.3.0",
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
"dependencies": {
"ee-first": {
@@ -829,7 +845,7 @@
},
"type-is": {
"version": "1.6.13",
- "from": "https://registry.npmjs.org/type-is/-/type-is-1.6.13.tgz",
+ "from": "type-is@~1.6.10",
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.13.tgz",
"dependencies": {
"media-typer": {
@@ -864,68 +880,66 @@
}
},
"express-session": {
- "version": "1.11.3",
- "from": "https://registry.npmjs.org/express-session/-/express-session-1.11.3.tgz",
- "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.11.3.tgz",
+ "version": "1.14.2",
+ "from": "express-session@1.14.2",
+ "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.14.2.tgz",
"dependencies": {
"cookie": {
- "version": "0.1.3",
- "from": "https://registry.npmjs.org/cookie/-/cookie-0.1.3.tgz",
- "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.1.3.tgz"
+ "version": "0.3.1",
+ "from": "cookie@0.3.1",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz"
},
"cookie-signature": {
"version": "1.0.6",
- "from": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
- "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz"
+ "from": "cookie-signature@1.0.6"
},
"crc": {
- "version": "3.3.0",
- "from": "https://registry.npmjs.org/crc/-/crc-3.3.0.tgz",
- "resolved": "https://registry.npmjs.org/crc/-/crc-3.3.0.tgz"
+ "version": "3.4.1",
+ "from": "crc@3.4.1",
+ "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.1.tgz"
},
"debug": {
"version": "2.2.0",
- "from": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz",
+ "from": "debug@2.2.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz",
"dependencies": {
"ms": {
"version": "0.7.1",
- "from": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz",
+ "from": "ms@0.7.1",
"resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz"
}
}
},
"depd": {
- "version": "1.0.1",
- "from": "https://registry.npmjs.org/depd/-/depd-1.0.1.tgz",
- "resolved": "https://registry.npmjs.org/depd/-/depd-1.0.1.tgz"
+ "version": "1.1.0",
+ "from": "depd@1.1.0"
},
"on-headers": {
"version": "1.0.1",
- "from": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz",
- "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz"
+ "from": "on-headers@1.0.1"
},
"parseurl": {
"version": "1.3.1",
- "from": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.1.tgz",
- "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.1.tgz"
+ "from": "parseurl@1.3.1"
},
"uid-safe": {
- "version": "2.0.0",
- "from": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.0.0.tgz",
- "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.0.0.tgz",
+ "version": "2.1.3",
+ "from": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.3.tgz",
+ "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.3.tgz",
"dependencies": {
"base64-url": {
- "version": "1.2.1",
- "from": "https://registry.npmjs.org/base64-url/-/base64-url-1.2.1.tgz",
- "resolved": "https://registry.npmjs.org/base64-url/-/base64-url-1.2.1.tgz"
+ "version": "1.3.3",
+ "from": "base64-url@1.3.3"
+ },
+ "random-bytes": {
+ "version": "1.0.0",
+ "from": "random-bytes@1.0.0"
}
}
},
"utils-merge": {
"version": "1.0.0",
- "from": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz",
- "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz"
+ "from": "utils-merge@1.0.0"
}
}
},
@@ -1166,6 +1180,53 @@
}
}
},
+ "ioredis": {
+ "version": "2.4.0",
+ "from": "https://registry.npmjs.org/ioredis/-/ioredis-2.4.0.tgz",
+ "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-2.4.0.tgz",
+ "dependencies": {
+ "bluebird": {
+ "version": "3.4.6",
+ "from": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.6.tgz",
+ "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.6.tgz"
+ },
+ "cluster-key-slot": {
+ "version": "1.0.8",
+ "from": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.0.8.tgz",
+ "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.0.8.tgz"
+ },
+ "debug": {
+ "version": "2.3.0",
+ "from": "https://registry.npmjs.org/debug/-/debug-2.3.0.tgz",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.3.0.tgz",
+ "dependencies": {
+ "ms": {
+ "version": "0.7.2",
+ "from": "ms@0.7.2"
+ }
+ }
+ },
+ "double-ended-queue": {
+ "version": "2.1.0-0",
+ "from": "https://registry.npmjs.org/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz",
+ "resolved": "https://registry.npmjs.org/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz"
+ },
+ "flexbuffer": {
+ "version": "0.0.6",
+ "from": "flexbuffer@0.0.6"
+ },
+ "redis-commands": {
+ "version": "1.3.0",
+ "from": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.3.0.tgz",
+ "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.3.0.tgz"
+ },
+ "redis-parser": {
+ "version": "1.3.0",
+ "from": "https://registry.npmjs.org/redis-parser/-/redis-parser-1.3.0.tgz",
+ "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-1.3.0.tgz"
+ }
+ }
+ },
"jade": {
"version": "1.3.1",
"from": "https://registry.npmjs.org/jade/-/jade-1.3.1.tgz",
@@ -1602,7 +1663,7 @@
},
"logger-sharelatex": {
"version": "1.3.1",
- "from": "git+https://github.com/sharelatex/logger-sharelatex.git#bf413ec621a000cf0e08c939de38d5e24541a08c",
+ "from": "logger-sharelatex@git+https://github.com/sharelatex/logger-sharelatex.git#bf413ec621a000cf0e08c939de38d5e24541a08c",
"resolved": "git+https://github.com/sharelatex/logger-sharelatex.git#bf413ec621a000cf0e08c939de38d5e24541a08c",
"dependencies": {
"bunyan": {
@@ -1783,7 +1844,7 @@
"dependencies": {
"debug": {
"version": "2.2.0",
- "from": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz",
+ "from": "debug@2.2.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz",
"dependencies": {
"ms": {
@@ -1812,7 +1873,7 @@
},
"metrics-sharelatex": {
"version": "1.3.0",
- "from": "git+https://github.com/sharelatex/metrics-sharelatex.git#080c4aeb696edcd5d6d86f202f2c528f0661d7a6",
+ "from": "metrics-sharelatex@git+https://github.com/sharelatex/metrics-sharelatex.git#080c4aeb696edcd5d6d86f202f2c528f0661d7a6",
"resolved": "git+https://github.com/sharelatex/metrics-sharelatex.git#080c4aeb696edcd5d6d86f202f2c528f0661d7a6",
"dependencies": {
"coffee-script": {
@@ -2535,32 +2596,32 @@
},
"passport-ldapauth": {
"version": "0.6.0",
- "from": "passport-ldapauth@*",
+ "from": "https://registry.npmjs.org/passport-ldapauth/-/passport-ldapauth-0.6.0.tgz",
"resolved": "https://registry.npmjs.org/passport-ldapauth/-/passport-ldapauth-0.6.0.tgz",
"dependencies": {
"passport-strategy": {
"version": "1.0.0",
- "from": "passport-strategy@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz",
"resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz"
},
"ldapauth-fork": {
"version": "2.5.3",
- "from": "ldapauth-fork@>=2.5.0 <2.6.0",
+ "from": "https://registry.npmjs.org/ldapauth-fork/-/ldapauth-fork-2.5.3.tgz",
"resolved": "https://registry.npmjs.org/ldapauth-fork/-/ldapauth-fork-2.5.3.tgz",
"dependencies": {
"bcryptjs": {
"version": "2.3.0",
- "from": "bcryptjs@2.3.0",
+ "from": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.3.0.tgz",
"resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.3.0.tgz"
},
"lru-cache": {
"version": "3.2.0",
- "from": "lru-cache@3.2.0",
+ "from": "https://registry.npmjs.org/lru-cache/-/lru-cache-3.2.0.tgz",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-3.2.0.tgz",
"dependencies": {
"pseudomap": {
"version": "1.0.2",
- "from": "pseudomap@>=1.0.1 <2.0.0",
+ "from": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
"resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz"
}
}
@@ -2581,6 +2642,89 @@
}
}
},
+ "passport-saml": {
+ "version": "0.15.0",
+ "from": "passport-saml@",
+ "resolved": "https://registry.npmjs.org/passport-saml/-/passport-saml-0.15.0.tgz",
+ "dependencies": {
+ "passport-strategy": {
+ "version": "1.0.0",
+ "from": "passport-strategy@*"
+ },
+ "q": {
+ "version": "1.1.2",
+ "from": "q@1.1.x"
+ },
+ "xml2js": {
+ "version": "0.4.17",
+ "from": "xml2js@0.4.x",
+ "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.17.tgz",
+ "dependencies": {
+ "sax": {
+ "version": "1.2.1",
+ "from": "sax@>=0.6.0"
+ },
+ "xmlbuilder": {
+ "version": "4.2.1",
+ "from": "xmlbuilder@^4.1.0",
+ "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-4.2.1.tgz"
+ }
+ }
+ },
+ "xml-crypto": {
+ "version": "0.8.4",
+ "from": "xml-crypto@0.8.x",
+ "dependencies": {
+ "xmldom": {
+ "version": "0.1.19",
+ "from": "xmldom@=0.1.19"
+ },
+ "xpath.js": {
+ "version": "1.0.6",
+ "from": "xpath.js@>=0.0.3"
+ }
+ }
+ },
+ "xmldom": {
+ "version": "0.1.22",
+ "from": "xmldom@0.1.x"
+ },
+ "xmlbuilder": {
+ "version": "2.5.2",
+ "from": "xmlbuilder@2.5.x",
+ "dependencies": {
+ "lodash": {
+ "version": "3.2.0",
+ "from": "lodash@~3.2.0"
+ }
+ }
+ },
+ "xml-encryption": {
+ "version": "0.7.4",
+ "from": "xml-encryption@~0.7",
+ "dependencies": {
+ "ejs": {
+ "version": "0.8.8",
+ "from": "ejs@~0.8.3"
+ },
+ "async": {
+ "version": "0.2.10",
+ "from": "async@~0.2.7"
+ },
+ "xpath": {
+ "version": "0.0.5",
+ "from": "xpath@0.0.5",
+ "resolved": "https://registry.npmjs.org/xpath/-/xpath-0.0.5.tgz"
+ },
+ "node-forge": {
+ "version": "0.2.24",
+ "from": "node-forge@0.2.24",
+ "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.2.24.tgz"
+ }
+ }
+ }
+ }
+ },
"pg": {
"version": "6.0.3",
"from": "https://registry.npmjs.org/pg/-/pg-6.0.3.tgz",
@@ -3430,7 +3574,7 @@
},
"json-stringify-safe": {
"version": "5.0.1",
- "from": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
+ "from": "json-stringify-safe@~5.0.0",
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz"
},
"mime-types": {
@@ -3462,7 +3606,7 @@
},
"stringstream": {
"version": "0.0.5",
- "from": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz",
+ "from": "stringstream@~0.0.4",
"resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz"
},
"tough-cookie": {
@@ -3472,7 +3616,7 @@
},
"tunnel-agent": {
"version": "0.4.3",
- "from": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz",
+ "from": "tunnel-agent@~0.4.0",
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz"
}
}
@@ -3558,7 +3702,7 @@
},
"depd": {
"version": "1.1.0",
- "from": "https://registry.npmjs.org/depd/-/depd-1.1.0.tgz",
+ "from": "depd@~1.1.0",
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.0.tgz"
},
"dottie": {
@@ -3656,7 +3800,7 @@
},
"settings-sharelatex": {
"version": "1.0.0",
- "from": "git+https://github.com/sharelatex/settings-sharelatex.git#cbc5e41c1dbe6789721a14b3fdae05bf22546559",
+ "from": "settings-sharelatex@git+https://github.com/sharelatex/settings-sharelatex.git#cbc5e41c1dbe6789721a14b3fdae05bf22546559",
"resolved": "git+https://github.com/sharelatex/settings-sharelatex.git#cbc5e41c1dbe6789721a14b3fdae05bf22546559",
"dependencies": {
"coffee-script": {
diff --git a/services/web/package.json b/services/web/package.json
index d302cc30d8..cfd2379f73 100644
--- a/services/web/package.json
+++ b/services/web/package.json
@@ -17,17 +17,18 @@
"bcrypt": "0.8.3",
"body-parser": "^1.13.1",
"bufferedstream": "1.6.0",
- "connect-redis": "2.3.0",
+ "connect-redis": "^3.1.0",
"contentful": "^3.3.14",
"cookie": "^0.2.3",
"cookie-parser": "1.3.5",
"csurf": "^1.8.3",
"dateformat": "1.0.4-1.2.3",
"express": "4.13.0",
- "express-session": "1.11.3",
+ "express-session": "^1.14.2",
"grunt": "^0.4.5",
"heapdump": "^0.3.7",
"http-proxy": "^1.8.1",
+ "ioredis": "^2.4.0",
"jade": "~1.3.1",
"ldapjs": "^1.0.0",
"lodash": "^4.13.1",
@@ -49,8 +50,6 @@
"passport": "^0.3.2",
"passport-ldapauth": "^0.6.0",
"passport-local": "^1.0.0",
- "pg": "^6.0.3",
- "pg-hstore": "^2.3.2",
"redback": "0.4.0",
"redis": "0.10.1",
"redis-sharelatex": "0.0.9",
@@ -64,7 +63,8 @@
"temp": "^0.8.3",
"underscore": "1.6.0",
"v8-profiler": "^5.2.3",
- "xml2js": "0.2.0"
+ "xml2js": "0.2.0",
+ "passport-saml": "^0.15.0"
},
"devDependencies": {
"bunyan": "0.22.1",
diff --git a/services/web/public/coffee/ide.coffee b/services/web/public/coffee/ide.coffee
index a835221f49..370f144ee1 100644
--- a/services/web/public/coffee/ide.coffee
+++ b/services/web/public/coffee/ide.coffee
@@ -91,23 +91,6 @@ define [
if value?
localStorage "ui.reviewPanelOpen.#{window.project_id}", value
- # Only run the header AB test for newly registered users.
- _abTestStartDate = new Date(Date.UTC(2016, 8, 28))
- _userSignUpDate = new Date(window.user.signUpDate)
-
- $scope.shouldABTestHeaderLabels = _userSignUpDate > _abTestStartDate
- $scope.headerLabelsABVariant = ""
-
- if ($scope.shouldABTestHeaderLabels)
- sixpack.participate "editor-header", [ "default", "labels"], (chosenVariation) ->
- $scope.headerLabelsABVariant = chosenVariation
-
- $scope.trackABTestConversion = (headerItem) ->
- event_tracking.sendMB "header-ab-conversion", {
- headerItem: headerItem,
- variant: $scope.headerLabelsABVariant
- }
-
# Tracking code.
$scope.$watch "ui.view", (newView, oldView) ->
if newView? and newView != "editor" and newView != "pdf"
diff --git a/services/web/public/coffee/ide/editor/Document.coffee b/services/web/public/coffee/ide/editor/Document.coffee
index 9226473387..17b1d9e28f 100644
--- a/services/web/public/coffee/ide/editor/Document.coffee
+++ b/services/web/public/coffee/ide/editor/Document.coffee
@@ -310,7 +310,7 @@ define [
_onError: (error, meta = {}) ->
meta.doc_id = @doc_id
- console.error "ShareJS error", error, meta
+ sl_console.log "ShareJS error", error, meta
ga?('send', 'event', 'error', "shareJsError", "#{error.message} - #{@ide.socket.socket.transport.name}" )
@doc?.clearInflightAndPendingOps()
@trigger "error", error, meta
diff --git a/services/web/public/coffee/ide/editor/directives/aceEditor/undo/UndoManager.coffee b/services/web/public/coffee/ide/editor/directives/aceEditor/undo/UndoManager.coffee
index ba06c3eb50..a4348bed98 100644
--- a/services/web/public/coffee/ide/editor/directives/aceEditor/undo/UndoManager.coffee
+++ b/services/web/public/coffee/ide/editor/directives/aceEditor/undo/UndoManager.coffee
@@ -207,16 +207,19 @@ define [
return doc.split("\n")
_aceDeltaSetsToSimpleDeltaSets: (aceDeltaSets, docLines) ->
+ simpleDeltaSets = []
for deltaSet in aceDeltaSets
- simpleDeltas = []
- for delta in deltaSet.deltas
- simpleDeltas.push @_aceDeltaToSimpleDelta(delta, docLines)
- docLines = @_applyAceDeltasToDocLines([delta], docLines)
- {
- deltas: simpleDeltas
- group: deltaSet.group
- }
-
+ if deltaSet.group == "doc" # ignore fold changes
+ simpleDeltas = []
+ for delta in deltaSet.deltas
+ simpleDeltas.push @_aceDeltaToSimpleDelta(delta, docLines)
+ docLines = @_applyAceDeltasToDocLines([delta], docLines)
+ simpleDeltaSets.push {
+ deltas: simpleDeltas
+ group: deltaSet.group
+ }
+ return simpleDeltaSets
+
_simpleDeltaSetsToAceDeltaSets: (simpleDeltaSets, docLines) ->
for deltaSet in simpleDeltaSets
aceDeltas = []
diff --git a/services/web/public/coffee/main.coffee b/services/web/public/coffee/main.coffee
index 60cc38ae6a..471870f280 100644
--- a/services/web/public/coffee/main.coffee
+++ b/services/web/public/coffee/main.coffee
@@ -14,6 +14,7 @@ define [
"main/subscription-dashboard"
"main/new-subscription"
"main/annual-upgrade"
+ "main/announcements"
"main/register-users"
"main/subscription/group-subscription-invite-controller"
"main/contact-us"
diff --git a/services/web/public/coffee/main/announcements.coffee b/services/web/public/coffee/main/announcements.coffee
new file mode 100644
index 0000000000..b0960bcc09
--- /dev/null
+++ b/services/web/public/coffee/main/announcements.coffee
@@ -0,0 +1,20 @@
+define [
+ "base"
+], (App) ->
+ App.controller "AnnouncementsController", ($scope, $http, event_tracking, $window) ->
+
+ $scope.dataRecived = false
+ announcement = null
+ $http.get("/announcements").success (announcements) ->
+ if announcements?[0]?
+ announcement = announcements[0]
+ $scope.title = announcement.title
+ $scope.totalAnnouncements = announcements.length
+ $scope.dataRecived = true
+
+ dismissannouncement = ->
+ event_tracking.sendMB "announcement-alert-dismissed", {blogPostId:announcement.id}
+
+ $scope.openLink = ->
+ dismissannouncement()
+ $window.location.href = announcement.url
diff --git a/services/web/public/coffee/main/event.coffee b/services/web/public/coffee/main/event.coffee
index b2847bc5a0..b788057b77 100644
--- a/services/web/public/coffee/main/event.coffee
+++ b/services/web/public/coffee/main/event.coffee
@@ -53,16 +53,6 @@ define [
@sendMB key, segmentation
}
- # App.directive "countlyTrack", () ->
- # return {
- # restrict: "A"
- # scope: false,
- # link: (scope, el, attrs) ->
- # eventKey = attrs.countlyTrack
- # if (eventKey?)
- # el.on "click", () ->
- # console.log eventKey
- # }
#header
$('.navbar a').on "click", (e)->
diff --git a/services/web/public/coffee/main/project-list/project-list.coffee b/services/web/public/coffee/main/project-list/project-list.coffee
index 39ce68043f..431c24ada7 100644
--- a/services/web/public/coffee/main/project-list/project-list.coffee
+++ b/services/web/public/coffee/main/project-list/project-list.coffee
@@ -99,7 +99,7 @@ define [
visible = true
# Only show if it matches any search text
if $scope.searchText.value? and $scope.searchText.value != ""
- if !project.name.toLowerCase().match($scope.searchText.value.toLowerCase())
+ if project.name.toLowerCase().indexOf($scope.searchText.value.toLowerCase()) == -1
visible = false
# Only show if it matches the selected tag
if $scope.filter == "tag" and selectedTag? and project.id not in selectedTag.project_ids
diff --git a/services/web/public/js/ace-1.2.5/worker-latex.js b/services/web/public/js/ace-1.2.5/worker-latex.js
index 20c377dc83..bdf11276d4 100644
--- a/services/web/public/js/ace-1.2.5/worker-latex.js
+++ b/services/web/public/js/ace-1.2.5/worker-latex.js
@@ -1813,7 +1813,7 @@ var CheckEnvironments = function (Environments, ErrorReporter) {
var verbatimRanges = [];
for (var i = 0, len = Environments.length; i < len; i++) {
var name = Environments[i].name ;
- if (name && name.match(/^(verbatim|boxedverbatim|lstlisting)$/)) {
+ if (name && name.match(/^(verbatim|boxedverbatim|lstlisting|minted)$/)) {
Environments[i].verbatim = true;
}
}
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/.gitattributes b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/.gitattributes
new file mode 100644
index 0000000000..556f8c827b
--- /dev/null
+++ b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/.gitattributes
@@ -0,0 +1 @@
+* binary
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/78-EUC-H.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/78-EUC-H.bcmap
new file mode 100644
index 0000000000..2655fc70ae
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/78-EUC-H.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/78-EUC-V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/78-EUC-V.bcmap
new file mode 100644
index 0000000000..f1ed853828
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/78-EUC-V.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/78-H.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/78-H.bcmap
new file mode 100644
index 0000000000..39e89d3339
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/78-H.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/78-RKSJ-H.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/78-RKSJ-H.bcmap
new file mode 100644
index 0000000000..e4167cb51f
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/78-RKSJ-H.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/78-RKSJ-V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/78-RKSJ-V.bcmap
new file mode 100644
index 0000000000..50b1646e94
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/78-RKSJ-V.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/78-V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/78-V.bcmap
new file mode 100644
index 0000000000..d7af99b5e2
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/78-V.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/78ms-RKSJ-H.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/78ms-RKSJ-H.bcmap
new file mode 100644
index 0000000000..37077d01e2
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/78ms-RKSJ-H.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/78ms-RKSJ-V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/78ms-RKSJ-V.bcmap
new file mode 100644
index 0000000000..acf23231ae
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/78ms-RKSJ-V.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/83pv-RKSJ-H.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/83pv-RKSJ-H.bcmap
new file mode 100644
index 0000000000..2359bc529d
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/83pv-RKSJ-H.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/90ms-RKSJ-H.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/90ms-RKSJ-H.bcmap
new file mode 100644
index 0000000000..af8293829c
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/90ms-RKSJ-H.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/90ms-RKSJ-V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/90ms-RKSJ-V.bcmap
new file mode 100644
index 0000000000..780549de19
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/90ms-RKSJ-V.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/90msp-RKSJ-H.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/90msp-RKSJ-H.bcmap
new file mode 100644
index 0000000000..bfd3119c62
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/90msp-RKSJ-H.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/90msp-RKSJ-V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/90msp-RKSJ-V.bcmap
new file mode 100644
index 0000000000..25ef14ab4a
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/90msp-RKSJ-V.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/90pv-RKSJ-H.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/90pv-RKSJ-H.bcmap
new file mode 100644
index 0000000000..02f713bb83
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/90pv-RKSJ-H.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/90pv-RKSJ-V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/90pv-RKSJ-V.bcmap
new file mode 100644
index 0000000000..d08e0cc5d9
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/90pv-RKSJ-V.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Add-H.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Add-H.bcmap
new file mode 100644
index 0000000000..59442acafb
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Add-H.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Add-RKSJ-H.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Add-RKSJ-H.bcmap
new file mode 100644
index 0000000000..a3065e441a
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Add-RKSJ-H.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Add-RKSJ-V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Add-RKSJ-V.bcmap
new file mode 100644
index 0000000000..040014cfc0
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Add-RKSJ-V.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Add-V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Add-V.bcmap
new file mode 100644
index 0000000000..2f816d320f
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Add-V.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-CNS1-0.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-CNS1-0.bcmap
new file mode 100644
index 0000000000..88ec04af49
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-CNS1-0.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-CNS1-1.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-CNS1-1.bcmap
new file mode 100644
index 0000000000..03a501477c
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-CNS1-1.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-CNS1-2.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-CNS1-2.bcmap
new file mode 100644
index 0000000000..2aa95141f9
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-CNS1-2.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-CNS1-3.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-CNS1-3.bcmap
new file mode 100644
index 0000000000..86d8b8c79c
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-CNS1-3.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-CNS1-4.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-CNS1-4.bcmap
new file mode 100644
index 0000000000..f50fc6c14e
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-CNS1-4.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-CNS1-5.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-CNS1-5.bcmap
new file mode 100644
index 0000000000..6caf4a8314
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-CNS1-5.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-CNS1-6.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-CNS1-6.bcmap
new file mode 100644
index 0000000000..b77fb0705c
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-CNS1-6.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-CNS1-UCS2.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-CNS1-UCS2.bcmap
new file mode 100644
index 0000000000..69d79a2c2c
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-CNS1-UCS2.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-GB1-0.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-GB1-0.bcmap
new file mode 100644
index 0000000000..36101083fa
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-GB1-0.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-GB1-1.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-GB1-1.bcmap
new file mode 100644
index 0000000000..707bb1065c
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-GB1-1.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-GB1-2.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-GB1-2.bcmap
new file mode 100644
index 0000000000..f7648cc3ff
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-GB1-2.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-GB1-3.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-GB1-3.bcmap
new file mode 100644
index 0000000000..852145890e
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-GB1-3.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-GB1-4.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-GB1-4.bcmap
new file mode 100644
index 0000000000..e40c63ab1e
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-GB1-4.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-GB1-5.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-GB1-5.bcmap
new file mode 100644
index 0000000000..d7623b5002
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-GB1-5.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-GB1-UCS2.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-GB1-UCS2.bcmap
new file mode 100644
index 0000000000..7586525936
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-GB1-UCS2.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-Japan1-0.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-Japan1-0.bcmap
new file mode 100644
index 0000000000..f0e94ec196
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-Japan1-0.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-Japan1-1.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-Japan1-1.bcmap
new file mode 100644
index 0000000000..dad42c5ad7
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-Japan1-1.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-Japan1-2.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-Japan1-2.bcmap
new file mode 100644
index 0000000000..090819a064
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-Japan1-2.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-Japan1-3.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-Japan1-3.bcmap
new file mode 100644
index 0000000000..087dfc1558
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-Japan1-3.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-Japan1-4.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-Japan1-4.bcmap
new file mode 100644
index 0000000000..46aa9bffe5
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-Japan1-4.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-Japan1-5.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-Japan1-5.bcmap
new file mode 100644
index 0000000000..5b4b65cc62
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-Japan1-5.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-Japan1-6.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-Japan1-6.bcmap
new file mode 100644
index 0000000000..e77d699ab6
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-Japan1-6.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-Japan1-UCS2.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-Japan1-UCS2.bcmap
new file mode 100644
index 0000000000..128a141077
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-Japan1-UCS2.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-Korea1-0.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-Korea1-0.bcmap
new file mode 100644
index 0000000000..cef1a99851
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-Korea1-0.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-Korea1-1.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-Korea1-1.bcmap
new file mode 100644
index 0000000000..11ffa36df8
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-Korea1-1.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-Korea1-2.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-Korea1-2.bcmap
new file mode 100644
index 0000000000..3172308c79
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-Korea1-2.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-Korea1-UCS2.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-Korea1-UCS2.bcmap
new file mode 100644
index 0000000000..f3371c0cbd
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Adobe-Korea1-UCS2.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/B5-H.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/B5-H.bcmap
new file mode 100644
index 0000000000..beb4d22810
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/B5-H.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/B5-V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/B5-V.bcmap
new file mode 100644
index 0000000000..2d4f87d503
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/B5-V.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/B5pc-H.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/B5pc-H.bcmap
new file mode 100644
index 0000000000..ce0013167f
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/B5pc-H.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/B5pc-V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/B5pc-V.bcmap
new file mode 100644
index 0000000000..73b99ff2fb
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/B5pc-V.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/CNS-EUC-H.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/CNS-EUC-H.bcmap
new file mode 100644
index 0000000000..61d1d0cb00
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/CNS-EUC-H.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/CNS-EUC-V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/CNS-EUC-V.bcmap
new file mode 100644
index 0000000000..1a393a51e0
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/CNS-EUC-V.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/CNS1-H.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/CNS1-H.bcmap
new file mode 100644
index 0000000000..f738e218ae
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/CNS1-H.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/CNS1-V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/CNS1-V.bcmap
new file mode 100644
index 0000000000..9c3169f0d9
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/CNS1-V.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/CNS2-H.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/CNS2-H.bcmap
new file mode 100644
index 0000000000..c89b3527fe
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/CNS2-H.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/CNS2-V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/CNS2-V.bcmap
new file mode 100644
index 0000000000..7588cec83e
--- /dev/null
+++ b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/CNS2-V.bcmap
@@ -0,0 +1,3 @@
+àRCopyright 1990-2009 Adobe Systems Incorporated.
+All rights reserved.
+See ./LICENSEáCNS2-H
\ No newline at end of file
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/ETHK-B5-H.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/ETHK-B5-H.bcmap
new file mode 100644
index 0000000000..cb29415de4
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/ETHK-B5-H.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/ETHK-B5-V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/ETHK-B5-V.bcmap
new file mode 100644
index 0000000000..f09aec6318
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/ETHK-B5-V.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/ETen-B5-H.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/ETen-B5-H.bcmap
new file mode 100644
index 0000000000..c2d77462d2
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/ETen-B5-H.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/ETen-B5-V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/ETen-B5-V.bcmap
new file mode 100644
index 0000000000..89bff159ec
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/ETen-B5-V.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/ETenms-B5-H.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/ETenms-B5-H.bcmap
new file mode 100644
index 0000000000..a7d69db5e3
--- /dev/null
+++ b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/ETenms-B5-H.bcmap
@@ -0,0 +1,3 @@
+àRCopyright 1990-2009 Adobe Systems Incorporated.
+All rights reserved.
+See ./LICENSEá ETen-B5-H` ^
\ No newline at end of file
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/ETenms-B5-V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/ETenms-B5-V.bcmap
new file mode 100644
index 0000000000..adc5d618d6
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/ETenms-B5-V.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/EUC-H.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/EUC-H.bcmap
new file mode 100644
index 0000000000..e92ea5b3b9
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/EUC-H.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/EUC-V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/EUC-V.bcmap
new file mode 100644
index 0000000000..7a7c183228
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/EUC-V.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Ext-H.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Ext-H.bcmap
new file mode 100644
index 0000000000..3b5cde44db
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Ext-H.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Ext-RKSJ-H.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Ext-RKSJ-H.bcmap
new file mode 100644
index 0000000000..ea4d2d97b8
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Ext-RKSJ-H.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Ext-RKSJ-V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Ext-RKSJ-V.bcmap
new file mode 100644
index 0000000000..3457c27709
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Ext-RKSJ-V.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Ext-V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Ext-V.bcmap
new file mode 100644
index 0000000000..4999ca4041
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Ext-V.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/GB-EUC-H.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/GB-EUC-H.bcmap
new file mode 100644
index 0000000000..e39908b984
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/GB-EUC-H.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/GB-EUC-V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/GB-EUC-V.bcmap
new file mode 100644
index 0000000000..d5be5446aa
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/GB-EUC-V.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/GB-H.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/GB-H.bcmap
new file mode 100644
index 0000000000..39189c54e3
--- /dev/null
+++ b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/GB-H.bcmap
@@ -0,0 +1,4 @@
+àRCopyright 1990-2009 Adobe Systems Incorporated.
+All rights reserved.
+See ./LICENSE!!�º]aX!!]`�21�> �p�z�$]‚�"R‚d�-Uƒ7�*„
4„%�+ „Z „{�/…%…<�9K…b�1]†.�"‡‰`]‡,�"]ˆ
+�"]ˆh�"]‰F�"]Š$�"]‹�"]‹`�"]Œ>�"]��"]�z�"]ŽX�"]�6�"]��"]�r�"]‘P�"]’.�"]“�"]“j�"]”H�"]•&�"]–�"]–b�"]—@�"]˜�"]˜|�"]™Z�"]š8�"]›�"]›t�"]œR�"]�0�"]ž�"]žl�"]ŸJ�"] (�"]¡�"]¡d�"]¢B�"]£ �"X£~�']¤W�"]¥5�"]¦�"]¦q�"]§O�"]¨-�"]©�"]©i�"]ªG�"]«%�"]¬�"]¬a�"]?�"]®�"]®{�"]¯Y�"]°7�"]±�"]±s�"]²Q�"]³/�"]´
�"]´k�"]µI�"]¶'�"]·�"]·c�"]¸A�"]¹�"]¹}�"]º[�"]»9
\ No newline at end of file
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/GB-V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/GB-V.bcmap
new file mode 100644
index 0000000000..310834512f
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/GB-V.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/GBK-EUC-H.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/GBK-EUC-H.bcmap
new file mode 100644
index 0000000000..05fff7e825
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/GBK-EUC-H.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/GBK-EUC-V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/GBK-EUC-V.bcmap
new file mode 100644
index 0000000000..0cdf6bed6d
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/GBK-EUC-V.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/GBK2K-H.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/GBK2K-H.bcmap
new file mode 100644
index 0000000000..46f6ba5967
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/GBK2K-H.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/GBK2K-V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/GBK2K-V.bcmap
new file mode 100644
index 0000000000..d9a9479843
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/GBK2K-V.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/GBKp-EUC-H.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/GBKp-EUC-H.bcmap
new file mode 100644
index 0000000000..5cb0af687e
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/GBKp-EUC-H.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/GBKp-EUC-V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/GBKp-EUC-V.bcmap
new file mode 100644
index 0000000000..bca93b8efb
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/GBKp-EUC-V.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/GBT-EUC-H.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/GBT-EUC-H.bcmap
new file mode 100644
index 0000000000..4b4e2d3229
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/GBT-EUC-H.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/GBT-EUC-V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/GBT-EUC-V.bcmap
new file mode 100644
index 0000000000..38f706699f
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/GBT-EUC-V.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/GBT-H.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/GBT-H.bcmap
new file mode 100644
index 0000000000..8437ac3377
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/GBT-H.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/GBT-V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/GBT-V.bcmap
new file mode 100644
index 0000000000..697ab4a8e7
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/GBT-V.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/GBTpc-EUC-H.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/GBTpc-EUC-H.bcmap
new file mode 100644
index 0000000000..f6e50e8936
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/GBTpc-EUC-H.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/GBTpc-EUC-V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/GBTpc-EUC-V.bcmap
new file mode 100644
index 0000000000..6c0d71a2d0
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/GBTpc-EUC-V.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/GBpc-EUC-H.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/GBpc-EUC-H.bcmap
new file mode 100644
index 0000000000..c9edf67cf6
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/GBpc-EUC-H.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/GBpc-EUC-V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/GBpc-EUC-V.bcmap
new file mode 100644
index 0000000000..31450c97f6
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/GBpc-EUC-V.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/H.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/H.bcmap
new file mode 100644
index 0000000000..7b24ea4629
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/H.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/HKdla-B5-H.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/HKdla-B5-H.bcmap
new file mode 100644
index 0000000000..7d30c05005
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/HKdla-B5-H.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/HKdla-B5-V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/HKdla-B5-V.bcmap
new file mode 100644
index 0000000000..78946940d6
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/HKdla-B5-V.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/HKdlb-B5-H.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/HKdlb-B5-H.bcmap
new file mode 100644
index 0000000000..d829a23101
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/HKdlb-B5-H.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/HKdlb-B5-V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/HKdlb-B5-V.bcmap
new file mode 100644
index 0000000000..2b572b50a4
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/HKdlb-B5-V.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/HKgccs-B5-H.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/HKgccs-B5-H.bcmap
new file mode 100644
index 0000000000..971a4f23f7
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/HKgccs-B5-H.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/HKgccs-B5-V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/HKgccs-B5-V.bcmap
new file mode 100644
index 0000000000..d353ca256b
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/HKgccs-B5-V.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/HKm314-B5-H.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/HKm314-B5-H.bcmap
new file mode 100644
index 0000000000..576dc01112
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/HKm314-B5-H.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/HKm314-B5-V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/HKm314-B5-V.bcmap
new file mode 100644
index 0000000000..0e96d0e228
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/HKm314-B5-V.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/HKm471-B5-H.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/HKm471-B5-H.bcmap
new file mode 100644
index 0000000000..11d170c75e
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/HKm471-B5-H.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/HKm471-B5-V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/HKm471-B5-V.bcmap
new file mode 100644
index 0000000000..54959bf9e7
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/HKm471-B5-V.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/HKscs-B5-H.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/HKscs-B5-H.bcmap
new file mode 100644
index 0000000000..6ef7857ad1
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/HKscs-B5-H.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/HKscs-B5-V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/HKscs-B5-V.bcmap
new file mode 100644
index 0000000000..1fb2fa2a2e
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/HKscs-B5-V.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Hankaku.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Hankaku.bcmap
new file mode 100644
index 0000000000..4b8ec7fcef
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Hankaku.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Hiragana.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Hiragana.bcmap
new file mode 100644
index 0000000000..17e983e772
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Hiragana.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/KSC-EUC-H.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/KSC-EUC-H.bcmap
new file mode 100644
index 0000000000..a45c65f008
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/KSC-EUC-H.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/KSC-EUC-V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/KSC-EUC-V.bcmap
new file mode 100644
index 0000000000..0e7b21f0a6
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/KSC-EUC-V.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/KSC-H.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/KSC-H.bcmap
new file mode 100644
index 0000000000..b9b22b6787
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/KSC-H.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/KSC-Johab-H.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/KSC-Johab-H.bcmap
new file mode 100644
index 0000000000..2531ffcf41
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/KSC-Johab-H.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/KSC-Johab-V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/KSC-Johab-V.bcmap
new file mode 100644
index 0000000000..367ceb226a
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/KSC-Johab-V.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/KSC-V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/KSC-V.bcmap
new file mode 100644
index 0000000000..6ae2f0b6b7
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/KSC-V.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/KSCms-UHC-H.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/KSCms-UHC-H.bcmap
new file mode 100644
index 0000000000..a8d4240e6a
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/KSCms-UHC-H.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/KSCms-UHC-HW-H.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/KSCms-UHC-HW-H.bcmap
new file mode 100644
index 0000000000..8b4ae18fd3
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/KSCms-UHC-HW-H.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/KSCms-UHC-HW-V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/KSCms-UHC-HW-V.bcmap
new file mode 100644
index 0000000000..b655dbcfb1
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/KSCms-UHC-HW-V.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/KSCms-UHC-V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/KSCms-UHC-V.bcmap
new file mode 100644
index 0000000000..21f97f65b4
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/KSCms-UHC-V.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/KSCpc-EUC-H.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/KSCpc-EUC-H.bcmap
new file mode 100644
index 0000000000..e06f361eb6
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/KSCpc-EUC-H.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/KSCpc-EUC-V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/KSCpc-EUC-V.bcmap
new file mode 100644
index 0000000000..f3c9113fcf
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/KSCpc-EUC-V.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Katakana.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Katakana.bcmap
new file mode 100644
index 0000000000..524303c4f0
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Katakana.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/LICENSE b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/LICENSE
new file mode 100644
index 0000000000..b1ad168ad0
--- /dev/null
+++ b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/LICENSE
@@ -0,0 +1,36 @@
+%%Copyright: -----------------------------------------------------------
+%%Copyright: Copyright 1990-2009 Adobe Systems Incorporated.
+%%Copyright: All rights reserved.
+%%Copyright:
+%%Copyright: Redistribution and use in source and binary forms, with or
+%%Copyright: without modification, are permitted provided that the
+%%Copyright: following conditions are met:
+%%Copyright:
+%%Copyright: Redistributions of source code must retain the above
+%%Copyright: copyright notice, this list of conditions and the following
+%%Copyright: disclaimer.
+%%Copyright:
+%%Copyright: Redistributions in binary form must reproduce the above
+%%Copyright: copyright notice, this list of conditions and the following
+%%Copyright: disclaimer in the documentation and/or other materials
+%%Copyright: provided with the distribution.
+%%Copyright:
+%%Copyright: Neither the name of Adobe Systems Incorporated nor the names
+%%Copyright: of its contributors may be used to endorse or promote
+%%Copyright: products derived from this software without specific prior
+%%Copyright: written permission.
+%%Copyright:
+%%Copyright: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+%%Copyright: CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+%%Copyright: INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+%%Copyright: MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+%%Copyright: DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+%%Copyright: CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+%%Copyright: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+%%Copyright: NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+%%Copyright: LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+%%Copyright: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+%%Copyright: CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+%%Copyright: OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+%%Copyright: SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+%%Copyright: -----------------------------------------------------------
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/NWP-H.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/NWP-H.bcmap
new file mode 100644
index 0000000000..afc5e4b05e
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/NWP-H.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/NWP-V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/NWP-V.bcmap
new file mode 100644
index 0000000000..bb5785e327
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/NWP-V.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/RKSJ-H.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/RKSJ-H.bcmap
new file mode 100644
index 0000000000..fb8d298e9b
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/RKSJ-H.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/RKSJ-V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/RKSJ-V.bcmap
new file mode 100644
index 0000000000..a2555a6c04
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/RKSJ-V.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Roman.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Roman.bcmap
new file mode 100644
index 0000000000..f896dcf1c7
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/Roman.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniCNS-UCS2-H.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniCNS-UCS2-H.bcmap
new file mode 100644
index 0000000000..d5db27c5cf
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniCNS-UCS2-H.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniCNS-UCS2-V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniCNS-UCS2-V.bcmap
new file mode 100644
index 0000000000..1dc9b7a21b
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniCNS-UCS2-V.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniCNS-UTF16-H.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniCNS-UTF16-H.bcmap
new file mode 100644
index 0000000000..961afefb66
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniCNS-UTF16-H.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniCNS-UTF16-V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniCNS-UTF16-V.bcmap
new file mode 100644
index 0000000000..df0cffe86b
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniCNS-UTF16-V.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniCNS-UTF32-H.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniCNS-UTF32-H.bcmap
new file mode 100644
index 0000000000..1ab18a1436
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniCNS-UTF32-H.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniCNS-UTF32-V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniCNS-UTF32-V.bcmap
new file mode 100644
index 0000000000..ad14662e25
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniCNS-UTF32-V.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniCNS-UTF8-H.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniCNS-UTF8-H.bcmap
new file mode 100644
index 0000000000..83c6bd7c4f
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniCNS-UTF8-H.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniCNS-UTF8-V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniCNS-UTF8-V.bcmap
new file mode 100644
index 0000000000..22a27e4ddb
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniCNS-UTF8-V.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniGB-UCS2-H.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniGB-UCS2-H.bcmap
new file mode 100644
index 0000000000..5bd6228ce6
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniGB-UCS2-H.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniGB-UCS2-V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniGB-UCS2-V.bcmap
new file mode 100644
index 0000000000..53c534b7fe
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniGB-UCS2-V.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniGB-UTF16-H.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniGB-UTF16-H.bcmap
new file mode 100644
index 0000000000..b95045b400
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniGB-UTF16-H.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniGB-UTF16-V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniGB-UTF16-V.bcmap
new file mode 100644
index 0000000000..51f023e0d6
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniGB-UTF16-V.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniGB-UTF32-H.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniGB-UTF32-H.bcmap
new file mode 100644
index 0000000000..f0dbd14f37
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniGB-UTF32-H.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniGB-UTF32-V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniGB-UTF32-V.bcmap
new file mode 100644
index 0000000000..ce9c30a985
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniGB-UTF32-V.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniGB-UTF8-H.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniGB-UTF8-H.bcmap
new file mode 100644
index 0000000000..982ca462b1
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniGB-UTF8-H.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniGB-UTF8-V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniGB-UTF8-V.bcmap
new file mode 100644
index 0000000000..f78020dd40
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniGB-UTF8-V.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJIS-UCS2-H.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJIS-UCS2-H.bcmap
new file mode 100644
index 0000000000..7daf56afab
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJIS-UCS2-H.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJIS-UCS2-HW-H.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJIS-UCS2-HW-H.bcmap
new file mode 100644
index 0000000000..ac9975c585
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJIS-UCS2-HW-H.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJIS-UCS2-HW-V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJIS-UCS2-HW-V.bcmap
new file mode 100644
index 0000000000..3da0a1c62f
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJIS-UCS2-HW-V.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJIS-UCS2-V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJIS-UCS2-V.bcmap
new file mode 100644
index 0000000000..c50b9ddfde
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJIS-UCS2-V.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJIS-UTF16-H.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJIS-UTF16-H.bcmap
new file mode 100644
index 0000000000..6761344639
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJIS-UTF16-H.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJIS-UTF16-V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJIS-UTF16-V.bcmap
new file mode 100644
index 0000000000..70bf90c0ef
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJIS-UTF16-V.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJIS-UTF32-H.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJIS-UTF32-H.bcmap
new file mode 100644
index 0000000000..7a83d53ae7
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJIS-UTF32-H.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJIS-UTF32-V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJIS-UTF32-V.bcmap
new file mode 100644
index 0000000000..7a87135394
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJIS-UTF32-V.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJIS-UTF8-H.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJIS-UTF8-H.bcmap
new file mode 100644
index 0000000000..9f0334cac7
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJIS-UTF8-H.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJIS-UTF8-V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJIS-UTF8-V.bcmap
new file mode 100644
index 0000000000..808a94f0fd
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJIS-UTF8-V.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJIS2004-UTF16-H.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJIS2004-UTF16-H.bcmap
new file mode 100644
index 0000000000..d768bf811f
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJIS2004-UTF16-H.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJIS2004-UTF16-V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJIS2004-UTF16-V.bcmap
new file mode 100644
index 0000000000..3d5bf6fb4e
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJIS2004-UTF16-V.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJIS2004-UTF32-H.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJIS2004-UTF32-H.bcmap
new file mode 100644
index 0000000000..09eee10d4f
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJIS2004-UTF32-H.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJIS2004-UTF32-V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJIS2004-UTF32-V.bcmap
new file mode 100644
index 0000000000..6c54600133
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJIS2004-UTF32-V.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJIS2004-UTF8-H.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJIS2004-UTF8-H.bcmap
new file mode 100644
index 0000000000..1b1a64f50d
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJIS2004-UTF8-H.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJIS2004-UTF8-V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJIS2004-UTF8-V.bcmap
new file mode 100644
index 0000000000..994aa9ef9f
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJIS2004-UTF8-V.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJISPro-UCS2-HW-V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJISPro-UCS2-HW-V.bcmap
new file mode 100644
index 0000000000..643f921b65
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJISPro-UCS2-HW-V.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJISPro-UCS2-V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJISPro-UCS2-V.bcmap
new file mode 100644
index 0000000000..c148f67f5e
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJISPro-UCS2-V.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJISPro-UTF8-V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJISPro-UTF8-V.bcmap
new file mode 100644
index 0000000000..1849d809a6
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJISPro-UTF8-V.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJISX0213-UTF32-H.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJISX0213-UTF32-H.bcmap
new file mode 100644
index 0000000000..a83a677c56
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJISX0213-UTF32-H.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJISX0213-UTF32-V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJISX0213-UTF32-V.bcmap
new file mode 100644
index 0000000000..f527248ad5
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJISX0213-UTF32-V.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJISX02132004-UTF32-H.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJISX02132004-UTF32-H.bcmap
new file mode 100644
index 0000000000..e1a988dc9e
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJISX02132004-UTF32-H.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJISX02132004-UTF32-V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJISX02132004-UTF32-V.bcmap
new file mode 100644
index 0000000000..47e054a961
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniJISX02132004-UTF32-V.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniKS-UCS2-H.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniKS-UCS2-H.bcmap
new file mode 100644
index 0000000000..b5b94852a5
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniKS-UCS2-H.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniKS-UCS2-V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniKS-UCS2-V.bcmap
new file mode 100644
index 0000000000..026adcaad4
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniKS-UCS2-V.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniKS-UTF16-H.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniKS-UTF16-H.bcmap
new file mode 100644
index 0000000000..fd4e66e81f
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniKS-UTF16-H.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniKS-UTF16-V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniKS-UTF16-V.bcmap
new file mode 100644
index 0000000000..075efb7054
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniKS-UTF16-V.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniKS-UTF32-H.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniKS-UTF32-H.bcmap
new file mode 100644
index 0000000000..769d2142c0
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniKS-UTF32-H.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniKS-UTF32-V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniKS-UTF32-V.bcmap
new file mode 100644
index 0000000000..bdab208b69
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniKS-UTF32-V.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniKS-UTF8-H.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniKS-UTF8-H.bcmap
new file mode 100644
index 0000000000..6ff8674af7
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniKS-UTF8-H.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniKS-UTF8-V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniKS-UTF8-V.bcmap
new file mode 100644
index 0000000000..8dfa76a58e
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/UniKS-UTF8-V.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/V.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/V.bcmap
new file mode 100644
index 0000000000..fdec990662
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/V.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/WP-Symbol.bcmap b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/WP-Symbol.bcmap
new file mode 100644
index 0000000000..46729bbf30
Binary files /dev/null and b/services/web/public/js/libs/pdfjs-1.6.210p2/bcmaps/WP-Symbol.bcmap differ
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/compatibility.js b/services/web/public/js/libs/pdfjs-1.6.210p2/compatibility.js
new file mode 100644
index 0000000000..2874bcb12e
--- /dev/null
+++ b/services/web/public/js/libs/pdfjs-1.6.210p2/compatibility.js
@@ -0,0 +1,596 @@
+/* Copyright 2012 Mozilla Foundation
+ *
+ * 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.
+ */
+/* globals VBArray, PDFJS */
+
+(function compatibilityWrapper() {
+ 'use strict';
+
+// Initializing PDFJS global object here, it case if we need to change/disable
+// some PDF.js features, e.g. range requests
+if (typeof PDFJS === 'undefined') {
+ (typeof window !== 'undefined' ? window : this).PDFJS = {};
+}
+
+// Checking if the typed arrays are supported
+// Support: iOS<6.0 (subarray), IE<10, Android<4.0
+(function checkTypedArrayCompatibility() {
+ if (typeof Uint8Array !== 'undefined') {
+ // Support: iOS<6.0
+ if (typeof Uint8Array.prototype.subarray === 'undefined') {
+ Uint8Array.prototype.subarray = function subarray(start, end) {
+ return new Uint8Array(this.slice(start, end));
+ };
+ Float32Array.prototype.subarray = function subarray(start, end) {
+ return new Float32Array(this.slice(start, end));
+ };
+ }
+
+ // Support: Android<4.1
+ if (typeof Float64Array === 'undefined') {
+ window.Float64Array = Float32Array;
+ }
+ return;
+ }
+
+ function subarray(start, end) {
+ return new TypedArray(this.slice(start, end));
+ }
+
+ function setArrayOffset(array, offset) {
+ if (arguments.length < 2) {
+ offset = 0;
+ }
+ for (var i = 0, n = array.length; i < n; ++i, ++offset) {
+ this[offset] = array[i] & 0xFF;
+ }
+ }
+
+ function TypedArray(arg1) {
+ var result, i, n;
+ if (typeof arg1 === 'number') {
+ result = [];
+ for (i = 0; i < arg1; ++i) {
+ result[i] = 0;
+ }
+ } else if ('slice' in arg1) {
+ result = arg1.slice(0);
+ } else {
+ result = [];
+ for (i = 0, n = arg1.length; i < n; ++i) {
+ result[i] = arg1[i];
+ }
+ }
+
+ result.subarray = subarray;
+ result.buffer = result;
+ result.byteLength = result.length;
+ result.set = setArrayOffset;
+
+ if (typeof arg1 === 'object' && arg1.buffer) {
+ result.buffer = arg1.buffer;
+ }
+ return result;
+ }
+
+ window.Uint8Array = TypedArray;
+ window.Int8Array = TypedArray;
+
+ // we don't need support for set, byteLength for 32-bit array
+ // so we can use the TypedArray as well
+ window.Uint32Array = TypedArray;
+ window.Int32Array = TypedArray;
+ window.Uint16Array = TypedArray;
+ window.Float32Array = TypedArray;
+ window.Float64Array = TypedArray;
+})();
+
+// URL = URL || webkitURL
+// Support: Safari<7, Android 4.2+
+(function normalizeURLObject() {
+ if (!window.URL) {
+ window.URL = window.webkitURL;
+ }
+})();
+
+// Object.defineProperty()?
+// Support: Android<4.0, Safari<5.1
+(function checkObjectDefinePropertyCompatibility() {
+ if (typeof Object.defineProperty !== 'undefined') {
+ var definePropertyPossible = true;
+ try {
+ // some browsers (e.g. safari) cannot use defineProperty() on DOM objects
+ // and thus the native version is not sufficient
+ Object.defineProperty(new Image(), 'id', { value: 'test' });
+ // ... another test for android gb browser for non-DOM objects
+ var Test = function Test() {};
+ Test.prototype = { get id() { } };
+ Object.defineProperty(new Test(), 'id',
+ { value: '', configurable: true, enumerable: true, writable: false });
+ } catch (e) {
+ definePropertyPossible = false;
+ }
+ if (definePropertyPossible) {
+ return;
+ }
+ }
+
+ Object.defineProperty = function objectDefineProperty(obj, name, def) {
+ delete obj[name];
+ if ('get' in def) {
+ obj.__defineGetter__(name, def['get']);
+ }
+ if ('set' in def) {
+ obj.__defineSetter__(name, def['set']);
+ }
+ if ('value' in def) {
+ obj.__defineSetter__(name, function objectDefinePropertySetter(value) {
+ this.__defineGetter__(name, function objectDefinePropertyGetter() {
+ return value;
+ });
+ return value;
+ });
+ obj[name] = def.value;
+ }
+ };
+})();
+
+
+// No XMLHttpRequest#response?
+// Support: IE<11, Android <4.0
+(function checkXMLHttpRequestResponseCompatibility() {
+ var xhrPrototype = XMLHttpRequest.prototype;
+ var xhr = new XMLHttpRequest();
+ if (!('overrideMimeType' in xhr)) {
+ // IE10 might have response, but not overrideMimeType
+ // Support: IE10
+ Object.defineProperty(xhrPrototype, 'overrideMimeType', {
+ value: function xmlHttpRequestOverrideMimeType(mimeType) {}
+ });
+ }
+ if ('responseType' in xhr) {
+ return;
+ }
+
+ // The worker will be using XHR, so we can save time and disable worker.
+ PDFJS.disableWorker = true;
+
+ Object.defineProperty(xhrPrototype, 'responseType', {
+ get: function xmlHttpRequestGetResponseType() {
+ return this._responseType || 'text';
+ },
+ set: function xmlHttpRequestSetResponseType(value) {
+ if (value === 'text' || value === 'arraybuffer') {
+ this._responseType = value;
+ if (value === 'arraybuffer' &&
+ typeof this.overrideMimeType === 'function') {
+ this.overrideMimeType('text/plain; charset=x-user-defined');
+ }
+ }
+ }
+ });
+
+ // Support: IE9
+ if (typeof VBArray !== 'undefined') {
+ Object.defineProperty(xhrPrototype, 'response', {
+ get: function xmlHttpRequestResponseGet() {
+ if (this.responseType === 'arraybuffer') {
+ return new Uint8Array(new VBArray(this.responseBody).toArray());
+ } else {
+ return this.responseText;
+ }
+ }
+ });
+ return;
+ }
+
+ Object.defineProperty(xhrPrototype, 'response', {
+ get: function xmlHttpRequestResponseGet() {
+ if (this.responseType !== 'arraybuffer') {
+ return this.responseText;
+ }
+ var text = this.responseText;
+ var i, n = text.length;
+ var result = new Uint8Array(n);
+ for (i = 0; i < n; ++i) {
+ result[i] = text.charCodeAt(i) & 0xFF;
+ }
+ return result.buffer;
+ }
+ });
+})();
+
+// window.btoa (base64 encode function) ?
+// Support: IE<10
+(function checkWindowBtoaCompatibility() {
+ if ('btoa' in window) {
+ return;
+ }
+
+ var digits =
+ 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
+
+ window.btoa = function windowBtoa(chars) {
+ var buffer = '';
+ var i, n;
+ for (i = 0, n = chars.length; i < n; i += 3) {
+ var b1 = chars.charCodeAt(i) & 0xFF;
+ var b2 = chars.charCodeAt(i + 1) & 0xFF;
+ var b3 = chars.charCodeAt(i + 2) & 0xFF;
+ var d1 = b1 >> 2, d2 = ((b1 & 3) << 4) | (b2 >> 4);
+ var d3 = i + 1 < n ? ((b2 & 0xF) << 2) | (b3 >> 6) : 64;
+ var d4 = i + 2 < n ? (b3 & 0x3F) : 64;
+ buffer += (digits.charAt(d1) + digits.charAt(d2) +
+ digits.charAt(d3) + digits.charAt(d4));
+ }
+ return buffer;
+ };
+})();
+
+// window.atob (base64 encode function)?
+// Support: IE<10
+(function checkWindowAtobCompatibility() {
+ if ('atob' in window) {
+ return;
+ }
+
+ // https://github.com/davidchambers/Base64.js
+ var digits =
+ 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
+ window.atob = function (input) {
+ input = input.replace(/=+$/, '');
+ if (input.length % 4 === 1) {
+ throw new Error('bad atob input');
+ }
+ for (
+ // initialize result and counters
+ var bc = 0, bs, buffer, idx = 0, output = '';
+ // get next character
+ buffer = input.charAt(idx++);
+ // character found in table?
+ // initialize bit storage and add its ascii value
+ ~buffer && (bs = bc % 4 ? bs * 64 + buffer : buffer,
+ // and if not first of each 4 characters,
+ // convert the first 8 bits to one ascii character
+ bc++ % 4) ? output += String.fromCharCode(255 & bs >> (-2 * bc & 6)) : 0
+ ) {
+ // try to find character in table (0-63, not found => -1)
+ buffer = digits.indexOf(buffer);
+ }
+ return output;
+ };
+})();
+
+// Function.prototype.bind?
+// Support: Android<4.0, iOS<6.0
+(function checkFunctionPrototypeBindCompatibility() {
+ if (typeof Function.prototype.bind !== 'undefined') {
+ return;
+ }
+
+ Function.prototype.bind = function functionPrototypeBind(obj) {
+ var fn = this, headArgs = Array.prototype.slice.call(arguments, 1);
+ var bound = function functionPrototypeBindBound() {
+ var args = headArgs.concat(Array.prototype.slice.call(arguments));
+ return fn.apply(obj, args);
+ };
+ return bound;
+ };
+})();
+
+// HTMLElement dataset property
+// Support: IE<11, Safari<5.1, Android<4.0
+(function checkDatasetProperty() {
+ var div = document.createElement('div');
+ if ('dataset' in div) {
+ return; // dataset property exists
+ }
+
+ Object.defineProperty(HTMLElement.prototype, 'dataset', {
+ get: function() {
+ if (this._dataset) {
+ return this._dataset;
+ }
+
+ var dataset = {};
+ for (var j = 0, jj = this.attributes.length; j < jj; j++) {
+ var attribute = this.attributes[j];
+ if (attribute.name.substring(0, 5) !== 'data-') {
+ continue;
+ }
+ var key = attribute.name.substring(5).replace(/\-([a-z])/g,
+ function(all, ch) {
+ return ch.toUpperCase();
+ });
+ dataset[key] = attribute.value;
+ }
+
+ Object.defineProperty(this, '_dataset', {
+ value: dataset,
+ writable: false,
+ enumerable: false
+ });
+ return dataset;
+ },
+ enumerable: true
+ });
+})();
+
+// HTMLElement classList property
+// Support: IE<10, Android<4.0, iOS<5.0
+(function checkClassListProperty() {
+ var div = document.createElement('div');
+ if ('classList' in div) {
+ return; // classList property exists
+ }
+
+ function changeList(element, itemName, add, remove) {
+ var s = element.className || '';
+ var list = s.split(/\s+/g);
+ if (list[0] === '') {
+ list.shift();
+ }
+ var index = list.indexOf(itemName);
+ if (index < 0 && add) {
+ list.push(itemName);
+ }
+ if (index >= 0 && remove) {
+ list.splice(index, 1);
+ }
+ element.className = list.join(' ');
+ return (index >= 0);
+ }
+
+ var classListPrototype = {
+ add: function(name) {
+ changeList(this.element, name, true, false);
+ },
+ contains: function(name) {
+ return changeList(this.element, name, false, false);
+ },
+ remove: function(name) {
+ changeList(this.element, name, false, true);
+ },
+ toggle: function(name) {
+ changeList(this.element, name, true, true);
+ }
+ };
+
+ Object.defineProperty(HTMLElement.prototype, 'classList', {
+ get: function() {
+ if (this._classList) {
+ return this._classList;
+ }
+
+ var classList = Object.create(classListPrototype, {
+ element: {
+ value: this,
+ writable: false,
+ enumerable: true
+ }
+ });
+ Object.defineProperty(this, '_classList', {
+ value: classList,
+ writable: false,
+ enumerable: false
+ });
+ return classList;
+ },
+ enumerable: true
+ });
+})();
+
+// Check console compatibility
+// In older IE versions the console object is not available
+// unless console is open.
+// Support: IE<10
+(function checkConsoleCompatibility() {
+ if (!('console' in window)) {
+ window.console = {
+ log: function() {},
+ error: function() {},
+ warn: function() {}
+ };
+ } else if (!('bind' in console.log)) {
+ // native functions in IE9 might not have bind
+ console.log = (function(fn) {
+ return function(msg) { return fn(msg); };
+ })(console.log);
+ console.error = (function(fn) {
+ return function(msg) { return fn(msg); };
+ })(console.error);
+ console.warn = (function(fn) {
+ return function(msg) { return fn(msg); };
+ })(console.warn);
+ }
+})();
+
+// Check onclick compatibility in Opera
+// Support: Opera<15
+(function checkOnClickCompatibility() {
+ // workaround for reported Opera bug DSK-354448:
+ // onclick fires on disabled buttons with opaque content
+ function ignoreIfTargetDisabled(event) {
+ if (isDisabled(event.target)) {
+ event.stopPropagation();
+ }
+ }
+ function isDisabled(node) {
+ return node.disabled || (node.parentNode && isDisabled(node.parentNode));
+ }
+ if (navigator.userAgent.indexOf('Opera') !== -1) {
+ // use browser detection since we cannot feature-check this bug
+ document.addEventListener('click', ignoreIfTargetDisabled, true);
+ }
+})();
+
+// Checks if possible to use URL.createObjectURL()
+// Support: IE
+(function checkOnBlobSupport() {
+ // sometimes IE loosing the data created with createObjectURL(), see #3977
+ if (navigator.userAgent.indexOf('Trident') >= 0) {
+ PDFJS.disableCreateObjectURL = true;
+ }
+})();
+
+// Checks if navigator.language is supported
+(function checkNavigatorLanguage() {
+ if ('language' in navigator) {
+ return;
+ }
+ PDFJS.locale = navigator.userLanguage || 'en-US';
+})();
+
+(function checkRangeRequests() {
+ // Safari has issues with cached range requests see:
+ // https://github.com/mozilla/pdf.js/issues/3260
+ // Last tested with version 6.0.4.
+ // Support: Safari 6.0+
+ var isSafari = Object.prototype.toString.call(
+ window.HTMLElement).indexOf('Constructor') > 0;
+
+ // Older versions of Android (pre 3.0) has issues with range requests, see:
+ // https://github.com/mozilla/pdf.js/issues/3381.
+ // Make sure that we only match webkit-based Android browsers,
+ // since Firefox/Fennec works as expected.
+ // Support: Android<3.0
+ var regex = /Android\s[0-2][^\d]/;
+ var isOldAndroid = regex.test(navigator.userAgent);
+
+ // Range requests are broken in Chrome 39 and 40, https://crbug.com/442318
+ var isChromeWithRangeBug = /Chrome\/(39|40)\./.test(navigator.userAgent);
+
+ if (isSafari || isOldAndroid || isChromeWithRangeBug) {
+ PDFJS.disableRange = true;
+ PDFJS.disableStream = true;
+ }
+})();
+
+// Check if the browser supports manipulation of the history.
+// Support: IE<10, Android<4.2
+(function checkHistoryManipulation() {
+ // Android 2.x has so buggy pushState support that it was removed in
+ // Android 3.0 and restored as late as in Android 4.2.
+ // Support: Android 2.x
+ if (!history.pushState || navigator.userAgent.indexOf('Android 2.') >= 0) {
+ PDFJS.disableHistory = true;
+ }
+})();
+
+// Support: IE<11, Chrome<21, Android<4.4, Safari<6
+(function checkSetPresenceInImageData() {
+ // IE < 11 will use window.CanvasPixelArray which lacks set function.
+ if (window.CanvasPixelArray) {
+ if (typeof window.CanvasPixelArray.prototype.set !== 'function') {
+ window.CanvasPixelArray.prototype.set = function(arr) {
+ for (var i = 0, ii = this.length; i < ii; i++) {
+ this[i] = arr[i];
+ }
+ };
+ }
+ } else {
+ // Old Chrome and Android use an inaccessible CanvasPixelArray prototype.
+ // Because we cannot feature detect it, we rely on user agent parsing.
+ var polyfill = false, versionMatch;
+ if (navigator.userAgent.indexOf('Chrom') >= 0) {
+ versionMatch = navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./);
+ // Chrome < 21 lacks the set function.
+ polyfill = versionMatch && parseInt(versionMatch[2]) < 21;
+ } else if (navigator.userAgent.indexOf('Android') >= 0) {
+ // Android < 4.4 lacks the set function.
+ // Android >= 4.4 will contain Chrome in the user agent,
+ // thus pass the Chrome check above and not reach this block.
+ polyfill = /Android\s[0-4][^\d]/g.test(navigator.userAgent);
+ } else if (navigator.userAgent.indexOf('Safari') >= 0) {
+ versionMatch = navigator.userAgent.
+ match(/Version\/([0-9]+)\.([0-9]+)\.([0-9]+) Safari\//);
+ // Safari < 6 lacks the set function.
+ polyfill = versionMatch && parseInt(versionMatch[1]) < 6;
+ }
+
+ if (polyfill) {
+ var contextPrototype = window.CanvasRenderingContext2D.prototype;
+ var createImageData = contextPrototype.createImageData;
+ contextPrototype.createImageData = function(w, h) {
+ var imageData = createImageData.call(this, w, h);
+ imageData.data.set = function(arr) {
+ for (var i = 0, ii = this.length; i < ii; i++) {
+ this[i] = arr[i];
+ }
+ };
+ return imageData;
+ };
+ // this closure will be kept referenced, so clear its vars
+ contextPrototype = null;
+ }
+ }
+})();
+
+// Support: IE<10, Android<4.0, iOS
+(function checkRequestAnimationFrame() {
+ function fakeRequestAnimationFrame(callback) {
+ window.setTimeout(callback, 20);
+ }
+
+ var isIOS = /(iPad|iPhone|iPod)/g.test(navigator.userAgent);
+ if (isIOS) {
+ // requestAnimationFrame on iOS is broken, replacing with fake one.
+ window.requestAnimationFrame = fakeRequestAnimationFrame;
+ return;
+ }
+ if ('requestAnimationFrame' in window) {
+ return;
+ }
+ window.requestAnimationFrame =
+ window.mozRequestAnimationFrame ||
+ window.webkitRequestAnimationFrame ||
+ fakeRequestAnimationFrame;
+})();
+
+(function checkCanvasSizeLimitation() {
+ var isIOS = /(iPad|iPhone|iPod)/g.test(navigator.userAgent);
+ var isAndroid = /Android/g.test(navigator.userAgent);
+ if (isIOS || isAndroid) {
+ // 5MP
+ PDFJS.maxCanvasPixels = 5242880;
+ }
+})();
+
+// Disable fullscreen support for certain problematic configurations.
+// Support: IE11+ (when embedded).
+(function checkFullscreenSupport() {
+ var isEmbeddedIE = (navigator.userAgent.indexOf('Trident') >= 0 &&
+ window.parent !== window);
+ if (isEmbeddedIE) {
+ PDFJS.disableFullscreen = true;
+ }
+})();
+
+// Provides document.currentScript support
+// Support: IE, Chrome<29.
+(function checkCurrentScript() {
+ if ('currentScript' in document) {
+ return;
+ }
+ Object.defineProperty(document, 'currentScript', {
+ get: function () {
+ var scripts = document.getElementsByTagName('script');
+ return scripts[scripts.length - 1];
+ },
+ enumerable: true,
+ configurable: true
+ });
+})();
+
+}).call((typeof window === 'undefined') ? this : window);
diff --git a/services/web/public/js/libs/pdfjs-1.6.210p2/pdf.js b/services/web/public/js/libs/pdfjs-1.6.210p2/pdf.js
new file mode 100644
index 0000000000..2d3c3c83bc
--- /dev/null
+++ b/services/web/public/js/libs/pdfjs-1.6.210p2/pdf.js
@@ -0,0 +1,11515 @@
+/* Copyright 2012 Mozilla Foundation
+ *
+ * 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.
+ */
+/* jshint globalstrict: false */
+/* umdutils ignore */
+
+(function (root, factory) {
+ 'use strict';
+ if (typeof define === 'function' && define.amd) {
+define('pdfjs-dist/build/pdf', ['exports'], factory);
+ } else if (typeof exports !== 'undefined') {
+ factory(exports);
+ } else {
+factory((root.pdfjsDistBuildPdf = {}));
+ }
+}(this, function (exports) {
+ // Use strict in our context only - users might not want it
+ 'use strict';
+
+var pdfjsVersion = '1.6.210';
+var pdfjsBuild = '4ce2356';
+
+ var pdfjsFilePath =
+ typeof document !== 'undefined' && document.currentScript ?
+ document.currentScript.src : null;
+
+ var pdfjsLibs = {};
+
+ (function pdfjsWrapper() {
+
+
+
+(function (root, factory) {
+ {
+ factory((root.pdfjsSharedUtil = {}));
+ }
+}(this, function (exports) {
+
+var globalScope = (typeof window !== 'undefined') ? window :
+ (typeof global !== 'undefined') ? global :
+ (typeof self !== 'undefined') ? self : this;
+
+var FONT_IDENTITY_MATRIX = [0.001, 0, 0, 0.001, 0, 0];
+
+var TextRenderingMode = {
+ 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
+};
+
+var ImageKind = {
+ GRAYSCALE_1BPP: 1,
+ RGB_24BPP: 2,
+ RGBA_32BPP: 3
+};
+
+var AnnotationType = {
+ 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
+};
+
+var AnnotationFlag = {
+ INVISIBLE: 0x01,
+ HIDDEN: 0x02,
+ PRINT: 0x04,
+ NOZOOM: 0x08,
+ NOROTATE: 0x10,
+ NOVIEW: 0x20,
+ READONLY: 0x40,
+ LOCKED: 0x80,
+ TOGGLENOVIEW: 0x100,
+ LOCKEDCONTENTS: 0x200
+};
+
+var AnnotationFieldFlag = {
+ 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,
+};
+
+var AnnotationBorderStyleType = {
+ SOLID: 1,
+ DASHED: 2,
+ BEVELED: 3,
+ INSET: 4,
+ UNDERLINE: 5
+};
+
+var StreamType = {
+ UNKNOWN: 0,
+ FLATE: 1,
+ LZW: 2,
+ DCT: 3,
+ JPX: 4,
+ JBIG: 5,
+ A85: 6,
+ AHX: 7,
+ CCF: 8,
+ RL: 9
+};
+
+var FontType = {
+ UNKNOWN: 0,
+ TYPE1: 1,
+ TYPE1C: 2,
+ CIDFONTTYPE0: 3,
+ CIDFONTTYPE0C: 4,
+ TRUETYPE: 5,
+ CIDFONTTYPE2: 6,
+ TYPE3: 7,
+ OPENTYPE: 8,
+ TYPE0: 9,
+ MMTYPE1: 10
+};
+
+var VERBOSITY_LEVELS = {
+ errors: 0,
+ warnings: 1,
+ infos: 5
+};
+
+// All the possible operations for an operator list.
+var OPS = {
+ // Intentionally start from 1 so it is easy to spot bad operators that will be
+ // 0's.
+ 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,
+ beginAnnotations: 78,
+ endAnnotations: 79,
+ beginAnnotation: 80,
+ endAnnotation: 81,
+ paintJpegXObject: 82,
+ paintImageMaskXObject: 83,
+ paintImageMaskXObjectGroup: 84,
+ paintImageXObject: 85,
+ paintInlineImageXObject: 86,
+ paintInlineImageXObjectGroup: 87,
+ paintImageXObjectRepeat: 88,
+ paintImageMaskXObjectRepeat: 89,
+ paintSolidColorImageMask: 90,
+ constructPath: 91
+};
+
+var verbosity = VERBOSITY_LEVELS.warnings;
+
+function setVerbosityLevel(level) {
+ verbosity = level;
+}
+
+function getVerbosityLevel() {
+ return verbosity;
+}
+
+// A notice for devs. These are good for things that are helpful to devs, such
+// as warning that Workers were disabled, which is important to devs but not
+// end users.
+function info(msg) {
+ if (verbosity >= VERBOSITY_LEVELS.infos) {
+ console.log('Info: ' + msg);
+ }
+}
+
+// Non-fatal warnings.
+function warn(msg) {
+ if (verbosity >= VERBOSITY_LEVELS.warnings) {
+ console.log('Warning: ' + msg);
+ }
+}
+
+// Deprecated API function -- display regardless of the PDFJS.verbosity setting.
+function deprecated(details) {
+ console.log('Deprecated API usage: ' + details);
+}
+
+// Fatal errors that should trigger the fallback UI and halt execution by
+// throwing an exception.
+function error(msg) {
+ if (verbosity >= VERBOSITY_LEVELS.errors) {
+ console.log('Error: ' + msg);
+ console.log(backtrace());
+ }
+ throw new Error(msg);
+}
+
+function backtrace() {
+ try {
+ throw new Error();
+ } catch (e) {
+ return e.stack ? e.stack.split('\n').slice(2).join('\n') : '';
+ }
+}
+
+function assert(cond, msg) {
+ if (!cond) {
+ error(msg);
+ }
+}
+
+var UNSUPPORTED_FEATURES = {
+ unknown: 'unknown',
+ forms: 'forms',
+ javaScript: 'javaScript',
+ smask: 'smask',
+ shadingPattern: 'shadingPattern',
+ font: 'font'
+};
+
+// Checks if URLs have the same origin. For non-HTTP based URLs, returns false.
+function isSameOrigin(baseUrl, otherUrl) {
+ try {
+ var base = new URL(baseUrl);
+ if (!base.origin || base.origin === 'null') {
+ return false; // non-HTTP url
+ }
+ } catch (e) {
+ return false;
+ }
+
+ var other = new URL(otherUrl, base);
+ return base.origin === other.origin;
+}
+
+// Validates if URL is safe and allowed, e.g. to avoid XSS.
+function isValidUrl(url, allowRelative) {
+ if (!url || typeof url !== 'string') {
+ return false;
+ }
+ // RFC 3986 (http://tools.ietf.org/html/rfc3986#section-3.1)
+ // scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
+ var protocol = /^[a-z][a-z0-9+\-.]*(?=:)/i.exec(url);
+ if (!protocol) {
+ return allowRelative;
+ }
+ protocol = protocol[0].toLowerCase();
+ switch (protocol) {
+ case 'http':
+ case 'https':
+ case 'ftp':
+ case 'mailto':
+ case 'tel':
+ return true;
+ default:
+ return false;
+ }
+}
+
+function shadow(obj, prop, value) {
+ Object.defineProperty(obj, prop, { value: value,
+ enumerable: true,
+ configurable: true,
+ writable: false });
+ return value;
+}
+
+function getLookupTableFactory(initializer) {
+ var lookup;
+ return function () {
+ if (initializer) {
+ lookup = Object.create(null);
+ initializer(lookup);
+ initializer = null;
+ }
+ return lookup;
+ };
+}
+
+var PasswordResponses = {
+ NEED_PASSWORD: 1,
+ INCORRECT_PASSWORD: 2
+};
+
+var PasswordException = (function PasswordExceptionClosure() {
+ function PasswordException(msg, code) {
+ this.name = 'PasswordException';
+ this.message = msg;
+ this.code = code;
+ }
+
+ PasswordException.prototype = new Error();
+ PasswordException.constructor = PasswordException;
+
+ return PasswordException;
+})();
+
+var UnknownErrorException = (function UnknownErrorExceptionClosure() {
+ function UnknownErrorException(msg, details) {
+ this.name = 'UnknownErrorException';
+ this.message = msg;
+ this.details = details;
+ }
+
+ UnknownErrorException.prototype = new Error();
+ UnknownErrorException.constructor = UnknownErrorException;
+
+ return UnknownErrorException;
+})();
+
+var InvalidPDFException = (function InvalidPDFExceptionClosure() {
+ function InvalidPDFException(msg) {
+ this.name = 'InvalidPDFException';
+ this.message = msg;
+ }
+
+ InvalidPDFException.prototype = new Error();
+ InvalidPDFException.constructor = InvalidPDFException;
+
+ return InvalidPDFException;
+})();
+
+var MissingPDFException = (function MissingPDFExceptionClosure() {
+ function MissingPDFException(msg) {
+ this.name = 'MissingPDFException';
+ this.message = msg;
+ }
+
+ MissingPDFException.prototype = new Error();
+ MissingPDFException.constructor = MissingPDFException;
+
+ return MissingPDFException;
+})();
+
+var UnexpectedResponseException =
+ (function UnexpectedResponseExceptionClosure() {
+ function UnexpectedResponseException(msg, status) {
+ this.name = 'UnexpectedResponseException';
+ this.message = msg;
+ this.status = status;
+ }
+
+ UnexpectedResponseException.prototype = new Error();
+ UnexpectedResponseException.constructor = UnexpectedResponseException;
+
+ return UnexpectedResponseException;
+})();
+
+var NotImplementedException = (function NotImplementedExceptionClosure() {
+ function NotImplementedException(msg) {
+ this.message = msg;
+ }
+
+ NotImplementedException.prototype = new Error();
+ NotImplementedException.prototype.name = 'NotImplementedException';
+ NotImplementedException.constructor = NotImplementedException;
+
+ return NotImplementedException;
+})();
+
+var MissingDataException = (function MissingDataExceptionClosure() {
+ function MissingDataException(begin, end) {
+ this.begin = begin;
+ this.end = end;
+ this.message = 'Missing data [' + begin + ', ' + end + ')';
+ }
+
+ MissingDataException.prototype = new Error();
+ MissingDataException.prototype.name = 'MissingDataException';
+ MissingDataException.constructor = MissingDataException;
+
+ return MissingDataException;
+})();
+
+var XRefParseException = (function XRefParseExceptionClosure() {
+ function XRefParseException(msg) {
+ this.message = msg;
+ }
+
+ XRefParseException.prototype = new Error();
+ XRefParseException.prototype.name = 'XRefParseException';
+ XRefParseException.constructor = XRefParseException;
+
+ return XRefParseException;
+})();
+
+var NullCharactersRegExp = /\x00/g;
+
+function removeNullCharacters(str) {
+ if (typeof str !== 'string') {
+ warn('The argument for removeNullCharacters must be a string.');
+ return str;
+ }
+ return str.replace(NullCharactersRegExp, '');
+}
+
+function bytesToString(bytes) {
+ assert(bytes !== null && typeof bytes === 'object' &&
+ bytes.length !== undefined, 'Invalid argument for bytesToString');
+ var length = bytes.length;
+ var MAX_ARGUMENT_COUNT = 8192;
+ if (length < MAX_ARGUMENT_COUNT) {
+ return String.fromCharCode.apply(null, bytes);
+ }
+ var strBuf = [];
+ for (var i = 0; i < length; i += MAX_ARGUMENT_COUNT) {
+ var chunkEnd = Math.min(i + MAX_ARGUMENT_COUNT, length);
+ var chunk = bytes.subarray(i, chunkEnd);
+ strBuf.push(String.fromCharCode.apply(null, chunk));
+ }
+ return strBuf.join('');
+}
+
+function stringToBytes(str) {
+ assert(typeof str === 'string', 'Invalid argument for stringToBytes');
+ var length = str.length;
+ var bytes = new Uint8Array(length);
+ for (var i = 0; i < length; ++i) {
+ bytes[i] = str.charCodeAt(i) & 0xFF;
+ }
+ return bytes;
+}
+
+/**
+ * Gets length of the array (Array, Uint8Array, or string) in bytes.
+ * @param {Array|Uint8Array|string} arr
+ * @returns {number}
+ */
+function arrayByteLength(arr) {
+ if (arr.length !== undefined) {
+ return arr.length;
+ }
+ assert(arr.byteLength !== undefined);
+ return arr.byteLength;
+}
+
+/**
+ * Combines array items (arrays) into single Uint8Array object.
+ * @param {Array} arr - the array of the arrays (Array, Uint8Array, or string).
+ * @returns {Uint8Array}
+ */
+function arraysToBytes(arr) {
+ // Shortcut: if first and only item is Uint8Array, return it.
+ if (arr.length === 1 && (arr[0] instanceof Uint8Array)) {
+ return arr[0];
+ }
+ var resultLength = 0;
+ var i, ii = arr.length;
+ var item, itemLength ;
+ for (i = 0; i < ii; i++) {
+ item = arr[i];
+ itemLength = arrayByteLength(item);
+ resultLength += itemLength;
+ }
+ var pos = 0;
+ var data = new Uint8Array(resultLength);
+ for (i = 0; i < ii; i++) {
+ item = arr[i];
+ if (!(item instanceof Uint8Array)) {
+ if (typeof item === 'string') {
+ item = stringToBytes(item);
+ } else {
+ item = new Uint8Array(item);
+ }
+ }
+ itemLength = item.byteLength;
+ data.set(item, pos);
+ pos += itemLength;
+ }
+ return data;
+}
+
+function string32(value) {
+ return String.fromCharCode((value >> 24) & 0xff, (value >> 16) & 0xff,
+ (value >> 8) & 0xff, value & 0xff);
+}
+
+function log2(x) {
+ var n = 1, i = 0;
+ while (x > n) {
+ n <<= 1;
+ i++;
+ }
+ return i;
+}
+
+function readInt8(data, start) {
+ return (data[start] << 24) >> 24;
+}
+
+function readUint16(data, offset) {
+ return (data[offset] << 8) | data[offset + 1];
+}
+
+function readUint32(data, offset) {
+ return ((data[offset] << 24) | (data[offset + 1] << 16) |
+ (data[offset + 2] << 8) | data[offset + 3]) >>> 0;
+}
+
+// Lazy test the endianness of the platform
+// NOTE: This will be 'true' for simulated TypedArrays
+function isLittleEndian() {
+ var buffer8 = new Uint8Array(2);
+ buffer8[0] = 1;
+ var buffer16 = new Uint16Array(buffer8.buffer);
+ return (buffer16[0] === 1);
+}
+
+// Checks if it's possible to eval JS expressions.
+function isEvalSupported() {
+ try {
+ /* jshint evil: true */
+ new Function('');
+ return true;
+ } catch (e) {
+ return false;
+ }
+}
+
+var Uint32ArrayView = (function Uint32ArrayViewClosure() {
+
+ function Uint32ArrayView(buffer, length) {
+ this.buffer = buffer;
+ this.byteLength = buffer.length;
+ this.length = length === undefined ? (this.byteLength >> 2) : length;
+ ensureUint32ArrayViewProps(this.length);
+ }
+ Uint32ArrayView.prototype = Object.create(null);
+
+ var uint32ArrayViewSetters = 0;
+ function createUint32ArrayProp(index) {
+ return {
+ get: function () {
+ var buffer = this.buffer, offset = index << 2;
+ return (buffer[offset] | (buffer[offset + 1] << 8) |
+ (buffer[offset + 2] << 16) | (buffer[offset + 3] << 24)) >>> 0;
+ },
+ set: function (value) {
+ var buffer = this.buffer, offset = index << 2;
+ buffer[offset] = value & 255;
+ buffer[offset + 1] = (value >> 8) & 255;
+ buffer[offset + 2] = (value >> 16) & 255;
+ buffer[offset + 3] = (value >>> 24) & 255;
+ }
+ };
+ }
+
+ function ensureUint32ArrayViewProps(length) {
+ while (uint32ArrayViewSetters < length) {
+ Object.defineProperty(Uint32ArrayView.prototype,
+ uint32ArrayViewSetters,
+ createUint32ArrayProp(uint32ArrayViewSetters));
+ uint32ArrayViewSetters++;
+ }
+ }
+
+ return Uint32ArrayView;
+})();
+
+exports.Uint32ArrayView = Uint32ArrayView;
+
+var IDENTITY_MATRIX = [1, 0, 0, 1, 0, 0];
+
+var Util = (function UtilClosure() {
+ function Util() {}
+
+ var rgbBuf = ['rgb(', 0, ',', 0, ',', 0, ')'];
+
+ // makeCssRgb() can be called thousands of times. Using |rgbBuf| avoids
+ // creating many intermediate strings.
+ Util.makeCssRgb = function Util_makeCssRgb(r, g, b) {
+ rgbBuf[1] = r;
+ rgbBuf[3] = g;
+ rgbBuf[5] = b;
+ return rgbBuf.join('');
+ };
+
+ // Concatenates two transformation matrices together and returns the result.
+ Util.transform = function Util_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]
+ ];
+ };
+
+ // For 2d affine transforms
+ Util.applyTransform = function Util_applyTransform(p, m) {
+ var xt = p[0] * m[0] + p[1] * m[2] + m[4];
+ var yt = p[0] * m[1] + p[1] * m[3] + m[5];
+ return [xt, yt];
+ };
+
+ Util.applyInverseTransform = function Util_applyInverseTransform(p, m) {
+ var d = m[0] * m[3] - m[1] * m[2];
+ var xt = (p[0] * m[3] - p[1] * m[2] + m[2] * m[5] - m[4] * m[3]) / d;
+ var yt = (-p[0] * m[1] + p[1] * m[0] + m[4] * m[1] - m[5] * m[0]) / d;
+ return [xt, yt];
+ };
+
+ // Applies the transform to the rectangle and finds the minimum axially
+ // aligned bounding box.
+ Util.getAxialAlignedBoundingBox =
+ function Util_getAxialAlignedBoundingBox(r, m) {
+
+ var p1 = Util.applyTransform(r, m);
+ var p2 = Util.applyTransform(r.slice(2, 4), m);
+ var p3 = Util.applyTransform([r[0], r[3]], m);
+ var p4 = Util.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])
+ ];
+ };
+
+ Util.inverseTransform = function Util_inverseTransform(m) {
+ var 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];
+ };
+
+ // Apply a generic 3d matrix M on a 3-vector v:
+ // | a b c | | X |
+ // | d e f | x | Y |
+ // | g h i | | Z |
+ // M is assumed to be serialized as [a,b,c,d,e,f,g,h,i],
+ // with v as [X,Y,Z]
+ Util.apply3dTransform = function Util_apply3dTransform(m, v) {
+ return [
+ m[0] * v[0] + m[1] * v[1] + m[2] * v[2],
+ m[3] * v[0] + m[4] * v[1] + m[5] * v[2],
+ m[6] * v[0] + m[7] * v[1] + m[8] * v[2]
+ ];
+ };
+
+ // This calculation uses Singular Value Decomposition.
+ // The SVD can be represented with formula A = USV. We are interested in the
+ // matrix S here because it represents the scale values.
+ Util.singularValueDecompose2dScale =
+ function Util_singularValueDecompose2dScale(m) {
+
+ var transpose = [m[0], m[2], m[1], m[3]];
+
+ // Multiply matrix m with its transpose.
+ var a = m[0] * transpose[0] + m[1] * transpose[2];
+ var b = m[0] * transpose[1] + m[1] * transpose[3];
+ var c = m[2] * transpose[0] + m[3] * transpose[2];
+ var d = m[2] * transpose[1] + m[3] * transpose[3];
+
+ // Solve the second degree polynomial to get roots.
+ var first = (a + d) / 2;
+ var second = Math.sqrt((a + d) * (a + d) - 4 * (a * d - c * b)) / 2;
+ var sx = first + second || 1;
+ var sy = first - second || 1;
+
+ // Scale values are the square roots of the eigenvalues.
+ return [Math.sqrt(sx), Math.sqrt(sy)];
+ };
+
+ // Normalize rectangle rect=[x1, y1, x2, y2] so that (x1,y1) < (x2,y2)
+ // For coordinate systems whose origin lies in the bottom-left, this
+ // means normalization to (BL,TR) ordering. For systems with origin in the
+ // top-left, this means (TL,BR) ordering.
+ Util.normalizeRect = function Util_normalizeRect(rect) {
+ var r = rect.slice(0); // clone rect
+ 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;
+ };
+
+ // Returns a rectangle [x1, y1, x2, y2] corresponding to the
+ // intersection of rect1 and rect2. If no intersection, returns 'false'
+ // The rectangle coordinates of rect1, rect2 should be [x1, y1, x2, y2]
+ Util.intersect = function Util_intersect(rect1, rect2) {
+ function compare(a, b) {
+ return a - b;
+ }
+
+ // Order points along the axes
+ var orderedX = [rect1[0], rect1[2], rect2[0], rect2[2]].sort(compare),
+ orderedY = [rect1[1], rect1[3], rect2[1], rect2[3]].sort(compare),
+ result = [];
+
+ rect1 = Util.normalizeRect(rect1);
+ rect2 = Util.normalizeRect(rect2);
+
+ // X: first and second points belong to different rectangles?
+ if ((orderedX[0] === rect1[0] && orderedX[1] === rect2[0]) ||
+ (orderedX[0] === rect2[0] && orderedX[1] === rect1[0])) {
+ // Intersection must be between second and third points
+ result[0] = orderedX[1];
+ result[2] = orderedX[2];
+ } else {
+ return false;
+ }
+
+ // Y: first and second points belong to different rectangles?
+ if ((orderedY[0] === rect1[1] && orderedY[1] === rect2[1]) ||
+ (orderedY[0] === rect2[1] && orderedY[1] === rect1[1])) {
+ // Intersection must be between second and third points
+ result[1] = orderedY[1];
+ result[3] = orderedY[2];
+ } else {
+ return false;
+ }
+
+ return result;
+ };
+
+ Util.sign = function Util_sign(num) {
+ return num < 0 ? -1 : 1;
+ };
+
+ var ROMAN_NUMBER_MAP = [
+ '', 'C', 'CC', 'CCC', 'CD', 'D', 'DC', 'DCC', 'DCCC', 'CM',
+ '', 'X', 'XX', 'XXX', 'XL', 'L', 'LX', 'LXX', 'LXXX', 'XC',
+ '', 'I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX'
+ ];
+ /**
+ * Converts positive integers to (upper case) Roman numerals.
+ * @param {integer} number - The number that should be converted.
+ * @param {boolean} lowerCase - Indicates if the result should be converted
+ * to lower case letters. The default is false.
+ * @return {string} The resulting Roman number.
+ */
+ Util.toRoman = function Util_toRoman(number, lowerCase) {
+ assert(isInt(number) && number > 0,
+ 'The number should be a positive integer.');
+ var pos, romanBuf = [];
+ // Thousands
+ while (number >= 1000) {
+ number -= 1000;
+ romanBuf.push('M');
+ }
+ // Hundreds
+ pos = (number / 100) | 0;
+ number %= 100;
+ romanBuf.push(ROMAN_NUMBER_MAP[pos]);
+ // Tens
+ pos = (number / 10) | 0;
+ number %= 10;
+ romanBuf.push(ROMAN_NUMBER_MAP[10 + pos]);
+ // Ones
+ romanBuf.push(ROMAN_NUMBER_MAP[20 + number]);
+
+ var romanStr = romanBuf.join('');
+ return (lowerCase ? romanStr.toLowerCase() : romanStr);
+ };
+
+ Util.appendToArray = function Util_appendToArray(arr1, arr2) {
+ Array.prototype.push.apply(arr1, arr2);
+ };
+
+ Util.prependToArray = function Util_prependToArray(arr1, arr2) {
+ Array.prototype.unshift.apply(arr1, arr2);
+ };
+
+ Util.extendObj = function extendObj(obj1, obj2) {
+ for (var key in obj2) {
+ obj1[key] = obj2[key];
+ }
+ };
+
+ Util.getInheritableProperty = function Util_getInheritableProperty(dict,
+ name) {
+ while (dict && !dict.has(name)) {
+ dict = dict.get('Parent');
+ }
+ if (!dict) {
+ return null;
+ }
+ return dict.get(name);
+ };
+
+ Util.inherit = function Util_inherit(sub, base, prototype) {
+ sub.prototype = Object.create(base.prototype);
+ sub.prototype.constructor = sub;
+ for (var prop in prototype) {
+ sub.prototype[prop] = prototype[prop];
+ }
+ };
+
+ Util.loadScript = function Util_loadScript(src, callback) {
+ var script = document.createElement('script');
+ var loaded = false;
+ script.setAttribute('src', src);
+ if (callback) {
+ script.onload = function() {
+ if (!loaded) {
+ callback();
+ }
+ loaded = true;
+ };
+ }
+ document.getElementsByTagName('head')[0].appendChild(script);
+ };
+
+ return Util;
+})();
+
+/**
+ * PDF page viewport created based on scale, rotation and offset.
+ * @class
+ * @alias PageViewport
+ */
+var PageViewport = (function PageViewportClosure() {
+ /**
+ * @constructor
+ * @private
+ * @param viewBox {Array} xMin, yMin, xMax and yMax coordinates.
+ * @param scale {number} scale of the viewport.
+ * @param rotation {number} rotations of the viewport in degrees.
+ * @param offsetX {number} offset X
+ * @param offsetY {number} offset Y
+ * @param dontFlip {boolean} if true, axis Y will not be flipped.
+ */
+ function PageViewport(viewBox, scale, rotation, offsetX, offsetY, dontFlip) {
+ this.viewBox = viewBox;
+ this.scale = scale;
+ this.rotation = rotation;
+ this.offsetX = offsetX;
+ this.offsetY = offsetY;
+
+ // creating transform to convert pdf coordinate system to the normal
+ // canvas like coordinates taking in account scale and rotation
+ var centerX = (viewBox[2] + viewBox[0]) / 2;
+ var centerY = (viewBox[3] + viewBox[1]) / 2;
+ var rotateA, rotateB, rotateC, rotateD;
+ rotation = rotation % 360;
+ rotation = rotation < 0 ? rotation + 360 : rotation;
+ 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:
+ default:
+ rotateA = 1; rotateB = 0; rotateC = 0; rotateD = -1;
+ break;
+ }
+
+ if (dontFlip) {
+ rotateC = -rotateC; rotateD = -rotateD;
+ }
+
+ var offsetCanvasX, offsetCanvasY;
+ var width, height;
+ if (rotateA === 0) {
+ offsetCanvasX = Math.abs(centerY - viewBox[1]) * scale + offsetX;
+ offsetCanvasY = Math.abs(centerX - viewBox[0]) * scale + offsetY;
+ width = Math.abs(viewBox[3] - viewBox[1]) * scale;
+ height = Math.abs(viewBox[2] - viewBox[0]) * scale;
+ } else {
+ offsetCanvasX = Math.abs(centerX - viewBox[0]) * scale + offsetX;
+ offsetCanvasY = Math.abs(centerY - viewBox[1]) * scale + offsetY;
+ width = Math.abs(viewBox[2] - viewBox[0]) * scale;
+ height = Math.abs(viewBox[3] - viewBox[1]) * scale;
+ }
+ // creating transform for the following operations:
+ // translate(-centerX, -centerY), rotate and flip vertically,
+ // scale, and translate(offsetCanvasX, offsetCanvasY)
+ 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;
+ this.fontScale = scale;
+ }
+ PageViewport.prototype = /** @lends PageViewport.prototype */ {
+ /**
+ * Clones viewport with additional properties.
+ * @param args {Object} (optional) If specified, may contain the 'scale' or
+ * 'rotation' properties to override the corresponding properties in
+ * the cloned viewport.
+ * @returns {PageViewport} Cloned viewport.
+ */
+ clone: function PageViewPort_clone(args) {
+ args = args || {};
+ var scale = 'scale' in args ? args.scale : this.scale;
+ var rotation = 'rotation' in args ? args.rotation : this.rotation;
+ return new PageViewport(this.viewBox.slice(), scale, rotation,
+ this.offsetX, this.offsetY, args.dontFlip);
+ },
+ /**
+ * Converts PDF point to the viewport coordinates. For examples, useful for
+ * converting PDF location into canvas pixel coordinates.
+ * @param x {number} X coordinate.
+ * @param y {number} Y coordinate.
+ * @returns {Object} Object that contains 'x' and 'y' properties of the
+ * point in the viewport coordinate space.
+ * @see {@link convertToPdfPoint}
+ * @see {@link convertToViewportRectangle}
+ */
+ convertToViewportPoint: function PageViewport_convertToViewportPoint(x, y) {
+ return Util.applyTransform([x, y], this.transform);
+ },
+ /**
+ * Converts PDF rectangle to the viewport coordinates.
+ * @param rect {Array} xMin, yMin, xMax and yMax coordinates.
+ * @returns {Array} Contains corresponding coordinates of the rectangle
+ * in the viewport coordinate space.
+ * @see {@link convertToViewportPoint}
+ */
+ convertToViewportRectangle:
+ function PageViewport_convertToViewportRectangle(rect) {
+ var tl = Util.applyTransform([rect[0], rect[1]], this.transform);
+ var br = Util.applyTransform([rect[2], rect[3]], this.transform);
+ return [tl[0], tl[1], br[0], br[1]];
+ },
+ /**
+ * Converts viewport coordinates to the PDF location. For examples, useful
+ * for converting canvas pixel location into PDF one.
+ * @param x {number} X coordinate.
+ * @param y {number} Y coordinate.
+ * @returns {Object} Object that contains 'x' and 'y' properties of the
+ * point in the PDF coordinate space.
+ * @see {@link convertToViewportPoint}
+ */
+ convertToPdfPoint: function PageViewport_convertToPdfPoint(x, y) {
+ return Util.applyInverseTransform([x, y], this.transform);
+ }
+ };
+ return PageViewport;
+})();
+
+var PDFStringTranslateTable = [
+ 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
+];
+
+function stringToPDFString(str) {
+ var i, n = str.length, strBuf = [];
+ if (str[0] === '\xFE' && str[1] === '\xFF') {
+ // UTF16BE BOM
+ for (i = 2; i < n; i += 2) {
+ strBuf.push(String.fromCharCode(
+ (str.charCodeAt(i) << 8) | str.charCodeAt(i + 1)));
+ }
+ } else {
+ for (i = 0; i < n; ++i) {
+ var code = PDFStringTranslateTable[str.charCodeAt(i)];
+ strBuf.push(code ? String.fromCharCode(code) : str.charAt(i));
+ }
+ }
+ return strBuf.join('');
+}
+
+function stringToUTF8String(str) {
+ return decodeURIComponent(escape(str));
+}
+
+function utf8StringToString(str) {
+ return unescape(encodeURIComponent(str));
+}
+
+function isEmptyObj(obj) {
+ for (var key in obj) {
+ return false;
+ }
+ return true;
+}
+
+function isBool(v) {
+ return typeof v === 'boolean';
+}
+
+function isInt(v) {
+ return typeof v === 'number' && ((v | 0) === v);
+}
+
+function isNum(v) {
+ return typeof v === 'number';
+}
+
+function isString(v) {
+ return typeof v === 'string';
+}
+
+function isArray(v) {
+ return v instanceof Array;
+}
+
+function isArrayBuffer(v) {
+ return typeof v === 'object' && v !== null && v.byteLength !== undefined;
+}
+
+// Checks if ch is one of the following characters: SPACE, TAB, CR or LF.
+function isSpace(ch) {
+ return (ch === 0x20 || ch === 0x09 || ch === 0x0D || ch === 0x0A);
+}
+
+/**
+ * Promise Capability object.
+ *
+ * @typedef {Object} PromiseCapability
+ * @property {Promise} promise - A promise object.
+ * @property {function} resolve - Fulfills the promise.
+ * @property {function} reject - Rejects the promise.
+ */
+
+/**
+ * Creates a promise capability object.
+ * @alias createPromiseCapability
+ *
+ * @return {PromiseCapability} A capability object contains:
+ * - a Promise, resolve and reject methods.
+ */
+function createPromiseCapability() {
+ var capability = {};
+ capability.promise = new Promise(function (resolve, reject) {
+ capability.resolve = resolve;
+ capability.reject = reject;
+ });
+ return capability;
+}
+
+/**
+ * Polyfill for Promises:
+ * The following promise implementation tries to generally implement the
+ * Promise/A+ spec. Some notable differences from other promise libraries are:
+ * - There currently isn't a separate deferred and promise object.
+ * - Unhandled rejections eventually show an error if they aren't handled.
+ *
+ * Based off of the work in:
+ * https://bugzilla.mozilla.org/show_bug.cgi?id=810490
+ */
+(function PromiseClosure() {
+ if (globalScope.Promise) {
+ // Promises existing in the DOM/Worker, checking presence of all/resolve
+ if (typeof globalScope.Promise.all !== 'function') {
+ globalScope.Promise.all = function (iterable) {
+ var count = 0, results = [], resolve, reject;
+ var promise = new globalScope.Promise(function (resolve_, reject_) {
+ resolve = resolve_;
+ reject = reject_;
+ });
+ iterable.forEach(function (p, i) {
+ count++;
+ p.then(function (result) {
+ results[i] = result;
+ count--;
+ if (count === 0) {
+ resolve(results);
+ }
+ }, reject);
+ });
+ if (count === 0) {
+ resolve(results);
+ }
+ return promise;
+ };
+ }
+ if (typeof globalScope.Promise.resolve !== 'function') {
+ globalScope.Promise.resolve = function (value) {
+ return new globalScope.Promise(function (resolve) { resolve(value); });
+ };
+ }
+ if (typeof globalScope.Promise.reject !== 'function') {
+ globalScope.Promise.reject = function (reason) {
+ return new globalScope.Promise(function (resolve, reject) {
+ reject(reason);
+ });
+ };
+ }
+ if (typeof globalScope.Promise.prototype.catch !== 'function') {
+ globalScope.Promise.prototype.catch = function (onReject) {
+ return globalScope.Promise.prototype.then(undefined, onReject);
+ };
+ }
+ return;
+ }
+ var STATUS_PENDING = 0;
+ var STATUS_RESOLVED = 1;
+ var STATUS_REJECTED = 2;
+
+ // In an attempt to avoid silent exceptions, unhandled rejections are
+ // tracked and if they aren't handled in a certain amount of time an
+ // error is logged.
+ var REJECTION_TIMEOUT = 500;
+
+ var HandlerManager = {
+ handlers: [],
+ running: false,
+ unhandledRejections: [],
+ pendingRejectionCheck: false,
+
+ scheduleHandlers: function scheduleHandlers(promise) {
+ if (promise._status === STATUS_PENDING) {
+ return;
+ }
+
+ this.handlers = this.handlers.concat(promise._handlers);
+ promise._handlers = [];
+
+ if (this.running) {
+ return;
+ }
+ this.running = true;
+
+ setTimeout(this.runHandlers.bind(this), 0);
+ },
+
+ runHandlers: function runHandlers() {
+ var RUN_TIMEOUT = 1; // ms
+ var timeoutAt = Date.now() + RUN_TIMEOUT;
+ while (this.handlers.length > 0) {
+ var handler = this.handlers.shift();
+
+ var nextStatus = handler.thisPromise._status;
+ var nextValue = handler.thisPromise._value;
+
+ try {
+ if (nextStatus === STATUS_RESOLVED) {
+ if (typeof handler.onResolve === 'function') {
+ nextValue = handler.onResolve(nextValue);
+ }
+ } else if (typeof handler.onReject === 'function') {
+ nextValue = handler.onReject(nextValue);
+ nextStatus = STATUS_RESOLVED;
+
+ if (handler.thisPromise._unhandledRejection) {
+ this.removeUnhandeledRejection(handler.thisPromise);
+ }
+ }
+ } catch (ex) {
+ nextStatus = STATUS_REJECTED;
+ nextValue = ex;
+ }
+
+ handler.nextPromise._updateStatus(nextStatus, nextValue);
+ if (Date.now() >= timeoutAt) {
+ break;
+ }
+ }
+
+ if (this.handlers.length > 0) {
+ setTimeout(this.runHandlers.bind(this), 0);
+ return;
+ }
+
+ this.running = false;
+ },
+
+ addUnhandledRejection: function addUnhandledRejection(promise) {
+ this.unhandledRejections.push({
+ promise: promise,
+ time: Date.now()
+ });
+ this.scheduleRejectionCheck();
+ },
+
+ removeUnhandeledRejection: function removeUnhandeledRejection(promise) {
+ promise._unhandledRejection = false;
+ for (var i = 0; i < this.unhandledRejections.length; i++) {
+ if (this.unhandledRejections[i].promise === promise) {
+ this.unhandledRejections.splice(i);
+ i--;
+ }
+ }
+ },
+
+ scheduleRejectionCheck: function scheduleRejectionCheck() {
+ if (this.pendingRejectionCheck) {
+ return;
+ }
+ this.pendingRejectionCheck = true;
+ setTimeout(function rejectionCheck() {
+ this.pendingRejectionCheck = false;
+ var now = Date.now();
+ for (var i = 0; i < this.unhandledRejections.length; i++) {
+ if (now - this.unhandledRejections[i].time > REJECTION_TIMEOUT) {
+ var unhandled = this.unhandledRejections[i].promise._value;
+ var msg = 'Unhandled rejection: ' + unhandled;
+ if (unhandled.stack) {
+ msg += '\n' + unhandled.stack;
+ }
+ warn(msg);
+ this.unhandledRejections.splice(i);
+ i--;
+ }
+ }
+ if (this.unhandledRejections.length) {
+ this.scheduleRejectionCheck();
+ }
+ }.bind(this), REJECTION_TIMEOUT);
+ }
+ };
+
+ function Promise(resolver) {
+ this._status = STATUS_PENDING;
+ this._handlers = [];
+ try {
+ resolver.call(this, this._resolve.bind(this), this._reject.bind(this));
+ } catch (e) {
+ this._reject(e);
+ }
+ }
+ /**
+ * Builds a promise that is resolved when all the passed in promises are
+ * resolved.
+ * @param {array} promises array of data and/or promises to wait for.
+ * @return {Promise} New dependent promise.
+ */
+ Promise.all = function Promise_all(promises) {
+ var resolveAll, rejectAll;
+ var deferred = new Promise(function (resolve, reject) {
+ resolveAll = resolve;
+ rejectAll = reject;
+ });
+ var unresolved = promises.length;
+ var results = [];
+ if (unresolved === 0) {
+ resolveAll(results);
+ return deferred;
+ }
+ function reject(reason) {
+ if (deferred._status === STATUS_REJECTED) {
+ return;
+ }
+ results = [];
+ rejectAll(reason);
+ }
+ for (var i = 0, ii = promises.length; i < ii; ++i) {
+ var promise = promises[i];
+ var resolve = (function(i) {
+ return function(value) {
+ if (deferred._status === STATUS_REJECTED) {
+ return;
+ }
+ results[i] = value;
+ unresolved--;
+ if (unresolved === 0) {
+ resolveAll(results);
+ }
+ };
+ })(i);
+ if (Promise.isPromise(promise)) {
+ promise.then(resolve, reject);
+ } else {
+ resolve(promise);
+ }
+ }
+ return deferred;
+ };
+
+ /**
+ * Checks if the value is likely a promise (has a 'then' function).
+ * @return {boolean} true if value is thenable
+ */
+ Promise.isPromise = function Promise_isPromise(value) {
+ return value && typeof value.then === 'function';
+ };
+
+ /**
+ * Creates resolved promise
+ * @param value resolve value
+ * @returns {Promise}
+ */
+ Promise.resolve = function Promise_resolve(value) {
+ return new Promise(function (resolve) { resolve(value); });
+ };
+
+ /**
+ * Creates rejected promise
+ * @param reason rejection value
+ * @returns {Promise}
+ */
+ Promise.reject = function Promise_reject(reason) {
+ return new Promise(function (resolve, reject) { reject(reason); });
+ };
+
+ Promise.prototype = {
+ _status: null,
+ _value: null,
+ _handlers: null,
+ _unhandledRejection: null,
+
+ _updateStatus: function Promise__updateStatus(status, value) {
+ if (this._status === STATUS_RESOLVED ||
+ this._status === STATUS_REJECTED) {
+ return;
+ }
+
+ if (status === STATUS_RESOLVED &&
+ Promise.isPromise(value)) {
+ value.then(this._updateStatus.bind(this, STATUS_RESOLVED),
+ this._updateStatus.bind(this, STATUS_REJECTED));
+ return;
+ }
+
+ this._status = status;
+ this._value = value;
+
+ if (status === STATUS_REJECTED && this._handlers.length === 0) {
+ this._unhandledRejection = true;
+ HandlerManager.addUnhandledRejection(this);
+ }
+
+ HandlerManager.scheduleHandlers(this);
+ },
+
+ _resolve: function Promise_resolve(value) {
+ this._updateStatus(STATUS_RESOLVED, value);
+ },
+
+ _reject: function Promise_reject(reason) {
+ this._updateStatus(STATUS_REJECTED, reason);
+ },
+
+ then: function Promise_then(onResolve, onReject) {
+ var nextPromise = new Promise(function (resolve, reject) {
+ this.resolve = resolve;
+ this.reject = reject;
+ });
+ this._handlers.push({
+ thisPromise: this,
+ onResolve: onResolve,
+ onReject: onReject,
+ nextPromise: nextPromise
+ });
+ HandlerManager.scheduleHandlers(this);
+ return nextPromise;
+ },
+
+ catch: function Promise_catch(onReject) {
+ return this.then(undefined, onReject);
+ }
+ };
+
+ globalScope.Promise = Promise;
+})();
+
+(function WeakMapClosure() {
+ if (globalScope.WeakMap) {
+ return;
+ }
+
+ var id = 0;
+ function WeakMap() {
+ this.id = '$weakmap' + (id++);
+ }
+ WeakMap.prototype = {
+ has: function(obj) {
+ return !!Object.getOwnPropertyDescriptor(obj, this.id);
+ },
+ get: function(obj, defaultValue) {
+ return this.has(obj) ? obj[this.id] : defaultValue;
+ },
+ set: function(obj, value) {
+ Object.defineProperty(obj, this.id, {
+ value: value,
+ enumerable: false,
+ configurable: true
+ });
+ },
+ delete: function(obj) {
+ delete obj[this.id];
+ }
+ };
+
+ globalScope.WeakMap = WeakMap;
+})();
+
+var StatTimer = (function StatTimerClosure() {
+ function rpad(str, pad, length) {
+ while (str.length < length) {
+ str += pad;
+ }
+ return str;
+ }
+ function StatTimer() {
+ this.started = Object.create(null);
+ this.times = [];
+ this.enabled = true;
+ }
+ StatTimer.prototype = {
+ time: function StatTimer_time(name) {
+ if (!this.enabled) {
+ return;
+ }
+ if (name in this.started) {
+ warn('Timer is already running for ' + name);
+ }
+ this.started[name] = Date.now();
+ },
+ timeEnd: function StatTimer_timeEnd(name) {
+ if (!this.enabled) {
+ return;
+ }
+ if (!(name in this.started)) {
+ warn('Timer has not been started for ' + name);
+ }
+ this.times.push({
+ 'name': name,
+ 'start': this.started[name],
+ 'end': Date.now()
+ });
+ // Remove timer from started so it can be called again.
+ delete this.started[name];
+ },
+ toString: function StatTimer_toString() {
+ var i, ii;
+ var times = this.times;
+ var out = '';
+ // Find the longest name for padding purposes.
+ var longest = 0;
+ for (i = 0, ii = times.length; i < ii; ++i) {
+ var name = times[i]['name'];
+ if (name.length > longest) {
+ longest = name.length;
+ }
+ }
+ for (i = 0, ii = times.length; i < ii; ++i) {
+ var span = times[i];
+ var duration = span.end - span.start;
+ out += rpad(span['name'], ' ', longest) + ' ' + duration + 'ms\n';
+ }
+ return out;
+ }
+ };
+ return StatTimer;
+})();
+
+var createBlob = function createBlob(data, contentType) {
+ if (typeof Blob !== 'undefined') {
+ return new Blob([data], { type: contentType });
+ }
+ warn('The "Blob" constructor is not supported.');
+};
+
+var createObjectURL = (function createObjectURLClosure() {
+ // Blob/createObjectURL is not available, falling back to data schema.
+ var digits =
+ 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
+
+ return function createObjectURL(data, contentType, forceDataSchema) {
+ if (!forceDataSchema &&
+ typeof URL !== 'undefined' && URL.createObjectURL) {
+ var blob = createBlob(data, contentType);
+ return URL.createObjectURL(blob);
+ }
+
+ var buffer = 'data:' + contentType + ';base64,';
+ for (var i = 0, ii = data.length; i < ii; i += 3) {
+ var b1 = data[i] & 0xFF;
+ var b2 = data[i + 1] & 0xFF;
+ var b3 = data[i + 2] & 0xFF;
+ var d1 = b1 >> 2, d2 = ((b1 & 3) << 4) | (b2 >> 4);
+ var d3 = i + 1 < ii ? ((b2 & 0xF) << 2) | (b3 >> 6) : 64;
+ var d4 = i + 2 < ii ? (b3 & 0x3F) : 64;
+ buffer += digits[d1] + digits[d2] + digits[d3] + digits[d4];
+ }
+ return buffer;
+ };
+})();
+
+function MessageHandler(sourceName, targetName, comObj) {
+ this.sourceName = sourceName;
+ this.targetName = targetName;
+ this.comObj = comObj;
+ this.callbackIndex = 1;
+ this.postMessageTransfers = true;
+ var callbacksCapabilities = this.callbacksCapabilities = Object.create(null);
+ var ah = this.actionHandler = Object.create(null);
+
+ this._onComObjOnMessage = function messageHandlerComObjOnMessage(event) {
+ var data = event.data;
+ if (data.targetName !== this.sourceName) {
+ return;
+ }
+ if (data.isReply) {
+ var callbackId = data.callbackId;
+ if (data.callbackId in callbacksCapabilities) {
+ var callback = callbacksCapabilities[callbackId];
+ delete callbacksCapabilities[callbackId];
+ if ('error' in data) {
+ callback.reject(data.error);
+ } else {
+ callback.resolve(data.data);
+ }
+ } else {
+ error('Cannot resolve callback ' + callbackId);
+ }
+ } else if (data.action in ah) {
+ var action = ah[data.action];
+ if (data.callbackId) {
+ var sourceName = this.sourceName;
+ var targetName = data.sourceName;
+ Promise.resolve().then(function () {
+ return action[0].call(action[1], data.data);
+ }).then(function (result) {
+ comObj.postMessage({
+ sourceName: sourceName,
+ targetName: targetName,
+ isReply: true,
+ callbackId: data.callbackId,
+ data: result
+ });
+ }, function (reason) {
+ if (reason instanceof Error) {
+ // Serialize error to avoid "DataCloneError"
+ reason = reason + '';
+ }
+ comObj.postMessage({
+ sourceName: sourceName,
+ targetName: targetName,
+ isReply: true,
+ callbackId: data.callbackId,
+ error: reason
+ });
+ });
+ } else {
+ action[0].call(action[1], data.data);
+ }
+ } else {
+ error('Unknown action from worker: ' + data.action);
+ }
+ }.bind(this);
+ comObj.addEventListener('message', this._onComObjOnMessage);
+}
+
+MessageHandler.prototype = {
+ on: function messageHandlerOn(actionName, handler, scope) {
+ var ah = this.actionHandler;
+ if (ah[actionName]) {
+ error('There is already an actionName called "' + actionName + '"');
+ }
+ ah[actionName] = [handler, scope];
+ },
+ /**
+ * Sends a message to the comObj to invoke the action with the supplied data.
+ * @param {String} actionName Action to call.
+ * @param {JSON} data JSON data to send.
+ * @param {Array} [transfers] Optional list of transfers/ArrayBuffers
+ */
+ send: function messageHandlerSend(actionName, data, transfers) {
+ var message = {
+ sourceName: this.sourceName,
+ targetName: this.targetName,
+ action: actionName,
+ data: data
+ };
+ this.postMessage(message, transfers);
+ },
+ /**
+ * Sends a message to the comObj to invoke the action with the supplied data.
+ * Expects that other side will callback with the response.
+ * @param {String} actionName Action to call.
+ * @param {JSON} data JSON data to send.
+ * @param {Array} [transfers] Optional list of transfers/ArrayBuffers.
+ * @returns {Promise} Promise to be resolved with response data.
+ */
+ sendWithPromise:
+ function messageHandlerSendWithPromise(actionName, data, transfers) {
+ var callbackId = this.callbackIndex++;
+ var message = {
+ sourceName: this.sourceName,
+ targetName: this.targetName,
+ action: actionName,
+ data: data,
+ callbackId: callbackId
+ };
+ var capability = createPromiseCapability();
+ this.callbacksCapabilities[callbackId] = capability;
+ try {
+ this.postMessage(message, transfers);
+ } catch (e) {
+ capability.reject(e);
+ }
+ return capability.promise;
+ },
+ /**
+ * Sends raw message to the comObj.
+ * @private
+ * @param message {Object} Raw message.
+ * @param transfers List of transfers/ArrayBuffers, or undefined.
+ */
+ postMessage: function (message, transfers) {
+ if (transfers && this.postMessageTransfers) {
+ this.comObj.postMessage(message, transfers);
+ } else {
+ this.comObj.postMessage(message);
+ }
+ },
+
+ destroy: function () {
+ this.comObj.removeEventListener('message', this._onComObjOnMessage);
+ }
+};
+
+function loadJpegStream(id, imageUrl, objs) {
+ var img = new Image();
+ img.onload = (function loadJpegStream_onloadClosure() {
+ objs.resolve(id, img);
+ });
+ img.onerror = (function loadJpegStream_onerrorClosure() {
+ objs.resolve(id, null);
+ warn('Error during JPEG image loading');
+ });
+ img.src = imageUrl;
+}
+
+ // Polyfill from https://github.com/Polymer/URL
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+(function checkURLConstructor(scope) {
+ // feature detect for URL constructor
+ var hasWorkingUrl = false;
+ try {
+ if (typeof URL === 'function' &&
+ typeof URL.prototype === 'object' &&
+ ('origin' in URL.prototype)) {
+ var u = new URL('b', 'http://a');
+ u.pathname = 'c%20d';
+ hasWorkingUrl = u.href === 'http://a/c%20d';
+ }
+ } catch(e) { }
+
+ if (hasWorkingUrl) {
+ return;
+ }
+
+ var relative = Object.create(null);
+ relative['ftp'] = 21;
+ relative['file'] = 0;
+ relative['gopher'] = 70;
+ relative['http'] = 80;
+ relative['https'] = 443;
+ relative['ws'] = 80;
+ relative['wss'] = 443;
+
+ var relativePathDotMapping = Object.create(null);
+ relativePathDotMapping['%2e'] = '.';
+ relativePathDotMapping['.%2e'] = '..';
+ relativePathDotMapping['%2e.'] = '..';
+ relativePathDotMapping['%2e%2e'] = '..';
+
+ function isRelativeScheme(scheme) {
+ return relative[scheme] !== undefined;
+ }
+
+ function invalid() {
+ clear.call(this);
+ this._isInvalid = true;
+ }
+
+ function IDNAToASCII(h) {
+ if ('' === h) {
+ invalid.call(this);
+ }
+ // XXX
+ return h.toLowerCase();
+ }
+
+ function percentEscape(c) {
+ var unicode = c.charCodeAt(0);
+ if (unicode > 0x20 &&
+ unicode < 0x7F &&
+ // " # < > ? `
+ [0x22, 0x23, 0x3C, 0x3E, 0x3F, 0x60].indexOf(unicode) === -1
+ ) {
+ return c;
+ }
+ return encodeURIComponent(c);
+ }
+
+ function percentEscapeQuery(c) {
+ // XXX This actually needs to encode c using encoding and then
+ // convert the bytes one-by-one.
+
+ var unicode = c.charCodeAt(0);
+ if (unicode > 0x20 &&
+ unicode < 0x7F &&
+ // " # < > ` (do not escape '?')
+ [0x22, 0x23, 0x3C, 0x3E, 0x60].indexOf(unicode) === -1
+ ) {
+ return c;
+ }
+ return encodeURIComponent(c);
+ }
+
+ var EOF, ALPHA = /[a-zA-Z]/,
+ ALPHANUMERIC = /[a-zA-Z0-9\+\-\.]/;
+
+ function parse(input, stateOverride, base) {
+ function err(message) {
+ errors.push(message);
+ }
+
+ var state = stateOverride || 'scheme start',
+ cursor = 0,
+ buffer = '',
+ seenAt = false,
+ seenBracket = false,
+ errors = [];
+
+ loop: while ((input[cursor - 1] !== EOF || cursor === 0) &&
+ !this._isInvalid) {
+ var c = input[cursor];
+ switch (state) {
+ case 'scheme start':
+ if (c && ALPHA.test(c)) {
+ buffer += c.toLowerCase(); // ASCII-safe
+ state = 'scheme';
+ } else if (!stateOverride) {
+ buffer = '';
+ state = 'no scheme';
+ continue;
+ } else {
+ err('Invalid scheme.');
+ break loop;
+ }
+ break;
+
+ case 'scheme':
+ if (c && ALPHANUMERIC.test(c)) {
+ buffer += c.toLowerCase(); // ASCII-safe
+ } else if (':' === c) {
+ this._scheme = buffer;
+ buffer = '';
+ if (stateOverride) {
+ break loop;
+ }
+ if (isRelativeScheme(this._scheme)) {
+ this._isRelative = true;
+ }
+ if ('file' === this._scheme) {
+ state = 'relative';
+ } else if (this._isRelative && base &&
+ base._scheme === this._scheme) {
+ state = 'relative or authority';
+ } else if (this._isRelative) {
+ state = 'authority first slash';
+ } else {
+ state = 'scheme data';
+ }
+ } else if (!stateOverride) {
+ buffer = '';
+ cursor = 0;
+ state = 'no scheme';
+ continue;
+ } else if (EOF === c) {
+ break loop;
+ } else {
+ err('Code point not allowed in scheme: ' + c);
+ break loop;
+ }
+ break;
+
+ case 'scheme data':
+ if ('?' === c) {
+ this._query = '?';
+ state = 'query';
+ } else if ('#' === c) {
+ this._fragment = '#';
+ state = 'fragment';
+ } else {
+ // XXX error handling
+ if (EOF !== c && '\t' !== c && '\n' !== c && '\r' !== c) {
+ this._schemeData += percentEscape(c);
+ }
+ }
+ break;
+
+ case 'no scheme':
+ if (!base || !(isRelativeScheme(base._scheme))) {
+ err('Missing scheme.');
+ invalid.call(this);
+ } else {
+ state = 'relative';
+ continue;
+ }
+ break;
+
+ case 'relative or authority':
+ if ('/' === c && '/' === input[cursor+1]) {
+ state = 'authority ignore slashes';
+ } else {
+ err('Expected /, got: ' + c);
+ state = 'relative';
+ continue;
+ }
+ break;
+
+ case 'relative':
+ this._isRelative = true;
+ if ('file' !== this._scheme) {
+ this._scheme = base._scheme;
+ }
+ if (EOF === c) {
+ this._host = base._host;
+ this._port = base._port;
+ this._path = base._path.slice();
+ this._query = base._query;
+ this._username = base._username;
+ this._password = base._password;
+ break loop;
+ } else if ('/' === c || '\\' === c) {
+ if ('\\' === c) {
+ err('\\ is an invalid code point.');
+ }
+ state = 'relative slash';
+ } else if ('?' === c) {
+ this._host = base._host;
+ this._port = base._port;
+ this._path = base._path.slice();
+ this._query = '?';
+ this._username = base._username;
+ this._password = base._password;
+ state = 'query';
+ } else if ('#' === c) {
+ this._host = base._host;
+ this._port = base._port;
+ this._path = base._path.slice();
+ this._query = base._query;
+ this._fragment = '#';
+ this._username = base._username;
+ this._password = base._password;
+ state = 'fragment';
+ } else {
+ var nextC = input[cursor+1];
+ var nextNextC = input[cursor+2];
+ if ('file' !== this._scheme || !ALPHA.test(c) ||
+ (nextC !== ':' && nextC !== '|') ||
+ (EOF !== nextNextC && '/' !== nextNextC && '\\' !== nextNextC &&
+ '?' !== nextNextC && '#' !== nextNextC)) {
+ this._host = base._host;
+ this._port = base._port;
+ this._username = base._username;
+ this._password = base._password;
+ this._path = base._path.slice();
+ this._path.pop();
+ }
+ state = 'relative path';
+ continue;
+ }
+ break;
+
+ case 'relative slash':
+ if ('/' === c || '\\' === c) {
+ if ('\\' === c) {
+ err('\\ is an invalid code point.');
+ }
+ if ('file' === this._scheme) {
+ state = 'file host';
+ } else {
+ state = 'authority ignore slashes';
+ }
+ } else {
+ if ('file' !== this._scheme) {
+ this._host = base._host;
+ this._port = base._port;
+ this._username = base._username;
+ this._password = base._password;
+ }
+ state = 'relative path';
+ continue;
+ }
+ break;
+
+ case 'authority first slash':
+ if ('/' === c) {
+ state = 'authority second slash';
+ } else {
+ err('Expected \'/\', got: ' + c);
+ state = 'authority ignore slashes';
+ continue;
+ }
+ break;
+
+ case 'authority second slash':
+ state = 'authority ignore slashes';
+ if ('/' !== c) {
+ err('Expected \'/\', got: ' + c);
+ continue;
+ }
+ break;
+
+ case 'authority ignore slashes':
+ if ('/' !== c && '\\' !== c) {
+ state = 'authority';
+ continue;
+ } else {
+ err('Expected authority, got: ' + c);
+ }
+ break;
+
+ case 'authority':
+ if ('@' === c) {
+ if (seenAt) {
+ err('@ already seen.');
+ buffer += '%40';
+ }
+ seenAt = true;
+ for (var i = 0; i < buffer.length; i++) {
+ var cp = buffer[i];
+ if ('\t' === cp || '\n' === cp || '\r' === cp) {
+ err('Invalid whitespace in authority.');
+ continue;
+ }
+ // XXX check URL code points
+ if (':' === cp && null === this._password) {
+ this._password = '';
+ continue;
+ }
+ var tempC = percentEscape(cp);
+ if (null !== this._password) {
+ this._password += tempC;
+ } else {
+ this._username += tempC;
+ }
+ }
+ buffer = '';
+ } else if (EOF === c || '/' === c || '\\' === c ||
+ '?' === c || '#' === c) {
+ cursor -= buffer.length;
+ buffer = '';
+ state = 'host';
+ continue;
+ } else {
+ buffer += c;
+ }
+ break;
+
+ case 'file host':
+ if (EOF === c || '/' === c || '\\' === c || '?' === c || '#' === c) {
+ if (buffer.length === 2 && ALPHA.test(buffer[0]) &&
+ (buffer[1] === ':' || buffer[1] === '|')) {
+ state = 'relative path';
+ } else if (buffer.length === 0) {
+ state = 'relative path start';
+ } else {
+ this._host = IDNAToASCII.call(this, buffer);
+ buffer = '';
+ state = 'relative path start';
+ }
+ continue;
+ } else if ('\t' === c || '\n' === c || '\r' === c) {
+ err('Invalid whitespace in file host.');
+ } else {
+ buffer += c;
+ }
+ break;
+
+ case 'host':
+ case 'hostname':
+ if (':' === c && !seenBracket) {
+ // XXX host parsing
+ this._host = IDNAToASCII.call(this, buffer);
+ buffer = '';
+ state = 'port';
+ if ('hostname' === stateOverride) {
+ break loop;
+ }
+ } else if (EOF === c || '/' === c ||
+ '\\' === c || '?' === c || '#' === c) {
+ this._host = IDNAToASCII.call(this, buffer);
+ buffer = '';
+ state = 'relative path start';
+ if (stateOverride) {
+ break loop;
+ }
+ continue;
+ } else if ('\t' !== c && '\n' !== c && '\r' !== c) {
+ if ('[' === c) {
+ seenBracket = true;
+ } else if (']' === c) {
+ seenBracket = false;
+ }
+ buffer += c;
+ } else {
+ err('Invalid code point in host/hostname: ' + c);
+ }
+ break;
+
+ case 'port':
+ if (/[0-9]/.test(c)) {
+ buffer += c;
+ } else if (EOF === c || '/' === c || '\\' === c ||
+ '?' === c || '#' === c || stateOverride) {
+ if ('' !== buffer) {
+ var temp = parseInt(buffer, 10);
+ if (temp !== relative[this._scheme]) {
+ this._port = temp + '';
+ }
+ buffer = '';
+ }
+ if (stateOverride) {
+ break loop;
+ }
+ state = 'relative path start';
+ continue;
+ } else if ('\t' === c || '\n' === c || '\r' === c) {
+ err('Invalid code point in port: ' + c);
+ } else {
+ invalid.call(this);
+ }
+ break;
+
+ case 'relative path start':
+ if ('\\' === c) {
+ err('\'\\\' not allowed in path.');
+ }
+ state = 'relative path';
+ if ('/' !== c && '\\' !== c) {
+ continue;
+ }
+ break;
+
+ case 'relative path':
+ if (EOF === c || '/' === c || '\\' === c ||
+ (!stateOverride && ('?' === c || '#' === c))) {
+ if ('\\' === c) {
+ err('\\ not allowed in relative path.');
+ }
+ var tmp;
+ if (tmp = relativePathDotMapping[buffer.toLowerCase()]) {
+ buffer = tmp;
+ }
+ if ('..' === buffer) {
+ this._path.pop();
+ if ('/' !== c && '\\' !== c) {
+ this._path.push('');
+ }
+ } else if ('.' === buffer && '/' !== c && '\\' !== c) {
+ this._path.push('');
+ } else if ('.' !== buffer) {
+ if ('file' === this._scheme && this._path.length === 0 &&
+ buffer.length === 2 && ALPHA.test(buffer[0]) &&
+ buffer[1] === '|') {
+ buffer = buffer[0] + ':';
+ }
+ this._path.push(buffer);
+ }
+ buffer = '';
+ if ('?' === c) {
+ this._query = '?';
+ state = 'query';
+ } else if ('#' === c) {
+ this._fragment = '#';
+ state = 'fragment';
+ }
+ } else if ('\t' !== c && '\n' !== c && '\r' !== c) {
+ buffer += percentEscape(c);
+ }
+ break;
+
+ case 'query':
+ if (!stateOverride && '#' === c) {
+ this._fragment = '#';
+ state = 'fragment';
+ } else if (EOF !== c && '\t' !== c && '\n' !== c && '\r' !== c) {
+ this._query += percentEscapeQuery(c);
+ }
+ break;
+
+ case 'fragment':
+ if (EOF !== c && '\t' !== c && '\n' !== c && '\r' !== c) {
+ this._fragment += c;
+ }
+ break;
+ }
+
+ cursor++;
+ }
+ }
+
+ function clear() {
+ this._scheme = '';
+ this._schemeData = '';
+ this._username = '';
+ this._password = null;
+ this._host = '';
+ this._port = '';
+ this._path = [];
+ this._query = '';
+ this._fragment = '';
+ this._isInvalid = false;
+ this._isRelative = false;
+ }
+
+ // Does not process domain names or IP addresses.
+ // Does not handle encoding for the query parameter.
+ function JURL(url, base /* , encoding */) {
+ if (base !== undefined && !(base instanceof JURL)) {
+ base = new JURL(String(base));
+ }
+
+ this._url = url;
+ clear.call(this);
+
+ var input = url.replace(/^[ \t\r\n\f]+|[ \t\r\n\f]+$/g, '');
+ // encoding = encoding || 'utf-8'
+
+ parse.call(this, input, null, base);
+ }
+
+ JURL.prototype = {
+ toString: function() {
+ return this.href;
+ },
+ get href() {
+ if (this._isInvalid) {
+ return this._url;
+ }
+ var authority = '';
+ if ('' !== this._username || null !== this._password) {
+ authority = this._username +
+ (null !== this._password ? ':' + this._password : '') + '@';
+ }
+
+ return this.protocol +
+ (this._isRelative ? '//' + authority + this.host : '') +
+ this.pathname + this._query + this._fragment;
+ },
+ set href(href) {
+ clear.call(this);
+ parse.call(this, href);
+ },
+
+ get protocol() {
+ return this._scheme + ':';
+ },
+ set protocol(protocol) {
+ if (this._isInvalid) {
+ return;
+ }
+ parse.call(this, protocol + ':', 'scheme start');
+ },
+
+ get host() {
+ return this._isInvalid ? '' : this._port ?
+ this._host + ':' + this._port : this._host;
+ },
+ set host(host) {
+ if (this._isInvalid || !this._isRelative) {
+ return;
+ }
+ parse.call(this, host, 'host');
+ },
+
+ get hostname() {
+ return this._host;
+ },
+ set hostname(hostname) {
+ if (this._isInvalid || !this._isRelative) {
+ return;
+ }
+ parse.call(this, hostname, 'hostname');
+ },
+
+ get port() {
+ return this._port;
+ },
+ set port(port) {
+ if (this._isInvalid || !this._isRelative) {
+ return;
+ }
+ parse.call(this, port, 'port');
+ },
+
+ get pathname() {
+ return this._isInvalid ? '' : this._isRelative ?
+ '/' + this._path.join('/') : this._schemeData;
+ },
+ set pathname(pathname) {
+ if (this._isInvalid || !this._isRelative) {
+ return;
+ }
+ this._path = [];
+ parse.call(this, pathname, 'relative path start');
+ },
+
+ get search() {
+ return this._isInvalid || !this._query || '?' === this._query ?
+ '' : this._query;
+ },
+ set search(search) {
+ if (this._isInvalid || !this._isRelative) {
+ return;
+ }
+ this._query = '?';
+ if ('?' === search[0]) {
+ search = search.slice(1);
+ }
+ parse.call(this, search, 'query');
+ },
+
+ get hash() {
+ return this._isInvalid || !this._fragment || '#' === this._fragment ?
+ '' : this._fragment;
+ },
+ set hash(hash) {
+ if (this._isInvalid) {
+ return;
+ }
+ this._fragment = '#';
+ if ('#' === hash[0]) {
+ hash = hash.slice(1);
+ }
+ parse.call(this, hash, 'fragment');
+ },
+
+ get origin() {
+ var host;
+ if (this._isInvalid || !this._scheme) {
+ return '';
+ }
+ // javascript: Gecko returns String(""), WebKit/Blink String("null")
+ // Gecko throws error for "data://"
+ // data: Gecko returns "", Blink returns "data://", WebKit returns "null"
+ // Gecko returns String("") for file: mailto:
+ // WebKit/Blink returns String("SCHEME://") for file: mailto:
+ switch (this._scheme) {
+ case 'data':
+ case 'file':
+ case 'javascript':
+ case 'mailto':
+ return 'null';
+ }
+ host = this.host;
+ if (!host) {
+ return '';
+ }
+ return this._scheme + '://' + host;
+ }
+ };
+
+ // Copy over the static methods
+ var OriginalURL = scope.URL;
+ if (OriginalURL) {
+ JURL.createObjectURL = function(blob) {
+ // IE extension allows a second optional options argument.
+ // http://msdn.microsoft.com/en-us/library/ie/hh772302(v=vs.85).aspx
+ return OriginalURL.createObjectURL.apply(OriginalURL, arguments);
+ };
+ JURL.revokeObjectURL = function(url) {
+ OriginalURL.revokeObjectURL(url);
+ };
+ }
+
+ scope.URL = JURL;
+})(globalScope);
+
+exports.FONT_IDENTITY_MATRIX = FONT_IDENTITY_MATRIX;
+exports.IDENTITY_MATRIX = IDENTITY_MATRIX;
+exports.OPS = OPS;
+exports.VERBOSITY_LEVELS = VERBOSITY_LEVELS;
+exports.UNSUPPORTED_FEATURES = UNSUPPORTED_FEATURES;
+exports.AnnotationBorderStyleType = AnnotationBorderStyleType;
+exports.AnnotationFieldFlag = AnnotationFieldFlag;
+exports.AnnotationFlag = AnnotationFlag;
+exports.AnnotationType = AnnotationType;
+exports.FontType = FontType;
+exports.ImageKind = ImageKind;
+exports.InvalidPDFException = InvalidPDFException;
+exports.MessageHandler = MessageHandler;
+exports.MissingDataException = MissingDataException;
+exports.MissingPDFException = MissingPDFException;
+exports.NotImplementedException = NotImplementedException;
+exports.PageViewport = PageViewport;
+exports.PasswordException = PasswordException;
+exports.PasswordResponses = PasswordResponses;
+exports.StatTimer = StatTimer;
+exports.StreamType = StreamType;
+exports.TextRenderingMode = TextRenderingMode;
+exports.UnexpectedResponseException = UnexpectedResponseException;
+exports.UnknownErrorException = UnknownErrorException;
+exports.Util = Util;
+exports.XRefParseException = XRefParseException;
+exports.arrayByteLength = arrayByteLength;
+exports.arraysToBytes = arraysToBytes;
+exports.assert = assert;
+exports.bytesToString = bytesToString;
+exports.createBlob = createBlob;
+exports.createPromiseCapability = createPromiseCapability;
+exports.createObjectURL = createObjectURL;
+exports.deprecated = deprecated;
+exports.error = error;
+exports.getLookupTableFactory = getLookupTableFactory;
+exports.getVerbosityLevel = getVerbosityLevel;
+exports.globalScope = globalScope;
+exports.info = info;
+exports.isArray = isArray;
+exports.isArrayBuffer = isArrayBuffer;
+exports.isBool = isBool;
+exports.isEmptyObj = isEmptyObj;
+exports.isInt = isInt;
+exports.isNum = isNum;
+exports.isString = isString;
+exports.isSpace = isSpace;
+exports.isSameOrigin = isSameOrigin;
+exports.isValidUrl = isValidUrl;
+exports.isLittleEndian = isLittleEndian;
+exports.isEvalSupported = isEvalSupported;
+exports.loadJpegStream = loadJpegStream;
+exports.log2 = log2;
+exports.readInt8 = readInt8;
+exports.readUint16 = readUint16;
+exports.readUint32 = readUint32;
+exports.removeNullCharacters = removeNullCharacters;
+exports.setVerbosityLevel = setVerbosityLevel;
+exports.shadow = shadow;
+exports.string32 = string32;
+exports.stringToBytes = stringToBytes;
+exports.stringToPDFString = stringToPDFString;
+exports.stringToUTF8String = stringToUTF8String;
+exports.utf8StringToString = utf8StringToString;
+exports.warn = warn;
+}));
+
+
+(function (root, factory) {
+ {
+ factory((root.pdfjsDisplayDOMUtils = {}), root.pdfjsSharedUtil);
+ }
+}(this, function (exports, sharedUtil) {
+
+var removeNullCharacters = sharedUtil.removeNullCharacters;
+var warn = sharedUtil.warn;
+
+/**
+ * Optimised CSS custom property getter/setter.
+ * @class
+ */
+var CustomStyle = (function CustomStyleClosure() {
+
+ // As noted on: http://www.zachstronaut.com/posts/2009/02/17/
+ // animate-css-transforms-firefox-webkit.html
+ // in some versions of IE9 it is critical that ms appear in this list
+ // before Moz
+ var prefixes = ['ms', 'Moz', 'Webkit', 'O'];
+ var _cache = Object.create(null);
+
+ function CustomStyle() {}
+
+ CustomStyle.getProp = function get(propName, element) {
+ // check cache only when no element is given
+ if (arguments.length === 1 && typeof _cache[propName] === 'string') {
+ return _cache[propName];
+ }
+
+ element = element || document.documentElement;
+ var style = element.style, prefixed, uPropName;
+
+ // test standard property first
+ if (typeof style[propName] === 'string') {
+ return (_cache[propName] = propName);
+ }
+
+ // capitalize
+ uPropName = propName.charAt(0).toUpperCase() + propName.slice(1);
+
+ // test vendor specific properties
+ for (var i = 0, l = prefixes.length; i < l; i++) {
+ prefixed = prefixes[i] + uPropName;
+ if (typeof style[prefixed] === 'string') {
+ return (_cache[propName] = prefixed);
+ }
+ }
+
+ //if all fails then set to undefined
+ return (_cache[propName] = 'undefined');
+ };
+
+ CustomStyle.setProp = function set(propName, element, str) {
+ var prop = this.getProp(propName);
+ if (prop !== 'undefined') {
+ element.style[prop] = str;
+ }
+ };
+
+ return CustomStyle;
+})();
+
+function hasCanvasTypedArrays() {
+ var canvas = document.createElement('canvas');
+ canvas.width = canvas.height = 1;
+ var ctx = canvas.getContext('2d');
+ var imageData = ctx.createImageData(1, 1);
+ return (typeof imageData.data.buffer !== 'undefined');
+}
+
+var LinkTarget = {
+ NONE: 0, // Default value.
+ SELF: 1,
+ BLANK: 2,
+ PARENT: 3,
+ TOP: 4,
+};
+
+var LinkTargetStringMap = [
+ '',
+ '_self',
+ '_blank',
+ '_parent',
+ '_top'
+];
+
+/**
+ * @typedef ExternalLinkParameters
+ * @typedef {Object} ExternalLinkParameters
+ * @property {string} url - An absolute URL.
+ * @property {LinkTarget} target - The link target.
+ * @property {string} rel - The link relationship.
+ */
+
+/**
+ * Adds various attributes (href, title, target, rel) to hyperlinks.
+ * @param {HTMLLinkElement} link - The link element.
+ * @param {ExternalLinkParameters} params
+ */
+function addLinkAttributes(link, params) {
+ var url = params && params.url;
+ link.href = link.title = (url ? removeNullCharacters(url) : '');
+
+ if (url) {
+ var target = params.target;
+ if (typeof target === 'undefined') {
+ target = getDefaultSetting('externalLinkTarget');
+ }
+ link.target = LinkTargetStringMap[target];
+
+ var rel = params.rel;
+ if (typeof rel === 'undefined') {
+ rel = getDefaultSetting('externalLinkRel');
+ }
+ link.rel = rel;
+ }
+}
+
+// Gets the file name from a given URL.
+function getFilenameFromUrl(url) {
+ var anchor = url.indexOf('#');
+ var query = url.indexOf('?');
+ var end = Math.min(
+ anchor > 0 ? anchor : url.length,
+ query > 0 ? query : url.length);
+ return url.substring(url.lastIndexOf('/', end) + 1, end);
+}
+
+function getDefaultSetting(id) {
+ // The list of the settings and their default is maintained for backward
+ // compatibility and shall not be extended or modified. See also global.js.
+ var globalSettings = sharedUtil.globalScope.PDFJS;
+ switch (id) {
+ case 'pdfBug':
+ return globalSettings ? globalSettings.pdfBug : false;
+ case 'disableAutoFetch':
+ return globalSettings ? globalSettings.disableAutoFetch : false;
+ case 'disableStream':
+ return globalSettings ? globalSettings.disableStream : false;
+ case 'disableRange':
+ return globalSettings ? globalSettings.disableRange : false;
+ case 'disableFontFace':
+ return globalSettings ? globalSettings.disableFontFace : false;
+ case 'disableCreateObjectURL':
+ return globalSettings ? globalSettings.disableCreateObjectURL : false;
+ case 'disableWebGL':
+ return globalSettings ? globalSettings.disableWebGL : true;
+ case 'cMapUrl':
+ return globalSettings ? globalSettings.cMapUrl : null;
+ case 'cMapPacked':
+ return globalSettings ? globalSettings.cMapPacked : false;
+ case 'postMessageTransfers':
+ return globalSettings ? globalSettings.postMessageTransfers : true;
+ case 'workerSrc':
+ return globalSettings ? globalSettings.workerSrc : null;
+ case 'disableWorker':
+ return globalSettings ? globalSettings.disableWorker : false;
+ case 'maxImageSize':
+ return globalSettings ? globalSettings.maxImageSize : -1;
+ case 'imageResourcesPath':
+ return globalSettings ? globalSettings.imageResourcesPath : '';
+ case 'isEvalSupported':
+ return globalSettings ? globalSettings.isEvalSupported : true;
+ case 'externalLinkTarget':
+ if (!globalSettings) {
+ return LinkTarget.NONE;
+ }
+ switch (globalSettings.externalLinkTarget) {
+ case LinkTarget.NONE:
+ case LinkTarget.SELF:
+ case LinkTarget.BLANK:
+ case LinkTarget.PARENT:
+ case LinkTarget.TOP:
+ return globalSettings.externalLinkTarget;
+ }
+ warn('PDFJS.externalLinkTarget is invalid: ' +
+ globalSettings.externalLinkTarget);
+ // Reset the external link target, to suppress further warnings.
+ globalSettings.externalLinkTarget = LinkTarget.NONE;
+ return LinkTarget.NONE;
+ case 'externalLinkRel':
+ return globalSettings ? globalSettings.externalLinkRel : 'noreferrer';
+ case 'enableStats':
+ return !!(globalSettings && globalSettings.enableStats);
+ default:
+ throw new Error('Unknown default setting: ' + id);
+ }
+}
+
+function isExternalLinkTargetSet() {
+ var externalLinkTarget = getDefaultSetting('externalLinkTarget');
+ switch (externalLinkTarget) {
+ case LinkTarget.NONE:
+ return false;
+ case LinkTarget.SELF:
+ case LinkTarget.BLANK:
+ case LinkTarget.PARENT:
+ case LinkTarget.TOP:
+ return true;
+ }
+}
+
+exports.CustomStyle = CustomStyle;
+exports.addLinkAttributes = addLinkAttributes;
+exports.isExternalLinkTargetSet = isExternalLinkTargetSet;
+exports.getFilenameFromUrl = getFilenameFromUrl;
+exports.LinkTarget = LinkTarget;
+exports.hasCanvasTypedArrays = hasCanvasTypedArrays;
+exports.getDefaultSetting = getDefaultSetting;
+}));
+
+
+(function (root, factory) {
+ {
+ factory((root.pdfjsDisplayFontLoader = {}), root.pdfjsSharedUtil);
+ }
+}(this, function (exports, sharedUtil) {
+
+var assert = sharedUtil.assert;
+var bytesToString = sharedUtil.bytesToString;
+var string32 = sharedUtil.string32;
+var shadow = sharedUtil.shadow;
+var warn = sharedUtil.warn;
+
+function FontLoader(docId) {
+ this.docId = docId;
+ this.styleElement = null;
+ this.nativeFontFaces = [];
+ this.loadTestFontId = 0;
+ this.loadingContext = {
+ requests: [],
+ nextRequestId: 0
+ };
+}
+FontLoader.prototype = {
+ insertRule: function fontLoaderInsertRule(rule) {
+ var styleElement = this.styleElement;
+ if (!styleElement) {
+ styleElement = this.styleElement = document.createElement('style');
+ styleElement.id = 'PDFJS_FONT_STYLE_TAG_' + this.docId;
+ document.documentElement.getElementsByTagName('head')[0].appendChild(
+ styleElement);
+ }
+
+ var styleSheet = styleElement.sheet;
+ styleSheet.insertRule(rule, styleSheet.cssRules.length);
+ },
+
+ clear: function fontLoaderClear() {
+ var styleElement = this.styleElement;
+ if (styleElement) {
+ styleElement.parentNode.removeChild(styleElement);
+ styleElement = this.styleElement = null;
+ }
+ this.nativeFontFaces.forEach(function(nativeFontFace) {
+ document.fonts.delete(nativeFontFace);
+ });
+ this.nativeFontFaces.length = 0;
+ },
+ get loadTestFont() {
+ // This is a CFF font with 1 glyph for '.' that fills its entire width and
+ // height.
+ return shadow(this, 'loadTestFont', atob(
+ 'T1RUTwALAIAAAwAwQ0ZGIDHtZg4AAAOYAAAAgUZGVE1lkzZwAAAEHAAAABxHREVGABQAFQ' +
+ 'AABDgAAAAeT1MvMlYNYwkAAAEgAAAAYGNtYXABDQLUAAACNAAAAUJoZWFk/xVFDQAAALwA' +
+ 'AAA2aGhlYQdkA+oAAAD0AAAAJGhtdHgD6AAAAAAEWAAAAAZtYXhwAAJQAAAAARgAAAAGbm' +
+ 'FtZVjmdH4AAAGAAAAAsXBvc3T/hgAzAAADeAAAACAAAQAAAAEAALZRFsRfDzz1AAsD6AAA' +
+ 'AADOBOTLAAAAAM4KHDwAAAAAA+gDIQAAAAgAAgAAAAAAAAABAAADIQAAAFoD6AAAAAAD6A' +
+ 'ABAAAAAAAAAAAAAAAAAAAAAQAAUAAAAgAAAAQD6AH0AAUAAAKKArwAAACMAooCvAAAAeAA' +
+ 'MQECAAACAAYJAAAAAAAAAAAAAQAAAAAAAAAAAAAAAFBmRWQAwAAuAC4DIP84AFoDIQAAAA' +
+ 'AAAQAAAAAAAAAAACAAIAABAAAADgCuAAEAAAAAAAAAAQAAAAEAAAAAAAEAAQAAAAEAAAAA' +
+ 'AAIAAQAAAAEAAAAAAAMAAQAAAAEAAAAAAAQAAQAAAAEAAAAAAAUAAQAAAAEAAAAAAAYAAQ' +
+ 'AAAAMAAQQJAAAAAgABAAMAAQQJAAEAAgABAAMAAQQJAAIAAgABAAMAAQQJAAMAAgABAAMA' +
+ 'AQQJAAQAAgABAAMAAQQJAAUAAgABAAMAAQQJAAYAAgABWABYAAAAAAAAAwAAAAMAAAAcAA' +
+ 'EAAAAAADwAAwABAAAAHAAEACAAAAAEAAQAAQAAAC7//wAAAC7////TAAEAAAAAAAABBgAA' +
+ 'AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAA' +
+ 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' +
+ 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' +
+ 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' +
+ 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAA' +
+ 'AAAAD/gwAyAAAAAQAAAAAAAAAAAAAAAAAAAAABAAQEAAEBAQJYAAEBASH4DwD4GwHEAvgc' +
+ 'A/gXBIwMAYuL+nz5tQXkD5j3CBLnEQACAQEBIVhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWF' +
+ 'hYWFhYWFhYAAABAQAADwACAQEEE/t3Dov6fAH6fAT+fPp8+nwHDosMCvm1Cvm1DAz6fBQA' +
+ 'AAAAAAABAAAAAMmJbzEAAAAAzgTjFQAAAADOBOQpAAEAAAAAAAAADAAUAAQAAAABAAAAAg' +
+ 'ABAAAAAAAAAAAD6AAAAAAAAA=='
+ ));
+ },
+
+ addNativeFontFace: function fontLoader_addNativeFontFace(nativeFontFace) {
+ this.nativeFontFaces.push(nativeFontFace);
+ document.fonts.add(nativeFontFace);
+ },
+
+ bind: function fontLoaderBind(fonts, callback) {
+ var rules = [];
+ var fontsToLoad = [];
+ var fontLoadPromises = [];
+ var getNativeFontPromise = function(nativeFontFace) {
+ // Return a promise that is always fulfilled, even when the font fails to
+ // load.
+ return nativeFontFace.loaded.catch(function(e) {
+ warn('Failed to load font "' + nativeFontFace.family + '": ' + e);
+ });
+ };
+ for (var i = 0, ii = fonts.length; i < ii; i++) {
+ var font = fonts[i];
+
+ // Add the font to the DOM only once or skip if the font
+ // is already loaded.
+ if (font.attached || font.loading === false) {
+ continue;
+ }
+ font.attached = true;
+
+ if (FontLoader.isFontLoadingAPISupported) {
+ var nativeFontFace = font.createNativeFontFace();
+ if (nativeFontFace) {
+ this.addNativeFontFace(nativeFontFace);
+ fontLoadPromises.push(getNativeFontPromise(nativeFontFace));
+ }
+ } else {
+ var rule = font.createFontFaceRule();
+ if (rule) {
+ this.insertRule(rule);
+ rules.push(rule);
+ fontsToLoad.push(font);
+ }
+ }
+ }
+
+ var request = this.queueLoadingCallback(callback);
+ if (FontLoader.isFontLoadingAPISupported) {
+ Promise.all(fontLoadPromises).then(function() {
+ request.complete();
+ });
+ } else if (rules.length > 0 && !FontLoader.isSyncFontLoadingSupported) {
+ this.prepareFontLoadEvent(rules, fontsToLoad, request);
+ } else {
+ request.complete();
+ }
+ },
+
+ queueLoadingCallback: function FontLoader_queueLoadingCallback(callback) {
+ function LoadLoader_completeRequest() {
+ assert(!request.end, 'completeRequest() cannot be called twice');
+ request.end = Date.now();
+
+ // sending all completed requests in order how they were queued
+ while (context.requests.length > 0 && context.requests[0].end) {
+ var otherRequest = context.requests.shift();
+ setTimeout(otherRequest.callback, 0);
+ }
+ }
+
+ var context = this.loadingContext;
+ var requestId = 'pdfjs-font-loading-' + (context.nextRequestId++);
+ var request = {
+ id: requestId,
+ complete: LoadLoader_completeRequest,
+ callback: callback,
+ started: Date.now()
+ };
+ context.requests.push(request);
+ return request;
+ },
+
+ prepareFontLoadEvent: function fontLoaderPrepareFontLoadEvent(rules,
+ fonts,
+ request) {
+ /** Hack begin */
+ // There's currently no event when a font has finished downloading so the
+ // following code is a dirty hack to 'guess' when a font is
+ // ready. It's assumed fonts are loaded in order, so add a known test
+ // font after the desired fonts and then test for the loading of that
+ // test font.
+
+ function int32(data, offset) {
+ return (data.charCodeAt(offset) << 24) |
+ (data.charCodeAt(offset + 1) << 16) |
+ (data.charCodeAt(offset + 2) << 8) |
+ (data.charCodeAt(offset + 3) & 0xff);
+ }
+
+ function spliceString(s, offset, remove, insert) {
+ var chunk1 = s.substr(0, offset);
+ var chunk2 = s.substr(offset + remove);
+ return chunk1 + insert + chunk2;
+ }
+
+ var i, ii;
+
+ var canvas = document.createElement('canvas');
+ canvas.width = 1;
+ canvas.height = 1;
+ var ctx = canvas.getContext('2d');
+
+ var called = 0;
+ function isFontReady(name, callback) {
+ called++;
+ // With setTimeout clamping this gives the font ~100ms to load.
+ if(called > 30) {
+ warn('Load test font never loaded.');
+ callback();
+ return;
+ }
+ ctx.font = '30px ' + name;
+ ctx.fillText('.', 0, 20);
+ var imageData = ctx.getImageData(0, 0, 1, 1);
+ if (imageData.data[3] > 0) {
+ callback();
+ return;
+ }
+ setTimeout(isFontReady.bind(null, name, callback));
+ }
+
+ var loadTestFontId = 'lt' + Date.now() + this.loadTestFontId++;
+ // Chromium seems to cache fonts based on a hash of the actual font data,
+ // so the font must be modified for each load test else it will appear to
+ // be loaded already.
+ // TODO: This could maybe be made faster by avoiding the btoa of the full
+ // font by splitting it in chunks before hand and padding the font id.
+ var data = this.loadTestFont;
+ var COMMENT_OFFSET = 976; // has to be on 4 byte boundary (for checksum)
+ data = spliceString(data, COMMENT_OFFSET, loadTestFontId.length,
+ loadTestFontId);
+ // CFF checksum is important for IE, adjusting it
+ var CFF_CHECKSUM_OFFSET = 16;
+ var XXXX_VALUE = 0x58585858; // the "comment" filled with 'X'
+ var 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) { // align to 4 bytes boundary
+ checksum = (checksum - XXXX_VALUE +
+ int32(loadTestFontId + 'XXX', i)) | 0;
+ }
+ data = spliceString(data, CFF_CHECKSUM_OFFSET, 4, string32(checksum));
+
+ var url = 'url(data:font/opentype;base64,' + btoa(data) + ');';
+ var rule = '@font-face { font-family:"' + loadTestFontId + '";src:' +
+ url + '}';
+ this.insertRule(rule);
+
+ var names = [];
+ for (i = 0, ii = fonts.length; i < ii; i++) {
+ names.push(fonts[i].loadedName);
+ }
+ names.push(loadTestFontId);
+
+ var div = document.createElement('div');
+ div.setAttribute('style',
+ 'visibility: hidden;' +
+ 'width: 10px; height: 10px;' +
+ 'position: absolute; top: 0px; left: 0px;');
+ for (i = 0, ii = names.length; i < ii; ++i) {
+ var span = document.createElement('span');
+ span.textContent = 'Hi';
+ span.style.fontFamily = names[i];
+ div.appendChild(span);
+ }
+ document.body.appendChild(div);
+
+ isFontReady(loadTestFontId, function() {
+ document.body.removeChild(div);
+ request.complete();
+ });
+ /** Hack end */
+ }
+};
+FontLoader.isFontLoadingAPISupported = typeof document !== 'undefined' &&
+ !!document.fonts;
+Object.defineProperty(FontLoader, 'isSyncFontLoadingSupported', {
+ get: function () {
+ if (typeof navigator === 'undefined') {
+ // node.js - we can pretend sync font loading is supported.
+ return shadow(FontLoader, 'isSyncFontLoadingSupported', true);
+ }
+
+ var supported = false;
+
+ // User agent string sniffing is bad, but there is no reliable way to tell
+ // if font is fully loaded and ready to be used with canvas.
+ var m = /Mozilla\/5.0.*?rv:(\d+).*? Gecko/.exec(navigator.userAgent);
+ if (m && m[1] >= 14) {
+ supported = true;
+ }
+ // TODO other browsers
+ return shadow(FontLoader, 'isSyncFontLoadingSupported', supported);
+ },
+ enumerable: true,
+ configurable: true
+});
+
+var IsEvalSupportedCached = {
+ get value() {
+ return shadow(this, 'value', sharedUtil.isEvalSupported());
+ }
+};
+
+var FontFaceObject = (function FontFaceObjectClosure() {
+ function FontFaceObject(translatedData, options) {
+ this.compiledGlyphs = Object.create(null);
+ // importing translated data
+ for (var i in translatedData) {
+ this[i] = translatedData[i];
+ }
+ this.options = options;
+ }
+ FontFaceObject.prototype = {
+ createNativeFontFace: function FontFaceObject_createNativeFontFace() {
+ if (!this.data) {
+ return null;
+ }
+
+ if (this.options.disableFontFace) {
+ this.disableFontFace = true;
+ return null;
+ }
+
+ var nativeFontFace = new FontFace(this.loadedName, this.data, {});
+
+ if (this.options.fontRegistry) {
+ this.options.fontRegistry.registerFont(this);
+ }
+ return nativeFontFace;
+ },
+
+ createFontFaceRule: function FontFaceObject_createFontFaceRule() {
+ if (!this.data) {
+ return null;
+ }
+
+ if (this.options.disableFontFace) {
+ this.disableFontFace = true;
+ return null;
+ }
+
+ var data = bytesToString(new Uint8Array(this.data));
+ var fontName = this.loadedName;
+
+ // Add the font-face rule to the document
+ var url = ('url(data:' + this.mimetype + ';base64,' + btoa(data) + ');');
+ var rule = '@font-face { font-family:"' + fontName + '";src:' + url + '}';
+
+ if (this.options.fontRegistry) {
+ this.options.fontRegistry.registerFont(this, url);
+ }
+
+ return rule;
+ },
+
+ getPathGenerator:
+ function FontFaceObject_getPathGenerator(objs, character) {
+ if (!(character in this.compiledGlyphs)) {
+ var cmds = objs.get(this.loadedName + '_path_' + character);
+ var current, i, len;
+
+ // If we can, compile cmds into JS for MAXIMUM SPEED
+ if (this.options.isEvalSupported && IsEvalSupportedCached.value) {
+ var args, js = '';
+ for (i = 0, len = cmds.length; i < len; i++) {
+ current = cmds[i];
+
+ if (current.args !== undefined) {
+ args = current.args.join(',');
+ } else {
+ args = '';
+ }
+
+ js += 'c.' + current.cmd + '(' + args + ');\n';
+ }
+ /* jshint -W054 */
+ this.compiledGlyphs[character] = new Function('c', 'size', js);
+ } else {
+ // But fall back on using Function.prototype.apply() if we're
+ // blocked from using eval() for whatever reason (like CSP policies)
+ this.compiledGlyphs[character] = function(c, size) {
+ for (i = 0, len = cmds.length; i < len; i++) {
+ current = cmds[i];
+
+ if (current.cmd === 'scale') {
+ current.args = [size, -size];
+ }
+
+ c[current.cmd].apply(c, current.args);
+ }
+ };
+ }
+ }
+ return this.compiledGlyphs[character];
+ }
+ };
+ return FontFaceObject;
+})();
+
+exports.FontFaceObject = FontFaceObject;
+exports.FontLoader = FontLoader;
+}));
+
+
+(function (root, factory) {
+ {
+ factory((root.pdfjsDisplayMetadata = {}), root.pdfjsSharedUtil);
+ }
+}(this, function (exports, sharedUtil) {
+
+var error = sharedUtil.error;
+
+ function fixMetadata(meta) {
+ return meta.replace(/>\\376\\377([^<]+)/g, function(all, codes) {
+ var bytes = codes.replace(/\\([0-3])([0-7])([0-7])/g,
+ function(code, d1, d2, d3) {
+ return String.fromCharCode(d1 * 64 + d2 * 8 + d3 * 1);
+ });
+ var chars = '';
+ for (var i = 0; i < bytes.length; i += 2) {
+ var code = bytes.charCodeAt(i) * 256 + bytes.charCodeAt(i + 1);
+ chars += code >= 32 && code < 127 && code !== 60 && code !== 62 &&
+ code !== 38 && false ? String.fromCharCode(code) :
+ '' + (0x10000 + code).toString(16).substring(1) + ';';
+ }
+ return '>' + chars;
+ });
+ }
+
+ function Metadata(meta) {
+ if (typeof meta === 'string') {
+ // Ghostscript produces invalid metadata
+ meta = fixMetadata(meta);
+
+ var parser = new DOMParser();
+ meta = parser.parseFromString(meta, 'application/xml');
+ } else if (!(meta instanceof Document)) {
+ error('Metadata: Invalid metadata object');
+ }
+
+ this.metaDocument = meta;
+ this.metadata = Object.create(null);
+ this.parse();
+ }
+
+ Metadata.prototype = {
+ parse: function Metadata_parse() {
+ var doc = this.metaDocument;
+ var rdf = doc.documentElement;
+
+ if (rdf.nodeName.toLowerCase() !== 'rdf:rdf') { // Wrapped in
+ rdf = rdf.firstChild;
+ while (rdf && rdf.nodeName.toLowerCase() !== 'rdf:rdf') {
+ rdf = rdf.nextSibling;
+ }
+ }
+
+ var nodeName = (rdf) ? rdf.nodeName.toLowerCase() : null;
+ if (!rdf || nodeName !== 'rdf:rdf' || !rdf.hasChildNodes()) {
+ return;
+ }
+
+ var children = rdf.childNodes, desc, entry, name, i, ii, length, iLength;
+ for (i = 0, length = children.length; i < length; i++) {
+ desc = children[i];
+ if (desc.nodeName.toLowerCase() !== 'rdf:description') {
+ continue;
+ }
+
+ for (ii = 0, iLength = desc.childNodes.length; ii < iLength; ii++) {
+ if (desc.childNodes[ii].nodeName.toLowerCase() !== '#text') {
+ entry = desc.childNodes[ii];
+ name = entry.nodeName.toLowerCase();
+ this.metadata[name] = entry.textContent.trim();
+ }
+ }
+ }
+ },
+
+ get: function Metadata_get(name) {
+ return this.metadata[name] || null;
+ },
+
+ has: function Metadata_has(name) {
+ return typeof this.metadata[name] !== 'undefined';
+ }
+ };
+
+exports.Metadata = Metadata;
+}));
+
+
+(function (root, factory) {
+ {
+ factory((root.pdfjsDisplaySVG = {}), root.pdfjsSharedUtil);
+ }
+}(this, function (exports, sharedUtil) {
+var FONT_IDENTITY_MATRIX = sharedUtil.FONT_IDENTITY_MATRIX;
+var IDENTITY_MATRIX = sharedUtil.IDENTITY_MATRIX;
+var ImageKind = sharedUtil.ImageKind;
+var OPS = sharedUtil.OPS;
+var Util = sharedUtil.Util;
+var isNum = sharedUtil.isNum;
+var isArray = sharedUtil.isArray;
+var warn = sharedUtil.warn;
+var createObjectURL = sharedUtil.createObjectURL;
+
+var SVG_DEFAULTS = {
+ fontStyle: 'normal',
+ fontWeight: 'normal',
+ fillColor: '#000000'
+};
+
+var convertImgDataToPng = (function convertImgDataToPngClosure() {
+ var PNG_HEADER =
+ new Uint8Array([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]);
+
+ var CHUNK_WRAPPER_SIZE = 12;
+
+ var crcTable = new Int32Array(256);
+ for (var i = 0; i < 256; i++) {
+ var c = i;
+ for (var h = 0; h < 8; h++) {
+ if (c & 1) {
+ c = 0xedB88320 ^ ((c >> 1) & 0x7fffffff);
+ } else {
+ c = (c >> 1) & 0x7fffffff;
+ }
+ }
+ crcTable[i] = c;
+ }
+
+ function crc32(data, start, end) {
+ var crc = -1;
+ for (var i = start; i < end; i++) {
+ var a = (crc ^ data[i]) & 0xff;
+ var b = crcTable[a];
+ crc = (crc >>> 8) ^ b;
+ }
+ return crc ^ -1;
+ }
+
+ function writePngChunk(type, body, data, offset) {
+ var p = offset;
+ var len = body.length;
+
+ data[p] = len >> 24 & 0xff;
+ data[p + 1] = len >> 16 & 0xff;
+ data[p + 2] = len >> 8 & 0xff;
+ data[p + 3] = len & 0xff;
+ p += 4;
+
+ data[p] = type.charCodeAt(0) & 0xff;
+ data[p + 1] = type.charCodeAt(1) & 0xff;
+ data[p + 2] = type.charCodeAt(2) & 0xff;
+ data[p + 3] = type.charCodeAt(3) & 0xff;
+ p += 4;
+
+ data.set(body, p);
+ p += body.length;
+
+ var crc = crc32(data, offset + 4, p);
+
+ data[p] = crc >> 24 & 0xff;
+ data[p + 1] = crc >> 16 & 0xff;
+ data[p + 2] = crc >> 8 & 0xff;
+ data[p + 3] = crc & 0xff;
+ }
+
+ function adler32(data, start, end) {
+ var a = 1;
+ var b = 0;
+ for (var i = start; i < end; ++i) {
+ a = (a + (data[i] & 0xff)) % 65521;
+ b = (b + a) % 65521;
+ }
+ return (b << 16) | a;
+ }
+
+ function encode(imgData, kind, forceDataSchema) {
+ var width = imgData.width;
+ var height = imgData.height;
+ var bitDepth, colorType, lineSize;
+ var bytes = imgData.data;
+
+ switch (kind) {
+ case ImageKind.GRAYSCALE_1BPP:
+ colorType = 0;
+ bitDepth = 1;
+ lineSize = (width + 7) >> 3;
+ break;
+ case ImageKind.RGB_24BPP:
+ colorType = 2;
+ bitDepth = 8;
+ lineSize = width * 3;
+ break;
+ case ImageKind.RGBA_32BPP:
+ colorType = 6;
+ bitDepth = 8;
+ lineSize = width * 4;
+ break;
+ default:
+ throw new Error('invalid format');
+ }
+
+ // prefix every row with predictor 0
+ var literals = new Uint8Array((1 + lineSize) * height);
+ var offsetLiterals = 0, offsetBytes = 0;
+ var y, i;
+ for (y = 0; y < height; ++y) {
+ literals[offsetLiterals++] = 0; // no prediction
+ literals.set(bytes.subarray(offsetBytes, offsetBytes + lineSize),
+ offsetLiterals);
+ offsetBytes += lineSize;
+ offsetLiterals += lineSize;
+ }
+
+ if (kind === ImageKind.GRAYSCALE_1BPP) {
+ // inverting for B/W
+ offsetLiterals = 0;
+ for (y = 0; y < height; y++) {
+ offsetLiterals++; // skipping predictor
+ for (i = 0; i < lineSize; i++) {
+ literals[offsetLiterals++] ^= 0xFF;
+ }
+ }
+ }
+
+ var ihdr = new Uint8Array([
+ width >> 24 & 0xff,
+ width >> 16 & 0xff,
+ width >> 8 & 0xff,
+ width & 0xff,
+ height >> 24 & 0xff,
+ height >> 16 & 0xff,
+ height >> 8 & 0xff,
+ height & 0xff,
+ bitDepth, // bit depth
+ colorType, // color type
+ 0x00, // compression method
+ 0x00, // filter method
+ 0x00 // interlace method
+ ]);
+
+ var len = literals.length;
+ var maxBlockLength = 0xFFFF;
+
+ var deflateBlocks = Math.ceil(len / maxBlockLength);
+ var idat = new Uint8Array(2 + len + deflateBlocks * 5 + 4);
+ var pi = 0;
+ idat[pi++] = 0x78; // compression method and flags
+ idat[pi++] = 0x9c; // flags
+
+ var pos = 0;
+ while (len > maxBlockLength) {
+ // writing non-final DEFLATE blocks type 0 and length of 65535
+ idat[pi++] = 0x00;
+ idat[pi++] = 0xff;
+ idat[pi++] = 0xff;
+ idat[pi++] = 0x00;
+ idat[pi++] = 0x00;
+ idat.set(literals.subarray(pos, pos + maxBlockLength), pi);
+ pi += maxBlockLength;
+ pos += maxBlockLength;
+ len -= maxBlockLength;
+ }
+
+ // writing non-final DEFLATE blocks type 0
+ idat[pi++] = 0x01;
+ idat[pi++] = len & 0xff;
+ idat[pi++] = len >> 8 & 0xff;
+ idat[pi++] = (~len & 0xffff) & 0xff;
+ idat[pi++] = (~len & 0xffff) >> 8 & 0xff;
+ idat.set(literals.subarray(pos), pi);
+ pi += literals.length - pos;
+
+ var adler = adler32(literals, 0, literals.length); // checksum
+ idat[pi++] = adler >> 24 & 0xff;
+ idat[pi++] = adler >> 16 & 0xff;
+ idat[pi++] = adler >> 8 & 0xff;
+ idat[pi++] = adler & 0xff;
+
+ // PNG will consists: header, IHDR+data, IDAT+data, and IEND.
+ var pngLength = PNG_HEADER.length + (CHUNK_WRAPPER_SIZE * 3) +
+ ihdr.length + idat.length;
+ var data = new Uint8Array(pngLength);
+ var offset = 0;
+ data.set(PNG_HEADER, offset);
+ offset += PNG_HEADER.length;
+ writePngChunk('IHDR', ihdr, data, offset);
+ offset += CHUNK_WRAPPER_SIZE + ihdr.length;
+ writePngChunk('IDATA', idat, data, offset);
+ offset += CHUNK_WRAPPER_SIZE + idat.length;
+ writePngChunk('IEND', new Uint8Array(0), data, offset);
+
+ return createObjectURL(data, 'image/png', forceDataSchema);
+ }
+
+ return function convertImgDataToPng(imgData, forceDataSchema) {
+ var kind = (imgData.kind === undefined ?
+ ImageKind.GRAYSCALE_1BPP : imgData.kind);
+ return encode(imgData, kind, forceDataSchema);
+ };
+})();
+
+var SVGExtraState = (function SVGExtraStateClosure() {
+ function SVGExtraState() {
+ this.fontSizeScale = 1;
+ this.fontWeight = SVG_DEFAULTS.fontWeight;
+ this.fontSize = 0;
+
+ this.textMatrix = IDENTITY_MATRIX;
+ this.fontMatrix = FONT_IDENTITY_MATRIX;
+ this.leading = 0;
+
+ // Current point (in user coordinates)
+ this.x = 0;
+ this.y = 0;
+
+ // Start of text line (in text coordinates)
+ this.lineX = 0;
+ this.lineY = 0;
+
+ // Character and word spacing
+ this.charSpacing = 0;
+ this.wordSpacing = 0;
+ this.textHScale = 1;
+ this.textRise = 0;
+
+ // Default foreground and background colors
+ this.fillColor = SVG_DEFAULTS.fillColor;
+ this.strokeColor = '#000000';
+
+ this.fillAlpha = 1;
+ this.strokeAlpha = 1;
+ this.lineWidth = 1;
+ this.lineJoin = '';
+ this.lineCap = '';
+ this.miterLimit = 0;
+
+ this.dashArray = [];
+ this.dashPhase = 0;
+
+ this.dependencies = [];
+
+ // Clipping
+ this.clipId = '';
+ this.pendingClip = false;
+
+ this.maskId = '';
+ }
+
+ SVGExtraState.prototype = {
+ clone: function SVGExtraState_clone() {
+ return Object.create(this);
+ },
+ setCurrentPoint: function SVGExtraState_setCurrentPoint(x, y) {
+ this.x = x;
+ this.y = y;
+ }
+ };
+ return SVGExtraState;
+})();
+
+var SVGGraphics = (function SVGGraphicsClosure() {
+ function createScratchSVG(width, height) {
+ var NS = 'http://www.w3.org/2000/svg';
+ var svg = document.createElementNS(NS, 'svg:svg');
+ svg.setAttributeNS(null, 'version', '1.1');
+ svg.setAttributeNS(null, 'width', width + 'px');
+ svg.setAttributeNS(null, 'height', height + 'px');
+ svg.setAttributeNS(null, 'viewBox', '0 0 ' + width + ' ' + height);
+ return svg;
+ }
+
+ function opListToTree(opList) {
+ var opTree = [];
+ var tmp = [];
+ var opListLen = opList.length;
+
+ for (var x = 0; x < opListLen; x++) {
+ if (opList[x].fn === 'save') {
+ opTree.push({'fnId': 92, 'fn': 'group', 'items': []});
+ tmp.push(opTree);
+ opTree = opTree[opTree.length - 1].items;
+ continue;
+ }
+
+ if(opList[x].fn === 'restore') {
+ opTree = tmp.pop();
+ } else {
+ opTree.push(opList[x]);
+ }
+ }
+ return opTree;
+ }
+
+ /**
+ * Formats float number.
+ * @param value {number} number to format.
+ * @returns {string}
+ */
+ function pf(value) {
+ if (value === (value | 0)) { // integer number
+ return value.toString();
+ }
+ var s = value.toFixed(10);
+ var i = s.length - 1;
+ if (s[i] !== '0') {
+ return s;
+ }
+ // removing trailing zeros
+ do {
+ i--;
+ } while (s[i] === '0');
+ return s.substr(0, s[i] === '.' ? i : i + 1);
+ }
+
+ /**
+ * Formats transform matrix. The standard rotation, scale and translate
+ * matrices are replaced by their shorter forms, and for identity matrix
+ * returns empty string to save the memory.
+ * @param m {Array} matrix to format.
+ * @returns {string}
+ */
+ function pm(m) {
+ if (m[4] === 0 && m[5] === 0) {
+ if (m[1] === 0 && m[2] === 0) {
+ if (m[0] === 1 && m[3] === 1) {
+ return '';
+ }
+ return 'scale(' + pf(m[0]) + ' ' + pf(m[3]) + ')';
+ }
+ if (m[0] === m[3] && m[1] === -m[2]) {
+ var a = Math.acos(m[0]) * 180 / Math.PI;
+ return 'rotate(' + pf(a) + ')';
+ }
+ } else {
+ if (m[0] === 1 && m[1] === 0 && m[2] === 0 && m[3] === 1) {
+ return 'translate(' + pf(m[4]) + ' ' + pf(m[5]) + ')';
+ }
+ }
+ return 'matrix(' + pf(m[0]) + ' ' + pf(m[1]) + ' ' + pf(m[2]) + ' ' +
+ pf(m[3]) + ' ' + pf(m[4]) + ' ' + pf(m[5]) + ')';
+ }
+
+ function SVGGraphics(commonObjs, objs, forceDataSchema) {
+ this.current = new SVGExtraState();
+ this.transformMatrix = IDENTITY_MATRIX; // Graphics state matrix
+ this.transformStack = [];
+ this.extraStack = [];
+ this.commonObjs = commonObjs;
+ this.objs = objs;
+ this.pendingEOFill = false;
+
+ this.embedFonts = false;
+ this.embeddedFonts = Object.create(null);
+ this.cssStyle = null;
+ this.forceDataSchema = !!forceDataSchema;
+ }
+
+ var NS = 'http://www.w3.org/2000/svg';
+ var XML_NS = 'http://www.w3.org/XML/1998/namespace';
+ var XLINK_NS = 'http://www.w3.org/1999/xlink';
+ var LINE_CAP_STYLES = ['butt', 'round', 'square'];
+ var LINE_JOIN_STYLES = ['miter', 'round', 'bevel'];
+ var clipCount = 0;
+ var maskCount = 0;
+
+ SVGGraphics.prototype = {
+ save: function SVGGraphics_save() {
+ this.transformStack.push(this.transformMatrix);
+ var old = this.current;
+ this.extraStack.push(old);
+ this.current = old.clone();
+ },
+
+ restore: function SVGGraphics_restore() {
+ this.transformMatrix = this.transformStack.pop();
+ this.current = this.extraStack.pop();
+
+ this.tgrp = document.createElementNS(NS, 'svg:g');
+ this.tgrp.setAttributeNS(null, 'transform', pm(this.transformMatrix));
+ this.pgrp.appendChild(this.tgrp);
+ },
+
+ group: function SVGGraphics_group(items) {
+ this.save();
+ this.executeOpTree(items);
+ this.restore();
+ },
+
+ loadDependencies: function SVGGraphics_loadDependencies(operatorList) {
+ var fnArray = operatorList.fnArray;
+ var fnArrayLen = fnArray.length;
+ var argsArray = operatorList.argsArray;
+
+ var self = this;
+ for (var i = 0; i < fnArrayLen; i++) {
+ if (OPS.dependency === fnArray[i]) {
+ var deps = argsArray[i];
+ for (var n = 0, nn = deps.length; n < nn; n++) {
+ var obj = deps[n];
+ var common = obj.substring(0, 2) === 'g_';
+ var promise;
+ if (common) {
+ promise = new Promise(function(resolve) {
+ self.commonObjs.get(obj, resolve);
+ });
+ } else {
+ promise = new Promise(function(resolve) {
+ self.objs.get(obj, resolve);
+ });
+ }
+ this.current.dependencies.push(promise);
+ }
+ }
+ }
+ return Promise.all(this.current.dependencies);
+ },
+
+ transform: function SVGGraphics_transform(a, b, c, d, e, f) {
+ var transformMatrix = [a, b, c, d, e, f];
+ this.transformMatrix = Util.transform(this.transformMatrix,
+ transformMatrix);
+
+ this.tgrp = document.createElementNS(NS, 'svg:g');
+ this.tgrp.setAttributeNS(null, 'transform', pm(this.transformMatrix));
+ },
+
+ getSVG: function SVGGraphics_getSVG(operatorList, viewport) {
+ this.svg = createScratchSVG(viewport.width, viewport.height);
+ this.viewport = viewport;
+
+ return this.loadDependencies(operatorList).then(function () {
+ this.transformMatrix = IDENTITY_MATRIX;
+ this.pgrp = document.createElementNS(NS, 'svg:g'); // Parent group
+ this.pgrp.setAttributeNS(null, 'transform', pm(viewport.transform));
+ this.tgrp = document.createElementNS(NS, 'svg:g'); // Transform group
+ this.tgrp.setAttributeNS(null, 'transform', pm(this.transformMatrix));
+ this.defs = document.createElementNS(NS, 'svg:defs');
+ this.pgrp.appendChild(this.defs);
+ this.pgrp.appendChild(this.tgrp);
+ this.svg.appendChild(this.pgrp);
+ var opTree = this.convertOpList(operatorList);
+ this.executeOpTree(opTree);
+ return this.svg;
+ }.bind(this));
+ },
+
+ convertOpList: function SVGGraphics_convertOpList(operatorList) {
+ var argsArray = operatorList.argsArray;
+ var fnArray = operatorList.fnArray;
+ var fnArrayLen = fnArray.length;
+ var REVOPS = [];
+ var opList = [];
+
+ for (var op in OPS) {
+ REVOPS[OPS[op]] = op;
+ }
+
+ for (var x = 0; x < fnArrayLen; x++) {
+ var fnId = fnArray[x];
+ opList.push({'fnId' : fnId, 'fn': REVOPS[fnId], 'args': argsArray[x]});
+ }
+ return opListToTree(opList);
+ },
+
+ executeOpTree: function SVGGraphics_executeOpTree(opTree) {
+ var opTreeLen = opTree.length;
+ for(var x = 0; x < opTreeLen; x++) {
+ var fn = opTree[x].fn;
+ var fnId = opTree[x].fnId;
+ var args = opTree[x].args;
+
+ switch (fnId | 0) {
+ case OPS.beginText:
+ this.beginText();
+ break;
+ case OPS.setLeading:
+ this.setLeading(args);
+ break;
+ case OPS.setLeadingMoveText:
+ this.setLeadingMoveText(args[0], args[1]);
+ break;
+ case OPS.setFont:
+ this.setFont(args);
+ break;
+ case OPS.showText:
+ this.showText(args[0]);
+ break;
+ case OPS.showSpacedText:
+ this.showText(args[0]);
+ break;
+ case OPS.endText:
+ this.endText();
+ break;
+ case OPS.moveText:
+ this.moveText(args[0], args[1]);
+ break;
+ case OPS.setCharSpacing:
+ this.setCharSpacing(args[0]);
+ break;
+ case OPS.setWordSpacing:
+ this.setWordSpacing(args[0]);
+ break;
+ case OPS.setHScale:
+ this.setHScale(args[0]);
+ break;
+ case OPS.setTextMatrix:
+ this.setTextMatrix(args[0], args[1], args[2],
+ args[3], args[4], args[5]);
+ break;
+ case OPS.setLineWidth:
+ this.setLineWidth(args[0]);
+ break;
+ case OPS.setLineJoin:
+ this.setLineJoin(args[0]);
+ break;
+ case OPS.setLineCap:
+ this.setLineCap(args[0]);
+ break;
+ case OPS.setMiterLimit:
+ this.setMiterLimit(args[0]);
+ break;
+ case OPS.setFillRGBColor:
+ this.setFillRGBColor(args[0], args[1], args[2]);
+ break;
+ case OPS.setStrokeRGBColor:
+ this.setStrokeRGBColor(args[0], args[1], args[2]);
+ break;
+ case OPS.setDash:
+ this.setDash(args[0], args[1]);
+ break;
+ case OPS.setGState:
+ this.setGState(args[0]);
+ break;
+ case OPS.fill:
+ this.fill();
+ break;
+ case OPS.eoFill:
+ this.eoFill();
+ break;
+ case OPS.stroke:
+ this.stroke();
+ break;
+ case OPS.fillStroke:
+ this.fillStroke();
+ break;
+ case OPS.eoFillStroke:
+ this.eoFillStroke();
+ break;
+ case OPS.clip:
+ this.clip('nonzero');
+ break;
+ case OPS.eoClip:
+ this.clip('evenodd');
+ break;
+ case OPS.paintSolidColorImageMask:
+ this.paintSolidColorImageMask();
+ break;
+ case OPS.paintJpegXObject:
+ this.paintJpegXObject(args[0], args[1], args[2]);
+ break;
+ case OPS.paintImageXObject:
+ this.paintImageXObject(args[0]);
+ break;
+ case OPS.paintInlineImageXObject:
+ this.paintInlineImageXObject(args[0]);
+ break;
+ case OPS.paintImageMaskXObject:
+ this.paintImageMaskXObject(args[0]);
+ break;
+ case OPS.paintFormXObjectBegin:
+ this.paintFormXObjectBegin(args[0], args[1]);
+ break;
+ case OPS.paintFormXObjectEnd:
+ this.paintFormXObjectEnd();
+ break;
+ case OPS.closePath:
+ this.closePath();
+ break;
+ case OPS.closeStroke:
+ this.closeStroke();
+ break;
+ case OPS.closeFillStroke:
+ this.closeFillStroke();
+ break;
+ case OPS.nextLine:
+ this.nextLine();
+ break;
+ case OPS.transform:
+ this.transform(args[0], args[1], args[2], args[3],
+ args[4], args[5]);
+ break;
+ case OPS.constructPath:
+ this.constructPath(args[0], args[1]);
+ break;
+ case OPS.endPath:
+ this.endPath();
+ break;
+ case 92:
+ this.group(opTree[x].items);
+ break;
+ default:
+ warn('Unimplemented method '+ fn);
+ break;
+ }
+ }
+ },
+
+ setWordSpacing: function SVGGraphics_setWordSpacing(wordSpacing) {
+ this.current.wordSpacing = wordSpacing;
+ },
+
+ setCharSpacing: function SVGGraphics_setCharSpacing(charSpacing) {
+ this.current.charSpacing = charSpacing;
+ },
+
+ nextLine: function SVGGraphics_nextLine() {
+ this.moveText(0, this.current.leading);
+ },
+
+ setTextMatrix: function SVGGraphics_setTextMatrix(a, b, c, d, e, f) {
+ var current = this.current;
+ this.current.textMatrix = this.current.lineMatrix = [a, b, c, d, e, f];
+
+ this.current.x = this.current.lineX = 0;
+ this.current.y = this.current.lineY = 0;
+
+ current.xcoords = [];
+ current.tspan = document.createElementNS(NS, 'svg:tspan');
+ current.tspan.setAttributeNS(null, 'font-family', current.fontFamily);
+ current.tspan.setAttributeNS(null, 'font-size',
+ pf(current.fontSize) + 'px');
+ current.tspan.setAttributeNS(null, 'y', pf(-current.y));
+
+ current.txtElement = document.createElementNS(NS, 'svg:text');
+ current.txtElement.appendChild(current.tspan);
+ },
+
+ beginText: function SVGGraphics_beginText() {
+ this.current.x = this.current.lineX = 0;
+ this.current.y = this.current.lineY = 0;
+ this.current.textMatrix = IDENTITY_MATRIX;
+ this.current.lineMatrix = IDENTITY_MATRIX;
+ this.current.tspan = document.createElementNS(NS, 'svg:tspan');
+ this.current.txtElement = document.createElementNS(NS, 'svg:text');
+ this.current.txtgrp = document.createElementNS(NS, 'svg:g');
+ this.current.xcoords = [];
+ },
+
+ moveText: function SVGGraphics_moveText(x, y) {
+ var current = this.current;
+ this.current.x = this.current.lineX += x;
+ this.current.y = this.current.lineY += y;
+
+ current.xcoords = [];
+ current.tspan = document.createElementNS(NS, 'svg:tspan');
+ current.tspan.setAttributeNS(null, 'font-family', current.fontFamily);
+ current.tspan.setAttributeNS(null, 'font-size',
+ pf(current.fontSize) + 'px');
+ current.tspan.setAttributeNS(null, 'y', pf(-current.y));
+ },
+
+ showText: function SVGGraphics_showText(glyphs) {
+ var current = this.current;
+ var font = current.font;
+ var fontSize = current.fontSize;
+
+ if (fontSize === 0) {
+ return;
+ }
+
+ var charSpacing = current.charSpacing;
+ var wordSpacing = current.wordSpacing;
+ var fontDirection = current.fontDirection;
+ var textHScale = current.textHScale * fontDirection;
+ var glyphsLength = glyphs.length;
+ var vertical = font.vertical;
+ var widthAdvanceScale = fontSize * current.fontMatrix[0];
+
+ var x = 0, i;
+ for (i = 0; i < glyphsLength; ++i) {
+ var glyph = glyphs[i];
+ if (glyph === null) {
+ // word break
+ x += fontDirection * wordSpacing;
+ continue;
+ } else if (isNum(glyph)) {
+ x += -glyph * fontSize * 0.001;
+ continue;
+ }
+ current.xcoords.push(current.x + x * textHScale);
+
+ var width = glyph.width;
+ var character = glyph.fontChar;
+ var charWidth = width * widthAdvanceScale + charSpacing * fontDirection;
+ x += charWidth;
+
+ current.tspan.textContent += character;
+ }
+ if (vertical) {
+ current.y -= x * textHScale;
+ } else {
+ current.x += x * textHScale;
+ }
+
+ current.tspan.setAttributeNS(null, 'x',
+ current.xcoords.map(pf).join(' '));
+ current.tspan.setAttributeNS(null, 'y', pf(-current.y));
+ current.tspan.setAttributeNS(null, 'font-family', current.fontFamily);
+ current.tspan.setAttributeNS(null, 'font-size',
+ pf(current.fontSize) + 'px');
+ if (current.fontStyle !== SVG_DEFAULTS.fontStyle) {
+ current.tspan.setAttributeNS(null, 'font-style', current.fontStyle);
+ }
+ if (current.fontWeight !== SVG_DEFAULTS.fontWeight) {
+ current.tspan.setAttributeNS(null, 'font-weight', current.fontWeight);
+ }
+ if (current.fillColor !== SVG_DEFAULTS.fillColor) {
+ current.tspan.setAttributeNS(null, 'fill', current.fillColor);
+ }
+
+ current.txtElement.setAttributeNS(null, 'transform',
+ pm(current.textMatrix) +
+ ' scale(1, -1)' );
+ current.txtElement.setAttributeNS(XML_NS, 'xml:space', 'preserve');
+ current.txtElement.appendChild(current.tspan);
+ current.txtgrp.appendChild(current.txtElement);
+
+ this.tgrp.appendChild(current.txtElement);
+
+ },
+
+ setLeadingMoveText: function SVGGraphics_setLeadingMoveText(x, y) {
+ this.setLeading(-y);
+ this.moveText(x, y);
+ },
+
+ addFontStyle: function SVGGraphics_addFontStyle(fontObj) {
+ if (!this.cssStyle) {
+ this.cssStyle = document.createElementNS(NS, 'svg:style');
+ this.cssStyle.setAttributeNS(null, 'type', 'text/css');
+ this.defs.appendChild(this.cssStyle);
+ }
+
+ var url = createObjectURL(fontObj.data, fontObj.mimetype,
+ this.forceDataSchema);
+ this.cssStyle.textContent +=
+ '@font-face { font-family: "' + fontObj.loadedName + '";' +
+ ' src: url(' + url + '); }\n';
+ },
+
+ setFont: function SVGGraphics_setFont(details) {
+ var current = this.current;
+ var fontObj = this.commonObjs.get(details[0]);
+ var size = details[1];
+ this.current.font = fontObj;
+
+ if (this.embedFonts && fontObj.data &&
+ !this.embeddedFonts[fontObj.loadedName]) {
+ this.addFontStyle(fontObj);
+ this.embeddedFonts[fontObj.loadedName] = fontObj;
+ }
+
+ current.fontMatrix = (fontObj.fontMatrix ?
+ fontObj.fontMatrix : FONT_IDENTITY_MATRIX);
+
+ var bold = fontObj.black ? (fontObj.bold ? 'bolder' : 'bold') :
+ (fontObj.bold ? 'bold' : 'normal');
+ var italic = fontObj.italic ? 'italic' : 'normal';
+
+ if (size < 0) {
+ size = -size;
+ current.fontDirection = -1;
+ } else {
+ current.fontDirection = 1;
+ }
+ current.fontSize = size;
+ current.fontFamily = fontObj.loadedName;
+ current.fontWeight = bold;
+ current.fontStyle = italic;
+
+ current.tspan = document.createElementNS(NS, 'svg:tspan');
+ current.tspan.setAttributeNS(null, 'y', pf(-current.y));
+ current.xcoords = [];
+ },
+
+ endText: function SVGGraphics_endText() {
+ if (this.current.pendingClip) {
+ this.cgrp.appendChild(this.tgrp);
+ this.pgrp.appendChild(this.cgrp);
+ } else {
+ this.pgrp.appendChild(this.tgrp);
+ }
+ this.tgrp = document.createElementNS(NS, 'svg:g');
+ this.tgrp.setAttributeNS(null, 'transform', pm(this.transformMatrix));
+ },
+
+ // Path properties
+ setLineWidth: function SVGGraphics_setLineWidth(width) {
+ this.current.lineWidth = width;
+ },
+ setLineCap: function SVGGraphics_setLineCap(style) {
+ this.current.lineCap = LINE_CAP_STYLES[style];
+ },
+ setLineJoin: function SVGGraphics_setLineJoin(style) {
+ this.current.lineJoin = LINE_JOIN_STYLES[style];
+ },
+ setMiterLimit: function SVGGraphics_setMiterLimit(limit) {
+ this.current.miterLimit = limit;
+ },
+ setStrokeRGBColor: function SVGGraphics_setStrokeRGBColor(r, g, b) {
+ var color = Util.makeCssRgb(r, g, b);
+ this.current.strokeColor = color;
+ },
+ setFillRGBColor: function SVGGraphics_setFillRGBColor(r, g, b) {
+ var color = Util.makeCssRgb(r, g, b);
+ this.current.fillColor = color;
+ this.current.tspan = document.createElementNS(NS, 'svg:tspan');
+ this.current.xcoords = [];
+ },
+ setDash: function SVGGraphics_setDash(dashArray, dashPhase) {
+ this.current.dashArray = dashArray;
+ this.current.dashPhase = dashPhase;
+ },
+
+ constructPath: function SVGGraphics_constructPath(ops, args) {
+ var current = this.current;
+ var x = current.x, y = current.y;
+ current.path = document.createElementNS(NS, 'svg:path');
+ var d = [];
+ var opLength = ops.length;
+
+ for (var i = 0, j = 0; i < opLength; i++) {
+ switch (ops[i] | 0) {
+ case OPS.rectangle:
+ x = args[j++];
+ y = args[j++];
+ var width = args[j++];
+ var height = args[j++];
+ var xw = x + width;
+ var yh = y + height;
+ d.push('M', pf(x), pf(y), 'L', pf(xw) , pf(y), 'L', pf(xw), pf(yh),
+ 'L', pf(x), pf(yh), 'Z');
+ break;
+ case OPS.moveTo:
+ x = args[j++];
+ y = args[j++];
+ d.push('M', pf(x), pf(y));
+ break;
+ case OPS.lineTo:
+ x = args[j++];
+ y = args[j++];
+ d.push('L', pf(x) , pf(y));
+ break;
+ case OPS.curveTo:
+ x = args[j + 4];
+ y = args[j + 5];
+ d.push('C', pf(args[j]), pf(args[j + 1]), pf(args[j + 2]),
+ pf(args[j + 3]), pf(x), pf(y));
+ j += 6;
+ break;
+ case OPS.curveTo2:
+ x = args[j + 2];
+ y = args[j + 3];
+ d.push('C', pf(x), pf(y), pf(args[j]), pf(args[j + 1]),
+ pf(args[j + 2]), pf(args[j + 3]));
+ j += 4;
+ break;
+ case OPS.curveTo3:
+ x = args[j + 2];
+ y = args[j + 3];
+ d.push('C', pf(args[j]), pf(args[j + 1]), pf(x), pf(y),
+ pf(x), pf(y));
+ j += 4;
+ break;
+ case OPS.closePath:
+ d.push('Z');
+ break;
+ }
+ }
+ current.path.setAttributeNS(null, 'd', d.join(' '));
+ current.path.setAttributeNS(null, 'stroke-miterlimit',
+ pf(current.miterLimit));
+ current.path.setAttributeNS(null, 'stroke-linecap', current.lineCap);
+ current.path.setAttributeNS(null, 'stroke-linejoin', current.lineJoin);
+ current.path.setAttributeNS(null, 'stroke-width',
+ pf(current.lineWidth) + 'px');
+ current.path.setAttributeNS(null, 'stroke-dasharray',
+ current.dashArray.map(pf).join(' '));
+ current.path.setAttributeNS(null, 'stroke-dashoffset',
+ pf(current.dashPhase) + 'px');
+ current.path.setAttributeNS(null, 'fill', 'none');
+
+ this.tgrp.appendChild(current.path);
+ if (current.pendingClip) {
+ this.cgrp.appendChild(this.tgrp);
+ this.pgrp.appendChild(this.cgrp);
+ } else {
+ this.pgrp.appendChild(this.tgrp);
+ }
+ // Saving a reference in current.element so that it can be addressed
+ // in 'fill' and 'stroke'
+ current.element = current.path;
+ current.setCurrentPoint(x, y);
+ },
+
+ endPath: function SVGGraphics_endPath() {
+ var current = this.current;
+ if (current.pendingClip) {
+ this.cgrp.appendChild(this.tgrp);
+ this.pgrp.appendChild(this.cgrp);
+ } else {
+ this.pgrp.appendChild(this.tgrp);
+ }
+ this.tgrp = document.createElementNS(NS, 'svg:g');
+ this.tgrp.setAttributeNS(null, 'transform', pm(this.transformMatrix));
+ },
+
+ clip: function SVGGraphics_clip(type) {
+ var current = this.current;
+ // Add current path to clipping path
+ current.clipId = 'clippath' + clipCount;
+ clipCount++;
+ this.clippath = document.createElementNS(NS, 'svg:clipPath');
+ this.clippath.setAttributeNS(null, 'id', current.clipId);
+ var clipElement = current.element.cloneNode();
+ if (type === 'evenodd') {
+ clipElement.setAttributeNS(null, 'clip-rule', 'evenodd');
+ } else {
+ clipElement.setAttributeNS(null, 'clip-rule', 'nonzero');
+ }
+ this.clippath.setAttributeNS(null, 'transform', pm(this.transformMatrix));
+ this.clippath.appendChild(clipElement);
+ this.defs.appendChild(this.clippath);
+
+ // Create a new group with that attribute
+ current.pendingClip = true;
+ this.cgrp = document.createElementNS(NS, 'svg:g');
+ this.cgrp.setAttributeNS(null, 'clip-path',
+ 'url(#' + current.clipId + ')');
+ this.pgrp.appendChild(this.cgrp);
+ },
+
+ closePath: function SVGGraphics_closePath() {
+ var current = this.current;
+ var d = current.path.getAttributeNS(null, 'd');
+ d += 'Z';
+ current.path.setAttributeNS(null, 'd', d);
+ },
+
+ setLeading: function SVGGraphics_setLeading(leading) {
+ this.current.leading = -leading;
+ },
+
+ setTextRise: function SVGGraphics_setTextRise(textRise) {
+ this.current.textRise = textRise;
+ },
+
+ setHScale: function SVGGraphics_setHScale(scale) {
+ this.current.textHScale = scale / 100;
+ },
+
+ setGState: function SVGGraphics_setGState(states) {
+ for (var i = 0, ii = states.length; i < ii; i++) {
+ var state = states[i];
+ var key = state[0];
+ var value = state[1];
+
+ 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':
+ break;
+ case 'FL':
+ break;
+ case 'Font':
+ this.setFont(value);
+ break;
+ case 'CA':
+ break;
+ case 'ca':
+ break;
+ case 'BM':
+ break;
+ case 'SMask':
+ break;
+ }
+ }
+ },
+
+ fill: function SVGGraphics_fill() {
+ var current = this.current;
+ current.element.setAttributeNS(null, 'fill', current.fillColor);
+ },
+
+ stroke: function SVGGraphics_stroke() {
+ var current = this.current;
+ current.element.setAttributeNS(null, 'stroke', current.strokeColor);
+ current.element.setAttributeNS(null, 'fill', 'none');
+ },
+
+ eoFill: function SVGGraphics_eoFill() {
+ var current = this.current;
+ current.element.setAttributeNS(null, 'fill', current.fillColor);
+ current.element.setAttributeNS(null, 'fill-rule', 'evenodd');
+ },
+
+ fillStroke: function SVGGraphics_fillStroke() {
+ // Order is important since stroke wants fill to be none.
+ // First stroke, then if fill needed, it will be overwritten.
+ this.stroke();
+ this.fill();
+ },
+
+ eoFillStroke: function SVGGraphics_eoFillStroke() {
+ this.current.element.setAttributeNS(null, 'fill-rule', 'evenodd');
+ this.fillStroke();
+ },
+
+ closeStroke: function SVGGraphics_closeStroke() {
+ this.closePath();
+ this.stroke();
+ },
+
+ closeFillStroke: function SVGGraphics_closeFillStroke() {
+ this.closePath();
+ this.fillStroke();
+ },
+
+ paintSolidColorImageMask:
+ function SVGGraphics_paintSolidColorImageMask() {
+ var current = this.current;
+ var rect = document.createElementNS(NS, 'svg:rect');
+ rect.setAttributeNS(null, 'x', '0');
+ rect.setAttributeNS(null, 'y', '0');
+ rect.setAttributeNS(null, 'width', '1px');
+ rect.setAttributeNS(null, 'height', '1px');
+ rect.setAttributeNS(null, 'fill', current.fillColor);
+ this.tgrp.appendChild(rect);
+ },
+
+ paintJpegXObject: function SVGGraphics_paintJpegXObject(objId, w, h) {
+ var current = this.current;
+ var imgObj = this.objs.get(objId);
+ var imgEl = document.createElementNS(NS, 'svg:image');
+ imgEl.setAttributeNS(XLINK_NS, 'xlink:href', imgObj.src);
+ imgEl.setAttributeNS(null, 'width', imgObj.width + 'px');
+ imgEl.setAttributeNS(null, 'height', imgObj.height + 'px');
+ imgEl.setAttributeNS(null, 'x', '0');
+ imgEl.setAttributeNS(null, 'y', pf(-h));
+ imgEl.setAttributeNS(null, 'transform',
+ 'scale(' + pf(1 / w) + ' ' + pf(-1 / h) + ')');
+
+ this.tgrp.appendChild(imgEl);
+ if (current.pendingClip) {
+ this.cgrp.appendChild(this.tgrp);
+ this.pgrp.appendChild(this.cgrp);
+ } else {
+ this.pgrp.appendChild(this.tgrp);
+ }
+ },
+
+ paintImageXObject: function SVGGraphics_paintImageXObject(objId) {
+ var imgData = this.objs.get(objId);
+ if (!imgData) {
+ warn('Dependent image isn\'t ready yet');
+ return;
+ }
+ this.paintInlineImageXObject(imgData);
+ },
+
+ paintInlineImageXObject:
+ function SVGGraphics_paintInlineImageXObject(imgData, mask) {
+ var current = this.current;
+ var width = imgData.width;
+ var height = imgData.height;
+
+ var imgSrc = convertImgDataToPng(imgData, this.forceDataSchema);
+ var cliprect = document.createElementNS(NS, 'svg:rect');
+ cliprect.setAttributeNS(null, 'x', '0');
+ cliprect.setAttributeNS(null, 'y', '0');
+ cliprect.setAttributeNS(null, 'width', pf(width));
+ cliprect.setAttributeNS(null, 'height', pf(height));
+ current.element = cliprect;
+ this.clip('nonzero');
+ var imgEl = document.createElementNS(NS, 'svg:image');
+ imgEl.setAttributeNS(XLINK_NS, 'xlink:href', imgSrc);
+ imgEl.setAttributeNS(null, 'x', '0');
+ imgEl.setAttributeNS(null, 'y', pf(-height));
+ imgEl.setAttributeNS(null, 'width', pf(width) + 'px');
+ imgEl.setAttributeNS(null, 'height', pf(height) + 'px');
+ imgEl.setAttributeNS(null, 'transform',
+ 'scale(' + pf(1 / width) + ' ' +
+ pf(-1 / height) + ')');
+ if (mask) {
+ mask.appendChild(imgEl);
+ } else {
+ this.tgrp.appendChild(imgEl);
+ }
+ if (current.pendingClip) {
+ this.cgrp.appendChild(this.tgrp);
+ this.pgrp.appendChild(this.cgrp);
+ } else {
+ this.pgrp.appendChild(this.tgrp);
+ }
+ },
+
+ paintImageMaskXObject:
+ function SVGGraphics_paintImageMaskXObject(imgData) {
+ var current = this.current;
+ var width = imgData.width;
+ var height = imgData.height;
+ var fillColor = current.fillColor;
+
+ current.maskId = 'mask' + maskCount++;
+ var mask = document.createElementNS(NS, 'svg:mask');
+ mask.setAttributeNS(null, 'id', current.maskId);
+
+ var rect = document.createElementNS(NS, 'svg:rect');
+ rect.setAttributeNS(null, 'x', '0');
+ rect.setAttributeNS(null, 'y', '0');
+ rect.setAttributeNS(null, 'width', pf(width));
+ rect.setAttributeNS(null, 'height', pf(height));
+ rect.setAttributeNS(null, 'fill', fillColor);
+ rect.setAttributeNS(null, 'mask', 'url(#' + current.maskId +')');
+ this.defs.appendChild(mask);
+ this.tgrp.appendChild(rect);
+
+ this.paintInlineImageXObject(imgData, mask);
+ },
+
+ paintFormXObjectBegin:
+ function SVGGraphics_paintFormXObjectBegin(matrix, bbox) {
+ this.save();
+
+ if (isArray(matrix) && matrix.length === 6) {
+ this.transform(matrix[0], matrix[1], matrix[2],
+ matrix[3], matrix[4], matrix[5]);
+ }
+
+ if (isArray(bbox) && bbox.length === 4) {
+ var width = bbox[2] - bbox[0];
+ var height = bbox[3] - bbox[1];
+
+ var cliprect = document.createElementNS(NS, 'svg:rect');
+ cliprect.setAttributeNS(null, 'x', bbox[0]);
+ cliprect.setAttributeNS(null, 'y', bbox[1]);
+ cliprect.setAttributeNS(null, 'width', pf(width));
+ cliprect.setAttributeNS(null, 'height', pf(height));
+ this.current.element = cliprect;
+ this.clip('nonzero');
+ this.endPath();
+ }
+ },
+
+ paintFormXObjectEnd:
+ function SVGGraphics_paintFormXObjectEnd() {
+ this.restore();
+ }
+ };
+ return SVGGraphics;
+})();
+
+exports.SVGGraphics = SVGGraphics;
+}));
+
+
+(function (root, factory) {
+ {
+ factory((root.pdfjsDisplayAnnotationLayer = {}), root.pdfjsSharedUtil,
+ root.pdfjsDisplayDOMUtils);
+ }
+}(this, function (exports, sharedUtil, displayDOMUtils) {
+
+var AnnotationBorderStyleType = sharedUtil.AnnotationBorderStyleType;
+var AnnotationType = sharedUtil.AnnotationType;
+var Util = sharedUtil.Util;
+var addLinkAttributes = displayDOMUtils.addLinkAttributes;
+var LinkTarget = displayDOMUtils.LinkTarget;
+var getFilenameFromUrl = displayDOMUtils.getFilenameFromUrl;
+var warn = sharedUtil.warn;
+var CustomStyle = displayDOMUtils.CustomStyle;
+var getDefaultSetting = displayDOMUtils.getDefaultSetting;
+
+/**
+ * @typedef {Object} AnnotationElementParameters
+ * @property {Object} data
+ * @property {HTMLDivElement} layer
+ * @property {PDFPage} page
+ * @property {PageViewport} viewport
+ * @property {IPDFLinkService} linkService
+ * @property {DownloadManager} downloadManager
+ * @property {string} imageResourcesPath
+ * @property {boolean} renderInteractiveForms
+ */
+
+/**
+ * @class
+ * @alias AnnotationElementFactory
+ */
+function AnnotationElementFactory() {}
+AnnotationElementFactory.prototype =
+ /** @lends AnnotationElementFactory.prototype */ {
+ /**
+ * @param {AnnotationElementParameters} parameters
+ * @returns {AnnotationElement}
+ */
+ create: function AnnotationElementFactory_create(parameters) {
+ var subtype = parameters.data.annotationType;
+
+ switch (subtype) {
+ case AnnotationType.LINK:
+ return new LinkAnnotationElement(parameters);
+
+ case AnnotationType.TEXT:
+ return new TextAnnotationElement(parameters);
+
+ case AnnotationType.WIDGET:
+ var fieldType = parameters.data.fieldType;
+
+ switch (fieldType) {
+ case 'Tx':
+ return new TextWidgetAnnotationElement(parameters);
+ }
+ return new WidgetAnnotationElement(parameters);
+
+ case AnnotationType.POPUP:
+ return new PopupAnnotationElement(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.FILEATTACHMENT:
+ return new FileAttachmentAnnotationElement(parameters);
+
+ default:
+ return new AnnotationElement(parameters);
+ }
+ }
+};
+
+/**
+ * @class
+ * @alias AnnotationElement
+ */
+var AnnotationElement = (function AnnotationElementClosure() {
+ function AnnotationElement(parameters, isRenderable) {
+ this.isRenderable = isRenderable || false;
+ this.data = parameters.data;
+ this.layer = parameters.layer;
+ this.page = parameters.page;
+ this.viewport = parameters.viewport;
+ this.linkService = parameters.linkService;
+ this.downloadManager = parameters.downloadManager;
+ this.imageResourcesPath = parameters.imageResourcesPath;
+ this.renderInteractiveForms = parameters.renderInteractiveForms;
+
+ if (isRenderable) {
+ this.container = this._createContainer();
+ }
+ }
+
+ AnnotationElement.prototype = /** @lends AnnotationElement.prototype */ {
+ /**
+ * Create an empty container for the annotation's HTML element.
+ *
+ * @private
+ * @memberof AnnotationElement
+ * @returns {HTMLSectionElement}
+ */
+ _createContainer: function AnnotationElement_createContainer() {
+ var data = this.data, page = this.page, viewport = this.viewport;
+ var container = document.createElement('section');
+ var width = data.rect[2] - data.rect[0];
+ var height = data.rect[3] - data.rect[1];
+
+ container.setAttribute('data-annotation-id', data.id);
+
+ // Do *not* modify `data.rect`, since that will corrupt the annotation
+ // position on subsequent calls to `_createContainer` (see issue 6804).
+ var 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]
+ ]);
+
+ CustomStyle.setProp('transform', container,
+ 'matrix(' + viewport.transform.join(',') + ')');
+ CustomStyle.setProp('transformOrigin', container,
+ -rect[0] + 'px ' + -rect[1] + 'px');
+
+ if (data.borderStyle.width > 0) {
+ container.style.borderWidth = data.borderStyle.width + 'px';
+ if (data.borderStyle.style !== AnnotationBorderStyleType.UNDERLINE) {
+ // Underline styles only have a bottom border, so we do not need
+ // to adjust for all borders. This yields a similar result as
+ // Adobe Acrobat/Reader.
+ width = width - 2 * data.borderStyle.width;
+ height = height - 2 * data.borderStyle.width;
+ }
+
+ var horizontalRadius = data.borderStyle.horizontalCornerRadius;
+ var verticalRadius = data.borderStyle.verticalCornerRadius;
+ if (horizontalRadius > 0 || verticalRadius > 0) {
+ var radius = horizontalRadius + 'px / ' + verticalRadius + 'px';
+ CustomStyle.setProp('borderRadius', container, radius);
+ }
+
+ switch (data.borderStyle.style) {
+ case AnnotationBorderStyleType.SOLID:
+ container.style.borderStyle = 'solid';
+ break;
+
+ case AnnotationBorderStyleType.DASHED:
+ container.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:
+ container.style.borderBottomStyle = 'solid';
+ break;
+
+ default:
+ break;
+ }
+
+ if (data.color) {
+ container.style.borderColor =
+ Util.makeCssRgb(data.color[0] | 0,
+ data.color[1] | 0,
+ data.color[2] | 0);
+ } else {
+ // Transparent (invisible) border, so do not draw it at all.
+ container.style.borderWidth = 0;
+ }
+ }
+
+ container.style.left = rect[0] + 'px';
+ container.style.top = rect[1] + 'px';
+
+ container.style.width = width + 'px';
+ container.style.height = height + 'px';
+
+ return container;
+ },
+
+ /**
+ * Create a popup for the annotation's HTML element. This is used for
+ * annotations that do not have a Popup entry in the dictionary, but
+ * are of a type that works with popups (such as Highlight annotations).
+ *
+ * @private
+ * @param {HTMLSectionElement} container
+ * @param {HTMLDivElement|HTMLImageElement|null} trigger
+ * @param {Object} data
+ * @memberof AnnotationElement
+ */
+ _createPopup:
+ function AnnotationElement_createPopup(container, trigger, data) {
+ // If no trigger element is specified, create it.
+ if (!trigger) {
+ trigger = document.createElement('div');
+ trigger.style.height = container.style.height;
+ trigger.style.width = container.style.width;
+ container.appendChild(trigger);
+ }
+
+ var popupElement = new PopupElement({
+ container: container,
+ trigger: trigger,
+ color: data.color,
+ title: data.title,
+ contents: data.contents,
+ hideWrapper: true
+ });
+ var popup = popupElement.render();
+
+ // Position the popup next to the annotation's container.
+ popup.style.left = container.style.width;
+
+ container.appendChild(popup);
+ },
+
+ /**
+ * Render the annotation's HTML element in the empty container.
+ *
+ * @public
+ * @memberof AnnotationElement
+ */
+ render: function AnnotationElement_render() {
+ throw new Error('Abstract method AnnotationElement.render called');
+ }
+ };
+
+ return AnnotationElement;
+})();
+
+/**
+ * @class
+ * @alias LinkAnnotationElement
+ */
+var LinkAnnotationElement = (function LinkAnnotationElementClosure() {
+ function LinkAnnotationElement(parameters) {
+ AnnotationElement.call(this, parameters, true);
+ }
+
+ Util.inherit(LinkAnnotationElement, AnnotationElement, {
+ /**
+ * Render the link annotation's HTML element in the empty container.
+ *
+ * @public
+ * @memberof LinkAnnotationElement
+ * @returns {HTMLSectionElement}
+ */
+ render: function LinkAnnotationElement_render() {
+ this.container.className = 'linkAnnotation';
+
+ var link = document.createElement('a');
+ addLinkAttributes(link, {
+ url: this.data.url,
+ target: (this.data.newWindow ? LinkTarget.BLANK : undefined),
+ });
+
+ if (!this.data.url) {
+ if (this.data.action) {
+ this._bindNamedAction(link, this.data.action);
+ } else {
+ this._bindLink(link, (this.data.dest || null));
+ }
+ }
+
+ this.container.appendChild(link);
+ return this.container;
+ },
+
+ /**
+ * Bind internal links to the link element.
+ *
+ * @private
+ * @param {Object} link
+ * @param {Object} destination
+ * @memberof LinkAnnotationElement
+ */
+ _bindLink: function LinkAnnotationElement_bindLink(link, destination) {
+ var self = this;
+
+ link.href = this.linkService.getDestinationHash(destination);
+ link.onclick = function() {
+ if (destination) {
+ self.linkService.navigateTo(destination);
+ }
+ return false;
+ };
+ if (destination) {
+ link.className = 'internalLink';
+ }
+ },
+
+ /**
+ * Bind named actions to the link element.
+ *
+ * @private
+ * @param {Object} link
+ * @param {Object} action
+ * @memberof LinkAnnotationElement
+ */
+ _bindNamedAction:
+ function LinkAnnotationElement_bindNamedAction(link, action) {
+ var self = this;
+
+ link.href = this.linkService.getAnchorUrl('');
+ link.onclick = function() {
+ self.linkService.executeNamedAction(action);
+ return false;
+ };
+ link.className = 'internalLink';
+ }
+ });
+
+ return LinkAnnotationElement;
+})();
+
+/**
+ * @class
+ * @alias TextAnnotationElement
+ */
+var TextAnnotationElement = (function TextAnnotationElementClosure() {
+ function TextAnnotationElement(parameters) {
+ var isRenderable = !!(parameters.data.hasPopup ||
+ parameters.data.title || parameters.data.contents);
+ AnnotationElement.call(this, parameters, isRenderable);
+ }
+
+ Util.inherit(TextAnnotationElement, AnnotationElement, {
+ /**
+ * Render the text annotation's HTML element in the empty container.
+ *
+ * @public
+ * @memberof TextAnnotationElement
+ * @returns {HTMLSectionElement}
+ */
+ render: function TextAnnotationElement_render() {
+ this.container.className = 'textAnnotation';
+
+ var image = document.createElement('img');
+ image.style.height = this.container.style.height;
+ image.style.width = this.container.style.width;
+ image.src = this.imageResourcesPath + 'annotation-' +
+ this.data.name.toLowerCase() + '.svg';
+ image.alt = '[{{type}} Annotation]';
+ image.dataset.l10nId = 'text_annotation_type';
+ image.dataset.l10nArgs = JSON.stringify({type: this.data.name});
+
+ if (!this.data.hasPopup) {
+ this._createPopup(this.container, image, this.data);
+ }
+
+ this.container.appendChild(image);
+ return this.container;
+ }
+ });
+
+ return TextAnnotationElement;
+})();
+
+/**
+ * @class
+ * @alias WidgetAnnotationElement
+ */
+var WidgetAnnotationElement = (function WidgetAnnotationElementClosure() {
+ function WidgetAnnotationElement(parameters) {
+ var isRenderable = parameters.renderInteractiveForms ||
+ (!parameters.data.hasAppearance && !!parameters.data.fieldValue);
+ AnnotationElement.call(this, parameters, isRenderable);
+ }
+
+ Util.inherit(WidgetAnnotationElement, AnnotationElement, {
+ /**
+ * Render the widget annotation's HTML element in the empty container.
+ *
+ * @public
+ * @memberof WidgetAnnotationElement
+ * @returns {HTMLSectionElement}
+ */
+ render: function WidgetAnnotationElement_render() {
+ // Show only the container for unsupported field types.
+ return this.container;
+ }
+ });
+
+ return WidgetAnnotationElement;
+})();
+
+/**
+ * @class
+ * @alias TextWidgetAnnotationElement
+ */
+var TextWidgetAnnotationElement = (
+ function TextWidgetAnnotationElementClosure() {
+ var TEXT_ALIGNMENT = ['left', 'center', 'right'];
+
+ function TextWidgetAnnotationElement(parameters) {
+ WidgetAnnotationElement.call(this, parameters);
+ }
+
+ Util.inherit(TextWidgetAnnotationElement, WidgetAnnotationElement, {
+ /**
+ * Render the text widget annotation's HTML element in the empty container.
+ *
+ * @public
+ * @memberof TextWidgetAnnotationElement
+ * @returns {HTMLSectionElement}
+ */
+ render: function TextWidgetAnnotationElement_render() {
+ this.container.className = 'textWidgetAnnotation';
+
+ var element = null;
+ if (this.renderInteractiveForms) {
+ // NOTE: We cannot set the values using `element.value` below, since it
+ // prevents the AnnotationLayer rasterizer in `test/driver.js`
+ // from parsing the elements correctly for the reference tests.
+ if (this.data.multiLine) {
+ element = document.createElement('textarea');
+ element.textContent = this.data.fieldValue;
+ } else {
+ element = document.createElement('input');
+ element.type = 'text';
+ element.setAttribute('value', this.data.fieldValue);
+ }
+
+ element.disabled = this.data.readOnly;
+
+ if (this.data.maxLen !== null) {
+ element.maxLength = this.data.maxLen;
+ }
+
+ if (this.data.comb) {
+ var fieldWidth = this.data.rect[2] - this.data.rect[0];
+ var combWidth = fieldWidth / this.data.maxLen;
+
+ element.classList.add('comb');
+ element.style.letterSpacing = 'calc(' + combWidth + 'px - 1ch)';
+ }
+ } else {
+ element = document.createElement('div');
+ element.textContent = this.data.fieldValue;
+ element.style.verticalAlign = 'middle';
+ element.style.display = 'table-cell';
+
+ var font = null;
+ if (this.data.fontRefName) {
+ font = this.page.commonObjs.getData(this.data.fontRefName);
+ }
+ this._setTextStyle(element, font);
+ }
+
+ if (this.data.textAlignment !== null) {
+ element.style.textAlign = TEXT_ALIGNMENT[this.data.textAlignment];
+ }
+
+ this.container.appendChild(element);
+ return this.container;
+ },
+
+ /**
+ * Apply text styles to the text in the element.
+ *
+ * @private
+ * @param {HTMLDivElement} element
+ * @param {Object} font
+ * @memberof TextWidgetAnnotationElement
+ */
+ _setTextStyle:
+ function TextWidgetAnnotationElement_setTextStyle(element, font) {
+ // TODO: This duplicates some of the logic in CanvasGraphics.setFont().
+ var style = element.style;
+ style.fontSize = this.data.fontSize + 'px';
+ style.direction = (this.data.fontDirection < 0 ? 'rtl': 'ltr');
+
+ if (!font) {
+ return;
+ }
+
+ style.fontWeight = (font.black ?
+ (font.bold ? '900' : 'bold') :
+ (font.bold ? 'bold' : 'normal'));
+ style.fontStyle = (font.italic ? 'italic' : 'normal');
+
+ // Use a reasonable default font if the font doesn't specify a fallback.
+ var fontFamily = font.loadedName ? '"' + font.loadedName + '", ' : '';
+ var fallbackName = font.fallbackName || 'Helvetica, sans-serif';
+ style.fontFamily = fontFamily + fallbackName;
+ }
+ });
+
+ return TextWidgetAnnotationElement;
+})();
+
+/**
+ * @class
+ * @alias PopupAnnotationElement
+ */
+var PopupAnnotationElement = (function PopupAnnotationElementClosure() {
+ function PopupAnnotationElement(parameters) {
+ var isRenderable = !!(parameters.data.title || parameters.data.contents);
+ AnnotationElement.call(this, parameters, isRenderable);
+ }
+
+ Util.inherit(PopupAnnotationElement, AnnotationElement, {
+ /**
+ * Render the popup annotation's HTML element in the empty container.
+ *
+ * @public
+ * @memberof PopupAnnotationElement
+ * @returns {HTMLSectionElement}
+ */
+ render: function PopupAnnotationElement_render() {
+ this.container.className = 'popupAnnotation';
+
+ var selector = '[data-annotation-id="' + this.data.parentId + '"]';
+ var parentElement = this.layer.querySelector(selector);
+ if (!parentElement) {
+ return this.container;
+ }
+
+ var popup = new PopupElement({
+ container: this.container,
+ trigger: parentElement,
+ color: this.data.color,
+ title: this.data.title,
+ contents: this.data.contents
+ });
+
+ // Position the popup next to the parent annotation's container.
+ // PDF viewers ignore a popup annotation's rectangle.
+ var parentLeft = parseFloat(parentElement.style.left);
+ var parentWidth = parseFloat(parentElement.style.width);
+ CustomStyle.setProp('transformOrigin', this.container,
+ -(parentLeft + parentWidth) + 'px -' +
+ parentElement.style.top);
+ this.container.style.left = (parentLeft + parentWidth) + 'px';
+
+ this.container.appendChild(popup.render());
+ return this.container;
+ }
+ });
+
+ return PopupAnnotationElement;
+})();
+
+/**
+ * @class
+ * @alias PopupElement
+ */
+var PopupElement = (function PopupElementClosure() {
+ var BACKGROUND_ENLIGHT = 0.7;
+
+ function PopupElement(parameters) {
+ this.container = parameters.container;
+ this.trigger = parameters.trigger;
+ this.color = parameters.color;
+ this.title = parameters.title;
+ this.contents = parameters.contents;
+ this.hideWrapper = parameters.hideWrapper || false;
+
+ this.pinned = false;
+ }
+
+ PopupElement.prototype = /** @lends PopupElement.prototype */ {
+ /**
+ * Render the popup's HTML element.
+ *
+ * @public
+ * @memberof PopupElement
+ * @returns {HTMLSectionElement}
+ */
+ render: function PopupElement_render() {
+ var wrapper = document.createElement('div');
+ wrapper.className = 'popupWrapper';
+
+ // For Popup annotations we hide the entire section because it contains
+ // only the popup. However, for Text annotations without a separate Popup
+ // annotation, we cannot hide the entire container as the image would
+ // disappear too. In that special case, hiding the wrapper suffices.
+ this.hideElement = (this.hideWrapper ? wrapper : this.container);
+ this.hideElement.setAttribute('hidden', true);
+
+ var popup = document.createElement('div');
+ popup.className = 'popup';
+
+ var color = this.color;
+ if (color) {
+ // Enlighten the color.
+ var r = BACKGROUND_ENLIGHT * (255 - color[0]) + color[0];
+ var g = BACKGROUND_ENLIGHT * (255 - color[1]) + color[1];
+ var b = BACKGROUND_ENLIGHT * (255 - color[2]) + color[2];
+ popup.style.backgroundColor = Util.makeCssRgb(r | 0, g | 0, b | 0);
+ }
+
+ var contents = this._formatContents(this.contents);
+ var title = document.createElement('h1');
+ title.textContent = this.title;
+
+ // Attach the event listeners to the trigger element.
+ this.trigger.addEventListener('click', this._toggle.bind(this));
+ this.trigger.addEventListener('mouseover', this._show.bind(this, false));
+ this.trigger.addEventListener('mouseout', this._hide.bind(this, false));
+ popup.addEventListener('click', this._hide.bind(this, true));
+
+ popup.appendChild(title);
+ popup.appendChild(contents);
+ wrapper.appendChild(popup);
+ return wrapper;
+ },
+
+ /**
+ * Format the contents of the popup by adding newlines where necessary.
+ *
+ * @private
+ * @param {string} contents
+ * @memberof PopupElement
+ * @returns {HTMLParagraphElement}
+ */
+ _formatContents: function PopupElement_formatContents(contents) {
+ var p = document.createElement('p');
+ var lines = contents.split(/(?:\r\n?|\n)/);
+ for (var i = 0, ii = lines.length; i < ii; ++i) {
+ var line = lines[i];
+ p.appendChild(document.createTextNode(line));
+ if (i < (ii - 1)) {
+ p.appendChild(document.createElement('br'));
+ }
+ }
+ return p;
+ },
+
+ /**
+ * Toggle the visibility of the popup.
+ *
+ * @private
+ * @memberof PopupElement
+ */
+ _toggle: function PopupElement_toggle() {
+ if (this.pinned) {
+ this._hide(true);
+ } else {
+ this._show(true);
+ }
+ },
+
+ /**
+ * Show the popup.
+ *
+ * @private
+ * @param {boolean} pin
+ * @memberof PopupElement
+ */
+ _show: function PopupElement_show(pin) {
+ if (pin) {
+ this.pinned = true;
+ }
+ if (this.hideElement.hasAttribute('hidden')) {
+ this.hideElement.removeAttribute('hidden');
+ this.container.style.zIndex += 1;
+ }
+ },
+
+ /**
+ * Hide the popup.
+ *
+ * @private
+ * @param {boolean} unpin
+ * @memberof PopupElement
+ */
+ _hide: function PopupElement_hide(unpin) {
+ if (unpin) {
+ this.pinned = false;
+ }
+ if (!this.hideElement.hasAttribute('hidden') && !this.pinned) {
+ this.hideElement.setAttribute('hidden', true);
+ this.container.style.zIndex -= 1;
+ }
+ }
+ };
+
+ return PopupElement;
+})();
+
+/**
+ * @class
+ * @alias HighlightAnnotationElement
+ */
+var HighlightAnnotationElement = (
+ function HighlightAnnotationElementClosure() {
+ function HighlightAnnotationElement(parameters) {
+ var isRenderable = !!(parameters.data.hasPopup ||
+ parameters.data.title || parameters.data.contents);
+ AnnotationElement.call(this, parameters, isRenderable);
+ }
+
+ Util.inherit(HighlightAnnotationElement, AnnotationElement, {
+ /**
+ * Render the highlight annotation's HTML element in the empty container.
+ *
+ * @public
+ * @memberof HighlightAnnotationElement
+ * @returns {HTMLSectionElement}
+ */
+ render: function HighlightAnnotationElement_render() {
+ this.container.className = 'highlightAnnotation';
+
+ if (!this.data.hasPopup) {
+ this._createPopup(this.container, null, this.data);
+ }
+
+ return this.container;
+ }
+ });
+
+ return HighlightAnnotationElement;
+})();
+
+/**
+ * @class
+ * @alias UnderlineAnnotationElement
+ */
+var UnderlineAnnotationElement = (
+ function UnderlineAnnotationElementClosure() {
+ function UnderlineAnnotationElement(parameters) {
+ var isRenderable = !!(parameters.data.hasPopup ||
+ parameters.data.title || parameters.data.contents);
+ AnnotationElement.call(this, parameters, isRenderable);
+ }
+
+ Util.inherit(UnderlineAnnotationElement, AnnotationElement, {
+ /**
+ * Render the underline annotation's HTML element in the empty container.
+ *
+ * @public
+ * @memberof UnderlineAnnotationElement
+ * @returns {HTMLSectionElement}
+ */
+ render: function UnderlineAnnotationElement_render() {
+ this.container.className = 'underlineAnnotation';
+
+ if (!this.data.hasPopup) {
+ this._createPopup(this.container, null, this.data);
+ }
+
+ return this.container;
+ }
+ });
+
+ return UnderlineAnnotationElement;
+})();
+
+/**
+ * @class
+ * @alias SquigglyAnnotationElement
+ */
+var SquigglyAnnotationElement = (function SquigglyAnnotationElementClosure() {
+ function SquigglyAnnotationElement(parameters) {
+ var isRenderable = !!(parameters.data.hasPopup ||
+ parameters.data.title || parameters.data.contents);
+ AnnotationElement.call(this, parameters, isRenderable);
+ }
+
+ Util.inherit(SquigglyAnnotationElement, AnnotationElement, {
+ /**
+ * Render the squiggly annotation's HTML element in the empty container.
+ *
+ * @public
+ * @memberof SquigglyAnnotationElement
+ * @returns {HTMLSectionElement}
+ */
+ render: function SquigglyAnnotationElement_render() {
+ this.container.className = 'squigglyAnnotation';
+
+ if (!this.data.hasPopup) {
+ this._createPopup(this.container, null, this.data);
+ }
+
+ return this.container;
+ }
+ });
+
+ return SquigglyAnnotationElement;
+})();
+
+/**
+ * @class
+ * @alias StrikeOutAnnotationElement
+ */
+var StrikeOutAnnotationElement = (
+ function StrikeOutAnnotationElementClosure() {
+ function StrikeOutAnnotationElement(parameters) {
+ var isRenderable = !!(parameters.data.hasPopup ||
+ parameters.data.title || parameters.data.contents);
+ AnnotationElement.call(this, parameters, isRenderable);
+ }
+
+ Util.inherit(StrikeOutAnnotationElement, AnnotationElement, {
+ /**
+ * Render the strikeout annotation's HTML element in the empty container.
+ *
+ * @public
+ * @memberof StrikeOutAnnotationElement
+ * @returns {HTMLSectionElement}
+ */
+ render: function StrikeOutAnnotationElement_render() {
+ this.container.className = 'strikeoutAnnotation';
+
+ if (!this.data.hasPopup) {
+ this._createPopup(this.container, null, this.data);
+ }
+
+ return this.container;
+ }
+ });
+
+ return StrikeOutAnnotationElement;
+})();
+
+/**
+ * @class
+ * @alias FileAttachmentAnnotationElement
+ */
+var FileAttachmentAnnotationElement = (
+ function FileAttachmentAnnotationElementClosure() {
+ function FileAttachmentAnnotationElement(parameters) {
+ AnnotationElement.call(this, parameters, true);
+
+ this.filename = getFilenameFromUrl(parameters.data.file.filename);
+ this.content = parameters.data.file.content;
+ }
+
+ Util.inherit(FileAttachmentAnnotationElement, AnnotationElement, {
+ /**
+ * Render the file attachment annotation's HTML element in the empty
+ * container.
+ *
+ * @public
+ * @memberof FileAttachmentAnnotationElement
+ * @returns {HTMLSectionElement}
+ */
+ render: function FileAttachmentAnnotationElement_render() {
+ this.container.className = 'fileAttachmentAnnotation';
+
+ var trigger = document.createElement('div');
+ trigger.style.height = this.container.style.height;
+ trigger.style.width = this.container.style.width;
+ trigger.addEventListener('dblclick', this._download.bind(this));
+
+ if (!this.data.hasPopup && (this.data.title || this.data.contents)) {
+ this._createPopup(this.container, trigger, this.data);
+ }
+
+ this.container.appendChild(trigger);
+ return this.container;
+ },
+
+ /**
+ * Download the file attachment associated with this annotation.
+ *
+ * @private
+ * @memberof FileAttachmentAnnotationElement
+ */
+ _download: function FileAttachmentAnnotationElement_download() {
+ if (!this.downloadManager) {
+ warn('Download cannot be started due to unavailable download manager');
+ return;
+ }
+ this.downloadManager.downloadData(this.content, this.filename, '');
+ }
+ });
+
+ return FileAttachmentAnnotationElement;
+})();
+
+/**
+ * @typedef {Object} AnnotationLayerParameters
+ * @property {PageViewport} viewport
+ * @property {HTMLDivElement} div
+ * @property {Array} annotations
+ * @property {PDFPage} page
+ * @property {IPDFLinkService} linkService
+ * @property {string} imageResourcesPath
+ * @property {boolean} renderInteractiveForms
+ */
+
+/**
+ * @class
+ * @alias AnnotationLayer
+ */
+var AnnotationLayer = (function AnnotationLayerClosure() {
+ return {
+ /**
+ * Render a new annotation layer with all annotation elements.
+ *
+ * @public
+ * @param {AnnotationLayerParameters} parameters
+ * @memberof AnnotationLayer
+ */
+ render: function AnnotationLayer_render(parameters) {
+ var annotationElementFactory = new AnnotationElementFactory();
+
+ for (var i = 0, ii = parameters.annotations.length; i < ii; i++) {
+ var data = parameters.annotations[i];
+ if (!data) {
+ continue;
+ }
+
+ var properties = {
+ data: data,
+ layer: parameters.div,
+ page: parameters.page,
+ viewport: parameters.viewport,
+ linkService: parameters.linkService,
+ downloadManager: parameters.downloadManager,
+ imageResourcesPath: parameters.imageResourcesPath ||
+ getDefaultSetting('imageResourcesPath'),
+ renderInteractiveForms: parameters.renderInteractiveForms || false,
+ };
+ var element = annotationElementFactory.create(properties);
+ if (element.isRenderable) {
+ parameters.div.appendChild(element.render());
+ }
+ }
+ },
+
+ /**
+ * Update the annotation elements on existing annotation layer.
+ *
+ * @public
+ * @param {AnnotationLayerParameters} parameters
+ * @memberof AnnotationLayer
+ */
+ update: function AnnotationLayer_update(parameters) {
+ for (var i = 0, ii = parameters.annotations.length; i < ii; i++) {
+ var data = parameters.annotations[i];
+ var element = parameters.div.querySelector(
+ '[data-annotation-id="' + data.id + '"]');
+ if (element) {
+ CustomStyle.setProp('transform', element,
+ 'matrix(' + parameters.viewport.transform.join(',') + ')');
+ }
+ }
+ parameters.div.removeAttribute('hidden');
+ }
+ };
+})();
+
+exports.AnnotationLayer = AnnotationLayer;
+}));
+
+
+(function (root, factory) {
+ {
+ factory((root.pdfjsDisplayTextLayer = {}), root.pdfjsSharedUtil,
+ root.pdfjsDisplayDOMUtils);
+ }
+}(this, function (exports, sharedUtil, displayDOMUtils) {
+
+var Util = sharedUtil.Util;
+var createPromiseCapability = sharedUtil.createPromiseCapability;
+var CustomStyle = displayDOMUtils.CustomStyle;
+var getDefaultSetting = displayDOMUtils.getDefaultSetting;
+
+/**
+ * Text layer render parameters.
+ *
+ * @typedef {Object} TextLayerRenderParameters
+ * @property {TextContent} textContent - Text content to render (the object is
+ * returned by the page's getTextContent() method).
+ * @property {HTMLElement} container - HTML element that will contain text runs.
+ * @property {PageViewport} viewport - The target viewport to properly
+ * layout the text runs.
+ * @property {Array} textDivs - (optional) HTML elements that are correspond
+ * the text items of the textContent input. This is output and shall be
+ * initially be set to empty array.
+ * @property {number} timeout - (optional) Delay in milliseconds before
+ * rendering of the text runs occurs.
+ * @property {boolean} enhanceTextSelection - (optional) Whether to turn on the
+ * text selection enhancement.
+ */
+var renderTextLayer = (function renderTextLayerClosure() {
+ var MAX_TEXT_DIVS_TO_RENDER = 100000;
+
+ var NonWhitespaceRegexp = /\S/;
+
+ function isAllWhitespace(str) {
+ return !NonWhitespaceRegexp.test(str);
+ }
+
+ // Text layers may contain many thousand div's, and using `styleBuf` avoids
+ // creating many intermediate strings when building their 'style' properties.
+ var styleBuf = ['left: ', 0, 'px; top: ', 0, 'px; font-size: ', 0,
+ 'px; font-family: ', '', ';'];
+
+ function appendText(task, geom, styles) {
+ // Initialize all used properties to keep the caches monomorphic.
+ var textDiv = document.createElement('div');
+ var textDivProperties = {
+ style: null,
+ angle: 0,
+ canvasWidth: 0,
+ isWhitespace: false,
+ originalTransform: null,
+ paddingBottom: 0,
+ paddingLeft: 0,
+ paddingRight: 0,
+ paddingTop: 0,
+ scale: 1,
+ };
+
+ task._textDivs.push(textDiv);
+ if (isAllWhitespace(geom.str)) {
+ textDivProperties.isWhitespace = true;
+ task._textDivProperties.set(textDiv, textDivProperties);
+ return;
+ }
+
+ var tx = Util.transform(task._viewport.transform, geom.transform);
+ var angle = Math.atan2(tx[1], tx[0]);
+ var style = styles[geom.fontName];
+ if (style.vertical) {
+ angle += Math.PI / 2;
+ }
+ var fontHeight = Math.sqrt((tx[2] * tx[2]) + (tx[3] * tx[3]));
+ var fontAscent = fontHeight;
+ if (style.ascent) {
+ fontAscent = style.ascent * fontAscent;
+ } else if (style.descent) {
+ fontAscent = (1 + style.descent) * fontAscent;
+ }
+
+ var left;
+ var top;
+ if (angle === 0) {
+ left = tx[4];
+ top = tx[5] - fontAscent;
+ } else {
+ left = tx[4] + (fontAscent * Math.sin(angle));
+ top = tx[5] - (fontAscent * Math.cos(angle));
+ }
+ styleBuf[1] = left;
+ styleBuf[3] = top;
+ styleBuf[5] = fontHeight;
+ styleBuf[7] = style.fontFamily;
+ textDivProperties.style = styleBuf.join('');
+ textDiv.setAttribute('style', textDivProperties.style);
+
+ textDiv.textContent = geom.str;
+ // |fontName| is only used by the Font Inspector. This test will succeed
+ // when e.g. the Font Inspector is off but the Stepper is on, but it's
+ // not worth the effort to do a more accurate test. We only use `dataset`
+ // here to make the font name available for the debugger.
+ if (getDefaultSetting('pdfBug')) {
+ textDiv.dataset.fontName = geom.fontName;
+ }
+ if (angle !== 0) {
+ textDivProperties.angle = angle * (180 / Math.PI);
+ }
+ // We don't bother scaling single-char text divs, because it has very
+ // little effect on text highlighting. This makes scrolling on docs with
+ // lots of such divs a lot faster.
+ if (geom.str.length > 1) {
+ if (style.vertical) {
+ textDivProperties.canvasWidth = geom.height * task._viewport.scale;
+ } else {
+ textDivProperties.canvasWidth = geom.width * task._viewport.scale;
+ }
+ }
+ task._textDivProperties.set(textDiv, textDivProperties);
+
+ if (task._enhanceTextSelection) {
+ var angleCos = 1, angleSin = 0;
+ if (angle !== 0) {
+ angleCos = Math.cos(angle);
+ angleSin = Math.sin(angle);
+ }
+ var divWidth = (style.vertical ? geom.height : geom.width) *
+ task._viewport.scale;
+ var divHeight = fontHeight;
+
+ var m, b;
+ if (angle !== 0) {
+ m = [angleCos, angleSin, -angleSin, angleCos, left, top];
+ b = Util.getAxialAlignedBoundingBox([0, 0, divWidth, divHeight], m);
+ } else {
+ b = [left, top, left + divWidth, top + divHeight];
+ }
+
+ task._bounds.push({
+ left: b[0],
+ top: b[1],
+ right: b[2],
+ bottom: b[3],
+ div: textDiv,
+ size: [divWidth, divHeight],
+ m: m
+ });
+ }
+ }
+
+ function render(task) {
+ if (task._canceled) {
+ return;
+ }
+ var textLayerFrag = task._container;
+ var textDivs = task._textDivs;
+ var capability = task._capability;
+ var textDivsLength = textDivs.length;
+
+ // No point in rendering many divs as it would make the browser
+ // unusable even after the divs are rendered.
+ if (textDivsLength > MAX_TEXT_DIVS_TO_RENDER) {
+ task._renderingDone = true;
+ capability.resolve();
+ return;
+ }
+
+ var canvas = document.createElement('canvas');
+ canvas.mozOpaque = true;
+ var ctx = canvas.getContext('2d', {alpha: false});
+
+ var lastFontSize;
+ var lastFontFamily;
+ for (var i = 0; i < textDivsLength; i++) {
+ var textDiv = textDivs[i];
+ var textDivProperties = task._textDivProperties.get(textDiv);
+ if (textDivProperties.isWhitespace) {
+ continue;
+ }
+
+ var fontSize = textDiv.style.fontSize;
+ var fontFamily = textDiv.style.fontFamily;
+
+ // Only build font string and set to context if different from last.
+ if (fontSize !== lastFontSize || fontFamily !== lastFontFamily) {
+ ctx.font = fontSize + ' ' + fontFamily;
+ lastFontSize = fontSize;
+ lastFontFamily = fontFamily;
+ }
+
+ var width = ctx.measureText(textDiv.textContent).width;
+ textLayerFrag.appendChild(textDiv);
+
+ var transform = '';
+ if (textDivProperties.canvasWidth !== 0 && width > 0) {
+ textDivProperties.scale = textDivProperties.canvasWidth / width;
+ transform = 'scaleX(' + textDivProperties.scale + ')';
+ }
+ if (textDivProperties.angle !== 0) {
+ transform = 'rotate(' + textDivProperties.angle + 'deg) ' + transform;
+ }
+ if (transform !== '') {
+ textDivProperties.originalTransform = transform;
+ CustomStyle.setProp('transform', textDiv, transform);
+ }
+ task._textDivProperties.set(textDiv, textDivProperties);
+ }
+ task._renderingDone = true;
+ capability.resolve();
+ }
+
+ function expand(task) {
+ var bounds = task._bounds;
+ var viewport = task._viewport;
+
+ var expanded = expandBounds(viewport.width, viewport.height, bounds);
+ for (var i = 0; i < expanded.length; i++) {
+ var div = bounds[i].div;
+ var divProperties = task._textDivProperties.get(div);
+ if (divProperties.angle === 0) {
+ divProperties.paddingLeft = bounds[i].left - expanded[i].left;
+ divProperties.paddingTop = bounds[i].top - expanded[i].top;
+ divProperties.paddingRight = expanded[i].right - bounds[i].right;
+ divProperties.paddingBottom = expanded[i].bottom - bounds[i].bottom;
+ task._textDivProperties.set(div, divProperties);
+ continue;
+ }
+ // Box is rotated -- trying to find padding so rotated div will not
+ // exceed its expanded bounds.
+ var e = expanded[i], b = bounds[i];
+ var m = b.m, c = m[0], s = m[1];
+ // Finding intersections with expanded box.
+ var points = [[0, 0], [0, b.size[1]], [b.size[0], 0], b.size];
+ var ts = new Float64Array(64);
+ points.forEach(function (p, i) {
+ var t = Util.applyTransform(p, m);
+ ts[i + 0] = c && (e.left - t[0]) / c;
+ ts[i + 4] = s && (e.top - t[1]) / s;
+ ts[i + 8] = c && (e.right - t[0]) / c;
+ ts[i + 12] = s && (e.bottom - t[1]) / s;
+
+ ts[i + 16] = s && (e.left - t[0]) / -s;
+ ts[i + 20] = c && (e.top - t[1]) / c;
+ ts[i + 24] = s && (e.right - t[0]) / -s;
+ ts[i + 28] = c && (e.bottom - t[1]) / c;
+
+ ts[i + 32] = c && (e.left - t[0]) / -c;
+ ts[i + 36] = s && (e.top - t[1]) / -s;
+ ts[i + 40] = c && (e.right - t[0]) / -c;
+ ts[i + 44] = s && (e.bottom - t[1]) / -s;
+
+ ts[i + 48] = s && (e.left - t[0]) / s;
+ ts[i + 52] = c && (e.top - t[1]) / -c;
+ ts[i + 56] = s && (e.right - t[0]) / s;
+ ts[i + 60] = c && (e.bottom - t[1]) / -c;
+ });
+ var findPositiveMin = function (ts, offset, count) {
+ var result = 0;
+ for (var i = 0; i < count; i++) {
+ var t = ts[offset++];
+ if (t > 0) {
+ result = result ? Math.min(t, result) : t;
+ }
+ }
+ return result;
+ };
+ // Not based on math, but to simplify calculations, using cos and sin
+ // absolute values to not exceed the box (it can but insignificantly).
+ var boxScale = 1 + Math.min(Math.abs(c), Math.abs(s));
+ divProperties.paddingLeft = findPositiveMin(ts, 32, 16) / boxScale;
+ divProperties.paddingTop = findPositiveMin(ts, 48, 16) / boxScale;
+ divProperties.paddingRight = findPositiveMin(ts, 0, 16) / boxScale;
+ divProperties.paddingBottom = findPositiveMin(ts, 16, 16) / boxScale;
+ task._textDivProperties.set(div, divProperties);
+ }
+ }
+
+ function expandBounds(width, height, boxes) {
+ var bounds = boxes.map(function (box, i) {
+ return {
+ x1: box.left,
+ y1: box.top,
+ x2: box.right,
+ y2: box.bottom,
+ index: i,
+ x1New: undefined,
+ x2New: undefined
+ };
+ });
+ expandBoundsLTR(width, bounds);
+ var expanded = new Array(boxes.length);
+ bounds.forEach(function (b) {
+ var i = b.index;
+ expanded[i] = {
+ left: b.x1New,
+ top: 0,
+ right: b.x2New,
+ bottom: 0
+ };
+ });
+
+ // Rotating on 90 degrees and extending extended boxes. Reusing the bounds
+ // array and objects.
+ boxes.map(function (box, i) {
+ var e = expanded[i], b = bounds[i];
+ b.x1 = box.top;
+ b.y1 = width - e.right;
+ b.x2 = box.bottom;
+ b.y2 = width - e.left;
+ b.index = i;
+ b.x1New = undefined;
+ b.x2New = undefined;
+ });
+ expandBoundsLTR(height, bounds);
+
+ bounds.forEach(function (b) {
+ var i = b.index;
+ expanded[i].top = b.x1New;
+ expanded[i].bottom = b.x2New;
+ });
+ return expanded;
+ }
+
+ function expandBoundsLTR(width, bounds) {
+ // Sorting by x1 coordinate and walk by the bounds in the same order.
+ bounds.sort(function (a, b) { return a.x1 - b.x1 || a.index - b.index; });
+
+ // First we see on the horizon is a fake boundary.
+ var fakeBoundary = {
+ x1: -Infinity,
+ y1: -Infinity,
+ x2: 0,
+ y2: Infinity,
+ index: -1,
+ x1New: 0,
+ x2New: 0
+ };
+ var horizon = [{
+ start: -Infinity,
+ end: Infinity,
+ boundary: fakeBoundary
+ }];
+
+ bounds.forEach(function (boundary) {
+ // Searching for the affected part of horizon.
+ // TODO red-black tree or simple binary search
+ var i = 0;
+ while (i < horizon.length && horizon[i].end <= boundary.y1) {
+ i++;
+ }
+ var j = horizon.length - 1;
+ while(j >= 0 && horizon[j].start >= boundary.y2) {
+ j--;
+ }
+
+ var horizonPart, affectedBoundary;
+ var q, k, maxXNew = -Infinity;
+ for (q = i; q <= j; q++) {
+ horizonPart = horizon[q];
+ affectedBoundary = horizonPart.boundary;
+ var xNew;
+ if (affectedBoundary.x2 > boundary.x1) {
+ // In the middle of the previous element, new x shall be at the
+ // boundary start. Extending if further if the affected bondary
+ // placed on top of the current one.
+ xNew = affectedBoundary.index > boundary.index ?
+ affectedBoundary.x1New : boundary.x1;
+ } else if (affectedBoundary.x2New === undefined) {
+ // We have some space in between, new x in middle will be a fair
+ // choice.
+ xNew = (affectedBoundary.x2 + boundary.x1) / 2;
+ } else {
+ // Affected boundary has x2new set, using it as new x.
+ xNew = affectedBoundary.x2New;
+ }
+ if (xNew > maxXNew) {
+ maxXNew = xNew;
+ }
+ }
+
+ // Set new x1 for current boundary.
+ boundary.x1New = maxXNew;
+
+ // Adjusts new x2 for the affected boundaries.
+ for (q = i; q <= j; q++) {
+ horizonPart = horizon[q];
+ affectedBoundary = horizonPart.boundary;
+ if (affectedBoundary.x2New === undefined) {
+ // Was not set yet, choosing new x if possible.
+ if (affectedBoundary.x2 > boundary.x1) {
+ // Current and affected boundaries intersect. If affected boundary
+ // is placed on top of the current, shrinking the affected.
+ if (affectedBoundary.index > boundary.index) {
+ affectedBoundary.x2New = affectedBoundary.x2;
+ }
+ } else {
+ affectedBoundary.x2New = maxXNew;
+ }
+ } else if (affectedBoundary.x2New > maxXNew) {
+ // Affected boundary is touching new x, pushing it back.
+ affectedBoundary.x2New = Math.max(maxXNew, affectedBoundary.x2);
+ }
+ }
+
+ // Fixing the horizon.
+ var changedHorizon = [], lastBoundary = null;
+ for (q = i; q <= j; q++) {
+ horizonPart = horizon[q];
+ affectedBoundary = horizonPart.boundary;
+ // Checking which boundary will be visible.
+ var useBoundary = affectedBoundary.x2 > boundary.x2 ?
+ affectedBoundary : boundary;
+ if (lastBoundary === useBoundary) {
+ // Merging with previous.
+ changedHorizon[changedHorizon.length - 1].end = horizonPart.end;
+ } else {
+ changedHorizon.push({
+ start: horizonPart.start,
+ end: horizonPart.end,
+ boundary: useBoundary
+ });
+ lastBoundary = useBoundary;
+ }
+ }
+ if (horizon[i].start < boundary.y1) {
+ changedHorizon[0].start = boundary.y1;
+ changedHorizon.unshift({
+ start: horizon[i].start,
+ end: boundary.y1,
+ boundary: horizon[i].boundary
+ });
+ }
+ if (boundary.y2 < horizon[j].end) {
+ changedHorizon[changedHorizon.length - 1].end = boundary.y2;
+ changedHorizon.push({
+ start: boundary.y2,
+ end: horizon[j].end,
+ boundary: horizon[j].boundary
+ });
+ }
+
+ // Set x2 new of boundary that is no longer visible (see overlapping case
+ // above).
+ // TODO more efficient, e.g. via reference counting.
+ for (q = i; q <= j; q++) {
+ horizonPart = horizon[q];
+ affectedBoundary = horizonPart.boundary;
+ if (affectedBoundary.x2New !== undefined) {
+ continue;
+ }
+ var used = false;
+ for (k = i - 1; !used && k >= 0 &&
+ horizon[k].start >= affectedBoundary.y1; k--) {
+ used = horizon[k].boundary === affectedBoundary;
+ }
+ for (k = j + 1; !used && k < horizon.length &&
+ horizon[k].end <= affectedBoundary.y2; k++) {
+ used = horizon[k].boundary === affectedBoundary;
+ }
+ for (k = 0; !used && k < changedHorizon.length; k++) {
+ used = changedHorizon[k].boundary === affectedBoundary;
+ }
+ if (!used) {
+ affectedBoundary.x2New = maxXNew;
+ }
+ }
+
+ Array.prototype.splice.apply(horizon,
+ [i, j - i + 1].concat(changedHorizon));
+ });
+
+ // Set new x2 for all unset boundaries.
+ horizon.forEach(function (horizonPart) {
+ var affectedBoundary = horizonPart.boundary;
+ if (affectedBoundary.x2New === undefined) {
+ affectedBoundary.x2New = Math.max(width, affectedBoundary.x2);
+ }
+ });
+ }
+
+ /**
+ * Text layer rendering task.
+ *
+ * @param {TextContent} textContent
+ * @param {HTMLElement} container
+ * @param {PageViewport} viewport
+ * @param {Array} textDivs
+ * @param {boolean} enhanceTextSelection
+ * @private
+ */
+ function TextLayerRenderTask(textContent, container, viewport, textDivs,
+ enhanceTextSelection) {
+ this._textContent = textContent;
+ this._container = container;
+ this._viewport = viewport;
+ this._textDivs = textDivs || [];
+ this._textDivProperties = new WeakMap();
+ this._renderingDone = false;
+ this._canceled = false;
+ this._capability = createPromiseCapability();
+ this._renderTimer = null;
+ this._bounds = [];
+ this._enhanceTextSelection = !!enhanceTextSelection;
+ }
+ TextLayerRenderTask.prototype = {
+ get promise() {
+ return this._capability.promise;
+ },
+
+ cancel: function TextLayer_cancel() {
+ this._canceled = true;
+ if (this._renderTimer !== null) {
+ clearTimeout(this._renderTimer);
+ this._renderTimer = null;
+ }
+ this._capability.reject('canceled');
+ },
+
+ _render: function TextLayer_render(timeout) {
+ var textItems = this._textContent.items;
+ var textStyles = this._textContent.styles;
+ for (var i = 0, len = textItems.length; i < len; i++) {
+ appendText(this, textItems[i], textStyles);
+ }
+
+ if (!timeout) { // Render right away
+ render(this);
+ } else { // Schedule
+ var self = this;
+ this._renderTimer = setTimeout(function() {
+ render(self);
+ self._renderTimer = null;
+ }, timeout);
+ }
+ },
+
+ expandTextDivs: function TextLayer_expandTextDivs(expandDivs) {
+ if (!this._enhanceTextSelection || !this._renderingDone) {
+ return;
+ }
+ if (this._bounds !== null) {
+ expand(this);
+ this._bounds = null;
+ }
+
+ for (var i = 0, ii = this._textDivs.length; i < ii; i++) {
+ var div = this._textDivs[i];
+ var divProperties = this._textDivProperties.get(div);
+
+ if (divProperties.isWhitespace) {
+ continue;
+ }
+ if (expandDivs) {
+ var transform = '', padding = '';
+
+ if (divProperties.scale !== 1) {
+ transform = 'scaleX(' + divProperties.scale + ')';
+ }
+ if (divProperties.angle !== 0) {
+ transform = 'rotate(' + divProperties.angle + 'deg) ' + transform;
+ }
+ if (divProperties.paddingLeft !== 0) {
+ padding += ' padding-left: ' +
+ (divProperties.paddingLeft / divProperties.scale) + 'px;';
+ transform += ' translateX(' +
+ (-divProperties.paddingLeft / divProperties.scale) + 'px)';
+ }
+ if (divProperties.paddingTop !== 0) {
+ padding += ' padding-top: ' + divProperties.paddingTop + 'px;';
+ transform += ' translateY(' + (-divProperties.paddingTop) + 'px)';
+ }
+ if (divProperties.paddingRight !== 0) {
+ padding += ' padding-right: ' +
+ (divProperties.paddingRight / divProperties.scale) + 'px;';
+ }
+ if (divProperties.paddingBottom !== 0) {
+ padding += ' padding-bottom: ' +
+ divProperties.paddingBottom + 'px;';
+ }
+
+ if (padding !== '') {
+ div.setAttribute('style', divProperties.style + padding);
+ }
+ if (transform !== '') {
+ CustomStyle.setProp('transform', div, transform);
+ }
+ } else {
+ div.style.padding = 0;
+ CustomStyle.setProp('transform', div,
+ divProperties.originalTransform || '');
+ }
+ }
+ },
+ };
+
+ /**
+ * Starts rendering of the text layer.
+ *
+ * @param {TextLayerRenderParameters} renderParameters
+ * @returns {TextLayerRenderTask}
+ */
+ function renderTextLayer(renderParameters) {
+ var task = new TextLayerRenderTask(renderParameters.textContent,
+ renderParameters.container,
+ renderParameters.viewport,
+ renderParameters.textDivs,
+ renderParameters.enhanceTextSelection);
+ task._render(renderParameters.timeout);
+ return task;
+ }
+
+ return renderTextLayer;
+})();
+
+exports.renderTextLayer = renderTextLayer;
+}));
+
+
+(function (root, factory) {
+ {
+ factory((root.pdfjsDisplayWebGL = {}), root.pdfjsSharedUtil,
+ root.pdfjsDisplayDOMUtils);
+ }
+}(this, function (exports, sharedUtil, displayDOMUtils) {
+
+var shadow = sharedUtil.shadow;
+var getDefaultSetting = displayDOMUtils.getDefaultSetting;
+
+var WebGLUtils = (function WebGLUtilsClosure() {
+ function loadShader(gl, code, shaderType) {
+ var shader = gl.createShader(shaderType);
+ gl.shaderSource(shader, code);
+ gl.compileShader(shader);
+ var compiled = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
+ if (!compiled) {
+ var errorMsg = gl.getShaderInfoLog(shader);
+ throw new Error('Error during shader compilation: ' + errorMsg);
+ }
+ return shader;
+ }
+ function createVertexShader(gl, code) {
+ return loadShader(gl, code, gl.VERTEX_SHADER);
+ }
+ function createFragmentShader(gl, code) {
+ return loadShader(gl, code, gl.FRAGMENT_SHADER);
+ }
+ function createProgram(gl, shaders) {
+ var program = gl.createProgram();
+ for (var i = 0, ii = shaders.length; i < ii; ++i) {
+ gl.attachShader(program, shaders[i]);
+ }
+ gl.linkProgram(program);
+ var linked = gl.getProgramParameter(program, gl.LINK_STATUS);
+ if (!linked) {
+ var errorMsg = gl.getProgramInfoLog(program);
+ throw new Error('Error during program linking: ' + errorMsg);
+ }
+ return program;
+ }
+ function createTexture(gl, image, textureId) {
+ gl.activeTexture(textureId);
+ var texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+
+ // Set the parameters so we can render any size image.
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+
+ // Upload the image into the texture.
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
+ return texture;
+ }
+
+ var currentGL, currentCanvas;
+ function generateGL() {
+ if (currentGL) {
+ return;
+ }
+ currentCanvas = document.createElement('canvas');
+ currentGL = currentCanvas.getContext('webgl',
+ { premultipliedalpha: false });
+ }
+
+ var smaskVertexShaderCode = '\
+ attribute vec2 a_position; \
+ attribute vec2 a_texCoord; \
+ \
+ uniform vec2 u_resolution; \
+ \
+ varying vec2 v_texCoord; \
+ \
+ void main() { \
+ vec2 clipSpace = (a_position / u_resolution) * 2.0 - 1.0; \
+ gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1); \
+ \
+ v_texCoord = a_texCoord; \
+ } ';
+
+ var smaskFragmentShaderCode = '\
+ precision mediump float; \
+ \
+ uniform vec4 u_backdrop; \
+ uniform int u_subtype; \
+ uniform sampler2D u_image; \
+ uniform sampler2D u_mask; \
+ \
+ varying vec2 v_texCoord; \
+ \
+ void main() { \
+ vec4 imageColor = texture2D(u_image, v_texCoord); \
+ vec4 maskColor = texture2D(u_mask, v_texCoord); \
+ if (u_backdrop.a > 0.0) { \
+ maskColor.rgb = maskColor.rgb * maskColor.a + \
+ u_backdrop.rgb * (1.0 - maskColor.a); \
+ } \
+ float lum; \
+ if (u_subtype == 0) { \
+ lum = maskColor.a; \
+ } else { \
+ lum = maskColor.r * 0.3 + maskColor.g * 0.59 + \
+ maskColor.b * 0.11; \
+ } \
+ imageColor.a *= lum; \
+ imageColor.rgb *= imageColor.a; \
+ gl_FragColor = imageColor; \
+ } ';
+
+ var smaskCache = null;
+
+ function initSmaskGL() {
+ var canvas, gl;
+
+ generateGL();
+ canvas = currentCanvas;
+ currentCanvas = null;
+ gl = currentGL;
+ currentGL = null;
+
+ // setup a GLSL program
+ var vertexShader = createVertexShader(gl, smaskVertexShaderCode);
+ var fragmentShader = createFragmentShader(gl, smaskFragmentShaderCode);
+ var program = createProgram(gl, [vertexShader, fragmentShader]);
+ gl.useProgram(program);
+
+ var cache = {};
+ cache.gl = gl;
+ cache.canvas = canvas;
+ cache.resolutionLocation = gl.getUniformLocation(program, 'u_resolution');
+ cache.positionLocation = gl.getAttribLocation(program, 'a_position');
+ cache.backdropLocation = gl.getUniformLocation(program, 'u_backdrop');
+ cache.subtypeLocation = gl.getUniformLocation(program, 'u_subtype');
+
+ var texCoordLocation = gl.getAttribLocation(program, 'a_texCoord');
+ var texLayerLocation = gl.getUniformLocation(program, 'u_image');
+ var texMaskLocation = gl.getUniformLocation(program, 'u_mask');
+
+ // provide texture coordinates for the rectangle.
+ var texCoordBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, texCoordBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
+ 0.0, 0.0,
+ 1.0, 0.0,
+ 0.0, 1.0,
+ 0.0, 1.0,
+ 1.0, 0.0,
+ 1.0, 1.0]), gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(texCoordLocation);
+ gl.vertexAttribPointer(texCoordLocation, 2, gl.FLOAT, false, 0, 0);
+
+ gl.uniform1i(texLayerLocation, 0);
+ gl.uniform1i(texMaskLocation, 1);
+
+ smaskCache = cache;
+ }
+
+ function composeSMask(layer, mask, properties) {
+ var width = layer.width, height = layer.height;
+
+ if (!smaskCache) {
+ initSmaskGL();
+ }
+ var cache = smaskCache,canvas = cache.canvas, gl = cache.gl;
+ canvas.width = width;
+ canvas.height = height;
+ gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
+ gl.uniform2f(cache.resolutionLocation, width, height);
+
+ if (properties.backdrop) {
+ gl.uniform4f(cache.resolutionLocation, properties.backdrop[0],
+ properties.backdrop[1], properties.backdrop[2], 1);
+ } else {
+ gl.uniform4f(cache.resolutionLocation, 0, 0, 0, 0);
+ }
+ gl.uniform1i(cache.subtypeLocation,
+ properties.subtype === 'Luminosity' ? 1 : 0);
+
+ // Create a textures
+ var texture = createTexture(gl, layer, gl.TEXTURE0);
+ var maskTexture = createTexture(gl, mask, gl.TEXTURE1);
+
+
+ // Create a buffer and put a single clipspace rectangle in
+ // it (2 triangles)
+ var buffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
+ 0, 0,
+ width, 0,
+ 0, height,
+ 0, height,
+ width, 0,
+ width, height]), gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(cache.positionLocation);
+ gl.vertexAttribPointer(cache.positionLocation, 2, gl.FLOAT, false, 0, 0);
+
+ // draw
+ gl.clearColor(0, 0, 0, 0);
+ gl.enable(gl.BLEND);
+ gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+
+ gl.flush();
+
+ gl.deleteTexture(texture);
+ gl.deleteTexture(maskTexture);
+ gl.deleteBuffer(buffer);
+
+ return canvas;
+ }
+
+ var figuresVertexShaderCode = '\
+ attribute vec2 a_position; \
+ attribute vec3 a_color; \
+ \
+ uniform vec2 u_resolution; \
+ uniform vec2 u_scale; \
+ uniform vec2 u_offset; \
+ \
+ varying vec4 v_color; \
+ \
+ void main() { \
+ vec2 position = (a_position + u_offset) * u_scale; \
+ vec2 clipSpace = (position / u_resolution) * 2.0 - 1.0; \
+ gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1); \
+ \
+ v_color = vec4(a_color / 255.0, 1.0); \
+ } ';
+
+ var figuresFragmentShaderCode = '\
+ precision mediump float; \
+ \
+ varying vec4 v_color; \
+ \
+ void main() { \
+ gl_FragColor = v_color; \
+ } ';
+
+ var figuresCache = null;
+
+ function initFiguresGL() {
+ var canvas, gl;
+
+ generateGL();
+ canvas = currentCanvas;
+ currentCanvas = null;
+ gl = currentGL;
+ currentGL = null;
+
+ // setup a GLSL program
+ var vertexShader = createVertexShader(gl, figuresVertexShaderCode);
+ var fragmentShader = createFragmentShader(gl, figuresFragmentShaderCode);
+ var program = createProgram(gl, [vertexShader, fragmentShader]);
+ gl.useProgram(program);
+
+ var cache = {};
+ cache.gl = gl;
+ cache.canvas = canvas;
+ cache.resolutionLocation = gl.getUniformLocation(program, 'u_resolution');
+ cache.scaleLocation = gl.getUniformLocation(program, 'u_scale');
+ cache.offsetLocation = gl.getUniformLocation(program, 'u_offset');
+ cache.positionLocation = gl.getAttribLocation(program, 'a_position');
+ cache.colorLocation = gl.getAttribLocation(program, 'a_color');
+
+ figuresCache = cache;
+ }
+
+ function drawFigures(width, height, backgroundColor, figures, context) {
+ if (!figuresCache) {
+ initFiguresGL();
+ }
+ var cache = figuresCache, canvas = cache.canvas, gl = cache.gl;
+
+ canvas.width = width;
+ canvas.height = height;
+ gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
+ gl.uniform2f(cache.resolutionLocation, width, height);
+
+ // count triangle points
+ var count = 0;
+ var i, ii, rows;
+ for (i = 0, ii = figures.length; i < ii; i++) {
+ switch (figures[i].type) {
+ case 'lattice':
+ rows = (figures[i].coords.length / figures[i].verticesPerRow) | 0;
+ count += (rows - 1) * (figures[i].verticesPerRow - 1) * 6;
+ break;
+ case 'triangles':
+ count += figures[i].coords.length;
+ break;
+ }
+ }
+ // transfer data
+ var coords = new Float32Array(count * 2);
+ var colors = new Uint8Array(count * 3);
+ var coordsMap = context.coords, colorsMap = context.colors;
+ var pIndex = 0, cIndex = 0;
+ for (i = 0, ii = figures.length; i < ii; i++) {
+ var figure = figures[i], ps = figure.coords, cs = figure.colors;
+ switch (figure.type) {
+ case 'lattice':
+ var cols = figure.verticesPerRow;
+ rows = (ps.length / cols) | 0;
+ for (var row = 1; row < rows; row++) {
+ var offset = row * cols + 1;
+ for (var col = 1; col < cols; col++, offset++) {
+ coords[pIndex] = coordsMap[ps[offset - cols - 1]];
+ coords[pIndex + 1] = coordsMap[ps[offset - cols - 1] + 1];
+ coords[pIndex + 2] = coordsMap[ps[offset - cols]];
+ coords[pIndex + 3] = coordsMap[ps[offset - cols] + 1];
+ coords[pIndex + 4] = coordsMap[ps[offset - 1]];
+ coords[pIndex + 5] = coordsMap[ps[offset - 1] + 1];
+ colors[cIndex] = colorsMap[cs[offset - cols - 1]];
+ colors[cIndex + 1] = colorsMap[cs[offset - cols - 1] + 1];
+ colors[cIndex + 2] = colorsMap[cs[offset - cols - 1] + 2];
+ colors[cIndex + 3] = colorsMap[cs[offset - cols]];
+ colors[cIndex + 4] = colorsMap[cs[offset - cols] + 1];
+ colors[cIndex + 5] = colorsMap[cs[offset - cols] + 2];
+ colors[cIndex + 6] = colorsMap[cs[offset - 1]];
+ colors[cIndex + 7] = colorsMap[cs[offset - 1] + 1];
+ colors[cIndex + 8] = colorsMap[cs[offset - 1] + 2];
+
+ coords[pIndex + 6] = coords[pIndex + 2];
+ coords[pIndex + 7] = coords[pIndex + 3];
+ coords[pIndex + 8] = coords[pIndex + 4];
+ coords[pIndex + 9] = coords[pIndex + 5];
+ coords[pIndex + 10] = coordsMap[ps[offset]];
+ coords[pIndex + 11] = coordsMap[ps[offset] + 1];
+ colors[cIndex + 9] = colors[cIndex + 3];
+ colors[cIndex + 10] = colors[cIndex + 4];
+ colors[cIndex + 11] = colors[cIndex + 5];
+ colors[cIndex + 12] = colors[cIndex + 6];
+ colors[cIndex + 13] = colors[cIndex + 7];
+ colors[cIndex + 14] = colors[cIndex + 8];
+ colors[cIndex + 15] = colorsMap[cs[offset]];
+ colors[cIndex + 16] = colorsMap[cs[offset] + 1];
+ colors[cIndex + 17] = colorsMap[cs[offset] + 2];
+ pIndex += 12;
+ cIndex += 18;
+ }
+ }
+ break;
+ case 'triangles':
+ for (var j = 0, jj = ps.length; j < jj; j++) {
+ coords[pIndex] = coordsMap[ps[j]];
+ coords[pIndex + 1] = coordsMap[ps[j] + 1];
+ colors[cIndex] = colorsMap[cs[j]];
+ colors[cIndex + 1] = colorsMap[cs[j] + 1];
+ colors[cIndex + 2] = colorsMap[cs[j] + 2];
+ pIndex += 2;
+ cIndex += 3;
+ }
+ break;
+ }
+ }
+
+ // draw
+ if (backgroundColor) {
+ gl.clearColor(backgroundColor[0] / 255, backgroundColor[1] / 255,
+ backgroundColor[2] / 255, 1.0);
+ } else {
+ gl.clearColor(0, 0, 0, 0);
+ }
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ var coordsBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, coordsBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, coords, gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(cache.positionLocation);
+ gl.vertexAttribPointer(cache.positionLocation, 2, gl.FLOAT, false, 0, 0);
+
+ var colorsBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, colorsBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, colors, gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(cache.colorLocation);
+ gl.vertexAttribPointer(cache.colorLocation, 3, gl.UNSIGNED_BYTE, false,
+ 0, 0);
+
+ gl.uniform2f(cache.scaleLocation, context.scaleX, context.scaleY);
+ gl.uniform2f(cache.offsetLocation, context.offsetX, context.offsetY);
+
+ gl.drawArrays(gl.TRIANGLES, 0, count);
+
+ gl.flush();
+
+ gl.deleteBuffer(coordsBuffer);
+ gl.deleteBuffer(colorsBuffer);
+
+ return canvas;
+ }
+
+ function cleanup() {
+ if (smaskCache && smaskCache.canvas) {
+ smaskCache.canvas.width = 0;
+ smaskCache.canvas.height = 0;
+ }
+ if (figuresCache && figuresCache.canvas) {
+ figuresCache.canvas.width = 0;
+ figuresCache.canvas.height = 0;
+ }
+ smaskCache = null;
+ figuresCache = null;
+ }
+
+ return {
+ get isEnabled() {
+ if (getDefaultSetting('disableWebGL')) {
+ return false;
+ }
+ var enabled = false;
+ try {
+ generateGL();
+ enabled = !!currentGL;
+ } catch (e) { }
+ return shadow(this, 'isEnabled', enabled);
+ },
+ composeSMask: composeSMask,
+ drawFigures: drawFigures,
+ clear: cleanup
+ };
+})();
+
+exports.WebGLUtils = WebGLUtils;
+}));
+
+
+(function (root, factory) {
+ {
+ factory((root.pdfjsDisplayPatternHelper = {}), root.pdfjsSharedUtil,
+ root.pdfjsDisplayWebGL);
+ }
+}(this, function (exports, sharedUtil, displayWebGL) {
+
+var Util = sharedUtil.Util;
+var info = sharedUtil.info;
+var isArray = sharedUtil.isArray;
+var error = sharedUtil.error;
+var WebGLUtils = displayWebGL.WebGLUtils;
+
+var ShadingIRs = {};
+
+ShadingIRs.RadialAxial = {
+ fromIR: function RadialAxial_fromIR(raw) {
+ var type = raw[1];
+ var colorStops = raw[2];
+ var p0 = raw[3];
+ var p1 = raw[4];
+ var r0 = raw[5];
+ var r1 = raw[6];
+ return {
+ type: 'Pattern',
+ getPattern: function RadialAxial_getPattern(ctx) {
+ var grad;
+ if (type === 'axial') {
+ grad = ctx.createLinearGradient(p0[0], p0[1], p1[0], p1[1]);
+ } else if (type === 'radial') {
+ grad = ctx.createRadialGradient(p0[0], p0[1], r0, p1[0], p1[1], r1);
+ }
+
+ for (var i = 0, ii = colorStops.length; i < ii; ++i) {
+ var c = colorStops[i];
+ grad.addColorStop(c[0], c[1]);
+ }
+ return grad;
+ }
+ };
+ }
+};
+
+var createMeshCanvas = (function createMeshCanvasClosure() {
+ function drawTriangle(data, context, p1, p2, p3, c1, c2, c3) {
+ // Very basic Gouraud-shaded triangle rasterization algorithm.
+ var coords = context.coords, colors = context.colors;
+ var bytes = data.data, rowSize = data.width * 4;
+ var tmp;
+ if (coords[p1 + 1] > coords[p2 + 1]) {
+ tmp = p1; p1 = p2; p2 = tmp; tmp = c1; c1 = c2; c2 = tmp;
+ }
+ 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;
+ }
+ var x1 = (coords[p1] + context.offsetX) * context.scaleX;
+ var y1 = (coords[p1 + 1] + context.offsetY) * context.scaleY;
+ var x2 = (coords[p2] + context.offsetX) * context.scaleX;
+ var y2 = (coords[p2 + 1] + context.offsetY) * context.scaleY;
+ var x3 = (coords[p3] + context.offsetX) * context.scaleX;
+ var y3 = (coords[p3 + 1] + context.offsetY) * context.scaleY;
+ if (y1 >= y3) {
+ return;
+ }
+ var c1r = colors[c1], c1g = colors[c1 + 1], c1b = colors[c1 + 2];
+ var c2r = colors[c2], c2g = colors[c2 + 1], c2b = colors[c2 + 2];
+ var c3r = colors[c3], c3g = colors[c3 + 1], c3b = colors[c3 + 2];
+
+ var minY = Math.round(y1), maxY = Math.round(y3);
+ var xa, car, cag, cab;
+ var xb, cbr, cbg, cbb;
+ var k;
+ for (var y = minY; y <= maxY; y++) {
+ if (y < y2) {
+ k = y < y1 ? 0 : y1 === y2 ? 1 : (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 {
+ k = y > y3 ? 1 : y2 === y3 ? 0 : (y2 - y) / (y2 - y3);
+ xa = x2 - (x2 - x3) * k;
+ car = c2r - (c2r - c3r) * k;
+ cag = c2g - (c2g - c3g) * k;
+ cab = c2b - (c2b - c3b) * k;
+ }
+ k = y < y1 ? 0 : y > y3 ? 1 : (y1 - y) / (y1 - y3);
+ xb = x1 - (x1 - x3) * k;
+ cbr = c1r - (c1r - c3r) * k;
+ cbg = c1g - (c1g - c3g) * k;
+ cbb = c1b - (c1b - c3b) * k;
+ var x1_ = Math.round(Math.min(xa, xb));
+ var x2_ = Math.round(Math.max(xa, xb));
+ var j = rowSize * y + x1_ * 4;
+ for (var x = x1_; x <= x2_; x++) {
+ k = (xa - x) / (xa - xb);
+ k = k < 0 ? 0 : k > 1 ? 1 : k;
+ bytes[j++] = (car - (car - cbr) * k) | 0;
+ bytes[j++] = (cag - (cag - cbg) * k) | 0;
+ bytes[j++] = (cab - (cab - cbb) * k) | 0;
+ bytes[j++] = 255;
+ }
+ }
+ }
+
+ function drawFigure(data, figure, context) {
+ var ps = figure.coords;
+ var cs = figure.colors;
+ var i, ii;
+ switch (figure.type) {
+ case 'lattice':
+ var verticesPerRow = figure.verticesPerRow;
+ var rows = Math.floor(ps.length / verticesPerRow) - 1;
+ var cols = verticesPerRow - 1;
+ for (i = 0; i < rows; i++) {
+ var q = i * verticesPerRow;
+ for (var 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]);
+ }
+ }
+ 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]);
+ }
+ break;
+ default:
+ error('illigal figure');
+ break;
+ }
+ }
+
+ function createMeshCanvas(bounds, combinesScale, coords, colors, figures,
+ backgroundColor, cachedCanvases) {
+ // we will increase scale on some weird factor to let antialiasing take
+ // care of "rough" edges
+ var EXPECTED_SCALE = 1.1;
+ // MAX_PATTERN_SIZE is used to avoid OOM situation.
+ var MAX_PATTERN_SIZE = 3000; // 10in @ 300dpi shall be enough
+ // We need to keep transparent border around our pattern for fill():
+ // createPattern with 'no-repeat' will bleed edges across entire area.
+ var BORDER_SIZE = 2;
+
+ var offsetX = Math.floor(bounds[0]);
+ var offsetY = Math.floor(bounds[1]);
+ var boundsWidth = Math.ceil(bounds[2]) - offsetX;
+ var boundsHeight = Math.ceil(bounds[3]) - offsetY;
+
+ var width = Math.min(Math.ceil(Math.abs(boundsWidth * combinesScale[0] *
+ EXPECTED_SCALE)), MAX_PATTERN_SIZE);
+ var height = Math.min(Math.ceil(Math.abs(boundsHeight * combinesScale[1] *
+ EXPECTED_SCALE)), MAX_PATTERN_SIZE);
+ var scaleX = boundsWidth / width;
+ var scaleY = boundsHeight / height;
+
+ var context = {
+ coords: coords,
+ colors: colors,
+ offsetX: -offsetX,
+ offsetY: -offsetY,
+ scaleX: 1 / scaleX,
+ scaleY: 1 / scaleY
+ };
+
+ var paddedWidth = width + BORDER_SIZE * 2;
+ var paddedHeight = height + BORDER_SIZE * 2;
+
+ var canvas, tmpCanvas, i, ii;
+ if (WebGLUtils.isEnabled) {
+ canvas = WebGLUtils.drawFigures(width, height, backgroundColor,
+ figures, context);
+
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=972126
+ tmpCanvas = cachedCanvases.getCanvas('mesh', paddedWidth, paddedHeight,
+ false);
+ tmpCanvas.context.drawImage(canvas, BORDER_SIZE, BORDER_SIZE);
+ canvas = tmpCanvas.canvas;
+ } else {
+ tmpCanvas = cachedCanvases.getCanvas('mesh', paddedWidth, paddedHeight,
+ false);
+ var tmpCtx = tmpCanvas.context;
+
+ var data = tmpCtx.createImageData(width, height);
+ if (backgroundColor) {
+ var bytes = data.data;
+ for (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;
+ }
+ }
+ for (i = 0; i < figures.length; i++) {
+ drawFigure(data, figures[i], context);
+ }
+ tmpCtx.putImageData(data, BORDER_SIZE, BORDER_SIZE);
+ canvas = tmpCanvas.canvas;
+ }
+
+ return {canvas: canvas,
+ offsetX: offsetX - BORDER_SIZE * scaleX,
+ offsetY: offsetY - BORDER_SIZE * scaleY,
+ scaleX: scaleX, scaleY: scaleY};
+ }
+ return createMeshCanvas;
+})();
+
+ShadingIRs.Mesh = {
+ fromIR: function Mesh_fromIR(raw) {
+ //var type = raw[1];
+ var coords = raw[2];
+ var colors = raw[3];
+ var figures = raw[4];
+ var bounds = raw[5];
+ var matrix = raw[6];
+ //var bbox = raw[7];
+ var background = raw[8];
+ return {
+ type: 'Pattern',
+ getPattern: function Mesh_getPattern(ctx, owner, shadingFill) {
+ var scale;
+ if (shadingFill) {
+ scale = Util.singularValueDecompose2dScale(ctx.mozCurrentTransform);
+ } else {
+ // Obtain scale from matrix and current transformation matrix.
+ scale = Util.singularValueDecompose2dScale(owner.baseTransform);
+ if (matrix) {
+ var matrixScale = Util.singularValueDecompose2dScale(matrix);
+ scale = [scale[0] * matrixScale[0],
+ scale[1] * matrixScale[1]];
+ }
+ }
+
+
+ // Rasterizing on the main thread since sending/queue large canvases
+ // might cause OOM.
+ var temporaryPatternCanvas = createMeshCanvas(bounds, scale, coords,
+ colors, figures, shadingFill ? null : background,
+ owner.cachedCanvases);
+
+ if (!shadingFill) {
+ ctx.setTransform.apply(ctx, owner.baseTransform);
+ if (matrix) {
+ ctx.transform.apply(ctx, matrix);
+ }
+ }
+
+ ctx.translate(temporaryPatternCanvas.offsetX,
+ temporaryPatternCanvas.offsetY);
+ ctx.scale(temporaryPatternCanvas.scaleX,
+ temporaryPatternCanvas.scaleY);
+
+ return ctx.createPattern(temporaryPatternCanvas.canvas, 'no-repeat');
+ }
+ };
+ }
+};
+
+ShadingIRs.Dummy = {
+ fromIR: function Dummy_fromIR() {
+ return {
+ type: 'Pattern',
+ getPattern: function Dummy_fromIR_getPattern() {
+ return 'hotpink';
+ }
+ };
+ }
+};
+
+function getShadingPatternFromIR(raw) {
+ var shadingIR = ShadingIRs[raw[0]];
+ if (!shadingIR) {
+ error('Unknown IR type: ' + raw[0]);
+ }
+ return shadingIR.fromIR(raw);
+}
+
+var TilingPattern = (function TilingPatternClosure() {
+ var PaintType = {
+ COLORED: 1,
+ UNCOLORED: 2
+ };
+
+ var MAX_PATTERN_SIZE = 3000; // 10in @ 300dpi shall be enough
+
+ function TilingPattern(IR, color, ctx, canvasGraphicsFactory, baseTransform) {
+ this.operatorList = IR[2];
+ this.matrix = IR[3] || [1, 0, 0, 1, 0, 0];
+ this.bbox = IR[4];
+ this.xstep = IR[5];
+ this.ystep = IR[6];
+ this.paintType = IR[7];
+ this.tilingType = IR[8];
+ this.color = color;
+ this.canvasGraphicsFactory = canvasGraphicsFactory;
+ this.baseTransform = baseTransform;
+ this.type = 'Pattern';
+ this.ctx = ctx;
+ }
+
+ TilingPattern.prototype = {
+ createPatternCanvas: function TilinPattern_createPatternCanvas(owner) {
+ var operatorList = this.operatorList;
+ var bbox = this.bbox;
+ var xstep = this.xstep;
+ var ystep = this.ystep;
+ var paintType = this.paintType;
+ var tilingType = this.tilingType;
+ var color = this.color;
+ var canvasGraphicsFactory = this.canvasGraphicsFactory;
+
+ info('TilingType: ' + tilingType);
+
+ var x0 = bbox[0], y0 = bbox[1], x1 = bbox[2], y1 = bbox[3];
+
+ var topLeft = [x0, y0];
+ // we want the canvas to be as large as the step size
+ var botRight = [x0 + xstep, y0 + ystep];
+
+ var width = botRight[0] - topLeft[0];
+ var height = botRight[1] - topLeft[1];
+
+ // Obtain scale from matrix and current transformation matrix.
+ var matrixScale = Util.singularValueDecompose2dScale(this.matrix);
+ var curMatrixScale = Util.singularValueDecompose2dScale(
+ this.baseTransform);
+ var combinedScale = [matrixScale[0] * curMatrixScale[0],
+ matrixScale[1] * curMatrixScale[1]];
+
+ // MAX_PATTERN_SIZE is used to avoid OOM situation.
+ // Use width and height values that are as close as possible to the end
+ // result when the pattern is used. Too low value makes the pattern look
+ // blurry. Too large value makes it look too crispy.
+ width = Math.min(Math.ceil(Math.abs(width * combinedScale[0])),
+ MAX_PATTERN_SIZE);
+
+ height = Math.min(Math.ceil(Math.abs(height * combinedScale[1])),
+ MAX_PATTERN_SIZE);
+
+ var tmpCanvas = owner.cachedCanvases.getCanvas('pattern',
+ width, height, true);
+ var tmpCtx = tmpCanvas.context;
+ var graphics = canvasGraphicsFactory.createCanvasGraphics(tmpCtx);
+ graphics.groupLevel = owner.groupLevel;
+
+ this.setFillAndStrokeStyleToContext(tmpCtx, paintType, color);
+
+ this.setScale(width, height, xstep, ystep);
+ this.transformToScale(graphics);
+
+ // transform coordinates to pattern space
+ var tmpTranslate = [1, 0, 0, 1, -topLeft[0], -topLeft[1]];
+ graphics.transform.apply(graphics, tmpTranslate);
+
+ this.clipBbox(graphics, bbox, x0, y0, x1, y1);
+
+ graphics.executeOperatorList(operatorList);
+ return tmpCanvas.canvas;
+ },
+
+ setScale: function TilingPattern_setScale(width, height, xstep, ystep) {
+ this.scale = [width / xstep, height / ystep];
+ },
+
+ transformToScale: function TilingPattern_transformToScale(graphics) {
+ var scale = this.scale;
+ var tmpScale = [scale[0], 0, 0, scale[1], 0, 0];
+ graphics.transform.apply(graphics, tmpScale);
+ },
+
+ scaleToContext: function TilingPattern_scaleToContext() {
+ var scale = this.scale;
+ this.ctx.scale(1 / scale[0], 1 / scale[1]);
+ },
+
+ clipBbox: function clipBbox(graphics, bbox, x0, y0, x1, y1) {
+ if (bbox && isArray(bbox) && bbox.length === 4) {
+ var bboxWidth = x1 - x0;
+ var bboxHeight = y1 - y0;
+ graphics.ctx.rect(x0, y0, bboxWidth, bboxHeight);
+ graphics.clip();
+ graphics.endPath();
+ }
+ },
+
+ setFillAndStrokeStyleToContext:
+ function setFillAndStrokeStyleToContext(context, paintType, color) {
+ switch (paintType) {
+ case PaintType.COLORED:
+ var ctx = this.ctx;
+ context.fillStyle = ctx.fillStyle;
+ context.strokeStyle = ctx.strokeStyle;
+ break;
+ case PaintType.UNCOLORED:
+ var cssColor = Util.makeCssRgb(color[0], color[1], color[2]);
+ context.fillStyle = cssColor;
+ context.strokeStyle = cssColor;
+ break;
+ default:
+ error('Unsupported paint type: ' + paintType);
+ }
+ },
+
+ getPattern: function TilingPattern_getPattern(ctx, owner) {
+ var temporaryPatternCanvas = this.createPatternCanvas(owner);
+
+ ctx = this.ctx;
+ ctx.setTransform.apply(ctx, this.baseTransform);
+ ctx.transform.apply(ctx, this.matrix);
+ this.scaleToContext();
+
+ return ctx.createPattern(temporaryPatternCanvas, 'repeat');
+ }
+ };
+
+ return TilingPattern;
+})();
+
+exports.getShadingPatternFromIR = getShadingPatternFromIR;
+exports.TilingPattern = TilingPattern;
+}));
+
+
+(function (root, factory) {
+ {
+ factory((root.pdfjsDisplayCanvas = {}), root.pdfjsSharedUtil,
+ root.pdfjsDisplayDOMUtils, root.pdfjsDisplayPatternHelper,
+ root.pdfjsDisplayWebGL);
+ }
+}(this, function (exports, sharedUtil, displayDOMUtils, displayPatternHelper,
+ displayWebGL) {
+
+var FONT_IDENTITY_MATRIX = sharedUtil.FONT_IDENTITY_MATRIX;
+var IDENTITY_MATRIX = sharedUtil.IDENTITY_MATRIX;
+var ImageKind = sharedUtil.ImageKind;
+var OPS = sharedUtil.OPS;
+var TextRenderingMode = sharedUtil.TextRenderingMode;
+var Uint32ArrayView = sharedUtil.Uint32ArrayView;
+var Util = sharedUtil.Util;
+var assert = sharedUtil.assert;
+var info = sharedUtil.info;
+var isNum = sharedUtil.isNum;
+var isArray = sharedUtil.isArray;
+var isLittleEndian = sharedUtil.isLittleEndian;
+var error = sharedUtil.error;
+var shadow = sharedUtil.shadow;
+var warn = sharedUtil.warn;
+var TilingPattern = displayPatternHelper.TilingPattern;
+var getShadingPatternFromIR = displayPatternHelper.getShadingPatternFromIR;
+var WebGLUtils = displayWebGL.WebGLUtils;
+var hasCanvasTypedArrays = displayDOMUtils.hasCanvasTypedArrays;
+
+//