PageRenderTime 45ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/src/php5_3/CKWalsh/LibSprite/Map.php

https://github.com/ckwalsh/LibSprite
PHP | 253 lines | 124 code | 38 blank | 91 comment | 20 complexity | b0252591ce3e06502f1dee7ff2711fe8 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. <?php
  2. /**
  3. * @package LibSprite
  4. * @copyright (c) 2011 Cullen Walsh
  5. * @license http://www.opensource.org/licenses/bsd-license.php BSD License
  6. */
  7. namespace CKWalsh\LibSprite;
  8. /**
  9. * Represents a specific group of images that are sprited together.
  10. * @package LibSprite
  11. */
  12. class Map {
  13. /**
  14. * The images in this sprite, indexed by id
  15. * @var array
  16. */
  17. private $images = array();
  18. /**
  19. * The options objects for each image in this sprite, indexed by id
  20. * @var array
  21. */
  22. private $options = array();
  23. /**
  24. * The Packer responsible for placing the images in this sprite
  25. * @var Packer
  26. */
  27. private $packer = null;
  28. /**
  29. * The Blocks in use in this sprite. Each contains an image from the
  30. * $images array and takes into account the padding specified in the options
  31. * @var array
  32. */
  33. private $blocks = array();
  34. /**
  35. * The images unable to be used in this sprite. Indexed by id, contains an
  36. * array with the image object and the reason it is not being used.
  37. * @var array
  38. */
  39. private $ignored = array();
  40. /**
  41. * The dimensions of the finished sprite
  42. * @var array(int)
  43. */
  44. private $dims = array();
  45. /**
  46. * Whether the $blocks, $ignored, and $dims variables are up to date,
  47. * considering if images have been added and removed.
  48. * @var bool
  49. */
  50. private $ready = false;
  51. /**
  52. * Construct a new Map object
  53. * @param Packer $packer The Packer object responsible for placing
  54. * images within this sprite
  55. */
  56. public function __construct(Packer $packer) {
  57. $this->setPacker($packer);
  58. }
  59. /**
  60. * Sets a new packer to be used for placing images in this sprite
  61. * @param Packer $packer The new Packer object responsible for
  62. * placing images within this sprite
  63. */
  64. public function setPacker(Packer $packer) {
  65. $this->packer = $packer;
  66. $this->ready = false;
  67. }
  68. /**
  69. * Add a new image to this sprite
  70. * @param Image $image The image to add
  71. * @param Options $options The options for this image, such as padding
  72. * and flush requirements
  73. * @param string $id A unique identifier for this image. If not provided, will
  74. * be filled with a semirandom 6 character hex string.
  75. * @return string the id used for this image
  76. */
  77. public function addImage(Image $image, Options $options = null, $id = false) {
  78. if ($id === false) {
  79. $id = sprintf("%06x", mt_rand(0, 0xffffff));
  80. }
  81. $this->images[$id] = $image;
  82. $this->options[$id] = $options;
  83. $this->ready = false;
  84. return $id;
  85. }
  86. /**
  87. * Removes an image from this sprite
  88. * @param string $id ID of the image to remove
  89. */
  90. public function removeImage($id) {
  91. unset($this->image[$id]);
  92. unset($this->options[$id]);
  93. $this->ready = false;
  94. }
  95. /**
  96. * Returns an array of the blocks used in this mapping, indexed by id. This may
  97. * be used to construct your own CSS and identify which images are really
  98. * contained in this sprite.
  99. * @return array(Block) Blocks in the mapping
  100. */
  101. public function getBlocks() {
  102. if (!$this->ready) {
  103. $this->generate();
  104. }
  105. return $this->blocks;
  106. }
  107. /**
  108. * Returns an array of the images added to the map but not placed in the
  109. * resulting sprite, indexed by id. This may occur when images cannot be loaded
  110. * or conflicting options prevented the image from being placed.
  111. * @return array(Image) Images not used in the mapping
  112. */
  113. public function getIgnoredImages() {
  114. if (!$this->ready) {
  115. $this->generate();
  116. }
  117. return $this->ignored;
  118. }
  119. /**
  120. * Gets the dimensions of the resulting sprite
  121. * @return array Dimensions, where index 0 is the width and 1 is the height
  122. */
  123. public function getDims() {
  124. if (!$this->ready) {
  125. $this->generate();
  126. }
  127. return $this->dims;
  128. }
  129. /**
  130. * Gets the GD image resource of the sprite with all the individual images
  131. * placed in it. Must be freed explicitly by the user of this method via
  132. * imagedestroy()
  133. * @return GD image of the sprite
  134. */
  135. public function getImage() {
  136. if (!$this->ready) {
  137. $this->generate();
  138. }
  139. $img = null;
  140. if (!empty($this->dims) && $this->dims[0] > 0 && $this->dims[1] > 0) {
  141. $img = imagecreatetruecolor($this->dims[0], $this->dims[1]);
  142. $transparent = imagecolorallocatealpha($img, 255, 255, 255, 127);
  143. imagefill($img, 0, 0, $transparent);
  144. foreach ($this->blocks as $block) {
  145. $x = $block->x + $block->xOffset;
  146. $y = $block->y + $block->yOffset;
  147. $width = $block->image->getWidth();
  148. $height = $block->image->getHeight();
  149. imagecopy($img, $block->image->getImage(), $x, $y, 0, 0, $width, $height);
  150. }
  151. }
  152. return $img;
  153. }
  154. public function getCSS($path, $namespace = 'spr') {
  155. if (!$this->ready) {
  156. $this->generate();
  157. }
  158. $css = '.' . $namespace . '{background:transparent url(' . $path . ") no-repeat}\n";
  159. foreach ($this->blocks as $id => $block) {
  160. $css .= '.' . $namespace . '.' . $namespace . '_' . $id . '{background-position:';
  161. $x = $block->x + $block->xOffset;
  162. $y = $block->y + $block->yOffset;
  163. if ($x == 0) {
  164. $css .= '0 ';
  165. } else {
  166. $css .= -$x . 'px ';
  167. }
  168. if ($y == 0) {
  169. $css .= '0';
  170. } else {
  171. $css .= -$y . 'px';
  172. }
  173. $css .= "}\n";
  174. }
  175. return $css;
  176. }
  177. /**
  178. * Processes the images and places them in the mapping. This is called
  179. * implicitly when methods are used that require the sprite mapping to be
  180. * available.
  181. */
  182. public function generate() {
  183. $this->blocks = array();
  184. $this->ignored = array();
  185. $blocks = array();
  186. foreach ($this->images as $id => $image) {
  187. // Only use the images that loaded correctly
  188. if ($image->getImage() === false) {
  189. $this->ignored[$id] = array("image" => $image, "reason" => "Unable to Load");
  190. } else {
  191. $options = $this->options[$id];
  192. if ($options === null) {
  193. $options = new Options();
  194. }
  195. $block = new Block();
  196. $block->image = $image;
  197. $block->xOffset = $options->paddingLeft;
  198. $block->yOffset = $options->paddingTop;
  199. $block->width = $image->getWidth() + $options->paddingLeft + $options->paddingRight;
  200. $block->height = $image->getHeight() + $options->paddingTop + $options->paddingBottom;
  201. $block->flushLeft = $options->flushLeft;
  202. $block->flushRight = $options->flushRight;
  203. $blocks[$id] = $block;
  204. }
  205. }
  206. $this->dims = $this->packer->pack($blocks);
  207. foreach ($blocks as $id => $block) {
  208. if ($block->inUse) {
  209. $this->blocks[$id] = $block;
  210. } else {
  211. $this->ignored[$id] = array("image" => $block->image, "reason" => "Unable to Pack");
  212. }
  213. }
  214. }
  215. }