From 2d65b8c600580cd64aa599a791a467101b873c5a Mon Sep 17 00:00:00 2001 From: Julius Haertl Date: Sun, 14 Aug 2016 12:24:51 +0200 Subject: [PATCH] Theming: Add favicon-touch and fix icon creation with non svg images Signed-off-by: Julius Haertl --- apps/theming/appinfo/routes.php | 8 +- .../theming/lib/Controller/IconController.php | 96 +++++++++++++------ lib/private/URLGenerator.php | 4 +- 3 files changed, 75 insertions(+), 33 deletions(-) diff --git a/apps/theming/appinfo/routes.php b/apps/theming/appinfo/routes.php index 1894d810287..a6511668d14 100644 --- a/apps/theming/appinfo/routes.php +++ b/apps/theming/appinfo/routes.php @@ -66,9 +66,15 @@ return ['routes' => [ 'verb' => 'GET', 'defaults' => array("app" => "core"), ], + [ + 'name' => 'Icon#getTouchIcon', + 'url' => '/icon/{app}', + 'verb' => 'GET', + 'defaults' => array("app" => "core"), + ], [ 'name' => 'Icon#getThemedIcon', - 'url' => '/image/{app}/{image}', + 'url' => '/img/{app}/{image}', 'verb' => 'GET', 'defaults' => array("app" => "core"), 'requirements' => array('image' => '.+') diff --git a/apps/theming/lib/Controller/IconController.php b/apps/theming/lib/Controller/IconController.php index e1690c039d3..d7c27a88134 100644 --- a/apps/theming/lib/Controller/IconController.php +++ b/apps/theming/lib/Controller/IconController.php @@ -121,53 +121,87 @@ class IconController extends Controller { return $response; } + /** + * Return a 512x512 icon for touch devices + * + * @PublicPage + * @NoCSRFRequired + * + * @param $app app name + * @return StreamResponse|DataResponse + */ + public function getTouchIcon($app) { + // TODO: we need caching here + $icon = $this->renderAppIcon($app); + $icon->resizeImage(512, 512, Imagick::FILTER_LANCZOS, 1); + $icon->setImageFormat("png24"); + + $response = new DataDisplayResponse($icon, Http::STATUS_OK, ['Content-Type' => 'image/png']); + $response->cacheFor(3600); + $response->addHeader('Expires', date(\DateTime::RFC2822, $this->timeFactory->getTime())); + return $response; + } + + /** + * Render app icon on themed background color + * fallback to logo + * + * @param $app app name + * @return Imagick + */ private function renderAppIcon($app) { $appIcon = $this->getAppIcon($app); $color = $this->config->getAppValue($this->appName, 'color'); + $mime = mime_content_type($appIcon); if ($color === "") { $color = '#0082c9'; } - $svg = file_get_contents($appIcon); - if ($this->util->invertTextColor($color)) { - $svg = $this->svgInvert($svg); - } - // generate background image with rounded corners $background = '' . '' . '' . ''; - $tmp = new Imagick(); - $tmp->readImageBlob($svg); - $x = $tmp->getImageWidth(); - $y = $tmp->getImageHeight(); - $res = $tmp->getImageResolution(); - $tmp->destroy(); - - // convert svg to resized image - $appIconFile = new Imagick(); - $resX = (int)(512 * $res['x'] / $x * 2.53); - $resY = (int)(512 * $res['y'] / $y * 2.53); - $appIconFile->setResolution($resX, $resY); - $appIconFile->setBackgroundColor(new ImagickPixel('transparent')); - $appIconFile->readImageBlob($svg); - $appIconFile->setImageFormat("png24"); - // offset for icon positioning - $offset_w = (int)($appIconFile->getImageWidth() * 0.05); - $offset_h = (int)($appIconFile->getImageHeight() * 0.05); - // center icon if it is not square - if ($x > $y) { - $offset_h += 512 / 2 - $appIconFile->getImageHeight() / 2; - } - if ($y > $x) { - $offset_h += 512 / 2 - $appIconFile->getImageHeight() / 2; + // resize svg magic as this seems broken in Imagemagick + if($mime === "image/svg+xml") { + $svg = file_get_contents($appIcon); + if ($this->util->invertTextColor($color)) { + $svg = $this->svgInvert($svg); + } + + $tmp = new Imagick(); + $tmp->readImageBlob($svg); + $x = $tmp->getImageWidth(); + $y = $tmp->getImageHeight(); + $res = $tmp->getImageResolution(); + $tmp->destroy(); + + // convert svg to resized image + $appIconFile = new Imagick(); + $resX = (int)(512 * $res['x'] / $x * 2.53); + $resY = (int)(512 * $res['y'] / $y * 2.53); + $appIconFile->setResolution($resX, $resY); + $appIconFile->setBackgroundColor(new ImagickPixel('transparent')); + $appIconFile->readImageBlob($svg); + } else { + $appIconFile = new Imagick(); + $appIconFile->setBackgroundColor(new ImagickPixel('transparent')); + $appIconFile->readImageBlob(file_get_contents($appIcon)); + $appIconFile->scaleImage(512, 512, true); } - $innerWidth = (int)($appIconFile->getImageWidth() - $offset_w * 2); - $innerHeight = (int)($appIconFile->getImageHeight() - $offset_h * 2); + // offset for icon positioning + $border_w = (int)($appIconFile->getImageWidth() * 0.05); + $border_h = (int)($appIconFile->getImageHeight() * 0.05); + $innerWidth = (int)($appIconFile->getImageWidth() - $border_w * 2); + $innerHeight = (int)($appIconFile->getImageHeight() - $border_h * 2); $appIconFile->adaptiveResizeImage($innerWidth, $innerHeight); + // center icon + $offset_w = 512 / 2 - $innerWidth / 2; + $offset_h = 512 / 2 - $innerHeight / 2; + + $appIconFile->setImageFormat("png24"); $finalIconFile = new Imagick(); $finalIconFile->readImageBlob($background); diff --git a/lib/private/URLGenerator.php b/lib/private/URLGenerator.php index e730bf7aedd..8972f1602e3 100644 --- a/lib/private/URLGenerator.php +++ b/lib/private/URLGenerator.php @@ -157,8 +157,10 @@ class URLGenerator implements IURLGenerator { // Check if the app is in the app folder $path = ''; - if(\OCP\App::isEnabled('theming') && $image === "favicon.ico" && $app !== "") { + if(\OCP\App::isEnabled('theming') && $image === "favicon.ico") { $path = $this->linkToRoute('theming.Icon.getFavicon', [ 'app' => $app ]); + } elseif(\OCP\App::isEnabled('theming') && $image === "favicon-touch.png") { + $path = $this->linkToRoute('theming.Icon.getTouchIcon', [ 'app' => $app ]); } elseif (file_exists(\OC::$SERVERROOT . "/themes/$theme/apps/$app/img/$image")) { $path = \OC::$WEBROOT . "/themes/$theme/apps/$app/img/$image"; } elseif (!file_exists(\OC::$SERVERROOT . "/themes/$theme/apps/$app/img/$basename.svg") -- 2.39.5