------------------------------ GNU Image Manipulation Program Development Branch ------------------------------ This is the unstable branch of GIMP. Overview of Changes from GIMP 2.99.2 to GIMP 2.99.4 =================================================== Core: - Action search now always show all actions, even inactive ones. In order not to clutter the results, inactive ones are shown after active results (following the same match quality level). Consequently the "Show unavailable actions" checkbox has been removed from the `Preferences > Help System` dialog. - Improve sample text logics for CJK fonts, showing different sample characters for Korean and Japanese, making detection at-a-glance of such fonts easier. - With "Ask what to do" color profile policy, profile conversion at image loading is not proposed anymore when the image's profile is the preferred profile set in Preferences for the current image type (currently it would only be discarded if the image's profile was the built-in profile, now GIMP accounts for both cases). - When file loading plug-ins are run, the file chooser dialog is now hidden until the plug-in returns. - GIMP tries to keep error dialogs above to raise awareness when they arrive (not discovered later under other dialogs). User Interface: - GimpSpinScale widget improvements: * The widget will grab focus when starting to edit the entry, and in particular the current number will be fully selected (because often we want to just type down a completely different number accurately). * Also when giving focus to the entry with middle click (from anywhere inside the widget), the scale value doesn't change in the same time anymore. * Finally we can now target-click accurately the entry current value to edit the entry (again, without changing the value and selecting existing number fully) with the main button (usually left button). Even though middle click is simpler because we don't have to be accurate (we can middle-click anywhere in the spin scale widget), it is hardly discoverable, whereas clicking a number entry which is meant to be editable is the most common GUI interaction expectation. * To help feature discoverability, when hovering the widget, the cursor will change and show a "grab" cursor when a click would start an absolute edit (the cursor changes to "grabbing" when actually clicking and dragging the scale) or a "text" cursor when a click would focus the number entry. When Shift key is being hold, the cursor is the one for the relative edit, wherever the position over the widget. This should make discovering possible interactions with the widget a lot easier. - Various improvements in the Layers dockable (and similar tree view widgets): * The bigger thumbnail popup on long click (e.g. on a layer or mask thumbnail) does not pop out when any modifier is hold (such as Shift/Ctrl for multi-selection or any other modifier used for alternative actions). * Alternative actions which were available with modifier-clicks on layer or mask thumbnails have been moved to an Alt+ modifier when necessary, in order to not clash with multi-layer selection interaction. In particular: + Ctrl-click on a mask to enable/disable it now moved to Alt-Ctrl-click. * The Shift+click and Ctrl+click actions on a layer thumbnail to add and remove respectively a layer mask have been removed because the much older feature for "Alpha to Selection" already use all the Alt+ modifier combinations. * The alternative Alt+ actions now only operate on the clicked layer and not on the selection unlike the corresponding actions (available through buttons, actions and menus). Also they do not change the selection. So you can Alt+click a layer for "Alpha to Selection", same as you can Alt+click a mask for showing it without triggering a selection change. This allows these alternative actions to not be redundant of the equivalent actions but complementary with a slightly different targetting behavior. * The various interactions with modifiers now catch the exact modifier combination they require, hence avoiding interaction cases running several actions (e.g. Alt-Ctrl on a layer thumbnail removes the clicked layer's alpha channel from the selection without modifying the selected layer while Ctrl only would modify the selection). Tools: - New Paint Select tool in the playground. This is a tool prototype which would hopefully end up as a quick binary selection tool. - The new default dynamics is: "Pressure Size". This doesn't change anything for common input devices (mouses, touchpad) yet would allow tablet devices to directly show that pressure input is working on first use. Until now, people would have the impression that tablets are not working (even though GIMP 3 will have hotplug so it is actually working from scratch) just because "Dynamics Off" was the default. Input Devices: - Various improvements to the Input Devices editor: * Do not show virtual devices and XTEST API (Linux/X11) device in the Input Devices editor as they are useless from a configuration standpoint. * Only show the axes returned by GDK instead of the whole list of possible axes, which made no sense. * Show better names for axes, as returned by GDK, for instance a X axis becomes often "Abs X" on a graphics tablet and "Rel X" on a mouse or other devices made to work relatively. * Don't show an empty list for devices with no axes, just don't show the list widget at all. * For each device, select by default the first axis with curve ability, if any, (i.e. the Pressure axis if the device has one) in order to make the dialog directly more useful and usable. - Default tool have been set on different device sources: * Pen devices (tablet styluses main input) now default to the paintbrush tool. * Eraser devices (tablet styluses back input) still defaults to eraser tool. * Touch screen (finger) defaults to Smudge tool. * All other devices defaults to paintbrush (this was already the case, but was broken for as long as I remember, now it should work properly). API: - GimpFileEntry public variables were made private and a new function has been added: gimp_file_entry_get_entry(). - New GimpScaleEntry and GimpColorScaleEntry widget classes and new relevant API for these objects, replacing the former functions creating various widgets and attaching them to a GtkGrid. This makes for easier to use and less constrained GUI functions (with a lot less arguments, as we try now to smartly generate appropriate defaults for many options; gimp_scale_entry_new() in particular went down from 17 arguments to 5), also better introspectability for bindings, and finally it will be useful for automatic dialog generation for plug-ins. - New GimpLabeled class and subclasses: GimpLabelSpin, GimpLabelIntWidget. - Several new functions for GimpProcedureDialog for automatic dialog generation based on input arguments. Though not mandatory, the various functions allow to organize better the widgets. - The GimpProcedureDialog class will now check that mnemonics are present on every option, and also that there is no duplicate mnemonics. It will print messages on stderr if any of these test fails (so that it won't bother users but developers and translators should be able to get feedback about missing/duplicate mnemonics). - GimpSaveProcedure now has generic metadata support (with an API so that an export procedure can declare whether it supports given metadata types or contents). Combined with a new subclass GimpSaveProcedureDialog (child of GimpProcedureDialog), this ensures that: * If a format supports a given metadata, they will always have an auxiliary argument with the same name across plug-ins. * The label and tooltips will also be always the same in the GUI. * Order of metadata widgets will also stay consistent. * The widgets will work the same (no more "Comment" text view missing in one plug-in but present in another, or with an entry here, and a text view there, and so on). * The metadata frame will show an "(edit)" link which will run the "plug-in-metadata-editor" plug-in. The eventual goal is to move some generic logics to the metadata editor (when it makes sense) and to raise awareness for metadata edition and viewing abilities. This is still a work-in-progress which requires much more improvements in said abilities. - New gimp_get_num_processors() function for plug-ins to be able to set their own multi-threading operations as configured in Preferences. Plug-ins: - file-fli, file-tiff, file-jpeg and file-png updated to new dialog generation API. In the most complicated case (file-jpeg), this shaved 600 lines out of the plug-in code. - file-heif: - now uses gimp_get_num_processors() instead of g_get_num_processors() (allowing to bypass system thread info). - Realtime parameter is set for AOM encoder when Fast encoding speed is selected by user. - Ability to set pixel format (YUV444, RGB) is enabled for >= libheif 1.10 to avoid issues in older versions. - file-jp2 is now able to decode JPEG2000 files faster with multi-threading, using the thread number settings returned by gimp_get_num_processors(). - Improved plug-in debugging helper infrastructure: GIMP_PLUGIN_DEBUG has a new `fatal-criticals` option and better defaults. Developer documentation got some rewritting and debugging code benefited from refactorization. Installer: - Various updates to adapt to the GIMP 2.99/3 build. - Lua made optional. Devel docs: - Documentation to port GIMP 2.10 plug-ins to GIMP 3.0 has been started in `devel-docs/GIMP3-plug-in-porting-guide/`. It is also visible directly on out Gitlab instance with visual styling: https://gitlab.gnome.org/GNOME/gimp/-/tree/master/devel-docs/GIMP3-plug-in-porting-guide Build: - Bumping minimum harfbuzz version to 1.0.5 for hb_ft_font_set_funcs(). - Bumping minimum pango version to 1.44.0 for pango_font_has_char(). - Bumping minimum GEGL to version 0.4.28. Overview of Changes from GIMP 2.10.x to GIMP 2.99.2 =================================================== Core: - Improved "space invasion". - New extension format support (.gex a.k.a. GIMP Extension) which is an archive containing various supported data. So far, it can package: brushes, MyPaint brushes, dynamics, patterns, gradients, palettes, tool presets, plug-ins, splash images and themes. - New extension manager allowing to enable, disable or uninstall installed extensions, with a dialog available in `Edit > Manage Extensions`. - Multi selection of layers now possible. Various tools and features are now multi-selection aware. - XCF format bumped to version 14 with awareness of multiple layer selection. - All code is year-2038-safe with deprecated time API replaced. - "Alpha to Selection" various actions warn when the result selection is empty. - Color Profile Policy (import) now exposes a "Convert to Preferred Profile" (fourth) choice and the import dialog default "Convert" action will convert the image to the preferred profile (if any was set, otherwise it falls back to the built-in profile). Converting to the built-in profile will be still available as secondary action. - A new "Metadata Rotation Policy" is now exposed in the Preferences dialog, next to the "Color Profile Policy" (in page `Preferences > Image Import & Export`) with 3 options: "Ask what to do", "Discard metadata without rotating" and "Rotate the image then discard metadata". This policy used to be handled API-size, with a dialog generated by libgimpui gimp_image_metadata_load_finish(), and saved in a global parasite. The whole logics and GUI has been moved as core logics, similar to the "Color Profile Policy". User Interface: - Whole interface ported to GTK+3: * Proper HiDPI support, which will follow the system's scale factor for all widgets. This is a core toolkit support, unlike the basic better-than-nothing hacks from GIMP 2.10.x. * GTK+3 CSS-like support. All themes for former versions are therefore not working anymore. * GTK+3 themes have the concept of "dark variant", so a same theme may propose both a light and a dark versions. Preference for dark variants can now be checked in `Preferences > Themes > Use dark theme variant if available` checkbox, allowing for instance to use your system theme in its light variant everywhere except in GIMP. This option is checked by default as graphics software are often prefered in dark modes. * Symbolic icon themes are now recolored automatically according to the theme colors (no theme and icon theme tweaking anymore to end up with dark on dark or light on light interfaces), except for color elements whose SVG style is marked as "!important". * Native Wayland support. * Various dialogs now use Client-Side decorations and modern GTK+ widgets are being used when relevant (e.g. GtkSwitch which gives a better feeling of a general "ON/OFF state"). - Image display rendered faster with a render cache that keeps the result of scaling, color management, display filters and shell mask (for tools like fuzzy select). - Shift-click on layer GimpContainerTreeView (typically the Layers dockable) allows to expand/collapse all item groups but the clicked one. - Compact GimpSpinScale is now the only available version. - Scalable symbolic icons "switch-on", "switch-off" (from GTK repository) and "software-update-available" (from Adwaita repository) are now bundled with GIMP in a "hicolor" overlay so that they are available even if missing from the custom theme. Devices: - Device hotplug supported (thanks to GTK+3). In particular: * you don't need to have your tablets and other devices plugged before you start GIMP anymore; * enabling your devices in the "Configure Input Devices" dialog is not needed anymore. Tablets will work out-of-the box; * you can safely unplug and replug the same or other input devices while GIMP is running. - "Input Devices" dialog improved: * "Save" and "Close" buttons replaced by "OK" (save and exit), "Cancel" (reset and exit) and "Reset" (reset to previous settings but keep the dialog open). * "Keys" list has been discontinued. The "key" concept is associated to "keyboard" devices (a tablet being a "pointing device" with buttons, not keys) so this list was actually useless and only confusing. Plug-ins: - Major rewrite of the API (see below). So GIMP 2.10.x plug-ins and below must be ported to the new API. - Every introspected binding which we test comes with a "Goat Exercise", which is a demo plug-in popping a dialog and showing its own source code. It processes a simple "gegl:invert" operation on a drawable. All "Goat Exercises" must do the same thing in the same way, simply in their respective languages, as documentation/example code for a language binding. - The Goat Exercise plug-ins are themselves installed as a GIMP Extension, as a demo for extension creation. - Plug-ins must be installed in their own subdirectory in `$XDG_CONFIG_HOME/GIMP/2.99/plug-ins/`, thus preventing data mess (with plug-ins coming with data and installing it all in the root plug-ins/ directory) and DLL hell. The main plug-in executable must be named the same as the directory (possibly with an added extension). E.g.: `plug-ins/my-cool-plug-in/my-cool-plug-in.py` - HEIF export allows selecting color subsampling/pixel format (YUV444, YUV420, RGB) and encoder speed (Slow, Balanced, Fast). Lossless option delivers visually lossless output. - New "file-heif-av1-load" procedure separate from "file-heif-load" for AVIF only. API: - `GimpPDB` is now a class to represent the PDB communication channel with GIMP. It is a singleton which exist exactly once per running plug-in, hence it is not meant to be manually instanciated and can only be returned by gimp_get_pdb(). It is mostly used to look up procedures declared by other plug-ins or by GIMP core, check if a given procedure exist and run the procedures. - `GimpPlugIn` is a class which every plug-in should now subclass as a way to create their plug-in, and override at least the methods query_procedures() and create_procedure(). Two other methods (init_procedures() and quit()) can be optionally overridden. The new subclass must be declared to gimp by calling gimp_main() to make it available to the core (PDB procedure, menu items, etc.). A plug-in can obtain its own GimpPlugIn instance with gimp_get_plug_in(). This is a singleton object which belongs to libgimp. - Plug-In procedures are now represented by a class `GimpProcedure`. * The subclass `GimpFileProcedure` handles file-related procedures, and its own subclasses `GimpLoadProcedure` and `GimpSaveProcedure` handle load/export procedures (file format support). * The subclass `GimpThumbnailProcedure` for procedures run during the lifetime of the GIMP session each time a plug-in thumbnail procedure is called. * The subclass `GimpImageProcedure` handles `GimpImage`-related procedures, i.e. any procedure which want to work on the opened image (GIMP core will pass through the active image and selected drawables to the plug-in procedure). * Objects of the subclass `GimpPDBProcedure` are not meant to be created or freed by plug-ins, they represent any `GimpProcedure` and are returned by `gimp_pdb_lookup_procedure()` by looking it up by name on the singleton `GimpPDB` object. - `GimpProcedureConfig` is the base class to represent the arguments when running a `GimpProcedure`. It implements the `GimpConfig` interface and will provide proper management of saved settings (including the last used values) and generated GUI using prop_widgets to plug-ins. This is still a work-in-progress. Currently `GimpProcedure` run function is called with a `GimpValueArray` whose values can be transfered into a `GimpProcedureConfig` by calling `gimp_procedure_config_begin_run()` or `gimp_procedure_config_begin_export()`. - `GimpDisplay` is now a class of its own. - `GimpImage` is now a class to represent an opened image. - `GimpItem` is now a class to represent various `GimpImage` items. * `GimpVectors` subclass represents an image path. * `GimpDrawable` subclass represents drawable object but is a simili-abstract class as it won't be a finale object class, which can be so far either a: + `GimpLayer` represents image layers. + `GimpChannel` represents a `GimpImage` channel which is typically in GIMP a named channel which can be added into a `GimpImage` channel stack (the "Channels" dockable in the GUI) with `gimp_image_insert_channel()`. This class is not really used to represent a color space component though this is conceptually the same thing (so maybe some day) and named channel can actually be created from an image color component with `gimp_channel_new_from_component()`. Some other specific usages have their own subclasses: - `GimpLayerMask` subclass is used for a `GimpLayer` mask. - `GimpSelection` subclass is used for a `GimpImage` selection. - GimpImage, GimpItem and GimpDisplay (and their various subclasses) represent objects which can be passed through the PDB. They are managed by libgimp and should not be freed by plug-ins. - The PDB-passing classes still have IDs which can be obtained with gimp_image_get_id(), gimp_item_get_id() and gimp_display_get_id() respectively. Conversely you can get back the object with gimp_image_get_by_id(), gimp_item_get_by_id() and gimp_display_get_by_id(). Specific variants exist to get back an item object from its ID, such as gimp_layer_get_by_id(), which do additional class verification (other than this, they are similar to gimp_item_get_by_id()). **NOTE**: since objects are managed by libgimp, you are ensured that a `*_get_by_id()` call returns you exactly the same object you had previously for a given object. Consequently you can do pointer comparison of objects to compare images, items or displays during a given run. This will work because objects are unique (these are not several object copies representing the same remote object). - Type validation function which used to work on IDs now work directly with object arguments while new function with added `*_id*` have been created to validate from an object ID instead, GIMP 2.10-style. To verify if an ID exist: * gimp_image_is_valid() / gimp_image_id_is_valid() * gimp_item_is_valid() / gimp_item_id_is_valid() * gimp_display_is_valid() / gimp_display_id_is_valid() To check if GimpItem are from specific subclasses: * gimp_item_is_drawable() / gimp_item_id_is_drawable() * gimp_item_is_layer() / gimp_item_id_is_layer() * gimp_item_is_text_layer() / gimp_item_id_is_text_layer() * gimp_item_is_channel() / gimp_item_id_is_channel() * gimp_item_is_layer_mask() / gimp_item_id_is_layer_mask() * gimp_item_is_selection() / gimp_item_id_is_selection() * gimp_item_is_vectors() / gimp_item_id_is_vectors() **NOTE**: since these are GObject classes, you can also use the GObject style macros such as GIMP_IS_LAYER(). Yet these macros do not do any ID verification (which is not a problem anyway in most cases as you got the object from API calls) and will not exist in bindings. **IMPORTANT**: using IDs is mostly for internal usage and actually there are very few reasons to ever need to get an object ID from a plug-in. Usually you should rather just work only with the unique object pointers returned by the API. - The whole API has been updated to use objects instead of object IDs when relevant. For instance all existing libgimp functions from 2.10 which were called on an image ID are now called on a GimpImage object instead. - All file paths procedure parameters are now handled by GIO's `GFile` which simplify various file handling issues (path formats, encoding, etc.) and brings new features (remote access, secure protocol support, etc.). We also got rid of the "filename" vs "raw_filename" differenciation in parameters. Hence all libgimp* functions with these parameters have been updated as well. - gimp_image_metadata_load_finish() is now fully GUI/GTK-code free. The first consequence is that it is not in libgimpui anymore, but in libgimp, as it should. The second consequence is that the boolean `interactive` argument has been removed. Now all image rotation logics (the part which needed a GUI) has been moved into core and will be automatically run when normally loading images from GIMP's interface, similarly as to how color profiles was already handled. - 2 new libgimp functions: gimp_image_policy_rotate() and gimp_image_policy_color_profile() are now available to explicitly call the Preferences-set policy on an image. This may result in a dialog being presented to the user if `interactive` is TRUE and settings is "Ask what to do". It is unecessary to call these functions when developing a new GimpLoadProcedure because the core will automatically do the right thing and call these on normal image loading workflow. Instead if a plug-in calls such GimpLoadProcedure through the PDB, no such functions will be run automatically. It is up to the plug-in to decide what to do (no conversion, mandatory conversion, or using user settings, possibly with a dialog to decide, hence calling these functions explicitly). - New function gimp_export_comment() to query the user settings (as set in Preferences) on whether or not a file plug-in should export the image's comment. - Several functions which are returning C-array of objects with a size output argument now also have a GList counterpart (not as replacement, but as additional API): * gimp_get_images() -> gimp_list_images() * gimp_image_get_layers() -> gimp_image_list_layers() * gimp_image_get_selected_layers() -> gimp_image_list_selected_layers() * gimp_image_get_channels() -> gimp_image_list_channels() * gimp_image_get_vectors() -> gimp_image_list_vectors() * gimp_item_get_children() -> gimp_item_list_children() - New function gimp_vectors_stroke_reverse() to reverse a specified stroke in a given GimpVectors. - In GIMP 2.10, functions gimp_drawable_preview_get_drawable() and gimp_zoom_preview_get_drawable() got deprecated in favor of respectively gimp_drawable_preview_get_drawable_id() and gimp_zoom_preview_get_drawable_id(). The original names have been reinstated and now returns a GimpDrawable object, whereas the newer functions got removed. Similarly gimp_zoom_preview_new_from_drawable_id() and gimp_drawable_preview_new_from_drawable_id() are replaced by respectively gimp_zoom_preview_new_from_drawable() and gimp_drawable_preview_new_from_drawable(). - Deprecated functions in GIMP 2.10.x have been removed. To get a list of these function, this file should hopefully map most of them to a replacement equivalent: devel-docs/GIMP3-plug-in-porting-guide/removed_functions.md - gimp_spin_button_new() had some weird compatibility macro to expand to a newer or older signature depending on the number of arguments. Now only the newer signature with 3 arguments is available. - Properties removed from custom widgets: * GimpAspectPreview, GimpDrawablePreview and GimpZoomPreview had a deprecated "drawable" property in favor of "drawable-id" property. The "drawable" property got reinstated (and the "drawable-id" removed) and obviously now stores a GimpDrawable object rather than an integer. * The property "stock-id" was removed from GimpHintBox and GimpCellRendererToggle. Use "icon-name" instead. - Note: there are likely more API changes, unfortunately we haven't kept the NEWS file up-to-start from scratch. The best is to look at the API generated documentation. - The full API is GObject Introspected into 2 modules: Gimp and GimpUi. This means plug-ins can be written in various non-C languages. So far the following languages have been tested and work well: Python 3, Lua, Javascript and Vala. (Note: Python 2 is also working, but considering that this language is end-of-life since 2020, we don't really care). - All pygimp specific Python API does not exist anymore. Python will use the same API as C plug-ins, introspected through GObject Introspection. Documentation: - `devel-docs/xcf.txt` updated to handle XCF 14. Build: - New meson build system. Still deemed "experimental" for the time being. Packagers are recommended to continue using the autotools build system in order to avoid build system-specific bugs. - Continuous integration in Gitlab with: - an autotools build with GCC on a Debian/testing runner - an autotools distcheck build on a Debian/testing runner - a meson build with GCC on a Debian/testing runner - a meson build with Clang on a Debian/testing runner - a meson cross-build with Mingw-w64 for Windows 32-bit - a meson cross-build with Mingw-w64 for Windows 64-bit - static code analysis with cppcheck - a source tarball distribution job (tar.bz2 and tar.xz) - a ready-to-run Windows 64-bit test archive - a ready-to-run Windows 32-bit test archive Known blocker issues: - GTK+3 port is functional but not complete as some deprecated APIs are still being used. - Space invasion is still a work-in-progress. - Plug-ins API update is still a work-in-progress. - GIMP extensions are still a work-in-progress. - Multiple layer selection is still work-in-progress. Some issues are expected, and possibly even some crashes in code paths which were not updated yet. - No custom theme yet, in particular we want a neutral gray theme with light/dark variants, and a middle-gray theme too. - We probably want to revive a "Small" theme as well with smaller icons (useful on smaller displays, or mid-high density displays or simply depending on tastes). - Various blocking bugs happen on Wayland only.