Example usage for java.awt.geom AffineTransform AffineTransform

List of usage examples for java.awt.geom AffineTransform AffineTransform

Introduction

In this page you can find the example usage for java.awt.geom AffineTransform AffineTransform.

Prototype

public AffineTransform() 

Source Link

Document

Constructs a new AffineTransform representing the Identity transformation.

Usage

From source file:AffineTransformApp.java

DisplayPanel() {
    setBackground(Color.black);/*from   w  ww .  ja v  a  2 s . c  o m*/
    loadImage();
    setSize(displayImage.getWidth(this), displayImage.getWidth(this)); // panel
    createBufferedImages();

    transform = new AffineTransform();
}

From source file:org.apache.fop.render.pdf.pdfbox.PSPDFGraphics2D.java

protected void applyPaint(Paint paint, boolean fill) {
    preparePainting();/*from  w  ww .j a  v  a2 s .  c om*/
    if (paint instanceof AxialShadingPaint || paint instanceof RadialShadingPaint) {
        PaintContext paintContext = paint.createContext(null, new Rectangle(), null, new AffineTransform(),
                getRenderingHints());
        int deviceColorSpace = PDFDeviceColorSpace.DEVICE_RGB;
        if (paint instanceof AxialShadingPaint) {
            try {
                AxialShadingContext asc = (AxialShadingContext) paintContext;
                float[] fCoords = asc.getCoords();
                transformCoords(fCoords, paint, true);
                PDFunction function = asc.getFunction();
                Function targetFT = getFunction(function);
                if (targetFT != null) {
                    if (targetFT.getFunctions().size() == 5
                            && targetFT.getFunctions().get(0).getFunctionType() == 0) {
                        return;
                    }
                    List<Double> dCoords = floatArrayToDoubleList(fCoords);
                    PDFDeviceColorSpace colSpace = new PDFDeviceColorSpace(deviceColorSpace);
                    Shading shading = new Shading(2, colSpace, dCoords, targetFT);
                    Pattern pattern = new Pattern(2, shading, null);
                    // gen.write(Gradient.outputPattern(pattern, doubleFormatter));
                }
            } catch (IOException ioe) {
                handleIOException(ioe);
            }
        } else if (paint instanceof RadialShadingPaint) {
            try {
                RadialShadingContext rsc = (RadialShadingContext) paintContext;
                float[] fCoords = rsc.getCoords();
                transformCoords(fCoords, paint, false);
                PDFunction function = rsc.getFunction();
                Function targetFT3 = getFunction(function);
                List<Double> dCoords = floatArrayToDoubleList(fCoords);
                PDFDeviceColorSpace colSpace = new PDFDeviceColorSpace(deviceColorSpace);
                Shading shading = new Shading(3, colSpace, dCoords, targetFT3);
                Pattern pattern = new Pattern(2, shading, null);
                // gen.write(Gradient.outputPattern(pattern, doubleFormatter));
            } catch (IOException ioe) {
                handleIOException(ioe);
            }
        }
    }
}

From source file:org.uva.itast.blended.omr.pages.PageImage.java

/**
 * @param data.getImage()/*from  w  w  w .j a va2  s  . co  m*/
 */
public void resetAlignmentInfo() {
    AffineTransform tr = new AffineTransform();

    double horizRatio = getHorizontalResolution();
    double vertRatio = getVerticalResolution();

    // Do not assume square pixels
    tr.setToScale(horizRatio, vertRatio);
    setAlignmentInfo(tr);
}

From source file:org.apache.fop.afp.svg.AFPGraphicsConfiguration.java

/**
 * The default transform (1:1).// w ww .j a va  2 s .  c  o  m
 *
 * @return the default transform for the configuration
 */
public AffineTransform getDefaultTransform() {
    LOG.debug("getDefaultTransform()");
    if (defaultTransform == null) {
        defaultTransform = new AffineTransform();
    }
    return defaultTransform;
}

