]> _ Git - cubeextranet.git/commitdiff
wait #2439 @0:10
authorvincent@cubedesigners.com <vincent@cubedesigners.com@f5622870-0f3c-0410-866d-9cb505b7a8ef>
Thu, 29 Aug 2019 12:07:58 +0000 (12:07 +0000)
committervincent@cubedesigners.com <vincent@cubedesigners.com@f5622870-0f3c-0410-866d-9cb505b7a8ef>
Thu, 29 Aug 2019 12:07:58 +0000 (12:07 +0000)
inc/ws/Metier/class.ws.book.parametres.php
inc/ws/Metier/class.ws.document.php

index 276a24caa102063c6d198e10c6c30aa3660cffae..38ef591994d61873f33b451cd3318eda196db04f 100644 (file)
@@ -595,9 +595,10 @@ class wsBookParametres extends wsParametres
         $this->fields['scorm_quiz_as_questionnaire'] = array('type' => 'boolean', 'default' => false, 'editable' => true, 'label' => __('Traiter les quiz comme des questionnaires (toutes les réponses sont considérées comme correctes)'), 'grade' => 5);
         $this->fields['scorm_quizdata'] = array('type' => 'freefile', 'editable' => true, 'default' => '', 'label' => __('Données de quiz'));
         $this->fields['scorm_complete_on_exit'] = ['type' => 'boolean', 'default' => false, 'label' => 'Marquer le cours comme "Complete" à la fermeture de la fenêtre', 'editable' => true];
+        $this->fields['scorm_complete_on_last_page'] = ['type' => 'boolean', 'default' => false, 'label' => 'Marquer le cours comme "Complete" lorsque le visiteur atteint la dernière page', 'editable' => true];
 
         $this->forms['scorm'] = array('label' => __('SCORM'),
-            'fieldsnames' => array('scorm_enable', 'scorm_version', 'scorm_id', 'scorm_org', 'scorm_title', 'scorm_variables', '|', 'scorm_complete_on_exit', '|', 'scorm_quizdata', 'scorm_score', 'scorm_score_min', 'scorm_quiz_as_questionnaire'));
+            'fieldsnames' => array('scorm_enable', 'scorm_version', 'scorm_id', 'scorm_org', 'scorm_title', 'scorm_variables', '|', 'scorm_complete_on_exit', 'scorm_complete_on_last_page', '|', 'scorm_quizdata', 'scorm_score', 'scorm_score_min', 'scorm_quiz_as_questionnaire'));
 
         $versions = wsUrl::getFluidbookVersions(false);
         $ignore = ['v1', 'v2', 'phonegap'];
index d694452ee625569c0dd0bfd9631b9a6997236a24..9d2477c4ca60ceb19101ff67830ac4c45cc87812 100644 (file)
 class wsDocument extends cubeMetier
 {
 
-       protected $document_id;
-       protected $file;
-       protected $proprietaire;
-       protected $pages;
-       protected $trim;
-       protected $date;
-       protected $localInfos;
-       protected $generalInfos;
-       protected $conversionInfos;
-       protected $bookmarks;
-       protected $numberSections;
-       protected $localHash;
-       protected $version;
-       // Crop & cut
-       protected $autocrop;
-       protected $manualcrop;
-       protected $autocut;
-       protected $manualcut;
-       // Files
-       protected $out;
-       protected $in;
-       protected $html;
-       protected $uncompressed;
-       protected $log;
-       protected $common_log_pointer;
-       protected $pages_log_pointers;
-       protected $infos;
-       protected $cropped;
-       protected $rgb;
-
-       protected static $_docsDir;
-
-       const NORMAL = 0;
-       const FLATTEN = 1;
-       const POLY2BITMAP = 2;
-       const BITMAP = 3;
-       const BARBARE_PNM = 4;
-       const BARBARE_GS = 5;
-       const MAX = 5;
-       const PNM_FILL = 2;
-
-       protected static $resolution2multiply = array(72 => 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 = wsDocument::getDir($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 getCroppedPDF(){
-               if(!file_exists($this->cropped)){
-                       return $this->in;
-               }
-               return $this->cropped;
-       }
-
-       public function copyOriginalFromUpload($tmp_file)
-       {
-               move_uploaded_file($tmp_file, $this->in);
-       }
-
-       public function copyOriginalFromOlderVersion()
-       {
-               if (!file_exists($this->in)) {
-                       copy('https://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.sh');
-               $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->addToLog('Parse infos');
-               $this->parseInfos($out);
-
-               $this->addToLog('Set Page Infos');
-               $this->conversionInfos->setPageNumber($this->generalInfos['pages']);
-
-               $this->addToLog('Write infos');
-               file_put_contents($this->infos, $out);
-
-               $this->addToLog('Find cut disposition');
-
-               $this->findCutDisposition();
-       }
-
-       public function findCutDisposition()
-       {
-               $this->detectSpreads();
-               $this->detectPageDifferences();
-       }
-
-       protected function detectPageDifferences()
-       {
-               $this->addToLog('Detect page differences');
-               // 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()
-       {
-               $this->addToLog('Detect spreads');
-               // 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 lnCrop()
-       {
-               $root = dirname($this->cropped);
-               `cd $root;ln -s original.pdf crop.pdf`;
-       }
-
-       public function parseInfos($data)
-       {
-               cubePHP::set_memory('4G');
-               // 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('&#13;', '', 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->addToLog('Get infos');
-               $this->getInfos();
-               if ($this->CropAndCut()) {
-                       $this->addToLog('Get infos after crop');
-                       $this->getInfos($this->cropped, true);
-               }
-               $this->addToLog('Get links');
-               $this->getLinks();
-               $this->addToLog('End of global ops');
-               $this->splitDoc();
-       }
-
-       public function splitDoc()
-       {
-               $this->addToLog('Split document');
-               mkdir($this->out . '/pdf');
-               $pdftk = new cubeCommandLine('pdftk');
-               $pdftk->setPath(CONVERTER_PATH);
-               $pdftk->setArg(null, $this->getCroppedPDF());
-               $pdftk->setArg(null, 'burst');
-               $pdftk->setArg(null, 'output');
-               $pdftk->setArg(null, $this->out . 'pdf/p%d.pdf');
-               $pdftk->execute();
-               $this->addToLog($pdftk);
-       }
-
-       public function CropAndCut()
-       {
-               $this->addToLog('Crop And Cut');
-               if (!$this->isCropped()) {
-                       $this->lnCrop();
-                       return false;
-               }
-               if ($this->autocrop == 'trim') {
-                       $this->trimDocument();
-               } else {
-                       $this->lnCrop();
-               }
-
-               if ($this->autocut) {
-                       $this->cutDocument($this->autocut);
-                       return true;
-               }
-               return false;
-       }
-
-       public function cutDocument($mode)
-       {
-               $fwstk = new cubeCommandLine('fwstk.sh');
-               $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.sh');
-               $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);
-               }
-       }
-
-       public function processRange($pages)
-       {
-               foreach ($pages as $i) {
-                       $this->processOnePage($i);
-               }
-       }
-
-       public function getLinks()
-       {
-               $fwstk = new cubeCommandLine('fwstk.sh');
-               $fwstk->setPath(CONVERTER_PATH);
-               $fwstk->setArg('--input ' . $this->getCroppedPDF());
-               $fwstk->setArg('--extractLinks ' . $this->out . 'p%d.csv');
-               $fwstk->setArg('--threads 1');
-               $fwstk->execute();
-               $this->addToLog($fwstk);
-       }
-
-       public function getHighlightTextsData()
-       {
-               $fwstk = new cubeCommandLine('fwstk.sh');
-               $fwstk->setPath(CONVERTER_PATH);
-               $fwstk->setArg('--input ' . $this->getCroppedPDF());
-               $fwstk->setArg('--layout ' . $this->html . 'p%d.fby');
-               $fwstk->setArg('--cmaps ' . $this->html);
-               $fwstk->setArg('--fonts' . $this->out . 'fonts/web/');
-               $fwstk->execute();
-               $this->addToLog($fwstk);
-       }
-
-       public function getResolutionRatio()
-       {
-               $a4surface = 500990; // en pt²
-               $docSurface = $this->generalInfos['size'][0] * $this->generalInfos['size'][1]; // en pt²
-               // to have the same surface resulting in px, we have to sqrt the ratio between the two surfaces defined above
-               return sqrt($a4surface / $docSurface);
-       }
-
-       public function makeMiniShot($page)
-       {
-               $this->makeShotFixedWidth($page, 'p', 500, 65, 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->getCroppedPDF();
-               }
-               // 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->getCroppedPDF();
-               }
-               // 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->getCroppedPDF();
-               }
-
-               $tmp = cubeFiles::tempnam();
-
-               $antialiasing = $antialiasing ? 'yes' : 'no';
-               $freetype = $texts ? 'yes' : 'no';
-               // 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);
-
-
-                       $cjpeg = new cubeCommandLine('cjpeg', null, true);
-                       $cjpeg->setArg('-quality ' . ($quality + 6));
-                       $cjpeg->setArg('-outfile ' . $jpegfile);
-                       $cjpeg->setArg(null, $tmp);
-                       $cjpeg->execute();
-                       $this->addToLog($cjpeg, 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 * $this->getResolutionRatio(), $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);
-               $rratio = $this->getResolutionRatio();
-               foreach ($resolutions as $r => $q) {
-                       $this->makeShotPNM($page, 'html/h' . $r . '-', $r * $rratio, $q, 4, null, false);
-                       $this->makeShotPNM($page, 'html/t' . $r . '-', $r * $rratio, $q, 4, null, true);
-               }
-               $this->makeSVGFile($page);
-       }
-
-       public function makeSVGFile($page)
-       {
-               $svgFile = $this->out . '/html/fp' . $page . '.svg';
-               $source =  $this->getCroppedPDF();
-
-               $pdftocairo = new cubeCommandLine('pdftocairo');
-               $pdftocairo->setPath(CONVERTER_PATH);
-               $pdftocairo->setArg('f', $page);
-               $pdftocairo->setArg('l', $page);
-               $pdftocairo->setArg('r', 300);
-               $pdftocairo->setArg(null, '-expand');
-               $pdftocairo->setArg(null, '-svg');
-               $pdftocairo->setArg(null, $source);
-               $pdftocairo->setArg(null, $svgFile);
-               $pdftocairo->execute();
-
-               $this->addToLog($pdftocairo, true, $page);
-       }
-
-       public static function extractTexts($svgFile, $textFile, $force = false)
-       {
-               $do = $force || !file_exists($textFile) || filesize($textFile) < 100 || filemtime($svgFile) > filemtime($textFile) || filemtime($textFile) < filemtime(__FILE__);
-               if (!$do) {
-                       return;
-               }
-
-               $svg = new DOMDocument();
-               $svg->preserveWhiteSpace = false;
-               $svg->load($svgFile, LIBXML_PARSEHUGE);
-
-               // 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:path',
-                       '//svg:defs/svg:pattern',
-                       '//svg:defs/svg:g[starts-with(@id, "surface")]//svg:path',
-                       '/svg:svg/svg:g//svg:path',
-                       '/svg:svg/svg:g//svg:rect',
-                       '//svg:use[starts-with(@xlink:href, "#image")]'
-               );
-
-               //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);
-                               }
-                       }
-               }
-               file_put_contents($textFile, $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=<dir>     a directory with additional fonts
-                 font=<filename>   an additional font filename
-                 pages=<range>     the range of pages to convert (example: pages=1-100,210-)
-                 zoom=<dpi>        the resultion (default: 72)
-                 languagedir=<dir> Add an xpdf language directory
-                 multiply=<times>  Render everything at <times> the resolution
-                 poly2bitmap       Convert graphics to bitmaps
-                 bitmap            Convert everything to bitmaps
-
-                 SWF Parameters :
-                 ----------------
-                 SWF layer options :
-                 -------------------
-
-                 jpegsubpixels=<pixels>      resolution adjustment for jpeg images (same as jpegdpi, but in pixels)
-                 ppmsubpixels=<pixels        resolution adjustment for  lossless images (same asppmdpi, but in pixels)
-                 subpixels=<pixels>          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=<color)           color of links (format: RRGGBBAA)
-                 linknameurl                 Link buttons will be named like the URL they refer to (handy for iterating through links with actionscript)
-                 storeallcharacters          don't reduce the fonts to used characters in the output file
-                 enablezlib                  switch on zlib compression (also done if flashversion>=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=<name> when the user clicks a internal link (to a different page) in the converted file, this actionscript function is called
-                 externallinkfunction=<name> 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=<width>        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=<version>      the SWF fileversion (6)
-                 framerate=<fps>             SWF framerate
-                 minlinewidth=<width>        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=<quality>       set compression quality of jpeg images
-                 splinequality=<value>       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', 1);
-                       $flashversion = 10;
-
-                       if ($method == self::NORMAL) {
-                               // Default
-                               $multiply = 1;
-                       } elseif ($method == self::FLATTEN) {
-                               $multiply = 1;
-                               $pdf2swf->setArg('flatten');
-                       } elseif ($method == self::POLY2BITMAP) {
-                               // Raster graphics, keep texts
-                               $pdf2swf->setArg('set poly2bitmap');
-                               $pdf2swf->setArg('set multiply', $this->_findMultiply($resolution));
-                       } elseif ($method == self::BITMAP) {
-                               // Raster all
-                               $pdf2swf->setArg('set bitmap');
-                               $pdf2swf->setArg('set multiply', $this->_findMultiply($resolution));
-                       }
-                       // $pdf2swf->setManualArg('-v');
-                       $pdf2swf->setArg('T', $flashversion);
-                       $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->out . 'pdf/p' . $page . '.pdf');
-                       $pdf2swf->setArg('output', $this->out . $prefix . $page . '.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 _findMultiply($resolution)
-       {
-               $resolution /= $this->getResolutionRatio();
-               return self::$resolution2multiply[$resolution];
-       }
-
-       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', 1);
-               $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->out . 'pdf/p' . $page . '.pdf');
-               $pdf2swf->setArg('output', $this->out . 't' . $page . '.swf');
-               $pdf2swf->execute();
-               $this->addToLog($pdf2swf, true, $page);
-
-               return '';
-       }
-
-       public function resetLog()
-       {
-               $f=$this->log . '/commons.log.gz';
-               if(file_exists($f)) {
-                       unlink($f);
-               }
-       }
-
-       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 (!file_exists($this->log)) {
-                       mkdir($this->log, 0777, true);
-               }
-
-
-               if (is_null($page)) {
-                       $fname = 'commons.log';
-               } else {
-                       $fname = 'p' . $page . '.log';
-               }
-
-               $file = $this->log . '/' . $fname;
-               if (!file_exists($file) && file_exists($fname . '.gz')) {
-                       $fopen = 'gzopen';
-                       $fwrite = 'gzwrite';
-                       $fclose = 'gzclose';
-                       $file .= '.gz';
-               } else {
-                       $fopen = 'fopen';
-                       $fwrite = 'fwrite';
-                       $fclose = 'fclose';
-               }
-
-               $pointer = $fopen($file, 'ab');
-               $fwrite($pointer, $c);
-               $fclose($pointer);
-       }
-
-       public function __destruct()
-       {
-
-       }
-
-       public static function getDir($id)
-       {
-
-               if (!is_array(self::$_docsDir)) {
-                       self::$_docsDir = array();
-               }
-
-               if (isset(self::$_docsDir[$id])) {
-                       return self::$_docsDir[$id];
-               }
-
-               $new = WS_FILES . '/docs/' . $id . '/';
-               $old = WS_FILES . '/docs1/' . $id . '/';
-               $veryold = WS_FILES . '/docs2/' . $id . '/';
-
-               if (file_exists($new . 'p1.swf')) {
-                       self::$_docsDir[$id] = $new;
-                       return $new;
-               } elseif (file_exists($old . 'p1.swf')) {
-                       self::$_docsDir[$id] = $old;
-                       return $old;
-               } else if (file_exists($veryold . 'p1.swf')) {
-                       self::$_docsDir[$id] = $veryold;
-                       return $veryold;
-               }
-               if (!file_exists($new)) {
-                       mkdir($new, 0777, true);
-               }
-               self::$_docsDir[$id] = $new;
-               return $new;
-       }
+    protected $document_id;
+    protected $file;
+    protected $proprietaire;
+    protected $pages;
+    protected $trim;
+    protected $date;
+    protected $localInfos;
+    protected $generalInfos;
+    protected $conversionInfos;
+    protected $bookmarks;
+    protected $numberSections;
+    protected $localHash;
+    protected $version;
+    // Crop & cut
+    protected $autocrop;
+    protected $manualcrop;
+    protected $autocut;
+    protected $manualcut;
+    // Files
+    protected $out;
+    protected $in;
+    protected $html;
+    protected $uncompressed;
+    protected $log;
+    protected $common_log_pointer;
+    protected $pages_log_pointers;
+    protected $infos;
+    protected $cropped;
+    protected $rgb;
+
+    protected static $_docsDir;
+
+    const NORMAL = 0;
+    const FLATTEN = 1;
+    const POLY2BITMAP = 2;
+    const BITMAP = 3;
+    const BARBARE_PNM = 4;
+    const BARBARE_GS = 5;
+    const MAX = 5;
+    const PNM_FILL = 2;
+
+    protected static $resolution2multiply = array(72 => 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 = wsDocument::getDir($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 getCroppedPDF()
+    {
+        if (!file_exists($this->cropped)) {
+            return $this->in;
+        }
+        return $this->cropped;
+    }
+
+    public function copyOriginalFromUpload($tmp_file)
+    {
+        move_uploaded_file($tmp_file, $this->in);
+    }
+
+    public function copyOriginalFromOlderVersion()
+    {
+        if (!file_exists($this->in)) {
+            copy('https://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.sh');
+        $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->addToLog('Parse infos');
+        $this->parseInfos($out);
+
+        $this->addToLog('Set Page Infos');
+        $this->conversionInfos->setPageNumber($this->generalInfos['pages']);
+
+        $this->addToLog('Write infos');
+        file_put_contents($this->infos, $out);
+
+        $this->addToLog('Find cut disposition');
+
+        $this->findCutDisposition();
+    }
+
+    public function findCutDisposition()
+    {
+        $this->detectSpreads();
+        $this->detectPageDifferences();
+    }
+
+    protected function detectPageDifferences()
+    {
+        $this->addToLog('Detect page differences');
+        // 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()
+    {
+        $this->addToLog('Detect spreads');
+        // 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 lnCrop()
+    {
+        $root = dirname($this->cropped);
+        `cd $root;ln -s original.pdf crop.pdf`;
+    }
+
+    public function parseInfos($data)
+    {
+        cubePHP::set_memory('4G');
+        // 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('&#13;', '', 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->addToLog('Get infos');
+        $this->getInfos();
+        if ($this->CropAndCut()) {
+            $this->addToLog('Get infos after crop');
+            $this->getInfos($this->cropped, true);
+        }
+        $this->addToLog('Get links');
+        $this->getLinks();
+        $this->addToLog('End of global ops');
+        $this->splitDoc();
+    }
+
+    public function splitDoc()
+    {
+        $this->addToLog('Split document');
+        mkdir($this->out . '/pdf');
+        $pdftk = new cubeCommandLine('pdftk');
+        $pdftk->setPath(CONVERTER_PATH);
+        $pdftk->setArg(null, $this->getCroppedPDF());
+        $pdftk->setArg(null, 'burst');
+        $pdftk->setArg(null, 'output');
+        $pdftk->setArg(null, $this->out . 'pdf/p%d.pdf');
+        $pdftk->execute();
+        $this->addToLog($pdftk);
+    }
+
+    public function CropAndCut()
+    {
+        $this->addToLog('Crop And Cut');
+        if (!$this->isCropped()) {
+            $this->lnCrop();
+            return false;
+        }
+        if ($this->autocrop == 'trim') {
+            $this->trimDocument();
+        } else {
+            $this->lnCrop();
+        }
+
+        if ($this->autocut) {
+            $this->cutDocument($this->autocut);
+            return true;
+        }
+        return false;
+    }
+
+    public function cutDocument($mode)
+    {
+        $fwstk = new cubeCommandLine('fwstk.sh');
+        $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.sh');
+        $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);
+        }
+    }
+
+    public function processRange($pages)
+    {
+        foreach ($pages as $i) {
+            $this->processOnePage($i);
+        }
+    }
+
+    public function getLinks()
+    {
+        $fwstk = new cubeCommandLine('fwstk.sh');
+        $fwstk->setPath(CONVERTER_PATH);
+        $fwstk->setArg('--input ' . $this->getCroppedPDF());
+        $fwstk->setArg('--extractLinks ' . $this->out . 'p%d.csv');
+        $fwstk->setArg('--threads 1');
+        $fwstk->execute();
+        $this->addToLog($fwstk);
+    }
+
+    public function getHighlightTextsData()
+    {
+        $fwstk = new cubeCommandLine('fwstk.sh');
+        $fwstk->setPath(CONVERTER_PATH);
+        $fwstk->setArg('--input ' . $this->getCroppedPDF());
+        $fwstk->setArg('--layout ' . $this->html . 'p%d.fby');
+        $fwstk->setArg('--cmaps ' . $this->html);
+        $fwstk->setArg('--fonts' . $this->out . 'fonts/web/');
+        $fwstk->execute();
+        $this->addToLog($fwstk);
+    }
+
+    public function getResolutionRatio()
+    {
+        $a4surface = 500990; // en pt²
+        $docSurface = $this->generalInfos['size'][0] * $this->generalInfos['size'][1]; // en pt²
+        // to have the same surface resulting in px, we have to sqrt the ratio between the two surfaces defined above
+        return sqrt($a4surface / $docSurface);
+    }
+
+    public function makeMiniShot($page)
+    {
+        $this->makeShotFixedWidth($page, 'p', 500, 65, 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->getCroppedPDF();
+        }
+        // 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->getCroppedPDF();
+        }
+        // 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->getCroppedPDF();
+        }
+
+        $tmp = cubeFiles::tempnam();
+
+        $antialiasing = $antialiasing ? 'yes' : 'no';
+        $freetype = $texts ? 'yes' : 'no';
+        // 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);
+
+
+            $cjpeg = new cubeCommandLine('cjpeg', null, true);
+            $cjpeg->setArg('-quality ' . ($quality + 6));
+            $cjpeg->setArg('-outfile ' . $jpegfile);
+            $cjpeg->setArg(null, $tmp);
+            $cjpeg->execute();
+            $this->addToLog($cjpeg, 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 * $this->getResolutionRatio(), $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);
+        $rratio = $this->getResolutionRatio();
+        foreach ($resolutions as $r => $q) {
+            $this->makeShotPNM($page, 'html/h' . $r . '-', $r * $rratio, $q, 4, null, false);
+            $this->makeShotPNM($page, 'html/t' . $r . '-', $r * $rratio, $q, 4, null, true);
+        }
+        $this->makeSVGFile($page);
+    }
+
+    public function makeSVGFile($page)
+    {
+        $svgFile = $this->out . '/html/fp' . $page . '.svg';
+        $source = $this->getCroppedPDF();
+
+        $pdftocairo = new cubeCommandLine('pdftocairo');
+        $pdftocairo->setPath(CONVERTER_PATH);
+        $pdftocairo->setArg('f', $page);
+        $pdftocairo->setArg('l', $page);
+        $pdftocairo->setArg('r', 300);
+        $pdftocairo->setArg(null, '-expand');
+        $pdftocairo->setArg(null, '-svg');
+        $pdftocairo->setArg(null, $source);
+        $pdftocairo->setArg(null, $svgFile);
+        $pdftocairo->execute();
+
+        $this->addToLog($pdftocairo, true, $page);
+    }
+
+    public static function extractTexts($svgFile, $textFile, $force = false)
+    {
+        $do = $force || !file_exists($textFile) || filesize($textFile) < 100 || filemtime($svgFile) > filemtime($textFile) || filemtime($textFile) < filemtime(__FILE__);
+        if (!$do) {
+            return;
+        }
+
+        $svg = new DOMDocument();
+        $svg->preserveWhiteSpace = false;
+        $svg->load($svgFile, LIBXML_PARSEHUGE);
+
+        // 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:path',
+            '//svg:defs/svg:pattern',
+            '//svg:defs/svg:g[starts-with(@id, "surface")]//svg:path',
+            '/svg:svg/svg:g//svg:path',
+            '/svg:svg/svg:g//svg:rect',
+            '//svg:use[starts-with(@xlink:href, "#image")]'
+        );
+
+        //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);
+                }
+            }
+        }
+        file_put_contents($textFile, $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=<dir>     a directory with additional fonts
+          font=<filename>   an additional font filename
+          pages=<range>     the range of pages to convert (example: pages=1-100,210-)
+          zoom=<dpi>        the resultion (default: 72)
+          languagedir=<dir> Add an xpdf language directory
+          multiply=<times>  Render everything at <times> the resolution
+          poly2bitmap       Convert graphics to bitmaps
+          bitmap            Convert everything to bitmaps
+
+          SWF Parameters :
+          ----------------
+          SWF layer options :
+          -------------------
+
+          jpegsubpixels=<pixels>      resolution adjustment for jpeg images (same as jpegdpi, but in pixels)
+          ppmsubpixels=<pixels        resolution adjustment for  lossless images (same asppmdpi, but in pixels)
+          subpixels=<pixels>          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=<color)           color of links (format: RRGGBBAA)
+          linknameurl                 Link buttons will be named like the URL they refer to (handy for iterating through links with actionscript)
+          storeallcharacters          don't reduce the fonts to used characters in the output file
+          enablezlib                  switch on zlib compression (also done if flashversion>=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=<name> when the user clicks a internal link (to a different page) in the converted file, this actionscript function is called
+          externallinkfunction=<name> 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=<width>        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=<version>      the SWF fileversion (6)
+          framerate=<fps>             SWF framerate
+          minlinewidth=<width>        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=<quality>       set compression quality of jpeg images
+          splinequality=<value>       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', 1);
+            $flashversion = 10;
+
+            if ($method == self::NORMAL) {
+                // Default
+                $multiply = 1;
+            } elseif ($method == self::FLATTEN) {
+                $multiply = 1;
+                $pdf2swf->setArg('flatten');
+            } elseif ($method == self::POLY2BITMAP) {
+                // Raster graphics, keep texts
+                $pdf2swf->setArg('set poly2bitmap');
+                $pdf2swf->setArg('set multiply', $this->_findMultiply($resolution));
+            } elseif ($method == self::BITMAP) {
+                // Raster all
+                $pdf2swf->setArg('set bitmap');
+                $pdf2swf->setArg('set multiply', $this->_findMultiply($resolution));
+            }
+            // $pdf2swf->setManualArg('-v');
+            $pdf2swf->setArg('T', $flashversion);
+            $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->out . 'pdf/p' . $page . '.pdf');
+            $pdf2swf->setArg('output', $this->out . $prefix . $page . '.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 _findMultiply($resolution)
+    {
+        $resolution /= $this->getResolutionRatio();
+        return self::$resolution2multiply[$resolution];
+    }
+
+    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', 1);
+        $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->out . 'pdf/p' . $page . '.pdf');
+        $pdf2swf->setArg('output', $this->out . 't' . $page . '.swf');
+        $pdf2swf->execute();
+        $this->addToLog($pdf2swf, true, $page);
+
+        return '';
+    }
+
+    public function resetLog()
+    {
+        $f = $this->log . '/commons.log.gz';
+        if (file_exists($f)) {
+            unlink($f);
+        }
+    }
+
+    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 (!file_exists($this->log)) {
+            mkdir($this->log, 0777, true);
+        }
+
+
+        if (is_null($page)) {
+            $fname = 'commons.log';
+        } else {
+            $fname = 'p' . $page . '.log';
+        }
+
+        $file = $this->log . '/' . $fname;
+        if (!file_exists($file) && file_exists($fname . '.gz')) {
+            $fopen = 'gzopen';
+            $fwrite = 'gzwrite';
+            $fclose = 'gzclose';
+            $file .= '.gz';
+        } else {
+            $fopen = 'fopen';
+            $fwrite = 'fwrite';
+            $fclose = 'fclose';
+        }
+
+        $pointer = $fopen($file, 'ab');
+        $fwrite($pointer, $c);
+        $fclose($pointer);
+    }
+
+    public function __destruct()
+    {
+
+    }
+
+    public static function getDir($id)
+    {
+
+        if (!is_array(self::$_docsDir)) {
+            self::$_docsDir = array();
+        }
+
+        if (isset(self::$_docsDir[$id])) {
+            return self::$_docsDir[$id];
+        }
+
+        $new = WS_FILES . '/docs/' . $id . '/';
+        $old = WS_FILES . '/docs1/' . $id . '/';
+        $veryold = WS_FILES . '/docs2/' . $id . '/';
+        $vveryold = WS_FILES . '/docs3/' . $id . '/';
+
+        if (file_exists($new . 'p1.swf')) {
+            self::$_docsDir[$id] = $new;
+            return $new;
+        } elseif (file_exists($old . 'p1.swf')) {
+            self::$_docsDir[$id] = $old;
+            return $old;
+        } else if (file_exists($veryold . 'p1.swf')) {
+            self::$_docsDir[$id] = $veryold;
+            return $veryold;
+        } else if (file_exists($vveryold . 'p1.swf')) {
+            self::$_docsDir[$id] = $vveryold;
+            return $vveryold;
+        }
+        if (!file_exists($new)) {
+            mkdir($new, 0777, true);
+        }
+        self::$_docsDir[$id] = $new;
+        return $new;
+    }
 }
\ No newline at end of file