+;;; JPEG support
+
+(define-callback jpeg-stream-write-func unsigned
+ ((stream-id pointer-data) (data pointer) (length unsigned-int))
+ (%stream-write-func stream-id data length))
+
+(define-callback jpeg-stream-read-func unsigned
+ ((stream-id pointer-data) (data pointer) (length unsigned-int))
+ (%stream-read-func stream-id data length))
+
+(defbinding %image-surface-create-from-jpeg () pointer
+ (filename pathname)
+ (status status-signal :out))
+
+(defbinding %image-surface-create-from-jpeg-stream (stream) pointer
+ (jpeg-stream-read-func callback)
+ (stream pointer-data)
+ (status status-signal :out))
+
+(defgeneric surface-write-to-jpeg (surface dest &key quality interlace))
+
+(defun %surface-acquire-image (surface)
+ (typecase surface
+ (image-surface surface)
+ ((let ((image (make-instance 'image-surface
+ :width (surface-width surface)
+ :height (surface-height surface)
+ :format :argb32)))
+ (with-surface (image cr)
+ (set-source-surface cr surface)
+ (setf (operator cr) :source)
+ (paint cr))
+ image))))
+
+(defbinding %surface-write-to-jpeg () status-signal
+ (surface image-surface)
+ (filename pathname)
+ (param jpeg-parameter))
+
+(defmethod surface-write-to-jpeg (surface filename &key
+ (quality 75) (interlace t))
+ (let ((param (make-instance 'jpeg-parameter
+ :quality quality :interlace interlace)))
+ (%surface-write-to-jpeg (%surface-acquire-image surface) filename param)))
+
+(defbinding %surface-write-to-jpeg-stream (surface stream param) status-signal
+ (surface surface)
+ (jpeg-stream-write-func callback)
+ (stream pointer-data)
+ (param jpeg-parameter))
+
+(defmethod surface-write-to-jpeg (surface (stream stream) &key
+ (quality 75) (interlace t))
+ (let ((stream-id (register-user-data stream))
+ (param (make-instance 'jpeg-parameter
+ :quality quality :interlace interlace)))
+ (unwind-protect
+ (%surface-write-to-jpeg-stream (%surface-acquire-image surface) stream-id param)
+ (destroy-user-data stream-id))))
+
+