PageRenderTime 46ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/texlive-2007/utils/tpic2pdftex/tpic2pdftex

#
Shell | 407 lines | 337 code | 3 blank | 67 comment | 0 complexity | 3cd59310c96719f6edf235cdde768e95 MD5 | raw file
Possible License(s): AGPL-1.0, BSD-3-Clause, LGPL-3.0, GPL-2.0, CPL-1.0, LGPL-2.1, LGPL-2.0
  1. #!/bin/sh -
  2. #
  3. # $Id: tpic2pdftex,v 1.94 2007/01/14 19:05:32 hahe Exp $
  4. #
  5. # Experimental awk-script for conversion of tpic \specials as produced
  6. # by (groff-)pic into pdfTeX \pdfliteral sections for further processing
  7. # by pdftex.
  8. #
  9. # Usage:
  10. # $ pic -t somefile.pic | tpic2pdftex > somefile.tex
  11. #
  12. # Process somefile.tex by pdftex/pdflatex.
  13. #
  14. # tpic \special desciption see e. g.:
  15. # Goossens, Rahtz, Mittelbach: The LaTeX Graphics Companion,
  16. # Addison-Wesley, 1997, pp. 464.
  17. #
  18. # Bugs:
  19. # Spline curve shapes not fully authentic (unknown algorithm).
  20. # Bounding box does not care for line thickness (groff pic feature).
  21. # Splines might be outside bounding box.
  22. #
  23. # Copyright (C) 2002--2004 by Hartmut Henkel
  24. #
  25. # This program is free software; you can redistribute it and/or modify
  26. # it under the terms of the GNU General Public License as published by
  27. # the Free Software Foundation; either version 2 of the License, or (at
  28. # your option) any later version.
  29. #
  30. # This program is distributed in the hope that it will be useful, but
  31. # WITHOUT ANY WARRANTY; without even the implied warranty of
  32. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  33. # See the GNU General Public License for more details.
  34. #
  35. # You should have received a copy of the GNU General Public License
  36. # along with this program; if not, write to the
  37. # Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  38. # MA 02111-1307 USA
  39. #
  40. # The author may be contacted via the e-mail address
  41. #
  42. # hartmut_henkel@gmx.de
  43. #
  44. # NEWS:
  45. # 14 Jan. 2007 - make it executable shell script, calling awk
  46. # 16 Dec. 2004 - Replaced // {print} by {print} (some AWKs did choke)
  47. # 09 Apr. 2004 - Locale check: Decimal point in float numbers?
  48. # 30 Oct. 2003 - Replaced print statements by printf to avoid
  49. # underflow numbers like 1e-14 in \pdfliterals. Remove trailing
  50. # zeroes of floating point numbers.
  51. # 02 May 2003 - Lines starting with \ allow TeX insertions,
  52. # e. g. of pdfTeX \pdfliteral{}
  53. # 29 Apr. 2003 - Changed for pic of groff 1.19
  54. # 16 Mar. 2003 - Bug corrected: Dashed lines shorter than minimum
  55. # dash-pause length now drawn solid.
  56. # 11 Nov. 2002 - Spline drawing improved: First half of first and last
  57. # half of last spline segments are drawn by straight lines.
  58. # 28 Nov. 2002 - Arc and circle drawing cleaned up. Full circle is now
  59. # drawn by 4 Bezier curves, as is common use. Arcs split evenly into
  60. # Bezier curves, to minimize max. error.
  61. # 02 Dec. 2002 - Experimental pic (groff > 1.18.1) with improved
  62. # vertical picture positioning supported.
  63. # 04 Dec. 2002 - Experiment with modified pic (\vtop -> \vbox),
  64. # Formula for Bezier constant c reduced.
  65. #
  66. ########################################################################
  67. AWK=${AWK:-gawk}
  68. export LANG="C"
  69. AWKPROG='
  70. # begin of awk input file
  71. function qprintf(a) {
  72. gsub(/0* /," ", a); # trailing zeroes in %f
  73. gsub(/\. /," ", a); # orphaned decimal dots
  74. gsub(/0*]/,"]", a); # trailing zeroes in brackets
  75. gsub(/0X/,"0", a); # guard integer zeroes
  76. gsub(/-0 /,"0 ", a); # correct -0 to 0
  77. print a;
  78. }
  79. function startpdfliteral() {
  80. if (pdfliteral == 0) {
  81. print "\\pdfliteral{";
  82. printf("q [] 0 d %d J %d j\n", linecap, linejoin); # no qprintf!
  83. qprintf(sprintf("%f w", linethickness * wscale));
  84. }
  85. pdfliteral = 1;
  86. }
  87. function stoppdfliteral() {
  88. if (pdfliteral == 1) {
  89. print "Q";
  90. print "}%";
  91. }
  92. pdfliteral = 0;
  93. }
  94. ########################################################################
  95. BEGIN{
  96. wscale = 72.0 / 1000;
  97. tpicmode = 0;
  98. pdfliteral = 0;
  99. pointbuf = 0;
  100. filled = 0;
  101. fillval = 0;
  102. linecap = 1;
  103. linejoin = 1;
  104. defaultlinethickness = 8;
  105. drawarc = 0;
  106. pi = atan2(0, -1);
  107. if (match(sprintf("%f", 0.5), /\./) == 0) {
  108. print "ERROR: Floating point numbers miss decimal point. Do"
  109. print " export LANG=\"C\""
  110. print "before calling awk."
  111. print "ERROR: Floating point numbers miss decimal point. Do" > "/dev/stderr"
  112. print " export LANG=\"C\"" > "/dev/stderr"
  113. print "before calling awk." > "/dev/stderr"
  114. exit 1;
  115. }
  116. }
  117. ########################################################################
  118. # the following expression triggers tpic processing for pic <= 1.18.1
  119. /^\\setbox\\graph=\\vtop{/ {
  120. pdfliteral = 0;
  121. tpicmode = 1;
  122. linethickness = defaultlinethickness;
  123. }
  124. # the following expression triggers tpic processing for pic = 1.19
  125. /^\\expandafter\\setbox\\csname graph\\endcsname/ {
  126. pdfliteral = 0;
  127. tpicmode = 1;
  128. linethickness = defaultlinethickness;
  129. }
  130. # TeX parts end \pdfliteral, and also TeX parts embedded in .PS ... .PE
  131. # section end \pdfliteral
  132. /^ *\\graphtemp|^ *\\rlap|^ *\\advance|^\\|^ *\\hbox/ {
  133. if(tpicmode == 1)
  134. stoppdfliteral();
  135. }
  136. /^}%/ {
  137. if(tpicmode == 1)
  138. tpicmode = 0;
  139. }
  140. ########################################################################
  141. # all specials handling
  142. /^ *\\special/ {
  143. if(tpicmode == 1)
  144. startpdfliteral();
  145. }
  146. # <pn> set pen size
  147. /^ *\\special{pn/ {
  148. gsub(/[{}]/, " ");
  149. linethickness = $3 + 0;
  150. qprintf(sprintf("%f w", linethickness * wscale));
  151. next;
  152. }
  153. # <pa> add point to path
  154. /^ *\\special{pa/ {
  155. gsub(/[{}]/, " ");
  156. x[pointbuf] = $3 + 0;
  157. y[pointbuf] = $4 + 0;
  158. pointbuf++;
  159. next;
  160. }
  161. # <fp> print path as straight lines
  162. /^ *\\special{fp/ {
  163. if (filled == 1)
  164. qprintf(sprintf("q %f g", 1 - fillval));
  165. qprintf(sprintf("%f %f m", x[0] * wscale, -y[0] * wscale));
  166. for (i = 1; i < pointbuf; i++)
  167. qprintf(sprintf("%f %f l", x[i] * wscale, -y[i] * wscale));
  168. if (filled == 1)
  169. print "B Q";
  170. else
  171. print "S";
  172. pointbuf = 0;
  173. filled = 0;
  174. next;
  175. }
  176. # <da> print path as straight dashed lines
  177. /^ *\\special{da/ {
  178. gsub(/[{}]/, " ");
  179. don = ($3 + 0) * 1000;
  180. if (filled == 1) {
  181. qprintf(sprintf("q %f g", 1 - fillval));
  182. qprintf(sprintf("%f %f m", x[0] * wscale, -y[0] * wscale));
  183. for (i = 1; i < pointbuf; i++)
  184. qprintf(sprintf("%f %f l", x[i] * wscale, -y[i] * wscale));
  185. print "f Q";
  186. }
  187. for (i = 1; i < pointbuf; i++) {
  188. dx = x[i] - x[i - 1];
  189. dy = y[i] - y[i - 1];
  190. len = sqrt(dx * dx + dy * dy);
  191. non = int(0.5 * len / don + 0.75);
  192. noff = non - 1;
  193. lon = don * non;
  194. loff = len - lon;
  195. if(noff > 0) {
  196. doff = loff / noff;
  197. qprintf(sprintf("q [%f %f] 0X d", don * wscale, doff * wscale));
  198. } else {
  199. print "q [] 0 d";
  200. }
  201. qprintf(sprintf("%f %f m", x[i - 1] * wscale, -y[i - 1] * wscale));
  202. qprintf(sprintf("%f %f l", x[i] * wscale, -y[i] * wscale));
  203. print "S Q";
  204. }
  205. pointbuf = 0;
  206. filled = 0;
  207. next;
  208. }
  209. # <dt> print path as straight dotted lines
  210. /^ *\\special{dt/ {
  211. gsub(/[{}]/, " ");
  212. dt = ($3 + 0) * 1000;
  213. if (filled == 1) {
  214. qprintf(sprintf("q %f g", 1 - fillval));
  215. qprintf(sprintf("%f %f m", x[0] * wscale, -y[0] * wscale));
  216. for (i = 1; i < pointbuf; i++)
  217. qprintf(sprintf("%f %f l", x[i] * wscale, -y[i] * wscale));
  218. print "f Q";
  219. }
  220. for (i = 1; i < pointbuf; i++) {
  221. dx = x[i] - x[i - 1];
  222. dy = y[i] - y[i - 1];
  223. len = sqrt(dx * dx + dy * dy);
  224. dl = int (len / dt + 0.5);
  225. if (!dl)
  226. dtl = len;
  227. else
  228. dtl = len / dl;
  229. qprintf(sprintf("q [0X %f] 0X d", dtl * wscale));
  230. qprintf(sprintf("%f %f m", x[i - 1] * wscale, -y[i - 1] * wscale));
  231. qprintf(sprintf("%f %f l", x[i] * wscale, -y[i] * wscale));
  232. print "S Q";
  233. }
  234. pointbuf = 0;
  235. filled = 0;
  236. next;
  237. }
  238. # <ip> like <fp>, but path actually not drawn
  239. /^ *\\special{ip/ {
  240. if (filled == 1)
  241. qprintf(sprintf("q %f g", 1 - fillval));
  242. qprintf(sprintf("%f %f m", x[0] * wscale, -y[0] * wscale));
  243. for (i = 1; i < pointbuf; i++)
  244. qprintf(sprintf("%f %f l", x[i] * wscale, -y[i] * wscale));
  245. if (filled == 1)
  246. print "f Q";
  247. else
  248. print "f";
  249. pointbuf = 0;
  250. filled = 0;
  251. next;
  252. }
  253. # <sp> like <fp>, but path printed as splines
  254. /^ *\\special{sp/ {
  255. gsub(/[{}]/, " ");
  256. don = ($3 + 0) * 1000;
  257. a = 0.68; # fudge, visually optimized
  258. x[pointbuf] = x[pointbuf - 1];
  259. y[pointbuf] = y[pointbuf - 1];
  260. if (don > 0)
  261. qprintf(sprintf("q [%f] 0X d", don * wscale));
  262. if (don < 0)
  263. qprintf(sprintf("q [0X %f] 0X d", -don * wscale));
  264. qprintf(sprintf("%f %f m", x[0] * wscale, -y[0] * wscale));
  265. if(pointbuf < 3)
  266. qprintf(sprintf("%f %f l", x[pointbuf - 1] * wscale, -y[pointbuf - 1] * wscale));
  267. else {
  268. qprintf(sprintf("%f %f l", 0.5 * (x[0] + x[1]) * wscale, \
  269. -0.5 * (y[0] + y[1]) * wscale)); # start straight, see cstr116.ps
  270. for (i = 1; i < pointbuf - 1; i++)
  271. qprintf(sprintf("%f %f %f %f %f %f c", \
  272. (a * x[i] + (1 - a) * 0.5 * (x[i] + x[i - 1])) * wscale, \
  273. -(a * y[i] + (1 - a) * 0.5 * (y[i] + y[i - 1])) * wscale, \
  274. (a * x[i] + (1 - a) * 0.5 * (x[i] + x[i + 1])) * wscale, \
  275. -(a * y[i] + (1 - a) * 0.5 * (y[i] + y[i + 1])) * wscale, \
  276. 0.5 * (x[i] + x[i + 1]) * wscale, -0.5 * (y[i] + y[i + 1]) * wscale));
  277. qprintf(sprintf("%f %f l", x[pointbuf - 1] * wscale, -y[pointbuf - 1] * wscale));
  278. }
  279. if (filled == 1) {
  280. qprintf(sprintf("q %f g", 1 - fillval));
  281. print "B Q";
  282. }
  283. else
  284. print "S";
  285. if (don != 0)
  286. print "Q";
  287. pointbuf = 0;
  288. filled = 0;
  289. next;
  290. }
  291. # <sh> prepare shading of object interior
  292. /^ *\\special{sh/ {
  293. gsub(/[{}]/, " ");
  294. fillval = $3 + 0;
  295. filled = 1;
  296. next;
  297. }
  298. # <ar> draw arc
  299. # <ia> like <ar>, but arc actually not drawn
  300. /^ *\\special{ar/ {
  301. drawarc = 1;
  302. }
  303. /^ *\\special{ar|^ *\\special{ia/ {
  304. gsub(/[{}]/, " ");
  305. xc = $3 + 0;
  306. yc = $4 + 0;
  307. rx = $5 + 0;
  308. ry = $6 + 0;
  309. s = $7 + 0;
  310. e = $8 + 0;
  311. if (e - s > 2 * pi) e = s + 2 * pi;
  312. if (s - e > 2 * pi) e = s - 2 * pi;
  313. curvespercircle = 4; # max. number Bezier curves per circle
  314. phi_max = 1.001 * 2 * pi / curvespercircle;
  315. if (e > s)
  316. imax = int ((e - s) / phi_max) + 1;
  317. else
  318. imax = int ((s - e) / phi_max) + 1;
  319. phi = (e - s) / imax;
  320. # parameter for Bezier control vectors, c(90 deg.) = 0.55228...:
  321. c = 4 * (1 - cos(0.5 * phi)) / (3 * sin(0.5 * phi));
  322. x0 = rx * cos(s) + xc;
  323. y0 = ry * sin(s) + yc;
  324. qprintf(sprintf("%f %f m", x0 * wscale, -y0 * wscale));
  325. for (i = 0; i < imax; i++) {
  326. x1 = x0 - rx * c * sin(s + i * phi);
  327. y1 = y0 + ry * c * cos(s + i * phi);
  328. x3 = rx * cos(s + (i + 1) * phi) + xc;
  329. y3 = ry * sin(s + (i + 1) * phi) + yc;
  330. x2 = x3 + rx * c * sin(s + (i + 1) * phi);
  331. y2 = y3 - ry * c * cos(s + (i + 1) * phi);
  332. qprintf(sprintf("%f %f %f %f %f %f c", x1 * wscale, -y1 * wscale, \
  333. x2 * wscale, -y2 * wscale, x3 * wscale, -y3 * wscale));
  334. x0 = x3;
  335. y0 = y3;
  336. }
  337. if(drawarc == 1) {
  338. if (filled == 1) {
  339. qprintf(sprintf("h q %f g", 1 - fillval));
  340. print "B Q";
  341. }
  342. else
  343. print "S";
  344. } else {
  345. if (filled == 1) {
  346. qprintf(sprintf("h q %f g", 1 - fillval));
  347. print "f Q";
  348. }
  349. else
  350. print "f";
  351. }
  352. filled = 0;
  353. drawarc = 0;
  354. next;
  355. }
  356. ########################################################################
  357. {print}
  358. ########################################################################
  359. '
  360. # end of awk input file
  361. $AWK "$AWKPROG" "$@"