array( 'x' => 96, 'y' => 40, 'css' => '.phabricator-main-menu-logo', ), 'eye' => array( 'x' => 40, 'y' => 40, 'css' => '.phabricator-main-menu-eye', ), ); $scales = array( '1x' => 1, '2x' => 2, ); $template = new PhutilSprite(); foreach ($sources as $name => $spec) { $sprite = id(clone $template) ->setName($name) ->setSourceSize($spec['x'], $spec['y']) ->setTargetCSS($spec['css']); foreach ($scales as $scale_name => $scale) { $path = 'menu_'.$scale_name.'/'.$name.'.png'; $path = $this->getPath($path); $sprite->setSourceFile($path, $scale); } $sprites[] = $sprite; } $sheet = $this->buildSheet('menu', true); $sheet->setScales($scales); foreach ($sprites as $sprite) { $sheet->addSprite($sprite); } return $sheet; } public function buildTokenSheet() { $icons = $this->getDirectoryList('tokens_1x'); $scales = array( '1x' => 1, '2x' => 2, ); $template = id(new PhutilSprite()) ->setSourceSize(16, 16); $sprites = array(); $prefix = 'tokens_'; foreach ($icons as $icon) { $sprite = id(clone $template) ->setName('tokens-'.$icon) ->setTargetCSS('.tokens-'.$icon); foreach ($scales as $scale_key => $scale) { $path = $this->getPath($prefix.$scale_key.'/'.$icon.'.png'); $sprite->setSourceFile($path, $scale); } $sprites[] = $sprite; } $sheet = $this->buildSheet('tokens', true); $sheet->setScales($scales); foreach ($sprites as $sprite) { $sheet->addSprite($sprite); } return $sheet; } public function buildProjectsSheet() { $icons = $this->getDirectoryList('projects_1x'); $scales = array( '1x' => 1, '2x' => 2, ); $template = id(new PhutilSprite()) ->setSourceSize(50, 50); $sprites = array(); $prefix = 'projects-'; foreach ($icons as $icon) { $sprite = id(clone $template) ->setName($prefix.$icon) ->setTargetCSS('.'.$prefix.$icon); foreach ($scales as $scale_key => $scale) { $path = $this->getPath('projects_'.$scale_key.'/'.$icon.'.png'); $sprite->setSourceFile($path, $scale); } $sprites[] = $sprite; } $sheet = $this->buildSheet('projects', true); $sheet->setScales($scales); foreach ($sprites as $sprite) { $sheet->addSprite($sprite); } return $sheet; } public function buildLoginSheet() { $icons = $this->getDirectoryList('login_1x'); $scales = array( '1x' => 1, '2x' => 2, ); $template = id(new PhutilSprite()) ->setSourceSize(34, 34); $sprites = array(); $prefix = 'login_'; foreach ($icons as $icon) { $sprite = id(clone $template) ->setName('login-'.$icon) ->setTargetCSS('.login-'.$icon); foreach ($scales as $scale_key => $scale) { $path = $this->getPath($prefix.$scale_key.'/'.$icon.'.png'); $sprite->setSourceFile($path, $scale); } $sprites[] = $sprite; } $sheet = $this->buildSheet('login', true); $sheet->setScales($scales); foreach ($sprites as $sprite) { $sheet->addSprite($sprite); } return $sheet; } public function buildGradientSheet() { $gradients = $this->getDirectoryList('gradients'); $template = new PhutilSprite(); $unusual_heights = array( 'breadcrumbs' => 31, 'grey-header' => 70, 'dark-grey-header' => 70, 'lightblue-header' => 240, 'lightgreen-header' => 240, 'lightviolet-header' => 240, 'lightred-header' => 240, ); $sprites = array(); foreach ($gradients as $gradient) { $path = $this->getPath('gradients/'.$gradient.'.png'); $sprite = id(clone $template) ->setName('gradient-'.$gradient) ->setSourceFile($path) ->setTargetCSS('.gradient-'.$gradient); $sprite->setSourceSize(4, idx($unusual_heights, $gradient, 26)); $sprites[] = $sprite; } $sheet = $this->buildSheet( 'gradient', false, PhutilSpriteSheet::TYPE_REPEAT_X); foreach ($sprites as $sprite) { $sheet->addSprite($sprite); } return $sheet; } public function buildMainHeaderSheet() { $gradients = $this->getDirectoryList('main_header'); $template = new PhutilSprite(); $sprites = array(); foreach ($gradients as $gradient) { $path = $this->getPath('main_header/'.$gradient.'.png'); $sprite = id(clone $template) ->setName('main-header-'.$gradient) ->setSourceFile($path) ->setTargetCSS('.main-header-'.$gradient); $sprite->setSourceSize(6, 44); $sprites[] = $sprite; } $sheet = $this->buildSheet('main-header', false, PhutilSpriteSheet::TYPE_REPEAT_X); foreach ($sprites as $sprite) { $sheet->addSprite($sprite); } return $sheet; } private function getPath($to_path = null) { $root = dirname(phutil_get_library_root('phabricator')); return $root.'/resources/sprite/'.$to_path; } private function getDirectoryList($dir) { $path = $this->getPath($dir); $result = array(); $images = Filesystem::listDirectory($path, $include_hidden = false); foreach ($images as $image) { if (!preg_match('/\.png$/', $image)) { throw new Exception( pht( "Expected file '%s' in '%s' to be a sprite source ending in '%s'.", $image, $path, '.png')); } $result[] = substr($image, 0, -4); } return $result; } private function buildSheet( $name, $has_retina, $type = null, $extra_css = '') { $sheet = new PhutilSpriteSheet(); $at = '@'; switch ($type) { case PhutilSpriteSheet::TYPE_STANDARD: default: $type = PhutilSpriteSheet::TYPE_STANDARD; $repeat_rule = 'no-repeat'; break; case PhutilSpriteSheet::TYPE_REPEAT_X: $repeat_rule = 'repeat-x'; break; case PhutilSpriteSheet::TYPE_REPEAT_Y: $repeat_rule = 'repeat-y'; break; } $retina_rules = null; if ($has_retina) { $retina_rules = <<setSheetType($type); $sheet->setCSSHeader(<<