SkiaSharp Printing to Windows printer - skiasharp

Im using SkiaSharp to generate bitmaps that I then print on thermal printers and to pdf files. I now need to print to windows printers but I don't want to use bitmaps. It would be cool if SkiaSharp could draw directly to a printer page canvas.
Has anyone done this or anything like it?
Alternative is to generate a PDF or XPS and then print that.
(Documentation and blogs for SkiaSharp are basically non-existant so please don't chastise me for not looking elsewhere - which I have).

Related

Rendering with Chromium direct to my own 'canvas' (e.g. GDI+)

First, a quick description of the end-goal:
I'm building a cross-platform, .NET Core-based, printing app. This app will be able to print all sorts of file types with custom page settings, such as headers, footers, and margins. A key feature is it supports multiple-pages-up (e.g. a landscape sheet of paper with two portrait pages rendered side by side...called "2up").
Printing HTML is important not just because of printing HTML, but I want to use all the great HTML-based syntax-highlighting out there for source code (e.g. www.prismjs.com).
The app is basically done but for one major problem: I can't get the HTML to render well enough. So far I've implemented source code printing three ways:
1) As plain text with my own line-numbering and line-wrap engine. This works wonderfully for everything I can throw at it, but it does not support syntax highlighting.
2) Using Html-Renderer (https://github.com/ArthurHub/HTML-Renderer/issues) an OSS .NET-based Html Renderer. This implementation is the weakest because Html-Renderer's CSS support is really weak. It can't handle hardly anything prismjs or highlightjs' generate.
3) Usinglitehtml' (www.litehtml.com) via LiteHtmlSharp. This was very promising and I almost have it working with some major hacks, but litehtml also does not support key, modern, HTML/CSS features.
Neither Html-Renderer or litehtml support the CSS page-break-before feature that, when combined with media print would let me ensure lines are not split between pages.
What I really want to use is the Chromium rendering engine. litehtml provides a fantastic API for this sort of problem: It calls me whenever it needs to render, and I draw (text, table borders, images, etc...) using GDI+. My dream is to find something in Chromium (CEF, Puppeteer, ???) that provides a similar API.
Or, an alternative, an API that will let me pass in a GDI+ Graphics (or HDC) and the renderer will render to that surface.
With Html-Renderer I measure calculate # pages like this.
SizeF size = HtmlRender.MeasureGdiPlus(g, html, containingSheet.GetPageWidth());
int numPages = (int)(size.Height / containingSheet.GetPageHeight());
My page rendering code (e.g. OnPaint) looks like this:
SizeF size = new SizeF(containingSheet.GetPageWidth(), containingSheet.GetPageHeight());
HtmlRender.RenderGdiPlus(g, html, PointF(0, 0), size );
With htmllite the OnPaint code looks like this:
// Set the clip such that any extraLines are clipped off bottom
g.SetClip(new Rectangle(0, 0, (int)Math.Round(PageSize.Width), (int)Math.Round(PageSize.Height - remainingPartialLineHeight)));
LiteHtmlSize size = new LiteHtmlSize(Math.Round(PageSize.Width), Math.Ceiling(PageSize.Height));
litehtml.Document.Draw((int)-0, (int)-yPos, new position {
x = 0,
y = 0,
width = (int)size.Width,
height = (int)size.Height
});
And in this case the call to litehtml.Document.Draw causes a bunch of callbacks into my app that I process using the same Graphics the OnPaint is called with.
Most discussions of CEF and Chromium point to ScreenshotAsync etc... which will not do because I need to be rendering to a PRINTERS HDC (or GDI+) and blitting bitmaps will loose quality.
I have poured over the Chromium source and I cannot find the obvious way to say to CEF/Chromium "render page 1 (defined as Height/Width) to this GDI+ Graphics object" then "render page 2..." etc... The printing support (and how pdfium is integrated come close!).
Chromium issue 311308 indicates I'm hosed until this work gets picked up again.
Note: I have full access to nodejs w/in my app. I have built a dotnet/nodejs bridge, which is how I convert the raw text file of a source code file to richly formatted, line-numbered, syntax-highlighted html via prismjs. This means I could easily use puppeteer/Headless Chrome if I could just figure out the right APIs.
Does anyone have a suggestion that might help? I'm willing to contribute to Chromium if it's not major heart surgery.

ghostscript ps2ps crops document adding some margins/ borders

