#lang scheme/base
(require scheme/class
scheme/gui/base
scheme/list
mrlib/cache-image-snip
scheme/contract
"runtime/stx.ss")
(define-struct named-bitmap (name bitmap))
(provide/contract [struct named-bitmap [(name string?)
(bitmap (is-a?/c bitmap%))]]
[named-bitmap-save (named-bitmap? path-string? . -> . any)]
[lift-images! ((is-a?/c text%)
. -> . (listof named-bitmap?))]
[lift-images/stx (stx? . -> . (values stx? (listof named-bitmap?)))]
[lift-images/stxs ((listof stx?) . -> . (values (listof stx?) (listof named-bitmap?)))])
(define (lift-images! a-text)
(let loop ([a-snip (send a-text find-first-snip)])
(cond
[(not a-snip)
empty]
[(image-snip? a-snip)
(let* ([file-name (make-image-name)]
[bitmap (send a-snip get-bitmap)]
[replacement-snip (make-object string-snip%
(format "(open-image-url ~s)"
file-name))])
(send a-text set-position
(send a-text get-snip-position a-snip)
(+ (send a-text get-snip-position a-snip)
(send a-snip get-count)))
(send a-text insert replacement-snip)
(cons (make-named-bitmap file-name bitmap)
(loop (send replacement-snip next))))]
[else
(loop (send a-snip next))])))
(define (lift-images/stx a-stx)
(cond
[(stx:list? a-stx)
(let-values ([(lifted-elts named-bitmaps)
(lift-images/stxs (stx-e a-stx))])
(values (make-stx:list lifted-elts (stx-loc a-stx))
named-bitmaps))]
[(stx:atom? a-stx)
(cond [(image-snip? (stx-e a-stx))
(let* ([filename (make-image-name)]
[bitmap (send (stx-e a-stx) get-bitmap)]
[replacement-stx (make-stx:list (list (make-stx:atom 'open-image-url
(stx-loc a-stx))
(make-stx:atom filename
(stx-loc a-stx)))
(stx-loc a-stx))])
(values replacement-stx (list (make-named-bitmap filename bitmap))))]
[else
(values a-stx empty)])]))
(define (lift-images/stxs stxs)
(cond
[(empty? stxs)
(values empty empty)]
[else
(let-values ([(lifted-stx named-bitmaps)
(lift-images/stx (first stxs))]
[(rest-lifted-stxs rest-named-bitmaps)
(lift-images/stxs (rest stxs))])
(values (cons lifted-stx rest-lifted-stxs)
(append named-bitmaps rest-named-bitmaps)))]))
(define (named-bitmap-save a-named-bitmap a-dir)
(let ([a-path
(build-path a-dir (named-bitmap-name a-named-bitmap))])
(send (named-bitmap-bitmap a-named-bitmap) save-file (path->string a-path)
'png)))
(define make-image-name
(let ([i 0])
(lambda ()
(begin0 (string-append "image-" (number->string i) ".png")
(set! i (add1 i))))))
(define (image-snip? a-snip)
(or (is-a? a-snip image-snip%)
(is-a? a-snip cache-image-snip%)))