showtextaligned imagen for example java pdf itext opentype

imagen - java itext table



Acceder a las variantes de glifos OpenType en iText (1)

Al compilar documentos PDF con fuentes OpenType en iText, deseo acceder a las variantes de glifos desde la fuente, específicamente las figuras tabulares. Como las variantes de glifos OpenType no tienen índices Unicode, no estoy seguro de cómo especificar que deseo usar un conjunto particular de variantes (figuras tabulares) o llamar a un glifo específico por su ID de glifo. Solo estoy buscando el nombre de clase iText relevante, si existe.


Esto no parece posible ni en la última etiqueta 5.5.8 , ni en la rama master de iText.

Como se explica en este artículo y en la especificación de archivo de fuentes OpenType de Microsoft, las variantes de glifos se almacenan en la Glyph Substitution Table (GSUB) de un archivo de fuente. El acceso a las variantes del glifo requiere leer esta tabla del archivo, que en realidad se implementa en la clase com.itextpdf.text.pdf.fonts.otf.GlyphSubstitutionTableReader , aunque esta clase está deshabilitada por el momento.

La llamada a readGsubTable() en la clase com.itextpdf.text.pdf.TrueTypeFontUnicode está comentada.

void process(byte ttfAfm[], boolean preload) throws DocumentException, IOException { super.process(ttfAfm, preload); //readGsubTable(); }

Resulta que esta línea está deshabilitada por algún motivo, ya que el código en realidad no funciona si intentas activarlo.

Desafortunadamente, no hay forma de usar variantes de glifos, ya que la información de sustitución nunca se carga desde el archivo de fuente.

Actualizar

La respuesta original fue sobre la posibilidad de utilizar iText API para acceder a las variantes de glifos de manera iText API , que todavía no está disponible. Sin embargo, el código de bajo nivel está en su lugar y se puede usar después de algunos hackers para acceder a la tabla de mapeo de sustitución de glifos.

Cuando se llama a read() , GlyphSubstitutionTableReader lee la tabla GSUB y aplana las sustituciones de todas las características en un mapa Map<Integer, List<Integer>> rawLigatureSubstitutionMap . Los nombres simbólicos de las características están actualmente descartados por OpenTypeFontTableReader . rawLigatureSubstitutionMap mapea una variante glyphId a un glyphId base, o un glyphId ligadura a una secuencia de glyphIds como este:

629 -> 66 // a.feature -> a 715 -> 71, 71, 77 // ffl ligature

Este mapeo se puede invertir para obtener todas las variantes para un glyphId base. Por lo tanto, todos los glifos extendidos con valores Unicode desconocidos pueden determinarse a través de su conexión a un glifo base o una secuencia de glifos.

A continuación, para poder escribir un glifo en PDF, necesitamos saber un valor unicode para ese glyphId . Una relación unicode -> glyphId está mapeada por un campo cmap31 en TrueTypeFont . Invertir el mapa da unicode por glyphId.

Afinando

rawLigatureSubstitutionMap no se puede acceder en GlyphSubstitutionTableReader , ya que es un miembro private y no tiene un acceso GlyphSubstitutionTableReader getter. El truco más simple sería copiar y pegar la clase original y agregar un getter para el mapa:

public class HackedGlyphSubstitutionTableReader extends OpenTypeFontTableReader { // copy-pasted code ... public Map<Integer, List<Integer>> getRawSubstitutionMap() { return rawLigatureSubstitutionMap; } }

El siguiente problema es que GlyphSubstitutionTableReader necesita un desplazamiento para la tabla GSUB , información que se almacena en protected HashMap<String, int[]> tables de la clase TrueTypeFont . Una clase auxiliar colocada en el mismo paquete reducirá el acceso a los miembros protegidos de TrueTypeFont .

package com.itextpdf.text.pdf; import com.itextpdf.text.pdf.fonts.otf.FontReadingException; import java.io.IOException; import java.util.List; import java.util.Map; public class GsubHelper { private Map<Integer, List<Integer>> rawSubstitutionMap; public GsubHelper(TrueTypeFont font) { // get tables offsets from the font instance Map<String, int[]> tables = font.tables; if (tables.get("GSUB") != null) { HackedGlyphSubstitutionTableReader gsubReader; try { gsubReader = new HackedGlyphSubstitutionTableReader( font.rf, tables.get("GSUB")[0], glyphToCharacterMap, font.glyphWidthsByIndex); gsubReader.read(); } catch (IOException | FontReadingException e) { throw new IllegalStateException(e.getMessage()); } rawSubstitutionMap = gsubReader.getRawSubstitutionMap(); } } /** Returns a glyphId substitution map */ public Map<Integer, List<Integer>> getRawSubstitutionMap() { return rawSubstitutionMap; } }

Sería mejor extender TrueTypeFont , pero eso no funcionaría con los métodos de fábrica createFont() de BaseFont , que se basa en nombres de clases codificadas para crear una fuente.