Merge branch 'master' of gitorious.org:owncloud/owncloud into ace-editor
|
@ -2,6 +2,7 @@ ErrorDocument 404 /core/templates/404.php
|
||||||
<IfModule mod_php5.c>
|
<IfModule mod_php5.c>
|
||||||
php_value upload_max_filesize 512M
|
php_value upload_max_filesize 512M
|
||||||
php_value post_max_size 512M
|
php_value post_max_size 512M
|
||||||
|
php_value memory_limit 512M
|
||||||
SetEnv htaccessWorking true
|
SetEnv htaccessWorking true
|
||||||
</IfModule>
|
</IfModule>
|
||||||
RewriteEngine on
|
RewriteEngine on
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
Copyright (C) 2007-2011 Rooftop Solutions.
|
||||||
|
Copyright (C) 2007-2009 FileMobile inc.
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
* Neither the name of the SabreDAV nor the names of its contributors
|
||||||
|
may be used to endorse or promote products derived from this software
|
||||||
|
without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
|
@ -12,8 +12,9 @@ if(!OC_USER::isLoggedIn()) {
|
||||||
}
|
}
|
||||||
OC_JSON::checkAppEnabled('calendar');
|
OC_JSON::checkAppEnabled('calendar');
|
||||||
$calendarid = $_POST['calendarid'];
|
$calendarid = $_POST['calendarid'];
|
||||||
|
$calendar = OC_Calendar_App::getCalendar($calendarid);//access check
|
||||||
OC_Calendar_Calendar::setCalendarActive($calendarid, $_POST['active']);
|
OC_Calendar_Calendar::setCalendarActive($calendarid, $_POST['active']);
|
||||||
$calendar = OC_Calendar_Calendar::findCalendar($calendarid);
|
$calendar = OC_Calendar_App::getCalendar($calendarid);
|
||||||
OC_JSON::success(array(
|
OC_JSON::success(array(
|
||||||
'active' => $calendar['active'],
|
'active' => $calendar['active'],
|
||||||
'eventSource' => OC_Calendar_Calendar::getEventSourceInfo($calendar),
|
'eventSource' => OC_Calendar_Calendar::getEventSourceInfo($calendar),
|
||||||
|
|
|
@ -8,8 +8,6 @@
|
||||||
|
|
||||||
require_once('../../../lib/base.php');
|
require_once('../../../lib/base.php');
|
||||||
|
|
||||||
$l10n = new OC_L10N('calendar');
|
|
||||||
|
|
||||||
// Check if we are a user
|
// Check if we are a user
|
||||||
OC_JSON::checkLoggedIn();
|
OC_JSON::checkLoggedIn();
|
||||||
OC_JSON::checkAppEnabled('calendar');
|
OC_JSON::checkAppEnabled('calendar');
|
||||||
|
@ -17,7 +15,8 @@ OC_JSON::checkAppEnabled('calendar');
|
||||||
$userid = OC_User::getUser();
|
$userid = OC_User::getUser();
|
||||||
$calendarid = OC_Calendar_Calendar::addCalendar($userid, $_POST['name'], 'VEVENT,VTODO,VJOURNAL', null, 0, $_POST['color']);
|
$calendarid = OC_Calendar_Calendar::addCalendar($userid, $_POST['name'], 'VEVENT,VTODO,VJOURNAL', null, 0, $_POST['color']);
|
||||||
OC_Calendar_Calendar::setCalendarActive($calendarid, 1);
|
OC_Calendar_Calendar::setCalendarActive($calendarid, 1);
|
||||||
$calendar = OC_Calendar_Calendar::findCalendar($calendarid);
|
|
||||||
|
$calendar = OC_Calendar_Calendar::find($calendarid);
|
||||||
$tmpl = new OC_Template('calendar', 'part.choosecalendar.rowfields');
|
$tmpl = new OC_Template('calendar', 'part.choosecalendar.rowfields');
|
||||||
$tmpl->assign('calendar', $calendar);
|
$tmpl->assign('calendar', $calendar);
|
||||||
OC_JSON::success(array(
|
OC_JSON::success(array(
|
||||||
|
|
|
@ -7,19 +7,13 @@
|
||||||
*/
|
*/
|
||||||
require_once('../../../lib/base.php');
|
require_once('../../../lib/base.php');
|
||||||
|
|
||||||
$l10n = new OC_L10N('calendar');
|
|
||||||
|
|
||||||
if(!OC_USER::isLoggedIn()) {
|
if(!OC_USER::isLoggedIn()) {
|
||||||
die('<script type="text/javascript">document.location = oc_webroot;</script>');
|
die('<script type="text/javascript">document.location = oc_webroot;</script>');
|
||||||
}
|
}
|
||||||
OC_JSON::checkAppEnabled('calendar');
|
OC_JSON::checkAppEnabled('calendar');
|
||||||
|
|
||||||
$cal = $_POST["calendarid"];
|
$cal = $_POST["calendarid"];
|
||||||
$calendar = OC_Calendar_Calendar::findCalendar($cal);
|
$calendar = OC_Calendar_App::getCalendar($cal);
|
||||||
if($calendar["userid"] != OC_User::getUser()){
|
|
||||||
OC_JSON::error(array('error'=>'permission_denied'));
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
$del = OC_Calendar_Calendar::deleteCalendar($cal);
|
$del = OC_Calendar_Calendar::deleteCalendar($cal);
|
||||||
if($del == true){
|
if($del == true){
|
||||||
OC_JSON::success();
|
OC_JSON::success();
|
||||||
|
|
|
@ -15,17 +15,7 @@ if(!OC_USER::isLoggedIn()) {
|
||||||
OC_JSON::checkAppEnabled('calendar');
|
OC_JSON::checkAppEnabled('calendar');
|
||||||
|
|
||||||
$id = $_POST['id'];
|
$id = $_POST['id'];
|
||||||
$data = OC_Calendar_Object::find($id);
|
$event_object = OC_Calendar_App::getEventObject($id);
|
||||||
if (!$data)
|
|
||||||
{
|
|
||||||
OC_JSON::error();
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
$calendar = OC_Calendar_Calendar::findCalendar($data['calendarid']);
|
|
||||||
if($calendar['userid'] != OC_User::getUser()){
|
|
||||||
OC_JSON::error();
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
$result = OC_Calendar_Object::delete($id);
|
$result = OC_Calendar_Object::delete($id);
|
||||||
OC_JSON::success();
|
OC_JSON::success();
|
||||||
?>
|
?>
|
||||||
|
|
|
@ -7,13 +7,13 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
require_once('../../../lib/base.php');
|
require_once('../../../lib/base.php');
|
||||||
$l10n = new OC_L10N('calendar');
|
|
||||||
if(!OC_USER::isLoggedIn()) {
|
if(!OC_USER::isLoggedIn()) {
|
||||||
die("<script type=\"text/javascript\">document.location = oc_webroot;</script>");
|
die("<script type=\"text/javascript\">document.location = oc_webroot;</script>");
|
||||||
}
|
}
|
||||||
OC_JSON::checkAppEnabled('calendar');
|
OC_JSON::checkAppEnabled('calendar');
|
||||||
|
|
||||||
$calendarcolor_options = OC_Calendar_Calendar::getCalendarColorOptions();
|
$calendarcolor_options = OC_Calendar_Calendar::getCalendarColorOptions();
|
||||||
$calendar = OC_Calendar_Calendar::findCalendar($_GET['calendarid']);
|
$calendar = OC_Calendar_App::getCalendar($_GET['calendarid']);
|
||||||
$tmpl = new OC_Template("calendar", "part.editcalendar");
|
$tmpl = new OC_Template("calendar", "part.editcalendar");
|
||||||
$tmpl->assign('new', false);
|
$tmpl->assign('new', false);
|
||||||
$tmpl->assign('calendarcolor_options', $calendarcolor_options);
|
$tmpl->assign('calendarcolor_options', $calendarcolor_options);
|
||||||
|
|
|
@ -7,9 +7,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
require_once('../../../lib/base.php');
|
require_once('../../../lib/base.php');
|
||||||
|
|
||||||
$l10n = new OC_L10N('calendar');
|
|
||||||
|
|
||||||
if(!OC_USER::isLoggedIn()) {
|
if(!OC_USER::isLoggedIn()) {
|
||||||
die('<script type="text/javascript">document.location = oc_webroot;</script>');
|
die('<script type="text/javascript">document.location = oc_webroot;</script>');
|
||||||
}
|
}
|
||||||
|
@ -23,26 +20,12 @@ if($errarr){
|
||||||
}else{
|
}else{
|
||||||
$id = $_POST['id'];
|
$id = $_POST['id'];
|
||||||
$cal = $_POST['calendar'];
|
$cal = $_POST['calendar'];
|
||||||
$data = OC_Calendar_Object::find($id);
|
$data = OC_Calendar_App::getEventObject($id);
|
||||||
if (!$data)
|
|
||||||
{
|
|
||||||
OC_JSON::error();
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
$calendar = OC_Calendar_Calendar::findCalendar($data['calendarid']);
|
|
||||||
if($calendar['userid'] != OC_User::getUser()){
|
|
||||||
OC_JSON::error();
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
$vcalendar = OC_VObject::parse($data['calendardata']);
|
$vcalendar = OC_VObject::parse($data['calendardata']);
|
||||||
|
|
||||||
$last_modified = $vcalendar->VEVENT->__get('LAST-MODIFIED');
|
OC_Calendar_App::isNotModified($vcalendar->VEVENT, $_POST['lastmodified']);
|
||||||
if($last_modified && $_POST['lastmodified'] != $last_modified->getDateTime()->format('U')){
|
|
||||||
OC_JSON::error(array('modified'=>true));
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
OC_Calendar_Object::updateVCalendarFromRequest($_POST, $vcalendar);
|
OC_Calendar_Object::updateVCalendarFromRequest($_POST, $vcalendar);
|
||||||
|
|
||||||
$result = OC_Calendar_Object::edit($id, $vcalendar->serialize());
|
$result = OC_Calendar_Object::edit($id, $vcalendar->serialize());
|
||||||
if ($data['calendarid'] != $cal) {
|
if ($data['calendarid'] != $cal) {
|
||||||
OC_Calendar_Object::moveToCalendar($id, $cal);
|
OC_Calendar_Object::moveToCalendar($id, $cal);
|
||||||
|
|
|
@ -8,26 +8,16 @@
|
||||||
|
|
||||||
require_once('../../../lib/base.php');
|
require_once('../../../lib/base.php');
|
||||||
|
|
||||||
$l10n = new OC_L10N('calendar');
|
|
||||||
|
|
||||||
if(!OC_USER::isLoggedIn()) {
|
if(!OC_USER::isLoggedIn()) {
|
||||||
die('<script type="text/javascript">document.location = oc_webroot;</script>');
|
die('<script type="text/javascript">document.location = oc_webroot;</script>');
|
||||||
}
|
}
|
||||||
OC_JSON::checkAppEnabled('calendar');
|
OC_JSON::checkAppEnabled('calendar');
|
||||||
|
|
||||||
$calendar_options = OC_Calendar_Calendar::allCalendars(OC_User::getUser());
|
|
||||||
$category_options = OC_Calendar_Object::getCategoryOptions($l10n);
|
|
||||||
$repeat_options = OC_Calendar_Object::getRepeatOptions($l10n);
|
|
||||||
|
|
||||||
$id = $_GET['id'];
|
$id = $_GET['id'];
|
||||||
$data = OC_Calendar_Object::find($id);
|
$data = OC_Calendar_App::getEventObject($id);
|
||||||
$calendar = OC_Calendar_Calendar::findCalendar($data['calendarid']);
|
|
||||||
if($calendar['userid'] != OC_User::getUser()){
|
|
||||||
echo $l10n->t('Wrong calendar');
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
$object = OC_VObject::parse($data['calendardata']);
|
$object = OC_VObject::parse($data['calendardata']);
|
||||||
$vevent = $object->VEVENT;
|
$vevent = $object->VEVENT;
|
||||||
|
|
||||||
$dtstart = $vevent->DTSTART;
|
$dtstart = $vevent->DTSTART;
|
||||||
$dtend = OC_Calendar_Object::getDTEndFromVEvent($vevent);
|
$dtend = OC_Calendar_Object::getDTEndFromVEvent($vevent);
|
||||||
switch($dtstart->getDateType()) {
|
switch($dtstart->getDateType()) {
|
||||||
|
@ -66,6 +56,10 @@ if ($last_modified){
|
||||||
$lastmodified = 0;
|
$lastmodified = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$calendar_options = OC_Calendar_Calendar::allCalendars(OC_User::getUser());
|
||||||
|
$category_options = OC_Calendar_App::getCategoryOptions();
|
||||||
|
$repeat_options = OC_Calendar_App::getRepeatOptions();
|
||||||
|
|
||||||
$tmpl = new OC_Template('calendar', 'part.editevent');
|
$tmpl = new OC_Template('calendar', 'part.editevent');
|
||||||
$tmpl->assign('id', $id);
|
$tmpl->assign('id', $id);
|
||||||
$tmpl->assign('lastmodified', $lastmodified);
|
$tmpl->assign('lastmodified', $lastmodified);
|
||||||
|
|
|
@ -5,31 +5,20 @@
|
||||||
* later.
|
* later.
|
||||||
* See the COPYING-README file.
|
* See the COPYING-README file.
|
||||||
*/
|
*/
|
||||||
error_reporting(E_ALL);
|
|
||||||
require_once('../../../lib/base.php');
|
require_once('../../../lib/base.php');
|
||||||
OC_JSON::checkLoggedIn();
|
OC_JSON::checkLoggedIn();
|
||||||
$data = OC_Calendar_Object::find($_POST["id"]);
|
|
||||||
$calendarid = $data["calendarid"];
|
|
||||||
$cal = $calendarid;
|
|
||||||
$id = $_POST['id'];
|
$id = $_POST['id'];
|
||||||
$calendar = OC_Calendar_Calendar::findCalendar($calendarid);
|
|
||||||
if(OC_User::getUser() != $calendar['userid']){
|
$vcalendar = OC_Calendar_App::getVCalendar($id);
|
||||||
OC_JSON::error();
|
$vevent = $vcalendar->VEVENT;
|
||||||
exit;
|
|
||||||
}
|
|
||||||
$allday = $_POST['allDay'];
|
$allday = $_POST['allDay'];
|
||||||
$delta = new DateInterval('P0D');
|
$delta = new DateInterval('P0D');
|
||||||
$delta->d = $_POST['dayDelta'];
|
$delta->d = $_POST['dayDelta'];
|
||||||
$delta->i = $_POST['minuteDelta'];
|
$delta->i = $_POST['minuteDelta'];
|
||||||
|
|
||||||
$vcalendar = OC_VObject::parse($data['calendardata']);
|
OC_Calendar_App::isNotModified($vevent, $_POST['lastmodified']);
|
||||||
$vevent = $vcalendar->VEVENT;
|
|
||||||
|
|
||||||
$last_modified = $vevent->__get('LAST-MODIFIED');
|
|
||||||
if($last_modified && $_POST['lastmodified'] != $last_modified->getDateTime()->format('U')){
|
|
||||||
OC_JSON::error();
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
$dtstart = $vevent->DTSTART;
|
$dtstart = $vevent->DTSTART;
|
||||||
$dtend = OC_Calendar_Object::getDTEndFromVEvent($vevent);
|
$dtend = OC_Calendar_Object::getDTEndFromVEvent($vevent);
|
||||||
|
@ -50,4 +39,5 @@ $vevent->setDateTime('LAST-MODIFIED', 'now', Sabre_VObject_Element_DateTime::UTC
|
||||||
$vevent->setDateTime('DTSTAMP', 'now', Sabre_VObject_Element_DateTime::UTC);
|
$vevent->setDateTime('DTSTAMP', 'now', Sabre_VObject_Element_DateTime::UTC);
|
||||||
|
|
||||||
$result = OC_Calendar_Object::edit($id, $vcalendar->serialize());
|
$result = OC_Calendar_Object::edit($id, $vcalendar->serialize());
|
||||||
OC_JSON::success(array('lastmodified'=>(int)$now->format('U')));
|
$lastmodified = $vevent->__get('LAST-MODIFIED')->getDateTime();
|
||||||
|
OC_JSON::success(array('lastmodified'=>(int)$lastmodified->format('U')));
|
||||||
|
|
|
@ -8,8 +8,6 @@
|
||||||
|
|
||||||
require_once('../../../lib/base.php');
|
require_once('../../../lib/base.php');
|
||||||
|
|
||||||
$l10n = new OC_L10N('calendar');
|
|
||||||
|
|
||||||
if(!OC_USER::isLoggedIn()) {
|
if(!OC_USER::isLoggedIn()) {
|
||||||
die('<script type="text/javascript">document.location = oc_webroot;</script>');
|
die('<script type="text/javascript">document.location = oc_webroot;</script>');
|
||||||
}
|
}
|
||||||
|
@ -34,8 +32,8 @@ $start->setTimezone(new DateTimeZone($timezone));
|
||||||
$end->setTimezone(new DateTimeZone($timezone));
|
$end->setTimezone(new DateTimeZone($timezone));
|
||||||
|
|
||||||
$calendar_options = OC_Calendar_Calendar::allCalendars(OC_User::getUser());
|
$calendar_options = OC_Calendar_Calendar::allCalendars(OC_User::getUser());
|
||||||
$category_options = OC_Calendar_Object::getCategoryOptions($l10n);
|
$category_options = OC_Calendar_App::getCategoryOptions();
|
||||||
$repeat_options = OC_Calendar_Object::getRepeatOptions($l10n);
|
$repeat_options = OC_Calendar_App::getRepeatOptions();
|
||||||
|
|
||||||
$tmpl = new OC_Template('calendar', 'part.newevent');
|
$tmpl = new OC_Template('calendar', 'part.newevent');
|
||||||
$tmpl->assign('calendar_options', $calendar_options);
|
$tmpl->assign('calendar_options', $calendar_options);
|
||||||
|
|
|
@ -5,45 +5,28 @@
|
||||||
* later.
|
* later.
|
||||||
* See the COPYING-README file.
|
* See the COPYING-README file.
|
||||||
*/
|
*/
|
||||||
error_reporting(E_ALL);
|
|
||||||
require_once('../../../lib/base.php');
|
require_once('../../../lib/base.php');
|
||||||
OC_JSON::checkLoggedIn();
|
OC_JSON::checkLoggedIn();
|
||||||
$data = OC_Calendar_Object::find($_POST["id"]);
|
|
||||||
$calendarid = $data["calendarid"];
|
|
||||||
$cal = $calendarid;
|
|
||||||
$id = $_POST['id'];
|
$id = $_POST['id'];
|
||||||
$calendar = OC_Calendar_Calendar::findCalendar($calendarid);
|
|
||||||
if(OC_User::getUser() != $calendar['userid']){
|
$vcalendar = OC_Calendar_App::getVCalendar($id);
|
||||||
OC_JSON::error();
|
$vevent = $vcalendar->VEVENT;
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
$delta = new DateInterval('P0D');
|
$delta = new DateInterval('P0D');
|
||||||
$delta->d = $_POST['dayDelta'];
|
$delta->d = $_POST['dayDelta'];
|
||||||
$delta->i = $_POST['minuteDelta'];
|
$delta->i = $_POST['minuteDelta'];
|
||||||
|
|
||||||
$vcalendar = OC_Calendar_Object::parse($data['calendardata']);
|
OC_Calendar_App::isNotModified($vevent, $_POST['lastmodified']);
|
||||||
$vevent = $vcalendar->VEVENT;
|
|
||||||
|
|
||||||
$last_modified = $vevent->__get('LAST-MODIFIED');
|
|
||||||
if($last_modified && $_POST['lastmodified'] != $last_modified->getDateTime()->format('U')){
|
|
||||||
OC_JSON::error();
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
$dtend = OC_Calendar_Object::getDTEndFromVEvent($vevent);
|
$dtend = OC_Calendar_Object::getDTEndFromVEvent($vevent);
|
||||||
$end_type = $dtend->getDateType();
|
$end_type = $dtend->getDateType();
|
||||||
$dtend->setDateTime($dtend->getDateTime()->add($delta), $end_type);
|
$dtend->setDateTime($dtend->getDateTime()->add($delta), $end_type);
|
||||||
unset($vevent->DURATION);
|
unset($vevent->DURATION);
|
||||||
|
|
||||||
$now = new DateTime();
|
$vevent->setDateTime('LAST-MODIFIED', 'now', Sabre_VObject_Element_DateTime::UTC);
|
||||||
$last_modified = new Sabre_VObject_Element_DateTime('LAST-MODIFIED');
|
$vevent->setDateTime('DTSTAMP', 'now', Sabre_VObject_Element_DateTime::UTC);
|
||||||
$last_modified->setDateTime($now, Sabre_VObject_Element_DateTime::UTC);
|
|
||||||
$vevent->__set('LAST-MODIFIED', $last_modified);
|
|
||||||
|
|
||||||
$dtstamp = new Sabre_VObject_Element_DateTime('DTSTAMP');
|
|
||||||
$dtstamp->setDateTime($now, Sabre_VObject_Element_DateTime::UTC);
|
|
||||||
$vevent->DTSTAMP = $dtstamp;
|
|
||||||
|
|
||||||
$result = OC_Calendar_Object::edit($id, $vcalendar->serialize());
|
$result = OC_Calendar_Object::edit($id, $vcalendar->serialize());
|
||||||
OC_JSON::success(array('lastmodified'=>$now->format('U')));
|
$lastmodified = $vevent->__get('LAST-MODIFIED')->getDateTime();
|
||||||
|
OC_JSON::success(array('lastmodified'=>(int)$lastmodified->format('U')));
|
||||||
|
|
|
@ -8,16 +8,16 @@
|
||||||
|
|
||||||
require_once('../../../lib/base.php');
|
require_once('../../../lib/base.php');
|
||||||
|
|
||||||
$l10n = new OC_L10N('calendar');
|
|
||||||
|
|
||||||
// Check if we are a user
|
// Check if we are a user
|
||||||
OC_JSON::checkLoggedIn();
|
OC_JSON::checkLoggedIn();
|
||||||
OC_JSON::checkAppEnabled('calendar');
|
OC_JSON::checkAppEnabled('calendar');
|
||||||
|
|
||||||
$calendarid = $_POST['id'];
|
$calendarid = $_POST['id'];
|
||||||
|
$calendar = OC_Calendar_App::getCalendar($calendarid);//access check
|
||||||
OC_Calendar_Calendar::editCalendar($calendarid, $_POST['name'], null, null, null, $_POST['color']);
|
OC_Calendar_Calendar::editCalendar($calendarid, $_POST['name'], null, null, null, $_POST['color']);
|
||||||
OC_Calendar_Calendar::setCalendarActive($calendarid, $_POST['active']);
|
OC_Calendar_Calendar::setCalendarActive($calendarid, $_POST['active']);
|
||||||
$calendar = OC_Calendar_Calendar::findCalendar($calendarid);
|
|
||||||
|
$calendar = OC_Calendar_App::getCalendar($calendarid);
|
||||||
$tmpl = new OC_Template('calendar', 'part.choosecalendar.rowfields');
|
$tmpl = new OC_Template('calendar', 'part.choosecalendar.rowfields');
|
||||||
$tmpl->assign('calendar', $calendar);
|
$tmpl->assign('calendar', $calendar);
|
||||||
OC_JSON::success(array(
|
OC_JSON::success(array(
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
$l=new OC_L10N('calendar');
|
$l=new OC_L10N('calendar');
|
||||||
|
OC::$CLASSPATH['OC_Calendar_App'] = 'apps/calendar/lib/app.php';
|
||||||
OC::$CLASSPATH['OC_Calendar_Calendar'] = 'apps/calendar/lib/calendar.php';
|
OC::$CLASSPATH['OC_Calendar_Calendar'] = 'apps/calendar/lib/calendar.php';
|
||||||
OC::$CLASSPATH['OC_Calendar_Object'] = 'apps/calendar/lib/object.php';
|
OC::$CLASSPATH['OC_Calendar_Object'] = 'apps/calendar/lib/object.php';
|
||||||
OC::$CLASSPATH['OC_Calendar_Hooks'] = 'apps/calendar/lib/hooks.php';
|
OC::$CLASSPATH['OC_Calendar_Hooks'] = 'apps/calendar/lib/hooks.php';
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
#editentry_dialog {display: none;}
|
#editentry_dialog {display: none;}
|
||||||
#parsingfail_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;}
|
#calendar_holder {position: relative;bottom: 0; right: 0; left: 0; top: 3em;}
|
||||||
.fc-content{padding:2px 4px;}
|
.fc-content{padding:2px 4px;}
|
||||||
#listview {margin: 0; padding: 10px; background: #EEEEEE;}
|
#listview {margin: 0; padding: 10px; background: #EEEEEE;}
|
||||||
|
|
|
@ -6,33 +6,25 @@
|
||||||
* See the COPYING-README file.
|
* See the COPYING-README file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
require_once ("../../lib/base.php");
|
require_once ('../../lib/base.php');
|
||||||
OC_Util::checkLoggedIn();
|
OC_Util::checkLoggedIn();
|
||||||
OC_Util::checkAppEnabled('calendar');
|
OC_Util::checkAppEnabled('calendar');
|
||||||
$cal = isset($_GET["calid"]) ? $_GET["calid"] : NULL;
|
$cal = isset($_GET['calid']) ? $_GET['calid'] : NULL;
|
||||||
$event = isset($_GET["eventid"]) ? $_GET["eventid"] : NULL;
|
$event = isset($_GET['eventid']) ? $_GET['eventid'] : NULL;
|
||||||
if(isset($cal)){
|
if(isset($cal)){
|
||||||
$calendar = OC_Calendar_Calendar::findCalendar($cal);
|
$calendar = OC_Calendar_App::getCalendar($cal);
|
||||||
if($calendar["userid"] != OC_User::getUser()){
|
|
||||||
OC_JSON::error();
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
$calobjects = OC_Calendar_Object::all($cal);
|
$calobjects = OC_Calendar_Object::all($cal);
|
||||||
header("Content-Type: text/Calendar");
|
header('Content-Type: text/Calendar');
|
||||||
header("Content-Disposition: inline; filename=calendar.ics");
|
header('Content-Disposition: inline; filename=' . $calendar['displayname'] . '.ics');
|
||||||
for($i = 0;$i <= count($calobjects); $i++){
|
foreach($calobjects as $calobject){
|
||||||
echo $calobjects[$i]["calendardata"] . "\n";
|
echo $calobject['calendardata'] . '\n';
|
||||||
}
|
}
|
||||||
}elseif(isset($event)){
|
}elseif(isset($event)){
|
||||||
$data = OC_Calendar_Object::find($_GET["eventid"]);
|
$data = OC_Calendar_App::getEventObject($_GET['eventid']);
|
||||||
$calendarid = $data["calendarid"];
|
$calendarid = $data['calendarid'];
|
||||||
$calendar = OC_Calendar_Calendar::findCalendar($calendarid);
|
$calendar = OC_Calendar_App::getCalendar($calendarid);
|
||||||
if($calendar["userid"] != OC_User::getUser()){
|
header('Content-Type: text/Calendar');
|
||||||
OC_JSON::error();
|
header('Content-Disposition: inline; filename=' . $data['summary'] . '.ics');
|
||||||
exit;
|
echo $data['calendardata'];
|
||||||
}
|
|
||||||
header("Content-Type: text/Calendar");
|
|
||||||
header("Content-Disposition: inline; filename=" . $data["summary"] . ".ics");
|
|
||||||
echo $data["calendardata"];
|
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
|
|
|
@ -12,11 +12,7 @@ OC_Util::checkAppEnabled('calendar');
|
||||||
|
|
||||||
if($_GET["import"] == "existing"){
|
if($_GET["import"] == "existing"){
|
||||||
$calid = $_GET["calid"];
|
$calid = $_GET["calid"];
|
||||||
$calendar = OC_Calendar_Calendar::findCalendar($calid);
|
$calendar = OC_Calendar_App::getCalendar($calid);
|
||||||
if($calendar['userid'] != OC_User::getUser()){
|
|
||||||
OC_JSON::error();
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
if($_GET["path"] != ""){
|
if($_GET["path"] != ""){
|
||||||
$filename = $_GET["path"] . "/" . $_GET["file"];
|
$filename = $_GET["path"] . "/" . $_GET["file"];
|
||||||
}else{
|
}else{
|
||||||
|
|
|
@ -8,7 +8,15 @@
|
||||||
|
|
||||||
Calendar={
|
Calendar={
|
||||||
UI:{
|
UI:{
|
||||||
|
loading: function(isLoading){
|
||||||
|
if (isLoading){
|
||||||
|
$('#loading').show();
|
||||||
|
}else{
|
||||||
|
$('#loading').hide();
|
||||||
|
}
|
||||||
|
},
|
||||||
startEventDialog:function(){
|
startEventDialog:function(){
|
||||||
|
Calendar.UI.loading(false);
|
||||||
$('.tipsy').remove();
|
$('.tipsy').remove();
|
||||||
$('#calendar_holder').fullCalendar('unselect');
|
$('#calendar_holder').fullCalendar('unselect');
|
||||||
Calendar.UI.lockTime();
|
Calendar.UI.lockTime();
|
||||||
|
@ -41,6 +49,7 @@ Calendar={
|
||||||
// TODO: save event
|
// TODO: save event
|
||||||
$('#event').dialog('destroy').remove();
|
$('#event').dialog('destroy').remove();
|
||||||
}else{
|
}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);
|
$('#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
|
// TODO: save event
|
||||||
$('#event').dialog('destroy').remove();
|
$('#event').dialog('destroy').remove();
|
||||||
}else{
|
}else{
|
||||||
|
Calendar.UI.loading(true);
|
||||||
$('#dialog_holder').load(OC.filePath('calendar', 'ajax', 'editeventform.php') + '?id=' + id, Calendar.UI.startEventDialog);
|
$('#dialog_holder').load(OC.filePath('calendar', 'ajax', 'editeventform.php') + '?id=' + id, Calendar.UI.startEventDialog);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
submitDeleteEventForm:function(url){
|
submitDeleteEventForm:function(url){
|
||||||
var post = $( '#event_form' ).serialize();
|
var post = $( '#event_form' ).serialize();
|
||||||
$('#errorbox').empty();
|
$('#errorbox').empty();
|
||||||
|
Calendar.UI.loading(true);
|
||||||
$.post(url, post, function(data){
|
$.post(url, post, function(data){
|
||||||
|
Calendar.UI.loading(false);
|
||||||
if(data.status == 'success'){
|
if(data.status == 'success'){
|
||||||
$('#calendar_holder').fullCalendar('removeEvents', $('#event_form input[name=id]').val());
|
$('#calendar_holder').fullCalendar('removeEvents', $('#event_form input[name=id]').val());
|
||||||
$('#event').dialog('destroy').remove();
|
$('#event').dialog('destroy').remove();
|
||||||
|
@ -69,8 +81,10 @@ Calendar={
|
||||||
validateEventForm:function(url){
|
validateEventForm:function(url){
|
||||||
var post = $( "#event_form" ).serialize();
|
var post = $( "#event_form" ).serialize();
|
||||||
$("#errorbox").empty();
|
$("#errorbox").empty();
|
||||||
|
Calendar.UI.loading(true);
|
||||||
$.post(url, post,
|
$.post(url, post,
|
||||||
function(data){
|
function(data){
|
||||||
|
Calendar.UI.loading(false);
|
||||||
if(data.status == "error"){
|
if(data.status == "error"){
|
||||||
var output = missing_field + ": <br />";
|
var output = missing_field + ": <br />";
|
||||||
if(data.title == "true"){
|
if(data.title == "true"){
|
||||||
|
@ -107,8 +121,10 @@ Calendar={
|
||||||
},
|
},
|
||||||
moveEvent:function(event, dayDelta, minuteDelta, allDay, revertFunc){
|
moveEvent:function(event, dayDelta, minuteDelta, allDay, revertFunc){
|
||||||
$('.tipsy').remove();
|
$('.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},
|
$.post(OC.filePath('calendar', 'ajax', 'moveevent.php'), { id: event.id, dayDelta: dayDelta, minuteDelta: minuteDelta, allDay: allDay?1:0, lastmodified: event.lastmodified},
|
||||||
function(data) {
|
function(data) {
|
||||||
|
Calendar.UI.loading(false);
|
||||||
if (data.status == 'success'){
|
if (data.status == 'success'){
|
||||||
event.lastmodified = data.lastmodified;
|
event.lastmodified = data.lastmodified;
|
||||||
console.log("Event moved successfully");
|
console.log("Event moved successfully");
|
||||||
|
@ -120,8 +136,10 @@ Calendar={
|
||||||
},
|
},
|
||||||
resizeEvent:function(event, dayDelta, minuteDelta, revertFunc){
|
resizeEvent:function(event, dayDelta, minuteDelta, revertFunc){
|
||||||
$('.tipsy').remove();
|
$('.tipsy').remove();
|
||||||
|
Calendar.UI.loading(true);
|
||||||
$.post(OC.filePath('calendar', 'ajax', 'resizeevent.php'), { id: event.id, dayDelta: dayDelta, minuteDelta: minuteDelta, lastmodified: event.lastmodified},
|
$.post(OC.filePath('calendar', 'ajax', 'resizeevent.php'), { id: event.id, dayDelta: dayDelta, minuteDelta: minuteDelta, lastmodified: event.lastmodified},
|
||||||
function(data) {
|
function(data) {
|
||||||
|
Calendar.UI.loading(false);
|
||||||
if (data.status == 'success'){
|
if (data.status == 'success'){
|
||||||
event.lastmodified = data.lastmodified;
|
event.lastmodified = data.lastmodified;
|
||||||
console.log("Event resized successfully");
|
console.log("Event resized successfully");
|
||||||
|
@ -210,6 +228,7 @@ Calendar={
|
||||||
if($('#choosecalendar_dialog').dialog('isOpen') == true){
|
if($('#choosecalendar_dialog').dialog('isOpen') == true){
|
||||||
$('#choosecalendar_dialog').dialog('moveToTop');
|
$('#choosecalendar_dialog').dialog('moveToTop');
|
||||||
}else{
|
}else{
|
||||||
|
Calendar.UI.loading(true);
|
||||||
$('#dialog_holder').load(OC.filePath('calendar', 'ajax', 'choosecalendar.php'), function(){
|
$('#dialog_holder').load(OC.filePath('calendar', 'ajax', 'choosecalendar.php'), function(){
|
||||||
$('#choosecalendar_dialog').dialog({
|
$('#choosecalendar_dialog').dialog({
|
||||||
width : 600,
|
width : 600,
|
||||||
|
@ -217,13 +236,16 @@ Calendar={
|
||||||
$(this).dialog('destroy').remove();
|
$(this).dialog('destroy').remove();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
Calendar.UI.loading(false);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
activation:function(checkbox, calendarid)
|
activation:function(checkbox, calendarid)
|
||||||
{
|
{
|
||||||
|
Calendar.UI.loading(true);
|
||||||
$.post(OC.filePath('calendar', 'ajax', 'activation.php'), { calendarid: calendarid, active: checkbox.checked?1:0 },
|
$.post(OC.filePath('calendar', 'ajax', 'activation.php'), { calendarid: calendarid, active: checkbox.checked?1:0 },
|
||||||
function(data) {
|
function(data) {
|
||||||
|
Calendar.UI.loading(false);
|
||||||
if (data.status == 'success'){
|
if (data.status == 'success'){
|
||||||
checkbox.checked = data.active == 1;
|
checkbox.checked = data.active == 1;
|
||||||
if (data.active == 1){
|
if (data.active == 1){
|
||||||
|
@ -520,6 +542,7 @@ $(document).ready(function(){
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
loading: Calendar.UI.loading,
|
||||||
eventSources: eventSources
|
eventSources: eventSources
|
||||||
});
|
});
|
||||||
$('#oneweekview_radio').click(function(){
|
$('#oneweekview_radio').click(function(){
|
||||||
|
|
|
@ -0,0 +1,82 @@
|
||||||
|
<?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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class manages our app actions
|
||||||
|
*/
|
||||||
|
OC_Calendar_App::$l10n = new OC_L10N('calendar');
|
||||||
|
class OC_Calendar_App{
|
||||||
|
public static $l10n;
|
||||||
|
|
||||||
|
public static function getCalendar($id){
|
||||||
|
$calendar = OC_Calendar_Calendar::find( $id );
|
||||||
|
if( $calendar === false || $calendar['userid'] != OC_User::getUser()){
|
||||||
|
OC_JSON::error(array('data' => array('message' => self::$l10n->t('Wrong calendar'))));
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
return $calendar;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getEventObject($id){
|
||||||
|
$event_object = OC_Calendar_Object::find( $id );
|
||||||
|
if( $event_object === false ){
|
||||||
|
OC_JSON::error();
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
self::getCalendar( $event_object['calendarid'] );//access check
|
||||||
|
return $event_object;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getVCalendar($id){
|
||||||
|
$event_object = self::getEventObject( $id );
|
||||||
|
|
||||||
|
$vcalendar = OC_VObject::parse($event_object['calendardata']);
|
||||||
|
// Check if the vcalendar is valid
|
||||||
|
if(is_null($vcalendar)){
|
||||||
|
OC_JSON::error();
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
return $vcalendar;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function isNotModified($vevent, $lastmodified)
|
||||||
|
{
|
||||||
|
$last_modified = $vevent->__get('LAST-MODIFIED');
|
||||||
|
if($last_modified && $lastmodified != $last_modified->getDateTime()->format('U')){
|
||||||
|
OC_JSON::error(array('modified'=>true));
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getCategoryOptions()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
self::$l10n->t('Birthday'),
|
||||||
|
self::$l10n->t('Business'),
|
||||||
|
self::$l10n->t('Call'),
|
||||||
|
self::$l10n->t('Clients'),
|
||||||
|
self::$l10n->t('Deliverer'),
|
||||||
|
self::$l10n->t('Holidays'),
|
||||||
|
self::$l10n->t('Ideas'),
|
||||||
|
self::$l10n->t('Journey'),
|
||||||
|
self::$l10n->t('Jubilee'),
|
||||||
|
self::$l10n->t('Meeting'),
|
||||||
|
self::$l10n->t('Other'),
|
||||||
|
self::$l10n->t('Personal'),
|
||||||
|
self::$l10n->t('Projects'),
|
||||||
|
self::$l10n->t('Questions'),
|
||||||
|
self::$l10n->t('Work'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getRepeatOptions()
|
||||||
|
{
|
||||||
|
OC_Calendar_Object::getRepeatOptions(self::$l10n);
|
||||||
|
}
|
||||||
|
}
|
|
@ -82,7 +82,7 @@ class OC_Calendar_Calendar{
|
||||||
* @param integer $id
|
* @param integer $id
|
||||||
* @return associative array
|
* @return associative array
|
||||||
*/
|
*/
|
||||||
public static function findCalendar($id){
|
public static function find($id){
|
||||||
$stmt = OC_DB::prepare( 'SELECT * FROM *PREFIX*calendar_calendars WHERE id = ?' );
|
$stmt = OC_DB::prepare( 'SELECT * FROM *PREFIX*calendar_calendars WHERE id = ?' );
|
||||||
$result = $stmt->execute(array($id));
|
$result = $stmt->execute(array($id));
|
||||||
|
|
||||||
|
@ -148,7 +148,7 @@ class OC_Calendar_Calendar{
|
||||||
*/
|
*/
|
||||||
public static function editCalendar($id,$name=null,$components=null,$timezone=null,$order=null,$color=null){
|
public static function editCalendar($id,$name=null,$components=null,$timezone=null,$order=null,$color=null){
|
||||||
// Need these ones for checking uri
|
// Need these ones for checking uri
|
||||||
$calendar = self::findCalendar($id);
|
$calendar = self::find($id);
|
||||||
|
|
||||||
// Keep old stuff
|
// Keep old stuff
|
||||||
if(is_null($name)) $name = $calendar['name'];
|
if(is_null($name)) $name = $calendar['name'];
|
||||||
|
|
|
@ -367,7 +367,7 @@ class OC_Calendar_Object{
|
||||||
$errarr['title'] = 'true';
|
$errarr['title'] = 'true';
|
||||||
$errnum++;
|
$errnum++;
|
||||||
}
|
}
|
||||||
$calendar = OC_Calendar_Calendar::findCalendar($request['calendar']);
|
$calendar = OC_Calendar_Calendar::find($request['calendar']);
|
||||||
if($calendar['userid'] != OC_User::getUser()){
|
if($calendar['userid'] != OC_User::getUser()){
|
||||||
$errarr['cal'] = 'true';
|
$errarr['cal'] = 'true';
|
||||||
$errnum++;
|
$errnum++;
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
var missing_field_dberror = '<?php echo $l->t('There was a database fail') ?>';
|
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';
|
var totalurl = '<?php echo OC_Helper::linkTo('apps/calendar', 'caldav.php', null, true); ?>/calendars';
|
||||||
</script>
|
</script>
|
||||||
|
<div id="loading"><img src="<?php echo OC_Helper::imagePath('core', 'loading.gif'); ?>" /></div>
|
||||||
<div id="controls">
|
<div id="controls">
|
||||||
<div>
|
<div>
|
||||||
<form>
|
<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
|
// Init owncloud
|
||||||
require_once('../../../lib/base.php');
|
require_once('../../../lib/base.php');
|
||||||
|
|
||||||
|
$l10n = new OC_L10N('contacts');
|
||||||
// Check if we are a user
|
// Check if we are a user
|
||||||
OC_JSON::checkLoggedIn();
|
OC_JSON::checkLoggedIn();
|
||||||
OC_JSON::checkAppEnabled('contacts');
|
OC_JSON::checkAppEnabled('contacts');
|
||||||
|
|
||||||
$id = $_GET['id'];
|
//$id = $_GET['id'];
|
||||||
|
$id = $_POST['id'];
|
||||||
$addressbook = OC_Contacts_App::getAddressbook( $id );
|
$addressbook = OC_Contacts_App::getAddressbook( $id );
|
||||||
|
|
||||||
OC_Contacts_Addressbook::delete($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,3 +1,4 @@
|
||||||
|
#chooseaddressbook {margin-right: 170px; float: right;}
|
||||||
#contacts_details_name { font-weight:bold;font-size:1.1em;margin-left:25%;}
|
#contacts_details_name { font-weight:bold;font-size:1.1em;margin-left:25%;}
|
||||||
#contacts_details_photo { margin:.5em 0em .5em 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){
|
function contacts_namesort($a,$b){
|
||||||
return strcmp($a['name'],$b['name']);
|
return strcmp($a['fullname'],$b['fullname']);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init owncloud
|
// Init owncloud
|
||||||
|
@ -31,17 +31,8 @@ require_once('../../lib/base.php');
|
||||||
OC_Util::checkLoggedIn();
|
OC_Util::checkLoggedIn();
|
||||||
OC_Util::checkAppEnabled('contacts');
|
OC_Util::checkAppEnabled('contacts');
|
||||||
|
|
||||||
// Check if the user has an addressbook
|
// Get active address books. This creates a default one if none exists.
|
||||||
$addressbooks = OC_Contacts_Addressbook::all(OC_User::getUser());
|
$addressbooks = OC_Contacts_Addressbook::active(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);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load the files we need
|
// Load the files we need
|
||||||
OC_App::setActiveNavigationEntry( 'contacts_index' );
|
OC_App::setActiveNavigationEntry( 'contacts_index' );
|
||||||
|
@ -51,17 +42,15 @@ $id = isset( $_GET['id'] ) ? $_GET['id'] : null;
|
||||||
|
|
||||||
// sort addressbooks (use contactsort)
|
// sort addressbooks (use contactsort)
|
||||||
usort($addressbooks,'contacts_namesort');
|
usort($addressbooks,'contacts_namesort');
|
||||||
// Addressbooks to load
|
|
||||||
$openaddressbooks = explode(';',$prefbooks);
|
|
||||||
|
|
||||||
$contacts = array();
|
$contacts = array();
|
||||||
foreach( $openaddressbooks as $addressbook ){
|
foreach( $addressbooks as $addressbook ){
|
||||||
$addressbookcontacts = OC_Contacts_VCard::all($addressbook);
|
$addressbookcontacts = OC_Contacts_VCard::all($addressbook['id']);
|
||||||
foreach( $addressbookcontacts as $contact ){
|
foreach( $addressbookcontacts as $contact ){
|
||||||
if(is_null($contact['fullname'])){
|
if(is_null($contact['fullname'])){
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
$contacts[] = array( 'name' => $contact['fullname'], 'id' => $contact['id'] );
|
$contacts[] = $contact;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,11 +63,20 @@ if( !is_null($id)/* || count($contacts)*/){
|
||||||
$details = OC_Contacts_VCard::structureContact($vcard);
|
$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');
|
$adr_types = OC_Contacts_App::getTypesOfProperty('ADR');
|
||||||
$phone_types = OC_Contacts_App::getTypesOfProperty('TEL');
|
$phone_types = OC_Contacts_App::getTypesOfProperty('TEL');
|
||||||
|
|
||||||
// Process the template
|
// Process the template
|
||||||
$tmpl = new OC_Template( 'contacts', 'index', 'user' );
|
$tmpl = new OC_Template( 'contacts', 'index', 'user' );
|
||||||
|
$tmpl->assign('property_types',$property_types);
|
||||||
$tmpl->assign('adr_types',$adr_types);
|
$tmpl->assign('adr_types',$adr_types);
|
||||||
$tmpl->assign('phone_types',$phone_types);
|
$tmpl->assign('phone_types',$phone_types);
|
||||||
$tmpl->assign('addressbooks', $addressbooks);
|
$tmpl->assign('addressbooks', $addressbooks);
|
||||||
|
|
|
@ -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(){
|
$(document).ready(function(){
|
||||||
/*-------------------------------------------------------------------------
|
/*-------------------------------------------------------------------------
|
||||||
* Event handlers
|
* Event handlers
|
||||||
|
@ -79,6 +194,11 @@ $(document).ready(function(){
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$('#chooseaddressbook').click(function(){
|
||||||
|
Contacts.UI.Addressbooks.overview();
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
$('#contacts_newcontact').click(function(){
|
$('#contacts_newcontact').click(function(){
|
||||||
$.getJSON('ajax/showaddcard.php',{},function(jsondata){
|
$.getJSON('ajax/showaddcard.php',{},function(jsondata){
|
||||||
if(jsondata.status == 'success'){
|
if(jsondata.status == 'success'){
|
||||||
|
|
|
@ -44,7 +44,7 @@ class OC_Contacts_Addressbook{
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public static function all($uid){
|
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));
|
$result = $stmt->execute(array($uid));
|
||||||
|
|
||||||
$addressbooks = array();
|
$addressbooks = array();
|
||||||
|
@ -140,12 +140,98 @@ class OC_Contacts_Addressbook{
|
||||||
return true;
|
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
|
* @brief removes an address book
|
||||||
* @param integer $id
|
* @param integer $id
|
||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
public static function delete($id){
|
public static function delete($id){
|
||||||
|
self::setActive($id, false);
|
||||||
$stmt = OC_DB::prepare( 'DELETE FROM *PREFIX*contacts_addressbooks WHERE id = ?' );
|
$stmt = OC_DB::prepare( 'DELETE FROM *PREFIX*contacts_addressbooks WHERE id = ?' );
|
||||||
$stmt->execute(array($id));
|
$stmt->execute(array($id));
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,7 @@ class OC_Contacts_App{
|
||||||
|
|
||||||
public static function getAddressbook($id){
|
public static function getAddressbook($id){
|
||||||
$addressbook = OC_Contacts_Addressbook::find( $id );
|
$addressbook = OC_Contacts_Addressbook::find( $id );
|
||||||
if( $addressbook === false || $addressbook['userid'] != OC_USER::getUser()){
|
if( $addressbook === false || $addressbook['userid'] != OC_User::getUser()){
|
||||||
OC_JSON::error(array('data' => array( 'message' => self::$l10n->t('This is not your addressbook.')))); // Same here (as with the contact error). Could this error be improved?
|
OC_JSON::error(array('data' => array( 'message' => self::$l10n->t('This is not your addressbook.')))); // Same here (as with the contact error). Could this error be improved?
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,15 +47,15 @@ class OC_Contacts_VCard{
|
||||||
* ['carddata']
|
* ['carddata']
|
||||||
*/
|
*/
|
||||||
public static function all($id){
|
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));
|
$result = $stmt->execute(array($id));
|
||||||
|
|
||||||
$addressbooks = array();
|
$cards = array();
|
||||||
while( $row = $result->fetchRow()){
|
while( $row = $result->fetchRow()){
|
||||||
$addressbooks[] = $row;
|
$cards[] = $row;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $addressbooks;
|
return $cards;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,16 +1,14 @@
|
||||||
<?php // Include Style and Script
|
<script type='text/javascript'>
|
||||||
OC_Util::addScript('contacts','interface');
|
var totalurl = '<?php echo OC_Helper::linkTo('contacts', 'carddav.php', null, true); ?>/addressbooks';
|
||||||
OC_Util::addStyle('contacts','styles');
|
</script>
|
||||||
OC_Util::addStyle('contacts','formtastic');
|
|
||||||
?>
|
|
||||||
|
|
||||||
<div id="controls">
|
<div id="controls">
|
||||||
<form>
|
<form>
|
||||||
<input type="button" id="contacts_newcontact" value="<?php echo $l->t('Add Contact'); ?>">
|
<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>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<div id="leftcontent" class="leftcontent">
|
<div id="leftcontent" class="leftcontent">
|
||||||
<ul>
|
<ul id="contacts">
|
||||||
<?php echo $this->inc("part.contacts"); ?>
|
<?php echo $this->inc("part.contacts"); ?>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
@ -24,3 +22,9 @@ OC_Util::addStyle('contacts','formtastic');
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
</div>
|
</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 ): ?>
|
<?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; ?>
|
<?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>
|
|
@ -20,7 +20,7 @@
|
||||||
<span style="display:none;" data-use="delete"><img class="svg action" src="<?php echo image_path('', 'actions/delete.svg'); ?>" /></span>
|
<span style="display:none;" data-use="delete"><img class="svg action" src="<?php echo image_path('', 'actions/delete.svg'); ?>" /></span>
|
||||||
</p>
|
</p>
|
||||||
<?php elseif($_['property']['name'] == 'TEL'): ?>
|
<?php elseif($_['property']['name'] == 'TEL'): ?>
|
||||||
<p class="contacts_property_name"><?php echo $_['property']['parameters']['PREF'] ? $l->t('Preferred').' ' : '' ?><?php echo $l->t('Phone'); ?></p>
|
<p class="contacts_property_name"><?php echo (isset($_['property']['parameters']['PREF']) && $_['property']['parameters']['PREF']) ? $l->t('Preferred').' ' : '' ?><?php echo $l->t('Phone'); ?></p>
|
||||||
<p class="contacts_property_data">
|
<p class="contacts_property_data">
|
||||||
<?php echo $_['property']['value']; ?>
|
<?php echo $_['property']['value']; ?>
|
||||||
<?php if(isset($_['property']['parameters']['TYPE']) && !empty($_['property']['parameters']['TYPE'])): ?>
|
<?php if(isset($_['property']['parameters']['TYPE']) && !empty($_['property']['parameters']['TYPE'])): ?>
|
||||||
|
|
|
@ -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');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
|
@ -19,6 +19,7 @@ $source = dirname($source);
|
||||||
while ($source != "" && $source != "/" && $source != "." && $source != $userDirectory) {
|
while ($source != "" && $source != "/" && $source != "." && $source != $userDirectory) {
|
||||||
if ($values = OC_Share::getMySharedItem($source)) {
|
if ($values = OC_Share::getMySharedItem($source)) {
|
||||||
$values = array_values($values);
|
$values = array_values($values);
|
||||||
|
$users = array();
|
||||||
$parentUsers = array();
|
$parentUsers = array();
|
||||||
for ($i = 0; $i < count($values); $i++) {
|
for ($i = 0; $i < count($values); $i++) {
|
||||||
if ($values[$i]['uid_shared_with'] == OC_Share::PUBLICLINK) {
|
if ($values[$i]['uid_shared_with'] == OC_Share::PUBLICLINK) {
|
||||||
|
|
|
@ -285,7 +285,9 @@ class OC_Filestorage_Shared extends OC_Filestorage {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function is_writeable($path) {
|
public function is_writeable($path) {
|
||||||
if ($path == "" || $path == "/" || OC_Share::getPermissions($this->datadir.$path) & OC_Share::WRITE) {
|
if($path == "" || $path == "/"){
|
||||||
|
return false;
|
||||||
|
}elseif (OC_Share::getPermissions($this->datadir.$path) & OC_Share::WRITE) {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -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');
|
OC_JSON::checkAppEnabled('gallery');
|
||||||
|
|
||||||
$a = array();
|
$a = array();
|
||||||
|
|
||||||
$result = OC_Gallery_Album::find(OC_User::getUser());
|
$result = OC_Gallery_Album::find(OC_User::getUser());
|
||||||
|
|
||||||
while ($r = $result->fetchRow()) {
|
while ($r = $result->fetchRow()) {
|
||||||
$album_name = $r['album_name'];
|
$album_name = $r['album_name'];
|
||||||
$tmp_res = OC_Gallery_Photo::find($r['album_id']);
|
$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));
|
OC_JSON::success(array('albums'=>$a));
|
||||||
|
|
|
@ -4,7 +4,7 @@ require_once('../../../lib/base.php');
|
||||||
OC_JSON::checkLoggedIn();
|
OC_JSON::checkLoggedIn();
|
||||||
OC_JSON::checkAppEnabled('gallery');
|
OC_JSON::checkAppEnabled('gallery');
|
||||||
|
|
||||||
|
OC_Gallery_Scanner::cleanUp();
|
||||||
OC_JSON::success(array('albums' => OC_Gallery_Scanner::scan('')));
|
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;
|
display: inline-block;
|
||||||
margin: 5pt;
|
margin: 5pt;
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
|
padding: 10px;
|
||||||
|
border: solid 1px black;
|
||||||
|
position: relative;
|
||||||
}
|
}
|
||||||
.leftcontent div#gallery_album_box {
|
.leftcontent div#gallery_album_box {
|
||||||
margin: 5px;
|
margin: 5px;
|
||||||
|
@ -21,13 +24,28 @@ div#gallery_album_box {
|
||||||
|
|
||||||
div#gallery_album_box h1 {
|
div#gallery_album_box h1 {
|
||||||
font-size: 12pt;
|
font-size: 12pt;
|
||||||
font-family: Arial;
|
font-family: Verdana;
|
||||||
}
|
}
|
||||||
|
|
||||||
div#gallery_album_cover {
|
div#gallery_album_cover {
|
||||||
width: 199px;
|
width: 199px;
|
||||||
height: 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 {
|
#gallery_images {
|
||||||
|
|
|
@ -5,6 +5,12 @@ OC_Util::checkLoggedIn();
|
||||||
OC_Util::checkAppEnabled('gallery');
|
OC_Util::checkAppEnabled('gallery');
|
||||||
OC_App::setActiveNavigationEntry( 'gallery_index' );
|
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'])) {
|
if (!isset($_GET['view'])) {
|
||||||
$result = OC_Gallery_Album::find(OC_User::getUser());
|
$result = OC_Gallery_Album::find(OC_User::getUser());
|
||||||
|
|
|
@ -4,7 +4,7 @@ $(document).ready(function() {
|
||||||
if (r.status == 'success') {
|
if (r.status == 'success') {
|
||||||
for (var i in r.albums) {
|
for (var i in r.albums) {
|
||||||
var a = r.albums[i];
|
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');
|
var targetDiv = document.getElementById('gallery_list');
|
||||||
if (targetDiv) {
|
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,
|
// album with the same name wont be insered,
|
||||||
// and false will be returned
|
// and false will be returned
|
||||||
// true on success
|
// true on success
|
||||||
add: function(album_name, num) {
|
add: function(album_name, num, bgPath) {
|
||||||
for (var a in Albums.albums) {
|
for (var a in Albums.albums) {
|
||||||
if (a.name == album_name) {
|
if (a.name == album_name) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Albums.albums.push({name: album_name, numOfCovers: num});
|
Albums.albums.push({name: album_name, numOfCovers: num, backgroundPath: bgPath});
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
// remove element with given name
|
// remove element with given name
|
||||||
|
@ -57,24 +57,38 @@ Albums={
|
||||||
// displays gallery in linear representation
|
// displays gallery in linear representation
|
||||||
// on given element, and apply default styles for gallery
|
// on given element, and apply default styles for gallery
|
||||||
display: function(element) {
|
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) {
|
for (var i in Albums.albums) {
|
||||||
var a = Albums.albums[i];
|
var a = Albums.albums[i];
|
||||||
var local = $(displayTemplate.replace(/\*NAME\*/g, a.name));
|
var local = $(displayTemplate.replace(/\*NAME\*/g, a.name));
|
||||||
local.css('background-repeat', 'no-repeat');
|
$("#gallery_album_cover", local).css('background-repeat', 'no-repeat');
|
||||||
local.css('background-position', '0 0');
|
$("#gallery_album_cover", local).css('background-position', '0');
|
||||||
local.css('background-image','url("ajax/getCovers.php?album_name='+a.name+'")');
|
$("#gallery_album_cover", local).css('background-image','url("ajax/getCovers.php?album_name='+a.name+'")');
|
||||||
local.mousemove(function(e) {
|
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);
|
var albumMetadata = Albums.find(this.title);
|
||||||
if (albumMetadata == undefined) {
|
if (albumMetadata == undefined) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var x = Math.min(Math.floor((e.clientX - this.offsetLeft)/(this.offsetWidth/albumMetadata.numOfCovers)), albumMetadata.numOfCovers-1);
|
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');
|
$(this).css('background-position', -x+'px 0');
|
||||||
});
|
});
|
||||||
$(element).append(local);
|
$(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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,23 @@ class OC_Gallery_Album{
|
||||||
$stmt = OC_DB::prepare('INSERT INTO *PREFIX*gallery_albums (uid_owner, album_name) VALUES (?, ?)');
|
$stmt = OC_DB::prepare('INSERT INTO *PREFIX*gallery_albums (uid_owner, album_name) VALUES (?, ?)');
|
||||||
$stmt->execute(array($owner, $name));
|
$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){
|
public static function find($owner, $name=null){
|
||||||
$sql = 'SELECT * FROM *PREFIX*gallery_albums WHERE uid_owner = ?';
|
$sql = 'SELECT * FROM *PREFIX*gallery_albums WHERE uid_owner = ?';
|
||||||
$args = array($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
|
<?php
|
||||||
|
|
||||||
|
require_once('base.php'); // base lib
|
||||||
|
require_once('images_utils.php');
|
||||||
|
|
||||||
class OC_Gallery_Scanner {
|
class OC_Gallery_Scanner {
|
||||||
|
|
||||||
public static function scan($root) {
|
public static function scan($root) {
|
||||||
$albums = array();
|
$albums = array();
|
||||||
self::scanDir($root, $albums);
|
self::scanDir($root, $albums);
|
||||||
return $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) {
|
public static function scanDir($path, &$albums) {
|
||||||
$current_album = array('name'=> $path, 'imagesCount' => 0, 'images' => array());
|
$current_album = array('name'=> $path, 'imagesCount' => 0, 'images' => array());
|
||||||
$current_album['name'] = str_replace('/', '.', str_replace(OC::$CONFIG_DATADIRECTORY, '', $current_album['name']));
|
$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']);
|
$current_album['imagesCount'] = count($current_album['images']);
|
||||||
$albums[] = $current_album;
|
$albums[] = $current_album;
|
||||||
|
|
||||||
$result = OC_Gallery_Album::find(OC_User::getUser(), $current_album['name']);
|
$result = OC_Gallery_Album::find(OC_User::getUser(), $current_album['name']);
|
||||||
if ($result->numRows() == 0 && count($current_album['images'])) {
|
if ($result->numRows() == 0 && count($current_album['images'])) {
|
||||||
OC_Gallery_Album::create(OC_User::getUser(), $current_album['name']);
|
OC_Gallery_Album::create(OC_User::getUser(), $current_album['name']);
|
||||||
|
@ -38,6 +50,18 @@ class OC_Gallery_Scanner {
|
||||||
OC_Gallery_Photo::create($albumId, $img);
|
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) {
|
public static function isPhoto($filename) {
|
||||||
|
|
|
@ -15,7 +15,8 @@ OC_Util::addStyle( 'files_imageviewer', 'jquery.fancybox-1.3.4' );
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div id="controls">
|
<div id="controls">
|
||||||
<a href="?"><input type="button" value="Back" /></a><br/>
|
<a href="?"><input type="button" value="Back" /></a>
|
||||||
|
<br/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="gallery_list" class="leftcontent">
|
<div id="gallery_list" class="leftcontent">
|
||||||
|
|
|
@ -14,7 +14,7 @@ if (isset($_POST['user'])) {
|
||||||
if (OC_User::userExists($_POST['user'])) {
|
if (OC_User::userExists($_POST['user'])) {
|
||||||
$token = sha1($_POST['user']+uniqId());
|
$token = sha1($_POST['user']+uniqId());
|
||||||
OC_Preferences::setValue($_POST['user'], 'owncloud', 'lostpassword', $token);
|
OC_Preferences::setValue($_POST['user'], 'owncloud', 'lostpassword', $token);
|
||||||
$email = OC_Preferences::getValue($_POST['user'], 'lostpassword', 'email', '');
|
$email = OC_Preferences::getValue($_POST['user'], 'settings', 'email', '');
|
||||||
if (!empty($email)) {
|
if (!empty($email)) {
|
||||||
$link = OC_Helper::linkTo('core/lostpassword', 'resetpassword.php', null, true).'?user='.$_POST['user'].'&token='.$token;
|
$link = OC_Helper::linkTo('core/lostpassword', 'resetpassword.php', null, true).'?user='.$_POST['user'].'&token='.$token;
|
||||||
$tmpl = new OC_Template('core/lostpassword', 'email');
|
$tmpl = new OC_Template('core/lostpassword', 'email');
|
||||||
|
|
|
@ -9,7 +9,7 @@ OC_JSON::checkLoggedIn();
|
||||||
$dir = isset( $_GET['dir'] ) ? $_GET['dir'] : '';
|
$dir = isset( $_GET['dir'] ) ? $_GET['dir'] : '';
|
||||||
$foldername = isset( $_GET['foldername'] ) ? $_GET['foldername'] : '';
|
$foldername = isset( $_GET['foldername'] ) ? $_GET['foldername'] : '';
|
||||||
|
|
||||||
if($foldername == '') {
|
if(trim($foldername) == '') {
|
||||||
OC_JSON::error(array("data" => array( "message" => "Empty Foldername" )));
|
OC_JSON::error(array("data" => array( "message" => "Empty Foldername" )));
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,9 +14,10 @@ if (!isset($_FILES['files'])) {
|
||||||
}
|
}
|
||||||
foreach ($_FILES['files']['error'] as $error) {
|
foreach ($_FILES['files']['error'] as $error) {
|
||||||
if ($error != 0) {
|
if ($error != 0) {
|
||||||
|
$l=new OC_L10N('files');
|
||||||
$errors = array(
|
$errors = array(
|
||||||
0=>$l->t("There is no error, the file uploaded with success"),
|
0=>$l->t("There is no error, the file uploaded with success"),
|
||||||
1=>$l->t("The uploaded file exceeds the upload_max_filesize directive in php.ini"),
|
1=>$l->t("The uploaded file exceeds the upload_max_filesize directive in php.ini").ini_get('upload_max_filesize'),
|
||||||
2=>$l->t("The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form"),
|
2=>$l->t("The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form"),
|
||||||
3=>$l->t("The uploaded file was only partially uploaded"),
|
3=>$l->t("The uploaded file was only partially uploaded"),
|
||||||
4=>$l->t("No file was uploaded"),
|
4=>$l->t("No file was uploaded"),
|
||||||
|
|
|
@ -71,7 +71,7 @@ $breadcrumb = array();
|
||||||
$pathtohere = "";
|
$pathtohere = "";
|
||||||
foreach( explode( "/", $dir ) as $i ){
|
foreach( explode( "/", $dir ) as $i ){
|
||||||
if( $i != "" ){
|
if( $i != "" ){
|
||||||
$pathtohere .= "/$i";
|
$pathtohere .= "/".urlencode($i);
|
||||||
$breadcrumb[] = array( "dir" => $pathtohere, "name" => $i );
|
$breadcrumb[] = array( "dir" => $pathtohere, "name" => $i );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -97,6 +97,7 @@ $tmpl = new OC_Template( "files", "index", "user" );
|
||||||
$tmpl->assign( "fileList", $list->fetchPage() );
|
$tmpl->assign( "fileList", $list->fetchPage() );
|
||||||
$tmpl->assign( "breadcrumb", $breadcrumbNav->fetchPage() );
|
$tmpl->assign( "breadcrumb", $breadcrumbNav->fetchPage() );
|
||||||
$tmpl->assign( 'dir', $dir);
|
$tmpl->assign( 'dir', $dir);
|
||||||
|
$tmpl->assign( 'readonly', !OC_Filesystem::is_writeable($dir));
|
||||||
$tmpl->assign( "files", $files );
|
$tmpl->assign( "files", $files );
|
||||||
$tmpl->assign( 'uploadMaxFilesize', $maxUploadFilesize);
|
$tmpl->assign( 'uploadMaxFilesize', $maxUploadFilesize);
|
||||||
$tmpl->assign( 'uploadMaxHumanFilesize', OC_Helper::humanFileSize($maxUploadFilesize));
|
$tmpl->assign( 'uploadMaxHumanFilesize', OC_Helper::humanFileSize($maxUploadFilesize));
|
||||||
|
|