Saturday, April 13, 2024
Google search engine
HomeUncategorizedGIMP 2.99.18: The last development preview before 3.0

GIMP 2.99.18: The last development preview before 3.0

At long last, we bring you the final development version before GIMP 3! While the release of 2.99.18 is a bit behind our intended schedule, there are a number of new features and improvements that we’re very excited to share with you.

⚠️ ☢️


We remind that a development version means that this is a release to show
work-in-progress but also give an opportunity to the community to detect issues
early and report issues. In other word, this is an unstable version and we
do not recommend to use it in production. Use it because you want to help GIMP
improve by reporting bugs.

This version 2.99.18 in particular might be one of the most unstable releases in
the 2.99 series because of the space invasion. It is expected and normal.


⚠️ ☢️

This news post lists the most notable and visible changes. We do not list minor bug fixes or smaller improvements here. To get a more complete list of changes, you should refer to the NEWS file or look at the commit history.

(Color) Space Invasion

We have been working very hard on the Space Invasion project, which is — as you might
recall
 —
our codename for the project of making GIMP more correct regarding colors.

Lately we have been porting older internal color structures (GimpRGB,
GimpCMYK, GimpHSV…) which we used to carry color information to
GeglColor. This
generic object can contain any color data regardless of color model, precision
or space supported by babl, our pixel encoding engine.

What it means for color correctness in particular is that we will now do color
conversion only when needed (last-second conversion) and therefore won’t lose
information when it could have been avoided. For instance, say you color-pick
color from an image: if we were to convert to an intermediate format, before
using it on a second image (which may or may not be in another color format),
we’d do 2 conversions. Which means more possibility of precision loss. The issue
is even more flagrant if the input and output formats are the same (i.e. no
conversion should happen at all). And this will be even more a problem when we
will have core CMYK backend (we really want to avoid doing a round-trip to an
intermediate format with CMYK, which doesn’t have bijective conversion with most
other color models, even when working unbounded and ignoring precision issues).

We are also slowly moving stored data to this generic color object. In
particular it means that color palettes will be able to contain CMYK colors,
CIELAB colors or in any other supported model (and not only these colors after a
conversion to unbounded sRGB).

A consequence for code maintainance is that it makes it a lot easier to handle
color conversions within our codebase, now that the structure embeds both the
data and its “meaning”. It makes color handling a lot less bug-prone compared to
when we had to keep track of both information as separate data.

Lastly we are working toward showing color space information in various parts of
the interface, when relevant, such as when displaying or choosing RGB, CMYK, HSL
or HSV data.
Values in these color models without the associated color space are
near-meaningless. Interface displaying values in RGB without further
information are a remnant of the past when it mostly meant sRGB. This is
clearly not true anymore in modern graphic work and the interface should make
this clear.

The below video shows some of this interface work where RGB, HSV or CMYK models
for instance are always displaying the color space the values are in (which very
often means the name of the ICC profile). This is being done in the color picker
tool, color samples, FG/BG Color dockable, “Change Foreground/Background Color
dialog and in more places.

Not only this, but when people select a soft-proofing profile and activate
soft-proofing (e.g. through the nice new simulation toggle which was added in GIMP
2.99.12
),
we will also show out-of-gamut area not only within the image’s color space, but
also the soft-proof space.

(Color) Space Invasion in the interface – GIMP 2.99.18

Very important warning: this is once again a huge port in our codebase,
which impacted litterally thousands of lines of code. This work is unfinished
though it will have to be finished before the first release candidate. Therefore
unstabilities or bugs are to be expected in this update so if you encounter any
issue, we recommend to report
them
.

Improved Color Algorithms

Øyvind Kolås improved a few internal algorithms:

  • Achromatic pixels in the Hue-Saturation tool are now special-cased so that
    grayscale pixels (saturation of 0) are only changed by the master adjustment,
    not by the red adjustment.
  • Grayscale gradients are now kept achromatic even with “Dithering” checked in
    the Gradient tool.

As the space invasion project goes on, getting things
consistent is getting easier in various color-related algorithms, hence enabling
us to discover issues quickly and fix them.

Initial Non-Destructive Editing