From source file:PathLength.java

/**
 * Flattens the path and determines the path length.
 */// ww w .  ja  va2  s . c  o  m
protected void initialise() {
    pathLength = 0f;

    PathIterator pi = path.getPathIterator(new AffineTransform());
    SingleSegmentPathIterator sspi = new SingleSegmentPathIterator();
    segments = new ArrayList(20);
    List indexes = new ArrayList(20);
    int index = 0;
    int origIndex = -1;
    float lastMoveX = 0f;
    float lastMoveY = 0f;
    float currentX = 0f;
    float currentY = 0f;
    float[] seg = new float[6];
    int segType;

    segments.add(new PathSegment(PathIterator.SEG_MOVETO, 0f, 0f, 0f, origIndex));

    while (!pi.isDone()) {
        origIndex++;
        indexes.add(new Integer(index));
        segType = pi.currentSegment(seg);
        switch (segType) {
        case PathIterator.SEG_MOVETO:
            segments.add(new PathSegment(segType, seg[0], seg[1], pathLength, origIndex));
            currentX = seg[0];
            currentY = seg[1];
            lastMoveX = currentX;
            lastMoveY = currentY;
            index++;
            pi.next();
            break;
        case PathIterator.SEG_LINETO:
            pathLength += Point2D.distance(currentX, currentY, seg[0], seg[1]);
            segments.add(new PathSegment(segType, seg[0], seg[1], pathLength, origIndex));
            currentX = seg[0];
            currentY = seg[1];
            index++;
            pi.next();
            break;
        case PathIterator.SEG_CLOSE:
            pathLength += Point2D.distance(currentX, currentY, lastMoveX, lastMoveY);
            segments.add(new PathSegment(PathIterator.SEG_LINETO, lastMoveX, lastMoveY, pathLength, origIndex));
            currentX = lastMoveX;
            currentY = lastMoveY;
            index++;
            pi.next();
            break;
        default:
            sspi.setPathIterator(pi, currentX, currentY);
            FlatteningPathIterator fpi = new FlatteningPathIterator(sspi, 0.01f);
            while (!fpi.isDone()) {
                segType = fpi.currentSegment(seg);
                if (segType == PathIterator.SEG_LINETO) {
                    pathLength += Point2D.distance(currentX, currentY, seg[0], seg[1]);
                    segments.add(new PathSegment(segType, seg[0], seg[1], pathLength, origIndex));
                    currentX = seg[0];
                    currentY = seg[1];
                    index++;
                }
                fpi.next();
            }
        }
    }
    segmentIndexes = new int[indexes.size()];
    for (int i = 0; i < segmentIndexes.length; i++) {
        segmentIndexes[i] = ((Integer) indexes.get(i)).intValue();
    }
    initialised = true;
}

From source file:org.esa.snap.core.gpf.common.BandMathsOpTest.java

@Test
public void testGeoCodingIsCopied() throws Exception {
    Map<String, Object> parameters = new HashMap<>();
    BandMathsOp.BandDescriptor[] bandDescriptors = new BandMathsOp.BandDescriptor[1];
    bandDescriptors[0] = createBandDescription("aBandName", "1.0", ProductData.TYPESTRING_UINT8, "simpleUnits");
    parameters.put("targetBands", bandDescriptors);
    Product sourceProduct = createTestProduct(4, 4);
    CoordinateReferenceSystem decode = CRS.decode("EPSG:32632");
    Rectangle imageBounds = new Rectangle(4, 4);
    AffineTransform imageToMap = new AffineTransform();
    final GeoCoding geoCoding = new CrsGeoCoding(decode, imageBounds, imageToMap);

    sourceProduct.setSceneGeoCoding(geoCoding);
    Product targetProduct = GPF.createProduct("BandMaths", parameters, sourceProduct);

    assertNotNull(targetProduct);//from   ww  w .ja  va  2s .  co  m
    assertNotNull(targetProduct.getSceneGeoCoding());
    assertTrue(targetProduct.isUsingSingleGeoCoding());
}

