99 "sun.java2d.print.enableGDITextLayout"));
100
101 if (textLayoutStr != null) {
102 useGDITextLayout = Boolean.getBoolean(textLayoutStr);
103 if (!useGDITextLayout) {
104 if (textLayoutStr.equalsIgnoreCase("prefer")) {
105 useGDITextLayout = true;
106 preferGDITextLayout = true;
107 }
108 }
109 }
110 }
111
112 WPathGraphics(Graphics2D graphics, PrinterJob printerJob,
113 Printable painter, PageFormat pageFormat, int pageIndex,
114 boolean canRedraw) {
115 super(graphics, printerJob, painter, pageFormat, pageIndex, canRedraw);
116 }
117
118 /**
119 * Creates a new <code>Graphics</code> object that is
120 * a copy of this <code>Graphics</code> object.
121 * @return a new graphics context that is a copy of
122 * this graphics context.
123 * @since 1.0
124 */
125 @Override
126 public Graphics create() {
127
128 return new WPathGraphics((Graphics2D) getDelegate().create(),
129 getPrinterJob(),
130 getPrintable(),
131 getPageFormat(),
132 getPageIndex(),
133 canDoRedraws());
134 }
135
136 /**
137 * Strokes the outline of a Shape using the settings of the current
138 * graphics state. The rendering attributes applied include the
139 * clip, transform, paint or color, composite and stroke attributes.
140 * @param s The shape to be drawn.
358 * rotation here is opposite than 2D's, so the rotation needed
359 * needs to be recalculated in the opposite direction.
360 */
361 if (angle != 0.0) {
362 angle = 360.0 - angle;
363 }
364 return (int)Math.round(angle * 10.0);
365 }
366
367 private float getAwScale(double scaleFactorX, double scaleFactorY) {
368
369 float awScale = (float)(scaleFactorX/scaleFactorY);
370 /* don't let rounding errors be interpreted as non-uniform scale */
371 if (awScale > 0.999f && awScale < 1.001f) {
372 awScale = 1.0f;
373 }
374 return awScale;
375 }
376
377 /**
378 * Renders the text specified by the specified <code>String</code>,
379 * using the current <code>Font</code> and <code>Paint</code> attributes
380 * in the <code>Graphics2D</code> context.
381 * The baseline of the first character is at position
382 * (<i>x</i>, <i>y</i>) in the User Space.
383 * The rendering attributes applied include the <code>Clip</code>,
384 * <code>Transform</code>, <code>Paint</code>, <code>Font</code> and
385 * <code>Composite</code> attributes. For characters in script systems
386 * such as Hebrew and Arabic, the glyphs can be rendered from right to
387 * left, in which case the coordinate supplied is the location of the
388 * leftmost character on the baseline.
389 * @param str the <code>String</code> to be rendered
390 * @param x, y the coordinates where the <code>String</code>
391 * should be rendered
392 * @see #setPaint
393 * @see java.awt.Graphics#setColor
394 * @see java.awt.Graphics#setFont
395 * @see #setTransform
396 * @see #setComposite
397 * @see #setClip
398 */
399 @Override
400 public void drawString(String str, float x, float y,
401 Font font, FontRenderContext frc, float targetW) {
402 if (str.length() == 0) {
403 return;
404 }
405
406 if (WPrinterJob.shapeTextProp) {
407 super.drawString(str, x, y, font, frc, targetW);
408 return;
409 }
410
852 */
853 private boolean okGDIMetrics(String str, Font font,
854 FontRenderContext frc, double scaleX) {
855
856 Rectangle2D bds = font.getStringBounds(str, frc);
857 double jdkAdvance = bds.getWidth();
858 jdkAdvance = Math.round(jdkAdvance*scaleX);
859 int gdiAdvance = ((WPrinterJob)getPrinterJob()).getGDIAdvance(str);
860 if (jdkAdvance > 0 && gdiAdvance > 0) {
861 double diff = Math.abs(gdiAdvance-jdkAdvance);
862 double ratio = gdiAdvance/jdkAdvance;
863 if (ratio < 1) {
864 ratio = 1/ratio;
865 }
866 return diff <= 1 || ratio < 1.002;
867 }
868 return true;
869 }
870
871 /**
872 * The various <code>drawImage()</code> methods for
873 * <code>WPathGraphics</code> are all decomposed
874 * into an invocation of <code>drawImageToPlatform</code>.
875 * The portion of the passed in image defined by
876 * <code>srcX, srcY, srcWidth, and srcHeight</code>
877 * is transformed by the supplied AffineTransform and
878 * drawn using GDI to the printer context.
879 *
880 * @param image The image to be drawn.
881 * @param xform Used to transform the image before drawing.
882 * This can be null.
883 * @param bgcolor This color is drawn where the image has transparent
884 * pixels. If this parameter is null then the
885 * pixels already in the destination should show
886 * through.
887 * @param srcX With srcY this defines the upper-left corner
888 * of the portion of the image to be drawn.
889 *
890 * @param srcY With srcX this defines the upper-left corner
891 * of the portion of the image to be drawn.
892 * @param srcWidth The width of the portion of the image to
893 * be drawn.
894 * @param srcHeight The height of the portion of the image to
895 * be drawn.
896 * @param handlingTransparency if being recursively called to
1317 deviceClip(getClip().getPathIterator(getTransform()));
1318
1319 wPrinterJob.drawDIBImage
1320 (data, scaledBounds.x, scaledBounds.y,
1321 (float)Math.rint(scaledBounds.width+0.5),
1322 (float)Math.rint(scaledBounds.height+0.5),
1323 0f, 0f,
1324 deepImage.getWidth(), deepImage.getHeight(),
1325 bitsPerPixel, icm);
1326
1327 setClip(holdClip);
1328 }
1329 }
1330 }
1331
1332 return true;
1333 }
1334
1335 /**
1336 * Have the printing application redraw everything that falls
1337 * within the page bounds defined by <code>region</code>.
1338 */
1339 @Override
1340 public void redrawRegion(Rectangle2D region, double scaleX, double scaleY,
1341 Shape savedClip, AffineTransform savedTransform)
1342 throws PrinterException {
1343
1344 WPrinterJob wPrinterJob = (WPrinterJob)getPrinterJob();
1345 Printable painter = getPrintable();
1346 PageFormat pageFormat = getPageFormat();
1347 int pageIndex = getPageIndex();
1348
1349 /* Create a buffered image big enough to hold the portion
1350 * of the source image being printed.
1351 */
1352 BufferedImage deepImage = new BufferedImage(
1353 (int) region.getWidth(),
1354 (int) region.getHeight(),
1355 BufferedImage.TYPE_3BYTE_BGR);
1356
1357 /* Get a graphics for the application to render into.
1417 (float) (region.getY() * scaleY),
1418 (float) (region.getWidth() * scaleX),
1419 (float) (region.getHeight() * scaleY));
1420
1421 /* Pull the raster data from the buffered image
1422 * and pass it along to GDI.
1423 */
1424 ByteComponentRaster tile
1425 = (ByteComponentRaster)deepImage.getRaster();
1426
1427 wPrinterJob.drawImage3ByteBGR(tile.getDataStorage(),
1428 scaledBounds.x, scaledBounds.y,
1429 scaledBounds.width,
1430 scaledBounds.height,
1431 0f, 0f,
1432 deepImage.getWidth(), deepImage.getHeight());
1433
1434 }
1435
1436 /*
1437 * Fill the path defined by <code>pathIter</code>
1438 * with the specified color.
1439 * The path is provided in device coordinates.
1440 */
1441 @Override
1442 protected void deviceFill(PathIterator pathIter, Color color) {
1443
1444 WPrinterJob wPrinterJob = (WPrinterJob) getPrinterJob();
1445
1446 convertToWPath(pathIter);
1447 wPrinterJob.selectSolidBrush(color);
1448 wPrinterJob.fillPath();
1449 }
1450
1451 /*
1452 * Set the printer device's clip to be the
1453 * path defined by <code>pathIter</code>
1454 * The path is provided in device coordinates.
1455 */
1456 @Override
1457 protected void deviceClip(PathIterator pathIter) {
1458
1459 WPrinterJob wPrinterJob = (WPrinterJob) getPrinterJob();
1460
1461 convertToWPath(pathIter);
1462 wPrinterJob.selectClipPath();
1463 }
1464
1465 /**
1466 * Draw the bounding rectangle using transformed coordinates.
1467 */
1468 @Override
1469 protected void deviceFrameRect(int x, int y, int width, int height,
1470 Color color) {
1471
1472 AffineTransform deviceTransform = getTransform();
1473
1657
1658 if ((endCap == BasicStroke.CAP_ROUND) ||
1659 (((xBegin == xEnd) || (yBegin == yEnd)) &&
1660 (deviceLineWidth/lowerRes < MAX_THINLINE_INCHES))) {
1661
1662 wPrinterJob.selectPen(deviceLineWidth, color);
1663 wPrinterJob.moveTo((float)begin_pos.getX(),
1664 (float)begin_pos.getY());
1665 wPrinterJob.lineTo((float)end_pos.getX(),
1666 (float)end_pos.getY());
1667 }
1668 else {
1669 draw(new Line2D.Float(xBegin, yBegin, xEnd, yEnd));
1670 }
1671 }
1672 }
1673 }
1674
1675
1676 /**
1677 * Given a Java2D <code>PathIterator</code> instance,
1678 * this method translates that into a Window's path
1679 * in the printer device context.
1680 */
1681 private void convertToWPath(PathIterator pathIter) {
1682
1683 float[] segment = new float[6];
1684 int segmentType;
1685
1686 WPrinterJob wPrinterJob = (WPrinterJob) getPrinterJob();
1687
1688 /* Map the PathIterator's fill rule into the Window's
1689 * polygon fill rule.
1690 */
1691 int polyFillRule;
1692 if (pathIter.getWindingRule() == PathIterator.WIND_EVEN_ODD) {
1693 polyFillRule = WPrinterJob.POLYFILL_ALTERNATE;
1694 } else {
1695 polyFillRule = WPrinterJob.POLYFILL_WINDING;
1696 }
1697 wPrinterJob.setPolyFillMode(polyFillRule);
|
99 "sun.java2d.print.enableGDITextLayout"));
100
101 if (textLayoutStr != null) {
102 useGDITextLayout = Boolean.getBoolean(textLayoutStr);
103 if (!useGDITextLayout) {
104 if (textLayoutStr.equalsIgnoreCase("prefer")) {
105 useGDITextLayout = true;
106 preferGDITextLayout = true;
107 }
108 }
109 }
110 }
111
112 WPathGraphics(Graphics2D graphics, PrinterJob printerJob,
113 Printable painter, PageFormat pageFormat, int pageIndex,
114 boolean canRedraw) {
115 super(graphics, printerJob, painter, pageFormat, pageIndex, canRedraw);
116 }
117
118 /**
119 * Creates a new {@code Graphics} object that is
120 * a copy of this {@code Graphics} object.
121 * @return a new graphics context that is a copy of
122 * this graphics context.
123 * @since 1.0
124 */
125 @Override
126 public Graphics create() {
127
128 return new WPathGraphics((Graphics2D) getDelegate().create(),
129 getPrinterJob(),
130 getPrintable(),
131 getPageFormat(),
132 getPageIndex(),
133 canDoRedraws());
134 }
135
136 /**
137 * Strokes the outline of a Shape using the settings of the current
138 * graphics state. The rendering attributes applied include the
139 * clip, transform, paint or color, composite and stroke attributes.
140 * @param s The shape to be drawn.
358 * rotation here is opposite than 2D's, so the rotation needed
359 * needs to be recalculated in the opposite direction.
360 */
361 if (angle != 0.0) {
362 angle = 360.0 - angle;
363 }
364 return (int)Math.round(angle * 10.0);
365 }
366
367 private float getAwScale(double scaleFactorX, double scaleFactorY) {
368
369 float awScale = (float)(scaleFactorX/scaleFactorY);
370 /* don't let rounding errors be interpreted as non-uniform scale */
371 if (awScale > 0.999f && awScale < 1.001f) {
372 awScale = 1.0f;
373 }
374 return awScale;
375 }
376
377 /**
378 * Renders the text specified by the specified {@code String},
379 * using the current {@code Font} and {@code Paint} attributes
380 * in the {@code Graphics2D} context.
381 * The baseline of the first character is at position
382 * (<i>x</i>, <i>y</i>) in the User Space.
383 * The rendering attributes applied include the {@code Clip},
384 * {@code Transform}, {@code Paint}, {@code Font} and
385 * {@code Composite} attributes. For characters in script systems
386 * such as Hebrew and Arabic, the glyphs can be rendered from right to
387 * left, in which case the coordinate supplied is the location of the
388 * leftmost character on the baseline.
389 * @param str the {@code String} to be rendered
390 * @param x, y the coordinates where the {@code String}
391 * should be rendered
392 * @see #setPaint
393 * @see java.awt.Graphics#setColor
394 * @see java.awt.Graphics#setFont
395 * @see #setTransform
396 * @see #setComposite
397 * @see #setClip
398 */
399 @Override
400 public void drawString(String str, float x, float y,
401 Font font, FontRenderContext frc, float targetW) {
402 if (str.length() == 0) {
403 return;
404 }
405
406 if (WPrinterJob.shapeTextProp) {
407 super.drawString(str, x, y, font, frc, targetW);
408 return;
409 }
410
852 */
853 private boolean okGDIMetrics(String str, Font font,
854 FontRenderContext frc, double scaleX) {
855
856 Rectangle2D bds = font.getStringBounds(str, frc);
857 double jdkAdvance = bds.getWidth();
858 jdkAdvance = Math.round(jdkAdvance*scaleX);
859 int gdiAdvance = ((WPrinterJob)getPrinterJob()).getGDIAdvance(str);
860 if (jdkAdvance > 0 && gdiAdvance > 0) {
861 double diff = Math.abs(gdiAdvance-jdkAdvance);
862 double ratio = gdiAdvance/jdkAdvance;
863 if (ratio < 1) {
864 ratio = 1/ratio;
865 }
866 return diff <= 1 || ratio < 1.002;
867 }
868 return true;
869 }
870
871 /**
872 * The various {@code drawImage()} methods for
873 * {@code WPathGraphics} are all decomposed
874 * into an invocation of {@code drawImageToPlatform}.
875 * The portion of the passed in image defined by
876 * {@code srcX, srcY, srcWidth, and srcHeight}
877 * is transformed by the supplied AffineTransform and
878 * drawn using GDI to the printer context.
879 *
880 * @param image The image to be drawn.
881 * @param xform Used to transform the image before drawing.
882 * This can be null.
883 * @param bgcolor This color is drawn where the image has transparent
884 * pixels. If this parameter is null then the
885 * pixels already in the destination should show
886 * through.
887 * @param srcX With srcY this defines the upper-left corner
888 * of the portion of the image to be drawn.
889 *
890 * @param srcY With srcX this defines the upper-left corner
891 * of the portion of the image to be drawn.
892 * @param srcWidth The width of the portion of the image to
893 * be drawn.
894 * @param srcHeight The height of the portion of the image to
895 * be drawn.
896 * @param handlingTransparency if being recursively called to
1317 deviceClip(getClip().getPathIterator(getTransform()));
1318
1319 wPrinterJob.drawDIBImage
1320 (data, scaledBounds.x, scaledBounds.y,
1321 (float)Math.rint(scaledBounds.width+0.5),
1322 (float)Math.rint(scaledBounds.height+0.5),
1323 0f, 0f,
1324 deepImage.getWidth(), deepImage.getHeight(),
1325 bitsPerPixel, icm);
1326
1327 setClip(holdClip);
1328 }
1329 }
1330 }
1331
1332 return true;
1333 }
1334
1335 /**
1336 * Have the printing application redraw everything that falls
1337 * within the page bounds defined by {@code region}.
1338 */
1339 @Override
1340 public void redrawRegion(Rectangle2D region, double scaleX, double scaleY,
1341 Shape savedClip, AffineTransform savedTransform)
1342 throws PrinterException {
1343
1344 WPrinterJob wPrinterJob = (WPrinterJob)getPrinterJob();
1345 Printable painter = getPrintable();
1346 PageFormat pageFormat = getPageFormat();
1347 int pageIndex = getPageIndex();
1348
1349 /* Create a buffered image big enough to hold the portion
1350 * of the source image being printed.
1351 */
1352 BufferedImage deepImage = new BufferedImage(
1353 (int) region.getWidth(),
1354 (int) region.getHeight(),
1355 BufferedImage.TYPE_3BYTE_BGR);
1356
1357 /* Get a graphics for the application to render into.
1417 (float) (region.getY() * scaleY),
1418 (float) (region.getWidth() * scaleX),
1419 (float) (region.getHeight() * scaleY));
1420
1421 /* Pull the raster data from the buffered image
1422 * and pass it along to GDI.
1423 */
1424 ByteComponentRaster tile
1425 = (ByteComponentRaster)deepImage.getRaster();
1426
1427 wPrinterJob.drawImage3ByteBGR(tile.getDataStorage(),
1428 scaledBounds.x, scaledBounds.y,
1429 scaledBounds.width,
1430 scaledBounds.height,
1431 0f, 0f,
1432 deepImage.getWidth(), deepImage.getHeight());
1433
1434 }
1435
1436 /*
1437 * Fill the path defined by {@code pathIter}
1438 * with the specified color.
1439 * The path is provided in device coordinates.
1440 */
1441 @Override
1442 protected void deviceFill(PathIterator pathIter, Color color) {
1443
1444 WPrinterJob wPrinterJob = (WPrinterJob) getPrinterJob();
1445
1446 convertToWPath(pathIter);
1447 wPrinterJob.selectSolidBrush(color);
1448 wPrinterJob.fillPath();
1449 }
1450
1451 /*
1452 * Set the printer device's clip to be the
1453 * path defined by {@code pathIter}
1454 * The path is provided in device coordinates.
1455 */
1456 @Override
1457 protected void deviceClip(PathIterator pathIter) {
1458
1459 WPrinterJob wPrinterJob = (WPrinterJob) getPrinterJob();
1460
1461 convertToWPath(pathIter);
1462 wPrinterJob.selectClipPath();
1463 }
1464
1465 /**
1466 * Draw the bounding rectangle using transformed coordinates.
1467 */
1468 @Override
1469 protected void deviceFrameRect(int x, int y, int width, int height,
1470 Color color) {
1471
1472 AffineTransform deviceTransform = getTransform();
1473
1657
1658 if ((endCap == BasicStroke.CAP_ROUND) ||
1659 (((xBegin == xEnd) || (yBegin == yEnd)) &&
1660 (deviceLineWidth/lowerRes < MAX_THINLINE_INCHES))) {
1661
1662 wPrinterJob.selectPen(deviceLineWidth, color);
1663 wPrinterJob.moveTo((float)begin_pos.getX(),
1664 (float)begin_pos.getY());
1665 wPrinterJob.lineTo((float)end_pos.getX(),
1666 (float)end_pos.getY());
1667 }
1668 else {
1669 draw(new Line2D.Float(xBegin, yBegin, xEnd, yEnd));
1670 }
1671 }
1672 }
1673 }
1674
1675
1676 /**
1677 * Given a Java2D {@code PathIterator} instance,
1678 * this method translates that into a Window's path
1679 * in the printer device context.
1680 */
1681 private void convertToWPath(PathIterator pathIter) {
1682
1683 float[] segment = new float[6];
1684 int segmentType;
1685
1686 WPrinterJob wPrinterJob = (WPrinterJob) getPrinterJob();
1687
1688 /* Map the PathIterator's fill rule into the Window's
1689 * polygon fill rule.
1690 */
1691 int polyFillRule;
1692 if (pathIter.getWindingRule() == PathIterator.WIND_EVEN_ODD) {
1693 polyFillRule = WPrinterJob.POLYFILL_ALTERNATE;
1694 } else {
1695 polyFillRule = WPrinterJob.POLYFILL_WINDING;
1696 }
1697 wPrinterJob.setPolyFillMode(polyFillRule);
|