Selaa lähdekoodia

:sparkles: EPS support (really!)

smiley 3 vuotta sitten
vanhempi
commit
00086063a6
3 muutettua tiedostoa jossa 167 lisäystä ja 1 poistoa
  1. 62 0
      examples/eps.php
  2. 101 0
      src/Output/QREps.php
  3. 4 1
      src/QRCode.php

+ 62 - 0
examples/eps.php

@@ -0,0 +1,62 @@
+<?php
+/**
+ * @created      10.05.2022
+ * @author       Smiley <smiley@chillerlan.net>
+ * @copyright    2022 Smiley
+ * @license      MIT
+ */
+
+namespace chillerlan\QRCodeExamples;
+
+use chillerlan\QRCode\{QRCode, QROptions};
+use chillerlan\QRCode\Common\EccLevel;
+use chillerlan\QRCode\Data\QRMatrix;
+
+require_once __DIR__.'/../vendor/autoload.php';
+
+$data = 'https://www.youtube.com/watch?v=dQw4w9WgXcQ';
+
+$options = new QROptions([
+	'version'      => 7,
+	'outputType'   => QRCode::OUTPUT_EPS,
+	'eccLevel'     => EccLevel::L,
+	'scale'        => 5,
+	'addQuietzone' => true,
+	'cachefile'    => __DIR__.'/test.eps',
+	'moduleValues' => [
+		// finder
+		QRMatrix::M_FINDER | QRMatrix::IS_DARK     => 0xA71111, // dark (true)
+		QRMatrix::M_FINDER                         => 0xFFBFBF, // light (false)
+		QRMatrix::M_FINDER_DOT | QRMatrix::IS_DARK => 0xA71111, // finder dot, dark (true)
+		// alignment
+		QRMatrix::M_ALIGNMENT | QRMatrix::IS_DARK  => 0xA70364,
+		QRMatrix::M_ALIGNMENT                      => 0xFFC9C9,
+		// timing
+		QRMatrix::M_TIMING | QRMatrix::IS_DARK     => 0x98005D,
+		QRMatrix::M_TIMING                         => 0xFFB8E9,
+		// format
+		QRMatrix::M_FORMAT | QRMatrix::IS_DARK     => 0x003804,
+		QRMatrix::M_FORMAT                         => 0x00FB12,
+		// version
+		QRMatrix::M_VERSION | QRMatrix::IS_DARK    => 0x650098,
+		QRMatrix::M_VERSION                        => 0xE0B8FF,
+		// data
+		QRMatrix::M_DATA | QRMatrix::IS_DARK       => 0x4A6000,
+		QRMatrix::M_DATA                           => 0xECF9BE,
+		// darkmodule
+		QRMatrix::M_DARKMODULE | QRMatrix::IS_DARK => 0x080063,
+		// separator
+		QRMatrix::M_SEPARATOR                      => 0xAFBFBF,
+		// quietzone
+		QRMatrix::M_QUIETZONE                      => 0xDDDDDD,
+	],
+]);
+
+// if viewed in the browser, we should push it as file download as EPS isn't usually supported
+header('Content-type: application/postscript');
+header('Content-Disposition: filename="qrcode.eps"');
+
+echo (new QRCode($options))->render($data);
+
+
+

+ 101 - 0
src/Output/QREps.php

