new standalone git repository for this Special Issue

master
manetta 3 years ago
commit 4fc3e69164

@ -0,0 +1,577 @@
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
/* 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 */
'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;
contextPrototype._createImageData = contextPrototype.createImageData;
contextPrototype.createImageData = function(w, h) {
var imageData = this._createImageData(w, h);
imageData.data.set = function(arr) {
for (var i = 0, ii = this.length; i < ii; i++) {
this[i] = arr[i];
}
};
return imageData;
};
}
}
})();
// 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;
}
})();

@ -0,0 +1,27 @@
/* This is just a sample file with CSS rules. You should write your own @font-face declarations
* to add support for your desired fonts.
*/
@font-face {
font-family: 'Novecentowide Book';
src: url("/ViewerJS/fonts/Novecentowide-Bold-webfont.eot");
src: url("/ViewerJS/fonts/Novecentowide-Bold-webfont.eot?#iefix") format("embedded-opentype"),
url("/ViewerJS/fonts/Novecentowide-Bold-webfont.woff") format("woff"),
url("/fonts/Novecentowide-Bold-webfont.ttf") format("truetype"),
url("/fonts/Novecentowide-Bold-webfont.svg#NovecentowideBookBold") format("svg");
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: 'exotica';
src: url('/ViewerJS/fonts/Exotica-webfont.eot');
src: url('/ViewerJS/fonts/Exotica-webfont.eot?#iefix') format('embedded-opentype'),
url('/ViewerJS/fonts/Exotica-webfont.woff') format('woff'),
url('/ViewerJS/fonts/Exotica-webfont.ttf') format('truetype'),
url('/ViewerJS/fonts/Exotica-webfont.svg#exoticamedium') format('svg');
font-weight: normal;
font-style: normal;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 512 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 491 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 237 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 353 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 344 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 228 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 143 B

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

39353
ViewerJS/pdf.worker.js vendored

File diff suppressed because it is too large Load Diff

@ -0,0 +1 @@
var /**@const{!string}*/pdfjs_version = "v1.1.114";

@ -0,0 +1,419 @@
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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 CustomStyle, PDFJS */
'use strict';
var MAX_TEXT_DIVS_TO_RENDER = 100000;
var NonWhitespaceRegexp = /\S/;
function isAllWhitespace(str) {
return !NonWhitespaceRegexp.test(str);
}
/**
* @typedef {Object} TextLayerBuilderOptions
* @property {HTMLDivElement} textLayerDiv - The text layer container.
* @property {number} pageIndex - The page index.
* @property {PageViewport} viewport - The viewport of the text layer.
* @property {PDFFindController} findController
*/
/**
* TextLayerBuilder provides text-selection functionality for the PDF.
* It does this by creating overlay divs over the PDF text. These divs
* contain text that matches the PDF text they are overlaying. This object
* also provides a way to highlight text that is being searched for.
* @class
*/
var TextLayerBuilder = (function TextLayerBuilderClosure() {
function TextLayerBuilder(options) {
this.textLayerDiv = options.textLayerDiv;
this.renderingDone = false;
this.divContentDone = false;
this.pageIdx = options.pageIndex;
this.pageNumber = this.pageIdx + 1;
this.matches = [];
this.viewport = options.viewport;
this.textDivs = [];
this.findController = options.findController || null;
}
TextLayerBuilder.prototype = {
_finishRendering: function TextLayerBuilder_finishRendering() {
this.renderingDone = true;
var event = document.createEvent('CustomEvent');
event.initCustomEvent('textlayerrendered', true, true, {
pageNumber: this.pageNumber
});
this.textLayerDiv.dispatchEvent(event);
},
renderLayer: function TextLayerBuilder_renderLayer() {
var textLayerFrag = document.createDocumentFragment();
var textDivs = this.textDivs;
var textDivsLength = textDivs.length;
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
// 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) {
this._finishRendering();
return;
}
var lastFontSize;
var lastFontFamily;
for (var i = 0; i < textDivsLength; i++) {
var textDiv = textDivs[i];
if (textDiv.dataset.isWhitespace !== undefined) {
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;
if (width > 0) {
textLayerFrag.appendChild(textDiv);
var transform;
if (textDiv.dataset.canvasWidth !== undefined) {
// Dataset values come of type string.
var textScale = textDiv.dataset.canvasWidth / width;
transform = 'scaleX(' + textScale + ')';
} else {
transform = '';
}
var rotation = textDiv.dataset.angle;
if (rotation) {
transform = 'rotate(' + rotation + 'deg) ' + transform;
}
if (transform) {
CustomStyle.setProp('transform' , textDiv, transform);
}
}
}
this.textLayerDiv.appendChild(textLayerFrag);
this._finishRendering();
this.updateMatches();
},
/**
* Renders the text layer.
* @param {number} timeout (optional) if specified, the rendering waits
* for specified amount of ms.
*/
render: function TextLayerBuilder_render(timeout) {
if (!this.divContentDone || this.renderingDone) {
return;
}
if (this.renderTimer) {
clearTimeout(this.renderTimer);
this.renderTimer = null;
}
if (!timeout) { // Render right away
this.renderLayer();
} else { // Schedule
var self = this;
this.renderTimer = setTimeout(function() {
self.renderLayer();
self.renderTimer = null;
}, timeout);
}
},
appendText: function TextLayerBuilder_appendText(geom, styles) {
var style = styles[geom.fontName];
var textDiv = document.createElement('div');
this.textDivs.push(textDiv);
if (isAllWhitespace(geom.str)) {
textDiv.dataset.isWhitespace = true;
return;
}
var tx = PDFJS.Util.transform(this.viewport.transform, geom.transform);
var angle = Math.atan2(tx[1], tx[0]);
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));
}
textDiv.style.left = left + 'px';
textDiv.style.top = top + 'px';
textDiv.style.fontSize = fontHeight + 'px';
textDiv.style.fontFamily = style.fontFamily;
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.
if (PDFJS.pdfBug) {
textDiv.dataset.fontName = geom.fontName;
}
// Storing into dataset will convert number into string.
if (angle !== 0) {
textDiv.dataset.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 (textDiv.textContent.length > 1) {
if (style.vertical) {
textDiv.dataset.canvasWidth = geom.height * this.viewport.scale;
} else {
textDiv.dataset.canvasWidth = geom.width * this.viewport.scale;
}
}
},
setTextContent: function TextLayerBuilder_setTextContent(textContent) {
this.textContent = textContent;
var textItems = textContent.items;
for (var i = 0, len = textItems.length; i < len; i++) {
this.appendText(textItems[i], textContent.styles);
}
this.divContentDone = true;
},
convertMatches: function TextLayerBuilder_convertMatches(matches) {
var i = 0;
var iIndex = 0;
var bidiTexts = this.textContent.items;
var end = bidiTexts.length - 1;
var queryLen = (this.findController === null ?
0 : this.findController.state.query.length);
var ret = [];
for (var m = 0, len = matches.length; m < len; m++) {
// Calculate the start position.
var matchIdx = matches[m];
// Loop over the divIdxs.
while (i !== end && matchIdx >= (iIndex + bidiTexts[i].str.length)) {
iIndex += bidiTexts[i].str.length;
i++;
}
if (i === bidiTexts.length) {
console.error('Could not find a matching mapping');
}
var match = {
begin: {
divIdx: i,
offset: matchIdx - iIndex
}
};
// Calculate the end position.
matchIdx += queryLen;
// Somewhat the same array as above, but use > instead of >= to get
// the end position right.
while (i !== end && matchIdx > (iIndex + bidiTexts[i].str.length)) {
iIndex += bidiTexts[i].str.length;
i++;
}
match.end = {
divIdx: i,
offset: matchIdx - iIndex
};
ret.push(match);
}
return ret;
},
renderMatches: function TextLayerBuilder_renderMatches(matches) {
// Early exit if there is nothing to render.
if (matches.length === 0) {
return;
}
var bidiTexts = this.textContent.items;
var textDivs = this.textDivs;
var prevEnd = null;
var pageIdx = this.pageIdx;
var isSelectedPage = (this.findController === null ?
false : (pageIdx === this.findController.selected.pageIdx));
var selectedMatchIdx = (this.findController === null ?
-1 : this.findController.selected.matchIdx);
var highlightAll = (this.findController === null ?
false : this.findController.state.highlightAll);
var infinity = {
divIdx: -1,
offset: undefined
};
function beginText(begin, className) {
var divIdx = begin.divIdx;
textDivs[divIdx].textContent = '';
appendTextToDiv(divIdx, 0, begin.offset, className);
}
function appendTextToDiv(divIdx, fromOffset, toOffset, className) {
var div = textDivs[divIdx];
var content = bidiTexts[divIdx].str.substring(fromOffset, toOffset);
var node = document.createTextNode(content);
if (className) {
var span = document.createElement('span');
span.className = className;
span.appendChild(node);
div.appendChild(span);
return;
}
div.appendChild(node);
}
var i0 = selectedMatchIdx, i1 = i0 + 1;
if (highlightAll) {
i0 = 0;
i1 = matches.length;
} else if (!isSelectedPage) {
// Not highlighting all and this isn't the selected page, so do nothing.
return;
}
for (var i = i0; i < i1; i++) {
var match = matches[i];
var begin = match.begin;
var end = match.end;
var isSelected = (isSelectedPage && i === selectedMatchIdx);
var highlightSuffix = (isSelected ? ' selected' : '');
if (this.findController) {
this.findController.updateMatchPosition(pageIdx, i, textDivs,
begin.divIdx, end.divIdx);
}
// Match inside new div.
if (!prevEnd || begin.divIdx !== prevEnd.divIdx) {
// If there was a previous div, then add the text at the end.
if (prevEnd !== null) {
appendTextToDiv(prevEnd.divIdx, prevEnd.offset, infinity.offset);
}
// Clear the divs and set the content until the starting point.
beginText(begin);
} else {
appendTextToDiv(prevEnd.divIdx, prevEnd.offset, begin.offset);
}
if (begin.divIdx === end.divIdx) {
appendTextToDiv(begin.divIdx, begin.offset, end.offset,
'highlight' + highlightSuffix);
} else {
appendTextToDiv(begin.divIdx, begin.offset, infinity.offset,
'highlight begin' + highlightSuffix);
for (var n0 = begin.divIdx + 1, n1 = end.divIdx; n0 < n1; n0++) {
textDivs[n0].className = 'highlight middle' + highlightSuffix;
}
beginText(end, 'highlight end' + highlightSuffix);
}
prevEnd = end;
}
if (prevEnd) {
appendTextToDiv(prevEnd.divIdx, prevEnd.offset, infinity.offset);
}
},
updateMatches: function TextLayerBuilder_updateMatches() {
// Only show matches when all rendering is done.
if (!this.renderingDone) {
return;
}
// Clear all matches.
var matches = this.matches;
var textDivs = this.textDivs;
var bidiTexts = this.textContent.items;
var clearedUntilDivIdx = -1;
// Clear all current matches.
for (var i = 0, len = matches.length; i < len; i++) {
var match = matches[i];
var begin = Math.max(clearedUntilDivIdx, match.begin.divIdx);
for (var n = begin, end = match.end.divIdx; n <= end; n++) {
var div = textDivs[n];
div.textContent = bidiTexts[n].str;
div.className = '';
}
clearedUntilDivIdx = match.end.divIdx + 1;
}
if (this.findController === null || !this.findController.active) {
return;
}
// Convert the matches on the page controller into the match format
// used for the textLayer.
this.matches = this.convertMatches(this.findController === null ?
[] : (this.findController.pageMatches[this.pageIdx] || []));
this.renderMatches(this.matches);
}
};
return TextLayerBuilder;
})();
/**
* @constructor
* @implements IPDFTextLayerFactory
*/
function DefaultTextLayerFactory() {}
DefaultTextLayerFactory.prototype = {
/**
* @param {HTMLDivElement} textLayerDiv
* @param {number} pageIndex
* @param {PageViewport} viewport
* @returns {TextLayerBuilder}
*/
createTextLayerBuilder: function (textLayerDiv, pageIndex, viewport) {
return new TextLayerBuilder({
textLayerDiv: textLayerDiv,
pageIndex: pageIndex,
viewport: viewport
});
}
};

