ArabicText.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 Arabic text on a GcBitmap.
    public class ArabicText
    {
        public GcBitmap GenerateImage (int pixelWidth = 1024, int pixelHeight = 1024, bool opaque = true, float dpiX = 96, float dpiY = 96)
        {
            string text = "العربية أكبر لغات المجموعة السامية من حيث عدد المتحدثين، وإحدى أكثر اللغات انتشارًا في العالم، يتحدثها أكثر من 422 مليون نسمة،1 ويتوزع متحدثوها في المنطقة المعروفة باسم الوطن العربي، بالإضافة إلى العديد من المناطق الأخرى المجاورة كالأحواز وتركيا وتشاد ومالي والسنغالوارتيرياوللغة العربية أهمية قصوى لدى أتباع الديانة الإسلامية، فهي لغة مصدري التشريع الأساسيين في الإسلام: القرآن، والأحاديث النبوية المروية عن النبي محمد، ولا تتم الصلاة في الإسلام (وعبادات أخرى) إلا بإتقان بعض من كلمات هذه اللغة. والعربية هي أيضًا لغة طقسية رئيسية لدى عدد من الكنائس المسيحية في العالم العربي، كما كتبت بها الكثير من أهم الأعمال الدينية والفكرية اليهودية في العصور الوسطى. وأثّر انتشار الإسلام، وتأسيسه دولًا، أرتفعت مكانة اللغة العربية، وأصبحت لغة السياسة والعلم والأدب لقرون طويلة في الأراضي التي حكمها المسلمون، وأثرت العربية، تأثيرًا مباشرًا أو غير مباشر على كثير من اللغات الأخرى في العالم الإسلامي، كالتركية والفارسية والأرديةوالالبانية واللغات الأفريقية الاخرى واللغات الأوروبية مثل الروسية والإنجليزية والفرنسية والأسبانية والايطالية والألمانية.كما انها تدرس بشكل رسمى او غير رسمى في الدول الاسلامية والدول الأفريقية المحادية للوطن العربى.";
            var ia = new ImageAlign(ImageAlignHorz.Left, ImageAlignVert.Top, true, true, false, false, false);

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

                var tl = g.CreateTextLayout();
                tl.FirstLineIndent = 18;
                tl.ParagraphSpacing = 6;
                tl.TextAlignment = TextAlignment.Justified;
                tl.RightToLeft = true;

                var tf = new TextFormat()
                {
                    Font = Font.FromFile(Path.Combine("Resources", "Fonts", "times.ttf")),
                    FontSize = 14
                };

                // Repeat test text to fill a few columns:
                for (int i = 0; i < 4; ++i)
                {
                    tl.Append(text, tf);
                    tl.AppendLine();
                }

                // Layout text in 3 columns:
                // (The logic/code in this sample is identical to JapaneseColumns
                const int NCOLS = 3;
                var margin = 48f;
                var gap = 24f;
                var colWid = (bmp.Width - margin * 2 - gap * (NCOLS - 1)) / NCOLS;
                tl.MaxWidth = bmp.Width;
                tl.MaxHeight = bmp.Height;
                tl.MarginTop = tl.MarginBottom = margin;
                tl.MarginRight = margin;
                tl.MarginLeft = margin + (colWid + 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:
                var rect1 = new ObjectRect(bmp.Width - margin - 315, margin, 320, 320);
                var rect2 = new ObjectRect(margin + 133, margin + 80, 177, 133);
                var rect3 = new ObjectRect(margin, bmp.Height - margin - 400, 400, 385);
                tl.ObjectRects = new List<ObjectRect>() { rect1, rect2, rect3 };

                // 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)
                    {
                        RestMarginRight = margin + (colWid + gap) * nextcol,
                        RestMarginLeft = margin + (colWid + gap) * (NCOLS - 1 - nextcol)
                    };
                    var split = tl.Split(tso, out TextLayout rest);
                    g.DrawTextLayout(tl, PointF.Empty);
                    if (split != SplitResult.Split)
                    {
                        break;
                    }
                    tl = rest;
                }

                rect1.Height -= 5;
                rect2.Left += 10;
                rect3.Width -= 10;

                using (var img = Common.Util.ImageFromFile(Path.Combine("Resources", "Images", "reds.jpg")))
                    g.DrawImage(img, rect1.ToRectangleF(), null, ia);
                using (var img = Common.Util.ImageFromFile(Path.Combine("Resources", "Images", "firth.jpg")))
                    g.DrawImage(img, rect2.ToRectangleF(), null, ia);
                using (var img = Common.Util.ImageFromFile(Path.Combine("Resources", "Images", "purples.jpg")))
                    g.DrawImage(img, rect3.ToRectangleF(), null, ia);

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