Colour only the selected letters of text being edited; project format version 10 (12.14d1)

This commit is contained in:
雷电芽衣 committed 2026-09-30 05:15:51 -04:00
1 parent 2fa8d9921d
commit 27a4fe8428
32 files changed
+1398 -82

No files matched your search

+26 -2
View File
@@ -102,7 +102,25 @@ QSizeF size(const QJsonValue &value)
return {width, height};
}
// Synthesized Codable skips defaults: all but the box required.
// A run's every key is required, as synthesized Codable asks.
LayerTextColorRun colorRun(const QJsonValue &value)
{
const QJsonObject object = value.toObject();
return {integer(object.value("location")), integer(object.value("length")), number(object.value("red")), number(object.value("green")),
number(object.value("blue"))};
}
std::vector<LayerTextColorRun> colorRuns(const QJsonValue &value)
{
if (!value.isArray())
refuse();
std::vector<LayerTextColorRun> runs;
for (const QJsonValue &each : value.toArray())
runs.push_back(colorRun(each));
return runs;
}
// Synthesized Codable: all required but the box and runs.
LayerTextStyle textStyle(const QJsonValue &value)
{
const QJsonObject object = value.toObject();
@@ -112,7 +130,7 @@ LayerTextStyle textStyle(const QJsonValue &value)
return {.content = string(object.value("content")), .fontName = string(object.value("fontName")), .fontSize = number(object.value("fontSize")),
.red = number(object.value("red")), .green = number(object.value("green")), .blue = number(object.value("blue")),
.alignment = *alignment, .tracking = number(object.value("tracking")), .leading = number(object.value("leading")),
.boxSize = optional(object, "boxSize", size)};
.boxSize = optional(object, "boxSize", size), .colorRuns = optional(object, "colorRuns", colorRuns)};
}
CanvasGuide guide(const QJsonValue &value)
@@ -176,6 +194,12 @@ QJsonObject encoded(const LayerTextStyle &text)
{"blue", text.blue}, {"alignment", rawValue(text.alignment)}, {"tracking", text.tracking}, {"leading", text.leading}};
if (text.boxSize)
object.insert("boxSize", QJsonArray{text.boxSize->width(), text.boxSize->height()});
if (text.colorRuns) {
QJsonArray runs;
for (const LayerTextColorRun &run : *text.colorRuns)
runs.append(QJsonObject{{"location", run.location}, {"length", run.length}, {"red", run.red}, {"green", run.green}, {"blue", run.blue}});
object.insert("colorRuns", runs);
}
return object;
}
+2 -2
View File
@@ -73,8 +73,8 @@ void validate(const ProjectManifest &manifest)
if (manifest.width < 1 || manifest.width > DocumentLimits::maxSide || manifest.height < 1 || manifest.height > DocumentLimits::maxSide || manifest.layers.size() > 10'000)
throw ProjectError(ProjectError::Kind::tooLarge);
for (const ProjectLayerRecord &layer : manifest.layers) {
// Text needs a valid style and pixels to show it.
if (layer.text && (!layer.text->isValid() || !layer.imageFile))
// Text needs a valid style, pixels; runs from 10.
if (layer.text && (!layer.text->isValid() || !layer.imageFile || (layer.text->colorRuns && manifest.version < 10)))
throw ProjectError(ProjectError::Kind::invalid);
// Version 7's adjustments hold settings, never pixels or children.
if (layer.adjustment && (manifest.version < 7 || layer.isGroup == true || layer.imageFile || !layer.adjustment->isValid()))
+1 -1
View File
@@ -51,7 +51,7 @@ QString uuidString(const QUuid &id);
struct ProjectManifest {
// Swift's current and supported: what saves write, what loads accept.
static constexpr qint64 current = 9;
static constexpr qint64 current = 10;
static constexpr std::pair<qint64, qint64> supported{1, current};
static bool supports(qint64 version) { return version >= supported.first && version <= supported.second; }
QString format = QStringLiteral("com.compositor.project");