JavaFX 8 - Printing 3d scene
Scott Palmer
swpalmer at gmail.com
Wed Nov 12 05:01:08 UTC 2014
"I am however not sure how "the AWT printing mechanism" can be coerced into
converting a node to a WriteableImage. I just don't follow that sentence."
The JavaFX printing API takes a Node as input. Node.snapshot produces an
image and can do so with a transform applied via the SnapshotParameters to
produce a high-resolution output image (matching the printer DPI). That
JavaFX image can be converted to a Java2D image with
javafx.embed.swing.SwingFXUtils, that Java2D image can be printed directly
to the Graphics context of Java2D printing APIs.
When I saw that JavaFX printing was implemented via Java2D printing, I
actually just assumed that was how it worked, but since printing 3D
directly doesn't work, but taking a snapshot of 3D node does work,
obviously it's different under the hood. I'm not sure why it has to be,
but my guess would be that there are threading issues that come up between
the AWT/Swing thread and the FX thread. Probably something that can be
worked around in an application, but was too scary to hide behind the
scenes in the FX printing API as it could lead to deadlocks. I'm just
speculating though.
Scott
On Tue, Nov 11, 2014 at 3:07 PM, Phil Race <philip.race at oracle.com> wrote:
> 2D printing will print images at hi-res, and FX printing will too .. I
> remember testing
> with some ultra hi-res images I found somewhere.
>
> To get a hi-res image printed out you would need to be able to capture all
> of the
> device pixels - if they aren't there to start with there's nothing
> printing can do.
> If you do that I believe it 'just works'. I used an image at full
> resolution and
> placed it into an ImageView which had the size I wanted.
>
> If it was scaled down to 144x144 screen /user pixels, it'll get scaled
> down to 2"x2" on the printer.
> If the image was really 1,440x1,440 all those pixels will be sent to the
> printer and the results
> should look good.
>
> The snippet below probably isn't working with a hi-res image, instead just
> scaling the
> up the image to fit the page. It may be scaling by < 2 for all I can tell.
> The PrintResolution attribute needs to be involved somewhere if you want
> to know
> how much to scale the backbuffer from which you get the pixels but 300dpi
> should
> look ok except to a discerning user.
>
> I am however not sure how "the AWT printing mechanism" can be coerced into
> converting a node to a WriteableImage. I just don't follow that sentence.
>
> -phil.
>
> On 11/11/2014 11:12 AM, Scott Palmer wrote:
>
>> I'm curious. If printing in JavaFX is implemented via Java2D then why
>> isn't it matching what "worked" for the OP?
>>
>> "I have tried using the AWT printing mechanism to convert the node to
>> a
>> WritableImage and then to a BufferedImage for printing. This works in that
>> it prints but we aren't happy with the quality that we get from it."
>>
>> Presumably with the appropriate transform in the SnapshotParameters the
>> image resolution can be made to match the printer. If memory is a concern,
>> it could be done in strips by manipulating the SnapshotParameters viewport.
>> Perhaps I am missing some threading issue that makes this impossible?
>>
>>
>> Scott
>>
>> On Tue, Nov 11, 2014 at 1:13 PM, Phil Race <philip.race at oracle.com
>> <mailto:philip.race at oracle.com>> wrote:
>>
>> This is analagous to the software pipeline where 3D rendering -
>> even to screen - is not supported.
>>
>> I can't see that we documented it, but we were aware that printing
>> 3D was out-of-scope for FX 8.
>> FWIW I think these features were overlapping in development and
>> printing was largely done
>> before 3D was complete.
>>
>> If you are running an accelerated (D3D or OpenGL) pipeline and the
>> Node.snapshot(..) function can grab
>> the 3d node perhaps we could implement printing the scene in
>> terms of that.
>> So what you get would be whatever snapshot would do for you. In
>> the interim you could do that yourself.
>>
>> -phil.
>>
>>
>>
>> On 11/11/2014 7:29 AM, Kevin Rushforth wrote:
>>
>> 3D is not supported for printing. I don't know whether this is
>> documented (it should be if it isn't), but it is a known
>> limitation of the current implementation which uses Java2D to
>> render.
>>
>> -- Kevin
>>
>>
>> Scott Palmer wrote:
>>
>> I suggest you file a bug with a reproducible test case at
>> https://javafx-jira.kenai.com/
>> If the 3D node will render to an image, then it should
>> also be printable
>> directly.
>>
>> Scott
>>
>> On Mon, Nov 10, 2014 at 8:16 PM, Cheryl Long
>> <clong9993 at gmail.com <mailto:clong9993 at gmail.com>> wrote:
>>
>> I posted the following question on Stack Overflow and
>> it was suggested that
>> I ask it here.
>>
>> I am trying to use the JavaFX 8 printing API and I am
>> running into problems
>> when I try to print any scene/node that contains any
>> sort of 3D content. I
>> have been searching both here and other sites for an
>> answer and haven't
>> been able to find anything to help.
>>
>> If the node contains only 2D content, the scene will
>> print on my selected
>> printer without issue. But if I add a single 3D object
>> to the scene, the
>> whole thing fails to print - without any error but
>> without any content. If
>> I am printing to a printer, a blank page is "printed"
>> and if I am printing
>> to a document printer, I get an empty document.
>>
>> I have tried using the AWT printing mechanism to
>> convert the node to a
>> WritableImage and then to a BufferedImage for
>> printing. This works in that
>> it prints but we aren't happy with the quality that we
>> get from it.
>>
>> My print caller is fairly standard at this stage -
>>
>> private void doPrintFX() {
>> Printer printer = Printer.getDefaultPrinter();
>> PageLayout pageLayout = printer.createPageLayout(
>> Paper.A3, PageOrientation.LANDSCAPE,
>> Printer.MarginType.DEFAULT);
>>
>> final double scaleFactor =
>> computeScaleFactor(pageLayout.getPrintableWidth(),
>> pageLayout.getPrintableHeight(),
>> sceneNode.getBoundsInParent().getWidth(),
>> sceneNode.getBoundsInParent().getHeight());
>> if (scaleFactor != 0) {
>> sceneNode.getTransforms().add(new
>> Scale(scaleFactor, scaleFactor));
>> }
>>
>> PrinterJob job = PrinterJob.createPrinterJob(
>> printer);
>> if (job != null) {
>> System.out.println("Printing to " +
>> job.getPrinter().getName());
>> boolean success = job.printPage(pageLayout,
>> sceneNode);
>> if (success) {
>> job.endJob();
>> }
>> }}
>>
>> I have scaled back the node to be a very simple scene
>> containing a couple
>> of rectangles and a cylinder. The code I am currently
>> using is:
>>
>> Cylinder cylinder = new Cylinder(50, 150);
>> cylinder.setLayoutX(250);
>> cylinder.setLayoutY(100);
>> canvas.getDrawingPane().getChildren().add(cylinder);
>>
>> Rectangle item = new Rectangle(50, 50, 100, 50);
>> item.setStroke(Color.BLACK);
>> item.setFill(null);
>> canvas.getDrawingPane().getChildren().add(item);
>>
>> item = new Rectangle(75, 75, 100, 50);
>> item.setStroke(Color.BLACK);
>> item.setFill(null);
>> canvas.getDrawingPane().getChildren().add(item);
>>
>> The canvas.getDrawingPane is a Pane and is what is
>> being sent to the print
>> function.
>>
>> Can anyone advise what might be wrong with what I am
>> doing? Does the JavaFX
>> print API support printing of 3D nodes?
>>
>> Thank you.
>>
>>
>>
>>
>
More information about the openjfx-dev
mailing list