private static float CalculatesCellHeight(CustomLocationTextExtractionStrategy.LocationTextResult reference, string text, CustomLocationTextExtractionStrategy strategy, PdfContentByte cb, IReadOnlyList <string> allStrings, ReplaceTextOptions options, float deltaY) { var value = cb.PdfDocument.PageSize.Height - cb.PdfDocument.BottomMargin - cb.PdfDocument.TopMargin - deltaY; CustomLocationTextExtractionStrategy.LocationTextResult nextMatchReference = null; var index = -1; for (var i = 0; i < allStrings.Count; i++) { string current = allStrings[i].Trim(); if (current.Equals(text.Trim(), options.Comparison)) { index = i; break; } } if (index == allStrings.Count) { return(value - (cb.PdfDocument.PageSize.Height - reference.Rect.Bottom)); } if (index == -1) { return(value - (cb.PdfDocument.PageSize.Height - reference.Rect.Bottom)); } var nextElementText = allStrings[index + 1]; if (!string.IsNullOrEmpty(nextElementText.Trim())) { var nextMatchReferences = strategy.GetExtendedTextLocations(nextElementText, options); nextMatchReference = nextMatchReferences.FirstOrDefault(); } if (nextMatchReference == null) { return(value - (cb.PdfDocument.PageSize.Height - reference.Rect.Bottom)); } // Same line? if (nextMatchReference.StartPoint.Y <= reference.StartPoint.Y) { return(value - (cb.PdfDocument.PageSize.Height - reference.Rect.Bottom)); } return(value - (cb.PdfDocument.PageSize.Height - nextMatchReference.Rect.Bottom)); }
private static NativeRectangle BuildRectangleByStrategies(CustomLocationTextExtractionStrategy.LocationTextResult reference, string text, CustomLocationTextExtractionStrategy strategy, PdfContentByte cb, IReadOnlyList <string> allStrings, ReplaceTextOptions options) { var x = reference.Rect.Left; var y = reference.Rect.Top; var w = reference.Rect.Width; var h = reference.Rect.Height; switch (options.StartStrategy) { case StartLocationStrategy.LeftMargin: x = cb.PdfDocument.LeftMargin; break; case StartLocationStrategy.PreviousElement: CustomLocationTextExtractionStrategy.LocationTextResult previousMatchReference = null; var index = -1; for (var i = 0; i < allStrings.Count; i++) { string current = allStrings[i].Trim(); if (current.Equals(text.Trim(), options.Comparison)) { index = i; break; } //if (current.Contains(text.Trim())) //{ // index = i; // break; //} } if (index == 0) { break; } var previousElementText = allStrings[index - 1]; if (!string.IsNullOrEmpty(previousElementText)) { var nextMatchReferences = strategy.GetExtendedTextLocations(previousElementText, options); previousMatchReference = nextMatchReferences.FirstOrDefault(); } if (previousMatchReference == null) { break; } // Same line? if (previousMatchReference.EndPoint.X >= reference.StartPoint.X) { break; } w = (reference.EndPoint.X + reference.TextChunk.CharSpaceWidth) - previousMatchReference.EndPoint.X; break; } switch (options.EndStrategy) { case EndLocationStrategy.RightMargin: w = cb.PdfDocument.PageSize.Width - (x + cb.PdfDocument.RightMargin); break; case EndLocationStrategy.NextElement: CustomLocationTextExtractionStrategy.LocationTextResult nextMatchReference = null; var index = -1; string nextElementText = string.Empty; for (var i = 0; i < allStrings.Count; i++) { string currentLine = allStrings[i].Trim(); string[] currentElementsInSameLine = currentLine.Split(new[] { " " }, StringSplitOptions.RemoveEmptyEntries); int totalElementsInLine = currentElementsInSameLine.Length; foreach (var currentLineElement in currentElementsInSameLine) { if (!currentLineElement.Equals(text.Trim(), options.Comparison)) { continue; } index = i; if (totalElementsInLine > 1) { nextElementText = currentElementsInSameLine[1]; } break; } if (index != -1) { break; } } if (index == allStrings.Count) { break; } if (!string.IsNullOrEmpty(nextElementText)) { var nextMatchReferences = strategy.GetExtendedTextLocations(nextElementText.Trim(), options); nextMatchReference = nextMatchReferences.FirstOrDefault(); } if (nextMatchReference == null) { w = cb.PdfDocument.PageSize.Width - (x + cb.PdfDocument.RightMargin); break; } // Same line? if (nextMatchReference.StartPoint.X <= reference.EndPoint.X) { w = cb.PdfDocument.PageSize.Width - (x + cb.PdfDocument.RightMargin); break; } // calculates new width if (options.StartStrategy == StartLocationStrategy.LeftMargin) { w = nextMatchReference.StartPoint.X - (reference.StartPoint.X + reference.TextChunk.CharSpaceWidth) + (reference.StartPoint.X - cb.PdfDocument.LeftMargin); } else { w = nextMatchReference.StartPoint.X - (reference.StartPoint.X + reference.TextChunk.CharSpaceWidth); } break; } switch (options.VerticalStrategy) { case VerticalFineStrategy.Middle: y -= reference.Rect.Height / 2.0f; break; case VerticalFineStrategy.Bottom: y -= reference.Rect.Height; break; default: case VerticalFineStrategy.Top: y += reference.TextChunk.CurFontSize / 4; break; } return(new NativeRectangle(x, y, w, h)); }
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 })); } }
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 })); } }
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 })); } }