From: vincent@cubedesigners.com Date: Tue, 9 Dec 2014 15:24:22 +0000 (+0000) Subject: (no commit message) X-Git-Url: http://git.cubedesigners.com/?a=commitdiff_plain;h=efe9143430b0ca142138a23ec88ad007b2960fdb;p=cubeextranet.git --- diff --git a/inc/commons/Metier/class.common.entreprise.php b/inc/commons/Metier/class.common.entreprise.php index bfbb0a2fe..c05ba2111 100644 --- a/inc/commons/Metier/class.common.entreprise.php +++ b/inc/commons/Metier/class.common.entreprise.php @@ -15,6 +15,7 @@ class commonEntreprise extends cubeMetier { protected $ws_admin; protected $ws_grade; protected $ws_signatures; + protected $type; // Composés protected $ca; protected $impaye; diff --git a/inc/ws/Controlleur/class.ws.users.tree.php b/inc/ws/Controlleur/class.ws.users.tree.php index ca377e954..5754e9b32 100644 --- a/inc/ws/Controlleur/class.ws.users.tree.php +++ b/inc/ws/Controlleur/class.ws.users.tree.php @@ -64,17 +64,17 @@ class wsUsersTree { $c->facturable_id = $facturable_id; $ce->facturable_entreprise_id = $c->facturable_entreprise_id = $this->entreprises[$facturable_id]; $ce->administrateur_id = $c->administrateur_id = $administrateur_id; - try { - $c->insert(); - } catch (Exception $e) { + try{ + $c->insert(); + }catch(Exception $e){ fb($e); } if (isset($evu[$c->entreprise_id])) { continue; } - try { - $ce->insert(); - } catch (Exception $e) { + try{ + $ce->insert(); + }catch(Exception $e){ fb($e); } $evu[$c->entreprise_id] = true; diff --git a/inc/ws/Metier/class.ws.parametres.php b/inc/ws/Metier/class.ws.parametres.php index 5fc7591bc..9ac085d1c 100644 --- a/inc/ws/Metier/class.ws.parametres.php +++ b/inc/ws/Metier/class.ws.parametres.php @@ -107,8 +107,10 @@ class wsParametres extends cubeMetier implements Iterator { $value = cubeMath::fill(ltrim($value, '#'), 6); break; case 'couleurAlpha': + fb($value); $value = cubeMath::fill(ltrim($value, '#'), 6); - $value = cubeMath::fill($value, 8, 'f'); + $value = cubeMath::fill($value,8,'f'); + fb($value); break; case 'date': if (!is_int($value)) { 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..bc76aedd0 --- /dev/null +++ b/inc/ws/Util/class.ws.pdf.fontextractor.php @@ -0,0 +1,470 @@ +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) { + $descendant = array_keys($this->descendantNames, $fontname); + if (count($descendant)) { + $f = array_keys($this->descendants, $descendant[0]); + $fontname = $f[0]; + } + + + $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 + * + 10 0 obj + << + /BaseFont /FuturaLT-Bold--Identity-H + /DescendantFonts [ 11 0 R ] + /Encoding /Identity-H + /Name /F0 + /Subtype /Type0 + /ToUnicode 3881 0 R + /Type /Font + >> + 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]; + } + + if ($e[0] == '/DescendantFonts') { + $this->fonts[$currentFont]['descendant'] = $e[1]; + $this->descendants[$fontname] = $e[1]; + } + } + + $this->manageDescendants(); + + $this->addToLog(print_r($this->fonts, true)); + } + + protected function manageDescendants() { + if (!count($this->descendants)) { + return; + } + + $pdfshow = $this->getCommandLine('pdfshow'); + $pdfshow->setArg(null, $this->in); + $pdfshow->setManualArg(implode(' ', $this->descendants)); + $pdfshow->execute(); + $this->doc->addToLog($pdfshow); + + /* + 11 0 obj + << + /BaseFont /EHLOJB+FuturaLT-Bold-OV-JVKOJB + /CIDSystemInfo << + /Ordering (Identity) + /Registry (Adobe) + /Supplement 0 + >> + /DW 343 + /FontDescriptor 3878 0 R + /Name /F0 + /Subtype /CIDFontType0 + /Type /Font + /W [ 1 [ 781 ] 4 [ 781 ] 9 [ 677 660 ] 12 [ 752 550 550 550 ] + 17 [ 550 ] 20 [ 542 842 803 324 ] 26 [ 324 ] 28 [ 489 ] 30 + [ 495 ] 32 [ 983 881 ] 35 [ 887 ] 43 [ 661 887 680 616 ] + 48 [ 533 ] 50 [ 778 ] 55 [ 761 ] 57 [ 789 ] 61 [ 707 ] 63 + [ 682 ] 77 [ 682 ] 87 [ 483 ] 93 [ 343 343 ] 97 [ 682 ] 106 + [ 610 610 610 ] 111 [ 686 ] 119 [ 388 ] 121 [ 689 ] 124 [ + 686 ] 126 [ 677 ] 134 [ 661 ] 136 [ 392 ] 138 [ 302 ] 140 + [ 302 302 ] 149 [ 989 ] 154 [ 661 ] 156 [ 686 ] 159 [ 662 ] + 167 [ 686 ] 175 [ 682 ] 180 [ 343 ] 193 [ 372 ] 196 [ 453 ] + 199 [ 513 ] 203 [ 686 686 ] 208 [ 360 ] 210 [ 686 ] 215 [ + 686 ] 217 [ 659 ] 232 [ 686 ] ] + >> + endobj + + */ + + $currentDescendant = null; + $lines = explode("\n", $pdfshow->output); + foreach ($lines as $line) { + $line = trim($line); + $e = explode(' ', $line); + if (count($e) == 3 && $e[2] == "obj") { + $currentDescendant = $e[0]; + } + if ($line == 'endobj') { + $currentDescendant = null; + } + + if (is_null($currentDescendant)) { + continue; + } + + if ($e[0] == '/BaseFont') { + $this->descendantNames[$currentDescendant] = trim($e[1], "/"); + } + } + + $this->addToLog('Descendant names : ' . print_r($this->descendantNames, 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) == 2 && $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(); + } + + if (strlen($to) >= 8) { + $toc = $to; + $to = $this->manageLigatures($to); + $this->addToLog('Correct ligature ' . $toc . ' -> ' . $to); + } + + $finalCmaps[$fontname][$from] = $to; + } + } + + foreach ($finalCmaps as $fontname => $cmap) { + arsort($cmap); + $data = ''; + foreach ($cmap as $from => $to) { + $data.=$from . "\t" . $to . "\n"; + } + + $this->addToLog('Write cmap for font ' . $fontname . ' in ' . $this->outpdf . '/' . $fontname . '.cmap'); + + file_put_contents($this->outpdf . '/' . $fontname . '.cmap', $data); + } + } + + protected function manageLigatures($code) { + $codes = str_split($code, 4); + $str = ''; + foreach ($codes as $c) { + $str.=chr(intval($c, 16)); + } + + $ligatures = array('AE' => '00C6', 'ae' => '00E6', + 'OE' => '0152', 'oe' => '0152', + 'IJ' => '0132', 'ij' => '0133', + 'ff' => 'fb00', + 'fi' => 'fb01', + 'fl' => 'fb02', + 'ffi' => 'fb03', + 'ffl' => 'fb04'); + + // Si un couple est une ligature standard + if (isset($ligatures[$str])) { + return $ligatures[$str]; + } + // Sinon, on ne retourne que le premier code + return $codes[0]; + } + + 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"; + } + } + +} + +?> diff --git a/inc/ws/Util/class.ws.pdf.fontextractor.php.php b/inc/ws/Util/class.ws.pdf.fontextractor.php.php new file mode 100644 index 000000000..dcb4cfb4d --- /dev/null +++ b/inc/ws/Util/class.ws.pdf.fontextractor.php.php @@ -0,0 +1,331 @@ +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()) { + $fontforge->setArg(null, '-'); + } else { + $fontforge->setArg(null, $cmapFile); + } + $fontforge->setArg(null, $this->outweb . '/' . $fontname . '.ttf'); + $fontforge->execute(); + $this->doc->addToLog($fontforge); + } + } + + public function getFonts() { + $pdfinfo = $this->getCommandLine('pdfinfo'); + $pdfinfo->setArg('f'); + $pdfinfo->setArg(null, $this->in); + $pdfinfo->execute(); + + $this->doc->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 ($e[2] == 'obj') { + $currentFont = $e[0]; + continue; + } + + if (is_null($currentFont)) { + continue; + } + + $fontname = $this->fonts[$currentFont]['name']; + + if ($e[0] == '/FontDescriptor') { + $this->fonts[$currentFont]['descriptor'] = $e[1]; + if (!isset($this->descriptors[$fontname])) { + $this->descriptors[$fontname] = array(); + } + $this->descriptors[$fontname][] = $e[1]; + } else if ($e[0] == 'ToUnicode') { + $this->fonts[$currentFont]['cmap'] = $e[1]; + $this->cmaps[$fontname] = $e[1]; + } + } + } + + protected function extractFonts() { + $descriptors = $this->getUniqueId('descriptor'); + + $pdfextract = $this->getCommandLine('pdfextract'); + $pdfextract->setArg(null, $this->in); + $pdfextract->setManualArg(implode(' ', $descriptors)); + $pdfextract->execute(); + $this->doc->addToLog($pdfextract); + } + + protected function extractCmaps() { + $cmaps = array_unique($this->cmaps); + + $pdfshow = $this->getCommandLine('pdfshow'); + $pdfshow->setArg(null, $this->in); + $pdfshow->setManualArg(implode(' ', $cmaps)); + $pdfshow->execute(); + $this->doc->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 ($e[2] == 'obj') { + $currentCmap = $e[0]; + continue; + } + + if ($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); + } + + protected function getCommandLine($program) { + $res = new cubeCommandLine('/usr/local/mupdf/' . $program); + $res->cd($this->outpdf); + $res->setPath(CONVERTER_PATH); + return $res; + } + +} + +?> diff --git a/inc/ws/Util/packager/class.ws.packager.air.php b/inc/ws/Util/packager/class.ws.packager.air.php index 21fec508b..f0d64a8ea 100644 --- a/inc/ws/Util/packager/class.ws.packager.air.php +++ b/inc/ws/Util/packager/class.ws.packager.air.php @@ -1,7 +1,16 @@ diff --git a/inc/ws/Util/packager/class.ws.packager.html5.php b/inc/ws/Util/packager/class.ws.packager.html5.php new file mode 100644 index 000000000..3defc0aa6 --- /dev/null +++ b/inc/ws/Util/packager/class.ws.packager.html5.php @@ -0,0 +1,578 @@ +version = 'html5'; + } + + protected function preparePackage() { + parent::preparePackage(); + + foreach ($this->pages as $page => $infos) { + $file = WS_DOCS . '/' . $infos['document_id'] . '/html/p' . $infos['document_page'] . '.layout'; + if (file_exists($file)) { + $this->layouts[$page] = simplexml_load_file($file, null, LIBXML_ERR_WARNING); + } + } + + $imagesize = getimagesize(WS_DOCS . '/' . $this->pages[1]['document_id'] . '/html/h72-' . $this->pages[1]['document_page'] . '.jpg'); + $this->pdf2htmlRatio = $imagesize[0] / $this->layouts[1]['width']; + $this->scale = 4; + $this->multiply = $this->pdf2htmlRatio * $this->scale; + + $this->createHTML(); + } + + public function makePackage() { + parent::makePackage(); + return $this->zip(); + } + + protected function createHTML() { + foreach ($this->layouts as $page => $layout) { + $this->div[$page] = array(); + $document_id = $this->pages[$page]['document_id']; + foreach ($layout->l as $line) { + $this->div[$page][] = $this->addLine($line, $document_id); + } + } + mkdir($this->vdir . '/data/images', 0777, true); + mkdir($this->vdir . '/data/contents', 0777, true); + mkdir($this->vdir . '/data/background', 0777, true); + mkdir($this->vdir . '/data/style', 0777, true); + + foreach ($this->div as $n => $page) { + file_put_contents($this->vdir . '/data/contents/p' . $n . '.html', $this->writePage($page)); + } + $this->writeFonts(); + $this->writeImages(); + $this->writeLinks(); + $this->writeCSS($this->vdir . '/data/style/style_%d.css'); + + file_put_contents($this->vdir . '/data/datas.js', $this->writeConfig()); + } + + protected function writeLinks() { + global $core; + $daoDoc = new wsDAODocument($core->con); + $daoDoc->getLinksAndRulers($this->book_id, $links, $rulers); + + foreach ($links as $link) { + fb($link); + } + } + + protected function writeConfig() { + $config = cubeObject::merge($this->book->parametres->toStandardObject(), $this->theme->parametres->toStandardObject()); + $config->id = $this->book->book_id; + return 'DATAS=' . json_encode($config) . ';'; + } + + protected function writeFonts() { + $fext = array('ttf', 'eot', 'svg', 'svgz', 'woff'); + foreach ($this->cssFont as $font => $index) { + list($font, $document_id) = explode('//', $font); + foreach ($fext as $ext) { + copy(WS_DOCS . '/' . $document_id . "/fonts/web/" . $font . '.' . $ext, $this->vdir . '/data/style/F' . $index . '.' . $ext); + } + } + } + + protected function writeIcons() { + $res = array(); + // Get the colors used to colorize graphics + if ($this->theme->parametres->colorizeIcons) { + $couleurI = '#' . $this->theme->parametres->couleurI; + } else { + $couleurI = '#FFFFFF'; + } + $arrowsColor = '#' . $this->theme->parametres->arrowsColor; + // Set the icon list with the color + $icons = array('nav-bookmark' => $couleurI, 'nav-friend' => $couleurI, 'nav-help' => $couleurI, 'nav-index' => $couleurI, 'nav-sommaire' => $couleurI, + 'next' => $arrowsColor, 'previous' => $arrowsColor, 'search' => $couleurI); + + foreach ($icons as $icon => $color) { + wsTools::colorizeAndRasterizeIcon($this->theme->parametres->iconSet, $icon, $color, $this->vdir . '/data/images/',4, $w, $h); + $res[] = '#icon-' . $icon . '{width:' . $w . 'px;height:' . $h . 'px;background-image:url(data/images/' . $icon . '.svg), url(data/images/' . $icon . '.png);background-repeat:no-repeat;background-size:' . $w . 'px ' . $h . 'px}'; + } + return $res; + } + + protected function writeImages() { + + foreach (self::$resolutions as $r) { + mkdir($this->vdir . '/data/background/' . $r, 0777); + } + foreach ($this->pages as $page => $infos) { + foreach (self::$resolutions as $r) { + copy(WS_DOCS . '/' . $infos['document_id'] . '/html/h' . $r . '-' . $infos['document_page'] . '.jpg', $this->vdir . '/data/background/' . $r . '/p' . $page . '.jpg'); + } + } + } + + protected function writePage($page) { + $res = ''; + foreach ($page as $line) { + $res .= $this->writeLine($line); + } + return $res; + } + + protected function writeLine($line) { + $line['x'] = $this->getCSSX($line['x'] * $this->multiply); + $line['y'] = $this->getCSSY($line['y'] * $this->multiply); + + $class = array('l'); + if (!is_null($line['rotation'])) { + $class[] = 'r' . $line['rotation']; + } + if (!is_null($line['x'])) { + $class[] = 'x' . $line['x']; + } + if (!is_null($line['y'])) { + $class[] = 'y' . $line['y']; + } + $class = implode(' ', $class); + + + $res = '
'; + foreach ($line['groups'] as $group) { + $res.=$this->writeGroup($group); + } + $res.='
'; + return $res; + } + + protected function writeGroup($group) { + if ($group === false) { + return ''; + } + + $group['y'] = $this->getCSSY($group['y'] * $this->multiply); + $group['x'] = $this->getCSSX($group['x'] * $this->multiply); + + $class = array('g'); + if (!is_null($group['color'])) { + $class[] = 'c' . $group['color']; + } + if (!is_null($group['size'])) { + $class[] = 's' . $group['size']; + } + if (!is_null($group['font'])) { + $class[] = 'f' . $group['font']; + } + if (!is_null($group['x'])) { + $class[] = 'x' . $group['x']; + } + if (!is_null($group['y'])) { + $class[] = 'y' . $group['y']; + } + if (!is_null($group['letterspacing'])) { + $class[] = 'l' . $group['letterspacing']; + } + if (!is_null($group['wordspacing'])) { + $class[] = 'w' . $group['wordspacing']; + } + $class = implode(' ', $class); + + $res = '
'; + foreach ($group['spans'] as $span) { + $res.=$this->writeSpan($span); + } + $res.='
'; + return $res; + } + + protected function writeSpan($span) { + if ($span === false) { + return ''; + } + + return self::escapeHTML($span['text']); + } + + protected function writeCSS($file) { + $res = array(); + + // General theme + $h = $this->book->parametres->height . 'px'; + $w2 = ($this->book->parametres->width * 2) . 'px'; + $w = $this->book->parametres->width . 'px'; + $wm = ($this->book->parametres->width * $this->multiply) . 'px'; + $hm = ($this->book->parametres->height * $this->multiply) . 'px'; + + + $navTop = ($this->book->parametres->height - 40 - 100) / 2; + $res[] = '.portrait #pages,.portrait .doublePage.page,.page,.portrait #shadow,#shadow.single{width:' . $w . ';max-width:' . $w . ';height:' . $h . ';max-height:' . $h . '}'; + $res[] = '.background{' . $this->writeCSSUA('transform-origin', 'top left') . ';}'; + foreach (self::$resolutions as $r) { + $ratio = 72 / $r; + $wr = $this->book->parametres->width / $ratio; + $hr = $this->book->parametres->height / $ratio; + + $br = '.background.r' . $r . '{'; + if ($ratio != 1) { + $br.=$this->writeCSSUA('transform', 'scale(' . $ratio . ')') . ';'; + } + $br.='width:' . $wr . 'px;height:' . $hr . 'px;}'; + $res[] = $br; + } + $res[] = '.doublePage,#pages,.landscape #shadow.double{width:' . $w2 . ';max-width:' . $w2 . ';height:' . $h . ';max-height:' . $h . '}'; + $res[] = '.landscape #shadow.single.right{left: ' . $w . ';}'; + $res[] = '.landscape .page.right{left:' . $w . '}'; + $texts = '.texts{' . $this->writeCSSUA('transform-origin', 'top left') . ';'; + $texts.=$this->writeCSSUA('transform', 'scale(' . (1 / $this->multiply) . ')') . ';'; + $texts.='width:' . $wm . '; max-width:' . $wm . ';'; + $texts.='height:' . $hm . '; max-height:' . $hm . ';'; + $texts.='}'; + $res[] = $texts; + + // Theme + // Background + $body = '#main{'; + $body.='background-color:#' . $this->theme->parametres->backgroundColor . ';'; + switch ($this->theme->parametres->repeat) { + case wsTheme::REPEAT: + $body.='background-repeat:repeat;'; + break; + case wsTheme::NONE: + $body.='background-repeat:no-repeat;'; + break; + case wsTheme::RATIO: + $body.='background-repeat:no-repeat;'; + break; + case wsTheme::STRETCH: + $body.='background-repeat:no-repeat;'; + $body.='background-size:100% 100%;'; + break; + } + if ($this->theme->parametres->backgroundImage != '') { + copy($this->themeRoot . '/' . $this->theme->parametres->backgroundImage, $this->vdir . '/data/images/' . $this->theme->parametres->backgroundImage); + $body.='background-image:url(../images/' . $this->theme->parametres->backgroundImage . ');'; + $body.='background-position:'; + + + switch ($this->theme->parametres->backgroundVAlign) { + case wsTheme::TOP: + $body.='top'; + break; + case wsTheme::MIDDLE: + $body.='center'; + break; + case wsTheme::BOTTOM: + $body.='bottom'; + break; + } + $body.=' '; + switch ($this->theme->parametres->backgroundHAlign) { + case wsTheme::LEFT: + $body.='left'; + break; + case wsTheme::CENTER: + $body.='center'; + break; + case wsTheme::RIGHT: + $body.='right'; + break; + } + $body.=';'; + } + + $body.='}'; + $res[] = $body; + + // Header + $header = '#header{'; + $header.='height:' . $this->theme->parametres->menuHeight . 'px;'; + $header.='background-color:' . self::colorToCSS($this->theme->parametres->menuColor) . ';'; + if ($this->theme->parametres->menuImage != '') { + copy($this->themeRoot . '/' . $this->theme->parametres->menuImage, $this->vdir . '/data/images/' . $this->theme->parametres->menuImage); + $header.='background-image:url(../images/' . $this->theme->parametres->menuImage . ');'; + $header.='background-repeat:no-repeat;'; + $header.='background-size:100% ' . $this->theme->parametres->menuHeight . 'px;'; + } + $header.='}'; + $res[] = $header; + + //Icons + $res = array_merge($res, $this->writeIcons()); + + // Logo + $logo = '#logo{'; + if ($this->theme->parametres->logo) { + copy($this->themeRoot . '/' . $this->theme->parametres->logo, $this->vdir . '/data/images/' . $this->theme->parametres->logo); + $dim = getimagesize($this->vdir . '/data/images/' . $this->theme->parametres->logo); + $logo.='background-image:url(../images/' . $this->theme->parametres->logo . ');width:' . $dim[0] . 'px;height:' . $dim[1] . 'px;'; + } + $logo.='}'; + $res[] = $logo; + + // Credits + $res[] = '#credits,#credits a{color:' . self::colorToCSS($this->theme->parametres->creditsColor) . ';}'; + + // Arrows + $res[] = '#next,#previous{background-color:' . self::colorToCSS($this->theme->parametres->couleurA) . ';}'; + // Book shadow + $shadowColor = self::colorToCSS($this->theme->parametres->bookShadeColor); + if ($shadowColor != 'transparent') { + $res[] = '#shadow{' . $this->writeCSSUA('box-shadow', '0 0 20px ' . $shadowColor) . '}'; + } + + // Pages styles + foreach ($this->cssColor as $color => $index) { + $res[] = '.c' . $index . '{color:#' . $color . '}'; + } + + foreach ($this->cssSize as $size => $index) { + $res[] = '.s' . $index . '{font-size:' . $size . 'px}'; + } + + foreach ($this->cssLetterSpacing as $letterspacing => $index) { + $res[] = '.l' . $index . '{letter-spacing:' . $letterspacing . 'em}'; + } + + foreach ($this->cssWordSpacing as $wordspacing => $index) { + $res[] = '.w' . $index . '{word-spacing:' . $wordspacing . 'em}'; + } + + foreach ($this->cssX as $x => $index) { + $res[] = '.x' . $index . '{left:' . $x . 'px}'; + } + + foreach ($this->cssY as $y => $index) { + $res[] = '.y' . $index . '{top:' . $y . 'px}'; + } + + foreach ($this->cssRotation as $rotation => $index) { + $rotation*= - 1; + + + $to = 'transform-origin:left top;'; + + $css = '.r' . $index . '{'; + $css.=self::writeCSSUA('transform', 'rotate(' . $rotation . 'deg)') . ';'; + $css.=self::writeCSSUA('transform-origin', 'left top'); + $css.='}'; + $res[] = $css; + } + + foreach ($this->cssFont as $font => $index) { + list($font, $document_id) = explode('//', $font); + $res[] = "@font-face{font-family:F" . $index . ";src:url('F" . $index . ".eot');src:url('F" . $index . ".eot?#iefix') format('eot'),url('F" . $index . ".ttf') format('truetype'),url('F" . $index . ".svgz#" . $font . "') format('svgz'),url('F" . $index . ".svg#" . $font . "') format('svg')}"; + $res[] = '.f' . $index . '{font-family:F' . $index . ',Arial,Helvetica}'; + } + + $res = array_chunk($res, 4000); + foreach ($res as $k => $css) { + file_put_contents(sprintf($file, $k), implode("\n", $css)); + } + } + + protected function writeCSSUA($property, $value) { + $res = array(); + foreach (self::$uaPrefixes as $prefix) { + $res[] = $prefix . $property . ':' . $value; + } + return implode(';', $res); + } + + protected function addLine($line, $document_id) { + $res = array(); + foreach ($line->a as $group) { + $res[] = $this->addGroup($group, $document_id); + } + return array('x' => $this->normalizeFloatValue($line['x']), + 'y' => $this->normalizeFloatValue($line['y']), + 'rotation' => $this->getCSSRotation($this->normalizeFloatValue($line['rotation'], 0)), + "groups" => $res); + } + + protected function addGroup($group, $document_id) { + $alpha = intval(substr($group['color'], 1, 2), 16); + if ($alpha == 0) { + return false; + } + + $res = array(); + + $first = true; + foreach ($group->s as $span) { + if ($first) { + $x = $span['x']; + $first = false; + } + $newSpan = $this->addSpan($span, $document_id); + + array_push($res, $newSpan); + } + + return array( + 'color' => $this->getCSSColor($group['color']), + 'size' => $this->getCSSSize($group['size']), + 'font' => $this->getCSSFont($group['font'], $document_id), + 'letterspacing' => $this->getCSSLetterSpacing($group['letterspacing']), + 'wordspacing' => $this->getCSSWordSpacing($group['wordspacing']), + 'y' => ($group['size']) / -1.2, + 'x' => $x, + 'spans' => $res); + } + + protected function addSpan($span, $document_id) { + + $text = (string) $span; + if ($text == '') { + return false; + } + return array('text' => $text); + } + + protected function getCSSSize(&$size) { + $size = $this->normalizeFloatValue($size * $this->multiply, 3); + $sizer = $size; + return $this->getIndex($sizer, $this->cssSize); + } + + protected function getCSSFont($font, $document_id) { + return $this->getIndex($font . "//" . $document_id, $this->cssFont); + } + + protected function getCSSColor($color) { + $color = trim($color, '#'); + if (strlen($color) > 6) { + $color = substr($color, 2, 6); + } + if ($color == '000000') { + return null; + } + return $this->getIndex($color, $this->cssColor); + } + + protected function getCSSLetterSpacing($letterspacing) { + + $letterspacing = $this->normalizeFloatValue($letterspacing, 5); + + if ($letterspacing == 0) { + return null; + } + return $this->getIndex($letterspacing, $this->cssLetterSpacing); + } + + protected function getCSSWordSpacing($wordspacing) { + $wordspacing = $this->normalizeFloatValue($wordspacing, 5); + + if ($wordspacing == 0) { + return null; + } + return $this->getIndex($wordspacing, $this->cssWordSpacing); + } + + protected function getCSSRotation($rotation) { + $rotation = $this->normalizeFloatValue($rotation, 0); + if ($rotation == 0) { + return null; + } + return $this->getIndex($rotation, $this->cssRotation); + } + + protected function getCSSX($x) { + $x = round($x); + if ($x == 0) { + return null; + } + return $this->getIndex($x, $this->cssX); + } + + protected function getCSSY($y) { + $y = round($y); + if ($y == 0) { + return null; + } + return $this->getIndex($y, $this->cssY); + } + + protected function getIndex($value, &$tab) { + $value = (string) $value; + if (isset($tab[$value])) { + return $tab[$value]; + } + $res = $this->base62(count($tab)); + $tab[$value] = $res; + return $res; + } + + protected function normalizeFloatValue($value, $round=3) { + $value = str_replace(',', '.', $value); + $value = (float) $value; + $value = round($value, $round); + return $value; + } + + protected function base62($val) { + $chars = '0123456789abcdefghijklmnopqrstuvwxyz'; + $base = strlen($chars); + $str = ''; + do { + $i = $val % $base; + $str = $chars[$i] . $str; + $val = ($val - $i) / $base; + } while ($val > 0); + return $str; + } + + public static function escapeHTML($in) { + $in = htmlentities($in, ENT_NOQUOTES, "UTF-8"); + $in = str_replace(' ', '', $in); + + return $in; + } + + public function __destruct() { + + } + + public static function colorToCSS($color) { + if (strlen($color) == 6) { + return '#' . $color; + } else { + $alpha = substr($color, 0, 2); + $red = substr($color, 2, 2); + $green = substr($color, 4, 2); + $blue = substr($color, 6, 2); + + $components = array('alpha', 'red', 'green', 'blue'); + foreach ($components as $k => $name) { + $hex = substr($color, $k * 2, 2); + $$name = intval($hex, 16); + } + $alpha/=255; + if ($alpha == 0) { + return 'transparent'; + } elseif ($alpha == 1) { + return '#' . substr($color, 2, 6); + } + return 'rgba(' . $red . ',' . $green . ',' . $blue . ',' . $alpha . ')'; + } + } + +} + +?> \ No newline at end of file diff --git a/inc/ws/Util/packager/html5/class.ws.packager.html5.links.php b/inc/ws/Util/packager/html5/class.ws.packager.html5.links.php new file mode 100644 index 000000000..e47b0f47f --- /dev/null +++ b/inc/ws/Util/packager/html5/class.ws.packager.html5.links.php @@ -0,0 +1,334 @@ + $v) { + $this->$k = $v; + } + $this->id = $id; + $this->packager = $packager; + } + + public function getHTMLContainer() { + return ''; + } + + public function getHTMLContent() { + return ''; + } + + public function copyExternalFile($file, $video=false) { + $this->packager->copyLinkFile($file, 'data/links/', $video); + } + + public function getCSSContainer() { + $css = '#link' . $this->id . '{'; + $css.='left:' . $this->left . 'px;top:' . $this->top . 'px;'; + $css.='width:' . $this->width . 'px;height:' . $this->height . 'px;'; + $css.=$this->getCSS(); + $css.='}'; + return $css; + } + + public function getCSS() { + return ''; + } + + public static function getUniversalLocation($loc, $css=false) { + $datas = parse_url($loc); + + if (isset($datas['scheme']) && !is_null($datas['scheme'])) { + return $loc; + } else { + if ($css) { + return '../links/' . $loc; + } else { + return 'data/links/' . $loc; + } + } + } + +} + +class normalLink extends wsPackagerHTML5Link { + + public function getHTMLContent() { + $class = array(); + if ($this->display_area) { + $class[] = 'displayArea'; + } + $c = ''; + if (count($class)) { + $c = ' class="' . implode(' ', $class) . '"'; + } + return ''; + } + + public function getURL() { + return '#'; + } + + public function getTarget() { + return '_self'; + } + +} + +class contentLink extends wsPackagerHTML5Link { + +} + +class webLink extends normalLink { + + public function getURL() { + return wsPackagerHTML5Link::getUniversalLocation($this->to); + } + + public function getTarget() { + return $this->target; + } + + public function getCSS() { + + } + +} + +class mailLink extends normalLink { + + public function getURL() { + return 'mailto:' . $this->to; + } + + public function getTarget() { + return '_self'; + } + +} + +class internalLink extends normalLink { + + public function getURL() { + return '#/page/' . $this->getPage(); + } + + public function getPage() { + if ($this->numerotation == 'physical') { + return $this->to; + } else { + return $this->packager->virtualToPhysical($this->to); + } + } + +} + +class videoLink extends wsPackagerHTML5Link { + + public function getHTMLContent() { + $file = $this->to; + $e = explode('.', $file); + $ext = array_pop($e); + $basename = implode('.', $e); + $w = round($this->width); + $h = round($this->height); + + $res = ''; + return $res; + } + +} + +class webVideoLink extends videoLink { + + public function getHTMLContent() { + return $this->getEmbed(); + } + + public function getEmbed() { + return ''; + } + + public function getEmbedURL() { + if ($this->video_service == 0) { + $url = 'http://www.youtube.com/embed/' . $this->to . '?html5=1'; + } else { + $url = 'http://www.dailymotion.com/embed/video/' . $this->to; + } + return $url; + } + +} + +class actionLink extends internalLink { + + public function getURL() { + return '#' . $to; + } + +} + +class basketLink extends wsPackagerHTML5Link { + +} + +class colorLink extends contentLink { + + public function getCSS() { + return 'background-color:' . wsPackagerHTML5::colorToCSS($this->to) . ';'; + } + +} + +class imageLink extends contentLink { + + public function getCSS() { + $this->copyExternalFile($this->to); + return 'background-image:url(' . wsPackagerHTML5Link::getUniversalLocation($this->to, true) . ');background-size:100% 100%;background-repeat:no-repeat;'; + } + +} + +class fileLink extends normalLink { + + public function getURL() { + $this->copyExternalFile($this->to); + return wsPackagerHTML5Link::getUniversalLocation($this->to); + } + + public function getTarget() { + return '_blank'; + } + +} + +class multimediaLink extends wsPackagerHTML5Link { + + public function getHTMLContent() { + return cubeMedia::flashObject(wsPackagerHTML5Link::getUniversalLocation($this->to), $this->width, $this->height, array(), '', '', 9, '#ffffff', '', 'true', 'noscale', 'transparent'); + } + +} + +class videoPopupLink extends normalLink { + + public function getURL() { + $this->copyExternalFile($this->to, true); + return '#/video/' . $this->to; + } + +} + +class webVideoPopupLink extends videoPopupLink { + + public function getURL() { + if ($this->video_service == 0) { + $service = 'youtube'; + } elseif ($this->video_service == 1) { + $service = 'dailymotion'; + } + return '#/webvideo/' . $service . '/' . $this->to; + } + +} + +?> diff --git a/inc/ws/Util/packager/html5/class.ws.packager.html5.php b/inc/ws/Util/packager/html5/class.ws.packager.html5.php new file mode 100644 index 000000000..ac21e910d --- /dev/null +++ b/inc/ws/Util/packager/html5/class.ws.packager.html5.php @@ -0,0 +1,903 @@ +version = 'html5'; + } + + protected function preparePackage() { + parent::preparePackage(); + + foreach ($this->pages as $page => $infos) { + $file = WS_DOCS . '/' . $infos['document_id'] . '/html/p' . $infos['document_page'] . '.layout'; + if (file_exists($file)) { + $this->layouts[$page] = simplexml_load_file($file, null, LIBXML_ERR_WARNING); + } + } + + $imagesize = getimagesize(WS_DOCS . '/' . $this->pages[1]['document_id'] . '/html/h72-' . $this->pages[1]['document_page'] . '.jpg'); + $this->pdf2htmlRatio = round($imagesize[0] / $this->layouts[1]['width'], 2); + $this->scale = 4; + $this->multiply = $this->pdf2htmlRatio * $this->scale; + $this->numerotation = explode(',', $this->book->numerotation); + + $this->createHTML(); + } + + public function makePackage() { + parent::makePackage(); + return $this->zip(); + } + + public function virtualToPhysical($virtual) { + if (!in_array($virtual, $this->numerotation)) { + return 1; + } + $p = array_search($virtual, $this->numerotation); + return $p + 1; + } + + protected function compareLines($a, $b) { + if ((float) $a['y'] > (float) $b['y']) { + return 1; + } else { + return -1; + } + } + + protected function createHTML() { + foreach ($this->layouts as $page => $layout) { + $this->div[$page] = array(); + $document_id = $this->pages[$page]['document_id']; + $lines = array(); + foreach ($layout->l as $line) { + $lines[] = $line; + } + usort($lines, array($this, 'compareLines')); + + foreach ($lines as $line) { + $this->div[$page][] = $this->addLine($line, $document_id); + } + } + mkdir($this->vdir . '/data/images', 0777, true); + mkdir($this->vdir . '/data/contents', 0777, true); + mkdir($this->vdir . '/data/background', 0777, true); + mkdir($this->vdir . '/data/thumbnails', 0777, true); + mkdir($this->vdir . '/data/style', 0777, true); + mkdir($this->vdir . '/data/links/pages', 0777, true); + mkdir($this->vdir . '/data/l10n/', 0777, true); + mkdir($this->vdir . '/swf', 0777, true); + + // Copy style folder + $from = WS_COMPILE_ASSETS . '/_html5/style'; + $to = $this->vdir; + `cp -r $from $to`; + + // Copy images folder + $from = WS_COMPILE_ASSETS . '/_html5/images'; + `cp -r $from $to`; + + // Copy swf + copy(WS_COMPILE_ASSETS . '/_html5/swf/video.swf', $this->vdir . '/swf/video.swf'); + + foreach ($this->div as $n => $page) { + file_put_contents($this->vdir . '/data/contents/p' . $n . '.html', $this->writePage($page)); + } + $this->writeFonts(); + $this->writeImages(); + $linksCSS = $this->writeLinks(); + $numCSS = $this->writeCSS($this->vdir . '/data/style/style_%d.css', $linksCSS); + $this->writeLangs(); + $this->writeJs(); + $this->writeIndex($numCSS); + } + + protected function writeIndex($numCSS) { + $html = file_get_contents(WS_COMPILE_ASSETS . '/_html5/_index.html'); + + $titre = $this->book->parametres->title; + $credits = ''; + // Google analytics + $ga = ''; + if ($this->book->parametres->googleAnalytics != '') { + $ga = cubePage::googleAnalytics($this->book->parametres->googleAnalytics); + } + // Feuilles de style + $sheets = array('style/fluidbook.css'); + for ($i = 0; $i < $numCSS; $i++) { + $sheets[] = 'data/style/style_' . $i . '.css'; + } + $style = array(); + foreach ($sheets as $sheet) { + $style[] = ''; + } + $style = implode("\n\t\t", $style); + + $vars = array('titre', 'credits', 'ga', 'style'); + foreach ($vars as $v) { + $html = str_replace('', $$v, $html); + } + file_put_contents($this->vdir . '/index.html', $html); + } + + protected function writeLangs() { + global $core; + $daoLang = new wsDAOLang($core->con); + $lang = $daoLang->selectById($this->book->lang); + $langs = $daoLang->selectAll(); + + + $traductions = (!count($this->book->traductions)) ? $lang->traductions : $this->book->traductions; + file_put_contents($this->vdir . '/data/l10n/default.json', json_encode($traductions)); + foreach ($langs as $lang) { + file_put_contents($this->vdir . '/data/l10n/' . $lang->lang_id . '.json', json_encode($lang->traductions)); + } + } + + protected function writeLinks() { + global $core; + $daoDoc = new wsDAODocument($core->con); + $daoDoc->getLinksAndRulers($this->book_id, $links, $rulers); + + $i = 0; + $pages = array(); + $css = array(); + foreach ($links as $linkData) { + $link = wsPackagerHTML5Link::getInstance($this->base62($i), $linkData, $this); + if (is_null($link)) { + continue; + } + if (!isset($pages[$link->page])) { + $pages[$link->page] = ''; + } + $pages[$link->page] .= $link->getHTMLContainer(); + $css[] = $link->getCSSContainer(); + $i++; + } + + for ($i = 0; $i <= $this->book->parametres->pages + 1; $i++) { + $c = ''; + if (isset($pages[$i])) { + $c = $pages[$i]; + } + file_put_contents($this->vdir . 'data/links/pages/p' . $i . '.html', $c); + } + return $css; + } + + protected function writeJs() { + $files = array('js/libs/modernizr.js', + 'js/libs/jquery/jquery.js', + 'js/libs/jquery/jquery.transform.js', + 'js/libs/jquery/jquery.mousewheel.js', + 'js/libs/jquery/jquery.hashchange.js', + 'js/libs/fluidbook/fluidbook.utils.js', + 'js/libs/fluidbook/fluidbook.cache.js', + 'js/libs/fluidbook/fluidbook.support.js', + 'js/libs/fluidbook/fluidbook.viewport.js', + 'js/libs/fluidbook/fluidbook.desktop.js', + 'js/libs/fluidbook/fluidbook.service.js', + 'js/libs/fluidbook/fluidbook.loader.js', + 'js/libs/fluidbook/fluidbook.l10n.js', + 'js/libs/fluidbook/fluidbook.nav.js', + 'js/libs/fluidbook/fluidbook.js', + 'js/main.js'); + + $mintime = 0; + $minimized = WS_COMPILE_ASSETS . '/_html5/js/min.js'; + if (file_exists($minimized)) { + $mintime = filemtime($minimized); + } + $reminimize = false; + foreach ($files as $file) { + if (filemtime(WS_COMPILE_ASSETS . '/_html5/' . $file) > $mintime) { + $reminimize = true; + break; + } + } + + if ($reminimize) { + $js = ''; + foreach ($files as $file) { + $js.=file_get_contents(WS_COMPILE_ASSETS . '/_html5/' . $file); + $js.="\n\n"; + } + $tmp = cubeFiles::tempnam(); + file_put_contents($tmp, $js); + + $compressor = new cubeCommandLine('yuicompressor'); + $compressor->setPath(CONVERTER_PATH); + $compressor->setArg('charset', 'UTF-8'); + $compressor->setArg('type', 'js'); + $compressor->setArg('line-break', 1024); + $compressor->setArg('o', $minimized); + $compressor->setArg(null, $tmp); + $compressor->execute(); + } + + $js = $this->writeConfig(); + $js.=file_get_contents($minimized); + file_put_contents($this->vdir . '/data/fluidbook.js', $js); + } + + protected function writeConfig() { + $config = cubeObject::merge($this->book->parametres->toStandardObject(), $this->theme->parametres->toStandardObject()); + $config->numerotation = explode(',', $this->book->numerotation); + $config->id = $this->book->book_id; + $config->cacheDate = TIME; + return 'var DATAS=' . json_encode($config) . ';' . "\n"; + } + + protected function writeFonts() { + $formats = array('ttf', 'woff', 'svg'); + + foreach ($this->cssFont as $font => $index) { + + foreach ($formats as $format) { + $fontforge = new cubeCommandLine('convert.pe'); + $fontforge->setPath(CONVERTER_PATH); + foreach ($this->fontDocs[$font] as $document_id => $dummy) { + $fontforge->setArg(null, WS_DOCS . '/' . $document_id . '/fonts/web/' . $font . '.ttf'); + } + $fontforge->setArg(null, $this->vdir . '/data/style/F' . $index . '.' . $format); + $fontforge->execute(); + } + } + } + + protected function writeIcons() { + $res = array(); + // Get the colors used to colorize graphics + if ($this->theme->parametres->colorizeIcons) { + $couleurI = '#' . $this->theme->parametres->couleurI; + } else { + $couleurI = '#FFFFFF'; + } + $arrowsColor = '#' . $this->theme->parametres->arrowsColor; + // Set the icon list with the color + $icons = array('nav-bookmark' => $couleurI, 'nav-friend' => $couleurI, 'nav-help' => $couleurI, 'nav-index' => $couleurI, 'nav-sommaire' => $couleurI, + 'next' => $arrowsColor, 'previous' => $arrowsColor, 'search' => $couleurI, 'nav-facebook' => $couleurI, 'nav-twitter' => $couleurI, + 'help-fingers' => $couleurI, 'help-mouse' => $couleurI); + + foreach ($icons as $icon => $color) { + wsTools::colorizeAndRasterizeIcon($this->theme->parametres->iconSet, $icon, $color, $this->vdir . '/data/images/', 4, $w, $h); + } + return $res; + } + + protected function writeImages() { + + foreach (self::$resolutions as $r) { + mkdir($this->vdir . '/data/background/' . $r, 0777); + } + foreach ($this->pages as $page => $infos) { + foreach (self::$resolutions as $r) { + copy(WS_DOCS . '/' . $infos['document_id'] . '/html/h' . $r . '-' . $infos['document_page'] . '.jpg', $this->vdir . '/data/background/' . $r . '/p' . $page . '.jpg'); + } + copy(WS_DOCS . '/' . $infos['document_id'] . '/p' . $infos['document_page'] . '.jpg', $this->vdir . '/data/thumbnails/p' . $page . '.jpg'); + } + } + + protected function writePage($page) { + $res = ''; + foreach ($page as $line) { + $res .= $this->writeLine($line); + } + return $res; + } + + protected function writeLine($line) { + $res = ''; + foreach ($line['groups'] as $group) { + $res.=$this->writeGroup($group, $line); + } + return $res; + } + + protected function writeGroup($group, $line) { + if ($group === false) { + return ''; + } + + $group['y'] = $this->getCSSY(($group['y'] + $line['y']) * $this->multiply); + $group['x'] = $this->getCSSX(($group['x']) * $this->multiply); + + $class = array('g'); + if (!is_null($group['color'])) { + $class[] = 'c' . $group['color']; + } + if (!is_null($group['size'])) { + $class[] = 's' . $group['size']; + } + if (!is_null($group['font'])) { + $class[] = 'f' . $group['font']; + } + if (!is_null($group['x'])) { + $class[] = 'x' . $group['x']; + } + if (!is_null($group['y'])) { + $class[] = 'y' . $group['y']; + } + if (!is_null($line['rotation'])) { + $class[] = 'r' . $line['rotation']; + } + if (!is_null($group['letterspacing'])) { + $class[] = 'l' . $group['letterspacing']; + } + if (!is_null($group['wordspacing'])) { + $class[] = 'w' . $group['wordspacing']; + } + $class = implode(' ', $class); + + $res = '
'; + foreach ($group['spans'] as $span) { + $res.=$this->writeSpan($span); + } + $res.='
'; + return $res; + } + + protected function writeSpan($span) { + if ($span === false) { + return ''; + } + + if ($span['space']) { + return $span['text']; + } else { + return self::escapeHTML($span['text']); + } + } + + protected function writeCSS($file, $links) { + $res = array(); + + // General theme + $h = $this->book->parametres->height . 'px'; + $w2 = ($this->book->parametres->width * 2) . 'px'; + $w = $this->book->parametres->width . 'px'; + $wm = ($this->book->parametres->width * $this->multiply) . 'px'; + $hm = ($this->book->parametres->height * $this->multiply) . 'px'; + + + $navTop = ($this->book->parametres->height - 40 - 100) / 2; + $res[] = '.portrait #pages,.portrait .doublePage.page,.page,.portrait #shadow,#shadow.single,.page .links{width:' . $w . ';max-width:' . $w . ';height:' . $h . ';max-height:' . $h . '}'; + $res[] = '.background{' . $this->writeCSSUA('transform-origin', 'top left') . ';}'; + foreach (self::$resolutions as $r) { + $ratio = round(72 / $r, 2); + $wr = $this->book->parametres->width / $ratio; + $hr = $this->book->parametres->height / $ratio; + + $br = '.background.r' . $r . '{'; + if ($ratio != 1) { + $br.=$this->writeCSSUA('transform', 'scale(' . $ratio . ')') . ';'; + } + $br.='width:' . $wr . 'px;height:' . $hr . 'px;}'; + $res[] = $br; + } + $res[] = '.doublePage,#pages,.landscape #shadow.double{width:' . $w2 . ';max-width:' . $w2 . ';height:' . $h . ';max-height:' . $h . '}'; + $res[] = '.landscape #shadow.single.right{left: ' . $w . ';}'; + $res[] = '.landscape .page.right{left:' . $w . '}'; + if ($this->theme->parametres->displayPageNumber) { + $res[] = '#pagesnumbers{top:' . $h . ';color:' . self::colorToCSS($this->theme->parametres->colorPageNumber) . '}'; + $res[] = '#pagesnumbers div{width:' . $w . '}'; + } else { + $res[] = '#pagesnumbers{display:none;}'; + } + + $texts = '.texts{' . $this->writeCSSUA('transform-origin', 'top left') . ';'; + $texts.=$this->writeCSSUA('transform', 'scale(' . round(1 / $this->multiply, 2) . ')') . ';'; + $texts.='width:' . $wm . '; max-width:' . $wm . ';'; + $texts.='height:' . $hm . '; max-height:' . $hm . ';'; + $texts.='}'; + $res[] = $texts; + + // Theme + // Background + $body = '#deviceView{'; + $body.='background-color:#' . $this->theme->parametres->backgroundColor . ';'; + switch ($this->theme->parametres->repeat) { + case wsTheme::REPEAT: + $body.='background-repeat:repeat;'; + break; + case wsTheme::NONE: + $body.='background-repeat:no-repeat;'; + break; + case wsTheme::RATIO: + $body.='background-repeat:no-repeat;'; + break; + case wsTheme::STRETCH: + $body.='background-repeat:no-repeat;'; + $body.='background-size:100% 100%;'; + break; + } + if ($this->theme->parametres->backgroundImage != '') { + copy($this->themeRoot . '/' . $this->theme->parametres->backgroundImage, $this->vdir . '/data/images/' . $this->theme->parametres->backgroundImage); + $body.='background-image:url(../images/' . $this->theme->parametres->backgroundImage . ');'; + $body.='background-position:'; + + + switch ($this->theme->parametres->backgroundVAlign) { + case wsTheme::TOP: + $body.='top'; + break; + case wsTheme::MIDDLE: + $body.='center'; + break; + case wsTheme::BOTTOM: + $body.='bottom'; + break; + } + $body.=' '; + switch ($this->theme->parametres->backgroundHAlign) { + case wsTheme::LEFT: + $body.='left'; + break; + case wsTheme::CENTER: + $body.='center'; + break; + case wsTheme::RIGHT: + $body.='right'; + break; + } + $body.=';'; + } + + $body.='}'; + $res[] = $body; + + // Header + $header = '#header{'; + $header.='height:' . $this->theme->parametres->menuHeight . 'px;'; + $header.='background-color:' . self::colorToCSS($this->theme->parametres->menuColor) . ';'; + if ($this->theme->parametres->menuImage != '') { + copy($this->themeRoot . '/' . $this->theme->parametres->menuImage, $this->vdir . '/data/images/' . $this->theme->parametres->menuImage); + $header.='background-image:url(../images/' . $this->theme->parametres->menuImage . ');'; + $header.='background-repeat:no-repeat;'; + $header.='background-size:100% ' . $this->theme->parametres->menuHeight . 'px;'; + } + $header.='}'; + $res[] = $header; + + //Icons + $res = array_merge($res, $this->writeIcons()); + + // Logo + $logo = '#logo{'; + if ($this->theme->parametres->logo) { + copy($this->themeRoot . '/' . $this->theme->parametres->logo, $this->vdir . '/data/images/' . $this->theme->parametres->logo); + $dim = getimagesize($this->vdir . '/data/images/' . $this->theme->parametres->logo); + $logo.='background-image:url(../images/' . $this->theme->parametres->logo . ');width:' . $dim[0] . 'px;height:' . $dim[1] . 'px;'; + } + $logo.='}'; + $res[] = $logo; + + // Credits + $res[] = '#credits,#credits a{color:' . self::colorToCSS($this->theme->parametres->creditsColor) . ';}'; + + // Arrows + $res[] = '#next,#previous{background-color:' . self::colorToCSS($this->theme->parametres->couleurA) . ';}'; + // Book shadow + $shadowColor = self::colorToCSS($this->theme->parametres->bookShadeColor); + if ($shadowColor != 'transparent') { + $res[] = '#shadow{' . $this->writeCSSUA('box-shadow', '0 0 20px ' . $shadowColor) . '}'; + } + + // Links Styles + $res = array_merge($res, $links); + $res[] = '.link a.displayArea:hover,.link a.displayArea.animating{background-color:' . self::colorToCSS($this->theme->parametres->linksColor, 0.4) . ';}'; + + // Menus + # View + $res[] = '.portrait #view{width:' . $w . ';min-height:' . $h . '}'; + $res[] = '.landscape #view{width:' . $w2 . ';min-height:' . $h . '}'; + $res[] = '#view{background-color:' . self::colorToCSS($this->theme->parametres->couleurB) . ';color:' . self::colorToCSS($this->theme->parametres->subTextColor) . ';}'; + # Index + $ratio = $this->book->parametres->width / $this->book->parametres->height; + $thumbh = round(100 / $ratio); + $res[] = '#index .thumb img{width:100px;height:' . $thumbh . 'px;}'; + $res[] = '#index .doubleThumb{height:' . $thumbh . 'px;' . $this->writeCSSUA('box-shadow', '0 0 3px ' . $shadowColor) . '}'; + $res[] = '#index .doubleThumb .overlay{height:' . $thumbh . 'px;}'; + $res[] = '#index .doubleThumb .hits.yes{background-color:' . self::colorToCSS($this->theme->parametres->subSelectColor) . ';color:' . self::colorToCSS($this->theme->parametres->subTextSelectColor) . '}'; + + // Pages styles + foreach ($this->cssColor as $color => $index) { + $res[] = '.c' . $index . '{color:#' . $color . '}'; + } + + foreach ($this->cssSize as $size => $index) { + $res[] = '.s' . $index . '{font-size:' . $size . 'px}'; + } + + foreach ($this->cssLetterSpacing as $letterspacing => $index) { + $res[] = '.l' . $index . '{letter-spacing:' . $letterspacing . 'em}'; + } + + foreach ($this->cssWordSpacing as $wordspacing => $index) { + $res[] = '.w' . $index . '{word-spacing:' . $wordspacing . 'em}'; + } + + foreach ($this->cssX as $x => $index) { + $res[] = '.x' . $index . '{left:' . $x . 'px}'; + } + + foreach ($this->cssY as $y => $index) { + $res[] = '.y' . $index . '{top:' . $y . 'px}'; + } + + foreach ($this->cssRotation as $rotation => $index) { + $rotation*= - 1; + + + $to = 'transform-origin:left top;'; + + $css = '.r' . $index . '{'; + $css.=self::writeCSSUA('transform', 'rotate(' . $rotation . 'deg)') . ';'; + $css.=self::writeCSSUA('transform-origin', 'left top') . ';'; + $css.='margin-top:' . round(cos(deg2rad($rotation)) * -1, 2) . 'em !important;'; + $css.='margin-left:' . round(sin(deg2rad($rotation)), 2) . 'em !important;'; + $css.='}'; + $res[] = $css; + } + + foreach ($this->cssFont as $font => $index) { + $res[] = "@font-face{font-family:F" . $index . ";src:url('F" . $index . ".woff') format('woff'),url('F" . $index . ".ttf') format('truetype'),url('F" . $index . ".svg#" . $font . "') format('svg')}"; + $res[] = '.f' . $index . '{font-family:F' . $index . ',Arial,Helvetica}'; + } + + $res = array_chunk($res, 3500); + foreach ($res as $k => $css) { + file_put_contents(sprintf($file, $k), implode("\n", $css)); + } + return count($res); + } + + protected function writeCSSUA($property, $value) { + $res = array(); + foreach (self::$uaPrefixes as $prefix) { + $res[] = $prefix . $property . ':' . $value; + } + return implode(';', $res); + } + + protected function addLine($line, $document_id) { + $res = array(); + foreach ($line->a as $group) { + $res = array_merge($res, $this->addGroup($group, $document_id)); + } + return array( + 'y' => $this->normalizeFloatValue($line['y']), + 'rotation' => $this->getCSSRotation($this->normalizeFloatValue($line['rotation'], 0)), + "groups" => $res); + } + + protected function addGroup($group, $document_id) { + $alpha = intval(substr($group['color'], 1, 2), 16); + if ($alpha == 0) { + return false; + } + + $first = true; + $letterSpacing = 0; + $letterCount = 0; + $wordSpacing = 0; + $wordCount = 0; + + $res = array(); + $spans = array(); + + foreach ($group->s as $span) { + if ($first && trim((string) $span) == '') { + continue; + } + if ($first) { + $pos = $x = $span['x']; + $pos+=$span['width']; + $first = false; + } else { + if ((float) $span['x'] < (float) $newSpan['x']) { + // On change de groupe + $ls = $ws = 0; + if ($letterCount > 0) { + $ls = $letterSpacing / $letterCount; + } + if ($wordCount > 0) { + $ws = $wordSpacing / $wordCount; + } + + $res[] = array( + 'color' => $this->getCSSColor($group['color']), + 'size' => $this->getCSSSize($group['size']), + 'font' => $this->getCSSFont((string) $group['font'], $document_id), + 'letterspacing' => $this->getCSSLetterSpacing($ls), + 'wordspacing' => $this->getCSSLetterSpacing($ws), + 'y' => 0, + 'x' => $x, + 'spans' => $spans); + + $spans = array(); + $pos = $x = $span['x']; + $pos+=$span['width']; + } else { + + $diff = $span['x'] - $pos; + if ($diff > $group['size'] / 4) { + $space = round($diff / $group['size'], 4); + if ($space > 2) { + // On change de groupe + $ls = $ws = 0; + if ($letterCount > 0) { + $ls = $letterSpacing / $letterCount; + } + if ($wordCount > 0) { + $ws = $wordSpacing / $wordCount; + } + $res[] = array( + 'color' => $this->getCSSColor($group['color']), + 'size' => $this->getCSSSize($group['size']), + 'font' => $this->getCSSFont($group['font'], $document_id), + 'letterspacing' => $this->getCSSLetterSpacing($ls), + 'wordspacing' => $this->getCSSLetterSpacing($ws), + 'y' => 0, + 'x' => $x, + 'spans' => $spans); + + $spans = array(); + $pos = $x = $span['x']; + $pos+=$span['width']; + } else { + + $newSpan = $this->addSpan(' ', true); + array_push($spans, $newSpan); + } + } + } + } + + + $newSpan = $this->addSpan($span); + $pos = $span['x'] + $span['width']; + + array_push($spans, $newSpan); + $copy = (string) $span; + $len = mb_strlen($copy); + str_replace(' ', '-', $copy, $w); + $l = $len - $w; + + $letterCount+=$l; + $wordCount+=$w; + + $letterSpacing+=$l * (float) $span['letterspacing']; + $wordSpacing+=$w * (float) $span['wordspacing']; + } + + if (count($spans)) { + $ls = $ws = 0; + if ($letterCount > 0) { + $ls = $letterSpacing / $letterCount; + } + if ($wordCount > 0) { + $ws = $wordSpacing / $wordCount; + } + + $res[] = array( + 'color' => $this->getCSSColor($group['color']), + 'size' => $this->getCSSSize($group['size']), + 'font' => $this->getCSSFont($group['font'], $document_id), + 'letterspacing' => $this->getCSSLetterSpacing($ls), + 'wordspacing' => $this->getCSSLetterSpacing($ws), + 'y' => 0, + 'x' => $x, + 'spans' => $spans); + } + + return $res; + } + + protected function addSpan($span, $space=false) { + $text = (string) $span; + return array('text' => $text, 'space' => $space, 'x' => $span['x']); + } + + protected function getCSSSize($size) { + $size = $this->normalizeFloatValue($size); + $size*=$this->multiply; + return $this->getIndex($size, $this->cssSize); + } + + protected function getCSSFont($font, $document_id) { + $font = (string) $font; + if (!isset($this->fontDocs[$font])) { + $this->fontDocs[$font] = array(); + } + $this->fontDocs[$font][$document_id] = true; + + return $this->getIndex($font, $this->cssFont); + } + + protected function getCSSColor($color) { + $color = trim($color, '#'); + if (strlen($color) > 6) { + $color = substr($color, 2, 6); + } + if ($color == '000000') { + return null; + } + return $this->getIndex($color, $this->cssColor); + } + + protected function getCSSLetterSpacing($letterspacing) { + + $letterspacing = $this->normalizeFloatValue($letterspacing, 4); + + if ($letterspacing == 0) { + return null; + } + return $this->getIndex($letterspacing, $this->cssLetterSpacing); + } + + protected function getCSSWordSpacing($wordspacing) { + $wordspacing = $this->normalizeFloatValue($wordspacing, 4); + + if ($wordspacing == 0) { + return null; + } + return $this->getIndex($wordspacing, $this->cssWordSpacing); + } + + protected function getCSSRotation($rotation) { + $rotation = $this->normalizeFloatValue($rotation, 0); + if ($rotation == 0) { + return null; + } + return $this->getIndex($rotation, $this->cssRotation); + } + + protected function getCSSX($x) { + $x = round($x); + if ($x == 0) { + return null; + } + return $this->getIndex($x, $this->cssX); + } + + protected function getCSSY($y) { + $y = round($y); + if ($y == 0) { + return null; + } + return $this->getIndex($y, $this->cssY); + } + + protected function getIndex($value, &$tab) { + $value = (string) $value; + if (isset($tab[$value])) { + return $tab[$value]; + } + $res = $this->base62(count($tab)); + $tab[$value] = $res; + return $res; + } + + protected function normalizeFloatValue($value, $round=3) { + $value = str_replace(',', '.', $value); + $value = (float) $value; + $value = round($value, $round); + return $value; + } + + protected function base62($val) { + $chars = '0123456789abcdefghijklmnopqrstuvwxyz'; + $base = strlen($chars); + $str = ''; + do { + $i = $val % $base; + $str = $chars[$i] . $str; + $val = ($val - $i) / $base; + } while ($val > 0); + return $str; + } + + public function copyLinkFile($source, $dest, $video=false) { + // TODO delete that return; + //return; + $origDir = WS_BOOKS . '/working/' . $this->book_id . '/'; + $types = array('mp4', 'ogv', 'webm', 'jpg'); + if ($video) { + return; + wsTools::encodeWebVideos($origDir . $source, null, false); + $e = explode('.', $source); + array_pop($e); + $base = implode('.', $e); + $source = array(); + foreach ($types as $type) { + $source[] = $base . '.' . $type; + } + } + + if (!is_array($source)) { + $source = array($source); + } + + foreach ($source as $so) { + $s = $origDir . $so; + if (file_exists($s)) { + $d = $this->vdir . '/' . $dest . '/' . $so; + if (!file_exists(dirname($d))) { + mkdir(dirname($d), 0777, true); + } + copy($s, $d); + } + } + } + + public static function escapeHTML($in) { + $in = htmlentities($in, ENT_NOQUOTES, "UTF-8"); + $in = str_replace(' ', '', $in); + + return $in; + } + + public function __destruct() { + + } + + public static function colorToCSS($color, $forceAlpha=null) { + + if (!is_null($forceAlpha)) { + $a = $forceAlpha * 255; + $a = base_convert($a, 10, 16); + if (strlen($color) == 6) { + $color = $a . $color; + } else { + $color = $a . substr($color, 2, 6); + } + } + + if (strlen($color) == 6) { + return '#' . $color; + } else { + $alpha = substr($color, 0, 2); + $red = substr($color, 2, 2); + $green = substr($color, 4, 2); + $blue = substr($color, 6, 2); + + $components = array('alpha', 'red', 'green', 'blue'); + foreach ($components as $k => $name) { + $hex = substr($color, $k * 2, 2); + $$name = intval($hex, 16); + } + $alpha/=255; + if ($alpha == 0) { + return 'transparent'; + } elseif ($alpha == 1) { + return '#' . substr($color, 2, 6); + } + return 'rgba(' . $red . ',' . $green . ',' . $blue . ',' . $alpha . ')'; + } + } + +} + +?> \ No newline at end of file