fpdf2 icon indicating copy to clipboard operation
fpdf2 copied to clipboard

Add a new bezier() method to draw curves

Open Lucas-C opened this issue 3 years ago • 43 comments

Documentation on Bézier curves:

There is some suggested usage example, once implemented, inspired by the existing polygon() method:

from fpdf import FPDF

pdf = FPDF()
pdf.bezier([(100, 150), (50, 100), ...], style="FD")

@torque already implemented bezier curves in PR #196 in order to support SVG: https://github.com/PyFPDF/fpdf2/blob/2.5.6/fpdf/drawing.py#L2016

The goal here is to expose this feature as a new public FPDF method.

Of course, new unit tests should be added, as well as a new documentation section in docs/Shapes.md


By implementing this feature you, as a benevolent FLOSS developper, will provide access to the large community of fpdf2 users to a standard and useful PDF functionality. As a contributor you will get review feedbacks from maintainers & other contributors, and learn about the lifecycle & structure of a Python library on the way. You will also be added to the contributors list & map.

This issue can count as part of hacktoberfest

Lucas-C avatar Aug 18 '22 15:08 Lucas-C

Would like to work on it, if no one else is working.

JDeepD avatar Oct 01 '22 09:10 JDeepD

Would like to work on it, if no one else is working.

You are very welcome, go on!

Lucas-C avatar Oct 03 '22 08:10 Lucas-C

hello, if its available can I work on it?

Aashish-Upadhyay-101 avatar Oct 04 '22 14:10 Aashish-Upadhyay-101

Ping @JDeepD: have you started working on this, or are you planning to do so soon? If so, great! 😊 Any help needed? Else, would you be OK to leave it for @Aashish-Upadhyay-101 to work on it?

Lucas-C avatar Oct 04 '22 15:10 Lucas-C

I am planning to work on this soon. Since I have not contributed to fpdf2 before, I am looking into some code and documentation. But @Aashish-Upadhyay-101 can work on it as I would probably need some more time to understand the codebase and begin working on it.

JDeepD avatar Oct 04 '22 15:10 JDeepD

nice, before starting I have a few questions @Lucas-C do I have to create bezier() method from scratch ?

Aashish-Upadhyay-101 avatar Oct 04 '22 15:10 Aashish-Upadhyay-101

I am planning to work on this soon. Since I have not contributed to fpdf2 before, I am looking into some code and documentation. But @Aashish-Upadhyay-101 can work on it as I would probably need some more time to understand the codebase and begin working on it.

@JDeepD : thank you for you answer. If @Aashish-Upadhyay-101 creates a PR first, you input will be welcome as a reviewer on it!

do I have to create bezier() method from scratch ?

@Aashish-Upadhyay-101 yes, no method exist at this moment.

Lucas-C avatar Oct 04 '22 17:10 Lucas-C

@Lucas-C, I have to make function that renders bezier curve. To actually render on the pdf which function or library this project is using? I think drawing.py has some functions inside it, right?

Aashish-Upadhyay-101 avatar Oct 05 '22 02:10 Aashish-Upadhyay-101

I think drawing.py has some functions inside it, right?

As mentioned in the issue description, the drawing.py module has several classes that implement the geometric calculations:

It might be easiest to just create a wrapper around one (or several) of those.

Actually, I think that several of our bespoke geometry methods could be simplified by calling the drawing.py module instead of doing the work themselves.

gmischler avatar Oct 05 '22 06:10 gmischler

I'm new to open source and really struggling to do this....! can you help?

Aashish-Upadhyay-101 avatar Oct 05 '22 07:10 Aashish-Upadhyay-101

Hi @Aashish-Upadhyay-101, and welcome. I am going to be a bit busy for a few days, but I should have some time on Monday to give you some pointers. Those pages are good starting points if you are new:

  • https://opensource.guide/how-to-contribute/#how-to-submit-a-contribution
  • https://pyfpdf.github.io/fpdf2/Development.html#installing-fpdf2-from-a-local-git-repository

Could you try to explain precisely on what points you are struggling?

Usually, when contributing to an open source project, the first steps are :

  1. Retrieve the code on your computer using git
  2. Install the require dependencies, with pip (following the instructions on the page I mentioned above)
  3. Run the unit tests (by executing pytest)
  4. Figure how to add a new one (here a new test/shapes/test_bezier.py file seems pertinent) by taking inspiration from the existing ones. You will want to call assert_pdf_equal() with generate=True while developping your new test, to generate a new reference PDF file
  5. Read some of the internal the code to understand it, but focus on just what you need to know in order to implement your task
  6. Start coding!

Lucas-C avatar Oct 07 '22 08:10 Lucas-C

@Lucas-C I tried to Setup locally, but got error when I run test

1. first of all the test failed with errors

i ran pytest -p test Screen Shot 2022-10-07 at 5 10 57 PM

2. After that i'm also confused where to start like from where should i began.

3. Afer that, I'm also confused which file to modify and how to add bezier() function

As I'm purely a beginner and really want to success in this area, I will do whatever it takes to learn so please guide me through

Or maybe you can assign me a little bit biginner friendly simple issue to get started with?

Aashish-Upadhyay-101 avatar Oct 07 '22 11:10 Aashish-Upadhyay-101

@Lucas-C I tried to Setup locally, but got error when I run test

1. first of all the test failed with errors

i ran pytest -p test Screen Shot 2022-10-07 at 5 10 57 PM

