mirror of
https://github.com/ManimCommunity/manim.git
synced 2026-06-22 10:01:47 +00:00
:class:~.MathTex, :class:~.Tex, :class:~.Text and :class:~.MarkupText inherit color from their parent mobjects. (#2467)
* comment out color-related things from tex_mob * add change to svg_mobject * MarkupText handles colour internally * MarkupText handles colour internally * make coordinate_system.py colour agnostic * get_line_from_axis_to_point * add typings for SingleStringMathTex * add typings for MathTex * make internal methods internal * black + isort * fix typo * black + isort * fix typo * revert internalizing change * Revert "Merge branch 'mathtexx' of https://github.com/hydrobeam/manim into mathtexx" This reverts commit6be3c39814, reversing changes made to2b30b446ae. * remove accidental import * do it in a less bad way * WIP: Text2setting causing problems * allow tex_mobject.py to inherit colour * allow tex_mobject.py to inherit colour * add tests * remove undeedde imports + formatting * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix warnings from pre-commit hooks * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix some tests * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * remove other color_inheritance test * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix typo * accomodate the color->attribute PR * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Fix tests and doc build add a check for None when inheriting colour in `coordinate_systems.py`, and turn written tests into graphical tests * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Comment out `Text` color inheritance test. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Set font for text_color_inheritance test * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Small change to retrigger docs build * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
parent
1e437d6587
commit
2275ec5916
11 changed files with 110 additions and 44 deletions
|
|
@ -49,7 +49,6 @@ from ..utils.color import (
|
|||
BLUE,
|
||||
BLUE_D,
|
||||
GREEN,
|
||||
LIGHT_GREY,
|
||||
WHITE,
|
||||
YELLOW,
|
||||
color_gradient,
|
||||
|
|
@ -487,7 +486,7 @@ class CoordinateSystem:
|
|||
point: Sequence[float],
|
||||
line_func: Line = DashedLine,
|
||||
line_config: dict | None = None,
|
||||
color: Color = LIGHT_GREY,
|
||||
color: Color | None = None,
|
||||
stroke_width: float = 2,
|
||||
) -> Line:
|
||||
"""Returns a straight line from a given axis to a point in the scene.
|
||||
|
|
@ -517,9 +516,15 @@ class CoordinateSystem:
|
|||
:meth:`~.CoordinateSystem.get_vertical_line`
|
||||
:meth:`~.CoordinateSystem.get_horizontal_line`
|
||||
"""
|
||||
|
||||
line_config = line_config if line_config is not None else {}
|
||||
|
||||
if color is None:
|
||||
color = VMobject().color
|
||||
|
||||
line_config["color"] = color
|
||||
line_config["stroke_width"] = stroke_width
|
||||
|
||||
axis = self.get_axis(index)
|
||||
line = line_func(axis.get_projection(point), point, **line_config)
|
||||
return line
|
||||
|
|
@ -977,9 +982,8 @@ class CoordinateSystem:
|
|||
|
||||
if dot_config is None:
|
||||
dot_config = {}
|
||||
label = self.x_axis._create_label_tex(label)
|
||||
color = color or graph.get_color()
|
||||
label.set_color(color)
|
||||
label = self.x_axis._create_label_tex(label).set_color(color)
|
||||
|
||||
if x_val is None:
|
||||
# Search from right to left
|
||||
|
|
@ -1630,9 +1634,9 @@ class CoordinateSystem:
|
|||
x_val: float,
|
||||
graph: ParametricFunction,
|
||||
label: float | str | Mobject | None = None,
|
||||
label_color: Color = WHITE,
|
||||
label_color: Color | None = None,
|
||||
triangle_size: float = MED_SMALL_BUFF,
|
||||
triangle_color: Color = WHITE,
|
||||
triangle_color: Color | None = WHITE,
|
||||
line_func: Line = Line,
|
||||
line_color: Color = YELLOW,
|
||||
) -> VGroup:
|
||||
|
|
@ -1688,7 +1692,7 @@ class CoordinateSystem:
|
|||
triangle.height = triangle_size
|
||||
triangle.move_to(self.coords_to_point(x_val, 0), UP)
|
||||
if label is not None:
|
||||
t_label = self.x_axis._create_label_tex(label).set_color(label_color)
|
||||
t_label = self.x_axis._create_label_tex(label, color=label_color)
|
||||
t_label.next_to(triangle, DOWN)
|
||||
T_label_group.add(t_label)
|
||||
|
||||
|
|
@ -2338,7 +2342,6 @@ class NumberPlane(Axes):
|
|||
|
||||
# configs
|
||||
self.axis_config = {
|
||||
"stroke_color": WHITE,
|
||||
"stroke_width": 2,
|
||||
"include_ticks": False,
|
||||
"include_tip": False,
|
||||
|
|
@ -2626,7 +2629,6 @@ class PolarPlane(Axes):
|
|||
|
||||
# configs
|
||||
self.radius_config = {
|
||||
"stroke_color": WHITE,
|
||||
"stroke_width": 2,
|
||||
"include_ticks": False,
|
||||
"include_tip": False,
|
||||
|
|
@ -3012,7 +3014,7 @@ class ComplexPlane(NumberPlane):
|
|||
|
||||
Returns
|
||||
-------
|
||||
List[Union[float, complex]]
|
||||
List[float | complex]
|
||||
A list of floats representing the x-axis and complex numbers representing the y-axis.
|
||||
"""
|
||||
x_numbers = self.get_x_axis().get_tick_range()
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ class NumberLine(Line):
|
|||
Parameters
|
||||
----------
|
||||
x_range
|
||||
The :code:`[x_min, x_max, x_step]` values to create the line.
|
||||
The ``[x_min, x_max, x_step]`` values to create the line.
|
||||
length
|
||||
The length of the number line.
|
||||
unit_size
|
||||
|
|
@ -559,7 +559,9 @@ class NumberLine(Line):
|
|||
self.add(labels)
|
||||
return self
|
||||
|
||||
def _create_label_tex(self, label_tex: str | float | VMobject) -> VMobject:
|
||||
def _create_label_tex(
|
||||
self, label_tex: str | float | VMobject, **kwargs
|
||||
) -> VMobject:
|
||||
"""Checks if the label is a :class:`~.VMobject`, otherwise, creates a
|
||||
label according to the ``label_constructor``.
|
||||
|
||||
|
|
@ -579,7 +581,7 @@ class NumberLine(Line):
|
|||
if isinstance(label_tex, VMobject):
|
||||
return label_tex
|
||||
else:
|
||||
return self.label_constructor(label_tex)
|
||||
return self.label_constructor(label_tex, **kwargs)
|
||||
|
||||
@staticmethod
|
||||
def _decimal_places_from_step(step) -> int:
|
||||
|
|
|
|||
|
|
@ -82,6 +82,7 @@ class SVGMobject(VMobject, metaclass=ConvertToOpenGL):
|
|||
stroke_opacity=1.0,
|
||||
**kwargs,
|
||||
):
|
||||
|
||||
self.def_map = {}
|
||||
self.file_name = file_name or self.file_name
|
||||
self._ensure_valid_file()
|
||||
|
|
|
|||
|
|
@ -27,16 +27,18 @@ import operator as op
|
|||
import re
|
||||
from functools import reduce
|
||||
from textwrap import dedent
|
||||
from typing import Dict, Iterable, Optional
|
||||
|
||||
from colour import Color
|
||||
|
||||
from manim.utils.tex import TexTemplate
|
||||
|
||||
from ... import config, logger
|
||||
from ...constants import *
|
||||
from ...mobject.geometry import Line
|
||||
from ...mobject.svg.svg_mobject import SVGMobject
|
||||
from ...mobject.svg.svg_path import SVGPathMobject
|
||||
from ...mobject.types.vectorized_mobject import VectorizedPoint, VGroup
|
||||
from ...utils.color import BLACK, WHITE
|
||||
from ...mobject.types.vectorized_mobject import VectorizedPoint, VGroup, VMobject
|
||||
from ...utils.tex_file_writing import tex_to_svg_file
|
||||
from .style_utils import parse_style
|
||||
|
||||
|
|
@ -64,21 +66,22 @@ class SingleStringMathTex(SVGMobject):
|
|||
|
||||
def __init__(
|
||||
self,
|
||||
tex_string,
|
||||
stroke_width=0,
|
||||
fill_opacity=1.0,
|
||||
background_stroke_width=0,
|
||||
background_stroke_color=BLACK,
|
||||
should_center=True,
|
||||
height=None,
|
||||
organize_left_to_right=False,
|
||||
tex_environment="align*",
|
||||
tex_template=None,
|
||||
font_size=DEFAULT_FONT_SIZE,
|
||||
color=Color(WHITE),
|
||||
tex_string: str,
|
||||
stroke_width: float = 0,
|
||||
should_center: bool = True,
|
||||
height: float | None = None,
|
||||
organize_left_to_right: bool = False,
|
||||
tex_environment: str = "align*",
|
||||
tex_template: TexTemplate | None = None,
|
||||
font_size: float = DEFAULT_FONT_SIZE,
|
||||
**kwargs,
|
||||
):
|
||||
|
||||
if kwargs.get("color") is None:
|
||||
# makes it so that color isn't explicitly passed for these mobs,
|
||||
# and can instead inherit from the parent
|
||||
kwargs["color"] = VMobject().color
|
||||
|
||||
self._font_size = font_size
|
||||
self.organize_left_to_right = organize_left_to_right
|
||||
self.tex_environment = tex_environment
|
||||
|
|
@ -98,12 +101,8 @@ class SingleStringMathTex(SVGMobject):
|
|||
should_center=should_center,
|
||||
stroke_width=stroke_width,
|
||||
height=height,
|
||||
fill_opacity=fill_opacity,
|
||||
background_stroke_width=background_stroke_width,
|
||||
background_stroke_color=background_stroke_color,
|
||||
should_subdivide_sharp_curves=True,
|
||||
should_remove_null_curves=True,
|
||||
color=color,
|
||||
**kwargs,
|
||||
)
|
||||
# used for scaling via font_size.setter
|
||||
|
|
@ -263,10 +262,10 @@ class MathTex(SingleStringMathTex):
|
|||
def __init__(
|
||||
self,
|
||||
*tex_strings,
|
||||
arg_separator=" ",
|
||||
substrings_to_isolate=None,
|
||||
tex_to_color_map=None,
|
||||
tex_environment="align*",
|
||||
arg_separator: str = " ",
|
||||
substrings_to_isolate: Iterable[str] | None = None,
|
||||
tex_to_color_map: dict[str, Color] = None,
|
||||
tex_environment: str = "align*",
|
||||
**kwargs,
|
||||
):
|
||||
self.tex_template = kwargs.pop("tex_template", config["tex_template"])
|
||||
|
|
|
|||
|
|
@ -70,8 +70,8 @@ from ... import config, logger
|
|||
from ...constants import *
|
||||
from ...mobject.geometry import Dot
|
||||
from ...mobject.svg.svg_mobject import SVGMobject
|
||||
from ...mobject.types.vectorized_mobject import VGroup
|
||||
from ...utils.color import WHITE, Colors, color_gradient
|
||||
from ...mobject.types.vectorized_mobject import VGroup, VMobject
|
||||
from ...utils.color import Colors, color_gradient
|
||||
from ...utils.deprecation import deprecated
|
||||
|
||||
TEXT_MOB_SCALE_FACTOR = 0.05
|
||||
|
|
@ -406,7 +406,7 @@ class Text(SVGMobject):
|
|||
text: str,
|
||||
fill_opacity: float = 1.0,
|
||||
stroke_width: float = 0,
|
||||
color: Color = WHITE,
|
||||
color: Color | None = None,
|
||||
font_size: float = DEFAULT_FONT_SIZE,
|
||||
line_spacing: float = -1,
|
||||
font: str = "",
|
||||
|
|
@ -427,6 +427,7 @@ class Text(SVGMobject):
|
|||
disable_ligatures: bool = False,
|
||||
**kwargs,
|
||||
):
|
||||
|
||||
self.line_spacing = line_spacing
|
||||
self.font = font
|
||||
self._font_size = float(font_size)
|
||||
|
|
@ -470,6 +471,8 @@ class Text(SVGMobject):
|
|||
)
|
||||
else:
|
||||
self.line_spacing = self._font_size + self._font_size * self.line_spacing
|
||||
|
||||
color = Color(color) if color else VMobject().color
|
||||
file_name = self._text2svg(color)
|
||||
PangoUtils.remove_last_M(file_name)
|
||||
super().__init__(
|
||||
|
|
@ -596,7 +599,7 @@ class Text(SVGMobject):
|
|||
def _text2hash(self, color: Color):
|
||||
"""Generates ``sha256`` hash for file name."""
|
||||
settings = (
|
||||
"PANGO" + self.font + self.slant + self.weight + color
|
||||
"PANGO" + self.font + self.slant + self.weight + color.hex_l
|
||||
) # to differentiate Text and CairoText
|
||||
settings += str(self.t2f) + str(self.t2s) + str(self.t2w) + str(self.t2c)
|
||||
settings += str(self.line_spacing) + str(self._font_size)
|
||||
|
|
@ -683,8 +686,9 @@ class Text(SVGMobject):
|
|||
(self.t2w, "weight"),
|
||||
(self.t2c, "color"),
|
||||
]
|
||||
# setting_args requires values to be strings
|
||||
default_args = {
|
||||
arg: getattr(self, arg) if arg != "color" else color for _, arg in t2xs
|
||||
arg: getattr(self, arg) if arg != "color" else str(color) for _, arg in t2xs
|
||||
}
|
||||
|
||||
settings = self._get_settings_from_t2xs(t2xs, default_args)
|
||||
|
|
@ -737,6 +741,7 @@ class Text(SVGMobject):
|
|||
for setting in settings:
|
||||
if setting.line_num == -1:
|
||||
setting.line_num = line_num
|
||||
|
||||
return settings
|
||||
|
||||
def _text2svg(self, color: Color):
|
||||
|
|
@ -896,8 +901,6 @@ class MarkupText(SVGMobject):
|
|||
The fill opacity with 1 meaning opaque and 0 meaning transparent.
|
||||
stroke_width : :class:`int`
|
||||
Stroke width.
|
||||
color : :class:`str`
|
||||
Global color setting for the entire text. Local overrides are possible.
|
||||
font_size : :class:`float`
|
||||
Font size.
|
||||
line_spacing : :class:`int`
|
||||
|
|
@ -1089,7 +1092,7 @@ class MarkupText(SVGMobject):
|
|||
text: str,
|
||||
fill_opacity: float = 1,
|
||||
stroke_width: float = 0,
|
||||
color: Color = WHITE,
|
||||
color: Color | None = None,
|
||||
font_size: float = DEFAULT_FONT_SIZE,
|
||||
line_spacing: int = -1,
|
||||
font: str = "",
|
||||
|
|
@ -1105,6 +1108,7 @@ class MarkupText(SVGMobject):
|
|||
disable_ligatures: bool = False,
|
||||
**kwargs,
|
||||
):
|
||||
|
||||
self.text = text
|
||||
self.line_spacing = line_spacing
|
||||
self.font = font
|
||||
|
|
@ -1138,7 +1142,9 @@ class MarkupText(SVGMobject):
|
|||
else:
|
||||
self.line_spacing = self._font_size + self._font_size * self.line_spacing
|
||||
|
||||
file_name = self._text2svg(Color(color) if color else None)
|
||||
color = Color(color) if color else VMobject().color
|
||||
file_name = self._text2svg(color)
|
||||
|
||||
PangoUtils.remove_last_M(file_name)
|
||||
super().__init__(
|
||||
file_name,
|
||||
|
|
@ -1150,6 +1156,7 @@ class MarkupText(SVGMobject):
|
|||
unpack_groups=unpack_groups,
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
self.chars = self.get_group_class()(*self.submobjects)
|
||||
self.text = text_without_tabs.replace(" ", "").replace("\n", "")
|
||||
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
20
tests/test_graphical_units/test_tex_mobject.py
Normal file
20
tests/test_graphical_units/test_tex_mobject.py
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
import pytest
|
||||
|
||||
from manim import *
|
||||
from manim.utils.testing.frames_comparison import frames_comparison
|
||||
|
||||
__module_test__ = "tex_mobject"
|
||||
|
||||
|
||||
@frames_comparison
|
||||
def test_color_inheritance(scene):
|
||||
"""Test that Text and MarkupText correctly inherit colour from
|
||||
their parent class."""
|
||||
|
||||
VMobject.set_default(color=RED)
|
||||
tex = Tex("test color inheritance")
|
||||
mathtex = MathTex("test color inheritance")
|
||||
vgr = VGroup(tex, mathtex).arrange()
|
||||
VMobject.set_default()
|
||||
|
||||
scene.add(vgr)
|
||||
|
|
@ -13,3 +13,23 @@ __module_test__ = "text"
|
|||
@frames_comparison
|
||||
def test_Text2Color(scene):
|
||||
scene.add(Text("this is a text with spaces!", t2c={"spaces": RED}))
|
||||
|
||||
|
||||
@pytest.mark.skipif(
|
||||
not sys.platform.startswith("linux"),
|
||||
reason="MacOS and Windows render fonts differently, so they need separate comparison data.",
|
||||
)
|
||||
@frames_comparison
|
||||
def test_text_color_inheritance(scene):
|
||||
"""Test that Text and MarkupText correctly inherit colour from
|
||||
their parent class."""
|
||||
VMobject.set_default(color=RED)
|
||||
# set both to a singular font so that the tests agree.
|
||||
text = Text("test_color_inheritance", font="Dejavu Sans")
|
||||
markup_text = MarkupText("test_color_inheritance", font="Dejavu Sans")
|
||||
vgr = VGroup(text, markup_text).arrange()
|
||||
|
||||
# reset the default color so that future tests aren't affected by this change.
|
||||
VMobject.set_default()
|
||||
|
||||
scene.add(vgr)
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ from pathlib import Path
|
|||
import pytest
|
||||
|
||||
from manim import MathTex, SingleStringMathTex, Tex, TexTemplate, config
|
||||
from manim.mobject.types.vectorized_mobject import VMobject
|
||||
from manim.utils.color import RED
|
||||
|
||||
|
||||
def test_MathTex():
|
||||
|
|
|
|||
|
|
@ -1,6 +1,11 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import pytest
|
||||
from colour import Color
|
||||
|
||||
from manim.mobject.svg.text_mobject import MarkupText, Text
|
||||
from manim.mobject.types.vectorized_mobject import VMobject
|
||||
from manim.utils.color import RED
|
||||
|
||||
|
||||
def test_font_size():
|
||||
|
|
@ -11,3 +16,11 @@ def test_font_size():
|
|||
|
||||
assert round(text_string.font_size, 5) == 14.4
|
||||
assert round(markuptext_string.font_size, 5) == 14.4
|
||||
|
||||
|
||||
def test_non_str_color():
|
||||
"""Test that the Text and MarkupText can accept non_str color values
|
||||
i.e. colour.Color(red)."""
|
||||
|
||||
text = Text("test_color_inheritance", color=Color("blue"))
|
||||
markup_text = MarkupText("test_color_inheritance", color=Color("blue"))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue