internal String ReplaceParametersInString(String source, JObject parameterObject)
        {
            ReplaceResult result   = new ReplaceResult();
            var           newValue = Regex.Replace(
                source,
                @"(?<!%)%(?!%)(?<match>.+?)(?<!%)%(?!%)",
                new MatchEvaluator(m =>
            {
                var parameterName = m.Groups["match"].Value.Trim('{', '}');
                var paramValue    = GetParameterValue(parameterName, parameterObject);
                if (paramValue == null)
                {
                    result.MissingParams.Add(parameterName);
                    return("%" + parameterName + "%");
                }
                result.HasReplaced = true;
                return(paramValue);
            }));

            if (result.MissingParams.Count > 0)
            {
                throw new ConfigurationErrorsException("Missing parameters: " +
                                                       result.MissingParams.Aggregate((s1, s2) => s1 + ", " + s2));
            }
            if (newValue.Contains("%%"))
            {
                newValue = newValue.Replace("%%", "%");
            }
            return(newValue);
        }
 internal void Merge(ReplaceResult result)
 {
     HasReplaced = HasReplaced || result.HasReplaced;
     foreach (var missingParam in result.MissingParams)
     {
         MissingParams.Add(missingParam);
     }
 }
        public static bool Show(string name, out ReplaceResult result)
        {
            ReplaceBox box = new ReplaceBox();

            box.label1.Text = string.Format(Properties.Resources.ReplaceConfirm, name);

            box.ShowDialog();
            result = box.result;

            return(true);
        }
        private JToken ManageParametersInJToken(
            JObject parameterObject,
            ReplaceResult result,
            JToken token)
        {
            String  value           = token.ToString();
            Boolean objectParameter = value.StartsWith("%{") && value.EndsWith("}%");

            if (Regex.IsMatch(value, "(?<!%)%(?!%).+?(?<!%)%(?!%)"))
            {
                String newValue = Regex.Replace(
                    value,
                    @"(?<!%)%(?!%)(?<match>.+?)(?<!%)%(?!%)",
                    new MatchEvaluator(m =>
                {
                    var parameterName = m.Groups["match"].Value.Trim('{', '}');
                    var paramValue    = GetParameterValue(parameterName, parameterObject);
                    if (paramValue == null)
                    {
                        result.MissingParams.Add(parameterName);
                        return(objectParameter ? value : "%" + parameterName + "%");
                    }
                    result.HasReplaced = true;
                    return(paramValue);
                }));
                if (objectParameter)
                {
                    if (newValue == value)
                    {
                        return(newValue);                   //object parameter that is missing
                    }
                    try
                    {
                        return((JToken)JsonConvert.DeserializeObject(newValue));
                    }
                    catch (Exception ex)
                    {
                        //parameters has some error, maybe it is malformed, treat as if parameter is missing.
                        return("Parameter " + value + " is an object parameter and cannot be parsed: " + newValue);
                    }
                }
                else
                {
                    return(newValue);
                }
            }
            return(token);
        }
Example #5
0
        /// <summary>
        /// Implementation to execute when replace action.
        /// </summary>
        /// <param name="input">stream input</param>
        /// <param name="context">Input context</param>
        /// <returns>
        /// <para>
        /// A <see cref="ReplaceResult"/> reference that contains the result of the operation, to check if the operation is correct, the <b>Success</b>
        /// property will be <b>true</b> and the <b>Value</b> property will contain the value; Otherwise, the the <b>Success</b> property
        /// will be false and the <b>Errors</b> property will contain the errors associated with the operation, if they have been filled in.
        /// </para>
        /// <para>
        /// The type of the return value is <see cref="ReplaceResultData"/>, which contains the operation result
        /// </para>
        /// </returns>
        protected override ReplaceResult ReplaceImpl(Stream input, IInput context)
        {
            if (Image == Design.Image.PdfImage.Null)
            {
                return(ReplaceResult.CreateSuccessResult(new ReplaceResultData
                {
                    Context = context,
                    InputStream = input,
                    OutputStream = input
                }));
            }

            if (Style == null)
            {
                Style = PdfImageStyle.Default;
            }

            return(ReplaceImpl(context, input, Text, ReplaceOptions, Image, ImageOffset, Style, UseTestMode));
        }
Example #6
0
        /// <summary>
        /// Try to replace an element in this input.
        /// </summary>
        /// <param name="data">Reference to replacement object information</param>
        /// <returns>
        /// <para>
        /// A <see cref="ReplaceResult"/> reference that contains the result of the operation, to check if the operation is correct, the <b>Success</b>
        /// property will be <b>true</b> and the <b>Result</b> property will contain the Result; Otherwise, the the <b>Success</b> property
        /// will be false and the <b>Errors</b> property will contain the errors associated with the operation, if they have been filled in.
        /// </para>
        /// <para>
        /// The type of the return Result is <see cref="ReplaceResultData"/>, which contains the operation result
        /// </para>
        /// </returns>
        public ReplaceResult Replace(IReplace data)
        {
            Logger.Instance.Debug("");
            Logger.Instance.Debug(" Assembly: iTin.Utilities.Pdf.Writer, Namespace: iTin.Utilities.Pdf.Writer, Class: PdfInput");
            Logger.Instance.Debug(" Try to replace an element in this input");
            Logger.Instance.Debug($" > Signature: ({typeof(ReplaceResult)}) Replace({typeof(IReplace)})");
            Logger.Instance.Debug($"   > data: {data}");

            ReplaceResult result = ReplaceImplStrategy(data, this);

            if (AutoUpdateChanges)
            {
                Input = result.Result.OutputStream;
            }

            Logger.Instance.Debug($" > Output: Replacement = {result.Success}");

            return(result);
        }
        internal ReplaceResult ReplaceParameters(JObject source, JObject parameterObject)
        {
            ReplaceResult result = new ReplaceResult();

            foreach (var property in source.Properties())
            {
                if (property.Value is JObject)
                {
                    var replaceReturn = ReplaceParameters((JObject)property.Value, parameterObject);
                    result.Merge(replaceReturn);
                }
                else if (property.Value is JArray)
                {
                    ReplaceParametersInArray(parameterObject, result, property.Value as JArray);
                }
                else if (property.Value is JToken)
                {
                    source[property.Name] = ManageParametersInJToken(parameterObject, result, property.Value);
                }
            }
            return(result);
        }
        private void ReplaceParametersInArray(
            JObject parameterObject,
            ReplaceResult result,
            JArray array)
        {
            for (int i = 0; i < array.Count; i++)
            {
                var element = array[i];

                if (element is JObject)
                {
                    var replaceReturn = ReplaceParameters((JObject)element, parameterObject);
                    result.Merge(replaceReturn);
                }
                else if (element is JArray)
                {
                    ReplaceParametersInArray(parameterObject, result, element as JArray);
                }
                else if (element is JToken)
                {
                    array[i] = ManageParametersInJToken(parameterObject, result, element);
                }
            }
        }
        internal static void Set(Entity entity, string kindCode, out long replacedTiles, out ReplaceResult result)
        {
            replacedTiles = 0;
            result        = ReplaceResult.Success;

            EntityCheck(entity);

            var target = PositionClone()[entity];

            if (target.Pos1 == default(Vector3D) || target.Pos2 == default(Vector3D))
            {
                result = ReplaceResult.InvalidPositions;
                return;
            }

            var newTileConfig = GameContext.TileDatabase.AllMaterials().FirstOrDefault(x =>
                                                                                       string.Equals(x.Code, kindCode, StringComparison.CurrentCultureIgnoreCase));

            if (newTileConfig == null)
            {
                result = ReplaceResult.InvalidTile;
                return;
            }

            var newTile = newTileConfig.MakeTile();

            var vc = new VectorCubeI(target.Pos1.From3Dto3I(), target.Pos2.From3Dto3I());

            SaveUndo(entity, vc.Start, vc.End, true, kindCode);

            var count = 0;

            var list = new List <RenderItem>();

            replacedTiles = count;
        }
        /// <summary>
        /// replace text in files
        /// </summary>
        /// <param name="editableFolder">paths</param>
        /// <param name="mode">where to search</param>
        /// <param name="searched">text to search</param>
        /// <param name="replaceWith">replace text with</param>
        /// <param name="caseSensitive">match case</param>
        /// <param name="regex">regular expressions</param>
        /// <returns>repalce result</returns>
        public ReplaceResult ReplaceText(EditableFolder editableFolder, EditMode mode, string searched, string replaceWith, bool caseSensitive, bool regex)
        {
            // replaceWith can be empty string!
            if (string.IsNullOrEmpty(searched) || replaceWith == null)
            {
                editableFolder.SendOutput("Cant search / replace empty text");
                return(null);
            }
            List <string> allFiles = editableFolder.GetAllFiles();

            // path -> position
            ReplaceResult results = new ReplaceResult(searched, replaceWith, caseSensitive, regex);
            // pattern with/without regex
            string          pattern = regex ? searched : Regex.Escape(searched);
            string          fileText;
            string          replacedFileText;
            MatchCollection matches;



            if (mode == EditMode.CONTENT || mode == EditMode.BOTH)
            {
                foreach (string file in allFiles)
                {
                    try
                    {
                        fileText = File.ReadAllText(file);
                        // find matches of text that will be replaced
                        matches = Regex.Matches(fileText, pattern, caseSensitive ? RegexOptions.None : RegexOptions.IgnoreCase);
                        // if there are matches
                        if (matches.Count > 0)
                        {
                            results.AddResult(file, matches);

                            // replace in file text
                            replacedFileText = Regex.Replace(fileText, pattern, replaceWith, caseSensitive ? RegexOptions.None : RegexOptions.IgnoreCase);
                            // write to file
                            File.WriteAllText(file, replacedFileText);
                        }
                    }
                    catch (Exception ex)
                    {
                        results.AddResult(file + " -> " + ex.Message, EditErrorCode.NOTFOUND);
                    }
                }
            }

            // must be done after editing files, otherwise file wont exist anymore
            if (mode == EditMode.NAME || mode == EditMode.BOTH)
            {
                // only change file name, not path
                string fileName;
                foreach (string file in allFiles)
                {
                    fileName = file.Substring(file.LastIndexOf('\\') + 1);
                    if (Regex.IsMatch(fileName, pattern))
                    {
                        try
                        {
                            File.Move(file, file.Replace(fileName, "") + Regex.Replace(fileName, pattern, replaceWith));
                            results.AddResult(file, EditErrorCode.FILENAME);
                        }
                        catch (Exception ex)
                        {
                            results.AddResult(file + " -> " + ex.Message, EditErrorCode.NOTFOUND);
                        }
                    }
                }

                // include directory names
                List <string> allDirs = editableFolder.GetAllDirectories();
                foreach (string dir in allDirs)
                {
                    if (Regex.IsMatch(dir, pattern))
                    {
                        try
                        {
                            Directory.Move(dir, Regex.Replace(dir, pattern, replaceWith));
                            results.AddResult(dir, EditErrorCode.FILENAME);
                        }
                        catch (Exception ex)
                        {
                            results.AddResult(dir + " -> " + ex.Message, EditErrorCode.NOTFOUND);
                        }
                    }
                }
            }
            // reset if file names could have been edited
            editableFolder.ClearSelection();
            return(results);
        }
Example #11
0
 private ReplaceResult ReplaceImplStrategy(IReplace data, IInput context)
 => data == null?ReplaceResult.CreateErroResult("Missing data") : data.Apply(ToStream(), context);
Example #12
0
        /// <summary>
        /// Merges all <see cref="PdfInput"/> entries.
        /// </summary>
        /// <returns>
        /// <para>
        /// A <see cref="OutputResult"/> reference that contains the result of the operation, to check if the operation is correct, the <b>Success</b>
        /// property will be <b>true</b> and the <b>Result</b> property will contain the Result; Otherwise, the the <b>Success</b> property
        /// will be false and the <b>Errors</b> property will contain the errors associated with the operation, if they have been filled in.
        /// </para>
        /// <para>
        /// The type of the return Result is <see cref="OutputResultData"/>, which contains the operation result
        /// </para>
        /// </returns>
        public OutputResult TryMergeInputs()
        {
            Logger.Instance.Debug("");
            Logger.Instance.Debug(" Assembly: iTin.Utilities.Pdf.Writer, Namespace: iTin.Utilities.Pdf.Writer, Class: PdfObject");
            Logger.Instance.Debug($" Merges all {typeof(PdfInput)} entries into a new {typeof(PdfObject)}");
            Logger.Instance.Debug($" > Signature: ({typeof(OutputResult)}) TryMergeInputs()");

            var items = Items.ToList();

            if (Configuration.UseIndex)
            {
                items = items.OrderBy(i => i.Index).ToList();
            }

            try
            {
                var outStream = new MemoryStream();
                using (var document = new Document())
                {
                    using (var copy = new PdfCopy(document, outStream))
                    {
                        document.Open();

                        PdfReader.unethicalreading = true;

                        foreach (var item in items)
                        {
                            var itemAsStream = item.Clone().ToStream();
                            if (itemAsStream == null)
                            {
                                continue;
                            }

                            itemAsStream.Position = 0;
                            copy.AddDocument(new PdfReader(itemAsStream));
                        }
                    }
                }

                bool hasSystemTags = false;
                if (Configuration.Tags.Any())
                {
                    hasSystemTags = true;

                    var pdfRawMerged = new PdfInput
                    {
                        AutoUpdateChanges = true,
                        Input             = outStream.GetBuffer().ToMemoryStream().Clone()
                    };

                    ReplaceResult rawMergedResult = null;
                    foreach (var tag in Configuration.Tags)
                    {
                        rawMergedResult = pdfRawMerged.Replace(new ReplaceSystemTag(tag.BuildReplacementObject()));
                    }

                    if (rawMergedResult.Success)
                    {
                        outStream = new MemoryStream((byte[])rawMergedResult.Result.OutputStream.AsByteArray().Clone());
                    }
                }

                bool hasGlobalReplacements = false;
                if (Configuration.GlobalReplacements.Any())
                {
                    hasGlobalReplacements = true;

                    var pdfRawMergedWithTags = new PdfInput
                    {
                        AutoUpdateChanges = true,
                        Input             = hasSystemTags ? outStream.ToMemoryStream().Clone() : outStream.GetBuffer().ToMemoryStream().Clone()
                    };

                    ReplaceResult rawMergedWithTagsResult = null;
                    foreach (var replacement in Configuration.GlobalReplacements)
                    {
                        rawMergedWithTagsResult = pdfRawMergedWithTags.Replace(new ReplaceText(replacement));
                    }

                    if (rawMergedWithTagsResult.Success)
                    {
                        if (rawMergedWithTagsResult.Result.OutputStream.Position != 0)
                        {
                            rawMergedWithTagsResult.Result.OutputStream.Position = 0;
                        }

                        outStream = new MemoryStream((byte[])rawMergedWithTagsResult.Result.OutputStream.AsByteArray().Clone());
                    }
                }

                if (Configuration.DeletePhysicalFilesAfterMerge)
                {
                    foreach (var item in items)
                    {
                        var inputType = item.InputType;
                        if (inputType != KnownInputType.Filename)
                        {
                            continue;
                        }

                        if (item.DeletePhysicalFilesAfterMerge)
                        {
                            File.Delete(TypeHelper.ToType <string>(item.Input));
                        }
                    }
                }

                var safeOutAsByteArray  = (hasSystemTags || hasGlobalReplacements) ? outStream.AsByteArray() : outStream.GetBuffer();
                var outputInMegaBytes   = (float)safeOutAsByteArray.Length / PdfObjectConfig.OneMegaByte;
                var generateOutputAsZip = outputInMegaBytes > Configuration.CompressionThreshold;
                var zipped = Configuration.AllowCompression && generateOutputAsZip;

                return
                    (OutputResult.CreateSuccessResult(
                         new OutputResultData
                {
                    Zipped = zipped,
                    Configuration = Configuration,
                    UncompressOutputStream = safeOutAsByteArray.ToMemoryStream()
                }));
            }
            catch (Exception ex)
            {
                return(OutputResult.FromException(ex));
            }
        }