From source file:org.esa.snap.core.gpf.common.BandMathsOpTest.java

@Test
public void testGeoCodingIsCopiedWithRasterInExpresssion() throws Exception {
    Product sourceProduct = createTestProduct(4, 4);
    CoordinateReferenceSystem decode = CRS.decode("EPSG:32632");
    Rectangle imageBounds = new Rectangle(4, 4);
    AffineTransform imageToMap = new AffineTransform();
    final GeoCoding geoCoding = new CrsGeoCoding(decode, imageBounds, imageToMap);
    sourceProduct.setSceneGeoCoding(geoCoding);

    Map<String, Object> parameters = new HashMap<>();
    BandMathsOp.BandDescriptor[] bandDescriptors = new BandMathsOp.BandDescriptor[1];
    bandDescriptors[0] = createBandDescription("aBandName", "band1 * 2.0", ProductData.TYPESTRING_UINT8,
            "simpleUnits");
    parameters.put("targetBands", bandDescriptors);

    Product targetProduct = GPF.createProduct("BandMaths", parameters, sourceProduct);

    assertNotNull(targetProduct);//from  w ww.ja  v a  2 s  .c  o  m
    assertNotNull(targetProduct.getSceneGeoCoding());
    assertNotNull(targetProduct.getBand("aBandName").getGeoCoding());
}

From source file:org.apache.fop.render.java2d.Java2DSVGHandler.java

/** {@inheritDoc} */
protected void renderSVGDocument(RendererContext context, Document doc) {
    Java2DInfo info = getJava2DInfo(context);
    if (log.isDebugEnabled()) {
        log.debug("renderSVGDocument(" + context + ", " + doc + ", " + info + ")");
    }//ww w .  j  a v a  2s .c om

    // fallback paint as bitmap
    if (info.paintAsBitmap) {
        try {
            super.renderSVGDocument(context, doc);
        } catch (IOException ioe) {
            SVGEventProducer eventProducer = SVGEventProducer.Provider
                    .get(context.getUserAgent().getEventBroadcaster());
            eventProducer.svgRenderingError(this, ioe, getDocumentURI(doc));
        }
        return;
    }

    int x = info.currentXPosition;
    int y = info.currentYPosition;

    SVGUserAgent ua = new SVGUserAgent(context.getUserAgent(), new AffineTransform());

    BridgeContext ctx = new BridgeContext(ua);

    //Cloning SVG DOM as Batik attaches non-thread-safe facilities (like the CSS engine)
    //to it.
    Document clonedDoc = BatikUtil.cloneSVGDocument(doc);

    GraphicsNode root;
    try {
        GVTBuilder builder = new GVTBuilder();
        root = builder.build(ctx, clonedDoc);
    } catch (Exception e) {
        SVGEventProducer eventProducer = SVGEventProducer.Provider
                .get(context.getUserAgent().getEventBroadcaster());
        eventProducer.svgNotBuilt(this, e, getDocumentURI(doc));
        return;
    }

    // If no viewbox is defined in the svg file, a viewbox of 100x100 is
    // assumed, as defined in SVGUserAgent.getViewportSize()
    float iw = (float) ctx.getDocumentSize().getWidth() * 1000f;
    float ih = (float) ctx.getDocumentSize().getHeight() * 1000f;

    float w = info.width;
    float h = info.height;

    AffineTransform origTransform = info.state.getGraph().getTransform();

    // correct integer roundoff
    info.state.getGraph().translate(x / 1000f, y / 1000f);

    //SVGSVGElement svg = ((SVGDocument) doc).getRootElement();
    // Aspect ratio preserved by layout engine, not here
    AffineTransform at = AffineTransform.getScaleInstance(w / iw, h / ih);
    if (!at.isIdentity()) {
        info.state.getGraph().transform(at);
    }

    try {
        root.paint(info.state.getGraph());
    } catch (Exception e) {
        SVGEventProducer eventProducer = SVGEventProducer.Provider
                .get(context.getUserAgent().getEventBroadcaster());
        eventProducer.svgRenderingError(this, e, getDocumentURI(doc));
    }

    info.state.getGraph().setTransform(origTransform);
}

