IQ.Pilot Release Commit @ 6d177d4
This commit is contained in:
@@ -33,10 +33,19 @@ EMOJI_REGEX = re.compile(
|
||||
flags=re.UNICODE
|
||||
)
|
||||
|
||||
_emoji_font_loaded = False
|
||||
|
||||
def _load_emoji_font() -> ImageFont.FreeTypeFont | None:
|
||||
global _emoji_font
|
||||
if _emoji_font is None:
|
||||
_emoji_font = ImageFont.truetype(str(FONT_DIR.joinpath("NotoColorEmoji.ttf")), 109)
|
||||
global _emoji_font, _emoji_font_loaded
|
||||
if not _emoji_font_loaded:
|
||||
_emoji_font_loaded = True
|
||||
try:
|
||||
# FONT_DIR is an importlib.resources path. Inside the setup zipapp it points into the archive,
|
||||
# so str() yields a path through the .zip that PIL can't open ("cannot open resource"). Read
|
||||
# the bytes and hand PIL a file object so it works both on disk and inside the zipapp.
|
||||
_emoji_font = ImageFont.truetype(io.BytesIO(FONT_DIR.joinpath("NotoColorEmoji.ttf").read_bytes()), 109)
|
||||
except Exception:
|
||||
_emoji_font = None # never crash the whole UI over an emoji glyph
|
||||
return _emoji_font
|
||||
|
||||
def find_emoji(text):
|
||||
@@ -44,12 +53,15 @@ def find_emoji(text):
|
||||
|
||||
def emoji_tex(emoji):
|
||||
if emoji not in _cache:
|
||||
font = _load_emoji_font()
|
||||
if font is None:
|
||||
return None
|
||||
img = Image.new("RGBA", (128, 128), (0, 0, 0, 0))
|
||||
draw = ImageDraw.Draw(img)
|
||||
draw.text((0, 0), emoji, font=_load_emoji_font(), embedded_color=True)
|
||||
draw.text((0, 0), emoji, font=font, embedded_color=True)
|
||||
with io.BytesIO() as buffer:
|
||||
img.save(buffer, format="PNG")
|
||||
l = buffer.tell()
|
||||
buffer.seek(0)
|
||||
_cache[emoji] = rl.load_texture_from_image(rl.load_image_from_memory(".png", buffer.getvalue(), l))
|
||||
return _cache[emoji]
|
||||
return _cache.get(emoji)
|
||||
|
||||
@@ -50,6 +50,8 @@ INSTALLER_URL_PATH = "/tmp/installer_url"
|
||||
# "<user>/<branch>" maps to a GitHub fork. IQ.OS uses the DRM "magic" compositor, not Wayland,
|
||||
# so comma's downloaded installers (installer.comma.ai) crash on launch; clone the fork directly.
|
||||
GITHUB_FORK_URL = "https://github.com/{user}/openpilot.git"
|
||||
# IQ.Pilot lives on the IQ Lvbs git server; github.com/IQLvbs is DMCA'd and dead.
|
||||
GIT_URL_OVERRIDES = {"IQLvbs": "https://git.konn3kt.com/IQ.Lvbs/IQ.Pilot.git"}
|
||||
|
||||
CONTINUE = """#!/usr/bin/env bash
|
||||
|
||||
@@ -756,7 +758,7 @@ class Setup(Widget):
|
||||
pass
|
||||
|
||||
def _fork_install_thread(self, user: str, branch: str):
|
||||
git_url = GITHUB_FORK_URL.format(user=user)
|
||||
git_url = GIT_URL_OVERRIDES.get(user) or GITHUB_FORK_URL.format(user=user)
|
||||
label = f"{user}/{branch}"
|
||||
try:
|
||||
subprocess.run(["rm", "-rf", TMP_INSTALL_PATH], check=False)
|
||||
@@ -774,7 +776,8 @@ class Setup(Widget):
|
||||
subprocess.run(["git", "-C", TMP_INSTALL_PATH, "submodule", "update", "--init"], check=False)
|
||||
|
||||
run_cmd(["rm", "-f", VALID_CACHE_PATH])
|
||||
run_cmd(["rm", "-rf", INSTALL_PATH])
|
||||
# sudo: a prior *run* install can leave root-owned .pyc here that a comma-user rm can't delete.
|
||||
run_cmd(["sudo", "rm", "-rf", INSTALL_PATH])
|
||||
run_cmd(["mv", TMP_INSTALL_PATH, INSTALL_PATH])
|
||||
|
||||
self._ble_progress("installing", 90)
|
||||
@@ -882,6 +885,11 @@ class Setup(Widget):
|
||||
# AGNOS might try to execute the installer before this process exits.
|
||||
# Therefore, important to close the fd before renaming the installer.
|
||||
os.close(fd)
|
||||
# comma's ELF installer does `rm -rf /data/openpilot` as the comma user and asserts it
|
||||
# succeeds; a prior *run* install leaves root-owned __pycache__ .pyc it can't delete, so it
|
||||
# aborts before continue.sh and bounces back to setup. Clear the old tree first (sudo) so the
|
||||
# installer's rm succeeds.
|
||||
subprocess.run(["sudo", "rm", "-rf", INSTALL_PATH], check=False)
|
||||
os.rename(tmpfile, INSTALLER_DESTINATION_PATH)
|
||||
|
||||
with open(INSTALLER_URL_PATH, "w") as f:
|
||||
|
||||
@@ -51,6 +51,8 @@ INSTALLER_DESTINATION_PATH = "/tmp/installer"
|
||||
INSTALLER_URL_PATH = "/tmp/installer_url"
|
||||
|
||||
GITHUB_FORK_URL = "https://github.com/{user}/openpilot.git"
|
||||
# IQ.Pilot lives on the IQ Lvbs git server; github.com/IQLvbs is DMCA'd and dead.
|
||||
GIT_URL_OVERRIDES = {"IQLvbs": "https://git.konn3kt.com/IQ.Lvbs/IQ.Pilot.git"}
|
||||
|
||||
CONTINUE = """#!/usr/bin/env bash
|
||||
|
||||
@@ -589,7 +591,7 @@ class Setup(Widget):
|
||||
pass
|
||||
|
||||
def _fork_install_thread(self, user: str, branch: str):
|
||||
git_url = GITHUB_FORK_URL.format(user=user)
|
||||
git_url = GIT_URL_OVERRIDES.get(user) or GITHUB_FORK_URL.format(user=user)
|
||||
label = f"{user}/{branch}"
|
||||
fail_msg = "Ensure the entered URL is valid, and the device's internet connection is good."
|
||||
try:
|
||||
@@ -609,7 +611,8 @@ class Setup(Widget):
|
||||
subprocess.run(["git", "-C", TMP_INSTALL_PATH, "submodule", "update", "--init"], check=False)
|
||||
|
||||
run_cmd(["rm", "-f", VALID_CACHE_PATH])
|
||||
run_cmd(["rm", "-rf", INSTALL_PATH])
|
||||
# sudo: a prior *run* install can leave root-owned .pyc here that a comma-user rm can't delete.
|
||||
run_cmd(["sudo", "rm", "-rf", INSTALL_PATH])
|
||||
run_cmd(["mv", TMP_INSTALL_PATH, INSTALL_PATH])
|
||||
|
||||
self._ble_progress("installing", 90)
|
||||
@@ -718,6 +721,11 @@ class Setup(Widget):
|
||||
# AGNOS might try to execute the installer before this process exits.
|
||||
# Therefore, important to close the fd before renaming the installer.
|
||||
os.close(fd)
|
||||
# comma's ELF installer does `rm -rf /data/openpilot` as the comma user and asserts it
|
||||
# succeeds; a prior *run* install leaves root-owned __pycache__ .pyc it can't delete, so it
|
||||
# aborts before continue.sh and bounces back to setup. Clear the old tree first (sudo) so the
|
||||
# installer's rm succeeds.
|
||||
subprocess.run(["sudo", "rm", "-rf", INSTALL_PATH], check=False)
|
||||
os.rename(tmpfile, INSTALLER_DESTINATION_PATH)
|
||||
|
||||
with open(INSTALLER_URL_PATH, "w") as f:
|
||||
|
||||
@@ -406,7 +406,8 @@ class Label(Widget):
|
||||
line_pos.x += width_before.x
|
||||
|
||||
tex = emoji_tex(emoji)
|
||||
rl.draw_texture_ex(tex, line_pos, 0.0, self._font_size / tex.height * FONT_SCALE, self._text_color)
|
||||
if tex is not None:
|
||||
rl.draw_texture_ex(tex, line_pos, 0.0, self._font_size / tex.height * FONT_SCALE, self._text_color)
|
||||
line_pos.x += self._font_size * FONT_SCALE
|
||||
prev_index = end
|
||||
rl.draw_text_ex(self._font, text[prev_index:], line_pos, self._font_size, 0, self._text_color)
|
||||
@@ -849,8 +850,9 @@ class UnifiedLabel(Widget):
|
||||
|
||||
# Draw emoji
|
||||
tex = emoji_tex(emoji)
|
||||
emoji_scale = self._font_size / tex.height * FONT_SCALE
|
||||
rl.draw_texture_ex(tex, line_pos, 0.0, emoji_scale, self._text_color)
|
||||
if tex is not None:
|
||||
emoji_scale = self._font_size / tex.height * FONT_SCALE
|
||||
rl.draw_texture_ex(tex, line_pos, 0.0, emoji_scale, self._text_color)
|
||||
# Emoji width is font_size * FONT_SCALE (as per measure_text_cached)
|
||||
line_pos.x += self._font_size * FONT_SCALE
|
||||
prev_index = end
|
||||
|
||||
Reference in New Issue
Block a user