@ -0,0 +1,394 @@
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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.
*/
'use strict';
var CSS_UNITS = 96.0 / 72.0;
var DEFAULT_SCALE = 'auto';
var UNKNOWN_SCALE = 0;
var MAX_AUTO_SCALE = 1.25;
var SCROLLBAR_PADDING = 40;
var VERTICAL_PADDING = 5;
// optimised CSS custom property getter/setter
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 = {};
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 getFileName(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);
}
/**
* Returns scale factor for the canvas. It makes sense for the HiDPI displays.
* @return {Object} The object with horizontal (sx) and vertical (sy)
scales. The scaled property is set to false if scaling is
not required, true otherwise.
*/
function getOutputScale(ctx) {
var devicePixelRatio = window.devicePixelRatio || 1;
var backingStoreRatio = ctx.webkitBackingStorePixelRatio ||
ctx.mozBackingStorePixelRatio ||
ctx.msBackingStorePixelRatio ||
ctx.oBackingStorePixelRatio ||
ctx.backingStorePixelRatio || 1;
var pixelRatio = devicePixelRatio / backingStoreRatio;
return {
sx: pixelRatio,
sy: pixelRatio,
scaled: pixelRatio !== 1
};
}
/**
* Scrolls specified element into view of its parent.
* element {Object} The element to be visible.
* spot {Object} An object with optional top and left properties,
* specifying the offset from the top left edge.
*/
function scrollIntoView(element, spot) {
// Assuming offsetParent is available (it's not available when viewer is in
// hidden iframe or object). We have to scroll: if the offsetParent is not set
// producing the error. See also animationStartedClosure.
var parent = element.offsetParent;
var offsetY = element.offsetTop + element.clientTop;
var offsetX = element.offsetLeft + element.clientLeft;
if (!parent) {
console.error('offsetParent is not set -- cannot scroll');
return;
}
while (parent.clientHeight === parent.scrollHeight) {
if (parent.dataset._scaleY) {
offsetY /= parent.dataset._scaleY;
offsetX /= parent.dataset._scaleX;
}
offsetY += parent.offsetTop;
offsetX += parent.offsetLeft;
parent = parent.offsetParent;
if (!parent) {
return; // no need to scroll
}
}
if (spot) {
if (spot.top !== undefined) {
offsetY += spot.top;
}
if (spot.left !== undefined) {
offsetX += spot.left;
parent.scrollLeft = offsetX;
}
}
parent.scrollTop = offsetY;
}
/**
* Helper function to start monitoring the scroll event and converting them into
* PDF.js friendly one: with scroll debounce and scroll direction.
*/
function watchScroll(viewAreaElement, callback) {
var debounceScroll = function debounceScroll(evt) {
if (rAF) {
return;
}
// schedule an invocation of scroll for next animation frame.
rAF = window.requestAnimationFrame(function viewAreaElementScrolled() {
rAF = null;
var currentY = viewAreaElement.scrollTop;
var lastY = state.lastY;
if (currentY !== lastY) {
state.down = currentY > lastY;
}
state.lastY = currentY;
callback(state);
});
};
var state = {
down: true,
lastY: viewAreaElement.scrollTop,
_eventHandler: debounceScroll
};
var rAF = null;
viewAreaElement.addEventListener('scroll', debounceScroll, true);
return state;
}
/**
* Use binary search to find the index of the first item in a given array which
* passes a given condition. The items are expected to be sorted in the sense
* that if the condition is true for one item in the array, then it is also true
* for all following items.
*
* @returns {Number} Index of the first array element to pass the test,
* or |items.length| if no such element exists.
*/
function binarySearchFirstItem(items, condition) {
var minIndex = 0;
var maxIndex = items.length - 1;
if (items.length === 0 || !condition(items[maxIndex])) {
return items.length;
}
if (condition(items[minIndex])) {
return minIndex;
}
while (minIndex < maxIndex) {
var currentIndex = (minIndex + maxIndex) >> 1;
var currentItem = items[currentIndex];
if (condition(currentItem)) {
maxIndex = currentIndex;
} else {
minIndex = currentIndex + 1;
}
}
return minIndex; /* === maxIndex */
}
/**
* Generic helper to find out what elements are visible within a scroll pane.
*/
function getVisibleElements(scrollEl, views, sortByVisibility) {
var top = scrollEl.scrollTop, bottom = top + scrollEl.clientHeight;
var left = scrollEl.scrollLeft, right = left + scrollEl.clientWidth;
function isElementBottomBelowViewTop(view) {
var element = view.div;
var elementBottom =
element.offsetTop + element.clientTop + element.clientHeight;
return elementBottom > top;
}
var visible = [], view, element;
var currentHeight, viewHeight, hiddenHeight, percentHeight;
var currentWidth, viewWidth;
var firstVisibleElementInd = (views.length === 0) ? 0 :
binarySearchFirstItem(views, isElementBottomBelowViewTop);
for (var i = firstVisibleElementInd, ii = views.length; i < ii; i++) {
view = views[i];
element = view.div;
currentHeight = element.offsetTop + element.clientTop;
viewHeight = element.clientHeight;
if (currentHeight > bottom) {
break;
}
currentWidth = element.offsetLeft + element.clientLeft;
viewWidth = element.clientWidth;
if (currentWidth + viewWidth < left || currentWidth > right) {
continue;
}
hiddenHeight = Math.max(0, top - currentHeight) +
Math.max(0, currentHeight + viewHeight - bottom);
percentHeight = ((viewHeight - hiddenHeight) * 100 / viewHeight) | 0;
visible.push({
id: view.id,
x: currentWidth,
y: currentHeight,
view: view,
percent: percentHeight
});
}
var first = visible[0];
var last = visible[visible.length - 1];
if (sortByVisibility) {
visible.sort(function(a, b) {
var pc = a.percent - b.percent;
if (Math.abs(pc) > 0.001) {
return -pc;
}
return a.id - b.id; // ensure stability
});
}
return {first: first, last: last, views: visible};
}
/**
* Event handler to suppress context menu.
*/
function noContextMenuHandler(e) {
e.preventDefault();
}
/**
* Returns the filename or guessed filename from the url (see issue 3455).
* url {String} The original PDF location.
* @return {String} Guessed PDF file name.
*/
function getPDFFileNameFromURL(url) {
var reURI = /^(?:([^:]+:)?\/\/[^\/]+)?([^?#]*)(\?[^#]*)?(#.*)?$/;
// SCHEME HOST 1.PATH 2.QUERY 3.REF
// Pattern to get last matching NAME.pdf
var reFilename = /[^\/?#=]+\.pdf\b(?!.*\.pdf\b)/i;
var splitURI = reURI.exec(url);
var suggestedFilename = reFilename.exec(splitURI[1]) ||
reFilename.exec(splitURI[2]) ||
reFilename.exec(splitURI[3]);
if (suggestedFilename) {
suggestedFilename = suggestedFilename[0];
if (suggestedFilename.indexOf('%') !== -1) {
// URL-encoded %2Fpath%2Fto%2Ffile.pdf should be file.pdf
try {
suggestedFilename =
reFilename.exec(decodeURIComponent(suggestedFilename))[0];
} catch(e) { // Possible (extremely rare) errors:
// URIError "Malformed URI", e.g. for "%AA.pdf"
// TypeError "null has no properties", e.g. for "%2F.pdf"
}
}
}
return suggestedFilename || 'document.pdf';
}
var ProgressBar = (function ProgressBarClosure() {
function clamp(v, min, max) {
return Math.min(Math.max(v, min), max);
}
function ProgressBar(id, opts) {
this.visible = true;
// Fetch the sub-elements for later.
this.div = document.querySelector(id + ' .progress');
// Get the loading bar element, so it can be resized to fit the viewer.
this.bar = this.div.parentNode;
// Get options, with sensible defaults.
this.height = opts.height || 100;
this.width = opts.width || 100;
this.units = opts.units || '%';
// Initialize heights.
this.div.style.height = this.height + this.units;
this.percent = 0;
}
ProgressBar.prototype = {
updateBar: function ProgressBar_updateBar() {
if (this._indeterminate) {
this.div.classList.add('indeterminate');
this.div.style.width = this.width + this.units;
return;
}
this.div.classList.remove('indeterminate');
var progressSize = this.width * this._percent / 100;
this.div.style.width = progressSize + this.units;
},
get percent() {
return this._percent;
},
set percent(val) {
this._indeterminate = isNaN(val);
this._percent = clamp(val, 0, 100);
this.updateBar();
},
setWidth: function ProgressBar_setWidth(viewer) {
if (viewer) {
var container = viewer.parentNode;
var scrollbarWidth = container.offsetWidth - viewer.offsetWidth;
if (scrollbarWidth > 0) {
this.bar.setAttribute('style', 'width: calc(100% - ' +
scrollbarWidth + 'px);');
}
}
},
hide: function ProgressBar_hide() {
if (!this.visible) {
return;
}
this.visible = false;
this.bar.classList.add('hidden');
document.body.classList.remove('loadingInProgress');
},
show: function ProgressBar_show() {
if (this.visible) {
return;
}
this.visible = true;
document.body.classList.add('loadingInProgress');
this.bar.classList.remove('hidden');
}
};
return ProgressBar;
})();

File diff suppressed because one or more lines are too long

@ -0,0 +1,75 @@
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<meta name=viewport content=width=device-width, initial-scale=1>
<title>The Library Is Open - Special Issue 9</title>
<!--
<meta name=Keywords content= >
<meta name=Description content= >
<link rel=icon href= type=image/x-icon>
-->
<link rel=stylesheet type=text/css href=./style.css>
</head>
<body>
<main>
<header>
<h1><a id="title" href="./index.html">The Library Is Open</a></h1>
<h2>Special Issue 09</h2>
<h3>Piet Zwart Institute</h3>
<hr><hr><br>
<nav>
<ul>
<li><a href="./video.html">Video</a></li>
<li><a href="./poster.html">Poster</a></li>
<li><a href="./publication.html">Publication</a></li>
<li><a href="./bb.html">Blurry Boundaries</a></li>
<li><a href="./mc.html">Marginal Conversations</a></li>
<li><a href="./ka.html">Knowledge In Action</a></li>
<li><a href="./photos.html">Photos</a></li>
</ul>
</nav>
<br>
</header>
<br>
<article>
<div id="right" >
<section id="description">
<p id="firstLine">Dear readers,<br><br>
The Library Is Open invites you to an afternoon of workshops that make the operations within libraries visible. Join us in exploring the actions and roles of legal and extra-legal libraries (municipal, pirate, academic, +++), their custodians, and the public that form a community around collections of texts.</p>
<p><b>Marginal Conversations</b><br>
We read texts, and write notes in the margins; usually in private, isolated from other readers. We come across texts with others' notes on them; the author unknown, their thoughts obscure. What happens when we share our notes, vocalise and perform them?</p>
<p>In this workshop...we'll read, annotate and discuss an open letter which asks for pirate library practices to come out from the shadows. We'll read aloud and perform parts of the text, enriched by our doubts, sympathies, tensions and diverse understandings. We'll personalise the text, opening it up for collective conversations. Our voices will occupy the space and leave traces on the text and in the library.</p>
<p><b>Knowledge In Action</b><br>
Through role play you will perform the activities crucial to the sustenance of libraries. You will interpret and reimagine the actors that take part in knowledge production and distribution, such as the librarian, the researcher, the pirate, the publisher, the reader, the writer, the student, the copyist, the printer.</p>
<p>The workshop consists of three activities where different scenarios shift your accustomed perspective to start common dialogues. Put yourselves in the shoes of the librarian, imagine together a reading space, and contest the morality of knowledge proprietization.</p>
<p><b>Blurry Boundaries</b><br>
Select, annotate, analyze, scan, correct, digitize, print, read, transfer, erase, encode, curate, hack, interface, work, copy...<br>
How do we reveal the hidden labour involved in these processes? What libraries become possible when you transform physical books into digital files, and vice versa? </p>
<p>In this workshop you will be a librarian converting books into machine readable files, a process involving tools, time and choices.</p><br>
<p class="extras">Contributors:<br>
Simon Browne, Tancredi Di Giovanni, Paloma García, Rita Graça, Artemis Gryllaki, Pedro Sá Couto, Femke Snelting, Biyi Wen, Bohye Woo</p>
<p class="extras">Special thanks to:<br>
Bodó Balázs, Dušan Barok, Anita Burato, André Castro, Aymeric Mansoux, Michael Murtaugh, Martino Morandi, Leslie Robbins, Steve Rushton, Amy Suo Wu, Eva Weinmayr</p>
</section>
</div>
<div class="vl"></div>
<div id="left">
<section id="pdf">
<iframe src="./ViewerJS/?zoom=page-width#../media/pdfs/bb_reader.pdf" alt="pdf" width="100%" height="100%">
</section>
</div>
</article>
</main>
</body>
</html>

@ -0,0 +1,18 @@
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<meta name=viewport content=width=device-width, initial-scale=1>
<meta http-equiv="refresh" content="0; url=./video.html">
<title>The Library Is Open - Special Issue 9</title>
<!--
<meta name=Keywords content= >
<meta name=Description content= >
<link rel=icon href= type=image/x-icon>
-->
<link rel=stylesheet type=text/css href=./style.css>
</head>
<body>
</body>
</html>

@ -0,0 +1,75 @@
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<meta name=viewport content=width=device-width, initial-scale=1>
<title>The Library Is Open - Special Issue 9</title>
<!--
<meta name=Keywords content= >
<meta name=Description content= >
<link rel=icon href= type=image/x-icon>
-->
<link rel=stylesheet type=text/css href=./style.css>
</head>
<body>
<main>
<header>
<h1><a id="title" href="./index.html">The Library Is Open</a></h1>
<h2>Special Issue 09</h2>
<h3>Piet Zwart Institute</h3>
<hr><hr><br>
<nav>
<ul>
<li><a href="./video.html">Video</a></li>
<li><a href="./poster.html">Poster</a></li>
<li><a href="./publication.html">Publication</a></li>
<li><a href="./bb.html">Blurry Boundaries</a></li>
<li><a href="./mc.html">Marginal Conversations</a></li>
<li><a href="./ka.html">Knowledge In Action</a></li>
<li><a href="./photos.html">Photos</a></li>
</ul>
</nav>
<br>
</header>
<br>
<article>
<div id="right" >
<section id="description">
<p id="firstLine">Dear readers,<br><br>
The Library Is Open invites you to an afternoon of workshops that make the operations within libraries visible. Join us in exploring the actions and roles of legal and extra-legal libraries (municipal, pirate, academic, +++), their custodians, and the public that form a community around collections of texts.</p>
<p><b>Marginal Conversations</b><br>
We read texts, and write notes in the margins; usually in private, isolated from other readers. We come across texts with others' notes on them; the author unknown, their thoughts obscure. What happens when we share our notes, vocalise and perform them?</p>
<p>In this workshop...we'll read, annotate and discuss an open letter which asks for pirate library practices to come out from the shadows. We'll read aloud and perform parts of the text, enriched by our doubts, sympathies, tensions and diverse understandings. We'll personalise the text, opening it up for collective conversations. Our voices will occupy the space and leave traces on the text and in the library.</p>
<p><b>Knowledge In Action</b><br>
Through role play you will perform the activities crucial to the sustenance of libraries. You will interpret and reimagine the actors that take part in knowledge production and distribution, such as the librarian, the researcher, the pirate, the publisher, the reader, the writer, the student, the copyist, the printer.</p>
<p>The workshop consists of three activities where different scenarios shift your accustomed perspective to start common dialogues. Put yourselves in the shoes of the librarian, imagine together a reading space, and contest the morality of knowledge proprietization.</p>
<p><b>Blurry Boundaries</b><br>
Select, annotate, analyze, scan, correct, digitize, print, read, transfer, erase, encode, curate, hack, interface, work, copy...<br>
How do we reveal the hidden labour involved in these processes? What libraries become possible when you transform physical books into digital files, and vice versa? </p>
<p>In this workshop you will be a librarian converting books into machine readable files, a process involving tools, time and choices.</p><br>
<p class="extras">Contributors:<br>
Simon Browne, Tancredi Di Giovanni, Paloma García, Rita Graça, Artemis Gryllaki, Pedro Sá Couto, Femke Snelting, Biyi Wen, Bohye Woo</p>
<p class="extras">Special thanks to:<br>
Bodó Balázs, Dušan Barok, Anita Burato, André Castro, Aymeric Mansoux, Michael Murtaugh, Martino Morandi, Leslie Robbins, Steve Rushton, Amy Suo Wu, Eva Weinmayr</p>
</section>
</div>
<div class="vl"></div>
<div id="left">
<section id="pdf">
<iframe src="./ViewerJS/?zoom=page-width#../media/pdfs/ka_reader.pdf" alt="pdf" width="100%" height="100%">
</section>
</div>
</article>
</main>
</body>
</html>

@ -0,0 +1,75 @@
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<meta name=viewport content=width=device-width, initial-scale=1>
<title>The Library Is Open - Special Issue 9</title>
<!--
<meta name=Keywords content= >
<meta name=Description content= >
<link rel=icon href= type=image/x-icon>
-->
<link rel=stylesheet type=text/css href=./style.css>
</head>
<body>
<main>
<header>
<h1><a id="title" href="./index.html">The Library Is Open</a></h1>
<h2>Special Issue 09</h2>
<h3>Piet Zwart Institute</h3>
<hr><hr><br>
<nav>
<ul>
<li><a href="./video.html">Video</a></li>
<li><a href="./poster.html">Poster</a></li>
<li><a href="./publication.html">Publication</a></li>
<li><a href="./bb.html">Blurry Boundaries</a></li>
<li><a href="./mc.html">Marginal Conversations</a></li>
<li><a href="./ka.html">Knowledge In Action</a></li>
<li><a href="./photos.html">Photos</a></li>
</ul>
</nav>
<br>
</header>
<br>
<article>
<div id="right" >
<section id="description">
<p id="firstLine">Dear readers,<br><br>
The Library Is Open invites you to an afternoon of workshops that make the operations within libraries visible. Join us in exploring the actions and roles of legal and extra-legal libraries (municipal, pirate, academic, +++), their custodians, and the public that form a community around collections of texts.</p>
<p><b>Marginal Conversations</b><br>
We read texts, and write notes in the margins; usually in private, isolated from other readers. We come across texts with others' notes on them; the author unknown, their thoughts obscure. What happens when we share our notes, vocalise and perform them?</p>
<p>In this workshop...we'll read, annotate and discuss an open letter which asks for pirate library practices to come out from the shadows. We'll read aloud and perform parts of the text, enriched by our doubts, sympathies, tensions and diverse understandings. We'll personalise the text, opening it up for collective conversations. Our voices will occupy the space and leave traces on the text and in the library.</p>
<p><b>Knowledge In Action</b><br>
Through role play you will perform the activities crucial to the sustenance of libraries. You will interpret and reimagine the actors that take part in knowledge production and distribution, such as the librarian, the researcher, the pirate, the publisher, the reader, the writer, the student, the copyist, the printer.</p>
<p>The workshop consists of three activities where different scenarios shift your accustomed perspective to start common dialogues. Put yourselves in the shoes of the librarian, imagine together a reading space, and contest the morality of knowledge proprietization.</p>
<p><b>Blurry Boundaries</b><br>
Select, annotate, analyze, scan, correct, digitize, print, read, transfer, erase, encode, curate, hack, interface, work, copy...<br>
How do we reveal the hidden labour involved in these processes? What libraries become possible when you transform physical books into digital files, and vice versa? </p>
<p>In this workshop you will be a librarian converting books into machine readable files, a process involving tools, time and choices.</p><br>
<p class="extras">Contributors:<br>
Simon Browne, Tancredi Di Giovanni, Paloma García, Rita Graça, Artemis Gryllaki, Pedro Sá Couto, Femke Snelting, Biyi Wen, Bohye Woo</p>
<p class="extras">Special thanks to:<br>
Bodó Balázs, Dušan Barok, Anita Burato, André Castro, Aymeric Mansoux, Michael Murtaugh, Martino Morandi, Leslie Robbins, Steve Rushton, Amy Suo Wu, Eva Weinmayr</p>
</section>
</div>
<div class="vl"></div>
<div id="left">
<section id="pdf">
<iframe src="./ViewerJS/?zoom=page-width#../media/pdfs/mc_reader.pdf" alt="pdf" width="100%" height="100%">
</section>
</div>
</article>
</main>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<title>The Library Is Open</title>
<meta charset="utf-8">
</head>
<body>
<embed src="https://issue.xpub.nl/09/posterSI9.pdf" alt="pdf"
pluginspage="https://www.adobe.com/products/acrobat/readstep2.html"
width="100%" height="1000px">
</body>
</html>

@ -0,0 +1,98 @@
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<meta name=viewport content=width=device-width, initial-scale=1>
<title>The Library Is Open - Special Issue 9</title>
<!--
<meta name=Keywords content= >
<meta name=Description content= >
<link rel=icon href= type=image/x-icon>
-->
<link rel=stylesheet type=text/css href=./style.css>
</head>
<body>
<main>
<header>
<h1><a id="title" href="./index.html">The Library Is Open</a></h1>
<h2>Special Issue 09</h2>
<h3>Piet Zwart Institute</h3>
<hr><hr><br>
<nav>
<ul>
<li><a href="./video.html">Video</a></li>
<li><a href="./poster.html">Poster</a></li>
<li><a href="./publication.html">Publication</a></li>
<li><a href="./bb.html">Blurry Boundaries</a></li>
<li><a href="./mc.html">Marginal Conversations</a></li>
<li><a href="./ka.html">Knowledge In Action</a></li>
<li><a href="./photos.html">Photos</a></li>
</ul>
</nav>
<br>
</header>
<br>
<article>
<div id="left">
<section id="photos">
<div class="row">
<div class="column">
<img src="./media/imgs/01-min.jpg" style="width:100%">
<img src="./media/imgs/02-min.jpg" style="width:100%">
<img src="./media/imgs/03-min.jpg" style="width:100%">
<img src="./media/imgs/04-min.jpg" style="width:100%">
<img src="./media/imgs/05-min.jpg" style="width:100%">
<img src="./media/imgs/06-min.jpg" style="width:100%">
<img src="./media/imgs/07-min.jpg" style="width:100%">
<img src="./media/imgs/08-min.jpg" style="width:100%">
<img src="./media/imgs/09-min.jpg" style="width:100%">
</div>
<div class="column">
<img src="./media/imgs/10-min.jpg" style="width:100%">
<img src="./media/imgs/11-min.jpg" style="width:100%">
<img src="./media/imgs/12-min.jpg" style="width:100%">
<img src="./media/imgs/13-min.jpg" style="width:100%">
<img src="./media/imgs/14-min.jpg" style="width:100%">
<img src="./media/imgs/15-min.jpg" style="width:100%">
<img src="./media/imgs/16-min.jpg" style="width:100%">
<img src="./media/imgs/17-min.jpg" style="width:100%">
<img src="./media/imgs/18-min.jpg" style="width:100%">
</div>
</div>
</section>
</div>
<div class="vl"></div>
<div id="right" >
<section id="description">
<p id="firstLine">Dear readers,<br><br>
The Library Is Open invites you to an afternoon of workshops that make the operations within libraries visible. Join us in exploring the actions and roles of legal and extra-legal libraries (municipal, pirate, academic, +++), their custodians, and the public that form a community around collections of texts.</p>
<p><b>Marginal Conversations</b><br>
We read texts, and write notes in the margins; usually in private, isolated from other readers. We come across texts with others' notes on them; the author unknown, their thoughts obscure. What happens when we share our notes, vocalise and perform them?</p>
<p>In this workshop...we'll read, annotate and discuss an open letter which asks for pirate library practices to come out from the shadows. We'll read aloud and perform parts of the text, enriched by our doubts, sympathies, tensions and diverse understandings. We'll personalise the text, opening it up for collective conversations. Our voices will occupy the space and leave traces on the text and in the library.</p>
<p><b>Knowledge In Action</b><br>
Through role play you will perform the activities crucial to the sustenance of libraries. You will interpret and reimagine the actors that take part in knowledge production and distribution, such as the librarian, the researcher, the pirate, the publisher, the reader, the writer, the student, the copyist, the printer.</p>
<p>The workshop consists of three activities where different scenarios shift your accustomed perspective to start common dialogues. Put yourselves in the shoes of the librarian, imagine together a reading space, and contest the morality of knowledge proprietization.</p>
<p><b>Blurry Boundaries</b><br>
Select, annotate, analyze, scan, correct, digitize, print, read, transfer, erase, encode, curate, hack, interface, work, copy...<br>
How do we reveal the hidden labour involved in these processes? What libraries become possible when you transform physical books into digital files, and vice versa? </p>
<p>In this workshop you will be a librarian converting books into machine readable files, a process involving tools, time and choices.</p><br>
<p class="extras">Contributors:<br>
Simon Browne, Tancredi Di Giovanni, Paloma García, Rita Graça, Artemis Gryllaki, Pedro Sá Couto, Femke Snelting, Biyi Wen, Bohye Woo</p>
<p class="extras">Special thanks to:<br>
Bodó Balázs, Dušan Barok, Anita Burato, André Castro, Aymeric Mansoux, Michael Murtaugh, Martino Morandi, Leslie Robbins, Steve Rushton, Amy Suo Wu, Eva Weinmayr</p>
</section>
</div>
</article>
</main>
</body>
</html>

@ -0,0 +1,76 @@
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<meta name=viewport content=width=device-width, initial-scale=1>
<title>The Library Is Open - Special Issue 9</title>
<!--
<meta name=Keywords content= >
<meta name=Description content= >
<link rel=icon href= type=image/x-icon>
-->
<link rel=stylesheet type=text/css href=./style.css>
</head>
<body>
<main>
<header>
<h1><a id="title" href="./index.html">The Library Is Open</a></h1>
<h2>Special Issue 09</h2>
<h3>Piet Zwart Institute</h3>
<hr><hr><br>
<nav>
<ul>
<li><a href="./video.html">Video</a></li>
<li><a href="./poster.html">Poster</a></li>
<li><a href="./publication.html">Publication</a></li>
<li><a href="./bb.html">Blurry Boundaries</a></li>
<li><a href="./mc.html">Marginal Conversations</a></li>
<li><a href="./ka.html">Knowledge In Action</a></li>
<li><a href="./photos.html">Photos</a></li>
</ul>
</nav>
<br>
</header>
<br>
<article>
<div id="right" >
<section id="description">
<p id="firstLine">Dear readers,<br><br>
The Library Is Open invites you to an afternoon of workshops that make the operations within libraries visible. Join us in exploring the actions and roles of legal and extra-legal libraries (municipal, pirate, academic, +++), their custodians, and the public that form a community around collections of texts.</p>
<p><b>Marginal Conversations</b><br>
We read texts, and write notes in the margins; usually in private, isolated from other readers. We come across texts with others' notes on them; the author unknown, their thoughts obscure. What happens when we share our notes, vocalise and perform them?</p>
<p>In this workshop...we'll read, annotate and discuss an open letter which asks for pirate library practices to come out from the shadows. We'll read aloud and perform parts of the text, enriched by our doubts, sympathies, tensions and diverse understandings. We'll personalise the text, opening it up for collective conversations. Our voices will occupy the space and leave traces on the text and in the library.</p>
<p><b>Knowledge In Action</b><br>
Through role play you will perform the activities crucial to the sustenance of libraries. You will interpret and reimagine the actors that take part in knowledge production and distribution, such as the librarian, the researcher, the pirate, the publisher, the reader, the writer, the student, the copyist, the printer.</p>
<p>The workshop consists of three activities where different scenarios shift your accustomed perspective to start common dialogues. Put yourselves in the shoes of the librarian, imagine together a reading space, and contest the morality of knowledge proprietization.</p>
<p><b>Blurry Boundaries</b><br>
Select, annotate, analyze, scan, correct, digitize, print, read, transfer, erase, encode, curate, hack, interface, work, copy...<br>
How do we reveal the hidden labour involved in these processes? What libraries become possible when you transform physical books into digital files, and vice versa? </p>
<p>In this workshop you will be a librarian converting books into machine readable files, a process involving tools, time and choices.</p><br>
<p class="extras">Contributors:<br>
Simon Browne, Tancredi Di Giovanni, Paloma García, Rita Graça, Artemis Gryllaki, Pedro Sá Couto, Femke Snelting, Biyi Wen, Bohye Woo</p>
<p class="extras">Special thanks to:<br>
Bodó Balázs, Dušan Barok, Anita Burato, André Castro, Aymeric Mansoux, Michael Murtaugh, Martino Morandi, Leslie Robbins, Steve Rushton, Amy Suo Wu, Eva Weinmayr</p>
</section>
</div>
<div class="vl"></div>
<div id="left">
<section id="pdf">
<iframe src="./ViewerJS/?zoom=page-width#../media/pdfs/poster.pdf" alt="pdf" width="100%" height="100%">
</section>
</div>
</article>
</main>
</body>
</html>

@ -0,0 +1,78 @@
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<meta name=viewport content=width=device-width, initial-scale=1>
<title>The Library Is Open - Special Issue 9</title>
<!--
<meta name=Keywords content= >
<meta name=Description content= >
<link rel=icon href= type=image/x-icon>
-->
<link rel=stylesheet type=text/css href=./style.css>
</head>
<body>
<main>
<header>
<h1><a id="title" href="./index.html">The Library Is Open</a></h1>
<h2>Special Issue 09</h2>
<h3>Piet Zwart Institute</h3>
<hr><hr><br>
<nav>
<ul>
<li><a href="./video.html">Video</a></li>
<li><a href="./poster.html">Poster</a></li>
<li><a href="./publication.html">Publication</a></li>
<li><a href="./bb.html">Blurry Boundaries</a></li>
<li><a href="./mc.html">Marginal Conversations</a></li>
<li><a href="./ka.html">Knowledge In Action</a></li>
<li><a href="./photos.html">Photos</a></li>
</ul>
</nav>
<br>
</header>
<br>
<article>
<div id="right" >
<section id="description">
<p id="firstLine">Dear readers,<br><br>
The Library Is Open invites you to an afternoon of workshops that make the operations within libraries visible. Join us in exploring the actions and roles of legal and extra-legal libraries (municipal, pirate, academic, +++), their custodians, and the public that form a community around collections of texts.</p>
<p><b>Marginal Conversations</b><br>
We read texts, and write notes in the margins; usually in private, isolated from other readers. We come across texts with others' notes on them; the author unknown, their thoughts obscure. What happens when we share our notes, vocalise and perform them?</p>
<p>In this workshop...we'll read, annotate and discuss an open letter which asks for pirate library practices to come out from the shadows. We'll read aloud and perform parts of the text, enriched by our doubts, sympathies, tensions and diverse understandings. We'll personalise the text, opening it up for collective conversations. Our voices will occupy the space and leave traces on the text and in the library.</p>
<p><b>Knowledge In Action</b><br>
Through role play you will perform the activities crucial to the sustenance of libraries. You will interpret and reimagine the actors that take part in knowledge production and distribution, such as the librarian, the researcher, the pirate, the publisher, the reader, the writer, the student, the copyist, the printer.</p>
<p>The workshop consists of three activities where different scenarios shift your accustomed perspective to start common dialogues. Put yourselves in the shoes of the librarian, imagine together a reading space, and contest the morality of knowledge proprietization.</p>
<p><b>Blurry Boundaries</b><br>
Select, annotate, analyze, scan, correct, digitize, print, read, transfer, erase, encode, curate, hack, interface, work, copy...<br>
How do we reveal the hidden labour involved in these processes? What libraries become possible when you transform physical books into digital files, and vice versa? </p>
<p>In this workshop you will be a librarian converting books into machine readable files, a process involving tools, time and choices.</p><br>
<p class="extras">Contributors:<br>
Simon Browne, Tancredi Di Giovanni, Paloma García, Rita Graça, Artemis Gryllaki, Pedro Sá Couto, Femke Snelting, Biyi Wen, Bohye Woo</p>
<p class="extras">Special thanks to:<br>
Bodó Balázs, Dušan Barok, Anita Burato, André Castro, Aymeric Mansoux, Michael Murtaugh, Martino Morandi, Leslie Robbins, Steve Rushton, Amy Suo Wu, Eva Weinmayr</p>
</section>
</div>
<div class="vl"></div>
<div id="left">
<a href="http://pedrosacouto.com/thelibraryisopen.pdf">READ HERE!</p></a>
<!--
<section id="pdf">
<iframe src="./ViewerJS/?zoom=page-width#../media/pdfs/mc_reader.pdf" alt="pdf" width="100%" height="100%">
</section>
-->
</div>
</article>
</main>
</body>
</html>

@ -0,0 +1,187 @@
@font-face {
font-family: "Book";
src: url("./media/fonts/standard-book-webfont.woff");
}
@font-face {
font-family: "Book";
src: url("./media/fonts/standard-book-italic-webfont.woff");
font-style: italic;
}
* {
font-family: Book ;
}
main {
width: 90%;
margin: auto;
}
/* HEADER */
header {
z-index: 101;
background-color: white;
padding-top: 10px;
line-height: .9em;
font-size: 14px;
text-align: center;
}
h1 {
font-style: italic;
}
a {
text-decoration: none;
}
article {
width: 100%;
}
nav {
background-color: white;
margin-top: -5px;
}
ul {
width: 80%;
margin: auto;
list-style: none;
font-size: 15px;
padding: 0px;
line-height: 19px;
}
/* MAIN CONTENT */
#left {
float: left;
width: 50%;
margin: auto;
margin-bottom: 15px;
}
.vl {
z-index: -1;
border-left: 2px solid black;
height: 500px;
position: fixed;
left: 50%;
margin-left: -1px;
bottom: 19px;
}
#right {
float: right;
width: 50%;
margin: auto;
margin-bottom: 15px;
}
section {
width: 96%;
margin: auto;
}
#description {
height: 55vh;
overflow-y: auto;
}
#firstLine {
margin-top: 0px;
}
.extras {
font-style: italic;
}
#pdf {
width: 94%;
height: 55vh;
}
#photos {
width: 94%;
overflow-y: auto;
height: 400px;
}
img {
width: 100%;
height: auto;
}
/* IMGS */
.row {
display: -ms-flexbox; /* IE 10 */
display: flex;
-ms-flex-wrap: wrap; /* IE 10 */
flex-wrap: wrap;
padding: 0 4px;
}
/* Create two equal columns that sits next to each other */
.column {
-ms-flex: 50%; /* IE 10 */
flex: 50%;
padding: 0 100px;
}
.column img {
margin-top: 8px;
vertical-align: middle;
}
/* RESPONSIVE */
@media only screen and (max-width: 600px) {
header { font-size: 10px; }
#left { width: 96%; }
.vl { visibility: hidden; }
#right {
width: 96%;
float: left;
}
#pdf { width: 96%; }
#photos { width: 96%; }
.column { padding: 0px 9px 0px 0px; }
}
@media only screen and (max-width: 1200px) and (min-width: 600px) {
.column { padding: 0px 20px; }
}
@media only screen and (min-height: 805px) {
.vl { height: 700px; }
#photos { height: 445px; }
.column { padding: 0px 50px; }
}
@media only screen and (min-height: 870px) {
.vl { height: 700px; }
#photos { height: 495px; }
.column { padding: 0px 50px; }
}

