iTextSharp unable to find text rotated at a specific angel - c#

I am using the following class to find text position in pdf:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using iTextSharp.text.pdf.parser;
namespace PdfTextHighlighter.Code
{
public class RectAndText
{
public iTextSharp.text.Rectangle Rect;
public String Text;
public RectAndText(iTextSharp.text.Rectangle rect, String text)
{
this.Rect = rect;
this.Text = text;
}
}
public class MyLocationTextExtractionStrategy : LocationTextExtractionStrategy
{
//Hold each coordinate
public List<RectAndText> MyPoints = new List<RectAndText>();
//The string that we're searching for
public String TextToSearchFor { get; set; }
//How to compare strings
public System.Globalization.CompareOptions CompareOptions { get; set; }
public MyLocationTextExtractionStrategy(String textToSearchFor,
System.Globalization.CompareOptions compareOptions = System.Globalization.CompareOptions.None)
{
this.TextToSearchFor = textToSearchFor;
this.CompareOptions = compareOptions;
}
//Automatically called for each chunk of text in the PDF
public override void RenderText(TextRenderInfo renderInfo)
{
base.RenderText(renderInfo);
//See if the current chunk contains the text
var startPosition = System.Globalization.CultureInfo.CurrentCulture.CompareInfo.IndexOf(
renderInfo.GetText(), this.TextToSearchFor, this.CompareOptions);
//If not found bail
if (startPosition < 0)
{
return;
}
if (renderInfo.PdfString.ToString() != this.TextToSearchFor)
{
return;
}
//Grab the individual characters
var chars =
renderInfo.GetCharacterRenderInfos().Skip(startPosition).Take(this.TextToSearchFor.Length).ToList();
//Grab the first and last character
var firstChar = chars.First();
var lastChar = chars.Last();
//Get the bounding box for the chunk of text
var bottomLeft = firstChar.GetDescentLine().GetStartPoint();
var topRight = lastChar.GetAscentLine().GetEndPoint();
//Create a rectangle from it
var rect = new iTextSharp.text.Rectangle(
bottomLeft[Vector.I1],
bottomLeft[Vector.I2],
topRight[Vector.I1],
topRight[Vector.I2]
);
//Add this to our main collection
this.MyPoints.Add(new RectAndText(rect, this.TextToSearchFor));
}
}
}
It works very well with horizontal or vertical text. However it is unable to find text rotated at an angle. How can I fix this?

Current open source version of iTextSharp will not be able to do this. If you have a licence you can login to itext forums & ask them. I am using the same class as above for my project but in my case text is horizontal so I have not problems.

Related

How to check existence of an embedded resource image before showing it in a pictureox

I have the image test.png in the resources. I want to test if that image exists and if it does show it in a picturebox. I read a lot of the existing articles but can't figure out how to do this??
The code below is very wrong and appreciate your help to point me in the right direction.
using System.Reflection;
namespace GetResource
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
string[] resNames = Assembly.GetExecutingAssembly().GetManifestResourceNames();
foreach (string resName in resNames)
{
if (resName == "test.png")
pictureBox1.Image = resName;
}
}
}
}
The following class is a container for remembering resources in a project of type Bitmap and Icon.
using System.Drawing;
Container
public class ResourceItem
{
/// <summary>
/// Resource name
/// </summary>
public string Name { get; set; }
/// <summary>
/// Image which is either an icon or bitmap
/// </summary>
public Bitmap Image { get; set; }
/// <summary>
/// Indicates if dealing with an icon so when displaying the
/// control used to display can adjust it's size or Size mode
/// </summary>
public bool IsIcon { get; set; }
public override string ToString() => Name;
}
Class to read into a List of ResourceItem each image name, is Icon and the image.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.Globalization;
using System.Linq;
// change ChangeImage with your namespace
using ChangeImage.Properties;
namespace ChangeImage.Classes
{
public class ImageHelper
{
public static List<ResourceItem> ResourceItemList()
{
var items = new List<ResourceItem>();
foreach (var name in ResourceImageNames())
{
var item = new ResourceItem() {Name = name, IsIcon = false};
if (Resources.ResourceManager.GetObject(name) is Icon)
{
item.Image = ((Icon)Resources.ResourceManager.GetObject(name))?.ToBitmap();
item.IsIcon = true;
}
else
{
item.Image = (Bitmap)Resources.ResourceManager.GetObject(name);
}
items.Add(item);
}
return items;
}
public static List<string> ResourceImageNames()
{
try
{
var names = new List<string>();
var resourceSet = Resources.ResourceManager
.GetResourceSet(CultureInfo.CurrentUICulture,
true, true);
names.AddRange(
from DictionaryEntry dictionaryEntry in resourceSet
where dictionaryEntry.Value is Image || dictionaryEntry.Value is Icon
select dictionaryEntry.Key.ToString());
return names;
}
catch (Exception)
{
return null;
}
}
}
}
The following shows the images in the current project
How to use
private void NamesInResourceButton_Click(object sender, EventArgs e)
{
var resources = ImageHelper.ResourceItemList();
var imageItem = resources.FirstOrDefault(x => x.Name == "Chat");
if (imageItem is not null)
{
pictureBox1.Image = imageItem.Image;
}
}
Resources in the project used.

