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

/coyote/fixps.pro

https://github.com/OpenCyclone/lib
Prolog | 298 lines | 274 code | 24 blank | 0 comment | 12 complexity | f7ea3d768bb6dda169a53ead61476b0d MD5 | raw file
  1. ;+
  2. ; NAME:
  3. ; FIXPS
  4. ;
  5. ; PURPOSE:
  6. ;
  7. ; Modifies an IDL-produced PostScript landscape mode file so that the output
  8. ; is right side up rather than upside down.
  9. ;
  10. ; AUTHOR:
  11. ; FANNING SOFTWARE CONSULTING:
  12. ; David Fanning, Ph.D.
  13. ; 1645 Sheely Drive
  14. ; Fort Collins, CO 80526 USA
  15. ; Phone: 970-221-0438
  16. ; E-mail: davidf@dfanning.com
  17. ; Coyote's Guide to IDL Programming: http://www.dfanning.com
  18. ;
  19. ; CATEGORY:
  20. ;
  21. ; Graphics
  22. ;
  23. ; CALLING SEQUENCE:
  24. ;
  25. ; FixPS, inputFile, outputFile
  26. ;
  27. ; Auguments:
  28. ;
  29. ; inputFile: A IDL-produced PostScript file in Landscape mode.
  30. ;
  31. ; outputFile: The name of the fixed output PostScript file. If not provided, the input
  32. ; file is overwritten. Assumes proper read/write permission in TEMP directory
  33. ; and in the directory where the input file is located.
  34. ;
  35. ; KEYWORDS:
  36. ;
  37. ; A4: Set this keyword if the PostScript file is using a A4 Europeran sized page.
  38. ; LEDGER: Set this keyword if the PostScript file is using a US ledger size (11 x 17 inch) page.
  39. ; LEGAL: Set this keyword if the PostScript file is using a US legal size (8.5 x 14 inch) page.
  40. ; LETTER: Set this keyword if the PostScript file is using a US letter size (8.5 x 11 inch) page.
  41. ; PAGETYPE: A generic way to set the page size. A string of "LETTER", "LEDGER", "LEGAL", or "A4".
  42. ; By default, set to "LETTER".
  43. ; QUIET: Set this keyword to suppress error messages from the program.
  44. ; SUCCESS: If this keyword is set to a named variable, then on output the variable will
  45. ; return a 1 if the operation was successful, and a 0 otherwise. Using this
  46. ; keyword also supresses the program's ability to "throw" an error. Informational
  47. ; messages are issued about program developments, but this program will allow the
  48. ; program caller to decide what to do with unsuccessful program completion.
  49. ;
  50. ; SIDE EFFECTS and RESTRICTIONS:
  51. ;
  52. ; Files that are not currently in Landscape mode will be ignored. Tested with single and
  53. ; multiple page PostScript output from IDL 7.0.1 and 7.1.
  54. ;
  55. ; MODIFICATION HISTORY:
  56. ;
  57. ; Written by: David W. Fanning, 6 August 2009.
  58. ; Change to overwrite input file if output filename is not provided. 6 August 2009. DWF.
  59. ; Incorporated checks for non-landscape mode files and files that have already been fixed. 6 August 2009. DWF.
  60. ; Modified to fix multiple-page PostScript files and to work seamlessly with PS_START output. 8 August 2009. DWF.
  61. ; Ran into a problem in which the PostScript file is stored in the directory pointed
  62. ; to by the IDL_TMPDIR environment variable. Now check to see if the input filename
  63. ; is the same as the output filename and make a change, if necessary. 22 July 2010. DWF.
  64. ; Retreated to standard error handling with ERROR_MESSAGE as there are inevitable errors. 2 August 2010. DWF.
  65. ; Output file was created, even if not used. Now deleting file and issuing messages to
  66. ; explain why output file was not created. 1 November 2010. DWF.
  67. ; Added SUCCESS and QUIET keywords. 15 Novemember 2010. DWF.
  68. ; PostScript file structure changed in IDL 8. Made adjustment to find the
  69. ; PageBoundingBox line. 19 Dec 2010. DWF.
  70. ;-
  71. ;
  72. ;******************************************************************************************;
  73. ; Copyright (c) 2009, by Fanning Software Consulting, Inc. ;
  74. ; All rights reserved. ;
  75. ; ;
  76. ; Redistribution and use in source and binary forms, with or without ;
  77. ; modification, are permitted provided that the following conditions are met: ;
  78. ; ;
  79. ; * Redistributions of source code must retain the above copyright ;
  80. ; notice, this list of conditions and the following disclaimer. ;
  81. ; * Redistributions in binary form must reproduce the above copyright ;
  82. ; notice, this list of conditions and the following disclaimer in the ;
  83. ; documentation and/or other materials provided with the distribution. ;
  84. ; * Neither the name of Fanning Software Consulting, Inc. nor the names of its ;
  85. ; contributors may be used to endorse or promote products derived from this ;
  86. ; software without specific prior written permission. ;
  87. ; ;
  88. ; THIS SOFTWARE IS PROVIDED BY FANNING SOFTWARE CONSULTING, INC. ''AS IS'' AND ANY ;
  89. ; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES ;
  90. ; OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT ;
  91. ; SHALL FANNING SOFTWARE CONSULTING, INC. BE LIABLE FOR ANY DIRECT, INDIRECT, ;
  92. ; INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED ;
  93. ; TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; ;
  94. ; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ;
  95. ; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ;
  96. ; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ;
  97. ; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ;
  98. ;******************************************************************************************;
  99. PRO FIXPS, in_filename, out_filename, $
  100. A4=A4, $
  101. LEDGER=ledger, $
  102. LEGAL=legal, $
  103. LETTER=letter, $
  104. PAGETYPE=pagetype, $
  105. QUIET=quiet, $
  106. SUCCESS=success
  107. Compile_Opt idl2
  108. ; Error handling.
  109. IF Arg_Present(success) THEN BEGIN
  110. Catch, theError
  111. IF theError NE 0 THEN BEGIN
  112. Catch, /CANCEL
  113. success = 0
  114. IF N_Elements(out_lun) NE 0 THEN Free_Lun, out_lun
  115. IF N_Elements(in_lun) NE 0 THEN Free_Lun, in_lun
  116. IF ~Keyword_Set(quiet) THEN Print, !Error_State.MSG
  117. RETURN
  118. ENDIF
  119. ENDIF ELSE BEGIN
  120. Catch, theError
  121. IF theError NE 0 THEN BEGIN
  122. Catch, /CANCEL
  123. IF ~Keyword_Set(quiet) THEN ok = Error_Message()
  124. success = 0
  125. IF N_Elements(out_lun) NE 0 THEN Free_Lun, out_lun
  126. IF N_Elements(in_lun) NE 0 THEN Free_Lun, in_lun
  127. RETURN
  128. ENDIF
  129. ENDELSE
  130. ; Assume success
  131. success = 1
  132. ; Is there an input filename?
  133. IF N_Elements(in_filename) EQ 0 THEN BEGIN
  134. in_filename = Dialog_Pickfile(FILTER='*.ps', TITLE='Select PostScript file to repair.')
  135. IF in_filename EQ "" THEN RETURN
  136. ENDIF
  137. ; Is there an output filename?
  138. IF N_Elements(out_filename) EQ 0 THEN BEGIN
  139. root_name = FSC_Base_Filename(in_filename, EXTENSION=ext)
  140. out_filename = Filepath(ROOT_DIR=GetEnv('IDL_TMPDIR'), root_name + '_tmp.' + ext)
  141. print_out = 1
  142. no_output_filename = 1
  143. ENDIF ELSE no_output_filename = 0
  144. ; The out_filename can be the same as the in_filename in some cases.
  145. IF out_filename EQ in_filename THEN BEGIN
  146. rootname = FSC_Base_Filename(out_filename, DIRECTORY=outDir, EXTENSION=ext)
  147. out_filename = FilePath(ROOT_DIR=outDir, rootname + '_tmp.' + ext)
  148. ENDIF
  149. ; Open the output filename.
  150. OpenW, out_lun, out_filename, /GET_LUN
  151. ; What kind of page is this?
  152. IF N_Elements(pagetype) EQ 0 THEN BEGIN
  153. IF Keyword_Set(A4) THEN pageType = 'A4'
  154. IF Keyword_Set(legal) THEN pageType = 'LEGAL'
  155. IF Keyword_Set(ledger) THEN pageType = 'LEDGER'
  156. IF Keyword_Set(letter) THEN pageType = 'LETTER'
  157. IF N_Elements(pageType) EQ 0 THEN pageType = 'LETTER'
  158. ENDIF ELSE pageType = StrUpCase(pageType)
  159. ; Set the rotate/translate command appropriately.
  160. CASE pageType OF
  161. 'LETTER': rtcmd = '180 rotate -612 -792 translate'
  162. 'A4': rtcmd = '180 rotate -595.28 -841.89 translate'
  163. 'LEGAL': rtcmd = '180 rotate -612 -1008 translate'
  164. 'LEDGER': rtcmd = '180 rotate -792 -1224 translate'
  165. ELSE: Message, 'Unknown PageType: ' + pageType
  166. ENDCASE
  167. ; Move along in the file until the end of the Prolog.
  168. line = ""
  169. count = 0
  170. target = "void"
  171. buffer = StrArr(100)
  172. OpenR, in_lun, in_filename, /GET_LUN
  173. WHILE target NE '%%EndProlog' DO BEGIN
  174. ReadF, in_lun, line
  175. buffer[count] = line
  176. target = StrMid(line, 0, 11)
  177. count = count + 1
  178. IF count MOD 100 EQ 0 THEN buffer = [buffer, StrArr(100)]
  179. ENDWHILE
  180. ; Read the next 10 lines all at once. If you have already processed
  181. ; this file, exit. But if you haven't write the buffer to the output file.
  182. in_lines = StrArr(10)
  183. ReadF, in_lun, in_lines
  184. ; Is this a landscape file? If not, out of here.
  185. index = Where(in_lines EQ '%%PageOrientation: Landscape', landscape_cnt)
  186. IF landscape_cnt EQ 0 THEN BEGIN
  187. Free_Lun, in_lun
  188. Free_Lun, out_lun
  189. File_Delete, out_filename
  190. Message, 'File not a landscape file. Exiting...', /Informational
  191. RETURN
  192. ENDIF
  193. ; Has this file already been mucked with? If so, out of here. If not, write
  194. ; the buffer to the output file.
  195. IF StrMid(in_lines[1], 0, 10) EQ '180 rotate' THEN BEGIN
  196. Free_Lun, in_lun
  197. Free_Lun, out_lun
  198. File_Delete, out_filename
  199. Message, 'File is in the proper rotation. Exiting...', /Informational
  200. RETURN
  201. ENDIF ELSE BEGIN
  202. FOR j=0,count-1 DO PrintF, out_lun, buffer[j]
  203. ENDELSE
  204. count = count + 10
  205. ; We are going to add an extra line in the output file.
  206. out_lines = StrArr(11)
  207. out_lines[0] = in_lines[0]
  208. out_lines[2:10] = in_lines[1:9]
  209. out_lines[1] = rtcmd
  210. ; Calculate the new bounding box boundaries.
  211. bbox_line_num = Where(StrMid(in_lines, 0, 17) EQ '%%PageBoundingBox', bbox_count)
  212. IF bbox_count EQ 0 THEN Message, 'Cannot find PageBoundingBox line in file.'
  213. bbox = StrMid(in_lines[bbox_line_num[0]], 18)
  214. x0 = 0
  215. x1 = 0
  216. y0 = 0
  217. y1 = 0
  218. ReadS, bbox, x0, y0, x1, y1
  219. CASE pageType OF
  220. 'LETTER': BEGIN
  221. lx = String(612 - x1, FORMAT='(I5)')
  222. ly = String(792 - y1, FORMAT='(I5)')
  223. ux = String(612 - lx, FORMAT='(I5)')
  224. uy = String(792 - ly, FORMAT='(I5)')
  225. END
  226. 'A4': BEGIN
  227. lx = String(595.28 - x1, FORMAT='(I5)')
  228. ly = String(841.89 - y1, FORMAT='(I5)')
  229. ux = String(595.28 - lx, FORMAT='(I5)')
  230. uy = String(841.89 - ly, FORMAT='(I5)')
  231. END
  232. 'LEGAL': BEGIN
  233. lx = String(612 - x1, FORMAT='(I5)')
  234. ly = String(1008 - y1, FORMAT='(I5)')
  235. ux = String(612 - lx, FORMAT='(I5)')
  236. uy = String(1008 - ly, FORMAT='(I5)')
  237. END
  238. 'LEDGER': BEGIN
  239. lx = String(792 - x1, FORMAT='(I5)')
  240. ly = String(1224 - y1, FORMAT='(I5)')
  241. ux = String(792 - lx, FORMAT='(I5)')
  242. uy = String(1224 - ly, FORMAT='(I5)')
  243. END
  244. ENDCASE
  245. ; Output the new boundaries.
  246. out_lines[5] = '%%PageBoundingBox: ' + lx + ly + ux + uy
  247. FOR j=0,10 DO PrintF, out_lun, out_lines[j]
  248. ; Output the rest of the file, looking for another "%%Page:" marker.
  249. WHILE ~EOF(in_lun) DO BEGIN
  250. ReadF, in_lun, line
  251. PrintF, out_lun, line
  252. IF StrMid(line, 0, 7) EQ '%%Page:' THEN BEGIN
  253. IF Keyword_Set(A4) THEN BEGIN
  254. PrintF, out_lun, rtcmd
  255. ENDIF ELSE BEGIN
  256. PrintF, out_lun, rtcmd
  257. ENDELSE
  258. ENDIF
  259. ENDWHILE
  260. ; Clean up.
  261. Free_lun, in_lun
  262. Free_lun, out_lun
  263. ; If there was no output filename given, then we are going
  264. ; to replace the input file with the temporary output file.
  265. IF no_output_filename THEN BEGIN
  266. inputDir = File_Dirname(in_filename)
  267. root_name = File_BaseName(in_filename)
  268. ; Can you write into the input directory?
  269. IF File_Test(in_filename, /WRITE) EQ 0 THEN Message, 'Cannot write TEMPORARY file into input file directory.'
  270. ; Replace the input file with the temporary output file.
  271. File_Delete, in_filename
  272. File_Move, out_filename, in_filename
  273. ENDIF
  274. END