Example #13
0
        private static ReplaceResult ReplaceImpl(IInput context, Stream input, string oldText, string newText, ReplaceTextOptions options, PointF offset, PdfTextStyle style, YesNo useTestMode)
        {
            var outputStream = new MemoryStream();

            try
            {
                var reader  = new PdfReader(input);
                var stamper = new PdfStamper(reader, outputStream);

                var pages = reader.NumberOfPages;
                for (var page = 1; page <= pages; page++)
                {
                    var strategy = new CustomLocationTextExtractionStrategy();
                    var cb       = stamper.GetOverContent(page);

                    // Send some data contained in PdfContentByte, looks like the first is always cero for me and the second 100,
                    // but i'm not sure if this could change in some cases.
                    strategy.UndercontentCharacterSpacing  = cb.CharacterSpacing;
                    strategy.UndercontentHorizontalScaling = cb.HorizontalScaling;

                    // It's not really needed to get the text back, but we have to call this line ALWAYS,
                    // because it triggers the process that will get all chunks from PDF into our strategy Object
                    var allStrings   = PdfTextExtractor.GetTextFromPage(reader, page, strategy);
                    var stringsArray = allStrings.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);

                    // The real getter process starts in the following line
                    var textMatchesFound = strategy.GetExtendedTextLocations(oldText, options).ToList();

                    // Text matches found contains all text with locations, so do whatever you want with it
                    foreach (var match in textMatchesFound)
                    {
                        // Delete tag
                        var bColor = BaseColor.WHITE;
                        cb.SetColorFill(bColor);
                        cb.Rectangle(match.Rect.Left, match.Rect.Bottom, match.Rect.Width, match.Rect.Height);
                        cb.Fill();

                        // Calculates new rectangle
                        var r = BuildRectangleByStrategies(match, oldText, strategy, cb, (string[])stringsArray.Clone(), options);

                        //PdfGState gs = new PdfGState {FillOpacity = 0.3f};
                        //cb.SaveState();
                        //cb.SetGState(gs);
                        //cb.SetRGBColorFill(200, 200, 0);

                        // Add table
                        var table = new PdfPTable(1)
                        {
                            TotalWidth = r.Width - offset.X
                        };
                        table.AddCell(PdfHelper.CreateCell(newText, style, useTestMode));
                        table.WriteSelectedRows(-1, -1, r.X + offset.X, r.Y - offset.Y, cb);
                        cb.Fill();

                        //cb.RestoreState();
                    }

                    cb.Fill();
                    cb.Stroke();
                }

                stamper.Close();
                reader.Close();

                return(ReplaceResult.CreateSuccessResult(new ReplaceResultData
                {
                    Context = context,
                    InputStream = input,
                    OutputStream = new MemoryStream(outputStream.GetBuffer())
                }));
            }
            catch (Exception ex)
            {
                return(ReplaceResult.FromException(
                           ex,
                           new ReplaceResultData
                {
                    Context = context,
                    InputStream = input,
                    OutputStream = input
                }));
            }
        }
