IV. Les problèmes rencontrés▲
Dans le chapitre précédent, nous avons vu brièvement comment imprimer en Java. Ce chapitre énumère les différents problèmes et lacunes que j'ai pu rencontrer lors de l'impression.
IV-A. Boîtes de configuration natives ou non▲
Nous avons vu que la méthode printDialog affiche deux boîtes différentes en fonction de la présence ou non d'un set de requêtes. Ne peut-on pas spécifier un set de requêtes et conserver la boîte de configuration native qui est plus complète ?
IV-B. La gestion de la résolution de l'impression▲
En consultant la documentation de PageFormat, on constate que toutes les méthodes retournent des mesures en 1/72 de pouce soit du 72 DPI.
Faisons le petit test suivant :
import
java.awt.Graphics;
import
java.awt.Graphics2D;
import
java.awt.Rectangle;
import
java.awt.print.PageFormat;
import
java.awt.print.Printable;
import
java.awt.print.PrinterException;
public
class
PrintResolution implements
Printable {
/** Constructeur par défaut de PrintResolution */
public
PrintResolution (
) {
}
public
int
print
(
Graphics graphics, PageFormat pageFormat, int
pageIndex) throws
PrinterException {
int
retValue =
Printable.NO_SUCH_PAGE;
if
(
pageIndex ==
0
){
Graphics2D g2d =
(
Graphics2D)graphics;
// Device
String text =
"Taille du device : "
+
g2d.getDeviceConfiguration
(
).getBounds
(
).toString
(
);
graphics.drawString
(
text, (
int
)(
pageFormat.getImageableX
(
)), (
int
)(
pageFormat.getImageableY
(
)+
pageFormat.getImageableHeight
(
)/
3.0
));
// clipping
text =
"Taille du clipping : "
+
g2d.getClipBounds
(
).toString
(
);
graphics.drawString
(
text, (
int
)(
pageFormat.getImageableX
(
)), (
int
)(
pageFormat.getImageableY
(
)+
pageFormat.getImageableHeight
(
)/
2.0
));
// imageable
Rectangle rect =
new
Rectangle
((
int
)pageFormat.getImageableX
(
),
(
int
)pageFormat.getImageableY
(
),
(
int
)pageFormat.getImageableWidth
(
),
(
int
)pageFormat.getImageableHeight
(
));
text =
"Taille de l'imageable : "
+
rect.toString
(
);
graphics.drawString
(
text, (
int
)(
pageFormat.getImageableX
(
)), (
int
)(
pageFormat.getImageableY
(
)+
2.0
*
pageFormat.getImageableHeight
(
)/
3.0
));
retValue =
PAGE_EXISTS;
}
return
retValue;
}
}
Pour une impression configurée en 600 DPI, nous pouvons avoir le résultat suivant (en fonction des marges acceptées par l'imprimante) :
- Taille du device : java.awt.Rectangle[x=0,y=0,width=4960,height=7015]
- Taille du clipping : java.awt.Rectangle[x=0,y=0,width=595,height=842]
- Taille de l'imageable : java.awt.Rectangle[x=0,y=0,width=594,height=841]
Ainsi le contexte graphique transmis à la méthode print est toujours configuré en 72 DPI, c'est-à-dire qu'une ligne de 72 pixels de long aura pour longueur un pouce sur la feuille. Pourtant l'utilisateur a demandé une impression en 600 DPI. Comment faire pour respecter cette résolution ?
Ce choix de résolution fixe à 72 DPI s'explique facilement pour la gestion des polices de caractères ; toutes les tailles de police en java étant exprimées en points c'est-à-dire en 1/72 de pouce. Cette gestion de la taille de police pose un problème si l'affichage a lieu à une autre résolution que les fameux 72 DPI.
Ainsi, pour un affichage en 72 DPI, une police de 12 points a donc une hauteur de 12 pixels. Les contextes graphiques de java considèrent automatiquement que la résolution d'affichage est de 72 DPI. Pour obtenir un affichage à une résolution autre, il faudra donc retailler le texte en fonction ; dans une résolution de 600 DPI, une police de 12 points a une hauteur de :
1 pouce => 600 pixels => 72 points
0.1667 pouces => 100 pixels => 12 points
Remarque : Ce problème de taille de caractères survient même à l'écran. En effet, sous Windows, la résolution native de l'écran est du 96 DPI voire plus alors que les contextes java se considèrent en 72 DPI. C'est pourquoi une police de 12 points java est plus petite qu'une police 12 points système comme y répond l'extrait de la FAQ de Sun ci-dessous :
Q: Why does (eg) a 10 pt font in Java applications appear to have a different size from the same font at 10pt in a native application?
A: Conversion from the size in points into device pixels depends on device resolution as reported by the platform APIs. Java 2D defaults to assuming 72 dpi. Platform defaults vary. Mac OS also uses 72 dpi. Linux desktops based on GTK (Gnome) or Qt (KDE) typically default to 96 dpi and let the end-user customise what they want to use. Windows defaults to 96 dpi (VGA resolution) and also offers 120 dpi (large fonts size) and lets users further specify a custom resolution. So a couple of things can now be seen
* The DPI reported by platform APIs likely has no correspondence to the true DPI of the display device
* Its unlikely that Java 2D's default matches the platform default.
So a typical results is that for Window's default 96 DPI that a 10 pt font in a Java application is 72/96 of the size of the native counterpart.
Note that Swing's Windows and GTK L&Fs do scale fonts based on the system DPI to match the desktop. If you want to do the same in your application you can call java.awt.Toolkit.getScreenResolution() and use this to apply a simple scale to the size you specify for fonts.
http://java.sun.com/products/java-media/2D/reference/faqs/index.html#Q_What_are_the_different_ways_th
IV-C. L'aperçu avant impression▲
Java ne propose aucune API pour afficher un aperçu avant impression c'est-à-dire émuler l'affichage d'une page imprimée en 600 DPI monochrome par exemple, sur un écran en 96 DPI couleur.
IV-D. Le découpage en bande▲
Une page A4 en 600 DPI atteint des dimensions de l'ordre de 5000x7000 pixels. Ces tailles peuvent être très coûteuses en mémoire pour imprimer des images par exemple. L'impression doit donc découper en bandes l'image finale pour se cantonner à des dimensions négligeables en mémoire.
IV-E. Afficher la progression de l'impression▲
Une impression n'est pas une opération rapide. Il faut donc informer l'utilisateur de la progression de celle-ci. Il n'est pas superflu non plus d'offrir à l'utilisateur la possibilité d'annuler l'impression.