Skip to content
This repository has been archived by the owner on Feb 26, 2024. It is now read-only.

copy image to clipboard example #3

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3,160 changes: 3,160 additions & 0 deletions 0.3/copy_image_to_clipboard/Cargo.lock

Large diffs are not rendered by default.

16 changes: 16 additions & 0 deletions 0.3/copy_image_to_clipboard/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[package]
name = "copy_image_to_clipboard"
version = "0.1.0"
authors = ["David Jaffe <[email protected]>"]
edition = "2018"

[dependencies]
iced = { version = "0.3", features = ["svg"] }
libc = "0.2"
resvg = { git = "https://github.com/RazrFalcon/resvg", rev = "6b29007311edc5022635362fe56f6e5c0318fdeb" }
tiny-skia = "0.5.0"
usvg = { git = "https://github.com/RazrFalcon/resvg", rev = "6b29007311edc5022635362fe56f6e5c0318fdeb" }

[target.'cfg(any(target_os = "macos", target_os = "ios"))'.dependencies]
cocoa = "0.24"
mach = "0.3"
13 changes: 13 additions & 0 deletions 0.3/copy_image_to_clipboard/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Clipboard copying

Illustrate a button that converts an SVG to a PNG and copies that to the clipboard.

As implemented, the clipboard copying only works on a Mac.

This includes code copied with small changes from the resvg and pasteboard crates.

Run with `cargo run --release --package copy_image_to_clipboard`.

<div align="center">
<img src="https://github.com/iced-rs/cookbook/blob/main/0.3/copy_image_to_clipboard/img/example.png">
</div>
1 change: 1 addition & 0 deletions 0.3/copy_image_to_clipboard/img/README
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
quad_hive.svg is taken from https://10xgenomics.github.io/enclone/pages/auto/plot.html
Binary file added 0.3/copy_image_to_clipboard/img/example.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3,005 changes: 3,005 additions & 0 deletions 0.3/copy_image_to_clipboard/img/quad_hive.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
45 changes: 45 additions & 0 deletions 0.3/copy_image_to_clipboard/src/convert_svg_to_png.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// This code is pretty much copied from the resvg crate,
// rev = 6b29007311edc5022635362fe56f6e5c0318fdeb, done June 14, 2021.

use usvg::SystemFontDB;

pub fn convert_svg_to_png(svg: &[u8]) -> Vec<u8> {
let fontdb = load_fonts();
let usvg = usvg::Options {
resources_dir: None,
dpi: 96.0,
font_family: "Arial".to_string(),
font_size: 12.0,
languages: vec!["en".to_string()],
shape_rendering: usvg::ShapeRendering::default(),
text_rendering: usvg::TextRendering::default(),
image_rendering: usvg::ImageRendering::default(),
keep_named_groups: false,
fontdb,
};
let tree = usvg::Tree::from_data(&svg, &usvg).unwrap();
let fit_to = usvg::FitTo::Original;
let size = fit_to
.fit_to(tree.svg_node().size.to_screen_size())
.unwrap();
let mut pixmap = tiny_skia::Pixmap::new(size.width(), size.height()).unwrap();
// set background to white
pixmap.fill(tiny_skia::Color::from_rgba8(255, 255, 255, 255));
resvg::render(&tree, fit_to, pixmap.as_mut());
pixmap.encode_png().unwrap()
}

fn load_fonts() -> usvg::fontdb::Database {
let mut fontdb = usvg::fontdb::Database::new();
// commented out lines show how one might add a font
// let deja = include_bytes!("../../fonts/DejaVuLGCSansMono.ttf").to_vec();
// fontdb.load_font_data(deja);
fontdb.load_system_fonts();
fontdb.set_generic_families();
fontdb.set_serif_family("Times New Roman");
fontdb.set_sans_serif_family("Arial");
fontdb.set_cursive_family("Comic Sans MS");
fontdb.set_fantasy_family("Impact");
fontdb.set_monospace_family("Courier New");
fontdb
}
40 changes: 40 additions & 0 deletions 0.3/copy_image_to_clipboard/src/copy_image_to_clipboard.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// This code is copied with small changes from the pasteboard crate. As implemented, it only
// works on a Mac.
//
// The same code presumably works for image types other than PNG, but has only been tested on PNG.

#[cfg(any(target_os = "macos", target_os = "ios"))]
use cocoa::{
appkit::{NSImage, NSPasteboard},
base::nil,
foundation::{NSArray, NSAutoreleasePool, NSData},
};

#[cfg(any(target_os = "macos", target_os = "ios"))]
use libc::c_void;

#[cfg(any(target_os = "macos", target_os = "ios"))]
pub fn copy_png_bytes_to_mac_clipboard(bytes: &[u8]) {
if bytes.len() > 0 {
unsafe {
let pool = NSAutoreleasePool::new(nil);
let data = NSData::dataWithBytes_length_(
pool,
bytes.as_ptr() as *const c_void,
bytes.len() as u64,
);
let object = NSImage::initWithData_(NSImage::alloc(pool), data);
if object != nil {
let pasteboard = NSPasteboard::generalPasteboard(pool);
pasteboard.clearContents();
pasteboard.writeObjects(NSArray::arrayWithObject(pool, object));
} else {
eprintln!("\ncopy to pasteboard failed\n");
std::process::exit(1);
}
}
}
}

#[cfg(not(any(target_os = "macos", target_os = "ios")))]
pub fn copy_png_bytes_to_mac_clipboard(_bytes: &[u8]) {}
2 changes: 2 additions & 0 deletions 0.3/copy_image_to_clipboard/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub mod convert_svg_to_png;
pub mod copy_image_to_clipboard;
54 changes: 54 additions & 0 deletions 0.3/copy_image_to_clipboard/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
use copy_image_to_clipboard::convert_svg_to_png::*;
use copy_image_to_clipboard::copy_image_to_clipboard::*;
use iced::svg::Handle;
use iced::{button, Button, Column, Container, Element, Length, Row, Sandbox, Settings, Svg, Text};

pub fn main() -> iced::Result {
Copier::run(Settings::default())
}

#[derive(Default)]
struct Copier {
button: button::State,
}

#[derive(Debug, Clone, Copy)]
enum Message {
ButtonPressed,
}

impl Sandbox for Copier {
type Message = Message;

fn new() -> Self {
Copier::default()
}

fn title(&self) -> String {
String::from("Copier")
}

fn update(&mut self, message: Message) {
match message {
Message::ButtonPressed => {
let svg_bytes = include_bytes!["../img/quad_hive.svg"].to_vec();
let png = convert_svg_to_png(&svg_bytes);
copy_png_bytes_to_mac_clipboard(&png);
}
}
}

fn view(&mut self) -> Element<Message> {
let button = Button::new(&mut self.button, Text::new("Copy"))
.padding(10)
.on_press(Message::ButtonPressed);
let svg_bytes = include_bytes!["../img/quad_hive.svg"].to_vec();
let svg = Svg::new(Handle::from_memory(svg_bytes));
let row = Row::new().push(svg).push(button);
let content = Column::new().push(row);
Container::new(content)
.width(Length::Fill)
.height(Length::Fill)
.into()
}
}