Develop and Download Open Source Software

Browse Subversion Repository

Annotation of /jpki-pdf-signer/trunk/src/main/java/net/osdn/jpki/pdf_signer/MainApp.java

Parent Directory Parent Directory | Revision Log Revision Log


Revision 68 - (hide annotations) (download) (as text)
Mon Jan 9 00:38:35 2023 UTC (15 months, 1 week ago) by hirukawa_ryo
File MIME type: text/x-java
File size: 28849 byte(s)
JPKI PDF SIGNER 1.2.7
スプラッシュスクリーンを廃止しました。
画面の一部が再描画されずに白くなってしまうバグの回避策 prism.dirtyopts=false を追加しました。
広域例外ハンドラーを設定しました。
1 hirukawa_ryo 31 package net.osdn.jpki.pdf_signer;
2    
3     import javafx.application.Platform;
4     import javafx.beans.binding.Bindings;
5     import javafx.beans.binding.ObjectBinding;
6 hirukawa_ryo 39 import javafx.beans.binding.StringBinding;
7 hirukawa_ryo 47 import javafx.beans.property.BooleanProperty;
8 hirukawa_ryo 31 import javafx.beans.property.ObjectProperty;
9 hirukawa_ryo 47 import javafx.beans.property.SimpleBooleanProperty;
10 hirukawa_ryo 31 import javafx.beans.property.SimpleObjectProperty;
11     import javafx.event.ActionEvent;
12     import javafx.fxml.FXML;
13     import javafx.fxml.Initializable;
14     import javafx.geometry.Rectangle2D;
15     import javafx.scene.Cursor;
16     import javafx.scene.Parent;
17     import javafx.scene.Scene;
18     import javafx.scene.control.Button;
19     import javafx.scene.control.ButtonType;
20     import javafx.scene.control.ListCell;
21     import javafx.scene.control.ListView;
22     import javafx.scene.control.MenuItem;
23 hirukawa_ryo 47 import javafx.scene.control.ProgressIndicator;
24 hirukawa_ryo 31 import javafx.scene.image.Image;
25     import javafx.scene.image.ImageView;
26     import javafx.scene.input.DragEvent;
27     import javafx.scene.input.MouseButton;
28     import javafx.scene.input.MouseEvent;
29     import javafx.scene.input.TransferMode;
30     import javafx.stage.FileChooser;
31     import javafx.stage.Stage;
32     import net.osdn.jpki.pdf_signer.control.LicenseDialog;
33     import net.osdn.jpki.pdf_signer.control.Toast;
34     import net.osdn.jpki.wrapper.JpkiException;
35     import net.osdn.jpki.wrapper.JpkiWrapper;
36 hirukawa_ryo 66 import net.osdn.util.javafx.Unchecked;
37 hirukawa_ryo 31 import net.osdn.util.javafx.application.SingletonApplication;
38 hirukawa_ryo 66 import net.osdn.util.javafx.concurrent.AsyncTask;
39 hirukawa_ryo 31 import net.osdn.util.javafx.fxml.Fxml;
40 hirukawa_ryo 66 import net.osdn.util.javafx.scene.SceneUtil;
41 hirukawa_ryo 31 import net.osdn.util.javafx.scene.control.Dialogs;
42     import net.osdn.util.javafx.scene.control.pdf.Pager;
43     import net.osdn.util.javafx.scene.control.pdf.PdfView;
44     import net.osdn.util.javafx.stage.StageUtil;
45     import org.apache.pdfbox.pdmodel.PDDocument;
46     import org.apache.pdfbox.pdmodel.common.PDRectangle;
47     import org.apache.pdfbox.pdmodel.interactive.digitalsignature.SignatureOptions;
48     import org.apache.pdfbox.pdmodel.interactive.digitalsignature.visible.PDVisibleSigProperties;
49     import org.apache.pdfbox.pdmodel.interactive.digitalsignature.visible.PDVisibleSignDesigner;
50    
51 hirukawa_ryo 62 import javax.imageio.ImageIO;
52 hirukawa_ryo 31 import java.awt.Desktop;
53 hirukawa_ryo 62 import java.awt.Graphics2D;
54     import java.awt.image.BufferedImage;
55     import java.io.ByteArrayInputStream;
56     import java.io.ByteArrayOutputStream;
57 hirukawa_ryo 31 import java.io.File;
58     import java.io.FileInputStream;
59     import java.io.FileOutputStream;
60     import java.io.IOException;
61     import java.io.InputStream;
62     import java.io.OutputStream;
63 hirukawa_ryo 39 import java.io.UncheckedIOException;
64 hirukawa_ryo 31 import java.net.URI;
65     import java.net.URL;
66     import java.nio.file.Files;
67     import java.nio.file.StandardCopyOption;
68     import java.util.List;
69     import java.util.ResourceBundle;
70 hirukawa_ryo 66 import java.util.concurrent.ExecutorService;
71     import java.util.concurrent.Executors;
72 hirukawa_ryo 31 import java.util.prefs.Preferences;
73    
74 hirukawa_ryo 57 public class MainApp extends SingletonApplication implements Initializable {
75 hirukawa_ryo 31
76     public static final String APPLICATION_NAME = "JPKI PDF SIGNER";
77     public static final String APPLICATION_VERSION;
78    
79 hirukawa_ryo 66 public static ExecutorService serialExecutor = Executors.newSingleThreadExecutor();
80    
81 hirukawa_ryo 31 static {
82     System.setProperty(
83     "org.apache.commons.logging.LogFactory", "net.osdn.jpki.pdf_signer.LogFilter");
84     LogFilter.setLevel("org.apache.pdfbox", LogFilter.Level.ERROR);
85     LogFilter.setLevel("org.apache.fontbox", LogFilter.Level.ERROR);
86    
87     int[] version = Datastore.getApplicationVersion();
88     if(version != null) {
89     if (version[2] == 0) {
90     APPLICATION_VERSION = String.format("%d.%d", version[0], version[1]);
91     } else {
92     APPLICATION_VERSION = String.format("%d.%d.%d", version[0], version[1], version[2]);
93     }
94     } else {
95     APPLICATION_VERSION = "";
96     }
97     }
98    
99     @Override
100     public void start(Stage primaryStage) throws Exception {
101 hirukawa_ryo 37 primaryStage.getIcons().add(new Image(getClass().getResourceAsStream("/img/app-icon-48px.png")));
102 hirukawa_ryo 39 primaryStage.titleProperty().bind(new StringBinding() {
103     {
104     bind(inputFileProperty);
105     }
106     @Override
107     protected String computeValue() {
108     try {
109     return (inputFileProperty.get() != null ? inputFileProperty.get().getCanonicalPath() + " - " : "")
110     + APPLICATION_NAME + " " + APPLICATION_VERSION;
111     } catch(IOException e) {
112     throw new UncheckedIOException(e);
113     }
114     }
115     });
116 hirukawa_ryo 31
117 hirukawa_ryo 57 primaryStage.showingProperty().addListener((observable, oldValue, newValue) -> {
118     if(oldValue == true && newValue == false) {
119     Platform.exit();
120     }
121     });
122    
123 hirukawa_ryo 44 Parent root = Fxml.load(this);
124    
125 hirukawa_ryo 31 Scene scene = new Scene(root);
126 hirukawa_ryo 66 scene.setOnDragOver(event -> Unchecked.execute(() -> {
127     scene_onDragOver(event);
128     }));
129     scene.setOnDragDropped(event -> Unchecked.execute(() -> {
130     scene_onDragDropped(event);
131     }));
132 hirukawa_ryo 31 scene.getAccelerators().putAll(pager.createDefaultAccelerators());
133    
134     StageUtil.setRestorable(primaryStage, Preferences.userNodeForPackage(getClass()));
135 hirukawa_ryo 66 primaryStage.setOnShown(event -> SceneUtil.invokeAfterLayout(root, Unchecked.runnable(() -> {
136     stage_onReady();
137     })));
138 hirukawa_ryo 31 primaryStage.setMinWidth(448.0);
139     primaryStage.setMinHeight(396.0);
140     primaryStage.setOpacity(0.0);
141     primaryStage.setScene(scene);
142     primaryStage.show();
143    
144 hirukawa_ryo 68 //
145     // ������������������������������������
146     //
147     Thread.setDefaultUncaughtExceptionHandler((thread, exception) -> Unchecked.execute(() -> {
148     onCaughtException(thread, exception);
149     }));
150 hirukawa_ryo 31 }
151    
152 hirukawa_ryo 68 /** ���������������������������������������������������������������������������������������������
153     *
154     * @param thread ������������������������������������
155     * @param exception ������������������������
156     */
157     protected void onCaughtException(Thread thread, Throwable exception) {
158 hirukawa_ryo 31 exception.printStackTrace();
159    
160 hirukawa_ryo 68 Platform.runLater(() -> {
161     try {
162     String title;
163     if(exception instanceof JpkiException) {
164     title = "���������";
165     } else {
166     title = exception.getClass().getName();
167     }
168     String message = exception.getLocalizedMessage();
169     if(message != null) {
170     message = message.trim();
171     }
172     toast.show(Toast.COLOR_ERROR, title, message);
173     } catch(Throwable t) {
174     t.printStackTrace();
175     System.exit(0);
176 hirukawa_ryo 31 }
177 hirukawa_ryo 68 });
178 hirukawa_ryo 31 }
179    
180     @FXML Toast toast;
181     @FXML MenuItem menuFileOpen;
182     @FXML MenuItem menuFileSave;
183     @FXML MenuItem menuFileExit;
184     @FXML MenuItem menuHelpAbout;
185     @FXML Pager pager;
186     @FXML PdfView pdfView;
187     @FXML ImageView ivCursor;
188 hirukawa_ryo 47 @FXML ProgressIndicator piSign;
189 hirukawa_ryo 31 @FXML Button btnRemoveSignature;
190     @FXML Button btnEditSignature;
191     @FXML Button btnAddSignature;
192     @FXML ListView<Signature> lvSignature;
193     ObjectBinding<Signature> signatureBinding;
194 hirukawa_ryo 39 ObjectProperty<File> inputFileProperty = new SimpleObjectProperty<File>();
195 hirukawa_ryo 31 ObjectProperty<File> signedTemporaryFileProperty = new SimpleObjectProperty<File>();
196 hirukawa_ryo 47 BooleanProperty busyProperty = new SimpleBooleanProperty();
197 hirukawa_ryo 31
198     @Override
199     public void initialize(URL location, ResourceBundle resources) {
200     lvSignature.setCellFactory(new SignatureListCell.Factory(this));
201    
202     //
203     // event handlers
204     //
205 hirukawa_ryo 66 menuFileOpen.setOnAction(event -> Unchecked.execute(() -> {
206     menuFileOpen_onAction(event);
207     }));
208     menuFileSave.setOnAction(event -> Unchecked.execute(() -> {
209     menuFileSave_onAction(event);
210     }));
211     menuFileExit.setOnAction(event -> Unchecked.execute(() -> {
212     menuFileExit_onAction(event);
213     }));
214     menuHelpAbout.setOnAction(event -> Unchecked.execute(() -> {
215     menuHelpAbout_onAction(event);
216     }));
217     pdfView.setOnMouseMoved(event -> Unchecked.execute(() -> {
218     pdfView_onMouseMoved(event);
219     }));
220     pdfView.setOnMouseClicked(event -> Unchecked.execute(() -> {
221     pdfView_onMouseClicked(event);
222     }));
223     btnRemoveSignature.setOnAction(event -> Unchecked.execute(() -> {
224     btnRemoveSignature_onAction(event);
225     }));
226     btnEditSignature.setOnAction(event -> Unchecked.execute(() -> {
227     btnEditSignature_onAction(event);
228     }));
229     btnAddSignature.setOnAction(event -> Unchecked.execute(() -> {
230     btnAddSignature_onAction(event);
231     }));
232 hirukawa_ryo 31
233     //
234     // bindings
235     //
236     signatureBinding = Bindings
237     .when(lvSignature.getSelectionModel().selectedItemProperty().isNotNull())
238     .then(lvSignature.getSelectionModel().selectedItemProperty())
239     .otherwise(Signature.EMPTY);
240    
241     menuFileSave.disableProperty().bind(signedTemporaryFileProperty.isNull());
242    
243     pager.maxPageIndexProperty().bind(pdfView.maxPageIndexProperty());
244     pager.pageIndexProperty().bindBidirectional(pdfView.pageIndexProperty());
245    
246     pdfView.cursorProperty().bind(Bindings
247     .when(pdfView.documentProperty().isNotNull()
248     .and(ivCursor.visibleProperty())
249     .and(ivCursor.imageProperty().isNotNull()))
250     .then(Cursor.NONE)
251     .otherwise(Cursor.DEFAULT));
252    
253     ivCursor.imageProperty().bind(Bindings.select(signatureBinding, "image"));
254     ivCursor.scaleXProperty().bind(
255     pdfView.renderScaleProperty().multiply(Bindings.selectDouble(signatureBinding, "imageScaleX")));
256     ivCursor.scaleYProperty().bind(
257     pdfView.renderScaleProperty().multiply(Bindings.selectDouble(signatureBinding, "imageScaleY")));
258     ivCursor.visibleProperty().bind(Bindings
259     .selectBoolean(signatureBinding, "visible")
260     .and(pdfView.hoverProperty()));
261    
262     btnRemoveSignature.disableProperty().bind(
263     Bindings.not(Bindings.selectBoolean(signatureBinding, "visible")));
264     btnEditSignature.disableProperty().bind(
265     Bindings.not(Bindings.selectBoolean(signatureBinding, "visible")));
266    
267 hirukawa_ryo 47 piSign.visibleProperty().bind(busyProperty);
268    
269 hirukawa_ryo 31 toast.maxWidthProperty().bind(getPrimaryStage().widthProperty().subtract(32));
270     toast.maxHeightProperty().bind(getPrimaryStage().heightProperty().subtract(32));
271     }
272    
273     void stage_onReady() {
274     getPrimaryStage().setOpacity(1.0);
275    
276     lvSignature.getItems().clear();
277     lvSignature.getItems().add(Signature.INVISIBLE);
278 hirukawa_ryo 66 MainApp.serialExecutor.execute(AsyncTask.create(() -> {
279 hirukawa_ryo 31 return Datastore.loadSignatures();
280     }).onSucceeded(signatures -> {
281     for (Signature signature : signatures) {
282     lvSignature.getItems().add(signature);
283     }
284 hirukawa_ryo 66 checkJpkiAvailability();
285     }));
286 hirukawa_ryo 31 }
287    
288     void scene_onDragOver(DragEvent event) {
289     if(isAcceptable(getFile(event))) {
290     event.acceptTransferModes(TransferMode.COPY);
291     } else {
292     event.consume();
293     }
294     }
295    
296     void scene_onDragDropped(DragEvent event) {
297     File file = getFile(event);
298     if(isAcceptable(file)) {
299     getPrimaryStage().toFront();
300     toast.hide();
301     signedTemporaryFileProperty.set(null);
302 hirukawa_ryo 39 inputFileProperty.set(file);
303 hirukawa_ryo 31 pdfView.load(file);
304     event.setDropCompleted(true);
305     }
306     event.consume();
307     }
308    
309     void menuFileOpen_onAction(ActionEvent event) {
310     toast.hide();
311     Preferences preferences = Preferences.userNodeForPackage(getClass());
312    
313     FileChooser fc = new FileChooser();
314     fc.setTitle("������");
315     fc.getExtensionFilters().add(new FileChooser.ExtensionFilter("PDF", "*.pdf"));
316    
317     String lastOpenDirectory = preferences.get("lastOpenDirectory", null);
318     if(lastOpenDirectory != null) {
319     File dir = new File(lastOpenDirectory);
320     if(dir.isDirectory()) {
321     fc.setInitialDirectory(dir);
322     }
323     }
324     File file = fc.showOpenDialog(getPrimaryStage());
325     if(file != null) {
326     preferences.put("lastOpenDirectory", file.getParentFile().getAbsolutePath());
327     if(isAcceptable(file)) {
328     signedTemporaryFileProperty.set(null);
329 hirukawa_ryo 39 inputFileProperty.set(file);
330 hirukawa_ryo 31 pdfView.load(file);
331     }
332     }
333     }
334    
335     void menuFileSave_onAction(ActionEvent event) throws IOException {
336     toast.hide();
337 hirukawa_ryo 39 String defaultName = inputFileProperty.get().getName();
338 hirukawa_ryo 31 int i = defaultName.lastIndexOf('.');
339     if(i > 0) {
340     defaultName = defaultName.substring(0, i);
341     }
342     defaultName += "-signed.pdf";
343    
344     FileChooser fc = new FileChooser();
345     fc.setTitle("������������������������");
346     fc.getExtensionFilters().add(new FileChooser.ExtensionFilter("PDF", "*.pdf"));
347 hirukawa_ryo 39 fc.setInitialDirectory(inputFileProperty.get().getParentFile());
348 hirukawa_ryo 31 fc.setInitialFileName(defaultName);
349    
350     File file = fc.showSaveDialog(getPrimaryStage());
351     if(file != null) {
352     Files.copy(signedTemporaryFileProperty.get().toPath(), file.toPath(), StandardCopyOption.REPLACE_EXISTING);
353 hirukawa_ryo 66 toast.show(Toast.COLOR_SUCCESS, "������������������", file.getPath());
354 hirukawa_ryo 31 }
355     }
356    
357     void menuFileExit_onAction(ActionEvent event) {
358 hirukawa_ryo 57 getPrimaryStage().close();
359 hirukawa_ryo 31 }
360    
361     void menuHelpAbout_onAction(ActionEvent event) throws IOException {
362     String license = Datastore.getLicense();
363 hirukawa_ryo 40 LicenseDialog dialog = new LicenseDialog(getPrimaryStage(), APPLICATION_NAME + " " + APPLICATION_VERSION, license);
364 hirukawa_ryo 31 dialog.showAndWait();
365     }
366    
367     void btnAddSignature_onAction(ActionEvent event) throws IOException {
368     toast.hide();
369     SignatureDialog dialog = new SignatureDialog(getPrimaryStage(), null);
370     Signature newSignature = dialog.showAndWait().orElse(null);
371     if(newSignature == null) {
372     return;
373     }
374     lvSignature.getItems().add(newSignature);
375     Datastore.saveSignatures(lvSignature.getItems().subList(0, lvSignature.getItems().size()));
376     }
377    
378     void btnEditSignature_onAction(ActionEvent event) throws IOException {
379     toast.hide();
380     Signature currentSignature = lvSignature.getSelectionModel().getSelectedItem();
381     if(currentSignature == null || currentSignature.getImage() == null) {
382     return;
383     }
384     SignatureDialog dialog = new SignatureDialog(getPrimaryStage(), currentSignature);
385     Signature newSignature = dialog.showAndWait().orElse(null);
386     if(newSignature == null) {
387     return;
388     }
389     lvSignature.getItems().add(lvSignature.getSelectionModel().getSelectedIndex(), newSignature);
390     lvSignature.getItems().remove(lvSignature.getSelectionModel().getSelectedIndex());
391     Datastore.saveSignatures(lvSignature.getItems().subList(0, lvSignature.getItems().size()));
392     }
393    
394     void btnRemoveSignature_onAction(ActionEvent event) throws IOException {
395     toast.hide();
396     Signature currentSignature = lvSignature.getSelectionModel().getSelectedItem();
397     if(currentSignature == null || currentSignature.getImage() == null) {
398     return;
399     }
400     ButtonType result = Dialogs.showConfirmation(getPrimaryStage(),
401     "���������������",
402     currentSignature.getTitle() + " ������������������������");
403     if(result != ButtonType.YES) {
404     return;
405     }
406    
407     lvSignature.getItems().remove(lvSignature.getSelectionModel().getSelectedIndex());
408     lvSignature.getSelectionModel().clearSelection();
409     Datastore.saveSignatures(lvSignature.getItems().subList(0, lvSignature.getItems().size()));
410     }
411    
412     public void lvSignature_cell_onMousePressed(MouseEvent event) throws JpkiException, IOException, ReflectiveOperationException {
413     toast.hide();
414     @SuppressWarnings("unchecked")
415     ListCell<Signature> cell = (ListCell<Signature>)event.getSource();
416    
417     //������������������������������������������������������������������������������������������
418     if(cell.isEmpty()) {
419     lvSignature.getSelectionModel().clearSelection();
420     return;
421     }
422    
423     Signature signature = cell.getItem();
424     if(signature != Signature.INVISIBLE) {
425     return;
426     }
427    
428     try {
429 hirukawa_ryo 41 if(!event.isPrimaryButtonDown()) {
430     return;
431     } else if(pdfView.getDocument() == null) {
432 hirukawa_ryo 66 toast.show(Toast.COLOR_SUCCESS,
433 hirukawa_ryo 41 "������������",
434     "PDF���������������������������������������������������&������������������������������������������");
435     } else if(checkJpkiAvailability()) {
436     ButtonType result = Dialogs.showConfirmation(getPrimaryStage(),
437     APPLICATION_NAME + " " + APPLICATION_VERSION,
438 hirukawa_ryo 31 "������������������������������������������������");
439     if(result == ButtonType.YES) {
440     PDDocument document = pdfView.getDocument();
441     int pageIndex = pdfView.getPageIndex();
442     SignatureOptions options = null;
443    
444 hirukawa_ryo 47 busyProperty.set(true);
445 hirukawa_ryo 66 MainApp.serialExecutor.execute(AsyncTask.create(() -> {
446     return sign(document, null, APPLICATION_NAME, APPLICATION_VERSION);
447     }).onSucceeded(tmpFile -> {
448     if(tmpFile != null) {
449     signedTemporaryFileProperty.set(tmpFile);
450     pdfView.load(tmpFile, pageIndex);
451     busyProperty.set(false);
452 hirukawa_ryo 47
453 hirukawa_ryo 66 if(ButtonType.YES == Dialogs.showConfirmation(getPrimaryStage(),
454     APPLICATION_NAME + " " + APPLICATION_VERSION,
455     "������������������������������\n������������������������������������������������������")) {
456     menuFileSave.fire();
457 hirukawa_ryo 47 }
458 hirukawa_ryo 66 }
459     }).onFinished(state -> {
460     busyProperty.set(false);
461     }));
462 hirukawa_ryo 31 }
463     }
464     } finally {
465     lvSignature.getSelectionModel().clearSelection();
466     }
467     }
468    
469     public void lvSignature_cell_onMouseClicked(MouseEvent event) {
470     // ������������������������������������������������������������
471     if(event.getButton() != MouseButton.PRIMARY || event.getClickCount() != 2) {
472     return;
473     }
474    
475     @SuppressWarnings("unchecked")
476     ListCell<Signature> cell = (ListCell<Signature>)event.getSource();
477    
478     // ���������������������������������������
479     Signature signature = cell.getItem();
480     if(signature == Signature.INVISIBLE) {
481     return;
482     }
483    
484     if(cell.isEmpty()) {
485     // ���������������������������������������������������������������������������������������������
486     btnAddSignature.fire();
487     } else {
488     // ���������������������������������������������������������������������������������������������
489     btnEditSignature.fire();
490     }
491     }
492    
493     void pdfView_onMouseMoved(MouseEvent event) {
494     Image image = ivCursor.getImage();
495     if(image != null) {
496     ivCursor.setLayoutX(event.getX() - (int)(image.getWidth() / 2.0));
497     ivCursor.setLayoutY(event.getY() - (int)(image.getHeight() / 2.0));
498     }
499     }
500    
501     void pdfView_onMouseClicked(MouseEvent event) throws JpkiException, IOException, ReflectiveOperationException {
502     toast.hide();
503    
504     // ������������������������������������������������������������������������������
505    
506     if(event.getButton() != MouseButton.PRIMARY) {
507     return;
508     }
509    
510     Rectangle2D renderBounds = pdfView.getRenderBounds();
511     double x = event.getX() - renderBounds.getMinX();
512     double y = event.getY() - renderBounds.getMinY();
513     if(x < 0.0 || y < 0.0 || x > renderBounds.getWidth() || y > renderBounds.getHeight()) {
514     return;
515     }
516    
517     Signature signature = signatureBinding.get();
518     if(!signature.isVisible()) {
519     return;
520     }
521    
522     if(!checkJpkiAvailability()) {
523     return;
524     }
525    
526     PDDocument document = pdfView.getDocument();
527     int pageIndex = pdfView.getPageIndex();
528 hirukawa_ryo 62 int rotation = document.getPage(pageIndex).getRotation();
529 hirukawa_ryo 31 PDRectangle pageMediaBox = document.getPage(pageIndex).getMediaBox();
530    
531     PDVisibleSignDesigner designer;
532     try(InputStream is = new FileInputStream(signature.getFile())) {
533 hirukawa_ryo 62 if(rotation == 0) {
534     designer = new PDVisibleSignDesigner(is);
535     designer.width((float)mm2px(signature.getWidthMillis()));
536     designer.height((float)mm2px(signature.getHeightMillis()));
537     double xPt = x * pageMediaBox.getWidth() / renderBounds.getWidth();
538     double yPt = y * pageMediaBox.getHeight() / renderBounds.getHeight();
539     designer.xAxis((float)xPt - designer.getWidth() / 2);
540     designer.yAxis((float)yPt - designer.getHeight() / 2 - pageMediaBox.getHeight());
541     } else {
542     ByteArrayOutputStream buf = new ByteArrayOutputStream();
543     BufferedImage image = ImageIO.read(is);
544     int w1 = image.getWidth();
545     int h1 = image.getHeight();
546     int w2 = (rotation % 180 == 0) ? w1 : h1;
547     int h2 = (rotation % 180 == 0) ? h1 : w1;
548     BufferedImage rotated = new BufferedImage(w2, h2, image.getType());
549     Graphics2D g2d = rotated.createGraphics();
550     g2d.translate((w2 - w1) / 2, (h2 - h1) / 2);
551     g2d.rotate(Math.toRadians(rotation * -1), w1 / 2, h1 / 2);
552     g2d.drawImage(image, null, 0, 0);
553     g2d.dispose();
554     ImageIO.write(rotated, "PNG", buf);
555    
556     try(InputStream is2 = new ByteArrayInputStream(buf.toByteArray())) {
557     designer = new PDVisibleSignDesigner(is2);
558     }
559     double xPt;
560     double yPt;
561     switch(rotation) {
562     case 90:
563     designer.width((float)mm2px(signature.getHeightMillis()));
564     designer.height((float)mm2px(signature.getWidthMillis()));
565     xPt = x * pageMediaBox.getHeight() / renderBounds.getWidth();
566     yPt = y * pageMediaBox.getWidth() / renderBounds.getHeight();
567     designer.xAxis((float)yPt - designer.getWidth() / 2);
568     designer.yAxis(- (float)xPt - designer.getHeight() / 2);
569     break;
570     case 180:
571     designer.width((float)mm2px(signature.getWidthMillis()));
572     designer.height((float)mm2px(signature.getHeightMillis()));
573     xPt = x * pageMediaBox.getWidth() / renderBounds.getWidth();
574     yPt = y * pageMediaBox.getHeight() / renderBounds.getHeight();
575     designer.xAxis(- (float)xPt - designer.getWidth() / 2 + pageMediaBox.getWidth());
576     designer.yAxis(- (float)yPt - designer.getHeight() / 2);
577     break;
578     case 270:
579     designer.width((float)mm2px(signature.getHeightMillis()));
580     designer.height((float)mm2px(signature.getWidthMillis()));
581     xPt = x * pageMediaBox.getHeight() / renderBounds.getWidth();
582     yPt = y * pageMediaBox.getWidth() / renderBounds.getHeight();
583     designer.xAxis(- (float)yPt - designer.getWidth() / 2 + pageMediaBox.getWidth());
584     designer.yAxis((float)xPt - designer.getHeight() / 2 - pageMediaBox.getHeight());
585     break;
586     }
587     }
588 hirukawa_ryo 31 }
589 hirukawa_ryo 62
590 hirukawa_ryo 31 PDVisibleSigProperties props = new PDVisibleSigProperties();
591     props.setPdVisibleSignature(designer);
592     props.visualSignEnabled(true);
593     props.page(pageIndex + 1);
594     props.buildSignature();
595    
596     SignatureOptions options = new SignatureOptions();
597     options.setPage(pageIndex);
598     options.setVisualSignature(props);
599    
600 hirukawa_ryo 47 lvSignature.getSelectionModel().clearSelection();
601     busyProperty.set(true);
602 hirukawa_ryo 66 MainApp.serialExecutor.execute(AsyncTask.create(() -> {
603     return sign(document, options, APPLICATION_NAME, APPLICATION_VERSION);
604     }).onSucceeded(tmpFile -> {
605     if(tmpFile != null) {
606     signedTemporaryFileProperty.set(tmpFile);
607     pdfView.load(tmpFile, pageIndex);
608     busyProperty.set(false);
609 hirukawa_ryo 31
610 hirukawa_ryo 66 if(ButtonType.YES == Dialogs.showConfirmation(getPrimaryStage(), APPLICATION_NAME + " " + APPLICATION_VERSION,
611     "������������������������������\n������������������������������������������������������")) {
612     menuFileSave.fire();
613 hirukawa_ryo 47 }
614 hirukawa_ryo 66 lvSignature.getSelectionModel().clearSelection();
615     }
616     }).onFinished(state -> {
617     busyProperty.set(false);
618     }));
619 hirukawa_ryo 31 }
620    
621     protected File getFile(DragEvent event) {
622     if(event.getDragboard().hasFiles()) {
623     List<File> files = event.getDragboard().getFiles();
624     if(files.size() == 1) {
625     return files.get(0);
626     }
627     }
628     return null;
629     }
630    
631     protected boolean isAcceptable(File file) {
632     return file != null && file.getName().matches("(?i).+(\\.pdf)");
633     }
634    
635     protected boolean checkJpkiAvailability() {
636     boolean isAvailable = JpkiWrapper.isAvailable();
637     if(!isAvailable) {
638 hirukawa_ryo 66 toast.show(
639     Toast.COLOR_SUCCESS,
640     "������������",
641     "JPKI ������������������������������������������������������������������������������\n" +
642     "���������������������������������������������������������������������������������������������",
643     Unchecked.runnable(() -> {
644     toast.hide();
645     Desktop.getDesktop().browse(URI.create("https://www.jpki.go.jp/download/win.html"));
646     }));
647 hirukawa_ryo 31 }
648     return isAvailable;
649     }
650    
651     protected File sign(PDDocument document, SignatureOptions options, String applicationName, String applicationVersion) throws JpkiException, IOException, ReflectiveOperationException {
652     File tmpFile = Datastore.getMyDataDirectory(true).resolve("output.tmp").toFile();
653     try (OutputStream output = new FileOutputStream(tmpFile)) {
654     output.flush();
655     JpkiWrapper jpki = new JpkiWrapper();
656     jpki.setApplicationName(applicationName);
657     jpki.setApplicationVersion(applicationVersion);
658     jpki.addSignature(output, document, options);
659     return tmpFile;
660     } catch(JpkiException e) {
661     //���������������������������������������������������������������������������������������������
662     if(e.getWinErrorCode() != JpkiException.SCARD_W_CANCELLED_BY_USER) {
663     throw e;
664     }
665     }
666     return null;
667     }
668    
669     public static double mm2px(double mm) {
670     return mm * 72.0 / 25.4;
671     }
672     }

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26