Add API to support multiple boxes

This commit is contained in:
Paul Campbell 2020-05-20 19:01:23 +01:00
parent 0af994b707
commit ccae310017
3 changed files with 151 additions and 42 deletions

View file

@ -5,6 +5,7 @@ import java.awt.font.FontRenderContext;
import java.awt.geom.Rectangle2D; import java.awt.geom.Rectangle2D;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -17,12 +18,30 @@ class TextLineWrapImpl implements WordWrapper {
Graphics2D graphics2D, Graphics2D graphics2D,
int width int width
) { ) {
String source = String.join(" ", text.split("\n")); return wrap(text, font, graphics2D,
List<Word> words = wordLengths(source.split(" "), font, graphics2D); Collections.singletonList(
return wrapWords(words, width); new Rectangle(width, width)))
.get(0);
} }
private List<String> wrapWords(List<Word> words, int width) { @Override
public List<List<String>> wrap(
String text,
Font font,
Graphics2D graphics2D,
List<Rectangle2D> boxes
) {
String source = String.join(" ", text.split("\n"));
List<Word> words = wordLengths(source.split(" "), font, graphics2D);
return wrapWords(words, boxes);
}
private List<List<String>> wrapWords(
List<Word> words,
List<Rectangle2D> boxes
) {
Rectangle2D rectangle2D = boxes.get(0);
double width = rectangle2D.getWidth();
List<String> lines = new ArrayList<>(); List<String> lines = new ArrayList<>();
int end = 0; int end = 0;
List<String> line = new ArrayList<>(); List<String> line = new ArrayList<>();
@ -36,9 +55,10 @@ class TextLineWrapImpl implements WordWrapper {
end += word.width; end += word.width;
} }
lines.add(String.join(" ", line)); lines.add(String.join(" ", line));
return lines.stream() return Collections.singletonList(
.filter(l -> l.length() > 0) lines.stream()
.collect(Collectors.toList()); .filter(l -> l.length() > 0)
.collect(Collectors.toList()));
} }
private List<Word> wordLengths(String[] words, Font font, Graphics2D graphics2D) { private List<Word> wordLengths(String[] words, Font font, Graphics2D graphics2D) {

View file

@ -1,6 +1,7 @@
package net.kemitix.text.fit; package net.kemitix.text.fit;
import java.awt.*; import java.awt.*;
import java.awt.geom.Rectangle2D;
import java.util.List; import java.util.List;
public interface WordWrapper { public interface WordWrapper {
@ -10,4 +11,10 @@ public interface WordWrapper {
Graphics2D graphics2D, Graphics2D graphics2D,
int width int width
); );
List<List<String>> wrap(
String text,
Font font,
Graphics2D graphics2D,
List<Rectangle2D> boxes
);
} }

View file

@ -1,15 +1,21 @@
package net.kemitix.text.fit; package net.kemitix.text.fit;
import org.assertj.core.api.WithAssertions; import org.assertj.core.api.WithAssertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.Nested;
import java.awt.*; import java.awt.*;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.net.URL; import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List; import java.util.List;
public class TextLineWrapTest public class TextLineWrapTest
@ -30,44 +36,49 @@ public class TextLineWrapTest
.deriveFont(Font.PLAIN, fontSize); .deriveFont(Font.PLAIN, fontSize);
} }
private List<String> invoke(String in) { @Nested
return textLineWrap.wrap(in, font, graphics2D, imageSize); @DisplayName("Single box")
} public class SingleBox {
@Test private List<String> invoke(String in) {
@DisplayName("Empty String give empty List") return textLineWrap.wrap(in, font, graphics2D, imageSize);
public void emptyStringEmptyList() { }
assertThat(invoke("")).isEmpty();
}
@Test @Test
@DisplayName("Short string fits on one line") @DisplayName("Empty String give empty List")
public void shortStringOnOneLine() { public void emptyStringEmptyList() {
assertThat(invoke("x")).containsExactly("x"); assertThat(invoke("")).isEmpty();
} }
@Test @Test
@DisplayName("Longer string fits on two lines") @DisplayName("Short string fits on one line")
public void longerStringOnTwoLines() { public void shortStringOnOneLine() {
assertThat(invoke( assertThat(invoke("x")).containsExactly("x");
"xxxxxxxxxxx xxxxxxxxxxxx " + }
"xxxxxxxxxxx xxxxxxxxxxxx"))
.containsExactly(
"xxxxxxxxxxx xxxxxxxxxxxx",
"xxxxxxxxxxx xxxxxxxxxxxx");
}
@Test @Test
@DisplayName("Longer string fits on three lines") @DisplayName("Longer string fits on two lines")
public void longerStringOnThreeLines() { public void longerStringOnTwoLines() {
assertThat(invoke( assertThat(invoke(
"xxxxxxxxxxx xxxxxxxxxxxx " + "xxxxxxxxxxx xxxxxxxxxxxx " +
"xxxxxxxxxxx xxxxxxxxxxxx " + "xxxxxxxxxxx xxxxxxxxxxxx"))
"xxxxxxxxxxx xxxxxxxxxxxx")) .containsExactly(
.containsExactly( "xxxxxxxxxxx xxxxxxxxxxxx",
"xxxxxxxxxxx xxxxxxxxxxxx", "xxxxxxxxxxx xxxxxxxxxxxx");
"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) { private Graphics2D graphics(int width, int height) {
@ -78,4 +89,75 @@ public class TextLineWrapTest
private BufferedImage image(int width, int height) { private BufferedImage image(int width, int height) {
return new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); return new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
} }
@Nested
@DisplayName("Overflowing Boxes")
public class OverflowingBoxes {
private List<Rectangle2D> boxes = new ArrayList<>();
private List<List<String>> 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);
}
}
}
} }