How to dynamically create a pie chart using any clicked data points in cartesian chart

Can anyone tell me how to extract cartesian chart values for a given X axis value? I created a cartesian chart and figured out how to change it. Now I want to dynamically create a pie chart for any clicked data point. To illustrate:
When I clicked on any data point with datetime 2022.02.27 00:57:04, I want to create and show a new page like this
I have three files, Data.cs for my custom data type, mainForm.cs with cartesianChart and pie.cs with pieChart
Data.cs
using System;
namespace TestUI
{
internal class Data
{
public DateTime dateTime { get; set; }
public double value { get; set; }
}
}
mainForm.cs
using LiveCharts;
using LiveCharts.Configurations;
using LiveCharts.Wpf;
using System;
using System.Windows.Forms;
using Brushes = System.Windows.Media.Brushes;
namespace TestUI
{
public partial class mainForm : Form
{
const int numLineSeries = 5;
const int numValues = 10;
const int ONESEC = 1000;
public mainForm()
{
InitializeComponent();
// I believe this is where the magic will happen
// cartesianChart.DataClick += CartesianChart_DataClick;
}
private void mainForm_Load(object sender, EventArgs e)
{
var dayConfig = Mappers.Xy<Data>()
.X(data => (double)data.dateTime.Ticks / TimeSpan.FromHours(1).Ticks)
.Y(data => data.value);
SeriesCollection seriesCollection = new SeriesCollection(dayConfig);
Timer chartTimer = new Timer() { Interval = 3 * ONESEC };
Random random = new Random();
for (int i = 0; i < numLineSeries; i++)
{
LineSeries lineSeries = new LineSeries
{
Values = new ChartValues<Data>(),
Fill = Brushes.Transparent,
Title = $"LineSeries[{i}]"
};
EventHandler updateLineSeries = (sender_, e_) =>
{
if (lineSeries.Values.Count > numValues) { lineSeries.Values.RemoveAt(0); };
Data data = new Data { dateTime = DateTime.Now, value = random.NextDouble() };
lineSeries.Values.Add(data);
};
seriesCollection.Add(lineSeries);
chartTimer.Tick += updateLineSeries;
}
cartesianChart.Series = seriesCollection;
Axis axis = new Axis() { LabelFormatter = value => new System.DateTime((long)(value * TimeSpan.FromHours(1).Ticks)).ToString("yyyy.MM.dd HH:mm:ss") };
cartesianChart.AxisX.Add(axis);
}
}
}
pie.cs
using LiveCharts;
using LiveCharts.Wpf;
using System;
using System.Windows.Forms;
namespace TestUI
{
public partial class pie : Form
{
public pie()
{
InitializeComponent();
}
private void pie_Load(object sender, EventArgs e)
{
Func<ChartPoint, string> labelPoint = chartPoint => string.Format("{0} ({1:P})", chartPoint.Y, chartPoint.Participation);
SeriesCollection seriesCollection = new SeriesCollection();
// How can I send these values from mainForm.cs to here?
double[] Values = { 0.56, 0.66, 0.01, 0.43, 0.58 };
int num = 0;
foreach (double value in Values)
{
PieSeries pieSeries = new PieSeries
{
Title = $"LineSeries[{num++}]",
Values = new ChartValues<double> { value },
DataLabels = true,
LabelPoint = labelPoint
};
seriesCollection.Add(pieSeries);
}
pieChart.Series = seriesCollection;
}
}
}