One area we’re “ahead of schedule” on is the much-requested non-destructive editing! The foundation for these features has been laid by many developers over many years, since the introduction of GEGL into GIMP. Originally planned for the 3.2 roadmap, an initial implementation was made as a continuation of a Google Summer of Code project. If you are not familiar with the term, “non-destructive editing” means that filter effects such as Blur are kept separate from the layer’s pixels. This means that if later on you want to change a setting, rearrange, or even remove the filter, you can easily do so without affecting the rest of the image. Until now, GIMP has followed a destructive editing workflow where effects were immediately merged down onto the layer, so this is a major change!

Any GEGL operation that has a GUI is now applied to layers non-destructively (Non-destructive effects for layer masks and channels are planned for future updates.). This includes third-party GEGL plug-ins and custom operations created with our GEGL Graph tool. These effects can be saved and loaded in .xcf project files, although not all GEGL properties are supported in the current build.

Once a filter has been applied, you can interact with it further by clicking the filter icon in the layers dockable. This will open a pop-up that shows all filters currently applied to the layer. From here, you can toggle the filter’s visibility, edit the filter settings, re-order the filters, and delete individual effects. You can also merge down all filters to recreate a destructive workflow.

Non-destructive layer effects – GIMP 2.99.18

Note that this is only an early implementation, and much work remains to be done for a full-featured version of non-destructive editing. We will continue to refine the existing features for the 3.0 release based on user testing and feedback, and extend them further afterwards.
The interface itself is not how we envision this feature ideally and a first
specification draft was layed out
for a much more integrated workflow.

The below screenshot is a mockup from this first specification which would show
layer effects within the main layer list, sharing the same “eye” and “lock”
buttons, but also with their own easily editable mask:

Non-destructive layer effect Specification mockup image
Specification mockup image: vision of layer effects directly in the layer list with their own mask

Nevertheless creating this new interface will be its own challenge so we decided
to delay it to after GIMP 3 release and to propose this early implementation at first.

Please share your thoughts on the discussion forums and issue tracker!

Font Handling Improvements

Idriss Fekir, another GSoC 2023 student, has been working with long-time developer Liam Quinn to improve how GIMP handles fonts. A lot of this work was internal to improve GIMP’s ability to handle future font and text updates. Some of the more visible changes include:

  • GIMP no longer relies on font names being unique to distinguish between them. This means it won’t append “#1”, “#2” and so on but instead keep the original names in the font selection list. Despite the apparent name clash, both identically named font will now work properly.

  • GIMP can now load fonts using custom styles (bypassing Pango which is unable
    to load them).

  • We can now load more types of fonts than before. In cases where we don’t support a font yet (or the font is non-existent), we can better detect this and fall back to a default font. This also improves support when loading an .xcf file created on another computer to different fonts available.

  • On Windows, we force the Pango backend to always use anti-aliasing. This improves the readability of menu text on that operating system, especially with a dark theme.

  • The XCF-saving code now stores font information much more accurately which
    helps to avoid loading the wrong font when reopening some XCF.

  • Alignment of text in text layers for RTL languages is now more consistent with
    how it works in other software (such as LibreOffice or Scribus).

These changes are a lot less flashy relatively to some of the other features and
therefore may feel less important, yet they are actually the foundation work on
making text handling a lot more reliable in GIMP. We are envisionning a future
where text editing will be simpler while much more powerful and featureful (in
particular OpenType features are some of the big improvements we hope to get eventually).

Auto-Expanding Layers

The third GSoC project last summer by student Shubham Daule brought a long requested feature – auto-expanding layers! Brush tools now have an additional “Expand Layers” option. When checked, painting past the layer boundaries will cause them to automatically expand so you don’t have to manage the layer size yourself. If you want to expand the layer beyond the current size of the canvas, you’ll need to also check the “Show All” option in the View menu.

Auto-expanding layers – GIMP 2.99.18

The Expand Layers option also has additional settings when selected. You can decide how much you want the layer boundaries to expand by whenever the brush reaches them. There are also options to specify how the new areas of the layer and layer mask should be filled in when expanded.

New Snapping Options

New contributor mr. fantastic developed two new options for aligning layers on the canvas. With “Snap to Bounding Boxes” enabled, dynamic guides will now show when the layer you are moving is aligned with the center or sides of others. The active layer will also snap to those boundaries to assist you with arranging them properly. The second option, “Snap to Equidistance”, allows you to snap between three layers that are equidistant from each other.

New snapping options – GIMP 2.99.18

Themes

