#lang racket/base (require racket/gui/base racket/class racket/file setup/main-collects) (require (for-syntax racket/base syntax/path-spec compiler/cm-accomplice setup/main-collects)) (provide include-bitmap include-bitmap/relative-to) (define-syntax (-include-bitmap stx) (syntax-case stx () [(_ orig-stx source path-spec type) (let* ([c-file (resolve-path-spec #'path-spec #'source #'orig-stx)] [content (with-handlers ([exn:fail? (lambda (exn) (error 'include-bitmap "could not load ~e: ~a" c-file (if (exn? exn) (exn-message exn) (format "~e" exn))))]) (with-input-from-file c-file (lambda () (read-bytes (file-size c-file)))))]) (register-external-file c-file) (with-syntax ([content content] [c-file (path->main-collects-relative c-file)]) (syntax/loc stx (get-or-load-bitmap content 'path-spec type))))])) (define-syntax (include-bitmap/relative-to stx) (syntax-case stx () [(_ source path-spec) #`(-include-bitmap #,stx source path-spec 'unknown/mask)] [(_ source path-spec type) #`(-include-bitmap #,stx source path-spec type)])) (define-syntax (include-bitmap stx) (syntax-case stx () [(_ path-spec) #`(-include-bitmap #,stx #,stx path-spec 'unknown/mask)] [(_ path-spec type) #`(-include-bitmap #,stx #,stx path-spec type)])) ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Run-time support (define cached (make-hash)) (define (get-or-load-bitmap content orig type) (hash-ref cached (cons content type) (λ () (define-values (in out) (make-pipe)) (thread (λ () (display content out) (close-output-port out))) (define bm (make-object bitmap% in type)) (unless (send bm ok?) (error 'include-bitmap "unable to parse image, originated from: ~a" (path->string (main-collects-relative->path orig)))) (hash-set! cached (cons content type) bm) bm)))