Text jumps in UITextField when focused

I'm dealing with this weird problem...the text inside the UITextField jumps when its focused.
https://www.youtube.com/watch?v=6AkgWXkmBwE
It's a custom UIView that I have created and is used inside another UIViewController.
I've tried removed Draw function, didn't work. Removed all the styling and fonts...no change.
Any idea what's wrong?
using System;
using UIKit;
using Foundation;
using System.Drawing;
using CoreGraphics;
namespace whatever
{
[Register("LoginPanelView")]
public class LoginPanelView : UIView
{
public UITextField UserNameField { get; private set; }
public UITextField PasswordField { get; private set; }
private const float HorizontalMargin = 15;
public LoginPanelView(IntPtr handle)
: base(handle)
{
UserNameField = new UITextField();
PasswordField = new UITextField();
UserNameField.Placeholder = "Username";
PasswordField.Placeholder = "Password";
UserNameField.Font = UIFont.FromName("Avenir", 14);
PasswordField.Font = UIFont.FromName("Avenir", 14);
PasswordField.SecureTextEntry = true;
AddSubviews(new [] { UserNameField, PasswordField });
Layer.CornerRadius = 5.0f;
Layer.BorderColor = UIColor.Gray.CGColor;
ClipsToBounds = true;
}
public override void LayoutSubviews()
{
base.LayoutSubviews();
var height = (float)(Bounds.Height / 2);
UserNameField.Frame = new RectangleF(HorizontalMargin, 0, (float)Bounds.Width - (2 * HorizontalMargin), height);
PasswordField.Frame = new RectangleF(HorizontalMargin, height, (float)Bounds.Width - (2 * HorizontalMargin), height);
}
public override void Draw(CGRect rect)
{
base.Draw(rect);
var graphicsContext = UIGraphics.GetCurrentContext();
var height = (float)(Bounds.Height / 2);
graphicsContext.SetLineWidth(0.25f);
graphicsContext.SetStrokeColor(Layer.BorderColor);
// create some cutout geometry
var path = new CGPath();
path.AddLines(new CGPoint[]
{
new PointF(0, height),
new PointF((float)Bounds.Width, height)
});
path.CloseSubpath();
graphicsContext.AddPath(path);
graphicsContext.DrawPath(CGPathDrawingMode.Stroke);
}
}
}

Dynamic shape graphic c#

