Skip to content

Commit

Permalink
Store alpha preserve of a layer in ORA files
Browse files Browse the repository at this point in the history
For compatibility with Krita and maybe other applications. In Drawpile,
alpha preserve is implicit depending on the blend mode, but e.g. in
Krita, it has to be enabled separately. This adds an
`alpha-preserve="true"` attribute to layers with affected blend mdoes so
that Krita can restore them properly, once the attribute is implemented
on their side.

Drawpile doesn't read the attribute, since it can't do anything with the
information, except for the special case of the Normal blend mode, which
becomes Recolor when alpha preserve is enabled. Normally this is saved
as a separate blend mode, but since it's a valid way to represent it, we
handle it too.
  • Loading branch information
askmeaboutlo0m committed Aug 24, 2023
1 parent 4f72944 commit 372114f
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 20 deletions.
1 change: 1 addition & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ Unreleased Version 2.2.0-pre
* Fix: Make the flipbook remember your last crop, frame range and playback speed for the current window. Thanks Ben for finding.
* Fix: Don't mark guests as registered. Thanks to xxxx for reporting.
* Fix: Allow assigning a shortcut to open the Layouts dialog (F9 by default) and to the entries in the Help menu (nothing by default.)
* Feature: Store alpha preserve state of layers in ORA files for better Krita compatibility.

2023-07-31 Version 2.2.0-beta.6
* Fix: Don't forget account password when entering a wrong session password.
Expand Down
11 changes: 11 additions & 0 deletions src/drawdance/libengine/dpengine/load.c
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,17 @@ static DP_TransientLayerProps *ora_make_layer_props(DP_XmlElement *element,
DP_BlendMode blend_mode = DP_blend_mode_by_svg_name(
DP_xml_element_attribute(element, NULL, "composite-op"),
DP_BLEND_MODE_NORMAL);

// Normal with alpha preserve is Recolor. Drawpile doesn't save it this way,
// but it's a valid way to represent it, so we handle it.
if (blend_mode == DP_BLEND_MODE_NORMAL) {
const char *alpha_preserve =
DP_xml_element_attribute(element, NULL, "alpha-preserve");
if (DP_str_equal_lowercase(alpha_preserve, "true")) {
blend_mode = DP_BLEND_MODE_RECOLOR;
}
}

DP_transient_layer_props_blend_mode_set(tlp, (int)blend_mode);

const char *censored =
Expand Down
9 changes: 9 additions & 0 deletions src/drawdance/libengine/dpengine/save.c
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,15 @@ static void ora_write_layer_props_xml(DP_SaveOraContext *c, DP_Output *output,
DP_blend_mode_svg_name(blend_mode));
}

// Drawpile doesn't itself need the alpha preserve property, since its alpha
// preserve behavior depends on the blend mode, but other software cares.
// The Recolor blend mode is saved as src-atop, which is alpha-preserving
// per its definition, so it doesn't get the extra attribute.
if (DP_blend_mode_preserves_alpha(blend_mode)
&& blend_mode != DP_BLEND_MODE_RECOLOR) {
DP_OUTPUT_PRINT_LITERAL(output, " alpha-preserve=\"true\"");
}

if (DP_layer_props_censored(lp)) {
DP_OUTPUT_PRINT_LITERAL(output, " drawpile:censored=\"true\"");
}
Expand Down
46 changes: 26 additions & 20 deletions src/drawdance/libmsg/dpmsg/blend_mode.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#define DECREASE_OPACITY (1 << 2)
#define INCREASE_OPACITY (1 << 3)
#define BLEND_BLANK (1 << 4)
#define PRESERVES_ALPHA (1 << 5)