We continued to improve the user interface and style for this release. One of the biggest improvements was dealing with “system theme leaks”. There are styles that were not specifically defined in our themes, thus allowing different systems to supply their own (often conflicting) styles. With the help and feedback of several contributors and users, we’ve made a lot of progress in defining those styles so that everyone has a consistent experience!

Recently Jehan worked on re-organizing and simplifying our theme system. In past development versions we had five different themes: Default, Gray, System, Darker, and Compact (Each with light and dark options). These have been simplified into the System theme and a single Default theme with three possible states – light, dark, and gray. Similarly, our four separate icon themes were condensed into the Legacy set and a Default with Color and Symbolic options. We think these changes will reduce user confusion and make it easier for them to find their preferred interface appearance.

In addition, on Windows the main titlebar (and most dialog title bars) now adjust to light or dark mode depending on the selected theme.

Welcome Dialog

The Welcome Dialog has been expanded to provide quick access to a number of useful features and options. There are now four new sections:

  • Personalize: There are several customization options that require you to dig through the Preference Dialog to change. Now from this page you can easily change the color and icon themes, the user interface language and font size, and OS-specific settings.

  • Create: This page shows your eight most recently opened images and allows you to quickly reopen them. There are also buttons to create a new image or load an existing one. As with other programs, you can set this screen to automatically appear when GIMP starts for immediate access to these features.

  • Contribute: We consolidated some of the many ways you can be involved in GIMP’s development on this page. There are direct links to report bugs, write code, assist with translation or donate financially.

  • Release Notes: Originally these were shown on the lower half of the Welcome page. Now we have a full tab dedicated to them for easier reading.

File Formats

As in other releases, we have made improvements to existing file formats and added import and export support for some new ones.

DDS

A new contributor Stayd has been working with developer Jacob Boerema to make many improvements to the DDS plug-in. As a start, the import functions have been written to be simpler and easier to extend in the future. Some of the other additional updates include:

  • Loading 16 and 32 bits per channel RGBA DDS images is now possible.

  • The Catmull-Rom cubic filter has been added for mipmap generation, and all mipmap generation calculations are performed at 32-bit precision.

  • DDS images in the R8G8, R16, and R16G16 formats can now be loaded as well.

  • An option to flip DDS images vertical on import was added to mirror the existing export option, as some game images store their data this way.

GIF

In the past, overwriting a GIF rather than exporting would always convert it into a single frame image. Now we check to see if the GIF is an animation on load, so it will stay that way when overwritten.

HEIF and JPEGXL

Both plug-ins now use their respective libraries (libheif and libjxl) to load metadata. As a result, we have removed our custom code to interpret the image orientation and rely on the information supplied from the library instead.

OpenEXR

OpenEXR allows for channels to have custom names besides the color type. In these cases we now treat any single channel image with an unconventional name as grayscale. On import, we also display a notification so that users are aware of the conversion.

PDF

The “Layers as Pages” export option now works even if there is only a single layer group. Previously this option was not available, as the plug-in only checked if there was more than one “layer” without considering if it was a layer group with multiple sub-layers.

PNG

Safe-to-copy PNG chunks are now preserved on import and included in the exported image. Additionally, an often-reported issue with exporting transparent indexed PNGs has been fixed. Now the exported indexed colors should be displayed correctly.

PSD

Jacob Boerema continued his work to improve the PSD plug-in. In addition to bug fixes such as correcting the layer order on import, he also clarified the export warning on layer mode compatibility between GIMP and Photoshop.

PSP

The Paintshop Pro plug-in now supports importing more features from the project file, such as the ICC color profile, guides, grids, and the active selection from when the file was saved. The ZDICAN-22096 and ZDICAN-22097 security vulnerabilities were also patched in this release.

New image format supports: Farbfeld, Esm Software PIX, HEJ2

We recently added import and export support for Farbfeld, an sRGB image format intended to be easy to parse, pipe, and compress externally.

We also added import only support for the following new file formats:

  • Esm Software PIX: A modified JPEG format used exclusively by the Esm Software company to store their customized images. This was implemented in response to a bug report that confused this format with our existing Alias PIX image support.

  • HEJ2: An addition to our existing HEIF plug-in by contributor Daniel Novomeský which allows importing JPEG 2000 compressed images.

New palette format support: Swatchbooker

