MarkupPerWord.cs
//
// This code is part of Document Solutions for PDF demos.
// Copyright (c) MESCIUS inc. All rights reserved.
//
using System;
using System.IO;
using System.Drawing;
using GrapeCity.Documents.Pdf;
using GrapeCity.Documents.Text;
using GrapeCity.Documents.Pdf.Annotations;
using System.Collections.Generic;
using GrapeCity.Documents.Pdf.TextMap;
using GrapeCity.Documents.Common;

namespace DsPdfWeb.Demos
{
    // This example shows how to find all occurrences of two words in a PDF document and
    // highlight each of those words with different color using text markup highlight annotations.
    // Points of interest in this code:
    // - We use separate FindText() calls for each word. To speed up the searches,
    //   for each page we cache the text map and reuse it in the two FindText() calls.
    //   While the performance improvement is minor in the case of two words, it would
    //   be significant if the task were to find multiple words (e.g. when building a word index,
    //   as illustrated in the WordIndex example which uses a similar approach.
    // - In order to highlight each of the two words using a different color,
    //   on each page we create one highlight markup annotation per word.
    public class MarkupPerWord
    {
        public int CreatePDF(Stream stream)
        {
            const string word0 = "JavaScript";
            const string word1 = "framework";

            // Load the PDF:
            var doc = new GcPdfDocument();
            using var fs = File.OpenRead(Path.Combine("Resources", "PDFs", "CompleteJavaScriptBook.pdf"));
            doc.Load(fs);

            // A FindTextParams for each of the search words:
            var ft0 = new FindTextParams(word0, wholeWord: false, matchCase: false, regex: false);
            var ft1 = new FindTextParams(word1, wholeWord: false, matchCase: false, regex: false);

            // Find and highlight words on the pages, caching and reusing the text map
            // of each page for the two searches:
            foreach (var p in doc.Pages)
            {
                // Find and highlight the first word:
                var textMap = p.GetTextMap();
                TextMarkupAnnotation markup0 = null;
                List<Quadrilateral> area0 = null;
                textMap.FindText(ft0, fp_ => {
                    markup0 ??= new TextMarkupAnnotation()
                    {
                        Subject = word0,
                        Page = doc.Pages[fp_.PageIndex],
                        MarkupType = TextMarkupType.Highlight,
                        Color = Color.Cyan
                    };
                    area0 ??= new List<Quadrilateral>();
                    foreach (var b in fp_.Bounds)
                        area0.Add(b);
                });
                if (markup0 != null)
                    markup0.Area = area0;

                // Find and highlight the second word:
                TextMarkupAnnotation markup1 = null;
                List<Quadrilateral> area1 = null;
                textMap.FindText(ft1, fp_ => {
                    markup1 ??= new TextMarkupAnnotation()
                    {
                        Subject = word1,
                        Page = doc.Pages[fp_.PageIndex],
                        MarkupType = TextMarkupType.Highlight,
                        Color = Color.Fuchsia
                    };
                    area1 ??= new List<Quadrilateral>();
                    foreach (var b in fp_.Bounds)
                        area1.Add(b);
                });
                if (markup1 != null)
                    markup1.Area = area1;
            }

            // Done:
            doc.Save(stream);
            return doc.Pages.Count;
        }
    }
}