Project

General

Profile

Feature #23150 ยป rfc15079.diff

Administrator Admin, 2010-08-06 21:25

View differences:

t3lib/spritemanager/class.t3lib_spritemanager_spritegenerator.php (Revision 0)
<?php
/***************************************************************
* Copyright notice
*
* (c) 2010 Steffen Ritter <info@steffen-ritter.net>
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project 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.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
* A copy is found in the textfile GPL.txt and important notices to the license
* from the author is found in LICENSE.txt distributed with these scripts.
*
*
* This script 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.
*
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/
/**
* sprite generator
*
* @author Steffen Ritter <info@steffen-ritter.net>
* @package TYPO3
* @subpackage t3lib
*/
class t3lib_spritemanager_SpriteGenerator {
/**
* template creating CSS for the spritefile
* @var string
*/
private $templateSprite = '
.NAMESPACE-SPRITENAME {
background-image: url(\'SPRITEURL\');
height: DEFAULTHEIGHTpx;
width: DEFAULTWIDTHpx;
}
';
/**
*
* template creating CSS for position and size of a single icon
* @var string
*/
private $templateIcon = '
.NAMESPACE-ICONNAME {
background-position: -LEFTpx -TOPpx;
SIZE_INFO
}
';
/**
* most common icon-width in the sprite
* @var int
*/
private $defaultWidth = 0;
/**
* most common icon-width in the sprite
* @var int
*/
private $defaultHeight = 0;
/**
* calculated width of the sprite
* @var int
*/
private $spriteWidth = 0;
/**
* calculated height of the sprite
* @var int
*/
private $spriteHeight = 0;
/**
* sprite name, will be the filename, too
* @var string
*/
private $spriteName = '';
/**
* the folder the sprite-images will be saved (relative to PATH_site)
* @var string
*/
private $spriteFolder = 'typo3temp/sprites/';
/**
* the folder the sprite-cs will be saved (relative to PATH_site)
* @var string
*/
private $cssFolder = 'typo3temp/sprites/';
/**
* the spriteName will not be included in icon names
* @var boolean
*/
private $ommitSpriteNameInIconName = FALSE;
/**
* @var boolean
* @deprecated IE6 support will be dropped within 4.6 - then gifcopies are superflous
*/
private $generateGIFCopy = TRUE;
/**
* namepsce of css classes
* @var string
*/
private $nameSpace = 't3-icon';
/**
* setting this to true, the timestamp of the creation will be included to the background import
* helps to easily rebuild sprites without cache problems
* @var boolean
*/
private $includeTimestampInCSS = TRUE;
/**
* all bases/root-names included in the sprite which has to be in css
* as sprite to include the background-image
* @var array
*/
private $spriteBases = array();
/**
* collects data about all icons to proces
* @var array
*/
private $iconsData = array();
/**
* collects all sizes of icons within this sprite and there count
* @var array
*/
private $iconSizes = array();
/**
* maps icon-sizes to iconnames
* @var array
*/
private $iconNamesPerSize = array();
/**
* space in px between to icons in the sprite (gap)
* @var int
*/
private $space = 2;
/**
* initializes the configuration of the spritegenerator
*
* @param string $spriteName the name of the sprite to be generated
* @return void
*/
public function __construct($spriteName) {
$this->spriteName = $spriteName;
}
/**
* sets namespace of css code
* @param string $string
* @return $this
*/
public function setNamespace($nameSpace) {
$this->nameSpace = $nameSpace;
return $this;
}
/**
* sets the spritename
* @param string $spriteName the name of the sprite to be generated
* @return $this
*/
public function setSpriteName($spriteName) {
$this->spriteName = $spriteName;
return $this;
}
/**
* sets the sprite-graphics target-folder
* @param string $folder the target folder where the generated sprite is stored
* @return $this
*/
public function setSpriteFolder($folder) {
$this->spriteFolder = $folder;
return $this;
}
/**
* sets the sprite-css target-folder
* @param string $folder the target folder where the generated CSS files are stored
* @return $this
*/
public function setCSSFolder($folder) {
$this->cssFolder = $folder;
return $this;
}
/**
* setter do enable the exclusion of the sprites-name from iconnames
* @param boolean $value
* @return $this
*/
public function setOmmitSpriteNameInIconName($value) {
$this->ommitSpriteNameInIconName = is_bool($value) ? $value : FALSE;
return $this;
}
/**
* setter to adjust how much space is between to icons in the sprite
* @param int $value
* @return $this
*/
public function setIconSpace($value) {
$this->space = intval($value);
return $this;
}
/**
* setter to enable/disable generating a GIF-Copy of the sprite
* @param boolean $value
* @deprecated IE6 support will be dropped within 4.6 - then gifcopies are superflous
* @return $this
*/
public function setGenerateGifCopy($value) {
$this->generateGIFCopy = is_bool($value) ? $value : TRUE;
return $this;
}
/**
* setter for timestamp inclusion: imageFiles will be included with ?timestamp
* @param boolean $value
*/
public function setIncludeTimestampInCSS($value) {
$this->includeTimestampInCSS = is_bool($value) ? $value : TRUE;
return $this;
}
/**
* reads all png,gif,jpg files from the passed foldername (including 1 subfolder level)
* extracts size information and stores data in internal array,
* afterwards triggers sprite generation.
* @param array $inputFolder folder from which files are read
* @return array
*/
public function generateSpriteFromFolder(array $inputFolder) {
$iconArray = array();
foreach ($inputFolder as $folder) {
//detect all files to be included in sprites
$iconArray = array_merge(
$iconArray,
$this->getFolder($folder)
);
}
return $this->generateSpriteFromArray($iconArray);
}
/**
*
* @param array $files
* @return array
*/
public function generateSpriteFromArray(array $files) {
if (!$this->ommitSpriteNameInIconName) {
$this->spriteBases[] = $this->spriteName;
}
t3lib_div::debug($this->spriteBases);
$this->buildFileInformationCache($files);
// calculate Icon Position in sprite
$this->calculateSpritePositions();
$this->generateGraphic();
$this->generateCSS();
$iconNames = array_keys($this->iconsData);
natsort($iconNames);
return array(
'spriteImage' => PATH_site . $this->spriteFolder . $this->spriteName . '.png',
'spriteGifImage'=> PATH_site . $this->spriteFolder . $this->spriteName . '.gif',
'cssFile' => PATH_site . $this->cssFolder . $this->spriteName . '.css',
'cssGif' => PATH_site . $this->cssFolder . $this->spriteName . '-ie6.css',
'iconNames' => $iconNames
);
}
/**
* generates the css files
* @return void
*/
private function generateCSS() {
$cssData = '';
$cssIe6 = '';
if($this->includeTimestampInCSS) {
$timestamp = '?' . time();
} else {
$timestamp = '';
}
$spritePathForCSS = $this->resolveSpritePath();
$markerArray = array(
'NAMESPACE' => $this->nameSpace,
'DEFAULTWIDTH' => $this->defaultWidth,
'DEFAULTHEIGHT' => $this->defaultHeight,
'SPRITENAME' => '',
'SPRITEURL' => ($spritePathForCSS ? $spritePathForCSS . DIRECTORY_SEPARATOR : '')
);
$markerArray['SPRITEURL'] .= $this->spriteName . '.png' . $timestamp;
foreach ($this->spriteBases as $base) {
$markerArray['SPRITENAME'] = $base;
$cssData .= t3lib_parsehtml::substituteMarkerArray($this->templateSprite, $markerArray);
}
if ($this->generateGIFCopy) {
$markerArray['SPRITEURL'] = str_replace('.png','.gif',$markerArray['SPRITEURL']);
foreach ($this->spriteBases as $base) {
$cssIe6 .= t3lib_parsehtml::substituteMarkerArray($this->templateSprite, $markerArray);
}
}
foreach ($this->iconsData as $key => $data) {
$markerArrayIcons = array(
'NAMESPACE' => $this->nameSpace,
'ICONNAME' => $data['singleName'],
'LEFT' => $data['left'],
'TOP' => $data['top'],
'SIZE_INFO' => ''
);
if ($data['height'] != $this->defaultHeight) {
$markerArrayIcons['SIZE_INFO'] .= "\theight: " . $data['height'] . 'px;' . LF;
}
if ($data['width'] != $this->defaultWidth) {
$markerArrayIcons['SIZE_INFO'] .= "\twidth: " . $data['width'] . 'px;' . LF;
}
$cssData .= t3lib_parsehtml::substituteMarkerArray($this->templateIcon, $markerArrayIcons);
}
t3lib_div::writeFile(PATH_site . $this->cssFolder . $this->spriteName . '.css', $cssData);
if ($this->generateGIFCopy) {
t3lib_div::writeFile(PATH_site . $this->cssFolder . $this->spriteName . '-ie6.css', $cssIe6);
}
}
/**
* compares Img-Path to CSS path and creates the relative backpath from css to the sprites
* @return string
*/
private function resolveSpritePath() {
$cssPathSegments = t3lib_div::trimExplode(DIRECTORY_SEPARATOR, trim($this->cssFolder, '/'));
$graphicPathSegments = t3lib_div::trimExplode(DIRECTORY_SEPARATOR, trim($this->spriteFolder, '/'));
$i = 0;
while (isset($cssPathSegments[$i]) && isset($graphicPathSegments[$i]) &&
$cssPathSegments[$i] == $graphicPathSegments[$i]) {
unset($cssPathSegments[$i]);
unset($graphicPathSegments[$i]);
++$i;
}
foreach ($cssPathSegments AS $key => $value) {
$cssPathSegments[$key] = '..';
}
$completePath = array_merge($cssPathSegments, $graphicPathSegments);
$path = implode(DIRECTORY_SEPARATOR, $completePath);
return t3lib_div::resolveBackPath($path);
}
/**
* the actual sprite generator, renders the command for Im/GM and executes
* @return void
*/
private function generateGraphic() {
$iconParameters = array();
$tempSprite = t3lib_div::tempnam($this->spriteName);
$filePath = array(
'mainFile' => PATH_site . $this->spriteFolder . $this->spriteName . '.png',
'gifFile' => NULL
);
// create black true color image with given size
$newSprite = imagecreatetruecolor($this->spriteWidth, $this->spriteHeight);
imagesavealpha($newSprite, true);
// make it transparent
imagefill($newSprite, 0, 0, imagecolorallocatealpha($newSprite, 0, 255, 255, 127));
foreach ($this->iconsData AS $icon) {
$function = 'imagecreatefrom' . strtolower($icon['fileExtension']);
if(function_exists($function)) {
$currentIcon = $function($icon['fileName']);
imagecopy($newSprite, $currentIcon, $icon['left'], $icon['top'], 0, 0, $icon['width'], $icon['height']);
}
}
imagepng($newSprite, $tempSprite . '.png');
if ($this->generateGIFCopy) {
$filePath['gifFile'] = PATH_site . $this->spriteFolder . $this->spriteName . '.gif';
$gifSprite = imagecreatetruecolor($this->spriteWidth, $this->spriteHeight);
// make it transparent
imagefill($gifSprite, 0, 0, imagecolorallocate($gifSprite, 127, 127, 127));
foreach ($this->iconsData AS $icon) {
$function = 'imagecreatefrom' . strtolower($icon['fileExtension']);
if(function_exists($function)) {
$currentIcon = $function($icon['fileName']);
imagecopy($gifSprite, $currentIcon, $icon['left'], $icon['top'], 0, 0, $icon['width'], $icon['height']);
}
}
imagecolortransparent($gifSprite, imagecolorallocate($gifSprite, 127, 127, 127));
imagegif($gifSprite, $tempSprite . '.gif');
}
t3lib_div::upload_copy_move($tempSprite . '.png', $filePath['mainFile']);
t3lib_div::unlink_tempfile($tempSprite . '.png');
if ($this->generateGIFCopy) {
t3lib_div::upload_copy_move($tempSprite . '.gif', $filePath['gifFile']);
t3lib_div::unlink_tempfile($tempSprite . '.gif');
}
}
/**
* aranges icons in sprites,
* afterwards all icons have information about ther position in sprite
*/
private function calculateSpritePositions() {
$currentLeft = 0;
$currentTop = 0;
// calculate width of every icon-size-group
$sizes = array();
foreach ($this->iconSizes as $sizeTag => $count) {
$size = $this->explodeSizeTag($sizeTag);
$sizes[ceil(sqrt($count)) * $size['width']] = $sizeTag;
}
// reverse sorting: widest group to top
krsort($sizes);
// integerate all icons grouped by icons size into the sprite
foreach ($sizes as $sizeTag) {
$size = $this->explodeSizeTag($sizeTag);
$currentLeft = 0;
$rowCounter = 0;
$rowSize = ceil(sqrt($this->iconSizes[$sizeTag]));
$rowWidth = $rowSize * $size['width'] + ($rowSize - 1) * $this->space;
$this->spriteWidth = ($rowWidth > $this->spriteWidth ? $rowWidth : $this->spriteWidth);
$firstLine = true;
natsort($this->iconNamesPerSize[$sizeTag]);
foreach ($this->iconNamesPerSize[$sizeTag] as $iconName) {
if ($rowCounter == $rowSize - 1) {
$rowCounter = -1;
} else if ($rowCounter == 0) {
if(!$firstLine) {
$currentTop += $size['height'];
$currentTop += $this->space;
}
$firstLine = false;
$currentLeft = 0;
}
$this->iconsData[$iconName]['left'] = $currentLeft;
$this->iconsData[$iconName]['top'] = $currentTop;
$currentLeft += $size['width'];
$currentLeft += $this->space;
$rowCounter++;
}
$currentTop += $size['height'];
$currentTop += $this->space;
}
$this->spriteHeight = $currentTop;
}
/**
* getFiles traverses the target directory,
* locates all iconFiles and
* @param string path to an folder which contains images
* @return array returns an array with all files key: iconname, value: fileName
*/
private function getFolder($directoryPath) {
$subFolders = t3lib_div::get_dirs(PATH_site . $directoryPath);
if (!$this->ommitSpriteNameInIconName) {
$subFolders[] = '';
}
$resultArray = array();
foreach ($subFolders as $folder) {
if ($folder != '.svn') {
$icons = t3lib_div::getFilesInDir(PATH_site . $directoryPath . $folder . DIRECTORY_SEPARATOR, 'gif,png,jpg');
if (!in_array($folder, $this->spriteBases) && count($icons)) {
$this->spriteBases[] = $folder;
}
foreach ($icons AS $icon) {
$fileInfo = pathinfo($icon);
$iconName = ($folder ? $folder . '-' : '') . $fileInfo['filename'];
if (!$this->ommitSpriteNameInIconName) {
$iconName = $this->spriteName . '-' . $iconName;
}
$resultArray[$iconName] = $directoryPath . $folder . DIRECTORY_SEPARATOR . $icon;
}
}
}
return $resultArray;
}
/**
* generates fileInformation Cache from file Array
* @param array list of all files with their icon name
* @return void
*/
private function buildFileInformationCache(array $files) {
foreach ($files as $iconName => $iconFile) {
$fileInfo = pathinfo(PATH_site . $iconFile);
$imageInfo = getimagesize(PATH_site . $iconFile);
$this->iconsData[$iconName] = array(
'iconName' => $iconName,
'singleName'=> $fileInfo['filename'],
'fileExtension'=> $fileInfo['extension'],
'fileName' => PATH_site . $iconFile,
'width' => $imageInfo[0],
'height' => $imageInfo[1],
'left' => 0,
'top' => 0
);
$sizeTag = $imageInfo[0] . 'x' . $imageInfo[1];
if (isset($this->iconSizes[$sizeTag])) {
$this->iconSizes[$sizeTag] += 1;
} else {
$this->iconSizes[$sizeTag] = 1;
$this->iconNamesPerSize[$sizeTag] = array();
}
$this->iconNamesPerSize[$sizeTag][] = $iconName;
}
// find most common imagesize, save it as default
asort($this->iconSizes);
$defaultSize = $this->explodeSizeTag(array_pop(array_keys($this->iconSizes)));
$this->defaultWidth = $defaultSize['width'];
$this->defaultHeight = $defaultSize['height'];
}
/**
* transforms size tag into size array
* @param string a size tag at the cache arrays
* @return array
*/
private function explodeSizeTag($tag = '') {
$size = t3lib_div::trimExplode("x", $tag);
return array(
'width' => $size[0],
'height'=> $size[1]
);
}
}
?>
t3lib/core_autoload.php (Arbeitskopie)
't3lib_spritemanager' => PATH_t3lib . 'class.t3lib_spritemanager.php',
't3lib_spritemanager_spriteicongenerator' => PATH_t3lib . 'interfaces/interface.t3lib_spritemanager_spriteicongenerator.php',
't3lib_spritemanager_simplehandler' => PATH_t3lib . 'spritemanager/class.t3lib_spritemanager_simplehandler.php',
't3lib_spritemanager_spritegenerator' => PATH_t3lib . 'spritemanager/class.t3lib_spritemanager_spritegenerator.php',
);
$tslibClasses = require(PATH_typo3 . 'sysext/cms/ext_autoload.php');
    (1-1/1)