Did you install the requirements first?

Install dependencies using pip install -r test/requirements.txt

2. After that i'm also confused where to start like from where should i began.

The docs/Development.md is a pretty good starting point.

3. Afer that, I'm also confused which file to modify and how to add bezier() function

The codebase should generally remain uniform. See how other functions are implemented and try to implement the bezier() function in a similar manner.

JDeepD avatar Oct 07 '22 14:10 JDeepD

Screen Shot 2022-10-07 at 9 43 43 PM

@JDeepD I got this error message when I tried to install the requirements.txt

Aashish-Upadhyay-101 avatar Oct 07 '22 15:10 Aashish-Upadhyay-101

Screen Shot 2022-10-07 at 9 43 43 PM

@JDeepD I got this error message when I tried to install the requirements.txt

First thing that you should do when you get errors is to google it and try out some top solutions.

For ex, the error here is error: command swig failed...

After a bit of googling, this is what I found.

JDeepD avatar Oct 07 '22 16:10 JDeepD

@JDeepD now everything is setup, now I will try to implement bezier

Aashish-Upadhyay-101 avatar Oct 07 '22 17:10 Aashish-Upadhyay-101

@JDeepD can you help me with bezier() function. I created a empty function inside fpdf's class FPDF like this

def bezier(self, point_list, style):
    pass

but don't know afterwards how to implement it, can you guide me

Aashish-Upadhyay-101 avatar Oct 07 '22 17:10 Aashish-Upadhyay-101

@JDeepD can you help me with bezier() function. I created a empty function inside fpdf's class FPDF like this

def bezier(self, point_list, style):
    pass

but don't know afterwards how to implement it, can you guide me

You need to read some internal code for it. See the links mentioned in the top comment by Lucas.

JDeepD avatar Oct 08 '22 04:10 JDeepD

@JDeepD I think if you have already understanded the code base, you can work on this issue. I'm just a beginner and like literally no idea whats going on the project

Aashish-Upadhyay-101 avatar Oct 08 '22 10:10 Aashish-Upadhyay-101

@Aashish-Upadhyay-101 If you have left working on this issue, then please let us know.

JDeepD avatar Oct 09 '22 18:10 JDeepD

@JDeepD I left working on this issue, I think I need some more time to understand whats going on.

Aashish-Upadhyay-101 avatar Oct 09 '22 18:10 Aashish-Upadhyay-101

I would like to work on this issue? Just let me know.....

Shikharishere avatar Oct 15 '22 19:10 Shikharishere

Great!

Feel free to drop a comment if you start working on this. I also suggest to quickly submit a pull request, as a draft, so that you can share your ongoing work.

Lucas-C avatar Oct 16 '22 17:10 Lucas-C

Also, thank you for your help & answers here @JDeepD! And thanks for your interest in fpdf2, your contributions will be very welcome 😊

@all-contributors please add @JDeepD for question

Lucas-C avatar Oct 17 '22 07:10 Lucas-C

I've begun work on this issue. I've opened draft PR (#596) so that I can share my progress.

From what I understand, here is my approach: Add a public method to class fpdf called bezier. This method has 1 required arguments. point_list: Must contain atleast 4 points. The first and last set of coordinates are taken as the starting and ending points respectively. The remainder of the points are used as control points for the Bezier curve.

The Bezier curve methods created in #196 can't be used here as they are for the case of 2 control points only. However, they can be seen as a special case of the general Bezier curve with arbitrarily many control points. My revised plan is to write a more general Bezier curve method of which the original methods will be special cases. ~~This method will take a list of two or more points. The method will simply iterate over this set of points and render bezier curves using the methods created in PR #196.~~

I notice that in the description of the issue, the method should also take a style argument. Given that we are rendering a line (which may not necessarily be closed unless the last point is the same coordinates as the first point), does it make sense to have style options that we would normally have for closed shapes (such as fill and draw).

jeettrivedi avatar Oct 22 '22 17:10 jeettrivedi

does it make sense to have style options that we would normally have for closed shapes

As can be seen in the CodePen snippet on the following page, yes bezier curves with filling make sense: https://www.sitepoint.com/html5-svg-cubic-curves/

Your plan sounds great 😊 It is important that, to draw those curves, the same code is used in this method and in the drawing module of fpdf2, to avoid code duplication.

Lucas-C avatar Oct 23 '22 08:10 Lucas-C

I see. I read through some of the implemented methods in the drawing module and realized that all I need to do is to generate the string representing the complete Bezier curve (as in the examples you linked) that can be passed to the path render function. Does that solution make sense?

jeettrivedi avatar Oct 29 '22 21:10 jeettrivedi

all I need to do is to generate the string representing the complete Bezier curve (as in the examples you linked) that can be passed to the path render function. Does that solution make sense?

Yes, absolutely 😊 In bezier() you can use the existing drawing_context() or new_path() methods that can be used as context managers

Lucas-C avatar Oct 30 '22 21:10 Lucas-C

@jeettrivedi, you might want to check out the svg.py module and compare how it uses the bezier methods in drawing.py. You can probably keep it simpler than that because you don't need to deal with other path elements, but the parts handling curves (especially continuous curves) may still be useful to study.

gmischler avatar Oct 31 '22 07:10 gmischler

@jeettrivedi: are you still working on this issue? If you do, can I help you with anything? If not, no worries, please just notify us 😊

Lucas-C avatar Nov 15 '22 12:11 Lucas-C