Swatchbooker is a free/libre open source software that creates and converts color palettes in a variety of formats. While the software itself has not been updated in many years, its custom palette format .sbz is the most comprehensive of all the ones we currently support. Among its many features are allowing multiple color model definitions per palette entry, localizable names and descriptions, and support for per-entry ICC color profiles.

While working on our import support, we were able to contribute information that led to a bug fix in Krita’s support for Swatchbooker. It’s always great when projects can work together and help each other!

Wayland Tablet Pad Interactions

Long-time GNOME contributor Carlos Garnacho added support for interacting with GIMP via tablet pads. When a tablet is plugged in, you can now assign different actions to the tablet controls via the “Input Device” dialog under the Edit menu.

This work also involved porting features to GTK 3, the GUI framework that GIMP is built on. Note that this feature is currently only supported on Wayland.

API Updates

The Application Programming Interface, for plug-in makers, is steadily being
reworked as part of the GIMP 3 overhaul. Part of it is that when colors are
involved, we are moving the API to use GeglColor as part of the more general
Space Invasion project. Yet it’s only a small part of
the whole API improvements.

We are also moving towards more classes to represent the various resources
managed by GIMP (brushes, fonts, patterns, etc.) instead of only representing
these by names (which was a historical limitation whereas it is absolutely
possible for 2 resource makers to choose the same name and the fact is that we
see such cases in the wild — for instance 2 fonts independently created may have
the same name).

Another big move is replacing the GimpValueArray representing the ordered
arguments of a plug-in procedure by a GimpProcedureConfig which contains
arguments by name instead of by order. This allows much more semantic usage of
plug-in procedures (especially when they have long list of arguments) but also
will make it easier to enhance plug-ins in the future, with new or reordered
arguments without creating new procedures because the order and number arguments
matter a lot less. It means that adding new arguments in the future won’t break
existing scripts depending on past versions of these plug-ins anymore (plug-in
writers will still have to choose appropriate defaults for the new arguments in
order for this to be true, of course).

In parallel, we continue to improve the ability of automatic GUI creation given
to plug-ins, making creating dialogs more easy than ever. This includes (among
many other enhancements) a new type of procedure argument named GimpChoice
which is a string list of choices which can be displayed to creators as
drop-down list widgets in your plug-in dialog.

We are planning to write and release tutorial for plug-in writers in the
Resource Development section of our
developer website in the same time as GIMP 3
release, or not long after.

GEGL and babl

This release of GIMP is accompanied by new releases of GEGL and babl, both of which assist with the color space invasion project.

babl 0.1.108 brings a new babl_space_is_rgb function to help us directly confirm a color space is RGB (rather than doing multiple tests to see if it’s not CMYK or grayscale). There were also several improvements to the build process and to the babl command-line interface tool.

GEGL 0.4.48 provides several updates to the GeglColor object which now supports much of GIMP’s color operation. Specific improvements include being able to directly get and set CMYK color values, as well as assigning the color space when setting RGB(A) colors.

A crash in the existing gegl:voroni filter was fixed, and a long-standing bug with the gegl:dropshadow filter which prevented the effect from shrinking was corrected too.

Last but not least, a new gegl:shuffle-search filter was added to the workshop. It shuffles neighboring pixels to create a more optimized dithering effect.

Release stats

Apart from the first version in the series (2.99.2), GIMP 2.99.18 is clearly the
biggest update in most numbers. Since 2.99.16:

  • 238 reports were closed as FIXED.
  • 201 merge requests were merged.
  • 1358 commits were pushed.
  • 26 translations were updated: Basque, Belarusian, Brazilian Portuguese,
    Bulgarian, Catalan, Chinese (China), Danish, Esperanto, Finnish, Georgian,
    German, Greek, Hungarian, Icelandic, Italian, Lithuanian, Norwegian Nynorsk,
    Persian, Polish, Russian, Slovenian, Spanish, Swedish, Turkish, Ukrainian, Vietnamese.

