Gitlab CSE Unil

Commit 37c852c7 authored by M. Chardon's avatar M. Chardon
Browse files

affichage pdf

parent d921fd04
......@@ -100,4 +100,34 @@ class annotation {
}
}
/**
* Convert a hexa decimal color code to its RGB equivalent
*
* @param string $hexStr (hexadecimal color value)
* @param boolean $returnAsString (if set true, returns the value separated by the separator character. Otherwise returns associative array)
* @param string $seperator (to separate RGB values. Applicable only if second parameter is true.)
* @return array or string (depending on second parameter. Returns False if invalid hex color value)
*/
private function hex2RGB($hexStr, $returnAsString = false, $seperator = ',') {
$hexStr = preg_replace("/[^0-9A-Fa-f]/", '', $hexStr); // Gets a proper hex string
$rgbArray = array();
if (strlen($hexStr) == 6) { //If a proper hex code, convert using bitwise operation. No overhead... faster
$colorVal = hexdec($hexStr);
$rgbArray['red'] = 0xFF & ($colorVal >> 0x10);
$rgbArray['green'] = 0xFF & ($colorVal >> 0x8);
$rgbArray['blue'] = 0xFF & $colorVal;
} elseif (strlen($hexStr) == 3) { //if shorthand notation, need some string manipulations
$rgbArray['red'] = hexdec(str_repeat(substr($hexStr, 0, 1), 2));
$rgbArray['green'] = hexdec(str_repeat(substr($hexStr, 1, 1), 2));
$rgbArray['blue'] = hexdec(str_repeat(substr($hexStr, 2, 1), 2));
} else {
return false; //Invalid hex color code
}
return $returnAsString ? implode($seperator, $rgbArray) : $rgbArray; // returns the rgb string or the associative array
}
public function getColorRGB() {
return $this->hex2RGB($this->colour, true);
}
}
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
......@@ -40,16 +41,22 @@ class document_services {
/** File area for generated pdf */
const FINAL_PDF_FILEAREA = 'download';
/** File area for combined pdf */
const COMBINED_PDF_FILEAREA = 'combined';
/** File area for importing html */
const IMPORT_HTML_FILEAREA = 'importhtml';
/** File area for page images */
const PAGE_IMAGE_FILEAREA = 'pages';
/** File area for readonly page images */
const PAGE_IMAGE_READONLY_FILEAREA = 'readonlypages';
/** File area for the stamps */
const STAMPS_FILEAREA = 'stamps';
/** Filename for combined pdf */
const COMBINED_PDF_FILENAME = 'combined.pdf';
......@@ -363,8 +370,7 @@ EOD;
if ($readonly) {
$grade = $assignment->get_user_grade($userid, true, $attemptnumber);
$fs = get_file_storage();
$files = $fs->get_directory_files($assignment->get_context()->id, 'assignfeedback_editpdfplus',
self::PAGE_IMAGE_READONLY_FILEAREA, $grade->id, '/');
$files = $fs->get_directory_files($assignment->get_context()->id, 'assignfeedback_editpdfplus', self::PAGE_IMAGE_READONLY_FILEAREA, $grade->id, '/');
$pagecount = count($files);
if ($pagecount > 0) {
return $pagecount;
......@@ -382,12 +388,10 @@ EOD;
. self::hash($assignment, $userid, $attemptnumber));
$combined = $tmpdir . '/' . self::COMBINED_PDF_FILENAME;
$file->copy_content_to($combined); // Copy the file.
// Get the total number of pages.
$pdf = new pdf();
$pagecount = $pdf->set_pdf($combined);
$pdf->Close(); // PDF loaded and never saved/outputted needs to be closed.
// Delete temporary folders and files.
@unlink($combined);
@rmdir($tmpdir);
......@@ -525,14 +529,14 @@ EOD;
// Need to reorder the files following their name.
// because get_directory_files() return a different order than generate_page_images_for_attempt().
foreach($files as $file) {
foreach ($files as $file) {
// Extract the page number from the file name image_pageXXXX.png.
preg_match('/page([\d]+)\./', $file->get_filename(), $matches);
if (empty($matches) or !is_numeric($matches[1])) {
if (empty($matches) or ! is_numeric($matches[1])) {
throw new \coding_exception("'" . $file->get_filename()
. "' file hasn't the expected format filename: image_pageXXXX.png.");
}
$pagenumber = (int)$matches[1];
$pagenumber = (int) $matches[1];
// Save the page in the ordered array.
$pages[$pagenumber] = $file;
......@@ -569,13 +573,13 @@ EOD;
$groupname = '';
if ($groupmode) {
$groupid = groups_get_activity_group($assignment->get_course_module(), true);
$groupname = groups_get_group_name($groupid).'-';
$groupname = groups_get_group_name($groupid) . '-';
}
if ($groupname == '-') {
$groupname = '';
}
$grade = $assignment->get_user_grade($userid, true, $attemptnumber);
$user = $DB->get_record('user', array('id'=>$userid), '*', MUST_EXIST);
$user = $DB->get_record('user', array('id' => $userid), '*', MUST_EXIST);
if ($assignment->is_blind_marking()) {
$prefix = $groupname . get_string('participant', 'assign');
......@@ -626,19 +630,35 @@ EOD;
$pdf = new pdf();
/*$defaultstamps = array('twoway_h.png', 'twoway_v.png');
// Stamp file object.
$filerecord = new stdClass;
$filerecord->component = 'assignfeedback_editpdfplus';
$filerecord->contextid = context_system::instance()->id;
$filerecord->userid = get_admin()->id;
$filerecord->filearea = 'stamps';
$filerecord->filepath = '/';
$filerecord->itemid = 0;
$fs = \get_file_storage();
// Load all default stamps.
foreach ($defaultstamps as $stamp) {
$filerecord->filename = $stamp;
$fs->create_file_from_pathname($filerecord,
$CFG->dirroot . '/mod/assign/feedback/editpdfplus/pix/' . $filerecord->filename);
}*/
$fs = \get_file_storage();
$stamptmpdir = \make_temp_directory('assignfeedback_editpdfplus/stamps/' . self::hash($assignment, $userid, $attemptnumber));
$grade = $assignment->get_user_grade($userid, true, $attemptnumber);
// Copy any new stamps to this instance.
if ($files = $fs->get_area_files($assignment->get_context()->id,
'assignfeedback_editpdfplus',
'stamps',
$grade->id,
"filename",
false)) {
if ($files = $fs->get_area_files($assignment->get_context()->id, 'assignfeedback_editpdfplus', 'stamps', $grade->id, "filename", false)) {
foreach ($files as $file) {
$filename = $stamptmpdir . '/' . $file->get_filename();
$file->copy_content_to($filename); // Copy the file.
debugging($filename);
}
}
......@@ -652,22 +672,11 @@ EOD;
$annotations = page_editor::get_annotations($grade->id, $i, false);
foreach ($comments as $comment) {
$pdf->add_comment($comment->rawtext,
$comment->x,
$comment->y,
$comment->width,
$comment->colour);
$pdf->add_comment($comment->rawtext, $comment->x, $comment->y, $comment->width, $comment->colour);
}
foreach ($annotations as $annotation) {
$pdf->add_annotation($annotation->x,
$annotation->y,
$annotation->endx,
$annotation->endy,
$annotation->colour,
$annotation->type, //@TODO
$annotation->path,
$stamptmpdir);
$pdf->add_annotation($annotation, $annotation->path, $stamptmpdir);
}
}
......@@ -759,12 +768,7 @@ EOD;
$filepath = '/';
$fs = \get_file_storage();
$files = $fs->get_area_files($contextid,
$component,
$filearea,
$itemid,
"itemid, filepath, filename",
false);
$files = $fs->get_area_files($contextid, $component, $filearea, $itemid, "itemid, filepath, filename", false);
if ($files) {
return reset($files);
}
......
......@@ -159,6 +159,34 @@ class page_editor {
return $tools;
}
/**
* Get a single tool by id.
* @param int $toolid
* @return tool or false
*/
public static function get_tool($toolid) {
global $DB;
$record = $DB->get_record('assignfeedback_editpp_tool', array('id' => $toolid), '*', IGNORE_MISSING);
if ($record) {
return new tool($record);
}
return false;
}
/**
* Get the tool with id tooltypeid.
* @param int $tooltypeid
* @return type_tool
*/
public static function get_type_tool($tooltypeid) {
global $DB;
$record = $DB->get_record('assignfeedback_editpp_typet', array('id' => $tooltypeid));
if ($record) {
return new type_tool($record);
}
return false;
}
public static function get_typetools($contextidlist) {
global $DB;
$typetools = array();
......@@ -258,7 +286,7 @@ class page_editor {
if ($newid) {
if ($currentdiv != '') {
$annotationdiv[$currentdiv] = $newid;
debugging($currentdiv . ' -> ' . $newid);
//debugging($currentdiv . ' -> ' . $newid);
}
$added++;
}
......@@ -383,7 +411,6 @@ class page_editor {
global $DB;
$annotation->id = null;
debugging('idparent : ' . $annotation->parent_annot);
if ($annotation->parent_annot == 0) {
$annotation->parent_annot = null;
}
......
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
......@@ -27,8 +28,8 @@ namespace assignfeedback_editpdfplus;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->libdir.'/pdflib.php');
require_once($CFG->dirroot.'/mod/assign/feedback/editpdf/fpdi/fpdi.php');
require_once($CFG->libdir . '/pdflib.php');
require_once($CFG->dirroot . '/mod/assign/feedback/editpdf/fpdi/fpdi.php');
/**
* Library code for manipulating PDFs
......@@ -41,31 +42,43 @@ class pdf extends \FPDI {
/** @var int the number of the current page in the PDF being processed */
protected $currentpage = 0;
/** @var int the total number of pages in the PDF being processed */
protected $pagecount = 0;
/** @var float used to scale the pixel position of annotations (in the database) to the position in the final PDF */
protected $scale = 0.0;
/** @var string the path in which to store generated page images */
protected $imagefolder = null;
/** @var string the path to the PDF currently being processed */
protected $filename = null;
/** No errors */
const GSPATH_OK = 'ok';
/** Not set */
const GSPATH_EMPTY = 'empty';
/** Does not exist */
const GSPATH_DOESNOTEXIST = 'doesnotexist';
/** Is a dir */
const GSPATH_ISDIR = 'isdir';
/** Not executable */
const GSPATH_NOTEXECUTABLE = 'notexecutable';
/** Test file missing */
const GSPATH_NOTESTFILE = 'notestfile';
/** Any other error */
const GSPATH_ERROR = 'error';
/** Min. width an annotation should have */
const MIN_ANNOTATION_WIDTH = 5;
/** Min. height an annotation should have */
const MIN_ANNOTATION_HEIGHT = 5;
......@@ -92,7 +105,7 @@ class pdf extends \FPDI {
foreach ($pdflist as $file) {
$pagecount = $this->setSourceFile($file);
$totalpagecount += $pagecount;
for ($i = 1; $i<=$pagecount; $i++) {
for ($i = 1; $i <= $pagecount; $i++) {
$this->create_page_from_source($i);
}
}
......@@ -171,7 +184,7 @@ class pdf extends \FPDI {
if (!$this->filename) {
return false;
}
if ($this->currentpage>=$this->pagecount) {
if ($this->currentpage >= $this->pagecount) {
return false;
}
$this->currentpage++;
......@@ -273,11 +286,15 @@ class pdf extends \FPDI {
* @param string $imagefolder - Folder containing stamp images.
* @return bool true if successful (always)
*/
public function add_annotation($sx, $sy, $ex, $ey, $colour = 'yellow', $type = 'line', $path, $imagefolder) {
public function add_annotation(annotation $annotation, $path, $imagefolder) {
global $CFG;
if (!$this->filename) {
return false;
}
$colour = $annotation->colour;
if (substr($colour, 0, 1) == '#') {
$colourarray = $annotation->getColorRGB();
} else {
switch ($colour) {
case 'yellow':
$colourarray = array(255, 207, 53);
......@@ -299,14 +316,20 @@ class pdf extends \FPDI {
$colourarray = array(239, 69, 64);
break;
}
}
$this->SetDrawColorArray($colourarray);
$sx *= $this->scale;
$sy *= $this->scale;
$ex *= $this->scale;
$ey *= $this->scale;
$sx = $this->scale * $annotation->x;
$sy = $this->scale * $annotation->y;
$ex = $this->scale * $annotation->endx;
$ey = $this->scale * $annotation->endy;
$this->SetLineWidth(3.0 * $this->scale);
//$type = 'line';
$toolid = $annotation->toolid;
$toolObject = page_editor::get_tool($toolid);
$typetool = page_editor::get_type_tool($toolObject->type);
$type = $typetool->label;
switch ($type) {
case 'oval':
$rx = abs($sx - $ex) / 2;
......@@ -378,6 +401,77 @@ class pdf extends \FPDI {
// Stamp is always more than 40px, so no need to check width/height.
$this->Image($imgfile, $sx, $sy, $w, $h);
break;
case 'highlightplus':
$w = abs($sx - $ex);
$h = 8.0 * $this->scale;
$sx = min($sx, $ex);
$sy = min($sy, $ey) + ($h * 0.5);
$this->SetAlpha(0.5, 'Normal', 0.5, 'Normal');
$this->SetLineWidth(8.0 * $this->scale);
// width should be >= min width
if ($w < self::MIN_ANNOTATION_WIDTH) {
$w = self::MIN_ANNOTATION_WIDTH;
}
$this->Rect($sx, $sy, $w, $h);
$this->SetAlpha(1.0, 'Normal', 1.0, 'Normal');
break;
case 'verticalline':
$this->Line($sx, $sy, $sx, $ey);
break;
case 'frame':
$w = abs($sx - $ex);
$h = abs($sy - $ey);
$sx = min($sx, $ex);
$sy = min($sy, $ey);
// Width or height should be >= min width and height
if ($w < self::MIN_ANNOTATION_WIDTH) {
$w = self::MIN_ANNOTATION_WIDTH;
}
if ($h < self::MIN_ANNOTATION_HEIGHT) {
$h = self::MIN_ANNOTATION_HEIGHT;
}
$this->Rect($sx, $sy, $w, $h);
break;
case 'stampcomment':
$imgfile = $CFG->dirroot . '/mod/assign/feedback/editpdfplus/pix/twoway_h.png';
$w = abs($sx - $ex);
$h = abs($sy - $ey);
$sx = min($sx, $ex);
$sy = min($sy, $ey);
// Stamp is always more than 40px, so no need to check width/height.
$this->Image($imgfile, $sx, $sy, $w, $h);
break;
case 'commentplus':
$imgfile = $CFG->dirroot . 'mod/assign/feedback/editpdfplus/pix/comment.png';
$w = abs(16);
$h = abs(16);
$sx = min($sx, $ex);
$sy = min($sy, $ey);
// Stamp is always more than 40px, so no need to check width/height.
$this->Image($imgfile, $sx, $sy, $w, $h);
break;
case 'stampplus':
$w = abs($sx - $ex);
$h = abs($sy - $ey);
$sx = min($sx, $ex);
$sy = min($sy, $ey);
// Width or height should be >= min width and height
if ($w < self::MIN_ANNOTATION_WIDTH) {
$w = self::MIN_ANNOTATION_WIDTH;
}
if ($h < self::MIN_ANNOTATION_HEIGHT) {
$h = self::MIN_ANNOTATION_HEIGHT;
}
$this->Rect($sx, $sy, $w, $h);
break;
default: // Line.
$this->Line($sx, $sy, $ex, $ey);
break;
......@@ -428,10 +522,10 @@ class pdf extends \FPDI {
throw new \coding_exception('The specified image output folder is not a valid folder');
}
$imagefile = $this->imagefolder.'/image_page' . $pageno . '.png';
$imagefile = $this->imagefolder . '/image_page' . $pageno . '.png';
$generate = true;
if (file_exists($imagefile)) {
if (filemtime($imagefile)>filemtime($this->filename)) {
if (filemtime($imagefile) > filemtime($this->filename)) {
// Make sure the image is newer than the PDF file.
$generate = false;
}
......@@ -444,23 +538,23 @@ class pdf extends \FPDI {
$imagefilearg = \escapeshellarg($imagefile);
$filename = \escapeshellarg($this->filename);
$pagenoinc = \escapeshellarg($pageno + 1);
$command = "$gsexec -q -sDEVICE=png16m -dSAFER -dBATCH -dNOPAUSE -r$imageres -dFirstPage=$pagenoinc -dLastPage=$pagenoinc ".
$command = "$gsexec -q -sDEVICE=png16m -dSAFER -dBATCH -dNOPAUSE -r$imageres -dFirstPage=$pagenoinc -dLastPage=$pagenoinc " .
"-dDOINTERPOLATE -dGraphicsAlphaBits=4 -dTextAlphaBits=4 -sOutputFile=$imagefilearg $filename";
$output = null;
$result = exec($command, $output);
if (!file_exists($imagefile)) {
$fullerror = '<pre>'.get_string('command', 'assignfeedback_editpdfplus')."\n";
$fullerror = '<pre>' . get_string('command', 'assignfeedback_editpdfplus') . "\n";
$fullerror .= $command . "\n\n";
$fullerror .= get_string('result', 'assignfeedback_editpdfplus')."\n";
$fullerror .= get_string('result', 'assignfeedback_editpdfplus') . "\n";
$fullerror .= htmlspecialchars($result) . "\n\n";
$fullerror .= get_string('output', 'assignfeedback_editpdfplus')."\n";
$fullerror .= htmlspecialchars(implode("\n",$output)) . '</pre>';
$fullerror .= get_string('output', 'assignfeedback_editpdfplus') . "\n";
$fullerror .= htmlspecialchars(implode("\n", $output)) . '</pre>';
throw new \moodle_exception('errorgenerateimage', 'assignfeedback_editpdfplus', '', $fullerror);
}
}
return 'image_page'.$pageno.'.png';
return 'image_page' . $pageno . '.png';
}
/**
......@@ -530,7 +624,7 @@ class pdf extends \FPDI {
public static function test_gs_path($generateimage = true) {
global $CFG;
$ret = (object)array(
$ret = (object) array(
'status' => self::GSPATH_OK,
'message' => null,
);
......@@ -556,14 +650,14 @@ class pdf extends \FPDI {
return $ret;
}
$testfile = $CFG->dirroot.'/mod/assign/feedback/editpdfplus/tests/fixtures/testgs.pdf';
$testfile = $CFG->dirroot . '/mod/assign/feedback/editpdfplus/tests/fixtures/testgs.pdf';
if (!file_exists($testfile)) {
$ret->status = self::GSPATH_NOTESTFILE;
return $ret;
}
$testimagefolder = \make_temp_directory('assignfeedback_editpdfplus_test');
@unlink($testimagefolder.'/image_page0.png'); // Delete any previous test images.
@unlink($testimagefolder . '/image_page0.png'); // Delete any previous test images.
$pdf = new pdf();
$pdf->set_pdf($testfile);
......@@ -585,13 +679,12 @@ class pdf extends \FPDI {
public static function send_test_image() {
global $CFG;
header('Content-type: image/png');
require_once($CFG->libdir.'/filelib.php');
require_once($CFG->libdir . '/filelib.php');
$testimagefolder = \make_temp_directory('assignfeedback_editpdfplus_test');
$testimage = $testimagefolder.'/image_page0.png';
$testimage = $testimagefolder . '/image_page0.png';
send_file($testimage, basename($testimage), 0);
die();
}
}
......@@ -31,7 +31,7 @@ function xmldb_assignfeedback_editpdfplus_install() {
global $CFG;
// List of default stamps.
$defaultstamps = array('smile.png', 'sad.png', 'tick.png', 'cross.png');
$defaultstamps = array('smile.png', 'sad.png', 'tick.png', 'cross.png', 'twoway_h.png', 'twoway_v.png');
// Stamp file object.
$filerecord = new stdClass;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment