#lang scheme/base
(require scheme/class
scheme/gui/base
scheme/list
scheme/port
mrlib/cache-image-snip
scheme/contract
"utils.ss"
"resource.ss"
"collects/moby/runtime/stx.ss")
(define-struct named-bitmap (name bitmap))
(provide/contract [struct named-bitmap [(name string?)
(bitmap (is-a?/c bitmap%))]]
[named-bitmap->resource (named-bitmap? . -> . (is-a?/c resource<%>))]
[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 named-bitmap-resource%
(class* object% (resource<%>)
(init-field named-bitmap)
(super-new)
(define/public (save! a-path)
(named-bitmap-save named-bitmap a-path))
(define/public (get-name)
(named-bitmap-name named-bitmap))
(define/public (get-bytes)
(with-temporary-directory
(lambda (a-dir)
(save! a-dir)
(call-with-input-file (build-path a-dir (get-name))
(lambda (ip)
(port->bytes ip))))))))
(define (named-bitmap->resource a-named-bitmap)
(new named-bitmap-resource% [named-bitmap a-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 (datum->stx #f 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 (datum->stx #f `(open-image-url ,filename)
(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%)))