fschutt / printpdf Goto Github PK
View Code? Open in Web Editor NEWAn easy-to-use library for writing PDF in Rust
Home Page: https://docs.rs/printpdf/
License: MIT License
An easy-to-use library for writing PDF in Rust
Home Page: https://docs.rs/printpdf/
License: MIT License
I'm trying out some of the examples, however the library does not seem willing to compile.
Compiling printpdf v0.1.6
error[E0308]: mismatched types
--> C:\Users\***\.cargo\registry\src\github.com-1ecc6299db9ec823\printpdf-0.1.6\src\types\pl
ugins\graphics\two_dimensional\font.rs:119:39
|
119 | ("Ascent".into(), Integer(face_metrics.ascender)),
| ^^^^^^^^^^^^^^^^^^^^^ expected i64, found i32
error[E0308]: mismatched types
--> C:\Users\***\.cargo\registry\src\github.com-1ecc6299db9ec823\printpdf-0.1.6\src\types\pl
ugins\graphics\two_dimensional\font.rs:120:40
|
120 | ("Descent".into(), Integer(face_metrics.descender)),
| ^^^^^^^^^^^^^^^^^^^^^^ expected i64, found i32
error[E0308]: mismatched types
--> C:\Users\***\.cargo\registry\src\github.com-1ecc6299db9ec823\printpdf-0.1.6\src\types\pl
ugins\graphics\two_dimensional\font.rs:121:42
|
121 | ("CapHeight".into(), Integer(face_metrics.ascender)),
| ^^^^^^^^^^^^^^^^^^^^^ expected i64, found i32
error[E0308]: mismatched types
--> C:\Users\***\.cargo\registry\src\github.com-1ecc6299db9ec823\printpdf-0.1.6\src\types\pl
ugins\graphics\two_dimensional\font.rs:258:51
|
258 | let font_bbox = vec![ Integer(0), Integer(max_height), Integer(total_width as i64),
Integer(max_height) ];
| ^^^^^^^^^^ expected i64, found i32
error[E0308]: mismatched types
--> C:\Users\***\.cargo\registry\src\github.com-1ecc6299db9ec823\printpdf-0.1.6\src\types\pl
ugins\graphics\two_dimensional\font.rs:258:101
|
258 | let font_bbox = vec![ Integer(0), Integer(max_height), Integer(total_width as i64),
Integer(max_height) ];
|
^^^^^^^^^^ expected i64, found i32
error: aborting due to 5 previous errors
error: Could not compile `printpdf`.
To learn more, run the command again with --verbose.
This can most likely be fixed pretty fast with type coercions.
I’m currently working on genpdf
, a document generator and layout engine built on top of printpdf
.
In #2, you wrote:
I'd also really like to do layout in a seperate library, not in
printpdf
- this library should only contain what the PDF spec says and contain the "primitives" for building a PDF. Anything fancy, like tables, page breaks, etc. should be done in a seperate library.
I think this applies to most features in genpdf
, but there are some genpdf
features that might be useful for printpdf
:
TextSection
type to ensure matching begin_text_section()
and end_text_section()
calls* Edit: I just saw that you already said that you don’t want to include this in printpdf
Also, I plan to implement these features for genpdf
that could be added to printpdf
instead:
Are you interested in adding any of these features to printpdf
?
If I run
extern crate printpdf;
fn main() {
println!("Hello, world!");
use printpdf::*;
use std::fs::File;
use std::io::{self, BufRead, BufWriter};
let (doc, page1, layer1) = PdfDocument::new("printpdf graphics test", Mm(210.0), Mm(297.0), "Layer 1");
let current_layer = doc.get_page(page1).get_layer(layer1);
let font = doc.add_external_font(File::open("OCRAStd.ttf").unwrap()).unwrap();
let mut image_file = File::open("card-retro.bmp").unwrap();
let image = Image::try_from(image::bmp::BMPDecoder::new(&mut image_file)).unwrap();
image.add_to_layer(current_layer.clone(), Some(Mm(15.0)), Some(Mm(232.0)), None, None, None, Some(600.0));
let fill_color = Color::Cmyk(Cmyk::new(0.0, 0.0, 0.0, 0.0, None));
current_layer.set_fill_color(fill_color);
let stdin = io::stdin();
let nome = stdin.lock().lines().next().unwrap().unwrap();
let lunghezza_nome = nome.len();
current_layer.use_text(nome, 12, Mm(15.0+(85.6-85.6*(lunghezza_nome as f64)/28.0)/2.0), Mm(240.0), &font);
current_layer.use_text("00001", 12, Mm(31.5), Mm(248.5), &font);
current_layer.use_text("124912", 12, Mm(56.5), Mm(248.5), &font);
// translate x, translate y, rotate, scale x, scale y
// by default, an image is optimized to 300 DPI (if scale is None)
// rotations and translations are always in relation to the lower left corner
let mut image_file_retro = File::open("card-retro.bmp").unwrap();
let image_retro = Image::try_from(image::bmp::BMPDecoder::new(&mut image_file_retro)).unwrap();
// translate x, translate y, rotate, scale x, scale y
// by default, an image is optimized to 300 DPI (if scale is None)
// rotations and translations are always in relation to the lower left corner
image_retro.add_to_layer(current_layer.clone(), Some(Mm(100.6)), Some(Mm(232.0)), None, None, None, Some(600.0));
doc.save(&mut BufWriter::new(File::create("test_working.pdf").unwrap())).unwrap();
}
the image looks wrong (macOS Preview app loads it but it looks like it encoded about 10% of the image while Adobe Acrobat X complains that there isn't enough image data)
The image above is what is shown in Preview.app
test_working.pdf
card-retro.bmp.zip
printpdf
currently uses rusttype
0.8 that is no longer maintained. I experimented with updating rusttype
to 0.9. It seems to work fine, but I noticed that ab_glyph
is rusttype
’s more efficient successor (by the same author). Then I noticed that printpdf
doesn’t really need rusttype
or ab_glyph
because they mainly deal with font rendering and rasterization. Instead it could directly use ttf-parser
.
So my questions are:
rusttype
0.8?printpdf
rusttype
0.9,ab_glyph
orttf-parser
?So I'm wondering if there is a way to either support word wrapping when writing text so newlines are automatically inserted, or provide some metrics around glyph sizes so it can be handled externally.
The idea is to be able to support a paragraph of text which wraps when the width is full.
Supporting centered and right aligned text is an obvious extension of this, but is harder to do.
When writing untrusted user input to a PDF file with write_text
, are there any security implications? Should the user escape or remove some control characters, or will all characters be interpreted as a string?
I just did
cargo run --example fonts
and then
firefox test_fonts.pdf
and the file is broken.
The same happens to us in production with external partner's pdf reader software.
Is it possible to use hyperlinks within the pdf? When I use the url directly in the string for use_text()
, it is clickable, but I would like to display other text that opens the link when clicked.
I am generating a large pdf where every page consists of the same layout with only the text varying. Is it possible to insert the bitmap only once in order to speed up generation of the file?
specifically, I'm currently using add_to_layer once per page. And noticed that when I use a bitmap of smaller size, the speedup is enormous. However, I understand the documentation so that perhaps this is a limitation of the PDF format?
Adds the image to a specific layer and consumes it This is due to a PDF weirdness - images are basically just "names" and you have to make sure that they are added to the same page as they are used on.
And printpdf::types::plugins::graphics::two_dimensional::image::Image::add_to_layer
consumes the image.
So if you would be so kind to tell me whether it is technically possible, I might try to read up on that and create a PR if it is :)
Thank you so much for the time you invested into this library!
Hi. I'm trying to generate a pdf and insert an image, but it simply doesn't seem to work. The code is almost just a copy/paste from the documentaion. I do not have a pure linux machine, but I have tested it on windows and the windows subsystem for linux. In both cases the code compiles, runs, reads an image and produces a pdf document - albeit a completely empty one.
I have attached both the image I run the code with all well as the pdf I produce.
The code is located in a test and looks like this:
#[tokio::test]
async fn test_pdf() {
let mut pdf_source = PathBuf::from(&env!("CARGO_MANIFEST_DIR").to_owned());
pdf_source.push("out");
pdf_source.push("codes");
pdf_source.set_extension("pdf");
let file = File::create(pdf_source).unwrap();
log::debug!("Writing pdf to location: {:?}", file);
let doc = make_pdf();
let res = save_pdf(doc, file);
assert!(res.is_ok());
}
pub fn make_pdf() -> PdfDocumentReference { // qrcodes: Vec<QrCode>
let (doc, page1, layer1) = PdfDocument::new("PDF_Document_title", Mm(210.0), Mm(297.0), "Layer 1");
let current_layer = doc.get_page(page1).get_layer(layer1);
// currently, the only reliable file format is bmp (jpeg works, but not in release mode)
// this is an issue of the image library, not a fault of printpdf
//let mut image_file = File::open("C:\\Users\\arbo\\Google Drive\\qrgithub\\assets\\pdf-img.bmp").unwrap();
//let image = Image::try_from(image::bmp::BmpDecoder::new(&mut image_file).unwrap()).unwrap();
let image_bytes = include_bytes!("/mnt/c/Users/arbo/Google Drive/qrgithub/assets/pdf-img.bmp");
let mut reader = Cursor::new(image_bytes.as_ref());
let decoder = BmpDecoder::new(&mut reader).unwrap();
let image2 = Image::try_from(decoder).unwrap();
log::debug!("decoded image: {:?}", image2);
// translate x, translate y, rotate, scale x, scale y
// by default, an image is optimized to 300 DPI (if scale is None)
// rotations and translations are always in relation to the lower left corner
image2.add_to_layer(current_layer, Some(Mm(100.0)), Some(Mm(100.0)), None, None, None, None);
doc
}
pub fn save_pdf(doc: PdfDocumentReference, file: File) -> Result<(), Error> {
let res = doc.save(&mut BufWriter::new(file));
res
}
It's annoying to convert the image to BMP beforehand. Would be nice to have the ability to add also PNG and JPG images. What about using image-rs crate for this?
image
provides implementations of common image format encoders and decoders.
Format | Decoding | Encoding |
---|---|---|
PNG | All supported color types | Same as decoding |
JPEG | Baseline and progressive | Baseline JPEG |
GIF | Yes | Yes |
BMP | Yes | RGB(8), RGBA(8), Gray(8), GrayA(8) |
ICO | Yes | Yes |
TIFF | Baseline(no fax support) + LZW + PackBits | RGB(8), RGBA(8), Gray(8) |
Webp | Lossy(Luma channel only) | No |
PNM | PBM, PGM, PPM, standard PAM | Yes |
ImageDecoder
TraitAll image format decoders implement the ImageDecoder
trait which provides the following methods:
image
provides the following pixel types:
i want to donate 20 usd, better in crypto
Regarding "1.1.1 Hello World PDF", I would like to know how the xref is calculated manually. You said that each object is 20-byte long. I can not verify that in the table
xref
0 7
0000000000 65535 f
0000000009 00000 n
0000000050 00000 n
0000000102 00000 n
0000000268 00000 n
0000000374 00000 n
0000000443 00000 n
Are these number in Hex? 9-0
is not 20 and also 50-9
isn't 20 bytes.
To be able to reproducibly generate a PDF document, e. g. for unit tests, it would be good to be able to set the creation date. If you don’t have any objections, I can try to implement this.
I have been wondering if it would be possible to get the length of a line of text for a certain font and at a certain font size.
Something along the lines of
get_length( text: String, font_size: i64 , font: &IndirectFontRef) -> Mm;
Any idea how I might go about implementing something like this ?
Or where I should start ?
I'm newish to rust, but I'm keen to give it a shot.
The add_builtin_font
method of the PdfDocumentReference
struct returns a Result
but as far as I see, it cannot fail. Would you accept a PR that refactors the method and removes the Result
?
Hi,
I would like to use the "evenodd" filling rule for a path. Skimming through the code the corresponding operations already seem to be defined but the Line
API only uses only "nonzero" filling at the moment.
I also have some time to create a PR for this if you want, but I would need your opinion on how the API should change and if an API break would be fine. Alternatively, I could also work with access to the low level Operation
.
Edit: On second look, I also need the "close" and "move" semantics.
Latest nightly has broken compatability with TryFrom
TODO: Fix this. See rust-lang/rust#33417 (comment)
I'd like to draw shapes with line thickness of ~0.08mm, but the line thickness setting accepts an i64, of which any value <= 0 seems to have the same result, which is still too thick. The unit for this setting isn't documented, so I'm not sure if it's supposed to be pt or mm (or neither, since 0 wouldn't be visible if it was a normal unit).
Hi, I just saw that you released the 0.3.4 version, could you please update it crates.io, so I can use it in a crate?
Hello 👍 tried to get this running on Windows but it's mostly a no-go because of freetype. Any chance of using something friendlier 🤒
I found only PDFDocument::new() and empty(). Is that possible to load a document for manipulation?
Is there any way to do table with printpdf?
First of all, thanks for this very useful crate!
I noticed that every embedded fonts adds about ~ 150–200 KiB to the size of the output file. This quickly leads to a quite large file when using multiple fonts. Running the generated file through ps2pdf
reduces the file size to some KiB. As far as I see, this is because printpdf
embeds every available glyph into the PDF file.
Would it be possible to keep track of the used characters and only embed the glyphs for the required characters?
No matter what I do, generated PDF files are large. 660KB in debug mode, 490KB in release mode on macOS.
use printpdf::*;
use std::fs::File;
use std::io::BufWriter;
let (doc, page1, layer1) = PdfDocument::new("PDF_Document_title", Mm(247.0), Mm(210.0), "Layer 1");
let (page2, layer1) = doc.add_page(Mm(10.0), Mm(250.0),"Page 2, Layer 1");
doc.save(&mut BufWriter::new(File::create("test_working.pdf").unwrap())).unwrap();
This produces test_working.pdf
with size of 660KB ( debug mode )
What's the reason PdfDocument::new
also creates the first page. Is there a way to create an empty document?
I'm writing something that reads in a CSV and creates a document with a page per CSV row. Things would be a little easier if the first page wasn't automatically created for me.
The line drawing API currently has a bug where you can't draw a circle - the last point doesn't get connected to the first point. Need to investigate this and do a circle drawing example.
For drawing maps, this is currently not important, however, it may become important later on.
I love this library it's easy to use and understand, perfect. The only issue I'm running into currently is multiline strings e.g.
let text_source_address = "610 Monroe St.\nStoudsburg, PA 18630-2115";
The output from:
current_layer.use_text(text_source_address, 10, Mm(30.0), Mm(230.0), &font);
is:
610 Monroe St. Stoudsburg, PA 18630-2115
Ideas?
Thank you for your efforts
It seems the PDF built-in fonts use the ISO-8859-1 encoding which causes output of a lot of "national" characters look wrong. Could printpdf be modified to check if the selected font is built-in and then translate the String contents into something that looks right on output? If the String contains characters not available in ISO-8859-1 they could maybe just be discarded?
The recoding of the String is quite straightforward - if the character code value is less than 256 then use it, otherwise discard it (or replace with NBSP or something else?).
If the chosen built-in font is 'Symbol' or 'Zapf Dingbats' then something more convoluted may have to be done, if at all.
Hi, when I create a PDF on my locale machine with som images, everything works fine.
But when the same program was executed on AWS Lambda, the images was not completely rendered
maybe this come from outdated image dependency
i have build my own to render some stuff and mapped it to printpdf stuff. but if printpdf will use that out of box could be cool
Reading opentype fonts(.otf) or truetype collection files (.ttc) causes panic!
let mut font_reader = std::io::Cursor::new(include_bytes!("../assets/fonts/Cantarell-Bold.otf").as_ref());
let font = doc.add_external_font(&mut font_reader).unwrap();
The second line caused panic, and retrun Rusttype(IllFormed).
I tried .ttc file and this also failed.
Hey,
Would be great with a example for rendering SVG.
Hi,
Thanks for the awesome library. One feature that I would really like is bookmarks in the pdf that you can put on a page. This bookmark shows up on the left of the page in firefox and is accessible on the kindle very easily with the goto
menu. (The kindle is my use case.)
I do not know how simple this would be to implement, but it doesn't seem that hard.
Thanks so much.
for reference, here is how the feature looks in firefox (on the left there is a list of pages)
And if it helps, my use case is making a code renderer that can render source code for a project in a pdf file so it can be read on a kindle, so I would like it to be able to jump around quickly with bookmarks.
Edit:
Just saw this is in the TODOs. I could try to implement this if you could give me a little background, since I know very little about pdfs. I think there could be a function for a page called set_bookmark
that just sets a bookmark on a page and accepts a &str
for the name of the bookmark.
@fschutt Are you okay If I attempt to refactor the library such that PageRef
and LayerRef
types actually use rust life times instead of Rc<>
? This would obviously be a breaking change but I believe it would more accurately communicate mutability and ownership of the referenced data.
Sometimes, when generating PDFs, character placement seems to become broken, or there are extra spaces inserted. Attached are two images; one showing the expected result and the other the strange result.
The PDFs these images were cut from were generated with the exact same code. The only thing differing between the generated PDFs should be a serial number high up on the page (which I cropped when converting PDF to JPG). The string "Godkänd för F-skatt" is a literal string in the code; it was added to the PDF like this (The font used is "LiberationSans-Bold.ttf"):
current_pdf_layer.use_text("Godkänd för F-skatt".to_string(), 10, Mm(155.0), Mm(56.0), &font_lib_sans_bold);
For generating JPGs from PDFs I did
gm convert -crop 595x692+0+150 "$pdf" "$pdf".jpg
For a test run I generated 800 PDFs and noticed that 716 were looking as expected but the rest were not (and those, in turn, were often differing in different places).
My system is xubuntu 19.10. All software should be up to date.
The documentation clearly states that the set_word_spacing
method (implemented for pdf_layer
) is not operational. However, examples on the front page of the documentation show the method being used.
Is it safe to use set_word_spacing
?
error: expected an item keyword
--> /home/qtfkwk/.cargo/registry/src/github.com-1ecc6299db9ec823/time-0.2.8/src/utc_offset.rs:366:13
|
366 | let tm = timestamp_to_tm(datetime.timestamp())?;
| ^^^
|
::: /home/qtfkwk/.cargo/registry/src/github.com-1ecc6299db9ec823/cfg-if-0.1.9/src/lib.rs:41:40
|
41 | if #[cfg($($meta:meta),*)] { $($it:item)* }
| -------- while parsing argument for this `item` macro fragment
error: aborting due to previous error
error: could not compile `time`.
This is relatively consistent on both a Windows 10 Debian WSL and a Linux laptop, both with Rust 1.44 stable. I say relatively because for some reason the build succeeds somehow sometimes, but no idea why.
I have a question regarding the design of the library. I'll start my question by describing what I'm trying to do.
I'm writing a small rust API which generates a PDF report. It's pretty straight forward, you throw data at it and it should spit out a PDF.
To do this created a simple struct Report
, my goal is to be able to call add_data
on my Report
struct and that it automatically appends data and new pages (if needed) to the report.
This is the place where I get stuck with this library. To save the current page in my struct I need to be able to access PdfPageIndex
from my application, which is not possible.
As far as I understood indices.rs are meant for internal use only.
However they're marked with pub
. Also the public api to create a Pdf document returns a PdfPageIndex
. In my opinion it's not logical to not export a type that's used in the public API.
I think a good solution would be to make indices
public instead of private. Another option would be to write some public wrapper structs that can be used in external applications. Otherwise we're restricted to write most of the code in one method, which isn't really good practice.
Current Readme states:
// text, font size, x from left edge, y from top edge, font
current_layer.use_text(text, 48, Mm(200.0), Mm(200.0), &font);
But actually, reducing the fourth argument makes the text move downwards, not upwards.
I created this as an issue instead of a PR because I don't want to fork the project just for this minor change. Thanks for your library! :)
Text using embedded fonts is not displayed correctly in iOS, like that one:
target_date.pdf
which looks like this in iOS:
when it should look like this:
I made it display correctly by a roundtrip through pdf2ps and ps2pdf, which also made the file 20 times smaller.
printpdf version: 0.3.3
If I try to add a png with transparency, the image wouldn't shown. Other png files works fine.
let mut image_file = File::open("test.png").unwrap();
let image = Image::try_from(image::png::PngDecoder::new(&mut image_file).unwrap()).unwrap();
image.add_to_layer(current_layer.clone(), Some(Mm(x)), Some(Mm(y)), None, Some(1.0), Some(1.0), Some(300.0));
Hi,
For a project I need to know the width of a string for a given font and font size, so I can split the string into multiple lines, typically when the string is much wider than the page.
I checked the crate's documentation but I haven't found anything about it.
If this feature doesn't exist in this crate or one of its dependencies is there anything about getting at least the width of a char. If not what would be the best approach to solve this issue.
Thanks for the help.
I'm trying to calculate how often x fits into y and would expect a float:
let a: f64 = Mm(x) / Mm(y);
But somehow it seems not possible. Is this not implemented?
Is there a workaround?
Or am I doing sth wrong?
I have also problems when multiplying: let b: Mm = Mm(x) * y: f64
From looking at some of the issued
here, I see that it looks like to get the font metrics, I would need to use azul-text-layout
but, in attempting this, I get the following error:
error: failed to run custom build command for `servo-freetype-sys v4.0.5`
Caused by:
process didn't exit successfully: `E:\proj\target\debug\build\servo-freetype-sys-b4e8d742cf1d3c83\build-script-build` (exit code: 101)
--- stdout
cargo:rerun-if-env-changed=FREETYPE2_NO_PKG_CONFIG
cargo:rerun-if-env-changed=PKG_CONFIG
cargo:rerun-if-env-changed=FREETYPE2_STATIC
cargo:rerun-if-env-changed=FREETYPE2_DYNAMIC
cargo:rerun-if-env-changed=PKG_CONFIG_ALL_STATIC
cargo:rerun-if-env-changed=PKG_CONFIG_ALL_DYNAMIC
cargo:rerun-if-env-changed=PKG_CONFIG_PATH_x86_64-pc-windows-msvc
cargo:rerun-if-env-changed=PKG_CONFIG_PATH_x86_64_pc_windows_msvc
cargo:rerun-if-env-changed=HOST_PKG_CONFIG_PATH
cargo:rerun-if-env-changed=PKG_CONFIG_PATH
cargo:rerun-if-env-changed=PKG_CONFIG_LIBDIR_x86_64-pc-windows-msvc
cargo:rerun-if-env-changed=PKG_CONFIG_LIBDIR_x86_64_pc_windows_msvc
cargo:rerun-if-env-changed=HOST_PKG_CONFIG_LIBDIR
cargo:rerun-if-env-changed=PKG_CONFIG_LIBDIR
cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR_x86_64-pc-windows-msvc
cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR_x86_64_pc_windows_msvc
cargo:rerun-if-env-changed=HOST_PKG_CONFIG_SYSROOT_DIR
cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR
running: "cmake" "C:\\Users\\user\\.cargo\\registry\\src\\github.com-1ecc6299db9ec823\\servo-freetype-sys-4.0.5\\freetype2" "-G" "Visual Studio 16 2019" "-Thost=x64" "-Ax64" "-DWITH_BZip2=OFF" "-DWITH_HarfBuzz=OFF" "-DWITH_PNG=OFF" "-DWITH_ZLIB=OFF" "-DCMAKE_INSTALL_PREFIX=E:\\delmenow\\target\\debug\\build\\servo-freetype-sys-bd77bc5f5b356b86\\out" "-DCMAKE_C_FLAGS= -nologo -MD -Brepro" "-DCMAKE_C_FLAGS_RELEASE= -nologo -MD -Brepro" "-DCMAKE_CXX_FLAGS= -nologo -MD -Brepro" "-DCMAKE_CXX_FLAGS_RELEASE= -nologo -MD -Brepro" "-DCMAKE_ASM_FLAGS= -nologo -MD -Brepro" "-DCMAKE_ASM_FLAGS_RELEASE= -nologo -MD -Brepro" "-DCMAKE_BUILD_TYPE=Release"
--- stderr
thread 'main' panicked at '
failed to execute command: The system cannot find the file specified. (os error 2)
is `cmake` not installed?
build script failed, must exit now', C:\Users\user\.cargo\registry\src\github.com-1ecc6299db9ec823\cmake-0.1.45\src\lib.rs:894:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
warning: build failed, waiting for other jobs to finish...
error: build failed
Is there an alternate method?
Hi!
Thanks for your work on creating this library. First off, the example that draws a shape needs this using
statement:
use std::iter::FromIterator;
Secondly, after copying the code verbatim running 1.28.0-nightly on OSX. This is the output. Is this correct as I assumed the seconds shape should be a triangle.
Thanks!
test_working.pdf
Now that printpdf has been migrated to rusttype, I have seen a problem where words are spaced weirdly, i.e. the space character is very wide. The strange thing about this is that the characters themselves are spaced correctly. So it's not the old character-spacing bug again. The font is Liberation Sans Bold. Need to investigate this later.
Using #![feature(try_from)]
makes this impossible to use from projects based on stable Rust.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.