Skip to main content

Pragtical v3.8.0 Release

· 11 min read
Jefferson Gonzalez
Contributor of Pragtical

Many fixes and new features like the image viewer, built-in color picker, support for drawing polygons, introduction of a canvas api and experimental live search!

Generalized RenCache

One prominent change is that the rencache source code was generalized to decouple it of the windows renderer, this allows using it in other contexts like the new canvas, which helps it perform better by leveraging the rencache feature of skipping unnecessary drawing operations.

Expanding on this subject, the rencache incorporates the following new struct with parts decoupled from renwindow:

typedef struct {
uint8_t *command_buf;
size_t command_buf_idx;
size_t command_buf_size;
unsigned cells_buf1[RENCACHE_CELLS_X * RENCACHE_CELLS_Y];
unsigned cells_buf2[RENCACHE_CELLS_X * RENCACHE_CELLS_Y];
unsigned *cells_prev;
unsigned *cells;
RenRect rect_buf[RENCACHE_CELLS_X * RENCACHE_CELLS_Y / 2];
bool resize_issue;
RenRect screen_rect;
RenRect last_clip_rect;
SDL_Window *window; /* The cache can be used for both a window or surface */
RenSurface rensurface;
#ifdef PRAGTICAL_USE_SDL_RENDERER
SDL_Renderer *renderer;
SDL_Texture *texture;
#endif
} RenCache;

Also, the rencache function interfaces now look like this:

void rencache_init(RenCache *rc);
void rencache_uninit(RenCache *rc);
void rencache_show_debug(bool enable);
void rencache_set_clip_rect(RenCache *rc, RenRect rect);
void rencache_draw_rect(RenCache *rc, RenRect rect, RenColor color, bool replace);
double rencache_draw_text(RenCache *rc, RenFont **font, const char *text, size_t len, double x, double y, RenColor color, RenTab tab);
RenRect rencache_draw_poly(RenCache *rc, RenPoint *points, int npoints, RenColor color);
void rencache_draw_canvas(RenCache *ren_cache, RenRect rect, RenCache *canvas);
void rencache_draw_pixels(RenCache *ren_cache, RenRect rect, const char* bytes, size_t len);
void rencache_invalidate(RenCache *rc);
void rencache_begin_frame(RenCache *rc);
void rencache_end_frame(RenCache *rc);
RenSurface rencache_get_surface(RenCache *rc);
void rencache_update_rects(RenCache *rc, RenRect *rects, int count);

As you may notice, this release introduces the new rencache_draw_poly and rencache_draw_canvas functions. Now lets talk about the new user facing changes!

Image Viewer

Now you don't have to leave the editor to view an image with the built-in image viewer, which leverages sdl3_image with support for basic svg rendering. The list of built-in supported image types are: bmp, cur, gif, ico, jpg, lbm, pcx, png, pnm, qoi, svg, tga, xcf xpm and xv. The supported formats that require an external library to work are: avif, jxl, webp and until we improve the custom sdl3_image meson wrapper, tiff (which doesn't actually works on macOS and Windows).

You can take a look at the new ImageView object.

Built-in Color Picker

The new built-in color picker will also assist on not having to leave the editor to pick a color :P. It allows you to pick an RGB or HEX color from any part of the editor UI and save it to the clipboard so you can use it wherever you like.

This is possible thanks to new renwindow.get_color api function:

---
---Gets the window pixel color of the specified position.
---
---@param window renwindow
---@param x number
---@param y number
---
---@return renderer.color? color
function renwindow.get_color(window, x, y) end

This release also introduces project search results syntax coloring and experimental live search support which was a nice suggestion by Amer. The live search support may cause undesired effects so use with cautious until bugs are ironed out on next releases. The plan for next releases is to also integrate it on the current file search with both the project search and file search offering an option to show them on a floating widget on the center of the screen, but for the moment enjoy the initial work!

Polygons Drawing Support

Polygons! the new renderer.draw_poly was merged from Takase work on #1857 and it leverages freetype advanced drawing capabilities. The feature was adapted to work with the generalized rencache changes in Pragtical. The api function allows to draw smooth shapes and it was also incorporated to the new canvas api.

pragtical polygons

Canvas

Meanwhile, the new canvas code is an adaptation of Guldo branch PR_canvas and it was also modified to use the new generalized rencache changes which helps get rid of those unnecessary draw calls improving its performance! Also to this api we introduced, draw_poly as image loading and saving support. We added the following additional functions to this api:

---
---Loads an image into a new canvas.
---
---@param path string
---
---@return canvas? canvas
---@return string? errmsg
function canvas.load_image(path) end

---
---Loads an svg image with the specified width and height.
---
---@param path string
---@param width integer
---@param height integer
---
---@return canvas? canvas
---@return string? errmsg
function canvas.load_svg_image(path, width, height) end

---
---Clean the canvas, content will be replaced with transparent pixels,
---or a full opaque color if the canvas is not transparent.
---
---@param color? renderer.color Optional color used to fill the surface.
function canvas:clear(color) end

---
---Draws a filled polygon, consisting of curves and points.
---The polygon is filled using the non-zero winding rule in clockwise direction.
---
---The function returns the control box of the polygon,
---which is greater than or equal to the dimensions of the rendered polygon.
---It is not guaranteed to the exact dimension of the rendered polygon.
---
---@param poly renderer.poly_object[] the lines or curves to draw, up to 65535 points.
---@param color renderer.color
---
---@return number x the X coordinate of top left corner of the control box.
---@return number y the Y coordinate of the top left corner of the control box.
---@return number w the width of the control box.
---@return number h the height of the control box.
function canvas:draw_poly(poly, color) end

