Update to github version
@@ -1,110 +0,0 @@
|
||||
import os
|
||||
import sys
|
||||
import importlib
|
||||
import inspect
|
||||
from pathlib import Path
|
||||
import matplotlib
|
||||
matplotlib.use('Agg')
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
import nazca as nd
|
||||
import mxpic as mx
|
||||
|
||||
# 2. Define your mxPIC Color Palette
|
||||
# You can map by your custom layer names (if defined) or raw GDS (layer, datatype) tuples.
|
||||
# Matplotlib accepts standard color names ('blue', 'cyan') or hex codes ('#FFD700').
|
||||
PALETTE = {
|
||||
"WG": "blue", # Example: Core waveguide layer
|
||||
"SLAB": "cyan", # Example: Shallow etch / Slab
|
||||
"M1": "#FFD700", # Example: Metal 1 (Gold)
|
||||
"M2": "silver", # Example: Metal 2
|
||||
"DEEP_TRENCH": "black", # Example: Trenching
|
||||
(1, 0): "darkred", # Fallback: You can use raw GDS tuples directly
|
||||
(2, 0): "green",
|
||||
(1111, 0): "green",
|
||||
(63, 30): "#FFD700",
|
||||
}
|
||||
|
||||
def apply_mxpic_colors():
|
||||
"""Applies the custom color palette to Nazca's active layer map."""
|
||||
print("🎨 Applying mxPIC layer colors...")
|
||||
for layer_id, color in PALETTE.items():
|
||||
try:
|
||||
# Nazca's built-in command to register plot colors
|
||||
nd.set_layercolor(layer=layer_id, color=color)
|
||||
except Exception:
|
||||
# If a specific layer name doesn't exist in the registry yet, it safely skips
|
||||
pass
|
||||
|
||||
def generate_component_images(img_root="images/components"):
|
||||
print("📸 Starting mxPIC Component Image Generation...")
|
||||
|
||||
# Define our source and target directories
|
||||
src_root = Path("mxpic/components")
|
||||
img_root = Path(img_root)
|
||||
|
||||
if not src_root.exists():
|
||||
print(f"❌ Error: Source directory '{src_root}' not found.")
|
||||
sys.exit(1)
|
||||
|
||||
# Walk through all Python files in the components folder
|
||||
success_count = 0
|
||||
fail_count = 0
|
||||
|
||||
tapeout = mx.foundries.Silterra.EOM1_2ML_CU()
|
||||
|
||||
for py_file in src_root.rglob("*.py"):
|
||||
if py_file.name == "__init__.py":
|
||||
continue
|
||||
|
||||
# Convert the file path to a Python module path (e.g., mxpic.components.mzm)
|
||||
rel_path = py_file.relative_to(src_root)
|
||||
module_name = "mxpic.components." + str(rel_path.with_suffix("")).replace(os.sep, ".")
|
||||
|
||||
try:
|
||||
# Dynamically import the module
|
||||
module = importlib.import_module(module_name)
|
||||
except Exception as e:
|
||||
print(f"⚠️ Could not import {module_name}: {e}")
|
||||
fail_count += 1
|
||||
continue
|
||||
|
||||
|
||||
# Scan the module for all defined classes
|
||||
for name, obj in inspect.getmembers(module, inspect.isclass):
|
||||
# Only process classes actually defined IN this file (ignore imported classes)
|
||||
if obj.__module__ == module_name:
|
||||
|
||||
# Determine where to save the image
|
||||
target_dir = img_root / rel_path.parent
|
||||
target_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
# img_path = target_dir / f"{name}.png"
|
||||
|
||||
try:
|
||||
# 1. Clear the Nazca canvas so components don't overlap!
|
||||
nd.clear_layout()
|
||||
|
||||
# 2. Instantiate the class (assuming zero arguments)
|
||||
instance = obj()
|
||||
|
||||
# 4. Export the image using Nazca
|
||||
nd.export_plt(path="",title=f"{name}",topcells=[instance.cell])
|
||||
# 3. Explicitly save to disk with tight borders
|
||||
plt.savefig(str(target_dir)+f"\\{name}.png", bbox_inches='tight', dpi=300)
|
||||
|
||||
# 4. CRITICAL: Clear the figure from RAM so the next loop is clean
|
||||
plt.close()
|
||||
|
||||
print(f"✅ Generated: {str(target_dir)}\\{name}.png")
|
||||
success_count += 1
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Failed to generate image for {name} in {module_name}: {e}")
|
||||
fail_count += 1
|
||||
|
||||
print("\n✨ Image generation complete!")
|
||||
print(f"📊 Success: {success_count} | Failures: {fail_count}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
generate_component_images(img_root="docs/source/mxpic/components/")
|
||||
@@ -1,166 +0,0 @@
|
||||
# import os
|
||||
# import shutil
|
||||
# from pathlib import Path
|
||||
|
||||
# basic_md_info = "\
|
||||
# .. mxpic_handbook documentation master file, created by\n\
|
||||
# sphinx-quickstart on Sun May 3 16:05:57 2026.\n\
|
||||
# You can adapt this file completely to your liking, but it should at least\n\
|
||||
# contain the root `toctree` directive.\n\n\
|
||||
# # Welcome to the automated documentation for the mxPIC silicon photonics library.\n\
|
||||
# ```{toctree}\n\
|
||||
# :maxdepth: 2\n\
|
||||
# :caption: Components:\n\n\
|
||||
# "
|
||||
|
||||
# def generate_myst_docs(src_dir: str, docs_api_dir: str) -> None:
|
||||
# """
|
||||
# Scans a Python package and generates MyST Markdown files for Sphinx autodoc.
|
||||
# """
|
||||
# src_path = Path(src_dir).resolve()
|
||||
# api_path = Path(docs_api_dir).resolve()
|
||||
|
||||
# # Clean the old api directory to prevent dead links from deleted files
|
||||
# if api_path.exists():
|
||||
# # shutil.rmtree(api_path)
|
||||
# pass
|
||||
# else :
|
||||
# api_path.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
# package_name = src_path.name
|
||||
# generated_files = []
|
||||
|
||||
# print(f"Scanning {package_name} for Python modules...")
|
||||
|
||||
# index_info = basic_md_info
|
||||
# # Recursively find all .py files
|
||||
# for py_file in src_path.rglob("*.py"):
|
||||
# # Skip init files and private/internal scripts if desired
|
||||
# if py_file.name == "__init__.py" or py_file.name.startswith("_"):
|
||||
# continue
|
||||
|
||||
# # Convert file path to Python module format (e.g., mxpic.primitives.mzm)
|
||||
# rel_path = py_file.relative_to(src_path.parent.parent)
|
||||
# class_name = str(rel_path.with_suffix("")).replace(os.sep, ".")
|
||||
# module_name = str(rel_path.with_suffix("")).replace(os.sep, "\\")
|
||||
# index_md_name = str(rel_path.with_suffix("")).replace(os.sep, "/")
|
||||
|
||||
# # Create the markdown file
|
||||
# md_filename = api_path / f"{module_name}.md"
|
||||
|
||||
# # MyST Markdown format using Sphinx autodoc directives
|
||||
# content = f"# {module_name}\n \
|
||||
# ```{{eval-rst}}\n \
|
||||
# .. automodule:: {class_name}\n\
|
||||
# :members:\n\
|
||||
# :undoc-members:\n\
|
||||
# :show-inheritance:\n\
|
||||
# ```\n\
|
||||
# "
|
||||
# ## Building .md file for each .py file
|
||||
# try :
|
||||
# try : os.makedirs(name=str(md_filename.parent.resolve()))
|
||||
# except : pass
|
||||
|
||||
# with open(file=str(md_filename.resolve()),mode="w") as md_file:
|
||||
# md_file.write(content)
|
||||
# print(f"Generated: {docs_api_dir}{module_name}.md")
|
||||
# except Exception as e:
|
||||
# print(e)
|
||||
|
||||
# ## Writing information into the index.md file
|
||||
# index_info = index_info + f"{index_md_name}\n"
|
||||
|
||||
# with open(file=docs_api_dir+"index.md",mode="w") as md_file:
|
||||
# md_file.write(index_info)
|
||||
|
||||
# if __name__ == "__main__":
|
||||
# generate_myst_docs(src_dir="mxpic\\components\\",docs_api_dir="mxpic\\docs\\source\\")
|
||||
|
||||
|
||||
import os
|
||||
import sys
|
||||
import importlib
|
||||
import inspect
|
||||
from pathlib import Path
|
||||
|
||||
def generate_markdown_handbook():
|
||||
print("📝 Starting mxPIC Markdown Generation...")
|
||||
|
||||
# Define paths
|
||||
src_root = Path("mxpic/components")
|
||||
# This should point to where your Sphinx .md files are stored
|
||||
docs_root = Path("docs/source/mxpic/components")
|
||||
|
||||
# We use absolute Sphinx paths for images (starts with / meaning docs/source root)
|
||||
sphinx_image_root = "source/images/components"
|
||||
|
||||
success_count = 0
|
||||
|
||||
for py_file in src_root.rglob("*.py"):
|
||||
if py_file.name == "__init__.py":
|
||||
continue
|
||||
|
||||
# Convert path to module name (e.g., mxpic.components.primitives.beam_splitters)
|
||||
rel_path = py_file.relative_to(src_root)
|
||||
module_name = "mxpic.components." + str(rel_path.with_suffix("")).replace(os.sep, ".")
|
||||
|
||||
try:
|
||||
module = importlib.import_module(module_name)
|
||||
except Exception as e:
|
||||
print(f"⚠️ Could not import {module_name}: {e}")
|
||||
continue
|
||||
|
||||
# Find all classes defined inside this specific module
|
||||
classes = []
|
||||
for name, obj in inspect.getmembers(module, inspect.isclass):
|
||||
if obj.__module__ == module_name:
|
||||
classes.append(name)
|
||||
|
||||
# If the file has no classes, skip it
|
||||
if not classes:
|
||||
continue
|
||||
|
||||
# Define where to save the .md file
|
||||
md_file_path = docs_root / rel_path.with_suffix(".md")
|
||||
md_file_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
# --- WRITE THE MARKDOWN FILE ---
|
||||
with open(md_file_path, "w", encoding="utf-8") as f:
|
||||
# 1. Write the Module Header
|
||||
f.write(f"# {module_name}\n\n")
|
||||
|
||||
# 2. Document any module-level docstrings (skipping classes)
|
||||
f.write("```{eval-rst}\n")
|
||||
f.write(f".. automodule:: {module_name}\n")
|
||||
f.write(" :no-members:\n") # This prevents duplicating the classes!
|
||||
f.write("```\n\n")
|
||||
|
||||
# 3. Loop through and write each class with its image
|
||||
for class_name in classes:
|
||||
f.write(f"## {class_name}\n\n")
|
||||
|
||||
# Point to the image path in Sphinx
|
||||
# img_path = f"{sphinx_image_root}/{rel_path.parent.as_posix()}/{class_name}.png"
|
||||
img_path = f"{class_name}.png"
|
||||
|
||||
f.write("```{eval-rst}\n")
|
||||
# Insert the Sphinx image directive
|
||||
f.write(f".. image:: {img_path}\n")
|
||||
f.write(" :align: center\n")
|
||||
f.write(" :width: 600px\n\n")
|
||||
|
||||
# Insert the specific class documentation
|
||||
f.write(f".. autoclass:: {module_name}.{class_name}\n")
|
||||
f.write(" :members:\n")
|
||||
f.write(" :undoc-members:\n")
|
||||
f.write(" :show-inheritance:\n")
|
||||
f.write("```\n\n")
|
||||
|
||||
print(f"✅ Generated docs for: {module_name}")
|
||||
success_count += 1
|
||||
|
||||
print(f"\n✨ Markdown generation complete! Updated {success_count} files.")
|
||||
|
||||
if __name__ == "__main__":
|
||||
generate_markdown_handbook()
|
||||
|
After Width: | Height: | Size: 40 KiB |
@@ -1,20 +0,0 @@
|
||||
# mxpic.components.primitives.EC_dual_layer_px3
|
||||
|
||||
```{eval-rst}
|
||||
.. automodule:: mxpic.components.primitives.EC_dual_layer_px3
|
||||
:no-members:
|
||||
```
|
||||
|
||||
## EC_dual_layer_px3
|
||||
|
||||
```{eval-rst}
|
||||
.. image:: EC_dual_layer_px3.png
|
||||
:align: center
|
||||
:width: 600px
|
||||
|
||||
.. autoclass:: mxpic.components.primitives.EC_dual_layer_px3.EC_dual_layer_px3
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
```
|
||||
|
||||
|
After Width: | Height: | Size: 103 KiB |
|
After Width: | Height: | Size: 212 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 43 KiB |
|
After Width: | Height: | Size: 343 KiB |
@@ -1,33 +0,0 @@
|
||||
# mxpic.components.primitives.beam_splitters
|
||||
|
||||
```{eval-rst}
|
||||
.. automodule:: mxpic.components.primitives.beam_splitters
|
||||
:no-members:
|
||||
```
|
||||
|
||||
## YBranch
|
||||
|
||||
```{eval-rst}
|
||||
.. image:: YBranch.png
|
||||
:align: center
|
||||
:width: 600px
|
||||
|
||||
.. autoclass:: mxpic.components.primitives.beam_splitters.YBranch
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
```
|
||||
|
||||
## Ybranch_3wg
|
||||
|
||||
```{eval-rst}
|
||||
.. image:: Ybranch_3wg.png
|
||||
:align: center
|
||||
:width: 600px
|
||||
|
||||
.. autoclass:: mxpic.components.primitives.beam_splitters.Ybranch_3wg
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
```
|
||||
|
||||
@@ -1,98 +0,0 @@
|
||||
# mxpic.components.primitives.directional_couplers
|
||||
|
||||
```{eval-rst}
|
||||
.. automodule:: mxpic.components.primitives.directional_couplers
|
||||
:no-members:
|
||||
```
|
||||
|
||||
## ADC_STD_2x2
|
||||
|
||||
```{eval-rst}
|
||||
.. image:: ADC_STD_2x2.png
|
||||
:align: center
|
||||
:width: 600px
|
||||
|
||||
.. autoclass:: mxpic.components.primitives.directional_couplers.ADC_STD_2x2
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
```
|
||||
|
||||
## BS_tdc
|
||||
|
||||
```{eval-rst}
|
||||
.. image:: BS_tdc.png
|
||||
:align: center
|
||||
:width: 600px
|
||||
|
||||
.. autoclass:: mxpic.components.primitives.directional_couplers.BS_tdc
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
```
|
||||
|
||||
## DC
|
||||
|
||||
```{eval-rst}
|
||||
.. image:: DC.png
|
||||
:align: center
|
||||
:width: 600px
|
||||
|
||||
.. autoclass:: mxpic.components.primitives.directional_couplers.DC
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
```
|
||||
|
||||
## DC_bend
|
||||
|
||||
```{eval-rst}
|
||||
.. image:: DC_bend.png
|
||||
:align: center
|
||||
:width: 600px
|
||||
|
||||
.. autoclass:: mxpic.components.primitives.directional_couplers.DC_bend
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
```
|
||||
|
||||
## DC_pX_3sg
|
||||
|
||||
```{eval-rst}
|
||||
.. image:: DC_pX_3sg.png
|
||||
:align: center
|
||||
:width: 600px
|
||||
|
||||
.. autoclass:: mxpic.components.primitives.directional_couplers.DC_pX_3sg
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
```
|
||||
|
||||
## MDM
|
||||
|
||||
```{eval-rst}
|
||||
.. image:: MDM.png
|
||||
:align: center
|
||||
:width: 600px
|
||||
|
||||
.. autoclass:: mxpic.components.primitives.directional_couplers.MDM
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
```
|
||||
|
||||
## ring_bus_wg
|
||||
|
||||
```{eval-rst}
|
||||
.. image:: ring_bus_wg.png
|
||||
:align: center
|
||||
:width: 600px
|
||||
|
||||
.. autoclass:: mxpic.components.primitives.directional_couplers.ring_bus_wg
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
```
|
||||
|
||||
@@ -1,111 +0,0 @@
|
||||
# mxpic.components.primitives.grating_couplers
|
||||
|
||||
```{eval-rst}
|
||||
.. automodule:: mxpic.components.primitives.grating_couplers
|
||||
:no-members:
|
||||
```
|
||||
|
||||
## FA
|
||||
|
||||
```{eval-rst}
|
||||
.. image:: FA.png
|
||||
:align: center
|
||||
:width: 600px
|
||||
|
||||
.. autoclass:: mxpic.components.primitives.grating_couplers.FA
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
```
|
||||
|
||||
## GC_STD_1D
|
||||
|
||||
```{eval-rst}
|
||||
.. image:: GC_STD_1D.png
|
||||
:align: center
|
||||
:width: 600px
|
||||
|
||||
.. autoclass:: mxpic.components.primitives.grating_couplers.GC_STD_1D
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
```
|
||||
|
||||
## GC_STD_2D
|
||||
|
||||
```{eval-rst}
|
||||
.. image:: GC_STD_2D.png
|
||||
:align: center
|
||||
:width: 600px
|
||||
|
||||
.. autoclass:: mxpic.components.primitives.grating_couplers.GC_STD_2D
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
```
|
||||
|
||||
## Grating_2D_Hole
|
||||
|
||||
```{eval-rst}
|
||||
.. image:: Grating_2D_Hole.png
|
||||
:align: center
|
||||
:width: 600px
|
||||
|
||||
.. autoclass:: mxpic.components.primitives.grating_couplers.Grating_2D_Hole
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
```
|
||||
|
||||
## Grating_2D_Hole_3Rec
|
||||
|
||||
```{eval-rst}
|
||||
.. image:: Grating_2D_Hole_3Rec.png
|
||||
:align: center
|
||||
:width: 600px
|
||||
|
||||
.. autoclass:: mxpic.components.primitives.grating_couplers.Grating_2D_Hole_3Rec
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
```
|
||||
|
||||
## Grating_2D_Hole_4Rec
|
||||
|
||||
```{eval-rst}
|
||||
.. image:: Grating_2D_Hole_4Rec.png
|
||||
:align: center
|
||||
:width: 600px
|
||||
|
||||
.. autoclass:: mxpic.components.primitives.grating_couplers.Grating_2D_Hole_4Rec
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
```
|
||||
|
||||
## Nano_ant
|
||||
|
||||
```{eval-rst}
|
||||
.. image:: Nano_ant.png
|
||||
:align: center
|
||||
:width: 600px
|
||||
|
||||
.. autoclass:: mxpic.components.primitives.grating_couplers.Nano_ant
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
```
|
||||
|
||||
## Taper
|
||||
|
||||
```{eval-rst}
|
||||
.. image:: Taper.png
|
||||
:align: center
|
||||
:width: 600px
|
||||
|
||||
.. autoclass:: mxpic.components.primitives.grating_couplers.Taper
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
```
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
# mxpic.components.primitives.multimode_interferometers
|
||||
|
||||
```{eval-rst}
|
||||
.. automodule:: mxpic.components.primitives.multimode_interferometers
|
||||
:no-members:
|
||||
```
|
||||
|
||||
## MMI_ML
|
||||
|
||||
```{eval-rst}
|
||||
.. image:: MMI_ML.png
|
||||
:align: center
|
||||
:width: 600px
|
||||
|
||||
.. autoclass:: mxpic.components.primitives.multimode_interferometers.MMI_ML
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
```
|
||||
|
||||
## MMI_STD
|
||||
|
||||
```{eval-rst}
|
||||
.. image:: MMI_STD.png
|
||||
:align: center
|
||||
:width: 600px
|
||||
|
||||
.. autoclass:: mxpic.components.primitives.multimode_interferometers.MMI_STD
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
```
|
||||
|
||||
@@ -1,85 +0,0 @@
|
||||
# mxpic.components.primitives.spiral
|
||||
|
||||
```{eval-rst}
|
||||
.. automodule:: mxpic.components.primitives.spiral
|
||||
:no-members:
|
||||
```
|
||||
|
||||
## Spiral_Cicle_MM
|
||||
|
||||
```{eval-rst}
|
||||
.. image:: Spiral_Cicle_MM.png
|
||||
:align: center
|
||||
:width: 600px
|
||||
|
||||
.. autoclass:: mxpic.components.primitives.spiral.Spiral_Cicle_MM
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
```
|
||||
|
||||
## Spiral_Cicle_STD
|
||||
|
||||
```{eval-rst}
|
||||
.. image:: Spiral_Cicle_STD.png
|
||||
:align: center
|
||||
:width: 600px
|
||||
|
||||
.. autoclass:: mxpic.components.primitives.spiral.Spiral_Cicle_STD
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
```
|
||||
|
||||
## Spiral_Rect_STD
|
||||
|
||||
```{eval-rst}
|
||||
.. image:: Spiral_Rect_STD.png
|
||||
:align: center
|
||||
:width: 600px
|
||||
|
||||
.. autoclass:: mxpic.components.primitives.spiral.Spiral_Rect_STD
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
```
|
||||
|
||||
## spiral
|
||||
|
||||
```{eval-rst}
|
||||
.. image:: spiral.png
|
||||
:align: center
|
||||
:width: 600px
|
||||
|
||||
.. autoclass:: mxpic.components.primitives.spiral.spiral
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
```
|
||||
|
||||
## spiral_circle
|
||||
|
||||
```{eval-rst}
|
||||
.. image:: spiral_circle.png
|
||||
:align: center
|
||||
:width: 600px
|
||||
|
||||
.. autoclass:: mxpic.components.primitives.spiral.spiral_circle
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
```
|
||||
|
||||
## spiral_rectangle
|
||||
|
||||
```{eval-rst}
|
||||
.. image:: spiral_rectangle.png
|
||||
:align: center
|
||||
:width: 600px
|
||||
|
||||
.. autoclass:: mxpic.components.primitives.spiral.spiral_rectangle
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
```
|
||||
|
||||
|
After Width: | Height: | Size: 318 KiB |