From ccae3100176c5430fb1a1fb1f497bdfc2dd61f5d Mon Sep 17 00:00:00 2001 From: Paul Campbell Date: Wed, 20 May 2020 19:01:23 +0100 Subject: [PATCH] Add API to support multiple boxes --- .../kemitix/text/fit/TextLineWrapImpl.java | 34 +++- .../net/kemitix/text/fit/WordWrapper.java | 7 + .../kemitix/text/fit/TextLineWrapTest.java | 152 ++++++++++++++---- 3 files changed, 151 insertions(+), 42 deletions(-) diff --git a/src/main/java/net/kemitix/text/fit/TextLineWrapImpl.java b/src/main/java/net/kemitix/text/fit/TextLineWrapImpl.java index 00bc9df..fb26357 100644 --- a/src/main/java/net/kemitix/text/fit/TextLineWrapImpl.java +++ b/src/main/java/net/kemitix/text/fit/TextLineWrapImpl.java @@ -5,6 +5,7 @@ import java.awt.font.FontRenderContext; import java.awt.geom.Rectangle2D; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.stream.Collectors; @@ -17,12 +18,30 @@ class TextLineWrapImpl implements WordWrapper { Graphics2D graphics2D, int width ) { - String source = String.join(" ", text.split("\n")); - List words = wordLengths(source.split(" "), font, graphics2D); - return wrapWords(words, width); + return wrap(text, font, graphics2D, + Collections.singletonList( + new Rectangle(width, width))) + .get(0); } - private List wrapWords(List words, int width) { + @Override + public List> wrap( + String text, + Font font, + Graphics2D graphics2D, + List boxes + ) { + String source = String.join(" ", text.split("\n")); + List words = wordLengths(source.split(" "), font, graphics2D); + return wrapWords(words, boxes); + } + + private List> wrapWords( + List words, + List boxes + ) { + Rectangle2D rectangle2D = boxes.get(0); + double width = rectangle2D.getWidth(); List lines = new ArrayList<>(); int end = 0; List line = new ArrayList<>(); @@ -36,9 +55,10 @@ class TextLineWrapImpl implements WordWrapper { end += word.width; } lines.add(String.join(" ", line)); - return lines.stream() - .filter(l -> l.length() > 0) - .collect(Collectors.toList()); + return Collections.singletonList( + lines.stream() + .filter(l -> l.length() > 0) + .collect(Collectors.toList())); } private List wordLengths(String[] words, Font font, Graphics2D graphics2D) { diff --git a/src/main/java/net/kemitix/text/fit/WordWrapper.java b/src/main/java/net/kemitix/text/fit/WordWrapper.java index a4d2a09..b17ffa1 100644 --- a/src/main/java/net/kemitix/text/fit/WordWrapper.java +++ b/src/main/java/net/kemitix/text/fit/WordWrapper.java @@ -1,6 +1,7 @@ package net.kemitix.text.fit; import java.awt.*; +import java.awt.geom.Rectangle2D; import java.util.List; public interface WordWrapper { @@ -10,4 +11,10 @@ public interface WordWrapper { Graphics2D graphics2D, int width ); + List> wrap( + String text, + Font font, + Graphics2D graphics2D, + List boxes + ); } diff --git a/src/test/java/net/kemitix/text/fit/TextLineWrapTest.java b/src/test/java/net/kemitix/text/fit/TextLineWrapTest.java index 48885b7..a1fbe4a 100644 --- a/src/test/java/net/kemitix/text/fit/TextLineWrapTest.java +++ b/src/test/java/net/kemitix/text/fit/TextLineWrapTest.java @@ -1,15 +1,21 @@ package net.kemitix.text.fit; import org.assertj.core.api.WithAssertions; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.Nested; import java.awt.*; +import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.net.URISyntaxException; import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; import java.util.List; public class TextLineWrapTest @@ -30,44 +36,49 @@ public class TextLineWrapTest .deriveFont(Font.PLAIN, fontSize); } - private List invoke(String in) { - return textLineWrap.wrap(in, font, graphics2D, imageSize); - } + @Nested + @DisplayName("Single box") + public class SingleBox { - @Test - @DisplayName("Empty String give empty List") - public void emptyStringEmptyList() { - assertThat(invoke("")).isEmpty(); - } + private List invoke(String in) { + return textLineWrap.wrap(in, font, graphics2D, imageSize); + } - @Test - @DisplayName("Short string fits on one line") - public void shortStringOnOneLine() { - assertThat(invoke("x")).containsExactly("x"); - } + @Test + @DisplayName("Empty String give empty List") + public void emptyStringEmptyList() { + assertThat(invoke("")).isEmpty(); + } - @Test - @DisplayName("Longer string fits on two lines") - public void longerStringOnTwoLines() { - assertThat(invoke( - "xxxxxxxxxxx xxxxxxxxxxxx " + - "xxxxxxxxxxx xxxxxxxxxxxx")) - .containsExactly( - "xxxxxxxxxxx xxxxxxxxxxxx", - "xxxxxxxxxxx xxxxxxxxxxxx"); - } + @Test + @DisplayName("Short string fits on one line") + public void shortStringOnOneLine() { + assertThat(invoke("x")).containsExactly("x"); + } - @Test - @DisplayName("Longer string fits on three lines") - public void longerStringOnThreeLines() { - assertThat(invoke( - "xxxxxxxxxxx xxxxxxxxxxxx " + - "xxxxxxxxxxx xxxxxxxxxxxx " + - "xxxxxxxxxxx xxxxxxxxxxxx")) - .containsExactly( - "xxxxxxxxxxx xxxxxxxxxxxx", - "xxxxxxxxxxx xxxxxxxxxxxx", - "xxxxxxxxxxx xxxxxxxxxxxx"); + @Test + @DisplayName("Longer string fits on two lines") + public void longerStringOnTwoLines() { + assertThat(invoke( + "xxxxxxxxxxx xxxxxxxxxxxx " + + "xxxxxxxxxxx xxxxxxxxxxxx")) + .containsExactly( + "xxxxxxxxxxx xxxxxxxxxxxx", + "xxxxxxxxxxx xxxxxxxxxxxx"); + } + + @Test + @DisplayName("Longer string fits on three lines") + public void longerStringOnThreeLines() { + assertThat(invoke( + "xxxxxxxxxxx xxxxxxxxxxxx " + + "xxxxxxxxxxx xxxxxxxxxxxx " + + "xxxxxxxxxxx xxxxxxxxxxxx")) + .containsExactly( + "xxxxxxxxxxx xxxxxxxxxxxx", + "xxxxxxxxxxx xxxxxxxxxxxx", + "xxxxxxxxxxx xxxxxxxxxxxx"); + } } private Graphics2D graphics(int width, int height) { @@ -78,4 +89,75 @@ public class TextLineWrapTest private BufferedImage image(int width, int height) { return new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); } -} + + @Nested + @DisplayName("Overflowing Boxes") + public class OverflowingBoxes { + + private List boxes = new ArrayList<>(); + + private List> invoke(String in) { + return textLineWrap.wrap(in, font, graphics2D, boxes); + } + + @Nested + @DisplayName("Single box") + public class SingleBox { + + @BeforeEach + public void setUp() { + boxes.add(new Rectangle(imageSize, imageSize)); + } + + @Test + @DisplayName("Empty String give empty List") + public void emptyStringEmptyList() { + assertThat(invoke("")).containsExactly(Collections.emptyList()); + } + + @Test + @DisplayName("Short string fits on one line") + public void shortStringOnOneLine() { + assertThat(invoke("x")) + .containsExactly(Collections.singletonList("x")); + } + + @Test + @DisplayName("Longer string fits on two lines") + public void longerStringOnTwoLines() { + assertThat(invoke( + "xxxxxxxxxxx xxxxxxxxxxxx " + + "xxxxxxxxxxx xxxxxxxxxxxx")) + .containsExactly(Arrays.asList( + "xxxxxxxxxxx xxxxxxxxxxxx", + "xxxxxxxxxxx xxxxxxxxxxxx")); + } + + @Test + @DisplayName("Longer string fits on three lines") + public void longerStringOnThreeLines() { + assertThat(invoke( + "xxxxxxxxxxx xxxxxxxxxxxx " + + "xxxxxxxxxxx xxxxxxxxxxxx " + + "xxxxxxxxxxx xxxxxxxxxxxx")) + .containsExactly(Arrays.asList( + "xxxxxxxxxxx xxxxxxxxxxxx", + "xxxxxxxxxxx xxxxxxxxxxxx", + "xxxxxxxxxxx xxxxxxxxxxxx")); + } + } + + @Nested + @DisplayName("Two boxes of equal width") + public class TwoEqualWidthBoxes { + + @BeforeEach + public void setUp() { + Rectangle box = new Rectangle(imageSize, imageSize); + boxes.add(box); + boxes.add(box); + } + + } + } +} \ No newline at end of file