JapaneseText.cs
//
// This code is part of GrapeCity Documents for Imaging samples.
// Copyright (c) GrapeCity, Inc. All rights reserved.
//
using System;
using System.IO;
using System.Drawing;
using System.Collections.Generic;
using System.Linq;
using GrapeCity.Documents.Drawing;
using GrapeCity.Documents.Text;
using GrapeCity.Documents.Imaging;

namespace GcImagingWeb.Samples
{
    // This sample shows how to draw Japanese text on a GcBitmap.
    public class JapaneseText
    {
        public GcBitmap GenerateImage (int pixelWidth = 1024, int pixelHeight = 1024, bool opaque = true, float dpiX = 96, float dpiY = 96)
        {
            string text = "日本語(にほんご、にっぽんご)は、主として、日本列島で使用されてきた言語である。日本手話を母語とする者などを除いて、ほぼ全ての日本在住者は日本語を第一言語とする。日本国は法令上、公用語を明記していないが、事実上の公用語となっており、学校教育の「国語」で教えられる。使用者は、日本国内を主として約\uFF11億\uFF13千万人。日本語の文法体系や音韻体系を反映する手話として日本語対応手話がある。";
            var ia = new ImageAlign(ImageAlignHorz.Left, ImageAlignVert.Top, true, true, true, false, false);

            int pageWidth = pixelWidth;
            int pageHeight = pixelHeight;

            var bmp = new GcBitmap(pixelWidth, pixelHeight, true, dpiX, dpiY);
            using (var g = bmp.CreateGraphics(Color.White))
            {
                g.Renderer.Multithreaded = true;

                // The TextLayout that will hold and render the text:
                var tl = g.CreateTextLayout();
                tl.FirstLineIndent = 18;
                tl.ParagraphSpacing = 6;
                tl.FlowDirection = FlowDirection.VerticalRightToLeft;
                tl.TextAlignment = TextAlignment.Justified;
                tl.DefaultFormat.Font = Font.FromFile(Path.Combine("Resources", "Fonts", "times.ttf"));
                var tf = new TextFormat()
                {
                    Font = Font.FromFile(Path.Combine("Resources", "Fonts", "yumin.ttf")),
                    FontSize = 14,
                };
                // Repeat test text to fill the page:
                for (int i = 0; i < 12; ++i)
                {
                    tl.Append(text, tf);
                    tl.AppendLine();
                }

                // Layout text in 4 horizontal columns:
                // (The logic/code in this sample is identical to ArabicText):
                const int NCOLS = 4;
                var margin = 36f;
                var gap = 18f;
                var colHeight = (pageHeight - margin * 2 - gap * (NCOLS - 1)) / NCOLS;
                tl.MaxWidth = pageWidth;
                tl.MaxHeight = pageHeight;
                tl.MarginLeft = tl.MarginRight = margin;
                tl.MarginTop = margin;
                tl.MarginBottom = margin + (colHeight + gap) * (NCOLS - 1);
                // We can specify arbitrary rectangles for the text to flow around.
                // In this case, we add 3 areas to draw some images:
                tl.ObjectRects = new List<ObjectRect>()
                    {
                        new ObjectRect(pageWidth - margin - 267, margin, 267, 200),
                        new ObjectRect(margin + 100, margin + 60, 133, 100),
                        new ObjectRect(margin, pageHeight - margin - 301, 200, 301),
                    };
                using (var clouds = Common.Util.ImageFromFile(Path.Combine("Resources", "Images", "clouds.jpg")))
                    g.DrawImage(clouds, tl.ObjectRects[0].ToRectangleF(), null, ia);
                using (var firth = Common.Util.ImageFromFile(Path.Combine("Resources", "Images", "firth.jpg")))
                    g.DrawImage(firth, tl.ObjectRects[1].ToRectangleF(), null, ia);
                using (var lavender = Common.Util.ImageFromFile(Path.Combine("Resources", "Images", "lavender.jpg")))
                    g.DrawImage(lavender, tl.ObjectRects[2].ToRectangleF(), null, ia);

                // THE call: it calculates the glyphs needed to draw the text, and lays it out:
                tl.PerformLayout(true);

                for (int col = 0; col < NCOLS; ++col)
                {
                    int nextcol = (col < NCOLS - 1) ? col + 1 : 0;
                    // TextSplitOptions tell TextLayout.Split() how to layout the remaining text.
                    // In this case we advance from column to column by updating top and bottom margins:
                    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);
                    g.DrawTextLayout(tl, PointF.Empty);
                    if (split != SplitResult.Split)
                        break;
                    tl = rest;
                }

                // Draw border around the whole image:
                g.DrawRectangle(new RectangleF(0, 0, bmp.Width, bmp.Height), Color.DarkSlateBlue, 4);
            }
            return bmp;
        }
    }
}