Issues (1369)

tools/classes/Sprite.php (3 issues)

1
<?php
2
/** Created by Gorlum 08.01.2024 19:57 */
3
4
namespace Tools;
5
6
require_once __DIR__ . '/SpriteLine.php';
7
require_once __DIR__ . '/SpriteLineGif.php';
8
require_once __DIR__ . '/ImageFile.php';
9
require_once __DIR__ . '/ImageContainer.php';
10
11
use Exception;
12
use ImageFile;
13
14
class Sprite {
15
  const LAYOUT_LINE = 0;
16
  const LAYOUT_COLUMN = 1;
17
  const LAYOUT_SQUARE = 'square';
18
  // const LAYOUT_MINIMAL = 'minimal'; // Minimize sum of linear dimensions
19
  // const LAYOUT_EQUAL_HEIGHT = 'equal_height'; // Put images with equal height in one line
20
  const LAYOUT_BTREE = 'btree';
21
22
  /** @var ImageFile[] $imageList */
23
  public $imageList = [];
24
  /** @var SpriteLine[] $lines */
25
  public $lines = [];
26
  /** @var ImageContainer|null $image */
27
  public $image = null;
28
29
  /** @var int $gridSize Sprite grid size in images */
30
  protected $gridSize = 0;
31
  /** @var int $scaleToPx Scale input images to specified PX. Default: 0 - no scaling */
32
  protected $scaleToPx = 0;
33
34
  protected $lineIndex = 0;
35
  protected $columnIndex = 0;
36
37
  protected $height = 0;
38
  protected $width = 0;
39
40
  /**
41
   * @param ImageFile[] $images
42
   * @param             $layout
43
   */
44
  public function __construct($images, $layout, $scaleToPx) {
45
    $this->scaleToPx = $scaleToPx;
46
47
    if ($layout === self::LAYOUT_SQUARE) {
48
      $gridSize = ceil(sqrt(count($images)));
49
    } elseif ($layout === self::LAYOUT_COLUMN) {
50
      $gridSize = 1;
51
    } elseif ($layout === self::LAYOUT_LINE) {
52
      $gridSize = 0;
53
    } else {
54
      $gridSize = 1;
55
    }
56
57
    $this->gridSize = $gridSize;
58
59
    $this->imageList = $images;
60
  }
61
62
  /**
63
   * @return void
64
   */
65
  protected function imageReset() {
66
    if (!empty($this->image)) {
67
      unset($this->image);
68
    }
69
70
    $this->image = ImageContainer::create($this->width, $this->height);
71
  }
72
73
  /**
74
   * @param $scaleToPx
75
   */
76
  protected function renderLines($scaleToPx) {
77
    $this->width = $this->height = 0;
78
    // Generating lines and calculating line sizes
79
    foreach ($this->lines as $line) {
80
      $line->generate($this->height, $scaleToPx);
81
82
      $this->height += $line->height;
83
      $this->width  = max($this->width, $line->width);
84
85
//      $line->image->savePng(__DIR__ . '/../gif_line_' . $this->height . '.png'); // TODO remove debug
86
    }
87
  }
88
89
  /**
90
   *
91
   * @return ImageContainer|null
92
   */
93
  public function generate() {
94
    $this->createGrid();
95
96
    $this->renderLines($this->scaleToPx);
97
98
    // Recreating main sprite image with new width and height
99
    $this->imageReset();
100
101
    // Generating final sprite
102
    $position = 0;
103
    foreach ($this->lines as $line) {
104
      $this->image->copyFrom($line->image, 0, $position);
0 ignored issues
show
It seems like $line->image can also be of type null; however, parameter $anImage of Tools\ImageContainer::copyFrom() does only seem to accept Tools\ImageContainer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

104
      $this->image->copyFrom(/** @scrutinizer ignore-type */ $line->image, 0, $position);
Loading history...
105
106
      $position += $line->height;
107
    }
108
109
    return $this->image;
110
  }
111
112
  /**
113
   *
114
   * @return string %3$s - $outName, %4$s - $relativeUrl
115
   */
116
  protected function generateCss() {
117
    $css = '';
118
    foreach ($this->lines as $line) {
119
      $css .= $line->css;
120
    }
121
122
    return ".%3\$s{background-image: url('%4\$s%3\$s.png');display: inline-block;" .
123
      ($this->scaleToPx > 0 ? "transform-origin: top left;" : "") .
124
      "}\n" . $css;
125
  }
126
127
  public function savePng($fileName) {
128
    // Saving PNG
129
    $this->image->savePng($fileName);
0 ignored issues
show
The method savePng() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

129
    $this->image->/** @scrutinizer ignore-call */ 
130
                  savePng($fileName);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
130
  }
131
132
  /**
133
   * @param          $fileName
134
   * @param string[] $vsprintf [$cssPrefix, $cssSuffix, $outName, $relativeUrl,]
135
   *
136
   * @return false|int
137
   */
138
  public function saveCss($fileName, $vsprintf = []) {
139
    // Saving CSS
140
    return file_put_contents($fileName, vsprintf($this->generateCss(), $vsprintf));
141
  }
142
143
  /**
144
   * @param string   $dirOut
145
   * @param string   $outName
146
   * @param string[] $vsprintf [$cssPrefix, $cssSuffix, $outName, $relativeUrl,]
147
   *
148
   * @return void
149
   * @throws Exception
150
   */
151
  public function saveOutput($dirOut, $outName, $vsprintf = []) {
152
    // Checking if output directory exists and creating one - if not
153
    if (!is_dir($dirOut) && !mkdir($dirOut, 0777, true)) {
154
      throw new Exception("Can't create output directory {$dirOut}\n");
155
    }
156
    // Saving PNG
157
    $this->savePng($dirOut . $outName . '.png');
158
    $this->saveCss($dirOut . $outName . '.css', $vsprintf);
159
  }
160
161
  /**
162
   * @return void
163
   */
164
  protected function createGrid() {
165
    $this->lineIndex = 0;
166
167
    usort($this->imageList, function (ImageFile $a, ImageFile $b) { return $b->height - $a->height; });
168
169
    $prevLine = new SpriteLine();
170
    foreach ($this->imageList as $image) {
171
      $line = $prevLine->fillLine($image, $this->gridSize);
172
      if ($line != $prevLine) {
173
        if ($prevLine && $prevLine->width > 0) {
174
          $this->lines[$this->lineIndex] = $prevLine;
175
          $this->lineIndex++;
176
        }
177
        $prevLine = $line;
178
      }
179
    }
180
181
    if ($prevLine) {
0 ignored issues
show
$prevLine is of type Tools\SpriteLine, thus it always evaluated to true.
Loading history...
182
      // There is something in line to keep
183
      $this->lines[$this->lineIndex] = $prevLine;
184
    }
185
  }
186
187
}
188