199 lines
6.1 KiB
PHP
199 lines
6.1 KiB
PHP
<?php
|
|
/**
|
|
* This file is part of Avatar Privacy.
|
|
*
|
|
* Copyright 2018-2023 Peter Putzer.
|
|
*
|
|
* This program 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 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program 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 this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
* This file incorporates work covered by the following copyright and
|
|
* permission notice:
|
|
*
|
|
* Copyright (c) 2013, 2014, 2016 Benjamin Laugueux <benjamin@yzalis.com>
|
|
* Copyright (c) 2015 Grummfy <grummfy@gmail.com>
|
|
* Copyright (c) 2016, 2017 Lucas Michot
|
|
* Copyright (c) 2019 Arjen van der Meijden
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
* in the Software without restriction, including without limitation the rights
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
* copies of the Software, and to permit persons to whom the Software is furnished
|
|
* to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in all
|
|
* copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
* THE SOFTWARE.
|
|
*
|
|
* ***
|
|
*
|
|
* @package mundschenk-at/avatar-privacy
|
|
* @license http://www.gnu.org/licenses/gpl-2.0.html
|
|
*/
|
|
|
|
namespace Avatar_Privacy\Avatar_Handlers\Default_Icons\Generators;
|
|
|
|
use Avatar_Privacy\Avatar_Handlers\Default_Icons\Generator;
|
|
|
|
use Avatar_Privacy\Tools\Number_Generator;
|
|
use Avatar_Privacy\Tools\Template;
|
|
|
|
use Avatar_Privacy\Vendor\Colors\RandomColor;
|
|
|
|
/**
|
|
* Generates a "retro" SVG icon based on a hash.
|
|
*
|
|
* @since 1.0.0
|
|
* @since 2.0.0 Moved to Avatar_Privacy\Avatar_Handlers\Default_Icons\Generators
|
|
* @since 2.7.0 Now directly incorporates the SVG generation code from the
|
|
* deprecated package `yzalis/identicon`.
|
|
*
|
|
* @author Peter Putzer <github@mundschenk.at>
|
|
* @author Grummfy <grummfy@gmail.com>
|
|
*/
|
|
class Retro implements Generator {
|
|
|
|
private const NUMBER_OF_PIXELS = 5;
|
|
|
|
private const DIVIDER = 3;
|
|
|
|
private const POSSIBLE_COLUMNS = [
|
|
0 => [ 0, 4 ],
|
|
1 => [ 1, 3 ],
|
|
2 => [ 2 ],
|
|
];
|
|
|
|
/**
|
|
* The random number generator.
|
|
*
|
|
* @since 2.3.0
|
|
*
|
|
* @var Number_Generator
|
|
*/
|
|
protected Number_Generator $number_generator;
|
|
|
|
|
|
/**
|
|
* The templating handler.
|
|
*
|
|
* @since 2.7.0
|
|
*
|
|
* @var Template
|
|
*/
|
|
protected Template $template;
|
|
|
|
|
|
/**
|
|
* Creates a new instance.
|
|
*
|
|
* @since 2.1.0 Parameter `$identicon` added.
|
|
* @since 2.3.0 Parameter `$number_generator` added.
|
|
* @since 2.7.0 Parameter `$template` added.
|
|
*
|
|
* @param Number_Generator $number_generator A pseudo-random number generator.
|
|
* @param Template $template The templating handler.
|
|
*/
|
|
public function __construct( Number_Generator $number_generator, Template $template ) {
|
|
$this->number_generator = $number_generator;
|
|
$this->template = $template;
|
|
}
|
|
|
|
/**
|
|
* Builds an icon based on the given seed returns the image data.
|
|
*
|
|
* @param string $seed The seed data (hash).
|
|
* @param int $size Optional. The size in pixels. Default 128 (but really ignored).
|
|
*
|
|
* @return string
|
|
*/
|
|
public function build( $seed, $size = 128 ) {
|
|
// Initialize random number with seed.
|
|
$this->number_generator->seed( $seed );
|
|
|
|
// Generate icon.
|
|
$bitmap = $this->get_bitmap( \md5( $seed ) ); // The seed is already hashed, but we want to generate the same result as earlier versions did using `yzalis/identicon`.
|
|
$args = [
|
|
'rows' => \count( $bitmap ),
|
|
'columns' => \count( $bitmap[1] ),
|
|
'path' => $this->draw_path( $bitmap ),
|
|
'color' => RandomColor::one( [ 'luminosity' => 'bright' ] ),
|
|
'bg_color' => RandomColor::one( [ 'luminosity' => 'light' ] ),
|
|
];
|
|
$result = $this->template->get_partial( 'public/partials/retro/svg.php', $args );
|
|
|
|
// Restore randomness.
|
|
$this->number_generator->reset();
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Converts the hash into an two-dimensional array of boolean.
|
|
*
|
|
* @since 2.7.0
|
|
*
|
|
* @param string $hash The MD5 hash.
|
|
*
|
|
* @return array<int, array<int, bool>>
|
|
*/
|
|
protected function get_bitmap( string $hash ): array {
|
|
$bitmap = [];
|
|
|
|
foreach ( \array_slice( \str_split( $hash, 2 ), 0, self::NUMBER_OF_PIXELS * self::DIVIDER ) as $i => $hex_tuple ) {
|
|
$row = (int) ( $i / self::DIVIDER );
|
|
$pixel = (bool) \round( \hexdec( $hex_tuple[0] ) / 10 );
|
|
|
|
foreach ( self::POSSIBLE_COLUMNS[ $i % self::DIVIDER ] as $column ) {
|
|
$bitmap[ $row ][ $column ] = $pixel;
|
|
}
|
|
|
|
\ksort( $bitmap[ $row ] );
|
|
}
|
|
|
|
return $bitmap;
|
|
}
|
|
|
|
/**
|
|
* Draws an SVG path from the given bitmap.
|
|
*
|
|
* @since 2.7.0
|
|
*
|
|
* @param array $bitmap A two-dimensional array of boolean pixel values.
|
|
*
|
|
* @return string
|
|
*
|
|
* @phpstan-param array<int, array<int, bool>> $bitmap
|
|
*/
|
|
protected function draw_path( array $bitmap ): string {
|
|
$rects = [];
|
|
foreach ( $bitmap as $line_key => $line_value ) {
|
|
foreach ( $line_value as $col_key => $col_value ) {
|
|
if ( true === $col_value ) {
|
|
$rects[] = 'M' . $col_key . ',' . $line_key . 'h1v1h-1v-1';
|
|
}
|
|
}
|
|
}
|
|
|
|
return \implode( '', $rects );
|
|
}
|
|
}
|