From 98ee792b7444cfacec88a0962c0ec75ce6f33882 Mon Sep 17 00:00:00 2001 From: Masaya Kataoka Date: Tue, 15 Oct 2024 16:09:27 +0900 Subject: [PATCH 1/2] Feature/add sensor computer circuit (#355) * add start script Signed-off-by: Masaya Kataoka * add BOM plugin Signed-off-by: Masaya Kataoka * enable use x11 forwarding Signed-off-by: Masaya Kataoka * update description Signed-off-by: Masaya Kataoka * update Dockerfile Signed-off-by: Masaya Kataoka * add 3rd party directory Signed-off-by: Masaya Kataoka * add entrypoint.sh Signed-off-by: Masaya Kataoka * add teensy library Signed-off-by: Masaya Kataoka * add teensy Signed-off-by: Masaya Kataoka * enable run kibot Signed-off-by: Masaya Kataoka * update kibot.yaml Signed-off-by: Masaya Kataoka * enable save schematic in SVG Signed-off-by: Masaya Kataoka * rename project Signed-off-by: Masaya Kataoka * add SVG schematic Signed-off-by: Masaya Kataoka * enable show schematics Signed-off-by: Masaya Kataoka * fix dashboard Signed-off-by: Masaya Kataoka * add depends Signed-off-by: Masaya Kataoka * use uv Signed-off-by: Masaya Kataoka * fix typo Signed-off-by: Masaya Kataoka --------- Signed-off-by: Masaya Kataoka --- .github/workflows/docker/kicad/Dockerfile | 45 +- .github/workflows/docker/kicad/README.md | 2 - .github/workflows/docker/kicad/entrypoint.sh | 3 + .github/workflows/docker/kicad/fp-lib-table | 146 + .github/workflows/docker/kicad/kibot.yaml | 10 + .github/workflows/docker/kicad/sym-lib-table | 225 + .github/workflows/document.yaml | 8 +- .gitignore | 6 +- .python-version | 1 + .../Run.bat | 73 + .../__init__.py | 58 + .../core/__init__.py | 0 .../core/config.py | 483 + .../core/fontparser.py | 52 + .../core/ibom.py | 365 + .../core/lzstring.py | 304 + .../core/newstroke_font.py | 11361 ++++++ .../core/units.py | 192 + .../dialog/__init__.py | 1 + .../dialog/bitmaps/btn-arrow-down.png | Bin 0 -> 386 bytes .../dialog/bitmaps/btn-arrow-up.png | Bin 0 -> 382 bytes .../dialog/bitmaps/btn-minus.png | Bin 0 -> 137 bytes .../dialog/bitmaps/btn-plus.png | Bin 0 -> 165 bytes .../dialog/bitmaps/btn-question.png | Bin 0 -> 460 bytes .../dialog/dialog_base.py | 578 + .../dialog/settings_dialog.py | 406 + .../ecad/__init__.py | 41 + .../ecad/common.py | 251 + .../ecad/easyeda.py | 493 + .../ecad/fusion_eagle.py | 920 + .../ecad/genericjson.py | 167 + .../ecad/kicad.py | 843 + .../ecad/kicad_extra/__init__.py | 59 + .../ecad/kicad_extra/netlistparser.py | 59 + .../ecad/kicad_extra/parser_base.py | 26 + .../ecad/kicad_extra/sexpressions.py | 32 + .../ecad/kicad_extra/xmlparser.py | 42 + .../ecad/schema/genericjsonpcbdata_v1.schema | 638 + .../ecad/svgpath.py | 538 + .../errors.py | 16 + .../generate_interactive_bom.py | 84 + .../i18n/language_en.bat | 12 + .../i18n/language_zh.bat | 17 + .../icon.png | Bin 0 -> 820 bytes .../version.py | 29 + .../web/ibom.css | 887 + .../web/ibom.html | 337 + .../web/ibom.js | 1294 + .../web/lz-string.js | 10 + .../web/pep.js | 43 + .../web/render.js | 1075 + .../web/split.js | 6 + .../web/table-util.js | 371 + .../web/user-file-examples/user.css | 1 + .../web/user-file-examples/user.js | 4 + .../web/user-file-examples/userfooter.html | 5 + .../web/user-file-examples/userheader.html | 5 + .../web/user.css | 5 + .../web/user.js | 6 + .../web/util.js | 638 + .../icon.png | Bin 0 -> 2105 bytes circuits/computer_sensor_board/.gitignore | 1 + ...omputer_sensor_board-2024-10-14_142016.zip | Bin 0 -> 15126 bytes .../computer_sensor_board.kicad_pcb | 2 + .../computer_sensor_board.kicad_prl | 83 + .../computer_sensor_board.kicad_pro | 392 + .../computer_sensor_board.kicad_sch | 4794 +++ circuits/run_kibot.sh | 6 + circuits/start_kicad.sh | 16 +- .../computer_sensor_board.md | 12 + .../computer_sensor_board-schematic.svg | 30902 ++++++++++++++++ docs/mkdocs.yml | 3 + hello.py | 6 + pyproject.toml | 20 + uv.lock | 924 + 75 files changed, 60407 insertions(+), 27 deletions(-) create mode 100644 .github/workflows/docker/kicad/entrypoint.sh create mode 100644 .github/workflows/docker/kicad/fp-lib-table create mode 100644 .github/workflows/docker/kicad/kibot.yaml create mode 100644 .github/workflows/docker/kicad/sym-lib-table create mode 100644 .python-version create mode 100644 circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/Run.bat create mode 100644 circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/__init__.py create mode 100644 circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/core/__init__.py create mode 100644 circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/core/config.py create mode 100644 circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/core/fontparser.py create mode 100644 circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/core/ibom.py create mode 100644 circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/core/lzstring.py create mode 100644 circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/core/newstroke_font.py create mode 100644 circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/core/units.py create mode 100644 circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/dialog/__init__.py create mode 100644 circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/dialog/bitmaps/btn-arrow-down.png create mode 100644 circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/dialog/bitmaps/btn-arrow-up.png create mode 100644 circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/dialog/bitmaps/btn-minus.png create mode 100644 circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/dialog/bitmaps/btn-plus.png create mode 100644 circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/dialog/bitmaps/btn-question.png create mode 100644 circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/dialog/dialog_base.py create mode 100644 circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/dialog/settings_dialog.py create mode 100644 circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/ecad/__init__.py create mode 100644 circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/ecad/common.py create mode 100644 circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/ecad/easyeda.py create mode 100644 circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/ecad/fusion_eagle.py create mode 100644 circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/ecad/genericjson.py create mode 100644 circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/ecad/kicad.py create mode 100644 circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/ecad/kicad_extra/__init__.py create mode 100644 circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/ecad/kicad_extra/netlistparser.py create mode 100644 circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/ecad/kicad_extra/parser_base.py create mode 100644 circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/ecad/kicad_extra/sexpressions.py create mode 100644 circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/ecad/kicad_extra/xmlparser.py create mode 100644 circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/ecad/schema/genericjsonpcbdata_v1.schema create mode 100644 circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/ecad/svgpath.py create mode 100644 circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/errors.py create mode 100644 circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/generate_interactive_bom.py create mode 100644 circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/i18n/language_en.bat create mode 100644 circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/i18n/language_zh.bat create mode 100644 circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/icon.png create mode 100644 circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/version.py create mode 100644 circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/web/ibom.css create mode 100644 circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/web/ibom.html create mode 100644 circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/web/ibom.js create mode 100644 circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/web/lz-string.js create mode 100644 circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/web/pep.js create mode 100644 circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/web/render.js create mode 100644 circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/web/split.js create mode 100644 circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/web/table-util.js create mode 100644 circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/web/user-file-examples/user.css create mode 100644 circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/web/user-file-examples/user.js create mode 100644 circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/web/user-file-examples/userfooter.html create mode 100644 circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/web/user-file-examples/userheader.html create mode 100644 circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/web/user.css create mode 100644 circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/web/user.js create mode 100644 circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/web/util.js create mode 100644 circuits/3rdparty/resources/org_openscopeproject_InteractiveHtmlBom/icon.png create mode 100644 circuits/computer_sensor_board/.gitignore create mode 100644 circuits/computer_sensor_board/computer_sensor_board/computer_sensor_board-backups/computer_sensor_board-2024-10-14_142016.zip create mode 100644 circuits/computer_sensor_board/computer_sensor_board/computer_sensor_board.kicad_pcb create mode 100644 circuits/computer_sensor_board/computer_sensor_board/computer_sensor_board.kicad_prl create mode 100644 circuits/computer_sensor_board/computer_sensor_board/computer_sensor_board.kicad_pro create mode 100644 circuits/computer_sensor_board/computer_sensor_board/computer_sensor_board.kicad_sch create mode 100644 circuits/run_kibot.sh create mode 100644 docs/docs/circuit/computer_sensor_board/computer_sensor_board.md create mode 100644 docs/docs/circuit/computer_sensor_board/kibot_output/schematics/computer_sensor_board-schematic.svg create mode 100644 hello.py create mode 100644 pyproject.toml create mode 100644 uv.lock diff --git a/.github/workflows/docker/kicad/Dockerfile b/.github/workflows/docker/kicad/Dockerfile index 8adde096f..5ff6d482a 100644 --- a/.github/workflows/docker/kicad/Dockerfile +++ b/.github/workflows/docker/kicad/Dockerfile @@ -1,18 +1,37 @@ -FROM linuxserver/kicad:8.0.1 +FROM ubuntu:22.04 +ENV DEBIAN_FRONTEND=noninteractive +RUN apt-get update && apt-get install -y \ + software-properties-common \ + wget \ + curl \ + && add-apt-repository --yes ppa:kicad/kicad-8.0-releases \ + && apt-get update && apt-get install -y \ + python3-pip \ + kicad \ + xvfb \ + x11-apps \ + unzip \ + git \ + && apt-get clean -ENV KICAD8_3DMODEL_DIR="/usr/share/kicad/3dmodels/" -ENV KICAD8_FOOTPRINT_DIR="/usr/share/kicad/footprints/" -ENV KICAD8_SYMBOL_DIR="/usr/share/kicad/symbols/" +RUN pip3 install kibot --no-compile -RUN mkdir kicad_libraries -WORKDIR /kicad_libraries -ADD https://github.com/ncarandini/KiCad-RP-Pico/archive/refs/heads/main.zip KiCad-RP-Pico.zip -RUN unzip KiCad-RP-Pico.zip +ADD entrypoint.sh / +RUN chmod +x /entrypoint.sh -RUN cp -r "/kicad_libraries/KiCad-RP-Pico-main/RP-Pico Libraries/Pico.wrl" ${KICAD8_3DMODEL_DIR} -RUN cp -r "/kicad_libraries/KiCad-RP-Pico-main/RP-Pico Libraries/MCU_RaspberryPi_and_Boards.pretty" ${KICAD8_FOOTPRINT_DIR} -RUN cp -r "/kicad_libraries/KiCad-RP-Pico-main/RP-Pico Libraries/MCU_RaspberryPi_and_Boards.kicad_sym" ${KICAD8_SYMBOL_DIR} +WORKDIR /usr/share/kicad/footprints +RUN git clone https://github.com/XenGi/teensy.pretty.git -WORKDIR / +WORKDIR /usr/share/kicad/symbols +RUN git clone https://github.com/XenGi/teensy_library.git +RUN kicad-cli sym upgrade teensy_library/teensy.lib -o teensy.kicad_sym -COPY autostart /defaults/autostart +# RUN mkdir -p ~/.config/kicad/8.0 +COPY fp-lib-table /root/.config/kicad/8.0 +COPY sym-lib-table /root/.config/kicad/8.0 + +WORKDIR /workspace + +COPY kibot.yaml /workspace/kibot.yaml + +ENTRYPOINT ["/entrypoint.sh"] diff --git a/.github/workflows/docker/kicad/README.md b/.github/workflows/docker/kicad/README.md index 06891e32e..cfad095ff 100644 --- a/.github/workflows/docker/kicad/README.md +++ b/.github/workflows/docker/kicad/README.md @@ -22,6 +22,4 @@ cd ouxt_automation/circuits sh start_kicad.sh ``` -Open [http://localhost:3000/](http://localhost:3000/) - ![kicad](https://raw.githubusercontent.com/OUXT-Polaris/ouxt_automation/refs/heads/master/.github/workflows/docker/kicad/kicad.png) diff --git a/.github/workflows/docker/kicad/entrypoint.sh b/.github/workflows/docker/kicad/entrypoint.sh new file mode 100644 index 000000000..5fc44481d --- /dev/null +++ b/.github/workflows/docker/kicad/entrypoint.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +exec "$@" diff --git a/.github/workflows/docker/kicad/fp-lib-table b/.github/workflows/docker/kicad/fp-lib-table new file mode 100644 index 000000000..6085eaa68 --- /dev/null +++ b/.github/workflows/docker/kicad/fp-lib-table @@ -0,0 +1,146 @@ +(fp_lib_table + (lib (name Audio_Module)(type Kicad)(uri ${KICAD8_FOOTPRINT_DIR}/Audio_Module.pretty)(options "")(descr "Audio Module footprints")) + (lib (name Battery)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Battery.pretty)(options "")(descr "Battery and battery holder footprints")) + (lib (name Button_Switch_Keyboard)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Button_Switch_Keyboard.pretty)(options "")(descr "Buttons and switches for keyboard applications")) + (lib (name Button_Switch_SMD)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Button_Switch_SMD.pretty)(options "")(descr "Buttons and switches, surface mount")) + (lib (name Button_Switch_THT)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Button_Switch_THT.pretty)(options "")(descr "Buttons and switches, through hole")) + (lib (name Buzzer_Beeper)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Buzzer_Beeper.pretty)(options "")(descr "Audio signalling devices")) + (lib (name Calibration_Scale)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Calibration_Scale.pretty)(options "")(descr "Scales and grids intended for calibration and measurement")) + (lib (name Capacitor_SMD)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Capacitor_SMD.pretty)(options "")(descr "Capacitor, surface mount")) + (lib (name Capacitor_THT)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Capacitor_THT.pretty)(options "")(descr "Capacitor, through hole")) + (lib (name Capacitor_Tantalum_SMD)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Capacitor_Tantalum_SMD.pretty)(options "")(descr "Tantalum Capacitor, surface mount")) + (lib (name Connector)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Connector.pretty)(options "")(descr "Generic/unsorted connector footprints")) + (lib (name Connector_AMASS)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Connector_AMASS.pretty)(options "")(descr "AMASS connector footprints")) + (lib (name Connector_Amphenol)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Connector_Amphenol.pretty)(options "")(descr "Amphenol LTW connector footprints")) + (lib (name Connector_Audio)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Connector_Audio.pretty)(options "")(descr "Audio connector footprints")) + (lib (name Connector_BarrelJack)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Connector_BarrelJack.pretty)(options "")(descr "(DC) barrel jack connector footprints")) + (lib (name Connector_Card)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Connector_Card.pretty)(options "")(descr "Card and card holder footprints")) + (lib (name Connector_Coaxial)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Connector_Coaxial.pretty)(options "")(descr "Coaxial and RF connector footprints")) + (lib (name Connector_DIN)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Connector_DIN.pretty)(options "")(descr "DIN connector footprints")) + (lib (name Connector_Dsub)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Connector_Dsub.pretty)(options "")(descr "DSub connector footprints")) + (lib (name Connector_FFC-FPC)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Connector_FFC-FPC.pretty)(options "")(descr "FFC (Flexible Flat Cable) and FPC (Flexible Printed Circuit) connector footprints")) + (lib (name Connector_Harting)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Connector_Harting.pretty)(options "")(descr "Harting connector footprints")) + (lib (name Connector_Harwin)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Connector_Harwin.pretty)(options "")(descr "Harwin connector footprints")) + (lib (name Connector_Hirose)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Connector_Hirose.pretty)(options "")(descr "Hirose connector footprints")) + (lib (name Connector_IDC)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Connector_IDC.pretty)(options "")(descr "IDC connector footprints")) + (lib (name Connector_JAE)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Connector_JAE.pretty)(options "")(descr "JAE connector footprints")) + (lib (name Connector_JST)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Connector_JST.pretty)(options "")(descr "JST connector footprints www.jst.com")) + (lib (name Connector_Molex)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Connector_Molex.pretty)(options "")(descr "Molex connector footprints www.molex.com")) + (lib (name Connector_PCBEdge)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Connector_PCBEdge.pretty)(options "")(descr "PCB edge connectors (e.g. PCI, ISA, PCIe, ...)")) + (lib (name Connector_Pin)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Connector_Pin.pretty)(options "")(descr "Single (solder) pin conectors")) + (lib (name Connector_PinHeader_1.00mm)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Connector_PinHeader_1.00mm.pretty)(options "")(descr "Pin headers, 1.0mm pitch")) + (lib (name Connector_PinHeader_1.27mm)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Connector_PinHeader_1.27mm.pretty)(options "")(descr "Pin headers, 1.27mm pitch")) + (lib (name Connector_PinHeader_2.00mm)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Connector_PinHeader_2.00mm.pretty)(options "")(descr "Pin headers, 2.0mm pitch")) + (lib (name Connector_PinHeader_2.54mm)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Connector_PinHeader_2.54mm.pretty)(options "")(descr "Pin headers, 2.54mm pitch")) + (lib (name Connector_PinSocket_1.00mm)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Connector_PinSocket_1.00mm.pretty)(options "")(descr "Pin sockets, 1.00mm pitch")) + (lib (name Connector_PinSocket_1.27mm)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Connector_PinSocket_1.27mm.pretty)(options "")(descr "Pin sockets, 1.27mm pitch")) + (lib (name Connector_PinSocket_2.00mm)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Connector_PinSocket_2.00mm.pretty)(options "")(descr "Pin sockets, 2.0mm pitch")) + (lib (name Connector_PinSocket_2.54mm)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Connector_PinSocket_2.54mm.pretty)(options "")(descr "Pin sockets, 2.54mm pitch")) + (lib (name Connector_Phoenix_MC)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Connector_Phoenix_MC.pretty)(options "")(descr "Phoenix MC connector footprints")) + (lib (name Connector_Phoenix_MC_HighVoltage)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Connector_Phoenix_MC_HighVoltage.pretty)(options "")(descr "Phoenix high voltage (320V, 5.08mm pitch) MC connector footprints")) + (lib (name Connector_Phoenix_MSTB)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Connector_Phoenix_MSTB.pretty)(options "")(descr "Phoenix MSTB connector footprints")) + (lib (name Connector_Phoenix_GMSTB)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Connector_Phoenix_GMSTB.pretty)(options "")(descr "Phoenix GMSTB series (high voltage MSTB) connector footprints")) + (lib (name Connector_Phoenix_SPT)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Connector_Phoenix_SPT.pretty)(options "")(descr "Phoenix SPT connector footprints")) + (lib (name Connector_Samtec)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Connector_Samtec.pretty)(options "")(descr "Samtec connector footprints")) + (lib (name Connector_Samtec_HLE_SMD)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Connector_Samtec_HLE_SMD.pretty)(options "")(descr "Samtec surface mount HLE series connector footprints")) + (lib (name Connector_Samtec_HLE_THT)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Connector_Samtec_HLE_THT.pretty)(options "")(descr "Samtec through hole HLE series connector footprints")) + (lib (name Connector_Samtec_HPM_THT)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Connector_Samtec_HPM_THT.pretty)(options "")(descr "Samtec through hole HPM series power header footprints")) + (lib (name Connector_Samtec_HSEC8)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Connector_Samtec_HSEC8.pretty)(options "")(descr "Samtec HSEC8 0.8mm high speed card edge connector footprints")) + (lib (name Connector_Samtec_MicroMate)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Connector_Samtec_MicroMate.pretty)(options "")(descr "Samtec MicroMate discrete wire terminal strips, 1.0mm pitch")) + (lib (name Connector_Samtec_MicroPower)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Connector_Samtec_MicroPower.pretty)(options "")(descr "Samtec 2.00mm mPOWER Ultra Micro Power connector footprints")) + (lib (name Connector_RJ)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Connector_RJ.pretty)(options "")(descr "Registered Jack (RJ) connector footprints (e.g. RJ11, RJ45, ...)")) + (lib (name Connector_SATA_SAS)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Connector_SATA_SAS.pretty)(options "")(descr "SATA/SAS connector footprints")) + (lib (name Connector_Stocko)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Connector_Stocko.pretty)(options "")(descr "Stocko connector footprints")) + (lib (name Connector_TE-Connectivity)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Connector_TE-Connectivity.pretty)(options "")(descr "Footprints for connectors by TE Connectivity")) + (lib (name Connector_USB)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Connector_USB.pretty)(options "")(descr "USB connector footprints")) + (lib (name Connector_Video)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Connector_Video.pretty)(options "")(descr "Video connector footprints like DVI and HDMI")) + (lib (name Connector_Wago)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Connector_Wago.pretty)(options "")(descr "Wago connector footprints")) + (lib (name Connector_Wire)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Connector_Wire.pretty)(options "")(descr "Footprints for solder wire pads")) + (lib (name Connector_Wuerth)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Connector_Wuerth.pretty)(options "")(descr "Wuerth connector footprints")) + (lib (name Converter_ACDC)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Converter_ACDC.pretty)(options "")(descr "AC/DC converter footprints")) + (lib (name Converter_DCDC)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Converter_DCDC.pretty)(options "")(descr "DC/DC converter footprints")) + (lib (name Crystal)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Crystal.pretty)(options "")(descr "Crystal footprints")) + (lib (name Diode_SMD)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Diode_SMD.pretty)(options "")(descr "Diode footprints, surface mount")) + (lib (name Diode_THT)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Diode_THT.pretty)(options "")(descr "Diode footprints, through hole")) + (lib (name Display_7Segment)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Display_7Segment.pretty)(options "")(descr "Seven segment Display")) + (lib (name Display)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Display.pretty)(options "")(descr "Display modules")) + (lib (name Ferrite_THT)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Ferrite_THT.pretty)(options "")(descr "Ferrite bead, through hole")) + (lib (name Fiducial)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Fiducial.pretty)(options "")(descr "Fiducial markings")) + (lib (name Filter)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Filter.pretty)(options "")(descr "Filter footprints")) + (lib (name Fuse)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Fuse.pretty)(options "")(descr "Fuse and fuse holder footprints")) + (lib (name Heatsink)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Heatsink.pretty)(options "")(descr "Heatsinks and thermal products")) + (lib (name Inductor_SMD)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Inductor_SMD.pretty)(options "")(descr "Inductor footprints, surface mount")) + (lib (name Inductor_SMD_Wurth)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Inductor_SMD_Wurth.pretty)(options "")(descr "Würth Elektronik inductor footprints, surface mount")) + (lib (name Inductor_THT)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Inductor_THT.pretty)(options "")(descr "Inductor footprints, through hole")) + (lib (name Inductor_THT_Wurth)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Inductor_THT_Wurth.pretty)(options "")(descr "Würth Elektronik inductor footprints, through hole")) + (lib (name Jumper)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Jumper.pretty)(options "")(descr "Jumpers, solder jumpers, ... footprints")) + (lib (name LED_SMD)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/LED_SMD.pretty)(options "")(descr "Light emitting diodes (LED), surface mount")) + (lib (name LED_THT)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/LED_THT.pretty)(options "")(descr "Light emitting diodes (LED), through hole")) + (lib (name Module)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Module.pretty)(options "")(descr "Footprints for SoM (System on Module)")) + (lib (name Motors)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Motors.pretty)(options "")(descr "Footprints for Motors")) + (lib (name MountingHole)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/MountingHole.pretty)(options "")(descr "Mechanical fasteners")) + (lib (name Mounting_Wuerth)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Mounting_Wuerth.pretty)(options "")(descr "Mechanical fasteners by wuerth electronics")) + (lib (name MountingEquipment)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/MountingEquipment.pretty)(options "")(descr "Mechanical parts")) + (lib (name NetTie)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/NetTie.pretty)(options "")(descr "Net ties")) + (lib (name OptoDevice)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/OptoDevice.pretty)(options "")(descr "Optical devices (light sensors, opto isolators/interrupters, laser diodes, fiber optical components, lightpipes, lenses ...)")) + (lib (name Oscillator)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Oscillator.pretty)(options "")(descr "Footprints for oscillator devices")) + (lib (name Package_BGA)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Package_BGA.pretty)(options "")(descr "Ball Grid Array (BGA)")) + (lib (name Package_CSP)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Package_CSP.pretty)(options "")(descr "Chip Scale Packages (CSP)")) + (lib (name Package_DFN_QFN)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Package_DFN_QFN.pretty)(options "")(descr "Surface mount IC packages, DFN / LGA / QFN")) + (lib (name Package_DIP)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Package_DIP.pretty)(options "")(descr "Through hole IC packages, DIP")) + (lib (name Package_DirectFET)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Package_DirectFET.pretty)(options "")(descr "DirectFET packages from International Rectifier")) + (lib (name Package_LCC)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Package_LCC.pretty)(options "")(descr "Leaded Chip Carriers (LCC)")) + (lib (name Package_LGA)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Package_LGA.pretty)(options "")(descr "Land Grid Array (LGA)")) + (lib (name Package_QFP)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Package_QFP.pretty)(options "")(descr "Quad Flat Package (QFP)")) + (lib (name Package_SIP)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Package_SIP.pretty)(options "")(descr "Single Inline Package(SIP)")) + (lib (name Package_SO)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Package_SO.pretty)(options "")(descr "Small Outline Integrated Circuits (SOIC, SSOP, xSOP, xSO)")) + (lib (name Package_SO_J-Lead)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Package_SO_J-Lead.pretty)(options "")(descr "Small Outline Integrated Circuits J-Lead")) + (lib (name Package_SON)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Package_SON.pretty)(options "")(descr "Small Outline No-Lead (SON)")) + (lib (name Package_TO_SOT_SMD)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Package_TO_SOT_SMD.pretty)(options "")(descr "Surface mount transistor packages")) + (lib (name Package_TO_SOT_THT)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Package_TO_SOT_THT.pretty)(options "")(descr "Through hole transistor packages")) + (lib (name Potentiometer_SMD)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Potentiometer_SMD.pretty)(options "")(descr "Potentiometer footprints, surface mount (SMD)")) + (lib (name Potentiometer_THT)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Potentiometer_THT.pretty)(options "")(descr "Potentiometer footprints, through hole (THT)")) + (lib (name Relay_SMD)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Relay_SMD.pretty)(options "")(descr "Surface mount relay packages")) + (lib (name Relay_THT)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Relay_THT.pretty)(options "")(descr "Through hole relay packages")) + (lib (name Resistor_SMD)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Resistor_SMD.pretty)(options "")(descr "Resistor footprints, surface mount (SMD)")) + (lib (name Resistor_THT)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Resistor_THT.pretty)(options "")(descr "Resistor footprints, through hole (THT)")) + (lib (name RF)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/RF.pretty)(options "")(descr "Specialized footprints for RF components that don't fit in the other RF libraries.")) + (lib (name RF_Antenna)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/RF_Antenna.pretty)(options "")(descr "Radio-frequency / wireless antenna footprints")) + (lib (name RF_Converter)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/RF_Converter.pretty)(options "")(descr "Specialized footprints for RF signal converters (Like Attenuators, Baluns, Mixers, Couplers, etc.)")) + (lib (name RF_GPS)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/RF_GPS.pretty)(options "")(descr "GNSS footprints")) + (lib (name RF_GSM)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/RF_GSM.pretty)(options "")(descr "GSM Modules footprints")) + (lib (name RF_Mini-Circuits)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/RF_Mini-Circuits.pretty)(options "")(descr "Footprints for Mini-Circuits RF parts.")) + (lib (name RF_Module)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/RF_Module.pretty)(options "")(descr "Radio-frequency / wireless modules")) + (lib (name RF_WiFi)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/RF_WiFi.pretty)(options "")(descr "WiFi modules")) + (lib (name RF_Shielding)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/RF_Shielding.pretty)(options "")(descr "Specialied footprints for EMI shields and covers")) + (lib (name Rotary_Encoder)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Rotary_Encoder.pretty)(options "")(descr "Rotary Encoder Footprints")) + (lib (name Sensor)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Sensor.pretty)(options "")(descr "Specialized footprints for multi-function sensors")) + (lib (name Sensor_Audio)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Sensor_Audio.pretty)(options "")(descr "Specialized footprints for audio sensors")) + (lib (name Sensor_Distance)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Sensor_Distance.pretty)(options "")(descr "Specialized footprints for distance sensors")) + (lib (name Sensor_Current)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Sensor_Current.pretty)(options "")(descr "Specialized footprints for current sensors")) + (lib (name Sensor_Humidity)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Sensor_Humidity.pretty)(options "")(descr "Specialized footprints for humidity sensors")) + (lib (name Sensor_Motion)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Sensor_Motion.pretty)(options "")(descr "Specialized footprints for motion sensors")) + (lib (name Sensor_Pressure)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Sensor_Pressure.pretty)(options "")(descr "Specialized footprints for pressure sensors")) + (lib (name Sensor_Voltage)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Sensor_Voltage.pretty)(options "")(descr "Specialized footprints for voltage sensors")) + (lib (name Socket)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Socket.pretty)(options "")(descr "Sockets")) + (lib (name Symbol)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Symbol.pretty)(options "")(descr "PCB symbols")) + (lib (name TerminalBlock_Altech)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/TerminalBlock_Altech.pretty)(options "")(descr "Altech terminal block footprints")) + (lib (name TerminalBlock)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/TerminalBlock.pretty)(options "")(descr "Footprints for terminal blocks that do not have their own manufacturer specific library.")) + (lib (name TerminalBlock_4Ucon)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/TerminalBlock_4Ucon.pretty)(options "")(descr "4UCON terminal blocks")) + (lib (name TerminalBlock_Dinkle)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/TerminalBlock_Dinkle.pretty)(options "")(descr "Dinkle terminal blocks")) + (lib (name TerminalBlock_MetzConnect)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/TerminalBlock_MetzConnect.pretty)(options "")(descr "Metz Connect terminal blocks")) + (lib (name TerminalBlock_Philmore)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/TerminalBlock_Philmore.pretty)(options "")(descr "Philmore terminal blocks")) + (lib (name TerminalBlock_Phoenix)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/TerminalBlock_Phoenix.pretty)(options "")(descr "Phoenix Contact terminal blocks")) + (lib (name TerminalBlock_RND)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/TerminalBlock_RND.pretty)(options "")(descr "RND terminal blocks")) + (lib (name TerminalBlock_TE-Connectivity)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/TerminalBlock_TE-Connectivity.pretty)(options "")(descr "TE Connectivity terminal blocks")) + (lib (name TerminalBlock_WAGO)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/TerminalBlock_WAGO.pretty)(options "")(descr "WAGO terminal blocks")) + (lib (name TerminalBlock_Wuerth)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/TerminalBlock_Wuerth.pretty)(options "")(descr "Wuerth Elektronik terminal blocks")) + (lib (name TestPoint)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/TestPoint.pretty)(options "")(descr "Test points, measurement points, probe connection points")) + (lib (name Transformer_SMD)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Transformer_SMD.pretty)(options "")(descr "Surface mount transformers")) + (lib (name Transformer_THT)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Transformer_THT.pretty)(options "")(descr "Through hole transformers")) + (lib (name Transistor_Power)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Transistor_Power.pretty)(options "")(descr "Power Transistors")) + (lib (name Transistor_Power_Module)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Transistor_Power_Module.pretty)(options "")(descr "Transistor Power Modules")) + (lib (name Valve)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Valve.pretty)(options "")(descr "Valve")) + (lib (name Varistor)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/Varistor.pretty)(options "")(descr "Varistor")) + (lib (name Teensy)(type KiCad)(uri ${KICAD8_FOOTPRINT_DIR}/teensy.pretty)(options "")(descr "Teensy microcontroller")) +) diff --git a/.github/workflows/docker/kicad/kibot.yaml b/.github/workflows/docker/kicad/kibot.yaml new file mode 100644 index 000000000..27c37203f --- /dev/null +++ b/.github/workflows/docker/kicad/kibot.yaml @@ -0,0 +1,10 @@ +kibot: + version: 1 + +preflight: + erc: true + +outputs: + - name: print schematic + type: svg_sch_print + dir: /workspace/schematics diff --git a/.github/workflows/docker/kicad/sym-lib-table b/.github/workflows/docker/kicad/sym-lib-table new file mode 100644 index 000000000..88fdfc452 --- /dev/null +++ b/.github/workflows/docker/kicad/sym-lib-table @@ -0,0 +1,225 @@ +(sym_lib_table + (lib (name "4xxx")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/4xxx.kicad_sym")(options "")(descr "4xxx series symbols")) + (lib (name "4xxx_IEEE")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/4xxx_IEEE.kicad_sym")(options "")(descr "4xxx series IEEE symbols")) + (lib (name "74xGxx")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/74xGxx.kicad_sym")(options "")(descr "74xGxx symbols")) + (lib (name "74xx")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/74xx.kicad_sym")(options "")(descr "74xx symbols")) + (lib (name "74xx_IEEE")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/74xx_IEEE.kicad_sym")(options "")(descr "74xx series IEEE symbols")) + (lib (name "Amplifier_Audio")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Amplifier_Audio.kicad_sym")(options "")(descr "Amplifier for audio applications")) + (lib (name "Amplifier_Buffer")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Amplifier_Buffer.kicad_sym")(options "")(descr "Buffer amplifiers")) + (lib (name "Amplifier_Current")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Amplifier_Current.kicad_sym")(options "")(descr "Amplifiers for current sensors (shunt)")) + (lib (name "Amplifier_Difference")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Amplifier_Difference.kicad_sym")(options "")(descr "Amplifiers for analog differential signals")) + (lib (name "Amplifier_Operational")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Amplifier_Operational.kicad_sym")(options "")(descr "General operational amplifiers")) + (lib (name "Amplifier_Instrumentation")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Amplifier_Instrumentation.kicad_sym")(options "")(descr "Instrumentation amplitifers")) + (lib (name "Amplifier_Video")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Amplifier_Video.kicad_sym")(options "")(descr "Video amplifiers")) + (lib (name "Analog")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Analog.kicad_sym")(options "")(descr "Miscellaneous analog devices")) + (lib (name "Analog_ADC")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Analog_ADC.kicad_sym")(options "")(descr "Analog to digital converters")) + (lib (name "Analog_DAC")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Analog_DAC.kicad_sym")(options "")(descr "Digital to analog converters")) + (lib (name "Analog_Switch")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Analog_Switch.kicad_sym")(options "")(descr "Analog switches")) + (lib (name "Audio")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Audio.kicad_sym")(options "")(descr "Audio devices")) + (lib (name "Battery_Management")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Battery_Management.kicad_sym")(options "")(descr "Battery management ICs")) + (lib (name "Buffer")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Buffer.kicad_sym")(options "")(descr "High-speed clock/data buffer ICs")) + (lib (name "Comparator")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Comparator.kicad_sym")(options "")(descr "Comparator symbols")) + (lib (name "Connector")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Connector.kicad_sym")(options "")(descr "Connector symbols (Examples: Terminal Block, D-SUB, DIN, USB...)")) + (lib (name "Connector_Audio")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Connector_Audio.kicad_sym")(options "")(descr "Audio connector symbols")) + (lib (name "Connector_Generic")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Connector_Generic.kicad_sym")(options "")(descr "Generic connector symbols")) + (lib (name "Connector_Generic_MountingPin")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Connector_Generic_MountingPin.kicad_sym")(options "")(descr "Generic connectors with mechanical mounting pin")) + (lib (name "Connector_Generic_Shielded")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Connector_Generic_Shielded.kicad_sym")(options "")(descr "Generic shielded connector symbols")) + (lib (name "Converter_ACDC")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Converter_ACDC.kicad_sym")(options "")(descr "AC to DC converter modules")) + (lib (name "Converter_DCDC")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Converter_DCDC.kicad_sym")(options "")(descr "DC to DC converter modules")) + (lib (name "CPLD_Altera")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/CPLD_Altera.kicad_sym")(options "")(descr "Altera CPLD symbols")) + (lib (name "CPLD_Microchip")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/CPLD_Microchip.kicad_sym")(options "")(descr "Microchip CPLD symbols")) + (lib (name "CPLD_Renesas")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/CPLD_Renesas.kicad_sym")(options "")(descr "Renesas CPLD symbols")) + (lib (name "CPLD_Xilinx")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/CPLD_Xilinx.kicad_sym")(options "")(descr "Xilinx CPLD symbols")) + (lib (name "CPU")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/CPU.kicad_sym")(options "")(descr "Central processor unit (CPU) symbols, assorted")) + (lib (name "CPU_NXP_6800")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/CPU_NXP_6800.kicad_sym")(options "")(descr "NXP (formerly Motorola) 6800 CPUs")) + (lib (name "CPU_NXP_68000")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/CPU_NXP_68000.kicad_sym")(options "")(descr "NXP (formerly Motorola) 68000 CPUs")) + (lib (name "CPU_NXP_IMX")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/CPU_NXP_IMX.kicad_sym")(options "")(descr "NXP IMX CPUs")) + (lib (name "CPU_PowerPC")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/CPU_PowerPC.kicad_sym")(options "")(descr "PowerPC-based CPUs")) + (lib (name "Device")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Device.kicad_sym")(options "")(descr "Generic symbols for common devices")) + (lib (name "Diode")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Diode.kicad_sym")(options "")(descr "Diodes")) + (lib (name "Diode_Bridge")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Diode_Bridge.kicad_sym")(options "")(descr "Diode Bridges/Rectifiers")) + (lib (name "Diode_Laser")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Diode_Laser.kicad_sym")(options "")(descr "Laser diodes")) + (lib (name "Display_Character")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Display_Character.kicad_sym")(options "")(descr "Character displays. (n-Segment, dot-matrix, ...)")) + (lib (name "Display_Graphic")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Display_Graphic.kicad_sym")(options "")(descr "Graphic displays. (Pixel-based color or monochrome displays.)")) + (lib (name "Driver_Display")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Driver_Display.kicad_sym")(options "")(descr "Drivers for displays. (For graphic and character based displays.)")) + (lib (name "Driver_FET")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Driver_FET.kicad_sym")(options "")(descr "MOSFET and gate drivers")) + (lib (name "Driver_Haptic")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Driver_Haptic.kicad_sym")(options "")(descr "Haptic drivers for solenoids, voice coils, LRAs, etc.")) + (lib (name "Driver_LED")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Driver_LED.kicad_sym")(options "")(descr "LED drivers")) + (lib (name "Driver_Motor")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Driver_Motor.kicad_sym")(options "")(descr "Integrated motor driver and controller ICs")) + (lib (name "Driver_Relay")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Driver_Relay.kicad_sym")(options "")(descr "Relay drivers and controllers")) + (lib (name "Driver_TEC")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Driver_TEC.kicad_sym")(options "")(descr "Thermoelectric cooler (Peltier) drivers and controllers")) + (lib (name "DSP_AnalogDevices")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/DSP_AnalogDevices.kicad_sym")(options "")(descr "Analog Devices DSP symbols")) + (lib (name "DSP_Freescale")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/DSP_Freescale.kicad_sym")(options "")(descr "Freescale DSP symbols")) + (lib (name "DSP_Microchip_DSPIC33")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/DSP_Microchip_DSPIC33.kicad_sym")(options "")(descr "Microchip DSPIC33 symbols")) + (lib (name "DSP_Motorola")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/DSP_Motorola.kicad_sym")(options "")(descr "Motorola DSP symbols")) + (lib (name "DSP_Texas")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/DSP_Texas.kicad_sym")(options "")(descr "Texas Instruments DSP symbols")) + (lib (name "Fiber_Optic")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Fiber_Optic.kicad_sym")(options "")(descr "Fiber optic symbols")) + (lib (name "Filter")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Filter.kicad_sym")(options "")(descr "Filter symbols")) + (lib (name "FPGA_CologneChip_GateMate")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/FPGA_CologneChip_GateMate.kicad_sym")(options "")(descr "CologneChip GateMate FPGA symbols")) + (lib (name "FPGA_Efinix_Trion")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/FPGA_Efinix_Trion.kicad_sym")(options "")(descr "Efinix Trion FPGA symbols")) + (lib (name "FPGA_Lattice")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/FPGA_Lattice.kicad_sym")(options "")(descr "Lattice FPGA symbols")) + (lib (name "FPGA_Microsemi")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/FPGA_Microsemi.kicad_sym")(options "")(descr "Microsemi FPGA symbols")) + (lib (name "FPGA_Xilinx")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/FPGA_Xilinx.kicad_sym")(options "")(descr "Assorted Xilinx FPGA symbols")) + (lib (name "FPGA_Xilinx_Artix7")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/FPGA_Xilinx_Artix7.kicad_sym")(options "")(descr "Xilinx Artix7 FPGA symbols")) + (lib (name "FPGA_Xilinx_Kintex7")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/FPGA_Xilinx_Kintex7.kicad_sym")(options "")(descr "Xilinx Kintex7 FPGA symbols")) + (lib (name "FPGA_Xilinx_Spartan6")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/FPGA_Xilinx_Spartan6.kicad_sym")(options "")(descr "Xilinx Spartan6 FPGA symbols")) + (lib (name "FPGA_Xilinx_Virtex5")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/FPGA_Xilinx_Virtex5.kicad_sym")(options "")(descr "Xilinx Virtex5 FPGA symbols")) + (lib (name "FPGA_Xilinx_Virtex6")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/FPGA_Xilinx_Virtex6.kicad_sym")(options "")(descr "Xilinx Virtex6 FPGA symbols")) + (lib (name "FPGA_Xilinx_Virtex7")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/FPGA_Xilinx_Virtex7.kicad_sym")(options "")(descr "Xilinx Virtex7 FPGA symbols")) + (lib (name "GPU")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/GPU.kicad_sym")(options "")(descr "Graphics Processing Units")) + (lib (name "Graphic")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Graphic.kicad_sym")(options "")(descr "Graphical symbols")) + (lib (name "Interface")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Interface.kicad_sym")(options "")(descr "Assorted interface symbols")) + (lib (name "Interface_CAN_LIN")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Interface_CAN_LIN.kicad_sym")(options "")(descr "CAN / LIN interface symbols")) + (lib (name "Interface_CurrentLoop")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Interface_CurrentLoop.kicad_sym")(options "")(descr "Current loop interface devices")) + (lib (name "Interface_Ethernet")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Interface_Ethernet.kicad_sym")(options "")(descr "Ethernet interface symbols")) + (lib (name "Interface_Expansion")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Interface_Expansion.kicad_sym")(options "")(descr "I/O expansion devices, shift registers, etc")) + (lib (name "Interface_HDMI")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Interface_HDMI.kicad_sym")(options "")(descr "High Definition Multimedia Interface (HDMI) symbols")) + (lib (name "Interface_HID")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Interface_HID.kicad_sym")(options "")(descr "Human Interface Device (HID) symbols")) + (lib (name "Interface_LineDriver")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Interface_LineDriver.kicad_sym")(options "")(descr "Line driver interface symbols")) + (lib (name "Interface_Optical")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Interface_Optical.kicad_sym")(options "")(descr "Optical interfaces (IR receivers)")) + (lib (name "Interface_Telecom")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Interface_Telecom.kicad_sym")(options "")(descr "Telecom interface symbols")) + (lib (name "Interface_UART")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Interface_UART.kicad_sym")(options "")(descr "UART interface symbols")) + (lib (name "Interface_USB")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Interface_USB.kicad_sym")(options "")(descr "USB interface symbols")) + (lib (name "Isolator")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Isolator.kicad_sym")(options "")(descr "Isolator devices")) + (lib (name "Isolator_Analog")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Isolator_Analog.kicad_sym")(options "")(descr "Analog isolator devices")) + (lib (name "Jumper")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Jumper.kicad_sym")(options "")(descr "(Solder) jumper symbols")) + (lib (name "LED")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/LED.kicad_sym")(options "")(descr "Light Emitting Diode (LED) symbols")) + (lib (name "Logic_LevelTranslator")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Logic_LevelTranslator.kicad_sym")(options "")(descr "Logic level translators and level shifters")) + (lib (name "Logic_Programmable")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Logic_Programmable.kicad_sym")(options "")(descr "Programmable logic symbols")) + (lib (name "MCU_AnalogDevices")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/MCU_AnalogDevices.kicad_sym")(options "")(descr "Analog Devices microcontrollers")) + (lib (name "MCU_Cypress")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/MCU_Cypress.kicad_sym")(options "")(descr "Cypress microcontrollers")) + (lib (name "MCU_Dialog")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/MCU_Dialog.kicad_sym")(options "")(descr "Dialog Semiconductor microcontrollers")) + (lib (name "MCU_Espressif")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/MCU_Espressif.kicad_sym")(options "")(descr "Espressif microcontrollers")) + (lib (name "MCU_Intel")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/MCU_Intel.kicad_sym")(options "")(descr "Various Intel MCU devices and associated peripherals")) + (lib (name "MCU_Microchip_8051")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/MCU_Microchip_8051.kicad_sym")(options "")(descr "Microchip 8051 microcontrollers")) + (lib (name "MCU_Microchip_ATmega")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/MCU_Microchip_ATmega.kicad_sym")(options "")(descr "Microchip ATmega microcontrollers")) + (lib (name "MCU_Microchip_ATtiny")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/MCU_Microchip_ATtiny.kicad_sym")(options "")(descr "Microchip ATtiny microcontrollers")) + (lib (name "MCU_Microchip_AVR")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/MCU_Microchip_AVR.kicad_sym")(options "")(descr "Microchip AVR microcontrollers")) + (lib (name "MCU_Microchip_AVR_Dx")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/MCU_Microchip_AVR_Dx.kicad_sym")(options "")(descr "Microchip AVR-Dx microcontrollers")) + (lib (name "MCU_Microchip_PIC10")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/MCU_Microchip_PIC10.kicad_sym")(options "")(descr "Microchip PIC10 microcontrollers")) + (lib (name "MCU_Microchip_PIC12")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/MCU_Microchip_PIC12.kicad_sym")(options "")(descr "Microchip PIC12 microcontrollers")) + (lib (name "MCU_Microchip_PIC16")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/MCU_Microchip_PIC16.kicad_sym")(options "")(descr "Microchip PIC16 microcontrollers")) + (lib (name "MCU_Microchip_PIC18")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/MCU_Microchip_PIC18.kicad_sym")(options "")(descr "Microchip PIC18 microcontrollers")) + (lib (name "MCU_Microchip_PIC24")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/MCU_Microchip_PIC24.kicad_sym")(options "")(descr "Microchip PIC24 microcontrollers")) + (lib (name "MCU_Microchip_PIC32")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/MCU_Microchip_PIC32.kicad_sym")(options "")(descr "Microchip PIC32 microcontrollers")) + (lib (name "MCU_Microchip_SAMA")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/MCU_Microchip_SAMA.kicad_sym")(options "")(descr "Microchip SAMA microcontrollers")) + (lib (name "MCU_Microchip_SAMD")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/MCU_Microchip_SAMD.kicad_sym")(options "")(descr "Microchip SAMD microcontrollers")) + (lib (name "MCU_Microchip_SAME")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/MCU_Microchip_SAME.kicad_sym")(options "")(descr "Microchip SAME microcontrollers")) + (lib (name "MCU_Microchip_SAML")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/MCU_Microchip_SAML.kicad_sym")(options "")(descr "Microchip SAML microcontrollers")) + (lib (name "MCU_Microchip_SAMV")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/MCU_Microchip_SAMV.kicad_sym")(options "")(descr "Microchip SAMV microcontrollers")) + (lib (name "MCU_Module")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/MCU_Module.kicad_sym")(options "")(descr "Microcontroller Modules and Breakouts (Arduino ...)")) + (lib (name "MCU_Nordic")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/MCU_Nordic.kicad_sym")(options "")(descr "Nordic Semiconductor microcontrollers")) + (lib (name "MCU_NXP_ColdFire")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/MCU_NXP_ColdFire.kicad_sym")(options "")(descr "NXP ColdFire microcontrollers (formerly Motorola)")) + (lib (name "MCU_NXP_HC11")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/MCU_NXP_HC11.kicad_sym")(options "")(descr "NXP HC11 microcontrollers")) + (lib (name "MCU_NXP_HC12")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/MCU_NXP_HC12.kicad_sym")(options "")(descr "NXP HC12 microcontrollers")) + (lib (name "MCU_NXP_HCS12")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/MCU_NXP_HCS12.kicad_sym")(options "")(descr "NXP HCS12 microcontrollers")) + (lib (name "MCU_NXP_Kinetis")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/MCU_NXP_Kinetis.kicad_sym")(options "")(descr "NXP Kinetis microcontrollers")) + (lib (name "MCU_NXP_LPC")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/MCU_NXP_LPC.kicad_sym")(options "")(descr "NXP LPC microcontrollers")) + (lib (name "MCU_NXP_MAC7100")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/MCU_NXP_MAC7100.kicad_sym")(options "")(descr "NXP MAC7100 (ARMv7-based) microcontrollers")) + (lib (name "MCU_NXP_MCore")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/MCU_NXP_MCore.kicad_sym")(options "")(descr "NXP M*Core microcontrollers")) + (lib (name "MCU_NXP_NTAG")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/MCU_NXP_NTAG.kicad_sym")(options "")(descr "NXP NFC microcontrollers")) + (lib (name "MCU_NXP_S08")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/MCU_NXP_S08.kicad_sym")(options "")(descr "NXP S08 microcontrollers")) + (lib (name "MCU_Parallax")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/MCU_Parallax.kicad_sym")(options "")(descr "Parallax microcontrollers")) + (lib (name "MCU_RaspberryPi")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/MCU_RaspberryPi.kicad_sym")(options "")(descr "Raspberry Pi microcontrollers")) + (lib (name "MCU_Renesas_Synergy_S1")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/MCU_Renesas_Synergy_S1.kicad_sym")(options "")(descr "Renesas Synergy S1 microcontrollers")) + (lib (name "MCU_SiFive")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/MCU_SiFive.kicad_sym")(options "")(descr "SiFive microcontrollers")) + (lib (name "MCU_SiliconLabs")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/MCU_SiliconLabs.kicad_sym")(options "")(descr "Silicon Labs (SiLabs) microcontrollers")) + (lib (name "MCU_STC")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/MCU_STC.kicad_sym")(options "")(descr "STC microcontrollers")) + (lib (name "MCU_ST_STM8")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/MCU_ST_STM8.kicad_sym")(options "")(descr "ST STM8 microcontrollers")) + (lib (name "MCU_ST_STM32C0")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/MCU_ST_STM32C0.kicad_sym")(options "")(descr "ST STM32C0 microcontrollers")) + (lib (name "MCU_ST_STM32F0")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/MCU_ST_STM32F0.kicad_sym")(options "")(descr "ST STM32F0 microcontrollers")) + (lib (name "MCU_ST_STM32F1")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/MCU_ST_STM32F1.kicad_sym")(options "")(descr "ST STM32F1 microcontrollers")) + (lib (name "MCU_ST_STM32F2")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/MCU_ST_STM32F2.kicad_sym")(options "")(descr "ST STM32F2 microcontrollers")) + (lib (name "MCU_ST_STM32F3")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/MCU_ST_STM32F3.kicad_sym")(options "")(descr "ST STM32F3 microcontrollers")) + (lib (name "MCU_ST_STM32F4")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/MCU_ST_STM32F4.kicad_sym")(options "")(descr "ST STM32F4 microcontrollers")) + (lib (name "MCU_ST_STM32F7")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/MCU_ST_STM32F7.kicad_sym")(options "")(descr "ST STM32F7 microcontrollers")) + (lib (name "MCU_ST_STM32G0")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/MCU_ST_STM32G0.kicad_sym")(options "")(descr "ST STM32G0 microcontrollers")) + (lib (name "MCU_ST_STM32G4")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/MCU_ST_STM32G4.kicad_sym")(options "")(descr "ST STM32G4 microcontrollers")) + (lib (name "MCU_ST_STM32H5")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/MCU_ST_STM32H5.kicad_sym")(options "")(descr "ST STM32H5 microcontrollers")) + (lib (name "MCU_ST_STM32H7")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/MCU_ST_STM32H7.kicad_sym")(options "")(descr "ST STM32H7 microcontrollers")) + (lib (name "MCU_ST_STM32L0")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/MCU_ST_STM32L0.kicad_sym")(options "")(descr "ST STM32L0 microcontrollers")) + (lib (name "MCU_ST_STM32L1")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/MCU_ST_STM32L1.kicad_sym")(options "")(descr "ST STM32L1 microcontrollers")) + (lib (name "MCU_ST_STM32L4")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/MCU_ST_STM32L4.kicad_sym")(options "")(descr "ST STM32L4 microcontrollers")) + (lib (name "MCU_ST_STM32L5")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/MCU_ST_STM32L5.kicad_sym")(options "")(descr "ST STM32L5 microcontrollers")) + (lib (name "MCU_ST_STM32MP1")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/MCU_ST_STM32MP1.kicad_sym")(options "")(descr "ST STM32MP1 microcontrollers")) + (lib (name "MCU_ST_STM32U5")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/MCU_ST_STM32U5.kicad_sym")(options "")(descr "ST STM32U5 microcontrollers")) + (lib (name "MCU_ST_STM32WB")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/MCU_ST_STM32WB.kicad_sym")(options "")(descr "ST STM32WB microcontrollers")) + (lib (name "MCU_ST_STM32WBA")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/MCU_ST_STM32WBA.kicad_sym")(options "")(descr "ST STM32WBA microcontrollers")) + (lib (name "MCU_ST_STM32WL")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/MCU_ST_STM32WL.kicad_sym")(options "")(descr "ST STM32WL microcontrollers")) + (lib (name "MCU_Texas")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/MCU_Texas.kicad_sym")(options "")(descr "Texas Instruments microcontrollers (assorted)")) + (lib (name "MCU_Texas_MSP430")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/MCU_Texas_MSP430.kicad_sym")(options "")(descr "Texas Instruments MSP430 microcontrollers")) + (lib (name "MCU_Texas_SimpleLink")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/MCU_Texas_SimpleLink.kicad_sym")(options "")(descr "Texas Instruments SimpleLink microcontrollers")) + (lib (name "MCU_WCH_CH32V0")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/MCU_WCH_CH32V0.kicad_sym")(options "")(descr "WCH CH32V0 microcontrollers")) + (lib (name "MCU_WCH_CH32V2")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/MCU_WCH_CH32V2.kicad_sym")(options "")(descr "3Nanjing Qingheng Microelectronics (WCH) CH32V2 2-bit Enhanced Low-Power RISC-V MCU")) + (lib (name "MCU_WCH_CH32V3")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/MCU_WCH_CH32V3.kicad_sym")(options "")(descr "Nanjing Qingheng Microelectronics (WCH) CH32V3 High-Density General RISC-V MCU")) + (lib (name "Mechanical")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Mechanical.kicad_sym")(options "")(descr "Mechanical symbols")) + (lib (name "Memory_EEPROM")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Memory_EEPROM.kicad_sym")(options "")(descr "EEPROM memory")) + (lib (name "Memory_EPROM")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Memory_EPROM.kicad_sym")(options "")(descr "EPROM memory")) + (lib (name "Memory_Flash")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Memory_Flash.kicad_sym")(options "")(descr "Flash memory")) + (lib (name "Memory_NVRAM")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Memory_NVRAM.kicad_sym")(options "")(descr "Non volatile RAM (NVRAM)")) + (lib (name "Memory_RAM")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Memory_RAM.kicad_sym")(options "")(descr "Volatile RAM")) + (lib (name "Memory_ROM")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Memory_ROM.kicad_sym")(options "")(descr "Read only memory (ROM)")) + (lib (name "Memory_UniqueID")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Memory_UniqueID.kicad_sym")(options "")(descr "UID and serial number memory devices")) + (lib (name "Motor")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Motor.kicad_sym")(options "")(descr "Motor symbols")) + (lib (name "Oscillator")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Oscillator.kicad_sym")(options "")(descr "Oscillator symbols")) + (lib (name "Potentiometer_Digital")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Potentiometer_Digital.kicad_sym")(options "")(descr "Digital potentiometers")) + (lib (name "power")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/power.kicad_sym")(options "")(descr "Power symbols, special power flags")) + (lib (name "Power_Management")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Power_Management.kicad_sym")(options "")(descr "Power management and distribution ICs")) + (lib (name "Power_Protection")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Power_Protection.kicad_sym")(options "")(descr "Power protection devices")) + (lib (name "Power_Supervisor")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Power_Supervisor.kicad_sym")(options "")(descr "Power supervisory devices")) + (lib (name "Reference_Current")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Reference_Current.kicad_sym")(options "")(descr "Precision current references")) + (lib (name "Reference_Voltage")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Reference_Voltage.kicad_sym")(options "")(descr "Precision voltage references")) + (lib (name "Regulator_Controller")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Regulator_Controller.kicad_sym")(options "")(descr "Power regulator controllers")) + (lib (name "Regulator_Current")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Regulator_Current.kicad_sym")(options "")(descr "Current regulators")) + (lib (name "Regulator_Linear")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Regulator_Linear.kicad_sym")(options "")(descr "Linear regulators")) + (lib (name "Regulator_SwitchedCapacitor")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Regulator_SwitchedCapacitor.kicad_sym")(options "")(descr "Switched capacitor / charge pump regulators")) + (lib (name "Regulator_Switching")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Regulator_Switching.kicad_sym")(options "")(descr "Switch-mode regulators")) + (lib (name "Relay")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Relay.kicad_sym")(options "")(descr "Relay symbols")) + (lib (name "Relay_SolidState")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Relay_SolidState.kicad_sym")(options "")(descr "Solid state relays (Transistor and Triac based)")) + (lib (name "RF")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/RF.kicad_sym")(options "")(descr "Assorted / uncategorized Radio Frequency (RF) devices")) + (lib (name "RF_Bluetooth")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/RF_Bluetooth.kicad_sym")(options "")(descr "RF Bluetooth wireless modules")) + (lib (name "RF_AM_FM")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/RF_AM_FM.kicad_sym")(options "")(descr "AM / FM wireless devices")) + (lib (name "RF_Amplifier")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/RF_Amplifier.kicad_sym")(options "")(descr "RF amplifier symbols")) + (lib (name "RF_Filter")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/RF_Filter.kicad_sym")(options "")(descr "RF filter symbols")) + (lib (name "RF_GPS")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/RF_GPS.kicad_sym")(options "")(descr "GPS devices")) + (lib (name "RF_GSM")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/RF_GSM.kicad_sym")(options "")(descr "GSM devices")) + (lib (name "RF_Mixer")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/RF_Mixer.kicad_sym")(options "")(descr "RF mixer symbols")) + (lib (name "RF_Module")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/RF_Module.kicad_sym")(options "")(descr "RF module symbols")) + (lib (name "RF_NFC")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/RF_NFC.kicad_sym")(options "")(descr "Near Field Communication (RFID)")) + (lib (name "RF_RFID")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/RF_RFID.kicad_sym")(options "")(descr "Radio Frequency ID (RFID)")) + (lib (name "RF_Switch")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/RF_Switch.kicad_sym")(options "")(descr "RF switch symbols")) + (lib (name "RF_WiFi")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/RF_WiFi.kicad_sym")(options "")(descr "WiFi symbols")) + (lib (name "RF_ZigBee")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/RF_ZigBee.kicad_sym")(options "")(descr "ZigBee / XBee symbols")) + (lib (name "Security")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Security.kicad_sym")(options "")(descr "Security devices")) + (lib (name "Sensor")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Sensor.kicad_sym")(options "")(descr "Multi-function sensors, assorted sensors")) + (lib (name "Sensor_Audio")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Sensor_Audio.kicad_sym")(options "")(descr "Audio / sound / microphone sensors")) + (lib (name "Sensor_Current")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Sensor_Current.kicad_sym")(options "")(descr "Current sensors")) + (lib (name "Sensor_Distance")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Sensor_Distance.kicad_sym")(options "")(descr "Distance sensors")) + (lib (name "Sensor_Energy")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Sensor_Energy.kicad_sym")(options "")(descr "Power / Energy sensors")) + (lib (name "Sensor_Gas")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Sensor_Gas.kicad_sym")(options "")(descr "Gas sensors")) + (lib (name "Sensor_Humidity")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Sensor_Humidity.kicad_sym")(options "")(descr "Humidity sensors")) + (lib (name "Sensor_Magnetic")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Sensor_Magnetic.kicad_sym")(options "")(descr "Magnetic field and hall-effect sensors")) + (lib (name "Sensor_Motion")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Sensor_Motion.kicad_sym")(options "")(descr "Accelerometers, gyroscopic sensors")) + (lib (name "Sensor_Optical")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Sensor_Optical.kicad_sym")(options "")(descr "Light and color sensors")) + (lib (name "Sensor_Pressure")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Sensor_Pressure.kicad_sym")(options "")(descr "Fluid and mechanical pressure sensors")) + (lib (name "Sensor_Proximity")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Sensor_Proximity.kicad_sym")(options "")(descr "Optical interuption and proximity (optical, inductive, capacitve, ...) sensors")) + (lib (name "Sensor_Temperature")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Sensor_Temperature.kicad_sym")(options "")(descr "Temperature sensors")) + (lib (name "Sensor_Touch")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Sensor_Touch.kicad_sym")(options "")(descr "Touch sensors")) + (lib (name "Sensor_Voltage")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Sensor_Voltage.kicad_sym")(options "")(descr "Voltage sensors")) + (lib (name "Simulation_SPICE")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Simulation_SPICE.kicad_sym")(options "")(descr "Symbols specialized for SPICE circuit simulation (including ngspice).")) + (lib (name "Switch")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Switch.kicad_sym")(options "")(descr "Switch symbols")) + (lib (name "Timer")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Timer.kicad_sym")(options "")(descr "Assorted timer devices")) + (lib (name "Timer_PLL")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Timer_PLL.kicad_sym")(options "")(descr "Phase locked loop (PLL) devices")) + (lib (name "Timer_RTC")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Timer_RTC.kicad_sym")(options "")(descr "Real time clock (RTC) devices")) + (lib (name "Transformer")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Transformer.kicad_sym")(options "")(descr "Transformer symbols")) + (lib (name "Transistor_Array")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Transistor_Array.kicad_sym")(options "")(descr "Specialized transistor arrays")) + (lib (name "Transistor_BJT")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Transistor_BJT.kicad_sym")(options "")(descr "BJT transistor symbols")) + (lib (name "Transistor_FET")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Transistor_FET.kicad_sym")(options "")(descr "FET transistor symbols")) + (lib (name "Transistor_FET_Other")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Transistor_FET_Other.kicad_sym")(options "")(descr "Other FET transistor symbols")) + (lib (name "Transistor_IGBT")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Transistor_IGBT.kicad_sym")(options "")(descr "IGBT transistor symbols")) + (lib (name "Transistor_Power_Module")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Transistor_Power_Module.kicad_sym")(options "")(descr "Transistor power modules")) + (lib (name "Triac_Thyristor")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Triac_Thyristor.kicad_sym")(options "")(descr "TRIAC and thyristor symbols")) + (lib (name "Valve")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Valve.kicad_sym")(options "")(descr "Valve symbols")) + (lib (name "Video")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/Video.kicad_sym")(options "")(descr "Video symbols")) + (lib (name "teensy")(type "KiCad")(uri "${KICAD8_SYMBOL_DIR}/teensy.kicad_sym")(options "")(descr "Teensy microcontroller")) +) diff --git a/.github/workflows/document.yaml b/.github/workflows/document.yaml index ad1c2749b..a1702c37e 100644 --- a/.github/workflows/document.yaml +++ b/.github/workflows/document.yaml @@ -19,12 +19,16 @@ jobs: uses: actions/setup-python@v1 with: python-version: "3.10.15" + - name: Install the latest version of uv + uses: astral-sh/setup-uv@v3 + with: + version: "latest" - name: Install - run: pip3 install mkdocs mkdocs-material fontawesome_markdown mkdocs-mermaid2-plugin pymdown-extensions plantuml-markdown python-markdown-math python-github-api mkdocs-github-dashboard pandas markdown==3.3.0 + run: uv sync - name: Set env run: echo "GITHUB_TOKEN=${{ secrets.WAMV_TAN_BOT_SECRET }}" >> $GITHUB_ENV - name: Generate documentation - run: mkdocs build + run: uv run mkdocs build working-directory: docs - uses: actions/upload-artifact@v4 if: ${{ github.event_name == 'pull_request'}} diff --git a/.gitignore b/.gitignore index 5de85e856..48e64fce1 100644 --- a/.gitignore +++ b/.gitignore @@ -12,4 +12,8 @@ scripts/packages_exact.repos scripts/rosdep_base.yaml scripts/rosdep.yaml dataset -poetry.lock \ No newline at end of file +poetry.lock +__pycache__ + +# kicad +fp-info-cache diff --git a/.python-version b/.python-version new file mode 100644 index 000000000..c8cfe3959 --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +3.10 diff --git a/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/Run.bat b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/Run.bat new file mode 100644 index 000000000..449246c94 --- /dev/null +++ b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/Run.bat @@ -0,0 +1,73 @@ +@echo off +set pathofEDASourceFile=%1 +set FilePath=%~dp0 + +::delete --show-dialog after first start up and setting +set option=--show-dialog + +::detect current language of user. +reg query "HKCU\Control Panel\Desktop" /v PreferredUILanguages>nul 2>nul&&goto _dosearch1_||goto _dosearch2_ + +:_dosearch1_ +FOR /F "tokens=3" %%a IN ( + 'reg query "HKCU\Control Panel\Desktop" /v PreferredUILanguages ^| find "PreferredUILanguages"' +) DO ( + set language=%%a +) +set language=%language:~,2% +goto _setlanguage_ + +:_dosearch2_ +FOR /F "tokens=3" %%a IN ( + 'reg query "HKLM\SYSTEM\ControlSet001\Control\Nls\Language" /v InstallLanguage ^| find "InstallLanguage"' +) DO ( + set language=%%a +) +if %language%==0804 ( + set language=zh +) +goto _setlanguage_ + +:_setlanguage_ +if %language%==zh ( + call %FilePath%\i18n\language_zh.bat +) else ( + call %FilePath%\i18n\language_en.bat +) + +cls + +echo ------------------------------------------------------------------------------------------------------------------- +echo ------------------------------------------------------------------------------------------------------------------- +echo. +echo %i18n_thx4using% +echo %i18n_gitAddr% +echo %i18n_batScar% +echo. +echo ------------------------------------------------------------------------------------------------------------------- +echo ------------------------------------------------------------------------------------------------------------------- + +set pyFilePath=%FilePath%generate_interactive_bom.py + +:_convert_ +if not defined pathofEDASourceFile ( + set /p pathofEDASourceFile=%i18n_draghere% +) +echo. +echo %i18n_converting% +echo. +python %pyFilePath% %pathofEDASourceFile% %option% +set pathofEDASourceFile= + +echo ------------------------------------------------------------------------------------------------------------------- +echo ------------------------------------------------------------------------------------------------------------------- +echo. +echo %i18n_converted% +echo. +echo ------------------------------------------------------------------------------------------------------------------- +echo ------------------------------------------------------------------------------------------------------------------- + + +CHOICE /C YN /N /M "%i18n_again% [ Y/N ]" + if errorlevel 2 exit + if errorlevel 1 goto _convert_ diff --git a/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/__init__.py b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/__init__.py new file mode 100644 index 000000000..276c2469a --- /dev/null +++ b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/__init__.py @@ -0,0 +1,58 @@ +import os +import sys +import threading +import time + +import wx +import wx.aui + + +def check_for_bom_button(): + # From Miles McCoo's blog + # https://kicad.mmccoo.com/2017/03/05/adding-your-own-command-buttons-to-the-pcbnew-gui/ + def find_pcbnew_window(): + windows = wx.GetTopLevelWindows() + pcbneww = [w for w in windows if "pcbnew" in w.GetTitle().lower()] + if len(pcbneww) != 1: + return None + return pcbneww[0] + + def callback(_): + plugin.Run() + + path = os.path.dirname(__file__) + while not wx.GetApp(): + time.sleep(1) + bm = wx.Bitmap(path + '/icon.png', wx.BITMAP_TYPE_PNG) + button_wx_item_id = 0 + + from pcbnew import ID_H_TOOLBAR + while True: + time.sleep(1) + pcbnew_window = find_pcbnew_window() + if not pcbnew_window: + continue + + top_tb = pcbnew_window.FindWindowById(ID_H_TOOLBAR) + if button_wx_item_id == 0 or not top_tb.FindTool(button_wx_item_id): + top_tb.AddSeparator() + button_wx_item_id = wx.NewId() + top_tb.AddTool(button_wx_item_id, "iBOM", bm, + "Generate interactive BOM", wx.ITEM_NORMAL) + top_tb.Bind(wx.EVT_TOOL, callback, id=button_wx_item_id) + top_tb.Realize() + + +if (not os.environ.get('INTERACTIVE_HTML_BOM_CLI_MODE', False) and + not os.path.basename(sys.argv[0]).startswith('generate_interactive_bom')): + from .ecad.kicad import InteractiveHtmlBomPlugin + + plugin = InteractiveHtmlBomPlugin() + plugin.register() + + # Add a button the hacky way if plugin button is not supported + # in pcbnew, unless this is linux. + if not plugin.pcbnew_icon_support and not sys.platform.startswith('linux'): + t = threading.Thread(target=check_for_bom_button) + t.daemon = True + t.start() diff --git a/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/core/__init__.py b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/core/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/core/config.py b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/core/config.py new file mode 100644 index 000000000..b39d0b670 --- /dev/null +++ b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/core/config.py @@ -0,0 +1,483 @@ +"""Config object""" + +import argparse +import os +import re + +from wx import FileConfig + +from .. import dialog + + +class Config: + FILE_NAME_FORMAT_HINT = ( + 'Output file name format supports substitutions:\n' + '\n' + ' %f : original pcb file name without extension.\n' + ' %p : pcb/project title from pcb metadata.\n' + ' %c : company from pcb metadata.\n' + ' %r : revision from pcb metadata.\n' + ' %d : pcb date from metadata if available, ' + 'file modification date otherwise.\n' + ' %D : bom generation date.\n' + ' %T : bom generation time.\n' + '\n' + 'Extension .html will be added automatically.' + ) # type: str + + # Helper constants + bom_view_choices = ['bom-only', 'left-right', 'top-bottom'] + layer_view_choices = ['F', 'FB', 'B'] + default_sort_order = [ + 'C', 'R', 'L', 'D', 'U', 'Y', 'X', 'F', 'SW', 'A', + '~', + 'HS', 'CNN', 'J', 'P', 'NT', 'MH', + ] + highlight_pin1_choices = ['none', 'all', 'selected'] + default_checkboxes = ['Sourced', 'Placed'] + html_config_fields = [ + 'dark_mode', 'show_pads', 'show_fabrication', 'show_silkscreen', + 'highlight_pin1', 'redraw_on_drag', 'board_rotation', 'checkboxes', + 'bom_view', 'layer_view', 'offset_back_rotation', + 'kicad_text_formatting' + ] + default_show_group_fields = ["Value", "Footprint"] + + # Defaults + + # HTML section + dark_mode = False + show_pads = True + show_fabrication = False + show_silkscreen = True + redraw_on_drag = True + highlight_pin1 = highlight_pin1_choices[0] + board_rotation = 0 + offset_back_rotation = False + checkboxes = ','.join(default_checkboxes) + bom_view = bom_view_choices[1] + layer_view = layer_view_choices[1] + compression = True + open_browser = True + + # General section + bom_dest_dir = 'bom/' # This is relative to pcb file directory + bom_name_format = 'ibom' + component_sort_order = default_sort_order + component_blacklist = [] + blacklist_virtual = True + blacklist_empty_val = False + include_tracks = False + include_nets = False + kicad_text_formatting = True + + # Extra fields section + extra_data_file = None + netlist_initial_directory = '' # This is relative to pcb file directory + show_fields = default_show_group_fields + group_fields = default_show_group_fields + normalize_field_case = False + board_variant_field = '' + board_variant_whitelist = [] + board_variant_blacklist = [] + dnp_field = '' + + @staticmethod + def _split(s): + """Splits string by ',' and drops empty strings from resulting array""" + return [a.replace('\\,', ',') for a in re.split(r'(? None + # Html + self.dark_mode = dlg.html.darkModeCheckbox.IsChecked() + self.show_pads = dlg.html.showPadsCheckbox.IsChecked() + self.show_fabrication = dlg.html.showFabricationCheckbox.IsChecked() + self.show_silkscreen = dlg.html.showSilkscreenCheckbox.IsChecked() + self.redraw_on_drag = dlg.html.continuousRedrawCheckbox.IsChecked() + self.highlight_pin1 = self.highlight_pin1_choices[dlg.html.highlightPin1.Selection] + self.board_rotation = dlg.html.boardRotationSlider.Value + self.offset_back_rotation = \ + dlg.html.offsetBackRotationCheckbox.IsChecked() + self.checkboxes = dlg.html.bomCheckboxesCtrl.Value + self.bom_view = self.bom_view_choices[dlg.html.bomDefaultView.Selection] + self.layer_view = self.layer_view_choices[ + dlg.html.layerDefaultView.Selection] + self.compression = dlg.html.compressionCheckbox.IsChecked() + self.open_browser = dlg.html.openBrowserCheckbox.IsChecked() + + # General + self.bom_dest_dir = dlg.general.bomDirPicker.Path + self.bom_name_format = dlg.general.fileNameFormatTextControl.Value + self.component_sort_order = dlg.general.componentSortOrderBox.GetItems() + self.component_blacklist = dlg.general.blacklistBox.GetItems() + self.blacklist_virtual = \ + dlg.general.blacklistVirtualCheckbox.IsChecked() + self.blacklist_empty_val = \ + dlg.general.blacklistEmptyValCheckbox.IsChecked() + self.include_tracks = dlg.general.includeTracksCheckbox.IsChecked() + self.include_nets = dlg.general.includeNetsCheckbox.IsChecked() + + # Fields + self.extra_data_file = dlg.fields.extraDataFilePicker.Path + self.show_fields = dlg.fields.GetShowFields() + self.group_fields = dlg.fields.GetGroupFields() + self.normalize_field_case = dlg.fields.normalizeCaseCheckbox.Value + self.board_variant_field = dlg.fields.boardVariantFieldBox.Value + if self.board_variant_field == dlg.fields.NONE_STRING: + self.board_variant_field = '' + self.board_variant_whitelist = list( + dlg.fields.boardVariantWhitelist.GetCheckedStrings()) + self.board_variant_blacklist = list( + dlg.fields.boardVariantBlacklist.GetCheckedStrings()) + self.dnp_field = dlg.fields.dnpFieldBox.Value + if self.dnp_field == dlg.fields.NONE_STRING: + self.dnp_field = '' + + def transfer_to_dialog(self, dlg): + # type: (dialog.settings_dialog.SettingsDialogPanel) -> None + # Html + dlg.html.darkModeCheckbox.Value = self.dark_mode + dlg.html.showPadsCheckbox.Value = self.show_pads + dlg.html.showFabricationCheckbox.Value = self.show_fabrication + dlg.html.showSilkscreenCheckbox.Value = self.show_silkscreen + dlg.html.highlightPin1.Selection = 0 + if self.highlight_pin1 in self.highlight_pin1_choices: + dlg.html.highlightPin1.Selection = \ + self.highlight_pin1_choices.index(self.highlight_pin1) + dlg.html.continuousRedrawCheckbox.value = self.redraw_on_drag + dlg.html.boardRotationSlider.Value = self.board_rotation + dlg.html.offsetBackRotationCheckbox.Value = self.offset_back_rotation + dlg.html.bomCheckboxesCtrl.Value = self.checkboxes + dlg.html.bomDefaultView.Selection = self.bom_view_choices.index( + self.bom_view) + dlg.html.layerDefaultView.Selection = self.layer_view_choices.index( + self.layer_view) + dlg.html.compressionCheckbox.Value = self.compression + dlg.html.openBrowserCheckbox.Value = self.open_browser + + # General + import os.path + if os.path.isabs(self.bom_dest_dir): + dlg.general.bomDirPicker.Path = self.bom_dest_dir + else: + dlg.general.bomDirPicker.Path = os.path.join( + self.netlist_initial_directory, self.bom_dest_dir) + dlg.general.fileNameFormatTextControl.Value = self.bom_name_format + dlg.general.componentSortOrderBox.SetItems(self.component_sort_order) + dlg.general.blacklistBox.SetItems(self.component_blacklist) + dlg.general.blacklistVirtualCheckbox.Value = self.blacklist_virtual + dlg.general.blacklistEmptyValCheckbox.Value = self.blacklist_empty_val + dlg.general.includeTracksCheckbox.Value = self.include_tracks + dlg.general.includeNetsCheckbox.Value = self.include_nets + + # Fields + dlg.fields.extraDataFilePicker.SetInitialDirectory( + self.netlist_initial_directory) + + def safe_set_checked_strings(clb, strings): + current = list(clb.GetStrings()) + if current: + present_strings = [s for s in strings if s in current] + not_present_strings = [s for s in current if s not in strings] + clb.Clear() + clb.InsertItems(present_strings + not_present_strings, 0) + clb.SetCheckedStrings(present_strings) + + dlg.fields.SetCheckedFields(self.show_fields, self.group_fields) + dlg.fields.normalizeCaseCheckbox.Value = self.normalize_field_case + dlg.fields.boardVariantFieldBox.Value = self.board_variant_field + dlg.fields.OnBoardVariantFieldChange(None) + safe_set_checked_strings(dlg.fields.boardVariantWhitelist, + self.board_variant_whitelist) + safe_set_checked_strings(dlg.fields.boardVariantBlacklist, + self.board_variant_blacklist) + dlg.fields.dnpFieldBox.Value = self.dnp_field + + dlg.finish_init() + + @classmethod + def add_options(cls, parser, version): + # type: (argparse.ArgumentParser, str) -> None + parser.add_argument('--show-dialog', action='store_true', + help='Shows config dialog. All other flags ' + 'will be ignored.') + parser.add_argument('--version', action='version', version=version) + # Html + parser.add_argument('--dark-mode', help='Default to dark mode.', + action='store_true') + parser.add_argument('--hide-pads', + help='Hide footprint pads by default.', + action='store_true') + parser.add_argument('--show-fabrication', + help='Show fabrication layer by default.', + action='store_true') + parser.add_argument('--hide-silkscreen', + help='Hide silkscreen by default.', + action='store_true') + parser.add_argument('--highlight-pin1', + default=cls.highlight_pin1_choices[0], + const=cls.highlight_pin1_choices[1], + choices=cls.highlight_pin1_choices, + nargs='?', + help='Highlight first pin.') + parser.add_argument('--no-redraw-on-drag', + help='Do not redraw pcb on drag by default.', + action='store_true') + parser.add_argument('--board-rotation', type=int, + default=cls.board_rotation * 5, + help='Board rotation in degrees (-180 to 180). ' + 'Will be rounded to multiple of 5.') + parser.add_argument('--offset-back-rotation', + help='Offset the back of the pcb by 180 degrees', + action='store_true') + parser.add_argument('--checkboxes', + default=cls.checkboxes, + help='Comma separated list of checkbox columns.') + parser.add_argument('--bom-view', default=cls.bom_view, + choices=cls.bom_view_choices, + help='Default BOM view.') + parser.add_argument('--layer-view', default=cls.layer_view, + choices=cls.layer_view_choices, + help='Default layer view.') + parser.add_argument('--no-compression', + help='Disable compression of pcb data.', + action='store_true') + parser.add_argument('--no-browser', help='Do not launch browser.', + action='store_true') + + # General + parser.add_argument('--dest-dir', default=cls.bom_dest_dir, + help='Destination directory for bom file ' + 'relative to pcb file directory.') + parser.add_argument('--name-format', default=cls.bom_name_format, + help=cls.FILE_NAME_FORMAT_HINT.replace('%', '%%')) + parser.add_argument('--include-tracks', action='store_true', + help='Include track/zone information in output. ' + 'F.Cu and B.Cu layers only.') + parser.add_argument('--include-nets', action='store_true', + help='Include netlist information in output.') + parser.add_argument('--sort-order', + help='Default sort order for components. ' + 'Must contain "~" once.', + default=','.join(cls.component_sort_order)) + parser.add_argument('--blacklist', + default=','.join(cls.component_blacklist), + help='List of comma separated blacklisted ' + 'components or prefixes with *. ' + 'E.g. "X1,MH*"') + parser.add_argument('--no-blacklist-virtual', action='store_true', + help='Do not blacklist virtual components.') + parser.add_argument('--blacklist-empty-val', action='store_true', + help='Blacklist components with empty value.') + + # Fields section + parser.add_argument('--netlist-file', + help='(Deprecated) Path to netlist or xml file.') + parser.add_argument('--extra-data-file', + help='Path to netlist or xml file.') + parser.add_argument('--extra-fields', + help='Passing --extra-fields "X,Y" is a shortcut ' + 'for --show-fields and --group-fields ' + 'with values "Value,Footprint,X,Y"') + parser.add_argument('--show-fields', + default=cls._join(cls.show_fields), + help='List of fields to show in the BOM.') + parser.add_argument('--group-fields', + default=cls._join(cls.group_fields), + help='Fields that components will be grouped by.') + parser.add_argument('--normalize-field-case', + help='Normalize extra field name case. E.g. "MPN" ' + ', "mpn" will be considered the same field.', + action='store_true') + parser.add_argument('--variant-field', + help='Name of the extra field that stores board ' + 'variant for component.') + parser.add_argument('--variants-whitelist', default='', + help='List of board variants to ' + 'include in the BOM. Use "" to denote ' + 'not set or empty value.') + parser.add_argument('--variants-blacklist', default='', + help='List of board variants to ' + 'exclude from the BOM. Use "" to denote ' + 'not set or empty value.') + parser.add_argument('--dnp-field', default=cls.dnp_field, + help='Name of the extra field that indicates ' + 'do not populate status. Components with ' + 'this field not empty will be excluded.') + + def set_from_args(self, args): + # type: (argparse.Namespace) -> None + import math + + # Html + self.dark_mode = args.dark_mode + self.show_pads = not args.hide_pads + self.show_fabrication = args.show_fabrication + self.show_silkscreen = not args.hide_silkscreen + self.highlight_pin1 = args.highlight_pin1 + self.redraw_on_drag = not args.no_redraw_on_drag + self.board_rotation = math.fmod(args.board_rotation // 5, 37) + self.offset_back_rotation = args.offset_back_rotation + self.checkboxes = args.checkboxes + self.bom_view = args.bom_view + self.layer_view = args.layer_view + self.compression = not args.no_compression + self.open_browser = not args.no_browser + + # General + self.bom_dest_dir = args.dest_dir + self.bom_name_format = args.name_format + self.component_sort_order = self._split(args.sort_order) + self.component_blacklist = self._split(args.blacklist) + self.blacklist_virtual = not args.no_blacklist_virtual + self.blacklist_empty_val = args.blacklist_empty_val + self.include_tracks = args.include_tracks + self.include_nets = args.include_nets + + # Fields + self.extra_data_file = args.extra_data_file or args.netlist_file + if args.extra_fields is not None: + self.show_fields = self.default_show_group_fields + \ + self._split(args.extra_fields) + self.group_fields = self.show_fields + else: + self.show_fields = self._split(args.show_fields) + self.group_fields = self._split(args.group_fields) + self.normalize_field_case = args.normalize_field_case + self.board_variant_field = args.variant_field + self.board_variant_whitelist = self._split(args.variants_whitelist) + self.board_variant_blacklist = self._split(args.variants_blacklist) + self.dnp_field = args.dnp_field + + def get_html_config(self): + import json + d = {f: getattr(self, f) for f in self.html_config_fields} + d["fields"] = self.show_fields + return json.dumps(d) diff --git a/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/core/fontparser.py b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/core/fontparser.py new file mode 100644 index 000000000..ee50df695 --- /dev/null +++ b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/core/fontparser.py @@ -0,0 +1,52 @@ +from .newstroke_font import NEWSTROKE_FONT + + +class FontParser: + STROKE_FONT_SCALE = 1.0 / 21.0 + FONT_OFFSET = -10 + + def __init__(self): + self.parsed_font = {} + + def parse_font_char(self, chr): + lines = [] + line = [] + glyph_x = 0 + index = ord(chr) - ord(' ') + if index >= len(NEWSTROKE_FONT): + index = ord('?') - ord(' ') + glyph_str = NEWSTROKE_FONT[index] + for i in range(0, len(glyph_str), 2): + coord = glyph_str[i:i + 2] + + # The first two values contain the width of the char + if i < 2: + glyph_x = (ord(coord[0]) - ord('R')) * self.STROKE_FONT_SCALE + glyph_width = (ord(coord[1]) - ord(coord[0])) * self.STROKE_FONT_SCALE + elif coord[0] == ' ' and coord[1] == 'R': + lines.append(line) + line = [] + else: + line.append([ + (ord(coord[0]) - ord('R')) * self.STROKE_FONT_SCALE - glyph_x, + (ord(coord[1]) - ord('R') + self.FONT_OFFSET) * self.STROKE_FONT_SCALE + ]) + + if len(line) > 0: + lines.append(line) + + return { + 'w': glyph_width, + 'l': lines + } + + def parse_font_for_string(self, s): + for c in s: + if c == '\t' and ' ' not in self.parsed_font: + # tabs rely on space char to calculate offset + self.parsed_font[' '] = self.parse_font_char(' ') + if c not in self.parsed_font and ord(c) >= ord(' '): + self.parsed_font[c] = self.parse_font_char(c) + + def get_parsed_font(self): + return self.parsed_font diff --git a/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/core/ibom.py b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/core/ibom.py new file mode 100644 index 000000000..178467cb5 --- /dev/null +++ b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/core/ibom.py @@ -0,0 +1,365 @@ +from __future__ import absolute_import + +import io +import json +import logging +import os +import re +import sys +from datetime import datetime + +import wx + +from . import units +from .config import Config +from ..dialog import SettingsDialog +from ..ecad.common import EcadParser, Component +from ..errors import ParsingException + + +class Logger(object): + + def __init__(self, cli=False): + self.cli = cli + self.logger = logging.getLogger('InteractiveHtmlBom') + self.logger.setLevel(logging.INFO) + ch = logging.StreamHandler(sys.stdout) + ch.setLevel(logging.INFO) + formatter = logging.Formatter( + "%(asctime)-15s %(levelname)s %(message)s") + ch.setFormatter(formatter) + self.logger.addHandler(ch) + + def info(self, *args): + if self.cli: + self.logger.info(*args) + + def error(self, msg): + if self.cli: + self.logger.error(msg) + else: + wx.MessageBox(msg) + + def warn(self, msg): + if self.cli: + self.logger.warning(msg) + else: + wx.LogWarning(msg) + + +log = None + + +def skip_component(m, config): + # type: (Component, Config) -> bool + # skip blacklisted components + ref_prefix = re.findall('^[A-Z]*', m.ref)[0] + if m.ref in config.component_blacklist: + return True + if ref_prefix + '*' in config.component_blacklist: + return True + + if config.blacklist_empty_val and m.val in ['', '~']: + return True + + # skip virtual components if needed + if config.blacklist_virtual and m.attr == 'Virtual': + return True + + # skip components with dnp field not empty + if config.dnp_field \ + and config.dnp_field in m.extra_fields \ + and m.extra_fields[config.dnp_field]: + return True + + # skip components with wrong variant field + empty_str = '' + if config.board_variant_field and config.board_variant_whitelist: + ref_variant = m.extra_fields.get(config.board_variant_field, '') + if ref_variant == '': + ref_variant = empty_str + if ref_variant not in config.board_variant_whitelist: + return True + + if config.board_variant_field and config.board_variant_blacklist: + ref_variant = m.extra_fields.get(config.board_variant_field, '') + if ref_variant == '': + ref_variant = empty_str + if ref_variant != empty_str and ref_variant in config.board_variant_blacklist: + return True + + return False + + +def generate_bom(pcb_footprints, config): + # type: (list, Config) -> dict + """ + Generate BOM from pcb layout. + :param pcb_footprints: list of footprints on the pcb + :param config: Config object + :return: dict of BOM tables (qty, value, footprint, refs) + and dnp components + """ + + def convert(text): + return int(text) if text.isdigit() else text.lower() + + def alphanum_key(key): + return [convert(c) + for c in re.split('([0-9]+)', key)] + + def natural_sort(lst): + """ + Natural sort for strings containing numbers + """ + + return sorted(lst, key=lambda r: (alphanum_key(r[0]), r[1])) + + # build grouped part list + skipped_components = [] + part_groups = {} + group_by = set(config.group_fields) + index_to_fields = {} + + for i, f in enumerate(pcb_footprints): + if skip_component(f, config): + skipped_components.append(i) + continue + + # group part refs by value and footprint + fields = [] + group_key = [] + + for field in config.show_fields: + if field == "Value": + fields.append(f.val) + if "Value" in group_by: + norm_value, unit = units.componentValue(f.val, f.ref) + group_key.append(norm_value) + group_key.append(unit) + elif field == "Footprint": + fields.append(f.footprint) + if "Footprint" in group_by: + group_key.append(f.footprint) + group_key.append(f.attr) + else: + field_key = field + if config.normalize_field_case: + field_key = field.lower() + fields.append(f.extra_fields.get(field_key, '')) + if field in group_by: + group_key.append(f.extra_fields.get(field_key, '')) + + index_to_fields[i] = fields + refs = part_groups.setdefault(tuple(group_key), []) + refs.append((f.ref, i)) + + bom_table = [] + + # If some extra fields are just integers then convert the whole column + # so that sorting will work naturally + for i, field in enumerate(config.show_fields): + if field in ["Value", "Footprint"]: + continue + all_num = True + for f in index_to_fields.values(): + if not f[i].isdigit() and len(f[i].strip()) > 0: + all_num = False + break + if all_num: + for f in index_to_fields.values(): + if f[i].isdigit(): + f[i] = int(f[i]) + + for _, refs in part_groups.items(): + # Fixup values to normalized string + if "Value" in group_by and "Value" in config.show_fields: + index = config.show_fields.index("Value") + value = index_to_fields[refs[0][1]][index] + for ref in refs: + index_to_fields[ref[1]][index] = value + + bom_table.append(natural_sort(refs)) + + # sort table by reference prefix and quantity + def row_sort_key(element): + prefix = re.findall('^[^0-9]*', element[0][0])[0] + if prefix in config.component_sort_order: + ref_ord = config.component_sort_order.index(prefix) + else: + ref_ord = config.component_sort_order.index('~') + return ref_ord, -len(element), alphanum_key(element[0][0]) + + if '~' not in config.component_sort_order: + config.component_sort_order.append('~') + + bom_table = sorted(bom_table, key=row_sort_key) + + result = { + 'both': bom_table, + 'skipped': skipped_components, + 'fields': index_to_fields + } + + for layer in ['F', 'B']: + filtered_table = [] + for row in bom_table: + filtered_refs = [ref for ref in row + if pcb_footprints[ref[1]].layer == layer] + if filtered_refs: + filtered_table.append(filtered_refs) + + result[layer] = sorted(filtered_table, key=row_sort_key) + + return result + + +def open_file(filename): + import subprocess + try: + if sys.platform.startswith('win'): + os.startfile(filename) + elif sys.platform.startswith('darwin'): + subprocess.call(('open', filename)) + elif sys.platform.startswith('linux'): + subprocess.call(('xdg-open', filename)) + except Exception as e: + log.warn('Failed to open browser: {}'.format(e)) + + +def process_substitutions(bom_name_format, pcb_file_name, metadata): + # type: (str, str, dict)->str + name = bom_name_format.replace('%f', os.path.splitext(pcb_file_name)[0]) + name = name.replace('%p', metadata['title']) + name = name.replace('%c', metadata['company']) + name = name.replace('%r', metadata['revision']) + name = name.replace('%d', metadata['date'].replace(':', '-')) + now = datetime.now() + name = name.replace('%D', now.strftime('%Y-%m-%d')) + name = name.replace('%T', now.strftime('%H-%M-%S')) + # sanitize the name to avoid characters illegal in file systems + name = name.replace('\\', '/') + name = re.sub(r'[?%*:|"<>]', '_', name) + return name + '.html' + + +def round_floats(o, precision): + if isinstance(o, float): + return round(o, precision) + if isinstance(o, dict): + return {k: round_floats(v, precision) for k, v in o.items()} + if isinstance(o, (list, tuple)): + return [round_floats(x, precision) for x in o] + return o + + +def get_pcbdata_javascript(pcbdata, compression): + from .lzstring import LZString + + js = "var pcbdata = {}" + pcbdata_str = json.dumps(round_floats(pcbdata, 6)) + + if compression: + log.info("Compressing pcb data") + pcbdata_str = json.dumps(LZString().compress_to_base64(pcbdata_str)) + js = "var pcbdata = JSON.parse(LZString.decompressFromBase64({}))" + + return js.format(pcbdata_str) + + +def generate_file(pcb_file_dir, pcb_file_name, pcbdata, config): + def get_file_content(file_name): + path = os.path.join(os.path.dirname(__file__), "..", "web", file_name) + if not os.path.exists(path): + return "" + with io.open(path, 'r', encoding='utf-8') as f: + return f.read() + + if os.path.isabs(config.bom_dest_dir): + bom_file_dir = config.bom_dest_dir + else: + bom_file_dir = os.path.join(pcb_file_dir, config.bom_dest_dir) + bom_file_name = process_substitutions( + config.bom_name_format, pcb_file_name, pcbdata['metadata']) + bom_file_name = os.path.join(bom_file_dir, bom_file_name) + bom_file_dir = os.path.dirname(bom_file_name) + if not os.path.isdir(bom_file_dir): + os.makedirs(bom_file_dir) + pcbdata_js = get_pcbdata_javascript(pcbdata, config.compression) + log.info("Dumping pcb data") + config_js = "var config = " + config.get_html_config() + html = get_file_content("ibom.html") + html = html.replace('///CSS///', get_file_content('ibom.css')) + html = html.replace('///USERCSS///', get_file_content('user.css')) + html = html.replace('///SPLITJS///', get_file_content('split.js')) + html = html.replace('///LZ-STRING///', + get_file_content('lz-string.js') + if config.compression else '') + html = html.replace('///POINTER_EVENTS_POLYFILL///', + get_file_content('pep.js')) + html = html.replace('///CONFIG///', config_js) + html = html.replace('///UTILJS///', get_file_content('util.js')) + html = html.replace('///RENDERJS///', get_file_content('render.js')) + html = html.replace('///TABLEUTILJS///', get_file_content('table-util.js')) + html = html.replace('///IBOMJS///', get_file_content('ibom.js')) + html = html.replace('///USERJS///', get_file_content('user.js')) + html = html.replace('///USERHEADER///', + get_file_content('userheader.html')) + html = html.replace('///USERFOOTER///', + get_file_content('userfooter.html')) + # Replace pcbdata last for better performance. + html = html.replace('///PCBDATA///', pcbdata_js) + + with io.open(bom_file_name, 'wt', encoding='utf-8') as bom: + bom.write(html) + + log.info("Created file %s", bom_file_name) + return bom_file_name + + +def main(parser, config, logger): + # type: (EcadParser, Config, Logger) -> None + global log + log = logger + pcb_file_name = os.path.basename(parser.file_name) + pcb_file_dir = os.path.dirname(parser.file_name) + + pcbdata, components = parser.parse() + if not pcbdata and not components: + raise ParsingException('Parsing failed.') + + pcbdata["bom"] = generate_bom(components, config) + pcbdata["ibom_version"] = config.version + + # build BOM + bom_file = generate_file(pcb_file_dir, pcb_file_name, pcbdata, config) + + if config.open_browser: + logger.info("Opening file in browser") + open_file(bom_file) + + +def run_with_dialog(parser, config, logger): + # type: (EcadParser, Config, Logger) -> None + def save_config(dialog_panel, locally=False): + config.set_from_dialog(dialog_panel) + config.save(locally) + + config.load_from_ini() + dlg = SettingsDialog(extra_data_func=parser.parse_extra_data, + extra_data_wildcard=parser.extra_data_file_filter(), + config_save_func=save_config, + file_name_format_hint=config.FILE_NAME_FORMAT_HINT, + version=config.version) + try: + config.netlist_initial_directory = os.path.dirname(parser.file_name) + extra_data_file = parser.latest_extra_data( + extra_dirs=[config.bom_dest_dir]) + if extra_data_file is not None: + dlg.set_extra_data_path(extra_data_file) + config.transfer_to_dialog(dlg.panel) + if dlg.ShowModal() == wx.ID_OK: + config.set_from_dialog(dlg.panel) + main(parser, config, logger) + finally: + dlg.Destroy() diff --git a/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/core/lzstring.py b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/core/lzstring.py new file mode 100644 index 000000000..507d23993 --- /dev/null +++ b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/core/lzstring.py @@ -0,0 +1,304 @@ +""" +Copyright 2014 Eduard Tomasek +This work is free. You can redistribute it and/or modify it under the +terms of the Do What The Fuck You Want To Public License, Version 2, +as published by Sam Hocevar. See the COPYING file for more details. +""" +import sys +if sys.version_info[0] == 3: + unichr = chr + + +class LZString: + + def __init__(self): + self.keyStr = ( + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=" + ) + + @staticmethod + def compress(uncompressed): + + if uncompressed is None: + return '' + + context_dictionary = {} + context_dictionary_to_create = {} + context_w = '' + context_enlarge_in = 2 + + context_dict_size = 3 + context_num_bits = 2 + context_data_string = '' + context_data_val = 0 + context_data_position = 0 + + uncompressed = uncompressed + + for ii in range(len(uncompressed)): + context_c = uncompressed[ii] + + if context_c not in context_dictionary: + context_dictionary[context_c] = context_dict_size + context_dict_size += 1 + context_dictionary_to_create[context_c] = True + + context_wc = context_w + context_c + + if context_wc in context_dictionary: + context_w = context_wc + else: + if context_w in context_dictionary_to_create: + if ord(context_w[0]) < 256: + for _ in range(context_num_bits): + context_data_val = (context_data_val << 1) + + if context_data_position == 15: + context_data_position = 0 + context_data_string += unichr(context_data_val) + context_data_val = 0 + else: + context_data_position += 1 + + value = ord(context_w[0]) + + for i in range(8): + context_data_val = ( + (context_data_val << 1) | (value & 1) + ) + + if context_data_position == 15: + context_data_position = 0 + context_data_string += unichr(context_data_val) + context_data_val = 0 + else: + context_data_position += 1 + + value = value >> 1 + else: + value = 1 + + for i in range(context_num_bits): + context_data_val = (context_data_val << 1) | value + + if context_data_position == 15: + context_data_position = 0 + context_data_string += unichr(context_data_val) + context_data_val = 0 + else: + context_data_position += 1 + + value = 0 + + value = ord(context_w[0]) + + for i in range(16): + context_data_val = ( + (context_data_val << 1) | (value & 1) + ) + + if context_data_position == 15: + context_data_position = 0 + context_data_string += unichr(context_data_val) + context_data_val = 0 + else: + context_data_position += 1 + + value = value >> 1 + + context_enlarge_in -= 1 + + if context_enlarge_in == 0: + context_enlarge_in = pow(2, context_num_bits) + context_num_bits += 1 + + context_dictionary_to_create.pop(context_w, None) + # del context_dictionary_to_create[context_w] + else: + value = context_dictionary[context_w] + + for i in range(context_num_bits): + context_data_val = ( + (context_data_val << 1) | (value & 1) + ) + + if context_data_position == 15: + context_data_position = 0 + context_data_string += unichr(context_data_val) + context_data_val = 0 + else: + context_data_position += 1 + + value = value >> 1 + + context_enlarge_in -= 1 + + if context_enlarge_in == 0: + context_enlarge_in = pow(2, context_num_bits) + context_num_bits += 1 + + context_dictionary[context_wc] = context_dict_size + context_dict_size += 1 + context_w = context_c + if context_w != '': + if context_w in context_dictionary_to_create: + if ord(context_w[0]) < 256: + for i in range(context_num_bits): + context_data_val = (context_data_val << 1) + + if context_data_position == 15: + context_data_position = 0 + context_data_string += unichr(context_data_val) + context_data_val = 0 + else: + context_data_position += 1 + + value = ord(context_w[0]) + + for i in range(8): + context_data_val = ( + (context_data_val << 1) | (value & 1) + ) + + if context_data_position == 15: + context_data_position = 0 + context_data_string += unichr(context_data_val) + context_data_val = 0 + else: + context_data_position += 1 + + value = value >> 1 + else: + value = 1 + + for i in range(context_num_bits): + context_data_val = (context_data_val << 1) | value + + if context_data_position == 15: + context_data_position = 0 + context_data_string += unichr(context_data_val) + context_data_val = 0 + else: + context_data_position += 1 + + value = 0 + + value = ord(context_w[0]) + + for i in range(16): + context_data_val = ( + (context_data_val << 1) | (value & 1) + ) + + if context_data_position == 15: + context_data_position = 0 + context_data_string += unichr(context_data_val) + context_data_val = 0 + else: + context_data_position += 1 + + value = value >> 1 + + context_enlarge_in -= 1 + + if context_enlarge_in == 0: + context_enlarge_in = pow(2, context_num_bits) + context_num_bits += 1 + + context_dictionary_to_create.pop(context_w, None) + # del context_dictionary_to_create[context_w] + else: + value = context_dictionary[context_w] + + for i in range(context_num_bits): + context_data_val = (context_data_val << 1) | (value & 1) + + if context_data_position == 15: + context_data_position = 0 + context_data_string += unichr(context_data_val) + context_data_val = 0 + else: + context_data_position += 1 + + value = value >> 1 + + context_enlarge_in -= 1 + + if context_enlarge_in == 0: + context_num_bits += 1 + + value = 2 + + for i in range(context_num_bits): + context_data_val = (context_data_val << 1) | (value & 1) + + if context_data_position == 15: + context_data_position = 0 + context_data_string += unichr(context_data_val) + context_data_val = 0 + else: + context_data_position += 1 + + value = value >> 1 + + context_data_val = (context_data_val << 1) + while context_data_position != 15: + context_data_position += 1 + context_data_val = (context_data_val << 1) + context_data_string += unichr(context_data_val) + + return context_data_string + + def compress_to_base64(self, string): + if string is None: + return '' + + output = '' + + string = self.compress(string) + str_len = len(string) + + for i in range(0, str_len * 2, 3): + if (i % 2) == 0: + chr1 = ord(string[i // 2]) >> 8 + chr2 = ord(string[i // 2]) & 255 + + if (i / 2) + 1 < str_len: + chr3 = ord(string[(i // 2) + 1]) >> 8 + else: + chr3 = None + else: + chr1 = ord(string[(i - 1) // 2]) & 255 + if (i + 1) / 2 < str_len: + chr2 = ord(string[(i + 1) // 2]) >> 8 + chr3 = ord(string[(i + 1) // 2]) & 255 + else: + chr2 = None + chr3 = None + + # python dont support bit operation with NaN like javascript + enc1 = chr1 >> 2 + enc2 = ( + ((chr1 & 3) << 4) | + (chr2 >> 4 if chr2 is not None else 0) + ) + enc3 = ( + ((chr2 & 15 if chr2 is not None else 0) << 2) | + (chr3 >> 6 if chr3 is not None else 0) + ) + enc4 = (chr3 if chr3 is not None else 0) & 63 + + if chr2 is None: + enc3 = 64 + enc4 = 64 + elif chr3 is None: + enc4 = 64 + + output += ( + self.keyStr[enc1] + + self.keyStr[enc2] + + self.keyStr[enc3] + + self.keyStr[enc4] + ) + + return output diff --git a/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/core/newstroke_font.py b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/core/newstroke_font.py new file mode 100644 index 000000000..8f217c1ab --- /dev/null +++ b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/core/newstroke_font.py @@ -0,0 +1,11361 @@ +""" + * newstroke_font.cpp - definitions for automatically converted font + * + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2010 vladimir uryvaev + * Copyright (C) 1992-2010 KiCad Developers, see change_log.txt for contributors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +#include + +This file is copied from KiCad source tree and +slightly modified to be valid python by qu1ck. +""" + +NEWSTROKE_FONT = [ + # /* // BASIC LATIN (0020-007F) */ + "JZ", # /* U+20 SPACE */ + "MWRYSZR[QZRYR[ RRSQGRFSGRSRF", + "JZNFNJ RVFVJ", + "H]LM[M RRDL_ RYVJV RS_YD", + "H\\LZO[T[VZWYXWXUWSVRTQPPNOMNLLLJMHNGPFUFXG RRCR^", + "F^J[ZF RMFOGPIOKMLKKJIKGMF RYZZXYVWUUVTXUZW[YZ", + "E_[[Z[XZUWPQNNMKMINGPFQFSGTITJSLRMLQKRJTJWKYLZN[Q[SZTYWUXRXP", + "MWSFQJ", + "KYVcUbS_R]QZPUPQQLRISGUDVC", + "KYNcObQ_R]SZTUTQSLRIQGODNC", + "JZRFRK RMIRKWI ROORKUO", + "E_JSZS RR[RK", + "MWSZS[R]Q^", + "E_JSZS", + "MWRYSZR[QZRYR[", + "G][EI`", + "H\\QFSFUGVHWJXNXSWWVYUZS[Q[OZNYMWLSLNMJNHOGQF", # /* U+30 DIGIT_0 */ + "H\\X[L[ RR[RFPINKLL", + "H\\LHMGOFTFVGWHXJXLWOK[X[", + "H\\KFXFQNTNVOWPXRXWWYVZT[N[LZKY", + "H\\VMV[ RQELTYT", + "H\\WFMFLPMOONTNVOWPXRXWWYVZT[O[MZLY", + "H\\VFRFPGOHMKLOLWMYNZP[T[VZWYXWXRWPVOTNPNNOMPLR", + "H\\KFYFP[", + "H\\PONNMMLKLJMHNGPFTFVGWHXJXKWMVNTOPONPMQLSLWMYNZP[T[VZWYXWXSWQVPTO", + "H\\N[R[TZUYWVXRXJWHVGTFPFNGMHLJLOMQNRPSTSVRWQXO", + "MWRYSZR[QZRYR[ RRNSORPQORNRP", + "MWSZS[R]Q^ RRNSORPQORNRP", + "E_ZMJSZY", + "E_JPZP RZVJV", + "E_JMZSJY", + "I[QYRZQ[PZQYQ[ RMGOFTFVGWIWKVMUNSORPQRQS", + "D_VQUPSOQOOPNQMSMUNWOXQYSYUXVW RVOVWWXXXZW[U[PYMVKRJNKKMIPHTIXK[N]R^V]Y[", # /* U+40 AT */ + "I[MUWU RK[RFY[", + "G\\SPVQWRXTXWWYVZT[L[LFSFUGVHWJWLVNUOSPLP", + "F[WYVZS[Q[NZLXKVJRJOKKLINGQFSFVGWH", + "G\\L[LFQFTGVIWKXOXRWVVXTZQ[L[", + "H[MPTP RW[M[MFWF", + "HZTPMP RM[MFWF", + "F[VGTFQFNGLIKKJOJRKVLXNZQ[S[VZWYWRSR", + "G]L[LF RLPXP RX[XF", + "MWR[RF", + "JZUFUUTXRZO[M[", + "G\\L[LF RX[OO RXFLR", + "HYW[M[MF", + "F^K[KFRUYFY[", + "G]L[LFX[XF", + "G]PFTFVGXIYMYTXXVZT[P[NZLXKTKMLINGPF", + "G\\L[LFTFVGWHXJXMWOVPTQLQ", # /* U+50 P_CAP */ + "G]Z]X\\VZSWQVOV RP[NZLXKTKMLINGPFTFVGXIYMYTXXVZT[P[", + "G\\X[QQ RL[LFTFVGWHXJXMWOVPTQLQ", + "H\\LZO[T[VZWYXWXUWSVRTQPPNOMNLLLJMHNGPFUFXG", + "JZLFXF RR[RF", + "G]LFLWMYNZP[T[VZWYXWXF", + "I[KFR[YF", + "F^IFN[RLV[[F", + "H\\KFY[ RYFK[", + "I[RQR[ RKFRQYF", + "H\\KFYFK[Y[", + "KYVbQbQDVD", + "KYID[_", + "KYNbSbSDND", + "LXNHREVH", + "JZJ]Z]", + "NVPESH", # /* U+60 GRAVE */ + "I\\W[WPVNTMPMNN RWZU[P[NZMXMVNTPSUSWR", + "H[M[MF RMNOMSMUNVOWQWWVYUZS[O[MZ", + "HZVZT[P[NZMYLWLQMONNPMTMVN", + "I\\W[WF RWZU[Q[OZNYMWMQNOONQMUMWN", + "I[VZT[P[NZMXMPNNPMTMVNWPWRMT", + "MYOMWM RR[RISGUFWF", + "I\\WMW^V`UaSbPbNa RWZU[Q[OZNYMWMQNOONQMUMWN", + "H[M[MF RV[VPUNSMPMNNMO", + "MWR[RM RRFQGRHSGRFRH", + "MWRMR_QaObNb RRFQGRHSGRFRH", + "IZN[NF RPSV[ RVMNU", + "MXU[SZRXRF", + "D`I[IM RIOJNLMOMQNRPR[ RRPSNUMXMZN[P[[", + "I\\NMN[ RNOONQMTMVNWPW[", + "H[P[NZMYLWLQMONNPMSMUNVOWQWWVYUZS[P[", + "H[MMMb RMNOMSMUNVOWQWWVYUZS[O[MZ", # /* U+70 P_SMALL */ + "I\\WMWb RWZU[Q[OZNYMWMQNOONQMUMWN", + "KXP[PM RPQQORNTMVM", + "J[NZP[T[VZWXWWVUTTQTOSNQNPONQMTMVN", + "MYOMWM RRFRXSZU[W[", + "H[VMV[ RMMMXNZP[S[UZVY", + "JZMMR[WM", + "G]JMN[RQV[ZM", + "IZL[WM RLMW[", + "JZMMR[ RWMR[P`OaMb", + "IZLMWML[W[", + "KYVcUcSbR`RVQTOSQRRPRFSDUCVC", + "H\\RbRD", + "KYNcOcQbR`RVSTUSSRRPRFQDOCNC", + "KZMSNRPQTSVRWQ", + "F^K[KFYFY[K[", + # /* // LATIN-1 SUPPLEMENT (0080-00FF) */ + "F^K[KFYFY[K[", # /* U+80 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+90 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "JZ", # /* U+A0 SPACE */ + "MWROQNRMSNRORM RRUSaRbQaRURb", + "HZVZT[P[NZMYLWLQMONNPMTMVN RRJR^", + "H[LMTM RL[W[ RO[OIPGRFUFWG", + "H]LYOV RLLOO RVVYY RVOYL RVVTWQWOVNTNQOOQNTNVOWQWTVV", + "F^JTZT RJMZM RRQR[ RKFRQYF", + "MWRbRW RRFRQ", + "I[N]P^S^U]V[UYOSNQNPONQM RVGTFQFOGNIOKUQVSVTUVSW", + "LXNFOGNHMGNFNH RVFWGVHUGVFVH", + "@dVKTJPJNKLMKOKSLUNWPXTXVW RRCMDHGELDQEVH[M^R_W^\\[_V`Q_L\\GWDRC", + "KZOEQDSDUEVGVN RVMTNQNOMNKOIQHVH", + "H\\RMLSRY RXWTSXO", + "E_JQZQZV", + "RR", + "@dWXRR RNXNJTJVKWMWOVQTRNR RRCMDHGELDQEVH[M^R_W^\\[_V`Q_L\\GWDRC", + "LXMGWG", + "JZRFPGOIPKRLTKUITGRF", # /* U+B0 DEGREE */ + "E_JOZO RRWRG RZ[J[", + "JZNAP@S@UAVCVEUGNNVN", + "JZN@V@RESEUFVHVKUMSNPNNM", + "NVTEQH", + "H^MMMb RWXXZZ[ RMXNZP[T[VZWXWM", + "F]VMV[ ROMOXNZL[ RZMMMKNJP", + "JZRRQSRTSSRRRT", + "MWR\\T]U_TaRbOb", + "JZVNNN RNCPBR@RN", + "KYQNOMNKNGOEQDSDUEVGVKUMSNQN", + "H\\RMXSRY RLWPSLO", + "G]KQYQ RVNNN RNCPBR@RN RUYUa RQSN]W]", + "G]KQYQ RVNNN RNCPBR@RN RNTPSSSUTVVVXUZNaVa", + "G]KQYQ RN@V@RESEUFVHVKUMSNPNNM RUYUa RQSN]W]", + "I[SORNSMTNSOSM RWaUbPbNaM_M]N[OZQYRXSVSU", + "I[MUWU RK[RFY[ RP>SA", # /* U+C0 A_CAP GRAVE */ + "I[MUWU RK[RFY[ RT>QA", + "I[MUWU RK[RFY[ RNAR>VA", + "I[MUWU RK[RFY[ RMAN@P?TAV@W?", + "I[MUWU RK[RFY[ RN?O@NAM@N?NA RV?W@VAU@V?VA", + "I[MUWU RK[RFY[ RRFPEOCPAR@TAUCTERF", + "F`JURU RRPYP RH[OF\\F RRFR[\\[", + "F[WYVZS[Q[NZLXKVJRJOKKLINGQFSFVGWH RR\\T]U_TaRbOb", + "H[MPTP RW[M[MFWF RP>SA", + "H[MPTP RW[M[MFWF RT>QA", + "H[MPTP RW[M[MFWF RNAR>VA", + "H[MPTP RW[M[MFWF RN?O@NAM@N?NA RV?W@VAU@V?VA", + "MWR[RF RP>SA", + "MWR[RF RT>QA", + "MWR[RF RNAR>VA", + "MWR[RF RN?O@NAM@N?NA RV?W@VAU@V?VA", + "G\\L[LFQFTGVIWKXOXRWVVXTZQ[L[ RIPQP", # /* U+D0 D_CAP STROKE_H */ + "G]L[LFX[XF RMAN@P?TAV@W?", + "G]PFTFVGXIYMYTXXVZT[P[NZLXKTKMLINGPF RP>SA", + "G]PFTFVGXIYMYTXXVZT[P[NZLXKTKMLINGPF RT>QA", + "G]PFTFVGXIYMYTXXVZT[P[NZLXKTKMLINGPF RNAR>VA", + "G]PFTFVGXIYMYTXXVZT[P[NZLXKTKMLINGPF RMAN@P?TAV@W?", + "G]PFTFVGXIYMYTXXVZT[P[NZLXKTKMLINGPF RN?O@NAM@N?NA RV?W@VAU@V?VA", + "E_LMXY RXMLY", + "G]ZFJ[ RP[NZLXKTKMLINGPFTFVGXIYMYTXXVZT[P[", + "G]LFLWMYNZP[T[VZWYXWXF RP>SA", + "G]LFLWMYNZP[T[VZWYXWXF RT>QA", + "G]LFLWMYNZP[T[VZWYXWXF RNAR>VA", + "G]LFLWMYNZP[T[VZWYXWXF RN?O@NAM@N?NA RV?W@VAU@V?VA", + "I[RQR[ RKFRQYF RT>QA", + "G\\LFL[ RLKTKVLWMXOXRWTVUTVLV", + "F]K[KJLHMGOFRFTGUHVJVMSMQNPPPQQSSTVTXUYWYXXZV[R[PZ", + "I\\W[WPVNTMPMNN RWZU[P[NZMXMVNTPSUSWR RPESH", # /* U+E0 A_SMALL GRAVE */ + "I\\W[WPVNTMPMNN RWZU[P[NZMXMVNTPSUSWR RTEQH", + "I\\W[WPVNTMPMNN RWZU[P[NZMXMVNTPSUSWR RNHREVH", + "I\\W[WPVNTMPMNN RWZU[P[NZMXMVNTPSUSWR RMHNGPFTHVGWF", + "I\\W[WPVNTMPMNN RWZU[P[NZMXMVNTPSUSWR RNFOGNHMGNFNH RVFWGVHUGVFVH", + "I\\W[WPVNTMPMNN RWZU[P[NZMXMVNTPSUSWR RRHPGOEPCRBTCUETGRH", + "D`INKMOMQNRP R[ZY[U[SZRXRPSNUMYM[N\\P\\RRSKSITHVHXIZK[O[QZRX", + "HZVZT[P[NZMYLWLQMONNPMTMVN RR\\T]U_TaRbOb", + "I[VZT[P[NZMXMPNNPMTMVNWPWRMT RPESH", + "I[VZT[P[NZMXMPNNPMTMVNWPWRMT RTEQH", + "I[VZT[P[NZMXMPNNPMTMVNWPWRMT RNHREVH", + "I[VZT[P[NZMXMPNNPMTMVNWPWRMT RNFOGNHMGNFNH RVFWGVHUGVFVH", + "MWR[RM RPESH", + "MWR[RM RTEQH", + "LXNHREVH RR[RM", + "LXNFOGNHMGNFNH RVFWGVHUGVFVH RR[RM", + "I\\SCQI RWNUMQMONNOMQMXNZP[T[VZWXWLVITGRFNE", # /* U+F0 ETH_SMALL */ + "I\\NMN[ RNOONQMTMVNWPW[ RMHNGPFTHVGWF", + "H[P[NZMYLWLQMONNPMSMUNVOWQWWVYUZS[P[ RPESH", + "H[P[NZMYLWLQMONNPMSMUNVOWQWWVYUZS[P[ RTEQH", + "H[P[NZMYLWLQMONNPMSMUNVOWQWWVYUZS[P[ RNHREVH", + "H[P[NZMYLWLQMONNPMSMUNVOWQWWVYUZS[P[ RMHNGPFTHVGWF", + "H[P[NZMYLWLQMONNPMSMUNVOWQWWVYUZS[P[ RNFOGNHMGNFNH RVFWGVHUGVFVH", + "E_ZSJS RRXSYRZQYRXRZ RRLSMRNQMRLRN", + "H[XMK[ RP[NZMYLWLQMONNPMSMUNVOWQWWVYUZS[P[", + "H[VMV[ RMMMXNZP[S[UZVY RPESH", + "H[VMV[ RMMMXNZP[S[UZVY RTEQH", + "H[VMV[ RMMMXNZP[S[UZVY RNHREVH", + "H[VMV[ RMMMXNZP[S[UZVY RNFOGNHMGNFNH RVFWGVHUGVFVH", + "JZMMR[ RWMR[P`OaMb RTEQH", + "H[MFMb RMNOMSMUNVOWQWWVYUZS[O[MZ", + "JZMMR[ RWMR[P`OaMb RNFOGNHMGNFNH RVFWGVHUGVFVH", + # /* // LATIN EXTENDED-A (0100-017F) */ + "I[MUWU RK[RFY[ RM@W@", # /* U+100 A_CAP MACRON */ + "I\\W[WPVNTMPMNN RWZU[P[NZMXMVNTPSUSWR RMGWG", + "I[MUWU RK[RFY[ RN>O@QASAU@V>", + "I\\W[WPVNTMPMNN RWZU[P[NZMXMVNTPSUSWR RNEOGQHSHUGVE", + "I[MUWU RK[RFY[ RY[W]V_WaYb[b", + "I\\W[WPVNTMPMNN RWZU[P[NZMXMVNTPSUSWR RW[U]T_UaWbYb", + "F[WYVZS[Q[NZLXKVJRJOKKLINGQFSFVGWH RT>QA", + "HZVZT[P[NZMYLWLQMONNPMTMVN RTEQH", + "F[WYVZS[Q[NZLXKVJRJOKKLINGQFSFVGWH RNAR>VA", + "HZVZT[P[NZMYLWLQMONNPMTMVN RNHREVH", + "F[WYVZS[Q[NZLXKVJRJOKKLINGQFSFVGWH RR?Q@RAS@R?RA", + "HZVZT[P[NZMYLWLQMONNPMTMVN RRFQGRHSGRFRH", + "F[WYVZS[Q[NZLXKVJRJOKKLINGQFSFVGWH RN>RAV>", + "HZVZT[P[NZMYLWLQMONNPMTMVN RNERHVE", + "G\\L[LFQFTGVIWKXOXRWVVXTZQ[L[ RN>RAV>", + "IfW[WF RWZU[Q[OZNYMWMQNOONQMUMWN RbF`J", + "G\\L[LFQFTGVIWKXOXRWVVXTZQ[L[ RIPQP", # /* U+110 D_CAP STROKE_H */ + "I\\W[WF RWZU[Q[OZNYMWMQNOONQMUMWN RRHZH", + "H[MPTP RW[M[MFWF RM@W@", + "I[VZT[P[NZMXMPNNPMTMVNWPWRMT RMGWG", + "H[MPTP RW[M[MFWF RN>O@QASAU@V>", + "I[VZT[P[NZMXMPNNPMTMVNWPWRMT RNEOGQHSHUGVE", + "H[MPTP RW[M[MFWF RR?Q@RAS@R?RA", + "I[VZT[P[NZMXMPNNPMTMVNWPWRMT RRFQGRHSGRFRH", + "H[MPTP RW[M[MFWF RR[P]O_PaRbTb", + "I[VZT[P[NZMXMPNNPMTMVNWPWRMT RR[P]O_PaRbTb", + "H[MPTP RW[M[MFWF RN>RAV>", + "I[VZT[P[NZMXMPNNPMTMVNWPWRMT RNERHVE", + "F[VGTFQFNGLIKKJOJRKVLXNZQ[S[VZWYWRSR RNAR>VA", + "I\\WMW^V`UaSbPbNa RWZU[Q[OZNYMWMQNOONQMUMWN RNHREVH", + "F[VGTFQFNGLIKKJOJRKVLXNZQ[S[VZWYWRSR RN>O@QASAU@V>", + "I\\WMW^V`UaSbPbNa RWZU[Q[OZNYMWMQNOONQMUMWN RNEOGQHSHUGVE", + "F[VGTFQFNGLIKKJOJRKVLXNZQ[S[VZWYWRSR RR?Q@RAS@R?RA", # /* U+120 G_CAP DOT */ + "I\\WMW^V`UaSbPbNa RWZU[Q[OZNYMWMQNOONQMUMWN RRFQGRHSGRFRH", + "F[VGTFQFNGLIKKJOJRKVLXNZQ[S[VZWYWRSR RR\\T]U_TaRbOb", + "I\\WMW^V`UaSbPbNa RWZU[Q[OZNYMWMQNOONQMUMWN RRGPFODPBRAUA", + "G]L[LF RLPXP RX[XF RNAR>VA", + "H[M[MF RV[VPUNSMPMNNMO RIAM>QA", + "G]IJ[J RL[LF RLPXP RX[XF", + "H[M[MF RV[VPUNSMPMNNMO RJHRH", + "MWR[RF RMAN@P?TAV@W?", + "MWR[RM RMHNGPFTHVGWF", + "MWR[RF RM@W@", + "MWR[RM RMGWG", + "MWR[RF RN>O@QASAU@V>", + "MWR[RM RNEOGQHSHUGVE", + "MWR[RF RR[P]O_PaRbTb", + "MWR[RM RR[P]O_PaRbTb", + "MWR[RF RR?Q@RAS@R?RA", # /* U+130 I_CAP DOT */ + "MWR[RM", + "MgR[RF RbFbUaX_Z\\[Z[", + "MaR[RM RRFQGRHSGRFRH R\\M\\_[aYbXb R\\F[G\\H]G\\F\\H", + "JZUFUUTXRZO[M[ RQAU>YA", + "MWRMR_QaObNb RNHREVH", + "G\\L[LF RX[OO RXFLR RR\\T]U_TaRbOb", + "IZN[NF RPSV[ RVMNU RR\\T]U_TaRbOb", + "IZNMN[ RPSV[ RVMNU", + "HYW[M[MF RO>LA", + "MXU[SZRXRF RTEQH", + "HYW[M[MF RR\\T]U_TaRbOb", + "MXU[SZRXRF RR\\T]U_TaRbOb", + "HYW[M[MF RVHSK", + "M^U[SZRXRF RZFXJ", + "HYW[M[MF RUNTOUPVOUNUP", + "M\\U[SZRXRF RYOZPYQXPYOYQ", # /* U+140 L_SMALL_MIDDOT */ + "HYW[M[MF RJQPM", + "MXU[SZRXRF ROQUM", + "G]L[LFX[XF RT>QA", + "I\\NMN[ RNOONQMTMVNWPW[ RTEQH", + "G]L[LFX[XF RR\\T]U_TaRbOb", + "I\\NMN[ RNOONQMTMVNWPW[ RR\\T]U_TaRbOb", + "G]L[LFX[XF RN>RAV>", + "I\\NMN[ RNOONQMTMVNWPW[ RNERHVE", + "MjSFQJ R\\M\\[ R\\O]N_MbMdNePe[", + "G]LFL[ RLINGPFTFVGWHXJX^W`VaTbQb", + "I\\NMN[ RNOONQMTMVNWPW_VaTbRb", + "G]PFTFVGXIYMYTXXVZT[P[NZLXKTKMLINGPF RM@W@", + "H[P[NZMYLWLQMONNPMSMUNVOWQWWVYUZS[P[ RMGWG", + "G]PFTFVGXIYMYTXXVZT[P[NZLXKTKMLINGPF RN>O@QASAU@V>", + "H[P[NZMYLWLQMONNPMSMUNVOWQWWVYUZS[P[ RNEOGQHSHUGVE", + "G]PFTFVGXIYMYTXXVZT[P[NZLXKTKMLINGPF RQ>NA RX>UA", # /* U+150 O_CAP ACUTE_DBL */ + "H[P[NZMYLWLQMONNPMSMUNVOWQWWVYUZS[P[ RQENH RXEUH", + "E`RPYP RRFR[ R\\FNFLGJIIMITJXLZN[\\[", + "C`[ZY[U[SZRXRPSNUMYM[N\\P\\RRT RRQQOPNNMKMINHOGQGWHYIZK[N[PZQYRW", + "G\\X[QQ RL[LFTFVGWHXJXMWOVPTQLQ RT>QA", + "KXP[PM RPQQORNTMVM RTEQH", + "G\\X[QQ RL[LFTFVGWHXJXMWOVPTQLQ RR\\T]U_TaRbOb", + "KXP[PM RPQQORNTMVM RR\\T]U_TaRbOb", + "G\\X[QQ RL[LFTFVGWHXJXMWOVPTQLQ RN>RAV>", + "KXP[PM RPQQORNTMVM RNERHVE", + "H\\LZO[T[VZWYXWXUWSVRTQPPNOMNLLLJMHNGPFUFXG RT>QA", + "J[NZP[T[VZWXWWVUTTQTOSNQNPONQMTMVN RTEQH", + "H\\LZO[T[VZWYXWXUWSVRTQPPNOMNLLLJMHNGPFUFXG RNAR>VA", + "J[NZP[T[VZWXWWVUTTQTOSNQNPONQMTMVN RNHREVH", + "H\\LZO[T[VZWYXWXUWSVRTQPPNOMNLLLJMHNGPFUFXG RR\\T]U_TaRbOb", + "J[NZP[T[VZWXWWVUTTQTOSNQNPONQMTMVN RR\\T]U_TaRbOb", + "H\\LZO[T[VZWYXWXUWSVRTQPPNOMNLLLJMHNGPFUFXG RN>RAV>", # /* U+160 S_CAP CARON */ + "J[NZP[T[VZWXWWVUTTQTOSNQNPONQMTMVN RNERHVE", + "JZLFXF RR[RF RR\\T]U_TaRbOb", + "MYOMWM RRFRXSZU[W[ RR\\T]U_TaRbOb", + "JZLFXF RR[RF RN>RAV>", + "M[OMWM RYFXI RRFRXSZU[W[", + "JZLFXF RR[RF RNQVQ", + "MYOMWM RRFRXSZU[W[ ROSUS", + "G]LFLWMYNZP[T[VZWYXWXF RMAN@P?TAV@W?", + "H[VMV[ RMMMXNZP[S[UZVY RMHNGPFTHVGWF", + "G]LFLWMYNZP[T[VZWYXWXF RM@W@", + "H[VMV[ RMMMXNZP[S[UZVY RMGWG", + "G]LFLWMYNZP[T[VZWYXWXF RN>O@QASAU@V>", + "H[VMV[ RMMMXNZP[S[UZVY RNEOGQHSHUGVE", + "G]LFLWMYNZP[T[VZWYXWXF RRAP@O>PT@RA", + "H[VMV[ RMMMXNZP[S[UZVY RRHPGOEPCRBTCUETGRH", + "G]LFLWMYNZP[T[VZWYXWXF RQ>NA RX>UA", # /* U+170 U_CAP ACUTE_DBL */ + "H[VMV[ RMMMXNZP[S[UZVY RQENH RXEUH", + "G]LFLWMYNZP[T[VZWYXWXF RR[P]O_PaRbTb", + "H[VMV[ RMMMXNZP[S[UZVY RV[T]S_TaVbXb", + "F^IFN[RLV[[F RNAR>VA", + "G]JMN[RQV[ZM RNHREVH", + "I[RQR[ RKFRQYF RNAR>VA", + "JZMMR[ RWMR[P`OaMb RNHREVH", + "JZLFXF RR[RF RN?O@NAM@N?NA RV?W@VAU@V?VA", + "H\\KFYFK[Y[ RT>QA", + "IZLMWML[W[ RTEQH", + "H\\KFYFK[Y[ RR?Q@RAS@R?RA", + "IZLMWML[W[ RRFQGRHSGRFRH", + "H\\KFYFK[Y[ RN>RAV>", + "IZLMWML[W[ RNERHVE", + "MYR[RISGUFWF", + # /* // LATIN EXTENDED-B (0180-024F) */ + "H[M[MF RMNOMSMUNVOWQWWVYUZS[O[MZ RJHRH", # /* U+180 B_SMALL STROKE_H */ + "C\\LFL[T[VZWYXWXTWRVQSPLP RFKFIGGIFSFUGVHWJWLVNUOSP", + "G\\VFLFL[R[UZWXXVXSWQUORNLN", + "H[WFMFM[ RMNOMSMUNVOWQWWVYUZS[O[MZ", + "H]MFM[S[VZXXYVYSXQVOSNMN", + "IZNMN[S[UZVXVUUSSRNR", + "I^MHNGQFSFVGXIYKZOZRYVXXVZS[Q[NZMY", + "F[WYVZS[Q[NZLXKVJRJOKKLINGQFSFVGWH RMHKGJEKCLB", + "HZVZT[P[NZMYLWLQMONNPMTMVN RTMTIUGWFYF", + "G\\L[LFQFTGVIWKXOXRWVVXTZQ[L[ RIPQP", + "C\\FKFIGGIFQFTGVIWKXOXRWVVXTZQ[L[LF", + "H]NFXFX[R[OZMXLVLSMQOORNXN", + "I\\MFWFW[ RWNUMQMONNOMQMWNYOZQ[U[WZ", + "I\\Q[T[VZWYXWXQWOVNTMQMONNOMQMWNYOZQ[T\\V]W_VaTbPbNa", + "I\\WPPP RM[W[WFMF", + "F^MHNGQFSFVGXIYKZOZRYVXXVZS[Q[NZLXKVJRZP", + "G[PPTP RWGUFPFNGMHLJLLMNNOPPMQLRKTKWLYMZO[U[WZ", # /* U+190 EPSILON_LARGE */ + "HZTPMP RM[MFWF RM[M_LaJbHb", + "MYOMWM RR[RISGUFWF RR[R_QaObMb", + "F[VGTFQFNGLIKKJOJRKVLXNZQ[S[VZWYWRSR RMHKGJEKCLB", + "I[KFU[U_TaRbPaO_O[YF", + "D`I[IF RIOJNLMOMQNRPRXSZU[X[ZZ[Y\\W\\P[NZM", + "MZRFRWSYTZV[X[", + "MWR[RF RNPVP", + "G_L[LF RX[OO RLRWGYF[G\\I\\K", + "IZNMN[ RPSV[ RVMNU RNMNIOGQFSF", + "MXU[SZRXRF RNOVO", + "JZRMM[ RMFOFPGRMW[ RNLTH", + "Ca\\F\\[ R\\XZZX[V[TZSYRWRF RRWQYPZN[L[JZIYHWHF", + "G]L[LFX[XF RL[L_KaIbGb", + "I\\NMN[ RNOONQMTMVNWPWb", + "G]KPYP RPFTFVGXIYMYTXXVZT[P[NZLXKTKMLINGPF", + "G]PFTFVGXIYMYTXXVZT[P[NZLXKTKMLINGPF RVGXFYDXBWA", # /* U+1A0 O_CAP HORN */ + "H[P[NZMYLWLQMONNPMSMUNVOWQWWVYUZS[P[ RUNWMXKWIVH", + "DaSGQFMFKGIIHMHTIXKZM[Q[SZUXVTVMUISGUFYF[G\\I\\b", + "E^RNPMMMKNJOIQIWJYKZM[P[RZSYTWTQSORNTMVMXNYPYb", + "C\\LFL[ RFKFIGGIFTFVGWHXJXMWOVPTQLQ", + "H[MMMb RMNOMSMUNVOWQWWVYUZS[O[MZ RRMRISGUFWF", + "G\\LFL[ RQVXb RLKTKVLWMXOXRWTVUTVLV", + "H\\XZU[P[NZMYLWLUMSNRPQTPVOWNXLXJWHVGTFOFLG", + "IZVZT[P[NZMXMWNUPTSTUSVQVPUNSMPMNN", + "H[W[L[SPLFWF", + "JYWbUbSaR_RIQGOFMGLIMKOLQKRI", + "MYOMWM RRFRXSZU[W[ RW[W_VaTbRb", + "HZR[RF RKKKILGNFXF", + "MYOMWM RWFUFSGRIRXSZU[W[", + "JZLFXF RR[RF RR[R_SaUbWb", + "G]LFLWMYNZP[T[VZWYXWXF RXFZE[CZAY@", + "H[VMV[ RMMMXNZP[S[UZVY RVMXLYJXHWG", # /* U+1B0 U_SMALL HORN */ + "F^ZFUFUJWKYMZPZUYXWZT[P[MZKXJUJPKMMKOJOFJF", + "G]LFLWMYNZP[T[VZXXYVYIXGWF", + "I`RQR[ RKFRQXGZF\\G]I]K", + "J^MMR[ RMbOaP`R[VNXMZN[P[R", + "H\\KFYFK[Y[ RNPVP", + "IZLMWML[W[ RNTVT", + "H\\KFXFQNTNVOWPXRXWWYVZT[N[LZKY", + "H\\YFLFSNPNNOMPLRLWMYNZP[V[XZYY", + "JZWMNMUVRVPWOXNZN^O`PaRbUbWa", + "JZMMVMOTSTUUVWVXUZS[Q[O\\N^N_OaQbVb", + "H\\LHMGOFTFVGWHXJXLWOK[X[ RNSVS", + "H\\WFMFLPMOONTNVOWPXRXWWYVZT[O[MZLY", + "JZVMOMNSPRSRUSVUVXUZS[P[NZ", + "J^MZP[T[WZYXZVZSYQWOTNPNPF RLITI", + "H[MMMb RMONNPMTMVNWPWSVUM^", + "MWRFRb", # /* U+1C0 LINE_V_LETTER */ + "JZOFOb RUFUb", + "MWRFRb ROWUW ROQUQ", + "MWRYSZR[QZRYR[ RRSQGRFSGRSRF", + "GpL[LFQFTGVIWKXOXRWVVXTZQ[L[ R_FmF_[m[ Rb>fAj>", + "GmL[LFQFTGVIWKXOXRWVVXTZQ[L[ R_MjM_[j[ RaEeHiE", + "ImW[WF RWZU[Q[OZNYMWMQNOONQMUMWN R_MjM_[j[ RaEeHiE", + "HiW[M[MF RdFdUcXaZ^[\\[", + "HcW[M[MF R^M^_]a[bZb R^F]G^H_G^F^H", + "MbU[SZRXRF R]M]_\\aZbYb R]F\\G]H^G]F]H", + "GmL[LFX[XF RhFhUgXeZb[`[", + "GgL[LFX[XF RbMb_aa_b^b RbFaGbHcGbFbH", + "IfNMN[ RNOONQMTMVNWPW[ RaMa_`a^b]b RaF`GaHbGaFaH", + "I[MUWU RK[RFY[ RN>RAV>", + "I\\W[WPVNTMPMNN RWZU[P[NZMXMVNTPSUSWR RNERHVE", + "MWR[RF RN>RAV>", + "MWR[RM RNERHVE", # /* U+1D0 I_SMALL CARON */ + "G]PFTFVGXIYMYTXXVZT[P[NZLXKTKMLINGPF RN>RAV>", + "H[P[NZMYLWLQMONNPMSMUNVOWQWWVYUZS[P[ RNERHVE", + "G]LFLWMYNZP[T[VZWYXWXF RN>RAV>", + "H[VMV[ RMMMXNZP[S[UZVY RNERHVE", + "G]LFLWMYNZP[T[VZWYXWXF RN?O@NAM@N?NA RV?W@VAU@V?VA RM;W;", + "H[VMV[ RMMMXNZP[S[UZVY RNFOGNHMGNFNH RVFWGVHUGVFVH RM@W@", + "G]LFLWMYNZP[T[VZWYXWXF RN?O@NAM@N?NA RV?W@VAU@V?VA RT9Q<", + "H[VMV[ RMMMXNZP[S[UZVY RNFOGNHMGNFNH RVFWGVHUGVFVH RT>QA", + "G]LFLWMYNZP[T[VZWYXWXF RN?O@NAM@N?NA RV?W@VAU@V?VA RN9RRAV>", + "G]LFLWMYNZP[T[VZWYXWXF RN?O@NAM@N?NA RV?W@VAU@V?VA RP9S<", + "H[VMV[ RMMMXNZP[S[UZVY RNFOGNHMGNFNH RVFWGVHUGVFVH RP>SA", + "I[NNPMTMVNWPWXVZT[P[NZMXMVWT", + "I[MUWU RK[RFY[ RN?O@NAM@N?NA RV?W@VAU@V?VA RM;W;", + "I\\W[WPVNTMPMNN RWZU[P[NZMXMVNTPSUSWR RNFOGNHMGNFNH RVFWGVHUGVFVH RM@W@", + "I[MUWU RK[RFY[ RR?Q@RAS@R?RA RM;W;", # /* U+1E0 A_CAP DOT */ + "I\\W[WPVNTMPMNN RWZU[P[NZMXMVNTPSUSWR RRFQGRHSGRFRH RM@W@", + "F`JURU RRPYP RH[OF\\F RRFR[\\[ RO@Y@", + "D`INKMOMQNRP R[ZY[U[SZRXRPSNUMYM[N\\P\\RRSKSITHVHXIZK[O[QZRX RMGWG", + "F[VGTFQFNGLIKKJOJRKVLXNZQ[S[VZWYWRSR RSV[V", + "I\\WMW^V`UaSbPbNa RWZU[Q[OZNYMWMQNOONQMUMWN RS^[^", + "F[VGTFQFNGLIKKJOJRKVLXNZQ[S[VZWYWRSR RN>RAV>", + "I\\WMW^V`UaSbPbNa RWZU[Q[OZNYMWMQNOONQMUMWN RNERHVE", + "G\\L[LF RX[OO RXFLR RN>RAV>", + "IZN[NF RPSV[ RVMNU RJANDRA", + "G]R[P]O_PaRbTb RPFTFVGXIYMYTXXVZT[P[NZLXKTKMLINGPF", + "H[R[P]O_PaRbTb RP[NZMYLWLQMONNPMSMUNVOWQWWVYUZS[P[", + "G]R[P]O_PaRbTb RPFTFVGXIYMYTXXVZT[P[NZLXKTKMLINGPF RM@W@", + "H[R[P]O_PaRbTb RP[NZMYLWLQMONNPMSMUNVOWQWWVYUZS[P[ RMGWG", + "H\\KFXFQNTNVOWPXRXWWYVZT[N[LZKY RN>RAV>", + "JZMMVMOVRVTWUXVZV^U`TaRbObMa RNERHVE", + "MWRMR_QaObNb RNERHVE", # /* U+1F0 J_SMALL CARON */ + "GpL[LFQFTGVIWKXOXRWVVXTZQ[L[ R_FmF_[m[", + "GmL[LFQFTGVIWKXOXRWVVXTZQ[L[ R_MjM_[j[", + "ImW[WF RWZU[Q[OZNYMWMQNOONQMUMWN R_MjM_[j[", + "F[VGTFQFNGLIKKJOJRKVLXNZQ[S[VZWYWRSR RT>QA", + "I\\WMW^V`UaSbPbNa RWZU[Q[OZNYMWMQNOONQMUMWN RTEQH", + "CaH[HF RHPTP RTFTXUZW[Z[\\Z]X]M", + "G\\LFLb RLINGPFTFVGWHXJXOWRUUL^", + "G]L[LFX[XF RP>SA", + "I\\NMN[ RNOONQMTMVNWPW[ RPESH", + "I[MUWU RK[RFY[ RZ9X< RR;PP@RAT@U>TSA", + "D`INKMOMQNRP R[ZY[U[SZRXRPSNUMYM[N\\P\\RRSKSITHVHXIZK[O[QZRX RTEQH", + "G]ZFJ[ RP[NZLXKTKMLINGPFTFVGXIYMYTXXVZT[P[ RT>QA", + "H[XMK[ RP[NZMYLWLQMONNPMSMUNVOWQWWVYUZS[P[ RTEQH", + "I[MUWU RK[RFY[ ROAL> RVAS>", # /* U+200 A_CAP GRAVE_DBL */ + "I\\W[WPVNTMPMNN RWZU[P[NZMXMVNTPSUSWR ROHLE RVHSE", + "I[MUWU RK[RFY[ RNAO?Q>S>U?VA", + "I\\W[WPVNTMPMNN RWZU[P[NZMXMVNTPSUSWR RNHOFQESEUFVH", + "H[MPTP RW[M[MFWF ROAL> RVAS>", + "I[VZT[P[NZMXMPNNPMTMVNWPWRMT ROHLE RVHSE", + "H[MPTP RW[M[MFWF RNAO?Q>S>U?VA", + "I[VZT[P[NZMXMPNNPMTMVNWPWRMT RNHOFQESEUFVH", + "MWR[RF ROAL> RVAS>", + "MWR[RM ROHLE RVHSE", + "MWR[RF RNAO?Q>S>U?VA", + "MWR[RM RNHOFQESEUFVH", + "G]PFTFVGXIYMYTXXVZT[P[NZLXKTKMLINGPF ROAL> RVAS>", + "H[P[NZMYLWLQMONNPMSMUNVOWQWWVYUZS[P[ ROHLE RVHSE", + "G]PFTFVGXIYMYTXXVZT[P[NZLXKTKMLINGPF RNAO?Q>S>U?VA", + "H[P[NZMYLWLQMONNPMSMUNVOWQWWVYUZS[P[ RNHOFQESEUFVH", + "G\\X[QQ RL[LFTFVGWHXJXMWOVPTQLQ ROAL> RVAS>", # /* U+210 R_CAP GRAVE_DBL */ + "KXP[PM RPQQORNTMVM RPHME RWHTE", + "G\\X[QQ RL[LFTFVGWHXJXMWOVPTQLQ RNAO?Q>S>U?VA", + "KXP[PM RPQQORNTMVM ROHPFRETEVFWH", + "G]LFLWMYNZP[T[VZWYXWXF ROAL> RVAS>", + "H[VMV[ RMMMXNZP[S[UZVY ROHLE RVHSE", + "G]LFLWMYNZP[T[VZWYXWXF RNAO?Q>S>U?VA", + "H[VMV[ RMMMXNZP[S[UZVY RNHOFQESEUFVH", + "H\\LZO[T[VZWYXWXUWSVRTQPPNOMNLLLJMHNGPFUFXG RS`SaRcQd", + "J[NZP[T[VZWXWWVUTTQTOSNQNPONQMTMVN RS`SaRcQd", + "JZLFXF RR[RF RS`SaRcQd", + "MYOMWM RRFRXSZU[W[ RU`UaTcSd", + "I]VRXTYVY[X]V_T`Lb RLHMGOFUFWGXHYJYNXPVRTSNU", + "J[UWVXWZW]V_U`SaMb RMNOMSMUNVOWQWTVVUWSXOY", + "G]L[LF RLPXP RX[XF RN>RAV>", + "H[M[MF RV[VPUNSMPMNNMO RI>MAQ>", + "G]L[LFX[XF RX[Xb", # /* U+220 N_CAP LEG */ + "IbWFWXXZZ[\\[^Z_X^V\\UZVV^ RWNUMQMONNOMQMWNYOZQ[T[VZWX", + "G]NFLGKIKKLMMNOO RVFXGYIYKXMWNUO ROOUOWPXQYSYWXYWZU[O[MZLYKWKSLQMPOO", + "J[MJMMNORQVOWMWJ RPQTQVRWTWXVZT[P[NZMXMTNRPQ", + "H\\KFYFK[Y[ RY[Y_XaVbTb", + "IZLMWML[W[ RW[W_VaTbRb", + "I[MUWU RK[RFY[ RR?Q@RAS@R?RA", + "I\\W[WPVNTMPMNN RWZU[P[NZMXMVNTPSUSWR RRFQGRHSGRFRH", + "H[MPTP RW[M[MFWF RR\\T]U_TaRbOb", + "I[VZT[P[NZMXMPNNPMTMVNWPWRMT RR\\T]U_TaRbOb", + "G]PFTFVGXIYMYTXXVZT[P[NZLXKTKMLINGPF RN?O@NAM@N?NA RV?W@VAU@V?VA RM;W;", + "H[P[NZMYLWLQMONNPMSMUNVOWQWWVYUZS[P[ RNFOGNHMGNFNH RVFWGVHUGVFVH RM@W@", + "G]PFTFVGXIYMYTXXVZT[P[NZLXKTKMLINGPF RMAN@P?TAV@W? RM;W;", + "H[P[NZMYLWLQMONNPMSMUNVOWQWWVYUZS[P[ RMHNGPFTHVGWF RM@W@", + "G]PFTFVGXIYMYTXXVZT[P[NZLXKTKMLINGPF RR?Q@RAS@R?RA", + "H[P[NZMYLWLQMONNPMSMUNVOWQWWVYUZS[P[ RRFQGRHSGRFRH", + "G]PFTFVGXIYMYTXXVZT[P[NZLXKTKMLINGPF RR?Q@RAS@R?RA RM;W;", # /* U+230 O_CAP DOT */ + "H[P[NZMYLWLQMONNPMSMUNVOWQWWVYUZS[P[ RRFQGRHSGRFRH RM@W@", + "I[RQR[ RKFRQYF RM@W@", + "JZMMR[ RWMR[P`OaMb RMGWG", + "M]RFRXSZU[W[YZZXYVWUUVQ^", + "IbNMN[ RNOONQMTMVNWPWXXZZ[\\[^Z_X^V\\UZVV^", + "M]OMWM RRFRXSZU[W[YZZXYVWUUVQ^", + "MWRMR_QaObNb", + "D`R[RF RRZP[L[JZIYHWHQIOJNLMPMRN RTMXMZN[O\\Q\\W[YZZX[T[RZ", + "D`RMRb RRZP[L[JZIYHWHQIOJNLMPMRN RTMXMZN[O\\Q\\W[YZZX[T[RZ", + "I[MUWU RK[RFY[ RXCL`", + "F[WYVZS[Q[NZLXKVJRJOKKLINGQFSFVGWH RXCL`", + "HZVZT[P[NZMYLWLQMONNPMTMVN RWHM`", + "HYW[M[MF RIOQO", + "JZLFXF RR[RF RXCL`", + "J[P[R^T_W_ RNZP[T[VZWXWWVUTTQTOSNQNPONQMTMVN", + "IZLMWML[N[P\\R^T_W_", # /* U+240 Z_SMALL_SWASHTAIL */ + "J^MGPFTFWGYIZKZNYPWRTSPSP[", + "J^NNPMTMVNWOXQXSWUVVTWPWP[", + "G\\SPVQWRXTXWWYVZT[L[LFSFUGVHWJWLVNUOSPLP RIUOU", + "G]IM[M RLFLWMYNZP[T[VZWYXWXF", + "I[Y[RFK[", + "H[MPTP RW[M[MFWF RXCL`", + "I[VZT[P[NZMXMPNNPMTMVNWPWRMT RWHM`", + "JZUFUUTXRZO[M[ RQPYP", + "MWRMR_QaObNb ROTUT RRFQGRHSGRFRH", + "G]XFX^Y`Za\\b^b RXIVGTFPFNGLIKMKTLXNZP[T[VZXX", + "I\\WMW^X`Ya[b]b RWZU[Q[OZNYMWMQNOONQMUMWN", + "G\\X[QQ RL[LFTFVGWHXJXMWOVPTQLQ RIQOQ", + "KXP[PM RPQQORNTMVM RMTUT", + "I[KIYI RRQR[ RKFRQYF", + "JZLQXQ RMMR[ RWMR[P`OaMb", + # /* // IPA EXTENSIONS (0250-02AF) */ + "H[MMMXNZP[T[VZ RMNOMTMVNWPWRVTTUOUMV", # /* U+250 +A_SMALL */ + "H]YMVWUYTZR[P[NZMYLVLRMONNPMRMTNUOVQWXXZZ[", + "G\\K[NQOOPNRMTMVNWOXRXVWYVZT[R[PZOYNWMPLNJM", + "H[RFPFNGMIM[ RMNOMSMUNVOWQWWVYUZS[O[MZ", + "J\\NNPMTMVNWOXQXWWYVZT[P[NZ", + "HZVNTMPMNNMOLQLWMYNZP[S[UZVXUVSUQVM^", + "I\\W[WF RWZU[Q[OZNYMWMQNOONQMUMWN RW[W_XaZb\\b", + "I\\\\FZFXGWIW[ RWZU[Q[OZNYMWMQNOONQMUMWN", + "I[NZP[T[VZWXWPVNTMPMNNMPMRWT", + "I[NNPMTMVNWPWXVZT[P[NZMXMVWT", + "IbNNPMTMVNWPWXVZT[P[NZMXMV\\S\\U]W_X`X", + "IZPTNUMWMXNZP[T[VZ RRTPTNSMQMPNNPMTMVN", + "J[TTVSWQWPVNTMPMNN RRTTTVUWWWXVZT[P[NZ", + "JaRTTTVUWWWXVZT[P[NZ RNNPMTMVNWPWQVSTT[S[U\\W^X_X", + "H[TTVSWQWPVNTMPMNNMOLRLVMYNZP[T[VZWXWWVUTTRT", + "MWRMR_QaObNb ROTUT", + "I\\WMW^V`UaSbPbNa RWZU[Q[OZNYMWMQNOONQMUMWN RWMWIXGZF\\F", # /* U+260 G_SMALL +HOOK */ + "I\\WYVZT[P[NZMXMQNOONQMWMW^V`UaSbMb", + "HZUNSMPMNNMOLQLWMYNZP[T[VZVUSU", + "JZMMU[U_TaRbPaO_O[WM", + "JZMMTVUXTZR[PZOXPVWM", + "I\\WMWb RNMNXOZQ[T[VZWY", + "H[RFPFNGMIM[ RV[VPUNSMPMNNMO", + "H[RFPFNGMIM[ RV[VPUNSMPMNNMO RV[V_UaSbQb", + "MWR[RM ROTUT RRFQGRHSGRFRH", + "MXRMRXSZU[", + "MWR[RM RU[O[ RUMOM", + "MXU[SZRXRF RMONNPMTOVNWM", + "IYU[SZRXRF RRQQOONMOLQMSOTWT", + "MXRFR_SaUbWb", + "GZLFLXMZO[ RLMVMOVRVTWUXVZV^U`TaRbObMa", + "D`[M[[ R[YZZX[U[SZRXRM RRXQZO[L[JZIXIM", + "D`[M[[ R[YZZX[U[SZRXRM RRXQZO[L[JZIXIM R[[[b", # /* U+270 +M_SMALL LEG */ + "D`I[IM RIOJNLMOMQNRPR[ RRPSNUMXMZN[P[[ R[[[_ZaXbVb", + "I\\NMN[ RNOONQMTMVNWPW[ RN[N_MaKbIb", + "I\\NMN[ RNOONQMTMVNWPW[ RW[W_XaZb\\b", + "H[M[MMV[VM", + "H[LTWT RP[NZMYLWLQMONNPMSMUNVOWQWWVYUZS[P[", + "E]RTXT RRMR[ RZMMMKNJOIQIWJYKZM[Z[", + "G]RTRXSZU[V[XZYXYQXOWNUMOMMNLOKQKXLZN[O[QZRX", + "G]RFRb RPMTMVNXPYRYVXXVZT[P[NZLXKVKRLPNNPM", + "LYTMT[ RTWSYRZP[N[", + "LYTMT[ RTWSYRZP[N[ RTMTF", + "LYTMT[ RTWSYRZP[N[ RT[T_UaWbYb", + "KXP[PM RPQQORNTMVM RP[Pb", + "KXP[PM RPQQORNTMVM RP[P_QaSbUb", + "KXM[S[ RVMTMRNQOPRP[", + "LYW[Q[ RNMPMRNSOTRT[", + "I[RUW[ RN[NMTMVNWPWRVTTUNU", # /* U+280 R_SMALLCAP */ + "I[RSWM RNMN[T[VZWXWVVTTSNS", + "J[NZP[T[VZWXWWVUTTQTOSNQNPONQMTMVN RN[N_OaQbSb", + "KYWFUFSGRIR_QaObMb", + "MWRMR_QaObNb ROTUT RRMRISGUFWF", + "KYMFOFQGRIRXSZU[W[", + "KYWFUFSGRIR_QaObMaL_M]O\\V\\", + "KWU[M[ RRbRPQNOMMM", + "MYOMWM RRFR_SaUbWb", + "H[JRYR RVMV[ RMMMXNZP[S[UZVY", + "I\\XMUMUPWRXTXWWYVZT[Q[OZNYMWMTNRPPPMMM", + "H[MMMXNZP[S[UZVYWWWPVNUM", + "JZW[RMM[", + "G]Z[VMRWNMJ[", + "JZW[RM RM[RMTHUGWF", + "KYRTR[ RMMRTWM", + "IZLMWML[W[ RW[W_XaZb\\b", # /* U+290 Z_SMALL !HOOK */ + "IZLMWML[T[VZWXVVTURVN^", + "JZMMVMOVRVTWUXVZV^U`TaRbObMa", + "JZMMVMOVRVTWUXVZV^U`TaRbPbNaM_N]P\\R]Uc", + "J^MGPFTFWGYIZKZNYPWRTSPSP[", + "FZWGTFPFMGKIJKJNKPMRPSTST[", + "J^MZP[T[WZYXZVZSYQWOTNPNPF", + "F[WHVGSFQFNGLIKKJOJYK]L_NaQbSbVaW`", + "G]PFTFVGXIYMYTXXVZT[P[NZLXKTKMLINGPF RROQPRQSPRORQ", + "I[STVUWWWXVZT[N[NMSMUNVPVQUSSTNT", + "I\\PTNUMWMXNZP[T[VZWYXVXRWOVNTMPMNNMPMQNSPTRT", + "HZUNSMPMNNMOLQLWMYNZP[T[VZVUSU RUMUIVGXFZF", + "H[MTVT RMMM[ RVMV[", + "LXRMR_QaObMaL_M]O\\V\\ RRFQGRHSGRFRH", + "J[VMVb RTUNM RN[VS", + "JYOMO[V[", + "I\\WMWb RWZU[Q[OZNYMWMQNOONQMUMWN RWMWIXGZF\\F", # /* U+2A0 Q_SMALL +HOOK */ + "J^MGPFTFWGYIZKZNYPWRTSPSP[ RLXTX", + "FZWGTFPFMGKIJKJNKPMRPSTST[ RPXXX", + "D`R[RF RRM]MR[][ RRZP[L[JZIYHWHQIOJNLMPMRN", + "E`RFR[ RRNPMMMKNJOIQIWJYKZM[P[RZ RRM\\MUVXVZW[X\\Z\\^[`ZaXbUbSa", + "D`R[RF RRM]MR[Z[\\Z]X\\VZUXVT^ RRZP[L[JZIYHWHQIOJNLMPMRN", + "G^IMQM RLFLXMZO[QZS[W[YZZXZWYUWTTTRSQQQPRNTMWMYN", + "I[KMTM RNFNXOZQ[T[ RYFWFUGTIT_SaQbOb", + "F^HMPM RKFKXLZN[P[RZ RZNXMTMRNQOPQPWQYRZT[W[YZZXYVWUUVQ^", + "F]HMPMP[ RK[KILGNFPF RPOQNSMVMXNYPY_XaVbTb", + "G^LFLXMZO[QZS[W[YZZXZWYUWTTTRSQQQPRNTMWMYN", + "H^MM[MP[ RMFMXNZP[[[", + "G]JSN[RUV[ZS RJFNNRHVNZF", + "G]XXXSLSLX RXKXFLFLK", + "I\\WMWb RNMNXOZQ[T[VZWY RNMNIMGKFIF", + "I\\\\bZbXaW_WM RNMNXOZQ[T[VZWY RNMNIMGKFIF", + # /* // SPACING MODIFIER LETTERS (02B0-02FF) */ + "F^K[KFYFY[K[", # /* U+2B0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2C0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2D0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2E0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2F0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // COMBINING DIACRITICAL MARKS (0300-036F) */ + "F^K[KFYFY[K[", # /* U+300 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+310 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+320 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+330 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+340 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+350 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+360 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // GREEK AND COPTIC (0370-03FF) */ + "H[MFM[ RXPMP", # /* U+370 HETA_CAP */ + "IZNTVT RNMN[", + "G]R[RF RKOKFYFYO", + "I[R[RF RMOMFWFWO", + "MWSFQJ", + "MWS[Q_", + "G]LFL[XFX[", + "H\\MMM[WMW[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "NVR`RcSdTd", + "J\\NZP[T[VZWYXWXQWOVNTMPMNN", + "HZVZT[P[NZMYLWLQMONNPMTMVN RRSQTRUSTRSRU", + "J\\NZP[T[VZWYXWXQWOVNTMPMNN RRSQTRUSTRSRU", + "MWSZS[R]Q^ RRNSORPQORNRP", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+380 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "NVTEQH", + "LXNFOGNHMGNFNH RVFWGVHUGVFVH RT>QA", + "G[MUWU RK[RFY[ RMEJH", + "JZRRQSRTSSRRRT", + "B[MPTP RW[M[MFWF RHEEH", + "A]L[LF RLPXP RX[XF RGEDH", + "GWR[RF RMEJH", + "RR", + "B]PFTFVGXIYMYTXXVZT[P[NZLXKTKMLINGPF RHEEH", + "RR", + "@[RQR[ RKFRQYF RFECH", + "@^J[O[OWMVKTJQJLKIMGPFTFWGYIZLZQYTWVUWU[Z[ RFECH", + "MXRMRXSZU[ RNFOGNHMGNFNH RVFWGVHUGVFVH RT>QA", # /* U+390 IOTA_SMALL DIAERESIS */ + "I[MUWU RK[RFY[", + "G\\SPVQWRXTXWWYVZT[L[LFSFUGVHWJWLVNUOSPLP", + "HZM[MFXF", + "I[K[RFY[K[", + "H[MPTP RW[M[MFWF", + "H\\KFYFK[Y[", + "G]L[LF RLPXP RX[XF", + "F^OPUP RPFTFVGXIYKZNZSYVXXVZT[P[NZLXKVJSJNKKLINGPF", + "MWR[RF", + "G\\L[LF RX[OO RXFLR", + "I[K[RFY[", + "F^K[KFRUYFY[", + "G]L[LFX[XF", + "H[L[W[ RLFWF RUPNP", + "G]PFTFVGXIYMYTXXVZT[P[NZLXKTKMLINGPF", + "G]L[LFXFX[", # /* U+3A0 PI_CAP */ + "G\\L[LFTFVGWHXJXMWOVPTQLQ", + "RR", + "H[W[L[SPLFWF", + "JZLFXF RR[RF", + "I[RQR[ RKFRQYF", + "G]R[RF RPITIWJYLZNZRYTWVTWPWMVKTJRJNKLMJPI", + "H\\KFY[ RYFK[", + "G]R[RF RHFJGKIKNLQMROSUSWRXQYNYIZG\\F", + "F^J[O[OWMVKTJQJLKIMGPFTFWGYIZLZQYTWVUWU[Z[", + "MWR[RF RN?O@NAM@N?NA RV?W@VAU@V?VA", + "I[RQR[ RKFRQYF RN?O@NAM@N?NA RV?W@VAU@V?VA", + "H]YMVWUYTZR[P[NZMYLVLRMONNPMRMTNUOVQWXXZZ[ RTEQH", + "IZPTNUMWMXNZP[T[VZ RRTPTNSMQMPNNPMTMVN RTEQH", + "I\\NMN[ RNOONQMTMVNWPWb RTEQH", + "MXRMRXSZU[ RTEQH", + "H[MMMXNZP[S[UZVYWWWPVNUM RNFOGNHMGNFNH RVFWGVHUGVFVH RT>QA", # /* U+3B0 UPSILON_SMALL DIAERESIS */ + "H]YMVWUYTZR[P[NZMYLVLRMONNPMRMTNUOVQWXXZZ[", + "H[SOUPVQWSWWVYUZS[P[NZMY RKbLaM_MINGPFSFUGVIVLUNSOQO", + "JZRYRb RLMMMNNRYWM", + "H[SMPMNNMOLQLWMYNZP[S[UZVYWWWQVOUNSMPLNKMINGPFTFVG", + "IZPTNUMWMXNZP[T[VZ RRTPTNSMQMPNNPMTMVN", + "HZMFWFPMNPMSMWNYOZQ[S[U\\V^V_UaSbRb", + "I\\NMN[ RNOONQMTMVNWPWb", + "H[LPWP RPFSFUGVHWKWVVYUZS[P[NZMYLVLKMHNGPF", + "MXRMRXSZU[", + "IZNMN[ RPSV[ RVMNU", + "JZRMM[ RMFOFPGRMW[", + "H^MMMb RWXXZZ[ RMXNZP[T[VZWXWM", + "J[MMR[WPWOVM", + "HZMFWF RQFOGNINLONQOUO RQOOPNQMSMWNYOZQ[S[U\\V^V_UaSbRb", + "H[P[NZMYLWLQMONNPMSMUNVOWQWWVYUZS[P[", + "F]VMV[ ROMOXNZL[ RZMMMKNJP", # /* U+3C0 PI_SMALL */ + "H\\MbMQNOONQMTMVNWOXQXWWYVZT[Q[OZMX", + "HZVNTMPMNNMOLQLWMYNZP[S[U\\V^V_UaSb", + "H\\YMPMNNMOLQLWMYNZP[S[UZVYWWWQVOUNSM", + "H\\LPMNOMXM RRMRXSZU[", + "H[MMMXNZP[S[UZVYWWWPVNUM", + "G]MMLNKPKVLXNZP[T[VZXXYVYPXNVMUMSNRPRb", + "IZWMLb RLMNNOPT_UaWb", + "G]RMRb RKMKVLXNZP[T[VZXXYVYM", + "G]RTRX RMMLNKPKXLZN[O[QZRXSZU[V[XZYXYPXNWM", + "LXNFOGNHMGNFNH RVFWGVHUGVFVH RRMRXSZU[", + "H[MMMXNZP[S[UZVYWWWPVNUM RNFOGNHMGNFNH RVFWGVHUGVFVH", + "H[P[NZMYLWLQMONNPMSMUNVOWQWWVYUZS[P[ RTEQH", + "H[MMMXNZP[S[UZVYWWWPVNUM RTEQH", + "G]RTRX RMMLNKPKXLZN[O[QZRXSZU[V[XZYXYPXNWM RTEQH", + "G\\L[LF RXFLR ROOX[Qb", + "H[SOUPVQWSWWVYUZS[P[NZMXMINGPFSFUGVIVLUNSOQO", # /* U+3D0 BETA_SMALL_CURLED */ + "H[JPKQLSLVMYNZP[S[UZVYWVWKVHUGSFPFNGMHLJLLMNNOPPWP", + "I\\KFMFOGQIRKR[ RRKSHTGVFWFYGZI", + "NiTEQH RXFZF\\G^I_K_[ R_K`HaGcFdFfGgI", + "I\\KFMFOGQIRKR[ RRKSHTGVFWFYGZI RN?O@NAM@N?NA RV?W@VAU@V?VA", + "G]RFRb RPMTMVNXPYRYVXXVZT[P[NZLXKVKRLPNNPM", + "F^RTRX R[MIM RMMLNKPKXLZN[O[QZRXSZU[V[XZYXYPXNWM", + "IZLMNNOPOXNZM[LZLXMVVRWPWNVMUNTPTXUZW[V^U`TaRb", + "G]R[Rb RPFTFVGXIYMYTXXVZT[P[NZLXKTKMLINGPF", + "H[R[Rb RP[NZMYLWLQMONNPMSMUNVOWQWWVYUZS[P[", + "FZWFQFNGLIKKJOJRKVLXNZQ[R[T\\U^U_TaSbQb", + "HZVMPMNNMOLQLWMYNZP[R[T\\U^U_TaRbPb", + "HZTPMP RM[MFWF", + "MZVPRP RWFUFSGRIR_QaOb", + "H\\MFOGPILSXNTXUZW[", + "I[RFMPWPR[", + "H\\NGNL RXIULTNTW RKIMGPFTFVGXIYKZOZUYYX[", # /* U+3E0 SAMPI_CAP */ + "H\\L[UR RR[WV RLMPNSPURWVXZXb", + "CaRWRR R\\XY]V`SaMa RLFJGHIGLGUHXJZL[N[PZQYRWSYTZV[X[ZZ\\X]U]L\\IZGXF", + "G]RTRX RXZW\\S`PaOa RMMLNKPKXLZN[O[QZRXSZU[V[XZYXYPXNWM", + "G]XFXb RPFNGLIKMKTLXNZP[T[VZXX", + "I\\WMWb RQMONNOMQMWNYOZQ[T[VZWY", + "F]KFK[ RKQMOPNTNVOXQYTYWXZW\\U^R`Nb", + "I[WLWMVPTRRSPSNRMPMONMPLRLTMVPWSWWVYUZS[M[", + "F]KHLGOFTFWGXHYJYLXOVQJ[N^Q_V_Y^", + "J[NNPMTMVNWPWRVTTVN[P]R^U^W]", + "G]I[[[ RIFJFLGXZZ[ R[FZFXGLZJ[", + "H[KMMNVZX[K[MZVNXM", + "G\\XEVFOFMGLHKJKWLYMZO[T[VZWYXWXPWNVMTLNLLMKN", + "H[WEVFTGPGNHMILKLWMYNZP[S[UZVYWWWQVOUNSMOMMNLO", + "G]RFRb RKQKMYMYQ", + "I[MMWM RRFRb", + "IZLMNNOPOXNZM[LZLXMVVRWPWNVMUNTPTXUZW[", # /* U+3F0 KAPPA_SMALL_SCRIPT */ + "H\\WbQbOaN`M^MQNOONQMTMVNWOXQXWWYVZT[Q[OZMX", + "HZVZT[P[NZMYLWLQMONNPMTMVN", + "MWRMR_QaObNb RRFQGRHSGRFRH", + "G]KPYP RPFTFVGXIYMYTXXVZT[P[NZLXKTKMLINGPF", + "HZLTST RVZT[P[NZMYLWLQMONNPMTMVN", + "J\\XTQT RNZP[T[VZWYXWXQWOVNTMPMNN", + "G\\LFL[ RLKTKVLWMXOXRWTVUTVLV", + "H[MFMb RMNOMSMUNVOWQWWVYUZS[O[MZ", + "F[WYVZS[Q[NZLXKVJRJOKKLINGQFSFVGWH", + "F^K[KFRMYFY[", + "G]LbLMRSXMX[", + "G\\J`S` RMbMQNOONQMTMVNWOXQXWWYVZT[Q[OZMX", + "I^MYNZQ[S[VZXXYVZRZOYKXIVGSFQFNGMH", + "F[WYVZS[Q[NZLXKVJRJOKKLINGQFSFVGWH RROQPRQSPRORQ", + "I^MYNZQ[S[VZXXYVZRZOYKXIVGSFQFNGMH RROQPRQSPRORQ", + # /* // Cyrillic (0400-04FF) */ + "H[MPTP RW[M[MFWF RP>SA", # /* U+400 E_CAP GRAVE */ + "H[MPTP RW[M[MFWF RN?O@NAM@N?NA RV?W@VAU@V?VA", + "JbLFXF RR[RF RRMXM[N]P^S^\\]_[aXbVb", + "HZM[MFXF RT>QA", + "F[JPTP RWYVZS[Q[NZLXKVJRJOKKLINGQFSFVGWH", + "H\\LZO[T[VZWYXWXUWSVRTQPPNOMNLLLJMHNGPFUFXG", + "MWR[RF", + "MWR[RF RN?O@NAM@N?NA RV?W@VAU@V?VA", + "JZUFUUTXRZO[M[", + "AbC[D[FZGXILJILGOFRFR[X[[Z]X^V^S]Q[OXNRN", + "AbF[FF RRFR[X[[Z]X^V^S]Q[OXNFN", + "JbLFXF RR[RF RRMXM[N]P^S^[", + "G\\L[LF RX[OO RXFLR RT>QA", + "G]LFL[XFX[ RP>SA", + "G[KFRT RYFPXNZL[K[ RN>O@QASAU@V>", + "G]R[R` RLFL[X[XF", + "I[MUWU RK[RFY[", # /* U+410 A_CAP */ + "G\\VFLFL[R[UZWXXVXSWQUORNLN", + "G\\SPVQWRXTXWWYVZT[L[LFSFUGVHWJWLVNUOSPLP", + "HZM[MFXF", + "F^[`[[I[I` RW[WFRFPGOHNJL[", + "H[MPTP RW[M[MFWF", + "BbOOF[ RR[RF RRRFF R^[UO R^FRR", + "I]PPTP RMGOFTFVGWHXJXLWNVOTPWQXRYTYWXYWZU[O[MZ", + "G]LFL[XFX[", + "G]LFL[XFX[ RN>O@QASAU@V>", + "G\\L[LF RX[OO RXFLR", + "F\\W[WFTFQGOINLLXKZI[H[", + "F^K[KFRUYFY[", + "G]L[LF RLPXP RX[XF", + "G]PFTFVGXIYMYTXXVZT[P[NZLXKTKMLINGPF", + "G]L[LFXFX[", + "G\\L[LFTFVGWHXJXMWOVPTQLQ", # /* U+420 P_CAP */ + "F[WYVZS[Q[NZLXKVJRJOKKLINGQFSFVGWH", + "JZLFXF RR[RF", + "G[KFRT RYFPXNZL[K[", + "G]R[RF RPITIWJYLZNZRYTWVTWPWMVKTJRJNKLMJPI", + "H\\KFY[ RYFK[", + "G]XFX[ RLFL[Z[Z`", + "H\\WFW[ RLFLNMPNQPRWR", + "CaRFR[ RHFH[\\[\\F", + "CaRFR[ RHFH[\\[\\F R\\[^[^`", + "F]HFMFM[S[VZXXYVYSXQVOSNMN", + "Da\\F\\[ RIFI[O[RZTXUVUSTQROONIN", + "H]MFM[S[VZXXYVYSXQVOSNMN", + "I^ZQPQ RMHNGQFSFVGXIYKZOZRYVXXVZS[Q[NZMY", + "CaHFH[ ROPHP RTFXFZG\\I]M]T\\XZZX[T[RZPXOTOMPIRGTF", + "G\\RQK[ RW[WFOFMGLHKJKMLOMPOQWQ", + "I\\W[WPVNTMPMNN RWZU[P[NZMXMVNTPSUSWR", # /* U+430 A_SMALL */ + "H[WEVFTGPGNHMILKLWMYNZP[S[UZVYWWWQVOUNSMOMMNLO", + "I[STVUWWWXVZT[N[NMSMUNVPVQUSSTNT", + "JYO[OMWM", + "H[WOVNTMPMNNMOLQLWMYNZP[S[UZVYWWWJVHUGSFOFMG", + "I[VZT[P[NZMXMPNNPMTMVNWPWRMT", + "F^QTJ[ RRUJM RRMR[ RZ[ST RZMRU", + "K[RTTT RNNPMTMVNWPWQVSTTVUWWWXVZT[P[NZ", + "H\\MMM[WMW[", + "H\\MMM[WMW[ RNEOGQHSHUGVE", + "IZNMN[ RPSV[ RVMNU", + "I[V[VMSMQNPPOXNZL[", + "G]L[LMRXXMX[", + "H[MTVT RMMM[ RVMV[", + "H[P[NZMYLWLQMONNPMSMUNVOWQWWVYUZS[P[", + "H[M[MMVMV[", + "H[MMMb RMNOMSMUNVOWQWWVYUZS[O[MZ", # /* U+440 P_SMALL */ + "HZVZT[P[NZMYLWLQMONNPMTMVN", + "KYMMWM RRMR[", + "JZMMR[ RWMR[P`OaMb", + "G]RFRb RPMTMVNXPYRYVXXVZT[P[NZLXKVKRLPNNPM", + "IZL[WM RLMW[", + "I\\WMW[ RNMN[Y[Y`", + "J\\VMV[ RNMNROTQUVU", + "F^RMR[ RKMK[Y[YM", + "F^RMR[ RKMK[Y[YM RY[[[[`", + "HZJMNMN[S[UZVXVUUSSRNR", + "F^YMY[ RKMK[P[RZSXSURSPRKR", + "IZNMN[S[UZVXVUUSSRNR", + "J\\XTQT RNNPMTMVNWOXQXWWYVZT[P[NZ", + "E_JTPT RJMJ[ RT[RZQYPWPQQORNTMWMYNZO[Q[WZYYZW[T[", + "I[RUM[ RV[VMPMNNMPMRNTPUVU", + "I[VZT[P[NZMXMPNNPMTMVNWPWRMT RPESH", # /* U+450 E_SMALL GRAVE */ + "I[VZT[P[NZMXMPNNPMTMVNWPWRMT RNFOGNHMGNFNH RVFWGVHUGVFVH", + "M^OKXK RRFR[ RRSSRUQWQYRZTZ[Y^WaVb", + "JYO[OMWM RTEQH", + "HZLTST RVZT[P[NZMYLWLQMONNPMTMVN", + "J[NZP[T[VZWXWWVUTTQTOSNQNPONQMTMVN", + "MWR[RM RRFQGRHSGRFRH", + "LXNFOGNHMGNFNH RVFWGVHUGVFVH RR[RM", + "MWRMR_QaObNb RRFQGRHSGRFRH", + "E^H[JZKXLPMNOMRMR[W[YZZXZUYSWRRR", + "D^IMI[ RRMR[W[YZZXZVYTWSIS", + "M^OKXK RRFR[ RRSSRUQWQYRZTZ[", + "IZNMN[ RPSV[ RVMNU RTEQH", + "H\\MMM[WMW[ RPESH", + "JZMMR[ RWMR[P`OaMb RNEOGQHSHUGVE", + "H]R[R` RMMM[W[WM", + "CaRWRR RLFJGHIGLGUHXJZL[N[PZQYRWSYTZV[X[ZZ\\X]U]L\\IZGXF", # /* U+460 OMEGA_LARGE */ + "G]RTRX RMMLNKPKXLZN[O[QZRXSZU[V[XZYXYPXNWM", + "F]IIVI RMFM[S[VZXXYVYSXQVOSNMN", + "HZJMTM RNFN[S[UZVXVUUSSRNR", + "D`IFI[ RYPIP R\\Y[ZX[V[SZQXPVOROOPKQISGVFXF[G\\H", + "F^KMK[ RWTKT RZZX[T[RZQYPWPQQORNTMXMZN", + "F^LSXS RRSR[ RH[RF\\[", + "I[NUVU RRUR[ RK[RMY[", + "AbF[FF RFS\\S RVSV[ RL[VF`[", + "E_J[JM RVUV[ RZUJU RO[VM][", + "E_R[RPJFZFRP RI[IVJSLQOPUPXQZS[V[[", + "G]R[RTLMXMRT RK[KXLVMUOTUTWUXVYXY[", + "AcF[FF RFPSP RV[VPNF^FVP RM[MVNSPQSPYP\\Q^S_V_[", + "DaI[IM RITST RV[VTPM\\MVT RO[OXPVQUSTYT[U\\V]X][", + "H\\OPSP RNAQFSBTAUA RLGNFSFUGVHWJWLVNUOSPVQWRXTXWWYVZT[O[M\\L^L_MaObWb", + "J[RTTT ROHRMTIUHVH RNNPMTMVNWPWQVSTTVUWWWXVZT[Q[O\\N^N_OaQbVb", + "G]R[RF RHFJGKIKNLQMROSUSWRXQYNYIZG\\F", # /* U+470 PSI_CAP */ + "G]RMRb RKMKVLXNZP[T[VZXXYVYM", + "G]KPYP RPFTFVGXIYMYTXXVZT[P[NZLXKTKMLINGPF", + "H[LTWT RP[NZMYLWLQMONNPMSMUNVOWQWWVYUZS[P[", + "I[KFR[YF", + "JZMMR[WM", + "I[KFR[YF ROAL> RVAS>", + "JZMMR[WM ROHLE RVHSE", + "GmPFTFVGXIYMYTXXVZT[P[NZLXKTKMLINGPF R`Me[ RjMe[c`ba`b", + "HkP[NZMYLWLQMONNPMSMUNVOWQWWVYUZS[P[ R^Mc[ RhMc[a``a^b", + "CaRXR^ RRCRI RMFJGHIGLGUHXJZM[W[ZZ\\X]U]L\\IZGWFMF", + "G]RYR] RRKRO ROMMNLOKQKWLYMZO[U[WZXYYWYQXOWNUMOM", + "CaRWRR RLFJGHIGLGUHXJZL[N[PZQYRWSYTZV[X[ZZ\\X]U]L\\IZGXF RLBM@O?R?U@X@", + "G]RTRX RMMLNKPKXLZN[O[QZRXSZU[V[XZYXYPXNWM RLIMGOFRFUGXG", + "CaRWRR RLFJGHIGLGUHXJZL[N[PZQYRWSYTZV[X[ZZ\\X]U]L\\IZGXF RMR?PAOCPDR RC^D\\F[H\\I^ RCFDDFCHDIF ROcPaR`TaUc ROAP?R>T?UA R[^\\\\^[`\\a^ R[F\\D^C`DaF R`RaPcOePfR", + ":jDQ>Q RH[D_ RHGDC RR_Re RRCR= R\\[`_ R\\G`C R`QfQ", + "G]LFL[XFX[ RX[[[Ub RN>O@QASAU@V>", + "H\\MMM[WMW[ RW[Z[Tb RNEOGQHSHUGVE", + "H]MFM[S[VZXXYVYSXQVOSNMN RJIPI", + "IZKMQM RNFN[S[UZVXVUUSSRNR", + "G\\L[LFTFVGWHXJXMWOVPTQLQ RTMXS", + "H[MMMb RMNOMSMUNVOWQWWVYUZS[O[MZ RSWW]", + "HZM[MFXFXA", # /* U+490 GAMMA_CAP_UPTURN */ + "JYO[OMWMWH", + "HZM[MFXF RJQRQ", + "JYO[OMWM RLTTT", + "H]M[MFXF RMMSMVNXPYSY\\X_VaSbQb", + "J\\O[OMWM ROTTTVUWVXXX[W^UaTb", + "BbOOF[ RR[RF RRRFF R^[UO R^FRR R^[`[``", + "F^QTJ[ RRUJM RRMR[ RZ[ST RZMRU RZ[\\[\\`", + "I]PPTP RMGOFTFVGWHXJXLWNVOTPWQXRYTYWXYWZU[O[MZ RR\\T]U_TaRbOb", + "K[RTTT RNNPMTMVNWPWQVSTTVUWWWXVZT[P[NZ RR\\T]U_TaRbOb", + "G\\L[LF RX[OO RXFLR RX[Z[Z`", + "IZNMN[ RPSV[ RVMNU RV[X[X`", + "G\\L[LF RX[OO RXFLR RPKPS", + "IZNMN[ RPSV[ RVMNU RRORW", + "G\\L[LF RX[OO RXFLR RIJOJ", + "IZN[NF RPSV[ RVMNU RKJQJ", + "E\\X[OO RXFLR RGFLFL[", # /* U+4A0 K_CAP_BASHKIR */ + "HZPSV[ RVMNU RJMNMN[", + "G]L[LF RLPXP RX[XF RX[Z[Z`", + "H[MTVT RMMM[ RVMV[ RV[X[X`", + "GeL[LF RLPXP RX[XFcF", + "H`MTVT RMMM[ RV[VM^M", + "GhL[LFXFX[ RXM^MaNcPdSd\\c_aa^b\\b", + "HcM[MMVMV[ RVT[T]U^V_X_[^^\\a[b", + "F^QFNGLIKKJOJRKVLXNZQ[S[VZXXYVZRZMYJWIVITJSMSRTVUXWZY[[[", + "H\\QMPMNNMOLQLWMYNZP[T[VZWYXWXRWPUOSPRRRWSYTZV[Y[", + "F[WYVZS[Q[NZLXKVJRJOKKLINGQFSFVGWH RR\\T]U_TaRbOb", + "HZVZT[P[NZMYLWLQMONNPMTMVN RR\\T]U_TaRbOb", + "JZLFXF RR[RF RR[T[T`", + "KYMMWM RRMR[ RR[T[T`", + "I[RQR[ RKFRQYF", + "JZR[Rb RMMR[WM", + "I[RQR[ RKFRQYF RNUVU", # /* U+4B0 Y_CAP STROKE_H */ + "JZR[Rb RMMR[WM RN]V]", + "H\\KFY[ RYFK[ RX[Z[Z`", + "IZL[WM RLMW[ RV[X[X`", + "D]FFRF RXFX[ RLFL[Z[Z`", + "G\\RMIM RWMW[ RNMN[Y[Y`", + "H\\WFW[ RLFLNMPNQPRWR RW[Y[Y`", + "J\\VMV[ RNMNROTQUVU RV[X[X`", + "H\\WFW[ RLFLNMPNQPRWR RRNRV", + "J\\VMV[ RNMNROTQUVU RRQRY", + "G]L[LF RL[ RLPRPUQWSXVX[", + "H[M[MF RV[VPUNSMPMNNMO", + "@^WYVZS[Q[NZLXKVJRJOKKLINGQFSFVGXIYKZOJQGQEPDOCMCK", + "E[VZT[P[NZMXMPNNPMTMVNWPWRMTKTISHQHO", + "@^WYVZS[Q[NZLXKVJRJOKKLINGQFSFVGXIYKZOJQGQEPDOCMCK RR[P]O_PaRbTb", + "E[VZT[P[NZMXMPNNPMTMVNWPWRMTKTISHQHO RR[P]O_PaRbTb", + "MWR[RF", # /* U+4C0 I_CAP */ + "BbOOF[ RR[RF RRRFF R^[UO R^FRR RN>O@QASAU@V>", + "F^QTJ[ RRUJM RRMR[ RZ[ST RZMRU RNEOGQHSHUGVE", + "G\\L[LF RX[OO RXFLR RX[X_WaUbSb", + "IZNMN[ RPSV[ RVMNU RV[V_UaSbQb", + "F\\W[WFTFQGOINLLXKZI[H[ RW[Z[Tb", + "I[V[VMSMQNPPOXNZL[ RV[Y[Sb", + "G]L[LF RLPXP RX[XF RX[X_WaUbSb", + "H[MTVT RMMM[ RVMV[ RV[V_UaSbQb", + "G]L[LF RLPXP RX[XF RX[[[Ub", + "H[MTVT RMMM[ RVMV[ RV[Y[Sb", + "H\\WFW[ RLFLNMPNQPRWR RW[U[U`", + "J\\VMV[ RNMNROTQUVU RV[T[T`", + "F^K[KFRUYFY[ RY[\\[Vb", + "G]L[LMRXXMX[ RX[[[Ub", + "MWR[RF", + "I[MUWU RK[RFY[ RN>O@QASAU@V>", # /* U+4D0 A_CAP BREVE */ + "I\\W[WPVNTMPMNN RWZU[P[NZMXMVNTPSUSWR RNEOGQHSHUGVE", + "I[MUWU RK[RFY[ RN?O@NAM@N?NA RV?W@VAU@V?VA", + "I\\W[WPVNTMPMNN RWZU[P[NZMXMVNTPSUSWR RNFOGNHMGNFNH RVFWGVHUGVFVH", + "F`JURU RRPYP RH[OF\\F RRFR[\\[", + "D`INKMOMQNRP R[ZY[U[SZRXRPSNUMYM[N\\P\\RRSKSITHVHXIZK[O[QZRX", + "H[MPTP RW[M[MFWF RN>O@QASAU@V>", + "I[VZT[P[NZMXMPNNPMTMVNWPWRMT RNEOGQHSHUGVE", + "F^MHNGQFSFVGXIYKZOZRYVXXVZS[Q[NZLXKVJRZP", + "I[NNPMTMVNWPWXVZT[P[NZMXMVWT", + "F^MHNGQFSFVGXIYKZOZRYVXXVZS[Q[NZLXKVJRZP RNBOCNDMCNBND RVBWCVDUCVBVD", + "I[NNPMTMVNWPWXVZT[P[NZMXMVWT RNFOGNHMGNFNH RVFWGVHUGVFVH", + "BbOOF[ RR[RF RRRFF R^[UO R^FRR RN?O@NAM@N?NA RV?W@VAU@V?VA", + "F^QTJ[ RRUJM RRMR[ RZ[ST RZMRU RNFOGNHMGNFNH RVFWGVHUGVFVH", + "I]PPTP RMGOFTFVGWHXJXLWNVOTPWQXRYTYWXYWZU[O[MZ RN?O@NAM@N?NA RV?W@VAU@V?VA", + "K[RTTT RNNPMTMVNWPWQVSTTVUWWWXVZT[P[NZ RNFOGNHMGNFNH RVFWGVHUGVFVH", + "H\\KFXFQNTNVOWPXRXWWYVZT[N[LZKY", # /* U+4E0 DIGIT_3 */ + "JZMMVMOVRVTWUXVZV^U`TaRbObMa", + "G]LFL[XFX[ RM@W@", + "H\\MMM[WMW[ RMGWG", + "G]LFL[XFX[ RN?O@NAM@N?NA RV?W@VAU@V?VA", + "H\\MMM[WMW[ RNFOGNHMGNFNH RVFWGVHUGVFVH", + "G]PFTFVGXIYMYTXXVZT[P[NZLXKTKMLINGPF RN?O@NAM@N?NA RV?W@VAU@V?VA", + "H[P[NZMYLWLQMONNPMSMUNVOWQWWVYUZS[P[ RNFOGNHMGNFNH RVFWGVHUGVFVH", + "G]KPYP RPFTFVGXIYMYTXXVZT[P[NZLXKTKMLINGPF", + "H[LTWT RP[NZMYLWLQMONNPMSMUNVOWQWWVYUZS[P[", + "G]KPYP RPFTFVGXIYMYTXXVZT[P[NZLXKTKMLINGPF RN?O@NAM@N?NA RV?W@VAU@V?VA", + "H[LTWT RP[NZMYLWLQMONNPMSMUNVOWQWWVYUZS[P[ RNFOGNHMGNFNH RVFWGVHUGVFVH", + "I^ZPPP RMYNZQ[S[VZXXYVZRZOYKXIVGSFQFNGMH RN?O@NAM@N?NA RV?W@VAU@V?VA", + "J\\XTQT RNZP[T[VZWYXWXQWOVNTMPMNN RNFOGNHMGNFNH RVFWGVHUGVFVH", + "G[KFRT RYFPXNZL[K[ RM@W@", + "JZMMR[ RWMR[P`OaMb RMGWG", + "G[KFRT RYFPXNZL[K[ RN?O@NAM@N?NA RV?W@VAU@V?VA", # /* U+4F0 Y_LARGE DIAERESIS */ + "JZMMR[ RWMR[P`OaMb RNFOGNHMGNFNH RVFWGVHUGVFVH", + "G[KFRT RYFPXNZL[K[ RQ>NA RX>UA", + "JZMMR[ RWMR[P`OaMb RQENH RXEUH", + "H\\WFW[ RLFLNMPNQPRWR RN?O@NAM@N?NA RV?W@VAU@V?VA", + "J\\VMV[ RNMNROTQUVU RNFOGNHMGNFNH RVFWGVHUGVFVH", + "HZM[MFXF RM[O[O`", + "JYO[OMWM RO[Q[Q`", + "Da\\F\\[ RIFI[O[RZTXUVUSTQROONIN RN?O@NAM@N?NA RV?W@VAU@V?VA", + "F^YMY[ RKMK[P[RZSXSURSPRKR RNFOGNHMGNFNH RVFWGVHUGVFVH", + "HZWFMFM[Q[Q_PaNbLb RJQRQ", + "JYWMOMO[S[S_RaPbNb RLTTT", + "H\\KFY[ RYFK[ RX[X_WaUbSb", + "IZL[WM RLMW[ RV[V_UaSbQb", + "H\\KFY[ RYFK[ RNPVP", + "IZL[WM RLMW[ RNTVT", + # /* // Cyrillic Supplement (500-52F) */ + "G\\WFW[Q[NZLXKVKSLQNOQNWN", # /* U+500 !SOFT_CAP */ + "J[VMV[Q[OZNXNUOSQRVR", + "B_RXSZU[X[ZZ[X[M RRFRXQZO[L[IZGXFVFSGQIOLNRN", + "E]RXSZU[V[XZYXYQ RRMRXQZO[M[KZJXJUKSMRRR", + "IePPTP RMGOFTFVGWHXJXLWNVOTPVQWRXTXXYZ[[^[`ZaXaM", + "KbRTTT RNNPMTMVNWPWQVSTTVUWWWXXZZ[[[]Z^X^Q", + "I\\PPTP RMGOFTFVGWHXJXLWNVOTPVQWRXTX[Z[Z`", + "K[RTTT RNNPMTMVNWPWQVSTTVUWWW[Y[Y`", + "FdH[I[KZLXNLOIQGTFWFWXXZZ[][_Z`X`M", + "IaL[NZOXPPQNSMVMVXWZY[Z[\\Z]X]Q", + "CaH[HF RHPTP RTFTXUZW[Z[\\Z]X]M", + "F^KTTT RKMK[ RTMTXUZW[X[ZZ[X[R", + "F[VGTFQFNGLIKKJOJRKVLXNZQ[S[VZWYWRSR", + "HZUNSMPMNNMOLQLWMYNZP[T[VZVUSU", + "J_LFXF RRFRXSZU[X[ZZ[X[M", + "K]MMWM RRMRXSZU[V[XZYXYS", + "G[PPTP RWGUFPFNGMHLJLLMNNOPPMQLRKTKWLYMZO[U[WZ", # /* U+510 EPSILON_LARGE */ + "IZPTNUMWMXNZP[T[VZ RRTPTNSMQMPNNPMTMVN", + "F\\W[WFTFQGOINLLXKZI[H[ RW[W_VaTbRb", + "I[V[VMSMQNPPOXNZL[ RV[V_UaSbQb", + "BaP[^F RD[E[GZHXJLKIMGPF^[", + "E^[MO[ RH[JZKXLPMNOM[[", + "E_\\FUO\\[ RJ[JFRFTGUHVJVMUOTPRQJQ", + "F^KMKb R[MUT[[ RKNMMQMSNTOUQUWTYSZQ[M[KZ", + "DaOQH[ RTFT[^[ R[QLQJPIOHMHJIHJGLF^F", + "D`H[MU RRPRMKMINHPHRITKURU R[ZY[U[SZRXRPSNUMYM[N\\P\\RRT", + "G]Z]X\\VZSWQVOV RP[NZLXKTKMLINGPFTFVGXIYMYTXXVZT[P[", + "I\\WMWb RWZU[Q[OZNYMWMQNOONQMUMWN", + "F^IFN[RLV[[F", + "G]JMN[RQV[ZM", + "G\\L[LF RX[OO RXFLR RXKRG", + "IZNMN[ RPSV[ RVMNU RWQQM", + "FgW[WFTFQGOINLLXKZI[H[ RWM]M`NbPcSc\\b_`a]b[b", # /* U+520 LYUDI_CAP MIDDLE_HOOK_CAP */ + "IcV[VMSMQNPPOXNZL[ RVT[T]U^V_X_[^^\\a[b", + "GhL[LF RLPXP RX[XF RXM^MaNcPdSd\\c_aa^b\\b", + "HcMTVT RMMM[ RVMV[ RVT[T]U^V_X_[^^\\a[b", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // Armenian (530-58F) */ + "F^K[KFYFY[K[", # /* U+530 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+540 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+550 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+560 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+570 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+580 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // Hebrew (590-5FF) */ + "F^K[KFYFY[K[", # /* U+590 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+5A0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+5B0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+5C0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+5D0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+5E0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+5F0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // Arabic (600-6FF) */ + "F^K[KFYFY[K[", # /* U+600 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+610 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+620 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+630 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+640 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+650 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+660 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+670 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+680 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+690 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+6A0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+6B0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+6C0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+6D0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+6E0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+6F0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // Syriac (700-74F) */ + "F^K[KFYFY[K[", # /* U+700 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+710 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+720 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+730 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+740 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // Arabic Supplement (750-77F) */ + "F^K[KFYFY[K[", # /* U+750 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+760 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+770 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // Taana (780-7BF) */ + "F^K[KFYFY[K[", # /* U+780 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+790 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+7A0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+7B0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // N'Ko (7C0-7FF) */ + "F^K[KFYFY[K[", # /* U+7C0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+7D0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+7E0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+7F0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // - (800-8FF) */ + "F^K[KFYFY[K[", # /* U+800 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+810 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+820 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+830 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+840 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+850 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+860 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+870 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+880 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+890 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+8A0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+8B0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+8C0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+8D0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+8E0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+8F0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // Devanagari (900-97F) */ + "F^K[KFYFY[K[", # /* U+900 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+910 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+920 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+930 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+940 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+950 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+960 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+970 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // Bengali (980-9FF) */ + "F^K[KFYFY[K[", # /* U+980 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+990 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+9A0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+9B0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+9C0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+9D0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+9E0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+9F0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // Gurmukhi (A00-A7F) */ + "F^K[KFYFY[K[", # /* U+A00 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+A10 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+A20 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+A30 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+A40 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+A50 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+A60 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+A70 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // Gujarati (A80-AFF) */ + "F^K[KFYFY[K[", # /* U+A80 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+A90 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+AA0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+AB0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+AC0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+AD0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+AE0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+AF0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // Oriya (B00-B7F) */ + "F^K[KFYFY[K[", # /* U+B00 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+B10 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+B20 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+B30 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+B40 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+B50 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+B60 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+B70 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // Tamil (B80-BFF) */ + "F^K[KFYFY[K[", # /* U+B80 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+B90 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+BA0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+BB0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+BC0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+BD0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+BE0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+BF0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // Telugu (C00-C7F) */ + "F^K[KFYFY[K[", # /* U+C00 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+C10 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+C20 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+C30 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+C40 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+C50 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+C60 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+C70 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // Kannada (C80-CFF) */ + "F^K[KFYFY[K[", # /* U+C80 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+C90 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+CA0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+CB0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+CC0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+CD0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+CE0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+CF0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // Malayalam (D00-D7F) */ + "F^K[KFYFY[K[", # /* U+D00 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+D10 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+D20 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+D30 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+D40 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+D50 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+D60 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+D70 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // Simhala (D80-DFF) */ + "F^K[KFYFY[K[", # /* U+D80 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+D90 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+DA0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+DB0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+DC0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+DD0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+DE0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+DF0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // Thai (E00-E7F) */ + "F^K[KFYFY[K[", # /* U+E00 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+E10 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+E20 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+E30 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+E40 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+E50 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+E60 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+E70 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // Lao (E80-EFF) */ + "F^K[KFYFY[K[", # /* U+E80 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+E90 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+EA0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+EB0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+EC0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+ED0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+EE0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+EF0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // Tibetan (F00-FFF) */ + "F^K[KFYFY[K[", # /* U+F00 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+F10 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+F20 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+F30 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+F40 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+F50 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+F60 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+F70 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+F80 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+F90 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+FA0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+FB0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+FC0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+FD0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+FE0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+FF0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // Myanmar (1000-109F) */ + "F^K[KFYFY[K[", # /* U+1000 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1010 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1020 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1030 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1040 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1050 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1060 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1070 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1080 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1090 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // Geogian (10A0-10FF) */ + "F^K[KFYFY[K[", # /* U+10A0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+10B0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+10C0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+10D0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+10E0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+10F0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // Hangul Jamo (1100-11FF) */ + "F^K[KFYFY[K[", # /* U+1100 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1110 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1120 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1130 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1140 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1150 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1160 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1170 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1180 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1190 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+11A0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+11B0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+11C0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+11D0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+11E0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+11F0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // Ethiopic (1200-137F) */ + "F^K[KFYFY[K[", # /* U+1200 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1210 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1220 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1230 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1240 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1250 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1260 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1270 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1280 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1290 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+12A0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+12B0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+12C0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+12D0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+12E0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+12F0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1300 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1310 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1320 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1330 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1340 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1350 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1360 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1370 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // Ethiopic Supplement (1380-139F) */ + "F^K[KFYFY[K[", # /* U+1380 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1390 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // Cherokee (13A0-13FF) */ + "F^K[KFYFY[K[", # /* U+13A0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+13B0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+13C0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+13D0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+13E0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+13F0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // Unified Canadian Aboriginal Syllabics (1400-167F) */ + "F^K[KFYFY[K[", # /* U+1400 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1410 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1420 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1430 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1440 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1450 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1460 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1470 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1480 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1490 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+14A0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+14B0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+14C0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+14D0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+14E0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+14F0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1500 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1510 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1520 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1530 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1540 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1550 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1560 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1570 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1580 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1590 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+15A0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+15B0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+15C0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+15D0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+15E0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+15F0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1600 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1610 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1620 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1630 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1640 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1650 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1660 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1670 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // Ogham (1680-169F) */ + "F^K[KFYFY[K[", # /* U+1680 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1690 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // Runic (16A0-16FF) */ + "F^K[KFYFY[K[", # /* U+16A0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+16B0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+16C0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+16D0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+16E0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+16F0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // Tagalog (1700-171F) */ + "F^K[KFYFY[K[", # /* U+1700 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1710 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // Hanunoo (1720-173F) */ + "F^K[KFYFY[K[", # /* U+1720 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1730 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // Buhid (1740-175F) */ + "F^K[KFYFY[K[", # /* U+1740 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1750 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // Tagbanwa (1760-177F) */ + "F^K[KFYFY[K[", # /* U+1760 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1770 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // Khmer (1780-17FF) */ + "F^K[KFYFY[K[", # /* U+1780 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1790 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+17A0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+17B0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+17C0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+17D0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+17E0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+17F0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // Mongolian (1800-18AF) */ + "F^K[KFYFY[K[", # /* U+1800 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1810 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1820 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1830 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1840 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1850 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1860 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1870 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1880 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1890 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+18A0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // - (18B0-18FF) */ + "F^K[KFYFY[K[", # /* U+18B0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+18C0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+18D0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+18E0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+18F0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // Limbu (1900-194F) */ + "F^K[KFYFY[K[", # /* U+1900 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1910 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1920 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1930 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1940 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // Tai Le (1950-197F) */ + "F^K[KFYFY[K[", # /* U+1950 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1960 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1970 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // New Tai Lue (1980-19DF) */ + "F^K[KFYFY[K[", # /* U+1980 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1990 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+19A0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+19B0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+19C0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+19D0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // Khmer Symbols (19E0-19FF) */ + "F^K[KFYFY[K[", # /* U+19E0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+19F0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // Buginese (1A00-1A1F) */ + "F^K[KFYFY[K[", # /* U+1A00 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1A10 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // - (1A20-1AFF) */ + "F^K[KFYFY[K[", # /* U+1A20 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1A30 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1A40 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1A50 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1A60 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1A70 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1A80 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1A90 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1AA0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1AB0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1AC0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1AD0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1AE0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1AF0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // Balinese (1B00-1B7F) */ + "F^K[KFYFY[K[", # /* U+1B00 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1B10 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1B20 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1B30 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1B40 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1B50 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1B60 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1B70 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // Sudanese (1B80-1BBF) */ + "F^K[KFYFY[K[", # /* U+1B80 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1B90 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1BA0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1BB0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // - (1BC0-1BFF) */ + "F^K[KFYFY[K[", # /* U+1BC0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1BD0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1BE0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1BF0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // Lepcha (1C00-1C4F) */ + "F^K[KFYFY[K[", # /* U+1C00 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1C10 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1C20 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1C30 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1C40 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // Ol Chiki (1C50-1C7F) */ + "F^K[KFYFY[K[", # /* U+1C50 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1C60 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1C70 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // - (1C80-1CFF) */ + "F^K[KFYFY[K[", # /* U+1C80 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1C90 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1CA0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1CB0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1CC0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1CD0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1CE0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1CF0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // Phonetic Extensions (1D00-1D7F) */ + "JZNXVX RM[RMW[", # /* U+1D00 A_SMALLCAP */ + "H\\LXRX RRTWT RRMR[Y[ RYMPMK[", + "D`[ZY[U[SZRX RINKMOMQNRPRXQZO[K[IZHXHVRUYU[T\\R\\P[NYMUMSNRP", + "I[STVUWWWXVZT[N[NMSMUNVPVQUSSTNT RKWQW", + "HZVZT[P[NZMYLWLQMONNPMTMVN", + "J[SMOMO[S[UZVYWVWRVOUNSM", + "J[SMOMO[S[UZVYWVWRVOUNSM RLTRT", + "JYOTTT RVMOMO[V[", + "J[TTVSWQWPVNTMPMNN RRTTTVUWWWXVZT[P[NZ", + "MWRMR[ RRbSaR`QaRbR`", + "LYTMTWSYRZP[O[", + "IZNMN[ RPSV[ RVMNU", + "JYOMO[V[ RLVRR", + "G]L[LMRXXMX[", + "I\\W[WMN[NM", + "H[P[NZMYLWLQMONNPMSMUNVOWQWWVYUZS[P[", + "J\\NNPMTMVNWOXQXWWYVZT[P[NZ", # /* U+1D10 +C_SMALL */ + "G]YSYVXXWYUZOZMYLXKVKSLQMPOOUOWPXQYS", + "G]XYYWYSXQWPUOOOMPLQKSKWLY", + "G]YNK[ RYSYVXXWYUZOZMYLXKVKSLQMPOOUOWPXQYS", + "DaINKMOMQNRPRXQZO[K[IZHXHVRT RRWSYTZV[Y[[Z\\Y]W]Q\\O[NYMVMTNSORQ", + "G]OMNNMPNRPS RTSVRWPVNUM RPSTSVTWVWXVZT[P[NZMXMVNTPS", + "I\\XTXQWOVNTMQMONNOMQMT", + "H[LTLWMYNZP[S[UZVYWWWT", + "I[N[NMTMVNWPWRVTTUNU", + "I[RUM[ RV[VMPMNNMPMRNTPUVU", + "I[RSMM RVMV[P[NZMXMVNTPSVS", + "KYMMWM RRMR[", + "H[MMMXNZP[S[UZVXVM", + "G]KPYP RKYVYXXYVYSXQWP", + "@]KPYP RKYVYXXYVYSXQWP REWFXEYDXEWEY REOFPEQDPEOEQ", + "G]KKYK RWKXLYNYQXSVTKT RVTXUYWYZX\\V]K]", + "JZMMR[WM", # /* U+1D20 V_SMALL */ + "G]JMN[RQV[ZM", + "IZLMWML[W[", + "JZNMVMRRSRUSVUVXUZS[P[NZ", + "H\\XNUMPMNNMOLQLSMUNVPWTXVYWZX\\X^W`VaTbObLa RRTR\\", + "JZW[PROPPNRMTNUPTRM[", + "JYO[OMWM", + "JZM[RMW[", + "H[M[MMVMV[", + "I[N[NMTMVNWPWRVTTUNU", + "I[RMR[ RLMMNMRNTPUTUVTWRWNXM", + "I[V[VMSMQNPPOXNZL[", + "JZNKVK RMNR@WN", + "H\\LKRK RRGWG RR@RNYN RY@P@KN", + "I[SGVHWJWKVMTNNNN@S@UAVCVDUFSGNG", + "I[SGVHWJWKVMTNNNN@S@UAVCVDUFSGNG RKGQG", + "J[S@O@ONSNUMVLWIWEVBUAS@", # /* U+1D30 ^D_SMALLCAP */ + "JYOGTG RV@O@ONVN", + "KZUGPG RN@U@UNNN", + "HZUAS@P@NAMBLDLJMLNMPNTNVMVHSH", + "H[MGVG RM@MN RV@VN", + "MWRNR@ RUNON RU@O@", + "LYT@TJSLRMPNON", + "IZN@NN RPFVN RV@NH", + "JYO@ONVN", + "G]LNL@RKX@XN", + "H[MNM@VNV@", + "I\\WNW@NNN@", + "H[PNNMMLLJLDMBNAP@S@UAVBWDWJVLUMSNPN", + "G]O@NAMCNEPF RTFVEWCVAU@ RPFTFVGWIWKVMTNPNNMMKMINGPF", + "I[NNN@T@VAWCWEVGTHNH", + "I[RHWN RNNN@T@VAWCWEVGTHNH", + "KYM@W@ RR@RN", # /* U+1D40 ^T_SMALLCAP */ + "H[M@MKNMPNSNUMVKV@", + "G]J@NNRDVNZ@", + "KZOEQDSDUEVGVN RVMTNQNOMNKOIQHVH", + "JYNDNKOMQNSNUM RNEPDSDUEVGUISJNJ", + "H]WDUKTMRNPNNMMKMGNEPDRDTEVMWN", + "H\\XMVNUNSMRK RLDODQERHRKQMONNNLMKKKJVJXIYGXEVDUDSERH", + "KYO@ON ROMQNSNUMVKVGUESDQDOE", + "KYU@UN RUESDQDOENGNKOMQNSNUM", + "LYVMTNRNPMOKOGPERDSDUEVGVHOI", + "LYOEQDSDUEVGVKUMSNRNPMOKOJVI", + "LXPIRI RUETDPDOEOHPIOJOMPNTNUM", + "LXRITI ROEPDTDUEUHTIUJUMTNPNOM", + "KYUDUPTRRSOS RUESDQDOENGNKOMQNSNUM", + "NVRDRN RRUSTRSQTRURS", + "IZO@ON RUNQH RUDOJ", + "G]KNKD RKEMDODQERGRN RRGSEUDVDXEYGYN", # /* U+1D50 ^M_TINY */ + "KZODON ROEQDSDUEVGVPURSSRS", + "KYQNOMNKNGOEQDSDUEVGVKUMSNQN", + "LYOEQDSDUEVGVKUMSNQNOM", + "KYNINGOEQDSDUEVGVI", + "KYNINKOMQNSNUMVKVI", + "KYOSOD ROEQDSDUEVGVKUMSNQNOM", + "NXPDVD RR@RKSMUNVN", + "KYUDUN RNDNKOMQNSNUM", + "I[MFWF RMMTMVLWJWHVF", + "G]YDYN RYMWNUNSMRKRD RRKQMONNNLMKKKD", + "LXNDRNVD", + "LXVNPGPEQDSDTETGNN", + "KYSFRF RNSOQOCPAR@S@UAVCUESFUGVIVKUMSNQNOM", + "KXRMRS RMDOERMVD", + "KYSDQDOENGNKOMQNSNUMVKVGUESDPCOBOAP@U@", + "I[MDLFLJMLNMPNTNVMWLXJXGWEUDSERGRS", # /* U+1D60 ^PHI_TINY */ + "LXVDNS RNDPETRVS", + "NVRWRa RRPQQRRSQRPRR", + "LWPWPa RPZQXSWUW", + "KYUWUa RNWN^O`QaSaU`", + "LXNWRaVW", + "KYSYRY RNfOdOVPTRSSSUTVVUXSYUZV\\V^U`SaQaO`", + "KXR`Rf RMWOXR`VW", + "KYOfOZPXRWSWUXVZV^U`SaQaO`", + "I[MWLYL]M_N`PaTaV`W_X]XZWXUWSXRZRf", + "LXVWNf RNWPXTeVf", + "D`IMIXJZL[O[QZRX R[ZY[U[SZRXRPSNUMYM[N\\P\\RRT", + "H[M[MF RMNOMSMUNVOWQWWVYUZS[O[MZ RIHJGLFPHRGSF", + "I\\W[WF RWZU[Q[OZNYMWMQNOONQMUMWN RQHRGTFXHZG[F", + "MYOMWM RR[RISGUFWF RMTNSPRTTVSWR", + "D`I[IM RIOJNLMOMQNRPR[ RRPSNUMXMZN[P[[ RMTNSPRTTVSWR", + "I\\NMN[ RNOONQMTMVNWPW[ RMTNSPRTTVSWR", # /* U+1D70 N_SMALL TILDE */ + "H[MMMb RMNOMSMUNVOWQWWVYUZS[O[MZ RI`J_L^P`R_S^", + "KXP[PM RPQQORNTMVM RLTMSORSTUSVR", + "KXM[S[ RVMTMRNQOPRP[ RLTMSORSTUSVR", + "J[NZP[T[VZWXWWVUTTQTOSNQNPONQMTMVN RNTOSQRUTWSXR", + "MYOMWM RRFRXSZU[W[ RMSNRPQTSVRWQ", + "IZLMWML[W[ RMTNSPRTTVSWR", + "H[M[MJNHOGQFTFVG RMNOMSMUNVOWQWWVYUZS[O[MZ", + "H[MGVG RM@MN RV@VN", + "JZMMVMOURUTVUWVYV^U`TaRbPbNaM_M^N\\P[V[", + "MlOMWM RRFRXSZU[W[ R^[^F Rg[gPfNdMaM_N^O RiC]`", + "MWR[RM RU[O[ RUMOM ROTUT", + "MXRMRXSZU[ ROTUT", + "H[MMMb RMNOMSMUNVOWQWWVYUZS[O[MZ RHT\\T", + "H[MMMXNZP[S[UZVXVM RHT\\T", + "I\\XMUMUPWRXTXWWYVZT[Q[OZNYMWMTNRPPPMMM RHU\\U", + # /* // Phonetic Extensions Supplement (1D80-1DBF) */ + "F^K[KFYFY[K[", # /* U+1D80 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1D90 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1DA0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1DB0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // Combining Diacritical Marks Supplement (1DC0-1DFF) */ + "F^K[KFYFY[K[", # /* U+1DC0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1DD0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1DE0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+1DF0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // Latin Extended Additional (1E00-1EFF) */ + "I[MUWU RK[RFY[ RR`TaUcTeRfPeOcPaR`", # /* U+1E00 A_CAP +RING */ + "I\\W[WPVNTMPMNN RWZU[P[NZMXMVNTPSUSWR RR`TaUcTeRfPeOcPaR`", + "G\\SPVQWRXTXWWYVZT[L[LFSFUGVHWJWLVNUOSPLP RR?Q@RAS@R?RA", + "H[M[MF RMNOMSMUNVOWQWWVYUZS[O[MZ RN?M@NAO@N?NA", + "G\\SPVQWRXTXWWYVZT[L[LFSFUGVHWJWLVNUOSPLP RRbSaR`QaRbR`", + "H[M[MF RMNOMSMUNVOWQWWVYUZS[O[MZ RRbSaR`QaRbR`", + "G\\SPVQWRXTXWWYVZT[L[LFSFUGVHWJWLVNUOSPLP RWaMa", + "H[M[MF RMNOMSMUNVOWQWWVYUZS[O[MZ RWaMa", + "F[WYVZS[Q[NZLXKVJRJOKKLINGQFSFVGWH RR\\T]U_TaRbOb RT>QA", + "HZVZT[P[NZMYLWLQMONNPMTMVN RR\\T]U_TaRbOb RTEQH", + "G\\L[LFQFTGVIWKXOXRWVVXTZQ[L[ RR?Q@RAS@R?RA", + "I\\W[WF RWZU[Q[OZNYMWMQNOONQMUMWN RV?U@VAW@V?VA", + "G\\L[LFQFTGVIWKXOXRWVVXTZQ[L[ RRbSaR`QaRbR`", + "I\\W[WF RWZU[Q[OZNYMWMQNOONQMUMWN RSbTaS`RaSbS`", + "G\\L[LFQFTGVIWKXOXRWVVXTZQ[L[ RWaMa", + "I\\W[WF RWZU[Q[OZNYMWMQNOONQMUMWN RXaNa", + "G\\L[LFQFTGVIWKXOXRWVVXTZQ[L[ RQ\\S]T_SaQbNb", # /* U+1E10 D_CAP CEDILLA */ + "I\\W[WF RWZU[Q[OZNYMWMQNOONQMUMWN RS\\U]V_UaSbPb", + "G\\L[LFQFTGVIWKXOXRWVVXTZQ[L[ RVcR`Nc", + "I\\W[WF RWZU[Q[OZNYMWMQNOONQMUMWN RWcS`Oc", + "H[MPTP RW[M[MFWF RM@W@ RP9S<", + "I[VZT[P[NZMXMPNNPMTMVNWPWRMT RMGWG RP>SA", + "H[MPTP RW[M[MFWF RM@W@ RT9Q<", + "I[VZT[P[NZMXMPNNPMTMVNWPWRMT RMGWG RT>QA", + "H[MPTP RW[M[MFWF RVcR`Nc", + "I[VZT[P[NZMXMPNNPMTMVNWPWRMT RVcR`Nc", + "H[MPTP RW[M[MFWF RW`VaTbP`NaMb", + "I[VZT[P[NZMXMPNNPMTMVNWPWRMT RW`VaTbP`NaMb", + "H[MPTP RW[M[MFWF RR\\T]U_TaRbOb RN>O@QASAU@V>", + "I[VZT[P[NZMXMPNNPMTMVNWPWRMT RR\\T]U_TaRbOb RNEOGQHSHUGVE", + "HZTPMP RM[MFWF RR?Q@RAS@R?RA", + "MYOMWM RR[RISGUFWF RT?S@TAU@T?TA", + "F[VGTFQFNGLIKKJOJRKVLXNZQ[S[VZWYWRSR RM@W@", # /* U+1E20 G_CAP MACRON */ + "I\\WMW^V`UaSbPbNa RWZU[Q[OZNYMWMQNOONQMUMWN RMGWG", + "G]L[LF RLPXP RX[XF RR?Q@RAS@R?RA", + "H[M[MF RV[VPUNSMPMNNMO RM?L@MAN@M?MA", + "G]L[LF RLPXP RX[XF RRbSaR`QaRbR`", + "H[M[MF RV[VPUNSMPMNNMO RRbSaR`QaRbR`", + "G]L[LF RLPXP RX[XF RN?O@NAM@N?NA RV?W@VAU@V?VA", + "H[M[MF RV[VPUNSMPMNNMO RI?J@IAH@I?IA RQ?R@QAP@Q?QA", + "G]L[LF RLPXP RX[XF RL\\N]O_NaLbIb", + "H[M[MF RV[VPUNSMPMNNMO RM\\O]P_OaMbJb", + "G]L[LF RLPXP RX[XF RV`UbScQcObN`", + "H[M[MF RV[VPUNSMPMNNMO RV`UbScQcObN`", + "MWR[RF RW`VaTbP`NaMb", + "MWR[RM RRFQGRHSGRFRH RW`VaTbP`NaMb", + "MWR[RF RN?O@NAM@N?NA RV?W@VAU@V?VA RT9Q<", + "MWR[RM RNFOGNHMGNFNH RVFWGVHUGVFVH RT>QA", + "G\\L[LF RX[OO RXFLR RT>QA", # /* U+1E30 K_CAP ACUTE */ + "IZN[NF RPSV[ RVMNU RPAMD", + "G\\L[LF RX[OO RXFLR RRbSaR`QaRbR`", + "IZN[NF RPSV[ RVMNU RRbSaR`QaRbR`", + "G\\L[LF RX[OO RXFLR RWaMa", + "IZN[NF RPSV[ RVMNU RWaMa", + "HYW[M[MF RRbSaR`QaRbR`", + "MXU[SZRXRF RSbTaS`RaSbS`", + "HYW[M[MF RH@R@ RRbSaR`QaRbR`", + "MXU[SZRXRF RM@W@ RSbTaS`RaSbS`", + "HYW[M[MF RWaMa", + "MXU[SZRXRF RXaNa", + "HYW[M[MF RVcR`Nc", + "MXU[SZRXRF RWcS`Oc", + "F^K[KFRUYFY[ RT>QA", + "D`I[IM RIOJNLMOMQNRPR[ RRPSNUMXMZN[P[[ RTEQH", + "F^K[KFRUYFY[ RR?Q@RAS@R?RA", # /* U+1E40 M_CAP DOT */ + "D`I[IM RIOJNLMOMQNRPR[ RRPSNUMXMZN[P[[ RRFQGRHSGRFRH", + "F^K[KFRUYFY[ RRbSaR`QaRbR`", + "D`I[IM RIOJNLMOMQNRPR[ RRPSNUMXMZN[P[[ RRbSaR`QaRbR`", + "G]L[LFX[XF RR?Q@RAS@R?RA", + "I\\NMN[ RNOONQMTMVNWPW[ RRFQGRHSGRFRH", + "G]L[LFX[XF RRbSaR`QaRbR`", + "I\\NMN[ RNOONQMTMVNWPW[ RRbSaR`QaRbR`", + "G]L[LFX[XF RWaMa", + "I\\NMN[ RNOONQMTMVNWPW[ RWaMa", + "G]L[LFX[XF RVcR`Nc", + "I\\NMN[ RNOONQMTMVNWPW[ RVcR`Nc", + "G]PFTFVGXIYMYTXXVZT[P[NZLXKTKMLINGPF RMAN@P?TAV@W? RT9Q<", + "H[P[NZMYLWLQMONNPMSMUNVOWQWWVYUZS[P[ RMHNGPFTHVGWF RT>QA", + "G]PFTFVGXIYMYTXXVZT[P[NZLXKTKMLINGPF RMAN@P?TAV@W? RN:O;NSA", + "G]PFTFVGXIYMYTXXVZT[P[NZLXKTKMLINGPF RM@W@ RT9Q<", + "H[P[NZMYLWLQMONNPMSMUNVOWQWWVYUZS[P[ RMGWG RT>QA", + "G\\L[LFTFVGWHXJXMWOVPTQLQ RT>QA", + "H[MMMb RMNOMSMUNVOWQWWVYUZS[O[MZ RTEQH", + "G\\L[LFTFVGWHXJXMWOVPTQLQ RR?Q@RAS@R?RA", + "H[MMMb RMNOMSMUNVOWQWWVYUZS[O[MZ RRFQGRHSGRFRH", + "G\\X[QQ RL[LFTFVGWHXJXMWOVPTQLQ RR?Q@RAS@R?RA", + "KXP[PM RPQQORNTMVM RSFRGSHTGSFSH", + "G\\X[QQ RL[LFTFVGWHXJXMWOVPTQLQ RRbSaR`QaRbR`", + "KXP[PM RPQQORNTMVM RPbQaP`OaPbP`", + "G\\X[QQ RL[LFTFVGWHXJXMWOVPTQLQ RM@W@ RRbSaR`QaRbR`", + "KXP[PM RPQQORNTMVM RNGXG RPbQaP`OaPbP`", + "G\\X[QQ RL[LFTFVGWHXJXMWOVPTQLQ RWaMa", + "KXP[PM RPQQORNTMVM RUaKa", + "H\\LZO[T[VZWYXWXUWSVRTQPPNOMNLLLJMHNGPFUFXG RR?Q@RAS@R?RA", # /* U+1E60 S_CAP DOT */ + "J[NZP[T[VZWXWWVUTTQTOSNQNPONQMTMVN RRFQGRHSGRFRH", + "H\\LZO[T[VZWYXWXUWSVRTQPPNOMNLLLJMHNGPFUFXG RRbSaR`QaRbR`", + "J[NZP[T[VZWXWWVUTTQTOSNQNPONQMTMVN RRbSaR`QaRbR`", + "H\\LZO[T[VZWYXWXUWSVRTQPPNOMNLLLJMHNGPFUFXG RU>RA RM>N?M@L?M>M@", + "J[NZP[T[VZWXWWVUTTQTOSNQNPONQMTMVN RUERH RMENFMGLFMEMG", + "H\\LZO[T[VZWYXWXUWSVRTQPPNOMNLLLJMHNGPFUFXG RN>RAV> RR:Q;RQA", + "G]LFLWMYNZP[T[VZWYXWXF RM@W@ RN:O;NSA", # /* U+1E80 W_CAP GRAVE */ + "G]JMN[RQV[ZM RPESH", + "F^IFN[RLV[[F RT>QA", + "G]JMN[RQV[ZM RTEQH", + "F^IFN[RLV[[F RN?O@NAM@N?NA RV?W@VAU@V?VA", + "G]JMN[RQV[ZM RNFOGNHMGNFNH RVFWGVHUGVFVH", + "F^IFN[RLV[[F RR?Q@RAS@R?RA", + "G]JMN[RQV[ZM RRFQGRHSGRFRH", + "F^IFN[RLV[[F RRbSaR`QaRbR`", + "G]JMN[RQV[ZM RRbSaR`QaRbR`", + "H\\KFY[ RYFK[ RR?Q@RAS@R?RA", + "IZL[WM RLMW[ RRFQGRHSGRFRH", + "H\\KFY[ RYFK[ RN?O@NAM@N?NA RV?W@VAU@V?VA", + "IZL[WM RLMW[ RNFOGNHMGNFNH RVFWGVHUGVFVH", + "I[RQR[ RKFRQYF RR?Q@RAS@R?RA", + "JZMMR[ RWMR[P`OaMb RRFQGRHSGRFRH", + "H\\KFYFK[Y[ RNAR>VA", # /* U+1E90 Z_CAP CIRCUMFLEX */ + "IZLMWML[W[ RNHREVH", + "H\\KFYFK[Y[ RRbSaR`QaRbR`", + "IZLMWML[W[ RRbSaR`QaRbR`", + "H\\KFYFK[Y[ RWaMa", + "IZLMWML[W[ RWaMa", + "H[M[MF RV[VPUNSMPMNNMO RWaMa", + "MYOMWM RRFRXSZU[W[ RN?O@NAM@N?NA RV?W@VAU@V?VA", + "G]JMN[RQV[ZM RRHPGOEPCRBTCUETGRH", + "JZMMR[ RWMR[P`OaMb RRHPGOEPCRBTCUETGRH", + "I\\W[WPVNTMPMNN RWZU[P[NZMXMVNTPSUSWR RWJYIZGYEWD", + "MYR[RISGUFWF RT?S@TAU@T?TA", + "MYR[RISGUFWF ROSUO", + "MYR[RISGUFWF ROLUL", + "E^J[JLKIMGPFZFSNVNXOYPZRZWYYXZV[R[PZOY", + "H[SMPMNNMOLQLWMYNZP[S[UZVYWWWQVOUNSMPLNKMINGPFTFVG", + "I[MUWU RK[RFY[ RRbSaR`QaRbR`", # /* U+1EA0 A_CAP +DOT */ + "I\\W[WPVNTMPMNN RWZU[P[NZMXMVNTPSUSWR RRbSaR`QaRbR`", + "I[MUWU RK[RFY[ RRAT?U=T;R:P:", + "I\\W[WPVNTMPMNN RWZU[P[NZMXMVNTPSUSWR RRHTFUDTBRAPA", + "I[MUWU RK[RFY[ RU>X; RNAR>VA", + "I\\W[WPVNTMPMNN RWZU[P[NZMXMVNTPSUSWR RUEXB RNHREVH", + "I[MUWU RK[RFY[ RO>L; RNAR>VA", + "I\\W[WPVNTMPMNN RWZU[P[NZMXMVNTPSUSWR ROELB RNHREVH", + "I[MUWU RK[RFY[ RNAR>VA RXAZ?[=Z;X:V:", + "I\\W[WPVNTMPMNN RWZU[P[NZMXMVNTPSUSWR RNHREVH RXHZF[DZBXAVA", + "I[MUWU RK[RFY[ RNAR>VA RMVA RRbSaR`QaRbR`", + "I\\W[WPVNTMPMNN RWZU[P[NZMXMVNTPSUSWR RNHREVH RRbSaR`QaRbR`", + "I[MUWU RK[RFY[ RN>O@QASAU@V> RT9Q<", + "I\\W[WPVNTMPMNN RWZU[P[NZMXMVNTPSUSWR RNEOGQHSHUGVE RT>QA", + "I[MUWU RK[RFY[ RN>O@QASAU@V> RP9S<", # /* U+1EB0 A_CAP BREVE */ + "I\\W[WPVNTMPMNN RWZU[P[NZMXMVNTPSUSWR RNEOGQHSHUGVE RP>SA", + "I[MUWU RK[RFY[ RN>O@QASAU@V> RP>RN>", + "I[MUWU RK[RFY[ RN>O@QASAU@V> RMO@QASAU@V> RRbSaR`QaRbR`", + "I\\W[WPVNTMPMNN RWZU[P[NZMXMVNTPSUSWR RNEOGQHSHUGVE RRbSaR`QaRbR`", + "H[MPTP RW[M[MFWF RRbSaR`QaRbR`", + "I[VZT[P[NZMXMPNNPMTMVNWPWRMT RRbSaR`QaRbR`", + "H[MPTP RW[M[MFWF RRAT?U=T;R:P:", + "I[VZT[P[NZMXMPNNPMTMVNWPWRMT RRHTFUDTBRAPA", + "H[MPTP RW[M[MFWF RMAN@P?TAV@W?", + "I[VZT[P[NZMXMPNNPMTMVNWPWRMT RMHNGPFTHVGWF", + "H[MPTP RW[M[MFWF RU>X; RNAR>VA", + "I[VZT[P[NZMXMPNNPMTMVNWPWRMT RUEXB RNHREVH", + "H[MPTP RW[M[MFWF RO>L; RNAR>VA", # /* U+1EC0 E_CAP CIRCUMFLEX_GRAVE */ + "I[VZT[P[NZMXMPNNPMTMVNWPWRMT ROELB RNHREVH", + "H[MPTP RW[M[MFWF RNAR>VA RXAZ?[=Z;X:V:", + "I[VZT[P[NZMXMPNNPMTMVNWPWRMT RNHREVH RXHZF[DZBXAVA", + "H[MPTP RW[M[MFWF RNAR>VA RMVA RRbSaR`QaRbR`", + "I[VZT[P[NZMXMPNNPMTMVNWPWRMT RNHREVH RRbSaR`QaRbR`", + "MWR[RF RRAT?U=T;R:P:", + "MWR[RM RRHTFUDTBRAPA", + "MWR[RF RRbSaR`QaRbR`", + "MWR[RM RRFQGRHSGRFRH RRbSaR`QaRbR`", + "G]PFTFVGXIYMYTXXVZT[P[NZLXKTKMLINGPF RRbSaR`QaRbR`", + "H[P[NZMYLWLQMONNPMSMUNVOWQWWVYUZS[P[ RRbSaR`QaRbR`", + "G]PFTFVGXIYMYTXXVZT[P[NZLXKTKMLINGPF RRAT?U=T;R:P:", + "H[P[NZMYLWLQMONNPMSMUNVOWQWWVYUZS[P[ RRHTFUDTBRAPA", + "G]PFTFVGXIYMYTXXVZT[P[NZLXKTKMLINGPF RU>X; RNAR>VA", # /* U+1ED0 O_CAP CIRCUMFLEX_ACUTE */ + "H[P[NZMYLWLQMONNPMSMUNVOWQWWVYUZS[P[ RUEXB RNHREVH", + "G]PFTFVGXIYMYTXXVZT[P[NZLXKTKMLINGPF RO>L; RNAR>VA", + "H[P[NZMYLWLQMONNPMSMUNVOWQWWVYUZS[P[ ROELB RNHREVH", + "G]PFTFVGXIYMYTXXVZT[P[NZLXKTKMLINGPF RNAR>VA RXAZ?[=Z;X:V:", + "H[P[NZMYLWLQMONNPMSMUNVOWQWWVYUZS[P[ RNHREVH RXHZF[DZBXAVA", + "G]PFTFVGXIYMYTXXVZT[P[NZLXKTKMLINGPF RNAR>VA RMVA RRbSaR`QaRbR`", + "H[P[NZMYLWLQMONNPMSMUNVOWQWWVYUZS[P[ RNHREVH RRbSaR`QaRbR`", + "G]PFTFVGXIYMYTXXVZT[P[NZLXKTKMLINGPF RVGXFYDXBWA RT>QA", + "H[P[NZMYLWLQMONNPMSMUNVOWQWWVYUZS[P[ RUNWMXKWIVH RTEQH", + "G]PFTFVGXIYMYTXXVZT[P[NZLXKTKMLINGPF RVGXFYDXBWA RP>SA", + "H[P[NZMYLWLQMONNPMSMUNVOWQWWVYUZS[P[ RUNWMXKWIVH RPESH", + "G]PFTFVGXIYMYTXXVZT[P[NZLXKTKMLINGPF RVGXFYDXBWA RRAT?U=T;R:P:", + "H[P[NZMYLWLQMONNPMSMUNVOWQWWVYUZS[P[ RUNWMXKWIVH RRHTFUDTBRAPA", + "G]PFTFVGXIYMYTXXVZT[P[NZLXKTKMLINGPF RVGXFYDXBWA RWAVBTCPANBMC", # /* U+1EE0 O_CAP HORN */ + "H[P[NZMYLWLQMONNPMSMUNVOWQWWVYUZS[P[ RUNWMXKWIVH RWHVITJPHNIMJ", + "G]PFTFVGXIYMYTXXVZT[P[NZLXKTKMLINGPF RVGXFYDXBWA RRbSaR`QaRbR`", + "H[P[NZMYLWLQMONNPMSMUNVOWQWWVYUZS[P[ RUNWMXKWIVH RRbSaR`QaRbR`", + "G]LFLWMYNZP[T[VZWYXWXF RRbSaR`QaRbR`", + "H[VMV[ RMMMXNZP[S[UZVY RRbSaR`QaRbR`", + "G]LFLWMYNZP[T[VZWYXWXF RRAT?U=T;R:P:", + "H[VMV[ RMMMXNZP[S[UZVY RRHTFUDTBRAPA", + "G]LFLWMYNZP[T[VZWYXWXF RXFZE[CZAY@ RT>QA", + "H[VMV[ RMMMXNZP[S[UZVY RVMXLYJXHWG RTEQH", + "G]LFLWMYNZP[T[VZWYXWXF RXFZE[CZAY@ RP>SA", + "H[VMV[ RMMMXNZP[S[UZVY RVMXLYJXHWG RPESH", + "G]LFLWMYNZP[T[VZWYXWXF RXFZE[CZAY@ RRAT?U=T;R:P:", + "H[VMV[ RMMMXNZP[S[UZVY RVMXLYJXHWG RRHTFUDTBRAPA", + "G]LFLWMYNZP[T[VZWYXWXF RXFZE[CZAY@ RWAVBTCPANBMC", + "H[VMV[ RMMMXNZP[S[UZVY RVMXLYJXHWG RWHVITJPHNIMJ", + "G]LFLWMYNZP[T[VZWYXWXF RXFZE[CZAY@ RRbSaR`QaRbR`", # /* U+1EF0 U_CAP HORN */ + "H[VMV[ RMMMXNZP[S[UZVY RVMXLYJXHWG RRbSaR`QaRbR`", + "I[RQR[ RKFRQYF RP>SA", + "JZMMR[ RWMR[P`OaMb RPESH", + "I[RQR[ RKFRQYF RRbSaR`QaRbR`", + "JZMMR[ RWMR[P`OaMb RVbWaV`UaVbV`", + "I[RQR[ RKFRQYF RRAT?U=T;R:P:", + "JZMMR[ RWMR[P`OaMb RRHTFUDTBRAPA", + "I[RQR[ RKFRQYF RMAN@P?TAV@W?", + "JZMMR[ RWMR[P`OaMb RMHNGPFTHVGWF", + "E\\PFP[ RJFJ[Z[", + "J[MMWM ROFOXPZR[ RX[VZUXUF", + "G]QFOGMJLMLWMYNZP[T[VZXXYVYTXPVMUL", + "H[QMONNOMQMWNYOZQ[S[UZVYWWWUVSURSQ", + "G[KFRT RYFRTPXOZM[KZJXKVMUOVPX", + "JZMMR[ RWMR[Q_PaNbLaK_L]N\\P]Q_", + # /* // Greek Extended (1F00-1FFF) */ + "H]YMVWUYTZR[P[NZMYLVLRMONNPMRMTNUOVQWXXZZ[ RQHRHSGSE", # /* U+1F00 ALPHA_SMALL PSILI */ + "H]YMVWUYTZR[P[NZMYLVLRMONNPMRMTNUOVQWXXZZ[ RQEQGRHSH", + "H]YMVWUYTZR[P[NZMYLVLRMONNPMRMTNUOVQWXXZZ[ RTEWH RMHNHOGOE", + "H]YMVWUYTZR[P[NZMYLVLRMONNPMRMTNUOVQWXXZZ[ RTEWH RMEMGNHOH", + "H]YMVWUYTZR[P[NZMYLVLRMONNPMRMTNUOVQWXXZZ[ RXEUH RMHNHOGOE", + "H]YMVWUYTZR[P[NZMYLVLRMONNPMRMTNUOVQWXXZZ[ RXEUH RMEMGNHOH", + "H]YMVWUYTZR[P[NZMYLVLRMONNPMRMTNUOVQWXXZZ[ RQHRHSGSE RMAN@P?TAV@W?", + "H]YMVWUYTZR[P[NZMYLVLRMONNPMRMTNUOVQWXXZZ[ RQEQGRHSH RMAN@P?TAV@W?", + "G[MUWU RK[RFY[ RJHKHLGLE", + "G[MUWU RK[RFY[ RJEJGKHLH", + "?[MUWU RK[RFY[ RIELH RBHCHDGDE", + "?[MUWU RK[RFY[ RIELH RBEBGCHDH", + "?[MUWU RK[RFY[ RMEJH RBHCHDGDE", + "?[MUWU RK[RFY[ RMEJH RBEBGCHDH", + "D[MUWU RK[RFY[ RFAG@I?MAO@P? RJHKHLGLE", + "D[MUWU RK[RFY[ RFAG@I?MAO@P? RJEJGKHLH", + "IZPTNUMWMXNZP[T[VZ RRTPTNSMQMPNNPMTMVN RQHRHSGSE", # /* U+1F10 EPSILON_SMALL PSILI */ + "IZPTNUMWMXNZP[T[VZ RRTPTNSMQMPNNPMTMVN RQEQGRHSH", + "IZPTNUMWMXNZP[T[VZ RRTPTNSMQMPNNPMTMVN RTEWH RMHNHOGOE", + "IZPTNUMWMXNZP[T[VZ RRTPTNSMQMPNNPMTMVN RTEWH RMEMGNHOH", + "IZPTNUMWMXNZP[T[VZ RRTPTNSMQMPNNPMTMVN RXEUH RMHNHOGOE", + "IZPTNUMWMXNZP[T[VZ RRTPTNSMQMPNNPMTMVN RXEUH RMEMGNHOH", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "B[MPTP RW[M[MFWF REHFHGGGE", + "B[MPTP RW[M[MFWF REEEGFHGH", + ":[MPTP RW[M[MFWF RDEGH R=H>H?G?E", + ":[MPTP RW[M[MFWF RDEGH R=E=G>H?H", + ":[MPTP RW[M[MFWF RHEEH R=H>H?G?E", + ":[MPTP RW[M[MFWF RHEEH R=E=G>H?H", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "I\\NMN[ RNOONQMTMVNWPWb RQHRHSGSE", # /* U+1F20 ETA_SMALL PSILI */ + "I\\NMN[ RNOONQMTMVNWPWb RQEQGRHSH", + "I\\NMN[ RNOONQMTMVNWPWb RTEWH RMHNHOGOE", + "I\\NMN[ RNOONQMTMVNWPWb RTEWH RMEMGNHOH", + "I\\NMN[ RNOONQMTMVNWPWb RXEUH RMHNHOGOE", + "I\\NMN[ RNOONQMTMVNWPWb RXEUH RMEMGNHOH", + "I\\NMN[ RNOONQMTMVNWPWb RQHRHSGSE RMAN@P?TAV@W?", + "I\\NMN[ RNOONQMTMVNWPWb RQEQGRHSH RMAN@P?TAV@W?", + "A]L[LF RLPXP RX[XF RDHEHFGFE", + "A]L[LF RLPXP RX[XF RDEDGEHFH", + "9]L[LF RLPXP RX[XF RCEFH RG>E", + "9]L[LF RLPXP RX[XF RCEFH RH", + "9]L[LF RLPXP RX[XF RGEDH RG>E", + "9]L[LF RLPXP RX[XF RGEDH RH", + ">]L[LF RLPXP RX[XF R@AA@C?GAI@J? RDHEHFGFE", + ">]L[LF RLPXP RX[XF R@AA@C?GAI@J? RDEDGEHFH", + "MXRMRXSZU[ RQHRHSGSE", # /* U+1F30 IOTA_SMALL PSILI */ + "MXRMRXSZU[ RQEQGRHSH", + "MXRMRXSZU[ RTEWH RMHNHOGOE", + "MXRMRXSZU[ RTEWH RMEMGNHOH", + "MXRMRXSZU[ RXEUH RMHNHOGOE", + "MXRMRXSZU[ RXEUH RMEMGNHOH", + "MXRMRXSZU[ RQHRHSGSE RMAN@P?TAV@W?", + "MXRMRXSZU[ RQEQGRHSH RMAN@P?TAV@W?", + "GWR[RF RJHKHLGLE", + "GWR[RF RJEJGKHLH", + "?WR[RF RIELH RBHCHDGDE", + "?WR[RF RIELH RBEBGCHDH", + "?WR[RF RMEJH RBHCHDGDE", + "?WR[RF RMEJH RBEBGCHDH", + "DWR[RF RFAG@I?MAO@P? RJHKHLGLE", + "DWR[RF RFAG@I?MAO@P? RJEJGKHLH", + "H[P[NZMYLWLQMONNPMSMUNVOWQWWVYUZS[P[ RQHRHSGSE", # /* U+1F40 O_SMALL PSILI */ + "H[P[NZMYLWLQMONNPMSMUNVOWQWWVYUZS[P[ RQEQGRHSH", + "H[P[NZMYLWLQMONNPMSMUNVOWQWWVYUZS[P[ RTEWH RMHNHOGOE", + "H[P[NZMYLWLQMONNPMSMUNVOWQWWVYUZS[P[ RTEWH RMEMGNHOH", + "H[P[NZMYLWLQMONNPMSMUNVOWQWWVYUZS[P[ RXEUH RMHNHOGOE", + "H[P[NZMYLWLQMONNPMSMUNVOWQWWVYUZS[P[ RXEUH RMEMGNHOH", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "B]PFTFVGXIYMYTXXVZT[P[NZLXKTKMLINGPF REHFHGGGE", + "B]PFTFVGXIYMYTXXVZT[P[NZLXKTKMLINGPF REEEGFHGH", + ":]PFTFVGXIYMYTXXVZT[P[NZLXKTKMLINGPF RDEGH R=H>H?G?E", + ":]PFTFVGXIYMYTXXVZT[P[NZLXKTKMLINGPF RDEGH R=E=G>H?H", + ":]PFTFVGXIYMYTXXVZT[P[NZLXKTKMLINGPF RHEEH R=H>H?G?E", + ":]PFTFVGXIYMYTXXVZT[P[NZLXKTKMLINGPF RHEEH R=E=G>H?H", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "H[MMMXNZP[S[UZVYWWWPVNUM RQHRHSGSE", # /* U+1F50 UPSILON_SMALL PSILI */ + "H[MMMXNZP[S[UZVYWWWPVNUM RQEQGRHSH", + "H[MMMXNZP[S[UZVYWWWPVNUM RTEWH RMHNHOGOE", + "H[MMMXNZP[S[UZVYWWWPVNUM RTEWH RMEMGNHOH", + "H[MMMXNZP[S[UZVYWWWPVNUM RXEUH RMHNHOGOE", + "H[MMMXNZP[S[UZVYWWWPVNUM RXEUH RMEMGNHOH", + "H[MMMXNZP[S[UZVYWWWPVNUM RQHRHSGSE RMAN@P?TAV@W?", + "H[MMMXNZP[S[UZVYWWWPVNUM RQEQGRHSH RMAN@P?TAV@W?", + "F^K[KFYFY[K[", + "@[RQR[ RKFRQYF RCECGDHEH", + "F^K[KFYFY[K[", + "8[RQR[ RKFRQYF RBEEH R;E;GG>E RR`RcSdTd", + "9]L[LF RLPXP RX[XF RCEFH RH RR`RcSdTd", + "9]L[LF RLPXP RX[XF RGEDH RG>E RR`RcSdTd", + "9]L[LF RLPXP RX[XF RGEDH RH RR`RcSdTd", + ">]L[LF RLPXP RX[XF R@AA@C?GAI@J? RDHEHFGFE RR`RcSdTd", + ">]L[LF RLPXP RX[XF R@AA@C?GAI@J? RDEDGEHFH RR`RcSdTd", + "G]RTRX RMMLNKPKXLZN[O[QZRXSZU[V[XZYXYPXNWM RQHRHSGSE RR`RcSdTd", # /* U+1FA0 OMEGA_SMALL PSILI */ + "G]RTRX RMMLNKPKXLZN[O[QZRXSZU[V[XZYXYPXNWM RQEQGRHSH RR`RcSdTd", + "G]RTRX RMMLNKPKXLZN[O[QZRXSZU[V[XZYXYPXNWM RTEWH RMHNHOGOE RR`RcSdTd", + "G]RTRX RMMLNKPKXLZN[O[QZRXSZU[V[XZYXYPXNWM RTEWH RMEMGNHOH RR`RcSdTd", + "G]RTRX RMMLNKPKXLZN[O[QZRXSZU[V[XZYXYPXNWM RXEUH RMHNHOGOE RR`RcSdTd", + "G]RTRX RMMLNKPKXLZN[O[QZRXSZU[V[XZYXYPXNWM RXEUH RMEMGNHOH RR`RcSdTd", + "G]RTRX RMMLNKPKXLZN[O[QZRXSZU[V[XZYXYPXNWM RQHRHSGSE RMAN@P?TAV@W? RR`RcSdTd", + "G]RTRX RMMLNKPKXLZN[O[QZRXSZU[V[XZYXYPXNWM RQEQGRHSH RMAN@P?TAV@W? RR`RcSdTd", + "@^J[O[OWMVKTJQJLKIMGPFTFWGYIZLZQYTWVUWU[Z[ RCHDHEGEE RR`RcSdTd", + "@^J[O[OWMVKTJQJLKIMGPFTFWGYIZLZQYTWVUWU[Z[ RCECGDHEH RR`RcSdTd", + "8^J[O[OWMVKTJQJLKIMGPFTFWGYIZLZQYTWVUWU[Z[ RBEEH R;HO@QASAU@V>", + "I[MUWU RK[RFY[ RM@W@", + "G[MUWU RK[RFY[ RIELH", + "G[MUWU RK[RFY[ RMEJH", + "I[MUWU RK[RFY[ RR`RcSdTd", + "NVQHRHSGSE", + "NVR`RcSdTd", + "NVQHRHSGSE", + "KZMHNGPFTHVGWF", # /* U+1FC0 TILDE */ + "LXMCNBPATCVBWA RNFOGNHMGNFNH RVFWGVHUGVFVH", + "I\\NMN[ RNOONQMTMVNWPWb RPESH RN`NcOdPd", + "I\\NMN[ RNOONQMTMVNWPWb RN`NcOdPd", + "I\\NMN[ RNOONQMTMVNWPWb RTEQH RN`NcOdPd", + "F^K[KFYFY[K[", + "I\\NMN[ RNOONQMTMVNWPWb RMHNGPFTHVGWF", + "I\\NMN[ RNOONQMTMVNWPWb RMHNGPFTHVGWF RN`NcOdPd", + "B[MPTP RW[M[MFWF RDEGH", + "B[MPTP RW[M[MFWF RHEEH", + "A]L[LF RLPXP RX[XF RCEFH", + "A]L[LF RLPXP RX[XF RGEDH", + "G]L[LF RLPXP RX[XF RR`RcSdTd", + "JZTEWH RMHNHOGOE", + "JZXEUH RMHNHOGOE", + "NVQHRHSGSE RMAN@P?TAV@W?", + "MXRMRXSZU[ RNEOGQHSHUGVE", # /* U+1FD0 IOTA_SMALL BREVE */ + "MXRMRXSZU[ RMGWG", + "MXRMRXSZU[ RNFOGNHMGNFNH RVFWGVHUGVFVH RP>SA", + "MXRMRXSZU[ RNFOGNHMGNFNH RVFWGVHUGVFVH RT>QA", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "MXRMRXSZU[ RMHNGPFTHVGWF", + "MXRMRXSZU[ RMCNBPATCVBWA RNFOGNHMGNFNH RVFWGVHUGVFVH", + "MWR[RF RN>O@QASAU@V>", + "MWR[RF RM@W@", + "GWR[RF RIELH", + "GWR[RF RMEJH", + "F^K[KFYFY[K[", + "JZTEWH RMEMGNHOH", + "JZXEUH RMEMGNHOH", + "NVQEQGRHSH RMAN@P?TAV@W?", + "H[MMMXNZP[S[UZVYWWWPVNUM RNEOGQHSHUGVE", # /* U+1FE0 UPSILON_SMALL BREVE */ + "H[MMMXNZP[S[UZVYWWWPVNUM RMGWG", + "H[MMMXNZP[S[UZVYWWWPVNUM RNFOGNHMGNFNH RVFWGVHUGVFVH RP>SA", + "H[MMMXNZP[S[UZVYWWWPVNUM RNFOGNHMGNFNH RVFWGVHUGVFVH RT>QA", + "H\\MbMQNOONQMTMVNWOXQXWWYVZT[Q[OZMX RQHRHSGSE", + "H\\MbMQNOONQMTMVNWOXQXWWYVZT[Q[OZMX RQEQGRHSH", + "H[MMMXNZP[S[UZVYWWWPVNUM RMHNGPFTHVGWF", + "H[MMMXNZP[S[UZVYWWWPVNUM RMCNBPATCVBWA RNFOGNHMGNFNH RVFWGVHUGVFVH", + "I[RQR[ RKFRQYF RN>O@QASAU@V>", + "I[RQR[ RKFRQYF RM@W@", + "@[RQR[ RKFRQYF RBEEH", + "@[RQR[ RKFRQYF RFECH", + "A\\L[LFTFVGWHXJXMWOVPTQLQ RDEDGEHFH", + "LXNFOGNHMGNFNH RVFWGVHUGVFVH RP>SA", + "LXNFOGNHMGNFNH RVFWGVHUGVFVH RT>QA", + "NVPESH", + "F^K[KFYFY[K[", # /* U+1FF0 */ + "F^K[KFYFY[K[", + "G]RTRX RMMLNKPKXLZN[O[QZRXSZU[V[XZYXYPXNWM RPESH RR`RcSdTd", + "G]RTRX RMMLNKPKXLZN[O[QZRXSZU[V[XZYXYPXNWM RR`RcSdTd", + "G]RTRX RMMLNKPKXLZN[O[QZRXSZU[V[XZYXYPXNWM RTEQH RR`RcSdTd", + "F^K[KFYFY[K[", + "G]RTRX RMMLNKPKXLZN[O[QZRXSZU[V[XZYXYPXNWM RMHNGPFTHVGWF", + "G]RTRX RMMLNKPKXLZN[O[QZRXSZU[V[XZYXYPXNWM RMHNGPFTHVGWF RR`RcSdTd", + "B]PFTFVGXIYMYTXXVZT[P[NZLXKTKMLINGPF RDEGH", + "B]PFTFVGXIYMYTXXVZT[P[NZLXKTKMLINGPF RHEEH", + "@^J[O[OWMVKTJQJLKIMGPFTFWGYIZLZQYTWVUWU[Z[ RBEEH", + "@^J[O[OWMVKTJQJLKIMGPFTFWGYIZLZQYTWVUWU[Z[ RFECH", + "F^J[O[OWMVKTJQJLKIMGPFTFWGYIZLZQYTWVUWU[Z[ RR`RcSdTd", + "NVTEQH", + "NVQEQGRHSH", + "F^K[KFYFY[K[", + # /* // General Punctuation (2000-206F) */ + "F^", # /* U+2000 SPACE_EM */ + "LX", + "F^", + "LX", + "NV", + "OU", + "PT", + "H\\", + "MW", + "PT", + "QS", + "RR", + "RR", + "RR", + "RR", + "RR", + "LXOTUT", # /* U+2010 HYPHEN */ + "LXOTUT", + "H\\JRZR", + "LXVTNT", + "F^IT[T", + "F^IT[T", + "H\\ODOb RUDUb", + "JZJbZb RJ]Z]", + "MWQGQFRDSC", + "MWSFSGRIQJ", + "MWSZS[R]Q^", + "MWQFQGRISJ", + "JZUGUFVDWC RMGMFNDOC", + "JZOFOGNIMJ RWFWGVIUJ", + "JZOZO[N]M^ RWZW[V]U^", + "JZUFUGVIWJ RMFMGNIOJ", + "I[MMWM RRFRb", # /* U+2020 DEI_SMALL */ + "I[M[W[ RMMWM RRFRb", + "E_PQPU RQUQQ RRPRV RSUSQ RTQTU RPTRVTT RPRRPTR RPQRPTQUSTURVPUOSPQ", + "E_PPPV RQQQU RRQRU RSSUS RSRST ROPUSOV RVSOWOOVS", + "MWRYSZR[QZRYR[", + "MaRYSZR[QZRYR[ R\\Y]Z\\[[Z\\Y\\[", + "MkRYSZR[QZRYR[ R\\Y]Z\\[[Z\\Y\\[ RfYgZf[eZfYf[", + "JZRRQSRTSSRRRT", + "RR", + "RR", + "RR", + "RR", + "RR", + "RR", + "RR", + "RR", + "FjJ[ZF RMFOGPIOKMLKKJIKGMF RcUeVfXeZc[aZ`XaVcU RYZZXYVWUUVTXUZW[YZ", # /* U+2030 PERMILLE */ + "FvJ[ZF RMFOGPIOKMLKKJIKGMF RcUeVfXeZc[aZ`XaVcU RoUqVrXqZo[mZlXmVoU RYZZXYVWUUVTXUZW[YZ", + "MWTFQL", + "JZQFNL RWFTL", + "G]NFKL RTFQL RZFWL", + "MWPFSL", + "JZSFVL RMFPL", + "G]VFYL RPFSL RJFML", + "LXVcR`Nc", + "KYUMOSUY", + "KYOMUSOY", + "E_LMXY RXMLY RKRLSKTJSKRKT RRYSZR[QZRYR[ RRKSLRMQLRKRM RYRZSYTXSYRYT", + "MaRYSZR[QZRYR[ RRSQGRFSGRSRF R\\Y]Z\\[[Z\\Y\\[ R\\S[G\\F]G\\S\\F", + "I[QFQS RQYRZQ[PZQYQ[ RQYRZQ[PZQYQ[ RMGOFTFVGWIWKVMUNSORPQRQS RMGOFTFVGWIWKVMUNSORPQRQS", + "E_JGZG", + "OUb`aa^c\\dYeTfPfKeHdFcCaB`", + "OUBFCEFCHBKAP@T@YA\\B^CaEbF", # /* U+2040 TIE */ + "E_N_VW RV_R[", + "CaKRKW RRFRK RYRYW RFUKWPU RH[KWN[ RMIRKWI ROORKUO RTUYW^U RV[YW\\[", + "LXOTUT", + "G][EI`", + "KYQSVS RVbQbQDVD", + "KYSSNS RNbSbSDND", + "ImQYRZQ[PZQYQ[ RMGOFTFVGWIWKVMUNSORPQRQS RcYdZc[bZcYc[ R_GaFfFhGiIiKhMgNeOdPcRcS", + "IeQYRZQ[PZQYQ[ RMGOFTFVGWIWKVMUNSORPQRQS R`YaZ`[_Z`Y`[ R`S_G`FaG`S`F", + "MiRYSZR[QZRYR[ RRSQGRFSGRSRF R_Y`Z_[^Z_Y_[ R[G]FbFdGeIeKdMcNaO`P_R_S", + "KYNMVMPb", + "G^NMN[ RUMUXVZX[ RJMWMYNZP", + "H\\NQNU RWPWV RPVPPOQOUPV RQPPPNQMSNUPVQVQP", + "H\\VQVU RMPMV RTVTPUQUUTV RSPTPVQWSVUTVSVSP", + "JZR[RV RWXRVMX RURRVOR", + "MWQZQ[R]S^ RRNQORPSORNRP", + "OUBFCEFCHBKAP@T@YA\\B^CaEbF Rb`aa^c\\dYeTfPfKeHdFcCaB`", # /* U+2050 TIE *TIE */ + "JZRFRK RMIRKWI ROORKUO RRFRK RWIRKMI RUORKOO", + "JZM^WB RNFOGNHMGNFNH RVYWZV[UZVYV[", + "E_JSKRNQQRSTVUYTZS", + ">fB^B]C[EZOZQYRWSYUZ_Za[b]b^", + "E_JSZS RR[RK RLMXY RXMLY", + "E_LRMSLTKSLRLT RXYYZX[WZXYX[ RXKYLXMWLXKXM", + "D`KFHL RQFNL RWFTL R]FZL", + "E_KRLSKTJSKRKT RRYSZR[QZRYR[ RRKSLRMQLRKRM RYRZSYTXSYRYT", + "E_LXMYLZKYLXLZ RLLMMLNKMLLLN RRRSSRTQSRRRT RXXYYXZWYXXXZ RXLYMXNWMXLXN", + "MWRYSZR[QZRYR[ RRNSORPQORNRP", + "E_KRLSKTJSKRKT RRYSZR[QZRYR[ RRKSLRMQLRKRM RYRZSYTXSYRYT", + "E_JSZS RR[RK RLXMYLZKYLXLZ RLLMMLNKMLLLN RXXYYXZWYXXXZ RXLYMXNWMXLXN", + "CaR\\S]R^Q]R\\R^ RRRSSRTQSRRRT RRHSIRJQIRHRJ", + "CaR^S_R`Q_R^R` RRVSWRXQWRVRX RRNSORPQORNRP RRFSGRHQGRFRH", + "OU", + "RR", # /* U+2060 0 */ + "RR", + "RR", + "RR", + "RR", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "RR", + "RR", + "RR", + "RR", + "RR", + "RR", + # /* // Subscripts and Superscripts (2070-209F) */ + "JZQ@S@UAVDVJUMSNQNOMNJNDOAQ@", # /* U+2070 ^DIGIT_0_SMALL */ + "NVRDRN RR=Q>R?S>R=R?", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "JZUFUN RQ@NJWJ", + "JZV@O@NFPESEUFVHVKUMSNPNNM", + "JZNHOFQESEUFVHVKUMSNQNOMNKNFOCPAR@U@", + "JZM@W@PN", + "JZQFOENCOAQ@S@UAVCUESFQFOGNINKOMQNSNUMVKVIUGSF", + "JZVFUHSIQIOHNFNCOAQ@S@UAVCVHUKTMRNON", + "I[LHXH RRBRN", + "I[LHXH", + "I[LJXJ RLFXF", + "MWT=S>RAQFQJROSRTS", + "MWP=Q>RASFSJROQRPS", + "KZODON ROEQDSDUEVGVN", + "JZQSSSUTVWV]U`SaQaO`N]NWOTQS", # /* U+2080 .DIGIT_0_SMALL */ + "JZVaNa RNVPURSRa", + "JZNTPSSSUTVVVXUZNaVa", + "JZNSVSRXSXUYV[V^U`SaPaN`", + "JZUYUa RQSN]W]", + "JZVSOSNYPXSXUYV[V^U`SaPaN`", + "JZN[OYQXSXUYV[V^U`SaQaO`N^NYOVPTRSUS", + "JZMSWSPa", + "JZQYOXNVOTQSSSUTVVUXSYQYOZN\\N^O`QaSaU`V^V\\UZSY", + "JZVYU[S\\Q\\O[NYNVOTQSSSUTVVV[U^T`RaOa", + "I[L[X[ RRURa", + "I[L[X[", + "I[L]X] RLYXY", + "MWTPSQRTQYQ]RbSeTf", + "MWPPQQRTSYS]RbQePf", + "RR", + "KZOXQWSWUXVZVa RV`TaQaO`N^O\\Q[V[", # /* U+2090 .A_TINY */ + "LYV`TaRaP`O^OZPXRWSWUXVZV[O\\", + "KYQaO`N^NZOXQWSWUXVZV^U`SaQa", + "KYNWVa RVWNa", + "LYOXQWSWUXVZV^U`SaRaP`O^O]V\\", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // Currency Symbols (20A0-20CF) */ + "F[XMPMP[X[ RTGRFNFLGKHJJJPKRLSNTUT", # /* U+20A0 ECU */ + "F[WYVZS[Q[NZLXKVJRJOKKLINGQFSFVGWH RSBG_ RZBN_", + "F[WYVZS[Q[NZLXKVJRJOKKLINGQFSFVGWH RR[RM RRQSOTNVMXM", + "HZTPMP RM[MFWF RJVRV", + "H[LMTM RL[W[ RO[OIPGRFUFWG RLSTS", + "D`I[IM RIOJNLMOMQNRPR[ RRPSNUMXMZN[P[[ RWHM`", + "G]L[LFX[XF RHV\\V RHP\\P", + "GyL[LFTFVGWHXJXMWOVPTQLQ R^MfM RaFaXbZd[f[ RlZn[r[tZuXuWtUrToTmSlQlPmNoMrMtN", + "GmX[QQ RL[LFTFVGWHXJXMWOVPTQLQ R`Zb[f[hZiXiWhUfTcTaS`Q`PaNcMfMhN", + "F^IFN[RLV[[F RHV\\V RHP\\P", + "D`I[IFOFRGTIULUR RONOUPXRZU[[[[F", + "I\\W[WF RWZU[Q[OZNYMWMQNOONQMUMWN RRHZH RXaNa", + "F[HSQS RHNTN RWYVZS[Q[NZLXKVJRJOKKLINGQFSFVGWH", + "G\\L[LF RX[OO RXFLR RLOTO", + "JZLFXF RR[RF ROVUR ROPUL", + "IoK[RFY[K[ R`b`QaObNdMgMiNjOkQkWjYiZg[d[bZ`X", + "G]ITJSLRNSOTQUSTXOYLYIXGVFUFSGRIRLSOXTYVYWXYWZT[", # /* U+20B0 PENNY_GERMAN */ + "G\\L[LFTFVGWHXJXMWOVPTQLQ RHL\\L", + "F[VGTFQFNGLIKKJOJRKVLXNZQ[S[VZWYWRSR RRCR^", + "I[K[RFY[ RHV\\V RHP\\P", + "H\\XZU[P[NZMYLWLUMSNRPQTPVOWNXLXJWHVGTFOFLG RRCR^", + "HZVZT[P[NZMYLWLQMONNPMTMVN RRJR^", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+20C0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // Combining Diacritical Marks For Symbols (20D0-20FF) */ + "F^K[KFYFY[K[", # /* U+20D0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+20E0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+20F0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // Letterlike Symbols (2100-214F) */ + "F^K[KFYFY[K[", # /* U+2100 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2110 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2120 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2130 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2140 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // Number Forms (2150-218F) */ + "F^K[KFYFY[K[", # /* U+2150 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2160 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2170 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2180 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // Arrows (2190-21FF) */ + "E_ZSJS RNWJSNO", # /* U+2190 !ARROW_E */ + "E_R[RK RNORKVO", + "E_JSZS RVWZSVO", + "E_RKR[ RVWR[NW", + "E_JSZS RVWZSVO RNOJSNW", + "E_R[RK RNORKVO RVWR[NW", + "E_KLYZ RRLKLKS", + "E_YLKZ RRLYLYS", + "E_YZKL RRZYZYS", + "E_KZYL RRZKZKS", + "E_ZSJS RRWVO RNOJSNW", + "E_JSZS RRONW RVWZSVO", + "E_JWJQPQ RJQMTOUQTSRUQWRZU", + "E_ZWZQTQ RZQWTUUSTQROQMRJU", + "E_ZSJS RTOPSTW RNWJSNO", + "E_R[RK RNURQVU RNORKVO", + "E_JSZS RPOTSPW RVWZSVO", # /* U+21A0 ARROW_DBL_E */ + "E_RKR[ RVQRUNQ RVWR[NW", + "E_JSVS RZOVSZW RNWJSNO", + "E_ZSNS RJONSJW RVWZSVO", + "E_ZOZW RJSZS RNWJSNO", + "E_R[RK RV[N[ RNORKVO", + "E_JOJW RZSJS RVWZSVO", + "E_RKR[ RNKVK RVWR[NW", + "E_N[V[ RR[RK RNWR[VW RNORKVO", + "E_NWJSNO RJSWSYRZPYNWM", + "E_VWZSVO RZSMSKRJPKNMM", + "E_NWJSNO RJSWSYRZPYNWMUNTPTW", + "E_VWZSVO RZSMSKRJPKNMMONPPPW", + "E_PUJUJO RZWZQTQ RZQWTUUSTQROQMRJU", + "E_JSZS RTOPW RNOJSNW RVWZSVO", + "E_PWR[VY ROKLTVOR[", + "E_V[VOJO RNSJONK", # /* U+21B0 !ARROW_E_N */ + "E_N[NOZO RVSZOVK", + "E_VKVWJW RNSJWN[", + "E_NKNWZW RVSZWV[", + "E_JOVOV[ RZWV[RW", + "E_VKVWJW RNSJWN[", + "E_OQKUGQ RYRYQXNVLSKQKNLLNKQKU", + "E_UQYU]Q RKRKQLNNLQKSKVLXNYQYU", + "E_KLYZ RKHYH RRLKLKS", + "E_JWZW RJKJS RZSZ[ RZOJO RNSJONK RV[ZWVS", + "E_[KUKUQ RMMLNKQKSLVNXQYSYVXXVYSYQXNUK", + "E_IKOKOQ RWMXNYQYSXVVXSYQYNXLVKSKQLNOK", + "E_ZSJSNO", + "E_ZSJSNW", + "E_R[RKVO", + "E_R[RKNO", + "E_JSZSVO", # /* U+21C0 HARPOON_UP_E */ + "E_JSZSVW", + "E_RKR[VW", + "E_RKR[NW", + "E_ZWJW RJOZO RVSZOVK RN[JWNS", + "E_N[NK RVKV[ RJONKRO RRWV[ZW", + "E_JWZW RZOJO RNSJONK RV[ZWVS", + "E_ZWJW RJOZO RN[JWNSJONK", + "E_N[NK RVKV[ RJONKROVKZO", + "E_JWZW RZOJO RV[ZWVSZOVK", + "E_VKV[ RN[NK RZWV[RWN[JW", + "E_JVZVVZ RZPJPNL", + "E_ZVJVNZ RJPZPVL", + "E_ZPMP RZVMV RRXVN ROXJSON", + "E_MVWV RMPWP RSNQX ROXJSON RUNZSUX", + "E_JVWV RJPWP RRNNX RUNZSUX", + "E_ZPMP RZVMV ROXJSON", # /* U+21D0 *ARROW_E_DBL */ + "E_ONO[ RUNU[ RWPRKMP", + "E_JVWV RJPWP RUNZSUX", + "E_UXUK ROXOK RMVR[WV", + "E_MVWV RMPWP ROXJSON RUNZSUX", + "E_OXON RUXUN RMVR[WV RWPRKMP", + "E_[XOL RW\\KP RSLKLKT", + "E_IXUL RM\\YP RQLYLYT", + "E_INUZ RMJYV RQZYZYR", + "E_[NOZ RWJKV RSZKZKR", + "E_ZXOX RZSJS RZNON RQLJSQZ", + "E_JXUX RJSZS RJNUN RSLZSSZ", + "E_NWJSNO RZUWQTUQQNULSJS", + "E_VWZSVO RJUMQPUSQVUXSZS", + "E_NXVX RNSVS RR[RK RNORKVO", + "E_VNNN RVSNS RRKR[ RVWR[NW", + "E_ZSWS RSSQS RMSJS RNOJSNW", # /* U+21E0 *ARROW_E_DASHED */ + "E_R[RX RRTRR RRNRK RNORKVO", + "E_JSMS RQSSS RWSZS RVWZSVO", + "E_RKRN RRRRT RRXR[ RVWR[NW", + "E_ZSJS RJWJO RNOJSNW", + "E_JSZS RZOZW RVWZSVO", + "E_ZPZVOVOXJSONOPZP", + "E_U[O[OPMPRKWPUPU[", + "E_JVJPUPUNZSUXUVJV", + "E_OKUKUVWVR[MVOVOK", + "E_U[O[OWUWU[ RUSOSOPMPRKWPUPUS", + "E_W[M[MWOWOPMPRKWPUPUWWWW[", + "E_ONUN RW[M[MWOWOPMPRKWPUPUWWWW[", + "E_RKR[ RW[M[MWOWOPMPRKWPUPUWWWW[", + "E_PPMPRKWPTP RU[O[OSMSRNWSUSU[", + "E_PPMPRKWPTP RW[M[MWOWOSMSRNWSUSUWWWW[", + "E_JNNNNPUPUNZSUXUVNVNXJXJN", # /* U+21F0 ARROW_E_WALL_WHITE */ + "E_Z[NO RZKJKJ[ RUONONV", + "E_JKVW RJ[Z[ZK ROWVWVP", + "E_MPRKWPUPUVWVR[MVOVOPMP", + "E_JSZS RVWZSVO RTRTTSVQWOWMVLTLRMPOOQOSPTR", + "E_V[VK RNKN[ RZOVKRO RRWN[JW", + "E_J[Z[ RJKZK RZSJS RVGZKVOZSVWZ[V_", + "E_ZSJS RTWTO RNOJSNW", + "E_JSZS RPOPW RVWZSVO", + "E_JSZS RRORW RNOJSNW RVWZSVO", + "E_ZSJS RWWWO RRWRO RNOJSNW", + "E_JSZS RMOMW RRORW RVWZSVO", + "E_JSZS RPOPW RTOTW RNWJSNO RVWZSVO", + "E_NSZS RNWNOJSNW", + "E_VSJS RVWVOZSVW", + "E_NSVS RNWJSNONW RVWVOZSVW", + # /* // Mathematical Operators (2200-22FF) */ + "I[MLWL RKFR[YF", # /* U+2200 =A_CAP */ + "HZVHUGSFPFNGMHLKLVMYNZP[S[UZVY", + "H[WOVNTMPMNNMOLQLWMYNZP[S[UZVYWWWJVHUGSFOFMG", + "I\\WPPP RM[W[WFMF", + "I\\WQPQ RMFWFW[M[ RXCL`", + "C`G[\\F ROFTFXHZJ\\N\\SZWXYT[O[KYIWGSGNIJKHOF", + "I[K[RFY[K[", + "I[YFR[KFYF", + "C`\\QGQ R\\GOGKIIKGOGSIWKYO[\\[", + "C`[CH^ R\\QGQ R\\GOGKIIKGOGSIWKYO[\\[", + "E_JSZS RZZPZMYKWJTJRKOMMPLZL", + "DaHP]P RHZUZYX[V]R]N[JYHUFHF", + "DaI^\\C RHP]P RHZUZYX[V]R]N[JYHUFHF", + "E_ZSJS RJZTZWYYWZTZRYOWMTLJL", + "E_M[WQ RMZWP RMYWO RMXWN RMWWM RMVWL RMUWK RMTVK RMSUK RMRTK RMQSK RMPRK RMOQK RMNPK RMMOK RMLNK RN[WR RO[WS RP[WT RQ[WU RR[WV RS[WW RT[WX RU[WY RV[WZ RM[MKWKW[M[", + "E_Z`ZFJFJ`", + "E_ZFZ`J`JF", # /* U+2210 ~PI_CAP_HUGE */ + "E_Z`I`TSIF[F", + "E_JSZS", + "E_ZWJW RROR_ RJKZK", + "E_JSZS RR[RK RRDQERFSERDRF", + "G][EI`", + "KYID[_", + "E_KOYW RR[RK RYOKW", + "E_PQRPTQUSTURVPUOSPQ", + "E_PQPU RQUQQ RRPRV RSUSQ RTQTU RPTRVTT RPRRPTR RPQRPTQUSTURVPUOSPQ", + "IbMTQSS[bB", + "IbMTQSS[bB RN@V@RESEUFVHVKUMSNPNNM", + "IbMTQSS[bB RUFUN RQ@NJWJ", + "E_XPWPUQQUOVMULSMQOPQQUUWVXV", + "E_TQVPXQYSXUVVTUPQNPLQKSLUNVPUTQ", + "E_JKJ[Z[", + "E_ZKJ[Z[", # /* U+2220 ANGLE */ + "E_ZKJ[Z[ RPSRUTZT]", + "E_Z[JSZK RSYTWUSTOSM", + "H\\RbRD", + "H\\NUVQ RRDRb", + "H\\ODOb RUDUb", + "H\\LVXP RODOb RUDUb", + "E_[[RKI[", + "E_IKR[[K", + "E_Z[ZQXMTKPKLMJQJ[", + "E_JKJULYP[T[XYZUZK", + "H\\L]M_O`Q_R]RISGUFWGXI", + "D`H]I_K`M_N]NIOGQFSGTI RP]Q_S`U_V]VIWGYF[G\\I", + "@dD]E_G`I_J]JIKGMFOGPI RL]M_O`Q_R]RISGUFWGXI RT]U_W`Y_Z]ZI[G]F_G`I", + "H\\L]M_O`Q_R]RISGUFWGXI RRMUNWPXSWVUXRYOXMVLSMPONRM", + "D`H]I_K`M_N]NIOGQFSGTI RP]Q_S`U_V]VIWGYF[G\\I RVMYN[P\\S[VYXVYNYKXIVHSIPKNNMVM", + "@dD]E_G`I_J]JIKGMFOGPI RL]M_O`Q_R]RISGUFWGXI RT]U_W`Y_Z]ZI[G]F_G`I RZM]N_P`S_V]XZYJYGXEVDSEPGNJMZM", # /* U+2230 INTEGRAL_TPL_CONTOUR */ + "H\\URXU[R RLSMPONRMUNWPXSXU RL]M_O`Q_R]RISGUFWGXI", + "H\\UQXT[Q RL]M_O`Q_R]RISGUFWGXI RLSMPONRMUNWPXSWVUXRYOXMVLS", + "H\\UUXR[U RL]M_O`Q_R]RISGUFWGXI RLSMPONRMUNWPXSWVUXRYOXMVLS", + "E_KXLYKZJYKXKZ RRLSMRNQMRLRN RYXZYYZXYYXYZ", + "E_YNXMYLZMYNYL RRZQYRXSYRZRX RKNJMKLLMKNKL", + "JZRXSYRZQYRXRZ RRLSMRNQMRLRN", + "E_LXMYLZKYLXLZ RLLMMLNKMLLLN RXXYYXZWYXXXZ RXLYMXNWMXLXN", + "E_JSZS RRFQGRHSGRFRH", + "E_JSTS RYXZYYZXYYXYZ RYLZMYNXMYLYN", + "E_JSZS RLXMYLZKYLXLZ RLLMMLNKMLLLN RXXYYXZWYXXXZ RXLYMXNWMXLXN", + "E_JSKRNQQRSTVUYTZS RRXSYRZQYRXRZ RRLSMRNQMRLRN", + "E_JSKRNQQRSTVUYTZS", + "E_ZSYRVQSRQTNUKTJS", + "E_WPYQZSYUWVTUPQMPKQJSKUMV", + "E_JSKNLLNKPLQNSXTZV[XZYXZS", + "E_RKSLTOSRQTPWQZR[", # /* U+2240 WREATH_PRODUCT */ + "E_JSKRNQQRSTVUYTZS RVKN[", + "E_ZPJP RZVYWVXSWQUNTKUJV", + "E_JVZV RJPKONNQOSQVRYQZP", + "E_JVZV RJPKONNQOSQVRYQZP RVKN[", + "E_JYZY RJSZS RJMKLNKQLSNVOYNZM", + "E_JYZY RJSZS RUPO\\ RJMKLNKQLSNVOYNZM", + "E_JYZY RJSZS RJMKLNKQLSNVOYNZM RXGL_", + "E_JVKUNTQUSWVXYWZV RJPKONNQOSQVRYQZP", + "E_JVKUNTQUSWVXYWZV RJPKONNQOSQVRYQZP RVKN[", + "E_JYZY RJSKRNQQRSTVUYTZS RJMKLNKQLSNVOYNZM", + "E_JYKXNWQXSZV[YZZY RJSKRNQQRSTVUYTZS RJMKLNKQLSNVOYNZM", + "E_ZYJY RZSJS RZMYLVKSLQNNOKNJM", + "E_JXLWPVTVXWZX RJNLOPPTPXOZN", + "E_JVNVNWOYQZSZUYVWVVZV RJPNPNOOMQLSLUMVOVPZP", + "E_ZVJV RJPNPNOOMQLSLUMVOVPZP", + "E_JPZP RZVJV RRHQIRJSIRHRJ", # /* U+2250 EQUAL DOT */ + "E_JPZP RZVJV RRXSYRZQYRXRZ RRLSMRNQMRLRN", + "E_JPZP RZVJV RKJLKKLJKKJKL RYZZ[Y\\X[YZY\\", + "E_ZPJP RJVZV RYJXKYLZKYJYL RKZJ[K\\L[KZK\\", + "AcNP^P R^VNV RGVHWGXFWGVGX RGNHOGPFOGNGP", + "AcVPFP RFVVV R]V\\W]X^W]V]X R]N\\O]P^O]N]P", + "E_JPZP RZVJV RPQRPTQUSTURVPUOSPQ", + "E_JPZP RZVJV RRJPIOGPERDTEUGTIRJ", + "E_JPZP RZVJV RNJOHQGSGUHVJ", + "E_JPZP RZVJV RNJRGVJ", + "E_JPZP RZVJV RNGRJVG", + "E_JPZP RZVJV RRATGOCUCPGRA", + "E_JPZP RZVJV RR?NJVJR?", + "E_JPZP RYC]C RZVJV R]?[@ZBZJ RM?MJKJIIHGHEICKBMB RQFVFVCUBRBQCQIRJUJ", + "E_JPZP RZVJV RMBMJ RMCNBQBRCRJ RRCSBVBWCWJ", + "E_JPZP RZVJV RRHSIRJQIRHRJ RN@P?S?U@VBUDSE", + "E_JPZP RTMPY RZVJV", # /* U+2260 EQUAL_SLASH */ + "E_JYZY RJSZS RJMZM", + "E_JYZY RJSZS RJMZM RXGL_", + "E_J\\Z\\ RJPZP RJJZJ RZVJV", + "E_ZZJZ RZVJPZJ", + "E_JZZZ RJVZPJJ", + "E_J]Z] RZWJW RZSJMZG", + "E_Z]J] RJWZW RJSZMJG", + "E_J]Z] RTTP` RZWJW RZSJMZG", + "E_JWZW RTTP` RZ]J] RJSZMJG", + "=gRMBSRY RbMRSbY", + "=gRMbSRY RBMRSBY", + "I[OCPDRGSITLUQUUTZS]R_PbOc RUcTbR_Q]PZOUOQPLQIRGTDUC", + "E_JXLWPVTVXWZX RJNLOPPTPXOZN RVKN[", + "E_ZMJSZY RVKN[", + "E_JMZSJY RVKN[", + "E_ZZJZ RZVJPZJ RXGL_", # /* U+2270 LESS_MINUS SLASH_OP */ + "E_JZZZ RJVZPJJ RXGL_", + "E_ZVJPZJ RJZKYNXQYS[V\\Y[ZZ", + "E_JVZPJJ RJZKYNXQYS[V\\Y[ZZ", + "E_ZVJPZJ RJZKYNXQYS[V\\Y[ZZ RXGL_", + "E_JVZPJJ RJZKYNXQYS[V\\Y[ZZ RXGL_", + "E_JSZYJ_ RZSJMZG", + "E_ZSJYZ_ RJSZMJG", + "E_JSZYJ_ RZSJMZG RXGL_", + "E_ZSJYZ_ RJSZMJG RXGL_", + "E_ZKXNVPRRJSRTVVXXZ[", + "E_JKLNNPRRZSRTNVLXJ[", + "E_JVRWVYX[Z^ RZHXKVMROJPRQVSXUZX", + "E_ZVRWNYL[J^ RJHLKNMROZPRQNSLUJX", + "E_J[KZNYQZS\\V]Y\\Z[ RZHXKVMROJPRQVSXUZX", + "E_J[KZNYQZS\\V]Y\\Z[ RJXLUNSRQZPRONMLKJH", + "E_ZKXNVPRRJSRTVVXXZ[ RVKN[", # /* U+2280 PRECEDES SLASH_REL */ + "E_JKLNNPRRZSRTNVLXJ[ RVKN[", + "E_ZMNMLNKOJQJUKWLXNYZY", + "E_JMVMXNYOZQZUYWXXVYJY", + "E_ZMNMLNKOJQJUKWLXNYZY RVKN[", + "E_JMVMXNYOZQZUYWXXVYJY RVKN[", + "E_J\\Z\\ RZJNJLKKLJNJRKTLUNVZV", + "E_Z\\J\\ RJJVJXKYLZNZRYTXUVVJV", + "E_J\\Z\\ RZJNJLKKLJNJRKTLUNVZV RXGL_", + "E_Z\\J\\ RJJVJXKYLZNZRYTXUVVJV RXGL_", + "E_J\\Z\\ RZJNJLKKLJNJRKTLUNVZV RSYQ_", + "E_Z\\J\\ RJJVJXKYLZNZRYTXUVVJV RSYQ_", + "E_JKJULYP[T[XYZUZK ROSUS RSUUSSQ", + "E_JKJULYP[T[XYZUZK RRRQSRTSSRRRT", + "E_JKJULYP[T[XYZUZK RLSXS RRMRY", + "E_ZYJYJMZM", + "E_JYZYZMJM", # /* U+2290 !SQIMAGE */ + "E_Z\\J\\ RZVJVJJZJ", + "E_J\\Z\\ RJVZVZJJJ", + "E_Z[ZKJKJ[", + "E_JKJ[Z[ZK", + "E_PKTKXMZQZUXYT[P[LYJUJQLMPK RLSXS RRMRY", + "E_PKTKXMZQZUXYT[P[LYJUJQLMPK RLSXS", + "E_PKTKXMZQZUXYT[P[LYJUJQLMPK RMNWX RWNMX", + "E_PKTKXMZQZUXYT[P[LYJUJQLMPK RWFM^", + "E_PKTKXMZQZUXYT[P[LYJUJQLMPK RRRQSRTSSRRRT", + "E_PKTKXMZQZUXYT[P[LYJUJQLMPK RPQRPTQUSTURVPUOSPQ", + "E_PKTKXMZQZUXYT[P[LYJUJQLMPK RRNRS RMQRSWQ ROWRSUW", + "E_PKTKXMZQZUXYT[P[LYJUJQLMPK RLUXU RLQXQ", + "E_PKTKXMZQZUXYT[P[LYJUJQLMPK RNSVS", + "E_JKZKZ[J[JK RLSXS RRMRY", + "E_JKZKZ[J[JK RLSXS", + "E_JKZKZ[J[JK RMNWX RWNMX", # /* U+22A0 SQUARE MULTIPLY_SMALL */ + "E_JKZKZ[J[JK RRRQSRTSSRRRT", + "E_J[JK RJSZS", + "E_Z[ZK RZSJS", + "E_ZKJK RRKR[", + "E_J[Z[ RR[RK", + "I[NSVS RNKN[", + "I[NVVV RNPVP RNKN[", + "E_JVZV RJPZP RJKJ[", + "E_JKJ[ RPSZS RPKP[", + "E_JKJ[ ROKO[ RTKT[ RYSTS", + "E_JKJ[ RPVYV RPPYP RPKP[", + "E_J[JK RJSZS RXGL_", + "E_JVZV RJPZP RJKJ[ RXGL_", + "E_JKJ[ RPSZS RPKP[ RXGL_", + "E_JKJ[ RPVYV RPPYP RPKP[ RXGL_", + "E_VKXLYNXPVQRRJSRTVUXVYXXZV[", # /* U+22B0 PRECEDESREL */ + "E_NKLLKNLPNQRRZSRTNULVKXLZN[", + "E_JSZYZMJS", + "E_ZSJYJMZS", + "E_Z[J[ RJQZWZKJQ", + "E_J[Z[ RZQJWJKZQ", + "BbXQXU RYQYU RZPZV R[Q[U R\\Q\\U RMSLQJPHQGSHUJVLUMSWSXUZV\\U]S\\QZPXQWS", + "BbLQLU RKQKU RJPJV RIQIU RHQHU RWSXQZP\\Q]S\\UZVXUWSMSLUJVHUGSHQJPLQMS", + "E_JSTSUUWVYUZSYQWPUQTS", + "E_JSNS RR[RW RRKRO RZSVS", + "I[NFVF RRFR[", + "E_J[Z[ RZKRVJK", + "E_ZKJK RJ[RPZ[", + "E_JKZK RZPR[JP", + "E_JKJ[Z[ RJOLOQQTTVYV[", + "E_Z[ZKJ[Z[", + "Bb_`REE`", # /* U+22C0 *OR_HUGE */ + "BbEFRa_F", + "Bb]`]O\\KZHWFSEQEMFJHHKGOG`", + "BbGFGWH[J^M`QaSaW`Z^\\[]W]F", + "E_RaJSRFZSRa", + "JZRRQSRTSSRRRT", + "I[RRTXOTUTPXRR", + "E_ZSJS RRXSYRZQYRXRZ RRLSMRNQMRLRN RLMXY RXMLY", + "E_JKZ[ZKJ[JK", + "E_ZKJ[JKZ[", + "E_JKZ[ZKJ[", + "E_JKZ[ RRSJ[", + "E_ZKJ[ RRSZ[", + "E_ZVJV RZPYOVNSOQQNRKQJP", + "E_JKMMOOQSR[SSUOWMZK", + "E_Z[WYUWSSRKQSOWMYJ[", + "E_ZPSPQQPSQUSVZV RZ\\Q\\N[KXJUJQKNNKQJZJ", # /* U+22D0 SUBSET_DBL */ + "E_JPQPSQTSSUQVJV RJ\\S\\V[YXZUZQYNVKSJJJ", + "E_U[UTTRRQPROTO[ R[[[RZOWLTKPKMLJOIRI[", + "E_OKORPTRUTTURUK RIKITJWMZP[T[WZZW[T[K", + "E_RKR[ RL[LSMPNOQNSNVOWPXSX[", + "E_JPZP RZVJV RODOb RUDUb", + "E_ZMJSZY RYRXSYTZSYRYT", + "E_JMZSJY RKRJSKTLSKRKT", + "5oJM:SJY RZMJSZY RjMZSjY", + "5oZMjSZY RJMZSJY R:MJS:Y", + "E_ZSJS RJWZ[J_ RZOJKZG", + "E_JSZS RZWJ[Z_ RJOZKJG", + "E_ZLJL RZPJVZ\\", + "E_JLZL RJPZVJ\\", + "E_JPROVMXKZH RZ^X[VYRWJVRUVSXQZN", + "E_ZPRONMLKJH RJ^L[NYRWZVRUNSLQJN", + "E_JPROVMXKZH RZ^X[VYRWJVRUVSXQZN RXGL_", # /* U+22E0 ~PRECEDESEQ SLASH_OP */ + "E_ZPRONMLKJH RJ^L[NYRWZVRUNSLQJN RXGL_", + "E_Z\\J\\ RZVJVJJZJ RXGL_", + "E_J\\Z\\ RJVZVZJJJ RXGL_", + "E_Z\\J\\ RZVJVJJZJ RSYQ_", + "E_J\\Z\\ RJVZVZJJJ RSYQ_", + "E_ZVJPZJ RJZKYNXQYS[V\\Y[ZZ RSWQ]", + "E_JVZPJJ RJZKYNXQYS[V\\Y[ZZ RSWQ]", + "E_J[KZNYQZS\\V]Y\\Z[ RZHXKVMROJPRQVSXUZX RSXQ^", + "E_J[KZNYQZS\\V]Y\\Z[ RJXLUNSRQZPRONMLKJH RSXQ^", + "E_JSZYZMJS RXGL_", + "E_ZSJYJMZS RXGL_", + "E_Z[J[ RJQZWZKJQ RXGL_", + "E_J[Z[ RZQJWJKZQ RXGL_", + "CaR\\S]R^Q]R\\R^ RRRSSRTQSRRRT RRHSIRJQIRHRJ", + "CaHRISHTGSHRHT RRRSSRTQSRRRT R\\R]S\\T[S\\R\\T", + "Ca\\H[I\\J]I\\H\\J RRRQSRTSSRRRT RH\\G]H^I]H\\H^", # /* U+22F0 !ELLIPSIS_DIAG */ + "CaHHIIHJGIHHHJ RRRSSRTQSRRRT R\\\\]]\\^[]\\\\\\^", + ">`BQ\\Q R\\GOGKIIKGOGSIWKYO[\\[", + ">`GQ\\Q R\\M\\U R\\GOGKIIKGOGSIWKYO[\\[", + "E_JSZS RZPZV RZZPZMYKWJTJRKOMMPLZL", + "C`\\QGQ R\\GOGKIIKGOGSIWKYO[\\[ RR@QARBSAR@RB", + "C`GA\\A R\\QGQ R\\[O[KYIWGSGOIKKIOG\\G", + "E_JSZS RZGJG RZLPLMMKOJRJTKWMYPZZZ", + "C`G`\\` R\\PGP R\\FOFKHIJGNGRIVKXOZ\\Z", + "C`HT\\T RHN\\N R\\GOGKIIKGOGSIWKYO[\\[", + "DfbQHQ RHGUGYI[K]O]S[WYYU[H[", + "Df]QHQ RHMHU RHGUGYI[K]O]S[WYYU[H[", + "E_ZSJS RJPJV RJZTZWYYWZTZRYOWMTLJL", + "Da]AHA RHQ]Q RH[U[YY[W]S]O[KYIUGHG", + "E_ZSJS RJGZG RJLTLWMYOZRZTYWWYTZJZ", + "C`GQ\\Q R\\GGGG[\\[", + # /* // Miscellaneous Technical (2300-23FF) */ + "E_PKTKXMZQZUXYT[P[LYJUJQLMPK RZKJ[", # /* U+2300 CIRCLE SLASH_SYM */ + "E_JQRWROZU", + "E_J[JORGZOZ[J[", + "E_NORKVO", + "E_VWR[NW", + "E_ZKJK RJ[RPZ[", + "E_JNZN RJHZH RJ[RSZ[", + "H\\RDSETGSIRJQLRNSOTQSSRTQVRXSYT[S]R^Q`Rb", + "KYQbQDVD", + "KYSbSDND", + "KYQDQbVb", + "KYSDSbNb", + "E_RWR[ RVSZS", + "E_RWR[ RNSJS", + "E_RORK RVSZS", + "E_RORK RNSJS", + "E_ZQJQJV", # /* U+2310 !NOT */ + "D`[JZLYPYVZZ[\\Y[UZOZK[I\\JZKVKPJLIJKKOLULYK[J", + "E_JSJQLMPKTKXMZQZS", + "E_JSJQLMPKTKXMZQZS RJSZS", + "E_JMLLPKTKXLZMR[JM", + "E_PUJ[ RTKWLYNZQYTWVTWQVOTNQONQLTK", + "E_JSZS RR[RK RVRUPSOQOOPNRNTOVQWSWUVVTVR", + "E_JWZW RJOZO RNKN[ RVKV[", + "E_LPXPZO[MZKXJVKUMUYV[X\\Z[[YZWXVLVJWIYJ[L\\N[OYOMNKLJJKIMJOLP", + "E_ZUJUJP", + "E_RORSUS RPKTKXMZQZUXYT[P[LYJUJQLMPK", + "E_M[RVW[ RN[RWV[ RP[RYT[ RS[RZQ[ RU[RXO[ RYMRPKMROYM RJFZFZKYMKTJVJ[Z[ZVYTKMJJJF", + "JZVFNFNM", + "JZNFVFVM", + "JZV[N[NT", + "JZN[V[VT", + "H\\RbRMSITGVFXGYI", # /* U+2320 INTEGRAL_TOP */ + "H\\RDRYQ]P_N`L_K]", + "E_JUKTMSRRWSYTZU", + "E_ZQYRWSRTMSKRJQ", + "E_LKHK RXK\\K RNORKVO", + "@dXK^K RFKLKX[^[", + "AfJKZ[ RZKJ[ RFKZKbSZ[F[FK", + "AcJKZ[ RZKJ[ RFK^K^[F[FK", + "9k>VfV R>LfL RCQCL RD[DV REVEQ RFLFG RHQHL RJVJQ RK[KV RKLKG RMQML ROVOQ RPLPG RRQRL RTVTQ RULUG RWQWL RYVYQ RZ[ZV RZLZG R\\Q\\L R^V^Q R_L_G R`[`V R>QaQaL R>[>GfGf[>[", + "KYUcOSUC", + "KYOcUSOC", + ">cZKJ[ RJKZ[ R^KJKBSJ[^[^K", + "AcKOKW RR[YW RRKYO RRE^L^ZRaFZFLRE", + "H\\PNKX RYNTX RVRUPSOQOOPNRNTOVQWSWUVVTVR", + "E_N[J[JW RZSRSJ[ RVRUPSOQOOPNRNTOVQWSWUVVTVR", + "E_JSZS RNYVY RVMNM", + "E_RPRKNN RZPZKVN RRKJ[R[ZK", # /* U+2330 TOTAL_RUNOUT */ + "H\\LS[S RRMRY RXP[SXV RVRUPSOQOOPNRNTOVQWSWUVVTVR", + "E_ZSJ\\JJZS RJSZS", + "E_J[JRZ[J[", + "E_JWJ[Z[ZW", + "E_VWR[NW", + "D`JaZa RJFZF RRFRa", + "D`MFWFWaMaMF", + "D`IF[F[aIaIF RJPZP RZVJV", + "D`IF[F[aIaIF RZSJS RRXSYRZQYRXRZ RRLSMRNQMRLRN", + "D`IF[F[aIaIF RRJ[SR\\ISRJ", + "D`IF[F[aIaIF RPQRPTQUSTURVPUOSPQ", + "D`IF[F[aIaIF RPKTKXMZQZUXYT[P[LYJUJQLMPK", + "E_PKTKXMZQZUXYT[P[LYJUJQLMPK RRbRD", + "E_PKTKXMZQZUXYT[P[LYJUJQLMPK RPQRPTQUSTURVPUOSPQ", + "E_JSZS RZKJ[", + "E_JSZS RJKZ[", # /* U+2340 MINUS !SLASH_SYM */ + "D`IaIF[F[aIa[F", + "D`[a[FIFIa[aIF", + "D`IF[F[aIaIF RZMJSZY", + "D`IF[F[aIaIF RJMZSJY", + "E_ZSJS RNWJSNO RR[RK", + "E_JSZS RVWZSVO RR[RK", + "D`IF[F[aIaIF RZSJS RNWJSNO", + "D`IF[F[aIaIF RJSZS RVWZSVO", + "E_PKTKXMZQZUXYT[P[LYJUJQLMPK RLGX_", + "E_J[Z[ RR[RK RZaJa", + "E_RKX[L[RK RRbRD", + "D`IF[F[aIaIF RIKR[[K", + "D`IF[F[aIaIF RRKX[L[RK", + "E_ZKJK RRKR[ RVRUPSOQOOPNRNTOVQWSWUVVTVR", + "E_R[RK RNORKVO RJSZS", + "D`IF[F[aIaIF RR[RK RNORKVO", # /* U+2350 RECTANGLE_V_HUGE ARROW_N */ + "E_ZKJK RRKR[ RMEWE", + "E_R[LKXKR[ RRbRD", + "D`IF[F[aIaIF R[[RKI[", + "D`IF[F[aIaIF RR[LKXKR[", + "E_J[Z[ RR[RK RPQRPTQUSTURVPUOSPQ", + "E_RKR[ RVWR[NW RJSZS", + "D`IF[F[aIaIF RRKR[ RVWR[NW", + "JZJ]Z] RSFQJ", + "E_RKX[L[RK RJ]Z]", + "E_RJ[SR\\ISRJ RJ]Z]", + "E_PQRPTQUSTURVPUOSPQ RJ]Z]", + "E_PKTKXMZQZUXYT[P[LYJUJQLMPK RJ]Z]", + "E_Z[ZQXMTKPKLMJQJ[ RPQRPTQUSTURVPUOSPQ", + "D`IF[F[aIaIF RSFQJ", + "E_PKTKXMZQZUXYT[P[LYJUJQLMPK RRPTVORURPVRP", + "D`IF[F[aIaIF RRYSZR[QZRYR[ RRNSORPQORNRP", # /* U+2360 RECTANGLE_V_HUGE COLON */ + "E_ZKJK RRKR[ RNDOENFMENDNF RVDWEVFUEVDVF", + "E_R[LKXKR[ RNFOGNHMGNFNH RVFWGVHUGVFVH", + "E_RKWZJQZQMZRK RNDOENFMENDNF RVDWEVFUEVDVF", + "E_PQRPTQUSTURVPUOSPQ RNIOJNKMJNINK RVIWJVKUJVIVK", + "E_PKTKXMZQZUXYT[P[LYJUJQLMPK RNDOENFMENDNF RVDWEVFUEVDVF", + "E_JKJULYP[T[XYZUZK RRbRD", + "E_ZMNMLNKOJQJUKWLXNYZY RRbRD", + "E_JSKRNQQRSTVUYTZS RNFOGNHMGNFNH RVFWGVHUGVFVH", + "E_JMZSJY RNFOGNHMGNFNH RVFWGVHUGVFVH", + "E_JSZS RSZS[R]Q^", + "E_R[LKXKR[ RJSKRNQQRSTVUYTZS", + "H\\QFSFUGVHWJXNXSWWVYUZS[Q[OZNYMWLSLNMJNHOGQF RJPKONNQOSQVRYQZP", + "E_JSKRNQQRSTVUYTZS RRbRD", + "MWSZS[R]Q^ RRNSORPQORNRP RJ]Z]", + "D`IF[F[aIaIF RJPZP RTMPY RZVJV", + "D`IF[F[aIaIF RQYRZQ[PZQYQ[ RMGOFTFVGWIWKVMUNSORPQRQS", # /* U+2370 RECTANGLE_V_HUGE QUESTION */ + "E_IKR[[K RJSKRNQQRSTVUYTZS", + "E_[[RKI[ RJSKRNQQRSTVUYTZS", + "MXRMRXSZU[", + "H\\MbMQNOONQMTMVNWOXQXWWYVZT[Q[OZMX", + "G]RTRX RMMLNKPKXLZN[O[QZRXSZU[V[XZYXYPXNWM", + "H]YMVWUYTZR[P[NZMYLVLRMONNPMRMTNUOVQWXXZZ[ RJ]Z]", + "HZLTST RVZT[P[NZMYLWLQMONNPMTMVN RJ]Z]", + "MXRMRXSZU[ RJ]Z]", + "G]RTRX RMMLNKPKXLZN[O[QZRXSZU[V[XZYXYPXNWM RJ]Z]", + "H]YMVWUYTZR[P[NZMYLVLRMONNPMRMTNUOVQWXXZZ[", + "IbMTQSS[bB RXL`L", + "A_J_F_F[ RJKJ[Z[ RF_OVEQOG", + "E_JWNWN[V[VWZW", + "E_NSN[J[ RVSV[Z[ RJSJQLMPKTKXMZQZSJS", + "E_PQPU RQUQQ RRPRV RSUSQ RTQTU RPTRVTT RPRRPTR RPQRPTQUSTURVPUOSPQ RRbRD", + "E_VWR[NW ROEQDSDUEVGVN RVMTNQNOMNKOIQHVH", # /* U+2380 *ARROWHEAD_N ^A_TINY */ + "BbF[^[ RGLIKKKMLNNNU RUSVTUUTTUSUU R]S^T]U\\T]S]U RNTLUIUGTFRGPIONO", + "BbF[N[ RV[^[ RGLIKKKMLNNNU RWLYK[K]L^N^U RNTLUIUGTFRGPIONO R^T\\UYUWTVRWPYO^O", + "BbHPDP RJUFX RJKFH R^XZU R^HZK R`P\\P RTTRUPUNTMRMQNNPLRKVKTU", + "=_RKR[B[BKRK RPKTKXMZQZUXYT[P[LYJUJQLMPK", + "E_JKZKZ[J[JK RRbRD", + "C_ESUS RQWUSQO RJWJ[Z[ZKJKJO", + "@dX[^[ RZO^KZG RF[L[XK^K", + "E_KOYW RR[RK RYOKW RRMONMPLSMVOXRYUXWVXSWPUNRM", + "E_JSOSR[USZS RPKTKXMZQZUXYT[P[LYJUJQLMPK", + "E_R[KOYOR[ RPKTKXMZQZUXYT[P[LYJUJQLMPK", + "E_STJK RJOJKNK RSKTKXMZQZUXYT[P[LYJUJT", + "D`KNKROR RYRWPTOPOMPKR RNXMVKUIVHXIZK[MZNX RVXWZY[[Z\\X[VYUWVVX", + "E_I[N[NKVKV[[[", + "E_I[V[VK RN[NK[K", + "E_JKZK RJSRKZSR[JS", + "E_Z[J[ RZSR[JSRKZS", # /* U+2390 *OPEN_H */ + "E_JKZK RJSRKZSR[JS RJSZS", + "E_Z[J[ RZSR[JSRKZS RJSZS", + "E_JVLV RJPZP RQVSV RXVZV", + "BbL[FQLGXG^QX[L[", + "D`IF[F[aIaIF", + "MWTFQL", + "AcZSJS RRORK RR[RW RNOJSNW R^[F[FK^K^[", + "AcJSZS RRWR[ RRKRO RVWZSVO RFK^K^[F[FK", + "BbLHQHQC RLSLHQCXCXSLS RLKJKHLGNGXHZJ[Z[\\Z]X]N\\LZKXK", + "BbROJW RZORW RGXGNHLJKZK\\L]N]X\\ZZ[J[HZGX", + "H\\XDVGUITLSQR[Rb", + "H\\RbRD", + "H\\XbV_U]TZSURKRD", + "H\\LDNGOIPLQQR[Rb", + "H\\RbRD", + "H\\LbN_O]PZQURKRD", # /* U+23A0 *PAREN_TOP */ + "H\\XGRGRb", + "H\\RbRD", + "H\\X_R_RD", + "H\\LGRGRb", + "H\\RbRD", + "H\\L_R_RD", + "H\\XDTHSJRNRb", + "H\\RDRIQMPOLSPWQYR]Rb", + "H\\XbT^S\\RXRD", + "H\\RbRD", + "H\\LDPHQJRNRb", + "H\\RDRISMTOXSTWSYR]Rb", + "H\\LbP^Q\\RXRD", + "H\\RbRD", + "H\\HS\\S", + "H\\WDSHRKR[Q^Mb", # /* U+23B0 MOUSTACHE */ + "H\\MDQHRKR[S^Wb", + "E_VbIF\\F", + "E_VDI`\\`", + ">fC^CYaYa^", + ">fCHCMaMaH", + ">fC^CYaYa^ RaHaMCMCH", + "IbMTQSS[bB", + "H\\RbRD", + "H\\RbRD", + "H\\HG\\G", + "H\\HM\\M", + "H\\\\YHY", + "H\\\\_H_", + "E_UFOFO[", + "E_U[O[OF", + "E_PKTKXMZQZUXYT[P[LYJUJQLMPK RRbRD", # /* U+23C0 CIRCLE LINE_V */ + "E_PKTKXMZQZUXYT[P[LYJUJQLMPK RZEJE RRERa", + "E_PKTKXMZQZUXYT[P[LYJUJQLMPK RJaZa RRaRE", + "E_RK[[I[RK RRbRD", + "E_RK[[I[RK RZEJE RRERa", + "E_RK[[I[RK RJaZa RRaRE", + "E_JSKRNQQRSTVUYTZS RRbRD", + "E_JSKRNQQRSTVUYTZS RZEJE RRERa", + "E_JSKRNQQRSTVUYTZS RJaZa RRaRE", + "E_JaZa RRaRE", + "E_ZEJE RRERa", + "E_OFUFU[", + "E_O[U[UF", + "D`TFQL RMKJKJ[Z[ZKWK", + "E_IWN\\NZZZZKTKTTNTNRIW", + "E_Z[J[ RJVRKZV", + "H\\RbRD", # /* U+23D0 LINE_V */ + "H\\NQNROTQUSUUTVRVQ", + "H\\NQNROTQUSUUTVRVQ RMKWK", + "H\\NQNROTQUSUUTVRVQ RW[M[", + "CaGQGRHTJULUNTOROQ RUQURVTXUZU\\T]R]Q RGK]K", + "CaGQGRHTJULUNTOROQ RUQURVTXUZU\\T]R]Q R][G[", + "E_JQJRKTMUOUQTRRRQ RRRSTUUWUYTZRZQ", + "E_JUZUZP", + "E_JPJUZUZP", + "E_RPRU RJPJUZUZP", + "E_HO\\O RLUXU RRFRO RT[P[", + "E_HS\\S RJMZMZYJYJM", + ">fB]C\\FZHYKXPWTWYX\\Y^Za\\b]", + ">fbIaJ^L\\MYNTOPOKNHMFLCJBI", + ">fB^B]C[EZOZQYRWSYUZ_Za[b]b^", + ">fbHbIaK_LULSMROQMOLELCKBIBH", + ">fB^FY^Yb^", # /* U+23E0 TOR_BRACKET_OVER */ + ">fbH^MFMBH", + "E_I[NKVK[[I[", + "AcRE^L^ZRaFZFLRE RQLSLVMXOYRYTXWVYSZQZNYLWKTKRLONMQL", + "E_JSZS", + "E_HXMN\\NWXHX", + "E_JSZS RJSKNLLNKPLQNSXTZV[XZYXZS", + "E_LMXY RXMLY RPQRPTQUSTURVPUOSPQ", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+23F0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // Control Pictures (2400-243F) */ + "F^K[KFYFY[K[", # /* U+2400 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2410 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2420 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2430 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // Optical Character Recognition (2440-245F) */ + "F^K[KFYFY[K[", # /* U+2440 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2450 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // Enclosed Alphanumerics (2460-24FF) */ + "F^K[KFYFY[K[", # /* U+2460 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2470 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2480 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2490 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+24A0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+24B0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+24C0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+24D0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+24E0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+24F0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // Box Drawing (2500-257F) */ + "F^K[KFYFY[K[", # /* U+2500 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2510 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2520 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2530 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2540 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2550 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2560 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2570 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // Block Elements (2580-259F) */ + "F^K[KFYFY[K[", # /* U+2580 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2590 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // Geometric Shapes (25A0-25FF) */ + "E_KKK[ RL[LK RMKM[ RN[NK ROKO[ RP[PK RQKQ[ RR[RK RSKS[ RT[TK RUKU[ RV[VK RWKW[ RX[XK RYKY[ RJKZKZ[J[JK", # /* U+25A0 SQUARE_BLACK */ + "E_JKZKZ[J[JK", + "E_KLMKWKYLZNZXYZW[M[KZJXJNKL", + "E_JKZKZ[J[JK RPPPV RQVQP RRPRV RSVSP RTPTV ROVOPUPUVOV", + "E_JWZW RJSZS RJOZO RJKZKZ[J[JK", + "E_NKN[ RRKR[ RVKV[ RJKZKZ[J[JK", + "E_JWZW RJSZS RJOZO RNKN[ RRKR[ RVKV[ RJKZKZ[J[JK", + "E_JKZ[ RN[JW RT[JQ RZUPK RZOVK RJKZKZ[J[JK", + "E_J[ZK RJUTK RJONK RP[ZQ RV[ZW RJKZKZ[J[JK", + "E_J[ZK RJUTK RJONK RJKZ[ RN[JW RP[ZQ RT[JQ RV[ZW RZUPK RZOVK RJKZKZ[J[JK", + "E_PPPV RQVQP RRPRV RSVSP RTPTV ROVOPUPUVOV", + "E_OVOPUPUVOV", + "E_JXTN RJWSN RJVRN RJUQN RJTPN RJSON RJRNN RJQMN RJPLN RJOKN RKXUN RLXVN RMXWN RNXXN ROXYN RPXZN RQXZO RRXZP RSXZQ RTXZR RUXZS RVXZT RWXZU RXXZV RYXZW RJNZNZXJXJN", + "E_JNZNZXJXJN", + "E_M[WQ RMZWP RMYWO RMXWN RMWWM RMVWL RMUWK RMTVK RMSUK RMRTK RMQSK RMPRK RMOQK RMNPK RMMOK RMLNK RN[WR RO[WS RP[WT RQ[WU RR[WV RS[WW RT[WX RU[WY RV[WZ RM[MKWKW[M[", + "E_M[MKWKW[M[", + "E_NNLP RONKR RPNJT RQNIV RRNHX RSNIX RTNJX RUNKX RVNLX RWNMX RXVVX RXNNX RYTUX RYNOX RZRTX RZNPX R[PSX R[NQX R\\NRX RHXMN\\NWXHX", # /* U+25B0 PARALLELOGRAM_BLACK */ + "E_HXMN\\NWXHX", + "E_JZJ[ RKXK[ RLVL[ RMTM[ RNSN[ ROQO[ RPOP[ RQMQ[ RRKR[ RSMS[ RTOT[ RUQU[ RVSV[ RWTW[ RXVX[ RYXY[ RZ[RLJ[ RZZZ[ RRK[[I[RK", + "E_RK[[I[RK", + "E_OUOV RPSPV RQQQV RRORV RSQSV RTSTV RUUUV ROVRPUV RROVVNVRO", + "E_ROVVNVRO", + "E_KKK[ RLLLZ RMLMZ RNMNY ROMOY RPNPX RQNQX RRORW RSPSV RTPTV RUQUU RVQVU RWSXS RWRWT RJKYSJ[ RZSJ\\JJZS", + "E_ZSJ\\JJZS", + "E_PPPV RQQQU RRQRU RSSUS RSRST ROPUSOV RVSOWOOVS", + "E_VSOWOOVS", + "E_KNKX RLNLX RMOMW RNONW ROOOW RPPPV RQPQV RRPRV RSQSU RTQTU RURUT RVRVT RWRWT RXSWS RJNYSJX RZSJYJMZS", + "E_ZSJYJMZS", + "E_ZLZK RYNYK RXPXK RWRWK RVSVK RUUUK RTWTK RSYSK RR[RK RQYQK RPWPK ROUOK RNSNK RMRMK RLPLK RKNKK RJKRZZK RJLJK RR[IK[KR[", + "E_R[IK[KR[", + "E_UQUP RTSTP RSUSP RRWRP RQUQP RPSPP ROQOP RUPRVOP RRWNPVPRW", + "E_RWNPVPRW", + "E_Y[YK RXZXL RWZWL RVYVM RUYUM RTXTN RSXSN RRWRO RQVQP RPVPP ROUOQ RNUNQ RMSLS RMTMR RZ[KSZK RJSZJZ\\JS", # /* U+25C0 *TRIANGLE_E_BLACK */ + "E_JSZJZ\\JS", + "E_TVTP RSUSQ RRURQ RQSOS RQTQR RUVOSUP RNSUOUWNS", + "E_NSUOUWNS", + "E_YXYN RXXXN RWWWO RVWVO RUWUO RTVTP RSVSP RRVRP RQUQQ RPUPQ ROTOR RNTNR RMTMR RLSMS RZXKSZN RJSZMZYJS", + "E_JSZMZYJS", + "E_JRJT RKUKQ RLPLV RMWMO RNNNX ROYOM RPLPZ RQ[QK RRJR\\ RS[SK RTLTZ RUYUM RVNVX RWWWO RXPXV RYUYQ RZRZT RRJ[SR\\ISRJ", + "E_RJ[SR\\ISRJ", + "E_RJ[SR\\ISRJ RPRPT RQUQQ RRPRV RSUSQ RTRTT RRPUSRVOSRP", + "E_PKTKXMZQZUXYT[P[LYJUJQLMPK RPQPU RQUQQ RRPRV RSUSQ RTQTU RPTRVTT RPRRPTR RPQRPTQUSTURVPUOSPQ", + "E_RaJSRFZSRa", + "E_PKTKXMZQZUXYT[P[LYJUJQLMPK", + "E_JQKO RKWJU RNLPK RP[NZ RTKVL RVZT[ RYOZQ RZUYW", + "E_NLNZ RRKR[ RVLVZ RPKTKXMZQZUXYT[P[LYJUJQLMPK", + "E_PKTKXMZQZUXYT[P[LYJUJQLMPK RPQRPTQUSTURVPUOSPQ", + "E_KOKW RLXP[ RLNPK RLMLY RMYMM RNLNZ ROZOL RPKP[ RQ[QK RRKR[ RS[SK RT[XX RTKT[ RTKXN RUZUL RVLVZ RWYWM RXMXY RYWYO RPKTKXMZQZUXYT[P[LYJUJQLMPK", + "E_PKTKXMZQZUXYT[P[LYJUJQLMPK RKOKW RLYLM RMMMY RNZNL ROLOZ RP[LX RP[PK RLN RQKQ[ RR[P[LYJUJQLMPKRKR[", # /* U+25D0 CIRCLE CIRCLE_LEFTHALF_BLACK */ + "E_PKTKXMZQZUXYT[P[LYJUJQLMPK RYWYO RXMXY RWYWM RVLVZ RUZUL RTKXN RTKT[ RXX RS[SK RRKTKXMZQZUXYT[R[RK", + "E_PKTKXMZQZUXYT[P[LYJUJQLMPK RKOKS RLMLS RMSMM RNLNS ROSOL RPKLN RPKPS RQKQS RRKRS RSKSS RTSTK RXN RULUS RVSVL RWMWS RXMXS RYOYS RJSJQLMPKTKXMZQZSJS", + "E_PKTKXMZQZUXYT[P[LYJUJQLMPK RYWYS RXYXS RWSWY RVZVS RUSUZ RT[XX RT[TS RS[SS RR[RS RQ[QS RPSP[ RLX ROZOS RNSNZ RMYMS RLYLS RKWKS RZSZUXYT[P[LYJUJSZS", + "E_SSSK RTKTS RTKXN RUSUL RVLVS RWSWM RXMXS RYSYO RZSRSRK RPKTKXMZQZUXYT[P[LYJUJQLMPK", + "E_QSQ[ RP[PS RP[LX ROSOZ RNZNS RMSMY RLYLS RKSKW RJSRSR[ RT[P[LYJUJQLMPKTKXMZQZUXYT[ RYWYO RXMXY RWYWM RVLVZ RUZUL RTKXN RTKT[ RXX RS[SK RRKTKXMZQZUXYT[R[RK", + "E_KOKW RLYLM RMMMY RNZNL ROLOZ RP[LX RP[PK RLN RQKQ[ RR[P[LYJUJQLMPKRKR[", + "E_YWYO RXMXY RWYWM RVLVZ RUZUL RTKXN RTKT[ RXX RS[SK RRKTKXMZQZUXYT[R[RK", + "E_FDFb RGbGD RHDHb RIbID RJDJb RKbKD RLbLW RLDLO RMXMb RMNMD RNbNY RNDNM ROZOb ROLOD RPbPZ RPDPL RQZQb RQLQD RRbRZ RRDRL RSZSb RSLSD RTbTZ RTDTL RUZUb RULUD RVbVY RVDVM RWXWb RWNWD RXbXW RXDXO RYbYD RZDZb R[b[D R\\D\\b R]b]D R^D^b R_bEbED_D_b RKTKRLONMQLSLVMXOYRYTXWVYSZQZNYLWKT", + "E_FRFD RGNIJ RGDGN RHLHD RIDIK RJJJD RJJMG RKDKI RLHLD RMHQF RMDMH RNGND ROPOS RODOG RPSPP RPGPD RQPQS RQDQG RRSRO RRGRD RSPSS RSFWH RSDSG RTSTP RTGTD RUPUS RUDUG RVGVD RWGZJ RWDWH RXHXD RYDYI RZJZD R[J]N R[D[K R\\L\\D R]D]N R^R^D ROQROUQ RNSOPROUPVSNS RFSFRGNIKJJMHQGSGWHZJ[K]N^R^S_S_DEDESFS R^T^b R]X[\\ R]b]X R\\Z\\b R[b[[ RZ\\Zb RZ\\W_ RYbY] RX^Xb RW^S` RWbW^ RV_Vb RUVUS RUbU_ RTSTV RT_Tb RSVSS RSbS_ RRSRW RR_Rb RQVQS RQ`M^ RQbQ_ RPSPV RP_Pb ROVOS RObO_ RN_Nb RM_J\\ RMbM^ RL^Lb RKbK] RJ\\Jb RI\\GX RIbI[ RHZHb RGbGX RFTFb RUURWOU RVSUVRWOVNSVS R^S^T]X[[Z\\W^S_Q_M^J\\I[GXFTFSESEb_b_S^S", + "E_FRFD RGNIJ RGDGN RHLHD RIDIK RJJJD RJJMG RKDKI RLHLD RMHQF RMDMH RNGND ROPOS RODOG RPSPP RPGPD RQPQS RQDQG RRSRO RRGRD RSPSS RSFWH RSDSG RTSTP RTGTD RUPUS RUDUG RVGVD RWGZJ RWDWH RXHXD RYDYI RZJZD R[J]N R[D[K R\\L\\D R]D]N R^R^D ROQROUQ RNSOPROUPVSNS RFSFRGNIKJJMHQGSGWHZJ[K]N^R^S_S_DEDESFS", + "E_^T^b R]X[\\ R]b]X R\\Z\\b R[b[[ RZ\\Zb RZ\\W_ RYbY] RX^Xb RW^S` RWbW^ RV_Vb RUVUS RUbU_ RTSTV RT_Tb RSVSS RSbS_ RRSRW RR_Rb RQVQS RQ`M^ RQbQ_ RPSPV RP_Pb ROVOS RObO_ RN_Nb RM_J\\ RMbM^ RL^Lb RKbK] RJ\\Jb RI\\GX RIbI[ RHZHb RGbGX RFTFb RUURWOU RVSUVRWOVNSVS R^S^T]X[[Z\\W^S_Q_M^J\\I[GXFTFSESEb_b_S^S", + "E_JSJQLMPKRK", + "E_ZSZQXMTKRK", + "E_ZSZUXYT[R[", + "E_JSJULYP[R[", + "E_JSJQLMPKTKXMZQZS", # /* U+25E0 CIRCLE_TOPHALF */ + "E_ZSZUXYT[P[LYJUJS", + "E_KZK[ RLYL[ RMXM[ RNWN[ ROVO[ RPUP[ RQTQ[ RRSR[ RSRS[ RTQT[ RUPU[ RVOV[ RWNW[ RXMX[ RYLY[ RZ[ZKJ[Z[", + "E_YZY[ RXYX[ RWXW[ RVWV[ RUVU[ RTUT[ RSTS[ RRSR[ RQRQ[ RPQP[ ROPO[ RNON[ RMNM[ RLML[ RKLK[ RJ[JKZ[J[", + "E_YLYK RXMXK RWNWK RVOVK RUPUK RTQTK RSRSK RRSRK RQTQK RPUPK ROVOK RNWNK RMXMK RLYLK RKZKK RJKJ[ZKJK", + "E_KLKK RLMLK RMNMK RNONK ROPOK RPQPK RQRQK RRSRK RSTSK RTUTK RUVUK RVWVK RWXWK RXYXK RYZYK RZKZ[JKZK", + "E_PQRPTQUSTURVPUOSPQ", + "E_JKZKZ[J[JK RK[KK RLKL[ RM[MK RNKN[ RO[OK RPKP[ RQ[QK RJ[JKRKR[J[", + "E_JKZKZ[J[JK RYKY[ RX[XK RWKW[ RV[VK RUKU[ RT[TK RSKS[ RZKZ[R[RKZK", + "E_JKZKZ[J[JK RYLYK RXMXK RWNWK RVOVK RUPUK RTQTK RSRSK RRSRK RQTQK RPUPK ROVOK RNWNK RMXMK RLYLK RKZKK RJKJ[ZKJK", + "E_JKZKZ[J[JK RKZK[ RLYL[ RMXM[ RNWN[ ROVO[ RPUP[ RQTQ[ RRSR[ RSRS[ RTQT[ RUPU[ RVOV[ RWNW[ RXMX[ RYLY[ RZ[ZKJ[Z[", + "E_JKZKZ[J[JK RR[RK", + "E_RK[[I[RK RRUQVRWSVRURW", + "E_J[RL RJZJ[ RKXK[ RLVL[ RMTM[ RNSN[ ROQO[ RPOP[ RQMQ[ RRKR[ RRK[[I[RK", + "E_Z[RL RZZZ[ RYXY[ RXVX[ RWTW[ RVSV[ RUQU[ RTOT[ RSMS[ RRKR[ RRKI[[[RK", + "C`OFTFXHZJ\\N\\SZWXYT[O[KYIWGSGNIJKHOF", + "E_JKZKZ[J[JK RRKRSJS", # /* U+25F0 SQUARE !QUADRANT */ + "E_JKZKZ[J[JK RR[RSJS", + "E_JKZKZ[J[JK RR[RSZS", + "E_JKZKZ[J[JK RRKRSZS", + "E_PKTKXMZQZUXYT[P[LYJUJQLMPK RRKRSJS", + "E_PKTKXMZQZUXYT[P[LYJUJQLMPK RR[RSJS", + "E_PKTKXMZQZUXYT[P[LYJUJQLMPK RR[RSZS", + "E_PKTKXMZQZUXYT[P[LYJUJQLMPK RRKRSZS", + "E_JKJ[ZKJK", + "E_ZKZ[JKZK", + "E_J[JKZ[J[", + "E_JKZKZ[J[JK", + "E_KKK[ RL[LK RMKM[ RN[NK ROKO[ RP[PK RQKQ[ RR[RK RSKS[ RT[TK RUKU[ RV[VK RWKW[ RX[XK RYKY[ RJKZKZ[J[JK", + "E_OVOPUPUVOV", + "E_PPPV RQVQP RRPRV RSVSP RTPTV ROVOPUPUVOV", + "E_Z[ZKJ[Z[", + # /* // Miscellaneous Symbols (2600-26FF) */ + "F^K[KFYFY[K[", # /* U+2600 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2610 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2620 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2630 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2640 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2650 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2660 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2670 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2680 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2690 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+26A0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+26B0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+26C0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+26D0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+26E0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+26F0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // Dingbats (2700-27BF) */ + "F^K[KFYFY[K[", # /* U+2700 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2710 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2720 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2730 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2740 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2750 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2760 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2770 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2780 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2790 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+27A0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+27B0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // Miscellaneous Mathematical Symbols A (27C0-27EF) */ + "F^K[KFYFY[K[", # /* U+27C0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+27D0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+27E0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // Supplemental Arrows A (27F0-27FF) */ + "F^K[KFYFY[K[", # /* U+27F0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // Braille Patterns (2800-28FF) */ + "F^K[KFYFY[K[", # /* U+2800 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2810 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2820 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2830 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2840 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2850 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2860 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2870 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2880 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2890 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+28A0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+28B0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+28C0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+28D0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+28E0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+28F0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // Supplemental Arrows B (2900-297F) */ + "F^K[KFYFY[K[", # /* U+2900 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2910 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2920 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2930 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2940 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2950 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2960 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2970 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // Miscellaneous Mathematical Symbols B (2980-29FF) */ + "F^K[KFYFY[K[", # /* U+2980 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2990 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+29A0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+29B0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+29C0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+29D0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+29E0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+29F0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // Supplemental Mathematical Operators (2A00-2AFF) */ + "F^K[KFYFY[K[", # /* U+2A00 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2A10 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2A20 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2A30 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2A40 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2A50 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2A60 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2A70 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2A80 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2A90 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2AA0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2AB0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2AC0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2AD0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2AE0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2AF0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + # /* // Miscellaneous Symbols and Arrows (2B00-2BFF) */ + "F^K[KFYFY[K[", # /* U+2B00 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2B10 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2B20 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2B30 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2B40 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2B50 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2B60 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2B70 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2B80 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2B90 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2BA0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2BB0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2BC0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2BD0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2BE0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", # /* U+2BF0 */ + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", + "F^K[KFYFY[K[", +] + +# const int newstroke_font_bufsize = sizeof(newstroke_font)/sizeof(newstroke_font[0]); + +# /* --- unused glyphs --- */ +# /* RECTANGLE_V_BLACK_SMALL */ +# /* TRIANGLE_TALL_BLACK */ +# /* COMBINING */ +# /* DIAMOND_SMALL */ diff --git a/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/core/units.py b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/core/units.py new file mode 100644 index 000000000..2edd0ffd5 --- /dev/null +++ b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/core/units.py @@ -0,0 +1,192 @@ +# _*_ coding:utf-8 _*_ + +# Stolen from +# https://github.com/SchrodingersGat/KiBoM/blob/master/KiBOM/units.py + +""" + +This file contains a set of functions for matching values which may be written +in different formats e.g. +0.1uF = 100n (different suffix specified, one has missing unit) +0R1 = 0.1Ohm (Unit replaces decimal, different units) + +""" + +import re +import locale + +current_locale = locale.setlocale(locale.LC_NUMERIC) +try: + locale.setlocale(locale.LC_NUMERIC, '') +except Exception: + # sometimes setlocale with empty string doesn't work on OSX + pass +decimal_separator = locale.localeconv()['decimal_point'] +locale.setlocale(locale.LC_NUMERIC, current_locale) + +PREFIX_MICRO = [u"μ", u"µ", "u", "micro"] # first is \u03BC second is \u00B5 +PREFIX_MILLI = ["milli", "m"] +PREFIX_NANO = ["nano", "n"] +PREFIX_PICO = ["pico", "p"] +PREFIX_KILO = ["kilo", "k"] +PREFIX_MEGA = ["mega", "meg"] +PREFIX_GIGA = ["giga", "g"] + +# All prefices +PREFIX_ALL = PREFIX_PICO + PREFIX_NANO + PREFIX_MICRO + \ + PREFIX_MILLI + PREFIX_KILO + PREFIX_MEGA + PREFIX_GIGA + +# Common methods of expressing component units +UNIT_R = ["r", "ohms", "ohm", u"Ω", u"ω"] +UNIT_C = ["farad", "f"] +UNIT_L = ["henry", "h"] + +UNIT_ALL = UNIT_R + UNIT_C + UNIT_L + +VALUE_REGEX = re.compile( + "^([0-9\\.]+)(" + "|".join(PREFIX_ALL) + ")*(" + "|".join( + UNIT_ALL) + ")*(\\d*)$") + +REFERENCE_REGEX = re.compile("^(r|rv|c|l)(\\d+)$") + + +def getUnit(unit): + """ + Return a simplified version of a units string, for comparison purposes + """ + if not unit: + return None + + unit = unit.lower() + + if unit in UNIT_R: + return "R" + if unit in UNIT_C: + return "F" + if unit in UNIT_L: + return "H" + + return None + + +def getPrefix(prefix): + """ + Return the (numerical) value of a given prefix + """ + if not prefix: + return 1 + + prefix = prefix.lower() + + if prefix in PREFIX_PICO: + return 1.0e-12 + if prefix in PREFIX_NANO: + return 1.0e-9 + if prefix in PREFIX_MICRO: + return 1.0e-6 + if prefix in PREFIX_MILLI: + return 1.0e-3 + if prefix in PREFIX_KILO: + return 1.0e3 + if prefix in PREFIX_MEGA: + return 1.0e6 + if prefix in PREFIX_GIGA: + return 1.0e9 + + return 1 + + +def compMatch(component): + """ + Return a normalized value and units for a given component value string + e.g. compMatch("10R2") returns (1000, R) + e.g. compMatch("3.3mOhm") returns (0.0033, R) + """ + component = component.strip().lower() + if decimal_separator == ',': + # replace separator with dot + component = component.replace(",", ".") + else: + # remove thousands separator + component = component.replace(",", "") + + result = VALUE_REGEX.match(component) + + if not result: + return None + + if not len(result.groups()) == 4: + return None + + value, prefix, units, post = result.groups() + + # special case where units is in the middle of the string + # e.g. "0R05" for 0.05Ohm + # in this case, we will NOT have a decimal + # we will also have a trailing number + + if post and "." not in value: + try: + value = float(int(value)) + postValue = float(int(post)) / (10 ** len(post)) + value = value * 1.0 + postValue + except ValueError: + return None + + try: + val = float(value) + except ValueError: + return None + + val = "{0:.15f}".format(val * 1.0 * getPrefix(prefix)) + + return (val, getUnit(units)) + + +def componentValue(valString, reference): + # type: (str, str) -> tuple + result = compMatch(valString) + + if not result: + return valString, None # return the same string back with `None` unit + + if not len(result) == 2: # result length is incorrect + return valString, None # return the same string back with `None` unit + + if result[1] is None: + # try to infer unit from reference + match = REFERENCE_REGEX.match(reference.lower()) + if match and len(match.groups()) == 2: + prefix, _ = match.groups() + unit = None + if prefix in ['r', 'rv']: + unit = 'R' + if prefix == 'c': + unit = 'F' + if prefix == 'l': + unit = 'H' + result = (result[0], unit) + + return result # (val,unit) + + +def compareValues(c1, c2): + r1 = compMatch(c1) + r2 = compMatch(c2) + + if not r1 or not r2: + return False + + (v1, u1) = r1 + (v2, u2) = r2 + + if v1 == v2: + # values match + if u1 == u2: + return True # units match + if not u1: + return True # no units for component 1 + if not u2: + return True # no units for component 2 + + return False diff --git a/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/dialog/__init__.py b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/dialog/__init__.py new file mode 100644 index 000000000..b6c0c9e2c --- /dev/null +++ b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/dialog/__init__.py @@ -0,0 +1 @@ +from .settings_dialog import SettingsDialog, GeneralSettingsPanel diff --git a/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/dialog/bitmaps/btn-arrow-down.png b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/dialog/bitmaps/btn-arrow-down.png new file mode 100644 index 0000000000000000000000000000000000000000..1f818906fe8ec6df94edb4b935567c4230f888dc GIT binary patch literal 386 zcmV-|0e$|7P)pF8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H10S`$; zK~y-6?UAuc13?r;&szyv*;uPsDfk5|LEM0Xh#-D}7FHHv*CN>2+RT21q!6?aEG)8{ z&N59vTZI%>VeK-=vrE+337S&!%6sM>9&ZHSnCuBy_0VUMXsrwcUg3l@6;6f!QYfU^ zDJqGJbP=d{dKTo>wW$#ROjZXqAd_yaDCe9-mokjf)*&iaz}(+lGC(*Y-f9BKHN~~TKB~=8C^r=B5=VVsZN@7E$ge-xSh;0(c^-JA gXrFL#Y{ykT0mGt5f-s#d)Bpeg07*qoM6N<$f`XcvxBvhE literal 0 HcmV?d00001 diff --git a/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/dialog/bitmaps/btn-arrow-up.png b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/dialog/bitmaps/btn-arrow-up.png new file mode 100644 index 0000000000000000000000000000000000000000..bfeb9a572b1d9083406814cbd58ce000fd7bd3a8 GIT binary patch literal 382 zcmV-^0fGLBP)pF8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H10Sie) zK~y-6?b1C<15pr#;dge~#U`+Yje=qq!Nyh_6Yv9tG(4p>#l=e@#VA_S+cu2oy86ZQ}B5+QLg4{v{)D c1pZ6#0~#+t$O4a67ytkO07*qoM6N<$g2OqQUH||9 literal 0 HcmV?d00001 diff --git a/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/dialog/bitmaps/btn-minus.png b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/dialog/bitmaps/btn-minus.png new file mode 100644 index 0000000000000000000000000000000000000000..7a5034c5630db00a29290fda9494cd362f642fe7 GIT binary patch literal 137 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&I!3HFo9rG^&Db50q$YKTtzQZ8Qcszea3Q$n8 z#5JNMI6tkVJh3R1p}f3YFEcN@I61K(RWH9NefB#WDWD=TPZ!4!iK)pcFK+*z-^kU_ eDb>c~*UT_imnnqVF(MnNg2B_(&t;ucLK6Vj_a)8% literal 0 HcmV?d00001 diff --git a/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/dialog/bitmaps/btn-plus.png b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/dialog/bitmaps/btn-plus.png new file mode 100644 index 0000000000000000000000000000000000000000..669a97b0e518cf200587a72614ba5a7bce8c4fd0 GIT binary patch literal 165 zcmeAS@N?(olHy`uVBq!ia0vp^LLkh+1|-AI^@Rf|&H|6fVg?4j!ywFfJby(BP*AeO zHKHUqKdq!Zu_%?Hyu4g5GcUV1Ik6yBFTW^#_B$IXpduqr7sn8b-sF@6?7zPKcYi2u zY4j-QRLgY*p#v)%OH4WhmAg)|G@s87;Zd$hFzMzgZf203&XJefRelVpo59o7&t;uc GLK6T=*fRzI literal 0 HcmV?d00001 diff --git a/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/dialog/bitmaps/btn-question.png b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/dialog/bitmaps/btn-question.png new file mode 100644 index 0000000000000000000000000000000000000000..8c91f56baff9d2c53d0cf804f4125cb325a86c33 GIT binary patch literal 460 zcmV;-0WpF8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H10a-~z zK~yM_wUfO|LSY!if6u)dL>~|l6+wZ2gF^*^LR-)f;Z%?fMf8DPT3ee^X%rf2D{5$s zOf8&@{(&HZ*02ZyNt36cYu@Xbh;3F9Sg}Lb&8b2X zA!F-v1|ow9uOLrY(IZb4!?|T5b)GPtR_Q{6vt2vdQ zLCvzmoTIBJ>mSGzcMv%T`t6fr>cLr7!gX(@)YT+nlmG##A-cv^?4T)oUod3;+YAWX zPP2bNjn>vaKTg`^fH$Cz7~BESTYLAJ@Sow`QYOEQ$|CSUM(iD0@H!qznzur}_d@Ibe3(X-+r*0000= (3, 1, 6): + return wx.BitmapBundle(png) + else: + return png + + +class SettingsDialog(dialog_base.SettingsDialogBase): + def __init__(self, extra_data_func, extra_data_wildcard, config_save_func, + file_name_format_hint, version): + dialog_base.SettingsDialogBase.__init__(self, None) + self.panel = SettingsDialogPanel( + self, extra_data_func, extra_data_wildcard, config_save_func, + file_name_format_hint) + best_size = self.panel.BestSize + # hack for some gtk themes that incorrectly calculate best size + best_size.IncBy(dx=0, dy=30) + self.SetClientSize(best_size) + self.SetTitle('InteractiveHtmlBom %s' % version) + + # hack for new wxFormBuilder generating code incompatible with old wxPython + # noinspection PyMethodOverriding + def SetSizeHints(self, sz1, sz2): + try: + # wxPython 4 + super(SettingsDialog, self).SetSizeHints(sz1, sz2) + except TypeError: + # wxPython 3 + self.SetSizeHintsSz(sz1, sz2) + + def set_extra_data_path(self, extra_data_file): + self.panel.fields.extraDataFilePicker.Path = extra_data_file + self.panel.fields.OnExtraDataFileChanged(None) + + +# Implementing settings_dialog +class SettingsDialogPanel(dialog_base.SettingsDialogPanel): + def __init__(self, parent, extra_data_func, extra_data_wildcard, + config_save_func, file_name_format_hint): + self.config_save_func = config_save_func + dialog_base.SettingsDialogPanel.__init__(self, parent) + self.general = GeneralSettingsPanel(self.notebook, + file_name_format_hint) + self.html = HtmlSettingsPanel(self.notebook) + self.fields = FieldsPanel(self.notebook, extra_data_func, + extra_data_wildcard) + self.notebook.AddPage(self.general, "General") + self.notebook.AddPage(self.html, "Html defaults") + self.notebook.AddPage(self.fields, "Fields") + + self.save_menu = wx.Menu() + self.save_locally = self.save_menu.Append( + wx.ID_ANY, u"Locally", wx.EmptyString, wx.ITEM_NORMAL) + self.save_globally = self.save_menu.Append( + wx.ID_ANY, u"Globally", wx.EmptyString, wx.ITEM_NORMAL) + + self.Bind( + wx.EVT_MENU, self.OnSaveLocally, id=self.save_locally.GetId()) + self.Bind( + wx.EVT_MENU, self.OnSaveGlobally, id=self.save_globally.GetId()) + + def OnExit(self, event): + self.GetParent().EndModal(wx.ID_CANCEL) + + def OnGenerateBom(self, event): + self.GetParent().EndModal(wx.ID_OK) + + def finish_init(self): + self.html.OnBoardRotationSlider(None) + + def OnSave(self, event): + # type: (wx.CommandEvent) -> None + pos = wx.Point(0, event.GetEventObject().GetSize().y) + self.saveSettingsBtn.PopupMenu(self.save_menu, pos) + + def OnSaveGlobally(self, event): + self.config_save_func(self) + + def OnSaveLocally(self, event): + self.config_save_func(self, locally=True) + + +# Implementing HtmlSettingsPanelBase +class HtmlSettingsPanel(dialog_base.HtmlSettingsPanelBase): + def __init__(self, parent): + dialog_base.HtmlSettingsPanelBase.__init__(self, parent) + + # Handlers for HtmlSettingsPanelBase events. + def OnBoardRotationSlider(self, event): + degrees = self.boardRotationSlider.Value * 5 + self.rotationDegreeLabel.LabelText = u"{}\u00B0".format(degrees) + + +# Implementing GeneralSettingsPanelBase +class GeneralSettingsPanel(dialog_base.GeneralSettingsPanelBase): + + def __init__(self, parent, file_name_format_hint): + dialog_base.GeneralSettingsPanelBase.__init__(self, parent) + + self.file_name_format_hint = file_name_format_hint + + bmp_arrow_up = get_btn_bitmap("btn-arrow-up.png") + bmp_arrow_down = get_btn_bitmap("btn-arrow-down.png") + bmp_plus = get_btn_bitmap("btn-plus.png") + bmp_minus = get_btn_bitmap("btn-minus.png") + bmp_question = get_btn_bitmap("btn-question.png") + + self.m_btnSortUp.SetBitmap(bmp_arrow_up) + self.m_btnSortDown.SetBitmap(bmp_arrow_down) + self.m_btnSortAdd.SetBitmap(bmp_plus) + self.m_btnSortRemove.SetBitmap(bmp_minus) + self.m_btnNameHint.SetBitmap(bmp_question) + self.m_btnBlacklistAdd.SetBitmap(bmp_plus) + self.m_btnBlacklistRemove.SetBitmap(bmp_minus) + + self.Layout() + + # Handlers for GeneralSettingsPanelBase events. + def OnComponentSortOrderUp(self, event): + selection = self.componentSortOrderBox.Selection + if selection != wx.NOT_FOUND and selection > 0: + item = self.componentSortOrderBox.GetString(selection) + self.componentSortOrderBox.Delete(selection) + self.componentSortOrderBox.Insert(item, selection - 1) + self.componentSortOrderBox.SetSelection(selection - 1) + + def OnComponentSortOrderDown(self, event): + selection = self.componentSortOrderBox.Selection + size = self.componentSortOrderBox.Count + if selection != wx.NOT_FOUND and selection < size - 1: + item = self.componentSortOrderBox.GetString(selection) + self.componentSortOrderBox.Delete(selection) + self.componentSortOrderBox.Insert(item, selection + 1) + self.componentSortOrderBox.SetSelection(selection + 1) + + def OnComponentSortOrderAdd(self, event): + item = wx.GetTextFromUser( + "Characters other than A-Z will be ignored.", + "Add sort order item") + item = re.sub('[^A-Z]', '', item.upper()) + if item == '': + return + found = self.componentSortOrderBox.FindString(item) + if found != wx.NOT_FOUND: + self.componentSortOrderBox.SetSelection(found) + return + self.componentSortOrderBox.Append(item) + self.componentSortOrderBox.SetSelection( + self.componentSortOrderBox.Count - 1) + + def OnComponentSortOrderRemove(self, event): + selection = self.componentSortOrderBox.Selection + if selection != wx.NOT_FOUND: + item = self.componentSortOrderBox.GetString(selection) + if item == '~': + pop_error("You can not delete '~' item") + return + self.componentSortOrderBox.Delete(selection) + if self.componentSortOrderBox.Count > 0: + self.componentSortOrderBox.SetSelection(max(selection - 1, 0)) + + def OnComponentBlacklistAdd(self, event): + item = wx.GetTextFromUser( + "Characters other than A-Z 0-9 and * will be ignored.", + "Add blacklist item") + item = re.sub('[^A-Z0-9*]', '', item.upper()) + if item == '': + return + found = self.blacklistBox.FindString(item) + if found != wx.NOT_FOUND: + self.blacklistBox.SetSelection(found) + return + self.blacklistBox.Append(item) + self.blacklistBox.SetSelection(self.blacklistBox.Count - 1) + + def OnComponentBlacklistRemove(self, event): + selection = self.blacklistBox.Selection + if selection != wx.NOT_FOUND: + self.blacklistBox.Delete(selection) + if self.blacklistBox.Count > 0: + self.blacklistBox.SetSelection(max(selection - 1, 0)) + + def OnNameFormatHintClick(self, event): + wx.MessageBox(self.file_name_format_hint, 'File name format help', + style=wx.ICON_NONE | wx.OK) + + def OnSize(self, event): + # Trick the listCheckBox best size calculations + tmp = self.componentSortOrderBox.GetStrings() + self.componentSortOrderBox.SetItems([]) + self.Layout() + self.componentSortOrderBox.SetItems(tmp) + + +# Implementing FieldsPanelBase +class FieldsPanel(dialog_base.FieldsPanelBase): + NONE_STRING = '' + EMPTY_STRING = '' + FIELDS_GRID_COLUMNS = 3 + + def __init__(self, parent, extra_data_func, extra_data_wildcard): + dialog_base.FieldsPanelBase.__init__(self, parent) + self.show_fields = [] + self.group_fields = [] + + self.extra_data_func = extra_data_func + self.extra_field_data = None + + self.m_btnUp.SetBitmap(get_btn_bitmap("btn-arrow-up.png")) + self.m_btnDown.SetBitmap(get_btn_bitmap("btn-arrow-down.png")) + + self.set_file_picker_wildcard(extra_data_wildcard) + self._setFieldsList([]) + for i in range(2): + box = self.GetTextExtent(self.fieldsGrid.GetColLabelValue(i)) + if hasattr(box, "x"): + width = box.x + else: + width = box[0] + width = int(width * 1.1 + 5) + self.fieldsGrid.SetColMinimalWidth(i, width) + self.fieldsGrid.SetColSize(i, width) + + self.Layout() + + def set_file_picker_wildcard(self, extra_data_wildcard): + if extra_data_wildcard is None: + self.extraDataFilePicker.Disable() + return + + # wxFilePickerCtrl doesn't support changing wildcard at runtime + # so we have to replace it + picker_parent = self.extraDataFilePicker.GetParent() + new_picker = wx.FilePickerCtrl( + picker_parent, wx.ID_ANY, wx.EmptyString, + u"Select a file", + extra_data_wildcard, + wx.DefaultPosition, wx.DefaultSize, + (wx.FLP_DEFAULT_STYLE | wx.FLP_FILE_MUST_EXIST | wx.FLP_OPEN | + wx.FLP_SMALL | wx.FLP_USE_TEXTCTRL | wx.BORDER_SIMPLE)) + self.GetSizer().Replace(self.extraDataFilePicker, new_picker, + recursive=True) + self.extraDataFilePicker.Destroy() + self.extraDataFilePicker = new_picker + self.extraDataFilePicker.Bind( + wx.EVT_FILEPICKER_CHANGED, self.OnExtraDataFileChanged) + self.Layout() + + def _swapRows(self, a, b): + for i in range(self.FIELDS_GRID_COLUMNS): + va = self.fieldsGrid.GetCellValue(a, i) + vb = self.fieldsGrid.GetCellValue(b, i) + self.fieldsGrid.SetCellValue(a, i, vb) + self.fieldsGrid.SetCellValue(b, i, va) + + # Handlers for FieldsPanelBase events. + def OnGridCellClicked(self, event): + self.fieldsGrid.ClearSelection() + self.fieldsGrid.SelectRow(event.Row) + if event.Col < 2: + # toggle checkbox + val = self.fieldsGrid.GetCellValue(event.Row, event.Col) + val = "" if val else "1" + self.fieldsGrid.SetCellValue(event.Row, event.Col, val) + # group shouldn't be enabled without show + if event.Col == 0 and val == "": + self.fieldsGrid.SetCellValue(event.Row, 1, val) + if event.Col == 1 and val == "1": + self.fieldsGrid.SetCellValue(event.Row, 0, val) + + def OnFieldsUp(self, event): + selection = self.fieldsGrid.SelectedRows + if len(selection) == 1 and selection[0] > 0: + self._swapRows(selection[0], selection[0] - 1) + self.fieldsGrid.ClearSelection() + self.fieldsGrid.SelectRow(selection[0] - 1) + + def OnFieldsDown(self, event): + selection = self.fieldsGrid.SelectedRows + size = self.fieldsGrid.NumberRows + if len(selection) == 1 and selection[0] < size - 1: + self._swapRows(selection[0], selection[0] + 1) + self.fieldsGrid.ClearSelection() + self.fieldsGrid.SelectRow(selection[0] + 1) + + def _setFieldsList(self, fields): + if self.fieldsGrid.NumberRows: + self.fieldsGrid.DeleteRows(0, self.fieldsGrid.NumberRows) + self.fieldsGrid.AppendRows(len(fields)) + row = 0 + for f in fields: + self.fieldsGrid.SetCellValue(row, 0, "1") + self.fieldsGrid.SetCellValue(row, 1, "1") + self.fieldsGrid.SetCellRenderer( + row, 0, wx.grid.GridCellBoolRenderer()) + self.fieldsGrid.SetCellRenderer( + row, 1, wx.grid.GridCellBoolRenderer()) + self.fieldsGrid.SetCellValue(row, 2, f) + self.fieldsGrid.SetCellAlignment( + row, 2, wx.ALIGN_LEFT, wx.ALIGN_TOP) + self.fieldsGrid.SetReadOnly(row, 2) + row += 1 + + def OnExtraDataFileChanged(self, event): + extra_data_file = self.extraDataFilePicker.Path + if not os.path.isfile(extra_data_file): + return + + self.extra_field_data = None + try: + self.extra_field_data = self.extra_data_func( + extra_data_file, self.normalizeCaseCheckbox.Value) + except Exception as e: + pop_error( + "Failed to parse file %s\n\n%s" % (extra_data_file, e)) + self.extraDataFilePicker.Path = '' + + if self.extra_field_data is not None: + field_list = list(self.extra_field_data.fields) + self._setFieldsList(["Value", "Footprint"] + field_list) + self.SetCheckedFields() + field_list.append(self.NONE_STRING) + self.boardVariantFieldBox.SetItems(field_list) + self.boardVariantFieldBox.SetStringSelection(self.NONE_STRING) + self.boardVariantWhitelist.Clear() + self.boardVariantBlacklist.Clear() + self.dnpFieldBox.SetItems(field_list) + self.dnpFieldBox.SetStringSelection(self.NONE_STRING) + + def OnBoardVariantFieldChange(self, event): + selection = self.boardVariantFieldBox.Value + if not selection or selection == self.NONE_STRING \ + or self.extra_field_data is None: + self.boardVariantWhitelist.Clear() + self.boardVariantBlacklist.Clear() + return + variant_set = set() + for _, field_dict in self.extra_field_data.fields_by_ref.items(): + if selection in field_dict: + v = field_dict[selection] + if v == "": + v = self.EMPTY_STRING + variant_set.add(v) + self.boardVariantWhitelist.SetItems(list(variant_set)) + self.boardVariantBlacklist.SetItems(list(variant_set)) + + def OnSize(self, event): + self.Layout() + g = self.fieldsGrid + g.SetColSize( + 2, g.GetClientSize().x - g.GetColSize(0) - g.GetColSize(1) - 30) + + def GetShowFields(self): + result = [] + for row in range(self.fieldsGrid.NumberRows): + if self.fieldsGrid.GetCellValue(row, 0) == "1": + result.append(self.fieldsGrid.GetCellValue(row, 2)) + return result + + def GetGroupFields(self): + result = [] + for row in range(self.fieldsGrid.NumberRows): + if self.fieldsGrid.GetCellValue(row, 1) == "1": + result.append(self.fieldsGrid.GetCellValue(row, 2)) + return result + + def SetCheckedFields(self, show=None, group=None): + self.show_fields = show or self.show_fields + self.group_fields = group or self.group_fields + self.group_fields = [ + s for s in self.group_fields if s in self.show_fields + ] + current = [] + for row in range(self.fieldsGrid.NumberRows): + current.append(self.fieldsGrid.GetCellValue(row, 2)) + new = [s for s in current if s not in self.show_fields] + self._setFieldsList(self.show_fields + new) + for row in range(self.fieldsGrid.NumberRows): + field = self.fieldsGrid.GetCellValue(row, 2) + self.fieldsGrid.SetCellValue( + row, 0, "1" if field in self.show_fields else "") + self.fieldsGrid.SetCellValue( + row, 1, "1" if field in self.group_fields else "") diff --git a/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/ecad/__init__.py b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/ecad/__init__.py new file mode 100644 index 000000000..ecaef5ee3 --- /dev/null +++ b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/ecad/__init__.py @@ -0,0 +1,41 @@ +import os + + +def get_parser_by_extension(file_name, config, logger): + ext = os.path.splitext(file_name)[1] + if ext == '.kicad_pcb': + return get_kicad_parser(file_name, config, logger) + elif ext == '.json': + """.json file may be from EasyEDA or a generic json format""" + import io + import json + with io.open(file_name, 'r', encoding='utf-8') as f: + obj = json.load(f) + if 'pcbdata' in obj: + return get_generic_json_parser(file_name, config, logger) + else: + return get_easyeda_parser(file_name, config, logger) + elif ext in ['.fbrd', '.brd']: + return get_fusion_eagle_parser(file_name, config, logger) + else: + return None + + +def get_kicad_parser(file_name, config, logger, board=None): + from .kicad import PcbnewParser + return PcbnewParser(file_name, config, logger, board) + + +def get_easyeda_parser(file_name, config, logger): + from .easyeda import EasyEdaParser + return EasyEdaParser(file_name, config, logger) + + +def get_generic_json_parser(file_name, config, logger): + from .genericjson import GenericJsonParser + return GenericJsonParser(file_name, config, logger) + + +def get_fusion_eagle_parser(file_name, config, logger): + from .fusion_eagle import FusionEagleParser + return FusionEagleParser(file_name, config, logger) diff --git a/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/ecad/common.py b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/ecad/common.py new file mode 100644 index 000000000..92b3f21b3 --- /dev/null +++ b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/ecad/common.py @@ -0,0 +1,251 @@ +import math + +from .svgpath import parse_path + + +class ExtraFieldData(object): + def __init__(self, fields, fields_by_ref, fields_by_index=None): + self.fields = fields + self.fields_by_ref = fields_by_ref + self.fields_by_index = fields_by_index + + +class EcadParser(object): + + def __init__(self, file_name, config, logger): + """ + :param file_name: path to file that should be parsed. + :param config: Config instance + :param logger: logging object. + """ + self.file_name = file_name + self.config = config + self.logger = logger + + def parse(self): + """ + Abstract method that should be overridden in implementations. + Performs all the parsing and returns a tuple of + (pcbdata, components) + pcbdata is described in DATAFORMAT.md + components is list of Component objects + :return: + """ + pass + + @staticmethod + def normalize_field_names(data): + # type: (ExtraFieldData) -> ExtraFieldData + def remap(ref_fields): + return {f.lower(): v for (f, v) in + sorted(ref_fields.items(), reverse=True) if v} + + by_ref = {r: remap(d) for (r, d) in data.fields_by_ref.items()} + if data.fields_by_index: + by_index = {i: remap(d) for (i, d) in data.fields_by_index.items()} + print([a.get("blah", "") for a in by_index.values()]) + else: + by_index = None + + field_map = {f.lower(): f for f in sorted(data.fields, reverse=True)} + return ExtraFieldData(field_map.values(), by_ref, by_index) + + def get_extra_field_data(self, file_name): + """ + Abstract method that may be overridden in implementations that support + extra field data. + :return: ExtraFieldData + """ + return ExtraFieldData([], {}) + + def parse_extra_data(self, file_name, normalize_case): + """ + Parses the file and returns extra field data. + :param file_name: path to file containing extra data + :param normalize_case: if true, normalize case so that + "mpn", "Mpn", "MPN" fields are combined + :return: + """ + data = self.get_extra_field_data(file_name) + if normalize_case: + data = self.normalize_field_names(data) + return ExtraFieldData( + sorted(data.fields), data.fields_by_ref, data.fields_by_index) + + def latest_extra_data(self, extra_dirs=None): + """ + Abstract method that may be overridden in implementations that support + extra field data. + :param extra_dirs: List of extra directories to search. + :return: File name of most recent file with extra field data. + """ + return None + + def extra_data_file_filter(self): + """ + Abstract method that may be overridden in implementations that support + extra field data. + :return: File open dialog filter string, eg: + "Netlist and xml files (*.net; *.xml)|*.net;*.xml" + """ + return None + + def add_drawing_bounding_box(self, drawing, bbox): + # type: (dict, BoundingBox) -> None + + def add_segment(): + bbox.add_segment(drawing['start'][0], drawing['start'][1], + drawing['end'][0], drawing['end'][1], + drawing['width'] / 2) + + def add_circle(): + bbox.add_circle(drawing['start'][0], drawing['start'][1], + drawing['radius'] + drawing['width'] / 2) + + def add_svgpath(): + width = drawing.get('width', 0) + bbox.add_svgpath(drawing['svgpath'], width, self.logger) + + def add_polygon(): + if 'polygons' not in drawing: + add_svgpath() + return + polygon = drawing['polygons'][0] + for point in polygon: + bbox.add_point(point[0], point[1]) + + def add_arc(): + if 'svgpath' in drawing: + add_svgpath() + else: + width = drawing.get('width', 0) + xc, yc = drawing['start'][:2] + a1 = drawing['startangle'] + a2 = drawing['endangle'] + r = drawing['radius'] + x1 = xc + math.cos(math.radians(a1)) + y1 = xc + math.sin(math.radians(a1)) + x2 = xc + math.cos(math.radians(a2)) + y2 = xc + math.sin(math.radians(a2)) + da = a2 - a1 if a2 > a1 else a2 + 360 - a1 + la = 1 if da > 180 else 0 + svgpath = 'M %s %s A %s %s 0 %s 1 %s %s' % \ + (x1, y1, r, r, la, x2, y2) + bbox.add_svgpath(svgpath, width, self.logger) + + { + 'segment': add_segment, + 'rect': add_segment, # bbox of a rect and segment are the same + 'circle': add_circle, + 'arc': add_arc, + 'polygon': add_polygon, + 'text': lambda: None, # text is not really needed for bounding box + }.get(drawing['type'])() + + +class Component(object): + """Simple data object to store component data needed for bom table.""" + + def __init__(self, ref, val, footprint, layer, attr=None, extra_fields={}): + self.ref = ref + self.val = val + self.footprint = footprint + self.layer = layer + self.attr = attr + self.extra_fields = extra_fields + + +class BoundingBox(object): + """Geometry util to calculate and combine bounding box of simple shapes.""" + + def __init__(self): + self._x0 = None + self._y0 = None + self._x1 = None + self._y1 = None + + def to_dict(self): + # type: () -> dict + return { + "minx": self._x0, + "miny": self._y0, + "maxx": self._x1, + "maxy": self._y1, + } + + def to_component_dict(self): + # type: () -> dict + return { + "pos": [self._x0, self._y0], + "relpos": [0, 0], + "size": [self._x1 - self._x0, self._y1 - self._y0], + "angle": 0, + } + + def add(self, other): + """Add another bounding box. + :type other: BoundingBox + """ + if other._x0 is not None: + self.add_point(other._x0, other._y0) + self.add_point(other._x1, other._y1) + return self + + @staticmethod + def _rotate(x, y, rx, ry, angle): + sin = math.sin(math.radians(angle)) + cos = math.cos(math.radians(angle)) + new_x = rx + (x - rx) * cos - (y - ry) * sin + new_y = ry + (x - rx) * sin + (y - ry) * cos + return new_x, new_y + + def add_point(self, x, y, rx=0, ry=0, angle=0): + x, y = self._rotate(x, y, rx, ry, angle) + if self._x0 is None: + self._x0 = x + self._y0 = y + self._x1 = x + self._y1 = y + else: + self._x0 = min(self._x0, x) + self._y0 = min(self._y0, y) + self._x1 = max(self._x1, x) + self._y1 = max(self._y1, y) + return self + + def add_segment(self, x0, y0, x1, y1, r): + self.add_circle(x0, y0, r) + self.add_circle(x1, y1, r) + return self + + def add_rectangle(self, x, y, w, h, angle=0): + self.add_point(x - w / 2, y - h / 2, x, y, angle) + self.add_point(x + w / 2, y - h / 2, x, y, angle) + self.add_point(x - w / 2, y + h / 2, x, y, angle) + self.add_point(x + w / 2, y + h / 2, x, y, angle) + return self + + def add_circle(self, x, y, r): + self.add_point(x - r, y) + self.add_point(x, y - r) + self.add_point(x + r, y) + self.add_point(x, y + r) + return self + + def add_svgpath(self, svgpath, width, logger): + w = width / 2 + for segment in parse_path(svgpath, logger): + x0, x1, y0, y1 = segment.bbox() + self.add_point(x0 - w, y0 - w) + self.add_point(x1 + w, y1 + w) + + def pad(self, amount): + """Add small padding to the box.""" + if self._x0 is not None: + self._x0 -= amount + self._y0 -= amount + self._x1 += amount + self._y1 += amount + + def initialized(self): + return self._x0 is not None diff --git a/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/ecad/easyeda.py b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/ecad/easyeda.py new file mode 100644 index 000000000..cb9f23382 --- /dev/null +++ b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/ecad/easyeda.py @@ -0,0 +1,493 @@ +import io +import os +import sys + +from .common import EcadParser, Component, BoundingBox, ExtraFieldData + + +if sys.version_info >= (3, 0): + string_types = str +else: + string_types = basestring # noqa F821: ignore undefined + + +class EasyEdaParser(EcadParser): + TOP_COPPER_LAYER = 1 + BOT_COPPER_LAYER = 2 + TOP_SILK_LAYER = 3 + BOT_SILK_LAYER = 4 + BOARD_OUTLINE_LAYER = 10 + TOP_ASSEMBLY_LAYER = 13 + BOT_ASSEMBLY_LAYER = 14 + ALL_LAYERS = 11 + + def extra_data_file_filter(self): + return "Json file ({f})|{f}".format(f=os.path.basename(self.file_name)) + + def latest_extra_data(self, extra_dirs=None): + return self.file_name + + def get_extra_field_data(self, file_name): + if os.path.abspath(file_name) != os.path.abspath(self.file_name): + return None + + _, components = self.parse() + field_set = set() + comp_dict = {} + + for c in components: + ref_fields = comp_dict.setdefault(c.ref, {}) + + for k, v in c.extra_fields.items(): + field_set.add(k) + ref_fields[k] = v + + by_index = { + i: components[i].extra_fields for i in range(len(components)) + } + + return ExtraFieldData(list(field_set), comp_dict, by_index) + + def get_easyeda_pcb(self): + import json + with io.open(self.file_name, 'r', encoding='utf-8') as f: + return json.load(f) + + @staticmethod + def tilda_split(s): + # type: (str) -> list + return s.split('~') + + @staticmethod + def sharp_split(s): + # type: (str) -> list + return s.split('#@$') + + def _verify(self, pcb): + """Spot check the pcb object.""" + if 'head' not in pcb: + self.logger.error('No head attribute.') + return False + head = pcb['head'] + if len(head) < 2: + self.logger.error('Incorrect head attribute ' + pcb['head']) + return False + if head['docType'] != '3': + self.logger.error('Incorrect document type: ' + head['docType']) + return False + if 'canvas' not in pcb: + self.logger.error('No canvas attribute.') + return False + canvas = self.tilda_split(pcb['canvas']) + if len(canvas) < 18: + self.logger.error('Incorrect canvas attribute ' + pcb['canvas']) + return False + self.logger.info('EasyEDA editor version ' + head['editorVersion']) + return True + + @staticmethod + def normalize(v): + if isinstance(v, string_types): + v = float(v) + return v + + def parse_track(self, shape): + shape = self.tilda_split(shape) + assert len(shape) >= 5, 'Invalid track ' + str(shape) + width = self.normalize(shape[0]) + layer = int(shape[1]) + points = [self.normalize(v) for v in shape[3].split(' ')] + + points_xy = [[points[i], points[i + 1]] for i in + range(0, len(points), 2)] + segments = [(points_xy[i], points_xy[i + 1]) for i in + range(len(points_xy) - 1)] + segments_json = [] + for segment in segments: + segments_json.append({ + "type": "segment", + "start": segment[0], + "end": segment[1], + "width": width, + }) + + return layer, segments_json + + def parse_rect(self, shape): + shape = self.tilda_split(shape) + assert len(shape) >= 9, 'Invalid rect ' + str(shape) + x = self.normalize(shape[0]) + y = self.normalize(shape[1]) + width = self.normalize(shape[2]) + height = self.normalize(shape[3]) + layer = int(shape[4]) + fill = shape[8] + + if fill == "none": + thickness = self.normalize(shape[7]) + return layer, [{ + "type": "rect", + "start": [x, y], + "end": [x + width, y + height], + "width": thickness, + }] + else: + return layer, [{ + "type": "polygon", + "pos": [x, y], + "angle": 0, + "polygons": [ + [[0, 0], [width, 0], [width, height], [0, height]] + ] + }] + + def parse_circle(self, shape): + shape = self.tilda_split(shape) + assert len(shape) >= 6, 'Invalid circle ' + str(shape) + cx = self.normalize(shape[0]) + cy = self.normalize(shape[1]) + r = self.normalize(shape[2]) + width = self.normalize(shape[3]) + layer = int(shape[4]) + + return layer, [{ + "type": "circle", + "start": [cx, cy], + "radius": r, + "width": width + }] + + def parse_solid_region(self, shape): + shape = self.tilda_split(shape) + assert len(shape) >= 5, 'Invalid solid region ' + str(shape) + layer = int(shape[0]) + svgpath = shape[2] + + return layer, [{ + "type": "polygon", + "svgpath": svgpath, + }] + + def parse_text(self, shape): + shape = self.tilda_split(shape) + assert len(shape) >= 12, 'Invalid text ' + str(shape) + text_type = shape[0] + stroke_width = self.normalize(shape[3]) + layer = int(shape[6]) + text = shape[9] + svgpath = shape[10] + hide = shape[11] + + return layer, [{ + "type": "text", + "text": text, + "thickness": stroke_width, + "attr": [], + "svgpath": svgpath, + "hide": hide, + "text_type": text_type, + }] + + def parse_arc(self, shape): + shape = self.tilda_split(shape) + assert len(shape) >= 6, 'Invalid arc ' + str(shape) + width = self.normalize(shape[0]) + layer = int(shape[1]) + svgpath = shape[3] + + return layer, [{ + "type": "arc", + "svgpath": svgpath, + "width": width + }] + + def parse_hole(self, shape): + shape = self.tilda_split(shape) + assert len(shape) >= 4, 'Invalid hole ' + str(shape) + cx = self.normalize(shape[0]) + cy = self.normalize(shape[1]) + radius = self.normalize(shape[2]) + + return self.BOARD_OUTLINE_LAYER, [{ + "type": "circle", + "start": [cx, cy], + "radius": radius, + "width": 0.1, # 1 mil + }] + + def parse_pad(self, shape): + shape = self.tilda_split(shape) + assert len(shape) >= 15, 'Invalid pad ' + str(shape) + pad_shape = shape[0] + x = self.normalize(shape[1]) + y = self.normalize(shape[2]) + width = self.normalize(shape[3]) + height = self.normalize(shape[4]) + layer = int(shape[5]) + number = shape[7] + hole_radius = self.normalize(shape[8]) + if shape[9]: + points = [self.normalize(v) for v in shape[9].split(' ')] + else: + points = [] + angle = int(shape[10]) + hole_length = self.normalize(shape[12]) if shape[12] else 0 + + pad_layers = { + self.TOP_COPPER_LAYER: ['F'], + self.BOT_COPPER_LAYER: ['B'], + self.ALL_LAYERS: ['F', 'B'] + }.get(layer) + pad_shape = { + "ELLIPSE": "circle", + "RECT": "rect", + "OVAL": "oval", + "POLYGON": "custom", + }.get(pad_shape) + pad_type = "smd" if len(pad_layers) == 1 else "th" + + json = { + "layers": pad_layers, + "pos": [x, y], + "size": [width, height], + "angle": angle, + "shape": pad_shape, + "type": pad_type, + } + if number == '1': + json['pin1'] = 1 + if pad_shape == "custom": + polygon = [(points[i], points[i + 1]) for i in + range(0, len(points), 2)] + # translate coordinates to be relative to footprint + polygon = [(p[0] - x, p[1] - y) for p in polygon] + json["polygons"] = [polygon] + json["angle"] = 0 + if pad_type == "th": + if hole_length > 1e-6: + json["drillshape"] = "oblong" + json["drillsize"] = [hole_radius * 2, hole_length] + else: + json["drillshape"] = "circle" + json["drillsize"] = [hole_radius * 2, hole_radius * 2] + + return layer, [{ + "type": "pad", + "pad": json, + }] + + @staticmethod + def add_pad_bounding_box(pad, bbox): + # type: (dict, BoundingBox) -> None + + def add_circle(): + bbox.add_circle(pad['pos'][0], pad['pos'][1], pad['size'][0] / 2) + + def add_rect(): + bbox.add_rectangle(pad['pos'][0], pad['pos'][1], + pad['size'][0], pad['size'][1], + pad['angle']) + + def add_custom(): + x = pad['pos'][0] + y = pad['pos'][1] + polygon = pad['polygons'][0] + for point in polygon: + bbox.add_point(x + point[0], y + point[1]) + + { + 'circle': add_circle, + 'rect': add_rect, + 'oval': add_rect, + 'custom': add_custom, + }.get(pad['shape'])() + + def parse_lib(self, shape): + parts = self.sharp_split(shape) + head = self.tilda_split(parts[0]) + inner_shapes, _, _ = self.parse_shapes(parts[1:]) + x = self.normalize(head[0]) + y = self.normalize(head[1]) + attr = head[2] + fp_layer = int(head[6]) + + attr = attr.split('`') + if len(attr) % 2 != 0: + attr.pop() + attr = {attr[i]: attr[i + 1] for i in range(0, len(attr), 2)} + fp_layer = 'F' if fp_layer == self.TOP_COPPER_LAYER else 'B' + val = '??' + ref = '??' + footprint = '??' + if 'package' in attr: + footprint = attr['package'] + del attr['package'] + + pads = [] + copper_drawings = [] + extra_drawings = [] + bbox = BoundingBox() + for layer, shapes in inner_shapes.items(): + for s in shapes: + if s["type"] == "pad": + pads.append(s["pad"]) + continue + if s["type"] == "text": + if s["text_type"] == "N": + val = s["text"] + if s["text_type"] == "P": + ref = s["text"] + del s["text_type"] + if s["hide"]: + continue + if layer in [self.TOP_COPPER_LAYER, self.BOT_COPPER_LAYER]: + copper_drawings.append({ + "layer": ( + 'F' if layer == self.TOP_COPPER_LAYER else 'B'), + "drawing": s, + }) + elif layer in [self.TOP_SILK_LAYER, + self.BOT_SILK_LAYER, + self.TOP_ASSEMBLY_LAYER, + self.BOT_ASSEMBLY_LAYER, + self.BOARD_OUTLINE_LAYER]: + extra_drawings.append((layer, s)) + + for pad in pads: + self.add_pad_bounding_box(pad, bbox) + for drawing in copper_drawings: + self.add_drawing_bounding_box(drawing['drawing'], bbox) + for _, drawing in extra_drawings: + self.add_drawing_bounding_box(drawing, bbox) + bbox.pad(0.5) # pad by 5 mil + if not bbox.initialized(): + # if bounding box is not calculated yet + # set it to 100x100 mil square + bbox.add_rectangle(x, y, 10, 10, 0) + + footprint_json = { + "ref": ref, + "center": [x, y], + "bbox": bbox.to_component_dict(), + "pads": pads, + "drawings": copper_drawings, + "layer": fp_layer, + } + + component = Component(ref, val, footprint, fp_layer, extra_fields=attr) + + return fp_layer, component, footprint_json, extra_drawings + + def parse_shapes(self, shapes): + drawings = {} + footprints = [] + components = [] + + for shape_str in shapes: + shape = shape_str.split('~', 1) + parse_func = { + 'TRACK': self.parse_track, + 'RECT': self.parse_rect, + 'CIRCLE': self.parse_circle, + 'SOLIDREGION': self.parse_solid_region, + 'TEXT': self.parse_text, + 'ARC': self.parse_arc, + 'PAD': self.parse_pad, + 'HOLE': self.parse_hole, + }.get(shape[0], None) + if parse_func: + layer, json_list = parse_func(shape[1]) + drawings.setdefault(layer, []).extend(json_list) + if shape[0] == 'LIB': + layer, component, json, extras = self.parse_lib(shape[1]) + for drawing_layer, drawing in extras: + drawings.setdefault(drawing_layer, []).append(drawing) + footprints.append(json) + components.append(component) + + return drawings, footprints, components + + def get_metadata(self, pcb): + if hasattr(pcb, 'metadata'): + return pcb.metadata + else: + import os + from datetime import datetime + pcb_file_name = os.path.basename(self.file_name) + title = os.path.splitext(pcb_file_name)[0] + file_mtime = os.path.getmtime(self.file_name) + file_date = datetime.fromtimestamp(file_mtime).strftime( + '%Y-%m-%d %H:%M:%S') + return { + "title": title, + "revision": "", + "company": "", + "date": file_date, + } + + def parse(self): + pcb = self.get_easyeda_pcb() + if not self._verify(pcb): + self.logger.error( + 'File ' + self.file_name + + ' does not appear to be valid EasyEDA json file.') + return None, None + + drawings, footprints, components = self.parse_shapes(pcb['shape']) + + board_outline_bbox = BoundingBox() + for drawing in drawings.get(self.BOARD_OUTLINE_LAYER, []): + self.add_drawing_bounding_box(drawing, board_outline_bbox) + if board_outline_bbox.initialized(): + bbox = board_outline_bbox.to_dict() + else: + # if nothing is drawn on outline layer then rely on EasyEDA bbox + x = self.normalize(pcb['BBox']['x']) + y = self.normalize(pcb['BBox']['y']) + bbox = { + "minx": x, + "miny": y, + "maxx": x + self.normalize(pcb['BBox']['width']), + "maxy": y + self.normalize(pcb['BBox']['height']) + } + + pcbdata = { + "edges_bbox": bbox, + "edges": drawings.get(self.BOARD_OUTLINE_LAYER, []), + "drawings": { + "silkscreen": { + 'F': drawings.get(self.TOP_SILK_LAYER, []), + 'B': drawings.get(self.BOT_SILK_LAYER, []), + }, + "fabrication": { + 'F': drawings.get(self.TOP_ASSEMBLY_LAYER, []), + 'B': drawings.get(self.BOT_ASSEMBLY_LAYER, []), + }, + }, + "footprints": footprints, + "metadata": self.get_metadata(pcb), + "bom": {}, + "font_data": {} + } + + if self.config.include_tracks: + def filter_tracks(drawing_list, drawing_type, keys): + result = [] + for d in drawing_list: + if d["type"] == drawing_type: + r = {} + for key in keys: + r[key] = d[key] + result.append(r) + return result + + pcbdata["tracks"] = { + 'F': filter_tracks(drawings.get(self.TOP_COPPER_LAYER, []), + "segment", ["start", "end", "width"]), + 'B': filter_tracks(drawings.get(self.BOT_COPPER_LAYER, []), + "segment", ["start", "end", "width"]), + } + # zones are not supported + pcbdata["zones"] = {'F': [], 'B': []} + + return pcbdata, components diff --git a/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/ecad/fusion_eagle.py b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/ecad/fusion_eagle.py new file mode 100644 index 000000000..76d001966 --- /dev/null +++ b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/ecad/fusion_eagle.py @@ -0,0 +1,920 @@ +import io +import math +import os +import string +import zipfile +from datetime import datetime +from xml.etree import ElementTree + +from .common import EcadParser, Component, BoundingBox +from .svgpath import Arc +from ..core.fontparser import FontParser + + +class FusionEagleParser(EcadParser): + TOP_COPPER_LAYER = '1' + BOT_COPPER_LAYER = '16' + TOP_PLACE_LAYER = '21' + BOT_PLACE_LAYER = '22' + TOP_NAMES_LAYER = '25' + BOT_NAMES_LAYER = '26' + DIMENSION_LAYER = '20' + TOP_DOCU_LAYER = '51' + BOT_DOCU_LAYER = '52' + + def __init__(self, file_name, config, logger): + super(FusionEagleParser, self).__init__(file_name, config, logger) + self.config = config + self.font_parser = FontParser() + self.min_via_w = 1e-3 + self.pcbdata = { + 'drawings': { + 'silkscreen': { + 'F': [], + 'B': [] + }, + 'fabrication': { + 'F': [], + 'B': [] + } + }, + 'edges': [], + 'footprints': [], + 'font_data': {} + } + self.components = [] + + def _parse_pad_nets(self, signals): + elements = {} + + for signal in signals.iter('signal'): + net = signal.attrib['name'] + for c in signal.iter('contactref'): + e = c.attrib['element'] + if e not in elements: + elements[e] = {} + elements[e][c.attrib['pad']] = net + + self.elements_pad_nets = elements + + @staticmethod + def _radian(ux, uy, vx, vy): + dot = ux * vx + uy * vy + mod = math.sqrt((ux * ux + uy * uy) * (vx * vx + vy * vy)) + rad = math.acos(dot / mod) + if ux * vy - uy * vx < 0.0: + rad = -rad + return rad + + def _curve_to_svgparams(self, el, x=0, y=0, angle=0, mirrored=False): + _x1 = float(el.attrib['x1']) + _x2 = float(el.attrib['x2']) + _y1 = -float(el.attrib['y1']) + _y2 = -float(el.attrib['y2']) + + dx1, dy1 = self._rotate(_x1, _y1, -angle, mirrored) + dx2, dy2 = self._rotate(_x2, _y2, -angle, mirrored) + + x1, y1 = x + dx1, -y + dy1 + x2, y2 = x + dx2, -y + dy2 + + chord = math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2) + theta = float(el.attrib['curve']) + theta = -theta if mirrored else theta + r = abs(0.5 * chord / math.sin(math.radians(theta) / 2)) + la = 0 if abs(theta) < 180 else 1 + sw = 0 if theta > 0 else 1 + return { + 'x1': x1, + 'y1': y1, + 'r': r, + 'la': la, + 'sw': sw, + 'x2': x2, + 'y2': y2 + } + + def _curve_to_svgpath(self, el, x=0, y=0, angle=0, mirrored=False): + p = self._curve_to_svgparams(el, x, y, angle, mirrored) + return 'M {x1} {y1} A {r} {r} 0 {la} {sw} {x2} {y2}'.format(**p) + + @staticmethod + class Rot: + def __init__(self, rot_string): + if not rot_string: + self.mirrored = False + self.spin = False + self.angle = 0 + return + self.mirrored = 'M' in rot_string + self.spin = 'S' in rot_string + self.angle = float(''.join(d for d in rot_string + if d in string.digits + '.')) + + def __repr__(self): + return self.__str__() + + def __str__(self): + return "Mirrored: {0}, Spin: {1}, Angle: {2}".format(self.mirrored, + self.spin, + self.angle) + + def _rectangle_vertices(self, el): + # Note: Eagle specifies a rectangle using opposing corners + # (x1, y1) = lower-left and (x2, y2) = upper-right) and *optionally* + # a rotation angle. The size of the rectangle is defined by the + # corners irrespective of rotation angle, and then it is rotated + # about its own center point. + _x1 = float(el.attrib['x1']) + _x2 = float(el.attrib['x2']) + _y1 = -float(el.attrib['y1']) + _y2 = -float(el.attrib['y2']) + + # Center of rectangle + xc = (_x1 + _x2) / 2 + yc = (_y1 + _y2) / 2 + + # Vertices of rectangle relative to its center, un-rotated + _dv_c = [ + (_x1 - xc, _y1 - yc), + (_x2 - xc, _y1 - yc), + (_x2 - xc, _y2 - yc), + (_x1 - xc, _y2 - yc) + ] + + elr = self.Rot(el.get('rot')) + + # Rotate the rectangle about its center + dv_c = [self._rotate(_x, _y, -elr.angle, elr.mirrored) + for (_x, _y) in _dv_c] + + # Map vertices to position relative to component origin, un-rotated + return [(_x + xc, _y + yc) for (_x, _y) in dv_c] + + def _add_drawing(self, el): + layer_dest = { + self.DIMENSION_LAYER: self.pcbdata['edges'], + self.TOP_PLACE_LAYER: self.pcbdata['drawings']['silkscreen']['F'], + self.BOT_PLACE_LAYER: self.pcbdata['drawings']['silkscreen']['B'], + self.TOP_NAMES_LAYER: self.pcbdata['drawings']['silkscreen']['F'], + self.BOT_NAMES_LAYER: self.pcbdata['drawings']['silkscreen']['B'] + } + if ("layer" in el.attrib) and (el.attrib['layer'] in layer_dest): + dwg = None + if el.tag == 'wire': + dwg = {'width': float(el.attrib['width'])} + + if 'curve' in el.attrib: + dwg['type'] = 'arc' + dwg['svgpath'] = self._curve_to_svgpath(el) + else: + dwg['type'] = 'segment' + dwg['start'] = [ + float(el.attrib['x1']), + -float(el.attrib['y1']) + ] + dwg['end'] = [ + float(el.attrib['x2']), + -float(el.attrib['y2']) + ] + + elif el.tag == 'text': + # Text is not currently supported (except refdes) + # due to lack of Eagle font data + pass + + elif el.tag == 'circle': + dwg = { + 'type': 'circle', + 'start': [float(el.attrib['x']), -float(el.attrib['y'])], + 'radius': float(el.attrib['radius']), + 'width': float(el.attrib['width']) + } + + elif el.tag in ['polygonshape', 'polygon']: + dwg = { + 'type': 'polygon', + 'pos': [0, 0], + 'angle': 0, + 'polygons': [] + } + segs = el if el.tag == 'polygon' \ + else el.find('polygonoutlinesegments') + polygon = FusionEagleParser._segments_to_polygon(segs) + dwg['polygons'].append(polygon) + + elif el.tag == 'rectangle': + vertices = self._rectangle_vertices(el) + dwg = { + 'type': 'polygon', + 'pos': [0, 0], + 'angle': 0, + 'polygons': [[list(v) for v in vertices]] + } + + if dwg: + layer_dest[el.attrib['layer']].append(dwg) + + def _add_track(self, el, net): + if el.tag == 'via' or ( + el.tag == 'wire' and el.attrib['layer'] in + [self.TOP_COPPER_LAYER, self.BOT_COPPER_LAYER]): + trk = {} + if self.config.include_nets: + trk['net'] = net + + if el.tag == 'wire': + dest = self.pcbdata['tracks']['F'] \ + if el.attrib['layer'] == self.TOP_COPPER_LAYER\ + else self.pcbdata['tracks']['B'] + + if 'curve' in el.attrib: + trk['width'] = float(el.attrib['width']) + # Get SVG parameters for the curve + p = self._curve_to_svgparams(el) + start = complex(p['x1'], p['y1']) + end = complex(p['x2'], p['y2']) + radius = complex(p['r'], p['r']) + large_arc = bool(p['la']) + sweep = bool(p['sw']) + # Pass SVG parameters to get center parameters + arc = Arc(start, radius, 0, large_arc, sweep, end) + # Create arc track from center parameters + trk['center'] = [arc.center.real, arc.center.imag] + trk['radius'] = radius.real + if arc.delta < 0: + trk['startangle'] = arc.theta + arc.delta + trk['endangle'] = arc.theta + else: + trk['startangle'] = arc.theta + trk['endangle'] = arc.theta + arc.delta + dest.append(trk) + else: + trk['start'] = [ + float(el.attrib['x1']), + -float(el.attrib['y1']) + ] + trk['end'] = [ + float(el.attrib['x2']), + -float(el.attrib['y2']) + ] + trk['width'] = float(el.attrib['width']) + dest.append(trk) + + elif el.tag == 'via': + trk['start'] = [float(el.attrib['x']), -float(el.attrib['y'])] + trk['end'] = trk['start'] + trk['width'] = float(el.attrib['drill']) + 2 * self.min_via_w \ + if 'diameter' not in el.attrib else float( + el.attrib['diameter']) + if float(el.attrib['drill']) >= self.min_drill_via_untented: + trk['drillsize'] = float(el.attrib['drill']) + self.pcbdata['tracks']['F'].append(trk) + self.pcbdata['tracks']['B'].append(trk) + + def _calculate_footprint_bbox(self, package, x, y, angle, mirrored): + _angle = angle if not mirrored else -angle + layers = [ + self.TOP_PLACE_LAYER, + self.BOT_PLACE_LAYER, + self.TOP_DOCU_LAYER, + self.BOT_DOCU_LAYER + ] + xmax, ymax = -float('inf'), -float('inf') + xmin, ymin = float('inf'), float('inf') + + for el in package.iter('wire'): + if el.tag == 'wire' and el.attrib['layer'] in layers: + xmax = max(xmax, + max(float(el.attrib['x1']), float(el.attrib['x2']))) + ymax = max(ymax, + max(float(el.attrib['y1']), float(el.attrib['y2']))) + xmin = min(xmin, + min(float(el.attrib['x1']), float(el.attrib['x2']))) + ymin = min(ymin, + min(float(el.attrib['y1']), float(el.attrib['y2']))) + + for el in package.iter(): + if el.tag in ['smd', 'pad']: + elx, ely = float(el.attrib['x']), float(el.attrib['y']) + if el.tag == 'smd': + dx, dy = abs(float(el.attrib['dx'])) / 2, abs( + float(el.attrib['dy'])) / 2 + else: + d = el.get('diameter') + if d is None: + diameter = float(el.get('drill')) + 2 * self.min_via_w + else: + diameter = float(d) + dx, dy = diameter / 2, diameter / 2 + xmax, ymax = max(xmax, elx + dx), max(ymax, ely + dy) + xmin, ymin = min(xmin, elx - dx), min(ymin, ely - dy) + + if not math.isinf(xmin): + if mirrored: + xmin, xmax = -xmax, -xmin + dx, dy = self._rotate(xmin, ymax, _angle) + sx = abs(xmax - xmin) + sy = abs(ymax - ymin) + else: + dx, dy = 0, 0 + sx, sy = 0, 0 + + return { + 'pos': [x + dx, -y - dy], + 'angle': _angle, + 'relpos': [0, 0], + 'size': [sx, sy] + } + + def _footprint_pads(self, package, x, y, angle, mirrored, refdes): + pads = [] + element_pad_nets = self.elements_pad_nets.get(refdes) + pin1_allocated = False + for el in package.iter(): + if el.tag == 'pad': + elx = float(el.attrib['x']) + ely = -float(el.attrib['y']) + drill = float(el.attrib['drill']) + + dx, dy = self._rotate(elx, ely, -angle, mirrored) + + diameter = drill + 2 * self.min_via_w \ + if 'diameter' not in el.attrib \ + else float(el.attrib['diameter']) + + pr = self.Rot(el.get('rot')) + if mirrored ^ pr.mirrored: + pad_angle = -angle - pr.angle + else: + pad_angle = angle + pr.angle + + pad = { + 'layers': ['F', 'B'], + 'pos': [x + dx, -y + dy], + 'angle': pad_angle, + 'type': 'th', + 'drillshape': 'circle', + 'drillsize': [ + drill, + drill + ] + } + + if el.get('name') in ['1', 'A', 'A1', 'P1', 'PAD1'] and \ + not pin1_allocated: + pad['pin1'] = 1 + pin1_allocated = True + + if 'shape' not in el.attrib or el.attrib['shape'] == 'round': + pad['shape'] = 'circle' + pad['size'] = [diameter, diameter] + elif el.attrib['shape'] == 'square': + pad['shape'] = 'rect' + pad['size'] = [diameter, diameter] + elif el.attrib['shape'] == 'octagon': + pad['shape'] = 'chamfrect' + pad['size'] = [diameter, diameter] + pad['radius'] = 0 + pad['chamfpos'] = 0b1111 # all corners + pad['chamfratio'] = 0.333 + elif el.attrib['shape'] == 'long': + pad['shape'] = 'roundrect' + pad['radius'] = diameter / 2 + pad['size'] = [2 * diameter, diameter] + elif el.attrib['shape'] == 'offset': + pad['shape'] = 'roundrect' + pad['radius'] = diameter / 2 + pad['size'] = [2 * diameter, diameter] + pad['offset'] = [diameter / 2, 0] + elif el.attrib['shape'] == 'slot': + pad['shape'] = 'roundrect' + pad['radius'] = diameter / 2 + slot_length = float(el.attrib['slotLength']) + pad['size'] = [slot_length + diameter / 2, diameter] + pad['drillshape'] = 'oblong' + pad['drillsize'] = [slot_length, drill] + else: + self.logger.info( + "Unsupported footprint pad shape %s, skipping", + el.attrib['shape']) + + if self.config.include_nets and element_pad_nets is not None: + net = element_pad_nets.get(el.attrib['name']) + if net is not None: + pad['net'] = net + + pads.append(pad) + + elif el.tag == 'smd': + layer = el.attrib['layer'] + if layer == self.TOP_COPPER_LAYER and not mirrored or \ + layer == self.BOT_COPPER_LAYER and mirrored: + layers = ['F'] + elif layer == self.TOP_COPPER_LAYER and mirrored or \ + layer == self.BOT_COPPER_LAYER and not mirrored: + layers = ['B'] + else: + self.logger.error('Unable to determine layer for ' + '{0} pad {1}'.format(refdes, + el.attrib['name'])) + layers = None + + if layers is not None: + elx = float(el.attrib['x']) + ely = -float(el.attrib['y']) + + dx, dy = self._rotate(elx, ely, -angle, mirrored) + + pr = self.Rot(el.get('rot')) + if mirrored ^ pr.mirrored: + pad_angle = -angle - pr.angle + else: + pad_angle = angle + pr.angle + + pad = {'layers': layers, + 'pos': [x + dx, -y + dy], + 'size': [ + float(el.attrib['dx']), + float(el.attrib['dy']) + ], + 'angle': pad_angle, + 'type': 'smd', + } + + if el.get('name') in ['1', 'A', 'A1', 'P1', 'PAD1'] and \ + not pin1_allocated: + pad['pin1'] = 1 + pin1_allocated = True + + if 'roundness' not in el.attrib: + pad['shape'] = 'rect' + else: + pad['shape'] = 'roundrect' + pad['radius'] = (float(el.attrib['roundness']) / 100) \ + * float(el.attrib['dy']) / 2 + + if self.config.include_nets and \ + element_pad_nets is not None: + net = element_pad_nets.get(el.attrib['name']) + if net is not None: + pad['net'] = net + + pads.append(pad) + return pads + + @staticmethod + def _rotate(x, y, angle, mirrored=False): + sin = math.sin(math.radians(angle)) + cos = math.cos(math.radians(angle)) + xr = x * cos - y * sin + yr = y * cos + x * sin + if mirrored: + return -xr, yr + else: + return xr, yr + + def _process_footprint(self, package, x, y, angle, mirrored, populate): + for el in package.iter(): + if el.tag in ['wire', 'rectangle', 'circle', 'hole', + 'polygonshape', 'polygon', 'hole']: + if el.tag == 'hole': + dwg_layer = self.pcbdata['edges'] + elif el.attrib['layer'] in [self.TOP_PLACE_LAYER, + self.BOT_PLACE_LAYER]: + dwg_layer = self.pcbdata['drawings']['silkscreen'] + top = el.attrib['layer'] == self.TOP_PLACE_LAYER + elif el.attrib['layer'] in [self.TOP_DOCU_LAYER, + self.BOT_DOCU_LAYER]: + if not populate: + return + dwg_layer = self.pcbdata['drawings']['fabrication'] + top = el.attrib['layer'] == self.TOP_DOCU_LAYER + elif el.tag == 'wire' and \ + el.attrib['layer'] == self.DIMENSION_LAYER: + dwg_layer = self.pcbdata['edges'] + top = True + else: + continue + + dwg = None + + if el.tag == 'wire': + _dx1 = float(el.attrib['x1']) + _dx2 = float(el.attrib['x2']) + _dy1 = -float(el.attrib['y1']) + _dy2 = -float(el.attrib['y2']) + + dx1, dy1 = self._rotate(_dx1, _dy1, -angle, mirrored) + dx2, dy2 = self._rotate(_dx2, _dy2, -angle, mirrored) + + x1, y1 = x + dx1, -y + dy1 + x2, y2 = x + dx2, -y + dy2 + + if el.get('curve'): + dwg = { + 'type': 'arc', + 'width': float(el.attrib['width']), + 'svgpath': self._curve_to_svgpath(el, x, y, angle, + mirrored) + } + else: + dwg = { + 'type': 'segment', + 'start': [x1, y1], + 'end': [x2, y2], + 'width': float(el.attrib['width']) + } + + elif el.tag == 'rectangle': + _dv = self._rectangle_vertices(el) + + # Rotate rectangle about component origin based on + # component angle + dv = [self._rotate(_x, _y, -angle, mirrored) + for (_x, _y) in _dv] + + # Map vertices back to absolute coordinates + v = [(x + _x, -y + _y) for (_x, _y) in dv] + + dwg = { + 'type': 'polygon', + 'filled': 1, + 'pos': [0, 0], + 'polygons': [v] + } + + elif el.tag in ['circle', 'hole']: + _x = float(el.attrib['x']) + _y = -float(el.attrib['y']) + dxc, dyc = self._rotate(_x, _y, -angle, mirrored) + xc, yc = x + dxc, -y + dyc + + if el.tag == 'circle': + radius = float(el.attrib['radius']) + width = float(el.attrib['width']) + else: + radius = float(el.attrib['drill']) / 2 + width = 0 + + dwg = { + 'type': 'circle', + 'start': [xc, yc], + 'radius': radius, + 'width': width + } + + elif el.tag in ['polygonshape', 'polygon']: + segs = el if el.tag == 'polygon' \ + else el.find('polygonoutlinesegments') + + dv = self._segments_to_polygon(segs, angle, mirrored) + + polygon = [[x + v[0], -y + v[1]] for v in dv] + + dwg = { + 'type': 'polygon', + 'filled': 1, + 'pos': [0, 0], + 'polygons': [polygon] + } + + if dwg is not None: + if el.tag == 'hole' or \ + el.attrib['layer'] == self.DIMENSION_LAYER: + dwg_layer.append(dwg) + else: + bot = not top + + # Note that in Eagle terminology, 'mirrored' + # essentially means 'flipped' (i.e. to the opposite + # side of the board) + if (mirrored and bot) or (not mirrored and top): + dwg_layer['F'].append(dwg) + elif (mirrored and top) or (not mirrored and bot): + dwg_layer['B'].append(dwg) + + def _name_to_silk(self, name, x, y, elr, tr, align, size, ratio): + angle = tr.angle + mirrored = tr.mirrored + spin = elr.spin ^ tr.spin + if mirrored: + angle = -angle + + if align is None: + justify = [-1, 1] + elif align == 'center': + justify = [0, 0] + else: + j = align.split('-') + alignments = { + 'bottom': 1, + 'center': 0, + 'top': -1, + 'left': -1, + 'right': 1 + } + justify = [alignments[ss] for ss in j[::-1]] + if (90 < angle <= 270 and not spin) or \ + (-90 > angle >= -270 and not spin): + angle += 180 + justify = [-j for j in justify] + + dwg = { + 'type': 'text', + 'text': name, + 'pos': [x, y], + 'height': size, + 'width': size, + 'justify': justify, + 'thickness': size * ratio, + 'attr': [] if not mirrored else ['mirrored'], + 'angle': angle + } + + self.font_parser.parse_font_for_string(name) + if mirrored: + self.pcbdata['drawings']['silkscreen']['B'].append(dwg) + else: + self.pcbdata['drawings']['silkscreen']['F'].append(dwg) + + def _element_refdes_to_silk(self, el, package): + if 'smashed' not in el.attrib: + elx = float(el.attrib['x']) + ely = -float(el.attrib['y']) + for p_el in package.iter('text'): + if p_el.text == '>NAME': + dx = float(p_el.attrib['x']) + dy = float(p_el.attrib['y']) + elr = self.Rot(el.get('rot')) + dx, dy = self._rotate(dx, dy, elr.angle, elr.mirrored) + tr = self.Rot(p_el.get('rot')) + tr.angle += elr.angle + tr.mirrored ^= elr.mirrored + self._name_to_silk( + name=el.attrib['name'], + x=elx + dx, + y=ely - dy, + elr=elr, + tr=tr, + align=p_el.get('align'), + size=float(p_el.attrib['size']), + ratio=float(p_el.get('ratio', '8')) / 100) + + for attr in el.iter('attribute'): + if attr.attrib['name'] == 'NAME': + self._name_to_silk( + name=el.attrib['name'], + x=float(attr.attrib['x']), + y=-float(attr.attrib['y']), + elr=self.Rot(el.get('rot')), + tr=self.Rot(attr.get('rot')), + align=attr.attrib.get('align'), + size=float(attr.attrib['size']), + ratio=float(attr.get('ratio', '8')) / 100) + + @staticmethod + def _segments_to_polygon(segs, angle=0, mirrored=False): + polygon = [] + for vertex in segs.iter('vertex'): + _x, _y = float(vertex.attrib['x']), -float(vertex.attrib['y']) + x, y = FusionEagleParser._rotate(_x, _y, -angle, mirrored) + polygon.append([x, y]) + return polygon + + def _add_zone(self, poly, net): + layer = poly.attrib['layer'] + if layer == self.TOP_COPPER_LAYER: + dest = self.pcbdata['zones']['F'] + elif layer == self.BOT_COPPER_LAYER: + dest = self.pcbdata['zones']['B'] + else: + return + + if poly.tag == 'polygonpour': + shapes = poly.find('polygonfilldetails').findall('polygonshape') + if shapes: + zone = {'polygons': [], + 'fillrule': 'evenodd'} + for shape in shapes: + segs = shape.find('polygonoutlinesegments') + zone['polygons'].append(self._segments_to_polygon(segs)) + holelist = shape.find('polygonholelist') + if holelist: + holes = holelist.findall('polygonholesegments') + for hole in holes: + zone['polygons'].append(self._segments_to_polygon(hole)) + if self.config.include_nets: + zone['net'] = net + dest.append(zone) + else: + zone = {'polygons': []} + zone['polygons'].append(self._segments_to_polygon(poly)) + if self.config.include_nets: + zone['net'] = net + dest.append(zone) + + def _add_parsed_font_data(self): + for (c, wl) in self.font_parser.get_parsed_font().items(): + if c not in self.pcbdata['font_data']: + self.pcbdata['font_data'][c] = wl + + def _parse_param_length(self, name, root, default): + # parse named parameter (typically a design rule) assuming it is in + # length units (mil or mm) + p = [el.attrib['value'] for el in root.iter('param') if + el.attrib['name'] == name] + if len(p) == 0: + self.logger.warning("{0} not found, defaulting to {1}" + .format(name, default)) + return default + else: + if len(p) > 1: + self.logger.warning( + "Multiple {0} found, using first occurrence".format(name)) + p = p[0] + p_val = float(''.join(d for d in p if d in string.digits + '.')) + p_units = (''.join(d for d in p if d in string.ascii_lowercase)) + + if p_units == 'mm': + return p_val + elif p_units == 'mil': + return p_val * 0.0254 + else: + self.logger.error("Unsupported units {0} on {1}" + .format(p_units, name)) + + def parse(self): + ext = os.path.splitext(self.file_name)[1] + + if ext.lower() == '.fbrd': + with zipfile.ZipFile(self.file_name) as myzip: + brdfilename = [fname for fname in myzip.namelist() if + os.path.splitext(fname)[1] == '.brd'] + with myzip.open(brdfilename[0]) as brdfile: + return self._parse(brdfile) + + elif ext.lower() == '.brd': + with io.open(self.file_name, 'r', encoding='utf-8') as brdfile: + return self._parse(brdfile) + + def _parse(self, brdfile): + try: + brdxml = ElementTree.parse(brdfile) + except ElementTree.ParseError as err: + self.logger.error( + "Exception occurred trying to parse {0}, message: {1}" + .format(brdfile.name, err.msg)) + return None, None + if brdxml is None: + self.logger.error( + "No data was able to be parsed from {0}".format(brdfile.name)) + return None, None + + # Pick out key sections + root = brdxml.getroot() + board = root.find('drawing').find('board') + plain = board.find('plain') + elements = board.find('elements') + signals = board.find('signals') + + # Build library mapping elements' pads to nets + self._parse_pad_nets(signals) + + # Parse needed design rules + + # Minimum via annular ring + # (Needed in order to calculate through-hole pad diameters correctly) + self.min_via_w = ( + self._parse_param_length('rlMinViaOuter', root, default=0)) + + # Minimum drill diameter above which vias will be un-tented + self.min_drill_via_untented = ( + self._parse_param_length('mlViaStopLimit', root, default=0)) + + # Signals --> nets + if self.config.include_nets: + self.pcbdata['nets'] = [] + for signal in signals.iter('signal'): + self.pcbdata['nets'].append(signal.attrib['name']) + + # Signals --> tracks, zones + if self.config.include_tracks: + self.pcbdata['tracks'] = {'F': [], 'B': []} + self.pcbdata['zones'] = {'F': [], 'B': []} + for signal in signals.iter('signal'): + for wire in signal.iter('wire'): + self._add_track(wire, signal.attrib['name']) + for via in signal.iter('via'): + self._add_track(via, signal.attrib['name']) + for poly in signal.iter('polygonpour'): + self._add_zone(poly, signal.attrib['name']) + + # Elements --> components, footprints, silkscreen, edges + for el in elements.iter('element'): + populate = el.get('populate') != 'no' + elr = self.Rot(el.get('rot')) + layer = 'B' if elr.mirrored else 'F' + extra_fields = {} + + for a in el.iter('attribute'): + if 'value' in a.attrib: + extra_fields[a.attrib['name']] = a.attrib['value'] + + comp = Component(ref=el.attrib['name'], + val='' if 'value' not in el.attrib else el.attrib[ + 'value'], + footprint=el.attrib['package'], + layer=layer, + attr=None if populate else 'Virtual', + extra_fields=extra_fields) + + # For component, get footprint data + libs = [lib for lib in board.find('libraries').findall('library') + if lib.attrib['name'] == el.attrib['library']] + packages = [] + for lib in libs: + p = [pac for pac in lib.find('packages').findall('package') + if pac.attrib['name'] == el.attrib['package']] + packages.extend(p) + if not packages: + self.logger.error("Package {0} in library {1} not found in " + "source file {2} for element {3}" + .format(el.attrib['package'], + el.attrib['library'], + brdfile.name, + el.attrib['name'])) + return None, None + else: + package = packages[0] + if len(packages) > 1: + self.logger.warn("Multiple packages found for package {0}" + " in library {1}, using first instance " + "found".format(el.attrib['package'], + el.attrib['library'])) + + elx = float(el.attrib['x']) + ely = float(el.attrib['y']) + refdes = el.attrib['name'] + footprint = { + 'ref': refdes, + 'center': [elx, ely], + 'pads': [], + 'drawings': [], + 'layer': layer + } + + elr = self.Rot(el.get('rot')) + footprint['pads'] = self._footprint_pads(package, elx, ely, + elr.angle, elr.mirrored, + refdes) + footprint['bbox'] = self._calculate_footprint_bbox(package, elx, + ely, elr.angle, + elr.mirrored) + self.pcbdata['footprints'].append(footprint) + + # Add silkscreen, edges for component footprint & refdes + self._process_footprint(package, elx, ely, elr.angle, elr.mirrored, + populate) + self._element_refdes_to_silk(el, package) + + self.components.append(comp) + + # Edges & silkscreen (independent of elements) + for el in plain.iter(): + self._add_drawing(el) + # identify board bounding box based on edges + board_outline_bbox = BoundingBox() + + for drawing in self.pcbdata['edges']: + self.add_drawing_bounding_box(drawing, board_outline_bbox) + if board_outline_bbox.initialized(): + self.pcbdata['edges_bbox'] = board_outline_bbox.to_dict() + + self._add_parsed_font_data() + + # Fabrication & metadata + company = [a.attrib['value'] for a in root.iter('attribute') if + a.attrib['name'] == 'COMPANY'] + company = '' if not company else company[0] + rev = [a.attrib['value'] for a in root.iter('attribute') if + a.attrib['name'] == 'REVISION'] + rev = '' if not rev else rev[0] + + if not rev: + rev = '' + + title = os.path.basename(self.file_name) + + variant = [a.attrib['name'] for a in root.iter('variantdef') if + a.get('current') == 'yes'] + variant = None if not variant else variant[0] + if variant: + title = "{0}, Variant: {1}".format(title, variant) + + date = datetime.fromtimestamp( + os.path.getmtime(self.file_name)).strftime('%Y-%m-%d %H:%M:%S') + self.pcbdata['metadata'] = {'title': title, 'revision': rev, + 'company': company, 'date': date} + + return self.pcbdata, self.components diff --git a/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/ecad/genericjson.py b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/ecad/genericjson.py new file mode 100644 index 000000000..c83f78e77 --- /dev/null +++ b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/ecad/genericjson.py @@ -0,0 +1,167 @@ +import io +import json +import os.path +from jsonschema import validate, ValidationError + +from .common import EcadParser, Component, BoundingBox, ExtraFieldData +from ..core.fontparser import FontParser +from ..errors import ParsingException + + +class GenericJsonParser(EcadParser): + COMPATIBLE_SPEC_VERSIONS = [1] + + def extra_data_file_filter(self): + return "Json file ({f})|{f}".format(f=os.path.basename(self.file_name)) + + def latest_extra_data(self, extra_dirs=None): + return self.file_name + + def get_extra_field_data(self, file_name): + if os.path.abspath(file_name) != os.path.abspath(self.file_name): + return None + + _, components = self._parse() + field_set = set() + comp_dict = {} + + for c in components: + ref_fields = comp_dict.setdefault(c.ref, {}) + + for k, v in c.extra_fields.items(): + field_set.add(k) + ref_fields[k] = v + + by_index = { + i: components[i].extra_fields for i in range(len(components)) + } + + return ExtraFieldData(list(field_set), comp_dict, by_index) + + def get_generic_json_pcb(self): + with io.open(self.file_name, 'r', encoding='utf-8') as f: + pcb = json.load(f) + + if 'spec_version' not in pcb: + raise ValidationError("'spec_version' is a required property") + + if pcb['spec_version'] not in self.COMPATIBLE_SPEC_VERSIONS: + raise ValidationError("Unsupported spec_version ({})" + .format(pcb['spec_version'])) + + schema_dir = os.path.join(os.path.dirname(__file__), 'schema') + schema_file_name = os.path.join(schema_dir, + 'genericjsonpcbdata_v{}.schema'.format( + pcb['spec_version'])) + + with io.open(schema_file_name, 'r', encoding='utf-8') as f: + schema = json.load(f) + + validate(instance=pcb, schema=schema) + + return pcb + + def _verify(self, pcb): + """Spot check the pcb object.""" + + if len(pcb['pcbdata']['footprints']) != len(pcb['components']): + self.logger.error("Length of components list doesn't match" + " length of footprints list.") + return False + + return True + + @staticmethod + def _texts(pcbdata): + for layer in pcbdata['drawings'].values(): + for side in layer.values(): + for dwg in side: + if 'text' in dwg: + yield dwg + + @staticmethod + def _remove_control_codes(s): + import unicodedata + return ''.join(c for c in s if unicodedata.category(c)[0] != "C") + + def _parse_font_data(self, pcbdata): + font_parser = FontParser() + for dwg in self._texts(pcbdata): + if 'svgpath' not in dwg: + dwg['text'] = self._remove_control_codes(dwg['text']) + font_parser.parse_font_for_string(dwg['text']) + + if font_parser.get_parsed_font(): + pcbdata['font_data'] = font_parser.get_parsed_font() + + def _check_font_data(self, pcbdata): + mc = set() + for dwg in self._texts(pcbdata): + dwg['text'] = self._remove_control_codes(dwg['text']) + mc.update({c for c in dwg['text'] if 'svgpath' not in dwg and + c not in pcbdata['font_data']}) + + if mc: + s = ''.join(mc) + self.logger.error('Provided font_data is missing character(s)' + f' "{s}" that are present in text drawing' + ' objects') + return False + else: + return True + + def _parse(self): + try: + pcb = self.get_generic_json_pcb() + except ValidationError as e: + self.logger.error('File {f} does not comply with json schema. {m}' + .format(f=self.file_name, m=e.message)) + return None, None + + if not self._verify(pcb): + self.logger.error('File {} does not appear to be valid generic' + ' InteractiveHtmlBom json file.' + .format(self.file_name)) + return None, None + + pcbdata = pcb['pcbdata'] + components = [Component(**c) for c in pcb['components']] + + if 'font_data' in pcbdata: + if not self._check_font_data(pcbdata): + raise ParsingException(f'Failed parsing {self.file_name}') + else: + self._parse_font_data(pcbdata) + if 'font_data' in pcbdata: + self.logger.info('No font_data provided in JSON, using ' + 'newstroke font') + + self.logger.info('Successfully parsed {}'.format(self.file_name)) + + return pcbdata, components + + def parse(self): + pcbdata, components = self._parse() + + # override board bounding box based on edges + board_outline_bbox = BoundingBox() + for drawing in pcbdata['edges']: + self.add_drawing_bounding_box(drawing, board_outline_bbox) + if board_outline_bbox.initialized(): + pcbdata['edges_bbox'] = board_outline_bbox.to_dict() + + extra_fields = set(self.config.show_fields) + extra_fields.discard("Footprint") + extra_fields.discard("Value") + if self.config.dnp_field: + extra_fields.add(self.config.dnp_field) + if self.config.board_variant_field: + extra_fields.add(self.config.board_variant_field) + if extra_fields: + for c in components: + c.extra_fields = { + f: c.extra_fields.get(f, "") for f in extra_fields} + + self.config.kicad_text_formatting = False + + return pcbdata, components diff --git a/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/ecad/kicad.py b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/ecad/kicad.py new file mode 100644 index 000000000..450a640fa --- /dev/null +++ b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/ecad/kicad.py @@ -0,0 +1,843 @@ +import os +from datetime import datetime + +import pcbnew + +from .common import EcadParser, Component, ExtraFieldData +from .kicad_extra import find_latest_schematic_data, parse_schematic_data +from .svgpath import create_path +from ..core import ibom +from ..core.config import Config +from ..core.fontparser import FontParser + + +class PcbnewParser(EcadParser): + + def __init__(self, file_name, config, logger, board=None): + super(PcbnewParser, self).__init__(file_name, config, logger) + self.board = board + if self.board is None: + self.board = pcbnew.LoadBoard(self.file_name) # type: pcbnew.BOARD + if hasattr(self.board, 'GetModules'): + self.footprints = list(self.board.GetModules()) + else: + self.footprints = list(self.board.GetFootprints()) + self.font_parser = FontParser() + + def get_extra_field_data(self, file_name): + if os.path.abspath(file_name) == os.path.abspath(self.file_name): + return self.parse_extra_data_from_pcb() + if os.path.splitext(file_name)[1] == '.kicad_pcb': + return None + + data = parse_schematic_data(file_name) + + return ExtraFieldData(data[0], data[1]) + + @staticmethod + def get_footprint_fields(f): + # type: (pcbnew.FOOTPRINT) -> dict + props = {} + if hasattr(f, "GetProperties"): + props = f.GetProperties() + if hasattr(f, "GetFields"): + props = f.GetFieldsShownText() + if "dnp" in props and props["dnp"] == "": + del props["dnp"] + props["kicad_dnp"] = "DNP" + if hasattr(f, "IsDNP"): + if f.IsDNP(): + props["kicad_dnp"] = "DNP" + return props + + def parse_extra_data_from_pcb(self): + field_set = set() + by_ref = {} + by_index = {} + + for (i, f) in enumerate(self.footprints): + props = self.get_footprint_fields(f) + by_index[i] = props + ref = f.GetReference() + ref_fields = by_ref.setdefault(ref, {}) + + for k, v in props.items(): + field_set.add(k) + ref_fields[k] = v + + return ExtraFieldData(list(field_set), by_ref, by_index) + + def latest_extra_data(self, extra_dirs=None): + base_name = os.path.splitext(os.path.basename(self.file_name))[0] + extra_dirs.append(self.board.GetPlotOptions().GetOutputDirectory()) + file_dir_name = os.path.dirname(self.file_name) + directories = [file_dir_name] + for dir in extra_dirs: + if not os.path.isabs(dir): + dir = os.path.join(file_dir_name, dir) + if os.path.exists(dir): + directories.append(dir) + return find_latest_schematic_data(base_name, directories) + + def extra_data_file_filter(self): + if hasattr(self.board, 'GetModules'): + return "Netlist and xml files (*.net; *.xml)|*.net;*.xml" + else: + return ("Netlist, xml and pcb files (*.net; *.xml; *.kicad_pcb)|" + "*.net;*.xml;*.kicad_pcb") + + @staticmethod + def normalize(point): + return [point.x * 1e-6, point.y * 1e-6] + + @staticmethod + def normalize_angle(angle): + if isinstance(angle, int) or isinstance(angle, float): + return angle * 0.1 + else: + return angle.AsDegrees() + + def get_arc_angles(self, d): + # type: (pcbnew.PCB_SHAPE) -> tuple + a1 = self.normalize_angle(d.GetArcAngleStart()) + if hasattr(d, "GetAngle"): + a2 = a1 + self.normalize_angle(d.GetAngle()) + else: + a2 = a1 + self.normalize_angle(d.GetArcAngle()) + if a2 < a1: + a1, a2 = a2, a1 + return round(a1, 2), round(a2, 2) + + def parse_shape(self, d): + # type: (pcbnew.PCB_SHAPE) -> dict or None + shape = { + pcbnew.S_SEGMENT: "segment", + pcbnew.S_CIRCLE: "circle", + pcbnew.S_ARC: "arc", + pcbnew.S_POLYGON: "polygon", + pcbnew.S_CURVE: "curve", + pcbnew.S_RECT: "rect", + }.get(d.GetShape(), "") + if shape == "": + self.logger.info("Unsupported shape %s, skipping", d.GetShape()) + return None + start = self.normalize(d.GetStart()) + end = self.normalize(d.GetEnd()) + if shape == "segment": + return { + "type": shape, + "start": start, + "end": end, + "width": d.GetWidth() * 1e-6 + } + + if shape == "rect": + if hasattr(d, "GetRectCorners"): + points = list(map(self.normalize, d.GetRectCorners())) + else: + points = [ + start, + [end[0], start[1]], + end, + [start[0], end[1]] + ] + shape_dict = { + "type": "polygon", + "pos": [0, 0], + "angle": 0, + "polygons": [points], + "width": d.GetWidth() * 1e-6, + "filled": 0 + } + if hasattr(d, "IsFilled") and d.IsFilled(): + shape_dict["filled"] = 1 + return shape_dict + + if shape == "circle": + shape_dict = { + "type": shape, + "start": start, + "radius": d.GetRadius() * 1e-6, + "width": d.GetWidth() * 1e-6 + } + if hasattr(d, "IsFilled") and d.IsFilled(): + shape_dict["filled"] = 1 + return shape_dict + + if shape == "arc": + a1, a2 = self.get_arc_angles(d) + if hasattr(d, "GetCenter"): + start = self.normalize(d.GetCenter()) + return { + "type": shape, + "start": start, + "radius": d.GetRadius() * 1e-6, + "startangle": a1, + "endangle": a2, + "width": d.GetWidth() * 1e-6 + } + + if shape == "polygon": + if hasattr(d, "GetPolyShape"): + polygons = self.parse_poly_set(d.GetPolyShape()) + else: + self.logger.info( + "Polygons not supported for KiCad 4, skipping") + return None + angle = 0 + if hasattr(d, 'GetParentModule'): + parent_footprint = d.GetParentModule() + else: + parent_footprint = d.GetParentFootprint() + if parent_footprint is not None: + angle = self.normalize_angle(parent_footprint.GetOrientation()) + shape_dict = { + "type": shape, + "pos": start, + "angle": angle, + "polygons": polygons + } + if hasattr(d, "IsFilled") and not d.IsFilled(): + shape_dict["filled"] = 0 + shape_dict["width"] = d.GetWidth() * 1e-6 + return shape_dict + if shape == "curve": + if hasattr(d, "GetBezierC1"): + c1 = self.normalize(d.GetBezierC1()) + c2 = self.normalize(d.GetBezierC2()) + else: + c1 = self.normalize(d.GetBezControl1()) + c2 = self.normalize(d.GetBezControl2()) + return { + "type": shape, + "start": start, + "cpa": c1, + "cpb": c2, + "end": end, + "width": d.GetWidth() * 1e-6 + } + + def parse_line_chain(self, shape): + # type: (pcbnew.SHAPE_LINE_CHAIN) -> list + result = [] + if not hasattr(shape, "PointCount"): + self.logger.warn("No PointCount method on outline object. " + "Unpatched kicad version?") + return result + + for point_index in range(shape.PointCount()): + result.append( + self.normalize(shape.CPoint(point_index))) + + return result + + def parse_poly_set(self, poly): + # type: (pcbnew.SHAPE_POLY_SET) -> list + result = [] + + for i in range(poly.OutlineCount()): + result.append(self.parse_line_chain(poly.Outline(i))) + + return result + + def parse_text(self, d): + # type: (pcbnew.PCB_TEXT) -> dict + if not d.IsVisible() and d.GetClass() not in ["PTEXT", "PCB_TEXT"]: + return None + pos = self.normalize(d.GetPosition()) + if hasattr(d, "GetTextThickness"): + thickness = d.GetTextThickness() * 1e-6 + else: + thickness = d.GetThickness() * 1e-6 + if hasattr(d, 'TransformToSegmentList'): + segments = [self.normalize(p) for p in d.TransformToSegmentList()] + lines = [] + for i in range(0, len(segments), 2): + if i == 0 or segments[i - 1] != segments[i]: + lines.append([segments[i]]) + lines[-1].append(segments[i + 1]) + return { + "thickness": thickness, + "svgpath": create_path(lines) + } + elif hasattr(d, 'GetEffectiveTextShape'): + shape = d.GetEffectiveTextShape(False) # type: pcbnew.SHAPE_COMPOUND + segments = [] + polygons = [] + for s in shape.GetSubshapes(): + if s.Type() == pcbnew.SH_LINE_CHAIN: + polygons.append(self.parse_line_chain(s)) + elif s.Type() == pcbnew.SH_SEGMENT: + seg = s.GetSeg() + segments.append( + [self.normalize(seg.A), self.normalize(seg.B)]) + else: + self.logger.warn( + "Unsupported subshape in text: %s" % s.Type()) + if segments: + return { + "thickness": thickness, + "svgpath": create_path(segments) + } + else: + return { + "polygons": polygons + } + + if d.GetClass() == "MTEXT": + angle = self.normalize_angle(d.GetDrawRotation()) + else: + if hasattr(d, "GetTextAngle"): + angle = self.normalize_angle(d.GetTextAngle()) + else: + angle = self.normalize_angle(d.GetOrientation()) + if hasattr(d, "GetTextHeight"): + height = d.GetTextHeight() * 1e-6 + width = d.GetTextWidth() * 1e-6 + else: + height = d.GetHeight() * 1e-6 + width = d.GetWidth() * 1e-6 + if hasattr(d, "GetShownText"): + text = d.GetShownText() + else: + text = d.GetText() + self.font_parser.parse_font_for_string(text) + attributes = [] + if d.IsMirrored(): + attributes.append("mirrored") + if d.IsItalic(): + attributes.append("italic") + if d.IsBold(): + attributes.append("bold") + + return { + "pos": pos, + "text": text, + "height": height, + "width": width, + "justify": [d.GetHorizJustify(), d.GetVertJustify()], + "thickness": thickness, + "attr": attributes, + "angle": angle + } + + def parse_dimension(self, d): + # type: (pcbnew.PCB_DIMENSION_BASE) -> dict + segments = [] + circles = [] + for s in d.GetShapes(): + s = s.Cast() + if s.Type() == pcbnew.SH_SEGMENT: + seg = s.GetSeg() + segments.append( + [self.normalize(seg.A), self.normalize(seg.B)]) + elif s.Type() == pcbnew.SH_CIRCLE: + circles.append( + [self.normalize(s.GetCenter()), s.GetRadius() * 1e-6]) + else: + self.logger.info( + "Unsupported shape type in dimension object: %s", s.Type()) + + svgpath = create_path(segments, circles=circles) + + return { + "thickness": d.GetLineThickness() * 1e-6, + "svgpath": svgpath + } + + def parse_drawing(self, d): + # type: (pcbnew.BOARD_ITEM) -> list + result = [] + s = None + if d.GetClass() in ["DRAWSEGMENT", "MGRAPHIC", "PCB_SHAPE"]: + s = self.parse_shape(d) + elif d.GetClass() in ["PTEXT", "MTEXT", "FP_TEXT", "PCB_TEXT", "PCB_FIELD"]: + s = self.parse_text(d) + elif (d.GetClass().startswith("PCB_DIM") + and hasattr(pcbnew, "VECTOR_SHAPEPTR")): + result.append(self.parse_dimension(d)) + if hasattr(d, "Text"): + s = self.parse_text(d.Text()) + else: + s = self.parse_text(d) + else: + self.logger.info("Unsupported drawing class %s, skipping", + d.GetClass()) + if s: + result.append(s) + return result + + def parse_edges(self, pcb): + edges = [] + drawings = list(pcb.GetDrawings()) + bbox = None + for f in self.footprints: + for g in f.GraphicalItems(): + drawings.append(g) + for d in drawings: + if d.GetLayer() == pcbnew.Edge_Cuts: + for parsed_drawing in self.parse_drawing(d): + edges.append(parsed_drawing) + if bbox is None: + bbox = d.GetBoundingBox() + else: + bbox.Merge(d.GetBoundingBox()) + if bbox: + bbox.Normalize() + return edges, bbox + + def parse_drawings_on_layers(self, drawings, f_layer, b_layer): + front = [] + back = [] + + for d in drawings: + if d[1].GetLayer() not in [f_layer, b_layer]: + continue + for drawing in self.parse_drawing(d[1]): + if d[0] in ["ref", "val"]: + drawing[d[0]] = 1 + if d[1].GetLayer() == f_layer: + front.append(drawing) + else: + back.append(drawing) + + return { + "F": front, + "B": back + } + + def get_all_drawings(self): + drawings = [(d.GetClass(), d) for d in list(self.board.GetDrawings())] + for f in self.footprints: + drawings.append(("ref", f.Reference())) + drawings.append(("val", f.Value())) + for d in f.GraphicalItems(): + drawings.append((d.GetClass(), d)) + return drawings + + def parse_pad(self, pad): + # type: (pcbnew.PAD) -> dict or None + layers_set = list(pad.GetLayerSet().Seq()) + layers = [] + if pcbnew.F_Cu in layers_set: + layers.append("F") + if pcbnew.B_Cu in layers_set: + layers.append("B") + pos = self.normalize(pad.GetPosition()) + size = self.normalize(pad.GetSize()) + angle = self.normalize_angle(pad.GetOrientation()) + shape_lookup = { + pcbnew.PAD_SHAPE_RECT: "rect", + pcbnew.PAD_SHAPE_OVAL: "oval", + pcbnew.PAD_SHAPE_CIRCLE: "circle", + } + if hasattr(pcbnew, "PAD_SHAPE_TRAPEZOID"): + shape_lookup[pcbnew.PAD_SHAPE_TRAPEZOID] = "trapezoid" + if hasattr(pcbnew, "PAD_SHAPE_ROUNDRECT"): + shape_lookup[pcbnew.PAD_SHAPE_ROUNDRECT] = "roundrect" + if hasattr(pcbnew, "PAD_SHAPE_CUSTOM"): + shape_lookup[pcbnew.PAD_SHAPE_CUSTOM] = "custom" + if hasattr(pcbnew, "PAD_SHAPE_CHAMFERED_RECT"): + shape_lookup[pcbnew.PAD_SHAPE_CHAMFERED_RECT] = "chamfrect" + shape = shape_lookup.get(pad.GetShape(), "") + if shape == "": + self.logger.info("Unsupported pad shape %s, skipping.", + pad.GetShape()) + return None + pad_dict = { + "layers": layers, + "pos": pos, + "size": size, + "angle": angle, + "shape": shape + } + if shape == "custom": + polygon_set = pad.GetCustomShapeAsPolygon() + if polygon_set.HasHoles(): + self.logger.warn('Detected holes in custom pad polygons') + pad_dict["polygons"] = self.parse_poly_set(polygon_set) + if shape == "trapezoid": + # treat trapezoid as custom shape + pad_dict["shape"] = "custom" + delta = self.normalize(pad.GetDelta()) + pad_dict["polygons"] = [[ + [size[0] / 2 + delta[1] / 2, size[1] / 2 - delta[0] / 2], + [-size[0] / 2 - delta[1] / 2, size[1] / 2 + delta[0] / 2], + [-size[0] / 2 + delta[1] / 2, -size[1] / 2 - delta[0] / 2], + [size[0] / 2 - delta[1] / 2, -size[1] / 2 + delta[0] / 2], + ]] + + if shape in ["roundrect", "chamfrect"]: + pad_dict["radius"] = pad.GetRoundRectCornerRadius() * 1e-6 + if shape == "chamfrect": + pad_dict["chamfpos"] = pad.GetChamferPositions() + pad_dict["chamfratio"] = pad.GetChamferRectRatio() + if hasattr(pcbnew, 'PAD_ATTRIB_PTH'): + through_hole_attributes = [pcbnew.PAD_ATTRIB_PTH, + pcbnew.PAD_ATTRIB_NPTH] + else: + through_hole_attributes = [pcbnew.PAD_ATTRIB_STANDARD, + pcbnew.PAD_ATTRIB_HOLE_NOT_PLATED] + if pad.GetAttribute() in through_hole_attributes: + pad_dict["type"] = "th" + pad_dict["drillshape"] = { + pcbnew.PAD_DRILL_SHAPE_CIRCLE: "circle", + pcbnew.PAD_DRILL_SHAPE_OBLONG: "oblong" + }.get(pad.GetDrillShape()) + pad_dict["drillsize"] = self.normalize(pad.GetDrillSize()) + else: + pad_dict["type"] = "smd" + if hasattr(pad, "GetOffset"): + pad_dict["offset"] = self.normalize(pad.GetOffset()) + if self.config.include_nets: + pad_dict["net"] = pad.GetNetname() + + return pad_dict + + def parse_footprints(self): + # type: () -> list + footprints = [] + for f in self.footprints: # type: pcbnew.FOOTPRINT + ref = f.GetReference() + + # bounding box + if hasattr(pcbnew, 'MODULE'): + f_copy = pcbnew.MODULE(f) + else: + f_copy = pcbnew.FOOTPRINT(f) + try: + f_copy.SetOrientation(0) + except TypeError: + f_copy.SetOrientation( + pcbnew.EDA_ANGLE(0, pcbnew.TENTHS_OF_A_DEGREE_T)) + pos = f_copy.GetPosition() + pos.x = pos.y = 0 + f_copy.SetPosition(pos) + if hasattr(f_copy, 'GetFootprintRect'): + footprint_rect = f_copy.GetFootprintRect() + else: + footprint_rect = f_copy.GetBoundingBox(False, False) + bbox = { + "pos": self.normalize(f.GetPosition()), + "relpos": self.normalize(footprint_rect.GetPosition()), + "size": self.normalize(footprint_rect.GetSize()), + "angle": self.normalize_angle(f.GetOrientation()), + } + + # graphical drawings + drawings = [] + for d in f.GraphicalItems(): + # we only care about copper ones, silkscreen is taken care of + if d.GetLayer() not in [pcbnew.F_Cu, pcbnew.B_Cu]: + continue + for drawing in self.parse_drawing(d): + drawings.append({ + "layer": "F" if d.GetLayer() == pcbnew.F_Cu else "B", + "drawing": drawing, + }) + + # footprint pads + pads = [] + for p in f.Pads(): + pad_dict = self.parse_pad(p) + if pad_dict is not None: + pads.append((p.GetPadName(), pad_dict)) + + if pads: + # Try to guess first pin name. + pads = sorted(pads, key=lambda el: el[0]) + pin1_pads = [p for p in pads if p[0] in + ['1', 'A', 'A1', 'P1', 'PAD1']] + if pin1_pads: + pin1_pad_name = pin1_pads[0][0] + else: + # No pads have common first pin name, + # pick lexicographically smallest. + pin1_pad_name = pads[0][0] + for pad_name, pad_dict in pads: + if pad_name == pin1_pad_name: + pad_dict['pin1'] = 1 + + pads = [p[1] for p in pads] + + # add footprint + footprints.append({ + "ref": ref, + "bbox": bbox, + "pads": pads, + "drawings": drawings, + "layer": { + pcbnew.F_Cu: "F", + pcbnew.B_Cu: "B" + }.get(f.GetLayer()) + }) + + return footprints + + def parse_tracks(self, tracks): + tent_vias = True + if hasattr(self.board, "GetTentVias"): + tent_vias = self.board.GetTentVias() + result = {pcbnew.F_Cu: [], pcbnew.B_Cu: []} + for track in tracks: + if track.GetClass() in ["VIA", "PCB_VIA"]: + track_dict = { + "start": self.normalize(track.GetStart()), + "end": self.normalize(track.GetEnd()), + "width": track.GetWidth() * 1e-6, + "net": track.GetNetname(), + } + if not tent_vias: + track_dict["drillsize"] = track.GetDrillValue() * 1e-6 + for layer in [pcbnew.F_Cu, pcbnew.B_Cu]: + if track.IsOnLayer(layer): + result[layer].append(track_dict) + else: + if track.GetLayer() in [pcbnew.F_Cu, pcbnew.B_Cu]: + if track.GetClass() in ["ARC", "PCB_ARC"]: + a1, a2 = self.get_arc_angles(track) + track_dict = { + "center": self.normalize(track.GetCenter()), + "startangle": a1, + "endangle": a2, + "radius": track.GetRadius() * 1e-6, + "width": track.GetWidth() * 1e-6, + } + else: + track_dict = { + "start": self.normalize(track.GetStart()), + "end": self.normalize(track.GetEnd()), + "width": track.GetWidth() * 1e-6, + } + if self.config.include_nets: + track_dict["net"] = track.GetNetname() + result[track.GetLayer()].append(track_dict) + + return { + 'F': result.get(pcbnew.F_Cu), + 'B': result.get(pcbnew.B_Cu) + } + + def parse_zones(self, zones): + result = {pcbnew.F_Cu: [], pcbnew.B_Cu: []} + for zone in zones: # type: pcbnew.ZONE + if (not zone.IsFilled() or + hasattr(zone, 'GetIsKeepout') and zone.GetIsKeepout() or + hasattr(zone, 'GetIsRuleArea') and zone.GetIsRuleArea()): + continue + layers = [layer for layer in list(zone.GetLayerSet().Seq()) + if layer in [pcbnew.F_Cu, pcbnew.B_Cu]] + for layer in layers: + try: + # kicad 5.1 and earlier + poly_set = zone.GetFilledPolysList() + except TypeError: + poly_set = zone.GetFilledPolysList(layer) + width = zone.GetMinThickness() * 1e-6 + if (hasattr(zone, 'GetFilledPolysUseThickness') and + not zone.GetFilledPolysUseThickness()): + width = 0 + zone_dict = { + "polygons": self.parse_poly_set(poly_set), + "width": width, + } + if self.config.include_nets: + zone_dict["net"] = zone.GetNetname() + result[layer].append(zone_dict) + + return { + 'F': result.get(pcbnew.F_Cu), + 'B': result.get(pcbnew.B_Cu) + } + + @staticmethod + def parse_netlist(net_info): + # type: (pcbnew.NETINFO_LIST) -> list + nets = net_info.NetsByName().asdict().keys() + nets = sorted([str(s) for s in nets]) + return nets + + @staticmethod + def footprint_to_component(footprint, extra_fields): + try: + footprint_name = str(footprint.GetFPID().GetFootprintName()) + except AttributeError: + footprint_name = str(footprint.GetFPID().GetLibItemName()) + + attr = 'Normal' + if hasattr(pcbnew, 'FP_EXCLUDE_FROM_BOM'): + if footprint.GetAttributes() & pcbnew.FP_EXCLUDE_FROM_BOM: + attr = 'Virtual' + elif hasattr(pcbnew, 'MOD_VIRTUAL'): + if footprint.GetAttributes() == pcbnew.MOD_VIRTUAL: + attr = 'Virtual' + layer = { + pcbnew.F_Cu: 'F', + pcbnew.B_Cu: 'B', + }.get(footprint.GetLayer()) + + return Component(footprint.GetReference(), + footprint.GetValue(), + footprint_name, + layer, + attr, + extra_fields) + + def parse(self): + from ..errors import ParsingException + + # Get extra field data from netlist + field_set = set(self.config.show_fields) + field_set.discard("Value") + field_set.discard("Footprint") + need_extra_fields = (field_set or + self.config.board_variant_whitelist or + self.config.board_variant_blacklist or + self.config.dnp_field) + + if not self.config.extra_data_file and need_extra_fields: + self.logger.warn('Ignoring extra fields related config parameters ' + 'since no netlist/xml file was specified.') + need_extra_fields = False + + extra_field_data = None + if (self.config.extra_data_file and + os.path.isfile(self.config.extra_data_file)): + extra_field_data = self.parse_extra_data( + self.config.extra_data_file, self.config.normalize_field_case) + + if extra_field_data is None and need_extra_fields: + raise ParsingException( + 'Failed parsing %s' % self.config.extra_data_file) + + title_block = self.board.GetTitleBlock() + title = title_block.GetTitle() + revision = title_block.GetRevision() + company = title_block.GetCompany() + file_date = title_block.GetDate() + if (hasattr(self.board, "GetProject") and + hasattr(pcbnew, "ExpandTextVars")): + project = self.board.GetProject() + title = pcbnew.ExpandTextVars(title, project) + revision = pcbnew.ExpandTextVars(revision, project) + company = pcbnew.ExpandTextVars(company, project) + file_date = pcbnew.ExpandTextVars(file_date, project) + + if not file_date: + file_mtime = os.path.getmtime(self.file_name) + file_date = datetime.fromtimestamp(file_mtime).strftime( + '%Y-%m-%d %H:%M:%S') + pcb_file_name = os.path.basename(self.file_name) + if not title: + # remove .kicad_pcb extension + title = os.path.splitext(pcb_file_name)[0] + edges, bbox = self.parse_edges(self.board) + if bbox is None: + self.logger.error('Please draw pcb outline on the edges ' + 'layer on sheet or any footprint before ' + 'generating BOM.') + return None, None + bbox = { + "minx": bbox.GetPosition().x * 1e-6, + "miny": bbox.GetPosition().y * 1e-6, + "maxx": bbox.GetRight() * 1e-6, + "maxy": bbox.GetBottom() * 1e-6, + } + + drawings = self.get_all_drawings() + + pcbdata = { + "edges_bbox": bbox, + "edges": edges, + "drawings": { + "silkscreen": self.parse_drawings_on_layers( + drawings, pcbnew.F_SilkS, pcbnew.B_SilkS), + "fabrication": self.parse_drawings_on_layers( + drawings, pcbnew.F_Fab, pcbnew.B_Fab), + }, + "footprints": self.parse_footprints(), + "metadata": { + "title": title, + "revision": revision, + "company": company, + "date": file_date, + }, + "bom": {}, + "font_data": self.font_parser.get_parsed_font() + } + if self.config.include_tracks: + pcbdata["tracks"] = self.parse_tracks(self.board.GetTracks()) + if hasattr(self.board, "Zones"): + pcbdata["zones"] = self.parse_zones(self.board.Zones()) + else: + self.logger.info("Zones not supported for KiCad 4, skipping") + pcbdata["zones"] = {'F': [], 'B': []} + if self.config.include_nets and hasattr(self.board, "GetNetInfo"): + pcbdata["nets"] = self.parse_netlist(self.board.GetNetInfo()) + + if extra_field_data and need_extra_fields: + extra_fields = extra_field_data.fields_by_index + if extra_fields: + extra_fields = extra_fields.values() + + if extra_fields is None: + extra_fields = [] + field_map = extra_field_data.fields_by_ref + warning_shown = False + + for f in self.footprints: + extra_fields.append(field_map.get(f.GetReference(), {})) + if f.GetReference() not in field_map: + # Some components are on pcb but not in schematic data. + # Show a warning about outdated extra data file. + self.logger.warn( + 'Component %s is missing from schematic data.' + % f.GetReference()) + warning_shown = True + + if warning_shown: + self.logger.warn('Netlist/xml file is likely out of date.') + else: + extra_fields = [{}] * len(self.footprints) + + components = [self.footprint_to_component(f, e) + for (f, e) in zip(self.footprints, extra_fields)] + + return pcbdata, components + + +class InteractiveHtmlBomPlugin(pcbnew.ActionPlugin, object): + + def __init__(self): + super(InteractiveHtmlBomPlugin, self).__init__() + self.name = "Generate Interactive HTML BOM" + self.category = "Read PCB" + self.pcbnew_icon_support = hasattr(self, "show_toolbar_button") + self.show_toolbar_button = True + icon_dir = os.path.dirname(os.path.dirname(__file__)) + self.icon_file_name = os.path.join(icon_dir, 'icon.png') + self.description = "Generate interactive HTML page with BOM " \ + "table and pcb drawing." + + def defaults(self): + pass + + def Run(self): + from ..version import version + from ..errors import ParsingException + + logger = ibom.Logger() + board = pcbnew.GetBoard() + pcb_file_name = board.GetFileName() + + if not pcb_file_name: + logger.error('Please save the board file before generating BOM.') + return + + config = Config(version, os.path.dirname(pcb_file_name)) + parser = PcbnewParser(pcb_file_name, config, logger, board) + + try: + ibom.run_with_dialog(parser, config, logger) + except ParsingException as e: + logger.error(str(e)) diff --git a/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/ecad/kicad_extra/__init__.py b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/ecad/kicad_extra/__init__.py new file mode 100644 index 000000000..453b40230 --- /dev/null +++ b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/ecad/kicad_extra/__init__.py @@ -0,0 +1,59 @@ +import os +import pcbnew + +from .xmlparser import XmlParser +from .netlistparser import NetlistParser + +PARSERS = { + '.xml': XmlParser, + '.net': NetlistParser, +} + + +if hasattr(pcbnew, 'FOOTPRINT'): + PARSERS['.kicad_pcb'] = None + + +def parse_schematic_data(file_name): + if not os.path.isfile(file_name): + return None + extension = os.path.splitext(file_name)[1] + if extension not in PARSERS: + return None + else: + parser_cls = PARSERS[extension] + if parser_cls is None: + return None + parser = parser_cls(file_name) + return parser.get_extra_field_data() + + +def find_latest_schematic_data(base_name, directories): + """ + :param base_name: base name of pcb file + :param directories: list of directories to search + :return: last modified parsable file path or None if not found + """ + files = [] + for d in directories: + files.extend(_find_in_dir(d)) + # sort by decreasing modification time + files = sorted(files, reverse=True) + if files: + # try to find first (last modified) file that has name matching pcb file + for _, f in files: + if os.path.splitext(os.path.basename(f))[0] == base_name: + return f + # if no such file is found just return last modified + return files[0][1] + else: + return None + + +def _find_in_dir(dir): + _, _, files = next(os.walk(dir), (None, None, [])) + # filter out files that we can not parse + files = [f for f in files if os.path.splitext(f)[1] in PARSERS.keys()] + files = [os.path.join(dir, f) for f in files] + # get their modification time and sort in descending order + return [(os.path.getmtime(f), f) for f in files] diff --git a/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/ecad/kicad_extra/netlistparser.py b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/ecad/kicad_extra/netlistparser.py new file mode 100644 index 000000000..df52d9bea --- /dev/null +++ b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/ecad/kicad_extra/netlistparser.py @@ -0,0 +1,59 @@ +import io + +from .parser_base import ParserBase +from .sexpressions import parse_sexpression + + +class NetlistParser(ParserBase): + def get_extra_field_data(self): + with io.open(self.file_name, 'r', encoding='utf-8') as f: + sexpression = parse_sexpression(f.read()) + components = None + for s in sexpression: + if s[0] == 'components': + components = s[1:] + if components is None: + return None + field_set = set() + comp_dict = {} + for c in components: + ref = None + fields = None + datasheet = None + libsource = None + dnp = False + for f in c[1:]: + if f[0] == 'ref': + ref = f[1] + if f[0] == 'fields': + fields = f[1:] + if f[0] == 'datasheet': + datasheet = f[1] + if f[0] == 'libsource': + libsource = f[1:] + if f[0] == 'property' and isinstance(f[1], list) and \ + f[1][0] == 'name' and f[1][1] == 'dnp': + dnp = True + if ref is None: + return None + ref_fields = comp_dict.setdefault(ref, {}) + if datasheet and datasheet != '~': + field_set.add('Datasheet') + ref_fields['Datasheet'] = datasheet + if libsource is not None: + for lib_field in libsource: + if lib_field[0] == 'description': + field_set.add('Description') + ref_fields['Description'] = lib_field[1] + if dnp: + field_set.add('kicad_dnp') + ref_fields['kicad_dnp'] = "DNP" + if fields is None: + continue + for f in fields: + if len(f) > 1: + field_set.add(f[1][1]) + if len(f) > 2: + ref_fields[f[1][1]] = f[2] + + return list(field_set), comp_dict diff --git a/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/ecad/kicad_extra/parser_base.py b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/ecad/kicad_extra/parser_base.py new file mode 100644 index 000000000..5dfce9338 --- /dev/null +++ b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/ecad/kicad_extra/parser_base.py @@ -0,0 +1,26 @@ +class ParserBase: + + def __init__(self, file_name): + """ + :param file_name: path to file that should be parsed. + """ + self.file_name = file_name + + def get_extra_field_data(self): + # type: () -> tuple + """ + Parses the file and returns extra field data. + :return: tuple of the format + ( + [field_name1, field_name2,... ], + { + ref1: { + field_name1: field_value1, + field_name2: field_value2, + ... + ], + ref2: ... + } + ) + """ + pass diff --git a/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/ecad/kicad_extra/sexpressions.py b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/ecad/kicad_extra/sexpressions.py new file mode 100644 index 000000000..adda3f259 --- /dev/null +++ b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/ecad/kicad_extra/sexpressions.py @@ -0,0 +1,32 @@ +import re + +term_regex = r'''(?mx) + \s*(?: + (?P\()| + (?P\))| + (?P"(?:\\\\|\\"|[^"])*")| + (?P[^(^)\s]+) + )''' +pattern = re.compile(term_regex) + + +def parse_sexpression(sexpression): + stack = [] + out = [] + for terms in pattern.finditer(sexpression): + term, value = [(t, v) for t, v in terms.groupdict().items() if v][0] + if term == 'open': + stack.append(out) + out = [] + elif term == 'close': + assert stack, "Trouble with nesting of brackets" + tmp, out = out, stack.pop(-1) + out.append(tmp) + elif term == 'sq': + out.append(value[1:-1].replace('\\\\', '\\').replace('\\"', '"')) + elif term == 's': + out.append(value) + else: + raise NotImplementedError("Error: %s, %s" % (term, value)) + assert not stack, "Trouble with nesting of brackets" + return out[0] diff --git a/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/ecad/kicad_extra/xmlparser.py b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/ecad/kicad_extra/xmlparser.py new file mode 100644 index 000000000..9303bb6a1 --- /dev/null +++ b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/ecad/kicad_extra/xmlparser.py @@ -0,0 +1,42 @@ +from xml.dom import minidom + +from .parser_base import ParserBase + + +class XmlParser(ParserBase): + @staticmethod + def get_text(nodelist): + rc = [] + for node in nodelist: + if node.nodeType == node.TEXT_NODE: + rc.append(node.data) + return ''.join(rc) + + def get_extra_field_data(self): + xml = minidom.parse(self.file_name) + components = xml.getElementsByTagName('comp') + field_set = set() + comp_dict = {} + for c in components: + ref_fields = comp_dict.setdefault(c.attributes['ref'].value, {}) + datasheet = c.getElementsByTagName('datasheet') + if datasheet: + datasheet = self.get_text(datasheet[0].childNodes) + if datasheet != '~': + field_set.add('Datasheet') + ref_fields['Datasheet'] = datasheet + libsource = c.getElementsByTagName('libsource') + if libsource and libsource[0].hasAttribute('description'): + field_set.add('Description') + attr = libsource[0].attributes['description'] + ref_fields['Description'] = attr.value + for f in c.getElementsByTagName('field'): + name = f.attributes['name'].value + field_set.add(name) + ref_fields[name] = self.get_text(f.childNodes) + for f in c.getElementsByTagName('property'): + if f.attributes['name'].value == 'dnp': + field_set.add('kicad_dnp') + ref_fields['kicad_dnp'] = "DNP" + + return list(field_set), comp_dict diff --git a/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/ecad/schema/genericjsonpcbdata_v1.schema b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/ecad/schema/genericjsonpcbdata_v1.schema new file mode 100644 index 000000000..3f60c6fac --- /dev/null +++ b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/ecad/schema/genericjsonpcbdata_v1.schema @@ -0,0 +1,638 @@ +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "$ref": "#/definitions/GenericJSONPCBData", + "definitions": { + "GenericJSONPCBData": { + "type": "object", + "additionalProperties": false, + "properties": { + "spec_version": { + "type": "integer" + }, + "pcbdata": { + "$ref": "#/definitions/Pcbdata" + }, + "components": { + "type": "array", + "items": { + "$ref": "#/definitions/Component" + } + } + }, + "required": [ + "spec_version", + "pcbdata", + "components" + ], + "title": "GenericJSONPCBData" + }, + "Component": { + "type": "object", + "additionalProperties": false, + "properties": { + "attr": { + "type": "string" + }, + "footprint": { + "type": "string" + }, + "layer": { + "$ref": "#/definitions/Layer" + }, + "ref": { + "type": "string" + }, + "val": { + "type": "string" + }, + "extra_fields": { + "$ref": "#/definitions/ExtraData" + } + }, + "required": [ + "footprint", + "layer", + "ref", + "val" + ], + "title": "Component" + }, + "Pcbdata": { + "type": "object", + "additionalProperties": false, + "properties": { + "edges_bbox": { + "$ref": "#/definitions/EdgesBbox" + }, + "edges": { + "$ref": "#/definitions/DrawingArray" + }, + "drawings": { + "$ref": "#/definitions/LayerDrawings" + }, + "footprints": { + "type": "array", + "items": { + "$ref": "#/definitions/Footprint" + } + }, + "metadata": { + "$ref": "#/definitions/Metadata" + }, + "tracks": { + "$ref": "#/definitions/Tracks" + }, + "zones": { + "$ref": "#/definitions/Zones" + }, + "nets": { + "type": "array", + "items": { "type": "string" } + }, + "font_data": { + "$ref": "#/definitions/FontData" + } + }, + "required": [ + "edges_bbox", + "edges", + "drawings", + "footprints", + "metadata" + ], + "dependencies": { + "tracks": { "required": ["zones"] }, + "zones": { "required": ["tracks"] } + }, + "title": "Pcbdata" + }, + "EdgesBbox": { + "type": "object", + "additionalProperties": false, + "properties": { + "minx": { + "type": "number" + }, + "miny": { + "type": "number" + }, + "maxx": { + "type": "number" + }, + "maxy": { + "type": "number" + } + }, + "required": ["minx", "miny", "maxx", "maxy"], + "title": "EdgesBbox" + }, + "DrawingSet": { + "type": "object", + "additionalProperties": false, + "properties": { + "F": { + "$ref": "#/definitions/DrawingArray" + }, + "B": { + "$ref": "#/definitions/DrawingArray" + } + }, + "required": ["F", "B"], + "title": "DrawingSet" + }, + "Footprint": { + "type": "object", + "additionalProperties": false, + "properties": { + "ref": { + "type": "string" + }, + "center": { + "$ref": "#/definitions/Coordinates" + }, + "bbox": { + "$ref": "#/definitions/Bbox" + }, + "pads": { + "type": "array", + "items": { + "$ref": "#/definitions/Pad" + } + }, + "drawings": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "layer": { "$ref": "#/definitions/Layer" }, + "drawing": { "$ref": "#/definitions/Drawing" } + }, + "required": [ "layer", "drawing" ] + } + }, + "layer": { + "$ref": "#/definitions/Layer" + } + }, + "required": ["ref", "center", "bbox", "pads", "drawings", "layer"], + "title": "Footprint" + }, + "Bbox": { + "type": "object", + "additionalProperties": false, + "properties": { + "pos": { + "$ref": "#/definitions/Coordinates" + }, + "relpos": { + "$ref": "#/definitions/Coordinates" + }, + "size": { + "$ref": "#/definitions/Coordinates" + }, + "angle": { + "type": "number" + } + }, + "required": ["pos", "relpos", "size", "angle"], + "title": "Bbox" + }, + "Pad": { + "type": "object", + "additionalProperties": false, + "properties": { + "layers": { + "type": "array", + "items": { + "$ref": "#/definitions/Layer" + }, + "minItems": 1, + "maxItems": 2 + }, + "pos": { + "$ref": "#/definitions/Coordinates" + }, + "size": { + "$ref": "#/definitions/Coordinates" + }, + "angle": { + "type": "number" + }, + "shape": { + "$ref": "#/definitions/Shape" + }, + "svgpath": { "type": "string" }, + "polygons": { "$ref": "#/definitions/Polygons" }, + "radius": { "type": "number" }, + "chamfpos": { "type": "integer" }, + "chamfratio": { "type": "number" }, + "type": { + "$ref": "#/definitions/PadType" + }, + "pin1": { + "type": "integer", "const": 1 + }, + "drillshape": { + "$ref": "#/definitions/Drillshape" + }, + "drillsize": { + "$ref": "#/definitions/Coordinates" + }, + "offset": { + "$ref": "#/definitions/Coordinates" + }, + "net": { "type": "string" } + }, + "required": [ + "layers", + "pos", + "size", + "shape", + "type" + ], + "allOf": [ + { + "if": { + "properties": { "shape": { "const": "custom" } } + }, + "then": { + "anyOf": [ + { "required": [ "svgpath" ] }, + { "required": [ "pos", "angle", "polygons" ] } + ] + } + }, + { + "if": { + "properties": { "shape": { "const": "roundrect" } } + }, + "then": { + "required": [ "radius" ] + } + }, + { + "if": { + "properties": { "shape": { "const": "chamfrect" } } + }, + "then": { + "required": [ "radius", "chamfpos", "chamfratio" ] + } + }, + { + "if": { + "properties": { "type": { "const": "th" } } + }, + "then": { + "required": [ "drillshape", "drillsize" ] + } + } + ], + "title": "Pad" + }, + "Metadata": { + "type": "object", + "additionalProperties": false, + "properties": { + "title": { + "type": "string" + }, + "revision": { + "type": "string" + }, + "company": { + "type": "string" + }, + "date": { + "type": "string" + } + }, + "required": ["title", "revision", "company", "date"], + "title": "Metadata" + }, + "LayerDrawings": { + "type": "object", + "items": { + "silkscreen": { + "$ref": "#/definitions/DrawingSet" + }, + "fabrication": { + "$ref": "#/definitions/DrawingSet" + } + } + }, + "DrawingArray": { + "type": "array", + "items": { + "$ref": "#/definitions/Drawing" + } + }, + "Drawing": { + "type": "object", + "oneOf": [ + { "$ref": "#/definitions/DrawingSegment" }, + { "$ref": "#/definitions/DrawingRect" }, + { "$ref": "#/definitions/DrawingCircle" }, + { "$ref": "#/definitions/DrawingArc" }, + { "$ref": "#/definitions/DrawingCurve" }, + { "$ref": "#/definitions/DrawingPolygon" }, + { "$ref": "#/definitions/DrawingText" } + ] + }, + "DrawingSegment": { + "type": "object", + "additionalProperties": false, + "properties": { + "type": { "type": "string", "const": "segment" }, + "start": { "$ref": "#/definitions/Coordinates" }, + "end": { "$ref": "#/definitions/Coordinates" }, + "width": { "type": "number" } + }, + "required": ["type", "start", "end", "width"], + "title": "DrawingSegment" + }, + "DrawingRect": { + "type": "object", + "additionalProperties": false, + "properties": { + "type": { "const": "rect" }, + "start": { "$ref": "#/definitions/Coordinates" }, + "end": { "$ref": "#/definitions/Coordinates" }, + "width": { "type": "number" } + }, + "required": ["type", "start", "end", "width"], + "title": "DrawingRect" + }, + "DrawingCircle": { + "type": "object", + "additionalProperties": false, + "properties": { + "type": { "const": "circle" }, + "start": { "$ref": "#/definitions/Coordinates" }, + "radius": { "type": "number" }, + "filled": { "type": "integer" }, + "width": { "type": "number" } + }, + "required": ["type", "start", "radius", "width"], + "title": "DrawingCircle" + }, + "DrawingArc": { + "type": "object", + "additionalProperties": false, + "properties": { + "type": { "const": "arc" }, + "width": { "type": "number" }, + "svgpath": { "type": "string" }, + "start": { "$ref": "#/definitions/Coordinates" }, + "radius": { "type": "number" }, + "startangle": { "type": "number" }, + "endangle": { "type": "number" } + }, + "required": [ + "type", + "width" + ], + "anyOf": [ + { "required": ["svgpath"] }, + { "required": ["start", "radius", "startangle", "endangle"] } + ], + "title": "DrawingArc" + }, + "DrawingCurve": { + "type": "object", + "additionalProperties": false, + "properties": { + "type": { "const": "curve" }, + "start": { "$ref": "#/definitions/Coordinates" }, + "end": { "$ref": "#/definitions/Coordinates" }, + "cpa": { "$ref": "#/definitions/Coordinates" }, + "cpb": { "$ref": "#/definitions/Coordinates" }, + "width": { "type": "number" } + }, + "required": ["type", "start", "end", "cpa", "cpb", "width"], + "title": "DrawingCurve" + }, + "DrawingPolygon": { + "type": "object", + "additionalProperties": false, + "properties": { + "type": { "const": "polygon" }, + "filled": { "type": "integer" }, + "width": { "type": "number" }, + "svgpath": { "type": "string" }, + "pos": { "$ref": "#/definitions/Coordinates" }, + "angle": { "type": "number" }, + "polygons": { + "type": "array", + "items": { + "type": "array", + "items": { "$ref": "#/definitions/Coordinates" } + } + } + }, + "required": ["type"], + "anyOf": [ + { "required": ["svgpath"] }, + { "required": ["pos", "angle", "polygons"] } + ], + "title": "DrawingPolygon" + }, + "DrawingText": { + "type": "object", + "additionalProperties": false, + "properties": { + "svgpath": { "type": "string" }, + "thickness": { "type": "number" }, + "ref": { "type": "integer" , "const": 1 }, + "val": { "type": "integer" , "const": 1 } + }, + "required": [ + "svgpath", + "thickness" + ], + "title": "DrawingText" + }, + "Coordinates": { + "type": "array", + "items": { "type": "number" }, + "minItems": 2, + "maxItems": 2 + }, + "Drillshape": { + "type": "string", + "enum": [ + "circle", + "oblong" + ], + "title": "Drillshape" + }, + "Layer": { + "type": "string", + "enum": [ + "B", + "F" + ], + "title": "Layer" + }, + "Shape": { + "type": "string", + "enum": [ + "rect", + "circle", + "oval", + "roundrect", + "chamfrect", + "custom" + ], + "title": "Shape" + }, + "PadType": { + "type": "string", + "enum": [ + "smd", + "th" + ], + "title": "PadType" + }, + "Tracks": { + "type": "object", + "additionalProperties": false, + "properties": { + "F": { + "type": "array", + "items": { "$ref": "#/definitions/Track" } + }, + "B": { + "type": "array", + "items": { "$ref": "#/definitions/Track" } + } + }, + "required": [ "F", "B" ], + "title": "Tracks" + }, + "Track": { + "type": "object", + "oneOf":[ + { + "additionalProperties": false, + "properties": { + "start": { "$ref": "#/definitions/Coordinates" }, + "end": { "$ref": "#/definitions/Coordinates" }, + "width": { "type": "number" }, + "drillsize": { "type": "number" }, + "net": { "type": "string" } + }, + "required": [ + "start", + "end", + "width" + ] + }, + { + "additionalProperties": false, + "properties": { + "center": { "$ref": "#/definitions/Coordinates" }, + "startangle": { "type": "number" }, + "endangle": { "type": "number" }, + "radius": { "type": "number" }, + "width": { "type": "number" }, + "net": { "type": "string" } + }, + "required": [ + "center", + "startangle", + "endangle", + "radius", + "width" + ] + } + ] + }, + "Zones": { + "type": "object", + "additionalProperties": false, + "properties": { + "F": { + "type": "array", + "items": { "$ref": "#/definitions/Zone" } + }, + "B": { + "type": "array", + "items": { "$ref": "#/definitions/Zone" } + } + }, + "required": [ "F", "B" ], + "title": "Zones" + }, + "Zone": { + "type": "object", + "additionalProperties": false, + "properties": { + "svgpath": { "type": "string" }, + "polygons": { + "$ref": "#/definitions/Polygons" + }, + "net": { "type": "string" }, + "fillrule": { + "type": "string", + "enum": [ + "nonzero", + "evenodd" + ] + } + }, + "anyOf": [ + { "required": [ "svgpath" ] }, + { "required": [ "polygons" ] } + ], + "title": "Zone" + }, + "Polygons": { + "type": "array", + "items": { + "type": "array", + "items": { + "$ref": "#/definitions/Coordinates" + } + } + }, + "PolyLineArray": { + "$ref": "#/definitions/Polygons" + }, + "ReferenceSet": { + "type": "array", + "items": { + "type": "array", + "items": [ + { "type": "string" }, + { "type": "integer" } + ], + "additionalItems": false + } + }, + "ExtraData": { + "type": "object", + "additionalProperties": true, + "properties": { + }, + "title": "ExtraData" + }, + "FontData": { + "type": "object", + "patternProperties": { + "^.$" : { + "type": "object", + "properties": { + "w": { "type": "number" }, + "l": { "$ref": "#/definitions/PolyLineArray" } + }, + "additionalProperties" : false, + "required": [ + "w", + "l" + ] + } + } + } + } +} diff --git a/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/ecad/svgpath.py b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/ecad/svgpath.py new file mode 100644 index 000000000..6f0a87ea8 --- /dev/null +++ b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/ecad/svgpath.py @@ -0,0 +1,538 @@ +"""This submodule contains very stripped down bare bones version of +svgpathtools module: +https://github.com/mathandy/svgpathtools + +All external dependencies are removed. This code can parse path strings with +segments and arcs, calculate bounding box and that's about it. This is all +that is needed in ibom parsers at the moment. +""" + +# External dependencies +from __future__ import division, absolute_import, print_function + +import re +from cmath import exp +from math import sqrt, cos, sin, acos, degrees, radians, pi + + +def clip(a, a_min, a_max): + return min(a_max, max(a_min, a)) + + +class Line(object): + def __init__(self, start, end): + self.start = start + self.end = end + + def __repr__(self): + return 'Line(start=%s, end=%s)' % (self.start, self.end) + + def __eq__(self, other): + if not isinstance(other, Line): + return NotImplemented + return self.start == other.start and self.end == other.end + + def __ne__(self, other): + if not isinstance(other, Line): + return NotImplemented + return not self == other + + def __len__(self): + return 2 + + def bbox(self): + """returns the bounding box for the segment in the form + (xmin, xmax, ymin, ymax).""" + xmin = min(self.start.real, self.end.real) + xmax = max(self.start.real, self.end.real) + ymin = min(self.start.imag, self.end.imag) + ymax = max(self.start.imag, self.end.imag) + return xmin, xmax, ymin, ymax + + +class Arc(object): + def __init__(self, start, radius, rotation, large_arc, sweep, end, + autoscale_radius=True): + """ + This should be thought of as a part of an ellipse connecting two + points on that ellipse, start and end. + Parameters + ---------- + start : complex + The start point of the curve. Note: `start` and `end` cannot be the + same. To make a full ellipse or circle, use two `Arc` objects. + radius : complex + rx + 1j*ry, where rx and ry are the radii of the ellipse (also + known as its semi-major and semi-minor axes, or vice-versa or if + rx < ry). + Note: If rx = 0 or ry = 0 then this arc is treated as a + straight line segment joining the endpoints. + Note: If rx or ry has a negative sign, the sign is dropped; the + absolute value is used instead. + Note: If no such ellipse exists, the radius will be scaled so + that one does (unless autoscale_radius is set to False). + rotation : float + This is the CCW angle (in degrees) from the positive x-axis of the + current coordinate system to the x-axis of the ellipse. + large_arc : bool + Given two points on an ellipse, there are two elliptical arcs + connecting those points, the first going the short way around the + ellipse, and the second going the long way around the ellipse. If + `large_arc == False`, the shorter elliptical arc will be used. If + `large_arc == True`, then longer elliptical will be used. + In other words, `large_arc` should be 0 for arcs spanning less than + or equal to 180 degrees and 1 for arcs spanning greater than 180 + degrees. + sweep : bool + For any acceptable parameters `start`, `end`, `rotation`, and + `radius`, there are two ellipses with the given major and minor + axes (radii) which connect `start` and `end`. One which connects + them in a CCW fashion and one which connected them in a CW + fashion. If `sweep == True`, the CCW ellipse will be used. If + `sweep == False`, the CW ellipse will be used. See note on curve + orientation below. + end : complex + The end point of the curve. Note: `start` and `end` cannot be the + same. To make a full ellipse or circle, use two `Arc` objects. + autoscale_radius : bool + If `autoscale_radius == True`, then will also scale `self.radius` + in the case that no ellipse exists with the input parameters + (see inline comments for further explanation). + + Derived Parameters/Attributes + ----------------------------- + self.theta : float + This is the phase (in degrees) of self.u1transform(self.start). + It is $\\theta_1$ in the official documentation and ranges from + -180 to 180. + self.delta : float + This is the angular distance (in degrees) between the start and + end of the arc after the arc has been sent to the unit circle + through self.u1transform(). + It is $\\Delta\\theta$ in the official documentation and ranges + from -360 to 360; being positive when the arc travels CCW and + negative otherwise (i.e. is positive/negative when + sweep == True/False). + self.center : complex + This is the center of the arc's ellipse. + self.phi : float + The arc's rotation in radians, i.e. `radians(self.rotation)`. + self.rot_matrix : complex + Equal to `exp(1j * self.phi)` which is also equal to + `cos(self.phi) + 1j*sin(self.phi)`. + + + Note on curve orientation (CW vs CCW) + ------------------------------------- + The notions of clockwise (CW) and counter-clockwise (CCW) are reversed + in some sense when viewing SVGs (as the y coordinate starts at the top + of the image and increases towards the bottom). + """ + assert start != end + assert radius.real != 0 and radius.imag != 0 + + self.start = start + self.radius = abs(radius.real) + 1j * abs(radius.imag) + self.rotation = rotation + self.large_arc = bool(large_arc) + self.sweep = bool(sweep) + self.end = end + self.autoscale_radius = autoscale_radius + + # Convenience parameters + self.phi = radians(self.rotation) + self.rot_matrix = exp(1j * self.phi) + + # Derive derived parameters + self._parameterize() + + def __repr__(self): + params = (self.start, self.radius, self.rotation, + self.large_arc, self.sweep, self.end) + return ("Arc(start={}, radius={}, rotation={}, " + "large_arc={}, sweep={}, end={})".format(*params)) + + def __eq__(self, other): + if not isinstance(other, Arc): + return NotImplemented + return self.start == other.start and self.end == other.end \ + and self.radius == other.radius \ + and self.rotation == other.rotation \ + and self.large_arc == other.large_arc and self.sweep == other.sweep + + def __ne__(self, other): + if not isinstance(other, Arc): + return NotImplemented + return not self == other + + def _parameterize(self): + # See http://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes + # my notation roughly follows theirs + rx = self.radius.real + ry = self.radius.imag + rx_sqd = rx * rx + ry_sqd = ry * ry + + # Transform z-> z' = x' + 1j*y' + # = self.rot_matrix**(-1)*(z - (end+start)/2) + # coordinates. This translates the ellipse so that the midpoint + # between self.end and self.start lies on the origin and rotates + # the ellipse so that the its axes align with the xy-coordinate axes. + # Note: This sends self.end to -self.start + zp1 = (1 / self.rot_matrix) * (self.start - self.end) / 2 + x1p, y1p = zp1.real, zp1.imag + x1p_sqd = x1p * x1p + y1p_sqd = y1p * y1p + + # Correct out of range radii + # Note: an ellipse going through start and end with radius and phi + # exists if and only if radius_check is true + radius_check = (x1p_sqd / rx_sqd) + (y1p_sqd / ry_sqd) + if radius_check > 1: + if self.autoscale_radius: + rx *= sqrt(radius_check) + ry *= sqrt(radius_check) + self.radius = rx + 1j * ry + rx_sqd = rx * rx + ry_sqd = ry * ry + else: + raise ValueError("No such elliptic arc exists.") + + # Compute c'=(c_x', c_y'), the center of the ellipse in (x', y') coords + # Noting that, in our new coord system, (x_2', y_2') = (-x_1', -x_2') + # and our ellipse is cut out by of the plane by the algebraic equation + # (x'-c_x')**2 / r_x**2 + (y'-c_y')**2 / r_y**2 = 1, + # we can find c' by solving the system of two quadratics given by + # plugging our transformed endpoints (x_1', y_1') and (x_2', y_2') + tmp = rx_sqd * y1p_sqd + ry_sqd * x1p_sqd + radicand = (rx_sqd * ry_sqd - tmp) / tmp + try: + radical = sqrt(radicand) + except ValueError: + radical = 0 + if self.large_arc == self.sweep: + cp = -radical * (rx * y1p / ry - 1j * ry * x1p / rx) + else: + cp = radical * (rx * y1p / ry - 1j * ry * x1p / rx) + + # The center in (x,y) coordinates is easy to find knowing c' + self.center = exp(1j * self.phi) * cp + (self.start + self.end) / 2 + + # Now we do a second transformation, from (x', y') to (u_x, u_y) + # coordinates, which is a translation moving the center of the + # ellipse to the origin and a dilation stretching the ellipse to be + # the unit circle + u1 = (x1p - cp.real) / rx + 1j * (y1p - cp.imag) / ry + u2 = (-x1p - cp.real) / rx + 1j * (-y1p - cp.imag) / ry + + # clip in case of floating point error + u1 = clip(u1.real, -1, 1) + 1j * clip(u1.imag, -1, 1) + u2 = clip(u2.real, -1, 1) + 1j * clip(u2.imag, -1, 1) + + # Now compute theta and delta (we'll define them as we go) + # delta is the angular distance of the arc (w.r.t the circle) + # theta is the angle between the positive x'-axis and the start point + # on the circle + if u1.imag > 0: + self.theta = degrees(acos(u1.real)) + elif u1.imag < 0: + self.theta = -degrees(acos(u1.real)) + else: + if u1.real > 0: # start is on pos u_x axis + self.theta = 0 + else: # start is on neg u_x axis + # Note: This behavior disagrees with behavior documented in + # http://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes + # where theta is set to 0 in this case. + self.theta = 180 + + det_uv = u1.real * u2.imag - u1.imag * u2.real + + acosand = u1.real * u2.real + u1.imag * u2.imag + acosand = clip(acosand.real, -1, 1) + clip(acosand.imag, -1, 1) + + if det_uv > 0: + self.delta = degrees(acos(acosand)) + elif det_uv < 0: + self.delta = -degrees(acos(acosand)) + else: + if u1.real * u2.real + u1.imag * u2.imag > 0: + # u1 == u2 + self.delta = 0 + else: + # u1 == -u2 + # Note: This behavior disagrees with behavior documented in + # http://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes + # where delta is set to 0 in this case. + self.delta = 180 + + if not self.sweep and self.delta >= 0: + self.delta -= 360 + elif self.large_arc and self.delta <= 0: + self.delta += 360 + + def point(self, t): + if t == 0: + return self.start + if t == 1: + return self.end + angle = radians(self.theta + t * self.delta) + cosphi = self.rot_matrix.real + sinphi = self.rot_matrix.imag + rx = self.radius.real + ry = self.radius.imag + + # z = self.rot_matrix*(rx*cos(angle) + 1j*ry*sin(angle)) + self.center + x = rx * cosphi * cos(angle) - ry * sinphi * sin( + angle) + self.center.real + y = rx * sinphi * cos(angle) + ry * cosphi * sin( + angle) + self.center.imag + return complex(x, y) + + def bbox(self): + """returns a bounding box for the segment in the form + (xmin, xmax, ymin, ymax).""" + # a(t) = radians(self.theta + self.delta*t) + # = (2*pi/360)*(self.theta + self.delta*t) + # x'=0: ~~~~~~~~~ + # -rx*cos(phi)*sin(a(t)) = ry*sin(phi)*cos(a(t)) + # -(rx/ry)*cot(phi)*tan(a(t)) = 1 + # a(t) = arctan(-(ry/rx)tan(phi)) + pi*k === atan_x + # y'=0: ~~~~~~~~~~ + # rx*sin(phi)*sin(a(t)) = ry*cos(phi)*cos(a(t)) + # (rx/ry)*tan(phi)*tan(a(t)) = 1 + # a(t) = arctan((ry/rx)*cot(phi)) + # atanres = arctan((ry/rx)*cot(phi)) === atan_y + # ~~~~~~~~ + # (2*pi/360)*(self.theta + self.delta*t) = atanres + pi*k + # Therefore, for both x' and y', we have... + # t = ((atan_{x/y} + pi*k)*(360/(2*pi)) - self.theta)/self.delta + # for all k s.t. 0 < t < 1 + from math import atan, tan + + if cos(self.phi) == 0: + atan_x = pi / 2 + atan_y = 0 + elif sin(self.phi) == 0: + atan_x = 0 + atan_y = pi / 2 + else: + rx, ry = self.radius.real, self.radius.imag + atan_x = atan(-(ry / rx) * tan(self.phi)) + atan_y = atan((ry / rx) / tan(self.phi)) + + def angle_inv(ang, q): # inverse of angle from Arc.derivative() + return ((ang + pi * q) * (360 / (2 * pi)) - + self.theta) / self.delta + + xtrema = [self.start.real, self.end.real] + ytrema = [self.start.imag, self.end.imag] + + for k in range(-4, 5): + tx = angle_inv(atan_x, k) + ty = angle_inv(atan_y, k) + if 0 <= tx <= 1: + xtrema.append(self.point(tx).real) + if 0 <= ty <= 1: + ytrema.append(self.point(ty).imag) + return min(xtrema), max(xtrema), min(ytrema), max(ytrema) + + +COMMANDS = set('MmZzLlHhVvCcSsQqTtAa') +UPPERCASE = set('MZLHVCSQTA') + +COMMAND_RE = re.compile("([MmZzLlHhVvCcSsQqTtAa])") +FLOAT_RE = re.compile(r"[-+]?[0-9]*\.?[0-9]+(?:[eE][-+]?[0-9]+)?") + + +def _tokenize_path(path_def): + for x in COMMAND_RE.split(path_def): + if x in COMMANDS: + yield x + for token in FLOAT_RE.findall(x): + yield token + + +def parse_path(pathdef, logger, current_pos=0j): + # In the SVG specs, initial movetos are absolute, even if + # specified as 'm'. This is the default behavior here as well. + # But if you pass in a current_pos variable, the initial moveto + # will be relative to that current_pos. This is useful. + elements = list(_tokenize_path(pathdef)) + # Reverse for easy use of .pop() + elements.reverse() + absolute = False + + segments = [] + + start_pos = None + command = None + + while elements: + + if elements[-1] in COMMANDS: + # New command. + command = elements.pop() + absolute = command in UPPERCASE + command = command.upper() + else: + # If this element starts with numbers, it is an implicit command + # and we don't change the command. Check that it's allowed: + if command is None: + raise ValueError( + "Unallowed implicit command in %s, position %s" % ( + pathdef, len(pathdef.split()) - len(elements))) + + if command == 'M': + # Moveto command. + x = elements.pop() + y = elements.pop() + pos = float(x) + float(y) * 1j + if absolute: + current_pos = pos + else: + current_pos += pos + + # when M is called, reset start_pos + # This behavior of Z is defined in svg spec: + # http://www.w3.org/TR/SVG/paths.html#PathDataClosePathCommand + start_pos = current_pos + + # Implicit moveto commands are treated as lineto commands. + # So we set command to lineto here, in case there are + # further implicit commands after this moveto. + command = 'L' + + elif command == 'Z': + # Close path + if not (current_pos == start_pos): + segments.append(Line(current_pos, start_pos)) + current_pos = start_pos + command = None + + elif command == 'L': + x = elements.pop() + y = elements.pop() + pos = float(x) + float(y) * 1j + if not absolute: + pos += current_pos + segments.append(Line(current_pos, pos)) + current_pos = pos + + elif command == 'H': + x = elements.pop() + pos = float(x) + current_pos.imag * 1j + if not absolute: + pos += current_pos.real + segments.append(Line(current_pos, pos)) + current_pos = pos + + elif command == 'V': + y = elements.pop() + pos = current_pos.real + float(y) * 1j + if not absolute: + pos += current_pos.imag * 1j + segments.append(Line(current_pos, pos)) + current_pos = pos + + elif command == 'C': + logger.warn('Encountered Cubic Bezier segment. ' + 'It is currently not supported and will be replaced ' + 'by a line segment.') + for i in range(4): + # ignore control points + elements.pop() + end = float(elements.pop()) + float(elements.pop()) * 1j + + if not absolute: + end += current_pos + + segments.append(Line(current_pos, end)) + current_pos = end + + elif command == 'S': + logger.warn('Encountered Quadratic Bezier segment. ' + 'It is currently not supported and will be replaced ' + 'by a line segment.') + for i in range(2): + # ignore control points + elements.pop() + end = float(elements.pop()) + float(elements.pop()) * 1j + + if not absolute: + end += current_pos + + segments.append(Line(current_pos, end)) + current_pos = end + + elif command == 'Q': + logger.warn('Encountered Quadratic Bezier segment. ' + 'It is currently not supported and will be replaced ' + 'by a line segment.') + for i in range(2): + # ignore control points + elements.pop() + end = float(elements.pop()) + float(elements.pop()) * 1j + + if not absolute: + end += current_pos + + segments.append(Line(current_pos, end)) + current_pos = end + + elif command == 'T': + logger.warn('Encountered Quadratic Bezier segment. ' + 'It is currently not supported and will be replaced ' + 'by a line segment.') + + end = float(elements.pop()) + float(elements.pop()) * 1j + + if not absolute: + end += current_pos + + segments.append(Line(current_pos, end)) + current_pos = end + + elif command == 'A': + radius = float(elements.pop()) + float(elements.pop()) * 1j + rotation = float(elements.pop()) + arc = float(elements.pop()) + sweep = float(elements.pop()) + end = float(elements.pop()) + float(elements.pop()) * 1j + + if not absolute: + end += current_pos + + segments.append( + Arc(current_pos, radius, rotation, arc, sweep, end)) + current_pos = end + + return segments + + +def create_path(lines, circles=[]): + """Returns a path d-string.""" + + def limit_digits(val): + return format(val, '.6f').rstrip('0').replace(',', '.').rstrip('.') + + def different_points(a, b): + return abs(a[0] - b[0]) > 1e-6 or abs(a[1] - b[1]) > 1e-6 + + parts = [] + + for i, line in enumerate(lines): + if i == 0 or different_points(lines[i - 1][-1], line[0]): + parts.append('M{},{}'.format(*map(limit_digits, line[0]))) + for point in line[1:]: + parts.append('L{},{}'.format(*map(limit_digits, point))) + + for circle in circles: + cx, cy, r = circle[0][0], circle[0][1], circle[1] + parts.append('M{},{}'.format(limit_digits(cx - r), limit_digits(cy))) + parts.append('a {},{} 0 1,0 {},0'.format( + *map(limit_digits, [r, r, r + r]))) + parts.append('a {},{} 0 1,0 -{},0'.format( + *map(limit_digits, [r, r, r + r]))) + + return ''.join(parts) diff --git a/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/errors.py b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/errors.py new file mode 100644 index 000000000..f62bc5516 --- /dev/null +++ b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/errors.py @@ -0,0 +1,16 @@ +import sys + + +class ExitCodes(): + ERROR_PARSE = 3 + ERROR_FILE_NOT_FOUND = 4 + ERROR_NO_DISPLAY = 5 + + +class ParsingException(Exception): + pass + + +def exit_error(logger, code, err): + logger.error(err) + sys.exit(code) diff --git a/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/generate_interactive_bom.py b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/generate_interactive_bom.py new file mode 100644 index 000000000..bca7f803c --- /dev/null +++ b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/generate_interactive_bom.py @@ -0,0 +1,84 @@ +#!/usr/bin/python3 +from __future__ import absolute_import + +import argparse +import os +import sys +# Add ../ to the path +# Works if this script is executed without installing the module +script_dir = os.path.dirname(os.path.abspath(os.path.realpath(__file__))) +sys.path.insert(0, os.path.dirname(script_dir)) +# Pretend we are part of a module +# Avoids: ImportError: attempted relative import with no known parent package +__package__ = os.path.basename(script_dir) +__import__(__package__) + + +# python 2 and 3 compatibility hack +def to_utf(s): + if isinstance(s, bytes): + return s.decode('utf-8') + else: + return s + + +def main(): + create_wx_app = 'INTERACTIVE_HTML_BOM_NO_DISPLAY' not in os.environ + + import wx + + if create_wx_app: + app = wx.App() + if hasattr(wx, "APP_ASSERT_SUPPRESS"): + app.SetAssertMode(wx.APP_ASSERT_SUPPRESS) + elif hasattr(wx, "DisableAsserts"): + wx.DisableAsserts() + + from .core import ibom + from .core.config import Config + from .ecad import get_parser_by_extension + from .version import version + from .errors import (ExitCodes, ParsingException, exit_error) + + parser = argparse.ArgumentParser( + description='KiCad InteractiveHtmlBom plugin CLI.', + formatter_class=argparse.ArgumentDefaultsHelpFormatter) + parser.add_argument('file', + type=lambda s: to_utf(s), + help="KiCad PCB file") + + Config.add_options(parser, version) + args = parser.parse_args() + logger = ibom.Logger(cli=True) + + if not os.path.isfile(args.file): + exit_error(logger, ExitCodes.ERROR_FILE_NOT_FOUND, + "File %s does not exist." % args.file) + + print("Loading %s" % args.file) + + config = Config(version, os.path.dirname(os.path.abspath(args.file))) + + parser = get_parser_by_extension( + os.path.abspath(args.file), config, logger) + + if args.show_dialog: + if not create_wx_app: + exit_error(logger, ExitCodes.ERROR_NO_DISPLAY, + "Can not show dialog when " + "INTERACTIVE_HTML_BOM_NO_DISPLAY is set.") + try: + ibom.run_with_dialog(parser, config, logger) + except ParsingException as e: + exit_error(logger, ExitCodes.ERROR_PARSE, e) + else: + config.set_from_args(args) + try: + ibom.main(parser, config, logger) + except ParsingException as e: + exit_error(logger, ExitCodes.ERROR_PARSE, str(e)) + return 0 + + +if __name__ == "__main__": + main() diff --git a/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/i18n/language_en.bat b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/i18n/language_en.bat new file mode 100644 index 000000000..90def75cb --- /dev/null +++ b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/i18n/language_en.bat @@ -0,0 +1,12 @@ +::start up echo +set i18n_gitAddr= https://github.com/openscopeproject/InteractiveHtmlBom +set i18n_batScar= Bat file by Scarrrr0725 +set i18n_thx4using= Thank You For Using Generate Interactive Bom + +::convert +set i18n_draghere=Please Drag the EasyEDA PCB source file here : +set i18n_converting=Converting . . . . . . + +::converted +set i18n_again=Do you want to convert another file ? +set i18n_converted= EDA source file is converted to bom successfully! \ No newline at end of file diff --git a/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/i18n/language_zh.bat b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/i18n/language_zh.bat new file mode 100644 index 000000000..a1abb7a08 --- /dev/null +++ b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/i18n/language_zh.bat @@ -0,0 +1,17 @@ +::This file needs to be in 'UTF-8 encoding' AND 'Windows CR LF' to work. + +::set active code page as UTF-8/65001 +set PYTHONIOENCODING=utf-8 +chcp 65001 +::start up echo +set i18n_gitAddr= https://github.com/openscopeproject/InteractiveHtmlBom +set i18n_batScar= Bat 文件: Scarrrr0725/XiaoMingXD +set i18n_thx4using= 感谢使用 Generate Interactive Bom + +::convert +set i18n_draghere=请将您的 EDA PCB 源文件拖移至此: +set i18n_converting=导出中 . . . . . ." + +::converted +set i18n_again=请问是否转换其他文件? +set i18n_converted= 您的 EDA 源文件已成功导出 Bom! diff --git a/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/icon.png b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..11b2cf05cb1fef49402b82f93ef9701ce03d8489 GIT binary patch literal 820 zcmV-41Izr0P)pF8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H10>Mc{ zK~zYIt(HqjR8btpf9KpYcQg~TEQ+#-q(Y>ishlu#5rL2e#Yl^&ktozfWSgQkEhH!k zbQ2T?Q79-9l~ju~Xj6!a7Se+tTD0gPy-nxN+&QPkOpK2i&CzdnIOlxd|Mi`F1wfOj z^l4}Wwg6sc2gg8vU+-mpzCe0n>#;#ANK8b!u)Lr$6Km}nERO_0&Wbq&UOoE6N?$Gz&!9%O zWB#KJ$ucc(O&I_8ki+1EkK8#kNOk+Rn1GHNgcMwL15=Vu>`|(oWn?S%UD!au_Pm5Z zItELYjgA`LJ{jUhu!sDOIjkwkLuuC_t%Sf#jrL$)2+J$5yoSOf9@g(%!v2dJczFIb z#~+r)GZ-U~j?s4AviZ`hdDHB&yv(Agd?{@w1^|!~1=2xe82)^O+;y>`%vxmg=W7@M zrCp6wiD^yeEqZo3Ok~)wzDiBno0AfiU9oXT;PFw1WqyU7lh~V+5&=X*#J&r1yrGnd z8pJH72%szIV0i_FM-_JV_+Zt%T-zD_8Sxq&Gu%u|wENEF^O4ago=gkCk@kGmv$}X8 z9p_#W2}Nf_o(yhS)79{nwL2CAbSr_ZtGcdiv { + position: relative; +} + +#toptoggle { + cursor: pointer; + user-select: none; + position: absolute; + padding: 0.1rem 0.3rem; + top: -0.4rem; + left: -1rem; + font-size: 1.4rem; + line-height: 60%; + border: 1px solid black; + border-radius: 1rem; + background-color: #fff; + z-index: 100; +} + +.flipped { + transform: rotate(0.5turn); +} + +.dark #toptoggle { + border: 1px solid #fff; + background-color: #222; +} + +#fileinfodiv { + flex: 20rem 1 0; + overflow: auto; +} + +#bomcontrols { + display: flex; + flex-direction: row-reverse; +} + +#bomcontrols>* { + flex-shrink: 0; +} + +#dbg { + display: block; +} + +::-webkit-scrollbar { + width: 8px; +} + +::-webkit-scrollbar-track { + background: #aaa; +} + +::-webkit-scrollbar-thumb { + background: #666; + border-radius: 3px; +} + +::-webkit-scrollbar-thumb:hover { + background: #555; +} + +.slider { + -webkit-appearance: none; + width: 100%; + margin: 3px 0; + padding: 0; + outline: none; + opacity: 0.7; + -webkit-transition: .2s; + transition: opacity .2s; + border-radius: 3px; +} + +.slider:hover { + opacity: 1; +} + +.slider:focus { + outline: none; +} + +.slider::-webkit-slider-runnable-track { + -webkit-appearance: none; + width: 100%; + height: 8px; + background: #d3d3d3; + border-radius: 3px; + border: none; +} + +.slider::-webkit-slider-thumb { + -webkit-appearance: none; + width: 15px; + height: 15px; + border-radius: 50%; + background: #0a0; + cursor: pointer; + margin-top: -4px; +} + +.dark .slider::-webkit-slider-thumb { + background: #3d3; +} + +.slider::-moz-range-thumb { + width: 15px; + height: 15px; + border-radius: 50%; + background: #0a0; + cursor: pointer; +} + +.slider::-moz-range-track { + height: 8px; + background: #d3d3d3; + border-radius: 3px; +} + +.dark .slider::-moz-range-thumb { + background: #3d3; +} + +.slider::-ms-track { + width: 100%; + height: 8px; + border-width: 3px 0; + background: transparent; + border-color: transparent; + color: transparent; + transition: opacity .2s; +} + +.slider::-ms-fill-lower { + background: #d3d3d3; + border: none; + border-radius: 3px; +} + +.slider::-ms-fill-upper { + background: #d3d3d3; + border: none; + border-radius: 3px; +} + +.slider::-ms-thumb { + width: 15px; + height: 15px; + border-radius: 50%; + background: #0a0; + cursor: pointer; + margin: 0; +} + +.shameless-plug { + font-size: 0.8em; + text-align: center; + display: block; +} + +a { + color: #0278a4; +} + +.dark a { + color: #00b9fd; +} + +#frontcanvas, +#backcanvas { + touch-action: none; +} + +.placeholder { + border: 1px dashed #9f9fda !important; + background-color: #edf2f7 !important; +} + +.dragging { + z-index: 999; +} + +.dark .dragging>table>tbody>tr { + background-color: #252c30; +} + +.dark .placeholder { + filter: invert(1); +} + +.column-spacer { + top: 0; + left: 0; + width: calc(100% - 4px); + position: absolute; + cursor: pointer; + user-select: none; + height: 100%; +} + +.column-width-handle { + top: 0; + right: 0; + width: 4px; + position: absolute; + cursor: col-resize; + user-select: none; + height: 100%; +} + +.column-width-handle:hover { + background-color: #4f99bd; +} + +.help-link { + border: 1px solid #0278a4; + padding-inline: 0.3rem; + border-radius: 3px; + cursor: pointer; +} + +.dark .help-link { + border: 1px solid #00b9fd; +} + +.bom-color { + width: 20%; +} + +.color-column input { + width: 1.6rem; + height: 1rem; + border: 1px solid black; + cursor: pointer; + padding: 0; +} + +/* removes default styling from input color element */ +::-webkit-color-swatch { + border: none; +} + +::-webkit-color-swatch-wrapper { + padding: 0; +} + +::-moz-color-swatch, +::-moz-focus-inner { + border: none; +} + +::-moz-focus-inner { + padding: 0; +} \ No newline at end of file diff --git a/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/web/ibom.html b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/web/ibom.html new file mode 100644 index 000000000..cfe45c742 --- /dev/null +++ b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/web/ibom.html @@ -0,0 +1,337 @@ + + + + + + + Interactive BOM for KiCAD + + + + + +///USERHEADER/// +
+
+
+ + + + + + + + + + + +
+ Title + + Revision +
+ Company + + Date +
+
+
+ +
+ + + +
+
+ + + +
+
+ + + +
+ + +
+
+
+
+
+
+
+
+
+
+ + +
+ +
+
+
+ + + + + +
+
+
+
+
+ + + + +
+
+
+
+ + + + +
+
+
+
+
+///USERFOOTER/// + + + diff --git a/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/web/ibom.js b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/web/ibom.js new file mode 100644 index 000000000..0d2bce05b --- /dev/null +++ b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/web/ibom.js @@ -0,0 +1,1294 @@ +/* DOM manipulation and misc code */ + +var bomsplit; +var canvassplit; +var initDone = false; +var bomSortFunction = null; +var currentSortColumn = null; +var currentSortOrder = null; +var currentHighlightedRowId; +var highlightHandlers = []; +var footprintIndexToHandler = {}; +var netsToHandler = {}; +var markedFootprints = new Set(); +var highlightedFootprints = []; +var highlightedNet = null; +var lastClicked; + +function dbg(html) { + dbgdiv.innerHTML = html; +} + +function redrawIfInitDone() { + if (initDone) { + redrawCanvas(allcanvas.front); + redrawCanvas(allcanvas.back); + } +} + +function padsVisible(value) { + writeStorage("padsVisible", value); + settings.renderPads = value; + redrawIfInitDone(); +} + +function referencesVisible(value) { + writeStorage("referencesVisible", value); + settings.renderReferences = value; + redrawIfInitDone(); +} + +function valuesVisible(value) { + writeStorage("valuesVisible", value); + settings.renderValues = value; + redrawIfInitDone(); +} + +function tracksVisible(value) { + writeStorage("tracksVisible", value); + settings.renderTracks = value; + redrawIfInitDone(); +} + +function zonesVisible(value) { + writeStorage("zonesVisible", value); + settings.renderZones = value; + redrawIfInitDone(); +} + +function dnpOutline(value) { + writeStorage("dnpOutline", value); + settings.renderDnpOutline = value; + redrawIfInitDone(); +} + +function setDarkMode(value) { + if (value) { + topmostdiv.classList.add("dark"); + } else { + topmostdiv.classList.remove("dark"); + } + writeStorage("darkmode", value); + settings.darkMode = value; + redrawIfInitDone(); + if (initDone) { + populateBomTable(); + } +} + +function setShowBOMColumn(field, value) { + if (field === "references") { + var rl = document.getElementById("reflookup"); + rl.disabled = !value; + if (!value) { + rl.value = ""; + updateRefLookup(""); + } + } + + var n = settings.hiddenColumns.indexOf(field); + if (value) { + if (n != -1) { + settings.hiddenColumns.splice(n, 1); + } + } else { + if (n == -1) { + settings.hiddenColumns.push(field); + } + } + + writeStorage("hiddenColumns", JSON.stringify(settings.hiddenColumns)); + + if (initDone) { + populateBomTable(); + } + + redrawIfInitDone(); +} + + +function setFullscreen(value) { + if (value) { + document.documentElement.requestFullscreen(); + } else { + document.exitFullscreen(); + } +} + +function fabricationVisible(value) { + writeStorage("fabricationVisible", value); + settings.renderFabrication = value; + redrawIfInitDone(); +} + +function silkscreenVisible(value) { + writeStorage("silkscreenVisible", value); + settings.renderSilkscreen = value; + redrawIfInitDone(); +} + +function setHighlightPin1(value) { + writeStorage("highlightpin1", value); + settings.highlightpin1 = value; + redrawIfInitDone(); +} + +function getStoredCheckboxRefs(checkbox) { + function convert(ref) { + var intref = parseInt(ref); + if (isNaN(intref)) { + for (var i = 0; i < pcbdata.footprints.length; i++) { + if (pcbdata.footprints[i].ref == ref) { + return i; + } + } + return -1; + } else { + return intref; + } + } + if (!(checkbox in settings.checkboxStoredRefs)) { + var val = readStorage("checkbox_" + checkbox); + settings.checkboxStoredRefs[checkbox] = val ? val : ""; + } + if (!settings.checkboxStoredRefs[checkbox]) { + return new Set(); + } else { + return new Set(settings.checkboxStoredRefs[checkbox].split(",").map(r => convert(r)).filter(a => a >= 0)); + } +} + +function getCheckboxState(checkbox, references) { + var storedRefsSet = getStoredCheckboxRefs(checkbox); + var currentRefsSet = new Set(references.map(r => r[1])); + // Get difference of current - stored + var difference = new Set(currentRefsSet); + for (ref of storedRefsSet) { + difference.delete(ref); + } + if (difference.size == 0) { + // All the current refs are stored + return "checked"; + } else if (difference.size == currentRefsSet.size) { + // None of the current refs are stored + return "unchecked"; + } else { + // Some of the refs are stored + return "indeterminate"; + } +} + +function setBomCheckboxState(checkbox, element, references) { + var state = getCheckboxState(checkbox, references); + element.checked = (state == "checked"); + element.indeterminate = (state == "indeterminate"); +} + +function createCheckboxChangeHandler(checkbox, references, row) { + return function () { + refsSet = getStoredCheckboxRefs(checkbox); + var markWhenChecked = settings.markWhenChecked == checkbox; + eventArgs = { + checkbox: checkbox, + refs: references, + } + if (this.checked) { + // checkbox ticked + for (var ref of references) { + refsSet.add(ref[1]); + } + if (markWhenChecked) { + row.classList.add("checked"); + for (var ref of references) { + markedFootprints.add(ref[1]); + } + drawHighlights(); + } + eventArgs.state = 'checked'; + } else { + // checkbox unticked + for (var ref of references) { + refsSet.delete(ref[1]); + } + if (markWhenChecked) { + row.classList.remove("checked"); + for (var ref of references) { + markedFootprints.delete(ref[1]); + } + drawHighlights(); + } + eventArgs.state = 'unchecked'; + } + settings.checkboxStoredRefs[checkbox] = [...refsSet].join(","); + writeStorage("checkbox_" + checkbox, settings.checkboxStoredRefs[checkbox]); + updateCheckboxStats(checkbox); + EventHandler.emitEvent(IBOM_EVENT_TYPES.CHECKBOX_CHANGE_EVENT, eventArgs); + } +} + +function clearHighlightedFootprints() { + if (currentHighlightedRowId) { + document.getElementById(currentHighlightedRowId).classList.remove("highlighted"); + currentHighlightedRowId = null; + highlightedFootprints = []; + highlightedNet = null; + } +} + +function createRowHighlightHandler(rowid, refs, net) { + return function () { + if (currentHighlightedRowId) { + if (currentHighlightedRowId == rowid) { + return; + } + document.getElementById(currentHighlightedRowId).classList.remove("highlighted"); + } + document.getElementById(rowid).classList.add("highlighted"); + currentHighlightedRowId = rowid; + highlightedFootprints = refs ? refs.map(r => r[1]) : []; + highlightedNet = net; + drawHighlights(); + EventHandler.emitEvent( + IBOM_EVENT_TYPES.HIGHLIGHT_EVENT, { + rowid: rowid, + refs: refs, + net: net + }); + } +} + +function updateNetColors() { + writeStorage("netColors", JSON.stringify(settings.netColors)); + redrawIfInitDone(); +} + +function netColorChangeHandler(net) { + return (event) => { + settings.netColors[net] = event.target.value; + updateNetColors(); + } +} + +function netColorRightClick(net) { + return (event) => { + if (event.button == 2) { + event.preventDefault(); + event.stopPropagation(); + + var style = getComputedStyle(topmostdiv); + var defaultNetColor = style.getPropertyValue('--track-color').trim(); + event.target.value = defaultNetColor; + delete settings.netColors[net]; + updateNetColors(); + } + } +} + +function entryMatches(entry) { + if (settings.bommode == "netlist") { + // entry is just a net name + return entry.toLowerCase().indexOf(filter) >= 0; + } + // check refs + if (!settings.hiddenColumns.includes("references")) { + for (var ref of entry) { + if (ref[0].toLowerCase().indexOf(filter) >= 0) { + return true; + } + } + } + // check fields + for (var i in config.fields) { + var f = config.fields[i]; + if (!settings.hiddenColumns.includes(f)) { + for (var ref of entry) { + if (String(pcbdata.bom.fields[ref[1]][i]).toLowerCase().indexOf(filter) >= 0) { + return true; + } + } + } + } + return false; +} + +function findRefInEntry(entry) { + return entry.filter(r => r[0].toLowerCase() == reflookup); +} + +function highlightFilter(s) { + if (!filter) { + return s; + } + var parts = s.toLowerCase().split(filter); + if (parts.length == 1) { + return s; + } + var r = ""; + var pos = 0; + for (var i in parts) { + if (i > 0) { + r += '' + + s.substring(pos, pos + filter.length) + + ''; + pos += filter.length; + } + r += s.substring(pos, pos + parts[i].length); + pos += parts[i].length; + } + return r; +} + +function checkboxSetUnsetAllHandler(checkboxname) { + return function () { + var checkboxnum = 0; + while (checkboxnum < settings.checkboxes.length && + settings.checkboxes[checkboxnum].toLowerCase() != checkboxname.toLowerCase()) { + checkboxnum++; + } + if (checkboxnum >= settings.checkboxes.length) { + return; + } + var allset = true; + var checkbox; + var row; + for (row of bombody.childNodes) { + checkbox = row.childNodes[checkboxnum + 1].childNodes[0]; + if (!checkbox.checked || checkbox.indeterminate) { + allset = false; + break; + } + } + for (row of bombody.childNodes) { + checkbox = row.childNodes[checkboxnum + 1].childNodes[0]; + checkbox.checked = !allset; + checkbox.indeterminate = false; + checkbox.onchange(); + } + } +} + +function createColumnHeader(name, cls, comparator, is_checkbox = false) { + var th = document.createElement("TH"); + th.innerHTML = name; + th.classList.add(cls); + if (is_checkbox) + th.setAttribute("col_name", "bom-checkbox"); + else + th.setAttribute("col_name", name); + var span = document.createElement("SPAN"); + span.classList.add("sortmark"); + span.classList.add("none"); + th.appendChild(span); + var spacer = document.createElement("div"); + spacer.className = "column-spacer"; + th.appendChild(spacer); + spacer.onclick = function () { + if (currentSortColumn && th !== currentSortColumn) { + // Currently sorted by another column + currentSortColumn.childNodes[1].classList.remove(currentSortOrder); + currentSortColumn.childNodes[1].classList.add("none"); + currentSortColumn = null; + currentSortOrder = null; + } + if (currentSortColumn && th === currentSortColumn) { + // Already sorted by this column + if (currentSortOrder == "asc") { + // Sort by this column, descending order + bomSortFunction = function (a, b) { + return -comparator(a, b); + } + currentSortColumn.childNodes[1].classList.remove("asc"); + currentSortColumn.childNodes[1].classList.add("desc"); + currentSortOrder = "desc"; + } else { + // Unsort + bomSortFunction = null; + currentSortColumn.childNodes[1].classList.remove("desc"); + currentSortColumn.childNodes[1].classList.add("none"); + currentSortColumn = null; + currentSortOrder = null; + } + } else { + // Sort by this column, ascending order + bomSortFunction = comparator; + currentSortColumn = th; + currentSortColumn.childNodes[1].classList.remove("none"); + currentSortColumn.childNodes[1].classList.add("asc"); + currentSortOrder = "asc"; + } + populateBomBody(); + } + if (is_checkbox) { + spacer.onclick = fancyDblClickHandler( + spacer, spacer.onclick, checkboxSetUnsetAllHandler(name)); + } + return th; +} + +function populateBomHeader(placeHolderColumn = null, placeHolderElements = null) { + while (bomhead.firstChild) { + bomhead.removeChild(bomhead.firstChild); + } + var tr = document.createElement("TR"); + var th = document.createElement("TH"); + th.classList.add("numCol"); + + var vismenu = document.createElement("div"); + vismenu.id = "vismenu"; + vismenu.classList.add("menu"); + + var visbutton = document.createElement("div"); + visbutton.classList.add("visbtn"); + visbutton.classList.add("hideonprint"); + + var viscontent = document.createElement("div"); + viscontent.classList.add("menu-content"); + viscontent.id = "vismenu-content"; + + settings.columnOrder.forEach(column => { + if (typeof column !== "string") + return; + + // Skip empty columns + if (column === "checkboxes" && settings.checkboxes.length == 0) + return; + else if (column === "Quantity" && settings.bommode == "ungrouped") + return; + + var label = document.createElement("label"); + label.classList.add("menu-label"); + + var input = document.createElement("input"); + input.classList.add("visibility_checkbox"); + input.type = "checkbox"; + input.onchange = function (e) { + setShowBOMColumn(column, e.target.checked) + }; + input.checked = !(settings.hiddenColumns.includes(column)); + + label.appendChild(input); + if (column.length > 0) + label.append(column[0].toUpperCase() + column.slice(1)); + + viscontent.appendChild(label); + }); + + viscontent.childNodes[0].classList.add("menu-label-top"); + + vismenu.appendChild(visbutton); + if (settings.bommode != "netlist") { + vismenu.appendChild(viscontent); + th.appendChild(vismenu); + } + tr.appendChild(th); + + var checkboxCompareClosure = function (checkbox) { + return (a, b) => { + var stateA = getCheckboxState(checkbox, a); + var stateB = getCheckboxState(checkbox, b); + if (stateA > stateB) return -1; + if (stateA < stateB) return 1; + return 0; + } + } + var stringFieldCompareClosure = function (fieldIndex) { + return (a, b) => { + var fa = pcbdata.bom.fields[a[0][1]][fieldIndex]; + var fb = pcbdata.bom.fields[b[0][1]][fieldIndex]; + if (fa != fb) return fa > fb ? 1 : -1; + else return 0; + } + } + var referenceRegex = /(?[^0-9]+)(?[0-9]+)/; + var compareRefs = (a, b) => { + var ra = referenceRegex.exec(a); + var rb = referenceRegex.exec(b); + if (ra === null || rb === null) { + if (a != b) return a > b ? 1 : -1; + return 0; + } else { + if (ra.groups.prefix != rb.groups.prefix) { + return ra.groups.prefix > rb.groups.prefix ? 1 : -1; + } + if (ra.groups.number != rb.groups.number) { + return parseInt(ra.groups.number) > parseInt(rb.groups.number) ? 1 : -1; + } + return 0; + } + } + if (settings.bommode == "netlist") { + tr.appendChild(createColumnHeader("Net name", "bom-netname", (a, b) => { + if (a > b) return -1; + if (a < b) return 1; + return 0; + })); + tr.appendChild(createColumnHeader("Color", "bom-color", (a, b) => { + return 0; + })); + } else { + // Filter hidden columns + var columns = settings.columnOrder.filter(e => !settings.hiddenColumns.includes(e)); + var valueIndex = config.fields.indexOf("Value"); + var footprintIndex = config.fields.indexOf("Footprint"); + columns.forEach((column) => { + if (column === placeHolderColumn) { + var n = 1; + if (column === "checkboxes") + n = settings.checkboxes.length; + for (i = 0; i < n; i++) { + td = placeHolderElements.shift(); + tr.appendChild(td); + } + return; + } else if (column === "checkboxes") { + for (var checkbox of settings.checkboxes) { + th = createColumnHeader( + checkbox, "bom-checkbox", checkboxCompareClosure(checkbox), true); + tr.appendChild(th); + } + } else if (column === "References") { + tr.appendChild(createColumnHeader("References", "references", (a, b) => { + var i = 0; + while (i < a.length && i < b.length) { + if (a[i] != b[i]) return compareRefs(a[i][0], b[i][0]); + i++; + } + return a.length - b.length; + })); + } else if (column === "Value") { + tr.appendChild(createColumnHeader("Value", "value", (a, b) => { + var ra = a[0][1], rb = b[0][1]; + return valueCompare( + pcbdata.bom.parsedValues[ra], pcbdata.bom.parsedValues[rb], + pcbdata.bom.fields[ra][valueIndex], pcbdata.bom.fields[rb][valueIndex]); + })); + return; + } else if (column === "Footprint") { + tr.appendChild(createColumnHeader( + "Footprint", "footprint", stringFieldCompareClosure(footprintIndex))); + } else if (column === "Quantity" && settings.bommode == "grouped") { + tr.appendChild(createColumnHeader("Quantity", "quantity", (a, b) => { + return a.length - b.length; + })); + } else { + // Other fields + var i = config.fields.indexOf(column); + if (i < 0) + return; + tr.appendChild(createColumnHeader( + column, `field${i + 1}`, stringFieldCompareClosure(i))); + } + }); + } + bomhead.appendChild(tr); +} + +function populateBomBody(placeholderColumn = null, placeHolderElements = null) { + const urlRegex = /^(https?:\/\/[^\s\/$.?#][^\s]*|file:\/\/([a-zA-Z]:|\/)[^\x00]+)$/; + while (bom.firstChild) { + bom.removeChild(bom.firstChild); + } + highlightHandlers = []; + footprintIndexToHandler = {}; + netsToHandler = {}; + currentHighlightedRowId = null; + var first = true; + var style = getComputedStyle(topmostdiv); + var defaultNetColor = style.getPropertyValue('--track-color').trim(); + if (settings.bommode == "netlist") { + bomtable = pcbdata.nets.slice(); + } else { + switch (settings.canvaslayout) { + case 'F': + bomtable = pcbdata.bom.F.slice(); + break; + case 'FB': + bomtable = pcbdata.bom.both.slice(); + break; + case 'B': + bomtable = pcbdata.bom.B.slice(); + break; + } + if (settings.bommode == "ungrouped") { + // expand bom table + expandedTable = [] + for (var bomentry of bomtable) { + for (var ref of bomentry) { + expandedTable.push([ref]); + } + } + bomtable = expandedTable; + } + } + if (bomSortFunction) { + bomtable = bomtable.sort(bomSortFunction); + } + for (var i in bomtable) { + var bomentry = bomtable[i]; + if (filter && !entryMatches(bomentry)) { + continue; + } + var references = null; + var netname = null; + var tr = document.createElement("TR"); + var td = document.createElement("TD"); + var rownum = +i + 1; + tr.id = "bomrow" + rownum; + td.textContent = rownum; + tr.appendChild(td); + if (settings.bommode == "netlist") { + netname = bomentry; + td = document.createElement("TD"); + td.innerHTML = highlightFilter(netname ? netname : "<no net>"); + tr.appendChild(td); + var color = settings.netColors[netname] || defaultNetColor; + td = document.createElement("TD"); + var colorBox = document.createElement("INPUT"); + colorBox.type = "color"; + colorBox.value = color; + colorBox.onchange = netColorChangeHandler(netname); + colorBox.onmouseup = netColorRightClick(netname); + colorBox.oncontextmenu = (e) => e.preventDefault(); + td.appendChild(colorBox); + td.classList.add("color-column"); + tr.appendChild(td); + } else { + if (reflookup) { + references = findRefInEntry(bomentry); + if (references.length == 0) { + continue; + } + } else { + references = bomentry; + } + // Filter hidden columns + var columns = settings.columnOrder.filter(e => !settings.hiddenColumns.includes(e)); + columns.forEach((column) => { + if (column === placeholderColumn) { + var n = 1; + if (column === "checkboxes") + n = settings.checkboxes.length; + for (i = 0; i < n; i++) { + td = placeHolderElements.shift(); + tr.appendChild(td); + } + return; + } else if (column === "checkboxes") { + for (var checkbox of settings.checkboxes) { + if (checkbox) { + td = document.createElement("TD"); + var input = document.createElement("input"); + input.type = "checkbox"; + input.onchange = createCheckboxChangeHandler(checkbox, references, tr); + setBomCheckboxState(checkbox, input, references); + if (input.checked && settings.markWhenChecked == checkbox) { + tr.classList.add("checked"); + } + td.appendChild(input); + tr.appendChild(td); + } + } + } else if (column === "References") { + td = document.createElement("TD"); + td.innerHTML = highlightFilter(references.map(r => r[0]).join(", ")); + tr.appendChild(td); + } else if (column === "Quantity" && settings.bommode == "grouped") { + // Quantity + td = document.createElement("TD"); + td.textContent = references.length; + tr.appendChild(td); + } else { + // All the other fields + var field_index = config.fields.indexOf(column) + if (field_index < 0) + return; + var valueSet = new Set(); + references.map(r => r[1]).forEach((id) => valueSet.add(pcbdata.bom.fields[id][field_index])); + td = document.createElement("TD"); + var output = new Array(); + for (let item of valueSet) { + const visible = highlightFilter(String(item)); + if (typeof item === 'string' && item.match(urlRegex)) { + output.push(`${visible}`); + } else { + output.push(visible); + } + } + td.innerHTML = output.join(", "); + tr.appendChild(td); + } + }); + } + bom.appendChild(tr); + var handler = createRowHighlightHandler(tr.id, references, netname); + tr.onmousemove = handler; + highlightHandlers.push({ + id: tr.id, + handler: handler, + }); + if (references !== null) { + for (var refIndex of references.map(r => r[1])) { + footprintIndexToHandler[refIndex] = handler; + } + } + if (netname !== null) { + netsToHandler[netname] = handler; + } + if ((filter || reflookup) && first) { + handler(); + first = false; + } + } + EventHandler.emitEvent( + IBOM_EVENT_TYPES.BOM_BODY_CHANGE_EVENT, { + filter: filter, + reflookup: reflookup, + checkboxes: settings.checkboxes, + bommode: settings.bommode, + }); +} + +function highlightPreviousRow() { + if (!currentHighlightedRowId) { + highlightHandlers[highlightHandlers.length - 1].handler(); + } else { + if (highlightHandlers.length > 1 && + highlightHandlers[0].id == currentHighlightedRowId) { + highlightHandlers[highlightHandlers.length - 1].handler(); + } else { + for (var i = 0; i < highlightHandlers.length - 1; i++) { + if (highlightHandlers[i + 1].id == currentHighlightedRowId) { + highlightHandlers[i].handler(); + break; + } + } + } + } + smoothScrollToRow(currentHighlightedRowId); +} + +function highlightNextRow() { + if (!currentHighlightedRowId) { + highlightHandlers[0].handler(); + } else { + if (highlightHandlers.length > 1 && + highlightHandlers[highlightHandlers.length - 1].id == currentHighlightedRowId) { + highlightHandlers[0].handler(); + } else { + for (var i = 1; i < highlightHandlers.length; i++) { + if (highlightHandlers[i - 1].id == currentHighlightedRowId) { + highlightHandlers[i].handler(); + break; + } + } + } + } + smoothScrollToRow(currentHighlightedRowId); +} + +function populateBomTable() { + populateBomHeader(); + populateBomBody(); + setBomHandlers(); + resizableGrid(bomhead); +} + +function footprintsClicked(footprintIndexes) { + var lastClickedIndex = footprintIndexes.indexOf(lastClicked); + for (var i = 1; i <= footprintIndexes.length; i++) { + var refIndex = footprintIndexes[(lastClickedIndex + i) % footprintIndexes.length]; + if (refIndex in footprintIndexToHandler) { + lastClicked = refIndex; + footprintIndexToHandler[refIndex](); + smoothScrollToRow(currentHighlightedRowId); + break; + } + } +} + +function netClicked(net) { + if (net in netsToHandler) { + netsToHandler[net](); + smoothScrollToRow(currentHighlightedRowId); + } else { + clearHighlightedFootprints(); + highlightedNet = net; + drawHighlights(); + } +} + +function updateFilter(input) { + filter = input.toLowerCase(); + populateBomTable(); +} + +function updateRefLookup(input) { + reflookup = input.toLowerCase(); + populateBomTable(); +} + +function changeCanvasLayout(layout) { + document.getElementById("fl-btn").classList.remove("depressed"); + document.getElementById("fb-btn").classList.remove("depressed"); + document.getElementById("bl-btn").classList.remove("depressed"); + switch (layout) { + case 'F': + document.getElementById("fl-btn").classList.add("depressed"); + if (settings.bomlayout != "bom-only") { + canvassplit.collapse(1); + } + break; + case 'B': + document.getElementById("bl-btn").classList.add("depressed"); + if (settings.bomlayout != "bom-only") { + canvassplit.collapse(0); + } + break; + default: + document.getElementById("fb-btn").classList.add("depressed"); + if (settings.bomlayout != "bom-only") { + canvassplit.setSizes([50, 50]); + } + } + settings.canvaslayout = layout; + writeStorage("canvaslayout", layout); + resizeAll(); + changeBomMode(settings.bommode); +} + +function populateMetadata() { + document.getElementById("title").innerHTML = pcbdata.metadata.title; + document.getElementById("revision").innerHTML = "Rev: " + pcbdata.metadata.revision; + document.getElementById("company").innerHTML = pcbdata.metadata.company; + document.getElementById("filedate").innerHTML = pcbdata.metadata.date; + if (pcbdata.metadata.title != "") { + document.title = pcbdata.metadata.title + " BOM"; + } + // Calculate board stats + var fp_f = 0, + fp_b = 0, + pads_f = 0, + pads_b = 0, + pads_th = 0; + for (var i = 0; i < pcbdata.footprints.length; i++) { + if (pcbdata.bom.skipped.includes(i)) continue; + var mod = pcbdata.footprints[i]; + if (mod.layer == "F") { + fp_f++; + } else { + fp_b++; + } + for (var pad of mod.pads) { + if (pad.type == "th") { + pads_th++; + } else { + if (pad.layers.includes("F")) { + pads_f++; + } + if (pad.layers.includes("B")) { + pads_b++; + } + } + } + } + document.getElementById("stats-components-front").innerHTML = fp_f; + document.getElementById("stats-components-back").innerHTML = fp_b; + document.getElementById("stats-components-total").innerHTML = fp_f + fp_b; + document.getElementById("stats-groups-front").innerHTML = pcbdata.bom.F.length; + document.getElementById("stats-groups-back").innerHTML = pcbdata.bom.B.length; + document.getElementById("stats-groups-total").innerHTML = pcbdata.bom.both.length; + document.getElementById("stats-smd-pads-front").innerHTML = pads_f; + document.getElementById("stats-smd-pads-back").innerHTML = pads_b; + document.getElementById("stats-smd-pads-total").innerHTML = pads_f + pads_b; + document.getElementById("stats-th-pads").innerHTML = pads_th; + // Update version string + document.getElementById("github-link").innerHTML = "InteractiveHtmlBom " + + /^v\d+\.\d+/.exec(pcbdata.ibom_version)[0]; +} + +function changeBomLayout(layout) { + document.getElementById("bom-btn").classList.remove("depressed"); + document.getElementById("lr-btn").classList.remove("depressed"); + document.getElementById("tb-btn").classList.remove("depressed"); + switch (layout) { + case 'bom-only': + document.getElementById("bom-btn").classList.add("depressed"); + if (bomsplit) { + bomsplit.destroy(); + bomsplit = null; + canvassplit.destroy(); + canvassplit = null; + } + document.getElementById("frontcanvas").style.display = "none"; + document.getElementById("backcanvas").style.display = "none"; + document.getElementById("topmostdiv").style.height = ""; + document.getElementById("topmostdiv").style.display = "block"; + break; + case 'top-bottom': + document.getElementById("tb-btn").classList.add("depressed"); + document.getElementById("frontcanvas").style.display = ""; + document.getElementById("backcanvas").style.display = ""; + document.getElementById("topmostdiv").style.height = "100%"; + document.getElementById("topmostdiv").style.display = "flex"; + document.getElementById("bomdiv").classList.remove("split-horizontal"); + document.getElementById("canvasdiv").classList.remove("split-horizontal"); + document.getElementById("frontcanvas").classList.add("split-horizontal"); + document.getElementById("backcanvas").classList.add("split-horizontal"); + if (bomsplit) { + bomsplit.destroy(); + bomsplit = null; + canvassplit.destroy(); + canvassplit = null; + } + bomsplit = Split(['#bomdiv', '#canvasdiv'], { + sizes: [50, 50], + onDragEnd: resizeAll, + direction: "vertical", + gutterSize: 5 + }); + canvassplit = Split(['#frontcanvas', '#backcanvas'], { + sizes: [50, 50], + gutterSize: 5, + onDragEnd: resizeAll + }); + break; + case 'left-right': + document.getElementById("lr-btn").classList.add("depressed"); + document.getElementById("frontcanvas").style.display = ""; + document.getElementById("backcanvas").style.display = ""; + document.getElementById("topmostdiv").style.height = "100%"; + document.getElementById("topmostdiv").style.display = "flex"; + document.getElementById("bomdiv").classList.add("split-horizontal"); + document.getElementById("canvasdiv").classList.add("split-horizontal"); + document.getElementById("frontcanvas").classList.remove("split-horizontal"); + document.getElementById("backcanvas").classList.remove("split-horizontal"); + if (bomsplit) { + bomsplit.destroy(); + bomsplit = null; + canvassplit.destroy(); + canvassplit = null; + } + bomsplit = Split(['#bomdiv', '#canvasdiv'], { + sizes: [50, 50], + onDragEnd: resizeAll, + gutterSize: 5 + }); + canvassplit = Split(['#frontcanvas', '#backcanvas'], { + sizes: [50, 50], + gutterSize: 5, + direction: "vertical", + onDragEnd: resizeAll + }); + } + settings.bomlayout = layout; + writeStorage("bomlayout", layout); + changeCanvasLayout(settings.canvaslayout); +} + +function changeBomMode(mode) { + document.getElementById("bom-grouped-btn").classList.remove("depressed"); + document.getElementById("bom-ungrouped-btn").classList.remove("depressed"); + document.getElementById("bom-netlist-btn").classList.remove("depressed"); + var chkbxs = document.getElementsByClassName("visibility_checkbox"); + + switch (mode) { + case 'grouped': + document.getElementById("bom-grouped-btn").classList.add("depressed"); + for (var i = 0; i < chkbxs.length; i++) { + chkbxs[i].disabled = false; + } + break; + case 'ungrouped': + document.getElementById("bom-ungrouped-btn").classList.add("depressed"); + for (var i = 0; i < chkbxs.length; i++) { + chkbxs[i].disabled = false; + } + break; + case 'netlist': + document.getElementById("bom-netlist-btn").classList.add("depressed"); + for (var i = 0; i < chkbxs.length; i++) { + chkbxs[i].disabled = true; + } + } + + writeStorage("bommode", mode); + if (mode != settings.bommode) { + settings.bommode = mode; + bomSortFunction = null; + currentSortColumn = null; + currentSortOrder = null; + clearHighlightedFootprints(); + } + populateBomTable(); +} + +function focusFilterField() { + focusInputField(document.getElementById("filter")); +} + +function focusRefLookupField() { + focusInputField(document.getElementById("reflookup")); +} + +function toggleBomCheckbox(bomrowid, checkboxnum) { + if (!bomrowid || checkboxnum > settings.checkboxes.length) { + return; + } + var bomrow = document.getElementById(bomrowid); + var checkbox = bomrow.childNodes[checkboxnum].childNodes[0]; + checkbox.checked = !checkbox.checked; + checkbox.indeterminate = false; + checkbox.onchange(); +} + +function checkBomCheckbox(bomrowid, checkboxname) { + var checkboxnum = 0; + while (checkboxnum < settings.checkboxes.length && + settings.checkboxes[checkboxnum].toLowerCase() != checkboxname.toLowerCase()) { + checkboxnum++; + } + if (!bomrowid || checkboxnum >= settings.checkboxes.length) { + return; + } + var bomrow = document.getElementById(bomrowid); + var checkbox = bomrow.childNodes[checkboxnum + 1].childNodes[0]; + checkbox.checked = true; + checkbox.indeterminate = false; + checkbox.onchange(); +} + +function setBomCheckboxes(value) { + writeStorage("bomCheckboxes", value); + settings.checkboxes = value.split(",").map((e) => e.trim()).filter((e) => e); + prepCheckboxes(); + populateMarkWhenCheckedOptions(); + setMarkWhenChecked(settings.markWhenChecked); +} + +function setMarkWhenChecked(value) { + writeStorage("markWhenChecked", value); + settings.markWhenChecked = value; + markedFootprints.clear(); + for (var ref of (value ? getStoredCheckboxRefs(value) : [])) { + markedFootprints.add(ref); + } + populateBomTable(); + drawHighlights(); +} + +function prepCheckboxes() { + var table = document.getElementById("checkbox-stats"); + while (table.childElementCount > 1) { + table.removeChild(table.lastChild); + } + if (settings.checkboxes.length) { + table.style.display = ""; + } else { + table.style.display = "none"; + } + for (var checkbox of settings.checkboxes) { + var tr = document.createElement("TR"); + var td = document.createElement("TD"); + td.innerHTML = checkbox; + tr.appendChild(td); + td = document.createElement("TD"); + td.id = "checkbox-stats-" + checkbox; + var progressbar = document.createElement("div"); + progressbar.classList.add("bar"); + td.appendChild(progressbar); + var text = document.createElement("div"); + text.classList.add("text"); + td.appendChild(text); + tr.appendChild(td); + table.appendChild(tr); + updateCheckboxStats(checkbox); + } +} + +function populateMarkWhenCheckedOptions() { + var container = document.getElementById("markWhenCheckedContainer"); + + if (settings.checkboxes.length == 0) { + container.parentElement.style.display = "none"; + return; + } + + container.innerHTML = ''; + container.parentElement.style.display = "inline-block"; + + function createOption(name, displayName) { + var id = "markWhenChecked-" + name; + + var div = document.createElement("div"); + div.classList.add("radio-container"); + + var input = document.createElement("input"); + input.type = "radio"; + input.name = "markWhenChecked"; + input.value = name; + input.id = id; + input.onchange = () => setMarkWhenChecked(name); + div.appendChild(input); + + // Preserve the selected element when the checkboxes change + if (name == settings.markWhenChecked) { + input.checked = true; + } + + var label = document.createElement("label"); + label.innerHTML = displayName; + label.htmlFor = id; + div.appendChild(label); + + container.appendChild(div); + } + createOption("", "None"); + for (var checkbox of settings.checkboxes) { + createOption(checkbox, checkbox); + } +} + +function updateCheckboxStats(checkbox) { + var checked = getStoredCheckboxRefs(checkbox).size; + var total = pcbdata.footprints.length - pcbdata.bom.skipped.length; + var percent = checked * 100.0 / total; + var td = document.getElementById("checkbox-stats-" + checkbox); + td.firstChild.style.width = percent + "%"; + td.lastChild.innerHTML = checked + "/" + total + " (" + Math.round(percent) + "%)"; +} + +function constrain(number, min, max) { + return Math.min(Math.max(parseInt(number), min), max); +} + +document.onkeydown = function (e) { + switch (e.key) { + case "n": + if (document.activeElement.type == "text") { + return; + } + if (currentHighlightedRowId !== null) { + checkBomCheckbox(currentHighlightedRowId, "placed"); + highlightNextRow(); + e.preventDefault(); + } + break; + case "ArrowUp": + highlightPreviousRow(); + e.preventDefault(); + break; + case "ArrowDown": + highlightNextRow(); + e.preventDefault(); + break; + case "ArrowLeft": + case "ArrowRight": + if (document.activeElement.type != "text") { + e.preventDefault(); + let boardRotationElement = document.getElementById("boardRotation") + settings.boardRotation = parseInt(boardRotationElement.value); // degrees / 5 + if (e.key == "ArrowLeft") { + settings.boardRotation += 3; // 15 degrees + } + else { + settings.boardRotation -= 3; + } + settings.boardRotation = constrain(settings.boardRotation, boardRotationElement.min, boardRotationElement.max); + boardRotationElement.value = settings.boardRotation + setBoardRotation(settings.boardRotation); + } + break; + default: + break; + } + if (e.altKey) { + switch (e.key) { + case "f": + focusFilterField(); + e.preventDefault(); + break; + case "r": + focusRefLookupField(); + e.preventDefault(); + break; + case "z": + changeBomLayout("bom-only"); + e.preventDefault(); + break; + case "x": + changeBomLayout("left-right"); + e.preventDefault(); + break; + case "c": + changeBomLayout("top-bottom"); + e.preventDefault(); + break; + case "v": + changeCanvasLayout("F"); + e.preventDefault(); + break; + case "b": + changeCanvasLayout("FB"); + e.preventDefault(); + break; + case "n": + changeCanvasLayout("B"); + e.preventDefault(); + break; + default: + break; + } + if (e.key >= '1' && e.key <= '9') { + toggleBomCheckbox(currentHighlightedRowId, parseInt(e.key)); + e.preventDefault(); + } + } +} + +function hideNetlistButton() { + document.getElementById("bom-ungrouped-btn").classList.remove("middle-button"); + document.getElementById("bom-ungrouped-btn").classList.add("right-most-button"); + document.getElementById("bom-netlist-btn").style.display = "none"; +} + +function topToggle() { + var top = document.getElementById("top"); + var toptoggle = document.getElementById("toptoggle"); + if (top.style.display === "none") { + top.style.display = "flex"; + toptoggle.classList.remove("flipped"); + } else { + top.style.display = "none"; + toptoggle.classList.add("flipped"); + } +} + +window.onload = function (e) { + initUtils(); + initRender(); + initStorage(); + initDefaults(); + cleanGutters(); + populateMetadata(); + dbgdiv = document.getElementById("dbg"); + bom = document.getElementById("bombody"); + bomhead = document.getElementById("bomhead"); + filter = ""; + reflookup = ""; + if (!("nets" in pcbdata)) { + hideNetlistButton(); + } + initDone = true; + setBomCheckboxes(document.getElementById("bomCheckboxes").value); + // Triggers render + changeBomLayout(settings.bomlayout); + + // Users may leave fullscreen without touching the checkbox. Uncheck. + document.addEventListener('fullscreenchange', () => { + if (!document.fullscreenElement) + document.getElementById('fullscreenCheckbox').checked = false; + }); +} + +window.onresize = resizeAll; +window.matchMedia("print").addListener(resizeAll); diff --git a/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/web/lz-string.js b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/web/lz-string.js new file mode 100644 index 000000000..0513686d7 --- /dev/null +++ b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/web/lz-string.js @@ -0,0 +1,10 @@ +// Copyright (c) 2013 Pieroxy +// This work is free. You can redistribute it and/or modify it +// under the terms of the WTFPL, Version 2 +// For more information see LICENSE.txt or http://www.wtfpl.net/ +// +// For more information, the home page: +// http://pieroxy.net/blog/pages/lz-string/testing.html +// +// LZ-based compression algorithm, version 1.4.4 +var LZString=function(){var o=String.fromCharCode,i={};var n={decompressFromBase64:function(o){return null==o?"":""==o?null:n._decompress(o.length,32,function(n){return function(o,n){if(!i[o]){i[o]={};for(var t=0;t>=1,0==m.position&&(m.position=n,m.val=t(m.index++)),a|=(s>0?1:0)*u,u<<=1;switch(a){case 0:for(a=0,p=Math.pow(2,8),u=1;u!=p;)s=m.val&m.position,m.position>>=1,0==m.position&&(m.position=n,m.val=t(m.index++)),a|=(s>0?1:0)*u,u<<=1;l=o(a);break;case 1:for(a=0,p=Math.pow(2,16),u=1;u!=p;)s=m.val&m.position,m.position>>=1,0==m.position&&(m.position=n,m.val=t(m.index++)),a|=(s>0?1:0)*u,u<<=1;l=o(a);break;case 2:return""}for(f[3]=l,e=l,g.push(l);;){if(m.index>i)return"";for(a=0,p=Math.pow(2,h),u=1;u!=p;)s=m.val&m.position,m.position>>=1,0==m.position&&(m.position=n,m.val=t(m.index++)),a|=(s>0?1:0)*u,u<<=1;switch(l=a){case 0:for(a=0,p=Math.pow(2,8),u=1;u!=p;)s=m.val&m.position,m.position>>=1,0==m.position&&(m.position=n,m.val=t(m.index++)),a|=(s>0?1:0)*u,u<<=1;f[d++]=o(a),l=d-1,c--;break;case 1:for(a=0,p=Math.pow(2,16),u=1;u!=p;)s=m.val&m.position,m.position>>=1,0==m.position&&(m.position=n,m.val=t(m.index++)),a|=(s>0?1:0)*u,u<<=1;f[d++]=o(a),l=d-1,c--;break;case 2:return g.join("")}if(0==c&&(c=Math.pow(2,h),h++),f[l])v=f[l];else{if(l!==d)return null;v=e+e.charAt(0)}g.push(v),f[d++]=e+v.charAt(0),e=v,0==--c&&(c=Math.pow(2,h),h++)}}};return n}();"function"==typeof define&&define.amd?define(function(){return LZString}):"undefined"!=typeof module&&null!=module?module.exports=LZString:"undefined"!=typeof angular&&null!=angular&&angular.module("LZString",[]).factory("LZString",function(){return LZString}); \ No newline at end of file diff --git a/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/web/pep.js b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/web/pep.js new file mode 100644 index 000000000..5d5c18bf8 --- /dev/null +++ b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/web/pep.js @@ -0,0 +1,43 @@ +/*! + * PEP v0.4.3 | https://github.com/jquery/PEP + * Copyright jQuery Foundation and other contributors | http://jquery.org/license + */ +!function(a,b){"object"==typeof exports&&"undefined"!=typeof module?module.exports=b():"function"==typeof define&&define.amd?define(b):a.PointerEventsPolyfill=b()}(this,function(){"use strict";function a(a,b){b=b||Object.create(null);var c=document.createEvent("Event");c.initEvent(a,b.bubbles||!1,b.cancelable||!1); +for(var d,e=2;e=h}return this.firstXY=null,b}},findTouch:function(a,b){for(var c,d=0,e=a.length;d=b.length){var c=[];R.forEach(function(a,d){ +if(1!==d&&!this.findTouch(b,d-2)){var e=a.out;c.push(e)}},this),c.forEach(this.cancelOut,this)}},touchstart:function(a){this.vacuumTouches(a),this.setPrimaryTouch(a.changedTouches[0]),this.dedupSynthMouse(a),this.scrolling||(this.clickCount++,this.processTouches(a,this.overDown))},overDown:function(a){R.set(a.pointerId,{target:a.target,out:a,outTarget:a.target}),u.enterOver(a),u.down(a)},touchmove:function(a){this.scrolling||(this.shouldScroll(a)?(this.scrolling=!0,this.touchcancel(a)):(a.preventDefault(),this.processTouches(a,this.moveOverOut)))},moveOverOut:function(a){var b=a,c=R.get(b.pointerId); +if(c){var d=c.out,e=c.outTarget;u.move(b),d&&e!==b.target&&(d.relatedTarget=b.target,b.relatedTarget=e, +d.target=e,b.target?(u.leaveOut(d),u.enterOver(b)):( +b.target=e,b.relatedTarget=null,this.cancelOut(b))),c.out=b,c.outTarget=b.target}},touchend:function(a){this.dedupSynthMouse(a),this.processTouches(a,this.upOut)},upOut:function(a){this.scrolling||(u.up(a),u.leaveOut(a)),this.cleanUpPointer(a)},touchcancel:function(a){this.processTouches(a,this.cancelOut)},cancelOut:function(a){u.cancel(a),u.leaveOut(a),this.cleanUpPointer(a)},cleanUpPointer:function(a){R["delete"](a.pointerId),this.removePrimaryPointer(a)}, +dedupSynthMouse:function(a){var b=N.lastTouches,c=a.changedTouches[0]; +if(this.isPrimaryTouch(c)){ +var d={x:c.clientX,y:c.clientY};b.push(d);var e=function(a,b){var c=a.indexOf(b);c>-1&&a.splice(c,1)}.bind(null,b,d);setTimeout(e,S)}}};M=new c(V.elementAdded,V.elementRemoved,V.elementChanged,V);var W,X,Y,Z=u.pointermap,$=window.MSPointerEvent&&"number"==typeof window.MSPointerEvent.MSPOINTER_TYPE_MOUSE,_={events:["MSPointerDown","MSPointerMove","MSPointerUp","MSPointerOut","MSPointerOver","MSPointerCancel","MSGotPointerCapture","MSLostPointerCapture"],register:function(a){u.listen(a,this.events)},unregister:function(a){u.unlisten(a,this.events)},POINTER_TYPES:["","unavailable","touch","pen","mouse"],prepareEvent:function(a){var b=a;return $&&(b=u.cloneEvent(a),b.pointerType=this.POINTER_TYPES[a.pointerType]),b},cleanup:function(a){Z["delete"](a)},MSPointerDown:function(a){Z.set(a.pointerId,a);var b=this.prepareEvent(a);u.down(b)},MSPointerMove:function(a){var b=this.prepareEvent(a);u.move(b)},MSPointerUp:function(a){var b=this.prepareEvent(a);u.up(b),this.cleanup(a.pointerId)},MSPointerOut:function(a){var b=this.prepareEvent(a);u.leaveOut(b)},MSPointerOver:function(a){var b=this.prepareEvent(a);u.enterOver(b)},MSPointerCancel:function(a){var b=this.prepareEvent(a);u.cancel(b),this.cleanup(a.pointerId)},MSLostPointerCapture:function(a){var b=u.makeEvent("lostpointercapture",a);u.dispatchEvent(b)},MSGotPointerCapture:function(a){var b=u.makeEvent("gotpointercapture",a);u.dispatchEvent(b)}},aa=window.navigator;aa.msPointerEnabled?(W=function(a){i(a),j(this),k(a)&&(u.setCapture(a,this,!0),this.msSetPointerCapture(a))},X=function(a){i(a),u.releaseCapture(a,!0),this.msReleasePointerCapture(a)}):(W=function(a){i(a),j(this),k(a)&&u.setCapture(a,this)},X=function(a){i(a),u.releaseCapture(a)}),Y=function(a){return!!u.captureInfo[a]},g(),h(),l();var ba={dispatcher:u,Installer:c,PointerEvent:a,PointerMap:p,targetFinding:v};return ba}); diff --git a/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/web/render.js b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/web/render.js new file mode 100644 index 000000000..a70653cde --- /dev/null +++ b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/web/render.js @@ -0,0 +1,1075 @@ +/* PCB rendering code */ + +var emptyContext2d = document.createElement("canvas").getContext("2d"); + +function deg2rad(deg) { + return deg * Math.PI / 180; +} + +function calcFontPoint(linepoint, text, offsetx, offsety, tilt) { + var point = [ + linepoint[0] * text.width + offsetx, + linepoint[1] * text.height + offsety + ]; + // This approximates pcbnew behavior with how text tilts depending on horizontal justification + point[0] -= (linepoint[1] + 0.5 * (1 + text.justify[0])) * text.height * tilt; + return point; +} + +function drawText(ctx, text, color) { + if ("ref" in text && !settings.renderReferences) return; + if ("val" in text && !settings.renderValues) return; + ctx.save(); + ctx.fillStyle = color; + ctx.strokeStyle = color; + ctx.lineCap = "round"; + ctx.lineJoin = "round"; + ctx.lineWidth = text.thickness; + if ("svgpath" in text) { + ctx.stroke(new Path2D(text.svgpath)); + ctx.restore(); + return; + } + if ("polygons" in text) { + ctx.fill(getPolygonsPath(text)); + ctx.restore(); + return; + } + ctx.translate(...text.pos); + ctx.translate(text.thickness * 0.5, 0); + var angle = -text.angle; + if (text.attr.includes("mirrored")) { + ctx.scale(-1, 1); + angle = -angle; + } + var tilt = 0; + if (text.attr.includes("italic")) { + tilt = 0.125; + } + var interline = text.height * 1.5 + text.thickness; + var txt = text.text.split("\n"); + // KiCad ignores last empty line. + if (txt[txt.length - 1] == '') txt.pop(); + ctx.rotate(deg2rad(angle)); + var offsety = (1 - text.justify[1]) / 2 * text.height; // One line offset + offsety -= (txt.length - 1) * (text.justify[1] + 1) / 2 * interline; // Multiline offset + for (var i in txt) { + var lineWidth = text.thickness + interline / 2 * tilt; + for (var j = 0; j < txt[i].length; j++) { + if (txt[i][j] == '\t') { + var fourSpaces = 4 * pcbdata.font_data[' '].w * text.width; + lineWidth += fourSpaces - lineWidth % fourSpaces; + } else { + if (txt[i][j] == '~') { + j++; + if (j == txt[i].length) + break; + } + lineWidth += pcbdata.font_data[txt[i][j]].w * text.width; + } + } + var offsetx = -lineWidth * (text.justify[0] + 1) / 2; + var inOverbar = false; + for (var j = 0; j < txt[i].length; j++) { + if (config.kicad_text_formatting) { + if (txt[i][j] == '\t') { + var fourSpaces = 4 * pcbdata.font_data[' '].w * text.width; + offsetx += fourSpaces - offsetx % fourSpaces; + continue; + } else if (txt[i][j] == '~') { + j++; + if (j == txt[i].length) + break; + if (txt[i][j] != '~') { + inOverbar = !inOverbar; + } + } + } + var glyph = pcbdata.font_data[txt[i][j]]; + if (inOverbar) { + var overbarStart = [offsetx, -text.height * 1.4 + offsety]; + var overbarEnd = [offsetx + text.width * glyph.w, overbarStart[1]]; + + if (!lastHadOverbar) { + overbarStart[0] += text.height * 1.4 * tilt; + lastHadOverbar = true; + } + ctx.beginPath(); + ctx.moveTo(...overbarStart); + ctx.lineTo(...overbarEnd); + ctx.stroke(); + } else { + lastHadOverbar = false; + } + for (var line of glyph.l) { + ctx.beginPath(); + ctx.moveTo(...calcFontPoint(line[0], text, offsetx, offsety, tilt)); + for (var k = 1; k < line.length; k++) { + ctx.lineTo(...calcFontPoint(line[k], text, offsetx, offsety, tilt)); + } + ctx.stroke(); + } + offsetx += glyph.w * text.width; + } + offsety += interline; + } + ctx.restore(); +} + +function drawedge(ctx, scalefactor, edge, color) { + ctx.strokeStyle = color; + ctx.fillStyle = color; + ctx.lineWidth = Math.max(1 / scalefactor, edge.width); + ctx.lineCap = "round"; + ctx.lineJoin = "round"; + if ("svgpath" in edge) { + ctx.stroke(new Path2D(edge.svgpath)); + } else { + ctx.beginPath(); + if (edge.type == "segment") { + ctx.moveTo(...edge.start); + ctx.lineTo(...edge.end); + } + if (edge.type == "rect") { + ctx.moveTo(...edge.start); + ctx.lineTo(edge.start[0], edge.end[1]); + ctx.lineTo(...edge.end); + ctx.lineTo(edge.end[0], edge.start[1]); + ctx.lineTo(...edge.start); + } + if (edge.type == "arc") { + ctx.arc( + ...edge.start, + edge.radius, + deg2rad(edge.startangle), + deg2rad(edge.endangle)); + } + if (edge.type == "circle") { + ctx.arc( + ...edge.start, + edge.radius, + 0, 2 * Math.PI); + ctx.closePath(); + } + if (edge.type == "curve") { + ctx.moveTo(...edge.start); + ctx.bezierCurveTo(...edge.cpa, ...edge.cpb, ...edge.end); + } + if("filled" in edge && edge.filled) + ctx.fill(); + else + ctx.stroke(); + } +} + +function getChamferedRectPath(size, radius, chamfpos, chamfratio) { + // chamfpos is a bitmask, left = 1, right = 2, bottom left = 4, bottom right = 8 + var path = new Path2D(); + var width = size[0]; + var height = size[1]; + var x = width * -0.5; + var y = height * -0.5; + var chamfOffset = Math.min(width, height) * chamfratio; + path.moveTo(x, 0); + if (chamfpos & 4) { + path.lineTo(x, y + height - chamfOffset); + path.lineTo(x + chamfOffset, y + height); + path.lineTo(0, y + height); + } else { + path.arcTo(x, y + height, x + width, y + height, radius); + } + if (chamfpos & 8) { + path.lineTo(x + width - chamfOffset, y + height); + path.lineTo(x + width, y + height - chamfOffset); + path.lineTo(x + width, 0); + } else { + path.arcTo(x + width, y + height, x + width, y, radius); + } + if (chamfpos & 2) { + path.lineTo(x + width, y + chamfOffset); + path.lineTo(x + width - chamfOffset, y); + path.lineTo(0, y); + } else { + path.arcTo(x + width, y, x, y, radius); + } + if (chamfpos & 1) { + path.lineTo(x + chamfOffset, y); + path.lineTo(x, y + chamfOffset); + path.lineTo(x, 0); + } else { + path.arcTo(x, y, x, y + height, radius); + } + path.closePath(); + return path; +} + +function getOblongPath(size) { + return getChamferedRectPath(size, Math.min(size[0], size[1]) / 2, 0, 0); +} + +function getPolygonsPath(shape) { + if (shape.path2d) { + return shape.path2d; + } + if ("svgpath" in shape) { + shape.path2d = new Path2D(shape.svgpath); + } else { + var path = new Path2D(); + for (var polygon of shape.polygons) { + path.moveTo(...polygon[0]); + for (var i = 1; i < polygon.length; i++) { + path.lineTo(...polygon[i]); + } + path.closePath(); + } + shape.path2d = path; + } + return shape.path2d; +} + +function drawPolygonShape(ctx, scalefactor, shape, color) { + ctx.save(); + if (!("svgpath" in shape)) { + ctx.translate(...shape.pos); + ctx.rotate(deg2rad(-shape.angle)); + } + if("filled" in shape && !shape.filled) { + ctx.strokeStyle = color; + ctx.lineWidth = Math.max(1 / scalefactor, shape.width); + ctx.lineCap = "round"; + ctx.lineJoin = "round"; + ctx.stroke(getPolygonsPath(shape)); + } else { + ctx.fillStyle = color; + ctx.fill(getPolygonsPath(shape)); + } + ctx.restore(); +} + +function drawDrawing(ctx, scalefactor, drawing, color) { + if (["segment", "arc", "circle", "curve", "rect"].includes(drawing.type)) { + drawedge(ctx, scalefactor, drawing, color); + } else if (drawing.type == "polygon") { + drawPolygonShape(ctx, scalefactor, drawing, color); + } else { + drawText(ctx, drawing, color); + } +} + +function getCirclePath(radius) { + var path = new Path2D(); + path.arc(0, 0, radius, 0, 2 * Math.PI); + path.closePath(); + return path; +} + +function getCachedPadPath(pad) { + if (!pad.path2d) { + // if path2d is not set, build one and cache it on pad object + if (pad.shape == "rect") { + pad.path2d = new Path2D(); + pad.path2d.rect(...pad.size.map(c => -c * 0.5), ...pad.size); + } else if (pad.shape == "oval") { + pad.path2d = getOblongPath(pad.size); + } else if (pad.shape == "circle") { + pad.path2d = getCirclePath(pad.size[0] / 2); + } else if (pad.shape == "roundrect") { + pad.path2d = getChamferedRectPath(pad.size, pad.radius, 0, 0); + } else if (pad.shape == "chamfrect") { + pad.path2d = getChamferedRectPath(pad.size, pad.radius, pad.chamfpos, pad.chamfratio) + } else if (pad.shape == "custom") { + pad.path2d = getPolygonsPath(pad); + } + } + return pad.path2d; +} + +function drawPad(ctx, pad, color, outline) { + ctx.save(); + ctx.translate(...pad.pos); + ctx.rotate(-deg2rad(pad.angle)); + if (pad.offset) { + ctx.translate(...pad.offset); + } + ctx.fillStyle = color; + ctx.strokeStyle = color; + var path = getCachedPadPath(pad); + if (outline) { + ctx.stroke(path); + } else { + ctx.fill(path); + } + ctx.restore(); +} + +function drawPadHole(ctx, pad, padHoleColor) { + if (pad.type != "th") return; + ctx.save(); + ctx.translate(...pad.pos); + ctx.rotate(-deg2rad(pad.angle)); + ctx.fillStyle = padHoleColor; + if (pad.drillshape == "oblong") { + ctx.fill(getOblongPath(pad.drillsize)); + } else { + ctx.fill(getCirclePath(pad.drillsize[0] / 2)); + } + ctx.restore(); +} + +function drawFootprint(ctx, layer, scalefactor, footprint, colors, highlight, outline) { + if (highlight) { + // draw bounding box + if (footprint.layer == layer) { + ctx.save(); + ctx.globalAlpha = 0.2; + ctx.translate(...footprint.bbox.pos); + ctx.rotate(deg2rad(-footprint.bbox.angle)); + ctx.translate(...footprint.bbox.relpos); + ctx.fillStyle = colors.pad; + ctx.fillRect(0, 0, ...footprint.bbox.size); + ctx.globalAlpha = 1; + ctx.strokeStyle = colors.pad; + ctx.lineWidth = 3 / scalefactor; + ctx.strokeRect(0, 0, ...footprint.bbox.size); + ctx.restore(); + } + } + // draw drawings + for (var drawing of footprint.drawings) { + if (drawing.layer == layer) { + drawDrawing(ctx, scalefactor, drawing.drawing, colors.pad); + } + } + ctx.lineWidth = 3 / scalefactor; + // draw pads + if (settings.renderPads) { + for (var pad of footprint.pads) { + if (pad.layers.includes(layer)) { + drawPad(ctx, pad, colors.pad, outline); + if (pad.pin1 && + (settings.highlightpin1 == "all" || + settings.highlightpin1 == "selected" && highlight)) { + drawPad(ctx, pad, colors.outline, true); + } + } + } + for (var pad of footprint.pads) { + drawPadHole(ctx, pad, colors.padHole); + } + } +} + +function drawEdgeCuts(canvas, scalefactor) { + var ctx = canvas.getContext("2d"); + var edgecolor = getComputedStyle(topmostdiv).getPropertyValue('--pcb-edge-color'); + for (var edge of pcbdata.edges) { + drawDrawing(ctx, scalefactor, edge, edgecolor); + } +} + +function drawFootprints(canvas, layer, scalefactor, highlight) { + var ctx = canvas.getContext("2d"); + ctx.lineWidth = 3 / scalefactor; + var style = getComputedStyle(topmostdiv); + + var colors = { + pad: style.getPropertyValue('--pad-color'), + padHole: style.getPropertyValue('--pad-hole-color'), + outline: style.getPropertyValue('--pin1-outline-color'), + } + + for (var i = 0; i < pcbdata.footprints.length; i++) { + var mod = pcbdata.footprints[i]; + var outline = settings.renderDnpOutline && pcbdata.bom.skipped.includes(i); + var h = highlightedFootprints.includes(i); + var d = markedFootprints.has(i); + if (highlight) { + if(h && d) { + colors.pad = style.getPropertyValue('--pad-color-highlight-both'); + colors.outline = style.getPropertyValue('--pin1-outline-color-highlight-both'); + } else if (h) { + colors.pad = style.getPropertyValue('--pad-color-highlight'); + colors.outline = style.getPropertyValue('--pin1-outline-color-highlight'); + } else if (d) { + colors.pad = style.getPropertyValue('--pad-color-highlight-marked'); + colors.outline = style.getPropertyValue('--pin1-outline-color-highlight-marked'); + } + } + if( h || d || !highlight) { + drawFootprint(ctx, layer, scalefactor, mod, colors, highlight, outline); + } + } +} + +function drawBgLayer(layername, canvas, layer, scalefactor, edgeColor, polygonColor, textColor) { + var ctx = canvas.getContext("2d"); + for (var d of pcbdata.drawings[layername][layer]) { + if (["segment", "arc", "circle", "curve", "rect"].includes(d.type)) { + drawedge(ctx, scalefactor, d, edgeColor); + } else if (d.type == "polygon") { + drawPolygonShape(ctx, scalefactor, d, polygonColor); + } else { + drawText(ctx, d, textColor); + } + } +} + +function drawTracks(canvas, layer, defaultColor, highlight) { + ctx = canvas.getContext("2d"); + ctx.lineCap = "round"; + + var hasHole = (track) => ( + 'drillsize' in track && + track.start[0] == track.end[0] && + track.start[1] == track.end[1]); + + // First draw tracks and tented vias + for (var track of pcbdata.tracks[layer]) { + if (highlight && highlightedNet != track.net) continue; + if (!hasHole(track)) { + ctx.strokeStyle = highlight ? defaultColor : settings.netColors[track.net] || defaultColor; + ctx.lineWidth = track.width; + ctx.beginPath(); + if ('radius' in track) { + ctx.arc( + ...track.center, + track.radius, + deg2rad(track.startangle), + deg2rad(track.endangle)); + } else { + ctx.moveTo(...track.start); + ctx.lineTo(...track.end); + } + ctx.stroke(); + } + } + // Second pass to draw untented vias + var style = getComputedStyle(topmostdiv); + var holeColor = style.getPropertyValue('--pad-hole-color') + + for (var track of pcbdata.tracks[layer]) { + if (highlight && highlightedNet != track.net) continue; + if (hasHole(track)) { + ctx.strokeStyle = highlight ? defaultColor : settings.netColors[track.net] || defaultColor; + ctx.lineWidth = track.width; + ctx.beginPath(); + ctx.moveTo(...track.start); + ctx.lineTo(...track.end); + ctx.stroke(); + ctx.strokeStyle = holeColor; + ctx.lineWidth = track.drillsize; + ctx.lineTo(...track.end); + ctx.stroke(); + } + } +} + +function drawZones(canvas, layer, defaultColor, highlight) { + ctx = canvas.getContext("2d"); + ctx.lineJoin = "round"; + for (var zone of pcbdata.zones[layer]) { + if (highlight && highlightedNet != zone.net) continue; + ctx.strokeStyle = highlight ? defaultColor : settings.netColors[zone.net] || defaultColor; + ctx.fillStyle = highlight ? defaultColor : settings.netColors[zone.net] || defaultColor; + if (!zone.path2d) { + zone.path2d = getPolygonsPath(zone); + } + ctx.fill(zone.path2d, zone.fillrule || "nonzero"); + if (zone.width > 0) { + ctx.lineWidth = zone.width; + ctx.stroke(zone.path2d); + } + } +} + +function clearCanvas(canvas, color = null) { + var ctx = canvas.getContext("2d"); + ctx.save(); + ctx.setTransform(1, 0, 0, 1, 0, 0); + if (color) { + ctx.fillStyle = color; + ctx.fillRect(0, 0, canvas.width, canvas.height); + } else { + if (!window.matchMedia("print").matches) + ctx.clearRect(0, 0, canvas.width, canvas.height); + } + ctx.restore(); +} + +function drawNets(canvas, layer, highlight) { + var style = getComputedStyle(topmostdiv); + if (settings.renderZones) { + var zoneColor = style.getPropertyValue(highlight ? '--zone-color-highlight' : '--zone-color'); + drawZones(canvas, layer, zoneColor, highlight); + } + if (settings.renderTracks) { + var trackColor = style.getPropertyValue(highlight ? '--track-color-highlight' : '--track-color'); + drawTracks(canvas, layer, trackColor, highlight); + } + if (highlight && settings.renderPads) { + var padColor = style.getPropertyValue('--pad-color-highlight'); + var padHoleColor = style.getPropertyValue('--pad-hole-color'); + var ctx = canvas.getContext("2d"); + for (var footprint of pcbdata.footprints) { + // draw pads + var padDrawn = false; + for (var pad of footprint.pads) { + if (highlightedNet != pad.net) continue; + if (pad.layers.includes(layer)) { + drawPad(ctx, pad, padColor, false); + padDrawn = true; + } + } + if (padDrawn) { + // redraw all pad holes because some pads may overlap + for (var pad of footprint.pads) { + drawPadHole(ctx, pad, padHoleColor); + } + } + } + } +} + +function drawHighlightsOnLayer(canvasdict, clear = true) { + if (clear) { + clearCanvas(canvasdict.highlight); + } + if (markedFootprints.size > 0 || highlightedFootprints.length > 0) { + drawFootprints(canvasdict.highlight, canvasdict.layer, + canvasdict.transform.s * canvasdict.transform.zoom, true); + } + if (highlightedNet !== null) { + drawNets(canvasdict.highlight, canvasdict.layer, true); + } +} + +function drawHighlights() { + drawHighlightsOnLayer(allcanvas.front); + drawHighlightsOnLayer(allcanvas.back); +} + +function drawBackground(canvasdict, clear = true) { + if (clear) { + clearCanvas(canvasdict.bg); + clearCanvas(canvasdict.fab); + clearCanvas(canvasdict.silk); + } + + drawNets(canvasdict.bg, canvasdict.layer, false); + drawFootprints(canvasdict.bg, canvasdict.layer, + canvasdict.transform.s * canvasdict.transform.zoom, false); + + drawEdgeCuts(canvasdict.bg, canvasdict.transform.s * canvasdict.transform.zoom); + + var style = getComputedStyle(topmostdiv); + var edgeColor = style.getPropertyValue('--silkscreen-edge-color'); + var polygonColor = style.getPropertyValue('--silkscreen-polygon-color'); + var textColor = style.getPropertyValue('--silkscreen-text-color'); + if (settings.renderSilkscreen) { + drawBgLayer( + "silkscreen", canvasdict.silk, canvasdict.layer, + canvasdict.transform.s * canvasdict.transform.zoom, + edgeColor, polygonColor, textColor); + } + edgeColor = style.getPropertyValue('--fabrication-edge-color'); + polygonColor = style.getPropertyValue('--fabrication-polygon-color'); + textColor = style.getPropertyValue('--fabrication-text-color'); + if (settings.renderFabrication) { + drawBgLayer( + "fabrication", canvasdict.fab, canvasdict.layer, + canvasdict.transform.s * canvasdict.transform.zoom, + edgeColor, polygonColor, textColor); + } +} + +function prepareCanvas(canvas, flip, transform) { + var ctx = canvas.getContext("2d"); + ctx.setTransform(1, 0, 0, 1, 0, 0); + ctx.scale(transform.zoom, transform.zoom); + ctx.translate(transform.panx, transform.pany); + if (flip) { + ctx.scale(-1, 1); + } + ctx.translate(transform.x, transform.y); + ctx.rotate(deg2rad(settings.boardRotation + (flip && settings.offsetBackRotation ? - 180 : 0))); + ctx.scale(transform.s, transform.s); +} + +function prepareLayer(canvasdict) { + var flip = (canvasdict.layer === "B"); + for (var c of ["bg", "fab", "silk", "highlight"]) { + prepareCanvas(canvasdict[c], flip, canvasdict.transform); + } +} + +function rotateVector(v, angle) { + angle = deg2rad(angle); + return [ + v[0] * Math.cos(angle) - v[1] * Math.sin(angle), + v[0] * Math.sin(angle) + v[1] * Math.cos(angle) + ]; +} + +function applyRotation(bbox, flip) { + var corners = [ + [bbox.minx, bbox.miny], + [bbox.minx, bbox.maxy], + [bbox.maxx, bbox.miny], + [bbox.maxx, bbox.maxy], + ]; + corners = corners.map((v) => rotateVector(v, settings.boardRotation + (flip && settings.offsetBackRotation ? - 180 : 0))); + return { + minx: corners.reduce((a, v) => Math.min(a, v[0]), Infinity), + miny: corners.reduce((a, v) => Math.min(a, v[1]), Infinity), + maxx: corners.reduce((a, v) => Math.max(a, v[0]), -Infinity), + maxy: corners.reduce((a, v) => Math.max(a, v[1]), -Infinity), + } +} + +function recalcLayerScale(layerdict, width, height) { + var flip = (layerdict.layer === "B"); + var bbox = applyRotation(pcbdata.edges_bbox, flip); + var scalefactor = 0.98 * Math.min( + width / (bbox.maxx - bbox.minx), + height / (bbox.maxy - bbox.miny) + ); + if (scalefactor < 0.1) { + scalefactor = 1; + } + layerdict.transform.s = scalefactor; + if (flip) { + layerdict.transform.x = -((bbox.maxx + bbox.minx) * scalefactor + width) * 0.5; + } else { + layerdict.transform.x = -((bbox.maxx + bbox.minx) * scalefactor - width) * 0.5; + } + layerdict.transform.y = -((bbox.maxy + bbox.miny) * scalefactor - height) * 0.5; + for (var c of ["bg", "fab", "silk", "highlight"]) { + canvas = layerdict[c]; + canvas.width = width; + canvas.height = height; + canvas.style.width = (width / devicePixelRatio) + "px"; + canvas.style.height = (height / devicePixelRatio) + "px"; + } +} + +function redrawCanvas(layerdict) { + prepareLayer(layerdict); + drawBackground(layerdict); + drawHighlightsOnLayer(layerdict); +} + +function resizeCanvas(layerdict) { + var canvasdivid = { + "F": "frontcanvas", + "B": "backcanvas" + } [layerdict.layer]; + var width = document.getElementById(canvasdivid).clientWidth * devicePixelRatio; + var height = document.getElementById(canvasdivid).clientHeight * devicePixelRatio; + recalcLayerScale(layerdict, width, height); + redrawCanvas(layerdict); +} + +function resizeAll() { + resizeCanvas(allcanvas.front); + resizeCanvas(allcanvas.back); +} + +function pointWithinDistanceToSegment(x, y, x1, y1, x2, y2, d) { + var A = x - x1; + var B = y - y1; + var C = x2 - x1; + var D = y2 - y1; + + var dot = A * C + B * D; + var len_sq = C * C + D * D; + var dx, dy; + if (len_sq == 0) { + // start and end of the segment coincide + dx = x - x1; + dy = y - y1; + } else { + var param = dot / len_sq; + var xx, yy; + if (param < 0) { + xx = x1; + yy = y1; + } else if (param > 1) { + xx = x2; + yy = y2; + } else { + xx = x1 + param * C; + yy = y1 + param * D; + } + dx = x - xx; + dy = y - yy; + } + return dx * dx + dy * dy <= d * d; +} + +function modulo(n, mod) { + return ((n % mod) + mod) % mod; +} + +function pointWithinDistanceToArc(x, y, xc, yc, radius, startangle, endangle, d) { + var dx = x - xc; + var dy = y - yc; + var r_sq = dx * dx + dy * dy; + var rmin = Math.max(0, radius - d); + var rmax = radius + d; + + if (r_sq < rmin * rmin || r_sq > rmax * rmax) + return false; + + var angle1 = modulo(deg2rad(startangle), 2 * Math.PI); + var dx1 = xc + radius * Math.cos(angle1) - x; + var dy1 = yc + radius * Math.sin(angle1) - y; + if (dx1 * dx1 + dy1 * dy1 <= d * d) + return true; + + var angle2 = modulo(deg2rad(endangle), 2 * Math.PI); + var dx2 = xc + radius * Math.cos(angle2) - x; + var dy2 = yc + radius * Math.sin(angle2) - y; + if (dx2 * dx2 + dy2 * dy2 <= d * d) + return true; + + var angle = modulo(Math.atan2(dy, dx), 2 * Math.PI); + if (angle1 > angle2) + return (angle >= angle2 || angle <= angle1); + else + return (angle >= angle1 && angle <= angle2); +} + +function pointWithinPad(x, y, pad) { + var v = [x - pad.pos[0], y - pad.pos[1]]; + v = rotateVector(v, pad.angle); + if (pad.offset) { + v[0] -= pad.offset[0]; + v[1] -= pad.offset[1]; + } + return emptyContext2d.isPointInPath(getCachedPadPath(pad), ...v); +} + +function netHitScan(layer, x, y) { + // Check track segments + if (settings.renderTracks && pcbdata.tracks) { + for (var track of pcbdata.tracks[layer]) { + if ('radius' in track) { + if (pointWithinDistanceToArc(x, y, ...track.center, track.radius, track.startangle, track.endangle, track.width / 2)) { + return track.net; + } + } else { + if (pointWithinDistanceToSegment(x, y, ...track.start, ...track.end, track.width / 2)) { + return track.net; + } + } + } + } + // Check pads + if (settings.renderPads) { + for (var footprint of pcbdata.footprints) { + for (var pad of footprint.pads) { + if (pad.layers.includes(layer) && pointWithinPad(x, y, pad)) { + return pad.net; + } + } + } + } + return null; +} + +function pointWithinFootprintBbox(x, y, bbox) { + var v = [x - bbox.pos[0], y - bbox.pos[1]]; + v = rotateVector(v, bbox.angle); + return bbox.relpos[0] <= v[0] && v[0] <= bbox.relpos[0] + bbox.size[0] && + bbox.relpos[1] <= v[1] && v[1] <= bbox.relpos[1] + bbox.size[1]; +} + +function bboxHitScan(layer, x, y) { + var result = []; + for (var i = 0; i < pcbdata.footprints.length; i++) { + var footprint = pcbdata.footprints[i]; + if (footprint.layer == layer) { + if (pointWithinFootprintBbox(x, y, footprint.bbox)) { + result.push(i); + } + } + } + return result; +} + +function handlePointerDown(e, layerdict) { + if (e.button != 0 && e.button != 1) { + return; + } + e.preventDefault(); + e.stopPropagation(); + + if (!e.hasOwnProperty("offsetX")) { + // The polyfill doesn't set this properly + e.offsetX = e.pageX - e.currentTarget.offsetLeft; + e.offsetY = e.pageY - e.currentTarget.offsetTop; + } + + layerdict.pointerStates[e.pointerId] = { + distanceTravelled: 0, + lastX: e.offsetX, + lastY: e.offsetY, + downTime: Date.now(), + }; +} + +function handleMouseClick(e, layerdict) { + if (!e.hasOwnProperty("offsetX")) { + // The polyfill doesn't set this properly + e.offsetX = e.pageX - e.currentTarget.offsetLeft; + e.offsetY = e.pageY - e.currentTarget.offsetTop; + } + + var x = e.offsetX; + var y = e.offsetY; + var t = layerdict.transform; + var flip = layerdict.layer === "B"; + if (flip) { + x = (devicePixelRatio * x / t.zoom - t.panx + t.x) / -t.s; + } else { + x = (devicePixelRatio * x / t.zoom - t.panx - t.x) / t.s; + } + y = (devicePixelRatio * y / t.zoom - t.y - t.pany) / t.s; + var v = rotateVector([x, y], -settings.boardRotation + (flip && settings.offsetBackRotation ? - 180 : 0)); + if ("nets" in pcbdata) { + var net = netHitScan(layerdict.layer, ...v); + if (net !== highlightedNet) { + netClicked(net); + } + } + if (highlightedNet === null) { + var footprints = bboxHitScan(layerdict.layer, ...v); + if (footprints.length > 0) { + footprintsClicked(footprints); + } + } +} + +function handlePointerLeave(e, layerdict) { + e.preventDefault(); + e.stopPropagation(); + + if (!settings.redrawOnDrag) { + redrawCanvas(layerdict); + } + + delete layerdict.pointerStates[e.pointerId]; +} + +function resetTransform(layerdict) { + layerdict.transform.panx = 0; + layerdict.transform.pany = 0; + layerdict.transform.zoom = 1; + redrawCanvas(layerdict); +} + +function handlePointerUp(e, layerdict) { + if (!e.hasOwnProperty("offsetX")) { + // The polyfill doesn't set this properly + e.offsetX = e.pageX - e.currentTarget.offsetLeft; + e.offsetY = e.pageY - e.currentTarget.offsetTop; + } + + e.preventDefault(); + e.stopPropagation(); + + if (e.button == 2) { + // Reset pan and zoom on right click. + resetTransform(layerdict); + layerdict.anotherPointerTapped = false; + return; + } + + // We haven't necessarily had a pointermove event since the interaction started, so make sure we update this now + var ptr = layerdict.pointerStates[e.pointerId]; + ptr.distanceTravelled += Math.abs(e.offsetX - ptr.lastX) + Math.abs(e.offsetY - ptr.lastY); + + if (e.button == 0 && ptr.distanceTravelled < 10 && Date.now() - ptr.downTime <= 500) { + if (Object.keys(layerdict.pointerStates).length == 1) { + if (layerdict.anotherPointerTapped) { + // This is the second pointer coming off of a two-finger tap + resetTransform(layerdict); + } else { + // This is just a regular tap + handleMouseClick(e, layerdict); + } + layerdict.anotherPointerTapped = false; + } else { + // This is the first finger coming off of what could become a two-finger tap + layerdict.anotherPointerTapped = true; + } + } else { + if (!settings.redrawOnDrag) { + redrawCanvas(layerdict); + } + layerdict.anotherPointerTapped = false; + } + + delete layerdict.pointerStates[e.pointerId]; +} + +function handlePointerMove(e, layerdict) { + if (!layerdict.pointerStates.hasOwnProperty(e.pointerId)) { + return; + } + e.preventDefault(); + e.stopPropagation(); + + if (!e.hasOwnProperty("offsetX")) { + // The polyfill doesn't set this properly + e.offsetX = e.pageX - e.currentTarget.offsetLeft; + e.offsetY = e.pageY - e.currentTarget.offsetTop; + } + + var thisPtr = layerdict.pointerStates[e.pointerId]; + + var dx = e.offsetX - thisPtr.lastX; + var dy = e.offsetY - thisPtr.lastY; + + // If this number is low on pointer up, we count the action as a click + thisPtr.distanceTravelled += Math.abs(dx) + Math.abs(dy); + + if (Object.keys(layerdict.pointerStates).length == 1) { + // This is a simple drag + layerdict.transform.panx += devicePixelRatio * dx / layerdict.transform.zoom; + layerdict.transform.pany += devicePixelRatio * dy / layerdict.transform.zoom; + } else if (Object.keys(layerdict.pointerStates).length == 2) { + var otherPtr = Object.values(layerdict.pointerStates).filter((ptr) => ptr != thisPtr)[0]; + + var oldDist = Math.sqrt(Math.pow(thisPtr.lastX - otherPtr.lastX, 2) + Math.pow(thisPtr.lastY - otherPtr.lastY, 2)); + var newDist = Math.sqrt(Math.pow(e.offsetX - otherPtr.lastX, 2) + Math.pow(e.offsetY - otherPtr.lastY, 2)); + + var scaleFactor = newDist / oldDist; + + if (scaleFactor != NaN) { + layerdict.transform.zoom *= scaleFactor; + + var zoomd = (1 - scaleFactor) / layerdict.transform.zoom; + layerdict.transform.panx += devicePixelRatio * otherPtr.lastX * zoomd; + layerdict.transform.pany += devicePixelRatio * otherPtr.lastY * zoomd; + } + } + + thisPtr.lastX = e.offsetX; + thisPtr.lastY = e.offsetY; + + if (settings.redrawOnDrag) { + redrawCanvas(layerdict); + } +} + +function handleMouseWheel(e, layerdict) { + e.preventDefault(); + e.stopPropagation(); + var t = layerdict.transform; + var wheeldelta = e.deltaY; + if (e.deltaMode == 1) { + // FF only, scroll by lines + wheeldelta *= 30; + } else if (e.deltaMode == 2) { + wheeldelta *= 300; + } + var m = Math.pow(1.1, -wheeldelta / 40); + // Limit amount of zoom per tick. + if (m > 2) { + m = 2; + } else if (m < 0.5) { + m = 0.5; + } + t.zoom *= m; + var zoomd = (1 - m) / t.zoom; + t.panx += devicePixelRatio * e.offsetX * zoomd; + t.pany += devicePixelRatio * e.offsetY * zoomd; + redrawCanvas(layerdict); +} + +function addMouseHandlers(div, layerdict) { + div.addEventListener("pointerdown", function(e) { + handlePointerDown(e, layerdict); + }); + div.addEventListener("pointermove", function(e) { + handlePointerMove(e, layerdict); + }); + div.addEventListener("pointerup", function(e) { + handlePointerUp(e, layerdict); + }); + var pointerleave = function(e) { + handlePointerLeave(e, layerdict); + } + div.addEventListener("pointercancel", pointerleave); + div.addEventListener("pointerleave", pointerleave); + div.addEventListener("pointerout", pointerleave); + + div.onwheel = function(e) { + handleMouseWheel(e, layerdict); + } + for (var element of [div, layerdict.bg, layerdict.fab, layerdict.silk, layerdict.highlight]) { + element.addEventListener("contextmenu", function(e) { + e.preventDefault(); + }, false); + } +} + +function setRedrawOnDrag(value) { + settings.redrawOnDrag = value; + writeStorage("redrawOnDrag", value); +} + +function setBoardRotation(value) { + settings.boardRotation = value * 5; + writeStorage("boardRotation", settings.boardRotation); + document.getElementById("rotationDegree").textContent = settings.boardRotation; + resizeAll(); +} + +function setOffsetBackRotation(value) { + settings.offsetBackRotation = value; + writeStorage("offsetBackRotation", value); + resizeAll(); +} + +function initRender() { + allcanvas = { + front: { + transform: { + x: 0, + y: 0, + s: 1, + panx: 0, + pany: 0, + zoom: 1, + }, + pointerStates: {}, + anotherPointerTapped: false, + bg: document.getElementById("F_bg"), + fab: document.getElementById("F_fab"), + silk: document.getElementById("F_slk"), + highlight: document.getElementById("F_hl"), + layer: "F", + }, + back: { + transform: { + x: 0, + y: 0, + s: 1, + panx: 0, + pany: 0, + zoom: 1, + }, + pointerStates: {}, + anotherPointerTapped: false, + bg: document.getElementById("B_bg"), + fab: document.getElementById("B_fab"), + silk: document.getElementById("B_slk"), + highlight: document.getElementById("B_hl"), + layer: "B", + } + }; + addMouseHandlers(document.getElementById("frontcanvas"), allcanvas.front); + addMouseHandlers(document.getElementById("backcanvas"), allcanvas.back); +} diff --git a/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/web/split.js b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/web/split.js new file mode 100644 index 000000000..7782651e4 --- /dev/null +++ b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/web/split.js @@ -0,0 +1,6 @@ +/* + Split.js - v1.3.5 + MIT License + https://github.com/nathancahill/Split.js +*/ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.Split=t()}(this,function(){"use strict";var e=window,t=e.document,n="addEventListener",i="removeEventListener",r="getBoundingClientRect",s=function(){return!1},o=e.attachEvent&&!e[n],a=["","-webkit-","-moz-","-o-"].filter(function(e){var n=t.createElement("div");return n.style.cssText="width:"+e+"calc(9px)",!!n.style.length}).shift()+"calc",l=function(e){return"string"==typeof e||e instanceof String?t.querySelector(e):e};return function(u,c){function z(e,t,n){var i=A(y,t,n);Object.keys(i).forEach(function(t){return e.style[t]=i[t]})}function h(e,t){var n=B(y,t);Object.keys(n).forEach(function(t){return e.style[t]=n[t]})}function f(e){var t=E[this.a],n=E[this.b],i=t.size+n.size;t.size=e/this.size*i,n.size=i-e/this.size*i,z(t.element,t.size,this.aGutterSize),z(n.element,n.size,this.bGutterSize)}function m(e){var t;this.dragging&&((t="touches"in e?e.touches[0][b]-this.start:e[b]-this.start)<=E[this.a].minSize+M+this.aGutterSize?t=E[this.a].minSize+this.aGutterSize:t>=this.size-(E[this.b].minSize+M+this.bGutterSize)&&(t=this.size-(E[this.b].minSize+this.bGutterSize)),f.call(this,t),c.onDrag&&c.onDrag())}function g(){var e=E[this.a].element,t=E[this.b].element;this.size=e[r]()[y]+t[r]()[y]+this.aGutterSize+this.bGutterSize,this.start=e[r]()[G]}function d(){var t=this,n=E[t.a].element,r=E[t.b].element;t.dragging&&c.onDragEnd&&c.onDragEnd(),t.dragging=!1,e[i]("mouseup",t.stop),e[i]("touchend",t.stop),e[i]("touchcancel",t.stop),t.parent[i]("mousemove",t.move),t.parent[i]("touchmove",t.move),delete t.stop,delete t.move,n[i]("selectstart",s),n[i]("dragstart",s),r[i]("selectstart",s),r[i]("dragstart",s),n.style.userSelect="",n.style.webkitUserSelect="",n.style.MozUserSelect="",n.style.pointerEvents="",r.style.userSelect="",r.style.webkitUserSelect="",r.style.MozUserSelect="",r.style.pointerEvents="",t.gutter.style.cursor="",t.parent.style.cursor=""}function S(t){var i=this,r=E[i.a].element,o=E[i.b].element;!i.dragging&&c.onDragStart&&c.onDragStart(),t.preventDefault(),i.dragging=!0,i.move=m.bind(i),i.stop=d.bind(i),e[n]("mouseup",i.stop),e[n]("touchend",i.stop),e[n]("touchcancel",i.stop),i.parent[n]("mousemove",i.move),i.parent[n]("touchmove",i.move),r[n]("selectstart",s),r[n]("dragstart",s),o[n]("selectstart",s),o[n]("dragstart",s),r.style.userSelect="none",r.style.webkitUserSelect="none",r.style.MozUserSelect="none",r.style.pointerEvents="none",o.style.userSelect="none",o.style.webkitUserSelect="none",o.style.MozUserSelect="none",o.style.pointerEvents="none",i.gutter.style.cursor=j,i.parent.style.cursor=j,g.call(i)}function v(e){e.forEach(function(t,n){if(n>0){var i=F[n-1],r=E[i.a],s=E[i.b];r.size=e[n-1],s.size=t,z(r.element,r.size,i.aGutterSize),z(s.element,s.size,i.bGutterSize)}})}function p(){F.forEach(function(e){e.parent.removeChild(e.gutter),E[e.a].element.style[y]="",E[e.b].element.style[y]=""})}void 0===c&&(c={});var y,b,G,E,w=l(u[0]).parentNode,D=e.getComputedStyle(w).flexDirection,U=c.sizes||u.map(function(){return 100/u.length}),k=void 0!==c.minSize?c.minSize:100,x=Array.isArray(k)?k:u.map(function(){return k}),L=void 0!==c.gutterSize?c.gutterSize:10,M=void 0!==c.snapOffset?c.snapOffset:30,O=c.direction||"horizontal",j=c.cursor||("horizontal"===O?"ew-resize":"ns-resize"),C=c.gutter||function(e,n){var i=t.createElement("div");return i.className="gutter gutter-"+n,i},A=c.elementStyle||function(e,t,n){var i={};return"string"==typeof t||t instanceof String?i[e]=t:i[e]=o?t+"%":a+"("+t+"% - "+n+"px)",i},B=c.gutterStyle||function(e,t){return n={},n[e]=t+"px",n;var n};"horizontal"===O?(y="width","clientWidth",b="clientX",G="left","paddingLeft"):"vertical"===O&&(y="height","clientHeight",b="clientY",G="top","paddingTop");var F=[];return E=u.map(function(e,t){var i,s={element:l(e),size:U[t],minSize:x[t]};if(t>0&&(i={a:t-1,b:t,dragging:!1,isFirst:1===t,isLast:t===u.length-1,direction:O,parent:w},i.aGutterSize=L,i.bGutterSize=L,i.isFirst&&(i.aGutterSize=L/2),i.isLast&&(i.bGutterSize=L/2),"row-reverse"===D||"column-reverse"===D)){var a=i.a;i.a=i.b,i.b=a}if(!o&&t>0){var c=C(t,O);h(c,L),c[n]("mousedown",S.bind(i)),c[n]("touchstart",S.bind(i)),w.insertBefore(c,s.element),i.gutter=c}0===t||t===u.length-1?z(s.element,s.size,L/2):z(s.element,s.size,L);var f=s.element[r]()[y];return f0&&F.push(i),s}),o?{setSizes:v,destroy:p}:{setSizes:v,getSizes:function(){return E.map(function(e){return e.size})},collapse:function(e){if(e===F.length){var t=F[e-1];g.call(t),o||f.call(t,t.size-t.bGutterSize)}else{var n=F[e];g.call(n),o||f.call(n,n.aGutterSize)}},destroy:p}}}); diff --git a/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/web/table-util.js b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/web/table-util.js new file mode 100644 index 000000000..e6dc6b6e0 --- /dev/null +++ b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/web/table-util.js @@ -0,0 +1,371 @@ +/* + * Table reordering via Drag'n'Drop + * Inspired by: https://htmldom.dev/drag-and-drop-table-column + */ + +function setBomHandlers() { + + const bom = document.getElementById('bomtable'); + + let dragName; + let placeHolderElements; + let draggingElement; + let forcePopulation; + let xOffset; + let yOffset; + let wasDragged; + + const mouseUpHandler = function(e) { + // Delete dragging element + draggingElement.remove(); + + // Make BOM selectable again + bom.style.removeProperty("userSelect"); + + // Remove listeners + document.removeEventListener('mousemove', mouseMoveHandler); + document.removeEventListener('mouseup', mouseUpHandler); + + if (wasDragged) { + // Redraw whole BOM + populateBomTable(); + } + } + + const mouseMoveHandler = function(e) { + // Notice the dragging + wasDragged = true; + + // Make the dragged element visible + draggingElement.style.removeProperty("display"); + + // Set elements position to mouse position + draggingElement.style.left = `${e.screenX - xOffset}px`; + draggingElement.style.top = `${e.screenY - yOffset}px`; + + // Forced redrawing of BOM table + if (forcePopulation) { + forcePopulation = false; + // Copy array + phe = Array.from(placeHolderElements); + // populate BOM table again + populateBomHeader(dragName, phe); + populateBomBody(dragName, phe); + } + + // Set up array of hidden columns + var hiddenColumns = Array.from(settings.hiddenColumns); + // In the ungrouped mode, quantity don't exist + if (settings.bommode === "ungrouped") + hiddenColumns.push("Quantity"); + // If no checkbox fields can be found, we consider them hidden + if (settings.checkboxes.length == 0) + hiddenColumns.push("checkboxes"); + + // Get table headers and group them into checkboxes, extrafields and normal headers + const bh = document.getElementById("bomhead"); + headers = Array.from(bh.querySelectorAll("th")) + headers.shift() // numCol is not part of the columnOrder + headerGroups = [] + lastCompoundClass = null; + for (i = 0; i < settings.columnOrder.length; i++) { + cElem = settings.columnOrder[i]; + if (hiddenColumns.includes(cElem)) { + // Hidden columns appear as a dummy element + headerGroups.push([]); + continue; + } + elem = headers.filter(e => getColumnOrderName(e) === cElem)[0]; + if (elem.classList.contains("bom-checkbox")) { + if (lastCompoundClass === "bom-checkbox") { + cbGroup = headerGroups.pop(); + cbGroup.push(elem); + headerGroups.push(cbGroup); + } else { + lastCompoundClass = "bom-checkbox"; + headerGroups.push([elem]) + } + } else { + headerGroups.push([elem]) + } + } + + // Copy settings.columnOrder + var columns = Array.from(settings.columnOrder) + + // Set up array with indices of hidden columns + var hiddenIndices = hiddenColumns.map(e => settings.columnOrder.indexOf(e)); + var dragIndex = columns.indexOf(dragName); + var swapIndex = dragIndex; + var swapDone = false; + + // Check if the current dragged element is swapable with the left or right element + if (dragIndex > 0) { + // Get left headers boundingbox + swapIndex = dragIndex - 1; + while (hiddenIndices.includes(swapIndex) && swapIndex > 0) + swapIndex--; + if (!hiddenIndices.includes(swapIndex)) { + box = getBoundingClientRectFromMultiple(headerGroups[swapIndex]); + if (e.clientX < box.left + window.scrollX + (box.width / 2)) { + swapElement = columns[dragIndex]; + columns.splice(dragIndex, 1); + columns.splice(swapIndex, 0, swapElement); + forcePopulation = true; + swapDone = true; + } + } + } + if ((!swapDone) && dragIndex < headerGroups.length - 1) { + // Get right headers boundingbox + swapIndex = dragIndex + 1; + while (hiddenIndices.includes(swapIndex)) + swapIndex++; + if (swapIndex < headerGroups.length) { + box = getBoundingClientRectFromMultiple(headerGroups[swapIndex]); + if (e.clientX > box.left + window.scrollX + (box.width / 2)) { + swapElement = columns[dragIndex]; + columns.splice(dragIndex, 1); + columns.splice(swapIndex, 0, swapElement); + forcePopulation = true; + swapDone = true; + } + } + } + + // Write back change to storage + if (swapDone) { + settings.columnOrder = columns + writeStorage("columnOrder", JSON.stringify(columns)); + } + + } + + const mouseDownHandler = function(e) { + var target = e.target; + if (target.tagName.toLowerCase() != "td") + target = target.parentElement; + + // Used to check if a dragging has ever happened + wasDragged = false; + + // Create new element which will be displayed as the dragged column + draggingElement = document.createElement("div") + draggingElement.classList.add("dragging"); + draggingElement.style.display = "none"; + draggingElement.style.position = "absolute"; + draggingElement.style.overflow = "hidden"; + + // Get bomhead and bombody elements + const bh = document.getElementById("bomhead"); + const bb = document.getElementById("bombody"); + + // Get all compound headers for the current column + var compoundHeaders; + if (target.classList.contains("bom-checkbox")) { + compoundHeaders = Array.from(bh.querySelectorAll("th.bom-checkbox")); + } else { + compoundHeaders = [target]; + } + + // Create new table which will display the column + var newTable = document.createElement("table"); + newTable.classList.add("bom"); + newTable.style.background = "white"; + draggingElement.append(newTable); + + // Create new header element + var newHeader = document.createElement("thead"); + newTable.append(newHeader); + + // Set up array for storing all placeholder elements + placeHolderElements = []; + + // Add all compound headers to the new thead element and placeholders + compoundHeaders.forEach(function(h) { + clone = cloneElementWithDimensions(h); + newHeader.append(clone); + placeHolderElements.push(clone); + }); + + // Create new body element + var newBody = document.createElement("tbody"); + newTable.append(newBody); + + // Get indices for compound headers + var idxs = compoundHeaders.map(e => getBomTableHeaderIndex(e)); + + // For each row in the BOM body... + var rows = bb.querySelectorAll("tr"); + rows.forEach(function(row) { + // ..get the cells for the compound column + const tds = row.querySelectorAll("td"); + var copytds = idxs.map(i => tds[i]); + // Add them to the new element and the placeholders + var newRow = document.createElement("tr"); + copytds.forEach(function(td) { + clone = cloneElementWithDimensions(td); + newRow.append(clone); + placeHolderElements.push(clone); + }); + newBody.append(newRow); + }); + + // Compute width for compound header + var width = compoundHeaders.reduce((acc, x) => acc + x.clientWidth, 0); + draggingElement.style.width = `${width}px`; + + // Insert the new dragging element and disable selection on BOM + bom.insertBefore(draggingElement, null); + bom.style.userSelect = "none"; + + // Determine the mouse position offset + xOffset = e.screenX - compoundHeaders.reduce((acc, x) => Math.min(acc, x.offsetLeft), compoundHeaders[0].offsetLeft); + yOffset = e.screenY - compoundHeaders[0].offsetTop; + + // Get name for the column in settings.columnOrder + dragName = getColumnOrderName(target); + + // Change text and class for placeholder elements + placeHolderElements = placeHolderElements.map(function(e) { + newElem = cloneElementWithDimensions(e); + newElem.textContent = ""; + newElem.classList.add("placeholder"); + return newElem; + }); + + // On next mouse move, the whole BOM needs to be redrawn to show the placeholders + forcePopulation = true; + + // Add listeners for move and up on mouse + document.addEventListener('mousemove', mouseMoveHandler); + document.addEventListener('mouseup', mouseUpHandler); + } + + // In netlist mode, there is nothing to reorder + if (settings.bommode === "netlist") + return; + + // Add mouseDownHandler to every column except the numCol + bom.querySelectorAll("th") + .forEach(function(head) { + if (!head.classList.contains("numCol")) { + head.onmousedown = mouseDownHandler; + } + }); + +} + +function getBoundingClientRectFromMultiple(elements) { + var elems = Array.from(elements); + + if (elems.length == 0) + return null; + + var box = elems.shift() + .getBoundingClientRect(); + + elems.forEach(function(elem) { + var elembox = elem.getBoundingClientRect(); + box.left = Math.min(elembox.left, box.left); + box.top = Math.min(elembox.top, box.top); + box.width += elembox.width; + box.height = Math.max(elembox.height, box.height); + }); + + return box; +} + +function cloneElementWithDimensions(elem) { + var newElem = elem.cloneNode(true); + newElem.style.height = window.getComputedStyle(elem).height; + newElem.style.width = window.getComputedStyle(elem).width; + return newElem; +} + +function getBomTableHeaderIndex(elem) { + const bh = document.getElementById('bomhead'); + const ths = Array.from(bh.querySelectorAll("th")); + return ths.indexOf(elem); +} + +function getColumnOrderName(elem) { + var cname = elem.getAttribute("col_name"); + if (cname === "bom-checkbox") + return "checkboxes"; + else + return cname; +} + +function resizableGrid(tablehead) { + var cols = tablehead.firstElementChild.children; + var rowWidth = tablehead.offsetWidth; + + for (var i = 1; i < cols.length; i++) { + if (cols[i].classList.contains("bom-checkbox")) + continue; + cols[i].style.width = ((cols[i].clientWidth - paddingDiff(cols[i])) * 100 / rowWidth) + '%'; + } + + for (var i = 1; i < cols.length - 1; i++) { + var div = document.createElement('div'); + div.className = "column-width-handle"; + cols[i].appendChild(div); + setListeners(div); + } + + function setListeners(div) { + var startX, curCol, nxtCol, curColWidth, nxtColWidth, rowWidth; + + div.addEventListener('mousedown', function(e) { + e.preventDefault(); + e.stopPropagation(); + + curCol = e.target.parentElement; + nxtCol = curCol.nextElementSibling; + startX = e.pageX; + + var padding = paddingDiff(curCol); + + rowWidth = curCol.parentElement.offsetWidth; + curColWidth = curCol.clientWidth - padding; + nxtColWidth = nxtCol.clientWidth - padding; + }); + + document.addEventListener('mousemove', function(e) { + if (startX) { + var diffX = e.pageX - startX; + diffX = -Math.min(-diffX, curColWidth - 20); + diffX = Math.min(diffX, nxtColWidth - 20); + + curCol.style.width = ((curColWidth + diffX) * 100 / rowWidth) + '%'; + nxtCol.style.width = ((nxtColWidth - diffX) * 100 / rowWidth) + '%'; + console.log(`${curColWidth + nxtColWidth} ${(curColWidth + diffX) * 100 / rowWidth + (nxtColWidth - diffX) * 100 / rowWidth}`); + } + }); + + document.addEventListener('mouseup', function(e) { + curCol = undefined; + nxtCol = undefined; + startX = undefined; + nxtColWidth = undefined; + curColWidth = undefined + }); + } + + function paddingDiff(col) { + + if (getStyleVal(col, 'box-sizing') == 'border-box') { + return 0; + } + + var padLeft = getStyleVal(col, 'padding-left'); + var padRight = getStyleVal(col, 'padding-right'); + return (parseInt(padLeft) + parseInt(padRight)); + + } + + function getStyleVal(elm, css) { + return (window.getComputedStyle(elm, null).getPropertyValue(css)) + } +} diff --git a/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/web/user-file-examples/user.css b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/web/user-file-examples/user.css new file mode 100644 index 000000000..80c5f0223 --- /dev/null +++ b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/web/user-file-examples/user.css @@ -0,0 +1 @@ +/* Add custom css styles and overrides here. */ diff --git a/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/web/user-file-examples/user.js b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/web/user-file-examples/user.js new file mode 100644 index 000000000..d74c019da --- /dev/null +++ b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/web/user-file-examples/user.js @@ -0,0 +1,4 @@ +// Example event listener. +// Event argument will always be {eventType, args} dict + +EventHandler.registerCallback(IBOM_EVENT_TYPES.ALL, (e) => console.log(e)); diff --git a/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/web/user-file-examples/userfooter.html b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/web/user-file-examples/userfooter.html new file mode 100644 index 000000000..76f6fa5ab --- /dev/null +++ b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/web/user-file-examples/userfooter.html @@ -0,0 +1,5 @@ + + +
+ Hello footer +
diff --git a/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/web/user-file-examples/userheader.html b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/web/user-file-examples/userheader.html new file mode 100644 index 000000000..ae0a31ca6 --- /dev/null +++ b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/web/user-file-examples/userheader.html @@ -0,0 +1,5 @@ + +
+ Hello header +
+
diff --git a/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/web/user.css b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/web/user.css new file mode 100644 index 000000000..a4f740cc0 --- /dev/null +++ b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/web/user.css @@ -0,0 +1,5 @@ +/* #bomhead { + position: sticky; + top: 0px; + z-index: 1; +} */ \ No newline at end of file diff --git a/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/web/user.js b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/web/user.js new file mode 100644 index 000000000..75bd28cc0 --- /dev/null +++ b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/web/user.js @@ -0,0 +1,6 @@ +// EventHandler.registerCallback(IBOM_EVENT_TYPES.BOM_BODY_CHANGE_EVENT, () => { +// for(var tr of bom.childNodes) { +// tr.onclick = tr.onmousemove; +// tr.onmousemove = null; +// }; +// }); diff --git a/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/web/util.js b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/web/util.js new file mode 100644 index 000000000..2b39eecba --- /dev/null +++ b/circuits/3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/web/util.js @@ -0,0 +1,638 @@ +/* Utility functions */ + +var storagePrefix = 'KiCad_HTML_BOM__' + pcbdata.metadata.title + '__' + + pcbdata.metadata.revision + '__#'; +var storage; + +function initStorage(key) { + try { + window.localStorage.getItem("blank"); + storage = window.localStorage; + } catch (e) { + // localStorage not available + } + if (!storage) { + try { + window.sessionStorage.getItem("blank"); + storage = window.sessionStorage; + } catch (e) { + // sessionStorage also not available + } + } +} + +function readStorage(key) { + if (storage) { + return storage.getItem(storagePrefix + key); + } else { + return null; + } +} + +function writeStorage(key, value) { + if (storage) { + storage.setItem(storagePrefix + key, value); + } +} + +function fancyDblClickHandler(el, onsingle, ondouble) { + return function () { + if (el.getAttribute("data-dblclick") == null) { + el.setAttribute("data-dblclick", 1); + setTimeout(function () { + if (el.getAttribute("data-dblclick") == 1) { + onsingle(); + } + el.removeAttribute("data-dblclick"); + }, 200); + } else { + el.removeAttribute("data-dblclick"); + ondouble(); + } + } +} + +function smoothScrollToRow(rowid) { + document.getElementById(rowid).scrollIntoView({ + behavior: "smooth", + block: "center", + inline: "nearest" + }); +} + +function focusInputField(input) { + input.scrollIntoView(false); + input.focus(); + input.select(); +} + +function saveBomTable(output) { + var text = ''; + for (var node of bomhead.childNodes[0].childNodes) { + if (node.firstChild) { + text += (output == 'csv' ? `"${node.firstChild.nodeValue}"` : node.firstChild.nodeValue); + } + if (node != bomhead.childNodes[0].lastChild) { + text += (output == 'csv' ? ',' : '\t'); + } + } + text += '\n'; + for (var row of bombody.childNodes) { + for (var cell of row.childNodes) { + let val = ''; + for (var node of cell.childNodes) { + if (node.nodeName == "INPUT") { + if (node.checked) { + val += '✓'; + } + } else if ((node.nodeName == "MARK") || (node.nodeName == "A")) { + val += node.firstChild.nodeValue; + } else { + val += node.nodeValue; + } + } + if (output == 'csv') { + val = val.replace(/\"/g, '\"\"'); // pair of double-quote characters + if (isNumeric(val)) { + val = +val; // use number + } else { + val = `"${val}"`; // enclosed within double-quote + } + } + text += val; + if (cell != row.lastChild) { + text += (output == 'csv' ? ',' : '\t'); + } + } + text += '\n'; + } + + if (output != 'clipboard') { + // To file: csv or txt + var blob = new Blob([text], { + type: `text/${output}` + }); + saveFile(`${pcbdata.metadata.title}.${output}`, blob); + } else { + // To clipboard + var textArea = document.createElement("textarea"); + textArea.classList.add('clipboard-temp'); + textArea.value = text; + + document.body.appendChild(textArea); + textArea.focus(); + textArea.select(); + + try { + if (document.execCommand('copy')) { + console.log('Bom copied to clipboard.'); + } + } catch (err) { + console.log('Can not copy to clipboard.'); + } + + document.body.removeChild(textArea); + } +} + +function isNumeric(str) { + /* https://stackoverflow.com/a/175787 */ + return (typeof str != "string" ? false : !isNaN(str) && !isNaN(parseFloat(str))); +} + +function removeGutterNode(node) { + for (var i = 0; i < node.childNodes.length; i++) { + if (node.childNodes[i].classList && + node.childNodes[i].classList.contains("gutter")) { + node.removeChild(node.childNodes[i]); + break; + } + } +} + +function cleanGutters() { + removeGutterNode(document.getElementById("bot")); + removeGutterNode(document.getElementById("canvasdiv")); +} + +var units = { + prefixes: { + giga: ["G", "g", "giga", "Giga", "GIGA"], + mega: ["M", "mega", "Mega", "MEGA"], + kilo: ["K", "k", "kilo", "Kilo", "KILO"], + milli: ["m", "milli", "Milli", "MILLI"], + micro: ["U", "u", "micro", "Micro", "MICRO", "μ", "µ"], // different utf8 μ + nano: ["N", "n", "nano", "Nano", "NANO"], + pico: ["P", "p", "pico", "Pico", "PICO"], + }, + unitsShort: ["R", "r", "Ω", "F", "f", "H", "h"], + unitsLong: [ + "OHM", "Ohm", "ohm", "ohms", + "FARAD", "Farad", "farad", + "HENRY", "Henry", "henry" + ], + getMultiplier: function (s) { + if (this.prefixes.giga.includes(s)) return 1e9; + if (this.prefixes.mega.includes(s)) return 1e6; + if (this.prefixes.kilo.includes(s)) return 1e3; + if (this.prefixes.milli.includes(s)) return 1e-3; + if (this.prefixes.micro.includes(s)) return 1e-6; + if (this.prefixes.nano.includes(s)) return 1e-9; + if (this.prefixes.pico.includes(s)) return 1e-12; + return 1; + }, + valueRegex: null, +} + +function initUtils() { + var allPrefixes = units.prefixes.giga + .concat(units.prefixes.mega) + .concat(units.prefixes.kilo) + .concat(units.prefixes.milli) + .concat(units.prefixes.micro) + .concat(units.prefixes.nano) + .concat(units.prefixes.pico); + var allUnits = units.unitsShort.concat(units.unitsLong); + units.valueRegex = new RegExp("^([0-9\.]+)" + + "\\s*(" + allPrefixes.join("|") + ")?" + + "(" + allUnits.join("|") + ")?" + + "(\\b.*)?$", ""); + units.valueAltRegex = new RegExp("^([0-9]*)" + + "(" + units.unitsShort.join("|") + ")?" + + "([GgMmKkUuNnPp])?" + + "([0-9]*)" + + "(\\b.*)?$", ""); + if (config.fields.includes("Value")) { + var index = config.fields.indexOf("Value"); + pcbdata.bom["parsedValues"] = {}; + for (var id in pcbdata.bom.fields) { + pcbdata.bom.parsedValues[id] = parseValue(pcbdata.bom.fields[id][index]) + } + } +} + +function parseValue(val, ref) { + var inferUnit = (unit, ref) => { + if (unit) { + unit = unit.toLowerCase(); + if (unit == 'Ω' || unit == "ohm" || unit == "ohms") { + unit = 'r'; + } + unit = unit[0]; + } else { + ref = /^([a-z]+)\d+$/i.exec(ref); + if (ref) { + ref = ref[1].toLowerCase(); + if (ref == "c") unit = 'f'; + else if (ref == "l") unit = 'h'; + else if (ref == "r" || ref == "rv") unit = 'r'; + else unit = null; + } + } + return unit; + }; + val = val.replace(/,/g, ""); + var match = units.valueRegex.exec(val); + var unit; + if (match) { + val = parseFloat(match[1]); + if (match[2]) { + val = val * units.getMultiplier(match[2]); + } + unit = inferUnit(match[3], ref); + if (!unit) return null; + else return { + val: val, + unit: unit, + extra: match[4], + } + } + match = units.valueAltRegex.exec(val); + if (match && (match[1] || match[4])) { + val = parseFloat(match[1] + "." + match[4]); + if (match[3]) { + val = val * units.getMultiplier(match[3]); + } + unit = inferUnit(match[2], ref); + if (!unit) return null; + else return { + val: val, + unit: unit, + extra: match[5], + } + } + return null; +} + +function valueCompare(a, b, stra, strb) { + if (a === null && b === null) { + // Failed to parse both values, compare them as strings. + if (stra != strb) return stra > strb ? 1 : -1; + else return 0; + } else if (a === null) { + return 1; + } else if (b === null) { + return -1; + } else { + if (a.unit != b.unit) return a.unit > b.unit ? 1 : -1; + else if (a.val != b.val) return a.val > b.val ? 1 : -1; + else if (a.extra != b.extra) return a.extra > b.extra ? 1 : -1; + else return 0; + } +} + +function validateSaveImgDimension(element) { + var valid = false; + var intValue = 0; + if (/^[1-9]\d*$/.test(element.value)) { + intValue = parseInt(element.value); + if (intValue <= 16000) { + valid = true; + } + } + if (valid) { + element.classList.remove("invalid"); + } else { + element.classList.add("invalid"); + } + return intValue; +} + +function saveImage(layer) { + var width = validateSaveImgDimension(document.getElementById("render-save-width")); + var height = validateSaveImgDimension(document.getElementById("render-save-height")); + var bgcolor = null; + if (!document.getElementById("render-save-transparent").checked) { + var style = getComputedStyle(topmostdiv); + bgcolor = style.getPropertyValue("background-color"); + } + if (!width || !height) return; + + // Prepare image + var canvas = document.createElement("canvas"); + var layerdict = { + transform: { + x: 0, + y: 0, + s: 1, + panx: 0, + pany: 0, + zoom: 1, + }, + bg: canvas, + fab: canvas, + silk: canvas, + highlight: canvas, + layer: layer, + } + // Do the rendering + recalcLayerScale(layerdict, width, height); + prepareLayer(layerdict); + clearCanvas(canvas, bgcolor); + drawBackground(layerdict, false); + drawHighlightsOnLayer(layerdict, false); + + // Save image + var imgdata = canvas.toDataURL("image/png"); + + var filename = pcbdata.metadata.title; + if (pcbdata.metadata.revision) { + filename += `.${pcbdata.metadata.revision}`; + } + filename += `.${layer}.png`; + saveFile(filename, dataURLtoBlob(imgdata)); +} + +function saveSettings() { + var data = { + type: "InteractiveHtmlBom settings", + version: 1, + pcbmetadata: pcbdata.metadata, + settings: settings, + } + var blob = new Blob([JSON.stringify(data, null, 4)], { + type: "application/json" + }); + saveFile(`${pcbdata.metadata.title}.settings.json`, blob); +} + +function loadSettings() { + var input = document.createElement("input"); + input.type = "file"; + input.accept = ".settings.json"; + input.onchange = function (e) { + var file = e.target.files[0]; + var reader = new FileReader(); + reader.onload = readerEvent => { + var content = readerEvent.target.result; + var newSettings; + try { + newSettings = JSON.parse(content); + } catch (e) { + alert("Selected file is not InteractiveHtmlBom settings file."); + return; + } + if (newSettings.type != "InteractiveHtmlBom settings") { + alert("Selected file is not InteractiveHtmlBom settings file."); + return; + } + var metadataMatches = newSettings.hasOwnProperty("pcbmetadata"); + if (metadataMatches) { + for (var k in pcbdata.metadata) { + if (!newSettings.pcbmetadata.hasOwnProperty(k) || newSettings.pcbmetadata[k] != pcbdata.metadata[k]) { + metadataMatches = false; + } + } + } + if (!metadataMatches) { + var currentMetadata = JSON.stringify(pcbdata.metadata, null, 4); + var fileMetadata = JSON.stringify(newSettings.pcbmetadata, null, 4); + if (!confirm( + `Settins file metadata does not match current metadata.\n\n` + + `Page metadata:\n${currentMetadata}\n\n` + + `Settings file metadata:\n${fileMetadata}\n\n` + + `Press OK if you would like to import settings anyway.`)) { + return; + } + } + overwriteSettings(newSettings.settings); + } + reader.readAsText(file, 'UTF-8'); + } + input.click(); +} + +function resetSettings() { + if (!confirm( + `This will reset all checkbox states and other settings.\n\n` + + `Press OK if you want to continue.`)) { + return; + } + if (storage) { + var keys = []; + for (var i = 0; i < storage.length; i++) { + var key = storage.key(i); + if (key.startsWith(storagePrefix)) keys.push(key); + } + for (var key of keys) storage.removeItem(key); + } + location.reload(); +} + +function overwriteSettings(newSettings) { + initDone = false; + Object.assign(settings, newSettings); + writeStorage("bomlayout", settings.bomlayout); + writeStorage("bommode", settings.bommode); + writeStorage("canvaslayout", settings.canvaslayout); + writeStorage("bomCheckboxes", settings.checkboxes.join(",")); + document.getElementById("bomCheckboxes").value = settings.checkboxes.join(","); + for (var checkbox of settings.checkboxes) { + writeStorage("checkbox_" + checkbox, settings.checkboxStoredRefs[checkbox]); + } + writeStorage("markWhenChecked", settings.markWhenChecked); + padsVisible(settings.renderPads); + document.getElementById("padsCheckbox").checked = settings.renderPads; + fabricationVisible(settings.renderFabrication); + document.getElementById("fabricationCheckbox").checked = settings.renderFabrication; + silkscreenVisible(settings.renderSilkscreen); + document.getElementById("silkscreenCheckbox").checked = settings.renderSilkscreen; + referencesVisible(settings.renderReferences); + document.getElementById("referencesCheckbox").checked = settings.renderReferences; + valuesVisible(settings.renderValues); + document.getElementById("valuesCheckbox").checked = settings.renderValues; + tracksVisible(settings.renderTracks); + document.getElementById("tracksCheckbox").checked = settings.renderTracks; + zonesVisible(settings.renderZones); + document.getElementById("zonesCheckbox").checked = settings.renderZones; + dnpOutline(settings.renderDnpOutline); + document.getElementById("dnpOutlineCheckbox").checked = settings.renderDnpOutline; + setRedrawOnDrag(settings.redrawOnDrag); + document.getElementById("dragCheckbox").checked = settings.redrawOnDrag; + setDarkMode(settings.darkMode); + document.getElementById("darkmodeCheckbox").checked = settings.darkMode; + setHighlightPin1(settings.highlightpin1); + document.forms.highlightpin1.highlightpin1.value = settings.highlightpin1; + writeStorage("boardRotation", settings.boardRotation); + document.getElementById("boardRotation").value = settings.boardRotation / 5; + document.getElementById("rotationDegree").textContent = settings.boardRotation; + setOffsetBackRotation(settings.offsetBackRotation); + document.getElementById("offsetBackRotationCheckbox").checked = settings.offsetBackRotation; + initDone = true; + prepCheckboxes(); + changeBomLayout(settings.bomlayout); +} + +function saveFile(filename, blob) { + var link = document.createElement("a"); + var objurl = URL.createObjectURL(blob); + link.download = filename; + link.href = objurl; + link.click(); +} + +function dataURLtoBlob(dataurl) { + var arr = dataurl.split(','), + mime = arr[0].match(/:(.*?);/)[1], + bstr = atob(arr[1]), + n = bstr.length, + u8arr = new Uint8Array(n); + while (n--) { + u8arr[n] = bstr.charCodeAt(n); + } + return new Blob([u8arr], { + type: mime + }); +} + +var settings = { + canvaslayout: "FB", + bomlayout: "left-right", + bommode: "grouped", + checkboxes: [], + checkboxStoredRefs: {}, + darkMode: false, + highlightpin1: "none", + redrawOnDrag: true, + boardRotation: 0, + offsetBackRotation: false, + renderPads: true, + renderReferences: true, + renderValues: true, + renderSilkscreen: true, + renderFabrication: true, + renderDnpOutline: false, + renderTracks: true, + renderZones: true, + columnOrder: [], + hiddenColumns: [], + netColors: {}, +} + +function initDefaults() { + settings.bomlayout = readStorage("bomlayout"); + if (settings.bomlayout === null) { + settings.bomlayout = config.bom_view; + } + if (!['bom-only', 'left-right', 'top-bottom'].includes(settings.bomlayout)) { + settings.bomlayout = config.bom_view; + } + settings.bommode = readStorage("bommode"); + if (settings.bommode === null) { + settings.bommode = "grouped"; + } + if (settings.bommode == "netlist" && !pcbdata.nets) { + settings.bommode = "grouped"; + } + if (!["grouped", "ungrouped", "netlist"].includes(settings.bommode)) { + settings.bommode = "grouped"; + } + settings.canvaslayout = readStorage("canvaslayout"); + if (settings.canvaslayout === null) { + settings.canvaslayout = config.layer_view; + } + var bomCheckboxes = readStorage("bomCheckboxes"); + if (bomCheckboxes === null) { + bomCheckboxes = config.checkboxes; + } + settings.checkboxes = bomCheckboxes.split(",").filter((e) => e); + document.getElementById("bomCheckboxes").value = bomCheckboxes; + + var highlightpin1 = readStorage("highlightpin1") || config.highlight_pin1; + if (highlightpin1 === "false") highlightpin1 = "none"; + if (highlightpin1 === "true") highlightpin1 = "all"; + setHighlightPin1(highlightpin1); + document.forms.highlightpin1.highlightpin1.value = highlightpin1; + + settings.markWhenChecked = readStorage("markWhenChecked") || ""; + populateMarkWhenCheckedOptions(); + + function initBooleanSetting(storageString, def, elementId, func) { + var b = readStorage(storageString); + if (b === null) { + b = def; + } else { + b = (b == "true"); + } + document.getElementById(elementId).checked = b; + func(b); + } + + initBooleanSetting("padsVisible", config.show_pads, "padsCheckbox", padsVisible); + initBooleanSetting("fabricationVisible", config.show_fabrication, "fabricationCheckbox", fabricationVisible); + initBooleanSetting("silkscreenVisible", config.show_silkscreen, "silkscreenCheckbox", silkscreenVisible); + initBooleanSetting("referencesVisible", true, "referencesCheckbox", referencesVisible); + initBooleanSetting("valuesVisible", true, "valuesCheckbox", valuesVisible); + if ("tracks" in pcbdata) { + initBooleanSetting("tracksVisible", true, "tracksCheckbox", tracksVisible); + initBooleanSetting("zonesVisible", true, "zonesCheckbox", zonesVisible); + } else { + document.getElementById("tracksAndZonesCheckboxes").style.display = "none"; + tracksVisible(false); + zonesVisible(false); + } + initBooleanSetting("dnpOutline", false, "dnpOutlineCheckbox", dnpOutline); + initBooleanSetting("redrawOnDrag", config.redraw_on_drag, "dragCheckbox", setRedrawOnDrag); + initBooleanSetting("darkmode", config.dark_mode, "darkmodeCheckbox", setDarkMode); + + var fields = ["checkboxes", "References"].concat(config.fields).concat(["Quantity"]); + var hcols = JSON.parse(readStorage("hiddenColumns")); + if (hcols === null) { + hcols = []; + } + settings.hiddenColumns = hcols.filter(e => fields.includes(e)); + + var cord = JSON.parse(readStorage("columnOrder")); + if (cord === null) { + cord = fields; + } else { + cord = cord.filter(e => fields.includes(e)); + if (cord.length != fields.length) + cord = fields; + } + settings.columnOrder = cord; + + settings.boardRotation = readStorage("boardRotation"); + if (settings.boardRotation === null) { + settings.boardRotation = config.board_rotation * 5; + } else { + settings.boardRotation = parseInt(settings.boardRotation); + } + document.getElementById("boardRotation").value = settings.boardRotation / 5; + document.getElementById("rotationDegree").textContent = settings.boardRotation; + initBooleanSetting("offsetBackRotation", config.offset_back_rotation, "offsetBackRotationCheckbox", setOffsetBackRotation); + + settings.netColors = JSON.parse(readStorage("netColors")) || {}; +} + +// Helper classes for user js callbacks. + +const IBOM_EVENT_TYPES = { + ALL: "all", + HIGHLIGHT_EVENT: "highlightEvent", + CHECKBOX_CHANGE_EVENT: "checkboxChangeEvent", + BOM_BODY_CHANGE_EVENT: "bomBodyChangeEvent", +} + +const EventHandler = { + callbacks: {}, + init: function () { + for (eventType of Object.values(IBOM_EVENT_TYPES)) + this.callbacks[eventType] = []; + }, + registerCallback: function (eventType, callback) { + this.callbacks[eventType].push(callback); + }, + emitEvent: function (eventType, eventArgs) { + event = { + eventType: eventType, + args: eventArgs, + } + var callback; + for (callback of this.callbacks[eventType]) + callback(event); + for (callback of this.callbacks[IBOM_EVENT_TYPES.ALL]) + callback(event); + } +} +EventHandler.init(); diff --git a/circuits/3rdparty/resources/org_openscopeproject_InteractiveHtmlBom/icon.png b/circuits/3rdparty/resources/org_openscopeproject_InteractiveHtmlBom/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..d99fcc8315be6d1aa1d95497ed9dbebfd4867557 GIT binary patch literal 2105 zcmV-92*&q`P)W4hxd&XEy|N_Yc)hR>=>2W!R?;TKQ~0e+7Ou-BW$Xw51nf$Nt!sqc51@uF2sOT? zwu|2uf5hc~w+*O5gH30Po6Z(D^=BNszvDd1UYg3%ZBs$8#etB(j{y|W+5mRKCH9pHCQeN5ZcZU9uP!jhj%q3FqM zY-yH$E8%hZc_HhtF4^z>ehyiMNxJXt?)2gJ1|rURy8~2x*u;r9F3{cX1>lo+E|E4N zf#U6j2*l3aa_JE@*xQp=`9UL9|7Zq4F$sR~?g9#yjMlA0EL5vsx9sRCiDb`C>Gw15 zTb{|{&H4Oh#YfbibpUX5=Xr{r%w|l%$Q&yPk0}C*0ZzYtQM+)#+MEGx{M{ruYXlq1 z9w0Hp3P8XoIli~1r&g>~f!P4nCtI|Oik`|IY&~Og__6NWl3)H_oK{X8Wo7Z^d=9<% zIRIZAZ46b-R)Ns~ZC72|1({P5`}Oc>O5AO7=cQ@oYxT}hF-rk#03K&JMlJCw!woe~ z(aPR#t*ti0wlsaFLds+%wqOhlYk-Vd3b`x$ufDE345e5eXbkHCo(|}`Dx=m}Yyxv) z)T%xh)&SLZAJukW)Vkc2D$~~LYg$w(=XDQ0x9QHci-O0cKNB2Gq8dPN&ORJ4YzT~b z&_u?p=)<6Ge4lxqn_^f4Bu^BKeWd?ksu`g749&el|5GW0^M3=}Z3XT&S|2dbv$C-m z>^{eJ-K&-3lg(QBp7DUD>Q1ekm=S)rG0ZU7-xspa4`0>FIrCDra#RB>+BAv0`RV<7 zU~g*v*}}13eKnx>)c@>OzBt;T9TzUk)XGr}kW-Y#?2@qqszksqfx$OGQ*|eAK7I<> z^WvDEo4~B^gxhAA5V&1Bn%$J|tE21}l{kAkKp|kwu9+xmI8`2!26(;X6y~@)>z@OD ziO1!qqtT6&k@E#hw@qcniZK!AhNJ-;mz}YNZUd95P_kGn_>-hXW$^Ols(%#rj@%F+9`5_qs8xGEoSje~&x>`My z@2lg;&ns~{f**#w|MHhin48M|#aWu%unmEPGz*Kj1*2gVHpA!{^F)m!)Lp_EPB(5h!F{fHNcI-AVAu5 z3&+;F@pJ@-zwTB^Yej(c8Mk(F!{!0KFE~z=_$I~8ZfW&db*Z}8tdT&{88z)HC@ge1~%L4!`Nigeq3qnVLt3W4U zv&5UU?}fcX^oy=rVX{JEw%{9cOk^)JVM&a1e_wYvFEGbxV`IAtTmkY^#>LZkz5{^z zGuN2^{RxAhwtg19Wd(VYsqGOW=6GLI-l~;Tv$Z#;D~dp#1(@_$<47>tF+^SM?;%IBcoZW? z$Kkr}y_pxra`h^K z*a75)&dGp`m`MdNSrn`ZhDs!B1Uw)5=R-vG^Wbh$xdOyWU>3pc^R{TRLzqtBvP7H( j`K}fy5tVbN!t1oVeVy6pbYH1f8Nh zFy(|4jhY}@blACk;~bOx!qEaKko^B&JN#emh9%$Y1pp8b6xjbmZAWVpWi8u7df2a7 z3Sd8U0b)13o`Ku~b;wHLF-<;Vap#TZv+Xoh8c&>4vZrYFVsivO_%WmB1DEFI#rq)K zGX-pCHTj-i0ph2x`Y@I7c%X=yN0x6$>TLb#;Zj)xzZTu&2s#nn{*YYEaW)Nc`R|qe zec#D~zp@K9D8ADRW^fZV}bW9@+|pEoTnfL3(?uFrCNNYUDO>u;1?vx^POS zZ<>Td)yIxDn%(Fo?I^guZhUrP9;pSuPBG-O8O+)f@&!WXfon8~Cc>ps1K`j#qetM^ z>@8UU_o;h(M7qjT(r)~zDzj6btd52|uf#t?34$+U?ak6s)W6Dn1afO2K%SR&I)QI9 zL_BO)m-4Al~Sr$n82=A;D86yQ`trchLnZJF~W#YJl zAKwy_{ONAX$Rf+=K0Ss@+l|Qh$YyOH9+keH#=TyjI`DC;^$5_tYrmeJd_SOBWj^1W zd{|j?KvO*kfvX`ZiQBTD-Q_f~K)1rA;>jbz6EpUP7okgA7I3)i#Yt;+h$b*ho`8la zk9?)cfs>72Fe(uN3QqEb^$a^t1al6|r2~x0gQW7M$u!LIxfbN*F#(gnDO9<{G4;O=alo%Uko+5-Ek zVL*Pmjrs%>!oSODJg(*^){24q6nHfO=@p4zGQdZ69M!}HpPk%UUa|>ZLz3En<@atv zpE>`Vlq)r%6x81kBrQ=u6^E?I)y#FfX+r(;!Dmuwi2vSlK9RW7j1`h{TLl16x+=Hi z&v~L{QPs3+M_g;?aDOa~PZ`z^UWR?Pl`Pu(m!m6SiNC-?vE^PM$Z?0#C4k*hB#CyO z<+yla+2!JCx=0D7*e89YepIDWGdm=)Hbm!B6tY-Np}~ru41apzFX|pMKFmfBUsFEs zU<`?-iVuzZ)JIe+dsjFiGx}gukYP5ntgi;ksRVvtDUxlX{P)9!OJtwcAG7DarV+z? zA4pc?A^azHkGJG}1w0$~=8|RkwHwl{YJ^?U!%Ez~ThxmopKB4+W0u;=oO)DrvPP6b z?AQCCJ-)5Q-;&z|!T~j2=op}!?JA8r=rKSo@SW!gp)4pO-0m`a%$ErLl7>(G3Xm+n z6-s>|Awy*bARR;!G6%du8>%s)tsxLFwQ{2Fr9=Z(VHJ0D1qcfN{JLJXv0wh)6hGIV zGiHNys4j3$_CP<8sB|2*-DZM>ZW2TaZ`vBomBUiFVxT;fmakXf&#g72&T#AMGN|VN zUMR`j$7W+18m#B-KX9hDxcWSAd(Gj^=YUvsWE`j3YsV$zhP#e*l>0E)b8lM)!41FO z;d_@?S3oO*bDza1W(G4A4I;)Yl|V1hOaYU86#{dS7g~1;?X`i@mD_PY_g}M4?jlf4 ztH$ZgliS$8b70!(dca^KAoM(X5Zk&#(z?>H-U%%p0;s-J0 zHPu%j{%h?uxFf3h!_ir_384?Od^W)w;jpT5(PW+L&;*>cBd>-CKiWrY!+;I2ooD=B z$}ZpN=ajLwSHzMmp<0?~ge_$7SH}IOzyyvyK74b|lCszoX!#$}slO_d7uj2}i0kAx z=cZB)7rhHo*sH)Gowgmuh0rIUz4MPe40qV%U z;#KlV3j8D+og)XQ{oy6v?fsyi({jlVYj)!(3&rj>fsAqujmVrUEca3;_paj#*rGHT zkRVddKwB&0gtK1fyRWVVXG~ki@HV*oj1w7S|65{}Aw6W4h+4A#xP1J4K63p0et!J? z@bL6LGV)B}@on8wIAzAHL({qDeW|U`f<)%BP#0KZQC8I_l)IJp1@XVGkRZaEZ13rS zfR<^1piPA^;=R^Bfs%)KO#!A#9+v3!E*2Mbz z0o~o^{nzx7PKUO)pX_c}l=tJrW|Y%7s~?+(v!Z1Oxmg8wCill?(a7VV_rh6f2h?dz zBJ#`m!J#4*vCjC@#G$7ztKJu4QpVq1;QQd~UTWX3q+>tapUVqJ-l|*DvXU9}yyp{p zqVd`Nr^w)T1tGa#tDJuL9KGCpd3`^!5;12 zI?xe!ePf9LUIzv*t}qa4G?RzJt~Qeg>qJ#>FCvVhpBUQtKC?x?G`GH7y(1}cXPQya zMjV0U4_8gIGAI6FK^{NeXjrPXvu@+bQt$UQ7;cj69!{Dm0PX3%;W2lNO^kYs_RK@^ zXY`Bp4jwLwa3MEjSiVnuI33XnkC^D+4Npc z>}AQDd=-jiRRsi6(rC$+jYt-Xd#GY(%g@eTsmZ3tO_6SwmM#&nY>I}Ct%dtIlMaok zf^oQ84PR@`vh978_m{6HoQb}#o;E7!_oI8e+i}14WhsbE=e%&$ssV@`6>8_+H+?76 zQH8I+rp{4cx#!cE4J#eT5Z3S0Vr&^9r6N{6nvxqna|06xK`|50ekOn3yW7;9<1WIg z!P@IpiAtUI_>ct93*?$dVTpD0S$Ng7ac8{RBG&dNO2dQV;wTF&ds4H2FI4M;pxm)P z_gAmXxRSTdwb`5x`}G;PvbuSGTC}C_!*aLwVo|KoG*4|y`o_wRuTVh=#I=2d*9ja; z`@WtY<}VUJDmjR=+~%jP*7-EDCfAp<#5<_)44!h44yb3x@8XSv7dM$3AVEIM4@8(M z35OF<2VRs0&59@mVyl9=v;zl%0HLM_Zd7|!x4O}l0G3AZ!Q(B+#eL`}tWkzm zPP*?R=;XX#N_KPsIHk>wV%L}a2zV$xso-u(_aEMl97K`K9qd2Pj}mRa-^xE@CK|1^ zAC4T=4ewu z#|n-&FO#$m?tpE{E)m=5&Iy5k{L>l1U3f7Vc1!(B@h)A-4PZCCffT=asfB%nsf~$w z>jwmv{6nabl7H&s5nk?IO$aXdsE-iF1ebcLjf*%}kHNYmox)=7ehMV<#7AQsSxs`g zDA&VK8{|N3*Rn0fHb#9gvb+#zAHztTKN&Z6DKb9mqg|u1&h{y*H51KW6s?q2`yeFZPz&IT=YW132_SHz4Gx4 z=iYZd_0-&Q8RXDliH7KmJ^A+71f2hTjuo+5uPe7V=((P)X9n()IZ;%XWWMAY2r-;N|OhSq*oZC~gn&$ydG2V1yF?MfcXE zEv3utbN_aJyM7u=GMnwoqc#45`-zWUOxx`}qo`>5BedF}J9}zJm&fY?>_+i8g*FKJKi!K2etY33wN?&MwihqKFj@n|{!dQ%(XKD+TO z2x6&jc1L%btk)#z{arXS_3zjF(PtHh4`k5Wd%FW`SvF}-CE3UA7<|)e=m!|)1$s__ zZ$Qeo;7`WN2Moq}z~S9o(ktX-FzqE=$9CAX!^e7?tl2C$ODlC8b(Z=k(>iAX!Z@9) z)EY@36%>>?A14&ord|k`$rvoOqXj7?!E;~+Z zoG8=1YCapjx$!M4;R38b45WXqjL>dKZ7wJt>lt?pfvmbL-EhQ=va%#scYkVM7jMF? zs)StnlIlf04go_O&j~{aXevL*%e?B!LkC}v^GA;ph2B3uR?b0aFL1U!?ekRSuafpb zz+ShwvHQEYII|X$UPJGuQNwsxvw-wPx;~GWN%_T`@E@_TTVJ5R?~gi(d`_ zf5&Yc=yp??LAYsUT5|QIPmWP~KP(?slTMTL^oCf`c)2A`=|`c~Hyi*xxuI%f{*NgR zz>DkP{WdEm-+RH&sy*Fy)m>1!Q@wrg_TZRHjK6HZjuQm8fmTmTvUPgBK8#-RmLH0C z2tSl|v7;@oLF%fupqGXy>ToGF@B6K!c0nrB(4DAzaigN~G{XU|crZ^{cB?(yd^yK0dY}AhI}V$goUw+QPHO@el#YoN- zsdp_Kw7*j_17uF-!0GAwrpe-PVWxMuv$~=BXykTiUFAD3Q&EXi*Z`gwj1Y)U$Kp}x z&4JI@6}DdW*3)!LKG!$McwpmDQwdZ?=3f(a3aSA zT)?IjrmM5b?}XTww|Cu1dwFoYo>0oTafwfjEnUic9iDJE!0URuB?lqb_377Vxd_9N zqYIh8c7cQ1-D8NA5yF@>3r;|lL* z#WoF#U1^$EPZ_~%6qOut)u}~`Y!#XfWH+7XO|m41xk`MTK1ro6UW2uHyo*O%|L*+R zADIu;8;DlmKhym#PfuA%r@PVGk!oV6_K|JAeC4Qn_Gt1|Wqz1?bYf&qk}Z~e)u@Ia ze`0ot@?&*vl}n#L_p9R<&2piix~aHgtJ4!SZr%?9N3>WLp6PBpuhws@s(G83d zyw&St9N5g^9c|`J#g-4AM-^M8t#fBON2tFathbi*;{MFuE(o;&8v1ZY;W0gp6@52D z46k@j_*|Rk#MXcY&%lbUo6qk5iCE4dh!yuoWx!jWI-xNhPyy{NROYKbY zcg8XL{$@+gEK=)8`?93diM}E>>U*`re?>vT2 zj%ROrgJyf}f=ClN**bj{X-Dxa@;EM>ukOZ3HSz-MICEWexfpcvjyp6wzCmoD;h=Z5 z2yBiV0Ob@El@M>IY1JLB-@nv?QLt4%S8WP*zPi!a9iBJ8oj=<}d%;cVAh{}c`1zQS z?c3zVQSIw+?p(@FmG-^6dTTm;Jvv2guWe`QD{bWX$$r0o9k*jYjq!=Lxz5gQZ_6*@ z{mkbSYiT>uJ05N!A_t5-gX0Mi;>V>!GXL#O<>}NUPmGar9`(iJ{{DH>Q!~rq{BD*H z6f>!jXjs&&7L&xw#_EV| zNzEN`clJW&NUKFkrr9>rvr0rIRq44XtZ*-0A%tASB%{CXXrf`jxbrMN)#XZCtNHF5 z$6Rvu3oEV0Hd&(jJ|T*9>Bz`IT4MCZy||@j@Bwm}@{uVTr+vQEI0rcj7TAR~qaX9>aPUu7xJUeCzRt4{muQvZzrksly)y(;Z=2pTinj zRTP7ao$vlvmtV+I$^wz2%3%`D=bg*s#V0E{ir6=3x@vnZR z#s!R~`ZN(jEnu_Cp)8`N8dWR7;F~I+y|{s5kkj?Cv?%lBxGskPHn_CVj&Lwp>oijm z>X#nVjD0ZDJqc|`^H%6TjE?x#<*HCAB~oq{t`XkP?_NgX54May|SWZq(T)|eGQ=Y6KN?67Djz90ih zv9@b$1b#6%Lo!vqhxIRs`oWP^QWSl|7Zq_0YiG(^tR|@u2qR5IAd8r0YJt3JLRXJn z^UG|sh6nA|KRF!cjtW<2apxvzumA!pI|jE)tW%;uL&FuUw4n7GIrjkOzYI||zuklP z=@S*fz63zn+JlwUbRm^oW6w7RmaL8`IA!fhLeu}Gj6$ek)9AO~Vd$i+bqM2+`Y?du zR~sK^-9%BU-vga2vL{GI=&JpjK28O5wq1|)rR5<*$ASDumtvgZw5yoau>{z4-fUeQ zLw}xZB>c1c&4r5$p61L%+XLKXLjCjM1~#@YdvC;mFkv$Xz(MWBpduKm>ia>s$DOLX zwhSMq7* z_|K0)!oY!5lL5+#qeLXss?5B`&$Z^oNJpYfDF#WCLdKBiL{jrZVXs92@sr+V5sHD_ z7)>kC<5rbnAQYGa9y+oy!(ouM%RnYKxJm@$w6kn4W1ufs2-u04+&hEP4DJ4Hq&L)V z4AxC^C0>&&uc*+KunR=vdnC;lzZ$$*YYnQ~4M`9f!gP#kyUI>@>A^wwfuzkDK(2vu zfhbGBqSOU4T+f}15}JiwkCJU*1F{#uh^L9S@l7JciK~|l$YQIFl2}73E`TS>CAjx+ z8j*|j>E!?`@$NmFDgBn`SAlm^ZlyKgEfX9AaHe$hr@`)5IzY>lqV}=mX@Xmg57CTW z&nc^|;M9<3iL>-x@VXaNf0T)~^-~#)JGlZfm|!>bJY`-Cs{we7VCH$C>|}~e1dWE0 zX1K_kEaeO|*wVP!QyEACqT=!c0YnlGN3a`G=N)wpWgISDr2m2@E1C!{5~74PiAzL0 z!(b(h{wtz+F`IK`W0uCh4@!^PPIi&Ogg3Z z3Alv=Bu0~_WXgbA1{~`Wbi%YOM;*-Ls!=COqe6U=x)OQ{^gRTkG4NvTptZ(Z%4}VT zu~tp}2H+4!BtDv$0x88TQ(L zur}xEM!L9OfJ{D~HsXoMO}*&euTHe$jc(8BR{TZFm{5TouSiS{R{bLT8FS1d=FWyc zgA65c^VffP%em+98u5=*-Q$xZFW4}+Ne!?t3CGPPfO=@U1tL}N;eg--13!R-^o#jD zW9N%PtWJda<9n7YVeHgt6RchQ#(~yCHn4V%q5NI=A^GD_6SyCc>JDY4bzcjARZoqZ zWJW>)&oYnmK&#@E=0{GU1=yAi)LAeMLpq6N;u9`ML@$VUQP*^*NE$srPH=@4V=dcD z=fPssyzWg&YAp-rYZ*mNs5|c$ZdFV_E7MYv(MxR06GViE2XYEH{c0`m9F)T*j~pDpr(D zdT@y$W=qlH@f4$}LCXHy5x6D(1?`Y4gsX)$UIg=q;L6 zW@K=2X)3~nO3Eqqb%54RbR6_z5f#YC2X zDI`tA)Iy^$leSmhmrQKLfHU4mbeXux&3mqKG0qBzn8SyNl4zv9wry>;mF8HA=Kj^NfEj7;FB?|B zlYC*IF-ok_%6{5N+9-sO-7(m3#pekGz$bU-(qqvh}R~PLImmWVf$O5%( zL#ls4T#M0;G{Zrvvx5`SVdb%#=@?=KE@?EtWKf8Tiy+0nwKPnSF=K0H+a3EPl3b2R z0mvARWx*_)u=hH)d=W?XUdtG&8<{2q(GxbI!~%Q*7ZUZHyW12s%|EUOSND-z33LGN6PRmG5VYLxxVbb8q!b@e0<|2r{Q)A*P@~5Qs3Z7*zS^WX z$+S}~Q<~8qnZ($@oAWn2S58v&r%i}oZckdK5Z}}*jHI8TJiu1P08jt~be&+|i=PF&1ErxuOOpaRkd`0F5L@x#Pi_ zmnyYG{L_?5BxO?QGKC&Yi4kzjnmeB=MEYh}pOD|K{5x30zC*=mSS6LZ zyf1mR`>Zz*DoC2^ZjRp6oPwiKJ_rahCL>#jaj?uL5bos;&CX9tbp4X1)ho)>iF!O3 z+a>|4QaDS2R3T;+0+XOeMdMJ< zNFu|qPq6xFuPMq^8@!J6lt|L!(!yCoIfw^f0R1&7(GKwk{_bx*SOtDe6FHj@#c=mG z&I~&sf{d?{z^4M!coaw(#X7C`_gA}ZJ&&q1uKMzDe4Kbb`RO?h^k@)YV3#KwVMk<& zb5Vwdl`JK^V2z=1NNG@|o%ZcfIok=;NG&vOrKrGvjRsJoh_4W*QWs0xPuSeCz(xd- zzsu*(&7jZX*z0-?6CEcYI|dWh$5htHf!TIUkAKKm!VIXs4+??73>*QoKSORL8wZbi z6x%9dnKiNyV)b&N*eEtYgb@~b6Jyv|7QiWtRv1B5FsJ2e+$NZ%+RSZ)RZGN~@?p@z zGIm@fkfO_>B=ECJV(_V{x)U4GrrJPXcIhJw<6b1HQ`STs%S6!oiDXbS<}B1J!!;gi zZ@D71P9U&lCf(3z*5t!wX2P2ftpTwKg4)vWx4_#=5VR_;!Y%6gIQB@n=uPyiH5KeI z7qN(oI3men@;tEH=9H!)s}NRQ-MPiUJp;11pT5zy$@7&TG`k z$AlRn#wl5&-2lGmdeG*B(ObT}p-MH|n2^jF5L8@7Id?x=QcEdTm4ytJZ{;H1=KrB2 z=0W-5K^Kq&B@8byUyXc0B``HC3?8JOGNgJ#z+xu*8`oJ{2@yfc?1oA!kzz_L4)zPJ z8_W_i*AiZO)rO>8;A2gS9Pjr?&}?E%G&>U}R$ zM_AsO;(-)(!;wyaMZkP@iCBQn8m+*VBrY;+g8)bn9+6AdNKR zxQ5Y)M8CF2Zcquw#K3q_a9~{(Lo-$99FfPChGZxHYr>PGW@SUa_i{&-Xm#d9-hsFYv!t^^dTU=Jj*_9c{bYKKHi?G(^87_wCP4- zAo;=;sXV`0Bv--mwJ&yN`;G(ja`R?)b^pwqxSx#<`SyJ9ez>&47(L*=Al)*K?va35e zHuTh(p`E2e%WdVX!Slz7%f%0=-oY0U>I@IJ2@#YG7A6kh&!X0jU40GV=~aK9X}R?7 z{K~@a+vOhbj39r!dGIe=b%WG4nrx&I{iNOGf-Z%m^*<6XF9EIhk6uV+Gnc-Hx&*kV zNZSr2=MA@vP@4^fSaX>Y3j)w~9l}NB;OeFUY z@2DV9Pia;XNN)k8(gk+$S`r39yfJ4JfhblRS1MkTn$QNT6b2^Oz~zI3um^>iM_etE zazgU=*bsJtAC)Ulccf{>V!svg1*sFL* zb1)Om@3jAMzWYT@Lt0a0s2e;2$o>YZa5xgv{2*k)O>7^UOaQ7;nF{QdJjHu`9 z*GE+{21-N0B4Q^Y7+D1H=zAuYaAGI?S$_tASB(=s$j)tscJZI1s>e+Mkx^cX<^d;B z)?@*&r3KVNn>ks5JB5_@qdNmpOyXoshXVza&%rS=5zQn%Dl24Sl=*SwIk7Jmos_qJ zEibt+UHteaM}7_)xFu%FR2sgi6r(^oi&q#3u2f?WJm4^`iZwODBR#Ul&Xl}MPb7lg zGI8ExxoEJiyntW0#>piLNrK)nS>s@+uX5n331RE*^wq@g#~!4_+$#-i>bdq!8)eE{zC;s zve=kEK30P*LJEWug%ovJqN4}QqYkVjg+k&I zh6BRV=oY5Lu`QrLGxbZV#t2bu2tcV0uX239NNz6b=0||Hrz}H!mkcB~c#~xEed_t^%O>lufVt%0j z2(IffdqI;9yY7DE0{Er+9MVi1Pd|K2Q{FCIN0wl04HSyoH4*|ph+d$&t`JvTA6CU> z;)9xAg+j21ygWXmq9w( z&dGmZ)ZXxFu!3}0I&_@hbx*dsx~d;ml>sW$9GH0^ZebtD1Zy?{HsGFV$mFFz^xq@W zdju^4O3k~ROHL^mp%OJJ8j3P$o_E3dJA!}(ksl9Re}ZzchD_g;Hej#5GXH1N!{yRI z1@@gF8tfj@eelc^fu3fLs~s)SFk(H+a!FJ^QAqq$aq)ia0C7VZhzznBRU}NvzqPf# z6ITs_a&NDUGGJ~vHUm(?-2$k60_WNV=sqGJnGYc!IVD|)H{}OY? z6*iD^Ks6YEgW$Xovq$~fT8b}UhfCU5P9rizCOk5_bnS;=&Lb$8(;pP4hGs!0qy-Z> z&E}x4FGmU1$qU57P=r?Sm)aDSf}R#t66ygf2T=eUw*-vWP$eLc*oRAPUkfEBV>llM zJjS@HoD+7d>k=%ymH-L~0y#}BoC@Tt(q*U0fpmw1*|H;-FF|0b5n&+8KnfF%f#RL5 zz2lu3po>_4lM~qSAMi(nPm!oYk47rUwV~XZT6UpIbIcW?41)Jz!shSSl>mpbUmp@R z1H(s;d9q*RpVpdo)PgXDOF7FHs=E`7Le95anpfgbKz`=BoI16y#A=R}^$$ulS>Wqt=%h zWYQuRX2JB^x(sQ+R1oaW=(F6P-qWt1k3 zkxkqwR6B{ltl=>5u;DF(xM5LJ?dmLcP%zYz&Nn1QD=gqs+V8bH>y4@hPaYqe^zJBN zuSXuyXY=6ua=zUkuHIi4L%jR;@e=Jm9yZZe8C}u+U{^ez9M3M_zpjrL$>au)O)~Ua zAEV-Dx^SY=cppK-L1c+xo%*dmK?|*rJ|uYM)a)kLzaA#I^Un3m((K|t=^$)&Pc{}g z?GPA>1QMPvZ)A+;j*Wd~+a&Ar`0~8_-0Lbv*|13&5}mPIsG#@+Bn=9v2-BVK5HOpC zN|Vxsqy^ixG z{-_;SYyUw4jIAf%@1`oZc@^y)sNCw<9VfW98ZWGqUIS{KTT~>(=Mx#|AtuhKnb`+c z$nV;+$m_G=%xbVqjH;CO+5ky@F9+|VN?qRr4X>@>Fs^6U_d-10{#{a+ImIdeHsp0= z&xbrEMLp{A3qJL6wr3cvAukmOL~xVk$D??&y0 z!pzT(Kkta~HV*gYWfDpAP`BvXWV1Z9G>KU(+0*Nc^WZ7NUILH*E)@)emM+af9&=nI zxzHf`CBn%|H;p*|X!j~IE8>Qzqt_casmr&bu*R5ZtyeycX<=8&wfC#c8Ct!a8kDYg z62H|I_214DWYgG>tY|9@b39E)~{ws0FM(3=s{BhB^1DUGR1okv|$}GWE+o~H=J=rxj&fuqo*# z{p}U*+A$extG|Y{gM7sa*LrGcj~YH~95gPyFsht6-!*^e3_dOc=e*iP(T!n(&gm`z z1gG){e!Jds-u>QoTO77~$&A?!!g`&{$nTjVy(kr{GYquVEm*FtEP7I+ga*aB5~6GZ zizNsNX-n=TF_qQO8L=G>_idksTTu^F)G1|TY@5haS_!tA8VE6F0FP9&LV*<#w=l_h zc6migpU`AGYj=3ID3{u2yhan}s^GGJ zt0P~oV%RWKwPBsahBK28vQwUK_}HQM-ip-=H?T{sEINq4g}pANv9)sCY*pHK6O$*b zjI?CLniudM*Vf9lim;n{bi0T0u&_VZ@xJHQ*pciUadUJcTA2$aISmPjT~=2~L9*TN zB@gqAPE8%7p=YP9Oc3BmSRTt!Y{<>`cyOqp1QvU66!wfLryg_U2Ui(A<~3crKV*MM zs*P6NJnKMsoqf!%#Qg3)X4rx495V=Uil~B^ni6dFPGer5;Q2&eGbfda)y78SKW|vJ zGd{Pvqu=}A5{!>nnAVkB+-0Jzy^|XyB6KAqxLMX~l#hb#j(DqEzV$oecK-M@3kUig zZIx-w79I2UsCnTrykd$)P9yt7a*&;)eO-IqTmZ9$LiA zn5Y9o7VrJ@}+Xy&&c8|x4?63#3 z7^n3krAiIC+~}Uk+JQMei4q-mgB1g`+x9JhVWzjWzOxHMdA-kTc?wpU4Gc+9TAtOd z5Wzj@i(a#%ZesYr*Xv!J5nP)UC25s7NOO6sGhZ;#`RdwqVpS!zu##Cz<`^wy!!8s7 z+pABRZIo4Dk)!q2McXUd9zyS_g2?+^`~z1^H@>=FPX?7H*j7$=FOxy3Q#)-viC1rV z5J()fP=seGTn)gd>^5IeB + + +SVG Image created as computer_sensor_board.svg date 2024/10/14 14:49:01 + Image generated by Eeschema-SVG + + + + + + + + + + + +1 +1 + + + + + +2 +2 + + + + + + + + + + +3 +3 + + + + + + + + + + + + + +4 +4 + + + +5 +5 + + + + + + + + + + + + + + + +6 +6 + + + + + + + + + + + + + + + + + + + + + + + + + + +1 +1 + + + + + +2 +2 + + + + + + + + + + +3 +3 + + + + + + + + + + + + + +4 +4 + + + +5 +5 + + + + + + + + + + + + + + + +6 +6 + + + + + + + + + + + + + + + + + + + + + + + + +A +A + + + +B +B + + + + + + + + + + + + + + + + + + +C +C + + + + + + + + + + + + + + + +D +D + + + + + + + + + + + + + + + +A +A + + + +B +B + + + + + + + + + + + + + + + + + + +C +C + + + + + + + + + + + + + + + +D +D + + + + + + + + + + + + +Date: +Date: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +KiCad E.D.A. 8.0.5 +KiCad E.D.A. 8.0.5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Rev: +Rev: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Size: A4 +Size: A4 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Id: 1/1 +Id: 1/1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Title: +Title: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +File: computer_sensor_board.kicad_sch +File: computer_sensor_board.kicad_sch + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Sheet: / +Sheet: / + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +GND +GND + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +PWR_FLAG +PWR_FLAG + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +1 +1 + + + + + + + + + + +2 +2 + + + + + + + + + + + + + + + +3 +3 + + + + + + + + + + + + + + + + + + +4 +4 + + + + + +J1 +J1 + + + + + + + + + + +Conn_Main_ADC +Conn_Main_ADC + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +(250mA max) +(250mA max) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +(3.6v to 5.5v) +(3.6v to 5.5v) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Device + +Device + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Ethernet + +Ethernet + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Host + +Host + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +USB + +USB + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +USB + +USB + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +8_TX2_IN1 +8_TX2_IN1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +10 +10 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +9_OUT1C +9_OUT1C + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +11 +11 + + + + + + + + + + + + + + + +10_CS_MQSR +10_CS_MQSR + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +12 +12 + + + + + + + + + + + + + + + + + + + + +11_MOSI_CTX1 +11_MOSI_CTX1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +13 +13 + + + + + + + + + + + + + + + + + + + + + + + +12_MISO_MQSL +12_MISO_MQSL + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +14 +14 + + + + + + + + + + + + + +3V3 +3V3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +15 +15 + + + + + + + + + + + + + + + + + + + + + + + + + +24_A10_TX6_SCL2 +24_A10_TX6_SCL2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +16 +16 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +25_A11_RX6_SDA2 +25_A11_RX6_SDA2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +17 +17 + + + + + + + + + + + + +26_A12_MOSI1 +26_A12_MOSI1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +18 +18 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +27_A13_SCK1 +27_A13_SCK1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +19 +19 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +28_RX7 +28_RX7 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +20 +20 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +29_TX7 +29_TX7 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +21 +21 + + + + + + + + + + + + + + + + + + + + +30_CRX3 +30_CRX3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +22 +22 + + + + + + + + + + + + + + + + + + + + + + + + + +31_CTX3 +31_CTX3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +23 +23 + + + + + + + + + + + + + + + + + + + + + + + + + + + + +32_OUT1B +32_OUT1B + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +24 +24 + + + + + + + + + + + + + + + + + + +33_MCLK2 +33_MCLK2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +25 +25 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +34_RX8 +34_RX8 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +26 +26 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +35_TX8 +35_TX8 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +27 +27 + + + + + + + + + + + + + + + + + +36_CS +36_CS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +28 +28 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +37_CS +37_CS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +29 +29 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +38_CS1_IN1 +38_CS1_IN1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +30 +30 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +39_MISO1_OUT1A +39_MISO1_OUT1A + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +31 +31 + + + + + + + + + + + + + + + + + + + + + + + +40_A16 +40_A16 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +32 +32 + + + + + + + + + + + + + + + + + + + + + + + + + + + + +41_A17 +41_A17 + + + + + + + + + + + + + + + + + + + + + +33 +33 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +13_SCK_LED +13_SCK_LED + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +35 +35 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +14_A0_TX3_SPDIF_OUT +14_A0_TX3_SPDIF_OUT + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +36 +36 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +15_A1_RX3_SPDIF_IN +15_A1_RX3_SPDIF_IN + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +37 +37 + + + + + + + + + + + + + + + + + + + + +16_A2_RX4_SCL1 +16_A2_RX4_SCL1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +38 +38 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +17_A3_TX4_SDA1 +17_A3_TX4_SDA1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +39 +39 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +18_A4_SDA +18_A4_SDA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +40 +40 + + + + + + + + + + + + + + + + + + + + + + + + + + + + +19_A5_SCL +19_A5_SCL + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +41 +41 + + + + + + + + + + + + + +20_A6_TX5_LRCLK1 +20_A6_TX5_LRCLK1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +42 +42 + + + + + + + + + + + + + + + + + + +21_A7_RX5_BCLK1 +21_A7_RX5_BCLK1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +43 +43 + + + + + + + + + + + + + + + + + + + + + +22_A8_CTX1 +22_A8_CTX1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +44 +44 + + + + + + + + + + + +23_A9_CRX1_MCLK1 +23_A9_CRX1_MCLK1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +45 +45 + + + + + + + + + + + + + + + + + + + + + + + +3V3 +3V3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +46 +46 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +GND +GND + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +47 +47 + + + + + + + + + + +VIN +VIN + + + + + + + + +48 +48 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +VUSB +VUSB + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +49 +49 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +3_LRCLK2 +3_LRCLK2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +5 +5 + + + + + + + + + + + + + + + + + + + + + +VBAT + +VBAT + + + + + + + + + + + + + + + + + + + + + + + + + + + + +50 + +50 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +3V3 + +3V3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +51 + +51 + + + + + + + + + + + + + + + + + + + + + + + + + + +GND + +GND + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +52 + +52 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +PROGRAM + +PROGRAM + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +53 + +53 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +ON_OFF + +ON_OFF + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +54 + +54 + + + + + + + + + + + + + + + + + + + + + + + +5V +5V + + + + + + + + + + + + + + + + + + + +55 +55 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +D- +D- + + + + + + + + + + + + + + + +56 +56 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +D+ +D+ + + + + + + + + + + + + + + + + +57 +57 + + + + + + + + + + + + + + + + + + + + + + +GND +GND + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +58 +58 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +GND +GND + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +59 +59 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +4_BCLK2 +4_BCLK2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +6 +6 + + + + + + + + + + + + + + + + + + + + + + + + + + +R+ +R+ + + + + + + + + + + + + + + + +60 +60 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +LED +LED + + + + + + + + + + + + + + + + + + + + +61 +61 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +T- +T- + + + + + +62 +62 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +T+ +T+ + + + + + + +63 +63 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +GND +GND + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +64 +64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +R- +R- + + + + + + + + + + + + + + +65 +65 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +D- +D- + + + + + + + + + + + + + + + +66 +66 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +D+ +D+ + + + + + + + + + + + + + + + + +67 +67 + + + + + + + + + + + + + + + + + + + + + + + + + + + + +5_IN2 +5_IN2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +7 +7 + + + + + + + +6_OUT1D +6_OUT1D + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +8 +8 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +7_RX2_OUT1A +7_RX2_OUT1A + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +9 +9 + + + + + + + + + + + + + + + + + + + + + + + + + + +GND +GND + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +1 +1 + + + + + + + + + + +0_RX1_CRX2_CS1 +0_RX1_CRX2_CS1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +2 +2 + + + + + + + + + + + + + + + +1_TX1_CTX2_MISO1 +1_TX1_CTX2_MISO1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +3 +3 + + + + + + + + + + + + + + + + + + +GND +GND + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +34 +34 + + + + + + + + + + + + + + + + + + + + + +2_OUT2 +2_OUT2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +4 +4 + + + + + +U2 +U2 + + + + + + + + + + + + + + + + + + + +Teensy4.1 +Teensy4.1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +PWR_FLAG +PWR_FLAG + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ++18V ++18V + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +R2 +R2 + + + + + + + + + + + + + + + + + + + + + +10K +10K + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +VBUS + +VBUS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +1 + +1 + + + + + + + + + + + +D- + +D- + + + + + + + + + + + + + + + + +2 + +2 + + + + + + + + + + + + + + + + +D+ + +D+ + + + + + + + + + + + + + + + + + +3 + +3 + + + + + + + + + + + + + + + + + + +GND +GND + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +4 +4 + + + + + + + + +Shield +Shield + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +5 +5 + + + + + + + + + + + + + + + + + +J3 +J3 + + + + + + + + + + + + + + + + + + +USB_M5Stack_0 +USB_M5Stack_0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +R1 +R1 + + + + + + + + + + + + + + + + +50K +50K + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +PWR_FLAG +PWR_FLAG + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ++VIN ++VIN + + + + + + + + + + +1 +1 + + + + + + + + + + +-VIN +-VIN + + + + + + + + + +2 +2 + + + + + + + + + + + + + + + +ON/OFF +ON/OFF + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +4 +4 + + + + + + + + +-VOUT +-VOUT + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +6 +6 + + + + + + + + + + + + + + + + + + + + + + + + + + ++VOUT ++VOUT + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +7 +7 + + + + +U1 +U1 + + + + + + + + + + + + + + +TDN_5-2411WISM +TDN_5-2411WISM + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +PWR_FLAG +PWR_FLAG + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +VBUS + +VBUS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +1 + +1 + + + + + + + + + + + +D- + +D- + + + + + + + + + + + + + + + + +2 + +2 + + + + + + + + + + + + + + + + +D+ + +D+ + + + + + + + + + + + + + + + + + +3 + +3 + + + + + + + + + + + + + + + + + + +GND +GND + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +4 +4 + + + + + + + + +Shield +Shield + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +5 +5 + + + + + + + + + + + + + + + + + +J4 +J4 + + + + + + + + +USB_M5Stack_1 +USB_M5Stack_1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +1 +1 + + + + + + + + + + +2 +2 + + + + + + + + + + + + +J2 +J2 + + + + + + + + + + + + + + + +Conn_Jetson +Conn_Jetson + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +PWR_FLAG +PWR_FLAG + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +R2 +R2 + + + + + + + + + + + + + + + + + + + + + +10K +10K + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +R1 +R1 + + + + + + + + + + + + + + + + +50K +50K + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +U1 +U1 + + + + + + + + + + + + + + +TDN_5-2411WISM +TDN_5-2411WISM + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ++VIN ++VIN + + + + + + + + + + +1 +1 + + + + + + + + + + +-VIN +-VIN + + + + + + + + + +2 +2 + + + + + + + + + + + + + + + +ON/OFF +ON/OFF + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +4 +4 + + + + + + + + +-VOUT +-VOUT + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +6 +6 + + + + + + + + + + + + + + + + + + + + + + + + + + ++VOUT ++VOUT + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +7 +7 + + + + +PWR_FLAG +PWR_FLAG + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 5efb122aa..685adad63 100755 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -34,6 +34,7 @@ theme: plugins: - github-dashboard - search + - inline-select-svg - mermaid2: arguments: theme: base @@ -101,5 +102,7 @@ nav: - tools/tools.md - tools/docker_images.md - Hardware Documentation: https://ouxt-polaris.github.io/robotx-hardware-documentation/ + - Circuit: + - Computer Sensor Board: circuit/computer_sensor_board/computer_sensor_board.md - Automation Pipeline: automation_pipeline.md - LICENSE: license.md diff --git a/hello.py b/hello.py new file mode 100644 index 000000000..b9afe0bc1 --- /dev/null +++ b/hello.py @@ -0,0 +1,6 @@ +def main(): + print("Hello from ouxt-automation!") + + +if __name__ == "__main__": + main() diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 000000000..a09286f3f --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,20 @@ +[project] +name = "ouxt-automation" +version = "0.1.0" +description = "Add your description here" +readme = "README.md" +requires-python = ">=3.10" +dependencies = [ + "fontawesome-markdown>=0.2.6", + "markdown==3.3.0", + "mkdocs>=1.5.3", + "mkdocs-github-dashboard>=0.2.3", + "mkdocs-material>=9.5.18", + "mkdocs-mermaid2-plugin>=1.1.1", + "pandas>=2.2.3", + "plantuml-markdown>=3.10.4", + "pymdown-extensions>=10.4", + "python-github-api>=0.1.1", + "python-markdown-math>=0.8", + "mkdocs-inline-select-svg-plugin>=0.1.0", +] diff --git a/uv.lock b/uv.lock new file mode 100644 index 000000000..971934c90 --- /dev/null +++ b/uv.lock @@ -0,0 +1,924 @@ +version = 1 +requires-python = ">=3.10" +resolution-markers = [ + "python_full_version < '3.11'", + "python_full_version == '3.11.*'", + "python_full_version >= '3.12'", +] + +[[package]] +name = "babel" +version = "2.16.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/2a/74/f1bc80f23eeba13393b7222b11d95ca3af2c1e28edca18af487137eefed9/babel-2.16.0.tar.gz", hash = "sha256:d1f3554ca26605fe173f3de0c65f750f5a42f924499bf134de6423582298e316", size = 9348104 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ed/20/bc79bc575ba2e2a7f70e8a1155618bb1301eaa5132a8271373a6903f73f8/babel-2.16.0-py3-none-any.whl", hash = "sha256:368b5b98b37c06b7daf6696391c3240c938b37767d4584413e8438c5c435fa8b", size = 9587599 }, +] + +[[package]] +name = "beautifulsoup4" +version = "4.12.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "soupsieve" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b3/ca/824b1195773ce6166d388573fc106ce56d4a805bd7427b624e063596ec58/beautifulsoup4-4.12.3.tar.gz", hash = "sha256:74e3d1928edc070d21748185c46e3fb33490f22f52a3addee9aee0f4f7781051", size = 581181 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b1/fe/e8c672695b37eecc5cbf43e1d0638d88d66ba3a44c4d321c796f4e59167f/beautifulsoup4-4.12.3-py3-none-any.whl", hash = "sha256:b80878c9f40111313e55da8ba20bdba06d8fa3969fc68304167741bbf9e082ed", size = 147925 }, +] + +[[package]] +name = "certifi" +version = "2024.8.30" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b0/ee/9b19140fe824b367c04c5e1b369942dd754c4c5462d5674002f75c4dedc1/certifi-2024.8.30.tar.gz", hash = "sha256:bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9", size = 168507 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/12/90/3c9ff0512038035f59d279fddeb79f5f1eccd8859f06d6163c58798b9487/certifi-2024.8.30-py3-none-any.whl", hash = "sha256:922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8", size = 167321 }, +] + +[[package]] +name = "charset-normalizer" +version = "3.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f2/4f/e1808dc01273379acc506d18f1504eb2d299bd4131743b9fc54d7be4df1e/charset_normalizer-3.4.0.tar.gz", hash = "sha256:223217c3d4f82c3ac5e29032b3f1c2eb0fb591b72161f86d93f5719079dae93e", size = 106620 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/69/8b/825cc84cf13a28bfbcba7c416ec22bf85a9584971be15b21dd8300c65b7f/charset_normalizer-3.4.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:4f9fc98dad6c2eaa32fc3af1417d95b5e3d08aff968df0cd320066def971f9a6", size = 196363 }, + { url = "https://files.pythonhosted.org/packages/23/81/d7eef6a99e42c77f444fdd7bc894b0ceca6c3a95c51239e74a722039521c/charset_normalizer-3.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0de7b687289d3c1b3e8660d0741874abe7888100efe14bd0f9fd7141bcbda92b", size = 125639 }, + { url = "https://files.pythonhosted.org/packages/21/67/b4564d81f48042f520c948abac7079356e94b30cb8ffb22e747532cf469d/charset_normalizer-3.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5ed2e36c3e9b4f21dd9422f6893dec0abf2cca553af509b10cd630f878d3eb99", size = 120451 }, + { url = "https://files.pythonhosted.org/packages/c2/72/12a7f0943dd71fb5b4e7b55c41327ac0a1663046a868ee4d0d8e9c369b85/charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40d3ff7fc90b98c637bda91c89d51264a3dcf210cade3a2c6f838c7268d7a4ca", size = 140041 }, + { url = "https://files.pythonhosted.org/packages/67/56/fa28c2c3e31217c4c52158537a2cf5d98a6c1e89d31faf476c89391cd16b/charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1110e22af8ca26b90bd6364fe4c763329b0ebf1ee213ba32b68c73de5752323d", size = 150333 }, + { url = "https://files.pythonhosted.org/packages/f9/d2/466a9be1f32d89eb1554cf84073a5ed9262047acee1ab39cbaefc19635d2/charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:86f4e8cca779080f66ff4f191a685ced73d2f72d50216f7112185dc02b90b9b7", size = 142921 }, + { url = "https://files.pythonhosted.org/packages/f8/01/344ec40cf5d85c1da3c1f57566c59e0c9b56bcc5566c08804a95a6cc8257/charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f683ddc7eedd742e2889d2bfb96d69573fde1d92fcb811979cdb7165bb9c7d3", size = 144785 }, + { url = "https://files.pythonhosted.org/packages/73/8b/2102692cb6d7e9f03b9a33a710e0164cadfce312872e3efc7cfe22ed26b4/charset_normalizer-3.4.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:27623ba66c183eca01bf9ff833875b459cad267aeeb044477fedac35e19ba907", size = 146631 }, + { url = "https://files.pythonhosted.org/packages/d8/96/cc2c1b5d994119ce9f088a9a0c3ebd489d360a2eb058e2c8049f27092847/charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f606a1881d2663630ea5b8ce2efe2111740df4b687bd78b34a8131baa007f79b", size = 140867 }, + { url = "https://files.pythonhosted.org/packages/c9/27/cde291783715b8ec30a61c810d0120411844bc4c23b50189b81188b273db/charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:0b309d1747110feb25d7ed6b01afdec269c647d382c857ef4663bbe6ad95a912", size = 149273 }, + { url = "https://files.pythonhosted.org/packages/3a/a4/8633b0fc1a2d1834d5393dafecce4a1cc56727bfd82b4dc18fc92f0d3cc3/charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:136815f06a3ae311fae551c3df1f998a1ebd01ddd424aa5603a4336997629e95", size = 152437 }, + { url = "https://files.pythonhosted.org/packages/64/ea/69af161062166b5975ccbb0961fd2384853190c70786f288684490913bf5/charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:14215b71a762336254351b00ec720a8e85cada43b987da5a042e4ce3e82bd68e", size = 150087 }, + { url = "https://files.pythonhosted.org/packages/3b/fd/e60a9d9fd967f4ad5a92810138192f825d77b4fa2a557990fd575a47695b/charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:79983512b108e4a164b9c8d34de3992f76d48cadc9554c9e60b43f308988aabe", size = 145142 }, + { url = "https://files.pythonhosted.org/packages/6d/02/8cb0988a1e49ac9ce2eed1e07b77ff118f2923e9ebd0ede41ba85f2dcb04/charset_normalizer-3.4.0-cp310-cp310-win32.whl", hash = "sha256:c94057af19bc953643a33581844649a7fdab902624d2eb739738a30e2b3e60fc", size = 94701 }, + { url = "https://files.pythonhosted.org/packages/d6/20/f1d4670a8a723c46be695dff449d86d6092916f9e99c53051954ee33a1bc/charset_normalizer-3.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:55f56e2ebd4e3bc50442fbc0888c9d8c94e4e06a933804e2af3e89e2f9c1c749", size = 102191 }, + { url = "https://files.pythonhosted.org/packages/9c/61/73589dcc7a719582bf56aae309b6103d2762b526bffe189d635a7fcfd998/charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0d99dd8ff461990f12d6e42c7347fd9ab2532fb70e9621ba520f9e8637161d7c", size = 193339 }, + { url = "https://files.pythonhosted.org/packages/77/d5/8c982d58144de49f59571f940e329ad6e8615e1e82ef84584c5eeb5e1d72/charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c57516e58fd17d03ebe67e181a4e4e2ccab1168f8c2976c6a334d4f819fe5944", size = 124366 }, + { url = "https://files.pythonhosted.org/packages/bf/19/411a64f01ee971bed3231111b69eb56f9331a769072de479eae7de52296d/charset_normalizer-3.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6dba5d19c4dfab08e58d5b36304b3f92f3bd5d42c1a3fa37b5ba5cdf6dfcbcee", size = 118874 }, + { url = "https://files.pythonhosted.org/packages/4c/92/97509850f0d00e9f14a46bc751daabd0ad7765cff29cdfb66c68b6dad57f/charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf4475b82be41b07cc5e5ff94810e6a01f276e37c2d55571e3fe175e467a1a1c", size = 138243 }, + { url = "https://files.pythonhosted.org/packages/e2/29/d227805bff72ed6d6cb1ce08eec707f7cfbd9868044893617eb331f16295/charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce031db0408e487fd2775d745ce30a7cd2923667cf3b69d48d219f1d8f5ddeb6", size = 148676 }, + { url = "https://files.pythonhosted.org/packages/13/bc/87c2c9f2c144bedfa62f894c3007cd4530ba4b5351acb10dc786428a50f0/charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ff4e7cdfdb1ab5698e675ca622e72d58a6fa2a8aa58195de0c0061288e6e3ea", size = 141289 }, + { url = "https://files.pythonhosted.org/packages/eb/5b/6f10bad0f6461fa272bfbbdf5d0023b5fb9bc6217c92bf068fa5a99820f5/charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3710a9751938947e6327ea9f3ea6332a09bf0ba0c09cae9cb1f250bd1f1549bc", size = 142585 }, + { url = "https://files.pythonhosted.org/packages/3b/a0/a68980ab8a1f45a36d9745d35049c1af57d27255eff8c907e3add84cf68f/charset_normalizer-3.4.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82357d85de703176b5587dbe6ade8ff67f9f69a41c0733cf2425378b49954de5", size = 144408 }, + { url = "https://files.pythonhosted.org/packages/d7/a1/493919799446464ed0299c8eef3c3fad0daf1c3cd48bff9263c731b0d9e2/charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:47334db71978b23ebcf3c0f9f5ee98b8d65992b65c9c4f2d34c2eaf5bcaf0594", size = 139076 }, + { url = "https://files.pythonhosted.org/packages/fb/9d/9c13753a5a6e0db4a0a6edb1cef7aee39859177b64e1a1e748a6e3ba62c2/charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8ce7fd6767a1cc5a92a639b391891bf1c268b03ec7e021c7d6d902285259685c", size = 146874 }, + { url = "https://files.pythonhosted.org/packages/75/d2/0ab54463d3410709c09266dfb416d032a08f97fd7d60e94b8c6ef54ae14b/charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f1a2f519ae173b5b6a2c9d5fa3116ce16e48b3462c8b96dfdded11055e3d6365", size = 150871 }, + { url = "https://files.pythonhosted.org/packages/8d/c9/27e41d481557be53d51e60750b85aa40eaf52b841946b3cdeff363105737/charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:63bc5c4ae26e4bc6be6469943b8253c0fd4e4186c43ad46e713ea61a0ba49129", size = 148546 }, + { url = "https://files.pythonhosted.org/packages/ee/44/4f62042ca8cdc0cabf87c0fc00ae27cd8b53ab68be3605ba6d071f742ad3/charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bcb4f8ea87d03bc51ad04add8ceaf9b0f085ac045ab4d74e73bbc2dc033f0236", size = 143048 }, + { url = "https://files.pythonhosted.org/packages/01/f8/38842422988b795220eb8038745d27a675ce066e2ada79516c118f291f07/charset_normalizer-3.4.0-cp311-cp311-win32.whl", hash = "sha256:9ae4ef0b3f6b41bad6366fb0ea4fc1d7ed051528e113a60fa2a65a9abb5b1d99", size = 94389 }, + { url = "https://files.pythonhosted.org/packages/0b/6e/b13bd47fa9023b3699e94abf565b5a2f0b0be6e9ddac9812182596ee62e4/charset_normalizer-3.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:cee4373f4d3ad28f1ab6290684d8e2ebdb9e7a1b74fdc39e4c211995f77bec27", size = 101752 }, + { url = "https://files.pythonhosted.org/packages/d3/0b/4b7a70987abf9b8196845806198975b6aab4ce016632f817ad758a5aa056/charset_normalizer-3.4.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0713f3adb9d03d49d365b70b84775d0a0d18e4ab08d12bc46baa6132ba78aaf6", size = 194445 }, + { url = "https://files.pythonhosted.org/packages/50/89/354cc56cf4dd2449715bc9a0f54f3aef3dc700d2d62d1fa5bbea53b13426/charset_normalizer-3.4.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:de7376c29d95d6719048c194a9cf1a1b0393fbe8488a22008610b0361d834ecf", size = 125275 }, + { url = "https://files.pythonhosted.org/packages/fa/44/b730e2a2580110ced837ac083d8ad222343c96bb6b66e9e4e706e4d0b6df/charset_normalizer-3.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4a51b48f42d9358460b78725283f04bddaf44a9358197b889657deba38f329db", size = 119020 }, + { url = "https://files.pythonhosted.org/packages/9d/e4/9263b8240ed9472a2ae7ddc3e516e71ef46617fe40eaa51221ccd4ad9a27/charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b295729485b06c1a0683af02a9e42d2caa9db04a373dc38a6a58cdd1e8abddf1", size = 139128 }, + { url = "https://files.pythonhosted.org/packages/6b/e3/9f73e779315a54334240353eaea75854a9a690f3f580e4bd85d977cb2204/charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ee803480535c44e7f5ad00788526da7d85525cfefaf8acf8ab9a310000be4b03", size = 149277 }, + { url = "https://files.pythonhosted.org/packages/1a/cf/f1f50c2f295312edb8a548d3fa56a5c923b146cd3f24114d5adb7e7be558/charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d59d125ffbd6d552765510e3f31ed75ebac2c7470c7274195b9161a32350284", size = 142174 }, + { url = "https://files.pythonhosted.org/packages/16/92/92a76dc2ff3a12e69ba94e7e05168d37d0345fa08c87e1fe24d0c2a42223/charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8cda06946eac330cbe6598f77bb54e690b4ca93f593dee1568ad22b04f347c15", size = 143838 }, + { url = "https://files.pythonhosted.org/packages/a4/01/2117ff2b1dfc61695daf2babe4a874bca328489afa85952440b59819e9d7/charset_normalizer-3.4.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07afec21bbbbf8a5cc3651aa96b980afe2526e7f048fdfb7f1014d84acc8b6d8", size = 146149 }, + { url = "https://files.pythonhosted.org/packages/f6/9b/93a332b8d25b347f6839ca0a61b7f0287b0930216994e8bf67a75d050255/charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6b40e8d38afe634559e398cc32b1472f376a4099c75fe6299ae607e404c033b2", size = 140043 }, + { url = "https://files.pythonhosted.org/packages/ab/f6/7ac4a01adcdecbc7a7587767c776d53d369b8b971382b91211489535acf0/charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b8dcd239c743aa2f9c22ce674a145e0a25cb1566c495928440a181ca1ccf6719", size = 148229 }, + { url = "https://files.pythonhosted.org/packages/9d/be/5708ad18161dee7dc6a0f7e6cf3a88ea6279c3e8484844c0590e50e803ef/charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:84450ba661fb96e9fd67629b93d2941c871ca86fc38d835d19d4225ff946a631", size = 151556 }, + { url = "https://files.pythonhosted.org/packages/5a/bb/3d8bc22bacb9eb89785e83e6723f9888265f3a0de3b9ce724d66bd49884e/charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:44aeb140295a2f0659e113b31cfe92c9061622cadbc9e2a2f7b8ef6b1e29ef4b", size = 149772 }, + { url = "https://files.pythonhosted.org/packages/f7/fa/d3fc622de05a86f30beea5fc4e9ac46aead4731e73fd9055496732bcc0a4/charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1db4e7fefefd0f548d73e2e2e041f9df5c59e178b4c72fbac4cc6f535cfb1565", size = 144800 }, + { url = "https://files.pythonhosted.org/packages/9a/65/bdb9bc496d7d190d725e96816e20e2ae3a6fa42a5cac99c3c3d6ff884118/charset_normalizer-3.4.0-cp312-cp312-win32.whl", hash = "sha256:5726cf76c982532c1863fb64d8c6dd0e4c90b6ece9feb06c9f202417a31f7dd7", size = 94836 }, + { url = "https://files.pythonhosted.org/packages/3e/67/7b72b69d25b89c0b3cea583ee372c43aa24df15f0e0f8d3982c57804984b/charset_normalizer-3.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:b197e7094f232959f8f20541ead1d9862ac5ebea1d58e9849c1bf979255dfac9", size = 102187 }, + { url = "https://files.pythonhosted.org/packages/f3/89/68a4c86f1a0002810a27f12e9a7b22feb198c59b2f05231349fbce5c06f4/charset_normalizer-3.4.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:dd4eda173a9fcccb5f2e2bd2a9f423d180194b1bf17cf59e3269899235b2a114", size = 194617 }, + { url = "https://files.pythonhosted.org/packages/4f/cd/8947fe425e2ab0aa57aceb7807af13a0e4162cd21eee42ef5b053447edf5/charset_normalizer-3.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e9e3c4c9e1ed40ea53acf11e2a386383c3304212c965773704e4603d589343ed", size = 125310 }, + { url = "https://files.pythonhosted.org/packages/5b/f0/b5263e8668a4ee9becc2b451ed909e9c27058337fda5b8c49588183c267a/charset_normalizer-3.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:92a7e36b000bf022ef3dbb9c46bfe2d52c047d5e3f3343f43204263c5addc250", size = 119126 }, + { url = "https://files.pythonhosted.org/packages/ff/6e/e445afe4f7fda27a533f3234b627b3e515a1b9429bc981c9a5e2aa5d97b6/charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:54b6a92d009cbe2fb11054ba694bc9e284dad30a26757b1e372a1fdddaf21920", size = 139342 }, + { url = "https://files.pythonhosted.org/packages/a1/b2/4af9993b532d93270538ad4926c8e37dc29f2111c36f9c629840c57cd9b3/charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ffd9493de4c922f2a38c2bf62b831dcec90ac673ed1ca182fe11b4d8e9f2a64", size = 149383 }, + { url = "https://files.pythonhosted.org/packages/fb/6f/4e78c3b97686b871db9be6f31d64e9264e889f8c9d7ab33c771f847f79b7/charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:35c404d74c2926d0287fbd63ed5d27eb911eb9e4a3bb2c6d294f3cfd4a9e0c23", size = 142214 }, + { url = "https://files.pythonhosted.org/packages/2b/c9/1c8fe3ce05d30c87eff498592c89015b19fade13df42850aafae09e94f35/charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4796efc4faf6b53a18e3d46343535caed491776a22af773f366534056c4e1fbc", size = 144104 }, + { url = "https://files.pythonhosted.org/packages/ee/68/efad5dcb306bf37db7db338338e7bb8ebd8cf38ee5bbd5ceaaaa46f257e6/charset_normalizer-3.4.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e7fdd52961feb4c96507aa649550ec2a0d527c086d284749b2f582f2d40a2e0d", size = 146255 }, + { url = "https://files.pythonhosted.org/packages/0c/75/1ed813c3ffd200b1f3e71121c95da3f79e6d2a96120163443b3ad1057505/charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:92db3c28b5b2a273346bebb24857fda45601aef6ae1c011c0a997106581e8a88", size = 140251 }, + { url = "https://files.pythonhosted.org/packages/7d/0d/6f32255c1979653b448d3c709583557a4d24ff97ac4f3a5be156b2e6a210/charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ab973df98fc99ab39080bfb0eb3a925181454d7c3ac8a1e695fddfae696d9e90", size = 148474 }, + { url = "https://files.pythonhosted.org/packages/ac/a0/c1b5298de4670d997101fef95b97ac440e8c8d8b4efa5a4d1ef44af82f0d/charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:4b67fdab07fdd3c10bb21edab3cbfe8cf5696f453afce75d815d9d7223fbe88b", size = 151849 }, + { url = "https://files.pythonhosted.org/packages/04/4f/b3961ba0c664989ba63e30595a3ed0875d6790ff26671e2aae2fdc28a399/charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:aa41e526a5d4a9dfcfbab0716c7e8a1b215abd3f3df5a45cf18a12721d31cb5d", size = 149781 }, + { url = "https://files.pythonhosted.org/packages/d8/90/6af4cd042066a4adad58ae25648a12c09c879efa4849c705719ba1b23d8c/charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ffc519621dce0c767e96b9c53f09c5d215578e10b02c285809f76509a3931482", size = 144970 }, + { url = "https://files.pythonhosted.org/packages/cc/67/e5e7e0cbfefc4ca79025238b43cdf8a2037854195b37d6417f3d0895c4c2/charset_normalizer-3.4.0-cp313-cp313-win32.whl", hash = "sha256:f19c1585933c82098c2a520f8ec1227f20e339e33aca8fa6f956f6691b784e67", size = 94973 }, + { url = "https://files.pythonhosted.org/packages/65/97/fc9bbc54ee13d33dc54a7fcf17b26368b18505500fc01e228c27b5222d80/charset_normalizer-3.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:707b82d19e65c9bd28b81dde95249b07bf9f5b90ebe1ef17d9b57473f8a64b7b", size = 102308 }, + { url = "https://files.pythonhosted.org/packages/bf/9b/08c0432272d77b04803958a4598a51e2a4b51c06640af8b8f0f908c18bf2/charset_normalizer-3.4.0-py3-none-any.whl", hash = "sha256:fe9f97feb71aa9896b81973a7bbada8c49501dc73e58a10fcef6663af95e5079", size = 49446 }, +] + +[[package]] +name = "click" +version = "8.1.7" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "platform_system == 'Windows'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/96/d3/f04c7bfcf5c1862a2a5b845c6b2b360488cf47af55dfa79c98f6a6bf98b5/click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de", size = 336121 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/00/2e/d53fa4befbf2cfa713304affc7ca780ce4fc1fd8710527771b58311a3229/click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28", size = 97941 }, +] + +[[package]] +name = "colorama" +version = "0.4.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335 }, +] + +[[package]] +name = "editorconfig" +version = "0.12.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/3d/85/7b5c2fac7fdc37d959fab714b13b9acb75884490dcc0e8b1dc5e64105084/EditorConfig-0.12.4.tar.gz", hash = "sha256:24857fa1793917dd9ccf0c7810a07e05404ce9b823521c7dce22a4fb5d125f80", size = 13278 } + +[[package]] +name = "fontawesome-markdown" +version = "0.2.6" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markdown" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c7/29/cbd664c42a119ee14d73a6991e4689beec529313ada5c4586c9c33f72e2b/fontawesome-markdown-0.2.6.tar.gz", hash = "sha256:95a12f1629a595afc4aabc886ffdb8b5fa0ae8f77e8f3437b7b1942d91f91f4b", size = 5762 } + +[[package]] +name = "ghp-import" +version = "2.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "python-dateutil" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d9/29/d40217cbe2f6b1359e00c6c307bb3fc876ba74068cbab3dde77f03ca0dc4/ghp-import-2.1.0.tar.gz", hash = "sha256:9c535c4c61193c2df8871222567d7fd7e5014d835f97dc7b7439069e2413d343", size = 10943 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f7/ec/67fbef5d497f86283db54c22eec6f6140243aae73265799baaaa19cd17fb/ghp_import-2.1.0-py3-none-any.whl", hash = "sha256:8337dd7b50877f163d4c0289bc1f1c7f127550241988d568c1db512c4324a619", size = 11034 }, +] + +[[package]] +name = "idna" +version = "3.10" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f1/70/7703c29685631f5a7590aa73f1f1d3fa9a380e654b86af429e0934a32f7d/idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", size = 190490 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442 }, +] + +[[package]] +name = "jinja2" +version = "3.1.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markupsafe" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ed/55/39036716d19cab0747a5020fc7e907f362fbf48c984b14e62127f7e68e5d/jinja2-3.1.4.tar.gz", hash = "sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369", size = 240245 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/31/80/3a54838c3fb461f6fec263ebf3a3a41771bd05190238de3486aae8540c36/jinja2-3.1.4-py3-none-any.whl", hash = "sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d", size = 133271 }, +] + +[[package]] +name = "jsbeautifier" +version = "1.15.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "editorconfig" }, + { name = "six" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/69/3e/dd37e1a7223247e3ef94714abf572415b89c4e121c4af48e9e4c392e2ca0/jsbeautifier-1.15.1.tar.gz", hash = "sha256:ebd733b560704c602d744eafc839db60a1ee9326e30a2a80c4adb8718adc1b24", size = 75606 } + +[[package]] +name = "lxml" +version = "5.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e7/6b/20c3a4b24751377aaa6307eb230b66701024012c29dd374999cc92983269/lxml-5.3.0.tar.gz", hash = "sha256:4e109ca30d1edec1ac60cdbe341905dc3b8f55b16855e03a54aaf59e51ec8c6f", size = 3679318 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a1/ce/2789e39eddf2b13fac29878bfa465f0910eb6b0096e29090e5176bc8cf43/lxml-5.3.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:dd36439be765e2dde7660212b5275641edbc813e7b24668831a5c8ac91180656", size = 8124570 }, + { url = "https://files.pythonhosted.org/packages/24/a8/f4010166a25d41715527129af2675981a50d3bbf7df09c5d9ab8ca24fbf9/lxml-5.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ae5fe5c4b525aa82b8076c1a59d642c17b6e8739ecf852522c6321852178119d", size = 4413042 }, + { url = "https://files.pythonhosted.org/packages/41/a4/7e45756cecdd7577ddf67a68b69c1db0f5ddbf0c9f65021ee769165ffc5a/lxml-5.3.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:501d0d7e26b4d261fca8132854d845e4988097611ba2531408ec91cf3fd9d20a", size = 5139213 }, + { url = "https://files.pythonhosted.org/packages/02/e2/ecf845b12323c92748077e1818b64e8b4dba509a4cb12920b3762ebe7552/lxml-5.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb66442c2546446944437df74379e9cf9e9db353e61301d1a0e26482f43f0dd8", size = 4838814 }, + { url = "https://files.pythonhosted.org/packages/12/91/619f9fb72cf75e9ceb8700706f7276f23995f6ad757e6d400fbe35ca4990/lxml-5.3.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9e41506fec7a7f9405b14aa2d5c8abbb4dbbd09d88f9496958b6d00cb4d45330", size = 5425084 }, + { url = "https://files.pythonhosted.org/packages/25/3b/162a85a8f0fd2a3032ec3f936636911c6e9523a8e263fffcfd581ce98b54/lxml-5.3.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f7d4a670107d75dfe5ad080bed6c341d18c4442f9378c9f58e5851e86eb79965", size = 4875993 }, + { url = "https://files.pythonhosted.org/packages/43/af/dd3f58cc7d946da6ae42909629a2b1d5dd2d1b583334d4af9396697d6863/lxml-5.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:41ce1f1e2c7755abfc7e759dc34d7d05fd221723ff822947132dc934d122fe22", size = 5012462 }, + { url = "https://files.pythonhosted.org/packages/69/c1/5ea46b2d4c98f5bf5c83fffab8a0ad293c9bc74df9ecfbafef10f77f7201/lxml-5.3.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:44264ecae91b30e5633013fb66f6ddd05c006d3e0e884f75ce0b4755b3e3847b", size = 4815288 }, + { url = "https://files.pythonhosted.org/packages/1d/51/a0acca077ad35da458f4d3f729ef98effd2b90f003440d35fc36323f8ae6/lxml-5.3.0-cp310-cp310-manylinux_2_28_ppc64le.whl", hash = "sha256:3c174dc350d3ec52deb77f2faf05c439331d6ed5e702fc247ccb4e6b62d884b7", size = 5472435 }, + { url = "https://files.pythonhosted.org/packages/4d/6b/0989c9368986961a6b0f55b46c80404c4b758417acdb6d87bfc3bd5f4967/lxml-5.3.0-cp310-cp310-manylinux_2_28_s390x.whl", hash = "sha256:2dfab5fa6a28a0b60a20638dc48e6343c02ea9933e3279ccb132f555a62323d8", size = 4976354 }, + { url = "https://files.pythonhosted.org/packages/05/9e/87492d03ff604fbf656ed2bf3e2e8d28f5d58ea1f00ff27ac27b06509079/lxml-5.3.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:b1c8c20847b9f34e98080da785bb2336ea982e7f913eed5809e5a3c872900f32", size = 5029973 }, + { url = "https://files.pythonhosted.org/packages/f9/cc/9ae1baf5472af88e19e2c454b3710c1be9ecafb20eb474eeabcd88a055d2/lxml-5.3.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:2c86bf781b12ba417f64f3422cfc302523ac9cd1d8ae8c0f92a1c66e56ef2e86", size = 4888837 }, + { url = "https://files.pythonhosted.org/packages/d2/10/5594ffaec8c120d75b17e3ad23439b740a51549a9b5fd7484b2179adfe8f/lxml-5.3.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:c162b216070f280fa7da844531169be0baf9ccb17263cf5a8bf876fcd3117fa5", size = 5530555 }, + { url = "https://files.pythonhosted.org/packages/ea/9b/de17f05377c8833343b629905571fb06cff2028f15a6f58ae2267662e341/lxml-5.3.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:36aef61a1678cb778097b4a6eeae96a69875d51d1e8f4d4b491ab3cfb54b5a03", size = 5405314 }, + { url = "https://files.pythonhosted.org/packages/8a/b4/227be0f1f3cca8255925985164c3838b8b36e441ff0cc10c1d3c6bdba031/lxml-5.3.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f65e5120863c2b266dbcc927b306c5b78e502c71edf3295dfcb9501ec96e5fc7", size = 5079303 }, + { url = "https://files.pythonhosted.org/packages/5c/ee/19abcebb7fc40319bb71cd6adefa1ad94d09b5660228715854d6cc420713/lxml-5.3.0-cp310-cp310-win32.whl", hash = "sha256:ef0c1fe22171dd7c7c27147f2e9c3e86f8bdf473fed75f16b0c2e84a5030ce80", size = 3475126 }, + { url = "https://files.pythonhosted.org/packages/a1/35/183d32551447e280032b2331738cd850da435a42f850b71ebeaab42c1313/lxml-5.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:052d99051e77a4f3e8482c65014cf6372e61b0a6f4fe9edb98503bb5364cfee3", size = 3805065 }, + { url = "https://files.pythonhosted.org/packages/5c/a8/449faa2a3cbe6a99f8d38dcd51a3ee8844c17862841a6f769ea7c2a9cd0f/lxml-5.3.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:74bcb423462233bc5d6066e4e98b0264e7c1bed7541fff2f4e34fe6b21563c8b", size = 8141056 }, + { url = "https://files.pythonhosted.org/packages/ac/8a/ae6325e994e2052de92f894363b038351c50ee38749d30cc6b6d96aaf90f/lxml-5.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a3d819eb6f9b8677f57f9664265d0a10dd6551d227afb4af2b9cd7bdc2ccbf18", size = 4425238 }, + { url = "https://files.pythonhosted.org/packages/f8/fb/128dddb7f9086236bce0eeae2bfb316d138b49b159f50bc681d56c1bdd19/lxml-5.3.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5b8f5db71b28b8c404956ddf79575ea77aa8b1538e8b2ef9ec877945b3f46442", size = 5095197 }, + { url = "https://files.pythonhosted.org/packages/b4/f9/a181a8ef106e41e3086629c8bdb2d21a942f14c84a0e77452c22d6b22091/lxml-5.3.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2c3406b63232fc7e9b8783ab0b765d7c59e7c59ff96759d8ef9632fca27c7ee4", size = 4809809 }, + { url = "https://files.pythonhosted.org/packages/25/2f/b20565e808f7f6868aacea48ddcdd7e9e9fb4c799287f21f1a6c7c2e8b71/lxml-5.3.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2ecdd78ab768f844c7a1d4a03595038c166b609f6395e25af9b0f3f26ae1230f", size = 5407593 }, + { url = "https://files.pythonhosted.org/packages/23/0e/caac672ec246d3189a16c4d364ed4f7d6bf856c080215382c06764058c08/lxml-5.3.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:168f2dfcfdedf611eb285efac1516c8454c8c99caf271dccda8943576b67552e", size = 4866657 }, + { url = "https://files.pythonhosted.org/packages/67/a4/1f5fbd3f58d4069000522196b0b776a014f3feec1796da03e495cf23532d/lxml-5.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa617107a410245b8660028a7483b68e7914304a6d4882b5ff3d2d3eb5948d8c", size = 4967017 }, + { url = "https://files.pythonhosted.org/packages/ee/73/623ecea6ca3c530dd0a4ed0d00d9702e0e85cd5624e2d5b93b005fe00abd/lxml-5.3.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:69959bd3167b993e6e710b99051265654133a98f20cec1d9b493b931942e9c16", size = 4810730 }, + { url = "https://files.pythonhosted.org/packages/1d/ce/fb84fb8e3c298f3a245ae3ea6221c2426f1bbaa82d10a88787412a498145/lxml-5.3.0-cp311-cp311-manylinux_2_28_ppc64le.whl", hash = "sha256:bd96517ef76c8654446fc3db9242d019a1bb5fe8b751ba414765d59f99210b79", size = 5455154 }, + { url = "https://files.pythonhosted.org/packages/b1/72/4d1ad363748a72c7c0411c28be2b0dc7150d91e823eadad3b91a4514cbea/lxml-5.3.0-cp311-cp311-manylinux_2_28_s390x.whl", hash = "sha256:ab6dd83b970dc97c2d10bc71aa925b84788c7c05de30241b9e96f9b6d9ea3080", size = 4969416 }, + { url = "https://files.pythonhosted.org/packages/42/07/b29571a58a3a80681722ea8ed0ba569211d9bb8531ad49b5cacf6d409185/lxml-5.3.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:eec1bb8cdbba2925bedc887bc0609a80e599c75b12d87ae42ac23fd199445654", size = 5013672 }, + { url = "https://files.pythonhosted.org/packages/b9/93/bde740d5a58cf04cbd38e3dd93ad1e36c2f95553bbf7d57807bc6815d926/lxml-5.3.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6a7095eeec6f89111d03dabfe5883a1fd54da319c94e0fb104ee8f23616b572d", size = 4878644 }, + { url = "https://files.pythonhosted.org/packages/56/b5/645c8c02721d49927c93181de4017164ec0e141413577687c3df8ff0800f/lxml-5.3.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:6f651ebd0b21ec65dfca93aa629610a0dbc13dbc13554f19b0113da2e61a4763", size = 5511531 }, + { url = "https://files.pythonhosted.org/packages/85/3f/6a99a12d9438316f4fc86ef88c5d4c8fb674247b17f3173ecadd8346b671/lxml-5.3.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:f422a209d2455c56849442ae42f25dbaaba1c6c3f501d58761c619c7836642ec", size = 5402065 }, + { url = "https://files.pythonhosted.org/packages/80/8a/df47bff6ad5ac57335bf552babfb2408f9eb680c074ec1ba412a1a6af2c5/lxml-5.3.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:62f7fdb0d1ed2065451f086519865b4c90aa19aed51081979ecd05a21eb4d1be", size = 5069775 }, + { url = "https://files.pythonhosted.org/packages/08/ae/e7ad0f0fbe4b6368c5ee1e3ef0c3365098d806d42379c46c1ba2802a52f7/lxml-5.3.0-cp311-cp311-win32.whl", hash = "sha256:c6379f35350b655fd817cd0d6cbeef7f265f3ae5fedb1caae2eb442bbeae9ab9", size = 3474226 }, + { url = "https://files.pythonhosted.org/packages/c3/b5/91c2249bfac02ee514ab135e9304b89d55967be7e53e94a879b74eec7a5c/lxml-5.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:9c52100e2c2dbb0649b90467935c4b0de5528833c76a35ea1a2691ec9f1ee7a1", size = 3814971 }, + { url = "https://files.pythonhosted.org/packages/eb/6d/d1f1c5e40c64bf62afd7a3f9b34ce18a586a1cccbf71e783cd0a6d8e8971/lxml-5.3.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:e99f5507401436fdcc85036a2e7dc2e28d962550afe1cbfc07c40e454256a859", size = 8171753 }, + { url = "https://files.pythonhosted.org/packages/bd/83/26b1864921869784355459f374896dcf8b44d4af3b15d7697e9156cb2de9/lxml-5.3.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:384aacddf2e5813a36495233b64cb96b1949da72bef933918ba5c84e06af8f0e", size = 4441955 }, + { url = "https://files.pythonhosted.org/packages/e0/d2/e9bff9fb359226c25cda3538f664f54f2804f4b37b0d7c944639e1a51f69/lxml-5.3.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:874a216bf6afaf97c263b56371434e47e2c652d215788396f60477540298218f", size = 5050778 }, + { url = "https://files.pythonhosted.org/packages/88/69/6972bfafa8cd3ddc8562b126dd607011e218e17be313a8b1b9cc5a0ee876/lxml-5.3.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:65ab5685d56914b9a2a34d67dd5488b83213d680b0c5d10b47f81da5a16b0b0e", size = 4748628 }, + { url = "https://files.pythonhosted.org/packages/5d/ea/a6523c7c7f6dc755a6eed3d2f6d6646617cad4d3d6d8ce4ed71bfd2362c8/lxml-5.3.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aac0bbd3e8dd2d9c45ceb82249e8bdd3ac99131a32b4d35c8af3cc9db1657179", size = 5322215 }, + { url = "https://files.pythonhosted.org/packages/99/37/396fbd24a70f62b31d988e4500f2068c7f3fd399d2fd45257d13eab51a6f/lxml-5.3.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b369d3db3c22ed14c75ccd5af429086f166a19627e84a8fdade3f8f31426e52a", size = 4813963 }, + { url = "https://files.pythonhosted.org/packages/09/91/e6136f17459a11ce1757df864b213efbeab7adcb2efa63efb1b846ab6723/lxml-5.3.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c24037349665434f375645fa9d1f5304800cec574d0310f618490c871fd902b3", size = 4923353 }, + { url = "https://files.pythonhosted.org/packages/1d/7c/2eeecf87c9a1fca4f84f991067c693e67340f2b7127fc3eca8fa29d75ee3/lxml-5.3.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:62d172f358f33a26d6b41b28c170c63886742f5b6772a42b59b4f0fa10526cb1", size = 4740541 }, + { url = "https://files.pythonhosted.org/packages/3b/ed/4c38ba58defca84f5f0d0ac2480fdcd99fc7ae4b28fc417c93640a6949ae/lxml-5.3.0-cp312-cp312-manylinux_2_28_ppc64le.whl", hash = "sha256:c1f794c02903c2824fccce5b20c339a1a14b114e83b306ff11b597c5f71a1c8d", size = 5346504 }, + { url = "https://files.pythonhosted.org/packages/a5/22/bbd3995437e5745cb4c2b5d89088d70ab19d4feabf8a27a24cecb9745464/lxml-5.3.0-cp312-cp312-manylinux_2_28_s390x.whl", hash = "sha256:5d6a6972b93c426ace71e0be9a6f4b2cfae9b1baed2eed2006076a746692288c", size = 4898077 }, + { url = "https://files.pythonhosted.org/packages/0a/6e/94537acfb5b8f18235d13186d247bca478fea5e87d224644e0fe907df976/lxml-5.3.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:3879cc6ce938ff4eb4900d901ed63555c778731a96365e53fadb36437a131a99", size = 4946543 }, + { url = "https://files.pythonhosted.org/packages/8d/e8/4b15df533fe8e8d53363b23a41df9be907330e1fa28c7ca36893fad338ee/lxml-5.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:74068c601baff6ff021c70f0935b0c7bc528baa8ea210c202e03757c68c5a4ff", size = 4816841 }, + { url = "https://files.pythonhosted.org/packages/1a/e7/03f390ea37d1acda50bc538feb5b2bda6745b25731e4e76ab48fae7106bf/lxml-5.3.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:ecd4ad8453ac17bc7ba3868371bffb46f628161ad0eefbd0a855d2c8c32dd81a", size = 5417341 }, + { url = "https://files.pythonhosted.org/packages/ea/99/d1133ab4c250da85a883c3b60249d3d3e7c64f24faff494cf0fd23f91e80/lxml-5.3.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:7e2f58095acc211eb9d8b5771bf04df9ff37d6b87618d1cbf85f92399c98dae8", size = 5327539 }, + { url = "https://files.pythonhosted.org/packages/7d/ed/e6276c8d9668028213df01f598f385b05b55a4e1b4662ee12ef05dab35aa/lxml-5.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e63601ad5cd8f860aa99d109889b5ac34de571c7ee902d6812d5d9ddcc77fa7d", size = 5012542 }, + { url = "https://files.pythonhosted.org/packages/36/88/684d4e800f5aa28df2a991a6a622783fb73cf0e46235cfa690f9776f032e/lxml-5.3.0-cp312-cp312-win32.whl", hash = "sha256:17e8d968d04a37c50ad9c456a286b525d78c4a1c15dd53aa46c1d8e06bf6fa30", size = 3486454 }, + { url = "https://files.pythonhosted.org/packages/fc/82/ace5a5676051e60355bd8fb945df7b1ba4f4fb8447f2010fb816bfd57724/lxml-5.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:c1a69e58a6bb2de65902051d57fde951febad631a20a64572677a1052690482f", size = 3816857 }, + { url = "https://files.pythonhosted.org/packages/94/6a/42141e4d373903bfea6f8e94b2f554d05506dfda522ada5343c651410dc8/lxml-5.3.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8c72e9563347c7395910de6a3100a4840a75a6f60e05af5e58566868d5eb2d6a", size = 8156284 }, + { url = "https://files.pythonhosted.org/packages/91/5e/fa097f0f7d8b3d113fb7312c6308af702f2667f22644441715be961f2c7e/lxml-5.3.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e92ce66cd919d18d14b3856906a61d3f6b6a8500e0794142338da644260595cd", size = 4432407 }, + { url = "https://files.pythonhosted.org/packages/2d/a1/b901988aa6d4ff937f2e5cfc114e4ec561901ff00660c3e56713642728da/lxml-5.3.0-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1d04f064bebdfef9240478f7a779e8c5dc32b8b7b0b2fc6a62e39b928d428e51", size = 5048331 }, + { url = "https://files.pythonhosted.org/packages/30/0f/b2a54f48e52de578b71bbe2a2f8160672a8a5e103df3a78da53907e8c7ed/lxml-5.3.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c2fb570d7823c2bbaf8b419ba6e5662137f8166e364a8b2b91051a1fb40ab8b", size = 4744835 }, + { url = "https://files.pythonhosted.org/packages/82/9d/b000c15538b60934589e83826ecbc437a1586488d7c13f8ee5ff1f79a9b8/lxml-5.3.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0c120f43553ec759f8de1fee2f4794452b0946773299d44c36bfe18e83caf002", size = 5316649 }, + { url = "https://files.pythonhosted.org/packages/e3/ee/ffbb9eaff5e541922611d2c56b175c45893d1c0b8b11e5a497708a6a3b3b/lxml-5.3.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:562e7494778a69086f0312ec9689f6b6ac1c6b65670ed7d0267e49f57ffa08c4", size = 4812046 }, + { url = "https://files.pythonhosted.org/packages/15/ff/7ff89d567485c7b943cdac316087f16b2399a8b997007ed352a1248397e5/lxml-5.3.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:423b121f7e6fa514ba0c7918e56955a1d4470ed35faa03e3d9f0e3baa4c7e492", size = 4918597 }, + { url = "https://files.pythonhosted.org/packages/c6/a3/535b6ed8c048412ff51268bdf4bf1cf052a37aa7e31d2e6518038a883b29/lxml-5.3.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:c00f323cc00576df6165cc9d21a4c21285fa6b9989c5c39830c3903dc4303ef3", size = 4738071 }, + { url = "https://files.pythonhosted.org/packages/7a/8f/cbbfa59cb4d4fd677fe183725a76d8c956495d7a3c7f111ab8f5e13d2e83/lxml-5.3.0-cp313-cp313-manylinux_2_28_ppc64le.whl", hash = "sha256:1fdc9fae8dd4c763e8a31e7630afef517eab9f5d5d31a278df087f307bf601f4", size = 5342213 }, + { url = "https://files.pythonhosted.org/packages/5c/fb/db4c10dd9958d4b52e34d1d1f7c1f434422aeaf6ae2bbaaff2264351d944/lxml-5.3.0-cp313-cp313-manylinux_2_28_s390x.whl", hash = "sha256:658f2aa69d31e09699705949b5fc4719cbecbd4a97f9656a232e7d6c7be1a367", size = 4893749 }, + { url = "https://files.pythonhosted.org/packages/f2/38/bb4581c143957c47740de18a3281a0cab7722390a77cc6e610e8ebf2d736/lxml-5.3.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:1473427aff3d66a3fa2199004c3e601e6c4500ab86696edffdbc84954c72d832", size = 4945901 }, + { url = "https://files.pythonhosted.org/packages/fc/d5/18b7de4960c731e98037bd48fa9f8e6e8f2558e6fbca4303d9b14d21ef3b/lxml-5.3.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a87de7dd873bf9a792bf1e58b1c3887b9264036629a5bf2d2e6579fe8e73edff", size = 4815447 }, + { url = "https://files.pythonhosted.org/packages/97/a8/cd51ceaad6eb849246559a8ef60ae55065a3df550fc5fcd27014361c1bab/lxml-5.3.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:0d7b36afa46c97875303a94e8f3ad932bf78bace9e18e603f2085b652422edcd", size = 5411186 }, + { url = "https://files.pythonhosted.org/packages/89/c3/1e3dabab519481ed7b1fdcba21dcfb8832f57000733ef0e71cf6d09a5e03/lxml-5.3.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:cf120cce539453ae086eacc0130a324e7026113510efa83ab42ef3fcfccac7fb", size = 5324481 }, + { url = "https://files.pythonhosted.org/packages/b6/17/71e9984cf0570cd202ac0a1c9ed5c1b8889b0fc8dc736f5ef0ffb181c284/lxml-5.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:df5c7333167b9674aa8ae1d4008fa4bc17a313cc490b2cca27838bbdcc6bb15b", size = 5011053 }, + { url = "https://files.pythonhosted.org/packages/69/68/9f7e6d3312a91e30829368c2b3217e750adef12a6f8eb10498249f4e8d72/lxml-5.3.0-cp313-cp313-win32.whl", hash = "sha256:c802e1c2ed9f0c06a65bc4ed0189d000ada8049312cfeab6ca635e39c9608957", size = 3485634 }, + { url = "https://files.pythonhosted.org/packages/7d/db/214290d58ad68c587bd5d6af3d34e56830438733d0d0856c0275fde43652/lxml-5.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:406246b96d552e0503e17a1006fd27edac678b3fcc9f1be71a2f94b4ff61528d", size = 3814417 }, + { url = "https://files.pythonhosted.org/packages/99/f7/b73a431c8500565aa500e99e60b448d305eaf7c0b4c893c7c5a8a69cc595/lxml-5.3.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:7b1cd427cb0d5f7393c31b7496419da594fe600e6fdc4b105a54f82405e6626c", size = 3925431 }, + { url = "https://files.pythonhosted.org/packages/db/48/4a206623c0d093d0e3b15f415ffb4345b0bdf661a3d0b15a112948c033c7/lxml-5.3.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:51806cfe0279e06ed8500ce19479d757db42a30fd509940b1701be9c86a5ff9a", size = 4216683 }, + { url = "https://files.pythonhosted.org/packages/54/47/577820c45dd954523ae8453b632d91e76da94ca6d9ee40d8c98dd86f916b/lxml-5.3.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ee70d08fd60c9565ba8190f41a46a54096afa0eeb8f76bd66f2c25d3b1b83005", size = 4326732 }, + { url = "https://files.pythonhosted.org/packages/68/de/96cb6d3269bc994b4f5ede8ca7bf0840f5de0a278bc6e50cb317ff71cafa/lxml-5.3.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:8dc2c0395bea8254d8daebc76dcf8eb3a95ec2a46fa6fae5eaccee366bfe02ce", size = 4218377 }, + { url = "https://files.pythonhosted.org/packages/a5/43/19b1ef6cbffa4244a217f95cc5f41a6cb4720fed33510a49670b03c5f1a0/lxml-5.3.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:6ba0d3dcac281aad8a0e5b14c7ed6f9fa89c8612b47939fc94f80b16e2e9bc83", size = 4351237 }, + { url = "https://files.pythonhosted.org/packages/ba/b2/6a22fb5c0885da3b00e116aee81f0b829ec9ac8f736cd414b4a09413fc7d/lxml-5.3.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:6e91cf736959057f7aac7adfc83481e03615a8e8dd5758aa1d95ea69e8931dba", size = 3487557 }, +] + +[[package]] +name = "markdown" +version = "3.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/92/57/9fd44cf022281ac9af66ac86d309351320ada5ec177c7e59e8e7861e90c3/Markdown-3.3.tar.gz", hash = "sha256:4f4172a4e989b97f96860fa434b89895069c576e2b537c4b4eed265266a7affc", size = 315253 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0e/ee/173f66a1954046debff7f4199cc826fc29d9e8521e1ae7a1c9d2bf858ea1/Markdown-3.3-py3-none-any.whl", hash = "sha256:fbb1ba54ca41e8991dc5a561d9c6f752f5e4546f8750e56413ea50f2385761d3", size = 94543 }, +] + +[[package]] +name = "markupsafe" +version = "3.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b4/d2/38ff920762f2247c3af5cbbbbc40756f575d9692d381d7c520f45deb9b8f/markupsafe-3.0.1.tar.gz", hash = "sha256:3e683ee4f5d0fa2dde4db77ed8dd8a876686e3fc417655c2ece9a90576905344", size = 20249 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/43/a2/0482d1a157f5f10f72fc4fe8c3be9ffa3651c1f7a12b60a3ab71b2635e13/MarkupSafe-3.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:db842712984e91707437461930e6011e60b39136c7331e971952bb30465bc1a1", size = 14391 }, + { url = "https://files.pythonhosted.org/packages/3b/25/5ea6500d200fd2dc3ea25c765f69dea0a1a8d42ec80a38cd896ad47cb85d/MarkupSafe-3.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3ffb4a8e7d46ed96ae48805746755fadd0909fea2306f93d5d8233ba23dda12a", size = 12414 }, + { url = "https://files.pythonhosted.org/packages/92/41/cf5397dd6bb18895d148aa402cafa71018f2ffc5f6e9d6e90d85b523c741/MarkupSafe-3.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:67c519635a4f64e495c50e3107d9b4075aec33634272b5db1cde839e07367589", size = 21787 }, + { url = "https://files.pythonhosted.org/packages/2e/0d/5d91ef2b4f30afa87483a3a7c108c777d144b1c42d7113459296a8a2bfa0/MarkupSafe-3.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:48488d999ed50ba8d38c581d67e496f955821dc183883550a6fbc7f1aefdc170", size = 20954 }, + { url = "https://files.pythonhosted.org/packages/f6/de/12a4110c2c7c7b502fe0e6f911367726dbb7a37e03e207495135d064bb48/MarkupSafe-3.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f31ae06f1328595d762c9a2bf29dafd8621c7d3adc130cbb46278079758779ca", size = 21086 }, + { url = "https://files.pythonhosted.org/packages/96/55/59389babc6e8ed206849a9958de9da7c23f3a75d294f46e99624fa38fb79/MarkupSafe-3.0.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:80fcbf3add8790caddfab6764bde258b5d09aefbe9169c183f88a7410f0f6dea", size = 21685 }, + { url = "https://files.pythonhosted.org/packages/3d/cb/cbad5f093e12cd79ceea3e2957ba5bd4c2706810f333d0a3422ab2aef358/MarkupSafe-3.0.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:3341c043c37d78cc5ae6e3e305e988532b072329639007fd408a476642a89fd6", size = 21348 }, + { url = "https://files.pythonhosted.org/packages/8e/70/e19c4f39d68a52406012ee118667b57efb0bbe6e950be21187cd7a1b4b80/MarkupSafe-3.0.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:cb53e2a99df28eee3b5f4fea166020d3ef9116fdc5764bc5117486e6d1211b25", size = 21098 }, + { url = "https://files.pythonhosted.org/packages/30/95/ca809c01624428d427e9b3a4500f9068eca941e0c520328954ce84ad966a/MarkupSafe-3.0.1-cp310-cp310-win32.whl", hash = "sha256:db15ce28e1e127a0013dfb8ac243a8e392db8c61eae113337536edb28bdc1f97", size = 15075 }, + { url = "https://files.pythonhosted.org/packages/23/41/decb99ab07793656821a86f827a394700ce28402ebb02dc6d003210d9859/MarkupSafe-3.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:4ffaaac913c3f7345579db4f33b0020db693f302ca5137f106060316761beea9", size = 15535 }, + { url = "https://files.pythonhosted.org/packages/ce/af/2f5d88a7fc7226bd34c6e15f6061246ad8cff979da9f19d11bdd0addd8e2/MarkupSafe-3.0.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:26627785a54a947f6d7336ce5963569b5d75614619e75193bdb4e06e21d447ad", size = 14387 }, + { url = "https://files.pythonhosted.org/packages/8d/43/fd588ef5d192308c5e05974bac659bf6ae29c202b7ea2c4194bcf01eacee/MarkupSafe-3.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b954093679d5750495725ea6f88409946d69cfb25ea7b4c846eef5044194f583", size = 12410 }, + { url = "https://files.pythonhosted.org/packages/58/26/78f161d602fb03804118905e5faacafc0ec592bbad71aaee62537529813a/MarkupSafe-3.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:973a371a55ce9ed333a3a0f8e0bcfae9e0d637711534bcb11e130af2ab9334e7", size = 24006 }, + { url = "https://files.pythonhosted.org/packages/ae/1d/7d5ec8bcfd9c2db235d720fa51d818b7e2abc45250ce5f53dd6cb60409ca/MarkupSafe-3.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:244dbe463d5fb6d7ce161301a03a6fe744dac9072328ba9fc82289238582697b", size = 23303 }, + { url = "https://files.pythonhosted.org/packages/26/ce/703ca3b03a709e3bd1fbffa407789e56b9fa664456538092617dd665fc1d/MarkupSafe-3.0.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d98e66a24497637dd31ccab090b34392dddb1f2f811c4b4cd80c230205c074a3", size = 23205 }, + { url = "https://files.pythonhosted.org/packages/88/60/40be0493decabc2344b12d3a709fd6ccdd15a5ebaee1e8d878315d107ad3/MarkupSafe-3.0.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ad91738f14eb8da0ff82f2acd0098b6257621410dcbd4df20aaa5b4233d75a50", size = 23684 }, + { url = "https://files.pythonhosted.org/packages/6d/f8/8fd52a66e8f62a9add62b4a0b5a3ab4092027437f2ef027f812d94ae91cf/MarkupSafe-3.0.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:7044312a928a66a4c2a22644147bc61a199c1709712069a344a3fb5cfcf16915", size = 23472 }, + { url = "https://files.pythonhosted.org/packages/d4/0b/998b17b9e06ea45ad1646fea586f1b83d02dfdb14d47dd2fd81fba5a08c9/MarkupSafe-3.0.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a4792d3b3a6dfafefdf8e937f14906a51bd27025a36f4b188728a73382231d91", size = 23388 }, + { url = "https://files.pythonhosted.org/packages/5a/57/b6b7aa23b2e26d68d601718f8ce3161fbdaf967b31752c7dec52bef828c9/MarkupSafe-3.0.1-cp311-cp311-win32.whl", hash = "sha256:fa7d686ed9883f3d664d39d5a8e74d3c5f63e603c2e3ff0abcba23eac6542635", size = 15106 }, + { url = "https://files.pythonhosted.org/packages/fc/b5/20cb1d714596acb553c810009c8004c809823947da63e13c19a7decfcb6c/MarkupSafe-3.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:9ba25a71ebf05b9bb0e2ae99f8bc08a07ee8e98c612175087112656ca0f5c8bf", size = 15542 }, + { url = "https://files.pythonhosted.org/packages/45/6d/72ed58d42a12bd9fc288dbff6dd8d03ea973a232ac0538d7f88d105b5251/MarkupSafe-3.0.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:8ae369e84466aa70f3154ee23c1451fda10a8ee1b63923ce76667e3077f2b0c4", size = 14322 }, + { url = "https://files.pythonhosted.org/packages/86/f5/241238f89cdd6461ac9f521af8389f9a48fab97e4f315c69e9e0d52bc919/MarkupSafe-3.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40f1e10d51c92859765522cbd79c5c8989f40f0419614bcdc5015e7b6bf97fc5", size = 12380 }, + { url = "https://files.pythonhosted.org/packages/27/94/79751928bca5841416d8ca02e22198672e021d5c7120338e2a6e3771f8fc/MarkupSafe-3.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5a4cb365cb49b750bdb60b846b0c0bc49ed62e59a76635095a179d440540c346", size = 24099 }, + { url = "https://files.pythonhosted.org/packages/10/6e/1b8070bbfc467429c7983cd5ffd4ec57e1d501763d974c7caaa0a9a79f4c/MarkupSafe-3.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ee3941769bd2522fe39222206f6dd97ae83c442a94c90f2b7a25d847d40f4729", size = 23249 }, + { url = "https://files.pythonhosted.org/packages/66/50/9389ae6cdff78d7481a2a2641830b5eb1d1f62177550e73355a810a889c9/MarkupSafe-3.0.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62fada2c942702ef8952754abfc1a9f7658a4d5460fabe95ac7ec2cbe0d02abc", size = 23149 }, + { url = "https://files.pythonhosted.org/packages/16/02/5dddff5366fde47133186efb847fa88bddef85914bbe623e25cfeccb3517/MarkupSafe-3.0.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:4c2d64fdba74ad16138300815cfdc6ab2f4647e23ced81f59e940d7d4a1469d9", size = 23864 }, + { url = "https://files.pythonhosted.org/packages/f3/f1/700ee6655561cfda986e03f7afc309e3738918551afa7dedd99225586227/MarkupSafe-3.0.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:fb532dd9900381d2e8f48172ddc5a59db4c445a11b9fab40b3b786da40d3b56b", size = 23440 }, + { url = "https://files.pythonhosted.org/packages/fb/3e/d26623ac7f16709823b4c80e0b4a1c9196eeb46182a6c1d47b5e0c8434f4/MarkupSafe-3.0.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:0f84af7e813784feb4d5e4ff7db633aba6c8ca64a833f61d8e4eade234ef0c38", size = 23610 }, + { url = "https://files.pythonhosted.org/packages/51/04/1f8da0810c39cb9fcff96b6baed62272c97065e9cf11471965a161439e20/MarkupSafe-3.0.1-cp312-cp312-win32.whl", hash = "sha256:cbf445eb5628981a80f54087f9acdbf84f9b7d862756110d172993b9a5ae81aa", size = 15113 }, + { url = "https://files.pythonhosted.org/packages/eb/24/a36dc37365bdd358b1e583cc40475593e36ab02cb7da6b3d0b9c05b0da7a/MarkupSafe-3.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:a10860e00ded1dd0a65b83e717af28845bb7bd16d8ace40fe5531491de76b79f", size = 15611 }, + { url = "https://files.pythonhosted.org/packages/b1/60/4572a8aa1beccbc24b133aa0670781a5d2697f4fa3fecf0a87b46383174b/MarkupSafe-3.0.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:e81c52638315ff4ac1b533d427f50bc0afc746deb949210bc85f05d4f15fd772", size = 14325 }, + { url = "https://files.pythonhosted.org/packages/38/42/849915b99a765ec104bfd07ee933de5fc9c58fa9570efa7db81717f495d8/MarkupSafe-3.0.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:312387403cd40699ab91d50735ea7a507b788091c416dd007eac54434aee51da", size = 12373 }, + { url = "https://files.pythonhosted.org/packages/ef/82/4caaebd963c6d60b28e4445f38841d24f8b49bc10594a09956c9d73bfc08/MarkupSafe-3.0.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2ae99f31f47d849758a687102afdd05bd3d3ff7dbab0a8f1587981b58a76152a", size = 24059 }, + { url = "https://files.pythonhosted.org/packages/20/15/6b319be2f79fcfa3173f479d69f4e950b5c9b642db4f22cf73ae5ade745f/MarkupSafe-3.0.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c97ff7fedf56d86bae92fa0a646ce1a0ec7509a7578e1ed238731ba13aabcd1c", size = 23211 }, + { url = "https://files.pythonhosted.org/packages/9d/3f/8963bdf4962feb2154475acb7dc350f04217b5e0be7763a39b432291e229/MarkupSafe-3.0.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a7420ceda262dbb4b8d839a4ec63d61c261e4e77677ed7c66c99f4e7cb5030dd", size = 23095 }, + { url = "https://files.pythonhosted.org/packages/af/93/f770bc70953d32de0c6ce4bcb76271512123a1ead91aaef625a020c5bfaf/MarkupSafe-3.0.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:45d42d132cff577c92bfba536aefcfea7e26efb975bd455db4e6602f5c9f45e7", size = 23901 }, + { url = "https://files.pythonhosted.org/packages/11/92/1e5a33aa0a1190161238628fb68eb1bc5e67b56a5c89f0636328704b463a/MarkupSafe-3.0.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:4c8817557d0de9349109acb38b9dd570b03cc5014e8aabf1cbddc6e81005becd", size = 23463 }, + { url = "https://files.pythonhosted.org/packages/0d/fe/657efdfe385d2a3a701f2c4fcc9577c63c438aeefdd642d0d956c4ecd225/MarkupSafe-3.0.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6a54c43d3ec4cf2a39f4387ad044221c66a376e58c0d0e971d47c475ba79c6b5", size = 23569 }, + { url = "https://files.pythonhosted.org/packages/cf/24/587dea40304046ace60f846cedaebc0d33d967a3ce46c11395a10e7a78ba/MarkupSafe-3.0.1-cp313-cp313-win32.whl", hash = "sha256:c91b394f7601438ff79a4b93d16be92f216adb57d813a78be4446fe0f6bc2d8c", size = 15117 }, + { url = "https://files.pythonhosted.org/packages/32/8f/d8961d633f26a011b4fe054f3bfff52f673423b8c431553268741dfb089e/MarkupSafe-3.0.1-cp313-cp313-win_amd64.whl", hash = "sha256:fe32482b37b4b00c7a52a07211b479653b7fe4f22b2e481b9a9b099d8a430f2f", size = 15613 }, + { url = "https://files.pythonhosted.org/packages/9e/93/d6367ffbcd0c5c371370767f768eaa32af60bc411245b8517e383c6a2b12/MarkupSafe-3.0.1-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:17b2aea42a7280db02ac644db1d634ad47dcc96faf38ab304fe26ba2680d359a", size = 14563 }, + { url = "https://files.pythonhosted.org/packages/4a/37/f813c3835747dec08fe19ac9b9eced01fdf93a4b3e626521675dc7f423a9/MarkupSafe-3.0.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:852dc840f6d7c985603e60b5deaae1d89c56cb038b577f6b5b8c808c97580f1d", size = 12505 }, + { url = "https://files.pythonhosted.org/packages/72/bf/800b4d1580298ca91ccd6c95915bbd147142dad1b8cf91d57b93b28670dd/MarkupSafe-3.0.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0778de17cff1acaeccc3ff30cd99a3fd5c50fc58ad3d6c0e0c4c58092b859396", size = 25358 }, + { url = "https://files.pythonhosted.org/packages/fd/78/26e209abc8f0a379f031f0acc151231974e5b153d7eda5759d17d8f329f2/MarkupSafe-3.0.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:800100d45176652ded796134277ecb13640c1a537cad3b8b53da45aa96330453", size = 23797 }, + { url = "https://files.pythonhosted.org/packages/09/e1/918496a9390891756efee818880e71c1bbaf587f4dc8ede3f3852357310a/MarkupSafe-3.0.1-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d06b24c686a34c86c8c1fba923181eae6b10565e4d80bdd7bc1c8e2f11247aa4", size = 23743 }, + { url = "https://files.pythonhosted.org/packages/cd/c6/26f576cd58d6c2decd9045e4e3f3c5dbc01ea6cb710916e7bbb6ebd95b6b/MarkupSafe-3.0.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:33d1c36b90e570ba7785dacd1faaf091203d9942bc036118fab8110a401eb1a8", size = 25076 }, + { url = "https://files.pythonhosted.org/packages/b5/fa/10b24fb3b0e15fe5389dc88ecc6226ede08297e0ba7130610efbe0cdfb27/MarkupSafe-3.0.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:beeebf760a9c1f4c07ef6a53465e8cfa776ea6a2021eda0d0417ec41043fe984", size = 24037 }, + { url = "https://files.pythonhosted.org/packages/c8/81/4b3f5537d9f6cc4f5c80d6c4b78af9a5247fd37b5aba95807b2cbc336b9a/MarkupSafe-3.0.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:bbde71a705f8e9e4c3e9e33db69341d040c827c7afa6789b14c6e16776074f5a", size = 24015 }, + { url = "https://files.pythonhosted.org/packages/5f/07/8e8dcecd53216c5e01a51e84c32a2bce166690ed19c184774b38cd41921d/MarkupSafe-3.0.1-cp313-cp313t-win32.whl", hash = "sha256:82b5dba6eb1bcc29cc305a18a3c5365d2af06ee71b123216416f7e20d2a84e5b", size = 15213 }, + { url = "https://files.pythonhosted.org/packages/0d/87/4c364e0f109eea2402079abecbe33fef4f347b551a11423d1f4e187ea497/MarkupSafe-3.0.1-cp313-cp313t-win_amd64.whl", hash = "sha256:730d86af59e0e43ce277bb83970530dd223bf7f2a838e086b50affa6ec5f9295", size = 15741 }, +] + +[[package]] +name = "mergedeep" +version = "1.3.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/3a/41/580bb4006e3ed0361b8151a01d324fb03f420815446c7def45d02f74c270/mergedeep-1.3.4.tar.gz", hash = "sha256:0096d52e9dad9939c3d975a774666af186eda617e6ca84df4c94dec30004f2a8", size = 4661 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl", hash = "sha256:70775750742b25c0d8f36c55aed03d24c3384d17c951b3175d898bd778ef0307", size = 6354 }, +] + +[[package]] +name = "mkdocs" +version = "1.5.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, + { name = "colorama", marker = "platform_system == 'Windows'" }, + { name = "ghp-import" }, + { name = "jinja2" }, + { name = "markdown" }, + { name = "markupsafe" }, + { name = "mergedeep" }, + { name = "packaging" }, + { name = "pathspec" }, + { name = "platformdirs" }, + { name = "pyyaml" }, + { name = "pyyaml-env-tag" }, + { name = "watchdog" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ed/bb/24a22f8154cf79b07b45da070633613837d6e59c7d870076f693b7b1c556/mkdocs-1.5.3.tar.gz", hash = "sha256:eb7c99214dcb945313ba30426c2451b735992c73c2e10838f76d09e39ff4d0e2", size = 3654364 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/89/58/aa3301b23966a71d7f8e55233f467b3cec94a651434e9cd9053811342539/mkdocs-1.5.3-py3-none-any.whl", hash = "sha256:3b3a78e736b31158d64dbb2f8ba29bd46a379d0c6e324c2246c3bc3d2189cfc1", size = 3694750 }, +] + +[[package]] +name = "mkdocs-github-dashboard" +version = "0.2.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "mkdocs" }, + { name = "pandas" }, + { name = "python-github-api" }, + { name = "tabulate" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a6/96/4ac42f1b50fc58e15e5b5354463c1393f624ea894844c92ba4ce148cf84c/mkdocs_github_dashboard-0.2.3.zip", hash = "sha256:0f38d8b882d13b9f91d6b3097d064c2863df3fcd1d6bb9e7af3b3cbb022097fc", size = 16673 } + +[[package]] +name = "mkdocs-inline-select-svg-plugin" +version = "0.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "beautifulsoup4" }, + { name = "lxml" }, + { name = "mkdocs" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d9/d4/ba1f0fba644e541701fa40e24124a983126e6b205afb7b2ab6e53f246f83/mkdocs_inline_select_svg_plugin-0.1.0.tar.gz", hash = "sha256:b2cfa3c79f6809fd86c778adfb7b8da9c6c101c98acf50b3de7169fcbc8d3daf", size = 8473 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/83/cc/a3cb392357c65563a5208b3b430a6569bd400aff7a1683451ab96eed3249/mkdocs_inline_select_svg_plugin-0.1.0-py3-none-any.whl", hash = "sha256:e35e242a0d51c844576b75258e15a29f05b8aaeaf871b209368df2e880fcaf5b", size = 8303 }, +] + +[[package]] +name = "mkdocs-material" +version = "9.5.18" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "babel" }, + { name = "colorama" }, + { name = "jinja2" }, + { name = "markdown" }, + { name = "mkdocs" }, + { name = "mkdocs-material-extensions" }, + { name = "paginate" }, + { name = "pygments" }, + { name = "pymdown-extensions" }, + { name = "regex" }, + { name = "requests" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b6/2d/6da67c06f8af1f7b8fb534eec7ebad5b9ce4fcecfab4287312dea2e62912/mkdocs_material-9.5.18.tar.gz", hash = "sha256:a43f470947053fa2405c33995f282d24992c752a50114f23f30da9d8d0c57e62", size = 4077674 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4a/c6/2db256334564689703390a27f3bdc64f4fe6e6f6c917cc497452cee8ef1c/mkdocs_material-9.5.18-py3-none-any.whl", hash = "sha256:1e0e27fc9fe239f9064318acf548771a4629d5fd5dfd45444fd80a953fe21eb4", size = 8766354 }, +] + +[[package]] +name = "mkdocs-material-extensions" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/79/9b/9b4c96d6593b2a541e1cb8b34899a6d021d208bb357042823d4d2cabdbe7/mkdocs_material_extensions-1.3.1.tar.gz", hash = "sha256:10c9511cea88f568257f960358a467d12b970e1f7b2c0e5fb2bb48cab1928443", size = 11847 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5b/54/662a4743aa81d9582ee9339d4ffa3c8fd40a4965e033d77b9da9774d3960/mkdocs_material_extensions-1.3.1-py3-none-any.whl", hash = "sha256:adff8b62700b25cb77b53358dad940f3ef973dd6db797907c49e3c2ef3ab4e31", size = 8728 }, +] + +[[package]] +name = "mkdocs-mermaid2-plugin" +version = "1.1.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "beautifulsoup4" }, + { name = "jsbeautifier" }, + { name = "mkdocs" }, + { name = "pymdown-extensions" }, + { name = "requests" }, + { name = "setuptools" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/6f/e5/6b9cfb9c73b7d3cb0858bcb15b7f2d506272c6e593eefa644b9a1f8130fc/mkdocs-mermaid2-plugin-1.1.1.tar.gz", hash = "sha256:bea5f3cbe6cb76bad21b81e49a01e074427ed466666c5d404e62fe8698bc2d7c", size = 1857620 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a5/9a/2933f5609fad97092a054eb51a830b017f0c338e251be8d518d90a3531fb/mkdocs_mermaid2_plugin-1.1.1-py3-none-any.whl", hash = "sha256:4e25876b59d1e151ca33a467207b346404b4a246f4f24af5e44c32408e175882", size = 10074 }, +] + +[[package]] +name = "numpy" +version = "2.1.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/4b/d1/8a730ea07f4a37d94f9172f4ce1d81064b7a64766b460378be278952de75/numpy-2.1.2.tar.gz", hash = "sha256:13532a088217fa624c99b843eeb54640de23b3414b14aa66d023805eb731066c", size = 18878063 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1c/a2/40a76d357f168e9f9f06d6cc2c8e22dd5fb2bfbe63fe2c433057258c145a/numpy-2.1.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:30d53720b726ec36a7f88dc873f0eec8447fbc93d93a8f079dfac2629598d6ee", size = 21150947 }, + { url = "https://files.pythonhosted.org/packages/b5/d0/ba271ea9108d7278d3889a7eb38d77370a88713fb94339964e71ac184d4a/numpy-2.1.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e8d3ca0a72dd8846eb6f7dfe8f19088060fcb76931ed592d29128e0219652884", size = 13758184 }, + { url = "https://files.pythonhosted.org/packages/7c/b9/5c6507439cd756201010f7937bf90712c2469052ae094584af14557dd64f/numpy-2.1.2-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:fc44e3c68ff00fd991b59092a54350e6e4911152682b4782f68070985aa9e648", size = 5354091 }, + { url = "https://files.pythonhosted.org/packages/60/21/7938cf724d9e84e45fb886f3fc794ab431d71facfebc261e3e9f19f3233a/numpy-2.1.2-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:7c1c60328bd964b53f8b835df69ae8198659e2b9302ff9ebb7de4e5a5994db3d", size = 6887169 }, + { url = "https://files.pythonhosted.org/packages/09/8d/42a124657f5d31902fca73921b25a0d022cead2b32ce7e6975762cd2995a/numpy-2.1.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6cdb606a7478f9ad91c6283e238544451e3a95f30fb5467fbf715964341a8a86", size = 13888165 }, + { url = "https://files.pythonhosted.org/packages/fb/25/ba023652a39a2c127200e85aed975fc6119b421e2c348e5d0171e2046edb/numpy-2.1.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d666cb72687559689e9906197e3bec7b736764df6a2e58ee265e360663e9baf7", size = 16326954 }, + { url = "https://files.pythonhosted.org/packages/34/58/23e6b07fad492b7c47cf09cd8bad6983658f0f925b6c535fd008e3e86274/numpy-2.1.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c6eef7a2dbd0abfb0d9eaf78b73017dbfd0b54051102ff4e6a7b2980d5ac1a03", size = 16702916 }, + { url = "https://files.pythonhosted.org/packages/91/24/37b5cf2dc7d385ac97f7b7fe50cba312abb70a2a5eac74c23af028811f73/numpy-2.1.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:12edb90831ff481f7ef5f6bc6431a9d74dc0e5ff401559a71e5e4611d4f2d466", size = 14384372 }, + { url = "https://files.pythonhosted.org/packages/ea/ec/0f6d471058a01d1a05a50d2793898de1549280fa715a8537987ee866b5d9/numpy-2.1.2-cp310-cp310-win32.whl", hash = "sha256:a65acfdb9c6ebb8368490dbafe83c03c7e277b37e6857f0caeadbbc56e12f4fb", size = 6535361 }, + { url = "https://files.pythonhosted.org/packages/c2/3d/293cc5927f916a7bc6bf74da8f6defab63d1b13f0959d7e21878ad8a20d8/numpy-2.1.2-cp310-cp310-win_amd64.whl", hash = "sha256:860ec6e63e2c5c2ee5e9121808145c7bf86c96cca9ad396c0bd3e0f2798ccbe2", size = 12865501 }, + { url = "https://files.pythonhosted.org/packages/aa/9c/9a6ec3ae89cd0648d419781284308f2956d2a61d932b5ac9682c956a171b/numpy-2.1.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b42a1a511c81cc78cbc4539675713bbcf9d9c3913386243ceff0e9429ca892fe", size = 21154845 }, + { url = "https://files.pythonhosted.org/packages/02/69/9f05c4ecc75fabf297b17743996371b4c3dfc4d92e15c5c38d8bb3db8d74/numpy-2.1.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:faa88bc527d0f097abdc2c663cddf37c05a1c2f113716601555249805cf573f1", size = 13789409 }, + { url = "https://files.pythonhosted.org/packages/34/4e/f95c99217bf77bbfaaf660d693c10bd0dc03b6032d19316d316088c9e479/numpy-2.1.2-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:c82af4b2ddd2ee72d1fc0c6695048d457e00b3582ccde72d8a1c991b808bb20f", size = 5352097 }, + { url = "https://files.pythonhosted.org/packages/06/13/f5d87a497c16658e9af8920449b0b5692b469586b8231340c672962071c5/numpy-2.1.2-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:13602b3174432a35b16c4cfb5de9a12d229727c3dd47a6ce35111f2ebdf66ff4", size = 6891195 }, + { url = "https://files.pythonhosted.org/packages/6c/89/691ac07429ac061b344d5e37fa8e94be51a6017734aea15f2d9d7c6d119a/numpy-2.1.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1ebec5fd716c5a5b3d8dfcc439be82a8407b7b24b230d0ad28a81b61c2f4659a", size = 13895153 }, + { url = "https://files.pythonhosted.org/packages/23/69/538317f0d925095537745f12aced33be1570bbdc4acde49b33748669af96/numpy-2.1.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e2b49c3c0804e8ecb05d59af8386ec2f74877f7ca8fd9c1e00be2672e4d399b1", size = 16338306 }, + { url = "https://files.pythonhosted.org/packages/af/03/863fe7062c2106d3c151f7df9353f2ae2237c1dd6900f127a3eb1f24cb1b/numpy-2.1.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:2cbba4b30bf31ddbe97f1c7205ef976909a93a66bb1583e983adbd155ba72ac2", size = 16710893 }, + { url = "https://files.pythonhosted.org/packages/70/77/0ad9efe25482009873f9660d29a40a8c41a6f0e8b541195e3c95c70684c5/numpy-2.1.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8e00ea6fc82e8a804433d3e9cedaa1051a1422cb6e443011590c14d2dea59146", size = 14398048 }, + { url = "https://files.pythonhosted.org/packages/3e/0f/e785fe75544db9f2b0bb1c181e13ceff349ce49753d807fd9672916aa06d/numpy-2.1.2-cp311-cp311-win32.whl", hash = "sha256:5006b13a06e0b38d561fab5ccc37581f23c9511879be7693bd33c7cd15ca227c", size = 6533458 }, + { url = "https://files.pythonhosted.org/packages/d4/96/450054662295125af861d48d2c4bc081dadcf1974a879b2104613157aa62/numpy-2.1.2-cp311-cp311-win_amd64.whl", hash = "sha256:f1eb068ead09f4994dec71c24b2844f1e4e4e013b9629f812f292f04bd1510d9", size = 12870896 }, + { url = "https://files.pythonhosted.org/packages/a0/7d/554a6838f37f3ada5a55f25173c619d556ae98092a6e01afb6e710501d70/numpy-2.1.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d7bf0a4f9f15b32b5ba53147369e94296f5fffb783db5aacc1be15b4bf72f43b", size = 20848077 }, + { url = "https://files.pythonhosted.org/packages/b0/29/cb48a402ea879e645b16218718f3f7d9588a77d674a9dcf22e4c43487636/numpy-2.1.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b1d0fcae4f0949f215d4632be684a539859b295e2d0cb14f78ec231915d644db", size = 13493242 }, + { url = "https://files.pythonhosted.org/packages/56/44/f899b0581766c230da42f751b7b8896d096640b19b312164c267e48d36cb/numpy-2.1.2-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:f751ed0a2f250541e19dfca9f1eafa31a392c71c832b6bb9e113b10d050cb0f1", size = 5089219 }, + { url = "https://files.pythonhosted.org/packages/79/8f/b987070d45161a7a4504afc67ed38544ed2c0ed5576263599a0402204a9c/numpy-2.1.2-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:bd33f82e95ba7ad632bc57837ee99dba3d7e006536200c4e9124089e1bf42426", size = 6620167 }, + { url = "https://files.pythonhosted.org/packages/c4/a7/af3329fda3c3ec31d9b650e42bbcd3422fc62a765cbb1405fde4177a0996/numpy-2.1.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1b8cde4f11f0a975d1fd59373b32e2f5a562ade7cde4f85b7137f3de8fbb29a0", size = 13604905 }, + { url = "https://files.pythonhosted.org/packages/9b/b4/e3c7e6fab0f77fff6194afa173d1f2342073d91b1d3b4b30b17c3fb4407a/numpy-2.1.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d95f286b8244b3649b477ac066c6906fbb2905f8ac19b170e2175d3d799f4df", size = 16041825 }, + { url = "https://files.pythonhosted.org/packages/e9/50/6828e66a78aa03147c111f84d55f33ce2dde547cb578d6744a3b06a0124b/numpy-2.1.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ab4754d432e3ac42d33a269c8567413bdb541689b02d93788af4131018cbf366", size = 16409541 }, + { url = "https://files.pythonhosted.org/packages/bf/72/66af7916d9c3c6dbfbc8acdd4930c65461e1953374a2bc43d00f948f004a/numpy-2.1.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e585c8ae871fd38ac50598f4763d73ec5497b0de9a0ab4ef5b69f01c6a046142", size = 14081134 }, + { url = "https://files.pythonhosted.org/packages/dc/5a/59a67d84f33fe00ae74f0b5b69dd4f93a586a4aba7f7e19b54b2133db038/numpy-2.1.2-cp312-cp312-win32.whl", hash = "sha256:9c6c754df29ce6a89ed23afb25550d1c2d5fdb9901d9c67a16e0b16eaf7e2550", size = 6237784 }, + { url = "https://files.pythonhosted.org/packages/4c/79/73735a6a5dad6059c085f240a4e74c9270feccd2bc66e4d31b5ca01d329c/numpy-2.1.2-cp312-cp312-win_amd64.whl", hash = "sha256:456e3b11cb79ac9946c822a56346ec80275eaf2950314b249b512896c0d2505e", size = 12568254 }, + { url = "https://files.pythonhosted.org/packages/16/72/716fa1dbe92395a9a623d5049203ff8ddb0cfce65b9df9117c3696ccc011/numpy-2.1.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a84498e0d0a1174f2b3ed769b67b656aa5460c92c9554039e11f20a05650f00d", size = 20834690 }, + { url = "https://files.pythonhosted.org/packages/1e/fb/3e85a39511586053b5c6a59a643879e376fae22230ebfef9cfabb0e032e2/numpy-2.1.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:4d6ec0d4222e8ffdab1744da2560f07856421b367928026fb540e1945f2eeeaf", size = 13507474 }, + { url = "https://files.pythonhosted.org/packages/35/eb/5677556d9ba13436dab51e129f98d4829d95cd1b6bd0e199c14485a4bdb9/numpy-2.1.2-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:259ec80d54999cc34cd1eb8ded513cb053c3bf4829152a2e00de2371bd406f5e", size = 5074742 }, + { url = "https://files.pythonhosted.org/packages/3e/c5/6c5ef5ba41b65a7e51bed50dbf3e1483eb578055633dd013e811a28e96a1/numpy-2.1.2-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:675c741d4739af2dc20cd6c6a5c4b7355c728167845e3c6b0e824e4e5d36a6c3", size = 6606787 }, + { url = "https://files.pythonhosted.org/packages/08/ac/f2f29dd4fd325b379c7dc932a0ebab22f0e031dbe80b2f6019b291a3a544/numpy-2.1.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:05b2d4e667895cc55e3ff2b56077e4c8a5604361fc21a042845ea3ad67465aa8", size = 13601333 }, + { url = "https://files.pythonhosted.org/packages/44/26/63f5f4e5089654dfb858f4892215ed968cd1a68e6f4a83f9961f84f855cb/numpy-2.1.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:43cca367bf94a14aca50b89e9bc2061683116cfe864e56740e083392f533ce7a", size = 16038090 }, + { url = "https://files.pythonhosted.org/packages/1d/21/015e0594de9c3a8d5edd24943d2bd23f102ec71aec026083f822f86497e2/numpy-2.1.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:76322dcdb16fccf2ac56f99048af32259dcc488d9b7e25b51e5eca5147a3fb98", size = 16410865 }, + { url = "https://files.pythonhosted.org/packages/df/01/c1bcf9e6025d79077fbf3f3ee503b50aa7bfabfcd8f4b54f5829f4c00f3f/numpy-2.1.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:32e16a03138cabe0cb28e1007ee82264296ac0983714094380b408097a418cfe", size = 14078077 }, + { url = "https://files.pythonhosted.org/packages/ba/06/db9d127d63bd11591770ba9f3d960f8041e0f895184b9351d4b1b5b56983/numpy-2.1.2-cp313-cp313-win32.whl", hash = "sha256:242b39d00e4944431a3cd2db2f5377e15b5785920421993770cddb89992c3f3a", size = 6234904 }, + { url = "https://files.pythonhosted.org/packages/a9/96/9f61f8f95b6e0ea0aa08633b704c75d1882bdcb331bdf8bfd63263b25b00/numpy-2.1.2-cp313-cp313-win_amd64.whl", hash = "sha256:f2ded8d9b6f68cc26f8425eda5d3877b47343e68ca23d0d0846f4d312ecaa445", size = 12561910 }, + { url = "https://files.pythonhosted.org/packages/36/b8/033f627821784a48e8f75c218033471eebbaacdd933f8979c79637a1b44b/numpy-2.1.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:2ffef621c14ebb0188a8633348504a35c13680d6da93ab5cb86f4e54b7e922b5", size = 20857719 }, + { url = "https://files.pythonhosted.org/packages/96/46/af5726fde5b74ed83f2f17a73386d399319b7ed4d51279fb23b721d0816d/numpy-2.1.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:ad369ed238b1959dfbade9018a740fb9392c5ac4f9b5173f420bd4f37ba1f7a0", size = 13518826 }, + { url = "https://files.pythonhosted.org/packages/db/6e/8ce677edf36da1c4dae80afe5529f47690697eb55b4864673af260ccea7b/numpy-2.1.2-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:d82075752f40c0ddf57e6e02673a17f6cb0f8eb3f587f63ca1eaab5594da5b17", size = 5115036 }, + { url = "https://files.pythonhosted.org/packages/6a/ba/3cce44fb1b8438042c11847048812a776f75ee0e7070179c22e4cfbf420c/numpy-2.1.2-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:1600068c262af1ca9580a527d43dc9d959b0b1d8e56f8a05d830eea39b7c8af6", size = 6628641 }, + { url = "https://files.pythonhosted.org/packages/59/c8/e722998720ccbd35ffbcf1d1b8ed0aa2304af88d3f1c38e06ebf983599b3/numpy-2.1.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a26ae94658d3ba3781d5e103ac07a876b3e9b29db53f68ed7df432fd033358a8", size = 13574803 }, + { url = "https://files.pythonhosted.org/packages/7c/8e/fc1fdd83a55476765329ac2913321c4aed5b082a7915095628c4ca30ea72/numpy-2.1.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13311c2db4c5f7609b462bc0f43d3c465424d25c626d95040f073e30f7570e35", size = 16021174 }, + { url = "https://files.pythonhosted.org/packages/2a/b6/a790742aa88067adb4bd6c89a946778c1417d4deaeafce3ca928f26d4c52/numpy-2.1.2-cp313-cp313t-musllinux_1_1_x86_64.whl", hash = "sha256:2abbf905a0b568706391ec6fa15161fad0fb5d8b68d73c461b3c1bab6064dd62", size = 16400117 }, + { url = "https://files.pythonhosted.org/packages/48/6f/129e3c17e3befe7fefdeaa6890f4c4df3f3cf0831aa053802c3862da67aa/numpy-2.1.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:ef444c57d664d35cac4e18c298c47d7b504c66b17c2ea91312e979fcfbdfb08a", size = 14066202 }, + { url = "https://files.pythonhosted.org/packages/73/c9/3e1d6bbe6d3d2e2c5a9483b24b2f29a229b323f62054278a3bba7fee11e5/numpy-2.1.2-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:bdd407c40483463898b84490770199d5714dcc9dd9b792f6c6caccc523c00952", size = 20981945 }, + { url = "https://files.pythonhosted.org/packages/6e/62/989c4988bde1a8e08117fccc3bab73d2886421fb98cde597168714f3c54e/numpy-2.1.2-pp310-pypy310_pp73-macosx_14_0_x86_64.whl", hash = "sha256:da65fb46d4cbb75cb417cddf6ba5e7582eb7bb0b47db4b99c9fe5787ce5d91f5", size = 6750558 }, + { url = "https://files.pythonhosted.org/packages/53/b1/00ef9f30975f1312a53257f68e57b4513d14d537e03d507e2773a684b1e8/numpy-2.1.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1c193d0b0238638e6fc5f10f1b074a6993cb13b0b431f64079a509d63d3aa8b7", size = 16141552 }, + { url = "https://files.pythonhosted.org/packages/c0/ec/0c04903b48dfea6be1d7b47ba70f98709fb7198fd970784a1400c391d522/numpy-2.1.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:a7d80b2e904faa63068ead63107189164ca443b42dd1930299e0d1cb041cec2e", size = 12789924 }, +] + +[[package]] +name = "ouxt-automation" +version = "0.1.0" +source = { virtual = "." } +dependencies = [ + { name = "fontawesome-markdown" }, + { name = "markdown" }, + { name = "mkdocs" }, + { name = "mkdocs-github-dashboard" }, + { name = "mkdocs-inline-select-svg-plugin" }, + { name = "mkdocs-material" }, + { name = "mkdocs-mermaid2-plugin" }, + { name = "pandas" }, + { name = "plantuml-markdown" }, + { name = "pymdown-extensions" }, + { name = "python-github-api" }, + { name = "python-markdown-math" }, +] + +[package.metadata] +requires-dist = [ + { name = "fontawesome-markdown", specifier = ">=0.2.6" }, + { name = "markdown", specifier = "==3.3.0" }, + { name = "mkdocs", specifier = ">=1.5.3" }, + { name = "mkdocs-github-dashboard", specifier = ">=0.2.3" }, + { name = "mkdocs-inline-select-svg-plugin", specifier = ">=0.1.0" }, + { name = "mkdocs-material", specifier = ">=9.5.18" }, + { name = "mkdocs-mermaid2-plugin", specifier = ">=1.1.1" }, + { name = "pandas", specifier = ">=2.2.3" }, + { name = "plantuml-markdown", specifier = ">=3.10.4" }, + { name = "pymdown-extensions", specifier = ">=10.4" }, + { name = "python-github-api", specifier = ">=0.1.1" }, + { name = "python-markdown-math", specifier = ">=0.8" }, +] + +[[package]] +name = "packaging" +version = "24.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/51/65/50db4dda066951078f0a96cf12f4b9ada6e4b811516bf0262c0f4f7064d4/packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002", size = 148788 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/08/aa/cc0199a5f0ad350994d660967a8efb233fe0416e4639146c089643407ce6/packaging-24.1-py3-none-any.whl", hash = "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124", size = 53985 }, +] + +[[package]] +name = "paginate" +version = "0.5.7" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ec/46/68dde5b6bc00c1296ec6466ab27dddede6aec9af1b99090e1107091b3b84/paginate-0.5.7.tar.gz", hash = "sha256:22bd083ab41e1a8b4f3690544afb2c60c25e5c9a63a30fa2f483f6c60c8e5945", size = 19252 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/90/96/04b8e52da071d28f5e21a805b19cb9390aa17a47462ac87f5e2696b9566d/paginate-0.5.7-py2.py3-none-any.whl", hash = "sha256:b885e2af73abcf01d9559fd5216b57ef722f8c42affbb63942377668e35c7591", size = 13746 }, +] + +[[package]] +name = "pandas" +version = "2.2.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy" }, + { name = "python-dateutil" }, + { name = "pytz" }, + { name = "tzdata" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9c/d6/9f8431bacc2e19dca897724cd097b1bb224a6ad5433784a44b587c7c13af/pandas-2.2.3.tar.gz", hash = "sha256:4f18ba62b61d7e192368b84517265a99b4d7ee8912f8708660fb4a366cc82667", size = 4399213 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/aa/70/c853aec59839bceed032d52010ff5f1b8d87dc3114b762e4ba2727661a3b/pandas-2.2.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1948ddde24197a0f7add2bdc4ca83bf2b1ef84a1bc8ccffd95eda17fd836ecb5", size = 12580827 }, + { url = "https://files.pythonhosted.org/packages/99/f2/c4527768739ffa4469b2b4fff05aa3768a478aed89a2f271a79a40eee984/pandas-2.2.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:381175499d3802cde0eabbaf6324cce0c4f5d52ca6f8c377c29ad442f50f6348", size = 11303897 }, + { url = "https://files.pythonhosted.org/packages/ed/12/86c1747ea27989d7a4064f806ce2bae2c6d575b950be087837bdfcabacc9/pandas-2.2.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d9c45366def9a3dd85a6454c0e7908f2b3b8e9c138f5dc38fed7ce720d8453ed", size = 66480908 }, + { url = "https://files.pythonhosted.org/packages/44/50/7db2cd5e6373ae796f0ddad3675268c8d59fb6076e66f0c339d61cea886b/pandas-2.2.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:86976a1c5b25ae3f8ccae3a5306e443569ee3c3faf444dfd0f41cda24667ad57", size = 13064210 }, + { url = "https://files.pythonhosted.org/packages/61/61/a89015a6d5536cb0d6c3ba02cebed51a95538cf83472975275e28ebf7d0c/pandas-2.2.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:b8661b0238a69d7aafe156b7fa86c44b881387509653fdf857bebc5e4008ad42", size = 16754292 }, + { url = "https://files.pythonhosted.org/packages/ce/0d/4cc7b69ce37fac07645a94e1d4b0880b15999494372c1523508511b09e40/pandas-2.2.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:37e0aced3e8f539eccf2e099f65cdb9c8aa85109b0be6e93e2baff94264bdc6f", size = 14416379 }, + { url = "https://files.pythonhosted.org/packages/31/9e/6ebb433de864a6cd45716af52a4d7a8c3c9aaf3a98368e61db9e69e69a9c/pandas-2.2.3-cp310-cp310-win_amd64.whl", hash = "sha256:56534ce0746a58afaf7942ba4863e0ef81c9c50d3f0ae93e9497d6a41a057645", size = 11598471 }, + { url = "https://files.pythonhosted.org/packages/a8/44/d9502bf0ed197ba9bf1103c9867d5904ddcaf869e52329787fc54ed70cc8/pandas-2.2.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:66108071e1b935240e74525006034333f98bcdb87ea116de573a6a0dccb6c039", size = 12602222 }, + { url = "https://files.pythonhosted.org/packages/52/11/9eac327a38834f162b8250aab32a6781339c69afe7574368fffe46387edf/pandas-2.2.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7c2875855b0ff77b2a64a0365e24455d9990730d6431b9e0ee18ad8acee13dbd", size = 11321274 }, + { url = "https://files.pythonhosted.org/packages/45/fb/c4beeb084718598ba19aa9f5abbc8aed8b42f90930da861fcb1acdb54c3a/pandas-2.2.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:cd8d0c3be0515c12fed0bdbae072551c8b54b7192c7b1fda0ba56059a0179698", size = 15579836 }, + { url = "https://files.pythonhosted.org/packages/cd/5f/4dba1d39bb9c38d574a9a22548c540177f78ea47b32f99c0ff2ec499fac5/pandas-2.2.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c124333816c3a9b03fbeef3a9f230ba9a737e9e5bb4060aa2107a86cc0a497fc", size = 13058505 }, + { url = "https://files.pythonhosted.org/packages/b9/57/708135b90391995361636634df1f1130d03ba456e95bcf576fada459115a/pandas-2.2.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:63cc132e40a2e084cf01adf0775b15ac515ba905d7dcca47e9a251819c575ef3", size = 16744420 }, + { url = "https://files.pythonhosted.org/packages/86/4a/03ed6b7ee323cf30404265c284cee9c65c56a212e0a08d9ee06984ba2240/pandas-2.2.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:29401dbfa9ad77319367d36940cd8a0b3a11aba16063e39632d98b0e931ddf32", size = 14440457 }, + { url = "https://files.pythonhosted.org/packages/ed/8c/87ddf1fcb55d11f9f847e3c69bb1c6f8e46e2f40ab1a2d2abadb2401b007/pandas-2.2.3-cp311-cp311-win_amd64.whl", hash = "sha256:3fc6873a41186404dad67245896a6e440baacc92f5b716ccd1bc9ed2995ab2c5", size = 11617166 }, + { url = "https://files.pythonhosted.org/packages/17/a3/fb2734118db0af37ea7433f57f722c0a56687e14b14690edff0cdb4b7e58/pandas-2.2.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b1d432e8d08679a40e2a6d8b2f9770a5c21793a6f9f47fdd52c5ce1948a5a8a9", size = 12529893 }, + { url = "https://files.pythonhosted.org/packages/e1/0c/ad295fd74bfac85358fd579e271cded3ac969de81f62dd0142c426b9da91/pandas-2.2.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a5a1595fe639f5988ba6a8e5bc9649af3baf26df3998a0abe56c02609392e0a4", size = 11363475 }, + { url = "https://files.pythonhosted.org/packages/c6/2a/4bba3f03f7d07207481fed47f5b35f556c7441acddc368ec43d6643c5777/pandas-2.2.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5de54125a92bb4d1c051c0659e6fcb75256bf799a732a87184e5ea503965bce3", size = 15188645 }, + { url = "https://files.pythonhosted.org/packages/38/f8/d8fddee9ed0d0c0f4a2132c1dfcf0e3e53265055da8df952a53e7eaf178c/pandas-2.2.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fffb8ae78d8af97f849404f21411c95062db1496aeb3e56f146f0355c9989319", size = 12739445 }, + { url = "https://files.pythonhosted.org/packages/20/e8/45a05d9c39d2cea61ab175dbe6a2de1d05b679e8de2011da4ee190d7e748/pandas-2.2.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6dfcb5ee8d4d50c06a51c2fffa6cff6272098ad6540aed1a76d15fb9318194d8", size = 16359235 }, + { url = "https://files.pythonhosted.org/packages/1d/99/617d07a6a5e429ff90c90da64d428516605a1ec7d7bea494235e1c3882de/pandas-2.2.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:062309c1b9ea12a50e8ce661145c6aab431b1e99530d3cd60640e255778bd43a", size = 14056756 }, + { url = "https://files.pythonhosted.org/packages/29/d4/1244ab8edf173a10fd601f7e13b9566c1b525c4f365d6bee918e68381889/pandas-2.2.3-cp312-cp312-win_amd64.whl", hash = "sha256:59ef3764d0fe818125a5097d2ae867ca3fa64df032331b7e0917cf5d7bf66b13", size = 11504248 }, + { url = "https://files.pythonhosted.org/packages/64/22/3b8f4e0ed70644e85cfdcd57454686b9057c6c38d2f74fe4b8bc2527214a/pandas-2.2.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f00d1345d84d8c86a63e476bb4955e46458b304b9575dcf71102b5c705320015", size = 12477643 }, + { url = "https://files.pythonhosted.org/packages/e4/93/b3f5d1838500e22c8d793625da672f3eec046b1a99257666c94446969282/pandas-2.2.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:3508d914817e153ad359d7e069d752cdd736a247c322d932eb89e6bc84217f28", size = 11281573 }, + { url = "https://files.pythonhosted.org/packages/f5/94/6c79b07f0e5aab1dcfa35a75f4817f5c4f677931d4234afcd75f0e6a66ca/pandas-2.2.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:22a9d949bfc9a502d320aa04e5d02feab689d61da4e7764b62c30b991c42c5f0", size = 15196085 }, + { url = "https://files.pythonhosted.org/packages/e8/31/aa8da88ca0eadbabd0a639788a6da13bb2ff6edbbb9f29aa786450a30a91/pandas-2.2.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3a255b2c19987fbbe62a9dfd6cff7ff2aa9ccab3fc75218fd4b7530f01efa24", size = 12711809 }, + { url = "https://files.pythonhosted.org/packages/ee/7c/c6dbdb0cb2a4344cacfb8de1c5808ca885b2e4dcfde8008266608f9372af/pandas-2.2.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:800250ecdadb6d9c78eae4990da62743b857b470883fa27f652db8bdde7f6659", size = 16356316 }, + { url = "https://files.pythonhosted.org/packages/57/b7/8b757e7d92023b832869fa8881a992696a0bfe2e26f72c9ae9f255988d42/pandas-2.2.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6374c452ff3ec675a8f46fd9ab25c4ad0ba590b71cf0656f8b6daa5202bca3fb", size = 14022055 }, + { url = "https://files.pythonhosted.org/packages/3b/bc/4b18e2b8c002572c5a441a64826252ce5da2aa738855747247a971988043/pandas-2.2.3-cp313-cp313-win_amd64.whl", hash = "sha256:61c5ad4043f791b61dd4752191d9f07f0ae412515d59ba8f005832a532f8736d", size = 11481175 }, + { url = "https://files.pythonhosted.org/packages/76/a3/a5d88146815e972d40d19247b2c162e88213ef51c7c25993942c39dbf41d/pandas-2.2.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:3b71f27954685ee685317063bf13c7709a7ba74fc996b84fc6821c59b0f06468", size = 12615650 }, + { url = "https://files.pythonhosted.org/packages/9c/8c/f0fd18f6140ddafc0c24122c8a964e48294acc579d47def376fef12bcb4a/pandas-2.2.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:38cf8125c40dae9d5acc10fa66af8ea6fdf760b2714ee482ca691fc66e6fcb18", size = 11290177 }, + { url = "https://files.pythonhosted.org/packages/ed/f9/e995754eab9c0f14c6777401f7eece0943840b7a9fc932221c19d1abee9f/pandas-2.2.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ba96630bc17c875161df3818780af30e43be9b166ce51c9a18c1feae342906c2", size = 14651526 }, + { url = "https://files.pythonhosted.org/packages/25/b0/98d6ae2e1abac4f35230aa756005e8654649d305df9a28b16b9ae4353bff/pandas-2.2.3-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1db71525a1538b30142094edb9adc10be3f3e176748cd7acc2240c2f2e5aa3a4", size = 11871013 }, + { url = "https://files.pythonhosted.org/packages/cc/57/0f72a10f9db6a4628744c8e8f0df4e6e21de01212c7c981d31e50ffc8328/pandas-2.2.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:15c0e1e02e93116177d29ff83e8b1619c93ddc9c49083f237d4312337a61165d", size = 15711620 }, + { url = "https://files.pythonhosted.org/packages/ab/5f/b38085618b950b79d2d9164a711c52b10aefc0ae6833b96f626b7021b2ed/pandas-2.2.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:ad5b65698ab28ed8d7f18790a0dc58005c7629f227be9ecc1072aa74c0c1d43a", size = 13098436 }, +] + +[[package]] +name = "pathspec" +version = "0.12.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ca/bc/f35b8446f4531a7cb215605d100cd88b7ac6f44ab3fc94870c120ab3adbf/pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712", size = 51043 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", size = 31191 }, +] + +[[package]] +name = "plantuml-markdown" +version = "3.10.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markdown" }, + { name = "requests" }, + { name = "six" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/75/2a/806d807ae4f65149b2f132e73b02beb6aa3cd9afc4bd79f45f13dee454b8/plantuml_markdown-3.10.4.tar.gz", hash = "sha256:5c303ef498dd6fd8efcfc8fe2540109fb6e3aac5bebaf09e33b6413ab3e5c374", size = 30578 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fd/12/72cdf2f4220c37be55d2c56a093013e4f385f006493ac2942a2a18f82801/plantuml_markdown-3.10.4-py3-none-any.whl", hash = "sha256:23e66b0ea958fc4335400b961784885138e497b9af7d2870d3cc800b11c22cea", size = 18868 }, +] + +[[package]] +name = "platformdirs" +version = "4.3.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/13/fc/128cc9cb8f03208bdbf93d3aa862e16d376844a14f9a0ce5cf4507372de4/platformdirs-4.3.6.tar.gz", hash = "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907", size = 21302 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3c/a6/bc1012356d8ece4d66dd75c4b9fc6c1f6650ddd5991e421177d9f8f671be/platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb", size = 18439 }, +] + +[[package]] +name = "pygments" +version = "2.18.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/8e/62/8336eff65bcbc8e4cb5d05b55faf041285951b6e80f33e2bff2024788f31/pygments-2.18.0.tar.gz", hash = "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199", size = 4891905 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f7/3f/01c8b82017c199075f8f788d0d906b9ffbbc5a47dc9918a945e13d5a2bda/pygments-2.18.0-py3-none-any.whl", hash = "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a", size = 1205513 }, +] + +[[package]] +name = "pymdown-extensions" +version = "10.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markdown" }, + { name = "pyyaml" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/85/71/5f48080bde77b07ca1eba6d7cb5c5598ac6c8f2a399846159b3c8b45e171/pymdown_extensions-10.4.tar.gz", hash = "sha256:bc46f11749ecd4d6b71cf62396104b4a200bad3498cb0f5dad1b8502fe461a35", size = 785151 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/98/2d/2929de81618c7213176899dd6372d6ec9c8f24337841dd74634fb69864ae/pymdown_extensions-10.4-py3-none-any.whl", hash = "sha256:cfc28d6a09d19448bcbf8eee3ce098c7d17ff99f7bd3069db4819af181212037", size = 240838 }, +] + +[[package]] +name = "python-dateutil" +version = "2.9.0.post0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "six" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892 }, +] + +[[package]] +name = "python-github-api" +version = "0.1.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "requests" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/8f/3b/e2871bb5c6e57f01c5585b511a87cdfcb59a7794b0ac6044e553b2d82723/python_github_api-0.1.1.zip", hash = "sha256:9811fc4742ebddfdccde8b11226b5c5e3b9524cfc838143caab85bc8f1513e61", size = 16450 } + +[[package]] +name = "python-markdown-math" +version = "0.8" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markdown" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ec/17/e7e3f3fce951b8adec10987834f4b2fa721ebd9bd6651ce2a4f39c4c544d/python-markdown-math-0.8.tar.gz", hash = "sha256:8564212af679fc18d53f38681f16080fcd3d186073f23825c7ce86fadd3e3635", size = 8509 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4d/36/d16118345ff5f503d4d1c708e8427ed2213f2af7aaffac9d59010e665b5c/python_markdown_math-0.8-py3-none-any.whl", hash = "sha256:c685249d84b5b697e9114d7beb352bd8ca2e07fd268fd4057ffca888c14641e5", size = 5858 }, +] + +[[package]] +name = "pytz" +version = "2024.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/3a/31/3c70bf7603cc2dca0f19bdc53b4537a797747a58875b552c8c413d963a3f/pytz-2024.2.tar.gz", hash = "sha256:2aa355083c50a0f93fa581709deac0c9ad65cca8a9e9beac660adcbd493c798a", size = 319692 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/11/c3/005fcca25ce078d2cc29fd559379817424e94885510568bc1bc53d7d5846/pytz-2024.2-py2.py3-none-any.whl", hash = "sha256:31c7c1817eb7fae7ca4b8c7ee50c72f93aa2dd863de768e1ef4245d426aa0725", size = 508002 }, +] + +[[package]] +name = "pyyaml" +version = "6.0.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/54/ed/79a089b6be93607fa5cdaedf301d7dfb23af5f25c398d5ead2525b063e17/pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e", size = 130631 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9b/95/a3fac87cb7158e231b5a6012e438c647e1a87f09f8e0d123acec8ab8bf71/PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086", size = 184199 }, + { url = "https://files.pythonhosted.org/packages/c7/7a/68bd47624dab8fd4afbfd3c48e3b79efe09098ae941de5b58abcbadff5cb/PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf", size = 171758 }, + { url = "https://files.pythonhosted.org/packages/49/ee/14c54df452143b9ee9f0f29074d7ca5516a36edb0b4cc40c3f280131656f/PyYAML-6.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237", size = 718463 }, + { url = "https://files.pythonhosted.org/packages/4d/61/de363a97476e766574650d742205be468921a7b532aa2499fcd886b62530/PyYAML-6.0.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b", size = 719280 }, + { url = "https://files.pythonhosted.org/packages/6b/4e/1523cb902fd98355e2e9ea5e5eb237cbc5f3ad5f3075fa65087aa0ecb669/PyYAML-6.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed", size = 751239 }, + { url = "https://files.pythonhosted.org/packages/b7/33/5504b3a9a4464893c32f118a9cc045190a91637b119a9c881da1cf6b7a72/PyYAML-6.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180", size = 695802 }, + { url = "https://files.pythonhosted.org/packages/5c/20/8347dcabd41ef3a3cdc4f7b7a2aff3d06598c8779faa189cdbf878b626a4/PyYAML-6.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68", size = 720527 }, + { url = "https://files.pythonhosted.org/packages/be/aa/5afe99233fb360d0ff37377145a949ae258aaab831bde4792b32650a4378/PyYAML-6.0.2-cp310-cp310-win32.whl", hash = "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99", size = 144052 }, + { url = "https://files.pythonhosted.org/packages/b5/84/0fa4b06f6d6c958d207620fc60005e241ecedceee58931bb20138e1e5776/PyYAML-6.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e", size = 161774 }, + { url = "https://files.pythonhosted.org/packages/f8/aa/7af4e81f7acba21a4c6be026da38fd2b872ca46226673c89a758ebdc4fd2/PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774", size = 184612 }, + { url = "https://files.pythonhosted.org/packages/8b/62/b9faa998fd185f65c1371643678e4d58254add437edb764a08c5a98fb986/PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee", size = 172040 }, + { url = "https://files.pythonhosted.org/packages/ad/0c/c804f5f922a9a6563bab712d8dcc70251e8af811fce4524d57c2c0fd49a4/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c", size = 736829 }, + { url = "https://files.pythonhosted.org/packages/51/16/6af8d6a6b210c8e54f1406a6b9481febf9c64a3109c541567e35a49aa2e7/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317", size = 764167 }, + { url = "https://files.pythonhosted.org/packages/75/e4/2c27590dfc9992f73aabbeb9241ae20220bd9452df27483b6e56d3975cc5/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85", size = 762952 }, + { url = "https://files.pythonhosted.org/packages/9b/97/ecc1abf4a823f5ac61941a9c00fe501b02ac3ab0e373c3857f7d4b83e2b6/PyYAML-6.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4", size = 735301 }, + { url = "https://files.pythonhosted.org/packages/45/73/0f49dacd6e82c9430e46f4a027baa4ca205e8b0a9dce1397f44edc23559d/PyYAML-6.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e", size = 756638 }, + { url = "https://files.pythonhosted.org/packages/22/5f/956f0f9fc65223a58fbc14459bf34b4cc48dec52e00535c79b8db361aabd/PyYAML-6.0.2-cp311-cp311-win32.whl", hash = "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5", size = 143850 }, + { url = "https://files.pythonhosted.org/packages/ed/23/8da0bbe2ab9dcdd11f4f4557ccaf95c10b9811b13ecced089d43ce59c3c8/PyYAML-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44", size = 161980 }, + { url = "https://files.pythonhosted.org/packages/86/0c/c581167fc46d6d6d7ddcfb8c843a4de25bdd27e4466938109ca68492292c/PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab", size = 183873 }, + { url = "https://files.pythonhosted.org/packages/a8/0c/38374f5bb272c051e2a69281d71cba6fdb983413e6758b84482905e29a5d/PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725", size = 173302 }, + { url = "https://files.pythonhosted.org/packages/c3/93/9916574aa8c00aa06bbac729972eb1071d002b8e158bd0e83a3b9a20a1f7/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5", size = 739154 }, + { url = "https://files.pythonhosted.org/packages/95/0f/b8938f1cbd09739c6da569d172531567dbcc9789e0029aa070856f123984/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425", size = 766223 }, + { url = "https://files.pythonhosted.org/packages/b9/2b/614b4752f2e127db5cc206abc23a8c19678e92b23c3db30fc86ab731d3bd/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476", size = 767542 }, + { url = "https://files.pythonhosted.org/packages/d4/00/dd137d5bcc7efea1836d6264f049359861cf548469d18da90cd8216cf05f/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48", size = 731164 }, + { url = "https://files.pythonhosted.org/packages/c9/1f/4f998c900485e5c0ef43838363ba4a9723ac0ad73a9dc42068b12aaba4e4/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b", size = 756611 }, + { url = "https://files.pythonhosted.org/packages/df/d1/f5a275fdb252768b7a11ec63585bc38d0e87c9e05668a139fea92b80634c/PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4", size = 140591 }, + { url = "https://files.pythonhosted.org/packages/0c/e8/4f648c598b17c3d06e8753d7d13d57542b30d56e6c2dedf9c331ae56312e/PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8", size = 156338 }, + { url = "https://files.pythonhosted.org/packages/ef/e3/3af305b830494fa85d95f6d95ef7fa73f2ee1cc8ef5b495c7c3269fb835f/PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba", size = 181309 }, + { url = "https://files.pythonhosted.org/packages/45/9f/3b1c20a0b7a3200524eb0076cc027a970d320bd3a6592873c85c92a08731/PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1", size = 171679 }, + { url = "https://files.pythonhosted.org/packages/7c/9a/337322f27005c33bcb656c655fa78325b730324c78620e8328ae28b64d0c/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133", size = 733428 }, + { url = "https://files.pythonhosted.org/packages/a3/69/864fbe19e6c18ea3cc196cbe5d392175b4cf3d5d0ac1403ec3f2d237ebb5/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484", size = 763361 }, + { url = "https://files.pythonhosted.org/packages/04/24/b7721e4845c2f162d26f50521b825fb061bc0a5afcf9a386840f23ea19fa/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5", size = 759523 }, + { url = "https://files.pythonhosted.org/packages/2b/b2/e3234f59ba06559c6ff63c4e10baea10e5e7df868092bf9ab40e5b9c56b6/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc", size = 726660 }, + { url = "https://files.pythonhosted.org/packages/fe/0f/25911a9f080464c59fab9027482f822b86bf0608957a5fcc6eaac85aa515/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652", size = 751597 }, + { url = "https://files.pythonhosted.org/packages/14/0d/e2c3b43bbce3cf6bd97c840b46088a3031085179e596d4929729d8d68270/PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183", size = 140527 }, + { url = "https://files.pythonhosted.org/packages/fa/de/02b54f42487e3d3c6efb3f89428677074ca7bf43aae402517bc7cca949f3/PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563", size = 156446 }, +] + +[[package]] +name = "pyyaml-env-tag" +version = "0.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pyyaml" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/fb/8e/da1c6c58f751b70f8ceb1eb25bc25d524e8f14fe16edcce3f4e3ba08629c/pyyaml_env_tag-0.1.tar.gz", hash = "sha256:70092675bda14fdec33b31ba77e7543de9ddc88f2e5b99160396572d11525bdb", size = 5631 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5a/66/bbb1dd374f5c870f59c5bb1db0e18cbe7fa739415a24cbd95b2d1f5ae0c4/pyyaml_env_tag-0.1-py3-none-any.whl", hash = "sha256:af31106dec8a4d68c60207c1886031cbf839b68aa7abccdb19868200532c2069", size = 3911 }, +] + +[[package]] +name = "regex" +version = "2024.9.11" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f9/38/148df33b4dbca3bd069b963acab5e0fa1a9dbd6820f8c322d0dd6faeff96/regex-2024.9.11.tar.gz", hash = "sha256:6c188c307e8433bcb63dc1915022deb553b4203a70722fc542c363bf120a01fd", size = 399403 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/63/12/497bd6599ce8a239ade68678132296aec5ee25ebea45fc8ba91aa60fceec/regex-2024.9.11-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:1494fa8725c285a81d01dc8c06b55287a1ee5e0e382d8413adc0a9197aac6408", size = 482488 }, + { url = "https://files.pythonhosted.org/packages/c1/24/595ddb9bec2a9b151cdaf9565b0c9f3da9f0cb1dca6c158bc5175332ddf8/regex-2024.9.11-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0e12c481ad92d129c78f13a2a3662317e46ee7ef96c94fd332e1c29131875b7d", size = 287443 }, + { url = "https://files.pythonhosted.org/packages/69/a8/b2fb45d9715b1469383a0da7968f8cacc2f83e9fbbcd6b8713752dd980a6/regex-2024.9.11-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:16e13a7929791ac1216afde26f712802e3df7bf0360b32e4914dca3ab8baeea5", size = 284561 }, + { url = "https://files.pythonhosted.org/packages/88/87/1ce4a5357216b19b7055e7d3b0efc75a6e426133bf1e7d094321df514257/regex-2024.9.11-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:46989629904bad940bbec2106528140a218b4a36bb3042d8406980be1941429c", size = 783177 }, + { url = "https://files.pythonhosted.org/packages/3c/65/b9f002ab32f7b68e7d1dcabb67926f3f47325b8dbc22cc50b6a043e1d07c/regex-2024.9.11-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a906ed5e47a0ce5f04b2c981af1c9acf9e8696066900bf03b9d7879a6f679fc8", size = 823193 }, + { url = "https://files.pythonhosted.org/packages/22/91/8339dd3abce101204d246e31bc26cdd7ec07c9f91598472459a3a902aa41/regex-2024.9.11-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e9a091b0550b3b0207784a7d6d0f1a00d1d1c8a11699c1a4d93db3fbefc3ad35", size = 809950 }, + { url = "https://files.pythonhosted.org/packages/cb/19/556638aa11c2ec9968a1da998f07f27ec0abb9bf3c647d7c7985ca0b8eea/regex-2024.9.11-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ddcd9a179c0a6fa8add279a4444015acddcd7f232a49071ae57fa6e278f1f71", size = 782661 }, + { url = "https://files.pythonhosted.org/packages/d1/e9/7a5bc4c6ef8d9cd2bdd83a667888fc35320da96a4cc4da5fa084330f53db/regex-2024.9.11-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6b41e1adc61fa347662b09398e31ad446afadff932a24807d3ceb955ed865cc8", size = 772348 }, + { url = "https://files.pythonhosted.org/packages/f1/0b/29f2105bfac3ed08e704914c38e93b07c784a6655f8a015297ee7173e95b/regex-2024.9.11-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ced479f601cd2f8ca1fd7b23925a7e0ad512a56d6e9476f79b8f381d9d37090a", size = 697460 }, + { url = "https://files.pythonhosted.org/packages/71/3a/52ff61054d15a4722605f5872ad03962b319a04c1ebaebe570b8b9b7dde1/regex-2024.9.11-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:635a1d96665f84b292e401c3d62775851aedc31d4f8784117b3c68c4fcd4118d", size = 769151 }, + { url = "https://files.pythonhosted.org/packages/97/07/37e460ab5ca84be8e1e197c3b526c5c86993dcc9e13cbc805c35fc2463c1/regex-2024.9.11-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:c0256beda696edcf7d97ef16b2a33a8e5a875affd6fa6567b54f7c577b30a137", size = 777478 }, + { url = "https://files.pythonhosted.org/packages/65/7b/953075723dd5ab00780043ac2f9de667306ff9e2a85332975e9f19279174/regex-2024.9.11-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:3ce4f1185db3fbde8ed8aa223fc9620f276c58de8b0d4f8cc86fd1360829edb6", size = 845373 }, + { url = "https://files.pythonhosted.org/packages/40/b8/3e9484c6230b8b6e8f816ab7c9a080e631124991a4ae2c27a81631777db0/regex-2024.9.11-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:09d77559e80dcc9d24570da3745ab859a9cf91953062e4ab126ba9d5993688ca", size = 845369 }, + { url = "https://files.pythonhosted.org/packages/b7/99/38434984d912edbd2e1969d116257e869578f67461bd7462b894c45ed874/regex-2024.9.11-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7a22ccefd4db3f12b526eccb129390942fe874a3a9fdbdd24cf55773a1faab1a", size = 773935 }, + { url = "https://files.pythonhosted.org/packages/ab/67/43174d2b46fa947b7b9dfe56b6c8a8a76d44223f35b1d64645a732fd1d6f/regex-2024.9.11-cp310-cp310-win32.whl", hash = "sha256:f745ec09bc1b0bd15cfc73df6fa4f726dcc26bb16c23a03f9e3367d357eeedd0", size = 261624 }, + { url = "https://files.pythonhosted.org/packages/c4/2a/4f9c47d9395b6aff24874c761d8d620c0232f97c43ef3cf668c8b355e7a7/regex-2024.9.11-cp310-cp310-win_amd64.whl", hash = "sha256:01c2acb51f8a7d6494c8c5eafe3d8e06d76563d8a8a4643b37e9b2dd8a2ff623", size = 274020 }, + { url = "https://files.pythonhosted.org/packages/86/a1/d526b7b6095a0019aa360948c143aacfeb029919c898701ce7763bbe4c15/regex-2024.9.11-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:2cce2449e5927a0bf084d346da6cd5eb016b2beca10d0013ab50e3c226ffc0df", size = 482483 }, + { url = "https://files.pythonhosted.org/packages/32/d9/bfdd153179867c275719e381e1e8e84a97bd186740456a0dcb3e7125c205/regex-2024.9.11-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3b37fa423beefa44919e009745ccbf353d8c981516e807995b2bd11c2c77d268", size = 287442 }, + { url = "https://files.pythonhosted.org/packages/33/c4/60f3370735135e3a8d673ddcdb2507a8560d0e759e1398d366e43d000253/regex-2024.9.11-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:64ce2799bd75039b480cc0360907c4fb2f50022f030bf9e7a8705b636e408fad", size = 284561 }, + { url = "https://files.pythonhosted.org/packages/b1/51/91a5ebdff17f9ec4973cb0aa9d37635efec1c6868654bbc25d1543aca4ec/regex-2024.9.11-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a4cc92bb6db56ab0c1cbd17294e14f5e9224f0cc6521167ef388332604e92679", size = 791779 }, + { url = "https://files.pythonhosted.org/packages/07/4a/022c5e6f0891a90cd7eb3d664d6c58ce2aba48bff107b00013f3d6167069/regex-2024.9.11-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d05ac6fa06959c4172eccd99a222e1fbf17b5670c4d596cb1e5cde99600674c4", size = 832605 }, + { url = "https://files.pythonhosted.org/packages/ac/1c/3793990c8c83ca04e018151ddda83b83ecc41d89964f0f17749f027fc44d/regex-2024.9.11-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:040562757795eeea356394a7fb13076ad4f99d3c62ab0f8bdfb21f99a1f85664", size = 818556 }, + { url = "https://files.pythonhosted.org/packages/e9/5c/8b385afbfacb853730682c57be56225f9fe275c5bf02ac1fc88edbff316d/regex-2024.9.11-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6113c008a7780792efc80f9dfe10ba0cd043cbf8dc9a76ef757850f51b4edc50", size = 792808 }, + { url = "https://files.pythonhosted.org/packages/9b/8b/a4723a838b53c771e9240951adde6af58c829fb6a6a28f554e8131f53839/regex-2024.9.11-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8e5fb5f77c8745a60105403a774fe2c1759b71d3e7b4ca237a5e67ad066c7199", size = 781115 }, + { url = "https://files.pythonhosted.org/packages/83/5f/031a04b6017033d65b261259c09043c06f4ef2d4eac841d0649d76d69541/regex-2024.9.11-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:54d9ff35d4515debf14bc27f1e3b38bfc453eff3220f5bce159642fa762fe5d4", size = 778155 }, + { url = "https://files.pythonhosted.org/packages/fd/cd/4660756070b03ce4a66663a43f6c6e7ebc2266cc6b4c586c167917185eb4/regex-2024.9.11-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:df5cbb1fbc74a8305b6065d4ade43b993be03dbe0f8b30032cced0d7740994bd", size = 784614 }, + { url = "https://files.pythonhosted.org/packages/93/8d/65b9bea7df120a7be8337c415b6d256ba786cbc9107cebba3bf8ff09da99/regex-2024.9.11-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:7fb89ee5d106e4a7a51bce305ac4efb981536301895f7bdcf93ec92ae0d91c7f", size = 853744 }, + { url = "https://files.pythonhosted.org/packages/96/a7/fba1eae75eb53a704475baf11bd44b3e6ccb95b316955027eb7748f24ef8/regex-2024.9.11-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:a738b937d512b30bf75995c0159c0ddf9eec0775c9d72ac0202076c72f24aa96", size = 855890 }, + { url = "https://files.pythonhosted.org/packages/45/14/d864b2db80a1a3358534392373e8a281d95b28c29c87d8548aed58813910/regex-2024.9.11-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e28f9faeb14b6f23ac55bfbbfd3643f5c7c18ede093977f1df249f73fd22c7b1", size = 781887 }, + { url = "https://files.pythonhosted.org/packages/4d/a9/bfb29b3de3eb11dc9b412603437023b8e6c02fb4e11311863d9bf62c403a/regex-2024.9.11-cp311-cp311-win32.whl", hash = "sha256:18e707ce6c92d7282dfce370cd205098384b8ee21544e7cb29b8aab955b66fa9", size = 261644 }, + { url = "https://files.pythonhosted.org/packages/c7/ab/1ad2511cf6a208fde57fafe49829cab8ca018128ab0d0b48973d8218634a/regex-2024.9.11-cp311-cp311-win_amd64.whl", hash = "sha256:313ea15e5ff2a8cbbad96ccef6be638393041b0a7863183c2d31e0c6116688cf", size = 274033 }, + { url = "https://files.pythonhosted.org/packages/6e/92/407531450762bed778eedbde04407f68cbd75d13cee96c6f8d6903d9c6c1/regex-2024.9.11-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:b0d0a6c64fcc4ef9c69bd5b3b3626cc3776520a1637d8abaa62b9edc147a58f7", size = 483590 }, + { url = "https://files.pythonhosted.org/packages/8e/a2/048acbc5ae1f615adc6cba36cc45734e679b5f1e4e58c3c77f0ed611d4e2/regex-2024.9.11-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:49b0e06786ea663f933f3710a51e9385ce0cba0ea56b67107fd841a55d56a231", size = 288175 }, + { url = "https://files.pythonhosted.org/packages/8a/ea/909d8620329ab710dfaf7b4adee41242ab7c9b95ea8d838e9bfe76244259/regex-2024.9.11-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5b513b6997a0b2f10e4fd3a1313568e373926e8c252bd76c960f96fd039cd28d", size = 284749 }, + { url = "https://files.pythonhosted.org/packages/ca/fa/521eb683b916389b4975337873e66954e0f6d8f91bd5774164a57b503185/regex-2024.9.11-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ee439691d8c23e76f9802c42a95cfeebf9d47cf4ffd06f18489122dbb0a7ad64", size = 795181 }, + { url = "https://files.pythonhosted.org/packages/28/db/63047feddc3280cc242f9c74f7aeddc6ee662b1835f00046f57d5630c827/regex-2024.9.11-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a8f877c89719d759e52783f7fe6e1c67121076b87b40542966c02de5503ace42", size = 835842 }, + { url = "https://files.pythonhosted.org/packages/e3/94/86adc259ff8ec26edf35fcca7e334566c1805c7493b192cb09679f9c3dee/regex-2024.9.11-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:23b30c62d0f16827f2ae9f2bb87619bc4fba2044911e2e6c2eb1af0161cdb766", size = 823533 }, + { url = "https://files.pythonhosted.org/packages/29/52/84662b6636061277cb857f658518aa7db6672bc6d1a3f503ccd5aefc581e/regex-2024.9.11-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85ab7824093d8f10d44330fe1e6493f756f252d145323dd17ab6b48733ff6c0a", size = 797037 }, + { url = "https://files.pythonhosted.org/packages/c3/2a/cd4675dd987e4a7505f0364a958bc41f3b84942de9efaad0ef9a2646681c/regex-2024.9.11-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8dee5b4810a89447151999428fe096977346cf2f29f4d5e29609d2e19e0199c9", size = 784106 }, + { url = "https://files.pythonhosted.org/packages/6f/75/3ea7ec29de0bbf42f21f812f48781d41e627d57a634f3f23947c9a46e303/regex-2024.9.11-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:98eeee2f2e63edae2181c886d7911ce502e1292794f4c5ee71e60e23e8d26b5d", size = 782468 }, + { url = "https://files.pythonhosted.org/packages/d3/67/15519d69b52c252b270e679cb578e22e0c02b8dd4e361f2b04efcc7f2335/regex-2024.9.11-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:57fdd2e0b2694ce6fc2e5ccf189789c3e2962916fb38779d3e3521ff8fe7a822", size = 790324 }, + { url = "https://files.pythonhosted.org/packages/9c/71/eff77d3fe7ba08ab0672920059ec30d63fa7e41aa0fb61c562726e9bd721/regex-2024.9.11-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:d552c78411f60b1fdaafd117a1fca2f02e562e309223b9d44b7de8be451ec5e0", size = 860214 }, + { url = "https://files.pythonhosted.org/packages/81/11/e1bdf84a72372e56f1ea4b833dd583b822a23138a616ace7ab57a0e11556/regex-2024.9.11-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:a0b2b80321c2ed3fcf0385ec9e51a12253c50f146fddb2abbb10f033fe3d049a", size = 859420 }, + { url = "https://files.pythonhosted.org/packages/ea/75/9753e9dcebfa7c3645563ef5c8a58f3a47e799c872165f37c55737dadd3e/regex-2024.9.11-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:18406efb2f5a0e57e3a5881cd9354c1512d3bb4f5c45d96d110a66114d84d23a", size = 787333 }, + { url = "https://files.pythonhosted.org/packages/bc/4e/ba1cbca93141f7416624b3ae63573e785d4bc1834c8be44a8f0747919eca/regex-2024.9.11-cp312-cp312-win32.whl", hash = "sha256:e464b467f1588e2c42d26814231edecbcfe77f5ac414d92cbf4e7b55b2c2a776", size = 262058 }, + { url = "https://files.pythonhosted.org/packages/6e/16/efc5f194778bf43e5888209e5cec4b258005d37c613b67ae137df3b89c53/regex-2024.9.11-cp312-cp312-win_amd64.whl", hash = "sha256:9e8719792ca63c6b8340380352c24dcb8cd7ec49dae36e963742a275dfae6009", size = 273526 }, + { url = "https://files.pythonhosted.org/packages/93/0a/d1c6b9af1ff1e36832fe38d74d5c5bab913f2bdcbbd6bc0e7f3ce8b2f577/regex-2024.9.11-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:c157bb447303070f256e084668b702073db99bbb61d44f85d811025fcf38f784", size = 483376 }, + { url = "https://files.pythonhosted.org/packages/a4/42/5910a050c105d7f750a72dcb49c30220c3ae4e2654e54aaaa0e9bc0584cb/regex-2024.9.11-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4db21ece84dfeefc5d8a3863f101995de646c6cb0536952c321a2650aa202c36", size = 288112 }, + { url = "https://files.pythonhosted.org/packages/8d/56/0c262aff0e9224fa7ffce47b5458d373f4d3e3ff84e99b5ff0cb15e0b5b2/regex-2024.9.11-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:220e92a30b426daf23bb67a7962900ed4613589bab80382be09b48896d211e92", size = 284608 }, + { url = "https://files.pythonhosted.org/packages/b9/54/9fe8f9aec5007bbbbce28ba3d2e3eaca425f95387b7d1e84f0d137d25237/regex-2024.9.11-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eb1ae19e64c14c7ec1995f40bd932448713d3c73509e82d8cd7744dc00e29e86", size = 795337 }, + { url = "https://files.pythonhosted.org/packages/b2/e7/6b2f642c3cded271c4f16cc4daa7231be544d30fe2b168e0223724b49a61/regex-2024.9.11-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f47cd43a5bfa48f86925fe26fbdd0a488ff15b62468abb5d2a1e092a4fb10e85", size = 835848 }, + { url = "https://files.pythonhosted.org/packages/cd/9e/187363bdf5d8c0e4662117b92aa32bf52f8f09620ae93abc7537d96d3311/regex-2024.9.11-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9d4a76b96f398697fe01117093613166e6aa8195d63f1b4ec3f21ab637632963", size = 823503 }, + { url = "https://files.pythonhosted.org/packages/f8/10/601303b8ee93589f879664b0cfd3127949ff32b17f9b6c490fb201106c4d/regex-2024.9.11-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ea51dcc0835eea2ea31d66456210a4e01a076d820e9039b04ae8d17ac11dee6", size = 797049 }, + { url = "https://files.pythonhosted.org/packages/ef/1c/ea200f61ce9f341763f2717ab4daebe4422d83e9fd4ac5e33435fd3a148d/regex-2024.9.11-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b7aaa315101c6567a9a45d2839322c51c8d6e81f67683d529512f5bcfb99c802", size = 784144 }, + { url = "https://files.pythonhosted.org/packages/d8/5c/d2429be49ef3292def7688401d3deb11702c13dcaecdc71d2b407421275b/regex-2024.9.11-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:c57d08ad67aba97af57a7263c2d9006d5c404d721c5f7542f077f109ec2a4a29", size = 782483 }, + { url = "https://files.pythonhosted.org/packages/12/d9/cbc30f2ff7164f3b26a7760f87c54bf8b2faed286f60efd80350a51c5b99/regex-2024.9.11-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:f8404bf61298bb6f8224bb9176c1424548ee1181130818fcd2cbffddc768bed8", size = 790320 }, + { url = "https://files.pythonhosted.org/packages/19/1d/43ed03a236313639da5a45e61bc553c8d41e925bcf29b0f8ecff0c2c3f25/regex-2024.9.11-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:dd4490a33eb909ef5078ab20f5f000087afa2a4daa27b4c072ccb3cb3050ad84", size = 860435 }, + { url = "https://files.pythonhosted.org/packages/34/4f/5d04da61c7c56e785058a46349f7285ae3ebc0726c6ea7c5c70600a52233/regex-2024.9.11-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:eee9130eaad130649fd73e5cd92f60e55708952260ede70da64de420cdcad554", size = 859571 }, + { url = "https://files.pythonhosted.org/packages/12/7f/8398c8155a3c70703a8e91c29532558186558e1aea44144b382faa2a6f7a/regex-2024.9.11-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6a2644a93da36c784e546de579ec1806bfd2763ef47babc1b03d765fe560c9f8", size = 787398 }, + { url = "https://files.pythonhosted.org/packages/58/3a/f5903977647a9a7e46d5535e9e96c194304aeeca7501240509bde2f9e17f/regex-2024.9.11-cp313-cp313-win32.whl", hash = "sha256:e997fd30430c57138adc06bba4c7c2968fb13d101e57dd5bb9355bf8ce3fa7e8", size = 262035 }, + { url = "https://files.pythonhosted.org/packages/ff/80/51ba3a4b7482f6011095b3a036e07374f64de180b7d870b704ed22509002/regex-2024.9.11-cp313-cp313-win_amd64.whl", hash = "sha256:042c55879cfeb21a8adacc84ea347721d3d83a159da6acdf1116859e2427c43f", size = 273510 }, +] + +[[package]] +name = "requests" +version = "2.32.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "charset-normalizer" }, + { name = "idna" }, + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/63/70/2bf7780ad2d390a8d301ad0b550f1581eadbd9a20f896afe06353c2a2913/requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760", size = 131218 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f9/9b/335f9764261e915ed497fcdeb11df5dfd6f7bf257d4a6a2a686d80da4d54/requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6", size = 64928 }, +] + +[[package]] +name = "setuptools" +version = "75.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/27/b8/f21073fde99492b33ca357876430822e4800cdf522011f18041351dfa74b/setuptools-75.1.0.tar.gz", hash = "sha256:d59a21b17a275fb872a9c3dae73963160ae079f1049ed956880cd7c09b120538", size = 1348057 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ff/ae/f19306b5a221f6a436d8f2238d5b80925004093fa3edea59835b514d9057/setuptools-75.1.0-py3-none-any.whl", hash = "sha256:35ab7fd3bcd95e6b7fd704e4a1539513edad446c097797f2985e0e4b960772f2", size = 1248506 }, +] + +[[package]] +name = "six" +version = "1.16.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/71/39/171f1c67cd00715f190ba0b100d606d440a28c93c7714febeca8b79af85e/six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926", size = 34041 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254", size = 11053 }, +] + +[[package]] +name = "soupsieve" +version = "2.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d7/ce/fbaeed4f9fb8b2daa961f90591662df6a86c1abf25c548329a86920aedfb/soupsieve-2.6.tar.gz", hash = "sha256:e2e68417777af359ec65daac1057404a3c8a5455bb8abc36f1a9866ab1a51abb", size = 101569 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/c2/fe97d779f3ef3b15f05c94a2f1e3d21732574ed441687474db9d342a7315/soupsieve-2.6-py3-none-any.whl", hash = "sha256:e72c4ff06e4fb6e4b5a9f0f55fe6e81514581fca1515028625d0f299c602ccc9", size = 36186 }, +] + +[[package]] +name = "tabulate" +version = "0.9.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ec/fe/802052aecb21e3797b8f7902564ab6ea0d60ff8ca23952079064155d1ae1/tabulate-0.9.0.tar.gz", hash = "sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c", size = 81090 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/40/44/4a5f08c96eb108af5cb50b41f76142f0afa346dfa99d5296fe7202a11854/tabulate-0.9.0-py3-none-any.whl", hash = "sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f", size = 35252 }, +] + +[[package]] +name = "tzdata" +version = "2024.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e1/34/943888654477a574a86a98e9896bae89c7aa15078ec29f490fef2f1e5384/tzdata-2024.2.tar.gz", hash = "sha256:7d85cc416e9382e69095b7bdf4afd9e3880418a2413feec7069d533d6b4e31cc", size = 193282 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a6/ab/7e5f53c3b9d14972843a647d8d7a853969a58aecc7559cb3267302c94774/tzdata-2024.2-py2.py3-none-any.whl", hash = "sha256:a48093786cdcde33cad18c2555e8532f34422074448fbc874186f0abd79565cd", size = 346586 }, +] + +[[package]] +name = "urllib3" +version = "2.2.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ed/63/22ba4ebfe7430b76388e7cd448d5478814d3032121827c12a2cc287e2260/urllib3-2.2.3.tar.gz", hash = "sha256:e7d814a81dad81e6caf2ec9fdedb284ecc9c73076b62654547cc64ccdcae26e9", size = 300677 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ce/d9/5f4c13cecde62396b0d3fe530a50ccea91e7dfc1ccf0e09c228841bb5ba8/urllib3-2.2.3-py3-none-any.whl", hash = "sha256:ca899ca043dcb1bafa3e262d73aa25c465bfb49e0bd9dd5d59f1d0acba2f8fac", size = 126338 }, +] + +[[package]] +name = "watchdog" +version = "5.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a2/48/a86139aaeab2db0a2482676f64798d8ac4d2dbb457523f50ab37bf02ce2c/watchdog-5.0.3.tar.gz", hash = "sha256:108f42a7f0345042a854d4d0ad0834b741d421330d5f575b81cb27b883500176", size = 129556 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/05/2b/dd2081aab6fc9e785c2eee7146d3c6de58e607f4e70049d715cd170cbf77/watchdog-5.0.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:85527b882f3facda0579bce9d743ff7f10c3e1e0db0a0d0e28170a7d0e5ce2ea", size = 96652 }, + { url = "https://files.pythonhosted.org/packages/9e/4f/f643c0a720d16ef7316aea06a79b96e229e59df4e0d83bec5e12713c1f29/watchdog-5.0.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:53adf73dcdc0ef04f7735066b4a57a4cd3e49ef135daae41d77395f0b5b692cb", size = 88651 }, + { url = "https://files.pythonhosted.org/packages/2b/72/acb22067d1f18161914c9b1087c703d63638131a9fde78090da290663407/watchdog-5.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e25adddab85f674acac303cf1f5835951345a56c5f7f582987d266679979c75b", size = 89289 }, + { url = "https://files.pythonhosted.org/packages/70/34/946f08602f8b8e6af45bc725e4a8013975a34883ab5570bd0d827a4c9829/watchdog-5.0.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f01f4a3565a387080dc49bdd1fefe4ecc77f894991b88ef927edbfa45eb10818", size = 96650 }, + { url = "https://files.pythonhosted.org/packages/96/2b/b84e35d49e8b0bad77e5d086fc1e2c6c833bbfe74d53144cfe8b26117eff/watchdog-5.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:91b522adc25614cdeaf91f7897800b82c13b4b8ac68a42ca959f992f6990c490", size = 88653 }, + { url = "https://files.pythonhosted.org/packages/d5/3f/41b5d77c10f450b79921c17b7d0b416616048867bfe63acaa072a619a0cb/watchdog-5.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d52db5beb5e476e6853da2e2d24dbbbed6797b449c8bf7ea118a4ee0d2c9040e", size = 89286 }, + { url = "https://files.pythonhosted.org/packages/1c/9b/8b206a928c188fdeb7b12e1c795199534cd44bdef223b8470129016009dd/watchdog-5.0.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:94d11b07c64f63f49876e0ab8042ae034674c8653bfcdaa8c4b32e71cfff87e8", size = 96739 }, + { url = "https://files.pythonhosted.org/packages/e1/26/129ca9cd0f8016672f37000010c2fedc0b86816e894ebdc0af9bb04a6439/watchdog-5.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:349c9488e1d85d0a58e8cb14222d2c51cbc801ce11ac3936ab4c3af986536926", size = 88708 }, + { url = "https://files.pythonhosted.org/packages/8f/b3/5e10ec32f0c429cdb55b1369066d6e83faf9985b3a53a4e37bb5c5e29aa0/watchdog-5.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:53a3f10b62c2d569e260f96e8d966463dec1a50fa4f1b22aec69e3f91025060e", size = 89309 }, + { url = "https://files.pythonhosted.org/packages/54/c4/49af4ab00bcfb688e9962eace2edda07a2cf89b9699ea536da48e8585cff/watchdog-5.0.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:950f531ec6e03696a2414b6308f5c6ff9dab7821a768c9d5788b1314e9a46ca7", size = 96740 }, + { url = "https://files.pythonhosted.org/packages/96/a4/b24de77cc9ae424c1687c9d4fb15aa560d7d7b28ba559aca72f781d0202b/watchdog-5.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ae6deb336cba5d71476caa029ceb6e88047fc1dc74b62b7c4012639c0b563906", size = 88711 }, + { url = "https://files.pythonhosted.org/packages/a4/71/3f2e9fe8403386b99d788868955b3a790f7a09721501a7e1eb58f514ffaa/watchdog-5.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1021223c08ba8d2d38d71ec1704496471ffd7be42cfb26b87cd5059323a389a1", size = 89319 }, + { url = "https://files.pythonhosted.org/packages/a2/d6/1d1ca81c75d903eca3fdb7061d93845485b58a5ba182d146843b88fc51c2/watchdog-5.0.3-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:90a67d7857adb1d985aca232cc9905dd5bc4803ed85cfcdcfcf707e52049eda7", size = 88172 }, + { url = "https://files.pythonhosted.org/packages/47/bb/d5e0abcfd6d729029a24766682e062526db8b59e9ae0c94aff509e0fd2b9/watchdog-5.0.3-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:720ef9d3a4f9ca575a780af283c8fd3a0674b307651c1976714745090da5a9e8", size = 88644 }, + { url = "https://files.pythonhosted.org/packages/60/33/7cb71c9df9a77b6927ee5f48d25e1de5562ce0fa7e0c56dcf2b0472e64a2/watchdog-5.0.3-py3-none-manylinux2014_aarch64.whl", hash = "sha256:dd021efa85970bd4824acacbb922066159d0f9e546389a4743d56919b6758b91", size = 79335 }, + { url = "https://files.pythonhosted.org/packages/f6/91/320bc1496cf951a3cf93a7ffd18a581f0792c304be963d943e0e608c2919/watchdog-5.0.3-py3-none-manylinux2014_armv7l.whl", hash = "sha256:78864cc8f23dbee55be34cc1494632a7ba30263951b5b2e8fc8286b95845f82c", size = 79334 }, + { url = "https://files.pythonhosted.org/packages/8b/2c/567c5e042ed667d3544c43d48a65cf853450a2d2a9089d9523a65f195e94/watchdog-5.0.3-py3-none-manylinux2014_i686.whl", hash = "sha256:1e9679245e3ea6498494b3028b90c7b25dbb2abe65c7d07423ecfc2d6218ff7c", size = 79333 }, + { url = "https://files.pythonhosted.org/packages/c3/f0/64059fe162ef3274662e67bbdea6c45b3cd53e846d5bd1365fcdc3dc1d15/watchdog-5.0.3-py3-none-manylinux2014_ppc64.whl", hash = "sha256:9413384f26b5d050b6978e6fcd0c1e7f0539be7a4f1a885061473c5deaa57221", size = 79334 }, + { url = "https://files.pythonhosted.org/packages/f6/d9/19b7d02965be2801e2d0f6f4bde23e4ae172620071b65430fa0c2f8441ac/watchdog-5.0.3-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:294b7a598974b8e2c6123d19ef15de9abcd282b0fbbdbc4d23dfa812959a9e05", size = 79333 }, + { url = "https://files.pythonhosted.org/packages/cb/a1/5393ac6d0b095d3a44946b09258e9b5f22cb2fb67bcfa419dd868478826c/watchdog-5.0.3-py3-none-manylinux2014_s390x.whl", hash = "sha256:26dd201857d702bdf9d78c273cafcab5871dd29343748524695cecffa44a8d97", size = 79332 }, + { url = "https://files.pythonhosted.org/packages/a0/58/edec25190b6403caf4426dd418234f2358a106634b7d6aa4aec6939b104f/watchdog-5.0.3-py3-none-manylinux2014_x86_64.whl", hash = "sha256:0f9332243355643d567697c3e3fa07330a1d1abf981611654a1f2bf2175612b7", size = 79334 }, + { url = "https://files.pythonhosted.org/packages/97/69/cfb2d17ba8aabc73be2e2d03c8c319b1f32053a02c4b571852983aa24ff2/watchdog-5.0.3-py3-none-win32.whl", hash = "sha256:c66f80ee5b602a9c7ab66e3c9f36026590a0902db3aea414d59a2f55188c1f49", size = 79320 }, + { url = "https://files.pythonhosted.org/packages/91/b4/2b5b59358dadfa2c8676322f955b6c22cde4937602f40490e2f7403e548e/watchdog-5.0.3-py3-none-win_amd64.whl", hash = "sha256:f00b4cf737f568be9665563347a910f8bdc76f88c2970121c86243c8cfdf90e9", size = 79325 }, + { url = "https://files.pythonhosted.org/packages/38/b8/0aa69337651b3005f161f7f494e59188a1d8d94171666900d26d29d10f69/watchdog-5.0.3-py3-none-win_ia64.whl", hash = "sha256:49f4d36cb315c25ea0d946e018c01bb028048023b9e103d3d3943f58e109dd45", size = 79324 }, +] From 0fc61ac1b9dcadd3ae660a0341da68d191d5d4aa Mon Sep 17 00:00:00 2001 From: Masaya Kataoka Date: Wed, 16 Oct 2024 23:43:38 +0900 Subject: [PATCH 2/2] Fix/add ad converter (#356) * add start script Signed-off-by: Masaya Kataoka * add BOM plugin Signed-off-by: Masaya Kataoka * enable use x11 forwarding Signed-off-by: Masaya Kataoka * update description Signed-off-by: Masaya Kataoka * update Dockerfile Signed-off-by: Masaya Kataoka * add 3rd party directory Signed-off-by: Masaya Kataoka * add entrypoint.sh Signed-off-by: Masaya Kataoka * add teensy library Signed-off-by: Masaya Kataoka * add teensy Signed-off-by: Masaya Kataoka * enable run kibot Signed-off-by: Masaya Kataoka * update kibot.yaml Signed-off-by: Masaya Kataoka * enable save schematic in SVG Signed-off-by: Masaya Kataoka * rename project Signed-off-by: Masaya Kataoka * add SVG schematic Signed-off-by: Masaya Kataoka * enable show schematics Signed-off-by: Masaya Kataoka * fix dashboard Signed-off-by: Masaya Kataoka * add depends Signed-off-by: Masaya Kataoka * use uv Signed-off-by: Masaya Kataoka * fix typo Signed-off-by: Masaya Kataoka * update schematics Signed-off-by: Masaya Kataoka * add AD converter Signed-off-by: Masaya Kataoka * add run kibot step Signed-off-by: Masaya Kataoka --------- Signed-off-by: Masaya Kataoka --- .github/workflows/document.yaml | 3 + .gitignore | 4 + .../computer_sensor_board.kicad_pro | 5 +- .../computer_sensor_board.kicad_sch | 1210 +++++++++++++---- 4 files changed, 962 insertions(+), 260 deletions(-) diff --git a/.github/workflows/document.yaml b/.github/workflows/document.yaml index a1702c37e..c0b508ee8 100644 --- a/.github/workflows/document.yaml +++ b/.github/workflows/document.yaml @@ -27,6 +27,9 @@ jobs: run: uv sync - name: Set env run: echo "GITHUB_TOKEN=${{ secrets.WAMV_TAN_BOT_SECRET }}" >> $GITHUB_ENV + - name: Run kibot + working-directory: circuits + run: sh run_kibot.sh - name: Generate documentation run: uv run mkdocs build working-directory: docs diff --git a/.gitignore b/.gitignore index 48e64fce1..fb66af2dd 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,7 @@ __pycache__ # kicad fp-info-cache +*backups* +*auto_saved_files* +*.lck +kibot_output diff --git a/circuits/computer_sensor_board/computer_sensor_board/computer_sensor_board.kicad_pro b/circuits/computer_sensor_board/computer_sensor_board/computer_sensor_board.kicad_pro index 6b90d6cc5..12a9777e8 100644 --- a/circuits/computer_sensor_board/computer_sensor_board/computer_sensor_board.kicad_pro +++ b/circuits/computer_sensor_board/computer_sensor_board/computer_sensor_board.kicad_pro @@ -24,7 +24,10 @@ "equivalence_files": [] }, "erc": { - "erc_exclusions": [], + "erc_exclusions": [ + "power_pin_not_driven|1549400|266700|0bc61f16-8db2-4ee2-8eb3-dd550ff96a15|00000000-0000-0000-0000-000000000000|/6ddf9647-3471-4724-9337-c9866d28db60|/6ddf9647-3471-4724-9337-c9866d28db60|", + "power_pin_not_driven|1549400|469900|6f856c81-5244-4bd5-ac7b-6bcc1b8d12c7|00000000-0000-0000-0000-000000000000|/6ddf9647-3471-4724-9337-c9866d28db60|/6ddf9647-3471-4724-9337-c9866d28db60|" + ], "meta": { "version": 0 }, diff --git a/circuits/computer_sensor_board/computer_sensor_board/computer_sensor_board.kicad_sch b/circuits/computer_sensor_board/computer_sensor_board/computer_sensor_board.kicad_sch index ef4ed5bbc..3f9a62f01 100644 --- a/circuits/computer_sensor_board/computer_sensor_board/computer_sensor_board.kicad_sch +++ b/circuits/computer_sensor_board/computer_sensor_board/computer_sensor_board.kicad_sch @@ -5,6 +5,199 @@ (uuid "6ddf9647-3471-4724-9337-c9866d28db60") (paper "A4") (lib_symbols + (symbol "Analog_ADC:MCP3425Axx-xCH" + (exclude_from_sim no) + (in_bom yes) + (on_board yes) + (property "Reference" "U" + (at -10.16 7.62 0) + (effects + (font + (size 1.27 1.27) + ) + (justify left) + ) + ) + (property "Value" "MCP3425Axx-xCH" + (at 2.54 7.62 0) + (effects + (font + (size 1.27 1.27) + ) + (justify left) + ) + ) + (property "Footprint" "Package_TO_SOT_SMD:SOT-23-6" + (at 16.51 -7.62 0) + (effects + (font + (size 1.27 1.27) + (italic yes) + ) + (hide yes) + ) + ) + (property "Datasheet" "http://ww1.microchip.com/downloads/en/DeviceDoc/22072b.pdf" + (at 0 12.7 0) + (effects + (font + (size 1.27 1.27) + ) + (hide yes) + ) + ) + (property "Description" "Single Delta-Sigma 16bit Analog to Digital Converter, I2C Interface, SOT-23-6" + (at 0 0 0) + (effects + (font + (size 1.27 1.27) + ) + (hide yes) + ) + ) + (property "ki_keywords" "Sigma-Delta ADC Converter 16bit I2C 1ch" + (at 0 0 0) + (effects + (font + (size 1.27 1.27) + ) + (hide yes) + ) + ) + (property "ki_fp_filters" "SOT?23*" + (at 0 0 0) + (effects + (font + (size 1.27 1.27) + ) + (hide yes) + ) + ) + (symbol "MCP3425Axx-xCH_0_1" + (polyline + (pts + (xy -5.08 6.35) (xy 8.89 6.35) (xy 8.89 0) (xy 8.89 -6.35) (xy -5.08 -6.35) (xy -11.43 0) (xy -5.08 6.35) + ) + (stroke + (width 0.254) + (type default) + ) + (fill + (type background) + ) + ) + ) + (symbol "MCP3425Axx-xCH_1_1" + (pin passive line + (at -12.7 2.54 0) + (length 3.81) + (name "Vin+" + (effects + (font + (size 1.27 1.27) + ) + ) + ) + (number "1" + (effects + (font + (size 1.27 1.27) + ) + ) + ) + ) + (pin power_in line + (at 0 -10.16 90) + (length 3.81) + (name "V_{SS}" + (effects + (font + (size 1.27 1.27) + ) + ) + ) + (number "2" + (effects + (font + (size 1.27 1.27) + ) + ) + ) + ) + (pin input line + (at 12.7 2.54 180) + (length 3.81) + (name "SCL" + (effects + (font + (size 1.27 1.27) + ) + ) + ) + (number "3" + (effects + (font + (size 1.27 1.27) + ) + ) + ) + ) + (pin bidirectional line + (at 12.7 0 180) + (length 3.81) + (name "SDA" + (effects + (font + (size 1.27 1.27) + ) + ) + ) + (number "4" + (effects + (font + (size 1.27 1.27) + ) + ) + ) + ) + (pin power_in line + (at 0 10.16 270) + (length 3.81) + (name "V_{DD}" + (effects + (font + (size 1.27 1.27) + ) + ) + ) + (number "5" + (effects + (font + (size 1.27 1.27) + ) + ) + ) + ) + (pin passive line + (at -12.7 -2.54 0) + (length 3.81) + (name "Vin-" + (effects + (font + (size 1.27 1.27) + ) + ) + ) + (number "6" + (effects + (font + (size 1.27 1.27) + ) + ) + ) + ) + ) + ) (symbol "Connector:USB_A" (pin_names (offset 1.016) @@ -2821,654 +3014,850 @@ ) ) (junction - (at 95.25 54.61) + (at 91.44 74.93) (diameter 0) (color 0 0 0 0) (uuid "11201e64-ce0b-4594-839d-7b17afbe1c2a") ) (junction - (at 113.03 55.88) + (at 109.22 76.2) (diameter 0) (color 0 0 0 0) (uuid "1f0c4f96-b2fb-435a-bb86-a0d71470e03b") ) (junction - (at 171.45 114.3) + (at 167.64 134.62) (diameter 0) (color 0 0 0 0) (uuid "1f6ee5aa-8d75-46c0-9b12-afc9be804300") ) (junction - (at 77.47 124.46) + (at 73.66 144.78) (diameter 0) (color 0 0 0 0) (uuid "234ef857-81f0-4af3-b4d0-ac2fcae7ec93") ) (junction - (at 135.89 114.3) + (at 132.08 134.62) (diameter 0) (color 0 0 0 0) (uuid "25ce634c-a2e3-4f95-a93f-33b7e51fb7bf") ) (junction - (at 73.66 121.92) + (at 69.85 142.24) (diameter 0) (color 0 0 0 0) (uuid "3338681e-0890-45f9-a90d-d88c61a902fc") ) (junction - (at 76.2 57.15) + (at 72.39 77.47) (diameter 0) (color 0 0 0 0) (uuid "4d82654c-6c13-43d1-b139-975e72e2705c") ) (junction - (at 76.2 54.61) + (at 72.39 74.93) (diameter 0) (color 0 0 0 0) (uuid "6beb4a32-6f83-499a-914a-dc2e0e12b133") ) (junction - (at 83.82 124.46) + (at 80.01 144.78) (diameter 0) (color 0 0 0 0) (uuid "7899c3bd-ab86-473e-b36c-5f782b490754") ) (junction - (at 186.69 124.46) + (at 171.45 34.29) + (diameter 0) + (color 0 0 0 0) + (uuid "7941c1ca-405d-4937-b848-4bb06c6fa009") + ) + (junction + (at 182.88 144.78) (diameter 0) (color 0 0 0 0) (uuid "8154df9d-fbf0-407e-874f-9292618a0a95") ) (junction - (at 151.13 124.46) + (at 147.32 144.78) (diameter 0) (color 0 0 0 0) (uuid "830af006-d8c1-49ee-8460-63d3ff557147") ) (junction - (at 83.82 114.3) + (at 243.84 144.78) + (diameter 0) + (color 0 0 0 0) + (uuid "93eca061-25a8-46ab-bb15-43f3fafa8a8a") + ) + (junction + (at 179.07 21.59) + (diameter 0) + (color 0 0 0 0) + (uuid "99cd4739-81c3-4516-a76d-e25a59de9985") + ) + (junction + (at 80.01 134.62) (diameter 0) (color 0 0 0 0) (uuid "9ee25083-8ae2-41b5-9e03-13608bf83c04") ) (junction - (at 186.69 137.16) + (at 182.88 158.75) + (diameter 0) + (color 0 0 0 0) + (uuid "bb3fe665-f02f-4d32-ba16-39ca2ec655cb") + ) + (junction + (at 171.45 21.59) (diameter 0) (color 0 0 0 0) - (uuid "da906ab5-1310-4f2e-8b1d-72f7424d38c5") + (uuid "db288119-c241-474b-b051-2704ec6d9340") ) (junction - (at 95.25 57.15) + (at 91.44 77.47) (diameter 0) (color 0 0 0 0) (uuid "e0123bb6-624b-4d09-838d-086a461aacb3") ) (junction - (at 151.13 138.43) + (at 121.92 76.2) + (diameter 0) + (color 0 0 0 0) + (uuid "e3f6a8bd-af27-4749-a20d-396155a6b984") + ) + (junction + (at 109.22 83.82) + (diameter 0) + (color 0 0 0 0) + (uuid "e433ab0f-0e84-4f1c-b47c-ba95cc2998c4") + ) + (junction + (at 179.07 36.83) + (diameter 0) + (color 0 0 0 0) + (uuid "faceb8ae-f4cb-43be-bfae-c045ee38a61f") + ) + (junction + (at 147.32 158.75) (diameter 0) (color 0 0 0 0) (uuid "fd79ae57-7d43-46be-8733-5009066d3507") ) (no_connect - (at 264.16 81.28) + (at 243.84 101.6) (uuid "0c472fbd-8a01-4ed0-91e8-c5ea5904c573") ) (no_connect - (at 264.16 96.52) + (at 243.84 116.84) (uuid "0f7841d6-55ab-495e-842b-38a2ae6eacde") ) (no_connect - (at 264.16 91.44) + (at 243.84 111.76) (uuid "1114c93b-e800-4e9f-ae1e-d9f233e7b84d") ) (no_connect - (at 264.16 34.29) + (at 243.84 54.61) (uuid "1172a5e7-370c-460f-8d99-578852bf1de3") ) (no_connect - (at 208.28 36.83) + (at 187.96 57.15) (uuid "193d203f-d597-4978-89ba-8c07768da673") ) (no_connect - (at 264.16 86.36) + (at 243.84 106.68) (uuid "1e7f1754-49ba-44e4-854f-13d8cf1edf9d") ) (no_connect - (at 264.16 88.9) + (at 243.84 109.22) (uuid "1ff1cb81-2417-408e-9a8f-52acb4245f42") ) (no_connect - (at 264.16 99.06) + (at 243.84 119.38) (uuid "218aed49-ed49-4e2b-a120-82deeb95f697") ) (no_connect - (at 208.28 41.91) + (at 187.96 62.23) (uuid "21b12032-73ea-4638-aace-1de282b4e173") ) (no_connect - (at 264.16 104.14) + (at 243.84 124.46) (uuid "246c2332-58a0-44da-995f-d697caea77e3") ) (no_connect - (at 208.28 81.28) + (at 187.96 101.6) (uuid "24d6c2d5-a21d-423a-9f27-0833291da63e") ) (no_connect - (at 208.28 86.36) + (at 187.96 106.68) (uuid "269ccd06-f6d0-4177-94a9-0f8cbaa19e88") ) (no_connect - (at 140.97 130.81) + (at 137.16 151.13) (uuid "2799b353-562d-4199-8e2d-10b0f24915f9") ) (no_connect - (at 264.16 101.6) + (at 243.84 121.92) (uuid "32dde710-c483-4753-a92f-7445fb1fe9dd") ) (no_connect - (at 264.16 55.88) + (at 243.84 76.2) (uuid "37bde2a4-4bb7-4ae9-acbd-38be438ff909") ) (no_connect - (at 264.16 109.22) + (at 243.84 91.44) + (uuid "399d6c63-8da8-4e3e-8f3c-29ab04989e97") + ) + (no_connect + (at 243.84 129.54) (uuid "41e50cb0-8c7c-41e8-b0cd-4d417b242bd1") ) (no_connect - (at 208.28 49.53) + (at 187.96 69.85) (uuid "41fff0f7-f98f-43b2-a8dc-3f0f147f6172") ) (no_connect - (at 243.84 26.67) + (at 223.52 46.99) (uuid "4a59693a-35ba-47a0-98f2-24c18718bae3") ) (no_connect - (at 264.16 93.98) + (at 243.84 114.3) (uuid "4ef78920-4434-4809-9d68-00e8e731abda") ) (no_connect - (at 264.16 41.91) + (at 243.84 62.23) (uuid "519a0017-1852-4dd8-8788-494520bbde3c") ) (no_connect - (at 208.28 109.22) - (uuid "53839847-654f-45ed-a6c5-03bbbe8775a7") - ) - (no_connect - (at 208.28 99.06) + (at 187.96 119.38) (uuid "56e04f8a-4dd5-494e-99b1-7bb1f2131c1f") ) (no_connect - (at 176.53 129.54) + (at 172.72 151.13) (uuid "57c88216-1828-4cbe-98a6-dd6211acdcab") ) (no_connect - (at 240.03 26.67) + (at 219.71 46.99) (uuid "57fa0e83-19d7-413e-9fe8-52e30700fec2") ) (no_connect - (at 264.16 106.68) + (at 187.96 99.06) + (uuid "5866721b-d6a0-4e70-9545-7b8b4d252471") + ) + (no_connect + (at 243.84 127) (uuid "5bae3676-726e-40c2-9212-22d4045d1bc0") ) (no_connect - (at 264.16 66.04) + (at 243.84 86.36) (uuid "5da986eb-7dd7-4219-8c41-6c5933919fba") ) (no_connect - (at 264.16 39.37) + (at 243.84 59.69) (uuid "5e5c63a6-d2fd-4612-ab6e-dbd521895ecc") ) (no_connect - (at 208.28 83.82) + (at 187.96 104.14) (uuid "61b02380-454a-41e0-97ee-46797e4ecf24") ) (no_connect - (at 179.07 129.54) + (at 175.26 151.13) (uuid "625dd5c8-2859-4d7a-a6f3-32672d4d2da5") ) (no_connect - (at 208.28 39.37) + (at 187.96 59.69) (uuid "6a7e5ea2-53bf-4971-a047-2371afacc07e") ) (no_connect - (at 264.16 36.83) + (at 243.84 57.15) (uuid "6f28d163-baaf-4f77-814b-07a7aff6f365") ) (no_connect - (at 208.28 60.96) + (at 187.96 81.28) (uuid "6f8cad64-530c-4177-9e8e-92a3cd38f26a") ) (no_connect - (at 208.28 104.14) + (at 187.96 124.46) (uuid "7f727589-a883-4d9d-b310-0f05bef7700f") ) (no_connect - (at 208.28 93.98) + (at 187.96 114.3) (uuid "7fed3c0c-c128-4aa0-bab4-2750ceefa575") ) (no_connect - (at 208.28 88.9) + (at 187.96 109.22) (uuid "8008312e-0877-4199-8d06-eaf2b3fc02d7") ) (no_connect - (at 208.28 68.58) + (at 187.96 88.9) (uuid "8eb0d02f-4a01-438e-a9e7-5f64eaa423c5") ) (no_connect - (at 264.16 68.58) + (at 243.84 88.9) (uuid "9077c827-148a-4b18-9ed0-5febeb1f950b") ) (no_connect - (at 208.28 101.6) + (at 187.96 121.92) (uuid "994809d3-e7fd-4b70-a965-70795e39bb87") ) (no_connect - (at 264.16 76.2) - (uuid "9e242f59-3340-4ad3-bc26-3aba8fec52ed") - ) - (no_connect - (at 232.41 26.67) + (at 212.09 46.99) (uuid "a23140a6-cad5-4159-b7f3-dc1b02d93549") ) (no_connect - (at 208.28 63.5) + (at 187.96 83.82) (uuid "aa0feeb1-170c-4dca-97d7-0e2c911495b2") ) (no_connect - (at 264.16 60.96) + (at 243.84 81.28) (uuid "aa78de80-f821-4f6f-8ee7-0d04e8d7be8f") ) (no_connect - (at 208.28 76.2) + (at 187.96 96.52) (uuid "abb3c054-2b90-4645-8478-9e7345b02520") ) (no_connect - (at 208.28 73.66) + (at 187.96 93.98) (uuid "abb9c61d-9932-4574-bd2d-7e6d5e328b39") ) (no_connect - (at 208.28 91.44) + (at 187.96 111.76) (uuid "b48204e5-2705-4804-97ba-106e72e07693") ) (no_connect - (at 208.28 78.74) - (uuid "b71f5e05-e568-4e0f-aaea-777b24083ac0") - ) - (no_connect - (at 208.28 96.52) + (at 187.96 116.84) (uuid "b75c9581-2a6d-4be8-8b14-677a3154dc31") ) (no_connect - (at 208.28 55.88) + (at 187.96 76.2) (uuid "b9010203-03da-403e-8742-31a90813ee53") ) (no_connect - (at 87.63 119.38) + (at 83.82 139.7) (uuid "ba562759-cd69-4b15-a8ad-0eca57a55bd9") ) (no_connect - (at 208.28 46.99) + (at 187.96 67.31) (uuid "bc9a5c87-acbd-4754-ba27-4caf61dd6ab4") ) (no_connect - (at 264.16 71.12) - (uuid "bdefffb0-b9db-4d6b-8d75-6fe46b4cb8ed") - ) - (no_connect - (at 228.6 26.67) + (at 208.28 46.99) (uuid "c536744c-7ba0-4ee9-a3f3-c98b59b2d625") ) (no_connect - (at 236.22 26.67) + (at 215.9 46.99) (uuid "c545f8d1-c47e-4638-bc80-28ec33e658fe") ) (no_connect - (at 143.51 130.81) + (at 139.7 151.13) (uuid "c660dc3c-4a9e-451e-8682-b8fa4ce15684") ) (no_connect - (at 264.16 111.76) + (at 243.84 132.08) (uuid "c985dbd0-36d5-41f0-935d-5f554fe000ce") ) (no_connect - (at 208.28 66.04) + (at 187.96 86.36) (uuid "d0eda133-df65-4ef1-83a5-1ef22e52c7e6") ) (no_connect - (at 208.28 58.42) + (at 187.96 78.74) (uuid "d365f221-df86-48ad-a02a-c7cbc30d37a5") ) (no_connect - (at 208.28 71.12) + (at 187.96 91.44) (uuid "dafde43e-a86a-4be7-850c-ef94d666c3e1") ) (no_connect - (at 264.16 83.82) + (at 243.84 104.14) (uuid "dcc337df-4bbe-4cee-bbf9-3e1999f0a338") ) (no_connect - (at 264.16 78.74) + (at 243.84 99.06) (uuid "de27596f-87d8-4e3e-a8fe-bf07698038db") ) (no_connect - (at 208.28 118.11) + (at 187.96 138.43) (uuid "dfc87ab0-8da5-46f5-a5db-3a57e5e05d89") ) (no_connect - (at 264.16 73.66) - (uuid "e2eb5b7f-77ee-4582-b6d4-b48fd94049ad") - ) - (no_connect - (at 264.16 63.5) + (at 243.84 83.82) (uuid "e3a1cad5-4f96-4568-910a-9212ad6f1611") ) (no_connect - (at 208.28 111.76) - (uuid "e4ae3504-447e-4dd1-8aaa-ee5d94711f22") - ) - (no_connect - (at 264.16 44.45) + (at 243.84 64.77) (uuid "eab60380-71c1-45af-9f8b-def2c48573c9") ) (no_connect - (at 264.16 50.8) + (at 243.84 71.12) (uuid "f0419da2-98cd-40b3-84c3-be327bc61dfb") ) (no_connect - (at 208.28 44.45) + (at 187.96 64.77) (uuid "f82321cb-b8b0-407d-b1f6-c21f6ab9fa3f") ) (no_connect - (at 264.16 58.42) + (at 243.84 78.74) (uuid "f85cddb4-4661-4950-b384-cca7115e5fb7") ) (no_connect - (at 264.16 48.26) + (at 243.84 68.58) (uuid "fe720fda-f169-4c38-8f93-f61252d5f15b") ) (wire (pts - (xy 105.41 48.26) (xy 113.03 48.26) + (xy 182.88 158.75) (xy 182.88 161.29) ) (stroke (width 0) (type default) ) - (uuid "042a898a-33ff-4940-b1c4-f24a8bc94934") + (uuid "023cfb68-a3eb-46c7-8388-822795b8a328") ) (wire (pts - (xy 118.11 114.3) (xy 135.89 114.3) + (xy 101.6 68.58) (xy 109.22 68.58) ) (stroke (width 0) (type default) ) - (uuid "05a3e86e-81b8-4df7-809e-c24bd0b62fba") + (uuid "042a898a-33ff-4940-b1c4-f24a8bc94934") ) (wire (pts - (xy 90.17 102.87) (xy 77.47 102.87) + (xy 167.64 36.83) (xy 179.07 36.83) ) (stroke (width 0) (type default) ) - (uuid "089202c9-9043-4d3e-a050-a41341813213") + (uuid "052b1db6-9bf6-413f-930c-832c8db1325d") ) (wire (pts - (xy 119.38 55.88) (xy 113.03 55.88) + (xy 179.07 21.59) (xy 185.42 21.59) ) (stroke (width 0) (type default) ) - (uuid "26672a1a-006f-4917-96f0-c246ddac629c") + (uuid "057dccf0-207c-4339-b762-84eb1f50572b") ) (wire (pts - (xy 186.69 124.46) (xy 264.16 124.46) + (xy 114.3 134.62) (xy 132.08 134.62) ) (stroke (width 0) (type default) ) - (uuid "27dbecd3-5706-4c2e-86c7-426eb1b0c38b") + (uuid "05a3e86e-81b8-4df7-809e-c24bd0b62fba") ) (wire (pts - (xy 135.89 114.3) (xy 135.89 130.81) + (xy 86.36 123.19) (xy 73.66 123.19) ) (stroke (width 0) (type default) ) - (uuid "2c4d6adf-4996-4950-bcdd-78d79b8fab23") + (uuid "089202c9-9043-4d3e-a050-a41341813213") ) (wire (pts - (xy 73.66 121.92) (xy 41.91 121.92) + (xy 255.27 36.83) (xy 255.27 93.98) ) (stroke (width 0) (type default) ) - (uuid "3464682e-6727-4ac5-bce4-816d4b767aca") + (uuid "14223dd2-0a32-4215-8ee6-f3493f74cc28") ) (wire (pts - (xy 77.47 124.46) (xy 83.82 124.46) + (xy 121.92 76.2) (xy 109.22 76.2) ) (stroke (width 0) (type default) ) - (uuid "36e24527-2425-41ef-81d6-c306417ef71c") + (uuid "26672a1a-006f-4917-96f0-c246ddac629c") ) (wire (pts - (xy 41.91 116.84) (xy 66.04 116.84) + (xy 182.88 144.78) (xy 243.84 144.78) ) (stroke (width 0) (type default) ) - (uuid "3860d806-efab-491b-a7c7-50a13de4126d") + (uuid "27dbecd3-5706-4c2e-86c7-426eb1b0c38b") ) (wire (pts - (xy 83.82 114.3) (xy 82.55 114.3) + (xy 154.94 21.59) (xy 171.45 21.59) ) (stroke (width 0) (type default) ) - (uuid "3cd5cc55-3dda-4db5-a85e-51775fe432c2") + (uuid "2912b804-0f26-43c9-818b-56abe0e205a3") ) (wire (pts - (xy 82.55 114.3) (xy 82.55 121.92) + (xy 179.07 31.75) (xy 179.07 36.83) ) (stroke (width 0) (type default) ) - (uuid "44431496-6048-4c18-9290-c9a95a806756") + (uuid "2c31aeb8-ae54-4144-bacf-1c8d5bf0db1b") ) (wire (pts - (xy 76.2 54.61) (xy 95.25 54.61) + (xy 132.08 134.62) (xy 132.08 151.13) ) (stroke (width 0) (type default) ) - (uuid "457d8239-1820-4512-8478-57e736be0383") + (uuid "2c4d6adf-4996-4950-bcdd-78d79b8fab23") ) (wire (pts - (xy 66.04 54.61) (xy 76.2 54.61) + (xy 109.22 83.82) (xy 142.24 83.82) ) (stroke (width 0) (type default) ) - (uuid "4c126136-50f7-4466-903f-b8f78d72450b") + (uuid "2e0c5ace-f970-43ec-a72b-0e667424ba40") ) (wire (pts - (xy 119.38 106.68) (xy 119.38 55.88) + (xy 179.07 36.83) (xy 255.27 36.83) ) (stroke (width 0) (type default) ) - (uuid "51ae9bcb-8fc2-47c1-9a4e-76887566eb98") + (uuid "323511bb-4e11-41f0-9863-8fdadd655564") ) (wire (pts - (xy 68.58 119.38) (xy 68.58 57.15) + (xy 69.85 142.24) (xy 38.1 142.24) ) (stroke (width 0) (type default) ) - (uuid "54440bc1-9884-401d-b198-5445e53ce2fb") + (uuid "3464682e-6727-4ac5-bce4-816d4b767aca") ) (wire (pts - (xy 73.66 100.33) (xy 73.66 121.92) + (xy 73.66 144.78) (xy 80.01 144.78) ) (stroke (width 0) (type default) ) - (uuid "570cb307-ecec-4ba3-8242-c0c701dc5fec") + (uuid "36e24527-2425-41ef-81d6-c306417ef71c") ) (wire (pts - (xy 264.16 124.46) (xy 264.16 114.3) + (xy 171.45 31.75) (xy 171.45 34.29) ) (stroke (width 0) (type default) ) - (uuid "589e9185-b59f-449d-a1dd-202f579ce95a") + (uuid "372595f9-aeb5-48c1-909c-90ecd02363c1") ) (wire (pts - (xy 171.45 114.3) (xy 208.28 114.3) + (xy 38.1 137.16) (xy 62.23 137.16) ) (stroke (width 0) (type default) ) - (uuid "5aa6de1b-986c-447a-89d8-33686d762b61") + (uuid "3860d806-efab-491b-a7c7-50a13de4126d") ) (wire (pts - (xy 77.47 102.87) (xy 77.47 124.46) + (xy 80.01 134.62) (xy 78.74 134.62) ) (stroke (width 0) (type default) ) - (uuid "649b5177-feb7-401e-b3ad-1390799e27e2") + (uuid "3cd5cc55-3dda-4db5-a85e-51775fe432c2") ) (wire (pts - (xy 95.25 54.61) (xy 105.41 54.61) + (xy 257.81 34.29) (xy 257.81 96.52) ) (stroke (width 0) (type default) ) - (uuid "6d6ff9f9-e943-4496-b398-14729f228be1") + (uuid "3fec058c-3a0f-4125-b214-667b1d8a908d") ) (wire (pts - (xy 68.58 57.15) (xy 76.2 57.15) + (xy 243.84 96.52) (xy 257.81 96.52) ) (stroke (width 0) (type default) ) - (uuid "6d755e71-eb07-46d4-85ce-0cf6d89de88b") + (uuid "4318fe73-4d6d-41b9-a668-3eca5f6e0251") ) (wire (pts - (xy 186.69 124.46) (xy 186.69 137.16) + (xy 78.74 134.62) (xy 78.74 142.24) ) (stroke (width 0) (type default) ) - (uuid "6fff715a-998f-46c1-ab84-02955a5fe22c") + (uuid "44431496-6048-4c18-9290-c9a95a806756") ) (wire (pts - (xy 171.45 114.3) (xy 171.45 129.54) + (xy 72.39 74.93) (xy 91.44 74.93) ) (stroke (width 0) (type default) ) - (uuid "706d6bf0-655b-4c83-a1b9-f11785ff1c4e") + (uuid "457d8239-1820-4512-8478-57e736be0383") ) (wire (pts - (xy 151.13 124.46) (xy 186.69 124.46) + (xy 179.07 21.59) (xy 179.07 24.13) ) (stroke (width 0) (type default) ) - (uuid "70898e54-da27-448f-a315-bb24e78897fc") + (uuid "4847e83d-54da-4bf8-ab19-9cdd1b815e30") ) (wire (pts - (xy 87.63 114.3) (xy 83.82 114.3) + (xy 62.23 74.93) (xy 72.39 74.93) ) (stroke (width 0) (type default) ) - (uuid "71f6dd75-4e76-491c-9d99-fd830faf347d") + (uuid "4c126136-50f7-4466-903f-b8f78d72450b") ) (wire (pts - (xy 82.55 121.92) (xy 73.66 121.92) + (xy 121.92 127) (xy 121.92 76.2) ) (stroke (width 0) (type default) ) - (uuid "7bdad320-5021-4b47-a812-39be6f63dbc8") + (uuid "51ae9bcb-8fc2-47c1-9a4e-76887566eb98") ) (wire (pts - (xy 186.69 137.16) (xy 186.69 139.7) + (xy 243.84 144.78) (xy 278.13 144.78) ) (stroke (width 0) (type default) ) - (uuid "7c8e1d40-535b-4f62-93d6-487fa3fd1fab") + (uuid "52b5d62e-d904-43d3-865a-ef4f2d4afd3b") ) (wire (pts - (xy 83.82 124.46) (xy 87.63 124.46) + (xy 64.77 139.7) (xy 64.77 77.47) ) (stroke (width 0) (type default) ) - (uuid "84294637-3e50-481e-8239-6fd17b3d3aa1") + (uuid "54440bc1-9884-401d-b198-5445e53ce2fb") ) (wire (pts - (xy 119.38 106.68) (xy 208.28 106.68) + (xy 69.85 120.65) (xy 69.85 142.24) + ) + (stroke + (width 0) + (type default) + ) + (uuid "570cb307-ecec-4ba3-8242-c0c701dc5fec") + ) + (wire + (pts + (xy 243.84 144.78) (xy 243.84 134.62) + ) + (stroke + (width 0) + (type default) + ) + (uuid "589e9185-b59f-449d-a1dd-202f579ce95a") + ) + (wire + (pts + (xy 167.64 134.62) (xy 187.96 134.62) + ) + (stroke + (width 0) + (type default) + ) + (uuid "5aa6de1b-986c-447a-89d8-33686d762b61") + ) + (wire + (pts + (xy 73.66 123.19) (xy 73.66 144.78) + ) + (stroke + (width 0) + (type default) + ) + (uuid "649b5177-feb7-401e-b3ad-1390799e27e2") + ) + (wire + (pts + (xy 185.42 129.54) (xy 187.96 129.54) + ) + (stroke + (width 0) + (type default) + ) + (uuid "6824428b-5a99-41ff-9a7d-73b6b228a21f") + ) + (wire + (pts + (xy 185.42 21.59) (xy 185.42 129.54) + ) + (stroke + (width 0) + (type default) + ) + (uuid "6cb51420-87ba-4e07-ab49-4a9ae7efb956") + ) + (wire + (pts + (xy 91.44 74.93) (xy 101.6 74.93) + ) + (stroke + (width 0) + (type default) + ) + (uuid "6d6ff9f9-e943-4496-b398-14729f228be1") + ) + (wire + (pts + (xy 64.77 77.47) (xy 72.39 77.47) + ) + (stroke + (width 0) + (type default) + ) + (uuid "6d755e71-eb07-46d4-85ce-0cf6d89de88b") + ) + (wire + (pts + (xy 182.88 144.78) (xy 182.88 158.75) + ) + (stroke + (width 0) + (type default) + ) + (uuid "6fff715a-998f-46c1-ab84-02955a5fe22c") + ) + (wire + (pts + (xy 167.64 134.62) (xy 167.64 151.13) + ) + (stroke + (width 0) + (type default) + ) + (uuid "706d6bf0-655b-4c83-a1b9-f11785ff1c4e") + ) + (wire + (pts + (xy 147.32 144.78) (xy 182.88 144.78) + ) + (stroke + (width 0) + (type default) + ) + (uuid "70898e54-da27-448f-a315-bb24e78897fc") + ) + (wire + (pts + (xy 83.82 134.62) (xy 80.01 134.62) + ) + (stroke + (width 0) + (type default) + ) + (uuid "71f6dd75-4e76-491c-9d99-fd830faf347d") + ) + (wire + (pts + (xy 171.45 21.59) (xy 171.45 24.13) + ) + (stroke + (width 0) + (type default) + ) + (uuid "727caf9c-dbd8-4bd6-9225-2d446061e836") + ) + (wire + (pts + (xy 154.94 26.67) (xy 154.94 21.59) + ) + (stroke + (width 0) + (type default) + ) + (uuid "7726a7df-fb64-485d-92be-9b23b16005c1") + ) + (wire + (pts + (xy 78.74 142.24) (xy 69.85 142.24) + ) + (stroke + (width 0) + (type default) + ) + (uuid "7bdad320-5021-4b47-a812-39be6f63dbc8") + ) + (wire + (pts + (xy 80.01 144.78) (xy 83.82 144.78) + ) + (stroke + (width 0) + (type default) + ) + (uuid "84294637-3e50-481e-8239-6fd17b3d3aa1") + ) + (wire + (pts + (xy 142.24 34.29) (xy 121.92 34.29) + ) + (stroke + (width 0) + (type default) + ) + (uuid "8e15a485-02d3-413f-a050-8bec2eea258b") + ) + (wire + (pts + (xy 121.92 127) (xy 187.96 127) ) (stroke (width 0) @@ -3478,7 +3867,7 @@ ) (wire (pts - (xy 105.41 63.5) (xy 113.03 63.5) + (xy 101.6 83.82) (xy 109.22 83.82) ) (stroke (width 0) @@ -3488,7 +3877,7 @@ ) (wire (pts - (xy 95.25 57.15) (xy 105.41 57.15) + (xy 91.44 77.47) (xy 101.6 77.47) ) (stroke (width 0) @@ -3498,7 +3887,7 @@ ) (wire (pts - (xy 151.13 138.43) (xy 151.13 140.97) + (xy 147.32 158.75) (xy 147.32 161.29) ) (stroke (width 0) @@ -3508,7 +3897,17 @@ ) (wire (pts - (xy 66.04 116.84) (xy 66.04 54.61) + (xy 121.92 34.29) (xy 121.92 76.2) + ) + (stroke + (width 0) + (type default) + ) + (uuid "964a751d-284a-4154-88f0-d3c6357e4729") + ) + (wire + (pts + (xy 62.23 137.16) (xy 62.23 74.93) ) (stroke (width 0) @@ -3518,7 +3917,27 @@ ) (wire (pts - (xy 105.41 54.61) (xy 105.41 48.26) + (xy 142.24 83.82) (xy 142.24 39.37) + ) + (stroke + (width 0) + (type default) + ) + (uuid "b187ab71-5627-4dbd-a703-a054417ca525") + ) + (wire + (pts + (xy 243.84 93.98) (xy 255.27 93.98) + ) + (stroke + (width 0) + (type default) + ) + (uuid "b5a63175-212f-4a75-a02e-f2a9a8db558c") + ) + (wire + (pts + (xy 101.6 74.93) (xy 101.6 68.58) ) (stroke (width 0) @@ -3528,7 +3947,7 @@ ) (wire (pts - (xy 135.89 114.3) (xy 171.45 114.3) + (xy 132.08 134.62) (xy 167.64 134.62) ) (stroke (width 0) @@ -3538,7 +3957,37 @@ ) (wire (pts - (xy 90.17 100.33) (xy 73.66 100.33) + (xy 154.94 46.99) (xy 154.94 132.08) + ) + (stroke + (width 0) + (type default) + ) + (uuid "babc2860-6081-420e-8304-039224019f56") + ) + (wire + (pts + (xy 171.45 34.29) (xy 257.81 34.29) + ) + (stroke + (width 0) + (type default) + ) + (uuid "c17bb7c4-dacb-4443-9ace-072b6ca8e943") + ) + (wire + (pts + (xy 154.94 132.08) (xy 187.96 132.08) + ) + (stroke + (width 0) + (type default) + ) + (uuid "d0469d4a-e69f-49a1-a852-5ece6d2c6593") + ) + (wire + (pts + (xy 86.36 120.65) (xy 69.85 120.65) ) (stroke (width 0) @@ -3548,7 +3997,7 @@ ) (wire (pts - (xy 41.91 119.38) (xy 68.58 119.38) + (xy 38.1 139.7) (xy 64.77 139.7) ) (stroke (width 0) @@ -3558,7 +4007,7 @@ ) (wire (pts - (xy 118.11 124.46) (xy 151.13 124.46) + (xy 114.3 144.78) (xy 147.32 144.78) ) (stroke (width 0) @@ -3568,7 +4017,7 @@ ) (wire (pts - (xy 41.91 124.46) (xy 77.47 124.46) + (xy 38.1 144.78) (xy 73.66 144.78) ) (stroke (width 0) @@ -3578,7 +4027,17 @@ ) (wire (pts - (xy 105.41 57.15) (xy 105.41 63.5) + (xy 167.64 34.29) (xy 171.45 34.29) + ) + (stroke + (width 0) + (type default) + ) + (uuid "e925b519-fee2-4afb-acc2-846818d4078c") + ) + (wire + (pts + (xy 101.6 77.47) (xy 101.6 83.82) ) (stroke (width 0) @@ -3588,7 +4047,7 @@ ) (wire (pts - (xy 76.2 57.15) (xy 95.25 57.15) + (xy 72.39 77.47) (xy 91.44 77.47) ) (stroke (width 0) @@ -3598,7 +4057,7 @@ ) (wire (pts - (xy 151.13 124.46) (xy 151.13 138.43) + (xy 147.32 144.78) (xy 147.32 158.75) ) (stroke (width 0) @@ -3606,9 +4065,19 @@ ) (uuid "f4c0e4c3-8b04-48c9-aa88-191b7501e464") ) + (wire + (pts + (xy 171.45 21.59) (xy 179.07 21.59) + ) + (stroke + (width 0) + (type default) + ) + (uuid "fe533b73-b11c-4037-bdbc-a336e9e26048") + ) (symbol (lib_id "power:PWR_FLAG") - (at 83.82 124.46 180) + (at 80.01 144.78 180) (unit 1) (exclude_from_sim no) (in_bom yes) @@ -3617,7 +4086,7 @@ (fields_autoplaced yes) (uuid "1d62a4f9-8d74-4d2d-bb68-90f20a720179") (property "Reference" "#FLG04" - (at 83.82 126.365 0) + (at 80.01 146.685 0) (effects (font (size 1.27 1.27) @@ -3626,7 +4095,7 @@ ) ) (property "Value" "PWR_FLAG" - (at 83.82 129.54 0) + (at 80.01 149.86 0) (effects (font (size 1.27 1.27) @@ -3634,7 +4103,7 @@ ) ) (property "Footprint" "" - (at 83.82 124.46 0) + (at 80.01 144.78 0) (effects (font (size 1.27 1.27) @@ -3643,7 +4112,7 @@ ) ) (property "Datasheet" "~" - (at 83.82 124.46 0) + (at 80.01 144.78 0) (effects (font (size 1.27 1.27) @@ -3652,7 +4121,7 @@ ) ) (property "Description" "Special symbol for telling ERC where power comes from" - (at 83.82 124.46 0) + (at 80.01 144.78 0) (effects (font (size 1.27 1.27) @@ -3674,7 +4143,7 @@ ) (symbol (lib_id "teensy:Teensy4.1") - (at 236.22 59.69 180) + (at 215.9 80.01 180) (unit 1) (exclude_from_sim no) (in_bom yes) @@ -3683,7 +4152,7 @@ (fields_autoplaced yes) (uuid "212ebb76-33f9-432b-b8e6-e9c67fefa303") (property "Reference" "U2" - (at 236.22 123.19 0) + (at 215.9 143.51 0) (effects (font (size 1.27 1.27) @@ -3691,7 +4160,7 @@ ) ) (property "Value" "Teensy4.1" - (at 236.22 125.73 0) + (at 215.9 146.05 0) (effects (font (size 1.27 1.27) @@ -3699,7 +4168,7 @@ ) ) (property "Footprint" "" - (at 246.38 69.85 0) + (at 226.06 90.17 0) (effects (font (size 1.27 1.27) @@ -3708,7 +4177,7 @@ ) ) (property "Datasheet" "" - (at 246.38 69.85 0) + (at 226.06 90.17 0) (effects (font (size 1.27 1.27) @@ -3717,7 +4186,7 @@ ) ) (property "Description" "" - (at 236.22 59.69 0) + (at 215.9 80.01 0) (effects (font (size 1.27 1.27) @@ -3937,7 +4406,7 @@ ) (symbol (lib_id "Regulator_Switching:TDN_5-2411WISM") - (at 102.87 119.38 0) + (at 99.06 139.7 0) (unit 1) (exclude_from_sim no) (in_bom yes) @@ -3946,7 +4415,7 @@ (fields_autoplaced yes) (uuid "33c7c804-cbf3-474d-ac4b-1d9a07a2ea13") (property "Reference" "U1" - (at 102.87 106.68 0) + (at 99.06 127 0) (effects (font (size 1.27 1.27) @@ -3954,7 +4423,7 @@ ) ) (property "Value" "TDN_5-2411WISM" - (at 102.87 109.22 0) + (at 99.06 129.54 0) (effects (font (size 1.27 1.27) @@ -3962,7 +4431,7 @@ ) ) (property "Footprint" "Converter_DCDC:Converter_DCDC_TRACO_TDN_5-xxxxWISM_SMD" - (at 99.06 119.38 0) + (at 95.25 139.7 0) (effects (font (size 1.27 1.27) @@ -3971,7 +4440,7 @@ ) ) (property "Datasheet" "https://assets.tracopower.com/20190626081517/TDN5WISM/documents/tdn5wism-datasheet.pdf" - (at 101.6 119.38 0) + (at 97.79 139.7 0) (effects (font (size 1.27 1.27) @@ -3980,7 +4449,7 @@ ) ) (property "Description" "Input 9.0 to 36.0V, Output 5.0V" - (at 102.87 119.38 0) + (at 99.06 139.7 0) (effects (font (size 1.27 1.27) @@ -4017,7 +4486,7 @@ ) (symbol (lib_id "Connector_Generic:Conn_01x04") - (at 36.83 121.92 180) + (at 33.02 142.24 180) (unit 1) (exclude_from_sim no) (in_bom yes) @@ -4026,7 +4495,7 @@ (fields_autoplaced yes) (uuid "3c5d7c59-24a4-4ece-ac66-ba30bc309a63") (property "Reference" "J1" - (at 36.83 110.49 0) + (at 33.02 130.81 0) (effects (font (size 1.27 1.27) @@ -4034,7 +4503,7 @@ ) ) (property "Value" "Conn_Main_ADC" - (at 36.83 113.03 0) + (at 33.02 133.35 0) (effects (font (size 1.27 1.27) @@ -4042,7 +4511,7 @@ ) ) (property "Footprint" "" - (at 36.83 121.92 0) + (at 33.02 142.24 0) (effects (font (size 1.27 1.27) @@ -4051,7 +4520,7 @@ ) ) (property "Datasheet" "~" - (at 36.83 121.92 0) + (at 33.02 142.24 0) (effects (font (size 1.27 1.27) @@ -4060,7 +4529,7 @@ ) ) (property "Description" "Generic connector, single row, 01x04, script generated (kicad-library-utils/schlib/autogen/connector/)" - (at 36.83 121.92 0) + (at 33.02 142.24 0) (effects (font (size 1.27 1.27) @@ -4089,9 +4558,79 @@ ) ) ) + (symbol + (lib_id "Device:R") + (at 179.07 27.94 0) + (unit 1) + (exclude_from_sim no) + (in_bom yes) + (on_board yes) + (dnp no) + (fields_autoplaced yes) + (uuid "4c472f2e-285c-48e4-b410-987404ba7198") + (property "Reference" "R4" + (at 181.61 26.6699 0) + (effects + (font + (size 1.27 1.27) + ) + (justify left) + ) + ) + (property "Value" "4.7K" + (at 181.61 29.2099 0) + (effects + (font + (size 1.27 1.27) + ) + (justify left) + ) + ) + (property "Footprint" "" + (at 177.292 27.94 90) + (effects + (font + (size 1.27 1.27) + ) + (hide yes) + ) + ) + (property "Datasheet" "~" + (at 179.07 27.94 0) + (effects + (font + (size 1.27 1.27) + ) + (hide yes) + ) + ) + (property "Description" "Resistor" + (at 179.07 27.94 0) + (effects + (font + (size 1.27 1.27) + ) + (hide yes) + ) + ) + (pin "2" + (uuid "1f69a6e1-c869-48d4-982e-755995136538") + ) + (pin "1" + (uuid "db5f8bff-7dd3-458e-9516-b9a44d4afd64") + ) + (instances + (project "" + (path "/6ddf9647-3471-4724-9337-c9866d28db60" + (reference "R4") + (unit 1) + ) + ) + ) + ) (symbol (lib_id "power:GND") - (at 95.25 57.15 0) + (at 91.44 77.47 0) (unit 1) (exclude_from_sim no) (in_bom yes) @@ -4100,7 +4639,7 @@ (fields_autoplaced yes) (uuid "50b9ea7c-489d-45e6-a5ca-73d221e9f3a2") (property "Reference" "#PWR02" - (at 95.25 63.5 0) + (at 91.44 83.82 0) (effects (font (size 1.27 1.27) @@ -4109,7 +4648,7 @@ ) ) (property "Value" "GND" - (at 95.25 62.23 0) + (at 91.44 82.55 0) (effects (font (size 1.27 1.27) @@ -4117,7 +4656,7 @@ ) ) (property "Footprint" "" - (at 95.25 57.15 0) + (at 91.44 77.47 0) (effects (font (size 1.27 1.27) @@ -4126,7 +4665,7 @@ ) ) (property "Datasheet" "" - (at 95.25 57.15 0) + (at 91.44 77.47 0) (effects (font (size 1.27 1.27) @@ -4135,7 +4674,7 @@ ) ) (property "Description" "Power symbol creates a global label with name \"GND\" , ground" - (at 95.25 57.15 0) + (at 91.44 77.47 0) (effects (font (size 1.27 1.27) @@ -4157,7 +4696,7 @@ ) (symbol (lib_id "power:PWR_FLAG") - (at 76.2 57.15 180) + (at 72.39 77.47 180) (unit 1) (exclude_from_sim no) (in_bom yes) @@ -4166,7 +4705,7 @@ (fields_autoplaced yes) (uuid "5a4d6e9d-f4ee-4570-b7df-92ba386540f3") (property "Reference" "#FLG02" - (at 76.2 59.055 0) + (at 72.39 79.375 0) (effects (font (size 1.27 1.27) @@ -4175,7 +4714,7 @@ ) ) (property "Value" "PWR_FLAG" - (at 76.2 62.23 0) + (at 72.39 82.55 0) (effects (font (size 1.27 1.27) @@ -4183,7 +4722,7 @@ ) ) (property "Footprint" "" - (at 76.2 57.15 0) + (at 72.39 77.47 0) (effects (font (size 1.27 1.27) @@ -4192,7 +4731,7 @@ ) ) (property "Datasheet" "~" - (at 76.2 57.15 0) + (at 72.39 77.47 0) (effects (font (size 1.27 1.27) @@ -4201,7 +4740,7 @@ ) ) (property "Description" "Special symbol for telling ERC where power comes from" - (at 76.2 57.15 0) + (at 72.39 77.47 0) (effects (font (size 1.27 1.27) @@ -4223,7 +4762,7 @@ ) (symbol (lib_id "Connector_Generic:Conn_01x02") - (at 95.25 100.33 0) + (at 91.44 120.65 0) (unit 1) (exclude_from_sim no) (in_bom yes) @@ -4232,7 +4771,7 @@ (fields_autoplaced yes) (uuid "85b604fd-79b8-4cf8-b510-f1b20d050a78") (property "Reference" "J2" - (at 97.79 100.3299 0) + (at 93.98 120.6499 0) (effects (font (size 1.27 1.27) @@ -4241,7 +4780,7 @@ ) ) (property "Value" "Conn_Jetson" - (at 97.79 102.8699 0) + (at 93.98 123.1899 0) (effects (font (size 1.27 1.27) @@ -4250,7 +4789,7 @@ ) ) (property "Footprint" "" - (at 95.25 100.33 0) + (at 91.44 120.65 0) (effects (font (size 1.27 1.27) @@ -4259,7 +4798,7 @@ ) ) (property "Datasheet" "~" - (at 95.25 100.33 0) + (at 91.44 120.65 0) (effects (font (size 1.27 1.27) @@ -4268,7 +4807,7 @@ ) ) (property "Description" "Generic connector, single row, 01x02, script generated (kicad-library-utils/schlib/autogen/connector/)" - (at 95.25 100.33 0) + (at 91.44 120.65 0) (effects (font (size 1.27 1.27) @@ -4293,7 +4832,7 @@ ) (symbol (lib_id "Device:R") - (at 113.03 59.69 0) + (at 109.22 80.01 0) (unit 1) (exclude_from_sim no) (in_bom yes) @@ -4302,7 +4841,7 @@ (fields_autoplaced yes) (uuid "8a89d902-9ea0-4632-8e46-8b41baa36b78") (property "Reference" "R2" - (at 115.57 58.4199 0) + (at 111.76 78.7399 0) (effects (font (size 1.27 1.27) @@ -4310,8 +4849,8 @@ (justify left) ) ) - (property "Value" "10K" - (at 115.57 60.9599 0) + (property "Value" "20K" + (at 111.76 81.2799 0) (effects (font (size 1.27 1.27) @@ -4320,7 +4859,7 @@ ) ) (property "Footprint" "" - (at 111.252 59.69 90) + (at 107.442 80.01 90) (effects (font (size 1.27 1.27) @@ -4329,7 +4868,7 @@ ) ) (property "Datasheet" "~" - (at 113.03 59.69 0) + (at 109.22 80.01 0) (effects (font (size 1.27 1.27) @@ -4338,7 +4877,7 @@ ) ) (property "Description" "Resistor" - (at 113.03 59.69 0) + (at 109.22 80.01 0) (effects (font (size 1.27 1.27) @@ -4363,7 +4902,7 @@ ) (symbol (lib_id "power:PWR_FLAG") - (at 83.82 114.3 0) + (at 80.01 134.62 0) (unit 1) (exclude_from_sim no) (in_bom yes) @@ -4372,7 +4911,7 @@ (fields_autoplaced yes) (uuid "9c40cff0-b607-4da3-b6ba-80567f898804") (property "Reference" "#FLG03" - (at 83.82 112.395 0) + (at 80.01 132.715 0) (effects (font (size 1.27 1.27) @@ -4381,7 +4920,7 @@ ) ) (property "Value" "PWR_FLAG" - (at 83.82 109.22 0) + (at 80.01 129.54 0) (effects (font (size 1.27 1.27) @@ -4389,7 +4928,7 @@ ) ) (property "Footprint" "" - (at 83.82 114.3 0) + (at 80.01 134.62 0) (effects (font (size 1.27 1.27) @@ -4398,7 +4937,7 @@ ) ) (property "Datasheet" "~" - (at 83.82 114.3 0) + (at 80.01 134.62 0) (effects (font (size 1.27 1.27) @@ -4407,7 +4946,7 @@ ) ) (property "Description" "Special symbol for telling ERC where power comes from" - (at 83.82 114.3 0) + (at 80.01 134.62 0) (effects (font (size 1.27 1.27) @@ -4429,7 +4968,7 @@ ) (symbol (lib_id "power:PWR_FLAG") - (at 76.2 54.61 0) + (at 72.39 74.93 0) (unit 1) (exclude_from_sim no) (in_bom yes) @@ -4438,7 +4977,7 @@ (fields_autoplaced yes) (uuid "9fd1b447-4b5a-4c06-aa59-6fb2447b5b71") (property "Reference" "#FLG01" - (at 76.2 52.705 0) + (at 72.39 73.025 0) (effects (font (size 1.27 1.27) @@ -4447,7 +4986,7 @@ ) ) (property "Value" "PWR_FLAG" - (at 76.2 49.53 0) + (at 72.39 69.85 0) (effects (font (size 1.27 1.27) @@ -4455,7 +4994,7 @@ ) ) (property "Footprint" "" - (at 76.2 54.61 0) + (at 72.39 74.93 0) (effects (font (size 1.27 1.27) @@ -4464,7 +5003,7 @@ ) ) (property "Datasheet" "~" - (at 76.2 54.61 0) + (at 72.39 74.93 0) (effects (font (size 1.27 1.27) @@ -4473,7 +5012,7 @@ ) ) (property "Description" "Special symbol for telling ERC where power comes from" - (at 76.2 54.61 0) + (at 72.39 74.93 0) (effects (font (size 1.27 1.27) @@ -4493,9 +5032,162 @@ ) ) ) + (symbol + (lib_id "Analog_ADC:MCP3425Axx-xCH") + (at 154.94 36.83 0) + (unit 1) + (exclude_from_sim no) + (in_bom yes) + (on_board yes) + (dnp no) + (fields_autoplaced yes) + (uuid "aed20779-2506-4d83-9198-a0f0325570fe") + (property "Reference" "U3" + (at 157.1341 25.4 0) + (effects + (font + (size 1.27 1.27) + ) + (justify left) + ) + ) + (property "Value" "MCP3425_DIP" + (at 157.1341 27.94 0) + (effects + (font + (size 1.27 1.27) + ) + (justify left) + ) + ) + (property "Footprint" "Package_TO_SOT_SMD:SOT-23-6" + (at 171.45 44.45 0) + (effects + (font + (size 1.27 1.27) + (italic yes) + ) + (hide yes) + ) + ) + (property "Datasheet" "http://ww1.microchip.com/downloads/en/DeviceDoc/22072b.pdf" + (at 154.94 24.13 0) + (effects + (font + (size 1.27 1.27) + ) + (hide yes) + ) + ) + (property "Description" "https://akizukidenshi.com/catalog/g/g108018/" + (at 154.94 36.83 0) + (effects + (font + (size 1.27 1.27) + ) + (hide yes) + ) + ) + (pin "5" + (uuid "0bc61f16-8db2-4ee2-8eb3-dd550ff96a15") + ) + (pin "4" + (uuid "f1e5f97d-ec37-4926-b0eb-62f229f0fd57") + ) + (pin "2" + (uuid "6f856c81-5244-4bd5-ac7b-6bcc1b8d12c7") + ) + (pin "3" + (uuid "7609c776-f87f-45f8-9f3b-086021986cb1") + ) + (pin "1" + (uuid "610c2d17-a991-449a-b759-17eeae7b217e") + ) + (pin "6" + (uuid "b6b5d294-ed28-48ae-a0f9-7f49fb55d01b") + ) + (instances + (project "" + (path "/6ddf9647-3471-4724-9337-c9866d28db60" + (reference "U3") + (unit 1) + ) + ) + ) + ) + (symbol + (lib_id "Device:R") + (at 171.45 27.94 0) + (unit 1) + (exclude_from_sim no) + (in_bom yes) + (on_board yes) + (dnp no) + (fields_autoplaced yes) + (uuid "c01a9de1-72f1-40f7-ac5b-c87a38325512") + (property "Reference" "R3" + (at 173.99 26.6699 0) + (effects + (font + (size 1.27 1.27) + ) + (justify left) + ) + ) + (property "Value" "4.7K" + (at 173.99 29.2099 0) + (effects + (font + (size 1.27 1.27) + ) + (justify left) + ) + ) + (property "Footprint" "" + (at 169.672 27.94 90) + (effects + (font + (size 1.27 1.27) + ) + (hide yes) + ) + ) + (property "Datasheet" "~" + (at 171.45 27.94 0) + (effects + (font + (size 1.27 1.27) + ) + (hide yes) + ) + ) + (property "Description" "Resistor" + (at 171.45 27.94 0) + (effects + (font + (size 1.27 1.27) + ) + (hide yes) + ) + ) + (pin "2" + (uuid "953e2755-0c3f-457f-b710-f9aaff5d51d1") + ) + (pin "1" + (uuid "95304f10-f90a-4414-8b3a-25a998b754d2") + ) + (instances + (project "" + (path "/6ddf9647-3471-4724-9337-c9866d28db60" + (reference "R3") + (unit 1) + ) + ) + ) + ) (symbol (lib_id "Device:R") - (at 113.03 52.07 0) + (at 109.22 72.39 0) (unit 1) (exclude_from_sim no) (in_bom yes) @@ -4504,7 +5196,7 @@ (fields_autoplaced yes) (uuid "c3b1fd03-f480-4543-9b33-ccb4a3777c74") (property "Reference" "R1" - (at 115.57 50.7999 0) + (at 111.76 71.1199 0) (effects (font (size 1.27 1.27) @@ -4512,8 +5204,8 @@ (justify left) ) ) - (property "Value" "50K" - (at 115.57 53.3399 0) + (property "Value" "120K" + (at 111.76 73.6599 0) (effects (font (size 1.27 1.27) @@ -4522,7 +5214,7 @@ ) ) (property "Footprint" "" - (at 111.252 52.07 90) + (at 107.442 72.39 90) (effects (font (size 1.27 1.27) @@ -4531,7 +5223,7 @@ ) ) (property "Datasheet" "~" - (at 113.03 52.07 0) + (at 109.22 72.39 0) (effects (font (size 1.27 1.27) @@ -4540,7 +5232,7 @@ ) ) (property "Description" "Resistor" - (at 113.03 52.07 0) + (at 109.22 72.39 0) (effects (font (size 1.27 1.27) @@ -4565,7 +5257,7 @@ ) (symbol (lib_id "Connector:USB_A") - (at 176.53 137.16 90) + (at 172.72 158.75 90) (unit 1) (exclude_from_sim no) (in_bom yes) @@ -4574,7 +5266,7 @@ (fields_autoplaced yes) (uuid "c6b9985c-9dfd-45d9-a848-58e69ee3563d") (property "Reference" "J4" - (at 167.64 135.8899 90) + (at 163.83 157.4799 90) (effects (font (size 1.27 1.27) @@ -4583,7 +5275,7 @@ ) ) (property "Value" "USB_M5Stack_1" - (at 167.64 138.4299 90) + (at 163.83 160.0199 90) (effects (font (size 1.27 1.27) @@ -4592,7 +5284,7 @@ ) ) (property "Footprint" "" - (at 177.8 133.35 0) + (at 173.99 154.94 0) (effects (font (size 1.27 1.27) @@ -4601,7 +5293,7 @@ ) ) (property "Datasheet" "~" - (at 177.8 133.35 0) + (at 173.99 154.94 0) (effects (font (size 1.27 1.27) @@ -4610,7 +5302,7 @@ ) ) (property "Description" "USB Type A connector" - (at 176.53 137.16 0) + (at 172.72 158.75 0) (effects (font (size 1.27 1.27) @@ -4644,7 +5336,7 @@ ) (symbol (lib_id "Connector:USB_A") - (at 140.97 138.43 90) + (at 137.16 158.75 90) (unit 1) (exclude_from_sim no) (in_bom yes) @@ -4653,7 +5345,7 @@ (fields_autoplaced yes) (uuid "e6b20517-dea7-42df-955a-8453a907de55") (property "Reference" "J3" - (at 132.08 137.1599 90) + (at 128.27 157.4799 90) (effects (font (size 1.27 1.27) @@ -4662,7 +5354,7 @@ ) ) (property "Value" "USB_M5Stack_0" - (at 132.08 139.6999 90) + (at 128.27 160.0199 90) (effects (font (size 1.27 1.27) @@ -4671,7 +5363,7 @@ ) ) (property "Footprint" "" - (at 142.24 134.62 0) + (at 138.43 154.94 0) (effects (font (size 1.27 1.27) @@ -4680,7 +5372,7 @@ ) ) (property "Datasheet" "~" - (at 142.24 134.62 0) + (at 138.43 154.94 0) (effects (font (size 1.27 1.27) @@ -4689,7 +5381,7 @@ ) ) (property "Description" "USB Type A connector" - (at 140.97 138.43 0) + (at 137.16 158.75 0) (effects (font (size 1.27 1.27) @@ -4723,7 +5415,7 @@ ) (symbol (lib_id "power:+12V") - (at 95.25 54.61 0) + (at 91.44 74.93 0) (unit 1) (exclude_from_sim no) (in_bom yes) @@ -4731,7 +5423,7 @@ (dnp no) (uuid "f56ee1b7-51e2-4ce3-85bd-4f3f7517baaa") (property "Reference" "#PWR01" - (at 95.25 58.42 0) + (at 91.44 78.74 0) (effects (font (size 1.27 1.27) @@ -4740,7 +5432,7 @@ ) ) (property "Value" "+18V" - (at 95.25 49.53 0) + (at 91.44 69.85 0) (effects (font (size 1.27 1.27) @@ -4748,7 +5440,7 @@ ) ) (property "Footprint" "" - (at 95.25 54.61 0) + (at 91.44 74.93 0) (effects (font (size 1.27 1.27) @@ -4757,7 +5449,7 @@ ) ) (property "Datasheet" "" - (at 95.25 54.61 0) + (at 91.44 74.93 0) (effects (font (size 1.27 1.27) @@ -4766,7 +5458,7 @@ ) ) (property "Description" "Power symbol creates a global label with name \"+12V\"" - (at 95.25 54.61 0) + (at 91.44 74.93 0) (effects (font (size 1.27 1.27)