I feel noob on this one... But here it comes:
Let's take a Vector program with a PS exporter (with no font sub setting: important to change text dynamically in the future) more specifically the Inkscape version 0.46.
Document size A4 and lets draw some lines very close to the border and a simple text, after that you export your ps as noborder.ps:
Everything is really fine! What is on the first lines of postscript file?
%!PS-Adobe-3.0
%%Creator: 0.46
%%Pages: 1
%%Orientation: Portrait
%%BoundingBox: 0 0 596 842
%%HiResBoundingBox: 0 0 596 842
%%DocumentMedia: plain 596 842 0 () ()
%%EndComments
%%Page: 1 1
Now we need to generate a PS file from this PS file (Why? Some new fonts that cannot be uploaded to the printer and dynamically text are changed. PS2PS is a good choice to embed fonts and other elements prior to printing). Let's use ps2ps from ghostscript 8.7.
user#server:/$ ps2ps noborder.ps whyborder.ps
Very good! No errors on running... But... What? BORDERS? MARGINS? CROPPING?
Lets look at the whyborder.ps header:
%!PS-Adobe-3.0
%%Pages: (atend)
%%BoundingBox: 5 6 587 792
%%HiResBoundingBox: 5.000000 6.791406 586.732813 792.000000
%.........................................
%%Creator: GPL Ghostscript 870 (pswrite)
%%CreationDate: 2015/09/09 16:09:24
%%DocumentData: Clean7Bit
%%LanguageLevel: 2
%%EndComments
%%BeginProlog
% This copyright applies to everything between here and the %%EndProlog:
Why is the BoundingBox changed??? Why add borders, margins, cropping?
I have tested options like "-dEPScrop", papersize... But the cropping remains... Why???
Firstly, stop using an ancient version of Ghostscript! 8.70 is now 6 years old, the current version is 9.16 (shortly to be superceded by 9.18).
Secondly, when experimenting like this do not use a script, use the command line directly. The device being used in the archaic version of GHostscript was pswrite, which was a very poor implementation and only supported level 1 output. The current code uses the ps2write device which is a much more powerful and flexible solution.
Note that in all cases running the input through Ghostscript does not 'embed fonts' or 'edit' or 'compress' the original. What happens is that your input is interpreted to produce graphics primitives which are fed to the device API, the device in question then processes the primitives. For a rendering device this means calling the graphics library to render the primitive to the canvas. For a high level device it means re-emitting the primitive , for example as a PDF operation.
ANY such processing brings inherent risks of approximation, the pswrite device was even worse in that much of the content was rendered to images. So in general it really doesn't embed new fonts, it just embeds pictures of the glyphs. This scales really badly and because the bounding box depends on the resolution can result in signficant inaccuracies.
You should really avoid doing ths unless there is no alternative. If you really must do it, be prepared to accept compromises, do not use archaic versions of Ghostscript and don't use the crappy old pswrite device.
Thank you KenS;
By upgrading the ghostscript to version 9.16 and using the following command everything was fine:
user#server:/$ ps2ps -sPAPERSIZE=a4 noborder.ps whyborder916.ps
This is a old and stable system (PHP/Bash/Ghostscript/CUPS), used for many years as a factory labeling system with old postscript printers also. More recently there was the need to change font style; ps2ps was the best choice to "embed" the glyphs and barcodes (postcript language) that dynamically change with the production line and packaging without need to change the printers (different models from different manufacturers). Since PostScript is a language with few changes in years, never crossed my mind to change the GS version.
At this point this is a real money saver! Thanks again!

WinRT barcode scanner component

I have a Windows Store (Metro) application. I need to add support for scanning barcodes.
I tried using ZXing first. From what I was able to get working, you actually need to click and save an image for it to do the processing. There's no nice overlay of a red line "scanner" nor does it process a live feed. This isn't a very elegant solution. It works far better on Android. Basically, this won't work as I need a constant video and a constant search for a barcode to be in focus.
This blog (http://www.soulier.ch/?p=1275&lang=en) mentions that extrapolating a frame out of a WinRT video stream is not allowed in managed code which means I'd need to use C++.
So, are there any components out there that do this? Anything free or paid that I can get that would be written in C++ and can find and extrapolate a barcode? Learning C++ is not on my bucket list.
You can capture frames while displaying a preview with C# only. Here's an example control that does it:
https://winrtxamltoolkit.codeplex.com/SourceControl/latest#WinRTXamlToolkit/Controls/CameraCaptureControl/CameraCaptureControl.cs
Basically you need to create a MediaCapture object and associate it with a CaptureElement control to display the preview. Then you can use CapturePhotoToStreamAsync() to capture a frame to a stream of your selected encoding format and then have a go at it with your bar code reading code.
I made a lib for WinRT using ZXing & Imaging SDK.
It works well (but does not include any additional focus feature).
There is a lib and a sample app that you can try.
It works for barcodes and QRCode (barcode by default but just change the optional parameter in the scan function code to use QRCode)

MediaScannerConnection for AS3/AIR?

import android.media.MediaScannerConnection;
import android.media.MediaScannerConnection.MediaScannerConnectionClient;
These are classes available in Java to refresh the detected images on an SD card on an Android device.
If you save an image to the SD card, it's there, but not visible unless you mount the device, unmount the device. These Java classes fix that problem.
But I'm building an App using AS3 and AIR, does anyone know the equivalent classes for AIR, AS3?
You can use Adobe Air's File class to poke around the device (also cf., Working with Files). Once you figure out what code gets you to the USB device, you can load it as a ByteArray and convert that to an image.
If you are looking for image import/conversion code, just search for what you need; there are numerous posts out there, and the answers are fairly standardized.

Using ICC Profiles in as3/flex

I am creating a flash site where someone can customize a canvas. Then they can preview this canvas on the product. Because of the way monitors display colors, we wanted to try to embed an icc color profile in the previewed image so the user can get a better idea of what the end product will look like. For instance, if they upload something with a really bright red, the preview will show this in a more realistic color to what can be printed on the canvas. This preview is generated on the fly in a flex application using as3.
How I could go about doing this? Is this possible? I realize I could fake something by manipulating colors in flash, but the printer that prints the canvas is able to export an icc profile that will be more accurate. So, I'd like to use that if possible.