319 * Nonetheless having them in sync with the attributeset and native 320 * state is probably safer. 321 * Also whereas the startDoc native code pulls the variables directly, 322 * the dialog code does use getter to pull some of these values. 323 * That's an inconsistency we should fix if it causes problems. 324 */ 325 private int mAttSides; 326 private int mAttChromaticity; 327 private int mAttXRes; 328 private int mAttYRes; 329 private int mAttQuality; 330 private int mAttCollate; 331 private int mAttCopies; 332 private int mAttMediaSizeName; 333 private int mAttMediaTray; 334 335 private String mDestination = null; 336 337 /** 338 * The last color set into the print device context or 339 * <code>null</code> if no color has been set. 340 */ 341 private Color mLastColor; 342 343 /** 344 * The last text color set into the print device context or 345 * <code>null</code> if no color has been set. 346 */ 347 private Color mLastTextColor; 348 349 /** 350 * Define the most recent java font set as a GDI font in the printer 351 * device context. mLastFontFamily will be NULL if no 352 * GDI font has been set. 353 */ 354 private String mLastFontFamily; 355 private float mLastFontSize; 356 private int mLastFontStyle; 357 private int mLastRotation; 358 private float mLastAwScale; 359 360 // for AwtPrintControl::InitPrintDialog 361 private PrinterJob pjob; 362 363 private java.awt.peer.ComponentPeer dialogOwnerPeer = null; 364 365 /* Static Initializations */ 385 /* Implement DisposerTarget. Weak references to an Object can delay 386 * its storage reclaimation marginally. 387 * It won't make the native resources be release any more quickly, but 388 * by pointing the reference held by Disposer at an object which becomes 389 * no longer strongly reachable when this WPrinterJob is no longer 390 * strongly reachable, we allow the WPrinterJob to be freed more promptly 391 * than if it were the referenced object. 392 */ 393 private Object disposerReferent = new Object(); 394 395 @Override 396 public Object getDisposerReferent() { 397 return disposerReferent; 398 } 399 400 /* Instance Methods */ 401 402 /** 403 * Display a dialog to the user allowing the modification of a 404 * PageFormat instance. 405 * The <code>page</code> argument is used to initialize controls 406 * in the page setup dialog. 407 * If the user cancels the dialog, then the method returns the 408 * original <code>page</code> object unmodified. 409 * If the user okays the dialog then the method returns a new 410 * PageFormat object with the indicated changes. 411 * In either case the original <code>page</code> object will 412 * not be modified. 413 * @param page the default PageFormat presented to the user 414 * for modification 415 * @return the original <code>page</code> object if the dialog 416 * is cancelled, or a new PageFormat object containing 417 * the format indicated by the user if the dialog is 418 * acknowledged 419 * @exception HeadlessException if GraphicsEnvironment.isHeadless() 420 * returns true. 421 * @see java.awt.GraphicsEnvironment#isHeadless 422 * @since 1.2 423 */ 424 @Override 425 public PageFormat pageDialog(PageFormat page) throws HeadlessException { 426 if (GraphicsEnvironment.isHeadless()) { 427 throw new HeadlessException(); 428 } 429 430 if (!(getPrintService() instanceof Win32PrintService)) { 431 return super.pageDialog(page); 432 } 433 434 PageFormat pageClone = (PageFormat) page.clone(); 435 boolean result = false; 571 // current request attribute set should be reflected to the print dialog. 572 // If null, create new instance of HashPrintRequestAttributeSet. 573 if (attributes == null) { 574 attributes = new HashPrintRequestAttributeSet(); 575 } 576 577 if (!(getPrintService() instanceof Win32PrintService)) { 578 return super.printDialog(attributes); 579 } 580 581 if (noDefaultPrinter == true) { 582 return false; 583 } else { 584 return displayNativeDialog(); 585 } 586 } 587 588 /** 589 * Associate this PrinterJob with a new PrintService. 590 * 591 * Throws <code>PrinterException</code> if the specified service 592 * cannot support the <code>Pageable</code> and 593 * </code>Printable</code> interfaces necessary to support 2D printing. 594 * @param service print service which supports 2D printing. 595 * 596 * @throws PrinterException if the specified service does not support 597 * 2D printing. 598 */ 599 @Override 600 public void setPrintService(PrintService service) 601 throws PrinterException { 602 super.setPrintService(service); 603 if (!(service instanceof Win32PrintService)) { 604 return; 605 } 606 driverDoesMultipleCopies = false; 607 driverDoesCollation = false; 608 setNativePrintServiceIfNeeded(service.getName()); 609 } 610 611 /* associates this job with the specified native service */ 612 private native void setNativePrintService(String name) 746 * the default page size and orientation of the PrinterJob's 747 * current printer. 748 * Note: PageFormat.getPaper() returns a clone and getDefaultPage() 749 * gets that clone so it won't overwrite the original paper. 750 */ 751 @Override 752 public PageFormat defaultPage(PageFormat page) { 753 PageFormat newPage = (PageFormat)page.clone(); 754 getDefaultPage(newPage); 755 return newPage; 756 } 757 758 /** 759 * validate the paper size against the current printer. 760 */ 761 @Override 762 protected native void validatePaper(Paper origPaper, Paper newPaper ); 763 764 /** 765 * Examine the metrics captured by the 766 * <code>PeekGraphics</code> instance and 767 * if capable of directly converting this 768 * print job to the printer's control language 769 * or the native OS's graphics primitives, then 770 * return a <code>PathGraphics</code> to perform 771 * that conversion. If there is not an object 772 * capable of the conversion then return 773 * <code>null</code>. Returning <code>null</code> 774 * causes the print job to be rasterized. 775 */ 776 777 @Override 778 protected Graphics2D createPathGraphics(PeekGraphics peekGraphics, 779 PrinterJob printerJob, 780 Printable painter, 781 PageFormat pageFormat, 782 int pageIndex) { 783 784 WPathGraphics pathGraphics; 785 PeekMetrics metrics = peekGraphics.getMetrics(); 786 787 /* If the application has drawn anything that 788 * out PathGraphics class can not handle then 789 * return a null PathGraphics. If the property 790 * to force the raster pipeline has been set then 791 * we also want to avoid the path (pdl) pipeline 792 * and return null. 793 */ 959 960 protected void moveTo(float x, float y) { 961 moveTo(getPrintDC(), x, y); 962 } 963 964 protected void lineTo(float x, float y) { 965 lineTo(getPrintDC(), x, y); 966 } 967 968 protected void polyBezierTo(float control1x, float control1y, 969 float control2x, float control2y, 970 float endX, float endY) { 971 972 polyBezierTo(getPrintDC(), control1x, control1y, 973 control2x, control2y, 974 endX, endY); 975 } 976 977 /** 978 * Set the current polgon fill rule into the printer device context. 979 * The <code>fillRule</code> should 980 * be one of the following Windows constants: 981 * <code>ALTERNATE</code> or <code>WINDING</code>. 982 */ 983 protected void setPolyFillMode(int fillRule) { 984 setPolyFillMode(getPrintDC(), fillRule); 985 } 986 987 /* 988 * Create a Window's solid brush for the color specified 989 * by <code>(red, green, blue)</code>. Once the brush 990 * is created, select it in the current printing device 991 * context and free the old brush. 992 */ 993 protected void selectSolidBrush(Color color) { 994 995 /* We only need to select a brush if the color has changed. 996 */ 997 if (color.equals(mLastColor) == false) { 998 mLastColor = color; 999 float[] rgb = color.getRGBColorComponents(null); 1000 1001 selectSolidBrush(getPrintDC(), 1002 (int) (rgb[0] * MAX_WCOLOR), 1003 (int) (rgb[1] * MAX_WCOLOR), 1004 (int) (rgb[2] * MAX_WCOLOR)); 1005 } 1006 } 1007 1008 /** 1009 * Return the x coordinate of the current pen 1129 if (color.equals(mLastTextColor) == false) { 1130 mLastTextColor = color; 1131 float[] rgb = color.getRGBColorComponents(null); 1132 1133 setTextColor(getPrintDC(), 1134 (int) (rgb[0] * MAX_WCOLOR), 1135 (int) (rgb[1] * MAX_WCOLOR), 1136 (int) (rgb[2] * MAX_WCOLOR)); 1137 } 1138 } 1139 1140 /** 1141 * Remove control characters. 1142 */ 1143 @Override 1144 protected String removeControlChars(String str) { 1145 return super.removeControlChars(str); 1146 } 1147 1148 /** 1149 * Draw the string <code>text</code> to the printer's 1150 * device context at the specified position. 1151 */ 1152 protected void textOut(String str, float x, float y, 1153 float[] positions) { 1154 /* Don't leave handling of control chars to GDI. 1155 * If control chars are removed, 'positions' isn't valid. 1156 * This means the caller needs to be aware of this and remove 1157 * control chars up front if supplying positions. Since the 1158 * caller is tightly integrated here, that's acceptable. 1159 */ 1160 String text = removeControlChars(str); 1161 assert (positions == null) || (text.length() == str.length()); 1162 if (text.length() == 0) { 1163 return; 1164 } 1165 textOut(getPrintDC(), text, text.length(), false, x, y, positions); 1166 } 1167 1168 /** 1169 * Draw the glyphs <code>glyphs</code> to the printer's 1170 * device context at the specified position. 1171 */ 1172 protected void glyphsOut(int []glyphs, float x, float y, 1173 float[] positions) { 1174 1175 /* TrueType glyph codes are 16 bit values, so can be packed 1176 * in a unicode string, and that's how GDI expects them. 1177 * A flag bit is set to indicate to GDI that these are glyphs, 1178 * not characters. The positions array must always be non-null 1179 * here for our purposes, although if not supplied, GDI should 1180 * just use the default advances for the glyphs. 1181 * Mask out upper 16 bits to remove any slot from a composite. 1182 */ 1183 char[] glyphCharArray = new char[glyphs.length]; 1184 for (int i=0;i<glyphs.length;i++) { 1185 glyphCharArray[i] = (char)(glyphs[i] & 0xffff); 1186 } 1187 String glyphStr = new String(glyphCharArray); 1188 textOut(getPrintDC(), glyphStr, glyphs.length, true, x, y, positions); 1189 } 1191 1192 /** 1193 * Get the advance of this text that GDI returns for the 1194 * font currently selected into the GDI device context for 1195 * this job. Note that the removed control characters are 1196 * interpreted as zero-width by JDK and we remove them for 1197 * rendering so also remove them for measurement so that 1198 * this measurement can be properly compared with JDK measurement. 1199 */ 1200 protected int getGDIAdvance(String text) { 1201 /* Don't leave handling of control chars to GDI. */ 1202 text = removeControlChars(text); 1203 if (text.length() == 0) { 1204 return 0; 1205 } 1206 return getGDIAdvance(getPrintDC(), text); 1207 } 1208 1209 /** 1210 * Draw the 24 bit BGR image buffer represented by 1211 * <code>image</code> to the GDI device context 1212 * <code>printDC</code>. The image is drawn at 1213 * <code>(destX, destY)</code> in device coordinates. 1214 * The image is scaled into a square of size 1215 * specified by <code>destWidth</code> and 1216 * <code>destHeight</code>. The portion of the 1217 * source image copied into that square is specified 1218 * by <code>srcX</code>, <code>srcY</code>, 1219 * <code>srcWidth</code>, and srcHeight. 1220 */ 1221 protected void drawImage3ByteBGR(byte[] image, 1222 float destX, float destY, 1223 float destWidth, float destHeight, 1224 float srcX, float srcY, 1225 float srcWidth, float srcHeight) { 1226 1227 1228 drawDIBImage(getPrintDC(), image, 1229 destX, destY, 1230 destWidth, destHeight, 1231 srcX, srcY, 1232 srcWidth, srcHeight, 1233 24, null); 1234 1235 } 1236 1237 /* If 'icm' is null we expect its 24 bit (ie 3BYTE_BGR). 1238 * If 'icm' is non-null we expect its no more than 8 bpp and 1239 * specifically must be a valid DIB sizes : 1, 4 or 8 bpp. 1395 /** 1396 * End a page. This call's Window's EndPage 1397 * routine. 1398 */ 1399 protected native void deviceEndPage(PageFormat format, Printable painter, 1400 int index); 1401 1402 /** 1403 * Prints the contents of the array of ints, 'data' 1404 * to the current page. The band is placed at the 1405 * location (x, y) in device coordinates on the 1406 * page. The width and height of the band is 1407 * specified by the caller. 1408 */ 1409 @Override 1410 protected native void printBand(byte[] data, int x, int y, 1411 int width, int height); 1412 1413 /** 1414 * Begin a Window's rendering path in the device 1415 * context <code>printDC</code>. 1416 */ 1417 protected native void beginPath(long printDC); 1418 1419 /** 1420 * End a Window's rendering path in the device 1421 * context <code>printDC</code>. 1422 */ 1423 protected native void endPath(long printDC); 1424 1425 /** 1426 * Close a subpath in a Window's rendering path in the device 1427 * context <code>printDC</code>. 1428 */ 1429 protected native void closeFigure(long printDC); 1430 1431 /** 1432 * Fill a defined Window's rendering path in the device 1433 * context <code>printDC</code>. 1434 */ 1435 protected native void fillPath(long printDC); 1436 1437 /** 1438 * Move the Window's pen position to <code>(x,y)</code> 1439 * in the device context <code>printDC</code>. 1440 */ 1441 protected native void moveTo(long printDC, float x, float y); 1442 1443 /** 1444 * Draw a line from the current pen position to 1445 * <code>(x,y)</code> in the device context <code>printDC</code>. 1446 */ 1447 protected native void lineTo(long printDC, float x, float y); 1448 1449 protected native void polyBezierTo(long printDC, 1450 float control1x, float control1y, 1451 float control2x, float control2y, 1452 float endX, float endY); 1453 1454 /** 1455 * Set the current polgon fill rule into the device context 1456 * <code>printDC</code>. The <code>fillRule</code> should 1457 * be one of the following Windows constants: 1458 * <code>ALTERNATE</code> or <code>WINDING</code>. 1459 */ 1460 protected native void setPolyFillMode(long printDC, int fillRule); 1461 1462 /** 1463 * Create a Window's solid brush for the color specified 1464 * by <code>(red, green, blue)</code>. Once the brush 1465 * is created, select it in the device 1466 * context <code>printDC</code> and free the old brush. 1467 */ 1468 protected native void selectSolidBrush(long printDC, 1469 int red, int green, int blue); 1470 1471 /** 1472 * Return the x coordinate of the current pen 1473 * position in the device context 1474 * <code>printDC</code>. 1475 */ 1476 protected native int getPenX(long printDC); 1477 1478 /** 1479 * Return the y coordinate of the current pen 1480 * position in the device context 1481 * <code>printDC</code>. 1482 */ 1483 protected native int getPenY(long printDC); 1484 1485 /** 1486 * Select the device context's current path 1487 * to be the clipping path. 1488 */ 1489 protected native void selectClipPath(long printDC); 1490 1491 /** 1492 * Draw a rectangle using specified brush. 1493 */ 1494 protected native void frameRect(long printDC, float x, float y, 1495 float width, float height); 1496 1497 /** 1498 * Fill a rectangle specified by the coordinates using 1499 * specified brush. 1500 */ 1501 protected native void fillRect(long printDC, float x, float y, 1520 /** 1521 * Set a GDI font capable of drawing the java Font 1522 * passed in. 1523 */ 1524 protected native boolean setFont(long printDC, String familyName, 1525 float fontSize, 1526 boolean bold, 1527 boolean italic, 1528 int rotation, 1529 float awScale); 1530 1531 1532 /** 1533 * Set the GDI color for text drawing. 1534 */ 1535 protected native void setTextColor(long printDC, 1536 int red, int green, int blue); 1537 1538 1539 /** 1540 * Draw the string <code>text</code> into the device 1541 * context <code>printDC</code> at the specified 1542 * position. 1543 */ 1544 protected native void textOut(long printDC, String text, 1545 int strlen, boolean glyphs, 1546 float x, float y, float[] positions); 1547 1548 1549 private native int getGDIAdvance(long printDC, String text); 1550 1551 /** 1552 * Draw the DIB compatible image buffer represented by 1553 * <code>image</code> to the GDI device context 1554 * <code>printDC</code>. The image is drawn at 1555 * <code>(destX, destY)</code> in device coordinates. 1556 * The image is scaled into a square of size 1557 * specified by <code>destWidth</code> and 1558 * <code>destHeight</code>. The portion of the 1559 * source image copied into that square is specified 1560 * by <code>srcX</code>, <code>srcY</code>, 1561 * <code>srcWidth</code>, and srcHeight. 1562 * Note that the image isn't completely compatible with DIB format. 1563 * At the very least it needs to be padded so each scanline is 1564 * DWORD aligned. Also we "flip" the image to make it a bottom-up DIB. 1565 */ 1566 private native void drawDIBImage(long printDC, byte[] image, 1567 float destX, float destY, 1568 float destWidth, float destHeight, 1569 float srcX, float srcY, 1570 float srcWidth, float srcHeight, 1571 int bitCount, byte[] bmiColors); 1572 1573 1574 //** BEGIN Functions called by native code for querying/updating attributes 1575 1576 private String getPrinterAttrib() { 1577 // getPrintService will get current print service or default if none 1578 PrintService service = this.getPrintService(); 1579 String name = (service != null) ? service.getName() : null; 1580 return name; 1581 } | 319 * Nonetheless having them in sync with the attributeset and native 320 * state is probably safer. 321 * Also whereas the startDoc native code pulls the variables directly, 322 * the dialog code does use getter to pull some of these values. 323 * That's an inconsistency we should fix if it causes problems. 324 */ 325 private int mAttSides; 326 private int mAttChromaticity; 327 private int mAttXRes; 328 private int mAttYRes; 329 private int mAttQuality; 330 private int mAttCollate; 331 private int mAttCopies; 332 private int mAttMediaSizeName; 333 private int mAttMediaTray; 334 335 private String mDestination = null; 336 337 /** 338 * The last color set into the print device context or 339 * {@code null} if no color has been set. 340 */ 341 private Color mLastColor; 342 343 /** 344 * The last text color set into the print device context or 345 * {@code null} if no color has been set. 346 */ 347 private Color mLastTextColor; 348 349 /** 350 * Define the most recent java font set as a GDI font in the printer 351 * device context. mLastFontFamily will be NULL if no 352 * GDI font has been set. 353 */ 354 private String mLastFontFamily; 355 private float mLastFontSize; 356 private int mLastFontStyle; 357 private int mLastRotation; 358 private float mLastAwScale; 359 360 // for AwtPrintControl::InitPrintDialog 361 private PrinterJob pjob; 362 363 private java.awt.peer.ComponentPeer dialogOwnerPeer = null; 364 365 /* Static Initializations */ 385 /* Implement DisposerTarget. Weak references to an Object can delay 386 * its storage reclaimation marginally. 387 * It won't make the native resources be release any more quickly, but 388 * by pointing the reference held by Disposer at an object which becomes 389 * no longer strongly reachable when this WPrinterJob is no longer 390 * strongly reachable, we allow the WPrinterJob to be freed more promptly 391 * than if it were the referenced object. 392 */ 393 private Object disposerReferent = new Object(); 394 395 @Override 396 public Object getDisposerReferent() { 397 return disposerReferent; 398 } 399 400 /* Instance Methods */ 401 402 /** 403 * Display a dialog to the user allowing the modification of a 404 * PageFormat instance. 405 * The {@code page} argument is used to initialize controls 406 * in the page setup dialog. 407 * If the user cancels the dialog, then the method returns the 408 * original {@code page} object unmodified. 409 * If the user okays the dialog then the method returns a new 410 * PageFormat object with the indicated changes. 411 * In either case the original {@code page} object will 412 * not be modified. 413 * @param page the default PageFormat presented to the user 414 * for modification 415 * @return the original {@code page} object if the dialog 416 * is cancelled, or a new PageFormat object containing 417 * the format indicated by the user if the dialog is 418 * acknowledged 419 * @exception HeadlessException if GraphicsEnvironment.isHeadless() 420 * returns true. 421 * @see java.awt.GraphicsEnvironment#isHeadless 422 * @since 1.2 423 */ 424 @Override 425 public PageFormat pageDialog(PageFormat page) throws HeadlessException { 426 if (GraphicsEnvironment.isHeadless()) { 427 throw new HeadlessException(); 428 } 429 430 if (!(getPrintService() instanceof Win32PrintService)) { 431 return super.pageDialog(page); 432 } 433 434 PageFormat pageClone = (PageFormat) page.clone(); 435 boolean result = false; 571 // current request attribute set should be reflected to the print dialog. 572 // If null, create new instance of HashPrintRequestAttributeSet. 573 if (attributes == null) { 574 attributes = new HashPrintRequestAttributeSet(); 575 } 576 577 if (!(getPrintService() instanceof Win32PrintService)) { 578 return super.printDialog(attributes); 579 } 580 581 if (noDefaultPrinter == true) { 582 return false; 583 } else { 584 return displayNativeDialog(); 585 } 586 } 587 588 /** 589 * Associate this PrinterJob with a new PrintService. 590 * 591 * Throws {@code PrinterException} if the specified service 592 * cannot support the {@code Pageable} and 593 * </code>Printable</code> interfaces necessary to support 2D printing. 594 * @param service print service which supports 2D printing. 595 * 596 * @throws PrinterException if the specified service does not support 597 * 2D printing. 598 */ 599 @Override 600 public void setPrintService(PrintService service) 601 throws PrinterException { 602 super.setPrintService(service); 603 if (!(service instanceof Win32PrintService)) { 604 return; 605 } 606 driverDoesMultipleCopies = false; 607 driverDoesCollation = false; 608 setNativePrintServiceIfNeeded(service.getName()); 609 } 610 611 /* associates this job with the specified native service */ 612 private native void setNativePrintService(String name) 746 * the default page size and orientation of the PrinterJob's 747 * current printer. 748 * Note: PageFormat.getPaper() returns a clone and getDefaultPage() 749 * gets that clone so it won't overwrite the original paper. 750 */ 751 @Override 752 public PageFormat defaultPage(PageFormat page) { 753 PageFormat newPage = (PageFormat)page.clone(); 754 getDefaultPage(newPage); 755 return newPage; 756 } 757 758 /** 759 * validate the paper size against the current printer. 760 */ 761 @Override 762 protected native void validatePaper(Paper origPaper, Paper newPaper ); 763 764 /** 765 * Examine the metrics captured by the 766 * {@code PeekGraphics} instance and 767 * if capable of directly converting this 768 * print job to the printer's control language 769 * or the native OS's graphics primitives, then 770 * return a {@code PathGraphics} to perform 771 * that conversion. If there is not an object 772 * capable of the conversion then return 773 * {@code null}. Returning {@code null} 774 * causes the print job to be rasterized. 775 */ 776 777 @Override 778 protected Graphics2D createPathGraphics(PeekGraphics peekGraphics, 779 PrinterJob printerJob, 780 Printable painter, 781 PageFormat pageFormat, 782 int pageIndex) { 783 784 WPathGraphics pathGraphics; 785 PeekMetrics metrics = peekGraphics.getMetrics(); 786 787 /* If the application has drawn anything that 788 * out PathGraphics class can not handle then 789 * return a null PathGraphics. If the property 790 * to force the raster pipeline has been set then 791 * we also want to avoid the path (pdl) pipeline 792 * and return null. 793 */ 959 960 protected void moveTo(float x, float y) { 961 moveTo(getPrintDC(), x, y); 962 } 963 964 protected void lineTo(float x, float y) { 965 lineTo(getPrintDC(), x, y); 966 } 967 968 protected void polyBezierTo(float control1x, float control1y, 969 float control2x, float control2y, 970 float endX, float endY) { 971 972 polyBezierTo(getPrintDC(), control1x, control1y, 973 control2x, control2y, 974 endX, endY); 975 } 976 977 /** 978 * Set the current polgon fill rule into the printer device context. 979 * The {@code fillRule} should 980 * be one of the following Windows constants: 981 * {@code ALTERNATE} or {@code WINDING}. 982 */ 983 protected void setPolyFillMode(int fillRule) { 984 setPolyFillMode(getPrintDC(), fillRule); 985 } 986 987 /* 988 * Create a Window's solid brush for the color specified 989 * by {@code (red, green, blue)}. Once the brush 990 * is created, select it in the current printing device 991 * context and free the old brush. 992 */ 993 protected void selectSolidBrush(Color color) { 994 995 /* We only need to select a brush if the color has changed. 996 */ 997 if (color.equals(mLastColor) == false) { 998 mLastColor = color; 999 float[] rgb = color.getRGBColorComponents(null); 1000 1001 selectSolidBrush(getPrintDC(), 1002 (int) (rgb[0] * MAX_WCOLOR), 1003 (int) (rgb[1] * MAX_WCOLOR), 1004 (int) (rgb[2] * MAX_WCOLOR)); 1005 } 1006 } 1007 1008 /** 1009 * Return the x coordinate of the current pen 1129 if (color.equals(mLastTextColor) == false) { 1130 mLastTextColor = color; 1131 float[] rgb = color.getRGBColorComponents(null); 1132 1133 setTextColor(getPrintDC(), 1134 (int) (rgb[0] * MAX_WCOLOR), 1135 (int) (rgb[1] * MAX_WCOLOR), 1136 (int) (rgb[2] * MAX_WCOLOR)); 1137 } 1138 } 1139 1140 /** 1141 * Remove control characters. 1142 */ 1143 @Override 1144 protected String removeControlChars(String str) { 1145 return super.removeControlChars(str); 1146 } 1147 1148 /** 1149 * Draw the string {@code text} to the printer's 1150 * device context at the specified position. 1151 */ 1152 protected void textOut(String str, float x, float y, 1153 float[] positions) { 1154 /* Don't leave handling of control chars to GDI. 1155 * If control chars are removed, 'positions' isn't valid. 1156 * This means the caller needs to be aware of this and remove 1157 * control chars up front if supplying positions. Since the 1158 * caller is tightly integrated here, that's acceptable. 1159 */ 1160 String text = removeControlChars(str); 1161 assert (positions == null) || (text.length() == str.length()); 1162 if (text.length() == 0) { 1163 return; 1164 } 1165 textOut(getPrintDC(), text, text.length(), false, x, y, positions); 1166 } 1167 1168 /** 1169 * Draw the glyphs {@code glyphs} to the printer's 1170 * device context at the specified position. 1171 */ 1172 protected void glyphsOut(int []glyphs, float x, float y, 1173 float[] positions) { 1174 1175 /* TrueType glyph codes are 16 bit values, so can be packed 1176 * in a unicode string, and that's how GDI expects them. 1177 * A flag bit is set to indicate to GDI that these are glyphs, 1178 * not characters. The positions array must always be non-null 1179 * here for our purposes, although if not supplied, GDI should 1180 * just use the default advances for the glyphs. 1181 * Mask out upper 16 bits to remove any slot from a composite. 1182 */ 1183 char[] glyphCharArray = new char[glyphs.length]; 1184 for (int i=0;i<glyphs.length;i++) { 1185 glyphCharArray[i] = (char)(glyphs[i] & 0xffff); 1186 } 1187 String glyphStr = new String(glyphCharArray); 1188 textOut(getPrintDC(), glyphStr, glyphs.length, true, x, y, positions); 1189 } 1191 1192 /** 1193 * Get the advance of this text that GDI returns for the 1194 * font currently selected into the GDI device context for 1195 * this job. Note that the removed control characters are 1196 * interpreted as zero-width by JDK and we remove them for 1197 * rendering so also remove them for measurement so that 1198 * this measurement can be properly compared with JDK measurement. 1199 */ 1200 protected int getGDIAdvance(String text) { 1201 /* Don't leave handling of control chars to GDI. */ 1202 text = removeControlChars(text); 1203 if (text.length() == 0) { 1204 return 0; 1205 } 1206 return getGDIAdvance(getPrintDC(), text); 1207 } 1208 1209 /** 1210 * Draw the 24 bit BGR image buffer represented by 1211 * {@code image} to the GDI device context 1212 * {@code printDC}. The image is drawn at 1213 * {@code (destX, destY)} in device coordinates. 1214 * The image is scaled into a square of size 1215 * specified by {@code destWidth} and 1216 * {@code destHeight}. The portion of the 1217 * source image copied into that square is specified 1218 * by {@code srcX}, {@code srcY}, 1219 * {@code srcWidth}, and srcHeight. 1220 */ 1221 protected void drawImage3ByteBGR(byte[] image, 1222 float destX, float destY, 1223 float destWidth, float destHeight, 1224 float srcX, float srcY, 1225 float srcWidth, float srcHeight) { 1226 1227 1228 drawDIBImage(getPrintDC(), image, 1229 destX, destY, 1230 destWidth, destHeight, 1231 srcX, srcY, 1232 srcWidth, srcHeight, 1233 24, null); 1234 1235 } 1236 1237 /* If 'icm' is null we expect its 24 bit (ie 3BYTE_BGR). 1238 * If 'icm' is non-null we expect its no more than 8 bpp and 1239 * specifically must be a valid DIB sizes : 1, 4 or 8 bpp. 1395 /** 1396 * End a page. This call's Window's EndPage 1397 * routine. 1398 */ 1399 protected native void deviceEndPage(PageFormat format, Printable painter, 1400 int index); 1401 1402 /** 1403 * Prints the contents of the array of ints, 'data' 1404 * to the current page. The band is placed at the 1405 * location (x, y) in device coordinates on the 1406 * page. The width and height of the band is 1407 * specified by the caller. 1408 */ 1409 @Override 1410 protected native void printBand(byte[] data, int x, int y, 1411 int width, int height); 1412 1413 /** 1414 * Begin a Window's rendering path in the device 1415 * context {@code printDC}. 1416 */ 1417 protected native void beginPath(long printDC); 1418 1419 /** 1420 * End a Window's rendering path in the device 1421 * context {@code printDC}. 1422 */ 1423 protected native void endPath(long printDC); 1424 1425 /** 1426 * Close a subpath in a Window's rendering path in the device 1427 * context {@code printDC}. 1428 */ 1429 protected native void closeFigure(long printDC); 1430 1431 /** 1432 * Fill a defined Window's rendering path in the device 1433 * context {@code printDC}. 1434 */ 1435 protected native void fillPath(long printDC); 1436 1437 /** 1438 * Move the Window's pen position to {@code (x,y)} 1439 * in the device context {@code printDC}. 1440 */ 1441 protected native void moveTo(long printDC, float x, float y); 1442 1443 /** 1444 * Draw a line from the current pen position to 1445 * {@code (x,y)} in the device context {@code printDC}. 1446 */ 1447 protected native void lineTo(long printDC, float x, float y); 1448 1449 protected native void polyBezierTo(long printDC, 1450 float control1x, float control1y, 1451 float control2x, float control2y, 1452 float endX, float endY); 1453 1454 /** 1455 * Set the current polgon fill rule into the device context 1456 * {@code printDC}. The {@code fillRule} should 1457 * be one of the following Windows constants: 1458 * {@code ALTERNATE} or {@code WINDING}. 1459 */ 1460 protected native void setPolyFillMode(long printDC, int fillRule); 1461 1462 /** 1463 * Create a Window's solid brush for the color specified 1464 * by {@code (red, green, blue)}. Once the brush 1465 * is created, select it in the device 1466 * context {@code printDC} and free the old brush. 1467 */ 1468 protected native void selectSolidBrush(long printDC, 1469 int red, int green, int blue); 1470 1471 /** 1472 * Return the x coordinate of the current pen 1473 * position in the device context 1474 * {@code printDC}. 1475 */ 1476 protected native int getPenX(long printDC); 1477 1478 /** 1479 * Return the y coordinate of the current pen 1480 * position in the device context 1481 * {@code printDC}. 1482 */ 1483 protected native int getPenY(long printDC); 1484 1485 /** 1486 * Select the device context's current path 1487 * to be the clipping path. 1488 */ 1489 protected native void selectClipPath(long printDC); 1490 1491 /** 1492 * Draw a rectangle using specified brush. 1493 */ 1494 protected native void frameRect(long printDC, float x, float y, 1495 float width, float height); 1496 1497 /** 1498 * Fill a rectangle specified by the coordinates using 1499 * specified brush. 1500 */ 1501 protected native void fillRect(long printDC, float x, float y, 1520 /** 1521 * Set a GDI font capable of drawing the java Font 1522 * passed in. 1523 */ 1524 protected native boolean setFont(long printDC, String familyName, 1525 float fontSize, 1526 boolean bold, 1527 boolean italic, 1528 int rotation, 1529 float awScale); 1530 1531 1532 /** 1533 * Set the GDI color for text drawing. 1534 */ 1535 protected native void setTextColor(long printDC, 1536 int red, int green, int blue); 1537 1538 1539 /** 1540 * Draw the string {@code text} into the device 1541 * context {@code printDC} at the specified 1542 * position. 1543 */ 1544 protected native void textOut(long printDC, String text, 1545 int strlen, boolean glyphs, 1546 float x, float y, float[] positions); 1547 1548 1549 private native int getGDIAdvance(long printDC, String text); 1550 1551 /** 1552 * Draw the DIB compatible image buffer represented by 1553 * {@code image} to the GDI device context 1554 * {@code printDC}. The image is drawn at 1555 * {@code (destX, destY)} in device coordinates. 1556 * The image is scaled into a square of size 1557 * specified by {@code destWidth} and 1558 * {@code destHeight}. The portion of the 1559 * source image copied into that square is specified 1560 * by {@code srcX}, {@code srcY}, 1561 * {@code srcWidth}, and srcHeight. 1562 * Note that the image isn't completely compatible with DIB format. 1563 * At the very least it needs to be padded so each scanline is 1564 * DWORD aligned. Also we "flip" the image to make it a bottom-up DIB. 1565 */ 1566 private native void drawDIBImage(long printDC, byte[] image, 1567 float destX, float destY, 1568 float destWidth, float destHeight, 1569 float srcX, float srcY, 1570 float srcWidth, float srcHeight, 1571 int bitCount, byte[] bmiColors); 1572 1573 1574 //** BEGIN Functions called by native code for querying/updating attributes 1575 1576 private String getPrinterAttrib() { 1577 // getPrintService will get current print service or default if none 1578 PrintService service = this.getPrintService(); 1579 String name = (service != null) ? service.getName() : null; 1580 return name; 1581 } |