def get_color_at_x(self, x): """ Returns the color at any position x(between 0 and 1) https://github.com/synfig/synfig/blob/ae11655a9bba068543be7a5df9090958579de78e/synfig-core/src/synfig/gradient.cpp#L178 Args: x (float) : position at which value of color is needed Returns: (common.Color.Color) : color at position x """ if len(self.colors) == 0: return Color() if len(self.colors) == 1 or math.isnan(x): return self.reverse_gamma(self.colors[0][1]) # point is outside of gradient if x <= self.colors[0][0]: return self.reverse_gamma(self.colors[0][1]) if x >= self.colors[-1][0]: return self.reverse_gamma(self.colors[-1][1]) # upper bound i = self.upper_bound(self.colors, x, 0, len(self.colors)) # considering i stores the upper bound j = i i = i - 1 d = self.colors[j][0] - self.colors[i][0] if d <= common.misc.real_high_precision(): return self.reverse_gamma(self.colors[i][1]) amount = (x - self.colors[i][0]) / d col = self.blend(self.reverse_gamma(self.colors[i][1]), self.reverse_gamma(self.colors[j][1]), amount) return col
def extract_colors(self): """ Helps in extracting all the colors present in the gradient """ initial_list = [] for col in self.synfig_gradient: red = float(col[0].text) ** (1/settings.GAMMA[0]) green = float(col[1].text) ** (1/settings.GAMMA[1]) blue = float(col[2].text) ** (1/settings.GAMMA[2]) alpha = float(col[3].text) initial_list.append([float(col.attrib["pos"]), Color(red, green, blue, alpha)]) self.colors = initial_list
def parse_position(animated, i): """ To convert the synfig coordinates from units(initially a string) to pixels Depends on whether a vector is provided to it or a real value If real value is provided, then time is also taken into consideration Args: animated (lxml.etree._Element) : Stores animation which contains waypoints i (int) : Iterator over animation Returns: (common.Vector.Vector) If the animated type is not color (common.Color.Color) Else if the animated type is color """ if animated.attrib["type"] == "vector": pos = [float(animated[i][0][0].text), float(animated[i][0][1].text)] pos = [settings.PIX_PER_UNIT * x for x in pos] elif animated.attrib["type"] in {"real", "circle_radius"}: pos = parse_value(animated, i) elif animated.attrib["type"] == "angle": pos = [ get_angle(float(animated[i][0].attrib["value"])), get_frame(animated[i]) ] elif animated.attrib["type"] == "base": pos = [ float(animated[i][0].attrib["value"]) * settings.PIX_PER_UNIT, get_frame(animated[i]) ] elif animated.attrib["type"] in { "composite_convert", "region_angle", "star_angle_new", "scalar_multiply" }: pos = [float(animated[i][0].attrib["value"]), get_frame(animated[i])] elif animated.attrib["type"] == "rotate_layer_angle": # Angle needs to made neg of what they are pos = [-float(animated[i][0].attrib["value"]), get_frame(animated[i])] elif animated.attrib["type"] == "opacity": pos = [ float(animated[i][0].attrib["value"]) * settings.OPACITY_CONSTANT, get_frame(animated[i]) ] elif animated.attrib["type"] == "effects_opacity": pos = [float(animated[i][0].attrib["value"]), get_frame(animated[i])] elif animated.attrib["type"] == "points": pos = [ int(animated[i][0].attrib["value"]) * settings.PIX_PER_UNIT, get_frame(animated[i]) ] elif animated.attrib["type"] == "bool": val = animated[i][0].attrib["value"] if val == "false": val = 0 else: val = 1 pos = [val, get_frame(animated[i])] elif animated.attrib["type"] == "rectangle_size": pos = parse_value(animated, i) vec = Vector(pos[0], pos[1], animated.attrib["type"]) vec.add_new_val( float(animated[i][0].attrib["value2"]) * settings.PIX_PER_UNIT) return vec elif animated.attrib["type"] == "image_scale": val = float(animated[i][0].attrib["value"]) val2 = get_frame(animated[i]) vec = Vector(val, val2, animated.attrib["type"]) vec.add_new_val(float(animated[i][0].attrib["value2"])) return vec elif animated.attrib["type"] == "scale_layer_zoom": val = (math.e**float(animated[i][0].attrib["value"])) * 100 val2 = get_frame(animated[i]) vec = Vector(val, val2, animated.attrib["type"]) vec.add_new_val(val) return vec elif animated.attrib["type"] == "stretch_layer_scale": val1 = float(animated[i][0][0].text) * 100 val3 = float(animated[i][0][1].text) * 100 vec = Vector(val1, get_frame(animated[i]), animated.attrib["type"]) vec.add_new_val(val3) return vec elif animated.attrib["type"] in { "group_layer_scale", "blur_anim_x", "blur_anim_y" }: if animated.attrib["type"] == "group_layer_scale": val1 = float(animated[i][0][0].text) * 100 val3 = float(animated[i][0][1].text) * 100 vec = Vector(val1, get_frame(animated[i]), animated.attrib["type"]) vec.add_new_val(val3) elif animated.attrib["type"] == "blur_anim_x": val1 = float(animated[i][0][0].text) * 100 vec = Vector(val1, get_frame(animated[i]), animated.attrib["type"]) else: val1 = float(animated[i][0][1].text) * 100 vec = Vector(val1, get_frame(animated[i]), animated.attrib["type"]) return vec elif animated.attrib["type"] == "time": val = parse_time(animated[i][0].attrib["value"]) # Needed in seconds val2 = get_frame(animated[i]) # Needed in frames return Vector(val, val2, animated.attrib["type"]) elif animated.attrib["type"] == "color": red = float(animated[i][0][0].text) green = float(animated[i][0][1].text) blue = float(animated[i][0][2].text) alpha = float(animated[i][0][3].text) red = red**(1 / settings.GAMMA[0]) green = green**(1 / settings.GAMMA[1]) blue = blue**(1 / settings.GAMMA[2]) return Color(red, green, blue, alpha) elif animated.attrib["type"] == "gradient": return Gradient(animated[i][0]) return Vector(pos[0], pos[1], animated.attrib["type"])