1<?php 2 3namespace dokuwiki\plugin\gallery\classes; 4 5/** 6 * Formats the gallery 7 * 8 * This is the most basic implementation. It simply adds linked thumbnails to the page. It will not look 9 * good, but will work with any renderer. Specialized formatters can be created for each renderer to make 10 * use of their special features. 11 */ 12class BasicFormatter 13{ 14 /** @var Options */ 15 protected $options; 16 /** @var \Doku_Renderer */ 17 protected $renderer; 18 19 /** 20 * Create a new Gallery formatter 21 * 22 * @param \Doku_Renderer $renderer 23 * @param Options $options 24 */ 25 public function __construct(\Doku_Renderer $renderer, Options $options) 26 { 27 $this->options = $options; 28 $this->renderer = $renderer; 29 } 30 31 /** 32 * Render the whole Gallery 33 * 34 * @param AbstractGallery $gallery 35 * @return void 36 */ 37 public function render(AbstractGallery $gallery) 38 { 39 $images = $gallery->getImages(); 40 foreach ($images as $image) { 41 $this->renderImage($image); 42 } 43 } 44 45 /** 46 * Render a single thumbnail image in the gallery 47 * 48 * @param Image $image 49 * @return void 50 */ 51 protected function renderImage(Image $image) 52 { 53 [$w, $h] = $this->getThumbnailSize($image); 54 $link = $image->getDetaillink() ?: $image->getSrc(); 55 56 $imgdata = [ 57 'src' => $image->getSrc(), 58 'title' => $image->getTitle(), 59 'align' => '', 60 'width' => $w, 61 'height' => $h, 62 'cache' => '' 63 ]; 64 65 if ($image->isExternal()) { 66 $this->renderer->externallink($link, $imgdata); 67 } else { 68 $this->renderer->internalmedia(":$link", $imgdata); // prefix with : to ensure absolute src 69 } 70 } 71 72 73 // region Utilities 74 75 /** 76 * Calculate the thumbnail size 77 * 78 * @param Image $image 79 * @param int|float $retina The retina scaling factor 80 * @return array 81 */ 82 protected function getThumbnailSize(Image $image, $retina = 1) 83 { 84 $thumbW = $this->options->thumbnailWidth * $retina; 85 $thumbH = $this->options->thumbnailHeight * $retina; 86 87 // if image size is unknown, use the configured thumbnail size 88 if (!$image->getWidth() || !$image->getHeight()) { 89 return [$thumbW, $thumbH]; 90 } 91 92 // avoid upscaling 93 if ( 94 $image->getWidth() < $thumbW && 95 $image->getHeight() < $thumbH 96 ) { 97 return [$image->getWidth(), $image->getHeight()]; 98 } 99 100 if (!$this->options->crop) { 101 [$thumbWidth, $thumbHeight] = $this->fitBoundingBox( 102 $image->getWidth(), 103 $image->getHeight(), 104 $thumbW, 105 $thumbH 106 ); 107 } else { 108 $thumbWidth = $thumbW; 109 $thumbHeight = $thumbH; 110 } 111 return [$thumbWidth, $thumbHeight]; 112 } 113 114 115 /** 116 * Calculate the size of a thumbnail to fit into a bounding box 117 * 118 * @param int $imgWidth 119 * @param int $imgHeight 120 * @param int $bBoxWidth 121 * @param int $bBoxHeight 122 * @return int[] 123 */ 124 protected function fitBoundingBox($imgWidth, $imgHeight, $bBoxWidth, $bBoxHeight) 125 { 126 $scale = min($bBoxWidth / $imgWidth, $bBoxHeight / $imgHeight); 127 128 $width = round($imgWidth * $scale); 129 $height = round($imgHeight * $scale); 130 131 return [$width, $height]; 132 } 133 134 // endregion 135} 136