Example #14
0
 private void btnYes_Click(object sender, EventArgs e)
 {
     result = ReplaceResult.Yes;
     FormClosing -= ReplaceBox_FormClosing;
     Close();
 }
Example #15
0
 private void btnYes_Click(object sender, EventArgs e)
 {
     result       = ReplaceResult.Yes;
     FormClosing -= ReplaceBox_FormClosing;
     Close();
 }
        private void btnNo_Click(object sender, EventArgs e)
        {
            result = ReplaceResult.No;

            Close();
        }
Example #17
0
 // TODO: A local won't work for iterators.
 public override MethodContract VisitMethodContract(MethodContract contract){
   if ( contract == null ) return null;
   Method m = contract.DeclaringMethod;
   if (m == null) return contract;
   if ( m.ReturnType != null && m.ReturnType != SystemTypes.Void && contract.Ensures != null && contract.Ensures.Count > 0 ){
     ReplaceResult rr = new ReplaceResult();
     for ( int i = 0, n = contract.Ensures.Count; i < n; i++ ){
       if ( contract.Ensures[i] is EnsuresNormal ){
         contract.Ensures[i].PostCondition = (Expression) rr.Visit(contract.Ensures[i].PostCondition);
       }
     }
   }
   if (contract.DeclaringMethod != null && contract.DeclaringMethod.Template != null &&
     !contract.DeclaringMethod.IsNormalized) return contract;
   return base.VisitMethodContract(contract);
 }
Example #18
0
 private void btnNotoall_Click(object sender, EventArgs e)
 {
     result = ReplaceResult.NoToAll;
     FormClosing -= ReplaceBox_FormClosing;
     Close();
 }
        private void btnYestoall_Click(object sender, EventArgs e)
        {
            result = ReplaceResult.YesToAll;

            Close();
        }