60 people contributed changes or fixes to GIMP 2.99.18 codebase (order is
determined by number of commits; some people are in several groups):

  • 23 developers to core code: Jehan, Alx Sa, Shubham, Jacob Boerema, Idriss
    Fekir, bootchk, Anders Jonsson, Carlos Garnacho, mr.fantastic, Stanislav
    Grinkov, lillolollo, Øyvind Kolås, Sabri Ünal, programmer_ceds, Lukas
    Oberhuber, programmer-ceds, James Golden, Luca Bacci, Massimo Valentini, Niels
    De Graef, Zander Brown, psykose, sonia.
  • 17 developers to plug-ins or modules: Jehan, Alx Sa, Jacob Boerema, bootchk,
    Anders Jonsson, Stayd, Zander Brown, Bruno Lopes, Daniel Novomeský, Sabri
    Ünal, programmer_ceds, Kamil Burda, Mark, Michael Schumacher, Stanislav
    Grinkov, programmer-ceds, sonia.
  • 31 translators: Yuri Chornoivan, Martin, Ekaterine Papava, Luming Zh, Sabri
    Ünal, Anders Jonsson, Rodrigo Lledó, Jordi Mas, Alan Mortensen, Vasil Pupkin,
    Asier Sarasua Garmendia, Kolbjørn Stuestøl, Boyuan Yang, Víttor Paulo Vieira
    da Costa, dimspingos, Alexander Shopov, Alexandre Prokoudine, Aurimas Černius,
    Balázs Úr, Marco Ciampa, Sveinn í Felli, Danial Behzadi, Ngọc Quân Trần,
    Jürgen Benvenuti, Piotr Drąg, Timo Jyrinki, Andre Klapper, Kristjan SCHMIDT,
    MohammadSaleh Kamyab, Rafael Fontenelle, Tim Sabsch.
  • 9 resource creators (icons, themes, cursors, splash screen, metadata…): Alx
    Sa, Jehan, Ferry Jérémie, Stanislav Grinkov, Anders Jonsson, Bruno Lopes,
    Jacob Boerema, Sabri Ünal, mr.fantastic.
  • 5 documentation contributors: Jehan, Bruno Lopes, Jacob Boerema, Alx Sa,
    Anders Jonsson.
  • 14 build, packaging or CI contributors: Jehan, Bruno Lopes, bootchk, Alx Sa,
    Zander Brown, Jacob Boerema, Jacob Boerema, Stayd, Carlos Garnacho, Heiko
    Becker, mr.fantastic, Daniel Novomeský, U-YGGDRASILender, lillolollo.

Contributions on other repositories in the GIMPverse (order is determined by
number of commits):

  • babl 0.1.108 is made of 17 commits by 6 contributors: Jehan, Øyvind Kolås,
    John Marshall, Andre Klapper, John, sid.
  • GEGL 0.4.48 is made of 77 commits by 20 contributors: Øyvind Kolås, Jehan,
    Anders Jonsson, Jacob Boerema, Yuri Chornoivan, Alan Mortensen, Sabri Ünal,
    Andre Klapper, Ekaterine Papava, Jan Tojnar, Jordi Mas, Luming Zh, Martin,
    Piotr Drąg, Víttor Paulo Vieira da Costa, Asier Sarasua Garmendia, Marco
    Ciampa, Rodrigo Lledó, dimspingos, woob.
  • ctx had 308 commits since 2.99.14 release by 1
    contributor: Øyvind Kolås.
  • The gimp-macos-build (macOS packaging scripts) release is made of 32 commits
    by 1 contributor: Lukas Oberhuber.
  • The flatpak release is made of 15 commits by 3 contributors: Jehan, Daniel
    Novomeský and Hubert Figuière.
  • Our main website (what you are reading right now) had 31 commits since
    2.10.36 release by 6 contributors: Jehan, Alx Sa, Sabri Ünal, Anders Jonsson,
    Bruno Lopes, Jonathan Demeyer.
  • Our developer website had 30 commits since
    2.10.36 release by 5 contributors: Bruno Lopes, Jehan, Alx Sa, bootchk, Robin Swift.
  • Our 3.0 documentation had 247 commits since
    2.99.16 release by 17 contributors: Andre Klapper, Jacob Boerema, Yuri
    Chornoivan, Alx Sa, Jordi Mas, Alan Mortensen, dimspingos, Anders Jonsson,
    Boyuan Yang, Sabri Ünal, Víttor Paulo Vieira da Costa, Juliano de Souza
    Camargo, Rodrigo Lledó, Kolbjørn Stuestøl, Marco Ciampa, Danial Behzadi, Emin
    Tufan Çetin.