From source file:com.piaoyou.util.ImageUtil.java

/**
 * @todo: xem lai ham nay, neu kich thuoc nho hon max thi ta luu truc tiep
 *          inputStream xuong thumbnailFile luon
 *
 * This method create a thumbnail and reserve the ratio of the output image
 * NOTE: This method closes the inputStream after it have done its work.
 *
 * @param inputStream     the stream of a jpeg file
 * @param outputStream    the output stream
 * @param maxWidth        the maximum width of the image
 * @param maxHeight       the maximum height of the image
 * @throws IOException//from   w  w  w  .j a  va2s .c  o m
 * @throws BadInputException
 */
public static void createThumbnail(InputStream inputStream, OutputStream outputStream, int maxWidth,
        int maxHeight) throws IOException {

    if (inputStream == null) {
        throw new IllegalArgumentException("inputStream must not be null.");
    }
    if (outputStream == null) {
        throw new IllegalArgumentException("outputStream must not be null.");
    }

    //boolean useSun = false;
    if (maxWidth <= 0) {
        throw new IllegalArgumentException("maxWidth must >= 0");
    }
    if (maxHeight <= 0) {
        throw new IllegalArgumentException("maxHeight must >= 0");
    }

    try {
        //JPEGImageDecoder decoder = JPEGCodec.createJPEGDecoder(inputStream);
        //BufferedImage srcImage = decoder.decodeAsBufferedImage();
        byte[] srcByte = FileUtil.getBytes(inputStream);
        InputStream is = new ByteArrayInputStream(srcByte);
        //ImageIcon imageIcon = new ImageIcon(srcByte);
        //Image srcImage = imageIcon.getImage();

        BufferedImage srcImage = ImageIO.read(is);
        if (srcImage == null) {
            throw new IOException("Cannot decode image. Please check your file again.");
        }

        int imgWidth = srcImage.getWidth();
        int imgHeight = srcImage.getHeight();
        //          imgWidth or imgHeight could be -1, which is considered as an assertion
        AssertionUtil.doAssert((imgWidth > 0) && (imgHeight > 0),
                "Assertion: ImageUtil: cannot get the image size.");
        // Set the scale.
        AffineTransform tx = new AffineTransform();
        if ((imgWidth > maxWidth) || (imgHeight > maxHeight)) {
            double scaleX = (double) maxWidth / imgWidth;
            double scaleY = (double) maxHeight / imgHeight;
            double scaleRatio = (scaleX < scaleY) ? scaleX : scaleY;
            imgWidth = (int) (imgWidth * scaleX);
            imgWidth = (imgWidth == 0) ? 1 : imgWidth;
            imgHeight = (int) (imgHeight * scaleY);
            imgHeight = (imgHeight == 0) ? 1 : imgHeight;
            // scale as needed
            tx.scale(scaleRatio, scaleRatio);
        } else {// we don't need any transform here, just save it to file and return
            outputStream.write(srcByte);
            return;
        }

        // create thumbnail image
        BufferedImage bufferedImage = new BufferedImage(imgWidth, imgHeight, BufferedImage.TYPE_INT_RGB);

        Graphics2D g = bufferedImage.createGraphics();
        boolean useTransform = false;
        if (useTransform) {// use transfrom to draw
            //log.trace("use transform");
            g.drawImage(srcImage, tx, null);
        } else {// use java filter
            //log.trace("use filter");
            Image scaleImage = getScaledInstance(srcImage, imgWidth, imgHeight);
            g.drawImage(scaleImage, 0, 0, null);
        }
        g.dispose();// free resource
        // write it to outputStream 
        // JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(outputStream);
        // encoder.encode(bufferedImage);

        ImageIO.write(bufferedImage, "jpeg", outputStream);
    } catch (IOException e) {
        log.error("Error", e);
        throw e;
    } finally {// this finally is very important
        try {
            inputStream.close();
        } catch (IOException e) {
            /* ignore */
            e.printStackTrace();
        }
        try {
            outputStream.close();
        } catch (IOException e) {/* ignore */
            e.printStackTrace();
        }
    }
}

