Merge pull request #1316 from TonyCrane/shaders

Improve Text's handling of non-display characters in shaders and Add a feature
This commit is contained in:
Grant Sanderson 2021-01-17 19:22:11 -08:00 committed by GitHub
commit 19e93454d9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 79 additions and 40 deletions

View file

@ -29,6 +29,10 @@ universal_import_line: "from manimlib.imports import *"
style: style:
font: "Consolas" font: "Consolas"
background_color: "#333333" background_color: "#333333"
# Set the position of preview window, you can use directions, e.g. UL/DR/OL/OO/...
# also, you can also specify the position(pixel) of the upper left corner of
# the window on the monitor, e.g. "960,540"
window_position: UR
camera_qualities: camera_qualities:
low: low:
resolution: "854x480" resolution: "854x480"

View file

@ -24,4 +24,5 @@ dependencies:
- pyyaml - pyyaml
- validators - validators
- ipython - ipython
- PyOpenGL

View file

@ -125,6 +125,7 @@ class TextExample(Scene):
fonts = Text( fonts = Text(
"And you can also set the font according to different words", "And you can also set the font according to different words",
font="Arial",
t2f={"font": "Consolas", "words": "Consolas"}, t2f={"font": "Consolas", "words": "Consolas"},
t2c={"font": BLUE, "words": GREEN} t2c={"font": BLUE, "words": GREEN}
) )

View file