@@ -0,0 +1,101 @@
+<?php
+/**
+ * Class QREps
+ *
+ * @created      09.05.2022
+ * @author       smiley <smiley@chillerlan.net>
+ * @copyright    2022 smiley
+ * @license      MIT
+ */
+
+namespace chillerlan\QRCode\Output;
+
+use function date, implode, is_int, sprintf;
+
+/**
+ * Encapsulated Postscript (EPS) output
+ *
+ * @see https://github.com/t0k4rt/phpqrcode/blob/bb29e6eb77e0a2a85bb0eb62725e0adc11ff5a90/qrvect.php#L52-L137
+ * @see https://web.archive.org/web/20170818010030/http://wwwimages.adobe.com/content/dam/Adobe/en/devnet/postscript/pdfs/5002.EPSF_Spec.pdf
+ * @see https://web.archive.org/web/20210419003859/https://www.adobe.com/content/dam/acom/en/devnet/actionscript/articles/PLRM.pdf
+ */
+class QREps extends QROutputAbstract{
+
+	/**
+	 * @inheritDoc
+	 */
+	protected function moduleValueIsValid($value):bool{
+		return is_int($value) && $value >= 0 && $value <= 0xffffff;
+	}
+
+	/**
+	 * @inheritDoc
+	 */
+	protected function getModuleValue($value):array{
+		return [
+			round((($value & 0xff0000) >> 16) / 255, 5),
+			round((($value & 0x00ff00) >> 8) / 255, 5),
+			round(($value & 0x0000ff) / 255, 5)
+		];
+	}
+
+	/**
+	 * @inheritDoc
+	 */
+	protected function getDefaultModuleValue(bool $isDark):array{
+		return $isDark ? [0.0, 0.0, 0.0] : [1.0, 1.0, 1.0];
+	}
+
+	/**
+	 * @inheritDoc
+	 */
+	public function dump(string $file = null):string{
+		$file       ??= $this->options->cachefile;
+		$saveToFile   = $file !== null;
+
+		$eps = [
+			// main header
+			'%!PS-Adobe-3.0 EPSF-3.0',
+			'%%Creator: php-qrcode (https://github.com/chillerlan/php-qrcode)',
+			'%%Title: QR Code',
+			sprintf('%%%%CreationDate: %1$s', date('c')),
+			'%%DocumentData: Clean7Bit',
+			'%%LanguageLevel: 3',
+			sprintf('%%%%BoundingBox: 0 -%1$s %1$s 0', $this->length),
+			'%%EndComments',
+			// function definitions
+			'%%BeginProlog',
+			'/F { rectfill } def',
+			'/S { setrgbcolor } def',
+			'%%EndProlog',
+			// rotate into the proper orientation and scale to fit
+			'-90 rotate',
+			sprintf('%1$s %1$s scale', $this->scale),
+		];
+
+		// create the path elements
+		$paths = $this->collectModules(fn(int $x, int $y):string => sprintf('%s %s 1 1 F', $x, $y));
+
+		foreach($paths as $M_TYPE => $path){
+
+			if(empty($path)){
+				continue;
+			}
+
+			$eps[] = sprintf('%f %f %f S', ...$this->moduleValues[$M_TYPE]);
+			$eps[] = implode("\n", $path);
+		}
+
+		// end file
+		$eps[] = '%%EOF';
+
+		$data = implode("\n", $eps);
+
+		if($saveToFile){
+			$this->saveToFile($data, $file);
+		}
+
+		return $data;
+	}
+
+}

+ 4 - 1
src/QRCode.php

@@ -13,7 +13,7 @@ namespace chillerlan\QRCode;
 use chillerlan\QRCode\Common\{EccLevel, ECICharset, MaskPattern, Mode};
 use chillerlan\QRCode\Common\{EccLevel, ECICharset, MaskPattern, Mode};
 use chillerlan\QRCode\Data\{AlphaNum, Byte, ECI, Kanji, Number, QRCodeDataException, QRData, QRDataModeInterface, QRMatrix};
 use chillerlan\QRCode\Data\{AlphaNum, Byte, ECI, Kanji, Number, QRCodeDataException, QRData, QRDataModeInterface, QRMatrix};
 use chillerlan\QRCode\Decoder\{Decoder, DecoderResult, LuminanceSourceInterface};
 use chillerlan\QRCode\Decoder\{Decoder, DecoderResult, LuminanceSourceInterface};
-use chillerlan\QRCode\Output\{QRCodeOutputException, QRFpdf, QRGdImage, QRImagick, QRMarkup, QROutputInterface, QRString};
+use chillerlan\QRCode\Output\{QRCodeOutputException, QRFpdf, QRGdImage, QRImagick, QRMarkup, QREps, QROutputInterface, QRString};
 use chillerlan\Settings\SettingsContainerInterface;
 use chillerlan\Settings\SettingsContainerInterface;
 use function class_exists, class_implements, in_array, mb_convert_encoding, mb_detect_encoding;
 use function class_exists, class_implements, in_array, mb_convert_encoding, mb_detect_encoding;
 
 
@@ -80,6 +80,8 @@ class QRCode{
 	/** @var string */
 	/** @var string */
 	public const OUTPUT_FPDF        = 'fpdf';
 	public const OUTPUT_FPDF        = 'fpdf';
 	/** @var string */
 	/** @var string */
+	public const OUTPUT_EPS         = 'eps';
+	/** @var string */
 	public const OUTPUT_CUSTOM      = 'custom';
 	public const OUTPUT_CUSTOM      = 'custom';
 
 
 	/**
 	/**
@@ -97,6 +99,7 @@ class QRCode{
 		self::OUTPUT_STRING_TEXT => QRString::class,
 		self::OUTPUT_STRING_TEXT => QRString::class,
 		self::OUTPUT_IMAGICK     => QRImagick::class,
 		self::OUTPUT_IMAGICK     => QRImagick::class,
 		self::OUTPUT_FPDF        => QRFpdf::class,
 		self::OUTPUT_FPDF        => QRFpdf::class,
+		self::OUTPUT_EPS         => QREps::class,
 	];
 	];
 
 
 	/**
 	/**