2016-05-16 2 views
0

J'ai un fichier de modèle PDF avec des champs. Modèle créé par le client. Il a du texte, des étiquettes de champs et des champs lui-même. Le texte et les étiquettes utilisent des polices incorporées dans le modèle.Remplir des champs de modèle pdf avec des valeurs cyrilliques (itextsharp)

Des problèmes se produisent lorsque j'essaie de remplir des champs avec des valeurs cyrilliques - il n'y a pas de symboles cyrilliques dans le document de résultat.

J'ai vu beaucoup de problèmes similaires qui ont été résolus en utilisant la police de substitution pour AcroFields. Mais ici je ne peux pas utiliser une police spécifique pour la substitution, parce que je ne peux pas définir la police de champ dans le modèle. J'ai essayé de définir des polices différentes pour les champs dans Acrobat Editor - Times New Roman, Arial et d'autres polices Windows bien connues, mais il n'y a aucun effet dans le pdf résultant.

Exemple de code:

 FontFactory.RegisterDirectory(Environment.GetFolderPath(Environment.SpecialFolder.Fonts)); 
     using (var dest = File.Create(@"result.pdf")) 
     { 
      using (var stamper = new PdfStamper(reader, dest)) 
      { 
       var fields = stamper.AcroFields; 
       fields.SetField("ClientName", "Имя клиента"); 
       stamper.FormFlattening = true; 
       stamper.Close(); 
      } 
     } 

J'ai même enregistré toutes les polices disponibles dans FontFactory, mais il n'y avait pas d'effet. Les questions sont les suivantes: 1. Si je peux intégrer une police dans Adobe Acrobat utilisée uniquement pour les champs, alors comment le faire? 2. Si je peux définir une famille de polices pour un champ existant avec iTextSharp, alors comment le faire?

+0

Donc la police est incorporée dans le PDF mais vous ne pouvez pas l'utiliser? Je commencerais là. Pouvez-vous taper manuellement dans le champ dans Adobe Acrobat et voir ce que vous attendez? Sinon, vous n'avez pas de polices intégrées ou elles ont une forme de corruption. Pouvez-vous poster le PDF? –

+0

Je ne peux pas utiliser les polices intégrées car les polices ne sont pas installées sur ma machine. Fields utilise Arial ou Times New Roman, et je peux y taper des symbos cyrilliques, mais quand je fais ça avec iTextSharp, aucun symbole cyrillique n'est affiché. – Nogard

Répondre

0

Eh bien, j'ai écrit la solution qui convient pour moi.

  1. Enregistrez toutes les polices système existantes dans FontFactory.
  2. Lire les métadonnées de document pour extraire toutes les polices utilisées dans les documents.
  3. Lire les métadonnées de champs et essayer de créer BaseFont approprié à la police de champ. S'il n'y a pas de police appropriée, utilisez la police fallback (arial avec l'encodage IDENTITY_H).

Code donc complet ressemble:

static IEnumerable<PdfFontInfo> ReadDocumentFonts(PdfReader reader) 
    { 
     if (reader.AcroForm == null) 
      yield break; 
     var dr = reader.AcroForm.GetAsDict(PdfName.DR); 

     // Read font information from resources 
     var fontDict = dr.GetAsDict(PdfName.FONT); 
     foreach (var fontKey in fontDict.Keys) 
     { 
      var data = fontDict.GetAsDict(fontKey); 
      // Read font descriptor if it possible 
      var descriptor = data.GetAsDict(PdfName.FONTDESCRIPTOR); 
      if (descriptor != null) 
      { 
       // Read font name and family 
       var family = descriptor.GetAsString(PdfName.FONTFAMILY); 
       yield return new PdfFontInfo(fontKey, family.ToUnicodeString()); 
      } 
     } 
    } 

    static IReadOnlyList<BaseFont> CreateSubstitutionFontsForFields(PdfReader reader) 
    { 
     if (reader.AcroForm.Fields == null) 
      return new List<BaseFont>(0); 
     var documentFontMap = ReadDocumentFonts(reader).ToDictionary(f => f.Name, StringComparer.InvariantCultureIgnoreCase); 
     var substFonts = new Dictionary<string, BaseFont>(); 
     var fallbackRequired = false; 

     // Read font information of each field 
     foreach (var field in reader.AcroForm.Fields) 
     { 
      var fieldFontDa = field.Info.GetAsString(PdfName.DA); 
      if (fieldFontDa == null) 
       continue; 
      var parts = AcroFields.SplitDAelements(fieldFontDa.ToUnicodeString()); 
      if (parts.Length == 0) 
       continue; 
      var fontName = (string) parts[0]; 
      PdfFontInfo inf; 
      if (documentFontMap.TryGetValue(fontName, out inf)) 
      { 
       if (!substFonts.ContainsKey(fontName)) 
       { 
        var font = FontFactory.GetFont(fontName, BaseFont.IDENTITY_H, true).BaseFont; 
        substFonts.Add(fontName, font); 
       } 
      } 
      else 
       fallbackRequired = true; 
     } 
     var allFonts = new List<BaseFont>(substFonts.Values); 
     if (fallbackRequired) 
      allFonts.Add(FALLBACK_FONT); 
     return allFonts; 
    } 

Si vous pouvez trouver des erreurs, vous êtes invités à commenter.