@ -203,7 +203,23 @@ def get_configuration(args):
else: else:
window_width = monitor.width / 2 window_width = monitor.width / 2
window_height = window_width * 9 / 16 window_height = window_width * 9 / 16
window_position = (int(monitor.width - window_width), 0) custom_position = custom_defaults["window_position"]
if "," in custom_position:
posx, posy = map(int, custom_position.split(","))
else:
if custom_position[1] == "L":
posx = 0
elif custom_position[1] == "O":
posx = int((monitor.width - window_width) / 2)
elif custom_position[1] == "R":
posx = int(monitor.width - window_width)
if custom_position[0] == "U":
posy = 0
elif custom_position[0] == "O":
posy = int((monitor.height - window_height) / 2)
elif custom_position[0] == "D":
posy = int(monitor.height - window_height)
window_position = (posx, posy)
config["window_config"] = { config["window_config"] = {
"size": (window_width, window_height), "size": (window_width, window_height),
"position": window_position, "position": window_position,

View file

@ -61,24 +61,12 @@ JOINT_TYPE_MAP = {
} }
# Related to Text # Related to Text
NOT_SETTING_FONT_MSG = '''
Warning:
You haven't set font.
If you are not using English, this may cause text rendering problem.
You set font like:
text = Text('your text', font='your font')
or:
class MyText(Text):
CONFIG = {
'font': 'My Font'
}
'''
START_X = 30 START_X = 30
START_Y = 20 START_Y = 20
NORMAL = 'NORMAL' NORMAL = "NORMAL"
ITALIC = 'ITALIC' ITALIC = "ITALIC"
OBLIQUE = 'OBLIQUE' OBLIQUE = "OBLIQUE"
BOLD = 'BOLD' BOLD = "BOLD"
DEFAULT_STROKE_WIDTH = 4 DEFAULT_STROKE_WIDTH = 4

View file

@ -4,6 +4,7 @@ import copy
import hashlib import hashlib
import cairo import cairo
from manimlib.constants import * from manimlib.constants import *
from manimlib.mobject.geometry import Dot, Rectangle
from manimlib.mobject.svg.svg_mobject import SVGMobject from manimlib.mobject.svg.svg_mobject import SVGMobject
from manimlib.utils.config_ops import digest_config from manimlib.utils.config_ops import digest_config
from manimlib.utils.customization import get_customization from manimlib.utils.customization import get_customization
@ -13,9 +14,6 @@ from manimlib.utils.directories import get_text_dir
TEXT_MOB_SCALE_FACTOR = 0.001048 TEXT_MOB_SCALE_FACTOR = 0.001048
# Warning, these classes are currently based on an old rendering mode
# not supported in this version of manim
class TextSetting(object): class TextSetting(object):
def __init__(self, start, end, font, slant, weight, line_num=-1): def __init__(self, start, end, font, slant, weight, line_num=-1):
self.start = start self.start = start
@ -29,33 +27,39 @@ class TextSetting(object):
class Text(SVGMobject): class Text(SVGMobject):
CONFIG = { CONFIG = {
# Mobject # Mobject
'color': WHITE, "color": WHITE,
'height': None, "height": None,
'stroke_width': 0, "stroke_width": 0,
# Text # Text
'font': '', "font": '',
'gradient': None, "gradient": None,
'lsh': -1, "lsh": -1,
'size': 1, "size": 1,
'font_size': 48, "font_size": 48,
'slant': NORMAL, "tab_width": 4,
'weight': NORMAL, "slant": NORMAL,
't2c': {}, "weight": NORMAL,
't2f': {}, "t2c": {},
't2g': {}, "t2f": {},
't2s': {}, "t2g": {},
't2w': {}, "t2s": {},
"t2w": {},
} }
def __init__(self, text, **config): def __init__(self, text, **config):
self.text = text
self.full2short(config) self.full2short(config)
digest_config(self, config) digest_config(self, config)
self.lsh = self.size if self.lsh == -1 else self.lsh self.lsh = self.size if self.lsh == -1 else self.lsh
text_without_tabs = text
if text.find('\t') != -1:
text_without_tabs = text.replace('\t', ' ' * self.tab_width)
self.text = text_without_tabs
file_name = self.text2svg() file_name = self.text2svg()
self.remove_last_M(file_name) self.remove_last_M(file_name)
self.remove_empty_path(file_name)
SVGMobject.__init__(self, file_name, **config) SVGMobject.__init__(self, file_name, **config)
self.text = text
self.apply_space_chars()
if self.t2c: if self.t2c:
self.set_color_by_t2c() self.set_color_by_t2c()
@ -68,6 +72,18 @@ class Text(SVGMobject):
if self.height is None: if self.height is None:
self.scale(TEXT_MOB_SCALE_FACTOR * self.font_size) self.scale(TEXT_MOB_SCALE_FACTOR * self.font_size)
def apply_space_chars(self):
submobs = self.submobjects.copy()
for char_index in range(self.text.__len__()):
if self.text[char_index] == " " or self.text[char_index] == "\t" or self.text[char_index] == "\n":
space = Dot(radius=0, fill_opacity=0, stroke_opacity=0)
if char_index == 0:
space.move_to(submobs[char_index].get_center())
else:
space.move_to(submobs[char_index - 1].get_center())
submobs.insert(char_index, space)
self.set_submobjects(submobs)
def remove_last_M(self, file_name): def remove_last_M(self, file_name):
with open(file_name, 'r') as fpr: with open(file_name, 'r') as fpr:
content = fpr.read() content = fpr.read()
@ -75,6 +91,13 @@ class Text(SVGMobject):
with open(file_name, 'w') as fpw: with open(file_name, 'w') as fpw:
fpw.write(content) fpw.write(content)
def remove_empty_path(self, file_name):
with open(file_name, 'r') as fpr:
content = fpr.read()
content = re.sub(r'<path .*?d=""/>', '', content)
with open(file_name, 'w') as fpw:
fpw.write(content)
def find_indexes(self, word): def find_indexes(self, word):
m = re.match(r'\[([0-9\-]{0,}):([0-9\-]{0,})\]', word) m = re.match(r'\[([0-9\-]{0,}):([0-9\-]{0,})\]', word)
if m: if m:

View file

@ -539,9 +539,14 @@ class Scene(object):
pass pass
def on_key_press(self, symbol, modifiers): def on_key_press(self, symbol, modifiers):
if chr(symbol) == "r": try:
char = chr(symbol)
except OverflowError:
print(" Warning: The value of the pressed key is too large.")
return
if char == "r":
self.camera.frame.to_default_state() self.camera.frame.to_default_state()
elif chr(symbol) == "q": elif char == "q":
self.quit_interaction = True self.quit_interaction = True
def on_resize(self, width: int, height: int): def on_resize(self, width: int, height: int):

View file

@ -15,4 +15,5 @@ pyyaml
screeninfo screeninfo
pyreadline; sys_platform == 'win32' pyreadline; sys_platform == 'win32'
validators validators
ipython ipython
PyOpenGL