diff options
author | Norbert Preining <norbert@preining.info> | 2023-01-24 03:02:57 +0000 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2023-01-24 03:02:57 +0000 |
commit | b06c6695162b493aeec3b594c6beb518c15c98ba (patch) | |
tree | 0c1dc3cfc73ea789d6bdc4673d776f3ef652d6d8 /macros/latex/contrib/pagelayout/scripts | |
parent | 4451a2090261307c963209bc65fea9fde4eceeea (diff) |
CTAN sync 202301240302
Diffstat (limited to 'macros/latex/contrib/pagelayout/scripts')
6 files changed, 1217 insertions, 0 deletions
diff --git a/macros/latex/contrib/pagelayout/scripts/pagelayoutapi b/macros/latex/contrib/pagelayout/scripts/pagelayoutapi new file mode 100755 index 0000000000..295beef2f4 --- /dev/null +++ b/macros/latex/contrib/pagelayout/scripts/pagelayoutapi @@ -0,0 +1,371 @@ +#!/bin/sh +# +# Copyright (c) 2022-2023 by Friedemann Bartels +# +# This file may be distributed and/or modified under the +# conditions of the LaTeX Project Public License, either +# version 1.3c of this license or (at your option) any later +# version. The latest version of this license is in: +# +# http://www.latex-project.org/lppl.txt +# +# and version 1.3c or later is part of all distributions of +# LaTeX version 2008/05/04 or later. +# + +version=1.0.3 + +_convert() { + turbo=$1 + filename=$2 + filenamecache=$3 + fileextcache=$4 + originalwidthsp=$5 + originalheightsp=$6 + originalcropleftsp=$7 + originalcroprightsp=$8 + originalcroptopsp=$9 + originalcropbottomsp=${10} + density=${11} + displaywidth=${12} + displayheight=${13} + resizethreshold=${14} + unsharp=${15} + quality="${16}" + + mkdir -p cache/"$filenamecache" + originalwidth=$( magick identify -ping -format %w "$filename" ) + originalheight=$( magick identify -ping -format %h "$filename" ) + width=$(( (10 * originalwidth * (originalwidthsp - originalcropleftsp - originalcroprightsp) / originalwidthsp + 5) / 10 )) + height=$(( (10 * originalheight * (originalheightsp - originalcroptopsp - originalcropbottomsp) / originalheightsp + 5) / 10 )) + cropleft=$(( (10 * originalwidth * originalcropleftsp / originalwidthsp + 5) / 10 )) + croptop=$(( (10 * originalheight * originalcroptopsp / originalheightsp + 5) / 10 )) + resizewidth=$(( (10 * displaywidth * 100 * density / 473628672 + 5) / 10 )) + if [ $(( resizewidth * resizethreshold / 100 )) -gt $width ]; then + resizewidth=$width + resizeheight=$height + else + resizeheight=$(( resizewidth * height / width + 1 )) + fi + + x="x" + if [ $turbo = 1 ]; then + export MAGICK_THREAD_LIMIT=1 + fi + if [ "$quality" != "" ]; then + quality="-quality $quality" + fi + if [ "$unsharp" != "" ]; then + unsharp="-unsharp $unsharp" + fi + + magick "$filename" -crop $width$x$height+$cropleft+$croptop -resize $resizewidth$x$resizeheight $unsharp $quality "cache/$filenamecache/.g$fileextcache" + mv "cache/$filenamecache/.g$fileextcache" "cache/$filenamecache/g$fileextcache" +} + +_startbatchprocess() { + success=0 + for file in cache/*; do + if [ -f "$file" ]; then + success=1 + name=$( basename "${file}" ) + mv "$file" "cache/.$name" 2> /dev/null + if [ $? -eq 0 ]; then + line=$(head -n 1 "cache/.$name") + + IFS="%" + set -- $line + IFS=" " + _convert 1 "$@" + + rm "cache/.$name" + break + fi + fi + done + + if [ $success -eq 1 ]; then + _startbatchprocess + fi +} + +getwidth() { + if command -v magick >/dev/null 2>&1; then + filename=$1 + + originalwidth=$( magick identify -ping -format %w "$filename" ) + echo $originalwidth + else + echo errormagicknotinstalled + fi +} + +optimize() { + if command -v magick >/dev/null 2>&1; then + filenamecache=$2 + fileextcache=$3 + + if [ -f cache/"$filenamecache" ]; then + mv cache/"$filenamecache" cache/."$filenamecache" 2> /dev/null + if [ $? -eq 0 ]; then + line=$(head -n 1 "cache/.$filenamecache") + + IFS="%" + set -- $line + IFS=" " + _convert 1 "$@" + + rm "cache/.$filenamecache" + else + while [ ! -f cache/"$filenamecache"/g"$fileextcache" ]; do + sleep 0.05 + done + fi + elif [ -d cache/"$filenamecache" ]; then + while [ ! -f cache/"$filenamecache"/g"$fileextcache" ]; do + sleep 0.05 + done + else + _convert 0 "$@" + fi + + echo ok + else + echo errormagicknotinstalled + fi +} + +makeshadow() { + if command -v magick >/dev/null 2>&1; then + filename=$1 + stdDeviation=$2 + opacity=$3 + fill=$4 + width=$5 + height=$6 + framewidth=$7 + frameheight=$8 + frameborder=$9 + frameradius=${10} + + [ ! -d cache ] && mkdir cache + mkdir -p cache/$filename + echo "<?xml version='1.0' encoding='UTF-8' standalone='no'?> + <svg + width='$width' + height='$height' + version='1.1' + xmlns='http://www.w3.org/2000/svg' + xmlns:svg='http://www.w3.org/2000/svg'> + <defs> + <filter + style='color-interpolation-filters:sRGB' + id='blur' + x='-4' + y='-4' + width='8' + height='8'> + <feGaussianBlur + stdDeviation='$stdDeviation' /> + </filter> + </defs> + <rect + style='filter:url(#blur);opacity:$opacity;fill:$fill' + width='$framewidth' + height='$frameheight' + x='$frameborder' + y='$frameborder' + rx='$frameradius' + ry='$frameradius' /> + </svg> + " > cache/$filename/s.svg + inkscape cache/$filename/s.svg --export-dpi=600 --export-filename cache/$filename/s.pdf + rm cache/$filename/s.svg + + echo ok + else + echo errorinkscapenotinstalled + fi +} + +import() { + if [ -d import ]; then + importdir=import + elif [ "$PAGELAYOUT_IMPORT_DIRECTORY" != "" ]; then + if [ -d "$PAGELAYOUT_IMPORT_DIRECTORY" ]; then + importdir="$PAGELAYOUT_IMPORT_DIRECTORY" + else + echo $PAGELAYOUT_IMPORT_DIRECTORY + exit + fi + else + echo errornoimportdir + exit + fi + + defaultdirectory=$( echo $1 | sed -e 's/^{//g' | sed -e 's/}{.*//g' ) + directorylist=$( echo $1 | sed -e 's/^{//g' | sed -e 's/}$//g' | sed -e 's/}{/$/g' ) + + for entry in "$importdir"/*.* + do + if [ -f "$entry" ]; then + name=$( basename "${entry}" ) + if [ "$directorylist" != "" ]; then + echo "$directorylist" | tr '$' '\n' | while read directory; do + if [ -f "$directory$name" ]; then + mv "$entry" "$directory" + fi + done + fi + if [ -f "$entry" ]; then + if [ -d "$defaultdirectory" ]; then + mv "$entry" "$defaultdirectory" + else + mv "$entry" . + fi + fi + cachename=$( echo "$name" | sed -e 's/\.[a-zA-Z]*$//g' ) + rm -rf cache/"$cachename"* + fi + done +} + +startturbo() { + file="$(echo $1 | sed -e 's/\.pdflatex$//g')" + if [ -f $file.tex ]; then + tmpdir=$( mktemp -d 2>/dev/null )/pagelayoutturbo$( date "+%Y%m%d%H%M%S" )$RANDOM + mkdir $tmpdir + + cp $file.tex $tmpdir/pagelayoutturbobatchoptimizexyz.tex + + command=$(echo $(ps -p $PPID -o command )) + engine=$(echo $command | sed -e 's/^[A-Z ]*//g' | sed -e 's/ .*//g' | tr -d '\n') + + case "$command" in + *-shell-escape*) + shellescape="--shell-escape" + ;; + esac + + if [ "$engine" = "xelatex" ]; then + nopdf="-no-pdf" + fi + + $engine $shellescape -interaction=batchmode $nopdf --output-directory $tmpdir $tmpdir/pagelayoutturbobatchoptimizexyz.tex > /dev/null + + rm -rf $tmpdir + fi +} + +batchoptimize() { + [ ! -d cache ] && mkdir cache + + length=$(( $# / 15 )) + cores=$( nproc ) + [ $cores -gt $length ] && cores=$length + + while [ $length -gt 0 ]; do + filenamecache="$2" + + if [ ! -e cache/"$filenamecache" ]; then + index=0 + while [ $index -lt 15 ]; do + if [ $index -eq 0 ]; then + item="$1" + else + item="$item%$1" + fi + + shift + index=$(( index + 1 )) + done + + echo $item > cache/"$filenamecache" + else + shift 15 + fi + + length=$(( length - 1 )) + done + + cores=$(( cores - 1 )) + while [ $cores -gt 0 ]; do + _startbatchprocess & + sleep 0.01 + cores=$(( cores - 1 )) + done +} + +usage() { + cat <<HELP_USAGE +usage: pagelayoutapi getwidth % FILE + pagelayoutapi optimize % FILE % FILENAME % EXTENSION % ORIGINALWIDTH + % ORIGINALHEIGHT % CROPLEFT % CROPRIGHT % CROPTOP % CROPBOTTOM + % DENSITY % WIDTH % HEIGHT % DOWNSAMPLETHRESHOLD % UNSHARP % QUALITY + pagelayoutapi makeshadow % FILENAME % STANDARDDEVIATION % OPACITY % COLOR + % WIDTH % HEIGHT % FRAMEWIDTH % FRAMEHEIGHT % MARGIN % BORDERRADIUS + pagelayoutapi start [% import % [GRAPHICSPATH]] [% turbo % JOBNAME] + pagelayoutapi batchoptimize % BATCHLIST + + --help Prints a help message. + --version Prints version information. +HELP_USAGE +} + +version() { + echo pagelayoutapi $version +} + +input=$( echo "$@" | sed -e 's/\\//g' | sed -e 's/ %/%/g' | sed -e 's/% /%/g' ) +IFS="%" +set -- $input +IFS=" " + +case "$1" in +getwidth) + shift + + getwidth "$1" + ;; +optimize) + shift + + optimize "$@" + ;; +makeshadow) + shift + + makeshadow "$@" + ;; +start) + shift + + if [ "$1" = "import" ]; then + shift + + import "$1" + + shift + fi + + if [ "$1" = "turbo" ]; then + shift + + startturbo "$1" & + fi + + echo ok + ;; +batchoptimize) + shift + + batchoptimize "$@" & + + echo ok + ;; +--version) + version + ;; +--help) + usage +esac diff --git a/macros/latex/contrib/pagelayout/scripts/pagelayoutapi.1 b/macros/latex/contrib/pagelayout/scripts/pagelayoutapi.1 new file mode 100644 index 0000000000..368e411ef7 --- /dev/null +++ b/macros/latex/contrib/pagelayout/scripts/pagelayoutapi.1 @@ -0,0 +1,125 @@ +.\" generated with Ronn/v0.7.3 +.\" http://github.com/rtomayko/ronn/tree/0.7.3 +. +.TH "PAGELAYOUTAPI" "1" "January 2023" "" "" +. +.SH "NAME" +\fBpagelayoutapi\fR \- API for the pagelayout LaTeX class +. +.SH "SYNOPSIS" +\fBpagelayoutapi getwidth\fR % FILE +. +.P +\fBpagelayoutapi optimize\fR % FILE % FILENAME % EXTENSION % ORIGINALWIDTH % ORIGINALHEIGHT % CROPLEFT % CROPRIGHT % CROPTOP % CROPBOTTOM % DENSITY % WIDTH % HEIGHT % DOWNSAMPLETHRESHOLD % UNSHARP % QUALITY +. +.P +\fBpagelayoutapi makeshadow\fR % FILENAME % STANDARDDEVIATION % OPACITY % COLOR % WIDTH % HEIGHT % FRAMEWIDTH % FRAMEHEIGHT % MARGIN % BORDERRADIUS +. +.P +\fBpagelayoutapi start\fR [% import % [GRAPHICSPATH]] [% turbo % JOBNAME] +. +.P +\fBpagelayoutapi batchoptimize\fR % BATCHLIST +. +.SH "DESCRIPTION" +This script provides an API for the pagelayout LaTeX class\. +. +.TP +\fBpagelayoutapi getwidth\fR +Returns the width in pixels for the given image file\. +. +.TP +\fBpagelayoutapi optimize\fR +Creates a cropped, rezised, sharpend and compressed image and stores it in the cache directory\. +. +.TP +\fBpagelayoutapi makeshadow\fR +Creates a shadow image and stores it in the cache directory\. +. +.TP +\fBpagelayoutapi start\fR +The import parameter triggers the image import (see pagelayout\-manual\.pdf chapter "Image Optimization")\. Running the command with the parameter turbo, where the jobname is the filename of the document, processes the document in a special batch mode, that creates a batch list and calls the command \fBpagelayoutapi batchoptimize\fR\. +. +.TP +\fBpagelayoutapi batchoptimize\fR +Optimizes multiple images in parallel\. +. +.SH "OPTIONS" +. +.TP +\fB\-\-help\fR +Prints a help message\. +. +.TP +\fB\-\-version\fR +Prints version information\. +. +.SH "PARAMETERS" +. +.TP +FILE +filename with extension (eg\. IMG1234\.JPEG) +. +.TP +FILENAME +filename without extension (eg\. IMG1234) +. +.TP +EXTENSION +optimized file extension (\.jpg|\.png) +. +.TP +DENSITY +density in ppi (eg\. 72) +. +.TP +DOWNSAMPLETHRESHOLD +downsample threshold (integer >= 100) +. +.TP +UNSHARP +unsharp filter (eg\. 2x1) +. +.TP +QUALITY +quality (integer > 0, <= 100) +. +.TP +STANDARDDEVIATION +standard deviation (decimal > 0\.0) +. +.TP +OPACITY +opacity (decimal >= 0\.0, <= 1\.0) +. +.TP +COLOR +color string (eg\. pink) +. +.TP +GRAPHICSPATH +list of directories (eg\. {images/}{tmp/}) +. +.TP +JOBNAME +LaTeX filename without extension (eg\. my\-document) +. +.TP +BATCHLIST +a flat list of batch items where each batch item is a flat list of the 15 parameters required by the command `pagelayoutapi optimize` +. +.P +All other parameters are length dimensions\. The command \fBpagelayoutapi optimize\fR expects integer values in the LaTeX unit sp (eg\. 65536)\. The command \fBpagelayoutapi makeshadow\fR expects decimal values in a SVG compatible unit (eg\. 420\.0pt)\. +. +.SH "ENVIRONMENT" +\fBpagelayoutapi\fR requires ImageMagick 7\.0 or later and Inkscape 1\.0 or later\. +. +.TP +\fBPAGELAYOUT_IMPORT_DIRECTORY\fR +Defines a system wide import directory\. +. +.SH "AUTHOR" +\fBpagelayoutapi\fR was written by Friedemann Bartels\. \fIhttps://github\.com/friedemannbartels\fR +. +.SH "LICENSE" +Copyright (c) 2022-2023 Friedemann Bartels\. Free use of this software is granted under the terms of the LaTeX Project Public License version 1\.3c or later\. diff --git a/macros/latex/contrib/pagelayout/scripts/pagelayoutapi.1.md b/macros/latex/contrib/pagelayout/scripts/pagelayoutapi.1.md new file mode 100644 index 0000000000..ab04ddd0b8 --- /dev/null +++ b/macros/latex/contrib/pagelayout/scripts/pagelayoutapi.1.md @@ -0,0 +1,87 @@ +pagelayoutapi(1) -- API for the pagelayout LaTeX class +==== + +## SYNOPSIS + +`pagelayoutapi getwidth` % FILE + +`pagelayoutapi optimize` % FILE % FILENAME % EXTENSION % ORIGINALWIDTH % ORIGINALHEIGHT % CROPLEFT % CROPRIGHT % CROPTOP % CROPBOTTOM % DENSITY % WIDTH % HEIGHT % DOWNSAMPLETHRESHOLD % UNSHARP % QUALITY + +`pagelayoutapi makeshadow` % FILENAME % STANDARDDEVIATION % OPACITY % COLOR % WIDTH % HEIGHT % FRAMEWIDTH % FRAMEHEIGHT % MARGIN % BORDERRADIUS + +`pagelayoutapi start` [% import % [GRAPHICSPATH]] [% turbo % JOBNAME] + +`pagelayoutapi batchoptimize` % BATCHLIST + +## DESCRIPTION + +This script provides an API for the pagelayout LaTeX class. + +* `pagelayoutapi getwidth`: + Returns the width in pixels for the given image file. + +* `pagelayoutapi optimize`: + Creates a cropped, rezised, sharpend and compressed image and stores it in the cache directory. + +* `pagelayoutapi makeshadow`: + Creates a shadow image and stores it in the cache directory. + +* `pagelayoutapi start`: + The import parameter triggers the image import (see pagelayout-manual.pdf chapter "Image Optimization"). + Running the command with the parameter turbo, where the jobname is the filename of the document, processes the document in a special batch mode, that creates a batch list and calls the command `pagelayoutapi batchoptimize`. + +* `pagelayoutapi batchoptimize`: + Optimizes multiple images in parallel. + +## OPTIONS + +* `--help`: + Prints a help message. +* `--version`: + Prints version information. + +## PARAMETERS + +* FILE: + filename with extension (eg. IMG1234.JPEG) +* FILENAME: + filename without extension (eg. IMG1234) +* EXTENSION: + optimized file extension (.jpg|.png) +* DENSITY: + density in ppi (eg. 72) +* DOWNSAMPLETHRESHOLD: + downsample threshold (integer >= 100) +* UNSHARP: + unsharp filter (eg. 2x1) +* QUALITY: + quality (integer > 0, <= 100) +* STANDARDDEVIATION: + standard deviation (decimal > 0.0) +* OPACITY: + opacity (decimal >= 0.0, <= 1.0) +* COLOR: + color string (eg. pink) +* GRAPHICSPATH: + list of directories (eg. {images/}{tmp/}) +* JOBNAME: + LaTeX filename without extension (eg. my-document) +* BATCHLIST: + a flat list of batch items where each batch item is a flat list of the 15 parameters required by the command \`pagelayoutapi optimize\` + +All other parameters are length dimensions. The command `pagelayoutapi optimize` expects integer values in the LaTeX unit sp (eg. 65536). The command `pagelayoutapi makeshadow` expects decimal values in a SVG compatible unit (eg. 420.0pt). + +## ENVIRONMENT + +`pagelayoutapi` requires ImageMagick 7.0 or later and Inkscape 1.0 or later. + +* `PAGELAYOUT_IMPORT_DIRECTORY`: + Defines a system wide import directory. + +## AUTHOR + +`pagelayoutapi` was written by Friedemann Bartels. <https://github.com/friedemannbartels> + +## LICENSE + +Copyright (c) 2022-2023 Friedemann Bartels. Free use of this software is granted under the terms of the LaTeX Project Public License version 1.3c or later. diff --git a/macros/latex/contrib/pagelayout/scripts/textestvis b/macros/latex/contrib/pagelayout/scripts/textestvis new file mode 100755 index 0000000000..36b3ff6cfb --- /dev/null +++ b/macros/latex/contrib/pagelayout/scripts/textestvis @@ -0,0 +1,506 @@ +#!/bin/sh +# +# Copyright (c) 2022-2023 by Friedemann Bartels +# +# This file may be distributed and/or modified under the +# conditions of the LaTeX Project Public License, either +# version 1.3c of this license or (at your option) any later +# version. The latest version of this license is in: +# +# http://www.latex-project.org/lppl.txt +# +# and version 1.3c or later is part of all distributions of +# LaTeX version 2008/05/04 or later. +# + +version=1.0.3 + +OK="$( tput setaf 2 )•$( tput sgr0 )" +FAILED="$( tput setaf 1 )$( tput bold )x$( tput sgr0 )" +NEW="$( tput setaf 3 )$( tput bold )+$( tput sgr0 )" +REMOVED="$( tput setaf 5 )$( tput bold )-$( tput sgr0 )" +ERROR="$( tput setaf 1 )$( tput bold )!$( tput sgr0 )" + +_playok() { + if [ -f /System/Library/Sounds/Glass.aiff ]; then + afplay /System/Library/Sounds/Glass.aiff >/dev/null 2>&1 + fi +} + +_playhm() { + if [ -f /System/Library/Sounds/Basso.aiff ]; then + afplay /System/Library/Sounds/Basso.aiff >/dev/null 2>&1 + fi +} + +_playerror() { + if [ -f /System/Library/Sounds/Sosumi.aiff ]; then + afplay /System/Library/Sounds/Sosumi.aiff >/dev/null 2>&1 + fi +} + +_gettime() { + if command -v gdate &> /dev/null; then + echo $( gdate +%s%3N ) + else + if command -v date &> /dev/null; then + milliseconds=$( date +%3N ) + if [ $milliseconds = 3N ]; then + echo $(( SECONDS * 1000 )) + else + echo $( date +%s%3N ) + fi + else + echo $(( SECONDS * 1000 )) + fi + fi +} + +_starttimer() { + starttime=$( _gettime ) +} + +_stoptimer() { + endtime=$( _gettime ) + + elapsedtime=$(( endtime - starttime )) + elapsedseconds=$(( elapsedtime / 1000 )) + elapsedmilliseconds=$(( elapsedtime % 1000 )) + elapsed=$elapsedseconds.$( printf "%03d" "$elapsedmilliseconds" ) +} + +test() { + _starttimer + tmpdir=$( mktemp -d 2>/dev/null )/textest$( date "+%Y%m%d%H%M%S" )$RANDOM + mkdir $tmpdir + + if [ $3 = true ] && [ -d cache ]; then + rm -rf cache + fi + + okcount=0 + failedcount=0 + newcount=0 + removedcount=0 + fileokcount=0 + filefailedcount=0 + defaultfiller=23 + + echo "" + for entry in *$5*.tex + do + if [ $entry != "*$5*.tex" ]; then + name=$( echo $entry | sed -e 's/\.tex$//g' ) + if [ ${name:0:1} != _ ]; then + printf "$( tput sgr0 )$name" + + runtwice=0 + if [ "${name:$(( ${#name} - 2 )):2}" = "@2" ]; then + runtwice=1 + fi + + if [ "$4" != "xelatex" ]; then + name="$name.$4" + fi + + passed=1 + rm -f $name.failed.* + + cp $entry $tmpdir/$name.tex + shell="" + if [ $1 = true ]; then + shell="--shell-escape" + fi + $4 -interaction=batchmode $shell --output-directory $tmpdir $tmpdir/$name.tex > /dev/null + if [ $? -eq 1 ]; then + passed=0 + fi + if [ $runtwice -eq 1 ]; then + $4 -interaction=batchmode $shell --output-directory $tmpdir $tmpdir/$name.tex > /dev/null + if [ $? -eq 1 ]; then + passed=0 + fi + fi + + magick convert -density $2 -quiet $tmpdir/$name.pdf $tmpdir/$name.png + if [ -f "$tmpdir/$name.png" ]; then + mv $tmpdir/$name.png $tmpdir/$name-0.png + fi + + if [ -f "$name.approved.pdf" ]; then + magick convert -density $2 -quiet $name.approved.pdf $tmpdir/$name.approved.png + if [ -f "$tmpdir/$name.approved.png" ]; then + mv $tmpdir/$name.approved.png $tmpdir/$name.approved-0.png + fi + fi + + if [ $passed -eq 0 ]; then + filler=$(( defaultfiller - ${#name} - 2 )) + else + filler=$(( defaultfiller - ${#name} )) + fi + while [ 0 -le $filler ]; do + printf " " + filler=$(( filler - 1 )) + done + if [ $passed -eq 0 ]; then + printf " $ERROR" + fi + + index=0 + while [ -f "$tmpdir/$name-$index.png" ]; do + if [ -f "$tmpdir/$name.approved-$index.png" ]; then + changedpixels=$( magick compare -quiet -metric AE $tmpdir/$name-$index.png $tmpdir/$name.approved-$index.png null: 2>&1 ) + if [ $changedpixels -eq 0 ]; then + okcount=$(( okcount + 1 )) + printf " $OK" + else + failedcount=$(( failedcount + 1 )) + passed=0 + printf " $FAILED" + magick compare -quiet $tmpdir/$name-$index.png $tmpdir/$name.approved-$index.png $name.failed.$(( index + 1 )).png + if [ -f "$tmpdir/$name.pdf" ]; then + mv $tmpdir/$name.pdf $name.failed.pdf + fi + fi + else + newcount=$(( newcount + 1 )) + passed=0 + printf " $NEW" + mv $tmpdir/$name-$index.png $name.failed.$(( index + 1 )).png + if [ -f "$tmpdir/$name.pdf" ]; then + mv $tmpdir/$name.pdf $name.failed.pdf + fi + fi + index=$(( index + 1 )) + if [ `expr $index % 20` -eq 0 ] && [ -f "$tmpdir/$name-$index.png" ]; then + echo "" + filler=$defaultfiller + while [ 0 -le $filler ]; do + printf " " + filler=$(( filler - 1 )) + done + fi + done + while [ -f "$tmpdir/$name.approved-$index.png" ]; do + removedcount=$(( removedcount + 1 )) + passed=0 + printf " $REMOVED" + mv $tmpdir/$name.approved-$index.png $name.failed.$(( index + 1 )).png + if [ -f "$tmpdir/$name.pdf" ]; then + mv $tmpdir/$name.pdf $name.failed.pdf + fi + index=$(( index + 1 )) + if [ `expr $index % 20` -eq 0 ] && [ -f "$tmpdir/$name.approved-$index.png" ]; then + echo "" + filler=$defaultfiller + while [ 0 -le $filler ]; do + printf " " + filler=$(( filler - 1 )) + done + fi + done + + if [ $passed -eq 1 ]; then + fileokcount=$(( fileokcount + 1 )) + else + filefailedcount=$(( filefailedcount + 1 )) + fi + + echo "" + fi + fi + done + + rm -rf $tmpdir + _stoptimer + seconds=$( printf "%.1f" "$elapsed" ) + + filecount=$(( fileokcount + filefailedcount )) + + if [ $filecount -gt 0 ]; then + echo "" + fi + if [ $filecount -eq $fileokcount ]; then + if [ $filecount -eq 0 ]; then + _playhm & + echo "$( tput sgr0 )Tested 0 files 🧐." + else + _playok & + echo "$( tput sgr0 )Successfully tested $filecount files in $seconds seconds 🎉." + fi + echo "" + else + _playerror & + echo "$( tput sgr0 )Tested $filecount files in $seconds seconds." + echo "" + + if [ $fileokcount -gt 0 ]; then + filler=$(( 6 + ${#filecount} - ${#fileokcount} )) + while [ 0 -le $filler ]; do + printf " " + filler=$(( filler - 1 )) + done + printf "$( tput setaf 2 )$fileokcount OK$( tput sgr0 )" + echo "" + fi + if [ $filefailedcount -gt 0 ]; then + filler=$(( 6 + ${#filecount} - ${#filefailedcount} )) + while [ 0 -le $filler ]; do + printf " " + filler=$(( filler - 1 )) + done + printf "$( tput setaf 1 )$filefailedcount Failed$( tput sgr0 )" + echo "" + fi + echo "" + exit 1 + fi +} + +approve() { + filecount=0 + + suffix="" + if [ "$1" != "xelatex" ]; then + suffix=".$1" + fi + + echo "" + for entry in *$2*$suffix.failed.pdf + do + if [ $entry != "*$2*$suffix.failed.pdf" ]; then + filecount=$(( filecount + 1 )) + name=$( echo $entry | sed -e "s/$suffix.failed.pdf//" ) + echo $name + rm -f $name$suffix.approved.pdf + if [ -f "$name.aux" ]; then + cp $name$suffix.failed.pdf $name$suffix.approved.pdf + else + mv $name$suffix.failed.pdf $name$suffix.approved.pdf + fi + + rm -f $name$suffix.failed.* + fi + done + + if [ $filecount -gt 0 ]; then + echo "" + fi + if [ $filecount -eq 1 ]; then + echo "Approved 1 file." + else + echo "Approved $filecount files." + fi + echo "" +} + +compare() { + filea=$2 + fileb=$3 + tmpdir=$( mktemp -d 2>/dev/null)/textest$( date "+%Y%m%d%H%M%S" )$RANDOM + mkdir $tmpdir + + namea=$( echo $filea | sed -e 's/\.\///g' | sed -e 's/\.pdf$//g' ) + nameb=$( echo $fileb | sed -e 's/\.\///g' | sed -e 's/\.pdf$//g' ) + basenamea=$(basename $namea) + basenameb=$(basename $nameb) + + rm -f $namea.diff.*.png + + spacer="" + if [ -f "$filea" ]; then + if [ -f "$fileb" ]; then + magick convert -density $1 -quiet $filea $tmpdir/$basenamea.png + if [ -f "$tmpdir/$basenamea.png" ]; then + mv $tmpdir/$basenamea.png $tmpdir/$basenamea-0.png + fi + magick convert -density $1 -quiet $fileb $tmpdir/$basenameb.png + if [ -f "$tmpdir/$basenameb.png" ]; then + mv $tmpdir/$basenameb.png $tmpdir/$basenameb-0.png + fi + + index=0 + while [ -f "$tmpdir/$basenamea-$index.png" ]; do + if [ -f "$tmpdir/$basenameb-$index.png" ]; then + changedpixels=$( magick compare -quiet -metric AE $tmpdir/$basenamea-$index.png $tmpdir/$basenameb-$index.png null: 2>&1 ) + if [ $changedpixels -eq 0 ]; then + printf "$spacer$OK" + spacer=" " + else + printf "$spacer$FAILED" + spacer=" " + magick compare -quiet $tmpdir/$basenamea-$index.png $tmpdir/$basenameb-$index.png $namea.diff.$(( index + 1 )).png + fi + else + printf "$spacer$NEW" + spacer=" " + fi + index=$(( index + 1 )) + done + while [ -f "$tmpdir/$basenameb-$index.png" ]; do + printf "$spacer$REMOVED" + spacer=" " + index=$(( index + 1 )) + done + echo "" + else + echo "File $fileb not found." + fi + else + echo "File $filea not found." + fi + + rm -rf $tmpdir +} + +perf() { + if [ -f $4 ]; then + tmpdir=$( mktemp -d 2>/dev/null )/textestperf$( date "+%Y%m%d%H%M%S" )$RANDOM + mkdir $tmpdir + basename=$(basename $4) + + if [ $1 = true ] && [ -d cache ]; then + rm -rf cache + fi + + cp $4 $tmpdir + shell="" + if [ $2 = true ]; then + shell="--shell-escape" + fi + _starttimer + $3 -interaction=batchmode $shell --output-directory $tmpdir $tmpdir/$basename > /dev/null + _stoptimer + echo "$elapsed" + + rm -rf $tmpdir + else + echo "File $4 not found." + fi +} + +usage() { + cat <<HELP_USAGE +usage: textest [-cs] [-e ENGINE] [-d DENSITY] [PATTERN] + textest approve [-e ENGINE] [PATTERN] + textest compare [-d DENSITY] FILE FILE + textest perf [-cs] [-e ENGINE] FILE + + -c Clears cache. + -s Enables shell escape. + -d DENSITY Sets density in ppi (default 72). + -e ENGINE Sets latex engine (default xelatex). + --help Prints a help message. + --version Prints version information. +HELP_USAGE +} + +version() { + echo textest $version +} + +case "$1" in +approve) + shift + engine=xelatex + + while getopts ":e:" arg; do + case "${arg}" in + e) + engine="${OPTARG}" + ;; + ?) + echo "Invalid option: -${OPTARG}." + ;; + esac + done + + shift "$(( OPTIND - 1 ))" + + approve $engine $1 + ;; +compare) + shift + + density=72 + + while getopts ":d:" arg; do + case "${arg}" in + d) + density="${OPTARG}" + ;; + ?) + echo "Invalid option: -${OPTARG}." + ;; + esac + done + + shift "$(( OPTIND - 1 ))" + + compare $density $1 $2 + ;; +perf) + shift + + shell=false + clear=false + engine=xelatex + + while getopts ":e:sc" arg; do + case "${arg}" in + c) + clear=true + ;; + e) + engine="${OPTARG}" + ;; + s) + shell=true + ;; + ?) + echo "Invalid option: -${OPTARG}." + ;; + esac + done + + shift "$(( OPTIND - 1 ))" + + perf $clear $shell $engine $1 + ;; +--version) + version + ;; +--help) + usage + ;; +*) + density=72 + shell=false + clear=false + engine=xelatex + + while getopts ":e:d:sc" arg; do + case "${arg}" in + c) + clear=true + ;; + d) + density="${OPTARG}" + ;; + e) + engine="${OPTARG}" + ;; + s) + shell=true + ;; + ?) + echo "Invalid option: -${OPTARG}." + ;; + esac + done + + shift "$(( OPTIND - 1 ))" + + test $shell $density $clear $engine $1 +esac diff --git a/macros/latex/contrib/pagelayout/scripts/textestvis.1 b/macros/latex/contrib/pagelayout/scripts/textestvis.1 new file mode 100644 index 0000000000..7f7b7df740 --- /dev/null +++ b/macros/latex/contrib/pagelayout/scripts/textestvis.1 @@ -0,0 +1,73 @@ +.\" generated with Ronn/v0.7.3 +.\" http://github.com/rtomayko/ronn/tree/0.7.3 +. +.TH "TEXTESTVIS" "1" "January 2023" "" "" +. +.SH "NAME" +\fBtextestvis\fR \- visual regression tests for LaTeX +. +.SH "SYNOPSIS" +\fBtextestvis\fR [\-cs] [\-e ENGINE] [\-d DENSITY] [PATTERN] +. +.P +\fBtextestvis approve\fR [\-e ENGINE] [PATTERN] +. +.P +\fBtextestvis compare\fR [\-d DENSITY] FILE FILE +. +.P +\fBtextestvis perf\fR [\-cs] [\-e ENGINE] FILE +. +.SH "DESCRIPTION" +Perform visual regression tests for LaTeX documents\. +. +.TP +\fBtextestvis\fR +Creates PDF files for all tex files matching the pattern and performs a visual regression test\. If no pattern is specified, all files in the current directory are tested except for files whose names begin with an underscore\. +. +.TP +\fBtextestvis approve\fR +Replaces the reference files with the test files\. +. +.TP +\fBtextestvis compare\fR +Creates a visual diff for two pdf files\. +. +.TP +\fBtextestvis perf\fR +Measures the time for creating a pdf file from the given tex file\. +. +.SH "OPTIONS" +. +.TP +\fB\-c\fR +Clears cache\. +. +.TP +\fB\-s\fR +Enables shell escape\. +. +.TP +\fB\-d\fR \fIDENSITY\fR +Sets density in ppi (default 72)\. +. +.TP +\fB\-e\fR \fIENGINE\fR +Sets latex engine (default xelatex)\. +. +.TP +\fB\-\-help\fR +Prints a help message\. +. +.TP +\fB\-\-version\fR +Prints version information\. +. +.SH "ENVIRONMENT" +\fBtextestvis\fR requires ImageMagick 7\.0 or later\. +. +.SH "AUTHOR" +\fBtextestvis\fR was written by Friedemann Bartels\. \fIhttps://github\.com/friedemannbartels\fR +. +.SH "LICENSE" +Copyright (c) 2022-2023 Friedemann Bartels\. Free use of this software is granted under the terms of the LaTeX Project Public License version 1\.3c or later\. diff --git a/macros/latex/contrib/pagelayout/scripts/textestvis.1.md b/macros/latex/contrib/pagelayout/scripts/textestvis.1.md new file mode 100644 index 0000000000..00b475d935 --- /dev/null +++ b/macros/latex/contrib/pagelayout/scripts/textestvis.1.md @@ -0,0 +1,55 @@ +textestvis(1) -- visual regression tests for LaTeX +==== + +## SYNOPSIS + +`textestvis` [-cs] [-e ENGINE] [-d DENSITY] [PATTERN] + +`textestvis approve` [-e ENGINE] [PATTERN] + +`textestvis compare` [-d DENSITY] FILE FILE + +`textestvis perf` [-cs] [-e ENGINE] FILE + +## DESCRIPTION + +Perform visual regression tests for LaTeX documents. + +* `textestvis`: + Creates PDF files for all tex files matching the pattern and performs a visual regression test. If no pattern is specified, all files in the current directory are tested except for files whose names begin with an underscore. + +* `textestvis approve`: + Replaces the reference files with the test files. + +* `textestvis compare`: + Creates a visual diff for two pdf files. + +* `textestvis perf`: + Measures the time for creating a pdf file from the given tex file. + +## OPTIONS + +* `-c`: + Clears cache. +* `-s`: + Enables shell escape. +* `-d` <DENSITY>: + Sets density in ppi (default 72). +* `-e` <ENGINE>: + Sets latex engine (default xelatex). +* `--help`: + Prints a help message. +* `--version`: + Prints version information. + +## ENVIRONMENT + +`textestvis` requires ImageMagick 7.0 or later. + +## AUTHOR + +`textestvis` was written by Friedemann Bartels. <https://github.com/friedemannbartels> + +## LICENSE + +Copyright (c) 2022-2023 Friedemann Bartels. Free use of this software is granted under the terms of the LaTeX Project Public License version 1.3c or later. |