+++ /dev/null
-<?php
-
-namespace Fluidbook\Tools\CommandLine;
-
-use Cubist\Util\CommandLine;
-use Fluidbook\Tools\FluidbookTools;
-
-class FWSTK extends CommandLine
-{
- public function __construct($output = null, $error = true)
- {
- parent::__construct(FluidbookTools::tools_path('fwstk.sh', true), $output, $error);
- }
-}
+++ /dev/null
-<?php
-
-namespace Fluidbook\Tools;
-class FluidbookTools
-{
- /**
- * @param $path string
- * @return string
- */
-
- public static function resource_path($path)
- {
- return __DIR__ . '/../resources/' . self::_cleanPath($path);
- }
-
- /**
- * @param $path string
- * @return string
- */
- public static function tools_path($path, $chmod = false)
- {
- $res = self::resource_path('tools/' . self::_cleanPath($path));
- if ($chmod) {
- self::chmodExec($res);
- }
- return $res;
- }
-
- public static function chmodExec($path)
- {
- if (is_file($path)) {
- chmod($path, 0755);
- }
- }
-
- /**
- * @param $path string
- * @return string
- */
- protected static function _cleanPath($path)
- {
- return trim($path, '/');
- }
-}
+++ /dev/null
-<?php
-
-namespace Fluidbook\Tools\Jobs;
-
-use Cubist\Util\Files\Files;
-use Fluidbook\Tools\PDF\PDFTools;
-use Fluidbook\Tools\SVG\SVGTools;
-
-class ProcessFile
-{
- protected $format = 'jpg';
- /**
- * @var int|string
- */
- protected $resolution = 150;
- /**
- * @var bool
- */
- protected $withGraphics = true;
- /**
- * @var bool
- */
- protected $withTexts = true;
- /**
- * @var string
- */
- protected $version = 'html';
-
- /**
- * @var ProcessPage
- */
- protected $job;
-
- public function __construct($format = 'jpg', $resolution = 150, $withGraphics = true, $withTexts = true, $version = 'html')
- {
- $this->format = $format;
- $this->resolution = $resolution;
- $this->withGraphics = $withGraphics;
- $this->withTexts = $withTexts;
- $this->version = $version;
- }
-
- /**
- * @param string $format
- */
- public function setFormat(string $format)
- {
- $this->format = $format;
- }
-
- /**
- * @return string
- */
- public function getFormat(): string
- {
- if ($this->format === 'jpeg') {
- return 'jpg';
- }
- return $this->format;
- }
-
- /**
- * @param int|string $resolution
- */
- public function setResolution(int|string $resolution)
- {
- $this->resolution = $resolution;
- }
-
- /**
- * @return int|string
- */
- public function getResolution(): int|string
- {
- return $this->resolution;
- }
-
- /**
- * @return bool
- */
- public function isWithGraphics(): bool
- {
- return $this->withGraphics;
- }
-
- /**
- * @param bool $withGraphics
- */
- public function setWithGraphics(bool $withGraphics)
- {
- $this->withGraphics = $withGraphics;
- }
-
- /**
- * @return bool
- */
- public function isWithTexts(): bool
- {
- return $this->withTexts;
- }
-
- /**
- * @param bool $withTexts
- */
- public function setWithTexts(bool $withTexts)
- {
- $this->withTexts = $withTexts;
- }
-
- /**
- * @return int
- */
- public function getPage(): int
- {
- return $this->job->getPage();
- }
-
- /**
- * @return mixed
- */
- public function getOut()
- {
- return $this->job->getOut();
- }
-
-
- /**
- * @return string
- */
- public function getVersion(): string
- {
- if ($this->getFormat() === 'svg') {
- return 'html';
- } else if ($this->getFormat() === 'swf') {
- return '';
- }
-
- return $this->version;
- }
-
- /**
- * @param string $version
- */
- public function setVersion(string $version)
- {
- $this->version = $version;
- }
-
- /**
- * @return ProcessPage
- */
- public function getJob(): ProcessPage
- {
- return $this->job;
- }
-
- /**
- * @param ProcessPage $job
- */
- public function setJob(ProcessPage $job)
- {
- $this->job = $job;
- return $this;
- }
-
- public function getPath($force = false)
- {
- $dir = rtrim($this->getOut() . $this->getVersion(), '/') . '/';
- $minsize = 1;
- $res = '';
- if ($this->getFormat() === 'svg') {
- $prefix = $this->isWithGraphics() ? 'f' : 't';
- $res = $dir . $prefix . 'o' . $this->getPage();
- if ($this->isWithGraphics()) {
- $res .= '-' . $this->getResolution();
- }
- $res .= '.svg';
- $reffile = $this->makeSVGFile();
- $minsize = 100;
- } else if (in_array($this->getFormat(), ['png', 'jpg'])) {
- $prefix = $this->isWithTexts() ? 't' : 'h';
- if ($this->getResolution() === 'thumb') {
- $res = $dir . 'p' . $this->getPage() . '.' . $this->getFormat();
- } else {
- $res = $dir . $prefix . $this->getPage() . '-' . $this->getResolution() . '.' . $this->getFormat();
- }
- } else if ($this->getFormat() === 'swf') {
- $res = $dir . 'p' . $this->getPage() . '.' . $this->getFormat();
- }
-
- $do = false;
- if (!file_exists($res) || filesize($res) < $minsize) {
- $do = true;
- } else if (isset($reffile) && filemtime($res) < filemtime($reffile)) {
- $do = true;
- }
-
- if ($do || $force) {
- $this->makeFile($res);
- }
- return $res;
- }
-
- public function makeFile($file)
- {
- $lock = $file . '.lock';
- if (file_exists($lock) && filemtime($lock) > time() - 300) {
- sleep(10);
- return $this->getPath();
- }
- Files::mkdir(dirname($lock));
- touch($lock);
- if ($this->getFormat() === 'svg') {
- if ($this->isWithGraphics()) {
- $this->makeOptimizedSVGFile($file);
- } else {
- $this->makeTextSVGFile($file);
- }
- } else if (in_array($this->getFormat(), ['png', 'jpg'])) {
- if ($this->getResolution() === 'thumb') {
- PDFTools::makeMiniShot($this->getSplittedPDFPage(), $file, 1, $this->getFormat());
- } else {
- $rr = $this->getVersion() === 'html' ? $this->getJob()->getResolutionRatio() : $this->getJob()->getMobileFirstRatio();
- PDFTools::makeShotPNM($this->getSplittedPDFPage(), $file, 1, '', $this->getResolution() * $rr, 85, 4, $this->isWithTexts(), null, null, $this->getFormat());
- }
- } else if ($this->getFormat() === 'swf') {
- PDFTools::makeSWF($this->getSplittedPDFPage(), $file, 1, $this->getResolution(), 80);
- }
- unlink($lock);
- if (!file_exists($file)) {
- throw new \Exception(sprintf('Failed to generate %s', $file));
- }
- }
-
- public function makeSVGFile($force = false)
- {
- $svgFile = $this->getOut() . '/html/fp' . $this->getPage() . '.svg';
- if (!$force && file_exists($svgFile) && filesize($svgFile) > 0) {
- return $svgFile;
- }
- PDFTools::makeBaseSVGFile($this->getSplittedPDFPage(), $svgFile, 1);
- return $svgFile;
- }
-
- public function makeTextSVGFile($out)
- {
- $in = $this->makeSVGFile();
- $inter = str_replace('/to', '/tp', $out);
- PDFTools::makeTextSVGFile($in, $inter);
- SVGTools::optimizeSVG($inter, $out);
- }
-
- public function makeOptimizedSVGFile($out)
- {
- $in = $this->makeSVGFile();
- SVGTools::optimizeSVGImages($in, $out, $this->getResolution());
- SVGTools::optimizeSVG($out, $out);
- }
-
- protected function getSplittedPDFPage()
- {
- $res = $this->getOut() . 'pdf/p' . $this->getPage() . '.pdf';
- if (!file_exists($res)) {
- $this->getJob()->splitDoc();
- }
- return $res;
- }
-}
+++ /dev/null
-<?php
-
-namespace Fluidbook\Tools\Jobs;
-
-use Cubist\Util\Files\Files;
-use Fluidbook\Tools\PDF\Document;
-use Illuminate\Bus\Queueable;
-use Illuminate\Contracts\Queue\ShouldQueue;
-use Illuminate\Foundation\Bus\Dispatchable;
-use Illuminate\Queue\InteractsWithQueue;
-use Illuminate\Queue\SerializesModels;
-use Cubist\Util\CommandLine;
-
-
-class ProcessPage implements ShouldQueue
-{
- use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
-
- /**
- * @var Document
- */
- protected $document;
-
- /**
- * @var integer
- */
- protected $page;
-
- /**
- * @var ProcessFile[]
- */
- protected $files = [];
-
- /**
- * @param $document Document
- * @param $page integer
- * @param ProcessFile[] $files
- */
- public function __construct($document, $page, $files = [])
- {
- $this->document = $document;
- $this->page = $page;
- $this->files = $files;
- }
-
- /**
- * @param int $page
- */
- public function setPage(int $page): void
- {
- $this->page = $page;
- }
-
- /**
- * @return int
- */
- public function getPage(): int
- {
- return $this->page;
- }
-
- /**
- * @return string
- */
- public function getOut(): string
- {
- return $this->document->getConvertPath();
- }
-
- public function handle()
- {
- start_measure('Process page ' . $this->page);
- foreach ($this->files as $file) {
- $this->getFile($this->page, $file, false);
- }
- stop_measure('Process page ' . $this->page);
- }
-
-
- /**
- * @param $page
- * @param $file ProcessFile
- * @param false $force
- * @return string
- */
- public function getFile($page, $file, $force = false)
- {
- $this->setPage($page);
- $file->setJob($this);
- return $file->getPath($force);
- }
-
- public function getResolutionRatio()
- {
- return $this->document->getResolutionRatio();
- }
-
- public function getMobileFirstRatio()
- {
- return $this->document->getMobileFirstRatio();
- }
-
- public function splitDoc()
- {
- start_measure('Split PDF');
-
- Files::mkdir($this->getOut() . '/pdf');
- $pdftk = new CommandLine('pdftk');
- $pdftk->setArg(null, $this->getPDFInput());
- $pdftk->setArg(null, 'burst');
- $pdftk->setArg(null, 'uncompress');
- $pdftk->setArg(null, 'output');
- $pdftk->setArg(null, $this->getOut() . 'pdf/p%d.pdf');
- $pdftk->execute();
-
-
- for ($i = 1; $i <= $this->getPagesNumber(); $i++) {
- // Remove annotations : https://gist.github.com/stefanschmidt/5248592
- $file = sprintf($this->getOut() . 'pdf/p%d.pdf', $i);
- $to = sprintf($this->getOut() . 'pdf/s%d.pdf', $i);
- `LANG=C LC_CTYPE=C sed -n '/^\/Annots/!p' $file > $to`;
- if (file_exists($to)) {
- if (filesize($to) > 0) {
- unlink($file);
- rename($to, $file);
- } else {
- unlink($to);
- }
- }
- }
- stop_measure('Split PDF');
- }
-
- /**
- * @return int
- */
- public function getPagesNumber()
- {
- return $this->document->getPages();
- }
-
- public function getPDFInput()
- {
- return $this->document->getPDFInput();
- }
-}
+++ /dev/null
-<?php
-
-namespace Fluidbook\Tools\PDF;
-
-use Cubist\Util\Text;
-use Fluidbook\Tools\CommandLine\FWSTK;
-use Fluidbook\Tools\Jobs\ProcessFile;
-use Fluidbook\Tools\Jobs\ProcessPage;
-
-class Document
-{
- protected $in;
-
- /**
- * @var string
- */
- protected $hash = null;
-
- /**
- * @var int
- */
- protected $pages = 0;
-
- /**
- * @var float
- */
- protected $width;
- /**
- * @var float
- */
- protected $height;
-
- /**
- * @var array
- */
- protected $pageNumbers = [];
-
- /**
- * @var array
- */
- protected $chapters = [];
-
- public function __construct($in)
- {
- $this->in = $in;
- }
-
- /**
- * @return string
- */
- public function getHash(): string
- {
- if (null === $this->hash) {
- $this->hash = hash_file('sha256', $this->in, false);
- }
- return $this->hash;
- }
-
- public function getConvertPath(): string
- {
- return storage_path('fluidbook/convert/' . $this->getHash() . '/');
- }
-
- /**
- * @throws \Exception
- */
- public function getInfos($force = false)
- {
- if (!$force && $this->pages > 0) {
- return;
- }
-
- $fwstk = new FWSTK();
- $fwstk->setArg('--input ' . $this->getPDFInput());
- $fwstk->setArg('--infos');
- $fwstk->execute();
-
- $infos = $fwstk->getOutput();
-
-
- if (preg_match('/Pages:\s*(\d+)/', $infos, $matches)) {
- $this->pages = (int)$matches[1];
- if ($this->pages <= 0) {
- throw new \Exception('Unable to get pages number');
- }
- }
- if (preg_match('/Page 1 size:\s*([0-9.]+)[ptsx\s]+([0-9.]+)/', $infos, $matches)) {
- $this->width = (float)$matches[1];
- $this->height = (float)$matches[2];
- }
-
- if (preg_match('/NumberSections:\s*(.*)/', $infos, $matches)) {
- $this->pageNumbers = explode(',', $matches[1]);
- } else {
- $this->pageNumbers = range(1, $this->pages);
- }
-
- if ($this->pages <= 0) {
- throw new \Exception(sprintf('Error running FWSTK %s', $infos));
- }
-
- $lines = Text::explodeNewLines($infos);
- $bookmark_id = -1;
-
- foreach ($lines as $line) {
- $line = trim($line);
- [$k, $v] = explode(':', $line);
- $k = trim($k);
- $v = trim($v);
-
- if ($k === 'BookmarkTitle') {
- $bookmark_id++;
- $this->chapters[$bookmark_id] = new \stdClass();
- $this->chapters[$bookmark_id]->label = html_entity_decode($v);
- } elseif ($k === 'BookmarkLevel') {
- $this->chapters[$bookmark_id]->level = (int)$v - 1;
- } elseif ($k === 'BookmarkPage') {
- $this->chapters[$bookmark_id]->page = $v;
- }
- }
- }
-
- /**
- * @return int
- */
- public function getPages()
- {
- $this->getInfos();
- return $this->pages;
- }
-
- /**
- * @return float
- */
- public function getHeight()
- {
- $this->getInfos();
- return $this->height;
- }
-
- /**
- * @return float
- */
- public function getWidth()
- {
- $this->getInfos();
- return $this->width;
- }
-
- /**
- * @param ProcessFile[] $files
- * @param array $pages
- * @param bool $sync
- */
- public function processPages($files, $pages, $sync = false)
- {
- start_measure('Process pages (doc)');
- foreach ($pages as $i) {
- $this->processPage($i, $files, $sync);
- }
- stop_measure('Process pages (doc)');
- }
-
- /**
- * @param $page int
- * @param $dest string
- * @param $files ProcessFile[]
- * @param false $sync
- */
- public function processPage($page, $files, $sync = false)
- {
- $dispatchFunction = $sync ? 'dispatchSync' : 'dispatch';
- ProcessPage::$dispatchFunction($this, $page, $files);
- }
-
- public function processLinks()
- {
- PDFTools::extractLinks($this->getPDFInput(), $this->getConvertPath());
- }
-
- public function processTexts()
- {
- start_measure('Extract texts');
- PDFTools::extractTexts($this->getPDFInput(), $this->getConvertPath());
- stop_measure('Extract texts');
- start_measure('Get highlights data');
- PDFTools::extractHighlightsData($this->getPDFInput(), $this->getConvertPath());
- stop_measure('Get highlights data');
- }
-
- public function getPageNumbers()
- {
- $this->getInfos();
- return $this->pageNumbers;
- }
-
- public function getChapters()
- {
- $this->getInfos();
- return $this->chapters;
- }
-
- public function getResolutionRatio()
- {
- $a4surface = 500990; // en pt²
- $docSurface = $this->getWidth() * $this->getHeight(); // 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 getMobileFirstRatio()
- {
- return 620 / $this->getWidth();
- }
-
- public function getPDFInput()
- {
- return $this->in;
- }
-}
+++ /dev/null
-<?php
-
-namespace Fluidbook\Tools\PDF;
-
-use Cubist\Util\CommandLine;
-use Cubist\Util\Files\Files;
-use DOMDocument;
-use DOMNode;
-use DOMXPath;
-use Fluidbook\Tools\CommandLine\FWSTK;
-
-class PDFTools
-{
- public static function makeMiniShot($in, $out, $page, $format = 'jpg')
- {
- self::makeShotFixedWidth($in, $out, $page, 'p', 500, 65, 4, 'PNM', $format);
- }
-
- public static function makeShotFixedWidth($in, $out, $page, $prefix = '', $w = 100, $quality = 90, $antialiasing = 4, $method = 'PNM', $format = 'jpg')
- {
- // Make thumbs of $w width
- self::makeShot($in, $out, $page, $prefix, null, $quality, $antialiasing, $method, $w, -1, $format);
- }
-
- public static function makeShotFixedHeight($in, $out, $page, $prefix = '', $h = '', $quality = 90, $antialiasing = 4, $method = 'PNM', $format = 'jpg')
- {
- // Make thumbs of $h height
- self::makeShot($in, $out, $page, $prefix, null, $quality, $antialiasing, $method, -1, $h, $format);
- }
-
- public static function makeSWF($in, $out, $page, $resolution = 100, $quality = 90)
- {
- if (file_exists($out)) {
- unlink($out);
- }
- $pdf2swf = new CommandLine('pdf2swf', null, true);
- $pdf2swf->setArg('p', $page);
- $pdf2swf->setArg('T', 10);
- $pdf2swf->setArg('Q', 30);
- $pdf2swf->setArg('set reordertags', '0');
- $pdf2swf->setArg('fonts');
- $pdf2swf->setArg('set storeallcharacters');
- $pdf2swf->setArg('set subpixels', $resolution / 72);
- $pdf2swf->setArg('set jpegquality', $quality);
- $pdf2swf->setArg('set disablelinks');
- $pdf2swf->setArg('set dots');
- $pdf2swf->setArg(null, $in);
- $pdf2swf->setArg('output', $out);
- $pdf2swf->execute();
- $pdf2swf->debug();
-
- if (file_exists($out)) {
- return;
- }
- $pdf2swf = new CommandLine('pdf2swf', null, true);
- $pdf2swf->setArg('p', $page);
- $pdf2swf->setArg('T', 10);
- $pdf2swf->setArg('Q', 120);
- $pdf2swf->setArg('set poly2bitmap');
- $pdf2swf->setArg('set storeallcharacters');
- $pdf2swf->setArg('set reordertags', '0');
- $pdf2swf->setArg('fonts');
- $pdf2swf->setArg('set subpixels', $resolution / 72);
- $pdf2swf->setArg('set jpegquality', $quality);
- $pdf2swf->setArg('set disablelinks');
- $pdf2swf->setArg('set dots');
- $pdf2swf->setArg(null, $in);
- $pdf2swf->setArg('output', $out);
- $pdf2swf->execute();
- $pdf2swf->debug();
- if (file_exists($out)) {
- return;
- }
- $pdf2swf = new CommandLine('pdf2swf', null, true);
- $pdf2swf->setArg('p', $page);
- $pdf2swf->setArg('T', 10);
- $pdf2swf->setArg('set reordertags', '0');
- $pdf2swf->setArg('fonts');
- $pdf2swf->setArg('set bitmap');
- $pdf2swf->setArg('set storeallcharacters');
- $pdf2swf->setArg('set subpixels', $resolution / 72);
- $pdf2swf->setArg('set jpegquality', $quality);
- $pdf2swf->setArg('set disablelinks');
- $pdf2swf->setArg('set dots');
- $pdf2swf->setArg(null, $in);
- $pdf2swf->setArg('output', $out);
- $pdf2swf->execute();
- $pdf2swf->debug();
- }
-
-
- public static function makeBaseSVGFile($in, $out, $page)
- {
- $pdftocairo = new CommandLine('pdftocairo');
- $pdftocairo->setArg('f', $page);
- $pdftocairo->setArg('l', $page);
- $pdftocairo->setArg('r', 300);
- $pdftocairo->setArg(null, '-expand');
- $pdftocairo->setArg(null, '-svg');
- $pdftocairo->setArg(null, $in);
- $pdftocairo->setArg(null, $out);
- $pdftocairo->execute();
- }
-
- public static function makeTextSVGFile($in, $out)
- {
- $svg = new DOMDocument();
- $svg->preserveWhiteSpace = false;
- $svg->load($in, 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");
- $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:defs/svg:g[starts-with(@id, "surface")]//svg:rect',
- '//svg:defs/svg:g[starts-with(@id, "surface")]//svg:use[starts-with(@xlink:href, "#image")]',
- '/svg:svg/svg:g[@id="surface1"]//svg:path',
- '/svg:svg/svg:g[@id="surface1"]//svg:rect',
- '/svg:svg/svg:g[@id="surface1"]//svg:filter',
- '/svg:svg/svg:g[@id="surface1"]//svg:use[starts-with(@xlink:href, "#image")]',
- '//svg:svg/svg:g[@id="surface1"]//svg:use[starts-with(@xlink:href, "#image")]',
- //'//svg: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($out, $svg->saveXML());
- }
-
- public static function makeShot($in, $out, $page, $prefix = '', $resolution = 72, $quality = 90, $antialiasing = 4, $method = 'PNM', $width = null, $height = null, $format = 'jpg')
- {
- $error = false;
- if ($method === 'GS') {
- self::makeShotGS($in, $out, $page, $prefix, $resolution, $quality, $antialiasing, $width, $height, $format);
- } elseif ($method === 'PNM') {
- self::makeShotPNM($in, $out, $page, $prefix, $resolution, $quality, $antialiasing, true, $width, $height, $format);
- }
- // Test the result by checking all files
- if (!file_exists($out)) {
- $error = true;
- }
- // If error, we try to make thumbs with other method
- if ($error) {
- if ($method === 'GS') {
- self::makeShotPNM($in, $out, $page, $prefix, $resolution, $quality, $antialiasing, true, $width, $height, $format);
- } elseif ($method === 'PNM') {
- self::makeShotGS($in, $out, $page, $prefix, $resolution, $quality, $antialiasing, $width, $height, $format);
- }
- }
- }
-
- protected static function makeShotGS($in, $out, $page, $prefix = '', $resolution = 72, $quality = 90, $antialiasing = 4, $width = null, $height = null, $format = 'jpg')
- {
- // Fabrication des thumbnails avec ghostscript
- $gs = new CommandLine('gs', null, true);
- $gs->setArg('-dBATCH');
- $gs->setArg('-dNOPAUSE');
- $gs->setArg('-dNOPROMPT');
- // Antialias
- $gs->setArg('-dDOINTERPOLATE');
- $gs->setArg('-dTextAlphaBits=' . $antialiasing);
- $gs->setArg('-dGraphicsAlphaBits=' . $antialiasing);
- // Device
- $device = $format === 'jpg' ? 'jpeg' : 'png16m';
- $gs->setArg('-sDEVICE=' . $device);
- // Dispotion & colors
- // $gs->setArg('-dUseCIEColor');
- $gs->setArg('-dAutoRotatePages=/None');
- $gs->setArg('-dUseCropBox');
- // Resolution & Quality
- $gs->setArg('-r' . round($resolution));
- if ($format === 'jpg') {
- $gs->setArg('-dJPEGQ=' . $quality);
- }
- // Performances
- $gs->setArg('-dNumRenderingThreads=4');
- // Page range
- $gs->setArg('-dFirstPage=' . $page);
- $gs->setArg('-dLastPage=' . $page);
- // Files
- $gs->setArg('-sOutputFile=' . $out);
-
- $gs->setArg(null, $in);
- $gs->execute();
- }
-
- public static function makeShotPNM($in, $out, $page, $prefix = '', $resolution = 72, $quality = 90, $antialiasing = 4, $texts = true, $width = null, $height = null, $format = 'jpg')
- {
- $tmp = Files::tempnam();
-
- $antialiasing = $antialiasing ? 'yes' : 'no';
- $freetype = $texts ? 'yes' : 'no';
- // Exporte les fichiers
- $pdftoppm = new CommandLine('pdftoppm', null, true);
- $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);
- if (null !== $resolution) {
- $pdftoppm->setArg('r', $resolution);
- }
- if (null !== $width) {
- $pdftoppm->setArg('-scale-to-x ' . $width);
- }
- if (null !== $height) {
- $pdftoppm->setArg('-scale-to-y ' . $height);
- }
- $pdftoppm->setArg(null, $in);
- $pdftoppm->setArg(null, $tmp);
- $pdftoppm->execute();
- $tmp .= '.ppm';
-
-
- if (file_exists($tmp)) {
- if ($format === 'jpg') {
- $cjpeg = new CommandLine('cjpeg', null, true);
- $cjpeg->setArg('-quality ' . ($quality + 6));
- $cjpeg->setArg('-outfile ' . $out);
- $cjpeg->setArg(null, $tmp);
- $cjpeg->execute();
- } else if ($format === 'png') {
- $pnmtopng = new CommandLine('pnmtopng', $out, false);
- $pnmtopng->setArg('-background white');
- $pnmtopng->setArg(null, $tmp);
- $pnmtopng->execute();
- }
- unlink($tmp);
- } else {
- $pdftoppm->debug();
- }
- }
-
- public static function getThumbFromPDF($pdf, $page, $format = 'jpg')
- {
- if (!file_exists($pdf)) {
- return false;
- }
- $dir = WS_CACHE . '/thumbs/' . sha1($pdf) . '/';
- if (!file_exists($dir)) {
- mkdir($dir, 0777, true);
- }
- $image = $dir . '/p' . $page . '.' . $format;
- $mtime = filemtime($image);
-
- if (!file_exists($image) || $mtime < filemtime(__FILE__) || $mtime < filemtime($pdf)) {
- self::makeMiniShot($pdf, $image, $page, $format);
- }
-
- return $image;
- }
-
- public static function extractLinks($pdf, $out)
- {
- $out .= 'links/';
- Files::mkdir($out);
-
- if (file_exists($out . '/p1.csv')) {
- return;
- }
- $fwstk = new FWSTK();
- $fwstk->setArg('--input ' . $pdf);
- $fwstk->setArg('--extractLinks ' . $out . 'p%d.csv');
- $fwstk->setArg('--threads 1');
- $fwstk->execute();
- }
-
- public static function extractTexts($pdf, $out, $ignoreSeparators = '')
- {
- $out .= 'texts/';
- Files::mkdir($out);
-
- $fwstk = new FWSTK();
- $fwstk->setArg('--input ' . $pdf);
- $fwstk->setArg('--extractTexts ' . $out . '%s%d.txt');
- $fwstk->setArg('--extractTextsMethod fluidbook');
- $fwstk->setArg('--threads 1');
- if ($ignoreSeparators !== '') {
- $fwstk->setArg('--ignoreSeparators ' . $ignoreSeparators);
- }
- $fwstk->execute();
- }
-
- public static function extractHighlightsData($pdf, $out)
- {
- $out .= 'texts/';
- Files::mkdir($out);
-
- $fwstk = new FWSTK();
- $fwstk->setArg('--input ' . $pdf);
- $fwstk->setArg('--layout ' . $out . 'p%d.fby');
- $fwstk->setArg('--cmaps ' . $out);
- $fwstk->setArg('--fonts' . $out . 'fonts/web/');
- $fwstk->execute();
- $fwstk->dd();
-
- }
-
-}
+++ /dev/null
-<?php
-
-namespace Fluidbook\Tools\SVG;
-
-use Cubist\Util\Files\Files;
-use Fluidbook\Tools\FluidbookTools;
-
-class SVGTools
-{
- protected static $_r;
- protected static $_i;
- protected static $_e;
- protected static $_u;
-
- public static function optimizeSVG($in, $out = null)
- {
- if (null === $out) {
- $e = explode('.', $in);
- $ext = array_pop($e);
- $e[] = 'o';
- $e[] = $ext;
- $out = implode('.', $e);
- }
-
- return self::_optimizeSVG($in, $out);
- }
-
- public static function _optimizeSVG($in, $out)
- {
-
- $svg = shell_exec('timeout -s 1 120 ' . FluidbookTools::tools_path('svgcleaner/svgcleaner', true) . ' --allow-bigger-file --paths-coordinates-precision 3 --copy-on-error --stdout ' . $in);
- if (!$svg) {
- $svg = file_get_contents($in);
- }
- $svg = self::_disablePreserveRatio($svg);
- file_put_contents($out, $svg);
- return $out;
- }
-
- protected static function _disablePreserveRatio($in)
- {
- $str = 'preserveAspectRatio="none"';
- if (str_contains($in, $str)) {
- return $in;
- }
- return str_replace("<svg ", '<svg ' . $str . ' ', $in);
- }
-
- public static function optimizeSVGImages($in, $out, $resolution)
- {
- $svg = file_get_contents($in);
- $svg = preg_replace('/\<\?xml([^\?]*)\?\>/', '', $svg);
- $svg = self::_disablePreserveRatio($svg);
-
- $osvg = preg_replace_callback('|\<image([^>]*)\>|', function ($matches) use ($resolution) {
- return self::optimizeRaster($matches, $resolution);
- }, $svg);
- $osvg = preg_replace('/^<svg[^>]*>/', '$0<rect width="100%" height="100%" fill="white" />', $osvg);
- file_put_contents($out, $osvg);
- }
-
- protected static function _svg($c, $p)
- {
- self::$_i = 0;
- self::$_e = 0;
- self::$_u = 0;
-
- $c = str_replace(array('id="', 'url(#', 'xlink:href="#'), array('id="p' . $p . '-', 'url(#p' . $p . '-', 'xlink:href="#p' . $p . '-'), $c);
- $c = preg_replace_callback('/\<image([^\>]*)\>/m', function ($matches) use ($p) {
- self::$_i++;
- return '<g id="p' . $p . '-imageholder-' . self::$_i . '"><image id="p' . $p . '-image-' . self::$_i . '" ' . $matches[1] . '></g>';
- }, $c);
- $c = str_replace('</image>', '</image></g></g>', $c);
-
- $c = preg_replace_callback('/<path /', function () use ($p) {
- self::$_e++;
- return '<path id="p' . $p . '-e-' . self::$_e . '" ';
- }, $c);
- $c = preg_replace_callback('/<use /', function () use ($p) {
- self::$_u++;
- return '<use id="p' . $p . '-u-' . self::$_u . '" ';
- }, $c);
-
- return $c;
- }
-
- public static function optimizeRaster($matches, $resolution)
- {
- preg_match_all('/([a-z\:\-]*)="([^"]*)"/', $matches[1], $m);
-
- foreach ($m[1] as $i => $key) {
- $attrs[$key] = $m[2][$i];
- }
- $e = explode(',', $attrs['xlink:href'], 2);
- $image = imagecreatefromstring(base64_decode($e[1]));
- $iw = imagesx($image);
- $ih = imagesy($image);
- $scale = 1;
- if (isset($attrs['transform']) && strpos($attrs['transform'], 'matrix(') === 0) {
- preg_match_all('/([\d\-\.]+)/', $attrs['transform'], $ma);
- $values = $ma[0];
- $scale = max($values[0], $values[1]);
- }
-
- $resolutionScale = ($iw / $attrs['width']) * $scale * ($resolution / 72);
-
- $dw = round($resolutionScale * $iw);
- $dh = round($resolutionScale * $ih);
-
- $im = imagecreatetruecolor($dw, $dh);
- imagecopyresampled($im, $image, 0, 0, 0, 0, $dw, $dh, $iw, $ih);
- imagedestroy($image);
-
- $tmp = Files::tempnam();
- imagejpeg($im, $tmp, 85);
- imagedestroy($im);
-
- $attrs['xlink:href'] = 'data:image/jpeg;base64,' . base64_encode(file_get_contents($tmp));
- unlink($tmp);
-
- $res = '<image ';
- foreach ($attrs as $k => $v) {
- $res .= $k . '="' . $v . '" ';
- }
- $res .= '/>';
- return $res;
- }
-}
+++ /dev/null
-<?php
-
-namespace Fluidbook\Tools\Search;
-
-use JsonException;
-use stdClass;
-
-class Page
-{
- protected $_documentPage;
- protected $_path;
-
- public function __construct($documentPage, $path)
- {
- $this->_documentPage = $documentPage;
- $this->_path = $path;
- }
-
- /**
- * @return array
- * @throws JsonException
- */
- public function getHighlights(): array
- {
- return json_decode(file_get_contents($this->_path . '/p' . $this->_documentPage . '.fby'), false, 512, JSON_THROW_ON_ERROR);
- }
-
- /**
- * @return string
- */
- public function getIndex(): string
- {
- return trim(file_get_contents($this->_path . '/fi' . $this->_documentPage . '.txt'));
- }
-}
+++ /dev/null
-<?php
-
-namespace Fluidbook\Tools\Search;
-
-use JsonException;
-use stdClass;
-
-class SearchIndex
-{
- /**
- * @var Page[]
- */
- protected $_pages = [];
-
- public function addPage($page, $documentPage, $path)
- {
- $this->_pages[$page] = new Page($documentPage, $path);
- }
-
- /**
- * @return array
- */
- public function compileIndex()
- {
- $index = [];
- foreach ($this->_pages as $pageNumber => $page) {
- $twords = explode("\n", $page->getIndex());
-
- foreach ($twords as $woadata) {
- $w1 = explode(',', trim($woadata));
- if (count($w1) <= 1) {
- continue;
- }
- list($woa, $worddata) = $w1;
- $e = explode("\t", $worddata, 2);
- if (count($e) < 2) {
- continue;
- }
- list($total, $wordslist) = $e;
-
- if ($woa === '') {
- continue;
- }
-
- if (!isset($index[$woa])) {
- $index[$woa] = array('t' => 0, 'w' => array());
- }
- $index[$woa]['t'] += (int)$total;
-
- $words = explode("\t", $wordslist);
-
- foreach ($words as $word) {
- list($wordwa, $count) = explode('$', $word, 2);
- if (!isset($index[$woa]['w'][$wordwa])) {
- $index[$woa]['w'][$wordwa] = array('t' => 0, 'p' => [$pageNumber => 0]);
- }
- if (!isset($index[$woa]['w'][$wordwa]['p'][$pageNumber])) {
- $index[$woa]['w'][$wordwa]['p'][$pageNumber] = 0;
- }
- $index[$woa]['w'][$wordwa]['t'] += (int)$count;
- $index[$woa]['w'][$wordwa]['p'][$pageNumber] += (int)$count;
- }
- }
- }
- return $index;
- }
-
-
- /**
- * @return stdClass
- * @throws JsonException
- */
- public function compileHighlights()
- {
- $res = new stdClass();
- foreach ($this->_pages as $pageNumber => $page) {
- $words = $page->getHighlights();
- foreach ($words as $i => $w) {
- $word = $w->word;
- $word = trim($word, "\0");
- if ($word === '') {
- continue;
- }
- unset($w->word);
- $w->page = $pageNumber;
- $w->idx = $i;
- if (!isset($res->{$word})) {
- $res->{$word} = array();
- }
- $res->{$word}[] = $w;
- }
- }
- return $res;
- }
-}
}
}
}
- file_put_contents($out, $svg->saveXML());
+ $res = $svg->saveXML();
+ $res = preg_replace('/<g clip-path="url\(#clip\d+\)" clip-rule="nonzero"\/>/', '', $res);
+ while (true) {
+ $res = preg_replace('/<g clip-path="url\(#clip\d+\)" clip-rule="nonzero"><\/g>/', '', $res, -1, $count);
+ if (!$count) {
+ break;
+ }
+ }
+
+ file_put_contents($out, $res);
}
public static function makeShot($in, $out, $page, $prefix = '', $resolution = 72, $quality = 90, $antialiasing = 4, $method = 'PNM', $width = null, $height = null, $format = 'jpg')