iText:ロシア語でPDFに書き込む

タスク: iTextライブラリを使用してPDFドキュメントを作成します。 この場合、ユーザーはシステムにインストールされているフォントを使用するフォントを指定する必要があります。 TrueTypeやType1などのフォント。
ITextには、FontFactoryシステムフォントへのアクセスを提供する静的クラスがあります。 フォントを受け取ったら、そのエンコーディングを正しく指定する必要があります。 ここで問題が発生しました。 TTとT1では、エンコーディングが異なります。また、.NETには、TTフォントをT1と区別するための標準ツールはありません。


フォントタイプは、TEXTMETRIC構造体のtmPitchAndFamilyフィールドに格納されます。
この構造には、Gdi32.dllライブラリのGetTextMetrics関数を使用してアクセスできます。
この関数にアクセスするためのラッパーを作成します。

namespace SYS_TEXT {

using System;
using System.Drawing;
using System.Runtime.InteropServices;

/// <summary> Access to system fon metric class. </summary>
static class METRIC {

public static byte TMPF_TRUETYPE = 0x4;

#region Native structs
[StructLayout( LayoutKind.Sequential )]
internal struct TEXTMETRIC {
public int tmHeight;
public int tmAscent;
public int tmDescent;
public int tmInternalLeading;
public int tmExternalLeading;
public int tmAveCharWidth;
public int tmMaxCharWidth;
public int tmWeight;
public int tmOverhang;
public int tmDigitizedAspectX;
public int tmDigitizedAspectY;
public char tmFirstChar;
public char tmLastChar;
public char tmDefaultChar;
public char tmBreakChar;
public byte tmItalic;
public byte tmUnderlined;
public byte tmStruckOut;
public byte tmPitchAndFamily;
public byte tmCharSet;
}
#endregion // Native structs

/// <summary> Verify is font TrueType </summary>
/// <param name="font">Font</param>
/// <returns>Font is TrueType</returns>
public static bool FontIsTrueType( Font font ) {
TEXTMETRIC tm;
GetFontMetrics( font, out tm );
return ( tm.tmPitchAndFamily & TMPF_TRUETYPE ) != 0;
}

/// <summary> Get font metrics </summary>
/// <param name="font">Font</param>
/// <param name="tm">Text metrics</param>
public static void GetFontMetrics( Font font, out TEXTMETRIC tm ) {
TEXTMETRIC tmRet = new TEXTMETRIC();
IntPtr hdc = GetDC( IntPtr .Zero );

IntPtr hfnt = font.ToHfont();
// Select in DC new font
IntPtr hFontPrevious = SelectObject( hdc, hfnt );

GetTextMetrics( hdc, ref tmRet );
SelectObject( hdc, hFontPrevious );
ReleaseDC( IntPtr .Zero, hdc );
tm = tmRet;
}

[DllImport( "Gdi32.dll" )]
private static extern IntPtr SelectObject( IntPtr hdc, IntPtr hgdiobj );

[DllImport( "Gdi32.dll" )]
private static extern bool GetTextMetrics( IntPtr hdc, ref TEXTMETRIC lptm );

[DllImport( "user32.dll" , CharSet = CharSet.Auto )]
static private extern IntPtr GetDC( IntPtr hWnd );

[DllImport( "user32.dll" , CharSet = CharSet.Auto )]
static private extern int ReleaseDC( IntPtr hWnd, IntPtr hDC );

} // METRIC

} // SYS_TEXT


* This source code was highlighted with Source Code Highlighter .


したがって、フォントのタイプが決定されます。
正しいエンコーディングを設定してください:
TrueType-BaseFont.IDENTITY_H、
タイプ1-「Cp1251」。
目的のフォントにアクセスしやすいように、別のラッパーを作成します。 同時に、ファクトリからフォントを取得するのが非常に遅いため、キャッシュを追加します。

namespace iText_font_test {

using System;
using System.Collections;
using iTextSharp.text;
using iTextSharp.text.pdf;
using SYS_TEXT;

/// <summary> Helpers for iTextSharp library </summary>
public static class ITEXT_HLP {

#region Properties
/// <summary> Font cache </summary>
private static Hashtable __cache_fonts;
#endregion // Properties

#region Methods
/// <summary> Get font from system fonts </summary>
/// <param name="font_nm">Font name</param>
/// <returns>BaseFont</returns>
public static BaseFont font_sys_get( string font_nm ) {

// Create font cache if not exist
if ( null == __cache_fonts )
__cache_fonts = new Hashtable ();

// Try get font from cache
if ( __cache_fonts.Contains( font_nm ) )
return (BaseFont) __cache_fonts[ font_nm ];

BaseFont result_font;

// Try get font from system
try {
var sf = new System.Drawing. Font ( font_nm, 8f );
var enc = METRIC.FontIsTrueType( sf ) ? BaseFont.IDENTITY_H : "Cp1251" ;
FontFactory.RegisterDirectories();
var font = FontFactory.GetFont( font_nm, enc, true );
result_font = font.GetCalculatedBaseFont( true );
} catch ( Exception ) {
return null ;
}

// Save font in cache
if ( null != result_font )
__cache_fonts[ font_nm ] = result_font;

return result_font;
} // font_sys_get
#endregion // Methods

} // ITEXT_HLP

} // iText_font_test

* This source code was highlighted with Source Code Highlighter .


そして実際に使用します:

using System.IO;
using iTextSharp.text;
using iTextSharp.text.pdf;

namespace iText_font_test {
class Program {
static void Main( string [] args ) {

// Create new PDF document
Rectangle pagesize = new Rectangle( 600f, 300f );
Document document = new Document( pagesize, 0f, 0f, 0f, 0f );
PdfWriter wr_pdf = PdfWriter.GetInstance( document, new FileStream ( "font_test.pdf" , FileMode .Create ) );
document.Open();
PdfContentByte canvas = wr_pdf.DirectContent;

// Draw text
canvas.BeginText();
BaseFont font = ITEXT_HLP.font_sys_get( "arial" );
canvas.SetFontAndSize( font, 24f );
canvas.ShowTextAligned( PdfContentByte.ALIGN_LEFT, ", !" , 100f, 200f, 0f );
canvas.EndText();

// Close document
document.Close();

}
}
}

* This source code was highlighted with Source Code Highlighter .


コードは、新しい多言語および古いTrueType、および古いType1フォントでテストされています。
多言語のType1フォントがある場合、このコードがそれらにどのように対処するかを知りたいです。
また、誰かがアンマネージコードを使用せずにTTをT1と区別する方法を知ることができますか?

Source: https://habr.com/ru/post/J113984/


All Articles