├── .gitignore
├── LICENSE
├── README.md
├── out
├── file.pdf
├── file2.pdf
└── nested
│ ├── file.pdf
│ └── nested2
│ └── file.pdf
├── pom.xml
└── src
├── main
├── java
│ ├── hse
│ │ └── btf
│ │ │ └── pdfeditor
│ │ │ ├── FormulaPaneController.java
│ │ │ ├── FormulaWindowController.java
│ │ │ ├── HelloSceneController.java
│ │ │ ├── ImagePaneController.java
│ │ │ ├── MouseController.java
│ │ │ ├── PdfEditorApplication.java
│ │ │ ├── PdfWorkWindowController.java
│ │ │ ├── TablePaneController.java
│ │ │ ├── TextPaneController.java
│ │ │ ├── entity
│ │ │ ├── PDFDocument.java
│ │ │ ├── PDFFormula.java
│ │ │ ├── PDFImage.java
│ │ │ ├── PDFItem.java
│ │ │ ├── PDFTable.java
│ │ │ └── PDFText.java
│ │ │ ├── models
│ │ │ ├── entities
│ │ │ │ ├── FormulaEntity.java
│ │ │ │ ├── FormulaEntityInterface.java
│ │ │ │ ├── ImageEntity.java
│ │ │ │ ├── ImageEntityInterface.java
│ │ │ │ ├── PaperEntity.java
│ │ │ │ ├── TextEntity.java
│ │ │ │ └── TextEntityInterface.java
│ │ │ └── utility
│ │ │ │ ├── PaperContextMenu.java
│ │ │ │ └── ProjectNameBox.java
│ │ │ ├── service
│ │ │ └── Converter.java
│ │ │ ├── storages
│ │ │ ├── EntitiesStorage.java
│ │ │ └── ProjectDataStorage.java
│ │ │ └── utils
│ │ │ ├── CreatorConstants.java
│ │ │ ├── FileUtil.java
│ │ │ ├── FontUtil.java
│ │ │ └── PDFEditorConstants.java
│ └── module-info.java
├── kotlin
│ └── hse
│ │ └── btf
│ │ └── pdfeditor
│ │ ├── EntityToItemConverter.kt
│ │ ├── Holder.kt
│ │ ├── datasaving
│ │ └── test.json
│ │ ├── models
│ │ ├── FormulaItem.kt
│ │ ├── ImageItem.kt
│ │ ├── Item.kt
│ │ ├── TableItem.kt
│ │ └── TextItem.kt
│ │ └── serializers
│ │ ├── SavingClass.kt
│ │ └── Serializers.kt
└── resources
│ ├── hello-scene.properties
│ ├── hse
│ └── btf
│ │ └── pdfeditor
│ │ ├── arial.ttf
│ │ ├── formula-pane.fxml
│ │ ├── formula-window.fxml
│ │ ├── free_sans.ttf
│ │ ├── hello-view.fxml
│ │ ├── image-pane.fxml
│ │ ├── main.css
│ │ ├── table-pane.fxml
│ │ ├── text-pane.fxml
│ │ ├── times_new_roman.ttf
│ │ └── work-window.fxml
│ └── users.projects
│ └── projectNamesList.json
└── test
├── java
└── hse
│ └── btf
│ └── pdfeditor
│ ├── ExportTest.java
│ └── PDFDocumentTest.java
└── resources
└── images
└── java_logo.svg
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .idea
3 | target
4 | /out/
5 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 Alexander Buyantuev
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # pdf-editor
2 |
--------------------------------------------------------------------------------
/out/file.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pdf-Creator/pdf-editor/ae30ad8db46ab7c922219e100ef6f5c7ebf551b8/out/file.pdf
--------------------------------------------------------------------------------
/out/file2.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pdf-Creator/pdf-editor/ae30ad8db46ab7c922219e100ef6f5c7ebf551b8/out/file2.pdf
--------------------------------------------------------------------------------
/out/nested/file.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pdf-Creator/pdf-editor/ae30ad8db46ab7c922219e100ef6f5c7ebf551b8/out/nested/file.pdf
--------------------------------------------------------------------------------
/out/nested/nested2/file.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pdf-Creator/pdf-editor/ae30ad8db46ab7c922219e100ef6f5c7ebf551b8/out/nested/nested2/file.pdf
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | hse.btf
8 | pdf-editor
9 | 1.0-SNAPSHOT
10 | pdf-editor
11 |
12 |
13 |
14 | nexus-gluonhq-com-repo
15 | gluon repo
16 | https://nexus.gluonhq.com/nexus/content/repositories/releases/
17 |
18 |
19 | itext
20 | iText Repository - releases
21 | https://repo.itextsupport.com/releases
22 |
23 |
24 |
25 |
26 | UTF-8
27 | 5.8.1
28 | 1.5.32
29 | 1.3.0-RC
30 |
31 |
32 |
33 |
34 | org.openjfx
35 | javafx-base
36 | 17.0.1
37 |
38 |
39 | org.openjfx
40 | javafx-controls
41 | 17.0.1
42 |
43 |
44 | org.openjfx
45 | javafx-fxml
46 | 17.0.1
47 |
48 |
49 | org.openjfx
50 | javafx-web
51 | 17.0.1
52 |
53 |
54 | org.openjfx
55 | javafx-swing
56 | 17.0.1
57 |
58 |
59 | org.jfree
60 | fxgraphics2d
61 | 1.8
62 |
63 |
64 | org.controlsfx
65 | controlsfx
66 | 11.1.0
67 |
68 |
69 | com.dlsc.formsfx
70 | formsfx-core
71 | 11.3.2
72 |
73 |
74 | org.openjfx
75 | *
76 |
77 |
78 |
79 |
80 | net.synedra
81 | validatorfx
82 | 0.1.13
83 |
84 |
85 | org.openjfx
86 | *
87 |
88 |
89 |
90 |
91 | org.kordamp.ikonli
92 | ikonli-javafx
93 | 12.2.0
94 |
95 |
96 | org.kordamp.bootstrapfx
97 | bootstrapfx-core
98 | 0.4.0
99 |
100 |
101 | org.scilab.forge
102 | jlatexmath
103 | 1.0.7
104 |
105 |
106 |
107 | com.proudapes
108 | jlatexmathfx
109 | 0.3.2
110 |
111 |
112 | com.itextpdf
113 | kernel
114 | 7.2.1
115 |
116 |
117 | com.itextpdf
118 | io
119 | 7.2.1
120 |
121 |
122 | com.itextpdf
123 | layout
124 | 7.2.1
125 |
126 |
127 | com.itextpdf
128 | forms
129 | 7.2.1
130 |
131 |
132 | com.itextpdf
133 | pdfa
134 | 7.2.1
135 |
136 |
137 | com.itextpdf
138 | sign
139 | 7.2.1
140 |
141 |
142 | com.itextpdf
143 | barcodes
144 | 7.2.1
145 |
146 |
147 | com.itextpdf
148 | font-asian
149 | 7.2.1
150 |
151 |
152 | com.itextpdf
153 | hyph
154 | 7.2.1
155 |
156 |
157 | org.slf4j
158 | slf4j-api
159 | 2.0.0-alpha7
160 |
161 |
162 | org.slf4j
163 | slf4j-simple
164 | 2.0.0-alpha7
165 |
166 |
167 | eu.hansolo
168 | tilesfx
169 | 11.48
170 |
171 |
172 | org.openjfx
173 | *
174 |
175 |
176 |
177 |
178 | org.junit.jupiter
179 | junit-jupiter-api
180 | ${junit.version}
181 | test
182 |
183 |
184 | com.gluonhq
185 | charm-glisten
186 | 6.0.2
187 |
188 |
189 | org.junit.jupiter
190 | junit-jupiter-engine
191 | ${junit.version}
192 | test
193 |
194 |
195 | org.jetbrains.kotlin
196 | kotlin-stdlib
197 | ${kotlin.version}
198 |
199 |
200 | no.tornado
201 | tornadofx
202 | 1.7.20
203 |
204 |
205 | org.jetbrains.kotlin
206 | kotlin-reflect
207 | ${kotlin.version}
208 |
209 |
210 | org.jetbrains.kotlinx
211 | kotlinx-serialization-json-jvm
212 | ${serialization.version}
213 |
214 |
215 | commons-io
216 | commons-io
217 | 2.11.0
218 |
219 |
220 |
221 |
222 |
223 |
224 | src/main/java
225 | ${project.build.outputDirectory}
226 |
227 | **/*.ttf
228 |
229 |
230 |
231 |
232 | src/main/resources
233 |
234 |
235 |
236 |
237 | org.jetbrains.kotlin
238 | kotlin-maven-plugin
239 | ${kotlin.version}
240 |
241 |
242 | compile
243 |
244 | compile
245 |
246 |
247 | 1.8
248 |
249 | ${project.basedir}/src/main/kotlin
250 | ${project.basedir}/src/main/java
251 |
252 |
253 |
254 |
255 | test-compile
256 | test-compile
257 |
258 |
259 | ${project.basedir}/src/test/kotlin
260 | ${project.basedir}/src/test/java
261 |
262 |
263 |
264 |
265 |
266 |
267 | kotlinx-serialization
268 |
269 |
270 |
271 |
272 | org.jetbrains.kotlin
273 | kotlin-maven-serialization
274 | ${kotlin.version}
275 |
276 |
277 |
278 |
279 | org.apache.maven.plugins
280 | maven-compiler-plugin
281 | 3.5.1
282 |
283 |
284 |
285 | default-compile
286 | none
287 |
288 |
289 |
290 | default-testCompile
291 | none
292 |
293 |
294 | java-compile
295 | compile
296 |
297 | compile
298 |
299 |
300 |
301 | java-test-compile
302 | test-compile
303 |
304 | testCompile
305 |
306 |
307 |
308 |
309 | 11
310 | 11
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 | org.openjfx
324 | javafx-maven-plugin
325 | 0.0.8
326 |
327 |
328 |
329 | default-cli
330 |
331 | hse.btf.pdfeditor/hse.btf.pdfeditor.PdfEditorApplication
332 | app
333 | app
334 | app
335 | true
336 | true
337 | true
338 |
339 |
340 |
341 |
342 |
343 |
344 |
--------------------------------------------------------------------------------
/src/main/java/hse/btf/pdfeditor/FormulaPaneController.java:
--------------------------------------------------------------------------------
1 | package hse.btf.pdfeditor;
2 |
3 | import javafx.fxml.FXML;
4 | import javafx.fxml.FXMLLoader;
5 | import javafx.fxml.Initializable;
6 | import javafx.scene.Parent;
7 | import javafx.scene.Scene;
8 | import javafx.scene.control.Button;
9 | import javafx.stage.Stage;
10 |
11 | import java.io.IOException;
12 | import java.net.URL;
13 | import java.util.ResourceBundle;
14 |
15 | public class FormulaPaneController implements Initializable {
16 |
17 | @Override
18 | public void initialize(URL url, ResourceBundle resourceBundle) {
19 | setFormulaActions();
20 | }
21 |
22 | synchronized private void setFormulaActions() {
23 | newFormulaButton.setOnMouseClicked(ev -> {
24 | Stage stage = new Stage();
25 | FXMLLoader fxmlLoader = new FXMLLoader(PdfEditorApplication.class.getResource("formula-window.fxml"));
26 |
27 | Parent root = null;
28 | try {
29 | root = fxmlLoader.load();
30 | } catch (IOException e) {
31 | e.printStackTrace();
32 | return;
33 | }
34 | Scene scene = new Scene(root);
35 | stage.setScene(scene);
36 | stage.show();
37 | });
38 | }
39 |
40 | @FXML
41 | public Button newFormulaButton;
42 | }
43 |
--------------------------------------------------------------------------------
/src/main/java/hse/btf/pdfeditor/FormulaWindowController.java:
--------------------------------------------------------------------------------
1 | package hse.btf.pdfeditor;
2 |
3 | import hse.btf.pdfeditor.models.entities.FormulaEntity;
4 | import javafx.fxml.Initializable;
5 | import javafx.scene.control.Button;
6 | import javafx.scene.control.TextArea;
7 | import javafx.stage.Stage;
8 |
9 | import java.net.URL;
10 | import java.util.ResourceBundle;
11 |
12 | import static hse.btf.pdfeditor.PdfWorkWindowController.papers;
13 | import static hse.btf.pdfeditor.storages.EntitiesStorage.entitiesList;
14 |
15 | public class FormulaWindowController implements Initializable {
16 | public TextArea formulaText;
17 | public Button createFormula;
18 | public Button closeFormula;
19 |
20 | @Override
21 | public void initialize(URL url, ResourceBundle resourceBundle) {
22 | createFormula.setOnAction(ev -> {
23 | FormulaEntity entity = new FormulaEntity(formulaText.getText());
24 | entitiesList.add(entity);
25 | entity.setBottomPadding(0);
26 | entity.setTopPadding(0);
27 | entity.setLeftPadding(0);
28 | entity.setRightPadding(0);
29 | papers.get(0).getChildren().add(entity.createFxmlObject());
30 | papers.get(0).getStylesheets().add(PdfEditorApplication.class.getResource("main.css").toExternalForm());
31 | Stage stage = (Stage)formulaText.getScene().getWindow();
32 | stage.close();
33 | });
34 |
35 | closeFormula.setOnAction(ev -> {
36 | Stage stage = (Stage)formulaText.getScene().getWindow();
37 | stage.close();
38 | });
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/main/java/hse/btf/pdfeditor/HelloSceneController.java:
--------------------------------------------------------------------------------
1 | package hse.btf.pdfeditor;
2 |
3 | import hse.btf.pdfeditor.models.utility.ProjectNameBox;
4 | import javafx.event.ActionEvent;
5 | import javafx.fxml.FXML;
6 | import javafx.fxml.FXMLLoader;
7 | import javafx.fxml.Initializable;
8 | import javafx.scene.Parent;
9 | import javafx.scene.Scene;
10 | import javafx.scene.control.Button;
11 | import javafx.scene.control.ListView;
12 | import javafx.scene.control.TextField;
13 | import javafx.stage.Stage;
14 | import javafx.stage.StageStyle;
15 |
16 | import java.io.IOException;
17 | import java.net.URL;
18 | import java.util.ArrayList;
19 | import java.util.List;
20 | import java.util.ResourceBundle;
21 |
22 | import static hse.btf.pdfeditor.serializers.SavingClassKt.deserializeProjectsNames;
23 | import static hse.btf.pdfeditor.serializers.SavingClassKt.readFromFile;
24 | import static hse.btf.pdfeditor.serializers.SavingClassKt.serializeProjectsNames;
25 |
26 | public class HelloSceneController implements Initializable {
27 | @FXML
28 | private TextField projectNameField;
29 |
30 | @FXML
31 | private Button createButton;
32 |
33 | @FXML
34 | private Button openButton;
35 |
36 | @FXML
37 | private ListView projectNamesListView;
38 |
39 | private final List projectNamesList = new ArrayList<>();
40 | private String currentProjectName = "";
41 | private final ResourceBundle resourceBundle = ResourceBundle.getBundle("hello-scene");
42 |
43 | public static boolean usedByOpenButton = false;
44 |
45 | @Override
46 | public void initialize(URL url, ResourceBundle resourceBundle) {
47 | deserializeProjectsNames(projectNamesList);
48 |
49 | projectNamesListView.getItems().addAll(projectNamesList);
50 | projectNamesListView.getSelectionModel().selectedItemProperty().addListener((observableValue, s, t1) -> {
51 | currentProjectName = projectNamesListView.getSelectionModel().getSelectedItem();
52 | projectNameField.setText(currentProjectName);
53 | });
54 | }
55 |
56 | @FXML
57 | public void createProjectButton(ActionEvent event) throws IOException {
58 | // check whether the project with that name is already created
59 | if (projectNamesList.contains(projectNameField.getText())) {
60 | ProjectNameBox.display(resourceBundle.getString("label.project-name.non-new"), resourceBundle.getString("message.project-name.non-new"));
61 | return;
62 | }
63 |
64 | if (projectNameField.getText().isEmpty()) {
65 | ProjectNameBox.display(resourceBundle.getString("label.project-name.empty"), resourceBundle.getString("message.project-name.empty"));
66 | return;
67 | }
68 |
69 | // add new project name to the name list
70 | projectNamesList.add(projectNameField.getText());
71 | serializeProjectsNames(projectNamesList);
72 |
73 | changeScene();
74 | }
75 |
76 | @FXML
77 | public void openProjectButton(ActionEvent event) throws IOException {
78 | // check whether project with that name doesn't exist
79 | if (!projectNamesList.contains(projectNameField.getText())) {
80 | ProjectNameBox.display(resourceBundle.getString("label.project-name.non-existing"), resourceBundle.getString("message.project-name.non-existing"));
81 | return;
82 | }
83 |
84 | // выгрузить состояние всей прошлой сцены
85 | System.out.println(projectNameField.getText());
86 | usedByOpenButton = readFromFile(projectNameField.getText());
87 |
88 | changeScene();
89 | }
90 |
91 | private void changeScene() throws IOException {
92 | // closing previous
93 | Stage thisStage = (Stage) createButton.getScene().getWindow();
94 | thisStage.close();
95 |
96 | FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("work-window.fxml"));
97 |
98 | Stage stage = new Stage();
99 | Parent root = fxmlLoader.load();
100 | Scene scene = new Scene(root);
101 |
102 | stage.setMaximized(false);
103 | stage.initStyle(StageStyle.DECORATED);
104 |
105 | stage.setTitle("Working Window");
106 | stage.setScene(scene);
107 | stage.show();
108 | }
109 | }
--------------------------------------------------------------------------------
/src/main/java/hse/btf/pdfeditor/ImagePaneController.java:
--------------------------------------------------------------------------------
1 | package hse.btf.pdfeditor;
2 |
3 | import hse.btf.pdfeditor.utils.FileUtil;
4 | import javafx.fxml.FXML;
5 | import javafx.fxml.Initializable;
6 | import javafx.scene.control.Button;
7 |
8 | import java.net.URL;
9 | import java.util.ResourceBundle;
10 |
11 | public class ImagePaneController implements Initializable {
12 | @Override
13 | public void initialize(URL url, ResourceBundle resourceBundle) {
14 | setImageActions();
15 | }
16 |
17 | private void setImageActions() {
18 | // добавить рамки + посмотреть в видео, что можно делать с картинкой
19 | FileUtil.loadImage(newImageButton);
20 | }
21 |
22 | @FXML
23 | public Button newImageButton;
24 | }
25 |
--------------------------------------------------------------------------------
/src/main/java/hse/btf/pdfeditor/MouseController.java:
--------------------------------------------------------------------------------
1 | package hse.btf.pdfeditor;
2 |
3 | public class MouseController {
4 | public static class Position {
5 | static public double x;
6 | static public double y;
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/src/main/java/hse/btf/pdfeditor/PdfEditorApplication.java:
--------------------------------------------------------------------------------
1 | package hse.btf.pdfeditor;
2 |
3 | import hse.btf.pdfeditor.utils.FontUtil;
4 | import javafx.application.Application;
5 | import javafx.fxml.FXMLLoader;
6 | import javafx.scene.Parent;
7 | import javafx.scene.Scene;
8 | import javafx.stage.Stage;
9 |
10 | import java.io.IOException;
11 |
12 | public class PdfEditorApplication extends Application {
13 | @Override
14 | public void start(Stage stage) throws IOException {
15 | FXMLLoader fxmlLoader = new FXMLLoader(PdfEditorApplication.class.getResource("hello-view.fxml"));
16 | FontUtil.init();
17 |
18 | Parent root = fxmlLoader.load();
19 | Scene scene = new Scene(root);
20 |
21 | stage.setTitle("Hello!");
22 | stage.setScene(scene);
23 | stage.show();
24 | }
25 |
26 | public static void main(String[] args) {
27 | launch();
28 | }
29 | }
--------------------------------------------------------------------------------
/src/main/java/hse/btf/pdfeditor/PdfWorkWindowController.java:
--------------------------------------------------------------------------------
1 | package hse.btf.pdfeditor;
2 |
3 | import hse.btf.pdfeditor.models.utility.PaperContextMenu;
4 | import hse.btf.pdfeditor.models.entities.PaperEntity;
5 | import hse.btf.pdfeditor.utils.FileUtil;
6 | import javafx.fxml.FXML;
7 | import javafx.fxml.Initializable;
8 | import javafx.scene.control.Button;
9 | import javafx.scene.control.Label;
10 | import javafx.scene.input.MouseButton;
11 | import javafx.scene.input.MouseEvent;
12 | import javafx.scene.layout.AnchorPane;
13 |
14 | import java.net.URL;
15 | import java.util.ArrayList;
16 | import java.util.List;
17 | import java.util.ResourceBundle;
18 |
19 | import static hse.btf.pdfeditor.HelloSceneController.usedByOpenButton;
20 |
21 | public class PdfWorkWindowController implements Initializable {
22 |
23 | @Override
24 | public void initialize(URL url, ResourceBundle resourceBundle) {
25 | papers = new ArrayList<>();
26 | papers.add(paper);
27 |
28 | setPaperSettings();
29 | setLeftPanelsActions();
30 |
31 | // TODO
32 | if (usedByOpenButton) {
33 | // создать entities из списка item'ов
34 | // отрисовать объекты на бумаге
35 | }
36 |
37 | FileUtil.savePDFDocument(createPdfButton);
38 | }
39 |
40 | private void setLeftPanelsActions() {
41 | leftPanel.setPrefWidth(20);
42 |
43 | textPane.setPrefWidth(0);
44 | tablePane.setPrefWidth(0);
45 | imagePane.setPrefWidth(0);
46 | formulaPane.setPrefWidth(0);
47 |
48 | addLeftButtonClicker(leftTextPaneButton, textPane);
49 | addLeftButtonClicker(leftTablePaneButton, tablePane);
50 | addLeftButtonClicker(leftImagePaneButton, imagePane);
51 | addLeftButtonClicker(leftFormulaPaneButton, formulaPane);
52 | }
53 |
54 | private void setPaperSettings() {
55 | paperSize = 100;
56 | originalPaperWidth = paper.getPrefWidth();
57 | originalPaperHeight = paper.getPrefHeight();
58 |
59 | PaperContextMenu contextMenu = new PaperContextMenu();
60 | paper.setOnMouseClicked(ev -> {
61 | if (ev.getButton() == MouseButton.SECONDARY) {
62 | contextMenu.show(paper, ev.getScreenX(), ev.getScreenY());
63 | } else {
64 | contextMenu.hide();
65 | }
66 | });
67 | }
68 |
69 | /*
70 | TODO : ultimate way to add handlers
71 | private void initFormulaPane() {
72 | formulaPane.getChildren().forEach(node -> {
73 | node.setOnMouseClicked();
74 | });
75 | }
76 | */
77 |
78 | private void addLeftButtonClicker(Button button, AnchorPane panel) {
79 | button.setOnMouseClicked(ev -> {
80 | if (selectedPane == null) {
81 | selectedPane = panel;
82 | leftPanel.setPrefWidth(164);
83 | selectedPane.setPrefWidth(144);
84 | } else {
85 | selectedPane.setPrefWidth(0);
86 |
87 | if (selectedPane == panel) {
88 | selectedPane = null;
89 | leftPanel.setPrefWidth(20);
90 | } else {
91 | selectedPane = panel;
92 | selectedPane.setPrefWidth(144);
93 | }
94 | }
95 | });
96 | }
97 |
98 | @FXML
99 | public void paperSizeDecrease(MouseEvent event) {
100 | if (paperSize != 25) {
101 | paperSize -= 25;
102 | sizeLabel.setText(paperSize + "%");
103 | resizePaper();
104 | }
105 | }
106 |
107 | @FXML
108 | public void paperSizeIncrease(MouseEvent event) {
109 | if (paperSize != 100) {
110 | paperSize += 25;
111 | sizeLabel.setText(paperSize + "%");
112 | resizePaper();
113 | }
114 | }
115 |
116 | private void resizePaper() {
117 | paper.setPrefWidth(originalPaperWidth / 100 * paperSize);
118 | paper.setPrefHeight(originalPaperHeight / 100 * paperSize);
119 | }
120 |
121 | static public PaperEntity target = null;
122 | /**
123 | * left panel
124 | **/
125 | @FXML
126 | public AnchorPane leftPanel;
127 |
128 | /**
129 | * choosing pane buttons
130 | **/
131 | @FXML
132 | public Button leftTextPaneButton;
133 |
134 | @FXML
135 | public Button leftTablePaneButton;
136 |
137 | @FXML
138 | public Button leftImagePaneButton;
139 |
140 | @FXML
141 | public Button leftFormulaPaneButton;
142 |
143 | /**
144 | * panes
145 | **/
146 | @FXML
147 | private AnchorPane selectedPane = null;
148 |
149 | public static List papers;
150 |
151 | @FXML
152 | public AnchorPane textPane;
153 |
154 | @FXML
155 | public AnchorPane tablePane;
156 |
157 | @FXML
158 | public AnchorPane imagePane;
159 |
160 | @FXML
161 | public AnchorPane formulaPane;
162 |
163 | /**
164 | * paper
165 | **/
166 | @FXML
167 | private AnchorPane paperBackground;
168 |
169 | @FXML
170 | private AnchorPane paper;
171 |
172 | @FXML
173 | private Button buttonPaperSizeIncrease;
174 |
175 | @FXML
176 | private Button buttonPaperSizeDecrease;
177 |
178 | @FXML
179 | private Label sizeLabel;
180 |
181 | @FXML
182 | private Button createPdfButton;
183 |
184 | private final EntityToItemConverter pdfEditorView = new EntityToItemConverter();
185 |
186 | private double originalPaperWidth;
187 |
188 | private double originalPaperHeight;
189 |
190 | private Integer paperSize;
191 | }
--------------------------------------------------------------------------------
/src/main/java/hse/btf/pdfeditor/TablePaneController.java:
--------------------------------------------------------------------------------
1 | package hse.btf.pdfeditor;
2 |
3 | import javafx.fxml.FXML;
4 | import javafx.fxml.Initializable;
5 | import javafx.scene.control.Button;
6 | import javafx.scene.control.Slider;
7 | import javafx.scene.control.TextField;
8 |
9 | import java.net.URL;
10 | import java.util.ResourceBundle;
11 |
12 | public class TablePaneController implements Initializable {
13 | @Override
14 | public void initialize(URL url, ResourceBundle resourceBundle) {
15 | setTableActions();
16 | }
17 |
18 | private void setTableActions() {
19 | newTableButton.setOnMouseClicked(ev -> {
20 | }
21 | //entitiesHolder.getObservableItemsList().add(new TableItem())
22 | );
23 |
24 | // columns
25 | connectSliderWithTextField(tableColsSlider, tableColsField);
26 |
27 | tableColsSlider.setMin(1.0);
28 | tableColsSlider.setMax(20.0);
29 | tableColsField.setText("2.0");
30 |
31 | // rows
32 | connectSliderWithTextField(tableRowsSlider, tableRowsField);
33 |
34 | tableRowsSlider.setMin(1.0);
35 | tableRowsSlider.setMax(20.0);
36 | tableRowsField.setText("2.0");
37 | }
38 |
39 | private void connectSliderWithTextField(Slider slider, TextField field) {
40 | slider.valueProperty().addListener((changed, oldValue, newValue) -> field.setText(newValue.toString()));
41 | field.textProperty().addListener((changed, oldValue, newValue) -> slider.setValue(Double.parseDouble(newValue)));
42 | }
43 |
44 | @FXML
45 | public Button newTableButton;
46 |
47 | @FXML
48 | public TextField tableColsField;
49 | public Slider tableColsSlider;
50 | public TextField tableRowsField;
51 | public Slider tableRowsSlider;
52 | }
53 |
--------------------------------------------------------------------------------
/src/main/java/hse/btf/pdfeditor/TextPaneController.java:
--------------------------------------------------------------------------------
1 | package hse.btf.pdfeditor;
2 |
3 | import hse.btf.pdfeditor.models.entities.TextEntity;
4 | import hse.btf.pdfeditor.utils.CreatorConstants;
5 | import hse.btf.pdfeditor.utils.FontUtil;
6 | import javafx.collections.FXCollections;
7 | import javafx.collections.ObservableList;
8 | import javafx.fxml.FXML;
9 | import javafx.fxml.Initializable;
10 | import javafx.scene.control.Button;
11 | import javafx.scene.control.ChoiceBox;
12 | import javafx.scene.control.ColorPicker;
13 | import javafx.scene.control.Slider;
14 | import javafx.scene.control.TextField;
15 | import javafx.scene.control.ToggleButton;
16 | import javafx.scene.control.ToggleGroup;
17 | import javafx.scene.control.Tooltip;
18 | import javafx.scene.input.MouseEvent;
19 | import javafx.scene.layout.AnchorPane;
20 | import javafx.scene.paint.Color;
21 |
22 | import java.net.URL;
23 | import java.util.List;
24 | import java.util.Objects;
25 | import java.util.ResourceBundle;
26 |
27 | import static hse.btf.pdfeditor.PdfWorkWindowController.papers;
28 | import static hse.btf.pdfeditor.PdfWorkWindowController.target;
29 | import static hse.btf.pdfeditor.storages.EntitiesStorage.entitiesList;
30 |
31 | public class TextPaneController implements Initializable {
32 |
33 | @Override
34 | public void initialize(URL url, ResourceBundle resourceBundle) {
35 | textParameters.setVisible(false);
36 | newTextButton.setOnMouseClicked(ev -> {
37 | textParameters.setVisible(true);
38 | TextEntity entity = new TextEntity();
39 | entitiesList.add(entity);
40 | entity.setBottomPadding(8.0);
41 | entity.setTopPadding(8.0);
42 | entity.setLeftPadding(8.0);
43 | entity.setRightPadding(8.0);
44 | entity.setWidth(150);
45 | entity.setHeight(90);
46 | papers.get(0).getChildren().add(entity.createFxmlObject());
47 | papers.get(0).getStylesheets().add(Objects.requireNonNull(PdfEditorApplication.class.getResource("main.css")).toExternalForm());
48 | });
49 |
50 | textShriftChoiceBox.getItems().addAll(List.of("Free Sans", "Arial", "Times New Roman"));
51 | textShriftChoiceBox.setValue("Free Sans");
52 | textShriftChoiceBox.setOnAction(ev -> {
53 | TextEntity entity = (TextEntity)target;
54 | String fontName = textShriftChoiceBox.getValue();
55 | entity.setFont(fontName);
56 | });
57 | }
58 |
59 | @FXML
60 | public AnchorPane textParameters;
61 |
62 | @FXML
63 | public Button newTextButton;
64 |
65 | @FXML
66 | public ChoiceBox textShriftChoiceBox;
67 |
68 | @FXML
69 | public TextField textSizeField;
70 | public Slider textSizeSlider;
71 |
72 | @FXML
73 | public ToggleButton alignmentLeftButton;
74 | public ToggleButton alignmentCenterButton;
75 | public ToggleButton alignmentRightButton;
76 | public ToggleButton alignmentWidthButton;
77 |
78 | private final ToggleGroup alignmentToggleGroup = new ToggleGroup();
79 |
80 | @FXML
81 | public ToggleButton textPropertyBoldButton;
82 | public ToggleButton textPropertyCursiveButton;
83 | public ToggleButton textPropertyUnderlineButton;
84 | public ToggleButton textPropertyCrossOutButton;
85 |
86 | @FXML
87 | public ColorPicker textColorPicker;
88 | public ColorPicker textFillColorPicker;
89 |
90 | @FXML
91 | public ColorPicker textFieldColorPicker;
92 | }
--------------------------------------------------------------------------------
/src/main/java/hse/btf/pdfeditor/entity/PDFDocument.java:
--------------------------------------------------------------------------------
1 | package hse.btf.pdfeditor.entity;
2 |
3 | import com.itextpdf.io.image.ImageData;
4 | import com.itextpdf.io.image.ImageDataFactory;
5 | import com.itextpdf.kernel.geom.PageSize;
6 | import com.itextpdf.kernel.geom.Rectangle;
7 | import com.itextpdf.kernel.pdf.PdfDocument;
8 | import com.itextpdf.kernel.pdf.PdfPage;
9 | import com.itextpdf.kernel.pdf.PdfWriter;
10 | import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
11 | import com.itextpdf.layout.Canvas;
12 | import com.itextpdf.layout.Document;
13 | import com.itextpdf.layout.element.Image;
14 | import com.itextpdf.layout.element.Paragraph;
15 | import com.itextpdf.layout.element.Table;
16 | import com.itextpdf.layout.element.Text;
17 | import com.itextpdf.layout.properties.TransparentColor;
18 | import hse.btf.pdfeditor.service.Converter;
19 | import hse.btf.pdfeditor.utils.PDFEditorConstants;
20 | import org.scilab.forge.jlatexmath.TeXConstants;
21 | import org.scilab.forge.jlatexmath.TeXFormula;
22 | import org.scilab.forge.jlatexmath.TeXIcon;
23 |
24 | import javax.imageio.ImageIO;
25 | import javax.swing.*;
26 | import javax.swing.text.StyleConstants;
27 | import java.awt.*;
28 | import java.awt.image.BufferedImage;
29 | import java.io.ByteArrayOutputStream;
30 | import java.io.IOException;
31 | import java.net.MalformedURLException;
32 | import java.nio.file.Files;
33 | import java.nio.file.Path;
34 | import java.nio.file.Paths;
35 | import java.util.List;
36 |
37 | public class PDFDocument {
38 | private final PdfWriter pdfWriter;
39 | private final PdfDocument pdfDocument;
40 | List pages;
41 | private PdfPage currentPage;
42 | private final PageSize pageSize;
43 |
44 | public PDFDocument() throws IOException {
45 | this(PDFEditorConstants.DEFAULT_PDF_FILE, PDFEditorConstants.DEFAULT_PAGE_SIZE);
46 | }
47 |
48 | public PDFDocument(String fileName) throws IOException {
49 | this(fileName, PDFEditorConstants.DEFAULT_PAGE_SIZE);
50 | }
51 |
52 | public PDFDocument(String fileName, PageSize pageSize) throws IOException {
53 | Path path = Paths.get(fileName);
54 | if (!Files.exists(path)) {
55 | Files.createDirectories(path.getParent());
56 | Files.createFile(path);
57 | }
58 | pdfWriter = new PdfWriter(fileName);
59 | pdfDocument = new PdfDocument(pdfWriter);
60 | this.pageSize = pageSize;
61 | addPage();
62 | }
63 |
64 | public PageSize getPageSize() {
65 | return pageSize;
66 | }
67 |
68 | public void addRectangleWithTextItem(PDFText textItem) {
69 | // creating canvas on current page
70 | PdfCanvas canvas = new PdfCanvas(currentPage);
71 | // creating rectangle on canvas
72 | Rectangle rect = new Rectangle(
73 | (float) textItem.getX(),
74 | (float) textItem.getY(),
75 | (float) textItem.getW(),
76 | (float) textItem.getH()
77 | );
78 | // drawing rectangle
79 | // stroke
80 | TransparentColor borderColor = textItem.getBorderColor();
81 | canvas.saveState().setStrokeColor(borderColor.getColor());
82 | borderColor.applyStrokeTransparency(canvas);
83 | canvas.rectangle(rect);
84 | canvas.stroke().restoreState();
85 | // fill
86 | TransparentColor backgroundColor = textItem.getBackgroundColor();
87 | canvas.saveState().setFillColor(backgroundColor.getColor());
88 | backgroundColor.applyFillTransparency(canvas);
89 | canvas.rectangle(rect);
90 | canvas.fill().restoreState();
91 |
92 | // adding text to rectangle
93 | Text text = new Text(textItem.getText())
94 | .setFontColor(textItem.getTextColor())
95 | .setFont(textItem.getTextFont());
96 | Paragraph paragraph = new Paragraph(text);
97 | new Canvas(canvas, rect).add(paragraph);
98 | }
99 |
100 | public void addRectangleWithImageItem(PDFImage imageItem) throws MalformedURLException {
101 | PdfCanvas canvas = new PdfCanvas(currentPage);
102 | Rectangle rect = new Rectangle(
103 | (float) imageItem.getX(),
104 | (float) imageItem.getY(),
105 | (float) imageItem.getW(),
106 | (float) imageItem.getH()
107 | );
108 |
109 | // drawing rectangle
110 | // stroke
111 | TransparentColor borderColor = imageItem.getBorderColor();
112 | canvas.saveState().setStrokeColor(borderColor.getColor());
113 | borderColor.applyStrokeTransparency(canvas);
114 | canvas.rectangle(rect);
115 | canvas.stroke().restoreState();
116 | // fill
117 | TransparentColor backgroundColor = imageItem.getBackgroundColor();
118 | canvas.saveState().setFillColor(backgroundColor.getColor());
119 | backgroundColor.applyFillTransparency(canvas);
120 | canvas.rectangle(rect);
121 | canvas.fill().restoreState();
122 |
123 | ImageData data = ImageDataFactory.create(imageItem.getImagePath());
124 | Image image = new Image(data);
125 | image.setFixedPosition((float) imageItem.getX(), (float) imageItem.getY());
126 | image.scaleAbsolute((float) imageItem.getW(), (float) imageItem.getH());
127 |
128 | new Canvas(canvas, rect).add(image);
129 | }
130 |
131 | public void addRectangleWithFormulaItem(PDFFormula formulaItem) throws IOException {
132 | PdfCanvas canvas = new PdfCanvas(currentPage);
133 | Rectangle rect = new Rectangle(
134 | (float) formulaItem.getX(),
135 | (float) formulaItem.getY(),
136 | (float) formulaItem.getW(),
137 | (float) formulaItem.getH()
138 | );
139 |
140 | // drawing rectangle
141 | // stroke
142 | TransparentColor borderColor = formulaItem.getBorderColor();
143 | canvas.saveState().setStrokeColor(borderColor.getColor());
144 | borderColor.applyStrokeTransparency(canvas);
145 | canvas.rectangle(rect);
146 | canvas.stroke().restoreState();
147 | // fill
148 | TransparentColor backgroundColor = formulaItem.getBackgroundColor();
149 | canvas.saveState().setFillColor(backgroundColor.getColor());
150 | backgroundColor.applyFillTransparency(canvas);
151 | canvas.rectangle(rect);
152 | canvas.fill().restoreState();
153 |
154 | // сreating formula image
155 | TeXFormula formula = new TeXFormula(formulaItem.getFormula());
156 | java.awt.Image formulaImage = formula.createBufferedImage(TeXConstants.STYLE_TEXT, PDFEditorConstants.DEFAULT_LATEX_DPI, formulaItem.getFormulaColor(), null);
157 | BufferedImage bufferedImage = (BufferedImage) formulaImage;
158 |
159 | // -- adding it to pdf --
160 | ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
161 | ImageIO.write(bufferedImage, "png", byteArrayOutputStream);
162 |
163 | ImageData data = ImageDataFactory.create(byteArrayOutputStream.toByteArray());
164 | Image image = new Image(data);
165 | image.setFixedPosition((float) formulaItem.getX(), (float) formulaItem.getY());
166 | image.setWidth((float) formulaItem.getW());
167 | image.setHeight((float) formulaItem.getH());
168 |
169 | new Canvas(canvas, rect).add(image);
170 | }
171 |
172 | public void addRectangleWithTableItem(PDFTable tableItem) {
173 | PdfCanvas canvas = new PdfCanvas(currentPage);
174 | Rectangle rect = new Rectangle(
175 | (float) tableItem.getX(),
176 | (float) tableItem.getY(),
177 | (float) tableItem.getW(),
178 | (float) tableItem.getH()
179 | );
180 | // canvas.setStrokeColor(tableItem.getRectangleStrokeColor().getColor())
181 | // .setFillColor(tableItem.getRectangleFillColor().getColor())
182 | // .rectangle(rect)
183 | // .fill()
184 | // .stroke();
185 |
186 | Table table = new Table(tableItem.getCols());
187 | table.setFontColor(tableItem.getFontColor());
188 |
189 | for (String cellContent : tableItem.getCellContents()) {
190 | table.addCell(cellContent);
191 | }
192 |
193 | new Canvas(canvas, rect).add(table);
194 | }
195 |
196 | public void setCurrentPage(int index) {
197 | currentPage = pdfDocument.getPage(index);
198 | }
199 |
200 | public void addPage() {
201 | currentPage = pdfDocument.addNewPage();
202 | }
203 |
204 | public void exportDocument() {
205 | Document document = new Document(pdfDocument, pageSize);
206 | document.close();
207 | }
208 | }
209 |
--------------------------------------------------------------------------------
/src/main/java/hse/btf/pdfeditor/entity/PDFFormula.java:
--------------------------------------------------------------------------------
1 | package hse.btf.pdfeditor.entity;
2 |
3 | import java.awt.Color;
4 | import com.itextpdf.kernel.colors.ColorConstants;
5 |
6 | public class PDFFormula extends PDFItem {
7 | public static final Color defaultColor = Color.BLACK;
8 | private String formula;
9 | private int fontSize;
10 | private Color formulaColor;
11 |
12 | public PDFFormula(float x, float y, float w, float h) {
13 | super(x, y, w, h);
14 | setFormulaColor(defaultColor);
15 | }
16 |
17 | public void setFormula(String formula) {
18 | this.formula = formula;
19 | }
20 |
21 | public String getFormula() {
22 | return formula;
23 | }
24 |
25 | public void setFontSize(int fontSize) {
26 | this.fontSize = fontSize;
27 | }
28 |
29 | public int getFontSize() {
30 | return fontSize;
31 | }
32 |
33 | public Color getFormulaColor() {
34 | return formulaColor;
35 | }
36 |
37 | public void setFormulaColor(Color formulaColor) {
38 | this.formulaColor = formulaColor;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/main/java/hse/btf/pdfeditor/entity/PDFImage.java:
--------------------------------------------------------------------------------
1 | package hse.btf.pdfeditor.entity;
2 |
3 | public class PDFImage extends PDFItem {
4 | private String imagePath;
5 |
6 | public PDFImage(float x, float y, float w, float h) {
7 | super(x, y, w, h);
8 | }
9 |
10 | public void setImagePath(String imagePath) {
11 | this.imagePath = imagePath;
12 | }
13 |
14 | public String getImagePath() {
15 | return imagePath;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/hse/btf/pdfeditor/entity/PDFItem.java:
--------------------------------------------------------------------------------
1 | package hse.btf.pdfeditor.entity;
2 |
3 | import com.itextpdf.kernel.colors.Color;
4 | import com.itextpdf.kernel.colors.ColorConstants;
5 | import com.itextpdf.layout.properties.TransparentColor;
6 |
7 | public class PDFItem {
8 | private double x;
9 | private double y;
10 | private double w;
11 | private double h;
12 | private TransparentColor borderColor;
13 | private TransparentColor backgroundColor;
14 |
15 | public PDFItem(double x, double y, double w, double h) {
16 | this.x = x;
17 | this.y = y;
18 | this.w = w;
19 | this.h = h;
20 | borderColor = new TransparentColor(ColorConstants.WHITE, 0);
21 | backgroundColor = new TransparentColor(ColorConstants.WHITE, 0);
22 | }
23 |
24 | public void setBorderColor(TransparentColor borderColor) {
25 | this.borderColor = borderColor;
26 | }
27 |
28 | public void setBackgroundColor(TransparentColor backgroundColor) {
29 | this.backgroundColor = backgroundColor;
30 | }
31 |
32 | public void setX(float x) {
33 | this.x = x;
34 | }
35 |
36 | public void setY(float y) {
37 | this.y = y;
38 | }
39 |
40 | public void setW(float w) {
41 | this.w = w;
42 | }
43 |
44 | public void setH(float h) {
45 | this.h = h;
46 | }
47 |
48 | public double getX() {
49 | return x;
50 | }
51 |
52 | public double getY() {
53 | return y;
54 | }
55 |
56 | public double getW() {
57 | return w;
58 | }
59 |
60 | public double getH() {
61 | return h;
62 | }
63 |
64 | public TransparentColor getBorderColor() {
65 | return borderColor;
66 | }
67 |
68 | public TransparentColor getBackgroundColor() {
69 | return backgroundColor;
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/src/main/java/hse/btf/pdfeditor/entity/PDFTable.java:
--------------------------------------------------------------------------------
1 | package hse.btf.pdfeditor.entity;
2 |
3 | import com.itextpdf.kernel.colors.Color;
4 |
5 | import java.util.List;
6 |
7 | public class PDFTable extends PDFItem {
8 | private int cols;
9 | private List extends String> cellContents;
10 | private Color fontColor;
11 |
12 |
13 | public PDFTable(double x, double y, double w, double h) {
14 | super(x, y, w, h);
15 | }
16 |
17 | public void setCols(int cols) {
18 | this.cols = cols;
19 | }
20 |
21 | public int getCols() {
22 | return cols;
23 | }
24 |
25 | public void setCellContents(List extends String> cellContents) {
26 | this.cellContents = cellContents;
27 | }
28 |
29 | public List extends String> getCellContents() {
30 | return cellContents;
31 | }
32 |
33 | public void setFontColor(Color fontColor) {
34 | this.fontColor = fontColor;
35 | }
36 |
37 | public Color getFontColor() {
38 | return fontColor;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/main/java/hse/btf/pdfeditor/entity/PDFText.java:
--------------------------------------------------------------------------------
1 | package hse.btf.pdfeditor.entity;
2 |
3 | import com.itextpdf.io.font.PdfEncodings;
4 | import com.itextpdf.kernel.colors.Color;
5 | import com.itextpdf.kernel.colors.ColorConstants;
6 | import com.itextpdf.kernel.font.PdfFont;
7 | import com.itextpdf.kernel.font.PdfFontFactory;
8 | import hse.btf.pdfeditor.utils.FontUtil;
9 | import hse.btf.pdfeditor.utils.PDFEditorConstants;
10 |
11 | import java.io.IOException;
12 |
13 | public class PDFText extends PDFItem {
14 | // TODO add to PDFEditorConstants
15 | public static final String defaultText = "default text";
16 | public static final Color defaultColor = ColorConstants.BLACK;
17 |
18 | private String text;
19 | private PdfFont textFont;
20 | private double textSize;
21 | private Color textColor;
22 |
23 | public PDFText(double x, double y, double w, double h) {
24 | super(x, y, w, h);
25 | setText(defaultText);
26 | setTextFont(FontUtil.getPdfFontByName(PDFEditorConstants.DEFAULT_FONT));
27 | setTextColor(defaultColor);
28 | setTextSize(PDFEditorConstants.DEFAULT_FONT_SIZE);
29 | }
30 |
31 | public void setText(String text) {
32 | this.text = text;
33 | }
34 |
35 | public void setTextColor(Color textColor) {
36 | this.textColor = textColor;
37 | }
38 |
39 | public void setTextFont(PdfFont font) {
40 | this.textFont = font;
41 | }
42 |
43 | public void setTextSize(double textSize) {
44 | this.textSize = textSize;
45 | }
46 |
47 | public String getText() {
48 | return text;
49 | }
50 |
51 | public Color getTextColor() {
52 | return textColor;
53 | }
54 |
55 | public PdfFont getTextFont() {
56 | return textFont;
57 | }
58 |
59 | public double getTextSize() {
60 | return textSize;
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/main/java/hse/btf/pdfeditor/models/entities/FormulaEntity.java:
--------------------------------------------------------------------------------
1 | package hse.btf.pdfeditor.models.entities;
2 |
3 | import hse.btf.pdfeditor.MouseController;
4 | import hse.btf.pdfeditor.PdfWorkWindowController;
5 | import hse.btf.pdfeditor.utils.PDFEditorConstants;
6 | import javafx.beans.property.SimpleStringProperty;
7 | import javafx.beans.property.StringProperty;
8 | import javafx.embed.swing.SwingFXUtils;
9 | import javafx.scene.Cursor;
10 | import javafx.scene.image.Image;
11 | import javafx.scene.image.ImageView;
12 | import javafx.scene.input.MouseEvent;
13 | import javafx.scene.layout.AnchorPane;
14 | import javafx.scene.layout.Pane;
15 | import javafx.scene.paint.Color;
16 | import javafx.scene.shape.Circle;
17 | import javafx.scene.shape.StrokeType;
18 | import org.scilab.forge.jlatexmath.TeXConstants;
19 | import org.scilab.forge.jlatexmath.TeXFormula;
20 |
21 | import java.awt.image.BufferedImage;
22 |
23 | public class FormulaEntity extends PaperEntity implements FormulaEntityInterface {
24 | private ImageView formulaImage;
25 | private final String formula;
26 | private final StringProperty formulaProperty;
27 |
28 | public FormulaEntity(String formula) {
29 | super();
30 | formulaImage = drawFormula(formula);
31 | double coef = formulaImage.getImage().getWidth() / formulaImage.getImage().getHeight();
32 | this.formula = formula;
33 | this.formulaProperty = new SimpleStringProperty(formula);
34 | formulaImage.setFitHeight(50);
35 | textBox.setPrefHeight(50);
36 | textBox.setPrefWidth(50 * coef);
37 | }
38 |
39 | @Override
40 | public Pane createFxmlObject() {
41 | if (PdfWorkWindowController.target != null) {
42 | PdfWorkWindowController.target.removeCss("text-region");
43 | PdfWorkWindowController.target.hidePoint();
44 | }
45 | this.applyCss("text-region");
46 | PdfWorkWindowController.target = this;
47 |
48 |
49 | formulaImage.setPreserveRatio(true);
50 | resizePoint = new Circle(6, Color.WHITE);
51 | resizePoint.setStrokeWidth(1);
52 | resizePoint.setStrokeType(StrokeType.INSIDE);
53 | resizePoint.setStroke(Color.valueOf("0x808080FF"));
54 |
55 | AnchorPane.setRightAnchor(resizePoint, -6.0);
56 | AnchorPane.setBottomAnchor(resizePoint, -6.0);
57 |
58 | AnchorPane.setTopAnchor(formulaImage, topPadding);
59 | AnchorPane.setLeftAnchor(formulaImage, leftPadding);
60 | AnchorPane.setRightAnchor(formulaImage, rightPadding);
61 | AnchorPane.setBottomAnchor(formulaImage, bottomPadding);
62 |
63 | textBox.getChildren().add(formulaImage);
64 | textBox.getChildren().add(resizePoint);
65 |
66 | textBox.addEventHandler(MouseEvent.MOUSE_ENTERED, event -> textBox.setCursor(Cursor.HAND));
67 | textBox.addEventHandler(MouseEvent.MOUSE_EXITED, event -> textBox.setCursor(Cursor.DEFAULT));
68 |
69 | textBox.addEventHandler(MouseEvent.MOUSE_PRESSED, e -> {
70 | if (PdfWorkWindowController.target != null) {
71 | PdfWorkWindowController.target.removeCss("text-region");
72 | PdfWorkWindowController.target.hidePoint();
73 | }
74 | this.applyCss("text-region");
75 | PdfWorkWindowController.target = this;
76 | this.showPoint();
77 | textBox.setCursor(Cursor.MOVE);
78 | MouseController.Position.x = e.getX();
79 | MouseController.Position.y = e.getY();
80 | });
81 |
82 | textBox.addEventHandler(MouseEvent.MOUSE_RELEASED, event -> textBox.setCursor(Cursor.DEFAULT));
83 |
84 | textBox.setOnMouseDragged(e -> {
85 | double distanceX = e.getX() - MouseController.Position.x;
86 | double distanceY = e.getY() - MouseController.Position.y;
87 |
88 | double x = textBox.getLayoutX() + distanceX;
89 | double y = textBox.getLayoutY() + distanceY;
90 |
91 | textBox.relocate(x, y);
92 | });
93 |
94 | resizePoint.addEventHandler(MouseEvent.MOUSE_ENTERED, event -> {
95 | textBox.setCursor(Cursor.SE_RESIZE);
96 | event.consume();
97 | });
98 |
99 | resizePoint.addEventHandler(MouseEvent.MOUSE_EXITED, event -> {
100 | textBox.setCursor(Cursor.DEFAULT);
101 | event.consume();
102 | });
103 |
104 | resizePoint.addEventHandler(MouseEvent.MOUSE_PRESSED, e -> {
105 | MouseController.Position.x = e.getX();
106 | MouseController.Position.y = e.getY();
107 | e.consume();
108 | });
109 |
110 | resizePoint.addEventHandler(MouseEvent.MOUSE_RELEASED, event -> {
111 | textBox.setCursor(Cursor.DEFAULT);
112 | event.consume();
113 | });
114 |
115 | resizePoint.setOnMouseDragged(e -> {
116 | double distanceX = e.getX() - MouseController.Position.x;
117 | double distanceY = e.getY() - MouseController.Position.y;
118 |
119 | double coef = textBox.getPrefHeight() / textBox.getPrefWidth();
120 | double x = textBox.getPrefWidth() + distanceX;
121 | double y = textBox.getPrefHeight() + distanceX * coef;
122 |
123 | textBox.setPrefWidth(x);
124 | textBox.setPrefHeight(y);
125 | formulaImage.setFitWidth(x - leftPadding - rightPadding);
126 | formulaImage.setFitHeight(y - bottomPadding - topPadding);
127 |
128 | e.consume();
129 | });
130 |
131 | return textBox;
132 | }
133 |
134 | private ImageView drawFormula(String latex) {
135 | TeXFormula formula = new TeXFormula(latex);
136 | java.awt.Image awtImage = formula.createBufferedImage(TeXConstants.STYLE_TEXT, PDFEditorConstants.DEFAULT_LATEX_DPI, java.awt.Color.BLACK, null);
137 | Image fxImage = SwingFXUtils.toFXImage((BufferedImage) awtImage, null);
138 | return new ImageView(fxImage);
139 | }
140 |
141 | @Override
142 | public StringProperty getFormulaProperty() {
143 | return formulaProperty;
144 | }
145 | }
146 |
--------------------------------------------------------------------------------
/src/main/java/hse/btf/pdfeditor/models/entities/FormulaEntityInterface.java:
--------------------------------------------------------------------------------
1 | package hse.btf.pdfeditor.models.entities;
2 |
3 | import javafx.beans.property.StringProperty;
4 |
5 | public interface FormulaEntityInterface {
6 | StringProperty getFormulaProperty();
7 | }
8 |
--------------------------------------------------------------------------------
/src/main/java/hse/btf/pdfeditor/models/entities/ImageEntity.java:
--------------------------------------------------------------------------------
1 | package hse.btf.pdfeditor.models.entities;
2 |
3 | import hse.btf.pdfeditor.MouseController;
4 | import hse.btf.pdfeditor.PdfWorkWindowController;
5 | import javafx.beans.property.DoubleProperty;
6 | import javafx.scene.Cursor;
7 | import javafx.scene.image.ImageView;
8 | import javafx.scene.input.MouseEvent;
9 | import javafx.scene.layout.AnchorPane;
10 | import javafx.scene.layout.Pane;
11 | import javafx.scene.paint.Color;
12 | import javafx.scene.shape.Circle;
13 | import javafx.scene.shape.StrokeType;
14 |
15 |
16 | public class ImageEntity extends PaperEntity implements ImageEntityInterface {
17 | ImageView image;
18 | String fileName;
19 |
20 | public ImageEntity(String url) {
21 | super();
22 | image = new ImageView(url);
23 | textBox.setPrefHeight(image.getImage().getHeight());
24 | textBox.setPrefWidth(image.getImage().getWidth());
25 | fileName = url;
26 | }
27 |
28 | @Override
29 | public Pane createFxmlObject() {
30 | if (PdfWorkWindowController.target != null) {
31 | PdfWorkWindowController.target.removeCss("text-region");
32 | PdfWorkWindowController.target.hidePoint();
33 | }
34 | PdfWorkWindowController.target = this;
35 | this.applyCss("text-region");
36 |
37 | image.setPreserveRatio(true);
38 | resizePoint = new Circle(6, Color.WHITE);
39 | resizePoint.setStrokeWidth(1);
40 | resizePoint.setStrokeType(StrokeType.INSIDE);
41 | resizePoint.setStroke(Color.valueOf("0x808080FF"));
42 |
43 | AnchorPane.setRightAnchor(resizePoint, -6.0);
44 | AnchorPane.setBottomAnchor(resizePoint, -6.0);
45 |
46 | AnchorPane.setTopAnchor(image, topPadding);
47 | AnchorPane.setLeftAnchor(image, leftPadding);
48 | AnchorPane.setRightAnchor(image, rightPadding);
49 | AnchorPane.setBottomAnchor(image, bottomPadding);
50 |
51 | textBox.getChildren().add(image);
52 | textBox.getChildren().add(resizePoint);
53 |
54 | textBox.addEventHandler(MouseEvent.MOUSE_ENTERED, event -> textBox.setCursor(Cursor.HAND));
55 | textBox.addEventHandler(MouseEvent.MOUSE_EXITED, event -> textBox.setCursor(Cursor.DEFAULT));
56 |
57 | textBox.addEventHandler(MouseEvent.MOUSE_PRESSED, e -> {
58 | if (PdfWorkWindowController.target != null) {
59 | PdfWorkWindowController.target.removeCss("text-region");
60 | PdfWorkWindowController.target.hidePoint();
61 | }
62 | this.applyCss("text-region");
63 | PdfWorkWindowController.target = this;
64 | this.showPoint();
65 | textBox.setCursor(Cursor.MOVE);
66 | MouseController.Position.x = e.getX();
67 | MouseController.Position.y = e.getY();
68 | });
69 |
70 | textBox.addEventHandler(MouseEvent.MOUSE_RELEASED, event -> textBox.setCursor(Cursor.DEFAULT));
71 |
72 | textBox.setOnMouseDragged(e -> {
73 | double distanceX = e.getX() - MouseController.Position.x;
74 | double distanceY = e.getY() - MouseController.Position.y;
75 |
76 | double x = textBox.getLayoutX() + distanceX;
77 | double y = textBox.getLayoutY() + distanceY;
78 |
79 | textBox.relocate(x, y);
80 | });
81 |
82 | resizePoint.addEventHandler(MouseEvent.MOUSE_ENTERED, event -> {
83 | textBox.setCursor(Cursor.SE_RESIZE);
84 | event.consume();
85 | });
86 |
87 | resizePoint.addEventHandler(MouseEvent.MOUSE_EXITED, event -> {
88 | textBox.setCursor(Cursor.DEFAULT);
89 | event.consume();
90 | });
91 |
92 | resizePoint.addEventHandler(MouseEvent.MOUSE_PRESSED, e -> {
93 | MouseController.Position.x = e.getX();
94 | MouseController.Position.y = e.getY();
95 | e.consume();
96 | });
97 |
98 | resizePoint.addEventHandler(MouseEvent.MOUSE_RELEASED, event -> {
99 | textBox.setCursor(Cursor.DEFAULT);
100 | event.consume();
101 | });
102 |
103 | resizePoint.setOnMouseDragged(e -> {
104 | double distanceX = e.getX() - MouseController.Position.x;
105 | double distanceY = e.getY() - MouseController.Position.y;
106 |
107 | double coef = textBox.getPrefHeight() / textBox.getPrefWidth();
108 | double x = textBox.getPrefWidth() + distanceX;
109 | double y = textBox.getPrefHeight() + distanceX * coef;
110 |
111 | textBox.setPrefWidth(x);
112 | textBox.setPrefHeight(y);
113 | image.setFitWidth(x - leftPadding - rightPadding);
114 | image.setFitHeight(y - bottomPadding - topPadding);
115 |
116 | e.consume();
117 | });
118 |
119 | return textBox;
120 | }
121 |
122 | @Override
123 | public String getFileName() {
124 | return fileName;
125 | }
126 | }
--------------------------------------------------------------------------------
/src/main/java/hse/btf/pdfeditor/models/entities/ImageEntityInterface.java:
--------------------------------------------------------------------------------
1 | package hse.btf.pdfeditor.models.entities;
2 |
3 | public interface ImageEntityInterface {
4 | String getFileName();
5 | }
6 |
--------------------------------------------------------------------------------
/src/main/java/hse/btf/pdfeditor/models/entities/PaperEntity.java:
--------------------------------------------------------------------------------
1 | package hse.btf.pdfeditor.models.entities;
2 |
3 | import javafx.beans.property.DoubleProperty;
4 | import javafx.scene.layout.AnchorPane;
5 | import javafx.scene.layout.Pane;
6 | import javafx.scene.shape.Circle;
7 |
8 | public abstract class PaperEntity {
9 | protected AnchorPane textBox;
10 | protected Circle resizePoint;
11 | protected double leftPadding;
12 | protected double rightPadding;
13 | protected double topPadding;
14 | protected double bottomPadding;
15 |
16 | protected PaperEntity() {
17 | textBox = new AnchorPane();
18 | }
19 |
20 | public abstract Pane createFxmlObject();
21 |
22 | public DoubleProperty getXProperty() {
23 | return textBox.layoutXProperty();
24 | }
25 |
26 | public DoubleProperty getYProperty() {
27 | return textBox.layoutYProperty();
28 | }
29 |
30 | public DoubleProperty getWidthProperty() {
31 | return textBox.prefWidthProperty();
32 | }
33 |
34 | public DoubleProperty getHeightProperty() {
35 | return textBox.prefHeightProperty();
36 | }
37 |
38 | public double getWidth() {
39 | return textBox.getWidth();
40 | }
41 |
42 | public double getHeight() {
43 | return textBox.getHeight();
44 | }
45 |
46 | public double getLeftPadding() {
47 | return leftPadding;
48 | }
49 |
50 | public double getRightPadding() {
51 | return rightPadding;
52 | }
53 |
54 | public double getTopPadding() {
55 | return topPadding;
56 | }
57 |
58 | public double getBottomPadding() {
59 | return bottomPadding;
60 | }
61 |
62 | public void setX(double x) {
63 | textBox.setLayoutX(x);
64 | }
65 |
66 | public void setY(double y) {
67 | textBox.setLayoutY(y);
68 | }
69 |
70 | public void setWidth(double width) {
71 | textBox.setPrefWidth(width);
72 | }
73 |
74 | public void setHeight(double height) {
75 | textBox.setPrefHeight(height);
76 | }
77 |
78 | public void setLeftPadding(double leftPadding) {
79 | this.leftPadding = leftPadding;
80 | }
81 |
82 | public void setRightPadding(double rightPadding) {
83 | this.rightPadding = rightPadding;
84 | }
85 |
86 | public void setTopPadding(double topPadding) {
87 | this.topPadding = topPadding;
88 | }
89 |
90 | public void setBottomPadding(double bottomPadding) {
91 | this.bottomPadding = bottomPadding;
92 | }
93 |
94 | protected void removeCss(String css) {
95 | textBox.getStyleClass().remove(css);
96 | }
97 |
98 | protected void applyCss(String css) {
99 | textBox.getStyleClass().add(css);
100 | }
101 |
102 | protected void hidePoint() {
103 | resizePoint.setVisible(false);
104 | }
105 |
106 | protected void showPoint() {
107 | resizePoint.setVisible(true);
108 | }
109 | }
110 |
111 |
--------------------------------------------------------------------------------
/src/main/java/hse/btf/pdfeditor/models/entities/TextEntity.java:
--------------------------------------------------------------------------------
1 | package hse.btf.pdfeditor.models.entities;
2 |
3 | import hse.btf.pdfeditor.PdfWorkWindowController;
4 | import hse.btf.pdfeditor.utils.FontUtil;
5 | import javafx.beans.property.IntegerProperty;
6 | import javafx.beans.property.ObjectProperty;
7 | import javafx.beans.property.SimpleIntegerProperty;
8 | import javafx.beans.property.SimpleStringProperty;
9 | import javafx.beans.property.StringProperty;
10 | import javafx.scene.Cursor;
11 | import javafx.scene.control.TextArea;
12 | import javafx.scene.input.MouseEvent;
13 | import javafx.scene.layout.AnchorPane;
14 | import javafx.scene.layout.Background;
15 | import javafx.scene.layout.Border;
16 | import javafx.scene.layout.Pane;
17 | import javafx.scene.paint.Color;
18 | import javafx.scene.shape.Circle;
19 | import javafx.scene.shape.StrokeType;
20 | import javafx.scene.text.Font;
21 |
22 | import static hse.btf.pdfeditor.MouseController.Position;
23 |
24 | public class TextEntity extends PaperEntity implements TextEntityInterface {
25 | private final TextArea text = new TextArea();
26 | private final StringProperty textFontFamily = new SimpleStringProperty("");
27 | private final StringProperty textFontName = new SimpleStringProperty("");
28 | private final IntegerProperty textFontSize = new SimpleIntegerProperty(13);
29 | private final StringProperty textFontStyle = new SimpleStringProperty("");
30 | public TextEntity() {
31 | super();
32 | }
33 |
34 | @Override
35 | public Pane createFxmlObject() {
36 | if (PdfWorkWindowController.target != null) {
37 | PdfWorkWindowController.target.removeCss("text-region");
38 | PdfWorkWindowController.target.hidePoint();
39 | }
40 | this.applyCss("text-region");
41 | PdfWorkWindowController.target = this;
42 |
43 | text.setWrapText(true);
44 |
45 | resizePoint = new Circle(6, Color.WHITE);
46 | resizePoint.setStrokeWidth(1);
47 | resizePoint.setStrokeType(StrokeType.INSIDE);
48 | resizePoint.setStroke(Color.valueOf("0x808080FF"));
49 |
50 | AnchorPane.setRightAnchor(resizePoint, -6.0);
51 | AnchorPane.setBottomAnchor(resizePoint, -6.0);
52 |
53 | AnchorPane.setTopAnchor(text, topPadding);
54 | AnchorPane.setLeftAnchor(text, leftPadding);
55 | AnchorPane.setRightAnchor(text, rightPadding);
56 | AnchorPane.setBottomAnchor(text, bottomPadding);
57 |
58 | textBox.getChildren().add(text);
59 | textBox.getChildren().add(resizePoint);
60 |
61 | textBox.addEventHandler(MouseEvent.MOUSE_ENTERED, event -> textBox.setCursor(Cursor.HAND));
62 | textBox.addEventHandler(MouseEvent.MOUSE_EXITED, event -> textBox.setCursor(Cursor.DEFAULT));
63 |
64 | textBox.addEventHandler(MouseEvent.MOUSE_PRESSED, e -> {
65 | if (PdfWorkWindowController.target != null) {
66 | PdfWorkWindowController.target.removeCss("text-region");
67 | PdfWorkWindowController.target.hidePoint();
68 | }
69 | this.applyCss("text-region");
70 | PdfWorkWindowController.target = this;
71 | this.showPoint();
72 | textBox.setCursor(Cursor.MOVE);
73 | Position.x = e.getX();
74 | Position.y = e.getY();
75 | });
76 |
77 | textBox.addEventHandler(MouseEvent.MOUSE_RELEASED, event -> textBox.setCursor(Cursor.DEFAULT));
78 |
79 | textBox.setOnMouseDragged(e -> {
80 | double distanceX = e.getX() - Position.x;
81 | double distanceY = e.getY() - Position.y;
82 |
83 | double x = textBox.getLayoutX() + distanceX;
84 | double y = textBox.getLayoutY() + distanceY;
85 |
86 | textBox.relocate(x, y);
87 | });
88 |
89 | resizePoint.addEventHandler(MouseEvent.MOUSE_ENTERED, event -> {
90 | textBox.setCursor(Cursor.SE_RESIZE);
91 | event.consume();
92 | });
93 |
94 | resizePoint.addEventHandler(MouseEvent.MOUSE_EXITED, event -> {
95 | textBox.setCursor(Cursor.DEFAULT);
96 | event.consume();
97 | });
98 |
99 | resizePoint.addEventHandler(MouseEvent.MOUSE_PRESSED, e -> {
100 | Position.x = e.getX();
101 | Position.y = e.getY();
102 | e.consume();
103 | });
104 |
105 | resizePoint.addEventHandler(MouseEvent.MOUSE_RELEASED, event -> {
106 | textBox.setCursor(Cursor.DEFAULT);
107 | event.consume();
108 | });
109 |
110 | resizePoint.setOnMouseDragged(e -> {
111 | double distanceX = e.getX() - Position.x;
112 | double distanceY = e.getY() - Position.y;
113 |
114 | double x = textBox.getPrefWidth() + distanceX;
115 | double y = textBox.getPrefHeight() + distanceY;
116 |
117 | textBox.setPrefWidth(x);
118 | textBox.setPrefHeight(y);
119 | e.consume();
120 | });
121 |
122 | return textBox;
123 | }
124 |
125 | @Override
126 | public StringProperty getText() {
127 | return text.textProperty();
128 | }
129 |
130 | @Override
131 | public ObjectProperty getFont() {
132 | return text.fontProperty();
133 | }
134 |
135 | @Override
136 | public StringProperty getFontFamily() {
137 | return textFontFamily;
138 | }
139 |
140 | @Override
141 | public StringProperty getFontName() {
142 | return textFontName;
143 | }
144 |
145 | @Override
146 | public IntegerProperty getFontSize() {
147 | return textFontSize;
148 | }
149 |
150 | @Override
151 | public StringProperty getFontStyle() {
152 | return textFontStyle;
153 | }
154 |
155 | @Override
156 | public ObjectProperty getBackground() {
157 | return text.backgroundProperty();
158 | }
159 |
160 | @Override
161 | public ObjectProperty getBorder() {
162 | return text.borderProperty();
163 | }
164 |
165 | public void setFont(String fontName) {
166 | text.setFont(FontUtil.getFxFontByName(fontName));
167 | }
168 | }
169 |
--------------------------------------------------------------------------------
/src/main/java/hse/btf/pdfeditor/models/entities/TextEntityInterface.java:
--------------------------------------------------------------------------------
1 | package hse.btf.pdfeditor.models.entities;
2 |
3 | import javafx.beans.property.IntegerProperty;
4 | import javafx.beans.property.ObjectProperty;
5 | import javafx.beans.property.StringProperty;
6 | import javafx.scene.layout.Background;
7 | import javafx.scene.layout.Border;
8 | import javafx.scene.text.Font;
9 |
10 | public interface TextEntityInterface {
11 | StringProperty getText();
12 | ObjectProperty getFont();
13 | ObjectProperty getBackground();
14 | ObjectProperty getBorder();
15 | StringProperty getFontFamily();
16 | StringProperty getFontName();
17 | IntegerProperty getFontSize();
18 | StringProperty getFontStyle();
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/hse/btf/pdfeditor/models/utility/PaperContextMenu.java:
--------------------------------------------------------------------------------
1 | package hse.btf.pdfeditor.models.utility;
2 |
3 | import javafx.scene.control.ContextMenu;
4 | import javafx.scene.control.MenuItem;
5 |
6 | public class PaperContextMenu extends ContextMenu {
7 | public PaperContextMenu() {
8 | super();
9 | MenuItem menuItem1 = new MenuItem("menu item 1");
10 | MenuItem menuItem2 = new MenuItem("menu item 2");
11 | MenuItem menuItem3 = new MenuItem("menu item 3");
12 |
13 | this.getItems().add(menuItem1);
14 | this.getItems().add(menuItem2);
15 | this.getItems().add(menuItem3);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/hse/btf/pdfeditor/models/utility/ProjectNameBox.java:
--------------------------------------------------------------------------------
1 | package hse.btf.pdfeditor.models.utility;
2 |
3 | import javafx.geometry.Pos;
4 | import javafx.scene.Scene;
5 | import javafx.scene.control.Button;
6 | import javafx.scene.control.Label;
7 | import javafx.scene.layout.VBox;
8 | import javafx.stage.Modality;
9 | import javafx.stage.Stage;
10 |
11 | public class ProjectNameBox {
12 | public static void display(String title, String message) {
13 | Stage window = new Stage();
14 |
15 | // blocking events for other windows
16 | window.initModality(Modality.APPLICATION_MODAL);
17 | window.setTitle(title);
18 | window.setMinWidth(350);
19 |
20 | // window elements
21 | Label messageLabel = new Label(message);
22 | Button okButton = new Button("Ok");
23 | okButton.setOnAction(event -> window.close());
24 |
25 | // layout
26 | VBox layout = new VBox(10);
27 | layout.getChildren().addAll(messageLabel, okButton);
28 | layout.setAlignment(Pos.CENTER);
29 |
30 | // displaying window and waiting for it to be closed
31 | Scene scene = new Scene(layout);
32 | window.setScene(scene);
33 | window.showAndWait();
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/main/java/hse/btf/pdfeditor/service/Converter.java:
--------------------------------------------------------------------------------
1 | package hse.btf.pdfeditor.service;
2 |
3 | import com.itextpdf.kernel.colors.Color;
4 | import com.itextpdf.kernel.colors.ColorConstants;
5 | import com.itextpdf.kernel.colors.DeviceRgb;
6 | import com.itextpdf.kernel.font.PdfFont;
7 | import com.itextpdf.kernel.geom.PageSize;
8 | import com.itextpdf.kernel.pdf.colorspace.PdfColorSpace;
9 | import com.itextpdf.layout.properties.TransparentColor;
10 | import hse.btf.pdfeditor.entity.*;
11 | import hse.btf.pdfeditor.models.*;
12 | import hse.btf.pdfeditor.utils.FontUtil;
13 | import hse.btf.pdfeditor.entity.PDFDocument;
14 | import hse.btf.pdfeditor.entity.PDFFormula;
15 | import hse.btf.pdfeditor.entity.PDFImage;
16 | import hse.btf.pdfeditor.entity.PDFText;
17 | import hse.btf.pdfeditor.models.FormulaItem;
18 | import hse.btf.pdfeditor.models.ImageItem;
19 | import hse.btf.pdfeditor.models.Item;
20 | import hse.btf.pdfeditor.models.TextItem;
21 | import hse.btf.pdfeditor.utils.PDFEditorConstants;
22 | import javafx.scene.layout.Background;
23 | import javafx.scene.layout.BackgroundFill;
24 | import javafx.scene.layout.Border;
25 | import javafx.scene.layout.BorderStroke;
26 |
27 | import java.awt.*;
28 | import java.awt.image.ColorConvertOp;
29 | import java.io.IOException;
30 | import java.math.BigInteger;
31 | import java.nio.file.Path;
32 | import java.util.ArrayList;
33 | import java.util.List;
34 | import java.util.Optional;
35 |
36 | import static hse.btf.pdfeditor.storages.ProjectDataStorage.itemsHolder;
37 | import static hse.btf.pdfeditor.utils.FontUtil.*;
38 |
39 | public class Converter {
40 | public static void saveDocument(String fileName) throws IOException {
41 | FontUtil.init();
42 | PDFDocument pdfDocument = new PDFDocument(fileName);
43 | PageSize pageSize = pdfDocument.getPageSize();
44 |
45 | System.out.println("size: " + itemsHolder.getObservableItemsList().size());
46 | for (Item item : itemsHolder.getObservableItemsList()) {
47 | if (item instanceof TextItem) {
48 | System.out.println("TextItem");
49 |
50 | TextItem textItem = (TextItem) item;
51 | PDFText pdfText = convertTextItem(textItem, pageSize);
52 | pdfDocument.addRectangleWithTextItem(pdfText);
53 | }
54 | if (item instanceof ImageItem) {
55 | System.out.println("image item");
56 | ImageItem imageItem = (ImageItem) item;
57 | PDFImage pdfImage = convertImageItem(imageItem, pageSize);
58 | pdfDocument.addRectangleWithImageItem(pdfImage);
59 | }
60 | if (item instanceof FormulaItem) {
61 | System.out.println("formula item");
62 | FormulaItem formulaItem = (FormulaItem) item;
63 | PDFFormula pdfFormula = convertFormulaItem(formulaItem, pageSize);
64 | pdfDocument.addRectangleWithFormulaItem(pdfFormula);
65 | }
66 | }
67 | pdfDocument.exportDocument();
68 | }
69 |
70 | // static {
71 | // try {
72 | // FontUtil.registerFont("Free Sans", Path.of(FREE_SANS));
73 | // FontUtil.registerFont("Arial", Path.of(ARIAL));
74 | // FontUtil.registerFont("Times New Roman", Path.of(TIMES_NEW_ROMAN));
75 | // } catch (IOException e) {
76 | // System.err.println("Couldn't load default fonts");
77 | // }
78 | // }
79 |
80 | private static List convertCoordinates(double x, double y, double w, double h, PageSize pageSize) {
81 | System.out.println("-- from ui --");
82 | System.out.println("x = " + x);
83 | System.out.println("y = " + y);
84 | System.out.println("w = " + w);
85 | System.out.println("h = " + h);
86 | System.out.println("-------------");
87 | System.out.println("-- page size --");
88 | System.out.println("width = " + pageSize.getWidth());
89 | System.out.println("height = " + pageSize.getHeight());
90 | System.out.println("---------------");
91 | List coordinates = new ArrayList<>();
92 | // // prefHeight="1188.0" prefWidth="840.0"
93 | double coef = 842.0 / 1188.0;
94 | double conv_x = x * coef;
95 | double conv_y = y * coef;
96 | double conv_w = w * coef;
97 | double conv_h = h * coef;
98 | System.out.println("conv_x = " + conv_x);
99 | System.out.println("conv_y = " + conv_y);
100 | System.out.println("conv_w = " + conv_w);
101 | System.out.println("conv_h = " + conv_h);
102 | coordinates.add(0, (float) conv_x); // x
103 | coordinates.add(1, (float) (pageSize.getHeight() - conv_y - conv_h)); //
104 | coordinates.add(2, (float) conv_w); // w
105 | coordinates.add(3, (float) conv_h); // h
106 | System.out.println("-- pdf --");
107 | System.out.println("x = " + coordinates.get(0));
108 | System.out.println("y = " + coordinates.get(1));
109 | System.out.println("w = " + coordinates.get(2));
110 | System.out.println("h = " + coordinates.get(3));
111 | System.out.println("---------");
112 | return coordinates;
113 | }
114 |
115 | private static TransparentColor getPdfColorfromRGBA(String rgbaString) {
116 | List rgba = new ArrayList<>();
117 | for (int i = 0; i < rgbaString.length(); i += 2) {
118 | rgba.add(Integer.parseInt(rgbaString.substring(i, i + 2), 16));
119 | }
120 | Color color = new DeviceRgb(rgba.get(0), rgba.get(1), rgba.get(2));
121 | return new TransparentColor(color, (float) rgba.get(3) / 255);
122 | }
123 |
124 | private static TransparentColor convertBorderColor(Border border) {
125 | if (border == null) {
126 | return new TransparentColor(ColorConstants.WHITE, 0);
127 | }
128 | Optional stroke = border.getStrokes().stream().findFirst();
129 | if (stroke.isEmpty()) {
130 | return new TransparentColor(ColorConstants.WHITE, 0);
131 | }
132 | System.out.println(stroke.get().getTopStroke());
133 | String rgbaString = stroke.get().getTopStroke().toString().substring(2);
134 | return getPdfColorfromRGBA(rgbaString);
135 | }
136 |
137 | private static TransparentColor convertBackgroundColor(Background background) {
138 | if (background == null) {
139 | return new TransparentColor(ColorConstants.WHITE, 0);
140 | }
141 | Optional fill = background.getFills().stream().findFirst();
142 | if (fill.isEmpty()) {
143 | return new TransparentColor(ColorConstants.WHITE, 0);
144 | }
145 | System.out.println(fill.get().getFill());
146 | String rgbaString = fill.get().getFill().toString().substring(2);
147 | return getPdfColorfromRGBA(rgbaString);
148 | }
149 |
150 | private static PDFText convertTextItem(TextItem textItem, PageSize pageSize) {
151 | List converted = convertCoordinates(textItem.getX().get(), textItem.getY().get(), textItem.getW().get(), textItem.getH().get(), pageSize);
152 | PDFText pdfText = new PDFText(
153 | converted.get(0),
154 | converted.get(1),
155 | converted.get(2),
156 | converted.get(3)
157 | );
158 | pdfText.setText(textItem.getText().get());
159 | // background and border
160 | // TransparentColor backgroundColor = convertBackgroundColor(textItem.getBackground().get());
161 | // TransparentColor borderColor = convertBorderColor(textItem.getBorder().get());
162 | // pdfText.setBackgroundColor(backgroundColor);
163 | // pdfText.setBorderColor(borderColor);
164 |
165 | // TODO add size, font, color
166 | PdfFont font = FontUtil.getPdfFontByName(textItem.getFontFamily().get());
167 | if (font == null) {
168 | font = FontUtil.getPdfFontByName(PDFEditorConstants.DEFAULT_FONT);
169 | }
170 | pdfText.setTextFont(font);
171 | pdfText.setTextSize(textItem.getFontSize().get());
172 | // TODO: здесь пофиксить геттеры
173 | // pdfText.setText(textItem.getText().get());
174 | // System.out.println("-- font --");
175 | // Font font = textItem.getFont().get();
176 | // if (font != null) {
177 | // System.out.println(font.getFamily());
178 | // System.out.println(font.getName());
179 | // System.out.println(font.getSize());
180 | // System.out.println(font.getStyle());
181 | // }
182 | // System.out.println("----------");
183 | // System.out.println("-- background --");
184 | // Background background = textItem.getBackground().get();
185 | // if (background != null) {
186 | // background.getFills().forEach(fill -> System.out.println("background fill: " + fill.getFill()));
187 | // background.getImages().forEach(image -> System.out.println("background image: " + image.getImage().getUrl()));
188 | // System.out.println("background outsets: " + background.getOutsets());
189 | // }
190 | // System.out.println("----------------");
191 | // System.out.println("-- border --");
192 | // Border border = textItem.getBorder().get();
193 | // if (border != null) {
194 | // border.getImages().forEach(image -> System.out.println("border image: " + image.getImage().getUrl()));
195 | // border.getStrokes().forEach(stroke -> System.out.println("border stroke: " + stroke));
196 | // System.out.println("border insets: " + border.getInsets());
197 | // System.out.println("border outsets: " + border.getOutsets());
198 | // }
199 | // System.out.println("------------");
200 | return pdfText;
201 | }
202 |
203 | private static PDFImage convertImageItem(ImageItem imageItem, PageSize pageSize) {
204 | List converted = convertCoordinates(imageItem.getX().get(), imageItem.getY().get(), imageItem.getW().get(), imageItem.getH().get(), pageSize);
205 | PDFImage pdfImage = new PDFImage(
206 | converted.get(0),
207 | converted.get(1),
208 | converted.get(2),
209 | converted.get(3)
210 | );
211 | pdfImage.setImagePath(imageItem.getImageFileName());
212 | return pdfImage;
213 | }
214 |
215 | private static PDFFormula convertFormulaItem(FormulaItem formulaItem, PageSize pageSize) {
216 | List converted = convertCoordinates(formulaItem.getX().get(), formulaItem.getY().get(), formulaItem.getW().get(), formulaItem.getH().get(), pageSize);
217 | PDFFormula pdfFormula = new PDFFormula(
218 | converted.get(0),
219 | converted.get(1),
220 | converted.get(2),
221 | converted.get(3)
222 | );
223 | pdfFormula.setFormula(formulaItem.getFormula().get());
224 | pdfFormula.setFontSize(50);
225 | return pdfFormula;
226 | }
227 | }
228 |
229 |
--------------------------------------------------------------------------------
/src/main/java/hse/btf/pdfeditor/storages/EntitiesStorage.java:
--------------------------------------------------------------------------------
1 | package hse.btf.pdfeditor.storages;
2 |
3 | import hse.btf.pdfeditor.models.entities.PaperEntity;
4 | import javafx.collections.FXCollections;
5 | import javafx.collections.ObservableList;
6 |
7 | public class EntitiesStorage {
8 | public static final ObservableList entitiesList = FXCollections.observableArrayList();
9 | }
10 |
--------------------------------------------------------------------------------
/src/main/java/hse/btf/pdfeditor/storages/ProjectDataStorage.java:
--------------------------------------------------------------------------------
1 | package hse.btf.pdfeditor.storages;
2 |
3 | import hse.btf.pdfeditor.Holder;
4 |
5 | public class ProjectDataStorage {
6 | public static String pdfFileName = "";
7 | public static final Holder itemsHolder = new Holder();
8 | }
9 |
--------------------------------------------------------------------------------
/src/main/java/hse/btf/pdfeditor/utils/CreatorConstants.java:
--------------------------------------------------------------------------------
1 | package hse.btf.pdfeditor.utils;
2 |
3 | import org.jetbrains.annotations.NotNull;
4 |
5 | import java.util.List;
6 |
7 | public final class CreatorConstants {
8 | private CreatorConstants() {
9 | }
10 |
11 | public static final @NotNull List FONTS = List.of("Arial", "Georgia", "Dubai");
12 | public static final @NotNull String DEFAULT_FONT = "Arial";
13 | public static final @NotNull List IMAGE_EFFECTS = List.of("Normal");
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/hse/btf/pdfeditor/utils/FileUtil.java:
--------------------------------------------------------------------------------
1 | package hse.btf.pdfeditor.utils;
2 |
3 | import hse.btf.pdfeditor.PdfEditorApplication;
4 | import hse.btf.pdfeditor.models.entities.ImageEntity;
5 | import hse.btf.pdfeditor.service.Converter;
6 | import hse.btf.pdfeditor.storages.ProjectDataStorage;
7 | import javafx.scene.control.Button;
8 | import javafx.stage.FileChooser;
9 |
10 | import java.awt.*;
11 | import java.io.File;
12 | import java.io.IOException;
13 | import java.nio.file.Files;
14 | import java.nio.file.Path;
15 | import java.util.Locale;
16 |
17 | import static hse.btf.pdfeditor.PdfWorkWindowController.papers;
18 | import static hse.btf.pdfeditor.serializers.SavingClassKt.saveToFile;
19 | import static hse.btf.pdfeditor.storages.EntitiesStorage.entitiesList;
20 |
21 | public class FileUtil {
22 | private static final FileChooser fileChooser = new FileChooser();
23 | private static final Desktop desktop = Desktop.getDesktop();
24 |
25 | public static void savePDFDocument(Button button) {
26 | button.setOnAction(ev -> {
27 | fileChooser.getExtensionFilters().clear();
28 | fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("PDF files", "*.pdf"));
29 | File file;
30 | if (ProjectDataStorage.pdfFileName.isEmpty()) {
31 | file = fileChooser.showSaveDialog(null);
32 | if (file == null) {
33 | return;
34 | }
35 | ProjectDataStorage.pdfFileName = file.getAbsolutePath();
36 | } else {
37 | file = Path.of(ProjectDataStorage.pdfFileName).toFile();
38 | }
39 | try {
40 | Converter.saveDocument(file.getAbsolutePath().toLowerCase(Locale.ROOT));
41 | } catch (IOException e) {
42 | System.err.println("Couldn't convert document");
43 | }
44 | openPDFDocument(file);
45 |
46 | // saving info to JSON
47 | saveToFile(file.getName());
48 | });
49 | }
50 |
51 | private static void openPDFDocument(File file) {
52 | try {
53 | desktop.open(file);
54 | } catch (IOException e) {
55 | System.err.println("Couldn't open file");
56 | }
57 | }
58 |
59 | public static void loadImage(Button button) {
60 | button.setOnAction(ev -> {
61 | fileChooser.getExtensionFilters().clear();
62 | fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("Image files", "*.jpg", "*.png", "*.gif"));
63 | File loadedImage = fileChooser.showOpenDialog(null);
64 | if (loadedImage == null) {
65 | return;
66 | }
67 | ImageEntity entity = new ImageEntity(loadedImage.getAbsolutePath());
68 | entitiesList.add(entity);
69 | entity.setBottomPadding(0);
70 | entity.setTopPadding(0);
71 | entity.setLeftPadding(0);
72 | entity.setRightPadding(0);
73 | papers.get(0).getChildren().add(entity.createFxmlObject());
74 | papers.get(0).getStylesheets().add(PdfEditorApplication.class.getResource("main.css").toExternalForm());
75 | });
76 | }
77 |
78 | public static void loadFont(Button button, String fontName) {
79 | button.setOnAction(ev -> {
80 | fileChooser.getExtensionFilters().clear();
81 | fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("TTF files", "*.ttf"));
82 | File loadedFont = fileChooser.showOpenDialog(null);
83 | System.out.println(loadedFont.getName());
84 | Path newPath = Path.of("src", "main", "resources", "hse/btf/pdfeditor/fonts", loadedFont.getName());
85 | try {
86 | Files.copy(loadedFont.toPath(), newPath);
87 | FontUtil.registerFont(fontName, newPath);
88 | } catch (IOException e) {
89 | System.err.println("Couldn't load font");
90 | }
91 | });
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/src/main/java/hse/btf/pdfeditor/utils/FontUtil.java:
--------------------------------------------------------------------------------
1 | package hse.btf.pdfeditor.utils;
2 |
3 | import com.itextpdf.io.font.PdfEncodings;
4 | import com.itextpdf.kernel.font.PdfFont;
5 | import com.itextpdf.kernel.font.PdfFontFactory;
6 | import hse.btf.pdfeditor.PdfEditorApplication;
7 | import javafx.scene.text.Font;
8 | import org.apache.commons.io.IOUtils;
9 | import org.jetbrains.annotations.NotNull;
10 |
11 | import java.io.IOException;
12 | import java.io.InputStream;
13 | import java.nio.file.Path;
14 | import java.util.HashMap;
15 | import java.util.Map;
16 |
17 | public class FontUtil {
18 | public static final @NotNull String FREE_SANS = "free_sans.ttf";
19 | public static final @NotNull String ARIAL = "arial.ttf";
20 | public static final @NotNull String TIMES_NEW_ROMAN = "times_new_roman.ttf";
21 |
22 | private static Map fontNameToFontPath = new HashMap<>();
23 | private static Map pdfFonts = new HashMap<>();
24 | private static Map fxFonts = new HashMap<>();
25 |
26 | public static void init() {
27 | try {
28 | fontNameToFontPath.clear();
29 | pdfFonts.clear();
30 | fxFonts.clear();
31 | registerFont("Free Sans", Path.of(FREE_SANS));
32 | registerFont("Arial", Path.of(ARIAL));
33 | registerFont("Times New Roman", Path.of(TIMES_NEW_ROMAN));
34 | } catch (IOException e) {
35 | System.err.println("Couldn't load default fonts");
36 | }
37 | }
38 |
39 | public static void registerFont(String fontName, Path fontPath) throws IOException {
40 | fontNameToFontPath.put(fontName, fontPath);
41 | addPdfFont(fontPath);
42 | addFxFont(fontPath);
43 | }
44 |
45 | private static void addPdfFont(Path fontPath) throws IOException {
46 | InputStream is = PdfEditorApplication.class.getResourceAsStream(fontPath.toString());
47 | byte[] fontBytes = IOUtils.toByteArray(is);
48 | PdfFont font = PdfFontFactory.createFont(fontBytes, PdfEncodings.IDENTITY_H);
49 | pdfFonts.put(fontPath, font);
50 | }
51 |
52 | private static void addFxFont(Path fontPath) {
53 | addFxFont(fontPath, PDFEditorConstants.DEFAULT_FONT_SIZE);
54 | }
55 |
56 | public static void addFxFont(Path fontPath, double fontSize) {
57 | Font font = Font.loadFont(PdfEditorApplication.class.getResourceAsStream(fontPath.toString()), fontSize);
58 | fxFonts.put(fontPath, font);
59 | }
60 |
61 | public static PdfFont getPdfFontByName(String fontName) {
62 | Path fontPath = fontNameToFontPath.get(fontName);
63 | return pdfFonts.get(fontPath);
64 | }
65 |
66 | public static Font getFxFontByName(String fontName) {
67 | Path fontPath = fontNameToFontPath.get(fontName);
68 | return fxFonts.get(fontPath);
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/src/main/java/hse/btf/pdfeditor/utils/PDFEditorConstants.java:
--------------------------------------------------------------------------------
1 | package hse.btf.pdfeditor.utils;
2 |
3 | import com.itextpdf.kernel.geom.PageSize;
4 | import org.jetbrains.annotations.NotNull;
5 |
6 | public class PDFEditorConstants {
7 | public static final @NotNull String DEFAULT_FONT = "Free Sans";
8 | public static final double DEFAULT_FONT_SIZE = 14;
9 | // TODO add default color
10 | // TODO add default bg color
11 |
12 | public static final @NotNull String DEFAULT_OUTPUT_DIR = "out/";
13 | public static final @NotNull String DEFAULT_PDF_FILE = DEFAULT_OUTPUT_DIR + "file.pdf";
14 |
15 | public static final @NotNull PageSize DEFAULT_PAGE_SIZE = PageSize.A4;
16 | public static final @NotNull int DEFAULT_LATEX_DPI = 1000;
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/module-info.java:
--------------------------------------------------------------------------------
1 | module hse.btf.pdfeditor {
2 | requires javafx.controls;
3 | requires javafx.fxml;
4 | requires javafx.web;
5 | requires javafx.swing;
6 |
7 | requires org.controlsfx.controls;
8 | requires com.dlsc.formsfx;
9 | requires validatorfx;
10 | requires org.kordamp.ikonli.javafx;
11 | requires org.kordamp.bootstrapfx.core;
12 | requires eu.hansolo.tilesfx;
13 |
14 | requires jlatexmath;
15 | requires kernel;
16 | requires io;
17 | requires layout;
18 | requires forms;
19 | requires pdfa;
20 | requires sign;
21 | requires barcodes;
22 | requires font.asian;
23 | requires hyph;
24 | requires java.desktop;
25 | requires org.apache.commons.io;
26 |
27 | opens hse.btf.pdfeditor to javafx.fxml;
28 | exports hse.btf.pdfeditor;
29 | exports hse.btf.pdfeditor.entity;
30 | opens hse.btf.pdfeditor.entity to javafx.fxml;
31 | exports hse.btf.pdfeditor.models;
32 | opens hse.btf.pdfeditor.models to javafx.fxml;
33 | exports hse.btf.pdfeditor.utils;
34 | opens hse.btf.pdfeditor.utils to javafx.fxml;
35 | exports hse.btf.pdfeditor.models.utility;
36 | opens hse.btf.pdfeditor.models.utility to javafx.fxml;
37 | exports hse.btf.pdfeditor.models.entities;
38 | opens hse.btf.pdfeditor.models.entities to javafx.fxml;
39 | exports hse.btf.pdfeditor.storages;
40 | opens hse.btf.pdfeditor.storages to javafx.fxml;
41 | exports hse.btf.pdfeditor.serializers;
42 | opens hse.btf.pdfeditor.serializers to javafx.fxml;
43 |
44 | requires tornadofx;
45 | requires kotlin.stdlib;
46 | requires kotlin.reflect;
47 | requires kotlinx.serialization.core;
48 | requires kotlinx.serialization.json;
49 | requires annotations;
50 | requires org.jfree.fxgraphics2d;
51 | }
--------------------------------------------------------------------------------
/src/main/kotlin/hse/btf/pdfeditor/EntityToItemConverter.kt:
--------------------------------------------------------------------------------
1 | package hse.btf.pdfeditor
2 |
3 | import hse.btf.pdfeditor.models.FormulaItem
4 | import hse.btf.pdfeditor.models.ImageItem
5 | import hse.btf.pdfeditor.models.TextItem
6 | import hse.btf.pdfeditor.models.entities.FormulaEntity
7 | import hse.btf.pdfeditor.models.entities.ImageEntity
8 | import hse.btf.pdfeditor.models.entities.TextEntity
9 | import hse.btf.pdfeditor.storages.EntitiesStorage.entitiesList
10 | import hse.btf.pdfeditor.storages.ProjectDataStorage.itemsHolder
11 | import tornadofx.bind
12 |
13 | class EntityToItemConverter {
14 | init {
15 | itemsHolder.observableItemsList.bind(entitiesList) {
16 | when (it) {
17 | is TextEntity ->
18 | TextItem().apply {
19 | x.bindBidirectional(it.xProperty)
20 | y.bindBidirectional(it.yProperty)
21 | w.bindBidirectional(it.widthProperty)
22 | h.bindBidirectional(it.heightProperty)
23 |
24 | text.bindBidirectional(it.text)
25 | fontFamily.bindBidirectional(it.fontFamily)
26 | fontName.bindBidirectional(it.fontName)
27 | fontSize.bindBidirectional(it.fontSize)
28 | fontStyle.bindBidirectional(it.fontStyle)
29 | // font.bindBidirectional(it.font)
30 | // background.bindBidirectional(it.background)
31 | // border.bindBidirectional(it.border)
32 |
33 | }
34 | is ImageEntity ->
35 | ImageItem().apply {
36 | x.bindBidirectional(it.xProperty)
37 | y.bindBidirectional(it.yProperty)
38 | w.bindBidirectional(it.widthProperty)
39 | h.bindBidirectional(it.heightProperty)
40 |
41 | imageFileName = it.fileName
42 | }
43 | is FormulaEntity ->
44 | FormulaItem().apply {
45 | x.bindBidirectional(it.xProperty)
46 | y.bindBidirectional(it.yProperty)
47 | w.bindBidirectional(it.widthProperty)
48 | h.bindBidirectional(it.heightProperty)
49 |
50 | formula.bindBidirectional(it.formulaProperty)
51 | }
52 | else -> {
53 | println("Else branch converter")
54 | null
55 | }
56 | }
57 | }
58 | }
59 | }
--------------------------------------------------------------------------------
/src/main/kotlin/hse/btf/pdfeditor/Holder.kt:
--------------------------------------------------------------------------------
1 | package hse.btf.pdfeditor
2 |
3 | import hse.btf.pdfeditor.models.Item
4 | import hse.btf.pdfeditor.storages.ProjectDataStorage
5 | import javafx.collections.FXCollections
6 | import javafx.collections.ObservableList
7 | import kotlinx.serialization.decodeFromString
8 | import kotlinx.serialization.json.Json
9 |
10 | data class Holder(val observableItemsList: ObservableList- = FXCollections.observableArrayList()) {
11 | fun updateFromFileData(fileData: String) {
12 | val itemsList = Json.decodeFromString
>(fileData)
13 |
14 | // updating data
15 | ProjectDataStorage.itemsHolder.observableItemsList.clear()
16 | ProjectDataStorage.itemsHolder.observableItemsList.addAll(itemsList)
17 | }
18 | }
--------------------------------------------------------------------------------
/src/main/kotlin/hse/btf/pdfeditor/datasaving/test.json:
--------------------------------------------------------------------------------
1 | [{"type":"hse.btf.pdfeditor.models.ImageItem","x":112.4,"y":180.0,"w":614,"h":614,"imageFileName":"C:\\Users\\sasha\\Downloads\\268.340x340.jpg"},{"type":"hse.btf.pdfeditor.models.TextItem","x":325.5999999999999,"y":331.2,"w":282,"h":142,"text":"fdjsalkfjslkjflsakjflkdsa;","fontFamily":"","fontName":"","fontSize":13,"fontStyle":""},{"type":"hse.btf.pdfeditor.models.FormulaItem","x":513.5999999999999,"y":284.0,"w":135,"h":220,"formula":"\\frac{1}{2}"}]
--------------------------------------------------------------------------------
/src/main/kotlin/hse/btf/pdfeditor/models/FormulaItem.kt:
--------------------------------------------------------------------------------
1 | package hse.btf.pdfeditor.models
2 |
3 | import hse.btf.pdfeditor.serializers.StringPropertySerializer
4 | import javafx.beans.property.SimpleStringProperty
5 | import javafx.beans.property.StringProperty
6 | import kotlinx.serialization.Serializable
7 |
8 | @Serializable
9 | data class FormulaItem(
10 | @Serializable(with = StringPropertySerializer::class)
11 | val formula: StringProperty = SimpleStringProperty("1")
12 | ) : Item()
--------------------------------------------------------------------------------
/src/main/kotlin/hse/btf/pdfeditor/models/ImageItem.kt:
--------------------------------------------------------------------------------
1 | package hse.btf.pdfeditor.models
2 |
3 | import kotlinx.serialization.Serializable
4 |
5 | @Serializable
6 | data class ImageItem(
7 | var imageFileName: String = ""
8 | ) : Item()
--------------------------------------------------------------------------------
/src/main/kotlin/hse/btf/pdfeditor/models/Item.kt:
--------------------------------------------------------------------------------
1 | package hse.btf.pdfeditor.models
2 |
3 | import hse.btf.pdfeditor.serializers.DoublePropertySerializer
4 | import hse.btf.pdfeditor.serializers.IntegerPropertySerializer
5 | import javafx.beans.property.DoubleProperty
6 | import javafx.beans.property.IntegerProperty
7 | import javafx.beans.property.SimpleDoubleProperty
8 | import javafx.beans.property.SimpleIntegerProperty
9 | import kotlinx.serialization.Serializable
10 |
11 | @Serializable
12 | sealed class Item {
13 | @Serializable(with = DoublePropertySerializer::class)
14 | val x: DoubleProperty = SimpleDoubleProperty(150.0)
15 |
16 | @Serializable(with = DoublePropertySerializer::class)
17 | val y: DoubleProperty = SimpleDoubleProperty(200.0)
18 |
19 | @Serializable(with = IntegerPropertySerializer::class)
20 | val w: IntegerProperty = SimpleIntegerProperty(100)
21 |
22 | @Serializable(with = IntegerPropertySerializer::class)
23 | val h: IntegerProperty = SimpleIntegerProperty(50)
24 | }
--------------------------------------------------------------------------------
/src/main/kotlin/hse/btf/pdfeditor/models/TableItem.kt:
--------------------------------------------------------------------------------
1 | package hse.btf.pdfeditor.models
2 |
3 | import hse.btf.pdfeditor.serializers.IntegerPropertySerializer
4 | import javafx.beans.property.IntegerProperty
5 | import javafx.beans.property.SimpleIntegerProperty
6 | import kotlinx.serialization.Serializable
7 |
8 | @Serializable
9 | data class TableItem (
10 | @Serializable(with = IntegerPropertySerializer::class)
11 | val rows: IntegerProperty = SimpleIntegerProperty(2),
12 |
13 | @Serializable(with = IntegerPropertySerializer::class)
14 | val cols: IntegerProperty = SimpleIntegerProperty(2)
15 | )
--------------------------------------------------------------------------------
/src/main/kotlin/hse/btf/pdfeditor/models/TextItem.kt:
--------------------------------------------------------------------------------
1 | package hse.btf.pdfeditor.models
2 |
3 | import hse.btf.pdfeditor.serializers.IntegerPropertySerializer
4 | import hse.btf.pdfeditor.serializers.StringPropertySerializer
5 | import javafx.beans.property.IntegerProperty
6 | import javafx.beans.property.SimpleIntegerProperty
7 | import javafx.beans.property.SimpleStringProperty
8 | import javafx.beans.property.StringProperty
9 | import kotlinx.serialization.Serializable
10 |
11 | @Serializable
12 | data class TextItem(
13 | @Serializable(with = StringPropertySerializer::class)
14 | val text: StringProperty = SimpleStringProperty("type text here"),
15 |
16 | // val font: ObjectProperty = SimpleObjectProperty(),
17 | // val background: ObjectProperty = SimpleObjectProperty(),
18 | // val border: ObjectProperty = SimpleObjectProperty()
19 |
20 | @Serializable(with = StringPropertySerializer::class)
21 | val fontFamily: StringProperty = SimpleStringProperty(""),
22 |
23 | @Serializable(with = StringPropertySerializer::class)
24 | val fontName: StringProperty = SimpleStringProperty("Arial"),
25 |
26 | @Serializable(with = IntegerPropertySerializer::class)
27 | val fontSize: IntegerProperty = SimpleIntegerProperty(13),
28 |
29 | @Serializable(with = StringPropertySerializer::class)
30 | val fontStyle: StringProperty = SimpleStringProperty("")
31 | ) : Item()
--------------------------------------------------------------------------------
/src/main/kotlin/hse/btf/pdfeditor/serializers/SavingClass.kt:
--------------------------------------------------------------------------------
1 | package hse.btf.pdfeditor.serializers
2 |
3 |
4 | import hse.btf.pdfeditor.storages.ProjectDataStorage.itemsHolder
5 | import kotlinx.serialization.ExperimentalSerializationApi
6 | import kotlinx.serialization.decodeFromString
7 | import kotlinx.serialization.encodeToString
8 | import kotlinx.serialization.json.Json
9 | import java.io.File
10 | import java.nio.file.Files
11 | import java.nio.file.Path
12 |
13 | private val format = Json { encodeDefaults = true }
14 |
15 | @OptIn(ExperimentalSerializationApi::class)
16 | fun saveToFile(fileName: String) {
17 | // opening vs creating file and (over)writing information to it
18 | // test.pdf -> test.json
19 | var splitedFile = fileName.split(".").toTypedArray()
20 | var fileDir = Path.of("src","main", "kotlin", "hse", "btf", "pdfeditor", "datasaving")
21 | if (Files.notExists(fileDir)) {
22 | Files.createDirectories(fileDir)
23 | }
24 | var filePath = Path.of(fileDir.toString(), splitedFile.get(0) + ".json")
25 | if (Files.notExists(filePath)) {
26 | Files.createFile(filePath)
27 | }
28 | val file = filePath.toAbsolutePath().toFile()
29 | // getting Json string
30 | System.out.println(filePath)
31 | val json = format.encodeToString(itemsHolder.observableItemsList.toList())
32 | file.writeText(json)
33 | }
34 |
35 | fun readFromFile(fileName: String) : Boolean {
36 | var filePath = "./src/main/kotlin/hse/btf/pdfeditor/datasaving/"
37 | filePath += if (fileName != "") "$fileName.json" else "dataFile.json"
38 | val file = File(filePath)
39 |
40 | if (!file.exists()) {
41 | return false
42 | }
43 |
44 | val fileData = file.readText()
45 | itemsHolder.updateFromFileData(fileData)
46 | return true
47 | }
48 |
49 | @OptIn(ExperimentalSerializationApi::class)
50 | fun serializeProjectsNames(projectNamesList: List) {
51 | val jsonFile = File("./src/main/resources/users.projects/projectNamesList.json")
52 |
53 | val json = format.encodeToString(projectNamesList)
54 | jsonFile.writeText(json)
55 | }
56 |
57 | @OptIn(ExperimentalSerializationApi::class)
58 | fun deserializeProjectsNames(projectNamesList: MutableList) {
59 | val jsonFile = File("./src/main/resources/users.projects/projectNamesList.json")
60 |
61 | val fileData = jsonFile.readText()
62 | val namesList = try {
63 | Json.decodeFromString>(fileData)
64 | } catch (e: Throwable) {
65 | listOf()
66 | }
67 |
68 | projectNamesList.clear()
69 | projectNamesList.addAll(namesList)
70 | }
--------------------------------------------------------------------------------
/src/main/kotlin/hse/btf/pdfeditor/serializers/Serializers.kt:
--------------------------------------------------------------------------------
1 | package hse.btf.pdfeditor.serializers
2 |
3 | import javafx.beans.property.DoubleProperty
4 | import javafx.beans.property.IntegerProperty
5 | import javafx.beans.property.SimpleDoubleProperty
6 | import javafx.beans.property.SimpleIntegerProperty
7 | import javafx.beans.property.SimpleStringProperty
8 | import javafx.beans.property.StringProperty
9 | import kotlinx.serialization.ExperimentalSerializationApi
10 | import kotlinx.serialization.KSerializer
11 | import kotlinx.serialization.builtins.serializer
12 | import kotlinx.serialization.encoding.Decoder
13 | import kotlinx.serialization.encoding.Encoder
14 |
15 | object StringPropertySerializer : KSerializer {
16 | private val delegateSerializer = String.serializer()
17 |
18 | @OptIn(ExperimentalSerializationApi::class)
19 | override val descriptor = delegateSerializer.descriptor
20 |
21 | override fun serialize(encoder: Encoder, value: StringProperty) {
22 | encoder.encodeSerializableValue(delegateSerializer, value.get())
23 | }
24 |
25 | override fun deserialize(decoder: Decoder): StringProperty {
26 | val stringData = decoder.decodeSerializableValue(delegateSerializer)
27 | return SimpleStringProperty(stringData)
28 | }
29 | }
30 |
31 | object IntegerPropertySerializer : KSerializer {
32 | private val delegateSerializer = Int.serializer()
33 |
34 | @OptIn(ExperimentalSerializationApi::class)
35 | override val descriptor = delegateSerializer.descriptor
36 |
37 | override fun serialize(encoder: Encoder, value: IntegerProperty) {
38 | encoder.encodeSerializableValue(delegateSerializer, value.get())
39 | }
40 |
41 | override fun deserialize(decoder: Decoder): IntegerProperty {
42 | val intData = decoder.decodeSerializableValue(delegateSerializer)
43 | return SimpleIntegerProperty(intData)
44 | }
45 | }
46 |
47 | object DoublePropertySerializer : KSerializer {
48 | private val delegateSerializer = Double.serializer()
49 |
50 | @OptIn(ExperimentalSerializationApi::class)
51 | override val descriptor = delegateSerializer.descriptor
52 |
53 | override fun serialize(encoder: Encoder, value: DoubleProperty) {
54 | encoder.encodeSerializableValue(delegateSerializer, value.get())
55 | }
56 |
57 | override fun deserialize(decoder: Decoder): DoubleProperty {
58 | val doubleData = decoder.decodeSerializableValue(delegateSerializer)
59 | return SimpleDoubleProperty(doubleData)
60 | }
61 | }
--------------------------------------------------------------------------------
/src/main/resources/hello-scene.properties:
--------------------------------------------------------------------------------
1 | # messages and labels for Hello Scene
2 | label.project-name.empty=Empty project name
3 | label.project-name.non-new=Non-new project name
4 | label.project-name.non-existing=No such project
5 |
6 | message.project-name.empty=A project name cannot be an empty string!
7 | message.project-name.non-new=The project with this name was already created!\nPlease, enter a new name or click the button \"open\"
8 | message.project-name.non-existing=The project with this name doesn't exist!\nPlease, enter the name of an existing project or click the button \"create\"
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/main/resources/hse/btf/pdfeditor/arial.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pdf-Creator/pdf-editor/ae30ad8db46ab7c922219e100ef6f5c7ebf551b8/src/main/resources/hse/btf/pdfeditor/arial.ttf
--------------------------------------------------------------------------------
/src/main/resources/hse/btf/pdfeditor/formula-pane.fxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
11 |
12 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/main/resources/hse/btf/pdfeditor/formula-window.fxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/src/main/resources/hse/btf/pdfeditor/free_sans.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pdf-Creator/pdf-editor/ae30ad8db46ab7c922219e100ef6f5c7ebf551b8/src/main/resources/hse/btf/pdfeditor/free_sans.ttf
--------------------------------------------------------------------------------
/src/main/resources/hse/btf/pdfeditor/hello-view.fxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/src/main/resources/hse/btf/pdfeditor/image-pane.fxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/src/main/resources/hse/btf/pdfeditor/main.css:
--------------------------------------------------------------------------------
1 | /*!* TODO: Fix auto-scrolling *!*/
2 | .text-region {
3 | -fx-border-color: gray;
4 | -fx-border-style: dotted;
5 | -fx-border-width: 2;
6 |
7 | -fx-background-color: transparent;
8 | }
9 |
10 | .text-area {
11 | -fx-background-color: transparent;
12 | }
13 |
14 | .text-area .scroll-pane {
15 | -fx-background-color: transparent;
16 | }
17 |
18 | .text-area .scroll-pane .viewport {
19 | -fx-background-color: transparent;
20 | }
21 |
22 |
23 | .text-area .scroll-pane .content{
24 | -fx-background-color: transparent;
25 | }
26 |
27 | .text-area .scroll-bar:vertical {
28 | -fx-pref-width: 0;
29 | -fx-opacity: 0;
30 | }
--------------------------------------------------------------------------------
/src/main/resources/hse/btf/pdfeditor/table-pane.fxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
14 |
15 |
19 |
20 |
22 |
24 |
26 |
27 |
29 |
30 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/src/main/resources/hse/btf/pdfeditor/text-pane.fxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/src/main/resources/hse/btf/pdfeditor/times_new_roman.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pdf-Creator/pdf-editor/ae30ad8db46ab7c922219e100ef6f5c7ebf551b8/src/main/resources/hse/btf/pdfeditor/times_new_roman.ttf
--------------------------------------------------------------------------------
/src/main/resources/hse/btf/pdfeditor/work-window.fxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
10 |
11 |
12 |
13 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
52 |
53 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
64 |
65 |
73 |
81 |
89 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
105 |
106 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
127 |
130 |
132 |
133 |
134 |
135 |
136 |
--------------------------------------------------------------------------------
/src/main/resources/users.projects/projectNamesList.json:
--------------------------------------------------------------------------------
1 | ["Name1","fjslafjlsaf","fdsafsa","fdsafsfsafsa","fsafdsf","fsadfsa","fdsafsafdsafsa","fdsafsafsafsafsaf","fdsafasfsaf","fsdafsfa","fsafsa","fsajflsakjfa","fsafasfsdfs","fsafdsafsafsafsafsa","fsafdsafsa","fdsafsafsafsdafsa","fsdalkjflks","fdsafsffffdsfsda","fdsafas","fdsafsafd","fdsafdsfsfs","fdsfdsa","fdsalkjflkdsajf;s"]
--------------------------------------------------------------------------------
/src/test/java/hse/btf/pdfeditor/ExportTest.java:
--------------------------------------------------------------------------------
1 | package hse.btf.pdfeditor;
2 |
3 | import hse.btf.pdfeditor.entity.PDFDocument;
4 | import org.junit.jupiter.api.AfterEach;
5 | import org.junit.jupiter.api.Test;
6 |
7 | import java.io.IOException;
8 |
9 | public class ExportTest {
10 | private PDFDocument pdfDocument;
11 |
12 | @Test
13 | public void inSameOutDir() throws IOException {
14 | pdfDocument = new PDFDocument("out/file2.pdf");
15 | }
16 |
17 | @Test
18 | public void inNestedDir() throws IOException {
19 | pdfDocument = new PDFDocument("out/nested/file.pdf");
20 | }
21 |
22 | @Test
23 | public void inDeepDir() throws IOException {
24 | pdfDocument = new PDFDocument("out/nested/nested2/file.pdf");
25 | }
26 |
27 | @AfterEach
28 | public void export() {
29 | pdfDocument.exportDocument();
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/test/java/hse/btf/pdfeditor/PDFDocumentTest.java:
--------------------------------------------------------------------------------
1 | package hse.btf.pdfeditor;
2 |
3 | import com.itextpdf.kernel.colors.Color;
4 | import com.itextpdf.kernel.colors.ColorConstants;
5 | import com.itextpdf.layout.properties.TransparentColor;
6 | import hse.btf.pdfeditor.entity.*;
7 | import org.junit.jupiter.api.*;
8 |
9 | import java.io.IOException;
10 | import java.net.MalformedURLException;
11 | import java.util.List;
12 |
13 | @TestClassOrder(ClassOrderer.OrderAnnotation.class)
14 | public class PDFDocumentTest {
15 | private static PDFDocument pdfDocument;
16 | private final int x = 200, y = 200, w = 200, h = 200;
17 |
18 | @BeforeAll
19 | static void init() throws IOException {
20 | pdfDocument = new PDFDocument();
21 | }
22 |
23 | @AfterEach
24 | public void addPage() {
25 | pdfDocument.addPage();
26 | }
27 |
28 | @AfterAll
29 | static void export() {
30 | pdfDocument.exportDocument();
31 | }
32 |
33 | @Test
34 | @Order(1)
35 | public void addRectangleWithTextTest() {
36 | PDFText textItem = new PDFText(x, y, w, h);
37 | textItem.setText("Testing TextItem");
38 | textItem.setTextColor(ColorConstants.BLACK);
39 | textItem.setBorderColor(new TransparentColor(ColorConstants.BLACK, 1));
40 | textItem.setBackgroundColor(new TransparentColor(ColorConstants.CYAN, .2f));
41 | pdfDocument.addRectangleWithTextItem(textItem);
42 | }
43 |
44 | @Test
45 | @Order(2)
46 | public void addRectangleWithImageTest() throws MalformedURLException {
47 | PDFImage imageItem = new PDFImage(x, y, w, h);
48 | imageItem.setImagePath("src/test/resources/images/java_logo.svg");
49 | imageItem.setBorderColor(new TransparentColor(ColorConstants.BLACK, 1));
50 | imageItem.setBackgroundColor(new TransparentColor(ColorConstants.CYAN, .2f));
51 | pdfDocument.addRectangleWithImageItem(imageItem);
52 | }
53 |
54 | @Test
55 | @Order(3)
56 | public void addRectangleWithTableTest() {
57 | PDFTable tableItem = new PDFTable(x, y, w, h);
58 | tableItem.setCols(3);
59 | List content = List.of("1", "2", "3", "4", "5", "6", "7", "8", "9");
60 | tableItem.setCellContents(content);
61 | tableItem.setFontColor(ColorConstants.BLACK);
62 | pdfDocument.addRectangleWithTableItem(tableItem);
63 | }
64 |
65 | @Test
66 | @Order(4)
67 | public void addRectangleWithFormulaTest() throws IOException {
68 | PDFFormula formulaItem = new PDFFormula(x, y, w, h);
69 | formulaItem.setFormula("x = \\frac{-b \\pm \\sqrt{b^2 - 4ac}}{2a}");
70 | formulaItem.setBorderColor(new TransparentColor(ColorConstants.BLACK, 1));
71 | formulaItem.setBackgroundColor(new TransparentColor(ColorConstants.CYAN, .2f));
72 | formulaItem.setFontSize(20);
73 | pdfDocument.addRectangleWithFormulaItem(formulaItem);
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/src/test/resources/images/java_logo.svg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pdf-Creator/pdf-editor/ae30ad8db46ab7c922219e100ef6f5c7ebf551b8/src/test/resources/images/java_logo.svg
--------------------------------------------------------------------------------