Example #20
0
        private static ReplaceResult ReplaceImpl(IInput context, Stream input, string oldText, ReplaceTextOptions options, Design.Image.PdfImage image, PointF imageOffset, PdfImageStyle style, YesNo useTestMode)
        {
            var outputStream = new MemoryStream();

            try
            {
                using (var reader = new PdfReader(input))
                    using (var stamper = new PdfStamper(reader, outputStream))
                    {
                        var pages = reader.NumberOfPages;
                        for (var page = 1; page <= pages; page++)
                        {
                            var strategy = new CustomLocationTextExtractionStrategy();
                            var cb       = stamper.GetOverContent(page);

                            // Send some data contained in PdfContentByte, looks like the first is always cero for me and the second 100,
                            // but i'm not sure if this could change in some cases.
                            strategy.UndercontentCharacterSpacing  = cb.CharacterSpacing;
                            strategy.UndercontentHorizontalScaling = cb.HorizontalScaling;

                            // It's not really needed to get the text back, but we have to call this line ALWAYS,
                            // because it triggers the process that will get all chunks from PDF into our strategy Object
                            var allStrings   = PdfTextExtractor.GetTextFromPage(reader, page, strategy);
                            var stringsArray = allStrings.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);

                            // The real getter process starts in the following line
                            var textMatchesFound = strategy.GetExtendedTextLocations(oldText, options).ToList();

                            // MatchesFound contains all text with locations
                            foreach (var match in textMatchesFound)
                            {
                                // Delete tag
                                var bColor = BaseColor.WHITE;
                                cb.SetColorFill(bColor);
                                cb.Rectangle(match.Rect.Left, match.Rect.Bottom, match.Rect.Width, match.Rect.Height);
                                cb.Fill();

                                // Calculates new rectangle
                                var r = BuildRectangleByStrategies(match, oldText, image.ScaledHeight, image.ScaledWidth, strategy, cb, (string[])stringsArray.Clone(), options);

                                image.Image.ScaleToFit(r.Width, r.Height);
                                var dX = CalculatesHorizontalDelta(style.Content.Alignment.Horizontal, r, image.Image, imageOffset.X);

                                if (useTestMode == YesNo.Yes)
                                {
                                    using (Bitmap emptyImage = BitmapHelper.CreateEmptyBitmap(image.Image.ScaledWidth + 1, image.Image.ScaledHeight + 1, Color.LightGray))
                                        using (Graphics g = Graphics.FromImage(emptyImage))
                                            using (Canvas canvas = new Canvas(g))
                                            {
                                                canvas.DrawBorder(Color.Red);

                                                var testImage = TextSharpPdfImage.GetInstance(emptyImage, ImageFormat.Png);
                                                testImage.SetAbsolutePosition(r.X + dX, -imageOffset.Y + (r.Y - image.Image.ScaledHeight));
                                                cb.AddImage(testImage);
                                            }
                                }
                                else
                                {
                                    image.Image.SetVisualStyle(style);
                                    image.Image.SetAbsolutePosition(r.X + dX, -imageOffset.Y + (r.Y - image.Image.ScaledHeight));
                                    cb.AddImage(image.Image);
                                }
                            }

                            cb.Fill();
                            cb.Stroke();
                        }

                        stamper.Close();
                        reader.Close();
                    }

                return(ReplaceResult.CreateSuccessResult(new ReplaceResultData
                {
                    Context = context,
                    InputStream = input,
                    OutputStream = new MemoryStream(outputStream.GetBuffer())
                }));
            }
            catch (Exception ex)
            {
                return(ReplaceResult.FromException(
                           ex,
                           new ReplaceResultData
                {
                    Context = context,
                    InputStream = input,
                    OutputStream = input
                }));
            }
        }
Example #21
0
 private void btnNotoall_Click(object sender, EventArgs e)
 {
     result       = ReplaceResult.NoToAll;
     FormClosing -= ReplaceBox_FormClosing;
     Close();
 }
