diff --git a/src/test/java/net/kemitix/text/fit/TextLineWrapTest.java b/src/test/java/net/kemitix/text/fit/TextLineWrapTest.java index a1fbe4a..a4a116c 100644 --- a/src/test/java/net/kemitix/text/fit/TextLineWrapTest.java +++ b/src/test/java/net/kemitix/text/fit/TextLineWrapTest.java @@ -7,6 +7,7 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Nested; import java.awt.*; +import java.awt.font.FontRenderContext; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; import java.io.File; @@ -17,15 +18,23 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; public class TextLineWrapTest implements WithAssertions { + private static final String WORD = "word"; + private static final String SPACE = " "; + private final WordWrapper textLineWrap = TextFit.wrapper(); private final int imageSize = 300; private final int fontSize = 20; private final Graphics2D graphics2D = graphics(imageSize, imageSize); private final Font font; + private final int spaceWidth; + private final int wordWidth; + private final int wordsPerLine; public TextLineWrapTest() throws FontFormatException, @@ -34,6 +43,15 @@ public class TextLineWrapTest URL resource = this.getClass().getResource("alice/Alice-Regular.ttf"); font = Font.createFont(Font.TRUETYPE_FONT, new File(resource.toURI())) .deriveFont(Font.PLAIN, fontSize); + spaceWidth = stringWidth(SPACE, font, graphics2D); + wordWidth = stringWidth(WORD, font, graphics2D); + wordsPerLine = imageSize / (wordWidth + spaceWidth); + } + + private int stringWidth(String string, Font font, Graphics2D graphics2D) { + FontRenderContext context = graphics2D.getFontRenderContext(); + Rectangle2D stringBounds = font.getStringBounds(string, context); + return (int) stringBounds.getWidth(); } @Nested @@ -57,28 +75,37 @@ public class TextLineWrapTest } @Test - @DisplayName("Longer string fits on two lines") - public void longerStringOnTwoLines() { - assertThat(invoke( - "xxxxxxxxxxx xxxxxxxxxxxx " + - "xxxxxxxxxxx xxxxxxxxxxxx")) - .containsExactly( - "xxxxxxxxxxx xxxxxxxxxxxx", - "xxxxxxxxxxx xxxxxxxxxxxx"); + @DisplayName("Fits max 'words' per line on one line") + public void fitMaxWordsOneLine() { + String input = words(wordsPerLine); + assertThat(invoke(input)).containsExactly(input); } @Test - @DisplayName("Longer string fits on three lines") - public void longerStringOnThreeLines() { - assertThat(invoke( - "xxxxxxxxxxx xxxxxxxxxxxx " + - "xxxxxxxxxxx xxxxxxxxxxxx " + - "xxxxxxxxxxx xxxxxxxxxxxx")) + @DisplayName("Wraps just over max 'words' per line onto two lines") + public void wrapOneWordTooManyOntoTwoLines() { + assertThat(invoke(words(wordsPerLine + 1))) .containsExactly( - "xxxxxxxxxxx xxxxxxxxxxxx", - "xxxxxxxxxxx xxxxxxxxxxxx", - "xxxxxxxxxxx xxxxxxxxxxxx"); + words(wordsPerLine), + WORD); } + + @Test + @DisplayName("Wraps onto three lines") + public void longerStringOnThreeLines() { + String oneLinesWorthOfWords = words(wordsPerLine); + assertThat(invoke(words(wordsPerLine + wordsPerLine + 1))) + .containsExactly( + oneLinesWorthOfWords, + oneLinesWorthOfWords, + WORD); + } + } + + private String words(int number) { + return IntStream.range(0, number) + .mapToObj(i -> WORD + SPACE) + .collect(Collectors.joining()).trim(); } private Graphics2D graphics(int width, int height) { @@ -123,27 +150,31 @@ public class TextLineWrapTest } @Test - @DisplayName("Longer string fits on two lines") - public void longerStringOnTwoLines() { - assertThat(invoke( - "xxxxxxxxxxx xxxxxxxxxxxx " + - "xxxxxxxxxxx xxxxxxxxxxxx")) - .containsExactly(Arrays.asList( - "xxxxxxxxxxx xxxxxxxxxxxx", - "xxxxxxxxxxx xxxxxxxxxxxx")); + @DisplayName("Fits max 'words' per line on one line") + public void fitMaxWordsOneLine() { + String input = words(wordsPerLine); + assertThat(invoke(input)) + .containsExactly(Collections.singletonList(input)); } @Test - @DisplayName("Longer string fits on three lines") + @DisplayName("Wraps just over max 'words' per line onto two lines") + public void wrapOneWordTooManyOntoTwoLines() { + String input = words(wordsPerLine + 1); + assertThat(invoke(input)).containsExactly(Arrays.asList( + words(wordsPerLine), + WORD)); + } + + @Test + @DisplayName("Wraps onto three lines") public void longerStringOnThreeLines() { - assertThat(invoke( - "xxxxxxxxxxx xxxxxxxxxxxx " + - "xxxxxxxxxxx xxxxxxxxxxxx " + - "xxxxxxxxxxx xxxxxxxxxxxx")) - .containsExactly(Arrays.asList( - "xxxxxxxxxxx xxxxxxxxxxxx", - "xxxxxxxxxxx xxxxxxxxxxxx", - "xxxxxxxxxxx xxxxxxxxxxxx")); + String input = words(wordsPerLine + wordsPerLine + 1); + String oneLinesWorthOfWords = words(wordsPerLine); + assertThat(invoke(input)).containsExactly(Arrays.asList( + oneLinesWorthOfWords, + oneLinesWorthOfWords, + WORD)); } } @@ -158,6 +189,47 @@ public class TextLineWrapTest boxes.add(box); } + + @Test + @DisplayName("Empty String give empty List") + public void emptyStringEmptyList() { + assertThat(invoke("")).isEmpty(); + } + + @Test + @DisplayName("Short string fits on one line") + public void shortStringOnOneLine() { + assertThat(invoke("x")) + .containsExactly(Collections.singletonList("x")); + } + + @Test + @DisplayName("Fits max 'words' per line on one line") + public void fitMaxWordsOneLine() { + String input = words(wordsPerLine); + assertThat(invoke(input)) + .containsExactly(Collections.singletonList(input)); + } + + @Test + @DisplayName("Wraps just over max 'words' per line onto two lines") + public void wrapOneWordTooManyOntoTwoLines() { + String input = words(wordsPerLine + 1); + assertThat(invoke(input)).containsExactly(Arrays.asList( + words(wordsPerLine), + WORD)); + } + + @Test + @DisplayName("Wraps onto three lines") + public void longerStringOnThreeLines() { + String input = words(wordsPerLine + wordsPerLine + 1); + String oneLinesWorthOfWords = words(wordsPerLine); + assertThat(invoke(input)).containsExactly(Arrays.asList( + oneLinesWorthOfWords, + oneLinesWorthOfWords, + WORD)); + } } } } \ No newline at end of file