Browse Source

Les filtres |balise_img et |balise_svg sont survitamines :

- le filtre |balise_img peut prendre en premier argument une balise img deja formee si besoin - ie issue d'un filtre image :
  `[(#FICHIER|image_reduire{200,200}|balise_img{'un nuage','spip_logo'})]`
- idem pour le filtre |balise_svg qui peut avoir en premier argument une balise svg inline deja preparee

Mais surtout :
- les 2 filtrez peuvent prendre un dernier argument size pour forcer la taille sous plusieurs formes :
  * `@1.5x`, `@2x` ou `@3x` permet de forcer une densite de 1.5, 2 ou 3 (on reprend la convention generique de nommage des assets)
    une image de largeur 200px affichee avec un `@2x` aura donc un attribut `width='100'`
  * Un nombre seul comme `64` pour forcer une image carree avec `width='64' height='64'`
  * Une largeur ET une hauteur sour la forme `1024x640` pour avoir un `width='1024' height='640'`
  * Une largeur seule et une hauteur automatique sous la forme '1024x*` pour avoir donc un `width='1024'` et un height ajuste automatiquement pour respecter les proportions initiales de l'image

Pour faciliter l'utilisation des 2 filtres, l'argument de taille (optionnel) arrive toujours en dernier, meme si on ne precise pas de alt ou de class :
`[(#FICHIER|balise_img{1024x640})]`
`[(#FICHIER|balise_img{'un nuage',1024x640})]`
`[(#FICHIER|balise_img{'un nuage','spip_logo',1024x640})]`

Mais si jamais le alt ou la class sont ambigus et peuvent etre interpretes comme une taille (a priori tres invraisemblable pour la class), il suffit d'indiquer une taille vide pour lever l'ambiguite :
`[(#FICHIER|balise_img{'@2x','',''})]`

Le filtre |balise_img peut donc ainsi facilement etre utilise pour ajuster l'affichage d'image en x2 ou x3 pour prendre en compte les ecrans retina :
`[(#FICHIER|image_reduire{400,400}|balise_img{'Mon image HD',@2x})]`

De même le filtre |balise_svg pourra être utilisé pour ajuster simplement la taille d'un svg inline

Au passage la fonction `taille_image()` fonctionne aussi sur un SVG inline
pull/132/head
Cerdic 7 months ago
parent
commit
5c40d310ce
  1. 191
      ecrire/inc/filtres.php

191
ecrire/inc/filtres.php

