Gitlab CSE Unil

Commit b3d5baea authored by M. Chardon's avatar M. Chardon
Browse files

- suppression des stamps

- generation des stamps depuis fontawesome pour la génération du PDF
parent 7d0ead4c
...@@ -62,7 +62,6 @@ class backup_assignfeedback_editpdfplus_subplugin extends backup_subplugin { ...@@ -62,7 +62,6 @@ class backup_assignfeedback_editpdfplus_subplugin extends backup_subplugin {
// We only need to backup the files in the final pdf area, and the readonly page images - the others can be regenerated. // We only need to backup the files in the final pdf area, and the readonly page images - the others can be regenerated.
$subpluginelementfiles->annotate_files('assignfeedback_editpdfplus', \assignfeedback_editpdfplus\document_services::FINAL_PDF_FILEAREA, 'gradeid'); $subpluginelementfiles->annotate_files('assignfeedback_editpdfplus', \assignfeedback_editpdfplus\document_services::FINAL_PDF_FILEAREA, 'gradeid');
$subpluginelementfiles->annotate_files('assignfeedback_editpdfplus', \assignfeedback_editpdfplus\document_services::PAGE_IMAGE_READONLY_FILEAREA, 'gradeid'); $subpluginelementfiles->annotate_files('assignfeedback_editpdfplus', \assignfeedback_editpdfplus\document_services::PAGE_IMAGE_READONLY_FILEAREA, 'gradeid');
$subpluginelementfiles->annotate_files('assignfeedback_editpdfplus', 'stamps', 'gradeid');
return $subplugin; return $subplugin;
} }
......
...@@ -68,7 +68,6 @@ class restore_assignfeedback_editpdfplus_subplugin extends restore_subplugin { ...@@ -68,7 +68,6 @@ class restore_assignfeedback_editpdfplus_subplugin extends restore_subplugin {
// In this case the id is the old gradeid which will be mapped. // In this case the id is the old gradeid which will be mapped.
$this->add_related_files('assignfeedback_editpdfplus', \assignfeedback_editpdfplus\document_services::FINAL_PDF_FILEAREA, 'grade', null, $data->gradeid); $this->add_related_files('assignfeedback_editpdfplus', \assignfeedback_editpdfplus\document_services::FINAL_PDF_FILEAREA, 'grade', null, $data->gradeid);
$this->add_related_files('assignfeedback_editpdfplus', \assignfeedback_editpdfplus\document_services::PAGE_IMAGE_READONLY_FILEAREA, 'grade', null, $data->gradeid); $this->add_related_files('assignfeedback_editpdfplus', \assignfeedback_editpdfplus\document_services::PAGE_IMAGE_READONLY_FILEAREA, 'grade', null, $data->gradeid);
$this->add_related_files('assignfeedback_editpdfplus', 'stamps', 'grade', null, $data->gradeid);
} }
/** /**
......
...@@ -610,24 +610,12 @@ EOD; ...@@ -610,24 +610,12 @@ EOD;
} }
$file = $document->get_combined_file(); $file = $document->get_combined_file();
$tmpdir = make_temp_directory('assignfeedback_editpdfplus/final/' . self::hash($assignment, $userid, $attemptnumber)); $tmpdir = make_temp_directory('assignfeedback_editpdfplus/final/' . self::hash($assignment, $userid, $attemptnumber));
$combined = $tmpdir . '/' . self::COMBINED_PDF_FILENAME; $combined = $tmpdir . '/' . self::COMBINED_PDF_FILENAME;
$file->copy_content_to($combined); // Copy the file. $file->copy_content_to($combined); // Copy the file.
$pdf = new pdf(); $pdf = new pdf();
$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)) {
foreach ($files as $file) {
$filename = $stamptmpdir . '/' . $file->get_filename();
$file->copy_content_to($filename); // Copy the file.
}
}
$pagecount = $pdf->set_pdf($combined); $pagecount = $pdf->set_pdf($combined);
$grade = $assignment->get_user_grade($userid, true, $attemptnumber); $grade = $assignment->get_user_grade($userid, true, $attemptnumber);
if (!$refresh) { if (!$refresh) {
...@@ -642,7 +630,7 @@ EOD; ...@@ -642,7 +630,7 @@ EOD;
$annotations = page_editor::get_annotations($grade->id, $i, false); $annotations = page_editor::get_annotations($grade->id, $i, false);
foreach ($annotations as $annotation) { foreach ($annotations as $annotation) {
$pdf->add_annotation($annotation, $annotation->path, $stamptmpdir, $compteur); $pdf->add_annotation($annotation, $annotation->path, $compteur);
if ($annotation->textannot && !$annotation->parent_annot) { if ($annotation->textannot && !$annotation->parent_annot) {
$annotation_index[$annotation->id] = $compteur; $annotation_index[$annotation->id] = $compteur;
$compteur++; $compteur++;
...@@ -705,15 +693,12 @@ EOD; ...@@ -705,15 +693,12 @@ EOD;
$finalcomment = page_editor::get_feedback_comments($grade->id); $finalcomment = page_editor::get_feedback_comments($grade->id);
$pdf->writeHTMLCell(0, 0, 40, 70, $finalcomment->commenttext); $pdf->writeHTMLCell(0, 0, 40, 70, $finalcomment->commenttext);
fulldelete($stamptmpdir);
$filename = self::get_downloadable_feedback_filename($assignment, $userid, $attemptnumber); $filename = self::get_downloadable_feedback_filename($assignment, $userid, $attemptnumber);
$filename = clean_param($filename, PARAM_FILE); $filename = clean_param($filename, PARAM_FILE);
$generatedpdf = $tmpdir . '/' . $filename; $generatedpdf = $tmpdir . '/' . $filename;
$pdf->save_pdf($generatedpdf); $pdf->save_pdf($generatedpdf);
$record = new \stdClass(); $record = new \stdClass();
$record->contextid = $assignment->get_context()->id; $record->contextid = $assignment->get_context()->id;
...@@ -723,8 +708,8 @@ EOD; ...@@ -723,8 +708,8 @@ EOD;
$record->filepath = '/'; $record->filepath = '/';
$record->filename = $filename; $record->filename = $filename;
// Only keep one current version of the generated pdf. // Only keep one current version of the generated pdf.
$fs = get_file_storage();
$fs->delete_area_files($record->contextid, $record->component, $record->filearea, $record->itemid); $fs->delete_area_files($record->contextid, $record->component, $record->filearea, $record->itemid);
$file = $fs->create_file_from_pathname($record, $generatedpdf); $file = $fs->create_file_from_pathname($record, $generatedpdf);
......
...@@ -25,6 +25,9 @@ ...@@ -25,6 +25,9 @@
namespace assignfeedback_editpdfplus; namespace assignfeedback_editpdfplus;
use \assignfeedback_editpdfplus\utils_color;
use \assignfeedback_editpdfplus\utils_stamp;
defined('MOODLE_INTERNAL') || die(); defined('MOODLE_INTERNAL') || die();
global $CFG; global $CFG;
...@@ -49,9 +52,6 @@ class pdf extends \FPDI { ...@@ -49,9 +52,6 @@ class pdf extends \FPDI {
/** @var float used to scale the pixel position of annotations (in the database) to the position in the final PDF */ /** @var float used to scale the pixel position of annotations (in the database) to the position in the final PDF */
protected $scale = 0.0; 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 */ /** @var string the path to the PDF currently being processed */
protected $filename = null; protected $filename = null;
...@@ -226,91 +226,22 @@ class pdf extends \FPDI { ...@@ -226,91 +226,22 @@ class pdf extends \FPDI {
} }
} }
/**
* Get RGB color from label of color or hexa code
* @param string $colour
* @return array()
*/
private function get_colour_for_pdf($colour) {
if (substr($colour, 0, 1) == '#') {
$colourarray = $this->hex2RGB($colour, false);
} else {
switch ($colour) {
case 'orange':
$colourarray = array(255, 207, 53);
break;
case 'yellow':
$colourarray = array(255, 207, 53);
break;
case 'yellowlemon':
$colourarray = array(255, 255, 0);
break;
case 'green':
$colourarray = array(153, 202, 62);
break;
case 'blue':
$colourarray = array(125, 159, 211);
break;
case 'white':
$colourarray = array(255, 255, 255);
break;
case 'black':
$colourarray = array(51, 51, 51);
break;
default:
$colourarray = array(239, 69, 64);
break;
}
}
return $colourarray;
}
/**
* 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
}
/** /**
* Add an annotation to the current page * Add an annotation to the current page
* @param int $sx starting x-coordinate (in pixels) *
* @param int $sy starting y-coordinate (in pixels) * @param \assignfeedback_editpdfplus\annotation $annotation
* @param int $ex ending x-coordinate (in pixels)
* @param int $ey ending y-coordinate (in pixels)
* @param string $colour optional the colour of the annotation (red, yellow, green, blue, white, black)
* @param string $type optional the type of annotation (line, oval, rectangle, highlight, pen, stamp)
* @param int[]|string $path optional for 'pen' annotations this is an array of x and y coordinates for * @param int[]|string $path optional for 'pen' annotations this is an array of x and y coordinates for
* the line, for 'stamp' annotations it is the name of the stamp file (without the path) * the line, for 'stamp' annotations it is the name of the stamp file (without the path)
* @param string $imagefolder - Folder containing stamp images. * @param type $annotation_index
* @return bool true if successful (always) * @return bool true if successful (always)
*/ */
public function add_annotation(annotation $annotation, $path, $imagefolder, $annotation_index) { public function add_annotation(annotation $annotation, $path, $annotation_index) {
global $CFG;
if (!$this->filename) { if (!$this->filename) {
return false; return false;
} }
$colour = $annotation->colour; $colour = $annotation->colour;
$colourarray = $this->get_colour_for_pdf($colour); $colourarray = utils_color::getColorRGB($colour); //$this->get_colour_for_pdf($colour);
$this->SetDrawColorArray($colourarray); $this->SetDrawColorArray($colourarray);
$sx = $this->scale * $annotation->x; $sx = $this->scale * $annotation->x;
...@@ -328,7 +259,7 @@ class pdf extends \FPDI { ...@@ -328,7 +259,7 @@ class pdf extends \FPDI {
if (!$colourcartridge) { if (!$colourcartridge) {
$colourcartridge = $typetool->cartridge_color; $colourcartridge = $typetool->cartridge_color;
} }
$colourcartridgearray = $this->get_colour_for_pdf($colourcartridge); $colourcartridgearray = utils_color::getColorRGB($colourcartridge); //$this->get_colour_for_pdf($colourcartridge);
$this->SetTextColorArray($colourcartridgearray); $this->SetTextColorArray($colourcartridgearray);
$this->SetFontSize(10); $this->SetFontSize(10);
...@@ -393,16 +324,6 @@ class pdf extends \FPDI { ...@@ -393,16 +324,6 @@ class pdf extends \FPDI {
} }
} }
break; break;
case 'stamp':
$imgfile = $imagefolder . '/' . clean_filename($path);
$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 'highlightplus': case 'highlightplus':
$w = abs($sx - $ex); $w = abs($sx - $ex);
$h = 8.0 * $this->scale; $h = 8.0 * $this->scale;
...@@ -462,34 +383,40 @@ class pdf extends \FPDI { ...@@ -462,34 +383,40 @@ class pdf extends \FPDI {
break; break;
case 'stampcomment': case 'stampcomment':
if ($annotation->displayrotation == 1) { if ($annotation->displayrotation == 1) {
$imgfile = $CFG->dirroot . '/mod/assign/feedback/editpdfplus/pix/twoway_v_pdf.png'; $imgFileFromFA = utils_stamp::getPngFromFont("arrows-v");
$h = 20; //abs($sy - $ey); //$imgfile = $CFG->dirroot . '/mod/assign/feedback/editpdfplus/pix/twoway_v_pdf.png';
$w = $h * 37 / 96; //$h = 20; //abs($sy - $ey);
$sx = min($sx, $ex) + 8; //$w = $h * 37 / 96;
$sy = min($sy, $ey) + 2; $sx = min($sx, $ex) - 6;
} else { } else {
$imgfile = $CFG->dirroot . '/mod/assign/feedback/editpdfplus/pix/twoway_h_pdf.png'; $imgFileFromFA = utils_stamp::getPngFromFont("arrows-h");
$w = 20; //abs($sx - $ex); //$imgfile = $CFG->dirroot . '/mod/assign/feedback/editpdfplus/pix/twoway_h_pdf.png';
$h = $w * 37 / 96; //$w = 20; //abs($sx - $ex);
$sx = min($sx, $ex) + 2; //$h = $w * 37 / 96;
$sy = min($sy, $ey) + 8; $sx = min($sx, $ex) - 1;
}
$sy = min($sy, $ey);
$w = 30 * $this->scale;
$h = 30 * $this->scale;
if ($imgFileFromFA) {
$this->Image($imgFileFromFA, $sx, $sy, $w, $h);
} }
// Stamp is always more than 40px, so no need to check width/height.
$this->Image($imgfile, $sx, $sy, $w, $h);
$scartx = ($annotation->cartridgex + $annotation->x) * $this->scale; $scartx = ($annotation->cartridgex + $annotation->x) * $this->scale;
$scarty = ($annotation->cartridgey + $annotation->y) * $this->scale; $scarty = ($annotation->cartridgey + $annotation->y) * $this->scale;
$this->SetXY($scartx, $scarty); $this->SetXY($scartx, $scarty);
break; break;
case 'commentplus': case 'commentplus':
$imgfile = $CFG->dirroot . '/mod/assign/feedback/editpdfplus/pix/comment.png'; $imgFileFromFA = utils_stamp::getPngFromFont("commenting");
//$imgfile = $CFG->dirroot . '/mod/assign/feedback/editpdfplus/pix/comment.png';
$w = 16 * $this->scale; $w = 16 * $this->scale;
$h = 16 * $this->scale; $h = 16 * $this->scale;
$sx = min($sx, $ex); $sx = min($sx, $ex);
$sy = min($sy, $ey); $sy = min($sy, $ey);
$this->SetXY($sx + $w + 2, $sy); $this->SetXY($sx + $w + 2, $sy);
// Stamp is always more than 40px, so no need to check width/height. if ($imgFileFromFA) {
$this->Image($imgfile, $sx, $sy, $w, $h); $this->Image($imgFileFromFA, $sx, $sy, $w, $h);
}
break; break;
case 'stampplus': case 'stampplus':
$w = abs($sx - $ex); $w = abs($sx - $ex);
...@@ -510,13 +437,13 @@ class pdf extends \FPDI { ...@@ -510,13 +437,13 @@ class pdf extends \FPDI {
if (!$colourcartridge) { if (!$colourcartridge) {
$colourcartridge = $typetool->color; $colourcartridge = $typetool->color;
} }
$colourcartridgearray = $this->get_colour_for_pdf($colourcartridge); $colourcartridgearray = utils_color::getColorRGB($colourcartridge); //$this->get_colour_for_pdf($colourcartridge);
$this->SetTextColorArray($colourcartridgearray); $this->SetTextColorArray($colourcartridgearray);
$cartouche = $toolObject->label; $cartouche = $toolObject->label;
//$this->Cell($w); //$this->Cell($w);
//Texte centré dans une cellule 20*10 mm encadrée et retour à la ligne //Texte centré dans une cellule 20*10 mm encadrée et retour à la ligne
$this->Cell(strlen($cartouche)*6+4, 10, $cartouche, 1, 1, 'C'); $this->Cell(strlen($cartouche) * 6 + 4, 10, $cartouche, 1, 1, 'C');
break; break;
default: // Line. default: // Line.
......
...@@ -347,7 +347,6 @@ class assignfeedback_editpdfplus_renderer extends plugin_renderer_base { ...@@ -347,7 +347,6 @@ class assignfeedback_editpdfplus_renderer extends plugin_renderer_base {
'assignmentid' => $widget->assignment, 'assignmentid' => $widget->assignment,
'userid' => $widget->userid, 'userid' => $widget->userid,
'attemptnumber' => $widget->attemptnumber, 'attemptnumber' => $widget->attemptnumber,
'stampfiles' => $widget->stampfiles,
'readonly' => $widget->readonly)); 'readonly' => $widget->readonly));
$this->page->requires->yui_module('moodle-assignfeedback_editpdfplus-editor', 'M.assignfeedback_editpdfplus.editor.init', $editorparams); $this->page->requires->yui_module('moodle-assignfeedback_editpdfplus-editor', 'M.assignfeedback_editpdfplus.editor.init', $editorparams);
......
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* This file contains the editor class for the assignfeedback_editpdfplus plugin
*
* @package assignfeedback_editpdfplus
* @copyright 2018 Université de Lausanne
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace assignfeedback_editpdfplus;
/**
* This class performs crud operations on colors.
*
* No capability checks are done - they should be done by the calling class.
*
* @package assignfeedback_editpdfplus
* @copyright 2018 Marion Chardon
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class utils_color {
/**
* Get RGB color from label of color or hexa code
*
* @param string $color Color name or Hexa code
* @return array()
*/
public static function getColorRGB($color = "default") {
if (substr($color, 0, 1) == '#') {
$hexaCode = self::hex2RGB($color);
if ($hexaCode) {
return $hexaCode;
}
$color = "default";
}
return self::colorNameToRGB($color);
}
/**
* 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)
*/
public static function hex2RGB($hexStr, $returnAsString = false, $seperator = ',') {
// Gets a proper hex string
$hexStr = preg_replace("/[^0-9A-Fa-f]/", '', $hexStr);
$rgbArray = array();
//If a proper hex code, convert using bitwise operation. No overhead... faster
if (strlen($hexStr) == 6) {
$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 {
//Invalid hex color code
return false;
}
// returns the rgb string or the associative array
return $returnAsString ? implode($seperator, $rgbArray) : $rgbArray;
}
/**
* Make association between color name and RGB association
*
* @param type $colorName Color Name like red
* @return array RGB representation
*/
public static function colorNameToRGB($colorName) {
$colorNameLower = strtolower($colorName);
if (isset(self::$colorsMap[$colorNameLower])) {
return self::$colorsMap[$colorNameLower];
}
return self::$colorsMap["default"];
}
/**
* Map between color name and RGB code
* @var array()
*/
static $colorsMap = array(
"wheat" => array(251, 221, 126),
"very dark purple" => array(42, 1, 52),
"bottle green" => array(4, 74, 5),
"watermelon" => array(253, 70, 89),
"deep sky blue" => array(13, 117, 248),
"fire engine red" => array(254, 0, 2),
"yellow ochre" => array(203, 157, 6),
"pumpkin orange" => array(251, 125, 7),
"pale olive" => array(185, 204, 129),
"light lilac" => array(237, 200, 255),
"lightish green" => array(97, 225, 96),
"carolina blue" => array(138, 184, 254),
"mulberry" => array(146, 10, 78),
"shocking pink" => array(254, 2, 162),
"auburn" => array(154, 48, 1),
"bright lime green" => array(101, 254, 8),
"celadon" => array(190, 253, 183),
"pinkish brown" => array(177, 114, 97),
"poo brown" => array(136, 95, 1),
"bright sky blue" => array(2, 204, 254),
"celery" => array(193, 253, 149),
"dirt brown" => array(131, 101, 57),
"strawberry" => array(251, 41, 67),
"dark lime" => array(132, 183, 1),
"copper" => array(182, 99, 37),
"medium brown" => array(127, 81, 18),
"muted green" => array(95, 160, 82),
"robin's egg" => array(109, 237, 253),
"bright aqua" => array(11, 249, 234),
"bright lavender" => array(199, 96, 255),
"ivory" => array(255, 255, 203),
"very light purple" => array(246, 206, 252),
"light navy" => array(21, 80, 132),
"pink red" => array(245, 5, 79),
"olive brown" => array(100, 84, 3),
"poop brown" => array(122, 89, 1),
"mustard green" => array(168, 181, 4),
"ocean green" => array(61, 153, 115),
"very dark blue" => array(0, 1, 51),
"dusty green" => array(118, 169, 115),
"light navy blue" => array(46, 90, 136),
"minty green" => array(11, 247, 125),
"adobe" => array(189, 108, 72),
"barney" => array(172, 29, 184),
"jade green" => array(43, 175, 106),
"bright light blue" => array(38, 247, 253),
"light lime" => array(174, 253, 108),
"dark khaki" => array(155, 143, 85),
"orange yellow" => array(255, 173, 1),
"ocre" => array(198, 156, 4),
"maize" => array(244, 208, 84),
"faded pink" => array(222, 157, 172),
"british racing green" => array(5, 72, 13),
"sandstone" => array(201, 174, 116),
"mud brown" => array(96, 70, 15),
"light sea green" => array(152, 246, 176),
"robin egg blue" => array(138, 241, 254),
"aqua marine" => array(46, 232, 187),
"dark sea green" => array(17, 135, 93),
"soft pink" => array(253, 176, 192),
"orangey brown" => array(177, 96, 2),
"cherry red" => array(247, 2, 42),
"burnt yellow" => array(213, 171, 9),
"brownish grey" => array(134, 119, 95),
"camel" => array(198, 159, 89),
"purplish grey" => array(122, 104, 127),
"marine" => array(4, 46, 96),
"greyish pink" => array(200, 141, 148),
"pale turquoise" => array(165, 251, 213),
"pastel yellow" => array(255, 254, 113),
"bluey purple" => array(98, 65, 199),
"canary yellow" => array(255, 254, 64),
"faded red" => array(211, 73, 78),
"sepia" => array(152, 94, 43),
"coffee" => array(166, 129, 76),
"bright magenta" => array(255, 8, 232),
"mocha" => array(157, 118, 81),
"ecru" => array(254, 255, 202),
"purpleish" => array(152, 86, 141),
"cranberry" => array(158, 0, 58),
"darkish green" => array(40, 124, 55),
"brown orange" => array(185, 105, 2),
"dusky rose" => array(186, 104, 115),
"melon" => array(255, 120, 85),
"sickly green" => array(148, 178, 28),
"silver" => array(197, 201, 199),
"purply blue" => array(102, 26, 238),
"purpleish blue" => array(97, 64, 239),
"hospital green" => array(155, 229, 170),
"shit brown" => array(123, 88, 4),
"mid blue" => array(39, 106, 179),
"amber" => array(254, 179, 8),
"easter green" => array(140, 253, 126),
"soft blue" => array(100, 136, 234),