From eaa37daef468cededc1adcdcd8cdb07180484a71 Mon Sep 17 00:00:00 2001 From: "vincent@cubedesigners.com" Date: Sun, 4 Sep 2011 21:57:18 +0000 Subject: [PATCH] --- _project/Rapport.docx | Bin 0 -> 34789 bytes fluidbook/tools/convert.pe | 7 +- .../apache/pdfbox/util/PDFStreamEngine.java | 38 +- inc/ws/Controlleur/class.ws.url.php | 14 + inc/ws/Metier/class.ws.document.php | 70 +--- inc/ws/Util/_common.php | 1 + inc/ws/Util/class.ws.pdf.fontextractor.php | 343 ++++++++++++++++++ 7 files changed, 398 insertions(+), 75 deletions(-) create mode 100644 inc/ws/Util/class.ws.pdf.fontextractor.php diff --git a/_project/Rapport.docx b/_project/Rapport.docx index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..3048e0292ae943bb9e4c3e8d8fe71b412763cec4 100644 GIT binary patch literal 34789 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 2) { + + HashMap ligatures = new HashMap<>(); + ligatures.put("AE", "\u00C6"); + ligatures.put("ae", "\u00E6"); + ligatures.put("OE", "\u0152"); + ligatures.put("oe", "\u0153"); + ligatures.put("IJ", "\u0132"); + ligatures.put("ij", "\u0133"); + ligatures.put("ff", "\ufb00"); + ligatures.put("fi", "\ufb01"); + ligatures.put("fl", "\ufb02"); + ligatures.put("ffi", "\ufb03"); + ligatures.put("ffl", "\ufb04"); + + if (ligatures.containsKey(c)) { + return ligatures.get(c); + } + } + + + return c; + } + public void updateCmaps(String c, byte b, PDFont font) { } @@ -512,7 +540,7 @@ public class PDFStreamEngine { PDFOperator oper = PDFOperator.getOperator(operation); processOperator(oper, arguments); } catch (IOException e) { - log.warn(e, e); + //log.warn(e, e); } } @@ -533,12 +561,12 @@ public class PDFStreamEngine { processor.process(operator, arguments); } else { if (!unsupportedOperators.contains(operation)) { - log.info("unsupported/disabled operation: " + operation); + //log.info("unsupported/disabled operation: " + operation); unsupportedOperators.add(operation); } } } catch (Exception e) { - log.warn(e, e); + //log.warn(e, e); } } diff --git a/inc/ws/Controlleur/class.ws.url.php b/inc/ws/Controlleur/class.ws.url.php index ebae1ddc6..b313c0ede 100644 --- a/inc/ws/Controlleur/class.ws.url.php +++ b/inc/ws/Controlleur/class.ws.url.php @@ -978,6 +978,20 @@ html{height:100%}' . "\n"; $dao->updateFromObject($doc); } + public static function testFontExtraction($args) { + $documentId = $args[1]; + + header('Content-type: text/plain'); + ob_clean(); + + + + $extractor = new wsPDFFontExtractor(WS_DOCS . '/' . $documentId); + $extractor->extract(); + + exit; + } + public static function getParamsHelp($args) { commonDroits::min(5); global $core; diff --git a/inc/ws/Metier/class.ws.document.php b/inc/ws/Metier/class.ws.document.php index 5287da6f7..f16fa8fb2 100644 --- a/inc/ws/Metier/class.ws.document.php +++ b/inc/ws/Metier/class.ws.document.php @@ -95,72 +95,8 @@ class wsDocument extends cubeMetier { } public function extractFonts() { - $out = $this->out . 'fonts/pdf'; - if (!file_exists($out)) { - mkdir($out, 0777, true); - } - // Extract fonts from PDF - /* $gs = new cubeCommandLine('gs'); - $gs->setPath(CONVERTER_PATH); - $gs->cd($out); - $gs->setArg('-dBATCH'); - $gs->setArg('-dNOPAUSE'); - $gs->setArg('-dNOPROMPT'); - $gs->setArg('-dNODISPLAY'); - $gs->setArg(null, WS_TOOLS . '/extractFonts.ps'); - $gs->setManualArg('-c "(' . $this->in . ') extractFonts quit"'); - - $gs->execute(); - $this->addToLog($gs); */ - - $mupdf = new cubeCommandLine('/usr/local/mupdf/pdfextract'); - $mupdf->setPath(CONVERTER_PATH); - $mupdf->cd($out); - $mupdf->setArg(null, $this->in); - $mupdf->execute(); - $this->addToLog($mupdf); - - - `rm $out/fonts/*.png`; - `rm $out/fonts/*.pam`; - $dr = opendir($out); - - if (!file_exists($this->out . '/fonts/web')) { - mkdir($this->out . '/fonts/web', 0777, true); - } - $images = array('pnm', 'jpg', 'jpeg', 'png', 'pam'); - // Fonts conversion - $collections = array(); - while ($file = readdir($dr)) { - if ($file == '.' || $file == '..' || in_array(files::getExtension($file), $images)) { - continue; - } - - $e = explode('.', $file); - array_pop($e); - $fname = implode('.', $e); - - $e = explode('-', $fname); - array_pop($e); - $fname = implode('-', $e); - - if (!isset($collections[$fname])) { - $collections[$fname] = array(); - } - $collections[$fname][] = $file; - } - - foreach ($collections as $fontname => $files) { - $fontforge = new cubeCommandLine('convert.pe'); - $fontforge->setPath(CONVERTER_PATH); - foreach ($files as $file) { - $fontforge->setArg(null, $out . '/' . $file); - } - $fontforge->setArg(null, $this->out . '/html/' . $fontname . '.cmap'); - $fontforge->setArg(null, $this->out . '/fonts/web/' . $fontname . '.ttf'); - $fontforge->execute(); - $this->addToLog($fontforge); - } + $extractor = new wsPDFFontExtractor($this->out, $this); + $extractor->extract(); } public function getInfos($in = null, $force = false) { @@ -319,8 +255,8 @@ class wsDocument extends cubeMetier { if ($this->CropAndCut()) { $this->getInfos($this->cropped, true); } - $this->getLinksAndTexts(); $this->extractFonts(); + $this->getLinksAndTexts(); } public function CropAndCut() { diff --git a/inc/ws/Util/_common.php b/inc/ws/Util/_common.php index 5753a4fe2..65010ba50 100644 --- a/inc/ws/Util/_common.php +++ b/inc/ws/Util/_common.php @@ -11,4 +11,5 @@ $__autoload['wsSecureSWF'] = dirname(__FILE__) . '/class.ws.secure.swf.php'; $__autoload['wsTools'] = dirname(__FILE__) . '/class.ws.tools.php'; $__autoload['wsHTML5Compiler'] = dirname(__FILE__) . '/html5/class.ws.html5.compiler.php'; $__autoload['wsHTML5Link'] = dirname(__FILE__) . '/html5/class.ws.html5.links.php'; +$__autoload['wsPDFFontExtractor'] = dirname(__FILE__) . '/class.ws.pdf.fontextractor.php'; ?> \ No newline at end of file diff --git a/inc/ws/Util/class.ws.pdf.fontextractor.php b/inc/ws/Util/class.ws.pdf.fontextractor.php new file mode 100644 index 000000000..6afff2a6a --- /dev/null +++ b/inc/ws/Util/class.ws.pdf.fontextractor.php @@ -0,0 +1,343 @@ +doc = $doc; + $this->in = $in . '/original.pdf'; + $this->outpdf = $in . '/fonts/pdf'; + $this->outweb = $in . '/fonts/web'; + } + + public function extract() { + $this->clean(); + + $this->getFonts(); + $this->getFontsDescriptors(); + $this->extractFonts(); + $this->extractCmaps(); + $this->convertToTTF(); + } + + public function convertToTTF() { + + + + $dr = opendir($this->outpdf); + while ($file = readdir($dr)) { + if ($file == '.' || $file == '..' || files::getExtension($file) == 'cmap') { + continue; + } + + $e = explode('.', $file); + array_pop($e); + $fname = implode('.', $e); + + $e = explode('-', $fname); + array_pop($e); + $fname = implode('-', $e); + + if (!isset($collections[$fname])) { + $collections[$fname] = array(); + } + $collections[$fname][] = $file; + } + + foreach ($collections as $fontname => $files) { + $fontforge = new cubeCommandLine('convert.pe'); + $fontforge->setPath(CONVERTER_PATH); + foreach ($files as $file) { + $fontforge->setArg(null, $this->outpdf . '/' . $file); + } + $cmapFile = $this->outpdf . '/' . $fontname . '.cmap'; + if (!file_exists($cmapFile)) { + $fontforge->setArg(null, '-'); + } else { + $fontforge->setArg(null, $cmapFile); + } + $fontforge->setArg(null, $this->outweb . '/' . $fontname . '.ttf'); + $fontforge->execute(); + $this->addToLog($fontforge); + } + } + + public function getFonts() { + $pdfinfo = $this->getCommandLine('pdfinfo'); + $pdfinfo->setArg('f'); + $pdfinfo->setArg(null, $this->in); + $pdfinfo->execute(); + + $this->addToLog($pdfinfo); + + /* + * /home/extranet/www/fluidbook/docs/100376/original.pdf: + + PDF-1.7 + Info object (9177 0 R): + << + /CreationDate (D:20110831090005+02'00') + /Creator (Adobe InDesign CS5 \(7.0\)) + /ModDate (D:20110901144502+02'00') + /Producer (Adobe PDF Library 9.9) + /Trapped /False + >> + + Pages: 116 + + Retrieving info from pages 1-116... + Fonts (201): + 1 ( 9180 0 R): Type1 'QGNYEE+AvantGarde-Book' (9193 0 R) + 1 ( 9180 0 R): Type1 'QGNYEE+AvantGarde-ExtraLight' (9195 0 R) + 2 ( 1 0 R): Type1 'QGNYEE+DIN-Light' (7605 0 R) + 2 ( 1 0 R): Type1 'QGNYEE+AvantGarde-ExtraLightObl' (7608 0 R) + 2 ( 1 0 R): Type1 'QGNYEE+AvantGarde-MediumObl' (7601 0 R) + + */ + + if (preg_match_all("|\s+\d+\s+\(\s+\d+\s+\d+\s+\w+\):\s+\w+\s+'([A-Za-z-+]+)'\s+\((\d+)\s+\d+\s+\w+\)\s|", $pdfinfo->output, $matches)) { + foreach ($matches[1] as $k => $name) { + $this->fonts[$matches[2][$k]] = array('name' => $name); + } + } + } + + protected function getFontsDescriptors() { + $pdfshow = $this->getCommandLine('pdfshow'); + $pdfshow->setArg(null, $this->in); + $pdfshow->setManualArg(implode(' ', array_keys($this->fonts))); + $pdfshow->execute(); + //$this->doc->addToLog($pdfshow); + + /* + 8677 0 obj + << + /BaseFont /YIKUMO+Futura-Condensed + /Encoding /WinAnsiEncoding + /FirstChar 32 + /FontDescriptor 7690 0 R + /LastChar 119 + /Subtype /Type1 + /Type /Font + /Widths [ 205 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 414 418 0 466 0 342 0 0 0 303 0 0 561 0 + 0 388 0 0 354 0 0 0 0 0 0 0 0 0 0 0 0 0 380 380 0 380 361 + 0 382 388 180 0 395 180 590 388 375 380 0 269 276 221 389 + 0 487 ] + >> + endobj + + 9193 0 obj + << + /BaseFont /QGNYEE+AvantGarde-Book + /Encoding /WinAnsiEncoding + /FirstChar 32 + /FontDescriptor 9192 0 R + /LastChar 201 + /Subtype /Type1 + /ToUnicode 9185 0 R + /Type /Font + /Widths [ 277 0 0 0 0 0 0 0 0 0 0 0 277 332 0 0 554 554 554 + 0 0 0 554 554 0 0 0 0 0 0 0 0 0 740 574 813 744 536 485 872 + 683 226 482 0 462 919 740 869 592 0 607 498 426 655 702 0 + 0 592 480 0 0 0 0 0 0 683 0 0 0 650 0 0 0 200 0 0 200 0 610 + 655 0 0 301 388 339 0 554 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1000 + 0 0 0 0 0 0 0 0 0 0 0 0 351 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 740 0 0 0 0 0 0 0 0 536 ] + >> + endobj + */ + + $lines = explode("\n", $pdfshow->output); + $currentFont = null; + foreach ($lines as $line) { + $line = trim($line); + if ($line == '' || $line == '<<' || $line == '>>') { + continue; + } + if ($line == 'endobj') { + $currentFont = null; + continue; + } + $e = explode(' ', $line); + if (count($e)==3 && $e[2] == 'obj') { + $currentFont = $e[0]; + continue; + } + + if (is_null($currentFont)) { + continue; + } + + $fontname = $this->fonts[$currentFont]['name']; + + if ($e[0] == '/ToUnicode') { + $this->fonts[$currentFont]['cmap'] = $e[1]; + $this->cmaps[$fontname] = $e[1]; + } + } + + $this->addToLog(print_r($this->fonts, true)); + } + + protected function extractFonts() { + $descriptors = $this->getUniqueId('descriptor'); + + $pdfextract = $this->getCommandLine('pdfextract'); + $pdfextract->setArg(null, $this->in); + $pdfextract->execute(); + $this->addToLog($pdfextract); + + + $formats = array('pnm', 'pam', 'pgm', 'jpg', 'gif', 'jpeg', 'png'); + foreach ($formats as $f) { + `rm $this->outpdf/*.$f`; + } + } + + protected function extractCmaps() { + $cmaps = array_unique($this->cmaps); + + $pdfshow = $this->getCommandLine('pdfshow'); + $pdfshow->setArg(null, $this->in); + $pdfshow->setManualArg(implode(' ', $cmaps)); + $pdfshow->execute(); + $this->addToLog($pdfshow); + + + /* 5266 0 obj + << + /Filter /FlateDecode + /Length 583 + >> + stream + /CIDInit /ProcSet findresource begin + 12 dict begin + begincmap + /CIDSystemInfo + << /Registry (Adobe) + /Ordering (UCS) /Supplement 0 >> def + /CMapName /Adobe-Identity-UCS def + /CMapType 2 def + 1 begincodespacerange + <0000> + endcodespacerange + 81 beginbfchar + <0000> <0020> + <0001> <0021> + <0005> <0025> + <0007> <2019> + <0008> <0028> + <0009> <0029> + <000C> <002C> + <000D> <002D> + <000E> <002E> + <000F> <002F> + endbfchar + endcmap CMapName currentdict /CMap defineresource pop end end + endstream + endobj + + */ + + $finalCmaps = array(); + + $lines = explode("\n", $pdfshow->output); + $currentCmap = null; + $inMap = false; + foreach ($lines as $line) { + $line = trim($line); + if ($line == '') { + continue; + } + if ($line == 'endobj') { + $currentCmap = null; + continue; + } elseif ($line == 'endbfchar') { + $inMap = false; + } + + $e = explode(' ', $line); + if (count($e)==3 && $e[2] == 'obj') { + $currentCmap = $e[0]; + continue; + } + + if (count($e)==1 && $e[1] == 'beginbfchar') { + $inMap = true; + continue; + } + + if (!$inMap || is_null($currentCmap)) { + continue; + } + + $fonts = array_keys($this->cmaps, $currentCmap); + + $from = trim($e[0], '<>'); + $to = trim($e[1], '<>'); + + foreach ($fonts as $fontname) { + if (!isset($finalCmaps[$fontname])) { + $finalCmaps[$fontname] = array(); + } + + $finalCmaps[$fontname][$from] = $to; + } + } + + foreach ($finalCmaps as $fontname => $cmap) { + arsort($cmap); + $data = ''; + foreach ($cmap as $from => $to) { + $data.=$from . "\t" . $to . "\n"; + } + file_put_contents($this->outpdf . '/' . $fontname . '.cmap', $data); + } + } + + protected function getUniqueId($param) { + $res = array(); + foreach ($this->fonts as $f) { + if (isset($f[$param])) { + $res[$id] = $f[$param]; + } + } + return array_unique($res); + } + + protected function clean() { + `rm -rf $this->outpdf`; + `rm -rf $this->outweb`; + mkdir($this->outweb, 0777, true); + mkdir($this->outpdf, 0777, true); + } + + protected function getCommandLine($program) { + $res = new cubeCommandLine('/usr/local/mupdf/' . $program); + $res->cd($this->outpdf); + $res->setPath(CONVERTER_PATH); + return $res; + } + + protected function addToLog($tolog) { + if (!is_null($this->doc)) { + $this->doc->addToLog($tolog); + } elseif ($tolog instanceof cubeCommandLine) { + echo $tolog->commande . "\n\n"; + echo $tolog->output . "\n\n"; + } else { + echo $tolog . "\n\n"; + } + } + +} + +?> -- 2.39.5