I want to draw graphics (shapes) onto the panel to the top left. The shape will be drawn depending on the shape chosen and the value given by the track bar. The track bar values aren't specific i.e aren't pixels or millimeters, so basically when the track bar increases in number the shape should get larger.
This is the my main code. Other classes such as Circle, Square and Triangle also exist.
public partial class drawShape : Form
{
Graphics drawArea;
public decimal area;
double myBoundary = 0;
double myArea = 0;
public double length = 100;
public drawShape()
{
InitializeComponent();
drawArea = pnlDrawArea.CreateGraphics();
}
public void updateShape()
{
if(rbCircle.Checked)
{
drawCircle();
}
if(rbSquare.Checked)
{
drawSquare();
}
if(rbTriangle.Checked)
{
drawTriangle();
}
if(rb2DecimalPlaces.Checked)
{
lblBoundaryLength.Text = myBoundary.ToString("#,0.00");
lblAreaResult.Text = myArea.ToString("#,0.00");
}
if(rb3DecimalPlaces.Checked)
{
lblBoundaryLength.Text = myBoundary.ToString("#,0.000");
lblAreaResult.Text = myArea.ToString("#,0.000");
}
if(rb4DecimalPlaces.Checked)
{
lblBoundaryLength.Text = myBoundary.ToString("#,0.0000");
lblAreaResult.Text = myArea.ToString("#,0.0000");
}
}
public void drawCircle()
{
Circle myCircle = new Circle(length);
myArea = myCircle.GetArea(length);
myBoundary = myCircle.GetCircumference();
lblAreaResult.Text = myArea.ToString();
lblBoundaryLength.Text = myBoundary.ToString();
}
public void drawSquare()
{
Square mySquare = new Square(length);
myArea = mySquare.GetArea();
myBoundary = mySquare.GetBoundLength(length);
lblAreaResult.Text = myArea.ToString();
lblBoundaryLength.Text = myBoundary.ToString();
}
public void drawTriangle()
{
Triangle myTriangle = new Triangle(length);
myArea = myTriangle.GetArea();
myBoundary = myTriangle.GetBoundLength();
lblAreaResult.Text = myArea.ToString();
lblBoundaryLength.Text = myBoundary.ToString();
}
You should use the Panel's Paint event like this:
private void pnlDrawArea_Paint(object sender, PaintEventArgs e)
{
int offset = 20;
Rectangle bounding = new Rectangle(offset, offset,
(int)myBoundary.Value, (int)myBoundary.Value);
if (rbSquare.Checked)
{
e.Graphics.DrawRectangle(Pens.Red, bounding);
}
else if (rbCircle.Checked)
{
e.Graphics.DrawEllipse(Pens.Red, bounding);
}
// else if...
}
and in your updateShape simply call the Paint event by coding: pnlDrawArea.Invalidate();
For the triangle you will
use the DrawLines methos and
have to calculate three Points for it
add them to an array or a list..
Don't forget to hook up the Paint event!!

Displays but does not print?

I am trying to print a document like shown below
The title in bold and the rest of the text in regular font style. This is the print preview!
The problem is, after printing, the title in bold does not display but space is left for it. How to fix this?
I have written the following class to print that document.
using System.Text;
using System.Collections;
using System.Drawing;
using System.Drawing.Printing;
namespace documentPrinter
{
public partial class documentPrinter : PrintDocument
{
public String documenTitle { get; set; }
public String doContent { get; set; }
String contenToPrint;
public Font contentFont { get; set; }
public Font titleFont { get; set; }
bool prinTitle = true;
protected override void OnQueryPageSettings(QueryPageSettingsEventArgs e)
{
PageSettings PgS = e.PageSettings;
PgS.Color = false;
PgS.Landscape = false;
PgS.PaperSize = new PaperSize("A4", 827, 1169);
PgS.Margins = new Margins(100, 100, 100, 100);
//base.OnQueryPageSettings(e);
}
protected override void OnBeginPrint(PrintEventArgs e)
{
contenToPrint = "\n\n\n" + doContent;
//base.OnBeginPrint(e);
}
protected override void OnPrintPage(PrintPageEventArgs e)
{
int charactersOnPage = 0;
int linesPerPage = 0;
// Sets the value of charactersOnPage to the number of characters
// of stringToPrint that will fit within the bounds of the page.
if (prinTitle)
{
e.Graphics.MeasureString(documenTitle,
titleFont,
e.MarginBounds.Size,
StringFormat.GenericTypographic,
out charactersOnPage,
out linesPerPage);
e.Graphics.DrawString(documenTitle,
titleFont,
Brushes.Black,
e.MarginBounds,
StringFormat.GenericTypographic);
prinTitle = false;
}
e.Graphics.MeasureString(contenToPrint,
contentFont,
e.MarginBounds.Size,
StringFormat.GenericTypographic,
out charactersOnPage,
out linesPerPage);
// Draws the string within the bounds of the page.
e.Graphics.DrawString(contenToPrint, contentFont, Brushes.Black, e.MarginBounds, StringFormat.GenericTypographic);
// Remove the portion of the string that has been printed.
contenToPrint = contenToPrint.Substring(charactersOnPage);
// Check to see if more pages are to be printed.
e.HasMorePages = (contenToPrint.Length > 0);
//base.OnPrintPage(e);
}
}
}

Categories