mirror of
https://github.com/lvgl/lvgl.git
synced 2026-05-26 11:07:34 +08:00
refactor(gdb): lv_global supports lazy loading and refactors some structures and formats. (#8939)
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
# lvglgdb
|
||||
|
||||
lvglgdb is a GDB script for LVGL.
|
||||
|
||||
# Structure
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
lvgl["lvgl<br/>(mem→python object)"]
|
||||
gdb_cmds["gdb_cmds<br/>(gdb commands)"]
|
||||
lvglgdb["lvglgdb"]
|
||||
|
||||
lvglgdb --> lvgl
|
||||
lvglgdb --> gdb_cmds
|
||||
gdb_cmds --> lvgl
|
||||
|
||||
classDef pkg fill:white,stroke:gray
|
||||
classDef core fill:white,stroke:gray
|
||||
class lvglgdb,lvgl,gdb_cmds pkg
|
||||
```
|
||||
@@ -1,22 +1,13 @@
|
||||
from .value import *
|
||||
from .lvgl import *
|
||||
from .lv_global import set_lvgl_instance
|
||||
from .core.lv_obj import DumpObj
|
||||
from .display.lv_display import DumpDisplayBuf
|
||||
from .draw.lv_draw import InfoDrawUnit
|
||||
from .misc.lv_style import InfoStyle
|
||||
from .debugger import *
|
||||
from .value import Value
|
||||
from .lvgl import curr_inst, LVDisplay, LVDrawBuf, LVList, LVObject, dump_style_info
|
||||
from . import cmds as cmds
|
||||
|
||||
# Debugger
|
||||
Debugger()
|
||||
|
||||
# Dumps
|
||||
DumpObj()
|
||||
DumpDisplayBuf()
|
||||
|
||||
# Infos
|
||||
InfoStyle()
|
||||
InfoDrawUnit()
|
||||
|
||||
# Set instance
|
||||
set_lvgl_instance(None)
|
||||
__all__ = [
|
||||
"curr_inst",
|
||||
"LVDisplay",
|
||||
"LVDrawBuf",
|
||||
"LVList",
|
||||
"LVObject",
|
||||
"dump_style_info",
|
||||
"Value",
|
||||
]
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
import gdb
|
||||
|
||||
from .core import DumpObj
|
||||
from .display import DumpDisplayBuf
|
||||
from .draw import InfoDrawUnit
|
||||
from .misc import InfoStyle
|
||||
from .debugger import Debugger
|
||||
|
||||
__all__ = []
|
||||
|
||||
# Set pagination off and python print-stack full
|
||||
gdb.execute("set pagination off")
|
||||
gdb.write("set pagination off\n")
|
||||
gdb.execute("set python print-stack full")
|
||||
gdb.write("set python print-stack full\n")
|
||||
|
||||
|
||||
# Debugger
|
||||
Debugger()
|
||||
|
||||
# Dumps
|
||||
DumpObj()
|
||||
DumpDisplayBuf()
|
||||
|
||||
# Infos
|
||||
InfoStyle()
|
||||
InfoDrawUnit()
|
||||
@@ -0,0 +1,5 @@
|
||||
from .lv_obj import DumpObj
|
||||
|
||||
__all__ = [
|
||||
"DumpObj",
|
||||
]
|
||||
@@ -0,0 +1,63 @@
|
||||
import argparse
|
||||
import gdb
|
||||
|
||||
from lvglgdb.lvgl import curr_inst
|
||||
from lvglgdb.lvgl import LVObject, dump_obj_info
|
||||
|
||||
|
||||
class DumpObj(gdb.Command):
|
||||
"""dump obj tree from specified obj"""
|
||||
|
||||
def __init__(self):
|
||||
super(DumpObj, self).__init__(
|
||||
"dump obj", gdb.COMMAND_USER, gdb.COMPLETE_EXPRESSION
|
||||
)
|
||||
|
||||
def dump_obj(self, obj: LVObject, depth=0, limit=None):
|
||||
if not obj:
|
||||
return
|
||||
|
||||
# dump self
|
||||
print(" " * depth, end="")
|
||||
dump_obj_info(obj)
|
||||
|
||||
if limit is not None and depth >= limit:
|
||||
return
|
||||
|
||||
# dump children
|
||||
for child in obj.children:
|
||||
self.dump_obj(child, depth + 1, limit=limit)
|
||||
|
||||
def invoke(self, args, from_tty):
|
||||
parser = argparse.ArgumentParser(description="Dump lvgl obj tree.")
|
||||
parser.add_argument(
|
||||
"-L",
|
||||
"--level",
|
||||
type=int,
|
||||
default=None,
|
||||
help="Limit the depth of the tree.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"root",
|
||||
type=str,
|
||||
nargs="?",
|
||||
default=None,
|
||||
help="Optional root obj to dump.",
|
||||
)
|
||||
try:
|
||||
args = parser.parse_args(gdb.string_to_argv(args))
|
||||
except SystemExit:
|
||||
return
|
||||
|
||||
if args.root:
|
||||
root = gdb.parse_and_eval(args.root)
|
||||
root = LVObject(root)
|
||||
self.dump_obj(root, limit=args.level)
|
||||
else:
|
||||
# dump all displays
|
||||
depth = 0
|
||||
for disp in curr_inst().displays():
|
||||
print(f"Display {hex(disp)}")
|
||||
for screen in disp.screens:
|
||||
print(f'{" " * (depth + 1)}Screen@{hex(screen)}')
|
||||
self.dump_obj(screen, depth=depth + 1, limit=args.level)
|
||||
@@ -57,7 +57,9 @@ class Debugger(gdb.Command):
|
||||
print("pydevd_pycharm module not found. Please install it using pip.")
|
||||
return
|
||||
|
||||
pydevd_pycharm.settrace(self.__host, port=self.__port, stdoutToServer=True, stderrToServer=True)
|
||||
pydevd_pycharm.settrace(
|
||||
self.__host, port=self.__port, stdoutToServer=True, stderrToServer=True
|
||||
)
|
||||
|
||||
def connect_to_vscode(self):
|
||||
try:
|
||||
@@ -0,0 +1,5 @@
|
||||
from .lv_display import DumpDisplayBuf
|
||||
|
||||
__all__ = [
|
||||
"DumpDisplayBuf",
|
||||
]
|
||||
+3
-47
@@ -1,52 +1,8 @@
|
||||
import argparse
|
||||
import gdb
|
||||
|
||||
from ..core.lv_obj import LVObject
|
||||
from ..draw.lv_draw_buf import LVDrawBuf
|
||||
from ..value import Value
|
||||
from .. import lv_global
|
||||
|
||||
|
||||
class LVDisplay(Value):
|
||||
"""LVGL display"""
|
||||
|
||||
def __init__(self, disp: Value):
|
||||
super().__init__(disp)
|
||||
|
||||
@property
|
||||
def hor_res(self) -> int:
|
||||
"""Get horizontal resolution in pixels"""
|
||||
return int(self.super_value("hor_res"))
|
||||
|
||||
@property
|
||||
def ver_res(self) -> int:
|
||||
"""Get vertical resolution in pixels"""
|
||||
return int(self.super_value("ver_res"))
|
||||
|
||||
@property
|
||||
def screens(self):
|
||||
screens = self.super_value("screens")
|
||||
for i in range(self.screen_cnt):
|
||||
yield LVObject(screens[i])
|
||||
|
||||
# Buffer-related properties
|
||||
@property
|
||||
def buf_1(self):
|
||||
"""Get first draw buffer (may be None)"""
|
||||
buf_ptr = self.super_value("buf_1")
|
||||
return LVDrawBuf(buf_ptr) if buf_ptr else None
|
||||
|
||||
@property
|
||||
def buf_2(self):
|
||||
"""Get second draw buffer (may be None)"""
|
||||
buf_ptr = self.super_value("buf_2")
|
||||
return LVDrawBuf(buf_ptr) if buf_ptr else None
|
||||
|
||||
@property
|
||||
def buf_act(self):
|
||||
"""Get currently active draw buffer (may be None)"""
|
||||
buf_ptr = self.super_value("buf_act")
|
||||
return LVDrawBuf(buf_ptr) if buf_ptr else None
|
||||
from lvglgdb.lvgl import curr_inst
|
||||
from lvglgdb.lvgl import LVDrawBuf
|
||||
|
||||
|
||||
class DumpDisplayBuf(gdb.Command):
|
||||
@@ -80,7 +36,7 @@ class DumpDisplayBuf(gdb.Command):
|
||||
except SystemExit:
|
||||
return
|
||||
|
||||
display = lv_global.g_lvgl_instance.disp_default()
|
||||
display = curr_inst().disp_default()
|
||||
if not display:
|
||||
print("Error: Invalid display pointer")
|
||||
return
|
||||
@@ -0,0 +1,5 @@
|
||||
from .lv_draw import InfoDrawUnit
|
||||
|
||||
__all__ = [
|
||||
"InfoDrawUnit",
|
||||
]
|
||||
@@ -1,7 +1,7 @@
|
||||
import gdb
|
||||
|
||||
from .. import lv_global
|
||||
from ..value import Value
|
||||
from lvglgdb.value import Value
|
||||
from lvglgdb.lvgl import curr_inst
|
||||
|
||||
|
||||
class InfoDrawUnit(gdb.Command):
|
||||
@@ -46,5 +46,5 @@ class InfoDrawUnit(gdb.Command):
|
||||
)
|
||||
|
||||
def invoke(self, args, from_tty):
|
||||
for unit in lv_global.g_lvgl_instance.draw_units():
|
||||
for unit in curr_inst().draw_units():
|
||||
self.dump_draw_unit(unit)
|
||||
@@ -0,0 +1,5 @@
|
||||
from .lv_style import InfoStyle
|
||||
|
||||
__all__ = [
|
||||
"InfoStyle",
|
||||
]
|
||||
@@ -1,8 +1,9 @@
|
||||
import argparse
|
||||
import gdb
|
||||
|
||||
from ..value import Value
|
||||
from ..core.lv_obj import LVObject
|
||||
from lvglgdb.value import Value
|
||||
from lvglgdb.lvgl import LVObject
|
||||
from lvglgdb.lvgl import dump_style_info
|
||||
|
||||
|
||||
class InfoStyle(gdb.Command):
|
||||
@@ -37,9 +38,3 @@ class InfoStyle(gdb.Command):
|
||||
for style in LVObject(obj).styles:
|
||||
print(" ", end="")
|
||||
dump_style_info(style)
|
||||
|
||||
|
||||
def dump_style_info(style: Value):
|
||||
prop = int(style.prop)
|
||||
value = style.value
|
||||
print(f"{prop} = {value}")
|
||||
@@ -1,30 +0,0 @@
|
||||
from typing import Union
|
||||
import gdb
|
||||
|
||||
from .value import Value
|
||||
|
||||
g_lvgl_instance = None
|
||||
|
||||
|
||||
def set_lvgl_instance(lv_global: Union[gdb.Value, Value, None]):
|
||||
global g_lvgl_instance
|
||||
|
||||
if not lv_global:
|
||||
try:
|
||||
lv_global = Value(gdb.parse_and_eval("lv_global").address)
|
||||
except gdb.error as e:
|
||||
print(f"Failed to get lv_global: {e}")
|
||||
return
|
||||
|
||||
if not isinstance(lv_global, Value):
|
||||
lv_global = Value(lv_global)
|
||||
|
||||
inited = lv_global.inited
|
||||
if not inited:
|
||||
print(
|
||||
"\x1b[31mlvgl is not initialized yet. Please call `set_lvgl_instance(None)` later.\x1b[0m"
|
||||
)
|
||||
return
|
||||
|
||||
from .lvgl import LVGL
|
||||
g_lvgl_instance = LVGL(lv_global)
|
||||
@@ -1,44 +0,0 @@
|
||||
from typing import Iterator
|
||||
|
||||
import gdb
|
||||
|
||||
from .display.lv_display import LVDisplay
|
||||
from .misc.lv_ll import LVList
|
||||
|
||||
from .value import Value
|
||||
|
||||
gdb.execute("set pagination off")
|
||||
gdb.write("set pagination off\n")
|
||||
gdb.execute("set python print-stack full")
|
||||
gdb.write("set python print-stack full\n")
|
||||
|
||||
|
||||
class LVGL:
|
||||
"""LVGL instance"""
|
||||
|
||||
def __init__(self, lv_global: Value):
|
||||
self.lv_global = lv_global.cast("lv_global_t", ptr=True)
|
||||
|
||||
def displays(self) -> Iterator[LVDisplay]:
|
||||
ll = self.lv_global.disp_ll
|
||||
if not ll:
|
||||
return
|
||||
|
||||
for disp in LVList(ll, "lv_display_t"):
|
||||
yield LVDisplay(disp)
|
||||
|
||||
def disp_default(self):
|
||||
disp_default = self.lv_global.disp_default
|
||||
return LVDisplay(disp_default) if disp_default else None
|
||||
|
||||
def screen_active(self):
|
||||
disp = self.lv_global.disp_default
|
||||
return disp.act_scr if disp else None
|
||||
|
||||
def draw_units(self):
|
||||
unit = self.lv_global.draw_info.unit_head
|
||||
|
||||
# Iterate through all draw units
|
||||
while unit:
|
||||
yield unit
|
||||
unit = unit.next
|
||||
@@ -0,0 +1,14 @@
|
||||
from .core import LVObject, curr_inst, dump_obj_info
|
||||
from .display import LVDisplay
|
||||
from .draw import LVDrawBuf
|
||||
from .misc import LVList, dump_style_info
|
||||
|
||||
__all__ = [
|
||||
"LVObject",
|
||||
"LVDisplay",
|
||||
"LVDrawBuf",
|
||||
"curr_inst",
|
||||
"LVList",
|
||||
"dump_style_info",
|
||||
"dump_obj_info",
|
||||
]
|
||||
@@ -0,0 +1,8 @@
|
||||
from .lv_obj import LVObject, dump_obj_info
|
||||
from .lv_global import curr_inst
|
||||
|
||||
__all__ = [
|
||||
"LVObject",
|
||||
"curr_inst",
|
||||
"dump_obj_info",
|
||||
]
|
||||
@@ -0,0 +1,107 @@
|
||||
import gdb
|
||||
from typing import Optional, Union, Iterator, TYPE_CHECKING
|
||||
|
||||
from lvglgdb.value import Value
|
||||
from ..misc.lv_ll import LVList
|
||||
|
||||
"""
|
||||
LVGL global instance
|
||||
|
||||
Note:
|
||||
lv_global is the global instance of LVGL.
|
||||
It will contain other components like display, draw unit, etc.
|
||||
So if you want add a new component, please add it in this class.
|
||||
And just import your component when you need it. Not expose to the whole file.
|
||||
"""
|
||||
|
||||
__all__ = ["curr_inst"]
|
||||
|
||||
"""
|
||||
Type hint for IDE, just imported at typechecking phase not in runtime.
|
||||
"""
|
||||
if TYPE_CHECKING:
|
||||
from ..display.lv_display import LVDisplay
|
||||
|
||||
|
||||
class LVGL:
|
||||
"""LVGL instance"""
|
||||
|
||||
def __init__(self, lv_global: Value):
|
||||
self.lv_global = lv_global.cast("lv_global_t", ptr=True)
|
||||
|
||||
def displays(self) -> "Iterator[LVDisplay]":
|
||||
ll = self.lv_global.disp_ll
|
||||
if not ll:
|
||||
return
|
||||
|
||||
from ..display.lv_display import LVDisplay
|
||||
|
||||
for disp in LVList(ll, "lv_display_t"):
|
||||
yield LVDisplay(disp)
|
||||
|
||||
def disp_default(self):
|
||||
from ..display.lv_display import LVDisplay
|
||||
|
||||
disp_default = self.lv_global.disp_default
|
||||
return LVDisplay(disp_default) if disp_default else None
|
||||
|
||||
def screen_active(self):
|
||||
disp = self.lv_global.disp_default
|
||||
return disp.act_scr if disp else None
|
||||
|
||||
def draw_units(self):
|
||||
unit = self.lv_global.draw_info.unit_head
|
||||
|
||||
# Iterate through all draw units
|
||||
while unit:
|
||||
yield unit
|
||||
unit = unit.next
|
||||
|
||||
|
||||
class _LVGLSingleton:
|
||||
__slots__ = ("_lvgl", "_ready")
|
||||
|
||||
def __init__(self) -> None:
|
||||
self._lvgl: Optional[object] = None
|
||||
self._ready = False
|
||||
|
||||
def ensure_init(self, lv_global: Union[gdb.Value, Value, None] = None) -> bool:
|
||||
if self._ready:
|
||||
return True
|
||||
|
||||
if lv_global is None:
|
||||
try:
|
||||
lv_global = Value(gdb.parse_and_eval("lv_global").address)
|
||||
except gdb.error as e:
|
||||
print(f"Failed to get lv_global: {e}")
|
||||
return False
|
||||
elif not isinstance(lv_global, Value):
|
||||
lv_global = Value(lv_global)
|
||||
|
||||
if not lv_global.inited:
|
||||
print(
|
||||
"\x1b[31mlvgl is not initialized yet. "
|
||||
"Please call `ensure_init()` later.\x1b[0m"
|
||||
)
|
||||
return False
|
||||
|
||||
self._lvgl = LVGL(lv_global)
|
||||
self._ready = True
|
||||
return True
|
||||
|
||||
def __getattr__(self, name: str):
|
||||
if not self._ready and not self.ensure_init():
|
||||
raise RuntimeError("LVGL singleton not ready")
|
||||
return getattr(self._lvgl, name)
|
||||
|
||||
def reset(self) -> None:
|
||||
self._lvgl = None
|
||||
self._ready = False
|
||||
|
||||
|
||||
__curr_inst = _LVGLSingleton()
|
||||
|
||||
|
||||
def curr_inst() -> _LVGLSingleton:
|
||||
"""Get the global instance of LVGL"""
|
||||
return __curr_inst
|
||||
@@ -1,8 +1,4 @@
|
||||
import argparse
|
||||
import gdb
|
||||
|
||||
from ..value import Value
|
||||
from .. import lv_global
|
||||
from lvglgdb.value import Value
|
||||
|
||||
|
||||
class LVObject(Value):
|
||||
@@ -70,64 +66,6 @@ class LVObject(Value):
|
||||
return self.spec_attr.children[index] if self.spec_attr else None
|
||||
|
||||
|
||||
class DumpObj(gdb.Command):
|
||||
"""dump obj tree from specified obj"""
|
||||
|
||||
def __init__(self):
|
||||
super(DumpObj, self).__init__(
|
||||
"dump obj", gdb.COMMAND_USER, gdb.COMPLETE_EXPRESSION
|
||||
)
|
||||
|
||||
def dump_obj(self, obj: LVObject, depth=0, limit=None):
|
||||
if not obj:
|
||||
return
|
||||
|
||||
# dump self
|
||||
print(" " * depth, end="")
|
||||
dump_obj_info(obj)
|
||||
|
||||
if limit is not None and depth >= limit:
|
||||
return
|
||||
|
||||
# dump children
|
||||
for child in obj.children:
|
||||
self.dump_obj(child, depth + 1, limit=limit)
|
||||
|
||||
def invoke(self, args, from_tty):
|
||||
parser = argparse.ArgumentParser(description="Dump lvgl obj tree.")
|
||||
parser.add_argument(
|
||||
"-L",
|
||||
"--level",
|
||||
type=int,
|
||||
default=None,
|
||||
help="Limit the depth of the tree.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"root",
|
||||
type=str,
|
||||
nargs="?",
|
||||
default=None,
|
||||
help="Optional root obj to dump.",
|
||||
)
|
||||
try:
|
||||
args = parser.parse_args(gdb.string_to_argv(args))
|
||||
except SystemExit:
|
||||
return
|
||||
|
||||
if args.root:
|
||||
root = gdb.parse_and_eval(args.root)
|
||||
root = LVObject(root)
|
||||
self.dump_obj(root, limit=args.level)
|
||||
else:
|
||||
# dump all displays
|
||||
depth = 0
|
||||
for disp in lv_global.g_lvgl_instance.displays():
|
||||
print(f"Display {hex(disp)}")
|
||||
for screen in disp.screens:
|
||||
print(f'{" " * (depth + 1)}Screen@{hex(screen)}')
|
||||
self.dump_obj(screen, depth=depth + 1, limit=args.level)
|
||||
|
||||
|
||||
def dump_obj_info(obj: LVObject):
|
||||
clzname = obj.class_name
|
||||
coords = f"{obj.x1},{obj.y1},{obj.x2},{obj.y2}"
|
||||
@@ -0,0 +1,5 @@
|
||||
from .lv_display import LVDisplay
|
||||
|
||||
__all__ = [
|
||||
"LVDisplay",
|
||||
]
|
||||
@@ -0,0 +1,45 @@
|
||||
from ..core.lv_obj import LVObject
|
||||
from ..draw.lv_draw_buf import LVDrawBuf
|
||||
from lvglgdb.value import Value
|
||||
|
||||
|
||||
class LVDisplay(Value):
|
||||
"""LVGL display"""
|
||||
|
||||
def __init__(self, disp: Value):
|
||||
super().__init__(disp)
|
||||
|
||||
@property
|
||||
def hor_res(self) -> int:
|
||||
"""Get horizontal resolution in pixels"""
|
||||
return int(self.super_value("hor_res"))
|
||||
|
||||
@property
|
||||
def ver_res(self) -> int:
|
||||
"""Get vertical resolution in pixels"""
|
||||
return int(self.super_value("ver_res"))
|
||||
|
||||
@property
|
||||
def screens(self):
|
||||
screens = self.super_value("screens")
|
||||
for i in range(self.screen_cnt):
|
||||
yield LVObject(screens[i])
|
||||
|
||||
# Buffer-related properties
|
||||
@property
|
||||
def buf_1(self):
|
||||
"""Get first draw buffer (may be None)"""
|
||||
buf_ptr = self.super_value("buf_1")
|
||||
return LVDrawBuf(buf_ptr) if buf_ptr else None
|
||||
|
||||
@property
|
||||
def buf_2(self):
|
||||
"""Get second draw buffer (may be None)"""
|
||||
buf_ptr = self.super_value("buf_2")
|
||||
return LVDrawBuf(buf_ptr) if buf_ptr else None
|
||||
|
||||
@property
|
||||
def buf_act(self):
|
||||
"""Get currently active draw buffer (may be None)"""
|
||||
buf_ptr = self.super_value("buf_act")
|
||||
return LVDrawBuf(buf_ptr) if buf_ptr else None
|
||||
@@ -0,0 +1,5 @@
|
||||
from .lv_draw_buf import LVDrawBuf
|
||||
|
||||
__all__ = [
|
||||
"LVDrawBuf",
|
||||
]
|
||||
+8
-4
@@ -5,7 +5,7 @@ import gdb
|
||||
import numpy as np
|
||||
from PIL import Image
|
||||
|
||||
from ..value import Value
|
||||
from lvglgdb.value import Value
|
||||
|
||||
|
||||
class LVDrawBuf(Value):
|
||||
@@ -143,7 +143,7 @@ class LVDrawBuf(Value):
|
||||
return False
|
||||
|
||||
def _convert_to_image(
|
||||
self, pixel_data: bytes, width: int, height: int, color_format: int
|
||||
self, pixel_data: bytes, width: int, height: int, color_format: int
|
||||
) -> Optional[Image.Image]:
|
||||
"""
|
||||
Convert raw pixel data to PIL Image based on color format.
|
||||
@@ -162,14 +162,18 @@ class LVDrawBuf(Value):
|
||||
# Convert RGB565 to RGB888
|
||||
arr = np.frombuffer(pixel_data, dtype=np.uint8)
|
||||
arr = arr.reshape((height, width, 2))
|
||||
rgb565 = np.frombuffer(pixel_data, dtype=np.uint16).reshape((height, width))
|
||||
rgb565 = np.frombuffer(pixel_data, dtype=np.uint16).reshape(
|
||||
(height, width)
|
||||
)
|
||||
r = (((rgb565 & 0xF800) >> 11) << 3).astype(np.uint8)
|
||||
g = ((rgb565 & 0x07E0) >> 3).astype(np.uint8)
|
||||
b = ((rgb565 & 0x001F) << 3).astype(np.uint8)
|
||||
return Image.fromarray(np.dstack((r, g, b)), "RGB")
|
||||
|
||||
elif color_format == self._color_formats["RGB888"]:
|
||||
arr = np.frombuffer(pixel_data, dtype=np.uint8).reshape(height, width, 3)
|
||||
arr = np.frombuffer(pixel_data, dtype=np.uint8).reshape(
|
||||
height, width, 3
|
||||
)
|
||||
rgb_arr = arr[:, :, [2, 1, 0]] # BGR -> RGB
|
||||
return Image.fromarray(rgb_arr, "RGB")
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
from .lv_ll import LVList
|
||||
from .lv_style import dump_style_info
|
||||
|
||||
__all__ = [
|
||||
"LVList",
|
||||
"dump_style_info",
|
||||
]
|
||||
@@ -1,7 +1,7 @@
|
||||
from typing import Union
|
||||
import gdb
|
||||
|
||||
from ..value import Value
|
||||
from lvglgdb.value import Value
|
||||
|
||||
|
||||
class LVList(Value):
|
||||
@@ -0,0 +1,7 @@
|
||||
from lvglgdb.value import Value
|
||||
|
||||
|
||||
def dump_style_info(style: Value):
|
||||
prop = int(style.prop)
|
||||
value = style.value
|
||||
print(f"{prop} = {value}")
|
||||
@@ -4,7 +4,7 @@ from typing import Optional, Union
|
||||
|
||||
|
||||
class Value(gdb.Value):
|
||||
def __init__(self, value: Union[gdb.Value, 'Value']):
|
||||
def __init__(self, value: Union[gdb.Value, "Value"]):
|
||||
super().__init__(value)
|
||||
|
||||
def __getitem__(self, key):
|
||||
@@ -19,14 +19,18 @@ class Value(gdb.Value):
|
||||
return Value(super().__getattribute__(key))
|
||||
return Value(super().__getitem__(key))
|
||||
|
||||
def cast(self, type_name: Union[str, gdb.Type], ptr: bool = False) -> Optional['Value']:
|
||||
def cast(
|
||||
self, type_name: Union[str, gdb.Type], ptr: bool = False
|
||||
) -> Optional["Value"]:
|
||||
try:
|
||||
gdb_type = gdb.lookup_type(type_name) if isinstance(type_name, str) else type_name
|
||||
gdb_type = (
|
||||
gdb.lookup_type(type_name) if isinstance(type_name, str) else type_name
|
||||
)
|
||||
if ptr:
|
||||
gdb_type = gdb_type.pointer()
|
||||
return Value(super().cast(gdb_type))
|
||||
except gdb.error:
|
||||
return None
|
||||
|
||||
def super_value(self, attr: str) -> 'Value':
|
||||
def super_value(self, attr: str) -> "Value":
|
||||
return self[attr]
|
||||
|
||||
Reference in New Issue
Block a user