%PDF- %PDF-
Direktori : /usr/share/cups/braille/ |
Current File : //usr/share/cups/braille/cups-braille.sh |
# # Copyright (c) 2015-2018, 2022 Samuel Thibault <samuel.thibault@ens-lyon.org> # # Licensed under Apache License v2.0. See the file "LICENSE" for more # information. # # Get an attribute from the ppd file getAttribute () { ATTRIBUTE=$1 VALUE=`grep "^\*$ATTRIBUTE:" "$PPD" | cut -d" " -f2-` VALUE=${VALUE##\"} VALUE=${VALUE%%\"} printf "DEBUG: Attribute $ATTRIBUTE is '%s'\n" "$VALUE" >&2 printf "%s" "$VALUE" } # Get an option for the document: either default ppd attribute or user-provided value getOption () { OPTION=$1 VALUE=$(getAttribute Default$OPTION) printf "DEBUG: Default $OPTION is '%s'\n" "$VALUE" >&2 if [ -n "$OPTIONS" ] then # Case of the very first option if [ -z "${OPTIONS/$OPTION=*}" ] then VALUE=${OPTIONS#$OPTION=} VALUE=${VALUE%% *} printf "DEBUG: Selected $OPTION is '%s'\n" "$VALUE" >&2 fi # Case of other options if [ -z "${OPTIONS/* $OPTION=*}" ] then VALUE=${OPTIONS##* $OPTION=} VALUE=${VALUE%% *} printf "DEBUG: Selected $OPTION is '%s'\n" "$VALUE" >&2 fi # Boolean options if [ -z "${OPTIONS/* $OPTION *}" ] then VALUE=True printf "DEBUG: Selected $OPTION is '%s'\n" "$VALUE" >&2 fi if [ -z "${OPTIONS/* no$OPTION *}" ] then VALUE=False printf "DEBUG: Selected $OPTION is '%s'\n" "$VALUE" >&2 fi fi printf "%s" "$VALUE" } # Get an option for the document and check that it is a number getOptionNumber () { OPTION=$1 VALUE=$(getOption $OPTION) VALUE=${VALUE#Custom.} case "$VALUE" in [0-9]*) ;; *) printf "ERROR: Option $OPTION must be a number, got '%s'\n" "$VALUE" >&2 exit 1 ;; esac printf "%s" "$VALUE" } # Printing options: number of copies and page ranges [ -z "$NB" ] && NB=1 PAGERANGES=$(getOption page-ranges) # # Page size # Units in 100th of mm # # TODO: better handle imageable area PAGESIZE=$(getOption PageSize) case "$PAGESIZE" in Legal) PAGEWIDTH=21590 PAGEHEIGHT=35560 ;; Letter) PAGEWIDTH=21590 PAGEHEIGHT=27940 ;; A3) PAGEWIDTH=29700 PAGEHEIGHT=42000 ;; A4) PAGEWIDTH=21000 PAGEHEIGHT=29700 ;; A4TF) PAGEWIDTH=21000 PAGEHEIGHT=30480 ;; A5) PAGEWIDTH=14850 PAGEHEIGHT=21000 ;; 110x115) PAGEWIDTH=27940 PAGEHEIGHT=29210 ;; 110x120) PAGEWIDTH=27940 PAGEHEIGHT=30480 ;; 110x170) PAGEWIDTH=27940 PAGEHEIGHT=43180 ;; 115x110) PAGEWIDTH=29210 PAGEHEIGHT=27940 ;; 120x120) PAGEWIDTH=30480 PAGEHEIGHT=30480 ;; *) printf "ERROR: Unknown page size '%s'\n" "$PAGESIZE" >&2 exit 1 ;; esac # Margins as announced by embosser HWMARGINS=$(getAttribute HWMargins) echo "DEBUG: HW margins are $HWMARGINS" >&2 HWMARGIN_LEFT="${HWMARGINS%% *}" HWMARGINS="${HWMARGINS#* }" HWMARGIN_BOTTOM="${HWMARGINS%% *}" HWMARGINS="${HWMARGINS#* }" HWMARGIN_RIGHT="${HWMARGINS%% *}" HWMARGINS="${HWMARGINS#* }" HWMARGIN_TOP="${HWMARGINS%% *}" # Convert from points (1/72 of inch) to 1/100th of mm points2mm() { # First get an integer so bash can compute # I.e. convert to 10^15th of point # Note: bash's integer computation will work until about 1000mm, that's plenty :) POINTS="$1" INT_POINTS="${POINTS%.*}" if [ "$INT_POINTS" = "$POINTS" ] then FRAC_POINTS=000000000000000 else FRAC_POINTS="${POINTS#*.}000000000000000" fi FRAC_POINTS="${FRAC_POINTS:0:15}" FRAC_POINTS="$INT_POINTS$FRAC_POINTS" # Then we can compute conversion # We round up to be safe FRAC_INCH=$((($FRAC_POINTS + 71) / 72)) FRAC_CM=$((($FRAC_INCH * 254 + 99) / 100)) HUNDRENDTH_MM=$((($FRAC_CM + 999999999999) / 1000000000000)) echo $HUNDRENDTH_MM } MARGIN_LEFT=$(points2mm "$HWMARGIN_LEFT") MARGIN_RIGHT=$(points2mm "$HWMARGIN_RIGHT") MARGIN_TOP=$(points2mm "$HWMARGIN_TOP") MARGIN_BOTTOM=$(points2mm "$HWMARGIN_BOTTOM") # Margins requested by user PAGE_LEFT=$(getOptionNumber page-left) [ "$?" = 0 ] || exit 1 PAGE_LEFT=$(points2mm $PAGE_LEFT) PAGE_RIGHT=$(getOptionNumber page-right) [ "$?" = 0 ] || exit 1 PAGE_RIGHT=$(points2mm $PAGE_RIGHT) PAGE_TOP=$(getOptionNumber page-top) [ "$?" = 0 ] || exit 1 PAGE_TOP=$(points2mm $PAGE_TOP) PAGE_BOTTOM=$(getOptionNumber page-bottom) [ "$?" = 0 ] || exit 1 PAGE_BOTTOM=$(points2mm $PAGE_BOTTOM) [ -n "$PAGE_LEFT" -a "$MARGIN_LEFT" -le "$PAGE_LEFT" ] || PAGE_LEFT=$MARGIN_LEFT [ -n "$PAGE_RIGHT" -a "$MARGIN_RIGHT" -le "$PAGE_RIGHT" ] || PAGE_RIGHT=$MARGIN_RIGHT [ -n "$PAGE_TOP" -a "$MARGIN_TOP" -le "$PAGE_TOP" ] || PAGE_TOP=$MARGIN_TOP [ -n "$PAGE_BOTTOM" -a "$MARGIN_BOTTOM" -le "$PAGE_BOTTOM" ] || PAGE_BOTTOM=$MARGIN_BOTTOM echo "DEBUG: hard margins are left $MARGIN_LEFT right $MARGIN_RIGHT top $MARGIN_TOP bottom $MARGIN_BOTTOM" >&2 echo "DEBUG: graphical margins are left $PAGE_LEFT right $PAGE_RIGHT top $PAGE_TOP bottom $PAGE_BOTTOM" >&2 # This is the hardware-printable area PRINTABLEWIDTH=$(($PAGEWIDTH - $MARGIN_LEFT - $MARGIN_RIGHT)) PRINTABLEHEIGHT=$(($PAGEHEIGHT - $MARGIN_TOP - $MARGIN_BOTTOM)) echo "DEBUG: printable area is ${PRINTABLEWIDTH}x${PRINTABLEHEIGHT}" >&2 # # Text spacing # TEXTDOTDISTANCE=$(getOptionNumber TextDotDistance) [ "$?" = 0 ] || exit 1 case "$TEXTDOTDISTANCE" in 220) TEXTCELLDISTANCE=310 ;; 250) TEXTCELLDISTANCE=350 ;; 320) TEXTCELLDISTANCE=525 ;; *) printf "ERROR: Unknown text dot distance '%s'\n" "$TEXTDOTDISTANCE" >&2 exit 1 ;; esac TEXTDOTS=$(getOptionNumber TextDots) [ "$?" = 0 ] || exit 1 LINESPACING=$(getOptionNumber LineSpacing) [ "$?" = 0 ] || exit 1 # Cell dimension, including spacing TEXTCELLWIDTH=$(( $TEXTDOTDISTANCE + $TEXTCELLDISTANCE )) TEXTCELLHEIGHT=$(( $TEXTDOTDISTANCE * ($TEXTDOTS / 2 - 1) + $LINESPACING )) # Compute number of printable cells according to page width and height PRINTABLETEXTWIDTH=$(( ($PRINTABLEWIDTH + $TEXTCELLDISTANCE) / $TEXTCELLWIDTH )) PRINTABLETEXTHEIGHT=$(( ($PRINTABLEHEIGHT + $LINESPACING) / $TEXTCELLHEIGHT )) if [ "$(getOption TopMargin)" = "" ] then # No margin TEXTWIDTH=$PRINTABLETEXTWIDTH TEXTHEIGHT=$PRINTABLETEXTHEIGHT else # Margins in cells TOPMARGIN=$(getOptionNumber TopMargin) [ "$?" = 0 ] || exit 1 BOTTOMMARGIN=$(getOptionNumber BottomMargin) [ "$?" = 0 ] || exit 1 LEFTMARGIN=$(getOptionNumber LeftMargin) [ "$?" = 0 ] || exit 1 RIGHTMARGIN=$(getOptionNumber RightMargin) [ "$?" = 0 ] || exit 1 TEXTWIDTH=$(( $PRINTABLETEXTWIDTH - $LEFTMARGIN - $RIGHTMARGIN )) TEXTHEIGHT=$(( $PRINTABLETEXTHEIGHT - $TOPMARGIN - $BOTTOMMARGIN )) fi # Filter that adds top and left margins on the fly, to be used while producing # BRF output. addmargins() { NEWPAGE="" if [ -n "$TOPMARGIN" ]; then for I in $(seq 1 $TOPMARGIN) ; do NEWPAGE="$NEWPAGE"$'\r'$'\n' done fi NEWPAGESED=${NEWPAGE//$'\n'/\\$'\n'} LEFTSPACES="" if [ -n "$LEFTMARGIN" ]; then for I in $(seq 1 $LEFTMARGIN) ; do LEFTSPACES="$LEFTSPACES " done fi echo -n "$NEWPAGE" sed -e '$s/$//' \ -e "s/^\(\?\)\([^ ]\)/\1$LEFTSPACES\2/" \ -e "s//$NEWPAGESED/" echo -n "" } # # Graphic spacing # # Compute number of printable cells according to page size GRAPHICDOTDISTANCE=$(getOptionNumber GraphicDotDistance) [ "$?" = 0 ] || exit 1 # This is the total area we will send to the embosser TOTALGRAPHICWIDTH=$(( ( ($PRINTABLEWIDTH - 160) / $GRAPHICDOTDISTANCE ) / 2 * 2 )) TOTALGRAPHICHEIGHT=$(( ( ($PRINTABLEHEIGHT - 160) / $GRAPHICDOTDISTANCE ) / 4 * 4 )) echo "DEBUG: total graphical: ${TOTALGRAPHICWIDTH}x${TOTALGRAPHICHEIGHT}" >&2 # This is how many dots we have to introduce to respect at least the software left+top margin GRAPHICHOFFSET=$(( ($PAGE_LEFT - $MARGIN_LEFT + $GRAPHICDOTDISTANCE - 1) / $GRAPHICDOTDISTANCE )) GRAPHICVOFFSET=$(( ($PAGE_TOP - $MARGIN_TOP + $GRAPHICDOTDISTANCE - 1) / $GRAPHICDOTDISTANCE )) echo "DEBUG: graphical offset: ${GRAPHICHOFFSET}x${GRAPHICVOFFSET}" >&2 # This is the resulting actual margin GRAPHICLEFTMARGIN=$(( $MARGIN_LEFT + $GRAPHICHOFFSET * $GRAPHICDOTDISTANCE )) GRAPHICTOPMARGIN=$(( $MARGIN_TOP + $GRAPHICVOFFSET * $GRAPHICDOTDISTANCE )) echo "DEBUG: rounded graphical top-left corner margin: ${GRAPHICLEFTMARGIN}x${GRAPHICTOPMARGIN}" >&2 # Then compute how many dots we can afford until reaching the software right+bottom margin GRAPHICWIDTH=$(( ( ( $PAGEWIDTH - $GRAPHICLEFTMARGIN - $PAGE_RIGHT ) - 160) / $GRAPHICDOTDISTANCE )) GRAPHICHEIGHT=$(( ( ( $PAGEHEIGHT - $GRAPHICTOPMARGIN - $PAGE_BOTTOM ) - 160) / $GRAPHICDOTDISTANCE )) echo "DEBUG: resulting graphical area: ${GRAPHICWIDTH}x${GRAPHICHEIGHT}" >&2 # # Text translation # TABLESDIR= echo "DEBUG: Liblouis table directory is $TABLESDIR" >&2 getOptionLibLouis () { OPTION=$1 VALUE=$(getOption $OPTION) # Check validity of input case "$VALUE" in [-_.0-9A-Za-z]*) ;; *) printf "ERROR: Option $OPTION must be a valid liblouis table name, got '%s'\n" "$VALUE" >&2 exit 1 ;; esac LOCALE=${LANG%@*} LOCALE=${LOCALE%.*} LANGUAGE=${LOCALE%_*} COUNTRY=${LOCALE#*_} LOUIS_LOCALE=$LANGUAGE-$COUNTRY getLibLouisTableScore () { GRADE="$1" printf "DEBUG: looking for locale '%s' and grade '%s' \n" "$LOCALE" "$GRADE" >&2 # Try to select a good table from its metadata selected= selectedscore=0 for table in "$TABLESDIR/"*.tbl "$TABLESDIR/"*.ctb "$TABLESDIR/"*.utb; do score=0 name=${table#$TABLESDIR/} if grep -q "^#+locale:$LOUIS_LOCALE$" $table; then printf "DEBUG: %s has correct locale %s\n" "$name" "$LOUIS_LOCALE" >&2 score=$((score + 15)) elif grep -q "^#+region:$LOUIS_LOCALE$" $table; then printf "DEBUG: %s has correct region %s\n" "$name" "$LOUIS_LOCALE" >&2 score=$((score + 15)) elif grep -q "^#+locale:$LANGUAGE$" $table; then printf "DEBUG: %s has correct language %s\n" "$name" "$LANGUAGE" >&2 score=$((score + 10)) elif grep -q "^#+language:$LANGUAGE$" $table; then printf "DEBUG: %s has correct language %s\n" "$name" "$LANGUAGE" >&2 score=$((score + 10)) else # Requested language is a must continue fi if [ -n "$GRADE" ]; then if grep -q "^#+grade:$GRADE$" $table || \ ( [ "$GRADE" = 0 ] && ( grep -q "^#+contraction:no" $table || grep -q "^#+type:computer" $table ) ) \ then printf "DEBUG: %s has correct grade %s\n" "$name" "$GRADE" >&2 score=$((score + 10)) else # Requested grade is a must continue fi fi # Dot numbers are not always specified in liblouis :/ if grep -q "^#+dots:$TEXTDOTS$" $table || \ ( [ "$TEXTDOTS" = 6 ] && grep -q "^#+grade:[1-3]" $table ) \ then printf "DEBUG: %s has correct dots %s\n" "$name" "$TEXTDOTS" >&2 score=$((score + 2)) fi if [ $score -gt $selectedscore ]; then printf "DEBUG: %s has better score $score\n" "$name" >&2 selected=$name selectedscore=$score fi done echo $selected } # Check presence of table case "$VALUE" in None) printf None ;; Locale) selected=$(getLibLouisTableScore '') # Try tagged tables before untagged ones if [ -n "$selected" ]; then printf "%s" "$selected" elif [ -f "$TABLESDIR/$LOCALE.tbl" ]; then printf "%s" "$LOCALE.tbl" elif [ -f "$TABLESDIR/$LANGUAGE.tbl" ]; then printf "%s" "$LANGUAGE.tbl" else printf "ERROR: Could not find $OPTION table with locale %s\n" "$LOCALE" >&2 printf None exit 1 fi ;; Locale-g[0-3]) GRADE=${VALUE#Locale-g} selected=$(getLibLouisTableScore $GRADE) if [ -n "$selected" ]; then printf "%s" "$selected" exit 0 else for i in "$TABLESDIR/$LOCALE.tbl" "$TABLESDIR/$LOCALE"*.tbl "$TABLESDIR/$LANGUAGE.tbl" "$TABLESDIR/$LANGUAGE"*.tbl do if grep -q "^#+grade:$GRADE$" "$i" then printf "%s" "${i//*\/}" exit 0 fi done fi printf "ERROR: Could not find $OPTION table with locale %s and grade %s\n" "$LOCALE" "$GRADE" >&2 printf None exit 1 ;; HyphLocale) if [ -f "$TABLESDIR/hyph_$LOCALE.dic" ]; then printf "%s" "hyph_$LOCALE.dic" elif [ -f "$TABLESDIR/hyph_$LANGUAGE.dic" ]; then printf "%s" "hyph_$LANGUAGE.dic" else printf "WARN: Could not find $OPTION hyphenation table with locale %s\n" "$LOCALE" >&2 printf None fi ;; *) [ -f "$TABLESDIR/$VALUE".utb ] && VALUE="$VALUE".utb [ -f "$TABLESDIR/$VALUE".ctb ] && VALUE="$VALUE".ctb if [ ! -f "$TABLESDIR/$VALUE" ] then printf "ERROR: Could not find $OPTION table '%s'\n" "$VALUE" >&2 exit 1 fi printf "%s" "$VALUE" ;; esac } LIBLOUIS1=$(getOptionLibLouis LibLouis) [ "$?" = 0 ] || exit 1 LIBLOUIS2=$(getOptionLibLouis LibLouis2) [ "$?" = 0 ] || exit 1 LIBLOUIS3=$(getOptionLibLouis LibLouis3) [ "$?" = 0 ] || exit 1 LIBLOUIS4=$(getOptionLibLouis LibLouis4) [ "$?" = 0 ] || exit 1 echo "DEBUG: Table1 $LIBLOUIS1" >&2 echo "DEBUG: Table2 $LIBLOUIS2" >&2 echo "DEBUG: Table3 $LIBLOUIS3" >&2 echo "DEBUG: Table4 $LIBLOUIS4" >&2 [ "$LIBLOUIS1" != None ] && LIBLOUIS_TABLES="$LIBLOUIS1" [ "$LIBLOUIS2" != None ] && LIBLOUIS_TABLES="${LIBLOUIS_TABLES:+$LIBLOUIS_TABLES,}$LIBLOUIS2" [ "$LIBLOUIS3" != None ] && LIBLOUIS_TABLES="${LIBLOUIS_TABLES:+$LIBLOUIS_TABLES,}$LIBLOUIS3" [ "$LIBLOUIS4" != None ] && LIBLOUIS_TABLES="${LIBLOUIS_TABLES:+$LIBLOUIS_TABLES,}$LIBLOUIS4" # # Checking for presence of tools # checkTool() { TOOL=$1 PACKAGE=$2 USE=$3 if ! type $TOOL > /dev/null then printf "ERROR: The $PACKAGE package is required for $USE\n" >&2 exit 1 fi }