From source file:be.fedict.eidviewer.gui.printing.IDPrintout.java

public int print(Graphics graphics, PageFormat pageFormat, int pageNumber) throws PrinterException {
    // we only support printing all in one single page
    if (pageNumber > 0)
        return Printable.NO_SUCH_PAGE;

    logger.finest(new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
            .append("width", pageFormat.getWidth()).append("height", pageFormat.getHeight())
            .append("imageableWidth", pageFormat.getImageableWidth())
            .append("imageableHeight", pageFormat.getImageableHeight())
            .append("imageableX", pageFormat.getImageableX()).append("imageableY", pageFormat.getImageableY())
            .append("orientation", pageFormat.getOrientation())
            .append("paper.width", pageFormat.getPaper().getWidth())
            .append("paper.height", pageFormat.getPaper().getHeight())
            .append("paper.imageableWidth", pageFormat.getPaper().getImageableWidth())
            .append("paper.imageableHeight", pageFormat.getPaper().getImageableHeight())
            .append("paper.imageableX", pageFormat.getPaper().getImageableX())
            .append("paper.imageableY", pageFormat.getPaper().getImageableY()).toString());

    logger.finest(new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
            .append("clip.width", graphics.getClipBounds().width)
            .append("clip.height", graphics.getClipBounds().height).append("clip.x", graphics.getClipBounds().x)
            .append("clip.y", graphics.getClipBounds().y).toString());

    // translate graphics2D with origin at top left first imageable location
    Graphics2D graphics2D = (Graphics2D) graphics;
    graphics2D.translate(pageFormat.getImageableX(), pageFormat.getImageableY());

    // keep imageable width and height as variables for clarity (we use them often)
    float imageableWidth = (float) pageFormat.getImageableWidth();
    float imageableHeight = (float) pageFormat.getImageableHeight();

    // Coat of Arms images are stored at approx 36 DPI, scale 1/2 to get to Java default of 72DPI
    AffineTransform coatOfArmsTransform = new AffineTransform();
    coatOfArmsTransform.scale(0.5, 0.5);

    // photo images are stored at approx 36 DPI, scale 1/2 to get to Java default of 72DPI
    AffineTransform photoTransform = new AffineTransform();
    photoTransform.scale(0.5, 0.5);//from  w  w w  .ja va  2 s  .  c  o  m
    photoTransform.translate((imageableWidth * 2) - (photo.getWidth(this)), 0);

    // make sure foreground is black, and draw coat of Arms and photo at the top of the page
    // using the transforms to scale them to 72DPI.
    graphics2D.setColor(Color.BLACK);
    graphics2D.drawImage(coatOfArms, coatOfArmsTransform, null);
    graphics2D.drawImage(photo, photoTransform, null);

    // calculate some sizes that need to take into account the scaling of the graphics, to avoid dragging
    // those non-intuitive "/2" further along in the code.
    float headerHeight = (float) (coatOfArms.getHeight(this)) / 2;
    float coatOfArmsWidth = (float) (coatOfArms.getWidth(this)) / 2;
    float photoWidth = (float) (photo.getWidth(this)) / 2;
    float headerSpaceBetweenImages = imageableWidth
            - (coatOfArmsWidth + photoWidth + (SPACE_BETWEEN_ITEMS * 2));

    logger.finest(new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE).append("headerHeight", headerHeight)
            .append("coatOfArmsWidth", coatOfArmsWidth).append("photoWidth", photoWidth)
            .append("headerSpaceBetweenImages", headerSpaceBetweenImages).toString());

    // get localised strings for card type. We'll take a new line every time a ";" is found in the resource
    String[] cardTypeStr = (bundle.getString("type_" + this.identity.getDocumentType().toString())
            .toUpperCase()).split(";");

    // if a "mention" is present, append it so it appears below the card type string, between brackets

    if (identity.getSpecialOrganisation() != SpecialOrganisation.UNSPECIFIED) {
        String mention = TextFormatHelper.getSpecialOrganisationString(bundle,
                identity.getSpecialOrganisation());
        if (mention != null && !mention.isEmpty()) {
            String[] cardTypeWithMention = new String[cardTypeStr.length + 1];
            System.arraycopy(cardTypeStr, 0, cardTypeWithMention, 0, cardTypeStr.length);
            cardTypeWithMention[cardTypeStr.length] = "(" + mention + ")";
            cardTypeStr = cardTypeWithMention;
        }
    }

    // iterate from MAXIMAL_FONT_SIZE, calculating how much space would be required to fit the card type strings
    // stop when a font size is found where they all fit the space between the graphics in an orderly manner
    boolean sizeFound = false;
    int fontSize;
    for (fontSize = TITLE_MAXIMAL_FONT_SIZE; (fontSize >= MINIMAL_FONT_SIZE) && (!sizeFound); fontSize--) // count down slowly until we find one that fits nicely
    {
        logger.log(Level.FINE, "fontSize=" + fontSize + " sizeFound=" + sizeFound);
        graphics2D.setFont(new Font(FONT, Font.PLAIN, fontSize));
        sizeFound = (ImageUtilities.getTotalStringWidth(graphics2D, cardTypeStr) < headerSpaceBetweenImages)
                && (ImageUtilities.getTotalStringHeight(graphics2D, cardTypeStr) < headerHeight);
    }

    // unless with extremely small papers, a size should always have been found.
    // draw the card type strings, centered, between the images at the top of the page
    if (sizeFound) {
        graphics2D.setFont(new Font(FONT, Font.PLAIN, fontSize + 1));
        float cardTypeHeight = cardTypeStr.length * ImageUtilities.getStringHeight(graphics2D);
        float cardTypeBaseLine = ((headerHeight - cardTypeHeight) / 2) + ImageUtilities.getAscent(graphics2D);
        float cardTypeLineHeight = ImageUtilities.getStringHeight(graphics2D);

        logger.finest(new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
                .append("cardTypeHeight", cardTypeHeight).append("cardTypeBaseLine", cardTypeBaseLine)
                .append("cardTypeLineHeight", cardTypeLineHeight).toString());

        for (int i = 0; i < cardTypeStr.length; i++) {
            float left = (coatOfArmsWidth + SPACE_BETWEEN_ITEMS
                    + (headerSpaceBetweenImages - ImageUtilities.getStringWidth(graphics2D, cardTypeStr[i]))
                            / 2);
            float leading = (float) cardTypeLineHeight * i;
            graphics2D.drawString(cardTypeStr[i], left, cardTypeBaseLine + leading);
        }
    }

    // populate idAttributes with all the information from identity and address
    // as well as date printed and some separators
    List<IdentityAttribute> idAttributes = populateAttributeList();

    // draw a horizontal line just below the header (images + card type titles)
    graphics2D.drawLine(0, (int) headerHeight, (int) imageableWidth, (int) headerHeight);

    // calculate how much space is left between the header and the bottom of the imageable area

    headerHeight += 32; // take some distance from header

    float imageableDataHeight = imageableHeight - headerHeight;
    float totalDataWidth = 0, totalDataHeight = 0;
    float labelWidth, widestLabelWidth = 0;
    float valueWidth, widestValueWidth = 0;

    // iterate from MAXIMAL_FONT_SIZE, calculating how much space would be required to fit the information in idAttributes into
    // the space between the header and the bottom of the imageable area
    // stop when a font size is found where it all fits in an orderly manner
    sizeFound = false;
    for (fontSize = MAXIMAL_FONT_SIZE; (fontSize >= MINIMAL_FONT_SIZE) && (!sizeFound); fontSize--) // count down slowly until we find one that fits nicely
    {
        logger.log(Level.FINE, "fontSize=" + fontSize + " sizeFound=" + sizeFound);
        graphics2D.setFont(new Font(FONT, Font.PLAIN, fontSize));

        widestLabelWidth = 0;
        widestValueWidth = 0;

        for (IdentityAttribute attribute : idAttributes) {
            if (attribute == SEPARATOR)
                continue;

            labelWidth = ImageUtilities.getStringWidth(graphics2D, attribute.getLabel());
            valueWidth = ImageUtilities.getStringWidth(graphics2D, attribute.getValue());
            if (labelWidth > widestLabelWidth)
                widestLabelWidth = labelWidth;
            if (valueWidth > widestValueWidth)
                widestValueWidth = valueWidth;
        }

        totalDataWidth = widestLabelWidth + SPACE_BETWEEN_ITEMS + widestValueWidth;
        totalDataHeight = ImageUtilities.getStringHeight(graphics2D)
                + (ImageUtilities.getStringHeight(graphics2D) * idAttributes.size());

        if ((totalDataWidth < imageableWidth) && (totalDataHeight < imageableDataHeight))
            sizeFound = true;
    }

    logger.finest(new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
            .append("widestLabelWidth", widestLabelWidth).append("widestValueWidth", widestValueWidth)
            .append("totalDataWidth", totalDataWidth).append("totalDataHeight", totalDataHeight).toString());

    // unless with extremely small papers, a size should always have been found.
    // draw the identity, addess and date printed information, in 2 columns, centered inside the
    // space between the header and the bottom of the imageable area
    if (sizeFound) {
        graphics2D.setFont(new Font(FONT, Font.PLAIN, fontSize));
        float labelsLeft = (imageableWidth - totalDataWidth) / 2;
        float valuesLeft = labelsLeft + widestLabelWidth + SPACE_BETWEEN_ITEMS;
        float dataLineHeight = ImageUtilities.getStringHeight(graphics2D);
        float dataTop = dataLineHeight + headerHeight + ((imageableDataHeight - totalDataHeight) / 2);
        float lineNumber = 0;

        logger.finest(new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE).append("labelsLeft", labelsLeft)
                .append("valuesLeft", valuesLeft).append("dataLineHeight", dataLineHeight)
                .append("dataTop", dataTop).toString());

        for (IdentityAttribute attribute : idAttributes) {
            if (attribute != SEPARATOR) // data
            {
                graphics2D.setColor(attribute.isRelevant() ? Color.BLACK : Color.LIGHT_GRAY);
                graphics2D.drawString(attribute.getLabel(), labelsLeft,
                        dataTop + (lineNumber * dataLineHeight));
                graphics2D.drawString(attribute.getValue(), valuesLeft,
                        dataTop + (lineNumber * dataLineHeight));
            } else // separator
            {
                int y = (int) (((dataTop + (lineNumber * dataLineHeight) + (dataLineHeight / 2)))
                        - ImageUtilities.getAscent(graphics2D));
                graphics2D.setColor(Color.BLACK);
                graphics2D.drawLine((int) labelsLeft, y, (int) (labelsLeft + totalDataWidth), y);
            }
            lineNumber++;
        }
    }

    // tell Java printing that all this makes for a page worth printing :-)
    return Printable.PAGE_EXISTS;
}