diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index b54e7c5..b53c82a 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -5,7 +5,7 @@ env:
# Build configurations
JAVA_VERSION: '17'
MAVEN_CLI_OPTS: "-B -ntp" # Non-interactive, no transfer progress
- MAVEN_OPTS: "-Xmx4g -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn" # More memory, less logging
+ MAVEN_OPTS: "-Xmx4g -Dorg.slf4j.simpleLOGGER.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn" # More memory, less logging
# Quality thresholds
MIN_COVERAGE: 80
diff --git a/config/checkstyle.xml b/config/checkstyle.xml
index 06bb9d3..c6c6c13 100644
--- a/config/checkstyle.xml
+++ b/config/checkstyle.xml
@@ -13,7 +13,7 @@
-
+
@@ -30,7 +30,6 @@
-
diff --git a/src/main/java/io/github/joabsonlg/pdfbuilder/components/image/Image.java b/src/main/java/io/github/joabsonlg/pdfbuilder/components/image/Image.java
index 7237fd2..203e9e3 100644
--- a/src/main/java/io/github/joabsonlg/pdfbuilder/components/image/Image.java
+++ b/src/main/java/io/github/joabsonlg/pdfbuilder/components/image/Image.java
@@ -16,7 +16,7 @@
* Componente para renderização de imagens em documentos PDF.
* Suporta redimensionamento, rotação e diferentes formatos de imagem.
*/
-public class Image {
+public final class Image {
public enum Alignment {
LEFT, CENTER, RIGHT
}
@@ -46,15 +46,11 @@ private Image(Builder builder) {
*/
public float render(PDPageContentStream contentStream, float x, float y, float availableWidth, float imageWidth) throws IOException {
// Calcula a posição X baseada no alinhamento
- float xPos = x;
- switch (alignment) {
- case CENTER:
- xPos = x + (availableWidth - imageWidth) / 2;
- break;
- case RIGHT:
- xPos = x + (availableWidth - imageWidth);
- break;
- }
+ float xPos = switch (alignment) {
+ case CENTER -> x + (availableWidth - imageWidth) / 2;
+ case RIGHT -> x + (availableWidth - imageWidth);
+ default -> x;
+ };
float imageHeight = (imageWidth / width) * height;
@@ -83,10 +79,10 @@ public float render(PDPageContentStream contentStream, float x, float y, float a
PDFont font = new PDType1Font(Standard14Fonts.FontName.HELVETICA);
contentStream.beginText();
contentStream.setFont(font, captionFontSize);
-
+
float captionWidth = font.getStringWidth(caption) / 1000 * captionFontSize;
float captionX;
-
+
// Alinha a legenda com a imagem
switch (alignment) {
case CENTER:
@@ -99,11 +95,11 @@ public float render(PDPageContentStream contentStream, float x, float y, float a
captionX = xPos;
break;
}
-
+
contentStream.newLineAtOffset(captionX, newY - captionFontSize - 5);
contentStream.showText(caption);
contentStream.endText();
-
+
newY -= (captionFontSize + 10); // Espaço extra após a legenda
}
@@ -125,7 +121,7 @@ public static Builder builder(PDDocument document, String imagePath) throws IOEx
return new Builder(document, new File(imagePath));
}
- public static class Builder {
+ public static final class Builder {
private PDImageXObject image;
private float width;
private float height;
diff --git a/src/main/java/io/github/joabsonlg/pdfbuilder/components/list/List.java b/src/main/java/io/github/joabsonlg/pdfbuilder/components/list/List.java
index ee137c0..c799e74 100644
--- a/src/main/java/io/github/joabsonlg/pdfbuilder/components/list/List.java
+++ b/src/main/java/io/github/joabsonlg/pdfbuilder/components/list/List.java
@@ -15,8 +15,8 @@
* Componente para renderizar listas ordenadas e não ordenadas em documentos PDF.
* Suporta subitens e numeração hierárquica.
*/
-public class List {
- private static final Logger logger = LoggerFactory.getLogger(List.class);
+public final class List {
+ private static final Logger LOGGER = LoggerFactory.getLogger(List.class);
private final java.util.List items;
private final boolean ordered;
diff --git a/src/main/java/io/github/joabsonlg/pdfbuilder/components/logo/Logo.java b/src/main/java/io/github/joabsonlg/pdfbuilder/components/logo/Logo.java
index 8883b7e..a3d7773 100644
--- a/src/main/java/io/github/joabsonlg/pdfbuilder/components/logo/Logo.java
+++ b/src/main/java/io/github/joabsonlg/pdfbuilder/components/logo/Logo.java
@@ -8,7 +8,7 @@
/**
* Componente para renderizar o logo do documento.
*/
-public class Logo {
+public final class Logo {
private final String title;
private final LogoStyle style;
private final PDImageXObject leftImage;
@@ -48,11 +48,11 @@ public void render(PDPageContentStream contentStream, float pageWidth, float y,
if (leftImage != null) {
float imageX = marginLeft + style.getImageMargin();
float imageY = y - style.getImageHeight() + (style.getFontSize() / 2);
-
+
// Calcula as dimensões da imagem mantendo a proporção se necessário
float imageWidth = style.getImageWidth();
float imageHeight = style.getImageHeight();
-
+
if (style.isMaintainAspectRatio()) {
float aspectRatio = (float) leftImage.getHeight() / leftImage.getWidth();
if (imageWidth > 0) {
@@ -61,7 +61,7 @@ public void render(PDPageContentStream contentStream, float pageWidth, float y,
imageWidth = imageHeight / aspectRatio;
}
}
-
+
contentStream.drawImage(leftImage, imageX, imageY, imageWidth, imageHeight);
}
@@ -76,11 +76,11 @@ public void render(PDPageContentStream contentStream, float pageWidth, float y,
if (rightImage != null) {
float imageX = pageWidth - marginRight - style.getImageWidth() - style.getImageMargin();
float imageY = y - style.getImageHeight() + (style.getFontSize() / 2);
-
+
// Calcula as dimensões da imagem mantendo a proporção se necessário
float imageWidth = style.getImageWidth();
float imageHeight = style.getImageHeight();
-
+
if (style.isMaintainAspectRatio()) {
float aspectRatio = (float) rightImage.getHeight() / rightImage.getWidth();
if (imageWidth > 0) {
@@ -89,7 +89,7 @@ public void render(PDPageContentStream contentStream, float pageWidth, float y,
imageWidth = imageHeight / aspectRatio;
}
}
-
+
contentStream.drawImage(rightImage, imageX, imageY, imageWidth, imageHeight);
}
@@ -115,7 +115,7 @@ public static Builder builder() {
return new Builder();
}
- public static class Builder {
+ public static final class Builder {
private String title;
private LogoStyle style;
private PDImageXObject leftImage;
diff --git a/src/main/java/io/github/joabsonlg/pdfbuilder/components/logo/LogoStyle.java b/src/main/java/io/github/joabsonlg/pdfbuilder/components/logo/LogoStyle.java
index d267c51..402778b 100644
--- a/src/main/java/io/github/joabsonlg/pdfbuilder/components/logo/LogoStyle.java
+++ b/src/main/java/io/github/joabsonlg/pdfbuilder/components/logo/LogoStyle.java
@@ -11,8 +11,8 @@
/**
* Configurações de estilo para o logo do documento.
*/
-public class LogoStyle {
- private static final Logger logger = LoggerFactory.getLogger(LogoStyle.class);
+public final class LogoStyle {
+ private static final Logger LOGGER = LoggerFactory.getLogger(LogoStyle.class);
private final PDFont font;
private final float fontSize;
@@ -108,7 +108,7 @@ public Builder() {
try {
this.font = new PDType1Font(Standard14Fonts.FontName.HELVETICA_BOLD);
} catch (Exception e) {
- logger.error("Erro ao criar fonte padrão", e);
+ LOGGER.error("Erro ao criar fonte padrão", e);
throw new RuntimeException("Erro ao criar fonte padrão", e);
}
}
diff --git a/src/main/java/io/github/joabsonlg/pdfbuilder/components/page/PageNumbering.java b/src/main/java/io/github/joabsonlg/pdfbuilder/components/page/PageNumbering.java
index b6353c0..55b5762 100644
--- a/src/main/java/io/github/joabsonlg/pdfbuilder/components/page/PageNumbering.java
+++ b/src/main/java/io/github/joabsonlg/pdfbuilder/components/page/PageNumbering.java
@@ -1,21 +1,20 @@
package io.github.joabsonlg.pdfbuilder.components.page;
import io.github.joabsonlg.pdfbuilder.components.text.TextAlignment;
-import io.github.joabsonlg.pdfbuilder.components.text.TextStyle;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.font.PDFont;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.awt.Color;
+import java.awt.*;
import java.io.IOException;
/**
* Componente para adicionar numeração de páginas em documentos PDF.
* Suporta diferentes formatos e posicionamentos.
*/
-public class PageNumbering {
- private static final Logger logger = LoggerFactory.getLogger(PageNumbering.class);
+public final class PageNumbering {
+ private static final Logger LOGGER = LoggerFactory.getLogger(PageNumbering.class);
private final Format format;
private final Position position;
@@ -41,10 +40,10 @@ private PageNumbering(Builder builder) {
* Renderiza o número da página no documento.
*
* @param contentStream Stream do conteúdo da página
- * @param pageWidth Largura da página
- * @param pageHeight Altura da página
- * @param pageNumber Número da página atual
- * @param totalPages Total de páginas no documento
+ * @param pageWidth Largura da página
+ * @param pageHeight Altura da página
+ * @param pageNumber Número da página atual
+ * @param totalPages Total de páginas no documento
*/
public void render(PDPageContentStream contentStream, float pageWidth, float pageHeight, int pageNumber, int totalPages) throws IOException {
String text = formatPageNumber(pageNumber, totalPages);
@@ -151,13 +150,9 @@ public PageNumbering build() {
* Formato da numeração de página.
*/
public enum Format {
- /** Apenas o número da página (ex: "1") */
SIMPLE,
- /** Número da página com total (ex: "1 de 10") */
WITH_TOTAL,
- /** Número da página com traço e total (ex: "1 - 10") */
DASH_TOTAL,
- /** Número da página com total entre parênteses (ex: "1 (10)") */
PARENTHESES_TOTAL
}
@@ -165,9 +160,7 @@ public enum Format {
* Posição da numeração na página.
*/
public enum Position {
- /** No topo da página */
TOP,
- /** No rodapé da página */
BOTTOM
}
}
diff --git a/src/main/java/io/github/joabsonlg/pdfbuilder/components/page/PageSection.java b/src/main/java/io/github/joabsonlg/pdfbuilder/components/page/PageSection.java
index 66ec5aa..3668e51 100644
--- a/src/main/java/io/github/joabsonlg/pdfbuilder/components/page/PageSection.java
+++ b/src/main/java/io/github/joabsonlg/pdfbuilder/components/page/PageSection.java
@@ -11,7 +11,7 @@
/**
* Componente para renderização de cabeçalhos e rodapés em documentos PDF.
*/
-public class PageSection {
+public final class PageSection {
private final String leftText;
private final String centerText;
private final String rightText;
@@ -93,7 +93,7 @@ public void render(PDPageContentStream contentStream, float pageWidth, float y,
float contentWidth = pageWidth - marginLeft - marginRight;
float textY = y;
float lineY = y - (fontSize / 2); // Move a linha para baixo do texto
-
+
// Configura a fonte e cor
contentStream.setFont(font, fontSize);
contentStream.setNonStrokingColor(color);
@@ -153,7 +153,7 @@ public static Builder builder() {
return new Builder();
}
- public static class Builder {
+ public static final class Builder {
private String leftText;
private String centerText;
private String rightText;
diff --git a/src/main/java/io/github/joabsonlg/pdfbuilder/components/page/PageSectionStyle.java b/src/main/java/io/github/joabsonlg/pdfbuilder/components/page/PageSectionStyle.java
index b12aaa5..c587f78 100644
--- a/src/main/java/io/github/joabsonlg/pdfbuilder/components/page/PageSectionStyle.java
+++ b/src/main/java/io/github/joabsonlg/pdfbuilder/components/page/PageSectionStyle.java
@@ -1,17 +1,20 @@
package io.github.joabsonlg.pdfbuilder.components.page;
-import io.github.joabsonlg.pdfbuilder.components.text.TextAlignment;
import org.apache.pdfbox.pdmodel.font.PDType1Font;
import org.apache.pdfbox.pdmodel.font.Standard14Fonts;
-import java.awt.Color;
+import java.awt.*;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
/**
* Estilos predefinidos para cabeçalhos e rodapés.
*/
-public class PageSectionStyle {
+public final class PageSectionStyle {
+
+ private PageSectionStyle() {
+ throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
+ }
/**
* Estilo minimalista com linha separadora fina.
diff --git a/src/main/java/io/github/joabsonlg/pdfbuilder/components/table/Table.java b/src/main/java/io/github/joabsonlg/pdfbuilder/components/table/Table.java
index da43d22..6c6e4e7 100644
--- a/src/main/java/io/github/joabsonlg/pdfbuilder/components/table/Table.java
+++ b/src/main/java/io/github/joabsonlg/pdfbuilder/components/table/Table.java
@@ -5,7 +5,7 @@
import org.apache.pdfbox.pdmodel.font.PDType1Font;
import org.apache.pdfbox.pdmodel.font.Standard14Fonts;
-import java.awt.Color;
+import java.awt.*;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@@ -14,7 +14,7 @@
* Componente para renderização de tabelas em documentos PDF.
* Suporta células com texto simples, alinhamento e cores de fundo.
*/
-public class Table {
+public final class Table {
private final List> data;
private final float[] columnWidths;
private final float rowHeight;
@@ -90,15 +90,15 @@ private float drawRow(PDPageContentStream contentStream, List row, float
// Primeiro, calcula a altura necessária para a linha
float maxTextHeight = 0;
List> wrappedTexts = new ArrayList<>();
-
+
for (int i = 0; i < row.size() && i < columnWidths.length; i++) {
String cellText = row.get(i);
float columnWidth = columnWidths[i];
float maxWidth = columnWidth - 10; // 5 pixels de padding de cada lado
-
+
List lines = wrapText(cellText, font, fontSize, maxWidth);
wrappedTexts.add(lines);
-
+
float textHeight = lines.size() * fontSize;
maxTextHeight = Math.max(maxTextHeight, textHeight);
}
@@ -127,14 +127,14 @@ private float drawRow(PDPageContentStream contentStream, List row, float
// Calcula a altura total do texto
float textHeight = lines.size() * fontSize;
-
+
// Calcula a posição Y inicial para centralizar verticalmente todas as linhas
float startY = y - actualRowHeight + (actualRowHeight - textHeight) / 2;
// Desenha cada linha do texto
for (int lineIndex = 0; lineIndex < lines.size(); lineIndex++) {
String line = lines.get(lineIndex);
-
+
// Calcula a posição X para centralizar a linha horizontalmente
float textWidth = font.getStringWidth(line) / 1000 * fontSize;
float textX = currentX + (columnWidth - textWidth) / 2;
@@ -215,7 +215,7 @@ public static Builder builder() {
return new Builder();
}
- public static class Builder {
+ public static final class Builder {
private List> data = new ArrayList<>();
private float[] columnWidths = new float[0];
private float rowHeight = 20f;
diff --git a/src/main/java/io/github/joabsonlg/pdfbuilder/components/text/Heading.java b/src/main/java/io/github/joabsonlg/pdfbuilder/components/text/Heading.java
index 5d0312b..744a273 100644
--- a/src/main/java/io/github/joabsonlg/pdfbuilder/components/text/Heading.java
+++ b/src/main/java/io/github/joabsonlg/pdfbuilder/components/text/Heading.java
@@ -5,14 +5,14 @@
import org.apache.pdfbox.pdmodel.font.PDType1Font;
import org.apache.pdfbox.pdmodel.font.Standard14Fonts;
-import java.awt.Color;
+import java.awt.*;
import java.io.IOException;
/**
* Componente para renderização de títulos e subtítulos.
* Suporta numeração automática, diferentes níveis e espaçamento personalizado.
*/
-public class Heading {
+public final class Heading {
private final HeadingLevel level;
private final String text;
private final TextStyle style;
diff --git a/src/main/java/io/github/joabsonlg/pdfbuilder/components/text/Paragraph.java b/src/main/java/io/github/joabsonlg/pdfbuilder/components/text/Paragraph.java
index 0f78e14..5e3265b 100644
--- a/src/main/java/io/github/joabsonlg/pdfbuilder/components/text/Paragraph.java
+++ b/src/main/java/io/github/joabsonlg/pdfbuilder/components/text/Paragraph.java
@@ -2,6 +2,7 @@
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.font.PDFont;
+
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@@ -9,7 +10,7 @@
/**
* Componente para renderização de parágrafos com alinhamento e formatação rica.
*/
-public class Paragraph {
+public final class Paragraph {
private final List styledTexts;
private final TextAlignment alignment;
private final float lineSpacing;
@@ -30,7 +31,7 @@ public float render(PDPageContentStream contentStream, float x, float y, float m
for (List line : lines) {
float startX = calculateStartX(line, x, maxWidth);
float wordSpacing = calculateWordSpacing(line, maxWidth);
-
+
float currentX = startX;
for (int i = 0; i < line.size(); i++) {
StyledText styledText = line.get(i);
@@ -78,15 +79,15 @@ private float calculateWordSpacing(List line, float maxWidth) throws
float totalTextWidth = 0;
int spaces = line.size() - 1;
-
+
for (StyledText styledText : line) {
- totalTextWidth += getStringWidth(styledText.getText(),
- styledText.getStyle().getFont(),
- styledText.getStyle().getFontSize());
+ totalTextWidth += getStringWidth(styledText.getText(),
+ styledText.getStyle().getFont(),
+ styledText.getStyle().getFontSize());
}
float totalSpaceWidth = maxWidth - totalTextWidth;
-
+
return totalSpaceWidth / spaces;
}
@@ -96,10 +97,10 @@ private float calculateStartX(List line, float baseX, float maxWidth
for (int i = 0; i < line.size(); i++) {
StyledText styledText = line.get(i);
- lineWidth += getStringWidth(styledText.getText(),
- styledText.getStyle().getFont(),
- styledText.getStyle().getFontSize());
-
+ lineWidth += getStringWidth(styledText.getText(),
+ styledText.getStyle().getFont(),
+ styledText.getStyle().getFontSize());
+
if (i < line.size() - 1) {
lineWidth += spaceWidth;
}
@@ -154,7 +155,9 @@ private float getSpaceWidth(PDFont font, float fontSize) throws IOException {
}
public float getHeight() {
- if (styledTexts.isEmpty()) return 0;
+ if (styledTexts.isEmpty()) {
+ return 0;
+ }
return styledTexts.get(0).getStyle().getFontSize() * lineSpacing;
}
diff --git a/src/main/java/io/github/joabsonlg/pdfbuilder/components/text/SimpleText.java b/src/main/java/io/github/joabsonlg/pdfbuilder/components/text/SimpleText.java
index c3a050b..2263bfc 100644
--- a/src/main/java/io/github/joabsonlg/pdfbuilder/components/text/SimpleText.java
+++ b/src/main/java/io/github/joabsonlg/pdfbuilder/components/text/SimpleText.java
@@ -2,7 +2,8 @@
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.font.PDFont;
-import java.awt.Color;
+
+import java.awt.*;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@@ -10,7 +11,7 @@
/**
* Componente para renderização de texto simples.
*/
-public class SimpleText {
+public final class SimpleText {
private final String text;
private final PDFont font;
private final float fontSize;
@@ -27,10 +28,11 @@ private SimpleText(String text, PDFont font, float fontSize, float lineSpacing,
/**
* Renderiza o texto no PDPageContentStream respeitando a largura máxima.
+ *
* @param contentStream Stream de conteúdo do PDF
- * @param x Posição X inicial
- * @param y Posição Y inicial
- * @param maxWidth Largura máxima disponível
+ * @param x Posição X inicial
+ * @param y Posição Y inicial
+ * @param maxWidth Largura máxima disponível
* @return Posição Y final após renderizar todo o texto
* @throws IOException se houver erro ao renderizar
*/
@@ -56,6 +58,7 @@ public float render(PDPageContentStream contentStream, float x, float y, float m
/**
* Quebra o texto em linhas respeitando a largura máxima.
+ *
* @param maxWidth Largura máxima disponível
* @return Lista de linhas
* @throws IOException se houver erro no cálculo
@@ -66,12 +69,12 @@ private List breakTextIntoLines(float maxWidth) throws IOException {
StringBuilder currentLine = new StringBuilder();
for (String word : words) {
- String testLine = currentLine.length() > 0
- ? currentLine + " " + word
- : word;
-
+ String testLine = currentLine.length() > 0
+ ? currentLine + " " + word
+ : word;
+
float lineWidth = getStringWidth(testLine);
-
+
if (lineWidth <= maxWidth) {
currentLine = new StringBuilder(testLine);
} else {
@@ -101,6 +104,7 @@ private float getStringWidth(String str) throws IOException {
/**
* Calcula a altura da linha incluindo o espaçamento.
+ *
* @return Altura em pontos
*/
public float getHeight() {
diff --git a/src/main/java/io/github/joabsonlg/pdfbuilder/components/text/StyledText.java b/src/main/java/io/github/joabsonlg/pdfbuilder/components/text/StyledText.java
index e37d8bb..8086793 100644
--- a/src/main/java/io/github/joabsonlg/pdfbuilder/components/text/StyledText.java
+++ b/src/main/java/io/github/joabsonlg/pdfbuilder/components/text/StyledText.java
@@ -12,6 +12,11 @@ public StyledText(String text, TextStyle style) {
this.style = style;
}
- public String getText() { return text; }
- public TextStyle getStyle() { return style; }
+ public String getText() {
+ return text;
+ }
+
+ public TextStyle getStyle() {
+ return style;
+ }
}
diff --git a/src/main/java/io/github/joabsonlg/pdfbuilder/components/text/TextStyle.java b/src/main/java/io/github/joabsonlg/pdfbuilder/components/text/TextStyle.java
index 0fbab48..aef7aa2 100644
--- a/src/main/java/io/github/joabsonlg/pdfbuilder/components/text/TextStyle.java
+++ b/src/main/java/io/github/joabsonlg/pdfbuilder/components/text/TextStyle.java
@@ -1,12 +1,13 @@
package io.github.joabsonlg.pdfbuilder.components.text;
-import java.awt.Color;
import org.apache.pdfbox.pdmodel.font.PDFont;
+import java.awt.*;
+
/**
* Define o estilo de formatação para um trecho de texto.
*/
-public class TextStyle {
+public final class TextStyle {
private final PDFont font;
private final float fontSize;
private final Color color;
@@ -23,12 +24,29 @@ private TextStyle(Builder builder) {
this.underlineOffset = builder.underlineOffset;
}
- public PDFont getFont() { return font; }
- public float getFontSize() { return fontSize; }
- public Color getColor() { return color; }
- public boolean isUnderline() { return underline; }
- public float getUnderlineThickness() { return underlineThickness; }
- public float getUnderlineOffset() { return underlineOffset; }
+ public PDFont getFont() {
+ return font;
+ }
+
+ public float getFontSize() {
+ return fontSize;
+ }
+
+ public Color getColor() {
+ return color;
+ }
+
+ public boolean isUnderline() {
+ return underline;
+ }
+
+ public float getUnderlineThickness() {
+ return underlineThickness;
+ }
+
+ public float getUnderlineOffset() {
+ return underlineOffset;
+ }
public static Builder builder() {
return new Builder();
diff --git a/src/main/java/io/github/joabsonlg/pdfbuilder/core/Coordinates.java b/src/main/java/io/github/joabsonlg/pdfbuilder/core/Coordinates.java
index e0c14f3..74fc8b9 100644
--- a/src/main/java/io/github/joabsonlg/pdfbuilder/core/Coordinates.java
+++ b/src/main/java/io/github/joabsonlg/pdfbuilder/core/Coordinates.java
@@ -7,8 +7,8 @@
/**
* Gerencia coordenadas e posicionamento no documento PDF.
*/
-public class Coordinates {
- private static final Logger logger = LoggerFactory.getLogger(Coordinates.class);
+public final class Coordinates {
+ private static final Logger LOGGER = LoggerFactory.getLogger(Coordinates.class);
private final float x;
private final float y;
@@ -24,6 +24,7 @@ private Coordinates(float x, float y, PDRectangle pageSize, SafeArea safeArea) {
/**
* Cria uma nova instância de Coordinates na origem (0,0).
+ *
* @param pageSize Tamanho da página
* @param safeArea Área segura
* @return Nova instância de Coordinates
@@ -34,6 +35,7 @@ public static Coordinates origin(PDRectangle pageSize, SafeArea safeArea) {
/**
* Move para uma posição específica.
+ *
* @param x Coordenada X
* @param y Coordenada Y
* @return Nova instância de Coordinates
@@ -44,6 +46,7 @@ public Coordinates moveTo(float x, float y) {
/**
* Move relativamente à posição atual.
+ *
* @param deltaX Deslocamento em X
* @param deltaY Deslocamento em Y
* @return Nova instância de Coordinates
@@ -54,6 +57,7 @@ public Coordinates moveBy(float deltaX, float deltaY) {
/**
* Move para uma posição relativa à área de conteúdo.
+ *
* @param percentX Porcentagem da largura (0-100)
* @param percentY Porcentagem da altura (0-100)
* @return Nova instância de Coordinates
@@ -72,6 +76,7 @@ public Coordinates moveToContentPercent(float percentX, float percentY) {
/**
* Move para uma posição na área do cabeçalho.
+ *
* @param percentX Porcentagem da largura (0-100)
* @param percentY Porcentagem da altura do cabeçalho (0-100)
* @return Nova instância de Coordinates
@@ -94,6 +99,7 @@ public Coordinates moveToHeader(float percentX, float percentY) {
/**
* Move para uma posição na área do rodapé.
+ *
* @param percentX Porcentagem da largura (0-100)
* @param percentY Porcentagem da altura do rodapé (0-100)
* @return Nova instância de Coordinates
@@ -116,6 +122,7 @@ public Coordinates moveToFooter(float percentX, float percentY) {
/**
* Move para o topo da área de conteúdo.
+ *
* @return Nova instância de Coordinates no topo da área de conteúdo
*/
public Coordinates moveToTop() {
@@ -126,6 +133,7 @@ public Coordinates moveToTop() {
/**
* Verifica se a posição atual está dentro da área segura.
+ *
* @return true se estiver dentro da área segura
*/
public boolean isInSafeArea() {
@@ -135,6 +143,7 @@ public boolean isInSafeArea() {
/**
* Retorna a posição atual ajustada para estar dentro da área segura.
* Se a posição atual estiver fora da área segura, move para o ponto mais próximo dentro dela.
+ *
* @return Nova instância de Coordinates dentro da área segura
*/
public Coordinates ensureInSafeArea() {
@@ -160,14 +169,25 @@ public Coordinates ensureInSafeArea() {
newY = contentArea.getUpperRightY();
}
- logger.debug("Ajustando coordenadas de ({},{}) para ({},{}) para respeitar área segura",
- x, y, newX, newY);
+ LOGGER.debug("Ajustando coordenadas de ({},{}) para ({},{}) para respeitar área segura",
+ x, y, newX, newY);
return new Coordinates(newX, newY, pageSize, safeArea);
}
// Getters
- public float getX() { return x; }
- public float getY() { return y; }
- public PDRectangle getPageSize() { return pageSize; }
- public SafeArea getSafeArea() { return safeArea; }
+ public float getX() {
+ return x;
+ }
+
+ public float getY() {
+ return y;
+ }
+
+ public PDRectangle getPageSize() {
+ return pageSize;
+ }
+
+ public SafeArea getSafeArea() {
+ return safeArea;
+ }
}
diff --git a/src/main/java/io/github/joabsonlg/pdfbuilder/core/PDFBuilder.java b/src/main/java/io/github/joabsonlg/pdfbuilder/core/PDFBuilder.java
index 7158b8c..a2dab38 100644
--- a/src/main/java/io/github/joabsonlg/pdfbuilder/core/PDFBuilder.java
+++ b/src/main/java/io/github/joabsonlg/pdfbuilder/core/PDFBuilder.java
@@ -19,7 +19,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.awt.Dimension;
+import java.awt.*;
import java.io.IOException;
/**
@@ -27,7 +27,7 @@
* Fornece uma API fluente para criação e manipulação de PDFs.
*/
public class PDFBuilder {
- private static final Logger logger = LoggerFactory.getLogger(PDFBuilder.class);
+ private static final Logger LOGGER = LoggerFactory.getLogger(PDFBuilder.class);
private static final float DEFAULT_FONT_SIZE = 12.0f;
private final PDDocument document;
@@ -45,6 +45,7 @@ public class PDFBuilder {
/**
* Cria uma nova instância do PDFBuilder com a configuração fornecida.
+ *
* @param config Configuração do PDF
*/
public PDFBuilder(PDFConfiguration config) {
@@ -55,16 +56,16 @@ public PDFBuilder(PDFConfiguration config) {
this.lineSpacing = 1.5f;
this.currentFontSize = DEFAULT_FONT_SIZE;
this.resourceManager = new ResourceManager(document);
-
+
try {
this.contentStream = new PDPageContentStream(document, currentPage);
// Inicializa a posição atual no topo da página
this.currentPosition = Coordinates.origin(config.getPageSize(), config.getSafeArea())
- .moveTo(
- config.getSafeArea().getMarginLeft(),
- config.getPageSize().getHeight() - config.getSafeArea().getMarginTop()
- );
-
+ .moveTo(
+ config.getSafeArea().getMarginLeft(),
+ config.getPageSize().getHeight() - config.getSafeArea().getMarginTop()
+ );
+
// Adiciona o logo na primeira página se existir
if (logo != null) {
addLogo();
@@ -76,6 +77,7 @@ public PDFBuilder(PDFConfiguration config) {
/**
* Cria uma nova instância do PDFBuilder com configuração padrão.
+ *
* @return Nova instância do PDFBuilder
*/
public static PDFBuilder create() {
@@ -84,6 +86,7 @@ public static PDFBuilder create() {
/**
* Cria uma nova instância do PDFBuilder com configuração personalizada.
+ *
* @param config Configuração personalizada
* @return Nova instância do PDFBuilder
*/
@@ -96,12 +99,13 @@ public static PDFBuilder create(PDFConfiguration config) {
/**
* Adiciona uma nova página ao documento.
+ *
* @return this para chamadas encadeadas
*/
public PDFBuilder addNewPage() {
try {
addNewPageInternal();
- logger.debug("Nova página adicionada ao documento");
+ LOGGER.debug("Nova página adicionada ao documento");
return this;
} catch (IOException e) {
throw new RuntimeException("Erro ao adicionar nova página", e);
@@ -126,14 +130,14 @@ private void addNewPageInternal() throws IOException {
// Cria novo content stream
contentStream = new PDPageContentStream(document, currentPage);
-
+
// Reseta a posição para o topo da nova página
currentPosition = Coordinates.origin(config.getPageSize(), config.getSafeArea())
- .moveTo(
- config.getSafeArea().getMarginLeft(),
- config.getPageSize().getHeight() - config.getSafeArea().getMarginTop()
- );
-
+ .moveTo(
+ config.getSafeArea().getMarginLeft(),
+ config.getPageSize().getHeight() - config.getSafeArea().getMarginTop()
+ );
+
// Adiciona logo à nova página
if (logo != null) {
addLogo();
@@ -142,6 +146,7 @@ private void addNewPageInternal() throws IOException {
/**
* Move para uma posição específica na página.
+ *
* @param x Coordenada X
* @param y Coordenada Y
* @return this para chamadas encadeadas
@@ -153,6 +158,7 @@ public PDFBuilder moveTo(float x, float y) {
/**
* Move relativamente à posição atual.
+ *
* @param deltaX Deslocamento em X
* @param deltaY Deslocamento em Y
* @return this para chamadas encadeadas
@@ -164,6 +170,7 @@ public PDFBuilder moveBy(float deltaX, float deltaY) {
/**
* Move para uma posição relativa à área de conteúdo.
+ *
* @param percentX Porcentagem da largura (0-100)
* @param percentY Porcentagem da altura (0-100)
* @return this para chamadas encadeadas
@@ -175,6 +182,7 @@ public PDFBuilder moveToContentPercent(float percentX, float percentY) {
/**
* Move para uma posição na área do cabeçalho.
+ *
* @param percentX Porcentagem da largura (0-100)
* @param percentY Porcentagem da altura do cabeçalho (0-100)
* @return this para chamadas encadeadas
@@ -186,6 +194,7 @@ public PDFBuilder moveToHeader(float percentX, float percentY) {
/**
* Move para uma posição na área do rodapé.
+ *
* @param percentX Porcentagem da largura (0-100)
* @param percentY Porcentagem da altura do rodapé (0-100)
* @return this para chamadas encadeadas
@@ -197,6 +206,7 @@ public PDFBuilder moveToFooter(float percentX, float percentY) {
/**
* Move para o topo da área de conteúdo.
+ *
* @return this para chamadas encadeadas
*/
public PDFBuilder moveToTop() {
@@ -208,6 +218,7 @@ public PDFBuilder moveToTop() {
/**
* Move para o início da linha atual.
+ *
* @return this para chamadas encadeadas
*/
public PDFBuilder moveToStart() {
@@ -219,6 +230,7 @@ public PDFBuilder moveToStart() {
/**
* Move para o final da área de conteúdo.
+ *
* @return this para chamadas encadeadas
*/
public PDFBuilder moveToBottom() {
@@ -230,6 +242,7 @@ public PDFBuilder moveToBottom() {
/**
* Move para a direita a partir da posição atual.
+ *
* @param distance Distância a mover em pontos
* @return this para chamadas encadeadas
*/
@@ -240,6 +253,7 @@ public PDFBuilder moveRight(float distance) {
/**
* Move para baixo a partir da posição atual.
+ *
* @param distance Distância a mover em pontos
* @return this para chamadas encadeadas
*/
@@ -250,6 +264,7 @@ public PDFBuilder moveDown(float distance) {
/**
* Adiciona texto na posição atual.
+ *
* @param text Texto a ser adicionado
* @return this para chamadas encadeadas
*/
@@ -262,7 +277,7 @@ public PDFBuilder addText(String text) {
contentStream.showText(text);
contentStream.endText();
- logger.debug("Texto adicionado: {}", text);
+ LOGGER.debug("Texto adicionado: {}", text);
return this;
} catch (IOException e) {
throw new RuntimeException("Erro ao adicionar texto", e);
@@ -271,6 +286,7 @@ public PDFBuilder addText(String text) {
/**
* Adiciona uma linha de texto e move para a próxima linha.
+ *
* @param text Texto a ser adicionado
* @return this para chamadas encadeadas
*/
@@ -288,7 +304,7 @@ public PDFBuilder addLine(String text) {
moveDown(lineHeight);
moveToStart();
- logger.debug("Linha de texto adicionada: {}", text);
+ LOGGER.debug("Linha de texto adicionada: {}", text);
return this;
} catch (IOException e) {
throw new RuntimeException("Erro ao adicionar linha de texto", e);
@@ -297,6 +313,7 @@ public PDFBuilder addLine(String text) {
/**
* Adiciona um componente de texto simples.
+ *
* @param simpleText Componente de texto
* @return this para chamadas encadeadas
*/
@@ -306,7 +323,7 @@ public PDFBuilder addSimpleText(SimpleText simpleText) {
float safeWidth = contentArea.getWidth();
float newY = simpleText.render(contentStream, currentPosition.getX(), currentPosition.getY(), safeWidth);
currentPosition = currentPosition.moveTo(currentPosition.getX(), newY);
- logger.debug("SimpleText adicionado com quebra de linha automática");
+ LOGGER.debug("SimpleText adicionado com quebra de linha automática");
return this;
} catch (IOException e) {
throw new RuntimeException("Erro ao adicionar SimpleText", e);
@@ -315,6 +332,7 @@ public PDFBuilder addSimpleText(SimpleText simpleText) {
/**
* Adiciona um parágrafo com alinhamento.
+ *
* @param paragraph Componente de parágrafo
* @return this para chamadas encadeadas
*/
@@ -324,7 +342,7 @@ public PDFBuilder addParagraph(Paragraph paragraph) {
float safeWidth = contentArea.getWidth();
float newY = paragraph.render(contentStream, currentPosition.getX(), currentPosition.getY(), safeWidth);
currentPosition = currentPosition.moveTo(currentPosition.getX(), newY);
- logger.debug("Parágrafo adicionado com alinhamento");
+ LOGGER.debug("Parágrafo adicionado com alinhamento");
return this;
} catch (IOException e) {
throw new RuntimeException("Erro ao adicionar parágrafo", e);
@@ -333,6 +351,7 @@ public PDFBuilder addParagraph(Paragraph paragraph) {
/**
* Adiciona um título ao documento.
+ *
* @param heading Componente de título
* @return this para chamadas encadeadas
*/
@@ -342,7 +361,7 @@ public PDFBuilder addHeading(Heading heading) {
float safeWidth = contentArea.getWidth();
float newY = heading.render(contentStream, currentPosition.getX(), currentPosition.getY(), safeWidth);
currentPosition = currentPosition.moveTo(currentPosition.getX(), newY);
- logger.debug("Título adicionado ao documento");
+ LOGGER.debug("Título adicionado ao documento");
return this;
} catch (IOException e) {
throw new RuntimeException("Erro ao adicionar título", e);
@@ -351,42 +370,44 @@ public PDFBuilder addHeading(Heading heading) {
/**
* Verifica se é necessário criar uma nova página baseado na altura necessária.
+ *
* @param heightNeeded Altura necessária para o próximo elemento
*/
private void checkNewPage(float heightNeeded) throws IOException {
PDRectangle contentArea = config.getSafeArea().getContentArea(config.getPageSize());
float bottomLimit = contentArea.getLowerLeftY();
-
+
if (currentPosition.getY() - heightNeeded < bottomLimit) {
// Fecha o content stream atual
if (contentStream != null) {
addFooter();
contentStream.close();
}
-
+
// Cria nova página
PDPage newPage = new PDPage(config.getPageSize());
document.addPage(newPage);
-
+
// Cria novo content stream
contentStream = new PDPageContentStream(document, newPage);
-
+
// Reseta a posição para o topo da nova página usando Coordinates.origin
currentPosition = Coordinates.origin(config.getPageSize(), config.getSafeArea())
- .moveTo(
- contentArea.getLowerLeftX(),
- contentArea.getUpperRightY()
- );
-
+ .moveTo(
+ contentArea.getLowerLeftX(),
+ contentArea.getUpperRightY()
+ );
+
// Adiciona cabeçalho à nova página
addHeader();
-
- logger.debug("Nova página criada");
+
+ LOGGER.debug("Nova página criada");
}
}
/**
* Adiciona uma imagem ao documento.
+ *
* @param image Componente de imagem
* @return this para chamadas encadeadas
*/
@@ -398,18 +419,18 @@ public PDFBuilder addImage(Image image) {
float aspectRatio = dimensions.height / (float) dimensions.width;
float imageWidth = Math.min(safeWidth, dimensions.width);
float imageHeight = imageWidth * aspectRatio;
-
+
// Verifica se precisa de nova página
checkNewPage(imageHeight);
-
+
// Renderiza a imagem e atualiza a posição Y
float newY = image.render(contentStream, currentPosition.getX(), currentPosition.getY(), safeWidth, imageWidth);
currentPosition = currentPosition.moveTo(currentPosition.getX(), newY);
-
+
// Adiciona espaço após a imagem
moveDown(20); // 20 pontos de espaço após cada imagem
-
- logger.debug("Imagem adicionada com dimensões: {}x{}", imageWidth, imageHeight);
+
+ LOGGER.debug("Imagem adicionada com dimensões: {}x{}", imageWidth, imageHeight);
return this;
} catch (IOException e) {
throw new RuntimeException("Erro ao adicionar imagem", e);
@@ -418,6 +439,7 @@ public PDFBuilder addImage(Image image) {
/**
* Adiciona uma tabela ao documento.
+ *
* @param table Componente de tabela
* @return this para chamadas encadeadas
*/
@@ -427,11 +449,11 @@ public PDFBuilder addTable(Table table) {
float safeWidth = contentArea.getWidth();
float newY = table.render(contentStream, currentPosition.getX(), currentPosition.getY(), safeWidth);
currentPosition = currentPosition.moveTo(currentPosition.getX(), newY);
-
+
// Adiciona espaço após a tabela
moveDown(20); // 20 pontos de espaço após a tabela
-
- logger.debug("Tabela adicionada ao documento");
+
+ LOGGER.debug("Tabela adicionada ao documento");
return this;
} catch (IOException e) {
throw new RuntimeException("Erro ao adicionar tabela", e);
@@ -440,6 +462,7 @@ public PDFBuilder addTable(Table table) {
/**
* Adiciona uma lista ao documento.
+ *
* @param list Componente de lista
* @return this para chamadas encadeadas
*/
@@ -449,11 +472,11 @@ public PDFBuilder addList(List list) {
float safeWidth = contentArea.getWidth();
float newY = list.render(contentStream, currentPosition.getX(), currentPosition.getY(), safeWidth);
currentPosition = currentPosition.moveTo(currentPosition.getX(), newY);
-
+
// Adiciona espaço após a lista
moveDown(20); // 20 pontos de espaço após a lista
-
- logger.debug("Lista adicionada ao documento");
+
+ LOGGER.debug("Lista adicionada ao documento");
return this;
} catch (IOException e) {
throw new RuntimeException("Erro ao adicionar lista", e);
@@ -462,6 +485,7 @@ public PDFBuilder addList(List list) {
/**
* Define o tamanho da fonte.
+ *
* @param fontSize Tamanho da fonte em pontos
* @return this para chamadas encadeadas
*/
@@ -475,6 +499,7 @@ public PDFBuilder setFontSize(float fontSize) {
/**
* Define o espaçamento entre linhas.
+ *
* @param spacing Fator de espaçamento (1.0 = espaçamento simples)
* @return this para chamadas encadeadas
*/
@@ -488,6 +513,7 @@ public PDFBuilder setLineSpacing(float spacing) {
/**
* Atualiza a configuração do builder.
+ *
* @param config Nova configuração
* @return this para chamadas encadeadas
*/
@@ -500,6 +526,7 @@ public PDFBuilder withConfiguration(PDFConfiguration config) {
/**
* Atualiza o tamanho da página.
+ *
* @param pageSize Novo tamanho de página
* @return this para chamadas encadeadas
*/
@@ -513,6 +540,7 @@ public PDFBuilder withPageSize(PDRectangle pageSize) {
/**
* Define a numeração de páginas.
+ *
* @param pageNumbering Configuração de numeração de páginas
* @return this para chamadas encadeadas
*/
@@ -523,6 +551,7 @@ public PDFBuilder setPageNumbering(PageNumbering pageNumbering) {
/**
* Define o cabeçalho do documento.
+ *
* @param header Configuração do cabeçalho
* @return this para chamadas encadeadas
*/
@@ -541,6 +570,7 @@ public PDFBuilder setHeader(PageSection header) {
/**
* Define o rodapé do documento.
+ *
* @param footer Configuração do rodapé
* @return this para chamadas encadeadas
*/
@@ -551,13 +581,14 @@ public PDFBuilder setFooter(PageSection footer) {
/**
* Define o logo do documento usando apenas um título.
+ *
* @param title Título do logo
* @return this para chamadas encadeadas
*/
public PDFBuilder setLogo(String title) {
this.logo = Logo.builder()
- .withTitle(title)
- .build();
+ .withTitle(title)
+ .build();
try {
addLogo();
} catch (IOException e) {
@@ -568,15 +599,16 @@ public PDFBuilder setLogo(String title) {
/**
* Define o logo do documento com título e estilo personalizado.
+ *
* @param title Título do logo
* @param style Estilo do logo
* @return this para chamadas encadeadas
*/
public PDFBuilder setLogo(String title, LogoStyle style) {
this.logo = Logo.builder()
- .withTitle(title)
- .withStyle(style)
- .build();
+ .withTitle(title)
+ .withStyle(style)
+ .build();
try {
addLogo();
} catch (IOException e) {
@@ -587,9 +619,10 @@ public PDFBuilder setLogo(String title, LogoStyle style) {
/**
* Define o logo do documento com imagens nas laterais.
- * @param title Título do logo
- * @param style Estilo do logo
- * @param leftImagePath Caminho da imagem da esquerda
+ *
+ * @param title Título do logo
+ * @param style Estilo do logo
+ * @param leftImagePath Caminho da imagem da esquerda
* @param rightImagePath Caminho da imagem da direita
* @return this para chamadas encadeadas
*/
@@ -605,19 +638,19 @@ public PDFBuilder setLogo(String title, LogoStyle style, String leftImagePath, S
}
this.logo = Logo.builder()
- .withTitle(title)
- .withStyle(style)
- .withLeftImage(leftImage)
- .withRightImage(rightImage)
- .build();
+ .withTitle(title)
+ .withStyle(style)
+ .withLeftImage(leftImage)
+ .withRightImage(rightImage)
+ .build();
try {
// Reseta a posição e adiciona o logo
currentPosition = Coordinates.origin(config.getPageSize(), config.getSafeArea())
- .moveTo(
- config.getSafeArea().getMarginLeft(),
- config.getPageSize().getHeight() - config.getSafeArea().getMarginTop()
- );
+ .moveTo(
+ config.getSafeArea().getMarginLeft(),
+ config.getPageSize().getHeight() - config.getSafeArea().getMarginTop()
+ );
addLogo();
} catch (IOException e) {
throw new RuntimeException("Erro ao adicionar logo", e);
@@ -644,13 +677,13 @@ private void addFooter() throws IOException {
float footerY = config.getSafeArea().getMarginBottom();
footer.render(contentStream, config.getPageSize().getWidth(), footerY,
config.getSafeArea().getMarginLeft(), config.getSafeArea().getMarginRight());
-
+
// Adiciona numeração de página se configurada
if (pageNumbering != null) {
int pageNumber = document.getPages().indexOf(currentPage) + 1;
int totalPages = document.getNumberOfPages();
- pageNumbering.render(contentStream, config.getPageSize().getWidth(),
- config.getPageSize().getHeight(), pageNumber, totalPages);
+ pageNumbering.render(contentStream, config.getPageSize().getWidth(),
+ config.getPageSize().getHeight(), pageNumber, totalPages);
}
}
}
@@ -661,11 +694,11 @@ private void addFooter() throws IOException {
private void addLogo() throws IOException {
if (logo != null) {
float y = currentPosition.getY();
-
+
// Renderiza o logo
logo.render(contentStream, config.getPageSize().getWidth(), y,
config.getSafeArea().getMarginLeft(), config.getSafeArea().getMarginRight());
-
+
// Atualiza a posição atual para logo abaixo do logo
float logoHeight = logo.getTotalHeight();
currentPosition = currentPosition.moveBy(0, -logoHeight);
@@ -674,6 +707,7 @@ private void addLogo() throws IOException {
/**
* Salva o documento no caminho especificado.
+ *
* @param path Caminho para salvar o documento
*/
public void save(String path) {
@@ -685,7 +719,7 @@ public void save(String path) {
contentStream = null;
}
document.save(path);
- logger.debug("Documento salvo em: {}", path);
+ LOGGER.debug("Documento salvo em: {}", path);
} catch (IOException e) {
throw new RuntimeException("Erro ao salvar documento", e);
}
@@ -702,7 +736,7 @@ public void close() {
contentStream = null;
}
document.close();
- logger.debug("Builder fechado e recursos liberados");
+ LOGGER.debug("Builder fechado e recursos liberados");
} catch (IOException e) {
throw new RuntimeException("Erro ao fechar recursos", e);
}
@@ -710,6 +744,7 @@ public void close() {
/**
* Retorna o gerenciador de recursos do documento.
+ *
* @return Gerenciador de recursos
*/
public ResourceManager getResourceManager() {
@@ -717,8 +752,19 @@ public ResourceManager getResourceManager() {
}
// Getters
- public PDDocument getDocument() { return document; }
- public PDFConfiguration getConfig() { return config; }
- public PDPage getCurrentPage() { return currentPage; }
- public Coordinates getCurrentPosition() { return currentPosition; }
+ public PDDocument getDocument() {
+ return document;
+ }
+
+ public PDFConfiguration getConfig() {
+ return config;
+ }
+
+ public PDPage getCurrentPage() {
+ return currentPage;
+ }
+
+ public Coordinates getCurrentPosition() {
+ return currentPosition;
+ }
}
diff --git a/src/main/java/io/github/joabsonlg/pdfbuilder/core/PDFConfiguration.java b/src/main/java/io/github/joabsonlg/pdfbuilder/core/PDFConfiguration.java
index 1f39469..5f032f4 100644
--- a/src/main/java/io/github/joabsonlg/pdfbuilder/core/PDFConfiguration.java
+++ b/src/main/java/io/github/joabsonlg/pdfbuilder/core/PDFConfiguration.java
@@ -8,8 +8,8 @@
* Configurações globais para documentos PDF.
* Esta classe usa o padrão Builder para uma configuração fluente.
*/
-public class PDFConfiguration {
- private static final Logger logger = LoggerFactory.getLogger(PDFConfiguration.class);
+public final class PDFConfiguration {
+ private static final Logger LOGGER = LoggerFactory.getLogger(PDFConfiguration.class);
// Valores padrão
private static final PDRectangle DEFAULT_PAGE_SIZE = PDRectangle.A4;
@@ -40,21 +40,23 @@ private PDFConfiguration(Builder builder) {
this.lineSpacing = builder.lineSpacing;
this.safeArea = builder.safeArea;
- logger.debug("PDFConfiguration criada com: pageSize={}, dpi={}, fontSize={}, lineSpacing={}",
- pageSize, dpi, fontSize, lineSpacing);
+ LOGGER.debug("PDFConfiguration criada com: pageSize={}, dpi={}, fontSize={}, lineSpacing={}",
+ pageSize, dpi, fontSize, lineSpacing);
}
/**
* Cria uma nova instância de PDFConfiguration com valores padrão.
+ *
* @return Nova instância de PDFConfiguration
*/
public static Builder create() {
- logger.debug("Criando nova configuração PDF com valores padrão");
+ LOGGER.debug("Criando nova configuração PDF com valores padrão");
return new Builder();
}
/**
* Define o tamanho padrão da página.
+ *
* @param pageSize Tamanho da página (ex: PDRectangle.A4)
* @return Nova instância de PDFConfiguration
* @throws IllegalArgumentException se pageSize for nulo
@@ -70,6 +72,7 @@ public PDFConfiguration withPageSize(PDRectangle pageSize) {
/**
* Define a resolução DPI para imagens.
+ *
* @param dpi Valor DPI (dots per inch)
* @return Nova instância de PDFConfiguration
* @throws IllegalArgumentException se dpi for menor ou igual a zero
@@ -85,6 +88,7 @@ public PDFConfiguration withDPI(int dpi) {
/**
* Define a qualidade de compressão para imagens.
+ *
* @param quality Valor entre 0.0 e 1.0
* @return Nova instância de PDFConfiguration
* @throws IllegalArgumentException se o valor estiver fora do intervalo [0,1]
@@ -100,6 +104,7 @@ public PDFConfiguration withCompressionQuality(float quality) {
/**
* Define o tamanho da fonte.
+ *
* @param fontSize Tamanho da fonte em pontos
* @return Nova instância de PDFConfiguration
* @throws IllegalArgumentException se fontSize for menor ou igual a zero
@@ -115,6 +120,7 @@ public PDFConfiguration withFontSize(float fontSize) {
/**
* Define o espaçamento entre linhas.
+ *
* @param lineSpacing Espaçamento em pontos
* @return Nova instância de PDFConfiguration
* @throws IllegalArgumentException se lineSpacing for menor ou igual a zero
@@ -130,6 +136,7 @@ public PDFConfiguration withLineSpacing(float lineSpacing) {
/**
* Define a área segura.
+ *
* @param safeArea Área segura
* @return Nova instância de PDFConfiguration
* @throws IllegalArgumentException se safeArea for nulo
@@ -169,13 +176,25 @@ public float getLineSpacing() {
}
// Métodos de conveniência para acessar margens
- public float getMarginLeft() { return safeArea.getMarginLeft(); }
- public float getMarginRight() { return safeArea.getMarginRight(); }
- public float getMarginTop() { return safeArea.getMarginTop(); }
- public float getMarginBottom() { return safeArea.getMarginBottom(); }
+ public float getMarginLeft() {
+ return safeArea.getMarginLeft();
+ }
+
+ public float getMarginRight() {
+ return safeArea.getMarginRight();
+ }
+
+ public float getMarginTop() {
+ return safeArea.getMarginTop();
+ }
+
+ public float getMarginBottom() {
+ return safeArea.getMarginBottom();
+ }
/**
* Calcula a área útil da página (área dentro das margens).
+ *
* @return PDRectangle representando a área útil
*/
public PDRectangle getContentArea() {
@@ -192,7 +211,8 @@ public static class Builder {
private float fontSize = DEFAULT_FONT_SIZE;
private float lineSpacing = DEFAULT_LINE_SPACING;
- public Builder() {}
+ public Builder() {
+ }
public Builder(PDFConfiguration pdfConfiguration) {
this.pageSize = pdfConfiguration.pageSize;
diff --git a/src/main/java/io/github/joabsonlg/pdfbuilder/core/ResourceManager.java b/src/main/java/io/github/joabsonlg/pdfbuilder/core/ResourceManager.java
index dc87197..d7253fb 100644
--- a/src/main/java/io/github/joabsonlg/pdfbuilder/core/ResourceManager.java
+++ b/src/main/java/io/github/joabsonlg/pdfbuilder/core/ResourceManager.java
@@ -20,7 +20,7 @@
* Responsável por carregar e gerenciar fontes e imagens.
*/
public class ResourceManager {
- private static final Logger logger = LoggerFactory.getLogger(ResourceManager.class);
+ private static final Logger LOGGER = LoggerFactory.getLogger(ResourceManager.class);
private final PDDocument document;
private final Map fonts;
@@ -37,7 +37,7 @@ public ResourceManager(PDDocument document) {
this.images = new HashMap<>();
this.defaultFont = new PDType1Font(Standard14Fonts.FontName.HELVETICA);
registerStandardFonts();
- logger.debug("ResourceManager inicializado");
+ LOGGER.debug("ResourceManager inicializado");
}
/**
@@ -57,7 +57,7 @@ private void registerStandardFonts() {
fonts.put("Courier-Oblique", new PDType1Font(Standard14Fonts.FontName.COURIER_OBLIQUE));
fonts.put("Courier-BoldOblique", new PDType1Font(Standard14Fonts.FontName.COURIER_BOLD_OBLIQUE));
- logger.debug("Fontes padrão registradas");
+ LOGGER.debug("Fontes padrão registradas");
}
/**
@@ -71,7 +71,7 @@ public void setDefaultFont(String fontName) {
throw new IllegalArgumentException("Fonte não registrada: " + fontName);
}
this.defaultFont = font;
- logger.debug("Fonte padrão definida para: {}", fontName);
+ LOGGER.debug("Fonte padrão definida para: {}", fontName);
}
/**
@@ -101,9 +101,9 @@ public void loadImage(String name, Path imagePath) throws IOException {
try {
PDImageXObject image = PDImageXObject.createFromFile(imagePath.toString(), document);
images.put(name, image);
- logger.debug("Imagem carregada: {} de {}", name, imagePath);
+ LOGGER.debug("Imagem carregada: {} de {}", name, imagePath);
} catch (IOException e) {
- logger.error("Erro ao carregar imagem {}: {}", imagePath, e.getMessage());
+ LOGGER.error("Erro ao carregar imagem {}: {}", imagePath, e.getMessage());
throw e;
}
}
@@ -118,9 +118,9 @@ public void loadImage(String name, InputStream inputStream) throws IOException {
try {
PDImageXObject image = PDImageXObject.createFromByteArray(document, inputStream.readAllBytes(), name);
images.put(name, image);
- logger.debug("Imagem carregada: {} do InputStream", name);
+ LOGGER.debug("Imagem carregada: {} do InputStream", name);
} catch (IOException e) {
- logger.error("Erro ao carregar imagem do InputStream: {}", e.getMessage());
+ LOGGER.error("Erro ao carregar imagem do InputStream: {}", e.getMessage());
throw e;
}
}
@@ -142,7 +142,7 @@ public PDImageXObject getImage(String name) {
public boolean removeImage(String name) {
PDImageXObject removed = images.remove(name);
if (removed != null) {
- logger.debug("Imagem removida: {}", name);
+ LOGGER.debug("Imagem removida: {}", name);
return true;
}
return false;
diff --git a/src/main/java/io/github/joabsonlg/pdfbuilder/core/SafeArea.java b/src/main/java/io/github/joabsonlg/pdfbuilder/core/SafeArea.java
index d91965c..30d0aa1 100644
--- a/src/main/java/io/github/joabsonlg/pdfbuilder/core/SafeArea.java
+++ b/src/main/java/io/github/joabsonlg/pdfbuilder/core/SafeArea.java
@@ -5,10 +5,10 @@
/**
* Define a área segura para renderização de conteúdo no PDF.
*/
-public class SafeArea {
+public final class SafeArea {
private static final float HEADER_HEIGHT = 40f;
private static final float FOOTER_HEIGHT = 40f;
-
+
private final float originalMarginLeft;
private final float originalMarginRight;
private final float originalMarginTop;
@@ -35,6 +35,7 @@ private SafeArea(Builder builder) {
/**
* Retorna a área de conteúdo segura considerando as margens e áreas de cabeçalho/rodapé.
+ *
* @param pageSize Tamanho da página
* @return Retângulo representando a área segura
*/
@@ -42,20 +43,21 @@ public PDRectangle getContentArea(PDRectangle pageSize) {
if (pageSize == null) {
throw new IllegalArgumentException("pageSize não pode ser nulo");
}
-
+
float extraTopMargin = hasHeader ? HEADER_HEIGHT : 0;
float extraBottomMargin = hasFooter ? FOOTER_HEIGHT : 0;
-
+
return new PDRectangle(
- marginLeft,
- marginBottom + extraBottomMargin,
- pageSize.getWidth() - marginLeft - marginRight,
- pageSize.getHeight() - marginTop - marginBottom - extraTopMargin - extraBottomMargin
+ marginLeft,
+ marginBottom + extraBottomMargin,
+ pageSize.getWidth() - marginLeft - marginRight,
+ pageSize.getHeight() - marginTop - marginBottom - extraTopMargin - extraBottomMargin
);
}
/**
* Retorna a área do cabeçalho.
+ *
* @param pageSize Tamanho da página
* @return Retângulo representando a área do cabeçalho
* @throws IllegalStateException se o cabeçalho não estiver habilitado
@@ -67,17 +69,18 @@ public PDRectangle getHeaderArea(PDRectangle pageSize) {
if (!hasHeader) {
throw new IllegalStateException("Cabeçalho não está habilitado");
}
-
+
return new PDRectangle(
- marginLeft,
- pageSize.getHeight() - marginTop - HEADER_HEIGHT,
- pageSize.getWidth() - marginLeft - marginRight,
- HEADER_HEIGHT
+ marginLeft,
+ pageSize.getHeight() - marginTop - HEADER_HEIGHT,
+ pageSize.getWidth() - marginLeft - marginRight,
+ HEADER_HEIGHT
);
}
/**
* Retorna a área do rodapé.
+ *
* @param pageSize Tamanho da página
* @return Retângulo representando a área do rodapé
* @throws IllegalStateException se o rodapé não estiver habilitado
@@ -89,28 +92,29 @@ public PDRectangle getFooterArea(PDRectangle pageSize) {
if (!hasFooter) {
throw new IllegalStateException("Rodapé não está habilitado");
}
-
+
return new PDRectangle(
- marginLeft,
- marginBottom,
- pageSize.getWidth() - marginLeft - marginRight,
- FOOTER_HEIGHT
+ marginLeft,
+ marginBottom,
+ pageSize.getWidth() - marginLeft - marginRight,
+ FOOTER_HEIGHT
);
}
/**
* Verifica se um ponto está dentro da área segura.
- * @param x Coordenada X do ponto
- * @param y Coordenada Y do ponto
+ *
+ * @param x Coordenada X do ponto
+ * @param y Coordenada Y do ponto
* @param pageSize Tamanho da página
* @return true se o ponto estiver dentro da área segura
*/
public boolean isPointInSafeArea(float x, float y, PDRectangle pageSize) {
PDRectangle contentArea = getContentArea(pageSize);
- return x >= contentArea.getLowerLeftX() &&
- x <= contentArea.getUpperRightX() &&
- y >= contentArea.getLowerLeftY() &&
- y <= contentArea.getUpperRightY();
+ return x >= contentArea.getLowerLeftX() &&
+ x <= contentArea.getUpperRightX() &&
+ y >= contentArea.getLowerLeftY() &&
+ y <= contentArea.getUpperRightY();
}
public void reset() {
@@ -152,10 +156,21 @@ public void setMarginLeft(float marginLeft) {
this.marginLeft = marginLeft;
}
- public boolean hasHeader() { return hasHeader; }
- public boolean hasFooter() { return hasFooter; }
- public float getHeaderHeight() { return HEADER_HEIGHT; }
- public float getFooterHeight() { return FOOTER_HEIGHT; }
+ public boolean hasHeader() {
+ return hasHeader;
+ }
+
+ public boolean hasFooter() {
+ return hasFooter;
+ }
+
+ public float getHeaderHeight() {
+ return HEADER_HEIGHT;
+ }
+
+ public float getFooterHeight() {
+ return FOOTER_HEIGHT;
+ }
public static Builder builder() {
return new Builder();
diff --git a/src/main/java/io/github/joabsonlg/pdfbuilder/examples/CompleteExample.java b/src/main/java/io/github/joabsonlg/pdfbuilder/examples/CompleteExample.java
index 57f1e5e..721d95a 100644
--- a/src/main/java/io/github/joabsonlg/pdfbuilder/examples/CompleteExample.java
+++ b/src/main/java/io/github/joabsonlg/pdfbuilder/examples/CompleteExample.java
@@ -5,25 +5,29 @@
import io.github.joabsonlg.pdfbuilder.components.logo.LogoStyle;
import io.github.joabsonlg.pdfbuilder.components.page.PageNumbering;
import io.github.joabsonlg.pdfbuilder.components.page.PageSectionStyle;
+import io.github.joabsonlg.pdfbuilder.components.table.Table;
import io.github.joabsonlg.pdfbuilder.components.text.Heading;
import io.github.joabsonlg.pdfbuilder.components.text.HeadingLevel;
import io.github.joabsonlg.pdfbuilder.components.text.Paragraph;
import io.github.joabsonlg.pdfbuilder.components.text.TextAlignment;
import io.github.joabsonlg.pdfbuilder.components.text.TextStyle;
-import io.github.joabsonlg.pdfbuilder.components.table.Table;
import io.github.joabsonlg.pdfbuilder.core.PDFBuilder;
import io.github.joabsonlg.pdfbuilder.core.PDFConfiguration;
import io.github.joabsonlg.pdfbuilder.core.SafeArea;
-
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.font.PDType1Font;
import org.apache.pdfbox.pdmodel.font.Standard14Fonts;
-import java.awt.Color;
+import java.awt.*;
import java.io.File;
import java.util.ArrayList;
-public class CompleteExample {
+public final class CompleteExample {
+
+ private CompleteExample() {
+ throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
+ }
+
public static void main(String[] args) {
try {
// Configuração da área segura com header e footer
@@ -111,19 +115,19 @@ public static void main(String[] args) {
// Adiciona texto introdutório
builder.addParagraph(Paragraph.builder()
- .addStyledText("Este é um exemplo completo que demonstra todas as funcionalidades do ",
+ .addStyledText("Este é um exemplo completo que demonstra todas as funcionalidades do ",
TextStyle.builder()
- .withFont(defaultFont)
- .withFontSize(12f)
- .withColor(Color.BLACK)
- .build())
+ .withFont(defaultFont)
+ .withFontSize(12f)
+ .withColor(Color.BLACK)
+ .build())
.addStyledText("PDF Builder", boldStyle)
- .addStyledText(". Abaixo você verá exemplos de cabeçalhos, rodapés, listas, tabelas e imagens.",
+ .addStyledText(". Abaixo você verá exemplos de cabeçalhos, rodapés, listas, tabelas e imagens.",
TextStyle.builder()
- .withFont(defaultFont)
- .withFontSize(12f)
- .withColor(Color.BLACK)
- .build())
+ .withFont(defaultFont)
+ .withFontSize(12f)
+ .withColor(Color.BLACK)
+ .build())
.build());
builder.moveDown(20);
@@ -141,13 +145,13 @@ public static void main(String[] args) {
// Cria uma lista com itens estilizados
java.util.List items = new ArrayList<>();
-
+
ListItem item1 = new ListItem("Recursos do PDF Builder:", defaultFont, 12, Color.BLACK);
item1.addSubItem(new ListItem("Cabeçalhos e Rodapés personalizados", defaultFont, 12, Color.BLACK));
item1.addSubItem(new ListItem("Numeração automática de páginas", defaultFont, 12, Color.BLACK));
item1.addSubItem(new ListItem("Suporte a imagens com legendas", defaultFont, 12, Color.BLACK));
items.add(item1);
-
+
ListItem item2 = new ListItem("Formatação de Texto:", defaultFont, 12, Color.BLACK);
item2.addSubItem(new ListItem("Diferentes estilos e cores", defaultFont, 12, Color.BLACK));
item2.addSubItem(new ListItem("Alinhamento personalizado", defaultFont, 12, Color.BLACK));
diff --git a/src/main/java/io/github/joabsonlg/pdfbuilder/examples/HeaderFooterDemo.java b/src/main/java/io/github/joabsonlg/pdfbuilder/examples/HeaderFooterDemo.java
index 6a179e3..2f5d738 100644
--- a/src/main/java/io/github/joabsonlg/pdfbuilder/examples/HeaderFooterDemo.java
+++ b/src/main/java/io/github/joabsonlg/pdfbuilder/examples/HeaderFooterDemo.java
@@ -17,7 +17,12 @@
import java.awt.Color;
-public class HeaderFooterDemo {
+public final class HeaderFooterDemo {
+
+ private HeaderFooterDemo() {
+ throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
+ }
+
public static void main(String[] args) {
try {
// Configuração da área segura com header e footer
diff --git a/src/main/java/io/github/joabsonlg/pdfbuilder/examples/HeadingDemo.java b/src/main/java/io/github/joabsonlg/pdfbuilder/examples/HeadingDemo.java
index 04b5b25..17e03d6 100644
--- a/src/main/java/io/github/joabsonlg/pdfbuilder/examples/HeadingDemo.java
+++ b/src/main/java/io/github/joabsonlg/pdfbuilder/examples/HeadingDemo.java
@@ -15,8 +15,13 @@
/**
* Demonstração do uso de títulos e subtítulos.
*/
-public class HeadingDemo {
- private static final Logger logger = LoggerFactory.getLogger(HeadingDemo.class);
+public final class HeadingDemo {
+
+ private HeadingDemo() {
+ throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
+ }
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(HeadingDemo.class);
public static void main(String[] args) {
try {
@@ -84,7 +89,7 @@ public static void main(String[] args) {
.addStyledText("Lorem ipsum dolor sit amet, consectetur adipiscing elit. " +
"Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. " +
"Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris " +
- "nisi ut aliquip ex ea commodo consequat.",
+ "nisi ut aliquip ex ea commodo consequat.",
TextStyle.builder()
.withFont(new PDType1Font(Standard14Fonts.FontName.HELVETICA))
.withFontSize(12f)
@@ -101,10 +106,10 @@ public static void main(String[] args) {
.addParagraph(text);
builder.save("demo_titulos.pdf");
- logger.info("PDF gerado com sucesso: demo_titulos.pdf");
+ LOGGER.info("PDF gerado com sucesso: demo_titulos.pdf");
} catch (Exception e) {
- logger.error("Erro ao gerar o PDF: {}", e.getMessage(), e);
+ LOGGER.error("Erro ao gerar o PDF: {}", e.getMessage(), e);
}
}
}
diff --git a/src/main/java/io/github/joabsonlg/pdfbuilder/examples/ImageDemo.java b/src/main/java/io/github/joabsonlg/pdfbuilder/examples/ImageDemo.java
index dd135fb..8f9c03f 100644
--- a/src/main/java/io/github/joabsonlg/pdfbuilder/examples/ImageDemo.java
+++ b/src/main/java/io/github/joabsonlg/pdfbuilder/examples/ImageDemo.java
@@ -19,8 +19,13 @@
/**
* Demonstração do uso de imagens no PDF Builder.
*/
-public class ImageDemo {
- private static final Logger logger = LoggerFactory.getLogger(ImageDemo.class);
+public final class ImageDemo {
+
+ private ImageDemo() {
+ throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
+ }
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(ImageDemo.class);
public static void main(String[] args) {
try {
@@ -63,7 +68,8 @@ public static void main(String[] args) {
.build();
// Carrega e adiciona imagens
- File imageFile = new File("C:\\Users\\joabs\\Documents\\Projetos\\MeusProjetos\\pdf-builder-workspace\\pdf-builder\\src\\main\\java\\br\\com\\nutit\\pdfbuilder\\examples\\sample-image.jpg");
+ File imageFile = new File("C:\\Users\\joabs\\Documents\\Projetos\\MeusProjetos\\pdf-builder-workspace" +
+ "\\pdf-builder\\src\\main\\java\\br\\com\\nutit\\pdfbuilder\\examples\\sample-image.jpg");
// Imagem original
Image originalImage = Image.builder(builder.getDocument(), imageFile)
@@ -109,10 +115,10 @@ public static void main(String[] args) {
.build());
builder.save("demo_imagens.pdf");
- logger.info("PDF gerado com sucesso: demo_imagens.pdf");
+ LOGGER.info("PDF gerado com sucesso: demo_imagens.pdf");
} catch (Exception e) {
- logger.error("Erro ao gerar o PDF: {}", e.getMessage(), e);
+ LOGGER.error("Erro ao gerar o PDF: {}", e.getMessage(), e);
}
}
}
diff --git a/src/main/java/io/github/joabsonlg/pdfbuilder/examples/ListDemo.java b/src/main/java/io/github/joabsonlg/pdfbuilder/examples/ListDemo.java
index 2df377a..ddc2a41 100644
--- a/src/main/java/io/github/joabsonlg/pdfbuilder/examples/ListDemo.java
+++ b/src/main/java/io/github/joabsonlg/pdfbuilder/examples/ListDemo.java
@@ -20,7 +20,12 @@
import java.util.ArrayList;
import java.util.Arrays;
-public class ListDemo {
+public final class ListDemo {
+
+ private ListDemo() {
+ throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
+ }
+
public static void main(String[] args) {
try {
// Configuração da área segura com header e footer
@@ -74,21 +79,21 @@ public static void main(String[] args) {
// Cria uma lista não ordenada com subitens
java.util.List items = new ArrayList<>();
-
+
// Item 1 com subitens
ListItem item1 = new ListItem("Frutas", defaultFont, 12, Color.BLACK);
item1.addSubItem(new ListItem("Maçã", defaultFont, 12, Color.BLACK));
item1.addSubItem(new ListItem("Banana", defaultFont, 12, Color.BLACK));
item1.addSubItem(new ListItem("Laranja", defaultFont, 12, Color.BLACK));
items.add(item1);
-
+
// Item 2 com subitens
ListItem item2 = new ListItem("Vegetais", defaultFont, 12, Color.BLACK);
item2.addSubItem(new ListItem("Cenoura", defaultFont, 12, Color.BLACK));
item2.addSubItem(new ListItem("Brócolis", defaultFont, 12, Color.BLACK));
item2.addSubItem(new ListItem("Alface", defaultFont, 12, Color.BLACK));
items.add(item2);
-
+
// Item 3 sem subitens
items.add(new ListItem("Grãos", defaultFont, 12, Color.BLACK));
@@ -119,62 +124,62 @@ public static void main(String[] args) {
// Cria uma lista ordenada com subitens
java.util.List orderedItems = new ArrayList<>();
-
+
// Item 1 com subitens numerados
ListItem step1 = new ListItem("Preparar a massa", defaultFont, 12, new Color(44, 62, 80));
step1.setNumber("1.");
-
- ListItem step1_1 = new ListItem("Misturar farinha e sal", defaultFont, 12, new Color(44, 62, 80));
- step1_1.setNumber("1.1.");
-
- ListItem step1_2 = new ListItem("Adicionar água aos poucos", defaultFont, 12, new Color(44, 62, 80));
- step1_2.setNumber("1.2.");
-
+
+ ListItem step1s1 = new ListItem("Misturar farinha e sal", defaultFont, 12, new Color(44, 62, 80));
+ step1s1.setNumber("1.1.");
+
+ ListItem step1s2 = new ListItem("Adicionar água aos poucos", defaultFont, 12, new Color(44, 62, 80));
+ step1s2.setNumber("1.2.");
+
// Item com texto estilizado
String text = "O entusiasmo é a maior força da ";
String highlightedWord = "alma";
String remainingText = ". Conserva-o e nunca te faltará poder para conseguires o que desejas.";
-
+
java.util.List styledTexts = Arrays.asList(
new StyledText(text, normalStyle),
new StyledText(highlightedWord, boldStyle),
new StyledText(remainingText, normalStyle)
);
-
- ListItem step1_3 = new ListItem(styledTexts);
- step1_3.setNumber("1.3.");
-
- step1.addSubItem(step1_1);
- step1.addSubItem(step1_2);
- step1.addSubItem(step1_3);
+
+ ListItem step1s3 = new ListItem(styledTexts);
+ step1s3.setNumber("1.3.");
+
+ step1.addSubItem(step1s1);
+ step1.addSubItem(step1s2);
+ step1.addSubItem(step1s3);
orderedItems.add(step1);
-
+
// Item 2 com subitens numerados
ListItem step2 = new ListItem("Preparar o recheio", defaultFont, 12, new Color(44, 62, 80));
step2.setNumber("2.");
-
- ListItem step2_1 = new ListItem("Cortar os ingredientes", defaultFont, 12, new Color(44, 62, 80));
- step2_1.setNumber("2.1.");
-
- ListItem step2_2 = new ListItem("Temperar a gosto", defaultFont, 12, new Color(44, 62, 80));
- step2_2.setNumber("2.2.");
-
- step2.addSubItem(step2_1);
- step2.addSubItem(step2_2);
+
+ ListItem step2s1 = new ListItem("Cortar os ingredientes", defaultFont, 12, new Color(44, 62, 80));
+ step2s1.setNumber("2.1.");
+
+ ListItem step2s2 = new ListItem("Temperar a gosto", defaultFont, 12, new Color(44, 62, 80));
+ step2s2.setNumber("2.2.");
+
+ step2.addSubItem(step2s1);
+ step2.addSubItem(step2s2);
orderedItems.add(step2);
-
+
// Item 3 com subitens numerados
ListItem step3 = new ListItem("Finalizar", defaultFont, 12, new Color(44, 62, 80));
step3.setNumber("3.");
-
- ListItem step3_1 = new ListItem("Montar a receita", defaultFont, 12, new Color(44, 62, 80));
- step3_1.setNumber("3.1.");
-
- ListItem step3_2 = new ListItem("Levar ao forno", defaultFont, 12, new Color(44, 62, 80));
- step3_2.setNumber("3.2.");
-
- step3.addSubItem(step3_1);
- step3.addSubItem(step3_2);
+
+ ListItem step3s1 = new ListItem("Montar a receita", defaultFont, 12, new Color(44, 62, 80));
+ step3s1.setNumber("3.1.");
+
+ ListItem step3s2 = new ListItem("Levar ao forno", defaultFont, 12, new Color(44, 62, 80));
+ step3s2.setNumber("3.2.");
+
+ step3.addSubItem(step3s1);
+ step3.addSubItem(step3s2);
orderedItems.add(step3);
List orderedList = List.builder()
diff --git a/src/main/java/io/github/joabsonlg/pdfbuilder/examples/PDFBuilderDemo.java b/src/main/java/io/github/joabsonlg/pdfbuilder/examples/PDFBuilderDemo.java
index 62ab15d..2ca2197 100644
--- a/src/main/java/io/github/joabsonlg/pdfbuilder/examples/PDFBuilderDemo.java
+++ b/src/main/java/io/github/joabsonlg/pdfbuilder/examples/PDFBuilderDemo.java
@@ -4,17 +4,21 @@
import io.github.joabsonlg.pdfbuilder.core.PDFBuilder;
import io.github.joabsonlg.pdfbuilder.core.PDFConfiguration;
import io.github.joabsonlg.pdfbuilder.core.SafeArea;
-
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.awt.Color;
+
+import java.awt.*;
/**
* Demonstração completa das funcionalidades implementadas no PDFBuilder.
*/
-public class PDFBuilderDemo {
- private static final Logger logger = LoggerFactory.getLogger(PDFBuilderDemo.class);
+public final class PDFBuilderDemo {
+ private static final Logger LOGGER = LoggerFactory.getLogger(PDFBuilderDemo.class);
+
+ private PDFBuilderDemo() {
+ throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
+ }
public static void main(String[] args) {
try {
@@ -29,61 +33,62 @@ public static void main(String[] args) {
PDFConfiguration config = PDFConfiguration.create()
.withPageSize(PDRectangle.A4)
.withSafeArea(safeArea)
- .withDPI(300)
- .withCompressionQuality(0.8f)
- .withFontSize(12f)
- .withLineSpacing(14f)
- .build();
+ .withDPI(300)
+ .withCompressionQuality(0.8f)
+ .withFontSize(12f)
+ .withLineSpacing(14f)
+ .build();
// 2. Criação do PDFBuilder
PDFBuilder builder = new PDFBuilder(config);
// 3. Demonstração de texto simples com formatação
SimpleText title = SimpleText.builder()
- .withText("Demonstração de Texto Simples")
- .withFont(builder.getResourceManager().getFont("Helvetica-Bold"))
- .withFontSize(24f)
- .withLineSpacing(1.5f)
- .withColor(new Color(0, 102, 204)) // Azul
- .build();
+ .withText("Demonstração de Texto Simples")
+ .withFont(builder.getResourceManager().getFont("Helvetica-Bold"))
+ .withFontSize(24f)
+ .withLineSpacing(1.5f)
+ .withColor(new Color(0, 102, 204)) // Azul
+ .build();
SimpleText subtitle = SimpleText.builder()
- .withText("Usando o componente SimpleText")
- .withFont(builder.getResourceManager().getFont("Times-Italic"))
- .withFontSize(16f)
- .withLineSpacing(1.3f)
- .withColor(new Color(102, 102, 102)) // Cinza
- .build();
+ .withText("Usando o componente SimpleText")
+ .withFont(builder.getResourceManager().getFont("Times-Italic"))
+ .withFontSize(16f)
+ .withLineSpacing(1.3f)
+ .withColor(new Color(102, 102, 102)) // Cinza
+ .build();
SimpleText normalText = SimpleText.builder()
- .withText("Este é um texto normal usando a fonte padrão.")
- .withFont(builder.getResourceManager().getDefaultFont())
- .withFontSize(12f)
- .build();
+ .withText("Este é um texto normal usando a fonte padrão.")
+ .withFont(builder.getResourceManager().getDefaultFont())
+ .withFontSize(12f)
+ .build();
SimpleText highlightText = SimpleText.builder()
- .withText(" Este texto está destacado em vermelho! Este texto está destacado em vermelho! Este texto está destacado em vermelho! Este texto está destacado em vermelho!")
- .withFont(builder.getResourceManager().getFont("Helvetica-Bold"))
- .withFontSize(12f)
- .withColor(new Color(204, 0, 0)) // Vermelho
- .build();
+ .withText(" Este texto está destacado em vermelho! Este texto está destacado em vermelho! Este " +
+ "texto está destacado em vermelho! Este texto está destacado em vermelho!")
+ .withFont(builder.getResourceManager().getFont("Helvetica-Bold"))
+ .withFontSize(12f)
+ .withColor(new Color(204, 0, 0)) // Vermelho
+ .build();
// 4. Adicionando os textos
builder.addSimpleText(title)
- .moveToStart()
- .moveDown(30f)
- .addSimpleText(subtitle)
- .moveToStart()
- .moveDown(60f)
- .addSimpleText(normalText)
- .addSimpleText(highlightText);
+ .moveToStart()
+ .moveDown(30f)
+ .addSimpleText(subtitle)
+ .moveToStart()
+ .moveDown(60f)
+ .addSimpleText(normalText)
+ .addSimpleText(highlightText);
// 5. Salvar o PDF
builder.save("demo_texto_simples.pdf");
- logger.info("PDF gerado com sucesso: demo_texto_simples.pdf");
+ LOGGER.info("PDF gerado com sucesso: demo_texto_simples.pdf");
} catch (Exception e) {
- logger.error("Erro ao gerar o PDF: {}", e.getMessage(), e);
+ LOGGER.error("Erro ao gerar o PDF: {}", e.getMessage(), e);
}
}
}
diff --git a/src/main/java/io/github/joabsonlg/pdfbuilder/examples/PageNumberingDemo.java b/src/main/java/io/github/joabsonlg/pdfbuilder/examples/PageNumberingDemo.java
index 495a0cf..7f285be 100644
--- a/src/main/java/io/github/joabsonlg/pdfbuilder/examples/PageNumberingDemo.java
+++ b/src/main/java/io/github/joabsonlg/pdfbuilder/examples/PageNumberingDemo.java
@@ -16,7 +16,12 @@
import java.awt.Color;
-public class PageNumberingDemo {
+public final class PageNumberingDemo {
+
+ private PageNumberingDemo() {
+ throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
+ }
+
public static void main(String[] args) {
try {
// Configuração da área segura com header e footer
@@ -75,7 +80,8 @@ public static void main(String[] args) {
// Adiciona texto de exemplo
String text = "Este é um exemplo de texto para a página " + i + ". " +
- "O texto é repetido várias vezes para ocupar espaço e forçar a criação de uma nova página. ".repeat(10);
+ "O texto é repetido várias vezes para ocupar espaço e forçar a criação de uma nova página. "
+ .repeat(10);
Paragraph paragraph = Paragraph.builder()
.addStyledText(text, normalStyle)
diff --git a/src/main/java/io/github/joabsonlg/pdfbuilder/examples/ParagraphDemo.java b/src/main/java/io/github/joabsonlg/pdfbuilder/examples/ParagraphDemo.java
index d4edc1b..1aa92bf 100644
--- a/src/main/java/io/github/joabsonlg/pdfbuilder/examples/ParagraphDemo.java
+++ b/src/main/java/io/github/joabsonlg/pdfbuilder/examples/ParagraphDemo.java
@@ -18,8 +18,12 @@
/**
* Demonstração dos diferentes tipos de alinhamento de parágrafos e formatação rica.
*/
-public class ParagraphDemo {
- private static final Logger logger = LoggerFactory.getLogger(ParagraphDemo.class);
+public final class ParagraphDemo {
+ private static final Logger LOGGER = LoggerFactory.getLogger(ParagraphDemo.class);
+
+ private ParagraphDemo() {
+ throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
+ }
public static void main(String[] args) {
try {
@@ -100,7 +104,8 @@ public static void main(String[] args) {
Paragraph justified = Paragraph.builder()
.addStyledText("Alinhamento Justificado: ", boldStyle)
- .addStyledText("Este é um exemplo de texto justificado que demonstra como as palavras são distribuídas uniformemente. ", normalStyle)
+ .addStyledText("Este é um exemplo de texto justificado que demonstra como as palavras são " +
+ "distribuídas uniformemente. ", normalStyle)
.addStyledText("Observe que o espaçamento entre as palavras é ajustado ", italicStyle)
.addStyledText("para que o texto fique alinhado em ambas as margens. ", underlineStyle)
.addStyledText("Este é um recurso muito utilizado em livros e documentos formais.", colorStyle)
@@ -118,10 +123,10 @@ public static void main(String[] args) {
// 5. Salvando o PDF
builder.save("demo_paragrafos_formatados.pdf");
- logger.info("PDF gerado com sucesso: demo_paragrafos_formatados.pdf");
+ LOGGER.info("PDF gerado com sucesso: demo_paragrafos_formatados.pdf");
} catch (Exception e) {
- logger.error("Erro ao gerar o PDF: {}", e.getMessage(), e);
+ LOGGER.error("Erro ao gerar o PDF: {}", e.getMessage(), e);
}
}
}
diff --git a/src/main/java/io/github/joabsonlg/pdfbuilder/examples/TableDemo.java b/src/main/java/io/github/joabsonlg/pdfbuilder/examples/TableDemo.java
index c132084..9f622a5 100644
--- a/src/main/java/io/github/joabsonlg/pdfbuilder/examples/TableDemo.java
+++ b/src/main/java/io/github/joabsonlg/pdfbuilder/examples/TableDemo.java
@@ -1,19 +1,22 @@
package io.github.joabsonlg.pdfbuilder.examples;
import io.github.joabsonlg.pdfbuilder.components.table.Table;
+import io.github.joabsonlg.pdfbuilder.components.text.Heading;
+import io.github.joabsonlg.pdfbuilder.components.text.HeadingLevel;
import io.github.joabsonlg.pdfbuilder.core.PDFBuilder;
import io.github.joabsonlg.pdfbuilder.core.PDFConfiguration;
import io.github.joabsonlg.pdfbuilder.core.SafeArea;
-import io.github.joabsonlg.pdfbuilder.components.text.Heading;
-import io.github.joabsonlg.pdfbuilder.components.text.HeadingLevel;
+import org.apache.pdfbox.pdmodel.common.PDRectangle;
-import java.awt.Color;
+import java.awt.*;
import java.util.Arrays;
import java.util.List;
-import org.apache.pdfbox.pdmodel.common.PDRectangle;
+public final class TableDemo {
+ private TableDemo() {
+ throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
+ }
-public class TableDemo {
public static void main(String[] args) {
try {
// Configuração da área segura com header e footer
@@ -84,11 +87,16 @@ public static void main(String[] args) {
// Cria os dados da tabela com muitas colunas
List> wideTableData = Arrays.asList(
- Arrays.asList("ID", "Nome", "Idade", "Cidade", "Estado", "País", "Profissão", "Departamento", "Salário", "Data de Admissão"),
- Arrays.asList("1", "João Silva", "25", "São Paulo", "SP", "Brasil", "Desenvolvedor", "TI", "5000", "01/01/2020"),
- Arrays.asList("2", "Maria Santos", "30", "Rio de Janeiro", "RJ", "Brasil", "Gerente", "RH", "7000", "15/03/2018"),
- Arrays.asList("3", "Pedro Costa", "28", "Belo Horizonte", "MG", "Brasil", "Analista", "Financeiro", "6000", "22/07/2019")
+ Arrays.asList("ID", "Nome", "Idade", "Cidade", "Estado", "País", "Profissão", "Departamento",
+ "Salário", "Data de Admissão"),
+ Arrays.asList("1", "João Silva", "25", "São Paulo", "SP", "Brasil", "Desenvolvedor", "TI", "5000",
+ "01/01/2020"),
+ Arrays.asList("2", "Maria Santos", "30", "Rio de Janeiro", "RJ", "Brasil", "Gerente", "RH", "7000",
+ "15/03/2018"),
+ Arrays.asList("3", "Pedro Costa", "28", "Belo Horizonte", "MG", "Brasil", "Analista", "Financeiro",
+ "6000", "22/07/2019")
);
+
// Cria uma tabela com muitas colunas
Table wideTable = Table.builder()
.withData(wideTableData)
diff --git a/src/test/java/io/github/joabsonlg/pdfbuilder/components/logo/LogoTest.java b/src/test/java/io/github/joabsonlg/pdfbuilder/components/logo/LogoTest.java
deleted file mode 100644
index 193291d..0000000
--- a/src/test/java/io/github/joabsonlg/pdfbuilder/components/logo/LogoTest.java
+++ /dev/null
@@ -1,128 +0,0 @@
-package io.github.joabsonlg.pdfbuilder.components.logo;
-
-import io.github.joabsonlg.pdfbuilder.core.PDFBuilder;
-import io.github.joabsonlg.pdfbuilder.core.PDFConfiguration;
-import org.apache.pdfbox.pdmodel.common.PDRectangle;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.io.TempDir;
-
-import java.awt.*;
-import java.io.File;
-import java.io.IOException;
-import java.nio.file.Path;
-
-import static org.junit.jupiter.api.Assertions.*;
-
-class LogoTest {
- private PDFBuilder builder;
- private Logo logo;
- private LogoStyle style;
-
- @TempDir
- Path tempDir;
-
- @BeforeEach
- void setUp() {
- PDFConfiguration config = PDFConfiguration.create()
- .withPageSize(PDRectangle.A4)
- .withMargins(50f, 40f, 30f, 40f)
- .build();
- builder = new PDFBuilder(config);
-
- style = LogoStyle.builder()
- .withFontSize(16f)
- .withColor(Color.BLACK)
- .withImageWidth(50f)
- .withImageHeight(30f)
- .withMaintainAspectRatio(true)
- .withMarginBottom(20f)
- .withDrawLine(true)
- .build();
- }
-
- @Test
- void testLogoBuilder() {
- logo = Logo.builder()
- .withTitle("Test Title")
- .withStyle(style)
- .build();
-
- assertNotNull(logo);
- assertEquals("Test Title", logo.getTitle());
- assertEquals(style, logo.getStyle());
- }
-
- @Test
- void testLogoWithImages() {
- logo = Logo.builder()
- .withTitle("Test Title")
- .withStyle(style)
- .withLeftImage("path/to/left.png")
- .withRightImage("path/to/right.png")
- .build();
-
- assertNotNull(logo);
- assertEquals("path/to/left.png", logo.getLeftImagePath());
- assertEquals("path/to/right.png", logo.getRightImagePath());
- }
-
- @Test
- void testLogoStyleBuilder() {
- LogoStyle style = LogoStyle.builder()
- .withFontSize(16f)
- .withColor(Color.BLACK)
- .withImageWidth(50f)
- .withImageHeight(30f)
- .withMaintainAspectRatio(true)
- .withMarginBottom(20f)
- .withDrawLine(true)
- .build();
-
- assertNotNull(style);
- assertEquals(16f, style.getFontSize());
- assertEquals(Color.BLACK, style.getColor());
- assertEquals(50f, style.getImageWidth());
- assertEquals(30f, style.getImageHeight());
- assertTrue(style.isMaintainAspectRatio());
- assertEquals(20f, style.getMarginBottom());
- assertTrue(style.isDrawLine());
- }
-
- @Test
- void testLogoRender() throws IOException {
- logo = Logo.builder()
- .withTitle("Test Title")
- .withStyle(style)
- .build();
-
- File outputFile = tempDir.resolve("test-logo.pdf").toFile();
- builder.setLogo(logo);
- builder.save(outputFile.getAbsolutePath());
-
- assertTrue(outputFile.exists());
- assertTrue(outputFile.length() > 0);
- }
-
- @Test
- void testLogoWithImagesRender() throws IOException {
- // Este teste requer imagens reais para funcionar corretamente
- // Você pode criar arquivos de imagem temporários ou usar recursos de teste
- String leftImagePath = getClass().getResource("/test-left-logo.png").getPath();
- String rightImagePath = getClass().getResource("/test-right-logo.png").getPath();
-
- logo = Logo.builder()
- .withTitle("Test Title")
- .withStyle(style)
- .withLeftImage(leftImagePath)
- .withRightImage(rightImagePath)
- .build();
-
- File outputFile = tempDir.resolve("test-logo-with-images.pdf").toFile();
- builder.setLogo(logo);
- builder.save(outputFile.getAbsolutePath());
-
- assertTrue(outputFile.exists());
- assertTrue(outputFile.length() > 0);
- }
-}
diff --git a/src/test/java/io/github/joabsonlg/pdfbuilder/core/CoordinatesTest.java b/src/test/java/io/github/joabsonlg/pdfbuilder/core/CoordinatesTest.java
deleted file mode 100644
index a351df9..0000000
--- a/src/test/java/io/github/joabsonlg/pdfbuilder/core/CoordinatesTest.java
+++ /dev/null
@@ -1,196 +0,0 @@
-package io.github.joabsonlg.pdfbuilder.core;
-
-import org.apache.pdfbox.pdmodel.common.PDRectangle;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.DisplayName;
-
-import static org.junit.jupiter.api.Assertions.*;
-
-class CoordinatesTest {
- private PDRectangle pageSize;
- private SafeArea safeArea;
- private Coordinates coordinates;
-
- @BeforeEach
- void setUp() {
- pageSize = PDRectangle.A4;
- safeArea = new SafeArea.Builder(pageSize)
- .margins(50f, 50f, 50f, 50f)
- .headerHeight(30f)
- .footerHeight(20f)
- .build();
- coordinates = Coordinates.origin(pageSize, safeArea);
- }
-
- @Test
- @DisplayName("Deve criar coordenadas na origem")
- void shouldCreateAtOrigin() {
- assertEquals(0f, coordinates.getX());
- assertEquals(0f, coordinates.getY());
- assertEquals(pageSize, coordinates.getPageSize());
- assertNotNull(coordinates.getSafeArea());
- }
-
- @Test
- @DisplayName("Deve mover para posição específica")
- void shouldMoveToPosition() {
- Coordinates moved = coordinates.moveTo(100f, 200f);
-
- assertEquals(100f, moved.getX());
- assertEquals(200f, moved.getY());
- }
-
- @Test
- @DisplayName("Deve mover relativamente")
- void shouldMoveRelatively() {
- Coordinates initial = coordinates.moveTo(50f, 50f);
- Coordinates moved = initial.moveBy(25f, -25f);
-
- assertEquals(75f, moved.getX());
- assertEquals(25f, moved.getY());
- }
-
- @Test
- @DisplayName("Deve mover para porcentagem da área de conteúdo")
- void shouldMoveToContentPercent() {
- Coordinates moved = coordinates.moveToContentPercent(50f, 50f);
- PDRectangle contentArea = safeArea.getContentArea();
-
- float expectedX = contentArea.getLowerLeftX() + (contentArea.getWidth() * 0.5f);
- float expectedY = contentArea.getLowerLeftY() + (contentArea.getHeight() * 0.5f);
-
- assertEquals(expectedX, moved.getX(), 0.01f);
- assertEquals(expectedY, moved.getY(), 0.01f);
- }
-
- @Test
- @DisplayName("Deve mover para área do cabeçalho")
- void shouldMoveToHeader() {
- Coordinates moved = coordinates.moveToHeader(50f, 50f);
- PDRectangle headerArea = safeArea.getHeaderArea();
-
- float expectedX = headerArea.getLowerLeftX() + (headerArea.getWidth() * 0.5f);
- float expectedY = headerArea.getLowerLeftY() + (headerArea.getHeight() * 0.5f);
-
- assertEquals(expectedX, moved.getX(), 0.01f);
- assertEquals(expectedY, moved.getY(), 0.01f);
- }
-
- @Test
- @DisplayName("Deve mover para área do rodapé")
- void shouldMoveToFooter() {
- Coordinates moved = coordinates.moveToFooter(50f, 50f);
- PDRectangle footerArea = safeArea.getFooterArea();
-
- float expectedX = footerArea.getLowerLeftX() + (footerArea.getWidth() * 0.5f);
- float expectedY = footerArea.getLowerLeftY() + (footerArea.getHeight() * 0.5f);
-
- assertEquals(expectedX, moved.getX(), 0.01f);
- assertEquals(expectedY, moved.getY(), 0.01f);
- }
-
- @Test
- @DisplayName("Deve validar ponto na área segura")
- void shouldValidatePointInSafeArea() {
- PDRectangle contentArea = safeArea.getContentArea();
-
- // Ponto dentro da área segura
- Coordinates inside = coordinates.moveTo(
- contentArea.getLowerLeftX() + 10,
- contentArea.getLowerLeftY() + 10
- );
- assertTrue(inside.isInSafeArea());
-
- // Ponto fora da área segura
- Coordinates outside = coordinates.moveTo(10f, 10f);
- assertFalse(outside.isInSafeArea());
- }
-
- @Test
- @DisplayName("Deve ajustar coordenadas para área segura")
- void shouldAdjustToSafeArea() {
- PDRectangle contentArea = safeArea.getContentArea();
-
- // Ponto fora da área segura (muito à esquerda e abaixo)
- Coordinates outside = coordinates.moveTo(10f, 10f);
- Coordinates adjusted = outside.ensureInSafeArea();
-
- assertEquals(contentArea.getLowerLeftX(), adjusted.getX());
- assertEquals(contentArea.getLowerLeftY(), adjusted.getY());
-
- // Ponto fora da área segura (muito à direita e acima)
- outside = coordinates.moveTo(
- pageSize.getWidth() + 10,
- pageSize.getHeight() + 10
- );
- adjusted = outside.ensureInSafeArea();
-
- assertEquals(contentArea.getUpperRightX(), adjusted.getX());
- assertEquals(contentArea.getUpperRightY(), adjusted.getY());
- }
-
- @Test
- @DisplayName("Deve rejeitar percentagens inválidas")
- void shouldRejectInvalidPercentages() {
- assertThrows(IllegalArgumentException.class, () ->
- coordinates.moveToContentPercent(-1f, 50f));
-
- assertThrows(IllegalArgumentException.class, () ->
- coordinates.moveToContentPercent(50f, 101f));
-
- assertThrows(IllegalArgumentException.class, () ->
- coordinates.moveToHeader(-1f, 50f));
-
- assertThrows(IllegalArgumentException.class, () ->
- coordinates.moveToFooter(50f, 101f));
- }
-
- @Test
- @DisplayName("Deve rejeitar movimento para cabeçalho quando não definido")
- void shouldRejectHeaderMoveWhenNotDefined() {
- SafeArea safeAreaNoHeader = new SafeArea.Builder(pageSize)
- .margins(50f, 50f, 50f, 50f)
- .build();
- Coordinates coords = Coordinates.origin(pageSize, safeAreaNoHeader);
-
- assertThrows(IllegalStateException.class, () ->
- coords.moveToHeader(50f, 50f));
- }
-
- @Test
- @DisplayName("Deve rejeitar movimento para rodapé quando não definido")
- void shouldRejectFooterMoveWhenNotDefined() {
- SafeArea safeAreaNoFooter = new SafeArea.Builder(pageSize)
- .margins(50f, 50f, 50f, 50f)
- .build();
- Coordinates coords = Coordinates.origin(pageSize, safeAreaNoFooter);
-
- assertThrows(IllegalStateException.class, () ->
- coords.moveToFooter(50f, 50f));
- }
-
- @Test
- @DisplayName("Deve mover para o topo da área de conteúdo")
- void shouldMoveToTop() {
- // Given
- float marginTop = 50f;
- float marginRight = 50f;
- float marginBottom = 50f;
- float marginLeft = 50f;
- float headerHeight = 30f;
- SafeArea safeArea = new SafeArea.Builder(pageSize)
- .margins(marginTop, marginRight, marginBottom, marginLeft)
- .headerHeight(headerHeight)
- .build();
- Coordinates coords = Coordinates.origin(pageSize, safeArea);
-
- // When
- Coordinates moved = coords.moveToTop();
-
- // Then
- float expectedY = pageSize.getHeight() - marginTop - headerHeight;
- assertEquals(coords.getX(), moved.getX(), 0.1); // X não deve mudar
- assertEquals(expectedY, moved.getY(), 0.1);
- }
-}
diff --git a/src/test/java/io/github/joabsonlg/pdfbuilder/core/PDFBuilderTest.java b/src/test/java/io/github/joabsonlg/pdfbuilder/core/PDFBuilderTest.java
deleted file mode 100644
index 142a2cc..0000000
--- a/src/test/java/io/github/joabsonlg/pdfbuilder/core/PDFBuilderTest.java
+++ /dev/null
@@ -1,327 +0,0 @@
-package io.github.joabsonlg.pdfbuilder.core;
-
-import org.apache.pdfbox.Loader;
-import org.apache.pdfbox.pdmodel.PDDocument;
-import org.apache.pdfbox.pdmodel.PDPage;
-import org.apache.pdfbox.pdmodel.common.PDRectangle;
-import org.apache.pdfbox.pdmodel.font.PDFont;
-import org.apache.pdfbox.pdmodel.font.PDType1Font;
-import org.apache.pdfbox.pdmodel.font.Standard14Fonts;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.io.TempDir;
-
-import java.io.File;
-import java.io.IOException;
-import java.nio.file.Path;
-
-import static org.junit.jupiter.api.Assertions.*;
-
-class PDFBuilderTest {
-
- @TempDir
- Path tempDir;
-
- @Test
- @DisplayName("Deve criar builder com configuração padrão")
- void createWithDefaultConfiguration() {
- PDFBuilder builder = PDFBuilder.create();
- assertNotNull(builder);
- assertNotNull(builder.getDocument());
- assertNotNull(builder.getCurrentPage());
- assertNotNull(builder.getCurrentPosition());
- assertEquals(PDRectangle.A4, builder.getConfig().getPageSize());
- }
-
- @Test
- @DisplayName("Deve criar builder com configuração personalizada")
- void createWithCustomConfiguration() {
- PDFConfiguration config = PDFConfiguration.create()
- .withPageSize(PDRectangle.LETTER)
- .withSafeArea(new SafeArea.Builder(PDRectangle.LETTER)
- .margins(50f, 50f, 50f, 50f)
- .build())
- .build();
-
- PDFBuilder builder = PDFBuilder.create(config);
- assertNotNull(builder);
- assertEquals(PDRectangle.LETTER, builder.getConfig().getPageSize());
- assertEquals(50f, builder.getConfig().getSafeArea().getMarginTop());
- }
-
- @Test
- @DisplayName("Deve criar nova página com tamanho correto")
- void addNewPageCreatesNewPageWithCorrectSize() {
- PDFBuilder builder = PDFBuilder.create();
- PDPage initialPage = builder.getCurrentPage();
-
- builder.addNewPage();
- PDPage newPage = builder.getCurrentPage();
-
- assertNotNull(newPage);
- assertNotEquals(initialPage, newPage);
- assertEquals(PDRectangle.A4, newPage.getMediaBox());
- }
-
- @Test
- @DisplayName("Deve atualizar posição com moveTo")
- void moveToUpdatesPosition() {
- PDFBuilder builder = PDFBuilder.create();
- builder.moveTo(100, 200);
-
- Coordinates pos = builder.getCurrentPosition();
- assertEquals(100, pos.getX());
- assertEquals(200, pos.getY());
- }
-
- @Test
- @DisplayName("Deve atualizar posição relativamente com moveBy")
- void moveByUpdatesPositionRelatively() {
- PDFBuilder builder = PDFBuilder.create();
- builder.moveTo(100, 100).moveBy(50, -25);
-
- Coordinates pos = builder.getCurrentPosition();
- assertEquals(150, pos.getX());
- assertEquals(75, pos.getY());
- }
-
- @Test
- @DisplayName("Deve posicionar corretamente na área de conteúdo")
- void moveToContentPercentPositionsCorrectly() {
- SafeArea safeArea = new SafeArea.Builder(PDRectangle.A4)
- .margins(50f, 50f, 50f, 50f)
- .build();
-
- PDFConfiguration config = PDFConfiguration.create()
- .withSafeArea(safeArea)
- .build();
-
- PDFBuilder builder = PDFBuilder.create(config);
- builder.moveToContentPercent(50, 50);
-
- Coordinates pos = builder.getCurrentPosition();
- PDRectangle contentArea = safeArea.getContentArea();
- float expectedX = contentArea.getLowerLeftX() + (contentArea.getWidth() * 0.5f);
- float expectedY = contentArea.getLowerLeftY() + (contentArea.getHeight() * 0.5f);
-
- assertEquals(expectedX, pos.getX(), 0.1);
- assertEquals(expectedY, pos.getY(), 0.1);
- }
-
- @Test
- @DisplayName("Deve posicionar corretamente na área do cabeçalho")
- void moveToHeaderPositionsInHeaderArea() {
- SafeArea safeArea = new SafeArea.Builder(PDRectangle.A4)
- .margins(50f, 50f, 50f, 50f)
- .headerHeight(100f)
- .build();
-
- PDFConfiguration config = PDFConfiguration.create()
- .withSafeArea(safeArea)
- .build();
-
- PDFBuilder builder = PDFBuilder.create(config);
- builder.moveToHeader(50, 50);
-
- Coordinates pos = builder.getCurrentPosition();
- PDRectangle headerArea = safeArea.getHeaderArea();
- float expectedY = headerArea.getLowerLeftY() + (headerArea.getHeight() * 0.5f);
- assertTrue(pos.getY() >= expectedY);
- }
-
- @Test
- @DisplayName("Deve posicionar corretamente na área do rodapé")
- void moveToFooterPositionsInFooterArea() {
- SafeArea safeArea = new SafeArea.Builder(PDRectangle.A4)
- .margins(50f, 50f, 50f, 50f)
- .footerHeight(100f)
- .build();
-
- PDFConfiguration config = PDFConfiguration.create()
- .withSafeArea(safeArea)
- .build();
-
- PDFBuilder builder = PDFBuilder.create(config);
- builder.moveToFooter(50, 50);
-
- Coordinates pos = builder.getCurrentPosition();
- PDRectangle footerArea = safeArea.getFooterArea();
- float expectedY = footerArea.getLowerLeftY() + (footerArea.getHeight() * 0.5f);
- assertTrue(pos.getY() <= expectedY + footerArea.getHeight());
- }
-
- @Test
- @DisplayName("Deve criar arquivo PDF com texto")
- void addTextAndSaveCreatesPDFFile() throws IOException {
- PDFBuilder builder = PDFBuilder.create();
- String testText = "Hello, PDF!";
-
- File outputFile = tempDir.resolve("test.pdf").toFile();
-
- builder.moveTo(50, 700)
- .addText(testText)
- .save(outputFile.getAbsolutePath());
-
- assertTrue(outputFile.exists());
- assertTrue(outputFile.length() > 0);
-
- try (PDDocument doc = Loader.loadPDF(outputFile)) {
- assertEquals(1, doc.getNumberOfPages());
- }
- }
-
- @Test
- @DisplayName("Deve lançar exceção para configuração nula")
- void throwsExceptionForNullConfiguration() {
- assertThrows(IllegalArgumentException.class, () -> PDFBuilder.create(null));
- }
-
- @Test
- @DisplayName("Deve criar PDF com configurações padrão")
- void shouldCreatePDFWithDefaultSettings() throws IOException {
- Path pdfPath = tempDir.resolve("test.pdf");
-
- PDFBuilder builder = PDFBuilder.create();
- builder.save(pdfPath.toString());
- builder.close();
-
- assertTrue(pdfPath.toFile().exists());
- assertTrue(pdfPath.toFile().length() > 0);
- }
-
- @Test
- @DisplayName("Deve criar PDF com configuração personalizada")
- void shouldCreatePDFWithCustomConfiguration() {
- SafeArea safeArea = new SafeArea.Builder(PDRectangle.A3)
- .margins(100f, 100f, 100f, 100f)
- .build();
-
- PDFConfiguration config = PDFConfiguration.create()
- .withPageSize(PDRectangle.A3)
- .withSafeArea(safeArea)
- .withDPI(600)
- .build();
-
- PDFBuilder builder = PDFBuilder.create(config);
-
- assertEquals(PDRectangle.A3, builder.getConfig().getPageSize());
- assertEquals(100f, builder.getConfig().getSafeArea().getMarginTop());
- assertEquals(600, builder.getConfig().getDpi());
- }
-
- @Test
- @DisplayName("Deve criar PDF com margens personalizadas")
- void shouldCreatePDFWithCustomMargins() {
- SafeArea safeArea = new SafeArea.Builder(PDRectangle.A4)
- .margins(100f, 100f, 100f, 100f)
- .build();
-
- PDFConfiguration config = PDFConfiguration.create()
- .withSafeArea(safeArea)
- .build();
-
- PDFBuilder builder = PDFBuilder.create(config);
-
- assertEquals(100f, builder.getConfig().getSafeArea().getMarginTop());
- }
-
- @Test
- @DisplayName("Deve atualizar tamanho da página via PDFBuilder")
- void shouldUpdatePageSizeViaPDFBuilder() {
- PDFBuilder builder = PDFBuilder.create()
- .withPageSize(PDRectangle.A3);
-
- PDRectangle pageSize = builder.getConfig().getPageSize();
- assertEquals(PDRectangle.A3.getWidth(), pageSize.getWidth(), 0.001);
- assertEquals(PDRectangle.A3.getHeight(), pageSize.getHeight(), 0.001);
- }
-
- @Test
- @DisplayName("Deve adicionar múltiplas páginas")
- void shouldAddMultiplePages() {
- PDFBuilder builder = PDFBuilder.create();
- int initialPageCount = builder.getDocument().getNumberOfPages();
-
- builder.addNewPage()
- .addNewPage();
-
- assertEquals(initialPageCount + 2, builder.getDocument().getNumberOfPages());
- }
-
- @Test
- @DisplayName("Deve usar novo tamanho de página ao adicionar página")
- void shouldUseNewPageSizeWhenAddingPage() {
- PDFBuilder builder = PDFBuilder.create()
- .withPageSize(PDRectangle.A3)
- .addNewPage();
-
- PDPage currentPage = builder.getCurrentPage();
- assertEquals(PDRectangle.A3.getWidth(), currentPage.getMediaBox().getWidth(), 0.001);
- assertEquals(PDRectangle.A3.getHeight(), currentPage.getMediaBox().getHeight(), 0.001);
- }
-
- @Test
- @DisplayName("Deve retornar uma instância de ResourceManager")
- void shouldReturnResourceManagerInstance() {
- PDFBuilder builder = PDFBuilder.create();
- assertNotNull(builder.getResourceManager());
- }
-
- @Test
- @DisplayName("Deve manter a mesma instância de ResourceManager")
- void shouldMaintainSameResourceManagerInstance() {
- PDFBuilder builder = PDFBuilder.create();
- ResourceManager manager1 = builder.getResourceManager();
- ResourceManager manager2 = builder.getResourceManager();
- assertSame(manager1, manager2);
- }
-
- @Test
- @DisplayName("ResourceManager deve inicializar com fonte padrão")
- void resourceManagerShouldInitializeWithDefaultFont() {
- PDFBuilder builder = PDFBuilder.create();
- ResourceManager manager = builder.getResourceManager();
- PDFont helvetica = new PDType1Font(Standard14Fonts.FontName.HELVETICA);
- assertEquals(helvetica.getName(), manager.getDefaultFont().getName());
- }
-
- @Test
- @DisplayName("Deve adicionar texto usando sistema de coordenadas")
- void shouldAddTextUsingCoordinates() throws IOException {
- PDFBuilder builder = PDFBuilder.create();
- Path outputPath = tempDir.resolve("test.pdf");
-
- builder.moveToTop()
- .moveRight(50.0f)
- .addText("Primeiro texto")
- .moveDown(20.0f)
- .moveToStart()
- .moveRight(100.0f)
- .addText("Segundo texto")
- .moveToBottom()
- .moveToStart()
- .addText("Texto no final");
-
- builder.save(outputPath.toString());
- assertTrue(outputPath.toFile().exists());
- assertTrue(outputPath.toFile().length() > 0);
- }
-
- @Test
- @DisplayName("Deve adicionar múltiplas linhas de texto")
- void shouldAddMultipleLines() throws IOException {
- PDFBuilder builder = PDFBuilder.create();
- Path outputPath = tempDir.resolve("test.pdf");
-
- builder.moveToTop()
- .addLine("Primeira linha")
- .addLine("Segunda linha")
- .addLine("Terceira linha")
- .addLine("Quarta linha")
- .addLine("Quinta linha");
-
- builder.save(outputPath.toString());
- assertTrue(outputPath.toFile().exists());
- assertTrue(outputPath.toFile().length() > 0);
- }
-}
diff --git a/src/test/java/io/github/joabsonlg/pdfbuilder/core/PDFConfigurationTest.java b/src/test/java/io/github/joabsonlg/pdfbuilder/core/PDFConfigurationTest.java
deleted file mode 100644
index e22a344..0000000
--- a/src/test/java/io/github/joabsonlg/pdfbuilder/core/PDFConfigurationTest.java
+++ /dev/null
@@ -1,386 +0,0 @@
-package io.github.joabsonlg.pdfbuilder.core;
-
-import org.apache.pdfbox.pdmodel.common.PDRectangle;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.DisplayName;
-
-import static org.junit.jupiter.api.Assertions.*;
-
-class PDFConfigurationTest {
-
- @Test
- @DisplayName("Deve criar configuração com valores padrão")
- void shouldCreateWithDefaultValues() {
- // When
- PDFConfiguration config = PDFConfiguration.create().build();
-
- // Then
- assertEquals(PDRectangle.A4, config.getPageSize());
- assertEquals(50f, config.getMarginTop());
- assertEquals(50f, config.getMarginRight());
- assertEquals(50f, config.getMarginBottom());
- assertEquals(50f, config.getMarginLeft());
- assertEquals(300, config.getDpi());
- assertEquals(0.7f, config.getCompressionQuality(), 0.001f);
- }
-
- @Test
- @DisplayName("Deve configurar tamanho de página personalizado")
- void shouldSetCustomPageSize() {
- // When
- PDFConfiguration config = PDFConfiguration.create()
- .withPageSize(PDRectangle.A3)
- .build();
-
- // Then
- assertEquals(PDRectangle.A3.getWidth(), config.getPageSize().getWidth(), 0.001f);
- assertEquals(PDRectangle.A3.getHeight(), config.getPageSize().getHeight(), 0.001f);
- }
-
- @Test
- @DisplayName("Deve configurar margem uniforme")
- void shouldSetUniformMargin() {
- // Given
- float margin = 100f;
-
- // When
- PDFConfiguration config = PDFConfiguration.create()
- .withMargin(margin)
- .build();
-
- // Then
- assertEquals(margin, config.getMarginTop());
- assertEquals(margin, config.getMarginRight());
- assertEquals(margin, config.getMarginBottom());
- assertEquals(margin, config.getMarginLeft());
- }
-
- @Test
- @DisplayName("Deve configurar margens individuais")
- void shouldSetIndividualMargins() {
- // Given
- float top = 100f;
- float right = 90f;
- float bottom = 120f;
- float left = 80f;
-
- // When
- PDFConfiguration config = PDFConfiguration.create()
- .withMargins(top, right, bottom, left)
- .build();
-
- // Then
- assertEquals(top, config.getMarginTop());
- assertEquals(right, config.getMarginRight());
- assertEquals(bottom, config.getMarginBottom());
- assertEquals(left, config.getMarginLeft());
- }
-
- @Test
- @DisplayName("Deve calcular área de conteúdo corretamente")
- void shouldCalculateContentArea() {
- // Given
- PDFConfiguration config = PDFConfiguration.create()
- .withPageSize(PDRectangle.A4)
- .withMargin(50f)
- .build();
-
- // When
- PDRectangle contentArea = config.getContentArea();
-
- // Then
- float expectedWidth = PDRectangle.A4.getWidth() - (2 * 50f);
- float expectedHeight = PDRectangle.A4.getHeight() - (2 * 50f);
-
- assertEquals(expectedWidth, contentArea.getWidth(), 0.001f);
- assertEquals(expectedHeight, contentArea.getHeight(), 0.001f);
- }
-
- @Test
- @DisplayName("Deve configurar DPI")
- void shouldSetDPI() {
- // Given
- int dpi = 600;
-
- // When
- PDFConfiguration config = PDFConfiguration.create()
- .withDPI(dpi)
- .build();
-
- // Then
- assertEquals(dpi, config.getDpi());
- }
-
- @Test
- @DisplayName("Deve configurar qualidade de compressão")
- void shouldSetCompressionQuality() {
- // Given
- float quality = 0.5f;
-
- // When
- PDFConfiguration config = PDFConfiguration.create()
- .withCompressionQuality(quality)
- .build();
-
- // Then
- assertEquals(quality, config.getCompressionQuality(), 0.001f);
- }
-
- @Test
- @DisplayName("Deve rejeitar qualidade de compressão inválida")
- void shouldRejectInvalidCompressionQuality() {
- // Given
- float invalidQuality = 1.5f;
-
- // Then
- assertThrows(IllegalArgumentException.class, () -> {
- PDFConfiguration.create().withCompressionQuality(invalidQuality).build();
- });
- }
-
- @Test
- @DisplayName("Deve criar configuração com margem uniforme")
- void shouldCreateConfigurationWithUniformMargin() {
- PDFConfiguration config = PDFConfiguration.create()
- .withMargin(100)
- .build();
- assertEquals(100, config.getMarginTop());
- assertEquals(100, config.getMarginRight());
- assertEquals(100, config.getMarginBottom());
- assertEquals(100, config.getMarginLeft());
- }
-
- @Test
- @DisplayName("Deve criar configuração com margens individuais")
- void shouldCreateConfigurationWithIndividualMargins() {
- PDFConfiguration config = PDFConfiguration.create()
- .withMargins(50, 60, 70, 80)
- .build();
- assertEquals(50, config.getMarginTop());
- assertEquals(60, config.getMarginRight());
- assertEquals(70, config.getMarginBottom());
- assertEquals(80, config.getMarginLeft());
- }
-
- @Test
- @DisplayName("Deve criar configuração com tamanho de fonte")
- void shouldCreateConfigurationWithFontSize() {
- PDFConfiguration config = PDFConfiguration.create()
- .withFontSize(14)
- .build();
- assertEquals(14, config.getFontSize());
- }
-
- @Test
- @DisplayName("Deve criar configuração com espaçamento entre linhas")
- void shouldCreateConfigurationWithLineSpacing() {
- PDFConfiguration config = PDFConfiguration.create()
- .withLineSpacing(16)
- .build();
- assertEquals(16, config.getLineSpacing());
- }
-
- @Test
- @DisplayName("Deve manter valores padrão quando não configurados")
- void shouldKeepDefaultValuesWhenNotConfigured() {
- PDFConfiguration config = PDFConfiguration.create().build();
- assertEquals(50, config.getMarginTop()); // DEFAULT_MARGIN
- assertEquals(12, config.getFontSize()); // DEFAULT_FONT_SIZE
- assertEquals(14, config.getLineSpacing()); // DEFAULT_LINE_SPACING
- }
-
- @Test
- @DisplayName("Deve permitir configuração em cadeia")
- void shouldAllowChainedConfiguration() {
- PDFConfiguration config = PDFConfiguration.create()
- .withMargin(100)
- .withFontSize(16)
- .withLineSpacing(18)
- .build();
-
- assertEquals(100, config.getMarginTop());
- assertEquals(16, config.getFontSize());
- assertEquals(18, config.getLineSpacing());
- }
-
- @Test
- @DisplayName("Deve rejeitar margens negativas")
- void shouldRejectNegativeMargins() {
- assertThrows(IllegalArgumentException.class, () -> {
- PDFConfiguration.create().withMargin(-1).build();
- });
-
- assertThrows(IllegalArgumentException.class, () -> {
- PDFConfiguration.create().withMargins(-1, 0, 0, 0).build();
- });
- }
-
- @Test
- @DisplayName("Deve rejeitar tamanho de fonte negativo ou zero")
- void shouldRejectNegativeOrZeroFontSize() {
- assertThrows(IllegalArgumentException.class, () -> {
- PDFConfiguration.create().withFontSize(-1).build();
- });
-
- assertThrows(IllegalArgumentException.class, () -> {
- PDFConfiguration.create().withFontSize(0).build();
- });
- }
-
- @Test
- @DisplayName("Deve rejeitar espaçamento entre linhas negativo ou zero")
- void shouldRejectNegativeOrZeroLineSpacing() {
- assertThrows(IllegalArgumentException.class, () -> {
- PDFConfiguration.create().withLineSpacing(-1).build();
- });
-
- assertThrows(IllegalArgumentException.class, () -> {
- PDFConfiguration.create().withLineSpacing(0).build();
- });
- }
-
- @Test
- @DisplayName("Deve rejeitar DPI menor ou igual a zero")
- void shouldRejectZeroOrNegativeDPI() {
- assertThrows(IllegalArgumentException.class, () -> {
- PDFConfiguration.create().withDPI(0).build();
- });
-
- assertThrows(IllegalArgumentException.class, () -> {
- PDFConfiguration.create().withDPI(-1).build();
- });
- }
-
- @Test
- @DisplayName("Deve rejeitar tamanho de página nulo")
- void shouldRejectNullPageSize() {
- assertThrows(IllegalArgumentException.class, () -> {
- PDFConfiguration.create().withPageSize(null).build();
- });
- }
-
- @Test
- @DisplayName("Deve rejeitar margens negativas em qualquer posição")
- void shouldRejectNegativeMarginsInAnyPosition() {
- assertThrows(IllegalArgumentException.class, () -> {
- PDFConfiguration.create().withMargins(0, -1, 0, 0).build();
- });
-
- assertThrows(IllegalArgumentException.class, () -> {
- PDFConfiguration.create().withMargins(0, 0, -1, 0).build();
- });
-
- assertThrows(IllegalArgumentException.class, () -> {
- PDFConfiguration.create().withMargins(0, 0, 0, -1).build();
- });
- }
-
- @Test
- @DisplayName("Deve validar que getMargin retorna margem superior quando todas são iguais")
- void shouldValidateUniformMarginGetter() {
- PDFConfiguration config = PDFConfiguration.create()
- .withMargin(100)
- .build();
-
- assertEquals(100, config.getMargin());
- assertEquals(config.getMarginTop(), config.getMargin());
- }
-
- @Test
- @DisplayName("Deve manter valores padrão ao alterar apenas algumas configurações")
- void shouldKeepDefaultValuesWhenPartiallyConfigured() {
- PDFConfiguration config = PDFConfiguration.create()
- .withMargin(100)
- .withFontSize(16)
- .build();
-
- assertEquals(100, config.getMarginTop());
- assertEquals(16, config.getFontSize());
- assertEquals(14, config.getLineSpacing()); // valor padrão do lineSpacing
- assertEquals(300, config.getDpi()); // valor padrão do DPI
- assertEquals(0.7f, config.getCompressionQuality(), 0.001f); // valor padrão da qualidade de compressão
- }
-
- @Test
- @DisplayName("Deve validar consistência dos valores padrão")
- void shouldValidateDefaultValuesConsistency() {
- PDFConfiguration config = PDFConfiguration.create().build();
-
- // Verifica se todos os valores padrão são consistentes
- assertEquals(PDRectangle.A4, config.getPageSize());
- assertEquals(50f, config.getMarginTop());
- assertEquals(50f, config.getMarginRight());
- assertEquals(50f, config.getMarginBottom());
- assertEquals(50f, config.getMarginLeft());
- assertEquals(300, config.getDpi());
- assertEquals(0.7f, config.getCompressionQuality(), 0.001f);
- assertEquals(12f, config.getFontSize());
- assertEquals(14f, config.getLineSpacing());
- }
-
- @Test
- @DisplayName("Deve configurar área segura")
- void shouldSetSafeArea() {
- // Given
- SafeArea safeArea = SafeArea.builder()
- .withMargins(30f, 50f, 40f, 30f)
- .withHeader(true)
- .withFooter(true)
- .build();
-
- // When
- PDFConfiguration config = PDFConfiguration.create()
- .withSafeArea(safeArea)
- .build();
-
- // Then
- assertEquals(safeArea, config.getSafeArea());
- assertEquals(30f, config.getSafeArea().getMarginLeft());
- assertEquals(50f, config.getSafeArea().getMarginRight());
- assertEquals(40f, config.getSafeArea().getMarginBottom());
- assertEquals(30f, config.getSafeArea().getMarginTop());
- assertTrue(config.getSafeArea().hasHeader());
- assertTrue(config.getSafeArea().hasFooter());
- }
-
- @Test
- @DisplayName("Deve atualizar área segura ao alterar tamanho da página")
- void shouldUpdateSafeAreaWhenChangingPageSize() {
- // Given
- PDFConfiguration configA4 = PDFConfiguration.create()
- .withPageSize(PDRectangle.A4)
- .build();
-
- // When
- PDFConfiguration configA3 = PDFConfiguration.create()
- .withPageSize(PDRectangle.A3)
- .build();
-
- // Then
- // Verifica se as margens foram mantidas
- assertEquals(50f, configA4.getSafeArea().getMarginTop());
- assertEquals(50f, configA4.getSafeArea().getMarginRight());
- assertEquals(50f, configA4.getSafeArea().getMarginBottom());
- assertEquals(50f, configA4.getSafeArea().getMarginLeft());
-
- assertEquals(50f, configA3.getSafeArea().getMarginTop());
- assertEquals(50f, configA3.getSafeArea().getMarginRight());
- assertEquals(50f, configA3.getSafeArea().getMarginBottom());
- assertEquals(50f, configA3.getSafeArea().getMarginLeft());
-
- // Verifica que as áreas de conteúdo são diferentes
- assertNotEquals(
- configA4.getSafeArea().getContentArea(PDRectangle.A4).getWidth(),
- configA3.getSafeArea().getContentArea(PDRectangle.A3).getWidth()
- );
- }
-
- @Test
- @DisplayName("Deve rejeitar área segura nula")
- void shouldRejectNullSafeArea() {
- assertThrows(IllegalArgumentException.class, () ->
- PDFConfiguration.create()
- .withSafeArea(null)
- .build());
- }
-}
diff --git a/src/test/java/io/github/joabsonlg/pdfbuilder/core/SafeAreaTest.java b/src/test/java/io/github/joabsonlg/pdfbuilder/core/SafeAreaTest.java
deleted file mode 100644
index 025e261..0000000
--- a/src/test/java/io/github/joabsonlg/pdfbuilder/core/SafeAreaTest.java
+++ /dev/null
@@ -1,179 +0,0 @@
-package io.github.joabsonlg.pdfbuilder.core;
-
-import org.apache.pdfbox.pdmodel.common.PDRectangle;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.DisplayName;
-
-import static org.junit.jupiter.api.Assertions.*;
-
-class SafeAreaTest {
-
- @Test
- @DisplayName("Deve criar SafeArea com valores padrão")
- void shouldCreateWithDefaultValues() {
- SafeArea safeArea = new SafeArea.Builder(PDRectangle.A4).build();
-
- assertEquals(50f, safeArea.getMarginTop());
- assertEquals(50f, safeArea.getMarginRight());
- assertEquals(50f, safeArea.getMarginBottom());
- assertEquals(50f, safeArea.getMarginLeft());
- assertEquals(0f, safeArea.getHeaderHeight());
- assertEquals(0f, safeArea.getFooterHeight());
- assertEquals(0f, safeArea.getBleedMargin());
- assertFalse(safeArea.isMirrored());
- }
-
- @Test
- @DisplayName("Deve criar SafeArea com margens personalizadas")
- void shouldCreateWithCustomMargins() {
- SafeArea safeArea = new SafeArea.Builder(PDRectangle.A4)
- .margins(70f, 60f, 50f, 40f)
- .build();
-
- assertEquals(70f, safeArea.getMarginTop());
- assertEquals(60f, safeArea.getMarginRight());
- assertEquals(50f, safeArea.getMarginBottom());
- assertEquals(40f, safeArea.getMarginLeft());
- }
-
- @Test
- @DisplayName("Deve criar SafeArea com cabeçalho e rodapé")
- void shouldCreateWithHeaderAndFooter() {
- SafeArea safeArea = new SafeArea.Builder(PDRectangle.A4)
- .headerHeight(50f)
- .footerHeight(30f)
- .build();
-
- PDRectangle headerArea = safeArea.getHeaderArea();
- PDRectangle footerArea = safeArea.getFooterArea();
-
- assertNotNull(headerArea);
- assertNotNull(footerArea);
- assertEquals(50f, headerArea.getHeight());
- assertEquals(30f, footerArea.getHeight());
- }
-
- @Test
- @DisplayName("Deve calcular área de conteúdo corretamente")
- void shouldCalculateContentArea() {
- SafeArea safeArea = new SafeArea.Builder(PDRectangle.A4)
- .margins(50f, 50f, 50f, 50f)
- .headerHeight(30f)
- .footerHeight(20f)
- .build();
-
- PDRectangle contentArea = safeArea.getContentArea();
-
- assertEquals(50f, contentArea.getLowerLeftX());
- assertEquals(70f, contentArea.getLowerLeftY()); // marginBottom + footerHeight
- assertEquals(495.28f, contentArea.getWidth(), 0.01f);
- assertEquals(691.89f, contentArea.getHeight(), 0.01f);
- }
-
- @Test
- @DisplayName("Deve validar pontos na área segura")
- void shouldValidatePointsInSafeArea() {
- SafeArea safeArea = new SafeArea.Builder(PDRectangle.A4)
- .margins(50f, 50f, 50f, 50f)
- .build();
-
- assertTrue(safeArea.isPointInSafeArea(100f, 100f));
- assertFalse(safeArea.isPointInSafeArea(10f, 10f));
- }
-
- @Test
- @DisplayName("Deve calcular margens espelhadas corretamente")
- void shouldCalculateMirroredMargins() {
- SafeArea safeArea = new SafeArea.Builder(PDRectangle.A4)
- .margins(50f, 60f, 50f, 40f)
- .mirrored(true)
- .build();
-
- float[] normalMargins = safeArea.getMirrordMargins(false);
- float[] mirroredMargins = safeArea.getMirrordMargins(true);
-
- // Página ímpar (normal)
- assertEquals(50f, normalMargins[0]); // top
- assertEquals(60f, normalMargins[1]); // right
- assertEquals(50f, normalMargins[2]); // bottom
- assertEquals(40f, normalMargins[3]); // left
-
- // Página par (espelhada)
- assertEquals(50f, mirroredMargins[0]); // top
- assertEquals(40f, mirroredMargins[1]); // right (trocado com left)
- assertEquals(50f, mirroredMargins[2]); // bottom
- assertEquals(60f, mirroredMargins[3]); // left (trocado com right)
- }
-
- @Test
- @DisplayName("Deve rejeitar valores negativos")
- void shouldRejectNegativeValues() {
- SafeArea.Builder builder = new SafeArea.Builder(PDRectangle.A4);
-
- assertThrows(IllegalArgumentException.class, () ->
- builder.margins(-1f, 0f, 0f, 0f));
-
- assertThrows(IllegalArgumentException.class, () ->
- builder.headerHeight(-1f));
-
- assertThrows(IllegalArgumentException.class, () ->
- builder.footerHeight(-1f));
-
- assertThrows(IllegalArgumentException.class, () ->
- builder.bleedMargin(-1f));
- }
-
- @Test
- @DisplayName("Deve rejeitar página nula")
- void shouldRejectNullPage() {
- assertThrows(IllegalArgumentException.class, () ->
- new SafeArea.Builder(null));
- }
-
- @Test
- @DisplayName("Deve calcular área com sangria")
- void shouldCalculateAreaWithBleed() {
- SafeArea safeArea = new SafeArea.Builder(PDRectangle.A4)
- .margins(50f, 50f, 50f, 50f)
- .bleedMargin(10f)
- .build();
-
- PDRectangle contentArea = safeArea.getContentArea();
-
- assertEquals(60f, contentArea.getLowerLeftX()); // marginLeft + bleed
- assertEquals(60f, contentArea.getLowerLeftY()); // marginBottom + bleed
- assertEquals(475.28f, contentArea.getWidth(), 0.01f); // pageWidth - (margins + 2*bleed)
- assertEquals(721.89f, contentArea.getHeight(), 0.01f); // pageHeight - (margins + 2*bleed)
- }
-
- @Test
- @DisplayName("Não deve retornar áreas de cabeçalho/rodapé quando altura é zero")
- void shouldNotReturnHeaderFooterAreasWhenHeightIsZero() {
- SafeArea safeArea = new SafeArea.Builder(PDRectangle.A4).build();
-
- assertNull(safeArea.getHeaderArea());
- assertNull(safeArea.getFooterArea());
- }
-
- @Test
- @DisplayName("Deve calcular posição do topo da área de conteúdo")
- void shouldCalculateTopPosition() {
- // Given
- float marginTop = 50f;
- float marginRight = 50f;
- float marginBottom = 50f;
- float marginLeft = 50f;
- float headerHeight = 30f;
- SafeArea safeArea = new SafeArea.Builder(PDRectangle.A4)
- .margins(marginTop, marginRight, marginBottom, marginLeft)
- .headerHeight(headerHeight)
- .build();
-
- // When
- float topY = safeArea.moveToTop();
-
- // Then
- float expectedY = PDRectangle.A4.getHeight() - marginTop - headerHeight;
- assertEquals(expectedY, topY, 0.1);
- }
-}