1 /*
2  * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  */
23 
24 /**
25  * @test
26  * @bug 8240342
27  * @summary Verify custom composite is called for image drawing
28  */
29 
30 import java.awt.Color;
31 import java.awt.Composite;
32 import java.awt.CompositeContext;
33 import java.awt.Graphics;
34 import java.awt.Graphics2D;
35 import java.awt.RenderingHints;
36 import java.awt.image.BufferedImage;
37 import java.awt.image.ColorModel;
38 import java.awt.image.Raster;
39 import java.awt.image.WritableRaster;
40 import java.awt.print.PageFormat;
41 import java.awt.print.Printable;
42 import java.awt.print.PrinterException;
43 import javax.print.DocFlavor;
44 import javax.print.DocPrintJob;
45 import javax.print.SimpleDoc;
46 import javax.print.StreamPrintService;
47 import javax.print.StreamPrintServiceFactory;
48 import javax.print.attribute.HashDocAttributeSet;
49 import javax.print.attribute.HashPrintRequestAttributeSet;
50 import java.io.ByteArrayOutputStream;
51 
52 public class CustomCompositePrintTest
53              implements Printable, Composite, CompositeContext {
54 
55     private BufferedImage mTestImage;
56     static volatile int composeCallCount = 0;
57 
CustomCompositePrintTest(BufferedImage testImage)58     public CustomCompositePrintTest(BufferedImage testImage) {
59         mTestImage = testImage;
60     }
61 
main(String [] args)62     public static void main(String [] args) throws Exception {
63 
64         DocFlavor flavor = DocFlavor.SERVICE_FORMATTED.PRINTABLE;
65         String mime = DocFlavor.BYTE_ARRAY.POSTSCRIPT.getMimeType();
66 
67         StreamPrintServiceFactory[] factories =
68                 StreamPrintServiceFactory.
69                         lookupStreamPrintServiceFactories(flavor, mime);
70         if (factories.length == 0) {
71             System.out.println("No print service found.");
72             return;
73         }
74 
75         ByteArrayOutputStream output = new ByteArrayOutputStream();
76         StreamPrintService service = factories[0].getPrintService(output);
77 
78         BufferedImage img = new BufferedImage(200, 200,
79                                               BufferedImage.TYPE_INT_RGB);
80         Graphics2D g2d = img.createGraphics();
81         g2d.setColor(Color.yellow);
82         g2d.fillRect(0,0,200,200);
83 
84         SimpleDoc doc =
85              new SimpleDoc(new CustomCompositePrintTest(img),
86                            DocFlavor.SERVICE_FORMATTED.PRINTABLE,
87                            new HashDocAttributeSet());
88         DocPrintJob job = service.createPrintJob();
89         job.print(doc, new HashPrintRequestAttributeSet());
90         if (composeCallCount < 2) {
91             throw new RuntimeException("Compose called " + composeCallCount +
92                                        "times. Expected at least 2");
93         }
94     }
95 
96     @Override
print(Graphics graphics, PageFormat pf, int pageIndex)97     public int print(Graphics graphics, PageFormat pf, int pageIndex)
98                      throws PrinterException {
99 
100         if (pageIndex == 0) {
101             Graphics2D g2 = (Graphics2D)graphics;
102             g2.translate(pf.getImageableX(), pf.getImageableY());
103             g2.setComposite(this);
104             g2.drawImage(mTestImage, 0, 0, null);
105             return PAGE_EXISTS;
106         } else {
107             return NO_SUCH_PAGE;
108         }
109     }
110 
111     @Override
createContext(ColorModel srcColorModel, ColorModel dstColorModel, RenderingHints hints)112     public CompositeContext createContext(ColorModel srcColorModel,
113                                           ColorModel dstColorModel,
114                                           RenderingHints hints) {
115         return this;
116     }
117 
118     @Override
compose(Raster src, Raster dstIn, WritableRaster dstOut)119     public void compose(Raster src, Raster dstIn, WritableRaster dstOut) {
120 
121        composeCallCount++;
122 
123        int w = dstOut.getWidth();
124        int h = dstOut.getHeight();
125        int[] samples3Band = { 0xff, 0x0, 0xff  };
126        int[] samples4Band = { 0xff, 0x0, 0xff, 0xff };
127        int bands = dstOut.getNumBands();
128        int[] samples = null;
129        if (bands == 3) {
130            samples = new int[] { 0xff, 0x0, 0xff };
131        } else if (bands == 4) {
132            samples = new int[] { 0xff, 0x0, 0xff, 0xff };
133        } else {
134            return; // at least compose() was called, so OK.
135        }
136        for (int i=0; i<w; i++) {
137           for (int j=0; j<h; j++) {
138               dstOut.setPixel(i, j, samples);
139            }
140        }
141     }
142 
143     @Override
dispose()144     public void dispose() {
145     }
146 }
147