For future reference: WIP branch of copy/pasting a mixture of images and text: https://github.com/zed-industries/zed/tree/copy-paste-images - we'll come back to that one after landing this one. Release Notes: - You can now paste images into the Assistant Panel to include them as context. Currently works only on Mac, and with Anthropic models. Future support is planned for more models, operating systems, and image clipboard operations. --------- Co-authored-by: Antonio <antonio@zed.dev> Co-authored-by: Mikayla <mikayla@zed.dev> Co-authored-by: Jason <jason@zed.dev> Co-authored-by: Kyle <kylek@zed.dev>
99 lines
2.6 KiB
Rust
99 lines
2.6 KiB
Rust
use crate::{size, DevicePixels, Result, SharedString, Size};
|
|
use smallvec::SmallVec;
|
|
|
|
use image::{Delay, Frame};
|
|
use std::{
|
|
borrow::Cow,
|
|
fmt,
|
|
hash::Hash,
|
|
sync::atomic::{AtomicUsize, Ordering::SeqCst},
|
|
};
|
|
|
|
/// A source of assets for this app to use.
|
|
pub trait AssetSource: 'static + Send + Sync {
|
|
/// Load the given asset from the source path.
|
|
fn load(&self, path: &str) -> Result<Option<Cow<'static, [u8]>>>;
|
|
|
|
/// List the assets at the given path.
|
|
fn list(&self, path: &str) -> Result<Vec<SharedString>>;
|
|
}
|
|
|
|
impl AssetSource for () {
|
|
fn load(&self, _path: &str) -> Result<Option<Cow<'static, [u8]>>> {
|
|
Ok(None)
|
|
}
|
|
|
|
fn list(&self, _path: &str) -> Result<Vec<SharedString>> {
|
|
Ok(vec![])
|
|
}
|
|
}
|
|
|
|
/// A unique identifier for the image cache
|
|
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
|
pub struct ImageId(usize);
|
|
|
|
#[derive(PartialEq, Eq, Hash, Clone)]
|
|
pub(crate) struct RenderImageParams {
|
|
pub(crate) image_id: ImageId,
|
|
pub(crate) frame_index: usize,
|
|
}
|
|
|
|
/// A cached and processed image, in BGRA format
|
|
pub struct RenderImage {
|
|
/// The ID associated with this image
|
|
pub id: ImageId,
|
|
data: SmallVec<[Frame; 1]>,
|
|
}
|
|
|
|
impl PartialEq for RenderImage {
|
|
fn eq(&self, other: &Self) -> bool {
|
|
self.id == other.id
|
|
}
|
|
}
|
|
|
|
impl Eq for RenderImage {}
|
|
|
|
impl RenderImage {
|
|
/// Create a new image from the given data.
|
|
pub fn new(data: impl Into<SmallVec<[Frame; 1]>>) -> Self {
|
|
static NEXT_ID: AtomicUsize = AtomicUsize::new(0);
|
|
|
|
Self {
|
|
id: ImageId(NEXT_ID.fetch_add(1, SeqCst)),
|
|
data: data.into(),
|
|
}
|
|
}
|
|
|
|
/// Convert this image into a byte slice.
|
|
pub fn as_bytes(&self, frame_index: usize) -> Option<&[u8]> {
|
|
self.data
|
|
.get(frame_index)
|
|
.map(|frame| frame.buffer().as_raw().as_slice())
|
|
}
|
|
|
|
/// Get the size of this image, in pixels.
|
|
pub fn size(&self, frame_index: usize) -> Size<DevicePixels> {
|
|
let (width, height) = self.data[frame_index].buffer().dimensions();
|
|
size(width.into(), height.into())
|
|
}
|
|
|
|
/// Get the delay of this frame from the previous
|
|
pub fn delay(&self, frame_index: usize) -> Delay {
|
|
self.data[frame_index].delay()
|
|
}
|
|
|
|
/// Get the number of frames for this image.
|
|
pub fn frame_count(&self) -> usize {
|
|
self.data.len()
|
|
}
|
|
}
|
|
|
|
impl fmt::Debug for RenderImage {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
f.debug_struct("ImageData")
|
|
.field("id", &self.id)
|
|
.field("size", &self.size(0))
|
|
.finish()
|
|
}
|
|
}
|