Let’s not forget to thank all the people who help us triaging in Gitlab, report
bugs and discuss possible improvements with us.
Our community is deeply thankful as well to the internet warriors who manage our
various discussion channels or social
network accounts such as Ville Pätsi, Liam Quin, Michael Schumacher and Sevenix!

Note: considering the number of parts in GIMP and around, and how we
get statistics through git scripting, errors may slip inside these
stats. Feel free to tell us if we missed or mis-categorized some
contributors or contributions.

Team news and release process

Access rights to the git repository were recently given to Bruno Lopes (who has been very active improving our build process and Windows packaging).

Several long term or recent developers or packagers who started to contribute to
the new developer website were also given access to the associated git
repository.

More contributors are now actively participating to testing releases and
packaging, and this is the first news for years which Jehan has not written
nearly entirely! Thanks a lot to Alx Sa (a.k.a. Nikc or CmykStudent) for taking
up on collaborative news writing!

Clearly we are consolidating day after day a solid core team of contributors and
this shows in our release process having more and more feedback at each release.

We are also particularly happy and proud that the 4 GSoC projects we had, since
we started again subscribing to this mentoring program, were all successful and
ended up being merged to the main code branch within half a year at most after
the internship end.

Around GIMP

Mirror News

Since our last
news
, a new
mirror has been
contributed to GIMP by:

  • Sahil Dhiman, in Nürnberg, Germany, as a personal project.

This brings us to a total of 46 mirrors all over the world.

Mirrors are important as they help the project by sharing the load for dozens of
thousands of daily downloads. Moreover by having mirrors spread across the
globe, we ensure that everyone can have fast download access to GIMP.

GIMP on Windows/ARM

Since our news for an experimental build on Windows for ARM 64-bit
architecture
,
we received help from Hernan Martinez, well known contributor in the MSYS2
project, who hosted our first ever CI runner for Windows on Aarch64
architecture. Though this was only a temporary setup (literally a build machine
in someone’s living room) until we get a more stable situation, we are extremely
thankful to Hernan who helped us make our second step on this platform (the
first step was done by Jernej, who made our first experimental installer), make
sure our automatic build process worked there and more.

Since then, we got the stabler situation: Arm Ltd. themselves stepped up and
contributed officially 3 runners for our Continuous Integration process in
Gitlab! Arm Ltd. also sponsored a Windows devkit to one of our developers.

While we still do consider this build experimental, because of lack of testing
and because only 2 contributors have a machine able to run it right now, the
biggest blocker got removed and we are happy to announce that our universal
Windows installer for GIMP 2.99.18 contains GIMP for all 3 platforms (x86 32 and
64-bit, and now ARM 64-bit)!

Downloading GIMP 2.99.18

You will find all our official builds on GIMP official website
(gimp.org)
:

  • Linux flatpaks for x86 and ARM (64-bit)
  • Universal Windows installer for x86 (32 and 64-bit) and for ARM (64-bit)
  • macOS DMG packages for Intel hardware
  • macOS DMG packages for Apple Silicon hardware

Other packages made by third-parties are obviously expected to follow
(Linux or *BSD distributions’ packages, etc.).

What’s next

As we have now entered a feature freeze, our focus has shifted to bug-fixing, clean-up, and preparing for the first 3.0 release candidate.

We indeed think that this should be the last development release since no new
feature will be introduced from now on, at least GUI features (the API is still
evolving until the first release candidate). So what you see now is basically
what you should get in GIMP 3.0.0, feature-wise.

This is why we released this version even though we know it is quite unstable.
Now is the time for last minute comments! Also it’s the moment to report and fix
bugs like there is no tomorrow. We hope to be able to deliver a RC1 soon and it should be as bugless as possible.

Our current expectation is to be able to release GIMP for the upcoming Libre
Graphics Meeting
in May 9-12. To be
fair, this is not an easy goal and therefore we are not sure if we can make it.
What is sure is that even if we did not manage this on time, it should not
happen too long after.
In particular we won’t release just because we set a deadline. We want to
provide the best experience, which means that if we discover last minute blocker
bugs, we will delay the release until they are fixed.

Don’t forget you can donate and personally fund GIMP
developers
, as a way to give back and
accelerate the development of GIMP.
Community commitment helps the project to grow stronger! 💪🥳

Read More

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

- Advertisment -
Google search engine

Most Popular

Recent Comments