/** * Check map_id value for allow chars and return map-config array by map_id. * * First check if user qpimg_config class has get_map function and * ask data by this function. Otherwise get data from map-array. * Otherwise return false. * * @param string $map_id * * @return array map-config data or false */ public static function get_map($map_id) { $qpimg_config = $GLOBALS['qpimg_config']; if (preg_match('/[^a-zA-Z0-9_]/', $map_id) > 0) { qpimg_logger::write("QPIMG_WARNING: Used illegal chars in map name '{$map_id}'", __FILE__, __LINE__); return false; } $map_cfg = false; if (function_exists('qpimg_user_get_map') === true) { $map_cfg = qpimg_user_get_map($map_id); } if (!$map_cfg) { if (isset($qpimg_config['maps']) === false || isset($qpimg_config['maps'][$map_id]) === false) { qpimg_logger::write("QPIMG_WARNING: Asked map '{$map_id}' is not exists", __FILE__, __LINE__); return false; } $map_cfg = $qpimg_config['maps'][$map_id]; } $map_cfg['id'] = $map_id; if (isset($map_cfg['hash']) === false) { $map_cfg['hash'] = qpimg_cache::get_basic_hash($map_cfg); } return $map_cfg; }
/** * Base generate function. Detect all using maps (incoming map_id & it's attach * and sub-sub-...-attach maps). Check validate of cache files. Then if need * generate data and make redirect to CSS-file. * If $get_link is true then return path to file * * @param string $map_id * * @param bool $get_link * * @return bool global execute status */ public static function execute($map_id, $get_link = FALSE) { list($map_id) = explode(':', $map_id); $need_get_maps_stack = array($map_id); $valid_maps_stack = array(); $invalid_maps_stack = array(); while (count($need_get_maps_stack) > 0) { $one_map_id = array_shift($need_get_maps_stack); $one_map_cfg = qpimg_config::get_map($one_map_id); if ($one_map_cfg === false) { return false; } if (isset($one_map_cfg['attach']) === true) { if (is_array($one_map_cfg['attach']) === false) { $one_map_cfg['attach'] = array($one_map_cfg['attach']); } foreach ($one_map_cfg['attach'] as $attach_map_id) { if (isset($valid_maps_stack[$attach_map_id]) === false && isset($invalid_maps_stack[$attach_map_id]) === false) { $need_get_maps_stack[] = $attach_map_id; } } } //--------------------------------------------------------------------- // Check for data in cache if (qpimg_cache::validate($one_map_cfg) === true) { $valid_maps_stack[$one_map_id] = $one_map_cfg; } else { if (qpimg_cache::clean($one_map_cfg) === false) { return false; } $invalid_maps_stack[$one_map_id] = $one_map_cfg; } if ($map_id == $one_map_id) { $map_cfg = $one_map_cfg; } } if (count($invalid_maps_stack) > 0) { if (isset($invalid_maps_stack[$map_id]) === false) { $invalid_maps_stack[$map_id] = $valid_maps_stack[$map_id]; unset($valid_maps_stack[$map_id]); } //--------------------------------------------------------------------- // Generate data foreach ($invalid_maps_stack as $one_map_id => $one_map_cfg) { if (qpimg_media::pack($one_map_cfg) === false) { return false; } $valid_maps_stack[$one_map_id] = $invalid_maps_stack[$one_map_id]; } qpimg_cache::clean($one_map_cfg, true); if (qpimg_media::pack_grouper_css($map_cfg, $valid_maps_stack) === false) { return false; } //--------------------------------------------------------------------- } return $get_link ? qpimg_cache::get_valid_css_source($map_cfg, isset($map_cfg['attach'])) : qpimg_cache::redirect($map_cfg); }
/** * Generate css & sprite (image) for single map * * @param array $map_cfg map-config array * * @return bool status */ public static function pack($map_cfg) { //--------------------------------------------------------------------- // PreCheck incoming data if (is_array($map_cfg['objects']) === false) { $map_cfg['objects'] = array(); } //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - if (isset($map_cfg['verbose_check']) === false) { $map_cfg['verbose_check'] = false; } $map_cfg['verbose_check'] = (bool) $map_cfg['verbose_check']; //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - $map_cfg['save_format'] = strtolower($map_cfg['save_format']); if (in_array($map_cfg['save_format'], array('png', 'gif', 'jpg')) === false) { $map_cfg['save_format'] = 'png'; } //--------------------------------------------------------------------- self::prepare_media_items($map_cfg); if ($map_cfg['objects:dataURI_files_count'] == 0) { // if no dataURI media-items -> then no need proecee MODE_DATAURI_REJECT $process_modes = array(self::MODE_STANDARD); } else { $process_modes = array(self::MODE_STANDARD, self::MODE_DATAURI_REJECT); } foreach ($process_modes as $mode) { switch ($mode) { case self::MODE_STANDARD: $css_filename = qpimg_cache::gen_filename($map_cfg, 'css', qpimg::CSS_FILE_KEY_DEFAULT); $sprite_filename = qpimg_cache::gen_filename($map_cfg, $map_cfg['save_format'], qpimg::SPRITE_FILE_KEY_DEFAULT); $sprite_url = qpimg_cache::gen_filename($map_cfg, $map_cfg['save_format'], qpimg::SPRITE_FILE_KEY_DEFAULT, true); break; case self::MODE_DATAURI_REJECT: $css_filename = qpimg_cache::gen_filename($map_cfg, 'css', qpimg::CSS_FILE_KEY_DATAURI_REJECT); $sprite_filename = qpimg_cache::gen_filename($map_cfg, $map_cfg['save_format'], qpimg::SPRITE_FILE_KEY_DATAURI_REJECT); $sprite_url = qpimg_cache::gen_filename($map_cfg, $map_cfg['save_format'], qpimg::SPRITE_FILE_KEY_DATAURI_REJECT, true); break; } //--------------------------------------------------------------------- // Set positions of each media-item-element for sprite switch ($map_cfg['orientation']) { case 'static': default: $set_position_funcname = 'set_position_static'; $css_bg_repeat_style = 'no-repeat'; break; case 'repeat_x': $set_position_funcname = 'set_position_repeat_x'; $css_bg_repeat_style = 'repeat-x'; break; case 'repeat_y': $set_position_funcname = 'set_position_repeat_y'; $css_bg_repeat_style = 'repeat-y'; break; } list($pos_media_items, $img_width, $img_height) = self::$set_position_funcname($map_cfg, $mode); //--------------------------------------------------------------------- // Save CSS data (by mode) $css_data = array(); if (count($pos_media_items) > 0) { $css_data[':main_sprite']['background-image'] = "url('{$sprite_url}')"; $css_data[':main_sprite']['background-repeat'] = $css_bg_repeat_style; $css_data[':main_sprite'][':css-selector'] = array(); } // Generate crash rules foreach ($map_cfg['objects:items'] as $media_id => $media_item) { if ($media_item->is_crashed() === false) { continue; } $item_css_data = array(); $item_css_data['background-image'] = 'none !important'; $item_css_data['background-color'] = '#800000'; $css_data[qpimg::get_obj_css_selector($map_cfg['id'], $media_id, $map_cfg)] = $item_css_data; } // Generate items data foreach ($pos_media_items as $media_id => $media_item) { $item_css_data = array(); $item_css_data['background-position'] = -($media_item->get('left') + $media_item->get('space-left')) . "px " . -($media_item->get('top') + $media_item->get('space-top')) . "px"; self::prepare_item_css($item_css_data, $media_item); $css_data[':main_sprite'][':css-selector'] = array_merge($css_data[':main_sprite'][':css-selector'], $item_css_data[':css-selector']); $css_data[qpimg::get_obj_css_selector($map_cfg['id'], $media_id, $map_cfg)] = $item_css_data; } unset($item_css_data); // Generate data:URI content (for MODE_STANDARD) if ($mode == self::MODE_STANDARD) { if (is_array($map_cfg['objects:items']) === true) { foreach ($map_cfg['objects:items'] as $media_id => $media_item) { if ($media_item->is_crashed() === true) { continue; } if ($media_item->get('data:URI') === false) { continue; } $item_css_data = array(); self::prepare_item_css($item_css_data, $media_item); switch ($media_item->get('imagetype')) { case IMAGETYPE_GIF: $mimetype = 'image/gif'; break; case IMAGETYPE_JPEG: $mimetype = 'image/jpeg'; break; case IMAGETYPE_PNG: $mimetype = 'image/png'; break; } $item_css_data['background-image'] = "url(" . "data:{$mimetype};" . "base64," . base64_encode(@file_get_contents($media_item->get('source'))) . ")"; $css_data[qpimg::get_obj_css_selector($map_cfg['id'], $media_id, $map_cfg)] = $item_css_data; } } } $css_hf = @fopen($css_filename, 'w'); if (is_resource($css_hf) === false) { self::drop_temporary_media(); return false; } ksort($css_data); foreach ($css_data as $css_selector => $item_css_data) { if ($css_selector == ':main_sprite') { $css_selector = qpimg::get_map_css_selector($map_cfg['id'], $map_cfg); } fwrite($css_hf, ".{$css_selector}"); if (is_array($item_css_data[':css-selector']) === true) { foreach ($item_css_data[':css-selector'] as $sub_css_selector) { $sub_css_selector = trim($sub_css_selector); if ($sub_css_selector == '') { continue; } fwrite($css_hf, ", {$sub_css_selector}"); } } fwrite($css_hf, " { "); foreach ($item_css_data as $css_attr_key => $css_attr_value) { if ($css_attr_key[0] == ':') { continue; } fwrite($css_hf, "{$css_attr_key}: {$css_attr_value}; "); } fwrite($css_hf, "}\n"); } fclose($css_hf); //--------------------------------------------------------------------- // Make SPRITE (image) if (count($pos_media_items) > 0) { $sprite_img = @imagecreatetruecolor($img_width, $img_height); if (is_resource($sprite_img) === false) { self::drop_temporary_media(); return false; } imagealphablending($sprite_img, false); imagesavealpha($sprite_img, true); if (isset($map_cfg['bgcolor']) === true && $map_cfg['bgcolor']) { list($color_r, $color_g, $color_b) = qpimg_utils::color2rgb($map_cfg['bgcolor']); imagefill($sprite_img, 0, 0, imagecolorallocate($sprite_img, $color_r, $color_g, $color_b)); unset($color_r, $color_g, $color_b); } else { imagefill($sprite_img, 0, 0, imagecolorallocatealpha($sprite_img, 0, 0, 0, 127)); } //--------------------------------------------------------------------- if (isset($map_cfg['transparent_color']) === true) { list($color_r, $color_g, $color_b) = qpimg_utils::color2rgb($map_cfg['transparent_color']); imagecolortransparent($sprite_img, imagecolorallocate($sprite_img, $color_r, $color_g, $color_b)); unset($color_r, $color_g, $color_b); } //--------------------------------------------------------------------- // Copy images in sprite & save css attributes for each element foreach ($pos_media_items as $media_id => $media_item) { $safe_image_source = self::parse_media_source($media_item->get('source'), $map_cfg['id']); if ($safe_image_source === false) { continue; } //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - switch ($media_item->get('imagetype')) { case IMAGETYPE_GIF: $tmp_img = @imagecreatefromgif($safe_image_source); break; case IMAGETYPE_JPEG: $tmp_img = @imagecreatefromjpeg($safe_image_source); break; case IMAGETYPE_PNG: $tmp_img = @imagecreatefrompng($safe_image_source); break; } if (is_resource($tmp_img) === false) { continue; } $src_x = 0; $src_y = 0; $src_w = $media_item->get('etalon-width'); $src_h = $media_item->get('etalon-height'); $dst_x = $media_item->get('left') + $media_item->get('space-left'); $dst_y = $media_item->get('top') + $media_item->get('space-top'); $dst_w = $media_item->get('scale-width'); $dst_h = $media_item->get('scale-height'); if ($media_item->get('bgcolor') !== false) { list($color_r, $color_g, $color_b) = qpimg_utils::color2rgb($media_item->get('bgcolor')); imagefilledrectangle($sprite_img, $media_item->get('left'), $media_item->get('top'), $media_item->get('left') + $media_item->get('full-width') - 1, $media_item->get('top') + $media_item->get('full-height') - 1, imagecolorallocate($sprite_img, $color_r, $color_g, $color_b)); unset($color_r, $color_g, $color_b); } if ($src_w == $dst_w && $src_h == $dst_h) { imagecopy($sprite_img, $tmp_img, $dst_x, $dst_y, $src_x, $src_y, $src_w, $src_h); } else { if ($media_item->get('scale-method') == 'resize') { imagecopyresized($sprite_img, $tmp_img, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h); } elseif ($media_item->get('scale-method') == 'resample') { imagecopyresampled($sprite_img, $tmp_img, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h); } elseif ($media_item->get('scale-method') == 'mosaic') { $mosaic_y = $dst_y; $mosaic_h = $dst_h; do { $mosaic_x = $dst_x; $mosaic_w = $dst_w; do { imagecopy($sprite_img, $tmp_img, $mosaic_x, $mosaic_y, 0, 0, min($mosaic_w, $src_w), min($mosaic_h, $src_h)); $mosaic_x += $src_w; $mosaic_w -= $src_w; } while ($mosaic_w > 0); $mosaic_y += $src_h; $mosaic_h -= $src_h; } while ($mosaic_h > 0); unset($mosaic_x, $mosaic_y, $mosaic_w, $mosaic_h); } else { qpimg_logger::write("QPIMG_WARNING: Undefined scale-method: " . $media_item->get('scale-method'), __FILE__, __LINE__); continue; } } unset($src_x, $src_y, $src_w, $src_h); unset($dst_x, $dst_y, $dst_w, $dst_h); imagedestroy($tmp_img); } //--------------------------------------------------------------------- // Save image-data switch ($map_cfg['save_format']) { case 'png': if (isset($map_cfg['save_quality']) === false) { $map_cfg['save_quality'] = 9; } $save_result = @imagepng($sprite_img, $sprite_filename, min(max($map_cfg['save_quality'], 0), 9)); break; case 'gif': $save_result = @imagegif($sprite_img, $sprite_filename); break; case 'jpg': if (isset($map_cfg['save_quality']) === false) { $map_cfg['save_quality'] = 95; } $save_result = @imagejpeg($sprite_img, $sprite_filename, min(max($map_cfg['save_quality'], 0), 100)); break; } if ($save_result === false) { qpimg_logger::write("QPIMG_ERROR: Failed on save result sprite '{$sprite_filename}'", __FILE__, __LINE__); } imagedestroy($sprite_img); } } //--------------------------------------------------------------------- // Save crc-hash [if set verbose_check mode] if ($map_cfg['verbose_check'] === true) { @file_put_contents(qpimg_cache::gen_filename($map_cfg, 'crc'), $map_cfg['hash'] . ':' . qpimg_cache::get_media_hash($map_cfg)); } self::drop_temporary_media(); return true; }