@ -0,0 +1,83 @@
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<meta name=viewport content=width=device-width, initial-scale=1>
<title>The Library Is Open - Special Issue 9</title>
<!--
<meta name=Keywords content= >
<meta name=Description content= >
<link rel=icon href= type=image/x-icon>
-->
<link rel=stylesheet type=text/css href=./style.css>
</head>
<body>
<main>
<header>
<h1><a id="title" href="./index.html">The Library Is Open</a></h1>
<h2>Special Issue 09</h2>
<h3>Piet Zwart Institute</h3>
<hr><hr><br>
<nav>
<ul>
<li><a href="./video.html">Video</a></li>
<li><a href="./poster.html">Poster</a></li>
<li><a href="./publication.html">Publication</a></li>
<li><a href="./bb.html">Blurry Boundaries</a></li>
<li><a href="./mc.html">Marginal Conversations</a></li>
<li><a href="./ka.html">Knowledge In Action</a></li>
<li><a href="./photos.html">Photos</a></li>
</ul>
</nav>
<br>
</header>
<br>
<article>
<div id="left">
SOON ONLINE!
<!--
<section id="video">
<video controls="" width="100%">
<source src="https://media.xpub.nl/special_issue_06-web.mp4" poster="preview.png" type="video/mp4">
Your browser does not support the video tag :(
Try a recent version of Firefox or Chromium!
</video>
</section>
-->
</div>
<div class="vl"></div>
<div id="right" >
<section id="description">
<p id="firstLine">Dear readers,<br><br>
The Library Is Open invites you to an afternoon of workshops that make the operations within libraries visible. Join us in exploring the actions and roles of legal and extra-legal libraries (municipal, pirate, academic, +++), their custodians, and the public that form a community around collections of texts.</p>
<p><b>Marginal Conversations</b><br>
We read texts, and write notes in the margins; usually in private, isolated from other readers. We come across texts with others' notes on them; the author unknown, their thoughts obscure. What happens when we share our notes, vocalise and perform them?</p>
<p>In this workshop...we'll read, annotate and discuss an open letter which asks for pirate library practices to come out from the shadows. We'll read aloud and perform parts of the text, enriched by our doubts, sympathies, tensions and diverse understandings. We'll personalise the text, opening it up for collective conversations. Our voices will occupy the space and leave traces on the text and in the library.</p>
<p><b>Knowledge In Action</b><br>
Through role play you will perform the activities crucial to the sustenance of libraries. You will interpret and reimagine the actors that take part in knowledge production and distribution, such as the librarian, the researcher, the pirate, the publisher, the reader, the writer, the student, the copyist, the printer.</p>
<p>The workshop consists of three activities where different scenarios shift your accustomed perspective to start common dialogues. Put yourselves in the shoes of the librarian, imagine together a reading space, and contest the morality of knowledge proprietization.</p>
<p><b>Blurry Boundaries</b><br>
Select, annotate, analyze, scan, correct, digitize, print, read, transfer, erase, encode, curate, hack, interface, work, copy...<br>
How do we reveal the hidden labour involved in these processes? What libraries become possible when you transform physical books into digital files, and vice versa? </p>
<p>In this workshop you will be a librarian converting books into machine readable files, a process involving tools, time and choices.</p><br>
<p class="extras">Contributors:<br>
Simon Browne, Tancredi Di Giovanni, Paloma García, Rita Graça, Artemis Gryllaki, Pedro Sá Couto, Femke Snelting, Biyi Wen, Bohye Woo</p>
<p class="extras">Special thanks to:<br>
Bodó Balázs, Dušan Barok, Anita Burato, André Castro, Aymeric Mansoux, Michael Murtaugh, Martino Morandi, Leslie Robbins, Steve Rushton, Amy Suo Wu, Eva Weinmayr</p>
</section>
</div>
</article>
</main>
</body>
</html>
Loading…
Cancel
Save