Skip to content

Commit 1dd361b

Browse files
authored
Supports toilet (tlf) fonts (#7)
* Adds test that generates the FONTS.md file * Preliminary support of toilet fonts (tlf) (non zipped) These files are similar to figlet fonts, but they have noticeable differences - header is `tlf2` - endmark may differ for each character - the font can be zipped * Supports of zipped toilet fonts (tlf) * Slight zip file reading code improvement
1 parent 8ff2baf commit 1dd361b

25 files changed

+4156
-17
lines changed

docs/FONTS.md

+207
Original file line numberDiff line numberDiff line change
@@ -4456,3 +4456,210 @@ BananaUtils.bananaify("Hello, World!", Font.WOW);
44564456
```
44574457
][-][ ]E ][_ ][_ [[]] , \\/\\/ [[]] ][2 ][_ ][_) !!1
44584458
```
4459+
4460+
Circle
4461+
4462+
```java
4463+
BananaUtils.bananaify("Hello, World!", Font.CIRCLE);
4464+
```
4465+
4466+
```
4467+
Ⓗⓔⓛⓛⓞ, Ⓦⓞⓡⓛⓓ!
4468+
```
4469+
4470+
Emboss
4471+
4472+
```java
4473+
BananaUtils.bananaify("Hello, World!", Font.EMBOSS);
4474+
```
4475+
4476+
```
4477+
┃ ┃┏━┛┃ ┃ ┏━┃ ┃┃┃┏━┃┏━┃┃ ┏━ ┃
4478+
┏━┃┏━┛┃ ┃ ┃ ┃ ┃┃┃┃ ┃┏┏┛┃ ┃ ┃┛
4479+
┛ ┛━━┛━━┛━━┛━━┛, ━━┛━━┛┛ ┛━━┛━━ ┛
4480+
```
4481+
4482+
Emboss 2
4483+
4484+
```java
4485+
BananaUtils.bananaify("Hello, World!", Font.EMBOSS2);
4486+
```
4487+
4488+
```
4489+
║ ║╔═╝║ ║ ╔═║ ║║║╔═║╔═║║ ╔═ ║
4490+
╔═║╔═╝║ ║ ║ ║ ║║║║ ║╔╔╝║ ║ ║╝
4491+
╝ ╝══╝══╝══╝══╝, ══╝══╝╝ ╝══╝══ ╝
4492+
```
4493+
4494+
Future
4495+
4496+
```java
4497+
BananaUtils.bananaify("Hello, World!", Font.FUTURE);
4498+
```
4499+
4500+
```
4501+
╻ ╻┏━╸╻ ╻ ┏━┓ ╻ ╻┏━┓┏━┓╻ ╺┳┓╻
4502+
┣━┫┣╸ ┃ ┃ ┃ ┃ ┃╻┃┃ ┃┣┳┛┃ ┃┃╹
4503+
╹ ╹┗━╸┗━╸┗━╸┗━┛ ┛ ┗┻┛┗━┛╹┗╸┗━╸╺┻┛╹
4504+
```
4505+
4506+
Pagga
4507+
4508+
```java
4509+
BananaUtils.bananaify("Hello, World!", Font.PAGGA);
4510+
```
4511+
4512+
```
4513+
░█░█░█▀▀░█░░░█░░░█▀█░░░░░░░█░█░█▀█░█▀▄░█░░░█▀▄░█
4514+
░█▀█░█▀▀░█░░░█░░░█░█░░░░░░░█▄█░█░█░█▀▄░█░░░█░█░▀
4515+
░▀░▀░▀▀▀░▀▀▀░▀▀▀░▀▀▀░▄▀░░░░▀░▀░▀▀▀░▀░▀░▀▀▀░▀▀░░▀
4516+
```
4517+
4518+
Rusto
4519+
4520+
```java
4521+
BananaUtils.bananaify("Hello, World!", Font.RUSTO);
4522+
```
4523+
4524+
```
4525+
┬ ┬┬─┐┬ ┬ ┌─┐ ┐ ┬┌─┐┬─┐┬ ┬─┐┐
4526+
│─┤├─ │ │ │ │ ││││ ││┬┘│ │ ││
4527+
┆ ┴┴─┘┆─┘┆─┘┘─┘┘ └┴┆┘─┘┆└┘┆─┘┆─┘o
4528+
```
4529+
4530+
Rusto Fat
4531+
4532+
```java
4533+
BananaUtils.bananaify("Hello, World!", Font.RUSTO_FAT);
4534+
```
4535+
4536+
```
4537+
┳ ┳┳━┓┳ ┳ ┏━┓ ┓ ┳┏━┓┳━┓┳ ┳━┓┓
4538+
┃━┫┣━ ┃ ┃ ┃ ┃ ┃┃┃┃ ┃┃┳┛┃ ┃ ┃┃
4539+
┇ ┻┻━┛┇━┛┇━┛┛━┛┛ ┗┻┇┛━┛┇┗┛┇━┛┇━┛o
4540+
```
4541+
4542+
ASCII 9
4543+
4544+
```java
4545+
BananaUtils.bananaify("Hello, World!", Font.ASCII9);
4546+
```
4547+
4548+
```
4549+
4550+
m m ""# ""# m m ""# # m
4551+
# # mmm # # mmm # # # mmm m mm # mmm# #
4552+
#mmmm# #" # # # #" "# " #"# # #" "# #" " # #" "# #
4553+
# # #"""" # # # # ## ##" # # # # # # "
4554+
# # "#mm" "mm "mm "#m#" # # # "#m#" # "mm "#m## #
4555+
"
4556+
4557+
```
4558+
4559+
ASCII 12
4560+
4561+
```java
4562+
BananaUtils.bananaify("Hello, World!", Font.ASCII12);
4563+
```
4564+
4565+
```
4566+
4567+
mm mm mmmm mmmm mm mm mmmm mm mm
4568+
## ## ""## ""## ## ## ""## ## ##
4569+
## ## m####m ## ## m####m "#m ## m#" m####m ##m#### ## m###m## ##
4570+
######## ##mmmm## ## ## ##" "## ## ## ## ##" "## ##" ## ##" "## ##
4571+
## ## ##"""""" ## ## ## ## ###""### ## ## ## ## ## ## ""
4572+
## ## "##mmmm# ##mmm ##mmm "##mm##" ## ### ### "##mm##" ## ##mmm "##mm### mm
4573+
"" "" """"" """" """" """" ## """ """ """" "" """" """ "" ""
4574+
""
4575+
4576+
```
4577+
4578+
Big ASCII 9
4579+
4580+
```java
4581+
BananaUtils.bananaify("Hello, World!", Font.BIG_ASCII9);
4582+
```
4583+
4584+
```
4585+
4586+
4587+
### ### ### #
4588+
# # # # # # # # #
4589+
# # # # #. # .# # # #
4590+
# # ### # # ### #.:#:.# ### #:##: # ## # #
4591+
# # :# # # # # :###:# # # ## # # # # #
4592+
###### # # # # # # ::#:#: # # # # # # #
4593+
# # ##### # # # # :## ## # # # # # # #
4594+
# # # # # # # :# #: # # # # # #
4595+
# # # #. #. # # # .#: :#: # # # #. # # #
4596+
# # ###: :## :## ### .# # #: ### # :## ## # #
4597+
#:
4598+
4599+
4600+
```
4601+
4602+
Big ASCII 12
4603+
4604+
```java
4605+
BananaUtils.bananaify("Hello, World!", Font.BIG_ASCII12);
4606+
```
4607+
4608+
```
4609+
4610+
4611+
4612+
## ## #### #### ## ## #### ## ##
4613+
## ## #### #### ##. .## #### ## ##
4614+
## ## ## ## ##: :## ## ## ##
4615+
## ## .####: ## ## .####. #: ## :# .####. ##.#### ## :###.## ##
4616+
## ## .######: ## ## .######. :# .## ##: .######. ####### ## :####### ##
4617+
######## ##: :## ## ## ### ### :##.##.##: ### ### ###. ## ### ### ##
4618+
######## ######## ## ## ##. .## .##:##:##. ##. .## ## ## ##. .## ##
4619+
## ## ######## ## ## ## ## ## ##. ## ## ## ## ## ## ##
4620+
## ## ## ## ## ##. .## ###::### ##. .## ## ## ##. .##
4621+
## ## ###. :# ##: ##: ### ### ## ###..### ### ### ## ##: ### ###
4622+
## ## .####### ##### ##### .######. ## ### ### .######. ## ##### :####### ##
4623+
## ## .#####: .#### .#### .####. .## ## ### .####. ## .#### :###.## ##
4624+
:#
4625+
##.
4626+
4627+
4628+
```
4629+
4630+
Small ASCII 9
4631+
4632+
```java
4633+
BananaUtils.bananaify("Hello, World!", Font.SMALL_ASCII9);
4634+
```
4635+
4636+
```
4637+
4638+
. , 'T 'T , , 'T ] .
4639+
] [ m, ] ] m, [] [ m, ,m ] md ]
4640+
]mm[]`] ] ] ]`T `P[[]`T P ` ] ]`T ]
4641+
] []"" ] ] ] ] ][W`] ] [ ] ] ] '
4642+
] ['b/ 'm 'm 'bP ] ] ] 'bP [ 'm 'bW ]
4643+
`
4644+
4645+
```
4646+
4647+
Small ASCII 12
4648+
4649+
```java
4650+
BananaUtils.bananaify("Hello, World!", Font.SMALL_ASCII12);
4651+
```
4652+
4653+
```
4654+
4655+
., ., .m, .m, m m .m, ., m
4656+
][ ][ 'T[ 'T[ W W 'T[ ][ W
4657+
][ ][ dWb ][ ][ dWb T,W.P dWb WdW[ ][ dWd[ W
4658+
]WWW[]bmd[ ][ ][ ]P T[ ][W][]P T[ W` ][ ]P T[ W
4659+
][ ][]P""` ][ ][ ][ ][ ]W"W[][ ][ W ][ ][ ][ "
4660+
][ ]['Wmm[ ]bm ]bm 'WmW` W ]W W['WmW` W ]bm 'WmW[ m
4661+
'` '` '"" "" "" '"` W '" "` '"` " "" '"'` "
4662+
'`
4663+
4664+
```
4665+

pom.xml

+9
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,15 @@
6363
<nexus-staging-maven-plugin.version>1.6.8</nexus-staging-maven-plugin.version>
6464
</properties>
6565

66+
<dependencies>
67+
<dependency>
68+
<groupId>junit</groupId>
69+
<artifactId>junit</artifactId>
70+
<version>4.13.1</version>
71+
<scope>test</scope>
72+
</dependency>
73+
</dependencies>
74+
6675
<profiles>
6776
<profile>
6877
<id>dev</id>

src/main/java/io/leego/banana/BananaUtils.java

+53-17
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,11 @@
11
package io.leego.banana;
22

3-
import java.io.BufferedReader;
4-
import java.io.IOException;
5-
import java.io.InputStream;
6-
import java.io.InputStreamReader;
7-
import java.util.ArrayList;
8-
import java.util.HashMap;
9-
import java.util.List;
10-
import java.util.Map;
3+
import java.io.*;
4+
import java.util.*;
115
import java.util.concurrent.ConcurrentHashMap;
126
import java.util.concurrent.ConcurrentMap;
7+
import java.util.zip.ZipEntry;
8+
import java.util.zip.ZipInputStream;
139

1410
/**
1511
* Banana is a FIGlet utility for Java.
@@ -192,21 +188,22 @@ private static Meta getMeta(Font font) {
192188
private static Meta buildMeta(Font font) {
193189
// Reads file content.
194190
List<String> data = new ArrayList<>();
195-
try {
196-
String path = Constants.FONT_DIR_PATH + font.getFilename();
197-
InputStream inputStream = BananaUtils.class.getClassLoader().getResourceAsStream(path);
191+
String path = Constants.FONT_DIR_PATH + font.getFilename();
192+
193+
try (InputStream resourceStream = BananaUtils.class.getClassLoader().getResourceAsStream(path);
194+
InputStream inputStream = unwrapZippedFontIfNecessary(resourceStream)) {
198195
if (inputStream == null) {
199196
return null;
200197
}
201198
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, font.getCharset());
202199
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
200+
203201
String line;
204202
while ((line = bufferedReader.readLine()) != null) {
205203
data.add(line);
206204
}
207205
bufferedReader.close();
208206
inputStreamReader.close();
209-
inputStream.close();
210207
} catch (IOException e) {
211208
throw new RuntimeException("Failed to load font \"" + font.getName() + "\"", e);
212209
}
@@ -233,10 +230,8 @@ private static Meta buildMeta(Font font) {
233230
List<Integer> codes = Constants.CODES;
234231
int height = option.getHeight();
235232
Map<Integer, String[]> figletMap = new HashMap<>(codes.size());
236-
String mark = data.get(num).substring(data.get(num).length() - 1);
237-
if (isEmpty(mark)) {
238-
mark = "@";
239-
}
233+
234+
// read font character
240235
for (int i = 0; i < codes.size(); i++) {
241236
Integer code = codes.get(i);
242237
if (i * height + num >= data.size()) {
@@ -250,13 +245,54 @@ private static Meta buildMeta(Font font) {
250245
figletMap.remove(code);
251246
break;
252247
}
253-
figlet[j] = data.get(row).replaceAll("[" + mark + "]+$", EMPTY);
248+
String charRow = data.get(row);
249+
250+
// inspired by readfontchar method in figlet.c
251+
// https://github.com/cmatsuoka/figlet/blob/202a0a8110650a943f1125f536b3bb455cf72ee1/figlet.c#L1146-L1168
252+
// endmarks my differ for each characters in tlf files
253+
int charIndex = charRow.length() - 1; // starts at the end
254+
255+
while (charIndex >= 0 && Character.isWhitespace(charRow.charAt(charIndex))) { // remove trailing space
256+
charIndex--;
257+
}
258+
259+
char endChar = charRow.charAt(charIndex); // first endmark
260+
while (charIndex >= 0 && charRow.charAt(charIndex) == endChar) { // remove all endmarks
261+
charIndex--;
262+
}
263+
264+
figlet[j] = charRow.substring(0, charIndex + 1);
254265
}
255266
}
256267
data.clear();
257268
return new Meta(font, option, figletMap, comment.toString());
258269
}
259270

271+
private static InputStream unwrapZippedFontIfNecessary(InputStream inputStream) throws IOException {
272+
if (inputStream == null) {
273+
return null;
274+
}
275+
276+
// detects zipped font
277+
PushbackInputStream pushbackInputStream = new PushbackInputStream(inputStream, 4);
278+
byte[] buf = new byte[4];
279+
pushbackInputStream.read(buf, 0, 4);
280+
pushbackInputStream.unread(buf);
281+
282+
byte[] pkzipHeader = new byte[] {0x50, 0x4b, 0x03, 0x04};
283+
if (Arrays.equals(pkzipHeader, buf)) {
284+
ZipInputStream zipInputStream = new ZipInputStream(pushbackInputStream);
285+
// expects a single anonymous entry
286+
ZipEntry nextEntry = zipInputStream.getNextEntry();
287+
if (nextEntry == null) {
288+
return null;
289+
}
290+
return zipInputStream;
291+
} else {
292+
return pushbackInputStream;
293+
}
294+
}
295+
260296
private static String[] generateFigletLine(String text, Map<Integer, String[]> figletMap, Option option) {
261297
int height = option.getHeight();
262298
String[] output = new String[height];

src/main/java/io/leego/banana/Font.java

+16
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,22 @@ public enum Font {
287287
WET_LETTER("Wet Letter", "Wet_Letter.flf"),
288288
WHIMSY("Whimsy", "Whimsy.flf"),
289289
WOW("Wow", "Wow.flf"),
290+
291+
292+
CIRCLE("Circle", "circle.tlf"),
293+
EMBOSS("Emboss", "emboss.tlf"),
294+
EMBOSS2("Emboss 2", "emboss2.tlf"),
295+
FUTURE("Future", "future.tlf"),
296+
PAGGA("Pagga", "pagga.tlf"),
297+
RUSTO("Rusto", "rusto.tlf"),
298+
RUSTO_FAT("Rusto Fat", "rustofat.tlf"),
299+
300+
ASCII9("ASCII 9", "ascii9.tlf"),
301+
ASCII12("ASCII 12", "ascii12.tlf"),
302+
BIG_ASCII9("Big ASCII 9", "bigascii9.tlf"),
303+
BIG_ASCII12("Big ASCII 12", "bigascii12.tlf"),
304+
SMALL_ASCII9("Small ASCII 9", "smascii9.tlf"),
305+
SMALL_ASCII12("Small ASCII 12", "smascii12.tlf"),
290306
;
291307
private final String name;
292308
private final String filename;
56.3 KB
Binary file not shown.
42.1 KB
Binary file not shown.
83.2 KB
Binary file not shown.
61.7 KB
Binary file not shown.
94.1 KB
Binary file not shown.
69.7 KB
Binary file not shown.

0 commit comments

Comments
 (0)