VerticalTextJP2.cs
//
// このコードは、DioDocs for PDF のサンプルの一部として提供されています。
// © MESCIUS inc. All rights reserved.
//
using System;
using System.IO;
using System.Drawing;
using System.Collections.Generic;
using GCDRAW = GrapeCity.Documents.Drawing;
using GrapeCity.Documents.Pdf;
using GrapeCity.Documents.Text;
using System.Text.RegularExpressions;
namespace DsPdfWeb.Demos.Basics
{
// 水平方向の列を持つレイアウトを使用して、小説の文章をテキストとして描画します。
// ArabicColumns、MultiLang、VerticalText、VerticalTextJPも参照してください。
public class VerticalTextJP2
{
public int CreatePDF(Stream stream)
{
var clouds = GCDRAW.Image.FromFile(Path.Combine("Resources", "Images", "hanamaki.jpg"));
var firth = GCDRAW.Image.FromFile(Path.Combine("Resources", "Images", "cello.jpg"));
var kenji = GCDRAW.Image.FromFile(Path.Combine("Resources", "Images", "kenji.jpg"));
var ia = new GCDRAW.ImageAlign(GCDRAW.ImageAlignHorz.Left, GCDRAW.ImageAlignVert.Top, true, true, true, false, false);
var doc = new GcPdfDocument();
// テキストを保持してレンダリングするTextLayout:
var tl = new TextLayout(72);
tl.ParagraphSpacing = 6;
tl.FlowDirection = FlowDirection.VerticalRightToLeft;
tl.TextAlignment = TextAlignment.Justified;
// IPAゴシックフォントを埋め込み
var font = Common.Util.getFont();
doc.FontEmbedMode = FontEmbedMode.EmbedFullFont;
var tf = new TextFormat() { Font = font, FontSize = 11 };
var tf2 = new TextFormat() { Font = font, FontSize = 14 };
// テストテキストを繰り返していくつかのページを埋める:
StreamReader sr = new StreamReader(Path.Combine("Resources", "Text", "gingatetsudono_yoru.txt"));
List<string> textList = getTextList();
for (int i = 0; i < textList.Count; i++)
{
string line = textList[i];
// 半角数字が3桁以上続く場合を抽出
line = Regex.Replace(line,("[0-9]{3,}"),new System.Text.RegularExpressions.MatchEvaluator(HanToZen));
// 半角数字1桁のみのパターン(前後が半角数字ではない数字一桁)を抽出
line = Regex.Replace(line,("(?<![0-9])[0-9]{1,}(?![0-9])"),new System.Text.RegularExpressions.MatchEvaluator(HanToZen));
// 見出しの処理
if (line.StartsWith("[#5字下げ]"))
{
var result = Regex.Replace(line.Replace("[#5字下げ]", ""), "[#「.*]|《.*》", "");
tl.Append(result, tf2);
}
else
{
var result = Regex.Replace(line, "[#「.*]|《.*》", "");
tl.Append(result, tf);
}
tl.AppendLine();
}
sr.Close();
// 2つの水平な列のレイアウトテキスト:
// (このサンプルのロジック/コードはArabicColumnsと同じです):
const int NCOLS = 2;
var margin = 36f;
var gap = 18f;
var page = doc.NewPage();
page.Landscape = true;
var colHeight = (page.Size.Height - margin * 2 - gap * (NCOLS - 1)) / NCOLS;
tl.MaxWidth = page.Size.Width;
tl.MaxHeight = page.Size.Height;
tl.MarginLeft = tl.MarginRight = margin;
tl.MarginTop = margin;
tl.MarginBottom = margin + (colHeight + gap) * (NCOLS - 1);
//テキストを流すための任意の矩形を指定することができます。
//この場合、画像を描画するために3つの領域を追加します。
tl.ObjectRects = new List<ObjectRect>()
{
new ObjectRect(page.Size.Width - margin - 600, margin, 320, 180),
new ObjectRect(page.Size.Width - margin - 250, page.Size.Height - margin - 270, 180, 270),
};
//オブジェクトをイメージ領域に変換し、調整して見栄えの良いパディングを提供する:
var rClouds = tl.ObjectRects[0].ToRectangleF();
rClouds.Inflate(-4, -3);
var rkenji = tl.ObjectRects[1].ToRectangleF();
rkenji.Inflate(-4, -3);
page.Graphics.DrawImage(clouds, rClouds, null, ia);
page.Graphics.DrawImage(kenji, rkenji, null, ia);
//呼び出し:テキストを描画するのに必要なグリフを計算し、それをレイアウトします。
tl.PerformLayout(true);
bool done = false;
while (!done) //レンダリングするテキストがまだある間にループする
{
for (int col = 0; col < NCOLS; ++col)
{
int nextcol = (col < NCOLS - 1) ? col + 1 : 0;
// TextSplitOptionsは、残りのテキストのレイアウト方法をTextLayout.Split()に伝えます。
//この場合、上下のマージンを更新することによって、列ごとに進めます。
var tso = new TextSplitOptions(tl)
{
RestMarginTop = margin + (colHeight + gap) * nextcol,
RestMarginBottom = margin + (colHeight + gap) * (NCOLS - 1 - nextcol)
};
var split = tl.Split(tso, out TextLayout rest);
page.Graphics.DrawTextLayout(tl, PointF.Empty);
if (split != SplitResult.Split)
{
done = true;
break;
}
tl = rest;
}
if (!done)
{
page = doc.NewPage();
page.Landscape = true;
// 最初のページにイメージをレンダリングしたいだけなので、ObjectRectをクリアします:
if (tl.ObjectRects != null)
{
tl.ObjectRects = null;
// レイアウトをやり直す必要がありますが、グリフを再計算する必要はありません:
tl.PerformLayout(false);
}
}
}
// PDF ドキュメントの保存
doc.Save(stream);
return doc.Pages.Count;
}
private List<string> _textList = new List<string>();
private List<string> getTextList(int lines=1000)
{
try
{
using (StreamReader sr = new StreamReader(Path.Combine("Resources", "Text", "gingatetsudono_yoru.txt")))
{
for (int i = 0; i < lines; i++)
{
if (sr.EndOfStream)
{
i = lines;
}
else
{
_textList.Add(sr.ReadLine());
}
}
}
}
catch (Exception e)
{
Console.WriteLine("The file could not be read:");
Console.WriteLine(e.Message);
}
return _textList;
}
//MatchEvaluatorデリゲートメソッド
private static string HanToZen(System.Text.RegularExpressions.Match m)
{
string result = "";
//引数で取得した文字列をCharの配列に変換
Char[] charAr = m.Value.ToCharArray();
//Charの配列でマッチした数字を全角に変換
foreach (var charValue in charAr)
{
// Charの文字コードで'0'との差分に'0'を足すと半角が全角にかわる
// '0'〜'9' は '0'〜'9'の並びと同じ
//(例 2は0の2つとなりにあるように、2は0の2つとなりにある
result += ((char)((charValue - '0') + '0')).ToString();
}
return result;
}
}
}