racket/collects/teachpack/2htdp/scribblings/image-gen.ss
Robby Findler ddf0b4ec01 added finer control over pens
svn: r17670
2010-01-16 02:03:54 +00:00

110 lines
3.7 KiB
Scheme

#lang scheme/gui
;; Run this file is generate the images in the img/ directory,
;; picked up by image-examples from image.scrbl
(require 2htdp/image
lang/posn
(only-in 2htdp/private/image-more save-image))
(define-namespace-anchor anchor)
(define ns (namespace-anchor->namespace anchor))
(define expressions
(parameterize ([current-namespace ns])
(putenv "PLTSHOWIMAGES" "show")
(let-values ([(in out) (make-pipe)])
(thread
(λ ()
(parameterize ([current-output-port out])
(dynamic-require "image.scrbl" #f))
(close-output-port out)))
(let loop ()
(let ([exp (read in)])
(if (eof-object? exp)
'()
(cons exp (loop))))))))
(define-namespace-anchor image-anchor)
(define image-ns (namespace-anchor->namespace anchor))
(define mapping '())
(define (handle-image exp)
(printf ".") (flush-output)
(let ([result
(with-handlers ([exn:fail?
(λ (x)
(printf "\nerror evaluating:\n")
(pretty-print exp)
(raise x))])
(parameterize ([current-namespace image-ns]) (eval exp)))])
(cond
[(image? result)
(let ([fn (exp->filename exp)])
(set! mapping (cons `(list ',exp 'image ,fn) mapping))
(save-image result (build-path "img" fn)))]
[else
(unless (equal? result (read/write result))
(error 'handle-image "expression ~s produced ~s, which I can't write"
exp result))
(set! mapping (cons `(list ',exp 'val ,result) mapping))])))
(define (exp->filename exp)
(let loop ([prev 0])
(let ([candidate
(format "~a~a.png"
(number->string (exp->number exp) 16) ;; abs to avoid filenames beginning with hyphens
(if (zero? prev)
""
(format "-~a" (number->string prev 16))))])
(cond
[(anywhere? candidate mapping)
(printf "dup!\n")
(loop (+ prev 1))]
[else
candidate]))))
(define (anywhere? x sexp)
(let loop ([sexp sexp])
(cond
[(pair? sexp) (or (loop (car sexp))
(loop (cdr sexp)))]
[else (equal? x sexp)])))
;(define a-prime (- (expt 2 127) 1)) ;; Lucas found this in 1876. (too long filenames)
(define a-prime (/ (- (expt 2 59) 1) 179951)) ;; found by Landry in 1867
;(define a-prime 113) ;; has too many collisions
(define base 256)
(define (exp->number exp)
(let ([digits (map char->integer (string->list (format "~s" exp)))])
(when (ormap (λ (x) (not (<= 0 x (- base 1)))) digits)
(error 'exp->number "found a char that was bigger than ~a in ~s" (- base 1) exp))
(let loop ([n 1]
[digits digits])
(cond
[(null? digits) (modulo n a-prime)]
[else (loop (+ (car digits) (* n base))
(cdr digits))]))))
(define (read/write result)
(let-values ([(in out) (make-pipe)])
(thread (λ () (write result out) (close-output-port out)))
(read in)))
(for-each handle-image expressions)
(cond
[(null? mapping)
(error 'image-gen "didn't find any images; probably this means that you need to delete .zo files and try again")]
[else
(printf "\n")])
(call-with-output-file "image-toc.ss"
(λ (port)
(fprintf port "#lang scheme/base\n(provide mapping)\n")
(fprintf port ";; this file is generated by image-gen.ss -- do not edit\n;; note that the file that creates this file depends on this file\n;; it is always safe to simply define (and provide) mapping as the empty list\n\n")
(pretty-print
`(define mapping (list ,@mapping))
port))
#:exists 'truncate)