38 if(errors->len > 0) g_string_append(errors,
"; ");
39 g_string_append(errors, message);
73 const int listed_count = count;
74 for(
int i = 0;
i < count;
i++)
97 g->stroke.stroke_sample_count = 0;
98 g->stroke.stroke_event_index = 0;
99 g->stroke.last_dab_valid =
FALSE;
112 if(
g->process.cache_imgid !=
key->imgid ||
g->process.base_patch.width !=
key->layer_width
113 ||
g->process.base_patch.height !=
key->layer_height)
123 const char *target_name =
key->layer_name ?
key->layer_name :
"";
124 if(target_name[0] !=
'\0' ||
g->process.cache_layer_name[0] !=
'\0')
return !g_strcmp0(
g->process.cache_layer_name, target_name);
126 if(
key->layer_order >= 0 &&
g->process.cache_layer_order >= 0)
127 return g->process.cache_layer_order ==
key->layer_order;
145 GMainContext *
const ui_ctx = g_main_context_default();
146 const gboolean ui_thread = ui_ctx && g_main_context_is_owner(ui_ctx);
158 g->process.cache_valid =
FALSE;
159 g->process.cache_dirty =
FALSE;
161 g->process.cache_imgid = -1;
162 g->process.cache_layer_name[0] =
'\0';
163 g->process.cache_layer_order = -1;
176 GString *errors = g_string_new(NULL);
180 current_profile,
sizeof(current_profile));
181 if(!have_current_profile)
191 g_string_free(errors,
TRUE);
199 g_string_free(errors,
TRUE);
210 "drawlayer sidecar cache", &created))
214 g->process.cache_valid =
FALSE;
216 g_string_free(errors,
TRUE);
220 "drawlayer stroke mask"))
224 g->process.cache_valid =
FALSE;
227 g_string_free(errors,
TRUE);
238 gboolean cache_loaded =
FALSE;
239 gboolean file_exists =
FALSE;
250 g->process.cache_valid =
FALSE;
253 g_string_free(errors,
TRUE);
257 if(created) file_exists = g_file_test(path, G_FILE_TEST_EXISTS);
259 if(created && !file_exists)
272 if(pending_new_layer)
278 g_snprintf(
g->session.missing_layer_error,
sizeof(
g->session.missing_layer_error),
279 _(
"The drawing layer \"%s\" was not found in the sidecar TIFF."),
287 g->process.cache_valid =
FALSE;
288 g->process.cache_dirty =
FALSE;
290 g->process.cache_imgid = -1;
291 g->process.cache_layer_name[0] =
'\0';
292 g->process.cache_layer_order = -1;
306 if(
g)
g->session.missing_layer_error[0] =
'\0';
316 .
x =
g->process.base_patch.x,
317 .y =
g->process.base_patch.y,
318 .width =
g->process.base_patch.width,
319 .height =
g->process.base_patch.height,
320 .pixels =
g->process.base_patch.pixels,
322 const gboolean loaded
340 g->process.cache_valid =
TRUE;
341 g->process.cache_dirty =
FALSE;
343 g->process.cache_imgid = imgid;
344 g_strlcpy(
g->process.cache_layer_name,
params->
layer_name,
sizeof(
g->process.cache_layer_name));
353 g->process.cache_valid =
FALSE;
354 g->process.cache_dirty =
FALSE;
360 g_string_free(errors,
TRUE);
361 return ok || !cache_loaded;
374 const int32_t flush_imgid = (
g->process.cache_imgid > 0) ?
g->process.cache_imgid : self->
dev->
image_storage.
id;
375 if(flush_imgid <= 0)
return TRUE;
378 int final_order =
g->process.cache_layer_order;
382 .
x =
g->process.base_patch.x,
383 .y =
g->process.base_patch.y,
384 .width =
g->process.base_patch.width,
385 .height =
g->process.base_patch.height,
386 .pixels =
g->process.base_patch.pixels,
390 g->process.base_patch.
width,
g->process.base_patch.height,
FALSE, &final_order);
392 if(!ok)
return FALSE;
394 g->process.cache_layer_order = final_order;
395 g->process.cache_dirty =
FALSE;
401 if(!g_strcmp0(mutable_params->
layer_name,
g->process.cache_layer_name)) mutable_params->
layer_order = final_order;
417 float wx0 = 0.0f, wy0 = 0.0f, wx1 = 0.0f, wy1 = 0.0f;
419 view.layer_y1, &wx0, &wy0, &wx1, &wy1))
424 .nw = { (int)floorf(
view.layer_x0), (int)floorf(
view.layer_y0) },
425 .se = { (int)ceilf(
view.layer_x1), (int)ceilf(
view.layer_y1) },
429 .nw = { (int)floorf(wx0), (int)floorf(wy0) },
430 .se = { (int)ceilf(wx1), (int)ceilf(wy1) },
433 const gboolean same_view = (memcmp(&
g->session.live_patch, &
view.patch,
sizeof(
view.patch)) == 0
434 && memcmp(&
g->session.live_view_rect, &live_view_rect,
sizeof(live_view_rect)) == 0
435 && memcmp(&
g->session.preview_rect, &preview_rect,
sizeof(preview_rect)) == 0);
445 g->session.live_patch =
view.patch;
446 g->session.live_view_rect = live_view_rect;
447 g->session.preview_rect = preview_rect;
465 if(was_realtime !=
state)
void dt_atomic_set_int(dt_atomic_int *var, int value)
int dt_bauhaus_combobox_length(GtkWidget *widget)
void dt_bauhaus_combobox_set(GtkWidget *widget, const int pos)
void dt_bauhaus_combobox_remove_at(GtkWidget *widget, int pos)
void dt_bauhaus_combobox_add(GtkWidget *widget, const char *text)
void dt_control_log(const char *msg,...)
gboolean dt_drawlayer_compute_view_patch(dt_iop_module_t *self, const float padding, drawlayer_view_patch_info_t *view)
gboolean dt_drawlayer_layer_bounds_to_widget_bounds(dt_iop_module_t *self, const float x0, const float y0, const float x1, const float y1, float *left, float *top, float *right, float *bottom)
float dt_drawlayer_current_live_padding(dt_iop_module_t *self)
dt_dev_image_geometry_t dt_dev_geometry_snapshot(const dt_develop_t *dev)
void dt_dev_transient_params_clear(dt_iop_module_t *module)
Drop the transient slot if it belongs to module.
#define dt_dev_pixelpipe_resync_history_main(dev)
float dt_dev_viewport_center_y(const dt_develop_t *dev)
float dt_dev_viewport_center_x(const dt_develop_t *dev)
float dt_dev_viewport_scaling(const dt_develop_t *dev)
GtkWidget * geometry
its size, under the preview
GHashTable * names
GtkWidget* -> the name the application knows it by.
GtkWidget * view
the tree view
void dt_drawlayer_sanitize_params(dt_iop_module_t *self, dt_iop_drawlayer_params_t *params)
void dt_drawlayer_release_all_base_patch_extra_refs(dt_iop_drawlayer_gui_data_t *g)
int64_t dt_drawlayer_sidecar_timestamp_from_path(const char *path)
gboolean dt_drawlayer_current_work_profile_key(dt_iop_module_t *self, GList *iop_list, dt_dev_pixelpipe_t *pipe, char *key, const size_t key_size)
void dt_drawlayer_retain_base_patch_loaded_ref(dt_iop_drawlayer_gui_data_t *g)
void dt_drawlayer_refresh_layer_widgets(dt_iop_module_t *self)
gboolean dt_drawlayer_layer_name_non_empty(const char *name)
gboolean dt_drawlayer_rekey_shared_base_patch(drawlayer_patch_t *patch, const int32_t imgid, const dt_iop_drawlayer_params_t *params)
static dt_iop_gui_data_t * dt_iop_gui_data(const struct dt_iop_module_t *m)
The module's GUI data blob, NULL-safe for headless callers: IOP process() implementations read it for...
gboolean dt_drawlayer_io_find_layer(const char *path, const char *target_name, const int target_order, dt_drawlayer_io_layer_info_t *info)
Find target layer metadata in sidecar TIFF.
gboolean dt_drawlayer_io_sidecar_path(const int32_t imgid, char *path, const size_t path_size)
Build absolute sidecar path from image id.
gboolean dt_drawlayer_io_list_layer_names(const char *path, char ***names, int *count)
List all TIFF layer page names.
gboolean dt_drawlayer_io_load_layer(const char *path, const char *target_name, const int target_order, const int layer_width, const int layer_height, dt_drawlayer_io_patch_t *patch)
Load one sidecar layer patch into float RGBA destination patch.
gboolean dt_drawlayer_io_store_layer(const char *path, const char *target_name, const int target_order, const char *work_profile, const dt_drawlayer_io_patch_t *patch, const int layer_width, const int layer_height, const gboolean delete_target, int *final_order)
Store/update/delete one layer entry in sidecar TIFF.
void dt_drawlayer_io_free_layer_names(char ***names, int *count)
Free array returned by dt_drawlayer_io_list_layer_names.
TIFF sidecar I/O API for drawlayer layers.
Patch/cache helpers for drawlayer process and preview buffers.
void dt_drawlayer_paint_runtime_state_reset(dt_drawlayer_damaged_rect_t *state)
Reset stroke-damage accumulator to empty/invalid.
gboolean dt_drawlayer_flush_layer_cache(dt_iop_module_t *self)
gboolean dt_drawlayer_sync_widget_cache(dt_iop_module_t *self)
void dt_drawlayer_layers_log_errors(GString *errors)
static gboolean _layer_cache_matches(const dt_iop_drawlayer_gui_data_t *g, const drawlayer_layer_cache_key_t *key)
void dt_drawlayer_set_pipeline_realtime_mode(dt_iop_module_t *self, const gboolean state)
void dt_drawlayer_layers_populate_list(dt_iop_module_t *self)
static gboolean _ensure_widget_cache(dt_iop_module_t *self)
void dt_drawlayer_layers_reset_stroke_session(dt_iop_drawlayer_gui_data_t *g)
void dt_drawlayer_layers_append_error(GString *errors, const char *message)
gboolean dt_drawlayer_ensure_layer_cache(dt_iop_module_t *self)
The drawlayer's layer store: the layer cache and its sidecar synchronisation.
static const dt_iop_drawlayer_params_t * params
static const dt_dev_pixelpipe_t const dt_dev_pixelpipe_iop_t int int * layer_height
static const dt_dev_pixelpipe_t const dt_dev_pixelpipe_iop_t int * layer_width
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
#define DT_PATH_MAX
Buffer size for a filesystem path anywhere in Ansel.
gboolean dt_dev_pixelpipe_get_realtime(const dt_dev_pixelpipe_t *pipe)
void dt_dev_pixelpipe_set_realtime(dt_dev_pixelpipe_t *pipe, gboolean state)
void dt_drawlayer_process_state_reset_stroke(dt_drawlayer_process_state_t *state)
void dt_drawlayer_process_state_invalidate(dt_drawlayer_process_state_t *state)
Private runtime state/helpers shared by drawlayer module entrypoints.
void dt_drawlayer_cache_patch_wrunlock(const dt_drawlayer_cache_patch_t *patch)
Release write lock on shared patch cache entry.
void dt_drawlayer_cache_patch_wrlock(const dt_drawlayer_cache_patch_t *patch)
Acquire write lock on shared patch cache entry.
void dt_drawlayer_cache_patch_clear(dt_drawlayer_cache_patch_t *patch, const char *external_alloc_name)
Release patch storage and reset patch metadata.
gboolean dt_drawlayer_cache_ensure_mask_buffer(dt_drawlayer_cache_patch_t *mask, const int width, const int height, const char *name)
Ensure a float stroke-mask buffer exists and matches the requested size.
gboolean dt_drawlayer_cache_patch_alloc_shared(dt_drawlayer_cache_patch_t *patch, const uint64_t hash, const size_t pixel_count, const int width, const int height, const char *name, int *created_out)
Allocate patch storage from shared pixel cache entry.
void dt_drawlayer_cache_patch_rdlock(const dt_drawlayer_cache_patch_t *patch)
Acquire read lock on shared patch cache entry.
void dt_drawlayer_cache_patch_rdunlock(const dt_drawlayer_cache_patch_t *patch)
Release read lock on shared patch cache entry.
void dt_drawlayer_cache_clear_transparent_float(float *pixels, const size_t pixel_count)
Fill float RGBA buffer with transparent black.
#define DRAWLAYER_PROFILE_SIZE
const float uint32_t state[4]
What one sidecar directory scan found about a layer.
char work_profile[DRAWLAYER_PROFILE_SIZE]
char name[DRAWLAYER_NAME_SIZE]
Objective facts about the image a dev is working on.
struct dt_dev_pixelpipe_t * preview_pipe
struct dt_dev_pixelpipe_t * pipe
Integer axis-aligned rectangle in buffer coordinates.
Metadata returned when probing one layer directory in sidecar TIFF.
Float RGBA patch used by drawlayer I/O routines.
int64_t sidecar_timestamp
struct dt_develop_t * dev
Telling the user something happened.
void dt_drawlayer_worker_reset_backend_path(dt_drawlayer_worker_t *worker)
Reset worker-owned backend damage accumulator.
gboolean dt_drawlayer_worker_wait_idle(dt_iop_module_t *self, dt_drawlayer_worker_t *rt)
Wait until worker queue is drained and not busy.
void dt_drawlayer_worker_pause(dt_iop_module_t *self, dt_drawlayer_worker_t *rt)
Pause worker processing after current callback returns.
gboolean dt_drawlayer_worker_any_active(const dt_drawlayer_worker_t *worker)
Public status query: TRUE when any worker still has pending activity.
void dt_drawlayer_worker_reset_live_publish(dt_drawlayer_worker_t *worker)
Reset worker-owned transient live-publish state.
void dt_drawlayer_worker_resume(dt_iop_module_t *self, dt_drawlayer_worker_t *rt)
Resume worker processing and wake sleeping thread.
Background stroke worker API for drawlayer realtime painting.