Example #22
0
        private static ReplaceResult ReplaceImpl(IInput context, Stream input, string oldText, ReplaceTextOptions options, PdfTable table, float fixedWidth, PointF tableOffset, PdfTableStyle style, YesNo useTestMode)
        {
            var outputStream = new MemoryStream();

            try
            {
                using (var reader = new PdfReader(input))
                    using (var stamper = new PdfStamper(reader, outputStream))
                    {
                        var pages = reader.NumberOfPages;
                        for (var page = 1; page <= pages; page++)
                        {
                            var strategy = new CustomLocationTextExtractionStrategy();
                            var cb       = stamper.GetOverContent(page);

                            // Send some data contained in PdfContentByte, looks like the first is always cero for me and the second 100,
                            // but i'm not sure if this could change in some cases.
                            strategy.UndercontentCharacterSpacing  = cb.CharacterSpacing;
                            strategy.UndercontentHorizontalScaling = cb.HorizontalScaling;

                            // It's not really needed to get the text back, but we have to call this line ALWAYS,
                            // because it triggers the process that will get all chunks from PDF into our strategy Object
                            var allStrings   = PdfTextExtractor.GetTextFromPage(reader, page, strategy);
                            var stringsArray = allStrings.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);

                            // The real getter process starts in the following line
                            var textMatchesFound = strategy.GetExtendedTextLocations(oldText, options).ToList();

                            // MatchesFound contains all text with locations
                            foreach (var match in textMatchesFound)
                            {
                                // Delete tag
                                var bColor = BaseColor.WHITE;
                                cb.SetColorFill(bColor);
                                cb.Rectangle(match.Rect.Left, match.Rect.Bottom, match.Rect.Width, match.Rect.Height);
                                cb.Fill();

                                // Calculates new rectangle
                                var deltaY     = CalculatesVerticalDelta(options, match.Rect);
                                var cellHeight = CalculatesCellHeight(match, oldText, strategy, cb, (string[])stringsArray.Clone(), options, deltaY);
                                var r          = BuildRectangleByStrategies(match, oldText, strategy, cb, (string[])stringsArray.Clone(), options);

                                // Width strategy to use
                                var safeFixedWidth = fixedWidth;
                                var useFixedWidth  = !fixedWidth.Equals(DefaultFixedWidth);
                                if (useFixedWidth)
                                {
                                    if (fixedWidth > r.Width)
                                    {
                                        safeFixedWidth = r.Width;
                                    }
                                }
                                else
                                {
                                    safeFixedWidth = r.Width;
                                }

                                // Creates aligned table by horizontal alignment value (this table contains the user table parameter)
                                var outerBorderTable = new PdfPTable(1)
                                {
                                    TotalWidth          = safeFixedWidth,
                                    HorizontalAlignment = Element.ALIGN_LEFT
                                };

                                var outerCell = PdfHelper.CreateEmptyWithBorderCell(style.Borders);
                                outerCell.MinimumHeight     = cellHeight;
                                outerCell.VerticalAlignment = style.Alignment.Vertical.ToVerticalTableAlignment();
                                outerCell.BackgroundColor   = new BaseColor(ColorHelper.GetColorFromString(style.Content.Color));

                                //table.Table.HorizontalAlignment = Element.ALIGN_LEFT;
                                table.Table.TotalWidth  = safeFixedWidth - (outerCell.EffectivePaddingRight + outerCell.EffectivePaddingLeft) * 2;
                                table.Table.LockedWidth = true; // options.StartStrategy.Equals(StartLocationStrategy.LeftMargin) && options.EndStrategy.Equals(EndLocationStrategy.RightMargin);
                                outerCell.AddElement(table.Table);
                                outerBorderTable.AddCell(outerCell);

                                // Creates strategy table (for shows testmode rectangle)
                                var useTestModeTable = new PdfPTable(1)
                                {
                                    TotalWidth = safeFixedWidth
                                };
                                var useTestCell = PdfHelper.CreateEmptyCell(useTestMode);

                                if (table.Configuration.HeightStrategy == TableHeightStrategy.Exact)
                                {
                                    useTestCell.FixedHeight = table.Table.TotalHeight;
                                }

                                useTestCell.AddElement(outerBorderTable);
                                useTestModeTable.AddCell(useTestCell);
                                useTestModeTable.WriteSelectedRows(-1, -1, r.X + tableOffset.X, r.Y - tableOffset.Y - deltaY, cb);

                                cb.Fill();
                            }

                            cb.Stroke();
                        }

                        stamper.Close();
                        reader.Close();
                    }

                return(ReplaceResult.CreateSuccessResult(new ReplaceResultData
                {
                    Context = context,
                    InputStream = input,
                    OutputStream = new MemoryStream(outputStream.GetBuffer())
                }));
            }
            catch (Exception ex)
            {
                return(ReplaceResult.FromException(
                           ex,
                           new ReplaceResultData
                {
                    Context = context,
                    InputStream = input,
                    OutputStream = input
                }));
            }
        }