Author: tilman Date: Sat Jul 4 13:31:20 2026 New Revision: 1935881 Log: PDFBOX-4951: add tests, by Volker Kunert; move resources to test for now
Added: pdfbox/trunk/pdfbox-layout-awt/src/test/appended-resources/ pdfbox/trunk/pdfbox-layout-awt/src/test/appended-resources/META-INF/ pdfbox/trunk/pdfbox-layout-awt/src/test/appended-resources/META-INF/LICENSE (contents, props changed) pdfbox/trunk/pdfbox-layout-awt/src/test/java/org/ pdfbox/trunk/pdfbox-layout-awt/src/test/java/org/apache/ pdfbox/trunk/pdfbox-layout-awt/src/test/java/org/apache/pdfbox/ pdfbox/trunk/pdfbox-layout-awt/src/test/java/org/apache/pdfbox/glyphlayout/ pdfbox/trunk/pdfbox-layout-awt/src/test/java/org/apache/pdfbox/glyphlayout/GlyphLayoutBidiTest.java (contents, props changed) pdfbox/trunk/pdfbox-layout-awt/src/test/java/org/apache/pdfbox/glyphlayout/GlyphLayoutDin91379FormTest.java (contents, props changed) pdfbox/trunk/pdfbox-layout-awt/src/test/java/org/apache/pdfbox/glyphlayout/GlyphLayoutDin91379Test.java (contents, props changed) pdfbox/trunk/pdfbox-layout-awt/src/test/java/org/apache/pdfbox/glyphlayout/GlyphLayoutLigaturesAndKerningTest.java (contents, props changed) pdfbox/trunk/pdfbox-layout-awt/src/test/resources/ pdfbox/trunk/pdfbox-layout-awt/src/test/resources/pdf/ pdfbox/trunk/pdfbox-layout-awt/src/test/resources/pdf/PdfForm.pdf (contents, props changed) pdfbox/trunk/pdfbox-layout-awt/src/test/resources/ttf/ pdfbox/trunk/pdfbox-layout-awt/src/test/resources/ttf/DejaVuSans.ttf (contents, props changed) pdfbox/trunk/pdfbox-layout-awt/src/test/resources/ttf/FiraCode-Regular.ttf (contents, props changed) pdfbox/trunk/pdfbox-layout-awt/src/test/resources/ttf/Lohit-Bengali.ttf (contents, props changed) pdfbox/trunk/pdfbox-layout-awt/src/test/resources/ttf/NotoSansArabic-Regular.ttf (contents, props changed) Added: pdfbox/trunk/pdfbox-layout-awt/src/test/appended-resources/META-INF/LICENSE ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ pdfbox/trunk/pdfbox-layout-awt/src/test/appended-resources/META-INF/LICENSE Sat Jul 4 13:31:20 2026 (r1935881) @@ -0,0 +1,278 @@ +Lohit fonts (https://pagure.io/lohit): + + Copyright 2011-15 Lohit Fonts Project contributors + + This Font Software is licensed under the SIL Open Font License, Version 1.1. + This license is copied below, and is also available with a FAQ at: + http://scripts.sil.org/OFL + + + ----------------------------------------------------------- + SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 + ----------------------------------------------------------- + + PREAMBLE + The goals of the Open Font License (OFL) are to stimulate worldwide + development of collaborative font projects, to support the font creation + efforts of academic and linguistic communities, and to provide a free and + open framework in which fonts may be shared and improved in partnership + with others. + + The OFL allows the licensed fonts to be used, studied, modified and + redistributed freely as long as they are not sold by themselves. The + fonts, including any derivative works, can be bundled, embedded, + redistributed and/or sold with any software provided that any reserved + names are not used by derivative works. The fonts and derivatives, + however, cannot be released under any other type of license. The + requirement for fonts to remain under this license does not apply + to any document created using the fonts or their derivatives. + + DEFINITIONS + "Font Software" refers to the set of files released by the Copyright + Holder(s) under this license and clearly marked as such. This may + include source files, build scripts and documentation. + + "Reserved Font Name" refers to any names specified as such after the + copyright statement(s). + + "Original Version" refers to the collection of Font Software components as + distributed by the Copyright Holder(s). + + "Modified Version" refers to any derivative made by adding to, deleting, + or substituting -- in part or in whole -- any of the components of the + Original Version, by changing formats or by porting the Font Software to a + new environment. + + "Author" refers to any designer, engineer, programmer, technical + writer or other person who contributed to the Font Software. + + PERMISSION & CONDITIONS + Permission is hereby granted, free of charge, to any person obtaining + a copy of the Font Software, to use, study, copy, merge, embed, modify, + redistribute, and sell modified and unmodified copies of the Font + Software, subject to the following conditions: + + 1) Neither the Font Software nor any of its individual components, + in Original or Modified Versions, may be sold by itself. + + 2) Original or Modified Versions of the Font Software may be bundled, + redistributed and/or sold with any software, provided that each copy + contains the above copyright notice and this license. These can be + included either as stand-alone text files, human-readable headers or + in the appropriate machine-readable metadata fields within text or + binary files as long as those fields can be easily viewed by the user. + + 3) No Modified Version of the Font Software may use the Reserved Font + Name(s) unless explicit written permission is granted by the corresponding + Copyright Holder. This restriction only applies to the primary font name as + presented to the users. + + 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font + Software shall not be used to promote, endorse or advertise any + Modified Version, except to acknowledge the contribution(s) of the + Copyright Holder(s) and the Author(s) or with their explicit written + permission. + + 5) The Font Software, modified or unmodified, in part or in whole, + must be distributed entirely under this license, and must not be + distributed under any other license. The requirement for fonts to + remain under this license does not apply to any document created + using the Font Software. + + TERMINATION + This license becomes null and void if any of the above conditions are + not met. + + DISCLAIMER + THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT + OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE + COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL + DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM + OTHER DEALINGS IN THE FONT SOFTWARE. + + +FiraCode font: + +Copyright (c) 2014, The Fira Code Project Authors (https://github.com/tonsky/FiraCode) +SIL Open Font License, see above + + +NotoSans Arabic font: + +Copyright 2022 The Noto Project Authors (https://github.com/notofonts/arabic) +SIL Open Font License, see above + + +Licenses for DejaVu font(s) (see also https://www.apache.org/legal/resolved.html ): + +Fonts are (c) Bitstream (see below). DejaVu changes are in public domain. +Glyphs imported from Arev fonts are (c) Tavmjong Bah (see below) + + +Bitstream Vera Fonts Copyright +------------------------------ + +Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is +a trademark of Bitstream, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of the fonts accompanying this license ("Fonts") and associated +documentation files (the "Font Software"), to reproduce and distribute the +Font Software, including without limitation the rights to use, copy, merge, +publish, distribute, and/or sell copies of the Font Software, and to permit +persons to whom the Font Software is furnished to do so, subject to the +following conditions: + +The above copyright and trademark notices and this permission notice shall +be included in all copies of one or more of the Font Software typefaces. + +The Font Software may be modified, altered, or added to, and in particular +the designs of glyphs or characters in the Fonts may be modified and +additional glyphs or characters may be added to the Fonts, only if the fonts +are renamed to names not containing either the words "Bitstream" or the word +"Vera". + +This License becomes null and void to the extent applicable to Fonts or Font +Software that has been modified and is distributed under the "Bitstream +Vera" names. + +The Font Software may be sold as part of a larger software package but no +copy of one or more of the Font Software typefaces may be sold by itself. + +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, +TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME +FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING +ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE +FONT SOFTWARE. + +Except as contained in this notice, the names of Gnome, the Gnome +Foundation, and Bitstream Inc., shall not be used in advertising or +otherwise to promote the sale, use or other dealings in this Font Software +without prior written authorization from the Gnome Foundation or Bitstream +Inc., respectively. For further information, contact: fonts at gnome dot org. + +Arev Fonts Copyright +------------------------------ + +Copyright (c) 2006 by Tavmjong Bah. All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of the fonts accompanying this license ("Fonts") and +associated documentation files (the "Font Software"), to reproduce +and distribute the modifications to the Bitstream Vera Font Software, +including without limitation the rights to use, copy, merge, publish, +distribute, and/or sell copies of the Font Software, and to permit +persons to whom the Font Software is furnished to do so, subject to +the following conditions: + +The above copyright and trademark notices and this permission notice +shall be included in all copies of one or more of the Font Software +typefaces. + +The Font Software may be modified, altered, or added to, and in +particular the designs of glyphs or characters in the Fonts may be +modified and additional glyphs or characters may be added to the +Fonts, only if the fonts are renamed to names not containing either +the words "Tavmjong Bah" or the word "Arev". + +This License becomes null and void to the extent applicable to Fonts +or Font Software that has been modified and is distributed under the +"Tavmjong Bah Arev" names. + +The Font Software may be sold as part of a larger software package but +no copy of one or more of the Font Software typefaces may be sold by +itself. + +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL +TAVMJONG BAH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. + +Except as contained in this notice, the name of Tavmjong Bah shall not +be used in advertising or otherwise to promote the sale, use or other +dealings in this Font Software without prior written authorization +from Tavmjong Bah. For further information, contact: tavmjong @ free . fr. + +TeX Gyre DJV Math +----------------- +Fonts are (c) Bitstream (see below). DejaVu changes are in public domain. + +Math extensions done by B. Jackowski, P. Strzelczyk and P. Pianowski +(on behalf of TeX users groups) are in public domain. + +Letters imported from Euler Fraktur from AMSfonts are (c) American Mathematical Society (see below). +Bitstream Vera Fonts Copyright +Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera +is a trademark of Bitstream, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of the fonts accompanying this license (“Fonts”) and associated documentation +files (the “Font Software”), to reproduce and distribute the Font Software, +including without limitation the rights to use, copy, merge, publish, distribute, +and/or sell copies of the Font Software, and to permit persons to whom +the Font Software is furnished to do so, subject to the following conditions: + +The above copyright and trademark notices and this permission notice shall be +included in all copies of one or more of the Font Software typefaces. + +The Font Software may be modified, altered, or added to, and in particular +the designs of glyphs or characters in the Fonts may be modified and additional +glyphs or characters may be added to the Fonts, only if the fonts are renamed +to names not containing either the words “Bitstream” or the word “Vera”. + +This License becomes null and void to the extent applicable to Fonts or Font Software +that has been modified and is distributed under the “Bitstream Vera” names. + +The Font Software may be sold as part of a larger software package but no copy +of one or more of the Font Software typefaces may be sold by itself. + +THE FONT SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, +TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME FOUNDATION +BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, +SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE +THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. +Except as contained in this notice, the names of GNOME, the GNOME Foundation, +and Bitstream Inc., shall not be used in advertising or otherwise to promote +the sale, use or other dealings in this Font Software without prior written +authorization from the GNOME Foundation or Bitstream Inc., respectively. +For further information, contact: fonts at gnome dot org. + +AMSFonts (v. 2.2) copyright + +The PostScript Type 1 implementation of the AMSFonts produced by and +previously distributed by Blue Sky Research and Y&Y, Inc. are now freely +available for general use. This has been accomplished through the cooperation +of a consortium of scientific publishers with Blue Sky Research and Y&Y. +Members of this consortium include: + +Elsevier Science IBM Corporation Society for Industrial and Applied +Mathematics (SIAM) Springer-Verlag American Mathematical Society (AMS) + +In order to assure the authenticity of these fonts, copyright will be held by +the American Mathematical Society. This is not meant to restrict in any way +the legitimate use of the fonts, such as (but not limited to) electronic +distribution of documents containing these fonts, inclusion of these fonts +into other public domain or commercial font collections or computer +applications, use of the outline data to create derivative fonts and/or +faces, etc. However, the AMS does require that the AMS copyright notice be +removed from any derivative versions of the fonts which have been altered in +any way. In addition, to ensure the fidelity of TeX documents using Computer +Modern fonts, Professor Donald Knuth, creator of the Computer Modern faces, +has requested that any alterations which yield different font metrics be +given a different name. \ No newline at end of file Added: pdfbox/trunk/pdfbox-layout-awt/src/test/java/org/apache/pdfbox/glyphlayout/GlyphLayoutBidiTest.java ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ pdfbox/trunk/pdfbox-layout-awt/src/test/java/org/apache/pdfbox/glyphlayout/GlyphLayoutBidiTest.java Sat Jul 4 13:31:20 2026 (r1935881) @@ -0,0 +1,117 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.pdfbox.glyphlayout; + +import org.junit.jupiter.api.Test; + +import java.awt.FontFormatException; +import java.io.IOException; +import java.io.InputStream; + +import org.apache.pdfbox.pdmodel.PDDocument; +import org.apache.pdfbox.pdmodel.PDPage; +import org.apache.pdfbox.pdmodel.PDPageContentStream; +import org.apache.pdfbox.pdmodel.font.PDType0Font; + +/** + * Examples for bidirectional text with GlyphLayoutProcessorAwt + * + * @author Volker Kunert + */ +public class GlyphLayoutBidiTest +{ + public static final String TEXT1 = "نحن الآن في شهر رمضان 1447 هجري"; + public static final String TEXT2 = "Guten Tag "; + public static final String TEXT3 = "السلام عليكم"; + public static final String TEXT4 = " Good afternoon"; + + /* + * show one line + */ + private float showLine(PDPageContentStream cs, PDType0Font font, float fontSize, + float x, float y, String text) throws IOException + { + return showLine(cs, new PDType0Font[]{font}, fontSize, x, y, new String[]{text}); + } + + /* + * show one line + */ + private float showLine(PDPageContentStream cs, PDType0Font[] fonts, float fontSize, + float x, float y, String[] texts) throws IOException + { + cs.beginText(); + cs.newLineAtOffset(x, y); + + if (fonts.length != texts.length) + { + throw new IllegalArgumentException("Size of fonts and texts is different"); + } + for (int i = 0; i < texts.length; i++) + { + cs.setFont(fonts[i], fontSize); + cs.showText(texts[i]); + } + cs.endText(); + + float height = fonts[0].getBoundingBox().getHeight(); + y -= height / 1000f * fontSize; + return y; + } + + @Test + void testGlyphLayoutBidi() throws IOException, FontFormatException + { + GlyphLayoutProcessorAwt glyphLayoutProcessorAwt = new GlyphLayoutProcessorAwt(); + + String outputFilename = "target/GlyphLayoutBidi.pdf"; + String arabicPath = "/ttf/NotoSansArabic-Regular.ttf"; + String lgcPath = "/ttf/DejaVuSans.ttf"; + + float fontSize = 12.0f; + + try (PDDocument doc = new PDDocument()) + { + PDType0Font arabicFont = createPdType0Font(glyphLayoutProcessorAwt, doc, arabicPath); + PDType0Font lgcFont = createPdType0Font(glyphLayoutProcessorAwt, doc, lgcPath); + + PDPage page = new PDPage(); + doc.addPage(page); + try (PDPageContentStream cs = new PDPageContentStream(doc, page)) + { + cs.setGlyphLayoutProcessor(glyphLayoutProcessorAwt); + + float x = page.getBBox().getLowerLeftX() + fontSize; + float y = page.getBBox().getUpperRightY() - fontSize; + + y = showLine(cs, arabicFont, fontSize, x, y, TEXT1); + showLine(cs, new PDType0Font[]{ lgcFont, arabicFont, lgcFont }, fontSize, x, y, new String[]{ TEXT2, TEXT3, TEXT4 }); + } + doc.save(outputFilename); + } + } + + /* + * Create the PDType0Font font + */ + private PDType0Font createPdType0Font(GlyphLayoutProcessorAwt glyphLayoutProcessorAwt, PDDocument doc, + String fontPath) throws IOException, FontFormatException + { + InputStream fontStream = this.getClass().getResourceAsStream(fontPath); + return glyphLayoutProcessorAwt.loadFont(doc, fontStream); + } +} Added: pdfbox/trunk/pdfbox-layout-awt/src/test/java/org/apache/pdfbox/glyphlayout/GlyphLayoutDin91379FormTest.java ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ pdfbox/trunk/pdfbox-layout-awt/src/test/java/org/apache/pdfbox/glyphlayout/GlyphLayoutDin91379FormTest.java Sat Jul 4 13:31:20 2026 (r1935881) @@ -0,0 +1,136 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.pdfbox.glyphlayout; + +import java.awt.FontFormatException; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.URISyntaxException; +import org.apache.pdfbox.Loader; +import org.apache.pdfbox.pdmodel.PDDocument; +import org.apache.pdfbox.pdmodel.PDDocumentCatalog; +import org.apache.pdfbox.pdmodel.PDResources; +import org.apache.pdfbox.pdmodel.font.PDType0Font; +import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm; +import org.apache.pdfbox.pdmodel.interactive.form.PDField; +import org.apache.pdfbox.pdmodel.interactive.form.PDTextField; +import static org.junit.jupiter.api.Assertions.assertEquals; +import org.junit.jupiter.api.Test; + +/* + * Example of formatting for letters defined in: + * DIN 91379: Characters and defined character sequences in Unicode for the electronic processing of names + * and data exchange in Europe + * <p> + * Use of the glyph layout features of Java that are based on HarfBuzz + * + * @author Volker Kunert + * @date 2026-04-04 + */ + +public class GlyphLayoutDin91379FormTest +{ + static String LATIN_CHARS_DIN_91379 = + "DIN 91379: Characters in Unicode for the electronic processing of names " + + "and data exchange in Europe\n" + + "bll; Latin Letters (normative)\n" + + "A B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z " + + "À Á Â Ã Ä Å Æ Ç È É Ê Ë Ì Í Î Ï Ð Ñ Ò Ó Ô Õ Ö Ø Ù Ú Û Ü Ý Þ ß à á â ã ä å æ ç è é ê ë ì í î ï ð ñ ò ó " + + "ô õ ö ø ù ú û ü ý þ ÿ Ā ā Ă ă Ą ą Ć ć Ĉ ĉ Ċ ċ Č č Ď ď Đ đ Ē ē Ĕ ĕ Ė ė Ę ę Ě ě Ĝ ĝ Ğ ğ Ġ ġ Ģ ģ Ĥ ĥ Ħ " + + "ħ Ĩ ĩ Ī ī Ĭ ĭ Į į İ ı IJ ij Ĵ ĵ Ķ ķ ĸ Ĺ ĺ Ļ ļ Ľ ľ Ŀ ŀ Ł ł Ń ń Ņ ņ Ň ň ʼn Ŋ ŋ Ō ō Ŏ ŏ Ő ő Œ œ Ŕ ŕ Ŗ ŗ Ř ř Ś ś Ŝ ŝ Ş " + + "ş Š š Ţ ţ Ť ť Ŧ ŧ Ũ ũ Ū ū Ŭ ŭ Ů ů Ű ű Ų ų Ŵ ŵ Ŷ ŷ Ÿ Ź ź Ż ż Ž ž Ƈ ƈ Ə Ɨ Ơ ơ Ư ư Ʒ Ǎ ǎ Ǐ ǐ Ǒ ǒ Ǔ ǔ Ǖ ǖ " + + "Ǘ ǘ Ǚ ǚ Ǜ ǜ Ǟ ǟ Ǣ ǣ Ǥ ǥ Ǧ ǧ Ǩ ǩ Ǫ ǫ Ǭ ǭ Ǯ ǯ ǰ Ǵ ǵ Ǹ ǹ Ǻ ǻ Ǽ ǽ Ǿ ǿ Ȓ ȓ Ș ș Ț ț Ȟ ȟ ȧ Ȩ ȩ Ȫ ȫ Ȭ ȭ " + + "Ȯ ȯ Ȱ ȱ Ȳ ȳ ə ɨ ʒ Ḃ ḃ Ḇ ḇ Ḋ ḋ Ḍ ḍ Ḏ ḏ Ḑ ḑ ḗ Ḝ ḝ Ḟ ḟ Ḡ ḡ Ḣ ḣ Ḥ ḥ Ḧ ḧ Ḩ ḩ Ḫ ḫ ḯ Ḱ ḱ Ḳ ḳ Ḵ ḵ Ḷ ḷ Ḻ ḻ Ṁ " + + "ṁ Ṃ ṃ Ṅ ṅ Ṇ ṇ Ṉ ṉ Ṓ ṓ Ṕ ṕ Ṗ ṗ Ṙ ṙ Ṛ ṛ Ṟ ṟ Ṡ ṡ Ṣ ṣ Ṫ ṫ Ṭ ṭ Ṯ ṯ Ẁ ẁ Ẃ ẃ Ẅ ẅ Ẇ ẇ Ẍ ẍ Ẏ ẏ Ẑ ẑ Ẓ ẓ Ẕ ẕ " + + "ẖ ẗ ẞ Ạ ạ Ả ả Ấ ấ Ầ ầ Ẩ ẩ Ẫ ẫ Ậ ậ Ắ ắ Ằ ằ Ẳ ẳ Ẵ ẵ Ặ ặ Ẹ ẹ Ẻ ẻ Ẽ ẽ Ế ế Ề ề Ể ể Ễ ễ Ệ ệ Ỉ ỉ Ị ị Ọ ọ Ỏ ỏ Ố " + + "ố Ồ ồ Ổ ổ Ỗ ỗ Ộ ộ Ớ ớ Ờ ờ Ở ở Ỡ ỡ Ợ ợ Ụ ụ Ủ ủ Ứ ứ Ừ ừ Ử ử Ữ ữ Ự ự Ỳ ỳ Ỵ ỵ Ỷ ỷ Ỹ ỹ\n" + + "Sequences\n" + + "A̋ C̀ C̄ C̆ C̈ C̕ C̣ C̦ C̨̆ D̂ F̀ F̄ G̀ H̄ H̦ H̱ J́ J̌ K̀ K̂ K̄ K̇ K̕ K̛ K̦ K͟H " + + "K͟h L̂ L̥ L̥̄ L̦ M̀ M̂ M̆ M̐ N̂ N̄ N̆ N̦ P̀ P̄ P̕ P̣ R̆ R̥ R̥̄ S̀ S̄ S̛̄ S̱ T̀ T̄ " + + "T̈ T̕ T̛ U̇ Z̀ Z̄ Z̆ Z̈ Z̧ a̋ c̀ c̄ c̆ c̈ c̕ c̣ c̦ c̨̆ d̂ f̀ f̄ g̀ h̄ h̦ j́ k̀ " + + "k̂ k̄ k̇ k̕ k̛ k̦ k͟h l̂ l̥ l̥̄ l̦ m̀ m̂ m̆ m̐ n̂ n̄ n̆ n̦ p̀ p̄ p̕ p̣ r̆ r̥ r̥ " + + "s̀ s̄ s̛̄ s̱ t̀ t̄ t̕ t̛ u̇ z̀ z̄ z̆ z̈ z̧ Ç̆ Û̄ ç̆ û̄ ÿ́ Č̕ Č̣ č̕ č̣ ē̍ Ī́ ī́ " + + "ō̍ Ž̦ Ž̧ ž̦ ž̧ Ḳ̄ ḳ̄ Ṣ̄ ṣ̄ Ṭ̄ ṭ̄ Ạ̈ ạ̈ Ọ̈ ọ̈ Ụ̄ Ụ̈ ụ̄ ụ̈\n" + + "bnlreq; Non-Letters N1 (normative)\n" + + " ' , - . ` ~ ¨ ´ · ʹ ʺ ʾ ʿ ˈ ˌ ’ ‡\n" + + "bnl; Non-Letters N2 (normative)\n" + + "! \" # $ % & ( ) * + / 0 1 2 3 4 5 6 7 8 9 : ; < = > " + + "? @ [ \\ ] ^ _ { | } ¡ ¢ £ ¥ § © ª « ¬ ® ¯ ° ± ² ³ µ " + + "¶ ¹ º » ¿ × ÷ € \n" + + "bnlopt; Non-Letters N3 (normative)\n" + + "¤ ¦ ¸ ¼ ½ ¾ \n" + + "gl; Greek Letters (extended)\n" + + "Ά Έ Ή Ί Ό Ύ Ώ ΐ Α Β Γ Δ Ε Ζ Η Θ Ι Κ Λ Μ Ν Ξ Ο Π Ρ Σ " + + "Τ Υ Φ Χ Ψ Ω Ϊ Ϋ ά έ ή ί ΰ α β γ δ ε ζ η θ ι κ λ μ ν " + + "ξ ο π ρ ς σ τ υ φ χ ψ ω ϊ ϋ ό ύ ώ \n" + + "cl; Cyrillic Letters (extended)\n" + + "Ѝ А Б В Г Д Е Ж З И Й К Л М Н О П Р С Т У Ф Х Ц Ч Ш " + + "Щ Ъ Ь Ю Я а б в г д е ж з и й к л м н о п р с т у ф " + + "х ц ч ш щ ъ ь ю я ѝ \n" + + "enl; Non-Letters E1 (extended)\n" + + "ƒ ʰ ʳ ˆ ˜ ˢ ᵈ ᵗ ‘ ‚ “ ” „ † … ‰ ′ ″ ‹ › ⁰ ⁴ ⁵ ⁶ ⁷ ⁸ " + + "⁹ ⁿ ₀ ₁ ₂ ₃ ₄ ₅ ₆ ₇ ₈ ₉ ™ ∞ ≤ ≥ \n" + + "Additional non-letters (not included in DIN 91379): – — •�"; + + @Test + void testGlyphLayoutDin91379Form() throws IOException, FontFormatException, URISyntaxException + { + GlyphLayoutProcessorAwt glyphLayoutProcessor = new GlyphLayoutProcessorAwt(); + + String outputFilename = "target/GlyphLayoutDIN91379Form.pdf"; + + String fontSizeString = "10.5"; + + InputStream fontStream = GlyphLayoutDin91379FormTest.class.getResourceAsStream("/ttf/DejaVuSans.ttf"); + File pdfForm = new File(GlyphLayoutDin91379FormTest.class.getResource("/pdf/PdfForm.pdf").toURI()); + + try (PDDocument doc = Loader.loadPDF(pdfForm)) + { + // embedSubset has to be set to false + PDType0Font font = glyphLayoutProcessor.loadFont(doc, fontStream, false); + + PDDocumentCatalog docCatalog = doc.getDocumentCatalog(); + PDAcroForm acroForm = docCatalog.getAcroForm(); + + acroForm.setGlyphLayoutProcessor(glyphLayoutProcessor); + + PDResources resources = new PDResources(); + String resourceFontName = resources.add(font).getName(); + acroForm.setDefaultResources(resources); + for (PDField field : acroForm.getFields()) + { + if (field instanceof PDTextField) + { + PDTextField textfield = (PDTextField) field; + textfield.setDefaultAppearance( + String.format("/%s %s Tf 0 g ", resourceFontName, fontSizeString)); + textfield.setValue(LATIN_CHARS_DIN_91379); + } + } + acroForm.refreshAppearances(); + acroForm.flatten(); + doc.save(outputFilename); + } + + //TODO add rendering comparison + try (PDDocument doc = Loader.loadPDF(new File(outputFilename))) + { + assertEquals(1, doc.getNumberOfPages()); + } + } +} Added: pdfbox/trunk/pdfbox-layout-awt/src/test/java/org/apache/pdfbox/glyphlayout/GlyphLayoutDin91379Test.java ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ pdfbox/trunk/pdfbox-layout-awt/src/test/java/org/apache/pdfbox/glyphlayout/GlyphLayoutDin91379Test.java Sat Jul 4 13:31:20 2026 (r1935881) @@ -0,0 +1,159 @@ +package org.apache.pdfbox.glyphlayout; + +import java.awt.FontFormatException; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Writer; +import org.apache.pdfbox.Loader; + +import org.junit.jupiter.api.Test; + +import org.apache.pdfbox.pdmodel.PDDocument; +import org.apache.pdfbox.pdmodel.PDPage; +import org.apache.pdfbox.pdmodel.PDPageContentStream; +import org.apache.pdfbox.pdmodel.font.PDType0Font; +import org.apache.pdfbox.text.PDFTextStripper; +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * Example of formatting for letters defined in: DIN 91379: Characters in Unicode for the electronic + * processing of names and data exchange in Europe + * <p> + * Use of the positioning features of Java. + * + * @author Volker Kunert + */ +class GlyphLayoutDin91379Test +{ + static String LATIN_CHARS_DIN_91379 = + "DIN 91379: Characters in Unicode for the electronic processing of names \n" + + "and data exchange in Europe\n" + + "Font used: DejaVuSans.ttf\n" + + "\n" + + "bll; Latin Letters (normative)\n" + + "A B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z\n" + + "À Á Â Ã Ä Å Æ Ç È É Ê Ë Ì Í Î Ï Ð Ñ Ò Ó Ô Õ Ö Ø Ù Ú Û Ü Ý Þ ß à á â ã ä å æ ç è é ê ë ì í î ï ð ñ ò ó\n" + + "ô õ ö ø ù ú û ü ý þ ÿ Ā ā Ă ă Ą ą Ć ć Ĉ ĉ Ċ ċ Č č Ď ď Đ đ Ē ē Ĕ ĕ Ė ė Ę ę Ě ě Ĝ ĝ Ğ ğ Ġ ġ Ģ ģ Ĥ ĥ Ħ\n" + + "ħ Ĩ ĩ Ī ī Ĭ ĭ Į į İ ı IJ ij Ĵ ĵ Ķ ķ ĸ Ĺ ĺ Ļ ļ Ľ ľ Ŀ ŀ Ł ł Ń ń Ņ ņ Ň ň ʼn Ŋ ŋ Ō ō Ŏ ŏ Ő ő Œ œ Ŕ ŕ Ŗ ŗ Ř ř Ś ś Ŝ ŝ Ş\n" + + "ş Š š Ţ ţ Ť ť Ŧ ŧ Ũ ũ Ū ū Ŭ ŭ Ů ů Ű ű Ų ų Ŵ ŵ Ŷ ŷ Ÿ Ź ź Ż ż Ž ž Ƈ ƈ Ə Ɨ Ơ ơ Ư ư Ʒ Ǎ ǎ Ǐ ǐ Ǒ ǒ Ǔ ǔ Ǖ ǖ\n" + + "Ǘ ǘ Ǚ ǚ Ǜ ǜ Ǟ ǟ Ǣ ǣ Ǥ ǥ Ǧ ǧ Ǩ ǩ Ǫ ǫ Ǭ ǭ Ǯ ǯ ǰ Ǵ ǵ Ǹ ǹ Ǻ ǻ Ǽ ǽ Ǿ ǿ Ȓ ȓ Ș ș Ț ț Ȟ ȟ ȧ Ȩ ȩ Ȫ ȫ Ȭ ȭ\n" + + "Ȯ ȯ Ȱ ȱ Ȳ ȳ ə ɨ ʒ Ḃ ḃ Ḇ ḇ Ḋ ḋ Ḍ ḍ Ḏ ḏ Ḑ ḑ ḗ Ḝ ḝ Ḟ ḟ Ḡ ḡ Ḣ ḣ Ḥ ḥ Ḧ ḧ Ḩ ḩ Ḫ ḫ ḯ Ḱ ḱ Ḳ ḳ Ḵ ḵ Ḷ ḷ Ḻ ḻ Ṁ\n" + + "ṁ Ṃ ṃ Ṅ ṅ Ṇ ṇ Ṉ ṉ Ṓ ṓ Ṕ ṕ Ṗ ṗ Ṙ ṙ Ṛ ṛ Ṟ ṟ Ṡ ṡ Ṣ ṣ Ṫ ṫ Ṭ ṭ Ṯ ṯ Ẁ ẁ Ẃ ẃ Ẅ ẅ Ẇ ẇ Ẍ ẍ Ẏ ẏ Ẑ ẑ Ẓ ẓ Ẕ ẕ\n" + + "ẖ ẗ ẞ Ạ ạ Ả ả Ấ ấ Ầ ầ Ẩ ẩ Ẫ ẫ Ậ ậ Ắ ắ Ằ ằ Ẳ ẳ Ẵ ẵ Ặ ặ Ẹ ẹ Ẻ ẻ Ẽ ẽ Ế ế Ề ề Ể ể Ễ ễ Ệ ệ Ỉ ỉ Ị ị Ọ ọ Ỏ ỏ Ố\n" + + "ố Ồ ồ Ổ ổ Ỗ ỗ Ộ ộ Ớ ớ Ờ ờ Ở ở Ỡ ỡ Ợ ợ Ụ ụ Ủ ủ Ứ ứ Ừ ừ Ử ử Ữ ữ Ự ự Ỳ ỳ Ỵ ỵ Ỷ ỷ Ỹ ỹ\n" + + "Sequences\n" + + "A̋ C̀ C̄ C̆ C̈ C̕ C̣ C̦ C̨̆ D̂ F̀ F̄ G̀ H̄ H̦ H̱ J́ J̌ K̀ K̂ K̄ K̇ K̕ K̛ K̦ K͟H \n" + + "K͟h L̂ L̥ L̥̄ L̦ M̀ M̂ M̆ M̐ N̂ N̄ N̆ N̦ P̀ P̄ P̕ P̣ R̆ R̥ R̥̄ S̀ S̄ S̛̄ S̱ T̀ T̄ \n" + + "T̈ T̕ T̛ U̇ Z̀ Z̄ Z̆ Z̈ Z̧ a̋ c̀ c̄ c̆ c̈ c̕ c̣ c̦ c̨̆ d̂ f̀ f̄ g̀ h̄ h̦ j́ k̀ \n" + + "k̂ k̄ k̇ k̕ k̛ k̦ k͟h l̂ l̥ l̥̄ l̦ m̀ m̂ m̆ m̐ n̂ n̄ n̆ n̦ p̀ p̄ p̕ p̣ r̆ r̥ r̥̄ \n" + + "s̀ s̄ s̛̄ s̱ t̀ t̄ t̕ t̛ u̇ z̀ z̄ z̆ z̈ z̧ Ç̆ Û̄ ç̆ û̄ ÿ́ Č̕ Č̣ č̕ č̣ ē̍ Ī́ ī́ \n" + + "ō̍ Ž̦ Ž̧ ž̦ ž̧ Ḳ̄ ḳ̄ Ṣ̄ ṣ̄ Ṭ̄ ṭ̄ Ạ̈ ạ̈ Ọ̈ ọ̈ Ụ̄ Ụ̈ ụ̄ ụ̈ \n" + + "bnlreq; Non-Letters N1 (normative)\n" + + " ' , - . ` ~ ¨ ´ · ʹ ʺ ʾ ʿ ˈ ˌ ’ ‡ \n" + + "bnl; Non-Letters N2 (normative)\n" + + "! \" # $ % & ( ) * + / 0 1 2 3 4 5 6 7 8 9 : ; < = > \n" + + "? @ [ \\ ] ^ _ { | } ¡ ¢ £ ¥ § © ª « ¬ ® ¯ ° ± ² ³ µ \n" + + "¶ ¹ º » ¿ × ÷ € \n" + + "bnlopt; Non-Letters N3 (normative)\n" + + "¤ ¦ ¸ ¼ ½ ¾ \n" + + "gl; Greek Letters (extended)\n" + + "Ά Έ Ή Ί Ό Ύ Ώ ΐ Α Β Γ Δ Ε Ζ Η Θ Ι Κ Λ Μ Ν Ξ Ο Π Ρ Σ \n" + + "Τ Υ Φ Χ Ψ Ω Ϊ Ϋ ά έ ή ί ΰ α β γ δ ε ζ η θ ι κ λ μ ν \n" + + "ξ ο π ρ ς σ τ υ φ χ ψ ω ϊ ϋ ό ύ ώ \n" + + "cl; Cyrillic Letters (extended)\n" + + "Ѝ А Б В Г Д Е Ж З И Й К Л М Н О П Р С Т У Ф Х Ц Ч Ш \n" + + "Щ Ъ Ь Ю Я а б в г д е ж з и й к л м н о п р с т у ф \n" + + "х ц ч ш щ ъ ь ю я ѝ \n" + + "enl; Non-Letters E1 (extended)\n" + + "ƒ ʰ ʳ ˆ ˜ ˢ ᵈ ᵗ ‘ ‚ “ ” „ † … ‰ ′ ″ ‹ › ⁰ ⁴ ⁵ ⁶ ⁷ ⁸ \n" + + "⁹ ⁿ ₀ ₁ ₂ ₃ ₄ ₅ ₆ ₇ ₈ ₉ ™ ∞ ≤ ≥ \n" + + "Additional non-letters (not included in DIN 91379): – — •�"; + + @Test + void testGlyphLayoutDin91379() throws IOException, FontFormatException + { + GlyphLayoutProcessorAwt glyphLayoutProcessor = new GlyphLayoutProcessorAwt(); + + String outputPDFFilename = "target/GlyphLayoutDIN91379.pdf"; + String outputTextFilename = "target/GlyphLayoutDIN91379.txt"; + float fontSize = 12.0f; + + try (PDDocument doc = new PDDocument()) + { + InputStream fontStream = GlyphLayoutDin91379Test.class.getResourceAsStream("/ttf/DejaVuSans.ttf"); + PDType0Font font = glyphLayoutProcessor.loadFont(doc, fontStream); + + PDPage page = new PDPage(); + doc.addPage(page); + try (PDPageContentStream cs = new PDPageContentStream(doc, page)) + { + cs.setGlyphLayoutProcessor(glyphLayoutProcessor); + + float x = page.getBBox().getLowerLeftX() + fontSize; + float y = page.getBBox().getUpperRightY() - fontSize; + showComposites(cs, font, fontSize, x, y, LATIN_CHARS_DIN_91379); + } + doc.save(outputPDFFilename); + } + + //TODO add rendering comparison + try (PDDocument doc = Loader.loadPDF(new File(outputPDFFilename))) + { + assertEquals(1, doc.getNumberOfPages()); + + PDFTextStripper stripper = new PDFTextStripper(); + String s = stripper.getText(doc); + try (OutputStream os = new FileOutputStream(outputTextFilename)) + { + os.write (0xEF); + os.write (0xBB); + os.write (0xBF); + + try (Writer writer = new BufferedWriter(new OutputStreamWriter(os, "utf-8"))) + { + //TODO compare this output with the input, like in TextStripper test + // Not yet correct as of 4.7.2026 + writer.write(s); + } + } + } + } + + /* + * break the text into lines and show them + */ + private void showComposites(PDPageContentStream cs, PDType0Font font, float fontSize, + float x, float y, String s) throws IOException + { + + s = s.replaceAll("\t", " "); + String[] lines = s.split("[\n]"); + + for (String line : lines) + { + if (!line.isEmpty()) + { + showCompositesLine(cs, font, fontSize, x, y, line); + y -= fontSize * 1.5; + } + } + } + + /* + * show one line + */ + private void showCompositesLine(PDPageContentStream cs, PDType0Font font, float fontSize, + float x, float y, String line) throws IOException + { + cs.beginText(); + cs.setFont(font, fontSize); + cs.newLineAtOffset(x, y); + cs.showText(line); + cs.endText(); + } +} Added: pdfbox/trunk/pdfbox-layout-awt/src/test/java/org/apache/pdfbox/glyphlayout/GlyphLayoutLigaturesAndKerningTest.java ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ pdfbox/trunk/pdfbox-layout-awt/src/test/java/org/apache/pdfbox/glyphlayout/GlyphLayoutLigaturesAndKerningTest.java Sat Jul 4 13:31:20 2026 (r1935881) @@ -0,0 +1,190 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.pdfbox.glyphlayout; + +/** + * Examples for ligatures and kerning + * See <a href="https://issues.apache.org/jira/browse/PDFBOX-4951">PDFBOX-4951</a> + * + * The default processing of GlyphLayoutProcessor is with ligatures and kerning disabled. + * You can enable ligatures and kerning using FontOptions, see below. + * + * @author Volker Kunert + */ + +import java.awt.FontFormatException; +import java.io.IOException; +import java.io.InputStream; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import org.junit.jupiter.api.Test; + +import org.apache.pdfbox.pdmodel.PDDocument; +import org.apache.pdfbox.pdmodel.PDPage; +import org.apache.pdfbox.pdmodel.PDPageContentStream; +import org.apache.pdfbox.pdmodel.font.PDType0Font; + +public class GlyphLayoutLigaturesAndKerningTest +{ + static final String FIRACODE_STRING = "!= == === >= <="; + static final String DEJAVU_STRING = "AVATAR, effective, affiliation, float, film, affluent"; + static final String BENGALI_STRING = "আমি কোন পথে ক্ষীরের লক্ষ্মী ষন্ড পুতুল রুপো গঙ্গা ঋষি"; + + /** + * Check that missing glyph is caught like in main pdfbox. + * + * @throws IOException + * @throws FontFormatException + */ + @Test + void testMissingGlyph() throws IOException, FontFormatException + { + GlyphLayoutProcessorAwt glyphLayoutProcessor = new GlyphLayoutProcessorAwt(); + + String lohitBengaliPath = "/ttf/Lohit-Bengali.ttf"; + + try (PDDocument doc = new PDDocument()) + { + PDType0Font lohitBengaliFont = createPdType0Font(glyphLayoutProcessor, doc, lohitBengaliPath); + + PDPage page = new PDPage(); + doc.addPage(page); + try (PDPageContentStream cs = new PDPageContentStream(doc, page)) + { + cs.setGlyphLayoutProcessor(glyphLayoutProcessor); + + IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> + showComposites(cs, lohitBengaliFont, 1, 0, 0, "123ABC")); + assertEquals("Missing glyph in font 'Lohit Bengali' for the character 'A', codePoint: 65 (U+0041).", ex.getMessage()); + } + } + } + + @Test + void testLigaturesAndKerning() throws IOException, FontFormatException + { + GlyphLayoutProcessorAwt glyphLayoutProcessor = new GlyphLayoutProcessorAwt(); + + String outputFilename = "target/GlyphLayoutLigaturesAndKerning.pdf"; + String firaPath = "/ttf/FiraCode-Regular.ttf"; + String dejavuPath = "/ttf/DejaVuSans.ttf"; // ligatures not in Liberation nor in Arimo + String lohitBengaliPath = "/ttf/Lohit-Bengali.ttf"; + + float fontSize = 12.0f; + + try (PDDocument doc = new PDDocument()) + { + PDType0Font firaFont = createPdType0Font(glyphLayoutProcessor, doc, firaPath); + PDType0Font firaLigFont = createPdType0Font(glyphLayoutProcessor, doc, firaPath, + new GlyphLayoutFontLoaderAwt.FontOptions().setLigaturesOn()); + + PDType0Font dejavuFont = createPdType0Font(glyphLayoutProcessor, doc, dejavuPath); + + PDType0Font dejavuLigFont = createPdType0Font(glyphLayoutProcessor, doc, dejavuPath, + new GlyphLayoutFontLoaderAwt.FontOptions().setLigaturesOn()); + + PDType0Font dejavuKernFont = createPdType0Font(glyphLayoutProcessor, doc, dejavuPath, + new GlyphLayoutFontLoaderAwt.FontOptions().setKerningOn()); + + PDType0Font dejavuLigKernFont = createPdType0Font(glyphLayoutProcessor, doc, dejavuPath, + new GlyphLayoutFontLoaderAwt.FontOptions().setLigaturesOn().setKerningOn()); + + PDType0Font lohitBengaliFont = createPdType0Font(glyphLayoutProcessor, doc, lohitBengaliPath, + new GlyphLayoutFontLoaderAwt.FontOptions()); + + PDPage page = new PDPage(); + doc.addPage(page); + try (PDPageContentStream cs = new PDPageContentStream(doc, page)) + { + cs.setGlyphLayoutProcessor(glyphLayoutProcessor); + + float x = page.getBBox().getLowerLeftX() + fontSize; + float y = page.getBBox().getUpperRightY() - fontSize; + y = showComposites(cs, firaFont, fontSize, x, y, FIRACODE_STRING); + y = showComposites(cs, firaLigFont, fontSize, x, y, FIRACODE_STRING + " (Ligatures)"); + y = showComposites(cs, dejavuFont, fontSize, x, y, DEJAVU_STRING); + y = showComposites(cs, dejavuLigFont, fontSize, x, y, DEJAVU_STRING + " (Ligatures)"); + y = showComposites(cs, dejavuKernFont, fontSize, x, y, DEJAVU_STRING + " (Kerning)"); + y = showComposites(cs, dejavuLigKernFont, fontSize, x, y, DEJAVU_STRING + " (Ligatures and kerning)"); + showComposites(cs, lohitBengaliFont, fontSize, x, y, BENGALI_STRING + " (ভারত)"); + } + doc.save(outputFilename); + } + } + + /* + * Create the PDType0Font font + */ + private PDType0Font createPdType0Font(GlyphLayoutProcessorAwt glyphLayoutProcessor, PDDocument pdDocument, + String fontPath) throws IOException, FontFormatException + { + InputStream fontStream = this.getClass(). + getResourceAsStream(fontPath); + PDType0Font font = glyphLayoutProcessor.loadFont(pdDocument, fontStream); + return font; + } + + /* + * Create the PDType0Font font with font options + */ + private PDType0Font createPdType0Font(GlyphLayoutProcessorAwt glyphLayoutProcessor, PDDocument pdDocument, + String fontPath, GlyphLayoutFontLoaderAwt.FontOptions fontOptions) throws IOException, FontFormatException + { + InputStream fontStream = this.getClass(). + getResourceAsStream(fontPath); + PDType0Font font = glyphLayoutProcessor.loadFont(pdDocument, fontStream, fontOptions); + return font; + } + + /* + * break the text into lines and show them + */ + public static float showComposites(PDPageContentStream cs, PDType0Font font, float fontSize, + float x, float y, String s) throws IOException + { + + s = s.replaceAll("\t", " "); + String[] lines = s.split("[\n]"); + + float height = font.getBoundingBox().getHeight(); + + for (String line : lines) + { + if (!line.isEmpty()) + { + showCompositesLine(cs, font, fontSize, x, y, line); + y -= height / 1000f * fontSize; + } + } + return y; + } + + /* + * show one line + */ + public static void showCompositesLine(PDPageContentStream cs, PDType0Font font, float fontSize, + float x, float y, String line) throws IOException + { + cs.beginText(); + cs.setFont(font, fontSize); + cs.newLineAtOffset(x, y); + cs.showText(line); + cs.endText(); + } +} Added: pdfbox/trunk/pdfbox-layout-awt/src/test/resources/pdf/PdfForm.pdf ============================================================================== Binary file. No diff available. Added: pdfbox/trunk/pdfbox-layout-awt/src/test/resources/ttf/DejaVuSans.ttf ============================================================================== Binary file. No diff available. Added: pdfbox/trunk/pdfbox-layout-awt/src/test/resources/ttf/FiraCode-Regular.ttf ============================================================================== Binary file. No diff available. Added: pdfbox/trunk/pdfbox-layout-awt/src/test/resources/ttf/Lohit-Bengali.ttf ============================================================================== Binary file. No diff available. Added: pdfbox/trunk/pdfbox-layout-awt/src/test/resources/ttf/NotoSansArabic-Regular.ttf ============================================================================== Binary file. No diff available.
