您如何正确使用pdpagecontentstream :: settextrise?

发布于 2025-02-01 05:22:38 字数 4489 浏览 4 评论 0原文

使用PDFBox,给定的数据如下:[g]荣耀是[d]上帝[em] [c]父亲,\ n [g]和[a]基督[d]儿子代码>,我正在创建一个吉他和弦表:

“在此处输入图像描述”

我的方法是通过歌曲中的每个字符迭代并检查针对地图的当前索引。字符索引,我们“跳到”上方的线,写和弦,然后跳下来。

方法setTextrise看起来很有希望,但仍然不正确地处理水平间距:

这是一个SSCCE(需要PDFBox库),该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中做什么创建与和弦对齐的文本(例如第一个图像中)?

Using PDFBox, given data notated like this: [G]Glory be to [D]God [Em]the [C]Father,\n[G]And to [A]Christ the [D]Son,, I am creating a guitar chord sheet like this:

enter image description here

My approach was to iterate through each character in the song and check the current index against the map.. whenever the map has an entry to that character index, we "jump" to the line above, write the chord, then jump back down.

The method setTextRise looked promising, but still processes the horizontal spacing incorrectly:

enter image description here

Here's an SSCCE (needs PDFBox libraries) that produces the PDF above:

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;
}

What would you do in PDFBox to create the text aligned with chords (like in the first image)?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

诗化ㄋ丶相逢 2025-02-08 05:22:38

我得到了它。答案不是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);
}

I got it. The answer was not setTextRise, rather newLineAtOffset while using getStringWidth to calculate font size:

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);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文