使用PDFBox,给定如下标注的数据:[G]Glory be to [D]God [Em]the [C]Father,\n[G]And to [A]Christ the [D]Son,
,我正在创建如下吉他和弦表:
我的方法是遍历歌曲中的每个字符,并根据地图检查当前索引。每当地图有一个条目到那个字符索引,我们“跳”到上面的行,写和弦,然后跳下来。
setTextRise
方法看起来很有希望,但仍然不正确地处理水平间距:
下面是一个SSCCE (需要PDFBox库),它生成上面的PDF:
public static void main(String[] args) {
try {
String extracted_text = "Capo 1\n\n1\n[G]Glory be to [D]God [Em]the [C]Father,\n[G]And to [A]Christ the [D]Son,\n[B7]Glory to the [Em]Holy [C]Spirit—\n[D-D7]Ever [ G]One.\n\n2\nAs we view the vast creation,\nPlanned with wondrous skill,\nSo our hearts would move to worship,\nAnd be still.\n\n3\nBut, our God, how great Thy yearning\nTo have sons who love\nIn the Son e’en now to praise Thee,\nLove to prove!\n\n4\n’Twas Thy thought in revelation,\nTo present to men\nSecrets of Thine own affections,\nTheirs to win.\n\n5\nSo in Christ, through His redemption\n(Vanquished evil powers!)\nThou hast brought, in new creation,\nWorshippers!\n\n6\nGlory be to God the Father,\nAnd to Christ the Son,\nGlory to the Holy Spirit—\nEver One.\n".replaceAll("\n", "\r");
String[] lines = extracted_text.split("\\r");
ArrayList<SongLine> songlines = new ArrayList<>();
for(String s : lines) {
LinkedHashMap<Integer, String> chords = new LinkedHashMap();
StringBuilder line = new StringBuilder();
StringBuilder currentchord = null;
int index = 0;
for(char c : s.toCharArray()) {
if(currentchord != null) {
if(c == ']') {
chords.put(index, currentchord.toString());
currentchord = null;
} else {
currentchord.append(c);
}
} else {
if(c == '[') {
currentchord = new StringBuilder();
} else {
line.append(c);
index++;
}
}
}
SongLine sl = new SongLine();
if(chords.size() > 0)
sl.char_index_to_chords = chords;
sl.line = line.toString();
songlines.add(sl);
}
try (PDDocument doc = new PDDocument()) {
PDPage page = new PDPage();
PDPageContentStream pcs = new PDPageContentStream(doc, page);
int firstLineX = 25;
int firstLineY = 700;
boolean first = true;
float leading = 14.5f;
pcs.beginText();
pcs.newLineAtOffset(firstLineX, firstLineY);
pcs.setFont(PDType1Font.TIMES_ROMAN, 12);
pcs.setLeading(leading);
for(SongLine line : songlines) {
if(line.char_index_to_chords != null)
System.out.println(line.char_index_to_chords.toString());
System.out.println(line.line);
if(!first) {
pcs.newLine();
}
first = false;
if(line.char_index_to_chords != null) {
pcs.newLine();
}
for(int i = 0; i < line.line.length(); i++) {
pcs.showText(String.valueOf(line.line.charAt(i)));
if(line.char_index_to_chords != null && line.char_index_to_chords.containsKey(i)) {
pcs.setTextRise(12);
pcs.showText(line.char_index_to_chords.get(i));
pcs.setTextRise(0);
}
}
}
pcs.endText();
pcs.close();
doc.addPage(page);
String path = "0001.pdf";
doc.save(path);
Desktop.getDesktop().open(new File(path));
}
} catch (Exception e) {
e.printStackTrace();
}
}
static class SongLine {
Map<Integer, String> char_index_to_chords;
String line;
}
您将如何在PDFBox中创建与和弦对齐的文本(如第一个图像)?
发布于 2022-05-24 14:42:20
这样啊,原来是这么回事。答案不是setTextRise
,而是newLineAtOffset
,同时使用getStringWidth
计算字体大小:
for(SongLine line : songlines) {
if(!first) {
pcs.newLine();
}
first = false;
if(line.char_index_to_chords != null) {
float offset = 0;
for(Entry<Integer, String> entry : line.char_index_to_chords.entrySet()) {
float offsetX = font.getStringWidth(line.char_index_to_leading_lyrics.get(entry.getKey())) / (float)1000 * fontSize;
pcs.newLineAtOffset(offsetX, 0);
offset += offsetX;
pcs.showText(entry.getValue());
}
pcs.newLineAtOffset(-offset, -leading);
}
pcs.showText(line.line);
}
https://stackoverflow.com/questions/72357162
复制相似问题