From a78f370c457a008140b5f492d911c95677a035c0 Mon Sep 17 00:00:00 2001 From: "vincent@cubedesigners.com" Date: Fri, 24 Jan 2014 14:39:24 +0000 Subject: [PATCH] --- inc/ws/Controlleur/class.ws.maintenance.php | 32 +- inc/ws/DAO/class.ws.dao.book.php | 1 - inc/ws/Metier/class.ws.document.php | 1849 +++++++++---------- 3 files changed, 951 insertions(+), 931 deletions(-) diff --git a/inc/ws/Controlleur/class.ws.maintenance.php b/inc/ws/Controlleur/class.ws.maintenance.php index bbcac4f28..801a72dbd 100644 --- a/inc/ws/Controlleur/class.ws.maintenance.php +++ b/inc/ws/Controlleur/class.ws.maintenance.php @@ -829,12 +829,9 @@ class wsMaintenance { } else { return; } - if (!$value) { return; } - - $newlinks = array(); foreach ($links as $link) { $link[$k]+=$value; @@ -845,6 +842,31 @@ class wsMaintenance { $dao->setLinksAndRulers($book_id, json_encode($newlinks), json_encode($rulers), 'Offset links positions (' . $direction . ' :: ' . $value . ')', $core->user->utilisateur_id); } -} + public function extractTexts($args) { + global $core; + $book_id = $args[0]; + $dao = new wsDAOBook($core->con); + $book = $dao->selectById($book_id); + $pages = $dao->getPagesOfBook($book_id); -?> \ No newline at end of file + $docs = array(); + foreach ($pages as $p) { + $docs[] = $p['document_id']; + } + $docs = array_unique($docs); + + foreach ($docs as $doc) { + $out = WS_DOCS . '/' . $doc . '/'; + + $fwstk = new cubeCommandLine('fwstk'); + $fwstk->setPath(CONVERTER_PATH); + $fwstk->setArg('--input ' . $out . '/crop.pdf'); + $fwstk->setArg('--extractTexts ' . $out . '%s%d.txt'); + if ($book->parametres->ignoreSearchSeparators != '') { + $fwstk->setArg('--ignoreSeparators ' . $book->parametres->ignoreSearchSeparators); + } + $fwstk->execute(); + } + } + +} diff --git a/inc/ws/DAO/class.ws.dao.book.php b/inc/ws/DAO/class.ws.dao.book.php index 5cd60abcf..0c8549e76 100644 --- a/inc/ws/DAO/class.ws.dao.book.php +++ b/inc/ws/DAO/class.ws.dao.book.php @@ -855,7 +855,6 @@ class wsDAOBook extends commonDAO { } ksort($index); - $textes = json_encode($textes); $index = json_encode($index); diff --git a/inc/ws/Metier/class.ws.document.php b/inc/ws/Metier/class.ws.document.php index 044e0cd80..3bdd425e7 100644 --- a/inc/ws/Metier/class.ws.document.php +++ b/inc/ws/Metier/class.ws.document.php @@ -1,926 +1,925 @@ - 2, 100 => 2, 150 => 3, 200 => 3, 300 => 3, 450 => 4, 600 => 5); - // Number section styles - protected static - $numberStyles = array('NoNumber' => 'no', 'DecimalArabicNumerals' => 'decimal', - 'UppercaseRomanNumerals' => 'roman_up', 'LowercaseRomanNumerals' => 'roman_low', - 'UppercaseLetters' => 'letters_up', 'LowercaseLetters' => 'letters_low'); - - public function init() { - $this->out = WS_DOCS . '/' . $this->document_id . '/'; - $this->log = $this->out . '/logs/'; - $this->html = $this->out . '/html/'; - $this->in = $this->out . 'original.pdf'; - $this->uncompressed = $this->out . 'uncompressed.pdf'; - $this->infos = $this->out . 'infos.txt'; - if (!file_exists($this->out)) { - mkdir($this->out, 0755, true); - mkdir($this->log, 0755); - } - if (!file_exists($this->html)) { - mkdir($this->html, 0755); - } - $this->cropped = $this->out . 'crop.pdf'; - $this->pages_log_pointers = array(); - - if (is_null($this->conversionInfos)) { - $this->conversionInfos = new wsDocumentConversionInfos(); - } - } - - public function copyOriginalFromUpload($tmp_file) { - move_uploaded_file($tmp_file, $this->in); - } - - public function copyOriginalFromOlderVersion() { - if (!file_exists($this->in)) { - copy('http://ws.fluidbook.com/docs/' . $this->document_id . '/original.pdf', $this->in); - } - } - - public function extractFonts() { - $extractor = new wsPDFFontExtractor($this->out, $this); - $extractor->extract(); - } - - public function getInfos($in = null, $force = false) { - if (is_null($in)) { - $in = $this->in; - } - - $fwstk = new cubeCommandLine('fwstk'); - $fwstk->setPath(CONVERTER_PATH); - $fwstk->setArg('--input ' . $in); - $fwstk->setArg('--infos'); - $fwstk->execute(); - $this->addToLog($fwstk); - $out = $fwstk->output; - - $pdfinfo = new cubeCommandLine('pdfinfo'); - $pdfinfo->setPath(CONVERTER_PATH); - $pdfinfo->setArg('-box'); - $pdfinfo->setArg('f', 1); - $pdfinfo->setArg('l', 100000); - $pdfinfo->setArg(null, $in); - $pdfinfo->execute(); - $this->addToLog($pdfinfo); - $out.="\n"; - $out.=$pdfinfo->output; - - $this->parseInfos($out); - - $this->conversionInfos->setPageNumber($this->generalInfos['pages']); - - file_put_contents($this->infos, $out); - $this->findCutDisposition(); - } - - public function findCutDisposition() { - $this->detectSpreads(); - $this->detectPageDifferences(); - } - - protected function detectPageDifferences() { - // Vérifie si la cropbox et la trimbox sont identiques pour toutes les pages - $difference = false; - foreach ($this->generalInfos['page'] as $page => $infos) { - if (!isset($infos['crop']) || !isset($infos['crop'])) { - continue; - } - if ($infos['crop'] != $infos['trim']) { - $difference = true; - } - } - if (!$difference) { - return false; - } - // Vérifie si la trimbox définie toutes les pages de la même taille - $heights = array(); - $widths = array(); - foreach ($this->generalInfos['page'] as $page => $infos) { - $heights[] = round($infos['trim']->height); - $widths[] = round($infos['trim']->width); - } - $heights = array_unique($heights); - $widths = array_unique($widths); - if (count($heights) == 1 && count($widths) == 1) { - $this->autocrop = 'trim'; - $this->manualcrop = false; - } else { - $this->autocrop = false; - $this->manualcrop = true; - } - } - - protected function detectSpreads() { - // Détection des spreads - - $this->autocut = false; - $this->manualcut = false; - if ($this->generalInfos['pages'] <= 2) { - return; - } - - foreach ($this->generalInfos['page'] as $page => $infos) { - if ($page == 1) { - $first = $infos['size']; - } elseif ($page == $this->generalInfos['pages']) { - $last = $infos['size']; - } elseif ($page == 2) { - $second = $infos['size']; - } - } - - if ($first == $last && $last == $second) { - $ratio = $first[0] / $first[1]; - $this->autocut = false; - if ($ratio <= 1) { - $this->manualcut = false; - } elseif ($ratio >= 6) { - $this->manualcut = 'L8'; - } elseif ($ratio >= 3) { - $this->manualcut = 'L4'; - } elseif ($ratio >= 2) { - $this->manualcut = 'L3'; - } else { - $this->manualcut = '14-23'; - } - return; - } - $this->manualcut = false; - if (self::compareSizes($last, $first) && cubeMath::compare($first[0] * 2, $second[0], 0.9)) { - $this->autocut = '1-23-4'; - } - if (cubeMath::compare($first[0] * 2, $second[0], 0.9) && self::compareSizes($last, $second)) { - $this->autocut = '1-23'; - } - - $this->addToLog('Detect Spreads : Manual cut ' . $this->manualcut . ' ; Auto cut : ' . $this->autocut); - } - - public static function compareSizes($x, $y, $tolerance = 0.9) { - return cubeMath::compare($x[0], $y[0], $tolerance) && cubeMath::compare($x[1], $y[1], $tolerance); - } - - public function parseInfos($data) { - // This function get general infos (pages sizes, boxes, number sections and - // bookmarks - // Init arrays - $this->generalInfos = array(); - $this->generalInfos['size'] = array(0, 0); - $this->bookmarks = array(); - $this->numberSections = ''; - $bookmark_id = 0; - - $res['size'] = array(0, 0); - $lines = explode("\n", $data); - foreach ($lines as $line) { - $line = trim(cubeText::condenseWhite($line)); - $e = explode(':', $line, 2); - $k = trim($e[0]); - if (count($e) < 2) { - continue; - } - $v = trim($e[1]); - if ($k == 'Pages' || $k == 'NumberOfPages') { - $this->pages = $this->generalInfos['pages'] = $v; - $this->generalInfos['page'] = array(); - for ($i = 1; $i <= $this->pages; $i++) { - $this->generalInfos['page'][$i] = array(); - } - } elseif (preg_match('|Page\s+([0-9]+)\s+(.*)Box:\s+([0-9.]*)\s+([0-9.]*)\s+([0-9.]*)\s+([0-9.]*)|iu', $line, $m)) { - $this->generalInfos['page'][$m[1]][strtolower($m[2])] = new wsBox($m[3], $m[4], $m[5], $m[6]); - } elseif (preg_match('|Page\s+([0-9]+)\s+size:\s+([0-9.]*)[pts[:space:]]+x\s+([0-9.]*)\s+pts|iu', $line, $m)) { - $this->generalInfos['page'][$m[1]]['size'] = array($m[2], $m[3]); - if ($m[1] == 1) { - $this->generalInfos['size'][0] = $m[2]; - $this->generalInfos['size'][1] = $m[3]; - } - } elseif ($k == 'BookmarkTitle') { - $this->bookmarks[$bookmark_id] = array('titre' => str_replace(' ', '', trim($v))); - } elseif ($k == 'BookmarkLevel') { - $this->bookmarks[$bookmark_id]['level'] = $v; - } elseif ($k == 'BookmarkPageNumber') { - $this->bookmarks[$bookmark_id]['page'] = $v; - $bookmark_id++; - } elseif ($k == 'NumberSections') { - $this->numberSections = $v; - } - } - - return $res; - } - - public function getPagesNumber() { - $this->getInfos(); - return $this->generalInfos['pages']; - } - - public function globalOperations() { - $this->getInfos(); - if ($this->CropAndCut()) { - $this->getInfos($this->cropped, true); - } - $this->getLinksAndTexts(); - } - - public function CropAndCut() { - if (!$this->isCropped()) { - copy($this->in, $this->cropped); - return false; - } - if ($this->autocrop == 'trim') { - $this->trimDocument(); - } else { - copy($this->in, $this->cropped); - } - - if ($this->autocut) { - $this->cutDocument($this->autocut); - return true; - } - return false; - } - - public function cutDocument($mode) { - $fwstk = new cubeCommandLine('fwstk'); - $fwstk->setPath(CONVERTER_PATH); - $fwstk->setArg('--input ' . $this->in); - $fwstk->setArg('--cut ' . $mode); - $fwstk->setArg('--output ' . $this->cropped); - $fwstk->execute(); - $this->addToLog($fwstk); - } - - public function trimDocument() { - $fwstk = new cubeCommandLine('fwstk'); - $fwstk->setPath(CONVERTER_PATH); - $fwstk->setArg('--input ' . $this->in); - $fwstk->setArg('--trim'); - $fwstk->setArg('--output ' . $this->cropped); - $fwstk->execute(); - $this->addToLog($fwstk); - } - - public function processOnePage($page, $force = true) { - if ($force) { - $this->addToLog('Processing page #' . $page); - $this->makeMiniShot($page); - $this->makeSWFFiles($page); - $this->makeHTML5Files($page); - } - } - - public function processAllPages() { - for ($i = 1; $i <= $this->generalInfos['pages']; $i++) { - $this->processOnePage($i); - } - $this->optimizeSVG(); - } - - public function optimizeSVG() { - - - - $scour = new cubeCommandLine('scour.php'); - $scour->setPath(CONVERTER_PATH); - $scour->setNohup(true); - $scour->setArg(null, $this->html); - $scour->execute(); - } - - public function processRange($pages) { - foreach ($pages as $i) { - $this->processOnePage($i); - } - $this->optimizeSVG(); - } - - public function getLinksAndTexts() { - $fwstk = new cubeCommandLine('fwstk'); - $fwstk->setPath(CONVERTER_PATH); - $fwstk->setArg('--input ' . $this->cropped); - $fwstk->setArg('--extractTexts ' . $this->out . '%s%d.txt'); - $fwstk->setArg('--extractLinks ' . $this->out . 'p%d.csv'); - $fwstk->execute(); - $this->addToLog($fwstk); - - /* $fwstk = new cubeCommandLine('fwstk'); - $fwstk->setPath(CONVERTER_PATH); - $fwstk->setArg('--input ' . $this->cropped); - $fwstk->setArg('--layout ' . $this->html . 'p%d.layout'); - $fwstk->setArg('--cmaps ' . $this->html); - $fwstk->setArg('--fonts' . $this->out . 'fonts/web/'); - $fwstk->execute(); - $this->addToLog($fwstk); */ - } - - public function makeMiniShot($page) { - $this->makeShotFixedWidth($page, 'p', 100, 90, 4, 'PNM'); - } - - public function makeShotFixedWidth($page, $prefix = '', $w = 100, $quality = 90, $antialiasing = 4, $method = 'PNM') { - // Make thumbs of $w width - // resolution 72 make 1pt=1px - $width = $this->generalInfos['size'][0]; - $ratio = $width / $w; - $this->makeShot($page, $prefix, round(72 / $ratio, 2), $quality, $antialiasing, $method); - } - - public function makeShotFixedHeight($page, $prefix = '', $h = '', $quality = 90, $antialiasing = 4, $method = 'PNM') { - // Make thumbs of $w height - // resolution 72 make 1pt=1px - $height = $this->generalInfos['size'][1]; - $ratio = $height / $h; - $this->makeShot($page, $prefix, round(72 / $ratio, 2), $quality, $antialiasing, $method); - } - - public function makeShot($page, $prefix = '', $resolution = 72, $quality = 90, $antialiasing = 4, $method = 'PNM', $in = null) { - $error = false; - if (is_null($in)) { - $in = $this->cropped; - } - // Delete all old files - $res = $this->out . $prefix . $page . '.jpg'; - if (file_exists($res)) { - @unlink($res); - } - - if ($method == 'GS') { - $this->makeShotGS($page, $prefix, $resolution, $quality, $antialiasing, $in); - } elseif ($method == 'PNM') { - $this->makeShotPNM($page, $prefix, $resolution, $quality, $antialiasing, $in); - } - // Test the result by checking all files - if (!file_exists($res)) { - $error = true; - } - // If error, we try to make thumbs with other method - if ($error) { - if ($method == 'GS') { - $this->makeShotPNM($page, $prefix, $resolution, $quality, $antialiasing, $in); - } elseif ($method == 'PNM') { - $this->makeShotGS($page, $prefix, $resolution, $quality, $antialiasing, $in); - } - } - } - - protected function makeShotGS($page, $prefix = '', $resolution = 72, $quality = 90, $antialiasing = 4, $in = null) { - if (is_null($in)) { - $in = $this->cropped; - } - // Fabrication des thumbanails avec ghostscript - $gs = new cubeCommandLine('gs', null, true); - $gs->setPath(CONVERTER_PATH); - $gs->setEnv('GS_FONTPATH', FONT_PATH); - $gs->setArg('-dBATCH'); - $gs->setArg('-dNOPAUSE'); - $gs->setArg('-dNOPROMPT'); - // Antialias - $gs->setArg('-dDOINTERPOLATE'); - $gs->setArg('-dTextAlphaBits=' . $antialiasing); - $gs->setArg('-dGraphicsAlphaBits=' . $antialiasing); - // Device - $gs->setArg('-sDEVICE=jpeg'); - // Dispotion & colors - // $gs->setArg('-dUseCIEColor'); - $gs->setArg('-dAutoRotatePages=/None'); - $gs->setArg('-dUseCropBox'); - // Resolution & Quality - $gs->setArg('-r' . round($resolution)); - $gs->setArg('-dJPEGQ=' . $quality); - // Performances - $gs->setArg('-dNumRenderingThreads=4'); - // Page range - $gs->setArg('-dFirstPage=' . $page); - $gs->setArg('-dLastPage=' . $page); - // Files - $gs->setArg('-sOutputFile=' . $this->out . '/' . $prefix . $page . '.jpg'); - - $gs->setArg(null, $in); - $gs->execute(); - $this->addToLog($gs, true, $page); - } - - protected function makeShotPNM($page, $prefix = '', $resolution = 72, $quality = 90, $antialiasing = 4, $in = null, $texts = true) { - if (is_null($in)) { - $in = $this->cropped; - } - - $tmp = cubeFiles::tempnam(); - - $antialiasing = $antialiasing ? 'yes' : 'no'; - $freetype = $texts ? 'yes' : 'no'; - $resolution = $resolution; - // Exporte les fichiers - $pdftoppm = new cubeCommandLine('pdftoppm', null, true); - $pdftoppm->setPath(CONVERTER_PATH); - - $pdftoppm->setArg('f', $page); - $pdftoppm->setArg('l', $page); - $pdftoppm->setArg('-cropbox'); - $pdftoppm->setArg('-freetype ' . $freetype); - $pdftoppm->setArg('-singlefile'); - $pdftoppm->setArg('-aa ' . $antialiasing); - $pdftoppm->setArg('-aaVector ' . $antialiasing); - $pdftoppm->setArg('r', $resolution); - $pdftoppm->setArg(null, $in); - $pdftoppm->setArg(null, $tmp); - $pdftoppm->execute(); - $this->addToLog($pdftoppm, true, $page); - - $tmp.='.ppm'; - - $jpegfile = $this->out . $prefix . $page . '.jpg'; - - - if (file_exists($tmp)) { - $pnmtojpeg = new cubeCommandLine('pnmtojpeg', $jpegfile, false); - $pnmtojpeg->setArg('-quality ' . $quality); - $pnmtojpeg->setArg(null, $tmp); - $pnmtojpeg->execute(); - $this->addToLog($pnmtojpeg, false, $page); - - unlink($tmp); - } - } - - protected function isCropped() { - return $this->autocrop || $this->manualcrop || $this->autocut || $this->manualcut; - } - - public function makeSWFFiles($page, $resolution = null, $quality = null, $storeAllChars = null, $maxObjects = null, $method = null, $version = null) { - $conversionSettings = $this->conversionInfos->pages[$page]; - if (is_null($storeAllChars)) { - $storeAllChars = true; - } - if (is_null($resolution)) { - $resolution = $conversionSettings->resolution; - } - if (is_null($method)) { - $method = $conversionSettings->method; - } - if (is_null($quality)) { - $quality = $conversionSettings->quality; - } - if (is_null($maxObjects)) { - $maxObjects = $conversionSettings->objects; - } - if (is_null($version)) { - $version = isset($conversionSettings->version) ? $conversionSettings->version : 'stable'; - } - - if ($maxObjects <= 1) { - $method = self::POLY2BITMAP; - } - - // Pour les fichiers croppés, on utilise la méthode flatten qui ne prends - // pas en compte les objets hors de la box - if ($this->isCropped()) { - // $method = max($method, self::FLATTEN); - } - - $out = $this->pdf2swf($page, $resolution, $quality, $storeAllChars, $method, 'p', $version); - if ($method < self::BARBARE_PNM) { - // Analyse de la sortie pour détecter des typos manquantes - $overflow = false; - $overflowObjects = false; - $written = false; - $missing_fonts = array(); - if (file_exists($out)) { - $fp = fopen($out, 'rb'); - while ($line = fgets($fp)) { - if (preg_match('|Try putting a TTF version of that font \(named \"([A-Z-_0-9.]*)\"\)|Uui', trim($line), $matches)) { - $missing_fonts[] = $matches[1]; - } elseif (stristr($line, 'ID Table overflow')) { - $overflow = true; - } elseif (stristr($line, 'NOTICE SWF written')) { - $written = true; - } elseif (stristr($line, 'NOTICE Writing SWF file')) { - $written = true; - } - } - } - if (!is_null($page) && file_exists($this->out . 'p' . $page . '.swf')) { - $written = true; - } - // On teste si le fichier est écrit et qu'il a été généré par le premier niveau - if ($method < self::POLY2BITMAP && $written) { - $overflowObjects = $this->checkObjectsNumber($this->out . 'p' . $page . '.swf', $maxObjects, $page); - } - - if (!$written || $overflow || $overflowObjects) { - if ($method == self::MAX) { - return; - } - $nextMethod = $method + 1; - return $this->makeSWFFiles($page, $resolution, $quality, $storeAllChars, $maxObjects, $nextMethod, $version); - } - } - } - - public function makeHTML5Files($page) { - // Then make HD background shots - $resolutions = array(300 => 85, 150 => 85, 36 => 85); - foreach ($resolutions as $r => $q) { - $this->makeShotPNM($page, 'html/h' . $r . '-', $r, $q, 4, null, false); - $this->makeShotPNM($page, 'html/t' . $r . '-', $r, $q, 4, null, true); - } - $this->makeSVGFile($page); - } - - public function makeSVGFile($page) { - $svgFile = $this->out . '/html/p' . $page . '.svg'; - $svgOpt = $this->out . '/html/o' . $page . '.svg'; - - $pdftocairo = new cubeCommandLine('pdftocairo'); - $pdftocairo->setPath(CONVERTER_PATH); - $pdftocairo->setArg('f', $page); - $pdftocairo->setArg('l', $page); - $pdftocairo->setArg(null, '-svg'); - $pdftocairo->setArg(null, '-cropbox'); - $pdftocairo->setArg(null, $this->cropped); - $pdftocairo->setArg(null, $svgFile); - $pdftocairo->execute(); - $this->addToLog($pdftocairo, true, $page); - - $this->_cleanSVG($svgFile); - } - - protected function _cleanSVG($svgFile) { - $svg = new DOMDocument(); - $svg->preserveWhiteSpace = false; - $svg->load($svgFile); - - // Operations to delete - $xpath = new DOMXPath($svg); - $xpath->registerNamespace('svg', 'http://www.w3.org/2000/svg'); - $xpath->registerNamespace('xlink', 'http://www.w3.org/1999/xlink'); - $xpath->registerNamespace("php", "http://php.net/xpath"); - $xpath->registerPhpFunctions('has_not_text'); - $toDelete = array('//svg:defs/svg:clipPath', - '//svg:defs/svg:image', - '//svg:defs/svg:pattern', - '/svg:svg/svg:g/svg:g[not(svg:use[@xlink:href])]', - '/svg:svg/svg:g/svg:path', - '/svg:svg/svg:g/svg:rect', - ); - - global $svglog; - $svglog = array('XPATH : ' . print_r($xpath, true)); - foreach ($toDelete as $q) { - $list = $xpath->query($q); - $svglog[] = "Evaluate xpath query " . $q; - $svglog[] = 'Give ' . $list->length . ' results'; - $svglog[] = 'Deleting Nodes in ' . print_r($list, true); - if (count($list)) { - foreach ($list as $node) { - - /* @var $node DOMNode */ - $parent = $node->parentNode; - $parent->removeChild($node); - } - } - } - - $this->addToLog(implode("\n", $svglog), false, $page); - file_put_contents($svgFile, $svg->saveXML()); - } - - protected function checkObjectsNumber($file, $maxObjects, $page) { - $swfdump = new cubeCommandLine('swfdump', null, true); - $swfdump->setPath(CONVERTER_PATH); - $swfdump->setArg(null, $file); - $swfdump->execute(); - $this->addToLog($swfdump, true, $page); - - str_replace('[01a]', '', $swfdump->output, $nbObjects); - if ($nbObjects > $maxObjects) { - return true; - } - return false; - } - - protected function dumpSWF($page, $prefix = 'p') { - $swfdump = new cubeCommandLine('/usr/local/swftools/special-swfdump/bin/swfdump', null, true); - $swfdump->setPath(CONVERTER_PATH); - $swfdump->setArg('t'); - $swfdump->setArg('p'); - $swfdump->setArg('F'); - $swfdump->setArg(null, $this->out . $prefix . $page . '.swf'); - $swfdump->execute(); - $this->addToLog($swfdump, false, $page); - return $swfdump->output; - } - - /** - * wsDocument::pdf2swf() - * - * @param mixed $page - * @param integer $resolution - * @param integer $quality - * @param mixed $storeAllChars - * @param integer $method - * @return - */ - protected function pdf2swf($page, $resolution = 150, $quality = 90, $storeAllChars = true, $method = 0, $prefix = 'p', $version = 'stable') { - /* - -h , --help Print short help message and exit - -V , --version Print version info and exit - -o , --output file.swf Direct output to file.swf. If file.swf contains '%' (file%.swf), then each page goes to a seperate file. - -p , --pages range Convert only pages in range with range e.g. 1-20 or 1,4,6,9-11 or - -P , --password password Use password for deciphering the pdf. - -v , --verbose Be verbose. Use more than one -v for greater effect. - -z , --zlib Use Flash 6 (MX) zlib compression. - -i , --ignore Allows pdf2swf to change the draw order of the pdf. This may make the generated - -j , --jpegquality quality Set quality of embedded jpeg pictures to quality. 0 is worst (small), 100 is best (big). (default:85) - -s , --set param=value Set a SWF encoder specific parameter. See pdf2swf -s help for more information. - -w , --samewindow When converting pdf hyperlinks, don't make the links open a new window. - -t , --stop Insert a stop() command in each page. - -T , --flashversion num Set Flash Version in the SWF header to num. - -F , --fontdir directory Add directory to the font search path. - -b , --defaultviewer Link a standard viewer to the swf file. - -l , --defaultloader Link a standard preloader to the swf file which will be displayed while the main swf is loading. - -B , --viewer filename Link viewer filename to the swf file. - -L , --preloader filename Link preloader filename to the swf file. - -q , --quiet Suppress normal messages. Use -qq to suppress warnings, also. - -S , --shapes Don't use SWF Fonts, but store everything as shape. - -f , --fonts Store full fonts in SWF. (Don't reduce to used characters). - -G , --flatten Remove as many clip layers from file as possible. - -I , --info Don't do actual conversion, just display a list of all pages in the PDF. - -Q , --maxtime n Abort conversion after n seconds. Only availableon Unix. - - PDF device global parameters: - ----------------------------- - fontdir= a directory with additional fonts - font= an additional font filename - pages= the range of pages to convert (example: pages=1-100,210-) - zoom= the resultion (default: 72) - languagedir= Add an xpdf language directory - multiply= Render everything at the resolution - poly2bitmap Convert graphics to bitmaps - bitmap Convert everything to bitmaps - - SWF Parameters : - ---------------- - SWF layer options : - ------------------- - - jpegsubpixels= resolution adjustment for jpeg images (same as jpegdpi, but in pixels) - ppmsubpixels= shortcut for setting both jpegsubpixels and ppmsubpixels - drawonlyshapes convert everything to shapes (currently broken) - ignoredraworder allow to perform a few optimizations for creating smaller SWFs - linksopennewwindow make links open a new browser window - linktarget target window name of new links - linkcolor==7) - bboxvars store the bounding box of the SWF file in actionscript variables - dots Take care to handle dots correctly - reordertags=0/1 (default: 1) perform some tag optimizations - internallinkfunction= when the user clicks a internal link (to a different page) in the converted file, this actionscript function is called - externallinkfunction= when the user clicks an external link (e.g. http://www.foo.bar/) on the converted file, this actionscript function is called - disable_polygon_conversion never convert strokes to polygons (will remove capstyles and joint styles) - caplinewidth= the minimum thichness a line needs to have so that capstyles become visible (and are converted) - insertstop put an ActionScript "STOP" tag in every frame - protect add a "protect" tag to the file, to prevent loading in the Flash editor - flashversion= the SWF fileversion (6) - framerate= SWF framerate - minlinewidth= convert horizontal/vertical boxes smaller than this width to lines (0.05) - simpleviewer Add next/previous buttons to the SWF - animate insert a showframe tag after each placeobject (animate draw order of PDF files) - jpegquality= set compression quality of jpeg images - splinequality= Set the quality of spline convertion to value (0-100, default: 100). - disablelinks Disable links. - */ - - if (file_exists($this->out . $prefix . $page . '.swf')) { - unlink($this->out . $prefix . $page . '.swf'); - } - - if (!in_array($method, array(self::BARBARE_PNM, self::BARBARE_GS))) { - if (in_array($version, array('legacy', 'stable', 'latest', 'git'))) { - $program = '/usr/local/swftools/' . $version . '/bin/pdf2swf'; - } else { - $program = 'pdf2swf'; - } - - $pdf2swf = new cubeCommandLine($program, null, true); - $pdf2swf->setPath(CONVERTER_PATH); - - $pdf2swf->setArg('p', $page); - - if ($method == self::NORMAL) { - // Default - $multiply = 1; - } elseif ($method == self::FLATTEN) { - $pdf2swf->setArg('flatten'); - $multiply = 1; - } elseif ($method == self::POLY2BITMAP) { - // Raster graphics, keep texts - $pdf2swf->setArg('set poly2bitmap'); - $multiply = self::$resolution2multiply[$resolution]; - $pdf2swf->setArg('set multiply', $multiply); - } elseif ($method == self::BITMAP) { - // Raster all - $pdf2swf->setArg('set bitmap'); - $multiply = self::$resolution2multiply[$resolution]; - $pdf2swf->setArg('set multiply', $multiply); - } - // $pdf2swf->setManualArg('-v'); - $pdf2swf->setArg('T', 10); - $pdf2swf->setArg('set reordertags', '0'); - if ($storeAllChars) { - $pdf2swf->setArg('fonts'); - $pdf2swf->setArg('set storeallcharacters'); - } - if (DEV) { - $pdf2swf->setArg('F', 'C:/Windows/Fonts'); - } else { - $pdf2swf->setArg('F', '/home/typo/fonts'); - } - $pdf2swf->setArg('set subpixels', $resolution / 72); - $pdf2swf->setArg('set jpegquality', $quality); - $pdf2swf->setArg('set disablelinks'); - $pdf2swf->setArg('set dots'); - if ($version == 'git') { - $pdf2swf->setArg(null, '-T7'); - $pdf2swf->setArg('set alignfonts'); - } - $pdf2swf->setArg(null, $this->cropped); - $pdf2swf->setArg('output', $this->out . $prefix . '%.swf'); - $pdf2swf->execute(); - - if ($version == 'git') { - $f = $this->out . $prefix . $page . '.swf'; - $combine = new cubeCommandLine('swfcombine'); - $combine->setArg('d'); - $combine->setArg(null, '-F9'); - $combine->setArg(null, $f); - $combine->setArg('o', $f); - $combine->execute(); - } - - $this->addToLog($pdf2swf, true, $page); - } else { - $this->pdf2swfBarbare($page, $resolution, $quality, $method); - } - } - - protected function makeAS3($page) { - $swffile = $this->out . 'p' . $page . '.swf'; - - $swfcombine = new cubeCommandLine('swfcombine'); - $swfcombine->setPath(CONVERTER_PATH); - $swfcombine->setArg('merge'); - $swfcombine->setArg('stack1'); - $swfcombine->setArg('z'); - $swfcombine->setManualArg('-v'); - $swfcombine->setArg('o', $swffile); - $swfcombine->setArg(null, ROOT . '/swf/as3Container.swf'); - $swfcombine->setManualArg('content=' . $swffile); - $swfcombine->execute(); - $this->addToLog($swfcombine, true, $page); - } - - protected function pdf2swfBarbare($page, $resolution = 150, $quality = 85, $method = 4) { - // Fabrique les images - - $this->addToLog('Making barbare swf', true, $page); - - if ($method == self::BARBARE_PNM) { - $this->makeShot($page, 'barbare', $resolution, $quality, 4, 'PNM'); - } elseif ($method == self::BARBARE_GS) { - $this->makeShot($page, 'barbare', $resolution, $quality, 4, 'GS'); - } - - $dim = getimagesize($this->out . 'barbare' . $page . '.jpg'); - - // A partir des images, on crée les swf - $jpeg2swf = new cubeCommandLine('jpeg2swf'); - $jpeg2swf->setPath(CONVERTER_PATH); - $jpeg2swf->setArg('--quality', $quality); - $jpeg2swf->setArg('--output', $this->out . 'p' . $page . '.swf'); - $jpeg2swf->setArg('--flashversion', 10); - $jpeg2swf->setArg('--width', $dim[0] * (72 / $resolution)); - $jpeg2swf->setArg('--height', $dim[1] * (72 / $resolution)); - $jpeg2swf->setArg('--fit-to-movie'); - $jpeg2swf->setArg(null, $this->out . 'barbare' . $page . '.jpg'); - $jpeg2swf->execute(); - $this->addToLog($jpeg2swf, true, $page); - // Suppression du jpeg - @unlink($this->out . '/barbare' . $page . '.jpg', true, $page); - - $pdf2swf = new cubeCommandLine('pdf2swf', null, true); - $pdf2swf->setPath(CONVERTER_PATH); - $pdf2swf->setArg('set poly2bitmap'); - $pdf2swf->setArg('p', $page); - $pdf2swf->setArg('stop'); - $pdf2swf->setArg('T', 10); - $pdf2swf->setArg('set reordertags', '0'); - $pdf2swf->setArg('fonts'); - $pdf2swf->setArg('set storeallcharacters'); - if (DEV) { - $pdf2swf->setArg('F', 'C:/Windows/Fonts'); - } else { - $pdf2swf->setArg('F', '/home/typo/fonts'); - } - if (file_exists($this->out . 't' . $page . '.swf')) { - unlink($this->out . 't' . $page . '.swf'); - } - $pdf2swf->setArg('set subpixels', '0.01'); - $pdf2swf->setArg('set jpegquality', '1'); - $pdf2swf->setArg('set disablelinks'); - $pdf2swf->setArg(null, $this->cropped); - $pdf2swf->setArg('output', $this->out . 't' . $page . '.swf'); - $pdf2swf->execute(); - $this->addToLog($pdf2swf, true, $page); - - return ''; - } - - public function resetLog() { - unlink($this->log . '/commons.log.gz'); - } - - public function addToLog($cl, $output = true, $page = null) { - if ($cl instanceof cubeCommandLine) { - $c = '--- Exécuté en ' . $cl->execTime . " s\n" . $cl->commande . "\n\n"; - if ($output) { - $c .= $cl->output . "\n\n"; - } - } elseif (is_string($cl)) { - $c = '--- ' . "\n\n"; - $c .= $cl . "\n\n"; - } - - if (is_null($page)) { - $pointer = fopen($this->log . '/commons.log', 'ab'); - } else { - $pointer = fopen($this->log . '/p' . $page . '.log', 'ab'); - } - - fwrite($pointer, $c); - fclose($pointer); - } - - public function __destruct() { - - } - -} - + 2, 100 => 2, 150 => 3, 200 => 3, 300 => 3, 450 => 4, 600 => 5); + // Number section styles + protected static + $numberStyles = array('NoNumber' => 'no', 'DecimalArabicNumerals' => 'decimal', + 'UppercaseRomanNumerals' => 'roman_up', 'LowercaseRomanNumerals' => 'roman_low', + 'UppercaseLetters' => 'letters_up', 'LowercaseLetters' => 'letters_low'); + + public function init() { + $this->out = WS_DOCS . '/' . $this->document_id . '/'; + $this->log = $this->out . '/logs/'; + $this->html = $this->out . '/html/'; + $this->in = $this->out . 'original.pdf'; + $this->uncompressed = $this->out . 'uncompressed.pdf'; + $this->infos = $this->out . 'infos.txt'; + if (!file_exists($this->out)) { + mkdir($this->out, 0755, true); + mkdir($this->log, 0755); + } + if (!file_exists($this->html)) { + mkdir($this->html, 0755); + } + $this->cropped = $this->out . 'crop.pdf'; + $this->pages_log_pointers = array(); + + if (is_null($this->conversionInfos)) { + $this->conversionInfos = new wsDocumentConversionInfos(); + } + } + + public function copyOriginalFromUpload($tmp_file) { + move_uploaded_file($tmp_file, $this->in); + } + + public function copyOriginalFromOlderVersion() { + if (!file_exists($this->in)) { + copy('http://ws.fluidbook.com/docs/' . $this->document_id . '/original.pdf', $this->in); + } + } + + public function extractFonts() { + $extractor = new wsPDFFontExtractor($this->out, $this); + $extractor->extract(); + } + + public function getInfos($in = null, $force = false) { + if (is_null($in)) { + $in = $this->in; + } + + $fwstk = new cubeCommandLine('fwstk'); + $fwstk->setPath(CONVERTER_PATH); + $fwstk->setArg('--input ' . $in); + $fwstk->setArg('--infos'); + $fwstk->execute(); + $this->addToLog($fwstk); + $out = $fwstk->output; + + $pdfinfo = new cubeCommandLine('pdfinfo'); + $pdfinfo->setPath(CONVERTER_PATH); + $pdfinfo->setArg('-box'); + $pdfinfo->setArg('f', 1); + $pdfinfo->setArg('l', 100000); + $pdfinfo->setArg(null, $in); + $pdfinfo->execute(); + $this->addToLog($pdfinfo); + $out.="\n"; + $out.=$pdfinfo->output; + + $this->parseInfos($out); + + $this->conversionInfos->setPageNumber($this->generalInfos['pages']); + + file_put_contents($this->infos, $out); + $this->findCutDisposition(); + } + + public function findCutDisposition() { + $this->detectSpreads(); + $this->detectPageDifferences(); + } + + protected function detectPageDifferences() { + // Vérifie si la cropbox et la trimbox sont identiques pour toutes les pages + $difference = false; + foreach ($this->generalInfos['page'] as $page => $infos) { + if (!isset($infos['crop']) || !isset($infos['crop'])) { + continue; + } + if ($infos['crop'] != $infos['trim']) { + $difference = true; + } + } + if (!$difference) { + return false; + } + // Vérifie si la trimbox définie toutes les pages de la même taille + $heights = array(); + $widths = array(); + foreach ($this->generalInfos['page'] as $page => $infos) { + $heights[] = round($infos['trim']->height); + $widths[] = round($infos['trim']->width); + } + $heights = array_unique($heights); + $widths = array_unique($widths); + if (count($heights) == 1 && count($widths) == 1) { + $this->autocrop = 'trim'; + $this->manualcrop = false; + } else { + $this->autocrop = false; + $this->manualcrop = true; + } + } + + protected function detectSpreads() { + // Détection des spreads + + $this->autocut = false; + $this->manualcut = false; + if ($this->generalInfos['pages'] <= 2) { + return; + } + + foreach ($this->generalInfos['page'] as $page => $infos) { + if ($page == 1) { + $first = $infos['size']; + } elseif ($page == $this->generalInfos['pages']) { + $last = $infos['size']; + } elseif ($page == 2) { + $second = $infos['size']; + } + } + + if ($first == $last && $last == $second) { + $ratio = $first[0] / $first[1]; + $this->autocut = false; + if ($ratio <= 1) { + $this->manualcut = false; + } elseif ($ratio >= 6) { + $this->manualcut = 'L8'; + } elseif ($ratio >= 3) { + $this->manualcut = 'L4'; + } elseif ($ratio >= 2) { + $this->manualcut = 'L3'; + } else { + $this->manualcut = '14-23'; + } + return; + } + $this->manualcut = false; + if (self::compareSizes($last, $first) && cubeMath::compare($first[0] * 2, $second[0], 0.9)) { + $this->autocut = '1-23-4'; + } + if (cubeMath::compare($first[0] * 2, $second[0], 0.9) && self::compareSizes($last, $second)) { + $this->autocut = '1-23'; + } + + $this->addToLog('Detect Spreads : Manual cut ' . $this->manualcut . ' ; Auto cut : ' . $this->autocut); + } + + public static function compareSizes($x, $y, $tolerance = 0.9) { + return cubeMath::compare($x[0], $y[0], $tolerance) && cubeMath::compare($x[1], $y[1], $tolerance); + } + + public function parseInfos($data) { + // This function get general infos (pages sizes, boxes, number sections and + // bookmarks + // Init arrays + $this->generalInfos = array(); + $this->generalInfos['size'] = array(0, 0); + $this->bookmarks = array(); + $this->numberSections = ''; + $bookmark_id = 0; + + $res['size'] = array(0, 0); + $lines = explode("\n", $data); + foreach ($lines as $line) { + $line = trim(cubeText::condenseWhite($line)); + $e = explode(':', $line, 2); + $k = trim($e[0]); + if (count($e) < 2) { + continue; + } + $v = trim($e[1]); + if ($k == 'Pages' || $k == 'NumberOfPages') { + $this->pages = $this->generalInfos['pages'] = $v; + $this->generalInfos['page'] = array(); + for ($i = 1; $i <= $this->pages; $i++) { + $this->generalInfos['page'][$i] = array(); + } + } elseif (preg_match('|Page\s+([0-9]+)\s+(.*)Box:\s+([0-9.]*)\s+([0-9.]*)\s+([0-9.]*)\s+([0-9.]*)|iu', $line, $m)) { + $this->generalInfos['page'][$m[1]][strtolower($m[2])] = new wsBox($m[3], $m[4], $m[5], $m[6]); + } elseif (preg_match('|Page\s+([0-9]+)\s+size:\s+([0-9.]*)[pts[:space:]]+x\s+([0-9.]*)\s+pts|iu', $line, $m)) { + $this->generalInfos['page'][$m[1]]['size'] = array($m[2], $m[3]); + if ($m[1] == 1) { + $this->generalInfos['size'][0] = $m[2]; + $this->generalInfos['size'][1] = $m[3]; + } + } elseif ($k == 'BookmarkTitle') { + $this->bookmarks[$bookmark_id] = array('titre' => str_replace(' ', '', trim($v))); + } elseif ($k == 'BookmarkLevel') { + $this->bookmarks[$bookmark_id]['level'] = $v; + } elseif ($k == 'BookmarkPageNumber') { + $this->bookmarks[$bookmark_id]['page'] = $v; + $bookmark_id++; + } elseif ($k == 'NumberSections') { + $this->numberSections = $v; + } + } + + return $res; + } + + public function getPagesNumber() { + $this->getInfos(); + return $this->generalInfos['pages']; + } + + public function globalOperations() { + $this->getInfos(); + if ($this->CropAndCut()) { + $this->getInfos($this->cropped, true); + } + $this->getLinksAndTexts(); + } + + public function CropAndCut() { + if (!$this->isCropped()) { + copy($this->in, $this->cropped); + return false; + } + if ($this->autocrop == 'trim') { + $this->trimDocument(); + } else { + copy($this->in, $this->cropped); + } + + if ($this->autocut) { + $this->cutDocument($this->autocut); + return true; + } + return false; + } + + public function cutDocument($mode) { + $fwstk = new cubeCommandLine('fwstk'); + $fwstk->setPath(CONVERTER_PATH); + $fwstk->setArg('--input ' . $this->in); + $fwstk->setArg('--cut ' . $mode); + $fwstk->setArg('--output ' . $this->cropped); + $fwstk->execute(); + $this->addToLog($fwstk); + } + + public function trimDocument() { + $fwstk = new cubeCommandLine('fwstk'); + $fwstk->setPath(CONVERTER_PATH); + $fwstk->setArg('--input ' . $this->in); + $fwstk->setArg('--trim'); + $fwstk->setArg('--output ' . $this->cropped); + $fwstk->execute(); + $this->addToLog($fwstk); + } + + public function processOnePage($page, $force = true) { + if ($force) { + $this->addToLog('Processing page #' . $page); + $this->makeMiniShot($page); + $this->makeSWFFiles($page); + $this->makeHTML5Files($page); + } + } + + public function processAllPages() { + for ($i = 1; $i <= $this->generalInfos['pages']; $i++) { + $this->processOnePage($i); + } + $this->optimizeSVG(); + } + + public function optimizeSVG() { + + + + $scour = new cubeCommandLine('scour.php'); + $scour->setPath(CONVERTER_PATH); + $scour->setNohup(true); + $scour->setArg(null, $this->html); + $scour->execute(); + } + + public function processRange($pages) { + foreach ($pages as $i) { + $this->processOnePage($i); + } + $this->optimizeSVG(); + } + + public function getLinksAndTexts() { + $fwstk = new cubeCommandLine('fwstk'); + $fwstk->setPath(CONVERTER_PATH); + $fwstk->setArg('--input ' . $this->cropped); + $fwstk->setArg('--extractTexts ' . $this->out . '%s%d.txt'); + $fwstk->setArg('--extractLinks ' . $this->out . 'p%d.csv'); + $fwstk->execute(); + $this->addToLog($fwstk); + + /* $fwstk = new cubeCommandLine('fwstk'); + $fwstk->setPath(CONVERTER_PATH); + $fwstk->setArg('--input ' . $this->cropped); + $fwstk->setArg('--layout ' . $this->html . 'p%d.layout'); + $fwstk->setArg('--cmaps ' . $this->html); + $fwstk->setArg('--fonts' . $this->out . 'fonts/web/'); + $fwstk->execute(); + $this->addToLog($fwstk); */ + } + + public function makeMiniShot($page) { + $this->makeShotFixedWidth($page, 'p', 100, 90, 4, 'PNM'); + } + + public function makeShotFixedWidth($page, $prefix = '', $w = 100, $quality = 90, $antialiasing = 4, $method = 'PNM') { + // Make thumbs of $w width + // resolution 72 make 1pt=1px + $width = $this->generalInfos['size'][0]; + $ratio = $width / $w; + $this->makeShot($page, $prefix, round(72 / $ratio, 2), $quality, $antialiasing, $method); + } + + public function makeShotFixedHeight($page, $prefix = '', $h = '', $quality = 90, $antialiasing = 4, $method = 'PNM') { + // Make thumbs of $w height + // resolution 72 make 1pt=1px + $height = $this->generalInfos['size'][1]; + $ratio = $height / $h; + $this->makeShot($page, $prefix, round(72 / $ratio, 2), $quality, $antialiasing, $method); + } + + public function makeShot($page, $prefix = '', $resolution = 72, $quality = 90, $antialiasing = 4, $method = 'PNM', $in = null) { + $error = false; + if (is_null($in)) { + $in = $this->cropped; + } + // Delete all old files + $res = $this->out . $prefix . $page . '.jpg'; + if (file_exists($res)) { + @unlink($res); + } + + if ($method == 'GS') { + $this->makeShotGS($page, $prefix, $resolution, $quality, $antialiasing, $in); + } elseif ($method == 'PNM') { + $this->makeShotPNM($page, $prefix, $resolution, $quality, $antialiasing, $in); + } + // Test the result by checking all files + if (!file_exists($res)) { + $error = true; + } + // If error, we try to make thumbs with other method + if ($error) { + if ($method == 'GS') { + $this->makeShotPNM($page, $prefix, $resolution, $quality, $antialiasing, $in); + } elseif ($method == 'PNM') { + $this->makeShotGS($page, $prefix, $resolution, $quality, $antialiasing, $in); + } + } + } + + protected function makeShotGS($page, $prefix = '', $resolution = 72, $quality = 90, $antialiasing = 4, $in = null) { + if (is_null($in)) { + $in = $this->cropped; + } + // Fabrication des thumbanails avec ghostscript + $gs = new cubeCommandLine('gs', null, true); + $gs->setPath(CONVERTER_PATH); + $gs->setEnv('GS_FONTPATH', FONT_PATH); + $gs->setArg('-dBATCH'); + $gs->setArg('-dNOPAUSE'); + $gs->setArg('-dNOPROMPT'); + // Antialias + $gs->setArg('-dDOINTERPOLATE'); + $gs->setArg('-dTextAlphaBits=' . $antialiasing); + $gs->setArg('-dGraphicsAlphaBits=' . $antialiasing); + // Device + $gs->setArg('-sDEVICE=jpeg'); + // Dispotion & colors + // $gs->setArg('-dUseCIEColor'); + $gs->setArg('-dAutoRotatePages=/None'); + $gs->setArg('-dUseCropBox'); + // Resolution & Quality + $gs->setArg('-r' . round($resolution)); + $gs->setArg('-dJPEGQ=' . $quality); + // Performances + $gs->setArg('-dNumRenderingThreads=4'); + // Page range + $gs->setArg('-dFirstPage=' . $page); + $gs->setArg('-dLastPage=' . $page); + // Files + $gs->setArg('-sOutputFile=' . $this->out . '/' . $prefix . $page . '.jpg'); + + $gs->setArg(null, $in); + $gs->execute(); + $this->addToLog($gs, true, $page); + } + + protected function makeShotPNM($page, $prefix = '', $resolution = 72, $quality = 90, $antialiasing = 4, $in = null, $texts = true) { + if (is_null($in)) { + $in = $this->cropped; + } + + $tmp = cubeFiles::tempnam(); + + $antialiasing = $antialiasing ? 'yes' : 'no'; + $freetype = $texts ? 'yes' : 'no'; + $resolution = $resolution; + // Exporte les fichiers + $pdftoppm = new cubeCommandLine('pdftoppm', null, true); + $pdftoppm->setPath(CONVERTER_PATH); + + $pdftoppm->setArg('f', $page); + $pdftoppm->setArg('l', $page); + $pdftoppm->setArg('-cropbox'); + $pdftoppm->setArg('-freetype ' . $freetype); + $pdftoppm->setArg('-singlefile'); + $pdftoppm->setArg('-aa ' . $antialiasing); + $pdftoppm->setArg('-aaVector ' . $antialiasing); + $pdftoppm->setArg('r', $resolution); + $pdftoppm->setArg(null, $in); + $pdftoppm->setArg(null, $tmp); + $pdftoppm->execute(); + $this->addToLog($pdftoppm, true, $page); + + $tmp.='.ppm'; + + $jpegfile = $this->out . $prefix . $page . '.jpg'; + + if (file_exists($tmp)) { + $pnmtojpeg = new cubeCommandLine('pnmtojpeg', $jpegfile, false); + $pnmtojpeg->setArg('-quality ' . $quality); + $pnmtojpeg->setArg(null, $tmp); + $pnmtojpeg->execute(); + $this->addToLog($pnmtojpeg, false, $page); + + unlink($tmp); + } + } + + protected function isCropped() { + return $this->autocrop || $this->manualcrop || $this->autocut || $this->manualcut; + } + + public function makeSWFFiles($page, $resolution = null, $quality = null, $storeAllChars = null, $maxObjects = null, $method = null, $version = null) { + $conversionSettings = $this->conversionInfos->pages[$page]; + if (is_null($storeAllChars)) { + $storeAllChars = true; + } + if (is_null($resolution)) { + $resolution = $conversionSettings->resolution; + } + if (is_null($method)) { + $method = $conversionSettings->method; + } + if (is_null($quality)) { + $quality = $conversionSettings->quality; + } + if (is_null($maxObjects)) { + $maxObjects = $conversionSettings->objects; + } + if (is_null($version)) { + $version = isset($conversionSettings->version) ? $conversionSettings->version : 'stable'; + } + + if ($maxObjects <= 1) { + $method = self::POLY2BITMAP; + } + + // Pour les fichiers croppés, on utilise la méthode flatten qui ne prends + // pas en compte les objets hors de la box + if ($this->isCropped()) { + // $method = max($method, self::FLATTEN); + } + + $out = $this->pdf2swf($page, $resolution, $quality, $storeAllChars, $method, 'p', $version); + if ($method < self::BARBARE_PNM) { + // Analyse de la sortie pour détecter des typos manquantes + $overflow = false; + $overflowObjects = false; + $written = false; + $missing_fonts = array(); + if (file_exists($out)) { + $fp = fopen($out, 'rb'); + while ($line = fgets($fp)) { + if (preg_match('|Try putting a TTF version of that font \(named \"([A-Z-_0-9.]*)\"\)|Uui', trim($line), $matches)) { + $missing_fonts[] = $matches[1]; + } elseif (stristr($line, 'ID Table overflow')) { + $overflow = true; + } elseif (stristr($line, 'NOTICE SWF written')) { + $written = true; + } elseif (stristr($line, 'NOTICE Writing SWF file')) { + $written = true; + } + } + } + if (!is_null($page) && file_exists($this->out . 'p' . $page . '.swf')) { + $written = true; + } + // On teste si le fichier est écrit et qu'il a été généré par le premier niveau + if ($method < self::POLY2BITMAP && $written) { + $overflowObjects = $this->checkObjectsNumber($this->out . 'p' . $page . '.swf', $maxObjects, $page); + } + + if (!$written || $overflow || $overflowObjects) { + if ($method == self::MAX) { + return; + } + $nextMethod = $method + 1; + return $this->makeSWFFiles($page, $resolution, $quality, $storeAllChars, $maxObjects, $nextMethod, $version); + } + } + } + + public function makeHTML5Files($page) { + // Then make HD background shots + $resolutions = array(300 => 85, 150 => 85, 36 => 85); + foreach ($resolutions as $r => $q) { + $this->makeShotPNM($page, 'html/h' . $r . '-', $r, $q, 4, null, false); + $this->makeShotPNM($page, 'html/t' . $r . '-', $r, $q, 4, null, true); + } + $this->makeSVGFile($page); + } + + public function makeSVGFile($page) { + $svgFile = $this->out . '/html/p' . $page . '.svg'; + $svgOpt = $this->out . '/html/o' . $page . '.svg'; + + $pdftocairo = new cubeCommandLine('pdftocairo'); + $pdftocairo->setPath(CONVERTER_PATH); + $pdftocairo->setArg('f', $page); + $pdftocairo->setArg('l', $page); + $pdftocairo->setArg(null, '-svg'); + $pdftocairo->setArg(null, '-cropbox'); + $pdftocairo->setArg(null, $this->cropped); + $pdftocairo->setArg(null, $svgFile); + $pdftocairo->execute(); + $this->addToLog($pdftocairo, true, $page); + + $this->_cleanSVG($svgFile); + } + + protected function _cleanSVG($svgFile) { + $svg = new DOMDocument(); + $svg->preserveWhiteSpace = false; + $svg->load($svgFile); + + // Operations to delete + $xpath = new DOMXPath($svg); + $xpath->registerNamespace('svg', 'http://www.w3.org/2000/svg'); + $xpath->registerNamespace('xlink', 'http://www.w3.org/1999/xlink'); + $xpath->registerNamespace("php", "http://php.net/xpath"); + $xpath->registerPhpFunctions('has_not_text'); + $toDelete = array('//svg:defs/svg:clipPath', + '//svg:defs/svg:image', + '//svg:defs/svg:pattern', + '/svg:svg/svg:g/svg:g[not(svg:use[@xlink:href])]', + '/svg:svg/svg:g/svg:path', + '/svg:svg/svg:g/svg:rect', + ); + + global $svglog; + $svglog = array('XPATH : ' . print_r($xpath, true)); + foreach ($toDelete as $q) { + $list = $xpath->query($q); + $svglog[] = "Evaluate xpath query " . $q; + $svglog[] = 'Give ' . $list->length . ' results'; + $svglog[] = 'Deleting Nodes in ' . print_r($list, true); + if (count($list)) { + foreach ($list as $node) { + + /* @var $node DOMNode */ + $parent = $node->parentNode; + $parent->removeChild($node); + } + } + } + + $this->addToLog(implode("\n", $svglog), false, $page); + file_put_contents($svgFile, $svg->saveXML()); + } + + protected function checkObjectsNumber($file, $maxObjects, $page) { + $swfdump = new cubeCommandLine('swfdump', null, true); + $swfdump->setPath(CONVERTER_PATH); + $swfdump->setArg(null, $file); + $swfdump->execute(); + $this->addToLog($swfdump, true, $page); + + str_replace('[01a]', '', $swfdump->output, $nbObjects); + if ($nbObjects > $maxObjects) { + return true; + } + return false; + } + + protected function dumpSWF($page, $prefix = 'p') { + $swfdump = new cubeCommandLine('/usr/local/swftools/special-swfdump/bin/swfdump', null, true); + $swfdump->setPath(CONVERTER_PATH); + $swfdump->setArg('t'); + $swfdump->setArg('p'); + $swfdump->setArg('F'); + $swfdump->setArg(null, $this->out . $prefix . $page . '.swf'); + $swfdump->execute(); + $this->addToLog($swfdump, false, $page); + return $swfdump->output; + } + + /** + * wsDocument::pdf2swf() + * + * @param mixed $page + * @param integer $resolution + * @param integer $quality + * @param mixed $storeAllChars + * @param integer $method + * @return + */ + protected function pdf2swf($page, $resolution = 150, $quality = 90, $storeAllChars = true, $method = 0, $prefix = 'p', $version = 'stable') { + /* + -h , --help Print short help message and exit + -V , --version Print version info and exit + -o , --output file.swf Direct output to file.swf. If file.swf contains '%' (file%.swf), then each page goes to a seperate file. + -p , --pages range Convert only pages in range with range e.g. 1-20 or 1,4,6,9-11 or + -P , --password password Use password for deciphering the pdf. + -v , --verbose Be verbose. Use more than one -v for greater effect. + -z , --zlib Use Flash 6 (MX) zlib compression. + -i , --ignore Allows pdf2swf to change the draw order of the pdf. This may make the generated + -j , --jpegquality quality Set quality of embedded jpeg pictures to quality. 0 is worst (small), 100 is best (big). (default:85) + -s , --set param=value Set a SWF encoder specific parameter. See pdf2swf -s help for more information. + -w , --samewindow When converting pdf hyperlinks, don't make the links open a new window. + -t , --stop Insert a stop() command in each page. + -T , --flashversion num Set Flash Version in the SWF header to num. + -F , --fontdir directory Add directory to the font search path. + -b , --defaultviewer Link a standard viewer to the swf file. + -l , --defaultloader Link a standard preloader to the swf file which will be displayed while the main swf is loading. + -B , --viewer filename Link viewer filename to the swf file. + -L , --preloader filename Link preloader filename to the swf file. + -q , --quiet Suppress normal messages. Use -qq to suppress warnings, also. + -S , --shapes Don't use SWF Fonts, but store everything as shape. + -f , --fonts Store full fonts in SWF. (Don't reduce to used characters). + -G , --flatten Remove as many clip layers from file as possible. + -I , --info Don't do actual conversion, just display a list of all pages in the PDF. + -Q , --maxtime n Abort conversion after n seconds. Only availableon Unix. + + PDF device global parameters: + ----------------------------- + fontdir= a directory with additional fonts + font= an additional font filename + pages= the range of pages to convert (example: pages=1-100,210-) + zoom= the resultion (default: 72) + languagedir= Add an xpdf language directory + multiply= Render everything at the resolution + poly2bitmap Convert graphics to bitmaps + bitmap Convert everything to bitmaps + + SWF Parameters : + ---------------- + SWF layer options : + ------------------- + + jpegsubpixels= resolution adjustment for jpeg images (same as jpegdpi, but in pixels) + ppmsubpixels= shortcut for setting both jpegsubpixels and ppmsubpixels + drawonlyshapes convert everything to shapes (currently broken) + ignoredraworder allow to perform a few optimizations for creating smaller SWFs + linksopennewwindow make links open a new browser window + linktarget target window name of new links + linkcolor==7) + bboxvars store the bounding box of the SWF file in actionscript variables + dots Take care to handle dots correctly + reordertags=0/1 (default: 1) perform some tag optimizations + internallinkfunction= when the user clicks a internal link (to a different page) in the converted file, this actionscript function is called + externallinkfunction= when the user clicks an external link (e.g. http://www.foo.bar/) on the converted file, this actionscript function is called + disable_polygon_conversion never convert strokes to polygons (will remove capstyles and joint styles) + caplinewidth= the minimum thichness a line needs to have so that capstyles become visible (and are converted) + insertstop put an ActionScript "STOP" tag in every frame + protect add a "protect" tag to the file, to prevent loading in the Flash editor + flashversion= the SWF fileversion (6) + framerate= SWF framerate + minlinewidth= convert horizontal/vertical boxes smaller than this width to lines (0.05) + simpleviewer Add next/previous buttons to the SWF + animate insert a showframe tag after each placeobject (animate draw order of PDF files) + jpegquality= set compression quality of jpeg images + splinequality= Set the quality of spline convertion to value (0-100, default: 100). + disablelinks Disable links. + */ + + if (file_exists($this->out . $prefix . $page . '.swf')) { + unlink($this->out . $prefix . $page . '.swf'); + } + + if (!in_array($method, array(self::BARBARE_PNM, self::BARBARE_GS))) { + if (in_array($version, array('legacy', 'stable', 'latest', 'git'))) { + $program = '/usr/local/swftools/' . $version . '/bin/pdf2swf'; + } else { + $program = 'pdf2swf'; + } + + $pdf2swf = new cubeCommandLine($program, null, true); + $pdf2swf->setPath(CONVERTER_PATH); + + $pdf2swf->setArg('p', $page); + + if ($method == self::NORMAL) { + // Default + $multiply = 1; + } elseif ($method == self::FLATTEN) { + $pdf2swf->setArg('flatten'); + $multiply = 1; + } elseif ($method == self::POLY2BITMAP) { + // Raster graphics, keep texts + $pdf2swf->setArg('set poly2bitmap'); + $multiply = self::$resolution2multiply[$resolution]; + $pdf2swf->setArg('set multiply', $multiply); + } elseif ($method == self::BITMAP) { + // Raster all + $pdf2swf->setArg('set bitmap'); + $multiply = self::$resolution2multiply[$resolution]; + $pdf2swf->setArg('set multiply', $multiply); + } + // $pdf2swf->setManualArg('-v'); + $pdf2swf->setArg('T', 10); + $pdf2swf->setArg('set reordertags', '0'); + if ($storeAllChars) { + $pdf2swf->setArg('fonts'); + $pdf2swf->setArg('set storeallcharacters'); + } + if (DEV) { + $pdf2swf->setArg('F', 'C:/Windows/Fonts'); + } else { + $pdf2swf->setArg('F', '/home/typo/fonts'); + } + $pdf2swf->setArg('set subpixels', $resolution / 72); + $pdf2swf->setArg('set jpegquality', $quality); + $pdf2swf->setArg('set disablelinks'); + $pdf2swf->setArg('set dots'); + if ($version == 'git') { + $pdf2swf->setArg(null, '-T7'); + $pdf2swf->setArg('set alignfonts'); + } + $pdf2swf->setArg(null, $this->cropped); + $pdf2swf->setArg('output', $this->out . $prefix . '%.swf'); + $pdf2swf->execute(); + + if ($version == 'git') { + $f = $this->out . $prefix . $page . '.swf'; + $combine = new cubeCommandLine('swfcombine'); + $combine->setArg('d'); + $combine->setArg(null, '-F9'); + $combine->setArg(null, $f); + $combine->setArg('o', $f); + $combine->execute(); + } + + $this->addToLog($pdf2swf, true, $page); + } else { + $this->pdf2swfBarbare($page, $resolution, $quality, $method); + } + } + + protected function makeAS3($page) { + $swffile = $this->out . 'p' . $page . '.swf'; + + $swfcombine = new cubeCommandLine('swfcombine'); + $swfcombine->setPath(CONVERTER_PATH); + $swfcombine->setArg('merge'); + $swfcombine->setArg('stack1'); + $swfcombine->setArg('z'); + $swfcombine->setManualArg('-v'); + $swfcombine->setArg('o', $swffile); + $swfcombine->setArg(null, ROOT . '/swf/as3Container.swf'); + $swfcombine->setManualArg('content=' . $swffile); + $swfcombine->execute(); + $this->addToLog($swfcombine, true, $page); + } + + protected function pdf2swfBarbare($page, $resolution = 150, $quality = 85, $method = 4) { + // Fabrique les images + + $this->addToLog('Making barbare swf', true, $page); + + if ($method == self::BARBARE_PNM) { + $this->makeShot($page, 'barbare', $resolution, $quality, 4, 'PNM'); + } elseif ($method == self::BARBARE_GS) { + $this->makeShot($page, 'barbare', $resolution, $quality, 4, 'GS'); + } + + $dim = getimagesize($this->out . 'barbare' . $page . '.jpg'); + + // A partir des images, on crée les swf + $jpeg2swf = new cubeCommandLine('jpeg2swf'); + $jpeg2swf->setPath(CONVERTER_PATH); + $jpeg2swf->setArg('--quality', $quality); + $jpeg2swf->setArg('--output', $this->out . 'p' . $page . '.swf'); + $jpeg2swf->setArg('--flashversion', 10); + $jpeg2swf->setArg('--width', $dim[0] * (72 / $resolution)); + $jpeg2swf->setArg('--height', $dim[1] * (72 / $resolution)); + $jpeg2swf->setArg('--fit-to-movie'); + $jpeg2swf->setArg(null, $this->out . 'barbare' . $page . '.jpg'); + $jpeg2swf->execute(); + $this->addToLog($jpeg2swf, true, $page); + // Suppression du jpeg + @unlink($this->out . '/barbare' . $page . '.jpg', true, $page); + + $pdf2swf = new cubeCommandLine('pdf2swf', null, true); + $pdf2swf->setPath(CONVERTER_PATH); + $pdf2swf->setArg('set poly2bitmap'); + $pdf2swf->setArg('p', $page); + $pdf2swf->setArg('stop'); + $pdf2swf->setArg('T', 10); + $pdf2swf->setArg('set reordertags', '0'); + $pdf2swf->setArg('fonts'); + $pdf2swf->setArg('set storeallcharacters'); + if (DEV) { + $pdf2swf->setArg('F', 'C:/Windows/Fonts'); + } else { + $pdf2swf->setArg('F', '/home/typo/fonts'); + } + if (file_exists($this->out . 't' . $page . '.swf')) { + unlink($this->out . 't' . $page . '.swf'); + } + $pdf2swf->setArg('set subpixels', '0.01'); + $pdf2swf->setArg('set jpegquality', '1'); + $pdf2swf->setArg('set disablelinks'); + $pdf2swf->setArg(null, $this->cropped); + $pdf2swf->setArg('output', $this->out . 't' . $page . '.swf'); + $pdf2swf->execute(); + $this->addToLog($pdf2swf, true, $page); + + return ''; + } + + public function resetLog() { + unlink($this->log . '/commons.log.gz'); + } + + public function addToLog($cl, $output = true, $page = null) { + if ($cl instanceof cubeCommandLine) { + $c = '--- Exécuté en ' . $cl->execTime . " s\n" . $cl->commande . "\n\n"; + if ($output) { + $c .= $cl->output . "\n\n"; + } + } elseif (is_string($cl)) { + $c = '--- ' . "\n\n"; + $c .= $cl . "\n\n"; + } + + if (is_null($page)) { + $pointer = fopen($this->log . '/commons.log', 'ab'); + } else { + $pointer = fopen($this->log . '/p' . $page . '.log', 'ab'); + } + + fwrite($pointer, $c); + fclose($pointer); + } + + public function __destruct() { + + } + +} + ?> \ No newline at end of file -- 2.39.5