---
---Explicitly render all the draw commands sent to the canvas so far
---without having to render the canvas into a window first.
---
function canvas:render() end

---
---Save the current canvas as an image.
---
---@param filename string
---@param type? "png" | "jpg" | "avif" Defaults to "png"
---@param quality? integer A number from 1 to 100 used for jpg and avif. Defaults to 100
---
---@return boolean saved
---@return string? errmsg
function canvas:save_image(filename, type, quality) end

For all the functionality of this api consult its doc file.

More Bug Fixes

Finally, this release incorporates various bug fixes and enhancements for:

  • Lua Core
  • The Build System
  • Widgets

Some of these changes and fixes are thanks to contributors like:

  • M4he who reported the contextmenu triggering on window manager resize. And also reported the Plugin Manager view stealing mouse clicks from tab bar.

Also, various upstream changes made it in with additional work from us to improve them as fixing regressions they introduced. Check the Changes Log below for more!

Downloads on GitHub.

Changes Log

New Features

  • Add a built-in color picker (#375)

    • Document new renwindow.get_color (c60ee0d9)

    • Use proper add keymap function on rootpickcolor plugin (71af13e6)

    • rootpickcolor: forgot to properly return on_mouse_pressed (2c1a6944)

  • Live refresh and coloring for projectsearch plugin (#377)

  • Image Viewer (directly added on merged canvas support) (#370)

Core Changes

  • Generalize the rendering cache system (#368)

  • Merged: Add support for drawing polygons (adapted to generalized rencache) (#369)

  • Merged: canvas (adapted to generalized rencache, added poly draw, additional image loading support and image viewer) (#370)

    • Add the option to change background mode of images (#371)

    • ImageView: keep scale at 1 if width less than view (e9c305ed)

    • ImageView: rescale svg images directly from source (#383)

Fixes

  • Fix contextmenu triggered on window manager resize (#356)

  • Update config.mouse_wheel_scroll on scale changes (#361)

  • Scale initialization fixes (#362)

  • Fix equal float comparison returning false (#363)

  • Replace settings ui scroll wheel set with on_apply (eef5ef1e)

  • Fix EmptyView AKA Welcome Screen flashing (#366)

  • Fix the statusview tooltips jumpy text (#367)

  • Fix treeview new file/folder regression (fix for inherited changes) (cb06c0fd)

  • Remove unneccesary save when loading project module (fix for inherited changes) (fe217606)

  • Fixes to threads and channels code (#376)

  • Fix inconsistency on toolbarview dest_size (#378)

  • Fix system.list_dir to work with / (sdl3 port regression) (#379)

  • Guard against null windows on draw operations (#381)

  • Fix support for larger posix process reading (fix for inherited changes and real cause of PGO CI failures) (73b60926)

  • TreeView: round size.x on move_towards (#384)

Enhancements

  • Add option to show repainted areas (#358)

  • Better out of box smoothness and responsiveness (#357)

Widgets

  • Properly return from updates and draws (8743ec6f)

  • keep list properly resized on selectbox (abad16b2)

  • Ensure draw is called after a proper update (dc3bdd3a)

  • SearchReplaceList: allow syntax highlighting on search results (623b88be)

  • TextBox: simplified placeholder logic (e8ffacbf)

  • SearchReplaceList: correction to skip draw logic (ba3bde34)

Build System

  • Fix pgo stresser getting stalled on CI (the endeavour) (b044ce4c)

    • Other changes to prevent pgo from stalling (64472f48)

    • Disable system sleep and poll_event to try fix CI stall (a8597926)

    • Timeout pgo stress to prevent stall (eac0b44b)

    • Remove ci lua system overrides and disable pgo sqlite download (f05047a0)

    • Restore pgo sqlite download stress (86b89ae8)

    • Real cause of PGO stalls renferenced on fixes section (73b60926)

  • Fixes to rolling and release CI linux build (#372)

  • Disable uchardet tests compilation (#374)

  • Update sdl to v3.2.28 (#373)

  • Update macOS x86 runner (66c75376)

  • Initial support for muon build (#380)

  • Fix luajit crosscompilation for muon (#382)

  • PPM subproject: download git submodules on demand (#385)

Miscelaneous

  • Keep icon svg segments on repo (16539334)

  • GIT ignore subprojects/.wraplock (b5017edc)

  • Remove leftover print statement (from inherited changes) (2b1c750a)

Lite XL Inherited Changes (with corrections and improvements)

  • Fixed timeout in process:wait; comparison (5a36b3f0)

  • system: update window scale on scale changes (#2081)

  • Improve folder drag-and-drop experience (#1830)

  • Resolved some type-complaints that are detected by LuaLS (#2120)

  • Backporting ancient fix to allow for large amounts of reading. (#1547)

  • Update renwindow.lua (#2150)

  • Adjusted parameter order and docs for renwindow create. (#2155)

  • Fix wrong suggestion when creating file or folder in treeview (#2183)

  • fix(doc): don't modify doc with empty clipboard paste (#2185)

  • fix(treeview): avoid crashing if creating a new file errors out (#2184)

  • Rearrange Plugin Loading and SDL Initialization (#1881) (#1881)

  • Added generic storage system and use on workspace plugin (#1929)

  • feat: add SDL file picker (#2072)

  • Allow for negative priority numbers. (7d636075)

  • fix: make get_custom_event_callback_by_name return NULL on invalid event name (#2154)

  • Added in check for the blink timer so that we don't needlessly redraw (#2053)