Merge git://gitorious.org/owncloud/owncloud into contact_thumbnails
Fixed some conflicts. Conflicts: apps/contacts/css/styles.css apps/contacts/templates/index.php
|
@ -2,6 +2,7 @@ ErrorDocument 404 /core/templates/404.php
|
|||
<IfModule mod_php5.c>
|
||||
php_value upload_max_filesize 512M
|
||||
php_value post_max_size 512M
|
||||
php_value memory_limit 512M
|
||||
SetEnv htaccessWorking true
|
||||
</IfModule>
|
||||
RewriteEngine on
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
#editentry_dialog {display: none;}
|
||||
#parsingfail_dialog{display: none;}
|
||||
|
||||
#loading { display: none; left: 40%; position: fixed; top: 4.4em; z-index: 100; }
|
||||
|
||||
#calendar_holder {position: relative;bottom: 0; right: 0; left: 0; top: 3em;}
|
||||
.fc-content{padding:2px 4px;}
|
||||
#listview {margin: 0; padding: 10px; background: #EEEEEE;}
|
||||
|
|
|
@ -6,25 +6,25 @@
|
|||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
require_once ("../../lib/base.php");
|
||||
require_once ('../../lib/base.php');
|
||||
OC_Util::checkLoggedIn();
|
||||
OC_Util::checkAppEnabled('calendar');
|
||||
$cal = isset($_GET["calid"]) ? $_GET["calid"] : NULL;
|
||||
$event = isset($_GET["eventid"]) ? $_GET["eventid"] : NULL;
|
||||
$cal = isset($_GET['calid']) ? $_GET['calid'] : NULL;
|
||||
$event = isset($_GET['eventid']) ? $_GET['eventid'] : NULL;
|
||||
if(isset($cal)){
|
||||
$calendar = OC_Calendar_App::getCalendar($cal);
|
||||
$calobjects = OC_Calendar_Object::all($cal);
|
||||
header("Content-Type: text/Calendar");
|
||||
header("Content-Disposition: inline; filename=calendar.ics");
|
||||
header('Content-Type: text/Calendar');
|
||||
header('Content-Disposition: inline; filename=' . $calendar['displayname'] . '.ics');
|
||||
foreach($calobjects as $calobject){
|
||||
echo $calobject["calendardata"] . "\n";
|
||||
echo $calobject['calendardata'] . '\n';
|
||||
}
|
||||
}elseif(isset($event)){
|
||||
$data = OC_Calendar_App::getEventObject($_GET["eventid"]);
|
||||
$calendarid = $data["calendarid"];
|
||||
$data = OC_Calendar_App::getEventObject($_GET['eventid']);
|
||||
$calendarid = $data['calendarid'];
|
||||
$calendar = OC_Calendar_App::getCalendar($calendarid);
|
||||
header("Content-Type: text/Calendar");
|
||||
header("Content-Disposition: inline; filename=" . $data["summary"] . ".ics");
|
||||
echo $data["calendardata"];
|
||||
header('Content-Type: text/Calendar');
|
||||
header('Content-Disposition: inline; filename=' . $data['summary'] . '.ics');
|
||||
echo $data['calendardata'];
|
||||
}
|
||||
?>
|
||||
|
|
|
@ -8,7 +8,15 @@
|
|||
|
||||
Calendar={
|
||||
UI:{
|
||||
loading: function(isLoading){
|
||||
if (isLoading){
|
||||
$('#loading').show();
|
||||
}else{
|
||||
$('#loading').hide();
|
||||
}
|
||||
},
|
||||
startEventDialog:function(){
|
||||
Calendar.UI.loading(false);
|
||||
$('.tipsy').remove();
|
||||
$('#calendar_holder').fullCalendar('unselect');
|
||||
Calendar.UI.lockTime();
|
||||
|
@ -41,6 +49,7 @@ Calendar={
|
|||
// TODO: save event
|
||||
$('#event').dialog('destroy').remove();
|
||||
}else{
|
||||
Calendar.UI.loading(true);
|
||||
$('#dialog_holder').load(OC.filePath('calendar', 'ajax', 'neweventform.php'), {start:start, end:end, allday:allday?1:0}, Calendar.UI.startEventDialog);
|
||||
}
|
||||
},
|
||||
|
@ -50,13 +59,16 @@ Calendar={
|
|||
// TODO: save event
|
||||
$('#event').dialog('destroy').remove();
|
||||
}else{
|
||||
Calendar.UI.loading(true);
|
||||
$('#dialog_holder').load(OC.filePath('calendar', 'ajax', 'editeventform.php') + '?id=' + id, Calendar.UI.startEventDialog);
|
||||
}
|
||||
},
|
||||
submitDeleteEventForm:function(url){
|
||||
var post = $( '#event_form' ).serialize();
|
||||
$('#errorbox').empty();
|
||||
Calendar.UI.loading(true);
|
||||
$.post(url, post, function(data){
|
||||
Calendar.UI.loading(false);
|
||||
if(data.status == 'success'){
|
||||
$('#calendar_holder').fullCalendar('removeEvents', $('#event_form input[name=id]').val());
|
||||
$('#event').dialog('destroy').remove();
|
||||
|
@ -69,8 +81,10 @@ Calendar={
|
|||
validateEventForm:function(url){
|
||||
var post = $( "#event_form" ).serialize();
|
||||
$("#errorbox").empty();
|
||||
Calendar.UI.loading(true);
|
||||
$.post(url, post,
|
||||
function(data){
|
||||
Calendar.UI.loading(false);
|
||||
if(data.status == "error"){
|
||||
var output = missing_field + ": <br />";
|
||||
if(data.title == "true"){
|
||||
|
@ -107,8 +121,10 @@ Calendar={
|
|||
},
|
||||
moveEvent:function(event, dayDelta, minuteDelta, allDay, revertFunc){
|
||||
$('.tipsy').remove();
|
||||
Calendar.UI.loading(true);
|
||||
$.post(OC.filePath('calendar', 'ajax', 'moveevent.php'), { id: event.id, dayDelta: dayDelta, minuteDelta: minuteDelta, allDay: allDay?1:0, lastmodified: event.lastmodified},
|
||||
function(data) {
|
||||
Calendar.UI.loading(false);
|
||||
if (data.status == 'success'){
|
||||
event.lastmodified = data.lastmodified;
|
||||
console.log("Event moved successfully");
|
||||
|
@ -120,8 +136,10 @@ Calendar={
|
|||
},
|
||||
resizeEvent:function(event, dayDelta, minuteDelta, revertFunc){
|
||||
$('.tipsy').remove();
|
||||
Calendar.UI.loading(true);
|
||||
$.post(OC.filePath('calendar', 'ajax', 'resizeevent.php'), { id: event.id, dayDelta: dayDelta, minuteDelta: minuteDelta, lastmodified: event.lastmodified},
|
||||
function(data) {
|
||||
Calendar.UI.loading(false);
|
||||
if (data.status == 'success'){
|
||||
event.lastmodified = data.lastmodified;
|
||||
console.log("Event resized successfully");
|
||||
|
@ -210,6 +228,7 @@ Calendar={
|
|||
if($('#choosecalendar_dialog').dialog('isOpen') == true){
|
||||
$('#choosecalendar_dialog').dialog('moveToTop');
|
||||
}else{
|
||||
Calendar.UI.loading(true);
|
||||
$('#dialog_holder').load(OC.filePath('calendar', 'ajax', 'choosecalendar.php'), function(){
|
||||
$('#choosecalendar_dialog').dialog({
|
||||
width : 600,
|
||||
|
@ -217,13 +236,16 @@ Calendar={
|
|||
$(this).dialog('destroy').remove();
|
||||
}
|
||||
});
|
||||
Calendar.UI.loading(false);
|
||||
});
|
||||
}
|
||||
},
|
||||
activation:function(checkbox, calendarid)
|
||||
{
|
||||
Calendar.UI.loading(true);
|
||||
$.post(OC.filePath('calendar', 'ajax', 'activation.php'), { calendarid: calendarid, active: checkbox.checked?1:0 },
|
||||
function(data) {
|
||||
Calendar.UI.loading(false);
|
||||
if (data.status == 'success'){
|
||||
checkbox.checked = data.active == 1;
|
||||
if (data.active == 1){
|
||||
|
@ -520,6 +542,7 @@ $(document).ready(function(){
|
|||
}
|
||||
});
|
||||
},
|
||||
loading: Calendar.UI.loading,
|
||||
eventSources: eventSources
|
||||
});
|
||||
$('#oneweekview_radio').click(function(){
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
var missing_field_dberror = '<?php echo $l->t('There was a database fail') ?>';
|
||||
var totalurl = '<?php echo OC_Helper::linkTo('apps/calendar', 'caldav.php', null, true); ?>/calendars';
|
||||
</script>
|
||||
<div id="loading"><img src="<?php echo OC_Helper::imagePath('core', 'loading.gif'); ?>" /></div>
|
||||
<div id="controls">
|
||||
<div>
|
||||
<form>
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
/**
|
||||
* Copyright (c) 2011 Thomas Tanghus <thomas@tanghus.net>
|
||||
* Copyright (c) 2011 Bart Visscher <bartv@thisnet.nl>
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
require_once ("../../../lib/base.php");
|
||||
OC_JSON::checkLoggedIn();
|
||||
OC_JSON::checkAppEnabled('contacts');
|
||||
$bookid = $_POST['bookid'];
|
||||
OC_Contacts_Addressbook::setActive($bookid, $_POST['active']);
|
||||
$book = OC_Contacts_App::getAddressbook($bookid);
|
||||
|
||||
/* is there an OC_JSON::error() ? */
|
||||
OC_JSON::success(array(
|
||||
'active' => OC_Contacts_Addressbook::isActive($bookid),
|
||||
'bookid' => $bookid,
|
||||
'book' => $book,
|
||||
));
|
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
/**
|
||||
* Copyright (c) 2011 Bart Visscher <bartv@thisnet.nl>
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
require_once('../../../lib/base.php');
|
||||
$l10n = new OC_L10N('contacts');
|
||||
OC_JSON::checkLoggedIn();
|
||||
OC_JSON::checkAppEnabled('contacts');
|
||||
$book = array(
|
||||
'id' => 'new',
|
||||
'displayname' => '',
|
||||
);
|
||||
$tmpl = new OC_Template('contacts', 'part.editaddressbook');
|
||||
$tmpl->assign('new', true);
|
||||
$tmpl->assign('addressbook', $book);
|
||||
$tmpl->printPage();
|
||||
?>
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
/**
|
||||
* Copyright (c) 2011 Thomas Tanghus <thomas@tanghus.net>
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
require_once('../../../lib/base.php');
|
||||
$l10n = new OC_L10N('contacts');
|
||||
OC_JSON::checkLoggedIn();
|
||||
OC_JSON::checkAppEnabled('contacts');
|
||||
|
||||
$output = new OC_TEMPLATE("contacts", "part.chooseaddressbook");
|
||||
$output -> printpage();
|
||||
?>
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
/**
|
||||
* Copyright (c) 2011 Thomas Tanghus <thomas@tanghus.net>
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
function contacts_namesort($a,$b){
|
||||
return strcasecmp($a['fullname'],$b['fullname']);
|
||||
}
|
||||
|
||||
require_once('../../../lib/base.php');
|
||||
OC_JSON::checkLoggedIn();
|
||||
OC_JSON::checkAppEnabled('contacts');
|
||||
|
||||
$addressbooks = OC_Contacts_Addressbook::active(OC_User::getUser());
|
||||
$contacts = array();
|
||||
foreach( $addressbooks as $addressbook ){
|
||||
$addressbookcontacts = OC_Contacts_VCard::all($addressbook['id']);
|
||||
foreach( $addressbookcontacts as $contact ){
|
||||
if(is_null($contact['fullname'])){
|
||||
continue;
|
||||
}
|
||||
$contacts[] = $contact;
|
||||
}
|
||||
}
|
||||
usort($contacts,'contacts_namesort');
|
||||
$tmpl = new OC_TEMPLATE("contacts", "part.contacts");
|
||||
$tmpl->assign('contacts', $contacts);
|
||||
$page = $tmpl->fetchPage();
|
||||
|
||||
OC_JSON::success(array('data' => array( 'page' => $page )));
|
||||
?>
|
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
/**
|
||||
* Copyright (c) 2011 Thomas Tanghus <thomas@tanghus.net>
|
||||
* Copyright (c) 2011 Bart Visscher <bartv@thisnet.nl>
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
require_once('../../../lib/base.php');
|
||||
|
||||
$l10n = new OC_L10N('contacts');
|
||||
|
||||
// Check if we are a user
|
||||
OC_JSON::checkLoggedIn();
|
||||
OC_JSON::checkAppEnabled('contacts');
|
||||
|
||||
$userid = OC_User::getUser();
|
||||
$bookid = OC_Contacts_Addressbook::add($userid, $_POST['name'], null);
|
||||
OC_Contacts_Addressbook::setActive($bookid, 1);
|
||||
$addressbook = OC_Contacts_App::getAddressbook($bookid);
|
||||
$tmpl = new OC_Template('contacts', 'part.chooseaddressbook.rowfields');
|
||||
$tmpl->assign('addressbook', $addressbook);
|
||||
OC_JSON::success(array(
|
||||
'page' => $tmpl->fetchPage(),
|
||||
'addressbook' => $addressbook,
|
||||
));
|
|
@ -23,11 +23,13 @@
|
|||
// Init owncloud
|
||||
require_once('../../../lib/base.php');
|
||||
|
||||
$l10n = new OC_L10N('contacts');
|
||||
// Check if we are a user
|
||||
OC_JSON::checkLoggedIn();
|
||||
OC_JSON::checkAppEnabled('contacts');
|
||||
|
||||
$id = $_GET['id'];
|
||||
//$id = $_GET['id'];
|
||||
$id = $_POST['id'];
|
||||
$addressbook = OC_Contacts_App::getAddressbook( $id );
|
||||
|
||||
OC_Contacts_Addressbook::delete($id);
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
/**
|
||||
* Copyright (c) 2011 Bart Visscher <bartv@thisnet.nl>
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
require_once('../../../lib/base.php');
|
||||
$l10n = new OC_L10N('contacts');
|
||||
OC_JSON::checkLoggedIn();
|
||||
OC_JSON::checkAppEnabled('contacts');
|
||||
$addressbook = OC_Contacts_App::getAddressbook($_GET['bookid']);
|
||||
$tmpl = new OC_Template("contacts", "part.editaddressbook");
|
||||
$tmpl->assign('new', false);
|
||||
$tmpl->assign('addressbook', $addressbook);
|
||||
$tmpl->printPage();
|
||||
?>
|
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
/**
|
||||
* Copyright (c) 2011 Bart Visscher <bartv@thisnet.nl>
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
require_once('../../../lib/base.php');
|
||||
|
||||
$l10n = new OC_L10N('contacts');
|
||||
|
||||
// Check if we are a user
|
||||
OC_JSON::checkLoggedIn();
|
||||
OC_JSON::checkAppEnabled('contacts');
|
||||
|
||||
$bookid = $_POST['id'];
|
||||
OC_Contacts_Addressbook::edit($bookid, $_POST['name'], null);
|
||||
OC_Contacts_Addressbook::setActive($bookid, $_POST['active']);
|
||||
$addressbook = OC_Contacts_App::getAddressbook($bookid);
|
||||
$tmpl = new OC_Template('contacts', 'part.chooseaddressbook.rowfields');
|
||||
$tmpl->assign('addressbook', $addressbook);
|
||||
OC_JSON::success(array(
|
||||
'page' => $tmpl->fetchPage(),
|
||||
'addressbook' => $addressbook,
|
||||
));
|
|
@ -1,4 +1,5 @@
|
|||
#contacts li { padding-left:25px;background:url('../img/person.svg') no-repeat; }
|
||||
#chooseaddressbook {margin-right: 170px; float: right;}
|
||||
#contacts_details_name { font-weight:bold;font-size:1.1em;margin-left:25%;}
|
||||
#contacts_details_photo { margin:.5em 0em .5em 25%; }
|
||||
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
/**
|
||||
* Copyright (c) 2011 Georg Ehrke <ownclouddev at georgswebsite dot de>
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
require_once ("../../lib/base.php");
|
||||
OC_Util::checkLoggedIn();
|
||||
OC_Util::checkAppEnabled('contacts');
|
||||
$book = isset($_GET['bookid']) ? $_GET['bookid'] : NULL;
|
||||
$contact = isset($_GET['contactid']) ? $_GET['contactid'] : NULL;
|
||||
if(isset($book)){
|
||||
$addressbook = OC_Contacts_App::getAddressbook($book);
|
||||
if($addressbook['userid'] != OC_User::getUser()){
|
||||
OC_JSON::error();
|
||||
exit;
|
||||
}
|
||||
$cardobjects = OC_Contacts_VCard::all($book);
|
||||
header('Content-Type: text/directory');
|
||||
header('Content-Disposition: inline; filename=' . str_replace(' ', '_', $addressbook['displayname']) . '.vcf');
|
||||
for($i = 0;$i <= count($cardobjects); $i++){
|
||||
echo $cardobjects[$i]['carddata'];
|
||||
//echo '\r\n';
|
||||
}
|
||||
}elseif(isset($contact)){
|
||||
$data = OC_Contacts_App::getContactObject($contact);
|
||||
$addressbookid = $data['addressbookid'];
|
||||
$addressbook = OC_Contacts_App::getAddressbook($addressbookid);
|
||||
if($addressbook['userid'] != OC_User::getUser()){
|
||||
OC_JSON::error();
|
||||
exit;
|
||||
}
|
||||
header('Content-Type: text/directory');
|
||||
header('Content-Disposition: inline; filename=' . $data['fullname'] . '.vcf');
|
||||
echo $data['carddata'];
|
||||
}
|
||||
?>
|
|
@ -21,7 +21,7 @@
|
|||
*/
|
||||
|
||||
function contacts_namesort($a,$b){
|
||||
return strcmp($a['name'],$b['name']);
|
||||
return strcmp($a['fullname'],$b['fullname']);
|
||||
}
|
||||
|
||||
// Init owncloud
|
||||
|
@ -31,17 +31,8 @@ require_once('../../lib/base.php');
|
|||
OC_Util::checkLoggedIn();
|
||||
OC_Util::checkAppEnabled('contacts');
|
||||
|
||||
// Check if the user has an addressbook
|
||||
$addressbooks = OC_Contacts_Addressbook::all(OC_User::getUser());
|
||||
if( count($addressbooks) == 0){
|
||||
OC_Contacts_Addressbook::add(OC_User::getUser(),'default','Default Address Book');
|
||||
$addressbooks = OC_Contacts_Addressbook::all(OC_User::getUser());
|
||||
}
|
||||
$prefbooks = OC_Preferences::getValue(OC_User::getUser(),'contacts','openaddressbooks',null);
|
||||
if(is_null($prefbooks)){
|
||||
$prefbooks = $addressbooks[0]['id'];
|
||||
OC_Preferences::setValue(OC_User::getUser(),'contacts','openaddressbooks',$prefbooks);
|
||||
}
|
||||
// Get active address books. This creates a default one if none exists.
|
||||
$addressbooks = OC_Contacts_Addressbook::active(OC_User::getUser());
|
||||
|
||||
// Load the files we need
|
||||
OC_App::setActiveNavigationEntry( 'contacts_index' );
|
||||
|
@ -51,17 +42,15 @@ $id = isset( $_GET['id'] ) ? $_GET['id'] : null;
|
|||
|
||||
// sort addressbooks (use contactsort)
|
||||
usort($addressbooks,'contacts_namesort');
|
||||
// Addressbooks to load
|
||||
$openaddressbooks = explode(';',$prefbooks);
|
||||
|
||||
$contacts = array();
|
||||
foreach( $openaddressbooks as $addressbook ){
|
||||
$addressbookcontacts = OC_Contacts_VCard::all($addressbook);
|
||||
foreach( $addressbooks as $addressbook ){
|
||||
$addressbookcontacts = OC_Contacts_VCard::all($addressbook['id']);
|
||||
foreach( $addressbookcontacts as $contact ){
|
||||
if(is_null($contact['fullname'])){
|
||||
continue;
|
||||
}
|
||||
$contacts[] = array( 'name' => $contact['fullname'], 'id' => $contact['id'] );
|
||||
$contacts[] = $contact;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -74,6 +63,13 @@ if( !is_null($id)/* || count($contacts)*/){
|
|||
$details = OC_Contacts_VCard::structureContact($vcard);
|
||||
}
|
||||
|
||||
// Include Style and Script
|
||||
OC_Util::addScript('contacts','interface');
|
||||
OC_Util::addStyle('contacts','styles');
|
||||
OC_Util::addStyle('contacts','formtastic');
|
||||
OC_Util::addScript('', 'jquery.multiselect');
|
||||
OC_Util::addStyle('', 'jquery.multiselect');
|
||||
|
||||
$property_types = OC_Contacts_App::getAddPropertyOptions();
|
||||
$adr_types = OC_Contacts_App::getTypesOfProperty('ADR');
|
||||
$phone_types = OC_Contacts_App::getTypesOfProperty('TEL');
|
||||
|
|
|
@ -1,3 +1,118 @@
|
|||
Contacts={
|
||||
UI:{
|
||||
showCardDAVUrl:function(username, bookname){
|
||||
$('#carddav_url').val(totalurl + '/' + username + '/' + bookname);
|
||||
$('#carddav_url').show();
|
||||
$('#carddav_url_close').show();
|
||||
},
|
||||
Addressbooks:{
|
||||
overview:function(){
|
||||
if($('#chooseaddressbook_dialog').dialog('isOpen') == true){
|
||||
$('#chooseaddressbook_dialog').dialog('moveToTop');
|
||||
}else{
|
||||
$('#dialog_holder').load(OC.filePath('contacts', 'ajax', 'chooseaddressbook.php'), function(){
|
||||
$('#chooseaddressbook_dialog').dialog({
|
||||
width : 600,
|
||||
close : function(event, ui) {
|
||||
$(this).dialog('destroy').remove();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
activation:function(checkbox, bookid)
|
||||
{
|
||||
$.post(OC.filePath('contacts', 'ajax', 'activation.php'), { bookid: bookid, active: checkbox.checked?1:0 },
|
||||
function(data) {
|
||||
/*
|
||||
* Arguments:
|
||||
* data.status
|
||||
* data.bookid
|
||||
* data.active
|
||||
*/
|
||||
if (data.status == 'success'){
|
||||
checkbox.checked = data.active == 1;
|
||||
Contacts.UI.Contacts.update();
|
||||
}
|
||||
});
|
||||
},
|
||||
newAddressbook:function(object){
|
||||
var tr = $(document.createElement('tr'))
|
||||
.load(OC.filePath('contacts', 'ajax', 'addbook.php'));
|
||||
$(object).closest('tr').after(tr).hide();
|
||||
/* TODO: Shouldn't there be some kinda error checking here? */
|
||||
},
|
||||
editAddressbook:function(object, bookid){
|
||||
var tr = $(document.createElement('tr'))
|
||||
.load(OC.filePath('contacts', 'ajax', 'editaddressbook.php') + "?bookid="+bookid);
|
||||
$(object).closest('tr').after(tr).hide();
|
||||
},
|
||||
deleteAddressbook:function(bookid){
|
||||
var check = confirm("Do you really want to delete this address book?");
|
||||
if(check == false){
|
||||
return false;
|
||||
}else{
|
||||
$.post(OC.filePath('contacts', 'ajax', 'deletebook.php'), { id: bookid},
|
||||
function(data) {
|
||||
if (data.status == 'success'){
|
||||
$('#chooseaddressbook_dialog').dialog('destroy').remove();
|
||||
Contacts.UI.Contacts.update();
|
||||
Contacts.UI.Addressbooks.overview();
|
||||
} else {
|
||||
alert('Error: ' + data.message);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
submit:function(button, bookid){
|
||||
var displayname = $("#displayname_"+bookid).val();
|
||||
var active = $("#edit_active_"+bookid+":checked").length;
|
||||
var description = $("#description_"+bookid).val();
|
||||
|
||||
var url;
|
||||
if (bookid == 'new'){
|
||||
url = OC.filePath('contacts', 'ajax', 'createaddressbook.php');
|
||||
}else{
|
||||
url = OC.filePath('contacts', 'ajax', 'updateaddressbook.php');
|
||||
}
|
||||
$.post(url, { id: bookid, name: displayname, active: active, description: description },
|
||||
function(data){
|
||||
if(data.status == 'success'){
|
||||
$(button).closest('tr').prev().html(data.page).show().next().remove();
|
||||
}
|
||||
});
|
||||
Contacts.UI.Contacts.update();
|
||||
},
|
||||
cancel:function(button, bookid){
|
||||
$(button).closest('tr').prev().show().next().remove();
|
||||
}
|
||||
},
|
||||
Contacts:{
|
||||
update:function(){
|
||||
$.getJSON('ajax/contacts.php',{},function(jsondata){
|
||||
if(jsondata.status == 'success'){
|
||||
$('#contacts').html(jsondata.data.page);
|
||||
}
|
||||
else{
|
||||
alert(jsondata.data.message);
|
||||
}
|
||||
});
|
||||
/*
|
||||
var contactlist = $('#contacts');
|
||||
var contacts = contactlist.children('li').get();
|
||||
//alert(contacts);
|
||||
contacts.sort(function(a, b) {
|
||||
var compA = $(a).text().toUpperCase();
|
||||
var compB = $(b).text().toUpperCase();
|
||||
return (compA < compB) ? -1 : (compA > compB) ? 1 : 0;
|
||||
})
|
||||
$.each(contacts, function(idx, itm) { contactlist.append(itm); });
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$(document).ready(function(){
|
||||
/*-------------------------------------------------------------------------
|
||||
* Event handlers
|
||||
|
@ -79,6 +194,11 @@ $(document).ready(function(){
|
|||
return false;
|
||||
});
|
||||
|
||||
$('#chooseaddressbook').click(function(){
|
||||
Contacts.UI.Addressbooks.overview();
|
||||
return false;
|
||||
});
|
||||
|
||||
$('#contacts_newcontact').click(function(){
|
||||
$.getJSON('ajax/showaddcard.php',{},function(jsondata){
|
||||
if(jsondata.status == 'success'){
|
||||
|
|
|
@ -44,7 +44,7 @@ class OC_Contacts_Addressbook{
|
|||
* @return array
|
||||
*/
|
||||
public static function all($uid){
|
||||
$stmt = OC_DB::prepare( 'SELECT * FROM *PREFIX*contacts_addressbooks WHERE userid = ?' );
|
||||
$stmt = OC_DB::prepare( 'SELECT * FROM *PREFIX*contacts_addressbooks WHERE userid = ? ORDER BY displayname' );
|
||||
$result = $stmt->execute(array($uid));
|
||||
|
||||
$addressbooks = array();
|
||||
|
@ -140,12 +140,98 @@ class OC_Contacts_Addressbook{
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get active addressbooks for a user.
|
||||
* @param integer $uid User id. If null current user will be used.
|
||||
* @return array
|
||||
*/
|
||||
public static function activeIds($uid = null){
|
||||
if(is_null($uid)){
|
||||
$uid = OC_User::getUser();
|
||||
}
|
||||
$prefbooks = OC_Preferences::getValue($uid,'contacts','openaddressbooks',null);
|
||||
if(is_null($prefbooks)){
|
||||
$addressbooks = OC_Contacts_Addressbook::all($uid);
|
||||
if(count($addressbooks) == 0){
|
||||
OC_Contacts_Addressbook::add($uid,'default','Default Address Book');
|
||||
$addressbooks = OC_Contacts_Addressbook::all($uid);
|
||||
}
|
||||
$prefbooks = $addressbooks[0]['id'];
|
||||
OC_Preferences::setValue($uid,'contacts','openaddressbooks',$prefbooks);
|
||||
}
|
||||
return explode(';',$prefbooks);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the list of active addressbooks for a specific user.
|
||||
* @param string $uid
|
||||
* @return array
|
||||
*/
|
||||
public static function active($uid){
|
||||
$active = self::activeIds($uid);
|
||||
$addressbooks = array();
|
||||
/** FIXME: Is there a way to prepare a statement 'WHERE id IN ([range])'?
|
||||
*/
|
||||
foreach( $active as $aid ){
|
||||
$stmt = OC_DB::prepare( 'SELECT * FROM *PREFIX*contacts_addressbooks WHERE id = ? ORDER BY displayname' );
|
||||
$result = $stmt->execute(array($aid,));
|
||||
|
||||
while( $row = $result->fetchRow()){
|
||||
$addressbooks[] = $row;
|
||||
}
|
||||
}
|
||||
|
||||
return $addressbooks;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Activates an addressbook
|
||||
* @param integer $id
|
||||
* @param integer $name
|
||||
* @return boolean
|
||||
*/
|
||||
public static function setActive($id,$active){
|
||||
// Need these ones for checking uri
|
||||
//$addressbook = self::find($id);
|
||||
|
||||
if(is_null($id)){
|
||||
$id = 0;
|
||||
}
|
||||
|
||||
$openaddressbooks = self::activeIds();
|
||||
if($active) {
|
||||
if(!in_array($id, $openaddressbooks)) {
|
||||
$openaddressbooks[] = $id;
|
||||
}
|
||||
} else {
|
||||
if(in_array($id, $openaddressbooks)) {
|
||||
unset($openaddressbooks[array_search($id, $openaddressbooks)]);
|
||||
}
|
||||
}
|
||||
sort($openaddressbooks, SORT_NUMERIC);
|
||||
// FIXME: I alway end up with a ';' prepending when imploding the array..?
|
||||
OC_Preferences::setValue(OC_User::getUser(),'contacts','openaddressbooks',implode(';', $openaddressbooks));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Checks if an addressbook is active.
|
||||
* @param integer $id ID of the address book.
|
||||
* @return boolean
|
||||
*/
|
||||
public static function isActive($id){
|
||||
OC_Log::write('contacts','OC_Contacts_Addressbook::isActive('.$id.'):'.in_array($id, self::activeIds()), OC_Log::DEBUG);
|
||||
return in_array($id, self::activeIds());
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief removes an address book
|
||||
* @param integer $id
|
||||
* @return boolean
|
||||
*/
|
||||
public static function delete($id){
|
||||
self::setActive($id, false);
|
||||
$stmt = OC_DB::prepare( 'DELETE FROM *PREFIX*contacts_addressbooks WHERE id = ?' );
|
||||
$stmt->execute(array($id));
|
||||
|
||||
|
|
|
@ -47,15 +47,15 @@ class OC_Contacts_VCard{
|
|||
* ['carddata']
|
||||
*/
|
||||
public static function all($id){
|
||||
$stmt = OC_DB::prepare( 'SELECT * FROM *PREFIX*contacts_cards WHERE addressbookid = ?' );
|
||||
$stmt = OC_DB::prepare( 'SELECT * FROM *PREFIX*contacts_cards WHERE addressbookid = ? ORDER BY fullname' );
|
||||
$result = $stmt->execute(array($id));
|
||||
|
||||
$addressbooks = array();
|
||||
$cards = array();
|
||||
while( $row = $result->fetchRow()){
|
||||
$addressbooks[] = $row;
|
||||
$cards[] = $row;
|
||||
}
|
||||
|
||||
return $addressbooks;
|
||||
return $cards;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -5,9 +5,13 @@ OC_Util::addStyle('contacts','styles');
|
|||
OC_Util::addStyle('contacts','formtastic');
|
||||
?>
|
||||
|
||||
<script type='text/javascript'>
|
||||
var totalurl = '<?php echo OC_Helper::linkTo('contacts', 'carddav.php', null, true); ?>/addressbooks';
|
||||
</script>
|
||||
<div id="controls">
|
||||
<form>
|
||||
<input type="button" id="contacts_newcontact" value="<?php echo $l->t('Add Contact'); ?>">
|
||||
<input type="button" id="chooseaddressbook" value="<?php echo $l->t('Address Books'); ?>">
|
||||
</form>
|
||||
</div>
|
||||
<div id="leftcontent" class="leftcontent">
|
||||
|
@ -25,3 +29,9 @@ OC_Util::addStyle('contacts','formtastic');
|
|||
}
|
||||
?>
|
||||
</div>
|
||||
<!-- Dialogs -->
|
||||
<div id="dialog_holder"></div>
|
||||
<div id="parsingfail_dialog" title="Parsing Fail">
|
||||
<?php echo $l->t("There was a fail, while parsing the file."); ?>
|
||||
</div>
|
||||
<!-- End of Dialogs -->
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
<div id="chooseaddressbook_dialog" title="<?php echo $l->t("Choose active Address Books"); ?>">
|
||||
<table width="100%" style="border: 0;">
|
||||
<?php
|
||||
$option_addressbooks = OC_Contacts_Addressbook::all(OC_User::getUser());
|
||||
for($i = 0; $i < count($option_addressbooks); $i++){
|
||||
echo "<tr>";
|
||||
$tmpl = new OC_Template('contacts', 'part.chooseaddressbook.rowfields');
|
||||
$tmpl->assign('addressbook', $option_addressbooks[$i]);
|
||||
$tmpl->assign('active', OC_Contacts_Addressbook::isActive($option_addressbooks[$i]['id']));
|
||||
$tmpl->printpage();
|
||||
echo "</tr>";
|
||||
}
|
||||
?>
|
||||
<tr>
|
||||
<td colspan="5">
|
||||
<a href="#" onclick="Contacts.UI.Addressbooks.newAddressbook(this);"><?php echo $l->t('New Address Book') ?></a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="5">
|
||||
<p style="margin: 0 auto;width: 90%;"><input style="display:none;width: 90%;float: left;" type="text" id="carddav_url" onmouseover="$('#carddav_url').select();" title="<?php echo $l->t("CardDav Link"); ?>"><img id="carddav_url_close" style="height: 20px;vertical-align: middle;display: none;" src="../../core/img/actions/delete.svg" alt="close" onclick="$('#carddav_url').hide();$('#carddav_url_close').hide();"/></p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
|
@ -0,0 +1,5 @@
|
|||
<?php
|
||||
|
||||
echo "<td width=\"20px\"><input id=\"active_" . $_['addressbook']["id"] . "\" type=\"checkbox\" onClick=\"Contacts.UI.Addressbooks.activation(this, " . $_['addressbook']["id"] . ")\"" . (OC_Contacts_Addressbook::isActive($_['addressbook']["id"]) ? ' checked="checked"' : '') . "></td>";
|
||||
echo "<td><label for=\"active_" . $_['addressbook']["id"] . "\">" . $_['addressbook']["displayname"] . "</label></td>";
|
||||
echo "<td width=\"20px\"><a href=\"#\" onclick=\"Contacts.UI.showCardDAVUrl('" . OC_User::getUser() . "', '" . $_['addressbook']["uri"] . "');\" title=\"" . $l->t("CardDav Link") . "\" class=\"action\"><img class=\"svg action\" src=\"../../core/img/actions/public.svg\"></a></td><td width=\"20px\"><a href=\"export.php?bookid=" . $_['addressbook']["id"] . "\" title=\"" . $l->t("Download") . "\" class=\"action\"><img class=\"svg action\" src=\"../../core/img/actions/download.svg\"></a></td><td width=\"20px\"><a href=\"#\" title=\"" . $l->t("Edit") . "\" class=\"action\" onclick=\"Contacts.UI.Addressbooks.editAddressbook(this, " . $_['addressbook']["id"] . ");\"><img class=\"svg action\" src=\"../../core/img/actions/rename.svg\"></a></td><td width=\"20px\"><a href=\"#\" onclick=\"Contacts.UI.Addressbooks.deleteAddressbook('" . $_['addressbook']["id"] . "');\" title=\"" . $l->t("Delete") . "\" class=\"action\"><img class=\"svg action\" src=\"../../core/img/actions/delete.svg\"></a></td>";
|
|
@ -1,3 +1,3 @@
|
|||
<?php foreach( $_['contacts'] as $contact ): ?>
|
||||
<li data-id="<?php echo $contact['id']; ?>"><a href="index.php?id=<?php echo $contact['id']; ?>"><?php echo $contact['name']; ?></a> </li>
|
||||
<li book-id="<?php echo $contact['addressbookid']; ?>" data-id="<?php echo $contact['id']; ?>"><a href="index.php?id=<?php echo $contact['id']; ?>"><?php echo $contact['fullname']; ?></a> </li>
|
||||
<?php endforeach; ?>
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
/**
|
||||
* Copyright (c) 2011 Bart Visscher <bartv@thisnet.nl>
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
?>
|
||||
<td id="<?php echo $_['new'] ? 'new' : 'edit' ?>addressbook_dialog" title="<?php echo $_['new'] ? $l->t("New Address Book") : $l->t("Edit Address Book"); ?>" colspan="6">
|
||||
<table width="100%" style="border: 0;">
|
||||
<tr>
|
||||
<th><?php echo $l->t('Displayname') ?></th>
|
||||
<td>
|
||||
<input id="displayname_<?php echo $_['addressbook']['id'] ?>" type="text" value="<?php echo $_['addressbook']['displayname'] ?>">
|
||||
</td>
|
||||
</tr>
|
||||
<?php if (!$_['new']): ?>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>
|
||||
<input id="edit_active_<?php echo $_['addressbook']['id'] ?>" type="checkbox"<?php echo OC_Contacts_Addressbook::isActive($_['addressbook']['id']) ? ' checked="checked"' : '' ?>>
|
||||
<label for="edit_active_<?php echo $_['addressbook']['id'] ?>">
|
||||
<?php echo $l->t('Active') ?>
|
||||
</label>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endif; ?>
|
||||
</table>
|
||||
<input style="float: left;" type="button" onclick="Contacts.UI.Addressbooks.submit(this, <?php echo $_['new'] ? "'new'" : $_['addressbook']['id'] ?>);" value="<?php echo $_['new'] ? $l->t("Save") : $l->t("Submit"); ?>">
|
||||
<input style="float: left;" type="button" onclick="Contacts.UI.Addressbooks.cancel(this, <?php echo $_['new'] ? "'new'" : $_['addressbook']['id'] ?>);" value="<?php echo $l->t("Cancel"); ?>">
|
||||
</td>
|
|
@ -0,0 +1,9 @@
|
|||
<?php
|
||||
//load the required files
|
||||
//OC_Util::addStyle( 'files_texteditor', 'style' );
|
||||
//OC_Util::addScript( 'files_texteditor', 'editor');
|
||||
OC_Util::addScript( 'files_pdfviewer', 'viewer');
|
||||
OC_Util::addStyle( 'files_pdfviewer', 'viewer');
|
||||
OC_Util::addScript( 'files_pdfviewer', 'pdfjs/build/pdf');
|
||||
OC_Util::addScript( 'files_pdfviewer', 'pdfview');
|
||||
?>
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0"?>
|
||||
<info>
|
||||
<id>files_pdfviewer</id>
|
||||
<name>PDF viewer (pdfjs-based)</name>
|
||||
<version>0.1</version>
|
||||
<licence>GPL</licence>
|
||||
<author>Joan Creus</author>
|
||||
<require>2</require>
|
||||
<default_enable/>
|
||||
</info>
|
After Width: | Height: | Size: 539 B |
|
@ -0,0 +1,27 @@
|
|||
#editor{
|
||||
position: absoloute;
|
||||
display: block;
|
||||
top: 80px;
|
||||
left: 160px;
|
||||
}
|
||||
#editorwrapper{
|
||||
position: absoloute;
|
||||
height: 0;
|
||||
width: 0;
|
||||
top: 41px;
|
||||
left: 160px;
|
||||
display: none;
|
||||
}
|
||||
#editor_close{
|
||||
margin-left: auto;
|
||||
margin-right: 167px;
|
||||
display: block;
|
||||
}
|
||||
#editor_save{
|
||||
margin-left: 7px;
|
||||
float: left;
|
||||
}
|
||||
#saving_icon{
|
||||
margin-top: 3px;
|
||||
float: left;
|
||||
}
|
|
@ -0,0 +1,277 @@
|
|||
/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- /
|
||||
/* vim: set shiftwidth=4 tabstop=8 autoindent cindent expandtab: */
|
||||
|
||||
#viewer {
|
||||
background-color: #929292;
|
||||
font-family: 'Lucida Grande', 'Lucida Sans Unicode', Helvetica, Arial, Verdana, sans-serif;
|
||||
/*margin: 0px;*/
|
||||
padding: 0px;
|
||||
/*position:absolute;*/
|
||||
}
|
||||
|
||||
[hidden] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.separator {
|
||||
display: inline;
|
||||
border-left: 1px solid #d3d3d3;
|
||||
border-right: 1px solid #fff;
|
||||
height: 10px;
|
||||
width:0px;
|
||||
margin: 4px;
|
||||
}
|
||||
|
||||
#controls2 > a > img {
|
||||
margin: 4px;
|
||||
height: 10px;
|
||||
}
|
||||
|
||||
#controls2 > button {
|
||||
line-height: 10px;
|
||||
}
|
||||
|
||||
#controls2 > button > img {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
}
|
||||
|
||||
#controls2 > button[disabled] > img {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
#pageNumber {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
span#info {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@-moz-document regexp("http:.*debug=1.*") {
|
||||
span#info {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
/* === Sidebar === */
|
||||
#sidebar {
|
||||
position: fixed;
|
||||
width: 350px;
|
||||
top: 62px;
|
||||
bottom: 18px;
|
||||
left: -290px;
|
||||
transition: left 0.25s ease-in-out 1s;
|
||||
-moz-transition: left 0.25s ease-in-out 1s;
|
||||
-webkit-transition: left 0.25s ease-in-out 1s;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
#sidebar:hover {
|
||||
left: 0px;
|
||||
transition: left 0.25s ease-in-out 0s;
|
||||
-moz-transition: left 0.25s ease-in-out 0s;
|
||||
-webkit-transition: left 0.25s ease-in-out 0s;
|
||||
}
|
||||
|
||||
#sidebarBox {
|
||||
background-color: rgba(0, 0, 0, 0.7);
|
||||
width: 300px;
|
||||
height: 100%;
|
||||
border-top-right-radius: 8px;
|
||||
border-bottom-right-radius: 8px;
|
||||
-moz-border-radius-topright: 8px;
|
||||
-moz-border-radius-bottomright: 8px;
|
||||
-webkit-border-top-right-radius: 8px;
|
||||
-webkit-border-bottom-right-radius: 8px;
|
||||
box-shadow: 0px 2px 8px #000;
|
||||
-moz-box-shadow: 0px 2px 8px #000;
|
||||
-webkit-box-shadow: 0px 2px 8px #000;
|
||||
}
|
||||
|
||||
#sidebarScrollView {
|
||||
position: absolute;
|
||||
overflow: hidden;
|
||||
overflow-y: auto;
|
||||
top: 10px;
|
||||
bottom: 10px;
|
||||
left: 10px;
|
||||
width: 280px;
|
||||
}
|
||||
|
||||
.thumbnail {
|
||||
width: 134px;
|
||||
height: 134px;
|
||||
margin-top: 5px;
|
||||
margin-bottom: 5px;
|
||||
margin-left:auto;
|
||||
margin-right:auto;
|
||||
line-height: 134px;
|
||||
text-align: center;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.thumbnail:not([data-loaded]) {
|
||||
background-color: gray;
|
||||
}
|
||||
|
||||
.thumbnail > canvas {
|
||||
vertical-align: middle;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
#outlineScrollView {
|
||||
position: absolute;
|
||||
background-color: #fff;
|
||||
overflow: auto;
|
||||
top: 10px;
|
||||
bottom: 10px;
|
||||
left: 10px;
|
||||
width: 280px;
|
||||
}
|
||||
|
||||
#outlineView {
|
||||
padding-top: 4px;
|
||||
padding-bottom: 100px;
|
||||
padding-left: 6px;
|
||||
padding-right: 6px;
|
||||
font-size: smaller;
|
||||
}
|
||||
|
||||
.outlineItem > .outlineItems {
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
.outlineItem > a {
|
||||
text-decoration: none;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.outlineItem > a:hover {
|
||||
background: #ff0;
|
||||
box-shadow: 0px 2px 10px #ff0;
|
||||
}
|
||||
|
||||
#sidebarControls {
|
||||
position:absolute;
|
||||
width: 120px;
|
||||
height: 32px;
|
||||
left: 15px;
|
||||
bottom: 35px;
|
||||
}
|
||||
|
||||
#sidebarControls > button {
|
||||
box-shadow: 0px 4px 10px #000;
|
||||
-moz-box-shadow: 0px 4px 10px #000;
|
||||
-webkit-box-shadow: 0px 4px 10px #000;
|
||||
}
|
||||
|
||||
#sidebarControls > button > img {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
#sidebarControls > button[disabled] > img {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
#sidebarControls > button[data-selected] {
|
||||
box-shadow: 0px 4px 10px #ff0;
|
||||
-moz-box-shadow: 0px 4px 10px #ff0;
|
||||
-webkit-box-shadow: 0px 4px 10px #ff0;
|
||||
}
|
||||
|
||||
/* === Content view === */
|
||||
canvas {
|
||||
margin: auto;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.page {
|
||||
width: 816px;
|
||||
height: 1056px;
|
||||
margin: 10px auto;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
box-shadow: 0px 4px 10px #000;
|
||||
-moz-box-shadow: 0px 4px 10px #000;
|
||||
-webkit-box-shadow: 0px 4px 10px #000;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.page > a {
|
||||
display: block;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.page > a:hover {
|
||||
opacity: 0.2;
|
||||
background: #ff0;
|
||||
box-shadow: 0px 2px 10px #ff0;
|
||||
-moz-box-shadow: 0px 2px 10px #ff0;
|
||||
-webkit-box-shadow: 0px 2px 10px #ff0;
|
||||
}
|
||||
|
||||
#viewer {
|
||||
/*overflow:auto;*/
|
||||
margin: 6.3em 0 0 0;
|
||||
margin-right:12.5em;
|
||||
padding: 8px 0px;
|
||||
position:static;
|
||||
height:100%;
|
||||
width:100%;
|
||||
text-align:center;
|
||||
}
|
||||
|
||||
#sidebarView canvas:hover {
|
||||
background: #ff0;
|
||||
box-shadow: 0px 2px 10px #ff0;
|
||||
-moz-box-shadow: 0px 2px 10px #ff0;
|
||||
-webkit-box-shadow: 0px 2px 10px #ff0;
|
||||
}
|
||||
|
||||
#pageWidthOption {
|
||||
border-top: 1px solid black;
|
||||
}
|
||||
|
||||
#customScaleOption {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* === Printed media overrides === */
|
||||
@media print {
|
||||
#sidebar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#controls2 {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#viewer {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.page {
|
||||
display: none;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.page canvas {
|
||||
box-shadow: none;
|
||||
-moz-box-shadow: none;
|
||||
-webkit-box-shadow: none;
|
||||
}
|
||||
|
||||
.page[data-loaded] {
|
||||
display: block;
|
||||
page-break-after: always;
|
||||
}
|
||||
}
|
||||
|
||||
#loading {
|
||||
margin: 100px 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
|
||||
Copyright (c) 2011 Mozilla Foundation
|
||||
|
||||
Contributors: Andreas Gal <gal@mozilla.com>
|
||||
Chris G Jones <cjones@mozilla.com>
|
||||
Shaon Barman <shaon.barman@gmail.com>
|
||||
Vivien Nicolas <21@vingtetun.org>
|
||||
Justin D'Arcangelo <justindarc@gmail.com>
|
||||
Yury Delendik
|
||||
Kalervo Kujala
|
||||
Adil Allawi <@ironymark>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
|
@ -0,0 +1,869 @@
|
|||
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
|
||||
|
||||
'use strict';
|
||||
|
||||
// <canvas> contexts store most of the state we need natively.
|
||||
// However, PDF needs a bit more state, which we store here.
|
||||
|
||||
var CanvasExtraState = (function canvasExtraState() {
|
||||
function constructor(old) {
|
||||
// Are soft masks and alpha values shapes or opacities?
|
||||
this.alphaIsShape = false;
|
||||
this.fontSize = 0;
|
||||
this.textMatrix = 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;
|
||||
// Color spaces
|
||||
this.fillColorSpace = new DeviceGrayCS();
|
||||
this.fillColorSpaceObj = null;
|
||||
this.strokeColorSpace = new DeviceGrayCS();
|
||||
this.strokeColorSpaceObj = null;
|
||||
this.fillColorObj = null;
|
||||
this.strokeColorObj = null;
|
||||
// Default fore and background colors
|
||||
this.fillColor = '#000000';
|
||||
this.strokeColor = '#000000';
|
||||
// Note: fill alpha applies to all non-stroking operations
|
||||
this.fillAlpha = 1;
|
||||
this.strokeAlpha = 1;
|
||||
|
||||
this.old = old;
|
||||
}
|
||||
|
||||
constructor.prototype = {
|
||||
clone: function canvasextra_clone() {
|
||||
return Object.create(this);
|
||||
},
|
||||
setCurrentPoint: function canvasextra_setCurrentPoint(x, y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
};
|
||||
return constructor;
|
||||
})();
|
||||
|
||||
function ScratchCanvas(width, height) {
|
||||
var canvas = document.createElement('canvas');
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
return canvas;
|
||||
}
|
||||
|
||||
var CanvasGraphics = (function canvasGraphics() {
|
||||
// Defines the time the executeIRQueue is going to be executing
|
||||
// before it stops and shedules a continue of execution.
|
||||
var kExecutionTime = 50;
|
||||
|
||||
// Number of IR commands to execute before checking
|
||||
// if we execute longer then `kExecutionTime`.
|
||||
var kExecutionTimeCheck = 500;
|
||||
|
||||
function constructor(canvasCtx, objs) {
|
||||
this.ctx = canvasCtx;
|
||||
this.current = new CanvasExtraState();
|
||||
this.stateStack = [];
|
||||
this.pendingClip = null;
|
||||
this.res = null;
|
||||
this.xobjs = null;
|
||||
this.ScratchCanvas = ScratchCanvas;
|
||||
this.objs = objs;
|
||||
}
|
||||
|
||||
var LINE_CAP_STYLES = ['butt', 'round', 'square'];
|
||||
var LINE_JOIN_STYLES = ['miter', 'round', 'bevel'];
|
||||
var NORMAL_CLIP = {};
|
||||
var EO_CLIP = {};
|
||||
|
||||
constructor.prototype = {
|
||||
beginDrawing: function canvasGraphicsBeginDrawing(mediaBox) {
|
||||
var cw = this.ctx.canvas.width, ch = this.ctx.canvas.height;
|
||||
this.ctx.save();
|
||||
switch (mediaBox.rotate) {
|
||||
case 0:
|
||||
this.ctx.transform(1, 0, 0, -1, 0, ch);
|
||||
break;
|
||||
case 90:
|
||||
this.ctx.transform(0, 1, 1, 0, 0, 0);
|
||||
break;
|
||||
case 180:
|
||||
this.ctx.transform(-1, 0, 0, 1, cw, 0);
|
||||
break;
|
||||
case 270:
|
||||
this.ctx.transform(0, -1, -1, 0, cw, ch);
|
||||
break;
|
||||
}
|
||||
this.ctx.scale(cw / mediaBox.width, ch / mediaBox.height);
|
||||
},
|
||||
|
||||
executeIRQueue: function canvasGraphicsExecuteIRQueue(codeIR,
|
||||
executionStartIdx, continueCallback) {
|
||||
var argsArray = codeIR.argsArray;
|
||||
var fnArray = codeIR.fnArray;
|
||||
var i = executionStartIdx || 0;
|
||||
var argsArrayLen = argsArray.length;
|
||||
|
||||
var executionEndIdx;
|
||||
var startTime = Date.now();
|
||||
|
||||
var objs = this.objs;
|
||||
|
||||
do {
|
||||
executionEndIdx = Math.min(argsArrayLen, i + kExecutionTimeCheck);
|
||||
|
||||
for (i; i < executionEndIdx; i++) {
|
||||
if (fnArray[i] !== 'dependency') {
|
||||
this[fnArray[i]].apply(this, argsArray[i]);
|
||||
} else {
|
||||
var deps = argsArray[i];
|
||||
for (var n = 0, nn = deps.length; n < nn; n++) {
|
||||
var depObjId = deps[n];
|
||||
|
||||
// If the promise isn't resolved yet, add the continueCallback
|
||||
// to the promise and bail out.
|
||||
if (!objs.isResolved(depObjId)) {
|
||||
objs.get(depObjId, continueCallback);
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If the entire IRQueue was executed, stop as were done.
|
||||
if (i == argsArrayLen) {
|
||||
return i;
|
||||
}
|
||||
|
||||
// If the execution took longer then a certain amount of time, shedule
|
||||
// to continue exeution after a short delay.
|
||||
// However, this is only possible if a 'continueCallback' is passed in.
|
||||
if (continueCallback && (Date.now() - startTime) > kExecutionTime) {
|
||||
setTimeout(continueCallback, 0);
|
||||
return i;
|
||||
}
|
||||
|
||||
// If the IRQueue isn't executed completly yet OR the execution time
|
||||
// was short enough, do another execution round.
|
||||
} while (true);
|
||||
},
|
||||
|
||||
endDrawing: function canvasGraphicsEndDrawing() {
|
||||
this.ctx.restore();
|
||||
},
|
||||
|
||||
// Graphics state
|
||||
setLineWidth: function canvasGraphicsSetLineWidth(width) {
|
||||
this.ctx.lineWidth = width;
|
||||
},
|
||||
setLineCap: function canvasGraphicsSetLineCap(style) {
|
||||
this.ctx.lineCap = LINE_CAP_STYLES[style];
|
||||
},
|
||||
setLineJoin: function canvasGraphicsSetLineJoin(style) {
|
||||
this.ctx.lineJoin = LINE_JOIN_STYLES[style];
|
||||
},
|
||||
setMiterLimit: function canvasGraphicsSetMiterLimit(limit) {
|
||||
this.ctx.miterLimit = limit;
|
||||
},
|
||||
setDash: function canvasGraphicsSetDash(dashArray, dashPhase) {
|
||||
this.ctx.mozDash = dashArray;
|
||||
this.ctx.mozDashOffset = dashPhase;
|
||||
},
|
||||
setRenderingIntent: function canvasGraphicsSetRenderingIntent(intent) {
|
||||
TODO('set rendering intent: ' + intent);
|
||||
},
|
||||
setFlatness: function canvasGraphicsSetFlatness(flatness) {
|
||||
TODO('set flatness: ' + flatness);
|
||||
},
|
||||
setGState: function canvasGraphicsSetGState(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':
|
||||
this.setRenderingIntent(value);
|
||||
break;
|
||||
case 'FL':
|
||||
this.setFlatness(value);
|
||||
break;
|
||||
case 'Font':
|
||||
this.setFont(state[1], state[2]);
|
||||
break;
|
||||
case 'CA':
|
||||
this.current.strokeAlpha = state[1];
|
||||
break;
|
||||
case 'ca':
|
||||
this.current.fillAlpha = state[1];
|
||||
this.ctx.globalAlpha = state[1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
save: function canvasGraphicsSave() {
|
||||
this.ctx.save();
|
||||
var old = this.current;
|
||||
this.stateStack.push(old);
|
||||
this.current = old.clone();
|
||||
},
|
||||
restore: function canvasGraphicsRestore() {
|
||||
var prev = this.stateStack.pop();
|
||||
if (prev) {
|
||||
this.current = prev;
|
||||
this.ctx.restore();
|
||||
}
|
||||
},
|
||||
transform: function canvasGraphicsTransform(a, b, c, d, e, f) {
|
||||
this.ctx.transform(a, b, c, d, e, f);
|
||||
},
|
||||
|
||||
// Path
|
||||
moveTo: function canvasGraphicsMoveTo(x, y) {
|
||||
this.ctx.moveTo(x, y);
|
||||
this.current.setCurrentPoint(x, y);
|
||||
},
|
||||
lineTo: function canvasGraphicsLineTo(x, y) {
|
||||
this.ctx.lineTo(x, y);
|
||||
this.current.setCurrentPoint(x, y);
|
||||
},
|
||||
curveTo: function canvasGraphicsCurveTo(x1, y1, x2, y2, x3, y3) {
|
||||
this.ctx.bezierCurveTo(x1, y1, x2, y2, x3, y3);
|
||||
this.current.setCurrentPoint(x3, y3);
|
||||
},
|
||||
curveTo2: function canvasGraphicsCurveTo2(x2, y2, x3, y3) {
|
||||
var current = this.current;
|
||||
this.ctx.bezierCurveTo(current.x, current.y, x2, y2, x3, y3);
|
||||
current.setCurrentPoint(x3, y3);
|
||||
},
|
||||
curveTo3: function canvasGraphicsCurveTo3(x1, y1, x3, y3) {
|
||||
this.curveTo(x1, y1, x3, y3, x3, y3);
|
||||
this.current.setCurrentPoint(x3, y3);
|
||||
},
|
||||
closePath: function canvasGraphicsClosePath() {
|
||||
this.ctx.closePath();
|
||||
},
|
||||
rectangle: function canvasGraphicsRectangle(x, y, width, height) {
|
||||
this.ctx.rect(x, y, width, height);
|
||||
},
|
||||
stroke: function canvasGraphicsStroke(consumePath) {
|
||||
consumePath = typeof consumePath !== 'undefined' ? consumePath : true;
|
||||
var ctx = this.ctx;
|
||||
var strokeColor = this.current.strokeColor;
|
||||
// For stroke we want to temporarily change the global alpha to the
|
||||
// stroking alpha.
|
||||
ctx.globalAlpha = this.current.strokeAlpha;
|
||||
if (strokeColor && strokeColor.hasOwnProperty('type') &&
|
||||
strokeColor.type === 'Pattern') {
|
||||
// for patterns, we transform to pattern space, calculate
|
||||
// the pattern, call stroke, and restore to user space
|
||||
ctx.save();
|
||||
ctx.strokeStyle = strokeColor.getPattern(ctx);
|
||||
ctx.stroke();
|
||||
ctx.restore();
|
||||
} else {
|
||||
ctx.stroke();
|
||||
}
|
||||
if (consumePath)
|
||||
this.consumePath();
|
||||
// Restore the global alpha to the fill alpha
|
||||
ctx.globalAlpha = this.current.fillAlpha;
|
||||
},
|
||||
closeStroke: function canvasGraphicsCloseStroke() {
|
||||
this.closePath();
|
||||
this.stroke();
|
||||
},
|
||||
fill: function canvasGraphicsFill(consumePath) {
|
||||
consumePath = typeof consumePath !== 'undefined' ? consumePath : true;
|
||||
var ctx = this.ctx;
|
||||
var fillColor = this.current.fillColor;
|
||||
|
||||
if (fillColor && fillColor.hasOwnProperty('type') &&
|
||||
fillColor.type === 'Pattern') {
|
||||
ctx.save();
|
||||
ctx.fillStyle = fillColor.getPattern(ctx);
|
||||
ctx.fill();
|
||||
ctx.restore();
|
||||
} else {
|
||||
ctx.fill();
|
||||
}
|
||||
if (consumePath)
|
||||
this.consumePath();
|
||||
},
|
||||
eoFill: function canvasGraphicsEoFill() {
|
||||
var savedFillRule = this.setEOFillRule();
|
||||
this.fill();
|
||||
this.restoreFillRule(savedFillRule);
|
||||
},
|
||||
fillStroke: function canvasGraphicsFillStroke() {
|
||||
this.fill(false);
|
||||
this.stroke(false);
|
||||
|
||||
this.consumePath();
|
||||
},
|
||||
eoFillStroke: function canvasGraphicsEoFillStroke() {
|
||||
var savedFillRule = this.setEOFillRule();
|
||||
this.fillStroke();
|
||||
this.restoreFillRule(savedFillRule);
|
||||
},
|
||||
closeFillStroke: function canvasGraphicsCloseFillStroke() {
|
||||
this.closePath();
|
||||
this.fillStroke();
|
||||
},
|
||||
closeEOFillStroke: function canvasGraphicsCloseEOFillStroke() {
|
||||
var savedFillRule = this.setEOFillRule();
|
||||
this.closePath();
|
||||
this.fillStroke();
|
||||
this.restoreFillRule(savedFillRule);
|
||||
},
|
||||
endPath: function canvasGraphicsEndPath() {
|
||||
this.consumePath();
|
||||
},
|
||||
|
||||
// Clipping
|
||||
clip: function canvasGraphicsClip() {
|
||||
this.pendingClip = NORMAL_CLIP;
|
||||
},
|
||||
eoClip: function canvasGraphicsEoClip() {
|
||||
this.pendingClip = EO_CLIP;
|
||||
},
|
||||
|
||||
// Text
|
||||
beginText: function canvasGraphicsBeginText() {
|
||||
this.current.textMatrix = IDENTITY_MATRIX;
|
||||
this.current.x = this.current.lineX = 0;
|
||||
this.current.y = this.current.lineY = 0;
|
||||
},
|
||||
endText: function canvasGraphicsEndText() {
|
||||
},
|
||||
setCharSpacing: function canvasGraphicsSetCharSpacing(spacing) {
|
||||
this.current.charSpacing = spacing;
|
||||
},
|
||||
setWordSpacing: function canvasGraphicsSetWordSpacing(spacing) {
|
||||
this.current.wordSpacing = spacing;
|
||||
},
|
||||
setHScale: function canvasGraphicsSetHScale(scale) {
|
||||
this.current.textHScale = scale / 100;
|
||||
},
|
||||
setLeading: function canvasGraphicsSetLeading(leading) {
|
||||
this.current.leading = -leading;
|
||||
},
|
||||
setFont: function canvasGraphicsSetFont(fontRefName, size) {
|
||||
var fontObj = this.objs.get(fontRefName).fontObj;
|
||||
|
||||
if (!fontObj) {
|
||||
throw 'Can\'t find font for ' + fontRefName;
|
||||
}
|
||||
|
||||
var name = fontObj.loadedName || 'sans-serif';
|
||||
|
||||
this.current.font = fontObj;
|
||||
this.current.fontSize = size;
|
||||
|
||||
var name = fontObj.loadedName || 'sans-serif';
|
||||
var bold = fontObj.black ? (fontObj.bold ? 'bolder' : 'bold') :
|
||||
(fontObj.bold ? 'bold' : 'normal');
|
||||
|
||||
var italic = fontObj.italic ? 'italic' : 'normal';
|
||||
var serif = fontObj.serif ? 'serif' : 'sans-serif';
|
||||
var typeface = '"' + name + '", ' + serif;
|
||||
var rule = italic + ' ' + bold + ' ' + size + 'px ' + typeface;
|
||||
this.ctx.font = rule;
|
||||
},
|
||||
setTextRenderingMode: function canvasGraphicsSetTextRenderingMode(mode) {
|
||||
TODO('text rendering mode: ' + mode);
|
||||
},
|
||||
setTextRise: function canvasGraphicsSetTextRise(rise) {
|
||||
TODO('text rise: ' + rise);
|
||||
},
|
||||
moveText: function canvasGraphicsMoveText(x, y) {
|
||||
this.current.x = this.current.lineX += x;
|
||||
this.current.y = this.current.lineY += y;
|
||||
},
|
||||
setLeadingMoveText: function canvasGraphicsSetLeadingMoveText(x, y) {
|
||||
this.setLeading(-y);
|
||||
this.moveText(x, y);
|
||||
},
|
||||
setTextMatrix: function canvasGraphicsSetTextMatrix(a, b, c, d, e, f) {
|
||||
this.current.textMatrix = [a, b, c, d, e, f];
|
||||
|
||||
this.current.x = this.current.lineX = 0;
|
||||
this.current.y = this.current.lineY = 0;
|
||||
},
|
||||
nextLine: function canvasGraphicsNextLine() {
|
||||
this.moveText(0, this.current.leading);
|
||||
},
|
||||
showText: function canvasGraphicsShowText(text) {
|
||||
var ctx = this.ctx;
|
||||
var current = this.current;
|
||||
var font = current.font;
|
||||
var glyphs = font.charsToGlyphs(text);
|
||||
var fontSize = current.fontSize;
|
||||
var charSpacing = current.charSpacing;
|
||||
var wordSpacing = current.wordSpacing;
|
||||
var textHScale = current.textHScale;
|
||||
var glyphsLength = glyphs.length;
|
||||
if (font.coded) {
|
||||
ctx.save();
|
||||
ctx.transform.apply(ctx, current.textMatrix);
|
||||
ctx.translate(current.x, current.y);
|
||||
|
||||
var fontMatrix = font.fontMatrix || IDENTITY_MATRIX;
|
||||
ctx.scale(1 / textHScale, 1);
|
||||
for (var i = 0; i < glyphsLength; ++i) {
|
||||
|
||||
var glyph = glyphs[i];
|
||||
if (glyph === null) {
|
||||
// word break
|
||||
this.ctx.translate(wordSpacing, 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
this.save();
|
||||
ctx.scale(fontSize, fontSize);
|
||||
ctx.transform.apply(ctx, fontMatrix);
|
||||
this.executeIRQueue(glyph.codeIRQueue);
|
||||
this.restore();
|
||||
|
||||
var transformed = Util.applyTransform([glyph.width, 0], fontMatrix);
|
||||
var width = transformed[0] * fontSize + charSpacing;
|
||||
|
||||
ctx.translate(width, 0);
|
||||
current.x += width;
|
||||
|
||||
}
|
||||
ctx.restore();
|
||||
} else {
|
||||
ctx.save();
|
||||
ctx.transform.apply(ctx, current.textMatrix);
|
||||
ctx.scale(1, -1);
|
||||
ctx.translate(current.x, -1 * current.y);
|
||||
ctx.transform.apply(ctx, font.fontMatrix || IDENTITY_MATRIX);
|
||||
|
||||
ctx.scale(1 / textHScale, 1);
|
||||
|
||||
var width = 0;
|
||||
for (var i = 0; i < glyphsLength; ++i) {
|
||||
var glyph = glyphs[i];
|
||||
if (glyph === null) {
|
||||
// word break
|
||||
width += wordSpacing;
|
||||
continue;
|
||||
}
|
||||
|
||||
var unicode = glyph.unicode;
|
||||
var char = (unicode >= 0x10000) ?
|
||||
String.fromCharCode(0xD800 | ((unicode - 0x10000) >> 10),
|
||||
0xDC00 | (unicode & 0x3FF)) : String.fromCharCode(unicode);
|
||||
|
||||
ctx.fillText(char, width, 0);
|
||||
width += glyph.width * fontSize * 0.001 + charSpacing;
|
||||
}
|
||||
current.x += width;
|
||||
|
||||
ctx.restore();
|
||||
}
|
||||
},
|
||||
|
||||
showSpacedText: function canvasGraphicsShowSpacedText(arr) {
|
||||
var ctx = this.ctx;
|
||||
var current = this.current;
|
||||
var fontSize = current.fontSize;
|
||||
var textHScale = current.textHScale;
|
||||
var arrLength = arr.length;
|
||||
for (var i = 0; i < arrLength; ++i) {
|
||||
var e = arr[i];
|
||||
if (isNum(e)) {
|
||||
current.x -= e * 0.001 * fontSize * textHScale;
|
||||
} else if (isString(e)) {
|
||||
this.showText(e);
|
||||
} else {
|
||||
malformed('TJ array element ' + e + ' is not string or num');
|
||||
}
|
||||
}
|
||||
},
|
||||
nextLineShowText: function canvasGraphicsNextLineShowText(text) {
|
||||
this.nextLine();
|
||||
this.showText(text);
|
||||
},
|
||||
nextLineSetSpacingShowText:
|
||||
function canvasGraphicsNextLineSetSpacingShowText(wordSpacing,
|
||||
charSpacing,
|
||||
text) {
|
||||
this.setWordSpacing(wordSpacing);
|
||||
this.setCharSpacing(charSpacing);
|
||||
this.nextLineShowText(text);
|
||||
},
|
||||
|
||||
// Type3 fonts
|
||||
setCharWidth: function canvasGraphicsSetCharWidth(xWidth, yWidth) {
|
||||
// We can safely ignore this since the width should be the same
|
||||
// as the width in the Widths array.
|
||||
},
|
||||
setCharWidthAndBounds: function canvasGraphicsSetCharWidthAndBounds(xWidth,
|
||||
yWidth,
|
||||
llx,
|
||||
lly,
|
||||
urx,
|
||||
ury) {
|
||||
// TODO According to the spec we're also suppose to ignore any operators
|
||||
// that set color or include images while processing this type3 font.
|
||||
this.rectangle(llx, lly, urx - llx, ury - lly);
|
||||
this.clip();
|
||||
this.endPath();
|
||||
},
|
||||
|
||||
// Color
|
||||
setStrokeColorSpace: function canvasGraphicsSetStrokeColorSpace(raw) {
|
||||
this.current.strokeColorSpace = ColorSpace.fromIR(raw);
|
||||
},
|
||||
setFillColorSpace: function canvasGraphicsSetFillColorSpace(raw) {
|
||||
this.current.fillColorSpace = ColorSpace.fromIR(raw);
|
||||
},
|
||||
setStrokeColor: function canvasGraphicsSetStrokeColor(/*...*/) {
|
||||
var cs = this.current.strokeColorSpace;
|
||||
var color = cs.getRgb(arguments);
|
||||
var color = Util.makeCssRgb.apply(null, cs.getRgb(arguments));
|
||||
this.ctx.strokeStyle = color;
|
||||
this.current.strokeColor = color;
|
||||
},
|
||||
getColorN_IR_Pattern: function canvasGraphicsGetColorN_IR_Pattern(IR, cs) {
|
||||
if (IR[0] == 'TilingPattern') {
|
||||
var args = IR[1];
|
||||
var base = cs.base;
|
||||
var color;
|
||||
if (base) {
|
||||
var baseComps = base.numComps;
|
||||
|
||||
color = [];
|
||||
for (var i = 0; i < baseComps; ++i)
|
||||
color.push(args[i]);
|
||||
|
||||
color = base.getRgb(color);
|
||||
}
|
||||
var pattern = new TilingPattern(IR, color, this.ctx, this.objs);
|
||||
} else if (IR[0] == 'RadialAxial' || IR[0] == 'Dummy') {
|
||||
var pattern = Pattern.shadingFromIR(this.ctx, IR);
|
||||
} else {
|
||||
throw 'Unkown IR type';
|
||||
}
|
||||
return pattern;
|
||||
},
|
||||
setStrokeColorN_IR: function canvasGraphicsSetStrokeColorN(/*...*/) {
|
||||
var cs = this.current.strokeColorSpace;
|
||||
|
||||
if (cs.name == 'Pattern') {
|
||||
this.current.strokeColor = this.getColorN_IR_Pattern(arguments, cs);
|
||||
} else {
|
||||
this.setStrokeColor.apply(this, arguments);
|
||||
}
|
||||
},
|
||||
setFillColor: function canvasGraphicsSetFillColor(/*...*/) {
|
||||
var cs = this.current.fillColorSpace;
|
||||
var color = Util.makeCssRgb.apply(null, cs.getRgb(arguments));
|
||||
this.ctx.fillStyle = color;
|
||||
this.current.fillColor = color;
|
||||
},
|
||||
setFillColorN_IR: function canvasGraphicsSetFillColorN(/*...*/) {
|
||||
var cs = this.current.fillColorSpace;
|
||||
|
||||
if (cs.name == 'Pattern') {
|
||||
this.current.fillColor = this.getColorN_IR_Pattern(arguments, cs);
|
||||
} else {
|
||||
this.setFillColor.apply(this, arguments);
|
||||
}
|
||||
},
|
||||
setStrokeGray: function canvasGraphicsSetStrokeGray(gray) {
|
||||
if (!(this.current.strokeColorSpace instanceof DeviceGrayCS))
|
||||
this.current.strokeColorSpace = new DeviceGrayCS();
|
||||
|
||||
var color = Util.makeCssRgb(gray, gray, gray);
|
||||
this.ctx.strokeStyle = color;
|
||||
this.current.strokeColor = color;
|
||||
},
|
||||
setFillGray: function canvasGraphicsSetFillGray(gray) {
|
||||
if (!(this.current.fillColorSpace instanceof DeviceGrayCS))
|
||||
this.current.fillColorSpace = new DeviceGrayCS();
|
||||
|
||||
var color = Util.makeCssRgb(gray, gray, gray);
|
||||
this.ctx.fillStyle = color;
|
||||
this.current.fillColor = color;
|
||||
},
|
||||
setStrokeRGBColor: function canvasGraphicsSetStrokeRGBColor(r, g, b) {
|
||||
if (!(this.current.strokeColorSpace instanceof DeviceRgbCS))
|
||||
this.current.strokeColorSpace = new DeviceRgbCS();
|
||||
|
||||
var color = Util.makeCssRgb(r, g, b);
|
||||
this.ctx.strokeStyle = color;
|
||||
this.current.strokeColor = color;
|
||||
},
|
||||
setFillRGBColor: function canvasGraphicsSetFillRGBColor(r, g, b) {
|
||||
if (!(this.current.fillColorSpace instanceof DeviceRgbCS))
|
||||
this.current.fillColorSpace = new DeviceRgbCS();
|
||||
|
||||
var color = Util.makeCssRgb(r, g, b);
|
||||
this.ctx.fillStyle = color;
|
||||
this.current.fillColor = color;
|
||||
},
|
||||
setStrokeCMYKColor: function canvasGraphicsSetStrokeCMYKColor(c, m, y, k) {
|
||||
if (!(this.current.strokeColorSpace instanceof DeviceCmykCS))
|
||||
this.current.strokeColorSpace = new DeviceCmykCS();
|
||||
|
||||
var color = Util.makeCssCmyk(c, m, y, k);
|
||||
this.ctx.strokeStyle = color;
|
||||
this.current.strokeColor = color;
|
||||
},
|
||||
setFillCMYKColor: function canvasGraphicsSetFillCMYKColor(c, m, y, k) {
|
||||
if (!(this.current.fillColorSpace instanceof DeviceCmykCS))
|
||||
this.current.fillColorSpace = new DeviceCmykCS();
|
||||
|
||||
var color = Util.makeCssCmyk(c, m, y, k);
|
||||
this.ctx.fillStyle = color;
|
||||
this.current.fillColor = color;
|
||||
},
|
||||
|
||||
shadingFill: function canvasGraphicsShadingFill(patternIR) {
|
||||
var ctx = this.ctx;
|
||||
|
||||
this.save();
|
||||
ctx.fillStyle = Pattern.shadingFromIR(ctx, patternIR);
|
||||
|
||||
var inv = ctx.mozCurrentTransformInverse;
|
||||
if (inv) {
|
||||
var canvas = ctx.canvas;
|
||||
var width = canvas.width;
|
||||
var height = canvas.height;
|
||||
|
||||
var bl = Util.applyTransform([0, 0], inv);
|
||||
var br = Util.applyTransform([0, width], inv);
|
||||
var ul = Util.applyTransform([height, 0], inv);
|
||||
var ur = Util.applyTransform([height, width], inv);
|
||||
|
||||
var x0 = Math.min(bl[0], br[0], ul[0], ur[0]);
|
||||
var y0 = Math.min(bl[1], br[1], ul[1], ur[1]);
|
||||
var x1 = Math.max(bl[0], br[0], ul[0], ur[0]);
|
||||
var y1 = Math.max(bl[1], br[1], ul[1], ur[1]);
|
||||
|
||||
this.ctx.fillRect(x0, y0, x1 - x0, y1 - y0);
|
||||
} else {
|
||||
// HACK to draw the gradient onto an infinite rectangle.
|
||||
// PDF gradients are drawn across the entire image while
|
||||
// Canvas only allows gradients to be drawn in a rectangle
|
||||
// The following bug should allow us to remove this.
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=664884
|
||||
|
||||
this.ctx.fillRect(-1e10, -1e10, 2e10, 2e10);
|
||||
}
|
||||
|
||||
this.restore();
|
||||
},
|
||||
|
||||
// Images
|
||||
beginInlineImage: function canvasGraphicsBeginInlineImage() {
|
||||
error('Should not call beginInlineImage');
|
||||
},
|
||||
beginImageData: function canvasGraphicsBeginImageData() {
|
||||
error('Should not call beginImageData');
|
||||
},
|
||||
|
||||
paintFormXObjectBegin: function canvasGraphicsPaintFormXObjectBegin(matrix,
|
||||
bbox) {
|
||||
this.save();
|
||||
|
||||
if (matrix && isArray(matrix) && 6 == matrix.length)
|
||||
this.transform.apply(this, matrix);
|
||||
|
||||
if (bbox && isArray(bbox) && 4 == bbox.length) {
|
||||
var width = bbox[2] - bbox[0];
|
||||
var height = bbox[3] - bbox[1];
|
||||
this.rectangle(bbox[0], bbox[1], width, height);
|
||||
this.clip();
|
||||
this.endPath();
|
||||
}
|
||||
},
|
||||
|
||||
paintFormXObjectEnd: function canvasGraphicsPaintFormXObjectEnd() {
|
||||
this.restore();
|
||||
},
|
||||
|
||||
paintJpegXObject: function canvasGraphicsPaintJpegXObject(objId, w, h) {
|
||||
var image = this.objs.get(objId);
|
||||
if (!image) {
|
||||
error('Dependent image isn\'t ready yet');
|
||||
}
|
||||
|
||||
this.save();
|
||||
|
||||
var ctx = this.ctx;
|
||||
// scale the image to the unit square
|
||||
ctx.scale(1 / w, -1 / h);
|
||||
|
||||
var domImage = image.getImage();
|
||||
ctx.drawImage(domImage, 0, 0, domImage.width, domImage.height,
|
||||
0, -h, w, h);
|
||||
|
||||
this.restore();
|
||||
},
|
||||
|
||||
paintImageMaskXObject: function canvasGraphicsPaintImageMaskXObject(
|
||||
imgArray, inverseDecode, width, height) {
|
||||
function applyStencilMask(buffer, inverseDecode) {
|
||||
var imgArrayPos = 0;
|
||||
var i, j, mask, buf;
|
||||
// removing making non-masked pixels transparent
|
||||
var bufferPos = 3; // alpha component offset
|
||||
for (i = 0; i < height; i++) {
|
||||
mask = 0;
|
||||
for (j = 0; j < width; j++) {
|
||||
if (!mask) {
|
||||
buf = imgArray[imgArrayPos++];
|
||||
mask = 128;
|
||||
}
|
||||
if (!(buf & mask) == inverseDecode) {
|
||||
buffer[bufferPos] = 0;
|
||||
}
|
||||
bufferPos += 4;
|
||||
mask >>= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.save();
|
||||
|
||||
var ctx = this.ctx;
|
||||
var w = width, h = height;
|
||||
// scale the image to the unit square
|
||||
ctx.scale(1 / w, -1 / h);
|
||||
|
||||
var tmpCanvas = new this.ScratchCanvas(w, h);
|
||||
var tmpCtx = tmpCanvas.getContext('2d');
|
||||
|
||||
var fillColor = this.current.fillColor;
|
||||
tmpCtx.fillStyle = (fillColor && fillColor.hasOwnProperty('type') &&
|
||||
fillColor.type === 'Pattern') ?
|
||||
fillColor.getPattern(tmpCtx) : fillColor;
|
||||
tmpCtx.fillRect(0, 0, w, h);
|
||||
|
||||
var imgData = tmpCtx.getImageData(0, 0, w, h);
|
||||
var pixels = imgData.data;
|
||||
|
||||
applyStencilMask(pixels, inverseDecode);
|
||||
|
||||
tmpCtx.putImageData(imgData, 0, 0);
|
||||
ctx.drawImage(tmpCanvas, 0, -h);
|
||||
this.restore();
|
||||
},
|
||||
|
||||
paintImageXObject: function canvasGraphicsPaintImageXObject(imgData) {
|
||||
this.save();
|
||||
var ctx = this.ctx;
|
||||
var w = imgData.width;
|
||||
var h = imgData.height;
|
||||
// scale the image to the unit square
|
||||
ctx.scale(1 / w, -1 / h);
|
||||
|
||||
var tmpCanvas = new this.ScratchCanvas(w, h);
|
||||
var tmpCtx = tmpCanvas.getContext('2d');
|
||||
var tmpImgData;
|
||||
|
||||
// Some browsers can set an UInt8Array directly as imageData, some
|
||||
// can't. As long as we don't have proper feature detection, just
|
||||
// copy over each pixel and set the imageData that way.
|
||||
tmpImgData = tmpCtx.getImageData(0, 0, w, h);
|
||||
|
||||
// Copy over the imageData.
|
||||
var tmpImgDataPixels = tmpImgData.data;
|
||||
var len = tmpImgDataPixels.length;
|
||||
|
||||
while (len--) {
|
||||
tmpImgDataPixels[len] = imgData.data[len];
|
||||
}
|
||||
|
||||
tmpCtx.putImageData(tmpImgData, 0, 0);
|
||||
ctx.drawImage(tmpCanvas, 0, -h);
|
||||
this.restore();
|
||||
},
|
||||
|
||||
// Marked content
|
||||
|
||||
markPoint: function canvasGraphicsMarkPoint(tag) {
|
||||
TODO('Marked content');
|
||||
},
|
||||
markPointProps: function canvasGraphicsMarkPointProps(tag, properties) {
|
||||
TODO('Marked content');
|
||||
},
|
||||
beginMarkedContent: function canvasGraphicsBeginMarkedContent(tag) {
|
||||
TODO('Marked content');
|
||||
},
|
||||
beginMarkedContentProps:
|
||||
function canvasGraphicsBeginMarkedContentProps(tag, properties) {
|
||||
TODO('Marked content');
|
||||
},
|
||||
endMarkedContent: function canvasGraphicsEndMarkedContent() {
|
||||
TODO('Marked content');
|
||||
},
|
||||
|
||||
// Compatibility
|
||||
|
||||
beginCompat: function canvasGraphicsBeginCompat() {
|
||||
TODO('ignore undefined operators (should we do that anyway?)');
|
||||
},
|
||||
endCompat: function canvasGraphicsEndCompat() {
|
||||
TODO('stop ignoring undefined operators');
|
||||
},
|
||||
|
||||
// Helper functions
|
||||
|
||||
consumePath: function canvasGraphicsConsumePath() {
|
||||
if (this.pendingClip) {
|
||||
var savedFillRule = null;
|
||||
if (this.pendingClip == EO_CLIP)
|
||||
savedFillRule = this.setEOFillRule();
|
||||
|
||||
this.ctx.clip();
|
||||
|
||||
this.pendingClip = null;
|
||||
if (savedFillRule !== null)
|
||||
this.restoreFillRule(savedFillRule);
|
||||
}
|
||||
this.ctx.beginPath();
|
||||
},
|
||||
// We generally keep the canvas context set for
|
||||
// nonzero-winding, and just set evenodd for the operations
|
||||
// that need them.
|
||||
setEOFillRule: function canvasGraphicsSetEOFillRule() {
|
||||
var savedFillRule = this.ctx.mozFillRule;
|
||||
this.ctx.mozFillRule = 'evenodd';
|
||||
return savedFillRule;
|
||||
},
|
||||
restoreFillRule: function canvasGraphicsRestoreFillRule(rule) {
|
||||
this.ctx.mozFillRule = rule;
|
||||
}
|
||||
};
|
||||
|
||||
return constructor;
|
||||
})();
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
|
||||
|
||||
'use strict';
|
||||
|
||||
var ISOAdobeCharset = [
|
||||
'.notdef', 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar',
|
||||
'percent', 'ampersand', 'quoteright', 'parenleft', 'parenright',
|
||||
'asterisk', 'plus', 'comma', 'hyphen', 'period', 'slash', 'zero',
|
||||
'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight',
|
||||
'nine', 'colon', 'semicolon', 'less', 'equal', 'greater', 'question',
|
||||
'at', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
|
||||
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
|
||||
'bracketleft', 'backslash', 'bracketright', 'asciicircum', 'underscore',
|
||||
'quoteleft', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
|
||||
'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
|
||||
'braceleft', 'bar', 'braceright', 'asciitilde', 'exclamdown', 'cent',
|
||||
'sterling', 'fraction', 'yen', 'florin', 'section', 'currency',
|
||||
'quotesingle', 'quotedblleft', 'guillemotleft', 'guilsinglleft',
|
||||
'guilsinglright', 'fi', 'fl', 'endash', 'dagger', 'daggerdbl',
|
||||
'periodcentered', 'paragraph', 'bullet', 'quotesinglbase',
|
||||
'quotedblbase', 'quotedblright', 'guillemotright', 'ellipsis',
|
||||
'perthousand', 'questiondown', 'grave', 'acute', 'circumflex', 'tilde',
|
||||
'macron', 'breve', 'dotaccent', 'dieresis', 'ring', 'cedilla',
|
||||
'hungarumlaut', 'ogonek', 'caron', 'emdash', 'AE', 'ordfeminine',
|
||||
'Lslash', 'Oslash', 'OE', 'ordmasculine', 'ae', 'dotlessi', 'lslash',
|
||||
'oslash', 'oe', 'germandbls', 'onesuperior', 'logicalnot', 'mu',
|
||||
'trademark', 'Eth', 'onehalf', 'plusminus', 'Thorn', 'onequarter',
|
||||
'divide', 'brokenbar', 'degree', 'thorn', 'threequarters', 'twosuperior',
|
||||
'registered', 'minus', 'eth', 'multiply', 'threesuperior', 'copyright',
|
||||
'Aacute', 'Acircumflex', 'Adieresis', 'Agrave', 'Aring', 'Atilde',
|
||||
'Ccedilla', 'Eacute', 'Ecircumflex', 'Edieresis', 'Egrave', 'Iacute',
|
||||
'Icircumflex', 'Idieresis', 'Igrave', 'Ntilde', 'Oacute', 'Ocircumflex',
|
||||
'Odieresis', 'Ograve', 'Otilde', 'Scaron', 'Uacute', 'Ucircumflex',
|
||||
'Udieresis', 'Ugrave', 'Yacute', 'Ydieresis', 'Zcaron', 'aacute',
|
||||
'acircumflex', 'adieresis', 'agrave', 'aring', 'atilde', 'ccedilla',
|
||||
'eacute', 'ecircumflex', 'edieresis', 'egrave', 'iacute', 'icircumflex',
|
||||
'idieresis', 'igrave', 'ntilde', 'oacute', 'ocircumflex', 'odieresis',
|
||||
'ograve', 'otilde', 'scaron', 'uacute', 'ucircumflex', 'udieresis',
|
||||
'ugrave', 'yacute', 'ydieresis', 'zcaron'
|
||||
];
|
||||
|
||||
var ExpertCharset = [
|
||||
'.notdef', 'space', 'exclamsmall', 'Hungarumlautsmall', 'dollaroldstyle',
|
||||
'dollarsuperior', 'ampersandsmall', 'Acutesmall', 'parenleftsuperior',
|
||||
'parenrightsuperior', 'twodotenleader', 'onedotenleader', 'comma',
|
||||
'hyphen', 'period', 'fraction', 'zerooldstyle', 'oneoldstyle',
|
||||
'twooldstyle', 'threeoldstyle', 'fouroldstyle', 'fiveoldstyle',
|
||||
'sixoldstyle', 'sevenoldstyle', 'eightoldstyle', 'nineoldstyle',
|
||||
'colon', 'semicolon', 'commasuperior', 'threequartersemdash',
|
||||
'periodsuperior', 'questionsmall', 'asuperior', 'bsuperior',
|
||||
'centsuperior', 'dsuperior', 'esuperior', 'isuperior', 'lsuperior',
|
||||
'msuperior', 'nsuperior', 'osuperior', 'rsuperior', 'ssuperior',
|
||||
'tsuperior', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'parenleftinferior',
|
||||
'parenrightinferior', 'Circumflexsmall', 'hyphensuperior', 'Gravesmall',
|
||||
'Asmall', 'Bsmall', 'Csmall', 'Dsmall', 'Esmall', 'Fsmall', 'Gsmall',
|
||||
'Hsmall', 'Ismall', 'Jsmall', 'Ksmall', 'Lsmall', 'Msmall', 'Nsmall',
|
||||
'Osmall', 'Psmall', 'Qsmall', 'Rsmall', 'Ssmall', 'Tsmall', 'Usmall',
|
||||
'Vsmall', 'Wsmall', 'Xsmall', 'Ysmall', 'Zsmall', 'colonmonetary',
|
||||
'onefitted', 'rupiah', 'Tildesmall', 'exclamdownsmall', 'centoldstyle',
|
||||
'Lslashsmall', 'Scaronsmall', 'Zcaronsmall', 'Dieresissmall',
|
||||
'Brevesmall', 'Caronsmall', 'Dotaccentsmall', 'Macronsmall',
|
||||
'figuredash', 'hypheninferior', 'Ogoneksmall', 'Ringsmall',
|
||||
'Cedillasmall', 'onequarter', 'onehalf', 'threequarters',
|
||||
'questiondownsmall', 'oneeighth', 'threeeighths', 'fiveeighths',
|
||||
'seveneighths', 'onethird', 'twothirds', 'zerosuperior', 'onesuperior',
|
||||
'twosuperior', 'threesuperior', 'foursuperior', 'fivesuperior',
|
||||
'sixsuperior', 'sevensuperior', 'eightsuperior', 'ninesuperior',
|
||||
'zeroinferior', 'oneinferior', 'twoinferior', 'threeinferior',
|
||||
'fourinferior', 'fiveinferior', 'sixinferior', 'seveninferior',
|
||||
'eightinferior', 'nineinferior', 'centinferior', 'dollarinferior',
|
||||
'periodinferior', 'commainferior', 'Agravesmall', 'Aacutesmall',
|
||||
'Acircumflexsmall', 'Atildesmall', 'Adieresissmall', 'Aringsmall',
|
||||
'AEsmall', 'Ccedillasmall', 'Egravesmall', 'Eacutesmall',
|
||||
'Ecircumflexsmall', 'Edieresissmall', 'Igravesmall', 'Iacutesmall',
|
||||
'Icircumflexsmall', 'Idieresissmall', 'Ethsmall', 'Ntildesmall',
|
||||
'Ogravesmall', 'Oacutesmall', 'Ocircumflexsmall', 'Otildesmall',
|
||||
'Odieresissmall', 'OEsmall', 'Oslashsmall', 'Ugravesmall', 'Uacutesmall',
|
||||
'Ucircumflexsmall', 'Udieresissmall', 'Yacutesmall', 'Thornsmall',
|
||||
'Ydieresissmall'
|
||||
];
|
||||
|
||||
var ExpertSubsetCharset = [
|
||||
'.notdef', 'space', 'dollaroldstyle', 'dollarsuperior',
|
||||
'parenleftsuperior', 'parenrightsuperior', 'twodotenleader',
|
||||
'onedotenleader', 'comma', 'hyphen', 'period', 'fraction',
|
||||
'zerooldstyle', 'oneoldstyle', 'twooldstyle', 'threeoldstyle',
|
||||
'fouroldstyle', 'fiveoldstyle', 'sixoldstyle', 'sevenoldstyle',
|
||||
'eightoldstyle', 'nineoldstyle', 'colon', 'semicolon', 'commasuperior',
|
||||
'threequartersemdash', 'periodsuperior', 'asuperior', 'bsuperior',
|
||||
'centsuperior', 'dsuperior', 'esuperior', 'isuperior', 'lsuperior',
|
||||
'msuperior', 'nsuperior', 'osuperior', 'rsuperior', 'ssuperior',
|
||||
'tsuperior', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'parenleftinferior',
|
||||
'parenrightinferior', 'hyphensuperior', 'colonmonetary', 'onefitted',
|
||||
'rupiah', 'centoldstyle', 'figuredash', 'hypheninferior', 'onequarter',
|
||||
'onehalf', 'threequarters', 'oneeighth', 'threeeighths', 'fiveeighths',
|
||||
'seveneighths', 'onethird', 'twothirds', 'zerosuperior', 'onesuperior',
|
||||
'twosuperior', 'threesuperior', 'foursuperior', 'fivesuperior',
|
||||
'sixsuperior', 'sevensuperior', 'eightsuperior', 'ninesuperior',
|
||||
'zeroinferior', 'oneinferior', 'twoinferior', 'threeinferior',
|
||||
'fourinferior', 'fiveinferior', 'sixinferior', 'seveninferior',
|
||||
'eightinferior', 'nineinferior', 'centinferior', 'dollarinferior',
|
||||
'periodinferior', 'commainferior'
|
||||
];
|
||||
|
|
@ -0,0 +1,411 @@
|
|||
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
|
||||
|
||||
'use strict';
|
||||
|
||||
var ColorSpace = (function colorSpaceColorSpace() {
|
||||
// Constructor should define this.numComps, this.defaultColor, this.name
|
||||
function constructor() {
|
||||
error('should not call ColorSpace constructor');
|
||||
}
|
||||
|
||||
constructor.prototype = {
|
||||
// Input: array of size numComps representing color component values
|
||||
// Output: array of rgb values, each value ranging from [0.1]
|
||||
getRgb: function colorSpaceGetRgb(color) {
|
||||
error('Should not call ColorSpace.getRgb: ' + color);
|
||||
},
|
||||
// Input: Uint8Array of component values, each value scaled to [0,255]
|
||||
// Output: Uint8Array of rgb values, each value scaled to [0,255]
|
||||
getRgbBuffer: function colorSpaceGetRgbBuffer(input) {
|
||||
error('Should not call ColorSpace.getRgbBuffer: ' + input);
|
||||
}
|
||||
};
|
||||
|
||||
constructor.parse = function colorSpaceParse(cs, xref, res) {
|
||||
var IR = constructor.parseToIR(cs, xref, res);
|
||||
if (IR instanceof AlternateCS)
|
||||
return IR;
|
||||
|
||||
return constructor.fromIR(IR);
|
||||
};
|
||||
|
||||
constructor.fromIR = function colorSpaceFromIR(IR) {
|
||||
var name = isArray(IR) ? IR[0] : IR;
|
||||
|
||||
switch (name) {
|
||||
case 'DeviceGrayCS':
|
||||
return new DeviceGrayCS();
|
||||
case 'DeviceRgbCS':
|
||||
return new DeviceRgbCS();
|
||||
case 'DeviceCmykCS':
|
||||
return new DeviceCmykCS();
|
||||
case 'PatternCS':
|
||||
var basePatternCS = IR[1];
|
||||
if (basePatternCS)
|
||||
basePatternCS = ColorSpace.fromIR(basePatternCS);
|
||||
return new PatternCS(basePatternCS);
|
||||
case 'IndexedCS':
|
||||
var baseIndexedCS = IR[1];
|
||||
var hiVal = IR[2];
|
||||
var lookup = IR[3];
|
||||
return new IndexedCS(ColorSpace.fromIR(baseIndexedCS), hiVal, lookup);
|
||||
case 'AlternateCS':
|
||||
var numComps = IR[1];
|
||||
var alt = IR[2];
|
||||
var tintFnIR = IR[3];
|
||||
|
||||
return new AlternateCS(numComps, ColorSpace.fromIR(alt),
|
||||
PDFFunction.fromIR(tintFnIR));
|
||||
default:
|
||||
error('Unkown name ' + name);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
constructor.parseToIR = function colorSpaceParseToIR(cs, xref, res) {
|
||||
if (isName(cs)) {
|
||||
var colorSpaces = xref.fetchIfRef(res.get('ColorSpace'));
|
||||
if (isDict(colorSpaces)) {
|
||||
var refcs = colorSpaces.get(cs.name);
|
||||
if (refcs)
|
||||
cs = refcs;
|
||||
}
|
||||
}
|
||||
|
||||
cs = xref.fetchIfRef(cs);
|
||||
var mode;
|
||||
|
||||
if (isName(cs)) {
|
||||
mode = cs.name;
|
||||
this.mode = mode;
|
||||
|
||||
switch (mode) {
|
||||
case 'DeviceGray':
|
||||
case 'G':
|
||||
return 'DeviceGrayCS';
|
||||
case 'DeviceRGB':
|
||||
case 'RGB':
|
||||
return 'DeviceRgbCS';
|
||||
case 'DeviceCMYK':
|
||||
case 'CMYK':
|
||||
return 'DeviceCmykCS';
|
||||
case 'Pattern':
|
||||
return ['PatternCS', null];
|
||||
default:
|
||||
error('unrecognized colorspace ' + mode);
|
||||
}
|
||||
} else if (isArray(cs)) {
|
||||
mode = cs[0].name;
|
||||
this.mode = mode;
|
||||
|
||||
switch (mode) {
|
||||
case 'DeviceGray':
|
||||
case 'G':
|
||||
return 'DeviceGrayCS';
|
||||
case 'DeviceRGB':
|
||||
case 'RGB':
|
||||
return 'DeviceRgbCS';
|
||||
case 'DeviceCMYK':
|
||||
case 'CMYK':
|
||||
return 'DeviceCmykCS';
|
||||
case 'CalGray':
|
||||
return 'DeviceGrayCS';
|
||||
case 'CalRGB':
|
||||
return 'DeviceRgbCS';
|
||||
case 'ICCBased':
|
||||
var stream = xref.fetchIfRef(cs[1]);
|
||||
var dict = stream.dict;
|
||||
var numComps = dict.get('N');
|
||||
if (numComps == 1)
|
||||
return 'DeviceGrayCS';
|
||||
if (numComps == 3)
|
||||
return 'DeviceRgbCS';
|
||||
if (numComps == 4)
|
||||
return 'DeviceCmykCS';
|
||||
break;
|
||||
case 'Pattern':
|
||||
var basePatternCS = cs[1];
|
||||
if (basePatternCS)
|
||||
basePatternCS = ColorSpace.parseToIR(basePatternCS, xref, res);
|
||||
return ['PatternCS', basePatternCS];
|
||||
case 'Indexed':
|
||||
var baseIndexedCS = ColorSpace.parseToIR(cs[1], xref, res);
|
||||
var hiVal = cs[2] + 1;
|
||||
var lookup = xref.fetchIfRef(cs[3]);
|
||||
return ['IndexedCS', baseIndexedCS, hiVal, lookup];
|
||||
case 'Separation':
|
||||
case 'DeviceN':
|
||||
var name = cs[1];
|
||||
var numComps = 1;
|
||||
if (isName(name))
|
||||
numComps = 1;
|
||||
else if (isArray(name))
|
||||
numComps = name.length;
|
||||
var alt = ColorSpace.parseToIR(cs[2], xref, res);
|
||||
var tintFnIR = PDFFunction.getIR(xref, xref.fetchIfRef(cs[3]));
|
||||
return ['AlternateCS', numComps, alt, tintFnIR];
|
||||
case 'Lab':
|
||||
default:
|
||||
error('unimplemented color space object "' + mode + '"');
|
||||
}
|
||||
} else {
|
||||
error('unrecognized color space object: "' + cs + '"');
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
return constructor;
|
||||
})();
|
||||
|
||||
/**
|
||||
* Alternate color space handles both Separation and DeviceN color spaces. A
|
||||
* Separation color space is actually just a DeviceN with one color component.
|
||||
* Both color spaces use a tinting function to convert colors to a base color
|
||||
* space.
|
||||
*/
|
||||
var AlternateCS = (function alternateCS() {
|
||||
function constructor(numComps, base, tintFn) {
|
||||
this.name = 'Alternate';
|
||||
this.numComps = numComps;
|
||||
this.defaultColor = [];
|
||||
for (var i = 0; i < numComps; ++i)
|
||||
this.defaultColor.push(1);
|
||||
this.base = base;
|
||||
this.tintFn = tintFn;
|
||||
}
|
||||
|
||||
constructor.prototype = {
|
||||
getRgb: function altcs_getRgb(color) {
|
||||
var tinted = this.tintFn(color);
|
||||
return this.base.getRgb(tinted);
|
||||
},
|
||||
getRgbBuffer: function altcs_getRgbBuffer(input, bits) {
|
||||
var tintFn = this.tintFn;
|
||||
var base = this.base;
|
||||
var scale = 1 / ((1 << bits) - 1);
|
||||
var length = input.length;
|
||||
var pos = 0;
|
||||
var baseNumComps = base.numComps;
|
||||
var baseBuf = new Uint8Array(baseNumComps * length);
|
||||
var numComps = this.numComps;
|
||||
var scaled = new Array(numComps);
|
||||
|
||||
for (var i = 0; i < length; i += numComps) {
|
||||
for (var z = 0; z < numComps; ++z)
|
||||
scaled[z] = input[i + z] * scale;
|
||||
|
||||
var tinted = tintFn(scaled);
|
||||
for (var j = 0; j < baseNumComps; ++j)
|
||||
baseBuf[pos++] = 255 * tinted[j];
|
||||
}
|
||||
return base.getRgbBuffer(baseBuf, 8);
|
||||
}
|
||||
};
|
||||
|
||||
return constructor;
|
||||
})();
|
||||
|
||||
var PatternCS = (function patternCS() {
|
||||
function constructor(baseCS) {
|
||||
this.name = 'Pattern';
|
||||
this.base = baseCS;
|
||||
}
|
||||
constructor.prototype = {};
|
||||
|
||||
return constructor;
|
||||
})();
|
||||
|
||||
var IndexedCS = (function indexedCS() {
|
||||
function constructor(base, highVal, lookup) {
|
||||
this.name = 'Indexed';
|
||||
this.numComps = 1;
|
||||
this.defaultColor = [0];
|
||||
this.base = base;
|
||||
this.highVal = highVal;
|
||||
|
||||
var baseNumComps = base.numComps;
|
||||
var length = baseNumComps * highVal;
|
||||
var lookupArray = new Uint8Array(length);
|
||||
|
||||
if (isStream(lookup)) {
|
||||
var bytes = lookup.getBytes(length);
|
||||
lookupArray.set(bytes);
|
||||
} else if (isString(lookup)) {
|
||||
for (var i = 0; i < length; ++i)
|
||||
lookupArray[i] = lookup.charCodeAt(i);
|
||||
} else {
|
||||
error('Unrecognized lookup table: ' + lookup);
|
||||
}
|
||||
this.lookup = lookupArray;
|
||||
}
|
||||
|
||||
constructor.prototype = {
|
||||
getRgb: function indexcs_getRgb(color) {
|
||||
var numComps = this.base.numComps;
|
||||
var start = color[0] * numComps;
|
||||
var c = [];
|
||||
|
||||
for (var i = start, ii = start + numComps; i < ii; ++i)
|
||||
c.push(this.lookup[i]);
|
||||
|
||||
return this.base.getRgb(c);
|
||||
},
|
||||
getRgbBuffer: function indexcs_getRgbBuffer(input) {
|
||||
var base = this.base;
|
||||
var numComps = base.numComps;
|
||||
var lookup = this.lookup;
|
||||
var length = input.length;
|
||||
var baseBuf = new Uint8Array(length * numComps);
|
||||
var baseBufPos = 0;
|
||||
|
||||
for (var i = 0; i < length; ++i) {
|
||||
var lookupPos = input[i] * numComps;
|
||||
for (var j = 0; j < numComps; ++j) {
|
||||
baseBuf[baseBufPos++] = lookup[lookupPos + j];
|
||||
}
|
||||
}
|
||||
|
||||
return base.getRgbBuffer(baseBuf, 8);
|
||||
}
|
||||
};
|
||||
return constructor;
|
||||
})();
|
||||
|
||||
var DeviceGrayCS = (function deviceGrayCS() {
|
||||
function constructor() {
|
||||
this.name = 'DeviceGray';
|
||||
this.numComps = 1;
|
||||
this.defaultColor = [0];
|
||||
}
|
||||
|
||||
constructor.prototype = {
|
||||
getRgb: function graycs_getRgb(color) {
|
||||
var c = color[0];
|
||||
return [c, c, c];
|
||||
},
|
||||
getRgbBuffer: function graycs_getRgbBuffer(input, bits) {
|
||||
var scale = 255 / ((1 << bits) - 1);
|
||||
var length = input.length;
|
||||
var rgbBuf = new Uint8Array(length * 3);
|
||||
for (var i = 0, j = 0; i < length; ++i) {
|
||||
var c = (scale * input[i]) | 0;
|
||||
rgbBuf[j++] = c;
|
||||
rgbBuf[j++] = c;
|
||||
rgbBuf[j++] = c;
|
||||
}
|
||||
return rgbBuf;
|
||||
}
|
||||
};
|
||||
return constructor;
|
||||
})();
|
||||
|
||||
var DeviceRgbCS = (function deviceRgbCS() {
|
||||
function constructor() {
|
||||
this.name = 'DeviceRGB';
|
||||
this.numComps = 3;
|
||||
this.defaultColor = [0, 0, 0];
|
||||
}
|
||||
constructor.prototype = {
|
||||
getRgb: function rgbcs_getRgb(color) {
|
||||
return color;
|
||||
},
|
||||
getRgbBuffer: function rgbcs_getRgbBuffer(input, bits) {
|
||||
if (bits == 8)
|
||||
return input;
|
||||
var scale = 255 / ((1 << bits) - 1);
|
||||
var i, length = input.length;
|
||||
var rgbBuf = new Uint8Array(length);
|
||||
for (i = 0; i < length; ++i)
|
||||
rgbBuf[i] = (scale * input[i]) | 0;
|
||||
return rgbBuf;
|
||||
}
|
||||
};
|
||||
return constructor;
|
||||
})();
|
||||
|
||||
var DeviceCmykCS = (function deviceCmykCS() {
|
||||
function constructor() {
|
||||
this.name = 'DeviceCMYK';
|
||||
this.numComps = 4;
|
||||
this.defaultColor = [0, 0, 0, 1];
|
||||
}
|
||||
constructor.prototype = {
|
||||
getRgb: function cmykcs_getRgb(color) {
|
||||
var c = color[0], m = color[1], y = color[2], k = color[3];
|
||||
var c1 = 1 - c, m1 = 1 - m, y1 = 1 - y, k1 = 1 - k;
|
||||
|
||||
var x, r, g, b;
|
||||
// this is a matrix multiplication, unrolled for performance
|
||||
// code is taken from the poppler implementation
|
||||
x = c1 * m1 * y1 * k1; // 0 0 0 0
|
||||
r = g = b = x;
|
||||
x = c1 * m1 * y1 * k; // 0 0 0 1
|
||||
r += 0.1373 * x;
|
||||
g += 0.1216 * x;
|
||||
b += 0.1255 * x;
|
||||
x = c1 * m1 * y * k1; // 0 0 1 0
|
||||
r += x;
|
||||
g += 0.9490 * x;
|
||||
x = c1 * m1 * y * k; // 0 0 1 1
|
||||
r += 0.1098 * x;
|
||||
g += 0.1020 * x;
|
||||
x = c1 * m * y1 * k1; // 0 1 0 0
|
||||
r += 0.9255 * x;
|
||||
b += 0.5490 * x;
|
||||
x = c1 * m * y1 * k; // 0 1 0 1
|
||||
r += 0.1412 * x;
|
||||
x = c1 * m * y * k1; // 0 1 1 0
|
||||
r += 0.9294 * x;
|
||||
g += 0.1098 * x;
|
||||
b += 0.1412 * x;
|
||||
x = c1 * m * y * k; // 0 1 1 1
|
||||
r += 0.1333 * x;
|
||||
x = c * m1 * y1 * k1; // 1 0 0 0
|
||||
g += 0.6784 * x;
|
||||
b += 0.9373 * x;
|
||||
x = c * m1 * y1 * k; // 1 0 0 1
|
||||
g += 0.0588 * x;
|
||||
b += 0.1412 * x;
|
||||
x = c * m1 * y * k1; // 1 0 1 0
|
||||
g += 0.6510 * x;
|
||||
b += 0.3137 * x;
|
||||
x = c * m1 * y * k; // 1 0 1 1
|
||||
g += 0.0745 * x;
|
||||
x = c * m * y1 * k1; // 1 1 0 0
|
||||
r += 0.1804 * x;
|
||||
g += 0.1922 * x;
|
||||
b += 0.5725 * x;
|
||||
x = c * m * y1 * k; // 1 1 0 1
|
||||
b += 0.0078 * x;
|
||||
x = c * m * y * k1; // 1 1 1 0
|
||||
r += 0.2118 * x;
|
||||
g += 0.2119 * x;
|
||||
b += 0.2235 * x;
|
||||
|
||||
return [r, g, b];
|
||||
},
|
||||
getRgbBuffer: function cmykcs_getRgbBuffer(colorBuf, bits) {
|
||||
var scale = 1 / ((1 << bits) - 1);
|
||||
var length = colorBuf.length / 4;
|
||||
var rgbBuf = new Uint8Array(length * 3);
|
||||
var rgbBufPos = 0;
|
||||
var colorBufPos = 0;
|
||||
|
||||
for (var i = 0; i < length; i++) {
|
||||
var cmyk = [];
|
||||
for (var j = 0; j < 4; ++j)
|
||||
cmyk.push(scale * colorBuf[colorBufPos++]);
|
||||
|
||||
var rgb = this.getRgb(cmyk);
|
||||
for (var j = 0; j < 3; ++j)
|
||||
rgbBuf[rgbBufPos++] = Math.round(rgb[j] * 255);
|
||||
}
|
||||
|
||||
return rgbBuf;
|
||||
}
|
||||
};
|
||||
|
||||
return constructor;
|
||||
})();
|
||||
|
|
@ -0,0 +1,652 @@
|
|||
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
|
||||
|
||||
'use strict';
|
||||
|
||||
var globalScope = (typeof window === 'undefined') ? this : window;
|
||||
|
||||
var ERRORS = 0, WARNINGS = 1, TODOS = 5;
|
||||
var verbosity = WARNINGS;
|
||||
|
||||
// The global PDFJS object exposes the API
|
||||
// In production, it will be declared outside a global wrapper
|
||||
// In development, it will be declared here
|
||||
if (!globalScope.PDFJS) {
|
||||
globalScope.PDFJS = {};
|
||||
}
|
||||
|
||||
// getPdf()
|
||||
// Convenience function to perform binary Ajax GET
|
||||
// Usage: getPdf('http://...', callback)
|
||||
// getPdf({
|
||||
// url:String ,
|
||||
// [,progress:Function, error:Function]
|
||||
// },
|
||||
// callback)
|
||||
function getPdf(arg, callback) {
|
||||
var params = arg;
|
||||
if (typeof arg === 'string')
|
||||
params = { url: arg };
|
||||
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', params.url);
|
||||
xhr.mozResponseType = xhr.responseType = 'arraybuffer';
|
||||
xhr.expected = (document.URL.indexOf('file:') === 0) ? 0 : 200;
|
||||
|
||||
if ('progress' in params)
|
||||
xhr.onprogress = params.progress || undefined;
|
||||
|
||||
if ('error' in params)
|
||||
xhr.onerror = params.error || undefined;
|
||||
|
||||
xhr.onreadystatechange = function getPdfOnreadystatechange() {
|
||||
if (xhr.readyState === 4 && xhr.status === xhr.expected) {
|
||||
var data = (xhr.mozResponseArrayBuffer || xhr.mozResponse ||
|
||||
xhr.responseArrayBuffer || xhr.response);
|
||||
callback(data);
|
||||
}
|
||||
};
|
||||
xhr.send(null);
|
||||
}
|
||||
globalScope.PDFJS.getPdf = getPdf;
|
||||
|
||||
var Page = (function pagePage() {
|
||||
function constructor(xref, pageNumber, pageDict, ref) {
|
||||
this.pageNumber = pageNumber;
|
||||
this.pageDict = pageDict;
|
||||
this.stats = {
|
||||
create: Date.now(),
|
||||
compile: 0.0,
|
||||
fonts: 0.0,
|
||||
images: 0.0,
|
||||
render: 0.0
|
||||
};
|
||||
this.xref = xref;
|
||||
this.ref = ref;
|
||||
}
|
||||
|
||||
constructor.prototype = {
|
||||
getPageProp: function pageGetPageProp(key) {
|
||||
return this.xref.fetchIfRef(this.pageDict.get(key));
|
||||
},
|
||||
inheritPageProp: function pageInheritPageProp(key) {
|
||||
var dict = this.pageDict;
|
||||
var obj = dict.get(key);
|
||||
while (obj === undefined) {
|
||||
dict = this.xref.fetchIfRef(dict.get('Parent'));
|
||||
if (!dict)
|
||||
break;
|
||||
obj = dict.get(key);
|
||||
}
|
||||
return obj;
|
||||
},
|
||||
get content() {
|
||||
return shadow(this, 'content', this.getPageProp('Contents'));
|
||||
},
|
||||
get resources() {
|
||||
return shadow(this, 'resources', this.inheritPageProp('Resources'));
|
||||
},
|
||||
get mediaBox() {
|
||||
var obj = this.inheritPageProp('MediaBox');
|
||||
// Reset invalid media box to letter size.
|
||||
if (!isArray(obj) || obj.length !== 4)
|
||||
obj = [0, 0, 612, 792];
|
||||
return shadow(this, 'mediaBox', obj);
|
||||
},
|
||||
get view() {
|
||||
var obj = this.inheritPageProp('CropBox');
|
||||
var view = {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: this.width,
|
||||
height: this.height
|
||||
};
|
||||
if (isArray(obj) && obj.length == 4) {
|
||||
var tl = this.rotatePoint(obj[0], obj[1]);
|
||||
var br = this.rotatePoint(obj[2], obj[3]);
|
||||
view.x = Math.min(tl.x, br.x);
|
||||
view.y = Math.min(tl.y, br.y);
|
||||
view.width = Math.abs(tl.x - br.x);
|
||||
view.height = Math.abs(tl.y - br.y);
|
||||
}
|
||||
|
||||
return shadow(this, 'cropBox', view);
|
||||
},
|
||||
get annotations() {
|
||||
return shadow(this, 'annotations', this.inheritPageProp('Annots'));
|
||||
},
|
||||
get width() {
|
||||
var mediaBox = this.mediaBox;
|
||||
var rotate = this.rotate;
|
||||
var width;
|
||||
if (rotate == 0 || rotate == 180) {
|
||||
width = (mediaBox[2] - mediaBox[0]);
|
||||
} else {
|
||||
width = (mediaBox[3] - mediaBox[1]);
|
||||
}
|
||||
return shadow(this, 'width', width);
|
||||
},
|
||||
get height() {
|
||||
var mediaBox = this.mediaBox;
|
||||
var rotate = this.rotate;
|
||||
var height;
|
||||
if (rotate == 0 || rotate == 180) {
|
||||
height = (mediaBox[3] - mediaBox[1]);
|
||||
} else {
|
||||
height = (mediaBox[2] - mediaBox[0]);
|
||||
}
|
||||
return shadow(this, 'height', height);
|
||||
},
|
||||
get rotate() {
|
||||
var rotate = this.inheritPageProp('Rotate') || 0;
|
||||
// Normalize rotation so it's a multiple of 90 and between 0 and 270
|
||||
if (rotate % 90 != 0) {
|
||||
rotate = 0;
|
||||
} else if (rotate >= 360) {
|
||||
rotate = rotate % 360;
|
||||
} else if (rotate < 0) {
|
||||
// The spec doesn't cover negatives, assume its counterclockwise
|
||||
// rotation. The following is the other implementation of modulo.
|
||||
rotate = ((rotate % 360) + 360) % 360;
|
||||
}
|
||||
return shadow(this, 'rotate', rotate);
|
||||
},
|
||||
|
||||
startRenderingFromIRQueue: function pageStartRenderingFromIRQueue(
|
||||
IRQueue, fonts) {
|
||||
var self = this;
|
||||
this.IRQueue = IRQueue;
|
||||
var gfx = new CanvasGraphics(this.ctx, this.objs);
|
||||
|
||||
var displayContinuation = function pageDisplayContinuation() {
|
||||
// Always defer call to display() to work around bug in
|
||||
// Firefox error reporting from XHR callbacks.
|
||||
setTimeout(function pageSetTimeout() {
|
||||
try {
|
||||
self.display(gfx, self.callback);
|
||||
} catch (e) {
|
||||
if (self.callback) self.callback(e.toString());
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
this.ensureFonts(fonts,
|
||||
function pageStartRenderingFromIRQueueEnsureFonts() {
|
||||
displayContinuation();
|
||||
});
|
||||
},
|
||||
|
||||
getIRQueue: function pageGetIRQueue(handler, dependency) {
|
||||
if (this.IRQueue) {
|
||||
// content was compiled
|
||||
return this.IRQueue;
|
||||
}
|
||||
|
||||
var xref = this.xref;
|
||||
var content = xref.fetchIfRef(this.content);
|
||||
var resources = xref.fetchIfRef(this.resources);
|
||||
if (isArray(content)) {
|
||||
// fetching items
|
||||
var i, n = content.length;
|
||||
for (i = 0; i < n; ++i)
|
||||
content[i] = xref.fetchIfRef(content[i]);
|
||||
content = new StreamsSequenceStream(content);
|
||||
}
|
||||
|
||||
var pe = this.pe = new PartialEvaluator(
|
||||
xref, handler, 'p' + this.pageNumber + '_');
|
||||
var IRQueue = {};
|
||||
return (this.IRQueue = pe.getIRQueue(content, resources, IRQueue,
|
||||
dependency));
|
||||
},
|
||||
|
||||
ensureFonts: function pageEnsureFonts(fonts, callback) {
|
||||
// Convert the font names to the corresponding font obj.
|
||||
for (var i = 0, ii = fonts.length; i < ii; i++) {
|
||||
fonts[i] = this.objs.objs[fonts[i]].data;
|
||||
}
|
||||
|
||||
// Load all the fonts
|
||||
var fontObjs = FontLoader.bind(
|
||||
fonts,
|
||||
function pageEnsureFontsFontObjs(fontObjs) {
|
||||
this.stats.fonts = Date.now();
|
||||
|
||||
callback.call(this);
|
||||
}.bind(this),
|
||||
this.objs
|
||||
);
|
||||
},
|
||||
|
||||
display: function pageDisplay(gfx, callback) {
|
||||
var xref = this.xref;
|
||||
var resources = xref.fetchIfRef(this.resources);
|
||||
var mediaBox = xref.fetchIfRef(this.mediaBox);
|
||||
assertWellFormed(isDict(resources), 'invalid page resources');
|
||||
|
||||
gfx.xref = xref;
|
||||
gfx.res = resources;
|
||||
gfx.beginDrawing({ x: mediaBox[0], y: mediaBox[1],
|
||||
width: this.width,
|
||||
height: this.height,
|
||||
rotate: this.rotate });
|
||||
|
||||
var startIdx = 0;
|
||||
var length = this.IRQueue.fnArray.length;
|
||||
var IRQueue = this.IRQueue;
|
||||
|
||||
var self = this;
|
||||
function next() {
|
||||
startIdx = gfx.executeIRQueue(IRQueue, startIdx, next);
|
||||
if (startIdx == length) {
|
||||
self.stats.render = Date.now();
|
||||
if (callback) callback();
|
||||
}
|
||||
}
|
||||
next();
|
||||
},
|
||||
rotatePoint: function pageRotatePoint(x, y, reverse) {
|
||||
var rotate = reverse ? (360 - this.rotate) : this.rotate;
|
||||
switch (rotate) {
|
||||
case 180:
|
||||
return {x: this.width - x, y: y};
|
||||
case 90:
|
||||
return {x: this.width - y, y: this.height - x};
|
||||
case 270:
|
||||
return {x: y, y: x};
|
||||
case 360:
|
||||
case 0:
|
||||
default:
|
||||
return {x: x, y: this.height - y};
|
||||
}
|
||||
},
|
||||
getLinks: function pageGetLinks() {
|
||||
var xref = this.xref;
|
||||
var annotations = xref.fetchIfRef(this.annotations) || [];
|
||||
var i, n = annotations.length;
|
||||
var links = [];
|
||||
for (i = 0; i < n; ++i) {
|
||||
var annotation = xref.fetch(annotations[i]);
|
||||
if (!isDict(annotation))
|
||||
continue;
|
||||
var subtype = annotation.get('Subtype');
|
||||
if (!isName(subtype) || subtype.name != 'Link')
|
||||
continue;
|
||||
var rect = annotation.get('Rect');
|
||||
var topLeftCorner = this.rotatePoint(rect[0], rect[1]);
|
||||
var bottomRightCorner = this.rotatePoint(rect[2], rect[3]);
|
||||
|
||||
var link = {};
|
||||
link.x = Math.min(topLeftCorner.x, bottomRightCorner.x);
|
||||
link.y = Math.min(topLeftCorner.y, bottomRightCorner.y);
|
||||
link.width = Math.abs(topLeftCorner.x - bottomRightCorner.x);
|
||||
link.height = Math.abs(topLeftCorner.y - bottomRightCorner.y);
|
||||
var a = this.xref.fetchIfRef(annotation.get('A'));
|
||||
if (a) {
|
||||
switch (a.get('S').name) {
|
||||
case 'URI':
|
||||
link.url = a.get('URI');
|
||||
break;
|
||||
case 'GoTo':
|
||||
link.dest = a.get('D');
|
||||
break;
|
||||
default:
|
||||
TODO('other link types');
|
||||
}
|
||||
} else if (annotation.has('Dest')) {
|
||||
// simple destination link
|
||||
var dest = annotation.get('Dest');
|
||||
link.dest = isName(dest) ? dest.name : dest;
|
||||
}
|
||||
links.push(link);
|
||||
}
|
||||
return links;
|
||||
},
|
||||
startRendering: function pageStartRendering(ctx, callback) {
|
||||
this.ctx = ctx;
|
||||
this.callback = callback;
|
||||
|
||||
this.startRenderingTime = Date.now();
|
||||
this.pdf.startRendering(this);
|
||||
}
|
||||
};
|
||||
|
||||
return constructor;
|
||||
})();
|
||||
|
||||
/**
|
||||
* The `PDFDocModel` holds all the data of the PDF file. Compared to the
|
||||
* `PDFDoc`, this one doesn't have any job management code.
|
||||
* Right now there exists one PDFDocModel on the main thread + one object
|
||||
* for each worker. If there is no worker support enabled, there are two
|
||||
* `PDFDocModel` objects on the main thread created.
|
||||
* TODO: Refactor the internal object structure, such that there is no
|
||||
* need for the `PDFDocModel` anymore and there is only one object on the
|
||||
* main thread and not one entire copy on each worker instance.
|
||||
*/
|
||||
var PDFDocModel = (function pdfDoc() {
|
||||
function constructor(arg, callback) {
|
||||
if (isStream(arg))
|
||||
init.call(this, arg);
|
||||
else if (isArrayBuffer(arg))
|
||||
init.call(this, new Stream(arg));
|
||||
else
|
||||
error('PDFDocModel: Unknown argument type');
|
||||
}
|
||||
|
||||
function init(stream) {
|
||||
assertWellFormed(stream.length > 0, 'stream must have data');
|
||||
this.stream = stream;
|
||||
this.setup();
|
||||
}
|
||||
|
||||
function find(stream, needle, limit, backwards) {
|
||||
var pos = stream.pos;
|
||||
var end = stream.end;
|
||||
var str = '';
|
||||
if (pos + limit > end)
|
||||
limit = end - pos;
|
||||
for (var n = 0; n < limit; ++n)
|
||||
str += stream.getChar();
|
||||
stream.pos = pos;
|
||||
var index = backwards ? str.lastIndexOf(needle) : str.indexOf(needle);
|
||||
if (index == -1)
|
||||
return false; /* not found */
|
||||
stream.pos += index;
|
||||
return true; /* found */
|
||||
}
|
||||
|
||||
constructor.prototype = {
|
||||
get linearization() {
|
||||
var length = this.stream.length;
|
||||
var linearization = false;
|
||||
if (length) {
|
||||
linearization = new Linearization(this.stream);
|
||||
if (linearization.length != length)
|
||||
linearization = false;
|
||||
}
|
||||
// shadow the prototype getter with a data property
|
||||
return shadow(this, 'linearization', linearization);
|
||||
},
|
||||
get startXRef() {
|
||||
var stream = this.stream;
|
||||
var startXRef = 0;
|
||||
var linearization = this.linearization;
|
||||
if (linearization) {
|
||||
// Find end of first obj.
|
||||
stream.reset();
|
||||
if (find(stream, 'endobj', 1024))
|
||||
startXRef = stream.pos + 6;
|
||||
} else {
|
||||
// Find startxref at the end of the file.
|
||||
var start = stream.end - 1024;
|
||||
if (start < 0)
|
||||
start = 0;
|
||||
stream.pos = start;
|
||||
if (find(stream, 'startxref', 1024, true)) {
|
||||
stream.skip(9);
|
||||
var ch;
|
||||
do {
|
||||
ch = stream.getChar();
|
||||
} while (Lexer.isSpace(ch));
|
||||
var str = '';
|
||||
while ((ch - '0') <= 9) {
|
||||
str += ch;
|
||||
ch = stream.getChar();
|
||||
}
|
||||
startXRef = parseInt(str, 10);
|
||||
if (isNaN(startXRef))
|
||||
startXRef = 0;
|
||||
}
|
||||
}
|
||||
// shadow the prototype getter with a data property
|
||||
return shadow(this, 'startXRef', startXRef);
|
||||
},
|
||||
get mainXRefEntriesOffset() {
|
||||
var mainXRefEntriesOffset = 0;
|
||||
var linearization = this.linearization;
|
||||
if (linearization)
|
||||
mainXRefEntriesOffset = linearization.mainXRefEntriesOffset;
|
||||
// shadow the prototype getter with a data property
|
||||
return shadow(this, 'mainXRefEntriesOffset', mainXRefEntriesOffset);
|
||||
},
|
||||
// Find the header, remove leading garbage and setup the stream
|
||||
// starting from the header.
|
||||
checkHeader: function pdfDocCheckHeader() {
|
||||
var stream = this.stream;
|
||||
stream.reset();
|
||||
if (find(stream, '%PDF-', 1024)) {
|
||||
// Found the header, trim off any garbage before it.
|
||||
stream.moveStart();
|
||||
return;
|
||||
}
|
||||
// May not be a PDF file, continue anyway.
|
||||
},
|
||||
setup: function pdfDocSetup(ownerPassword, userPassword) {
|
||||
this.checkHeader();
|
||||
this.xref = new XRef(this.stream,
|
||||
this.startXRef,
|
||||
this.mainXRefEntriesOffset);
|
||||
this.catalog = new Catalog(this.xref);
|
||||
},
|
||||
get numPages() {
|
||||
var linearization = this.linearization;
|
||||
var num = linearization ? linearization.numPages : this.catalog.numPages;
|
||||
// shadow the prototype getter
|
||||
return shadow(this, 'numPages', num);
|
||||
},
|
||||
getPage: function pdfDocGetPage(n) {
|
||||
return this.catalog.getPage(n);
|
||||
}
|
||||
};
|
||||
|
||||
return constructor;
|
||||
})();
|
||||
|
||||
var PDFDoc = (function pdfDoc() {
|
||||
function constructor(arg, callback) {
|
||||
var stream = null;
|
||||
var data = null;
|
||||
|
||||
if (isStream(arg)) {
|
||||
stream = arg;
|
||||
data = arg.bytes;
|
||||
} else if (isArrayBuffer(arg)) {
|
||||
stream = new Stream(arg);
|
||||
data = arg;
|
||||
} else {
|
||||
error('PDFDoc: Unknown argument type');
|
||||
}
|
||||
|
||||
this.data = data;
|
||||
this.stream = stream;
|
||||
this.pdf = new PDFDocModel(stream);
|
||||
|
||||
this.catalog = this.pdf.catalog;
|
||||
this.objs = new PDFObjects();
|
||||
|
||||
this.pageCache = [];
|
||||
this.fontsLoading = {};
|
||||
this.workerReadyPromise = new Promise('workerReady');
|
||||
|
||||
// If worker support isn't disabled explicit and the browser has worker
|
||||
// support, create a new web worker and test if it/the browser fullfills
|
||||
// all requirements to run parts of pdf.js in a web worker.
|
||||
// Right now, the requirement is, that an Uint8Array is still an Uint8Array
|
||||
// as it arrives on the worker. Chrome added this with version 15.
|
||||
if (!globalScope.PDFJS.disableWorker && typeof Worker !== 'undefined') {
|
||||
var workerSrc = PDFJS.workerSrc;
|
||||
if (typeof workerSrc === 'undefined') {
|
||||
throw 'No PDFJS.workerSrc specified';
|
||||
}
|
||||
|
||||
var worker;
|
||||
try {
|
||||
worker = new Worker(workerSrc);
|
||||
} catch (e) {
|
||||
// Some versions of FF can't create a worker on localhost, see:
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=683280
|
||||
globalScope.PDFJS.disableWorker = true;
|
||||
this.setupFakeWorker();
|
||||
return;
|
||||
}
|
||||
|
||||
var messageHandler = new MessageHandler('main', worker);
|
||||
|
||||
// Tell the worker the file it was created from.
|
||||
messageHandler.send('workerSrc', workerSrc);
|
||||
|
||||
messageHandler.on('test', function pdfDocTest(supportTypedArray) {
|
||||
if (supportTypedArray) {
|
||||
this.worker = worker;
|
||||
this.setupMessageHandler(messageHandler);
|
||||
} else {
|
||||
this.setupFakeWorker();
|
||||
}
|
||||
}.bind(this));
|
||||
|
||||
var testObj = new Uint8Array(1);
|
||||
messageHandler.send('test', testObj);
|
||||
} else {
|
||||
this.setupFakeWorker();
|
||||
}
|
||||
}
|
||||
|
||||
constructor.prototype = {
|
||||
setupFakeWorker: function() {
|
||||
// If we don't use a worker, just post/sendMessage to the main thread.
|
||||
var fakeWorker = {
|
||||
postMessage: function pdfDocPostMessage(obj) {
|
||||
fakeWorker.onmessage({data: obj});
|
||||
},
|
||||
terminate: function pdfDocTerminate() {}
|
||||
};
|
||||
|
||||
var messageHandler = new MessageHandler('main', fakeWorker);
|
||||
this.setupMessageHandler(messageHandler);
|
||||
|
||||
// If the main thread is our worker, setup the handling for the messages
|
||||
// the main thread sends to it self.
|
||||
WorkerMessageHandler.setup(messageHandler);
|
||||
},
|
||||
|
||||
|
||||
setupMessageHandler: function(messageHandler) {
|
||||
this.messageHandler = messageHandler;
|
||||
|
||||
messageHandler.on('page', function pdfDocPage(data) {
|
||||
var pageNum = data.pageNum;
|
||||
var page = this.pageCache[pageNum];
|
||||
var depFonts = data.depFonts;
|
||||
|
||||
page.startRenderingFromIRQueue(data.IRQueue, depFonts);
|
||||
}, this);
|
||||
|
||||
messageHandler.on('obj', function pdfDocObj(data) {
|
||||
var id = data[0];
|
||||
var type = data[1];
|
||||
|
||||
switch (type) {
|
||||
case 'JpegStream':
|
||||
var IR = data[2];
|
||||
new JpegImageLoader(id, IR, this.objs);
|
||||
break;
|
||||
case 'Font':
|
||||
var name = data[2];
|
||||
var file = data[3];
|
||||
var properties = data[4];
|
||||
|
||||
if (file) {
|
||||
var fontFileDict = new Dict();
|
||||
fontFileDict.map = file.dict.map;
|
||||
|
||||
var fontFile = new Stream(file.bytes, file.start,
|
||||
file.end - file.start, fontFileDict);
|
||||
|
||||
// Check if this is a FlateStream. Otherwise just use the created
|
||||
// Stream one. This makes complex_ttf_font.pdf work.
|
||||
var cmf = file.bytes[0];
|
||||
if ((cmf & 0x0f) == 0x08) {
|
||||
file = new FlateStream(fontFile);
|
||||
} else {
|
||||
file = fontFile;
|
||||
}
|
||||
}
|
||||
|
||||
// For now, resolve the font object here direclty. The real font
|
||||
// object is then created in FontLoader.bind().
|
||||
this.objs.resolve(id, {
|
||||
name: name,
|
||||
file: file,
|
||||
properties: properties
|
||||
});
|
||||
break;
|
||||
default:
|
||||
throw 'Got unkown object type ' + type;
|
||||
}
|
||||
}, this);
|
||||
|
||||
messageHandler.on('font_ready', function pdfDocFontReady(data) {
|
||||
var id = data[0];
|
||||
var font = new FontShape(data[1]);
|
||||
|
||||
// If there is no string, then there is nothing to attach to the DOM.
|
||||
if (!font.str) {
|
||||
this.objs.resolve(id, font);
|
||||
} else {
|
||||
this.objs.setData(id, font);
|
||||
}
|
||||
}.bind(this));
|
||||
|
||||
setTimeout(function pdfDocFontReadySetTimeout() {
|
||||
messageHandler.send('doc', this.data);
|
||||
this.workerReadyPromise.resolve(true);
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
get numPages() {
|
||||
return this.pdf.numPages;
|
||||
},
|
||||
|
||||
startRendering: function pdfDocStartRendering(page) {
|
||||
// The worker might not be ready to receive the page request yet.
|
||||
this.workerReadyPromise.then(function pdfDocStartRenderingThen() {
|
||||
this.messageHandler.send('page_request', page.pageNumber + 1);
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
getPage: function pdfDocGetPage(n) {
|
||||
if (this.pageCache[n])
|
||||
return this.pageCache[n];
|
||||
|
||||
var page = this.pdf.getPage(n);
|
||||
// Add a reference to the objects such that Page can forward the reference
|
||||
// to the CanvasGraphics and so on.
|
||||
page.objs = this.objs;
|
||||
page.pdf = this;
|
||||
return (this.pageCache[n] = page);
|
||||
},
|
||||
|
||||
destroy: function pdfDocDestroy() {
|
||||
if (this.worker)
|
||||
this.worker.terminate();
|
||||
|
||||
if (this.fontWorker)
|
||||
this.fontWorker.terminate();
|
||||
|
||||
for (var n in this.pageCache)
|
||||
delete this.pageCache[n];
|
||||
|
||||
delete this.data;
|
||||
delete this.stream;
|
||||
delete this.pdf;
|
||||
delete this.catalog;
|
||||
}
|
||||
};
|
||||
|
||||
return constructor;
|
||||
})();
|
||||
|
||||
globalScope.PDFJS.PDFDoc = PDFDoc;
|
||||
|
|
@ -0,0 +1,597 @@
|
|||
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
|
||||
|
||||
'use strict';
|
||||
|
||||
var ARCFourCipher = (function arcFourCipher() {
|
||||
function constructor(key) {
|
||||
this.a = 0;
|
||||
this.b = 0;
|
||||
var s = new Uint8Array(256);
|
||||
var i, j = 0, tmp, keyLength = key.length;
|
||||
for (i = 0; i < 256; ++i)
|
||||
s[i] = i;
|
||||
for (i = 0; i < 256; ++i) {
|
||||
tmp = s[i];
|
||||
j = (j + tmp + key[i % keyLength]) & 0xFF;
|
||||
s[i] = s[j];
|
||||
s[j] = tmp;
|
||||
}
|
||||
this.s = s;
|
||||
}
|
||||
|
||||
constructor.prototype = {
|
||||
encryptBlock: function arcFourCipherEncryptBlock(data) {
|
||||
var i, n = data.length, tmp, tmp2;
|
||||
var a = this.a, b = this.b, s = this.s;
|
||||
var output = new Uint8Array(n);
|
||||
for (i = 0; i < n; ++i) {
|
||||
a = (a + 1) & 0xFF;
|
||||
tmp = s[a];
|
||||
b = (b + tmp) & 0xFF;
|
||||
tmp2 = s[b];
|
||||
s[a] = tmp2;
|
||||
s[b] = tmp;
|
||||
output[i] = data[i] ^ s[(tmp + tmp2) & 0xFF];
|
||||
}
|
||||
this.a = a;
|
||||
this.b = b;
|
||||
return output;
|
||||
}
|
||||
};
|
||||
constructor.prototype.decryptBlock = constructor.prototype.encryptBlock;
|
||||
|
||||
return constructor;
|
||||
})();
|
||||
|
||||
var calculateMD5 = (function calculateMD5() {
|
||||
var r = new Uint8Array([
|
||||
7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
|
||||
5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,
|
||||
4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
|
||||
6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21]);
|
||||
|
||||
var k = new Int32Array([
|
||||
-680876936, -389564586, 606105819, -1044525330, -176418897, 1200080426,
|
||||
-1473231341, -45705983, 1770035416, -1958414417, -42063, -1990404162,
|
||||
1804603682, -40341101, -1502002290, 1236535329, -165796510, -1069501632,
|
||||
643717713, -373897302, -701558691, 38016083, -660478335, -405537848,
|
||||
568446438, -1019803690, -187363961, 1163531501, -1444681467, -51403784,
|
||||
1735328473, -1926607734, -378558, -2022574463, 1839030562, -35309556,
|
||||
-1530992060, 1272893353, -155497632, -1094730640, 681279174, -358537222,
|
||||
-722521979, 76029189, -640364487, -421815835, 530742520, -995338651,
|
||||
-198630844, 1126891415, -1416354905, -57434055, 1700485571, -1894986606,
|
||||
-1051523, -2054922799, 1873313359, -30611744, -1560198380, 1309151649,
|
||||
-145523070, -1120210379, 718787259, -343485551]);
|
||||
|
||||
function hash(data, offset, length) {
|
||||
var h0 = 1732584193, h1 = -271733879, h2 = -1732584194, h3 = 271733878;
|
||||
// pre-processing
|
||||
var paddedLength = (length + 72) & ~63; // data + 9 extra bytes
|
||||
var padded = new Uint8Array(paddedLength);
|
||||
var i, j, n;
|
||||
for (i = 0; i < length; ++i)
|
||||
padded[i] = data[offset++];
|
||||
padded[i++] = 0x80;
|
||||
n = paddedLength - 8;
|
||||
while (i < n)
|
||||
padded[i++] = 0;
|
||||
padded[i++] = (length << 3) & 0xFF;
|
||||
padded[i++] = (length >> 5) & 0xFF;
|
||||
padded[i++] = (length >> 13) & 0xFF;
|
||||
padded[i++] = (length >> 21) & 0xFF;
|
||||
padded[i++] = (length >>> 29) & 0xFF;
|
||||
padded[i++] = 0;
|
||||
padded[i++] = 0;
|
||||
padded[i++] = 0;
|
||||
// chunking
|
||||
// TODO ArrayBuffer ?
|
||||
var w = new Int32Array(16);
|
||||
for (i = 0; i < paddedLength;) {
|
||||
for (j = 0; j < 16; ++j, i += 4) {
|
||||
w[j] = (padded[i] | (padded[i + 1] << 8) |
|
||||
(padded[i + 2] << 16) | (padded[i + 3] << 24));
|
||||
}
|
||||
var a = h0, b = h1, c = h2, d = h3, f, g;
|
||||
for (j = 0; j < 64; ++j) {
|
||||
if (j < 16) {
|
||||
f = (b & c) | ((~b) & d);
|
||||
g = j;
|
||||
} else if (j < 32) {
|
||||
f = (d & b) | ((~d) & c);
|
||||
g = (5 * j + 1) & 15;
|
||||
} else if (j < 48) {
|
||||
f = b ^ c ^ d;
|
||||
g = (3 * j + 5) & 15;
|
||||
} else {
|
||||
f = c ^ (b | (~d));
|
||||
g = (7 * j) & 15;
|
||||
}
|
||||
var tmp = d, rotateArg = (a + f + k[j] + w[g]) | 0, rotate = r[j];
|
||||
d = c;
|
||||
c = b;
|
||||
b = (b + ((rotateArg << rotate) | (rotateArg >>> (32 - rotate)))) | 0;
|
||||
a = tmp;
|
||||
}
|
||||
h0 = (h0 + a) | 0;
|
||||
h1 = (h1 + b) | 0;
|
||||
h2 = (h2 + c) | 0;
|
||||
h3 = (h3 + d) | 0;
|
||||
}
|
||||
return new Uint8Array([
|
||||
h0 & 0xFF, (h0 >> 8) & 0xFF, (h0 >> 16) & 0xFF, (h0 >>> 24) & 0xFF,
|
||||
h1 & 0xFF, (h1 >> 8) & 0xFF, (h1 >> 16) & 0xFF, (h1 >>> 24) & 0xFF,
|
||||
h2 & 0xFF, (h2 >> 8) & 0xFF, (h2 >> 16) & 0xFF, (h2 >>> 24) & 0xFF,
|
||||
h3 & 0xFF, (h3 >> 8) & 0xFF, (h3 >> 16) & 0xFF, (h3 >>> 24) & 0xFF
|
||||
]);
|
||||
}
|
||||
return hash;
|
||||
})();
|
||||
|
||||
var NullCipher = (function nullCipher() {
|
||||
function constructor() {
|
||||
}
|
||||
|
||||
constructor.prototype = {
|
||||
decryptBlock: function nullCipherDecryptBlock(data) {
|
||||
return data;
|
||||
}
|
||||
};
|
||||
|
||||
return constructor;
|
||||
})();
|
||||
|
||||
var AES128Cipher = (function aes128Cipher() {
|
||||
var rcon = new Uint8Array([
|
||||
0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c,
|
||||
0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a,
|
||||
0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd,
|
||||
0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a,
|
||||
0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
|
||||
0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6,
|
||||
0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72,
|
||||
0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc,
|
||||
0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10,
|
||||
0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e,
|
||||
0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5,
|
||||
0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94,
|
||||
0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02,
|
||||
0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d,
|
||||
0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d,
|
||||
0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f,
|
||||
0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb,
|
||||
0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c,
|
||||
0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a,
|
||||
0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd,
|
||||
0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a,
|
||||
0x74, 0xe8, 0xcb, 0x8d]);
|
||||
|
||||
var s = new Uint8Array([
|
||||
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b,
|
||||
0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
|
||||
0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26,
|
||||
0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
|
||||
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2,
|
||||
0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
|
||||
0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed,
|
||||
0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
|
||||
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f,
|
||||
0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
|
||||
0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec,
|
||||
0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
|
||||
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14,
|
||||
0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
|
||||
0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d,
|
||||
0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
|
||||
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f,
|
||||
0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
|
||||
0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11,
|
||||
0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
|
||||
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f,
|
||||
0xb0, 0x54, 0xbb, 0x16]);
|
||||
|
||||
var inv_s = new Uint8Array([
|
||||
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e,
|
||||
0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87,
|
||||
0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32,
|
||||
0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
|
||||
0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49,
|
||||
0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16,
|
||||
0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50,
|
||||
0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
|
||||
0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05,
|
||||
0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02,
|
||||
0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91, 0x11, 0x41,
|
||||
0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
|
||||
0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8,
|
||||
0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89,
|
||||
0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b,
|
||||
0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
|
||||
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59,
|
||||
0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d,
|
||||
0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d,
|
||||
0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
|
||||
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63,
|
||||
0x55, 0x21, 0x0c, 0x7d]);
|
||||
|
||||
var mix = new Uint32Array([
|
||||
0x00000000, 0x0e090d0b, 0x1c121a16, 0x121b171d, 0x3824342c, 0x362d3927,
|
||||
0x24362e3a, 0x2a3f2331, 0x70486858, 0x7e416553, 0x6c5a724e, 0x62537f45,
|
||||
0x486c5c74, 0x4665517f, 0x547e4662, 0x5a774b69, 0xe090d0b0, 0xee99ddbb,
|
||||
0xfc82caa6, 0xf28bc7ad, 0xd8b4e49c, 0xd6bde997, 0xc4a6fe8a, 0xcaaff381,
|
||||
0x90d8b8e8, 0x9ed1b5e3, 0x8ccaa2fe, 0x82c3aff5, 0xa8fc8cc4, 0xa6f581cf,
|
||||
0xb4ee96d2, 0xbae79bd9, 0xdb3bbb7b, 0xd532b670, 0xc729a16d, 0xc920ac66,
|
||||
0xe31f8f57, 0xed16825c, 0xff0d9541, 0xf104984a, 0xab73d323, 0xa57ade28,
|
||||
0xb761c935, 0xb968c43e, 0x9357e70f, 0x9d5eea04, 0x8f45fd19, 0x814cf012,
|
||||
0x3bab6bcb, 0x35a266c0, 0x27b971dd, 0x29b07cd6, 0x038f5fe7, 0x0d8652ec,
|
||||
0x1f9d45f1, 0x119448fa, 0x4be30393, 0x45ea0e98, 0x57f11985, 0x59f8148e,
|
||||
0x73c737bf, 0x7dce3ab4, 0x6fd52da9, 0x61dc20a2, 0xad766df6, 0xa37f60fd,
|
||||
0xb16477e0, 0xbf6d7aeb, 0x955259da, 0x9b5b54d1, 0x894043cc, 0x87494ec7,
|
||||
0xdd3e05ae, 0xd33708a5, 0xc12c1fb8, 0xcf2512b3, 0xe51a3182, 0xeb133c89,
|
||||
0xf9082b94, 0xf701269f, 0x4de6bd46, 0x43efb04d, 0x51f4a750, 0x5ffdaa5b,
|
||||
0x75c2896a, 0x7bcb8461, 0x69d0937c, 0x67d99e77, 0x3daed51e, 0x33a7d815,
|
||||
0x21bccf08, 0x2fb5c203, 0x058ae132, 0x0b83ec39, 0x1998fb24, 0x1791f62f,
|
||||
0x764dd68d, 0x7844db86, 0x6a5fcc9b, 0x6456c190, 0x4e69e2a1, 0x4060efaa,
|
||||
0x527bf8b7, 0x5c72f5bc, 0x0605bed5, 0x080cb3de, 0x1a17a4c3, 0x141ea9c8,
|
||||
0x3e218af9, 0x302887f2, 0x223390ef, 0x2c3a9de4, 0x96dd063d, 0x98d40b36,
|
||||
0x8acf1c2b, 0x84c61120, 0xaef93211, 0xa0f03f1a, 0xb2eb2807, 0xbce2250c,
|
||||
0xe6956e65, 0xe89c636e, 0xfa877473, 0xf48e7978, 0xdeb15a49, 0xd0b85742,
|
||||
0xc2a3405f, 0xccaa4d54, 0x41ecdaf7, 0x4fe5d7fc, 0x5dfec0e1, 0x53f7cdea,
|
||||
0x79c8eedb, 0x77c1e3d0, 0x65daf4cd, 0x6bd3f9c6, 0x31a4b2af, 0x3fadbfa4,
|
||||
0x2db6a8b9, 0x23bfa5b2, 0x09808683, 0x07898b88, 0x15929c95, 0x1b9b919e,
|
||||
0xa17c0a47, 0xaf75074c, 0xbd6e1051, 0xb3671d5a, 0x99583e6b, 0x97513360,
|
||||
0x854a247d, 0x8b432976, 0xd134621f, 0xdf3d6f14, 0xcd267809, 0xc32f7502,
|
||||
0xe9105633, 0xe7195b38, 0xf5024c25, 0xfb0b412e, 0x9ad7618c, 0x94de6c87,
|
||||
0x86c57b9a, 0x88cc7691, 0xa2f355a0, 0xacfa58ab, 0xbee14fb6, 0xb0e842bd,
|
||||
0xea9f09d4, 0xe49604df, 0xf68d13c2, 0xf8841ec9, 0xd2bb3df8, 0xdcb230f3,
|
||||
0xcea927ee, 0xc0a02ae5, 0x7a47b13c, 0x744ebc37, 0x6655ab2a, 0x685ca621,
|
||||
0x42638510, 0x4c6a881b, 0x5e719f06, 0x5078920d, 0x0a0fd964, 0x0406d46f,
|
||||
0x161dc372, 0x1814ce79, 0x322bed48, 0x3c22e043, 0x2e39f75e, 0x2030fa55,
|
||||
0xec9ab701, 0xe293ba0a, 0xf088ad17, 0xfe81a01c, 0xd4be832d, 0xdab78e26,
|
||||
0xc8ac993b, 0xc6a59430, 0x9cd2df59, 0x92dbd252, 0x80c0c54f, 0x8ec9c844,
|
||||
0xa4f6eb75, 0xaaffe67e, 0xb8e4f163, 0xb6edfc68, 0x0c0a67b1, 0x02036aba,
|
||||
0x10187da7, 0x1e1170ac, 0x342e539d, 0x3a275e96, 0x283c498b, 0x26354480,
|
||||
0x7c420fe9, 0x724b02e2, 0x605015ff, 0x6e5918f4, 0x44663bc5, 0x4a6f36ce,
|
||||
0x587421d3, 0x567d2cd8, 0x37a10c7a, 0x39a80171, 0x2bb3166c, 0x25ba1b67,
|
||||
0x0f853856, 0x018c355d, 0x13972240, 0x1d9e2f4b, 0x47e96422, 0x49e06929,
|
||||
0x5bfb7e34, 0x55f2733f, 0x7fcd500e, 0x71c45d05, 0x63df4a18, 0x6dd64713,
|
||||
0xd731dcca, 0xd938d1c1, 0xcb23c6dc, 0xc52acbd7, 0xef15e8e6, 0xe11ce5ed,
|
||||
0xf307f2f0, 0xfd0efffb, 0xa779b492, 0xa970b999, 0xbb6bae84, 0xb562a38f,
|
||||
0x9f5d80be, 0x91548db5, 0x834f9aa8, 0x8d4697a3]);
|
||||
|
||||
function expandKey128(cipherKey) {
|
||||
var b = 176, result = new Uint8Array(b);
|
||||
result.set(cipherKey);
|
||||
for (var j = 16, i = 1; j < b; ++i) {
|
||||
// RotWord
|
||||
var t1 = result[j - 3], t2 = result[j - 2],
|
||||
t3 = result[j - 1], t4 = result[j - 4];
|
||||
// SubWord
|
||||
t1 = s[t1]; t2 = s[t2]; t3 = s[t3]; t4 = s[t4];
|
||||
// Rcon
|
||||
t1 = t1 ^ rcon[i];
|
||||
for (var n = 0; n < 4; ++n) {
|
||||
result[j] = (t1 ^= result[j - 16]); j++;
|
||||
result[j] = (t2 ^= result[j - 16]); j++;
|
||||
result[j] = (t3 ^= result[j - 16]); j++;
|
||||
result[j] = (t4 ^= result[j - 16]); j++;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function decrypt128(input, key) {
|
||||
var state = new Uint8Array(16);
|
||||
state.set(input);
|
||||
var i, j, k;
|
||||
var t, u, v;
|
||||
// AddRoundKey
|
||||
for (j = 0, k = 160; j < 16; ++j, ++k)
|
||||
state[j] ^= key[k];
|
||||
for (i = 9; i >= 1; --i) {
|
||||
// InvShiftRows
|
||||
t = state[13]; state[13] = state[9]; state[9] = state[5];
|
||||
state[5] = state[1]; state[1] = t;
|
||||
t = state[14]; u = state[10]; state[14] = state[6];
|
||||
state[10] = state[2]; state[6] = t; state[2] = u;
|
||||
t = state[15]; u = state[11]; v = state[7]; state[15] = state[3];
|
||||
state[11] = t; state[7] = u; state[3] = v;
|
||||
// InvSubBytes
|
||||
for (j = 0; j < 16; ++j)
|
||||
state[j] = inv_s[state[j]];
|
||||
// AddRoundKey
|
||||
for (j = 0, k = i * 16; j < 16; ++j, ++k)
|
||||
state[j] ^= key[k];
|
||||
// InvMixColumns
|
||||
for (j = 0; j < 16; j += 4) {
|
||||
var s0 = mix[state[j]], s1 = mix[state[j + 1]],
|
||||
s2 = mix[state[j + 2]], s3 = mix[state[j + 3]];
|
||||
t = (s0 ^ (s1 >>> 8) ^ (s1 << 24) ^ (s2 >>> 16) ^ (s2 << 16) ^
|
||||
(s3 >>> 24) ^ (s3 << 8));
|
||||
state[j] = (t >>> 24) & 0xFF;
|
||||
state[j + 1] = (t >> 16) & 0xFF;
|
||||
state[j + 2] = (t >> 8) & 0xFF;
|
||||
state[j + 3] = t & 0xFF;
|
||||
}
|
||||
}
|
||||
// InvShiftRows
|
||||
t = state[13]; state[13] = state[9]; state[9] = state[5];
|
||||
state[5] = state[1]; state[1] = t;
|
||||
t = state[14]; u = state[10]; state[14] = state[6];
|
||||
state[10] = state[2]; state[6] = t; state[2] = u;
|
||||
t = state[15]; u = state[11]; v = state[7]; state[15] = state[3];
|
||||
state[11] = t; state[7] = u; state[3] = v;
|
||||
for (j = 0; j < 16; ++j) {
|
||||
// InvSubBytes
|
||||
state[j] = inv_s[state[j]];
|
||||
// AddRoundKey
|
||||
state[j] ^= key[j];
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
function constructor(key) {
|
||||
this.key = expandKey128(key);
|
||||
this.buffer = new Uint8Array(16);
|
||||
this.bufferPosition = 0;
|
||||
}
|
||||
|
||||
function decryptBlock2(data) {
|
||||
var i, j, ii, sourceLength = data.length,
|
||||
buffer = this.buffer, bufferLength = this.bufferPosition,
|
||||
result = [], iv = this.iv;
|
||||
for (i = 0; i < sourceLength; ++i) {
|
||||
buffer[bufferLength] = data[i];
|
||||
++bufferLength;
|
||||
if (bufferLength < 16)
|
||||
continue;
|
||||
// buffer is full, decrypting
|
||||
var plain = decrypt128(buffer, this.key);
|
||||
// xor-ing the IV vector to get plain text
|
||||
for (j = 0; j < 16; ++j)
|
||||
plain[j] ^= iv[j];
|
||||
iv = buffer;
|
||||
result.push(plain);
|
||||
buffer = new Uint8Array(16);
|
||||
bufferLength = 0;
|
||||
}
|
||||
// saving incomplete buffer
|
||||
this.buffer = buffer;
|
||||
this.bufferLength = bufferLength;
|
||||
this.iv = iv;
|
||||
if (result.length == 0)
|
||||
return new Uint8Array([]);
|
||||
if (result.length == 1)
|
||||
return result[0];
|
||||
// combining plain text blocks into one
|
||||
var output = new Uint8Array(16 * result.length);
|
||||
for (i = 0, j = 0, ii = result.length; i < ii; ++i, j += 16)
|
||||
output.set(result[i], j);
|
||||
return output;
|
||||
}
|
||||
|
||||
constructor.prototype = {
|
||||
decryptBlock: function aes128CipherDecryptBlock(data) {
|
||||
var i, sourceLength = data.length;
|
||||
var buffer = this.buffer, bufferLength = this.bufferPosition;
|
||||
// waiting for IV values -- they are at the start of the stream
|
||||
for (i = 0; bufferLength < 16 && i < sourceLength; ++i, ++bufferLength)
|
||||
buffer[bufferLength] = data[i];
|
||||
if (bufferLength < 16) {
|
||||
// need more data
|
||||
this.bufferLength = bufferLength;
|
||||
return new Uint8Array([]);
|
||||
}
|
||||
this.iv = buffer;
|
||||
this.buffer = new Uint8Array(16);
|
||||
this.bufferLength = 0;
|
||||
// starting decryption
|
||||
this.decryptBlock = decryptBlock2;
|
||||
return this.decryptBlock(data.subarray(16));
|
||||
}
|
||||
};
|
||||
|
||||
return constructor;
|
||||
})();
|
||||
|
||||
var CipherTransform = (function cipherTransform() {
|
||||
function constructor(stringCipherConstructor, streamCipherConstructor) {
|
||||
this.stringCipherConstructor = stringCipherConstructor;
|
||||
this.streamCipherConstructor = streamCipherConstructor;
|
||||
}
|
||||
constructor.prototype = {
|
||||
createStream: function cipherTransformCreateStream(stream) {
|
||||
var cipher = new this.streamCipherConstructor();
|
||||
return new DecryptStream(stream,
|
||||
function cipherTransformDecryptStream(data) {
|
||||
return cipher.decryptBlock(data);
|
||||
}
|
||||
);
|
||||
},
|
||||
decryptString: function cipherTransformDecryptString(s) {
|
||||
var cipher = new this.stringCipherConstructor();
|
||||
var data = stringToBytes(s);
|
||||
data = cipher.decryptBlock(data);
|
||||
return bytesToString(data);
|
||||
}
|
||||
};
|
||||
return constructor;
|
||||
})();
|
||||
|
||||
var CipherTransformFactory = (function cipherTransformFactory() {
|
||||
function prepareKeyData(fileId, password, ownerPassword, userPassword,
|
||||
flags, revision, keyLength, encryptMetadata) {
|
||||
var defaultPasswordBytes = new Uint8Array([
|
||||
0x28, 0xBF, 0x4E, 0x5E, 0x4E, 0x75, 0x8A, 0x41,
|
||||
0x64, 0x00, 0x4E, 0x56, 0xFF, 0xFA, 0x01, 0x08,
|
||||
0x2E, 0x2E, 0x00, 0xB6, 0xD0, 0x68, 0x3E, 0x80,
|
||||
0x2F, 0x0C, 0xA9, 0xFE, 0x64, 0x53, 0x69, 0x7A]);
|
||||
var hashData = new Uint8Array(100), i = 0, j, n;
|
||||
if (password) {
|
||||
n = Math.min(32, password.length);
|
||||
for (; i < n; ++i)
|
||||
hashData[i] = password[i];
|
||||
}
|
||||
j = 0;
|
||||
while (i < 32) {
|
||||
hashData[i++] = defaultPasswordBytes[j++];
|
||||
}
|
||||
// as now the padded password in the hashData[0..i]
|
||||
for (j = 0, n = ownerPassword.length; j < n; ++j)
|
||||
hashData[i++] = ownerPassword[j];
|
||||
hashData[i++] = flags & 0xFF;
|
||||
hashData[i++] = (flags >> 8) & 0xFF;
|
||||
hashData[i++] = (flags >> 16) & 0xFF;
|
||||
hashData[i++] = (flags >>> 24) & 0xFF;
|
||||
for (j = 0, n = fileId.length; j < n; ++j)
|
||||
hashData[i++] = fileId[j];
|
||||
if (revision >= 4 && !encryptMetadata) {
|
||||
hashData[i++] = 0xFF;
|
||||
hashData[i++] = 0xFF;
|
||||
hashData[i++] = 0xFF;
|
||||
hashData[i++] = 0xFF;
|
||||
}
|
||||
var hash = calculateMD5(hashData, 0, i);
|
||||
var keyLengthInBytes = keyLength >> 3;
|
||||
if (revision >= 3) {
|
||||
for (j = 0; j < 50; ++j) {
|
||||
hash = calculateMD5(hash, 0, keyLengthInBytes);
|
||||
}
|
||||
}
|
||||
var encryptionKey = hash.subarray(0, keyLengthInBytes);
|
||||
var cipher, checkData;
|
||||
|
||||
if (revision >= 3) {
|
||||
// padded password in hashData, we can use this array for user
|
||||
// password check
|
||||
i = 32;
|
||||
for (j = 0, n = fileId.length; j < n; ++j)
|
||||
hashData[i++] = fileId[j];
|
||||
cipher = new ARCFourCipher(encryptionKey);
|
||||
var checkData = cipher.encryptBlock(calculateMD5(hashData, 0, i));
|
||||
n = encryptionKey.length;
|
||||
var derivedKey = new Uint8Array(n), k;
|
||||
for (j = 1; j <= 19; ++j) {
|
||||
for (k = 0; k < n; ++k)
|
||||
derivedKey[k] = encryptionKey[k] ^ j;
|
||||
cipher = new ARCFourCipher(derivedKey);
|
||||
checkData = cipher.encryptBlock(checkData);
|
||||
}
|
||||
} else {
|
||||
cipher = new ARCFourCipher(encryptionKey);
|
||||
checkData = cipher.encryptBlock(hashData.subarray(0, 32));
|
||||
}
|
||||
for (j = 0, n = checkData.length; j < n; ++j) {
|
||||
if (userPassword[j] != checkData[j])
|
||||
error('incorrect password');
|
||||
}
|
||||
return encryptionKey;
|
||||
}
|
||||
|
||||
var identityName = new Name('Identity');
|
||||
|
||||
function constructor(dict, fileId, password) {
|
||||
var filter = dict.get('Filter');
|
||||
if (!isName(filter) || filter.name != 'Standard')
|
||||
error('unknown encryption method');
|
||||
this.dict = dict;
|
||||
var algorithm = dict.get('V');
|
||||
if (!isInt(algorithm) ||
|
||||
(algorithm != 1 && algorithm != 2 && algorithm != 4))
|
||||
error('unsupported encryption algorithm');
|
||||
this.algorithm = algorithm;
|
||||
var keyLength = dict.get('Length') || 40;
|
||||
if (!isInt(keyLength) ||
|
||||
keyLength < 40 || (keyLength % 8) != 0)
|
||||
error('invalid key length');
|
||||
// prepare keys
|
||||
var ownerPassword = stringToBytes(dict.get('O'));
|
||||
var userPassword = stringToBytes(dict.get('U'));
|
||||
var flags = dict.get('P');
|
||||
var revision = dict.get('R');
|
||||
var encryptMetadata =
|
||||
dict.get('EncryptMetadata') !== false; // makes true as default value
|
||||
var fileIdBytes = stringToBytes(fileId);
|
||||
var passwordBytes;
|
||||
if (password)
|
||||
passwordBytes = stringToBytes(password);
|
||||
|
||||
this.encryptionKey = prepareKeyData(fileIdBytes, passwordBytes,
|
||||
ownerPassword, userPassword,
|
||||
flags, revision,
|
||||
keyLength, encryptMetadata);
|
||||
if (algorithm == 4) {
|
||||
this.cf = dict.get('CF');
|
||||
this.stmf = dict.get('StmF') || identityName;
|
||||
this.strf = dict.get('StrF') || identityName;
|
||||
this.eff = dict.get('EFF') || this.strf;
|
||||
}
|
||||
}
|
||||
|
||||
function buildObjectKey(num, gen, encryptionKey, isAes) {
|
||||
var key = new Uint8Array(encryptionKey.length + 9), i, n;
|
||||
for (i = 0, n = encryptionKey.length; i < n; ++i)
|
||||
key[i] = encryptionKey[i];
|
||||
key[i++] = num & 0xFF;
|
||||
key[i++] = (num >> 8) & 0xFF;
|
||||
key[i++] = (num >> 16) & 0xFF;
|
||||
key[i++] = gen & 0xFF;
|
||||
key[i++] = (gen >> 8) & 0xFF;
|
||||
if (isAes) {
|
||||
key[i++] = 0x73;
|
||||
key[i++] = 0x41;
|
||||
key[i++] = 0x6C;
|
||||
key[i++] = 0x54;
|
||||
}
|
||||
var hash = calculateMD5(key, 0, i);
|
||||
return hash.subarray(0, Math.min(encryptionKey.length + 5, 16));
|
||||
}
|
||||
|
||||
function buildCipherConstructor(cf, name, num, gen, key) {
|
||||
var cryptFilter = cf.get(name.name);
|
||||
var cfm;
|
||||
if (cryptFilter != null)
|
||||
cfm = cryptFilter.get('CFM');
|
||||
if (!cfm || cfm.name == 'None') {
|
||||
return function cipherTransformFactoryBuildCipherConstructorNone() {
|
||||
return new NullCipher();
|
||||
};
|
||||
}
|
||||
if ('V2' == cfm.name) {
|
||||
return function cipherTransformFactoryBuildCipherConstructorV2() {
|
||||
return new ARCFourCipher(
|
||||
buildObjectKey(num, gen, key, false));
|
||||
};
|
||||
}
|
||||
if ('AESV2' == cfm.name) {
|
||||
return function cipherTransformFactoryBuildCipherConstructorAESV2() {
|
||||
return new AES128Cipher(
|
||||
buildObjectKey(num, gen, key, true));
|
||||
};
|
||||
}
|
||||
error('Unknown crypto method');
|
||||
return null;
|
||||
}
|
||||
|
||||
constructor.prototype = {
|
||||
createCipherTransform: function buildCipherCreateCipherTransform(num,
|
||||
gen) {
|
||||
if (this.algorithm == 4) {
|
||||
return new CipherTransform(
|
||||
buildCipherConstructor(this.cf, this.stmf,
|
||||
num, gen, this.encryptionKey),
|
||||
buildCipherConstructor(this.cf, this.strf,
|
||||
num, gen, this.encryptionKey));
|
||||
}
|
||||
// algorithms 1 and 2
|
||||
var key = buildObjectKey(num, gen, this.encryptionKey, false);
|
||||
var cipherConstructor = function buildCipherCipherConstructor() {
|
||||
return new ARCFourCipher(key);
|
||||
};
|
||||
return new CipherTransform(cipherConstructor, cipherConstructor);
|
||||
}
|
||||
};
|
||||
|
||||
return constructor;
|
||||
})();
|
||||
|
|
@ -0,0 +1,857 @@
|
|||
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
|
||||
|
||||
'use strict';
|
||||
|
||||
var PartialEvaluator = (function partialEvaluator() {
|
||||
function constructor(xref, handler, uniquePrefix) {
|
||||
this.state = new EvalState();
|
||||
this.stateStack = [];
|
||||
|
||||
this.xref = xref;
|
||||
this.handler = handler;
|
||||
this.uniquePrefix = uniquePrefix;
|
||||
this.objIdCounter = 0;
|
||||
}
|
||||
|
||||
var OP_MAP = {
|
||||
// Graphics state
|
||||
w: 'setLineWidth',
|
||||
J: 'setLineCap',
|
||||
j: 'setLineJoin',
|
||||
M: 'setMiterLimit',
|
||||
d: 'setDash',
|
||||
ri: 'setRenderingIntent',
|
||||
i: 'setFlatness',
|
||||
gs: 'setGState',
|
||||
q: 'save',
|
||||
Q: 'restore',
|
||||
cm: 'transform',
|
||||
|
||||
// Path
|
||||
m: 'moveTo',
|
||||
l: 'lineTo',
|
||||
c: 'curveTo',
|
||||
v: 'curveTo2',
|
||||
y: 'curveTo3',
|
||||
h: 'closePath',
|
||||
re: 'rectangle',
|
||||
S: 'stroke',
|
||||
s: 'closeStroke',
|
||||
f: 'fill',
|
||||
F: 'fill',
|
||||
'f*': 'eoFill',
|
||||
B: 'fillStroke',
|
||||
'B*': 'eoFillStroke',
|
||||
b: 'closeFillStroke',
|
||||
'b*': 'closeEOFillStroke',
|
||||
n: 'endPath',
|
||||
|
||||
// Clipping
|
||||
W: 'clip',
|
||||
'W*': 'eoClip',
|
||||
|
||||
// Text
|
||||
BT: 'beginText',
|
||||
ET: 'endText',
|
||||
Tc: 'setCharSpacing',
|
||||
Tw: 'setWordSpacing',
|
||||
Tz: 'setHScale',
|
||||
TL: 'setLeading',
|
||||
Tf: 'setFont',
|
||||
Tr: 'setTextRenderingMode',
|
||||
Ts: 'setTextRise',
|
||||
Td: 'moveText',
|
||||
TD: 'setLeadingMoveText',
|
||||
Tm: 'setTextMatrix',
|
||||
'T*': 'nextLine',
|
||||
Tj: 'showText',
|
||||
TJ: 'showSpacedText',
|
||||
"'": 'nextLineShowText',
|
||||
'"': 'nextLineSetSpacingShowText',
|
||||
|
||||
// Type3 fonts
|
||||
d0: 'setCharWidth',
|
||||
d1: 'setCharWidthAndBounds',
|
||||
|
||||
// Color
|
||||
CS: 'setStrokeColorSpace',
|
||||
cs: 'setFillColorSpace',
|
||||
SC: 'setStrokeColor',
|
||||
SCN: 'setStrokeColorN',
|
||||
sc: 'setFillColor',
|
||||
scn: 'setFillColorN',
|
||||
G: 'setStrokeGray',
|
||||
g: 'setFillGray',
|
||||
RG: 'setStrokeRGBColor',
|
||||
rg: 'setFillRGBColor',
|
||||
K: 'setStrokeCMYKColor',
|
||||
k: 'setFillCMYKColor',
|
||||
|
||||
// Shading
|
||||
sh: 'shadingFill',
|
||||
|
||||
// Images
|
||||
BI: 'beginInlineImage',
|
||||
ID: 'beginImageData',
|
||||
EI: 'endInlineImage',
|
||||
|
||||
// XObjects
|
||||
Do: 'paintXObject',
|
||||
|
||||
// Marked content
|
||||
MP: 'markPoint',
|
||||
DP: 'markPointProps',
|
||||
BMC: 'beginMarkedContent',
|
||||
BDC: 'beginMarkedContentProps',
|
||||
EMC: 'endMarkedContent',
|
||||
|
||||
// Compatibility
|
||||
BX: 'beginCompat',
|
||||
EX: 'endCompat'
|
||||
};
|
||||
|
||||
constructor.prototype = {
|
||||
getIRQueue: function partialEvaluatorGetIRQueue(stream, resources,
|
||||
queue, dependency) {
|
||||
|
||||
var self = this;
|
||||
var xref = this.xref;
|
||||
var handler = this.handler;
|
||||
var uniquePrefix = this.uniquePrefix;
|
||||
|
||||
function insertDependency(depList) {
|
||||
fnArray.push('dependency');
|
||||
argsArray.push(depList);
|
||||
for (var i = 0, ii = depList.length; i < ii; i++) {
|
||||
var dep = depList[i];
|
||||
if (dependency.indexOf(dep) == -1) {
|
||||
dependency.push(depList[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function handleSetFont(fontName, fontRef) {
|
||||
var loadedName = null;
|
||||
|
||||
var fontRes = resources.get('Font');
|
||||
|
||||
// TODO: TOASK: Is it possible to get here? If so, what does
|
||||
// args[0].name should be like???
|
||||
assert(fontRes, 'fontRes not available');
|
||||
|
||||
fontRes = xref.fetchIfRef(fontRes);
|
||||
fontRef = fontRef || fontRes.get(fontName);
|
||||
var font = xref.fetchIfRef(fontRef);
|
||||
assertWellFormed(isDict(font));
|
||||
if (!font.translated) {
|
||||
font.translated = self.translateFont(font, xref, resources,
|
||||
dependency);
|
||||
if (font.translated) {
|
||||
// keep track of each font we translated so the caller can
|
||||
// load them asynchronously before calling display on a page
|
||||
loadedName = 'font_' + uniquePrefix + (++self.objIdCounter);
|
||||
font.translated.properties.loadedName = loadedName;
|
||||
font.loadedName = loadedName;
|
||||
|
||||
var translated = font.translated;
|
||||
handler.send('obj', [
|
||||
loadedName,
|
||||
'Font',
|
||||
translated.name,
|
||||
translated.file,
|
||||
translated.properties
|
||||
]);
|
||||
}
|
||||
}
|
||||
loadedName = loadedName || font.loadedName;
|
||||
|
||||
// Ensure the font is ready before the font is set
|
||||
// and later on used for drawing.
|
||||
// TODO: This should get insert to the IRQueue only once per
|
||||
// page.
|
||||
insertDependency([loadedName]);
|
||||
return loadedName;
|
||||
}
|
||||
|
||||
function buildPaintImageXObject(image, inline) {
|
||||
var dict = image.dict;
|
||||
var w = dict.get('Width', 'W');
|
||||
var h = dict.get('Height', 'H');
|
||||
|
||||
if (image instanceof JpegStream && image.isNative) {
|
||||
var objId = 'img_' + uniquePrefix + (++self.objIdCounter);
|
||||
handler.send('obj', [objId, 'JpegStream', image.getIR()]);
|
||||
|
||||
// Add the dependency on the image object.
|
||||
insertDependency([objId]);
|
||||
|
||||
// The normal fn.
|
||||
fn = 'paintJpegXObject';
|
||||
args = [objId, w, h];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Needs to be rendered ourself.
|
||||
|
||||
// Figure out if the image has an imageMask.
|
||||
var imageMask = dict.get('ImageMask', 'IM') || false;
|
||||
|
||||
// If there is no imageMask, create the PDFImage and a lot
|
||||
// of image processing can be done here.
|
||||
if (!imageMask) {
|
||||
var imageObj = new PDFImage(xref, resources, image, inline);
|
||||
|
||||
if (imageObj.imageMask) {
|
||||
throw 'Can\'t handle this in the web worker :/';
|
||||
}
|
||||
|
||||
var imgData = {
|
||||
width: w,
|
||||
height: h,
|
||||
data: new Uint8Array(w * h * 4)
|
||||
};
|
||||
var pixels = imgData.data;
|
||||
imageObj.fillRgbaBuffer(pixels, imageObj.decode);
|
||||
|
||||
fn = 'paintImageXObject';
|
||||
args = [imgData];
|
||||
return;
|
||||
}
|
||||
|
||||
// This depends on a tmpCanvas beeing filled with the
|
||||
// current fillStyle, such that processing the pixel
|
||||
// data can't be done here. Instead of creating a
|
||||
// complete PDFImage, only read the information needed
|
||||
// for later.
|
||||
fn = 'paintImageMaskXObject';
|
||||
|
||||
var width = dict.get('Width', 'W');
|
||||
var height = dict.get('Height', 'H');
|
||||
var bitStrideLength = (width + 7) >> 3;
|
||||
var imgArray = image.getBytes(bitStrideLength * height);
|
||||
var decode = dict.get('Decode', 'D');
|
||||
var inverseDecode = !!decode && decode[0] > 0;
|
||||
|
||||
args = [imgArray, inverseDecode, width, height];
|
||||
}
|
||||
|
||||
uniquePrefix = uniquePrefix || '';
|
||||
if (!queue.argsArray) {
|
||||
queue.argsArray = [];
|
||||
}
|
||||
if (!queue.fnArray) {
|
||||
queue.fnArray = [];
|
||||
}
|
||||
|
||||
var fnArray = queue.fnArray, argsArray = queue.argsArray;
|
||||
var dependencyArray = dependency || [];
|
||||
|
||||
resources = xref.fetchIfRef(resources) || new Dict();
|
||||
var xobjs = xref.fetchIfRef(resources.get('XObject')) || new Dict();
|
||||
var patterns = xref.fetchIfRef(resources.get('Pattern')) || new Dict();
|
||||
var parser = new Parser(new Lexer(stream), false);
|
||||
var res = resources;
|
||||
var args = [], obj;
|
||||
var getObjBt = function getObjBt() {
|
||||
parser = this.oldParser;
|
||||
return { name: 'BT' };
|
||||
};
|
||||
var TILING_PATTERN = 1, SHADING_PATTERN = 2;
|
||||
|
||||
while (!isEOF(obj = parser.getObj())) {
|
||||
if (isCmd(obj)) {
|
||||
var cmd = obj.cmd;
|
||||
var fn = OP_MAP[cmd];
|
||||
if (!fn) {
|
||||
// invalid content command, trying to recover
|
||||
if (cmd.substr(-2) == 'BT') {
|
||||
fn = OP_MAP[cmd.substr(0, cmd.length - 2)];
|
||||
// feeding 'BT' on next interation
|
||||
parser = {
|
||||
getObj: getObjBt,
|
||||
oldParser: parser
|
||||
};
|
||||
}
|
||||
}
|
||||
assertWellFormed(fn, 'Unknown command "' + cmd + '"');
|
||||
// TODO figure out how to type-check vararg functions
|
||||
|
||||
if ((cmd == 'SCN' || cmd == 'scn') && !args[args.length - 1].code) {
|
||||
// Use the IR version for setStroke/FillColorN.
|
||||
fn += '_IR';
|
||||
|
||||
// compile tiling patterns
|
||||
var patternName = args[args.length - 1];
|
||||
// SCN/scn applies patterns along with normal colors
|
||||
if (isName(patternName)) {
|
||||
var pattern = xref.fetchIfRef(patterns.get(patternName.name));
|
||||
if (pattern) {
|
||||
var dict = isStream(pattern) ? pattern.dict : pattern;
|
||||
var typeNum = dict.get('PatternType');
|
||||
|
||||
if (typeNum == TILING_PATTERN) {
|
||||
// Create an IR of the pattern code.
|
||||
var depIdx = dependencyArray.length;
|
||||
var queueObj = {};
|
||||
var codeIR = this.getIRQueue(pattern, dict.get('Resources'),
|
||||
queueObj, dependencyArray);
|
||||
|
||||
// Add the dependencies that are required to execute the
|
||||
// codeIR.
|
||||
insertDependency(dependencyArray.slice(depIdx));
|
||||
|
||||
args = TilingPattern.getIR(codeIR, dict, args);
|
||||
}
|
||||
else if (typeNum == SHADING_PATTERN) {
|
||||
var shading = xref.fetchIfRef(dict.get('Shading'));
|
||||
var matrix = dict.get('Matrix');
|
||||
var pattern = Pattern.parseShading(shading, matrix, xref, res,
|
||||
null /*ctx*/);
|
||||
args = pattern.getIR();
|
||||
} else {
|
||||
error('Unkown PatternType ' + typeNum);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (cmd == 'Do' && !args[0].code) {
|
||||
// eagerly compile XForm objects
|
||||
var name = args[0].name;
|
||||
var xobj = xobjs.get(name);
|
||||
if (xobj) {
|
||||
xobj = xref.fetchIfRef(xobj);
|
||||
assertWellFormed(isStream(xobj), 'XObject should be a stream');
|
||||
|
||||
var type = xobj.dict.get('Subtype');
|
||||
assertWellFormed(
|
||||
isName(type),
|
||||
'XObject should have a Name subtype'
|
||||
);
|
||||
|
||||
if ('Form' == type.name) {
|
||||
var matrix = xobj.dict.get('Matrix');
|
||||
var bbox = xobj.dict.get('BBox');
|
||||
|
||||
fnArray.push('paintFormXObjectBegin');
|
||||
argsArray.push([matrix, bbox]);
|
||||
|
||||
// This adds the IRQueue of the xObj to the current queue.
|
||||
var depIdx = dependencyArray.length;
|
||||
|
||||
this.getIRQueue(xobj, xobj.dict.get('Resources'), queue,
|
||||
dependencyArray);
|
||||
|
||||
// Add the dependencies that are required to execute the
|
||||
// codeIR.
|
||||
insertDependency(dependencyArray.slice(depIdx));
|
||||
|
||||
fn = 'paintFormXObjectEnd';
|
||||
args = [];
|
||||
} else if ('Image' == type.name) {
|
||||
buildPaintImageXObject(xobj, false);
|
||||
} else {
|
||||
error('Unhandled XObject subtype ' + type.name);
|
||||
}
|
||||
}
|
||||
} else if (cmd == 'Tf') { // eagerly collect all fonts
|
||||
args[0] = handleSetFont(args[0].name);
|
||||
} else if (cmd == 'EI') {
|
||||
buildPaintImageXObject(args[0], true);
|
||||
}
|
||||
|
||||
switch (fn) {
|
||||
// Parse the ColorSpace data to a raw format.
|
||||
case 'setFillColorSpace':
|
||||
case 'setStrokeColorSpace':
|
||||
args = [ColorSpace.parseToIR(args[0], xref, resources)];
|
||||
break;
|
||||
case 'shadingFill':
|
||||
var shadingRes = xref.fetchIfRef(res.get('Shading'));
|
||||
if (!shadingRes)
|
||||
error('No shading resource found');
|
||||
|
||||
var shading = xref.fetchIfRef(shadingRes.get(args[0].name));
|
||||
if (!shading)
|
||||
error('No shading object found');
|
||||
|
||||
var shadingFill = Pattern.parseShading(shading, null, xref, res,
|
||||
null);
|
||||
var patternIR = shadingFill.getIR();
|
||||
args = [patternIR];
|
||||
fn = 'shadingFill';
|
||||
break;
|
||||
case 'setGState':
|
||||
var dictName = args[0];
|
||||
var extGState = xref.fetchIfRef(resources.get('ExtGState'));
|
||||
|
||||
if (!isDict(extGState) || !extGState.has(dictName.name))
|
||||
break;
|
||||
|
||||
var gsState = xref.fetchIfRef(extGState.get(dictName.name));
|
||||
|
||||
// This array holds the converted/processed state data.
|
||||
var gsStateObj = [];
|
||||
|
||||
gsState.forEach(
|
||||
function canvasGraphicsSetGStateForEach(key, value) {
|
||||
switch (key) {
|
||||
case 'Type':
|
||||
break;
|
||||
case 'LW':
|
||||
case 'LC':
|
||||
case 'LJ':
|
||||
case 'ML':
|
||||
case 'D':
|
||||
case 'RI':
|
||||
case 'FL':
|
||||
case 'CA':
|
||||
case 'ca':
|
||||
gsStateObj.push([key, value]);
|
||||
break;
|
||||
case 'Font':
|
||||
gsStateObj.push([
|
||||
'Font',
|
||||
handleSetFont(null, value[0]),
|
||||
value[1]
|
||||
]);
|
||||
break;
|
||||
case 'OP':
|
||||
case 'op':
|
||||
case 'OPM':
|
||||
case 'BG':
|
||||
case 'BG2':
|
||||
case 'UCR':
|
||||
case 'UCR2':
|
||||
case 'TR':
|
||||
case 'TR2':
|
||||
case 'HT':
|
||||
case 'SM':
|
||||
case 'SA':
|
||||
case 'BM':
|
||||
case 'SMask':
|
||||
case 'AIS':
|
||||
case 'TK':
|
||||
TODO('graphic state operator ' + key);
|
||||
break;
|
||||
default:
|
||||
warn('Unknown graphic state operator ' + key);
|
||||
break;
|
||||
}
|
||||
}
|
||||
);
|
||||
args = [gsStateObj];
|
||||
break;
|
||||
} // switch
|
||||
|
||||
fnArray.push(fn);
|
||||
argsArray.push(args);
|
||||
args = [];
|
||||
} else if (obj != null) {
|
||||
assertWellFormed(args.length <= 33, 'Too many arguments');
|
||||
args.push(obj);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
fnArray: fnArray,
|
||||
argsArray: argsArray
|
||||
};
|
||||
},
|
||||
|
||||
extractDataStructures: function
|
||||
partialEvaluatorExtractDataStructures(dict, baseDict,
|
||||
xref, properties) {
|
||||
// 9.10.2
|
||||
var toUnicode = dict.get('ToUnicode') ||
|
||||
baseDict.get('ToUnicode');
|
||||
if (toUnicode)
|
||||
properties.toUnicode = this.readToUnicode(toUnicode, xref);
|
||||
|
||||
if (properties.composite) {
|
||||
// CIDSystemInfo helps to match CID to glyphs
|
||||
var cidSystemInfo = xref.fetchIfRef(dict.get('CIDSystemInfo'));
|
||||
if (isDict(cidSystemInfo)) {
|
||||
properties.cidSystemInfo = {
|
||||
registry: cidSystemInfo.get('Registry'),
|
||||
ordering: cidSystemInfo.get('Ordering'),
|
||||
supplement: cidSystemInfo.get('Supplement')
|
||||
};
|
||||
}
|
||||
|
||||
var cidToGidMap = xref.fetchIfRef(dict.get('CIDToGIDMap'));
|
||||
if (isStream(cidToGidMap))
|
||||
properties.cidToGidMap = this.readCidToGidMap(cidToGidMap);
|
||||
}
|
||||
|
||||
var differences = [];
|
||||
var baseEncoding = Encodings.StandardEncoding;
|
||||
var hasEncoding = dict.has('Encoding');
|
||||
if (hasEncoding) {
|
||||
var encoding = xref.fetchIfRef(dict.get('Encoding'));
|
||||
if (isDict(encoding)) {
|
||||
var baseName = encoding.get('BaseEncoding');
|
||||
if (baseName)
|
||||
baseEncoding = Encodings[baseName.name];
|
||||
|
||||
// Load the differences between the base and original
|
||||
if (encoding.has('Differences')) {
|
||||
var diffEncoding = encoding.get('Differences');
|
||||
var index = 0;
|
||||
for (var j = 0, jj = diffEncoding.length; j < jj; j++) {
|
||||
var data = diffEncoding[j];
|
||||
if (isNum(data))
|
||||
index = data;
|
||||
else
|
||||
differences[index++] = data.name;
|
||||
}
|
||||
}
|
||||
} else if (isName(encoding)) {
|
||||
baseEncoding = Encodings[encoding.name];
|
||||
} else {
|
||||
error('Encoding is not a Name nor a Dict');
|
||||
}
|
||||
}
|
||||
properties.differences = differences;
|
||||
properties.baseEncoding = baseEncoding;
|
||||
properties.hasEncoding = hasEncoding;
|
||||
},
|
||||
|
||||
readToUnicode:
|
||||
function partialEvaluatorReadToUnicode(toUnicode, xref) {
|
||||
var cmapObj = xref.fetchIfRef(toUnicode);
|
||||
var charToUnicode = [];
|
||||
if (isName(cmapObj)) {
|
||||
var isIdentityMap = cmapObj.name.substr(0, 9) == 'Identity-';
|
||||
if (!isIdentityMap)
|
||||
error('ToUnicode file cmap translation not implemented');
|
||||
} else if (isStream(cmapObj)) {
|
||||
var tokens = [];
|
||||
var token = '';
|
||||
var beginArrayToken = {};
|
||||
|
||||
var cmap = cmapObj.getBytes(cmapObj.length);
|
||||
for (var i = 0, ii = cmap.length; i < ii; i++) {
|
||||
var byte = cmap[i];
|
||||
if (byte == 0x20 || byte == 0x0D || byte == 0x0A ||
|
||||
byte == 0x3C || byte == 0x5B || byte == 0x5D) {
|
||||
switch (token) {
|
||||
case 'usecmap':
|
||||
error('usecmap is not implemented');
|
||||
break;
|
||||
|
||||
case 'beginbfchar':
|
||||
case 'beginbfrange':
|
||||
case 'begincidchar':
|
||||
case 'begincidrange':
|
||||
token = '';
|
||||
tokens = [];
|
||||
break;
|
||||
|
||||
case 'endcidrange':
|
||||
case 'endbfrange':
|
||||
for (var j = 0, jj = tokens.length; j < jj; j += 3) {
|
||||
var startRange = tokens[j];
|
||||
var endRange = tokens[j + 1];
|
||||
var code = tokens[j + 2];
|
||||
while (startRange <= endRange) {
|
||||
charToUnicode[startRange] = code++;
|
||||
++startRange;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'endcidchar':
|
||||
case 'endbfchar':
|
||||
for (var j = 0, jj = tokens.length; j < jj; j += 2) {
|
||||
var index = tokens[j];
|
||||
var code = tokens[j + 1];
|
||||
charToUnicode[index] = code;
|
||||
}
|
||||
break;
|
||||
|
||||
case '':
|
||||
break;
|
||||
|
||||
default:
|
||||
if (token[0] >= '0' && token[0] <= '9')
|
||||
token = parseInt(token, 10); // a number
|
||||
tokens.push(token);
|
||||
token = '';
|
||||
}
|
||||
switch (byte) {
|
||||
case 0x5B:
|
||||
// begin list parsing
|
||||
tokens.push(beginArrayToken);
|
||||
break;
|
||||
case 0x5D:
|
||||
// collect array items
|
||||
var items = [], item;
|
||||
while (tokens.length &&
|
||||
(item = tokens.pop()) != beginArrayToken)
|
||||
items.unshift(item);
|
||||
tokens.push(items);
|
||||
break;
|
||||
}
|
||||
} else if (byte == 0x3E) {
|
||||
if (token.length) {
|
||||
// parsing hex number
|
||||
tokens.push(parseInt(token, 16));
|
||||
token = '';
|
||||
}
|
||||
} else {
|
||||
token += String.fromCharCode(byte);
|
||||
}
|
||||
}
|
||||
}
|
||||
return charToUnicode;
|
||||
},
|
||||
readCidToGidMap:
|
||||
function partialEvaluatorReadCidToGidMap(cidToGidStream) {
|
||||
// Extract the encoding from the CIDToGIDMap
|
||||
var glyphsData = cidToGidStream.getBytes();
|
||||
|
||||
// Set encoding 0 to later verify the font has an encoding
|
||||
var result = [];
|
||||
for (var j = 0, jj = glyphsData.length; j < jj; j++) {
|
||||
var glyphID = (glyphsData[j++] << 8) | glyphsData[j];
|
||||
if (glyphID == 0)
|
||||
continue;
|
||||
|
||||
var code = j >> 1;
|
||||
result[code] = glyphID;
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
||||
extractWidths: function partialEvaluatorWidths(dict,
|
||||
xref,
|
||||
descriptor,
|
||||
properties) {
|
||||
var glyphsWidths = [];
|
||||
var defaultWidth = 0;
|
||||
if (properties.composite) {
|
||||
defaultWidth = xref.fetchIfRef(dict.get('DW')) || 1000;
|
||||
|
||||
var widths = xref.fetchIfRef(dict.get('W'));
|
||||
if (widths) {
|
||||
var start = 0, end = 0;
|
||||
for (var i = 0, ii = widths.length; i < ii; i++) {
|
||||
var code = widths[i];
|
||||
if (isArray(code)) {
|
||||
for (var j = 0, jj = code.length; j < jj; j++)
|
||||
glyphsWidths[start++] = code[j];
|
||||
start = 0;
|
||||
} else if (start) {
|
||||
var width = widths[++i];
|
||||
for (var j = start; j <= code; j++)
|
||||
glyphsWidths[j] = width;
|
||||
start = 0;
|
||||
} else {
|
||||
start = code;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var firstChar = properties.firstChar;
|
||||
var widths = xref.fetchIfRef(dict.get('Widths'));
|
||||
if (widths) {
|
||||
var j = firstChar;
|
||||
for (var i = 0, ii = widths.length; i < ii; i++)
|
||||
glyphsWidths[j++] = widths[i];
|
||||
defaultWidth = parseFloat(descriptor.get('MissingWidth')) || 0;
|
||||
} else {
|
||||
// Trying get the BaseFont metrics (see comment above).
|
||||
var baseFontName = dict.get('BaseFont');
|
||||
if (isName(baseFontName)) {
|
||||
var metrics = this.getBaseFontMetrics(baseFontName.name);
|
||||
|
||||
glyphsWidths = metrics.widths;
|
||||
defaultWidth = metrics.defaultWidth;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
properties.defaultWidth = defaultWidth;
|
||||
properties.widths = glyphsWidths;
|
||||
},
|
||||
|
||||
getBaseFontMetrics: function getBaseFontMetrics(name) {
|
||||
var defaultWidth = 0, widths = [];
|
||||
var glyphWidths = Metrics[stdFontMap[name] || name];
|
||||
if (isNum(glyphWidths)) {
|
||||
defaultWidth = glyphWidths;
|
||||
} else {
|
||||
widths = glyphWidths;
|
||||
}
|
||||
|
||||
return {
|
||||
defaultWidth: defaultWidth,
|
||||
widths: widths
|
||||
};
|
||||
},
|
||||
|
||||
translateFont: function partialEvaluatorTranslateFont(dict, xref, resources,
|
||||
dependency) {
|
||||
var baseDict = dict;
|
||||
var type = dict.get('Subtype');
|
||||
assertWellFormed(isName(type), 'invalid font Subtype');
|
||||
|
||||
var composite = false;
|
||||
if (type.name == 'Type0') {
|
||||
// If font is a composite
|
||||
// - get the descendant font
|
||||
// - set the type according to the descendant font
|
||||
// - get the FontDescriptor from the descendant font
|
||||
var df = dict.get('DescendantFonts');
|
||||
if (!df)
|
||||
return null;
|
||||
|
||||
if (isRef(df))
|
||||
df = xref.fetch(df);
|
||||
|
||||
dict = xref.fetchIfRef(isRef(df) ? df : df[0]);
|
||||
|
||||
type = dict.get('Subtype');
|
||||
assertWellFormed(isName(type), 'invalid font Subtype');
|
||||
composite = true;
|
||||
}
|
||||
var maxCharIndex = composite ? 0xFFFF : 0xFF;
|
||||
|
||||
var descriptor = xref.fetchIfRef(dict.get('FontDescriptor'));
|
||||
if (!descriptor) {
|
||||
if (type.name == 'Type3') {
|
||||
// FontDescriptor is only required for Type3 fonts when the document
|
||||
// is a tagged pdf. Create a barbebones one to get by.
|
||||
descriptor = new Dict();
|
||||
descriptor.set('FontName', new Name(type.name));
|
||||
} else {
|
||||
// Before PDF 1.5 if the font was one of the base 14 fonts, having a
|
||||
// FontDescriptor was not required.
|
||||
// This case is here for compatibility.
|
||||
var baseFontName = dict.get('BaseFont');
|
||||
if (!isName(baseFontName))
|
||||
return null;
|
||||
|
||||
// Using base font name as a font name.
|
||||
baseFontName = baseFontName.name.replace(/[,_]/g, '-');
|
||||
var metrics = this.getBaseFontMetrics(baseFontName);
|
||||
|
||||
var properties = {
|
||||
type: type.name,
|
||||
widths: metrics.widths,
|
||||
defaultWidth: metrics.defaultWidth,
|
||||
firstChar: 0,
|
||||
lastChar: maxCharIndex
|
||||
};
|
||||
this.extractDataStructures(dict, dict, xref, properties);
|
||||
|
||||
return {
|
||||
name: baseFontName,
|
||||
dict: baseDict,
|
||||
properties: properties
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// According to the spec if 'FontDescriptor' is declared, 'FirstChar',
|
||||
// 'LastChar' and 'Widths' should exists too, but some PDF encoders seems
|
||||
// to ignore this rule when a variant of a standart font is used.
|
||||
// TODO Fill the width array depending on which of the base font this is
|
||||
// a variant.
|
||||
var firstChar = xref.fetchIfRef(dict.get('FirstChar')) || 0;
|
||||
var lastChar = xref.fetchIfRef(dict.get('LastChar')) || maxCharIndex;
|
||||
var fontName = xref.fetchIfRef(descriptor.get('FontName'));
|
||||
assertWellFormed(isName(fontName), 'invalid font name');
|
||||
|
||||
var fontFile = descriptor.get('FontFile', 'FontFile2', 'FontFile3');
|
||||
if (fontFile) {
|
||||
fontFile = xref.fetchIfRef(fontFile);
|
||||
if (fontFile.dict) {
|
||||
var subtype = fontFile.dict.get('Subtype');
|
||||
if (subtype)
|
||||
subtype = subtype.name;
|
||||
|
||||
var length1 = fontFile.dict.get('Length1');
|
||||
if (!isInt(length1))
|
||||
length1 = xref.fetchIfRef(length1);
|
||||
|
||||
var length2 = fontFile.dict.get('Length2');
|
||||
if (!isInt(length2))
|
||||
length2 = xref.fetchIfRef(length2);
|
||||
}
|
||||
}
|
||||
|
||||
var properties = {
|
||||
type: type.name,
|
||||
subtype: subtype,
|
||||
file: fontFile,
|
||||
length1: length1,
|
||||
length2: length2,
|
||||
composite: composite,
|
||||
fixedPitch: false,
|
||||
fontMatrix: dict.get('FontMatrix') || IDENTITY_MATRIX,
|
||||
firstChar: firstChar || 0,
|
||||
lastChar: lastChar || maxCharIndex,
|
||||
bbox: descriptor.get('FontBBox'),
|
||||
ascent: descriptor.get('Ascent'),
|
||||
descent: descriptor.get('Descent'),
|
||||
xHeight: descriptor.get('XHeight'),
|
||||
capHeight: descriptor.get('CapHeight'),
|
||||
flags: descriptor.get('Flags'),
|
||||
italicAngle: descriptor.get('ItalicAngle'),
|
||||
coded: false
|
||||
};
|
||||
this.extractWidths(dict, xref, descriptor, properties);
|
||||
this.extractDataStructures(dict, baseDict, xref, properties);
|
||||
|
||||
if (type.name === 'Type3') {
|
||||
properties.coded = true;
|
||||
var charProcs = xref.fetchIfRef(dict.get('CharProcs'));
|
||||
var fontResources = xref.fetchIfRef(dict.get('Resources')) || resources;
|
||||
properties.resources = fontResources;
|
||||
properties.charProcIRQueues = {};
|
||||
for (var key in charProcs.map) {
|
||||
var glyphStream = xref.fetchIfRef(charProcs.map[key]);
|
||||
var queueObj = {};
|
||||
properties.charProcIRQueues[key] =
|
||||
this.getIRQueue(glyphStream, fontResources, queueObj, dependency);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
name: fontName.name,
|
||||
dict: baseDict,
|
||||
file: fontFile,
|
||||
properties: properties
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
return constructor;
|
||||
})();
|
||||
|
||||
var EvalState = (function evalState() {
|
||||
function constructor() {
|
||||
// Are soft masks and alpha values shapes or opacities?
|
||||
this.alphaIsShape = false;
|
||||
this.fontSize = 0;
|
||||
this.textMatrix = IDENTITY_MATRIX;
|
||||
this.leading = 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;
|
||||
// Color spaces
|
||||
this.fillColorSpace = null;
|
||||
this.strokeColorSpace = null;
|
||||
}
|
||||
constructor.prototype = {
|
||||
};
|
||||
return constructor;
|
||||
})();
|
||||
|
|
@ -0,0 +1,351 @@
|
|||
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
|
||||
|
||||
'use strict';
|
||||
|
||||
var PDFFunction = (function pdfFunction() {
|
||||
var CONSTRUCT_SAMPLED = 0;
|
||||
var CONSTRUCT_INTERPOLATED = 2;
|
||||
var CONSTRUCT_STICHED = 3;
|
||||
var CONSTRUCT_POSTSCRIPT = 4;
|
||||
|
||||
return {
|
||||
getSampleArray: function pdfFunctionGetSampleArray(size, outputSize, bps,
|
||||
str) {
|
||||
var length = 1;
|
||||
for (var i = 0, ii = size.length; i < ii; i++)
|
||||
length *= size[i];
|
||||
length *= outputSize;
|
||||
|
||||
var array = [];
|
||||
var codeSize = 0;
|
||||
var codeBuf = 0;
|
||||
// 32 is a valid bps so shifting won't work
|
||||
var sampleMul = 1.0 / (Math.pow(2.0, bps) - 1);
|
||||
|
||||
var strBytes = str.getBytes((length * bps + 7) / 8);
|
||||
var strIdx = 0;
|
||||
for (var i = 0; i < length; i++) {
|
||||
while (codeSize < bps) {
|
||||
codeBuf <<= 8;
|
||||
codeBuf |= strBytes[strIdx++];
|
||||
codeSize += 8;
|
||||
}
|
||||
codeSize -= bps;
|
||||
array.push((codeBuf >> codeSize) * sampleMul);
|
||||
codeBuf &= (1 << codeSize) - 1;
|
||||
}
|
||||
return array;
|
||||
},
|
||||
|
||||
getIR: function pdfFunctionGetIR(xref, fn) {
|
||||
var dict = fn.dict;
|
||||
if (!dict)
|
||||
dict = fn;
|
||||
|
||||
var types = [this.constructSampled,
|
||||
null,
|
||||
this.constructInterpolated,
|
||||
this.constructStiched,
|
||||
this.constructPostScript];
|
||||
|
||||
var typeNum = dict.get('FunctionType');
|
||||
var typeFn = types[typeNum];
|
||||
if (!typeFn)
|
||||
error('Unknown type of function');
|
||||
|
||||
return typeFn.call(this, fn, dict, xref);
|
||||
},
|
||||
|
||||
fromIR: function pdfFunctionFromIR(IR) {
|
||||
var type = IR[0];
|
||||
switch (type) {
|
||||
case CONSTRUCT_SAMPLED:
|
||||
return this.constructSampledFromIR(IR);
|
||||
case CONSTRUCT_INTERPOLATED:
|
||||
return this.constructInterpolatedFromIR(IR);
|
||||
case CONSTRUCT_STICHED:
|
||||
return this.constructStichedFromIR(IR);
|
||||
case CONSTRUCT_POSTSCRIPT:
|
||||
default:
|
||||
return this.constructPostScriptFromIR(IR);
|
||||
}
|
||||
},
|
||||
|
||||
parse: function pdfFunctionParse(xref, fn) {
|
||||
var IR = this.getIR(xref, fn);
|
||||
return this.fromIR(IR);
|
||||
},
|
||||
|
||||
constructSampled: function pdfFunctionConstructSampled(str, dict) {
|
||||
function toMultiArray(arr) {
|
||||
var inputLength = arr.length;
|
||||
var outputLength = arr.length / 2;
|
||||
var out = new Array(outputLength);
|
||||
var index = 0;
|
||||
for (var i = 0; i < inputLength; i += 2) {
|
||||
out[index] = [arr[i], arr[i + 1]];
|
||||
++index;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
var domain = dict.get('Domain');
|
||||
var range = dict.get('Range');
|
||||
|
||||
if (!domain || !range)
|
||||
error('No domain or range');
|
||||
|
||||
var inputSize = domain.length / 2;
|
||||
var outputSize = range.length / 2;
|
||||
|
||||
domain = toMultiArray(domain);
|
||||
range = toMultiArray(range);
|
||||
|
||||
var size = dict.get('Size');
|
||||
var bps = dict.get('BitsPerSample');
|
||||
var order = dict.get('Order');
|
||||
if (!order)
|
||||
order = 1;
|
||||
if (order !== 1)
|
||||
error('No support for cubic spline interpolation: ' + order);
|
||||
|
||||
var encode = dict.get('Encode');
|
||||
if (!encode) {
|
||||
encode = [];
|
||||
for (var i = 0; i < inputSize; ++i) {
|
||||
encode.push(0);
|
||||
encode.push(size[i] - 1);
|
||||
}
|
||||
}
|
||||
encode = toMultiArray(encode);
|
||||
|
||||
var decode = dict.get('Decode');
|
||||
if (!decode)
|
||||
decode = range;
|
||||
else
|
||||
decode = toMultiArray(decode);
|
||||
|
||||
// Precalc the multipliers
|
||||
var inputMul = new Float64Array(inputSize);
|
||||
for (var i = 0; i < inputSize; ++i) {
|
||||
inputMul[i] = (encode[i][1] - encode[i][0]) /
|
||||
(domain[i][1] - domain[i][0]);
|
||||
}
|
||||
|
||||
var idxMul = new Int32Array(inputSize);
|
||||
idxMul[0] = outputSize;
|
||||
for (i = 1; i < inputSize; ++i) {
|
||||
idxMul[i] = idxMul[i - 1] * size[i - 1];
|
||||
}
|
||||
|
||||
var nSamples = outputSize;
|
||||
for (i = 0; i < inputSize; ++i)
|
||||
nSamples *= size[i];
|
||||
|
||||
var samples = this.getSampleArray(size, outputSize, bps, str);
|
||||
|
||||
return [
|
||||
CONSTRUCT_SAMPLED, inputSize, domain, encode, decode, samples, size,
|
||||
outputSize, bps, range, inputMul, idxMul, nSamples
|
||||
];
|
||||
},
|
||||
|
||||
constructSampledFromIR: function pdfFunctionConstructSampledFromIR(IR) {
|
||||
var inputSize = IR[1];
|
||||
var domain = IR[2];
|
||||
var encode = IR[3];
|
||||
var decode = IR[4];
|
||||
var samples = IR[5];
|
||||
var size = IR[6];
|
||||
var outputSize = IR[7];
|
||||
var bps = IR[8];
|
||||
var range = IR[9];
|
||||
var inputMul = IR[10];
|
||||
var idxMul = IR[11];
|
||||
var nSamples = IR[12];
|
||||
|
||||
return function constructSampledFromIRResult(args) {
|
||||
if (inputSize != args.length)
|
||||
error('Incorrect number of arguments: ' + inputSize + ' != ' +
|
||||
args.length);
|
||||
// Most of the below is a port of Poppler's implementation.
|
||||
// TODO: There's a few other ways to do multilinear interpolation such
|
||||
// as piecewise, which is much faster but an approximation.
|
||||
var out = new Float64Array(outputSize);
|
||||
var x;
|
||||
var e = new Array(inputSize);
|
||||
var efrac0 = new Float64Array(inputSize);
|
||||
var efrac1 = new Float64Array(inputSize);
|
||||
var sBuf = new Float64Array(1 << inputSize);
|
||||
var i, j, k, idx, t;
|
||||
|
||||
// map input values into sample array
|
||||
for (i = 0; i < inputSize; ++i) {
|
||||
x = (args[i] - domain[i][0]) * inputMul[i] + encode[i][0];
|
||||
if (x < 0) {
|
||||
x = 0;
|
||||
} else if (x > size[i] - 1) {
|
||||
x = size[i] - 1;
|
||||
}
|
||||
e[i] = [Math.floor(x), 0];
|
||||
if ((e[i][1] = e[i][0] + 1) >= size[i]) {
|
||||
// this happens if in[i] = domain[i][1]
|
||||
e[i][1] = e[i][0];
|
||||
}
|
||||
efrac1[i] = x - e[i][0];
|
||||
efrac0[i] = 1 - efrac1[i];
|
||||
}
|
||||
|
||||
// for each output, do m-linear interpolation
|
||||
for (i = 0; i < outputSize; ++i) {
|
||||
|
||||
// pull 2^m values out of the sample array
|
||||
for (j = 0; j < (1 << inputSize); ++j) {
|
||||
idx = i;
|
||||
for (k = 0, t = j; k < inputSize; ++k, t >>= 1) {
|
||||
idx += idxMul[k] * (e[k][t & 1]);
|
||||
}
|
||||
if (idx >= 0 && idx < nSamples) {
|
||||
sBuf[j] = samples[idx];
|
||||
} else {
|
||||
sBuf[j] = 0; // TODO Investigate if this is what Adobe does
|
||||
}
|
||||
}
|
||||
|
||||
// do m sets of interpolations
|
||||
for (j = 0, t = (1 << inputSize); j < inputSize; ++j, t >>= 1) {
|
||||
for (k = 0; k < t; k += 2) {
|
||||
sBuf[k >> 1] = efrac0[j] * sBuf[k] + efrac1[j] * sBuf[k + 1];
|
||||
}
|
||||
}
|
||||
|
||||
// map output value to range
|
||||
out[i] = (sBuf[0] * (decode[i][1] - decode[i][0]) + decode[i][0]);
|
||||
if (out[i] < range[i][0]) {
|
||||
out[i] = range[i][0];
|
||||
} else if (out[i] > range[i][1]) {
|
||||
out[i] = range[i][1];
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
},
|
||||
|
||||
constructInterpolated:
|
||||
function pdfFunctionConstructInterpolated(str, dict) {
|
||||
var c0 = dict.get('C0') || [0];
|
||||
var c1 = dict.get('C1') || [1];
|
||||
var n = dict.get('N');
|
||||
|
||||
if (!isArray(c0) || !isArray(c1))
|
||||
error('Illegal dictionary for interpolated function');
|
||||
|
||||
var length = c0.length;
|
||||
var diff = [];
|
||||
for (var i = 0; i < length; ++i)
|
||||
diff.push(c1[i] - c0[i]);
|
||||
|
||||
return [CONSTRUCT_INTERPOLATED, c0, diff, n];
|
||||
},
|
||||
|
||||
constructInterpolatedFromIR:
|
||||
function pdfFunctionconstructInterpolatedFromIR(IR) {
|
||||
var c0 = IR[1];
|
||||
var diff = IR[2];
|
||||
var n = IR[3];
|
||||
|
||||
var length = diff.length;
|
||||
|
||||
return function constructInterpolatedFromIRResult(args) {
|
||||
var x = n == 1 ? args[0] : Math.pow(args[0], n);
|
||||
|
||||
var out = [];
|
||||
for (var j = 0; j < length; ++j)
|
||||
out.push(c0[j] + (x * diff[j]));
|
||||
|
||||
return out;
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
constructStiched: function pdfFunctionConstructStiched(fn, dict, xref) {
|
||||
var domain = dict.get('Domain');
|
||||
var range = dict.get('Range');
|
||||
|
||||
if (!domain)
|
||||
error('No domain');
|
||||
|
||||
var inputSize = domain.length / 2;
|
||||
if (inputSize != 1)
|
||||
error('Bad domain for stiched function');
|
||||
|
||||
var fnRefs = dict.get('Functions');
|
||||
var fns = [];
|
||||
for (var i = 0, ii = fnRefs.length; i < ii; ++i)
|
||||
fns.push(PDFFunction.getIR(xref, xref.fetchIfRef(fnRefs[i])));
|
||||
|
||||
var bounds = dict.get('Bounds');
|
||||
var encode = dict.get('Encode');
|
||||
|
||||
return [CONSTRUCT_STICHED, domain, bounds, encode, fns];
|
||||
},
|
||||
|
||||
constructStichedFromIR: function pdfFunctionConstructStichedFromIR(IR) {
|
||||
var domain = IR[1];
|
||||
var bounds = IR[2];
|
||||
var encode = IR[3];
|
||||
var fnsIR = IR[4];
|
||||
var fns = [];
|
||||
|
||||
for (var i = 0, ii = fnsIR.length; i < ii; i++) {
|
||||
fns.push(PDFFunction.fromIR(fnsIR[i]));
|
||||
}
|
||||
|
||||
return function constructStichedFromIRResult(args) {
|
||||
var clip = function constructStichedFromIRClip(v, min, max) {
|
||||
if (v > max)
|
||||
v = max;
|
||||
else if (v < min)
|
||||
v = min;
|
||||
return v;
|
||||
};
|
||||
|
||||
// clip to domain
|
||||
var v = clip(args[0], domain[0], domain[1]);
|
||||
// calulate which bound the value is in
|
||||
for (var i = 0, ii = bounds.length; i < ii; ++i) {
|
||||
if (v < bounds[i])
|
||||
break;
|
||||
}
|
||||
|
||||
// encode value into domain of function
|
||||
var dmin = domain[0];
|
||||
if (i > 0)
|
||||
dmin = bounds[i - 1];
|
||||
var dmax = domain[1];
|
||||
if (i < bounds.length)
|
||||
dmax = bounds[i];
|
||||
|
||||
var rmin = encode[2 * i];
|
||||
var rmax = encode[2 * i + 1];
|
||||
|
||||
var v2 = rmin + (v - dmin) * (rmax - rmin) / (dmax - dmin);
|
||||
|
||||
// call the appropropriate function
|
||||
return fns[i]([v2]);
|
||||
};
|
||||
},
|
||||
|
||||
constructPostScript: function pdfFunctionConstructPostScript() {
|
||||
return [CONSTRUCT_POSTSCRIPT];
|
||||
},
|
||||
|
||||
constructPostScriptFromIR: function pdfFunctionConstructPostScriptFromIR() {
|
||||
TODO('unhandled type of function');
|
||||
return function constructPostScriptFromIRResult() {
|
||||
return [255, 105, 180];
|
||||
};
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
|
@ -0,0 +1,257 @@
|
|||
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
|
||||
|
||||
'use strict';
|
||||
|
||||
var PDFImage = (function pdfImage() {
|
||||
function constructor(xref, res, image, inline) {
|
||||
this.image = image;
|
||||
if (image.getParams) {
|
||||
// JPX/JPEG2000 streams directly contain bits per component
|
||||
// and color space mode information.
|
||||
TODO('get params from actual stream');
|
||||
// var bits = ...
|
||||
// var colorspace = ...
|
||||
}
|
||||
// TODO cache rendered images?
|
||||
|
||||
var dict = image.dict;
|
||||
this.width = dict.get('Width', 'W');
|
||||
this.height = dict.get('Height', 'H');
|
||||
|
||||
if (this.width < 1 || this.height < 1)
|
||||
error('Invalid image width: ' + this.width + ' or height: ' +
|
||||
this.height);
|
||||
|
||||
this.interpolate = dict.get('Interpolate', 'I') || false;
|
||||
this.imageMask = dict.get('ImageMask', 'IM') || false;
|
||||
|
||||
var bitsPerComponent = image.bitsPerComponent;
|
||||
if (!bitsPerComponent) {
|
||||
bitsPerComponent = dict.get('BitsPerComponent', 'BPC');
|
||||
if (!bitsPerComponent) {
|
||||
if (this.imageMask)
|
||||
bitsPerComponent = 1;
|
||||
else
|
||||
error('Bits per component missing in image: ' + this.imageMask);
|
||||
}
|
||||
}
|
||||
this.bpc = bitsPerComponent;
|
||||
|
||||
if (!this.imageMask) {
|
||||
var colorSpace = dict.get('ColorSpace', 'CS');
|
||||
if (!colorSpace) {
|
||||
TODO('JPX images (which don"t require color spaces');
|
||||
colorSpace = new Name('DeviceRGB');
|
||||
}
|
||||
this.colorSpace = ColorSpace.parse(colorSpace, xref, res);
|
||||
this.numComps = this.colorSpace.numComps;
|
||||
}
|
||||
|
||||
this.decode = dict.get('Decode', 'D');
|
||||
|
||||
var mask = xref.fetchIfRef(dict.get('Mask'));
|
||||
var smask = xref.fetchIfRef(dict.get('SMask'));
|
||||
|
||||
if (mask) {
|
||||
TODO('masked images');
|
||||
} else if (smask) {
|
||||
this.smask = new PDFImage(xref, res, smask);
|
||||
}
|
||||
}
|
||||
|
||||
constructor.prototype = {
|
||||
getComponents: function getComponents(buffer, decodeMap) {
|
||||
var bpc = this.bpc;
|
||||
if (bpc == 8)
|
||||
return buffer;
|
||||
|
||||
var width = this.width;
|
||||
var height = this.height;
|
||||
var numComps = this.numComps;
|
||||
|
||||
var length = width * height;
|
||||
var bufferPos = 0;
|
||||
var output = bpc <= 8 ? new Uint8Array(length) :
|
||||
bpc <= 16 ? new Uint16Array(length) : new Uint32Array(length);
|
||||
var rowComps = width * numComps;
|
||||
|
||||
if (bpc == 1) {
|
||||
var valueZero = 0, valueOne = 1;
|
||||
if (decodeMap) {
|
||||
valueZero = decodeMap[0] ? 1 : 0;
|
||||
valueOne = decodeMap[1] ? 1 : 0;
|
||||
}
|
||||
var mask = 0;
|
||||
var buf = 0;
|
||||
|
||||
for (var i = 0, ii = length; i < ii; ++i) {
|
||||
if (i % rowComps == 0) {
|
||||
mask = 0;
|
||||
buf = 0;
|
||||
} else {
|
||||
mask >>= 1;
|
||||
}
|
||||
|
||||
if (mask <= 0) {
|
||||
buf = buffer[bufferPos++];
|
||||
mask = 128;
|
||||
}
|
||||
|
||||
output[i] = !(buf & mask) ? valueZero : valueOne;
|
||||
}
|
||||
} else {
|
||||
if (decodeMap != null)
|
||||
TODO('interpolate component values');
|
||||
var bits = 0, buf = 0;
|
||||
for (var i = 0, ii = length; i < ii; ++i) {
|
||||
if (i % rowComps == 0) {
|
||||
buf = 0;
|
||||
bits = 0;
|
||||
}
|
||||
|
||||
while (bits < bpc) {
|
||||
buf = (buf << 8) | buffer[bufferPos++];
|
||||
bits += 8;
|
||||
}
|
||||
|
||||
var remainingBits = bits - bpc;
|
||||
output[i] = buf >> remainingBits;
|
||||
buf = buf & ((1 << remainingBits) - 1);
|
||||
bits = remainingBits;
|
||||
}
|
||||
}
|
||||
return output;
|
||||
},
|
||||
getOpacity: function getOpacity() {
|
||||
var smask = this.smask;
|
||||
var width = this.width;
|
||||
var height = this.height;
|
||||
var buf = new Uint8Array(width * height);
|
||||
|
||||
if (smask) {
|
||||
if (smask.image.getImage) {
|
||||
// smask is a DOM image
|
||||
var tempCanvas = new ScratchCanvas(width, height);
|
||||
var tempCtx = tempCanvas.getContext('2d');
|
||||
var domImage = smask.image.getImage();
|
||||
tempCtx.drawImage(domImage, 0, 0, domImage.width, domImage.height,
|
||||
0, 0, width, height);
|
||||
var data = tempCtx.getImageData(0, 0, width, height).data;
|
||||
for (var i = 0, j = 0, ii = width * height; i < ii; ++i, j += 4)
|
||||
buf[i] = data[j]; // getting first component value
|
||||
return buf;
|
||||
}
|
||||
var sw = smask.width;
|
||||
var sh = smask.height;
|
||||
if (sw != this.width || sh != this.height)
|
||||
error('smask dimensions do not match image dimensions: ' + sw +
|
||||
' != ' + this.width + ', ' + sh + ' != ' + this.height);
|
||||
|
||||
smask.fillGrayBuffer(buf);
|
||||
return buf;
|
||||
} else {
|
||||
for (var i = 0, ii = width * height; i < ii; ++i)
|
||||
buf[i] = 255;
|
||||
}
|
||||
return buf;
|
||||
},
|
||||
applyStencilMask: function applyStencilMask(buffer, inverseDecode) {
|
||||
var width = this.width, height = this.height;
|
||||
var bitStrideLength = (width + 7) >> 3;
|
||||
this.image.reset();
|
||||
var imgArray = this.image.getBytes(bitStrideLength * height);
|
||||
var imgArrayPos = 0;
|
||||
var i, j, mask, buf;
|
||||
// removing making non-masked pixels transparent
|
||||
var bufferPos = 3; // alpha component offset
|
||||
for (i = 0; i < height; i++) {
|
||||
mask = 0;
|
||||
for (j = 0; j < width; j++) {
|
||||
if (!mask) {
|
||||
buf = imgArray[imgArrayPos++];
|
||||
mask = 128;
|
||||
}
|
||||
if (!(buf & mask) == inverseDecode) {
|
||||
buffer[bufferPos] = 0;
|
||||
}
|
||||
bufferPos += 4;
|
||||
mask >>= 1;
|
||||
}
|
||||
}
|
||||
},
|
||||
fillRgbaBuffer: function fillRgbaBuffer(buffer, decodeMap) {
|
||||
var numComps = this.numComps;
|
||||
var width = this.width;
|
||||
var height = this.height;
|
||||
var bpc = this.bpc;
|
||||
|
||||
// rows start at byte boundary;
|
||||
var rowBytes = (width * numComps * bpc + 7) >> 3;
|
||||
this.image.reset();
|
||||
var imgArray = this.image.getBytes(height * rowBytes);
|
||||
|
||||
var comps = this.colorSpace.getRgbBuffer(
|
||||
this.getComponents(imgArray, decodeMap), bpc);
|
||||
var compsPos = 0;
|
||||
var opacity = this.getOpacity();
|
||||
var opacityPos = 0;
|
||||
var length = width * height * 4;
|
||||
|
||||
for (var i = 0; i < length; i += 4) {
|
||||
buffer[i] = comps[compsPos++];
|
||||
buffer[i + 1] = comps[compsPos++];
|
||||
buffer[i + 2] = comps[compsPos++];
|
||||
buffer[i + 3] = opacity[opacityPos++];
|
||||
}
|
||||
},
|
||||
fillGrayBuffer: function fillGrayBuffer(buffer) {
|
||||
var numComps = this.numComps;
|
||||
if (numComps != 1)
|
||||
error('Reading gray scale from a color image: ' + numComps);
|
||||
|
||||
var width = this.width;
|
||||
var height = this.height;
|
||||
var bpc = this.bpc;
|
||||
|
||||
// rows start at byte boundary;
|
||||
var rowBytes = (width * numComps * bpc + 7) >> 3;
|
||||
this.image.reset();
|
||||
var imgArray = this.image.getBytes(height * rowBytes);
|
||||
|
||||
var comps = this.getComponents(imgArray);
|
||||
var length = width * height;
|
||||
|
||||
for (var i = 0; i < length; ++i)
|
||||
buffer[i] = comps[i];
|
||||
}
|
||||
};
|
||||
return constructor;
|
||||
})();
|
||||
|
||||
var JpegImageLoader = (function jpegImage() {
|
||||
function JpegImageLoader(objId, imageData, objs) {
|
||||
var src = 'data:image/jpeg;base64,' + window.btoa(imageData);
|
||||
|
||||
var img = new Image();
|
||||
img.onload = (function jpegImageLoaderOnload() {
|
||||
this.loaded = true;
|
||||
|
||||
objs.resolve(objId, this);
|
||||
|
||||
if (this.onLoad)
|
||||
this.onLoad();
|
||||
}).bind(this);
|
||||
img.src = src;
|
||||
this.domImage = img;
|
||||
}
|
||||
|
||||
JpegImageLoader.prototype = {
|
||||
getImage: function jpegImageLoaderGetImage() {
|
||||
return this.domImage;
|
||||
}
|
||||
};
|
||||
|
||||
return JpegImageLoader;
|
||||
})();
|
||||
|
|
@ -0,0 +1,742 @@
|
|||
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
|
||||
|
||||
'use strict';
|
||||
|
||||
var Name = (function nameName() {
|
||||
function constructor(name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
constructor.prototype = {
|
||||
};
|
||||
|
||||
return constructor;
|
||||
})();
|
||||
|
||||
var Cmd = (function cmdCmd() {
|
||||
function constructor(cmd) {
|
||||
this.cmd = cmd;
|
||||
}
|
||||
|
||||
constructor.prototype = {
|
||||
};
|
||||
|
||||
return constructor;
|
||||
})();
|
||||
|
||||
var Dict = (function dictDict() {
|
||||
function constructor() {
|
||||
this.map = Object.create(null);
|
||||
}
|
||||
|
||||
constructor.prototype = {
|
||||
get: function dictGet(key1, key2, key3) {
|
||||
var value;
|
||||
if (typeof (value = this.map[key1]) != 'undefined' || key1 in this.map ||
|
||||
typeof key2 == 'undefined') {
|
||||
return value;
|
||||
}
|
||||
if (typeof (value = this.map[key2]) != 'undefined' || key2 in this.map ||
|
||||
typeof key3 == 'undefined') {
|
||||
return value;
|
||||
}
|
||||
|
||||
return this.map[key3] || null;
|
||||
},
|
||||
|
||||
set: function dictSet(key, value) {
|
||||
this.map[key] = value;
|
||||
},
|
||||
|
||||
has: function dictHas(key) {
|
||||
return key in this.map;
|
||||
},
|
||||
|
||||
forEach: function dictForEach(callback) {
|
||||
for (var key in this.map) {
|
||||
callback(key, this.map[key]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return constructor;
|
||||
})();
|
||||
|
||||
var Ref = (function refRef() {
|
||||
function constructor(num, gen) {
|
||||
this.num = num;
|
||||
this.gen = gen;
|
||||
}
|
||||
|
||||
constructor.prototype = {
|
||||
};
|
||||
|
||||
return constructor;
|
||||
})();
|
||||
|
||||
// The reference is identified by number and generation,
|
||||
// this structure stores only one instance of the reference.
|
||||
var RefSet = (function refSet() {
|
||||
function constructor() {
|
||||
this.dict = {};
|
||||
}
|
||||
|
||||
constructor.prototype = {
|
||||
has: function refSetHas(ref) {
|
||||
return !!this.dict['R' + ref.num + '.' + ref.gen];
|
||||
},
|
||||
|
||||
put: function refSetPut(ref) {
|
||||
this.dict['R' + ref.num + '.' + ref.gen] = ref;
|
||||
}
|
||||
};
|
||||
|
||||
return constructor;
|
||||
})();
|
||||
|
||||
var Catalog = (function catalogCatalog() {
|
||||
function constructor(xref) {
|
||||
this.xref = xref;
|
||||
var obj = xref.getCatalogObj();
|
||||
assertWellFormed(isDict(obj), 'catalog object is not a dictionary');
|
||||
this.catDict = obj;
|
||||
}
|
||||
|
||||
constructor.prototype = {
|
||||
get toplevelPagesDict() {
|
||||
var pagesObj = this.catDict.get('Pages');
|
||||
assertWellFormed(isRef(pagesObj), 'invalid top-level pages reference');
|
||||
var xrefObj = this.xref.fetch(pagesObj);
|
||||
assertWellFormed(isDict(xrefObj), 'invalid top-level pages dictionary');
|
||||
// shadow the prototype getter
|
||||
return shadow(this, 'toplevelPagesDict', xrefObj);
|
||||
},
|
||||
get documentOutline() {
|
||||
var obj = this.catDict.get('Outlines');
|
||||
var xref = this.xref;
|
||||
var root = { items: [] };
|
||||
if (isRef(obj)) {
|
||||
obj = xref.fetch(obj).get('First');
|
||||
var processed = new RefSet();
|
||||
if (isRef(obj)) {
|
||||
var queue = [{obj: obj, parent: root}];
|
||||
// to avoid recursion keeping track of the items
|
||||
// in the processed dictionary
|
||||
processed.put(obj);
|
||||
while (queue.length > 0) {
|
||||
var i = queue.shift();
|
||||
var outlineDict = xref.fetch(i.obj);
|
||||
if (!outlineDict.has('Title'))
|
||||
error('Invalid outline item');
|
||||
var dest = outlineDict.get('A');
|
||||
if (dest)
|
||||
dest = xref.fetchIfRef(dest).get('D');
|
||||
else if (outlineDict.has('Dest')) {
|
||||
dest = outlineDict.get('Dest');
|
||||
if (isName(dest))
|
||||
dest = dest.name;
|
||||
}
|
||||
var title = xref.fetchIfRef(outlineDict.get('Title'));
|
||||
var outlineItem = {
|
||||
dest: dest,
|
||||
title: stringToPDFString(title),
|
||||
color: outlineDict.get('C') || [0, 0, 0],
|
||||
count: outlineDict.get('Count'),
|
||||
bold: !!(outlineDict.get('F') & 2),
|
||||
italic: !!(outlineDict.get('F') & 1),
|
||||
items: []
|
||||
};
|
||||
i.parent.items.push(outlineItem);
|
||||
obj = outlineDict.get('First');
|
||||
if (isRef(obj) && !processed.has(obj)) {
|
||||
queue.push({obj: obj, parent: outlineItem});
|
||||
processed.put(obj);
|
||||
}
|
||||
obj = outlineDict.get('Next');
|
||||
if (isRef(obj) && !processed.has(obj)) {
|
||||
queue.push({obj: obj, parent: i.parent});
|
||||
processed.put(obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
obj = root.items.length > 0 ? root.items : null;
|
||||
return shadow(this, 'documentOutline', obj);
|
||||
},
|
||||
get numPages() {
|
||||
var obj = this.toplevelPagesDict.get('Count');
|
||||
assertWellFormed(
|
||||
isInt(obj),
|
||||
'page count in top level pages object is not an integer'
|
||||
);
|
||||
// shadow the prototype getter
|
||||
return shadow(this, 'num', obj);
|
||||
},
|
||||
traverseKids: function catalogTraverseKids(pagesDict) {
|
||||
var pageCache = this.pageCache;
|
||||
var kids = pagesDict.get('Kids');
|
||||
assertWellFormed(isArray(kids),
|
||||
'page dictionary kids object is not an array');
|
||||
for (var i = 0, ii = kids.length; i < ii; ++i) {
|
||||
var kid = kids[i];
|
||||
assertWellFormed(isRef(kid),
|
||||
'page dictionary kid is not a reference');
|
||||
var obj = this.xref.fetch(kid);
|
||||
if (isDict(obj, 'Page') || (isDict(obj) && !obj.has('Kids'))) {
|
||||
pageCache.push(new Page(this.xref, pageCache.length, obj, kid));
|
||||
} else { // must be a child page dictionary
|
||||
assertWellFormed(
|
||||
isDict(obj),
|
||||
'page dictionary kid reference points to wrong type of object'
|
||||
);
|
||||
this.traverseKids(obj);
|
||||
}
|
||||
}
|
||||
},
|
||||
get destinations() {
|
||||
function fetchDestination(xref, ref) {
|
||||
var dest = xref.fetchIfRef(ref);
|
||||
return isDict(dest) ? dest.get('D') : dest;
|
||||
}
|
||||
|
||||
var xref = this.xref;
|
||||
var dests = {}, nameTreeRef, nameDictionaryRef;
|
||||
var obj = this.catDict.get('Names');
|
||||
if (obj)
|
||||
nameTreeRef = xref.fetchIfRef(obj).get('Dests');
|
||||
else if (this.catDict.has('Dests'))
|
||||
nameDictionaryRef = this.catDict.get('Dests');
|
||||
|
||||
if (nameDictionaryRef) {
|
||||
// reading simple destination dictionary
|
||||
obj = xref.fetchIfRef(nameDictionaryRef);
|
||||
obj.forEach(function catalogForEach(key, value) {
|
||||
if (!value) return;
|
||||
dests[key] = fetchDestination(xref, value);
|
||||
});
|
||||
}
|
||||
if (nameTreeRef) {
|
||||
// reading name tree
|
||||
var processed = new RefSet();
|
||||
processed.put(nameTreeRef);
|
||||
var queue = [nameTreeRef];
|
||||
while (queue.length > 0) {
|
||||
var i, n;
|
||||
obj = xref.fetch(queue.shift());
|
||||
if (obj.has('Kids')) {
|
||||
var kids = obj.get('Kids');
|
||||
for (i = 0, n = kids.length; i < n; i++) {
|
||||
var kid = kids[i];
|
||||
if (processed.has(kid))
|
||||
error('invalid destinations');
|
||||
queue.push(kid);
|
||||
processed.put(kid);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
var names = obj.get('Names');
|
||||
for (i = 0, n = names.length; i < n; i += 2) {
|
||||
dests[names[i]] = fetchDestination(xref, names[i + 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return shadow(this, 'destinations', dests);
|
||||
},
|
||||
getPage: function catalogGetPage(n) {
|
||||
var pageCache = this.pageCache;
|
||||
if (!pageCache) {
|
||||
pageCache = this.pageCache = [];
|
||||
this.traverseKids(this.toplevelPagesDict);
|
||||
}
|
||||
return this.pageCache[n - 1];
|
||||
}
|
||||
};
|
||||
|
||||
return constructor;
|
||||
})();
|
||||
|
||||
var XRef = (function xRefXRef() {
|
||||
function constructor(stream, startXRef, mainXRefEntriesOffset) {
|
||||
this.stream = stream;
|
||||
this.entries = [];
|
||||
this.xrefstms = {};
|
||||
var trailerDict = this.readXRef(startXRef);
|
||||
|
||||
// prepare the XRef cache
|
||||
this.cache = [];
|
||||
|
||||
var encrypt = trailerDict.get('Encrypt');
|
||||
if (encrypt) {
|
||||
var fileId = trailerDict.get('ID');
|
||||
this.encrypt = new CipherTransformFactory(this.fetch(encrypt),
|
||||
fileId[0] /*, password */);
|
||||
}
|
||||
|
||||
// get the root dictionary (catalog) object
|
||||
if (!isRef(this.root = trailerDict.get('Root')))
|
||||
error('Invalid root reference');
|
||||
}
|
||||
|
||||
constructor.prototype = {
|
||||
readXRefTable: function readXRefTable(parser) {
|
||||
var obj;
|
||||
while (true) {
|
||||
if (isCmd(obj = parser.getObj(), 'trailer'))
|
||||
break;
|
||||
if (!isInt(obj))
|
||||
error('Invalid XRef table');
|
||||
var first = obj;
|
||||
if (!isInt(obj = parser.getObj()))
|
||||
error('Invalid XRef table');
|
||||
var n = obj;
|
||||
if (first < 0 || n < 0 || (first + n) != ((first + n) | 0))
|
||||
error('Invalid XRef table: ' + first + ', ' + n);
|
||||
for (var i = first; i < first + n; ++i) {
|
||||
var entry = {};
|
||||
if (!isInt(obj = parser.getObj()))
|
||||
error('Invalid XRef table: ' + first + ', ' + n);
|
||||
entry.offset = obj;
|
||||
if (!isInt(obj = parser.getObj()))
|
||||
error('Invalid XRef table: ' + first + ', ' + n);
|
||||
entry.gen = obj;
|
||||
obj = parser.getObj();
|
||||
if (isCmd(obj, 'n')) {
|
||||
entry.uncompressed = true;
|
||||
} else if (isCmd(obj, 'f')) {
|
||||
entry.free = true;
|
||||
} else {
|
||||
error('Invalid XRef table: ' + first + ', ' + n);
|
||||
}
|
||||
if (!this.entries[i]) {
|
||||
// In some buggy PDF files the xref table claims to start at 1
|
||||
// instead of 0.
|
||||
if (i == 1 && first == 1 &&
|
||||
entry.offset == 0 && entry.gen == 65535 && entry.free) {
|
||||
i = first = 0;
|
||||
}
|
||||
this.entries[i] = entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// read the trailer dictionary
|
||||
var dict;
|
||||
if (!isDict(dict = parser.getObj()))
|
||||
error('Invalid XRef table');
|
||||
|
||||
// get the 'Prev' pointer
|
||||
var prev;
|
||||
obj = dict.get('Prev');
|
||||
if (isInt(obj)) {
|
||||
prev = obj;
|
||||
} else if (isRef(obj)) {
|
||||
// certain buggy PDF generators generate "/Prev NNN 0 R" instead
|
||||
// of "/Prev NNN"
|
||||
prev = obj.num;
|
||||
}
|
||||
if (prev) {
|
||||
this.readXRef(prev);
|
||||
}
|
||||
|
||||
// check for 'XRefStm' key
|
||||
if (isInt(obj = dict.get('XRefStm'))) {
|
||||
var pos = obj;
|
||||
// ignore previously loaded xref streams (possible infinite recursion)
|
||||
if (!(pos in this.xrefstms)) {
|
||||
this.xrefstms[pos] = 1;
|
||||
this.readXRef(pos);
|
||||
}
|
||||
}
|
||||
|
||||
return dict;
|
||||
},
|
||||
readXRefStream: function readXRefStream(stream) {
|
||||
var streamParameters = stream.parameters;
|
||||
var byteWidths = streamParameters.get('W');
|
||||
var range = streamParameters.get('Index');
|
||||
if (!range)
|
||||
range = [0, streamParameters.get('Size')];
|
||||
var i, j;
|
||||
while (range.length > 0) {
|
||||
var first = range[0], n = range[1];
|
||||
if (!isInt(first) || !isInt(n))
|
||||
error('Invalid XRef range fields: ' + first + ', ' + n);
|
||||
var typeFieldWidth = byteWidths[0];
|
||||
var offsetFieldWidth = byteWidths[1];
|
||||
var generationFieldWidth = byteWidths[2];
|
||||
if (!isInt(typeFieldWidth) || !isInt(offsetFieldWidth) ||
|
||||
!isInt(generationFieldWidth)) {
|
||||
error('Invalid XRef entry fields length: ' + first + ', ' + n);
|
||||
}
|
||||
for (i = 0; i < n; ++i) {
|
||||
var type = 0, offset = 0, generation = 0;
|
||||
for (j = 0; j < typeFieldWidth; ++j)
|
||||
type = (type << 8) | stream.getByte();
|
||||
// if type field is absent, its default value = 1
|
||||
if (typeFieldWidth == 0)
|
||||
type = 1;
|
||||
for (j = 0; j < offsetFieldWidth; ++j)
|
||||
offset = (offset << 8) | stream.getByte();
|
||||
for (j = 0; j < generationFieldWidth; ++j)
|
||||
generation = (generation << 8) | stream.getByte();
|
||||
var entry = {};
|
||||
entry.offset = offset;
|
||||
entry.gen = generation;
|
||||
switch (type) {
|
||||
case 0:
|
||||
entry.free = true;
|
||||
break;
|
||||
case 1:
|
||||
entry.uncompressed = true;
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
default:
|
||||
error('Invalid XRef entry type: ' + type);
|
||||
}
|
||||
if (!this.entries[first + i])
|
||||
this.entries[first + i] = entry;
|
||||
}
|
||||
range.splice(0, 2);
|
||||
}
|
||||
var prev = streamParameters.get('Prev');
|
||||
if (isInt(prev))
|
||||
this.readXRef(prev);
|
||||
return streamParameters;
|
||||
},
|
||||
indexObjects: function indexObjects() {
|
||||
// Simple scan through the PDF content to find objects,
|
||||
// trailers and XRef streams.
|
||||
function readToken(data, offset) {
|
||||
var token = '', ch = data[offset];
|
||||
while (ch !== 13 && ch !== 10) {
|
||||
if (++offset >= data.length)
|
||||
break;
|
||||
token += String.fromCharCode(ch);
|
||||
ch = data[offset];
|
||||
}
|
||||
return token;
|
||||
}
|
||||
function skipUntil(data, offset, what) {
|
||||
var length = what.length, dataLength = data.length;
|
||||
var skipped = 0;
|
||||
// finding byte sequence
|
||||
while (offset < dataLength) {
|
||||
var i = 0;
|
||||
while (i < length && data[offset + i] == what[i])
|
||||
++i;
|
||||
if (i >= length)
|
||||
break; // sequence found
|
||||
|
||||
offset++;
|
||||
skipped++;
|
||||
}
|
||||
return skipped;
|
||||
}
|
||||
var trailerBytes = new Uint8Array([116, 114, 97, 105, 108, 101, 114]);
|
||||
var startxrefBytes = new Uint8Array([115, 116, 97, 114, 116, 120, 114,
|
||||
101, 102]);
|
||||
var endobjBytes = new Uint8Array([101, 110, 100, 111, 98, 106]);
|
||||
var xrefBytes = new Uint8Array([47, 88, 82, 101, 102]);
|
||||
|
||||
var stream = this.stream;
|
||||
stream.pos = 0;
|
||||
var buffer = stream.getBytes();
|
||||
var position = stream.start, length = buffer.length;
|
||||
var trailers = [], xrefStms = [];
|
||||
var state = 0;
|
||||
var currentToken;
|
||||
while (position < length) {
|
||||
var ch = buffer[position];
|
||||
if (ch === 32 || ch === 9 || ch === 13 || ch === 10) {
|
||||
++position;
|
||||
continue;
|
||||
}
|
||||
if (ch === 37) { // %-comment
|
||||
do {
|
||||
++position;
|
||||
ch = buffer[position];
|
||||
} while (ch !== 13 && ch !== 10);
|
||||
continue;
|
||||
}
|
||||
var token = readToken(buffer, position);
|
||||
var m;
|
||||
if (token === 'xref') {
|
||||
position += skipUntil(buffer, position, trailerBytes);
|
||||
trailers.push(position);
|
||||
position += skipUntil(buffer, position, startxrefBytes);
|
||||
} else if ((m = /^(\d+)\s+(\d+)\s+obj\b/.exec(token))) {
|
||||
this.entries[m[1]] = {
|
||||
offset: position,
|
||||
gen: m[2] | 0,
|
||||
uncompressed: true
|
||||
};
|
||||
|
||||
var contentLength = skipUntil(buffer, position, endobjBytes) + 7;
|
||||
var content = buffer.subarray(position, position + contentLength);
|
||||
|
||||
// checking XRef stream suspect
|
||||
// (it shall have '/XRef' and next char is not a letter)
|
||||
var xrefTagOffset = skipUntil(content, 0, xrefBytes);
|
||||
if (xrefTagOffset < contentLength &&
|
||||
content[xrefTagOffset + 5] < 64) {
|
||||
xrefStms.push(position);
|
||||
this.xrefstms[position] = 1; // don't read it recursively
|
||||
}
|
||||
|
||||
position += contentLength;
|
||||
} else
|
||||
position += token.length + 1;
|
||||
}
|
||||
// reading XRef streams
|
||||
for (var i = 0, ii = xrefStms.length; i < ii; ++i) {
|
||||
this.readXRef(xrefStms[i]);
|
||||
}
|
||||
// finding main trailer
|
||||
var dict;
|
||||
for (var i = 0, ii = trailers.length; i < ii; ++i) {
|
||||
stream.pos = trailers[i];
|
||||
var parser = new Parser(new Lexer(stream), true);
|
||||
var obj = parser.getObj();
|
||||
if (!isCmd(obj, 'trailer'))
|
||||
continue;
|
||||
// read the trailer dictionary
|
||||
if (!isDict(dict = parser.getObj()))
|
||||
continue;
|
||||
// taking the first one with 'ID'
|
||||
if (dict.has('ID'))
|
||||
return dict;
|
||||
}
|
||||
// no tailer with 'ID', taking last one (if exists)
|
||||
if (dict)
|
||||
return dict;
|
||||
// nothing helps
|
||||
error('Invalid PDF structure');
|
||||
return null;
|
||||
},
|
||||
readXRef: function readXref(startXRef) {
|
||||
var stream = this.stream;
|
||||
stream.pos = startXRef;
|
||||
var parser = new Parser(new Lexer(stream), true);
|
||||
var obj = parser.getObj();
|
||||
// parse an old-style xref table
|
||||
if (isCmd(obj, 'xref'))
|
||||
return this.readXRefTable(parser);
|
||||
// parse an xref stream
|
||||
if (isInt(obj)) {
|
||||
if (!isInt(parser.getObj()) ||
|
||||
!isCmd(parser.getObj(), 'obj') ||
|
||||
!isStream(obj = parser.getObj())) {
|
||||
error('Invalid XRef stream');
|
||||
}
|
||||
return this.readXRefStream(obj);
|
||||
}
|
||||
return this.indexObjects();
|
||||
},
|
||||
getEntry: function xRefGetEntry(i) {
|
||||
var e = this.entries[i];
|
||||
if (e.free)
|
||||
error('reading an XRef stream not implemented yet');
|
||||
return e;
|
||||
},
|
||||
fetchIfRef: function xRefFetchIfRef(obj) {
|
||||
if (!isRef(obj))
|
||||
return obj;
|
||||
return this.fetch(obj);
|
||||
},
|
||||
fetch: function xRefFetch(ref, suppressEncryption) {
|
||||
var num = ref.num;
|
||||
var e = this.cache[num];
|
||||
if (e)
|
||||
return e;
|
||||
|
||||
e = this.getEntry(num);
|
||||
var gen = ref.gen;
|
||||
var stream, parser;
|
||||
if (e.uncompressed) {
|
||||
if (e.gen != gen)
|
||||
throw ('inconsistent generation in XRef');
|
||||
stream = this.stream.makeSubStream(e.offset);
|
||||
parser = new Parser(new Lexer(stream), true, this);
|
||||
var obj1 = parser.getObj();
|
||||
var obj2 = parser.getObj();
|
||||
var obj3 = parser.getObj();
|
||||
if (!isInt(obj1) || obj1 != num ||
|
||||
!isInt(obj2) || obj2 != gen ||
|
||||
!isCmd(obj3)) {
|
||||
error('bad XRef entry');
|
||||
}
|
||||
if (!isCmd(obj3, 'obj')) {
|
||||
// some bad pdfs use "obj1234" and really mean 1234
|
||||
if (obj3.cmd.indexOf('obj') == 0) {
|
||||
num = parseInt(obj3.cmd.substring(3), 10);
|
||||
if (!isNaN(num))
|
||||
return num;
|
||||
}
|
||||
error('bad XRef entry');
|
||||
}
|
||||
if (this.encrypt && !suppressEncryption) {
|
||||
try {
|
||||
e = parser.getObj(this.encrypt.createCipherTransform(num, gen));
|
||||
} catch (ex) {
|
||||
// almost all streams must be encrypted, but sometimes
|
||||
// they are not probably due to some broken generators
|
||||
// re-trying without encryption
|
||||
return this.fetch(ref, true);
|
||||
}
|
||||
} else {
|
||||
e = parser.getObj();
|
||||
}
|
||||
// Don't cache streams since they are mutable (except images).
|
||||
if (!isStream(e) || e.getImage)
|
||||
this.cache[num] = e;
|
||||
return e;
|
||||
}
|
||||
|
||||
// compressed entry
|
||||
stream = this.fetch(new Ref(e.offset, 0));
|
||||
if (!isStream(stream))
|
||||
error('bad ObjStm stream');
|
||||
var first = stream.parameters.get('First');
|
||||
var n = stream.parameters.get('N');
|
||||
if (!isInt(first) || !isInt(n)) {
|
||||
error('invalid first and n parameters for ObjStm stream');
|
||||
}
|
||||
parser = new Parser(new Lexer(stream), false);
|
||||
var i, entries = [], nums = [];
|
||||
// read the object numbers to populate cache
|
||||
for (i = 0; i < n; ++i) {
|
||||
num = parser.getObj();
|
||||
if (!isInt(num)) {
|
||||
error('invalid object number in the ObjStm stream: ' + num);
|
||||
}
|
||||
nums.push(num);
|
||||
var offset = parser.getObj();
|
||||
if (!isInt(offset)) {
|
||||
error('invalid object offset in the ObjStm stream: ' + offset);
|
||||
}
|
||||
}
|
||||
// read stream objects for cache
|
||||
for (i = 0; i < n; ++i) {
|
||||
entries.push(parser.getObj());
|
||||
this.cache[nums[i]] = entries[i];
|
||||
}
|
||||
e = entries[e.gen];
|
||||
if (!e) {
|
||||
error('bad XRef entry for compressed object');
|
||||
}
|
||||
return e;
|
||||
},
|
||||
getCatalogObj: function xRefGetCatalogObj() {
|
||||
return this.fetch(this.root);
|
||||
}
|
||||
};
|
||||
|
||||
return constructor;
|
||||
})();
|
||||
|
||||
/**
|
||||
* A PDF document and page is built of many objects. E.g. there are objects
|
||||
* for fonts, images, rendering code and such. These objects might get processed
|
||||
* inside of a worker. The `PDFObjects` implements some basic functions to
|
||||
* manage these objects.
|
||||
*/
|
||||
var PDFObjects = (function pdfObjects() {
|
||||
function PDFObjects() {
|
||||
this.objs = {};
|
||||
}
|
||||
|
||||
PDFObjects.prototype = {
|
||||
objs: null,
|
||||
|
||||
/**
|
||||
* Internal function.
|
||||
* Ensures there is an object defined for `objId`. Stores `data` on the
|
||||
* object *if* it is created.
|
||||
*/
|
||||
ensureObj: function pdfObjectsEnsureObj(objId, data) {
|
||||
if (this.objs[objId])
|
||||
return this.objs[objId];
|
||||
return this.objs[objId] = new Promise(objId, data);
|
||||
},
|
||||
|
||||
/**
|
||||
* If called *without* callback, this returns the data of `objId` but the
|
||||
* object needs to be resolved. If it isn't, this function throws.
|
||||
*
|
||||
* If called *with* a callback, the callback is called with the data of the
|
||||
* object once the object is resolved. That means, if you call this
|
||||
* function and the object is already resolved, the callback gets called
|
||||
* right away.
|
||||
*/
|
||||
get: function pdfObjectsGet(objId, callback) {
|
||||
// If there is a callback, then the get can be async and the object is
|
||||
// not required to be resolved right now
|
||||
if (callback) {
|
||||
this.ensureObj(objId).then(callback);
|
||||
return null;
|
||||
}
|
||||
|
||||
// If there isn't a callback, the user expects to get the resolved data
|
||||
// directly.
|
||||
var obj = this.objs[objId];
|
||||
|
||||
// If there isn't an object yet or the object isn't resolved, then the
|
||||
// data isn't ready yet!
|
||||
if (!obj || !obj.isResolved) {
|
||||
throw 'Requesting object that isn\'t resolved yet ' + objId;
|
||||
return null;
|
||||
} else {
|
||||
return obj.data;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Resolves the object `objId` with optional `data`.
|
||||
*/
|
||||
resolve: function pdfObjectsResolve(objId, data) {
|
||||
var objs = this.objs;
|
||||
|
||||
// In case there is a promise already on this object, just resolve it.
|
||||
if (objs[objId]) {
|
||||
objs[objId].resolve(data);
|
||||
} else {
|
||||
this.ensureObj(objId, data);
|
||||
}
|
||||
},
|
||||
|
||||
onData: function pdfObjectsOnData(objId, callback) {
|
||||
this.ensureObj(objId).onData(callback);
|
||||
},
|
||||
|
||||
isResolved: function pdfObjectsIsResolved(objId) {
|
||||
var objs = this.objs;
|
||||
if (!objs[objId]) {
|
||||
return false;
|
||||
} else {
|
||||
return objs[objId].isResolved;
|
||||
}
|
||||
},
|
||||
|
||||
hasData: function pdfObjectsHasData(objId) {
|
||||
var objs = this.objs;
|
||||
if (!objs[objId]) {
|
||||
return false;
|
||||
} else {
|
||||
return objs[objId].hasData;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets the data of an object but *doesn't* resolve it.
|
||||
*/
|
||||
setData: function pdfObjectsSetData(objId, data) {
|
||||
// Watchout! If you call `this.ensureObj(objId, data)` you're going to
|
||||
// create a *resolved* promise which shouldn't be the case!
|
||||
this.ensureObj(objId).data = data;
|
||||
}
|
||||
};
|
||||
return PDFObjects;
|
||||
})();
|
||||
|
|
@ -0,0 +1,636 @@
|
|||
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
|
||||
|
||||
'use strict';
|
||||
|
||||
var EOF = {};
|
||||
|
||||
function isEOF(v) {
|
||||
return v == EOF;
|
||||
}
|
||||
|
||||
var Parser = (function parserParser() {
|
||||
function constructor(lexer, allowStreams, xref) {
|
||||
this.lexer = lexer;
|
||||
this.allowStreams = allowStreams;
|
||||
this.xref = xref;
|
||||
this.inlineImg = 0;
|
||||
this.refill();
|
||||
}
|
||||
|
||||
constructor.prototype = {
|
||||
refill: function parserRefill() {
|
||||
this.buf1 = this.lexer.getObj();
|
||||
this.buf2 = this.lexer.getObj();
|
||||
},
|
||||
shift: function parserShift() {
|
||||
if (isCmd(this.buf2, 'ID')) {
|
||||
this.buf1 = this.buf2;
|
||||
this.buf2 = null;
|
||||
// skip byte after ID
|
||||
this.lexer.skip();
|
||||
} else {
|
||||
this.buf1 = this.buf2;
|
||||
this.buf2 = this.lexer.getObj();
|
||||
}
|
||||
},
|
||||
getObj: function parserGetObj(cipherTransform) {
|
||||
if (isCmd(this.buf1, 'BI')) { // inline image
|
||||
this.shift();
|
||||
return this.makeInlineImage(cipherTransform);
|
||||
}
|
||||
if (isCmd(this.buf1, '[')) { // array
|
||||
this.shift();
|
||||
var array = [];
|
||||
while (!isCmd(this.buf1, ']') && !isEOF(this.buf1))
|
||||
array.push(this.getObj());
|
||||
if (isEOF(this.buf1))
|
||||
error('End of file inside array');
|
||||
this.shift();
|
||||
return array;
|
||||
}
|
||||
if (isCmd(this.buf1, '<<')) { // dictionary or stream
|
||||
this.shift();
|
||||
var dict = new Dict();
|
||||
while (!isCmd(this.buf1, '>>') && !isEOF(this.buf1)) {
|
||||
if (!isName(this.buf1)) {
|
||||
error('Dictionary key must be a name object');
|
||||
} else {
|
||||
var key = this.buf1.name;
|
||||
this.shift();
|
||||
if (isEOF(this.buf1))
|
||||
break;
|
||||
dict.set(key, this.getObj(cipherTransform));
|
||||
}
|
||||
}
|
||||
if (isEOF(this.buf1))
|
||||
error('End of file inside dictionary');
|
||||
|
||||
// stream objects are not allowed inside content streams or
|
||||
// object streams
|
||||
if (isCmd(this.buf2, 'stream')) {
|
||||
return this.allowStreams ?
|
||||
this.makeStream(dict, cipherTransform) : dict;
|
||||
}
|
||||
this.shift();
|
||||
return dict;
|
||||
}
|
||||
if (isInt(this.buf1)) { // indirect reference or integer
|
||||
var num = this.buf1;
|
||||
this.shift();
|
||||
if (isInt(this.buf1) && isCmd(this.buf2, 'R')) {
|
||||
var ref = new Ref(num, this.buf1);
|
||||
this.shift();
|
||||
this.shift();
|
||||
return ref;
|
||||
}
|
||||
return num;
|
||||
}
|
||||
if (isString(this.buf1)) { // string
|
||||
var str = this.buf1;
|
||||
this.shift();
|
||||
if (cipherTransform)
|
||||
str = cipherTransform.decryptString(str);
|
||||
return str;
|
||||
}
|
||||
|
||||
// simple object
|
||||
var obj = this.buf1;
|
||||
this.shift();
|
||||
return obj;
|
||||
},
|
||||
makeInlineImage: function parserMakeInlineImage(cipherTransform) {
|
||||
var lexer = this.lexer;
|
||||
var stream = lexer.stream;
|
||||
|
||||
// parse dictionary
|
||||
var dict = new Dict();
|
||||
while (!isCmd(this.buf1, 'ID') && !isEOF(this.buf1)) {
|
||||
if (!isName(this.buf1)) {
|
||||
error('Dictionary key must be a name object');
|
||||
} else {
|
||||
var key = this.buf1.name;
|
||||
this.shift();
|
||||
if (isEOF(this.buf1))
|
||||
break;
|
||||
dict.set(key, this.getObj(cipherTransform));
|
||||
}
|
||||
}
|
||||
|
||||
// parse image stream
|
||||
var startPos = stream.pos;
|
||||
|
||||
// searching for the /\sEI\s/
|
||||
var state = 0, ch;
|
||||
while (state != 4 && (ch = stream.getByte()) != null) {
|
||||
switch (ch) {
|
||||
case 0x20:
|
||||
case 0x0D:
|
||||
case 0x0A:
|
||||
state = state === 3 ? 4 : 1;
|
||||
break;
|
||||
case 0x45:
|
||||
state = state === 1 ? 2 : 0;
|
||||
break;
|
||||
case 0x49:
|
||||
state = state === 2 ? 3 : 0;
|
||||
break;
|
||||
default:
|
||||
state = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO improve the small images performance to remove the limit
|
||||
var inlineImgLimit = 500;
|
||||
if (++this.inlineImg >= inlineImgLimit) {
|
||||
if (this.inlineImg === inlineImgLimit)
|
||||
warn('Too many inline images');
|
||||
this.shift();
|
||||
return null;
|
||||
}
|
||||
|
||||
var length = (stream.pos - 4) - startPos;
|
||||
var imageStream = stream.makeSubStream(startPos, length, dict);
|
||||
if (cipherTransform)
|
||||
imageStream = cipherTransform.createStream(imageStream);
|
||||
imageStream = this.filter(imageStream, dict, length);
|
||||
imageStream.parameters = dict;
|
||||
|
||||
this.buf2 = new Cmd('EI');
|
||||
this.shift();
|
||||
|
||||
return imageStream;
|
||||
},
|
||||
makeStream: function parserMakeStream(dict, cipherTransform) {
|
||||
var lexer = this.lexer;
|
||||
var stream = lexer.stream;
|
||||
|
||||
// get stream start position
|
||||
lexer.skipToNextLine();
|
||||
var pos = stream.pos;
|
||||
|
||||
// get length
|
||||
var length = dict.get('Length');
|
||||
var xref = this.xref;
|
||||
if (xref)
|
||||
length = xref.fetchIfRef(length);
|
||||
if (!isInt(length)) {
|
||||
error('Bad ' + length + ' attribute in stream');
|
||||
length = 0;
|
||||
}
|
||||
|
||||
// skip over the stream data
|
||||
stream.pos = pos + length;
|
||||
this.shift(); // '>>'
|
||||
this.shift(); // 'stream'
|
||||
if (!isCmd(this.buf1, 'endstream'))
|
||||
error('Missing endstream');
|
||||
this.shift();
|
||||
|
||||
stream = stream.makeSubStream(pos, length, dict);
|
||||
if (cipherTransform)
|
||||
stream = cipherTransform.createStream(stream);
|
||||
stream = this.filter(stream, dict, length);
|
||||
stream.parameters = dict;
|
||||
return stream;
|
||||
},
|
||||
filter: function parserFilter(stream, dict, length) {
|
||||
var filter = dict.get('Filter', 'F');
|
||||
var params = dict.get('DecodeParms', 'DP');
|
||||
if (isName(filter))
|
||||
return this.makeFilter(stream, filter.name, length, params);
|
||||
if (isArray(filter)) {
|
||||
var filterArray = filter;
|
||||
var paramsArray = params;
|
||||
for (var i = 0, ii = filterArray.length; i < ii; ++i) {
|
||||
filter = filterArray[i];
|
||||
if (!isName(filter))
|
||||
error('Bad filter name: ' + filter);
|
||||
else {
|
||||
params = null;
|
||||
if (isArray(paramsArray) && (i in paramsArray))
|
||||
params = paramsArray[i];
|
||||
stream = this.makeFilter(stream, filter.name, length, params);
|
||||
// after the first stream the length variable is invalid
|
||||
length = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
return stream;
|
||||
},
|
||||
makeFilter: function parserMakeFilter(stream, name, length, params) {
|
||||
if (name == 'FlateDecode' || name == 'Fl') {
|
||||
if (params) {
|
||||
return new PredictorStream(new FlateStream(stream), params);
|
||||
}
|
||||
return new FlateStream(stream);
|
||||
} else if (name == 'LZWDecode' || name == 'LZW') {
|
||||
var earlyChange = 1;
|
||||
if (params) {
|
||||
if (params.has('EarlyChange'))
|
||||
earlyChange = params.get('EarlyChange');
|
||||
return new PredictorStream(
|
||||
new LZWStream(stream, earlyChange), params);
|
||||
}
|
||||
return new LZWStream(stream, earlyChange);
|
||||
} else if (name == 'DCTDecode' || name == 'DCT') {
|
||||
var bytes = stream.getBytes(length);
|
||||
return new JpegStream(bytes, stream.dict, this.xref);
|
||||
} else if (name == 'ASCII85Decode' || name == 'A85') {
|
||||
return new Ascii85Stream(stream);
|
||||
} else if (name == 'ASCIIHexDecode' || name == 'AHx') {
|
||||
return new AsciiHexStream(stream);
|
||||
} else if (name == 'CCITTFaxDecode' || name == 'CCF') {
|
||||
return new CCITTFaxStream(stream, params);
|
||||
} else {
|
||||
TODO('filter "' + name + '" not supported yet');
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
};
|
||||
|
||||
return constructor;
|
||||
})();
|
||||
|
||||
var Lexer = (function lexer() {
|
||||
function constructor(stream) {
|
||||
this.stream = stream;
|
||||
}
|
||||
|
||||
constructor.isSpace = function lexerIsSpace(ch) {
|
||||
return ch == ' ' || ch == '\t' || ch == '\x0d' || ch == '\x0a';
|
||||
};
|
||||
|
||||
// A '1' in this array means the character is white space. A '1' or
|
||||
// '2' means the character ends a name or command.
|
||||
var specialChars = [
|
||||
1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, // 0x
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1x
|
||||
1, 0, 0, 0, 0, 2, 0, 0, 2, 2, 0, 0, 0, 0, 0, 2, // 2x
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, // 3x
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 4x
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, // 5x
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 6x
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, // 7x
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8x
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9x
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // ax
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // bx
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // cx
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // dx
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // ex
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // fx
|
||||
];
|
||||
|
||||
function toHexDigit(ch) {
|
||||
if (ch >= '0' && ch <= '9')
|
||||
return ch.charCodeAt(0) - 48;
|
||||
ch = ch.toUpperCase();
|
||||
if (ch >= 'A' && ch <= 'F')
|
||||
return ch.charCodeAt(0) - 55;
|
||||
return -1;
|
||||
}
|
||||
|
||||
constructor.prototype = {
|
||||
getNumber: function lexerGetNumber(ch) {
|
||||
var floating = false;
|
||||
var str = ch;
|
||||
var stream = this.stream;
|
||||
for (;;) {
|
||||
ch = stream.lookChar();
|
||||
if (ch == '.' && !floating) {
|
||||
str += ch;
|
||||
floating = true;
|
||||
} else if (ch == '-') {
|
||||
// ignore minus signs in the middle of numbers to match
|
||||
// Adobe's behavior
|
||||
warn('Badly formated number');
|
||||
} else if (ch >= '0' && ch <= '9') {
|
||||
str += ch;
|
||||
} else if (ch == 'e' || ch == 'E') {
|
||||
floating = true;
|
||||
} else {
|
||||
// the last character doesn't belong to us
|
||||
break;
|
||||
}
|
||||
stream.skip();
|
||||
}
|
||||
var value = parseFloat(str);
|
||||
if (isNaN(value))
|
||||
error('Invalid floating point number: ' + value);
|
||||
return value;
|
||||
},
|
||||
getString: function lexerGetString() {
|
||||
var numParen = 1;
|
||||
var done = false;
|
||||
var str = '';
|
||||
var stream = this.stream;
|
||||
var ch;
|
||||
do {
|
||||
ch = stream.getChar();
|
||||
switch (ch) {
|
||||
case undefined:
|
||||
warn('Unterminated string');
|
||||
done = true;
|
||||
break;
|
||||
case '(':
|
||||
++numParen;
|
||||
str += ch;
|
||||
break;
|
||||
case ')':
|
||||
if (--numParen == 0) {
|
||||
done = true;
|
||||
} else {
|
||||
str += ch;
|
||||
}
|
||||
break;
|
||||
case '\\':
|
||||
ch = stream.getChar();
|
||||
switch (ch) {
|
||||
case undefined:
|
||||
warn('Unterminated string');
|
||||
done = true;
|
||||
break;
|
||||
case 'n':
|
||||
str += '\n';
|
||||
break;
|
||||
case 'r':
|
||||
str += '\r';
|
||||
break;
|
||||
case 't':
|
||||
str += '\t';
|
||||
break;
|
||||
case 'b':
|
||||
str += '\b';
|
||||
break;
|
||||
case 'f':
|
||||
str += '\f';
|
||||
break;
|
||||
case '\\':
|
||||
case '(':
|
||||
case ')':
|
||||
str += ch;
|
||||
break;
|
||||
case '0': case '1': case '2': case '3':
|
||||
case '4': case '5': case '6': case '7':
|
||||
var x = ch - '0';
|
||||
ch = stream.lookChar();
|
||||
if (ch >= '0' && ch <= '7') {
|
||||
stream.skip();
|
||||
x = (x << 3) + (ch - '0');
|
||||
ch = stream.lookChar();
|
||||
if (ch >= '0' && ch <= '7') {
|
||||
stream.skip();
|
||||
x = (x << 3) + (ch - '0');
|
||||
}
|
||||
}
|
||||
|
||||
str += String.fromCharCode(x);
|
||||
break;
|
||||
case '\r':
|
||||
ch = stream.lookChar();
|
||||
if (ch == '\n')
|
||||
stream.skip();
|
||||
break;
|
||||
case '\n':
|
||||
break;
|
||||
default:
|
||||
str += ch;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
str += ch;
|
||||
}
|
||||
} while (!done);
|
||||
return str;
|
||||
},
|
||||
getName: function lexerGetName(ch) {
|
||||
var str = '';
|
||||
var stream = this.stream;
|
||||
while (!!(ch = stream.lookChar()) && !specialChars[ch.charCodeAt(0)]) {
|
||||
stream.skip();
|
||||
if (ch == '#') {
|
||||
ch = stream.lookChar();
|
||||
var x = toHexDigit(ch);
|
||||
if (x != -1) {
|
||||
stream.skip();
|
||||
var x2 = toHexDigit(stream.getChar());
|
||||
if (x2 == -1)
|
||||
error('Illegal digit in hex char in name: ' + x2);
|
||||
str += String.fromCharCode((x << 4) | x2);
|
||||
} else {
|
||||
str += '#';
|
||||
str += ch;
|
||||
}
|
||||
} else {
|
||||
str += ch;
|
||||
}
|
||||
}
|
||||
if (str.length > 128)
|
||||
error('Warning: name token is longer than allowed by the spec: ' +
|
||||
str.length);
|
||||
return new Name(str);
|
||||
},
|
||||
getHexString: function lexerGetHexString(ch) {
|
||||
var str = '';
|
||||
var stream = this.stream;
|
||||
for (;;) {
|
||||
ch = stream.getChar();
|
||||
if (ch == '>') {
|
||||
break;
|
||||
}
|
||||
if (!ch) {
|
||||
warn('Unterminated hex string');
|
||||
break;
|
||||
}
|
||||
if (specialChars[ch.charCodeAt(0)] != 1) {
|
||||
var x, x2;
|
||||
if ((x = toHexDigit(ch)) == -1)
|
||||
error('Illegal character in hex string: ' + ch);
|
||||
|
||||
ch = stream.getChar();
|
||||
while (specialChars[ch.charCodeAt(0)] == 1)
|
||||
ch = stream.getChar();
|
||||
|
||||
if ((x2 = toHexDigit(ch)) == -1)
|
||||
error('Illegal character in hex string: ' + ch);
|
||||
|
||||
str += String.fromCharCode((x << 4) | x2);
|
||||
}
|
||||
}
|
||||
return str;
|
||||
},
|
||||
getObj: function lexerGetObj() {
|
||||
// skip whitespace and comments
|
||||
var comment = false;
|
||||
var stream = this.stream;
|
||||
var ch;
|
||||
while (true) {
|
||||
if (!(ch = stream.getChar()))
|
||||
return EOF;
|
||||
if (comment) {
|
||||
if (ch == '\r' || ch == '\n')
|
||||
comment = false;
|
||||
} else if (ch == '%') {
|
||||
comment = true;
|
||||
} else if (specialChars[ch.charCodeAt(0)] != 1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// start reading token
|
||||
switch (ch) {
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
case '+': case '-': case '.':
|
||||
return this.getNumber(ch);
|
||||
case '(':
|
||||
return this.getString();
|
||||
case '/':
|
||||
return this.getName(ch);
|
||||
// array punctuation
|
||||
case '[':
|
||||
case ']':
|
||||
return new Cmd(ch);
|
||||
// hex string or dict punctuation
|
||||
case '<':
|
||||
ch = stream.lookChar();
|
||||
if (ch == '<') {
|
||||
// dict punctuation
|
||||
stream.skip();
|
||||
return new Cmd('<<');
|
||||
}
|
||||
return this.getHexString(ch);
|
||||
// dict punctuation
|
||||
case '>':
|
||||
ch = stream.lookChar();
|
||||
if (ch == '>') {
|
||||
stream.skip();
|
||||
return new Cmd('>>');
|
||||
}
|
||||
case '{':
|
||||
case '}':
|
||||
return new Cmd(ch);
|
||||
// fall through
|
||||
case ')':
|
||||
error('Illegal character: ' + ch);
|
||||
return Error;
|
||||
}
|
||||
|
||||
// command
|
||||
var str = ch;
|
||||
while (!!(ch = stream.lookChar()) && !specialChars[ch.charCodeAt(0)]) {
|
||||
stream.skip();
|
||||
if (str.length == 128) {
|
||||
error('Command token too long: ' + str.length);
|
||||
break;
|
||||
}
|
||||
str += ch;
|
||||
}
|
||||
if (str == 'true')
|
||||
return true;
|
||||
if (str == 'false')
|
||||
return false;
|
||||
if (str == 'null')
|
||||
return null;
|
||||
return new Cmd(str);
|
||||
},
|
||||
skipToNextLine: function lexerSkipToNextLine() {
|
||||
var stream = this.stream;
|
||||
while (true) {
|
||||
var ch = stream.getChar();
|
||||
if (!ch || ch == '\n')
|
||||
return;
|
||||
if (ch == '\r') {
|
||||
if ((ch = stream.lookChar()) == '\n')
|
||||
stream.skip();
|
||||
return;
|
||||
}
|
||||
}
|
||||
},
|
||||
skip: function lexerSkip() {
|
||||
this.stream.skip();
|
||||
}
|
||||
};
|
||||
|
||||
return constructor;
|
||||
})();
|
||||
|
||||
var Linearization = (function linearizationLinearization() {
|
||||
function constructor(stream) {
|
||||
this.parser = new Parser(new Lexer(stream), false);
|
||||
var obj1 = this.parser.getObj();
|
||||
var obj2 = this.parser.getObj();
|
||||
var obj3 = this.parser.getObj();
|
||||
this.linDict = this.parser.getObj();
|
||||
if (isInt(obj1) && isInt(obj2) && isCmd(obj3, 'obj') &&
|
||||
isDict(this.linDict)) {
|
||||
var obj = this.linDict.get('Linearized');
|
||||
if (!(isNum(obj) && obj > 0))
|
||||
this.linDict = null;
|
||||
}
|
||||
}
|
||||
|
||||
constructor.prototype = {
|
||||
getInt: function linearizationGetInt(name) {
|
||||
var linDict = this.linDict;
|
||||
var obj;
|
||||
if (isDict(linDict) &&
|
||||
isInt(obj = linDict.get(name)) &&
|
||||
obj > 0) {
|
||||
return obj;
|
||||
}
|
||||
error('"' + name + '" field in linearization table is invalid');
|
||||
return 0;
|
||||
},
|
||||
getHint: function linearizationGetHint(index) {
|
||||
var linDict = this.linDict;
|
||||
var obj1, obj2;
|
||||
if (isDict(linDict) &&
|
||||
isArray(obj1 = linDict.get('H')) &&
|
||||
obj1.length >= 2 &&
|
||||
isInt(obj2 = obj1[index]) &&
|
||||
obj2 > 0) {
|
||||
return obj2;
|
||||
}
|
||||
error('Hints table in linearization table is invalid: ' + index);
|
||||
return 0;
|
||||
},
|
||||
get length() {
|
||||
if (!isDict(this.linDict))
|
||||
return 0;
|
||||
return this.getInt('L');
|
||||
},
|
||||
get hintsOffset() {
|
||||
return this.getHint(0);
|
||||
},
|
||||
get hintsLength() {
|
||||
return this.getHint(1);
|
||||
},
|
||||
get hintsOffset2() {
|
||||
return this.getHint(2);
|
||||
},
|
||||
get hintsLenth2() {
|
||||
return this.getHint(3);
|
||||
},
|
||||
get objectNumberFirst() {
|
||||
return this.getInt('O');
|
||||
},
|
||||
get endFirst() {
|
||||
return this.getInt('E');
|
||||
},
|
||||
get numPages() {
|
||||
return this.getInt('N');
|
||||
},
|
||||
get mainXRefEntriesOffset() {
|
||||
return this.getInt('T');
|
||||
},
|
||||
get pageFirst() {
|
||||
return this.getInt('P');
|
||||
}
|
||||
};
|
||||
|
||||
return constructor;
|
||||
})();
|
||||
|
|
@ -0,0 +1,291 @@
|
|||
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
|
||||
|
||||
'use strict';
|
||||
|
||||
var Pattern = (function patternPattern() {
|
||||
// Constructor should define this.getPattern
|
||||
function constructor() {
|
||||
error('should not call Pattern constructor');
|
||||
}
|
||||
|
||||
constructor.prototype = {
|
||||
// Input: current Canvas context
|
||||
// Output: the appropriate fillStyle or strokeStyle
|
||||
getPattern: function pattern_getStyle(ctx) {
|
||||
error('Should not call Pattern.getStyle: ' + ctx);
|
||||
}
|
||||
};
|
||||
|
||||
constructor.shadingFromIR = function pattern_shadingFromIR(ctx, raw) {
|
||||
return Shadings[raw[0]].fromIR(ctx, raw);
|
||||
};
|
||||
|
||||
constructor.parseShading = function pattern_shading(shading, matrix, xref,
|
||||
res, ctx) {
|
||||
|
||||
var dict = isStream(shading) ? shading.dict : shading;
|
||||
var type = dict.get('ShadingType');
|
||||
|
||||
switch (type) {
|
||||
case 2:
|
||||
case 3:
|
||||
// both radial and axial shadings are handled by RadialAxial shading
|
||||
return new Shadings.RadialAxial(dict, matrix, xref, res, ctx);
|
||||
default:
|
||||
return new Shadings.Dummy();
|
||||
}
|
||||
};
|
||||
return constructor;
|
||||
})();
|
||||
|
||||
var Shadings = {};
|
||||
|
||||
// Radial and axial shading have very similar implementations
|
||||
// If needed, the implementations can be broken into two classes
|
||||
Shadings.RadialAxial = (function radialAxialShading() {
|
||||
function constructor(dict, matrix, xref, res, ctx) {
|
||||
this.matrix = matrix;
|
||||
this.coordsArr = dict.get('Coords');
|
||||
this.shadingType = dict.get('ShadingType');
|
||||
this.type = 'Pattern';
|
||||
|
||||
this.ctx = ctx;
|
||||
var cs = dict.get('ColorSpace', 'CS');
|
||||
cs = ColorSpace.parse(cs, xref, res);
|
||||
this.cs = cs;
|
||||
|
||||
var t0 = 0.0, t1 = 1.0;
|
||||
if (dict.has('Domain')) {
|
||||
var domainArr = dict.get('Domain');
|
||||
t0 = domainArr[0];
|
||||
t1 = domainArr[1];
|
||||
}
|
||||
|
||||
var extendStart = false, extendEnd = false;
|
||||
if (dict.has('Extend')) {
|
||||
var extendArr = dict.get('Extend');
|
||||
extendStart = extendArr[0];
|
||||
extendEnd = extendArr[1];
|
||||
TODO('Support extend');
|
||||
}
|
||||
|
||||
this.extendStart = extendStart;
|
||||
this.extendEnd = extendEnd;
|
||||
|
||||
var fnObj = dict.get('Function');
|
||||
fnObj = xref.fetchIfRef(fnObj);
|
||||
if (isArray(fnObj))
|
||||
error('No support for array of functions');
|
||||
else if (!isPDFFunction(fnObj))
|
||||
error('Invalid function');
|
||||
var fn = PDFFunction.parse(xref, fnObj);
|
||||
|
||||
// 10 samples seems good enough for now, but probably won't work
|
||||
// if there are sharp color changes. Ideally, we would implement
|
||||
// the spec faithfully and add lossless optimizations.
|
||||
var step = (t1 - t0) / 10;
|
||||
var diff = t1 - t0;
|
||||
|
||||
var colorStops = [];
|
||||
for (var i = t0; i <= t1; i += step) {
|
||||
var color = fn([i]);
|
||||
var rgbColor = Util.makeCssRgb.apply(this, cs.getRgb(color));
|
||||
colorStops.push([(i - t0) / diff, rgbColor]);
|
||||
}
|
||||
|
||||
this.colorStops = colorStops;
|
||||
}
|
||||
|
||||
constructor.fromIR = function radialAxialShadingGetIR(ctx, 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];
|
||||
|
||||
var curMatrix = ctx.mozCurrentTransform;
|
||||
if (curMatrix) {
|
||||
var userMatrix = ctx.mozCurrentTransformInverse;
|
||||
|
||||
p0 = Util.applyTransform(p0, curMatrix);
|
||||
p0 = Util.applyTransform(p0, userMatrix);
|
||||
|
||||
p1 = Util.applyTransform(p1, curMatrix);
|
||||
p1 = Util.applyTransform(p1, userMatrix);
|
||||
}
|
||||
|
||||
var grad;
|
||||
if (type == 2)
|
||||
grad = ctx.createLinearGradient(p0[0], p0[1], p1[0], p1[1]);
|
||||
else if (type == 3)
|
||||
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;
|
||||
};
|
||||
|
||||
constructor.prototype = {
|
||||
getIR: function radialAxialShadingGetIR() {
|
||||
var coordsArr = this.coordsArr;
|
||||
var type = this.shadingType;
|
||||
if (type == 2) {
|
||||
var p0 = [coordsArr[0], coordsArr[1]];
|
||||
var p1 = [coordsArr[2], coordsArr[3]];
|
||||
var r0 = null;
|
||||
var r1 = null;
|
||||
} else if (type == 3) {
|
||||
var p0 = [coordsArr[0], coordsArr[1]];
|
||||
var p1 = [coordsArr[3], coordsArr[4]];
|
||||
var r0 = coordsArr[2];
|
||||
var r1 = coordsArr[5];
|
||||
} else {
|
||||
error('getPattern type unknown: ' + type);
|
||||
}
|
||||
|
||||
var matrix = this.matrix;
|
||||
if (matrix) {
|
||||
p0 = Util.applyTransform(p0, matrix);
|
||||
p1 = Util.applyTransform(p1, matrix);
|
||||
}
|
||||
|
||||
return ['RadialAxial', type, this.colorStops, p0, p1, r0, r1];
|
||||
}
|
||||
};
|
||||
|
||||
return constructor;
|
||||
})();
|
||||
|
||||
Shadings.Dummy = (function dummyShading() {
|
||||
function constructor() {
|
||||
this.type = 'Pattern';
|
||||
}
|
||||
|
||||
constructor.fromIR = function dummyShadingFromIR() {
|
||||
return 'hotpink';
|
||||
};
|
||||
|
||||
constructor.prototype = {
|
||||
getIR: function dummyShadingGetIR() {
|
||||
return ['Dummy'];
|
||||
}
|
||||
};
|
||||
return constructor;
|
||||
})();
|
||||
|
||||
var TilingPattern = (function tilingPattern() {
|
||||
var PAINT_TYPE_COLORED = 1, PAINT_TYPE_UNCOLORED = 2;
|
||||
|
||||
function TilingPattern(IR, color, ctx, objs) {
|
||||
var IRQueue = IR[2];
|
||||
this.matrix = IR[3];
|
||||
var bbox = IR[4];
|
||||
var xstep = IR[5];
|
||||
var ystep = IR[6];
|
||||
var paintType = IR[7];
|
||||
|
||||
TODO('TilingType');
|
||||
|
||||
this.curMatrix = ctx.mozCurrentTransform;
|
||||
this.invMatrix = ctx.mozCurrentTransformInverse;
|
||||
this.ctx = ctx;
|
||||
this.type = 'Pattern';
|
||||
|
||||
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];
|
||||
|
||||
// TODO: hack to avoid OOM, we would idealy compute the tiling
|
||||
// pattern to be only as large as the acual size in device space
|
||||
// This could be computed with .mozCurrentTransform, but still
|
||||
// needs to be implemented
|
||||
while (Math.abs(width) > 512 || Math.abs(height) > 512) {
|
||||
width = 512;
|
||||
height = 512;
|
||||
}
|
||||
|
||||
var tmpCanvas = new ScratchCanvas(width, height);
|
||||
|
||||
// set the new canvas element context as the graphics context
|
||||
var tmpCtx = tmpCanvas.getContext('2d');
|
||||
var graphics = new CanvasGraphics(tmpCtx, objs);
|
||||
|
||||
switch (paintType) {
|
||||
case PAINT_TYPE_COLORED:
|
||||
tmpCtx.fillStyle = ctx.fillStyle;
|
||||
tmpCtx.strokeStyle = ctx.strokeStyle;
|
||||
break;
|
||||
case PAINT_TYPE_UNCOLORED:
|
||||
color = Util.makeCssRgb.apply(this, color);
|
||||
tmpCtx.fillStyle = color;
|
||||
tmpCtx.strokeStyle = color;
|
||||
break;
|
||||
default:
|
||||
error('Unsupported paint type: ' + paintType);
|
||||
}
|
||||
|
||||
var scale = [width / xstep, height / ystep];
|
||||
this.scale = scale;
|
||||
|
||||
// transform coordinates to pattern space
|
||||
var tmpTranslate = [1, 0, 0, 1, -topLeft[0], -topLeft[1]];
|
||||
var tmpScale = [scale[0], 0, 0, scale[1], 0, 0];
|
||||
graphics.transform.apply(graphics, tmpScale);
|
||||
graphics.transform.apply(graphics, tmpTranslate);
|
||||
|
||||
if (bbox && isArray(bbox) && 4 == bbox.length) {
|
||||
var bboxWidth = x1 - x0;
|
||||
var bboxHeight = y1 - y0;
|
||||
graphics.rectangle(x0, y0, bboxWidth, bboxHeight);
|
||||
graphics.clip();
|
||||
graphics.endPath();
|
||||
}
|
||||
|
||||
graphics.executeIRQueue(IRQueue);
|
||||
|
||||
this.canvas = tmpCanvas;
|
||||
}
|
||||
|
||||
TilingPattern.getIR = function tiling_getIR(codeIR, dict, args) {
|
||||
var matrix = dict.get('Matrix');
|
||||
var bbox = dict.get('BBox');
|
||||
var xstep = dict.get('XStep');
|
||||
var ystep = dict.get('YStep');
|
||||
var paintType = dict.get('PaintType');
|
||||
|
||||
return [
|
||||
'TilingPattern', args, codeIR, matrix, bbox, xstep, ystep, paintType
|
||||
];
|
||||
};
|
||||
|
||||
TilingPattern.prototype = {
|
||||
getPattern: function tiling_getPattern() {
|
||||
var matrix = this.matrix;
|
||||
var curMatrix = this.curMatrix;
|
||||
var ctx = this.ctx;
|
||||
|
||||
if (curMatrix)
|
||||
ctx.setTransform.apply(ctx, curMatrix);
|
||||
|
||||
if (matrix)
|
||||
ctx.transform.apply(ctx, matrix);
|
||||
|
||||
var scale = this.scale;
|
||||
ctx.scale(1 / scale[0], 1 / scale[1]);
|
||||
|
||||
return ctx.createPattern(this.canvas, 'repeat');
|
||||
}
|
||||
};
|
||||
|
||||
return TilingPattern;
|
||||
})();
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
|
||||
|
||||
var PDFJS = {};
|
||||
|
||||
(function pdfjsWrapper() {
|
||||
// Use strict in our context only - users might not want it
|
||||
'use strict';
|
||||
|
||||
PDFJS.build = 'PDFJSSCRIPT_BUNDLE_VER';
|
||||
|
||||
// Files are inserted below - see Makefile
|
||||
/* PDFJSSCRIPT_INCLUDE_ALL */
|
||||
|
||||
}).call((typeof window === 'undefined') ? this : window);
|
|
@ -0,0 +1,286 @@
|
|||
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
|
||||
|
||||
'use strict';
|
||||
|
||||
function log(msg) {
|
||||
if (console && console.log)
|
||||
console.log(msg);
|
||||
else if (print)
|
||||
print(msg);
|
||||
}
|
||||
|
||||
function warn(msg) {
|
||||
if (verbosity >= WARNINGS)
|
||||
log('Warning: ' + msg);
|
||||
}
|
||||
|
||||
function backtrace() {
|
||||
try {
|
||||
throw new Error();
|
||||
} catch (e) {
|
||||
return e.stack ? e.stack.split('\n').slice(2).join('\n') : '';
|
||||
}
|
||||
}
|
||||
|
||||
function error(msg) {
|
||||
log('Error: ' + msg);
|
||||
log(backtrace());
|
||||
throw new Error(msg);
|
||||
}
|
||||
|
||||
function TODO(what) {
|
||||
if (verbosity >= TODOS)
|
||||
log('TODO: ' + what);
|
||||
}
|
||||
|
||||
function malformed(msg) {
|
||||
error('Malformed PDF: ' + msg);
|
||||
}
|
||||
|
||||
function assert(cond, msg) {
|
||||
if (!cond)
|
||||
error(msg);
|
||||
}
|
||||
|
||||
// In a well-formed PDF, |cond| holds. If it doesn't, subsequent
|
||||
// behavior is undefined.
|
||||
function assertWellFormed(cond, msg) {
|
||||
if (!cond)
|
||||
malformed(msg);
|
||||
}
|
||||
|
||||
function shadow(obj, prop, value) {
|
||||
Object.defineProperty(obj, prop, { value: value,
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
writable: false });
|
||||
return value;
|
||||
}
|
||||
|
||||
function bytesToString(bytes) {
|
||||
var str = '';
|
||||
var length = bytes.length;
|
||||
for (var n = 0; n < length; ++n)
|
||||
str += String.fromCharCode(bytes[n]);
|
||||
return str;
|
||||
}
|
||||
|
||||
function stringToBytes(str) {
|
||||
var length = str.length;
|
||||
var bytes = new Uint8Array(length);
|
||||
for (var n = 0; n < length; ++n)
|
||||
bytes[n] = str.charCodeAt(n) & 0xFF;
|
||||
return bytes;
|
||||
}
|
||||
|
||||
var IDENTITY_MATRIX = [1, 0, 0, 1, 0, 0];
|
||||
|
||||
var Util = (function utilUtil() {
|
||||
function constructor() {}
|
||||
constructor.makeCssRgb = function makergb(r, g, b) {
|
||||
var ri = (255 * r) | 0, gi = (255 * g) | 0, bi = (255 * b) | 0;
|
||||
return 'rgb(' + ri + ',' + gi + ',' + bi + ')';
|
||||
};
|
||||
constructor.makeCssCmyk = function makecmyk(c, m, y, k) {
|
||||
c = (new DeviceCmykCS()).getRgb([c, m, y, k]);
|
||||
var ri = (255 * c[0]) | 0, gi = (255 * c[1]) | 0, bi = (255 * c[2]) | 0;
|
||||
return 'rgb(' + ri + ',' + gi + ',' + bi + ')';
|
||||
};
|
||||
constructor.applyTransform = function apply(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];
|
||||
};
|
||||
|
||||
return constructor;
|
||||
})();
|
||||
|
||||
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, str2 = '';
|
||||
if (str[0] === '\xFE' && str[1] === '\xFF') {
|
||||
// UTF16BE BOM
|
||||
for (i = 2; i < n; i += 2)
|
||||
str2 += String.fromCharCode(
|
||||
(str.charCodeAt(i) << 8) | str.charCodeAt(i + 1));
|
||||
} else {
|
||||
for (i = 0; i < n; ++i) {
|
||||
var code = PDFStringTranslateTable[str.charCodeAt(i)];
|
||||
str2 += code ? String.fromCharCode(code) : str.charAt(i);
|
||||
}
|
||||
}
|
||||
return str2;
|
||||
}
|
||||
|
||||
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 isNull(v) {
|
||||
return v === null;
|
||||
}
|
||||
|
||||
function isName(v) {
|
||||
return v instanceof Name;
|
||||
}
|
||||
|
||||
function isCmd(v, cmd) {
|
||||
return v instanceof Cmd && (!cmd || v.cmd == cmd);
|
||||
}
|
||||
|
||||
function isDict(v, type) {
|
||||
return v instanceof Dict && (!type || v.get('Type').name == type);
|
||||
}
|
||||
|
||||
function isArray(v) {
|
||||
return v instanceof Array;
|
||||
}
|
||||
|
||||
function isStream(v) {
|
||||
return typeof v == 'object' && v != null && ('getChar' in v);
|
||||
}
|
||||
|
||||
function isArrayBuffer(v) {
|
||||
return typeof v == 'object' && v != null && ('byteLength' in v);
|
||||
}
|
||||
|
||||
function isRef(v) {
|
||||
return v instanceof Ref;
|
||||
}
|
||||
|
||||
function isPDFFunction(v) {
|
||||
var fnDict;
|
||||
if (typeof v != 'object')
|
||||
return false;
|
||||
else if (isDict(v))
|
||||
fnDict = v;
|
||||
else if (isStream(v))
|
||||
fnDict = v.dict;
|
||||
else
|
||||
return false;
|
||||
return fnDict.has('FunctionType');
|
||||
}
|
||||
|
||||
/**
|
||||
* 'Promise' object.
|
||||
* Each object that is stored in PDFObjects is based on a Promise object that
|
||||
* contains the status of the object and the data. There migth be situations,
|
||||
* where a function want to use the value of an object, but it isn't ready at
|
||||
* that time. To get a notification, once the object is ready to be used, s.o.
|
||||
* can add a callback using the `then` method on the promise that then calls
|
||||
* the callback once the object gets resolved.
|
||||
* A promise can get resolved only once and only once the data of the promise
|
||||
* can be set. If any of these happens twice or the data is required before
|
||||
* it was set, an exception is throw.
|
||||
*/
|
||||
var Promise = (function promise() {
|
||||
var EMPTY_PROMISE = {};
|
||||
|
||||
/**
|
||||
* If `data` is passed in this constructor, the promise is created resolved.
|
||||
* If there isn't data, it isn't resolved at the beginning.
|
||||
*/
|
||||
function Promise(name, data) {
|
||||
this.name = name;
|
||||
// If you build a promise and pass in some data it's already resolved.
|
||||
if (data != null) {
|
||||
this.isResolved = true;
|
||||
this._data = data;
|
||||
this.hasData = true;
|
||||
} else {
|
||||
this.isResolved = false;
|
||||
this._data = EMPTY_PROMISE;
|
||||
}
|
||||
this.callbacks = [];
|
||||
};
|
||||
|
||||
Promise.prototype = {
|
||||
hasData: false,
|
||||
|
||||
set data(value) {
|
||||
if (value === undefined) {
|
||||
return;
|
||||
}
|
||||
if (this._data !== EMPTY_PROMISE) {
|
||||
throw 'Promise ' + this.name +
|
||||
': Cannot set the data of a promise twice';
|
||||
}
|
||||
this._data = value;
|
||||
this.hasData = true;
|
||||
|
||||
if (this.onDataCallback) {
|
||||
this.onDataCallback(value);
|
||||
}
|
||||
},
|
||||
|
||||
get data() {
|
||||
if (this._data === EMPTY_PROMISE) {
|
||||
throw 'Promise ' + this.name + ': Cannot get data that isn\'t set';
|
||||
}
|
||||
return this._data;
|
||||
},
|
||||
|
||||
onData: function promiseOnData(callback) {
|
||||
if (this._data !== EMPTY_PROMISE) {
|
||||
callback(this._data);
|
||||
} else {
|
||||
this.onDataCallback = callback;
|
||||
}
|
||||
},
|
||||
|
||||
resolve: function promiseResolve(data) {
|
||||
if (this.isResolved) {
|
||||
throw 'A Promise can be resolved only once ' + this.name;
|
||||
}
|
||||
|
||||
this.isResolved = true;
|
||||
this.data = data;
|
||||
var callbacks = this.callbacks;
|
||||
|
||||
for (var i = 0, ii = callbacks.length; i < ii; i++) {
|
||||
callbacks[i].call(null, data);
|
||||
}
|
||||
},
|
||||
|
||||
then: function promiseThen(callback) {
|
||||
if (!callback) {
|
||||
throw 'Requiring callback' + this.name;
|
||||
}
|
||||
|
||||
// If the promise is already resolved, call the callback directly.
|
||||
if (this.isResolved) {
|
||||
var data = this.data;
|
||||
callback.call(null, data);
|
||||
} else {
|
||||
this.callbacks.push(callback);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return Promise;
|
||||
})();
|
||||
|
|
@ -0,0 +1,298 @@
|
|||
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
|
||||
|
||||
var CFFEncodingMap = {
|
||||
'0': '-reserved-',
|
||||
'1': 'hstem',
|
||||
'2': '-reserved-',
|
||||
'3': 'vstem',
|
||||
'4': 'vmoveto',
|
||||
'5': 'rlineto',
|
||||
'6': 'hlineto',
|
||||
'7': 'vlineto',
|
||||
'8': 'rrcurveto',
|
||||
'9': '-reserved-',
|
||||
'10': 'callsubr',
|
||||
'11': 'return',
|
||||
'12': {
|
||||
'3': 'and',
|
||||
'4': 'or',
|
||||
'5': 'not',
|
||||
'9': 'abs',
|
||||
'10': 'add',
|
||||
'11': 'div',
|
||||
'12': 'sub',
|
||||
'14': 'neg',
|
||||
'15': 'eq',
|
||||
'18': 'drop',
|
||||
'20': 'put',
|
||||
'21': 'get',
|
||||
'22': 'ifelse',
|
||||
'23': 'random',
|
||||
'24': 'mul',
|
||||
'26': 'sqrt',
|
||||
'27': 'dup',
|
||||
'28': 'exch',
|
||||
'29': 'index',
|
||||
'30': 'roll',
|
||||
'34': 'hflex',
|
||||
'35': 'flex',
|
||||
'36': 'hflex1',
|
||||
'37': 'flex1'
|
||||
},
|
||||
'13': '-reserved-',
|
||||
'14': 'endchar',
|
||||
'15': '-reserved-',
|
||||
'16': '-reserved-',
|
||||
'17': '-reserved-',
|
||||
'18': 'hstemhm',
|
||||
'19': 'hintmask',
|
||||
'20': 'cntrmask',
|
||||
'21': 'rmoveto',
|
||||
'22': 'hmoveto',
|
||||
'23': 'vstemhm',
|
||||
'24': 'rcurveline',
|
||||
'25': 'rlivecurve',
|
||||
'26': 'vvcurveto',
|
||||
'27': 'hhcurveto',
|
||||
'29': 'callgsubr',
|
||||
'30': 'vhcurveto',
|
||||
'31': 'hvcurveto'
|
||||
};
|
||||
|
||||
var CFFDictDataMap = {
|
||||
'0': {
|
||||
name: 'version',
|
||||
operand: 'SID'
|
||||
},
|
||||
'1': {
|
||||
name: 'Notice',
|
||||
operand: 'SID'
|
||||
},
|
||||
'2': {
|
||||
name: 'FullName',
|
||||
operand: 'SID'
|
||||
},
|
||||
'3': {
|
||||
name: 'FamilyName',
|
||||
operand: 'SID'
|
||||
},
|
||||
'4': {
|
||||
name: 'Weight',
|
||||
operand: 'SID'
|
||||
},
|
||||
'5': {
|
||||
name: 'FontBBox',
|
||||
operand: [0, 0, 0, 0]
|
||||
},
|
||||
'6': {
|
||||
name: 'BlueValues'
|
||||
},
|
||||
'7': {
|
||||
name: 'OtherBlues'
|
||||
},
|
||||
'8': {
|
||||
name: 'FamilyBlues'
|
||||
},
|
||||
'9': {
|
||||
name: 'FamilyOtherBlues'
|
||||
},
|
||||
'10': {
|
||||
name: 'StdHW'
|
||||
},
|
||||
'11': {
|
||||
name: 'StdVW'
|
||||
},
|
||||
'12': {
|
||||
'0': {
|
||||
name: 'Copyright',
|
||||
operand: 'SID'
|
||||
},
|
||||
'1': {
|
||||
name: 'IsFixedPitch',
|
||||
operand: false
|
||||
},
|
||||
'2': {
|
||||
name: 'ItalicAngle',
|
||||
operand: 0
|
||||
},
|
||||
'3': {
|
||||
name: 'UnderlinePosition',
|
||||
operand: -100
|
||||
},
|
||||
'4': {
|
||||
name: 'UnderlineThickness',
|
||||
operand: 50
|
||||
},
|
||||
'5': {
|
||||
name: 'PaintType',
|
||||
operand: 0
|
||||
},
|
||||
'6': {
|
||||
name: 'CharstringType',
|
||||
operand: 2
|
||||
},
|
||||
'7': {
|
||||
name: 'FontMatrix',
|
||||
operand: [0.001, 0, 0, 0.001, 0 , 0]
|
||||
},
|
||||
'8': {
|
||||
name: 'StrokeWidth',
|
||||
operand: 0
|
||||
},
|
||||
'9': {
|
||||
name: 'BlueScale'
|
||||
},
|
||||
'10': {
|
||||
name: 'BlueShift'
|
||||
},
|
||||
'11': {
|
||||
name: 'BlueFuzz'
|
||||
},
|
||||
'12': {
|
||||
name: 'StemSnapH'
|
||||
},
|
||||
'13': {
|
||||
name: 'StemSnapV'
|
||||
},
|
||||
'14': {
|
||||
name: 'ForceBold'
|
||||
},
|
||||
'17': {
|
||||
name: 'LanguageGroup'
|
||||
},
|
||||
'18': {
|
||||
name: 'ExpansionFactor'
|
||||
},
|
||||
'19': {
|
||||
name: 'initialRandomSeed'
|
||||
},
|
||||
'20': {
|
||||
name: 'SyntheticBase',
|
||||
operand: null
|
||||
},
|
||||
'21': {
|
||||
name: 'PostScript',
|
||||
operand: 'SID'
|
||||
},
|
||||
'22': {
|
||||
name: 'BaseFontName',
|
||||
operand: 'SID'
|
||||
},
|
||||
'23': {
|
||||
name: 'BaseFontBlend',
|
||||
operand: 'delta'
|
||||
}
|
||||
},
|
||||
'13': {
|
||||
name: 'UniqueID',
|
||||
operand: null
|
||||
},
|
||||
'14': {
|
||||
name: 'XUID',
|
||||
operand: []
|
||||
},
|
||||
'15': {
|
||||
name: 'charset',
|
||||
operand: 0
|
||||
},
|
||||
'16': {
|
||||
name: 'Encoding',
|
||||
operand: 0
|
||||
},
|
||||
'17': {
|
||||
name: 'CharStrings',
|
||||
operand: null
|
||||
},
|
||||
'18': {
|
||||
name: 'Private',
|
||||
operand: 'number number'
|
||||
},
|
||||
'19': {
|
||||
name: 'Subrs'
|
||||
},
|
||||
'20': {
|
||||
name: 'defaultWidthX'
|
||||
},
|
||||
'21': {
|
||||
name: 'nominalWidthX'
|
||||
}
|
||||
};
|
||||
|
||||
var CFFDictPrivateDataMap = {
|
||||
'6': {
|
||||
name: 'BluesValues',
|
||||
operand: 'delta'
|
||||
},
|
||||
'7': {
|
||||
name: 'OtherBlues',
|
||||
operand: 'delta'
|
||||
},
|
||||
'8': {
|
||||
name: 'FamilyBlues',
|
||||
operand: 'delta'
|
||||
},
|
||||
'9': {
|
||||
name: 'FamilyOtherBlues',
|
||||
operand: 'delta'
|
||||
},
|
||||
'10': {
|
||||
name: 'StdHW',
|
||||
operand: null
|
||||
},
|
||||
'11': {
|
||||
name: 'StdVW',
|
||||
operand: null
|
||||
},
|
||||
'12': {
|
||||
'9': {
|
||||
name: 'BlueScale',
|
||||
operand: 0.039625
|
||||
},
|
||||
'10': {
|
||||
name: 'BlueShift',
|
||||
operand: 7
|
||||
},
|
||||
'11': {
|
||||
name: 'BlueFuzz',
|
||||
operand: 1
|
||||
},
|
||||
'12': {
|
||||
name: 'StemSnapH',
|
||||
operand: 'delta'
|
||||
},
|
||||
'13': {
|
||||
name: 'StemSnapV',
|
||||
operand: 'delta'
|
||||
},
|
||||
'14': {
|
||||
name: 'ForceBold',
|
||||
operand: 'boolean'
|
||||
},
|
||||
'17': {
|
||||
name: 'LanguageGroup',
|
||||
operand: 0
|
||||
},
|
||||
'18': {
|
||||
name: 'ExpansionFactor',
|
||||
operand: 0.06
|
||||
},
|
||||
'19': {
|
||||
name: 'initialRandomSeed',
|
||||
operand: 0
|
||||
}
|
||||
},
|
||||
'19': {
|
||||
name: 'Subrs',
|
||||
operand: null
|
||||
},
|
||||
'20': {
|
||||
name: 'defaultWidthX',
|
||||
operand: 0
|
||||
},
|
||||
'21': {
|
||||
name: 'nominalWidthX',
|
||||
operand: 0
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,408 @@
|
|||
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
|
||||
|
||||
/*
|
||||
* The Type2 reader code below is only used for debugging purpose since Type2
|
||||
* is only a CharString format and is never used directly as a Font file.
|
||||
*
|
||||
* So the code here is useful for dumping the data content of a .cff file in
|
||||
* order to investigate the similarity between a Type1 CharString and a Type2
|
||||
* CharString or to understand the structure of the CFF format.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Build a charset by assigning the glyph name and the human readable form
|
||||
* of the glyph data.
|
||||
*/
|
||||
function readCharset(aStream, aCharstrings) {
|
||||
var charset = {};
|
||||
|
||||
var format = aStream.getByte();
|
||||
var count = aCharstrings.length - 1;
|
||||
if (format == 0) {
|
||||
charset['.notdef'] = readCharstringEncoding(aCharstrings[0]);
|
||||
|
||||
for (var i = 1; i < count + 1; i++) {
|
||||
var sid = aStream.getByte() << 8 | aStream.getByte();
|
||||
charset[CFFStrings[sid]] = readCharstringEncoding(aCharstrings[i]);
|
||||
//log(CFFStrings[sid] + "::" + charset[CFFStrings[sid]]);
|
||||
}
|
||||
} else if (format == 1) {
|
||||
for (var i = 1; i < count + 1; i++) {
|
||||
var first = aStream.getByte();
|
||||
first = (first << 8) | aStream.getByte();
|
||||
var numLeft = aStream.getByte();
|
||||
for (var j = 0; j <= numLeft; j++) {
|
||||
var sid = first++;
|
||||
if (CFFStrings[sid] == 'three')
|
||||
log(aCharstrings[j]);
|
||||
charset[CFFStrings[sid]] = readCharstringEncoding(aCharstrings[j]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
error('Invalid charset format');
|
||||
}
|
||||
|
||||
return charset;
|
||||
}
|
||||
|
||||
/*
|
||||
* Take a Type2 binary charstring as input and transform it to a human
|
||||
* readable representation as specified by the 'The Type 2 Charstring Format',
|
||||
* chapter 3.1.
|
||||
*/
|
||||
function readCharstringEncoding(aString) {
|
||||
if (!aString)
|
||||
return '';
|
||||
|
||||
var charstringTokens = [];
|
||||
|
||||
var count = aString.length;
|
||||
for (var i = 0; i < count; ) {
|
||||
var value = aString[i++];
|
||||
var token = null;
|
||||
|
||||
if (value < 0) {
|
||||
continue;
|
||||
} else if (value <= 11) {
|
||||
token = CFFEncodingMap[value];
|
||||
} else if (value == 12) {
|
||||
token = CFFEncodingMap[value][aString[i++]];
|
||||
} else if (value <= 18) {
|
||||
token = CFFEncodingMap[value];
|
||||
} else if (value <= 20) {
|
||||
var mask = aString[i++];
|
||||
token = CFFEncodingMap[value];
|
||||
} else if (value <= 27) {
|
||||
token = CFFEncodingMap[value];
|
||||
} else if (value == 28) {
|
||||
token = aString[i++] << 8 | aString[i++];
|
||||
} else if (value <= 31) {
|
||||
token = CFFEncodingMap[value];
|
||||
} else if (value < 247) {
|
||||
token = parseInt(value, 10) - 139;
|
||||
} else if (value < 251) {
|
||||
token = (value - 247) * 256 + aString[i++] + 108;
|
||||
} else if (value < 255) {
|
||||
token = -(value - 251) * 256 - aString[i++] - 108;
|
||||
} else {// value == 255
|
||||
token = aString[i++] << 24 | aString[i++] << 16 |
|
||||
aString[i++] << 8 | aString[i];
|
||||
}
|
||||
|
||||
charstringTokens.push(token);
|
||||
}
|
||||
|
||||
return charstringTokens;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Take a binary DICT Data as input and transform it into a human readable
|
||||
* form as specified by 'The Compact Font Format Specification', chapter 5.
|
||||
*/
|
||||
function readFontDictData(aString, aMap) {
|
||||
var fontDictDataTokens = [];
|
||||
|
||||
var count = aString.length;
|
||||
for (var i = 0; i < count; i) {
|
||||
var value = aString[i++];
|
||||
var token = null;
|
||||
|
||||
if (value == 12) {
|
||||
token = aMap[value][aString[i++]];
|
||||
} else if (value == 28) {
|
||||
token = aString[i++] << 8 | aString[i++];
|
||||
} else if (value == 29) {
|
||||
token = aString[i++] << 24 |
|
||||
aString[i++] << 16 |
|
||||
aString[i++] << 8 |
|
||||
aString[i++];
|
||||
} else if (value == 30) {
|
||||
token = '';
|
||||
var parsed = false;
|
||||
while (!parsed) {
|
||||
var byte = aString[i++];
|
||||
|
||||
var nibbles = [parseInt(byte / 16, 10), parseInt(byte % 16, 10)];
|
||||
for (var j = 0; j < nibbles.length; j++) {
|
||||
var nibble = nibbles[j];
|
||||
switch (nibble) {
|
||||
case 0xA:
|
||||
token += '.';
|
||||
break;
|
||||
case 0xB:
|
||||
token += 'E';
|
||||
break;
|
||||
case 0xC:
|
||||
token += 'E-';
|
||||
break;
|
||||
case 0xD:
|
||||
break;
|
||||
case 0xE:
|
||||
token += '-';
|
||||
break;
|
||||
case 0xF:
|
||||
parsed = true;
|
||||
break;
|
||||
default:
|
||||
token += nibble;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
token = parseFloat(token);
|
||||
} else if (value <= 31) {
|
||||
token = aMap[value];
|
||||
} else if (value <= 246) {
|
||||
token = parseInt(value, 10) - 139;
|
||||
} else if (value <= 250) {
|
||||
token = (value - 247) * 256 + aString[i++] + 108;
|
||||
} else if (value <= 254) {
|
||||
token = -(value - 251) * 256 - aString[i++] - 108;
|
||||
} else if (value == 255) {
|
||||
error('255 is not a valid DICT command');
|
||||
}
|
||||
|
||||
fontDictDataTokens.push(token);
|
||||
}
|
||||
|
||||
return fontDictDataTokens;
|
||||
}
|
||||
|
||||
/*
|
||||
* Take a stream as input and return an array of objects.
|
||||
* In CFF an INDEX is a structure with the following format:
|
||||
* {
|
||||
* count: 2 bytes (Number of objects stored in INDEX),
|
||||
* offsize: 1 byte (Offset array element size),
|
||||
* offset: [count + 1] bytes (Offsets array),
|
||||
* data: - (Objects data)
|
||||
* }
|
||||
*
|
||||
* More explanation are given in the 'CFF Font Format Specification',
|
||||
* chapter 5.
|
||||
*/
|
||||
function readFontIndexData(aStream, aIsByte) {
|
||||
var count = aStream.getByte() << 8 | aStream.getByte();
|
||||
var offsize = aStream.getByte();
|
||||
|
||||
function getNextOffset() {
|
||||
switch (offsize) {
|
||||
case 0:
|
||||
return 0;
|
||||
case 1:
|
||||
return aStream.getByte();
|
||||
case 2:
|
||||
return aStream.getByte() << 8 | aStream.getByte();
|
||||
case 3:
|
||||
return aStream.getByte() << 16 | aStream.getByte() << 8 |
|
||||
aStream.getByte();
|
||||
case 4:
|
||||
return aStream.getByte() << 24 | aStream.getByte() << 16 |
|
||||
aStream.getByte() << 8 | aStream.getByte();
|
||||
}
|
||||
error(offsize + ' is not a valid offset size');
|
||||
return null;
|
||||
}
|
||||
|
||||
var offsets = [];
|
||||
for (var i = 0; i < count + 1; i++)
|
||||
offsets.push(getNextOffset());
|
||||
|
||||
dump('Found ' + count + ' objects at offsets :' +
|
||||
offsets + ' (offsize: ' + offsize + ')');
|
||||
|
||||
// Now extract the objects
|
||||
var relativeOffset = aStream.pos;
|
||||
var objects = [];
|
||||
for (var i = 0; i < count; i++) {
|
||||
var offset = offsets[i];
|
||||
aStream.pos = relativeOffset + offset - 1;
|
||||
|
||||
var data = [];
|
||||
var length = offsets[i + 1] - 1;
|
||||
for (var j = offset - 1; j < length; j++)
|
||||
data.push(aIsByte ? aStream.getByte() : aStream.getChar());
|
||||
objects.push(data);
|
||||
}
|
||||
|
||||
return objects;
|
||||
}
|
||||
|
||||
var Type2Parser = function type2Parser(aFilePath) {
|
||||
var font = new Dict();
|
||||
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', aFilePath, false);
|
||||
xhr.mozResponseType = xhr.responseType = 'arraybuffer';
|
||||
xhr.expected = (document.URL.indexOf('file:') == 0) ? 0 : 200;
|
||||
xhr.send(null);
|
||||
this.data = new Stream(xhr.mozResponseArrayBuffer || xhr.mozResponse ||
|
||||
xhr.responseArrayBuffer || xhr.response);
|
||||
|
||||
// Turn on this flag for additional debugging logs
|
||||
var debug = false;
|
||||
|
||||
function dump(aStr) {
|
||||
if (debug)
|
||||
log(aStr);
|
||||
}
|
||||
|
||||
function parseAsToken(aString, aMap) {
|
||||
var decoded = readFontDictData(aString, aMap);
|
||||
|
||||
var stack = [];
|
||||
var count = decoded.length;
|
||||
for (var i = 0; i < count; i++) {
|
||||
var token = decoded[i];
|
||||
if (isNum(token)) {
|
||||
stack.push(token);
|
||||
} else {
|
||||
switch (token.operand) {
|
||||
case 'SID':
|
||||
font.set(token.name, CFFStrings[stack.pop()]);
|
||||
break;
|
||||
case 'number number':
|
||||
font.set(token.name, {
|
||||
offset: stack.pop(),
|
||||
size: stack.pop()
|
||||
});
|
||||
break;
|
||||
case 'boolean':
|
||||
font.set(token.name, stack.pop());
|
||||
break;
|
||||
case 'delta':
|
||||
font.set(token.name, stack.pop());
|
||||
break;
|
||||
default:
|
||||
if (token.operand && token.operand.length) {
|
||||
var array = [];
|
||||
for (var j = 0; j < token.operand.length; j++)
|
||||
array.push(stack.pop());
|
||||
font.set(token.name, array);
|
||||
} else {
|
||||
font.set(token.name, stack.pop());
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.parse = function type2ParserParse(aStream) {
|
||||
font.set('major', aStream.getByte());
|
||||
font.set('minor', aStream.getByte());
|
||||
font.set('hdrSize', aStream.getByte());
|
||||
font.set('offsize', aStream.getByte());
|
||||
|
||||
// Read the NAME Index
|
||||
dump('Reading Index: Names');
|
||||
font.set('Names', readFontIndexData(aStream));
|
||||
dump('Names: ' + font.get('Names'));
|
||||
|
||||
// Read the Top Dict Index
|
||||
dump('Reading Index: TopDict');
|
||||
var topDict = readFontIndexData(aStream, true);
|
||||
dump('TopDict: ' + topDict);
|
||||
|
||||
// Read the String Index
|
||||
dump('Reading Index: Strings');
|
||||
var strings = readFontIndexData(aStream);
|
||||
dump('strings: ' + strings);
|
||||
|
||||
// Fill up the Strings dictionary with the new unique strings
|
||||
for (var i = 0; i < strings.length; i++)
|
||||
CFFStrings.push(strings[i].join(''));
|
||||
|
||||
// Parse the TopDict operator
|
||||
var objects = [];
|
||||
var count = topDict.length;
|
||||
for (var i = 0; i < count; i++)
|
||||
parseAsToken(topDict[i], CFFDictDataMap);
|
||||
|
||||
// Read the Global Subr Index that comes just after the Strings Index
|
||||
// (cf. "The Compact Font Format Specification" Chapter 16)
|
||||
dump('Reading Global Subr Index');
|
||||
var subrs = readFontIndexData(aStream, true);
|
||||
dump(subrs);
|
||||
|
||||
// Reading Private Dict
|
||||
var priv = font.get('Private');
|
||||
dump('Reading Private Dict (offset: ' + priv.offset +
|
||||
' size: ' + priv.size + ')');
|
||||
aStream.pos = priv.offset;
|
||||
|
||||
var privateDict = [];
|
||||
for (var i = 0; i < priv.size; i++)
|
||||
privateDict.push(aStream.getByte());
|
||||
dump('private:' + privateDict);
|
||||
parseAsToken(privateDict, CFFDictPrivateDataMap);
|
||||
|
||||
for (var p in font.map)
|
||||
dump(p + '::' + font.get(p));
|
||||
|
||||
// Read CharStrings Index
|
||||
var charStringsOffset = font.get('CharStrings');
|
||||
dump('Read CharStrings Index (offset: ' + charStringsOffset + ')');
|
||||
aStream.pos = charStringsOffset;
|
||||
var charStrings = readFontIndexData(aStream, true);
|
||||
|
||||
// Read Charset
|
||||
dump('Read Charset for ' + charStrings.length + ' glyphs');
|
||||
var charsetEntry = font.get('charset');
|
||||
if (charsetEntry == 0) {
|
||||
error('Need to support CFFISOAdobeCharset');
|
||||
} else if (charsetEntry == 1) {
|
||||
error('Need to support CFFExpert');
|
||||
} else if (charsetEntry == 2) {
|
||||
error('Need to support CFFExpertSubsetCharset');
|
||||
} else {
|
||||
aStream.pos = charsetEntry;
|
||||
var charset = readCharset(aStream, charStrings);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
* To try the Type2 decoder on a local file in the current directory:
|
||||
*
|
||||
* var cff = new Type2Parser("file.cff");
|
||||
* cff.parse(this.data);
|
||||
*
|
||||
* To try the Type2 decoder on a custom built CFF array:
|
||||
*
|
||||
* var file = new Uint8Array(cffFileArray, 0, cffFileSize);
|
||||
* var parser = new Type2Parser();
|
||||
* parser.parse(new Stream(file));
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Write to a file to the disk (works only on Firefox in privilege mode)
|
||||
* but this is useful for dumping a font file to the disk and check with
|
||||
* fontforge or the ots program what's wrong with the file.
|
||||
*
|
||||
* writeToFile(fontData, "/tmp/pdf.js." + fontCount + ".cff");
|
||||
*/
|
||||
function writeToFile(aBytes, aFilePath) {
|
||||
if (!('netscape' in window))
|
||||
return;
|
||||
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
var Cc = Components.classes,
|
||||
Ci = Components.interfaces;
|
||||
var file = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsILocalFile);
|
||||
file.initWithPath(aFilePath);
|
||||
|
||||
var stream = Cc['@mozilla.org/network/file-output-stream;1']
|
||||
.createInstance(Ci.nsIFileOutputStream);
|
||||
stream.init(file, 0x04 | 0x08 | 0x20, 0x180, 0);
|
||||
|
||||
var bos = Cc['@mozilla.org/binaryoutputstream;1']
|
||||
.createInstance(Ci.nsIBinaryOutputStream);
|
||||
bos.setOutputStream(stream);
|
||||
bos.writeByteArray(aBytes, aBytes.length);
|
||||
stream.close();
|
||||
}
|
||||
|
|
@ -0,0 +1,193 @@
|
|||
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
|
||||
|
||||
'use strict';
|
||||
|
||||
function MessageHandler(name, comObj) {
|
||||
this.name = name;
|
||||
this.comObj = comObj;
|
||||
var ah = this.actionHandler = {};
|
||||
|
||||
ah['console_log'] = [function ahConsoleLog(data) {
|
||||
console.log.apply(console, data);
|
||||
}];
|
||||
ah['console_error'] = [function ahConsoleError(data) {
|
||||
console.error.apply(console, data);
|
||||
}];
|
||||
|
||||
comObj.onmessage = function messageHandlerComObjOnMessage(event) {
|
||||
var data = event.data;
|
||||
if (data.action in ah) {
|
||||
var action = ah[data.action];
|
||||
action[0].call(action[1], data.data);
|
||||
} else {
|
||||
throw 'Unkown action from worker: ' + data.action;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
MessageHandler.prototype = {
|
||||
on: function messageHandlerOn(actionName, handler, scope) {
|
||||
var ah = this.actionHandler;
|
||||
if (ah[actionName]) {
|
||||
throw 'There is already an actionName called "' + actionName + '"';
|
||||
}
|
||||
ah[actionName] = [handler, scope];
|
||||
},
|
||||
|
||||
send: function messageHandlerSend(actionName, data) {
|
||||
this.comObj.postMessage({
|
||||
action: actionName,
|
||||
data: data
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
var WorkerMessageHandler = {
|
||||
setup: function wphSetup(handler) {
|
||||
var pdfDoc = null;
|
||||
|
||||
handler.on('test', function wphSetupTest(data) {
|
||||
handler.send('test', data instanceof Uint8Array);
|
||||
});
|
||||
|
||||
handler.on('workerSrc', function wphSetupWorkerSrc(data) {
|
||||
// In development, the `workerSrc` message is handled in the
|
||||
// `worker_loader.js` file. In production the workerProcessHandler is
|
||||
// called for this. This servers as a dummy to prevent calling an
|
||||
// undefined action `workerSrc`.
|
||||
});
|
||||
|
||||
handler.on('doc', function wphSetupDoc(data) {
|
||||
// Create only the model of the PDFDoc, which is enough for
|
||||
// processing the content of the pdf.
|
||||
pdfDoc = new PDFDocModel(new Stream(data));
|
||||
});
|
||||
|
||||
handler.on('page_request', function wphSetupPageRequest(pageNum) {
|
||||
pageNum = parseInt(pageNum);
|
||||
|
||||
var page = pdfDoc.getPage(pageNum);
|
||||
|
||||
// The following code does quite the same as
|
||||
// Page.prototype.startRendering, but stops at one point and sends the
|
||||
// result back to the main thread.
|
||||
var gfx = new CanvasGraphics(null);
|
||||
|
||||
var start = Date.now();
|
||||
|
||||
var dependency = [];
|
||||
|
||||
// Pre compile the pdf page and fetch the fonts/images.
|
||||
var IRQueue = page.getIRQueue(handler, dependency);
|
||||
|
||||
console.log('page=%d - getIRQueue: time=%dms, len=%d', pageNum,
|
||||
Date.now() - start, IRQueue.fnArray.length);
|
||||
|
||||
// Filter the dependecies for fonts.
|
||||
var fonts = {};
|
||||
for (var i = 0, ii = dependency.length; i < ii; i++) {
|
||||
var dep = dependency[i];
|
||||
if (dep.indexOf('font_') == 0) {
|
||||
fonts[dep] = true;
|
||||
}
|
||||
}
|
||||
|
||||
handler.send('page', {
|
||||
pageNum: pageNum,
|
||||
IRQueue: IRQueue,
|
||||
depFonts: Object.keys(fonts)
|
||||
});
|
||||
}, this);
|
||||
|
||||
handler.on('font', function wphSetupFont(data) {
|
||||
var objId = data[0];
|
||||
var name = data[1];
|
||||
var file = data[2];
|
||||
var properties = data[3];
|
||||
|
||||
var font = {
|
||||
name: name,
|
||||
file: file,
|
||||
properties: properties
|
||||
};
|
||||
|
||||
// Some fonts don't have a file, e.g. the build in ones like Arial.
|
||||
if (file) {
|
||||
var fontFileDict = new Dict();
|
||||
fontFileDict.map = file.dict.map;
|
||||
|
||||
var fontFile = new Stream(file.bytes, file.start,
|
||||
file.end - file.start, fontFileDict);
|
||||
|
||||
// Check if this is a FlateStream. Otherwise just use the created
|
||||
// Stream one. This makes complex_ttf_font.pdf work.
|
||||
var cmf = file.bytes[0];
|
||||
if ((cmf & 0x0f) == 0x08) {
|
||||
font.file = new FlateStream(fontFile);
|
||||
} else {
|
||||
font.file = fontFile;
|
||||
}
|
||||
}
|
||||
|
||||
var obj = new Font(font.name, font.file, font.properties);
|
||||
|
||||
var str = '';
|
||||
var objData = obj.data;
|
||||
if (objData) {
|
||||
var length = objData.length;
|
||||
for (var j = 0; j < length; ++j)
|
||||
str += String.fromCharCode(objData[j]);
|
||||
}
|
||||
|
||||
obj.str = str;
|
||||
|
||||
// Remove the data array form the font object, as it's not needed
|
||||
// anymore as we sent over the ready str.
|
||||
delete obj.data;
|
||||
|
||||
handler.send('font_ready', [objId, obj]);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
var consoleTimer = {};
|
||||
|
||||
var workerConsole = {
|
||||
log: function log() {
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
postMessage({
|
||||
action: 'console_log',
|
||||
data: args
|
||||
});
|
||||
},
|
||||
|
||||
error: function error() {
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
postMessage({
|
||||
action: 'console_error',
|
||||
data: args
|
||||
});
|
||||
},
|
||||
|
||||
time: function time(name) {
|
||||
consoleTimer[name] = Date.now();
|
||||
},
|
||||
|
||||
timeEnd: function timeEnd(name) {
|
||||
var time = consoleTimer[name];
|
||||
if (time == null) {
|
||||
throw 'Unkown timer name ' + name;
|
||||
}
|
||||
this.log('Timer:', name, Date.now() - time);
|
||||
}
|
||||
};
|
||||
|
||||
// Worker thread?
|
||||
if (typeof window === 'undefined') {
|
||||
globalScope.console = workerConsole;
|
||||
|
||||
var handler = new MessageHandler('worker_processor', this);
|
||||
WorkerMessageHandler.setup(handler);
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
|
||||
|
||||
'use strict';
|
||||
|
||||
function onMessageLoader(evt) {
|
||||
// Reset the `onmessage` function as it was only set to call
|
||||
// this function the first time a message is passed to the worker
|
||||
// but shouldn't get called anytime afterwards.
|
||||
this.onmessage = null;
|
||||
|
||||
if (evt.data.action !== 'workerSrc') {
|
||||
throw 'Worker expects first message to be `workerSrc`';
|
||||
}
|
||||
|
||||
// Content of `PDFJS.workerSrc` as defined on the main thread.
|
||||
var workerSrc = evt.data.data;
|
||||
|
||||
// Extract the directory that contains the source files to load.
|
||||
// Assuming the source files have the same relative possition as the
|
||||
// `workerSrc` file.
|
||||
var dir = workerSrc.substring(0, workerSrc.lastIndexOf('/') + 1);
|
||||
|
||||
// List of files to include;
|
||||
var files = [
|
||||
'core.js',
|
||||
'util.js',
|
||||
'canvas.js',
|
||||
'obj.js',
|
||||
'function.js',
|
||||
'charsets.js',
|
||||
'cidmaps.js',
|
||||
'colorspace.js',
|
||||
'crypto.js',
|
||||
'evaluator.js',
|
||||
'fonts.js',
|
||||
'glyphlist.js',
|
||||
'image.js',
|
||||
'metrics.js',
|
||||
'parser.js',
|
||||
'pattern.js',
|
||||
'stream.js',
|
||||
'worker.js',
|
||||
'../external/jpgjs/jpg.js'
|
||||
];
|
||||
|
||||
// Load all the files.
|
||||
for (var i = 0; i < files.length; i++) {
|
||||
importScripts(dir + files[i]);
|
||||
}
|
||||
}
|
||||
|
||||
this.onmessage = onMessageLoader;
|
|
@ -0,0 +1,661 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
inkscape:export-ydpi="240.00000"
|
||||
inkscape:export-xdpi="240.00000"
|
||||
inkscape:export-filename="/home/jimmac/gfx/novell/pdes/trunk/docs/BIGmime-text.png"
|
||||
sodipodi:docname="bookmark.svg"
|
||||
inkscape:version="0.48.1 r9760"
|
||||
sodipodi:version="0.32"
|
||||
id="svg249"
|
||||
height="48.000000px"
|
||||
width="48.000000px"
|
||||
inkscape:output_extension="org.inkscape.output.svg.inkscape"
|
||||
version="1.1">
|
||||
<defs
|
||||
id="defs3">
|
||||
<inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="0 : 24 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_z="48 : 24 : 1"
|
||||
inkscape:persp3d-origin="24 : 16 : 1"
|
||||
id="perspective100" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient5060"
|
||||
id="radialGradient5031"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(-2.774389,0,0,1.969706,112.7623,-872.8854)"
|
||||
cx="605.71429"
|
||||
cy="486.64789"
|
||||
fx="605.71429"
|
||||
fy="486.64789"
|
||||
r="117.14286" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient5060">
|
||||
<stop
|
||||
style="stop-color:black;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop5062" />
|
||||
<stop
|
||||
style="stop-color:black;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop5064" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient5060"
|
||||
id="radialGradient5029"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(2.774389,0,0,1.969706,-1891.633,-872.8854)"
|
||||
cx="605.71429"
|
||||
cy="486.64789"
|
||||
fx="605.71429"
|
||||
fy="486.64789"
|
||||
r="117.14286" />
|
||||
<linearGradient
|
||||
id="linearGradient5048">
|
||||
<stop
|
||||
style="stop-color:black;stop-opacity:0;"
|
||||
offset="0"
|
||||
id="stop5050" />
|
||||
<stop
|
||||
id="stop5056"
|
||||
offset="0.5"
|
||||
style="stop-color:black;stop-opacity:1;" />
|
||||
<stop
|
||||
style="stop-color:black;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop5052" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient5048"
|
||||
id="linearGradient5027"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(2.774389,0,0,1.969706,-1892.179,-872.8854)"
|
||||
x1="302.85715"
|
||||
y1="366.64789"
|
||||
x2="302.85715"
|
||||
y2="609.50507" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient2906">
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop2908" />
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop2910" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient2896">
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop2898" />
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop2900" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient2598">
|
||||
<stop
|
||||
style="stop-color:#859dbc;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop2600" />
|
||||
<stop
|
||||
style="stop-color:#547299;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop2602" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient2590">
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop2592" />
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop2594" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient5897">
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:0.0000000;"
|
||||
offset="0.0000000"
|
||||
id="stop5899" />
|
||||
<stop
|
||||
id="stop5905"
|
||||
offset="0.50000000"
|
||||
style="stop-color:#000000;stop-opacity:0.56701028;" />
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:0.0000000;"
|
||||
offset="1.0000000"
|
||||
id="stop5901" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient5866">
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop5868" />
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop5870" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient4404">
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop4406" />
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop4408" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient4542">
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop4544" />
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop4546" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient15662">
|
||||
<stop
|
||||
id="stop15664"
|
||||
offset="0.0000000"
|
||||
style="stop-color:#ffffff;stop-opacity:1.0000000;" />
|
||||
<stop
|
||||
id="stop15666"
|
||||
offset="1.0000000"
|
||||
style="stop-color:#f8f8f8;stop-opacity:1.0000000;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient269">
|
||||
<stop
|
||||
id="stop270"
|
||||
offset="0.0000000"
|
||||
style="stop-color:#a3a3a3;stop-opacity:1.0000000;" />
|
||||
<stop
|
||||
id="stop271"
|
||||
offset="1.0000000"
|
||||
style="stop-color:#4c4c4c;stop-opacity:1.0000000;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient259">
|
||||
<stop
|
||||
id="stop260"
|
||||
offset="0.0000000"
|
||||
style="stop-color:#fafafa;stop-opacity:1.0000000;" />
|
||||
<stop
|
||||
id="stop261"
|
||||
offset="1.0000000"
|
||||
style="stop-color:#bbbbbb;stop-opacity:1.0000000;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient12512">
|
||||
<stop
|
||||
id="stop12513"
|
||||
offset="0.0000000"
|
||||
style="stop-color:#ffffff;stop-opacity:1.0000000;" />
|
||||
<stop
|
||||
id="stop12517"
|
||||
offset="0.50000000"
|
||||
style="stop-color:#fff520;stop-opacity:0.89108908;" />
|
||||
<stop
|
||||
id="stop12514"
|
||||
offset="1.0000000"
|
||||
style="stop-color:#fff300;stop-opacity:0.0000000;" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
r="14.375000"
|
||||
fy="125.00000"
|
||||
fx="55.000000"
|
||||
cy="125.00000"
|
||||
cx="55.000000"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="radialGradient278"
|
||||
xlink:href="#linearGradient12512"
|
||||
inkscape:collect="always" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient269"
|
||||
id="radialGradient15656"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.968273,0.000000,0.000000,1.036374,3.250000,0.489522)"
|
||||
cx="8.8244190"
|
||||
cy="3.7561285"
|
||||
fx="8.8244190"
|
||||
fy="3.7561285"
|
||||
r="37.751713" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient259"
|
||||
id="radialGradient15658"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.960493,0.000000,0.000000,1.044769,-0.103553,-0.159183)"
|
||||
cx="33.966679"
|
||||
cy="35.736916"
|
||||
fx="33.966679"
|
||||
fy="35.736916"
|
||||
r="86.708450" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient15662"
|
||||
id="radialGradient15668"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.973033,0.000000,0.000000,1.034937,3.168754,0.555277)"
|
||||
cx="8.1435566"
|
||||
cy="7.2678967"
|
||||
fx="8.1435566"
|
||||
fy="7.2678967"
|
||||
r="38.158695" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4542"
|
||||
id="radialGradient4548"
|
||||
cx="24.306795"
|
||||
cy="42.07798"
|
||||
fx="24.306795"
|
||||
fy="42.07798"
|
||||
r="15.821514"
|
||||
gradientTransform="matrix(1.000000,0.000000,0.000000,0.284916,0.000000,30.08928)"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4404"
|
||||
id="linearGradient4410"
|
||||
x1="16.812500"
|
||||
y1="1.8750000"
|
||||
x2="16.812500"
|
||||
y2="4.7187500"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(-1.319549,0.000000,0.000000,1.362060,40.38853,-0.362057)" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient5866"
|
||||
id="linearGradient5872"
|
||||
x1="19.452349"
|
||||
y1="13.174174"
|
||||
x2="19.685436"
|
||||
y2="27.095339"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1.224255,0.000000,0.000000,1.282176,0.371569,0.264657)" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient5897"
|
||||
id="linearGradient5903"
|
||||
x1="19.000000"
|
||||
y1="9.7738247"
|
||||
x2="19.000000"
|
||||
y2="15.635596"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1.319549,0.000000,0.000000,2.133926,-4.476133,-14.64845)" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2590"
|
||||
id="linearGradient2596"
|
||||
x1="19.970377"
|
||||
y1="6.1167107"
|
||||
x2="19.970377"
|
||||
y2="2.53125"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1.319549,0.000000,0.000000,1.280356,-5.745298,0.249007)" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2598"
|
||||
id="linearGradient2604"
|
||||
x1="18.431311"
|
||||
y1="19.119474"
|
||||
x2="18.402472"
|
||||
y2="4.2702327"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1.319549,0.000000,0.000000,1.299013,-3.106200,-1.336165)" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2896"
|
||||
id="linearGradient2902"
|
||||
x1="14.584077"
|
||||
y1="1.6392649"
|
||||
x2="14.552828"
|
||||
y2="2.4912448"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1.000000,0.000000,0.000000,1.594214,0.000000,-0.790249)" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2906"
|
||||
id="linearGradient2912"
|
||||
x1="13.354311"
|
||||
y1="1.4866425"
|
||||
x2="14.075844"
|
||||
y2="2.4017651"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1.000000,0.000000,0.000000,1.184816,0.000000,-0.727880)" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
inkscape:window-y="158"
|
||||
inkscape:window-x="433"
|
||||
inkscape:window-height="690"
|
||||
inkscape:window-width="872"
|
||||
inkscape:document-units="px"
|
||||
inkscape:grid-bbox="true"
|
||||
showgrid="false"
|
||||
inkscape:current-layer="layer5"
|
||||
inkscape:cy="24"
|
||||
inkscape:cx="24"
|
||||
inkscape:zoom="9.8333333"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
borderopacity="0.25490196"
|
||||
bordercolor="#666666"
|
||||
pagecolor="#ffffff"
|
||||
id="base"
|
||||
inkscape:showpageshadow="false"
|
||||
showguides="true"
|
||||
inkscape:guide-bbox="true"
|
||||
inkscape:window-maximized="0" />
|
||||
<metadata
|
||||
id="metadata4">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title>New Bookmark</dc:title>
|
||||
<dc:subject>
|
||||
<rdf:Bag>
|
||||
<rdf:li>bookmark</rdf:li>
|
||||
<rdf:li>remember</rdf:li>
|
||||
<rdf:li>favorite</rdf:li>
|
||||
</rdf:Bag>
|
||||
</dc:subject>
|
||||
<cc:license
|
||||
rdf:resource="http://creativecommons.org/licenses/publicdomain/" />
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>Andreas Nilsson</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
<dc:source />
|
||||
<dc:contributor>
|
||||
<cc:Agent>
|
||||
<dc:title>Jakub Steiner</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:contributor>
|
||||
<dc:description>create bookmark action</dc:description>
|
||||
</cc:Work>
|
||||
<cc:License
|
||||
rdf:about="http://creativecommons.org/licenses/publicdomain/">
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#Reproduction" />
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#Distribution" />
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
|
||||
</cc:License>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer6"
|
||||
inkscape:label="Shadow">
|
||||
<g
|
||||
style="display:inline"
|
||||
id="g5022"
|
||||
transform="matrix(2.165152e-2,0,0,1.485743e-2,43.0076,42.68539)">
|
||||
<rect
|
||||
y="-150.69685"
|
||||
x="-1559.2523"
|
||||
height="478.35718"
|
||||
width="1339.6335"
|
||||
id="rect4173"
|
||||
style="opacity:0.40206185;color:black;fill:url(#linearGradient5027);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
|
||||
<path
|
||||
sodipodi:nodetypes="cccc"
|
||||
id="path5058"
|
||||
d="M -219.61876,-150.68038 C -219.61876,-150.68038 -219.61876,327.65041 -219.61876,327.65041 C -76.744594,328.55086 125.78146,220.48075 125.78138,88.454235 C 125.78138,-43.572302 -33.655436,-150.68036 -219.61876,-150.68038 z "
|
||||
style="opacity:0.40206185;color:black;fill:url(#radialGradient5029);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
|
||||
<path
|
||||
style="opacity:0.40206185;color:black;fill:url(#radialGradient5031);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
|
||||
d="M -1559.2523,-150.68038 C -1559.2523,-150.68038 -1559.2523,327.65041 -1559.2523,327.65041 C -1702.1265,328.55086 -1904.6525,220.48075 -1904.6525,88.454235 C -1904.6525,-43.572302 -1745.2157,-150.68036 -1559.2523,-150.68038 z "
|
||||
id="path5018"
|
||||
sodipodi:nodetypes="cccc" />
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
style="display:inline"
|
||||
inkscape:groupmode="layer"
|
||||
inkscape:label="Base"
|
||||
id="layer1">
|
||||
<rect
|
||||
style="color:#000000;fill:url(#radialGradient15658);fill-opacity:1.0000000;fill-rule:nonzero;stroke:url(#radialGradient15656);stroke-width:0.99999982;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:block;overflow:visible"
|
||||
id="rect15391"
|
||||
width="34.875000"
|
||||
height="41.063431"
|
||||
x="6.5000000"
|
||||
y="3.5000000"
|
||||
ry="1.1490481"
|
||||
rx="1.1490486" />
|
||||
<rect
|
||||
style="color:#000000;fill:none;fill-opacity:1.0000000;fill-rule:nonzero;stroke:url(#radialGradient15668);stroke-width:0.99999958;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:block;overflow:visible"
|
||||
id="rect15660"
|
||||
width="32.937012"
|
||||
height="39.028210"
|
||||
x="7.5024552"
|
||||
y="4.5010486"
|
||||
ry="0.14904849"
|
||||
rx="0.14904852" />
|
||||
<path
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:0.98855311;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:0.017543854"
|
||||
d="M 11.505723,5.4942766 L 11.505723,43.400869"
|
||||
id="path15672"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:0.20467831"
|
||||
d="M 12.500000,5.0205154 L 12.500000,43.038228"
|
||||
id="path15674"
|
||||
sodipodi:nodetypes="cc" />
|
||||
</g>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer5"
|
||||
inkscape:label="Text"
|
||||
style="display:inline">
|
||||
<g
|
||||
id="g2188">
|
||||
<rect
|
||||
style="color:#000000;fill:#9b9b9b;fill-opacity:0.54970759;fill-rule:nonzero;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:0.081871338;visibility:visible;display:block;overflow:visible"
|
||||
id="rect15686"
|
||||
width="20.000006"
|
||||
height="1.0000000"
|
||||
x="15.999994"
|
||||
y="9.0000000"
|
||||
rx="0.13778631"
|
||||
ry="0.065390877" />
|
||||
<rect
|
||||
style="color:#000000;fill:#9b9b9b;fill-opacity:0.54970759;fill-rule:nonzero;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:0.081871338;visibility:visible;display:block;overflow:visible"
|
||||
id="rect15688"
|
||||
width="20.000006"
|
||||
height="1.0000000"
|
||||
x="15.999994"
|
||||
y="11.000000"
|
||||
rx="0.13778631"
|
||||
ry="0.065390877" />
|
||||
<rect
|
||||
style="color:#000000;fill:#9b9b9b;fill-opacity:0.54970759;fill-rule:nonzero;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:0.081871338;visibility:visible;display:block;overflow:visible"
|
||||
id="rect15690"
|
||||
width="20.000006"
|
||||
height="1.0000000"
|
||||
x="15.999994"
|
||||
y="13.000000"
|
||||
rx="0.13778631"
|
||||
ry="0.065390877" />
|
||||
<rect
|
||||
style="color:#000000;fill:#9b9b9b;fill-opacity:0.54970759;fill-rule:nonzero;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:0.081871338;visibility:visible;display:block;overflow:visible"
|
||||
id="rect15692"
|
||||
width="20.000006"
|
||||
height="1.0000000"
|
||||
x="15.999994"
|
||||
y="15.000000"
|
||||
rx="0.13778631"
|
||||
ry="0.065390877" />
|
||||
<rect
|
||||
style="color:#000000;fill:#9b9b9b;fill-opacity:0.54970759;fill-rule:nonzero;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:0.081871338;visibility:visible;display:block;overflow:visible"
|
||||
id="rect15694"
|
||||
width="20.000006"
|
||||
height="1.0000000"
|
||||
x="15.999994"
|
||||
y="17.000000"
|
||||
rx="0.13778631"
|
||||
ry="0.065390877" />
|
||||
<rect
|
||||
style="color:#000000;fill:#9b9b9b;fill-opacity:0.54970759;fill-rule:nonzero;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:0.081871338;visibility:visible;display:block;overflow:visible"
|
||||
id="rect15696"
|
||||
width="20.000006"
|
||||
height="1.0000000"
|
||||
x="15.999994"
|
||||
y="19.000000"
|
||||
rx="0.13778631"
|
||||
ry="0.065390877" />
|
||||
<rect
|
||||
style="color:#000000;fill:#9b9b9b;fill-opacity:0.54970759;fill-rule:nonzero;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:0.081871338;visibility:visible;display:block;overflow:visible"
|
||||
id="rect15698"
|
||||
width="20.000006"
|
||||
height="1.0000000"
|
||||
x="15.999994"
|
||||
y="21.000000"
|
||||
rx="0.13778631"
|
||||
ry="0.065390877" />
|
||||
<rect
|
||||
style="color:#000000;fill:#9b9b9b;fill-opacity:0.54970759;fill-rule:nonzero;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:0.081871338;visibility:visible;display:block;overflow:visible"
|
||||
id="rect15700"
|
||||
width="20.000006"
|
||||
height="1.0000000"
|
||||
x="15.999994"
|
||||
y="23.000000"
|
||||
rx="0.13778631"
|
||||
ry="0.065390877" />
|
||||
<rect
|
||||
style="color:#000000;fill:#9b9b9b;fill-opacity:0.54970759;fill-rule:nonzero;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:0.081871338;visibility:visible;display:block;overflow:visible"
|
||||
id="rect15732"
|
||||
width="9.0000057"
|
||||
height="1.0000000"
|
||||
x="15.999986"
|
||||
y="25.000000"
|
||||
rx="0.062003858"
|
||||
ry="0.065390877" />
|
||||
<rect
|
||||
style="color:#000000;fill:#9b9b9b;fill-opacity:0.54970759;fill-rule:nonzero;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:0.081871338;visibility:visible;display:block;overflow:visible"
|
||||
id="rect15736"
|
||||
width="20.000006"
|
||||
height="1.0000000"
|
||||
x="15.999986"
|
||||
y="29.000000"
|
||||
rx="0.13778631"
|
||||
ry="0.065390877" />
|
||||
<rect
|
||||
style="color:#000000;fill:#9b9b9b;fill-opacity:0.54970759;fill-rule:nonzero;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:0.081871338;visibility:visible;display:block;overflow:visible"
|
||||
id="rect15738"
|
||||
width="20.000006"
|
||||
height="1.0000000"
|
||||
x="15.999986"
|
||||
y="31.000000"
|
||||
rx="0.13778631"
|
||||
ry="0.065390877" />
|
||||
<rect
|
||||
style="color:#000000;fill:#9b9b9b;fill-opacity:0.54970759;fill-rule:nonzero;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:0.081871338;visibility:visible;display:block;overflow:visible"
|
||||
id="rect15740"
|
||||
width="20.000006"
|
||||
height="1.0000000"
|
||||
x="15.999986"
|
||||
y="33.000000"
|
||||
rx="0.13778631"
|
||||
ry="0.065390877" />
|
||||
<rect
|
||||
style="color:#000000;fill:#9b9b9b;fill-opacity:0.54970759;fill-rule:nonzero;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:0.081871338;visibility:visible;display:block;overflow:visible"
|
||||
id="rect15742"
|
||||
width="20.000006"
|
||||
height="1.0000000"
|
||||
x="15.999986"
|
||||
y="35.000000"
|
||||
rx="0.13778631"
|
||||
ry="0.065390877" />
|
||||
<rect
|
||||
style="color:#000000;fill:#9b9b9b;fill-opacity:0.54970759;fill-rule:nonzero;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:0.081871338;visibility:visible;display:block;overflow:visible"
|
||||
id="rect15744"
|
||||
width="14.000014"
|
||||
height="1.0000000"
|
||||
x="15.999986"
|
||||
y="37.000000"
|
||||
rx="0.096450485"
|
||||
ry="0.065390877" />
|
||||
</g>
|
||||
<path
|
||||
style="opacity:0.28021976;fill:url(#linearGradient5872);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.25pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 28.245858,31.324906 L 21.147869,27.133701 L 14.30757,30.8838 L 13.761859,3.9475667 L 28.549598,3.9475667 L 28.245858,31.324906 z "
|
||||
id="path5138"
|
||||
sodipodi:nodetypes="cccccc" />
|
||||
<path
|
||||
style="fill:url(#linearGradient2604);fill-opacity:1;fill-rule:evenodd;stroke:#364878;stroke-width:0.99999988;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;display:inline"
|
||||
d="M 12.427339,3.5180202 C 12.427339,3.5180202 12.240033,0.60520607 15.107867,0.54270607 L 25.119343,0.50728624 C 26.277287,0.50728624 26.581888,1.1910178 26.581888,2.1095589 L 26.581888,29.729916 L 20.545426,24.533862 L 14.674346,29.729916 L 14.591655,3.519629 L 12.427339,3.5180202 z "
|
||||
id="path2204"
|
||||
sodipodi:nodetypes="ccccccccc" />
|
||||
<path
|
||||
style="opacity:0.4450549;fill:url(#linearGradient4410);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.25pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 13.030252,3.0117919 C 13.011046,2.225362 13.312918,1.0801307 15.375418,1.0176307 L 25.027906,1 C 25.640922,1 26.090152,1.1674319 26.090152,1.7994802 L 26.060994,10.491851 L 15.317102,10.491851 L 15.192102,2.9993251 C 15.192102,2.9993251 13.030252,3.0117919 13.030252,3.0117919 z "
|
||||
id="path3668"
|
||||
sodipodi:nodetypes="cccccccs" />
|
||||
<rect
|
||||
style="opacity:0.28021976;fill:url(#linearGradient5903);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
id="rect5895"
|
||||
width="10.556392"
|
||||
height="12.803556"
|
||||
x="15.317101"
|
||||
y="6.6907959"
|
||||
rx="0.062003858"
|
||||
ry="0.065390877" />
|
||||
<path
|
||||
style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient2596);stroke-width:1.00000012;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.19125683;display:inline"
|
||||
d="M 24.476832,2.2095507 L 25.575535,3.113139 L 25.547445,27.511911 L 20.497463,23.203758 L 15.704084,27.415203 L 15.699081,2.7495618 L 24.476832,2.2095507 z "
|
||||
id="path5969"
|
||||
sodipodi:nodetypes="ccccccc" />
|
||||
<path
|
||||
style="opacity:0.48295456;color:#000000;fill:url(#linearGradient2912);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.10533953;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
|
||||
d="M 15.158602,3.9384083 L 15.114407,1.0335178 C 12.983906,1.0335178 12.993087,2.9680775 12.993087,3.9384083 L 15.158602,3.9384083 z "
|
||||
id="path2894"
|
||||
sodipodi:nodetypes="cccc" />
|
||||
<path
|
||||
sodipodi:nodetypes="cccc"
|
||||
id="path2904"
|
||||
d="M 15.158602,3.9384086 L 15.114407,1.8247593 C 12.81631,1.8426926 12.993087,3.9384086 12.993087,3.9384086 L 15.158602,3.9384086 z "
|
||||
style="opacity:0.35795455;color:#000000;fill:url(#linearGradient2902);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.10533953;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 28 KiB |
|
@ -0,0 +1,532 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
sodipodi:docname="document-print.svg"
|
||||
sodipodi:docbase="/home/jimmac/src/cvs/tango-icon-theme/scalable/actions"
|
||||
inkscape:version="0.46"
|
||||
sodipodi:version="0.32"
|
||||
id="svg2994"
|
||||
height="48px"
|
||||
width="48px"
|
||||
inkscape:output_extension="org.inkscape.output.svg.inkscape">
|
||||
<defs
|
||||
id="defs3">
|
||||
<inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="0 : 24 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_z="48 : 24 : 1"
|
||||
inkscape:persp3d-origin="24 : 16 : 1"
|
||||
id="perspective84" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient5060"
|
||||
id="radialGradient5031"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(-2.774389,0,0,1.969706,112.7623,-872.8854)"
|
||||
cx="605.71429"
|
||||
cy="486.64789"
|
||||
fx="605.71429"
|
||||
fy="486.64789"
|
||||
r="117.14286" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient5060">
|
||||
<stop
|
||||
style="stop-color:black;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop5062" />
|
||||
<stop
|
||||
style="stop-color:black;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop5064" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient5060"
|
||||
id="radialGradient5029"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(2.774389,0,0,1.969706,-1891.633,-872.8854)"
|
||||
cx="605.71429"
|
||||
cy="486.64789"
|
||||
fx="605.71429"
|
||||
fy="486.64789"
|
||||
r="117.14286" />
|
||||
<linearGradient
|
||||
id="linearGradient5048">
|
||||
<stop
|
||||
style="stop-color:black;stop-opacity:0;"
|
||||
offset="0"
|
||||
id="stop5050" />
|
||||
<stop
|
||||
id="stop5056"
|
||||
offset="0.5"
|
||||
style="stop-color:black;stop-opacity:1;" />
|
||||
<stop
|
||||
style="stop-color:black;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop5052" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient5048"
|
||||
id="linearGradient5027"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(2.774389,0,0,1.969706,-1892.179,-872.8854)"
|
||||
x1="302.85715"
|
||||
y1="366.64789"
|
||||
x2="302.85715"
|
||||
y2="609.50507" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient7612">
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop7614" />
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop7616" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient7612"
|
||||
id="radialGradient7618"
|
||||
cx="24.000000"
|
||||
cy="41.875000"
|
||||
fx="24.000000"
|
||||
fy="41.875000"
|
||||
r="19.125000"
|
||||
gradientTransform="matrix(1.000000,0.000000,0.000000,0.333333,0.000000,27.91667)"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
id="linearGradient4762">
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:0.12371134;"
|
||||
offset="0.0000000"
|
||||
id="stop4764" />
|
||||
<stop
|
||||
id="stop4768"
|
||||
offset="0.10344828"
|
||||
style="stop-color:#ffffff;stop-opacity:1.0000000;" />
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop4766" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient4741">
|
||||
<stop
|
||||
id="stop4743"
|
||||
offset="0.0000000"
|
||||
style="stop-color:#dcdcda;stop-opacity:1.0000000;" />
|
||||
<stop
|
||||
id="stop4745"
|
||||
offset="1.0000000"
|
||||
style="stop-color:#bab9b7;stop-opacity:1.0000000;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient4733">
|
||||
<stop
|
||||
id="stop4735"
|
||||
offset="0.0000000"
|
||||
style="stop-color:#000000;stop-opacity:0.23711340;" />
|
||||
<stop
|
||||
id="stop4737"
|
||||
offset="1"
|
||||
style="stop-color:#000000;stop-opacity:0;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient4698">
|
||||
<stop
|
||||
id="stop4700"
|
||||
offset="0.0000000"
|
||||
style="stop-color:#fffffd;stop-opacity:1.0000000;" />
|
||||
<stop
|
||||
style="stop-color:#bbbbb9;stop-opacity:1.0000000;"
|
||||
offset="0.50000000"
|
||||
id="stop4706" />
|
||||
<stop
|
||||
id="stop4702"
|
||||
offset="1.0000000"
|
||||
style="stop-color:#000000;stop-opacity:1.0000000;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient4688">
|
||||
<stop
|
||||
id="stop4690"
|
||||
offset="0.0000000"
|
||||
style="stop-color:#666666;stop-opacity:1.0000000;" />
|
||||
<stop
|
||||
id="stop4692"
|
||||
offset="1"
|
||||
style="stop-color:#000000;stop-opacity:0;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient4680"
|
||||
inkscape:collect="always">
|
||||
<stop
|
||||
id="stop4682"
|
||||
offset="0"
|
||||
style="stop-color:#f7f6f5;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop4684"
|
||||
offset="1"
|
||||
style="stop-color:#f7f6f5;stop-opacity:0;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient4668">
|
||||
<stop
|
||||
id="stop4670"
|
||||
offset="0"
|
||||
style="stop-color:#8e8d87;stop-opacity:1;" />
|
||||
<stop
|
||||
style="stop-color:#cbc9c1;stop-opacity:1.0000000;"
|
||||
offset="0.27586207"
|
||||
id="stop4676" />
|
||||
<stop
|
||||
id="stop4672"
|
||||
offset="1.0000000"
|
||||
style="stop-color:#8e8d87;stop-opacity:1.0000000;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient259">
|
||||
<stop
|
||||
id="stop260"
|
||||
offset="0.0000000"
|
||||
style="stop-color:#e0e0e0;stop-opacity:1.0000000;" />
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1.0000000;"
|
||||
offset="0.40546969"
|
||||
id="stop4886" />
|
||||
<stop
|
||||
style="stop-color:#cdcdcd;stop-opacity:1.0000000;"
|
||||
offset="0.53448278"
|
||||
id="stop4884" />
|
||||
<stop
|
||||
id="stop261"
|
||||
offset="1.0000000"
|
||||
style="stop-color:#494949;stop-opacity:1.0000000;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient15662">
|
||||
<stop
|
||||
id="stop15664"
|
||||
offset="0.0000000"
|
||||
style="stop-color:#ffffff;stop-opacity:0.0000000;" />
|
||||
<stop
|
||||
id="stop15666"
|
||||
offset="1.0000000"
|
||||
style="stop-color:#f8f8f8;stop-opacity:1.0000000;" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
r="2.1227016"
|
||||
fy="26.925594"
|
||||
fx="9.1295490"
|
||||
cy="26.925594"
|
||||
cx="9.1295490"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="radialGradient1433"
|
||||
xlink:href="#linearGradient4698"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
y2="72.064316"
|
||||
x2="9.9128132"
|
||||
y1="57.227650"
|
||||
x1="9.8698082"
|
||||
gradientTransform="matrix(2.772086,0.000000,0.000000,0.360739,0.618718,2.883883)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient1447"
|
||||
xlink:href="#linearGradient4733"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
y2="54.136139"
|
||||
x2="10.338233"
|
||||
y1="64.652260"
|
||||
x1="10.338233"
|
||||
gradientTransform="matrix(2.369844,0.000000,0.000000,0.421969,0.000000,2.000000)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient1451"
|
||||
xlink:href="#linearGradient4680"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
y2="62.282467"
|
||||
x2="9.7052784"
|
||||
y1="70.724976"
|
||||
x1="9.7316532"
|
||||
gradientTransform="matrix(2.369844,0.000000,0.000000,0.421969,0.000000,2.000000)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient1453"
|
||||
xlink:href="#linearGradient4688"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
y2="19.337463"
|
||||
x2="20.717800"
|
||||
y1="25.140253"
|
||||
x1="20.771229"
|
||||
gradientTransform="matrix(1.198769,0,0,0.853565,-0.143086,2.034513)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient1456"
|
||||
xlink:href="#linearGradient15662"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
y2="25.247311"
|
||||
x2="24.789707"
|
||||
y1="3.6785457"
|
||||
x1="25.056711"
|
||||
gradientTransform="matrix(0.944939,0,0,1.076147,6.844577e-2,4.093177)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient1459"
|
||||
xlink:href="#linearGradient259"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
y2="58.831264"
|
||||
x2="15.487823"
|
||||
y1="32.539238"
|
||||
x1="15.387969"
|
||||
gradientTransform="matrix(1.490161,0,0,0.668741,8.895132e-2,2)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient1464"
|
||||
xlink:href="#linearGradient4762"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
y2="88.294930"
|
||||
x2="18.972126"
|
||||
y1="88.294930"
|
||||
x1="1.8456430"
|
||||
gradientTransform="matrix(2.291824,0,0,0.434269,8.855179e-2,2)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient1468"
|
||||
xlink:href="#linearGradient4741"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
y2="88.294933"
|
||||
x2="18.972126"
|
||||
y1="88.294933"
|
||||
x1="1.8456431"
|
||||
gradientTransform="matrix(2.30272,0,0,0.437918,0,0.584034)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient1471"
|
||||
xlink:href="#linearGradient4668"
|
||||
inkscape:collect="always" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
inkscape:window-y="160"
|
||||
inkscape:window-x="331"
|
||||
inkscape:window-height="688"
|
||||
inkscape:window-width="872"
|
||||
inkscape:guide-bbox="true"
|
||||
showguides="true"
|
||||
inkscape:document-units="px"
|
||||
inkscape:grid-bbox="true"
|
||||
showgrid="false"
|
||||
inkscape:current-layer="layer1"
|
||||
inkscape:cy="-18.264187"
|
||||
inkscape:cx="-72.591911"
|
||||
inkscape:zoom="1"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
borderopacity="0.090196078"
|
||||
bordercolor="#666666"
|
||||
pagecolor="#ffffff"
|
||||
id="base"
|
||||
inkscape:showpageshadow="false"
|
||||
fill="#729fcf" />
|
||||
<metadata
|
||||
id="metadata4">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title>Print Document</dc:title>
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>Jakub Steiner</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
<cc:license
|
||||
rdf:resource="http://creativecommons.org/licenses/publicdomain/" />
|
||||
<dc:source>http://jimmac.musichall.cz</dc:source>
|
||||
<dc:subject>
|
||||
<rdf:Bag>
|
||||
<rdf:li>document</rdf:li>
|
||||
<rdf:li>lpr</rdf:li>
|
||||
<rdf:li>print</rdf:li>
|
||||
<rdf:li>local</rdf:li>
|
||||
<rdf:li>laser</rdf:li>
|
||||
<rdf:li>bubblejet</rdf:li>
|
||||
<rdf:li>inkjet</rdf:li>
|
||||
<rdf:li>print</rdf:li>
|
||||
<rdf:li>output</rdf:li>
|
||||
<rdf:li>cups</rdf:li>
|
||||
<rdf:li>lpd</rdf:li>
|
||||
</rdf:Bag>
|
||||
</dc:subject>
|
||||
</cc:Work>
|
||||
<cc:License
|
||||
rdf:about="http://creativecommons.org/licenses/publicdomain/">
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#Reproduction" />
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#Distribution" />
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
|
||||
</cc:License>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
inkscape:label="Layer 1"
|
||||
id="layer1">
|
||||
<g
|
||||
style="display:inline"
|
||||
id="g5022"
|
||||
transform="matrix(2.411405e-2,0,0,1.929202e-2,45.48953,39.75228)">
|
||||
<rect
|
||||
y="-150.69685"
|
||||
x="-1559.2523"
|
||||
height="478.35718"
|
||||
width="1339.6335"
|
||||
id="rect4173"
|
||||
style="opacity:0.40206185;color:black;fill:url(#linearGradient5027);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
|
||||
<path
|
||||
sodipodi:nodetypes="cccc"
|
||||
id="path5058"
|
||||
d="M -219.61876,-150.68038 C -219.61876,-150.68038 -219.61876,327.65041 -219.61876,327.65041 C -76.744594,328.55086 125.78146,220.48075 125.78138,88.454235 C 125.78138,-43.572302 -33.655436,-150.68036 -219.61876,-150.68038 z "
|
||||
style="opacity:0.40206185;color:black;fill:url(#radialGradient5029);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
|
||||
<path
|
||||
style="opacity:0.40206185;color:black;fill:url(#radialGradient5031);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
|
||||
d="M -1559.2523,-150.68038 C -1559.2523,-150.68038 -1559.2523,327.65041 -1559.2523,327.65041 C -1702.1265,328.55086 -1904.6525,220.48075 -1904.6525,88.454235 C -1904.6525,-43.572302 -1745.2157,-150.68036 -1559.2523,-150.68038 z "
|
||||
id="path5018"
|
||||
sodipodi:nodetypes="cccc" />
|
||||
</g>
|
||||
<rect
|
||||
ry="1.7115477"
|
||||
rx="1.7115483"
|
||||
y="36.004189"
|
||||
x="4.75"
|
||||
height="6.4915943"
|
||||
width="38.4375"
|
||||
id="rect4652"
|
||||
style="fill:url(#linearGradient1471);fill-opacity:1;stroke:#595959;stroke-width:0.99999982;stroke-miterlimit:4;stroke-opacity:1" />
|
||||
<path
|
||||
sodipodi:nodetypes="cssssssssssss"
|
||||
id="rect4609"
|
||||
d="M 7.1308961,21.5 L 40.870615,21.5 C 41.255661,21.5 41.747648,21.788155 42.051049,22.223919 C 42.354451,22.659684 43.787518,24.83394 44.109448,25.297964 C 44.431378,25.761987 44.502397,26.201852 44.502397,26.774049 L 44.502397,38.850951 C 44.502397,39.764524 43.770402,40.5 42.861152,40.5 L 5.1403596,40.5 C 4.2311094,40.5 3.4991138,39.764524 3.4991138,38.850951 L 3.4991138,26.774049 C 3.4991138,26.280031 3.6002798,25.571641 3.9455202,25.120718 C 4.3811666,24.551713 5.5498664,22.57277 5.8581276,22.153118 C 6.1663887,21.733467 6.7324461,21.5 7.1308961,21.5 z "
|
||||
style="color:#000000;fill:url(#linearGradient1468);fill-opacity:1;fill-rule:nonzero;stroke:#676767;stroke-width:1.00000036;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
|
||||
<path
|
||||
sodipodi:nodetypes="cssssssss"
|
||||
id="path4718"
|
||||
d="M 7.705278,21.975532 C 7.20729,21.975532 6.5669691,22.107308 6.3043987,22.511224 L 4.4657443,25.339651 C 4.169761,25.794966 4.4993705,26.868141 5.3900051,26.868141 L 42.678553,26.868141 C 43.883282,26.868141 43.8868,25.858073 43.602814,25.428039 L 41.851714,22.776389 C 41.534204,22.295589 41.418956,21.975532 40.625945,21.975532 L 7.705278,21.975532 z "
|
||||
style="fill:#fbfbfb;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<path
|
||||
style="color:#000000;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient1464);stroke-width:0.94696701;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
|
||||
d="M 7.6002951,22.445756 L 40.374658,22.445756 C 40.739745,22.445756 41.206233,22.718629 41.493909,23.131283 C 41.781585,23.543938 42.788049,25.160945 43.093293,25.60036 C 43.398536,26.039775 43.528159,26.456312 43.528159,26.998164 L 43.528159,38.279261 C 43.528159,39.144385 43.394653,39.528356 42.532529,39.528356 L 5.530506,39.528356 C 4.6683828,39.528356 4.472593,39.144385 4.472593,38.279261 L 4.472593,26.998164 C 4.472593,26.530345 4.6930819,25.859523 5.0204282,25.432514 C 5.4334949,24.893685 6.1012112,23.461633 6.393495,23.064237 C 6.6857789,22.666841 7.222497,22.445756 7.6002951,22.445756 z "
|
||||
id="path4750"
|
||||
sodipodi:nodetypes="cssssssssssss" />
|
||||
<path
|
||||
sodipodi:nodetypes="ccccccc"
|
||||
id="rect15391"
|
||||
d="M 11.68177,4.4977642 L 36.313839,4.4977642 C 36.964072,4.4977642 37.487546,5.007949 37.487546,5.6416762 L 37.487546,24.348117 L 10.508063,24.348117 L 10.508063,5.6416762 C 10.508063,5.007949 11.031536,4.4977642 11.68177,4.4977642 z "
|
||||
style="color:#000000;fill:url(#linearGradient1459);fill-opacity:1;fill-rule:nonzero;stroke:#898989;stroke-width:1.00000012;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:block;overflow:visible" />
|
||||
<rect
|
||||
style="color:#000000;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient1456);stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:block;overflow:visible"
|
||||
id="rect15660"
|
||||
width="25.000576"
|
||||
height="18.836374"
|
||||
x="11.498513"
|
||||
y="5.4992466"
|
||||
ry="0.17677675"
|
||||
rx="0.17677672" />
|
||||
<rect
|
||||
ry="1.7115483"
|
||||
rx="1.7115483"
|
||||
y="27.375000"
|
||||
x="6.8750000"
|
||||
height="5.1875000"
|
||||
width="33.750000"
|
||||
id="rect4678"
|
||||
style="fill:url(#linearGradient1451);fill-opacity:1.0000000;stroke:url(#linearGradient1453);stroke-width:1.0000000;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
|
||||
<path
|
||||
transform="translate(0.000000,2.000000)"
|
||||
d="M 10.871767 27.626486 A 1.2816310 1.2816310 0 1 1 8.3085046,27.626486 A 1.2816310 1.2816310 0 1 1 10.871767 27.626486 z"
|
||||
sodipodi:ry="1.2816310"
|
||||
sodipodi:rx="1.2816310"
|
||||
sodipodi:cy="27.626486"
|
||||
sodipodi:cx="9.5901356"
|
||||
id="path4696"
|
||||
style="fill:url(#radialGradient1433);fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
|
||||
sodipodi:type="arc" />
|
||||
<path
|
||||
sodipodi:nodetypes="csscssssc"
|
||||
id="path4731"
|
||||
d="M 11.743718,25.416053 L 37.306218,25.478553 C 37.993716,25.480234 38.294038,25.107558 38.243718,24.478553 L 38.118718,22.916053 L 39.984835,22.916053 C 40.797335,22.916053 40.975035,23.108616 41.172335,23.478553 L 41.672335,24.416053 C 42.199130,25.403793 43.483508,26.390165 42.170495,26.390165 C 37.667784,26.390165 13.993718,26.041053 11.743718,25.416053 z "
|
||||
style="fill:url(#linearGradient1447);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;opacity:0.36571429" />
|
||||
<path
|
||||
style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="M 42.9375,26.5 L 4.8125,26.5"
|
||||
id="path4760"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<g
|
||||
transform="translate(0.000000,2.000000)"
|
||||
style="opacity:0.43575415"
|
||||
id="g4849">
|
||||
<rect
|
||||
style="color:#000000;fill:#000000;fill-opacity:0.29239765;fill-rule:nonzero;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible"
|
||||
id="rect4831"
|
||||
width="19.000000"
|
||||
height="1.0000000"
|
||||
x="14.000000"
|
||||
y="5.0000000" />
|
||||
<rect
|
||||
y="7.0000000"
|
||||
x="14.000000"
|
||||
height="1.0000000"
|
||||
width="19.000000"
|
||||
id="rect4833"
|
||||
style="color:#000000;fill:#000000;fill-opacity:0.29239765;fill-rule:nonzero;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible" />
|
||||
<rect
|
||||
style="color:#000000;fill:#000000;fill-opacity:0.29239765;fill-rule:nonzero;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible"
|
||||
id="rect4835"
|
||||
width="19.000000"
|
||||
height="1.0000000"
|
||||
x="14.000000"
|
||||
y="9.0000000" />
|
||||
<rect
|
||||
y="11.000000"
|
||||
x="14.000000"
|
||||
height="1.0000000"
|
||||
width="19.000000"
|
||||
id="rect4837"
|
||||
style="color:#000000;fill:#000000;fill-opacity:0.29239765;fill-rule:nonzero;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible" />
|
||||
<rect
|
||||
style="color:#000000;fill:#000000;fill-opacity:0.29239765;fill-rule:nonzero;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible"
|
||||
id="rect4839"
|
||||
width="11.000000"
|
||||
height="1.0000000"
|
||||
x="14.000000"
|
||||
y="13.000000" />
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer2"
|
||||
inkscape:label="arrow">
|
||||
<path
|
||||
sodipodi:nodetypes="cccccccc"
|
||||
id="path8643"
|
||||
d="M 21.02159,20.989431 L 27.989391,20.989431 L 27.989391,16.064984 L 31,16.064984 L 24.553756,8 L 17.435622,15.986875 L 21.023684,15.986875 L 21.02159,20.989431 z "
|
||||
style="opacity:1;color:#000000;fill:#a7a7a7;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.99999958;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 23 KiB |
|
@ -0,0 +1,619 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
sodipodi:docname="document-save.svg"
|
||||
sodipodi:docbase="/home/jimmac/src/cvs/tango-icon-theme/scalable/actions"
|
||||
inkscape:version="0.46"
|
||||
sodipodi:version="0.32"
|
||||
id="svg2913"
|
||||
height="48px"
|
||||
width="48px"
|
||||
inkscape:output_extension="org.inkscape.output.svg.inkscape">
|
||||
<defs
|
||||
id="defs3">
|
||||
<inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="0 : 24 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_z="48 : 24 : 1"
|
||||
inkscape:persp3d-origin="24 : 16 : 1"
|
||||
id="perspective104" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient5060"
|
||||
id="radialGradient5031"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(-2.774389,0,0,1.969706,112.7623,-872.8854)"
|
||||
cx="605.71429"
|
||||
cy="486.64789"
|
||||
fx="605.71429"
|
||||
fy="486.64789"
|
||||
r="117.14286" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient5060">
|
||||
<stop
|
||||
style="stop-color:black;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop5062" />
|
||||
<stop
|
||||
style="stop-color:black;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop5064" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient5060"
|
||||
id="radialGradient5029"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(2.774389,0,0,1.969706,-1891.633,-872.8854)"
|
||||
cx="605.71429"
|
||||
cy="486.64789"
|
||||
fx="605.71429"
|
||||
fy="486.64789"
|
||||
r="117.14286" />
|
||||
<linearGradient
|
||||
id="linearGradient5048">
|
||||
<stop
|
||||
style="stop-color:black;stop-opacity:0;"
|
||||
offset="0"
|
||||
id="stop5050" />
|
||||
<stop
|
||||
id="stop5056"
|
||||
offset="0.5"
|
||||
style="stop-color:black;stop-opacity:1;" />
|
||||
<stop
|
||||
style="stop-color:black;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop5052" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient5048"
|
||||
id="linearGradient5027"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(2.774389,0,0,1.969706,-1892.179,-872.8854)"
|
||||
x1="302.85715"
|
||||
y1="366.64789"
|
||||
x2="302.85715"
|
||||
y2="609.50507" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient6925">
|
||||
<stop
|
||||
style="stop-color:#204a87;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop6927" />
|
||||
<stop
|
||||
style="stop-color:#204a87;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop6929" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient6901">
|
||||
<stop
|
||||
style="stop-color:#3465a4;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop6903" />
|
||||
<stop
|
||||
style="stop-color:#3465a4;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop6905" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient4991">
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop4993" />
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop4995" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4991"
|
||||
id="radialGradient4997"
|
||||
cx="23.447077"
|
||||
cy="6.4576745"
|
||||
fx="23.447077"
|
||||
fy="6.4576745"
|
||||
r="19.0625"
|
||||
gradientTransform="matrix(-1.314471,-1.006312e-2,-1.022964e-2,1.336221,46.22108,-4.909887)"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
id="linearGradient2187"
|
||||
inkscape:collect="always">
|
||||
<stop
|
||||
id="stop2189"
|
||||
offset="0"
|
||||
style="stop-color:#ffffff;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop2191"
|
||||
offset="1"
|
||||
style="stop-color:#ffffff;stop-opacity:0;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2187"
|
||||
id="linearGradient1764"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.914114,1.412791e-16,-1.412791e-16,0.914114,-3.868698,-2.706902)"
|
||||
x1="33.059906"
|
||||
y1="27.394117"
|
||||
x2="12.624337"
|
||||
y2="12.583769" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient8662">
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop8664" />
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop8666" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient8662"
|
||||
id="radialGradient8668"
|
||||
cx="24.837126"
|
||||
cy="36.421127"
|
||||
fx="24.837126"
|
||||
fy="36.421127"
|
||||
r="15.644737"
|
||||
gradientTransform="matrix(1.000000,-7.816467e-32,-1.132409e-32,0.536723,-5.897962e-14,16.87306)"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
id="linearGradient2555">
|
||||
<stop
|
||||
id="stop2557"
|
||||
offset="0"
|
||||
style="stop-color:#ffffff;stop-opacity:1;" />
|
||||
<stop
|
||||
style="stop-color:#e6e6e6;stop-opacity:1.0000000;"
|
||||
offset="0.50000000"
|
||||
id="stop2561" />
|
||||
<stop
|
||||
id="stop2563"
|
||||
offset="0.75000000"
|
||||
style="stop-color:#ffffff;stop-opacity:1.0000000;" />
|
||||
<stop
|
||||
style="stop-color:#e1e1e1;stop-opacity:1.0000000;"
|
||||
offset="0.84166664"
|
||||
id="stop2565" />
|
||||
<stop
|
||||
id="stop2559"
|
||||
offset="1.0000000"
|
||||
style="stop-color:#ffffff;stop-opacity:1.0000000;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient4274">
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:0.25490198;"
|
||||
offset="0.0000000"
|
||||
id="stop4276" />
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1.0000000;"
|
||||
offset="1.0000000"
|
||||
id="stop4278" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient4264"
|
||||
inkscape:collect="always">
|
||||
<stop
|
||||
id="stop4266"
|
||||
offset="0"
|
||||
style="stop-color:#000000;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop4268"
|
||||
offset="1"
|
||||
style="stop-color:#000000;stop-opacity:0;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient4254"
|
||||
inkscape:collect="always">
|
||||
<stop
|
||||
id="stop4256"
|
||||
offset="0"
|
||||
style="stop-color:#ffffff;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop4258"
|
||||
offset="1"
|
||||
style="stop-color:#ffffff;stop-opacity:0;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient4244">
|
||||
<stop
|
||||
id="stop4246"
|
||||
offset="0.0000000"
|
||||
style="stop-color:#e4e4e4;stop-opacity:1.0000000;" />
|
||||
<stop
|
||||
id="stop4248"
|
||||
offset="1.0000000"
|
||||
style="stop-color:#d3d3d3;stop-opacity:1.0000000;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient4236"
|
||||
inkscape:collect="always">
|
||||
<stop
|
||||
id="stop4238"
|
||||
offset="0"
|
||||
style="stop-color:#eeeeee;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop4240"
|
||||
offset="1"
|
||||
style="stop-color:#eeeeee;stop-opacity:0;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient4228">
|
||||
<stop
|
||||
id="stop4230"
|
||||
offset="0.0000000"
|
||||
style="stop-color:#bbbbbb;stop-opacity:1.0000000;" />
|
||||
<stop
|
||||
id="stop4232"
|
||||
offset="1.0000000"
|
||||
style="stop-color:#9f9f9f;stop-opacity:1.0000000;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient4184">
|
||||
<stop
|
||||
id="stop4186"
|
||||
offset="0.0000000"
|
||||
style="stop-color:#838383;stop-opacity:1.0000000;" />
|
||||
<stop
|
||||
id="stop4188"
|
||||
offset="1.0000000"
|
||||
style="stop-color:#bbbbbb;stop-opacity:0.0000000;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
gradientTransform="translate(0.795493,3.799180)"
|
||||
y2="35.281250"
|
||||
x2="24.687500"
|
||||
y1="35.281250"
|
||||
x1="7.0625000"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient4209"
|
||||
xlink:href="#linearGradient4184"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
gradientUnits="userSpaceOnUse"
|
||||
y2="40.943935"
|
||||
x2="36.183067"
|
||||
y1="28.481176"
|
||||
x1="7.6046205"
|
||||
id="linearGradient4234"
|
||||
xlink:href="#linearGradient4228"
|
||||
inkscape:collect="always"
|
||||
gradientTransform="translate(0.000000,5.125000)" />
|
||||
<linearGradient
|
||||
gradientUnits="userSpaceOnUse"
|
||||
y2="33.758667"
|
||||
x2="12.221823"
|
||||
y1="37.205811"
|
||||
x1="12.277412"
|
||||
id="linearGradient4242"
|
||||
xlink:href="#linearGradient4236"
|
||||
inkscape:collect="always"
|
||||
gradientTransform="translate(0.000000,5.125000)" />
|
||||
<radialGradient
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1.286242,0.781698,-0.710782,1.169552,-2.354348,0.248140)"
|
||||
r="20.935817"
|
||||
fy="2.9585190"
|
||||
fx="15.571491"
|
||||
cy="2.9585190"
|
||||
cx="15.571491"
|
||||
id="radialGradient4250"
|
||||
xlink:href="#linearGradient4244"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
gradientUnits="userSpaceOnUse"
|
||||
y2="47.620636"
|
||||
x2="44.096100"
|
||||
y1="4.4331360"
|
||||
x1="12.378357"
|
||||
id="linearGradient4260"
|
||||
xlink:href="#linearGradient4254"
|
||||
inkscape:collect="always"
|
||||
gradientTransform="translate(0.000000,5.125000)" />
|
||||
<radialGradient
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1.000000,0.000000,0.000000,0.651032,-2.885063e-16,9.455693)"
|
||||
r="23.555494"
|
||||
fy="27.096155"
|
||||
fx="23.201941"
|
||||
cy="27.096155"
|
||||
cx="23.201941"
|
||||
id="radialGradient4270"
|
||||
xlink:href="#linearGradient4264"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
gradientUnits="userSpaceOnUse"
|
||||
y2="26.357183"
|
||||
x2="23.688078"
|
||||
y1="11.318835"
|
||||
x1="23.688078"
|
||||
id="linearGradient4272"
|
||||
xlink:href="#linearGradient4274"
|
||||
inkscape:collect="always"
|
||||
gradientTransform="translate(0.000000,5.125000)" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2555"
|
||||
id="linearGradient2553"
|
||||
x1="33.431175"
|
||||
y1="31.964777"
|
||||
x2="21.747974"
|
||||
y2="11.780679"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient6901"
|
||||
id="linearGradient6907"
|
||||
x1="14.751649"
|
||||
y1="15.868432"
|
||||
x2="8.8953285"
|
||||
y2="16.743431"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient6925"
|
||||
id="linearGradient6931"
|
||||
x1="12.25"
|
||||
y1="18.25"
|
||||
x2="7"
|
||||
y2="21.118431"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
inkscape:window-y="30"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-height="818"
|
||||
inkscape:window-width="999"
|
||||
inkscape:document-units="px"
|
||||
inkscape:grid-bbox="true"
|
||||
showgrid="false"
|
||||
inkscape:current-layer="layer2"
|
||||
inkscape:cy="11.891468"
|
||||
inkscape:cx="-133.68151"
|
||||
inkscape:zoom="1"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
borderopacity="0.22745098"
|
||||
bordercolor="#666666"
|
||||
pagecolor="#ffffff"
|
||||
id="base"
|
||||
inkscape:showpageshadow="false"
|
||||
fill="#3465a4"
|
||||
stroke="#204a87" />
|
||||
<metadata
|
||||
id="metadata4">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title>Save</dc:title>
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>Jakub Steiner</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
<dc:subject>
|
||||
<rdf:Bag>
|
||||
<rdf:li>hdd</rdf:li>
|
||||
<rdf:li>hard drive</rdf:li>
|
||||
<rdf:li>save</rdf:li>
|
||||
<rdf:li>io</rdf:li>
|
||||
<rdf:li>store</rdf:li>
|
||||
</rdf:Bag>
|
||||
</dc:subject>
|
||||
<cc:license
|
||||
rdf:resource="http://creativecommons.org/licenses/publicdomain/" />
|
||||
<dc:identifier />
|
||||
<dc:source>http://jimmac.musichall.cz</dc:source>
|
||||
</cc:Work>
|
||||
<cc:License
|
||||
rdf:about="http://creativecommons.org/licenses/publicdomain/">
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#Reproduction" />
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#Distribution" />
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
|
||||
</cc:License>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="pix"
|
||||
id="layer2"
|
||||
inkscape:groupmode="layer">
|
||||
<g
|
||||
style="display:inline"
|
||||
id="g5022"
|
||||
transform="matrix(2.411405e-2,0,0,1.929202e-2,45.48953,41.75228)">
|
||||
<rect
|
||||
y="-150.69685"
|
||||
x="-1559.2523"
|
||||
height="478.35718"
|
||||
width="1339.6335"
|
||||
id="rect4173"
|
||||
style="opacity:0.40206185;color:black;fill:url(#linearGradient5027);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
|
||||
<path
|
||||
sodipodi:nodetypes="cccc"
|
||||
id="path5058"
|
||||
d="M -219.61876,-150.68038 C -219.61876,-150.68038 -219.61876,327.65041 -219.61876,327.65041 C -76.744594,328.55086 125.78146,220.48075 125.78138,88.454235 C 125.78138,-43.572302 -33.655436,-150.68036 -219.61876,-150.68038 z "
|
||||
style="opacity:0.40206185;color:black;fill:url(#radialGradient5029);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
|
||||
<path
|
||||
style="opacity:0.40206185;color:black;fill:url(#radialGradient5031);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
|
||||
d="M -1559.2523,-150.68038 C -1559.2523,-150.68038 -1559.2523,327.65041 -1559.2523,327.65041 C -1702.1265,328.55086 -1904.6525,220.48075 -1904.6525,88.454235 C -1904.6525,-43.572302 -1745.2157,-150.68036 -1559.2523,-150.68038 z "
|
||||
id="path5018"
|
||||
sodipodi:nodetypes="cccc" />
|
||||
</g>
|
||||
<path
|
||||
sodipodi:nodetypes="cccsccccccccc"
|
||||
id="path4196"
|
||||
d="M 11.28569,13.087628 C 10.66069,13.087628 10.254441,13.377808 10.004442,13.931381 C 10.004441,13.931381 3.5356915,31.034938 3.5356915,31.034938 C 3.5356915,31.034938 3.2856915,31.706497 3.2856915,32.816188 C 3.2856915,32.816188 3.2856915,42.466156 3.2856915,42.466156 C 3.2856915,43.548769 3.943477,44.091158 4.9419415,44.091156 L 43.50444,44.091156 C 44.489293,44.091156 45.09819,43.372976 45.09819,42.247406 L 45.09819,32.597438 C 45.09819,32.597438 45.204153,31.827015 45.00444,31.284938 L 38.28569,14.087631 C 38.101165,13.575725 37.648785,13.099533 37.16069,13.087628 L 11.28569,13.087628 z "
|
||||
style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#535353;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
sodipodi:nodetypes="ccccccccc"
|
||||
id="path4170"
|
||||
d="M 3.2735915,32.121812 L 4.0381936,31.429597 L 41.647883,31.492097 L 45.11029,31.809395 L 45.11029,42.247927 C 45.11029,43.373496 44.503272,44.091258 43.518419,44.091258 L 4.9354314,44.091258 C 3.9369667,44.091258 3.2735915,43.549207 3.2735915,42.466594 L 3.2735915,32.121812 z "
|
||||
style="fill:url(#linearGradient4234);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.02044296px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<path
|
||||
sodipodi:nodetypes="csccccccs"
|
||||
id="path3093"
|
||||
d="M 3.5490842,31.039404 C 2.8347985,32.50369 3.5484686,33.432261 4.5847985,33.432261 C 4.5847985,33.432261 43.584797,33.432261 43.584797,33.432261 C 44.703844,33.408451 45.430035,32.420356 45.013368,31.289403 L 38.299082,14.078704 C 38.114558,13.566798 37.64432,13.090606 37.156225,13.078701 L 11.299083,13.078701 C 10.674083,13.078701 10.263369,13.382274 10.01337,13.935847 C 10.01337,13.935847 3.5490842,31.039404 3.5490842,31.039404 z "
|
||||
style="fill:url(#radialGradient4250);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<rect
|
||||
y="36.299183"
|
||||
x="7.857996"
|
||||
height="5.5625"
|
||||
width="17.625"
|
||||
id="rect4174"
|
||||
style="opacity:1;color:#000000;fill:url(#linearGradient4209);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.40899992;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
|
||||
<path
|
||||
sodipodi:nodetypes="cscc"
|
||||
id="path4194"
|
||||
d="M 7.8579947,41.86168 C 7.8579947,41.86168 7.8579947,37.850195 7.8579947,37.850195 C 9.6935221,41.029421 16.154485,41.86168 20.795492,41.86168 C 20.795492,41.86168 7.8579947,41.86168 7.8579947,41.86168 z "
|
||||
style="opacity:0.81142853;fill:url(#linearGradient4242);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<path
|
||||
sodipodi:nodetypes="cccccccc"
|
||||
id="path4201"
|
||||
d="M 44.796162,30.753688 C 44.859684,32.003662 44.382159,33.069528 43.474046,33.097438 C 43.474046,33.097438 5.3553296,33.097437 5.3553297,33.097438 C 4.0660978,33.097438 3.4875937,32.772491 3.271279,32.229382 C 3.3630404,33.173714 4.0970964,33.878688 5.3553297,33.878688 C 5.3553296,33.878687 43.474046,33.878688 43.474046,33.878688 C 44.550053,33.845617 45.226851,32.454664 44.82621,30.883897 L 44.796162,30.753688 z "
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<path
|
||||
id="path4211"
|
||||
d="M 10.96875,15.28125 C 10.922675,15.481571 10.78125,15.668047 10.78125,15.875 C 10.78125,16.823605 11.37223,17.664474 12.125,18.46875 C 12.365268,18.314675 12.490117,18.114342 12.75,17.96875 C 11.809691,17.152746 11.196604,16.252168 10.96875,15.28125 z M 37.625,15.28125 C 37.396273,16.250866 36.782988,17.153676 35.84375,17.96875 C 36.117894,18.122332 36.247738,18.33699 36.5,18.5 C 37.257262,17.693344 37.8125,16.826956 37.8125,15.875 C 37.8125,15.668047 37.670906,15.481571 37.625,15.28125 z M 39.8125,23.71875 C 39.198709,27.758861 32.513887,30.96875 24.28125,30.96875 C 16.068996,30.968751 9.4211001,27.775964 8.78125,23.75 C 8.7488928,23.947132 8.65625,24.141882 8.65625,24.34375 C 8.6562503,28.661697 15.645354,32.187501 24.28125,32.1875 C 32.917146,32.1875 39.937499,28.661698 39.9375,24.34375 C 39.9375,24.130826 39.848449,23.926394 39.8125,23.71875 z "
|
||||
style="opacity:0.69142857;color:#000000;fill:url(#linearGradient4272);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
|
||||
<path
|
||||
transform="translate(8.838843e-2,5.301780)"
|
||||
d="M 8.5736699 25.593554 A 1.3700194 1.016466 0 1 1 5.833631,25.593554 A 1.3700194 1.016466 0 1 1 8.5736699 25.593554 z"
|
||||
sodipodi:ry="1.016466"
|
||||
sodipodi:rx="1.3700194"
|
||||
sodipodi:cy="25.593554"
|
||||
sodipodi:cx="7.2036505"
|
||||
id="path4224"
|
||||
style="opacity:1;color:#000000;fill:#ffffff;fill-opacity:0.45762706;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
|
||||
sodipodi:type="arc" />
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="opacity:1;color:#000000;fill:#ffffff;fill-opacity:0.45762706;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
|
||||
id="path4226"
|
||||
sodipodi:cx="7.2036505"
|
||||
sodipodi:cy="25.593554"
|
||||
sodipodi:rx="1.3700194"
|
||||
sodipodi:ry="1.016466"
|
||||
d="M 8.5736699 25.593554 A 1.3700194 1.016466 0 1 1 5.833631,25.593554 A 1.3700194 1.016466 0 1 1 8.5736699 25.593554 z"
|
||||
transform="translate(33.96705,5.213390)" />
|
||||
<path
|
||||
style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient4260);stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 11.642515,13.540723 C 11.040823,13.540723 10.649724,13.820081 10.409049,14.35301 C 10.409048,14.35301 3.9940341,30.943732 3.9940341,30.943732 C 3.9940341,30.943732 3.7533573,31.590247 3.7533573,32.658555 C 3.7533573,32.658555 3.7533573,41.948651 3.7533573,41.948651 C 3.7533573,43.303391 4.1974134,43.57555 5.3478414,43.57555 L 43.034746,43.57555 C 44.357872,43.57555 44.569062,43.259153 44.569062,41.738058 L 44.569062,32.447962 C 44.569062,32.447962 44.671072,31.706271 44.478807,31.184409 L 37.885616,14.378434 C 37.707973,13.885617 37.334964,13.552184 36.865071,13.540723 L 11.642515,13.540723 z "
|
||||
id="path4252"
|
||||
sodipodi:nodetypes="cccsccccccccc" />
|
||||
<path
|
||||
style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.00000048px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:0.42372885"
|
||||
d="M 40.5,36.554166 L 40.5,41.575101"
|
||||
id="path4282" />
|
||||
<path
|
||||
id="path4284"
|
||||
d="M 38.5,36.613943 L 38.5,41.634878"
|
||||
style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.00000048px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:0.42372885" />
|
||||
<path
|
||||
style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.00000048px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:0.42372885"
|
||||
d="M 36.5,36.613943 L 36.5,41.634878"
|
||||
id="path4286" />
|
||||
<path
|
||||
id="path4288"
|
||||
d="M 34.5,36.613943 L 34.5,41.634878"
|
||||
style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.00000048px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:0.42372885" />
|
||||
<path
|
||||
style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.00000048px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:0.42372885"
|
||||
d="M 32.5,36.613943 L 32.5,41.634878"
|
||||
id="path4290" />
|
||||
<path
|
||||
id="path4292"
|
||||
d="M 30.5,36.613943 L 30.5,41.634878"
|
||||
style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.00000048px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:0.42372885" />
|
||||
<path
|
||||
id="path4294"
|
||||
d="M 39.5,36.604065 L 39.5,41.625"
|
||||
style="opacity:0.09714284;fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000048px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<path
|
||||
style="opacity:0.09714284;fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000048px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 37.5,36.663842 L 37.5,41.684777"
|
||||
id="path4296" />
|
||||
<path
|
||||
id="path4298"
|
||||
d="M 35.5,36.663842 L 35.5,41.684777"
|
||||
style="opacity:0.09714284;fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000048px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<path
|
||||
style="opacity:0.09714284;fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000048px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 33.5,36.663842 L 33.5,41.684777"
|
||||
id="path4300" />
|
||||
<path
|
||||
id="path4302"
|
||||
d="M 31.5,36.663842 L 31.5,41.684777"
|
||||
style="opacity:0.09714284;fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000048px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<path
|
||||
id="path4572"
|
||||
d="M 7.875,36.3125 L 7.875,41.84375 L 20.4375,41.84375 L 8.21875,41.5 L 7.875,36.3125 z "
|
||||
style="opacity:0.43999999;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="opacity:0.20571427;color:#000000;fill:url(#linearGradient2553);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.93365198;stroke-linecap:square;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.42372879;visibility:visible;display:inline;overflow:visible"
|
||||
id="path2545"
|
||||
sodipodi:cx="25"
|
||||
sodipodi:cy="19.5625"
|
||||
sodipodi:rx="14.875"
|
||||
sodipodi:ry="6.6875"
|
||||
d="M 39.875 19.5625 A 14.875 6.6875 0 1 1 10.125,19.5625 A 14.875 6.6875 0 1 1 39.875 19.5625 z"
|
||||
transform="matrix(1.037815,0.000000,0.000000,1.060747,-1.632878,3.030370)" />
|
||||
</g>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
inkscape:label="down">
|
||||
<path
|
||||
transform="matrix(1.130190,1.178179e-16,7.918544e-17,-0.759601,-3.909725,53.66554)"
|
||||
d="M 40.481863 36.421127 A 15.644737 8.3968935 0 1 1 9.1923885,36.421127 A 15.644737 8.3968935 0 1 1 40.481863 36.421127 z"
|
||||
sodipodi:ry="8.3968935"
|
||||
sodipodi:rx="15.644737"
|
||||
sodipodi:cy="36.421127"
|
||||
sodipodi:cx="24.837126"
|
||||
id="path8660"
|
||||
style="opacity:0.14117647;color:#000000;fill:url(#radialGradient8668);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
|
||||
sodipodi:type="arc" />
|
||||
<path
|
||||
style="opacity:1;color:#000000;fill:url(#linearGradient6907);fill-opacity:1.0;fill-rule:nonzero;stroke:url(#linearGradient6931);stroke-width:0.99999982;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:block;overflow:visible"
|
||||
d="M 3.2034501,25.835194 C 2.1729477,-5.3853369 28.741616,-0.4511153 28.582416,15.788689 L 35.89533,15.788689 L 24.517652,28.774671 L 12.585426,15.788689 C 12.585426,15.788689 20.126859,15.788689 20.126859,15.788689 C 20.583921,4.8193225 3.4092324,1.6100346 3.2034501,25.835194 z "
|
||||
id="path1432"
|
||||
sodipodi:nodetypes="ccccccc" />
|
||||
<path
|
||||
sodipodi:nodetypes="ccccccc"
|
||||
id="path2177"
|
||||
d="M 7.6642103,9.1041047 C 12.40638,-0.0400306 28.122336,2.7175443 27.761604,16.579393 L 34.078976,16.579393 C 34.078976,16.579393 24.513151,27.536769 24.513151,27.536769 L 14.41668,16.579393 C 14.41668,16.579393 20.87332,16.579393 20.87332,16.579393 C 21.144975,5.0041615 10.922265,5.5345215 7.6642103,9.1041047 z "
|
||||
style="opacity:0.47159091;color:#000000;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient1764);stroke-width:0.99999934;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:block;overflow:visible" />
|
||||
<path
|
||||
style="opacity:0.49431817;color:#000000;fill:url(#radialGradient4997);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.9999997;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
|
||||
d="M 34.767155,16.211613 L 32.782979,18.757322 C 27.372947,17.241029 24.896829,21.486664 17.109284,20.489112 L 13.247998,16.080077 L 20.434468,16.162862 C 20.483219,4.3164571 8.3443098,4.998966 5.0292663,13.627829 C 8.8372201,-1.2611216 27.893316,0.8064118 28.28332,16.114112 L 34.767155,16.211613 z "
|
||||
id="path4989"
|
||||
sodipodi:nodetypes="cccccccc" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 29 KiB |
|
@ -0,0 +1,200 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
sodipodi:docname="go-down.svg"
|
||||
sodipodi:docbase="/home/tigert/cvs/freedesktop.org/tango-icon-theme/scalable/actions"
|
||||
inkscape:version="0.46"
|
||||
sodipodi:version="0.32"
|
||||
id="svg11300"
|
||||
height="48px"
|
||||
width="48px"
|
||||
inkscape:export-filename="/home/jimmac/Desktop/wi-fi.png"
|
||||
inkscape:export-xdpi="90.000000"
|
||||
inkscape:export-ydpi="90.000000"
|
||||
inkscape:output_extension="org.inkscape.output.svg.inkscape">
|
||||
<defs
|
||||
id="defs3">
|
||||
<inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="0 : 24 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_z="48 : 24 : 1"
|
||||
inkscape:persp3d-origin="24 : 16 : 1"
|
||||
id="perspective24" />
|
||||
<linearGradient
|
||||
id="linearGradient1442">
|
||||
<stop
|
||||
id="stop1444"
|
||||
offset="0"
|
||||
style="stop-color:#73d216" />
|
||||
<stop
|
||||
id="stop1446"
|
||||
offset="1.0000000"
|
||||
style="stop-color:#4e9a06" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient8662"
|
||||
inkscape:collect="always">
|
||||
<stop
|
||||
id="stop8664"
|
||||
offset="0"
|
||||
style="stop-color:#000000;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop8666"
|
||||
offset="1"
|
||||
style="stop-color:#000000;stop-opacity:0;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient8650"
|
||||
inkscape:collect="always">
|
||||
<stop
|
||||
id="stop8652"
|
||||
offset="0"
|
||||
style="stop-color:#ffffff;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop8654"
|
||||
offset="1"
|
||||
style="stop-color:#ffffff;stop-opacity:0;" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient8662"
|
||||
id="radialGradient1444"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1.000000,0.000000,0.000000,0.536723,1.614716e-15,16.87306)"
|
||||
cx="24.837126"
|
||||
cy="36.421127"
|
||||
fx="24.837126"
|
||||
fy="36.421127"
|
||||
r="15.644737" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient1442"
|
||||
id="radialGradient1469"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1.871885e-16,-0.843022,1.020168,2.265228e-16,0.606436,42.58614)"
|
||||
cx="35.292667"
|
||||
cy="20.494493"
|
||||
fx="35.292667"
|
||||
fy="20.494493"
|
||||
r="16.956199" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient8650"
|
||||
id="radialGradient1471"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(3.749427e-16,-2.046729,-1.557610,-2.853404e-16,44.11559,66.93275)"
|
||||
cx="15.987216"
|
||||
cy="1.5350308"
|
||||
fx="15.987216"
|
||||
fy="1.5350308"
|
||||
r="17.171415" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
inkscape:window-y="30"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-height="818"
|
||||
inkscape:window-width="1280"
|
||||
inkscape:showpageshadow="false"
|
||||
inkscape:document-units="px"
|
||||
inkscape:grid-bbox="true"
|
||||
showgrid="false"
|
||||
inkscape:current-layer="layer1"
|
||||
inkscape:cy="23.239067"
|
||||
inkscape:cx="15.972815"
|
||||
inkscape:zoom="11.313708"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
borderopacity="0.25490196"
|
||||
bordercolor="#666666"
|
||||
pagecolor="#ffffff"
|
||||
id="base"
|
||||
fill="#4e9a06"
|
||||
stroke="#4e9a06" />
|
||||
<metadata
|
||||
id="metadata4">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>Jakub Steiner</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
<dc:source>http://jimmac.musichall.cz</dc:source>
|
||||
<cc:license
|
||||
rdf:resource="http://creativecommons.org/licenses/publicdomain/" />
|
||||
<dc:title>Go Down</dc:title>
|
||||
<dc:subject>
|
||||
<rdf:Bag>
|
||||
<rdf:li>go</rdf:li>
|
||||
<rdf:li>lower</rdf:li>
|
||||
<rdf:li>down</rdf:li>
|
||||
<rdf:li>arrow</rdf:li>
|
||||
<rdf:li>pointer</rdf:li>
|
||||
<rdf:li>></rdf:li>
|
||||
</rdf:Bag>
|
||||
</dc:subject>
|
||||
<dc:contributor>
|
||||
<cc:Agent>
|
||||
<dc:title>Andreas Nilsson</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:contributor>
|
||||
</cc:Work>
|
||||
<cc:License
|
||||
rdf:about="http://creativecommons.org/licenses/publicdomain/">
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#Reproduction" />
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#Distribution" />
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
|
||||
</cc:License>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
inkscape:label="Layer 1"
|
||||
id="layer1">
|
||||
<path
|
||||
transform="matrix(1.214466,0.000000,0.000000,0.595458,-6.163846,16.31275)"
|
||||
d="M 40.481863 36.421127 A 15.644737 8.3968935 0 1 1 9.1923885,36.421127 A 15.644737 8.3968935 0 1 1 40.481863 36.421127 z"
|
||||
sodipodi:ry="8.3968935"
|
||||
sodipodi:rx="15.644737"
|
||||
sodipodi:cy="36.421127"
|
||||
sodipodi:cx="24.837126"
|
||||
id="path8660"
|
||||
style="opacity:0.20454545;color:#000000;fill:url(#radialGradient1444);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:10.000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible"
|
||||
sodipodi:type="arc" />
|
||||
<g
|
||||
id="g1464"
|
||||
transform="matrix(-1.000000,0.000000,0.000000,-1.000000,47.02856,43.99921)">
|
||||
<path
|
||||
style="opacity:1.0000000;color:#000000;fill:url(#radialGradient1469);fill-opacity:1.0000000;fill-rule:evenodd;stroke:#3a7304;stroke-width:1.0000004;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:10.000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
|
||||
d="M 14.519136,38.500000 L 32.524165,38.496094 L 32.524165,25.504468 L 40.519531,25.496656 L 23.374809,5.4992135 L 6.5285585,25.497284 L 14.524440,25.501074 L 14.519136,38.500000 z "
|
||||
id="path8643"
|
||||
sodipodi:nodetypes="cccccccc" />
|
||||
<path
|
||||
style="opacity:0.50802141;color:#000000;fill:url(#radialGradient1471);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:10.000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible"
|
||||
d="M 39.429889,24.993467 L 32.023498,25.005186 L 32.026179,37.998023 L 16.647623,37.98887 C 17.417545,19.64788 27.370272,26.995797 32.029282,16.341991 L 39.429889,24.993467 z "
|
||||
id="path8645"
|
||||
sodipodi:nodetypes="cccccc" />
|
||||
<path
|
||||
sodipodi:nodetypes="cccccccc"
|
||||
id="path8658"
|
||||
d="M 15.520704,37.496094 L 31.522109,37.500000 L 31.522109,24.507050 L 38.338920,24.491425 L 23.384644,7.0388396 L 8.6781173,24.495782 L 15.518018,24.501029 L 15.520704,37.496094 z "
|
||||
style="opacity:0.48128340;color:#000000;fill:none;fill-opacity:1.0000000;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.0000004;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:10.000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 8.1 KiB |
|
@ -0,0 +1,196 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
sodipodi:docname="go-up.svg"
|
||||
sodipodi:docbase="/home/tigert/cvs/freedesktop.org/tango-icon-theme/scalable/actions"
|
||||
inkscape:version="0.46"
|
||||
sodipodi:version="0.32"
|
||||
id="svg11300"
|
||||
height="48px"
|
||||
width="48px"
|
||||
inkscape:export-filename="/home/jimmac/Desktop/wi-fi.png"
|
||||
inkscape:export-xdpi="90.000000"
|
||||
inkscape:export-ydpi="90.000000"
|
||||
inkscape:output_extension="org.inkscape.output.svg.inkscape">
|
||||
<defs
|
||||
id="defs3">
|
||||
<inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="0 : 24 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_z="48 : 24 : 1"
|
||||
inkscape:persp3d-origin="24 : 16 : 1"
|
||||
id="perspective23" />
|
||||
<linearGradient
|
||||
id="linearGradient2304">
|
||||
<stop
|
||||
id="stop2306"
|
||||
offset="0"
|
||||
style="stop-color:#73d216" />
|
||||
<stop
|
||||
id="stop2308"
|
||||
offset="1.0000000"
|
||||
style="stop-color:#4e9a06" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient8662"
|
||||
inkscape:collect="always">
|
||||
<stop
|
||||
id="stop8664"
|
||||
offset="0"
|
||||
style="stop-color:#000000;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop8666"
|
||||
offset="1"
|
||||
style="stop-color:#000000;stop-opacity:0;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient8650"
|
||||
inkscape:collect="always">
|
||||
<stop
|
||||
id="stop8652"
|
||||
offset="0"
|
||||
style="stop-color:#ffffff;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop8654"
|
||||
offset="1"
|
||||
style="stop-color:#ffffff;stop-opacity:0;" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient8650"
|
||||
id="radialGradient1438"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(-3.749427e-16,-2.046729,1.557610,-2.853404e-16,2.767009,66.93275)"
|
||||
cx="24.53788"
|
||||
cy="0.40010813"
|
||||
fx="24.53788"
|
||||
fy="0.40010813"
|
||||
r="17.171415" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2304"
|
||||
id="radialGradient1441"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1.871885e-16,-0.843022,1.020168,2.265228e-16,0.606436,42.58614)"
|
||||
cx="11.319205"
|
||||
cy="22.454971"
|
||||
fx="11.319205"
|
||||
fy="22.454971"
|
||||
r="16.956199" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient8662"
|
||||
id="radialGradient1444"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1.000000,0.000000,0.000000,0.536723,1.614716e-15,16.87306)"
|
||||
cx="24.837126"
|
||||
cy="36.421127"
|
||||
fx="24.837126"
|
||||
fy="36.421127"
|
||||
r="15.644737" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
inkscape:window-y="30"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-height="818"
|
||||
inkscape:window-width="1280"
|
||||
inkscape:showpageshadow="false"
|
||||
inkscape:document-units="px"
|
||||
inkscape:grid-bbox="true"
|
||||
showgrid="false"
|
||||
inkscape:current-layer="layer1"
|
||||
inkscape:cy="25.620377"
|
||||
inkscape:cx="9.6380363"
|
||||
inkscape:zoom="13.059378"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
borderopacity="0.25490196"
|
||||
bordercolor="#666666"
|
||||
pagecolor="#ffffff"
|
||||
id="base"
|
||||
fill="#73d216"
|
||||
stroke="#73d216" />
|
||||
<metadata
|
||||
id="metadata4">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>Jakub Steiner</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
<dc:source>http://jimmac.musichall.cz</dc:source>
|
||||
<cc:license
|
||||
rdf:resource="http://creativecommons.org/licenses/publicdomain/" />
|
||||
<dc:title>Go Up</dc:title>
|
||||
<dc:subject>
|
||||
<rdf:Bag>
|
||||
<rdf:li>go</rdf:li>
|
||||
<rdf:li>higher</rdf:li>
|
||||
<rdf:li>up</rdf:li>
|
||||
<rdf:li>arrow</rdf:li>
|
||||
<rdf:li>pointer</rdf:li>
|
||||
<rdf:li>></rdf:li>
|
||||
</rdf:Bag>
|
||||
</dc:subject>
|
||||
<dc:contributor>
|
||||
<cc:Agent>
|
||||
<dc:title>Andreas Nilsson</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:contributor>
|
||||
</cc:Work>
|
||||
<cc:License
|
||||
rdf:about="http://creativecommons.org/licenses/publicdomain/">
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#Reproduction" />
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#Distribution" />
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
|
||||
</cc:License>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
inkscape:label="Layer 1"
|
||||
id="layer1">
|
||||
<path
|
||||
transform="matrix(1.214466,0.000000,0.000000,0.595458,-6.163846,16.31275)"
|
||||
d="M 40.481863 36.421127 A 15.644737 8.3968935 0 1 1 9.1923885,36.421127 A 15.644737 8.3968935 0 1 1 40.481863 36.421127 z"
|
||||
sodipodi:ry="8.3968935"
|
||||
sodipodi:rx="15.644737"
|
||||
sodipodi:cy="36.421127"
|
||||
sodipodi:cx="24.837126"
|
||||
id="path8660"
|
||||
style="opacity:0.29946521;color:#000000;fill:url(#radialGradient1444);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:10.000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible"
|
||||
sodipodi:type="arc" />
|
||||
<path
|
||||
sodipodi:nodetypes="cccccccc"
|
||||
id="path8643"
|
||||
d="M 14.491792,38.500000 L 32.469477,38.500000 L 32.469477,25.547437 L 40.500000,25.547437 L 23.374809,5.4992135 L 6.5285585,25.489471 L 14.497096,25.555762 L 14.491792,38.500000 z "
|
||||
style="opacity:1.0000000;color:#000000;fill:url(#radialGradient1441);fill-opacity:1.0000000;fill-rule:evenodd;stroke:#3a7304;stroke-width:1.0000004;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:10.000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
|
||||
<path
|
||||
sodipodi:nodetypes="cccscc"
|
||||
id="path8645"
|
||||
d="M 7.5855237,25.03253 L 14.995821,25.03253 L 15.062422,31.594339 C 20.718034,20.593878 31.055517,22.749928 31.656768,15.966674 C 31.656768,15.966674 23.366938,6.4219692 23.366938,6.4219692 L 7.5855237,25.03253 z "
|
||||
style="opacity:0.50802141;color:#000000;fill:url(#radialGradient1438);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:10.000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible" />
|
||||
<path
|
||||
style="opacity:0.48128340;color:#000000;fill:none;fill-opacity:1.0000000;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.0000004;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:10.000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible"
|
||||
d="M 15.602735,37.500000 L 31.502578,37.500000 L 31.502578,24.507050 L 38.311576,24.507050 L 23.361206,7.0700896 L 8.6546798,24.550470 L 15.475049,24.528373 L 15.602735,37.500000 z "
|
||||
id="path8658"
|
||||
sodipodi:nodetypes="cccccccc" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 8.0 KiB |
|
@ -0,0 +1,202 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="48px"
|
||||
height="48px"
|
||||
id="svg3007"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.1 r9760"
|
||||
sodipodi:docname="nav-outline.svg">
|
||||
<defs
|
||||
id="defs3009">
|
||||
<filter
|
||||
inkscape:collect="always"
|
||||
id="filter5333"
|
||||
x="-0.16623206"
|
||||
width="1.3324641"
|
||||
y="-0.030014125"
|
||||
height="1.0600282">
|
||||
<feGaussianBlur
|
||||
inkscape:collect="always"
|
||||
stdDeviation="0.47888561"
|
||||
id="feGaussianBlur5335" />
|
||||
</filter>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="11.945051"
|
||||
inkscape:cx="20.614872"
|
||||
inkscape:cy="23.423899"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
inkscape:grid-bbox="true"
|
||||
inkscape:document-units="px"
|
||||
inkscape:window-width="1440"
|
||||
inkscape:window-height="773"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="0" />
|
||||
<metadata
|
||||
id="metadata3012">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1"
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer">
|
||||
<rect
|
||||
style="fill:#f0f0f0;fill-rule:evenodd;stroke:#808080;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1;fill-opacity:1"
|
||||
id="rect3783"
|
||||
width="46.16272"
|
||||
height="45.59861"
|
||||
x="1.0341953"
|
||||
y="0.99112236" />
|
||||
<rect
|
||||
style="fill:#404040;fill-opacity:1;stroke:none"
|
||||
id="rect3787"
|
||||
width="2.8205326"
|
||||
height="2.7823999"
|
||||
x="4.2307992"
|
||||
y="4.093708" />
|
||||
<rect
|
||||
style="fill:#404040;fill-opacity:1;stroke:none"
|
||||
id="rect5257"
|
||||
width="24.68285"
|
||||
height="1.4102663"
|
||||
x="8.0855274"
|
||||
y="4.657815" />
|
||||
<rect
|
||||
y="8.4185247"
|
||||
x="8.4615984"
|
||||
height="2.7823999"
|
||||
width="2.8205326"
|
||||
id="rect5259"
|
||||
style="fill:#404040;fill-opacity:1;stroke:none" />
|
||||
<rect
|
||||
y="9.0766497"
|
||||
x="12.410344"
|
||||
height="1.4102663"
|
||||
width="30.498053"
|
||||
id="rect5261"
|
||||
style="fill:#404040;fill-opacity:1;stroke:none" />
|
||||
<rect
|
||||
style="fill:#404040;fill-opacity:1;stroke:none"
|
||||
id="rect5263"
|
||||
width="2.8205326"
|
||||
height="2.7823999"
|
||||
x="8.4615984"
|
||||
y="13.307448" />
|
||||
<rect
|
||||
style="fill:#404040;fill-opacity:1;stroke:none"
|
||||
id="rect5265"
|
||||
width="24.972752"
|
||||
height="1.4102663"
|
||||
x="12.410344"
|
||||
y="13.965573" />
|
||||
<rect
|
||||
y="17.444229"
|
||||
x="4.3248172"
|
||||
height="2.7823999"
|
||||
width="2.8205326"
|
||||
id="rect5267"
|
||||
style="fill:#404040;fill-opacity:1;stroke:none" />
|
||||
<rect
|
||||
y="18.008337"
|
||||
x="8.1795454"
|
||||
height="1.4102663"
|
||||
width="25.101433"
|
||||
id="rect5269"
|
||||
style="fill:#404040;fill-opacity:1;stroke:none" />
|
||||
<rect
|
||||
style="fill:#404040;fill-opacity:1;stroke:none"
|
||||
id="rect5271"
|
||||
width="2.8205326"
|
||||
height="2.7823999"
|
||||
x="8.5556164"
|
||||
y="21.769047" />
|
||||
<rect
|
||||
style="fill:#404040;fill-opacity:1;stroke:none"
|
||||
id="rect5273"
|
||||
width="28.782515"
|
||||
height="1.4102663"
|
||||
x="12.880433"
|
||||
y="22.427172" />
|
||||
<rect
|
||||
y="26.65797"
|
||||
x="13.475181"
|
||||
height="2.7823999"
|
||||
width="2.8205326"
|
||||
id="rect5275"
|
||||
style="fill:#404040;fill-opacity:1;stroke:none" />
|
||||
<rect
|
||||
y="27.316095"
|
||||
x="17.479"
|
||||
height="1.4102663"
|
||||
width="23.681646"
|
||||
id="rect5277"
|
||||
style="fill:#404040;fill-opacity:1;stroke:none" />
|
||||
<rect
|
||||
style="fill:#404040;fill-opacity:1;stroke:none"
|
||||
id="rect5279"
|
||||
width="2.8205326"
|
||||
height="2.7823999"
|
||||
x="8.5130949"
|
||||
y="31.006269" />
|
||||
<rect
|
||||
style="fill:#404040;fill-opacity:1;stroke:none"
|
||||
id="rect5281"
|
||||
width="24.557148"
|
||||
height="1.4102663"
|
||||
x="12.592034"
|
||||
y="31.636858" />
|
||||
<rect
|
||||
y="35.464046"
|
||||
x="13.475181"
|
||||
height="2.7823999"
|
||||
width="2.8205326"
|
||||
id="rect5283"
|
||||
style="fill:#404040;fill-opacity:1;stroke:none" />
|
||||
<rect
|
||||
y="36.055695"
|
||||
x="17.744923"
|
||||
height="1.4102663"
|
||||
width="18.577394"
|
||||
id="rect5285"
|
||||
style="fill:#404040;fill-opacity:1;stroke:none" />
|
||||
<rect
|
||||
style="fill:#404040;fill-opacity:1;stroke:none"
|
||||
id="rect5287"
|
||||
width="2.8205326"
|
||||
height="2.7823999"
|
||||
x="13.54166"
|
||||
y="40.35297" />
|
||||
<rect
|
||||
style="fill:#404040;fill-opacity:1;stroke:none"
|
||||
id="rect5289"
|
||||
width="23.080858"
|
||||
height="1.4102663"
|
||||
x="17.678442"
|
||||
y="40.944618" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 5.3 KiB |
|
@ -0,0 +1,283 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="48px"
|
||||
height="48px"
|
||||
id="svg3007"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.1 r9760"
|
||||
sodipodi:docname="nav-thumbs.svg">
|
||||
<defs
|
||||
id="defs3009">
|
||||
<filter
|
||||
inkscape:collect="always"
|
||||
id="filter5333"
|
||||
x="-0.16623206"
|
||||
width="1.3324641"
|
||||
y="-0.030014125"
|
||||
height="1.0600282">
|
||||
<feGaussianBlur
|
||||
inkscape:collect="always"
|
||||
stdDeviation="0.47888561"
|
||||
id="feGaussianBlur5335" />
|
||||
</filter>
|
||||
<filter
|
||||
inkscape:collect="always"
|
||||
id="filter5966">
|
||||
<feGaussianBlur
|
||||
inkscape:collect="always"
|
||||
stdDeviation="0.3570515"
|
||||
id="feGaussianBlur5968" />
|
||||
</filter>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="11.945051"
|
||||
inkscape:cx="9.375932"
|
||||
inkscape:cy="24.942259"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
inkscape:grid-bbox="true"
|
||||
inkscape:document-units="px"
|
||||
inkscape:window-width="1440"
|
||||
inkscape:window-height="773"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="0" />
|
||||
<metadata
|
||||
id="metadata3012">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1"
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer">
|
||||
<rect
|
||||
style="fill:#484848;fill-rule:evenodd;stroke:#808080;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1;fill-opacity:1"
|
||||
id="rect3783"
|
||||
width="46.16272"
|
||||
height="45.59861"
|
||||
x="1.0341953"
|
||||
y="0.99112236" />
|
||||
<rect
|
||||
y="4.7876148"
|
||||
x="14.359808"
|
||||
height="12.764274"
|
||||
width="9.7061672"
|
||||
id="rect5960"
|
||||
style="fill:#000000;fill-opacity:1;stroke:none;filter:url(#filter5966)"
|
||||
transform="matrix(1.0465713,0,0,1.0642851,3.6426579,-2.1141417)" />
|
||||
<rect
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none"
|
||||
id="rect5958"
|
||||
width="9.7061672"
|
||||
height="12.764274"
|
||||
x="18.897236"
|
||||
y="3.1920807" />
|
||||
<rect
|
||||
transform="matrix(1.0465713,0,0,1.0642851,3.6426579,13.043433)"
|
||||
style="fill:#000000;fill-opacity:1;stroke:none;filter:url(#filter5966)"
|
||||
id="rect5970"
|
||||
width="9.7061672"
|
||||
height="12.764274"
|
||||
x="14.359808"
|
||||
y="4.7876148" />
|
||||
<rect
|
||||
y="18.349655"
|
||||
x="18.897236"
|
||||
height="12.764274"
|
||||
width="9.7061672"
|
||||
id="rect5972"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none" />
|
||||
<rect
|
||||
y="4.7876148"
|
||||
x="14.359808"
|
||||
height="12.764274"
|
||||
width="9.7061672"
|
||||
id="rect5974"
|
||||
style="fill:#000000;fill-opacity:1;stroke:none;filter:url(#filter5966)"
|
||||
transform="matrix(1.0465713,0,0,0.9368834,3.6426579,29.209842)" />
|
||||
<rect
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none"
|
||||
id="rect5976"
|
||||
width="9.7061672"
|
||||
height="11.833546"
|
||||
x="18.897236"
|
||||
y="33.906113" />
|
||||
<rect
|
||||
y="4.905829"
|
||||
x="19.960924"
|
||||
height="0.66480595"
|
||||
width="7.7117486"
|
||||
id="rect5995"
|
||||
style="fill:#808080;fill-opacity:1;stroke:none" />
|
||||
<rect
|
||||
style="fill:#808080;fill-opacity:1;stroke:none"
|
||||
id="rect6177"
|
||||
width="3.6219761"
|
||||
height="0.66480595"
|
||||
x="19.960924"
|
||||
y="6.0340419" />
|
||||
<rect
|
||||
style="fill:#808080;fill-opacity:1;stroke:none"
|
||||
id="rect6179"
|
||||
width="7.7117486"
|
||||
height="0.66480595"
|
||||
x="19.960924"
|
||||
y="7.2562728" />
|
||||
<rect
|
||||
y="8.3844862"
|
||||
x="19.960924"
|
||||
height="0.66480595"
|
||||
width="5.6903667"
|
||||
id="rect6181"
|
||||
style="fill:#808080;fill-opacity:1;stroke:none" />
|
||||
<rect
|
||||
y="9.7007341"
|
||||
x="19.960924"
|
||||
height="0.66480595"
|
||||
width="7.7117486"
|
||||
id="rect6183"
|
||||
style="fill:#808080;fill-opacity:1;stroke:none" />
|
||||
<rect
|
||||
style="fill:#808080;fill-opacity:1;stroke:none"
|
||||
id="rect6185"
|
||||
width="7.7117486"
|
||||
height="0.66480595"
|
||||
x="19.960924"
|
||||
y="10.828948" />
|
||||
<rect
|
||||
y="12.051179"
|
||||
x="19.960924"
|
||||
height="0.66480595"
|
||||
width="7.7117486"
|
||||
id="rect6187"
|
||||
style="fill:#808080;fill-opacity:1;stroke:none" />
|
||||
<rect
|
||||
y="14.213587"
|
||||
x="23.204536"
|
||||
height="0.66480595"
|
||||
width="1.2245234"
|
||||
id="rect6189"
|
||||
style="fill:#808080;fill-opacity:1;stroke:none" />
|
||||
<rect
|
||||
style="fill:#808080;fill-opacity:1;stroke:none"
|
||||
id="rect6209"
|
||||
width="7.7117486"
|
||||
height="0.66480595"
|
||||
x="19.772888"
|
||||
y="19.854652" />
|
||||
<rect
|
||||
y="39.08128"
|
||||
x="19.913914"
|
||||
height="0.66480595"
|
||||
width="3.6219761"
|
||||
id="rect6211"
|
||||
style="fill:#808080;fill-opacity:1;stroke:none" />
|
||||
<rect
|
||||
y="22.205095"
|
||||
x="19.772888"
|
||||
height="0.66480595"
|
||||
width="6.6305442"
|
||||
id="rect6213"
|
||||
style="fill:#808080;fill-opacity:1;stroke:none" />
|
||||
<rect
|
||||
style="fill:#808080;fill-opacity:1;stroke:none"
|
||||
id="rect6215"
|
||||
width="7.7587576"
|
||||
height="0.66480595"
|
||||
x="19.866905"
|
||||
y="37.859051" />
|
||||
<rect
|
||||
style="fill:#808080;fill-opacity:1;stroke:none"
|
||||
id="rect6217"
|
||||
width="7.7117486"
|
||||
height="0.66480595"
|
||||
x="19.772888"
|
||||
y="21.029873" />
|
||||
<rect
|
||||
y="25.777771"
|
||||
x="19.772888"
|
||||
height="0.66480595"
|
||||
width="7.7117486"
|
||||
id="rect6219"
|
||||
style="fill:#808080;fill-opacity:1;stroke:none" />
|
||||
<rect
|
||||
style="fill:#808080;fill-opacity:1;stroke:none"
|
||||
id="rect6221"
|
||||
width="7.7117486"
|
||||
height="0.66480595"
|
||||
x="19.772888"
|
||||
y="27.000002" />
|
||||
<rect
|
||||
style="fill:#808080;fill-opacity:1;stroke:none"
|
||||
id="rect6223"
|
||||
width="1.2245234"
|
||||
height="0.66480595"
|
||||
x="23.204536"
|
||||
y="28.974375" />
|
||||
<rect
|
||||
style="fill:#808080;fill-opacity:1;stroke:none"
|
||||
id="rect6225"
|
||||
width="3.6219761"
|
||||
height="0.66480595"
|
||||
x="19.960922"
|
||||
y="42.983021" />
|
||||
<rect
|
||||
style="fill:#808080;fill-opacity:1;stroke:none"
|
||||
id="rect6227"
|
||||
width="7.7117486"
|
||||
height="0.66480595"
|
||||
x="19.913914"
|
||||
y="36.777847" />
|
||||
<rect
|
||||
y="35.602627"
|
||||
x="19.913914"
|
||||
height="0.66480595"
|
||||
width="7.7117486"
|
||||
id="rect6231"
|
||||
style="fill:#808080;fill-opacity:1;stroke:none" />
|
||||
<rect
|
||||
style="fill:#808080;fill-opacity:1;stroke:none"
|
||||
id="rect6233"
|
||||
width="7.7117486"
|
||||
height="0.66480595"
|
||||
x="19.913914"
|
||||
y="40.350525" />
|
||||
<rect
|
||||
y="41.572754"
|
||||
x="19.913914"
|
||||
height="0.66480595"
|
||||
width="7.7117486"
|
||||
id="rect6235"
|
||||
style="fill:#808080;fill-opacity:1;stroke:none" />
|
||||
<rect
|
||||
style="fill:#0000e6;fill-opacity:0.44444448;stroke:none"
|
||||
id="rect6237"
|
||||
width="3.5256658"
|
||||
height="1.927364"
|
||||
x="22.077036"
|
||||
y="23.367346" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 7.6 KiB |
|
@ -0,0 +1,436 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="48px"
|
||||
height="48px"
|
||||
id="svg6431"
|
||||
sodipodi:version="0.32"
|
||||
inkscape:version="0.46"
|
||||
sodipodi:docbase="/home/jimmac/src/cvs/tango-icon-theme/scalable/actions"
|
||||
sodipodi:docname="list-add.svg"
|
||||
inkscape:output_extension="org.inkscape.output.svg.inkscape">
|
||||
<defs
|
||||
id="defs6433">
|
||||
<inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="0 : 24 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_z="48 : 24 : 1"
|
||||
inkscape:persp3d-origin="24 : 16 : 1"
|
||||
id="perspective70" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient2091">
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop2093" />
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop2095" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient7916">
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop7918" />
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:0.34020618;"
|
||||
offset="1.0000000"
|
||||
id="stop7920" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient8662">
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop8664" />
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop8666" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient8662"
|
||||
id="radialGradient1503"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1.000000,0.000000,0.000000,0.536723,-1.018989e-13,16.87306)"
|
||||
cx="24.837126"
|
||||
cy="36.421127"
|
||||
fx="24.837126"
|
||||
fy="36.421127"
|
||||
r="15.644737" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient2847">
|
||||
<stop
|
||||
style="stop-color:#3465a4;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop2849" />
|
||||
<stop
|
||||
style="stop-color:#3465a4;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop2851" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2847"
|
||||
id="linearGradient1488"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(-1.000000,0.000000,0.000000,-1.000000,-1.242480,40.08170)"
|
||||
x1="37.128052"
|
||||
y1="29.729605"
|
||||
x2="37.065414"
|
||||
y2="26.194071" />
|
||||
<linearGradient
|
||||
id="linearGradient2831">
|
||||
<stop
|
||||
style="stop-color:#3465a4;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop2833" />
|
||||
<stop
|
||||
id="stop2855"
|
||||
offset="0.33333334"
|
||||
style="stop-color:#5b86be;stop-opacity:1;" />
|
||||
<stop
|
||||
style="stop-color:#83a8d8;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop2835" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2831"
|
||||
id="linearGradient1486"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(-48.30498,-6.043298)"
|
||||
x1="13.478554"
|
||||
y1="10.612206"
|
||||
x2="15.419417"
|
||||
y2="19.115122" />
|
||||
<linearGradient
|
||||
id="linearGradient2380">
|
||||
<stop
|
||||
style="stop-color:#b9cfe7;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop2382" />
|
||||
<stop
|
||||
style="stop-color:#729fcf;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop2384" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient2682">
|
||||
<stop
|
||||
style="stop-color:#3977c3;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop2684" />
|
||||
<stop
|
||||
style="stop-color:#89aedc;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop2686" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2682"
|
||||
id="linearGradient2688"
|
||||
x1="36.713837"
|
||||
y1="31.455952"
|
||||
x2="37.124462"
|
||||
y2="24.842253"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(-48.77039,-5.765705)" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient2690">
|
||||
<stop
|
||||
style="stop-color:#c4d7eb;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop2692" />
|
||||
<stop
|
||||
style="stop-color:#c4d7eb;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop2694" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2690"
|
||||
id="linearGradient2696"
|
||||
x1="32.647972"
|
||||
y1="30.748846"
|
||||
x2="37.124462"
|
||||
y2="24.842253"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(-48.77039,-5.765705)" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient2871">
|
||||
<stop
|
||||
style="stop-color:#3465a4;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop2873" />
|
||||
<stop
|
||||
style="stop-color:#3465a4;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop2875" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient2402">
|
||||
<stop
|
||||
style="stop-color:#729fcf;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop2404" />
|
||||
<stop
|
||||
style="stop-color:#528ac5;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop2406" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2797"
|
||||
id="linearGradient1493"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="5.9649176"
|
||||
y1="26.048164"
|
||||
x2="52.854097"
|
||||
y2="26.048164" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient2797">
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop2799" />
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop2801" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2797"
|
||||
id="linearGradient1491"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="5.9649176"
|
||||
y1="26.048164"
|
||||
x2="52.854097"
|
||||
y2="26.048164" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient7179">
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop7181" />
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop7183" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient2316">
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop2318" />
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:0.65979379;"
|
||||
offset="1"
|
||||
id="stop2320" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient1322">
|
||||
<stop
|
||||
id="stop1324"
|
||||
offset="0.0000000"
|
||||
style="stop-color:#729fcf" />
|
||||
<stop
|
||||
id="stop1326"
|
||||
offset="1.0000000"
|
||||
style="stop-color:#5187d6;stop-opacity:1.0000000;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient1322"
|
||||
id="linearGradient4975"
|
||||
x1="34.892849"
|
||||
y1="36.422989"
|
||||
x2="45.918697"
|
||||
y2="48.547989"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(-18.01785,-13.57119)" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient7179"
|
||||
id="linearGradient7185"
|
||||
x1="13.435029"
|
||||
y1="13.604306"
|
||||
x2="22.374878"
|
||||
y2="23.554308"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient7179"
|
||||
id="linearGradient7189"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="13.435029"
|
||||
y1="13.604306"
|
||||
x2="22.374878"
|
||||
y2="23.554308"
|
||||
gradientTransform="matrix(-1.000000,0.000000,0.000000,-1.000000,47.93934,50.02474)" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2380"
|
||||
id="linearGradient7180"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="62.513836"
|
||||
y1="36.061237"
|
||||
x2="15.984863"
|
||||
y2="20.60858" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2871"
|
||||
id="linearGradient7182"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="46.834816"
|
||||
y1="45.264122"
|
||||
x2="45.380436"
|
||||
y2="50.939667" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2402"
|
||||
id="linearGradient7184"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="18.935766"
|
||||
y1="23.667896"
|
||||
x2="53.588622"
|
||||
y2="26.649362" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2871"
|
||||
id="linearGradient7186"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="46.834816"
|
||||
y1="45.264122"
|
||||
x2="45.380436"
|
||||
y2="50.939667" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient7916"
|
||||
id="linearGradient7922"
|
||||
x1="16.874998"
|
||||
y1="22.851799"
|
||||
x2="27.900846"
|
||||
y2="34.976799"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2091"
|
||||
id="radialGradient2097"
|
||||
cx="23.070683"
|
||||
cy="35.127438"
|
||||
fx="23.070683"
|
||||
fy="35.127438"
|
||||
r="10.319340"
|
||||
gradientTransform="matrix(0.914812,1.265023e-2,-8.21502e-3,0.213562,2.253914,27.18889)"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="0.15686275"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1"
|
||||
inkscape:cx="-123.56934"
|
||||
inkscape:cy="0.031886897"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:grid-bbox="true"
|
||||
inkscape:document-units="px"
|
||||
inkscape:window-width="1280"
|
||||
inkscape:window-height="818"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="30"
|
||||
showguides="true"
|
||||
inkscape:guide-bbox="true"
|
||||
inkscape:showpageshadow="false" />
|
||||
<metadata
|
||||
id="metadata6436">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title>Add</dc:title>
|
||||
<dc:date>2006-01-04</dc:date>
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>Andreas Nilsson</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
<dc:source>http://tango-project.org</dc:source>
|
||||
<dc:subject>
|
||||
<rdf:Bag>
|
||||
<rdf:li>add</rdf:li>
|
||||
<rdf:li>plus</rdf:li>
|
||||
</rdf:Bag>
|
||||
</dc:subject>
|
||||
<cc:license
|
||||
rdf:resource="http://creativecommons.org/licenses/publicdomain/" />
|
||||
</cc:Work>
|
||||
<cc:License
|
||||
rdf:about="http://creativecommons.org/licenses/publicdomain/">
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#Reproduction" />
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#Distribution" />
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
|
||||
</cc:License>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1"
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer">
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="opacity:0.10824742;fill:url(#radialGradient2097);fill-opacity:1;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
id="path1361"
|
||||
sodipodi:cx="22.958872"
|
||||
sodipodi:cy="34.94062"
|
||||
sodipodi:rx="10.31934"
|
||||
sodipodi:ry="2.320194"
|
||||
d="M 33.278212 34.94062 A 10.31934 2.320194 0 1 1 12.639532,34.94062 A 10.31934 2.320194 0 1 1 33.278212 34.94062 z"
|
||||
transform="matrix(1.550487,0,0,1.978714,-12.4813,-32.49103)" />
|
||||
<path
|
||||
style="font-size:59.901077px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125.00000%;writing-mode:lr-tb;text-anchor:start;fill:#75a1d0;fill-opacity:1.0000000;stroke:#3465a4;stroke-width:1.0000004px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
|
||||
d="M 27.514356,37.542682 L 27.514356,28.515722 L 37.492820,28.475543 L 37.492820,21.480219 L 27.523285,21.480219 L 27.514356,11.520049 L 20.498082,11.531210 L 20.502546,21.462362 L 10.512920,21.536022 L 10.477206,28.504561 L 20.511475,28.475543 L 20.518171,37.515896 L 27.514356,37.542682 z "
|
||||
id="text1314"
|
||||
sodipodi:nodetypes="ccccccccccccc" />
|
||||
<path
|
||||
style="font-size:59.901077px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125.00000%;writing-mode:lr-tb;text-anchor:start;opacity:0.40860215;fill:url(#linearGradient4975);fill-opacity:1.0000000;stroke:url(#linearGradient7922);stroke-width:1.0000006px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
|
||||
d="M 26.498702,36.533920 L 26.498702,27.499738 L 36.501304,27.499738 L 36.494607,22.475309 L 26.507630,22.475309 L 26.507630,12.480335 L 21.512796,12.498193 L 21.521725,22.475309 L 11.495536,22.493166 L 11.468750,27.466256 L 21.533143,27.475185 L 21.519750,36.502670 L 26.498702,36.533920 z "
|
||||
id="path7076"
|
||||
sodipodi:nodetypes="ccccccccccccc" />
|
||||
<path
|
||||
style="fill:#ffffff;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;opacity:0.31182796"
|
||||
d="M 11.000000,25.000000 C 11.000000,26.937500 36.984375,24.031250 36.984375,24.968750 L 36.984375,21.968750 L 27.000000,22.000000 L 27.000000,12.034772 L 21.000000,12.034772 L 21.000000,22.000000 L 11.000000,22.000000 L 11.000000,25.000000 z "
|
||||
id="path7914"
|
||||
sodipodi:nodetypes="ccccccccc" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 14 KiB |
|
@ -0,0 +1,424 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="48px"
|
||||
height="48px"
|
||||
id="svg6431"
|
||||
sodipodi:version="0.32"
|
||||
inkscape:version="0.46"
|
||||
sodipodi:docbase="/home/jimmac/src/cvs/tango-icon-theme/scalable/actions"
|
||||
sodipodi:docname="list-remove.svg"
|
||||
inkscape:output_extension="org.inkscape.output.svg.inkscape">
|
||||
<defs
|
||||
id="defs6433">
|
||||
<inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="0 : 24 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_z="48 : 24 : 1"
|
||||
inkscape:persp3d-origin="24 : 16 : 1"
|
||||
id="perspective69" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient2091">
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop2093" />
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop2095" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2091"
|
||||
id="radialGradient2097"
|
||||
cx="23.070683"
|
||||
cy="35.127438"
|
||||
fx="23.070683"
|
||||
fy="35.127438"
|
||||
r="10.319340"
|
||||
gradientTransform="matrix(0.914812,1.265023e-2,-8.21502e-3,0.213562,2.253914,27.18889)"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
id="linearGradient7916">
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop7918" />
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:0.34020618;"
|
||||
offset="1.0000000"
|
||||
id="stop7920" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient8662">
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop8664" />
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop8666" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient8662"
|
||||
id="radialGradient1503"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1.000000,0.000000,0.000000,0.536723,-1.018989e-13,16.87306)"
|
||||
cx="24.837126"
|
||||
cy="36.421127"
|
||||
fx="24.837126"
|
||||
fy="36.421127"
|
||||
r="15.644737" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient2847">
|
||||
<stop
|
||||
style="stop-color:#3465a4;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop2849" />
|
||||
<stop
|
||||
style="stop-color:#3465a4;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop2851" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2847"
|
||||
id="linearGradient1488"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(-1.000000,0.000000,0.000000,-1.000000,-1.242480,40.08170)"
|
||||
x1="37.128052"
|
||||
y1="29.729605"
|
||||
x2="37.065414"
|
||||
y2="26.194071" />
|
||||
<linearGradient
|
||||
id="linearGradient2831">
|
||||
<stop
|
||||
style="stop-color:#3465a4;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop2833" />
|
||||
<stop
|
||||
id="stop2855"
|
||||
offset="0.33333334"
|
||||
style="stop-color:#5b86be;stop-opacity:1;" />
|
||||
<stop
|
||||
style="stop-color:#83a8d8;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop2835" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2831"
|
||||
id="linearGradient1486"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(-48.30498,-6.043298)"
|
||||
x1="13.478554"
|
||||
y1="10.612206"
|
||||
x2="15.419417"
|
||||
y2="19.115122" />
|
||||
<linearGradient
|
||||
id="linearGradient2380">
|
||||
<stop
|
||||
style="stop-color:#b9cfe7;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop2382" />
|
||||
<stop
|
||||
style="stop-color:#729fcf;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop2384" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient2682">
|
||||
<stop
|
||||
style="stop-color:#3977c3;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop2684" />
|
||||
<stop
|
||||
style="stop-color:#89aedc;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop2686" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2682"
|
||||
id="linearGradient2688"
|
||||
x1="36.713837"
|
||||
y1="31.455952"
|
||||
x2="37.124462"
|
||||
y2="24.842253"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(-48.77039,-5.765705)" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient2690">
|
||||
<stop
|
||||
style="stop-color:#c4d7eb;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop2692" />
|
||||
<stop
|
||||
style="stop-color:#c4d7eb;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop2694" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2690"
|
||||
id="linearGradient2696"
|
||||
x1="32.647972"
|
||||
y1="30.748846"
|
||||
x2="37.124462"
|
||||
y2="24.842253"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(-48.77039,-5.765705)" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient2871">
|
||||
<stop
|
||||
style="stop-color:#3465a4;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop2873" />
|
||||
<stop
|
||||
style="stop-color:#3465a4;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop2875" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient2402">
|
||||
<stop
|
||||
style="stop-color:#729fcf;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop2404" />
|
||||
<stop
|
||||
style="stop-color:#528ac5;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop2406" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2797"
|
||||
id="linearGradient1493"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="5.9649176"
|
||||
y1="26.048164"
|
||||
x2="52.854097"
|
||||
y2="26.048164" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient2797">
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop2799" />
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop2801" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2797"
|
||||
id="linearGradient1491"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="5.9649176"
|
||||
y1="26.048164"
|
||||
x2="52.854097"
|
||||
y2="26.048164" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient7179">
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop7181" />
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop7183" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient2316">
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop2318" />
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:0.65979379;"
|
||||
offset="1"
|
||||
id="stop2320" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient1322">
|
||||
<stop
|
||||
id="stop1324"
|
||||
offset="0.0000000"
|
||||
style="stop-color:#729fcf" />
|
||||
<stop
|
||||
id="stop1326"
|
||||
offset="1.0000000"
|
||||
style="stop-color:#5187d6;stop-opacity:1.0000000;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient1322"
|
||||
id="linearGradient4975"
|
||||
x1="34.892849"
|
||||
y1="36.422989"
|
||||
x2="45.918697"
|
||||
y2="48.547989"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(-18.01785,-13.57119)" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient7179"
|
||||
id="linearGradient7185"
|
||||
x1="13.435029"
|
||||
y1="13.604306"
|
||||
x2="22.374878"
|
||||
y2="23.554308"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient7179"
|
||||
id="linearGradient7189"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="13.435029"
|
||||
y1="13.604306"
|
||||
x2="22.374878"
|
||||
y2="23.554308"
|
||||
gradientTransform="matrix(-1.000000,0.000000,0.000000,-1.000000,47.93934,50.02474)" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2380"
|
||||
id="linearGradient7180"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="62.513836"
|
||||
y1="36.061237"
|
||||
x2="15.984863"
|
||||
y2="20.60858" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2871"
|
||||
id="linearGradient7182"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="46.834816"
|
||||
y1="45.264122"
|
||||
x2="45.380436"
|
||||
y2="50.939667" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2402"
|
||||
id="linearGradient7184"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="18.935766"
|
||||
y1="23.667896"
|
||||
x2="53.588622"
|
||||
y2="26.649362" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2871"
|
||||
id="linearGradient7186"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="46.834816"
|
||||
y1="45.264122"
|
||||
x2="45.380436"
|
||||
y2="50.939667" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient7916"
|
||||
id="linearGradient7922"
|
||||
x1="16.874998"
|
||||
y1="22.851799"
|
||||
x2="27.900846"
|
||||
y2="34.976799"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="0.10980392"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1"
|
||||
inkscape:cx="-123.27226"
|
||||
inkscape:cy="26.474252"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:grid-bbox="true"
|
||||
inkscape:document-units="px"
|
||||
inkscape:window-width="1280"
|
||||
inkscape:window-height="818"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="30"
|
||||
inkscape:showpageshadow="false" />
|
||||
<metadata
|
||||
id="metadata6436">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title>Remove</dc:title>
|
||||
<dc:date>2006-01-04</dc:date>
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>Andreas Nilsson</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
<dc:source>http://tango-project.org</dc:source>
|
||||
<dc:subject>
|
||||
<rdf:Bag>
|
||||
<rdf:li>remove</rdf:li>
|
||||
<rdf:li>delete</rdf:li>
|
||||
</rdf:Bag>
|
||||
</dc:subject>
|
||||
<cc:license
|
||||
rdf:resource="http://creativecommons.org/licenses/publicdomain/" />
|
||||
</cc:Work>
|
||||
<cc:License
|
||||
rdf:about="http://creativecommons.org/licenses/publicdomain/">
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#Reproduction" />
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#Distribution" />
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
|
||||
</cc:License>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1"
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer">
|
||||
<path
|
||||
style="font-size:59.901077px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125.00000%;writing-mode:lr-tb;text-anchor:start;fill:#75a1d0;fill-opacity:1.0000000;stroke:#3465a4;stroke-width:1.0000004px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
|
||||
d="M 27.514356,28.359472 L 39.633445,28.475543 L 39.633445,21.480219 L 27.523285,21.480219 L 20.502546,21.462362 L 8.5441705,21.489147 L 8.5084565,28.457686 L 20.511475,28.475543 L 27.514356,28.359472 z "
|
||||
id="text1314"
|
||||
sodipodi:nodetypes="ccccccccc" />
|
||||
<path
|
||||
style="font-size:59.901077px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125.00000%;writing-mode:lr-tb;text-anchor:start;opacity:0.40860215;fill:url(#linearGradient4975);fill-opacity:1.0000000;stroke:url(#linearGradient7922);stroke-width:1.0000006px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
|
||||
d="M 38.579429,27.484113 L 38.588357,22.475309 L 9.5267863,22.493166 L 9.5000003,27.466256 L 38.579429,27.484113 z "
|
||||
id="path7076"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
style="fill:#ffffff;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;opacity:0.31182796"
|
||||
d="M 9.0000000,25.000000 C 9.0000000,26.937500 39.125000,24.062500 39.125000,25.000000 L 39.125000,22.000000 L 9.0000000,22.000000 L 9.0000000,25.000000 z "
|
||||
id="path7914"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 14 KiB |
|
@ -0,0 +1,737 @@
|
|||
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
|
||||
|
||||
/* FROM PDF.JS, ADAPTED */
|
||||
|
||||
'use strict';
|
||||
|
||||
var kDefaultURL = 'compressed.tracemonkey-pldi-09.pdf';
|
||||
var kDefaultScale = 1.25;
|
||||
var kDefaultScaleDelta = 1.1;
|
||||
var kCacheSize = 20;
|
||||
var kCssUnits = 96.0 / 72.0;
|
||||
var kScrollbarPadding = 40;
|
||||
var kMinScale = 0.25;
|
||||
var kMaxScale = 4.0;
|
||||
|
||||
|
||||
var Cache = function cacheCache(size) {
|
||||
var data = [];
|
||||
this.push = function cachePush(view) {
|
||||
var i = data.indexOf(view);
|
||||
if (i >= 0)
|
||||
data.splice(i);
|
||||
data.push(view);
|
||||
if (data.length > size)
|
||||
data.shift().update();
|
||||
};
|
||||
};
|
||||
|
||||
var cache = new Cache(kCacheSize);
|
||||
var currentPageNumber = 1;
|
||||
|
||||
var PDFView = {
|
||||
pages: [],
|
||||
thumbnails: [],
|
||||
currentScale: kDefaultScale,
|
||||
initialBookmark: document.location.hash.substring(1),
|
||||
|
||||
setScale: function pdfViewSetScale(val, resetAutoSettings) {
|
||||
var pages = this.pages;
|
||||
for (var i = 0; i < pages.length; i++)
|
||||
pages[i].update(val * kCssUnits);
|
||||
|
||||
if (this.currentScale != val)
|
||||
this.pages[this.page - 1].scrollIntoView();
|
||||
this.currentScale = val;
|
||||
|
||||
var event = document.createEvent('UIEvents');
|
||||
event.initUIEvent('scalechange', false, false, window, 0);
|
||||
event.scale = val;
|
||||
event.resetAutoSettings = resetAutoSettings;
|
||||
window.dispatchEvent(event);
|
||||
},
|
||||
|
||||
parseScale: function pdfViewParseScale(value, resetAutoSettings) {
|
||||
if ('custom' == value)
|
||||
return;
|
||||
|
||||
var scale = parseFloat(value);
|
||||
if (scale) {
|
||||
this.setScale(scale, true);
|
||||
return;
|
||||
}
|
||||
|
||||
var currentPage = this.pages[this.page - 1];
|
||||
var pageWidthScale = ($("#content").width() - kScrollbarPadding) /
|
||||
currentPage.width / kCssUnits;
|
||||
var pageHeightScale = ($("#content").height() - kScrollbarPadding) /
|
||||
currentPage.height / kCssUnits;
|
||||
if ('page-width' == value)
|
||||
this.setScale(pageWidthScale, resetAutoSettings);
|
||||
if ('page-height' == value)
|
||||
this.setScale(pageHeightScale, resetAutoSettings);
|
||||
if ('page-fit' == value) {
|
||||
this.setScale(
|
||||
Math.min(pageWidthScale, pageHeightScale), resetAutoSettings);
|
||||
}
|
||||
},
|
||||
|
||||
zoomIn: function pdfViewZoomIn() {
|
||||
var newScale = Math.min(kMaxScale, this.currentScale * kDefaultScaleDelta);
|
||||
this.setScale(newScale, true);
|
||||
},
|
||||
|
||||
zoomOut: function pdfViewZoomOut() {
|
||||
var newScale = Math.max(kMinScale, this.currentScale / kDefaultScaleDelta);
|
||||
this.setScale(newScale, true);
|
||||
},
|
||||
|
||||
set page(val) {
|
||||
var pages = this.pages;
|
||||
var input = document.getElementById('pageNumber');
|
||||
if (!(0 < val && val <= pages.length)) {
|
||||
var event = document.createEvent('UIEvents');
|
||||
event.initUIEvent('pagechange', false, false, window, 0);
|
||||
event.pageNumber = this.page;
|
||||
window.dispatchEvent(event);
|
||||
return;
|
||||
}
|
||||
|
||||
currentPageNumber = val;
|
||||
var event = document.createEvent('UIEvents');
|
||||
event.initUIEvent('pagechange', false, false, window, 0);
|
||||
event.pageNumber = val;
|
||||
window.dispatchEvent(event);
|
||||
|
||||
// checking if the this.page was called from the updateViewarea function:
|
||||
// avoiding the creation of two "set page" method (internal and public)
|
||||
if (updateViewarea.inProgress)
|
||||
return;
|
||||
|
||||
// Avoid scrolling the first page during loading
|
||||
if (this.loading && val == 1)
|
||||
return;
|
||||
|
||||
pages[val - 1].scrollIntoView();
|
||||
},
|
||||
|
||||
get page() {
|
||||
return currentPageNumber;
|
||||
},
|
||||
|
||||
open: function pdfViewOpen(url, scale) {
|
||||
document.title = PDFView.Ptitle;
|
||||
this.url = url;
|
||||
var self = this;
|
||||
PDFJS.getPdf(
|
||||
{
|
||||
url: url,
|
||||
progress: function getPdfProgress(evt) {
|
||||
if (evt.lengthComputable)
|
||||
self.progress(evt.loaded / evt.total);
|
||||
},
|
||||
error: self.error
|
||||
},
|
||||
function getPdfLoad(data) {
|
||||
self.loading = true;
|
||||
self.load(data, scale);
|
||||
self.loading = false;
|
||||
});
|
||||
},
|
||||
|
||||
download: function pdfViewDownload() {
|
||||
window.open(this.url + '#pdfjs.action=download', '_parent');
|
||||
},
|
||||
|
||||
navigateTo: function pdfViewNavigateTo(dest) {
|
||||
if (typeof dest === 'string')
|
||||
dest = this.destinations[dest];
|
||||
if (!(dest instanceof Array))
|
||||
return; // invalid destination
|
||||
// dest array looks like that: <page-ref> </XYZ|FitXXX> <args..>
|
||||
var destRef = dest[0];
|
||||
var pageNumber = destRef instanceof Object ?
|
||||
this.pagesRefMap[destRef.num + ' ' + destRef.gen + ' R'] : (destRef + 1);
|
||||
if (pageNumber) {
|
||||
this.page = pageNumber;
|
||||
var currentPage = this.pages[pageNumber - 1];
|
||||
currentPage.scrollIntoView(dest);
|
||||
}
|
||||
},
|
||||
|
||||
getDestinationHash: function pdfViewGetDestinationHash(dest) {
|
||||
if (typeof dest === 'string')
|
||||
return '#' + escape(dest);
|
||||
if (dest instanceof Array) {
|
||||
var destRef = dest[0]; // see navigateTo method for dest format
|
||||
var pageNumber = destRef instanceof Object ?
|
||||
this.pagesRefMap[destRef.num + ' ' + destRef.gen + ' R'] :
|
||||
(destRef + 1);
|
||||
if (pageNumber) {
|
||||
var pdfOpenParams = '#page=' + pageNumber;
|
||||
if (isName(dest[1], 'XYZ')) {
|
||||
var scale = (dest[4] || this.currentScale);
|
||||
pdfOpenParams += '&zoom=' + (scale * 100);
|
||||
if (dest[2] || dest[3]) {
|
||||
pdfOpenParams += ',' + (dest[2] || 0) + ',' + (dest[3] || 0);
|
||||
}
|
||||
}
|
||||
return pdfOpenParams;
|
||||
}
|
||||
}
|
||||
return '';
|
||||
},
|
||||
|
||||
error: function pdfViewError() {
|
||||
var loadingIndicator = document.getElementById('loading');
|
||||
loadingIndicator.innerHTML = 'Error';
|
||||
},
|
||||
|
||||
progress: function pdfViewProgress(level) {
|
||||
var percent = Math.round(level * 100);
|
||||
var loadingIndicator = document.getElementById('loading');
|
||||
loadingIndicator.innerHTML = 'Loading... ' + percent + '%';
|
||||
},
|
||||
|
||||
load: function pdfViewLoad(data, scale) {
|
||||
var loadingIndicator = document.getElementById('loading');
|
||||
loadingIndicator.setAttribute('hidden', 'true');
|
||||
|
||||
var container = document.getElementById('viewer');
|
||||
while (container.hasChildNodes())
|
||||
container.removeChild(container.lastChild);
|
||||
|
||||
var pdf = new PDFJS.PDFDoc(data);
|
||||
var pagesCount = pdf.numPages;
|
||||
document.getElementById('numPages').innerHTML = pagesCount;
|
||||
document.getElementById('pageNumber').max = pagesCount;
|
||||
|
||||
var pages = this.pages = [];
|
||||
var pagesRefMap = {};
|
||||
var thumbnails = this.thumbnails = [];
|
||||
for (var i = 1; i <= pagesCount; i++) {
|
||||
var page = pdf.getPage(i);
|
||||
pages.push(new PageView(container, page, i, page.width, page.height,
|
||||
page.stats, this.navigateTo.bind(this)));
|
||||
/*thumbnails.push(new ThumbnailView(sidebar, page, i,
|
||||
page.width / page.height));*/
|
||||
var pageRef = page.ref;
|
||||
pagesRefMap[pageRef.num + ' ' + pageRef.gen + ' R'] = i;
|
||||
}
|
||||
|
||||
this.setScale(scale || kDefaultScale, true);
|
||||
|
||||
/*this.pagesRefMap = pagesRefMap;
|
||||
this.destinations = pdf.catalog.destinations;
|
||||
if (pdf.catalog.documentOutline) {
|
||||
this.outline = new DocumentOutlineView(pdf.catalog.documentOutline);
|
||||
var outlineSwitchButton = document.getElementById('outlineSwitch');
|
||||
outlineSwitchButton.removeAttribute('disabled');
|
||||
this.switchSidebarView('outline');
|
||||
}*/
|
||||
this.page = 1;
|
||||
|
||||
/*if (this.initialBookmark) {
|
||||
this.setHash(this.initialBookmark);
|
||||
this.initialBookmark = null;
|
||||
}
|
||||
else
|
||||
this.page = 1;*/
|
||||
},
|
||||
|
||||
setHash: function pdfViewSetHash(hash) {
|
||||
if (!hash)
|
||||
return;
|
||||
|
||||
if (hash.indexOf('=') >= 0) {
|
||||
// parsing query string
|
||||
var paramsPairs = hash.split('&');
|
||||
var params = {};
|
||||
for (var i = 0; i < paramsPairs.length; ++i) {
|
||||
var paramPair = paramsPairs[i].split('=');
|
||||
params[paramPair[0]] = paramPair[1];
|
||||
}
|
||||
// borrowing syntax from "Parameters for Opening PDF Files"
|
||||
if ('nameddest' in params) {
|
||||
PDFView.navigateTo(params.nameddest);
|
||||
return;
|
||||
}
|
||||
if ('page' in params) {
|
||||
var pageNumber = (params.page | 0) || 1;
|
||||
this.page = pageNumber;
|
||||
if ('zoom' in params) {
|
||||
var zoomArgs = params.zoom.split(','); // scale,left,top
|
||||
// building destination array
|
||||
var dest = [null, new Name('XYZ'), (zoomArgs[1] | 0),
|
||||
(zoomArgs[2] | 0), (zoomArgs[0] | 0) / 100];
|
||||
var currentPage = this.pages[pageNumber - 1];
|
||||
currentPage.scrollIntoView(dest);
|
||||
} else
|
||||
this.page = params.page; // simple page
|
||||
return;
|
||||
}
|
||||
} else if (/^\d+$/.test(hash)) // page number
|
||||
this.page = hash;
|
||||
else // named destination
|
||||
PDFView.navigateTo(unescape(hash));
|
||||
},
|
||||
|
||||
/*switchSidebarView: function pdfViewSwitchSidebarView(view) {
|
||||
var thumbsScrollView = document.getElementById('sidebarScrollView');
|
||||
var outlineScrollView = document.getElementById('outlineScrollView');
|
||||
var thumbsSwitchButton = document.getElementById('thumbsSwitch');
|
||||
var outlineSwitchButton = document.getElementById('outlineSwitch');
|
||||
switch (view) {
|
||||
case 'thumbs':
|
||||
thumbsScrollView.removeAttribute('hidden');
|
||||
outlineScrollView.setAttribute('hidden', 'true');
|
||||
thumbsSwitchButton.setAttribute('data-selected', true);
|
||||
outlineSwitchButton.removeAttribute('data-selected');
|
||||
break;
|
||||
case 'outline':
|
||||
thumbsScrollView.setAttribute('hidden', 'true');
|
||||
outlineScrollView.removeAttribute('hidden');
|
||||
thumbsSwitchButton.removeAttribute('data-selected');
|
||||
outlineSwitchButton.setAttribute('data-selected', true);
|
||||
break;
|
||||
}
|
||||
},*/
|
||||
|
||||
getVisiblePages: function pdfViewGetVisiblePages() {
|
||||
var pages = this.pages;
|
||||
var kBottomMargin = 10;
|
||||
var visiblePages = [];
|
||||
|
||||
var currentHeight = kBottomMargin;
|
||||
var windowTop = window.pageYOffset;
|
||||
for (var i = 1; i <= pages.length; ++i) {
|
||||
var page = pages[i - 1];
|
||||
var pageHeight = page.height * page.scale + kBottomMargin;
|
||||
if (currentHeight + pageHeight > windowTop)
|
||||
break;
|
||||
|
||||
currentHeight += pageHeight;
|
||||
}
|
||||
|
||||
var windowBottom = window.pageYOffset + window.innerHeight;
|
||||
for (; i <= pages.length && currentHeight < windowBottom; ++i) {
|
||||
var singlePage = pages[i - 1];
|
||||
visiblePages.push({ id: singlePage.id, y: currentHeight,
|
||||
view: singlePage });
|
||||
currentHeight += singlePage.height * singlePage.scale + kBottomMargin;
|
||||
}
|
||||
return visiblePages;
|
||||
}
|
||||
};
|
||||
|
||||
var PageView = function pageView(container, content, id, pageWidth, pageHeight,
|
||||
stats, navigateTo) {
|
||||
this.id = id;
|
||||
this.content = content;
|
||||
|
||||
var view = this.content.view;
|
||||
this.x = view.x;
|
||||
this.y = view.y;
|
||||
this.width = view.width;
|
||||
this.height = view.height;
|
||||
|
||||
var anchor = document.createElement('a');
|
||||
anchor.name = '' + this.id;
|
||||
|
||||
var div = document.createElement('div');
|
||||
div.id = 'pageContainer' + this.id;
|
||||
div.className = 'page';
|
||||
|
||||
container.appendChild(anchor);
|
||||
container.appendChild(div);
|
||||
|
||||
this.update = function pageViewUpdate(scale) {
|
||||
this.scale = scale || this.scale;
|
||||
div.style.width = (this.width * this.scale) + 'px';
|
||||
|
||||
div.style.height = (this.height * this.scale) + 'px';
|
||||
|
||||
var container = document.getElementById('viewer');
|
||||
container.style.left = (document.getElementById("content").offsetWidth-(this.width))/2 + 'px';
|
||||
|
||||
while (div.hasChildNodes())
|
||||
div.removeChild(div.lastChild);
|
||||
div.removeAttribute('data-loaded');
|
||||
};
|
||||
|
||||
function setupLinks(content, scale) {
|
||||
function bindLink(link, dest) {
|
||||
link.href = PDFView.getDestinationHash(dest);
|
||||
link.onclick = function pageViewSetupLinksOnclick() {
|
||||
if (dest)
|
||||
PDFView.navigateTo(dest);
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
var links = content.getLinks();
|
||||
for (var i = 0; i < links.length; i++) {
|
||||
var link = document.createElement('a');
|
||||
link.style.left = (Math.floor(links[i].x - view.x) * scale) + 'px';
|
||||
link.style.top = (Math.floor(links[i].y - view.y) * scale) + 'px';
|
||||
link.style.width = Math.ceil(links[i].width * scale) + 'px';
|
||||
link.style.height = Math.ceil(links[i].height * scale) + 'px';
|
||||
link.href = links[i].url || '';
|
||||
if (!links[i].url)
|
||||
bindLink(link, ('dest' in links[i]) ? links[i].dest : null);
|
||||
div.appendChild(link);
|
||||
}
|
||||
}
|
||||
|
||||
this.getPagePoint = function pageViewGetPagePoint(x, y) {
|
||||
var scale = PDFView.currentScale;
|
||||
return this.content.rotatePoint(x / scale, y / scale);
|
||||
};
|
||||
|
||||
this.scrollIntoView = function pageViewScrollIntoView(dest) {
|
||||
if (!dest) {
|
||||
div.scrollIntoView(true);
|
||||
return;
|
||||
}
|
||||
|
||||
var x = 0, y = 0;
|
||||
var width = 0, height = 0, widthScale, heightScale;
|
||||
var scale = 0;
|
||||
switch (dest[1].name) {
|
||||
case 'XYZ':
|
||||
x = dest[2];
|
||||
y = dest[3];
|
||||
scale = dest[4];
|
||||
break;
|
||||
case 'Fit':
|
||||
case 'FitB':
|
||||
scale = 'page-fit';
|
||||
break;
|
||||
case 'FitH':
|
||||
case 'FitBH':
|
||||
y = dest[2];
|
||||
scale = 'page-width';
|
||||
break;
|
||||
case 'FitV':
|
||||
case 'FitBV':
|
||||
x = dest[2];
|
||||
scale = 'page-height';
|
||||
break;
|
||||
case 'FitR':
|
||||
x = dest[2];
|
||||
y = dest[3];
|
||||
width = dest[4] - x;
|
||||
height = dest[5] - y;
|
||||
widthScale = (window.innerWidth - kScrollbarPadding) /
|
||||
width / kCssUnits;
|
||||
heightScale = (window.innerHeight - kScrollbarPadding) /
|
||||
height / kCssUnits;
|
||||
scale = Math.min(widthScale, heightScale);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
var boundingRect = [
|
||||
this.content.rotatePoint(x, y),
|
||||
this.content.rotatePoint(x + width, y + height)
|
||||
];
|
||||
|
||||
if (scale && scale !== PDFView.currentScale)
|
||||
PDFView.setScale(scale, true);
|
||||
|
||||
setTimeout(function pageViewScrollIntoViewRelayout() {
|
||||
// letting page to re-layout before scrolling
|
||||
var scale = PDFView.currentScale;
|
||||
var x = Math.min(boundingRect[0].x, boundingRect[1].x);
|
||||
var y = Math.min(boundingRect[0].y, boundingRect[1].y);
|
||||
var width = Math.abs(boundingRect[0].x - boundingRect[1].x);
|
||||
var height = Math.abs(boundingRect[0].y - boundingRect[1].y);
|
||||
|
||||
// using temporary div to scroll it into view
|
||||
var tempDiv = document.createElement('div');
|
||||
tempDiv.style.position = 'absolute';
|
||||
tempDiv.style.left = Math.floor(x * scale) + 'px';
|
||||
tempDiv.style.top = Math.floor(y * scale) + 'px';
|
||||
tempDiv.style.width = Math.ceil(width * scale) + 'px';
|
||||
tempDiv.style.height = Math.ceil(height * scale) + 'px';
|
||||
div.appendChild(tempDiv);
|
||||
tempDiv.scrollIntoView(true);
|
||||
div.removeChild(tempDiv);
|
||||
}, 0);
|
||||
};
|
||||
|
||||
this.draw = function pageviewDraw() {
|
||||
if (div.hasChildNodes()) {
|
||||
this.updateStats();
|
||||
return false;
|
||||
}
|
||||
|
||||
var canvas = document.createElement('canvas');
|
||||
canvas.id = 'page' + this.id;
|
||||
canvas.mozOpaque = true;
|
||||
div.appendChild(canvas);
|
||||
|
||||
var scale = this.scale;
|
||||
canvas.width = pageWidth * scale;
|
||||
canvas.height = pageHeight * scale;
|
||||
|
||||
var ctx = canvas.getContext('2d');
|
||||
ctx.save();
|
||||
ctx.fillStyle = 'rgb(255, 255, 255)';
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
ctx.restore();
|
||||
ctx.translate(-this.x * scale, -this.y * scale);
|
||||
|
||||
stats.begin = Date.now();
|
||||
this.content.startRendering(ctx, this.updateStats);
|
||||
|
||||
setupLinks(this.content, this.scale);
|
||||
div.setAttribute('data-loaded', true);
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
this.updateStats = function pageViewUpdateStats() {
|
||||
var t1 = stats.compile, t2 = stats.fonts, t3 = stats.render;
|
||||
var str = 'Time to compile/fonts/render: ' +
|
||||
(t1 - stats.begin) + '/' + (t2 - t1) + '/' + (t3 - t2) + ' ms';
|
||||
};
|
||||
};
|
||||
|
||||
var ThumbnailView = function thumbnailView(container, page, id, pageRatio) {
|
||||
var anchor = document.createElement('a');
|
||||
anchor.href = '#' + id;
|
||||
anchor.onclick = function stopNivigation() {
|
||||
PDFView.page = id;
|
||||
return false;
|
||||
};
|
||||
|
||||
var div = document.createElement('div');
|
||||
div.id = 'thumbnailContainer' + id;
|
||||
div.className = 'thumbnail';
|
||||
|
||||
anchor.appendChild(div);
|
||||
container.appendChild(anchor);
|
||||
|
||||
this.draw = function thumbnailViewDraw() {
|
||||
if (div.hasChildNodes())
|
||||
return;
|
||||
|
||||
var canvas = document.createElement('canvas');
|
||||
canvas.id = 'thumbnail' + id;
|
||||
canvas.mozOpaque = true;
|
||||
|
||||
var maxThumbSize = 134;
|
||||
canvas.width = pageRatio >= 1 ? maxThumbSize :
|
||||
maxThumbSize * pageRatio;
|
||||
canvas.height = pageRatio <= 1 ? maxThumbSize :
|
||||
maxThumbSize / pageRatio;
|
||||
|
||||
div.setAttribute('data-loaded', true);
|
||||
div.appendChild(canvas);
|
||||
|
||||
var ctx = canvas.getContext('2d');
|
||||
ctx.save();
|
||||
ctx.fillStyle = 'rgb(255, 255, 255)';
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
ctx.restore();
|
||||
|
||||
var view = page.view;
|
||||
var scaleX = (canvas.width / page.width);
|
||||
var scaleY = (canvas.height / page.height);
|
||||
ctx.translate(-view.x * scaleX, -view.y * scaleY);
|
||||
div.style.width = (view.width * scaleX) + 'px';
|
||||
div.style.height = (view.height * scaleY) + 'px';
|
||||
div.style.lineHeight = (view.height * scaleY) + 'px';
|
||||
|
||||
page.startRendering(ctx, function thumbnailViewDrawStartRendering() {});
|
||||
};
|
||||
};
|
||||
|
||||
var DocumentOutlineView = function documentOutlineView(outline) {
|
||||
var outlineView = document.getElementById('outlineView');
|
||||
|
||||
function bindItemLink(domObj, item) {
|
||||
domObj.href = PDFView.getDestinationHash(item.dest);
|
||||
domObj.onclick = function documentOutlineViewOnclick(e) {
|
||||
PDFView.navigateTo(item.dest);
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
var queue = [{parent: outlineView, items: outline}];
|
||||
while (queue.length > 0) {
|
||||
var levelData = queue.shift();
|
||||
var i, n = levelData.items.length;
|
||||
for (i = 0; i < n; i++) {
|
||||
var item = levelData.items[i];
|
||||
var div = document.createElement('div');
|
||||
div.className = 'outlineItem';
|
||||
var a = document.createElement('a');
|
||||
bindItemLink(a, item);
|
||||
a.textContent = item.title;
|
||||
div.appendChild(a);
|
||||
|
||||
if (item.items.length > 0) {
|
||||
var itemsDiv = document.createElement('div');
|
||||
itemsDiv.className = 'outlineItems';
|
||||
div.appendChild(itemsDiv);
|
||||
queue.push({parent: itemsDiv, items: item.items});
|
||||
}
|
||||
|
||||
levelData.parent.appendChild(div);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function webViewerLoad(url) {
|
||||
var scale = kDefaultScale;
|
||||
PDFView.open(url, parseFloat(PDFView.parseScale(scale)));
|
||||
|
||||
if (!window.File || !window.FileReader || !window.FileList || !window.Blob)
|
||||
document.getElementById('fileInput').setAttribute('hidden', 'true');
|
||||
else
|
||||
document.getElementById('fileInput').value = null;
|
||||
}
|
||||
|
||||
window.addEventListener('unload', function webViewerUnload(evt) {
|
||||
window.scrollTo(0, 0);
|
||||
}, true);
|
||||
|
||||
function updateViewarea() {
|
||||
var visiblePages = PDFView.getVisiblePages();
|
||||
for (var i = 0; i < visiblePages.length; i++) {
|
||||
var page = visiblePages[i];
|
||||
if (PDFView.pages[page.id - 1].draw())
|
||||
cache.push(page.view);
|
||||
}
|
||||
|
||||
if (!visiblePages.length)
|
||||
return;
|
||||
|
||||
updateViewarea.inProgress = true; // used in "set page"
|
||||
var currentId = PDFView.page;
|
||||
var firstPage = visiblePages[0];
|
||||
PDFView.page = firstPage.id;
|
||||
updateViewarea.inProgress = false;
|
||||
|
||||
var kViewerTopMargin = 52;
|
||||
var pageNumber = firstPage.id;
|
||||
var pdfOpenParams = '#page=' + pageNumber;
|
||||
pdfOpenParams += '&zoom=' + Math.round(PDFView.currentScale * 100);
|
||||
var currentPage = PDFView.pages[pageNumber - 1];
|
||||
var topLeft = currentPage.getPagePoint(window.pageXOffset,
|
||||
window.pageYOffset - firstPage.y - kViewerTopMargin);
|
||||
pdfOpenParams += ',' + Math.round(topLeft.x) + ',' + Math.round(topLeft.y);
|
||||
}
|
||||
|
||||
window.addEventListener('scroll', function webViewerScroll(evt) {
|
||||
updateViewarea();
|
||||
}, true);
|
||||
|
||||
window.addEventListener('resize', function webViewerResize(evt) {
|
||||
if (document.getElementById('pageWidthOption').selected ||
|
||||
document.getElementById('pageFitOption').selected)
|
||||
PDFView.parseScale(document.getElementById('scaleSelect').value);
|
||||
updateViewarea();
|
||||
});
|
||||
|
||||
window.addEventListener('hashchange', function webViewerHashchange(evt) {
|
||||
PDFView.setHash(document.location.hash.substring(1));
|
||||
});
|
||||
|
||||
window.addEventListener('change', function webViewerChange(evt) {
|
||||
var files = evt.target.files;
|
||||
if (!files || files.length == 0)
|
||||
return;
|
||||
|
||||
// Read the local file into a Uint8Array.
|
||||
var fileReader = new FileReader();
|
||||
fileReader.onload = function webViewerChangeFileReaderOnload(evt) {
|
||||
var data = evt.target.result;
|
||||
var buffer = new ArrayBuffer(data.length);
|
||||
var uint8Array = new Uint8Array(buffer);
|
||||
|
||||
for (var i = 0; i < data.length; i++)
|
||||
uint8Array[i] = data.charCodeAt(i);
|
||||
PDFView.load(uint8Array);
|
||||
};
|
||||
|
||||
// Read as a binary string since "readAsArrayBuffer" is not yet
|
||||
// implemented in Firefox.
|
||||
var file = files[0];
|
||||
fileReader.readAsBinaryString(file);
|
||||
|
||||
document.title = PDFView.Ptitle;
|
||||
|
||||
// URL does not reflect proper document location - hiding some icons.
|
||||
document.getElementById('download').setAttribute('hidden', 'true');
|
||||
}, true);
|
||||
|
||||
window.addEventListener('scalechange', function scalechange(evt) {
|
||||
var customScaleOption = document.getElementById('customScaleOption');
|
||||
customScaleOption.selected = false;
|
||||
|
||||
if (!evt.resetAutoSettings &&
|
||||
(document.getElementById('pageWidthOption').selected ||
|
||||
document.getElementById('pageFitOption').selected)) {
|
||||
updateViewarea();
|
||||
return;
|
||||
}
|
||||
|
||||
var options = document.getElementById('scaleSelect').options;
|
||||
var predefinedValueFound = false;
|
||||
var value = '' + evt.scale;
|
||||
for (var i = 0; i < options.length; i++) {
|
||||
var option = options[i];
|
||||
if (option.value != value) {
|
||||
option.selected = false;
|
||||
continue;
|
||||
}
|
||||
option.selected = true;
|
||||
predefinedValueFound = true;
|
||||
}
|
||||
|
||||
if (!predefinedValueFound) {
|
||||
customScaleOption.textContent = Math.round(evt.scale * 10000) / 100 + '%';
|
||||
customScaleOption.selected = true;
|
||||
}
|
||||
|
||||
updateViewarea();
|
||||
}, true);
|
||||
|
||||
window.addEventListener('pagechange', function pagechange(evt) {
|
||||
var page = evt.pageNumber;
|
||||
if (document.getElementById('pageNumber').value != page)
|
||||
document.getElementById('pageNumber').value = page;
|
||||
document.getElementById('previous').disabled = (page <= 1);
|
||||
document.getElementById('next').disabled = (page >= PDFView.pages.length);
|
||||
}, true);
|
||||
|
||||
window.addEventListener('keydown', function keydown(evt) {
|
||||
var curElement = document.activeElement;
|
||||
var controlsElement = document.getElementById('controls2');
|
||||
while (curElement) {
|
||||
if (curElement === controlsElement)
|
||||
return; // ignoring if the 'controls' element is focused
|
||||
curElement = curElement.parentNode;
|
||||
}
|
||||
switch (evt.keyCode) {
|
||||
case 61: // FF/Mac '='
|
||||
case 107: // FF '+' and '='
|
||||
case 187: // Chrome '+'
|
||||
PDFView.zoomIn();
|
||||
break;
|
||||
case 109: // FF '-'
|
||||
case 189: // Chrome '-'
|
||||
PDFView.zoomOut();
|
||||
break;
|
||||
case 48: // '0'
|
||||
PDFView.setScale(kDefaultScale, true);
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
function hidePDFviewer() {
|
||||
showPDFviewer.shown = false;
|
||||
$('table').show();
|
||||
$('#controls').html(showPDFviewer.oldcode);
|
||||
$("#viewer").remove();
|
||||
$("#loading").remove()
|
||||
document.title = showPDFviewer.lastTitle;
|
||||
}
|
||||
|
||||
function showPDFviewer(dir,filename){
|
||||
if(!showPDFviewer.shown){
|
||||
$("#editor").hide();
|
||||
var url = OC.filePath('files','ajax','download.php')+'?files='+encodeURIComponent(filename)+"&dir="+encodeURIComponent(dir);
|
||||
$('table').hide();
|
||||
function im(path) { return OC.filePath('files_pdfviewer','js','pdfjs/web/images/'+path); }
|
||||
showPDFviewer.oldcode = $("#controls").html();
|
||||
$("#controls").empty();
|
||||
$("#controls").html('<button id="previous" onclick="PDFView.page--;" oncontextmenu="return false;"><img src="'+im('go-up.svg')+'" align="top" height="10"/>Previous</button><button id="next" onclick="PDFView.page++;" oncontextmenu="return false;"><img src="'+im('go-down.svg')+'" align="top" height="10"/>Next</button><div class="separator"></div><input style="width:25px;" type="number" id="pageNumber" onchange="PDFView.page = this.value;" value="1" size="4" min="1" /><span>/</span><span id="numPages">--</span><div class="separator"></div><button id="zoomOut" title="Zoom Out" onclick="PDFView.zoomOut();" oncontextmenu="return false;"><img src="'+im('zoom-out.svg')+'" align="top" height="10"/></button><button id="zoomIn" title="Zoom In" onclick="PDFView.zoomIn();" oncontextmenu="return false;"><img src="'+im('zoom-in.svg')+
|
||||
'" align="top" height="10"/></button><div class="separator"></div><select id="scaleSelect" onchange="PDFView.parseScale(this.value);" oncontextmenu="return false;"><option id="customScaleOption" value="custom"></option><option value="0.5">50%</option><option value="0.75">75%</option><option value="1">100%</option><option value="1.25" selected="selected">125%</option><option value="1.5">150%</option><option value="2">200%</option><option id="pageWidthOption" value="page-width">Page Width</option><option id="pageFitOption" value="page-fit">Page Fit</option></select><div class="separator"></div><button id="print" onclick="window.print();" oncontextmenu="return false;"><img src="'+im('document-print.svg')+'" align="top" height="10"/>Print</button><button id="download" title="Download" onclick="PDFView.download();" oncontextmenu="return false;">'+
|
||||
'<img src="'+im('download.svg')+'" align="top" height="10"/>Download</button><button id="close" title="Close viewer" onclick="hidePDFviewer();" oncontextmenu="return false;">x</button><span id="info">--</span></div>');
|
||||
var oldcontent = $("#content").html();
|
||||
$("#content").html(oldcontent+'<div id="loading">Loading... 0%</div><div id="viewer"></div>');
|
||||
showPDFviewer.lastTitle = document.title;
|
||||
PDFView.Ptitle = filename;
|
||||
PDFView.open(url,1.00);
|
||||
$("#pageWidthOption").attr("selected","selected");
|
||||
showPDFviewer.shown = true;
|
||||
}
|
||||
}
|
||||
showPDFviewer.shown=false;
|
||||
showPDFviewer.oldCode='';
|
||||
showPDFviewer.lastTitle='';
|
||||
|
||||
var extrahtml = '<li id="extra" style="display:none;"><a title="" href="'+OC.webroot+"/apps/files_pdfviewer/lastopened.php"+'" style="background-image:url(/owncloud/apps/files_pdfviewer/css/history.png)">Last opened</a></li>';
|
||||
|
||||
$(document).ready(function(){
|
||||
if(location.href.indexOf("files")!=-1) {
|
||||
PDFJS.workerSrc = OC.filePath('files_pdfviewer','js','pdfjs/build/pdf.js');
|
||||
if(typeof FileActions!=='undefined'){
|
||||
FileActions.register('application/pdf','Edit','',function(filename){
|
||||
showPDFviewer($('#dir').val(),filename);
|
||||
});
|
||||
FileActions.setDefault('application/pdf','Edit');
|
||||
}
|
||||
}
|
||||
});
|
|
@ -0,0 +1,29 @@
|
|||
<?
|
||||
require_once('../../../lib/base.php');
|
||||
require_once('../lib/album.php');
|
||||
OC_JSON::checkLoggedIn();
|
||||
OC_JSON::checkAppEnabled('gallery');
|
||||
|
||||
function handleRename($oldname, $newname) {
|
||||
OC_Gallery_Album::rename($oldname, $newname, OC_User::getUser());
|
||||
}
|
||||
|
||||
function handleRemove($name) {
|
||||
OC_Gallery_Album::remove(OC_User::getUser(), $name);
|
||||
}
|
||||
|
||||
if ($_GET['operation']) {
|
||||
switch($_GET['operation']) {
|
||||
case "rename":
|
||||
handleRename($_GET['oldname'], $_GET['newname']);
|
||||
OC_JSON::success(array('newname' => $_GET['newname']));
|
||||
break;
|
||||
case "remove":
|
||||
handleRemove($_GET['name']);
|
||||
OC_JSON::success();
|
||||
break;
|
||||
default:
|
||||
OC_JSON::error(array('cause' => "Unknown operation"));
|
||||
}
|
||||
}
|
||||
?>
|
|
@ -4,12 +4,14 @@ OC_JSON::checkLoggedIn();
|
|||
OC_JSON::checkAppEnabled('gallery');
|
||||
|
||||
$a = array();
|
||||
|
||||
$result = OC_Gallery_Album::find(OC_User::getUser());
|
||||
|
||||
while ($r = $result->fetchRow()) {
|
||||
$album_name = $r['album_name'];
|
||||
$tmp_res = OC_Gallery_Photo::find($r['album_id']);
|
||||
$a[] = array('name' => $album_name, 'numOfItems' => min($tmp_res->numRows(), 10));
|
||||
|
||||
$a[] = array('name' => $album_name, 'numOfItems' => min($tmp_res->numRows(), 10), 'bgPath' => OC::$WEBROOT.'/data/'.OC_User::getUser().'/gallery/'.$album_name.'.png');
|
||||
}
|
||||
|
||||
OC_JSON::success(array('albums'=>$a));
|
||||
|
|
|
@ -4,7 +4,7 @@ require_once('../../../lib/base.php');
|
|||
OC_JSON::checkLoggedIn();
|
||||
OC_JSON::checkAppEnabled('gallery');
|
||||
|
||||
OC_Gallery_Scanner::cleanUp();
|
||||
OC_JSON::success(array('albums' => OC_Gallery_Scanner::scan('')));
|
||||
//OC_JSON::success(array('albums' => array(array('name' => 'test', 'imagesCount' => 1, 'images' => array('dupa')))));
|
||||
|
||||
?>
|
||||
|
|
|
@ -14,6 +14,9 @@ div#gallery_album_box {
|
|||
display: inline-block;
|
||||
margin: 5pt;
|
||||
vertical-align: top;
|
||||
padding: 10px;
|
||||
border: solid 1px black;
|
||||
position: relative;
|
||||
}
|
||||
.leftcontent div#gallery_album_box {
|
||||
margin: 5px;
|
||||
|
@ -21,13 +24,28 @@ div#gallery_album_box {
|
|||
|
||||
div#gallery_album_box h1 {
|
||||
font-size: 12pt;
|
||||
font-family: Arial;
|
||||
font-family: Verdana;
|
||||
}
|
||||
|
||||
div#gallery_album_cover {
|
||||
width: 199px;
|
||||
height: 199px;
|
||||
border: solid 1px black;
|
||||
border: solid 1pt #999;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
div#gallery_control_overlay {
|
||||
border: 0;
|
||||
position:absolute;
|
||||
right: 10pt;
|
||||
background-color: #333;
|
||||
opacity: 0.5;
|
||||
visibility:hidden;
|
||||
padding: 0 5pt;
|
||||
}
|
||||
|
||||
div#gallery_control_overlay a {
|
||||
color:white;
|
||||
}
|
||||
|
||||
#gallery_images {
|
||||
|
|
|
@ -5,6 +5,12 @@ OC_Util::checkLoggedIn();
|
|||
OC_Util::checkAppEnabled('gallery');
|
||||
OC_App::setActiveNavigationEntry( 'gallery_index' );
|
||||
|
||||
if (!file_exists(OC_Config::getValue("datadirectory").'/'. OC_User::getUser() .'/gallery')) {
|
||||
mkdir(OC_Config::getValue("datadirectory").'/'. OC_User::getUser() .'/gallery');
|
||||
$f = fopen(OC_Config::getValue("datadirectory").'/'. OC_User::getUser() .'/gallery/.htaccess', 'w');
|
||||
fwrite($f, "allow from all");
|
||||
fclose($f);
|
||||
}
|
||||
|
||||
if (!isset($_GET['view'])) {
|
||||
$result = OC_Gallery_Album::find(OC_User::getUser());
|
||||
|
|
|
@ -4,7 +4,7 @@ $(document).ready(function() {
|
|||
if (r.status == 'success') {
|
||||
for (var i in r.albums) {
|
||||
var a = r.albums[i];
|
||||
Albums.add(a.name, a.numOfItems);
|
||||
Albums.add(a.name, a.numOfItems, a.bgPath);
|
||||
}
|
||||
var targetDiv = document.getElementById('gallery_list');
|
||||
if (targetDiv) {
|
||||
|
@ -39,3 +39,37 @@ function scanForAlbums() {
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
function galleryRemove(albumName) {
|
||||
if (confirm("Do you wan't to remove album " + albumName + "?")) {
|
||||
$.getJSON("ajax/galleryOp.php", {operation: "remove", name: albumName}, function(r) {
|
||||
if (r.status == "success") {
|
||||
$("#gallery_album_box[title='"+albumName+"']").remove();
|
||||
Albums.remove(albumName);
|
||||
} else {
|
||||
alert("Error: " + r.cause);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function galleryRename(name) {
|
||||
var result = window.prompt("Input new gallery name", "");
|
||||
if (result) {
|
||||
if (Albums.find(result)) {
|
||||
alert("Album named '" + result + "' already exists");
|
||||
return;
|
||||
}
|
||||
$.getJSON("ajax/galleryOp.php", {operation: "rename", oldname: name, newname: result}, function(r) {
|
||||
if (r.status == "success") {
|
||||
Albums.rename($("#gallery_album_box[title='"+name+"']"), result);
|
||||
} else {
|
||||
alert("Error: " + r.cause);
|
||||
}
|
||||
});
|
||||
|
||||
} else {
|
||||
alert("Album name can't be empty")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,13 +12,13 @@ Albums={
|
|||
// album with the same name wont be insered,
|
||||
// and false will be returned
|
||||
// true on success
|
||||
add: function(album_name, num) {
|
||||
add: function(album_name, num, bgPath) {
|
||||
for (var a in Albums.albums) {
|
||||
if (a.name == album_name) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Albums.albums.push({name: album_name, numOfCovers: num});
|
||||
Albums.albums.push({name: album_name, numOfCovers: num, backgroundPath: bgPath});
|
||||
return true;
|
||||
},
|
||||
// remove element with given name
|
||||
|
@ -57,24 +57,38 @@ Albums={
|
|||
// displays gallery in linear representation
|
||||
// on given element, and apply default styles for gallery
|
||||
display: function(element) {
|
||||
var displayTemplate = '<div id="gallery_album_box" title="*NAME*"><a href="?view=*NAME*"><div id="gallery_album_cover"></div></a><h1>*NAME*</h1></div></div>';
|
||||
var displayTemplate = '<div id="gallery_album_box" title="*NAME*"><div id="gallery_control_overlay"><a href="#" onclick="galleryRename(\'*NAME*\');return false;">rename</a> | <a href="#" onclick="galleryRemove(\'*NAME*\');">remove</a></div><a href="?view=*NAME*"><div id="gallery_album_cover" title="*NAME*"></div></a><h1>*NAME*</h1></div></div>';
|
||||
for (var i in Albums.albums) {
|
||||
var a = Albums.albums[i];
|
||||
var local = $(displayTemplate.replace(/\*NAME\*/g, a.name));
|
||||
local.css('background-repeat', 'no-repeat');
|
||||
local.css('background-position', '0 0');
|
||||
local.css('background-image','url("ajax/getCovers.php?album_name='+a.name+'")');
|
||||
local.mousemove(function(e) {
|
||||
$("#gallery_album_cover", local).css('background-repeat', 'no-repeat');
|
||||
$("#gallery_album_cover", local).css('background-position', '0');
|
||||
$("#gallery_album_cover", local).css('background-image','url("ajax/getCovers.php?album_name='+a.name+'")');
|
||||
local.mouseover(function(e) {
|
||||
$("#gallery_control_overlay", this).css('visibility','visible');
|
||||
});
|
||||
local.mouseout(function(e) {
|
||||
$("#gallery_control_overlay", this).css('visibility','hidden');
|
||||
});
|
||||
$("#gallery_album_cover", local).mousemove(function(e) {
|
||||
|
||||
var albumMetadata = Albums.find(this.title);
|
||||
if (albumMetadata == undefined) {
|
||||
return;
|
||||
}
|
||||
var x = Math.min(Math.floor((e.layerX - this.offsetLeft)/(this.offsetWidth/albumMetadata.numOfCovers)), albumMetadata.numOfCovers-1);
|
||||
x *= this.offsetWidth;
|
||||
x *= this.offsetWidth-1;
|
||||
$(this).css('background-position', -x+'px 0');
|
||||
});
|
||||
$(element).append(local);
|
||||
}
|
||||
},
|
||||
rename: function(element, new_name) {
|
||||
if (new_name) {
|
||||
$(element).attr("title", new_name);
|
||||
$("a", element).attr("href", "?view="+new_name);
|
||||
$("h1", element).text(new_name);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,10 +1,27 @@
|
|||
<?php
|
||||
|
||||
class OC_Gallery_Album{
|
||||
class OC_Gallery_Album {
|
||||
public static function create($owner, $name){
|
||||
$stmt = OC_DB::prepare('INSERT INTO *PREFIX*gallery_albums (uid_owner, album_name) VALUES (?, ?)');
|
||||
$stmt->execute(array($owner, $name));
|
||||
}
|
||||
|
||||
public static function rename($oldname, $newname, $owner) {
|
||||
$stmt = OC_DB::prepare('UPDATE OR IGNORE *PREFIX*gallery_albums SET album_name=? WHERE uid_owner=? AND album_name=?');
|
||||
$stmt->execute(array($newname, $owner, $oldname));
|
||||
}
|
||||
|
||||
public static function remove($owner, $name=null) {
|
||||
$sql = 'DELETE FROM *PREFIX*gallery_albums WHERE uid_owner = ?';
|
||||
$args = array($owner);
|
||||
if (!is_null($name)){
|
||||
$sql .= ' AND album_name = ?';
|
||||
$args[] = $name;
|
||||
}
|
||||
$stmt = OC_DB::prepare($sql);
|
||||
return $stmt->execute($args);
|
||||
}
|
||||
|
||||
public static function find($owner, $name=null){
|
||||
$sql = 'SELECT * FROM *PREFIX*gallery_albums WHERE uid_owner = ?';
|
||||
$args = array($owner);
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
require_once('../../../lib/base.php');
|
||||
OC_JSON::checkLoggedIn();
|
||||
OC_JSON::checkAppEnabled('gallery');
|
||||
|
||||
function CroppedThumbnail($imgSrc,$thumbnail_width,$thumbnail_height, $tgtImg, $shift) {
|
||||
//getting the image dimensions
|
||||
list($width_orig, $height_orig) = getimagesize($imgSrc);
|
||||
switch (strtolower(substr($imgSrc, strrpos($imgSrc, '.')+1))) {
|
||||
case "jpeg":
|
||||
case "jpg":
|
||||
case "tiff":
|
||||
$myImage = imagecreatefromjpeg($imgSrc);
|
||||
break;
|
||||
case "png":
|
||||
$myImage = imagecreatefrompng($imgSrc);
|
||||
break;
|
||||
default:
|
||||
exit();
|
||||
}
|
||||
$ratio_orig = $width_orig/$height_orig;
|
||||
|
||||
if ($thumbnail_width/$thumbnail_height > $ratio_orig) {
|
||||
$new_height = $thumbnail_width/$ratio_orig;
|
||||
$new_width = $thumbnail_width;
|
||||
} else {
|
||||
$new_width = $thumbnail_height*$ratio_orig;
|
||||
$new_height = $thumbnail_height;
|
||||
}
|
||||
|
||||
$x_mid = $new_width/2; //horizontal middle
|
||||
$y_mid = $new_height/2; //vertical middle
|
||||
|
||||
$process = imagecreatetruecolor(round($new_width), round($new_height));
|
||||
|
||||
imagecopyresampled($process, $myImage, 0, 0, 0, 0, $new_width, $new_height, $width_orig, $height_orig);
|
||||
imagecopyresampled($tgtImg, $process, $shift, 0, ($x_mid-($thumbnail_width/2)), ($y_mid-($thumbnail_height/2)), $thumbnail_width, $thumbnail_height, $thumbnail_width, $thumbnail_height);
|
||||
|
||||
imagedestroy($process);
|
||||
imagedestroy($myImage);
|
||||
}
|
||||
|
||||
?>
|
|
@ -1,12 +1,23 @@
|
|||
<?php
|
||||
|
||||
require_once('base.php'); // base lib
|
||||
require_once('images_utils.php');
|
||||
|
||||
class OC_Gallery_Scanner {
|
||||
|
||||
public static function scan($root) {
|
||||
$albums = array();
|
||||
self::scanDir($root, $albums);
|
||||
return $albums;
|
||||
}
|
||||
|
||||
public static function cleanUp() {
|
||||
$stmt = OC_DB::prepare('DELETE FROM *PREFIX*gallery_albums');
|
||||
$stmt->execute(array());
|
||||
$stmt = OC_DB::prepare('DELETE FROM *PREFIX*gallery_photos');
|
||||
$stmt->execute(array());
|
||||
}
|
||||
|
||||
public static function scanDir($path, &$albums) {
|
||||
$current_album = array('name'=> $path, 'imagesCount' => 0, 'images' => array());
|
||||
$current_album['name'] = str_replace('/', '.', str_replace(OC::$CONFIG_DATADIRECTORY, '', $current_album['name']));
|
||||
|
@ -25,6 +36,7 @@ class OC_Gallery_Scanner {
|
|||
}
|
||||
$current_album['imagesCount'] = count($current_album['images']);
|
||||
$albums[] = $current_album;
|
||||
|
||||
$result = OC_Gallery_Album::find(OC_User::getUser(), $current_album['name']);
|
||||
if ($result->numRows() == 0 && count($current_album['images'])) {
|
||||
OC_Gallery_Album::create(OC_User::getUser(), $current_album['name']);
|
||||
|
@ -38,6 +50,18 @@ class OC_Gallery_Scanner {
|
|||
OC_Gallery_Photo::create($albumId, $img);
|
||||
}
|
||||
}
|
||||
if (count($current_album['images'])) {
|
||||
self::createThumbnail($current_album['name'],$current_album['images']);
|
||||
}
|
||||
}
|
||||
|
||||
public static function createThumbnail($albumName, $files) {
|
||||
$file_count = min(count($files), 10);
|
||||
$thumbnail = imagecreatetruecolor($file_count*200, 200);
|
||||
for ($i = 0; $i < $file_count; $i++) {
|
||||
CroppedThumbnail(OC_Config::getValue("datadirectory").'/'. OC_User::getUser() .'/files/'.$files[$i], 200, 200, $thumbnail, $i*200);
|
||||
}
|
||||
imagepng($thumbnail, OC_Config::getValue("datadirectory").'/'. OC_User::getUser() .'/gallery/' . $albumName.'.png');
|
||||
}
|
||||
|
||||
public static function isPhoto($filename) {
|
||||
|
|
|
@ -15,7 +15,8 @@ OC_Util::addStyle( 'files_imageviewer', 'jquery.fancybox-1.3.4' );
|
|||
</script>
|
||||
|
||||
<div id="controls">
|
||||
<a href="?"><input type="button" value="Back" /></a><br/>
|
||||
<a href="?"><input type="button" value="Back" /></a>
|
||||
<br/>
|
||||
</div>
|
||||
|
||||
<div id="gallery_list" class="leftcontent">
|
||||
|
|
|
@ -71,7 +71,7 @@ $breadcrumb = array();
|
|||
$pathtohere = "";
|
||||
foreach( explode( "/", $dir ) as $i ){
|
||||
if( $i != "" ){
|
||||
$pathtohere .= "/$i";
|
||||
$pathtohere .= "/".urlencode($i);
|
||||
$breadcrumb[] = array( "dir" => $pathtohere, "name" => $i );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -137,7 +137,7 @@ FileActions.register('all','Rename',function(){return OC.imagePath('core','actio
|
|||
});
|
||||
|
||||
FileActions.register('dir','Open','',function(filename){
|
||||
window.location='index.php?dir='+$('#dir').val()+'/'+filename;
|
||||
window.location='index.php?dir='+encodeURIComponent($('#dir').val()).replace(/%2F/g, '/')+'/'+encodeURIComponent(filename);
|
||||
});
|
||||
|
||||
FileActions.setDefault('dir','Open');
|
||||
|
|
|
@ -5,10 +5,10 @@
|
|||
$relative_modified_date = relative_modified_date($file['mtime']);
|
||||
$relative_date_color = round((time()-$file['mtime'])/60/60/24*14); // the older the file, the brighter the shade of grey; days*14
|
||||
if($relative_date_color>200) $relative_date_color = 200; ?>
|
||||
<tr data-file="<?php echo str_replace('+','%20',urlencode($file['name']));?>" data-type="<?php echo ($file['type'] == 'dir')?'dir':'file'?>" data-mime="<?php echo $file['mime']?>" data-size='<?php echo $file['size'];?>'>
|
||||
<tr data-file="<?php echo str_replace('+','%2B',urlencode($file['name']));?>" data-type="<?php echo ($file['type'] == 'dir')?'dir':'file'?>" data-mime="<?php echo $file['mime']?>" data-size='<?php echo $file['size'];?>'>
|
||||
<td class="filename svg" style="background-image:url(<?php if($file['type'] == 'dir') echo mimetype_icon('dir'); else echo mimetype_icon($file['mime']); ?>)">
|
||||
<?php if(!isset($_['readonly']) || !$_['readonly']) { ?><input type="checkbox" /><?php } ?>
|
||||
<a class="name" href="<?php if($file['type'] == 'dir') echo $_['baseURL'].$file['directory'].'/'.$file['name']; else echo $_['downloadURL'].urlencode($file['directory']).'/'.urlencode($file['name']); ?>" title="">
|
||||
<a class="name" href="<?php if($file['type'] == 'dir') echo $_['baseURL'].str_replace('%2F','/',urlencode($file['directory'])).'/'.urlencode($file['name']); else echo $_['downloadURL'].str_replace('%2F','/',urlencode($file['directory'])).'/'.urlencode($file['name']); ?>" title="">
|
||||
<span class="nametext">
|
||||
<?php if($file['type'] == 'dir'):?>
|
||||
<?php echo htmlspecialchars($file['name']);?>
|
||||
|
|
17
index.php
|
@ -100,14 +100,15 @@ else {
|
|||
$error = true;
|
||||
}
|
||||
}
|
||||
// The user is already authenticated using Apaches AuthType Basic... very usable in combination with LDAP
|
||||
elseif(isset($_SERVER["PHP_AUTH_USER"]) && isset($_SERVER["PHP_AUTH_PW"])){
|
||||
if (OC_User::login($_SERVER["PHP_AUTH_USER"],$_SERVER["PHP_AUTH_PW"])) {
|
||||
OC_User::unsetMagicInCookie();
|
||||
OC_Util::redirectToDefaultPage();
|
||||
}else{
|
||||
$error = true;
|
||||
}
|
||||
// The user is already authenticated using Apaches AuthType Basic... very usable in combination with LDAP
|
||||
elseif(isset($_SERVER["PHP_AUTH_USER"]) && isset($_SERVER["PHP_AUTH_PW"])){
|
||||
if (OC_User::login($_SERVER["PHP_AUTH_USER"],$_SERVER["PHP_AUTH_PW"])) {
|
||||
//OC_Log::write('core',"Logged in with HTTP Authentication",OC_Log::DEBUG);
|
||||
OC_User::unsetMagicInCookie();
|
||||
OC_Util::redirectToDefaultPage();
|
||||
}else{
|
||||
$error = true;
|
||||
}
|
||||
}
|
||||
OC_Template::printGuestPage('', 'login', array('error' => $error, 'redirect' => isset($_REQUEST['redirect_url'])?$_REQUEST['redirect_url']:'' ));
|
||||
}
|
||||
|
|