build-cursors 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. #! /bin/bash
  2. #
  3. # bin/build-cursors
  4. # Part of ComixCursors, a desktop cursor theme.
  5. #
  6. # Copyright © 2010–2013 Ben Finney <ben+opendesktop@benfinney.id.au>
  7. # Copyright © 2006–2013 Jens Luetkens <j.luetkens@limitland.de>
  8. #
  9. # This work is free software: you can redistribute it and/or modify it
  10. # under the terms of the GNU General Public License as published by
  11. # the Free Software Foundation, either version 3 of the License, or
  12. # (at your option) any later version.
  13. #
  14. # This work is distributed in the hope that it will be useful, but
  15. # WITHOUT ANY WARRANTY; without even the implied warranty of
  16. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. # General Public License for more details.
  18. #
  19. # You should have received a copy of the GNU General Public License
  20. # along with this work. If not, see <http://www.gnu.org/licenses/>.
  21. # Create the cursor image files from SVG source.
  22. THEMENAME="${THEMENAME:-Custom}"
  23. export THEMENAME
  24. ORIENTATION="${ORIENTATION:-RightHanded}"
  25. export ORIENTATION
  26. bindir="$(dirname $0)"
  27. themename_stem="ComixCursors"
  28. configfile_dir="${themename_stem}Configs"
  29. configfile="${configfile_dir}/${THEMENAME}.CONFIG"
  30. theme_template="${configfile_dir}/${themename_stem}.theme"
  31. # source the theme config file
  32. source "${configfile}"
  33. if [ ${THEMEINCLUDE} ] ; then
  34. source "${configfile_dir}/${THEMEINCLUDE#-}.INCLUDE"
  35. fi
  36. SHADOWOPAQ=$(echo "1 - $SHADOWTRANS" | bc | sed 's/^\./0\./' | sed 's/\.0$//')
  37. CURSOROPAQ=$(echo "1 - $CURSORTRANS" | bc | sed 's/^\./0\./' | sed 's/\.0$//')
  38. function svg_substitutions {
  39. # Process an SVG file with custom substitutions.
  40. local infile="$1"
  41. substitutions=(
  42. "s/#000000/$OUTLINECOLOR/g"
  43. "s/stroke-width:20/stroke-width:$OUTLINE/g"
  44. "s/#999999/$CURSORCOLORHI/g"
  45. "s/#555555/$CURSORCOLORLO/g"
  46. "s/#999933/$HILIGHTHI/g"
  47. "s/#666600/$HILIGHTLO/g"
  48. "s/#010101/$HAIR/g"
  49. "s/#111111/$SHADOWCOLOR/g"
  50. "s/opacity:0.15/opacity:$SHADOWOPAQ/g"
  51. "s/opacity:0.75/opacity:$CURSOROPAQ/g"
  52. )
  53. sed $(for subst in "${substitutions[@]}" ; do printf " -e ${subst}" ; done) \
  54. "$infile"
  55. }
  56. function svg_rotate {
  57. # Apply rotation angle.
  58. local infile="$1"
  59. local angle="$2"
  60. sed \
  61. -e "s/rotate(0,/rotate($angle,/" \
  62. "$infile"
  63. }
  64. svgdir="svg"
  65. indir="${svgdir}/${ORIENTATION}"
  66. workdir="tmp"
  67. builddir="build"
  68. xcursor_builddir="cursors"
  69. export workdir builddir
  70. mkdir --parents "${builddir}"
  71. mkdir --parents "${workdir}"
  72. mkdir --parents "${xcursor_builddir}"
  73. # Copy the HOTSPOTS file to the working directory.
  74. hotspots_file="${indir}/HOTSPOTS"
  75. cp "$hotspots_file" "$workdir"/.
  76. function generate_theme {
  77. # Process the theme file.
  78. local name="$1"
  79. local sizename="${SIZENAME//-/ }"
  80. xcursor_theme="${builddir}/${name}.theme"
  81. custom_theme="ComixCursorsConfigs/${name}.theme"
  82. themename=${name//-/ }
  83. if [[ $ORIENTATION == "LeftHanded" ]] ; then
  84. facing=" left-handed"
  85. else
  86. facing=""
  87. fi
  88. variation=" ${THEMEINCLUDE#-}" && [ -v ${THEMEINCLUDE} ] && variation=""
  89. variation=${variation//-/ }
  90. if [ -f "$custom_theme" ] ; then
  91. sed "s/THEMENAME/$themename/g" "$custom_theme" | sed "s/ORIENTATION/$facing/g" | sed "s/SIZENAME/$sizename/g" | sed "s/VARIATION/$variation/g" > "$xcursor_theme"
  92. elif [ -f "$theme_template" ] ; then
  93. sed "s/THEMENAME/$themename/g" "$theme_template" | sed "s/ORIENTATION/$facing/g" | sed "s/SIZENAME/$sizename/g" | sed "s/VARIATION/$variation/g" > "$xcursor_theme"
  94. fi
  95. }
  96. function generate_animation_source_frames {
  97. # Generate the source frame images for an animation.
  98. local name="$1"
  99. local frames_count=$2
  100. first_frame_file="${indir}/${name}.svg"
  101. for frame in $(seq --equal-width 1 $frames_count) ; do
  102. frame_file="${indir}/${name}.frame${frame}.svg"
  103. case $frame in
  104. 1)
  105. cp "$first_frame_file" "$frame_file"
  106. ;;
  107. *)
  108. angle=$(echo "360 / $frames_count * ($frame - 1)" | bc)
  109. svg_rotate "$first_frame_file" $angle > "$frame_file"
  110. ;;
  111. esac
  112. done
  113. }
  114. function render_cursor_image {
  115. # Render SVG source image to finished PNG image.
  116. local name="$1"
  117. local compose_opts="$2"
  118. local frame=$3
  119. local frame_duration=$4
  120. compose_opts="${compose_opts} --orientation $ORIENTATION"
  121. if [[ "$frame" ]] ; then
  122. image_name="${name}.frame${frame}"
  123. compose_opts="${compose_opts} --frame $frame"
  124. if [[ "$frame_duration" ]] ; then
  125. compose_opts="${compose_opts} --duration $frame_duration"
  126. fi
  127. else
  128. frame=0
  129. image_name="${name}"
  130. fi
  131. infile="${indir}/${image_name}.svg"
  132. if [[ ! -f "$infile" ]] ; then
  133. echo "skipping $name; no svg file found."
  134. return 1
  135. fi
  136. tempfile="${workdir}/$(basename $infile)"
  137. outfile="${builddir}/${image_name}.png"
  138. svg_substitutions "$infile" > "$tempfile"
  139. "${bindir}"/render-cursor-image $compose_opts "$name" "$tempfile" "$outfile"
  140. }
  141. ## Generate the theme file. Process the size argument only if the
  142. ## configuration has only one SIZES() item.
  143. #if [ ${#SIZES[@]} -eq 1 ]; then
  144. # sizename=${SIZES[0]%%=*}
  145. #fi
  146. generate_theme "$THEMENAME"
  147. # the basic cursors
  148. names="
  149. all-scroll
  150. cell
  151. col-resize
  152. crosshair
  153. default
  154. e-resize
  155. ew-resize
  156. grabbing
  157. n-resize
  158. ne-resize
  159. nesw-resize
  160. not-allowed
  161. ns-resize
  162. nw-resize
  163. nwse-resize
  164. pencil
  165. pirate
  166. pointer
  167. right-arrow
  168. row-resize
  169. s-resize
  170. se-resize
  171. sw-resize
  172. text
  173. up-arrow
  174. vertical-text
  175. w-resize
  176. X-cursor
  177. zoom-in
  178. zoom-out
  179. alias
  180. context-menu
  181. copy
  182. move
  183. no-drop
  184. "
  185. for name in $names ; do
  186. compose_opts=""
  187. render_cursor_image "$name" "$compose_opts"
  188. done
  189. # the animated cursors
  190. name="help"
  191. compose_opts=""
  192. frames_count=2
  193. generate_animation_source_frames "$name" $frames_count
  194. render_cursor_image "$name" "$compose_opts" 1 2000
  195. render_cursor_image "$name" "$compose_opts" 2 500
  196. name="progress"
  197. frames_count=24
  198. generate_animation_source_frames "$name" $frames_count
  199. for frame in $(seq --equal-width 1 $frames_count) ; do
  200. compose_opts=""
  201. render_cursor_image "$name" "$compose_opts" $frame
  202. done
  203. name="wait"
  204. frames_count=36
  205. generate_animation_source_frames "$name" $frames_count
  206. for frame in $(seq --equal-width 1 $frames_count) ; do
  207. compose_opts=""
  208. render_cursor_image "$name" "$compose_opts" $frame
  209. done