GSoC/2019/StatusReports/Albertoefg: Difference between revisions

From KDE Community Wiki
< GSoC‎ | 2019‎ | StatusReports
No edit summary
No edit summary
 
(11 intermediate revisions by the same user not shown)
Line 2: Line 2:


=== Summary ===
=== Summary ===
* Project Name: Animated Vector Brush for Krita
* '''Project Name''': Animated Vector Brush for Krita
* Proposal: Google Docs Proposal
* '''Proposal''': [https://docs.google.com/document/d/1SwIBNFthJ5Qg3N7DBgzMKMrW-rn5hB_NPxuf8EuMr2w/edit#heading=h.banhzxz4dibc Google Docs Proposal]
* Abstract: This projects aims to implement an Animated Vector Brush for Krita, which uses SVG as a source file for the brush tips. The purpose of an animated brush is to change the brush tips automatically with every dab on the canvas. This allows for a quick way to paint different images, create random and fun designs, and explore new ways to paint that are not easy in physical world. In the other hand, using SVG as a source makes it easy to share the brush tips as they are saved as plain text, as opposed to raster image brushes.
* '''Related blog''': [https://albertoefg.info/blog/kde.html albertoefg.info]
* '''Abstract''': This projects aims to implement an Animated Vector Brush for Krita, which uses SVG as a source file for the brush tips. The purpose of an animated brush is to change the brush tips automatically with every dab on the canvas. This allows for a quick way to paint different images, create random and fun designs, and explore new ways to paint that are not easy in physical world. In the other hand, using SVG as a source makes it easy to share the brush tips as they are saved as plain text, as opposed to raster image brushes.


=== Project Goals ===
=== Project Goals ===
Line 11: Line 12:
* Load AVB
* Load AVB
* Parse SVG
* Parse SVG
* Render SVG as images  
* Render brush tips as images  
* Write a helper parasite class
* Write a parasite class to hold the index
* Write a VectorAnimatedBrush class
* Write a VectorShapeObject class
* Write a helper class to populate the VectorAnimatedBrush class  
* Change brush tip with every dab
* Change brush tip with every dab
* Save AVB


=== Project related links ===
=== Project related links ===
Line 27: Line 30:
* '''TODO''': Add screenshots.
* '''TODO''': Add screenshots.
* '''Related blog post''':  [https://albertoefg.info/blog/2019/06/2019-06-09-my_first_two_weeks.html My first two weeks on Google Summer of Code]  
* '''Related blog post''':  [https://albertoefg.info/blog/2019/06/2019-06-09-my_first_two_weeks.html My first two weeks on Google Summer of Code]  
==== Commits and Differentials ====
==== Commits and Differentials ====
* [https://phabricator.kde.org/T10930 Phabricator T10930]
* [https://phabricator.kde.org/T10930 Phabricator T10930]
Line 35: Line 37:


=== Load AVB ===
=== Load AVB ===
* '''Goal''': The Animated Vector Brush file should be loaded and call the proper Class, in this case ''kis_vectoranimated_brush''
* '''Goal''': The Animated Vector Brush file should be loaded and call the proper class, in this case <code>KisVectorAnimatedBrush</code>.
* '''Status''': The implementation is done, the loading of the AVB by the user is using the +import tab.  
* '''Status''': The implementation is done, the loading of the AVB by the user is using the <code>+import</code> tab.  
* '''Related blog post''': [https://albertoefg.info/blog/2019/06/2019-06-09-my_first_two_weeks.html#org54db47c My first two weeks on Google Summer of Code]  
* '''Related blog post''': [https://albertoefg.info/blog/2019/06/2019-06-09-my_first_two_weeks.html#org54db47c My first two weeks on Google Summer of Code]  
==== Commits and Differentials ====
==== Commits and Differentials ====
Line 42: Line 44:
** [https://invent.kde.org/albertofl/krita/commit/bd654077f29b2f50cdb0ea9c93766a57295bbdb1 bd654077: Added vectorAnimatedBrush to brush server]  
** [https://invent.kde.org/albertofl/krita/commit/bd654077f29b2f50cdb0ea9c93766a57295bbdb1 bd654077: Added vectorAnimatedBrush to brush server]  
** [https://invent.kde.org/albertofl/krita/commit/ddee5b98b3aacf2cbed764f3c650167243e17a29 ddee5b98: Load Vector Animated Brush]  
** [https://invent.kde.org/albertofl/krita/commit/ddee5b98b3aacf2cbed764f3c650167243e17a29 ddee5b98: Load Vector Animated Brush]  
** [https://invent.kde.org/albertofl/krita/commit/d1afdb4053d237b123424db07bc837951d008bbe d1afdb40: Return false for empty SVG]


=== Parse SVG ===
=== Parse SVG ===
* '''Goal''': The SVG should be parsed and transformed to KoShape as necessary, so Krita can use them to set ''brushTipImage'', paint dabs or change the size of the brush tip.
* '''Goal''': The SVG should be parsed and transformed to <code>KoShape</code> as necessary, so Krita can use them to set <code>brushTipImage</code>, paint dabs or change the size of the brush tip.
* '''Status''': Done.
* '''Status''': Done.
* '''Related blog post''': [https://albertoefg.info/blog/2019/06/2019-06-23-the_last_two_weeks_on_krita.html Basic functionality almost ready]  
* '''Related blog post''': [https://albertoefg.info/blog/2019/06/2019-06-23-the_last_two_weeks_on_krita.html Basic functionality almost ready]  
Line 52: Line 56:
** [https://invent.kde.org/albertofl/krita/commit/cffe647e8064117fb7ab70c9147ec0ad67c48120 cffe647e: Set brushTipImage from the KoShapePainter]  
** [https://invent.kde.org/albertofl/krita/commit/cffe647e8064117fb7ab70c9147ec0ad67c48120 cffe647e: Set brushTipImage from the KoShapePainter]  


=== Render brush tips as images. ===
=== Render brush tips as images ===
* '''Goal''': The KoShapes should be transformed to QImage as necessary, so Krita can use them to set ''brushTipImage'', paint dabs or change the size of the brush tip.
* '''Goal''': The <code>KoShapes</code> should be transformed to <code>QImage</code> as necessary, so Krita can use them to set <code>brushTipImage</code>, paint dabs or change the size of the brush tip.
* '''Status''': Done.
* '''Status''': Done.
* '''Related blog post''': [https://albertoefg.info/blog/2019/06/2019-06-23-the_last_two_weeks_on_krita.html Basic functionality almost ready]  
* '''Related blog post''': [https://albertoefg.info/blog/2019/06/2019-06-23-the_last_two_weeks_on_krita.html Basic functionality almost ready]  
Line 62: Line 66:
** [https://invent.kde.org/albertofl/krita/commit/b024e4fb08ce78d438a0f9b081ad1a1dc3d0c548 b024e4fb: Render QImages only once]  
** [https://invent.kde.org/albertofl/krita/commit/b024e4fb08ce78d438a0f9b081ad1a1dc3d0c548 b024e4fb: Render QImages only once]  


 
=== Write a parasite class to hold the index ===
=== Write a helper parasite class ===
* '''Goal''': Write a parasite class that will aid <code>KisVectorAnimatedBrush</code> class, holding the values of the Index and related data.
* '''Goal''': Write a class that will aid the ''kis_vectoranimatedbrush'' class, holding the values of the Index and related data.
* '''Status''': In Progress. Although the majority of the class works now, there is a need for comments and cleaning. It can also be extended to add more functionality like different types of sequences: tilt, velocity, etc.
* '''Status''': In Progress. Although the majority of the class works now, there is a need for comments and cleaning.
* Related blog post: [https://albertoefg.info/blog/2019/07/implementing_a_derivated_class_of_kis_brushes_pipe.html Implementing a derivated class of kis_brushes_pipe]  
* Related blog post: [https://albertoefg.info/blog/2019/07/implementing_a_derivated_class_of_kis_brushes_pipe.html Implementing a derivated class of kis_brushes_pipe]  
==== Commits and Differentials ====
==== Commits and Differentials ====
Line 73: Line 76:




=== Change brush tip with every dab. ===
=== Write a KisVectorAnimatedBrush class ===
* '''Goal''': Change the ''brushTipimage'' with every dab
* '''Goal''': Write a the class <code>KisVectorAnimatedBrush</code> that will inherit from <code>KisBrushesPipe</code> to work as a brush pipe of <code>VectorShapeObject</code> brushes, it will also have a <code>Private</code> struct to hold a <code>KisVectorHelperPipe</code> object.
* '''Status''': In Progress. As of right now the images are being changed with every dab but it could be done in a faster way, not using ''prepareForSeqNo'' or limiting the amount of times it runs.
* '''Status''': In Progress. The class is mostly done, however it can be extended to get more functionality.
* '''Related blog post''': To be written
* '''Related blog post''':
** [https://albertoefg.info/blog/2019/07/implementing_a_derivated_class_of_kis_brushes_pipe.html Implementing a derivated class of kis_brushes_pipe]
** [https://albertoefg.info/blog/2019/08/krita_sprint_news.html Krita Sprint News]
** [https://albertoefg.info/blog/2019/08/building-a-vector-animated-brush.html Building a Vector Animated Brush]
==== Commits and Differentials ====
* [https://phabricator.kde.org/T10930 Phabricator T10930]
** [https://invent.kde.org/albertofl/krita/commit/ddee5b98b3aacf2cbed764f3c650167243e17a29 ddee5b98: Load Vector Animated Brush]
** [https://invent.kde.org/albertofl/krita/commit/058756d2f898127d4751bbda1b40a758e7233e3e 058756d2: Intitalize Private struct to hold KisVectorHelperPipe object]
** [https://invent.kde.org/albertofl/krita/commit/7536541236ed90d376252d77c9ea5058f7aa1992 75365412: Use paintDevice to render brush ]
** [https://invent.kde.org/albertofl/krita/commit/bbd5667e219e055ddf4a80803c16a845888045d2 bbd5667e: Add destructor for Private object]
 
=== Write a VectorShapeObject class ===
* '''Goal''': Write a class that will work as a single brush that will hold a single <code>KoShape</code> and a single <code>QImage</code>. A series of objects of this class will populate the <code>VectorAnimatedBrush</code> class, using the <code>KisVectorHelperPipe</code> class.
* '''Status''': Done.
* '''Related blog post''': [https://albertoefg.info/blog/2019/08/krita_sprint_news.html Krita Sprint News]
==== Commits and Differentials ====
* [https://phabricator.kde.org/T10930 Phabricator T10930]
** [https://invent.kde.org/albertofl/krita/commit/eae68aa720867cc0c94a54caca7abf2b474a2d67 eae68aa7: Add KisVectorHelperPipe Class] ''Note: This class was added in the same commit as the helper pipe class.''
** [https://invent.kde.org/albertofl/krita/commit/0b2ef645ce666c0173a0805ca31cb6034ef74620 0b2ef645: Inherit from KisScalingsizebrush in KisVectorShapeObject]
** [https://invent.kde.org/albertofl/krita/commit/ebdd8f8c384b1c6a30fa9d0eee1037a5da93e80e ebdd8f8c: Convert brushTip to MaskImage]
** [https://invent.kde.org/albertofl/krita/commit/9e6ee54775c2e06d723f43b1d37e3741b9ce72bd 9e6ee547: Add appropriate brushType]
** [https://invent.kde.org/albertofl/krita/commit/058756d2f898127d4751bbda1b40a758e7233e3e 058756d2: Intitalize Private struct to hold KisVectorHelperPipe object ]
 
=== Write a Helper Pipe class to populate the KisVectorAnimatedBrush ===
* '''Goal''': Write a helper class for <code>KisVectorAnimatedBrush</code> that will aid holding a parasite object of the class written earlier, and populate the pipe brush with <code>VectorShapeObject</code> brushes.
* '''Status''': Done.
* '''Related blog post''': [https://albertoefg.info/blog/2019/08/krita_sprint_news.html Krita Sprint News]
==== Commits and Differentials ====
* [https://phabricator.kde.org/T10930 Phabricator T10930]
** [https://invent.kde.org/albertofl/krita/commit/eae68aa720867cc0c94a54caca7abf2b474a2d67 eae68aa7: Add KisVectorHelperPipe Class]
** [https://invent.kde.org/albertofl/krita/commit/30c2f3c9f2c2b11c27cb296a3e7b093f3670e7bc 30c2f3c9: Populate brushesPipe with VectorShapeObjects]
 
=== Change brush tip with every dab ===
* '''Goal''': Change the <code>brushTipimage</code> with every dab
* '''Status''': Done.
* '''Related blog post''': [https://albertoefg.info/blog/2019/08/building-a-vector-animated-brush.html Building a Vector Animated Brush]
==== Commits and Differentials ====
==== Commits and Differentials ====
* [https://phabricator.kde.org/T10930 Phabricator T10930]
* [https://phabricator.kde.org/T10930 Phabricator T10930]
** [https://invent.kde.org/albertofl/krita/commit/2ed1c1d5acd7e5098a85f4948893ff52cfd52ac9 2ed1c1d5: Fix iteration of shapesToimages]  
** [https://invent.kde.org/albertofl/krita/commit/2ed1c1d5acd7e5098a85f4948893ff52cfd52ac9 2ed1c1d5: Fix iteration of shapesToimages]  
** [https://invent.kde.org/albertofl/krita/commit/cda1fd56f6c6d4cb2b05fcd98b1e4d084a9561eb cda1fd56: Use chooseNextBrush to update the Index]
** [https://invent.kde.org/albertofl/krita/commit/e8248790db65b8f1280f30242041b035822182a3 e8248790: Use KisVectorHelperPipe for the Index]
== All Commits == 
** [https://invent.kde.org/albertofl/docs-krita-org/commit/e9dbd91fff1754ad6fc9e215d9bd16ee5a43116f e9dbd91f: Added Tutorial for Animated Vector Brushes.]
** [https://invent.kde.org/albertofl/docs-krita-org/commit/378b759a4c849f3c3feb50c2000920f9a7e63a3a 378b759a: Added small description for AVB]
** [https://invent.kde.org/albertofl/docs-krita-org/commit/1aa98e85589b0786b2b8e67d64513272663d99bb 1aa98e85: Created documentation for avb]
** [https://invent.kde.org/albertofl/krita/commit/bd654077f29b2f50cdb0ea9c93766a57295bbdb1 bd654077: Added vectorAnimatedBrush to brush server]
** [https://invent.kde.org/albertofl/krita/commit/ddee5b98b3aacf2cbed764f3c650167243e17a29 ddee5b98: Load Vector Animated Brush]
** [https://invent.kde.org/albertofl/krita/commit/d1afdb4053d237b123424db07bc837951d008bbe d1afdb40: Return false for empty SVG]
** [https://invent.kde.org/albertofl/krita/commit/7ed4b9c13c86c4b1b3347528c739cd733c163354 7ed4b9c1:  Use SvgParser to loadFromDevice] 
** [https://invent.kde.org/albertofl/krita/commit/cffe647e8064117fb7ab70c9147ec0ad67c48120 cffe647e: Set brushTipImage from the KoShapePainter]
** [https://invent.kde.org/albertofl/krita/commit/b024e4fb08ce78d438a0f9b081ad1a1dc3d0c548 b024e4fb: Render QImages only once]
** [https://invent.kde.org/albertofl/krita/commit/065ac9ba9ce8c037f8ffeedb0ce4081bf4716bcf 065ac9ba: Added a parasite helper class]
** [https://invent.kde.org/albertofl/krita/commit/4d3fbd9b40260b21f138e6df30495fe0c6b3c4f3 4d3fbd9b: Fix the segmentation fault]
** [https://invent.kde.org/albertofl/krita/commit/058756d2f898127d4751bbda1b40a758e7233e3e 058756d2: Intitalize Private struct to hold KisVectorHelperPipe object]
** [https://invent.kde.org/albertofl/krita/commit/7536541236ed90d376252d77c9ea5058f7aa1992 75365412: Use paintDevice to render brush ]
** [https://invent.kde.org/albertofl/krita/commit/bbd5667e219e055ddf4a80803c16a845888045d2 bbd5667e: Add destructor for Private object]
** [https://invent.kde.org/albertofl/krita/commit/0b2ef645ce666c0173a0805ca31cb6034ef74620 0b2ef645: Inherit from KisScalingsizebrush in KisVectorShapeObject]
** [https://invent.kde.org/albertofl/krita/commit/ebdd8f8c384b1c6a30fa9d0eee1037a5da93e80e ebdd8f8c: Convert brushTip to MaskImage]
** [https://invent.kde.org/albertofl/krita/commit/9e6ee54775c2e06d723f43b1d37e3741b9ce72bd 9e6ee547: Add appropriate brushType]
** [https://invent.kde.org/albertofl/krita/commit/eae68aa720867cc0c94a54caca7abf2b474a2d67 eae68aa7: Add KisVectorHelperPipe Class]
** [https://invent.kde.org/albertofl/krita/commit/30c2f3c9f2c2b11c27cb296a3e7b093f3670e7bc 30c2f3c9: Populate brushesPipe with VectorShapeObjects]
** [https://invent.kde.org/albertofl/krita/commit/2ed1c1d5acd7e5098a85f4948893ff52cfd52ac9 2ed1c1d5: Fix iteration of shapesToimages]
** [https://invent.kde.org/albertofl/krita/commit/cda1fd56f6c6d4cb2b05fcd98b1e4d084a9561eb cda1fd56: Use chooseNextBrush to update the Index]
** [https://invent.kde.org/albertofl/krita/commit/e8248790db65b8f1280f30242041b035822182a3 e8248790: Use KisVectorHelperPipe for the Index]
== Chronicle ==
=== Community Bonding Period ===
During this period of the Google Summer of Code I tried to contribute to Krita in different ways, including helping users on IRC and Reddit, and also improving the Krita documentation.
The biggest amount of work I did was to contribute with the ''Selections Tools'' section of the manual, as suggested by Wolthera van Hövell. This helped me to understand better how to write documentation, how to use git and gitlab, and how to work with an Open Source project. My work was merged right before the Google Summer of Code started.
[https://invent.kde.org/websites/docs-krita-org/merge_requests/4#note_5561 Link to the closed merge request]
=== First two weeks ===
During this period I wrote the documentation for my brush. I don't have experience with writing real world software, but I've read it is always a good idea to start writing the end user documentation, this way there is a clear path on what to achieve at the end of the project.
I also read the specification on [https://www.w3.org/TR/SVG11/ Scalable Vector Graphics (SVG) 1.1], because I wanted to know as much as I could about the <code><symbol></code> and <code><use></code> elements. Upon reading this with more detail, I realized it would be a bad idea to use <code><symbol></code> for this type of brushes.
This is because <q>‘symbol’ elements are never rendered directly; their only usage is as something that can be referenced using the ‘use’ element.</q> Using a <code><symbol></code> would imply that the users have a broken workflow when it comes to editing the brush tips, because they won't be able to edit the brush in the Krita canvas, as the canvas should not show <code><symbol></code> elements only <code><use></code> elements. And changing this behavior would be against the SVG specification.
Because of this, I asked for permission to change the original design of the brush, to use the <code><g></code> element instead. This would bring a number of benefits: 1) the brush tips could be open, edited and saved in the Krita canvas; 2) the brush tips could be parsed using the <code>SvgParser</code> from the Flake library. 3) It would simplify the user workflow.
=== Second and Third weeks ===
During this period I worked on implementing the base class for my brush and to have the basic functionality, this includes: Opening an AVB with the <code>+import</code> tab, parse the XML from the SVG to be a <code>QList</code> of <code>KoShapes</code>, adding the mimetype of <code>.avb</code> to Krita; during this period I didn't have much trouble with Object Oriented Programming as the majority of the work was using functions and implementing the simple things, not touching classes much.
=== Fourth and Fifth weeks ===
This was a harder time, I started to work with classes and to implement the index that will change with every dab, changing the images accordingly. This was the first time I really had to understand the way OOP, and C++ works, it wasn't an easy time for me. I tried to implement a class that inherited from <code>KisBrushesPipe</code>, however I was not successful, but I had some small achievements, I started to understand how a brush pipe should work on Krita, what basic functionality I needed and how to achieve this. During this period my mentor started to work with me closer, to make sure I understood everything and were not completely lost.
=== Sixth and Seventh weeks ===
This was a period of darkness, although my mentor was really helpful and patient with me. I started to read more of the Krita codebase, specially to look at how KisBrushesPipe and KisImagePipeBrush work, it was really hard, a lot of the functionality was not obvious to me and there was no easy way to understand it.
My mentor guided me by telling me to work on a single class and not look at those classes for the moment, that way I could start to improve my brush in a simple way, this was a good advice. I stopped trying to implement those things and slowly worked on built a more humble thing. Here is a point where I did my biggest mistake, I didn't write tests. I was feeling really confused and had a lot of new things to understand and work with, and the unit tests only added to the complexity, so I tried to focus on learning more about the work I was doing before adding another layer of complexity to my code.
=== Eight and Ninth weeks ===
Finally out of the darkness. During this period thanks to the help of my mentor I started to work slowly to improve my brush, to understand more and more of the code of Krita and to implement more functionality.
This weeks were also the ones when the Krita Sprint happened, so I got to talk to my mentor directly, we did a lot of progress, when the Krita Sprint ended my project had a lot of new classes and functionality. I was able to read the code of <code>KisImagepipebrush</code> and have a much clear idea of what was happening and why.
Unfortunately this wasn't all a victory, I did a huge amount of progress and this two weeks were probably the ones were I learned the most about programming, but I also didn't produce as good code as I wish I could, there were was a lot of code I needed to clean, I still needed to write unit testing and have lots of things to improve. But overall I am quite proud of how much I learned and improved.
=== Conclusion ===
Overall the whole I am proud of all the learning and work I did. It has been one of the greatest experiences to learn and collaborate with such an amazing project as Krita, to meet all the team during the Krita Sprint and to realize how much more I can do to help.
I still have a lot to improve my project. Fortunately the end of the Google Summer of Code does not mean the end of my collaboration with Krita, which I hope will last for years to come and I feel proud to be a member of this community.
I have to admit my project is not yet ready to be part of Krita. There are still things to do, it is necessary to clean the code, to add more comments, and to add more tests. But thanks to the progress of the last few weeks I am confident it won't be that long before my brush can become part of Krita.
=== The future  ===
Talking to my mentor and some other Krita developers, I was suggested to read more programming books, one of them being "Design Patterns: Elements of Reusable Object-Oriented Software". I plan to read this book to learn more and be able to produce better code for Krita.
I was also suggested by Tiar to start writing and small program that would reset the configuration of Krita, to help non-technical users, [https://phabricator.kde.org/T11427 as suggested by this phabricator task].
Of course I want to keep improving my brush to take it to the next level, adding new features and options that were beyond the scope of the Google Summer of Code period and my coding abilities.


** Save as AVB.
[[File:Possible future User Interface.png|thumb|center]]
- TODO

Latest revision as of 03:11, 26 August 2019

Krita: Animated Vector Brush

Summary

  • Project Name: Animated Vector Brush for Krita
  • Proposal: Google Docs Proposal
  • Related blog: albertoefg.info
  • Abstract: This projects aims to implement an Animated Vector Brush for Krita, which uses SVG as a source file for the brush tips. The purpose of an animated brush is to change the brush tips automatically with every dab on the canvas. This allows for a quick way to paint different images, create random and fun designs, and explore new ways to paint that are not easy in physical world. In the other hand, using SVG as a source makes it easy to share the brush tips as they are saved as plain text, as opposed to raster image brushes.

Project Goals

  • Write documentation for end users as per the Krita Contribution Guide.
  • Define the structure of the SVG file containing the source tips for the Animated Vector Brush
  • Load AVB
  • Parse SVG
  • Render brush tips as images
  • Write a parasite class to hold the index
  • Write a VectorAnimatedBrush class
  • Write a VectorShapeObject class
  • Write a helper class to populate the VectorAnimatedBrush class
  • Change brush tip with every dab

Project related links

Implementations Status

Write documentation

  • Goal: The documentation should be written for end users as per the Krita Contribution Guide, it should also be sufficient for the users to understand and use the brush.
  • Status: The documentation is mostly done, it is only necessary to add the proper screenshots and update in case of changes.
  • TODO: Add screenshots.
  • Related blog post: My first two weeks on Google Summer of Code

Commits and Differentials

Load AVB

  • Goal: The Animated Vector Brush file should be loaded and call the proper class, in this case KisVectorAnimatedBrush.
  • Status: The implementation is done, the loading of the AVB by the user is using the +import tab.
  • Related blog post: My first two weeks on Google Summer of Code

Commits and Differentials


Parse SVG

  • Goal: The SVG should be parsed and transformed to KoShape as necessary, so Krita can use them to set brushTipImage, paint dabs or change the size of the brush tip.
  • Status: Done.
  • Related blog post: Basic functionality almost ready

Commits and Differentials

Render brush tips as images

  • Goal: The KoShapes should be transformed to QImage as necessary, so Krita can use them to set brushTipImage, paint dabs or change the size of the brush tip.
  • Status: Done.
  • Related blog post: Basic functionality almost ready

Commits and Differentials

Write a parasite class to hold the index

  • Goal: Write a parasite class that will aid KisVectorAnimatedBrush class, holding the values of the Index and related data.
  • Status: In Progress. Although the majority of the class works now, there is a need for comments and cleaning. It can also be extended to add more functionality like different types of sequences: tilt, velocity, etc.
  • Related blog post: Implementing a derivated class of kis_brushes_pipe

Commits and Differentials


Write a KisVectorAnimatedBrush class

Commits and Differentials

Write a VectorShapeObject class

  • Goal: Write a class that will work as a single brush that will hold a single KoShape and a single QImage. A series of objects of this class will populate the VectorAnimatedBrush class, using the KisVectorHelperPipe class.
  • Status: Done.
  • Related blog post: Krita Sprint News

Commits and Differentials

Write a Helper Pipe class to populate the KisVectorAnimatedBrush

  • Goal: Write a helper class for KisVectorAnimatedBrush that will aid holding a parasite object of the class written earlier, and populate the pipe brush with VectorShapeObject brushes.
  • Status: Done.
  • Related blog post: Krita Sprint News

Commits and Differentials

Change brush tip with every dab

Commits and Differentials

All Commits


Chronicle

Community Bonding Period

During this period of the Google Summer of Code I tried to contribute to Krita in different ways, including helping users on IRC and Reddit, and also improving the Krita documentation.

The biggest amount of work I did was to contribute with the Selections Tools section of the manual, as suggested by Wolthera van Hövell. This helped me to understand better how to write documentation, how to use git and gitlab, and how to work with an Open Source project. My work was merged right before the Google Summer of Code started. Link to the closed merge request

First two weeks

During this period I wrote the documentation for my brush. I don't have experience with writing real world software, but I've read it is always a good idea to start writing the end user documentation, this way there is a clear path on what to achieve at the end of the project.

I also read the specification on Scalable Vector Graphics (SVG) 1.1, because I wanted to know as much as I could about the <symbol> and <use> elements. Upon reading this with more detail, I realized it would be a bad idea to use <symbol> for this type of brushes.

This is because ‘symbol’ elements are never rendered directly; their only usage is as something that can be referenced using the ‘use’ element. Using a <symbol> would imply that the users have a broken workflow when it comes to editing the brush tips, because they won't be able to edit the brush in the Krita canvas, as the canvas should not show <symbol> elements only <use> elements. And changing this behavior would be against the SVG specification.

Because of this, I asked for permission to change the original design of the brush, to use the <g> element instead. This would bring a number of benefits: 1) the brush tips could be open, edited and saved in the Krita canvas; 2) the brush tips could be parsed using the SvgParser from the Flake library. 3) It would simplify the user workflow.

Second and Third weeks

During this period I worked on implementing the base class for my brush and to have the basic functionality, this includes: Opening an AVB with the +import tab, parse the XML from the SVG to be a QList of KoShapes, adding the mimetype of .avb to Krita; during this period I didn't have much trouble with Object Oriented Programming as the majority of the work was using functions and implementing the simple things, not touching classes much.

Fourth and Fifth weeks

This was a harder time, I started to work with classes and to implement the index that will change with every dab, changing the images accordingly. This was the first time I really had to understand the way OOP, and C++ works, it wasn't an easy time for me. I tried to implement a class that inherited from KisBrushesPipe, however I was not successful, but I had some small achievements, I started to understand how a brush pipe should work on Krita, what basic functionality I needed and how to achieve this. During this period my mentor started to work with me closer, to make sure I understood everything and were not completely lost.

Sixth and Seventh weeks

This was a period of darkness, although my mentor was really helpful and patient with me. I started to read more of the Krita codebase, specially to look at how KisBrushesPipe and KisImagePipeBrush work, it was really hard, a lot of the functionality was not obvious to me and there was no easy way to understand it.

My mentor guided me by telling me to work on a single class and not look at those classes for the moment, that way I could start to improve my brush in a simple way, this was a good advice. I stopped trying to implement those things and slowly worked on built a more humble thing. Here is a point where I did my biggest mistake, I didn't write tests. I was feeling really confused and had a lot of new things to understand and work with, and the unit tests only added to the complexity, so I tried to focus on learning more about the work I was doing before adding another layer of complexity to my code.

Eight and Ninth weeks

Finally out of the darkness. During this period thanks to the help of my mentor I started to work slowly to improve my brush, to understand more and more of the code of Krita and to implement more functionality.

This weeks were also the ones when the Krita Sprint happened, so I got to talk to my mentor directly, we did a lot of progress, when the Krita Sprint ended my project had a lot of new classes and functionality. I was able to read the code of KisImagepipebrush and have a much clear idea of what was happening and why.

Unfortunately this wasn't all a victory, I did a huge amount of progress and this two weeks were probably the ones were I learned the most about programming, but I also didn't produce as good code as I wish I could, there were was a lot of code I needed to clean, I still needed to write unit testing and have lots of things to improve. But overall I am quite proud of how much I learned and improved.


Conclusion

Overall the whole I am proud of all the learning and work I did. It has been one of the greatest experiences to learn and collaborate with such an amazing project as Krita, to meet all the team during the Krita Sprint and to realize how much more I can do to help.

I still have a lot to improve my project. Fortunately the end of the Google Summer of Code does not mean the end of my collaboration with Krita, which I hope will last for years to come and I feel proud to be a member of this community.

I have to admit my project is not yet ready to be part of Krita. There are still things to do, it is necessary to clean the code, to add more comments, and to add more tests. But thanks to the progress of the last few weeks I am confident it won't be that long before my brush can become part of Krita.


The future

Talking to my mentor and some other Krita developers, I was suggested to read more programming books, one of them being "Design Patterns: Elements of Reusable Object-Oriented Software". I plan to read this book to learn more and be able to produce better code for Krita.

I was also suggested by Tiar to start writing and small program that would reset the configuration of Krita, to help non-technical users, as suggested by this phabricator task.

Of course I want to keep improving my brush to take it to the next level, adding new features and options that were beyond the scope of the Google Summer of Code period and my coding abilities.