@ -607,6 +607,18 @@ function taille_image($img, $force_refresh = false) {
$hauteur_img[$src] = $srcHeight = $srcsize[1];
}
}
elseif(strpos($src, "<svg") !== false) {
include_spip('inc/svg');
if ($attrs = svg_lire_attributs($src)){
list($width, $height, $viewbox) = svg_getimagesize_from_attr($attrs);
if (!$srcWidth){
$largeur_img[$src] = $srcWidth = $width;
}
if (!$srcHeight){
$hauteur_img[$src] = $srcHeight = $height;
}
}
}
// $src peut etre une reference a une image temporaire dont a n'a que le log .src
// on s'y refere, l'image sera reconstruite en temps utile si necessaire
elseif (@file_exists($f = "$src.src")
@ -3443,30 +3455,126 @@ function http_style_background($img, $att = '', $size=null) {
. "'";
}
function helper_filtre_balise_img_svg_arguments($alt_or_size, $class_or_size, $size) {
$args = [$alt_or_size, $class_or_size, $size];
while (is_null(end($args)) and count($args)) {
array_pop($args);
}
if (!count($args)) {
return [null, null, null];
}
if (count($args) < 3) {
$maybe_size = array_pop($args);
// @2x
// @1.5x
// 512
// 512x*
// 512x300
if (!strlen($maybe_size)
or !preg_match(',^(@\d+(\.\d+)?x|\d+(x\*)?|\d+x\d+)$,', trim($maybe_size))) {
$args[] = $maybe_size;
$maybe_size = null;
}
while (count($args)<2) {
$args[] = null; // default alt or class
}
$args[] = $maybe_size;
}
return $args;
}
function helper_filtre_balise_img_svg_size($img, $size) {
// si size est de la forme '@2x' c'est un coeff multiplicateur sur la densite
if (strpos($size, '@') === 0 and substr($size,-1) === 'x') {
$coef = floatval(substr($size, 1, -1));
list($h, $w) = taille_image($img);
$height = intval(round($h / $coef));
$width = intval(round($w / $coef));
}
// sinon c'est une valeur seule si image caree ou largeurxhauteur
else {
$size = explode('x', $size, 2);
$size = array_map('trim', $size);
$height = $width = intval(array_shift($size));
if (count($size) and reset($size)) {
$height = array_shift($size);
if ($height === '*') {
list($h, $w) = taille_image($img);
$height = intval(round($h * $width / $w));
}
}
}
return [$width, $height];
}
/**
* Générer une balise HTML `img` à partir d'un nom de fichier
* Générer une balise HTML `img` à partir d'un nom de fichier et/ou renseigne son alt/class/width/height
* selon les arguments passés
*
* Le class et le alt peuvent etre omis et dans ce cas size peut-être renseigné comme dernier argument :
* [(#FICHIER|balise_img{@2x})]
* [(#FICHIER|balise_img{1024})]
* [(#FICHIER|balise_img{1024x*})]
* [(#FICHIER|balise_img{1024x640})]
* [(#FICHIER|balise_img{'un nuage',1024x640})]
* [(#FICHIER|balise_img{'un nuage','spip_logo',1024x640})]
* Si le alt ou la class sont ambigu et peuvent etre interpretes comme une taille, il suffit d'indiquer une taille vide pour lever l'ambiguite
* [(#FICHIER|balise_img{'@2x','',''})]
*
* @uses http_img_pack()
*
* @param string $img
* chemin vers un fichier ou balise `<img src='...' />` (generee par un filtre image par exemple)
* @param string $alt
* texte alternatif ; une valeur nulle pour explicitement ne pas avoir de balise alt sur l'image (au lieu d'un alt vide)
* @param string $class
* @param string $width
* attribut class ; null par defaut (ie si img est une balise, son attribut class sera inchange. pas de class inseree
* @param string|int $size
* taille imposee
* @2x : pour imposer une densite x2 (widht et height seront divisees par 2)
* largeur : pour une image carree
* largeurx* : pour imposer uniquement la largeur (un attribut height sera aussi ajoute, mais calcule automatiquement pour respecter le ratio initial de l'image)
* largeurxhauteur pour fixer les 2 dimensions
* @return string
* Code HTML de la balise IMG
*/
function filtre_balise_img_dist($img, $alt = "", $class = "", $width=null) {
$atts = $class ? " class='" . attribut_html($class) . "'" : '';
// ecriture courte : on donne le width en 2e arg
if (empty($width) and is_numeric($alt)) {
$width = $alt;
$alt = '';
function filtre_balise_img_dist($img, $alt = '', $class = null, $size=null) {
list($alt, $class, $size) = helper_filtre_balise_img_svg_arguments($alt, $class, $size);
$img = trim($img);
if (strpos($img, '<img') === 0) {
if (!is_null($alt)) {
$img = inserer_attribut($img, 'alt', $alt);
}
if (!is_null($class)) {
if (strlen($class)) {
$img = inserer_attribut($img, 'class', $class);
}
else {
$img = vider_attribut($img, 'class');
}
}
}
if ($width) {
$atts .= " width='{$width}'";
else {
$img = http_img_pack($img, $alt, $class ? " class='" . attribut_html($class) . "'" : '', '',
array('chemin_image' => false, 'utiliser_suffixe_size' => false));
if (is_null($alt)) {
$img = vider_attribut($img, 'alt');
}
}
return http_img_pack($img, $alt, $atts, '',
array('chemin_image' => false, 'utiliser_suffixe_size' => false));
if ($img and !is_null($size) and strlen($size = trim($size))) {
list($width, $height) = helper_filtre_balise_img_svg_size($img, $size);
$img = inserer_attribut($img, 'width', $width);
$img = inserer_attribut($img, 'height', $height);
}
return $img;
}
@ -3476,24 +3584,48 @@ function filtre_balise_img_dist($img, $alt = "", $class = "", $width=null) {
*
* pour l'inserer avec une balise <img>, utiliser le filtre |balise_img
*
* Le class et le alt peuvent etre omis et dans ce cas size peut-être renseigné comme dernier argument :
* [(#FICHIER|balise_svg{1024x640})]
* [(#FICHIER|balise_svg{'un nuage',1024x640})]
* [(#FICHIER|balise_svg{'un nuage','spip_logo',1024x640})]
* Si le alt ou la class sont ambigu et peuvent etre interpretes comme une taille, il suffit d'indiquer une taille vide pour lever l'ambiguite
* [(#FICHIER|balise_svg{'un nuage','@2x',''})]
*
* @param string $img
* chemin vers un fichier ou balise `<svg ... >... </svg>` deja preparee
* @param string $alt
* texte alternatif ; une valeur nulle pour explicitement ne pas avoir de balise alt sur l'image (au lieu d'un alt vide)
* @param string $class
* attribut class ; null par defaut (ie si img est une balise, son attribut class sera inchange. pas de class inseree
* @param string|int $size
* taille imposee
* @2x : pour imposer une densite x2 (widht et height seront divisees par 2)
* largeur : pour une image carree
* largeurx* : pour imposer uniquement la largeur (un attribut height sera aussi ajoute, mais calcule automatiquement pour respecter le ratio initial de l'image)
* largeurxhauteur pour fixer les 2 dimensions
* @return string
* Code HTML de la balise SVG
*/
function filtre_balise_svg_dist($img, $alt = "", $class = "") {
function filtre_balise_svg_dist($img, $alt = '', $class = null, $size=null) {
$img = trim($img);
$img_file = $img;
if ($p = strpos($img_file, '?')) {
$img_file = substr($img_file,0, $p);
}
if (strpos($img, '<svg') === false){
if ($p = strpos($img_file, '?')){
$img_file = substr($img_file, 0, $p);
}
if (!$img_file or !$svg = file_get_contents($img_file)) {
return '';
if (!$img_file or !$svg = file_get_contents($img_file)){
return '';
}
}
if (!preg_match(",<svg\b[^>]*>,UimsS", $svg, $match)) {
return '';
}
list($alt, $class, $size) = helper_filtre_balise_img_svg_arguments($alt, $class, $size);
$balise_svg = $match[0];
$balise_svg_source = $balise_svg;
@ -3502,9 +3634,18 @@ function filtre_balise_svg_dist($img, $alt = "", $class = "") {
// IE est toujours mon ami
$balise_svg = inserer_attribut($balise_svg, 'focusable', 'false');
if ($class) {
$balise_svg = inserer_attribut($balise_svg, 'class', $class);
// regler la classe
if (!is_null($class)) {
if (strlen($class)) {
$balise_svg = inserer_attribut($balise_svg, 'class', $class);
}
else {
$balise_svg = vider_attribut($balise_svg, 'class');
}
}
// regler le alt
if ($alt){
$balise_svg = inserer_attribut($balise_svg, 'role', 'img');
$id = "img-svg-title-" . substr(md5("$img_file:$svg:$alt"),0,4);
@ -3515,8 +3656,18 @@ function filtre_balise_svg_dist($img, $alt = "", $class = "") {
else {
$balise_svg = inserer_attribut($balise_svg, 'aria-hidden', 'true');
}
$svg = str_replace($balise_svg_source, $balise_svg, $svg);
if (!is_null($size) and strlen($size = trim($size))) {
list($width, $height) = helper_filtre_balise_img_svg_size($svg, $size);
if (!function_exists('svg_redimensionner')) {
include_spip('inc/svg');
}
$svg = svg_redimensionner($svg, $width, $height);
}
return $svg;
}

Loading…
Cancel
Save