// The Krita name for the linear light blend mode contains a space, which isn't
// supported in draw dabs messages, since they already use the curly brace body
Expand Down Expand Up @@ -65,63 +66,63 @@ static const DP_BlendModeAttributes mode_attributes[DP_BLEND_MODE_COUNT] = {
},
[DP_BLEND_MODE_MULTIPLY] =
{
LAYER | BRUSH,
LAYER | BRUSH | PRESERVES_ALPHA,
"DP_BLEND_MODE_MULTIPLY",
"svg:multiply",
"Multiply",
},
[DP_BLEND_MODE_DIVIDE] =
{
LAYER | BRUSH,
LAYER | BRUSH | PRESERVES_ALPHA,
"DP_BLEND_MODE_DIVIDE",
"-dp-divide",
"Divide",
},
[DP_BLEND_MODE_BURN] =
{
LAYER | BRUSH,
LAYER | BRUSH | PRESERVES_ALPHA,
"DP_BLEND_MODE_BURN",
"svg:color-burn",
"Burn",
},
[DP_BLEND_MODE_DODGE] =
{
LAYER | BRUSH,
LAYER | BRUSH | PRESERVES_ALPHA,
"DP_BLEND_MODE_DODGE",
"svg:color-dodge",
"Dodge",
},
[DP_BLEND_MODE_DARKEN] =
{
LAYER | BRUSH,
LAYER | BRUSH | PRESERVES_ALPHA,
"DP_BLEND_MODE_DARKEN",
"svg:darken",
"Darken",
},
[DP_BLEND_MODE_LIGHTEN] =
{
LAYER | BRUSH,
LAYER | BRUSH | PRESERVES_ALPHA,
"DP_BLEND_MODE_LIGHTEN",
"svg:lighten",
"Lighten",
},
[DP_BLEND_MODE_SUBTRACT] =
{
LAYER | BRUSH,
LAYER | BRUSH | PRESERVES_ALPHA,
"DP_BLEND_MODE_SUBTRACT",
"-dp-minus",
"Subtract",
},
[DP_BLEND_MODE_ADD] =
{
LAYER | BRUSH,
LAYER | BRUSH | PRESERVES_ALPHA,
"DP_BLEND_MODE_ADD",
"svg:plus",
"Add",
},
[DP_BLEND_MODE_RECOLOR] =
{
LAYER | BRUSH,
LAYER | BRUSH | PRESERVES_ALPHA,
"DP_BLEND_MODE_RECOLOR",
"svg:src-atop",
"Recolor",
Expand All @@ -142,7 +143,7 @@ static const DP_BlendModeAttributes mode_attributes[DP_BLEND_MODE_COUNT] = {
},
[DP_BLEND_MODE_SCREEN] =
{
LAYER | BRUSH,
LAYER | BRUSH | PRESERVES_ALPHA,
"DP_BLEND_MODE_SCREEN",
"svg:screen",
"Screen",
Expand All @@ -156,70 +157,70 @@ static const DP_BlendModeAttributes mode_attributes[DP_BLEND_MODE_COUNT] = {
},
[DP_BLEND_MODE_LUMINOSITY_SHINE_SAI] =
{
LAYER | BRUSH,
LAYER | BRUSH | PRESERVES_ALPHA,
"DP_BLEND_MODE_LUMINOSITY_SHINE_SAI",
"krita:luminosity_sai",
"Luminosity/Shine (SAI)",
},
[DP_BLEND_MODE_OVERLAY] =
{
LAYER | BRUSH,
LAYER | BRUSH | PRESERVES_ALPHA,
"DP_BLEND_MODE_OVERLAY",
"svg:overlay",
"Overlay",
},
[DP_BLEND_MODE_HARD_LIGHT] =
{
LAYER | BRUSH,
LAYER | BRUSH | PRESERVES_ALPHA,
"DP_BLEND_MODE_HARD_LIGHT",
"svg:hard-light",
"Hard Light",
},
[DP_BLEND_MODE_SOFT_LIGHT] =
{
LAYER | BRUSH,
LAYER | BRUSH | PRESERVES_ALPHA,
"DP_BLEND_MODE_SOFT_LIGHT",
"svg:soft-light",
"Soft Light",
},
[DP_BLEND_MODE_LINEAR_BURN] =
{
LAYER | BRUSH,
LAYER | BRUSH | PRESERVES_ALPHA,
"DP_BLEND_MODE_LINEAR_BURN",
"krita:linear_burn",
"Linear Burn",
},
[DP_BLEND_MODE_LINEAR_LIGHT] =
{
LAYER | BRUSH,
LAYER | BRUSH | PRESERVES_ALPHA,
"DP_BLEND_MODE_LINEAR_LIGHT",
"krita:linear light",
"Linear Light",
},
[DP_BLEND_MODE_HUE] =
{
LAYER | BRUSH,
LAYER | BRUSH | PRESERVES_ALPHA,
"DP_BLEND_MODE_HUE",
"svg:hue",
"Hue",
},
[DP_BLEND_MODE_SATURATION] =
{
LAYER | BRUSH,
LAYER | BRUSH | PRESERVES_ALPHA,
"DP_BLEND_MODE_SATURATION",
"svg:saturation",
"Saturation",
},
[DP_BLEND_MODE_LUMINOSITY] =
{
LAYER | BRUSH,
LAYER | BRUSH | PRESERVES_ALPHA,
"DP_BLEND_MODE_LUMINOSITY",
"svg:luminosity",
"Luminosity",
},
[DP_BLEND_MODE_COLOR] =
{
LAYER | BRUSH,
LAYER | BRUSH | PRESERVES_ALPHA,
"DP_BLEND_MODE_COLOR",
"svg:color",
"Color",
Expand Down Expand Up @@ -310,6 +311,11 @@ bool DP_blend_mode_blend_blank(int blend_mode)
return get_attributes(blend_mode)->flags & BLEND_BLANK;
}

bool DP_blend_mode_preserves_alpha(int blend_mode)
{
return get_attributes(blend_mode)->flags & PRESERVES_ALPHA;
}

DP_BlendMode DP_blend_mode_by_svg_name(const char *svg_name,
DP_BlendMode not_found_value)
{
Expand Down
2 changes: 2 additions & 0 deletions src/drawdance/libmsg/dpmsg/blend_mode.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ bool DP_blend_mode_can_decrease_opacity(int blend_mode);

bool DP_blend_mode_blend_blank(int blend_mode);

bool DP_blend_mode_preserves_alpha(int blend_mode);

DP_BlendMode DP_blend_mode_by_svg_name(const char *svg_name,
DP_BlendMode not_found_value);

Expand Down

0 comments on commit 372114f

Please sign in to comment.