12.2a: folders duplicate with their contents, folder opacity, format version 8, View > Snap (Compositor 1.1.5–1.1.6)

This commit is contained in:
雷电芽衣 committed 2026-09-26 18:17:14 -04:00
1 parent ee34c338d4
commit f1b2c65c1e
52 files changed
+909 -239

No files matched your search

+2 -2
View File
@@ -75,7 +75,7 @@ try {
const std::optional<LayerMask> mask = snapshot.mask(layer);
const std::optional<QImage> shown =
mask ? mask->clipImage(mask->placement, layer.transform, pixels.width(), pixels.height()) : std::nullopt;
const double opacity = layer.opacity.value_or(1);
const double opacity = layer.effectiveOpacity(records);
const LayerBlendMode mode = layer.blendMode.value_or(LayerBlendMode::normal);
// With effects the mask is in their image already.
if (const auto effects = LayerEffectsRenderer::cached(pixels, shown, layer.effects)) {
@@ -87,7 +87,7 @@ try {
{.opacity = opacity, .blendMode = mode, .mask = shown.value_or(QImage()), .clip = clip});
});
live.adjustment = [&](QUuid id) { return records.contains(id) ? records.at(id).adjustment : std::nullopt; };
live.adjustmentOpacity = [&](QUuid id) { return records.at(id).opacity.value_or(1); };
live.adjustmentOpacity = [&](QUuid id) { return records.at(id).effectiveOpacity(records); };
live.adjustmentClip = [&](QUuid id, const QPainter &context, QImage &coverage) {
const ProjectLayerRecord &layer = records.at(id);
const std::optional<LayerMask> mask = snapshot.mask(layer);
+7 -5
View File
@@ -42,7 +42,7 @@ void validate(const ProjectManifest &manifest)
{
if (manifest.format != QLatin1String("com.compositor.project"))
throw ProjectError(ProjectError::Kind::invalid);
if (manifest.version < 1 || manifest.version > 7)
if (manifest.version < 1 || manifest.version > 8)
throw ProjectError::unsupportedVersion(manifest.version);
if (manifest.colorSpace != QLatin1String("sRGB"))
throw ProjectError(ProjectError::Kind::invalid);
@@ -64,9 +64,11 @@ void validate(const ProjectManifest &manifest)
|| (manifest.version >= (group ? 6 : 4) && *layer.maskFile == uuidString(layer.id) + QLatin1String(".mask.png"));
const bool placementAllowed = !layer.maskPlacement || (layer.maskPlacement->isValid() && layer.maskFile);
const double opacity = layer.opacity.value_or(1);
const bool plain = opacity == 1 && layer.blendMode.value_or(LayerBlendMode::normal) == LayerBlendMode::normal;
const bool normal = layer.blendMode.value_or(LayerBlendMode::normal) == LayerBlendMode::normal;
const bool plain = opacity == 1 && normal;
// Folders dim from version 8; they always pass through.
if (!maskAllowed || (layer.maskEnabled && !layer.maskFile) || !placementAllowed || !std::isfinite(opacity) || opacity < 0
|| opacity > 1 || (manifest.version < 3 && !plain) || (group && !plain))
|| opacity > 1 || (manifest.version < 3 && !plain) || (group && !(normal && (manifest.version >= 8 || opacity == 1))))
throw ProjectError(ProjectError::Kind::invalid);
}
LayerHierarchy::validate(manifest.layers);
@@ -228,7 +230,7 @@ ProjectError::ProjectError(Kind kind) : ProjectError(kind, std::nullopt, descrip
ProjectError ProjectError::unsupportedVersion(qint64 version)
{
return ProjectError(Kind::version, version,
QStringLiteral("This project uses format version %1. This app supports versions 1–7.").arg(version));
QStringLiteral("This project uses format version %1. This app supports versions 1–8.").arg(version));
}
ProjectError::ProjectError(Kind kind, std::optional<qint64> version, const QString &description)
@@ -304,7 +306,7 @@ ProjectSnapshot ProjectStore::load(const QString &path)
const auto [format, version] = ProjectManifest::header(metadata);
if (format != QLatin1String("com.compositor.project"))
throw ProjectError(ProjectError::Kind::invalid);
if (version < 1 || version > 7)
if (version < 1 || version > 8)
throw ProjectError::unsupportedVersion(version);
const ProjectManifest manifest = ProjectManifest::decoded(metadata);
validate(manifest);
+4 -1
View File
@@ -40,6 +40,9 @@ struct ProjectLayerRecord {
// What the layer draws round itself; its pixels stay.
std::optional<LayerEffects> effects = std::nullopt;
std::optional<LayerTextStyle> text = std::nullopt;
// Drawn opacity, folders included; defined in LayerGroups.cpp.
double effectiveOpacity(const std::map<QUuid, ProjectLayerRecord> &byID) const;
};
// A UUID as Swift writes it: upper case, no braces.
@@ -48,7 +51,7 @@ QString uuidString(const QUuid &id);
struct ProjectManifest {
QString format = QStringLiteral("com.compositor.project");
// Swift's Int: a wild number must reach validation whole.
qint64 version = 7;
qint64 version = 8;
QString colorSpace = QStringLiteral("sRGB");
// Version-1 projects carry none: 72 pixels per inch.
std::optional<double> resolution = std::nullopt;