Closed jfcherng closed 3 years ago
I'm happy to add your custom color class.
Can you update the docstrings to silence the linter issues?
I picked ahex for the alpha hex colors mainly because it is kind of a generic form that is used in multiple implementations. But this form seems very specific to ASS. Maybe give the setting a more descriptive name like ass
or ssa_ass
. Something that kind of describes their main use as this is a very specific color style to ASS it seems (which I guess is from SSA v4 -- based on what I read) . I'd also rename the file using a similar name.
I'd also just rename the color class ColorAlphaHex
object something like ColorASS
or ColorSsaAss
. Maybe something like that.
Overall, I think it looks fine. I haven't tested it yet, but I'm assuming you have, but I'll take a closer look and test before I merge.
I think with this, ColorHelper should support ASS out of the box. That acronym though 🙃.
I updated the original post, just call the file something like ass
or ssa_ass
should be fine along with the custom name in the settings.
I've tested pull, making the suggested changes locally and it seems to work well. After changes are made, I'll be happy to pull it in.
diff --git a/color_helper.sublime-settings b/color_helper.sublime-settings
index dab27af..43cb521 100755
--- a/color_helper.sublime-settings
+++ b/color_helper.sublime-settings
@@ -211,6 +211,14 @@
"output": [
{"space": "srgb", "format": {"hex": true}}
]
+ },
+ // for color codes like `&HAABBGGRR` and `&HBBGGRR`
+ "ass_abgr": {
+ "class": "ColorHelper.custom.ass_abgr.ColorAssABGR",
+ "filters": ["srgb"],
+ "output": [
+ {"space": "srgb", "format": {"upper": true}}
+ ]
}
},
@@ -379,6 +387,14 @@
"constant.color.w3c-standard-color-name.css",
"meta.property-value.css"
]
+ },
+ {
+ // ASS ( based on: https://packagecontrol.io/packages/Advanced%20Substation%20Alpha%20(ASS) )
+ "name": "ASS",
+ "base_scopes": ["text.ass"],
+ "scanning": ["constant.other.color"],
+ "color_class": "ass_abgr",
+ "color_trigger": "(?i)&h"
}
],
diff --git a/custom/ass_abgr.py b/custom/ass_abgr.py
new file mode 100644
index 0000000..1d620e7
--- /dev/null
+++ b/custom/ass_abgr.py
@@ -0,0 +1,85 @@
+"""Custom color that looks for colors of format `&HAABBGGRR` as `#AARRGGBB`."""
+from ColorHelper.lib.coloraide import Color
+from ColorHelper.lib.coloraide import util
+from ColorHelper.lib.coloraide.spaces import _parse
+from ColorHelper.lib.coloraide.spaces.srgb.css import SRGB
+import copy
+import re
+
+
+class AssABGR(SRGB):
+ """ASS `ABGR` color space."""
+
+ MATCH = re.compile(r"&H([0-9a-fA-f]{8}|[0-9a-fA-f]{6})\b")
+
+ @classmethod
+ def match(cls, string: str, start: int = 0, fullmatch: bool = True):
+ """Match a color string."""
+
+ m = cls.MATCH.match(string, start)
+ if m is not None and (not fullmatch or m.end(0) == len(string)):
+ return cls.split_channels(m.group(1)), m.end(0)
+ return None, None
+
+ @classmethod
+ def translate_channel(cls, channel: int, value: str):
+ """Translate channel string."""
+
+ if -1 <= channel <= 2:
+ return _parse.norm_hex_channel(value)
+
+ @classmethod
+ def split_channels(cls, color: str):
+ """Split string into the appropriate channels."""
+
+ # convert `BBGGRR` to `AABBGGRR`
+ if len(color) == 6:
+ color = "00" + color
+ # deal with `AABBGGRR`
+ if len(color) == 8:
+ return cls.null_adjust(
+ (
+ cls.translate_channel(0, "#" + color[6:]), # RR
+ cls.translate_channel(1, "#" + color[4:6]), # GG
+ cls.translate_channel(2, "#" + color[2:4]), # BB
+ ),
+ 1 - cls.translate_channel(-1, "#" + color[:2]), # AA
+ )
+
+ raise RuntimeError("Something is wrong in code logics.")
+
+ def to_string(self, parent, *, options=None, alpha=None, precision=None, fit=True, **kwargs):
+ """Convert color to `&HAABBGGRR`."""
+
+ options = kwargs
+ a = util.no_nan(self.alpha)
+ show_alpha = alpha is not False and (alpha is True or a < 1.0)
+
+ template = "&H{:02x}{:02x}{:02x}{:02x}" if show_alpha else "&H{:02x}{:02x}{:02x}"
+ if options.get("upper"):
+ template = template.upper()
+
+ # Always fit hex
+ method = None if not isinstance(fit, str) else fit
+ coords = util.no_nan(parent.fit(method=method).coords())
+ if show_alpha:
+ value = template.format(
+ int(util.round_half_up(a * 255.0)),
+ int(util.round_half_up(coords[2] * 255.0)),
+ int(util.round_half_up(coords[1] * 255.0)),
+ int(util.round_half_up(coords[0] * 255.0)),
+ )
+ else:
+ value = template.format(
+ int(util.round_half_up(coords[2] * 255.0)),
+ int(util.round_half_up(coords[1] * 255.0)),
+ int(util.round_half_up(coords[0] * 255.0)),
+ )
+ return value
+
+
+class ColorAssABGR(Color):
+ """Color class for ASS `ABGR` colors."""
+
+ CS_MAP = copy.copy(Color.CS_MAP)
+ CS_MAP["srgb"] = AssABGR
@jfcherng, I basically had it done, so I've merged the changes with your name attached. It will be included in tag st-3.6.0. I may tag it today as I don't really have anything else in the queue right now for ColorHelper tasks.
Thanks!
Thanks!
Just as an aside, the ASS format (or rather the renderer that became the reference implementation) has terrible and very lax parsing, meaning that override blocks a la {\1cffffff}
are also valid color specifications (iirc) that the check for (?i)&h
will miss, but that's very much discouraged to begin with. The "correct" format for that would be {\1c&Hffffff&}
.
@FichteFoll, I'm more than happy to accept any changes to ensure that all proper forms are accepted. Internally, they all get serialized to color(srgb r g b / a)
. It is more controlling what is read in and what is exported out. Obviously, I would suggest the output format to probably follow the widely accepted format, but I'll let you experts in ASS work out what you most prefer.
This may work for identifying all colors as an input:
diff --git a/color_helper.sublime-settings b/color_helper.sublime-settings
index 43cb521..169874c 100755
--- a/color_helper.sublime-settings
+++ b/color_helper.sublime-settings
@@ -394,7 +394,7 @@
"base_scopes": ["text.ass"],
"scanning": ["constant.other.color"],
"color_class": "ass_abgr",
- "color_trigger": "(?i)&h"
+ "color_trigger": "(?i)(?:&H|(?<=\\\\c)[a-f0-9])"
}
],
diff --git a/custom/ass_abgr.py b/custom/ass_abgr.py
index 1d620e7..5983dbe 100644
--- a/custom/ass_abgr.py
+++ b/custom/ass_abgr.py
@@ -10,7 +10,7 @@ import re
class AssABGR(SRGB):
"""ASS `ABGR` color space."""
- MATCH = re.compile(r"&H([0-9a-fA-f]{8}|[0-9a-fA-f]{6})\b")
+ MATCH = re.compile(r"(?:&H)?([0-9a-fA-f]{8}|[0-9a-fA-f]{6})\b")
@classmethod
def match(cls, string: str, start: int = 0, fullmatch: bool = True):
The Goal
I would like to add support for color codes in ASS/SSA subtitles. The color codes are in the forms of
&HAABBGGRR
or&HBBGGRR
such as&H80FF0000
or&HFF0000
. Note that by default alpha=00
and it means opaque.Currently, it's done in the https://packagecontrol.io/packages/Advanced%20Substation%20Alpha%20(ASS) side. But it will require users to modify their ColorHelper's settings so it would be better if it can be moved to ColorHelper.
I am willing to change the naming of files and classes. (I don't know how to name them properly actually.)
References