From 0238726e4919c3814702ad4ab53a003b598bab54 Mon Sep 17 00:00:00 2001 From: fanpt <320622572@qq.com> Date: Thu, 7 Nov 2024 14:10:26 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0ocr=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E6=97=A5=E5=BF=97=E6=89=93=E5=8D=B0=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- OCR_LLM_attribute/0_Ocr_txt_scripting.py | 67 +++++ README_api.md | 117 ++++---- .../SynthText_resnet18_FPN_DBhead_polyLR.yaml | 2 +- ...ar2015_dcn_resnet18_FPN_DBhead_polyLR.yaml | 2 +- .../icdar2015_resnet18_FPN_DBhead_polyLR.yaml | 2 +- ...5_resnet18_FPN_DBhead_polyLR_finetune.yaml | 2 +- .../icdar2015_resnet50_FPN_DBhead_polyLR.yaml | 2 +- ...ataset_dcn_resnet50_FPN_DBhead_polyLR.yaml | 2 +- ...n_dataset_resnest50_FPN_DBhead_polyLR.yaml | 2 +- ...en_dataset_resnet18_FPN_DBhead_polyLR.yaml | 2 +- benchmark/PaddleOCR_DBNet/tools/eval.py | 2 +- benchmark/PaddleOCR_DBNet/tools/infer.py | 14 +- benchmark/PaddleOCR_DBNet/tools/predict.py | 4 +- .../utils/ocr_metric/icdar2015/quad_metric.py | 2 +- .../cls/ch_PP-OCRv3/ch_PP-OCRv3_rotnet.yml | 4 +- configs/cls/cls_mv3.yml | 2 +- .../det/ch_PP-OCRv2/ch_PP-OCRv2_det_cml.yml | 4 +- .../ch_PP-OCRv2/ch_PP-OCRv2_det_distill.yml | 4 +- .../det/ch_PP-OCRv2/ch_PP-OCRv2_det_dml.yml | 4 +- .../ch_PP-OCRv2/ch_PP-OCRv2_det_student.yml | 4 +- .../det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml | 2 +- .../det/ch_PP-OCRv3/ch_PP-OCRv3_det_dml.yml | 4 +- .../ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml | 2 +- .../det/ch_PP-OCRv4/ch_PP-OCRv4_det_cml.yml | 2 +- .../ch_PP-OCRv4/ch_PP-OCRv4_det_student.yml | 2 +- .../ch_PP-OCRv4/ch_PP-OCRv4_det_teacher.yml | 2 +- .../det/ch_ppocr_v2.0/ch_det_mv3_db_v2.0.yml | 4 +- .../ch_ppocr_v2.0/ch_det_res18_db_v2.0.yml | 4 +- configs/det/det_mv3_db.yml | 4 +- configs/det/det_mv3_east.yml | 4 +- configs/det/det_mv3_pse.yml | 6 +- configs/det/det_r18_vd_ct.yml | 4 +- configs/det/det_r50_db++_icdar15.yml | 2 +- configs/det/det_r50_db++_td_tr.yml | 2 +- configs/det/det_r50_drrg_ctw.yml | 4 +- configs/det/det_r50_vd_db.yml | 4 +- configs/det/det_r50_vd_dcn_fce_ctw.yml | 4 +- configs/det/det_r50_vd_east.yml | 4 +- configs/det/det_r50_vd_pse.yml | 6 +- configs/det/det_r50_vd_sast_icdar15.yml | 4 +- configs/det/det_r50_vd_sast_totaltext.yml | 4 +- configs/det/det_repsvtr_db.yml | 2 +- configs/det/det_res18_db_v2.0.yml | 4 +- configs/e2e/e2e_r50_vd_pg.yml | 4 +- .../re_layoutlmv2_xfund_zh.yml | 4 +- .../layoutlm_series/re_layoutxlm_xfund_zh.yml | 4 +- .../layoutlm_series/ser_layoutlm_xfund_zh.yml | 4 +- .../ser_layoutlmv2_xfund_zh.yml | 4 +- .../ser_layoutxlm_xfund_zh.yml | 4 +- configs/kie/sdmgr/kie_unet_sdmgr.yml | 4 +- .../vi_layoutxlm/re_vi_layoutxlm_xfund_zh.yml | 4 +- .../re_vi_layoutxlm_xfund_zh_udml.yml | 4 +- .../ser_vi_layoutxlm_xfund_zh.yml | 4 +- .../ser_vi_layoutxlm_xfund_zh_udml.yml | 4 +- configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml | 4 +- .../PP-OCRv3/ch_PP-OCRv3_rec_distillation.yml | 4 +- configs/rec/PP-OCRv3/en_PP-OCRv3_rec.yml | 4 +- .../multi_language/arabic_PP-OCRv3_rec.yml | 4 +- .../chinese_cht_PP-OCRv3_rec.yml | 4 +- .../multi_language/cyrillic_PP-OCRv3_rec.yml | 4 +- .../devanagari_PP-OCRv3_rec.yml | 4 +- .../multi_language/japan_PP-OCRv3_rec.yml | 4 +- .../multi_language/ka_PP-OCRv3_rec.yml | 4 +- .../multi_language/korean_PP-OCRv3_rec.yml | 4 +- .../multi_language/latin_PP-OCRv3_rec.yml | 4 +- .../multi_language/ta_PP-OCRv3_rec.yml | 4 +- .../multi_language/te_PP-OCRv3_rec.yml | 4 +- configs/rec/PP-OCRv4/ch_PP-OCRv4_rec.yml | 4 +- .../PP-OCRv4/ch_PP-OCRv4_rec_ampO2_ultra.yml | 4 +- .../PP-OCRv4/ch_PP-OCRv4_rec_distillation.yml | 6 +- .../PP-OCRv4/ch_PP-OCRv4_rec_fp32_ultra.yml | 4 +- .../rec/PP-OCRv4/ch_PP-OCRv4_rec_hgnet.yml | 4 +- .../ch_PP-OCRv4_rec_hgnet_ampO2_ultra.yml | 4 +- .../ch_PP-OCRv4_rec_hgnet_fp32_ultra.yml | 4 +- .../PP-OCRv4/ch_PP-OCRv4_rec_svtr_large.yml | 4 +- configs/rec/PP-OCRv4/en_PP-OCRv4_rec.yml | 4 +- configs/rec/SVTRv2/rec_repsvtr_ch.yml | 4 +- configs/rec/SVTRv2/rec_repsvtr_gtc.yml | 4 +- configs/rec/SVTRv2/rec_svtrv2_ch.yml | 4 +- .../rec/SVTRv2/rec_svtrv2_ch_distillation.yml | 8 +- configs/rec/SVTRv2/rec_svtrv2_gtc.yml | 4 +- configs/rec/SVTRv2/rec_svtrv2_gtc_distill.yml | 8 +- configs/rec/ch_PP-OCRv2/ch_PP-OCRv2_rec.yml | 4 +- .../ch_PP-OCRv2_rec_distillation.yml | 4 +- .../ch_PP-OCRv2_rec_enhanced_ctc_loss.yml | 4 +- .../rec_chinese_common_train_v2.0.yml | 4 +- .../rec_chinese_lite_train_v2.0.yml | 4 +- .../generate_multi_language_configs.py | 2 +- .../multi_language/rec_arabic_lite_train.yml | 2 +- .../rec_cyrillic_lite_train.yml | 2 +- .../rec_devanagari_lite_train.yml | 2 +- .../rec_en_number_lite_train.yml | 2 +- .../multi_language/rec_french_lite_train.yml | 2 +- .../multi_language/rec_german_lite_train.yml | 2 +- .../multi_language/rec_japan_lite_train.yml | 2 +- .../multi_language/rec_korean_lite_train.yml | 2 +- .../multi_language/rec_latin_lite_train.yml | 2 +- .../rec_multi_language_lite_train.yml | 2 +- configs/rec/rec_d28_can.yml | 4 +- configs/rec/rec_efficientb3_fpn_pren.yml | 4 +- configs/rec/rec_icdar15_train.yml | 4 +- configs/rec/rec_latex_ocr.yml | 4 +- configs/rec/rec_mtb_nrtr.yml | 4 +- configs/rec/rec_mv3_none_bilstm_ctc.yml | 4 +- configs/rec/rec_mv3_none_none_ctc.yml | 4 +- configs/rec/rec_mv3_tps_bilstm_att.yml | 4 +- configs/rec/rec_mv3_tps_bilstm_ctc.yml | 4 +- configs/rec/rec_r31_robustscanner.yml | 4 +- configs/rec/rec_r31_sar.yml | 2 +- configs/rec/rec_r32_gaspin_bilstm_att.yml | 4 +- configs/rec/rec_r34_vd_none_bilstm_ctc.yml | 4 +- configs/rec/rec_r34_vd_none_none_ctc.yml | 4 +- configs/rec/rec_r34_vd_tps_bilstm_att.yml | 4 +- configs/rec/rec_r34_vd_tps_bilstm_ctc.yml | 4 +- configs/rec/rec_r45_abinet.yml | 6 +- configs/rec/rec_r45_visionlan.yml | 4 +- configs/rec/rec_r50_fpn_srn.yml | 4 +- configs/rec/rec_resnet_rfl_att.yml | 4 +- configs/rec/rec_resnet_rfl_visual.yml | 4 +- configs/rec/rec_resnet_stn_bilstm_att.yml | 4 +- configs/rec/rec_satrn.yml | 4 +- configs/rec/rec_svtrnet.yml | 4 +- configs/rec/rec_svtrnet_ch.yml | 4 +- configs/rec/rec_svtrnet_cppd_base_ch.yml | 4 +- configs/rec/rec_svtrnet_cppd_base_en.yml | 4 +- configs/rec/rec_vit_parseq.yml | 4 +- configs/rec/rec_vitstr_none_ce.yml | 4 +- configs/sr/sr_telescope.yml | 6 +- configs/sr/sr_tsrn_transformer_strock.yml | 4 +- configs/table/SLANet.yml | 6 +- configs/table/SLANet_ch.yml | 6 +- configs/table/SLANet_lcnetv2.yml | 4 +- configs/table/table_master.yml | 6 +- configs/table/table_mv3.yml | 4 +- deploy/avh/convert_image.py | 6 +- deploy/cpp_infer/readme.md | 6 +- deploy/cpp_infer/readme_ch.md | 6 +- deploy/fastdeploy/ascend/python/infer.py | 2 +- deploy/fastdeploy/kunlunxin/python/infer.py | 2 +- .../models/cls_postprocess/1/model.py | 6 +- .../models/det_postprocess/1/model.py | 10 +- .../models/det_preprocess/1/model.py | 6 +- .../models/rec_postprocess/1/model.py | 6 +- deploy/hubserving/structure_system/params.py | 2 +- deploy/paddlecloud/README.md | 6 +- deploy/pdserving/ocr_reader.py | 2 +- deploy/pdserving/win/ocr_reader.py | 2 +- deploy/slim/auto_compression/run.py | 2 +- deploy/slim/prune/README.md | 4 +- deploy/slim/prune/README_en.md | 4 +- deploy/slim/quantization/README.md | 2 +- deploy/slim/quantization/README_en.md | 2 +- doc/doc_ch/algorithm_kie_sdmgr.md | 2 +- doc/doc_ch/algorithm_rec_rfl.md | 10 +- doc/doc_ch/algorithm_table_master.md | 6 +- doc/doc_ch/detection.md | 2 +- doc/doc_ch/kie.md | 10 +- doc/doc_en/algorithm_kie_sdmgr_en.md | 4 +- doc/doc_en/algorithm_sdmgr_en.md | 4 +- doc/doc_en/algorithm_table_master_en.md | 6 +- doc/doc_en/kie_en.md | 12 +- doc/doc_en/knowledge_distillation_en.md | 16 +- .../algorithm_rec_can.en.md | 2 +- docs/algorithm/kie/algorithm_kie_sdmgr.en.md | 4 +- docs/algorithm/kie/algorithm_kie_sdmgr.md | 4 +- .../algorithm_table_master.en.md | 6 +- .../algorithm_table_master.md | 6 +- .../algorithm_table_slanet.md | 4 +- .../text_recognition/algorithm_rec_rfl.md | 10 +- .../text_recognition/algorithm_rec_svtrv2.md | 6 +- docs/applications/PCB字符识别.md | 6 +- docs/applications/中文表格识别.md | 16 +- docs/applications/包装生产日期识别.md | 4 +- docs/applications/印章弯曲文字识别.md | 2 +- docs/applications/多模态表单识别.md | 12 +- docs/applications/手写文字识别.md | 2 +- docs/applications/液晶屏读数识别.md | 16 +- docs/applications/轻量级车牌识别.md | 60 ++--- docs/javascripts/katex.min.js | 2 +- docs/ppocr/infer_deploy/cpp_infer.en.md | 6 +- docs/ppocr/infer_deploy/cpp_infer.md | 6 +- docs/ppocr/infer_deploy/paddle_cloud.md | 6 +- .../knowledge_distillation.en.md | 18 +- docs/ppocr/model_compress/prune.en.md | 4 +- docs/ppocr/model_compress/prune.md | 4 +- docs/ppocr/model_compress/quantization.en.md | 4 +- docs/ppocr/model_compress/quantization.md | 4 +- .../ppocr/model_train/PPOCRv3_det_train.en.md | 24 +- docs/ppocr/model_train/PPOCRv3_det_train.md | 24 +- docs/ppocr/model_train/detection.md | 2 +- docs/ppocr/model_train/kie.en.md | 16 +- docs/ppocr/model_train/kie.md | 16 +- docs/ppstructure/blog/return_word_pos.en.md | 4 +- docs/ppstructure/blog/return_word_pos.md | 4 +- docs/ppstructure/infer_deploy/cpp_infer.en.md | 6 +- docs/ppstructure/infer_deploy/cpp_infer.md | 6 +- .../infer_deploy/python_infer.en.md | 6 +- docs/ppstructure/infer_deploy/python_infer.md | 6 +- .../model_train/recovery_to_doc.en.md | 4 +- .../model_train/recovery_to_doc.md | 4 +- .../model_train/train_layout.en.md | 12 +- docs/ppstructure/model_train/train_layout.md | 12 +- .../ppstructure/model_train/train_table.en.md | 2 +- docs/ppstructure/model_train/train_table.md | 2 +- docs/ppstructure/quick_start.en.md | 14 +- docs/ppstructure/quick_start.md | 14 +- ocr_api.py | 255 ++++++++++++++---- ppocr/data/imaug/drrg_targets.py | 2 +- ppocr/data/imaug/fce_targets.py | 2 +- ppocr/data/imaug/label_ops.py | 2 +- .../backbones/rec_efficientb3_pren.py | 2 +- ppocr/modeling/backbones/rec_resnet_31.py | 2 +- ppocr/modeling/backbones/rec_resnet_32.py | 6 +- ppocr/modeling/backbones/rec_resnet_fpn.py | 6 +- ppocr/modeling/backbones/rec_resnet_rfl.py | 2 +- ppocr/modeling/heads/local_graph.py | 2 +- ppocr/modeling/heads/rec_aster_head.py | 8 +- ppocr/modeling/heads/rec_nrtr_head.py | 10 +- .../modeling/heads/rec_robustscanner_head.py | 50 ++-- ppocr/modeling/heads/rec_visionlan_head.py | 6 +- ppocr/modeling/heads/self_attention.py | 2 +- ppocr/modeling/heads/table_att_head.py | 2 +- ppocr/modeling/necks/csp_pan.py | 10 +- ppocr/modeling/necks/fce_fpn.py | 6 +- ppocr/modeling/necks/rf_adaptor.py | 2 +- ppocr/modeling/necks/rnn.py | 2 +- ppocr/postprocess/fce_postprocess.py | 2 +- ppocr/postprocess/picodet_postprocess.py | 2 +- ppocr/utils/profiler.py | 2 +- ppstructure/docs/inference.md | 6 +- ppstructure/docs/inference_en.md | 6 +- ppstructure/docs/quickstart.md | 14 +- ppstructure/docs/quickstart_en.md | 14 +- .../kie/tools/eval_with_label_end2end.py | 2 +- ppstructure/layout/README.md | 8 +- ppstructure/layout/README_ch.md | 8 +- ppstructure/pdf2word/pdf2word.py | 8 +- ppstructure/recovery/README.md | 4 +- ppstructure/recovery/README_ch.md | 4 +- ppstructure/return_word_pos.md | 4 +- ppstructure/table/table_master_match.py | 4 +- .../table/table_metric/table_metric.py | 2 +- ppstructure/utility.py | 4 +- test_tipc/compare_results.py | 2 +- .../ch_PP-OCRv2_rec_distillation.yml | 4 +- .../ch_PP-OCRv3_rec_distillation.yml | 4 +- .../rec_chinese_lite_train_v2.0.yml | 4 +- .../rec_chinese_lite_train_v2.0.yml | 4 +- .../rec_chinese_lite_train_v2.0.yml | 4 +- .../det_r50_vd_db.yml | 4 +- .../rec_icdar15_train.yml | 4 +- .../det_mv3_east_v2_0/det_mv3_east.yml | 4 +- .../configs/det_mv3_pse_v2_0/det_mv3_pse.yml | 6 +- .../det_r50_vd_dcn_fce_ctw.yml | 4 +- .../det_r50_vd_east_v2_0/det_r50_vd_east.yml | 4 +- .../det_r50_vd_pse_v2_0/det_r50_vd_pse.yml | 6 +- .../det_r50_vd_sast_icdar2015.yml | 4 +- .../det_r50_vd_sast_totaltext.yml | 4 +- .../layoutxlm_ser/ser_layoutxlm_xfund_zh.yml | 4 +- test_tipc/configs/rec_d28_can/rec_d28_can.yml | 4 +- .../configs/rec_mtb_nrtr/rec_mtb_nrtr.yml | 4 +- .../rec_icdar15_train.yml | 4 +- .../rec_icdar15_train.yml | 4 +- .../rec_mv3_tps_bilstm_att.yml | 4 +- .../rec_icdar15_train.yml | 4 +- .../configs/rec_parseq/rec_vit_parseq.yml | 4 +- .../rec_r31_robustscanner.yml | 4 +- test_tipc/configs/rec_r31_sar/rec_r31_sar.yml | 2 +- .../rec_r32_gaspin_bilstm_att.yml | 4 +- .../rec_icdar15_train.yml | 4 +- .../rec_icdar15_train.yml | 4 +- .../rec_r34_vd_tps_bilstm_att.yml | 4 +- .../rec_icdar15_train.yml | 4 +- .../configs/rec_r45_abinet/rec_r45_abinet.yml | 4 +- .../rec_r45_visionlan/rec_r45_visionlan.yml | 4 +- .../rec_r50_fpn_srn.yml | 4 +- .../configs/rec_resnet_rfl/rec_resnet_rfl.yml | 4 +- test_tipc/configs/rec_svtrnet/rec_svtrnet.yml | 4 +- .../rec_vitstr_none_ce/rec_vitstr_none_ce.yml | 4 +- .../configs/sr_telescope/sr_telescope.yml | 6 +- .../configs/table_master/table_master.yml | 6 +- .../jeston_test_train_inference_python.md | 2 +- .../docs/mac_test_train_inference_python.md | 2 +- test_tipc/docs/test_inference_cpp.md | 4 +- .../docs/test_train_fleet_inference_python.md | 4 +- test_tipc/docs/test_train_inference_python.md | 2 +- .../docs/win_test_train_inference_python.md | 2 +- test_tipc/supplementary/metric.py | 2 +- test_tipc/supplementary/mv3_distill.yml | 2 +- test_tipc/supplementary/mv3_large_x0_5.yml | 4 +- tools/infer/predict_system_1.py | 129 +++++++-- tools/infer/utility.py | 2 +- tools/infer_kie.py | 2 +- tools/infer_rec.py | 2 +- tools/test_hubserving.py | 2 +- tst.py | 31 --- 296 files changed, 1157 insertions(+), 888 deletions(-) create mode 100644 OCR_LLM_attribute/0_Ocr_txt_scripting.py delete mode 100644 tst.py diff --git a/OCR_LLM_attribute/0_Ocr_txt_scripting.py b/OCR_LLM_attribute/0_Ocr_txt_scripting.py new file mode 100644 index 0000000..10c239f --- /dev/null +++ b/OCR_LLM_attribute/0_Ocr_txt_scripting.py @@ -0,0 +1,67 @@ +import os +import subprocess +import json + + +def process_images_in_folder(image_folder, output_json_file): + results = [] # 用于存储所有图片的识别结果 + + # 使用 os.walk 遍历文件夹及其子文件夹 + for root, dirs, files in os.walk(image_folder): + for image_file in files: + # 获取每个图片的完整路径 + temp_image_file = os.path.join(root, image_file) + + # 检查是否为图片文件 + if os.path.splitext(image_file)[-1].lower() in ['.jpg', '.jpeg', '.png', '.gif', '.bmp']: + # 构造命令,调用 `predict_system_1.py` 进行处理 + command = [ + 'python', 'tools/infer/predict_system_1.py', + '--use_gpu=False', + '--cls_model_dir=./models/cls', + '--rec_model_dir=./models/rec', + '--det_model_dir=./models/det', + f'--image_dir={temp_image_file}' + ] + + try: + # 执行命令,指定 UTF-8 编码并捕获输出 + result = subprocess.run(command, capture_output=True, text=True, encoding='utf-8') + + # 检查命令是否成功执行 + if result.returncode == 0: + ocr_result = result.stdout.strip() # 获取识别结果 + else: + ocr_result = f"识别失败,返回代码: {result.returncode}" + + # 将结果保存为字典格式,添加到结果列表中 + results.append({ + "图片名称": image_file, + "文件路径": temp_image_file, + "识别结果": ocr_result + }) + + except Exception as e: + # 捕获处理图片时的错误并存储 + results.append({ + "图片名称": image_file, + "文件路径": temp_image_file, + "识别结果": f"处理图片时发生错误: {str(e)}" + }) + + # 将结果保存到指定的 JSON 文件 + with open(output_json_file, 'w', encoding='utf-8') as f: + json.dump(results, f, ensure_ascii=False, indent=4) # 使用 UTF-8 保存 JSON 文件 + print(f"识别结果已保存到 {output_json_file}") + + +if __name__ == "__main__": + # 设置待处理图片所在的文件夹路径 + # image_folder = r"E:\Project\PaddleOcr_v4\contract" + image_folder = r"E:\Project\PaddleOcr_v4\OCR_LLM_attribute\output_2\MaiMaiHeTong" + # 设置输出 JSON 文件的路径 + output_json_file = r"E:\Project\PaddleOcr_v4\OCR_LLM_attribute\output_2\MaiMaiHeTong_results.json" + + # 调用函数处理图片并保存结果 + process_images_in_folder(image_folder, output_json_file) + diff --git a/README_api.md b/README_api.md index e63768d..0329786 100644 --- a/README_api.md +++ b/README_api.md @@ -1,81 +1,80 @@ +## API 文档 ---- +### OCR 接口 -# OCR API 文档 +**接口地址:** `/ocr` -## 概述 +**请求方法:** `POST` -该API提供了图片文字识别服务(OCR)。客户端可以通过POST请求将图片以Base64编码格式上传到服务器,服务器将返回识别出的文本内容。 +**描述:** 处理一组图像文件进行 OCR(光学字符识别)并返回结果。 -- **服务地址**: `http://192.168.10.137:8866/ocr` -- **请求方法**: `POST` -- **请求格式**: JSON -- **响应格式**: JSON +**请求体:** +- `file_ids` (List\[str\]): 要处理的文件 ID 列表。 +- `suffix` (str): 图像文件的后缀(例如 "jpg", "png")。 -## 请求说明 - -### 请求URL - -`POST http://192.168.10.137:8866/ocr` - -### 请求头 - -- `Content-Type`: `application/json` - -### 请求参数 - -请求主体应包含一个JSON数组,每个元素代表一张待处理的图片。 - -| 字段名 | 类型 | 必填 | 描述 | -| ------ | ---- | ---- | ---- | -| pic_id | int | 是 | 图片的唯一标识符,应为整数。 | -| pic | str | 是 | 图片的Base64编码字符串。| +**请求示例:** +```json +{ + "file_ids": ["file1", "file2"], + "suffix": "jpg" +} +``` -#### 请求示例 +**响应:** +- `file_id` (str): 处理后的文件 ID。 +- `draw_img_id` (str): 带有绘制结果的图像 ID。 +- `ocr_text` (str): 从图像中提取的 OCR 文本。 +- `status` (int): 状态码(0 表示成功,2 表示失败)。 +- `error_msg` (str, 可选): 如果处理失败的错误信息。 +**响应示例:** ```json [ - { - "pic_id": 1234567890, - "pic": "/9j/4AAQSkZJRgABAQEAYABgAAD/4QAiRXhpZgAATU0AKgAAAAgABgESAAMAAAABAAEA..." - }, - { - "pic_id": 2345678901, - "pic": "/9j/4AAQSkZJRgABAQEAYABgAAD/4QAiRXhpZgAATU0AKgAAAAgABgESAAMAAAABAAEA..." - } + { + "file_id": "file1", + "draw_img_id": "processed_file1", + "ocr_text": "提取的文本", + "status": 0, + "error_msg": "" + }, + { + "file_id": "file2", + "draw_img_id": "", + "ocr_text": "", + "status": 2, + "error_msg": "错误信息" + } ] ``` -## 响应说明 +### 获取标题接口 -### 响应体 +**接口地址:** `/get-title` -服务器将返回一个JSON数组,其中每个元素对应于请求中的一张图片。 +**请求方法:** `POST` -| 字段名 | 类型 | 描述 | -| ------ | ---- | ---- | -| pic_id | int | 图片的唯一标识符,与请求中的`pic_id`一致。 | -| pic_txt| str | 识别出的文本内容。如果识别失败,该字段为空字符串。 | -| code | int | 状态码,`200`表示成功,`500`表示失败。| +**描述:** 使用模型 API 从提供的文本中提取标题。 -#### 响应示例 +**请求体:** +- `text` (str): 要从中提取标题的文本。 +**请求示例:** ```json -[ - { - "pic_id": 1234567890, - "pic_txt": "This is the recognized text from the image.", - "code": 200 - }, - { - "pic_id": 2345678901, - "pic_txt": "", - "code": 500 - } -] +{ + "text": "这是一个示例文本,用于提取标题。" +} ``` -## 错误处理 - -- **500 Internal Server Error**: 如果服务器在处理过程中遇到错误(例如,图片解析失败或OCR工具运行出错),将返回状态码500,`pic_txt`字段为空字符串。 +**响应:** +- `title` (str): 提取的标题。 +- `status` (int): 状态码(0 表示成功,2 表示失败)。 +- `error_msg` (str, 可选): 如果提取失败的错误信息。 +**响应示例:** +```json +{ + "title": "示例标题", + "status": 0, + "error_msg": "" +} +``` \ No newline at end of file diff --git a/benchmark/PaddleOCR_DBNet/config/SynthText_resnet18_FPN_DBhead_polyLR.yaml b/benchmark/PaddleOCR_DBNet/config/SynthText_resnet18_FPN_DBhead_polyLR.yaml index c285d36..93d6bfc 100644 --- a/benchmark/PaddleOCR_DBNet/config/SynthText_resnet18_FPN_DBhead_polyLR.yaml +++ b/benchmark/PaddleOCR_DBNet/config/SynthText_resnet18_FPN_DBhead_polyLR.yaml @@ -45,7 +45,7 @@ trainer: show_images_iter: 50 resume_checkpoint: '' finetune_checkpoint: '' - output_dir: output + output_dir: json visual_dl: false amp: scale_loss: 1024 diff --git a/benchmark/PaddleOCR_DBNet/config/icdar2015_dcn_resnet18_FPN_DBhead_polyLR.yaml b/benchmark/PaddleOCR_DBNet/config/icdar2015_dcn_resnet18_FPN_DBhead_polyLR.yaml index 3e24428..21eb3e6 100644 --- a/benchmark/PaddleOCR_DBNet/config/icdar2015_dcn_resnet18_FPN_DBhead_polyLR.yaml +++ b/benchmark/PaddleOCR_DBNet/config/icdar2015_dcn_resnet18_FPN_DBhead_polyLR.yaml @@ -45,7 +45,7 @@ trainer: show_images_iter: 50 resume_checkpoint: '' finetune_checkpoint: '' - output_dir: output + output_dir: json visual_dl: false amp: scale_loss: 1024 diff --git a/benchmark/PaddleOCR_DBNet/config/icdar2015_resnet18_FPN_DBhead_polyLR.yaml b/benchmark/PaddleOCR_DBNet/config/icdar2015_resnet18_FPN_DBhead_polyLR.yaml index 62c392b..0ad63b4 100644 --- a/benchmark/PaddleOCR_DBNet/config/icdar2015_resnet18_FPN_DBhead_polyLR.yaml +++ b/benchmark/PaddleOCR_DBNet/config/icdar2015_resnet18_FPN_DBhead_polyLR.yaml @@ -45,7 +45,7 @@ trainer: show_images_iter: 50 resume_checkpoint: '' finetune_checkpoint: '' - output_dir: output + output_dir: json visual_dl: false amp: scale_loss: 1024 diff --git a/benchmark/PaddleOCR_DBNet/config/icdar2015_resnet18_FPN_DBhead_polyLR_finetune.yaml b/benchmark/PaddleOCR_DBNet/config/icdar2015_resnet18_FPN_DBhead_polyLR_finetune.yaml index 9b018d5..d32f5d1 100644 --- a/benchmark/PaddleOCR_DBNet/config/icdar2015_resnet18_FPN_DBhead_polyLR_finetune.yaml +++ b/benchmark/PaddleOCR_DBNet/config/icdar2015_resnet18_FPN_DBhead_polyLR_finetune.yaml @@ -46,7 +46,7 @@ trainer: show_images_iter: 50 resume_checkpoint: '' finetune_checkpoint: '' - output_dir: output + output_dir: json visual_dl: false amp: scale_loss: 1024 diff --git a/benchmark/PaddleOCR_DBNet/config/icdar2015_resnet50_FPN_DBhead_polyLR.yaml b/benchmark/PaddleOCR_DBNet/config/icdar2015_resnet50_FPN_DBhead_polyLR.yaml index 2a870fd..3219d68 100644 --- a/benchmark/PaddleOCR_DBNet/config/icdar2015_resnet50_FPN_DBhead_polyLR.yaml +++ b/benchmark/PaddleOCR_DBNet/config/icdar2015_resnet50_FPN_DBhead_polyLR.yaml @@ -42,7 +42,7 @@ trainer: show_images_iter: 50 resume_checkpoint: '' finetune_checkpoint: '' - output_dir: output/fp16_o2 + output_dir: json/fp16_o2 visual_dl: false amp: scale_loss: 1024 diff --git a/benchmark/PaddleOCR_DBNet/config/open_dataset_dcn_resnet50_FPN_DBhead_polyLR.yaml b/benchmark/PaddleOCR_DBNet/config/open_dataset_dcn_resnet50_FPN_DBhead_polyLR.yaml index 6c81738..07d3eee 100644 --- a/benchmark/PaddleOCR_DBNet/config/open_dataset_dcn_resnet50_FPN_DBhead_polyLR.yaml +++ b/benchmark/PaddleOCR_DBNet/config/open_dataset_dcn_resnet50_FPN_DBhead_polyLR.yaml @@ -45,7 +45,7 @@ trainer: show_images_iter: 1 resume_checkpoint: '' finetune_checkpoint: '' - output_dir: output + output_dir: json visual_dl: false amp: scale_loss: 1024 diff --git a/benchmark/PaddleOCR_DBNet/config/open_dataset_resnest50_FPN_DBhead_polyLR.yaml b/benchmark/PaddleOCR_DBNet/config/open_dataset_resnest50_FPN_DBhead_polyLR.yaml index d47ab06..c321bb7 100644 --- a/benchmark/PaddleOCR_DBNet/config/open_dataset_resnest50_FPN_DBhead_polyLR.yaml +++ b/benchmark/PaddleOCR_DBNet/config/open_dataset_resnest50_FPN_DBhead_polyLR.yaml @@ -45,7 +45,7 @@ trainer: show_images_iter: 1 resume_checkpoint: '' finetune_checkpoint: '' - output_dir: output + output_dir: json visual_dl: false amp: scale_loss: 1024 diff --git a/benchmark/PaddleOCR_DBNet/config/open_dataset_resnet18_FPN_DBhead_polyLR.yaml b/benchmark/PaddleOCR_DBNet/config/open_dataset_resnet18_FPN_DBhead_polyLR.yaml index ff16ddb..a00f54e 100644 --- a/benchmark/PaddleOCR_DBNet/config/open_dataset_resnet18_FPN_DBhead_polyLR.yaml +++ b/benchmark/PaddleOCR_DBNet/config/open_dataset_resnet18_FPN_DBhead_polyLR.yaml @@ -45,7 +45,7 @@ trainer: show_images_iter: 1 resume_checkpoint: '' finetune_checkpoint: '' - output_dir: output + output_dir: json visual_dl: false amp: scale_loss: 1024 diff --git a/benchmark/PaddleOCR_DBNet/tools/eval.py b/benchmark/PaddleOCR_DBNet/tools/eval.py index 191e5af..55f3a85 100644 --- a/benchmark/PaddleOCR_DBNet/tools/eval.py +++ b/benchmark/PaddleOCR_DBNet/tools/eval.py @@ -79,7 +79,7 @@ def init_args(): parser.add_argument( "--model_path", required=False, - default="output/DBNet_resnet18_FPN_DBHead/checkpoint/1.pth", + default="json/DBNet_resnet18_FPN_DBHead/checkpoint/1.pth", type=str, ) args = parser.parse_args() diff --git a/benchmark/PaddleOCR_DBNet/tools/infer.py b/benchmark/PaddleOCR_DBNet/tools/infer.py index 1ca4bef..0a0816e 100644 --- a/benchmark/PaddleOCR_DBNet/tools/infer.py +++ b/benchmark/PaddleOCR_DBNet/tools/infer.py @@ -152,7 +152,7 @@ class InferenceEngine(object): # create predictor predictor = inference.create_predictor(config) - # get input and output tensor property + # get input and json tensor property input_names = predictor.get_input_names() input_tensor = predictor.get_input_handle(input_names[0]) @@ -179,9 +179,9 @@ class InferenceEngine(object): def postprocess(self, x, shape_info, is_output_polygon): """postprocess - Postprocess to the inference engine output. + Postprocess to the inference engine json. Args: - x: Inference engine output. + x: Inference engine json. Returns: Output data after argmax. """ box_list, score_list = self.post_process( @@ -207,7 +207,7 @@ class InferenceEngine(object): Inference process using inference engine. Args: x: Input data after preprocess. - Returns: Inference engine output + Returns: Inference engine json """ self.input_tensor.copy_from_cpu(x) self.predictor.run() @@ -235,7 +235,7 @@ def get_args(add_help=True): parser.add_argument("--benchmark", default=False, type=str2bool, help="benchmark") parser.add_argument("--warmup", default=0, type=int, help="warmup iter") - parser.add_argument("--polygon", action="store_true", help="output polygon or box") + parser.add_argument("--polygon", action="store_true", help="json polygon or box") parser.add_argument("--use_gpu", type=str2bool, default=True) parser.add_argument("--use_tensorrt", type=str2bool, default=False) @@ -298,9 +298,9 @@ def main(args): img = draw_bbox(cv2.imread(args.img_path)[:, :, ::-1], box_list) # 保存结果到路径 - os.makedirs("output", exist_ok=True) + os.makedirs("json", exist_ok=True) img_path = pathlib.Path(args.img_path) - output_path = os.path.join("output", img_path.stem + "_infer_result.jpg") + output_path = os.path.join("json", img_path.stem + "_infer_result.jpg") cv2.imwrite(output_path, img[:, :, ::-1]) save_result( output_path.replace("_infer_result.jpg", ".txt"), diff --git a/benchmark/PaddleOCR_DBNet/tools/predict.py b/benchmark/PaddleOCR_DBNet/tools/predict.py index 16d8d97..db66e33 100644 --- a/benchmark/PaddleOCR_DBNet/tools/predict.py +++ b/benchmark/PaddleOCR_DBNet/tools/predict.py @@ -125,13 +125,13 @@ def init_args(): "--input_folder", default="./test/input", type=str, help="Crop_img path for predict" ) parser.add_argument( - "--output_folder", default="./test/output", type=str, help="Crop_img path for output" + "--output_folder", default="./test/json", type=str, help="Crop_img path for json" ) parser.add_argument("--gpu", default=0, type=int, help="gpu for inference") parser.add_argument( "--thre", default=0.3, type=float, help="the thresh of post_processing" ) - parser.add_argument("--polygon", action="store_true", help="output polygon or box") + parser.add_argument("--polygon", action="store_true", help="json polygon or box") parser.add_argument("--show", action="store_true", help="show result") parser.add_argument( "--save_result", action="store_true", help="save box and score to txt file" diff --git a/benchmark/PaddleOCR_DBNet/utils/ocr_metric/icdar2015/quad_metric.py b/benchmark/PaddleOCR_DBNet/utils/ocr_metric/icdar2015/quad_metric.py index b4b6714..11a1720 100644 --- a/benchmark/PaddleOCR_DBNet/utils/ocr_metric/icdar2015/quad_metric.py +++ b/benchmark/PaddleOCR_DBNet/utils/ocr_metric/icdar2015/quad_metric.py @@ -37,7 +37,7 @@ class QuadMetric: ignore_tags: tensor of shape (N, K), indicates whether a region is ignorable or not. shape: the original shape of images. filename: the original filenames of images. - output: (polygons, ...) + json: (polygons, ...) """ results = [] gt_polyons_batch = batch["text_polys"] diff --git a/configs/cls/ch_PP-OCRv3/ch_PP-OCRv3_rotnet.yml b/configs/cls/ch_PP-OCRv3/ch_PP-OCRv3_rotnet.yml index f7e327d..f00c253 100644 --- a/configs/cls/ch_PP-OCRv3/ch_PP-OCRv3_rotnet.yml +++ b/configs/cls/ch_PP-OCRv3/ch_PP-OCRv3_rotnet.yml @@ -4,7 +4,7 @@ Global: epoch_num: 100 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec_ppocr_v3_rotnet + save_model_dir: ./json/rec_ppocr_v3_rotnet save_epoch_step: 3 eval_batch_step: [0, 2000] cal_metric_during_train: true @@ -17,7 +17,7 @@ Global: max_text_length: 25 infer_mode: false use_space_char: true - save_res_path: ./output/rec/predicts_chinese_lite_v2.0.txt + save_res_path: ./json/rec/predicts_chinese_lite_v2.0.txt Optimizer: name: Adam beta1: 0.9 diff --git a/configs/cls/cls_mv3.yml b/configs/cls/cls_mv3.yml index 0c46ff5..e65a479 100644 --- a/configs/cls/cls_mv3.yml +++ b/configs/cls/cls_mv3.yml @@ -3,7 +3,7 @@ Global: epoch_num: 100 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/cls/mv3/ + save_model_dir: ./json/cls/mv3/ save_epoch_step: 3 # evaluation is run every 5000 iterations after the 4000th iteration eval_batch_step: [0, 1000] diff --git a/configs/det/ch_PP-OCRv2/ch_PP-OCRv2_det_cml.yml b/configs/det/ch_PP-OCRv2/ch_PP-OCRv2_det_cml.yml index d35e08a..18a809e 100644 --- a/configs/det/ch_PP-OCRv2/ch_PP-OCRv2_det_cml.yml +++ b/configs/det/ch_PP-OCRv2/ch_PP-OCRv2_det_cml.yml @@ -3,7 +3,7 @@ Global: epoch_num: 1200 log_smooth_window: 20 print_batch_step: 2 - save_model_dir: ./output/ch_db_mv3/ + save_model_dir: ./json/ch_db_mv3/ save_epoch_step: 1200 # evaluation is run every 5000 iterations after the 4000th iteration eval_batch_step: [3000, 2000] @@ -13,7 +13,7 @@ Global: save_inference_dir: use_visualdl: False infer_img: doc/imgs_en/img_10.jpg - save_res_path: ./output/det_db/predicts_db.txt + save_res_path: ./json/det_db/predicts_db.txt use_amp: False amp_level: O2 amp_dtype: bfloat16 diff --git a/configs/det/ch_PP-OCRv2/ch_PP-OCRv2_det_distill.yml b/configs/det/ch_PP-OCRv2/ch_PP-OCRv2_det_distill.yml index d24ee11..d3c78d4 100644 --- a/configs/det/ch_PP-OCRv2/ch_PP-OCRv2_det_distill.yml +++ b/configs/det/ch_PP-OCRv2/ch_PP-OCRv2_det_distill.yml @@ -3,7 +3,7 @@ Global: epoch_num: 1200 log_smooth_window: 20 print_batch_step: 2 - save_model_dir: ./output/ch_db_mv3/ + save_model_dir: ./json/ch_db_mv3/ save_epoch_step: 1200 # evaluation is run every 5000 iterations after the 4000th iteration eval_batch_step: [3000, 2000] @@ -13,7 +13,7 @@ Global: save_inference_dir: use_visualdl: False infer_img: doc/imgs_en/img_10.jpg - save_res_path: ./output/det_db/predicts_db.txt + save_res_path: ./json/det_db/predicts_db.txt Architecture: name: DistillationModel diff --git a/configs/det/ch_PP-OCRv2/ch_PP-OCRv2_det_dml.yml b/configs/det/ch_PP-OCRv2/ch_PP-OCRv2_det_dml.yml index 8b160f6..ebbb849 100644 --- a/configs/det/ch_PP-OCRv2/ch_PP-OCRv2_det_dml.yml +++ b/configs/det/ch_PP-OCRv2/ch_PP-OCRv2_det_dml.yml @@ -3,7 +3,7 @@ Global: epoch_num: 1200 log_smooth_window: 20 print_batch_step: 2 - save_model_dir: ./output/ch_db_mv3/ + save_model_dir: ./json/ch_db_mv3/ save_epoch_step: 1200 # evaluation is run every 5000 iterations after the 4000th iteration eval_batch_step: [3000, 2000] @@ -13,7 +13,7 @@ Global: save_inference_dir: use_visualdl: False infer_img: doc/imgs_en/img_10.jpg - save_res_path: ./output/det_db/predicts_db.txt + save_res_path: ./json/det_db/predicts_db.txt Architecture: name: DistillationModel diff --git a/configs/det/ch_PP-OCRv2/ch_PP-OCRv2_det_student.yml b/configs/det/ch_PP-OCRv2/ch_PP-OCRv2_det_student.yml index cca2a59..0c41bb5 100644 --- a/configs/det/ch_PP-OCRv2/ch_PP-OCRv2_det_student.yml +++ b/configs/det/ch_PP-OCRv2/ch_PP-OCRv2_det_student.yml @@ -3,7 +3,7 @@ Global: epoch_num: 1200 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/ch_db_mv3/ + save_model_dir: ./json/ch_db_mv3/ save_epoch_step: 1200 # evaluation is run every 5000 iterations after the 4000th iteration eval_batch_step: [0, 400] @@ -13,7 +13,7 @@ Global: save_inference_dir: use_visualdl: False infer_img: doc/imgs_en/img_10.jpg - save_res_path: ./output/det_db/predicts_db.txt + save_res_path: ./json/det_db/predicts_db.txt Architecture: model_type: det diff --git a/configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml b/configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml index 252d159..3faa8d7 100644 --- a/configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml +++ b/configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml @@ -4,7 +4,7 @@ Global: epoch_num: 500 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/ch_PP-OCR_v3_det/ + save_model_dir: ./json/ch_PP-OCR_v3_det/ save_epoch_step: 100 eval_batch_step: - 0 diff --git a/configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_dml.yml b/configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_dml.yml index e85127a..dd19760 100644 --- a/configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_dml.yml +++ b/configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_dml.yml @@ -3,7 +3,7 @@ Global: epoch_num: 1200 log_smooth_window: 20 print_batch_step: 2 - save_model_dir: ./output/ch_db_mv3/ + save_model_dir: ./json/ch_db_mv3/ save_epoch_step: 1200 # evaluation is run every 5000 iterations after the 4000th iteration eval_batch_step: [3000, 2000] @@ -13,7 +13,7 @@ Global: save_inference_dir: use_visualdl: False infer_img: doc/imgs_en/img_10.jpg - save_res_path: ./output/det_db/predicts_db.txt + save_res_path: ./json/det_db/predicts_db.txt Architecture: name: DistillationModel diff --git a/configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml b/configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml index 083383a..a246103 100644 --- a/configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml +++ b/configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml @@ -4,7 +4,7 @@ Global: epoch_num: 500 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/ch_PP-OCR_V3_det/ + save_model_dir: ./json/ch_PP-OCR_V3_det/ save_epoch_step: 100 eval_batch_step: - 0 diff --git a/configs/det/ch_PP-OCRv4/ch_PP-OCRv4_det_cml.yml b/configs/det/ch_PP-OCRv4/ch_PP-OCRv4_det_cml.yml index 1d93166..93ee4c4 100644 --- a/configs/det/ch_PP-OCRv4/ch_PP-OCRv4_det_cml.yml +++ b/configs/det/ch_PP-OCRv4/ch_PP-OCRv4_det_cml.yml @@ -4,7 +4,7 @@ Global: epoch_num: 500 log_smooth_window: 20 print_batch_step: 20 - save_model_dir: ./output/ch_PP-OCRv4 + save_model_dir: ./json/ch_PP-OCRv4 save_epoch_step: 50 eval_batch_step: - 0 diff --git a/configs/det/ch_PP-OCRv4/ch_PP-OCRv4_det_student.yml b/configs/det/ch_PP-OCRv4/ch_PP-OCRv4_det_student.yml index 39b260c..eef5ae7 100644 --- a/configs/det/ch_PP-OCRv4/ch_PP-OCRv4_det_student.yml +++ b/configs/det/ch_PP-OCRv4/ch_PP-OCRv4_det_student.yml @@ -4,7 +4,7 @@ Global: epoch_num: &epoch_num 500 log_smooth_window: 20 print_batch_step: 100 - save_model_dir: ./output/ch_PP-OCRv4 + save_model_dir: ./json/ch_PP-OCRv4 save_epoch_step: 10 eval_batch_step: - 0 diff --git a/configs/det/ch_PP-OCRv4/ch_PP-OCRv4_det_teacher.yml b/configs/det/ch_PP-OCRv4/ch_PP-OCRv4_det_teacher.yml index b58af1c..f32b9c9 100644 --- a/configs/det/ch_PP-OCRv4/ch_PP-OCRv4_det_teacher.yml +++ b/configs/det/ch_PP-OCRv4/ch_PP-OCRv4_det_teacher.yml @@ -4,7 +4,7 @@ Global: epoch_num: &epoch_num 500 log_smooth_window: 20 print_batch_step: 100 - save_model_dir: ./output/ch_PP-OCRv4 + save_model_dir: ./json/ch_PP-OCRv4 save_epoch_step: 10 eval_batch_step: - 0 diff --git a/configs/det/ch_ppocr_v2.0/ch_det_mv3_db_v2.0.yml b/configs/det/ch_ppocr_v2.0/ch_det_mv3_db_v2.0.yml index 87718ca..74d558d 100644 --- a/configs/det/ch_ppocr_v2.0/ch_det_mv3_db_v2.0.yml +++ b/configs/det/ch_ppocr_v2.0/ch_det_mv3_db_v2.0.yml @@ -3,7 +3,7 @@ Global: epoch_num: 1200 log_smooth_window: 20 print_batch_step: 2 - save_model_dir: ./output/ch_db_mv3/ + save_model_dir: ./json/ch_db_mv3/ save_epoch_step: 1200 # evaluation is run every 5000 iterations after the 4000th iteration eval_batch_step: [3000, 2000] @@ -13,7 +13,7 @@ Global: save_inference_dir: use_visualdl: False infer_img: doc/imgs_en/img_10.jpg - save_res_path: ./output/det_db/predicts_db.txt + save_res_path: ./json/det_db/predicts_db.txt Architecture: model_type: det diff --git a/configs/det/ch_ppocr_v2.0/ch_det_res18_db_v2.0.yml b/configs/det/ch_ppocr_v2.0/ch_det_res18_db_v2.0.yml index e983c22..b2582fd 100644 --- a/configs/det/ch_ppocr_v2.0/ch_det_res18_db_v2.0.yml +++ b/configs/det/ch_ppocr_v2.0/ch_det_res18_db_v2.0.yml @@ -3,7 +3,7 @@ Global: epoch_num: 1200 log_smooth_window: 20 print_batch_step: 2 - save_model_dir: ./output/ch_db_res18/ + save_model_dir: ./json/ch_db_res18/ save_epoch_step: 1200 # evaluation is run every 5000 iterations after the 4000th iteration eval_batch_step: [3000, 2000] @@ -13,7 +13,7 @@ Global: save_inference_dir: use_visualdl: False infer_img: doc/imgs_en/img_10.jpg - save_res_path: ./output/det_db/predicts_db.txt + save_res_path: ./json/det_db/predicts_db.txt Architecture: model_type: det diff --git a/configs/det/det_mv3_db.yml b/configs/det/det_mv3_db.yml index 8f5685e..6a45829 100644 --- a/configs/det/det_mv3_db.yml +++ b/configs/det/det_mv3_db.yml @@ -5,7 +5,7 @@ Global: epoch_num: 1200 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/db_mv3/ + save_model_dir: ./json/db_mv3/ save_epoch_step: 1200 # evaluation is run every 2000 iterations eval_batch_step: [0, 2000] @@ -15,7 +15,7 @@ Global: save_inference_dir: use_visualdl: False infer_img: doc/imgs_en/img_10.jpg - save_res_path: ./output/det_db/predicts_db.txt + save_res_path: ./json/det_db/predicts_db.txt Architecture: model_type: det diff --git a/configs/det/det_mv3_east.yml b/configs/det/det_mv3_east.yml index 461179e..eb4932a 100644 --- a/configs/det/det_mv3_east.yml +++ b/configs/det/det_mv3_east.yml @@ -3,7 +3,7 @@ Global: epoch_num: 10000 log_smooth_window: 20 print_batch_step: 2 - save_model_dir: ./output/east_mv3/ + save_model_dir: ./json/east_mv3/ save_epoch_step: 1000 # evaluation is run every 5000 iterations after the 4000th iteration eval_batch_step: [4000, 5000] @@ -13,7 +13,7 @@ Global: save_inference_dir: use_visualdl: False infer_img: - save_res_path: ./output/det_east/predicts_east.txt + save_res_path: ./json/det_east/predicts_east.txt Architecture: model_type: det diff --git a/configs/det/det_mv3_pse.yml b/configs/det/det_mv3_pse.yml index 4b8c4be..a289b60 100644 --- a/configs/det/det_mv3_pse.yml +++ b/configs/det/det_mv3_pse.yml @@ -3,17 +3,17 @@ Global: epoch_num: 600 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/det_mv3_pse/ + save_model_dir: ./json/det_mv3_pse/ save_epoch_step: 600 # evaluation is run every 63 iterations eval_batch_step: [ 0,63 ] cal_metric_during_train: False pretrained_model: ./pretrain_models/MobileNetV3_large_x0_5_pretrained - checkpoints: #./output/det_r50_vd_pse_batch8_ColorJitter/best_accuracy + checkpoints: #./json/det_r50_vd_pse_batch8_ColorJitter/best_accuracy save_inference_dir: use_visualdl: False infer_img: doc/imgs_en/img_10.jpg - save_res_path: ./output/det_pse/predicts_pse.txt + save_res_path: ./json/det_pse/predicts_pse.txt Architecture: model_type: det diff --git a/configs/det/det_r18_vd_ct.yml b/configs/det/det_r18_vd_ct.yml index 42922df..0bf54b5 100644 --- a/configs/det/det_r18_vd_ct.yml +++ b/configs/det/det_r18_vd_ct.yml @@ -3,7 +3,7 @@ Global: epoch_num: 600 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/det_ct/ + save_model_dir: ./json/det_ct/ save_epoch_step: 10 # evaluation is run every 2000 iterations eval_batch_step: [0,1000] @@ -13,7 +13,7 @@ Global: save_inference_dir: use_visualdl: False infer_img: doc/imgs_en/img623.jpg - save_res_path: ./output/det_ct/predicts_ct.txt + save_res_path: ./json/det_ct/predicts_ct.txt Architecture: model_type: det diff --git a/configs/det/det_r50_db++_icdar15.yml b/configs/det/det_r50_db++_icdar15.yml index 2bb2cb8..f22d65f 100644 --- a/configs/det/det_r50_db++_icdar15.yml +++ b/configs/det/det_r50_db++_icdar15.yml @@ -4,7 +4,7 @@ Global: epoch_num: 1000 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/det_r50_icdar15/ + save_model_dir: ./json/det_r50_icdar15/ save_epoch_step: 200 eval_batch_step: - 0 diff --git a/configs/det/det_r50_db++_td_tr.yml b/configs/det/det_r50_db++_td_tr.yml index f3b02aa..255b519 100644 --- a/configs/det/det_r50_db++_td_tr.yml +++ b/configs/det/det_r50_db++_td_tr.yml @@ -4,7 +4,7 @@ Global: epoch_num: 1000 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/det_r50_td_tr/ + save_model_dir: ./json/det_r50_td_tr/ save_epoch_step: 200 eval_batch_step: - 0 diff --git a/configs/det/det_r50_drrg_ctw.yml b/configs/det/det_r50_drrg_ctw.yml index f56ac39..b13dda7 100644 --- a/configs/det/det_r50_drrg_ctw.yml +++ b/configs/det/det_r50_drrg_ctw.yml @@ -3,7 +3,7 @@ Global: epoch_num: 1200 log_smooth_window: 20 print_batch_step: 5 - save_model_dir: ./output/det_r50_drrg_ctw/ + save_model_dir: ./json/det_r50_drrg_ctw/ save_epoch_step: 100 # evaluation is run every 1260 iterations eval_batch_step: [37800, 1260] @@ -13,7 +13,7 @@ Global: save_inference_dir: use_visualdl: False infer_img: doc/imgs_en/img_10.jpg - save_res_path: ./output/det_drrg/predicts_drrg.txt + save_res_path: ./json/det_drrg/predicts_drrg.txt Architecture: diff --git a/configs/det/det_r50_vd_db.yml b/configs/det/det_r50_vd_db.yml index 288dcc8..aacfa8e 100644 --- a/configs/det/det_r50_vd_db.yml +++ b/configs/det/det_r50_vd_db.yml @@ -3,7 +3,7 @@ Global: epoch_num: 1200 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/det_r50_vd/ + save_model_dir: ./json/det_r50_vd/ save_epoch_step: 1200 # evaluation is run every 2000 iterations eval_batch_step: [0,2000] @@ -13,7 +13,7 @@ Global: save_inference_dir: use_visualdl: False infer_img: doc/imgs_en/img_10.jpg - save_res_path: ./output/det_db/predicts_db.txt + save_res_path: ./json/det_db/predicts_db.txt Architecture: model_type: det diff --git a/configs/det/det_r50_vd_dcn_fce_ctw.yml b/configs/det/det_r50_vd_dcn_fce_ctw.yml index 5e851d1..2963293 100644 --- a/configs/det/det_r50_vd_dcn_fce_ctw.yml +++ b/configs/det/det_r50_vd_dcn_fce_ctw.yml @@ -3,7 +3,7 @@ Global: epoch_num: 1500 log_smooth_window: 20 print_batch_step: 20 - save_model_dir: ./output/det_r50_dcn_fce_ctw/ + save_model_dir: ./json/det_r50_dcn_fce_ctw/ save_epoch_step: 100 # evaluation is run every 835 iterations eval_batch_step: [0, 835] @@ -13,7 +13,7 @@ Global: save_inference_dir: use_visualdl: False infer_img: doc/imgs_en/img_10.jpg - save_res_path: ./output/det_fce/predicts_fce.txt + save_res_path: ./json/det_fce/predicts_fce.txt Architecture: diff --git a/configs/det/det_r50_vd_east.yml b/configs/det/det_r50_vd_east.yml index 5a488dd..9a35ab8 100644 --- a/configs/det/det_r50_vd_east.yml +++ b/configs/det/det_r50_vd_east.yml @@ -3,7 +3,7 @@ Global: epoch_num: 10000 log_smooth_window: 20 print_batch_step: 2 - save_model_dir: ./output/east_r50_vd/ + save_model_dir: ./json/east_r50_vd/ save_epoch_step: 1000 # evaluation is run every 5000 iterations after the 4000th iteration eval_batch_step: [4000, 5000] @@ -13,7 +13,7 @@ Global: save_inference_dir: use_visualdl: False infer_img: - save_res_path: ./output/det_east/predicts_east.txt + save_res_path: ./json/det_east/predicts_east.txt Architecture: model_type: det diff --git a/configs/det/det_r50_vd_pse.yml b/configs/det/det_r50_vd_pse.yml index 408e16d..713d0ad 100644 --- a/configs/det/det_r50_vd_pse.yml +++ b/configs/det/det_r50_vd_pse.yml @@ -3,17 +3,17 @@ Global: epoch_num: 600 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/det_r50_vd_pse/ + save_model_dir: ./json/det_r50_vd_pse/ save_epoch_step: 600 # evaluation is run every 125 iterations eval_batch_step: [ 0,125 ] cal_metric_during_train: False pretrained_model: ./pretrain_models/ResNet50_vd_ssld_pretrained - checkpoints: #./output/det_r50_vd_pse_batch8_ColorJitter/best_accuracy + checkpoints: #./json/det_r50_vd_pse_batch8_ColorJitter/best_accuracy save_inference_dir: use_visualdl: False infer_img: doc/imgs_en/img_10.jpg - save_res_path: ./output/det_pse/predicts_pse.txt + save_res_path: ./json/det_pse/predicts_pse.txt Architecture: model_type: det diff --git a/configs/det/det_r50_vd_sast_icdar15.yml b/configs/det/det_r50_vd_sast_icdar15.yml index e1bf6fa..81f0d61 100644 --- a/configs/det/det_r50_vd_sast_icdar15.yml +++ b/configs/det/det_r50_vd_sast_icdar15.yml @@ -3,7 +3,7 @@ Global: epoch_num: 5000 log_smooth_window: 20 print_batch_step: 2 - save_model_dir: ./output/sast_r50_vd_ic15/ + save_model_dir: ./json/sast_r50_vd_ic15/ save_epoch_step: 1000 # evaluation is run every 5000 iterations after the 4000th iteration eval_batch_step: [4000, 5000] @@ -13,7 +13,7 @@ Global: save_inference_dir: use_visualdl: False infer_img: - save_res_path: ./output/sast_r50_vd_ic15/predicts_sast.txt + save_res_path: ./json/sast_r50_vd_ic15/predicts_sast.txt Architecture: diff --git a/configs/det/det_r50_vd_sast_totaltext.yml b/configs/det/det_r50_vd_sast_totaltext.yml index 557ff8b..fc782ba 100644 --- a/configs/det/det_r50_vd_sast_totaltext.yml +++ b/configs/det/det_r50_vd_sast_totaltext.yml @@ -3,7 +3,7 @@ Global: epoch_num: 5000 log_smooth_window: 20 print_batch_step: 2 - save_model_dir: ./output/sast_r50_vd_tt/ + save_model_dir: ./json/sast_r50_vd_tt/ save_epoch_step: 1000 # evaluation is run every 5000 iterations after the 4000th iteration eval_batch_step: [4000, 5000] @@ -13,7 +13,7 @@ Global: save_inference_dir: use_visualdl: False infer_img: - save_res_path: ./output/sast_r50_vd_tt/predicts_sast.txt + save_res_path: ./json/sast_r50_vd_tt/predicts_sast.txt Architecture: model_type: det diff --git a/configs/det/det_repsvtr_db.yml b/configs/det/det_repsvtr_db.yml index 8c4768e..6780946 100644 --- a/configs/det/det_repsvtr_db.yml +++ b/configs/det/det_repsvtr_db.yml @@ -4,7 +4,7 @@ Global: epoch_num: &epoch_num 500 log_smooth_window: 20 print_batch_step: 100 - save_model_dir: ./output/det_repsvtr_db + save_model_dir: ./json/det_repsvtr_db save_epoch_step: 10 eval_batch_step: - 0 diff --git a/configs/det/det_res18_db_v2.0.yml b/configs/det/det_res18_db_v2.0.yml index e983c22..b2582fd 100644 --- a/configs/det/det_res18_db_v2.0.yml +++ b/configs/det/det_res18_db_v2.0.yml @@ -3,7 +3,7 @@ Global: epoch_num: 1200 log_smooth_window: 20 print_batch_step: 2 - save_model_dir: ./output/ch_db_res18/ + save_model_dir: ./json/ch_db_res18/ save_epoch_step: 1200 # evaluation is run every 5000 iterations after the 4000th iteration eval_batch_step: [3000, 2000] @@ -13,7 +13,7 @@ Global: save_inference_dir: use_visualdl: False infer_img: doc/imgs_en/img_10.jpg - save_res_path: ./output/det_db/predicts_db.txt + save_res_path: ./json/det_db/predicts_db.txt Architecture: model_type: det diff --git a/configs/e2e/e2e_r50_vd_pg.yml b/configs/e2e/e2e_r50_vd_pg.yml index 4642f54..01dfaf8 100644 --- a/configs/e2e/e2e_r50_vd_pg.yml +++ b/configs/e2e/e2e_r50_vd_pg.yml @@ -3,7 +3,7 @@ Global: epoch_num: 600 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/pgnet_r50_vd_totaltext/ + save_model_dir: ./json/pgnet_r50_vd_totaltext/ save_epoch_step: 10 # evaluation is run every 0 iterationss after the 1000th iteration eval_batch_step: [ 0, 1000 ] @@ -15,7 +15,7 @@ Global: infer_img: infer_visual_type: EN # two mode: EN is for english datasets, CN is for chinese datasets valid_set: totaltext # two mode: totaltext valid curved words, partvgg valid non-curved words - save_res_path: ./output/pgnet_r50_vd_totaltext/predicts_pgnet.txt + save_res_path: ./json/pgnet_r50_vd_totaltext/predicts_pgnet.txt character_dict_path: ppocr/utils/ic15_dict.txt character_type: EN max_text_length: 50 # the max length in seq diff --git a/configs/kie/layoutlm_series/re_layoutlmv2_xfund_zh.yml b/configs/kie/layoutlm_series/re_layoutlmv2_xfund_zh.yml index 3e3578d..3dc6ae1 100644 --- a/configs/kie/layoutlm_series/re_layoutlmv2_xfund_zh.yml +++ b/configs/kie/layoutlm_series/re_layoutlmv2_xfund_zh.yml @@ -3,7 +3,7 @@ Global: epoch_num: &epoch_num 200 log_smooth_window: 10 print_batch_step: 10 - save_model_dir: ./output/re_layoutlmv2_xfund_zh + save_model_dir: ./json/re_layoutlmv2_xfund_zh save_epoch_step: 2000 # evaluation is run every 10 iterations after the 0th iteration eval_batch_step: [ 0, 19 ] @@ -12,7 +12,7 @@ Global: use_visualdl: False seed: 2022 infer_img: ppstructure/docs/kie/input/zh_val_21.jpg - save_res_path: ./output/re_layoutlmv2_xfund_zh/res/ + save_res_path: ./json/re_layoutlmv2_xfund_zh/res/ Architecture: model_type: kie diff --git a/configs/kie/layoutlm_series/re_layoutxlm_xfund_zh.yml b/configs/kie/layoutlm_series/re_layoutxlm_xfund_zh.yml index 99dc771..8845ee3 100644 --- a/configs/kie/layoutlm_series/re_layoutxlm_xfund_zh.yml +++ b/configs/kie/layoutlm_series/re_layoutxlm_xfund_zh.yml @@ -3,7 +3,7 @@ Global: epoch_num: &epoch_num 130 log_smooth_window: 10 print_batch_step: 10 - save_model_dir: ./output/re_layoutxlm_xfund_zh + save_model_dir: ./json/re_layoutxlm_xfund_zh save_epoch_step: 2000 # evaluation is run every 10 iterations after the 0th iteration eval_batch_step: [ 0, 19 ] @@ -12,7 +12,7 @@ Global: use_visualdl: False seed: 2022 infer_img: ppstructure/docs/kie/input/zh_val_21.jpg - save_res_path: ./output/re_layoutxlm_xfund_zh/res/ + save_res_path: ./json/re_layoutxlm_xfund_zh/res/ Architecture: model_type: kie diff --git a/configs/kie/layoutlm_series/ser_layoutlm_xfund_zh.yml b/configs/kie/layoutlm_series/ser_layoutlm_xfund_zh.yml index 5424d7e..d76bd09 100644 --- a/configs/kie/layoutlm_series/ser_layoutlm_xfund_zh.yml +++ b/configs/kie/layoutlm_series/ser_layoutlm_xfund_zh.yml @@ -3,7 +3,7 @@ Global: epoch_num: &epoch_num 200 log_smooth_window: 10 print_batch_step: 10 - save_model_dir: ./output/ser_layoutlm_xfund_zh + save_model_dir: ./json/ser_layoutlm_xfund_zh save_epoch_step: 2000 # evaluation is run every 10 iterations after the 0th iteration eval_batch_step: [ 0, 19 ] @@ -12,7 +12,7 @@ Global: use_visualdl: False seed: 2022 infer_img: ppstructure/docs/kie/input/zh_val_42.jpg - save_res_path: ./output/re_layoutlm_xfund_zh/res + save_res_path: ./json/re_layoutlm_xfund_zh/res Architecture: model_type: kie diff --git a/configs/kie/layoutlm_series/ser_layoutlmv2_xfund_zh.yml b/configs/kie/layoutlm_series/ser_layoutlmv2_xfund_zh.yml index c5e8335..341dfaf 100644 --- a/configs/kie/layoutlm_series/ser_layoutlmv2_xfund_zh.yml +++ b/configs/kie/layoutlm_series/ser_layoutlmv2_xfund_zh.yml @@ -3,7 +3,7 @@ Global: epoch_num: &epoch_num 200 log_smooth_window: 10 print_batch_step: 10 - save_model_dir: ./output/ser_layoutlmv2_xfund_zh/ + save_model_dir: ./json/ser_layoutlmv2_xfund_zh/ save_epoch_step: 2000 # evaluation is run every 10 iterations after the 0th iteration eval_batch_step: [ 0, 19 ] @@ -12,7 +12,7 @@ Global: use_visualdl: False seed: 2022 infer_img: ppstructure/docs/kie/input/zh_val_42.jpg - save_res_path: ./output/ser_layoutlmv2_xfund_zh/res/ + save_res_path: ./json/ser_layoutlmv2_xfund_zh/res/ Architecture: model_type: kie diff --git a/configs/kie/layoutlm_series/ser_layoutxlm_xfund_zh.yml b/configs/kie/layoutlm_series/ser_layoutxlm_xfund_zh.yml index abcfec2..03ffb63 100644 --- a/configs/kie/layoutlm_series/ser_layoutxlm_xfund_zh.yml +++ b/configs/kie/layoutlm_series/ser_layoutxlm_xfund_zh.yml @@ -3,7 +3,7 @@ Global: epoch_num: &epoch_num 200 log_smooth_window: 10 print_batch_step: 10 - save_model_dir: ./output/ser_layoutxlm_xfund_zh + save_model_dir: ./json/ser_layoutxlm_xfund_zh save_epoch_step: 2000 # evaluation is run every 10 iterations after the 0th iteration eval_batch_step: [ 0, 19 ] @@ -12,7 +12,7 @@ Global: use_visualdl: False seed: 2022 infer_img: ppstructure/docs/kie/input/zh_val_42.jpg - save_res_path: ./output/ser_layoutxlm_xfund_zh/res + save_res_path: ./json/ser_layoutxlm_xfund_zh/res Architecture: model_type: kie diff --git a/configs/kie/sdmgr/kie_unet_sdmgr.yml b/configs/kie/sdmgr/kie_unet_sdmgr.yml index da2e4fd..34427eb 100644 --- a/configs/kie/sdmgr/kie_unet_sdmgr.yml +++ b/configs/kie/sdmgr/kie_unet_sdmgr.yml @@ -3,7 +3,7 @@ Global: epoch_num: 60 log_smooth_window: 20 print_batch_step: 50 - save_model_dir: ./output/kie_5/ + save_model_dir: ./json/kie_5/ save_epoch_step: 50 # evaluation is run every 5000 iterations after the 4000th iteration eval_batch_step: [ 0, 80 ] @@ -19,7 +19,7 @@ Global: use_visualdl: False class_path: &class_path ./train_data/wildreceipt/class_list.txt infer_img: ./train_data/wildreceipt/1.txt - save_res_path: ./output/sdmgr_kie/predicts_kie.txt + save_res_path: ./json/sdmgr_kie/predicts_kie.txt img_scale: [ 1024, 512 ] Architecture: diff --git a/configs/kie/vi_layoutxlm/re_vi_layoutxlm_xfund_zh.yml b/configs/kie/vi_layoutxlm/re_vi_layoutxlm_xfund_zh.yml index e65af0a..e197fc9 100644 --- a/configs/kie/vi_layoutxlm/re_vi_layoutxlm_xfund_zh.yml +++ b/configs/kie/vi_layoutxlm/re_vi_layoutxlm_xfund_zh.yml @@ -3,7 +3,7 @@ Global: epoch_num: &epoch_num 130 log_smooth_window: 10 print_batch_step: 10 - save_model_dir: ./output/re_vi_layoutxlm_xfund_zh + save_model_dir: ./json/re_vi_layoutxlm_xfund_zh save_epoch_step: 2000 # evaluation is run every 10 iterations after the 0th iteration eval_batch_step: [ 0, 19 ] @@ -12,7 +12,7 @@ Global: use_visualdl: False seed: 2022 infer_img: ppstructure/docs/kie/input/zh_val_21.jpg - save_res_path: ./output/re/xfund_zh/with_gt + save_res_path: ./json/re/xfund_zh/with_gt kie_rec_model_dir: kie_det_model_dir: diff --git a/configs/kie/vi_layoutxlm/re_vi_layoutxlm_xfund_zh_udml.yml b/configs/kie/vi_layoutxlm/re_vi_layoutxlm_xfund_zh_udml.yml index eda3a2b..ca3aa93 100644 --- a/configs/kie/vi_layoutxlm/re_vi_layoutxlm_xfund_zh_udml.yml +++ b/configs/kie/vi_layoutxlm/re_vi_layoutxlm_xfund_zh_udml.yml @@ -3,7 +3,7 @@ Global: epoch_num: &epoch_num 130 log_smooth_window: 10 print_batch_step: 10 - save_model_dir: ./output/re_vi_layoutxlm_xfund_zh_udml + save_model_dir: ./json/re_vi_layoutxlm_xfund_zh_udml save_epoch_step: 2000 # evaluation is run every 10 iterations after the 0th iteration eval_batch_step: [ 0, 19 ] @@ -12,7 +12,7 @@ Global: use_visualdl: False seed: 2022 infer_img: ppstructure/docs/kie/input/zh_val_21.jpg - save_res_path: ./output/re/xfund_zh/with_gt + save_res_path: ./json/re/xfund_zh/with_gt Architecture: model_type: &model_type "kie" diff --git a/configs/kie/vi_layoutxlm/ser_vi_layoutxlm_xfund_zh.yml b/configs/kie/vi_layoutxlm/ser_vi_layoutxlm_xfund_zh.yml index 50b04ba..17f30d0 100644 --- a/configs/kie/vi_layoutxlm/ser_vi_layoutxlm_xfund_zh.yml +++ b/configs/kie/vi_layoutxlm/ser_vi_layoutxlm_xfund_zh.yml @@ -3,7 +3,7 @@ Global: epoch_num: &epoch_num 200 log_smooth_window: 10 print_batch_step: 10 - save_model_dir: ./output/ser_vi_layoutxlm_xfund_zh + save_model_dir: ./json/ser_vi_layoutxlm_xfund_zh save_epoch_step: 2000 # evaluation is run every 10 iterations after the 0th iteration eval_batch_step: [ 0, 19 ] @@ -18,7 +18,7 @@ Global: # infer_img: train_data/XFUND/zh_val/val.json # infer_mode: False - save_res_path: ./output/ser/xfund_zh/res + save_res_path: ./json/ser/xfund_zh/res kie_rec_model_dir: kie_det_model_dir: amp_custom_white_list: ['scale', 'concat', 'elementwise_add'] diff --git a/configs/kie/vi_layoutxlm/ser_vi_layoutxlm_xfund_zh_udml.yml b/configs/kie/vi_layoutxlm/ser_vi_layoutxlm_xfund_zh_udml.yml index 5166533..c6764b4 100644 --- a/configs/kie/vi_layoutxlm/ser_vi_layoutxlm_xfund_zh_udml.yml +++ b/configs/kie/vi_layoutxlm/ser_vi_layoutxlm_xfund_zh_udml.yml @@ -3,7 +3,7 @@ Global: epoch_num: &epoch_num 200 log_smooth_window: 10 print_batch_step: 10 - save_model_dir: ./output/ser_vi_layoutxlm_xfund_zh_udml + save_model_dir: ./json/ser_vi_layoutxlm_xfund_zh_udml save_epoch_step: 2000 # evaluation is run every 10 iterations after the 0th iteration eval_batch_step: [ 0, 19 ] @@ -12,7 +12,7 @@ Global: use_visualdl: False seed: 2022 infer_img: ppstructure/docs/kie/input/zh_val_42.jpg - save_res_path: ./output/ser_layoutxlm_xfund_zh/res + save_res_path: ./json/ser_layoutxlm_xfund_zh/res Architecture: diff --git a/configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml b/configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml index fd15873..df0a0ac 100644 --- a/configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml +++ b/configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml @@ -4,7 +4,7 @@ Global: epoch_num: 500 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec_ppocr_v3 + save_model_dir: ./json/rec_ppocr_v3 save_epoch_step: 3 eval_batch_step: [0, 2000] cal_metric_during_train: true @@ -18,7 +18,7 @@ Global: infer_mode: false use_space_char: true distributed: true - save_res_path: ./output/rec/predicts_ppocrv3.txt + save_res_path: ./json/rec/predicts_ppocrv3.txt Optimizer: diff --git a/configs/rec/PP-OCRv3/ch_PP-OCRv3_rec_distillation.yml b/configs/rec/PP-OCRv3/ch_PP-OCRv3_rec_distillation.yml index 3b82ef8..d4cb668 100644 --- a/configs/rec/PP-OCRv3/ch_PP-OCRv3_rec_distillation.yml +++ b/configs/rec/PP-OCRv3/ch_PP-OCRv3_rec_distillation.yml @@ -4,7 +4,7 @@ Global: epoch_num: 800 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec_ppocr_v3_distillation + save_model_dir: ./json/rec_ppocr_v3_distillation save_epoch_step: 3 eval_batch_step: [0, 2000] cal_metric_during_train: true @@ -18,7 +18,7 @@ Global: infer_mode: false use_space_char: true distributed: true - save_res_path: ./output/rec/predicts_ppocrv3_distillation.txt + save_res_path: ./json/rec/predicts_ppocrv3_distillation.txt d2s_train_image_shape: [3, 48, -1] diff --git a/configs/rec/PP-OCRv3/en_PP-OCRv3_rec.yml b/configs/rec/PP-OCRv3/en_PP-OCRv3_rec.yml index af42001..6f8b3f6 100644 --- a/configs/rec/PP-OCRv3/en_PP-OCRv3_rec.yml +++ b/configs/rec/PP-OCRv3/en_PP-OCRv3_rec.yml @@ -4,7 +4,7 @@ Global: epoch_num: 500 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/v3_en_mobile + save_model_dir: ./json/v3_en_mobile save_epoch_step: 3 eval_batch_step: [0, 2000] cal_metric_during_train: true @@ -18,7 +18,7 @@ Global: infer_mode: false use_space_char: true distributed: true - save_res_path: ./output/rec/predicts_ppocrv3_en.txt + save_res_path: ./json/rec/predicts_ppocrv3_en.txt Optimizer: diff --git a/configs/rec/PP-OCRv3/multi_language/arabic_PP-OCRv3_rec.yml b/configs/rec/PP-OCRv3/multi_language/arabic_PP-OCRv3_rec.yml index f8e9260..50d6bc1 100644 --- a/configs/rec/PP-OCRv3/multi_language/arabic_PP-OCRv3_rec.yml +++ b/configs/rec/PP-OCRv3/multi_language/arabic_PP-OCRv3_rec.yml @@ -4,7 +4,7 @@ Global: epoch_num: 500 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/v3_arabic_mobile + save_model_dir: ./json/v3_arabic_mobile save_epoch_step: 3 eval_batch_step: [0, 2000] cal_metric_during_train: true @@ -18,7 +18,7 @@ Global: infer_mode: false use_space_char: true distributed: true - save_res_path: ./output/rec/predicts_ppocrv3_arabic.txt + save_res_path: ./json/rec/predicts_ppocrv3_arabic.txt Optimizer: diff --git a/configs/rec/PP-OCRv3/multi_language/chinese_cht_PP-OCRv3_rec.yml b/configs/rec/PP-OCRv3/multi_language/chinese_cht_PP-OCRv3_rec.yml index 7709084..f5f5893 100644 --- a/configs/rec/PP-OCRv3/multi_language/chinese_cht_PP-OCRv3_rec.yml +++ b/configs/rec/PP-OCRv3/multi_language/chinese_cht_PP-OCRv3_rec.yml @@ -4,7 +4,7 @@ Global: epoch_num: 500 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/v3_chinese_cht_mobile + save_model_dir: ./json/v3_chinese_cht_mobile save_epoch_step: 3 eval_batch_step: [0, 2000] cal_metric_during_train: true @@ -18,7 +18,7 @@ Global: infer_mode: false use_space_char: true distributed: true - save_res_path: ./output/rec/predicts_ppocrv3_chinese_cht.txt + save_res_path: ./json/rec/predicts_ppocrv3_chinese_cht.txt Optimizer: diff --git a/configs/rec/PP-OCRv3/multi_language/cyrillic_PP-OCRv3_rec.yml b/configs/rec/PP-OCRv3/multi_language/cyrillic_PP-OCRv3_rec.yml index 0aa1a93..3b17d88 100644 --- a/configs/rec/PP-OCRv3/multi_language/cyrillic_PP-OCRv3_rec.yml +++ b/configs/rec/PP-OCRv3/multi_language/cyrillic_PP-OCRv3_rec.yml @@ -4,7 +4,7 @@ Global: epoch_num: 500 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/v3_cyrillic_mobile + save_model_dir: ./json/v3_cyrillic_mobile save_epoch_step: 3 eval_batch_step: [0, 2000] cal_metric_during_train: true @@ -18,7 +18,7 @@ Global: infer_mode: false use_space_char: true distributed: true - save_res_path: ./output/rec/predicts_ppocrv3_cyrillic.txt + save_res_path: ./json/rec/predicts_ppocrv3_cyrillic.txt Optimizer: diff --git a/configs/rec/PP-OCRv3/multi_language/devanagari_PP-OCRv3_rec.yml b/configs/rec/PP-OCRv3/multi_language/devanagari_PP-OCRv3_rec.yml index b05371e..6044b64 100644 --- a/configs/rec/PP-OCRv3/multi_language/devanagari_PP-OCRv3_rec.yml +++ b/configs/rec/PP-OCRv3/multi_language/devanagari_PP-OCRv3_rec.yml @@ -4,7 +4,7 @@ Global: epoch_num: 500 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/v3_devanagari_mobile + save_model_dir: ./json/v3_devanagari_mobile save_epoch_step: 3 eval_batch_step: [0, 2000] cal_metric_during_train: true @@ -18,7 +18,7 @@ Global: infer_mode: false use_space_char: true distributed: true - save_res_path: ./output/rec/predicts_ppocrv3_devanagari.txt + save_res_path: ./json/rec/predicts_ppocrv3_devanagari.txt Optimizer: diff --git a/configs/rec/PP-OCRv3/multi_language/japan_PP-OCRv3_rec.yml b/configs/rec/PP-OCRv3/multi_language/japan_PP-OCRv3_rec.yml index 420019e..6f26da0 100644 --- a/configs/rec/PP-OCRv3/multi_language/japan_PP-OCRv3_rec.yml +++ b/configs/rec/PP-OCRv3/multi_language/japan_PP-OCRv3_rec.yml @@ -4,7 +4,7 @@ Global: epoch_num: 500 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/v3_japan_mobile + save_model_dir: ./json/v3_japan_mobile save_epoch_step: 3 eval_batch_step: [0, 2000] cal_metric_during_train: true @@ -18,7 +18,7 @@ Global: infer_mode: false use_space_char: true distributed: true - save_res_path: ./output/rec/predicts_ppocrv3_japan.txt + save_res_path: ./json/rec/predicts_ppocrv3_japan.txt Optimizer: diff --git a/configs/rec/PP-OCRv3/multi_language/ka_PP-OCRv3_rec.yml b/configs/rec/PP-OCRv3/multi_language/ka_PP-OCRv3_rec.yml index 75e1666..d3a760d 100644 --- a/configs/rec/PP-OCRv3/multi_language/ka_PP-OCRv3_rec.yml +++ b/configs/rec/PP-OCRv3/multi_language/ka_PP-OCRv3_rec.yml @@ -4,7 +4,7 @@ Global: epoch_num: 500 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/v3_ka_mobile + save_model_dir: ./json/v3_ka_mobile save_epoch_step: 3 eval_batch_step: [0, 2000] cal_metric_during_train: true @@ -18,7 +18,7 @@ Global: infer_mode: false use_space_char: true distributed: true - save_res_path: ./output/rec/predicts_ppocrv3_ka.txt + save_res_path: ./json/rec/predicts_ppocrv3_ka.txt Optimizer: diff --git a/configs/rec/PP-OCRv3/multi_language/korean_PP-OCRv3_rec.yml b/configs/rec/PP-OCRv3/multi_language/korean_PP-OCRv3_rec.yml index f5d4c09..6d03420 100644 --- a/configs/rec/PP-OCRv3/multi_language/korean_PP-OCRv3_rec.yml +++ b/configs/rec/PP-OCRv3/multi_language/korean_PP-OCRv3_rec.yml @@ -4,7 +4,7 @@ Global: epoch_num: 500 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/v3_korean_mobile + save_model_dir: ./json/v3_korean_mobile save_epoch_step: 3 eval_batch_step: [0, 2000] cal_metric_during_train: true @@ -18,7 +18,7 @@ Global: infer_mode: false use_space_char: true distributed: true - save_res_path: ./output/rec/predicts_ppocrv3_korean.txt + save_res_path: ./json/rec/predicts_ppocrv3_korean.txt Optimizer: diff --git a/configs/rec/PP-OCRv3/multi_language/latin_PP-OCRv3_rec.yml b/configs/rec/PP-OCRv3/multi_language/latin_PP-OCRv3_rec.yml index d43444b..c73dbd8 100644 --- a/configs/rec/PP-OCRv3/multi_language/latin_PP-OCRv3_rec.yml +++ b/configs/rec/PP-OCRv3/multi_language/latin_PP-OCRv3_rec.yml @@ -4,7 +4,7 @@ Global: epoch_num: 500 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/v3_latin_mobile + save_model_dir: ./json/v3_latin_mobile save_epoch_step: 3 eval_batch_step: [0, 2000] cal_metric_during_train: true @@ -18,7 +18,7 @@ Global: infer_mode: false use_space_char: true distributed: true - save_res_path: ./output/rec/predicts_ppocrv3_latin.txt + save_res_path: ./json/rec/predicts_ppocrv3_latin.txt Optimizer: diff --git a/configs/rec/PP-OCRv3/multi_language/ta_PP-OCRv3_rec.yml b/configs/rec/PP-OCRv3/multi_language/ta_PP-OCRv3_rec.yml index 9d152e2..fcb03d3 100644 --- a/configs/rec/PP-OCRv3/multi_language/ta_PP-OCRv3_rec.yml +++ b/configs/rec/PP-OCRv3/multi_language/ta_PP-OCRv3_rec.yml @@ -4,7 +4,7 @@ Global: epoch_num: 500 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/v3_ta_mobile + save_model_dir: ./json/v3_ta_mobile save_epoch_step: 3 eval_batch_step: [0, 2000] cal_metric_during_train: true @@ -18,7 +18,7 @@ Global: infer_mode: false use_space_char: true distributed: true - save_res_path: ./output/rec/predicts_ppocrv3_ta.txt + save_res_path: ./json/rec/predicts_ppocrv3_ta.txt Optimizer: diff --git a/configs/rec/PP-OCRv3/multi_language/te_PP-OCRv3_rec.yml b/configs/rec/PP-OCRv3/multi_language/te_PP-OCRv3_rec.yml index b1e52e4..fac4888 100644 --- a/configs/rec/PP-OCRv3/multi_language/te_PP-OCRv3_rec.yml +++ b/configs/rec/PP-OCRv3/multi_language/te_PP-OCRv3_rec.yml @@ -4,7 +4,7 @@ Global: epoch_num: 500 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/v3_te_mobile + save_model_dir: ./json/v3_te_mobile save_epoch_step: 3 eval_batch_step: [0, 2000] cal_metric_during_train: true @@ -18,7 +18,7 @@ Global: infer_mode: false use_space_char: true distributed: true - save_res_path: ./output/rec/predicts_ppocrv3_te.txt + save_res_path: ./json/rec/predicts_ppocrv3_te.txt Optimizer: diff --git a/configs/rec/PP-OCRv4/ch_PP-OCRv4_rec.yml b/configs/rec/PP-OCRv4/ch_PP-OCRv4_rec.yml index 827f5ee..205adc7 100644 --- a/configs/rec/PP-OCRv4/ch_PP-OCRv4_rec.yml +++ b/configs/rec/PP-OCRv4/ch_PP-OCRv4_rec.yml @@ -4,7 +4,7 @@ Global: epoch_num: 200 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec_ppocr_v4 + save_model_dir: ./json/rec_ppocr_v4 save_epoch_step: 10 eval_batch_step: [0, 2000] cal_metric_during_train: true @@ -18,7 +18,7 @@ Global: infer_mode: false use_space_char: true distributed: true - save_res_path: ./output/rec/predicts_ppocrv3.txt + save_res_path: ./json/rec/predicts_ppocrv3.txt Optimizer: diff --git a/configs/rec/PP-OCRv4/ch_PP-OCRv4_rec_ampO2_ultra.yml b/configs/rec/PP-OCRv4/ch_PP-OCRv4_rec_ampO2_ultra.yml index 475c551..7fd909d 100644 --- a/configs/rec/PP-OCRv4/ch_PP-OCRv4_rec_ampO2_ultra.yml +++ b/configs/rec/PP-OCRv4/ch_PP-OCRv4_rec_ampO2_ultra.yml @@ -4,7 +4,7 @@ Global: epoch_num: 200 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec_ppocr_v4 + save_model_dir: ./json/rec_ppocr_v4 save_epoch_step: 10 eval_batch_step: [0, 2000] cal_metric_during_train: true @@ -18,7 +18,7 @@ Global: infer_mode: false use_space_char: true distributed: true - save_res_path: ./output/rec/predicts_ppocrv3.txt + save_res_path: ./json/rec/predicts_ppocrv3.txt use_amp: True amp_level: O2 diff --git a/configs/rec/PP-OCRv4/ch_PP-OCRv4_rec_distillation.yml b/configs/rec/PP-OCRv4/ch_PP-OCRv4_rec_distillation.yml index aa2a36d..01d30fe 100644 --- a/configs/rec/PP-OCRv4/ch_PP-OCRv4_rec_distillation.yml +++ b/configs/rec/PP-OCRv4/ch_PP-OCRv4_rec_distillation.yml @@ -4,14 +4,14 @@ Global: epoch_num: 200 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec_dkd_400w_svtr_ctc_lcnet_blank_dkd0.1/ + save_model_dir: ./json/rec_dkd_400w_svtr_ctc_lcnet_blank_dkd0.1/ save_epoch_step: 40 eval_batch_step: - 0 - 2000 cal_metric_during_train: true pretrained_model: null - checkpoints: ./output/rec_dkd_400w_svtr_ctc_lcnet_blank_dkd0.1/latest + checkpoints: ./json/rec_dkd_400w_svtr_ctc_lcnet_blank_dkd0.1/latest save_inference_dir: null use_visualdl: false infer_img: doc/imgs_words/ch/word_1.jpg @@ -20,7 +20,7 @@ Global: infer_mode: false use_space_char: true distributed: true - save_res_path: ./output/rec/predicts_ppocrv3.txt + save_res_path: ./json/rec/predicts_ppocrv3.txt Optimizer: name: Adam beta1: 0.9 diff --git a/configs/rec/PP-OCRv4/ch_PP-OCRv4_rec_fp32_ultra.yml b/configs/rec/PP-OCRv4/ch_PP-OCRv4_rec_fp32_ultra.yml index 8c26730..d6932f6 100644 --- a/configs/rec/PP-OCRv4/ch_PP-OCRv4_rec_fp32_ultra.yml +++ b/configs/rec/PP-OCRv4/ch_PP-OCRv4_rec_fp32_ultra.yml @@ -4,7 +4,7 @@ Global: epoch_num: 200 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec_ppocr_v4 + save_model_dir: ./json/rec_ppocr_v4 save_epoch_step: 10 eval_batch_step: [0, 2000] cal_metric_during_train: true @@ -18,7 +18,7 @@ Global: infer_mode: false use_space_char: true distributed: true - save_res_path: ./output/rec/predicts_ppocrv3.txt + save_res_path: ./json/rec/predicts_ppocrv3.txt Optimizer: diff --git a/configs/rec/PP-OCRv4/ch_PP-OCRv4_rec_hgnet.yml b/configs/rec/PP-OCRv4/ch_PP-OCRv4_rec_hgnet.yml index dba966e..f9e99a8 100644 --- a/configs/rec/PP-OCRv4/ch_PP-OCRv4_rec_hgnet.yml +++ b/configs/rec/PP-OCRv4/ch_PP-OCRv4_rec_hgnet.yml @@ -4,7 +4,7 @@ Global: epoch_num: 200 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec_ppocr_v4_hgnet + save_model_dir: ./json/rec_ppocr_v4_hgnet save_epoch_step: 10 eval_batch_step: [0, 2000] cal_metric_during_train: true @@ -18,7 +18,7 @@ Global: infer_mode: false use_space_char: true distributed: true - save_res_path: ./output/rec/predicts_ppocrv3.txt + save_res_path: ./json/rec/predicts_ppocrv3.txt Optimizer: diff --git a/configs/rec/PP-OCRv4/ch_PP-OCRv4_rec_hgnet_ampO2_ultra.yml b/configs/rec/PP-OCRv4/ch_PP-OCRv4_rec_hgnet_ampO2_ultra.yml index 4303521..43c0175 100644 --- a/configs/rec/PP-OCRv4/ch_PP-OCRv4_rec_hgnet_ampO2_ultra.yml +++ b/configs/rec/PP-OCRv4/ch_PP-OCRv4_rec_hgnet_ampO2_ultra.yml @@ -4,7 +4,7 @@ Global: epoch_num: 200 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec_ppocr_v4_hgnet + save_model_dir: ./json/rec_ppocr_v4_hgnet save_epoch_step: 10 eval_batch_step: [0, 2000] cal_metric_during_train: true @@ -18,7 +18,7 @@ Global: infer_mode: false use_space_char: true distributed: true - save_res_path: ./output/rec/predicts_ppocrv3.txt + save_res_path: ./json/rec/predicts_ppocrv3.txt use_amp: True amp_level: O2 diff --git a/configs/rec/PP-OCRv4/ch_PP-OCRv4_rec_hgnet_fp32_ultra.yml b/configs/rec/PP-OCRv4/ch_PP-OCRv4_rec_hgnet_fp32_ultra.yml index ee9ebca..76ce33d 100644 --- a/configs/rec/PP-OCRv4/ch_PP-OCRv4_rec_hgnet_fp32_ultra.yml +++ b/configs/rec/PP-OCRv4/ch_PP-OCRv4_rec_hgnet_fp32_ultra.yml @@ -4,7 +4,7 @@ Global: epoch_num: 200 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec_ppocr_v4_hgnet + save_model_dir: ./json/rec_ppocr_v4_hgnet save_epoch_step: 10 eval_batch_step: [0, 2000] cal_metric_during_train: true @@ -18,7 +18,7 @@ Global: infer_mode: false use_space_char: true distributed: true - save_res_path: ./output/rec/predicts_ppocrv3.txt + save_res_path: ./json/rec/predicts_ppocrv3.txt Optimizer: diff --git a/configs/rec/PP-OCRv4/ch_PP-OCRv4_rec_svtr_large.yml b/configs/rec/PP-OCRv4/ch_PP-OCRv4_rec_svtr_large.yml index 525d1c0..d3913ad 100644 --- a/configs/rec/PP-OCRv4/ch_PP-OCRv4_rec_svtr_large.yml +++ b/configs/rec/PP-OCRv4/ch_PP-OCRv4_rec_svtr_large.yml @@ -4,7 +4,7 @@ Global: epoch_num: 200 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec/svtr_large/ + save_model_dir: ./json/rec/svtr_large/ save_epoch_step: 10 # evaluation is run every 2000 iterations after the 0th iteration eval_batch_step: [0, 2000] @@ -19,7 +19,7 @@ Global: infer_mode: false use_space_char: true distributed: true - save_res_path: ./output/rec/predicts_svtr_large.txt + save_res_path: ./json/rec/predicts_svtr_large.txt Optimizer: diff --git a/configs/rec/PP-OCRv4/en_PP-OCRv4_rec.yml b/configs/rec/PP-OCRv4/en_PP-OCRv4_rec.yml index d4a718b..6f53efc 100644 --- a/configs/rec/PP-OCRv4/en_PP-OCRv4_rec.yml +++ b/configs/rec/PP-OCRv4/en_PP-OCRv4_rec.yml @@ -4,7 +4,7 @@ Global: epoch_num: 50 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec_ppocr_v4 + save_model_dir: ./json/rec_ppocr_v4 save_epoch_step: 10 eval_batch_step: - 0 @@ -20,7 +20,7 @@ Global: infer_mode: false use_space_char: true distributed: true - save_res_path: ./output/rec/predicts_ppocrv3.txt + save_res_path: ./json/rec/predicts_ppocrv3.txt Optimizer: name: Adam beta1: 0.9 diff --git a/configs/rec/SVTRv2/rec_repsvtr_ch.yml b/configs/rec/SVTRv2/rec_repsvtr_ch.yml index 4fd643b..3c3c673 100644 --- a/configs/rec/SVTRv2/rec_repsvtr_ch.yml +++ b/configs/rec/SVTRv2/rec_repsvtr_ch.yml @@ -4,7 +4,7 @@ Global: epoch_num: 200 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec_repsvtr_ch + save_model_dir: ./json/rec_repsvtr_ch save_epoch_step: 10 eval_batch_step: [0, 1000] cal_metric_during_train: False @@ -18,7 +18,7 @@ Global: infer_mode: false use_space_char: true distributed: true - save_res_path: ./output/rec/predicts_repsvtr.txt + save_res_path: ./json/rec/predicts_repsvtr.txt Optimizer: name: AdamW diff --git a/configs/rec/SVTRv2/rec_repsvtr_gtc.yml b/configs/rec/SVTRv2/rec_repsvtr_gtc.yml index 6d1340e..ee7f95f 100644 --- a/configs/rec/SVTRv2/rec_repsvtr_gtc.yml +++ b/configs/rec/SVTRv2/rec_repsvtr_gtc.yml @@ -4,7 +4,7 @@ Global: epoch_num: 200 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec_repsvtr_gtc + save_model_dir: ./json/rec_repsvtr_gtc save_epoch_step: 10 eval_batch_step: [0, 1000] cal_metric_during_train: False @@ -18,7 +18,7 @@ Global: infer_mode: false use_space_char: true distributed: true - save_res_path: ./output/rec/predicts_repsvtr.txt + save_res_path: ./json/rec/predicts_repsvtr.txt Optimizer: name: AdamW diff --git a/configs/rec/SVTRv2/rec_svtrv2_ch.yml b/configs/rec/SVTRv2/rec_svtrv2_ch.yml index 70efe10..c35d556 100644 --- a/configs/rec/SVTRv2/rec_svtrv2_ch.yml +++ b/configs/rec/SVTRv2/rec_svtrv2_ch.yml @@ -4,7 +4,7 @@ Global: epoch_num: 200 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec_svtrv2_ch + save_model_dir: ./json/rec_svtrv2_ch save_epoch_step: 10 eval_batch_step: [0, 1000] cal_metric_during_train: False @@ -18,7 +18,7 @@ Global: infer_mode: false use_space_char: true distributed: true - save_res_path: ./output/rec/predicts_svrtv2.txt + save_res_path: ./json/rec/predicts_svrtv2.txt Optimizer: diff --git a/configs/rec/SVTRv2/rec_svtrv2_ch_distillation.yml b/configs/rec/SVTRv2/rec_svtrv2_ch_distillation.yml index 071070e..2ab8cdb 100644 --- a/configs/rec/SVTRv2/rec_svtrv2_ch_distillation.yml +++ b/configs/rec/SVTRv2/rec_svtrv2_ch_distillation.yml @@ -4,7 +4,7 @@ Global: epoch_num: 100 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec_svtrv2_ch_distill_lr00002/ + save_model_dir: ./json/rec_svtrv2_ch_distill_lr00002/ save_epoch_step: 5 eval_batch_step: - 0 @@ -20,7 +20,7 @@ Global: infer_mode: false use_space_char: true distributed: true - save_res_path: ./output/rec/predicts_svtrv2_ch_distill.txt + save_res_path: ./json/rec/predicts_svtrv2_ch_distill.txt Optimizer: name: AdamW beta1: 0.9 @@ -39,7 +39,7 @@ Architecture: algorithm: Distillation Models: Teacher: - pretrained: ./output/rec_svtrv2_ch/best_accuracy + pretrained: ./json/rec_svtrv2_ch/best_accuracy freeze_params: true return_all_feats: true model_type: rec @@ -74,7 +74,7 @@ Architecture: num_decoder_layers: 2 max_text_length: *max_text_length Student: - pretrained: ./output/rec_repsvtr_ch/best_accuracy + pretrained: ./json/rec_repsvtr_ch/best_accuracy freeze_params: false return_all_feats: true model_type: rec diff --git a/configs/rec/SVTRv2/rec_svtrv2_gtc.yml b/configs/rec/SVTRv2/rec_svtrv2_gtc.yml index d2ab95a..21ee1e8 100644 --- a/configs/rec/SVTRv2/rec_svtrv2_gtc.yml +++ b/configs/rec/SVTRv2/rec_svtrv2_gtc.yml @@ -4,7 +4,7 @@ Global: epoch_num: 200 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec_svtrv2_gtc + save_model_dir: ./json/rec_svtrv2_gtc save_epoch_step: 10 eval_batch_step: [0, 1000] cal_metric_during_train: False @@ -18,7 +18,7 @@ Global: infer_mode: false use_space_char: true distributed: true - save_res_path: ./output/rec/predicts_svrtv2.txt + save_res_path: ./json/rec/predicts_svrtv2.txt Optimizer: diff --git a/configs/rec/SVTRv2/rec_svtrv2_gtc_distill.yml b/configs/rec/SVTRv2/rec_svtrv2_gtc_distill.yml index 15d781f..2755b83 100644 --- a/configs/rec/SVTRv2/rec_svtrv2_gtc_distill.yml +++ b/configs/rec/SVTRv2/rec_svtrv2_gtc_distill.yml @@ -4,7 +4,7 @@ Global: epoch_num: 100 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec_svtrv2_gtc_distill_lr00002/ + save_model_dir: ./json/rec_svtrv2_gtc_distill_lr00002/ save_epoch_step: 5 eval_batch_step: - 0 @@ -20,7 +20,7 @@ Global: infer_mode: false use_space_char: true distributed: true - save_res_path: ./output/rec/predicts_svtrv2_gtc_distill.txt + save_res_path: ./json/rec/predicts_svtrv2_gtc_distill.txt Optimizer: name: AdamW beta1: 0.9 @@ -39,7 +39,7 @@ Architecture: algorithm: Distillation Models: Teacher: - pretrained: ./output/rec_svtrv2_gtc/best_accuracy + pretrained: ./json/rec_svtrv2_gtc/best_accuracy freeze_params: true return_all_feats: true model_type: rec @@ -74,7 +74,7 @@ Architecture: num_decoder_layers: 2 max_text_length: *max_text_length Student: - pretrained: ./output/rec_repsvtr_gtc/best_accuracy + pretrained: ./json/rec_repsvtr_gtc/best_accuracy freeze_params: false return_all_feats: true model_type: rec diff --git a/configs/rec/ch_PP-OCRv2/ch_PP-OCRv2_rec.yml b/configs/rec/ch_PP-OCRv2/ch_PP-OCRv2_rec.yml index 793bb5c..416af61 100644 --- a/configs/rec/ch_PP-OCRv2/ch_PP-OCRv2_rec.yml +++ b/configs/rec/ch_PP-OCRv2/ch_PP-OCRv2_rec.yml @@ -4,7 +4,7 @@ Global: epoch_num: 800 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec_mobile_pp-OCRv2 + save_model_dir: ./json/rec_mobile_pp-OCRv2 save_epoch_step: 3 eval_batch_step: [0, 2000] cal_metric_during_train: true @@ -18,7 +18,7 @@ Global: infer_mode: false use_space_char: true distributed: true - save_res_path: ./output/rec/predicts_mobile_pp-OCRv2.txt + save_res_path: ./json/rec/predicts_mobile_pp-OCRv2.txt Optimizer: diff --git a/configs/rec/ch_PP-OCRv2/ch_PP-OCRv2_rec_distillation.yml b/configs/rec/ch_PP-OCRv2/ch_PP-OCRv2_rec_distillation.yml index 3855005..2c84f16 100644 --- a/configs/rec/ch_PP-OCRv2/ch_PP-OCRv2_rec_distillation.yml +++ b/configs/rec/ch_PP-OCRv2/ch_PP-OCRv2_rec_distillation.yml @@ -4,7 +4,7 @@ Global: epoch_num: 800 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec_pp-OCRv2_distillation + save_model_dir: ./json/rec_pp-OCRv2_distillation save_epoch_step: 3 eval_batch_step: [0, 2000] cal_metric_during_train: true @@ -18,7 +18,7 @@ Global: infer_mode: false use_space_char: true distributed: true - save_res_path: ./output/rec/predicts_pp-OCRv2_distillation.txt + save_res_path: ./json/rec/predicts_pp-OCRv2_distillation.txt amp_custom_black_list: ['matmul','matmul_v2','elementwise_add'] diff --git a/configs/rec/ch_PP-OCRv2/ch_PP-OCRv2_rec_enhanced_ctc_loss.yml b/configs/rec/ch_PP-OCRv2/ch_PP-OCRv2_rec_enhanced_ctc_loss.yml index ef0e893..5d96331 100644 --- a/configs/rec/ch_PP-OCRv2/ch_PP-OCRv2_rec_enhanced_ctc_loss.yml +++ b/configs/rec/ch_PP-OCRv2/ch_PP-OCRv2_rec_enhanced_ctc_loss.yml @@ -4,7 +4,7 @@ Global: epoch_num: 800 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec_mobile_pp-OCRv2_enhanced_ctc_loss + save_model_dir: ./json/rec_mobile_pp-OCRv2_enhanced_ctc_loss save_epoch_step: 3 eval_batch_step: [0, 2000] cal_metric_during_train: true @@ -18,7 +18,7 @@ Global: infer_mode: false use_space_char: true distributed: true - save_res_path: ./output/rec/predicts_mobile_pp-OCRv2_enhanced_ctc_loss.txt + save_res_path: ./json/rec/predicts_mobile_pp-OCRv2_enhanced_ctc_loss.txt Optimizer: diff --git a/configs/rec/ch_ppocr_v2.0/rec_chinese_common_train_v2.0.yml b/configs/rec/ch_ppocr_v2.0/rec_chinese_common_train_v2.0.yml index 3e427b6..13daf75 100644 --- a/configs/rec/ch_ppocr_v2.0/rec_chinese_common_train_v2.0.yml +++ b/configs/rec/ch_ppocr_v2.0/rec_chinese_common_train_v2.0.yml @@ -3,7 +3,7 @@ Global: epoch_num: 500 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec_chinese_common_v2.0 + save_model_dir: ./json/rec_chinese_common_v2.0 save_epoch_step: 3 # evaluation is run every 5000 iterations after the 4000th iteration eval_batch_step: [0, 2000] @@ -18,7 +18,7 @@ Global: max_text_length: 25 infer_mode: False use_space_char: True - save_res_path: ./output/rec/predicts_chinese_common_v2.0.txt + save_res_path: ./json/rec/predicts_chinese_common_v2.0.txt Optimizer: diff --git a/configs/rec/ch_ppocr_v2.0/rec_chinese_lite_train_v2.0.yml b/configs/rec/ch_ppocr_v2.0/rec_chinese_lite_train_v2.0.yml index abd5cd9..6a6415a 100644 --- a/configs/rec/ch_ppocr_v2.0/rec_chinese_lite_train_v2.0.yml +++ b/configs/rec/ch_ppocr_v2.0/rec_chinese_lite_train_v2.0.yml @@ -3,7 +3,7 @@ Global: epoch_num: 500 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec_chinese_lite_v2.0 + save_model_dir: ./json/rec_chinese_lite_v2.0 save_epoch_step: 3 # evaluation is run every 5000 iterations after the 4000th iteration eval_batch_step: [0, 2000] @@ -18,7 +18,7 @@ Global: max_text_length: 25 infer_mode: False use_space_char: True - save_res_path: ./output/rec/predicts_chinese_lite_v2.0.txt + save_res_path: ./json/rec/predicts_chinese_lite_v2.0.txt Optimizer: diff --git a/configs/rec/multi_language/generate_multi_language_configs.py b/configs/rec/multi_language/generate_multi_language_configs.py index d4b0b51..e991106 100644 --- a/configs/rec/multi_language/generate_multi_language_configs.py +++ b/configs/rec/multi_language/generate_multi_language_configs.py @@ -201,7 +201,7 @@ class ArgsParser(ArgumentParser): global_config["Global"]["character_dict_path"] = ( "ppocr/utils/dict/{}_dict.txt".format(lang) ) - global_config["Global"]["save_model_dir"] = "./output/rec_{}_lite".format(lang) + global_config["Global"]["save_model_dir"] = "./json/rec_{}_lite".format(lang) global_config["Train"]["dataset"]["label_file_list"] = [ "train_data/{}_train.txt".format(lang) ] diff --git a/configs/rec/multi_language/rec_arabic_lite_train.yml b/configs/rec/multi_language/rec_arabic_lite_train.yml index a746260..dec0e82 100644 --- a/configs/rec/multi_language/rec_arabic_lite_train.yml +++ b/configs/rec/multi_language/rec_arabic_lite_train.yml @@ -3,7 +3,7 @@ Global: epoch_num: 500 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec_arabic_lite + save_model_dir: ./json/rec_arabic_lite save_epoch_step: 3 eval_batch_step: - 0 diff --git a/configs/rec/multi_language/rec_cyrillic_lite_train.yml b/configs/rec/multi_language/rec_cyrillic_lite_train.yml index 98544f6..6b90a91 100644 --- a/configs/rec/multi_language/rec_cyrillic_lite_train.yml +++ b/configs/rec/multi_language/rec_cyrillic_lite_train.yml @@ -3,7 +3,7 @@ Global: epoch_num: 500 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec_cyrillic_lite + save_model_dir: ./json/rec_cyrillic_lite save_epoch_step: 3 eval_batch_step: - 0 diff --git a/configs/rec/multi_language/rec_devanagari_lite_train.yml b/configs/rec/multi_language/rec_devanagari_lite_train.yml index 518b9f1..6539a9c 100644 --- a/configs/rec/multi_language/rec_devanagari_lite_train.yml +++ b/configs/rec/multi_language/rec_devanagari_lite_train.yml @@ -3,7 +3,7 @@ Global: epoch_num: 500 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec_devanagari_lite + save_model_dir: ./json/rec_devanagari_lite save_epoch_step: 3 eval_batch_step: - 0 diff --git a/configs/rec/multi_language/rec_en_number_lite_train.yml b/configs/rec/multi_language/rec_en_number_lite_train.yml index ff1fb86..050d673 100644 --- a/configs/rec/multi_language/rec_en_number_lite_train.yml +++ b/configs/rec/multi_language/rec_en_number_lite_train.yml @@ -3,7 +3,7 @@ Global: epoch_num: 500 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec_en_number_lite + save_model_dir: ./json/rec_en_number_lite save_epoch_step: 3 # evaluation is run every 5000 iterations after the 4000th iteration eval_batch_step: [0, 2000] diff --git a/configs/rec/multi_language/rec_french_lite_train.yml b/configs/rec/multi_language/rec_french_lite_train.yml index 217369d..55365ab 100644 --- a/configs/rec/multi_language/rec_french_lite_train.yml +++ b/configs/rec/multi_language/rec_french_lite_train.yml @@ -3,7 +3,7 @@ Global: epoch_num: 500 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec_french_lite + save_model_dir: ./json/rec_french_lite save_epoch_step: 3 # evaluation is run every 5000 iterations after the 4000th iteration eval_batch_step: [0, 2000] diff --git a/configs/rec/multi_language/rec_german_lite_train.yml b/configs/rec/multi_language/rec_german_lite_train.yml index 67520f5..2fc68e7 100644 --- a/configs/rec/multi_language/rec_german_lite_train.yml +++ b/configs/rec/multi_language/rec_german_lite_train.yml @@ -3,7 +3,7 @@ Global: epoch_num: 500 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec_german_lite + save_model_dir: ./json/rec_german_lite save_epoch_step: 3 # evaluation is run every 5000 iterations after the 4000th iteration eval_batch_step: [0, 2000] diff --git a/configs/rec/multi_language/rec_japan_lite_train.yml b/configs/rec/multi_language/rec_japan_lite_train.yml index 448aff1..a6c9779 100644 --- a/configs/rec/multi_language/rec_japan_lite_train.yml +++ b/configs/rec/multi_language/rec_japan_lite_train.yml @@ -3,7 +3,7 @@ Global: epoch_num: 500 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec_japan_lite + save_model_dir: ./json/rec_japan_lite save_epoch_step: 3 # evaluation is run every 5000 iterations after the 4000th iteration eval_batch_step: [0, 2000] diff --git a/configs/rec/multi_language/rec_korean_lite_train.yml b/configs/rec/multi_language/rec_korean_lite_train.yml index 8118119..f1a830e 100644 --- a/configs/rec/multi_language/rec_korean_lite_train.yml +++ b/configs/rec/multi_language/rec_korean_lite_train.yml @@ -3,7 +3,7 @@ Global: epoch_num: 500 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec_korean_lite + save_model_dir: ./json/rec_korean_lite save_epoch_step: 3 # evaluation is run every 5000 iterations after the 4000th iteration eval_batch_step: [0, 2000] diff --git a/configs/rec/multi_language/rec_latin_lite_train.yml b/configs/rec/multi_language/rec_latin_lite_train.yml index 04fe6d1..511e0cd 100644 --- a/configs/rec/multi_language/rec_latin_lite_train.yml +++ b/configs/rec/multi_language/rec_latin_lite_train.yml @@ -3,7 +3,7 @@ Global: epoch_num: 500 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec_latin_lite + save_model_dir: ./json/rec_latin_lite save_epoch_step: 3 eval_batch_step: - 0 diff --git a/configs/rec/multi_language/rec_multi_language_lite_train.yml b/configs/rec/multi_language/rec_multi_language_lite_train.yml index c42a3d1..8dbfd68 100644 --- a/configs/rec/multi_language/rec_multi_language_lite_train.yml +++ b/configs/rec/multi_language/rec_multi_language_lite_train.yml @@ -3,7 +3,7 @@ Global: epoch_num: 500 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec_multi_language_lite + save_model_dir: ./json/rec_multi_language_lite save_epoch_step: 3 # evaluation is run every 5000 iterations after the 4000th iteration eval_batch_step: [0, 2000] diff --git a/configs/rec/rec_d28_can.yml b/configs/rec/rec_d28_can.yml index 7c3b0fd..2549a18 100644 --- a/configs/rec/rec_d28_can.yml +++ b/configs/rec/rec_d28_can.yml @@ -3,7 +3,7 @@ Global: epoch_num: 240 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec/can/ + save_model_dir: ./json/rec/can/ save_epoch_step: 1 # evaluation is run every 1105 iterations (1 epoch)(batch_size = 8) eval_batch_step: [0, 1105] @@ -18,7 +18,7 @@ Global: max_text_length: 36 infer_mode: False use_space_char: False - save_res_path: ./output/rec/predicts_can.txt + save_res_path: ./json/rec/predicts_can.txt Optimizer: name: Momentum diff --git a/configs/rec/rec_efficientb3_fpn_pren.yml b/configs/rec/rec_efficientb3_fpn_pren.yml index 0fac6a7..61f2e10 100644 --- a/configs/rec/rec_efficientb3_fpn_pren.yml +++ b/configs/rec/rec_efficientb3_fpn_pren.yml @@ -3,7 +3,7 @@ Global: epoch_num: 8 log_smooth_window: 20 print_batch_step: 5 - save_model_dir: ./output/rec/pren_new + save_model_dir: ./json/rec/pren_new save_epoch_step: 3 # evaluation is run every 2000 iterations after the 4000th iteration eval_batch_step: [4000, 2000] @@ -18,7 +18,7 @@ Global: max_text_length: &max_text_length 25 infer_mode: False use_space_char: False - save_res_path: ./output/rec/predicts_pren.txt + save_res_path: ./json/rec/predicts_pren.txt Optimizer: name: Adadelta diff --git a/configs/rec/rec_icdar15_train.yml b/configs/rec/rec_icdar15_train.yml index 893f738..4e0891c 100644 --- a/configs/rec/rec_icdar15_train.yml +++ b/configs/rec/rec_icdar15_train.yml @@ -3,7 +3,7 @@ Global: epoch_num: 72 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec/ic15/ + save_model_dir: ./json/rec/ic15/ save_epoch_step: 3 # evaluation is run every 2000 iterations eval_batch_step: [0, 2000] @@ -18,7 +18,7 @@ Global: max_text_length: 25 infer_mode: False use_space_char: False - save_res_path: ./output/rec/predicts_ic15.txt + save_res_path: ./json/rec/predicts_ic15.txt Optimizer: name: Adam diff --git a/configs/rec/rec_latex_ocr.yml b/configs/rec/rec_latex_ocr.yml index 2c604bf..4822b31 100644 --- a/configs/rec/rec_latex_ocr.yml +++ b/configs/rec/rec_latex_ocr.yml @@ -3,7 +3,7 @@ Global: epoch_num: 500 log_smooth_window: 20 print_batch_step: 100 - save_model_dir: ./output/rec/latex_ocr/ + save_model_dir: ./json/rec/latex_ocr/ save_epoch_step: 5 max_seq_len: 512 # evaluation is run every 60000 iterations (22 epoch)(batch_size = 56) @@ -17,7 +17,7 @@ Global: infer_mode: False use_space_char: False rec_char_dict_path: ppocr/utils/dict/latex_ocr_tokenizer.json - save_res_path: ./output/rec/predicts_latexocr.txt + save_res_path: ./json/rec/predicts_latexocr.txt Optimizer: name: AdamW diff --git a/configs/rec/rec_mtb_nrtr.yml b/configs/rec/rec_mtb_nrtr.yml index aa9a347..f50d7e4 100644 --- a/configs/rec/rec_mtb_nrtr.yml +++ b/configs/rec/rec_mtb_nrtr.yml @@ -3,7 +3,7 @@ Global: epoch_num: 21 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec/nrtr/ + save_model_dir: ./json/rec/nrtr/ save_epoch_step: 1 # evaluation is run every 2000 iterations eval_batch_step: [0, 2000] @@ -18,7 +18,7 @@ Global: max_text_length: 25 infer_mode: False use_space_char: False - save_res_path: ./output/rec/predicts_nrtr.txt + save_res_path: ./json/rec/predicts_nrtr.txt Optimizer: name: Adam diff --git a/configs/rec/rec_mv3_none_bilstm_ctc.yml b/configs/rec/rec_mv3_none_bilstm_ctc.yml index 9a95092..906d2e4 100644 --- a/configs/rec/rec_mv3_none_bilstm_ctc.yml +++ b/configs/rec/rec_mv3_none_bilstm_ctc.yml @@ -3,7 +3,7 @@ Global: epoch_num: 72 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec/mv3_none_bilstm_ctc/ + save_model_dir: ./json/rec/mv3_none_bilstm_ctc/ save_epoch_step: 3 # evaluation is run every 2000 iterations eval_batch_step: [0, 2000] @@ -18,7 +18,7 @@ Global: max_text_length: 25 infer_mode: False use_space_char: False - save_res_path: ./output/rec/predicts_mv3_none_bilstm_ctc.txt + save_res_path: ./json/rec/predicts_mv3_none_bilstm_ctc.txt Optimizer: name: Adam diff --git a/configs/rec/rec_mv3_none_none_ctc.yml b/configs/rec/rec_mv3_none_none_ctc.yml index 28f0252..21fba92 100644 --- a/configs/rec/rec_mv3_none_none_ctc.yml +++ b/configs/rec/rec_mv3_none_none_ctc.yml @@ -3,7 +3,7 @@ Global: epoch_num: 72 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec/mv3_none_none_ctc/ + save_model_dir: ./json/rec/mv3_none_none_ctc/ save_epoch_step: 3 # evaluation is run every 2000 iterations eval_batch_step: [0, 2000] @@ -18,7 +18,7 @@ Global: max_text_length: 25 infer_mode: False use_space_char: False - save_res_path: ./output/rec/predicts_mv3_none_none_ctc.txt + save_res_path: ./json/rec/predicts_mv3_none_none_ctc.txt Optimizer: name: Adam diff --git a/configs/rec/rec_mv3_tps_bilstm_att.yml b/configs/rec/rec_mv3_tps_bilstm_att.yml index 6c347e7..3611e89 100644 --- a/configs/rec/rec_mv3_tps_bilstm_att.yml +++ b/configs/rec/rec_mv3_tps_bilstm_att.yml @@ -3,7 +3,7 @@ Global: epoch_num: 72 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec/rec_mv3_tps_bilstm_att/ + save_model_dir: ./json/rec/rec_mv3_tps_bilstm_att/ save_epoch_step: 3 # evaluation is run every 5000 iterations after the 4000th iteration eval_batch_step: [0, 2000] @@ -18,7 +18,7 @@ Global: max_text_length: 25 infer_mode: False use_space_char: False - save_res_path: ./output/rec/predicts_mv3_tps_bilstm_att.txt + save_res_path: ./json/rec/predicts_mv3_tps_bilstm_att.txt Optimizer: diff --git a/configs/rec/rec_mv3_tps_bilstm_ctc.yml b/configs/rec/rec_mv3_tps_bilstm_ctc.yml index 9d1ebbe..5461c1c 100644 --- a/configs/rec/rec_mv3_tps_bilstm_ctc.yml +++ b/configs/rec/rec_mv3_tps_bilstm_ctc.yml @@ -3,7 +3,7 @@ Global: epoch_num: 72 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec/mv3_tps_bilstm_ctc/ + save_model_dir: ./json/rec/mv3_tps_bilstm_ctc/ save_epoch_step: 3 # evaluation is run every 2000 iterations eval_batch_step: [0, 2000] @@ -18,7 +18,7 @@ Global: max_text_length: 25 infer_mode: False use_space_char: False - save_res_path: ./output/rec/predicts_mv3_tps_bilstm_ctc.txt + save_res_path: ./json/rec/predicts_mv3_tps_bilstm_ctc.txt Optimizer: name: Adam diff --git a/configs/rec/rec_r31_robustscanner.yml b/configs/rec/rec_r31_robustscanner.yml index 54b69d4..d5eed3a 100644 --- a/configs/rec/rec_r31_robustscanner.yml +++ b/configs/rec/rec_r31_robustscanner.yml @@ -3,7 +3,7 @@ Global: epoch_num: 5 log_smooth_window: 20 print_batch_step: 20 - save_model_dir: ./output/rec/rec_r31_robustscanner/ + save_model_dir: ./json/rec/rec_r31_robustscanner/ save_epoch_step: 1 # evaluation is run every 2000 iterations eval_batch_step: [0, 2000] @@ -19,7 +19,7 @@ Global: infer_mode: False use_space_char: False rm_symbol: True - save_res_path: ./output/rec/predicts_robustscanner.txt + save_res_path: ./json/rec/predicts_robustscanner.txt Optimizer: name: Adam diff --git a/configs/rec/rec_r31_sar.yml b/configs/rec/rec_r31_sar.yml index 65e7877..788e028 100644 --- a/configs/rec/rec_r31_sar.yml +++ b/configs/rec/rec_r31_sar.yml @@ -19,7 +19,7 @@ Global: infer_mode: False use_space_char: False rm_symbol: True - save_res_path: ./output/rec/predicts_sar.txt + save_res_path: ./json/rec/predicts_sar.txt Optimizer: name: Adam diff --git a/configs/rec/rec_r32_gaspin_bilstm_att.yml b/configs/rec/rec_r32_gaspin_bilstm_att.yml index 91d3e10..2e2e049 100644 --- a/configs/rec/rec_r32_gaspin_bilstm_att.yml +++ b/configs/rec/rec_r32_gaspin_bilstm_att.yml @@ -3,7 +3,7 @@ Global: epoch_num: 6 log_smooth_window: 50 print_batch_step: 50 - save_model_dir: ./output/rec/rec_r32_gaspin_bilstm_att/ + save_model_dir: ./json/rec/rec_r32_gaspin_bilstm_att/ save_epoch_step: 3 # evaluation is run every 2000 iterations after the 4000th iteration eval_batch_step: [0, 2000] @@ -18,7 +18,7 @@ Global: max_text_length: 25 infer_mode: False use_space_char: False - save_res_path: ./output/rec/predicts_r32_gaspin_bilstm_att.txt + save_res_path: ./json/rec/predicts_r32_gaspin_bilstm_att.txt Optimizer: diff --git a/configs/rec/rec_r34_vd_none_bilstm_ctc.yml b/configs/rec/rec_r34_vd_none_bilstm_ctc.yml index 9fdb5e9..ac2896b 100644 --- a/configs/rec/rec_r34_vd_none_bilstm_ctc.yml +++ b/configs/rec/rec_r34_vd_none_bilstm_ctc.yml @@ -3,7 +3,7 @@ Global: epoch_num: 72 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec/r34_vd_none_bilstm_ctc/ + save_model_dir: ./json/rec/r34_vd_none_bilstm_ctc/ save_epoch_step: 3 # evaluation is run every 2000 iterations eval_batch_step: [0, 2000] @@ -18,7 +18,7 @@ Global: max_text_length: 25 infer_mode: False use_space_char: False - save_res_path: ./output/rec/predicts_r34_vd_none_bilstm_ctc.txt + save_res_path: ./json/rec/predicts_r34_vd_none_bilstm_ctc.txt Optimizer: name: Adam diff --git a/configs/rec/rec_r34_vd_none_none_ctc.yml b/configs/rec/rec_r34_vd_none_none_ctc.yml index 0af2b2f..63e9eca 100644 --- a/configs/rec/rec_r34_vd_none_none_ctc.yml +++ b/configs/rec/rec_r34_vd_none_none_ctc.yml @@ -3,7 +3,7 @@ Global: epoch_num: 72 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec/r34_vd_none_none_ctc/ + save_model_dir: ./json/rec/r34_vd_none_none_ctc/ save_epoch_step: 3 # evaluation is run every 2000 iterations eval_batch_step: [0, 2000] @@ -18,7 +18,7 @@ Global: max_text_length: 25 infer_mode: False use_space_char: False - save_res_path: ./output/rec/predicts_r34_vd_none_none_ctc.txt + save_res_path: ./json/rec/predicts_r34_vd_none_none_ctc.txt Optimizer: name: Adam diff --git a/configs/rec/rec_r34_vd_tps_bilstm_att.yml b/configs/rec/rec_r34_vd_tps_bilstm_att.yml index 8919aae..57ef1e3 100644 --- a/configs/rec/rec_r34_vd_tps_bilstm_att.yml +++ b/configs/rec/rec_r34_vd_tps_bilstm_att.yml @@ -3,7 +3,7 @@ Global: epoch_num: 400 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec/b3_rare_r34_none_gru/ + save_model_dir: ./json/rec/b3_rare_r34_none_gru/ save_epoch_step: 3 # evaluation is run every 5000 iterations after the 4000th iteration eval_batch_step: [0, 2000] @@ -18,7 +18,7 @@ Global: max_text_length: 25 infer_mode: False use_space_char: False - save_res_path: ./output/rec/predicts_b3_rare_r34_none_gru.txt + save_res_path: ./json/rec/predicts_b3_rare_r34_none_gru.txt Optimizer: diff --git a/configs/rec/rec_r34_vd_tps_bilstm_ctc.yml b/configs/rec/rec_r34_vd_tps_bilstm_ctc.yml index c21fe61..5eb5f12 100644 --- a/configs/rec/rec_r34_vd_tps_bilstm_ctc.yml +++ b/configs/rec/rec_r34_vd_tps_bilstm_ctc.yml @@ -3,7 +3,7 @@ Global: epoch_num: 72 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec/r34_vd_tps_bilstm_ctc/ + save_model_dir: ./json/rec/r34_vd_tps_bilstm_ctc/ save_epoch_step: 3 # evaluation is run every 2000 iterations eval_batch_step: [0, 2000] @@ -18,7 +18,7 @@ Global: max_text_length: 25 infer_mode: False use_space_char: False - save_res_path: ./output/rec/predicts_r34_vd_tps_bilstm_ctc.txt + save_res_path: ./json/rec/predicts_r34_vd_tps_bilstm_ctc.txt Optimizer: name: Adam diff --git a/configs/rec/rec_r45_abinet.yml b/configs/rec/rec_r45_abinet.yml index db2f28f..f886ed4 100644 --- a/configs/rec/rec_r45_abinet.yml +++ b/configs/rec/rec_r45_abinet.yml @@ -3,14 +3,14 @@ Global: epoch_num: 10 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec/r45_abinet/ + save_model_dir: ./json/rec/r45_abinet/ save_epoch_step: 1 # evaluation is run every 2000 iterations eval_batch_step: [0, 2000] cal_metric_during_train: True pretrained_model: ./pretrain_models/abinet_vl_pretrained checkpoints: - save_inference_dir: ./output/rec/r45_abinet/infer + save_inference_dir: ./json/rec/r45_abinet/infer use_visualdl: False infer_img: doc/imgs_words_en/word_10.png # for data or label process @@ -19,7 +19,7 @@ Global: max_text_length: &max_text_length 25 infer_mode: False use_space_char: False - save_res_path: ./output/rec/predicts_abinet.txt + save_res_path: ./json/rec/predicts_abinet.txt Optimizer: name: Adam diff --git a/configs/rec/rec_r45_visionlan.yml b/configs/rec/rec_r45_visionlan.yml index 2501765..d975181 100644 --- a/configs/rec/rec_r45_visionlan.yml +++ b/configs/rec/rec_r45_visionlan.yml @@ -3,7 +3,7 @@ Global: epoch_num: 8 log_smooth_window: 200 print_batch_step: 200 - save_model_dir: ./output/rec/r45_visionlan + save_model_dir: ./json/rec/r45_visionlan save_epoch_step: 1 # evaluation is run every 2000 iterations eval_batch_step: [0, 2000] @@ -19,7 +19,7 @@ Global: training_step: &training_step LA infer_mode: False use_space_char: False - save_res_path: ./output/rec/predicts_visionlan.txt + save_res_path: ./json/rec/predicts_visionlan.txt Optimizer: name: Adam diff --git a/configs/rec/rec_r50_fpn_srn.yml b/configs/rec/rec_r50_fpn_srn.yml index b685362..5b7cde5 100644 --- a/configs/rec/rec_r50_fpn_srn.yml +++ b/configs/rec/rec_r50_fpn_srn.yml @@ -3,7 +3,7 @@ Global: epoch_num: 72 log_smooth_window: 20 print_batch_step: 5 - save_model_dir: ./output/rec/srn_new + save_model_dir: ./json/rec/srn_new save_epoch_step: 3 # evaluation is run every 5000 iterations after the 4000th iteration eval_batch_step: [0, 5000] @@ -19,7 +19,7 @@ Global: num_heads: 8 infer_mode: False use_space_char: False - save_res_path: ./output/rec/predicts_srn.txt + save_res_path: ./json/rec/predicts_srn.txt Optimizer: diff --git a/configs/rec/rec_resnet_rfl_att.yml b/configs/rec/rec_resnet_rfl_att.yml index b9fb741..18e8003 100644 --- a/configs/rec/rec_resnet_rfl_att.yml +++ b/configs/rec/rec_resnet_rfl_att.yml @@ -3,7 +3,7 @@ Global: epoch_num: 6 log_smooth_window: 20 print_batch_step: 50 - save_model_dir: ./output/rec/rec_resnet_rfl_att/ + save_model_dir: ./json/rec/rec_resnet_rfl_att/ save_epoch_step: 1 # evaluation is run every 5000 iterations after the 4000th iteration eval_batch_step: [0, 5000] @@ -18,7 +18,7 @@ Global: max_text_length: 25 infer_mode: False use_space_char: False - save_res_path: ./output/rec/rec_resnet_rfl.txt + save_res_path: ./json/rec/rec_resnet_rfl.txt Optimizer: diff --git a/configs/rec/rec_resnet_rfl_visual.yml b/configs/rec/rec_resnet_rfl_visual.yml index 5eaea08..1840b2e 100644 --- a/configs/rec/rec_resnet_rfl_visual.yml +++ b/configs/rec/rec_resnet_rfl_visual.yml @@ -3,7 +3,7 @@ Global: epoch_num: 6 log_smooth_window: 20 print_batch_step: 50 - save_model_dir: ./output/rec/rec_resnet_rfl_visual/ + save_model_dir: ./json/rec/rec_resnet_rfl_visual/ save_epoch_step: 1 # evaluation is run every 5000 iterations after the 4000th iteration eval_batch_step: [0, 5000] @@ -18,7 +18,7 @@ Global: max_text_length: 25 infer_mode: False use_space_char: False - save_res_path: ./output/rec/rec_resnet_rfl_visual.txt + save_res_path: ./json/rec/rec_resnet_rfl_visual.txt Optimizer: diff --git a/configs/rec/rec_resnet_stn_bilstm_att.yml b/configs/rec/rec_resnet_stn_bilstm_att.yml index 20ed953..0554c01 100644 --- a/configs/rec/rec_resnet_stn_bilstm_att.yml +++ b/configs/rec/rec_resnet_stn_bilstm_att.yml @@ -3,7 +3,7 @@ Global: epoch_num: 6 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec/seed + save_model_dir: ./json/rec/seed save_epoch_step: 3 # evaluation is run every 5000 iterations after the 4000th iteration eval_batch_step: [0, 2000] @@ -18,7 +18,7 @@ Global: max_text_length: 100 infer_mode: False use_space_char: False - save_res_path: ./output/rec/predicts_seed.txt + save_res_path: ./json/rec/predicts_seed.txt Optimizer: diff --git a/configs/rec/rec_satrn.yml b/configs/rec/rec_satrn.yml index 376c2cc..494d921 100644 --- a/configs/rec/rec_satrn.yml +++ b/configs/rec/rec_satrn.yml @@ -3,7 +3,7 @@ Global: epoch_num: 5 log_smooth_window: 20 print_batch_step: 50 - save_model_dir: ./output/rec/rec_satrn/ + save_model_dir: ./json/rec/rec_satrn/ save_epoch_step: 1 # evaluation is run every 5000 iterations eval_batch_step: [0, 5000] @@ -19,7 +19,7 @@ Global: infer_mode: False use_space_char: False rm_symbol: True - save_res_path: ./output/rec/predicts_satrn.txt + save_res_path: ./json/rec/predicts_satrn.txt Optimizer: name: Adam diff --git a/configs/rec/rec_svtrnet.yml b/configs/rec/rec_svtrnet.yml index 4657c5c..d39d3c3 100644 --- a/configs/rec/rec_svtrnet.yml +++ b/configs/rec/rec_svtrnet.yml @@ -3,7 +3,7 @@ Global: epoch_num: 20 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec/svtr/ + save_model_dir: ./json/rec/svtr/ save_epoch_step: 1 # evaluation is run every 2000 iterations after the 0th iteration eval_batch_step: [0, 2000] @@ -19,7 +19,7 @@ Global: max_text_length: 25 infer_mode: False use_space_char: False - save_res_path: ./output/rec/predicts_svtr_tiny.txt + save_res_path: ./json/rec/predicts_svtr_tiny.txt d2s_train_image_shape: [3, 64, 256] diff --git a/configs/rec/rec_svtrnet_ch.yml b/configs/rec/rec_svtrnet_ch.yml index bb82cfc..f240cc4 100644 --- a/configs/rec/rec_svtrnet_ch.yml +++ b/configs/rec/rec_svtrnet_ch.yml @@ -3,7 +3,7 @@ Global: epoch_num: 100 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec/svtr_ch_all/ + save_model_dir: ./json/rec/svtr_ch_all/ save_epoch_step: 10 eval_batch_step: - 0 @@ -18,7 +18,7 @@ Global: max_text_length: 25 infer_mode: false use_space_char: true - save_res_path: ./output/rec/predicts_svtr_tiny_ch_all.txt + save_res_path: ./json/rec/predicts_svtr_tiny_ch_all.txt d2s_train_image_shape: [3, 32, 320] Optimizer: name: AdamW diff --git a/configs/rec/rec_svtrnet_cppd_base_ch.yml b/configs/rec/rec_svtrnet_cppd_base_ch.yml index e2ed04c..5e31fac 100644 --- a/configs/rec/rec_svtrnet_cppd_base_ch.yml +++ b/configs/rec/rec_svtrnet_cppd_base_ch.yml @@ -3,7 +3,7 @@ Global: epoch_num: 100 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec/svtr_cppd_base_ch/ + save_model_dir: ./json/rec/svtr_cppd_base_ch/ save_epoch_step: 10 # evaluation is run every 2000 iterations after the 0th iteration eval_batch_step: [0, 2000] @@ -18,7 +18,7 @@ Global: max_text_length: 25 infer_mode: False use_space_char: False - save_res_path: ./output/rec/predicts_svtr_cppd_base_ch.txt + save_res_path: ./json/rec/predicts_svtr_cppd_base_ch.txt Optimizer: diff --git a/configs/rec/rec_svtrnet_cppd_base_en.yml b/configs/rec/rec_svtrnet_cppd_base_en.yml index 99885fb..9de000e 100644 --- a/configs/rec/rec_svtrnet_cppd_base_en.yml +++ b/configs/rec/rec_svtrnet_cppd_base_en.yml @@ -3,7 +3,7 @@ Global: epoch_num: 20 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec/svtr_cppd_base/ + save_model_dir: ./json/rec/svtr_cppd_base/ save_epoch_step: 1 # evaluation is run every 2000 iterations after the 0th iteration eval_batch_step: [0, 2000] @@ -19,7 +19,7 @@ Global: max_text_length: 25 infer_mode: False use_space_char: False - save_res_path: ./output/rec/predicts_svtr_cppd_base.txt + save_res_path: ./json/rec/predicts_svtr_cppd_base.txt Optimizer: diff --git a/configs/rec/rec_vit_parseq.yml b/configs/rec/rec_vit_parseq.yml index 8ba99e6..9c5b5f2 100644 --- a/configs/rec/rec_vit_parseq.yml +++ b/configs/rec/rec_vit_parseq.yml @@ -3,7 +3,7 @@ Global: epoch_num: 20 log_smooth_window: 20 print_batch_step: 5 - save_model_dir: ./output/rec/parseq + save_model_dir: ./json/rec/parseq save_epoch_step: 3 # evaluation is run every 5000 iterations after the 4000th iteration eval_batch_step: [0, 500] @@ -20,7 +20,7 @@ Global: num_heads: 8 infer_mode: False use_space_char: False - save_res_path: ./output/rec/predicts_parseq.txt + save_res_path: ./json/rec/predicts_parseq.txt Optimizer: diff --git a/configs/rec/rec_vitstr_none_ce.yml b/configs/rec/rec_vitstr_none_ce.yml index ebe304f..a0af1c5 100644 --- a/configs/rec/rec_vitstr_none_ce.yml +++ b/configs/rec/rec_vitstr_none_ce.yml @@ -3,7 +3,7 @@ Global: epoch_num: 20 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec/vitstr_none_ce/ + save_model_dir: ./json/rec/vitstr_none_ce/ save_epoch_step: 1 # evaluation is run every 2000 iterations after the 0th iteration# eval_batch_step: [0, 2000] @@ -18,7 +18,7 @@ Global: max_text_length: 25 infer_mode: False use_space_char: False - save_res_path: ./output/rec/predicts_vitstr.txt + save_res_path: ./json/rec/predicts_vitstr.txt Optimizer: diff --git a/configs/sr/sr_telescope.yml b/configs/sr/sr_telescope.yml index ed25725..c066117 100644 --- a/configs/sr/sr_telescope.yml +++ b/configs/sr/sr_telescope.yml @@ -3,14 +3,14 @@ Global: epoch_num: 100 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/sr/sr_telescope/ + save_model_dir: ./json/sr/sr_telescope/ save_epoch_step: 3 # evaluation is run every 2000 iterations eval_batch_step: [0, 1000] cal_metric_during_train: False pretrained_model: checkpoints: - save_inference_dir: ./output/sr/sr_telescope/infer + save_inference_dir: ./json/sr/sr_telescope/infer use_visualdl: False infer_img: doc/imgs_words_en/word_52.png # for data or label process @@ -18,7 +18,7 @@ Global: max_text_length: 100 infer_mode: False use_space_char: False - save_res_path: ./output/sr/predicts_telescope.txt + save_res_path: ./json/sr/predicts_telescope.txt Optimizer: name: Adam diff --git a/configs/sr/sr_tsrn_transformer_strock.yml b/configs/sr/sr_tsrn_transformer_strock.yml index 627bf24..ec628ca 100644 --- a/configs/sr/sr_tsrn_transformer_strock.yml +++ b/configs/sr/sr_tsrn_transformer_strock.yml @@ -3,7 +3,7 @@ Global: epoch_num: 500 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/sr/sr_tsrn_transformer_strock/ + save_model_dir: ./json/sr/sr_tsrn_transformer_strock/ save_epoch_step: 3 # evaluation is run every 2000 iterations eval_batch_step: [0, 1000] @@ -18,7 +18,7 @@ Global: max_text_length: 100 infer_mode: False use_space_char: False - save_res_path: ./output/sr/predicts_gestalt.txt + save_res_path: ./json/sr/predicts_gestalt.txt Optimizer: name: Adam diff --git a/configs/table/SLANet.yml b/configs/table/SLANet.yml index 4388c5f..937f5d8 100644 --- a/configs/table/SLANet.yml +++ b/configs/table/SLANet.yml @@ -3,14 +3,14 @@ Global: epoch_num: 100 log_smooth_window: 20 print_batch_step: 20 - save_model_dir: ./output/SLANet + save_model_dir: ./json/SLANet save_epoch_step: 400 # evaluation is run every 1000 iterations after the 0th iteration eval_batch_step: [0, 1000] cal_metric_during_train: True pretrained_model: checkpoints: - save_inference_dir: ./output/SLANet/infer + save_inference_dir: ./json/SLANet/infer use_visualdl: False infer_img: ppstructure/docs/table/table.jpg # for data or label process @@ -20,7 +20,7 @@ Global: box_format: &box_format 'xyxy' # 'xywh', 'xyxy', 'xyxyxyxy' infer_mode: False use_sync_bn: True - save_res_path: 'output/infer' + save_res_path: 'json/infer' d2s_train_image_shape: [3, -1, -1] amp_custom_white_list: ['concat', 'elementwise_sub', 'set_value'] diff --git a/configs/table/SLANet_ch.yml b/configs/table/SLANet_ch.yml index c16f7ef..f62b5bc 100644 --- a/configs/table/SLANet_ch.yml +++ b/configs/table/SLANet_ch.yml @@ -3,14 +3,14 @@ Global: epoch_num: 400 log_smooth_window: 20 print_batch_step: 20 - save_model_dir: ./output/SLANet_ch + save_model_dir: ./json/SLANet_ch save_epoch_step: 400 # evaluation is run every 331 iterations after the 0th iteration eval_batch_step: [0, 331] cal_metric_during_train: True pretrained_model: checkpoints: - save_inference_dir: ./output/SLANet_ch/infer + save_inference_dir: ./json/SLANet_ch/infer use_visualdl: False infer_img: ppstructure/docs/table/table.jpg # for data or label process @@ -20,7 +20,7 @@ Global: box_format: &box_format xyxyxyxy # 'xywh', 'xyxy', 'xyxyxyxy' infer_mode: False use_sync_bn: True - save_res_path: output/infer + save_res_path: json/infer Optimizer: name: Adam diff --git a/configs/table/SLANet_lcnetv2.yml b/configs/table/SLANet_lcnetv2.yml index df11acf..bc1ccc0 100644 --- a/configs/table/SLANet_lcnetv2.yml +++ b/configs/table/SLANet_lcnetv2.yml @@ -3,7 +3,7 @@ Global: epoch_num: 50 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/SLANet_lcnetv2 + save_model_dir: ./json/SLANet_lcnetv2 save_epoch_step: 20 # evaluation is run every 1000 iterations after the 0th iteration eval_batch_step: [0, 1000] @@ -20,7 +20,7 @@ Global: box_format: &box_format 'xyxy' # 'xywh', 'xyxy', 'xyxyxyxy' infer_mode: False use_sync_bn: True - save_res_path: 'output/infer' + save_res_path: 'json/infer' d2s_train_image_shape: [3, -1, -1] amp_custom_white_list: ['concat', 'elementwise_sub', 'set_value'] diff --git a/configs/table/table_master.yml b/configs/table/table_master.yml index 37cf44d..87b86b7 100644 --- a/configs/table/table_master.yml +++ b/configs/table/table_master.yml @@ -3,16 +3,16 @@ Global: epoch_num: 17 log_smooth_window: 20 print_batch_step: 100 - save_model_dir: ./output/table_master/ + save_model_dir: ./json/table_master/ save_epoch_step: 17 eval_batch_step: [0, 6259] cal_metric_during_train: true pretrained_model: null checkpoints: - save_inference_dir: output/table_master/infer + save_inference_dir: json/table_master/infer use_visualdl: false infer_img: ppstructure/docs/table/table.jpg - save_res_path: ./output/table_master + save_res_path: ./json/table_master character_dict_path: ppocr/utils/dict/table_master_structure_dict.txt infer_mode: false max_text_length: &max_text_length 500 diff --git a/configs/table/table_mv3.yml b/configs/table/table_mv3.yml index 50c8439..4bce90e 100644 --- a/configs/table/table_mv3.yml +++ b/configs/table/table_mv3.yml @@ -3,7 +3,7 @@ Global: epoch_num: 400 log_smooth_window: 20 print_batch_step: 5 - save_model_dir: ./output/table_mv3/ + save_model_dir: ./json/table_mv3/ save_epoch_step: 400 # evaluation is run every 400 iterations after the 0th iteration eval_batch_step: [0, 400] @@ -13,7 +13,7 @@ Global: save_inference_dir: use_visualdl: False infer_img: ppstructure/docs/table/table.jpg - save_res_path: output/table_mv3 + save_res_path: json/table_mv3 # for data or label process character_dict_path: ppocr/utils/dict/table_structure_dict.txt character_type: en diff --git a/deploy/avh/convert_image.py b/deploy/avh/convert_image.py index 7a78fac..94ba7f5 100644 --- a/deploy/avh/convert_image.py +++ b/deploy/avh/convert_image.py @@ -74,7 +74,7 @@ def create_header_file(name, tensor_name, tensor_data, output_path): def create_headers(image_name): """ - This function generates C header files for the input and output arrays required to run inferences + This function generates C header files for the input and json arrays required to run inferences """ img_path = os.path.join("./", f"{image_name}") @@ -88,11 +88,11 @@ def create_headers(image_name): # Create input header file create_header_file("inputs", "input", img_data, "./include") - # Create output header file + # Create json header file output_data = np.zeros([7760], np.float32) create_header_file( "outputs", - "output", + "json", output_data, "./include", ) diff --git a/deploy/cpp_infer/readme.md b/deploy/cpp_infer/readme.md index 3027eba..d5d721a 100644 --- a/deploy/cpp_infer/readme.md +++ b/deploy/cpp_infer/readme.md @@ -400,7 +400,7 @@ predict Crop_img: ../../doc/imgs/12.jpg 1 det boxes: [[23,507],[513,488],[515,529],[24,548]] rec text: 绿洲仕格维花园公寓 rec score: 0.993728 2 det boxes: [[187,456],[399,448],[400,480],[188,488]] rec text: 打浦路15号 rec score: 0.964994 3 det boxes: [[42,413],[483,391],[484,428],[43,450]] rec text: 上海斯格威铂尔大酒店 rec score: 0.980086 -The detection visualized image saved in ./output//12.jpg +The detection visualized image saved in ./json//12.jpg ``` - layout+table @@ -439,9 +439,9 @@ predict Crop_img: ../../ppstructure/docs/table/1.png 0 det boxes: [[6,2],[113,2],[113,14],[6,14]] rec text: 5.Conclusion rec score: 0.856903 ********** end print ocr result ********** 6 type: table, region: [14,360,402,711], score: 0.963643, res:
MethodsExtRPFFPS
TextSnake [18]Syn85.367.975.6
CSE [17]MiLT76.178.777.40.38
LOMO[40]Syn76.585.780.84.4
ATRR[35]Sy-80.280.180.1-
SegLink++ [28]Syn79.882.881.3-
TextField [37]Syn79.883.081.46.0
MSR[38]Syn79.084.181.54.3
PSENet-1s [33]MLT79.784.882.23.9
DB [12]Syn80.286.983.422.0
CRAFT [2]Syn81.186.083.5-
TextDragon [5]MLT+82.884.583.6
PAN [34]Syn81.286.483.739.8
ContourNet [36]84.183.783.94.5
DRRG [41]MLT83.0285.9384.45-
TextPerception[23]Syn81.987.584.6
Ours Syn80.5787.6683.9712.08
Ours81.4587.8184.5112.15
OursMLT83.6086.4585.0012.21
-The table visualized image saved in ./output//6_1.png +The table visualized image saved in ./json//6_1.png 7 type: table, region: [462,359,820,657], score: 0.953917, res:
MethodsRPFFPS
SegLink [26]70.086.077.08.9
PixelLink [4]73.283.077.8-
TextSnake [18]73.983.278.31.1
TextField [37]75.987.481.35.2
MSR[38]76.787.481.7-
FTSN[3]77.187.682.0:
LSE[30]81.784.282.9
CRAFT [2]78.288.282.98.6
MCN [16]798883-
ATRR[35]82.185.283.6-
PAN [34]83.884.484.130.2
DB[12]79.291.584.932.0
DRRG [41]82.3088.0585.08-
Ours (SynText)80.6885.4082.9712.68
Ours (MLT-17)84.5486.6285.5712.31
-The table visualized image saved in ./output//7_1.png +The table visualized image saved in ./json//7_1.png 8 type: figure, region: [14,3,836,310], score: 0.969443, res: count of ocr result is : 26 ********** print ocr result ********** 0 det boxes: [[506,14],[539,15],[539,22],[506,21]] rec text: E rec score: 0.318073 diff --git a/deploy/cpp_infer/readme_ch.md b/deploy/cpp_infer/readme_ch.md index 3a6fed2..9203772 100644 --- a/deploy/cpp_infer/readme_ch.md +++ b/deploy/cpp_infer/readme_ch.md @@ -411,7 +411,7 @@ predict Crop_img: ../../doc/imgs/12.jpg 1 det boxes: [[23,507],[513,488],[515,529],[24,548]] rec text: 绿洲仕格维花园公寓 rec score: 0.993728 2 det boxes: [[187,456],[399,448],[400,480],[188,488]] rec text: 打浦路15号 rec score: 0.964994 3 det boxes: [[42,413],[483,391],[484,428],[43,450]] rec text: 上海斯格威铂尔大酒店 rec score: 0.980086 -The detection visualized image saved in ./output//12.jpg +The detection visualized image saved in ./json//12.jpg ``` - layout+table @@ -450,9 +450,9 @@ predict Crop_img: ../../ppstructure/docs/table/1.png 0 det boxes: [[6,2],[113,2],[113,14],[6,14]] rec text: 5.Conclusion rec score: 0.856903 ********** end print ocr result ********** 6 type: table, region: [14,360,402,711], score: 0.963643, res:
MethodsExtRPFFPS
TextSnake [18]Syn85.367.975.6
CSE [17]MiLT76.178.777.40.38
LOMO[40]Syn76.585.780.84.4
ATRR[35]Sy-80.280.180.1-
SegLink++ [28]Syn79.882.881.3-
TextField [37]Syn79.883.081.46.0
MSR[38]Syn79.084.181.54.3
PSENet-1s [33]MLT79.784.882.23.9
DB [12]Syn80.286.983.422.0
CRAFT [2]Syn81.186.083.5-
TextDragon [5]MLT+82.884.583.6
PAN [34]Syn81.286.483.739.8
ContourNet [36]84.183.783.94.5
DRRG [41]MLT83.0285.9384.45-
TextPerception[23]Syn81.987.584.6
Ours Syn80.5787.6683.9712.08
Ours81.4587.8184.5112.15
OursMLT83.6086.4585.0012.21
-The table visualized image saved in ./output//6_1.png +The table visualized image saved in ./json//6_1.png 7 type: table, region: [462,359,820,657], score: 0.953917, res:
MethodsRPFFPS
SegLink [26]70.086.077.08.9
PixelLink [4]73.283.077.8-
TextSnake [18]73.983.278.31.1
TextField [37]75.987.481.35.2
MSR[38]76.787.481.7-
FTSN[3]77.187.682.0:
LSE[30]81.784.282.9
CRAFT [2]78.288.282.98.6
MCN [16]798883-
ATRR[35]82.185.283.6-
PAN [34]83.884.484.130.2
DB[12]79.291.584.932.0
DRRG [41]82.3088.0585.08-
Ours (SynText)80.6885.4082.9712.68
Ours (MLT-17)84.5486.6285.5712.31
-The table visualized image saved in ./output//7_1.png +The table visualized image saved in ./json//7_1.png 8 type: figure, region: [14,3,836,310], score: 0.969443, res: count of ocr result is : 26 ********** print ocr result ********** 0 det boxes: [[506,14],[539,15],[539,22],[506,21]] rec text: E rec score: 0.318073 diff --git a/deploy/fastdeploy/ascend/python/infer.py b/deploy/fastdeploy/ascend/python/infer.py index cdaa167..9b01d32 100644 --- a/deploy/fastdeploy/ascend/python/infer.py +++ b/deploy/fastdeploy/ascend/python/infer.py @@ -100,7 +100,7 @@ result = ppocr_v3.predict(im) print(result) -# Visuliaze the output. +# Visuliaze the json. vis_im = fd.vision.vis_ppocr(im, result) cv2.imwrite("visualized_result.jpg", vis_im) print("Visualized result save in ./visualized_result.jpg") diff --git a/deploy/fastdeploy/kunlunxin/python/infer.py b/deploy/fastdeploy/kunlunxin/python/infer.py index bf95174..8f1553d 100644 --- a/deploy/fastdeploy/kunlunxin/python/infer.py +++ b/deploy/fastdeploy/kunlunxin/python/infer.py @@ -107,7 +107,7 @@ result = ppocr_v3.predict(im) print(result) -# Visuliaze the output. +# Visuliaze the json. vis_im = fd.vision.vis_ppocr(im, result) cv2.imwrite("visualized_result.jpg", vis_im) print("Visualized result save in ./visualized_result.jpg") diff --git a/deploy/fastdeploy/serving/fastdeploy_serving/models/cls_postprocess/1/model.py b/deploy/fastdeploy/serving/fastdeploy_serving/models/cls_postprocess/1/model.py index fbafcae..57d705b 100644 --- a/deploy/fastdeploy/serving/fastdeploy_serving/models/cls_postprocess/1/model.py +++ b/deploy/fastdeploy/serving/fastdeploy_serving/models/cls_postprocess/1/model.py @@ -21,7 +21,7 @@ import fastdeploy as fd # triton_python_backend_utils is available in every Triton Python model. You # need to use this module to create inference requests and responses. It also # contains some utility functions for extracting information from model_config -# and converting Triton input/output types to numpy types. +# and converting Triton input/json types to numpy types. import triton_python_backend_utils as pb_utils @@ -56,11 +56,11 @@ class TritonPythonModel: self.output_names = [] self.output_dtype = [] - for output_config in self.model_config["output"]: + for output_config in self.model_config["json"]: self.output_names.append(output_config["name"]) dtype = pb_utils.triton_string_to_numpy(output_config["data_type"]) self.output_dtype.append(dtype) - print("postprocess output names:", self.output_names) + print("postprocess json names:", self.output_names) self.postprocessor = fd.vision.ocr.ClassifierPostprocessor() def execute(self, requests): diff --git a/deploy/fastdeploy/serving/fastdeploy_serving/models/det_postprocess/1/model.py b/deploy/fastdeploy/serving/fastdeploy_serving/models/det_postprocess/1/model.py index 81c4193..42dec56 100644 --- a/deploy/fastdeploy/serving/fastdeploy_serving/models/det_postprocess/1/model.py +++ b/deploy/fastdeploy/serving/fastdeploy_serving/models/det_postprocess/1/model.py @@ -22,7 +22,7 @@ import fastdeploy as fd # triton_python_backend_utils is available in every Triton Python model. You # need to use this module to create inference requests and responses. It also # contains some utility functions for extracting information from model_config -# and converting Triton input/output types to numpy types. +# and converting Triton input/json types to numpy types. import triton_python_backend_utils as pb_utils @@ -106,11 +106,11 @@ class TritonPythonModel: self.output_names = [] self.output_dtype = [] - for output_config in self.model_config["output"]: + for output_config in self.model_config["json"]: self.output_names.append(output_config["name"]) dtype = pb_utils.triton_string_to_numpy(output_config["data_type"]) self.output_dtype.append(dtype) - print("postprocess output names:", self.output_names) + print("postprocess json names:", self.output_names) self.postprocessor = fd.vision.ocr.DBDetectorPostprocessor() self.cls_preprocessor = fd.vision.ocr.ClassifierPreprocessor() self.rec_preprocessor = fd.vision.ocr.RecognizerPreprocessor() @@ -183,7 +183,7 @@ class TritonPythonModel: inference_response.error().message() ) else: - # Extract the output tensors from the inference response. + # Extract the json tensors from the inference response. cls_labels = pb_utils.get_output_tensor_by_name( inference_response, "cls_labels" ) @@ -219,7 +219,7 @@ class TritonPythonModel: inference_response.error().message() ) else: - # Extract the output tensors from the inference response. + # Extract the json tensors from the inference response. rec_texts = pb_utils.get_output_tensor_by_name( inference_response, "rec_texts" ) diff --git a/deploy/fastdeploy/serving/fastdeploy_serving/models/det_preprocess/1/model.py b/deploy/fastdeploy/serving/fastdeploy_serving/models/det_preprocess/1/model.py index 070cb45..841ed52 100644 --- a/deploy/fastdeploy/serving/fastdeploy_serving/models/det_preprocess/1/model.py +++ b/deploy/fastdeploy/serving/fastdeploy_serving/models/det_preprocess/1/model.py @@ -21,7 +21,7 @@ import fastdeploy as fd # triton_python_backend_utils is available in every Triton Python model. You # need to use this module to create inference requests and responses. It also # contains some utility functions for extracting information from model_config -# and converting Triton input/output types to numpy types. +# and converting Triton input/json types to numpy types. import triton_python_backend_utils as pb_utils @@ -56,11 +56,11 @@ class TritonPythonModel: self.output_names = [] self.output_dtype = [] - for output_config in self.model_config["output"]: + for output_config in self.model_config["json"]: self.output_names.append(output_config["name"]) dtype = pb_utils.triton_string_to_numpy(output_config["data_type"]) self.output_dtype.append(dtype) - print("preprocess output names:", self.output_names) + print("preprocess json names:", self.output_names) self.preprocessor = fd.vision.ocr.DBDetectorPreprocessor() def execute(self, requests): diff --git a/deploy/fastdeploy/serving/fastdeploy_serving/models/rec_postprocess/1/model.py b/deploy/fastdeploy/serving/fastdeploy_serving/models/rec_postprocess/1/model.py index dc4c655..693cee4 100644 --- a/deploy/fastdeploy/serving/fastdeploy_serving/models/rec_postprocess/1/model.py +++ b/deploy/fastdeploy/serving/fastdeploy_serving/models/rec_postprocess/1/model.py @@ -23,7 +23,7 @@ import fastdeploy as fd # triton_python_backend_utils is available in every Triton Python model. You # need to use this module to create inference requests and responses. It also # contains some utility functions for extracting information from model_config -# and converting Triton input/output types to numpy types. +# and converting Triton input/json types to numpy types. import triton_python_backend_utils as pb_utils @@ -58,11 +58,11 @@ class TritonPythonModel: self.output_names = [] self.output_dtype = [] - for output_config in self.model_config["output"]: + for output_config in self.model_config["json"]: self.output_names.append(output_config["name"]) dtype = pb_utils.triton_string_to_numpy(output_config["data_type"]) self.output_dtype.append(dtype) - print("postprocess output names:", self.output_names) + print("postprocess json names:", self.output_names) dir_name = os.path.dirname(os.path.realpath(__file__)) + "/" file_name = dir_name + "ppocr_keys_v1.txt" diff --git a/deploy/hubserving/structure_system/params.py b/deploy/hubserving/structure_system/params.py index c5d28de..9f368cf 100644 --- a/deploy/hubserving/structure_system/params.py +++ b/deploy/hubserving/structure_system/params.py @@ -29,5 +29,5 @@ def read_params(): cfg.layout_nms_threshold = 0.5 cfg.mode = "structure" - cfg.output = "./output" + cfg.output = "./json" return cfg diff --git a/deploy/paddlecloud/README.md b/deploy/paddlecloud/README.md index 7ff58ce..c817628 100644 --- a/deploy/paddlecloud/README.md +++ b/deploy/paddlecloud/README.md @@ -148,14 +148,14 @@ $ tar xf /home/PaddleOCR/pre_train/ch_PP-OCRv3_det_distill_train.tar -C /home/Pa ```bash # 这里以 GPU 训练为例,使用 CPU 进行训练的话,需要指定参数 Global.use_gpu=false -python3 tools/train.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml -o Global.save_model_dir=./output/ Global.pretrained_model=./pre_train/ch_PP-OCRv3_det_distill_train/best_accuracy +python3 tools/train.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml -o Global.save_model_dir=./json/ Global.pretrained_model=./pre_train/ch_PP-OCRv3_det_distill_train/best_accuracy ``` 如果要使用多GPU分布式训练,请使用如下命令: ```bash # 启动训练,训练模型默认保存在output目录下,--gpus '0,1,2,3'表示使用0,1,2,3号GPU训练 -python3 -m paddle.distributed.launch --log_dir=./debug/ --gpus '0,1,2,3' tools/train.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml -o Global.save_model_dir=./output/ Global.pretrained_model=./pre_train/ch_PP-OCRv3_det_distill_train/best_accuracy +python3 -m paddle.distributed.launch --log_dir=./debug/ --gpus '0,1,2,3' tools/train.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml -o Global.save_model_dir=./json/ Global.pretrained_model=./pre_train/ch_PP-OCRv3_det_distill_train/best_accuracy ``` ### 1.6 模型评估 @@ -177,7 +177,7 @@ latest.pdopt # 默认保存的最新模型的优化器相关参数 # 进行模型评估 cd /home/PaddleOCR/ -python3 tools/eval.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml -o Global.checkpoints=./output/best_accuracy +python3 tools/eval.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml -o Global.checkpoints=./json/best_accuracy ``` ## 2. PP-OCRv3云端部署 diff --git a/deploy/pdserving/ocr_reader.py b/deploy/pdserving/ocr_reader.py index 9efbe8a..6da8cf9 100644 --- a/deploy/pdserving/ocr_reader.py +++ b/deploy/pdserving/ocr_reader.py @@ -313,7 +313,7 @@ class CharacterOps(object): input: text: text labels of each image. [batch_size] - output: + json: text: concatenated text index for CTCLoss. [sum(text_lengths)] = [text_index_0 + text_index_1 + ... + text_index_(n - 1)] length: length of each text. [batch_size] diff --git a/deploy/pdserving/win/ocr_reader.py b/deploy/pdserving/win/ocr_reader.py index f4d8808..a561157 100644 --- a/deploy/pdserving/win/ocr_reader.py +++ b/deploy/pdserving/win/ocr_reader.py @@ -313,7 +313,7 @@ class CharacterOps(object): input: text: text labels of each image. [batch_size] - output: + json: text: concatenated text index for CTCLoss. [sum(text_lengths)] = [text_index_0 + text_index_1 + ... + text_index_(n - 1)] length: length of each text. [batch_size] diff --git a/deploy/slim/auto_compression/run.py b/deploy/slim/auto_compression/run.py index 32bdede..8149313 100644 --- a/deploy/slim/auto_compression/run.py +++ b/deploy/slim/auto_compression/run.py @@ -44,7 +44,7 @@ def argsparser(): parser.add_argument( "--save_dir", type=str, - default="output", + default="json", help="directory to save compressed model.", ) parser.add_argument( diff --git a/deploy/slim/prune/README.md b/deploy/slim/prune/README.md index 6d04f16..b3428bd 100644 --- a/deploy/slim/prune/README.md +++ b/deploy/slim/prune/README.md @@ -52,14 +52,14 @@ sen.pickle(Dict){ 进入PaddleOCR根目录,通过以下命令对模型进行敏感度分析训练: ```bash -python3.7 deploy/slim/prune/sensitivity_anal.py -c configs/det/ch_ppocr_v2.0/ch_det_mv3_db_v2.0.yml -o Global.pretrained_model="your trained model" Global.save_model_dir=./output/prune_model/ +python3.7 deploy/slim/prune/sensitivity_anal.py -c configs/det/ch_ppocr_v2.0/ch_det_mv3_db_v2.0.yml -o Global.pretrained_model="your trained model" Global.save_model_dir=./json/prune_model/ ``` ### 4. 导出模型、预测部署 在得到裁剪训练保存的模型后,我们可以将其导出为inference_model: ```bash -pytho3.7 deploy/slim/prune/export_prune_model.py -c configs/det/ch_ppocr_v2.0/ch_det_mv3_db_v2.0.yml -o Global.pretrained_model=./output/det_db/best_accuracy Global.save_inference_dir=./prune/prune_inference_model +pytho3.7 deploy/slim/prune/export_prune_model.py -c configs/det/ch_ppocr_v2.0/ch_det_mv3_db_v2.0.yml -o Global.pretrained_model=./json/det_db/best_accuracy Global.save_inference_dir=./prune/prune_inference_model ``` inference model的预测和部署参考: diff --git a/deploy/slim/prune/README_en.md b/deploy/slim/prune/README_en.md index 7fa1e5b..3f316e8 100644 --- a/deploy/slim/prune/README_en.md +++ b/deploy/slim/prune/README_en.md @@ -57,7 +57,7 @@ example: Enter the PaddleOCR root directory,perform sensitivity analysis on the model with the following command: ```bash -python3.7 deploy/slim/prune/sensitivity_anal.py -c configs/det/ch_ppocr_v2.0/ch_det_mv3_db_v2.0.yml -o Global.pretrained_model="your trained model" Global.save_model_dir=./output/prune_model/ +python3.7 deploy/slim/prune/sensitivity_anal.py -c configs/det/ch_ppocr_v2.0/ch_det_mv3_db_v2.0.yml -o Global.pretrained_model="your trained model" Global.save_model_dir=./json/prune_model/ ``` @@ -65,7 +65,7 @@ python3.7 deploy/slim/prune/sensitivity_anal.py -c configs/det/ch_ppocr_v2.0/ch_ We can export the pruned model as inference_model for deployment: ```bash -python deploy/slim/prune/export_prune_model.py -c configs/det/ch_ppocr_v2.0/ch_det_mv3_db_v2.0.yml -o Global.pretrained_model=./output/det_db/best_accuracy Global.save_inference_dir=./prune/prune_inference_model +python deploy/slim/prune/export_prune_model.py -c configs/det/ch_ppocr_v2.0/ch_det_mv3_db_v2.0.yml -o Global.pretrained_model=./json/det_db/best_accuracy Global.save_inference_dir=./prune/prune_inference_model ``` Reference for prediction and deployment of inference model: diff --git a/deploy/slim/quantization/README.md b/deploy/slim/quantization/README.md index d401d3b..eabf0e6 100644 --- a/deploy/slim/quantization/README.md +++ b/deploy/slim/quantization/README.md @@ -48,7 +48,7 @@ python deploy/slim/quantization/quant.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_ 在得到量化训练保存的模型后,我们可以将其导出为inference_model,用于预测部署: ```bash -python deploy/slim/quantization/export_model.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml -o Global.checkpoints=output/quant_model/best_accuracy Global.save_inference_dir=./output/quant_inference_model +python deploy/slim/quantization/export_model.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml -o Global.checkpoints=json/quant_model/best_accuracy Global.save_inference_dir=./json/quant_inference_model ``` ### 5. 量化模型部署 diff --git a/deploy/slim/quantization/README_en.md b/deploy/slim/quantization/README_en.md index f82c3d8..5a97adf 100644 --- a/deploy/slim/quantization/README_en.md +++ b/deploy/slim/quantization/README_en.md @@ -55,7 +55,7 @@ If you want to quantify the text recognition model, you can modify the configura Once we got the model after pruning and fine-tuning, we can export it as an inference model for the deployment of predictive tasks: ```bash -python deploy/slim/quantization/export_model.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml -o Global.checkpoints=output/quant_model/best_accuracy Global.save_inference_dir=./output/quant_inference_model +python deploy/slim/quantization/export_model.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml -o Global.checkpoints=json/quant_model/best_accuracy Global.save_inference_dir=./json/quant_inference_model ``` ### 5. Deploy diff --git a/doc/doc_ch/algorithm_kie_sdmgr.md b/doc/doc_ch/algorithm_kie_sdmgr.md index 86b44f6..d465895 100644 --- a/doc/doc_ch/algorithm_kie_sdmgr.md +++ b/doc/doc_ch/algorithm_kie_sdmgr.md @@ -75,7 +75,7 @@ python3 tools/train.py -c configs/kie/sdmgr/kie_unet_sdmgr.yml -o Global.save_mo 执行下面的命令进行模型评估 ```bash -python3 tools/eval.py -c configs/kie/sdmgr/kie_unet_sdmgr.yml -o Global.checkpoints=./output/kie/best_accuracy +python3 tools/eval.py -c configs/kie/sdmgr/kie_unet_sdmgr.yml -o Global.checkpoints=./json/kie/best_accuracy ``` 输出信息示例如下所示。 diff --git a/doc/doc_ch/algorithm_rec_rfl.md b/doc/doc_ch/algorithm_rec_rfl.md index 547fab3..e7ca851 100644 --- a/doc/doc_ch/algorithm_rec_rfl.md +++ b/doc/doc_ch/algorithm_rec_rfl.md @@ -57,10 +57,10 @@ python3 -m paddle.distributed.launch --gpus '0,1,2,3' tools/train.py -c configs #step2:联合训练CNT和Att分支,注意将pretrained_model的路径设置为本地路径。 #单卡训练(训练周期长,不建议) -python3 tools/train.py -c configs/rec/rec_resnet_rfl_att.yml -o Global.pretrained_model=./output/rec/rec_resnet_rfl_visual/best_accuracy +python3 tools/train.py -c configs/rec/rec_resnet_rfl_att.yml -o Global.pretrained_model=./json/rec/rec_resnet_rfl_visual/best_accuracy #多卡训练,通过--gpus参数指定卡号 -python3 -m paddle.distributed.launch --gpus '0,1,2,3' tools/train.py -c configs/rec/rec_resnet_rfl_att.yml -o Global.pretrained_model=./output/rec/rec_resnet_rfl_visual/best_accuracy +python3 -m paddle.distributed.launch --gpus '0,1,2,3' tools/train.py -c configs/rec/rec_resnet_rfl_att.yml -o Global.pretrained_model=./json/rec/rec_resnet_rfl_visual/best_accuracy ``` @@ -70,7 +70,7 @@ python3 -m paddle.distributed.launch --gpus '0,1,2,3' tools/train.py -c configs ```shell # 注意将pretrained_model的路径设置为本地路径。 -python3 -m paddle.distributed.launch --gpus '0' tools/eval.py -c configs/rec/rec_resnet_rfl_att.yml -o Global.pretrained_model=./output/rec/rec_resnet_rfl_att/best_accuracy +python3 -m paddle.distributed.launch --gpus '0' tools/eval.py -c configs/rec/rec_resnet_rfl_att.yml -o Global.pretrained_model=./json/rec/rec_resnet_rfl_att/best_accuracy ``` @@ -79,7 +79,7 @@ python3 -m paddle.distributed.launch --gpus '0' tools/eval.py -c configs/rec/rec 使用如下命令进行单张图片预测: ```shell # 注意将pretrained_model的路径设置为本地路径。 -python3 tools/infer_rec.py -c configs/rec/rec_resnet_rfl_att.yml -o Global.infer_img='./doc/imgs_words_en/word_10.png' Global.pretrained_model=./output/rec/rec_resnet_rfl_att/best_accuracy +python3 tools/infer_rec.py -c configs/rec/rec_resnet_rfl_att.yml -o Global.infer_img='./doc/imgs_words_en/word_10.png' Global.pretrained_model=./json/rec/rec_resnet_rfl_att/best_accuracy # 预测文件夹下所有图像时,可修改infer_img为文件夹,如 Global.infer_img='./doc/imgs_words_en/'。 ``` @@ -93,7 +93,7 @@ python3 tools/infer_rec.py -c configs/rec/rec_resnet_rfl_att.yml -o Global.infer ```shell # 注意将pretrained_model的路径设置为本地路径。 -python3 tools/export_model.py -c configs/rec/rec_resnet_rfl_att.yml -o Global.pretrained_model=./output/rec/rec_resnet_rfl_att/best_accuracy Global.save_inference_dir=./inference/rec_resnet_rfl_att/ +python3 tools/export_model.py -c configs/rec/rec_resnet_rfl_att.yml -o Global.pretrained_model=./json/rec/rec_resnet_rfl_att/best_accuracy Global.save_inference_dir=./inference/rec_resnet_rfl_att/ ``` **注意:** - 如果您是在自己的数据集上训练的模型,并且调整了字典文件,请注意修改配置文件中的`character_dict_path`是否是所需要的字典文件。 diff --git a/doc/doc_ch/algorithm_table_master.md b/doc/doc_ch/algorithm_table_master.md index 36455ed..13ef054 100644 --- a/doc/doc_ch/algorithm_table_master.md +++ b/doc/doc_ch/algorithm_table_master.md @@ -47,7 +47,7 @@ ```shell # 注意将pretrained_model的路径设置为本地路径。 -python3 tools/export_model.py -c configs/table/table_master.yml -o Global.pretrained_model=output/table_master/best_accuracy Global.save_inference_dir=./inference/table_master +python3 tools/export_model.py -c configs/table/table_master.yml -o Global.pretrained_model=json/table_master/best_accuracy Global.save_inference_dir=./inference/table_master ``` **注意:** @@ -66,7 +66,7 @@ python3 tools/export_model.py -c configs/table/table_master.yml -o Global.pretra ```shell cd ppstructure/ -python3.7 table/predict_structure.py --table_model_dir=../output/table_master/table_structure_tablemaster_infer/ --table_algorithm=TableMaster --table_char_dict_path=../ppocr/utils/dict/table_master_structure_dict.txt --table_max_len=480 --image_dir=docs/table/table.jpg +python3.7 table/predict_structure.py --table_model_dir=../json/table_master/table_structure_tablemaster_infer/ --table_algorithm=TableMaster --table_char_dict_path=../ppocr/utils/dict/table_master_structure_dict.txt --table_max_len=480 --image_dir=docs/table/table.jpg # 预测文件夹下所有图像时,可修改image_dir为文件夹,如 --image_dir='docs/table'。 ``` @@ -76,7 +76,7 @@ python3.7 table/predict_structure.py --table_model_dir=../output/table_master/ta [2022/06/16 13:06:54] ppocr INFO: result: ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '
', '', ''], [[72.17591094970703, 10.759100914001465, 60.29658508300781, 16.6805362701416], [161.85562133789062, 10.884308815002441, 14.9495210647583, 16.727018356323242], [277.79876708984375, 29.54340362548828, 31.490320205688477, 18.143272399902344], ... [336.11724853515625, 280.3601989746094, 39.456939697265625, 18.121286392211914]] -[2022/06/16 13:06:54] ppocr INFO: save vis result to ./output/table.jpg +[2022/06/16 13:06:54] ppocr INFO: save vis result to ./json/table.jpg [2022/06/16 13:06:54] ppocr INFO: Predict time of docs/table/table.jpg: 17.36806297302246 ``` diff --git a/doc/doc_ch/detection.md b/doc/doc_ch/detection.md index 8271f10..87cd711 100644 --- a/doc/doc_ch/detection.md +++ b/doc/doc_ch/detection.md @@ -233,7 +233,7 @@ inference 模型(`paddle.jit.save`保存的模型) 检测模型转inference 模型方式: ```shell -# 加载配置文件`det_mv3_db.yml`,从`output/det_db`目录下加载`best_accuracy`模型,inference模型保存在`./output/det_db_inference`目录下 +# 加载配置文件`det_mv3_db.yml`,从`json/det_db`目录下加载`best_accuracy`模型,inference模型保存在`./json/det_db_inference`目录下 python3 tools/export_model.py -c configs/det/det_mv3_db.yml -o Global.pretrained_model="./output/det_db/best_accuracy" Global.save_inference_dir="./output/det_db_inference/" ``` diff --git a/doc/doc_ch/kie.md b/doc/doc_ch/kie.md index 0ebb05d..03dfcba 100644 --- a/doc/doc_ch/kie.md +++ b/doc/doc_ch/kie.md @@ -248,7 +248,7 @@ Eval: 如果训练程序中断,如果希望加载训练中断的模型从而恢复训练,可以通过指定` Architecture.Backbone.checkpoints`指定要加载的模型路径: ```bash -python3 tools/train.py -c configs/kie/vi_layoutxlm/ser_vi_layoutxlm_xfund_zh.yml -o Architecture.Backbone.checkpoints=./output/ser_vi_layoutxlm_xfund_zh/best_accuracy +python3 tools/train.py -c configs/kie/vi_layoutxlm/ser_vi_layoutxlm_xfund_zh.yml -o Architecture.Backbone.checkpoints=./json/ser_vi_layoutxlm_xfund_zh/best_accuracy ``` **注意**: @@ -300,7 +300,7 @@ DCU设备上运行需要设置环境变量 `export HIP_VISIBLE_DEVICES=0,1,2,3` ```bash # GPU 评估, Global.checkpoints 为待测权重 -python3 tools/eval.py -c configs/kie/vi_layoutxlm/ser_vi_layoutxlm_xfund_zh.yml -o Architecture.Backbone.checkpoints=./output/ser_vi_layoutxlm_xfund_zh/best_accuracy +python3 tools/eval.py -c configs/kie/vi_layoutxlm/ser_vi_layoutxlm_xfund_zh.yml -o Architecture.Backbone.checkpoints=./json/ser_vi_layoutxlm_xfund_zh/best_accuracy ``` 会输出以下信息,打印出precision、recall、hmean等信息。 @@ -347,7 +347,7 @@ output/ser_vi_layoutxlm_xfund_zh/ ```bash -python3 tools/infer_kie_token_ser.py -c configs/kie/vi_layoutxlm/ser_vi_layoutxlm_xfund_zh.yml -o Architecture.Backbone.checkpoints=./output/ser_vi_layoutxlm_xfund_zh/best_accuracy Global.infer_img=./ppstructure/docs/kie/input/zh_val_42.jpg +python3 tools/infer_kie_token_ser.py -c configs/kie/vi_layoutxlm/ser_vi_layoutxlm_xfund_zh.yml -o Architecture.Backbone.checkpoints=./json/ser_vi_layoutxlm_xfund_zh/best_accuracy Global.infer_img=./ppstructure/docs/kie/input/zh_val_42.jpg ``` 预测图片如下所示,图片会存储在`Global.save_res_path`路径中。 @@ -359,7 +359,7 @@ python3 tools/infer_kie_token_ser.py -c configs/kie/vi_layoutxlm/ser_vi_layoutxl 预测过程中,默认会加载PP-OCRv3的检测识别模型,用于OCR的信息抽取,如果希望加载预先获取的OCR结果,可以使用下面的方式进行预测,指定`Global.infer_img`为标注文件,其中包含图片路径以及OCR信息,同时指定`Global.infer_mode`为False,表示此时不使用OCR预测引擎。 ```bash -python3 tools/infer_kie_token_ser.py -c configs/kie/vi_layoutxlm/ser_vi_layoutxlm_xfund_zh.yml -o Architecture.Backbone.checkpoints=./output/ser_vi_layoutxlm_xfund_zh/best_accuracy Global.infer_img=./train_data/XFUND/zh_val/val.json Global.infer_mode=False +python3 tools/infer_kie_token_ser.py -c configs/kie/vi_layoutxlm/ser_vi_layoutxlm_xfund_zh.yml -o Architecture.Backbone.checkpoints=./json/ser_vi_layoutxlm_xfund_zh/best_accuracy Global.infer_img=./train_data/XFUND/zh_val/val.json Global.infer_mode=False ``` 对于上述图片,如果使用标注的OCR结果进行信息抽取,预测结果如下。 @@ -426,7 +426,7 @@ inference 模型(`paddle.jit.save`保存的模型) # Architecture.Backbone.checkpoints 参数设置待转换的训练模型地址 # Global.save_inference_dir 参数设置转换的模型将保存的地址 -python3 tools/export_model.py -c configs/kie/vi_layoutxlm/ser_vi_layoutxlm_xfund_zh.yml -o Architecture.Backbone.checkpoints=./output/ser_vi_layoutxlm_xfund_zh/best_accuracy Global.save_inference_dir=./inference/ser_vi_layoutxlm +python3 tools/export_model.py -c configs/kie/vi_layoutxlm/ser_vi_layoutxlm_xfund_zh.yml -o Architecture.Backbone.checkpoints=./json/ser_vi_layoutxlm_xfund_zh/best_accuracy Global.save_inference_dir=./inference/ser_vi_layoutxlm ``` 转换成功后,在目录下有三个文件: diff --git a/doc/doc_en/algorithm_kie_sdmgr_en.md b/doc/doc_en/algorithm_kie_sdmgr_en.md index ce52ef1..3302d30 100644 --- a/doc/doc_en/algorithm_kie_sdmgr_en.md +++ b/doc/doc_en/algorithm_kie_sdmgr_en.md @@ -62,7 +62,7 @@ The config file is `configs/kie/sdmgr/kie_unet_sdmgr.yml`, the default dataset Use the following command to train the model. ```bash -python3 tools/train.py -c configs/kie/sdmgr/kie_unet_sdmgr.yml -o Global.save_model_dir=./output/kie/ +python3 tools/train.py -c configs/kie/sdmgr/kie_unet_sdmgr.yml -o Global.save_model_dir=./json/kie/ ``` ### 3.2 Model evaluation @@ -70,7 +70,7 @@ python3 tools/train.py -c configs/kie/sdmgr/kie_unet_sdmgr.yml -o Global.save_mo Use the following command to evaluate the model. ```bash -python3 tools/eval.py -c configs/kie/sdmgr/kie_unet_sdmgr.yml -o Global.checkpoints=./output/kie/best_accuracy +python3 tools/eval.py -c configs/kie/sdmgr/kie_unet_sdmgr.yml -o Global.checkpoints=./json/kie/best_accuracy ``` An example of output information is shown below. diff --git a/doc/doc_en/algorithm_sdmgr_en.md b/doc/doc_en/algorithm_sdmgr_en.md index 7b37522..5a3b8f3 100644 --- a/doc/doc_en/algorithm_sdmgr_en.md +++ b/doc/doc_en/algorithm_sdmgr_en.md @@ -45,7 +45,7 @@ ln -s ../../wildreceipt ./ The configuration file used for training is `configs/kie/kie_unet_sdmgr.yml`. The default training data path in the configuration file is `train_data/wildreceipt`. After preparing the data, you can execute the model training with the following command: ```shell -python3.7 tools/train.py -c configs/kie/kie_unet_sdmgr.yml -o Global.save_model_dir=./output/kie/ +python3.7 tools/train.py -c configs/kie/kie_unet_sdmgr.yml -o Global.save_model_dir=./json/kie/ ``` ## 3. Model Evaluation @@ -53,7 +53,7 @@ python3.7 tools/train.py -c configs/kie/kie_unet_sdmgr.yml -o Global.save_model_ After training, you can execute the model evaluation with the following command: ```shell -python3.7 tools/eval.py -c configs/kie/kie_unet_sdmgr.yml -o Global.checkpoints=./output/kie/best_accuracy +python3.7 tools/eval.py -c configs/kie/kie_unet_sdmgr.yml -o Global.checkpoints=./json/kie/best_accuracy ``` ## 4. Reference diff --git a/doc/doc_en/algorithm_table_master_en.md b/doc/doc_en/algorithm_table_master_en.md index e9249a2..bb11f2a 100644 --- a/doc/doc_en/algorithm_table_master_en.md +++ b/doc/doc_en/algorithm_table_master_en.md @@ -50,7 +50,7 @@ First, convert the model saved in the TableMaster table recognition training pro ```shell -python3 tools/export_model.py -c configs/table/table_master.yml -o Global.pretrained_model=output/table_master/best_accuracy Global.save_inference_dir=./inference/table_master +python3 tools/export_model.py -c configs/table/table_master.yml -o Global.pretrained_model=json/table_master/best_accuracy Global.save_inference_dir=./inference/table_master ``` **Note: ** @@ -62,7 +62,7 @@ Execute the following command for model inference: ```shell cd ppstructure/ # When predicting all images in a folder, you can modify image_dir to a folder, such as --image_dir='docs/table'. -python3.7 table/predict_structure.py --table_model_dir=../output/table_master/table_structure_tablemaster_infer/ --table_algorithm=TableMaster --table_char_dict_path=../ppocr/utils/dict/table_master_structure_dict.txt --table_max_len=480 --image_dir=docs/table/table.jpg +python3.7 table/predict_structure.py --table_model_dir=../json/table_master/table_structure_tablemaster_infer/ --table_algorithm=TableMaster --table_char_dict_path=../ppocr/utils/dict/table_master_structure_dict.txt --table_max_len=480 --image_dir=docs/table/table.jpg ``` @@ -73,7 +73,7 @@ result: [2022/06/16 13:06:54] ppocr INFO: result: ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '
', '', ''], [[72.17591094970703, 10.759100914001465, 60.29658508300781, 16.6805362701416], [161.85562133789062, 10.884308815002441, 14.9495210647583, 16.727018356323242], [277.79876708984375, 29.54340362548828, 31.490320205688477, 18.143272399902344], ... [336.11724853515625, 280.3601989746094, 39.456939697265625, 18.121286392211914]] -[2022/06/16 13:06:54] ppocr INFO: save vis result to ./output/table.jpg +[2022/06/16 13:06:54] ppocr INFO: save vis result to ./json/table.jpg [2022/06/16 13:06:54] ppocr INFO: Predict time of docs/table/table.jpg: 17.36806297302246 ``` diff --git a/doc/doc_en/kie_en.md b/doc/doc_en/kie_en.md index b041b39..b53a7e5 100644 --- a/doc/doc_en/kie_en.md +++ b/doc/doc_en/kie_en.md @@ -259,7 +259,7 @@ If the training process is interrupted and you want to load the saved model to r ```bash -python3 tools/train.py -c configs/kie/vi_layoutxlm/ser_vi_layoutxlm_xfund_zh.yml -o Architecture.Backbone.checkpoints=./output/ser_vi_layoutxlm_xfund_zh/best_accuracy +python3 tools/train.py -c configs/kie/vi_layoutxlm/ser_vi_layoutxlm_xfund_zh.yml -o Architecture.Backbone.checkpoints=./json/ser_vi_layoutxlm_xfund_zh/best_accuracy ``` **Note:** @@ -313,7 +313,7 @@ The trained model will be saved in `Global.save_model_dir`. When evaluation, you ```bash # GPU evaluation, Global.checkpoints is the weight to be tested -python3 tools/eval.py -c configs/kie/vi_layoutxlm/ser_vi_layoutxlm_xfund_zh.yml -o Architecture.Backbone.checkpoints=./output/ser_vi_layoutxlm_xfund_zh/best_accuracy +python3 tools/eval.py -c configs/kie/vi_layoutxlm/ser_vi_layoutxlm_xfund_zh.yml -o Architecture.Backbone.checkpoints=./json/ser_vi_layoutxlm_xfund_zh/best_accuracy ``` The following information will be printed such as precision, recall, hmean and so on. @@ -358,7 +358,7 @@ The configuration file for prediction must be consistent with the training file. ```bash -python3 tools/infer_kie_token_ser.py -c configs/kie/vi_layoutxlm/ser_vi_layoutxlm_xfund_zh.yml -o Architecture.Backbone.checkpoints=./output/ser_vi_layoutxlm_xfund_zh/best_accuracy Global.infer_img=./ppstructure/docs/kie/input/zh_val_42.jpg +python3 tools/infer_kie_token_ser.py -c configs/kie/vi_layoutxlm/ser_vi_layoutxlm_xfund_zh.yml -o Architecture.Backbone.checkpoints=./json/ser_vi_layoutxlm_xfund_zh/best_accuracy Global.infer_img=./ppstructure/docs/kie/input/zh_val_42.jpg ``` The output image is as follows, which is also saved in `Global.save_res_path`. @@ -371,7 +371,7 @@ The output image is as follows, which is also saved in `Global.save_res_path`. During the prediction process, the detection and recognition model of PP-OCRv3 will be loaded by default for information extraction of OCR. If you want to load the OCR results obtained in advance, you can use the following method to predict, and specify `Global.infer_img` as the annotation file, which contains the image path and OCR information, and specifies `Global.infer_mode` as False, indicating that the OCR inference engine is not used at this time. ```bash -python3 tools/infer_kie_token_ser.py -c configs/kie/vi_layoutxlm/ser_vi_layoutxlm_xfund_zh.yml -o Architecture.Backbone.checkpoints=./output/ser_vi_layoutxlm_xfund_zh/best_accuracy Global.infer_img=./train_data/XFUND/zh_val/val.json Global.infer_mode=False +python3 tools/infer_kie_token_ser.py -c configs/kie/vi_layoutxlm/ser_vi_layoutxlm_xfund_zh.yml -o Architecture.Backbone.checkpoints=./json/ser_vi_layoutxlm_xfund_zh/best_accuracy Global.infer_img=./train_data/XFUND/zh_val/val.json Global.infer_mode=False ``` For the above image, if information extraction is performed using the labeled OCR results, the prediction results are as follows. @@ -445,7 +445,7 @@ The SER model can be converted to the inference model using the following comman # -o Set optional parameters. # Architecture.Backbone.checkpoints Set the training model address. # Global.save_inference_dir Set the address where the converted model will be saved. -python3 tools/export_model.py -c configs/kie/vi_layoutxlm/ser_vi_layoutxlm_xfund_zh.yml -o Architecture.Backbone.checkpoints=./output/ser_vi_layoutxlm_xfund_zh/best_accuracy Global.save_inference_dir=./inference/ser_vi_layoutxlm +python3 tools/export_model.py -c configs/kie/vi_layoutxlm/ser_vi_layoutxlm_xfund_zh.yml -o Architecture.Backbone.checkpoints=./json/ser_vi_layoutxlm_xfund_zh/best_accuracy Global.save_inference_dir=./inference/ser_vi_layoutxlm ``` After the conversion is successful, there are three files in the model save directory: @@ -465,7 +465,7 @@ The RE model can be converted to the inference model using the following command # -o Set optional parameters. # Architecture.Backbone.checkpoints Set the training model address. # Global.save_inference_dir Set the address where the converted model will be saved. -python3 tools/export_model.py -c configs/kie/vi_layoutxlm/re_vi_layoutxlm_xfund_zh.yml -o Architecture.Backbone.checkpoints=./output/re_vi_layoutxlm_xfund_zh/best_accuracy Global.save_inference_dir=./inference/re_vi_layoutxlm +python3 tools/export_model.py -c configs/kie/vi_layoutxlm/re_vi_layoutxlm_xfund_zh.yml -o Architecture.Backbone.checkpoints=./json/re_vi_layoutxlm_xfund_zh/best_accuracy Global.save_inference_dir=./inference/re_vi_layoutxlm ``` After the conversion is successful, there are three files in the model save directory: diff --git a/doc/doc_en/knowledge_distillation_en.md b/doc/doc_en/knowledge_distillation_en.md index 334a8c4..25a26e5 100644 --- a/doc/doc_en/knowledge_distillation_en.md +++ b/doc/doc_en/knowledge_distillation_en.md @@ -84,7 +84,7 @@ Architecture: Teacher: # The name of the subnet, it must include at least the `pretrained` and `freeze_params` parameters, and the other parameters are the construction parameters of the subnet pretrained: # Does this sub-network need to load pre-training weights freeze_params: false # Do you need fixed parameters - return_all_feats: true # Do you need to return all features, if it is False, only the final output is returned + return_all_feats: true # Do you need to return all features, if it is False, only the final json is returned model_type: *model_type # Model category algorithm: SVTR # The algorithm name of the sub-network. The remaining parameters of the sub-network are consistent with the general model training configuration Transform: @@ -264,8 +264,8 @@ Loss: loss_config_list: # List of loss function configuration files, mandatory functions for CombinedLoss - DistillationCTCLoss: # CTC loss function based on distillation, inherited from standard CTC loss weight: 1.0 # The weight of the loss function. In loss_config_list, each loss function must include this field - model_name_list: ["Student", "Teacher"] # For the prediction results of the distillation model, extract the output of these two sub-networks and calculate the CTC loss with gt - key: head_out # In the sub-network output dict, take the corresponding tensor + model_name_list: ["Student", "Teacher"] # For the prediction results of the distillation model, extract the json of these two sub-networks and calculate the CTC loss with gt + key: head_out # In the sub-network json dict, take the corresponding tensor - DistillationDMLLoss: # DML loss function, inherited from the standard DMLLoss weight: 1.0 act: "softmax" # Activation function, use it to process the input, can be softmax, sigmoid or None, the default is None @@ -292,8 +292,8 @@ Loss: key: backbone_out - DistillationSARLoss: # SAR loss function based on distillation, inherited from standard SAR loss weight: 1.0 # The weight of the loss function. In loss_config_list, each loss function must include this field - model_name_list: ["Student", "Teacher"] # For the prediction results of the distillation model, extract the output of these two sub-networks and calculate the SAR loss with gt - key: head_out # In the sub-network output dict, take the corresponding tensor + model_name_list: ["Student", "Teacher"] # For the prediction results of the distillation model, extract the json of these two sub-networks and calculate the SAR loss with gt + key: head_out # In the sub-network json dict, take the corresponding tensor multi_head: True # whether it is multi-head or not, if true, SAR branch is used to calculate the loss ``` @@ -322,7 +322,7 @@ In the knowledge distillation task, the post-processing configuration is as foll PostProcess: name: DistillationCTCLabelDecode # CTC decoding post-processing of distillation tasks, inherited from the standard CTCLabelDecode class model_name: ["Student", "Teacher"] # For the prediction results of the distillation model, extract the outputs of these two sub-networks and decode them - key: head_out # Take the corresponding tensor in the subnet output dict + key: head_out # Take the corresponding tensor in the subnet json dict multi_head: True # whether it is multi-head or not, if true, CTC branch is used to calculate the loss ``` @@ -340,7 +340,7 @@ In the knowledge distillation task, the metric calculation configuration is as f ```yaml Metric: name: DistillationMetric # CTC decoding post-processing of distillation tasks, inherited from the standard CTCLabelDecode class - base_metric_name: RecMetric # The base class of indicator calculation. For the output of the model, the indicator will be calculated based on this class + base_metric_name: RecMetric # The base class of indicator calculation. For the json of the model, the indicator will be calculated based on this class main_indicator: acc # The name of the indicator key: "Student" # Select the main_indicator of this subnet as the criterion for saving the best model ignore_space: False # whether to ignore space during evaulation @@ -576,7 +576,7 @@ In the task of detecting knowledge distillation, the post-processing configurati ```yaml PostProcess: name: DistillationDBPostProcess # The post-processing of the DB detection distillation task, inherited from the standard DBPostProcess class - model_name: ["Student", "Student2", "Teacher"] # Extract the output of multiple sub-networks and decode them. The network that does not require post-processing is not set in model_name + model_name: ["Student", "Student2", "Teacher"] # Extract the json of multiple sub-networks and decode them. The network that does not require post-processing is not set in model_name thresh: 0.3 box_thresh: 0.6 max_candidates: 1000 diff --git a/docs/algorithm/formula_recognition/algorithm_rec_can.en.md b/docs/algorithm/formula_recognition/algorithm_rec_can.en.md index 9683c18..d3aefd8 100644 --- a/docs/algorithm/formula_recognition/algorithm_rec_can.en.md +++ b/docs/algorithm/formula_recognition/algorithm_rec_can.en.md @@ -58,7 +58,7 @@ First, the model saved during the CAN handwritten mathematical expression recogn ```bash linenums="1" python3 tools/export_model.py -c configs/rec/rec_d28_can.yml -o Global.pretrained_model=./rec_d28_can_train/best_accuracy.pdparams Global.save_inference_dir=./inference/rec_d28_can/ Architecture.Head.attdecoder.is_train=False -# The default output max length of the model is 36. If you need to predict a longer sequence, please specify its output sequence as an appropriate value when exporting the model, as: Architecture.Head.max_ text_ length=72 +# The default json max length of the model is 36. If you need to predict a longer sequence, please specify its json sequence as an appropriate value when exporting the model, as: Architecture.Head.max_ text_ length=72 ``` For CAN handwritten mathematical expression recognition model inference, the following commands can be executed: diff --git a/docs/algorithm/kie/algorithm_kie_sdmgr.en.md b/docs/algorithm/kie/algorithm_kie_sdmgr.en.md index 2eb7139..1d56064 100644 --- a/docs/algorithm/kie/algorithm_kie_sdmgr.en.md +++ b/docs/algorithm/kie/algorithm_kie_sdmgr.en.md @@ -48,7 +48,7 @@ The config file is `configs/kie/sdmgr/kie_unet_sdmgr.yml`, the default dataset Use the following command to train the model. ```bash linenums="1" -python3 tools/train.py -c configs/kie/sdmgr/kie_unet_sdmgr.yml -o Global.save_model_dir=./output/kie/ +python3 tools/train.py -c configs/kie/sdmgr/kie_unet_sdmgr.yml -o Global.save_model_dir=./json/kie/ ``` ### 3.2 Model evaluation @@ -56,7 +56,7 @@ python3 tools/train.py -c configs/kie/sdmgr/kie_unet_sdmgr.yml -o Global.save_mo Use the following command to evaluate the model: ```bash linenums="1" -python3 tools/eval.py -c configs/kie/sdmgr/kie_unet_sdmgr.yml -o Global.checkpoints=./output/kie/best_accuracy +python3 tools/eval.py -c configs/kie/sdmgr/kie_unet_sdmgr.yml -o Global.checkpoints=./json/kie/best_accuracy ``` An example of output information is shown below. diff --git a/docs/algorithm/kie/algorithm_kie_sdmgr.md b/docs/algorithm/kie/algorithm_kie_sdmgr.md index 04ac586..f9b1123 100644 --- a/docs/algorithm/kie/algorithm_kie_sdmgr.md +++ b/docs/algorithm/kie/algorithm_kie_sdmgr.md @@ -47,7 +47,7 @@ ln -s ../../wildreceipt ./ 训练采用的配置文件是`configs/kie/sdmgr/kie_unet_sdmgr.yml`,配置文件中默认训练数据路径是`train_data/wildreceipt`,准备好数据后,可以通过如下指令执行训练: ```bash linenums="1" -python3 tools/train.py -c configs/kie/sdmgr/kie_unet_sdmgr.yml -o Global.save_model_dir=./output/kie/ +python3 tools/train.py -c configs/kie/sdmgr/kie_unet_sdmgr.yml -o Global.save_model_dir=./json/kie/ ``` ### 3.2 模型评估 @@ -55,7 +55,7 @@ python3 tools/train.py -c configs/kie/sdmgr/kie_unet_sdmgr.yml -o Global.save_mo 执行下面的命令进行模型评估 ```bash linenums="1" -python3 tools/eval.py -c configs/kie/sdmgr/kie_unet_sdmgr.yml -o Global.checkpoints=./output/kie/best_accuracy +python3 tools/eval.py -c configs/kie/sdmgr/kie_unet_sdmgr.yml -o Global.checkpoints=./json/kie/best_accuracy ``` 输出信息示例如下所示: diff --git a/docs/algorithm/table_recognition/algorithm_table_master.en.md b/docs/algorithm/table_recognition/algorithm_table_master.en.md index 77e8ade..cf34598 100644 --- a/docs/algorithm/table_recognition/algorithm_table_master.en.md +++ b/docs/algorithm/table_recognition/algorithm_table_master.en.md @@ -36,7 +36,7 @@ After the data download is complete, please refer to [Text Recognition Training First, convert the model saved in the TableMaster table recognition training process into an inference model. Taking the model based on the TableResNetExtra backbone network and trained on the PubTabNet dataset as example ([model download link](https://paddleocr.bj.bcebos.com/contribution/table_master.tar)), you can use the following command to convert: ```bash linenums="1" -python3 tools/export_model.py -c configs/table/table_master.yml -o Global.pretrained_model=output/table_master/best_accuracy Global.save_inference_dir=./inference/table_master +python3 tools/export_model.py -c configs/table/table_master.yml -o Global.pretrained_model=json/table_master/best_accuracy Global.save_inference_dir=./inference/table_master ``` **Note:** @@ -48,7 +48,7 @@ Execute the following command for model inference: ```bash linenums="1" cd ppstructure/ # When predicting all images in a folder, you can modify image_dir to a folder, such as --image_dir='docs/table'. -python3.7 table/predict_structure.py --table_model_dir=../output/table_master/table_structure_tablemaster_infer/ --table_algorithm=TableMaster --table_char_dict_path=../ppocr/utils/dict/table_master_structure_dict.txt --table_max_len=480 --image_dir=docs/table/table.jpg +python3.7 table/predict_structure.py --table_model_dir=../json/table_master/table_structure_tablemaster_infer/ --table_algorithm=TableMaster --table_char_dict_path=../ppocr/utils/dict/table_master_structure_dict.txt --table_max_len=480 --image_dir=docs/table/table.jpg ``` After executing the command, the prediction results of the above image (structural information and the coordinates of each cell in the table) are printed to the screen, and the visualization of the cell coordinates is also saved. An example is as follows: @@ -59,7 +59,7 @@ result: [2022/06/16 13:06:54] ppocr INFO: result: ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '
', '', ''], [[72.17591094970703, 10.759100914001465, 60.29658508300781, 16.6805362701416], [161.85562133789062, 10.884308815002441, 14.9495210647583, 16.727018356323242], [277.79876708984375, 29.54340362548828, 31.490320205688477, 18.143272399902344], ... [336.11724853515625, 280.3601989746094, 39.456939697265625, 18.121286392211914]] -[2022/06/16 13:06:54] ppocr INFO: save vis result to ./output/table.jpg +[2022/06/16 13:06:54] ppocr INFO: save vis result to ./json/table.jpg [2022/06/16 13:06:54] ppocr INFO: Predict time of docs/table/table.jpg: 17.36806297302246 ``` diff --git a/docs/algorithm/table_recognition/algorithm_table_master.md b/docs/algorithm/table_recognition/algorithm_table_master.md index 7621d01..8bf70d0 100644 --- a/docs/algorithm/table_recognition/algorithm_table_master.md +++ b/docs/algorithm/table_recognition/algorithm_table_master.md @@ -37,7 +37,7 @@ comments: true ```bash linenums="1" # 注意将pretrained_model的路径设置为本地路径。 -python3 tools/export_model.py -c configs/table/table_master.yml -o Global.pretrained_model=output/table_master/best_accuracy Global.save_inference_dir=./inference/table_master +python3 tools/export_model.py -c configs/table/table_master.yml -o Global.pretrained_model=json/table_master/best_accuracy Global.save_inference_dir=./inference/table_master ``` **注意:** 如果您是在自己的数据集上训练的模型,并且调整了字典文件,请注意修改配置文件中的`character_dict_path`是否为所正确的字典文件。 @@ -55,7 +55,7 @@ python3 tools/export_model.py -c configs/table/table_master.yml -o Global.pretra ```bash linenums="1" cd ppstructure/ -python3.7 table/predict_structure.py --table_model_dir=../output/table_master/table_structure_tablemaster_infer/ --table_algorithm=TableMaster --table_char_dict_path=../ppocr/utils/dict/table_master_structure_dict.txt --table_max_len=480 --image_dir=docs/table/table.jpg +python3.7 table/predict_structure.py --table_model_dir=../json/table_master/table_structure_tablemaster_infer/ --table_algorithm=TableMaster --table_char_dict_path=../ppocr/utils/dict/table_master_structure_dict.txt --table_max_len=480 --image_dir=docs/table/table.jpg # 预测文件夹下所有图像时,可修改image_dir为文件夹,如 --image_dir='docs/table'。 ``` @@ -66,7 +66,7 @@ python3.7 table/predict_structure.py --table_model_dir=../output/table_master/ta [2022/06/16 13:06:54] ppocr INFO: result: ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '
', '', ''], [[72.17591094970703, 10.759100914001465, 60.29658508300781, 16.6805362701416], [161.85562133789062, 10.884308815002441, 14.9495210647583, 16.727018356323242], [277.79876708984375, 29.54340362548828, 31.490320205688477, 18.143272399902344], ... [336.11724853515625, 280.3601989746094, 39.456939697265625, 18.121286392211914]] -[2022/06/16 13:06:54] ppocr INFO: save vis result to ./output/table.jpg +[2022/06/16 13:06:54] ppocr INFO: save vis result to ./json/table.jpg [2022/06/16 13:06:54] ppocr INFO: Predict time of docs/table/table.jpg: 17.36806297302246 ``` diff --git a/docs/algorithm/table_recognition/algorithm_table_slanet.md b/docs/algorithm/table_recognition/algorithm_table_slanet.md index 977b75a..b97076f 100644 --- a/docs/algorithm/table_recognition/algorithm_table_slanet.md +++ b/docs/algorithm/table_recognition/algorithm_table_slanet.md @@ -67,7 +67,7 @@ python3 tools/export_model.py -c configs/table/SLANet_lcnetv2.yml -o Global.pret ```bash linenums="1" cd ppstructure/ -python table/predict_structure.py --table_model_dir=../inference/slanet_lcnetv2_infer/ --table_char_dict_path=../ppocr/utils/dict/table_structure_dict.txt --image_dir=docs/table/table.jpg --output=../output/table_slanet_lcnetv2 --use_gpu=False --benchmark=True --enable_mkldnn=True --table_max_len=512 +python table/predict_structure.py --table_model_dir=../inference/slanet_lcnetv2_infer/ --table_char_dict_path=../ppocr/utils/dict/table_structure_dict.txt --image_dir=docs/table/table.jpg --json=../json/table_slanet_lcnetv2 --use_gpu=False --benchmark=True --enable_mkldnn=True --table_max_len=512 # 预测文件夹下所有图像时,可修改image_dir为文件夹,如 --image_dir='docs/table'。 ``` @@ -78,7 +78,7 @@ python table/predict_structure.py --table_model_dir=../inference/slanet_lcnetv2_ [2022/06/16 13:06:54] ppocr INFO: result: ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '
', '', ''], [[72.17591094970703, 10.759100914001465, 60.29658508300781, 16.6805362701416], [161.85562133789062, 10.884308815002441, 14.9495210647583, 16.727018356323242], [277.79876708984375, 29.54340362548828, 31.490320205688477, 18.143272399902344], ... [336.11724853515625, 280.3601989746094, 39.456939697265625, 18.121286392211914]] -[2022/06/16 13:06:54] ppocr INFO: save vis result to ./output/table.jpg +[2022/06/16 13:06:54] ppocr INFO: save vis result to ./json/table.jpg [2022/06/16 13:06:54] ppocr INFO: Predict time of docs/table/table.jpg: 17.36806297302246 ``` diff --git a/docs/algorithm/text_recognition/algorithm_rec_rfl.md b/docs/algorithm/text_recognition/algorithm_rec_rfl.md index 9ab9bd8..a67224a 100644 --- a/docs/algorithm/text_recognition/algorithm_rec_rfl.md +++ b/docs/algorithm/text_recognition/algorithm_rec_rfl.md @@ -42,10 +42,10 @@ python3 -m paddle.distributed.launch --gpus '0,1,2,3' tools/train.py -c configs #step2:联合训练CNT和Att分支,注意将pretrained_model的路径设置为本地路径。 #单卡训练(训练周期长,不建议) -python3 tools/train.py -c configs/rec/rec_resnet_rfl_att.yml -o Global.pretrained_model=./output/rec/rec_resnet_rfl_visual/best_accuracy +python3 tools/train.py -c configs/rec/rec_resnet_rfl_att.yml -o Global.pretrained_model=./json/rec/rec_resnet_rfl_visual/best_accuracy # 多卡训练,通过--gpus参数指定卡号 -python3 -m paddle.distributed.launch --gpus '0,1,2,3' tools/train.py -c configs/rec/rec_resnet_rfl_att.yml -o Global.pretrained_model=./output/rec/rec_resnet_rfl_visual/best_accuracy +python3 -m paddle.distributed.launch --gpus '0,1,2,3' tools/train.py -c configs/rec/rec_resnet_rfl_att.yml -o Global.pretrained_model=./json/rec/rec_resnet_rfl_visual/best_accuracy ``` ### 3.2 评估 @@ -54,7 +54,7 @@ python3 -m paddle.distributed.launch --gpus '0,1,2,3' tools/train.py -c configs ```bash linenums="1" # 注意将pretrained_model的路径设置为本地路径。 -python3 -m paddle.distributed.launch --gpus '0' tools/eval.py -c configs/rec/rec_resnet_rfl_att.yml -o Global.pretrained_model=./output/rec/rec_resnet_rfl_att/best_accuracy +python3 -m paddle.distributed.launch --gpus '0' tools/eval.py -c configs/rec/rec_resnet_rfl_att.yml -o Global.pretrained_model=./json/rec/rec_resnet_rfl_att/best_accuracy ``` ### 3.3 预测 @@ -63,7 +63,7 @@ python3 -m paddle.distributed.launch --gpus '0' tools/eval.py -c configs/rec/rec ```bash linenums="1" # 注意将pretrained_model的路径设置为本地路径。 -python3 tools/infer_rec.py -c configs/rec/rec_resnet_rfl_att.yml -o Global.infer_img='./doc/imgs_words_en/word_10.png' Global.pretrained_model=./output/rec/rec_resnet_rfl_att/best_accuracy +python3 tools/infer_rec.py -c configs/rec/rec_resnet_rfl_att.yml -o Global.infer_img='./doc/imgs_words_en/word_10.png' Global.pretrained_model=./json/rec/rec_resnet_rfl_att/best_accuracy # 预测文件夹下所有图像时,可修改infer_img为文件夹,如 Global.infer_img='./doc/imgs_words_en/'。 ``` @@ -75,7 +75,7 @@ python3 tools/infer_rec.py -c configs/rec/rec_resnet_rfl_att.yml -o Global.infer ```bash linenums="1" # 注意将pretrained_model的路径设置为本地路径。 -python3 tools/export_model.py -c configs/rec/rec_resnet_rfl_att.yml -o Global.pretrained_model=./output/rec/rec_resnet_rfl_att/best_accuracy Global.save_inference_dir=./inference/rec_resnet_rfl_att/ +python3 tools/export_model.py -c configs/rec/rec_resnet_rfl_att.yml -o Global.pretrained_model=./json/rec/rec_resnet_rfl_att/best_accuracy Global.save_inference_dir=./inference/rec_resnet_rfl_att/ ``` **注意:** 如果您是在自己的数据集上训练的模型,并且调整了字典文件,请注意修改配置文件中的`character_dict_path`是否是所需要的字典文件。 diff --git a/docs/algorithm/text_recognition/algorithm_rec_svtrv2.md b/docs/algorithm/text_recognition/algorithm_rec_svtrv2.md index 66733fd..d162c71 100644 --- a/docs/algorithm/text_recognition/algorithm_rec_svtrv2.md +++ b/docs/algorithm/text_recognition/algorithm_rec_svtrv2.md @@ -45,7 +45,7 @@ python -m paddle.distributed.launch --gpus '0,1,2,3,4,5,6,7' tools/train.py -c ```bash linenums="1" # 注意将pretrained_model的路径设置为本地路径。 -python3 -m paddle.distributed.launch --gpus '0' tools/eval.py -c configs/rec/SVTRv2/rec_repsvtr_gtc.yml -o Global.pretrained_model=output/rec_repsvtr_gtc/best_accuracy +python3 -m paddle.distributed.launch --gpus '0' tools/eval.py -c configs/rec/SVTRv2/rec_repsvtr_gtc.yml -o Global.pretrained_model=json/rec_repsvtr_gtc/best_accuracy ``` ### 3.3 预测 @@ -54,7 +54,7 @@ python3 -m paddle.distributed.launch --gpus '0' tools/eval.py -c configs/rec/SVT ```bash linenums="1" # 注意将pretrained_model的路径设置为本地路径。 -python3 tools/infer_rec.py -c tools/eval.py -c configs/rec/SVTRv2/rec_repsvtr_gtc.yml -o Global.pretrained_model=output/rec_repsvtr_gtc/best_accuracy Global.infer_img='./doc/imgs_words_en/word_10.png' +python3 tools/infer_rec.py -c tools/eval.py -c configs/rec/SVTRv2/rec_repsvtr_gtc.yml -o Global.pretrained_model=json/rec_repsvtr_gtc/best_accuracy Global.infer_img='./doc/imgs_words_en/word_10.png' # 预测文件夹下所有图像时,可修改infer_img为文件夹,如 Global.infer_img='./doc/imgs_words_en/'。 ``` @@ -66,7 +66,7 @@ python3 tools/infer_rec.py -c tools/eval.py -c configs/rec/SVTRv2/rec_repsvtr_gt ```bash linenums="1" # 注意将pretrained_model的路径设置为本地路径。 -python3 tools/export_model.py -c configs/rec/SVTRv2/rec_repsvtr_gtc.yml -o Global.pretrained_model=output/rec_repsvtr_gtc/best_accuracy Global.save_inference_dir=./inference/rec_repsvtr_infer +python3 tools/export_model.py -c configs/rec/SVTRv2/rec_repsvtr_gtc.yml -o Global.pretrained_model=json/rec_repsvtr_gtc/best_accuracy Global.save_inference_dir=./inference/rec_repsvtr_infer ``` **注意:** 如果您是在自己的数据集上训练的模型,并且调整了字典文件,请注意修改配置文件中的`character_dict_path`是否为所正确的字典文件。 diff --git a/docs/applications/PCB字符识别.md b/docs/applications/PCB字符识别.md index 4a49b77..6c2e2e5 100644 --- a/docs/applications/PCB字符识别.md +++ b/docs/applications/PCB字符识别.md @@ -224,7 +224,7 @@ python tools/train.py \ cd /home/aistudio/PaddleOCR/ python3 tools/eval.py \ -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml \ - -o Global.checkpoints="./output/ch_PP-OCR_V3_det/latest" + -o Global.checkpoints="./json/ch_PP-OCR_V3_det/latest" ``` 使用训练好的模型进行评估,指标如下所示: @@ -386,7 +386,7 @@ inference 模型(paddle.jit.save保存的模型) 一般是模型训练,把 # 导出检测模型 python3 tools/export_model.py \ -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml \ - -o Global.pretrained_model="./output/ch_PP-OCR_V3_det/latest" \ + -o Global.pretrained_model="./json/ch_PP-OCR_V3_det/latest" \ Global.save_inference_dir="./inference_model/ch_PP-OCR_V3_det/" ``` @@ -421,7 +421,7 @@ python3 tools/infer/predict_det.py \ # 导出识别模型 python3 tools/export_model.py \ -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml \ - -o Global.pretrained_model="./output/rec_ppocr_v3/latest" \ + -o Global.pretrained_model="./json/rec_ppocr_v3/latest" \ Global.save_inference_dir="./inference_model/rec_ppocr_v3/" ``` diff --git a/docs/applications/中文表格识别.md b/docs/applications/中文表格识别.md index f46f630..1b18974 100644 --- a/docs/applications/中文表格识别.md +++ b/docs/applications/中文表格识别.md @@ -224,7 +224,7 @@ os.chdir('/home/aistudio/PaddleOCR') 训练完成后,可使用如下命令在测试集上评估最优模型的精度 ```bash linenums="1" -! python3 tools/eval.py -c /home/aistudio/SLANet_ch.yml -o Global.checkpoints=/home/aistudio/PaddleOCR/output/SLANet_ch/best_accuracy.pdparams +! python3 tools/eval.py -c /home/aistudio/SLANet_ch.yml -o Global.checkpoints=/home/aistudio/PaddleOCR/json/SLANet_ch/best_accuracy.pdparams ``` ### 2.5 训练引擎推理 @@ -233,7 +233,7 @@ os.chdir('/home/aistudio/PaddleOCR') ```bash linenums="1" import os;os.chdir('/home/aistudio/PaddleOCR') -! python3 tools/infer_table.py -c /home/aistudio/SLANet_ch.yml -o Global.checkpoints=/home/aistudio/PaddleOCR/output/SLANet_ch/best_accuracy.pdparams Global.infer_img=/home/aistudio/data/data165849/table_gen_dataset/Crop_img/no_border_18298_G7XZH93DDCMATGJQ8RW2.jpg +! python3 tools/infer_table.py -c /home/aistudio/SLANet_ch.yml -o Global.checkpoints=/home/aistudio/PaddleOCR/json/SLANet_ch/best_accuracy.pdparams Global.infer_img=/home/aistudio/data/data165849/table_gen_dataset/Crop_img/no_border_18298_G7XZH93DDCMATGJQ8RW2.jpg ``` ```python linenums="1" @@ -248,7 +248,7 @@ plt.imshow(show_img) plt.show() # 显示预测的单元格 -show_img = cv2.imread('/home/aistudio/PaddleOCR/output/infer/no_border_18298_G7XZH93DDCMATGJQ8RW2.jpg') +show_img = cv2.imread('/home/aistudio/PaddleOCR/json/infer/no_border_18298_G7XZH93DDCMATGJQ8RW2.jpg') plt.figure(figsize=(15,15)) plt.imshow(show_img) plt.show() @@ -259,7 +259,7 @@ plt.show() 使用如下命令可将模型导出为inference模型 ```bash linenums="1" -! python3 tools/export_model.py -c /home/aistudio/SLANet_ch.yml -o Global.checkpoints=/home/aistudio/PaddleOCR/output/SLANet_ch/best_accuracy.pdparams Global.save_inference_dir=/home/aistudio/SLANet_ch/infer +! python3 tools/export_model.py -c /home/aistudio/SLANet_ch.yml -o Global.checkpoints=/home/aistudio/PaddleOCR/json/SLANet_ch/best_accuracy.pdparams Global.save_inference_dir=/home/aistudio/SLANet_ch/infer ``` ### 2.7 预测引擎推理 @@ -272,7 +272,7 @@ os.chdir('/home/aistudio/PaddleOCR/ppstructure') --table_model_dir=/home/aistudio/SLANet_ch/infer \ --table_char_dict_path=../ppocr/utils/dict/table_structure_dict.txt \ --image_dir=/home/aistudio/data/data165849/table_gen_dataset/Crop_img/no_border_18298_G7XZH93DDCMATGJQ8RW2.jpg \ - --output=../output/inference + --json=../json/inference ``` ```python linenums="1" @@ -283,7 +283,7 @@ plt.imshow(show_img) plt.show() # 显示预测的单元格 -show_img = cv2.imread('/home/aistudio/PaddleOCR/output/inference/no_border_18298_G7XZH93DDCMATGJQ8RW2.jpg') +show_img = cv2.imread('/home/aistudio/PaddleOCR/json/inference/no_border_18298_G7XZH93DDCMATGJQ8RW2.jpg') plt.figure(figsize=(15,15)) plt.imshow(show_img) plt.show() @@ -313,7 +313,7 @@ import os;os.chdir('/home/aistudio/PaddleOCR/ppstructure') --rec_char_dict_path=../ppocr/utils/ppocr_keys_v1.txt \ --table_char_dict_path=../ppocr/utils/dict/table_structure_dict.txt \ --image_dir=/home/aistudio/data/data165849/table_gen_dataset/Crop_img/no_border_18298_G7XZH93DDCMATGJQ8RW2.jpg \ - --output=../output/table + --json=../json/table ``` ```python linenums="1" @@ -388,7 +388,7 @@ display(HTML('") - # format output + # format json match_result.setdefault("matched_master_token_list", master_token_list) return match_result diff --git a/ppstructure/table/table_metric/table_metric.py b/ppstructure/table/table_metric/table_metric.py index 1ed4c45..4e9deef 100644 --- a/ppstructure/table/table_metric/table_metric.py +++ b/ppstructure/table/table_metric/table_metric.py @@ -192,7 +192,7 @@ class TEDS(object): a batch of samples @params pred_json: {'FILENAME': 'HTML CODE', ...} @params true_json: {'FILENAME': {'html': 'HTML CODE'}, ...} - @output: {'FILENAME': 'TEDS SCORE', ...} + @json: {'FILENAME': 'TEDS SCORE', ...} """ samples = true_json.keys() if self.n_jobs == 1: diff --git a/ppstructure/utility.py b/ppstructure/utility.py index bffc1fd..aaa6db1 100644 --- a/ppstructure/utility.py +++ b/ppstructure/utility.py @@ -28,8 +28,8 @@ import math def init_args(): parser = infer_args() - # params for output - parser.add_argument("--output", type=str, default="./output") + # params for json + parser.add_argument("--json", type=str, default="./json") # params for table structure parser.add_argument("--table_max_len", type=int, default=488) parser.add_argument("--table_algorithm", type=str, default="TableAttn") diff --git a/test_tipc/compare_results.py b/test_tipc/compare_results.py index 96a1f20..7d84c6d 100644 --- a/test_tipc/compare_results.py +++ b/test_tipc/compare_results.py @@ -110,7 +110,7 @@ def testing_assert_allclose(dict_x, dict_y, atol=1e-7, rtol=1e-7): if __name__ == "__main__": # Usage: - # python3.7 tests/compare_results.py --gt_file=./tests/results/*.txt --log_file=./tests/output/infer_*.log + # python3.7 tests/compare_results.py --gt_file=./tests/results/*.txt --log_file=./tests/json/infer_*.log args = parse_args() diff --git a/test_tipc/configs/ch_PP-OCRv2_rec/ch_PP-OCRv2_rec_distillation.yml b/test_tipc/configs/ch_PP-OCRv2_rec/ch_PP-OCRv2_rec_distillation.yml index 43e14b8..136a23d 100644 --- a/test_tipc/configs/ch_PP-OCRv2_rec/ch_PP-OCRv2_rec_distillation.yml +++ b/test_tipc/configs/ch_PP-OCRv2_rec/ch_PP-OCRv2_rec_distillation.yml @@ -4,7 +4,7 @@ Global: epoch_num: 800 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec_pp-OCRv2_distillation + save_model_dir: ./json/rec_pp-OCRv2_distillation save_epoch_step: 3 eval_batch_step: [0, 200000] cal_metric_during_train: true @@ -18,7 +18,7 @@ Global: infer_mode: false use_space_char: true distributed: true - save_res_path: ./output/rec/predicts_pp-OCRv2_distillation.txt + save_res_path: ./json/rec/predicts_pp-OCRv2_distillation.txt Optimizer: diff --git a/test_tipc/configs/ch_PP-OCRv3_rec/ch_PP-OCRv3_rec_distillation.yml b/test_tipc/configs/ch_PP-OCRv3_rec/ch_PP-OCRv3_rec_distillation.yml index 6336213..1b45a26 100644 --- a/test_tipc/configs/ch_PP-OCRv3_rec/ch_PP-OCRv3_rec_distillation.yml +++ b/test_tipc/configs/ch_PP-OCRv3_rec/ch_PP-OCRv3_rec_distillation.yml @@ -4,7 +4,7 @@ Global: epoch_num: 800 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec_ppocr_v3_distillation + save_model_dir: ./json/rec_ppocr_v3_distillation save_epoch_step: 3 eval_batch_step: [0, 2000] cal_metric_during_train: true @@ -18,7 +18,7 @@ Global: infer_mode: false use_space_char: true distributed: true - save_res_path: ./output/rec/predicts_ppocrv3_distillation.txt + save_res_path: ./json/rec/predicts_ppocrv3_distillation.txt d2s_train_image_shape: [3, 48, -1] diff --git a/test_tipc/configs/ch_ppocr_mobile_v2_0_rec_FPGM/rec_chinese_lite_train_v2.0.yml b/test_tipc/configs/ch_ppocr_mobile_v2_0_rec_FPGM/rec_chinese_lite_train_v2.0.yml index ee42dbf..ce16b2f 100644 --- a/test_tipc/configs/ch_ppocr_mobile_v2_0_rec_FPGM/rec_chinese_lite_train_v2.0.yml +++ b/test_tipc/configs/ch_ppocr_mobile_v2_0_rec_FPGM/rec_chinese_lite_train_v2.0.yml @@ -3,7 +3,7 @@ Global: epoch_num: 500 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec_chinese_lite_v2.0 + save_model_dir: ./json/rec_chinese_lite_v2.0 save_epoch_step: 3 # evaluation is run every 5000 iterations after the 4000th iteration eval_batch_step: [0, 2000] @@ -18,7 +18,7 @@ Global: max_text_length: 25 infer_mode: False use_space_char: True - save_res_path: ./output/rec/predicts_chinese_lite_v2.0.txt + save_res_path: ./json/rec/predicts_chinese_lite_v2.0.txt Optimizer: diff --git a/test_tipc/configs/ch_ppocr_mobile_v2_0_rec_KL/rec_chinese_lite_train_v2.0.yml b/test_tipc/configs/ch_ppocr_mobile_v2_0_rec_KL/rec_chinese_lite_train_v2.0.yml index b06dafe..fdaf0cd 100644 --- a/test_tipc/configs/ch_ppocr_mobile_v2_0_rec_KL/rec_chinese_lite_train_v2.0.yml +++ b/test_tipc/configs/ch_ppocr_mobile_v2_0_rec_KL/rec_chinese_lite_train_v2.0.yml @@ -3,7 +3,7 @@ Global: epoch_num: 500 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec_chinese_lite_v2.0 + save_model_dir: ./json/rec_chinese_lite_v2.0 save_epoch_step: 3 # evaluation is run every 5000 iterations after the 4000th iteration eval_batch_step: [0, 2000] @@ -18,7 +18,7 @@ Global: max_text_length: 25 infer_mode: False use_space_char: True - save_res_path: ./output/rec/predicts_chinese_lite_v2.0.txt + save_res_path: ./json/rec/predicts_chinese_lite_v2.0.txt Optimizer: diff --git a/test_tipc/configs/ch_ppocr_mobile_v2_0_rec_PACT/rec_chinese_lite_train_v2.0.yml b/test_tipc/configs/ch_ppocr_mobile_v2_0_rec_PACT/rec_chinese_lite_train_v2.0.yml index b06dafe..fdaf0cd 100644 --- a/test_tipc/configs/ch_ppocr_mobile_v2_0_rec_PACT/rec_chinese_lite_train_v2.0.yml +++ b/test_tipc/configs/ch_ppocr_mobile_v2_0_rec_PACT/rec_chinese_lite_train_v2.0.yml @@ -3,7 +3,7 @@ Global: epoch_num: 500 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec_chinese_lite_v2.0 + save_model_dir: ./json/rec_chinese_lite_v2.0 save_epoch_step: 3 # evaluation is run every 5000 iterations after the 4000th iteration eval_batch_step: [0, 2000] @@ -18,7 +18,7 @@ Global: max_text_length: 25 infer_mode: False use_space_char: True - save_res_path: ./output/rec/predicts_chinese_lite_v2.0.txt + save_res_path: ./json/rec/predicts_chinese_lite_v2.0.txt Optimizer: diff --git a/test_tipc/configs/ch_ppocr_server_v2_0_det/det_r50_vd_db.yml b/test_tipc/configs/ch_ppocr_server_v2_0_det/det_r50_vd_db.yml index 6728703..b2494ac 100644 --- a/test_tipc/configs/ch_ppocr_server_v2_0_det/det_r50_vd_db.yml +++ b/test_tipc/configs/ch_ppocr_server_v2_0_det/det_r50_vd_db.yml @@ -3,7 +3,7 @@ Global: epoch_num: 5 log_smooth_window: 20 print_batch_step: 2 - save_model_dir: ./output/db_mv3/ + save_model_dir: ./json/db_mv3/ save_epoch_step: 1200 # evaluation is run every 2000 iterations eval_batch_step: [0, 30000] @@ -13,7 +13,7 @@ Global: save_inference_dir: use_visualdl: False infer_img: doc/imgs_en/img_10.jpg - save_res_path: ./output/det_db/predicts_db.txt + save_res_path: ./json/det_db/predicts_db.txt Architecture: model_type: det diff --git a/test_tipc/configs/ch_ppocr_server_v2_0_rec/rec_icdar15_train.yml b/test_tipc/configs/ch_ppocr_server_v2_0_rec/rec_icdar15_train.yml index 5825c3e..fc78457 100644 --- a/test_tipc/configs/ch_ppocr_server_v2_0_rec/rec_icdar15_train.yml +++ b/test_tipc/configs/ch_ppocr_server_v2_0_rec/rec_icdar15_train.yml @@ -3,7 +3,7 @@ Global: epoch_num: 72 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec/ic15/ + save_model_dir: ./json/rec/ic15/ save_epoch_step: 3 # evaluation is run every 2000 iterations eval_batch_step: [0, 2000] @@ -19,7 +19,7 @@ Global: max_text_length: 25 infer_mode: False use_space_char: False - save_res_path: ./output/rec/predicts_ic15.txt + save_res_path: ./json/rec/predicts_ic15.txt Optimizer: name: Adam diff --git a/test_tipc/configs/det_mv3_east_v2_0/det_mv3_east.yml b/test_tipc/configs/det_mv3_east_v2_0/det_mv3_east.yml index 461179e..eb4932a 100644 --- a/test_tipc/configs/det_mv3_east_v2_0/det_mv3_east.yml +++ b/test_tipc/configs/det_mv3_east_v2_0/det_mv3_east.yml @@ -3,7 +3,7 @@ Global: epoch_num: 10000 log_smooth_window: 20 print_batch_step: 2 - save_model_dir: ./output/east_mv3/ + save_model_dir: ./json/east_mv3/ save_epoch_step: 1000 # evaluation is run every 5000 iterations after the 4000th iteration eval_batch_step: [4000, 5000] @@ -13,7 +13,7 @@ Global: save_inference_dir: use_visualdl: False infer_img: - save_res_path: ./output/det_east/predicts_east.txt + save_res_path: ./json/det_east/predicts_east.txt Architecture: model_type: det diff --git a/test_tipc/configs/det_mv3_pse_v2_0/det_mv3_pse.yml b/test_tipc/configs/det_mv3_pse_v2_0/det_mv3_pse.yml index 27ec3eb..1f5ee00 100644 --- a/test_tipc/configs/det_mv3_pse_v2_0/det_mv3_pse.yml +++ b/test_tipc/configs/det_mv3_pse_v2_0/det_mv3_pse.yml @@ -3,17 +3,17 @@ Global: epoch_num: 600 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/det_mv3_pse/ + save_model_dir: ./json/det_mv3_pse/ save_epoch_step: 600 # evaluation is run every 63 iterations eval_batch_step: [ 0,1000 ] cal_metric_during_train: False pretrained_model: ./pretrain_models/MobileNetV3_large_x0_5_pretrained - checkpoints: #./output/det_r50_vd_pse_batch8_ColorJitter/best_accuracy + checkpoints: #./json/det_r50_vd_pse_batch8_ColorJitter/best_accuracy save_inference_dir: use_visualdl: False infer_img: doc/imgs_en/img_10.jpg - save_res_path: ./output/det_pse/predicts_pse.txt + save_res_path: ./json/det_pse/predicts_pse.txt Architecture: model_type: det diff --git a/test_tipc/configs/det_r50_dcn_fce_ctw_v2_0/det_r50_vd_dcn_fce_ctw.yml b/test_tipc/configs/det_r50_dcn_fce_ctw_v2_0/det_r50_vd_dcn_fce_ctw.yml index cd355f1..a46bd86 100644 --- a/test_tipc/configs/det_r50_dcn_fce_ctw_v2_0/det_r50_vd_dcn_fce_ctw.yml +++ b/test_tipc/configs/det_r50_dcn_fce_ctw_v2_0/det_r50_vd_dcn_fce_ctw.yml @@ -3,7 +3,7 @@ Global: epoch_num: 1500 log_smooth_window: 20 print_batch_step: 20 - save_model_dir: ./output/det_r50_dcn_fce_ctw/ + save_model_dir: ./json/det_r50_dcn_fce_ctw/ save_epoch_step: 100 # evaluation is run every 835 iterations eval_batch_step: [0, 4000] @@ -13,7 +13,7 @@ Global: save_inference_dir: use_visualdl: False infer_img: doc/imgs_en/img_10.jpg - save_res_path: ./output/det_fce/predicts_fce.txt + save_res_path: ./json/det_fce/predicts_fce.txt Architecture: diff --git a/test_tipc/configs/det_r50_vd_east_v2_0/det_r50_vd_east.yml b/test_tipc/configs/det_r50_vd_east_v2_0/det_r50_vd_east.yml index ae7bd94..cb53b6c 100644 --- a/test_tipc/configs/det_r50_vd_east_v2_0/det_r50_vd_east.yml +++ b/test_tipc/configs/det_r50_vd_east_v2_0/det_r50_vd_east.yml @@ -3,7 +3,7 @@ Global: epoch_num: 10000 log_smooth_window: 20 print_batch_step: 2 - save_model_dir: ./output/east_r50_vd/ + save_model_dir: ./json/east_r50_vd/ save_epoch_step: 1000 # evaluation is run every 5000 iterations after the 4000th iteration eval_batch_step: [4000, 5000] @@ -13,7 +13,7 @@ Global: save_inference_dir: use_visualdl: False infer_img: - save_res_path: ./output/det_east/predicts_east.txt + save_res_path: ./json/det_east/predicts_east.txt Architecture: model_type: det diff --git a/test_tipc/configs/det_r50_vd_pse_v2_0/det_r50_vd_pse.yml b/test_tipc/configs/det_r50_vd_pse_v2_0/det_r50_vd_pse.yml index c069d1f..74b17fe 100644 --- a/test_tipc/configs/det_r50_vd_pse_v2_0/det_r50_vd_pse.yml +++ b/test_tipc/configs/det_r50_vd_pse_v2_0/det_r50_vd_pse.yml @@ -3,17 +3,17 @@ Global: epoch_num: 600 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/det_r50_vd_pse/ + save_model_dir: ./json/det_r50_vd_pse/ save_epoch_step: 600 # evaluation is run every 125 iterations eval_batch_step: [ 0,1000 ] cal_metric_during_train: False pretrained_model: ./pretrain_models/ResNet50_vd_ssld_pretrained - checkpoints: #./output/det_r50_vd_pse_batch8_ColorJitter/best_accuracy + checkpoints: #./json/det_r50_vd_pse_batch8_ColorJitter/best_accuracy save_inference_dir: use_visualdl: False infer_img: doc/imgs_en/img_10.jpg - save_res_path: ./output/det_pse/predicts_pse.txt + save_res_path: ./json/det_pse/predicts_pse.txt Architecture: model_type: det diff --git a/test_tipc/configs/det_r50_vd_sast_icdar15_v2_0/det_r50_vd_sast_icdar2015.yml b/test_tipc/configs/det_r50_vd_sast_icdar15_v2_0/det_r50_vd_sast_icdar2015.yml index 8055884..dd697fb 100644 --- a/test_tipc/configs/det_r50_vd_sast_icdar15_v2_0/det_r50_vd_sast_icdar2015.yml +++ b/test_tipc/configs/det_r50_vd_sast_icdar15_v2_0/det_r50_vd_sast_icdar2015.yml @@ -3,7 +3,7 @@ Global: epoch_num: 5000 log_smooth_window: 20 print_batch_step: 2 - save_model_dir: ./output/sast_r50_vd_ic15/ + save_model_dir: ./json/sast_r50_vd_ic15/ save_epoch_step: 1000 # evaluation is run every 5000 iterations after the 4000th iteration eval_batch_step: [4000, 5000] @@ -13,7 +13,7 @@ Global: save_inference_dir: use_visualdl: False infer_img: - save_res_path: ./output/sast_r50_vd_ic15/predicts_sast.txt + save_res_path: ./json/sast_r50_vd_ic15/predicts_sast.txt Architecture: diff --git a/test_tipc/configs/det_r50_vd_sast_totaltext_v2_0/det_r50_vd_sast_totaltext.yml b/test_tipc/configs/det_r50_vd_sast_totaltext_v2_0/det_r50_vd_sast_totaltext.yml index 6c6a9f1..a77b682 100644 --- a/test_tipc/configs/det_r50_vd_sast_totaltext_v2_0/det_r50_vd_sast_totaltext.yml +++ b/test_tipc/configs/det_r50_vd_sast_totaltext_v2_0/det_r50_vd_sast_totaltext.yml @@ -3,7 +3,7 @@ Global: epoch_num: 5000 log_smooth_window: 20 print_batch_step: 2 - save_model_dir: ./output/sast_r50_vd_tt/ + save_model_dir: ./json/sast_r50_vd_tt/ save_epoch_step: 1000 # evaluation is run every 5000 iterations after the 4000th iteration eval_batch_step: [4000, 5000] @@ -13,7 +13,7 @@ Global: save_inference_dir: use_visualdl: False infer_img: - save_res_path: ./output/sast_r50_vd_tt/predicts_sast.txt + save_res_path: ./json/sast_r50_vd_tt/predicts_sast.txt Architecture: model_type: det diff --git a/test_tipc/configs/layoutxlm_ser/ser_layoutxlm_xfund_zh.yml b/test_tipc/configs/layoutxlm_ser/ser_layoutxlm_xfund_zh.yml index 31e0ed4..058a162 100644 --- a/test_tipc/configs/layoutxlm_ser/ser_layoutxlm_xfund_zh.yml +++ b/test_tipc/configs/layoutxlm_ser/ser_layoutxlm_xfund_zh.yml @@ -3,7 +3,7 @@ Global: epoch_num: &epoch_num 200 log_smooth_window: 10 print_batch_step: 10 - save_model_dir: ./output/ser_layoutxlm_xfund_zh + save_model_dir: ./json/ser_layoutxlm_xfund_zh save_epoch_step: 2000 # evaluation is run every 10 iterations after the 0th iteration eval_batch_step: [ 0, 187 ] @@ -12,7 +12,7 @@ Global: use_visualdl: False seed: 2022 infer_img: ppstructure/docs/kie/input/zh_val_42.jpg - save_res_path: ./output/ser_layoutxlm_xfund_zh/res + save_res_path: ./json/ser_layoutxlm_xfund_zh/res Architecture: model_type: kie diff --git a/test_tipc/configs/rec_d28_can/rec_d28_can.yml b/test_tipc/configs/rec_d28_can/rec_d28_can.yml index 5501865..dfac153 100644 --- a/test_tipc/configs/rec_d28_can/rec_d28_can.yml +++ b/test_tipc/configs/rec_d28_can/rec_d28_can.yml @@ -3,7 +3,7 @@ Global: epoch_num: 240 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec/can/ + save_model_dir: ./json/rec/can/ save_epoch_step: 1 # evaluation is run every 1105 iterations (1 epoch)(batch_size = 8) eval_batch_step: [0, 1105] @@ -18,7 +18,7 @@ Global: max_text_length: 36 infer_mode: False use_space_char: False - save_res_path: ./output/rec/predicts_can.txt + save_res_path: ./json/rec/predicts_can.txt Optimizer: name: Momentum diff --git a/test_tipc/configs/rec_mtb_nrtr/rec_mtb_nrtr.yml b/test_tipc/configs/rec_mtb_nrtr/rec_mtb_nrtr.yml index 8118d58..647f703 100644 --- a/test_tipc/configs/rec_mtb_nrtr/rec_mtb_nrtr.yml +++ b/test_tipc/configs/rec_mtb_nrtr/rec_mtb_nrtr.yml @@ -3,7 +3,7 @@ Global: epoch_num: 21 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec/nrtr/ + save_model_dir: ./json/rec/nrtr/ save_epoch_step: 1 # evaluation is run every 2000 iterations eval_batch_step: [0, 2000] @@ -18,7 +18,7 @@ Global: max_text_length: 25 infer_mode: False use_space_char: False - save_res_path: ./output/rec/predicts_nrtr.txt + save_res_path: ./json/rec/predicts_nrtr.txt Optimizer: name: Adam diff --git a/test_tipc/configs/rec_mv3_none_bilstm_ctc_v2_0/rec_icdar15_train.yml b/test_tipc/configs/rec_mv3_none_bilstm_ctc_v2_0/rec_icdar15_train.yml index b0ba615..1930694 100644 --- a/test_tipc/configs/rec_mv3_none_bilstm_ctc_v2_0/rec_icdar15_train.yml +++ b/test_tipc/configs/rec_mv3_none_bilstm_ctc_v2_0/rec_icdar15_train.yml @@ -3,7 +3,7 @@ Global: epoch_num: 72 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec/mv3_none_bilstm_ctc/ + save_model_dir: ./json/rec/mv3_none_bilstm_ctc/ save_epoch_step: 3 # evaluation is run every 2000 iterations eval_batch_step: [0, 20000] @@ -18,7 +18,7 @@ Global: max_text_length: 25 infer_mode: False use_space_char: False - save_res_path: ./output/rec/predicts_mv3_none_bilstm_ctc.txt + save_res_path: ./json/rec/predicts_mv3_none_bilstm_ctc.txt Optimizer: name: Adam diff --git a/test_tipc/configs/rec_mv3_none_none_ctc_v2_0/rec_icdar15_train.yml b/test_tipc/configs/rec_mv3_none_none_ctc_v2_0/rec_icdar15_train.yml index 06a2b71..91f3c1a 100644 --- a/test_tipc/configs/rec_mv3_none_none_ctc_v2_0/rec_icdar15_train.yml +++ b/test_tipc/configs/rec_mv3_none_none_ctc_v2_0/rec_icdar15_train.yml @@ -3,7 +3,7 @@ Global: epoch_num: 72 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec/mv3_none_none_ctc/ + save_model_dir: ./json/rec/mv3_none_none_ctc/ save_epoch_step: 3 # evaluation is run every 2000 iterations eval_batch_step: [0, 2000] @@ -18,7 +18,7 @@ Global: max_text_length: 25 infer_mode: False use_space_char: False - save_res_path: ./output/rec/predicts_mv3_none_none_ctc.txt + save_res_path: ./json/rec/predicts_mv3_none_none_ctc.txt Optimizer: name: Adam diff --git a/test_tipc/configs/rec_mv3_tps_bilstm_att_v2_0/rec_mv3_tps_bilstm_att.yml b/test_tipc/configs/rec_mv3_tps_bilstm_att_v2_0/rec_mv3_tps_bilstm_att.yml index 2b14c04..5e8aabd 100644 --- a/test_tipc/configs/rec_mv3_tps_bilstm_att_v2_0/rec_mv3_tps_bilstm_att.yml +++ b/test_tipc/configs/rec_mv3_tps_bilstm_att_v2_0/rec_mv3_tps_bilstm_att.yml @@ -3,7 +3,7 @@ Global: epoch_num: 72 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec/rec_mv3_tps_bilstm_att/ + save_model_dir: ./json/rec/rec_mv3_tps_bilstm_att/ save_epoch_step: 3 # evaluation is run every 5000 iterations after the 4000th iteration eval_batch_step: [0, 2000] @@ -18,7 +18,7 @@ Global: max_text_length: 25 infer_mode: False use_space_char: False - save_res_path: ./output/rec/predicts_mv3_tps_bilstm_att.txt + save_res_path: ./json/rec/predicts_mv3_tps_bilstm_att.txt Optimizer: diff --git a/test_tipc/configs/rec_mv3_tps_bilstm_ctc_v2_0/rec_icdar15_train.yml b/test_tipc/configs/rec_mv3_tps_bilstm_ctc_v2_0/rec_icdar15_train.yml index e20ea00..56b6cd4 100644 --- a/test_tipc/configs/rec_mv3_tps_bilstm_ctc_v2_0/rec_icdar15_train.yml +++ b/test_tipc/configs/rec_mv3_tps_bilstm_ctc_v2_0/rec_icdar15_train.yml @@ -3,7 +3,7 @@ Global: epoch_num: 72 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec/mv3_tps_bilstm_ctc/ + save_model_dir: ./json/rec/mv3_tps_bilstm_ctc/ save_epoch_step: 3 # evaluation is run every 2000 iterations eval_batch_step: [0, 2000] @@ -18,7 +18,7 @@ Global: max_text_length: 25 infer_mode: False use_space_char: False - save_res_path: ./output/rec/predicts_mv3_tps_bilstm_ctc.txt + save_res_path: ./json/rec/predicts_mv3_tps_bilstm_ctc.txt Optimizer: name: Adam diff --git a/test_tipc/configs/rec_parseq/rec_vit_parseq.yml b/test_tipc/configs/rec_parseq/rec_vit_parseq.yml index fc283ba..eb57c26 100644 --- a/test_tipc/configs/rec_parseq/rec_vit_parseq.yml +++ b/test_tipc/configs/rec_parseq/rec_vit_parseq.yml @@ -3,7 +3,7 @@ Global: epoch_num: 20 log_smooth_window: 20 print_batch_step: 5 - save_model_dir: ./output/rec/parseq + save_model_dir: ./json/rec/parseq save_epoch_step: 3 # evaluation is run every 5000 iterations after the 4000th iteration eval_batch_step: [0, 500] @@ -20,7 +20,7 @@ Global: num_heads: 8 infer_mode: False use_space_char: False - save_res_path: ./output/rec/predicts_parseq.txt + save_res_path: ./json/rec/predicts_parseq.txt Optimizer: diff --git a/test_tipc/configs/rec_r31_robustscanner/rec_r31_robustscanner.yml b/test_tipc/configs/rec_r31_robustscanner/rec_r31_robustscanner.yml index b5466d4..8bf2530 100644 --- a/test_tipc/configs/rec_r31_robustscanner/rec_r31_robustscanner.yml +++ b/test_tipc/configs/rec_r31_robustscanner/rec_r31_robustscanner.yml @@ -3,7 +3,7 @@ Global: epoch_num: 5 log_smooth_window: 20 print_batch_step: 20 - save_model_dir: ./output/rec/rec_r31_robustscanner/ + save_model_dir: ./json/rec/rec_r31_robustscanner/ save_epoch_step: 1 # evaluation is run every 2000 iterations eval_batch_step: [0, 2000] @@ -19,7 +19,7 @@ Global: infer_mode: False use_space_char: False rm_symbol: True - save_res_path: ./output/rec/predicts_robustscanner.txt + save_res_path: ./json/rec/predicts_robustscanner.txt Optimizer: name: Adam diff --git a/test_tipc/configs/rec_r31_sar/rec_r31_sar.yml b/test_tipc/configs/rec_r31_sar/rec_r31_sar.yml index 36bc3c5..2b181b3 100644 --- a/test_tipc/configs/rec_r31_sar/rec_r31_sar.yml +++ b/test_tipc/configs/rec_r31_sar/rec_r31_sar.yml @@ -19,7 +19,7 @@ Global: infer_mode: False use_space_char: False rm_symbol: True - save_res_path: ./output/rec/predicts_sar.txt + save_res_path: ./json/rec/predicts_sar.txt Optimizer: name: Adam diff --git a/test_tipc/configs/rec_r32_gaspin_bilstm_att/rec_r32_gaspin_bilstm_att.yml b/test_tipc/configs/rec_r32_gaspin_bilstm_att/rec_r32_gaspin_bilstm_att.yml index 21d56b6..b651a5a 100644 --- a/test_tipc/configs/rec_r32_gaspin_bilstm_att/rec_r32_gaspin_bilstm_att.yml +++ b/test_tipc/configs/rec_r32_gaspin_bilstm_att/rec_r32_gaspin_bilstm_att.yml @@ -3,7 +3,7 @@ Global: epoch_num: 6 log_smooth_window: 50 print_batch_step: 50 - save_model_dir: ./output/rec/rec_r32_gaspin_bilstm_att/ + save_model_dir: ./json/rec/rec_r32_gaspin_bilstm_att/ save_epoch_step: 3 # evaluation is run every 5000 iterations after the 4000th iteration eval_batch_step: [0, 2000] @@ -18,7 +18,7 @@ Global: max_text_length: 25 infer_mode: False use_space_char: False - save_res_path: ./output/rec/predicts_r32_gaspin_bilstm_att.txt + save_res_path: ./json/rec/predicts_r32_gaspin_bilstm_att.txt Optimizer: diff --git a/test_tipc/configs/rec_r34_vd_none_bilstm_ctc_v2_0/rec_icdar15_train.yml b/test_tipc/configs/rec_r34_vd_none_bilstm_ctc_v2_0/rec_icdar15_train.yml index 3e9ea48..7a8b547 100644 --- a/test_tipc/configs/rec_r34_vd_none_bilstm_ctc_v2_0/rec_icdar15_train.yml +++ b/test_tipc/configs/rec_r34_vd_none_bilstm_ctc_v2_0/rec_icdar15_train.yml @@ -3,7 +3,7 @@ Global: epoch_num: 72 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec/r34_vd_none_bilstm_ctc/ + save_model_dir: ./json/rec/r34_vd_none_bilstm_ctc/ save_epoch_step: 3 # evaluation is run every 2000 iterations eval_batch_step: [0, 2000] @@ -18,7 +18,7 @@ Global: max_text_length: 25 infer_mode: False use_space_char: False - save_res_path: ./output/rec/predicts_r34_vd_none_bilstm_ctc.txt + save_res_path: ./json/rec/predicts_r34_vd_none_bilstm_ctc.txt Optimizer: name: Adam diff --git a/test_tipc/configs/rec_r34_vd_none_none_ctc_v2_0/rec_icdar15_train.yml b/test_tipc/configs/rec_r34_vd_none_none_ctc_v2_0/rec_icdar15_train.yml index ce15e27..28f3192 100644 --- a/test_tipc/configs/rec_r34_vd_none_none_ctc_v2_0/rec_icdar15_train.yml +++ b/test_tipc/configs/rec_r34_vd_none_none_ctc_v2_0/rec_icdar15_train.yml @@ -3,7 +3,7 @@ Global: epoch_num: 72 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec/r34_vd_none_none_ctc/ + save_model_dir: ./json/rec/r34_vd_none_none_ctc/ save_epoch_step: 3 # evaluation is run every 2000 iterations eval_batch_step: [0, 2000] @@ -18,7 +18,7 @@ Global: max_text_length: 25 infer_mode: False use_space_char: False - save_res_path: ./output/rec/predicts_r34_vd_none_none_ctc.txt + save_res_path: ./json/rec/predicts_r34_vd_none_none_ctc.txt Optimizer: name: Adam diff --git a/test_tipc/configs/rec_r34_vd_tps_bilstm_att_v2_0/rec_r34_vd_tps_bilstm_att.yml b/test_tipc/configs/rec_r34_vd_tps_bilstm_att_v2_0/rec_r34_vd_tps_bilstm_att.yml index 5dd797b..befb4c6 100644 --- a/test_tipc/configs/rec_r34_vd_tps_bilstm_att_v2_0/rec_r34_vd_tps_bilstm_att.yml +++ b/test_tipc/configs/rec_r34_vd_tps_bilstm_att_v2_0/rec_r34_vd_tps_bilstm_att.yml @@ -3,7 +3,7 @@ Global: epoch_num: 400 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec/b3_rare_r34_none_gru/ + save_model_dir: ./json/rec/b3_rare_r34_none_gru/ save_epoch_step: 3 # evaluation is run every 5000 iterations after the 4000th iteration eval_batch_step: [0, 2000] @@ -18,7 +18,7 @@ Global: max_text_length: 25 infer_mode: False use_space_char: False - save_res_path: ./output/rec/predicts_b3_rare_r34_none_gru.txt + save_res_path: ./json/rec/predicts_b3_rare_r34_none_gru.txt Optimizer: diff --git a/test_tipc/configs/rec_r34_vd_tps_bilstm_ctc_v2_0/rec_icdar15_train.yml b/test_tipc/configs/rec_r34_vd_tps_bilstm_ctc_v2_0/rec_icdar15_train.yml index 2dcba81..ee9f6ab 100644 --- a/test_tipc/configs/rec_r34_vd_tps_bilstm_ctc_v2_0/rec_icdar15_train.yml +++ b/test_tipc/configs/rec_r34_vd_tps_bilstm_ctc_v2_0/rec_icdar15_train.yml @@ -3,7 +3,7 @@ Global: epoch_num: 72 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec/r34_vd_tps_bilstm_ctc/ + save_model_dir: ./json/rec/r34_vd_tps_bilstm_ctc/ save_epoch_step: 3 # evaluation is run every 2000 iterations eval_batch_step: [0, 2000] @@ -18,7 +18,7 @@ Global: max_text_length: 25 infer_mode: False use_space_char: False - save_res_path: ./output/rec/predicts_r34_vd_tps_bilstm_ctc.txt + save_res_path: ./json/rec/predicts_r34_vd_tps_bilstm_ctc.txt Optimizer: name: Adam diff --git a/test_tipc/configs/rec_r45_abinet/rec_r45_abinet.yml b/test_tipc/configs/rec_r45_abinet/rec_r45_abinet.yml index 5b5890e..aedccb8 100644 --- a/test_tipc/configs/rec_r45_abinet/rec_r45_abinet.yml +++ b/test_tipc/configs/rec_r45_abinet/rec_r45_abinet.yml @@ -3,7 +3,7 @@ Global: epoch_num: 10 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec/r45_abinet/ + save_model_dir: ./json/rec/r45_abinet/ save_epoch_step: 1 # evaluation is run every 2000 iterations eval_batch_step: [0, 2000] @@ -19,7 +19,7 @@ Global: max_text_length: 25 infer_mode: False use_space_char: False - save_res_path: ./output/rec/predicts_abinet.txt + save_res_path: ./json/rec/predicts_abinet.txt Optimizer: name: Adam diff --git a/test_tipc/configs/rec_r45_visionlan/rec_r45_visionlan.yml b/test_tipc/configs/rec_r45_visionlan/rec_r45_visionlan.yml index 860e4f5..44e305a 100644 --- a/test_tipc/configs/rec_r45_visionlan/rec_r45_visionlan.yml +++ b/test_tipc/configs/rec_r45_visionlan/rec_r45_visionlan.yml @@ -3,7 +3,7 @@ Global: epoch_num: 8 log_smooth_window: 200 print_batch_step: 200 - save_model_dir: ./output/rec/r45_visionlan + save_model_dir: ./json/rec/r45_visionlan save_epoch_step: 1 # evaluation is run every 2000 iterations eval_batch_step: [0, 2000] @@ -19,7 +19,7 @@ Global: training_step: &training_step LA infer_mode: False use_space_char: False - save_res_path: ./output/rec/predicts_visionlan.txt + save_res_path: ./json/rec/predicts_visionlan.txt Optimizer: name: Adam diff --git a/test_tipc/configs/rec_r50_fpn_vd_none_srn/rec_r50_fpn_srn.yml b/test_tipc/configs/rec_r50_fpn_vd_none_srn/rec_r50_fpn_srn.yml index 41e5252..8591cd2 100644 --- a/test_tipc/configs/rec_r50_fpn_vd_none_srn/rec_r50_fpn_srn.yml +++ b/test_tipc/configs/rec_r50_fpn_vd_none_srn/rec_r50_fpn_srn.yml @@ -3,7 +3,7 @@ Global: epoch_num: 72 log_smooth_window: 20 print_batch_step: 5 - save_model_dir: ./output/rec/srn_new + save_model_dir: ./json/rec/srn_new save_epoch_step: 3 # evaluation is run every 5000 iterations after the 4000th iteration eval_batch_step: [0, 5000] @@ -19,7 +19,7 @@ Global: num_heads: 8 infer_mode: False use_space_char: False - save_res_path: ./output/rec/predicts_srn.txt + save_res_path: ./json/rec/predicts_srn.txt Optimizer: diff --git a/test_tipc/configs/rec_resnet_rfl/rec_resnet_rfl.yml b/test_tipc/configs/rec_resnet_rfl/rec_resnet_rfl.yml index b4f18f5..71470fa 100644 --- a/test_tipc/configs/rec_resnet_rfl/rec_resnet_rfl.yml +++ b/test_tipc/configs/rec_resnet_rfl/rec_resnet_rfl.yml @@ -3,7 +3,7 @@ Global: epoch_num: 6 log_smooth_window: 20 print_batch_step: 50 - save_model_dir: ./output/rec/rec_resnet_rfl/ + save_model_dir: ./json/rec/rec_resnet_rfl/ save_epoch_step: 1 # evaluation is run every 5000 iterations after the 4000th iteration eval_batch_step: [0, 5000] @@ -18,7 +18,7 @@ Global: max_text_length: 25 infer_mode: False use_space_char: False - save_res_path: ./output/rec/rec_resnet_rfl.txt + save_res_path: ./json/rec/rec_resnet_rfl.txt Optimizer: diff --git a/test_tipc/configs/rec_svtrnet/rec_svtrnet.yml b/test_tipc/configs/rec_svtrnet/rec_svtrnet.yml index 6e22bc7..b4a315f 100644 --- a/test_tipc/configs/rec_svtrnet/rec_svtrnet.yml +++ b/test_tipc/configs/rec_svtrnet/rec_svtrnet.yml @@ -3,7 +3,7 @@ Global: epoch_num: 20 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec/svtr/ + save_model_dir: ./json/rec/svtr/ save_epoch_step: 1 # evaluation is run every 2000 iterations after the 0th iteration eval_batch_step: [0, 2000] @@ -19,7 +19,7 @@ Global: max_text_length: 25 infer_mode: False use_space_char: False - save_res_path: ./output/rec/predicts_svtr_tiny.txt + save_res_path: ./json/rec/predicts_svtr_tiny.txt d2s_train_image_shape: [3, 64, 256] diff --git a/test_tipc/configs/rec_vitstr_none_ce/rec_vitstr_none_ce.yml b/test_tipc/configs/rec_vitstr_none_ce/rec_vitstr_none_ce.yml index a0aed48..f630077 100644 --- a/test_tipc/configs/rec_vitstr_none_ce/rec_vitstr_none_ce.yml +++ b/test_tipc/configs/rec_vitstr_none_ce/rec_vitstr_none_ce.yml @@ -3,7 +3,7 @@ Global: epoch_num: 20 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/rec/vitstr_none_ce/ + save_model_dir: ./json/rec/vitstr_none_ce/ save_epoch_step: 1 # evaluation is run every 2000 iterations after the 0th iteration# eval_batch_step: [0, 2000] @@ -18,7 +18,7 @@ Global: max_text_length: 25 infer_mode: False use_space_char: False - save_res_path: ./output/rec/predicts_vitstr.txt + save_res_path: ./json/rec/predicts_vitstr.txt Optimizer: diff --git a/test_tipc/configs/sr_telescope/sr_telescope.yml b/test_tipc/configs/sr_telescope/sr_telescope.yml index 774c19d..f88749f 100644 --- a/test_tipc/configs/sr_telescope/sr_telescope.yml +++ b/test_tipc/configs/sr_telescope/sr_telescope.yml @@ -3,14 +3,14 @@ Global: epoch_num: 2 log_smooth_window: 20 print_batch_step: 10 - save_model_dir: ./output/sr/sr_telescope/ + save_model_dir: ./json/sr/sr_telescope/ save_epoch_step: 3 # evaluation is run every 2000 iterations eval_batch_step: [0, 1000] cal_metric_during_train: False pretrained_model: checkpoints: - save_inference_dir: ./output/sr/sr_telescope/infer + save_inference_dir: ./json/sr/sr_telescope/infer use_visualdl: False infer_img: doc/imgs_words_en/word_52.png # for data or label process @@ -18,7 +18,7 @@ Global: max_text_length: 100 infer_mode: False use_space_char: False - save_res_path: ./output/sr/predicts_telescope.txt + save_res_path: ./json/sr/predicts_telescope.txt Optimizer: name: Adam diff --git a/test_tipc/configs/table_master/table_master.yml b/test_tipc/configs/table_master/table_master.yml index cc96fbc..cb12626 100644 --- a/test_tipc/configs/table_master/table_master.yml +++ b/test_tipc/configs/table_master/table_master.yml @@ -3,16 +3,16 @@ Global: epoch_num: 17 log_smooth_window: 20 print_batch_step: 100 - save_model_dir: ./output/table_master/ + save_model_dir: ./json/table_master/ save_epoch_step: 17 eval_batch_step: [0, 6259] cal_metric_during_train: false pretrained_model: null checkpoints: - save_inference_dir: output/table_master/infer + save_inference_dir: json/table_master/infer use_visualdl: false infer_img: ppstructure/docs/table/table.jpg - save_res_path: ./output/table_master + save_res_path: ./json/table_master character_dict_path: ppocr/utils/dict/table_master_structure_dict.txt infer_mode: false max_text_length: 500 diff --git a/test_tipc/docs/jeston_test_train_inference_python.md b/test_tipc/docs/jeston_test_train_inference_python.md index 23d95cd..1d3a95a 100644 --- a/test_tipc/docs/jeston_test_train_inference_python.md +++ b/test_tipc/docs/jeston_test_train_inference_python.md @@ -81,7 +81,7 @@ Run failed with command - python tools/infer/predict_det.py --use_gpu=True --use #### 使用方式 运行命令: ```shell -python test_tipc/compare_results.py --gt_file=./test_tipc/results/python_*.txt --log_file=./test_tipc/output/python_*.log --atol=1e-3 --rtol=1e-3 +python test_tipc/compare_results.py --gt_file=./test_tipc/results/python_*.txt --log_file=./test_tipc/json/python_*.log --atol=1e-3 --rtol=1e-3 ``` 参数介绍: diff --git a/test_tipc/docs/mac_test_train_inference_python.md b/test_tipc/docs/mac_test_train_inference_python.md index f3ece93..51103b8 100644 --- a/test_tipc/docs/mac_test_train_inference_python.md +++ b/test_tipc/docs/mac_test_train_inference_python.md @@ -111,7 +111,7 @@ Run failed with command - python3.7 tools/export_model.py -c tests/configs/det_m #### 使用方式 运行命令: ```shell -python test_tipc/compare_results.py --gt_file=./test_tipc/results/python_*.txt --log_file=./test_tipc/output/python_*.log --atol=1e-3 --rtol=1e-3 +python test_tipc/compare_results.py --gt_file=./test_tipc/results/python_*.txt --log_file=./test_tipc/json/python_*.log --atol=1e-3 --rtol=1e-3 ``` 参数介绍: diff --git a/test_tipc/docs/test_inference_cpp.md b/test_tipc/docs/test_inference_cpp.md index 5e9e852..f3b3b3d 100644 --- a/test_tipc/docs/test_inference_cpp.md +++ b/test_tipc/docs/test_inference_cpp.md @@ -31,7 +31,7 @@ bash test_tipc/test_inference_cpp.sh test_tipc/configs/ch_PP-OCRv2_rec/model_lin 运行预测指令后,在`test_tipc/output`文件夹下自动会保存运行日志,包括以下文件: ```shell -test_tipc/output/ +test_tipc/json/ |- results_cpp.log # 运行指令状态的日志 |- cpp_infer_cpu_usemkldnn_False_threads_6_precision_fp32_batchsize_6.log # CPU上不开启Mkldnn,线程数设置为6,测试batch_size=6条件下的预测运行日志 |- cpp_infer_gpu_usetrt_False_precision_fp32_batchsize_6.log # GPU上不开启TensorRT,测试batch_size=6的fp32精度预测日志 @@ -63,7 +63,7 @@ Run failed with command - ch_PP-OCRv2_rec - ./deploy/cpp_infer/build/ppocr --rec #### 使用方式 运行命令: ```shell -python3.7 test_tipc/compare_results.py --gt_file=./test_tipc/results/cpp_*.txt --log_file=./test_tipc/output/cpp_*.log --atol=1e-3 --rtol=1e-3 +python3.7 test_tipc/compare_results.py --gt_file=./test_tipc/results/cpp_*.txt --log_file=./test_tipc/json/cpp_*.log --atol=1e-3 --rtol=1e-3 ``` 参数介绍: diff --git a/test_tipc/docs/test_train_fleet_inference_python.md b/test_tipc/docs/test_train_fleet_inference_python.md index 15f32c9..3a7ac11 100644 --- a/test_tipc/docs/test_train_fleet_inference_python.md +++ b/test_tipc/docs/test_train_fleet_inference_python.md @@ -61,9 +61,9 @@ bash test_tipc/test_train_inference_python.sh test_tipc/configs/ch_PP-OCRv3_rec 输出结果如下,表示命令运行成功。 ```bash - Run successfully with command - ch_PP-OCRv3_rec - python3.7 -m paddle.distributed.launch --ips=192.168.0.1,192.168.0.2 --gpus=0,1 tools/train.py -c test_tipc/configs/ch_PP-OCRv3_rec/ch_PP-OCRv3_rec_distillation.yml -o Global.use_gpu=True Global.save_model_dir=./test_tipc/output/ch_PP-OCRv3_rec/lite_train_lite_infer/norm_train_gpus_0,1_autocast_fp32_nodes_2 Global.epoch_num=3 Global.auto_cast=fp32 Train.loader.batch_size_per_card=16 ! + Run successfully with command - ch_PP-OCRv3_rec - python3.7 -m paddle.distributed.launch --ips=192.168.0.1,192.168.0.2 --gpus=0,1 tools/train.py -c test_tipc/configs/ch_PP-OCRv3_rec/ch_PP-OCRv3_rec_distillation.yml -o Global.use_gpu=True Global.save_model_dir=./test_tipc/json/ch_PP-OCRv3_rec/lite_train_lite_infer/norm_train_gpus_0,1_autocast_fp32_nodes_2 Global.epoch_num=3 Global.auto_cast=fp32 Train.loader.batch_size_per_card=16 ! ...... - Run successfully with command - ch_PP-OCRv3_rec - python3.7 tools/infer/predict_rec.py --rec_image_shape="3,48,320" --use_gpu=False --enable_mkldnn=False --cpu_threads=6 --rec_model_dir=./test_tipc/output/ch_PP-OCRv3_rec/lite_train_lite_infer/norm_train_gpus_0,1_autocast_fp32_nodes_2/Student --rec_batch_num=1 --image_dir=./inference/rec_inference --benchmark=True --precision=fp32 > ./test_tipc/output/ch_PP-OCRv3_rec/lite_train_lite_infer/python_infer_cpu_usemkldnn_False_threads_6_precision_fp32_batchsize_1.log 2>&1 ! + Run successfully with command - ch_PP-OCRv3_rec - python3.7 tools/infer/predict_rec.py --rec_image_shape="3,48,320" --use_gpu=False --enable_mkldnn=False --cpu_threads=6 --rec_model_dir=./test_tipc/json/ch_PP-OCRv3_rec/lite_train_lite_infer/norm_train_gpus_0,1_autocast_fp32_nodes_2/Student --rec_batch_num=1 --image_dir=./inference/rec_inference --benchmark=True --precision=fp32 > ./test_tipc/json/ch_PP-OCRv3_rec/lite_train_lite_infer/python_infer_cpu_usemkldnn_False_threads_6_precision_fp32_batchsize_1.log 2>&1 ! ``` 在开启benchmark参数时,可以得到测试的详细数据,包含运行环境信息(系统版本、CUDA版本、CUDNN版本、驱动版本),Paddle版本信息,参数设置信息(运行设备、线程数、是否开启内存优化等),模型信息(模型名称、精度),数据信息(batchsize、是否为动态shape等),性能信息(CPU,GPU的占用、运行耗时、预处理耗时、推理耗时、后处理耗时),内容如下所示: diff --git a/test_tipc/docs/test_train_inference_python.md b/test_tipc/docs/test_train_inference_python.md index 4578057..eeee020 100644 --- a/test_tipc/docs/test_train_inference_python.md +++ b/test_tipc/docs/test_train_inference_python.md @@ -141,7 +141,7 @@ bash test_tipc/test_train_inference_python.sh ./test_tipc/configs/ch_PP-OCRv2_de #### 使用方式 运行命令: ```shell -python3.7 test_tipc/compare_results.py --gt_file=./test_tipc/results/python_*.txt --log_file=./test_tipc/output/python_*.log --atol=1e-3 --rtol=1e-3 +python3.7 test_tipc/compare_results.py --gt_file=./test_tipc/results/python_*.txt --log_file=./test_tipc/json/python_*.log --atol=1e-3 --rtol=1e-3 ``` 参数介绍: diff --git a/test_tipc/docs/win_test_train_inference_python.md b/test_tipc/docs/win_test_train_inference_python.md index 5f80df1..0ebdffe 100644 --- a/test_tipc/docs/win_test_train_inference_python.md +++ b/test_tipc/docs/win_test_train_inference_python.md @@ -114,7 +114,7 @@ Run failed with command - python3.7 tools/export_model.py -c tests/configs/det_m #### 使用方式 运行命令: ```shell -python test_tipc/compare_results.py --gt_file=./test_tipc/results/python_*.txt --log_file=./test_tipc/output/python_*.log --atol=1e-3 --rtol=1e-3 +python test_tipc/compare_results.py --gt_file=./test_tipc/results/python_*.txt --log_file=./test_tipc/json/python_*.log --atol=1e-3 --rtol=1e-3 ``` 参数介绍: diff --git a/test_tipc/supplementary/metric.py b/test_tipc/supplementary/metric.py index 687fade..22cc5e1 100644 --- a/test_tipc/supplementary/metric.py +++ b/test_tipc/supplementary/metric.py @@ -16,7 +16,7 @@ def create_metric( Create measures of model accuracy, such as top1 and top5 Args: - out(variable): model output variable + out(variable): model json variable feeds(dict): dict of model input variables(included label) topk(int): usually top5 classes_num(int): num of classes diff --git a/test_tipc/supplementary/mv3_distill.yml b/test_tipc/supplementary/mv3_distill.yml index 57b8130..5be8ff2 100644 --- a/test_tipc/supplementary/mv3_distill.yml +++ b/test_tipc/supplementary/mv3_distill.yml @@ -3,7 +3,7 @@ class_dim: 100 total_images: 50000 epochs: 1000 topk: 5 -save_model_dir: ./output/ +save_model_dir: ./json/ use_gpu: True model_type: cls_distill diff --git a/test_tipc/supplementary/mv3_large_x0_5.yml b/test_tipc/supplementary/mv3_large_x0_5.yml index fd7d308..1337f54 100644 --- a/test_tipc/supplementary/mv3_large_x0_5.yml +++ b/test_tipc/supplementary/mv3_large_x0_5.yml @@ -3,13 +3,13 @@ class_dim: 100 total_images: 50000 epoch: 1000 topk: 5 -save_model_dir: ./output/ +save_model_dir: ./json/ use_gpu: True model_type: cls use_custom_relu: false pretrained_model: checkpoints: -save_model_dir: ./output/cls/ +save_model_dir: ./json/cls/ # slim quant_train: false diff --git a/tools/infer/predict_system_1.py b/tools/infer/predict_system_1.py index dbdd0d1..4175b05 100644 --- a/tools/infer/predict_system_1.py +++ b/tools/infer/predict_system_1.py @@ -1,9 +1,18 @@ import os import sys import subprocess + +__dir__ = os.path.dirname(os.path.abspath(__file__)) +sys.path.append(__dir__) +sys.path.insert(0, os.path.abspath(os.path.join(__dir__, "../.."))) + +os.environ["FLAGS_allocator_strategy"] = "auto_growth" + import cv2 import copy import numpy as np +import json +import time from PIL import Image import tools.infer.utility as utility import tools.infer.predict_rec as predict_rec @@ -11,13 +20,13 @@ import tools.infer.predict_det as predict_det import tools.infer.predict_cls as predict_cls from ppocr.utils.utility import get_image_file_list, check_and_read from tools.infer.utility import ( + draw_ocr_box_txt, get_rotate_crop_image, get_minarea_rect_crop, slice_generator, merge_fragmented, ) - class TextSystem(object): def __init__(self, args): self.text_detector = predict_det.TextDetector(args) @@ -36,16 +45,19 @@ class TextSystem(object): for bno in range(bbox_num): cv2.imwrite( os.path.join( - output_dir, f"mg_crop_{bno + self.crop_image_res_index}.jpg" + output_dir, f"mg_crop_{bno+self.crop_image_res_index}.jpg" ), img_crop_list[bno], ) self.crop_image_res_index += bbox_num def __call__(self, img, cls=True, slice={}): + time_dict = {"det": 0, "rec": 0, "cls": 0, "all": 0} + if img is None: - return None, None, {} + return None, None, time_dict + start = time.time() ori_im = img.copy() if slice: slice_gen = slice_generator( @@ -73,9 +85,12 @@ class TextSystem(object): else: dt_boxes, elapse = self.text_detector(img) - if dt_boxes is None: - return None, None, {} + time_dict["det"] = elapse + if dt_boxes is None: + end = time.time() + time_dict["all"] = end - start + return None, None, time_dict img_crop_list = [] dt_boxes = sorted_boxes(dt_boxes) @@ -89,17 +104,21 @@ class TextSystem(object): img_crop_list.append(img_crop) if self.use_angle_cls and cls: img_crop_list, angle_list, elapse = self.text_classifier(img_crop_list) - if len(img_crop_list) > 1000: - pass - + time_dict["cls"] = elapse rec_res, elapse = self.text_recognizer(img_crop_list) + time_dict["rec"] = elapse + + if self.args.save_crop_res: + self.draw_crop_rec_res(self.args.crop_res_save_dir, img_crop_list, rec_res) filter_boxes, filter_rec_res = [], [] for box, rec_result in zip(dt_boxes, rec_res): text, score = rec_result[0], rec_result[1] if score >= self.drop_score: filter_boxes.append(box) filter_rec_res.append(rec_result) - return filter_boxes, filter_rec_res, {} + end = time.time() + time_dict["all"] = end - start + return filter_boxes, filter_rec_res, time_dict def sorted_boxes(dt_boxes): @@ -110,7 +129,7 @@ def sorted_boxes(dt_boxes): for i in range(num_boxes - 1): for j in range(i, -1, -1): if abs(_boxes[j + 1][0][1] - _boxes[j][0][1]) < 10 and ( - _boxes[j + 1][0][0] < _boxes[j][0][0] + _boxes[j + 1][0][0] < _boxes[j][0][0] ): tmp = _boxes[j] _boxes[j] = _boxes[j + 1] @@ -122,15 +141,25 @@ def sorted_boxes(dt_boxes): def main(args): image_file_list = get_image_file_list(args.image_dir) - image_file_list = image_file_list[args.process_id:: args.total_process_num] + image_file_list = image_file_list[args.process_id :: args.total_process_num] text_sys = TextSystem(args) - - # Warm-up (optional) + is_visualize = True + font_path = args.vis_font_path + drop_score = args.drop_score + draw_img_save_dir = args.draw_img_save_dir + os.makedirs(draw_img_save_dir, exist_ok=True) + save_results = [] + + # warm up 10 times if args.warmup: img = np.random.uniform(0, 255, [640, 640, 3]).astype(np.uint8) for i in range(10): - text_sys(img) + res = text_sys(img) + total_time = 0 + cpu_mem, gpu_mem, gpu_util = 0, 0, 0 + _st = time.time() + count = 0 for idx, image_file in enumerate(image_file_list): img, flag_gif, flag_pdf = check_and_read(image_file) if not flag_gif and not flag_pdf: @@ -144,13 +173,67 @@ def main(args): if page_num > len(img) or page_num == 0: page_num = len(img) imgs = img[:page_num] - for index, img in enumerate(imgs): - dt_boxes, rec_res, _ = text_sys(img) - - # Output the recognized text - for text, _ in rec_res: - print(f"{text}") + starttime = time.time() + dt_boxes, rec_res, time_dict = text_sys(img) + elapse = time.time() - starttime + total_time += elapse + for text, score in rec_res: + print(text) + + res = [ + { + "transcription": rec_res[i][0], + "points": np.array(dt_boxes[i]).astype(np.int32).tolist(), + } + for i in range(len(dt_boxes)) + ] + if len(imgs) > 1: + save_pred = ( + os.path.basename(image_file) + + "_" + + str(index) + + "\t" + + json.dumps(res, ensure_ascii=False) + + "\n" + ) + else: + save_pred = ( + os.path.basename(image_file) + + "\t" + + json.dumps(res, ensure_ascii=False) + + "\n" + ) + save_results.append(save_pred) + + if is_visualize: + image = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)) + boxes = dt_boxes + txts = [rec_res[i][0] for i in range(len(rec_res))] + scores = [rec_res[i][1] for i in range(len(rec_res))] + + draw_img = draw_ocr_box_txt( + image, + boxes, + txts, + scores, + drop_score=drop_score, + font_path=font_path, + ) + if flag_gif: + save_file = image_file[:-3] + "png" + elif flag_pdf: + save_file = image_file.replace(".pdf", "_" + str(index) + ".png") + else: + save_file = image_file + cv2.imwrite( + os.path.join(draw_img_save_dir, os.path.basename(save_file)), + draw_img[:, :, ::-1], + ) + + if args.benchmark: + text_sys.text_detector.autolog.report() + text_sys.text_recognizer.autolog.report() if __name__ == "__main__": @@ -160,9 +243,9 @@ if __name__ == "__main__": total_process_num = args.total_process_num for process_id in range(total_process_num): cmd = ( - [sys.executable, "-u"] - + sys.argv - + ["--process_id={}".format(process_id), "--use_mp={}".format(False)] + [sys.executable, "-u"] + + sys.argv + + ["--process_id={}".format(process_id), "--use_mp={}".format(False)] ) p = subprocess.Popen(cmd, stdout=sys.stdout, stderr=sys.stdout) p_list.append(p) diff --git a/tools/infer/utility.py b/tools/infer/utility.py index 46c8028..409c7d1 100644 --- a/tools/infer/utility.py +++ b/tools/infer/utility.py @@ -135,7 +135,7 @@ def init_args(): # parser.add_argument("--draw_img_save_dir", type=str, default="./inference_results") parser.add_argument("--save_crop_res", type=str2bool, default=False) - parser.add_argument("--crop_res_save_dir", type=str, default="./output") + parser.add_argument("--crop_res_save_dir", type=str, default="./json") # multi-process parser.add_argument("--use_mp", type=str2bool, default=False) diff --git a/tools/infer_kie.py b/tools/infer_kie.py index f3efaf9..1530570 100644 --- a/tools/infer_kie.py +++ b/tools/infer_kie.py @@ -99,7 +99,7 @@ def draw_kie_result(batch, node, idx_to_cls, count): def write_kie_result(fout, node, data): """ - Write infer result to output file, sorted by the predict label of each line. + Write infer result to json file, sorted by the predict label of each line. The format keeps the same as the input with additional score attribute. """ import json diff --git a/tools/infer_rec.py b/tools/infer_rec.py index a3e8aef..efb1248 100644 --- a/tools/infer_rec.py +++ b/tools/infer_rec.py @@ -120,7 +120,7 @@ def main(): ops = create_operators(transforms, global_config) save_res_path = config["Global"].get( - "save_res_path", "./output/rec/predicts_rec.txt" + "save_res_path", "./json/rec/predicts_rec.txt" ) if not os.path.exists(os.path.dirname(save_res_path)): os.makedirs(os.path.dirname(save_res_path)) diff --git a/tools/test_hubserving.py b/tools/test_hubserving.py index 5480107..859be84 100644 --- a/tools/test_hubserving.py +++ b/tools/test_hubserving.py @@ -152,7 +152,7 @@ def parse_args(): parser.add_argument("--server_url", type=str, required=True) parser.add_argument("--image_dir", type=str, required=True) parser.add_argument("--visualize", type=str2bool, default=False) - parser.add_argument("--output", type=str, default="./hubserving_result") + parser.add_argument("--json", type=str, default="./hubserving_result") args = parser.parse_args() return args diff --git a/tst.py b/tst.py deleted file mode 100644 index c7a8e01..0000000 --- a/tst.py +++ /dev/null @@ -1,31 +0,0 @@ -import requests -import base64 -import uuid - -# 函数用于读取图片并将其转换为 Base64 编码 -def image_to_base64(image_path): - with open(image_path, "rb") as image_file: - return base64.b64encode(image_file.read()).decode('utf-8') - -# FastAPI 服务的 URL -url = "http://192.168.10.137:8866/ocr" -# url = "http://127.0.0.1:8000/ocr" - -# 准备测试数据 -pictures = [ - { - "pic_id": uuid.uuid4().int, # 生成整数类型的 pic_id - "pic": image_to_base64(r"E:\Project\PaddleOCR\doc\imgs\10.08\Image_00032.jpg") - }, - { - "pic_id": uuid.uuid4().int, # 生成另一个唯一的整数类型 pic_id - "pic": image_to_base64(r"E:\Project\PaddleOCR\doc\imgs\10.08\Image_00032.jpg") - } -] - -# 发送 POST 请求 -response = requests.post(url, json=pictures) - -# 打印响应结果 -print("Status Code:", response.status_code) -print("Response JSON:", response.json())
alleadersh { }) }) -!function (e, t) { "object" == typeof exports && "object" == typeof module ? module.exports = t() : "function" == typeof define && define.amd ? define([], t) : "object" == typeof exports ? exports.katex = t() : e.katex = t() }("undefined" != typeof self ? self : this, (function () { return function () { "use strict"; var e = { d: function (t, r) { for (var n in r) e.o(r, n) && !e.o(t, n) && Object.defineProperty(t, n, { enumerable: !0, get: r[n] }) }, o: function (e, t) { return Object.prototype.hasOwnProperty.call(e, t) } }, t = {}; e.d(t, { default: function () { return Yn } }); class r { constructor(e, t) { this.name = void 0, this.position = void 0, this.length = void 0, this.rawMessage = void 0; let n, o, s = "KaTeX parse error: " + e; const i = t && t.loc; if (i && i.start <= i.end) { const e = i.lexer.input; n = i.start, o = i.end, n === e.length ? s += " at end of input: " : s += " at position " + (n + 1) + ": "; const t = e.slice(n, o).replace(/[^]/g, "$&\u0332"); let r, a; r = n > 15 ? "\u2026" + e.slice(n - 15, n) : e.slice(0, n), a = o + 15 < e.length ? e.slice(o, o + 15) + "\u2026" : e.slice(o), s += r + t + a } const a = new Error(s); return a.name = "ParseError", a.__proto__ = r.prototype, a.position = n, null != n && null != o && (a.length = o - n), a.rawMessage = e, a } } r.prototype.__proto__ = Error.prototype; var n = r; const o = /([A-Z])/g, s = { "&": "&", ">": ">", "<": "<", '"': """, "'": "'" }, i = /[&><"']/g; const a = function (e) { return "ordgroup" === e.type || "color" === e.type ? 1 === e.body.length ? a(e.body[0]) : e : "font" === e.type ? a(e.body) : e }; var l = { contains: function (e, t) { return -1 !== e.indexOf(t) }, deflt: function (e, t) { return void 0 === e ? t : e }, escape: function (e) { return String(e).replace(i, (e => s[e])) }, hyphenate: function (e) { return e.replace(o, "-$1").toLowerCase() }, getBaseElem: a, isCharacterBox: function (e) { const t = a(e); return "mathord" === t.type || "textord" === t.type || "atom" === t.type }, protocolFromUrl: function (e) { const t = /^[\x00-\x20]*([^\\/#?]*?)(:|�*58|�*3a|&colon)/i.exec(e); return t ? ":" !== t[2] ? null : /^[a-zA-Z][a-zA-Z0-9+\-.]*$/.test(t[1]) ? t[1].toLowerCase() : null : "_relative" } }; const h = { displayMode: { type: "boolean", description: "Render math in display mode, which puts the math in display style (so \\int and \\sum are large, for example), and centers the math on the page on its own line.", cli: "-d, --display-mode" }, output: { type: { enum: ["htmlAndMathml", "html", "mathml"] }, description: "Determines the markup language of the output.", cli: "-F, --format " }, leqno: { type: "boolean", description: "Render display math in leqno style (left-justified tags)." }, fleqn: { type: "boolean", description: "Render display math flush left." }, throwOnError: { type: "boolean", default: !0, cli: "-t, --no-throw-on-error", cliDescription: "Render errors (in the color given by --error-color) instead of throwing a ParseError exception when encountering an error." }, errorColor: { type: "string", default: "#cc0000", cli: "-c, --error-color ", cliDescription: "A color string given in the format 'rgb' or 'rrggbb' (no #). This option determines the color of errors rendered by the -t option.", cliProcessor: e => "#" + e }, macros: { type: "object", cli: "-m, --macro ", cliDescription: "Define custom macro of the form '\\foo:expansion' (use multiple -m arguments for multiple macros).", cliDefault: [], cliProcessor: (e, t) => (t.push(e), t) }, minRuleThickness: { type: "number", description: "Specifies a minimum thickness, in ems, for fraction lines, `\\sqrt` top lines, `{array}` vertical lines, `\\hline`, `\\hdashline`, `\\underline`, `\\overline`, and the borders of `\\fbox`, `\\boxed`, and `\\fcolorbox`.", processor: e => Math.max(0, e), cli: "--min-rule-thickness ", cliProcessor: parseFloat }, colorIsTextColor: { type: "boolean", description: "Makes \\color behave like LaTeX's 2-argument \\textcolor, instead of LaTeX's one-argument \\color mode change.", cli: "-b, --color-is-text-color" }, strict: { type: [{ enum: ["warn", "ignore", "error"] }, "boolean", "function"], description: "Turn on strict / LaTeX faithfulness mode, which throws an error if the input uses features that are not supported by LaTeX.", cli: "-S, --strict", cliDefault: !1 }, trust: { type: ["boolean", "function"], description: "Trust the input, enabling all HTML features such as \\url.", cli: "-T, --trust" }, maxSize: { type: "number", default: 1 / 0, description: "If non-zero, all user-specified sizes, e.g. in \\rule{500em}{500em}, will be capped to maxSize ems. Otherwise, elements and spaces can be arbitrarily large", processor: e => Math.max(0, e), cli: "-s, --max-size ", cliProcessor: parseInt }, maxExpand: { type: "number", default: 1e3, description: "Limit the number of macro expansions to the specified number, to prevent e.g. infinite macro loops. If set to Infinity, the macro expander will try to fully expand as in LaTeX.", processor: e => Math.max(0, e), cli: "-e, --max-expand ", cliProcessor: e => "Infinity" === e ? 1 / 0 : parseInt(e) }, globalGroup: { type: "boolean", cli: !1 } }; function c(e) { if (e.default) return e.default; const t = e.type, r = Array.isArray(t) ? t[0] : t; if ("string" != typeof r) return r.enum[0]; switch (r) { case "boolean": return !1; case "string": return ""; case "number": return 0; case "object": return {} } } class m { constructor(e) { this.displayMode = void 0, this.output = void 0, this.leqno = void 0, this.fleqn = void 0, this.throwOnError = void 0, this.errorColor = void 0, this.macros = void 0, this.minRuleThickness = void 0, this.colorIsTextColor = void 0, this.strict = void 0, this.trust = void 0, this.maxSize = void 0, this.maxExpand = void 0, this.globalGroup = void 0, e = e || {}; for (const t in h) if (h.hasOwnProperty(t)) { const r = h[t]; this[t] = void 0 !== e[t] ? r.processor ? r.processor(e[t]) : e[t] : c(r) } } reportNonstrict(e, t, r) { let o = this.strict; if ("function" == typeof o && (o = o(e, t, r)), o && "ignore" !== o) { if (!0 === o || "error" === o) throw new n("LaTeX-incompatible input and strict mode is set to 'error': " + t + " [" + e + "]", r); "warn" === o ? "undefined" != typeof console && console.warn("LaTeX-incompatible input and strict mode is set to 'warn': " + t + " [" + e + "]") : "undefined" != typeof console && console.warn("LaTeX-incompatible input and strict mode is set to unrecognized '" + o + "': " + t + " [" + e + "]") } } useStrictBehavior(e, t, r) { let n = this.strict; if ("function" == typeof n) try { n = n(e, t, r) } catch (e) { n = "error" } return !(!n || "ignore" === n) && (!0 === n || "error" === n || ("warn" === n ? ("undefined" != typeof console && console.warn("LaTeX-incompatible input and strict mode is set to 'warn': " + t + " [" + e + "]"), !1) : ("undefined" != typeof console && console.warn("LaTeX-incompatible input and strict mode is set to unrecognized '" + n + "': " + t + " [" + e + "]"), !1))) } isTrusted(e) { if (e.url && !e.protocol) { const t = l.protocolFromUrl(e.url); if (null == t) return !1; e.protocol = t } const t = "function" == typeof this.trust ? this.trust(e) : this.trust; return Boolean(t) } } class p { constructor(e, t, r) { this.id = void 0, this.size = void 0, this.cramped = void 0, this.id = e, this.size = t, this.cramped = r } sup() { return u[d[this.id]] } sub() { return u[g[this.id]] } fracNum() { return u[f[this.id]] } fracDen() { return u[b[this.id]] } cramp() { return u[y[this.id]] } text() { return u[x[this.id]] } isTight() { return this.size >= 2 } } const u = [new p(0, 0, !1), new p(1, 0, !0), new p(2, 1, !1), new p(3, 1, !0), new p(4, 2, !1), new p(5, 2, !0), new p(6, 3, !1), new p(7, 3, !0)], d = [4, 5, 4, 5, 6, 7, 6, 7], g = [5, 5, 5, 5, 7, 7, 7, 7], f = [2, 3, 4, 5, 6, 7, 6, 7], b = [3, 3, 5, 5, 7, 7, 7, 7], y = [1, 1, 3, 3, 5, 5, 7, 7], x = [0, 1, 2, 3, 2, 3, 2, 3]; var w = { DISPLAY: u[0], TEXT: u[2], SCRIPT: u[4], SCRIPTSCRIPT: u[6] }; const v = [{ name: "latin", blocks: [[256, 591], [768, 879]] }, { name: "cyrillic", blocks: [[1024, 1279]] }, { name: "armenian", blocks: [[1328, 1423]] }, { name: "brahmic", blocks: [[2304, 4255]] }, { name: "georgian", blocks: [[4256, 4351]] }, { name: "cjk", blocks: [[12288, 12543], [19968, 40879], [65280, 65376]] }, { name: "hangul", blocks: [[44032, 55215]] }]; const k = []; function S(e) { for (let t = 0; t < k.length; t += 2)if (e >= k[t] && e <= k[t + 1]) return !0; return !1 } v.forEach((e => e.blocks.forEach((e => k.push(...e))))); const M = 80, z = { doubleleftarrow: "M262 157\nl10-10c34-36 62.7-77 86-123 3.3-8 5-13.3 5-16 0-5.3-6.7-8-20-8-7.3\n 0-12.2.5-14.5 1.5-2.3 1-4.8 4.5-7.5 10.5-49.3 97.3-121.7 169.3-217 216-28\n 14-57.3 25-88 33-6.7 2-11 3.8-13 5.5-2 1.7-3 4.2-3 7.5s1 5.8 3 7.5\nc2 1.7 6.3 3.5 13 5.5 68 17.3 128.2 47.8 180.5 91.5 52.3 43.7 93.8 96.2 124.5\n 157.5 9.3 8 15.3 12.3 18 13h6c12-.7 18-4 18-10 0-2-1.7-7-5-15-23.3-46-52-87\n-86-123l-10-10h399738v-40H218c328 0 0 0 0 0l-10-8c-26.7-20-65.7-43-117-69 2.7\n-2 6-3.7 10-5 36.7-16 72.3-37.3 107-64l10-8h399782v-40z\nm8 0v40h399730v-40zm0 194v40h399730v-40z", doublerightarrow: "M399738 392l\n-10 10c-34 36-62.7 77-86 123-3.3 8-5 13.3-5 16 0 5.3 6.7 8 20 8 7.3 0 12.2-.5\n 14.5-1.5 2.3-1 4.8-4.5 7.5-10.5 49.3-97.3 121.7-169.3 217-216 28-14 57.3-25 88\n-33 6.7-2 11-3.8 13-5.5 2-1.7 3-4.2 3-7.5s-1-5.8-3-7.5c-2-1.7-6.3-3.5-13-5.5-68\n-17.3-128.2-47.8-180.5-91.5-52.3-43.7-93.8-96.2-124.5-157.5-9.3-8-15.3-12.3-18\n-13h-6c-12 .7-18 4-18 10 0 2 1.7 7 5 15 23.3 46 52 87 86 123l10 10H0v40h399782\nc-328 0 0 0 0 0l10 8c26.7 20 65.7 43 117 69-2.7 2-6 3.7-10 5-36.7 16-72.3 37.3\n-107 64l-10 8H0v40zM0 157v40h399730v-40zm0 194v40h399730v-40z", leftarrow: "M400000 241H110l3-3c68.7-52.7 113.7-120\n 135-202 4-14.7 6-23 6-25 0-7.3-7-11-21-11-8 0-13.2.8-15.5 2.5-2.3 1.7-4.2 5.8\n-5.5 12.5-1.3 4.7-2.7 10.3-4 17-12 48.7-34.8 92-68.5 130S65.3 228.3 18 247\nc-10 4-16 7.7-18 11 0 8.7 6 14.3 18 17 47.3 18.7 87.8 47 121.5 85S196 441.3 208\n 490c.7 2 1.3 5 2 9s1.2 6.7 1.5 8c.3 1.3 1 3.3 2 6s2.2 4.5 3.5 5.5c1.3 1 3.3\n 1.8 6 2.5s6 1 10 1c14 0 21-3.7 21-11 0-2-2-10.3-6-25-20-79.3-65-146.7-135-202\n l-3-3h399890zM100 241v40h399900v-40z", leftbrace: "M6 548l-6-6v-35l6-11c56-104 135.3-181.3 238-232 57.3-28.7 117\n-45 179-50h399577v120H403c-43.3 7-81 15-113 26-100.7 33-179.7 91-237 174-2.7\n 5-6 9-10 13-.7 1-7.3 1-20 1H6z", leftbraceunder: "M0 6l6-6h17c12.688 0 19.313.3 20 1 4 4 7.313 8.3 10 13\n 35.313 51.3 80.813 93.8 136.5 127.5 55.688 33.7 117.188 55.8 184.5 66.5.688\n 0 2 .3 4 1 18.688 2.7 76 4.3 172 5h399450v120H429l-6-1c-124.688-8-235-61.7\n-331-161C60.687 138.7 32.312 99.3 7 54L0 41V6z", leftgroup: "M400000 80\nH435C64 80 168.3 229.4 21 260c-5.9 1.2-18 0-18 0-2 0-3-1-3-3v-38C76 61 257 0\n 435 0h399565z", leftgroupunder: "M400000 262\nH435C64 262 168.3 112.6 21 82c-5.9-1.2-18 0-18 0-2 0-3 1-3 3v38c76 158 257 219\n 435 219h399565z", leftharpoon: "M0 267c.7 5.3 3 10 7 14h399993v-40H93c3.3\n-3.3 10.2-9.5 20.5-18.5s17.8-15.8 22.5-20.5c50.7-52 88-110.3 112-175 4-11.3 5\n-18.3 3-21-1.3-4-7.3-6-18-6-8 0-13 .7-15 2s-4.7 6.7-8 16c-42 98.7-107.3 174.7\n-196 228-6.7 4.7-10.7 8-12 10-1.3 2-2 5.7-2 11zm100-26v40h399900v-40z", leftharpoonplus: "M0 267c.7 5.3 3 10 7 14h399993v-40H93c3.3-3.3 10.2-9.5\n 20.5-18.5s17.8-15.8 22.5-20.5c50.7-52 88-110.3 112-175 4-11.3 5-18.3 3-21-1.3\n-4-7.3-6-18-6-8 0-13 .7-15 2s-4.7 6.7-8 16c-42 98.7-107.3 174.7-196 228-6.7 4.7\n-10.7 8-12 10-1.3 2-2 5.7-2 11zm100-26v40h399900v-40zM0 435v40h400000v-40z\nm0 0v40h400000v-40z", leftharpoondown: "M7 241c-4 4-6.333 8.667-7 14 0 5.333.667 9 2 11s5.333\n 5.333 12 10c90.667 54 156 130 196 228 3.333 10.667 6.333 16.333 9 17 2 .667 5\n 1 9 1h5c10.667 0 16.667-2 18-6 2-2.667 1-9.667-3-21-32-87.333-82.667-157.667\n-152-211l-3-3h399907v-40zM93 281 H400000 v-40L7 241z", leftharpoondownplus: "M7 435c-4 4-6.3 8.7-7 14 0 5.3.7 9 2 11s5.3 5.3 12\n 10c90.7 54 156 130 196 228 3.3 10.7 6.3 16.3 9 17 2 .7 5 1 9 1h5c10.7 0 16.7\n-2 18-6 2-2.7 1-9.7-3-21-32-87.3-82.7-157.7-152-211l-3-3h399907v-40H7zm93 0\nv40h399900v-40zM0 241v40h399900v-40zm0 0v40h399900v-40z", lefthook: "M400000 281 H103s-33-11.2-61-33.5S0 197.3 0 164s14.2-61.2 42.5\n-83.5C70.8 58.2 104 47 142 47 c16.7 0 25 6.7 25 20 0 12-8.7 18.7-26 20-40 3.3\n-68.7 15.7-86 37-10 12-15 25.3-15 40 0 22.7 9.8 40.7 29.5 54 19.7 13.3 43.5 21\n 71.5 23h399859zM103 281v-40h399897v40z", leftlinesegment: "M40 281 V428 H0 V94 H40 V241 H400000 v40z\nM40 281 V428 H0 V94 H40 V241 H400000 v40z", leftmapsto: "M40 281 V448H0V74H40V241H400000v40z\nM40 281 V448H0V74H40V241H400000v40z", leftToFrom: "M0 147h400000v40H0zm0 214c68 40 115.7 95.7 143 167h22c15.3 0 23\n-.3 23-1 0-1.3-5.3-13.7-16-37-18-35.3-41.3-69-70-101l-7-8h399905v-40H95l7-8\nc28.7-32 52-65.7 70-101 10.7-23.3 16-35.7 16-37 0-.7-7.7-1-23-1h-22C115.7 265.3\n 68 321 0 361zm0-174v-40h399900v40zm100 154v40h399900v-40z", longequal: "M0 50 h400000 v40H0z m0 194h40000v40H0z\nM0 50 h400000 v40H0z m0 194h40000v40H0z", midbrace: "M200428 334\nc-100.7-8.3-195.3-44-280-108-55.3-42-101.7-93-139-153l-9-14c-2.7 4-5.7 8.7-9 14\n-53.3 86.7-123.7 153-211 199-66.7 36-137.3 56.3-212 62H0V214h199568c178.3-11.7\n 311.7-78.3 403-201 6-8 9.7-12 11-12 .7-.7 6.7-1 18-1s17.3.3 18 1c1.3 0 5 4 11\n 12 44.7 59.3 101.3 106.3 170 141s145.3 54.3 229 60h199572v120z", midbraceunder: "M199572 214\nc100.7 8.3 195.3 44 280 108 55.3 42 101.7 93 139 153l9 14c2.7-4 5.7-8.7 9-14\n 53.3-86.7 123.7-153 211-199 66.7-36 137.3-56.3 212-62h199568v120H200432c-178.3\n 11.7-311.7 78.3-403 201-6 8-9.7 12-11 12-.7.7-6.7 1-18 1s-17.3-.3-18-1c-1.3 0\n-5-4-11-12-44.7-59.3-101.3-106.3-170-141s-145.3-54.3-229-60H0V214z", oiintSize1: "M512.6 71.6c272.6 0 320.3 106.8 320.3 178.2 0 70.8-47.7 177.6\n-320.3 177.6S193.1 320.6 193.1 249.8c0-71.4 46.9-178.2 319.5-178.2z\nm368.1 178.2c0-86.4-60.9-215.4-368.1-215.4-306.4 0-367.3 129-367.3 215.4 0 85.8\n60.9 214.8 367.3 214.8 307.2 0 368.1-129 368.1-214.8z", oiintSize2: "M757.8 100.1c384.7 0 451.1 137.6 451.1 230 0 91.3-66.4 228.8\n-451.1 228.8-386.3 0-452.7-137.5-452.7-228.8 0-92.4 66.4-230 452.7-230z\nm502.4 230c0-111.2-82.4-277.2-502.4-277.2s-504 166-504 277.2\nc0 110 84 276 504 276s502.4-166 502.4-276z", oiiintSize1: "M681.4 71.6c408.9 0 480.5 106.8 480.5 178.2 0 70.8-71.6 177.6\n-480.5 177.6S202.1 320.6 202.1 249.8c0-71.4 70.5-178.2 479.3-178.2z\nm525.8 178.2c0-86.4-86.8-215.4-525.7-215.4-437.9 0-524.7 129-524.7 215.4 0\n85.8 86.8 214.8 524.7 214.8 438.9 0 525.7-129 525.7-214.8z", oiiintSize2: "M1021.2 53c603.6 0 707.8 165.8 707.8 277.2 0 110-104.2 275.8\n-707.8 275.8-606 0-710.2-165.8-710.2-275.8C311 218.8 415.2 53 1021.2 53z\nm770.4 277.1c0-131.2-126.4-327.6-770.5-327.6S248.4 198.9 248.4 330.1\nc0 130 128.8 326.4 772.7 326.4s770.5-196.4 770.5-326.4z", rightarrow: "M0 241v40h399891c-47.3 35.3-84 78-110 128\n-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20\n 11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7\n 39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85\n-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5\n-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67\n 151.7 139 205zm0 0v40h399900v-40z", rightbrace: "M400000 542l\n-6 6h-17c-12.7 0-19.3-.3-20-1-4-4-7.3-8.3-10-13-35.3-51.3-80.8-93.8-136.5-127.5\ns-117.2-55.8-184.5-66.5c-.7 0-2-.3-4-1-18.7-2.7-76-4.3-172-5H0V214h399571l6 1\nc124.7 8 235 61.7 331 161 31.3 33.3 59.7 72.7 85 118l7 13v35z", rightbraceunder: "M399994 0l6 6v35l-6 11c-56 104-135.3 181.3-238 232-57.3\n 28.7-117 45-179 50H-300V214h399897c43.3-7 81-15 113-26 100.7-33 179.7-91 237\n-174 2.7-5 6-9 10-13 .7-1 7.3-1 20-1h17z", rightgroup: "M0 80h399565c371 0 266.7 149.4 414 180 5.9 1.2 18 0 18 0 2 0\n 3-1 3-3v-38c-76-158-257-219-435-219H0z", rightgroupunder: "M0 262h399565c371 0 266.7-149.4 414-180 5.9-1.2 18 0 18\n 0 2 0 3 1 3 3v38c-76 158-257 219-435 219H0z", rightharpoon: "M0 241v40h399993c4.7-4.7 7-9.3 7-14 0-9.3\n-3.7-15.3-11-18-92.7-56.7-159-133.7-199-231-3.3-9.3-6-14.7-8-16-2-1.3-7-2-15-2\n-10.7 0-16.7 2-18 6-2 2.7-1 9.7 3 21 15.3 42 36.7 81.8 64 119.5 27.3 37.7 58\n 69.2 92 94.5zm0 0v40h399900v-40z", rightharpoonplus: "M0 241v40h399993c4.7-4.7 7-9.3 7-14 0-9.3-3.7-15.3-11\n-18-92.7-56.7-159-133.7-199-231-3.3-9.3-6-14.7-8-16-2-1.3-7-2-15-2-10.7 0-16.7\n 2-18 6-2 2.7-1 9.7 3 21 15.3 42 36.7 81.8 64 119.5 27.3 37.7 58 69.2 92 94.5z\nm0 0v40h399900v-40z m100 194v40h399900v-40zm0 0v40h399900v-40z", rightharpoondown: "M399747 511c0 7.3 6.7 11 20 11 8 0 13-.8 15-2.5s4.7-6.8\n 8-15.5c40-94 99.3-166.3 178-217 13.3-8 20.3-12.3 21-13 5.3-3.3 8.5-5.8 9.5\n-7.5 1-1.7 1.5-5.2 1.5-10.5s-2.3-10.3-7-15H0v40h399908c-34 25.3-64.7 57-92 95\n-27.3 38-48.7 77.7-64 119-3.3 8.7-5 14-5 16zM0 241v40h399900v-40z", rightharpoondownplus: "M399747 705c0 7.3 6.7 11 20 11 8 0 13-.8\n 15-2.5s4.7-6.8 8-15.5c40-94 99.3-166.3 178-217 13.3-8 20.3-12.3 21-13 5.3-3.3\n 8.5-5.8 9.5-7.5 1-1.7 1.5-5.2 1.5-10.5s-2.3-10.3-7-15H0v40h399908c-34 25.3\n-64.7 57-92 95-27.3 38-48.7 77.7-64 119-3.3 8.7-5 14-5 16zM0 435v40h399900v-40z\nm0-194v40h400000v-40zm0 0v40h400000v-40z", righthook: "M399859 241c-764 0 0 0 0 0 40-3.3 68.7-15.7 86-37 10-12 15-25.3\n 15-40 0-22.7-9.8-40.7-29.5-54-19.7-13.3-43.5-21-71.5-23-17.3-1.3-26-8-26-20 0\n-13.3 8.7-20 26-20 38 0 71 11.2 99 33.5 0 0 7 5.6 21 16.7 14 11.2 21 33.5 21\n 66.8s-14 61.2-42 83.5c-28 22.3-61 33.5-99 33.5L0 241z M0 281v-40h399859v40z", rightlinesegment: "M399960 241 V94 h40 V428 h-40 V281 H0 v-40z\nM399960 241 V94 h40 V428 h-40 V281 H0 v-40z", rightToFrom: "M400000 167c-70.7-42-118-97.7-142-167h-23c-15.3 0-23 .3-23\n 1 0 1.3 5.3 13.7 16 37 18 35.3 41.3 69 70 101l7 8H0v40h399905l-7 8c-28.7 32\n-52 65.7-70 101-10.7 23.3-16 35.7-16 37 0 .7 7.7 1 23 1h23c24-69.3 71.3-125 142\n-167z M100 147v40h399900v-40zM0 341v40h399900v-40z", twoheadleftarrow: "M0 167c68 40\n 115.7 95.7 143 167h22c15.3 0 23-.3 23-1 0-1.3-5.3-13.7-16-37-18-35.3-41.3-69\n-70-101l-7-8h125l9 7c50.7 39.3 85 86 103 140h46c0-4.7-6.3-18.7-19-42-18-35.3\n-40-67.3-66-96l-9-9h399716v-40H284l9-9c26-28.7 48-60.7 66-96 12.7-23.333 19\n-37.333 19-42h-46c-18 54-52.3 100.7-103 140l-9 7H95l7-8c28.7-32 52-65.7 70-101\n 10.7-23.333 16-35.7 16-37 0-.7-7.7-1-23-1h-22C115.7 71.3 68 127 0 167z", twoheadrightarrow: "M400000 167\nc-68-40-115.7-95.7-143-167h-22c-15.3 0-23 .3-23 1 0 1.3 5.3 13.7 16 37 18 35.3\n 41.3 69 70 101l7 8h-125l-9-7c-50.7-39.3-85-86-103-140h-46c0 4.7 6.3 18.7 19 42\n 18 35.3 40 67.3 66 96l9 9H0v40h399716l-9 9c-26 28.7-48 60.7-66 96-12.7 23.333\n-19 37.333-19 42h46c18-54 52.3-100.7 103-140l9-7h125l-7 8c-28.7 32-52 65.7-70\n 101-10.7 23.333-16 35.7-16 37 0 .7 7.7 1 23 1h22c27.3-71.3 75-127 143-167z", tilde1: "M200 55.538c-77 0-168 73.953-177 73.953-3 0-7\n-2.175-9-5.437L2 97c-1-2-2-4-2-6 0-4 2-7 5-9l20-12C116 12 171 0 207 0c86 0\n 114 68 191 68 78 0 168-68 177-68 4 0 7 2 9 5l12 19c1 2.175 2 4.35 2 6.525 0\n 4.35-2 7.613-5 9.788l-19 13.05c-92 63.077-116.937 75.308-183 76.128\n-68.267.847-113-73.952-191-73.952z", tilde2: "M344 55.266c-142 0-300.638 81.316-311.5 86.418\n-8.01 3.762-22.5 10.91-23.5 5.562L1 120c-1-2-1-3-1-4 0-5 3-9 8-10l18.4-9C160.9\n 31.9 283 0 358 0c148 0 188 122 331 122s314-97 326-97c4 0 8 2 10 7l7 21.114\nc1 2.14 1 3.21 1 4.28 0 5.347-3 9.626-7 10.696l-22.3 12.622C852.6 158.372 751\n 181.476 676 181.476c-149 0-189-126.21-332-126.21z", tilde3: "M786 59C457 59 32 175.242 13 175.242c-6 0-10-3.457\n-11-10.37L.15 138c-1-7 3-12 10-13l19.2-6.4C378.4 40.7 634.3 0 804.3 0c337 0\n 411.8 157 746.8 157 328 0 754-112 773-112 5 0 10 3 11 9l1 14.075c1 8.066-.697\n 16.595-6.697 17.492l-21.052 7.31c-367.9 98.146-609.15 122.696-778.15 122.696\n -338 0-409-156.573-744-156.573z", tilde4: "M786 58C457 58 32 177.487 13 177.487c-6 0-10-3.345\n-11-10.035L.15 143c-1-7 3-12 10-13l22-6.7C381.2 35 637.15 0 807.15 0c337 0 409\n 177 744 177 328 0 754-127 773-127 5 0 10 3 11 9l1 14.794c1 7.805-3 13.38-9\n 14.495l-20.7 5.574c-366.85 99.79-607.3 139.372-776.3 139.372-338 0-409\n -175.236-744-175.236z", vec: "M377 20c0-5.333 1.833-10 5.5-14S391 0 397 0c4.667 0 8.667 1.667 12 5\n3.333 2.667 6.667 9 10 19 6.667 24.667 20.333 43.667 41 57 7.333 4.667 11\n10.667 11 18 0 6-1 10-3 12s-6.667 5-14 9c-28.667 14.667-53.667 35.667-75 63\n-1.333 1.333-3.167 3.5-5.5 6.5s-4 4.833-5 5.5c-1 .667-2.5 1.333-4.5 2s-4.333 1\n-7 1c-4.667 0-9.167-1.833-13.5-5.5S337 184 337 178c0-12.667 15.667-32.333 47-59\nH213l-171-1c-8.667-6-13-12.333-13-19 0-4.667 4.333-11.333 13-20h359\nc-16-25.333-24-45-24-59z", widehat1: "M529 0h5l519 115c5 1 9 5 9 10 0 1-1 2-1 3l-4 22\nc-1 5-5 9-11 9h-2L532 67 19 159h-2c-5 0-9-4-11-9l-5-22c-1-6 2-12 8-13z", widehat2: "M1181 0h2l1171 176c6 0 10 5 10 11l-2 23c-1 6-5 10\n-11 10h-1L1182 67 15 220h-1c-6 0-10-4-11-10l-2-23c-1-6 4-11 10-11z", widehat3: "M1181 0h2l1171 236c6 0 10 5 10 11l-2 23c-1 6-5 10\n-11 10h-1L1182 67 15 280h-1c-6 0-10-4-11-10l-2-23c-1-6 4-11 10-11z", widehat4: "M1181 0h2l1171 296c6 0 10 5 10 11l-2 23c-1 6-5 10\n-11 10h-1L1182 67 15 340h-1c-6 0-10-4-11-10l-2-23c-1-6 4-11 10-11z", widecheck1: "M529,159h5l519,-115c5,-1,9,-5,9,-10c0,-1,-1,-2,-1,-3l-4,-22c-1,\n-5,-5,-9,-11,-9h-2l-512,92l-513,-92h-2c-5,0,-9,4,-11,9l-5,22c-1,6,2,12,8,13z", widecheck2: "M1181,220h2l1171,-176c6,0,10,-5,10,-11l-2,-23c-1,-6,-5,-10,\n-11,-10h-1l-1168,153l-1167,-153h-1c-6,0,-10,4,-11,10l-2,23c-1,6,4,11,10,11z", widecheck3: "M1181,280h2l1171,-236c6,0,10,-5,10,-11l-2,-23c-1,-6,-5,-10,\n-11,-10h-1l-1168,213l-1167,-213h-1c-6,0,-10,4,-11,10l-2,23c-1,6,4,11,10,11z", widecheck4: "M1181,340h2l1171,-296c6,0,10,-5,10,-11l-2,-23c-1,-6,-5,-10,\n-11,-10h-1l-1168,273l-1167,-273h-1c-6,0,-10,4,-11,10l-2,23c-1,6,4,11,10,11z", baraboveleftarrow: "M400000 620h-399890l3 -3c68.7 -52.7 113.7 -120 135 -202\nc4 -14.7 6 -23 6 -25c0 -7.3 -7 -11 -21 -11c-8 0 -13.2 0.8 -15.5 2.5\nc-2.3 1.7 -4.2 5.8 -5.5 12.5c-1.3 4.7 -2.7 10.3 -4 17c-12 48.7 -34.8 92 -68.5 130\ns-74.2 66.3 -121.5 85c-10 4 -16 7.7 -18 11c0 8.7 6 14.3 18 17c47.3 18.7 87.8 47\n121.5 85s56.5 81.3 68.5 130c0.7 2 1.3 5 2 9s1.2 6.7 1.5 8c0.3 1.3 1 3.3 2 6\ns2.2 4.5 3.5 5.5c1.3 1 3.3 1.8 6 2.5s6 1 10 1c14 0 21 -3.7 21 -11\nc0 -2 -2 -10.3 -6 -25c-20 -79.3 -65 -146.7 -135 -202l-3 -3h399890z\nM100 620v40h399900v-40z M0 241v40h399900v-40zM0 241v40h399900v-40z", rightarrowabovebar: "M0 241v40h399891c-47.3 35.3-84 78-110 128-16.7 32\n-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20 11 8 0\n13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7 39\n-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85-40.5\n-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5\n-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67\n151.7 139 205zm96 379h399894v40H0zm0 0h399904v40H0z", baraboveshortleftharpoon: "M507,435c-4,4,-6.3,8.7,-7,14c0,5.3,0.7,9,2,11\nc1.3,2,5.3,5.3,12,10c90.7,54,156,130,196,228c3.3,10.7,6.3,16.3,9,17\nc2,0.7,5,1,9,1c0,0,5,0,5,0c10.7,0,16.7,-2,18,-6c2,-2.7,1,-9.7,-3,-21\nc-32,-87.3,-82.7,-157.7,-152,-211c0,0,-3,-3,-3,-3l399351,0l0,-40\nc-398570,0,-399437,0,-399437,0z M593 435 v40 H399500 v-40z\nM0 281 v-40 H399908 v40z M0 281 v-40 H399908 v40z", rightharpoonaboveshortbar: "M0,241 l0,40c399126,0,399993,0,399993,0\nc4.7,-4.7,7,-9.3,7,-14c0,-9.3,-3.7,-15.3,-11,-18c-92.7,-56.7,-159,-133.7,-199,\n-231c-3.3,-9.3,-6,-14.7,-8,-16c-2,-1.3,-7,-2,-15,-2c-10.7,0,-16.7,2,-18,6\nc-2,2.7,-1,9.7,3,21c15.3,42,36.7,81.8,64,119.5c27.3,37.7,58,69.2,92,94.5z\nM0 241 v40 H399908 v-40z M0 475 v-40 H399500 v40z M0 475 v-40 H399500 v40z", shortbaraboveleftharpoon: "M7,435c-4,4,-6.3,8.7,-7,14c0,5.3,0.7,9,2,11\nc1.3,2,5.3,5.3,12,10c90.7,54,156,130,196,228c3.3,10.7,6.3,16.3,9,17c2,0.7,5,1,9,\n1c0,0,5,0,5,0c10.7,0,16.7,-2,18,-6c2,-2.7,1,-9.7,-3,-21c-32,-87.3,-82.7,-157.7,\n-152,-211c0,0,-3,-3,-3,-3l399907,0l0,-40c-399126,0,-399993,0,-399993,0z\nM93 435 v40 H400000 v-40z M500 241 v40 H400000 v-40z M500 241 v40 H400000 v-40z", shortrightharpoonabovebar: "M53,241l0,40c398570,0,399437,0,399437,0\nc4.7,-4.7,7,-9.3,7,-14c0,-9.3,-3.7,-15.3,-11,-18c-92.7,-56.7,-159,-133.7,-199,\n-231c-3.3,-9.3,-6,-14.7,-8,-16c-2,-1.3,-7,-2,-15,-2c-10.7,0,-16.7,2,-18,6\nc-2,2.7,-1,9.7,3,21c15.3,42,36.7,81.8,64,119.5c27.3,37.7,58,69.2,92,94.5z\nM500 241 v40 H399408 v-40z M500 435 v40 H400000 v-40z" }; class A { constructor(e) { this.children = void 0, this.classes = void 0, this.height = void 0, this.depth = void 0, this.maxFontSize = void 0, this.style = void 0, this.children = e, this.classes = [], this.height = 0, this.depth = 0, this.maxFontSize = 0, this.style = {} } hasClass(e) { return l.contains(this.classes, e) } toNode() { const e = document.createDocumentFragment(); for (let t = 0; t < this.children.length; t++)e.appendChild(this.children[t].toNode()); return e } toMarkup() { let e = ""; for (let t = 0; t < this.children.length; t++)e += this.children[t].toMarkup(); return e } toText() { return this.children.map((e => e.toText())).join("") } } var T = { "AMS-Regular": { 32: [0, 0, 0, 0, .25], 65: [0, .68889, 0, 0, .72222], 66: [0, .68889, 0, 0, .66667], 67: [0, .68889, 0, 0, .72222], 68: [0, .68889, 0, 0, .72222], 69: [0, .68889, 0, 0, .66667], 70: [0, .68889, 0, 0, .61111], 71: [0, .68889, 0, 0, .77778], 72: [0, .68889, 0, 0, .77778], 73: [0, .68889, 0, 0, .38889], 74: [.16667, .68889, 0, 0, .5], 75: [0, .68889, 0, 0, .77778], 76: [0, .68889, 0, 0, .66667], 77: [0, .68889, 0, 0, .94445], 78: [0, .68889, 0, 0, .72222], 79: [.16667, .68889, 0, 0, .77778], 80: [0, .68889, 0, 0, .61111], 81: [.16667, .68889, 0, 0, .77778], 82: [0, .68889, 0, 0, .72222], 83: [0, .68889, 0, 0, .55556], 84: [0, .68889, 0, 0, .66667], 85: [0, .68889, 0, 0, .72222], 86: [0, .68889, 0, 0, .72222], 87: [0, .68889, 0, 0, 1], 88: [0, .68889, 0, 0, .72222], 89: [0, .68889, 0, 0, .72222], 90: [0, .68889, 0, 0, .66667], 107: [0, .68889, 0, 0, .55556], 160: [0, 0, 0, 0, .25], 165: [0, .675, .025, 0, .75], 174: [.15559, .69224, 0, 0, .94666], 240: [0, .68889, 0, 0, .55556], 295: [0, .68889, 0, 0, .54028], 710: [0, .825, 0, 0, 2.33334], 732: [0, .9, 0, 0, 2.33334], 770: [0, .825, 0, 0, 2.33334], 771: [0, .9, 0, 0, 2.33334], 989: [.08167, .58167, 0, 0, .77778], 1008: [0, .43056, .04028, 0, .66667], 8245: [0, .54986, 0, 0, .275], 8463: [0, .68889, 0, 0, .54028], 8487: [0, .68889, 0, 0, .72222], 8498: [0, .68889, 0, 0, .55556], 8502: [0, .68889, 0, 0, .66667], 8503: [0, .68889, 0, 0, .44445], 8504: [0, .68889, 0, 0, .66667], 8513: [0, .68889, 0, 0, .63889], 8592: [-.03598, .46402, 0, 0, .5], 8594: [-.03598, .46402, 0, 0, .5], 8602: [-.13313, .36687, 0, 0, 1], 8603: [-.13313, .36687, 0, 0, 1], 8606: [.01354, .52239, 0, 0, 1], 8608: [.01354, .52239, 0, 0, 1], 8610: [.01354, .52239, 0, 0, 1.11111], 8611: [.01354, .52239, 0, 0, 1.11111], 8619: [0, .54986, 0, 0, 1], 8620: [0, .54986, 0, 0, 1], 8621: [-.13313, .37788, 0, 0, 1.38889], 8622: [-.13313, .36687, 0, 0, 1], 8624: [0, .69224, 0, 0, .5], 8625: [0, .69224, 0, 0, .5], 8630: [0, .43056, 0, 0, 1], 8631: [0, .43056, 0, 0, 1], 8634: [.08198, .58198, 0, 0, .77778], 8635: [.08198, .58198, 0, 0, .77778], 8638: [.19444, .69224, 0, 0, .41667], 8639: [.19444, .69224, 0, 0, .41667], 8642: [.19444, .69224, 0, 0, .41667], 8643: [.19444, .69224, 0, 0, .41667], 8644: [.1808, .675, 0, 0, 1], 8646: [.1808, .675, 0, 0, 1], 8647: [.1808, .675, 0, 0, 1], 8648: [.19444, .69224, 0, 0, .83334], 8649: [.1808, .675, 0, 0, 1], 8650: [.19444, .69224, 0, 0, .83334], 8651: [.01354, .52239, 0, 0, 1], 8652: [.01354, .52239, 0, 0, 1], 8653: [-.13313, .36687, 0, 0, 1], 8654: [-.13313, .36687, 0, 0, 1], 8655: [-.13313, .36687, 0, 0, 1], 8666: [.13667, .63667, 0, 0, 1], 8667: [.13667, .63667, 0, 0, 1], 8669: [-.13313, .37788, 0, 0, 1], 8672: [-.064, .437, 0, 0, 1.334], 8674: [-.064, .437, 0, 0, 1.334], 8705: [0, .825, 0, 0, .5], 8708: [0, .68889, 0, 0, .55556], 8709: [.08167, .58167, 0, 0, .77778], 8717: [0, .43056, 0, 0, .42917], 8722: [-.03598, .46402, 0, 0, .5], 8724: [.08198, .69224, 0, 0, .77778], 8726: [.08167, .58167, 0, 0, .77778], 8733: [0, .69224, 0, 0, .77778], 8736: [0, .69224, 0, 0, .72222], 8737: [0, .69224, 0, 0, .72222], 8738: [.03517, .52239, 0, 0, .72222], 8739: [.08167, .58167, 0, 0, .22222], 8740: [.25142, .74111, 0, 0, .27778], 8741: [.08167, .58167, 0, 0, .38889], 8742: [.25142, .74111, 0, 0, .5], 8756: [0, .69224, 0, 0, .66667], 8757: [0, .69224, 0, 0, .66667], 8764: [-.13313, .36687, 0, 0, .77778], 8765: [-.13313, .37788, 0, 0, .77778], 8769: [-.13313, .36687, 0, 0, .77778], 8770: [-.03625, .46375, 0, 0, .77778], 8774: [.30274, .79383, 0, 0, .77778], 8776: [-.01688, .48312, 0, 0, .77778], 8778: [.08167, .58167, 0, 0, .77778], 8782: [.06062, .54986, 0, 0, .77778], 8783: [.06062, .54986, 0, 0, .77778], 8785: [.08198, .58198, 0, 0, .77778], 8786: [.08198, .58198, 0, 0, .77778], 8787: [.08198, .58198, 0, 0, .77778], 8790: [0, .69224, 0, 0, .77778], 8791: [.22958, .72958, 0, 0, .77778], 8796: [.08198, .91667, 0, 0, .77778], 8806: [.25583, .75583, 0, 0, .77778], 8807: [.25583, .75583, 0, 0, .77778], 8808: [.25142, .75726, 0, 0, .77778], 8809: [.25142, .75726, 0, 0, .77778], 8812: [.25583, .75583, 0, 0, .5], 8814: [.20576, .70576, 0, 0, .77778], 8815: [.20576, .70576, 0, 0, .77778], 8816: [.30274, .79383, 0, 0, .77778], 8817: [.30274, .79383, 0, 0, .77778], 8818: [.22958, .72958, 0, 0, .77778], 8819: [.22958, .72958, 0, 0, .77778], 8822: [.1808, .675, 0, 0, .77778], 8823: [.1808, .675, 0, 0, .77778], 8828: [.13667, .63667, 0, 0, .77778], 8829: [.13667, .63667, 0, 0, .77778], 8830: [.22958, .72958, 0, 0, .77778], 8831: [.22958, .72958, 0, 0, .77778], 8832: [.20576, .70576, 0, 0, .77778], 8833: [.20576, .70576, 0, 0, .77778], 8840: [.30274, .79383, 0, 0, .77778], 8841: [.30274, .79383, 0, 0, .77778], 8842: [.13597, .63597, 0, 0, .77778], 8843: [.13597, .63597, 0, 0, .77778], 8847: [.03517, .54986, 0, 0, .77778], 8848: [.03517, .54986, 0, 0, .77778], 8858: [.08198, .58198, 0, 0, .77778], 8859: [.08198, .58198, 0, 0, .77778], 8861: [.08198, .58198, 0, 0, .77778], 8862: [0, .675, 0, 0, .77778], 8863: [0, .675, 0, 0, .77778], 8864: [0, .675, 0, 0, .77778], 8865: [0, .675, 0, 0, .77778], 8872: [0, .69224, 0, 0, .61111], 8873: [0, .69224, 0, 0, .72222], 8874: [0, .69224, 0, 0, .88889], 8876: [0, .68889, 0, 0, .61111], 8877: [0, .68889, 0, 0, .61111], 8878: [0, .68889, 0, 0, .72222], 8879: [0, .68889, 0, 0, .72222], 8882: [.03517, .54986, 0, 0, .77778], 8883: [.03517, .54986, 0, 0, .77778], 8884: [.13667, .63667, 0, 0, .77778], 8885: [.13667, .63667, 0, 0, .77778], 8888: [0, .54986, 0, 0, 1.11111], 8890: [.19444, .43056, 0, 0, .55556], 8891: [.19444, .69224, 0, 0, .61111], 8892: [.19444, .69224, 0, 0, .61111], 8901: [0, .54986, 0, 0, .27778], 8903: [.08167, .58167, 0, 0, .77778], 8905: [.08167, .58167, 0, 0, .77778], 8906: [.08167, .58167, 0, 0, .77778], 8907: [0, .69224, 0, 0, .77778], 8908: [0, .69224, 0, 0, .77778], 8909: [-.03598, .46402, 0, 0, .77778], 8910: [0, .54986, 0, 0, .76042], 8911: [0, .54986, 0, 0, .76042], 8912: [.03517, .54986, 0, 0, .77778], 8913: [.03517, .54986, 0, 0, .77778], 8914: [0, .54986, 0, 0, .66667], 8915: [0, .54986, 0, 0, .66667], 8916: [0, .69224, 0, 0, .66667], 8918: [.0391, .5391, 0, 0, .77778], 8919: [.0391, .5391, 0, 0, .77778], 8920: [.03517, .54986, 0, 0, 1.33334], 8921: [.03517, .54986, 0, 0, 1.33334], 8922: [.38569, .88569, 0, 0, .77778], 8923: [.38569, .88569, 0, 0, .77778], 8926: [.13667, .63667, 0, 0, .77778], 8927: [.13667, .63667, 0, 0, .77778], 8928: [.30274, .79383, 0, 0, .77778], 8929: [.30274, .79383, 0, 0, .77778], 8934: [.23222, .74111, 0, 0, .77778], 8935: [.23222, .74111, 0, 0, .77778], 8936: [.23222, .74111, 0, 0, .77778], 8937: [.23222, .74111, 0, 0, .77778], 8938: [.20576, .70576, 0, 0, .77778], 8939: [.20576, .70576, 0, 0, .77778], 8940: [.30274, .79383, 0, 0, .77778], 8941: [.30274, .79383, 0, 0, .77778], 8994: [.19444, .69224, 0, 0, .77778], 8995: [.19444, .69224, 0, 0, .77778], 9416: [.15559, .69224, 0, 0, .90222], 9484: [0, .69224, 0, 0, .5], 9488: [0, .69224, 0, 0, .5], 9492: [0, .37788, 0, 0, .5], 9496: [0, .37788, 0, 0, .5], 9585: [.19444, .68889, 0, 0, .88889], 9586: [.19444, .74111, 0, 0, .88889], 9632: [0, .675, 0, 0, .77778], 9633: [0, .675, 0, 0, .77778], 9650: [0, .54986, 0, 0, .72222], 9651: [0, .54986, 0, 0, .72222], 9654: [.03517, .54986, 0, 0, .77778], 9660: [0, .54986, 0, 0, .72222], 9661: [0, .54986, 0, 0, .72222], 9664: [.03517, .54986, 0, 0, .77778], 9674: [.11111, .69224, 0, 0, .66667], 9733: [.19444, .69224, 0, 0, .94445], 10003: [0, .69224, 0, 0, .83334], 10016: [0, .69224, 0, 0, .83334], 10731: [.11111, .69224, 0, 0, .66667], 10846: [.19444, .75583, 0, 0, .61111], 10877: [.13667, .63667, 0, 0, .77778], 10878: [.13667, .63667, 0, 0, .77778], 10885: [.25583, .75583, 0, 0, .77778], 10886: [.25583, .75583, 0, 0, .77778], 10887: [.13597, .63597, 0, 0, .77778], 10888: [.13597, .63597, 0, 0, .77778], 10889: [.26167, .75726, 0, 0, .77778], 10890: [.26167, .75726, 0, 0, .77778], 10891: [.48256, .98256, 0, 0, .77778], 10892: [.48256, .98256, 0, 0, .77778], 10901: [.13667, .63667, 0, 0, .77778], 10902: [.13667, .63667, 0, 0, .77778], 10933: [.25142, .75726, 0, 0, .77778], 10934: [.25142, .75726, 0, 0, .77778], 10935: [.26167, .75726, 0, 0, .77778], 10936: [.26167, .75726, 0, 0, .77778], 10937: [.26167, .75726, 0, 0, .77778], 10938: [.26167, .75726, 0, 0, .77778], 10949: [.25583, .75583, 0, 0, .77778], 10950: [.25583, .75583, 0, 0, .77778], 10955: [.28481, .79383, 0, 0, .77778], 10956: [.28481, .79383, 0, 0, .77778], 57350: [.08167, .58167, 0, 0, .22222], 57351: [.08167, .58167, 0, 0, .38889], 57352: [.08167, .58167, 0, 0, .77778], 57353: [0, .43056, .04028, 0, .66667], 57356: [.25142, .75726, 0, 0, .77778], 57357: [.25142, .75726, 0, 0, .77778], 57358: [.41951, .91951, 0, 0, .77778], 57359: [.30274, .79383, 0, 0, .77778], 57360: [.30274, .79383, 0, 0, .77778], 57361: [.41951, .91951, 0, 0, .77778], 57366: [.25142, .75726, 0, 0, .77778], 57367: [.25142, .75726, 0, 0, .77778], 57368: [.25142, .75726, 0, 0, .77778], 57369: [.25142, .75726, 0, 0, .77778], 57370: [.13597, .63597, 0, 0, .77778], 57371: [.13597, .63597, 0, 0, .77778] }, "Caligraphic-Regular": { 32: [0, 0, 0, 0, .25], 65: [0, .68333, 0, .19445, .79847], 66: [0, .68333, .03041, .13889, .65681], 67: [0, .68333, .05834, .13889, .52653], 68: [0, .68333, .02778, .08334, .77139], 69: [0, .68333, .08944, .11111, .52778], 70: [0, .68333, .09931, .11111, .71875], 71: [.09722, .68333, .0593, .11111, .59487], 72: [0, .68333, .00965, .11111, .84452], 73: [0, .68333, .07382, 0, .54452], 74: [.09722, .68333, .18472, .16667, .67778], 75: [0, .68333, .01445, .05556, .76195], 76: [0, .68333, 0, .13889, .68972], 77: [0, .68333, 0, .13889, 1.2009], 78: [0, .68333, .14736, .08334, .82049], 79: [0, .68333, .02778, .11111, .79611], 80: [0, .68333, .08222, .08334, .69556], 81: [.09722, .68333, 0, .11111, .81667], 82: [0, .68333, 0, .08334, .8475], 83: [0, .68333, .075, .13889, .60556], 84: [0, .68333, .25417, 0, .54464], 85: [0, .68333, .09931, .08334, .62583], 86: [0, .68333, .08222, 0, .61278], 87: [0, .68333, .08222, .08334, .98778], 88: [0, .68333, .14643, .13889, .7133], 89: [.09722, .68333, .08222, .08334, .66834], 90: [0, .68333, .07944, .13889, .72473], 160: [0, 0, 0, 0, .25] }, "Fraktur-Regular": { 32: [0, 0, 0, 0, .25], 33: [0, .69141, 0, 0, .29574], 34: [0, .69141, 0, 0, .21471], 38: [0, .69141, 0, 0, .73786], 39: [0, .69141, 0, 0, .21201], 40: [.24982, .74947, 0, 0, .38865], 41: [.24982, .74947, 0, 0, .38865], 42: [0, .62119, 0, 0, .27764], 43: [.08319, .58283, 0, 0, .75623], 44: [0, .10803, 0, 0, .27764], 45: [.08319, .58283, 0, 0, .75623], 46: [0, .10803, 0, 0, .27764], 47: [.24982, .74947, 0, 0, .50181], 48: [0, .47534, 0, 0, .50181], 49: [0, .47534, 0, 0, .50181], 50: [0, .47534, 0, 0, .50181], 51: [.18906, .47534, 0, 0, .50181], 52: [.18906, .47534, 0, 0, .50181], 53: [.18906, .47534, 0, 0, .50181], 54: [0, .69141, 0, 0, .50181], 55: [.18906, .47534, 0, 0, .50181], 56: [0, .69141, 0, 0, .50181], 57: [.18906, .47534, 0, 0, .50181], 58: [0, .47534, 0, 0, .21606], 59: [.12604, .47534, 0, 0, .21606], 61: [-.13099, .36866, 0, 0, .75623], 63: [0, .69141, 0, 0, .36245], 65: [0, .69141, 0, 0, .7176], 66: [0, .69141, 0, 0, .88397], 67: [0, .69141, 0, 0, .61254], 68: [0, .69141, 0, 0, .83158], 69: [0, .69141, 0, 0, .66278], 70: [.12604, .69141, 0, 0, .61119], 71: [0, .69141, 0, 0, .78539], 72: [.06302, .69141, 0, 0, .7203], 73: [0, .69141, 0, 0, .55448], 74: [.12604, .69141, 0, 0, .55231], 75: [0, .69141, 0, 0, .66845], 76: [0, .69141, 0, 0, .66602], 77: [0, .69141, 0, 0, 1.04953], 78: [0, .69141, 0, 0, .83212], 79: [0, .69141, 0, 0, .82699], 80: [.18906, .69141, 0, 0, .82753], 81: [.03781, .69141, 0, 0, .82699], 82: [0, .69141, 0, 0, .82807], 83: [0, .69141, 0, 0, .82861], 84: [0, .69141, 0, 0, .66899], 85: [0, .69141, 0, 0, .64576], 86: [0, .69141, 0, 0, .83131], 87: [0, .69141, 0, 0, 1.04602], 88: [0, .69141, 0, 0, .71922], 89: [.18906, .69141, 0, 0, .83293], 90: [.12604, .69141, 0, 0, .60201], 91: [.24982, .74947, 0, 0, .27764], 93: [.24982, .74947, 0, 0, .27764], 94: [0, .69141, 0, 0, .49965], 97: [0, .47534, 0, 0, .50046], 98: [0, .69141, 0, 0, .51315], 99: [0, .47534, 0, 0, .38946], 100: [0, .62119, 0, 0, .49857], 101: [0, .47534, 0, 0, .40053], 102: [.18906, .69141, 0, 0, .32626], 103: [.18906, .47534, 0, 0, .5037], 104: [.18906, .69141, 0, 0, .52126], 105: [0, .69141, 0, 0, .27899], 106: [0, .69141, 0, 0, .28088], 107: [0, .69141, 0, 0, .38946], 108: [0, .69141, 0, 0, .27953], 109: [0, .47534, 0, 0, .76676], 110: [0, .47534, 0, 0, .52666], 111: [0, .47534, 0, 0, .48885], 112: [.18906, .52396, 0, 0, .50046], 113: [.18906, .47534, 0, 0, .48912], 114: [0, .47534, 0, 0, .38919], 115: [0, .47534, 0, 0, .44266], 116: [0, .62119, 0, 0, .33301], 117: [0, .47534, 0, 0, .5172], 118: [0, .52396, 0, 0, .5118], 119: [0, .52396, 0, 0, .77351], 120: [.18906, .47534, 0, 0, .38865], 121: [.18906, .47534, 0, 0, .49884], 122: [.18906, .47534, 0, 0, .39054], 160: [0, 0, 0, 0, .25], 8216: [0, .69141, 0, 0, .21471], 8217: [0, .69141, 0, 0, .21471], 58112: [0, .62119, 0, 0, .49749], 58113: [0, .62119, 0, 0, .4983], 58114: [.18906, .69141, 0, 0, .33328], 58115: [.18906, .69141, 0, 0, .32923], 58116: [.18906, .47534, 0, 0, .50343], 58117: [0, .69141, 0, 0, .33301], 58118: [0, .62119, 0, 0, .33409], 58119: [0, .47534, 0, 0, .50073] }, "Main-Bold": { 32: [0, 0, 0, 0, .25], 33: [0, .69444, 0, 0, .35], 34: [0, .69444, 0, 0, .60278], 35: [.19444, .69444, 0, 0, .95833], 36: [.05556, .75, 0, 0, .575], 37: [.05556, .75, 0, 0, .95833], 38: [0, .69444, 0, 0, .89444], 39: [0, .69444, 0, 0, .31944], 40: [.25, .75, 0, 0, .44722], 41: [.25, .75, 0, 0, .44722], 42: [0, .75, 0, 0, .575], 43: [.13333, .63333, 0, 0, .89444], 44: [.19444, .15556, 0, 0, .31944], 45: [0, .44444, 0, 0, .38333], 46: [0, .15556, 0, 0, .31944], 47: [.25, .75, 0, 0, .575], 48: [0, .64444, 0, 0, .575], 49: [0, .64444, 0, 0, .575], 50: [0, .64444, 0, 0, .575], 51: [0, .64444, 0, 0, .575], 52: [0, .64444, 0, 0, .575], 53: [0, .64444, 0, 0, .575], 54: [0, .64444, 0, 0, .575], 55: [0, .64444, 0, 0, .575], 56: [0, .64444, 0, 0, .575], 57: [0, .64444, 0, 0, .575], 58: [0, .44444, 0, 0, .31944], 59: [.19444, .44444, 0, 0, .31944], 60: [.08556, .58556, 0, 0, .89444], 61: [-.10889, .39111, 0, 0, .89444], 62: [.08556, .58556, 0, 0, .89444], 63: [0, .69444, 0, 0, .54305], 64: [0, .69444, 0, 0, .89444], 65: [0, .68611, 0, 0, .86944], 66: [0, .68611, 0, 0, .81805], 67: [0, .68611, 0, 0, .83055], 68: [0, .68611, 0, 0, .88194], 69: [0, .68611, 0, 0, .75555], 70: [0, .68611, 0, 0, .72361], 71: [0, .68611, 0, 0, .90416], 72: [0, .68611, 0, 0, .9], 73: [0, .68611, 0, 0, .43611], 74: [0, .68611, 0, 0, .59444], 75: [0, .68611, 0, 0, .90138], 76: [0, .68611, 0, 0, .69166], 77: [0, .68611, 0, 0, 1.09166], 78: [0, .68611, 0, 0, .9], 79: [0, .68611, 0, 0, .86388], 80: [0, .68611, 0, 0, .78611], 81: [.19444, .68611, 0, 0, .86388], 82: [0, .68611, 0, 0, .8625], 83: [0, .68611, 0, 0, .63889], 84: [0, .68611, 0, 0, .8], 85: [0, .68611, 0, 0, .88472], 86: [0, .68611, .01597, 0, .86944], 87: [0, .68611, .01597, 0, 1.18888], 88: [0, .68611, 0, 0, .86944], 89: [0, .68611, .02875, 0, .86944], 90: [0, .68611, 0, 0, .70277], 91: [.25, .75, 0, 0, .31944], 92: [.25, .75, 0, 0, .575], 93: [.25, .75, 0, 0, .31944], 94: [0, .69444, 0, 0, .575], 95: [.31, .13444, .03194, 0, .575], 97: [0, .44444, 0, 0, .55902], 98: [0, .69444, 0, 0, .63889], 99: [0, .44444, 0, 0, .51111], 100: [0, .69444, 0, 0, .63889], 101: [0, .44444, 0, 0, .52708], 102: [0, .69444, .10903, 0, .35139], 103: [.19444, .44444, .01597, 0, .575], 104: [0, .69444, 0, 0, .63889], 105: [0, .69444, 0, 0, .31944], 106: [.19444, .69444, 0, 0, .35139], 107: [0, .69444, 0, 0, .60694], 108: [0, .69444, 0, 0, .31944], 109: [0, .44444, 0, 0, .95833], 110: [0, .44444, 0, 0, .63889], 111: [0, .44444, 0, 0, .575], 112: [.19444, .44444, 0, 0, .63889], 113: [.19444, .44444, 0, 0, .60694], 114: [0, .44444, 0, 0, .47361], 115: [0, .44444, 0, 0, .45361], 116: [0, .63492, 0, 0, .44722], 117: [0, .44444, 0, 0, .63889], 118: [0, .44444, .01597, 0, .60694], 119: [0, .44444, .01597, 0, .83055], 120: [0, .44444, 0, 0, .60694], 121: [.19444, .44444, .01597, 0, .60694], 122: [0, .44444, 0, 0, .51111], 123: [.25, .75, 0, 0, .575], 124: [.25, .75, 0, 0, .31944], 125: [.25, .75, 0, 0, .575], 126: [.35, .34444, 0, 0, .575], 160: [0, 0, 0, 0, .25], 163: [0, .69444, 0, 0, .86853], 168: [0, .69444, 0, 0, .575], 172: [0, .44444, 0, 0, .76666], 176: [0, .69444, 0, 0, .86944], 177: [.13333, .63333, 0, 0, .89444], 184: [.17014, 0, 0, 0, .51111], 198: [0, .68611, 0, 0, 1.04166], 215: [.13333, .63333, 0, 0, .89444], 216: [.04861, .73472, 0, 0, .89444], 223: [0, .69444, 0, 0, .59722], 230: [0, .44444, 0, 0, .83055], 247: [.13333, .63333, 0, 0, .89444], 248: [.09722, .54167, 0, 0, .575], 305: [0, .44444, 0, 0, .31944], 338: [0, .68611, 0, 0, 1.16944], 339: [0, .44444, 0, 0, .89444], 567: [.19444, .44444, 0, 0, .35139], 710: [0, .69444, 0, 0, .575], 711: [0, .63194, 0, 0, .575], 713: [0, .59611, 0, 0, .575], 714: [0, .69444, 0, 0, .575], 715: [0, .69444, 0, 0, .575], 728: [0, .69444, 0, 0, .575], 729: [0, .69444, 0, 0, .31944], 730: [0, .69444, 0, 0, .86944], 732: [0, .69444, 0, 0, .575], 733: [0, .69444, 0, 0, .575], 915: [0, .68611, 0, 0, .69166], 916: [0, .68611, 0, 0, .95833], 920: [0, .68611, 0, 0, .89444], 923: [0, .68611, 0, 0, .80555], 926: [0, .68611, 0, 0, .76666], 928: [0, .68611, 0, 0, .9], 931: [0, .68611, 0, 0, .83055], 933: [0, .68611, 0, 0, .89444], 934: [0, .68611, 0, 0, .83055], 936: [0, .68611, 0, 0, .89444], 937: [0, .68611, 0, 0, .83055], 8211: [0, .44444, .03194, 0, .575], 8212: [0, .44444, .03194, 0, 1.14999], 8216: [0, .69444, 0, 0, .31944], 8217: [0, .69444, 0, 0, .31944], 8220: [0, .69444, 0, 0, .60278], 8221: [0, .69444, 0, 0, .60278], 8224: [.19444, .69444, 0, 0, .51111], 8225: [.19444, .69444, 0, 0, .51111], 8242: [0, .55556, 0, 0, .34444], 8407: [0, .72444, .15486, 0, .575], 8463: [0, .69444, 0, 0, .66759], 8465: [0, .69444, 0, 0, .83055], 8467: [0, .69444, 0, 0, .47361], 8472: [.19444, .44444, 0, 0, .74027], 8476: [0, .69444, 0, 0, .83055], 8501: [0, .69444, 0, 0, .70277], 8592: [-.10889, .39111, 0, 0, 1.14999], 8593: [.19444, .69444, 0, 0, .575], 8594: [-.10889, .39111, 0, 0, 1.14999], 8595: [.19444, .69444, 0, 0, .575], 8596: [-.10889, .39111, 0, 0, 1.14999], 8597: [.25, .75, 0, 0, .575], 8598: [.19444, .69444, 0, 0, 1.14999], 8599: [.19444, .69444, 0, 0, 1.14999], 8600: [.19444, .69444, 0, 0, 1.14999], 8601: [.19444, .69444, 0, 0, 1.14999], 8636: [-.10889, .39111, 0, 0, 1.14999], 8637: [-.10889, .39111, 0, 0, 1.14999], 8640: [-.10889, .39111, 0, 0, 1.14999], 8641: [-.10889, .39111, 0, 0, 1.14999], 8656: [-.10889, .39111, 0, 0, 1.14999], 8657: [.19444, .69444, 0, 0, .70277], 8658: [-.10889, .39111, 0, 0, 1.14999], 8659: [.19444, .69444, 0, 0, .70277], 8660: [-.10889, .39111, 0, 0, 1.14999], 8661: [.25, .75, 0, 0, .70277], 8704: [0, .69444, 0, 0, .63889], 8706: [0, .69444, .06389, 0, .62847], 8707: [0, .69444, 0, 0, .63889], 8709: [.05556, .75, 0, 0, .575], 8711: [0, .68611, 0, 0, .95833], 8712: [.08556, .58556, 0, 0, .76666], 8715: [.08556, .58556, 0, 0, .76666], 8722: [.13333, .63333, 0, 0, .89444], 8723: [.13333, .63333, 0, 0, .89444], 8725: [.25, .75, 0, 0, .575], 8726: [.25, .75, 0, 0, .575], 8727: [-.02778, .47222, 0, 0, .575], 8728: [-.02639, .47361, 0, 0, .575], 8729: [-.02639, .47361, 0, 0, .575], 8730: [.18, .82, 0, 0, .95833], 8733: [0, .44444, 0, 0, .89444], 8734: [0, .44444, 0, 0, 1.14999], 8736: [0, .69224, 0, 0, .72222], 8739: [.25, .75, 0, 0, .31944], 8741: [.25, .75, 0, 0, .575], 8743: [0, .55556, 0, 0, .76666], 8744: [0, .55556, 0, 0, .76666], 8745: [0, .55556, 0, 0, .76666], 8746: [0, .55556, 0, 0, .76666], 8747: [.19444, .69444, .12778, 0, .56875], 8764: [-.10889, .39111, 0, 0, .89444], 8768: [.19444, .69444, 0, 0, .31944], 8771: [.00222, .50222, 0, 0, .89444], 8773: [.027, .638, 0, 0, .894], 8776: [.02444, .52444, 0, 0, .89444], 8781: [.00222, .50222, 0, 0, .89444], 8801: [.00222, .50222, 0, 0, .89444], 8804: [.19667, .69667, 0, 0, .89444], 8805: [.19667, .69667, 0, 0, .89444], 8810: [.08556, .58556, 0, 0, 1.14999], 8811: [.08556, .58556, 0, 0, 1.14999], 8826: [.08556, .58556, 0, 0, .89444], 8827: [.08556, .58556, 0, 0, .89444], 8834: [.08556, .58556, 0, 0, .89444], 8835: [.08556, .58556, 0, 0, .89444], 8838: [.19667, .69667, 0, 0, .89444], 8839: [.19667, .69667, 0, 0, .89444], 8846: [0, .55556, 0, 0, .76666], 8849: [.19667, .69667, 0, 0, .89444], 8850: [.19667, .69667, 0, 0, .89444], 8851: [0, .55556, 0, 0, .76666], 8852: [0, .55556, 0, 0, .76666], 8853: [.13333, .63333, 0, 0, .89444], 8854: [.13333, .63333, 0, 0, .89444], 8855: [.13333, .63333, 0, 0, .89444], 8856: [.13333, .63333, 0, 0, .89444], 8857: [.13333, .63333, 0, 0, .89444], 8866: [0, .69444, 0, 0, .70277], 8867: [0, .69444, 0, 0, .70277], 8868: [0, .69444, 0, 0, .89444], 8869: [0, .69444, 0, 0, .89444], 8900: [-.02639, .47361, 0, 0, .575], 8901: [-.02639, .47361, 0, 0, .31944], 8902: [-.02778, .47222, 0, 0, .575], 8968: [.25, .75, 0, 0, .51111], 8969: [.25, .75, 0, 0, .51111], 8970: [.25, .75, 0, 0, .51111], 8971: [.25, .75, 0, 0, .51111], 8994: [-.13889, .36111, 0, 0, 1.14999], 8995: [-.13889, .36111, 0, 0, 1.14999], 9651: [.19444, .69444, 0, 0, 1.02222], 9657: [-.02778, .47222, 0, 0, .575], 9661: [.19444, .69444, 0, 0, 1.02222], 9667: [-.02778, .47222, 0, 0, .575], 9711: [.19444, .69444, 0, 0, 1.14999], 9824: [.12963, .69444, 0, 0, .89444], 9825: [.12963, .69444, 0, 0, .89444], 9826: [.12963, .69444, 0, 0, .89444], 9827: [.12963, .69444, 0, 0, .89444], 9837: [0, .75, 0, 0, .44722], 9838: [.19444, .69444, 0, 0, .44722], 9839: [.19444, .69444, 0, 0, .44722], 10216: [.25, .75, 0, 0, .44722], 10217: [.25, .75, 0, 0, .44722], 10815: [0, .68611, 0, 0, .9], 10927: [.19667, .69667, 0, 0, .89444], 10928: [.19667, .69667, 0, 0, .89444], 57376: [.19444, .69444, 0, 0, 0] }, "Main-BoldItalic": { 32: [0, 0, 0, 0, .25], 33: [0, .69444, .11417, 0, .38611], 34: [0, .69444, .07939, 0, .62055], 35: [.19444, .69444, .06833, 0, .94444], 37: [.05556, .75, .12861, 0, .94444], 38: [0, .69444, .08528, 0, .88555], 39: [0, .69444, .12945, 0, .35555], 40: [.25, .75, .15806, 0, .47333], 41: [.25, .75, .03306, 0, .47333], 42: [0, .75, .14333, 0, .59111], 43: [.10333, .60333, .03306, 0, .88555], 44: [.19444, .14722, 0, 0, .35555], 45: [0, .44444, .02611, 0, .41444], 46: [0, .14722, 0, 0, .35555], 47: [.25, .75, .15806, 0, .59111], 48: [0, .64444, .13167, 0, .59111], 49: [0, .64444, .13167, 0, .59111], 50: [0, .64444, .13167, 0, .59111], 51: [0, .64444, .13167, 0, .59111], 52: [.19444, .64444, .13167, 0, .59111], 53: [0, .64444, .13167, 0, .59111], 54: [0, .64444, .13167, 0, .59111], 55: [.19444, .64444, .13167, 0, .59111], 56: [0, .64444, .13167, 0, .59111], 57: [0, .64444, .13167, 0, .59111], 58: [0, .44444, .06695, 0, .35555], 59: [.19444, .44444, .06695, 0, .35555], 61: [-.10889, .39111, .06833, 0, .88555], 63: [0, .69444, .11472, 0, .59111], 64: [0, .69444, .09208, 0, .88555], 65: [0, .68611, 0, 0, .86555], 66: [0, .68611, .0992, 0, .81666], 67: [0, .68611, .14208, 0, .82666], 68: [0, .68611, .09062, 0, .87555], 69: [0, .68611, .11431, 0, .75666], 70: [0, .68611, .12903, 0, .72722], 71: [0, .68611, .07347, 0, .89527], 72: [0, .68611, .17208, 0, .8961], 73: [0, .68611, .15681, 0, .47166], 74: [0, .68611, .145, 0, .61055], 75: [0, .68611, .14208, 0, .89499], 76: [0, .68611, 0, 0, .69777], 77: [0, .68611, .17208, 0, 1.07277], 78: [0, .68611, .17208, 0, .8961], 79: [0, .68611, .09062, 0, .85499], 80: [0, .68611, .0992, 0, .78721], 81: [.19444, .68611, .09062, 0, .85499], 82: [0, .68611, .02559, 0, .85944], 83: [0, .68611, .11264, 0, .64999], 84: [0, .68611, .12903, 0, .7961], 85: [0, .68611, .17208, 0, .88083], 86: [0, .68611, .18625, 0, .86555], 87: [0, .68611, .18625, 0, 1.15999], 88: [0, .68611, .15681, 0, .86555], 89: [0, .68611, .19803, 0, .86555], 90: [0, .68611, .14208, 0, .70888], 91: [.25, .75, .1875, 0, .35611], 93: [.25, .75, .09972, 0, .35611], 94: [0, .69444, .06709, 0, .59111], 95: [.31, .13444, .09811, 0, .59111], 97: [0, .44444, .09426, 0, .59111], 98: [0, .69444, .07861, 0, .53222], 99: [0, .44444, .05222, 0, .53222], 100: [0, .69444, .10861, 0, .59111], 101: [0, .44444, .085, 0, .53222], 102: [.19444, .69444, .21778, 0, .4], 103: [.19444, .44444, .105, 0, .53222], 104: [0, .69444, .09426, 0, .59111], 105: [0, .69326, .11387, 0, .35555], 106: [.19444, .69326, .1672, 0, .35555], 107: [0, .69444, .11111, 0, .53222], 108: [0, .69444, .10861, 0, .29666], 109: [0, .44444, .09426, 0, .94444], 110: [0, .44444, .09426, 0, .64999], 111: [0, .44444, .07861, 0, .59111], 112: [.19444, .44444, .07861, 0, .59111], 113: [.19444, .44444, .105, 0, .53222], 114: [0, .44444, .11111, 0, .50167], 115: [0, .44444, .08167, 0, .48694], 116: [0, .63492, .09639, 0, .385], 117: [0, .44444, .09426, 0, .62055], 118: [0, .44444, .11111, 0, .53222], 119: [0, .44444, .11111, 0, .76777], 120: [0, .44444, .12583, 0, .56055], 121: [.19444, .44444, .105, 0, .56166], 122: [0, .44444, .13889, 0, .49055], 126: [.35, .34444, .11472, 0, .59111], 160: [0, 0, 0, 0, .25], 168: [0, .69444, .11473, 0, .59111], 176: [0, .69444, 0, 0, .94888], 184: [.17014, 0, 0, 0, .53222], 198: [0, .68611, .11431, 0, 1.02277], 216: [.04861, .73472, .09062, 0, .88555], 223: [.19444, .69444, .09736, 0, .665], 230: [0, .44444, .085, 0, .82666], 248: [.09722, .54167, .09458, 0, .59111], 305: [0, .44444, .09426, 0, .35555], 338: [0, .68611, .11431, 0, 1.14054], 339: [0, .44444, .085, 0, .82666], 567: [.19444, .44444, .04611, 0, .385], 710: [0, .69444, .06709, 0, .59111], 711: [0, .63194, .08271, 0, .59111], 713: [0, .59444, .10444, 0, .59111], 714: [0, .69444, .08528, 0, .59111], 715: [0, .69444, 0, 0, .59111], 728: [0, .69444, .10333, 0, .59111], 729: [0, .69444, .12945, 0, .35555], 730: [0, .69444, 0, 0, .94888], 732: [0, .69444, .11472, 0, .59111], 733: [0, .69444, .11472, 0, .59111], 915: [0, .68611, .12903, 0, .69777], 916: [0, .68611, 0, 0, .94444], 920: [0, .68611, .09062, 0, .88555], 923: [0, .68611, 0, 0, .80666], 926: [0, .68611, .15092, 0, .76777], 928: [0, .68611, .17208, 0, .8961], 931: [0, .68611, .11431, 0, .82666], 933: [0, .68611, .10778, 0, .88555], 934: [0, .68611, .05632, 0, .82666], 936: [0, .68611, .10778, 0, .88555], 937: [0, .68611, .0992, 0, .82666], 8211: [0, .44444, .09811, 0, .59111], 8212: [0, .44444, .09811, 0, 1.18221], 8216: [0, .69444, .12945, 0, .35555], 8217: [0, .69444, .12945, 0, .35555], 8220: [0, .69444, .16772, 0, .62055], 8221: [0, .69444, .07939, 0, .62055] }, "Main-Italic": { 32: [0, 0, 0, 0, .25], 33: [0, .69444, .12417, 0, .30667], 34: [0, .69444, .06961, 0, .51444], 35: [.19444, .69444, .06616, 0, .81777], 37: [.05556, .75, .13639, 0, .81777], 38: [0, .69444, .09694, 0, .76666], 39: [0, .69444, .12417, 0, .30667], 40: [.25, .75, .16194, 0, .40889], 41: [.25, .75, .03694, 0, .40889], 42: [0, .75, .14917, 0, .51111], 43: [.05667, .56167, .03694, 0, .76666], 44: [.19444, .10556, 0, 0, .30667], 45: [0, .43056, .02826, 0, .35778], 46: [0, .10556, 0, 0, .30667], 47: [.25, .75, .16194, 0, .51111], 48: [0, .64444, .13556, 0, .51111], 49: [0, .64444, .13556, 0, .51111], 50: [0, .64444, .13556, 0, .51111], 51: [0, .64444, .13556, 0, .51111], 52: [.19444, .64444, .13556, 0, .51111], 53: [0, .64444, .13556, 0, .51111], 54: [0, .64444, .13556, 0, .51111], 55: [.19444, .64444, .13556, 0, .51111], 56: [0, .64444, .13556, 0, .51111], 57: [0, .64444, .13556, 0, .51111], 58: [0, .43056, .0582, 0, .30667], 59: [.19444, .43056, .0582, 0, .30667], 61: [-.13313, .36687, .06616, 0, .76666], 63: [0, .69444, .1225, 0, .51111], 64: [0, .69444, .09597, 0, .76666], 65: [0, .68333, 0, 0, .74333], 66: [0, .68333, .10257, 0, .70389], 67: [0, .68333, .14528, 0, .71555], 68: [0, .68333, .09403, 0, .755], 69: [0, .68333, .12028, 0, .67833], 70: [0, .68333, .13305, 0, .65277], 71: [0, .68333, .08722, 0, .77361], 72: [0, .68333, .16389, 0, .74333], 73: [0, .68333, .15806, 0, .38555], 74: [0, .68333, .14028, 0, .525], 75: [0, .68333, .14528, 0, .76888], 76: [0, .68333, 0, 0, .62722], 77: [0, .68333, .16389, 0, .89666], 78: [0, .68333, .16389, 0, .74333], 79: [0, .68333, .09403, 0, .76666], 80: [0, .68333, .10257, 0, .67833], 81: [.19444, .68333, .09403, 0, .76666], 82: [0, .68333, .03868, 0, .72944], 83: [0, .68333, .11972, 0, .56222], 84: [0, .68333, .13305, 0, .71555], 85: [0, .68333, .16389, 0, .74333], 86: [0, .68333, .18361, 0, .74333], 87: [0, .68333, .18361, 0, .99888], 88: [0, .68333, .15806, 0, .74333], 89: [0, .68333, .19383, 0, .74333], 90: [0, .68333, .14528, 0, .61333], 91: [.25, .75, .1875, 0, .30667], 93: [.25, .75, .10528, 0, .30667], 94: [0, .69444, .06646, 0, .51111], 95: [.31, .12056, .09208, 0, .51111], 97: [0, .43056, .07671, 0, .51111], 98: [0, .69444, .06312, 0, .46], 99: [0, .43056, .05653, 0, .46], 100: [0, .69444, .10333, 0, .51111], 101: [0, .43056, .07514, 0, .46], 102: [.19444, .69444, .21194, 0, .30667], 103: [.19444, .43056, .08847, 0, .46], 104: [0, .69444, .07671, 0, .51111], 105: [0, .65536, .1019, 0, .30667], 106: [.19444, .65536, .14467, 0, .30667], 107: [0, .69444, .10764, 0, .46], 108: [0, .69444, .10333, 0, .25555], 109: [0, .43056, .07671, 0, .81777], 110: [0, .43056, .07671, 0, .56222], 111: [0, .43056, .06312, 0, .51111], 112: [.19444, .43056, .06312, 0, .51111], 113: [.19444, .43056, .08847, 0, .46], 114: [0, .43056, .10764, 0, .42166], 115: [0, .43056, .08208, 0, .40889], 116: [0, .61508, .09486, 0, .33222], 117: [0, .43056, .07671, 0, .53666], 118: [0, .43056, .10764, 0, .46], 119: [0, .43056, .10764, 0, .66444], 120: [0, .43056, .12042, 0, .46389], 121: [.19444, .43056, .08847, 0, .48555], 122: [0, .43056, .12292, 0, .40889], 126: [.35, .31786, .11585, 0, .51111], 160: [0, 0, 0, 0, .25], 168: [0, .66786, .10474, 0, .51111], 176: [0, .69444, 0, 0, .83129], 184: [.17014, 0, 0, 0, .46], 198: [0, .68333, .12028, 0, .88277], 216: [.04861, .73194, .09403, 0, .76666], 223: [.19444, .69444, .10514, 0, .53666], 230: [0, .43056, .07514, 0, .71555], 248: [.09722, .52778, .09194, 0, .51111], 338: [0, .68333, .12028, 0, .98499], 339: [0, .43056, .07514, 0, .71555], 710: [0, .69444, .06646, 0, .51111], 711: [0, .62847, .08295, 0, .51111], 713: [0, .56167, .10333, 0, .51111], 714: [0, .69444, .09694, 0, .51111], 715: [0, .69444, 0, 0, .51111], 728: [0, .69444, .10806, 0, .51111], 729: [0, .66786, .11752, 0, .30667], 730: [0, .69444, 0, 0, .83129], 732: [0, .66786, .11585, 0, .51111], 733: [0, .69444, .1225, 0, .51111], 915: [0, .68333, .13305, 0, .62722], 916: [0, .68333, 0, 0, .81777], 920: [0, .68333, .09403, 0, .76666], 923: [0, .68333, 0, 0, .69222], 926: [0, .68333, .15294, 0, .66444], 928: [0, .68333, .16389, 0, .74333], 931: [0, .68333, .12028, 0, .71555], 933: [0, .68333, .11111, 0, .76666], 934: [0, .68333, .05986, 0, .71555], 936: [0, .68333, .11111, 0, .76666], 937: [0, .68333, .10257, 0, .71555], 8211: [0, .43056, .09208, 0, .51111], 8212: [0, .43056, .09208, 0, 1.02222], 8216: [0, .69444, .12417, 0, .30667], 8217: [0, .69444, .12417, 0, .30667], 8220: [0, .69444, .1685, 0, .51444], 8221: [0, .69444, .06961, 0, .51444], 8463: [0, .68889, 0, 0, .54028] }, "Main-Regular": { 32: [0, 0, 0, 0, .25], 33: [0, .69444, 0, 0, .27778], 34: [0, .69444, 0, 0, .5], 35: [.19444, .69444, 0, 0, .83334], 36: [.05556, .75, 0, 0, .5], 37: [.05556, .75, 0, 0, .83334], 38: [0, .69444, 0, 0, .77778], 39: [0, .69444, 0, 0, .27778], 40: [.25, .75, 0, 0, .38889], 41: [.25, .75, 0, 0, .38889], 42: [0, .75, 0, 0, .5], 43: [.08333, .58333, 0, 0, .77778], 44: [.19444, .10556, 0, 0, .27778], 45: [0, .43056, 0, 0, .33333], 46: [0, .10556, 0, 0, .27778], 47: [.25, .75, 0, 0, .5], 48: [0, .64444, 0, 0, .5], 49: [0, .64444, 0, 0, .5], 50: [0, .64444, 0, 0, .5], 51: [0, .64444, 0, 0, .5], 52: [0, .64444, 0, 0, .5], 53: [0, .64444, 0, 0, .5], 54: [0, .64444, 0, 0, .5], 55: [0, .64444, 0, 0, .5], 56: [0, .64444, 0, 0, .5], 57: [0, .64444, 0, 0, .5], 58: [0, .43056, 0, 0, .27778], 59: [.19444, .43056, 0, 0, .27778], 60: [.0391, .5391, 0, 0, .77778], 61: [-.13313, .36687, 0, 0, .77778], 62: [.0391, .5391, 0, 0, .77778], 63: [0, .69444, 0, 0, .47222], 64: [0, .69444, 0, 0, .77778], 65: [0, .68333, 0, 0, .75], 66: [0, .68333, 0, 0, .70834], 67: [0, .68333, 0, 0, .72222], 68: [0, .68333, 0, 0, .76389], 69: [0, .68333, 0, 0, .68056], 70: [0, .68333, 0, 0, .65278], 71: [0, .68333, 0, 0, .78472], 72: [0, .68333, 0, 0, .75], 73: [0, .68333, 0, 0, .36111], 74: [0, .68333, 0, 0, .51389], 75: [0, .68333, 0, 0, .77778], 76: [0, .68333, 0, 0, .625], 77: [0, .68333, 0, 0, .91667], 78: [0, .68333, 0, 0, .75], 79: [0, .68333, 0, 0, .77778], 80: [0, .68333, 0, 0, .68056], 81: [.19444, .68333, 0, 0, .77778], 82: [0, .68333, 0, 0, .73611], 83: [0, .68333, 0, 0, .55556], 84: [0, .68333, 0, 0, .72222], 85: [0, .68333, 0, 0, .75], 86: [0, .68333, .01389, 0, .75], 87: [0, .68333, .01389, 0, 1.02778], 88: [0, .68333, 0, 0, .75], 89: [0, .68333, .025, 0, .75], 90: [0, .68333, 0, 0, .61111], 91: [.25, .75, 0, 0, .27778], 92: [.25, .75, 0, 0, .5], 93: [.25, .75, 0, 0, .27778], 94: [0, .69444, 0, 0, .5], 95: [.31, .12056, .02778, 0, .5], 97: [0, .43056, 0, 0, .5], 98: [0, .69444, 0, 0, .55556], 99: [0, .43056, 0, 0, .44445], 100: [0, .69444, 0, 0, .55556], 101: [0, .43056, 0, 0, .44445], 102: [0, .69444, .07778, 0, .30556], 103: [.19444, .43056, .01389, 0, .5], 104: [0, .69444, 0, 0, .55556], 105: [0, .66786, 0, 0, .27778], 106: [.19444, .66786, 0, 0, .30556], 107: [0, .69444, 0, 0, .52778], 108: [0, .69444, 0, 0, .27778], 109: [0, .43056, 0, 0, .83334], 110: [0, .43056, 0, 0, .55556], 111: [0, .43056, 0, 0, .5], 112: [.19444, .43056, 0, 0, .55556], 113: [.19444, .43056, 0, 0, .52778], 114: [0, .43056, 0, 0, .39167], 115: [0, .43056, 0, 0, .39445], 116: [0, .61508, 0, 0, .38889], 117: [0, .43056, 0, 0, .55556], 118: [0, .43056, .01389, 0, .52778], 119: [0, .43056, .01389, 0, .72222], 120: [0, .43056, 0, 0, .52778], 121: [.19444, .43056, .01389, 0, .52778], 122: [0, .43056, 0, 0, .44445], 123: [.25, .75, 0, 0, .5], 124: [.25, .75, 0, 0, .27778], 125: [.25, .75, 0, 0, .5], 126: [.35, .31786, 0, 0, .5], 160: [0, 0, 0, 0, .25], 163: [0, .69444, 0, 0, .76909], 167: [.19444, .69444, 0, 0, .44445], 168: [0, .66786, 0, 0, .5], 172: [0, .43056, 0, 0, .66667], 176: [0, .69444, 0, 0, .75], 177: [.08333, .58333, 0, 0, .77778], 182: [.19444, .69444, 0, 0, .61111], 184: [.17014, 0, 0, 0, .44445], 198: [0, .68333, 0, 0, .90278], 215: [.08333, .58333, 0, 0, .77778], 216: [.04861, .73194, 0, 0, .77778], 223: [0, .69444, 0, 0, .5], 230: [0, .43056, 0, 0, .72222], 247: [.08333, .58333, 0, 0, .77778], 248: [.09722, .52778, 0, 0, .5], 305: [0, .43056, 0, 0, .27778], 338: [0, .68333, 0, 0, 1.01389], 339: [0, .43056, 0, 0, .77778], 567: [.19444, .43056, 0, 0, .30556], 710: [0, .69444, 0, 0, .5], 711: [0, .62847, 0, 0, .5], 713: [0, .56778, 0, 0, .5], 714: [0, .69444, 0, 0, .5], 715: [0, .69444, 0, 0, .5], 728: [0, .69444, 0, 0, .5], 729: [0, .66786, 0, 0, .27778], 730: [0, .69444, 0, 0, .75], 732: [0, .66786, 0, 0, .5], 733: [0, .69444, 0, 0, .5], 915: [0, .68333, 0, 0, .625], 916: [0, .68333, 0, 0, .83334], 920: [0, .68333, 0, 0, .77778], 923: [0, .68333, 0, 0, .69445], 926: [0, .68333, 0, 0, .66667], 928: [0, .68333, 0, 0, .75], 931: [0, .68333, 0, 0, .72222], 933: [0, .68333, 0, 0, .77778], 934: [0, .68333, 0, 0, .72222], 936: [0, .68333, 0, 0, .77778], 937: [0, .68333, 0, 0, .72222], 8211: [0, .43056, .02778, 0, .5], 8212: [0, .43056, .02778, 0, 1], 8216: [0, .69444, 0, 0, .27778], 8217: [0, .69444, 0, 0, .27778], 8220: [0, .69444, 0, 0, .5], 8221: [0, .69444, 0, 0, .5], 8224: [.19444, .69444, 0, 0, .44445], 8225: [.19444, .69444, 0, 0, .44445], 8230: [0, .123, 0, 0, 1.172], 8242: [0, .55556, 0, 0, .275], 8407: [0, .71444, .15382, 0, .5], 8463: [0, .68889, 0, 0, .54028], 8465: [0, .69444, 0, 0, .72222], 8467: [0, .69444, 0, .11111, .41667], 8472: [.19444, .43056, 0, .11111, .63646], 8476: [0, .69444, 0, 0, .72222], 8501: [0, .69444, 0, 0, .61111], 8592: [-.13313, .36687, 0, 0, 1], 8593: [.19444, .69444, 0, 0, .5], 8594: [-.13313, .36687, 0, 0, 1], 8595: [.19444, .69444, 0, 0, .5], 8596: [-.13313, .36687, 0, 0, 1], 8597: [.25, .75, 0, 0, .5], 8598: [.19444, .69444, 0, 0, 1], 8599: [.19444, .69444, 0, 0, 1], 8600: [.19444, .69444, 0, 0, 1], 8601: [.19444, .69444, 0, 0, 1], 8614: [.011, .511, 0, 0, 1], 8617: [.011, .511, 0, 0, 1.126], 8618: [.011, .511, 0, 0, 1.126], 8636: [-.13313, .36687, 0, 0, 1], 8637: [-.13313, .36687, 0, 0, 1], 8640: [-.13313, .36687, 0, 0, 1], 8641: [-.13313, .36687, 0, 0, 1], 8652: [.011, .671, 0, 0, 1], 8656: [-.13313, .36687, 0, 0, 1], 8657: [.19444, .69444, 0, 0, .61111], 8658: [-.13313, .36687, 0, 0, 1], 8659: [.19444, .69444, 0, 0, .61111], 8660: [-.13313, .36687, 0, 0, 1], 8661: [.25, .75, 0, 0, .61111], 8704: [0, .69444, 0, 0, .55556], 8706: [0, .69444, .05556, .08334, .5309], 8707: [0, .69444, 0, 0, .55556], 8709: [.05556, .75, 0, 0, .5], 8711: [0, .68333, 0, 0, .83334], 8712: [.0391, .5391, 0, 0, .66667], 8715: [.0391, .5391, 0, 0, .66667], 8722: [.08333, .58333, 0, 0, .77778], 8723: [.08333, .58333, 0, 0, .77778], 8725: [.25, .75, 0, 0, .5], 8726: [.25, .75, 0, 0, .5], 8727: [-.03472, .46528, 0, 0, .5], 8728: [-.05555, .44445, 0, 0, .5], 8729: [-.05555, .44445, 0, 0, .5], 8730: [.2, .8, 0, 0, .83334], 8733: [0, .43056, 0, 0, .77778], 8734: [0, .43056, 0, 0, 1], 8736: [0, .69224, 0, 0, .72222], 8739: [.25, .75, 0, 0, .27778], 8741: [.25, .75, 0, 0, .5], 8743: [0, .55556, 0, 0, .66667], 8744: [0, .55556, 0, 0, .66667], 8745: [0, .55556, 0, 0, .66667], 8746: [0, .55556, 0, 0, .66667], 8747: [.19444, .69444, .11111, 0, .41667], 8764: [-.13313, .36687, 0, 0, .77778], 8768: [.19444, .69444, 0, 0, .27778], 8771: [-.03625, .46375, 0, 0, .77778], 8773: [-.022, .589, 0, 0, .778], 8776: [-.01688, .48312, 0, 0, .77778], 8781: [-.03625, .46375, 0, 0, .77778], 8784: [-.133, .673, 0, 0, .778], 8801: [-.03625, .46375, 0, 0, .77778], 8804: [.13597, .63597, 0, 0, .77778], 8805: [.13597, .63597, 0, 0, .77778], 8810: [.0391, .5391, 0, 0, 1], 8811: [.0391, .5391, 0, 0, 1], 8826: [.0391, .5391, 0, 0, .77778], 8827: [.0391, .5391, 0, 0, .77778], 8834: [.0391, .5391, 0, 0, .77778], 8835: [.0391, .5391, 0, 0, .77778], 8838: [.13597, .63597, 0, 0, .77778], 8839: [.13597, .63597, 0, 0, .77778], 8846: [0, .55556, 0, 0, .66667], 8849: [.13597, .63597, 0, 0, .77778], 8850: [.13597, .63597, 0, 0, .77778], 8851: [0, .55556, 0, 0, .66667], 8852: [0, .55556, 0, 0, .66667], 8853: [.08333, .58333, 0, 0, .77778], 8854: [.08333, .58333, 0, 0, .77778], 8855: [.08333, .58333, 0, 0, .77778], 8856: [.08333, .58333, 0, 0, .77778], 8857: [.08333, .58333, 0, 0, .77778], 8866: [0, .69444, 0, 0, .61111], 8867: [0, .69444, 0, 0, .61111], 8868: [0, .69444, 0, 0, .77778], 8869: [0, .69444, 0, 0, .77778], 8872: [.249, .75, 0, 0, .867], 8900: [-.05555, .44445, 0, 0, .5], 8901: [-.05555, .44445, 0, 0, .27778], 8902: [-.03472, .46528, 0, 0, .5], 8904: [.005, .505, 0, 0, .9], 8942: [.03, .903, 0, 0, .278], 8943: [-.19, .313, 0, 0, 1.172], 8945: [-.1, .823, 0, 0, 1.282], 8968: [.25, .75, 0, 0, .44445], 8969: [.25, .75, 0, 0, .44445], 8970: [.25, .75, 0, 0, .44445], 8971: [.25, .75, 0, 0, .44445], 8994: [-.14236, .35764, 0, 0, 1], 8995: [-.14236, .35764, 0, 0, 1], 9136: [.244, .744, 0, 0, .412], 9137: [.244, .745, 0, 0, .412], 9651: [.19444, .69444, 0, 0, .88889], 9657: [-.03472, .46528, 0, 0, .5], 9661: [.19444, .69444, 0, 0, .88889], 9667: [-.03472, .46528, 0, 0, .5], 9711: [.19444, .69444, 0, 0, 1], 9824: [.12963, .69444, 0, 0, .77778], 9825: [.12963, .69444, 0, 0, .77778], 9826: [.12963, .69444, 0, 0, .77778], 9827: [.12963, .69444, 0, 0, .77778], 9837: [0, .75, 0, 0, .38889], 9838: [.19444, .69444, 0, 0, .38889], 9839: [.19444, .69444, 0, 0, .38889], 10216: [.25, .75, 0, 0, .38889], 10217: [.25, .75, 0, 0, .38889], 10222: [.244, .744, 0, 0, .412], 10223: [.244, .745, 0, 0, .412], 10229: [.011, .511, 0, 0, 1.609], 10230: [.011, .511, 0, 0, 1.638], 10231: [.011, .511, 0, 0, 1.859], 10232: [.024, .525, 0, 0, 1.609], 10233: [.024, .525, 0, 0, 1.638], 10234: [.024, .525, 0, 0, 1.858], 10236: [.011, .511, 0, 0, 1.638], 10815: [0, .68333, 0, 0, .75], 10927: [.13597, .63597, 0, 0, .77778], 10928: [.13597, .63597, 0, 0, .77778], 57376: [.19444, .69444, 0, 0, 0] }, "Math-BoldItalic": { 32: [0, 0, 0, 0, .25], 48: [0, .44444, 0, 0, .575], 49: [0, .44444, 0, 0, .575], 50: [0, .44444, 0, 0, .575], 51: [.19444, .44444, 0, 0, .575], 52: [.19444, .44444, 0, 0, .575], 53: [.19444, .44444, 0, 0, .575], 54: [0, .64444, 0, 0, .575], 55: [.19444, .44444, 0, 0, .575], 56: [0, .64444, 0, 0, .575], 57: [.19444, .44444, 0, 0, .575], 65: [0, .68611, 0, 0, .86944], 66: [0, .68611, .04835, 0, .8664], 67: [0, .68611, .06979, 0, .81694], 68: [0, .68611, .03194, 0, .93812], 69: [0, .68611, .05451, 0, .81007], 70: [0, .68611, .15972, 0, .68889], 71: [0, .68611, 0, 0, .88673], 72: [0, .68611, .08229, 0, .98229], 73: [0, .68611, .07778, 0, .51111], 74: [0, .68611, .10069, 0, .63125], 75: [0, .68611, .06979, 0, .97118], 76: [0, .68611, 0, 0, .75555], 77: [0, .68611, .11424, 0, 1.14201], 78: [0, .68611, .11424, 0, .95034], 79: [0, .68611, .03194, 0, .83666], 80: [0, .68611, .15972, 0, .72309], 81: [.19444, .68611, 0, 0, .86861], 82: [0, .68611, .00421, 0, .87235], 83: [0, .68611, .05382, 0, .69271], 84: [0, .68611, .15972, 0, .63663], 85: [0, .68611, .11424, 0, .80027], 86: [0, .68611, .25555, 0, .67778], 87: [0, .68611, .15972, 0, 1.09305], 88: [0, .68611, .07778, 0, .94722], 89: [0, .68611, .25555, 0, .67458], 90: [0, .68611, .06979, 0, .77257], 97: [0, .44444, 0, 0, .63287], 98: [0, .69444, 0, 0, .52083], 99: [0, .44444, 0, 0, .51342], 100: [0, .69444, 0, 0, .60972], 101: [0, .44444, 0, 0, .55361], 102: [.19444, .69444, .11042, 0, .56806], 103: [.19444, .44444, .03704, 0, .5449], 104: [0, .69444, 0, 0, .66759], 105: [0, .69326, 0, 0, .4048], 106: [.19444, .69326, .0622, 0, .47083], 107: [0, .69444, .01852, 0, .6037], 108: [0, .69444, .0088, 0, .34815], 109: [0, .44444, 0, 0, 1.0324], 110: [0, .44444, 0, 0, .71296], 111: [0, .44444, 0, 0, .58472], 112: [.19444, .44444, 0, 0, .60092], 113: [.19444, .44444, .03704, 0, .54213], 114: [0, .44444, .03194, 0, .5287], 115: [0, .44444, 0, 0, .53125], 116: [0, .63492, 0, 0, .41528], 117: [0, .44444, 0, 0, .68102], 118: [0, .44444, .03704, 0, .56666], 119: [0, .44444, .02778, 0, .83148], 120: [0, .44444, 0, 0, .65903], 121: [.19444, .44444, .03704, 0, .59028], 122: [0, .44444, .04213, 0, .55509], 160: [0, 0, 0, 0, .25], 915: [0, .68611, .15972, 0, .65694], 916: [0, .68611, 0, 0, .95833], 920: [0, .68611, .03194, 0, .86722], 923: [0, .68611, 0, 0, .80555], 926: [0, .68611, .07458, 0, .84125], 928: [0, .68611, .08229, 0, .98229], 931: [0, .68611, .05451, 0, .88507], 933: [0, .68611, .15972, 0, .67083], 934: [0, .68611, 0, 0, .76666], 936: [0, .68611, .11653, 0, .71402], 937: [0, .68611, .04835, 0, .8789], 945: [0, .44444, 0, 0, .76064], 946: [.19444, .69444, .03403, 0, .65972], 947: [.19444, .44444, .06389, 0, .59003], 948: [0, .69444, .03819, 0, .52222], 949: [0, .44444, 0, 0, .52882], 950: [.19444, .69444, .06215, 0, .50833], 951: [.19444, .44444, .03704, 0, .6], 952: [0, .69444, .03194, 0, .5618], 953: [0, .44444, 0, 0, .41204], 954: [0, .44444, 0, 0, .66759], 955: [0, .69444, 0, 0, .67083], 956: [.19444, .44444, 0, 0, .70787], 957: [0, .44444, .06898, 0, .57685], 958: [.19444, .69444, .03021, 0, .50833], 959: [0, .44444, 0, 0, .58472], 960: [0, .44444, .03704, 0, .68241], 961: [.19444, .44444, 0, 0, .6118], 962: [.09722, .44444, .07917, 0, .42361], 963: [0, .44444, .03704, 0, .68588], 964: [0, .44444, .13472, 0, .52083], 965: [0, .44444, .03704, 0, .63055], 966: [.19444, .44444, 0, 0, .74722], 967: [.19444, .44444, 0, 0, .71805], 968: [.19444, .69444, .03704, 0, .75833], 969: [0, .44444, .03704, 0, .71782], 977: [0, .69444, 0, 0, .69155], 981: [.19444, .69444, 0, 0, .7125], 982: [0, .44444, .03194, 0, .975], 1009: [.19444, .44444, 0, 0, .6118], 1013: [0, .44444, 0, 0, .48333], 57649: [0, .44444, 0, 0, .39352], 57911: [.19444, .44444, 0, 0, .43889] }, "Math-Italic": { 32: [0, 0, 0, 0, .25], 48: [0, .43056, 0, 0, .5], 49: [0, .43056, 0, 0, .5], 50: [0, .43056, 0, 0, .5], 51: [.19444, .43056, 0, 0, .5], 52: [.19444, .43056, 0, 0, .5], 53: [.19444, .43056, 0, 0, .5], 54: [0, .64444, 0, 0, .5], 55: [.19444, .43056, 0, 0, .5], 56: [0, .64444, 0, 0, .5], 57: [.19444, .43056, 0, 0, .5], 65: [0, .68333, 0, .13889, .75], 66: [0, .68333, .05017, .08334, .75851], 67: [0, .68333, .07153, .08334, .71472], 68: [0, .68333, .02778, .05556, .82792], 69: [0, .68333, .05764, .08334, .7382], 70: [0, .68333, .13889, .08334, .64306], 71: [0, .68333, 0, .08334, .78625], 72: [0, .68333, .08125, .05556, .83125], 73: [0, .68333, .07847, .11111, .43958], 74: [0, .68333, .09618, .16667, .55451], 75: [0, .68333, .07153, .05556, .84931], 76: [0, .68333, 0, .02778, .68056], 77: [0, .68333, .10903, .08334, .97014], 78: [0, .68333, .10903, .08334, .80347], 79: [0, .68333, .02778, .08334, .76278], 80: [0, .68333, .13889, .08334, .64201], 81: [.19444, .68333, 0, .08334, .79056], 82: [0, .68333, .00773, .08334, .75929], 83: [0, .68333, .05764, .08334, .6132], 84: [0, .68333, .13889, .08334, .58438], 85: [0, .68333, .10903, .02778, .68278], 86: [0, .68333, .22222, 0, .58333], 87: [0, .68333, .13889, 0, .94445], 88: [0, .68333, .07847, .08334, .82847], 89: [0, .68333, .22222, 0, .58056], 90: [0, .68333, .07153, .08334, .68264], 97: [0, .43056, 0, 0, .52859], 98: [0, .69444, 0, 0, .42917], 99: [0, .43056, 0, .05556, .43276], 100: [0, .69444, 0, .16667, .52049], 101: [0, .43056, 0, .05556, .46563], 102: [.19444, .69444, .10764, .16667, .48959], 103: [.19444, .43056, .03588, .02778, .47697], 104: [0, .69444, 0, 0, .57616], 105: [0, .65952, 0, 0, .34451], 106: [.19444, .65952, .05724, 0, .41181], 107: [0, .69444, .03148, 0, .5206], 108: [0, .69444, .01968, .08334, .29838], 109: [0, .43056, 0, 0, .87801], 110: [0, .43056, 0, 0, .60023], 111: [0, .43056, 0, .05556, .48472], 112: [.19444, .43056, 0, .08334, .50313], 113: [.19444, .43056, .03588, .08334, .44641], 114: [0, .43056, .02778, .05556, .45116], 115: [0, .43056, 0, .05556, .46875], 116: [0, .61508, 0, .08334, .36111], 117: [0, .43056, 0, .02778, .57246], 118: [0, .43056, .03588, .02778, .48472], 119: [0, .43056, .02691, .08334, .71592], 120: [0, .43056, 0, .02778, .57153], 121: [.19444, .43056, .03588, .05556, .49028], 122: [0, .43056, .04398, .05556, .46505], 160: [0, 0, 0, 0, .25], 915: [0, .68333, .13889, .08334, .61528], 916: [0, .68333, 0, .16667, .83334], 920: [0, .68333, .02778, .08334, .76278], 923: [0, .68333, 0, .16667, .69445], 926: [0, .68333, .07569, .08334, .74236], 928: [0, .68333, .08125, .05556, .83125], 931: [0, .68333, .05764, .08334, .77986], 933: [0, .68333, .13889, .05556, .58333], 934: [0, .68333, 0, .08334, .66667], 936: [0, .68333, .11, .05556, .61222], 937: [0, .68333, .05017, .08334, .7724], 945: [0, .43056, .0037, .02778, .6397], 946: [.19444, .69444, .05278, .08334, .56563], 947: [.19444, .43056, .05556, 0, .51773], 948: [0, .69444, .03785, .05556, .44444], 949: [0, .43056, 0, .08334, .46632], 950: [.19444, .69444, .07378, .08334, .4375], 951: [.19444, .43056, .03588, .05556, .49653], 952: [0, .69444, .02778, .08334, .46944], 953: [0, .43056, 0, .05556, .35394], 954: [0, .43056, 0, 0, .57616], 955: [0, .69444, 0, 0, .58334], 956: [.19444, .43056, 0, .02778, .60255], 957: [0, .43056, .06366, .02778, .49398], 958: [.19444, .69444, .04601, .11111, .4375], 959: [0, .43056, 0, .05556, .48472], 960: [0, .43056, .03588, 0, .57003], 961: [.19444, .43056, 0, .08334, .51702], 962: [.09722, .43056, .07986, .08334, .36285], 963: [0, .43056, .03588, 0, .57141], 964: [0, .43056, .1132, .02778, .43715], 965: [0, .43056, .03588, .02778, .54028], 966: [.19444, .43056, 0, .08334, .65417], 967: [.19444, .43056, 0, .05556, .62569], 968: [.19444, .69444, .03588, .11111, .65139], 969: [0, .43056, .03588, 0, .62245], 977: [0, .69444, 0, .08334, .59144], 981: [.19444, .69444, 0, .08334, .59583], 982: [0, .43056, .02778, 0, .82813], 1009: [.19444, .43056, 0, .08334, .51702], 1013: [0, .43056, 0, .05556, .4059], 57649: [0, .43056, 0, .02778, .32246], 57911: [.19444, .43056, 0, .08334, .38403] }, "SansSerif-Bold": { 32: [0, 0, 0, 0, .25], 33: [0, .69444, 0, 0, .36667], 34: [0, .69444, 0, 0, .55834], 35: [.19444, .69444, 0, 0, .91667], 36: [.05556, .75, 0, 0, .55], 37: [.05556, .75, 0, 0, 1.02912], 38: [0, .69444, 0, 0, .83056], 39: [0, .69444, 0, 0, .30556], 40: [.25, .75, 0, 0, .42778], 41: [.25, .75, 0, 0, .42778], 42: [0, .75, 0, 0, .55], 43: [.11667, .61667, 0, 0, .85556], 44: [.10556, .13056, 0, 0, .30556], 45: [0, .45833, 0, 0, .36667], 46: [0, .13056, 0, 0, .30556], 47: [.25, .75, 0, 0, .55], 48: [0, .69444, 0, 0, .55], 49: [0, .69444, 0, 0, .55], 50: [0, .69444, 0, 0, .55], 51: [0, .69444, 0, 0, .55], 52: [0, .69444, 0, 0, .55], 53: [0, .69444, 0, 0, .55], 54: [0, .69444, 0, 0, .55], 55: [0, .69444, 0, 0, .55], 56: [0, .69444, 0, 0, .55], 57: [0, .69444, 0, 0, .55], 58: [0, .45833, 0, 0, .30556], 59: [.10556, .45833, 0, 0, .30556], 61: [-.09375, .40625, 0, 0, .85556], 63: [0, .69444, 0, 0, .51945], 64: [0, .69444, 0, 0, .73334], 65: [0, .69444, 0, 0, .73334], 66: [0, .69444, 0, 0, .73334], 67: [0, .69444, 0, 0, .70278], 68: [0, .69444, 0, 0, .79445], 69: [0, .69444, 0, 0, .64167], 70: [0, .69444, 0, 0, .61111], 71: [0, .69444, 0, 0, .73334], 72: [0, .69444, 0, 0, .79445], 73: [0, .69444, 0, 0, .33056], 74: [0, .69444, 0, 0, .51945], 75: [0, .69444, 0, 0, .76389], 76: [0, .69444, 0, 0, .58056], 77: [0, .69444, 0, 0, .97778], 78: [0, .69444, 0, 0, .79445], 79: [0, .69444, 0, 0, .79445], 80: [0, .69444, 0, 0, .70278], 81: [.10556, .69444, 0, 0, .79445], 82: [0, .69444, 0, 0, .70278], 83: [0, .69444, 0, 0, .61111], 84: [0, .69444, 0, 0, .73334], 85: [0, .69444, 0, 0, .76389], 86: [0, .69444, .01528, 0, .73334], 87: [0, .69444, .01528, 0, 1.03889], 88: [0, .69444, 0, 0, .73334], 89: [0, .69444, .0275, 0, .73334], 90: [0, .69444, 0, 0, .67223], 91: [.25, .75, 0, 0, .34306], 93: [.25, .75, 0, 0, .34306], 94: [0, .69444, 0, 0, .55], 95: [.35, .10833, .03056, 0, .55], 97: [0, .45833, 0, 0, .525], 98: [0, .69444, 0, 0, .56111], 99: [0, .45833, 0, 0, .48889], 100: [0, .69444, 0, 0, .56111], 101: [0, .45833, 0, 0, .51111], 102: [0, .69444, .07639, 0, .33611], 103: [.19444, .45833, .01528, 0, .55], 104: [0, .69444, 0, 0, .56111], 105: [0, .69444, 0, 0, .25556], 106: [.19444, .69444, 0, 0, .28611], 107: [0, .69444, 0, 0, .53056], 108: [0, .69444, 0, 0, .25556], 109: [0, .45833, 0, 0, .86667], 110: [0, .45833, 0, 0, .56111], 111: [0, .45833, 0, 0, .55], 112: [.19444, .45833, 0, 0, .56111], 113: [.19444, .45833, 0, 0, .56111], 114: [0, .45833, .01528, 0, .37222], 115: [0, .45833, 0, 0, .42167], 116: [0, .58929, 0, 0, .40417], 117: [0, .45833, 0, 0, .56111], 118: [0, .45833, .01528, 0, .5], 119: [0, .45833, .01528, 0, .74445], 120: [0, .45833, 0, 0, .5], 121: [.19444, .45833, .01528, 0, .5], 122: [0, .45833, 0, 0, .47639], 126: [.35, .34444, 0, 0, .55], 160: [0, 0, 0, 0, .25], 168: [0, .69444, 0, 0, .55], 176: [0, .69444, 0, 0, .73334], 180: [0, .69444, 0, 0, .55], 184: [.17014, 0, 0, 0, .48889], 305: [0, .45833, 0, 0, .25556], 567: [.19444, .45833, 0, 0, .28611], 710: [0, .69444, 0, 0, .55], 711: [0, .63542, 0, 0, .55], 713: [0, .63778, 0, 0, .55], 728: [0, .69444, 0, 0, .55], 729: [0, .69444, 0, 0, .30556], 730: [0, .69444, 0, 0, .73334], 732: [0, .69444, 0, 0, .55], 733: [0, .69444, 0, 0, .55], 915: [0, .69444, 0, 0, .58056], 916: [0, .69444, 0, 0, .91667], 920: [0, .69444, 0, 0, .85556], 923: [0, .69444, 0, 0, .67223], 926: [0, .69444, 0, 0, .73334], 928: [0, .69444, 0, 0, .79445], 931: [0, .69444, 0, 0, .79445], 933: [0, .69444, 0, 0, .85556], 934: [0, .69444, 0, 0, .79445], 936: [0, .69444, 0, 0, .85556], 937: [0, .69444, 0, 0, .79445], 8211: [0, .45833, .03056, 0, .55], 8212: [0, .45833, .03056, 0, 1.10001], 8216: [0, .69444, 0, 0, .30556], 8217: [0, .69444, 0, 0, .30556], 8220: [0, .69444, 0, 0, .55834], 8221: [0, .69444, 0, 0, .55834] }, "SansSerif-Italic": { 32: [0, 0, 0, 0, .25], 33: [0, .69444, .05733, 0, .31945], 34: [0, .69444, .00316, 0, .5], 35: [.19444, .69444, .05087, 0, .83334], 36: [.05556, .75, .11156, 0, .5], 37: [.05556, .75, .03126, 0, .83334], 38: [0, .69444, .03058, 0, .75834], 39: [0, .69444, .07816, 0, .27778], 40: [.25, .75, .13164, 0, .38889], 41: [.25, .75, .02536, 0, .38889], 42: [0, .75, .11775, 0, .5], 43: [.08333, .58333, .02536, 0, .77778], 44: [.125, .08333, 0, 0, .27778], 45: [0, .44444, .01946, 0, .33333], 46: [0, .08333, 0, 0, .27778], 47: [.25, .75, .13164, 0, .5], 48: [0, .65556, .11156, 0, .5], 49: [0, .65556, .11156, 0, .5], 50: [0, .65556, .11156, 0, .5], 51: [0, .65556, .11156, 0, .5], 52: [0, .65556, .11156, 0, .5], 53: [0, .65556, .11156, 0, .5], 54: [0, .65556, .11156, 0, .5], 55: [0, .65556, .11156, 0, .5], 56: [0, .65556, .11156, 0, .5], 57: [0, .65556, .11156, 0, .5], 58: [0, .44444, .02502, 0, .27778], 59: [.125, .44444, .02502, 0, .27778], 61: [-.13, .37, .05087, 0, .77778], 63: [0, .69444, .11809, 0, .47222], 64: [0, .69444, .07555, 0, .66667], 65: [0, .69444, 0, 0, .66667], 66: [0, .69444, .08293, 0, .66667], 67: [0, .69444, .11983, 0, .63889], 68: [0, .69444, .07555, 0, .72223], 69: [0, .69444, .11983, 0, .59722], 70: [0, .69444, .13372, 0, .56945], 71: [0, .69444, .11983, 0, .66667], 72: [0, .69444, .08094, 0, .70834], 73: [0, .69444, .13372, 0, .27778], 74: [0, .69444, .08094, 0, .47222], 75: [0, .69444, .11983, 0, .69445], 76: [0, .69444, 0, 0, .54167], 77: [0, .69444, .08094, 0, .875], 78: [0, .69444, .08094, 0, .70834], 79: [0, .69444, .07555, 0, .73611], 80: [0, .69444, .08293, 0, .63889], 81: [.125, .69444, .07555, 0, .73611], 82: [0, .69444, .08293, 0, .64584], 83: [0, .69444, .09205, 0, .55556], 84: [0, .69444, .13372, 0, .68056], 85: [0, .69444, .08094, 0, .6875], 86: [0, .69444, .1615, 0, .66667], 87: [0, .69444, .1615, 0, .94445], 88: [0, .69444, .13372, 0, .66667], 89: [0, .69444, .17261, 0, .66667], 90: [0, .69444, .11983, 0, .61111], 91: [.25, .75, .15942, 0, .28889], 93: [.25, .75, .08719, 0, .28889], 94: [0, .69444, .0799, 0, .5], 95: [.35, .09444, .08616, 0, .5], 97: [0, .44444, .00981, 0, .48056], 98: [0, .69444, .03057, 0, .51667], 99: [0, .44444, .08336, 0, .44445], 100: [0, .69444, .09483, 0, .51667], 101: [0, .44444, .06778, 0, .44445], 102: [0, .69444, .21705, 0, .30556], 103: [.19444, .44444, .10836, 0, .5], 104: [0, .69444, .01778, 0, .51667], 105: [0, .67937, .09718, 0, .23889], 106: [.19444, .67937, .09162, 0, .26667], 107: [0, .69444, .08336, 0, .48889], 108: [0, .69444, .09483, 0, .23889], 109: [0, .44444, .01778, 0, .79445], 110: [0, .44444, .01778, 0, .51667], 111: [0, .44444, .06613, 0, .5], 112: [.19444, .44444, .0389, 0, .51667], 113: [.19444, .44444, .04169, 0, .51667], 114: [0, .44444, .10836, 0, .34167], 115: [0, .44444, .0778, 0, .38333], 116: [0, .57143, .07225, 0, .36111], 117: [0, .44444, .04169, 0, .51667], 118: [0, .44444, .10836, 0, .46111], 119: [0, .44444, .10836, 0, .68334], 120: [0, .44444, .09169, 0, .46111], 121: [.19444, .44444, .10836, 0, .46111], 122: [0, .44444, .08752, 0, .43472], 126: [.35, .32659, .08826, 0, .5], 160: [0, 0, 0, 0, .25], 168: [0, .67937, .06385, 0, .5], 176: [0, .69444, 0, 0, .73752], 184: [.17014, 0, 0, 0, .44445], 305: [0, .44444, .04169, 0, .23889], 567: [.19444, .44444, .04169, 0, .26667], 710: [0, .69444, .0799, 0, .5], 711: [0, .63194, .08432, 0, .5], 713: [0, .60889, .08776, 0, .5], 714: [0, .69444, .09205, 0, .5], 715: [0, .69444, 0, 0, .5], 728: [0, .69444, .09483, 0, .5], 729: [0, .67937, .07774, 0, .27778], 730: [0, .69444, 0, 0, .73752], 732: [0, .67659, .08826, 0, .5], 733: [0, .69444, .09205, 0, .5], 915: [0, .69444, .13372, 0, .54167], 916: [0, .69444, 0, 0, .83334], 920: [0, .69444, .07555, 0, .77778], 923: [0, .69444, 0, 0, .61111], 926: [0, .69444, .12816, 0, .66667], 928: [0, .69444, .08094, 0, .70834], 931: [0, .69444, .11983, 0, .72222], 933: [0, .69444, .09031, 0, .77778], 934: [0, .69444, .04603, 0, .72222], 936: [0, .69444, .09031, 0, .77778], 937: [0, .69444, .08293, 0, .72222], 8211: [0, .44444, .08616, 0, .5], 8212: [0, .44444, .08616, 0, 1], 8216: [0, .69444, .07816, 0, .27778], 8217: [0, .69444, .07816, 0, .27778], 8220: [0, .69444, .14205, 0, .5], 8221: [0, .69444, .00316, 0, .5] }, "SansSerif-Regular": { 32: [0, 0, 0, 0, .25], 33: [0, .69444, 0, 0, .31945], 34: [0, .69444, 0, 0, .5], 35: [.19444, .69444, 0, 0, .83334], 36: [.05556, .75, 0, 0, .5], 37: [.05556, .75, 0, 0, .83334], 38: [0, .69444, 0, 0, .75834], 39: [0, .69444, 0, 0, .27778], 40: [.25, .75, 0, 0, .38889], 41: [.25, .75, 0, 0, .38889], 42: [0, .75, 0, 0, .5], 43: [.08333, .58333, 0, 0, .77778], 44: [.125, .08333, 0, 0, .27778], 45: [0, .44444, 0, 0, .33333], 46: [0, .08333, 0, 0, .27778], 47: [.25, .75, 0, 0, .5], 48: [0, .65556, 0, 0, .5], 49: [0, .65556, 0, 0, .5], 50: [0, .65556, 0, 0, .5], 51: [0, .65556, 0, 0, .5], 52: [0, .65556, 0, 0, .5], 53: [0, .65556, 0, 0, .5], 54: [0, .65556, 0, 0, .5], 55: [0, .65556, 0, 0, .5], 56: [0, .65556, 0, 0, .5], 57: [0, .65556, 0, 0, .5], 58: [0, .44444, 0, 0, .27778], 59: [.125, .44444, 0, 0, .27778], 61: [-.13, .37, 0, 0, .77778], 63: [0, .69444, 0, 0, .47222], 64: [0, .69444, 0, 0, .66667], 65: [0, .69444, 0, 0, .66667], 66: [0, .69444, 0, 0, .66667], 67: [0, .69444, 0, 0, .63889], 68: [0, .69444, 0, 0, .72223], 69: [0, .69444, 0, 0, .59722], 70: [0, .69444, 0, 0, .56945], 71: [0, .69444, 0, 0, .66667], 72: [0, .69444, 0, 0, .70834], 73: [0, .69444, 0, 0, .27778], 74: [0, .69444, 0, 0, .47222], 75: [0, .69444, 0, 0, .69445], 76: [0, .69444, 0, 0, .54167], 77: [0, .69444, 0, 0, .875], 78: [0, .69444, 0, 0, .70834], 79: [0, .69444, 0, 0, .73611], 80: [0, .69444, 0, 0, .63889], 81: [.125, .69444, 0, 0, .73611], 82: [0, .69444, 0, 0, .64584], 83: [0, .69444, 0, 0, .55556], 84: [0, .69444, 0, 0, .68056], 85: [0, .69444, 0, 0, .6875], 86: [0, .69444, .01389, 0, .66667], 87: [0, .69444, .01389, 0, .94445], 88: [0, .69444, 0, 0, .66667], 89: [0, .69444, .025, 0, .66667], 90: [0, .69444, 0, 0, .61111], 91: [.25, .75, 0, 0, .28889], 93: [.25, .75, 0, 0, .28889], 94: [0, .69444, 0, 0, .5], 95: [.35, .09444, .02778, 0, .5], 97: [0, .44444, 0, 0, .48056], 98: [0, .69444, 0, 0, .51667], 99: [0, .44444, 0, 0, .44445], 100: [0, .69444, 0, 0, .51667], 101: [0, .44444, 0, 0, .44445], 102: [0, .69444, .06944, 0, .30556], 103: [.19444, .44444, .01389, 0, .5], 104: [0, .69444, 0, 0, .51667], 105: [0, .67937, 0, 0, .23889], 106: [.19444, .67937, 0, 0, .26667], 107: [0, .69444, 0, 0, .48889], 108: [0, .69444, 0, 0, .23889], 109: [0, .44444, 0, 0, .79445], 110: [0, .44444, 0, 0, .51667], 111: [0, .44444, 0, 0, .5], 112: [.19444, .44444, 0, 0, .51667], 113: [.19444, .44444, 0, 0, .51667], 114: [0, .44444, .01389, 0, .34167], 115: [0, .44444, 0, 0, .38333], 116: [0, .57143, 0, 0, .36111], 117: [0, .44444, 0, 0, .51667], 118: [0, .44444, .01389, 0, .46111], 119: [0, .44444, .01389, 0, .68334], 120: [0, .44444, 0, 0, .46111], 121: [.19444, .44444, .01389, 0, .46111], 122: [0, .44444, 0, 0, .43472], 126: [.35, .32659, 0, 0, .5], 160: [0, 0, 0, 0, .25], 168: [0, .67937, 0, 0, .5], 176: [0, .69444, 0, 0, .66667], 184: [.17014, 0, 0, 0, .44445], 305: [0, .44444, 0, 0, .23889], 567: [.19444, .44444, 0, 0, .26667], 710: [0, .69444, 0, 0, .5], 711: [0, .63194, 0, 0, .5], 713: [0, .60889, 0, 0, .5], 714: [0, .69444, 0, 0, .5], 715: [0, .69444, 0, 0, .5], 728: [0, .69444, 0, 0, .5], 729: [0, .67937, 0, 0, .27778], 730: [0, .69444, 0, 0, .66667], 732: [0, .67659, 0, 0, .5], 733: [0, .69444, 0, 0, .5], 915: [0, .69444, 0, 0, .54167], 916: [0, .69444, 0, 0, .83334], 920: [0, .69444, 0, 0, .77778], 923: [0, .69444, 0, 0, .61111], 926: [0, .69444, 0, 0, .66667], 928: [0, .69444, 0, 0, .70834], 931: [0, .69444, 0, 0, .72222], 933: [0, .69444, 0, 0, .77778], 934: [0, .69444, 0, 0, .72222], 936: [0, .69444, 0, 0, .77778], 937: [0, .69444, 0, 0, .72222], 8211: [0, .44444, .02778, 0, .5], 8212: [0, .44444, .02778, 0, 1], 8216: [0, .69444, 0, 0, .27778], 8217: [0, .69444, 0, 0, .27778], 8220: [0, .69444, 0, 0, .5], 8221: [0, .69444, 0, 0, .5] }, "Script-Regular": { 32: [0, 0, 0, 0, .25], 65: [0, .7, .22925, 0, .80253], 66: [0, .7, .04087, 0, .90757], 67: [0, .7, .1689, 0, .66619], 68: [0, .7, .09371, 0, .77443], 69: [0, .7, .18583, 0, .56162], 70: [0, .7, .13634, 0, .89544], 71: [0, .7, .17322, 0, .60961], 72: [0, .7, .29694, 0, .96919], 73: [0, .7, .19189, 0, .80907], 74: [.27778, .7, .19189, 0, 1.05159], 75: [0, .7, .31259, 0, .91364], 76: [0, .7, .19189, 0, .87373], 77: [0, .7, .15981, 0, 1.08031], 78: [0, .7, .3525, 0, .9015], 79: [0, .7, .08078, 0, .73787], 80: [0, .7, .08078, 0, 1.01262], 81: [0, .7, .03305, 0, .88282], 82: [0, .7, .06259, 0, .85], 83: [0, .7, .19189, 0, .86767], 84: [0, .7, .29087, 0, .74697], 85: [0, .7, .25815, 0, .79996], 86: [0, .7, .27523, 0, .62204], 87: [0, .7, .27523, 0, .80532], 88: [0, .7, .26006, 0, .94445], 89: [0, .7, .2939, 0, .70961], 90: [0, .7, .24037, 0, .8212], 160: [0, 0, 0, 0, .25] }, "Size1-Regular": { 32: [0, 0, 0, 0, .25], 40: [.35001, .85, 0, 0, .45834], 41: [.35001, .85, 0, 0, .45834], 47: [.35001, .85, 0, 0, .57778], 91: [.35001, .85, 0, 0, .41667], 92: [.35001, .85, 0, 0, .57778], 93: [.35001, .85, 0, 0, .41667], 123: [.35001, .85, 0, 0, .58334], 125: [.35001, .85, 0, 0, .58334], 160: [0, 0, 0, 0, .25], 710: [0, .72222, 0, 0, .55556], 732: [0, .72222, 0, 0, .55556], 770: [0, .72222, 0, 0, .55556], 771: [0, .72222, 0, 0, .55556], 8214: [-99e-5, .601, 0, 0, .77778], 8593: [1e-5, .6, 0, 0, .66667], 8595: [1e-5, .6, 0, 0, .66667], 8657: [1e-5, .6, 0, 0, .77778], 8659: [1e-5, .6, 0, 0, .77778], 8719: [.25001, .75, 0, 0, .94445], 8720: [.25001, .75, 0, 0, .94445], 8721: [.25001, .75, 0, 0, 1.05556], 8730: [.35001, .85, 0, 0, 1], 8739: [-.00599, .606, 0, 0, .33333], 8741: [-.00599, .606, 0, 0, .55556], 8747: [.30612, .805, .19445, 0, .47222], 8748: [.306, .805, .19445, 0, .47222], 8749: [.306, .805, .19445, 0, .47222], 8750: [.30612, .805, .19445, 0, .47222], 8896: [.25001, .75, 0, 0, .83334], 8897: [.25001, .75, 0, 0, .83334], 8898: [.25001, .75, 0, 0, .83334], 8899: [.25001, .75, 0, 0, .83334], 8968: [.35001, .85, 0, 0, .47222], 8969: [.35001, .85, 0, 0, .47222], 8970: [.35001, .85, 0, 0, .47222], 8971: [.35001, .85, 0, 0, .47222], 9168: [-99e-5, .601, 0, 0, .66667], 10216: [.35001, .85, 0, 0, .47222], 10217: [.35001, .85, 0, 0, .47222], 10752: [.25001, .75, 0, 0, 1.11111], 10753: [.25001, .75, 0, 0, 1.11111], 10754: [.25001, .75, 0, 0, 1.11111], 10756: [.25001, .75, 0, 0, .83334], 10758: [.25001, .75, 0, 0, .83334] }, "Size2-Regular": { 32: [0, 0, 0, 0, .25], 40: [.65002, 1.15, 0, 0, .59722], 41: [.65002, 1.15, 0, 0, .59722], 47: [.65002, 1.15, 0, 0, .81111], 91: [.65002, 1.15, 0, 0, .47222], 92: [.65002, 1.15, 0, 0, .81111], 93: [.65002, 1.15, 0, 0, .47222], 123: [.65002, 1.15, 0, 0, .66667], 125: [.65002, 1.15, 0, 0, .66667], 160: [0, 0, 0, 0, .25], 710: [0, .75, 0, 0, 1], 732: [0, .75, 0, 0, 1], 770: [0, .75, 0, 0, 1], 771: [0, .75, 0, 0, 1], 8719: [.55001, 1.05, 0, 0, 1.27778], 8720: [.55001, 1.05, 0, 0, 1.27778], 8721: [.55001, 1.05, 0, 0, 1.44445], 8730: [.65002, 1.15, 0, 0, 1], 8747: [.86225, 1.36, .44445, 0, .55556], 8748: [.862, 1.36, .44445, 0, .55556], 8749: [.862, 1.36, .44445, 0, .55556], 8750: [.86225, 1.36, .44445, 0, .55556], 8896: [.55001, 1.05, 0, 0, 1.11111], 8897: [.55001, 1.05, 0, 0, 1.11111], 8898: [.55001, 1.05, 0, 0, 1.11111], 8899: [.55001, 1.05, 0, 0, 1.11111], 8968: [.65002, 1.15, 0, 0, .52778], 8969: [.65002, 1.15, 0, 0, .52778], 8970: [.65002, 1.15, 0, 0, .52778], 8971: [.65002, 1.15, 0, 0, .52778], 10216: [.65002, 1.15, 0, 0, .61111], 10217: [.65002, 1.15, 0, 0, .61111], 10752: [.55001, 1.05, 0, 0, 1.51112], 10753: [.55001, 1.05, 0, 0, 1.51112], 10754: [.55001, 1.05, 0, 0, 1.51112], 10756: [.55001, 1.05, 0, 0, 1.11111], 10758: [.55001, 1.05, 0, 0, 1.11111] }, "Size3-Regular": { 32: [0, 0, 0, 0, .25], 40: [.95003, 1.45, 0, 0, .73611], 41: [.95003, 1.45, 0, 0, .73611], 47: [.95003, 1.45, 0, 0, 1.04445], 91: [.95003, 1.45, 0, 0, .52778], 92: [.95003, 1.45, 0, 0, 1.04445], 93: [.95003, 1.45, 0, 0, .52778], 123: [.95003, 1.45, 0, 0, .75], 125: [.95003, 1.45, 0, 0, .75], 160: [0, 0, 0, 0, .25], 710: [0, .75, 0, 0, 1.44445], 732: [0, .75, 0, 0, 1.44445], 770: [0, .75, 0, 0, 1.44445], 771: [0, .75, 0, 0, 1.44445], 8730: [.95003, 1.45, 0, 0, 1], 8968: [.95003, 1.45, 0, 0, .58334], 8969: [.95003, 1.45, 0, 0, .58334], 8970: [.95003, 1.45, 0, 0, .58334], 8971: [.95003, 1.45, 0, 0, .58334], 10216: [.95003, 1.45, 0, 0, .75], 10217: [.95003, 1.45, 0, 0, .75] }, "Size4-Regular": { 32: [0, 0, 0, 0, .25], 40: [1.25003, 1.75, 0, 0, .79167], 41: [1.25003, 1.75, 0, 0, .79167], 47: [1.25003, 1.75, 0, 0, 1.27778], 91: [1.25003, 1.75, 0, 0, .58334], 92: [1.25003, 1.75, 0, 0, 1.27778], 93: [1.25003, 1.75, 0, 0, .58334], 123: [1.25003, 1.75, 0, 0, .80556], 125: [1.25003, 1.75, 0, 0, .80556], 160: [0, 0, 0, 0, .25], 710: [0, .825, 0, 0, 1.8889], 732: [0, .825, 0, 0, 1.8889], 770: [0, .825, 0, 0, 1.8889], 771: [0, .825, 0, 0, 1.8889], 8730: [1.25003, 1.75, 0, 0, 1], 8968: [1.25003, 1.75, 0, 0, .63889], 8969: [1.25003, 1.75, 0, 0, .63889], 8970: [1.25003, 1.75, 0, 0, .63889], 8971: [1.25003, 1.75, 0, 0, .63889], 9115: [.64502, 1.155, 0, 0, .875], 9116: [1e-5, .6, 0, 0, .875], 9117: [.64502, 1.155, 0, 0, .875], 9118: [.64502, 1.155, 0, 0, .875], 9119: [1e-5, .6, 0, 0, .875], 9120: [.64502, 1.155, 0, 0, .875], 9121: [.64502, 1.155, 0, 0, .66667], 9122: [-99e-5, .601, 0, 0, .66667], 9123: [.64502, 1.155, 0, 0, .66667], 9124: [.64502, 1.155, 0, 0, .66667], 9125: [-99e-5, .601, 0, 0, .66667], 9126: [.64502, 1.155, 0, 0, .66667], 9127: [1e-5, .9, 0, 0, .88889], 9128: [.65002, 1.15, 0, 0, .88889], 9129: [.90001, 0, 0, 0, .88889], 9130: [0, .3, 0, 0, .88889], 9131: [1e-5, .9, 0, 0, .88889], 9132: [.65002, 1.15, 0, 0, .88889], 9133: [.90001, 0, 0, 0, .88889], 9143: [.88502, .915, 0, 0, 1.05556], 10216: [1.25003, 1.75, 0, 0, .80556], 10217: [1.25003, 1.75, 0, 0, .80556], 57344: [-.00499, .605, 0, 0, 1.05556], 57345: [-.00499, .605, 0, 0, 1.05556], 57680: [0, .12, 0, 0, .45], 57681: [0, .12, 0, 0, .45], 57682: [0, .12, 0, 0, .45], 57683: [0, .12, 0, 0, .45] }, "Typewriter-Regular": { 32: [0, 0, 0, 0, .525], 33: [0, .61111, 0, 0, .525], 34: [0, .61111, 0, 0, .525], 35: [0, .61111, 0, 0, .525], 36: [.08333, .69444, 0, 0, .525], 37: [.08333, .69444, 0, 0, .525], 38: [0, .61111, 0, 0, .525], 39: [0, .61111, 0, 0, .525], 40: [.08333, .69444, 0, 0, .525], 41: [.08333, .69444, 0, 0, .525], 42: [0, .52083, 0, 0, .525], 43: [-.08056, .53055, 0, 0, .525], 44: [.13889, .125, 0, 0, .525], 45: [-.08056, .53055, 0, 0, .525], 46: [0, .125, 0, 0, .525], 47: [.08333, .69444, 0, 0, .525], 48: [0, .61111, 0, 0, .525], 49: [0, .61111, 0, 0, .525], 50: [0, .61111, 0, 0, .525], 51: [0, .61111, 0, 0, .525], 52: [0, .61111, 0, 0, .525], 53: [0, .61111, 0, 0, .525], 54: [0, .61111, 0, 0, .525], 55: [0, .61111, 0, 0, .525], 56: [0, .61111, 0, 0, .525], 57: [0, .61111, 0, 0, .525], 58: [0, .43056, 0, 0, .525], 59: [.13889, .43056, 0, 0, .525], 60: [-.05556, .55556, 0, 0, .525], 61: [-.19549, .41562, 0, 0, .525], 62: [-.05556, .55556, 0, 0, .525], 63: [0, .61111, 0, 0, .525], 64: [0, .61111, 0, 0, .525], 65: [0, .61111, 0, 0, .525], 66: [0, .61111, 0, 0, .525], 67: [0, .61111, 0, 0, .525], 68: [0, .61111, 0, 0, .525], 69: [0, .61111, 0, 0, .525], 70: [0, .61111, 0, 0, .525], 71: [0, .61111, 0, 0, .525], 72: [0, .61111, 0, 0, .525], 73: [0, .61111, 0, 0, .525], 74: [0, .61111, 0, 0, .525], 75: [0, .61111, 0, 0, .525], 76: [0, .61111, 0, 0, .525], 77: [0, .61111, 0, 0, .525], 78: [0, .61111, 0, 0, .525], 79: [0, .61111, 0, 0, .525], 80: [0, .61111, 0, 0, .525], 81: [.13889, .61111, 0, 0, .525], 82: [0, .61111, 0, 0, .525], 83: [0, .61111, 0, 0, .525], 84: [0, .61111, 0, 0, .525], 85: [0, .61111, 0, 0, .525], 86: [0, .61111, 0, 0, .525], 87: [0, .61111, 0, 0, .525], 88: [0, .61111, 0, 0, .525], 89: [0, .61111, 0, 0, .525], 90: [0, .61111, 0, 0, .525], 91: [.08333, .69444, 0, 0, .525], 92: [.08333, .69444, 0, 0, .525], 93: [.08333, .69444, 0, 0, .525], 94: [0, .61111, 0, 0, .525], 95: [.09514, 0, 0, 0, .525], 96: [0, .61111, 0, 0, .525], 97: [0, .43056, 0, 0, .525], 98: [0, .61111, 0, 0, .525], 99: [0, .43056, 0, 0, .525], 100: [0, .61111, 0, 0, .525], 101: [0, .43056, 0, 0, .525], 102: [0, .61111, 0, 0, .525], 103: [.22222, .43056, 0, 0, .525], 104: [0, .61111, 0, 0, .525], 105: [0, .61111, 0, 0, .525], 106: [.22222, .61111, 0, 0, .525], 107: [0, .61111, 0, 0, .525], 108: [0, .61111, 0, 0, .525], 109: [0, .43056, 0, 0, .525], 110: [0, .43056, 0, 0, .525], 111: [0, .43056, 0, 0, .525], 112: [.22222, .43056, 0, 0, .525], 113: [.22222, .43056, 0, 0, .525], 114: [0, .43056, 0, 0, .525], 115: [0, .43056, 0, 0, .525], 116: [0, .55358, 0, 0, .525], 117: [0, .43056, 0, 0, .525], 118: [0, .43056, 0, 0, .525], 119: [0, .43056, 0, 0, .525], 120: [0, .43056, 0, 0, .525], 121: [.22222, .43056, 0, 0, .525], 122: [0, .43056, 0, 0, .525], 123: [.08333, .69444, 0, 0, .525], 124: [.08333, .69444, 0, 0, .525], 125: [.08333, .69444, 0, 0, .525], 126: [0, .61111, 0, 0, .525], 127: [0, .61111, 0, 0, .525], 160: [0, 0, 0, 0, .525], 176: [0, .61111, 0, 0, .525], 184: [.19445, 0, 0, 0, .525], 305: [0, .43056, 0, 0, .525], 567: [.22222, .43056, 0, 0, .525], 711: [0, .56597, 0, 0, .525], 713: [0, .56555, 0, 0, .525], 714: [0, .61111, 0, 0, .525], 715: [0, .61111, 0, 0, .525], 728: [0, .61111, 0, 0, .525], 730: [0, .61111, 0, 0, .525], 770: [0, .61111, 0, 0, .525], 771: [0, .61111, 0, 0, .525], 776: [0, .61111, 0, 0, .525], 915: [0, .61111, 0, 0, .525], 916: [0, .61111, 0, 0, .525], 920: [0, .61111, 0, 0, .525], 923: [0, .61111, 0, 0, .525], 926: [0, .61111, 0, 0, .525], 928: [0, .61111, 0, 0, .525], 931: [0, .61111, 0, 0, .525], 933: [0, .61111, 0, 0, .525], 934: [0, .61111, 0, 0, .525], 936: [0, .61111, 0, 0, .525], 937: [0, .61111, 0, 0, .525], 8216: [0, .61111, 0, 0, .525], 8217: [0, .61111, 0, 0, .525], 8242: [0, .61111, 0, 0, .525], 9251: [.11111, .21944, 0, 0, .525] } }; const B = { slant: [.25, .25, .25], space: [0, 0, 0], stretch: [0, 0, 0], shrink: [0, 0, 0], xHeight: [.431, .431, .431], quad: [1, 1.171, 1.472], extraSpace: [0, 0, 0], num1: [.677, .732, .925], num2: [.394, .384, .387], num3: [.444, .471, .504], denom1: [.686, .752, 1.025], denom2: [.345, .344, .532], sup1: [.413, .503, .504], sup2: [.363, .431, .404], sup3: [.289, .286, .294], sub1: [.15, .143, .2], sub2: [.247, .286, .4], supDrop: [.386, .353, .494], subDrop: [.05, .071, .1], delim1: [2.39, 1.7, 1.98], delim2: [1.01, 1.157, 1.42], axisHeight: [.25, .25, .25], defaultRuleThickness: [.04, .049, .049], bigOpSpacing1: [.111, .111, .111], bigOpSpacing2: [.166, .166, .166], bigOpSpacing3: [.2, .2, .2], bigOpSpacing4: [.6, .611, .611], bigOpSpacing5: [.1, .143, .143], sqrtRuleThickness: [.04, .04, .04], ptPerEm: [10, 10, 10], doubleRuleSep: [.2, .2, .2], arrayRuleWidth: [.04, .04, .04], fboxsep: [.3, .3, .3], fboxrule: [.04, .04, .04] }, C = { "\xc5": "A", "\xd0": "D", "\xde": "o", "\xe5": "a", "\xf0": "d", "\xfe": "o", "\u0410": "A", "\u0411": "B", "\u0412": "B", "\u0413": "F", "\u0414": "A", "\u0415": "E", "\u0416": "K", "\u0417": "3", "\u0418": "N", "\u0419": "N", "\u041a": "K", "\u041b": "N", "\u041c": "M", "\u041d": "H", "\u041e": "O", "\u041f": "N", "\u0420": "P", "\u0421": "C", "\u0422": "T", "\u0423": "y", "\u0424": "O", "\u0425": "X", "\u0426": "U", "\u0427": "h", "\u0428": "W", "\u0429": "W", "\u042a": "B", "\u042b": "X", "\u042c": "B", "\u042d": "3", "\u042e": "X", "\u042f": "R", "\u0430": "a", "\u0431": "b", "\u0432": "a", "\u0433": "r", "\u0434": "y", "\u0435": "e", "\u0436": "m", "\u0437": "e", "\u0438": "n", "\u0439": "n", "\u043a": "n", "\u043b": "n", "\u043c": "m", "\u043d": "n", "\u043e": "o", "\u043f": "n", "\u0440": "p", "\u0441": "c", "\u0442": "o", "\u0443": "y", "\u0444": "b", "\u0445": "x", "\u0446": "n", "\u0447": "n", "\u0448": "w", "\u0449": "w", "\u044a": "a", "\u044b": "m", "\u044c": "a", "\u044d": "e", "\u044e": "m", "\u044f": "r" }; function N(e, t, r) { if (!T[t]) throw new Error("Font metrics not found for font: " + t + "."); let n = e.charCodeAt(0), o = T[t][n]; if (!o && e[0] in C && (n = C[e[0]].charCodeAt(0), o = T[t][n]), o || "text" !== r || S(n) && (o = T[t][77]), o) return { depth: o[0], height: o[1], italic: o[2], skew: o[3], width: o[4] } } const q = {}; const I = [[1, 1, 1], [2, 1, 1], [3, 1, 1], [4, 2, 1], [5, 2, 1], [6, 3, 1], [7, 4, 2], [8, 6, 3], [9, 7, 6], [10, 8, 7], [11, 10, 9]], R = [.5, .6, .7, .8, .9, 1, 1.2, 1.44, 1.728, 2.074, 2.488], H = function (e, t) { return t.size < 2 ? e : I[e - 1][t.size - 1] }; class O { constructor(e) { this.style = void 0, this.color = void 0, this.size = void 0, this.textSize = void 0, this.phantom = void 0, this.font = void 0, this.fontFamily = void 0, this.fontWeight = void 0, this.fontShape = void 0, this.sizeMultiplier = void 0, this.maxSize = void 0, this.minRuleThickness = void 0, this._fontMetrics = void 0, this.style = e.style, this.color = e.color, this.size = e.size || O.BASESIZE, this.textSize = e.textSize || this.size, this.phantom = !!e.phantom, this.font = e.font || "", this.fontFamily = e.fontFamily || "", this.fontWeight = e.fontWeight || "", this.fontShape = e.fontShape || "", this.sizeMultiplier = R[this.size - 1], this.maxSize = e.maxSize, this.minRuleThickness = e.minRuleThickness, this._fontMetrics = void 0 } extend(e) { const t = { style: this.style, size: this.size, textSize: this.textSize, color: this.color, phantom: this.phantom, font: this.font, fontFamily: this.fontFamily, fontWeight: this.fontWeight, fontShape: this.fontShape, maxSize: this.maxSize, minRuleThickness: this.minRuleThickness }; for (const r in e) e.hasOwnProperty(r) && (t[r] = e[r]); return new O(t) } havingStyle(e) { return this.style === e ? this : this.extend({ style: e, size: H(this.textSize, e) }) } havingCrampedStyle() { return this.havingStyle(this.style.cramp()) } havingSize(e) { return this.size === e && this.textSize === e ? this : this.extend({ style: this.style.text(), size: e, textSize: e, sizeMultiplier: R[e - 1] }) } havingBaseStyle(e) { e = e || this.style.text(); const t = H(O.BASESIZE, e); return this.size === t && this.textSize === O.BASESIZE && this.style === e ? this : this.extend({ style: e, size: t }) } havingBaseSizing() { let e; switch (this.style.id) { case 4: case 5: e = 3; break; case 6: case 7: e = 1; break; default: e = 6 }return this.extend({ style: this.style.text(), size: e }) } withColor(e) { return this.extend({ color: e }) } withPhantom() { return this.extend({ phantom: !0 }) } withFont(e) { return this.extend({ font: e }) } withTextFontFamily(e) { return this.extend({ fontFamily: e, font: "" }) } withTextFontWeight(e) { return this.extend({ fontWeight: e, font: "" }) } withTextFontShape(e) { return this.extend({ fontShape: e, font: "" }) } sizingClasses(e) { return e.size !== this.size ? ["sizing", "reset-size" + e.size, "size" + this.size] : [] } baseSizingClasses() { return this.size !== O.BASESIZE ? ["sizing", "reset-size" + this.size, "size" + O.BASESIZE] : [] } fontMetrics() { return this._fontMetrics || (this._fontMetrics = function (e) { let t; if (t = e >= 5 ? 0 : e >= 3 ? 1 : 2, !q[t]) { const e = q[t] = { cssEmPerMu: B.quad[t] / 18 }; for (const r in B) B.hasOwnProperty(r) && (e[r] = B[r][t]) } return q[t] }(this.size)), this._fontMetrics } getColor() { return this.phantom ? "transparent" : this.color } } O.BASESIZE = 6; var E = O; const L = { pt: 1, mm: 7227 / 2540, cm: 7227 / 254, in: 72.27, bp: 1.00375, pc: 12, dd: 1238 / 1157, cc: 14856 / 1157, nd: 685 / 642, nc: 1370 / 107, sp: 1 / 65536, px: 1.00375 }, D = { ex: !0, em: !0, mu: !0 }, V = function (e) { return "string" != typeof e && (e = e.unit), e in L || e in D || "ex" === e }, P = function (e, t) { let r; if (e.unit in L) r = L[e.unit] / t.fontMetrics().ptPerEm / t.sizeMultiplier; else if ("mu" === e.unit) r = t.fontMetrics().cssEmPerMu; else { let o; if (o = t.style.isTight() ? t.havingStyle(t.style.text()) : t, "ex" === e.unit) r = o.fontMetrics().xHeight; else { if ("em" !== e.unit) throw new n("Invalid unit: '" + e.unit + "'"); r = o.fontMetrics().quad } o !== t && (r *= o.sizeMultiplier / t.sizeMultiplier) } return Math.min(e.number * r, t.maxSize) }, F = function (e) { return +e.toFixed(4) + "em" }, G = function (e) { return e.filter((e => e)).join(" ") }, U = function (e, t, r) { if (this.classes = e || [], this.attributes = {}, this.height = 0, this.depth = 0, this.maxFontSize = 0, this.style = r || {}, t) { t.style.isTight() && this.classes.push("mtight"); const e = t.getColor(); e && (this.style.color = e) } }, Y = function (e) { const t = document.createElement(e); t.className = G(this.classes); for (const e in this.style) this.style.hasOwnProperty(e) && (t.style[e] = this.style[e]); for (const e in this.attributes) this.attributes.hasOwnProperty(e) && t.setAttribute(e, this.attributes[e]); for (let e = 0; e < this.children.length; e++)t.appendChild(this.children[e].toNode()); return t }, X = function (e) { let t = "<" + e; this.classes.length && (t += ' class="' + l.escape(G(this.classes)) + '"'); let r = ""; for (const e in this.style) this.style.hasOwnProperty(e) && (r += l.hyphenate(e) + ":" + this.style[e] + ";"); r && (t += ' style="' + l.escape(r) + '"'); for (const e in this.attributes) this.attributes.hasOwnProperty(e) && (t += " " + e + '="' + l.escape(this.attributes[e]) + '"'); t += ">"; for (let e = 0; e < this.children.length; e++)t += this.children[e].toMarkup(); return t += "", t }; class W { constructor(e, t, r, n) { this.children = void 0, this.attributes = void 0, this.classes = void 0, this.height = void 0, this.depth = void 0, this.width = void 0, this.maxFontSize = void 0, this.style = void 0, U.call(this, e, r, n), this.children = t || [] } setAttribute(e, t) { this.attributes[e] = t } hasClass(e) { return l.contains(this.classes, e) } toNode() { return Y.call(this, "span") } toMarkup() { return X.call(this, "span") } } class _ { constructor(e, t, r, n) { this.children = void 0, this.attributes = void 0, this.classes = void 0, this.height = void 0, this.depth = void 0, this.maxFontSize = void 0, this.style = void 0, U.call(this, t, n), this.children = r || [], this.setAttribute("href", e) } setAttribute(e, t) { this.attributes[e] = t } hasClass(e) { return l.contains(this.classes, e) } toNode() { return Y.call(this, "a") } toMarkup() { return X.call(this, "a") } } class j { constructor(e, t, r) { this.src = void 0, this.alt = void 0, this.classes = void 0, this.height = void 0, this.depth = void 0, this.maxFontSize = void 0, this.style = void 0, this.alt = t, this.src = e, this.classes = ["mord"], this.style = r } hasClass(e) { return l.contains(this.classes, e) } toNode() { const e = document.createElement("Crop_img"); e.src = this.src, e.alt = this.alt, e.className = "mord"; for (const t in this.style) this.style.hasOwnProperty(t) && (e.style[t] = this.style[t]); return e } toMarkup() { let e = '= n[0] && e <= n[1]) return r.name } } return null }(this.text.charCodeAt(0)); l && this.classes.push(l + "_fallback"), /[\xee\xef\xed\xec]/.test(this.text) && (this.text = $[this.text]) } hasClass(e) { return l.contains(this.classes, e) } toNode() { const e = document.createTextNode(this.text); let t = null; this.italic > 0 && (t = document.createElement("span"), t.style.marginRight = F(this.italic)), this.classes.length > 0 && (t = t || document.createElement("span"), t.className = G(this.classes)); for (const e in this.style) this.style.hasOwnProperty(e) && (t = t || document.createElement("span"), t.style[e] = this.style[e]); return t ? (t.appendChild(e), t) : e } toMarkup() { let e = !1, t = " 0 && (r += "margin-right:" + this.italic + "em;"); for (const e in this.style) this.style.hasOwnProperty(e) && (r += l.hyphenate(e) + ":" + this.style[e] + ";"); r && (e = !0, t += ' style="' + l.escape(r) + '"'); const n = l.escape(this.text); return e ? (t += ">", t += n, t += "", t) : n } } class K { constructor(e, t) { this.children = void 0, this.attributes = void 0, this.children = e || [], this.attributes = t || {} } toNode() { const e = document.createElementNS("http://www.w3.org/2000/svg", "svg"); for (const t in this.attributes) Object.prototype.hasOwnProperty.call(this.attributes, t) && e.setAttribute(t, this.attributes[t]); for (let t = 0; t < this.children.length; t++)e.appendChild(this.children[t].toNode()); return e } toMarkup() { let e = '' : '' } } class Q { constructor(e) { this.attributes = void 0, this.attributes = e || {} } toNode() { const e = document.createElementNS("http://www.w3.org/2000/svg", "line"); for (const t in this.attributes) Object.prototype.hasOwnProperty.call(this.attributes, t) && e.setAttribute(t, this.attributes[t]); return e } toMarkup() { let e = "", "\\gt", !0), se(ie, le, ye, "\u2208", "\\in", !0), se(ie, le, ye, "\ue020", "\\@not"), se(ie, le, ye, "\u2282", "\\subset", !0), se(ie, le, ye, "\u2283", "\\supset", !0), se(ie, le, ye, "\u2286", "\\subseteq", !0), se(ie, le, ye, "\u2287", "\\supseteq", !0), se(ie, he, ye, "\u2288", "\\nsubseteq", !0), se(ie, he, ye, "\u2289", "\\nsupseteq", !0), se(ie, le, ye, "\u22a8", "\\models"), se(ie, le, ye, "\u2190", "\\leftarrow", !0), se(ie, le, ye, "\u2264", "\\le"), se(ie, le, ye, "\u2264", "\\leq", !0), se(ie, le, ye, "<", "\\lt", !0), se(ie, le, ye, "\u2192", "\\rightarrow", !0), se(ie, le, ye, "\u2192", "\\to"), se(ie, he, ye, "\u2271", "\\ngeq", !0), se(ie, he, ye, "\u2270", "\\nleq", !0), se(ie, le, xe, "\xa0", "\\ "), se(ie, le, xe, "\xa0", "\\space"), se(ie, le, xe, "\xa0", "\\nobreakspace"), se(ae, le, xe, "\xa0", "\\ "), se(ae, le, xe, "\xa0", " "), se(ae, le, xe, "\xa0", "\\space"), se(ae, le, xe, "\xa0", "\\nobreakspace"), se(ie, le, xe, null, "\\nobreak"), se(ie, le, xe, null, "\\allowbreak"), se(ie, le, be, ",", ","), se(ie, le, be, ";", ";"), se(ie, he, me, "\u22bc", "\\barwedge", !0), se(ie, he, me, "\u22bb", "\\veebar", !0), se(ie, le, me, "\u2299", "\\odot", !0), se(ie, le, me, "\u2295", "\\oplus", !0), se(ie, le, me, "\u2297", "\\otimes", !0), se(ie, le, we, "\u2202", "\\partial", !0), se(ie, le, me, "\u2298", "\\oslash", !0), se(ie, he, me, "\u229a", "\\circledcirc", !0), se(ie, he, me, "\u22a1", "\\boxdot", !0), se(ie, le, me, "\u25b3", "\\bigtriangleup"), se(ie, le, me, "\u25bd", "\\bigtriangledown"), se(ie, le, me, "\u2020", "\\dagger"), se(ie, le, me, "\u22c4", "\\diamond"), se(ie, le, me, "\u22c6", "\\star"), se(ie, le, me, "\u25c3", "\\triangleleft"), se(ie, le, me, "\u25b9", "\\triangleright"), se(ie, le, fe, "{", "\\{"), se(ae, le, we, "{", "\\{"), se(ae, le, we, "{", "\\textbraceleft"), se(ie, le, pe, "}", "\\}"), se(ae, le, we, "}", "\\}"), se(ae, le, we, "}", "\\textbraceright"), se(ie, le, fe, "{", "\\lbrace"), se(ie, le, pe, "}", "\\rbrace"), se(ie, le, fe, "[", "\\lbrack", !0), se(ae, le, we, "[", "\\lbrack", !0), se(ie, le, pe, "]", "\\rbrack", !0), se(ae, le, we, "]", "\\rbrack", !0), se(ie, le, fe, "(", "\\lparen", !0), se(ie, le, pe, ")", "\\rparen", !0), se(ae, le, we, "<", "\\textless", !0), se(ae, le, we, ">", "\\textgreater", !0), se(ie, le, fe, "\u230a", "\\lfloor", !0), se(ie, le, pe, "\u230b", "\\rfloor", !0), se(ie, le, fe, "\u2308", "\\lceil", !0), se(ie, le, pe, "\u2309", "\\rceil", !0), se(ie, le, we, "\\", "\\backslash"), se(ie, le, we, "\u2223", "|"), se(ie, le, we, "\u2223", "\\vert"), se(ae, le, we, "|", "\\textbar", !0), se(ie, le, we, "\u2225", "\\|"), se(ie, le, we, "\u2225", "\\Vert"), se(ae, le, we, "\u2225", "\\textbardbl"), se(ae, le, we, "~", "\\textasciitilde"), se(ae, le, we, "\\", "\\textbackslash"), se(ae, le, we, "^", "\\textasciicircum"), se(ie, le, ye, "\u2191", "\\uparrow", !0), se(ie, le, ye, "\u21d1", "\\Uparrow", !0), se(ie, le, ye, "\u2193", "\\downarrow", !0), se(ie, le, ye, "\u21d3", "\\Downarrow", !0), se(ie, le, ye, "\u2195", "\\updownarrow", !0), se(ie, le, ye, "\u21d5", "\\Updownarrow", !0), se(ie, le, ge, "\u2210", "\\coprod"), se(ie, le, ge, "\u22c1", "\\bigvee"), se(ie, le, ge, "\u22c0", "\\bigwedge"), se(ie, le, ge, "\u2a04", "\\biguplus"), se(ie, le, ge, "\u22c2", "\\bigcap"), se(ie, le, ge, "\u22c3", "\\bigcup"), se(ie, le, ge, "\u222b", "\\int"), se(ie, le, ge, "\u222b", "\\intop"), se(ie, le, ge, "\u222c", "\\iint"), se(ie, le, ge, "\u222d", "\\iiint"), se(ie, le, ge, "\u220f", "\\prod"), se(ie, le, ge, "\u2211", "\\sum"), se(ie, le, ge, "\u2a02", "\\bigotimes"), se(ie, le, ge, "\u2a01", "\\bigoplus"), se(ie, le, ge, "\u2a00", "\\bigodot"), se(ie, le, ge, "\u222e", "\\oint"), se(ie, le, ge, "\u222f", "\\oiint"), se(ie, le, ge, "\u2230", "\\oiiint"), se(ie, le, ge, "\u2a06", "\\bigsqcup"), se(ie, le, ge, "\u222b", "\\smallint"), se(ae, le, ue, "\u2026", "\\textellipsis"), se(ie, le, ue, "\u2026", "\\mathellipsis"), se(ae, le, ue, "\u2026", "\\ldots", !0), se(ie, le, ue, "\u2026", "\\ldots", !0), se(ie, le, ue, "\u22ef", "\\@cdots", !0), se(ie, le, ue, "\u22f1", "\\ddots", !0), se(ie, le, we, "\u22ee", "\\varvdots"), se(ie, le, ce, "\u02ca", "\\acute"), se(ie, le, ce, "\u02cb", "\\grave"), se(ie, le, ce, "\xa8", "\\ddot"), se(ie, le, ce, "~", "\\tilde"), se(ie, le, ce, "\u02c9", "\\bar"), se(ie, le, ce, "\u02d8", "\\breve"), se(ie, le, ce, "\u02c7", "\\check"), se(ie, le, ce, "^", "\\hat"), se(ie, le, ce, "\u20d7", "\\vec"), se(ie, le, ce, "\u02d9", "\\dot"), se(ie, le, ce, "\u02da", "\\mathring"), se(ie, le, de, "\ue131", "\\@imath"), se(ie, le, de, "\ue237", "\\@jmath"), se(ie, le, we, "\u0131", "\u0131"), se(ie, le, we, "\u0237", "\u0237"), se(ae, le, we, "\u0131", "\\i", !0), se(ae, le, we, "\u0237", "\\j", !0), se(ae, le, we, "\xdf", "\\ss", !0), se(ae, le, we, "\xe6", "\\ae", !0), se(ae, le, we, "\u0153", "\\oe", !0), se(ae, le, we, "\xf8", "\\o", !0), se(ae, le, we, "\xc6", "\\AE", !0), se(ae, le, we, "\u0152", "\\OE", !0), se(ae, le, we, "\xd8", "\\O", !0), se(ae, le, ce, "\u02ca", "\\'"), se(ae, le, ce, "\u02cb", "\\`"), se(ae, le, ce, "\u02c6", "\\^"), se(ae, le, ce, "\u02dc", "\\~"), se(ae, le, ce, "\u02c9", "\\="), se(ae, le, ce, "\u02d8", "\\u"), se(ae, le, ce, "\u02d9", "\\."), se(ae, le, ce, "\xb8", "\\c"), se(ae, le, ce, "\u02da", "\\r"), se(ae, le, ce, "\u02c7", "\\v"), se(ae, le, ce, "\xa8", '\\"'), se(ae, le, ce, "\u02dd", "\\H"), se(ae, le, ce, "\u25ef", "\\textcircled"); const ve = { "--": !0, "---": !0, "``": !0, "''": !0 }; se(ae, le, we, "\u2013", "--", !0), se(ae, le, we, "\u2013", "\\textendash"), se(ae, le, we, "\u2014", "---", !0), se(ae, le, we, "\u2014", "\\textemdash"), se(ae, le, we, "\u2018", "`", !0), se(ae, le, we, "\u2018", "\\textquoteleft"), se(ae, le, we, "\u2019", "'", !0), se(ae, le, we, "\u2019", "\\textquoteright"), se(ae, le, we, "\u201c", "``", !0), se(ae, le, we, "\u201c", "\\textquotedblleft"), se(ae, le, we, "\u201d", "''", !0), se(ae, le, we, "\u201d", "\\textquotedblright"), se(ie, le, we, "\xb0", "\\degree", !0), se(ae, le, we, "\xb0", "\\degree"), se(ae, le, we, "\xb0", "\\textdegree", !0), se(ie, le, we, "\xa3", "\\pounds"), se(ie, le, we, "\xa3", "\\mathsterling", !0), se(ae, le, we, "\xa3", "\\pounds"), se(ae, le, we, "\xa3", "\\textsterling", !0), se(ie, he, we, "\u2720", "\\maltese"), se(ae, he, we, "\u2720", "\\maltese"); const ke = '0123456789/@."'; for (let e = 0; e < ke.length; e++) { const t = ke.charAt(e); se(ie, le, we, t, t) } const Se = '0123456789!@*()-=+";:?/.,'; for (let e = 0; e < Se.length; e++) { const t = Se.charAt(e); se(ae, le, we, t, t) } const Me = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; for (let e = 0; e < Me.length; e++) { const t = Me.charAt(e); se(ie, le, de, t, t), se(ae, le, we, t, t) } se(ie, he, we, "C", "\u2102"), se(ae, he, we, "C", "\u2102"), se(ie, he, we, "H", "\u210d"), se(ae, he, we, "H", "\u210d"), se(ie, he, we, "N", "\u2115"), se(ae, he, we, "N", "\u2115"), se(ie, he, we, "P", "\u2119"), se(ae, he, we, "P", "\u2119"), se(ie, he, we, "Q", "\u211a"), se(ae, he, we, "Q", "\u211a"), se(ie, he, we, "R", "\u211d"), se(ae, he, we, "R", "\u211d"), se(ie, he, we, "Z", "\u2124"), se(ae, he, we, "Z", "\u2124"), se(ie, le, de, "h", "\u210e"), se(ae, le, de, "h", "\u210e"); let ze = ""; for (let e = 0; e < Me.length; e++) { const t = Me.charAt(e); ze = String.fromCharCode(55349, 56320 + e), se(ie, le, de, t, ze), se(ae, le, we, t, ze), ze = String.fromCharCode(55349, 56372 + e), se(ie, le, de, t, ze), se(ae, le, we, t, ze), ze = String.fromCharCode(55349, 56424 + e), se(ie, le, de, t, ze), se(ae, le, we, t, ze), ze = String.fromCharCode(55349, 56580 + e), se(ie, le, de, t, ze), se(ae, le, we, t, ze), ze = String.fromCharCode(55349, 56684 + e), se(ie, le, de, t, ze), se(ae, le, we, t, ze), ze = String.fromCharCode(55349, 56736 + e), se(ie, le, de, t, ze), se(ae, le, we, t, ze), ze = String.fromCharCode(55349, 56788 + e), se(ie, le, de, t, ze), se(ae, le, we, t, ze), ze = String.fromCharCode(55349, 56840 + e), se(ie, le, de, t, ze), se(ae, le, we, t, ze), ze = String.fromCharCode(55349, 56944 + e), se(ie, le, de, t, ze), se(ae, le, we, t, ze), e < 26 && (ze = String.fromCharCode(55349, 56632 + e), se(ie, le, de, t, ze), se(ae, le, we, t, ze), ze = String.fromCharCode(55349, 56476 + e), se(ie, le, de, t, ze), se(ae, le, we, t, ze)) } ze = String.fromCharCode(55349, 56668), se(ie, le, de, "k", ze), se(ae, le, we, "k", ze); for (let e = 0; e < 10; e++) { const t = e.toString(); ze = String.fromCharCode(55349, 57294 + e), se(ie, le, de, t, ze), se(ae, le, we, t, ze), ze = String.fromCharCode(55349, 57314 + e), se(ie, le, de, t, ze), se(ae, le, we, t, ze), ze = String.fromCharCode(55349, 57324 + e), se(ie, le, de, t, ze), se(ae, le, we, t, ze), ze = String.fromCharCode(55349, 57334 + e), se(ie, le, de, t, ze), se(ae, le, we, t, ze) } const Ae = "\xd0\xde\xfe"; for (let e = 0; e < Ae.length; e++) { const t = Ae.charAt(e); se(ie, le, de, t, t), se(ae, le, we, t, t) } const Te = [["mathbf", "textbf", "Main-Bold"], ["mathbf", "textbf", "Main-Bold"], ["mathnormal", "textit", "Math-Italic"], ["mathnormal", "textit", "Math-Italic"], ["boldsymbol", "boldsymbol", "Main-BoldItalic"], ["boldsymbol", "boldsymbol", "Main-BoldItalic"], ["mathscr", "textscr", "Script-Regular"], ["", "", ""], ["", "", ""], ["", "", ""], ["mathfrak", "textfrak", "Fraktur-Regular"], ["mathfrak", "textfrak", "Fraktur-Regular"], ["mathbb", "textbb", "AMS-Regular"], ["mathbb", "textbb", "AMS-Regular"], ["mathboldfrak", "textboldfrak", "Fraktur-Regular"], ["mathboldfrak", "textboldfrak", "Fraktur-Regular"], ["mathsf", "textsf", "SansSerif-Regular"], ["mathsf", "textsf", "SansSerif-Regular"], ["mathboldsf", "textboldsf", "SansSerif-Bold"], ["mathboldsf", "textboldsf", "SansSerif-Bold"], ["mathitsf", "textitsf", "SansSerif-Italic"], ["mathitsf", "textitsf", "SansSerif-Italic"], ["", "", ""], ["", "", ""], ["mathtt", "texttt", "Typewriter-Regular"], ["mathtt", "texttt", "Typewriter-Regular"]], Be = [["mathbf", "textbf", "Main-Bold"], ["", "", ""], ["mathsf", "textsf", "SansSerif-Regular"], ["mathboldsf", "textboldsf", "SansSerif-Bold"], ["mathtt", "texttt", "Typewriter-Regular"]], Ce = function (e, t, r) { return oe[r][e] && oe[r][e].replace && (e = oe[r][e].replace), { value: e, metrics: N(e, t, r) } }, Ne = function (e, t, r, n, o) { const s = Ce(e, t, r), i = s.metrics; let a; if (e = s.value, i) { let t = i.italic; ("text" === r || n && "mathit" === n.font) && (t = 0), a = new Z(e, i.height, i.depth, t, i.skew, i.width, o) } else "undefined" != typeof console && console.warn("No character metrics for '" + e + "' in style '" + t + "' and mode '" + r + "'"), a = new Z(e, 0, 0, 0, 0, 0, o); if (n) { a.maxFontSize = n.sizeMultiplier, n.style.isTight() && a.classes.push("mtight"); const e = n.getColor(); e && (a.style.color = e) } return a }, qe = (e, t) => { if (G(e.classes) !== G(t.classes) || e.skew !== t.skew || e.maxFontSize !== t.maxFontSize) return !1; if (1 === e.classes.length) { const t = e.classes[0]; if ("mbin" === t || "mord" === t) return !1 } for (const r in e.style) if (e.style.hasOwnProperty(r) && e.style[r] !== t.style[r]) return !1; for (const r in t.style) if (t.style.hasOwnProperty(r) && e.style[r] !== t.style[r]) return !1; return !0 }, Ie = function (e) { let t = 0, r = 0, n = 0; for (let o = 0; o < e.children.length; o++) { const s = e.children[o]; s.height > t && (t = s.height), s.depth > r && (r = s.depth), s.maxFontSize > n && (n = s.maxFontSize) } e.height = t, e.depth = r, e.maxFontSize = n }, Re = function (e, t, r, n) { const o = new W(e, t, r, n); return Ie(o), o }, He = (e, t, r, n) => new W(e, t, r, n), Oe = function (e) { const t = new A(e); return Ie(t), t }, Ee = function (e, t, r) { let n, o = ""; switch (e) { case "amsrm": o = "AMS"; break; case "textrm": o = "Main"; break; case "textsf": o = "SansSerif"; break; case "texttt": o = "Typewriter"; break; default: o = e }return n = "textbf" === t && "textit" === r ? "BoldItalic" : "textbf" === t ? "Bold" : "textit" === t ? "Italic" : "Regular", o + "-" + n }, Le = { mathbf: { variant: "bold", fontName: "Main-Bold" }, mathrm: { variant: "normal", fontName: "Main-Regular" }, textit: { variant: "italic", fontName: "Main-Italic" }, mathit: { variant: "italic", fontName: "Main-Italic" }, mathnormal: { variant: "italic", fontName: "Math-Italic" }, mathbb: { variant: "double-struck", fontName: "AMS-Regular" }, mathcal: { variant: "script", fontName: "Caligraphic-Regular" }, mathfrak: { variant: "fraktur", fontName: "Fraktur-Regular" }, mathscr: { variant: "script", fontName: "Script-Regular" }, mathsf: { variant: "sans-serif", fontName: "SansSerif-Regular" }, mathtt: { variant: "monospace", fontName: "Typewriter-Regular" } }, De = { vec: ["vec", .471, .714], oiintSize1: ["oiintSize1", .957, .499], oiintSize2: ["oiintSize2", 1.472, .659], oiiintSize1: ["oiiintSize1", 1.304, .499], oiiintSize2: ["oiiintSize2", 1.98, .659] }; var Ve = { fontMap: Le, makeSymbol: Ne, mathsym: function (e, t, r, n) { return void 0 === n && (n = []), "boldsymbol" === r.font && Ce(e, "Main-Bold", t).metrics ? Ne(e, "Main-Bold", t, r, n.concat(["mathbf"])) : "\\" === e || "main" === oe[t][e].font ? Ne(e, "Main-Regular", t, r, n) : Ne(e, "AMS-Regular", t, r, n.concat(["amsrm"])) }, makeSpan: Re, makeSvgSpan: He, makeLineSpan: function (e, t, r) { const n = Re([e], [], t); return n.height = Math.max(r || t.fontMetrics().defaultRuleThickness, t.minRuleThickness), n.style.borderBottomWidth = F(n.height), n.maxFontSize = 1, n }, makeAnchor: function (e, t, r, n) { const o = new _(e, t, r, n); return Ie(o), o }, makeFragment: Oe, wrapFragment: function (e, t) { return e instanceof A ? Re([], [e], t) : e }, makeVList: function (e, t) { const { children: r, depth: n } = function (e) { if ("individualShift" === e.positionType) { const t = e.children, r = [t[0]], n = -t[0].shift - t[0].elem.depth; let o = n; for (let e = 1; e < t.length; e++) { const n = -t[e].shift - o - t[e].elem.depth, s = n - (t[e - 1].elem.height + t[e - 1].elem.depth); o += n, r.push({ type: "kern", size: s }), r.push(t[e]) } return { children: r, depth: n } } let t; if ("top" === e.positionType) { let r = e.positionData; for (let t = 0; t < e.children.length; t++) { const n = e.children[t]; r -= "kern" === n.type ? n.size : n.elem.height + n.elem.depth } t = r } else if ("bottom" === e.positionType) t = -e.positionData; else { const r = e.children[0]; if ("elem" !== r.type) throw new Error('First child must have type "elem".'); if ("shift" === e.positionType) t = -r.elem.depth - e.positionData; else { if ("firstBaseline" !== e.positionType) throw new Error("Invalid positionType " + e.positionType + "."); t = -r.elem.depth } } return { children: e.children, depth: t } }(e); let o = 0; for (let e = 0; e < r.length; e++) { const t = r[e]; if ("elem" === t.type) { const e = t.elem; o = Math.max(o, e.maxFontSize, e.height) } } o += 2; const s = Re(["pstrut"], []); s.style.height = F(o); const i = []; let a = n, l = n, h = n; for (let e = 0; e < r.length; e++) { const t = r[e]; if ("kern" === t.type) h += t.size; else { const e = t.elem, r = t.wrapperClasses || [], n = t.wrapperStyle || {}, a = Re(r, [s, e], void 0, n); a.style.top = F(-o - h - e.depth), t.marginLeft && (a.style.marginLeft = t.marginLeft), t.marginRight && (a.style.marginRight = t.marginRight), i.push(a), h += e.height + e.depth } a = Math.min(a, h), l = Math.max(l, h) } const c = Re(["vlist"], i); let m; if (c.style.height = F(l), a < 0) { const e = Re([], []), t = Re(["vlist"], [e]); t.style.height = F(-a); const r = Re(["vlist-s"], [new Z("\u200b")]); m = [Re(["vlist-r"], [c, r]), Re(["vlist-r"], [t])] } else m = [Re(["vlist-r"], [c])]; const p = Re(["vlist-t"], m); return 2 === m.length && p.classes.push("vlist-t2"), p.height = l, p.depth = -a, p }, makeOrd: function (e, t, r) { const o = e.mode, s = e.text, i = ["mord"], a = "math" === o || "text" === o && t.font, l = a ? t.font : t.fontFamily; let h = "", c = ""; if (55349 === s.charCodeAt(0) && ([h, c] = function (e, t) { const r = 1024 * (e.charCodeAt(0) - 55296) + (e.charCodeAt(1) - 56320) + 65536, o = "math" === t ? 0 : 1; if (119808 <= r && r < 120484) { const e = Math.floor((r - 119808) / 26); return [Te[e][2], Te[e][o]] } if (120782 <= r && r <= 120831) { const e = Math.floor((r - 120782) / 10); return [Be[e][2], Be[e][o]] } if (120485 === r || 120486 === r) return [Te[0][2], Te[0][o]]; if (120486 < r && r < 120782) return ["", ""]; throw new n("Unsupported character: " + e) }(s, o)), h.length > 0) return Ne(s, h, o, t, i.concat(c)); if (l) { let e, n; if ("boldsymbol" === l) { const t = function (e, t, r, n, o) { return "textord" !== o && Ce(e, "Math-BoldItalic", t).metrics ? { fontName: "Math-BoldItalic", fontClass: "boldsymbol" } : { fontName: "Main-Bold", fontClass: "mathbf" } }(s, o, 0, 0, r); e = t.fontName, n = [t.fontClass] } else a ? (e = Le[l].fontName, n = [l]) : (e = Ee(l, t.fontWeight, t.fontShape), n = [l, t.fontWeight, t.fontShape]); if (Ce(s, e, o).metrics) return Ne(s, e, o, t, i.concat(n)); if (ve.hasOwnProperty(s) && "Typewriter" === e.slice(0, 10)) { const r = []; for (let a = 0; a < s.length; a++)r.push(Ne(s[a], e, o, t, i.concat(n))); return Oe(r) } } if ("mathord" === r) return Ne(s, "Math-Italic", o, t, i.concat(["mathnormal"])); if ("textord" === r) { const e = oe[o][s] && oe[o][s].font; if ("ams" === e) { const e = Ee("amsrm", t.fontWeight, t.fontShape); return Ne(s, e, o, t, i.concat("amsrm", t.fontWeight, t.fontShape)) } if ("main" !== e && e) { const r = Ee(e, t.fontWeight, t.fontShape); return Ne(s, r, o, t, i.concat(r, t.fontWeight, t.fontShape)) } { const e = Ee("textrm", t.fontWeight, t.fontShape); return Ne(s, e, o, t, i.concat(t.fontWeight, t.fontShape)) } } throw new Error("unexpected type: " + r + " in makeOrd") }, makeGlue: (e, t) => { const r = Re(["mspace"], [], t), n = P(e, t); return r.style.marginRight = F(n), r }, staticSvg: function (e, t) { const [r, n, o] = De[e], s = new J(r), i = new K([s], { width: F(n), height: F(o), style: "width:" + F(n), viewBox: "0 0 " + 1e3 * n + " " + 1e3 * o, preserveAspectRatio: "xMinYMin" }), a = He(["overlay"], [i], t); return a.height = o, a.style.height = F(o), a.style.width = F(n), a }, svgData: De, tryCombineChars: e => { for (let t = 0; t < e.length - 1; t++) { const r = e[t], n = e[t + 1]; r instanceof Z && n instanceof Z && qe(r, n) && (r.text += n.text, r.height = Math.max(r.height, n.height), r.depth = Math.max(r.depth, n.depth), r.italic = n.italic, e.splice(t + 1, 1), t--) } return e } }; const Pe = { number: 3, unit: "mu" }, Fe = { number: 4, unit: "mu" }, Ge = { number: 5, unit: "mu" }, Ue = { mord: { mop: Pe, mbin: Fe, mrel: Ge, minner: Pe }, mop: { mord: Pe, mop: Pe, mrel: Ge, minner: Pe }, mbin: { mord: Fe, mop: Fe, mopen: Fe, minner: Fe }, mrel: { mord: Ge, mop: Ge, mopen: Ge, minner: Ge }, mopen: {}, mclose: { mop: Pe, mbin: Fe, mrel: Ge, minner: Pe }, mpunct: { mord: Pe, mop: Pe, mrel: Ge, mopen: Pe, mclose: Pe, mpunct: Pe, minner: Pe }, minner: { mord: Pe, mop: Pe, mbin: Fe, mrel: Ge, mopen: Pe, mpunct: Pe, minner: Pe } }, Ye = { mord: { mop: Pe }, mop: { mord: Pe, mop: Pe }, mbin: {}, mrel: {}, mopen: {}, mclose: { mop: Pe }, mpunct: {}, minner: { mop: Pe } }, Xe = {}, We = {}, _e = {}; function je(e) { let { type: t, names: r, props: n, handler: o, htmlBuilder: s, mathmlBuilder: i } = e; const a = { type: t, numArgs: n.numArgs, argTypes: n.argTypes, allowedInArgument: !!n.allowedInArgument, allowedInText: !!n.allowedInText, allowedInMath: void 0 === n.allowedInMath || n.allowedInMath, numOptionalArgs: n.numOptionalArgs || 0, infix: !!n.infix, primitive: !!n.primitive, handler: o }; for (let e = 0; e < r.length; ++e)Xe[r[e]] = a; t && (s && (We[t] = s), i && (_e[t] = i)) } function $e(e) { let { type: t, htmlBuilder: r, mathmlBuilder: n } = e; je({ type: t, names: [], props: { numArgs: 0 }, handler() { throw new Error("Should never be called.") }, htmlBuilder: r, mathmlBuilder: n }) } const Ze = function (e) { return "ordgroup" === e.type && 1 === e.body.length ? e.body[0] : e }, Ke = function (e) { return "ordgroup" === e.type ? e.body : [e] }, Je = Ve.makeSpan, Qe = ["leftmost", "mbin", "mopen", "mrel", "mop", "mpunct"], et = ["rightmost", "mrel", "mclose", "mpunct"], tt = { display: w.DISPLAY, text: w.TEXT, script: w.SCRIPT, scriptscript: w.SCRIPTSCRIPT }, rt = { mord: "mord", mop: "mop", mbin: "mbin", mrel: "mrel", mopen: "mopen", mclose: "mclose", mpunct: "mpunct", minner: "minner" }, nt = function (e, t, r, n) { void 0 === n && (n = [null, null]); const o = []; for (let r = 0; r < e.length; r++) { const n = ht(e[r], t); if (n instanceof A) { const e = n.children; o.push(...e) } else o.push(n) } if (Ve.tryCombineChars(o), !r) return o; let s = t; if (1 === e.length) { const r = e[0]; "sizing" === r.type ? s = t.havingSize(r.size) : "styling" === r.type && (s = t.havingStyle(tt[r.style])) } const i = Je([n[0] || "leftmost"], [], t), a = Je([n[1] || "rightmost"], [], t), h = "root" === r; return ot(o, ((e, t) => { const r = t.classes[0], n = e.classes[0]; "mbin" === r && l.contains(et, n) ? t.classes[0] = "mord" : "mbin" === n && l.contains(Qe, r) && (e.classes[0] = "mord") }), { node: i }, a, h), ot(o, ((e, t) => { const r = at(t), n = at(e), o = r && n ? e.hasClass("mtight") ? Ye[r][n] : Ue[r][n] : null; if (o) return Ve.makeGlue(o, s) }), { node: i }, a, h), o }, ot = function (e, t, r, n, o) { n && e.push(n); let s = 0; for (; s < e.length; s++) { const n = e[s], i = st(n); if (i) { ot(i.children, t, r, null, o); continue } const a = !n.hasClass("mspace"); if (a) { const o = t(n, r.node); o && (r.insertAfter ? r.insertAfter(o) : (e.unshift(o), s++)) } a ? r.node = n : o && n.hasClass("newline") && (r.node = Je(["leftmost"])), r.insertAfter = (t => r => { e.splice(t + 1, 0, r), s++ })(s) } n && e.pop() }, st = function (e) { return e instanceof A || e instanceof _ || e instanceof W && e.hasClass("enclosing") ? e : null }, it = function (e, t) { const r = st(e); if (r) { const e = r.children; if (e.length) { if ("right" === t) return it(e[e.length - 1], "right"); if ("left" === t) return it(e[0], "left") } } return e }, at = function (e, t) { return e ? (t && (e = it(e, t)), rt[e.classes[0]] || null) : null }, lt = function (e, t) { const r = ["nulldelimiter"].concat(e.baseSizingClasses()); return Je(t.concat(r)) }, ht = function (e, t, r) { if (!e) return Je(); if (We[e.type]) { let n = We[e.type](e, t); if (r && t.size !== r.size) { n = Je(t.sizingClasses(r), [n], t); const e = t.sizeMultiplier / r.sizeMultiplier; n.height *= e, n.depth *= e } return n } throw new n("Got group of unknown type: '" + e.type + "'") }; function ct(e, t) { const r = Je(["base"], e, t), n = Je(["strut"]); return n.style.height = F(r.height + r.depth), r.depth && (n.style.verticalAlign = F(-r.depth)), r.children.unshift(n), r } function mt(e, t) { let r = null; 1 === e.length && "tag" === e[0].type && (r = e[0].tag, e = e[0].body); const n = nt(e, t, "root"); let o; 2 === n.length && n[1].hasClass("tag") && (o = n.pop()); const s = []; let i, a = []; for (let e = 0; e < n.length; e++)if (a.push(n[e]), n[e].hasClass("mbin") || n[e].hasClass("mrel") || n[e].hasClass("allowbreak")) { let r = !1; for (; e < n.length - 1 && n[e + 1].hasClass("mspace") && !n[e + 1].hasClass("newline");)e++, a.push(n[e]), n[e].hasClass("nobreak") && (r = !0); r || (s.push(ct(a, t)), a = []) } else n[e].hasClass("newline") && (a.pop(), a.length > 0 && (s.push(ct(a, t)), a = []), s.push(n[e])); a.length > 0 && s.push(ct(a, t)), r ? (i = ct(nt(r, t, !0)), i.classes = ["tag"], s.push(i)) : o && s.push(o); const l = Je(["katex-html"], s); if (l.setAttribute("aria-hidden", "true"), i) { const e = i.children[0]; e.style.height = F(l.height + l.depth), l.depth && (e.style.verticalAlign = F(-l.depth)) } return l } function pt(e) { return new A(e) } class ut { constructor(e, t, r) { this.type = void 0, this.attributes = void 0, this.children = void 0, this.classes = void 0, this.type = e, this.attributes = {}, this.children = t || [], this.classes = r || [] } setAttribute(e, t) { this.attributes[e] = t } getAttribute(e) { return this.attributes[e] } toNode() { const e = document.createElementNS("http://www.w3.org/1998/Math/MathML", this.type); for (const t in this.attributes) Object.prototype.hasOwnProperty.call(this.attributes, t) && e.setAttribute(t, this.attributes[t]); this.classes.length > 0 && (e.className = G(this.classes)); for (let t = 0; t < this.children.length; t++)e.appendChild(this.children[t].toNode()); return e } toMarkup() { let e = "<" + this.type; for (const t in this.attributes) Object.prototype.hasOwnProperty.call(this.attributes, t) && (e += " " + t + '="', e += l.escape(this.attributes[t]), e += '"'); this.classes.length > 0 && (e += ' class ="' + l.escape(G(this.classes)) + '"'), e += ">"; for (let t = 0; t < this.children.length; t++)e += this.children[t].toMarkup(); return e += "", e } toText() { return this.children.map((e => e.toText())).join("") } } class dt { constructor(e) { this.text = void 0, this.text = e } toNode() { return document.createTextNode(this.text) } toMarkup() { return l.escape(this.toText()) } toText() { return this.text } } var gt = { MathNode: ut, TextNode: dt, SpaceNode: class { constructor(e) { this.width = void 0, this.character = void 0, this.width = e, this.character = e >= .05555 && e <= .05556 ? "\u200a" : e >= .1666 && e <= .1667 ? "\u2009" : e >= .2222 && e <= .2223 ? "\u2005" : e >= .2777 && e <= .2778 ? "\u2005\u200a" : e >= -.05556 && e <= -.05555 ? "\u200a\u2063" : e >= -.1667 && e <= -.1666 ? "\u2009\u2063" : e >= -.2223 && e <= -.2222 ? "\u205f\u2063" : e >= -.2778 && e <= -.2777 ? "\u2005\u2063" : null } toNode() { if (this.character) return document.createTextNode(this.character); { const e = document.createElementNS("http://www.w3.org/1998/Math/MathML", "mspace"); return e.setAttribute("width", F(this.width)), e } } toMarkup() { return this.character ? "" + this.character + "" : '' } toText() { return this.character ? this.character : " " } }, newDocumentFragment: pt }; const ft = function (e, t, r) { return !oe[t][e] || !oe[t][e].replace || 55349 === e.charCodeAt(0) || ve.hasOwnProperty(e) && r && (r.fontFamily && "tt" === r.fontFamily.slice(4, 6) || r.font && "tt" === r.font.slice(4, 6)) || (e = oe[t][e].replace), new gt.TextNode(e) }, bt = function (e) { return 1 === e.length ? e[0] : new gt.MathNode("mrow", e) }, yt = function (e, t) { if ("texttt" === t.fontFamily) return "monospace"; if ("textsf" === t.fontFamily) return "textit" === t.fontShape && "textbf" === t.fontWeight ? "sans-serif-bold-italic" : "textit" === t.fontShape ? "sans-serif-italic" : "textbf" === t.fontWeight ? "bold-sans-serif" : "sans-serif"; if ("textit" === t.fontShape && "textbf" === t.fontWeight) return "bold-italic"; if ("textit" === t.fontShape) return "italic"; if ("textbf" === t.fontWeight) return "bold"; const r = t.font; if (!r || "mathnormal" === r) return null; const n = e.mode; if ("mathit" === r) return "italic"; if ("boldsymbol" === r) return "textord" === e.type ? "bold" : "bold-italic"; if ("mathbf" === r) return "bold"; if ("mathbb" === r) return "double-struck"; if ("mathfrak" === r) return "fraktur"; if ("mathscr" === r || "mathcal" === r) return "script"; if ("mathsf" === r) return "sans-serif"; if ("mathtt" === r) return "monospace"; let o = e.text; if (l.contains(["\\imath", "\\jmath"], o)) return null; oe[n][o] && oe[n][o].replace && (o = oe[n][o].replace); return N(o, Ve.fontMap[r].fontName, n) ? Ve.fontMap[r].variant : null }, xt = function (e, t, r) { if (1 === e.length) { const n = vt(e[0], t); return r && n instanceof ut && "mo" === n.type && (n.setAttribute("lspace", "0em"), n.setAttribute("rspace", "0em")), [n] } const n = []; let o; for (let r = 0; r < e.length; r++) { const s = vt(e[r], t); if (s instanceof ut && o instanceof ut) { if ("mtext" === s.type && "mtext" === o.type && s.getAttribute("mathvariant") === o.getAttribute("mathvariant")) { o.children.push(...s.children); continue } if ("mn" === s.type && "mn" === o.type) { o.children.push(...s.children); continue } if ("mi" === s.type && 1 === s.children.length && "mn" === o.type) { const e = s.children[0]; if (e instanceof dt && "." === e.text) { o.children.push(...s.children); continue } } else if ("mi" === o.type && 1 === o.children.length) { const e = o.children[0]; if (e instanceof dt && "\u0338" === e.text && ("mo" === s.type || "mi" === s.type || "mn" === s.type)) { const e = s.children[0]; e instanceof dt && e.text.length > 0 && (e.text = e.text.slice(0, 1) + "\u0338" + e.text.slice(1), n.pop()) } } } n.push(s), o = s } return n }, wt = function (e, t, r) { return bt(xt(e, t, r)) }, vt = function (e, t) { if (!e) return new gt.MathNode("mrow"); if (_e[e.type]) { return _e[e.type](e, t) } throw new n("Got group of unknown type: '" + e.type + "'") }; function kt(e, t, r, n, o) { const s = xt(e, r); let i; i = 1 === s.length && s[0] instanceof ut && l.contains(["mrow", "mtable"], s[0].type) ? s[0] : new gt.MathNode("mrow", s); const a = new gt.MathNode("annotation", [new gt.TextNode(t)]); a.setAttribute("encoding", "application/x-tex"); const h = new gt.MathNode("semantics", [i, a]), c = new gt.MathNode("math", [h]); c.setAttribute("xmlns", "http://www.w3.org/1998/Math/MathML"), n && c.setAttribute("display", "block"); const m = o ? "katex" : "katex-mathml"; return Ve.makeSpan([m], [c]) } const St = function (e) { return new E({ style: e.displayMode ? w.DISPLAY : w.TEXT, maxSize: e.maxSize, minRuleThickness: e.minRuleThickness }) }, Mt = function (e, t) { if (t.displayMode) { const r = ["katex-display"]; t.leqno && r.push("leqno"), t.fleqn && r.push("fleqn"), e = Ve.makeSpan(r, [e]) } return e }, zt = function (e, t, r) { const n = St(r); let o; if ("mathml" === r.output) return kt(e, t, n, r.displayMode, !0); if ("html" === r.output) { const t = mt(e, n); o = Ve.makeSpan(["katex"], [t]) } else { const s = kt(e, t, n, r.displayMode, !1), i = mt(e, n); o = Ve.makeSpan(["katex"], [s, i]) } return Mt(o, r) }; const At = { widehat: "^", widecheck: "\u02c7", widetilde: "~", utilde: "~", overleftarrow: "\u2190", underleftarrow: "\u2190", xleftarrow: "\u2190", overrightarrow: "\u2192", underrightarrow: "\u2192", xrightarrow: "\u2192", underbrace: "\u23df", overbrace: "\u23de", overgroup: "\u23e0", undergroup: "\u23e1", overleftrightarrow: "\u2194", underleftrightarrow: "\u2194", xleftrightarrow: "\u2194", Overrightarrow: "\u21d2", xRightarrow: "\u21d2", overleftharpoon: "\u21bc", xleftharpoonup: "\u21bc", overrightharpoon: "\u21c0", xrightharpoonup: "\u21c0", xLeftarrow: "\u21d0", xLeftrightarrow: "\u21d4", xhookleftarrow: "\u21a9", xhookrightarrow: "\u21aa", xmapsto: "\u21a6", xrightharpoondown: "\u21c1", xleftharpoondown: "\u21bd", xrightleftharpoons: "\u21cc", xleftrightharpoons: "\u21cb", xtwoheadleftarrow: "\u219e", xtwoheadrightarrow: "\u21a0", xlongequal: "=", xtofrom: "\u21c4", xrightleftarrows: "\u21c4", xrightequilibrium: "\u21cc", xleftequilibrium: "\u21cb", "\\cdrightarrow": "\u2192", "\\cdleftarrow": "\u2190", "\\cdlongequal": "=" }, Tt = { overrightarrow: [["rightarrow"], .888, 522, "xMaxYMin"], overleftarrow: [["leftarrow"], .888, 522, "xMinYMin"], underrightarrow: [["rightarrow"], .888, 522, "xMaxYMin"], underleftarrow: [["leftarrow"], .888, 522, "xMinYMin"], xrightarrow: [["rightarrow"], 1.469, 522, "xMaxYMin"], "\\cdrightarrow": [["rightarrow"], 3, 522, "xMaxYMin"], xleftarrow: [["leftarrow"], 1.469, 522, "xMinYMin"], "\\cdleftarrow": [["leftarrow"], 3, 522, "xMinYMin"], Overrightarrow: [["doublerightarrow"], .888, 560, "xMaxYMin"], xRightarrow: [["doublerightarrow"], 1.526, 560, "xMaxYMin"], xLeftarrow: [["doubleleftarrow"], 1.526, 560, "xMinYMin"], overleftharpoon: [["leftharpoon"], .888, 522, "xMinYMin"], xleftharpoonup: [["leftharpoon"], .888, 522, "xMinYMin"], xleftharpoondown: [["leftharpoondown"], .888, 522, "xMinYMin"], overrightharpoon: [["rightharpoon"], .888, 522, "xMaxYMin"], xrightharpoonup: [["rightharpoon"], .888, 522, "xMaxYMin"], xrightharpoondown: [["rightharpoondown"], .888, 522, "xMaxYMin"], xlongequal: [["longequal"], .888, 334, "xMinYMin"], "\\cdlongequal": [["longequal"], 3, 334, "xMinYMin"], xtwoheadleftarrow: [["twoheadleftarrow"], .888, 334, "xMinYMin"], xtwoheadrightarrow: [["twoheadrightarrow"], .888, 334, "xMaxYMin"], overleftrightarrow: [["leftarrow", "rightarrow"], .888, 522], overbrace: [["leftbrace", "midbrace", "rightbrace"], 1.6, 548], underbrace: [["leftbraceunder", "midbraceunder", "rightbraceunder"], 1.6, 548], underleftrightarrow: [["leftarrow", "rightarrow"], .888, 522], xleftrightarrow: [["leftarrow", "rightarrow"], 1.75, 522], xLeftrightarrow: [["doubleleftarrow", "doublerightarrow"], 1.75, 560], xrightleftharpoons: [["leftharpoondownplus", "rightharpoonplus"], 1.75, 716], xleftrightharpoons: [["leftharpoonplus", "rightharpoondownplus"], 1.75, 716], xhookleftarrow: [["leftarrow", "righthook"], 1.08, 522], xhookrightarrow: [["lefthook", "rightarrow"], 1.08, 522], overlinesegment: [["leftlinesegment", "rightlinesegment"], .888, 522], underlinesegment: [["leftlinesegment", "rightlinesegment"], .888, 522], overgroup: [["leftgroup", "rightgroup"], .888, 342], undergroup: [["leftgroupunder", "rightgroupunder"], .888, 342], xmapsto: [["leftmapsto", "rightarrow"], 1.5, 522], xtofrom: [["leftToFrom", "rightToFrom"], 1.75, 528], xrightleftarrows: [["baraboveleftarrow", "rightarrowabovebar"], 1.75, 901], xrightequilibrium: [["baraboveshortleftharpoon", "rightharpoonaboveshortbar"], 1.75, 716], xleftequilibrium: [["shortbaraboveleftharpoon", "shortrightharpoonabovebar"], 1.75, 716] }; var Bt = function (e, t, r, n, o) { let s; const i = e.height + e.depth + r + n; if (/fbox|color|angl/.test(t)) { if (s = Ve.makeSpan(["stretchy", t], [], o), "fbox" === t) { const e = o.color && o.getColor(); e && (s.style.borderColor = e) } } else { const e = []; /^[bx]cancel$/.test(t) && e.push(new Q({ x1: "0", y1: "0", x2: "100%", y2: "100%", "stroke-width": "0.046em" })), /^x?cancel$/.test(t) && e.push(new Q({ x1: "0", y1: "100%", x2: "100%", y2: "0", "stroke-width": "0.046em" })); const r = new K(e, { width: "100%", height: F(i) }); s = Ve.makeSvgSpan([], [r], o) } return s.height = i, s.style.height = F(i), s }, Ct = function (e) { const t = new gt.MathNode("mo", [new gt.TextNode(At[e.replace(/^\\/, "")])]); return t.setAttribute("stretchy", "true"), t }, Nt = function (e, t) { const { span: r, minWidth: n, height: o } = function () { let r = 4e5; const n = e.label.slice(1); if (l.contains(["widehat", "widecheck", "widetilde", "utilde"], n)) { const s = "ordgroup" === (o = e.base).type ? o.body.length : 1; let i, a, l; if (s > 5) "widehat" === n || "widecheck" === n ? (i = 420, r = 2364, l = .42, a = n + "4") : (i = 312, r = 2340, l = .34, a = "tilde4"); else { const e = [1, 1, 2, 2, 3, 3][s]; "widehat" === n || "widecheck" === n ? (r = [0, 1062, 2364, 2364, 2364][e], i = [0, 239, 300, 360, 420][e], l = [0, .24, .3, .3, .36, .42][e], a = n + e) : (r = [0, 600, 1033, 2339, 2340][e], i = [0, 260, 286, 306, 312][e], l = [0, .26, .286, .3, .306, .34][e], a = "tilde" + e) } const h = new J(a), c = new K([h], { width: "100%", height: F(l), viewBox: "0 0 " + r + " " + i, preserveAspectRatio: "none" }); return { span: Ve.makeSvgSpan([], [c], t), minWidth: 0, height: l } } { const e = [], o = Tt[n], [s, i, a] = o, l = a / 1e3, h = s.length; let c, m; if (1 === h) { c = ["hide-tail"], m = [o[3]] } else if (2 === h) c = ["halfarrow-left", "halfarrow-right"], m = ["xMinYMin", "xMaxYMin"]; else { if (3 !== h) throw new Error("Correct katexImagesData or update code here to support\n " + h + " children."); c = ["brace-left", "brace-center", "brace-right"], m = ["xMinYMin", "xMidYMin", "xMaxYMin"] } for (let n = 0; n < h; n++) { const o = new J(s[n]), p = new K([o], { width: "400em", height: F(l), viewBox: "0 0 " + r + " " + a, preserveAspectRatio: m[n] + " slice" }), u = Ve.makeSvgSpan([c[n]], [p], t); if (1 === h) return { span: u, minWidth: i, height: l }; u.style.height = F(l), e.push(u) } return { span: Ve.makeSpan(["stretchy"], e, t), minWidth: i, height: l } } var o }(); return r.height = o, r.style.height = F(o), n > 0 && (r.style.minWidth = F(n)), r }; function qt(e, t) { if (!e || e.type !== t) throw new Error("Expected node of type " + t + ", but got " + (e ? "node of type " + e.type : String(e))); return e } function It(e) { const t = Rt(e); if (!t) throw new Error("Expected node of symbol group type, but got " + (e ? "node of type " + e.type : String(e))); return t } function Rt(e) { return e && ("atom" === e.type || re.hasOwnProperty(e.type)) ? e : null } const Ht = (e, t) => { let r, n, o; e && "supsub" === e.type ? (n = qt(e.base, "accent"), r = n.base, e.base = r, o = function (e) { if (e instanceof W) return e; throw new Error("Expected span but got " + String(e) + ".") }(ht(e, t)), e.base = n) : (n = qt(e, "accent"), r = n.base); const s = ht(r, t.havingCrampedStyle()); let i = 0; if (n.isShifty && l.isCharacterBox(r)) { const e = l.getBaseElem(r); i = ee(ht(e, t.havingCrampedStyle())).skew } const a = "\\c" === n.label; let h, c = a ? s.height + s.depth : Math.min(s.height, t.fontMetrics().xHeight); if (n.isStretchy) h = Nt(n, t), h = Ve.makeVList({ positionType: "firstBaseline", children: [{ type: "elem", elem: s }, { type: "elem", elem: h, wrapperClasses: ["svg-align"], wrapperStyle: i > 0 ? { width: "calc(100% - " + F(2 * i) + ")", marginLeft: F(2 * i) } : void 0 }] }, t); else { let e, r; "\\vec" === n.label ? (e = Ve.staticSvg("vec", t), r = Ve.svgData.vec[1]) : (e = Ve.makeOrd({ mode: n.mode, text: n.label }, t, "textord"), e = ee(e), e.italic = 0, r = e.width, a && (c += e.depth)), h = Ve.makeSpan(["accent-body"], [e]); const o = "\\textcircled" === n.label; o && (h.classes.push("accent-full"), c = s.height); let l = i; o || (l -= r / 2), h.style.left = F(l), "\\textcircled" === n.label && (h.style.top = ".2em"), h = Ve.makeVList({ positionType: "firstBaseline", children: [{ type: "elem", elem: s }, { type: "kern", size: -c }, { type: "elem", elem: h }] }, t) } const m = Ve.makeSpan(["mord", "accent"], [h], t); return o ? (o.children[0] = m, o.height = Math.max(m.height, o.height), o.classes[0] = "mord", o) : m }, Ot = (e, t) => { const r = e.isStretchy ? Ct(e.label) : new gt.MathNode("mo", [ft(e.label, e.mode)]), n = new gt.MathNode("mover", [vt(e.base, t), r]); return n.setAttribute("accent", "true"), n }, Et = new RegExp(["\\acute", "\\grave", "\\ddot", "\\tilde", "\\bar", "\\breve", "\\check", "\\hat", "\\vec", "\\dot", "\\mathring"].map((e => "\\" + e)).join("|")); je({ type: "accent", names: ["\\acute", "\\grave", "\\ddot", "\\tilde", "\\bar", "\\breve", "\\check", "\\hat", "\\vec", "\\dot", "\\mathring", "\\widecheck", "\\widehat", "\\widetilde", "\\overrightarrow", "\\overleftarrow", "\\Overrightarrow", "\\overleftrightarrow", "\\overgroup", "\\overlinesegment", "\\overleftharpoon", "\\overrightharpoon"], props: { numArgs: 1 }, handler: (e, t) => { const r = Ze(t[0]), n = !Et.test(e.funcName), o = !n || "\\widehat" === e.funcName || "\\widetilde" === e.funcName || "\\widecheck" === e.funcName; return { type: "accent", mode: e.parser.mode, label: e.funcName, isStretchy: n, isShifty: o, base: r } }, htmlBuilder: Ht, mathmlBuilder: Ot }), je({ type: "accent", names: ["\\'", "\\`", "\\^", "\\~", "\\=", "\\u", "\\.", '\\"', "\\c", "\\r", "\\H", "\\v", "\\textcircled"], props: { numArgs: 1, allowedInText: !0, allowedInMath: !0, argTypes: ["primitive"] }, handler: (e, t) => { const r = t[0]; let n = e.parser.mode; return "math" === n && (e.parser.settings.reportNonstrict("mathVsTextAccents", "LaTeX's accent " + e.funcName + " works only in text mode"), n = "text"), { type: "accent", mode: n, label: e.funcName, isStretchy: !1, isShifty: !0, base: r } }, htmlBuilder: Ht, mathmlBuilder: Ot }), je({ type: "accentUnder", names: ["\\underleftarrow", "\\underrightarrow", "\\underleftrightarrow", "\\undergroup", "\\underlinesegment", "\\utilde"], props: { numArgs: 1 }, handler: (e, t) => { let { parser: r, funcName: n } = e; const o = t[0]; return { type: "accentUnder", mode: r.mode, label: n, base: o } }, htmlBuilder: (e, t) => { const r = ht(e.base, t), n = Nt(e, t), o = "\\utilde" === e.label ? .12 : 0, s = Ve.makeVList({ positionType: "top", positionData: r.height, children: [{ type: "elem", elem: n, wrapperClasses: ["svg-align"] }, { type: "kern", size: o }, { type: "elem", elem: r }] }, t); return Ve.makeSpan(["mord", "accentunder"], [s], t) }, mathmlBuilder: (e, t) => { const r = Ct(e.label), n = new gt.MathNode("munder", [vt(e.base, t), r]); return n.setAttribute("accentunder", "true"), n } }); const Lt = e => { const t = new gt.MathNode("mpadded", e ? [e] : []); return t.setAttribute("width", "+0.6em"), t.setAttribute("lspace", "0.3em"), t }; je({ type: "xArrow", names: ["\\xleftarrow", "\\xrightarrow", "\\xLeftarrow", "\\xRightarrow", "\\xleftrightarrow", "\\xLeftrightarrow", "\\xhookleftarrow", "\\xhookrightarrow", "\\xmapsto", "\\xrightharpoondown", "\\xrightharpoonup", "\\xleftharpoondown", "\\xleftharpoonup", "\\xrightleftharpoons", "\\xleftrightharpoons", "\\xlongequal", "\\xtwoheadrightarrow", "\\xtwoheadleftarrow", "\\xtofrom", "\\xrightleftarrows", "\\xrightequilibrium", "\\xleftequilibrium", "\\\\cdrightarrow", "\\\\cdleftarrow", "\\\\cdlongequal"], props: { numArgs: 1, numOptionalArgs: 1 }, handler(e, t, r) { let { parser: n, funcName: o } = e; return { type: "xArrow", mode: n.mode, label: o, body: t[0], below: r[0] } }, htmlBuilder(e, t) { const r = t.style; let n = t.havingStyle(r.sup()); const o = Ve.wrapFragment(ht(e.body, n, t), t), s = "\\x" === e.label.slice(0, 2) ? "x" : "cd"; let i; o.classes.push(s + "-arrow-pad"), e.below && (n = t.havingStyle(r.sub()), i = Ve.wrapFragment(ht(e.below, n, t), t), i.classes.push(s + "-arrow-pad")); const a = Nt(e, t), l = -t.fontMetrics().axisHeight + .5 * a.height; let h, c = -t.fontMetrics().axisHeight - .5 * a.height - .111; if ((o.depth > .25 || "\\xleftequilibrium" === e.label) && (c -= o.depth), i) { const e = -t.fontMetrics().axisHeight + i.height + .5 * a.height + .111; h = Ve.makeVList({ positionType: "individualShift", children: [{ type: "elem", elem: o, shift: c }, { type: "elem", elem: a, shift: l }, { type: "elem", elem: i, shift: e }] }, t) } else h = Ve.makeVList({ positionType: "individualShift", children: [{ type: "elem", elem: o, shift: c }, { type: "elem", elem: a, shift: l }] }, t); return h.children[0].children[0].children[1].classes.push("svg-align"), Ve.makeSpan(["mrel", "x-arrow"], [h], t) }, mathmlBuilder(e, t) { const r = Ct(e.label); let n; if (r.setAttribute("minsize", "x" === e.label.charAt(0) ? "1.75em" : "3.0em"), e.body) { const o = Lt(vt(e.body, t)); if (e.below) { const s = Lt(vt(e.below, t)); n = new gt.MathNode("munderover", [r, s, o]) } else n = new gt.MathNode("mover", [r, o]) } else if (e.below) { const o = Lt(vt(e.below, t)); n = new gt.MathNode("munder", [r, o]) } else n = Lt(), n = new gt.MathNode("mover", [r, n]); return n } }); const Dt = Ve.makeSpan; function Vt(e, t) { const r = nt(e.body, t, !0); return Dt([e.mclass], r, t) } function Pt(e, t) { let r; const n = xt(e.body, t); return "minner" === e.mclass ? r = new gt.MathNode("mpadded", n) : "mord" === e.mclass ? e.isCharacterBox ? (r = n[0], r.type = "mi") : r = new gt.MathNode("mi", n) : (e.isCharacterBox ? (r = n[0], r.type = "mo") : r = new gt.MathNode("mo", n), "mbin" === e.mclass ? (r.attributes.lspace = "0.22em", r.attributes.rspace = "0.22em") : "mpunct" === e.mclass ? (r.attributes.lspace = "0em", r.attributes.rspace = "0.17em") : "mopen" === e.mclass || "mclose" === e.mclass ? (r.attributes.lspace = "0em", r.attributes.rspace = "0em") : "minner" === e.mclass && (r.attributes.lspace = "0.0556em", r.attributes.width = "+0.1111em")), r } je({ type: "mclass", names: ["\\mathord", "\\mathbin", "\\mathrel", "\\mathopen", "\\mathclose", "\\mathpunct", "\\mathinner"], props: { numArgs: 1, primitive: !0 }, handler(e, t) { let { parser: r, funcName: n } = e; const o = t[0]; return { type: "mclass", mode: r.mode, mclass: "m" + n.slice(5), body: Ke(o), isCharacterBox: l.isCharacterBox(o) } }, htmlBuilder: Vt, mathmlBuilder: Pt }); const Ft = e => { const t = "ordgroup" === e.type && e.body.length ? e.body[0] : e; return "atom" !== t.type || "bin" !== t.family && "rel" !== t.family ? "mord" : "m" + t.family }; je({ type: "mclass", names: ["\\@binrel"], props: { numArgs: 2 }, handler(e, t) { let { parser: r } = e; return { type: "mclass", mode: r.mode, mclass: Ft(t[0]), body: Ke(t[1]), isCharacterBox: l.isCharacterBox(t[1]) } } }), je({ type: "mclass", names: ["\\stackrel", "\\overset", "\\underset"], props: { numArgs: 2 }, handler(e, t) { let { parser: r, funcName: n } = e; const o = t[1], s = t[0]; let i; i = "\\stackrel" !== n ? Ft(o) : "mrel"; const a = { type: "op", mode: o.mode, limits: !0, alwaysHandleSupSub: !0, parentIsSupSub: !1, symbol: !1, suppressBaseShift: "\\stackrel" !== n, body: Ke(o) }, h = { type: "supsub", mode: s.mode, base: a, sup: "\\underset" === n ? null : s, sub: "\\underset" === n ? s : null }; return { type: "mclass", mode: r.mode, mclass: i, body: [h], isCharacterBox: l.isCharacterBox(h) } }, htmlBuilder: Vt, mathmlBuilder: Pt }), je({ type: "pmb", names: ["\\pmb"], props: { numArgs: 1, allowedInText: !0 }, handler(e, t) { let { parser: r } = e; return { type: "pmb", mode: r.mode, mclass: Ft(t[0]), body: Ke(t[0]) } }, htmlBuilder(e, t) { const r = nt(e.body, t, !0), n = Ve.makeSpan([e.mclass], r, t); return n.style.textShadow = "0.02em 0.01em 0.04px", n }, mathmlBuilder(e, t) { const r = xt(e.body, t), n = new gt.MathNode("mstyle", r); return n.setAttribute("style", "text-shadow: 0.02em 0.01em 0.04px"), n } }); const Gt = { ">": "\\\\cdrightarrow", "<": "\\\\cdleftarrow", "=": "\\\\cdlongequal", A: "\\uparrow", V: "\\downarrow", "|": "\\Vert", ".": "no arrow" }, Ut = e => "textord" === e.type && "@" === e.text; function Yt(e, t, r) { const n = Gt[e]; switch (n) { case "\\\\cdrightarrow": case "\\\\cdleftarrow": return r.callFunction(n, [t[0]], [t[1]]); case "\\uparrow": case "\\downarrow": { const e = { type: "atom", text: n, mode: "math", family: "rel" }, o = { type: "ordgroup", mode: "math", body: [r.callFunction("\\\\cdleft", [t[0]], []), r.callFunction("\\Big", [e], []), r.callFunction("\\\\cdright", [t[1]], [])] }; return r.callFunction("\\\\cdparent", [o], []) } case "\\\\cdlongequal": return r.callFunction("\\\\cdlongequal", [], []); case "\\Vert": { const e = { type: "textord", text: "\\Vert", mode: "math" }; return r.callFunction("\\Big", [e], []) } default: return { type: "textord", text: " ", mode: "math" } } } je({ type: "cdlabel", names: ["\\\\cdleft", "\\\\cdright"], props: { numArgs: 1 }, handler(e, t) { let { parser: r, funcName: n } = e; return { type: "cdlabel", mode: r.mode, side: n.slice(4), label: t[0] } }, htmlBuilder(e, t) { const r = t.havingStyle(t.style.sup()), n = Ve.wrapFragment(ht(e.label, r, t), t); return n.classes.push("cd-label-" + e.side), n.style.bottom = F(.8 - n.depth), n.height = 0, n.depth = 0, n }, mathmlBuilder(e, t) { let r = new gt.MathNode("mrow", [vt(e.label, t)]); return r = new gt.MathNode("mpadded", [r]), r.setAttribute("width", "0"), "left" === e.side && r.setAttribute("lspace", "-1width"), r.setAttribute("voffset", "0.7em"), r = new gt.MathNode("mstyle", [r]), r.setAttribute("displaystyle", "false"), r.setAttribute("scriptlevel", "1"), r } }), je({ type: "cdlabelparent", names: ["\\\\cdparent"], props: { numArgs: 1 }, handler(e, t) { let { parser: r } = e; return { type: "cdlabelparent", mode: r.mode, fragment: t[0] } }, htmlBuilder(e, t) { const r = Ve.wrapFragment(ht(e.fragment, t), t); return r.classes.push("cd-vert-arrow"), r }, mathmlBuilder(e, t) { return new gt.MathNode("mrow", [vt(e.fragment, t)]) } }), je({ type: "textord", names: ["\\@char"], props: { numArgs: 1, allowedInText: !0 }, handler(e, t) { let { parser: r } = e; const o = qt(t[0], "ordgroup").body; let s = ""; for (let e = 0; e < o.length; e++) { s += qt(o[e], "textord").text } let i, a = parseInt(s); if (isNaN(a)) throw new n("\\@char has non-numeric argument " + s); if (a < 0 || a >= 1114111) throw new n("\\@char with invalid code point " + s); return a <= 65535 ? i = String.fromCharCode(a) : (a -= 65536, i = String.fromCharCode(55296 + (a >> 10), 56320 + (1023 & a))), { type: "textord", mode: r.mode, text: i } } }); const Xt = (e, t) => { const r = nt(e.body, t.withColor(e.color), !1); return Ve.makeFragment(r) }, Wt = (e, t) => { const r = xt(e.body, t.withColor(e.color)), n = new gt.MathNode("mstyle", r); return n.setAttribute("mathcolor", e.color), n }; je({ type: "color", names: ["\\textcolor"], props: { numArgs: 2, allowedInText: !0, argTypes: ["color", "original"] }, handler(e, t) { let { parser: r } = e; const n = qt(t[0], "color-token").color, o = t[1]; return { type: "color", mode: r.mode, color: n, body: Ke(o) } }, htmlBuilder: Xt, mathmlBuilder: Wt }), je({ type: "color", names: ["\\color"], props: { numArgs: 1, allowedInText: !0, argTypes: ["color"] }, handler(e, t) { let { parser: r, breakOnTokenText: n } = e; const o = qt(t[0], "color-token").color; r.gullet.macros.set("\\current@color", o); const s = r.parseExpression(!0, n); return { type: "color", mode: r.mode, color: o, body: s } }, htmlBuilder: Xt, mathmlBuilder: Wt }), je({ type: "cr", names: ["\\\\"], props: { numArgs: 0, numOptionalArgs: 0, allowedInText: !0 }, handler(e, t, r) { let { parser: n } = e; const o = "[" === n.gullet.future().text ? n.parseSizeGroup(!0) : null, s = !n.settings.displayMode || !n.settings.useStrictBehavior("newLineInDisplayMode", "In LaTeX, \\\\ or \\newline does nothing in display mode"); return { type: "cr", mode: n.mode, newLine: s, size: o && qt(o, "size").value } }, htmlBuilder(e, t) { const r = Ve.makeSpan(["mspace"], [], t); return e.newLine && (r.classes.push("newline"), e.size && (r.style.marginTop = F(P(e.size, t)))), r }, mathmlBuilder(e, t) { const r = new gt.MathNode("mspace"); return e.newLine && (r.setAttribute("linebreak", "newline"), e.size && r.setAttribute("height", F(P(e.size, t)))), r } }); const _t = { "\\global": "\\global", "\\long": "\\\\globallong", "\\\\globallong": "\\\\globallong", "\\def": "\\gdef", "\\gdef": "\\gdef", "\\edef": "\\xdef", "\\xdef": "\\xdef", "\\let": "\\\\globallet", "\\futurelet": "\\\\globalfuture" }, jt = e => { const t = e.text; if (/^(?:[\\{}$&#^_]|EOF)$/.test(t)) throw new n("Expected a control sequence", e); return t }, $t = (e, t, r, n) => { let o = e.gullet.macros.get(r.text); null == o && (r.noexpand = !0, o = { tokens: [r], numArgs: 0, unexpandable: !e.gullet.isExpandable(r.text) }), e.gullet.macros.set(t, o, n) }; je({ type: "internal", names: ["\\global", "\\long", "\\\\globallong"], props: { numArgs: 0, allowedInText: !0 }, handler(e) { let { parser: t, funcName: r } = e; t.consumeSpaces(); const o = t.fetch(); if (_t[o.text]) return "\\global" !== r && "\\\\globallong" !== r || (o.text = _t[o.text]), qt(t.parseFunction(), "internal"); throw new n("Invalid token after macro prefix", o) } }), je({ type: "internal", names: ["\\def", "\\gdef", "\\edef", "\\xdef"], props: { numArgs: 0, allowedInText: !0, primitive: !0 }, handler(e) { let { parser: t, funcName: r } = e, o = t.gullet.popToken(); const s = o.text; if (/^(?:[\\{}$&#^_]|EOF)$/.test(s)) throw new n("Expected a control sequence", o); let i, a = 0; const l = [[]]; for (; "{" !== t.gullet.future().text;)if (o = t.gullet.popToken(), "#" === o.text) { if ("{" === t.gullet.future().text) { i = t.gullet.future(), l[a].push("{"); break } if (o = t.gullet.popToken(), !/^[1-9]$/.test(o.text)) throw new n('Invalid argument number "' + o.text + '"'); if (parseInt(o.text) !== a + 1) throw new n('Argument number "' + o.text + '" out of order'); a++, l.push([]) } else { if ("EOF" === o.text) throw new n("Expected a macro definition"); l[a].push(o.text) } let { tokens: h } = t.gullet.consumeArg(); return i && h.unshift(i), "\\edef" !== r && "\\xdef" !== r || (h = t.gullet.expandTokens(h), h.reverse()), t.gullet.macros.set(s, { tokens: h, numArgs: a, delimiters: l }, r === _t[r]), { type: "internal", mode: t.mode } } }), je({ type: "internal", names: ["\\let", "\\\\globallet"], props: { numArgs: 0, allowedInText: !0, primitive: !0 }, handler(e) { let { parser: t, funcName: r } = e; const n = jt(t.gullet.popToken()); t.gullet.consumeSpaces(); const o = (e => { let t = e.gullet.popToken(); return "=" === t.text && (t = e.gullet.popToken(), " " === t.text && (t = e.gullet.popToken())), t })(t); return $t(t, n, o, "\\\\globallet" === r), { type: "internal", mode: t.mode } } }), je({ type: "internal", names: ["\\futurelet", "\\\\globalfuture"], props: { numArgs: 0, allowedInText: !0, primitive: !0 }, handler(e) { let { parser: t, funcName: r } = e; const n = jt(t.gullet.popToken()), o = t.gullet.popToken(), s = t.gullet.popToken(); return $t(t, n, s, "\\\\globalfuture" === r), t.gullet.pushToken(s), t.gullet.pushToken(o), { type: "internal", mode: t.mode } } }); const Zt = function (e, t, r) { const n = N(oe.math[e] && oe.math[e].replace || e, t, r); if (!n) throw new Error("Unsupported symbol " + e + " and font size " + t + "."); return n }, Kt = function (e, t, r, n) { const o = r.havingBaseStyle(t), s = Ve.makeSpan(n.concat(o.sizingClasses(r)), [e], r), i = o.sizeMultiplier / r.sizeMultiplier; return s.height *= i, s.depth *= i, s.maxFontSize = o.sizeMultiplier, s }, Jt = function (e, t, r) { const n = t.havingBaseStyle(r), o = (1 - t.sizeMultiplier / n.sizeMultiplier) * t.fontMetrics().axisHeight; e.classes.push("delimcenter"), e.style.top = F(o), e.height -= o, e.depth += o }, Qt = function (e, t, r, n, o, s) { const i = function (e, t, r, n) { return Ve.makeSymbol(e, "Size" + t + "-Regular", r, n) }(e, t, o, n), a = Kt(Ve.makeSpan(["delimsizing", "size" + t], [i], n), w.TEXT, n, s); return r && Jt(a, n, w.TEXT), a }, er = function (e, t, r) { let n; n = "Size1-Regular" === t ? "delim-size1" : "delim-size4"; return { type: "elem", elem: Ve.makeSpan(["delimsizinginner", n], [Ve.makeSpan([], [Ve.makeSymbol(e, t, r)])]) } }, tr = function (e, t, r) { const n = T["Size4-Regular"][e.charCodeAt(0)] ? T["Size4-Regular"][e.charCodeAt(0)][4] : T["Size1-Regular"][e.charCodeAt(0)][4], o = new J("inner", function (e, t) { switch (e) { case "\u239c": return "M291 0 H417 V" + t + " H291z M291 0 H417 V" + t + " H291z"; case "\u2223": return "M145 0 H188 V" + t + " H145z M145 0 H188 V" + t + " H145z"; case "\u2225": return "M145 0 H188 V" + t + " H145z M145 0 H188 V" + t + " H145zM367 0 H410 V" + t + " H367z M367 0 H410 V" + t + " H367z"; case "\u239f": return "M457 0 H583 V" + t + " H457z M457 0 H583 V" + t + " H457z"; case "\u23a2": return "M319 0 H403 V" + t + " H319z M319 0 H403 V" + t + " H319z"; case "\u23a5": return "M263 0 H347 V" + t + " H263z M263 0 H347 V" + t + " H263z"; case "\u23aa": return "M384 0 H504 V" + t + " H384z M384 0 H504 V" + t + " H384z"; case "\u23d0": return "M312 0 H355 V" + t + " H312z M312 0 H355 V" + t + " H312z"; case "\u2016": return "M257 0 H300 V" + t + " H257z M257 0 H300 V" + t + " H257zM478 0 H521 V" + t + " H478z M478 0 H521 V" + t + " H478z"; default: return "" } }(e, Math.round(1e3 * t))), s = new K([o], { width: F(n), height: F(t), style: "width:" + F(n), viewBox: "0 0 " + 1e3 * n + " " + Math.round(1e3 * t), preserveAspectRatio: "xMinYMin" }), i = Ve.makeSvgSpan([], [s], r); return i.height = t, i.style.height = F(t), i.style.width = F(n), { type: "elem", elem: i } }, rr = { type: "kern", size: -.008 }, nr = ["|", "\\lvert", "\\rvert", "\\vert"], or = ["\\|", "\\lVert", "\\rVert", "\\Vert"], sr = function (e, t, r, n, o, s) { let i, a, h, c, m = "", p = 0; i = h = c = e, a = null; let u = "Size1-Regular"; "\\uparrow" === e ? h = c = "\u23d0" : "\\Uparrow" === e ? h = c = "\u2016" : "\\downarrow" === e ? i = h = "\u23d0" : "\\Downarrow" === e ? i = h = "\u2016" : "\\updownarrow" === e ? (i = "\\uparrow", h = "\u23d0", c = "\\downarrow") : "\\Updownarrow" === e ? (i = "\\Uparrow", h = "\u2016", c = "\\Downarrow") : l.contains(nr, e) ? (h = "\u2223", m = "vert", p = 333) : l.contains(or, e) ? (h = "\u2225", m = "doublevert", p = 556) : "[" === e || "\\lbrack" === e ? (i = "\u23a1", h = "\u23a2", c = "\u23a3", u = "Size4-Regular", m = "lbrack", p = 667) : "]" === e || "\\rbrack" === e ? (i = "\u23a4", h = "\u23a5", c = "\u23a6", u = "Size4-Regular", m = "rbrack", p = 667) : "\\lfloor" === e || "\u230a" === e ? (h = i = "\u23a2", c = "\u23a3", u = "Size4-Regular", m = "lfloor", p = 667) : "\\lceil" === e || "\u2308" === e ? (i = "\u23a1", h = c = "\u23a2", u = "Size4-Regular", m = "lceil", p = 667) : "\\rfloor" === e || "\u230b" === e ? (h = i = "\u23a5", c = "\u23a6", u = "Size4-Regular", m = "rfloor", p = 667) : "\\rceil" === e || "\u2309" === e ? (i = "\u23a4", h = c = "\u23a5", u = "Size4-Regular", m = "rceil", p = 667) : "(" === e || "\\lparen" === e ? (i = "\u239b", h = "\u239c", c = "\u239d", u = "Size4-Regular", m = "lparen", p = 875) : ")" === e || "\\rparen" === e ? (i = "\u239e", h = "\u239f", c = "\u23a0", u = "Size4-Regular", m = "rparen", p = 875) : "\\{" === e || "\\lbrace" === e ? (i = "\u23a7", a = "\u23a8", c = "\u23a9", h = "\u23aa", u = "Size4-Regular") : "\\}" === e || "\\rbrace" === e ? (i = "\u23ab", a = "\u23ac", c = "\u23ad", h = "\u23aa", u = "Size4-Regular") : "\\lgroup" === e || "\u27ee" === e ? (i = "\u23a7", c = "\u23a9", h = "\u23aa", u = "Size4-Regular") : "\\rgroup" === e || "\u27ef" === e ? (i = "\u23ab", c = "\u23ad", h = "\u23aa", u = "Size4-Regular") : "\\lmoustache" === e || "\u23b0" === e ? (i = "\u23a7", c = "\u23ad", h = "\u23aa", u = "Size4-Regular") : "\\rmoustache" !== e && "\u23b1" !== e || (i = "\u23ab", c = "\u23a9", h = "\u23aa", u = "Size4-Regular"); const d = Zt(i, u, o), g = d.height + d.depth, f = Zt(h, u, o), b = f.height + f.depth, y = Zt(c, u, o), x = y.height + y.depth; let v = 0, k = 1; if (null !== a) { const e = Zt(a, u, o); v = e.height + e.depth, k = 2 } const S = g + x + v, M = S + Math.max(0, Math.ceil((t - S) / (k * b))) * k * b; let z = n.fontMetrics().axisHeight; r && (z *= n.sizeMultiplier); const A = M / 2 - z, T = []; if (m.length > 0) { const e = M - g - x, t = Math.round(1e3 * M), r = function (e, t) { switch (e) { case "lbrack": return "M403 1759 V84 H666 V0 H319 V1759 v" + t + " v1759 h347 v-84\nH403z M403 1759 V0 H319 V1759 v" + t + " v1759 h84z"; case "rbrack": return "M347 1759 V0 H0 V84 H263 V1759 v" + t + " v1759 H0 v84 H347z\nM347 1759 V0 H263 V1759 v" + t + " v1759 h84z"; case "vert": return "M145 15 v585 v" + t + " v585 c2.667,10,9.667,15,21,15\nc10,0,16.667,-5,20,-15 v-585 v" + -t + " v-585 c-2.667,-10,-9.667,-15,-21,-15\nc-10,0,-16.667,5,-20,15z M188 15 H145 v585 v" + t + " v585 h43z"; case "doublevert": return "M145 15 v585 v" + t + " v585 c2.667,10,9.667,15,21,15\nc10,0,16.667,-5,20,-15 v-585 v" + -t + " v-585 c-2.667,-10,-9.667,-15,-21,-15\nc-10,0,-16.667,5,-20,15z M188 15 H145 v585 v" + t + " v585 h43z\nM367 15 v585 v" + t + " v585 c2.667,10,9.667,15,21,15\nc10,0,16.667,-5,20,-15 v-585 v" + -t + " v-585 c-2.667,-10,-9.667,-15,-21,-15\nc-10,0,-16.667,5,-20,15z M410 15 H367 v585 v" + t + " v585 h43z"; case "lfloor": return "M319 602 V0 H403 V602 v" + t + " v1715 h263 v84 H319z\nMM319 602 V0 H403 V602 v" + t + " v1715 H319z"; case "rfloor": return "M319 602 V0 H403 V602 v" + t + " v1799 H0 v-84 H319z\nMM319 602 V0 H403 V602 v" + t + " v1715 H319z"; case "lceil": return "M403 1759 V84 H666 V0 H319 V1759 v" + t + " v602 h84z\nM403 1759 V0 H319 V1759 v" + t + " v602 h84z"; case "rceil": return "M347 1759 V0 H0 V84 H263 V1759 v" + t + " v602 h84z\nM347 1759 V0 h-84 V1759 v" + t + " v602 h84z"; case "lparen": return "M863,9c0,-2,-2,-5,-6,-9c0,0,-17,0,-17,0c-12.7,0,-19.3,0.3,-20,1\nc-5.3,5.3,-10.3,11,-15,17c-242.7,294.7,-395.3,682,-458,1162c-21.3,163.3,-33.3,349,\n-36,557 l0," + (t + 84) + "c0.2,6,0,26,0,60c2,159.3,10,310.7,24,454c53.3,528,210,\n949.7,470,1265c4.7,6,9.7,11.7,15,17c0.7,0.7,7,1,19,1c0,0,18,0,18,0c4,-4,6,-7,6,-9\nc0,-2.7,-3.3,-8.7,-10,-18c-135.3,-192.7,-235.5,-414.3,-300.5,-665c-65,-250.7,-102.5,\n-544.7,-112.5,-882c-2,-104,-3,-167,-3,-189\nl0,-" + (t + 92) + "c0,-162.7,5.7,-314,17,-454c20.7,-272,63.7,-513,129,-723c65.3,\n-210,155.3,-396.3,270,-559c6.7,-9.3,10,-15.3,10,-18z"; case "rparen": return "M76,0c-16.7,0,-25,3,-25,9c0,2,2,6.3,6,13c21.3,28.7,42.3,60.3,\n63,95c96.7,156.7,172.8,332.5,228.5,527.5c55.7,195,92.8,416.5,111.5,664.5\nc11.3,139.3,17,290.7,17,454c0,28,1.7,43,3.3,45l0," + (t + 9) + "\nc-3,4,-3.3,16.7,-3.3,38c0,162,-5.7,313.7,-17,455c-18.7,248,-55.8,469.3,-111.5,664\nc-55.7,194.7,-131.8,370.3,-228.5,527c-20.7,34.7,-41.7,66.3,-63,95c-2,3.3,-4,7,-6,11\nc0,7.3,5.7,11,17,11c0,0,11,0,11,0c9.3,0,14.3,-0.3,15,-1c5.3,-5.3,10.3,-11,15,-17\nc242.7,-294.7,395.3,-681.7,458,-1161c21.3,-164.7,33.3,-350.7,36,-558\nl0,-" + (t + 144) + "c-2,-159.3,-10,-310.7,-24,-454c-53.3,-528,-210,-949.7,\n-470,-1265c-4.7,-6,-9.7,-11.7,-15,-17c-0.7,-0.7,-6.7,-1,-18,-1z"; default: throw new Error("Unknown stretchy delimiter.") } }(m, Math.round(1e3 * e)), o = new J(m, r), s = (p / 1e3).toFixed(3) + "em", i = (t / 1e3).toFixed(3) + "em", a = new K([o], { width: s, height: i, viewBox: "0 0 " + p + " " + t }), l = Ve.makeSvgSpan([], [a], n); l.height = t / 1e3, l.style.width = s, l.style.height = i, T.push({ type: "elem", elem: l }) } else { if (T.push(er(c, u, o)), T.push(rr), null === a) { const e = M - g - x + .016; T.push(tr(h, e, n)) } else { const e = (M - g - x - v) / 2 + .016; T.push(tr(h, e, n)), T.push(rr), T.push(er(a, u, o)), T.push(rr), T.push(tr(h, e, n)) } T.push(rr), T.push(er(i, u, o)) } const B = n.havingBaseStyle(w.TEXT), C = Ve.makeVList({ positionType: "bottom", positionData: A, children: T }, B); return Kt(Ve.makeSpan(["delimsizing", "mult"], [C], B), w.TEXT, n, s) }, ir = .08, ar = function (e, t, r, n, o) { const s = function (e, t, r) { t *= 1e3; let n = ""; switch (e) { case "sqrtMain": n = function (e, t) { return "M95," + (622 + e + t) + "\nc-2.7,0,-7.17,-2.7,-13.5,-8c-5.8,-5.3,-9.5,-10,-9.5,-14\nc0,-2,0.3,-3.3,1,-4c1.3,-2.7,23.83,-20.7,67.5,-54\nc44.2,-33.3,65.8,-50.3,66.5,-51c1.3,-1.3,3,-2,5,-2c4.7,0,8.7,3.3,12,10\ns173,378,173,378c0.7,0,35.3,-71,104,-213c68.7,-142,137.5,-285,206.5,-429\nc69,-144,104.5,-217.7,106.5,-221\nl" + e / 2.075 + " -" + e + "\nc5.3,-9.3,12,-14,20,-14\nH400000v" + (40 + e) + "H845.2724\ns-225.272,467,-225.272,467s-235,486,-235,486c-2.7,4.7,-9,7,-19,7\nc-6,0,-10,-1,-12,-3s-194,-422,-194,-422s-65,47,-65,47z\nM" + (834 + e) + " " + t + "h400000v" + (40 + e) + "h-400000z" }(t, M); break; case "sqrtSize1": n = function (e, t) { return "M263," + (601 + e + t) + "c0.7,0,18,39.7,52,119\nc34,79.3,68.167,158.7,102.5,238c34.3,79.3,51.8,119.3,52.5,120\nc340,-704.7,510.7,-1060.3,512,-1067\nl" + e / 2.084 + " -" + e + "\nc4.7,-7.3,11,-11,19,-11\nH40000v" + (40 + e) + "H1012.3\ns-271.3,567,-271.3,567c-38.7,80.7,-84,175,-136,283c-52,108,-89.167,185.3,-111.5,232\nc-22.3,46.7,-33.8,70.3,-34.5,71c-4.7,4.7,-12.3,7,-23,7s-12,-1,-12,-1\ns-109,-253,-109,-253c-72.7,-168,-109.3,-252,-110,-252c-10.7,8,-22,16.7,-34,26\nc-22,17.3,-33.3,26,-34,26s-26,-26,-26,-26s76,-59,76,-59s76,-60,76,-60z\nM" + (1001 + e) + " " + t + "h400000v" + (40 + e) + "h-400000z" }(t, M); break; case "sqrtSize2": n = function (e, t) { return "M983 " + (10 + e + t) + "\nl" + e / 3.13 + " -" + e + "\nc4,-6.7,10,-10,18,-10 H400000v" + (40 + e) + "\nH1013.1s-83.4,268,-264.1,840c-180.7,572,-277,876.3,-289,913c-4.7,4.7,-12.7,7,-24,7\ns-12,0,-12,0c-1.3,-3.3,-3.7,-11.7,-7,-25c-35.3,-125.3,-106.7,-373.3,-214,-744\nc-10,12,-21,25,-33,39s-32,39,-32,39c-6,-5.3,-15,-14,-27,-26s25,-30,25,-30\nc26.7,-32.7,52,-63,76,-91s52,-60,52,-60s208,722,208,722\nc56,-175.3,126.3,-397.3,211,-666c84.7,-268.7,153.8,-488.2,207.5,-658.5\nc53.7,-170.3,84.5,-266.8,92.5,-289.5z\nM" + (1001 + e) + " " + t + "h400000v" + (40 + e) + "h-400000z" }(t, M); break; case "sqrtSize3": n = function (e, t) { return "M424," + (2398 + e + t) + "\nc-1.3,-0.7,-38.5,-172,-111.5,-514c-73,-342,-109.8,-513.3,-110.5,-514\nc0,-2,-10.7,14.3,-32,49c-4.7,7.3,-9.8,15.7,-15.5,25c-5.7,9.3,-9.8,16,-12.5,20\ns-5,7,-5,7c-4,-3.3,-8.3,-7.7,-13,-13s-13,-13,-13,-13s76,-122,76,-122s77,-121,77,-121\ns209,968,209,968c0,-2,84.7,-361.7,254,-1079c169.3,-717.3,254.7,-1077.7,256,-1081\nl" + e / 4.223 + " -" + e + "c4,-6.7,10,-10,18,-10 H400000\nv" + (40 + e) + "H1014.6\ns-87.3,378.7,-272.6,1166c-185.3,787.3,-279.3,1182.3,-282,1185\nc-2,6,-10,9,-24,9\nc-8,0,-12,-0.7,-12,-2z M" + (1001 + e) + " " + t + "\nh400000v" + (40 + e) + "h-400000z" }(t, M); break; case "sqrtSize4": n = function (e, t) { return "M473," + (2713 + e + t) + "\nc339.3,-1799.3,509.3,-2700,510,-2702 l" + e / 5.298 + " -" + e + "\nc3.3,-7.3,9.3,-11,18,-11 H400000v" + (40 + e) + "H1017.7\ns-90.5,478,-276.2,1466c-185.7,988,-279.5,1483,-281.5,1485c-2,6,-10,9,-24,9\nc-8,0,-12,-0.7,-12,-2c0,-1.3,-5.3,-32,-16,-92c-50.7,-293.3,-119.7,-693.3,-207,-1200\nc0,-1.3,-5.3,8.7,-16,30c-10.7,21.3,-21.3,42.7,-32,64s-16,33,-16,33s-26,-26,-26,-26\ns76,-153,76,-153s77,-151,77,-151c0.7,0.7,35.7,202,105,604c67.3,400.7,102,602.7,104,\n606zM" + (1001 + e) + " " + t + "h400000v" + (40 + e) + "H1017.7z" }(t, M); break; case "sqrtTall": n = function (e, t, r) { return "M702 " + (e + t) + "H400000" + (40 + e) + "\nH742v" + (r - 54 - t - e) + "l-4 4-4 4c-.667.7 -2 1.5-4 2.5s-4.167 1.833-6.5 2.5-5.5 1-9.5 1\nh-12l-28-84c-16.667-52-96.667 -294.333-240-727l-212 -643 -85 170\nc-4-3.333-8.333-7.667-13 -13l-13-13l77-155 77-156c66 199.333 139 419.667\n219 661 l218 661zM702 " + t + "H400000v" + (40 + e) + "H742z" }(t, M, r) }return n }(e, n, r), i = new J(e, s), a = new K([i], { width: "400em", height: F(t), viewBox: "0 0 400000 " + r, preserveAspectRatio: "xMinYMin slice" }); return Ve.makeSvgSpan(["hide-tail"], [a], o) }, lr = ["(", "\\lparen", ")", "\\rparen", "[", "\\lbrack", "]", "\\rbrack", "\\{", "\\lbrace", "\\}", "\\rbrace", "\\lfloor", "\\rfloor", "\u230a", "\u230b", "\\lceil", "\\rceil", "\u2308", "\u2309", "\\surd"], hr = ["\\uparrow", "\\downarrow", "\\updownarrow", "\\Uparrow", "\\Downarrow", "\\Updownarrow", "|", "\\|", "\\vert", "\\Vert", "\\lvert", "\\rvert", "\\lVert", "\\rVert", "\\lgroup", "\\rgroup", "\u27ee", "\u27ef", "\\lmoustache", "\\rmoustache", "\u23b0", "\u23b1"], cr = ["<", ">", "\\langle", "\\rangle", "/", "\\backslash", "\\lt", "\\gt"], mr = [0, 1.2, 1.8, 2.4, 3], pr = [{ type: "small", style: w.SCRIPTSCRIPT }, { type: "small", style: w.SCRIPT }, { type: "small", style: w.TEXT }, { type: "large", size: 1 }, { type: "large", size: 2 }, { type: "large", size: 3 }, { type: "large", size: 4 }], ur = [{ type: "small", style: w.SCRIPTSCRIPT }, { type: "small", style: w.SCRIPT }, { type: "small", style: w.TEXT }, { type: "stack" }], dr = [{ type: "small", style: w.SCRIPTSCRIPT }, { type: "small", style: w.SCRIPT }, { type: "small", style: w.TEXT }, { type: "large", size: 1 }, { type: "large", size: 2 }, { type: "large", size: 3 }, { type: "large", size: 4 }, { type: "stack" }], gr = function (e) { if ("small" === e.type) return "Main-Regular"; if ("large" === e.type) return "Size" + e.size + "-Regular"; if ("stack" === e.type) return "Size4-Regular"; throw new Error("Add support for delim type '" + e.type + "' here.") }, fr = function (e, t, r, n) { for (let o = Math.min(2, 3 - n.style.size); o < r.length && "stack" !== r[o].type; o++) { const s = Zt(e, gr(r[o]), "math"); let i = s.height + s.depth; if ("small" === r[o].type) { i *= n.havingBaseStyle(r[o].style).sizeMultiplier } if (i > t) return r[o] } return r[r.length - 1] }, br = function (e, t, r, n, o, s) { let i; "<" === e || "\\lt" === e || "\u27e8" === e ? e = "\\langle" : ">" !== e && "\\gt" !== e && "\u27e9" !== e || (e = "\\rangle"), i = l.contains(cr, e) ? pr : l.contains(lr, e) ? dr : ur; const a = fr(e, t, i, n); return "small" === a.type ? function (e, t, r, n, o, s) { const i = Ve.makeSymbol(e, "Main-Regular", o, n), a = Kt(i, t, n, s); return r && Jt(a, n, t), a }(e, a.style, r, n, o, s) : "large" === a.type ? Qt(e, a.size, r, n, o, s) : sr(e, t, r, n, o, s) }; var yr = { sqrtImage: function (e, t) { const r = t.havingBaseSizing(), n = fr("\\surd", e * r.sizeMultiplier, dr, r); let o = r.sizeMultiplier; const s = Math.max(0, t.minRuleThickness - t.fontMetrics().sqrtRuleThickness); let i, a, l = 0, h = 0, c = 0; return "small" === n.type ? (c = 1e3 + 1e3 * s + 80, e < 1 ? o = 1 : e < 1.4 && (o = .7), l = (1 + s + ir) / o, h = (1 + s) / o, i = ar("sqrtMain", l, c, s, t), i.style.minWidth = "0.853em", a = .833 / o) : "large" === n.type ? (c = 1080 * mr[n.size], h = (mr[n.size] + s) / o, l = (mr[n.size] + s + ir) / o, i = ar("sqrtSize" + n.size, l, c, s, t), i.style.minWidth = "1.02em", a = 1 / o) : (l = e + s + ir, h = e + s, c = Math.floor(1e3 * e + s) + 80, i = ar("sqrtTall", l, c, s, t), i.style.minWidth = "0.742em", a = 1.056), i.height = h, i.style.height = F(l), { span: i, advanceWidth: a, ruleWidth: (t.fontMetrics().sqrtRuleThickness + s) * o } }, sizedDelim: function (e, t, r, o, s) { if ("<" === e || "\\lt" === e || "\u27e8" === e ? e = "\\langle" : ">" !== e && "\\gt" !== e && "\u27e9" !== e || (e = "\\rangle"), l.contains(lr, e) || l.contains(cr, e)) return Qt(e, t, !1, r, o, s); if (l.contains(hr, e)) return sr(e, mr[t], !1, r, o, s); throw new n("Illegal delimiter: '" + e + "'") }, sizeToMaxHeight: mr, customSizedDelim: br, leftRightDelim: function (e, t, r, n, o, s) { const i = n.fontMetrics().axisHeight * n.sizeMultiplier, a = 5 / n.fontMetrics().ptPerEm, l = Math.max(t - i, r + i), h = Math.max(l / 500 * 901, 2 * l - a); return br(e, h, !0, n, o, s) } }; const xr = { "\\bigl": { mclass: "mopen", size: 1 }, "\\Bigl": { mclass: "mopen", size: 2 }, "\\biggl": { mclass: "mopen", size: 3 }, "\\Biggl": { mclass: "mopen", size: 4 }, "\\bigr": { mclass: "mclose", size: 1 }, "\\Bigr": { mclass: "mclose", size: 2 }, "\\biggr": { mclass: "mclose", size: 3 }, "\\Biggr": { mclass: "mclose", size: 4 }, "\\bigm": { mclass: "mrel", size: 1 }, "\\Bigm": { mclass: "mrel", size: 2 }, "\\biggm": { mclass: "mrel", size: 3 }, "\\Biggm": { mclass: "mrel", size: 4 }, "\\big": { mclass: "mord", size: 1 }, "\\Big": { mclass: "mord", size: 2 }, "\\bigg": { mclass: "mord", size: 3 }, "\\Bigg": { mclass: "mord", size: 4 } }, wr = ["(", "\\lparen", ")", "\\rparen", "[", "\\lbrack", "]", "\\rbrack", "\\{", "\\lbrace", "\\}", "\\rbrace", "\\lfloor", "\\rfloor", "\u230a", "\u230b", "\\lceil", "\\rceil", "\u2308", "\u2309", "<", ">", "\\langle", "\u27e8", "\\rangle", "\u27e9", "\\lt", "\\gt", "\\lvert", "\\rvert", "\\lVert", "\\rVert", "\\lgroup", "\\rgroup", "\u27ee", "\u27ef", "\\lmoustache", "\\rmoustache", "\u23b0", "\u23b1", "/", "\\backslash", "|", "\\vert", "\\|", "\\Vert", "\\uparrow", "\\Uparrow", "\\downarrow", "\\Downarrow", "\\updownarrow", "\\Updownarrow", "."]; function vr(e, t) { const r = Rt(e); if (r && l.contains(wr, r.text)) return r; throw new n(r ? "Invalid delimiter '" + r.text + "' after '" + t.funcName + "'" : "Invalid delimiter type '" + e.type + "'", e) } function kr(e) { if (!e.body) throw new Error("Bug: The leftright ParseNode wasn't fully parsed.") } je({ type: "delimsizing", names: ["\\bigl", "\\Bigl", "\\biggl", "\\Biggl", "\\bigr", "\\Bigr", "\\biggr", "\\Biggr", "\\bigm", "\\Bigm", "\\biggm", "\\Biggm", "\\big", "\\Big", "\\bigg", "\\Bigg"], props: { numArgs: 1, argTypes: ["primitive"] }, handler: (e, t) => { const r = vr(t[0], e); return { type: "delimsizing", mode: e.parser.mode, size: xr[e.funcName].size, mclass: xr[e.funcName].mclass, delim: r.text } }, htmlBuilder: (e, t) => "." === e.delim ? Ve.makeSpan([e.mclass]) : yr.sizedDelim(e.delim, e.size, t, e.mode, [e.mclass]), mathmlBuilder: e => { const t = []; "." !== e.delim && t.push(ft(e.delim, e.mode)); const r = new gt.MathNode("mo", t); "mopen" === e.mclass || "mclose" === e.mclass ? r.setAttribute("fence", "true") : r.setAttribute("fence", "false"), r.setAttribute("stretchy", "true"); const n = F(yr.sizeToMaxHeight[e.size]); return r.setAttribute("minsize", n), r.setAttribute("maxsize", n), r } }), je({ type: "leftright-right", names: ["\\right"], props: { numArgs: 1, primitive: !0 }, handler: (e, t) => { const r = e.parser.gullet.macros.get("\\current@color"); if (r && "string" != typeof r) throw new n("\\current@color set to non-string in \\right"); return { type: "leftright-right", mode: e.parser.mode, delim: vr(t[0], e).text, color: r } } }), je({ type: "leftright", names: ["\\left"], props: { numArgs: 1, primitive: !0 }, handler: (e, t) => { const r = vr(t[0], e), n = e.parser; ++n.leftrightDepth; const o = n.parseExpression(!1); --n.leftrightDepth, n.expect("\\right", !1); const s = qt(n.parseFunction(), "leftright-right"); return { type: "leftright", mode: n.mode, body: o, left: r.text, right: s.delim, rightColor: s.color } }, htmlBuilder: (e, t) => { kr(e); const r = nt(e.body, t, !0, ["mopen", "mclose"]); let n, o, s = 0, i = 0, a = !1; for (let e = 0; e < r.length; e++)r[e].isMiddle ? a = !0 : (s = Math.max(r[e].height, s), i = Math.max(r[e].depth, i)); if (s *= t.sizeMultiplier, i *= t.sizeMultiplier, n = "." === e.left ? lt(t, ["mopen"]) : yr.leftRightDelim(e.left, s, i, t, e.mode, ["mopen"]), r.unshift(n), a) for (let t = 1; t < r.length; t++) { const n = r[t].isMiddle; n && (r[t] = yr.leftRightDelim(n.delim, s, i, n.options, e.mode, [])) } if ("." === e.right) o = lt(t, ["mclose"]); else { const r = e.rightColor ? t.withColor(e.rightColor) : t; o = yr.leftRightDelim(e.right, s, i, r, e.mode, ["mclose"]) } return r.push(o), Ve.makeSpan(["minner"], r, t) }, mathmlBuilder: (e, t) => { kr(e); const r = xt(e.body, t); if ("." !== e.left) { const t = new gt.MathNode("mo", [ft(e.left, e.mode)]); t.setAttribute("fence", "true"), r.unshift(t) } if ("." !== e.right) { const t = new gt.MathNode("mo", [ft(e.right, e.mode)]); t.setAttribute("fence", "true"), e.rightColor && t.setAttribute("mathcolor", e.rightColor), r.push(t) } return bt(r) } }), je({ type: "middle", names: ["\\middle"], props: { numArgs: 1, primitive: !0 }, handler: (e, t) => { const r = vr(t[0], e); if (!e.parser.leftrightDepth) throw new n("\\middle without preceding \\left", r); return { type: "middle", mode: e.parser.mode, delim: r.text } }, htmlBuilder: (e, t) => { let r; if ("." === e.delim) r = lt(t, []); else { r = yr.sizedDelim(e.delim, 1, t, e.mode, []); const n = { delim: e.delim, options: t }; r.isMiddle = n } return r }, mathmlBuilder: (e, t) => { const r = "\\vert" === e.delim || "|" === e.delim ? ft("|", "text") : ft(e.delim, e.mode), n = new gt.MathNode("mo", [r]); return n.setAttribute("fence", "true"), n.setAttribute("lspace", "0.05em"), n.setAttribute("rspace", "0.05em"), n } }); const Sr = (e, t) => { const r = Ve.wrapFragment(ht(e.body, t), t), n = e.label.slice(1); let o, s = t.sizeMultiplier, i = 0; const a = l.isCharacterBox(e.body); if ("sout" === n) o = Ve.makeSpan(["stretchy", "sout"]), o.height = t.fontMetrics().defaultRuleThickness / s, i = -.5 * t.fontMetrics().xHeight; else if ("phase" === n) { const e = P({ number: .6, unit: "pt" }, t), n = P({ number: .35, unit: "ex" }, t); s /= t.havingBaseSizing().sizeMultiplier; const a = r.height + r.depth + e + n; r.style.paddingLeft = F(a / 2 + e); const l = Math.floor(1e3 * a * s), c = "M400000 " + (h = l) + " H0 L" + h / 2 + " 0 l65 45 L145 " + (h - 80) + " H400000z", m = new K([new J("phase", c)], { width: "400em", height: F(l / 1e3), viewBox: "0 0 400000 " + l, preserveAspectRatio: "xMinYMin slice" }); o = Ve.makeSvgSpan(["hide-tail"], [m], t), o.style.height = F(a), i = r.depth + e + n } else { /cancel/.test(n) ? a || r.classes.push("cancel-pad") : "angl" === n ? r.classes.push("anglpad") : r.classes.push("boxpad"); let s = 0, l = 0, h = 0; /box/.test(n) ? (h = Math.max(t.fontMetrics().fboxrule, t.minRuleThickness), s = t.fontMetrics().fboxsep + ("colorbox" === n ? 0 : h), l = s) : "angl" === n ? (h = Math.max(t.fontMetrics().defaultRuleThickness, t.minRuleThickness), s = 4 * h, l = Math.max(0, .25 - r.depth)) : (s = a ? .2 : 0, l = s), o = Bt(r, n, s, l, t), /fbox|boxed|fcolorbox/.test(n) ? (o.style.borderStyle = "solid", o.style.borderWidth = F(h)) : "angl" === n && .049 !== h && (o.style.borderTopWidth = F(h), o.style.borderRightWidth = F(h)), i = r.depth + l, e.backgroundColor && (o.style.backgroundColor = e.backgroundColor, e.borderColor && (o.style.borderColor = e.borderColor)) } var h; let c; if (e.backgroundColor) c = Ve.makeVList({ positionType: "individualShift", children: [{ type: "elem", elem: o, shift: i }, { type: "elem", elem: r, shift: 0 }] }, t); else { const e = /cancel|phase/.test(n) ? ["svg-align"] : []; c = Ve.makeVList({ positionType: "individualShift", children: [{ type: "elem", elem: r, shift: 0 }, { type: "elem", elem: o, shift: i, wrapperClasses: e }] }, t) } return /cancel/.test(n) && (c.height = r.height, c.depth = r.depth), /cancel/.test(n) && !a ? Ve.makeSpan(["mord", "cancel-lap"], [c], t) : Ve.makeSpan(["mord"], [c], t) }, Mr = (e, t) => { let r = 0; const n = new gt.MathNode(e.label.indexOf("colorbox") > -1 ? "mpadded" : "menclose", [vt(e.body, t)]); switch (e.label) { case "\\cancel": n.setAttribute("notation", "updiagonalstrike"); break; case "\\bcancel": n.setAttribute("notation", "downdiagonalstrike"); break; case "\\phase": n.setAttribute("notation", "phasorangle"); break; case "\\sout": n.setAttribute("notation", "horizontalstrike"); break; case "\\fbox": n.setAttribute("notation", "box"); break; case "\\angl": n.setAttribute("notation", "actuarial"); break; case "\\fcolorbox": case "\\colorbox": if (r = t.fontMetrics().fboxsep * t.fontMetrics().ptPerEm, n.setAttribute("width", "+" + 2 * r + "pt"), n.setAttribute("height", "+" + 2 * r + "pt"), n.setAttribute("lspace", r + "pt"), n.setAttribute("voffset", r + "pt"), "\\fcolorbox" === e.label) { const r = Math.max(t.fontMetrics().fboxrule, t.minRuleThickness); n.setAttribute("style", "border: " + r + "em solid " + String(e.borderColor)) } break; case "\\xcancel": n.setAttribute("notation", "updiagonalstrike downdiagonalstrike") }return e.backgroundColor && n.setAttribute("mathbackground", e.backgroundColor), n }; je({ type: "enclose", names: ["\\colorbox"], props: { numArgs: 2, allowedInText: !0, argTypes: ["color", "text"] }, handler(e, t, r) { let { parser: n, funcName: o } = e; const s = qt(t[0], "color-token").color, i = t[1]; return { type: "enclose", mode: n.mode, label: o, backgroundColor: s, body: i } }, htmlBuilder: Sr, mathmlBuilder: Mr }), je({ type: "enclose", names: ["\\fcolorbox"], props: { numArgs: 3, allowedInText: !0, argTypes: ["color", "color", "text"] }, handler(e, t, r) { let { parser: n, funcName: o } = e; const s = qt(t[0], "color-token").color, i = qt(t[1], "color-token").color, a = t[2]; return { type: "enclose", mode: n.mode, label: o, backgroundColor: i, borderColor: s, body: a } }, htmlBuilder: Sr, mathmlBuilder: Mr }), je({ type: "enclose", names: ["\\fbox"], props: { numArgs: 1, argTypes: ["hbox"], allowedInText: !0 }, handler(e, t) { let { parser: r } = e; return { type: "enclose", mode: r.mode, label: "\\fbox", body: t[0] } } }), je({ type: "enclose", names: ["\\cancel", "\\bcancel", "\\xcancel", "\\sout", "\\phase"], props: { numArgs: 1 }, handler(e, t) { let { parser: r, funcName: n } = e; const o = t[0]; return { type: "enclose", mode: r.mode, label: n, body: o } }, htmlBuilder: Sr, mathmlBuilder: Mr }), je({ type: "enclose", names: ["\\angl"], props: { numArgs: 1, argTypes: ["hbox"], allowedInText: !1 }, handler(e, t) { let { parser: r } = e; return { type: "enclose", mode: r.mode, label: "\\angl", body: t[0] } } }); const zr = {}; function Ar(e) { let { type: t, names: r, props: n, handler: o, htmlBuilder: s, mathmlBuilder: i } = e; const a = { type: t, numArgs: n.numArgs || 0, allowedInText: !1, numOptionalArgs: 0, handler: o }; for (let e = 0; e < r.length; ++e)zr[r[e]] = a; s && (We[t] = s), i && (_e[t] = i) } const Tr = {}; function Br(e, t) { Tr[e] = t } class Cr { constructor(e, t, r) { this.lexer = void 0, this.start = void 0, this.end = void 0, this.lexer = e, this.start = t, this.end = r } static range(e, t) { return t ? e && e.loc && t.loc && e.loc.lexer === t.loc.lexer ? new Cr(e.loc.lexer, e.loc.start, t.loc.end) : null : e && e.loc } } class Nr { constructor(e, t) { this.text = void 0, this.loc = void 0, this.noexpand = void 0, this.treatAsRelax = void 0, this.text = e, this.loc = t } range(e, t) { return new Nr(t, Cr.range(this, e)) } } function qr(e) { const t = []; e.consumeSpaces(); let r = e.fetch().text; for ("\\relax" === r && (e.consume(), e.consumeSpaces(), r = e.fetch().text); "\\hline" === r || "\\hdashline" === r;)e.consume(), t.push("\\hdashline" === r), e.consumeSpaces(), r = e.fetch().text; return t } const Ir = e => { if (!e.parser.settings.displayMode) throw new n("{" + e.envName + "} can be used only in display mode.") }; function Rr(e) { if (-1 === e.indexOf("ed")) return -1 === e.indexOf("*") } function Hr(e, t, r) { let { hskipBeforeAndAfter: o, addJot: s, cols: i, arraystretch: a, colSeparationType: l, autoTag: h, singleRow: c, emptySingleRow: m, maxNumCols: p, leqno: u } = t; if (e.gullet.beginGroup(), c || e.gullet.macros.set("\\cr", "\\\\\\relax"), !a) { const t = e.gullet.expandMacroAsText("\\arraystretch"); if (null == t) a = 1; else if (a = parseFloat(t), !a || a < 0) throw new n("Invalid \\arraystretch: " + t) } e.gullet.beginGroup(); let d = []; const g = [d], f = [], b = [], y = null != h ? [] : void 0; function x() { h && e.gullet.macros.set("\\@eqnsw", "1", !0) } function w() { y && (e.gullet.macros.get("\\df@tag") ? (y.push(e.subparse([new Nr("\\df@tag")])), e.gullet.macros.set("\\df@tag", void 0, !0)) : y.push(Boolean(h) && "1" === e.gullet.macros.get("\\@eqnsw"))) } for (x(), b.push(qr(e)); ;) { let t = e.parseExpression(!1, c ? "\\end" : "\\\\"); e.gullet.endGroup(), e.gullet.beginGroup(), t = { type: "ordgroup", mode: e.mode, body: t }, r && (t = { type: "styling", mode: e.mode, style: r, body: [t] }), d.push(t); const o = e.fetch().text; if ("&" === o) { if (p && d.length === p) { if (c || l) throw new n("Too many tab characters: &", e.nextToken); e.settings.reportNonstrict("textEnv", "Too few columns specified in the {array} column argument.") } e.consume() } else { if ("\\end" === o) { w(), 1 === d.length && "styling" === t.type && 0 === t.body[0].body.length && (g.length > 1 || !m) && g.pop(), b.length < g.length + 1 && b.push([]); break } if ("\\\\" !== o) throw new n("Expected & or \\\\ or \\cr or \\end", e.nextToken); { let t; e.consume(), " " !== e.gullet.future().text && (t = e.parseSizeGroup(!0)), f.push(t ? t.value : null), w(), b.push(qr(e)), d = [], g.push(d), x() } } } return e.gullet.endGroup(), e.gullet.endGroup(), { type: "array", mode: e.mode, addJot: s, arraystretch: a, body: g, cols: i, rowGaps: f, hskipBeforeAndAfter: o, hLinesBeforeRow: b, colSeparationType: l, tags: y, leqno: u } } function Or(e) { return "d" === e.slice(0, 1) ? "display" : "text" } const Er = function (e, t) { let r, o; const s = e.body.length, i = e.hLinesBeforeRow; let a = 0, h = new Array(s); const c = [], m = Math.max(t.fontMetrics().arrayRuleWidth, t.minRuleThickness), p = 1 / t.fontMetrics().ptPerEm; let u = 5 * p; if (e.colSeparationType && "small" === e.colSeparationType) { u = t.havingStyle(w.SCRIPT).sizeMultiplier / t.sizeMultiplier * .2778 } const d = "CD" === e.colSeparationType ? P({ number: 3, unit: "ex" }, t) : 12 * p, g = 3 * p, f = e.arraystretch * d, b = .7 * f, y = .3 * f; let x = 0; function v(e) { for (let t = 0; t < e.length; ++t)t > 0 && (x += .25), c.push({ pos: x, isDashed: e[t] }) } for (v(i[0]), r = 0; r < e.body.length; ++r) { const n = e.body[r]; let s = b, l = y; a < n.length && (a = n.length); const c = new Array(n.length); for (o = 0; o < n.length; ++o) { const e = ht(n[o], t); l < e.depth && (l = e.depth), s < e.height && (s = e.height), c[o] = e } const m = e.rowGaps[r]; let p = 0; m && (p = P(m, t), p > 0 && (p += y, l < p && (l = p), p = 0)), e.addJot && (l += g), c.height = s, c.depth = l, x += s, c.pos = x, x += l + p, h[r] = c, v(i[r + 1]) } const k = x / 2 + t.fontMetrics().axisHeight, S = e.cols || [], M = []; let z, A; const T = []; if (e.tags && e.tags.some((e => e))) for (r = 0; r < s; ++r) { const n = h[r], o = n.pos - k, s = e.tags[r]; let i; i = !0 === s ? Ve.makeSpan(["eqn-num"], [], t) : !1 === s ? Ve.makeSpan([], [], t) : Ve.makeSpan([], nt(s, t, !0), t), i.depth = n.depth, i.height = n.height, T.push({ type: "elem", elem: i, shift: o }) } for (o = 0, A = 0; o < a || A < S.length; ++o, ++A) { let i, c = S[A] || {}, p = !0; for (; "separator" === c.type;) { if (p || (z = Ve.makeSpan(["arraycolsep"], []), z.style.width = F(t.fontMetrics().doubleRuleSep), M.push(z)), "|" !== c.separator && ":" !== c.separator) throw new n("Invalid separator type: " + c.separator); { const e = "|" === c.separator ? "solid" : "dashed", r = Ve.makeSpan(["vertical-separator"], [], t); r.style.height = F(x), r.style.borderRightWidth = F(m), r.style.borderRightStyle = e, r.style.margin = "0 " + F(-m / 2); const n = x - k; n && (r.style.verticalAlign = F(-n)), M.push(r) } A++, c = S[A] || {}, p = !1 } if (o >= a) continue; (o > 0 || e.hskipBeforeAndAfter) && (i = l.deflt(c.pregap, u), 0 !== i && (z = Ve.makeSpan(["arraycolsep"], []), z.style.width = F(i), M.push(z))); let d = []; for (r = 0; r < s; ++r) { const e = h[r], t = e[o]; if (!t) continue; const n = e.pos - k; t.depth = e.depth, t.height = e.height, d.push({ type: "elem", elem: t, shift: n }) } d = Ve.makeVList({ positionType: "individualShift", children: d }, t), d = Ve.makeSpan(["col-align-" + (c.align || "c")], [d]), M.push(d), (o < a - 1 || e.hskipBeforeAndAfter) && (i = l.deflt(c.postgap, u), 0 !== i && (z = Ve.makeSpan(["arraycolsep"], []), z.style.width = F(i), M.push(z))) } if (h = Ve.makeSpan(["mtable"], M), c.length > 0) { const e = Ve.makeLineSpan("hline", t, m), r = Ve.makeLineSpan("hdashline", t, m), n = [{ type: "elem", elem: h, shift: 0 }]; for (; c.length > 0;) { const t = c.pop(), o = t.pos - k; t.isDashed ? n.push({ type: "elem", elem: r, shift: o }) : n.push({ type: "elem", elem: e, shift: o }) } h = Ve.makeVList({ positionType: "individualShift", children: n }, t) } if (0 === T.length) return Ve.makeSpan(["mord"], [h], t); { let e = Ve.makeVList({ positionType: "individualShift", children: T }, t); return e = Ve.makeSpan(["tag"], [e], t), Ve.makeFragment([h, e]) } }, Lr = { c: "center ", l: "left ", r: "right " }, Dr = function (e, t) { const r = [], n = new gt.MathNode("mtd", [], ["mtr-glue"]), o = new gt.MathNode("mtd", [], ["mml-eqn-num"]); for (let s = 0; s < e.body.length; s++) { const i = e.body[s], a = []; for (let e = 0; e < i.length; e++)a.push(new gt.MathNode("mtd", [vt(i[e], t)])); e.tags && e.tags[s] && (a.unshift(n), a.push(n), e.leqno ? a.unshift(o) : a.push(o)), r.push(new gt.MathNode("mtr", a)) } let s = new gt.MathNode("mtable", r); const i = .5 === e.arraystretch ? .1 : .16 + e.arraystretch - 1 + (e.addJot ? .09 : 0); s.setAttribute("rowspacing", F(i)); let a = "", l = ""; if (e.cols && e.cols.length > 0) { const t = e.cols; let r = "", n = !1, o = 0, i = t.length; "separator" === t[0].type && (a += "top ", o = 1), "separator" === t[t.length - 1].type && (a += "bottom ", i -= 1); for (let e = o; e < i; e++)"align" === t[e].type ? (l += Lr[t[e].align], n && (r += "none "), n = !0) : "separator" === t[e].type && n && (r += "|" === t[e].separator ? "solid " : "dashed ", n = !1); s.setAttribute("columnalign", l.trim()), /[sd]/.test(r) && s.setAttribute("columnlines", r.trim()) } if ("align" === e.colSeparationType) { const t = e.cols || []; let r = ""; for (let e = 1; e < t.length; e++)r += e % 2 ? "0em " : "1em "; s.setAttribute("columnspacing", r.trim()) } else "alignat" === e.colSeparationType || "gather" === e.colSeparationType ? s.setAttribute("columnspacing", "0em") : "small" === e.colSeparationType ? s.setAttribute("columnspacing", "0.2778em") : "CD" === e.colSeparationType ? s.setAttribute("columnspacing", "0.5em") : s.setAttribute("columnspacing", "1em"); let h = ""; const c = e.hLinesBeforeRow; a += c[0].length > 0 ? "left " : "", a += c[c.length - 1].length > 0 ? "right " : ""; for (let e = 1; e < c.length - 1; e++)h += 0 === c[e].length ? "none " : c[e][0] ? "dashed " : "solid "; return /[sd]/.test(h) && s.setAttribute("rowlines", h.trim()), "" !== a && (s = new gt.MathNode("menclose", [s]), s.setAttribute("notation", a.trim())), e.arraystretch && e.arraystretch < 1 && (s = new gt.MathNode("mstyle", [s]), s.setAttribute("scriptlevel", "1")), s }, Vr = function (e, t) { -1 === e.envName.indexOf("ed") && Ir(e); const r = [], o = e.envName.indexOf("at") > -1 ? "alignat" : "align", s = "split" === e.envName, i = Hr(e.parser, { cols: r, addJot: !0, autoTag: s ? void 0 : Rr(e.envName), emptySingleRow: !0, colSeparationType: o, maxNumCols: s ? 2 : void 0, leqno: e.parser.settings.leqno }, "display"); let a, l = 0; const h = { type: "ordgroup", mode: e.mode, body: [] }; if (t[0] && "ordgroup" === t[0].type) { let e = ""; for (let r = 0; r < t[0].body.length; r++) { e += qt(t[0].body[r], "textord").text } a = Number(e), l = 2 * a } const c = !l; i.body.forEach((function (e) { for (let t = 1; t < e.length; t += 2) { const r = qt(e[t], "styling"); qt(r.body[0], "ordgroup").body.unshift(h) } if (c) l < e.length && (l = e.length); else { const t = e.length / 2; if (a < t) throw new n("Too many math in a row: expected " + a + ", but got " + t, e[0]) } })); for (let e = 0; e < l; ++e) { let t = "r", n = 0; e % 2 == 1 ? t = "l" : e > 0 && c && (n = 1), r[e] = { type: "align", align: t, pregap: n, postgap: 0 } } return i.colSeparationType = c ? "align" : "alignat", i }; Ar({ type: "array", names: ["array", "darray"], props: { numArgs: 1 }, handler(e, t) { const r = (Rt(t[0]) ? [t[0]] : qt(t[0], "ordgroup").body).map((function (e) { const t = It(e).text; if (-1 !== "lcr".indexOf(t)) return { type: "align", align: t }; if ("|" === t) return { type: "separator", separator: "|" }; if (":" === t) return { type: "separator", separator: ":" }; throw new n("Unknown column alignment: " + t, e) })), o = { cols: r, hskipBeforeAndAfter: !0, maxNumCols: r.length }; return Hr(e.parser, o, Or(e.envName)) }, htmlBuilder: Er, mathmlBuilder: Dr }), Ar({ type: "array", names: ["matrix", "pmatrix", "bmatrix", "Bmatrix", "vmatrix", "Vmatrix", "matrix*", "pmatrix*", "bmatrix*", "Bmatrix*", "vmatrix*", "Vmatrix*"], props: { numArgs: 0 }, handler(e) { const t = { matrix: null, pmatrix: ["(", ")"], bmatrix: ["[", "]"], Bmatrix: ["\\{", "\\}"], vmatrix: ["|", "|"], Vmatrix: ["\\Vert", "\\Vert"] }[e.envName.replace("*", "")]; let r = "c"; const o = { hskipBeforeAndAfter: !1, cols: [{ type: "align", align: r }] }; if ("*" === e.envName.charAt(e.envName.length - 1)) { const t = e.parser; if (t.consumeSpaces(), "[" === t.fetch().text) { if (t.consume(), t.consumeSpaces(), r = t.fetch().text, -1 === "lcr".indexOf(r)) throw new n("Expected l or c or r", t.nextToken); t.consume(), t.consumeSpaces(), t.expect("]"), t.consume(), o.cols = [{ type: "align", align: r }] } } const s = Hr(e.parser, o, Or(e.envName)), i = Math.max(0, ...s.body.map((e => e.length))); return s.cols = new Array(i).fill({ type: "align", align: r }), t ? { type: "leftright", mode: e.mode, body: [s], left: t[0], right: t[1], rightColor: void 0 } : s }, htmlBuilder: Er, mathmlBuilder: Dr }), Ar({ type: "array", names: ["smallmatrix"], props: { numArgs: 0 }, handler(e) { const t = Hr(e.parser, { arraystretch: .5 }, "script"); return t.colSeparationType = "small", t }, htmlBuilder: Er, mathmlBuilder: Dr }), Ar({ type: "array", names: ["subarray"], props: { numArgs: 1 }, handler(e, t) { const r = (Rt(t[0]) ? [t[0]] : qt(t[0], "ordgroup").body).map((function (e) { const t = It(e).text; if (-1 !== "lc".indexOf(t)) return { type: "align", align: t }; throw new n("Unknown column alignment: " + t, e) })); if (r.length > 1) throw new n("{subarray} can contain only one column"); let o = { cols: r, hskipBeforeAndAfter: !1, arraystretch: .5 }; if (o = Hr(e.parser, o, "script"), o.body.length > 0 && o.body[0].length > 1) throw new n("{subarray} can contain only one column"); return o }, htmlBuilder: Er, mathmlBuilder: Dr }), Ar({ type: "array", names: ["cases", "dcases", "rcases", "drcases"], props: { numArgs: 0 }, handler(e) { const t = Hr(e.parser, { arraystretch: 1.2, cols: [{ type: "align", align: "l", pregap: 0, postgap: 1 }, { type: "align", align: "l", pregap: 0, postgap: 0 }] }, Or(e.envName)); return { type: "leftright", mode: e.mode, body: [t], left: e.envName.indexOf("r") > -1 ? "." : "\\{", right: e.envName.indexOf("r") > -1 ? "\\}" : ".", rightColor: void 0 } }, htmlBuilder: Er, mathmlBuilder: Dr }), Ar({ type: "array", names: ["align", "align*", "aligned", "split"], props: { numArgs: 0 }, handler: Vr, htmlBuilder: Er, mathmlBuilder: Dr }), Ar({ type: "array", names: ["gathered", "gather", "gather*"], props: { numArgs: 0 }, handler(e) { l.contains(["gather", "gather*"], e.envName) && Ir(e); const t = { cols: [{ type: "align", align: "c" }], addJot: !0, colSeparationType: "gather", autoTag: Rr(e.envName), emptySingleRow: !0, leqno: e.parser.settings.leqno }; return Hr(e.parser, t, "display") }, htmlBuilder: Er, mathmlBuilder: Dr }), Ar({ type: "array", names: ["alignat", "alignat*", "alignedat"], props: { numArgs: 1 }, handler: Vr, htmlBuilder: Er, mathmlBuilder: Dr }), Ar({ type: "array", names: ["equation", "equation*"], props: { numArgs: 0 }, handler(e) { Ir(e); const t = { autoTag: Rr(e.envName), emptySingleRow: !0, singleRow: !0, maxNumCols: 1, leqno: e.parser.settings.leqno }; return Hr(e.parser, t, "display") }, htmlBuilder: Er, mathmlBuilder: Dr }), Ar({ type: "array", names: ["CD"], props: { numArgs: 0 }, handler(e) { return Ir(e), function (e) { const t = []; for (e.gullet.beginGroup(), e.gullet.macros.set("\\cr", "\\\\\\relax"), e.gullet.beginGroup(); ;) { t.push(e.parseExpression(!1, "\\\\")), e.gullet.endGroup(), e.gullet.beginGroup(); const r = e.fetch().text; if ("&" !== r && "\\\\" !== r) { if ("\\end" === r) { 0 === t[t.length - 1].length && t.pop(); break } throw new n("Expected \\\\ or \\cr or \\end", e.nextToken) } e.consume() } let r = []; const o = [r]; for (let a = 0; a < t.length; a++) { const l = t[a]; let h = { type: "styling", body: [], mode: "math", style: "display" }; for (let t = 0; t < l.length; t++)if (Ut(l[t])) { r.push(h), t += 1; const o = It(l[t]).text, a = new Array(2); if (a[0] = { type: "ordgroup", mode: "math", body: [] }, a[1] = { type: "ordgroup", mode: "math", body: [] }, "=|.".indexOf(o) > -1); else { if (!("<>AV".indexOf(o) > -1)) throw new n('Expected one of "<>AV=|." after @', l[t]); for (let e = 0; e < 2; e++) { let r = !0; for (let h = t + 1; h < l.length; h++) { if (i = o, ("mathord" === (s = l[h]).type || "atom" === s.type) && s.text === i) { r = !1, t = h; break } if (Ut(l[h])) throw new n("Missing a " + o + " character to complete a CD arrow.", l[h]); a[e].body.push(l[h]) } if (r) throw new n("Missing a " + o + " character to complete a CD arrow.", l[t]) } } const c = { type: "styling", body: [Yt(o, a, e)], mode: "math", style: "display" }; r.push(c), h = { type: "styling", body: [], mode: "math", style: "display" } } else h.body.push(l[t]); a % 2 == 0 ? r.push(h) : r.shift(), r = [], o.push(r) } var s, i; return e.gullet.endGroup(), e.gullet.endGroup(), { type: "array", mode: "math", body: o, arraystretch: 1, addJot: !0, rowGaps: [null], cols: new Array(o[0].length).fill({ type: "align", align: "c", pregap: .25, postgap: .25 }), colSeparationType: "CD", hLinesBeforeRow: new Array(o.length + 1).fill([]) } }(e.parser) }, htmlBuilder: Er, mathmlBuilder: Dr }), Br("\\nonumber", "\\gdef\\@eqnsw{0}"), Br("\\notag", "\\nonumber"), je({ type: "text", names: ["\\hline", "\\hdashline"], props: { numArgs: 0, allowedInText: !0, allowedInMath: !0 }, handler(e, t) { throw new n(e.funcName + " valid only within array environment") } }); var Pr = zr; je({ type: "environment", names: ["\\begin", "\\end"], props: { numArgs: 1, argTypes: ["text"] }, handler(e, t) { let { parser: r, funcName: o } = e; const s = t[0]; if ("ordgroup" !== s.type) throw new n("Invalid environment name", s); let i = ""; for (let e = 0; e < s.body.length; ++e)i += qt(s.body[e], "textord").text; if ("\\begin" === o) { if (!Pr.hasOwnProperty(i)) throw new n("No such environment: " + i, s); const e = Pr[i], { args: t, optArgs: o } = r.parseArguments("\\begin{" + i + "}", e), a = { mode: r.mode, envName: i, parser: r }, l = e.handler(a, t, o); r.expect("\\end", !1); const h = r.nextToken, c = qt(r.parseFunction(), "environment"); if (c.name !== i) throw new n("Mismatch: \\begin{" + i + "} matched by \\end{" + c.name + "}", h); return l } return { type: "environment", mode: r.mode, name: i, nameGroup: s } } }); const Fr = (e, t) => { const r = e.font, n = t.withFont(r); return ht(e.body, n) }, Gr = (e, t) => { const r = e.font, n = t.withFont(r); return vt(e.body, n) }, Ur = { "\\Bbb": "\\mathbb", "\\bold": "\\mathbf", "\\frak": "\\mathfrak", "\\bm": "\\boldsymbol" }; je({ type: "font", names: ["\\mathrm", "\\mathit", "\\mathbf", "\\mathnormal", "\\mathbb", "\\mathcal", "\\mathfrak", "\\mathscr", "\\mathsf", "\\mathtt", "\\Bbb", "\\bold", "\\frak"], props: { numArgs: 1, allowedInArgument: !0 }, handler: (e, t) => { let { parser: r, funcName: n } = e; const o = Ze(t[0]); let s = n; return s in Ur && (s = Ur[s]), { type: "font", mode: r.mode, font: s.slice(1), body: o } }, htmlBuilder: Fr, mathmlBuilder: Gr }), je({ type: "mclass", names: ["\\boldsymbol", "\\bm"], props: { numArgs: 1 }, handler: (e, t) => { let { parser: r } = e; const n = t[0], o = l.isCharacterBox(n); return { type: "mclass", mode: r.mode, mclass: Ft(n), body: [{ type: "font", mode: r.mode, font: "boldsymbol", body: n }], isCharacterBox: o } } }), je({ type: "font", names: ["\\rm", "\\sf", "\\tt", "\\bf", "\\it", "\\cal"], props: { numArgs: 0, allowedInText: !0 }, handler: (e, t) => { let { parser: r, funcName: n, breakOnTokenText: o } = e; const { mode: s } = r, i = r.parseExpression(!0, o); return { type: "font", mode: s, font: "math" + n.slice(1), body: { type: "ordgroup", mode: r.mode, body: i } } }, htmlBuilder: Fr, mathmlBuilder: Gr }); const Yr = (e, t) => { let r = t; return "display" === e ? r = r.id >= w.SCRIPT.id ? r.text() : w.DISPLAY : "text" === e && r.size === w.DISPLAY.size ? r = w.TEXT : "script" === e ? r = w.SCRIPT : "scriptscript" === e && (r = w.SCRIPTSCRIPT), r }, Xr = (e, t) => { const r = Yr(e.size, t.style), n = r.fracNum(), o = r.fracDen(); let s; s = t.havingStyle(n); const i = ht(e.numer, s, t); if (e.continued) { const e = 8.5 / t.fontMetrics().ptPerEm, r = 3.5 / t.fontMetrics().ptPerEm; i.height = i.height < e ? e : i.height, i.depth = i.depth < r ? r : i.depth } s = t.havingStyle(o); const a = ht(e.denom, s, t); let l, h, c, m, p, u, d, g, f, b; if (e.hasBarLine ? (e.barSize ? (h = P(e.barSize, t), l = Ve.makeLineSpan("frac-line", t, h)) : l = Ve.makeLineSpan("frac-line", t), h = l.height, c = l.height) : (l = null, h = 0, c = t.fontMetrics().defaultRuleThickness), r.size === w.DISPLAY.size || "display" === e.size ? (m = t.fontMetrics().num1, p = h > 0 ? 3 * c : 7 * c, u = t.fontMetrics().denom1) : (h > 0 ? (m = t.fontMetrics().num2, p = c) : (m = t.fontMetrics().num3, p = 3 * c), u = t.fontMetrics().denom2), l) { const e = t.fontMetrics().axisHeight; m - i.depth - (e + .5 * h) < p && (m += p - (m - i.depth - (e + .5 * h))), e - .5 * h - (a.height - u) < p && (u += p - (e - .5 * h - (a.height - u))); const r = -(e - .5 * h); d = Ve.makeVList({ positionType: "individualShift", children: [{ type: "elem", elem: a, shift: u }, { type: "elem", elem: l, shift: r }, { type: "elem", elem: i, shift: -m }] }, t) } else { const e = m - i.depth - (a.height - u); e < p && (m += .5 * (p - e), u += .5 * (p - e)), d = Ve.makeVList({ positionType: "individualShift", children: [{ type: "elem", elem: a, shift: u }, { type: "elem", elem: i, shift: -m }] }, t) } return s = t.havingStyle(r), d.height *= s.sizeMultiplier / t.sizeMultiplier, d.depth *= s.sizeMultiplier / t.sizeMultiplier, g = r.size === w.DISPLAY.size ? t.fontMetrics().delim1 : r.size === w.SCRIPTSCRIPT.size ? t.havingStyle(w.SCRIPT).fontMetrics().delim2 : t.fontMetrics().delim2, f = null == e.leftDelim ? lt(t, ["mopen"]) : yr.customSizedDelim(e.leftDelim, g, !0, t.havingStyle(r), e.mode, ["mopen"]), b = e.continued ? Ve.makeSpan([]) : null == e.rightDelim ? lt(t, ["mclose"]) : yr.customSizedDelim(e.rightDelim, g, !0, t.havingStyle(r), e.mode, ["mclose"]), Ve.makeSpan(["mord"].concat(s.sizingClasses(t)), [f, Ve.makeSpan(["mfrac"], [d]), b], t) }, Wr = (e, t) => { let r = new gt.MathNode("mfrac", [vt(e.numer, t), vt(e.denom, t)]); if (e.hasBarLine) { if (e.barSize) { const n = P(e.barSize, t); r.setAttribute("linethickness", F(n)) } } else r.setAttribute("linethickness", "0px"); const n = Yr(e.size, t.style); if (n.size !== t.style.size) { r = new gt.MathNode("mstyle", [r]); const e = n.size === w.DISPLAY.size ? "true" : "false"; r.setAttribute("displaystyle", e), r.setAttribute("scriptlevel", "0") } if (null != e.leftDelim || null != e.rightDelim) { const t = []; if (null != e.leftDelim) { const r = new gt.MathNode("mo", [new gt.TextNode(e.leftDelim.replace("\\", ""))]); r.setAttribute("fence", "true"), t.push(r) } if (t.push(r), null != e.rightDelim) { const r = new gt.MathNode("mo", [new gt.TextNode(e.rightDelim.replace("\\", ""))]); r.setAttribute("fence", "true"), t.push(r) } return bt(t) } return r }; je({ type: "genfrac", names: ["\\dfrac", "\\frac", "\\tfrac", "\\dbinom", "\\binom", "\\tbinom", "\\\\atopfrac", "\\\\bracefrac", "\\\\brackfrac"], props: { numArgs: 2, allowedInArgument: !0 }, handler: (e, t) => { let { parser: r, funcName: n } = e; const o = t[0], s = t[1]; let i, a = null, l = null, h = "auto"; switch (n) { case "\\dfrac": case "\\frac": case "\\tfrac": i = !0; break; case "\\\\atopfrac": i = !1; break; case "\\dbinom": case "\\binom": case "\\tbinom": i = !1, a = "(", l = ")"; break; case "\\\\bracefrac": i = !1, a = "\\{", l = "\\}"; break; case "\\\\brackfrac": i = !1, a = "[", l = "]"; break; default: throw new Error("Unrecognized genfrac command") }switch (n) { case "\\dfrac": case "\\dbinom": h = "display"; break; case "\\tfrac": case "\\tbinom": h = "text" }return { type: "genfrac", mode: r.mode, continued: !1, numer: o, denom: s, hasBarLine: i, leftDelim: a, rightDelim: l, size: h, barSize: null } }, htmlBuilder: Xr, mathmlBuilder: Wr }), je({ type: "genfrac", names: ["\\cfrac"], props: { numArgs: 2 }, handler: (e, t) => { let { parser: r, funcName: n } = e; const o = t[0], s = t[1]; return { type: "genfrac", mode: r.mode, continued: !0, numer: o, denom: s, hasBarLine: !0, leftDelim: null, rightDelim: null, size: "display", barSize: null } } }), je({ type: "infix", names: ["\\over", "\\choose", "\\atop", "\\brace", "\\brack"], props: { numArgs: 0, infix: !0 }, handler(e) { let t, { parser: r, funcName: n, token: o } = e; switch (n) { case "\\over": t = "\\frac"; break; case "\\choose": t = "\\binom"; break; case "\\atop": t = "\\\\atopfrac"; break; case "\\brace": t = "\\\\bracefrac"; break; case "\\brack": t = "\\\\brackfrac"; break; default: throw new Error("Unrecognized infix genfrac command") }return { type: "infix", mode: r.mode, replaceWith: t, token: o } } }); const _r = ["display", "text", "script", "scriptscript"], jr = function (e) { let t = null; return e.length > 0 && (t = e, t = "." === t ? null : t), t }; je({ type: "genfrac", names: ["\\genfrac"], props: { numArgs: 6, allowedInArgument: !0, argTypes: ["math", "math", "size", "text", "math", "math"] }, handler(e, t) { let { parser: r } = e; const n = t[4], o = t[5], s = Ze(t[0]), i = "atom" === s.type && "open" === s.family ? jr(s.text) : null, a = Ze(t[1]), l = "atom" === a.type && "close" === a.family ? jr(a.text) : null, h = qt(t[2], "size"); let c, m = null; h.isBlank ? c = !0 : (m = h.value, c = m.number > 0); let p = "auto", u = t[3]; if ("ordgroup" === u.type) { if (u.body.length > 0) { const e = qt(u.body[0], "textord"); p = _r[Number(e.text)] } } else u = qt(u, "textord"), p = _r[Number(u.text)]; return { type: "genfrac", mode: r.mode, numer: n, denom: o, continued: !1, hasBarLine: c, barSize: m, leftDelim: i, rightDelim: l, size: p } }, htmlBuilder: Xr, mathmlBuilder: Wr }), je({ type: "infix", names: ["\\above"], props: { numArgs: 1, argTypes: ["size"], infix: !0 }, handler(e, t) { let { parser: r, funcName: n, token: o } = e; return { type: "infix", mode: r.mode, replaceWith: "\\\\abovefrac", size: qt(t[0], "size").value, token: o } } }), je({ type: "genfrac", names: ["\\\\abovefrac"], props: { numArgs: 3, argTypes: ["math", "size", "math"] }, handler: (e, t) => { let { parser: r, funcName: n } = e; const o = t[0], s = function (e) { if (!e) throw new Error("Expected non-null, but got " + String(e)); return e }(qt(t[1], "infix").size), i = t[2], a = s.number > 0; return { type: "genfrac", mode: r.mode, numer: o, denom: i, continued: !1, hasBarLine: a, barSize: s, leftDelim: null, rightDelim: null, size: "auto" } }, htmlBuilder: Xr, mathmlBuilder: Wr }); const $r = (e, t) => { const r = t.style; let n, o; "supsub" === e.type ? (n = e.sup ? ht(e.sup, t.havingStyle(r.sup()), t) : ht(e.sub, t.havingStyle(r.sub()), t), o = qt(e.base, "horizBrace")) : o = qt(e, "horizBrace"); const s = ht(o.base, t.havingBaseStyle(w.DISPLAY)), i = Nt(o, t); let a; if (o.isOver ? (a = Ve.makeVList({ positionType: "firstBaseline", children: [{ type: "elem", elem: s }, { type: "kern", size: .1 }, { type: "elem", elem: i }] }, t), a.children[0].children[0].children[1].classes.push("svg-align")) : (a = Ve.makeVList({ positionType: "bottom", positionData: s.depth + .1 + i.height, children: [{ type: "elem", elem: i }, { type: "kern", size: .1 }, { type: "elem", elem: s }] }, t), a.children[0].children[0].children[0].classes.push("svg-align")), n) { const e = Ve.makeSpan(["mord", o.isOver ? "mover" : "munder"], [a], t); a = o.isOver ? Ve.makeVList({ positionType: "firstBaseline", children: [{ type: "elem", elem: e }, { type: "kern", size: .2 }, { type: "elem", elem: n }] }, t) : Ve.makeVList({ positionType: "bottom", positionData: e.depth + .2 + n.height + n.depth, children: [{ type: "elem", elem: n }, { type: "kern", size: .2 }, { type: "elem", elem: e }] }, t) } return Ve.makeSpan(["mord", o.isOver ? "mover" : "munder"], [a], t) }; je({ type: "horizBrace", names: ["\\overbrace", "\\underbrace"], props: { numArgs: 1 }, handler(e, t) { let { parser: r, funcName: n } = e; return { type: "horizBrace", mode: r.mode, label: n, isOver: /^\\over/.test(n), base: t[0] } }, htmlBuilder: $r, mathmlBuilder: (e, t) => { const r = Ct(e.label); return new gt.MathNode(e.isOver ? "mover" : "munder", [vt(e.base, t), r]) } }), je({ type: "href", names: ["\\href"], props: { numArgs: 2, argTypes: ["url", "original"], allowedInText: !0 }, handler: (e, t) => { let { parser: r } = e; const n = t[1], o = qt(t[0], "url").url; return r.settings.isTrusted({ command: "\\href", url: o }) ? { type: "href", mode: r.mode, href: o, body: Ke(n) } : r.formatUnsupportedCmd("\\href") }, htmlBuilder: (e, t) => { const r = nt(e.body, t, !1); return Ve.makeAnchor(e.href, [], r, t) }, mathmlBuilder: (e, t) => { let r = wt(e.body, t); return r instanceof ut || (r = new ut("mrow", [r])), r.setAttribute("href", e.href), r } }), je({ type: "href", names: ["\\url"], props: { numArgs: 1, argTypes: ["url"], allowedInText: !0 }, handler: (e, t) => { let { parser: r } = e; const n = qt(t[0], "url").url; if (!r.settings.isTrusted({ command: "\\url", url: n })) return r.formatUnsupportedCmd("\\url"); const o = []; for (let e = 0; e < n.length; e++) { let t = n[e]; "~" === t && (t = "\\textasciitilde"), o.push({ type: "textord", mode: "text", text: t }) } const s = { type: "text", mode: r.mode, font: "\\texttt", body: o }; return { type: "href", mode: r.mode, href: n, body: Ke(s) } } }), je({ type: "hbox", names: ["\\hbox"], props: { numArgs: 1, argTypes: ["text"], allowedInText: !0, primitive: !0 }, handler(e, t) { let { parser: r } = e; return { type: "hbox", mode: r.mode, body: Ke(t[0]) } }, htmlBuilder(e, t) { const r = nt(e.body, t, !1); return Ve.makeFragment(r) }, mathmlBuilder(e, t) { return new gt.MathNode("mrow", xt(e.body, t)) } }), je({ type: "html", names: ["\\htmlClass", "\\htmlId", "\\htmlStyle", "\\htmlData"], props: { numArgs: 2, argTypes: ["raw", "original"], allowedInText: !0 }, handler: (e, t) => { let { parser: r, funcName: o, token: s } = e; const i = qt(t[0], "raw").string, a = t[1]; let l; r.settings.strict && r.settings.reportNonstrict("htmlExtension", "HTML extension is disabled on strict mode"); const h = {}; switch (o) { case "\\htmlClass": h.class = i, l = { command: "\\htmlClass", class: i }; break; case "\\htmlId": h.id = i, l = { command: "\\htmlId", id: i }; break; case "\\htmlStyle": h.style = i, l = { command: "\\htmlStyle", style: i }; break; case "\\htmlData": { const e = i.split(","); for (let t = 0; t < e.length; t++) { const r = e[t].split("="); if (2 !== r.length) throw new n("Error parsing key-value for \\htmlData"); h["data-" + r[0].trim()] = r[1].trim() } l = { command: "\\htmlData", attributes: h }; break } default: throw new Error("Unrecognized html command") }return r.settings.isTrusted(l) ? { type: "html", mode: r.mode, attributes: h, body: Ke(a) } : r.formatUnsupportedCmd(o) }, htmlBuilder: (e, t) => { const r = nt(e.body, t, !1), n = ["enclosing"]; e.attributes.class && n.push(...e.attributes.class.trim().split(/\s+/)); const o = Ve.makeSpan(n, r, t); for (const t in e.attributes) "class" !== t && e.attributes.hasOwnProperty(t) && o.setAttribute(t, e.attributes[t]); return o }, mathmlBuilder: (e, t) => wt(e.body, t) }), je({ type: "htmlmathml", names: ["\\html@mathml"], props: { numArgs: 2, allowedInText: !0 }, handler: (e, t) => { let { parser: r } = e; return { type: "htmlmathml", mode: r.mode, html: Ke(t[0]), mathml: Ke(t[1]) } }, htmlBuilder: (e, t) => { const r = nt(e.html, t, !1); return Ve.makeFragment(r) }, mathmlBuilder: (e, t) => wt(e.mathml, t) }); const Zr = function (e) { if (/^[-+]? *(\d+(\.\d*)?|\.\d+)$/.test(e)) return { number: +e, unit: "bp" }; { const t = /([-+]?) *(\d+(?:\.\d*)?|\.\d+) *([a-z]{2})/.exec(e); if (!t) throw new n("Invalid size: '" + e + "' in \\includegraphics"); const r = { number: +(t[1] + t[2]), unit: t[3] }; if (!V(r)) throw new n("Invalid unit: '" + r.unit + "' in \\includegraphics."); return r } }; je({ type: "includegraphics", names: ["\\includegraphics"], props: { numArgs: 1, numOptionalArgs: 1, argTypes: ["raw", "url"], allowedInText: !1 }, handler: (e, t, r) => { let { parser: o } = e, s = { number: 0, unit: "em" }, i = { number: .9, unit: "em" }, a = { number: 0, unit: "em" }, l = ""; if (r[0]) { const e = qt(r[0], "raw").string.split(","); for (let t = 0; t < e.length; t++) { const r = e[t].split("="); if (2 === r.length) { const e = r[1].trim(); switch (r[0].trim()) { case "alt": l = e; break; case "width": s = Zr(e); break; case "height": i = Zr(e); break; case "totalheight": a = Zr(e); break; default: throw new n("Invalid key: '" + r[0] + "' in \\includegraphics.") } } } } const h = qt(t[0], "url").url; return "" === l && (l = h, l = l.replace(/^.*[\\/]/, ""), l = l.substring(0, l.lastIndexOf("."))), o.settings.isTrusted({ command: "\\includegraphics", url: h }) ? { type: "includegraphics", mode: o.mode, alt: l, width: s, height: i, totalheight: a, src: h } : o.formatUnsupportedCmd("\\includegraphics") }, htmlBuilder: (e, t) => { const r = P(e.height, t); let n = 0; e.totalheight.number > 0 && (n = P(e.totalheight, t) - r); let o = 0; e.width.number > 0 && (o = P(e.width, t)); const s = { height: F(r + n) }; o > 0 && (s.width = F(o)), n > 0 && (s.verticalAlign = F(-n)); const i = new j(e.src, e.alt, s); return i.height = r, i.depth = n, i }, mathmlBuilder: (e, t) => { const r = new gt.MathNode("mglyph", []); r.setAttribute("alt", e.alt); const n = P(e.height, t); let o = 0; if (e.totalheight.number > 0 && (o = P(e.totalheight, t) - n, r.setAttribute("valign", F(-o))), r.setAttribute("height", F(n + o)), e.width.number > 0) { const n = P(e.width, t); r.setAttribute("width", F(n)) } return r.setAttribute("src", e.src), r } }), je({ type: "kern", names: ["\\kern", "\\mkern", "\\hskip", "\\mskip"], props: { numArgs: 1, argTypes: ["size"], primitive: !0, allowedInText: !0 }, handler(e, t) { let { parser: r, funcName: n } = e; const o = qt(t[0], "size"); if (r.settings.strict) { const e = "m" === n[1], t = "mu" === o.value.unit; e ? (t || r.settings.reportNonstrict("mathVsTextUnits", "LaTeX's " + n + " supports only mu units, not " + o.value.unit + " units"), "math" !== r.mode && r.settings.reportNonstrict("mathVsTextUnits", "LaTeX's " + n + " works only in math mode")) : t && r.settings.reportNonstrict("mathVsTextUnits", "LaTeX's " + n + " doesn't support mu units") } return { type: "kern", mode: r.mode, dimension: o.value } }, htmlBuilder(e, t) { return Ve.makeGlue(e.dimension, t) }, mathmlBuilder(e, t) { const r = P(e.dimension, t); return new gt.SpaceNode(r) } }), je({ type: "lap", names: ["\\mathllap", "\\mathrlap", "\\mathclap"], props: { numArgs: 1, allowedInText: !0 }, handler: (e, t) => { let { parser: r, funcName: n } = e; const o = t[0]; return { type: "lap", mode: r.mode, alignment: n.slice(5), body: o } }, htmlBuilder: (e, t) => { let r; "clap" === e.alignment ? (r = Ve.makeSpan([], [ht(e.body, t)]), r = Ve.makeSpan(["inner"], [r], t)) : r = Ve.makeSpan(["inner"], [ht(e.body, t)]); const n = Ve.makeSpan(["fix"], []); let o = Ve.makeSpan([e.alignment], [r, n], t); const s = Ve.makeSpan(["strut"]); return s.style.height = F(o.height + o.depth), o.depth && (s.style.verticalAlign = F(-o.depth)), o.children.unshift(s), o = Ve.makeSpan(["thinbox"], [o], t), Ve.makeSpan(["mord", "vbox"], [o], t) }, mathmlBuilder: (e, t) => { const r = new gt.MathNode("mpadded", [vt(e.body, t)]); if ("rlap" !== e.alignment) { const t = "llap" === e.alignment ? "-1" : "-0.5"; r.setAttribute("lspace", t + "width") } return r.setAttribute("width", "0px"), r } }), je({ type: "styling", names: ["\\(", "$"], props: { numArgs: 0, allowedInText: !0, allowedInMath: !1 }, handler(e, t) { let { funcName: r, parser: n } = e; const o = n.mode; n.switchMode("math"); const s = "\\(" === r ? "\\)" : "$", i = n.parseExpression(!1, s); return n.expect(s), n.switchMode(o), { type: "styling", mode: n.mode, style: "text", body: i } } }), je({ type: "text", names: ["\\)", "\\]"], props: { numArgs: 0, allowedInText: !0, allowedInMath: !1 }, handler(e, t) { throw new n("Mismatched " + e.funcName) } }); const Kr = (e, t) => { switch (t.style.size) { case w.DISPLAY.size: return e.display; case w.TEXT.size: return e.text; case w.SCRIPT.size: return e.script; case w.SCRIPTSCRIPT.size: return e.scriptscript; default: return e.text } }; je({ type: "mathchoice", names: ["\\mathchoice"], props: { numArgs: 4, primitive: !0 }, handler: (e, t) => { let { parser: r } = e; return { type: "mathchoice", mode: r.mode, display: Ke(t[0]), text: Ke(t[1]), script: Ke(t[2]), scriptscript: Ke(t[3]) } }, htmlBuilder: (e, t) => { const r = Kr(e, t), n = nt(r, t, !1); return Ve.makeFragment(n) }, mathmlBuilder: (e, t) => { const r = Kr(e, t); return wt(r, t) } }); const Jr = (e, t, r, n, o, s, i) => { e = Ve.makeSpan([], [e]); const a = r && l.isCharacterBox(r); let h, c, m; if (t) { const e = ht(t, n.havingStyle(o.sup()), n); c = { elem: e, kern: Math.max(n.fontMetrics().bigOpSpacing1, n.fontMetrics().bigOpSpacing3 - e.depth) } } if (r) { const e = ht(r, n.havingStyle(o.sub()), n); h = { elem: e, kern: Math.max(n.fontMetrics().bigOpSpacing2, n.fontMetrics().bigOpSpacing4 - e.height) } } if (c && h) { const t = n.fontMetrics().bigOpSpacing5 + h.elem.height + h.elem.depth + h.kern + e.depth + i; m = Ve.makeVList({ positionType: "bottom", positionData: t, children: [{ type: "kern", size: n.fontMetrics().bigOpSpacing5 }, { type: "elem", elem: h.elem, marginLeft: F(-s) }, { type: "kern", size: h.kern }, { type: "elem", elem: e }, { type: "kern", size: c.kern }, { type: "elem", elem: c.elem, marginLeft: F(s) }, { type: "kern", size: n.fontMetrics().bigOpSpacing5 }] }, n) } else if (h) { const t = e.height - i; m = Ve.makeVList({ positionType: "top", positionData: t, children: [{ type: "kern", size: n.fontMetrics().bigOpSpacing5 }, { type: "elem", elem: h.elem, marginLeft: F(-s) }, { type: "kern", size: h.kern }, { type: "elem", elem: e }] }, n) } else { if (!c) return e; { const t = e.depth + i; m = Ve.makeVList({ positionType: "bottom", positionData: t, children: [{ type: "elem", elem: e }, { type: "kern", size: c.kern }, { type: "elem", elem: c.elem, marginLeft: F(s) }, { type: "kern", size: n.fontMetrics().bigOpSpacing5 }] }, n) } } const p = [m]; if (h && 0 !== s && !a) { const e = Ve.makeSpan(["mspace"], [], n); e.style.marginRight = F(s), p.unshift(e) } return Ve.makeSpan(["mop", "op-limits"], p, n) }, Qr = ["\\smallint"], en = (e, t) => { let r, n, o, s = !1; "supsub" === e.type ? (r = e.sup, n = e.sub, o = qt(e.base, "op"), s = !0) : o = qt(e, "op"); const i = t.style; let a, h = !1; if (i.size === w.DISPLAY.size && o.symbol && !l.contains(Qr, o.name) && (h = !0), o.symbol) { const e = h ? "Size2-Regular" : "Size1-Regular"; let r = ""; if ("\\oiint" !== o.name && "\\oiiint" !== o.name || (r = o.name.slice(1), o.name = "oiint" === r ? "\\iint" : "\\iiint"), a = Ve.makeSymbol(o.name, e, "math", t, ["mop", "op-symbol", h ? "large-op" : "small-op"]), r.length > 0) { const e = a.italic, n = Ve.staticSvg(r + "Size" + (h ? "2" : "1"), t); a = Ve.makeVList({ positionType: "individualShift", children: [{ type: "elem", elem: a, shift: 0 }, { type: "elem", elem: n, shift: h ? .08 : 0 }] }, t), o.name = "\\" + r, a.classes.unshift("mop"), a.italic = e } } else if (o.body) { const e = nt(o.body, t, !0); 1 === e.length && e[0] instanceof Z ? (a = e[0], a.classes[0] = "mop") : a = Ve.makeSpan(["mop"], e, t) } else { const e = []; for (let r = 1; r < o.name.length; r++)e.push(Ve.mathsym(o.name[r], o.mode, t)); a = Ve.makeSpan(["mop"], e, t) } let c = 0, m = 0; return (a instanceof Z || "\\oiint" === o.name || "\\oiiint" === o.name) && !o.suppressBaseShift && (c = (a.height - a.depth) / 2 - t.fontMetrics().axisHeight, m = a.italic), s ? Jr(a, r, n, t, i, m, c) : (c && (a.style.position = "relative", a.style.top = F(c)), a) }, tn = (e, t) => { let r; if (e.symbol) r = new ut("mo", [ft(e.name, e.mode)]), l.contains(Qr, e.name) && r.setAttribute("largeop", "false"); else if (e.body) r = new ut("mo", xt(e.body, t)); else { r = new ut("mi", [new dt(e.name.slice(1))]); const t = new ut("mo", [ft("\u2061", "text")]); r = e.parentIsSupSub ? new ut("mrow", [r, t]) : pt([r, t]) } return r }, rn = { "\u220f": "\\prod", "\u2210": "\\coprod", "\u2211": "\\sum", "\u22c0": "\\bigwedge", "\u22c1": "\\bigvee", "\u22c2": "\\bigcap", "\u22c3": "\\bigcup", "\u2a00": "\\bigodot", "\u2a01": "\\bigoplus", "\u2a02": "\\bigotimes", "\u2a04": "\\biguplus", "\u2a06": "\\bigsqcup" }; je({ type: "op", names: ["\\coprod", "\\bigvee", "\\bigwedge", "\\biguplus", "\\bigcap", "\\bigcup", "\\intop", "\\prod", "\\sum", "\\bigotimes", "\\bigoplus", "\\bigodot", "\\bigsqcup", "\\smallint", "\u220f", "\u2210", "\u2211", "\u22c0", "\u22c1", "\u22c2", "\u22c3", "\u2a00", "\u2a01", "\u2a02", "\u2a04", "\u2a06"], props: { numArgs: 0 }, handler: (e, t) => { let { parser: r, funcName: n } = e, o = n; return 1 === o.length && (o = rn[o]), { type: "op", mode: r.mode, limits: !0, parentIsSupSub: !1, symbol: !0, name: o } }, htmlBuilder: en, mathmlBuilder: tn }), je({ type: "op", names: ["\\mathop"], props: { numArgs: 1, primitive: !0 }, handler: (e, t) => { let { parser: r } = e; const n = t[0]; return { type: "op", mode: r.mode, limits: !1, parentIsSupSub: !1, symbol: !1, body: Ke(n) } }, htmlBuilder: en, mathmlBuilder: tn }); const nn = { "\u222b": "\\int", "\u222c": "\\iint", "\u222d": "\\iiint", "\u222e": "\\oint", "\u222f": "\\oiint", "\u2230": "\\oiiint" }; je({ type: "op", names: ["\\arcsin", "\\arccos", "\\arctan", "\\arctg", "\\arcctg", "\\arg", "\\ch", "\\cos", "\\cosec", "\\cosh", "\\cot", "\\cotg", "\\coth", "\\csc", "\\ctg", "\\cth", "\\deg", "\\dim", "\\exp", "\\hom", "\\ker", "\\lg", "\\ln", "\\log", "\\sec", "\\sin", "\\sinh", "\\sh", "\\tan", "\\tanh", "\\tg", "\\th"], props: { numArgs: 0 }, handler(e) { let { parser: t, funcName: r } = e; return { type: "op", mode: t.mode, limits: !1, parentIsSupSub: !1, symbol: !1, name: r } }, htmlBuilder: en, mathmlBuilder: tn }), je({ type: "op", names: ["\\det", "\\gcd", "\\inf", "\\lim", "\\max", "\\min", "\\Pr", "\\sup"], props: { numArgs: 0 }, handler(e) { let { parser: t, funcName: r } = e; return { type: "op", mode: t.mode, limits: !0, parentIsSupSub: !1, symbol: !1, name: r } }, htmlBuilder: en, mathmlBuilder: tn }), je({ type: "op", names: ["\\int", "\\iint", "\\iiint", "\\oint", "\\oiint", "\\oiiint", "\u222b", "\u222c", "\u222d", "\u222e", "\u222f", "\u2230"], props: { numArgs: 0 }, handler(e) { let { parser: t, funcName: r } = e, n = r; return 1 === n.length && (n = nn[n]), { type: "op", mode: t.mode, limits: !1, parentIsSupSub: !1, symbol: !0, name: n } }, htmlBuilder: en, mathmlBuilder: tn }); const on = (e, t) => { let r, n, o, s, i = !1; if ("supsub" === e.type ? (r = e.sup, n = e.sub, o = qt(e.base, "operatorname"), i = !0) : o = qt(e, "operatorname"), o.body.length > 0) { const e = o.body.map((e => { const t = e.text; return "string" == typeof t ? { type: "textord", mode: e.mode, text: t } : e })), r = nt(e, t.withFont("mathrm"), !0); for (let e = 0; e < r.length; e++) { const t = r[e]; t instanceof Z && (t.text = t.text.replace(/\u2212/, "-").replace(/\u2217/, "*")) } s = Ve.makeSpan(["mop"], r, t) } else s = Ve.makeSpan(["mop"], [], t); return i ? Jr(s, r, n, t, t.style, 0, 0) : s }; function sn(e, t, r) { const n = nt(e, t, !1), o = t.sizeMultiplier / r.sizeMultiplier; for (let e = 0; e < n.length; e++) { const s = n[e].classes.indexOf("sizing"); s < 0 ? Array.prototype.push.apply(n[e].classes, t.sizingClasses(r)) : n[e].classes[s + 1] === "reset-size" + t.size && (n[e].classes[s + 1] = "reset-size" + r.size), n[e].height *= o, n[e].depth *= o } return Ve.makeFragment(n) } je({ type: "operatorname", names: ["\\operatorname@", "\\operatornamewithlimits"], props: { numArgs: 1 }, handler: (e, t) => { let { parser: r, funcName: n } = e; const o = t[0]; return { type: "operatorname", mode: r.mode, body: Ke(o), alwaysHandleSupSub: "\\operatornamewithlimits" === n, limits: !1, parentIsSupSub: !1 } }, htmlBuilder: on, mathmlBuilder: (e, t) => { let r = xt(e.body, t.withFont("mathrm")), n = !0; for (let e = 0; e < r.length; e++) { const t = r[e]; if (t instanceof gt.SpaceNode); else if (t instanceof gt.MathNode) switch (t.type) { case "mi": case "mn": case "ms": case "mspace": case "mtext": break; case "mo": { const e = t.children[0]; 1 === t.children.length && e instanceof gt.TextNode ? e.text = e.text.replace(/\u2212/, "-").replace(/\u2217/, "*") : n = !1; break } default: n = !1 } else n = !1 } if (n) { const e = r.map((e => e.toText())).join(""); r = [new gt.TextNode(e)] } const o = new gt.MathNode("mi", r); o.setAttribute("mathvariant", "normal"); const s = new gt.MathNode("mo", [ft("\u2061", "text")]); return e.parentIsSupSub ? new gt.MathNode("mrow", [o, s]) : gt.newDocumentFragment([o, s]) } }), Br("\\operatorname", "\\@ifstar\\operatornamewithlimits\\operatorname@"), $e({ type: "ordgroup", htmlBuilder(e, t) { return e.semisimple ? Ve.makeFragment(nt(e.body, t, !1)) : Ve.makeSpan(["mord"], nt(e.body, t, !0), t) }, mathmlBuilder(e, t) { return wt(e.body, t, !0) } }), je({ type: "overline", names: ["\\overline"], props: { numArgs: 1 }, handler(e, t) { let { parser: r } = e; const n = t[0]; return { type: "overline", mode: r.mode, body: n } }, htmlBuilder(e, t) { const r = ht(e.body, t.havingCrampedStyle()), n = Ve.makeLineSpan("overline-line", t), o = t.fontMetrics().defaultRuleThickness, s = Ve.makeVList({ positionType: "firstBaseline", children: [{ type: "elem", elem: r }, { type: "kern", size: 3 * o }, { type: "elem", elem: n }, { type: "kern", size: o }] }, t); return Ve.makeSpan(["mord", "overline"], [s], t) }, mathmlBuilder(e, t) { const r = new gt.MathNode("mo", [new gt.TextNode("\u203e")]); r.setAttribute("stretchy", "true"); const n = new gt.MathNode("mover", [vt(e.body, t), r]); return n.setAttribute("accent", "true"), n } }), je({ type: "phantom", names: ["\\phantom"], props: { numArgs: 1, allowedInText: !0 }, handler: (e, t) => { let { parser: r } = e; const n = t[0]; return { type: "phantom", mode: r.mode, body: Ke(n) } }, htmlBuilder: (e, t) => { const r = nt(e.body, t.withPhantom(), !1); return Ve.makeFragment(r) }, mathmlBuilder: (e, t) => { const r = xt(e.body, t); return new gt.MathNode("mphantom", r) } }), je({ type: "hphantom", names: ["\\hphantom"], props: { numArgs: 1, allowedInText: !0 }, handler: (e, t) => { let { parser: r } = e; const n = t[0]; return { type: "hphantom", mode: r.mode, body: n } }, htmlBuilder: (e, t) => { let r = Ve.makeSpan([], [ht(e.body, t.withPhantom())]); if (r.height = 0, r.depth = 0, r.children) for (let e = 0; e < r.children.length; e++)r.children[e].height = 0, r.children[e].depth = 0; return r = Ve.makeVList({ positionType: "firstBaseline", children: [{ type: "elem", elem: r }] }, t), Ve.makeSpan(["mord"], [r], t) }, mathmlBuilder: (e, t) => { const r = xt(Ke(e.body), t), n = new gt.MathNode("mphantom", r), o = new gt.MathNode("mpadded", [n]); return o.setAttribute("height", "0px"), o.setAttribute("depth", "0px"), o } }), je({ type: "vphantom", names: ["\\vphantom"], props: { numArgs: 1, allowedInText: !0 }, handler: (e, t) => { let { parser: r } = e; const n = t[0]; return { type: "vphantom", mode: r.mode, body: n } }, htmlBuilder: (e, t) => { const r = Ve.makeSpan(["inner"], [ht(e.body, t.withPhantom())]), n = Ve.makeSpan(["fix"], []); return Ve.makeSpan(["mord", "rlap"], [r, n], t) }, mathmlBuilder: (e, t) => { const r = xt(Ke(e.body), t), n = new gt.MathNode("mphantom", r), o = new gt.MathNode("mpadded", [n]); return o.setAttribute("width", "0px"), o } }), je({ type: "raisebox", names: ["\\raisebox"], props: { numArgs: 2, argTypes: ["size", "hbox"], allowedInText: !0 }, handler(e, t) { let { parser: r } = e; const n = qt(t[0], "size").value, o = t[1]; return { type: "raisebox", mode: r.mode, dy: n, body: o } }, htmlBuilder(e, t) { const r = ht(e.body, t), n = P(e.dy, t); return Ve.makeVList({ positionType: "shift", positionData: -n, children: [{ type: "elem", elem: r }] }, t) }, mathmlBuilder(e, t) { const r = new gt.MathNode("mpadded", [vt(e.body, t)]), n = e.dy.number + e.dy.unit; return r.setAttribute("voffset", n), r } }), je({ type: "internal", names: ["\\relax"], props: { numArgs: 0, allowedInText: !0 }, handler(e) { let { parser: t } = e; return { type: "internal", mode: t.mode } } }), je({ type: "rule", names: ["\\rule"], props: { numArgs: 2, numOptionalArgs: 1, argTypes: ["size", "size", "size"] }, handler(e, t, r) { let { parser: n } = e; const o = r[0], s = qt(t[0], "size"), i = qt(t[1], "size"); return { type: "rule", mode: n.mode, shift: o && qt(o, "size").value, width: s.value, height: i.value } }, htmlBuilder(e, t) { const r = Ve.makeSpan(["mord", "rule"], [], t), n = P(e.width, t), o = P(e.height, t), s = e.shift ? P(e.shift, t) : 0; return r.style.borderRightWidth = F(n), r.style.borderTopWidth = F(o), r.style.bottom = F(s), r.width = n, r.height = o + s, r.depth = -s, r.maxFontSize = 1.125 * o * t.sizeMultiplier, r }, mathmlBuilder(e, t) { const r = P(e.width, t), n = P(e.height, t), o = e.shift ? P(e.shift, t) : 0, s = t.color && t.getColor() || "black", i = new gt.MathNode("mspace"); i.setAttribute("mathbackground", s), i.setAttribute("width", F(r)), i.setAttribute("height", F(n)); const a = new gt.MathNode("mpadded", [i]); return o >= 0 ? a.setAttribute("height", F(o)) : (a.setAttribute("height", F(o)), a.setAttribute("depth", F(-o))), a.setAttribute("voffset", F(o)), a } }); const an = ["\\tiny", "\\sixptsize", "\\scriptsize", "\\footnotesize", "\\small", "\\normalsize", "\\large", "\\Large", "\\LARGE", "\\huge", "\\Huge"]; je({ type: "sizing", names: an, props: { numArgs: 0, allowedInText: !0 }, handler: (e, t) => { let { breakOnTokenText: r, funcName: n, parser: o } = e; const s = o.parseExpression(!1, r); return { type: "sizing", mode: o.mode, size: an.indexOf(n) + 1, body: s } }, htmlBuilder: (e, t) => { const r = t.havingSize(e.size); return sn(e.body, r, t) }, mathmlBuilder: (e, t) => { const r = t.havingSize(e.size), n = xt(e.body, r), o = new gt.MathNode("mstyle", n); return o.setAttribute("mathsize", F(r.sizeMultiplier)), o } }), je({ type: "smash", names: ["\\smash"], props: { numArgs: 1, numOptionalArgs: 1, allowedInText: !0 }, handler: (e, t, r) => { let { parser: n } = e, o = !1, s = !1; const i = r[0] && qt(r[0], "ordgroup"); if (i) { let e = ""; for (let t = 0; t < i.body.length; ++t) { if (e = i.body[t].text, "t" === e) o = !0; else { if ("b" !== e) { o = !1, s = !1; break } s = !0 } } } else o = !0, s = !0; const a = t[0]; return { type: "smash", mode: n.mode, body: a, smashHeight: o, smashDepth: s } }, htmlBuilder: (e, t) => { const r = Ve.makeSpan([], [ht(e.body, t)]); if (!e.smashHeight && !e.smashDepth) return r; if (e.smashHeight && (r.height = 0, r.children)) for (let e = 0; e < r.children.length; e++)r.children[e].height = 0; if (e.smashDepth && (r.depth = 0, r.children)) for (let e = 0; e < r.children.length; e++)r.children[e].depth = 0; const n = Ve.makeVList({ positionType: "firstBaseline", children: [{ type: "elem", elem: r }] }, t); return Ve.makeSpan(["mord"], [n], t) }, mathmlBuilder: (e, t) => { const r = new gt.MathNode("mpadded", [vt(e.body, t)]); return e.smashHeight && r.setAttribute("height", "0px"), e.smashDepth && r.setAttribute("depth", "0px"), r } }), je({ type: "sqrt", names: ["\\sqrt"], props: { numArgs: 1, numOptionalArgs: 1 }, handler(e, t, r) { let { parser: n } = e; const o = r[0], s = t[0]; return { type: "sqrt", mode: n.mode, body: s, index: o } }, htmlBuilder(e, t) { let r = ht(e.body, t.havingCrampedStyle()); 0 === r.height && (r.height = t.fontMetrics().xHeight), r = Ve.wrapFragment(r, t); const n = t.fontMetrics().defaultRuleThickness; let o = n; t.style.id < w.TEXT.id && (o = t.fontMetrics().xHeight); let s = n + o / 4; const i = r.height + r.depth + s + n, { span: a, ruleWidth: l, advanceWidth: h } = yr.sqrtImage(i, t), c = a.height - l; c > r.height + r.depth + s && (s = (s + c - r.height - r.depth) / 2); const m = a.height - r.height - s - l; r.style.paddingLeft = F(h); const p = Ve.makeVList({ positionType: "firstBaseline", children: [{ type: "elem", elem: r, wrapperClasses: ["svg-align"] }, { type: "kern", size: -(r.height + m) }, { type: "elem", elem: a }, { type: "kern", size: l }] }, t); if (e.index) { const r = t.havingStyle(w.SCRIPTSCRIPT), n = ht(e.index, r, t), o = .6 * (p.height - p.depth), s = Ve.makeVList({ positionType: "shift", positionData: -o, children: [{ type: "elem", elem: n }] }, t), i = Ve.makeSpan(["root"], [s]); return Ve.makeSpan(["mord", "sqrt"], [i, p], t) } return Ve.makeSpan(["mord", "sqrt"], [p], t) }, mathmlBuilder(e, t) { const { body: r, index: n } = e; return n ? new gt.MathNode("mroot", [vt(r, t), vt(n, t)]) : new gt.MathNode("msqrt", [vt(r, t)]) } }); const ln = { display: w.DISPLAY, text: w.TEXT, script: w.SCRIPT, scriptscript: w.SCRIPTSCRIPT }; je({ type: "styling", names: ["\\displaystyle", "\\textstyle", "\\scriptstyle", "\\scriptscriptstyle"], props: { numArgs: 0, allowedInText: !0, primitive: !0 }, handler(e, t) { let { breakOnTokenText: r, funcName: n, parser: o } = e; const s = o.parseExpression(!0, r), i = n.slice(1, n.length - 5); return { type: "styling", mode: o.mode, style: i, body: s } }, htmlBuilder(e, t) { const r = ln[e.style], n = t.havingStyle(r).withFont(""); return sn(e.body, n, t) }, mathmlBuilder(e, t) { const r = ln[e.style], n = t.havingStyle(r), o = xt(e.body, n), s = new gt.MathNode("mstyle", o), i = { display: ["0", "true"], text: ["0", "false"], script: ["1", "false"], scriptscript: ["2", "false"] }[e.style]; return s.setAttribute("scriptlevel", i[0]), s.setAttribute("displaystyle", i[1]), s } }); $e({ type: "supsub", htmlBuilder(e, t) { const r = function (e, t) { const r = e.base; if (r) return "op" === r.type ? r.limits && (t.style.size === w.DISPLAY.size || r.alwaysHandleSupSub) ? en : null : "operatorname" === r.type ? r.alwaysHandleSupSub && (t.style.size === w.DISPLAY.size || r.limits) ? on : null : "accent" === r.type ? l.isCharacterBox(r.base) ? Ht : null : "horizBrace" === r.type && !e.sub === r.isOver ? $r : null; return null }(e, t); if (r) return r(e, t); const { base: n, sup: o, sub: s } = e, i = ht(n, t); let a, h; const c = t.fontMetrics(); let m = 0, p = 0; const u = n && l.isCharacterBox(n); if (o) { const e = t.havingStyle(t.style.sup()); a = ht(o, e, t), u || (m = i.height - e.fontMetrics().supDrop * e.sizeMultiplier / t.sizeMultiplier) } if (s) { const e = t.havingStyle(t.style.sub()); h = ht(s, e, t), u || (p = i.depth + e.fontMetrics().subDrop * e.sizeMultiplier / t.sizeMultiplier) } let d; d = t.style === w.DISPLAY ? c.sup1 : t.style.cramped ? c.sup3 : c.sup2; const g = t.sizeMultiplier, f = F(.5 / c.ptPerEm / g); let b, y = null; if (h) { const t = e.base && "op" === e.base.type && e.base.name && ("\\oiint" === e.base.name || "\\oiiint" === e.base.name); (i instanceof Z || t) && (y = F(-i.italic)) } if (a && h) { m = Math.max(m, d, a.depth + .25 * c.xHeight), p = Math.max(p, c.sub2); const e = 4 * c.defaultRuleThickness; if (m - a.depth - (h.height - p) < e) { p = e - (m - a.depth) + h.height; const t = .8 * c.xHeight - (m - a.depth); t > 0 && (m += t, p -= t) } const r = [{ type: "elem", elem: h, shift: p, marginRight: f, marginLeft: y }, { type: "elem", elem: a, shift: -m, marginRight: f }]; b = Ve.makeVList({ positionType: "individualShift", children: r }, t) } else if (h) { p = Math.max(p, c.sub1, h.height - .8 * c.xHeight); const e = [{ type: "elem", elem: h, marginLeft: y, marginRight: f }]; b = Ve.makeVList({ positionType: "shift", positionData: p, children: e }, t) } else { if (!a) throw new Error("supsub must have either sup or sub."); m = Math.max(m, d, a.depth + .25 * c.xHeight), b = Ve.makeVList({ positionType: "shift", positionData: -m, children: [{ type: "elem", elem: a, marginRight: f }] }, t) } const x = at(i, "right") || "mord"; return Ve.makeSpan([x], [i, Ve.makeSpan(["msupsub"], [b])], t) }, mathmlBuilder(e, t) { let r, n, o = !1; e.base && "horizBrace" === e.base.type && (n = !!e.sup, n === e.base.isOver && (o = !0, r = e.base.isOver)), !e.base || "op" !== e.base.type && "operatorname" !== e.base.type || (e.base.parentIsSupSub = !0); const s = [vt(e.base, t)]; let i; if (e.sub && s.push(vt(e.sub, t)), e.sup && s.push(vt(e.sup, t)), o) i = r ? "mover" : "munder"; else if (e.sub) if (e.sup) { const r = e.base; i = r && "op" === r.type && r.limits && t.style === w.DISPLAY || r && "operatorname" === r.type && r.alwaysHandleSupSub && (t.style === w.DISPLAY || r.limits) ? "munderover" : "msubsup" } else { const r = e.base; i = r && "op" === r.type && r.limits && (t.style === w.DISPLAY || r.alwaysHandleSupSub) || r && "operatorname" === r.type && r.alwaysHandleSupSub && (r.limits || t.style === w.DISPLAY) ? "munder" : "msub" } else { const r = e.base; i = r && "op" === r.type && r.limits && (t.style === w.DISPLAY || r.alwaysHandleSupSub) || r && "operatorname" === r.type && r.alwaysHandleSupSub && (r.limits || t.style === w.DISPLAY) ? "mover" : "msup" } return new gt.MathNode(i, s) } }), $e({ type: "atom", htmlBuilder(e, t) { return Ve.mathsym(e.text, e.mode, t, ["m" + e.family]) }, mathmlBuilder(e, t) { const r = new gt.MathNode("mo", [ft(e.text, e.mode)]); if ("bin" === e.family) { const n = yt(e, t); "bold-italic" === n && r.setAttribute("mathvariant", n) } else "punct" === e.family ? r.setAttribute("separator", "true") : "open" !== e.family && "close" !== e.family || r.setAttribute("stretchy", "false"); return r } }); const hn = { mi: "italic", mn: "normal", mtext: "normal" }; $e({ type: "mathord", htmlBuilder(e, t) { return Ve.makeOrd(e, t, "mathord") }, mathmlBuilder(e, t) { const r = new gt.MathNode("mi", [ft(e.text, e.mode, t)]), n = yt(e, t) || "italic"; return n !== hn[r.type] && r.setAttribute("mathvariant", n), r } }), $e({ type: "textord", htmlBuilder(e, t) { return Ve.makeOrd(e, t, "textord") }, mathmlBuilder(e, t) { const r = ft(e.text, e.mode, t), n = yt(e, t) || "normal"; let o; return o = "text" === e.mode ? new gt.MathNode("mtext", [r]) : /[0-9]/.test(e.text) ? new gt.MathNode("mn", [r]) : "\\prime" === e.text ? new gt.MathNode("mo", [r]) : new gt.MathNode("mi", [r]), n !== hn[o.type] && o.setAttribute("mathvariant", n), o } }); const cn = { "\\nobreak": "nobreak", "\\allowbreak": "allowbreak" }, mn = { " ": {}, "\\ ": {}, "~": { className: "nobreak" }, "\\space": {}, "\\nobreakspace": { className: "nobreak" } }; $e({ type: "spacing", htmlBuilder(e, t) { if (mn.hasOwnProperty(e.text)) { const r = mn[e.text].className || ""; if ("text" === e.mode) { const n = Ve.makeOrd(e, t, "textord"); return n.classes.push(r), n } return Ve.makeSpan(["mspace", r], [Ve.mathsym(e.text, e.mode, t)], t) } if (cn.hasOwnProperty(e.text)) return Ve.makeSpan(["mspace", cn[e.text]], [], t); throw new n('Unknown type of space "' + e.text + '"') }, mathmlBuilder(e, t) { let r; if (!mn.hasOwnProperty(e.text)) { if (cn.hasOwnProperty(e.text)) return new gt.MathNode("mspace"); throw new n('Unknown type of space "' + e.text + '"') } return r = new gt.MathNode("mtext", [new gt.TextNode("\xa0")]), r } }); const pn = () => { const e = new gt.MathNode("mtd", []); return e.setAttribute("width", "50%"), e }; $e({ type: "tag", mathmlBuilder(e, t) { const r = new gt.MathNode("mtable", [new gt.MathNode("mtr", [pn(), new gt.MathNode("mtd", [wt(e.body, t)]), pn(), new gt.MathNode("mtd", [wt(e.tag, t)])])]); return r.setAttribute("width", "100%"), r } }); const un = { "\\text": void 0, "\\textrm": "textrm", "\\textsf": "textsf", "\\texttt": "texttt", "\\textnormal": "textrm" }, dn = { "\\textbf": "textbf", "\\textmd": "textmd" }, gn = { "\\textit": "textit", "\\textup": "textup" }, fn = (e, t) => { const r = e.font; return r ? un[r] ? t.withTextFontFamily(un[r]) : dn[r] ? t.withTextFontWeight(dn[r]) : "\\emph" === r ? "textit" === t.fontShape ? t.withTextFontShape("textup") : t.withTextFontShape("textit") : t.withTextFontShape(gn[r]) : t }; je({ type: "text", names: ["\\text", "\\textrm", "\\textsf", "\\texttt", "\\textnormal", "\\textbf", "\\textmd", "\\textit", "\\textup", "\\emph"], props: { numArgs: 1, argTypes: ["text"], allowedInArgument: !0, allowedInText: !0 }, handler(e, t) { let { parser: r, funcName: n } = e; const o = t[0]; return { type: "text", mode: r.mode, body: Ke(o), font: n } }, htmlBuilder(e, t) { const r = fn(e, t), n = nt(e.body, r, !0); return Ve.makeSpan(["mord", "text"], n, r) }, mathmlBuilder(e, t) { const r = fn(e, t); return wt(e.body, r) } }), je({ type: "underline", names: ["\\underline"], props: { numArgs: 1, allowedInText: !0 }, handler(e, t) { let { parser: r } = e; return { type: "underline", mode: r.mode, body: t[0] } }, htmlBuilder(e, t) { const r = ht(e.body, t), n = Ve.makeLineSpan("underline-line", t), o = t.fontMetrics().defaultRuleThickness, s = Ve.makeVList({ positionType: "top", positionData: r.height, children: [{ type: "kern", size: o }, { type: "elem", elem: n }, { type: "kern", size: 3 * o }, { type: "elem", elem: r }] }, t); return Ve.makeSpan(["mord", "underline"], [s], t) }, mathmlBuilder(e, t) { const r = new gt.MathNode("mo", [new gt.TextNode("\u203e")]); r.setAttribute("stretchy", "true"); const n = new gt.MathNode("munder", [vt(e.body, t), r]); return n.setAttribute("accentunder", "true"), n } }), je({ type: "vcenter", names: ["\\vcenter"], props: { numArgs: 1, argTypes: ["original"], allowedInText: !1 }, handler(e, t) { let { parser: r } = e; return { type: "vcenter", mode: r.mode, body: t[0] } }, htmlBuilder(e, t) { const r = ht(e.body, t), n = t.fontMetrics().axisHeight, o = .5 * (r.height - n - (r.depth + n)); return Ve.makeVList({ positionType: "shift", positionData: o, children: [{ type: "elem", elem: r }] }, t) }, mathmlBuilder(e, t) { return new gt.MathNode("mpadded", [vt(e.body, t)], ["vcenter"]) } }), je({ type: "verb", names: ["\\verb"], props: { numArgs: 0, allowedInText: !0 }, handler(e, t, r) { throw new n("\\verb ended by end of line instead of matching delimiter") }, htmlBuilder(e, t) { const r = bn(e), n = [], o = t.havingStyle(t.style.text()); for (let t = 0; t < r.length; t++) { let s = r[t]; "~" === s && (s = "\\textasciitilde"), n.push(Ve.makeSymbol(s, "Typewriter-Regular", e.mode, o, ["mord", "texttt"])) } return Ve.makeSpan(["mord", "text"].concat(o.sizingClasses(t)), Ve.tryCombineChars(n), o) }, mathmlBuilder(e, t) { const r = new gt.TextNode(bn(e)), n = new gt.MathNode("mtext", [r]); return n.setAttribute("mathvariant", "monospace"), n } }); const bn = e => e.body.replace(/ /g, e.star ? "\u2423" : "\xa0"); var yn = Xe; const xn = "[ \r\n\t]", wn = "(\\\\[a-zA-Z@]+)" + xn + "*", vn = "[\u0300-\u036f]", kn = new RegExp(vn + "+$"), Sn = "(" + xn + "+)|\\\\(\n|[ \r\t]+\n?)[ \r\t]*|([!-\\[\\]-\u2027\u202a-\ud7ff\uf900-\uffff]" + vn + "*|[\ud800-\udbff][\udc00-\udfff]" + vn + "*|\\\\verb\\*([^]).*?\\4|\\\\verb([^*a-zA-Z]).*?\\5|" + wn + "|\\\\[^\ud800-\udfff])"; class Mn { constructor(e, t) { this.input = void 0, this.settings = void 0, this.tokenRegex = void 0, this.catcodes = void 0, this.input = e, this.settings = t, this.tokenRegex = new RegExp(Sn, "g"), this.catcodes = { "%": 14, "~": 13 } } setCatcode(e, t) { this.catcodes[e] = t } lex() { const e = this.input, t = this.tokenRegex.lastIndex; if (t === e.length) return new Nr("EOF", new Cr(this, t, t)); const r = this.tokenRegex.exec(e); if (null === r || r.index !== t) throw new n("Unexpected character: '" + e[t] + "'", new Nr(e[t], new Cr(this, t, t + 1))); const o = r[6] || r[3] || (r[2] ? "\\ " : " "); if (14 === this.catcodes[o]) { const t = e.indexOf("\n", this.tokenRegex.lastIndex); return -1 === t ? (this.tokenRegex.lastIndex = e.length, this.settings.reportNonstrict("commentAtEnd", "% comment has no terminating newline; LaTeX would fail because of commenting the end of math mode (e.g. $)")) : this.tokenRegex.lastIndex = t + 1, this.lex() } return new Nr(o, new Cr(this, t, this.tokenRegex.lastIndex)) } } class zn { constructor(e, t) { void 0 === e && (e = {}), void 0 === t && (t = {}), this.current = void 0, this.builtins = void 0, this.undefStack = void 0, this.current = t, this.builtins = e, this.undefStack = [] } beginGroup() { this.undefStack.push({}) } endGroup() { if (0 === this.undefStack.length) throw new n("Unbalanced namespace destruction: attempt to pop global namespace; please report this as a bug"); const e = this.undefStack.pop(); for (const t in e) e.hasOwnProperty(t) && (null == e[t] ? delete this.current[t] : this.current[t] = e[t]) } endGroups() { for (; this.undefStack.length > 0;)this.endGroup() } has(e) { return this.current.hasOwnProperty(e) || this.builtins.hasOwnProperty(e) } get(e) { return this.current.hasOwnProperty(e) ? this.current[e] : this.builtins[e] } set(e, t, r) { if (void 0 === r && (r = !1), r) { for (let t = 0; t < this.undefStack.length; t++)delete this.undefStack[t][e]; this.undefStack.length > 0 && (this.undefStack[this.undefStack.length - 1][e] = t) } else { const t = this.undefStack[this.undefStack.length - 1]; t && !t.hasOwnProperty(e) && (t[e] = this.current[e]) } null == t ? delete this.current[e] : this.current[e] = t } } var An = Tr; Br("\\noexpand", (function (e) { const t = e.popToken(); return e.isExpandable(t.text) && (t.noexpand = !0, t.treatAsRelax = !0), { tokens: [t], numArgs: 0 } })), Br("\\expandafter", (function (e) { const t = e.popToken(); return e.expandOnce(!0), { tokens: [t], numArgs: 0 } })), Br("\\@firstoftwo", (function (e) { return { tokens: e.consumeArgs(2)[0], numArgs: 0 } })), Br("\\@secondoftwo", (function (e) { return { tokens: e.consumeArgs(2)[1], numArgs: 0 } })), Br("\\@ifnextchar", (function (e) { const t = e.consumeArgs(3); e.consumeSpaces(); const r = e.future(); return 1 === t[0].length && t[0][0].text === r.text ? { tokens: t[1], numArgs: 0 } : { tokens: t[2], numArgs: 0 } })), Br("\\@ifstar", "\\@ifnextchar *{\\@firstoftwo{#1}}"), Br("\\TextOrMath", (function (e) { const t = e.consumeArgs(2); return "text" === e.mode ? { tokens: t[0], numArgs: 0 } : { tokens: t[1], numArgs: 0 } })); const Tn = { 0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, a: 10, A: 10, b: 11, B: 11, c: 12, C: 12, d: 13, D: 13, e: 14, E: 14, f: 15, F: 15 }; Br("\\char", (function (e) { let t, r = e.popToken(), o = ""; if ("'" === r.text) t = 8, r = e.popToken(); else if ('"' === r.text) t = 16, r = e.popToken(); else if ("`" === r.text) if (r = e.popToken(), "\\" === r.text[0]) o = r.text.charCodeAt(1); else { if ("EOF" === r.text) throw new n("\\char` missing argument"); o = r.text.charCodeAt(0) } else t = 10; if (t) { if (o = Tn[r.text], null == o || o >= t) throw new n("Invalid base-" + t + " digit " + r.text); let s; for (; null != (s = Tn[e.future().text]) && s < t;)o *= t, o += s, e.popToken() } return "\\@char{" + o + "}" })); const Bn = (e, t, r) => { let o = e.consumeArg().tokens; if (1 !== o.length) throw new n("\\newcommand's first argument must be a macro name"); const s = o[0].text, i = e.isDefined(s); if (i && !t) throw new n("\\newcommand{" + s + "} attempting to redefine " + s + "; use \\renewcommand"); if (!i && !r) throw new n("\\renewcommand{" + s + "} when command " + s + " does not yet exist; use \\newcommand"); let a = 0; if (o = e.consumeArg().tokens, 1 === o.length && "[" === o[0].text) { let t = "", r = e.expandNextToken(); for (; "]" !== r.text && "EOF" !== r.text;)t += r.text, r = e.expandNextToken(); if (!t.match(/^\s*[0-9]+\s*$/)) throw new n("Invalid number of arguments: " + t); a = parseInt(t), o = e.consumeArg().tokens } return e.macros.set(s, { tokens: o, numArgs: a }), "" }; Br("\\newcommand", (e => Bn(e, !1, !0))), Br("\\renewcommand", (e => Bn(e, !0, !1))), Br("\\providecommand", (e => Bn(e, !0, !0))), Br("\\message", (e => { const t = e.consumeArgs(1)[0]; return console.log(t.reverse().map((e => e.text)).join("")), "" })), Br("\\errmessage", (e => { const t = e.consumeArgs(1)[0]; return console.error(t.reverse().map((e => e.text)).join("")), "" })), Br("\\show", (e => { const t = e.popToken(), r = t.text; return console.log(t, e.macros.get(r), yn[r], oe.math[r], oe.text[r]), "" })), Br("\\bgroup", "{"), Br("\\egroup", "}"), Br("~", "\\nobreakspace"), Br("\\lq", "`"), Br("\\rq", "'"), Br("\\aa", "\\r a"), Br("\\AA", "\\r A"), Br("\\textcopyright", "\\html@mathml{\\textcircled{c}}{\\char`\xa9}"), Br("\\copyright", "\\TextOrMath{\\textcopyright}{\\text{\\textcopyright}}"), Br("\\textregistered", "\\html@mathml{\\textcircled{\\scriptsize R}}{\\char`\xae}"), Br("\u212c", "\\mathscr{B}"), Br("\u2130", "\\mathscr{E}"), Br("\u2131", "\\mathscr{F}"), Br("\u210b", "\\mathscr{H}"), Br("\u2110", "\\mathscr{I}"), Br("\u2112", "\\mathscr{L}"), Br("\u2133", "\\mathscr{M}"), Br("\u211b", "\\mathscr{R}"), Br("\u212d", "\\mathfrak{C}"), Br("\u210c", "\\mathfrak{H}"), Br("\u2128", "\\mathfrak{Z}"), Br("\\Bbbk", "\\Bbb{k}"), Br("\xb7", "\\cdotp"), Br("\\llap", "\\mathllap{\\textrm{#1}}"), Br("\\rlap", "\\mathrlap{\\textrm{#1}}"), Br("\\clap", "\\mathclap{\\textrm{#1}}"), Br("\\mathstrut", "\\vphantom{(}"), Br("\\underbar", "\\underline{\\text{#1}}"), Br("\\not", '\\html@mathml{\\mathrel{\\mathrlap\\@not}}{\\char"338}'), Br("\\neq", "\\html@mathml{\\mathrel{\\not=}}{\\mathrel{\\char`\u2260}}"), Br("\\ne", "\\neq"), Br("\u2260", "\\neq"), Br("\\notin", "\\html@mathml{\\mathrel{{\\in}\\mathllap{/\\mskip1mu}}}{\\mathrel{\\char`\u2209}}"), Br("\u2209", "\\notin"), Br("\u2258", "\\html@mathml{\\mathrel{=\\kern{-1em}\\raisebox{0.4em}{$\\scriptsize\\frown$}}}{\\mathrel{\\char`\u2258}}"), Br("\u2259", "\\html@mathml{\\stackrel{\\tiny\\wedge}{=}}{\\mathrel{\\char`\u2258}}"), Br("\u225a", "\\html@mathml{\\stackrel{\\tiny\\vee}{=}}{\\mathrel{\\char`\u225a}}"), Br("\u225b", "\\html@mathml{\\stackrel{\\scriptsize\\star}{=}}{\\mathrel{\\char`\u225b}}"), Br("\u225d", "\\html@mathml{\\stackrel{\\tiny\\mathrm{def}}{=}}{\\mathrel{\\char`\u225d}}"), Br("\u225e", "\\html@mathml{\\stackrel{\\tiny\\mathrm{m}}{=}}{\\mathrel{\\char`\u225e}}"), Br("\u225f", "\\html@mathml{\\stackrel{\\tiny?}{=}}{\\mathrel{\\char`\u225f}}"), Br("\u27c2", "\\perp"), Br("\u203c", "\\mathclose{!\\mkern-0.8mu!}"), Br("\u220c", "\\notni"), Br("\u231c", "\\ulcorner"), Br("\u231d", "\\urcorner"), Br("\u231e", "\\llcorner"), Br("\u231f", "\\lrcorner"), Br("\xa9", "\\copyright"), Br("\xae", "\\textregistered"), Br("\ufe0f", "\\textregistered"), Br("\\ulcorner", '\\html@mathml{\\@ulcorner}{\\mathop{\\char"231c}}'), Br("\\urcorner", '\\html@mathml{\\@urcorner}{\\mathop{\\char"231d}}'), Br("\\llcorner", '\\html@mathml{\\@llcorner}{\\mathop{\\char"231e}}'), Br("\\lrcorner", '\\html@mathml{\\@lrcorner}{\\mathop{\\char"231f}}'), Br("\\vdots", "\\mathord{\\varvdots\\rule{0pt}{15pt}}"), Br("\u22ee", "\\vdots"), Br("\\varGamma", "\\mathit{\\Gamma}"), Br("\\varDelta", "\\mathit{\\Delta}"), Br("\\varTheta", "\\mathit{\\Theta}"), Br("\\varLambda", "\\mathit{\\Lambda}"), Br("\\varXi", "\\mathit{\\Xi}"), Br("\\varPi", "\\mathit{\\Pi}"), Br("\\varSigma", "\\mathit{\\Sigma}"), Br("\\varUpsilon", "\\mathit{\\Upsilon}"), Br("\\varPhi", "\\mathit{\\Phi}"), Br("\\varPsi", "\\mathit{\\Psi}"), Br("\\varOmega", "\\mathit{\\Omega}"), Br("\\substack", "\\begin{subarray}{c}#1\\end{subarray}"), Br("\\colon", "\\nobreak\\mskip2mu\\mathpunct{}\\mathchoice{\\mkern-3mu}{\\mkern-3mu}{}{}{:}\\mskip6mu\\relax"), Br("\\boxed", "\\fbox{$\\displaystyle{#1}$}"), Br("\\iff", "\\DOTSB\\;\\Longleftrightarrow\\;"), Br("\\implies", "\\DOTSB\\;\\Longrightarrow\\;"), Br("\\impliedby", "\\DOTSB\\;\\Longleftarrow\\;"); const Cn = { ",": "\\dotsc", "\\not": "\\dotsb", "+": "\\dotsb", "=": "\\dotsb", "<": "\\dotsb", ">": "\\dotsb", "-": "\\dotsb", "*": "\\dotsb", ":": "\\dotsb", "\\DOTSB": "\\dotsb", "\\coprod": "\\dotsb", "\\bigvee": "\\dotsb", "\\bigwedge": "\\dotsb", "\\biguplus": "\\dotsb", "\\bigcap": "\\dotsb", "\\bigcup": "\\dotsb", "\\prod": "\\dotsb", "\\sum": "\\dotsb", "\\bigotimes": "\\dotsb", "\\bigoplus": "\\dotsb", "\\bigodot": "\\dotsb", "\\bigsqcup": "\\dotsb", "\\And": "\\dotsb", "\\longrightarrow": "\\dotsb", "\\Longrightarrow": "\\dotsb", "\\longleftarrow": "\\dotsb", "\\Longleftarrow": "\\dotsb", "\\longleftrightarrow": "\\dotsb", "\\Longleftrightarrow": "\\dotsb", "\\mapsto": "\\dotsb", "\\longmapsto": "\\dotsb", "\\hookrightarrow": "\\dotsb", "\\doteq": "\\dotsb", "\\mathbin": "\\dotsb", "\\mathrel": "\\dotsb", "\\relbar": "\\dotsb", "\\Relbar": "\\dotsb", "\\xrightarrow": "\\dotsb", "\\xleftarrow": "\\dotsb", "\\DOTSI": "\\dotsi", "\\int": "\\dotsi", "\\oint": "\\dotsi", "\\iint": "\\dotsi", "\\iiint": "\\dotsi", "\\iiiint": "\\dotsi", "\\idotsint": "\\dotsi", "\\DOTSX": "\\dotsx" }; Br("\\dots", (function (e) { let t = "\\dotso"; const r = e.expandAfterFuture().text; return r in Cn ? t = Cn[r] : ("\\not" === r.slice(0, 4) || r in oe.math && l.contains(["bin", "rel"], oe.math[r].group)) && (t = "\\dotsb"), t })); const Nn = { ")": !0, "]": !0, "\\rbrack": !0, "\\}": !0, "\\rbrace": !0, "\\rangle": !0, "\\rceil": !0, "\\rfloor": !0, "\\rgroup": !0, "\\rmoustache": !0, "\\right": !0, "\\bigr": !0, "\\biggr": !0, "\\Bigr": !0, "\\Biggr": !0, $: !0, ";": !0, ".": !0, ",": !0 }; Br("\\dotso", (function (e) { return e.future().text in Nn ? "\\ldots\\," : "\\ldots" })), Br("\\dotsc", (function (e) { const t = e.future().text; return t in Nn && "," !== t ? "\\ldots\\," : "\\ldots" })), Br("\\cdots", (function (e) { return e.future().text in Nn ? "\\@cdots\\," : "\\@cdots" })), Br("\\dotsb", "\\cdots"), Br("\\dotsm", "\\cdots"), Br("\\dotsi", "\\!\\cdots"), Br("\\dotsx", "\\ldots\\,"), Br("\\DOTSI", "\\relax"), Br("\\DOTSB", "\\relax"), Br("\\DOTSX", "\\relax"), Br("\\tmspace", "\\TextOrMath{\\kern#1#3}{\\mskip#1#2}\\relax"), Br("\\,", "\\tmspace+{3mu}{.1667em}"), Br("\\thinspace", "\\,"), Br("\\>", "\\mskip{4mu}"), Br("\\:", "\\tmspace+{4mu}{.2222em}"), Br("\\medspace", "\\:"), Br("\\;", "\\tmspace+{5mu}{.2777em}"), Br("\\thickspace", "\\;"), Br("\\!", "\\tmspace-{3mu}{.1667em}"), Br("\\negthinspace", "\\!"), Br("\\negmedspace", "\\tmspace-{4mu}{.2222em}"), Br("\\negthickspace", "\\tmspace-{5mu}{.277em}"), Br("\\enspace", "\\kern.5em "), Br("\\enskip", "\\hskip.5em\\relax"), Br("\\quad", "\\hskip1em\\relax"), Br("\\qquad", "\\hskip2em\\relax"), Br("\\tag", "\\@ifstar\\tag@literal\\tag@paren"), Br("\\tag@paren", "\\tag@literal{({#1})}"), Br("\\tag@literal", (e => { if (e.macros.get("\\df@tag")) throw new n("Multiple \\tag"); return "\\gdef\\df@tag{\\text{#1}}" })), Br("\\bmod", "\\mathchoice{\\mskip1mu}{\\mskip1mu}{\\mskip5mu}{\\mskip5mu}\\mathbin{\\rm mod}\\mathchoice{\\mskip1mu}{\\mskip1mu}{\\mskip5mu}{\\mskip5mu}"), Br("\\pod", "\\allowbreak\\mathchoice{\\mkern18mu}{\\mkern8mu}{\\mkern8mu}{\\mkern8mu}(#1)"), Br("\\pmod", "\\pod{{\\rm mod}\\mkern6mu#1}"), Br("\\mod", "\\allowbreak\\mathchoice{\\mkern18mu}{\\mkern12mu}{\\mkern12mu}{\\mkern12mu}{\\rm mod}\\,\\,#1"), Br("\\newline", "\\\\\\relax"), Br("\\TeX", "\\textrm{\\html@mathml{T\\kern-.1667em\\raisebox{-.5ex}{E}\\kern-.125emX}{TeX}}"); const qn = F(T["Main-Regular"]["T".charCodeAt(0)][1] - .7 * T["Main-Regular"]["A".charCodeAt(0)][1]); Br("\\LaTeX", "\\textrm{\\html@mathml{L\\kern-.36em\\raisebox{" + qn + "}{\\scriptstyle A}\\kern-.15em\\TeX}{LaTeX}}"), Br("\\KaTeX", "\\textrm{\\html@mathml{K\\kern-.17em\\raisebox{" + qn + "}{\\scriptstyle A}\\kern-.15em\\TeX}{KaTeX}}"), Br("\\hspace", "\\@ifstar\\@hspacer\\@hspace"), Br("\\@hspace", "\\hskip #1\\relax"), Br("\\@hspacer", "\\rule{0pt}{0pt}\\hskip #1\\relax"), Br("\\ordinarycolon", ":"), Br("\\vcentcolon", "\\mathrel{\\mathop\\ordinarycolon}"), Br("\\dblcolon", '\\html@mathml{\\mathrel{\\vcentcolon\\mathrel{\\mkern-.9mu}\\vcentcolon}}{\\mathop{\\char"2237}}'), Br("\\coloneqq", '\\html@mathml{\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}=}}{\\mathop{\\char"2254}}'), Br("\\Coloneqq", '\\html@mathml{\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}=}}{\\mathop{\\char"2237\\char"3d}}'), Br("\\coloneq", '\\html@mathml{\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}\\mathrel{-}}}{\\mathop{\\char"3a\\char"2212}}'), Br("\\Coloneq", '\\html@mathml{\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}\\mathrel{-}}}{\\mathop{\\char"2237\\char"2212}}'), Br("\\eqqcolon", '\\html@mathml{\\mathrel{=\\mathrel{\\mkern-1.2mu}\\vcentcolon}}{\\mathop{\\char"2255}}'), Br("\\Eqqcolon", '\\html@mathml{\\mathrel{=\\mathrel{\\mkern-1.2mu}\\dblcolon}}{\\mathop{\\char"3d\\char"2237}}'), Br("\\eqcolon", '\\html@mathml{\\mathrel{\\mathrel{-}\\mathrel{\\mkern-1.2mu}\\vcentcolon}}{\\mathop{\\char"2239}}'), Br("\\Eqcolon", '\\html@mathml{\\mathrel{\\mathrel{-}\\mathrel{\\mkern-1.2mu}\\dblcolon}}{\\mathop{\\char"2212\\char"2237}}'), Br("\\colonapprox", '\\html@mathml{\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}\\approx}}{\\mathop{\\char"3a\\char"2248}}'), Br("\\Colonapprox", '\\html@mathml{\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}\\approx}}{\\mathop{\\char"2237\\char"2248}}'), Br("\\colonsim", '\\html@mathml{\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}\\sim}}{\\mathop{\\char"3a\\char"223c}}'), Br("\\Colonsim", '\\html@mathml{\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}\\sim}}{\\mathop{\\char"2237\\char"223c}}'), Br("\u2237", "\\dblcolon"), Br("\u2239", "\\eqcolon"), Br("\u2254", "\\coloneqq"), Br("\u2255", "\\eqqcolon"), Br("\u2a74", "\\Coloneqq"), Br("\\ratio", "\\vcentcolon"), Br("\\coloncolon", "\\dblcolon"), Br("\\colonequals", "\\coloneqq"), Br("\\coloncolonequals", "\\Coloneqq"), Br("\\equalscolon", "\\eqqcolon"), Br("\\equalscoloncolon", "\\Eqqcolon"), Br("\\colonminus", "\\coloneq"), Br("\\coloncolonminus", "\\Coloneq"), Br("\\minuscolon", "\\eqcolon"), Br("\\minuscoloncolon", "\\Eqcolon"), Br("\\coloncolonapprox", "\\Colonapprox"), Br("\\coloncolonsim", "\\Colonsim"), Br("\\simcolon", "\\mathrel{\\sim\\mathrel{\\mkern-1.2mu}\\vcentcolon}"), Br("\\simcoloncolon", "\\mathrel{\\sim\\mathrel{\\mkern-1.2mu}\\dblcolon}"), Br("\\approxcolon", "\\mathrel{\\approx\\mathrel{\\mkern-1.2mu}\\vcentcolon}"), Br("\\approxcoloncolon", "\\mathrel{\\approx\\mathrel{\\mkern-1.2mu}\\dblcolon}"), Br("\\notni", "\\html@mathml{\\not\\ni}{\\mathrel{\\char`\u220c}}"), Br("\\limsup", "\\DOTSB\\operatorname*{lim\\,sup}"), Br("\\liminf", "\\DOTSB\\operatorname*{lim\\,inf}"), Br("\\injlim", "\\DOTSB\\operatorname*{inj\\,lim}"), Br("\\projlim", "\\DOTSB\\operatorname*{proj\\,lim}"), Br("\\varlimsup", "\\DOTSB\\operatorname*{\\overline{lim}}"), Br("\\varliminf", "\\DOTSB\\operatorname*{\\underline{lim}}"), Br("\\varinjlim", "\\DOTSB\\operatorname*{\\underrightarrow{lim}}"), Br("\\varprojlim", "\\DOTSB\\operatorname*{\\underleftarrow{lim}}"), Br("\\gvertneqq", "\\html@mathml{\\@gvertneqq}{\u2269}"), Br("\\lvertneqq", "\\html@mathml{\\@lvertneqq}{\u2268}"), Br("\\ngeqq", "\\html@mathml{\\@ngeqq}{\u2271}"), Br("\\ngeqslant", "\\html@mathml{\\@ngeqslant}{\u2271}"), Br("\\nleqq", "\\html@mathml{\\@nleqq}{\u2270}"), Br("\\nleqslant", "\\html@mathml{\\@nleqslant}{\u2270}"), Br("\\nshortmid", "\\html@mathml{\\@nshortmid}{\u2224}"), Br("\\nshortparallel", "\\html@mathml{\\@nshortparallel}{\u2226}"), Br("\\nsubseteqq", "\\html@mathml{\\@nsubseteqq}{\u2288}"), Br("\\nsupseteqq", "\\html@mathml{\\@nsupseteqq}{\u2289}"), Br("\\varsubsetneq", "\\html@mathml{\\@varsubsetneq}{\u228a}"), Br("\\varsubsetneqq", "\\html@mathml{\\@varsubsetneqq}{\u2acb}"), Br("\\varsupsetneq", "\\html@mathml{\\@varsupsetneq}{\u228b}"), Br("\\varsupsetneqq", "\\html@mathml{\\@varsupsetneqq}{\u2acc}"), Br("\\imath", "\\html@mathml{\\@imath}{\u0131}"), Br("\\jmath", "\\html@mathml{\\@jmath}{\u0237}"), Br("\\llbracket", "\\html@mathml{\\mathopen{[\\mkern-3.2mu[}}{\\mathopen{\\char`\u27e6}}"), Br("\\rrbracket", "\\html@mathml{\\mathclose{]\\mkern-3.2mu]}}{\\mathclose{\\char`\u27e7}}"), Br("\u27e6", "\\llbracket"), Br("\u27e7", "\\rrbracket"), Br("\\lBrace", "\\html@mathml{\\mathopen{\\{\\mkern-3.2mu[}}{\\mathopen{\\char`\u2983}}"), Br("\\rBrace", "\\html@mathml{\\mathclose{]\\mkern-3.2mu\\}}}{\\mathclose{\\char`\u2984}}"), Br("\u2983", "\\lBrace"), Br("\u2984", "\\rBrace"), Br("\\minuso", "\\mathbin{\\html@mathml{{\\mathrlap{\\mathchoice{\\kern{0.145em}}{\\kern{0.145em}}{\\kern{0.1015em}}{\\kern{0.0725em}}\\circ}{-}}}{\\char`\u29b5}}"), Br("\u29b5", "\\minuso"), Br("\\darr", "\\downarrow"), Br("\\dArr", "\\Downarrow"), Br("\\Darr", "\\Downarrow"), Br("\\lang", "\\langle"), Br("\\rang", "\\rangle"), Br("\\uarr", "\\uparrow"), Br("\\uArr", "\\Uparrow"), Br("\\Uarr", "\\Uparrow"), Br("\\N", "\\mathbb{N}"), Br("\\R", "\\mathbb{R}"), Br("\\Z", "\\mathbb{Z}"), Br("\\alef", "\\aleph"), Br("\\alefsym", "\\aleph"), Br("\\Alpha", "\\mathrm{A}"), Br("\\Beta", "\\mathrm{B}"), Br("\\bull", "\\bullet"), Br("\\Chi", "\\mathrm{X}"), Br("\\clubs", "\\clubsuit"), Br("\\cnums", "\\mathbb{C}"), Br("\\Complex", "\\mathbb{C}"), Br("\\Dagger", "\\ddagger"), Br("\\diamonds", "\\diamondsuit"), Br("\\empty", "\\emptyset"), Br("\\Epsilon", "\\mathrm{E}"), Br("\\Eta", "\\mathrm{H}"), Br("\\exist", "\\exists"), Br("\\harr", "\\leftrightarrow"), Br("\\hArr", "\\Leftrightarrow"), Br("\\Harr", "\\Leftrightarrow"), Br("\\hearts", "\\heartsuit"), Br("\\image", "\\Im"), Br("\\infin", "\\infty"), Br("\\Iota", "\\mathrm{I}"), Br("\\isin", "\\in"), Br("\\Kappa", "\\mathrm{K}"), Br("\\larr", "\\leftarrow"), Br("\\lArr", "\\Leftarrow"), Br("\\Larr", "\\Leftarrow"), Br("\\lrarr", "\\leftrightarrow"), Br("\\lrArr", "\\Leftrightarrow"), Br("\\Lrarr", "\\Leftrightarrow"), Br("\\Mu", "\\mathrm{M}"), Br("\\natnums", "\\mathbb{N}"), Br("\\Nu", "\\mathrm{N}"), Br("\\Omicron", "\\mathrm{O}"), Br("\\plusmn", "\\pm"), Br("\\rarr", "\\rightarrow"), Br("\\rArr", "\\Rightarrow"), Br("\\Rarr", "\\Rightarrow"), Br("\\real", "\\Re"), Br("\\reals", "\\mathbb{R}"), Br("\\Reals", "\\mathbb{R}"), Br("\\Rho", "\\mathrm{P}"), Br("\\sdot", "\\cdot"), Br("\\sect", "\\S"), Br("\\spades", "\\spadesuit"), Br("\\sub", "\\subset"), Br("\\sube", "\\subseteq"), Br("\\supe", "\\supseteq"), Br("\\Tau", "\\mathrm{T}"), Br("\\thetasym", "\\vartheta"), Br("\\weierp", "\\wp"), Br("\\Zeta", "\\mathrm{Z}"), Br("\\argmin", "\\DOTSB\\operatorname*{arg\\,min}"), Br("\\argmax", "\\DOTSB\\operatorname*{arg\\,max}"), Br("\\plim", "\\DOTSB\\mathop{\\operatorname{plim}}\\limits"), Br("\\bra", "\\mathinner{\\langle{#1}|}"), Br("\\ket", "\\mathinner{|{#1}\\rangle}"), Br("\\braket", "\\mathinner{\\langle{#1}\\rangle}"), Br("\\Bra", "\\left\\langle#1\\right|"), Br("\\Ket", "\\left|#1\\right\\rangle"); const In = e => t => { const r = t.consumeArg().tokens, n = t.consumeArg().tokens, o = t.consumeArg().tokens, s = t.consumeArg().tokens, i = t.macros.get("|"), a = t.macros.get("\\|"); t.macros.beginGroup(); const l = t => r => { e && (r.macros.set("|", i), o.length && r.macros.set("\\|", a)); let s = t; if (!t && o.length) { "|" === r.future().text && (r.popToken(), s = !0) } return { tokens: s ? o : n, numArgs: 0 } }; t.macros.set("|", l(!1)), o.length && t.macros.set("\\|", l(!0)); const h = t.consumeArg().tokens, c = t.expandTokens([...s, ...h, ...r]); return t.macros.endGroup(), { tokens: c.reverse(), numArgs: 0 } }; Br("\\bra@ket", In(!1)), Br("\\bra@set", In(!0)), Br("\\Braket", "\\bra@ket{\\left\\langle}{\\,\\middle\\vert\\,}{\\,\\middle\\vert\\,}{\\right\\rangle}"), Br("\\Set", "\\bra@set{\\left\\{\\:}{\\;\\middle\\vert\\;}{\\;\\middle\\Vert\\;}{\\:\\right\\}}"), Br("\\set", "\\bra@set{\\{\\,}{\\mid}{}{\\,\\}}"), Br("\\angln", "{\\angl n}"), Br("\\blue", "\\textcolor{##6495ed}{#1}"), Br("\\orange", "\\textcolor{##ffa500}{#1}"), Br("\\pink", "\\textcolor{##ff00af}{#1}"), Br("\\red", "\\textcolor{##df0030}{#1}"), Br("\\green", "\\textcolor{##28ae7b}{#1}"), Br("\\gray", "\\textcolor{gray}{#1}"), Br("\\purple", "\\textcolor{##9d38bd}{#1}"), Br("\\blueA", "\\textcolor{##ccfaff}{#1}"), Br("\\blueB", "\\textcolor{##80f6ff}{#1}"), Br("\\blueC", "\\textcolor{##63d9ea}{#1}"), Br("\\blueD", "\\textcolor{##11accd}{#1}"), Br("\\blueE", "\\textcolor{##0c7f99}{#1}"), Br("\\tealA", "\\textcolor{##94fff5}{#1}"), Br("\\tealB", "\\textcolor{##26edd5}{#1}"), Br("\\tealC", "\\textcolor{##01d1c1}{#1}"), Br("\\tealD", "\\textcolor{##01a995}{#1}"), Br("\\tealE", "\\textcolor{##208170}{#1}"), Br("\\greenA", "\\textcolor{##b6ffb0}{#1}"), Br("\\greenB", "\\textcolor{##8af281}{#1}"), Br("\\greenC", "\\textcolor{##74cf70}{#1}"), Br("\\greenD", "\\textcolor{##1fab54}{#1}"), Br("\\greenE", "\\textcolor{##0d923f}{#1}"), Br("\\goldA", "\\textcolor{##ffd0a9}{#1}"), Br("\\goldB", "\\textcolor{##ffbb71}{#1}"), Br("\\goldC", "\\textcolor{##ff9c39}{#1}"), Br("\\goldD", "\\textcolor{##e07d10}{#1}"), Br("\\goldE", "\\textcolor{##a75a05}{#1}"), Br("\\redA", "\\textcolor{##fca9a9}{#1}"), Br("\\redB", "\\textcolor{##ff8482}{#1}"), Br("\\redC", "\\textcolor{##f9685d}{#1}"), Br("\\redD", "\\textcolor{##e84d39}{#1}"), Br("\\redE", "\\textcolor{##bc2612}{#1}"), Br("\\maroonA", "\\textcolor{##ffbde0}{#1}"), Br("\\maroonB", "\\textcolor{##ff92c6}{#1}"), Br("\\maroonC", "\\textcolor{##ed5fa6}{#1}"), Br("\\maroonD", "\\textcolor{##ca337c}{#1}"), Br("\\maroonE", "\\textcolor{##9e034e}{#1}"), Br("\\purpleA", "\\textcolor{##ddd7ff}{#1}"), Br("\\purpleB", "\\textcolor{##c6b9fc}{#1}"), Br("\\purpleC", "\\textcolor{##aa87ff}{#1}"), Br("\\purpleD", "\\textcolor{##7854ab}{#1}"), Br("\\purpleE", "\\textcolor{##543b78}{#1}"), Br("\\mintA", "\\textcolor{##f5f9e8}{#1}"), Br("\\mintB", "\\textcolor{##edf2df}{#1}"), Br("\\mintC", "\\textcolor{##e0e5cc}{#1}"), Br("\\grayA", "\\textcolor{##f6f7f7}{#1}"), Br("\\grayB", "\\textcolor{##f0f1f2}{#1}"), Br("\\grayC", "\\textcolor{##e3e5e6}{#1}"), Br("\\grayD", "\\textcolor{##d6d8da}{#1}"), Br("\\grayE", "\\textcolor{##babec2}{#1}"), Br("\\grayF", "\\textcolor{##888d93}{#1}"), Br("\\grayG", "\\textcolor{##626569}{#1}"), Br("\\grayH", "\\textcolor{##3b3e40}{#1}"), Br("\\grayI", "\\textcolor{##21242c}{#1}"), Br("\\kaBlue", "\\textcolor{##314453}{#1}"), Br("\\kaGreen", "\\textcolor{##71B307}{#1}"); const Rn = { "^": !0, _: !0, "\\limits": !0, "\\nolimits": !0 }; class Hn { constructor(e, t, r) { this.settings = void 0, this.expansionCount = void 0, this.lexer = void 0, this.macros = void 0, this.stack = void 0, this.mode = void 0, this.settings = t, this.expansionCount = 0, this.feed(e), this.macros = new zn(An, t.macros), this.mode = r, this.stack = [] } feed(e) { this.lexer = new Mn(e, this.settings) } switchMode(e) { this.mode = e } beginGroup() { this.macros.beginGroup() } endGroup() { this.macros.endGroup() } endGroups() { this.macros.endGroups() } future() { return 0 === this.stack.length && this.pushToken(this.lexer.lex()), this.stack[this.stack.length - 1] } popToken() { return this.future(), this.stack.pop() } pushToken(e) { this.stack.push(e) } pushTokens(e) { this.stack.push(...e) } scanArgument(e) { let t, r, n; if (e) { if (this.consumeSpaces(), "[" !== this.future().text) return null; t = this.popToken(), ({ tokens: n, end: r } = this.consumeArg(["]"])) } else ({ tokens: n, start: t, end: r } = this.consumeArg()); return this.pushToken(new Nr("EOF", r.loc)), this.pushTokens(n), t.range(r, "") } consumeSpaces() { for (; ;) { if (" " !== this.future().text) break; this.stack.pop() } } consumeArg(e) { const t = [], r = e && e.length > 0; r || this.consumeSpaces(); const o = this.future(); let s, i = 0, a = 0; do { if (s = this.popToken(), t.push(s), "{" === s.text) ++i; else if ("}" === s.text) { if (--i, -1 === i) throw new n("Extra }", s) } else if ("EOF" === s.text) throw new n("Unexpected end of input in a macro argument, expected '" + (e && r ? e[a] : "}") + "'", s); if (e && r) if ((0 === i || 1 === i && "{" === e[a]) && s.text === e[a]) { if (++a, a === e.length) { t.splice(-a, a); break } } else a = 0 } while (0 !== i || r); return "{" === o.text && "}" === t[t.length - 1].text && (t.pop(), t.shift()), t.reverse(), { tokens: t, start: o, end: s } } consumeArgs(e, t) { if (t) { if (t.length !== e + 1) throw new n("The length of delimiters doesn't match the number of args!"); const r = t[0]; for (let e = 0; e < r.length; e++) { const t = this.popToken(); if (r[e] !== t.text) throw new n("Use of the macro doesn't match its definition", t) } } const r = []; for (let n = 0; n < e; n++)r.push(this.consumeArg(t && t[n + 1]).tokens); return r } countExpansion(e) { if (this.expansionCount += e, this.expansionCount > this.settings.maxExpand) throw new n("Too many expansions: infinite loop or need to increase maxExpand setting") } expandOnce(e) { const t = this.popToken(), r = t.text, o = t.noexpand ? null : this._getExpansion(r); if (null == o || e && o.unexpandable) { if (e && null == o && "\\" === r[0] && !this.isDefined(r)) throw new n("Undefined control sequence: " + r); return this.pushToken(t), !1 } this.countExpansion(1); let s = o.tokens; const i = this.consumeArgs(o.numArgs, o.delimiters); if (o.numArgs) { s = s.slice(); for (let e = s.length - 1; e >= 0; --e) { let t = s[e]; if ("#" === t.text) { if (0 === e) throw new n("Incomplete placeholder at end of macro body", t); if (t = s[--e], "#" === t.text) s.splice(e + 1, 1); else { if (!/^[1-9]$/.test(t.text)) throw new n("Not a valid argument number", t); s.splice(e, 2, ...i[+t.text - 1]) } } } } return this.pushTokens(s), s.length } expandAfterFuture() { return this.expandOnce(), this.future() } expandNextToken() { for (; ;)if (!1 === this.expandOnce()) { const e = this.stack.pop(); return e.treatAsRelax && (e.text = "\\relax"), e } throw new Error } expandMacro(e) { return this.macros.has(e) ? this.expandTokens([new Nr(e)]) : void 0 } expandTokens(e) { const t = [], r = this.stack.length; for (this.pushTokens(e); this.stack.length > r;)if (!1 === this.expandOnce(!0)) { const e = this.stack.pop(); e.treatAsRelax && (e.noexpand = !1, e.treatAsRelax = !1), t.push(e) } return this.countExpansion(t.length), t } expandMacroAsText(e) { const t = this.expandMacro(e); return t ? t.map((e => e.text)).join("") : t } _getExpansion(e) { const t = this.macros.get(e); if (null == t) return t; if (1 === e.length) { const t = this.lexer.catcodes[e]; if (null != t && 13 !== t) return } const r = "function" == typeof t ? t(this) : t; if ("string" == typeof r) { let e = 0; if (-1 !== r.indexOf("#")) { const t = r.replace(/##/g, ""); for (; -1 !== t.indexOf("#" + (e + 1));)++e } const t = new Mn(r, this.settings), n = []; let o = t.lex(); for (; "EOF" !== o.text;)n.push(o), o = t.lex(); n.reverse(); return { tokens: n, numArgs: e } } return r } isDefined(e) { return this.macros.has(e) || yn.hasOwnProperty(e) || oe.math.hasOwnProperty(e) || oe.text.hasOwnProperty(e) || Rn.hasOwnProperty(e) } isExpandable(e) { const t = this.macros.get(e); return null != t ? "string" == typeof t || "function" == typeof t || !t.unexpandable : yn.hasOwnProperty(e) && !yn[e].primitive } } const On = /^[\u208a\u208b\u208c\u208d\u208e\u2080\u2081\u2082\u2083\u2084\u2085\u2086\u2087\u2088\u2089\u2090\u2091\u2095\u1d62\u2c7c\u2096\u2097\u2098\u2099\u2092\u209a\u1d63\u209b\u209c\u1d64\u1d65\u2093\u1d66\u1d67\u1d68\u1d69\u1d6a]/, En = Object.freeze({ "\u208a": "+", "\u208b": "-", "\u208c": "=", "\u208d": "(", "\u208e": ")", "\u2080": "0", "\u2081": "1", "\u2082": "2", "\u2083": "3", "\u2084": "4", "\u2085": "5", "\u2086": "6", "\u2087": "7", "\u2088": "8", "\u2089": "9", "\u2090": "a", "\u2091": "e", "\u2095": "h", "\u1d62": "i", "\u2c7c": "j", "\u2096": "k", "\u2097": "l", "\u2098": "m", "\u2099": "n", "\u2092": "o", "\u209a": "p", "\u1d63": "r", "\u209b": "s", "\u209c": "t", "\u1d64": "u", "\u1d65": "v", "\u2093": "x", "\u1d66": "\u03b2", "\u1d67": "\u03b3", "\u1d68": "\u03c1", "\u1d69": "\u03d5", "\u1d6a": "\u03c7", "\u207a": "+", "\u207b": "-", "\u207c": "=", "\u207d": "(", "\u207e": ")", "\u2070": "0", "\xb9": "1", "\xb2": "2", "\xb3": "3", "\u2074": "4", "\u2075": "5", "\u2076": "6", "\u2077": "7", "\u2078": "8", "\u2079": "9", "\u1d2c": "A", "\u1d2e": "B", "\u1d30": "D", "\u1d31": "E", "\u1d33": "G", "\u1d34": "H", "\u1d35": "I", "\u1d36": "J", "\u1d37": "K", "\u1d38": "L", "\u1d39": "M", "\u1d3a": "N", "\u1d3c": "O", "\u1d3e": "P", "\u1d3f": "R", "\u1d40": "T", "\u1d41": "U", "\u2c7d": "V", "\u1d42": "W", "\u1d43": "a", "\u1d47": "b", "\u1d9c": "c", "\u1d48": "d", "\u1d49": "e", "\u1da0": "f", "\u1d4d": "g", "\u02b0": "h", "\u2071": "i", "\u02b2": "j", "\u1d4f": "k", "\u02e1": "l", "\u1d50": "m", "\u207f": "n", "\u1d52": "o", "\u1d56": "p", "\u02b3": "r", "\u02e2": "s", "\u1d57": "t", "\u1d58": "u", "\u1d5b": "v", "\u02b7": "w", "\u02e3": "x", "\u02b8": "y", "\u1dbb": "z", "\u1d5d": "\u03b2", "\u1d5e": "\u03b3", "\u1d5f": "\u03b4", "\u1d60": "\u03d5", "\u1d61": "\u03c7", "\u1dbf": "\u03b8" }), Ln = { "\u0301": { text: "\\'", math: "\\acute" }, "\u0300": { text: "\\`", math: "\\grave" }, "\u0308": { text: '\\"', math: "\\ddot" }, "\u0303": { text: "\\~", math: "\\tilde" }, "\u0304": { text: "\\=", math: "\\bar" }, "\u0306": { text: "\\u", math: "\\breve" }, "\u030c": { text: "\\v", math: "\\check" }, "\u0302": { text: "\\^", math: "\\hat" }, "\u0307": { text: "\\.", math: "\\dot" }, "\u030a": { text: "\\r", math: "\\mathring" }, "\u030b": { text: "\\H" }, "\u0327": { text: "\\c" } }, Dn = { "\xe1": "a\u0301", "\xe0": "a\u0300", "\xe4": "a\u0308", "\u01df": "a\u0308\u0304", "\xe3": "a\u0303", "\u0101": "a\u0304", "\u0103": "a\u0306", "\u1eaf": "a\u0306\u0301", "\u1eb1": "a\u0306\u0300", "\u1eb5": "a\u0306\u0303", "\u01ce": "a\u030c", "\xe2": "a\u0302", "\u1ea5": "a\u0302\u0301", "\u1ea7": "a\u0302\u0300", "\u1eab": "a\u0302\u0303", "\u0227": "a\u0307", "\u01e1": "a\u0307\u0304", "\xe5": "a\u030a", "\u01fb": "a\u030a\u0301", "\u1e03": "b\u0307", "\u0107": "c\u0301", "\u1e09": "c\u0327\u0301", "\u010d": "c\u030c", "\u0109": "c\u0302", "\u010b": "c\u0307", "\xe7": "c\u0327", "\u010f": "d\u030c", "\u1e0b": "d\u0307", "\u1e11": "d\u0327", "\xe9": "e\u0301", "\xe8": "e\u0300", "\xeb": "e\u0308", "\u1ebd": "e\u0303", "\u0113": "e\u0304", "\u1e17": "e\u0304\u0301", "\u1e15": "e\u0304\u0300", "\u0115": "e\u0306", "\u1e1d": "e\u0327\u0306", "\u011b": "e\u030c", "\xea": "e\u0302", "\u1ebf": "e\u0302\u0301", "\u1ec1": "e\u0302\u0300", "\u1ec5": "e\u0302\u0303", "\u0117": "e\u0307", "\u0229": "e\u0327", "\u1e1f": "f\u0307", "\u01f5": "g\u0301", "\u1e21": "g\u0304", "\u011f": "g\u0306", "\u01e7": "g\u030c", "\u011d": "g\u0302", "\u0121": "g\u0307", "\u0123": "g\u0327", "\u1e27": "h\u0308", "\u021f": "h\u030c", "\u0125": "h\u0302", "\u1e23": "h\u0307", "\u1e29": "h\u0327", "\xed": "i\u0301", "\xec": "i\u0300", "\xef": "i\u0308", "\u1e2f": "i\u0308\u0301", "\u0129": "i\u0303", "\u012b": "i\u0304", "\u012d": "i\u0306", "\u01d0": "i\u030c", "\xee": "i\u0302", "\u01f0": "j\u030c", "\u0135": "j\u0302", "\u1e31": "k\u0301", "\u01e9": "k\u030c", "\u0137": "k\u0327", "\u013a": "l\u0301", "\u013e": "l\u030c", "\u013c": "l\u0327", "\u1e3f": "m\u0301", "\u1e41": "m\u0307", "\u0144": "n\u0301", "\u01f9": "n\u0300", "\xf1": "n\u0303", "\u0148": "n\u030c", "\u1e45": "n\u0307", "\u0146": "n\u0327", "\xf3": "o\u0301", "\xf2": "o\u0300", "\xf6": "o\u0308", "\u022b": "o\u0308\u0304", "\xf5": "o\u0303", "\u1e4d": "o\u0303\u0301", "\u1e4f": "o\u0303\u0308", "\u022d": "o\u0303\u0304", "\u014d": "o\u0304", "\u1e53": "o\u0304\u0301", "\u1e51": "o\u0304\u0300", "\u014f": "o\u0306", "\u01d2": "o\u030c", "\xf4": "o\u0302", "\u1ed1": "o\u0302\u0301", "\u1ed3": "o\u0302\u0300", "\u1ed7": "o\u0302\u0303", "\u022f": "o\u0307", "\u0231": "o\u0307\u0304", "\u0151": "o\u030b", "\u1e55": "p\u0301", "\u1e57": "p\u0307", "\u0155": "r\u0301", "\u0159": "r\u030c", "\u1e59": "r\u0307", "\u0157": "r\u0327", "\u015b": "s\u0301", "\u1e65": "s\u0301\u0307", "\u0161": "s\u030c", "\u1e67": "s\u030c\u0307", "\u015d": "s\u0302", "\u1e61": "s\u0307", "\u015f": "s\u0327", "\u1e97": "t\u0308", "\u0165": "t\u030c", "\u1e6b": "t\u0307", "\u0163": "t\u0327", "\xfa": "u\u0301", "\xf9": "u\u0300", "\xfc": "u\u0308", "\u01d8": "u\u0308\u0301", "\u01dc": "u\u0308\u0300", "\u01d6": "u\u0308\u0304", "\u01da": "u\u0308\u030c", "\u0169": "u\u0303", "\u1e79": "u\u0303\u0301", "\u016b": "u\u0304", "\u1e7b": "u\u0304\u0308", "\u016d": "u\u0306", "\u01d4": "u\u030c", "\xfb": "u\u0302", "\u016f": "u\u030a", "\u0171": "u\u030b", "\u1e7d": "v\u0303", "\u1e83": "w\u0301", "\u1e81": "w\u0300", "\u1e85": "w\u0308", "\u0175": "w\u0302", "\u1e87": "w\u0307", "\u1e98": "w\u030a", "\u1e8d": "x\u0308", "\u1e8b": "x\u0307", "\xfd": "y\u0301", "\u1ef3": "y\u0300", "\xff": "y\u0308", "\u1ef9": "y\u0303", "\u0233": "y\u0304", "\u0177": "y\u0302", "\u1e8f": "y\u0307", "\u1e99": "y\u030a", "\u017a": "z\u0301", "\u017e": "z\u030c", "\u1e91": "z\u0302", "\u017c": "z\u0307", "\xc1": "A\u0301", "\xc0": "A\u0300", "\xc4": "A\u0308", "\u01de": "A\u0308\u0304", "\xc3": "A\u0303", "\u0100": "A\u0304", "\u0102": "A\u0306", "\u1eae": "A\u0306\u0301", "\u1eb0": "A\u0306\u0300", "\u1eb4": "A\u0306\u0303", "\u01cd": "A\u030c", "\xc2": "A\u0302", "\u1ea4": "A\u0302\u0301", "\u1ea6": "A\u0302\u0300", "\u1eaa": "A\u0302\u0303", "\u0226": "A\u0307", "\u01e0": "A\u0307\u0304", "\xc5": "A\u030a", "\u01fa": "A\u030a\u0301", "\u1e02": "B\u0307", "\u0106": "C\u0301", "\u1e08": "C\u0327\u0301", "\u010c": "C\u030c", "\u0108": "C\u0302", "\u010a": "C\u0307", "\xc7": "C\u0327", "\u010e": "D\u030c", "\u1e0a": "D\u0307", "\u1e10": "D\u0327", "\xc9": "E\u0301", "\xc8": "E\u0300", "\xcb": "E\u0308", "\u1ebc": "E\u0303", "\u0112": "E\u0304", "\u1e16": "E\u0304\u0301", "\u1e14": "E\u0304\u0300", "\u0114": "E\u0306", "\u1e1c": "E\u0327\u0306", "\u011a": "E\u030c", "\xca": "E\u0302", "\u1ebe": "E\u0302\u0301", "\u1ec0": "E\u0302\u0300", "\u1ec4": "E\u0302\u0303", "\u0116": "E\u0307", "\u0228": "E\u0327", "\u1e1e": "F\u0307", "\u01f4": "G\u0301", "\u1e20": "G\u0304", "\u011e": "G\u0306", "\u01e6": "G\u030c", "\u011c": "G\u0302", "\u0120": "G\u0307", "\u0122": "G\u0327", "\u1e26": "H\u0308", "\u021e": "H\u030c", "\u0124": "H\u0302", "\u1e22": "H\u0307", "\u1e28": "H\u0327", "\xcd": "I\u0301", "\xcc": "I\u0300", "\xcf": "I\u0308", "\u1e2e": "I\u0308\u0301", "\u0128": "I\u0303", "\u012a": "I\u0304", "\u012c": "I\u0306", "\u01cf": "I\u030c", "\xce": "I\u0302", "\u0130": "I\u0307", "\u0134": "J\u0302", "\u1e30": "K\u0301", "\u01e8": "K\u030c", "\u0136": "K\u0327", "\u0139": "L\u0301", "\u013d": "L\u030c", "\u013b": "L\u0327", "\u1e3e": "M\u0301", "\u1e40": "M\u0307", "\u0143": "N\u0301", "\u01f8": "N\u0300", "\xd1": "N\u0303", "\u0147": "N\u030c", "\u1e44": "N\u0307", "\u0145": "N\u0327", "\xd3": "O\u0301", "\xd2": "O\u0300", "\xd6": "O\u0308", "\u022a": "O\u0308\u0304", "\xd5": "O\u0303", "\u1e4c": "O\u0303\u0301", "\u1e4e": "O\u0303\u0308", "\u022c": "O\u0303\u0304", "\u014c": "O\u0304", "\u1e52": "O\u0304\u0301", "\u1e50": "O\u0304\u0300", "\u014e": "O\u0306", "\u01d1": "O\u030c", "\xd4": "O\u0302", "\u1ed0": "O\u0302\u0301", "\u1ed2": "O\u0302\u0300", "\u1ed6": "O\u0302\u0303", "\u022e": "O\u0307", "\u0230": "O\u0307\u0304", "\u0150": "O\u030b", "\u1e54": "P\u0301", "\u1e56": "P\u0307", "\u0154": "R\u0301", "\u0158": "R\u030c", "\u1e58": "R\u0307", "\u0156": "R\u0327", "\u015a": "S\u0301", "\u1e64": "S\u0301\u0307", "\u0160": "S\u030c", "\u1e66": "S\u030c\u0307", "\u015c": "S\u0302", "\u1e60": "S\u0307", "\u015e": "S\u0327", "\u0164": "T\u030c", "\u1e6a": "T\u0307", "\u0162": "T\u0327", "\xda": "U\u0301", "\xd9": "U\u0300", "\xdc": "U\u0308", "\u01d7": "U\u0308\u0301", "\u01db": "U\u0308\u0300", "\u01d5": "U\u0308\u0304", "\u01d9": "U\u0308\u030c", "\u0168": "U\u0303", "\u1e78": "U\u0303\u0301", "\u016a": "U\u0304", "\u1e7a": "U\u0304\u0308", "\u016c": "U\u0306", "\u01d3": "U\u030c", "\xdb": "U\u0302", "\u016e": "U\u030a", "\u0170": "U\u030b", "\u1e7c": "V\u0303", "\u1e82": "W\u0301", "\u1e80": "W\u0300", "\u1e84": "W\u0308", "\u0174": "W\u0302", "\u1e86": "W\u0307", "\u1e8c": "X\u0308", "\u1e8a": "X\u0307", "\xdd": "Y\u0301", "\u1ef2": "Y\u0300", "\u0178": "Y\u0308", "\u1ef8": "Y\u0303", "\u0232": "Y\u0304", "\u0176": "Y\u0302", "\u1e8e": "Y\u0307", "\u0179": "Z\u0301", "\u017d": "Z\u030c", "\u1e90": "Z\u0302", "\u017b": "Z\u0307", "\u03ac": "\u03b1\u0301", "\u1f70": "\u03b1\u0300", "\u1fb1": "\u03b1\u0304", "\u1fb0": "\u03b1\u0306", "\u03ad": "\u03b5\u0301", "\u1f72": "\u03b5\u0300", "\u03ae": "\u03b7\u0301", "\u1f74": "\u03b7\u0300", "\u03af": "\u03b9\u0301", "\u1f76": "\u03b9\u0300", "\u03ca": "\u03b9\u0308", "\u0390": "\u03b9\u0308\u0301", "\u1fd2": "\u03b9\u0308\u0300", "\u1fd1": "\u03b9\u0304", "\u1fd0": "\u03b9\u0306", "\u03cc": "\u03bf\u0301", "\u1f78": "\u03bf\u0300", "\u03cd": "\u03c5\u0301", "\u1f7a": "\u03c5\u0300", "\u03cb": "\u03c5\u0308", "\u03b0": "\u03c5\u0308\u0301", "\u1fe2": "\u03c5\u0308\u0300", "\u1fe1": "\u03c5\u0304", "\u1fe0": "\u03c5\u0306", "\u03ce": "\u03c9\u0301", "\u1f7c": "\u03c9\u0300", "\u038e": "\u03a5\u0301", "\u1fea": "\u03a5\u0300", "\u03ab": "\u03a5\u0308", "\u1fe9": "\u03a5\u0304", "\u1fe8": "\u03a5\u0306", "\u038f": "\u03a9\u0301", "\u1ffa": "\u03a9\u0300" }; class Vn { constructor(e, t) { this.mode = void 0, this.gullet = void 0, this.settings = void 0, this.leftrightDepth = void 0, this.nextToken = void 0, this.mode = "math", this.gullet = new Hn(e, t, this.mode), this.settings = t, this.leftrightDepth = 0 } expect(e, t) { if (void 0 === t && (t = !0), this.fetch().text !== e) throw new n("Expected '" + e + "', got '" + this.fetch().text + "'", this.fetch()); t && this.consume() } consume() { this.nextToken = null } fetch() { return null == this.nextToken && (this.nextToken = this.gullet.expandNextToken()), this.nextToken } switchMode(e) { this.mode = e, this.gullet.switchMode(e) } parse() { this.settings.globalGroup || this.gullet.beginGroup(), this.settings.colorIsTextColor && this.gullet.macros.set("\\color", "\\textcolor"); try { const e = this.parseExpression(!1); return this.expect("EOF"), this.settings.globalGroup || this.gullet.endGroup(), e } finally { this.gullet.endGroups() } } subparse(e) { const t = this.nextToken; this.consume(), this.gullet.pushToken(new Nr("}")), this.gullet.pushTokens(e); const r = this.parseExpression(!1); return this.expect("}"), this.nextToken = t, r } parseExpression(e, t) { const r = []; for (; ;) { "math" === this.mode && this.consumeSpaces(); const n = this.fetch(); if (-1 !== Vn.endOfExpression.indexOf(n.text)) break; if (t && n.text === t) break; if (e && yn[n.text] && yn[n.text].infix) break; const o = this.parseAtom(t); if (!o) break; "internal" !== o.type && r.push(o) } return "text" === this.mode && this.formLigatures(r), this.handleInfixNodes(r) } handleInfixNodes(e) { let t, r = -1; for (let o = 0; o < e.length; o++)if ("infix" === e[o].type) { if (-1 !== r) throw new n("only one infix operator per group", e[o].token); r = o, t = e[o].replaceWith } if (-1 !== r && t) { let n, o; const s = e.slice(0, r), i = e.slice(r + 1); let a; return n = 1 === s.length && "ordgroup" === s[0].type ? s[0] : { type: "ordgroup", mode: this.mode, body: s }, o = 1 === i.length && "ordgroup" === i[0].type ? i[0] : { type: "ordgroup", mode: this.mode, body: i }, a = "\\\\abovefrac" === t ? this.callFunction(t, [n, e[r], o], []) : this.callFunction(t, [n, o], []), [a] } return e } handleSupSubscript(e) { const t = this.fetch(), r = t.text; this.consume(), this.consumeSpaces(); const o = this.parseGroup(e); if (!o) throw new n("Expected group after '" + r + "'", t); return o } formatUnsupportedCmd(e) { const t = []; for (let r = 0; r < e.length; r++)t.push({ type: "textord", mode: "text", text: e[r] }); const r = { type: "text", mode: this.mode, body: t }; return { type: "color", mode: this.mode, color: this.settings.errorColor, body: [r] } } parseAtom(e) { const t = this.parseGroup("atom", e); if ("text" === this.mode) return t; let r, o; for (; ;) { this.consumeSpaces(); const e = this.fetch(); if ("\\limits" === e.text || "\\nolimits" === e.text) { if (t && "op" === t.type) { const r = "\\limits" === e.text; t.limits = r, t.alwaysHandleSupSub = !0 } else { if (!t || "operatorname" !== t.type) throw new n("Limit controls must follow a math operator", e); t.alwaysHandleSupSub && (t.limits = "\\limits" === e.text) } this.consume() } else if ("^" === e.text) { if (r) throw new n("Double superscript", e); r = this.handleSupSubscript("superscript") } else if ("_" === e.text) { if (o) throw new n("Double subscript", e); o = this.handleSupSubscript("subscript") } else if ("'" === e.text) { if (r) throw new n("Double superscript", e); const t = { type: "textord", mode: this.mode, text: "\\prime" }, o = [t]; for (this.consume(); "'" === this.fetch().text;)o.push(t), this.consume(); "^" === this.fetch().text && o.push(this.handleSupSubscript("superscript")), r = { type: "ordgroup", mode: this.mode, body: o } } else { if (!En[e.text]) break; { const t = On.test(e.text), n = []; for (n.push(new Nr(En[e.text])), this.consume(); ;) { const e = this.fetch().text; if (!En[e]) break; if (On.test(e) !== t) break; n.unshift(new Nr(En[e])), this.consume() } const s = this.subparse(n); t ? o = { type: "ordgroup", mode: "math", body: s } : r = { type: "ordgroup", mode: "math", body: s } } } } return r || o ? { type: "supsub", mode: this.mode, base: t, sup: r, sub: o } : t } parseFunction(e, t) { const r = this.fetch(), o = r.text, s = yn[o]; if (!s) return null; if (this.consume(), t && "atom" !== t && !s.allowedInArgument) throw new n("Got function '" + o + "' with no arguments" + (t ? " as " + t : ""), r); if ("text" === this.mode && !s.allowedInText) throw new n("Can't use function '" + o + "' in text mode", r); if ("math" === this.mode && !1 === s.allowedInMath) throw new n("Can't use function '" + o + "' in math mode", r); const { args: i, optArgs: a } = this.parseArguments(o, s); return this.callFunction(o, i, a, r, e) } callFunction(e, t, r, o, s) { const i = { funcName: e, parser: this, token: o, breakOnTokenText: s }, a = yn[e]; if (a && a.handler) return a.handler(i, t, r); throw new n("No function handler for " + e) } parseArguments(e, t) { const r = t.numArgs + t.numOptionalArgs; if (0 === r) return { args: [], optArgs: [] }; const o = [], s = []; for (let i = 0; i < r; i++) { let r = t.argTypes && t.argTypes[i]; const a = i < t.numOptionalArgs; (t.primitive && null == r || "sqrt" === t.type && 1 === i && null == s[0]) && (r = "primitive"); const l = this.parseGroupOfType("argument to '" + e + "'", r, a); if (a) s.push(l); else { if (null == l) throw new n("Null argument, please report this as a bug"); o.push(l) } } return { args: o, optArgs: s } } parseGroupOfType(e, t, r) { switch (t) { case "color": return this.parseColorGroup(r); case "size": return this.parseSizeGroup(r); case "url": return this.parseUrlGroup(r); case "math": case "text": return this.parseArgumentGroup(r, t); case "hbox": { const e = this.parseArgumentGroup(r, "text"); return null != e ? { type: "styling", mode: e.mode, body: [e], style: "text" } : null } case "raw": { const e = this.parseStringGroup("raw", r); return null != e ? { type: "raw", mode: "text", string: e.text } : null } case "primitive": { if (r) throw new n("A primitive argument cannot be optional"); const t = this.parseGroup(e); if (null == t) throw new n("Expected group as " + e, this.fetch()); return t } case "original": case null: case void 0: return this.parseArgumentGroup(r); default: throw new n("Unknown group type as " + e, this.fetch()) } } consumeSpaces() { for (; " " === this.fetch().text;)this.consume() } parseStringGroup(e, t) { const r = this.gullet.scanArgument(t); if (null == r) return null; let n, o = ""; for (; "EOF" !== (n = this.fetch()).text;)o += n.text, this.consume(); return this.consume(), r.text = o, r } parseRegexGroup(e, t) { const r = this.fetch(); let o, s = r, i = ""; for (; "EOF" !== (o = this.fetch()).text && e.test(i + o.text);)s = o, i += s.text, this.consume(); if ("" === i) throw new n("Invalid " + t + ": '" + r.text + "'", r); return r.range(s, i) } parseColorGroup(e) { const t = this.parseStringGroup("color", e); if (null == t) return null; const r = /^(#[a-f0-9]{3}|#?[a-f0-9]{6}|[a-z]+)$/i.exec(t.text); if (!r) throw new n("Invalid color: '" + t.text + "'", t); let o = r[0]; return /^[0-9a-f]{6}$/i.test(o) && (o = "#" + o), { type: "color-token", mode: this.mode, color: o } } parseSizeGroup(e) { let t, r = !1; if (this.gullet.consumeSpaces(), t = e || "{" === this.gullet.future().text ? this.parseStringGroup("size", e) : this.parseRegexGroup(/^[-+]? *(?:$|\d+|\d+\.\d*|\.\d*) *[a-z]{0,2} *$/, "size"), !t) return null; e || 0 !== t.text.length || (t.text = "0pt", r = !0); const o = /([-+]?) *(\d+(?:\.\d*)?|\.\d+) *([a-z]{2})/.exec(t.text); if (!o) throw new n("Invalid size: '" + t.text + "'", t); const s = { number: +(o[1] + o[2]), unit: o[3] }; if (!V(s)) throw new n("Invalid unit: '" + s.unit + "'", t); return { type: "size", mode: this.mode, value: s, isBlank: r } } parseUrlGroup(e) { this.gullet.lexer.setCatcode("%", 13), this.gullet.lexer.setCatcode("~", 12); const t = this.parseStringGroup("url", e); if (this.gullet.lexer.setCatcode("%", 14), this.gullet.lexer.setCatcode("~", 13), null == t) return null; const r = t.text.replace(/\\([#$%&~_^{}])/g, "$1"); return { type: "url", mode: this.mode, url: r } } parseArgumentGroup(e, t) { const r = this.gullet.scanArgument(e); if (null == r) return null; const n = this.mode; t && this.switchMode(t), this.gullet.beginGroup(); const o = this.parseExpression(!1, "EOF"); this.expect("EOF"), this.gullet.endGroup(); const s = { type: "ordgroup", mode: this.mode, loc: r.loc, body: o }; return t && this.switchMode(n), s } parseGroup(e, t) { const r = this.fetch(), o = r.text; let s; if ("{" === o || "\\begingroup" === o) { this.consume(); const e = "{" === o ? "}" : "\\endgroup"; this.gullet.beginGroup(); const t = this.parseExpression(!1, e), n = this.fetch(); this.expect(e), this.gullet.endGroup(), s = { type: "ordgroup", mode: this.mode, loc: Cr.range(r, n), body: t, semisimple: "\\begingroup" === o || void 0 } } else if (s = this.parseFunction(t, e) || this.parseSymbol(), null == s && "\\" === o[0] && !Rn.hasOwnProperty(o)) { if (this.settings.throwOnError) throw new n("Undefined control sequence: " + o, r); s = this.formatUnsupportedCmd(o), this.consume() } return s } formLigatures(e) { let t = e.length - 1; for (let r = 0; r < t; ++r) { const n = e[r], o = n.text; "-" === o && "-" === e[r + 1].text && (r + 1 < t && "-" === e[r + 2].text ? (e.splice(r, 3, { type: "textord", mode: "text", loc: Cr.range(n, e[r + 2]), text: "---" }), t -= 2) : (e.splice(r, 2, { type: "textord", mode: "text", loc: Cr.range(n, e[r + 1]), text: "--" }), t -= 1)), "'" !== o && "`" !== o || e[r + 1].text !== o || (e.splice(r, 2, { type: "textord", mode: "text", loc: Cr.range(n, e[r + 1]), text: o + o }), t -= 1) } } parseSymbol() { const e = this.fetch(); let t = e.text; if (/^\\verb[^a-zA-Z]/.test(t)) { this.consume(); let e = t.slice(5); const r = "*" === e.charAt(0); if (r && (e = e.slice(1)), e.length < 2 || e.charAt(0) !== e.slice(-1)) throw new n("\\verb assertion failed --\n please report what input caused this bug"); return e = e.slice(1, -1), { type: "verb", mode: "text", body: e, star: r } } Dn.hasOwnProperty(t[0]) && !oe[this.mode][t[0]] && (this.settings.strict && "math" === this.mode && this.settings.reportNonstrict("unicodeTextInMathMode", 'Accented Unicode text character "' + t[0] + '" used in math mode', e), t = Dn[t[0]] + t.slice(1)); const r = kn.exec(t); let o; if (r && (t = t.substring(0, r.index), "i" === t ? t = "\u0131" : "j" === t && (t = "\u0237")), oe[this.mode][t]) { this.settings.strict && "math" === this.mode && Ae.indexOf(t) >= 0 && this.settings.reportNonstrict("unicodeTextInMathMode", 'Latin-1/Unicode text character "' + t[0] + '" used in math mode', e); const r = oe[this.mode][t].group, n = Cr.range(e); let s; if (te.hasOwnProperty(r)) { const e = r; s = { type: "atom", mode: this.mode, family: e, loc: n, text: t } } else s = { type: r, mode: this.mode, loc: n, text: t }; o = s } else { if (!(t.charCodeAt(0) >= 128)) return null; this.settings.strict && (S(t.charCodeAt(0)) ? "math" === this.mode && this.settings.reportNonstrict("unicodeTextInMathMode", 'Unicode text character "' + t[0] + '" used in math mode', e) : this.settings.reportNonstrict("unknownSymbol", 'Unrecognized Unicode character "' + t[0] + '" (' + t.charCodeAt(0) + ")", e)), o = { type: "textord", mode: "text", loc: Cr.range(e), text: t } } if (this.consume(), r) for (let t = 0; t < r[0].length; t++) { const s = r[0][t]; if (!Ln[s]) throw new n("Unknown accent ' " + s + "'", e); const i = Ln[s][this.mode] || Ln[s].text; if (!i) throw new n("Accent " + s + " unsupported in " + this.mode + " mode", e); o = { type: "accent", mode: this.mode, loc: Cr.range(e), label: i, isStretchy: !1, isShifty: !0, base: o } } return o } } Vn.endOfExpression = ["}", "\\endgroup", "\\end", "\\right", "&"]; var Pn = function (e, t) { if (!("string" == typeof e || e instanceof String)) throw new TypeError("KaTeX can only parse string typed expression"); const r = new Vn(e, t); delete r.gullet.macros.current["\\df@tag"]; let o = r.parse(); if (delete r.gullet.macros.current["\\current@color"], delete r.gullet.macros.current["\\color"], r.gullet.macros.get("\\df@tag")) { if (!t.displayMode) throw new n("\\tag works only in display equations"); o = [{ type: "tag", mode: "text", body: o, tag: r.subparse([new Nr("\\df@tag")]) }] } return o }; let Fn = function (e, t, r) { t.textContent = ""; const n = Un(e, r).toNode(); t.appendChild(n) }; "undefined" != typeof document && "CSS1Compat" !== document.compatMode && ("undefined" != typeof console && console.warn("Warning: KaTeX doesn't work in quirks mode. Make sure your website has a suitable doctype."), Fn = function () { throw new n("KaTeX doesn't work in quirks mode.") }); const Gn = function (e, t, r) { if (r.throwOnError || !(e instanceof n)) throw e; const o = Ve.makeSpan(["katex-error"], [new Z(t)]); return o.setAttribute("title", e.toString()), o.setAttribute("style", "color:" + r.errorColor), o }, Un = function (e, t) { const r = new m(t); try { const t = Pn(e, r); return zt(t, e, r) } catch (t) { return Gn(t, e, r) } }; var Yn = { version: "0.16.11", render: Fn, renderToString: function (e, t) { return Un(e, t).toMarkup() }, ParseError: n, SETTINGS_SCHEMA: h, __parse: function (e, t) { const r = new m(t); return Pn(e, r) }, __renderToDomTree: Un, __renderToHTMLTree: function (e, t) { const r = new m(t); try { return function (e, t, r) { const n = mt(e, St(r)), o = Ve.makeSpan(["katex"], [n]); return Mt(o, r) }(Pn(e, r), 0, r) } catch (t) { return Gn(t, e, r) } }, __setFontMetrics: function (e, t) { T[e] = t }, __defineSymbol: se, __defineFunction: je, __defineMacro: Br, __domTree: { Span: W, Anchor: _, SymbolNode: Z, SvgNode: K, PathNode: J, LineNode: Q } }; return t = t.default }() })); +!function (e, t) { "object" == typeof exports && "object" == typeof module ? module.exports = t() : "function" == typeof define && define.amd ? define([], t) : "object" == typeof exports ? exports.katex = t() : e.katex = t() }("undefined" != typeof self ? self : this, (function () { return function () { "use strict"; var e = { d: function (t, r) { for (var n in r) e.o(r, n) && !e.o(t, n) && Object.defineProperty(t, n, { enumerable: !0, get: r[n] }) }, o: function (e, t) { return Object.prototype.hasOwnProperty.call(e, t) } }, t = {}; e.d(t, { default: function () { return Yn } }); class r { constructor(e, t) { this.name = void 0, this.position = void 0, this.length = void 0, this.rawMessage = void 0; let n, o, s = "KaTeX parse error: " + e; const i = t && t.loc; if (i && i.start <= i.end) { const e = i.lexer.input; n = i.start, o = i.end, n === e.length ? s += " at end of input: " : s += " at position " + (n + 1) + ": "; const t = e.slice(n, o).replace(/[^]/g, "$&\u0332"); let r, a; r = n > 15 ? "\u2026" + e.slice(n - 15, n) : e.slice(0, n), a = o + 15 < e.length ? e.slice(o, o + 15) + "\u2026" : e.slice(o), s += r + t + a } const a = new Error(s); return a.name = "ParseError", a.__proto__ = r.prototype, a.position = n, null != n && null != o && (a.length = o - n), a.rawMessage = e, a } } r.prototype.__proto__ = Error.prototype; var n = r; const o = /([A-Z])/g, s = { "&": "&", ">": ">", "<": "<", '"': """, "'": "'" }, i = /[&><"']/g; const a = function (e) { return "ordgroup" === e.type || "color" === e.type ? 1 === e.body.length ? a(e.body[0]) : e : "font" === e.type ? a(e.body) : e }; var l = { contains: function (e, t) { return -1 !== e.indexOf(t) }, deflt: function (e, t) { return void 0 === e ? t : e }, escape: function (e) { return String(e).replace(i, (e => s[e])) }, hyphenate: function (e) { return e.replace(o, "-$1").toLowerCase() }, getBaseElem: a, isCharacterBox: function (e) { const t = a(e); return "mathord" === t.type || "textord" === t.type || "atom" === t.type }, protocolFromUrl: function (e) { const t = /^[\x00-\x20]*([^\\/#?]*?)(:|�*58|�*3a|&colon)/i.exec(e); return t ? ":" !== t[2] ? null : /^[a-zA-Z][a-zA-Z0-9+\-.]*$/.test(t[1]) ? t[1].toLowerCase() : null : "_relative" } }; const h = { displayMode: { type: "boolean", description: "Render math in display mode, which puts the math in display style (so \\int and \\sum are large, for example), and centers the math on the page on its own line.", cli: "-d, --display-mode" }, output: { type: { enum: ["htmlAndMathml", "html", "mathml"] }, description: "Determines the markup language of the json.", cli: "-F, --format " }, leqno: { type: "boolean", description: "Render display math in leqno style (left-justified tags)." }, fleqn: { type: "boolean", description: "Render display math flush left." }, throwOnError: { type: "boolean", default: !0, cli: "-t, --no-throw-on-error", cliDescription: "Render errors (in the color given by --error-color) instead of throwing a ParseError exception when encountering an error." }, errorColor: { type: "string", default: "#cc0000", cli: "-c, --error-color ", cliDescription: "A color string given in the format 'rgb' or 'rrggbb' (no #). This option determines the color of errors rendered by the -t option.", cliProcessor: e => "#" + e }, macros: { type: "object", cli: "-m, --macro ", cliDescription: "Define custom macro of the form '\\foo:expansion' (use multiple -m arguments for multiple macros).", cliDefault: [], cliProcessor: (e, t) => (t.push(e), t) }, minRuleThickness: { type: "number", description: "Specifies a minimum thickness, in ems, for fraction lines, `\\sqrt` top lines, `{array}` vertical lines, `\\hline`, `\\hdashline`, `\\underline`, `\\overline`, and the borders of `\\fbox`, `\\boxed`, and `\\fcolorbox`.", processor: e => Math.max(0, e), cli: "--min-rule-thickness ", cliProcessor: parseFloat }, colorIsTextColor: { type: "boolean", description: "Makes \\color behave like LaTeX's 2-argument \\textcolor, instead of LaTeX's one-argument \\color mode change.", cli: "-b, --color-is-text-color" }, strict: { type: [{ enum: ["warn", "ignore", "error"] }, "boolean", "function"], description: "Turn on strict / LaTeX faithfulness mode, which throws an error if the input uses features that are not supported by LaTeX.", cli: "-S, --strict", cliDefault: !1 }, trust: { type: ["boolean", "function"], description: "Trust the input, enabling all HTML features such as \\url.", cli: "-T, --trust" }, maxSize: { type: "number", default: 1 / 0, description: "If non-zero, all user-specified sizes, e.g. in \\rule{500em}{500em}, will be capped to maxSize ems. Otherwise, elements and spaces can be arbitrarily large", processor: e => Math.max(0, e), cli: "-s, --max-size ", cliProcessor: parseInt }, maxExpand: { type: "number", default: 1e3, description: "Limit the number of macro expansions to the specified number, to prevent e.g. infinite macro loops. If set to Infinity, the macro expander will try to fully expand as in LaTeX.", processor: e => Math.max(0, e), cli: "-e, --max-expand ", cliProcessor: e => "Infinity" === e ? 1 / 0 : parseInt(e) }, globalGroup: { type: "boolean", cli: !1 } }; function c(e) { if (e.default) return e.default; const t = e.type, r = Array.isArray(t) ? t[0] : t; if ("string" != typeof r) return r.enum[0]; switch (r) { case "boolean": return !1; case "string": return ""; case "number": return 0; case "object": return {} } } class m { constructor(e) { this.displayMode = void 0, this.output = void 0, this.leqno = void 0, this.fleqn = void 0, this.throwOnError = void 0, this.errorColor = void 0, this.macros = void 0, this.minRuleThickness = void 0, this.colorIsTextColor = void 0, this.strict = void 0, this.trust = void 0, this.maxSize = void 0, this.maxExpand = void 0, this.globalGroup = void 0, e = e || {}; for (const t in h) if (h.hasOwnProperty(t)) { const r = h[t]; this[t] = void 0 !== e[t] ? r.processor ? r.processor(e[t]) : e[t] : c(r) } } reportNonstrict(e, t, r) { let o = this.strict; if ("function" == typeof o && (o = o(e, t, r)), o && "ignore" !== o) { if (!0 === o || "error" === o) throw new n("LaTeX-incompatible input and strict mode is set to 'error': " + t + " [" + e + "]", r); "warn" === o ? "undefined" != typeof console && console.warn("LaTeX-incompatible input and strict mode is set to 'warn': " + t + " [" + e + "]") : "undefined" != typeof console && console.warn("LaTeX-incompatible input and strict mode is set to unrecognized '" + o + "': " + t + " [" + e + "]") } } useStrictBehavior(e, t, r) { let n = this.strict; if ("function" == typeof n) try { n = n(e, t, r) } catch (e) { n = "error" } return !(!n || "ignore" === n) && (!0 === n || "error" === n || ("warn" === n ? ("undefined" != typeof console && console.warn("LaTeX-incompatible input and strict mode is set to 'warn': " + t + " [" + e + "]"), !1) : ("undefined" != typeof console && console.warn("LaTeX-incompatible input and strict mode is set to unrecognized '" + n + "': " + t + " [" + e + "]"), !1))) } isTrusted(e) { if (e.url && !e.protocol) { const t = l.protocolFromUrl(e.url); if (null == t) return !1; e.protocol = t } const t = "function" == typeof this.trust ? this.trust(e) : this.trust; return Boolean(t) } } class p { constructor(e, t, r) { this.id = void 0, this.size = void 0, this.cramped = void 0, this.id = e, this.size = t, this.cramped = r } sup() { return u[d[this.id]] } sub() { return u[g[this.id]] } fracNum() { return u[f[this.id]] } fracDen() { return u[b[this.id]] } cramp() { return u[y[this.id]] } text() { return u[x[this.id]] } isTight() { return this.size >= 2 } } const u = [new p(0, 0, !1), new p(1, 0, !0), new p(2, 1, !1), new p(3, 1, !0), new p(4, 2, !1), new p(5, 2, !0), new p(6, 3, !1), new p(7, 3, !0)], d = [4, 5, 4, 5, 6, 7, 6, 7], g = [5, 5, 5, 5, 7, 7, 7, 7], f = [2, 3, 4, 5, 6, 7, 6, 7], b = [3, 3, 5, 5, 7, 7, 7, 7], y = [1, 1, 3, 3, 5, 5, 7, 7], x = [0, 1, 2, 3, 2, 3, 2, 3]; var w = { DISPLAY: u[0], TEXT: u[2], SCRIPT: u[4], SCRIPTSCRIPT: u[6] }; const v = [{ name: "latin", blocks: [[256, 591], [768, 879]] }, { name: "cyrillic", blocks: [[1024, 1279]] }, { name: "armenian", blocks: [[1328, 1423]] }, { name: "brahmic", blocks: [[2304, 4255]] }, { name: "georgian", blocks: [[4256, 4351]] }, { name: "cjk", blocks: [[12288, 12543], [19968, 40879], [65280, 65376]] }, { name: "hangul", blocks: [[44032, 55215]] }]; const k = []; function S(e) { for (let t = 0; t < k.length; t += 2)if (e >= k[t] && e <= k[t + 1]) return !0; return !1 } v.forEach((e => e.blocks.forEach((e => k.push(...e))))); const M = 80, z = { doubleleftarrow: "M262 157\nl10-10c34-36 62.7-77 86-123 3.3-8 5-13.3 5-16 0-5.3-6.7-8-20-8-7.3\n 0-12.2.5-14.5 1.5-2.3 1-4.8 4.5-7.5 10.5-49.3 97.3-121.7 169.3-217 216-28\n 14-57.3 25-88 33-6.7 2-11 3.8-13 5.5-2 1.7-3 4.2-3 7.5s1 5.8 3 7.5\nc2 1.7 6.3 3.5 13 5.5 68 17.3 128.2 47.8 180.5 91.5 52.3 43.7 93.8 96.2 124.5\n 157.5 9.3 8 15.3 12.3 18 13h6c12-.7 18-4 18-10 0-2-1.7-7-5-15-23.3-46-52-87\n-86-123l-10-10h399738v-40H218c328 0 0 0 0 0l-10-8c-26.7-20-65.7-43-117-69 2.7\n-2 6-3.7 10-5 36.7-16 72.3-37.3 107-64l10-8h399782v-40z\nm8 0v40h399730v-40zm0 194v40h399730v-40z", doublerightarrow: "M399738 392l\n-10 10c-34 36-62.7 77-86 123-3.3 8-5 13.3-5 16 0 5.3 6.7 8 20 8 7.3 0 12.2-.5\n 14.5-1.5 2.3-1 4.8-4.5 7.5-10.5 49.3-97.3 121.7-169.3 217-216 28-14 57.3-25 88\n-33 6.7-2 11-3.8 13-5.5 2-1.7 3-4.2 3-7.5s-1-5.8-3-7.5c-2-1.7-6.3-3.5-13-5.5-68\n-17.3-128.2-47.8-180.5-91.5-52.3-43.7-93.8-96.2-124.5-157.5-9.3-8-15.3-12.3-18\n-13h-6c-12 .7-18 4-18 10 0 2 1.7 7 5 15 23.3 46 52 87 86 123l10 10H0v40h399782\nc-328 0 0 0 0 0l10 8c26.7 20 65.7 43 117 69-2.7 2-6 3.7-10 5-36.7 16-72.3 37.3\n-107 64l-10 8H0v40zM0 157v40h399730v-40zm0 194v40h399730v-40z", leftarrow: "M400000 241H110l3-3c68.7-52.7 113.7-120\n 135-202 4-14.7 6-23 6-25 0-7.3-7-11-21-11-8 0-13.2.8-15.5 2.5-2.3 1.7-4.2 5.8\n-5.5 12.5-1.3 4.7-2.7 10.3-4 17-12 48.7-34.8 92-68.5 130S65.3 228.3 18 247\nc-10 4-16 7.7-18 11 0 8.7 6 14.3 18 17 47.3 18.7 87.8 47 121.5 85S196 441.3 208\n 490c.7 2 1.3 5 2 9s1.2 6.7 1.5 8c.3 1.3 1 3.3 2 6s2.2 4.5 3.5 5.5c1.3 1 3.3\n 1.8 6 2.5s6 1 10 1c14 0 21-3.7 21-11 0-2-2-10.3-6-25-20-79.3-65-146.7-135-202\n l-3-3h399890zM100 241v40h399900v-40z", leftbrace: "M6 548l-6-6v-35l6-11c56-104 135.3-181.3 238-232 57.3-28.7 117\n-45 179-50h399577v120H403c-43.3 7-81 15-113 26-100.7 33-179.7 91-237 174-2.7\n 5-6 9-10 13-.7 1-7.3 1-20 1H6z", leftbraceunder: "M0 6l6-6h17c12.688 0 19.313.3 20 1 4 4 7.313 8.3 10 13\n 35.313 51.3 80.813 93.8 136.5 127.5 55.688 33.7 117.188 55.8 184.5 66.5.688\n 0 2 .3 4 1 18.688 2.7 76 4.3 172 5h399450v120H429l-6-1c-124.688-8-235-61.7\n-331-161C60.687 138.7 32.312 99.3 7 54L0 41V6z", leftgroup: "M400000 80\nH435C64 80 168.3 229.4 21 260c-5.9 1.2-18 0-18 0-2 0-3-1-3-3v-38C76 61 257 0\n 435 0h399565z", leftgroupunder: "M400000 262\nH435C64 262 168.3 112.6 21 82c-5.9-1.2-18 0-18 0-2 0-3 1-3 3v38c76 158 257 219\n 435 219h399565z", leftharpoon: "M0 267c.7 5.3 3 10 7 14h399993v-40H93c3.3\n-3.3 10.2-9.5 20.5-18.5s17.8-15.8 22.5-20.5c50.7-52 88-110.3 112-175 4-11.3 5\n-18.3 3-21-1.3-4-7.3-6-18-6-8 0-13 .7-15 2s-4.7 6.7-8 16c-42 98.7-107.3 174.7\n-196 228-6.7 4.7-10.7 8-12 10-1.3 2-2 5.7-2 11zm100-26v40h399900v-40z", leftharpoonplus: "M0 267c.7 5.3 3 10 7 14h399993v-40H93c3.3-3.3 10.2-9.5\n 20.5-18.5s17.8-15.8 22.5-20.5c50.7-52 88-110.3 112-175 4-11.3 5-18.3 3-21-1.3\n-4-7.3-6-18-6-8 0-13 .7-15 2s-4.7 6.7-8 16c-42 98.7-107.3 174.7-196 228-6.7 4.7\n-10.7 8-12 10-1.3 2-2 5.7-2 11zm100-26v40h399900v-40zM0 435v40h400000v-40z\nm0 0v40h400000v-40z", leftharpoondown: "M7 241c-4 4-6.333 8.667-7 14 0 5.333.667 9 2 11s5.333\n 5.333 12 10c90.667 54 156 130 196 228 3.333 10.667 6.333 16.333 9 17 2 .667 5\n 1 9 1h5c10.667 0 16.667-2 18-6 2-2.667 1-9.667-3-21-32-87.333-82.667-157.667\n-152-211l-3-3h399907v-40zM93 281 H400000 v-40L7 241z", leftharpoondownplus: "M7 435c-4 4-6.3 8.7-7 14 0 5.3.7 9 2 11s5.3 5.3 12\n 10c90.7 54 156 130 196 228 3.3 10.7 6.3 16.3 9 17 2 .7 5 1 9 1h5c10.7 0 16.7\n-2 18-6 2-2.7 1-9.7-3-21-32-87.3-82.7-157.7-152-211l-3-3h399907v-40H7zm93 0\nv40h399900v-40zM0 241v40h399900v-40zm0 0v40h399900v-40z", lefthook: "M400000 281 H103s-33-11.2-61-33.5S0 197.3 0 164s14.2-61.2 42.5\n-83.5C70.8 58.2 104 47 142 47 c16.7 0 25 6.7 25 20 0 12-8.7 18.7-26 20-40 3.3\n-68.7 15.7-86 37-10 12-15 25.3-15 40 0 22.7 9.8 40.7 29.5 54 19.7 13.3 43.5 21\n 71.5 23h399859zM103 281v-40h399897v40z", leftlinesegment: "M40 281 V428 H0 V94 H40 V241 H400000 v40z\nM40 281 V428 H0 V94 H40 V241 H400000 v40z", leftmapsto: "M40 281 V448H0V74H40V241H400000v40z\nM40 281 V448H0V74H40V241H400000v40z", leftToFrom: "M0 147h400000v40H0zm0 214c68 40 115.7 95.7 143 167h22c15.3 0 23\n-.3 23-1 0-1.3-5.3-13.7-16-37-18-35.3-41.3-69-70-101l-7-8h399905v-40H95l7-8\nc28.7-32 52-65.7 70-101 10.7-23.3 16-35.7 16-37 0-.7-7.7-1-23-1h-22C115.7 265.3\n 68 321 0 361zm0-174v-40h399900v40zm100 154v40h399900v-40z", longequal: "M0 50 h400000 v40H0z m0 194h40000v40H0z\nM0 50 h400000 v40H0z m0 194h40000v40H0z", midbrace: "M200428 334\nc-100.7-8.3-195.3-44-280-108-55.3-42-101.7-93-139-153l-9-14c-2.7 4-5.7 8.7-9 14\n-53.3 86.7-123.7 153-211 199-66.7 36-137.3 56.3-212 62H0V214h199568c178.3-11.7\n 311.7-78.3 403-201 6-8 9.7-12 11-12 .7-.7 6.7-1 18-1s17.3.3 18 1c1.3 0 5 4 11\n 12 44.7 59.3 101.3 106.3 170 141s145.3 54.3 229 60h199572v120z", midbraceunder: "M199572 214\nc100.7 8.3 195.3 44 280 108 55.3 42 101.7 93 139 153l9 14c2.7-4 5.7-8.7 9-14\n 53.3-86.7 123.7-153 211-199 66.7-36 137.3-56.3 212-62h199568v120H200432c-178.3\n 11.7-311.7 78.3-403 201-6 8-9.7 12-11 12-.7.7-6.7 1-18 1s-17.3-.3-18-1c-1.3 0\n-5-4-11-12-44.7-59.3-101.3-106.3-170-141s-145.3-54.3-229-60H0V214z", oiintSize1: "M512.6 71.6c272.6 0 320.3 106.8 320.3 178.2 0 70.8-47.7 177.6\n-320.3 177.6S193.1 320.6 193.1 249.8c0-71.4 46.9-178.2 319.5-178.2z\nm368.1 178.2c0-86.4-60.9-215.4-368.1-215.4-306.4 0-367.3 129-367.3 215.4 0 85.8\n60.9 214.8 367.3 214.8 307.2 0 368.1-129 368.1-214.8z", oiintSize2: "M757.8 100.1c384.7 0 451.1 137.6 451.1 230 0 91.3-66.4 228.8\n-451.1 228.8-386.3 0-452.7-137.5-452.7-228.8 0-92.4 66.4-230 452.7-230z\nm502.4 230c0-111.2-82.4-277.2-502.4-277.2s-504 166-504 277.2\nc0 110 84 276 504 276s502.4-166 502.4-276z", oiiintSize1: "M681.4 71.6c408.9 0 480.5 106.8 480.5 178.2 0 70.8-71.6 177.6\n-480.5 177.6S202.1 320.6 202.1 249.8c0-71.4 70.5-178.2 479.3-178.2z\nm525.8 178.2c0-86.4-86.8-215.4-525.7-215.4-437.9 0-524.7 129-524.7 215.4 0\n85.8 86.8 214.8 524.7 214.8 438.9 0 525.7-129 525.7-214.8z", oiiintSize2: "M1021.2 53c603.6 0 707.8 165.8 707.8 277.2 0 110-104.2 275.8\n-707.8 275.8-606 0-710.2-165.8-710.2-275.8C311 218.8 415.2 53 1021.2 53z\nm770.4 277.1c0-131.2-126.4-327.6-770.5-327.6S248.4 198.9 248.4 330.1\nc0 130 128.8 326.4 772.7 326.4s770.5-196.4 770.5-326.4z", rightarrow: "M0 241v40h399891c-47.3 35.3-84 78-110 128\n-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20\n 11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7\n 39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85\n-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5\n-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67\n 151.7 139 205zm0 0v40h399900v-40z", rightbrace: "M400000 542l\n-6 6h-17c-12.7 0-19.3-.3-20-1-4-4-7.3-8.3-10-13-35.3-51.3-80.8-93.8-136.5-127.5\ns-117.2-55.8-184.5-66.5c-.7 0-2-.3-4-1-18.7-2.7-76-4.3-172-5H0V214h399571l6 1\nc124.7 8 235 61.7 331 161 31.3 33.3 59.7 72.7 85 118l7 13v35z", rightbraceunder: "M399994 0l6 6v35l-6 11c-56 104-135.3 181.3-238 232-57.3\n 28.7-117 45-179 50H-300V214h399897c43.3-7 81-15 113-26 100.7-33 179.7-91 237\n-174 2.7-5 6-9 10-13 .7-1 7.3-1 20-1h17z", rightgroup: "M0 80h399565c371 0 266.7 149.4 414 180 5.9 1.2 18 0 18 0 2 0\n 3-1 3-3v-38c-76-158-257-219-435-219H0z", rightgroupunder: "M0 262h399565c371 0 266.7-149.4 414-180 5.9-1.2 18 0 18\n 0 2 0 3 1 3 3v38c-76 158-257 219-435 219H0z", rightharpoon: "M0 241v40h399993c4.7-4.7 7-9.3 7-14 0-9.3\n-3.7-15.3-11-18-92.7-56.7-159-133.7-199-231-3.3-9.3-6-14.7-8-16-2-1.3-7-2-15-2\n-10.7 0-16.7 2-18 6-2 2.7-1 9.7 3 21 15.3 42 36.7 81.8 64 119.5 27.3 37.7 58\n 69.2 92 94.5zm0 0v40h399900v-40z", rightharpoonplus: "M0 241v40h399993c4.7-4.7 7-9.3 7-14 0-9.3-3.7-15.3-11\n-18-92.7-56.7-159-133.7-199-231-3.3-9.3-6-14.7-8-16-2-1.3-7-2-15-2-10.7 0-16.7\n 2-18 6-2 2.7-1 9.7 3 21 15.3 42 36.7 81.8 64 119.5 27.3 37.7 58 69.2 92 94.5z\nm0 0v40h399900v-40z m100 194v40h399900v-40zm0 0v40h399900v-40z", rightharpoondown: "M399747 511c0 7.3 6.7 11 20 11 8 0 13-.8 15-2.5s4.7-6.8\n 8-15.5c40-94 99.3-166.3 178-217 13.3-8 20.3-12.3 21-13 5.3-3.3 8.5-5.8 9.5\n-7.5 1-1.7 1.5-5.2 1.5-10.5s-2.3-10.3-7-15H0v40h399908c-34 25.3-64.7 57-92 95\n-27.3 38-48.7 77.7-64 119-3.3 8.7-5 14-5 16zM0 241v40h399900v-40z", rightharpoondownplus: "M399747 705c0 7.3 6.7 11 20 11 8 0 13-.8\n 15-2.5s4.7-6.8 8-15.5c40-94 99.3-166.3 178-217 13.3-8 20.3-12.3 21-13 5.3-3.3\n 8.5-5.8 9.5-7.5 1-1.7 1.5-5.2 1.5-10.5s-2.3-10.3-7-15H0v40h399908c-34 25.3\n-64.7 57-92 95-27.3 38-48.7 77.7-64 119-3.3 8.7-5 14-5 16zM0 435v40h399900v-40z\nm0-194v40h400000v-40zm0 0v40h400000v-40z", righthook: "M399859 241c-764 0 0 0 0 0 40-3.3 68.7-15.7 86-37 10-12 15-25.3\n 15-40 0-22.7-9.8-40.7-29.5-54-19.7-13.3-43.5-21-71.5-23-17.3-1.3-26-8-26-20 0\n-13.3 8.7-20 26-20 38 0 71 11.2 99 33.5 0 0 7 5.6 21 16.7 14 11.2 21 33.5 21\n 66.8s-14 61.2-42 83.5c-28 22.3-61 33.5-99 33.5L0 241z M0 281v-40h399859v40z", rightlinesegment: "M399960 241 V94 h40 V428 h-40 V281 H0 v-40z\nM399960 241 V94 h40 V428 h-40 V281 H0 v-40z", rightToFrom: "M400000 167c-70.7-42-118-97.7-142-167h-23c-15.3 0-23 .3-23\n 1 0 1.3 5.3 13.7 16 37 18 35.3 41.3 69 70 101l7 8H0v40h399905l-7 8c-28.7 32\n-52 65.7-70 101-10.7 23.3-16 35.7-16 37 0 .7 7.7 1 23 1h23c24-69.3 71.3-125 142\n-167z M100 147v40h399900v-40zM0 341v40h399900v-40z", twoheadleftarrow: "M0 167c68 40\n 115.7 95.7 143 167h22c15.3 0 23-.3 23-1 0-1.3-5.3-13.7-16-37-18-35.3-41.3-69\n-70-101l-7-8h125l9 7c50.7 39.3 85 86 103 140h46c0-4.7-6.3-18.7-19-42-18-35.3\n-40-67.3-66-96l-9-9h399716v-40H284l9-9c26-28.7 48-60.7 66-96 12.7-23.333 19\n-37.333 19-42h-46c-18 54-52.3 100.7-103 140l-9 7H95l7-8c28.7-32 52-65.7 70-101\n 10.7-23.333 16-35.7 16-37 0-.7-7.7-1-23-1h-22C115.7 71.3 68 127 0 167z", twoheadrightarrow: "M400000 167\nc-68-40-115.7-95.7-143-167h-22c-15.3 0-23 .3-23 1 0 1.3 5.3 13.7 16 37 18 35.3\n 41.3 69 70 101l7 8h-125l-9-7c-50.7-39.3-85-86-103-140h-46c0 4.7 6.3 18.7 19 42\n 18 35.3 40 67.3 66 96l9 9H0v40h399716l-9 9c-26 28.7-48 60.7-66 96-12.7 23.333\n-19 37.333-19 42h46c18-54 52.3-100.7 103-140l9-7h125l-7 8c-28.7 32-52 65.7-70\n 101-10.7 23.333-16 35.7-16 37 0 .7 7.7 1 23 1h22c27.3-71.3 75-127 143-167z", tilde1: "M200 55.538c-77 0-168 73.953-177 73.953-3 0-7\n-2.175-9-5.437L2 97c-1-2-2-4-2-6 0-4 2-7 5-9l20-12C116 12 171 0 207 0c86 0\n 114 68 191 68 78 0 168-68 177-68 4 0 7 2 9 5l12 19c1 2.175 2 4.35 2 6.525 0\n 4.35-2 7.613-5 9.788l-19 13.05c-92 63.077-116.937 75.308-183 76.128\n-68.267.847-113-73.952-191-73.952z", tilde2: "M344 55.266c-142 0-300.638 81.316-311.5 86.418\n-8.01 3.762-22.5 10.91-23.5 5.562L1 120c-1-2-1-3-1-4 0-5 3-9 8-10l18.4-9C160.9\n 31.9 283 0 358 0c148 0 188 122 331 122s314-97 326-97c4 0 8 2 10 7l7 21.114\nc1 2.14 1 3.21 1 4.28 0 5.347-3 9.626-7 10.696l-22.3 12.622C852.6 158.372 751\n 181.476 676 181.476c-149 0-189-126.21-332-126.21z", tilde3: "M786 59C457 59 32 175.242 13 175.242c-6 0-10-3.457\n-11-10.37L.15 138c-1-7 3-12 10-13l19.2-6.4C378.4 40.7 634.3 0 804.3 0c337 0\n 411.8 157 746.8 157 328 0 754-112 773-112 5 0 10 3 11 9l1 14.075c1 8.066-.697\n 16.595-6.697 17.492l-21.052 7.31c-367.9 98.146-609.15 122.696-778.15 122.696\n -338 0-409-156.573-744-156.573z", tilde4: "M786 58C457 58 32 177.487 13 177.487c-6 0-10-3.345\n-11-10.035L.15 143c-1-7 3-12 10-13l22-6.7C381.2 35 637.15 0 807.15 0c337 0 409\n 177 744 177 328 0 754-127 773-127 5 0 10 3 11 9l1 14.794c1 7.805-3 13.38-9\n 14.495l-20.7 5.574c-366.85 99.79-607.3 139.372-776.3 139.372-338 0-409\n -175.236-744-175.236z", vec: "M377 20c0-5.333 1.833-10 5.5-14S391 0 397 0c4.667 0 8.667 1.667 12 5\n3.333 2.667 6.667 9 10 19 6.667 24.667 20.333 43.667 41 57 7.333 4.667 11\n10.667 11 18 0 6-1 10-3 12s-6.667 5-14 9c-28.667 14.667-53.667 35.667-75 63\n-1.333 1.333-3.167 3.5-5.5 6.5s-4 4.833-5 5.5c-1 .667-2.5 1.333-4.5 2s-4.333 1\n-7 1c-4.667 0-9.167-1.833-13.5-5.5S337 184 337 178c0-12.667 15.667-32.333 47-59\nH213l-171-1c-8.667-6-13-12.333-13-19 0-4.667 4.333-11.333 13-20h359\nc-16-25.333-24-45-24-59z", widehat1: "M529 0h5l519 115c5 1 9 5 9 10 0 1-1 2-1 3l-4 22\nc-1 5-5 9-11 9h-2L532 67 19 159h-2c-5 0-9-4-11-9l-5-22c-1-6 2-12 8-13z", widehat2: "M1181 0h2l1171 176c6 0 10 5 10 11l-2 23c-1 6-5 10\n-11 10h-1L1182 67 15 220h-1c-6 0-10-4-11-10l-2-23c-1-6 4-11 10-11z", widehat3: "M1181 0h2l1171 236c6 0 10 5 10 11l-2 23c-1 6-5 10\n-11 10h-1L1182 67 15 280h-1c-6 0-10-4-11-10l-2-23c-1-6 4-11 10-11z", widehat4: "M1181 0h2l1171 296c6 0 10 5 10 11l-2 23c-1 6-5 10\n-11 10h-1L1182 67 15 340h-1c-6 0-10-4-11-10l-2-23c-1-6 4-11 10-11z", widecheck1: "M529,159h5l519,-115c5,-1,9,-5,9,-10c0,-1,-1,-2,-1,-3l-4,-22c-1,\n-5,-5,-9,-11,-9h-2l-512,92l-513,-92h-2c-5,0,-9,4,-11,9l-5,22c-1,6,2,12,8,13z", widecheck2: "M1181,220h2l1171,-176c6,0,10,-5,10,-11l-2,-23c-1,-6,-5,-10,\n-11,-10h-1l-1168,153l-1167,-153h-1c-6,0,-10,4,-11,10l-2,23c-1,6,4,11,10,11z", widecheck3: "M1181,280h2l1171,-236c6,0,10,-5,10,-11l-2,-23c-1,-6,-5,-10,\n-11,-10h-1l-1168,213l-1167,-213h-1c-6,0,-10,4,-11,10l-2,23c-1,6,4,11,10,11z", widecheck4: "M1181,340h2l1171,-296c6,0,10,-5,10,-11l-2,-23c-1,-6,-5,-10,\n-11,-10h-1l-1168,273l-1167,-273h-1c-6,0,-10,4,-11,10l-2,23c-1,6,4,11,10,11z", baraboveleftarrow: "M400000 620h-399890l3 -3c68.7 -52.7 113.7 -120 135 -202\nc4 -14.7 6 -23 6 -25c0 -7.3 -7 -11 -21 -11c-8 0 -13.2 0.8 -15.5 2.5\nc-2.3 1.7 -4.2 5.8 -5.5 12.5c-1.3 4.7 -2.7 10.3 -4 17c-12 48.7 -34.8 92 -68.5 130\ns-74.2 66.3 -121.5 85c-10 4 -16 7.7 -18 11c0 8.7 6 14.3 18 17c47.3 18.7 87.8 47\n121.5 85s56.5 81.3 68.5 130c0.7 2 1.3 5 2 9s1.2 6.7 1.5 8c0.3 1.3 1 3.3 2 6\ns2.2 4.5 3.5 5.5c1.3 1 3.3 1.8 6 2.5s6 1 10 1c14 0 21 -3.7 21 -11\nc0 -2 -2 -10.3 -6 -25c-20 -79.3 -65 -146.7 -135 -202l-3 -3h399890z\nM100 620v40h399900v-40z M0 241v40h399900v-40zM0 241v40h399900v-40z", rightarrowabovebar: "M0 241v40h399891c-47.3 35.3-84 78-110 128-16.7 32\n-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20 11 8 0\n13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7 39\n-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85-40.5\n-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5\n-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67\n151.7 139 205zm96 379h399894v40H0zm0 0h399904v40H0z", baraboveshortleftharpoon: "M507,435c-4,4,-6.3,8.7,-7,14c0,5.3,0.7,9,2,11\nc1.3,2,5.3,5.3,12,10c90.7,54,156,130,196,228c3.3,10.7,6.3,16.3,9,17\nc2,0.7,5,1,9,1c0,0,5,0,5,0c10.7,0,16.7,-2,18,-6c2,-2.7,1,-9.7,-3,-21\nc-32,-87.3,-82.7,-157.7,-152,-211c0,0,-3,-3,-3,-3l399351,0l0,-40\nc-398570,0,-399437,0,-399437,0z M593 435 v40 H399500 v-40z\nM0 281 v-40 H399908 v40z M0 281 v-40 H399908 v40z", rightharpoonaboveshortbar: "M0,241 l0,40c399126,0,399993,0,399993,0\nc4.7,-4.7,7,-9.3,7,-14c0,-9.3,-3.7,-15.3,-11,-18c-92.7,-56.7,-159,-133.7,-199,\n-231c-3.3,-9.3,-6,-14.7,-8,-16c-2,-1.3,-7,-2,-15,-2c-10.7,0,-16.7,2,-18,6\nc-2,2.7,-1,9.7,3,21c15.3,42,36.7,81.8,64,119.5c27.3,37.7,58,69.2,92,94.5z\nM0 241 v40 H399908 v-40z M0 475 v-40 H399500 v40z M0 475 v-40 H399500 v40z", shortbaraboveleftharpoon: "M7,435c-4,4,-6.3,8.7,-7,14c0,5.3,0.7,9,2,11\nc1.3,2,5.3,5.3,12,10c90.7,54,156,130,196,228c3.3,10.7,6.3,16.3,9,17c2,0.7,5,1,9,\n1c0,0,5,0,5,0c10.7,0,16.7,-2,18,-6c2,-2.7,1,-9.7,-3,-21c-32,-87.3,-82.7,-157.7,\n-152,-211c0,0,-3,-3,-3,-3l399907,0l0,-40c-399126,0,-399993,0,-399993,0z\nM93 435 v40 H400000 v-40z M500 241 v40 H400000 v-40z M500 241 v40 H400000 v-40z", shortrightharpoonabovebar: "M53,241l0,40c398570,0,399437,0,399437,0\nc4.7,-4.7,7,-9.3,7,-14c0,-9.3,-3.7,-15.3,-11,-18c-92.7,-56.7,-159,-133.7,-199,\n-231c-3.3,-9.3,-6,-14.7,-8,-16c-2,-1.3,-7,-2,-15,-2c-10.7,0,-16.7,2,-18,6\nc-2,2.7,-1,9.7,3,21c15.3,42,36.7,81.8,64,119.5c27.3,37.7,58,69.2,92,94.5z\nM500 241 v40 H399408 v-40z M500 435 v40 H400000 v-40z" }; class A { constructor(e) { this.children = void 0, this.classes = void 0, this.height = void 0, this.depth = void 0, this.maxFontSize = void 0, this.style = void 0, this.children = e, this.classes = [], this.height = 0, this.depth = 0, this.maxFontSize = 0, this.style = {} } hasClass(e) { return l.contains(this.classes, e) } toNode() { const e = document.createDocumentFragment(); for (let t = 0; t < this.children.length; t++)e.appendChild(this.children[t].toNode()); return e } toMarkup() { let e = ""; for (let t = 0; t < this.children.length; t++)e += this.children[t].toMarkup(); return e } toText() { return this.children.map((e => e.toText())).join("") } } var T = { "AMS-Regular": { 32: [0, 0, 0, 0, .25], 65: [0, .68889, 0, 0, .72222], 66: [0, .68889, 0, 0, .66667], 67: [0, .68889, 0, 0, .72222], 68: [0, .68889, 0, 0, .72222], 69: [0, .68889, 0, 0, .66667], 70: [0, .68889, 0, 0, .61111], 71: [0, .68889, 0, 0, .77778], 72: [0, .68889, 0, 0, .77778], 73: [0, .68889, 0, 0, .38889], 74: [.16667, .68889, 0, 0, .5], 75: [0, .68889, 0, 0, .77778], 76: [0, .68889, 0, 0, .66667], 77: [0, .68889, 0, 0, .94445], 78: [0, .68889, 0, 0, .72222], 79: [.16667, .68889, 0, 0, .77778], 80: [0, .68889, 0, 0, .61111], 81: [.16667, .68889, 0, 0, .77778], 82: [0, .68889, 0, 0, .72222], 83: [0, .68889, 0, 0, .55556], 84: [0, .68889, 0, 0, .66667], 85: [0, .68889, 0, 0, .72222], 86: [0, .68889, 0, 0, .72222], 87: [0, .68889, 0, 0, 1], 88: [0, .68889, 0, 0, .72222], 89: [0, .68889, 0, 0, .72222], 90: [0, .68889, 0, 0, .66667], 107: [0, .68889, 0, 0, .55556], 160: [0, 0, 0, 0, .25], 165: [0, .675, .025, 0, .75], 174: [.15559, .69224, 0, 0, .94666], 240: [0, .68889, 0, 0, .55556], 295: [0, .68889, 0, 0, .54028], 710: [0, .825, 0, 0, 2.33334], 732: [0, .9, 0, 0, 2.33334], 770: [0, .825, 0, 0, 2.33334], 771: [0, .9, 0, 0, 2.33334], 989: [.08167, .58167, 0, 0, .77778], 1008: [0, .43056, .04028, 0, .66667], 8245: [0, .54986, 0, 0, .275], 8463: [0, .68889, 0, 0, .54028], 8487: [0, .68889, 0, 0, .72222], 8498: [0, .68889, 0, 0, .55556], 8502: [0, .68889, 0, 0, .66667], 8503: [0, .68889, 0, 0, .44445], 8504: [0, .68889, 0, 0, .66667], 8513: [0, .68889, 0, 0, .63889], 8592: [-.03598, .46402, 0, 0, .5], 8594: [-.03598, .46402, 0, 0, .5], 8602: [-.13313, .36687, 0, 0, 1], 8603: [-.13313, .36687, 0, 0, 1], 8606: [.01354, .52239, 0, 0, 1], 8608: [.01354, .52239, 0, 0, 1], 8610: [.01354, .52239, 0, 0, 1.11111], 8611: [.01354, .52239, 0, 0, 1.11111], 8619: [0, .54986, 0, 0, 1], 8620: [0, .54986, 0, 0, 1], 8621: [-.13313, .37788, 0, 0, 1.38889], 8622: [-.13313, .36687, 0, 0, 1], 8624: [0, .69224, 0, 0, .5], 8625: [0, .69224, 0, 0, .5], 8630: [0, .43056, 0, 0, 1], 8631: [0, .43056, 0, 0, 1], 8634: [.08198, .58198, 0, 0, .77778], 8635: [.08198, .58198, 0, 0, .77778], 8638: [.19444, .69224, 0, 0, .41667], 8639: [.19444, .69224, 0, 0, .41667], 8642: [.19444, .69224, 0, 0, .41667], 8643: [.19444, .69224, 0, 0, .41667], 8644: [.1808, .675, 0, 0, 1], 8646: [.1808, .675, 0, 0, 1], 8647: [.1808, .675, 0, 0, 1], 8648: [.19444, .69224, 0, 0, .83334], 8649: [.1808, .675, 0, 0, 1], 8650: [.19444, .69224, 0, 0, .83334], 8651: [.01354, .52239, 0, 0, 1], 8652: [.01354, .52239, 0, 0, 1], 8653: [-.13313, .36687, 0, 0, 1], 8654: [-.13313, .36687, 0, 0, 1], 8655: [-.13313, .36687, 0, 0, 1], 8666: [.13667, .63667, 0, 0, 1], 8667: [.13667, .63667, 0, 0, 1], 8669: [-.13313, .37788, 0, 0, 1], 8672: [-.064, .437, 0, 0, 1.334], 8674: [-.064, .437, 0, 0, 1.334], 8705: [0, .825, 0, 0, .5], 8708: [0, .68889, 0, 0, .55556], 8709: [.08167, .58167, 0, 0, .77778], 8717: [0, .43056, 0, 0, .42917], 8722: [-.03598, .46402, 0, 0, .5], 8724: [.08198, .69224, 0, 0, .77778], 8726: [.08167, .58167, 0, 0, .77778], 8733: [0, .69224, 0, 0, .77778], 8736: [0, .69224, 0, 0, .72222], 8737: [0, .69224, 0, 0, .72222], 8738: [.03517, .52239, 0, 0, .72222], 8739: [.08167, .58167, 0, 0, .22222], 8740: [.25142, .74111, 0, 0, .27778], 8741: [.08167, .58167, 0, 0, .38889], 8742: [.25142, .74111, 0, 0, .5], 8756: [0, .69224, 0, 0, .66667], 8757: [0, .69224, 0, 0, .66667], 8764: [-.13313, .36687, 0, 0, .77778], 8765: [-.13313, .37788, 0, 0, .77778], 8769: [-.13313, .36687, 0, 0, .77778], 8770: [-.03625, .46375, 0, 0, .77778], 8774: [.30274, .79383, 0, 0, .77778], 8776: [-.01688, .48312, 0, 0, .77778], 8778: [.08167, .58167, 0, 0, .77778], 8782: [.06062, .54986, 0, 0, .77778], 8783: [.06062, .54986, 0, 0, .77778], 8785: [.08198, .58198, 0, 0, .77778], 8786: [.08198, .58198, 0, 0, .77778], 8787: [.08198, .58198, 0, 0, .77778], 8790: [0, .69224, 0, 0, .77778], 8791: [.22958, .72958, 0, 0, .77778], 8796: [.08198, .91667, 0, 0, .77778], 8806: [.25583, .75583, 0, 0, .77778], 8807: [.25583, .75583, 0, 0, .77778], 8808: [.25142, .75726, 0, 0, .77778], 8809: [.25142, .75726, 0, 0, .77778], 8812: [.25583, .75583, 0, 0, .5], 8814: [.20576, .70576, 0, 0, .77778], 8815: [.20576, .70576, 0, 0, .77778], 8816: [.30274, .79383, 0, 0, .77778], 8817: [.30274, .79383, 0, 0, .77778], 8818: [.22958, .72958, 0, 0, .77778], 8819: [.22958, .72958, 0, 0, .77778], 8822: [.1808, .675, 0, 0, .77778], 8823: [.1808, .675, 0, 0, .77778], 8828: [.13667, .63667, 0, 0, .77778], 8829: [.13667, .63667, 0, 0, .77778], 8830: [.22958, .72958, 0, 0, .77778], 8831: [.22958, .72958, 0, 0, .77778], 8832: [.20576, .70576, 0, 0, .77778], 8833: [.20576, .70576, 0, 0, .77778], 8840: [.30274, .79383, 0, 0, .77778], 8841: [.30274, .79383, 0, 0, .77778], 8842: [.13597, .63597, 0, 0, .77778], 8843: [.13597, .63597, 0, 0, .77778], 8847: [.03517, .54986, 0, 0, .77778], 8848: [.03517, .54986, 0, 0, .77778], 8858: [.08198, .58198, 0, 0, .77778], 8859: [.08198, .58198, 0, 0, .77778], 8861: [.08198, .58198, 0, 0, .77778], 8862: [0, .675, 0, 0, .77778], 8863: [0, .675, 0, 0, .77778], 8864: [0, .675, 0, 0, .77778], 8865: [0, .675, 0, 0, .77778], 8872: [0, .69224, 0, 0, .61111], 8873: [0, .69224, 0, 0, .72222], 8874: [0, .69224, 0, 0, .88889], 8876: [0, .68889, 0, 0, .61111], 8877: [0, .68889, 0, 0, .61111], 8878: [0, .68889, 0, 0, .72222], 8879: [0, .68889, 0, 0, .72222], 8882: [.03517, .54986, 0, 0, .77778], 8883: [.03517, .54986, 0, 0, .77778], 8884: [.13667, .63667, 0, 0, .77778], 8885: [.13667, .63667, 0, 0, .77778], 8888: [0, .54986, 0, 0, 1.11111], 8890: [.19444, .43056, 0, 0, .55556], 8891: [.19444, .69224, 0, 0, .61111], 8892: [.19444, .69224, 0, 0, .61111], 8901: [0, .54986, 0, 0, .27778], 8903: [.08167, .58167, 0, 0, .77778], 8905: [.08167, .58167, 0, 0, .77778], 8906: [.08167, .58167, 0, 0, .77778], 8907: [0, .69224, 0, 0, .77778], 8908: [0, .69224, 0, 0, .77778], 8909: [-.03598, .46402, 0, 0, .77778], 8910: [0, .54986, 0, 0, .76042], 8911: [0, .54986, 0, 0, .76042], 8912: [.03517, .54986, 0, 0, .77778], 8913: [.03517, .54986, 0, 0, .77778], 8914: [0, .54986, 0, 0, .66667], 8915: [0, .54986, 0, 0, .66667], 8916: [0, .69224, 0, 0, .66667], 8918: [.0391, .5391, 0, 0, .77778], 8919: [.0391, .5391, 0, 0, .77778], 8920: [.03517, .54986, 0, 0, 1.33334], 8921: [.03517, .54986, 0, 0, 1.33334], 8922: [.38569, .88569, 0, 0, .77778], 8923: [.38569, .88569, 0, 0, .77778], 8926: [.13667, .63667, 0, 0, .77778], 8927: [.13667, .63667, 0, 0, .77778], 8928: [.30274, .79383, 0, 0, .77778], 8929: [.30274, .79383, 0, 0, .77778], 8934: [.23222, .74111, 0, 0, .77778], 8935: [.23222, .74111, 0, 0, .77778], 8936: [.23222, .74111, 0, 0, .77778], 8937: [.23222, .74111, 0, 0, .77778], 8938: [.20576, .70576, 0, 0, .77778], 8939: [.20576, .70576, 0, 0, .77778], 8940: [.30274, .79383, 0, 0, .77778], 8941: [.30274, .79383, 0, 0, .77778], 8994: [.19444, .69224, 0, 0, .77778], 8995: [.19444, .69224, 0, 0, .77778], 9416: [.15559, .69224, 0, 0, .90222], 9484: [0, .69224, 0, 0, .5], 9488: [0, .69224, 0, 0, .5], 9492: [0, .37788, 0, 0, .5], 9496: [0, .37788, 0, 0, .5], 9585: [.19444, .68889, 0, 0, .88889], 9586: [.19444, .74111, 0, 0, .88889], 9632: [0, .675, 0, 0, .77778], 9633: [0, .675, 0, 0, .77778], 9650: [0, .54986, 0, 0, .72222], 9651: [0, .54986, 0, 0, .72222], 9654: [.03517, .54986, 0, 0, .77778], 9660: [0, .54986, 0, 0, .72222], 9661: [0, .54986, 0, 0, .72222], 9664: [.03517, .54986, 0, 0, .77778], 9674: [.11111, .69224, 0, 0, .66667], 9733: [.19444, .69224, 0, 0, .94445], 10003: [0, .69224, 0, 0, .83334], 10016: [0, .69224, 0, 0, .83334], 10731: [.11111, .69224, 0, 0, .66667], 10846: [.19444, .75583, 0, 0, .61111], 10877: [.13667, .63667, 0, 0, .77778], 10878: [.13667, .63667, 0, 0, .77778], 10885: [.25583, .75583, 0, 0, .77778], 10886: [.25583, .75583, 0, 0, .77778], 10887: [.13597, .63597, 0, 0, .77778], 10888: [.13597, .63597, 0, 0, .77778], 10889: [.26167, .75726, 0, 0, .77778], 10890: [.26167, .75726, 0, 0, .77778], 10891: [.48256, .98256, 0, 0, .77778], 10892: [.48256, .98256, 0, 0, .77778], 10901: [.13667, .63667, 0, 0, .77778], 10902: [.13667, .63667, 0, 0, .77778], 10933: [.25142, .75726, 0, 0, .77778], 10934: [.25142, .75726, 0, 0, .77778], 10935: [.26167, .75726, 0, 0, .77778], 10936: [.26167, .75726, 0, 0, .77778], 10937: [.26167, .75726, 0, 0, .77778], 10938: [.26167, .75726, 0, 0, .77778], 10949: [.25583, .75583, 0, 0, .77778], 10950: [.25583, .75583, 0, 0, .77778], 10955: [.28481, .79383, 0, 0, .77778], 10956: [.28481, .79383, 0, 0, .77778], 57350: [.08167, .58167, 0, 0, .22222], 57351: [.08167, .58167, 0, 0, .38889], 57352: [.08167, .58167, 0, 0, .77778], 57353: [0, .43056, .04028, 0, .66667], 57356: [.25142, .75726, 0, 0, .77778], 57357: [.25142, .75726, 0, 0, .77778], 57358: [.41951, .91951, 0, 0, .77778], 57359: [.30274, .79383, 0, 0, .77778], 57360: [.30274, .79383, 0, 0, .77778], 57361: [.41951, .91951, 0, 0, .77778], 57366: [.25142, .75726, 0, 0, .77778], 57367: [.25142, .75726, 0, 0, .77778], 57368: [.25142, .75726, 0, 0, .77778], 57369: [.25142, .75726, 0, 0, .77778], 57370: [.13597, .63597, 0, 0, .77778], 57371: [.13597, .63597, 0, 0, .77778] }, "Caligraphic-Regular": { 32: [0, 0, 0, 0, .25], 65: [0, .68333, 0, .19445, .79847], 66: [0, .68333, .03041, .13889, .65681], 67: [0, .68333, .05834, .13889, .52653], 68: [0, .68333, .02778, .08334, .77139], 69: [0, .68333, .08944, .11111, .52778], 70: [0, .68333, .09931, .11111, .71875], 71: [.09722, .68333, .0593, .11111, .59487], 72: [0, .68333, .00965, .11111, .84452], 73: [0, .68333, .07382, 0, .54452], 74: [.09722, .68333, .18472, .16667, .67778], 75: [0, .68333, .01445, .05556, .76195], 76: [0, .68333, 0, .13889, .68972], 77: [0, .68333, 0, .13889, 1.2009], 78: [0, .68333, .14736, .08334, .82049], 79: [0, .68333, .02778, .11111, .79611], 80: [0, .68333, .08222, .08334, .69556], 81: [.09722, .68333, 0, .11111, .81667], 82: [0, .68333, 0, .08334, .8475], 83: [0, .68333, .075, .13889, .60556], 84: [0, .68333, .25417, 0, .54464], 85: [0, .68333, .09931, .08334, .62583], 86: [0, .68333, .08222, 0, .61278], 87: [0, .68333, .08222, .08334, .98778], 88: [0, .68333, .14643, .13889, .7133], 89: [.09722, .68333, .08222, .08334, .66834], 90: [0, .68333, .07944, .13889, .72473], 160: [0, 0, 0, 0, .25] }, "Fraktur-Regular": { 32: [0, 0, 0, 0, .25], 33: [0, .69141, 0, 0, .29574], 34: [0, .69141, 0, 0, .21471], 38: [0, .69141, 0, 0, .73786], 39: [0, .69141, 0, 0, .21201], 40: [.24982, .74947, 0, 0, .38865], 41: [.24982, .74947, 0, 0, .38865], 42: [0, .62119, 0, 0, .27764], 43: [.08319, .58283, 0, 0, .75623], 44: [0, .10803, 0, 0, .27764], 45: [.08319, .58283, 0, 0, .75623], 46: [0, .10803, 0, 0, .27764], 47: [.24982, .74947, 0, 0, .50181], 48: [0, .47534, 0, 0, .50181], 49: [0, .47534, 0, 0, .50181], 50: [0, .47534, 0, 0, .50181], 51: [.18906, .47534, 0, 0, .50181], 52: [.18906, .47534, 0, 0, .50181], 53: [.18906, .47534, 0, 0, .50181], 54: [0, .69141, 0, 0, .50181], 55: [.18906, .47534, 0, 0, .50181], 56: [0, .69141, 0, 0, .50181], 57: [.18906, .47534, 0, 0, .50181], 58: [0, .47534, 0, 0, .21606], 59: [.12604, .47534, 0, 0, .21606], 61: [-.13099, .36866, 0, 0, .75623], 63: [0, .69141, 0, 0, .36245], 65: [0, .69141, 0, 0, .7176], 66: [0, .69141, 0, 0, .88397], 67: [0, .69141, 0, 0, .61254], 68: [0, .69141, 0, 0, .83158], 69: [0, .69141, 0, 0, .66278], 70: [.12604, .69141, 0, 0, .61119], 71: [0, .69141, 0, 0, .78539], 72: [.06302, .69141, 0, 0, .7203], 73: [0, .69141, 0, 0, .55448], 74: [.12604, .69141, 0, 0, .55231], 75: [0, .69141, 0, 0, .66845], 76: [0, .69141, 0, 0, .66602], 77: [0, .69141, 0, 0, 1.04953], 78: [0, .69141, 0, 0, .83212], 79: [0, .69141, 0, 0, .82699], 80: [.18906, .69141, 0, 0, .82753], 81: [.03781, .69141, 0, 0, .82699], 82: [0, .69141, 0, 0, .82807], 83: [0, .69141, 0, 0, .82861], 84: [0, .69141, 0, 0, .66899], 85: [0, .69141, 0, 0, .64576], 86: [0, .69141, 0, 0, .83131], 87: [0, .69141, 0, 0, 1.04602], 88: [0, .69141, 0, 0, .71922], 89: [.18906, .69141, 0, 0, .83293], 90: [.12604, .69141, 0, 0, .60201], 91: [.24982, .74947, 0, 0, .27764], 93: [.24982, .74947, 0, 0, .27764], 94: [0, .69141, 0, 0, .49965], 97: [0, .47534, 0, 0, .50046], 98: [0, .69141, 0, 0, .51315], 99: [0, .47534, 0, 0, .38946], 100: [0, .62119, 0, 0, .49857], 101: [0, .47534, 0, 0, .40053], 102: [.18906, .69141, 0, 0, .32626], 103: [.18906, .47534, 0, 0, .5037], 104: [.18906, .69141, 0, 0, .52126], 105: [0, .69141, 0, 0, .27899], 106: [0, .69141, 0, 0, .28088], 107: [0, .69141, 0, 0, .38946], 108: [0, .69141, 0, 0, .27953], 109: [0, .47534, 0, 0, .76676], 110: [0, .47534, 0, 0, .52666], 111: [0, .47534, 0, 0, .48885], 112: [.18906, .52396, 0, 0, .50046], 113: [.18906, .47534, 0, 0, .48912], 114: [0, .47534, 0, 0, .38919], 115: [0, .47534, 0, 0, .44266], 116: [0, .62119, 0, 0, .33301], 117: [0, .47534, 0, 0, .5172], 118: [0, .52396, 0, 0, .5118], 119: [0, .52396, 0, 0, .77351], 120: [.18906, .47534, 0, 0, .38865], 121: [.18906, .47534, 0, 0, .49884], 122: [.18906, .47534, 0, 0, .39054], 160: [0, 0, 0, 0, .25], 8216: [0, .69141, 0, 0, .21471], 8217: [0, .69141, 0, 0, .21471], 58112: [0, .62119, 0, 0, .49749], 58113: [0, .62119, 0, 0, .4983], 58114: [.18906, .69141, 0, 0, .33328], 58115: [.18906, .69141, 0, 0, .32923], 58116: [.18906, .47534, 0, 0, .50343], 58117: [0, .69141, 0, 0, .33301], 58118: [0, .62119, 0, 0, .33409], 58119: [0, .47534, 0, 0, .50073] }, "Main-Bold": { 32: [0, 0, 0, 0, .25], 33: [0, .69444, 0, 0, .35], 34: [0, .69444, 0, 0, .60278], 35: [.19444, .69444, 0, 0, .95833], 36: [.05556, .75, 0, 0, .575], 37: [.05556, .75, 0, 0, .95833], 38: [0, .69444, 0, 0, .89444], 39: [0, .69444, 0, 0, .31944], 40: [.25, .75, 0, 0, .44722], 41: [.25, .75, 0, 0, .44722], 42: [0, .75, 0, 0, .575], 43: [.13333, .63333, 0, 0, .89444], 44: [.19444, .15556, 0, 0, .31944], 45: [0, .44444, 0, 0, .38333], 46: [0, .15556, 0, 0, .31944], 47: [.25, .75, 0, 0, .575], 48: [0, .64444, 0, 0, .575], 49: [0, .64444, 0, 0, .575], 50: [0, .64444, 0, 0, .575], 51: [0, .64444, 0, 0, .575], 52: [0, .64444, 0, 0, .575], 53: [0, .64444, 0, 0, .575], 54: [0, .64444, 0, 0, .575], 55: [0, .64444, 0, 0, .575], 56: [0, .64444, 0, 0, .575], 57: [0, .64444, 0, 0, .575], 58: [0, .44444, 0, 0, .31944], 59: [.19444, .44444, 0, 0, .31944], 60: [.08556, .58556, 0, 0, .89444], 61: [-.10889, .39111, 0, 0, .89444], 62: [.08556, .58556, 0, 0, .89444], 63: [0, .69444, 0, 0, .54305], 64: [0, .69444, 0, 0, .89444], 65: [0, .68611, 0, 0, .86944], 66: [0, .68611, 0, 0, .81805], 67: [0, .68611, 0, 0, .83055], 68: [0, .68611, 0, 0, .88194], 69: [0, .68611, 0, 0, .75555], 70: [0, .68611, 0, 0, .72361], 71: [0, .68611, 0, 0, .90416], 72: [0, .68611, 0, 0, .9], 73: [0, .68611, 0, 0, .43611], 74: [0, .68611, 0, 0, .59444], 75: [0, .68611, 0, 0, .90138], 76: [0, .68611, 0, 0, .69166], 77: [0, .68611, 0, 0, 1.09166], 78: [0, .68611, 0, 0, .9], 79: [0, .68611, 0, 0, .86388], 80: [0, .68611, 0, 0, .78611], 81: [.19444, .68611, 0, 0, .86388], 82: [0, .68611, 0, 0, .8625], 83: [0, .68611, 0, 0, .63889], 84: [0, .68611, 0, 0, .8], 85: [0, .68611, 0, 0, .88472], 86: [0, .68611, .01597, 0, .86944], 87: [0, .68611, .01597, 0, 1.18888], 88: [0, .68611, 0, 0, .86944], 89: [0, .68611, .02875, 0, .86944], 90: [0, .68611, 0, 0, .70277], 91: [.25, .75, 0, 0, .31944], 92: [.25, .75, 0, 0, .575], 93: [.25, .75, 0, 0, .31944], 94: [0, .69444, 0, 0, .575], 95: [.31, .13444, .03194, 0, .575], 97: [0, .44444, 0, 0, .55902], 98: [0, .69444, 0, 0, .63889], 99: [0, .44444, 0, 0, .51111], 100: [0, .69444, 0, 0, .63889], 101: [0, .44444, 0, 0, .52708], 102: [0, .69444, .10903, 0, .35139], 103: [.19444, .44444, .01597, 0, .575], 104: [0, .69444, 0, 0, .63889], 105: [0, .69444, 0, 0, .31944], 106: [.19444, .69444, 0, 0, .35139], 107: [0, .69444, 0, 0, .60694], 108: [0, .69444, 0, 0, .31944], 109: [0, .44444, 0, 0, .95833], 110: [0, .44444, 0, 0, .63889], 111: [0, .44444, 0, 0, .575], 112: [.19444, .44444, 0, 0, .63889], 113: [.19444, .44444, 0, 0, .60694], 114: [0, .44444, 0, 0, .47361], 115: [0, .44444, 0, 0, .45361], 116: [0, .63492, 0, 0, .44722], 117: [0, .44444, 0, 0, .63889], 118: [0, .44444, .01597, 0, .60694], 119: [0, .44444, .01597, 0, .83055], 120: [0, .44444, 0, 0, .60694], 121: [.19444, .44444, .01597, 0, .60694], 122: [0, .44444, 0, 0, .51111], 123: [.25, .75, 0, 0, .575], 124: [.25, .75, 0, 0, .31944], 125: [.25, .75, 0, 0, .575], 126: [.35, .34444, 0, 0, .575], 160: [0, 0, 0, 0, .25], 163: [0, .69444, 0, 0, .86853], 168: [0, .69444, 0, 0, .575], 172: [0, .44444, 0, 0, .76666], 176: [0, .69444, 0, 0, .86944], 177: [.13333, .63333, 0, 0, .89444], 184: [.17014, 0, 0, 0, .51111], 198: [0, .68611, 0, 0, 1.04166], 215: [.13333, .63333, 0, 0, .89444], 216: [.04861, .73472, 0, 0, .89444], 223: [0, .69444, 0, 0, .59722], 230: [0, .44444, 0, 0, .83055], 247: [.13333, .63333, 0, 0, .89444], 248: [.09722, .54167, 0, 0, .575], 305: [0, .44444, 0, 0, .31944], 338: [0, .68611, 0, 0, 1.16944], 339: [0, .44444, 0, 0, .89444], 567: [.19444, .44444, 0, 0, .35139], 710: [0, .69444, 0, 0, .575], 711: [0, .63194, 0, 0, .575], 713: [0, .59611, 0, 0, .575], 714: [0, .69444, 0, 0, .575], 715: [0, .69444, 0, 0, .575], 728: [0, .69444, 0, 0, .575], 729: [0, .69444, 0, 0, .31944], 730: [0, .69444, 0, 0, .86944], 732: [0, .69444, 0, 0, .575], 733: [0, .69444, 0, 0, .575], 915: [0, .68611, 0, 0, .69166], 916: [0, .68611, 0, 0, .95833], 920: [0, .68611, 0, 0, .89444], 923: [0, .68611, 0, 0, .80555], 926: [0, .68611, 0, 0, .76666], 928: [0, .68611, 0, 0, .9], 931: [0, .68611, 0, 0, .83055], 933: [0, .68611, 0, 0, .89444], 934: [0, .68611, 0, 0, .83055], 936: [0, .68611, 0, 0, .89444], 937: [0, .68611, 0, 0, .83055], 8211: [0, .44444, .03194, 0, .575], 8212: [0, .44444, .03194, 0, 1.14999], 8216: [0, .69444, 0, 0, .31944], 8217: [0, .69444, 0, 0, .31944], 8220: [0, .69444, 0, 0, .60278], 8221: [0, .69444, 0, 0, .60278], 8224: [.19444, .69444, 0, 0, .51111], 8225: [.19444, .69444, 0, 0, .51111], 8242: [0, .55556, 0, 0, .34444], 8407: [0, .72444, .15486, 0, .575], 8463: [0, .69444, 0, 0, .66759], 8465: [0, .69444, 0, 0, .83055], 8467: [0, .69444, 0, 0, .47361], 8472: [.19444, .44444, 0, 0, .74027], 8476: [0, .69444, 0, 0, .83055], 8501: [0, .69444, 0, 0, .70277], 8592: [-.10889, .39111, 0, 0, 1.14999], 8593: [.19444, .69444, 0, 0, .575], 8594: [-.10889, .39111, 0, 0, 1.14999], 8595: [.19444, .69444, 0, 0, .575], 8596: [-.10889, .39111, 0, 0, 1.14999], 8597: [.25, .75, 0, 0, .575], 8598: [.19444, .69444, 0, 0, 1.14999], 8599: [.19444, .69444, 0, 0, 1.14999], 8600: [.19444, .69444, 0, 0, 1.14999], 8601: [.19444, .69444, 0, 0, 1.14999], 8636: [-.10889, .39111, 0, 0, 1.14999], 8637: [-.10889, .39111, 0, 0, 1.14999], 8640: [-.10889, .39111, 0, 0, 1.14999], 8641: [-.10889, .39111, 0, 0, 1.14999], 8656: [-.10889, .39111, 0, 0, 1.14999], 8657: [.19444, .69444, 0, 0, .70277], 8658: [-.10889, .39111, 0, 0, 1.14999], 8659: [.19444, .69444, 0, 0, .70277], 8660: [-.10889, .39111, 0, 0, 1.14999], 8661: [.25, .75, 0, 0, .70277], 8704: [0, .69444, 0, 0, .63889], 8706: [0, .69444, .06389, 0, .62847], 8707: [0, .69444, 0, 0, .63889], 8709: [.05556, .75, 0, 0, .575], 8711: [0, .68611, 0, 0, .95833], 8712: [.08556, .58556, 0, 0, .76666], 8715: [.08556, .58556, 0, 0, .76666], 8722: [.13333, .63333, 0, 0, .89444], 8723: [.13333, .63333, 0, 0, .89444], 8725: [.25, .75, 0, 0, .575], 8726: [.25, .75, 0, 0, .575], 8727: [-.02778, .47222, 0, 0, .575], 8728: [-.02639, .47361, 0, 0, .575], 8729: [-.02639, .47361, 0, 0, .575], 8730: [.18, .82, 0, 0, .95833], 8733: [0, .44444, 0, 0, .89444], 8734: [0, .44444, 0, 0, 1.14999], 8736: [0, .69224, 0, 0, .72222], 8739: [.25, .75, 0, 0, .31944], 8741: [.25, .75, 0, 0, .575], 8743: [0, .55556, 0, 0, .76666], 8744: [0, .55556, 0, 0, .76666], 8745: [0, .55556, 0, 0, .76666], 8746: [0, .55556, 0, 0, .76666], 8747: [.19444, .69444, .12778, 0, .56875], 8764: [-.10889, .39111, 0, 0, .89444], 8768: [.19444, .69444, 0, 0, .31944], 8771: [.00222, .50222, 0, 0, .89444], 8773: [.027, .638, 0, 0, .894], 8776: [.02444, .52444, 0, 0, .89444], 8781: [.00222, .50222, 0, 0, .89444], 8801: [.00222, .50222, 0, 0, .89444], 8804: [.19667, .69667, 0, 0, .89444], 8805: [.19667, .69667, 0, 0, .89444], 8810: [.08556, .58556, 0, 0, 1.14999], 8811: [.08556, .58556, 0, 0, 1.14999], 8826: [.08556, .58556, 0, 0, .89444], 8827: [.08556, .58556, 0, 0, .89444], 8834: [.08556, .58556, 0, 0, .89444], 8835: [.08556, .58556, 0, 0, .89444], 8838: [.19667, .69667, 0, 0, .89444], 8839: [.19667, .69667, 0, 0, .89444], 8846: [0, .55556, 0, 0, .76666], 8849: [.19667, .69667, 0, 0, .89444], 8850: [.19667, .69667, 0, 0, .89444], 8851: [0, .55556, 0, 0, .76666], 8852: [0, .55556, 0, 0, .76666], 8853: [.13333, .63333, 0, 0, .89444], 8854: [.13333, .63333, 0, 0, .89444], 8855: [.13333, .63333, 0, 0, .89444], 8856: [.13333, .63333, 0, 0, .89444], 8857: [.13333, .63333, 0, 0, .89444], 8866: [0, .69444, 0, 0, .70277], 8867: [0, .69444, 0, 0, .70277], 8868: [0, .69444, 0, 0, .89444], 8869: [0, .69444, 0, 0, .89444], 8900: [-.02639, .47361, 0, 0, .575], 8901: [-.02639, .47361, 0, 0, .31944], 8902: [-.02778, .47222, 0, 0, .575], 8968: [.25, .75, 0, 0, .51111], 8969: [.25, .75, 0, 0, .51111], 8970: [.25, .75, 0, 0, .51111], 8971: [.25, .75, 0, 0, .51111], 8994: [-.13889, .36111, 0, 0, 1.14999], 8995: [-.13889, .36111, 0, 0, 1.14999], 9651: [.19444, .69444, 0, 0, 1.02222], 9657: [-.02778, .47222, 0, 0, .575], 9661: [.19444, .69444, 0, 0, 1.02222], 9667: [-.02778, .47222, 0, 0, .575], 9711: [.19444, .69444, 0, 0, 1.14999], 9824: [.12963, .69444, 0, 0, .89444], 9825: [.12963, .69444, 0, 0, .89444], 9826: [.12963, .69444, 0, 0, .89444], 9827: [.12963, .69444, 0, 0, .89444], 9837: [0, .75, 0, 0, .44722], 9838: [.19444, .69444, 0, 0, .44722], 9839: [.19444, .69444, 0, 0, .44722], 10216: [.25, .75, 0, 0, .44722], 10217: [.25, .75, 0, 0, .44722], 10815: [0, .68611, 0, 0, .9], 10927: [.19667, .69667, 0, 0, .89444], 10928: [.19667, .69667, 0, 0, .89444], 57376: [.19444, .69444, 0, 0, 0] }, "Main-BoldItalic": { 32: [0, 0, 0, 0, .25], 33: [0, .69444, .11417, 0, .38611], 34: [0, .69444, .07939, 0, .62055], 35: [.19444, .69444, .06833, 0, .94444], 37: [.05556, .75, .12861, 0, .94444], 38: [0, .69444, .08528, 0, .88555], 39: [0, .69444, .12945, 0, .35555], 40: [.25, .75, .15806, 0, .47333], 41: [.25, .75, .03306, 0, .47333], 42: [0, .75, .14333, 0, .59111], 43: [.10333, .60333, .03306, 0, .88555], 44: [.19444, .14722, 0, 0, .35555], 45: [0, .44444, .02611, 0, .41444], 46: [0, .14722, 0, 0, .35555], 47: [.25, .75, .15806, 0, .59111], 48: [0, .64444, .13167, 0, .59111], 49: [0, .64444, .13167, 0, .59111], 50: [0, .64444, .13167, 0, .59111], 51: [0, .64444, .13167, 0, .59111], 52: [.19444, .64444, .13167, 0, .59111], 53: [0, .64444, .13167, 0, .59111], 54: [0, .64444, .13167, 0, .59111], 55: [.19444, .64444, .13167, 0, .59111], 56: [0, .64444, .13167, 0, .59111], 57: [0, .64444, .13167, 0, .59111], 58: [0, .44444, .06695, 0, .35555], 59: [.19444, .44444, .06695, 0, .35555], 61: [-.10889, .39111, .06833, 0, .88555], 63: [0, .69444, .11472, 0, .59111], 64: [0, .69444, .09208, 0, .88555], 65: [0, .68611, 0, 0, .86555], 66: [0, .68611, .0992, 0, .81666], 67: [0, .68611, .14208, 0, .82666], 68: [0, .68611, .09062, 0, .87555], 69: [0, .68611, .11431, 0, .75666], 70: [0, .68611, .12903, 0, .72722], 71: [0, .68611, .07347, 0, .89527], 72: [0, .68611, .17208, 0, .8961], 73: [0, .68611, .15681, 0, .47166], 74: [0, .68611, .145, 0, .61055], 75: [0, .68611, .14208, 0, .89499], 76: [0, .68611, 0, 0, .69777], 77: [0, .68611, .17208, 0, 1.07277], 78: [0, .68611, .17208, 0, .8961], 79: [0, .68611, .09062, 0, .85499], 80: [0, .68611, .0992, 0, .78721], 81: [.19444, .68611, .09062, 0, .85499], 82: [0, .68611, .02559, 0, .85944], 83: [0, .68611, .11264, 0, .64999], 84: [0, .68611, .12903, 0, .7961], 85: [0, .68611, .17208, 0, .88083], 86: [0, .68611, .18625, 0, .86555], 87: [0, .68611, .18625, 0, 1.15999], 88: [0, .68611, .15681, 0, .86555], 89: [0, .68611, .19803, 0, .86555], 90: [0, .68611, .14208, 0, .70888], 91: [.25, .75, .1875, 0, .35611], 93: [.25, .75, .09972, 0, .35611], 94: [0, .69444, .06709, 0, .59111], 95: [.31, .13444, .09811, 0, .59111], 97: [0, .44444, .09426, 0, .59111], 98: [0, .69444, .07861, 0, .53222], 99: [0, .44444, .05222, 0, .53222], 100: [0, .69444, .10861, 0, .59111], 101: [0, .44444, .085, 0, .53222], 102: [.19444, .69444, .21778, 0, .4], 103: [.19444, .44444, .105, 0, .53222], 104: [0, .69444, .09426, 0, .59111], 105: [0, .69326, .11387, 0, .35555], 106: [.19444, .69326, .1672, 0, .35555], 107: [0, .69444, .11111, 0, .53222], 108: [0, .69444, .10861, 0, .29666], 109: [0, .44444, .09426, 0, .94444], 110: [0, .44444, .09426, 0, .64999], 111: [0, .44444, .07861, 0, .59111], 112: [.19444, .44444, .07861, 0, .59111], 113: [.19444, .44444, .105, 0, .53222], 114: [0, .44444, .11111, 0, .50167], 115: [0, .44444, .08167, 0, .48694], 116: [0, .63492, .09639, 0, .385], 117: [0, .44444, .09426, 0, .62055], 118: [0, .44444, .11111, 0, .53222], 119: [0, .44444, .11111, 0, .76777], 120: [0, .44444, .12583, 0, .56055], 121: [.19444, .44444, .105, 0, .56166], 122: [0, .44444, .13889, 0, .49055], 126: [.35, .34444, .11472, 0, .59111], 160: [0, 0, 0, 0, .25], 168: [0, .69444, .11473, 0, .59111], 176: [0, .69444, 0, 0, .94888], 184: [.17014, 0, 0, 0, .53222], 198: [0, .68611, .11431, 0, 1.02277], 216: [.04861, .73472, .09062, 0, .88555], 223: [.19444, .69444, .09736, 0, .665], 230: [0, .44444, .085, 0, .82666], 248: [.09722, .54167, .09458, 0, .59111], 305: [0, .44444, .09426, 0, .35555], 338: [0, .68611, .11431, 0, 1.14054], 339: [0, .44444, .085, 0, .82666], 567: [.19444, .44444, .04611, 0, .385], 710: [0, .69444, .06709, 0, .59111], 711: [0, .63194, .08271, 0, .59111], 713: [0, .59444, .10444, 0, .59111], 714: [0, .69444, .08528, 0, .59111], 715: [0, .69444, 0, 0, .59111], 728: [0, .69444, .10333, 0, .59111], 729: [0, .69444, .12945, 0, .35555], 730: [0, .69444, 0, 0, .94888], 732: [0, .69444, .11472, 0, .59111], 733: [0, .69444, .11472, 0, .59111], 915: [0, .68611, .12903, 0, .69777], 916: [0, .68611, 0, 0, .94444], 920: [0, .68611, .09062, 0, .88555], 923: [0, .68611, 0, 0, .80666], 926: [0, .68611, .15092, 0, .76777], 928: [0, .68611, .17208, 0, .8961], 931: [0, .68611, .11431, 0, .82666], 933: [0, .68611, .10778, 0, .88555], 934: [0, .68611, .05632, 0, .82666], 936: [0, .68611, .10778, 0, .88555], 937: [0, .68611, .0992, 0, .82666], 8211: [0, .44444, .09811, 0, .59111], 8212: [0, .44444, .09811, 0, 1.18221], 8216: [0, .69444, .12945, 0, .35555], 8217: [0, .69444, .12945, 0, .35555], 8220: [0, .69444, .16772, 0, .62055], 8221: [0, .69444, .07939, 0, .62055] }, "Main-Italic": { 32: [0, 0, 0, 0, .25], 33: [0, .69444, .12417, 0, .30667], 34: [0, .69444, .06961, 0, .51444], 35: [.19444, .69444, .06616, 0, .81777], 37: [.05556, .75, .13639, 0, .81777], 38: [0, .69444, .09694, 0, .76666], 39: [0, .69444, .12417, 0, .30667], 40: [.25, .75, .16194, 0, .40889], 41: [.25, .75, .03694, 0, .40889], 42: [0, .75, .14917, 0, .51111], 43: [.05667, .56167, .03694, 0, .76666], 44: [.19444, .10556, 0, 0, .30667], 45: [0, .43056, .02826, 0, .35778], 46: [0, .10556, 0, 0, .30667], 47: [.25, .75, .16194, 0, .51111], 48: [0, .64444, .13556, 0, .51111], 49: [0, .64444, .13556, 0, .51111], 50: [0, .64444, .13556, 0, .51111], 51: [0, .64444, .13556, 0, .51111], 52: [.19444, .64444, .13556, 0, .51111], 53: [0, .64444, .13556, 0, .51111], 54: [0, .64444, .13556, 0, .51111], 55: [.19444, .64444, .13556, 0, .51111], 56: [0, .64444, .13556, 0, .51111], 57: [0, .64444, .13556, 0, .51111], 58: [0, .43056, .0582, 0, .30667], 59: [.19444, .43056, .0582, 0, .30667], 61: [-.13313, .36687, .06616, 0, .76666], 63: [0, .69444, .1225, 0, .51111], 64: [0, .69444, .09597, 0, .76666], 65: [0, .68333, 0, 0, .74333], 66: [0, .68333, .10257, 0, .70389], 67: [0, .68333, .14528, 0, .71555], 68: [0, .68333, .09403, 0, .755], 69: [0, .68333, .12028, 0, .67833], 70: [0, .68333, .13305, 0, .65277], 71: [0, .68333, .08722, 0, .77361], 72: [0, .68333, .16389, 0, .74333], 73: [0, .68333, .15806, 0, .38555], 74: [0, .68333, .14028, 0, .525], 75: [0, .68333, .14528, 0, .76888], 76: [0, .68333, 0, 0, .62722], 77: [0, .68333, .16389, 0, .89666], 78: [0, .68333, .16389, 0, .74333], 79: [0, .68333, .09403, 0, .76666], 80: [0, .68333, .10257, 0, .67833], 81: [.19444, .68333, .09403, 0, .76666], 82: [0, .68333, .03868, 0, .72944], 83: [0, .68333, .11972, 0, .56222], 84: [0, .68333, .13305, 0, .71555], 85: [0, .68333, .16389, 0, .74333], 86: [0, .68333, .18361, 0, .74333], 87: [0, .68333, .18361, 0, .99888], 88: [0, .68333, .15806, 0, .74333], 89: [0, .68333, .19383, 0, .74333], 90: [0, .68333, .14528, 0, .61333], 91: [.25, .75, .1875, 0, .30667], 93: [.25, .75, .10528, 0, .30667], 94: [0, .69444, .06646, 0, .51111], 95: [.31, .12056, .09208, 0, .51111], 97: [0, .43056, .07671, 0, .51111], 98: [0, .69444, .06312, 0, .46], 99: [0, .43056, .05653, 0, .46], 100: [0, .69444, .10333, 0, .51111], 101: [0, .43056, .07514, 0, .46], 102: [.19444, .69444, .21194, 0, .30667], 103: [.19444, .43056, .08847, 0, .46], 104: [0, .69444, .07671, 0, .51111], 105: [0, .65536, .1019, 0, .30667], 106: [.19444, .65536, .14467, 0, .30667], 107: [0, .69444, .10764, 0, .46], 108: [0, .69444, .10333, 0, .25555], 109: [0, .43056, .07671, 0, .81777], 110: [0, .43056, .07671, 0, .56222], 111: [0, .43056, .06312, 0, .51111], 112: [.19444, .43056, .06312, 0, .51111], 113: [.19444, .43056, .08847, 0, .46], 114: [0, .43056, .10764, 0, .42166], 115: [0, .43056, .08208, 0, .40889], 116: [0, .61508, .09486, 0, .33222], 117: [0, .43056, .07671, 0, .53666], 118: [0, .43056, .10764, 0, .46], 119: [0, .43056, .10764, 0, .66444], 120: [0, .43056, .12042, 0, .46389], 121: [.19444, .43056, .08847, 0, .48555], 122: [0, .43056, .12292, 0, .40889], 126: [.35, .31786, .11585, 0, .51111], 160: [0, 0, 0, 0, .25], 168: [0, .66786, .10474, 0, .51111], 176: [0, .69444, 0, 0, .83129], 184: [.17014, 0, 0, 0, .46], 198: [0, .68333, .12028, 0, .88277], 216: [.04861, .73194, .09403, 0, .76666], 223: [.19444, .69444, .10514, 0, .53666], 230: [0, .43056, .07514, 0, .71555], 248: [.09722, .52778, .09194, 0, .51111], 338: [0, .68333, .12028, 0, .98499], 339: [0, .43056, .07514, 0, .71555], 710: [0, .69444, .06646, 0, .51111], 711: [0, .62847, .08295, 0, .51111], 713: [0, .56167, .10333, 0, .51111], 714: [0, .69444, .09694, 0, .51111], 715: [0, .69444, 0, 0, .51111], 728: [0, .69444, .10806, 0, .51111], 729: [0, .66786, .11752, 0, .30667], 730: [0, .69444, 0, 0, .83129], 732: [0, .66786, .11585, 0, .51111], 733: [0, .69444, .1225, 0, .51111], 915: [0, .68333, .13305, 0, .62722], 916: [0, .68333, 0, 0, .81777], 920: [0, .68333, .09403, 0, .76666], 923: [0, .68333, 0, 0, .69222], 926: [0, .68333, .15294, 0, .66444], 928: [0, .68333, .16389, 0, .74333], 931: [0, .68333, .12028, 0, .71555], 933: [0, .68333, .11111, 0, .76666], 934: [0, .68333, .05986, 0, .71555], 936: [0, .68333, .11111, 0, .76666], 937: [0, .68333, .10257, 0, .71555], 8211: [0, .43056, .09208, 0, .51111], 8212: [0, .43056, .09208, 0, 1.02222], 8216: [0, .69444, .12417, 0, .30667], 8217: [0, .69444, .12417, 0, .30667], 8220: [0, .69444, .1685, 0, .51444], 8221: [0, .69444, .06961, 0, .51444], 8463: [0, .68889, 0, 0, .54028] }, "Main-Regular": { 32: [0, 0, 0, 0, .25], 33: [0, .69444, 0, 0, .27778], 34: [0, .69444, 0, 0, .5], 35: [.19444, .69444, 0, 0, .83334], 36: [.05556, .75, 0, 0, .5], 37: [.05556, .75, 0, 0, .83334], 38: [0, .69444, 0, 0, .77778], 39: [0, .69444, 0, 0, .27778], 40: [.25, .75, 0, 0, .38889], 41: [.25, .75, 0, 0, .38889], 42: [0, .75, 0, 0, .5], 43: [.08333, .58333, 0, 0, .77778], 44: [.19444, .10556, 0, 0, .27778], 45: [0, .43056, 0, 0, .33333], 46: [0, .10556, 0, 0, .27778], 47: [.25, .75, 0, 0, .5], 48: [0, .64444, 0, 0, .5], 49: [0, .64444, 0, 0, .5], 50: [0, .64444, 0, 0, .5], 51: [0, .64444, 0, 0, .5], 52: [0, .64444, 0, 0, .5], 53: [0, .64444, 0, 0, .5], 54: [0, .64444, 0, 0, .5], 55: [0, .64444, 0, 0, .5], 56: [0, .64444, 0, 0, .5], 57: [0, .64444, 0, 0, .5], 58: [0, .43056, 0, 0, .27778], 59: [.19444, .43056, 0, 0, .27778], 60: [.0391, .5391, 0, 0, .77778], 61: [-.13313, .36687, 0, 0, .77778], 62: [.0391, .5391, 0, 0, .77778], 63: [0, .69444, 0, 0, .47222], 64: [0, .69444, 0, 0, .77778], 65: [0, .68333, 0, 0, .75], 66: [0, .68333, 0, 0, .70834], 67: [0, .68333, 0, 0, .72222], 68: [0, .68333, 0, 0, .76389], 69: [0, .68333, 0, 0, .68056], 70: [0, .68333, 0, 0, .65278], 71: [0, .68333, 0, 0, .78472], 72: [0, .68333, 0, 0, .75], 73: [0, .68333, 0, 0, .36111], 74: [0, .68333, 0, 0, .51389], 75: [0, .68333, 0, 0, .77778], 76: [0, .68333, 0, 0, .625], 77: [0, .68333, 0, 0, .91667], 78: [0, .68333, 0, 0, .75], 79: [0, .68333, 0, 0, .77778], 80: [0, .68333, 0, 0, .68056], 81: [.19444, .68333, 0, 0, .77778], 82: [0, .68333, 0, 0, .73611], 83: [0, .68333, 0, 0, .55556], 84: [0, .68333, 0, 0, .72222], 85: [0, .68333, 0, 0, .75], 86: [0, .68333, .01389, 0, .75], 87: [0, .68333, .01389, 0, 1.02778], 88: [0, .68333, 0, 0, .75], 89: [0, .68333, .025, 0, .75], 90: [0, .68333, 0, 0, .61111], 91: [.25, .75, 0, 0, .27778], 92: [.25, .75, 0, 0, .5], 93: [.25, .75, 0, 0, .27778], 94: [0, .69444, 0, 0, .5], 95: [.31, .12056, .02778, 0, .5], 97: [0, .43056, 0, 0, .5], 98: [0, .69444, 0, 0, .55556], 99: [0, .43056, 0, 0, .44445], 100: [0, .69444, 0, 0, .55556], 101: [0, .43056, 0, 0, .44445], 102: [0, .69444, .07778, 0, .30556], 103: [.19444, .43056, .01389, 0, .5], 104: [0, .69444, 0, 0, .55556], 105: [0, .66786, 0, 0, .27778], 106: [.19444, .66786, 0, 0, .30556], 107: [0, .69444, 0, 0, .52778], 108: [0, .69444, 0, 0, .27778], 109: [0, .43056, 0, 0, .83334], 110: [0, .43056, 0, 0, .55556], 111: [0, .43056, 0, 0, .5], 112: [.19444, .43056, 0, 0, .55556], 113: [.19444, .43056, 0, 0, .52778], 114: [0, .43056, 0, 0, .39167], 115: [0, .43056, 0, 0, .39445], 116: [0, .61508, 0, 0, .38889], 117: [0, .43056, 0, 0, .55556], 118: [0, .43056, .01389, 0, .52778], 119: [0, .43056, .01389, 0, .72222], 120: [0, .43056, 0, 0, .52778], 121: [.19444, .43056, .01389, 0, .52778], 122: [0, .43056, 0, 0, .44445], 123: [.25, .75, 0, 0, .5], 124: [.25, .75, 0, 0, .27778], 125: [.25, .75, 0, 0, .5], 126: [.35, .31786, 0, 0, .5], 160: [0, 0, 0, 0, .25], 163: [0, .69444, 0, 0, .76909], 167: [.19444, .69444, 0, 0, .44445], 168: [0, .66786, 0, 0, .5], 172: [0, .43056, 0, 0, .66667], 176: [0, .69444, 0, 0, .75], 177: [.08333, .58333, 0, 0, .77778], 182: [.19444, .69444, 0, 0, .61111], 184: [.17014, 0, 0, 0, .44445], 198: [0, .68333, 0, 0, .90278], 215: [.08333, .58333, 0, 0, .77778], 216: [.04861, .73194, 0, 0, .77778], 223: [0, .69444, 0, 0, .5], 230: [0, .43056, 0, 0, .72222], 247: [.08333, .58333, 0, 0, .77778], 248: [.09722, .52778, 0, 0, .5], 305: [0, .43056, 0, 0, .27778], 338: [0, .68333, 0, 0, 1.01389], 339: [0, .43056, 0, 0, .77778], 567: [.19444, .43056, 0, 0, .30556], 710: [0, .69444, 0, 0, .5], 711: [0, .62847, 0, 0, .5], 713: [0, .56778, 0, 0, .5], 714: [0, .69444, 0, 0, .5], 715: [0, .69444, 0, 0, .5], 728: [0, .69444, 0, 0, .5], 729: [0, .66786, 0, 0, .27778], 730: [0, .69444, 0, 0, .75], 732: [0, .66786, 0, 0, .5], 733: [0, .69444, 0, 0, .5], 915: [0, .68333, 0, 0, .625], 916: [0, .68333, 0, 0, .83334], 920: [0, .68333, 0, 0, .77778], 923: [0, .68333, 0, 0, .69445], 926: [0, .68333, 0, 0, .66667], 928: [0, .68333, 0, 0, .75], 931: [0, .68333, 0, 0, .72222], 933: [0, .68333, 0, 0, .77778], 934: [0, .68333, 0, 0, .72222], 936: [0, .68333, 0, 0, .77778], 937: [0, .68333, 0, 0, .72222], 8211: [0, .43056, .02778, 0, .5], 8212: [0, .43056, .02778, 0, 1], 8216: [0, .69444, 0, 0, .27778], 8217: [0, .69444, 0, 0, .27778], 8220: [0, .69444, 0, 0, .5], 8221: [0, .69444, 0, 0, .5], 8224: [.19444, .69444, 0, 0, .44445], 8225: [.19444, .69444, 0, 0, .44445], 8230: [0, .123, 0, 0, 1.172], 8242: [0, .55556, 0, 0, .275], 8407: [0, .71444, .15382, 0, .5], 8463: [0, .68889, 0, 0, .54028], 8465: [0, .69444, 0, 0, .72222], 8467: [0, .69444, 0, .11111, .41667], 8472: [.19444, .43056, 0, .11111, .63646], 8476: [0, .69444, 0, 0, .72222], 8501: [0, .69444, 0, 0, .61111], 8592: [-.13313, .36687, 0, 0, 1], 8593: [.19444, .69444, 0, 0, .5], 8594: [-.13313, .36687, 0, 0, 1], 8595: [.19444, .69444, 0, 0, .5], 8596: [-.13313, .36687, 0, 0, 1], 8597: [.25, .75, 0, 0, .5], 8598: [.19444, .69444, 0, 0, 1], 8599: [.19444, .69444, 0, 0, 1], 8600: [.19444, .69444, 0, 0, 1], 8601: [.19444, .69444, 0, 0, 1], 8614: [.011, .511, 0, 0, 1], 8617: [.011, .511, 0, 0, 1.126], 8618: [.011, .511, 0, 0, 1.126], 8636: [-.13313, .36687, 0, 0, 1], 8637: [-.13313, .36687, 0, 0, 1], 8640: [-.13313, .36687, 0, 0, 1], 8641: [-.13313, .36687, 0, 0, 1], 8652: [.011, .671, 0, 0, 1], 8656: [-.13313, .36687, 0, 0, 1], 8657: [.19444, .69444, 0, 0, .61111], 8658: [-.13313, .36687, 0, 0, 1], 8659: [.19444, .69444, 0, 0, .61111], 8660: [-.13313, .36687, 0, 0, 1], 8661: [.25, .75, 0, 0, .61111], 8704: [0, .69444, 0, 0, .55556], 8706: [0, .69444, .05556, .08334, .5309], 8707: [0, .69444, 0, 0, .55556], 8709: [.05556, .75, 0, 0, .5], 8711: [0, .68333, 0, 0, .83334], 8712: [.0391, .5391, 0, 0, .66667], 8715: [.0391, .5391, 0, 0, .66667], 8722: [.08333, .58333, 0, 0, .77778], 8723: [.08333, .58333, 0, 0, .77778], 8725: [.25, .75, 0, 0, .5], 8726: [.25, .75, 0, 0, .5], 8727: [-.03472, .46528, 0, 0, .5], 8728: [-.05555, .44445, 0, 0, .5], 8729: [-.05555, .44445, 0, 0, .5], 8730: [.2, .8, 0, 0, .83334], 8733: [0, .43056, 0, 0, .77778], 8734: [0, .43056, 0, 0, 1], 8736: [0, .69224, 0, 0, .72222], 8739: [.25, .75, 0, 0, .27778], 8741: [.25, .75, 0, 0, .5], 8743: [0, .55556, 0, 0, .66667], 8744: [0, .55556, 0, 0, .66667], 8745: [0, .55556, 0, 0, .66667], 8746: [0, .55556, 0, 0, .66667], 8747: [.19444, .69444, .11111, 0, .41667], 8764: [-.13313, .36687, 0, 0, .77778], 8768: [.19444, .69444, 0, 0, .27778], 8771: [-.03625, .46375, 0, 0, .77778], 8773: [-.022, .589, 0, 0, .778], 8776: [-.01688, .48312, 0, 0, .77778], 8781: [-.03625, .46375, 0, 0, .77778], 8784: [-.133, .673, 0, 0, .778], 8801: [-.03625, .46375, 0, 0, .77778], 8804: [.13597, .63597, 0, 0, .77778], 8805: [.13597, .63597, 0, 0, .77778], 8810: [.0391, .5391, 0, 0, 1], 8811: [.0391, .5391, 0, 0, 1], 8826: [.0391, .5391, 0, 0, .77778], 8827: [.0391, .5391, 0, 0, .77778], 8834: [.0391, .5391, 0, 0, .77778], 8835: [.0391, .5391, 0, 0, .77778], 8838: [.13597, .63597, 0, 0, .77778], 8839: [.13597, .63597, 0, 0, .77778], 8846: [0, .55556, 0, 0, .66667], 8849: [.13597, .63597, 0, 0, .77778], 8850: [.13597, .63597, 0, 0, .77778], 8851: [0, .55556, 0, 0, .66667], 8852: [0, .55556, 0, 0, .66667], 8853: [.08333, .58333, 0, 0, .77778], 8854: [.08333, .58333, 0, 0, .77778], 8855: [.08333, .58333, 0, 0, .77778], 8856: [.08333, .58333, 0, 0, .77778], 8857: [.08333, .58333, 0, 0, .77778], 8866: [0, .69444, 0, 0, .61111], 8867: [0, .69444, 0, 0, .61111], 8868: [0, .69444, 0, 0, .77778], 8869: [0, .69444, 0, 0, .77778], 8872: [.249, .75, 0, 0, .867], 8900: [-.05555, .44445, 0, 0, .5], 8901: [-.05555, .44445, 0, 0, .27778], 8902: [-.03472, .46528, 0, 0, .5], 8904: [.005, .505, 0, 0, .9], 8942: [.03, .903, 0, 0, .278], 8943: [-.19, .313, 0, 0, 1.172], 8945: [-.1, .823, 0, 0, 1.282], 8968: [.25, .75, 0, 0, .44445], 8969: [.25, .75, 0, 0, .44445], 8970: [.25, .75, 0, 0, .44445], 8971: [.25, .75, 0, 0, .44445], 8994: [-.14236, .35764, 0, 0, 1], 8995: [-.14236, .35764, 0, 0, 1], 9136: [.244, .744, 0, 0, .412], 9137: [.244, .745, 0, 0, .412], 9651: [.19444, .69444, 0, 0, .88889], 9657: [-.03472, .46528, 0, 0, .5], 9661: [.19444, .69444, 0, 0, .88889], 9667: [-.03472, .46528, 0, 0, .5], 9711: [.19444, .69444, 0, 0, 1], 9824: [.12963, .69444, 0, 0, .77778], 9825: [.12963, .69444, 0, 0, .77778], 9826: [.12963, .69444, 0, 0, .77778], 9827: [.12963, .69444, 0, 0, .77778], 9837: [0, .75, 0, 0, .38889], 9838: [.19444, .69444, 0, 0, .38889], 9839: [.19444, .69444, 0, 0, .38889], 10216: [.25, .75, 0, 0, .38889], 10217: [.25, .75, 0, 0, .38889], 10222: [.244, .744, 0, 0, .412], 10223: [.244, .745, 0, 0, .412], 10229: [.011, .511, 0, 0, 1.609], 10230: [.011, .511, 0, 0, 1.638], 10231: [.011, .511, 0, 0, 1.859], 10232: [.024, .525, 0, 0, 1.609], 10233: [.024, .525, 0, 0, 1.638], 10234: [.024, .525, 0, 0, 1.858], 10236: [.011, .511, 0, 0, 1.638], 10815: [0, .68333, 0, 0, .75], 10927: [.13597, .63597, 0, 0, .77778], 10928: [.13597, .63597, 0, 0, .77778], 57376: [.19444, .69444, 0, 0, 0] }, "Math-BoldItalic": { 32: [0, 0, 0, 0, .25], 48: [0, .44444, 0, 0, .575], 49: [0, .44444, 0, 0, .575], 50: [0, .44444, 0, 0, .575], 51: [.19444, .44444, 0, 0, .575], 52: [.19444, .44444, 0, 0, .575], 53: [.19444, .44444, 0, 0, .575], 54: [0, .64444, 0, 0, .575], 55: [.19444, .44444, 0, 0, .575], 56: [0, .64444, 0, 0, .575], 57: [.19444, .44444, 0, 0, .575], 65: [0, .68611, 0, 0, .86944], 66: [0, .68611, .04835, 0, .8664], 67: [0, .68611, .06979, 0, .81694], 68: [0, .68611, .03194, 0, .93812], 69: [0, .68611, .05451, 0, .81007], 70: [0, .68611, .15972, 0, .68889], 71: [0, .68611, 0, 0, .88673], 72: [0, .68611, .08229, 0, .98229], 73: [0, .68611, .07778, 0, .51111], 74: [0, .68611, .10069, 0, .63125], 75: [0, .68611, .06979, 0, .97118], 76: [0, .68611, 0, 0, .75555], 77: [0, .68611, .11424, 0, 1.14201], 78: [0, .68611, .11424, 0, .95034], 79: [0, .68611, .03194, 0, .83666], 80: [0, .68611, .15972, 0, .72309], 81: [.19444, .68611, 0, 0, .86861], 82: [0, .68611, .00421, 0, .87235], 83: [0, .68611, .05382, 0, .69271], 84: [0, .68611, .15972, 0, .63663], 85: [0, .68611, .11424, 0, .80027], 86: [0, .68611, .25555, 0, .67778], 87: [0, .68611, .15972, 0, 1.09305], 88: [0, .68611, .07778, 0, .94722], 89: [0, .68611, .25555, 0, .67458], 90: [0, .68611, .06979, 0, .77257], 97: [0, .44444, 0, 0, .63287], 98: [0, .69444, 0, 0, .52083], 99: [0, .44444, 0, 0, .51342], 100: [0, .69444, 0, 0, .60972], 101: [0, .44444, 0, 0, .55361], 102: [.19444, .69444, .11042, 0, .56806], 103: [.19444, .44444, .03704, 0, .5449], 104: [0, .69444, 0, 0, .66759], 105: [0, .69326, 0, 0, .4048], 106: [.19444, .69326, .0622, 0, .47083], 107: [0, .69444, .01852, 0, .6037], 108: [0, .69444, .0088, 0, .34815], 109: [0, .44444, 0, 0, 1.0324], 110: [0, .44444, 0, 0, .71296], 111: [0, .44444, 0, 0, .58472], 112: [.19444, .44444, 0, 0, .60092], 113: [.19444, .44444, .03704, 0, .54213], 114: [0, .44444, .03194, 0, .5287], 115: [0, .44444, 0, 0, .53125], 116: [0, .63492, 0, 0, .41528], 117: [0, .44444, 0, 0, .68102], 118: [0, .44444, .03704, 0, .56666], 119: [0, .44444, .02778, 0, .83148], 120: [0, .44444, 0, 0, .65903], 121: [.19444, .44444, .03704, 0, .59028], 122: [0, .44444, .04213, 0, .55509], 160: [0, 0, 0, 0, .25], 915: [0, .68611, .15972, 0, .65694], 916: [0, .68611, 0, 0, .95833], 920: [0, .68611, .03194, 0, .86722], 923: [0, .68611, 0, 0, .80555], 926: [0, .68611, .07458, 0, .84125], 928: [0, .68611, .08229, 0, .98229], 931: [0, .68611, .05451, 0, .88507], 933: [0, .68611, .15972, 0, .67083], 934: [0, .68611, 0, 0, .76666], 936: [0, .68611, .11653, 0, .71402], 937: [0, .68611, .04835, 0, .8789], 945: [0, .44444, 0, 0, .76064], 946: [.19444, .69444, .03403, 0, .65972], 947: [.19444, .44444, .06389, 0, .59003], 948: [0, .69444, .03819, 0, .52222], 949: [0, .44444, 0, 0, .52882], 950: [.19444, .69444, .06215, 0, .50833], 951: [.19444, .44444, .03704, 0, .6], 952: [0, .69444, .03194, 0, .5618], 953: [0, .44444, 0, 0, .41204], 954: [0, .44444, 0, 0, .66759], 955: [0, .69444, 0, 0, .67083], 956: [.19444, .44444, 0, 0, .70787], 957: [0, .44444, .06898, 0, .57685], 958: [.19444, .69444, .03021, 0, .50833], 959: [0, .44444, 0, 0, .58472], 960: [0, .44444, .03704, 0, .68241], 961: [.19444, .44444, 0, 0, .6118], 962: [.09722, .44444, .07917, 0, .42361], 963: [0, .44444, .03704, 0, .68588], 964: [0, .44444, .13472, 0, .52083], 965: [0, .44444, .03704, 0, .63055], 966: [.19444, .44444, 0, 0, .74722], 967: [.19444, .44444, 0, 0, .71805], 968: [.19444, .69444, .03704, 0, .75833], 969: [0, .44444, .03704, 0, .71782], 977: [0, .69444, 0, 0, .69155], 981: [.19444, .69444, 0, 0, .7125], 982: [0, .44444, .03194, 0, .975], 1009: [.19444, .44444, 0, 0, .6118], 1013: [0, .44444, 0, 0, .48333], 57649: [0, .44444, 0, 0, .39352], 57911: [.19444, .44444, 0, 0, .43889] }, "Math-Italic": { 32: [0, 0, 0, 0, .25], 48: [0, .43056, 0, 0, .5], 49: [0, .43056, 0, 0, .5], 50: [0, .43056, 0, 0, .5], 51: [.19444, .43056, 0, 0, .5], 52: [.19444, .43056, 0, 0, .5], 53: [.19444, .43056, 0, 0, .5], 54: [0, .64444, 0, 0, .5], 55: [.19444, .43056, 0, 0, .5], 56: [0, .64444, 0, 0, .5], 57: [.19444, .43056, 0, 0, .5], 65: [0, .68333, 0, .13889, .75], 66: [0, .68333, .05017, .08334, .75851], 67: [0, .68333, .07153, .08334, .71472], 68: [0, .68333, .02778, .05556, .82792], 69: [0, .68333, .05764, .08334, .7382], 70: [0, .68333, .13889, .08334, .64306], 71: [0, .68333, 0, .08334, .78625], 72: [0, .68333, .08125, .05556, .83125], 73: [0, .68333, .07847, .11111, .43958], 74: [0, .68333, .09618, .16667, .55451], 75: [0, .68333, .07153, .05556, .84931], 76: [0, .68333, 0, .02778, .68056], 77: [0, .68333, .10903, .08334, .97014], 78: [0, .68333, .10903, .08334, .80347], 79: [0, .68333, .02778, .08334, .76278], 80: [0, .68333, .13889, .08334, .64201], 81: [.19444, .68333, 0, .08334, .79056], 82: [0, .68333, .00773, .08334, .75929], 83: [0, .68333, .05764, .08334, .6132], 84: [0, .68333, .13889, .08334, .58438], 85: [0, .68333, .10903, .02778, .68278], 86: [0, .68333, .22222, 0, .58333], 87: [0, .68333, .13889, 0, .94445], 88: [0, .68333, .07847, .08334, .82847], 89: [0, .68333, .22222, 0, .58056], 90: [0, .68333, .07153, .08334, .68264], 97: [0, .43056, 0, 0, .52859], 98: [0, .69444, 0, 0, .42917], 99: [0, .43056, 0, .05556, .43276], 100: [0, .69444, 0, .16667, .52049], 101: [0, .43056, 0, .05556, .46563], 102: [.19444, .69444, .10764, .16667, .48959], 103: [.19444, .43056, .03588, .02778, .47697], 104: [0, .69444, 0, 0, .57616], 105: [0, .65952, 0, 0, .34451], 106: [.19444, .65952, .05724, 0, .41181], 107: [0, .69444, .03148, 0, .5206], 108: [0, .69444, .01968, .08334, .29838], 109: [0, .43056, 0, 0, .87801], 110: [0, .43056, 0, 0, .60023], 111: [0, .43056, 0, .05556, .48472], 112: [.19444, .43056, 0, .08334, .50313], 113: [.19444, .43056, .03588, .08334, .44641], 114: [0, .43056, .02778, .05556, .45116], 115: [0, .43056, 0, .05556, .46875], 116: [0, .61508, 0, .08334, .36111], 117: [0, .43056, 0, .02778, .57246], 118: [0, .43056, .03588, .02778, .48472], 119: [0, .43056, .02691, .08334, .71592], 120: [0, .43056, 0, .02778, .57153], 121: [.19444, .43056, .03588, .05556, .49028], 122: [0, .43056, .04398, .05556, .46505], 160: [0, 0, 0, 0, .25], 915: [0, .68333, .13889, .08334, .61528], 916: [0, .68333, 0, .16667, .83334], 920: [0, .68333, .02778, .08334, .76278], 923: [0, .68333, 0, .16667, .69445], 926: [0, .68333, .07569, .08334, .74236], 928: [0, .68333, .08125, .05556, .83125], 931: [0, .68333, .05764, .08334, .77986], 933: [0, .68333, .13889, .05556, .58333], 934: [0, .68333, 0, .08334, .66667], 936: [0, .68333, .11, .05556, .61222], 937: [0, .68333, .05017, .08334, .7724], 945: [0, .43056, .0037, .02778, .6397], 946: [.19444, .69444, .05278, .08334, .56563], 947: [.19444, .43056, .05556, 0, .51773], 948: [0, .69444, .03785, .05556, .44444], 949: [0, .43056, 0, .08334, .46632], 950: [.19444, .69444, .07378, .08334, .4375], 951: [.19444, .43056, .03588, .05556, .49653], 952: [0, .69444, .02778, .08334, .46944], 953: [0, .43056, 0, .05556, .35394], 954: [0, .43056, 0, 0, .57616], 955: [0, .69444, 0, 0, .58334], 956: [.19444, .43056, 0, .02778, .60255], 957: [0, .43056, .06366, .02778, .49398], 958: [.19444, .69444, .04601, .11111, .4375], 959: [0, .43056, 0, .05556, .48472], 960: [0, .43056, .03588, 0, .57003], 961: [.19444, .43056, 0, .08334, .51702], 962: [.09722, .43056, .07986, .08334, .36285], 963: [0, .43056, .03588, 0, .57141], 964: [0, .43056, .1132, .02778, .43715], 965: [0, .43056, .03588, .02778, .54028], 966: [.19444, .43056, 0, .08334, .65417], 967: [.19444, .43056, 0, .05556, .62569], 968: [.19444, .69444, .03588, .11111, .65139], 969: [0, .43056, .03588, 0, .62245], 977: [0, .69444, 0, .08334, .59144], 981: [.19444, .69444, 0, .08334, .59583], 982: [0, .43056, .02778, 0, .82813], 1009: [.19444, .43056, 0, .08334, .51702], 1013: [0, .43056, 0, .05556, .4059], 57649: [0, .43056, 0, .02778, .32246], 57911: [.19444, .43056, 0, .08334, .38403] }, "SansSerif-Bold": { 32: [0, 0, 0, 0, .25], 33: [0, .69444, 0, 0, .36667], 34: [0, .69444, 0, 0, .55834], 35: [.19444, .69444, 0, 0, .91667], 36: [.05556, .75, 0, 0, .55], 37: [.05556, .75, 0, 0, 1.02912], 38: [0, .69444, 0, 0, .83056], 39: [0, .69444, 0, 0, .30556], 40: [.25, .75, 0, 0, .42778], 41: [.25, .75, 0, 0, .42778], 42: [0, .75, 0, 0, .55], 43: [.11667, .61667, 0, 0, .85556], 44: [.10556, .13056, 0, 0, .30556], 45: [0, .45833, 0, 0, .36667], 46: [0, .13056, 0, 0, .30556], 47: [.25, .75, 0, 0, .55], 48: [0, .69444, 0, 0, .55], 49: [0, .69444, 0, 0, .55], 50: [0, .69444, 0, 0, .55], 51: [0, .69444, 0, 0, .55], 52: [0, .69444, 0, 0, .55], 53: [0, .69444, 0, 0, .55], 54: [0, .69444, 0, 0, .55], 55: [0, .69444, 0, 0, .55], 56: [0, .69444, 0, 0, .55], 57: [0, .69444, 0, 0, .55], 58: [0, .45833, 0, 0, .30556], 59: [.10556, .45833, 0, 0, .30556], 61: [-.09375, .40625, 0, 0, .85556], 63: [0, .69444, 0, 0, .51945], 64: [0, .69444, 0, 0, .73334], 65: [0, .69444, 0, 0, .73334], 66: [0, .69444, 0, 0, .73334], 67: [0, .69444, 0, 0, .70278], 68: [0, .69444, 0, 0, .79445], 69: [0, .69444, 0, 0, .64167], 70: [0, .69444, 0, 0, .61111], 71: [0, .69444, 0, 0, .73334], 72: [0, .69444, 0, 0, .79445], 73: [0, .69444, 0, 0, .33056], 74: [0, .69444, 0, 0, .51945], 75: [0, .69444, 0, 0, .76389], 76: [0, .69444, 0, 0, .58056], 77: [0, .69444, 0, 0, .97778], 78: [0, .69444, 0, 0, .79445], 79: [0, .69444, 0, 0, .79445], 80: [0, .69444, 0, 0, .70278], 81: [.10556, .69444, 0, 0, .79445], 82: [0, .69444, 0, 0, .70278], 83: [0, .69444, 0, 0, .61111], 84: [0, .69444, 0, 0, .73334], 85: [0, .69444, 0, 0, .76389], 86: [0, .69444, .01528, 0, .73334], 87: [0, .69444, .01528, 0, 1.03889], 88: [0, .69444, 0, 0, .73334], 89: [0, .69444, .0275, 0, .73334], 90: [0, .69444, 0, 0, .67223], 91: [.25, .75, 0, 0, .34306], 93: [.25, .75, 0, 0, .34306], 94: [0, .69444, 0, 0, .55], 95: [.35, .10833, .03056, 0, .55], 97: [0, .45833, 0, 0, .525], 98: [0, .69444, 0, 0, .56111], 99: [0, .45833, 0, 0, .48889], 100: [0, .69444, 0, 0, .56111], 101: [0, .45833, 0, 0, .51111], 102: [0, .69444, .07639, 0, .33611], 103: [.19444, .45833, .01528, 0, .55], 104: [0, .69444, 0, 0, .56111], 105: [0, .69444, 0, 0, .25556], 106: [.19444, .69444, 0, 0, .28611], 107: [0, .69444, 0, 0, .53056], 108: [0, .69444, 0, 0, .25556], 109: [0, .45833, 0, 0, .86667], 110: [0, .45833, 0, 0, .56111], 111: [0, .45833, 0, 0, .55], 112: [.19444, .45833, 0, 0, .56111], 113: [.19444, .45833, 0, 0, .56111], 114: [0, .45833, .01528, 0, .37222], 115: [0, .45833, 0, 0, .42167], 116: [0, .58929, 0, 0, .40417], 117: [0, .45833, 0, 0, .56111], 118: [0, .45833, .01528, 0, .5], 119: [0, .45833, .01528, 0, .74445], 120: [0, .45833, 0, 0, .5], 121: [.19444, .45833, .01528, 0, .5], 122: [0, .45833, 0, 0, .47639], 126: [.35, .34444, 0, 0, .55], 160: [0, 0, 0, 0, .25], 168: [0, .69444, 0, 0, .55], 176: [0, .69444, 0, 0, .73334], 180: [0, .69444, 0, 0, .55], 184: [.17014, 0, 0, 0, .48889], 305: [0, .45833, 0, 0, .25556], 567: [.19444, .45833, 0, 0, .28611], 710: [0, .69444, 0, 0, .55], 711: [0, .63542, 0, 0, .55], 713: [0, .63778, 0, 0, .55], 728: [0, .69444, 0, 0, .55], 729: [0, .69444, 0, 0, .30556], 730: [0, .69444, 0, 0, .73334], 732: [0, .69444, 0, 0, .55], 733: [0, .69444, 0, 0, .55], 915: [0, .69444, 0, 0, .58056], 916: [0, .69444, 0, 0, .91667], 920: [0, .69444, 0, 0, .85556], 923: [0, .69444, 0, 0, .67223], 926: [0, .69444, 0, 0, .73334], 928: [0, .69444, 0, 0, .79445], 931: [0, .69444, 0, 0, .79445], 933: [0, .69444, 0, 0, .85556], 934: [0, .69444, 0, 0, .79445], 936: [0, .69444, 0, 0, .85556], 937: [0, .69444, 0, 0, .79445], 8211: [0, .45833, .03056, 0, .55], 8212: [0, .45833, .03056, 0, 1.10001], 8216: [0, .69444, 0, 0, .30556], 8217: [0, .69444, 0, 0, .30556], 8220: [0, .69444, 0, 0, .55834], 8221: [0, .69444, 0, 0, .55834] }, "SansSerif-Italic": { 32: [0, 0, 0, 0, .25], 33: [0, .69444, .05733, 0, .31945], 34: [0, .69444, .00316, 0, .5], 35: [.19444, .69444, .05087, 0, .83334], 36: [.05556, .75, .11156, 0, .5], 37: [.05556, .75, .03126, 0, .83334], 38: [0, .69444, .03058, 0, .75834], 39: [0, .69444, .07816, 0, .27778], 40: [.25, .75, .13164, 0, .38889], 41: [.25, .75, .02536, 0, .38889], 42: [0, .75, .11775, 0, .5], 43: [.08333, .58333, .02536, 0, .77778], 44: [.125, .08333, 0, 0, .27778], 45: [0, .44444, .01946, 0, .33333], 46: [0, .08333, 0, 0, .27778], 47: [.25, .75, .13164, 0, .5], 48: [0, .65556, .11156, 0, .5], 49: [0, .65556, .11156, 0, .5], 50: [0, .65556, .11156, 0, .5], 51: [0, .65556, .11156, 0, .5], 52: [0, .65556, .11156, 0, .5], 53: [0, .65556, .11156, 0, .5], 54: [0, .65556, .11156, 0, .5], 55: [0, .65556, .11156, 0, .5], 56: [0, .65556, .11156, 0, .5], 57: [0, .65556, .11156, 0, .5], 58: [0, .44444, .02502, 0, .27778], 59: [.125, .44444, .02502, 0, .27778], 61: [-.13, .37, .05087, 0, .77778], 63: [0, .69444, .11809, 0, .47222], 64: [0, .69444, .07555, 0, .66667], 65: [0, .69444, 0, 0, .66667], 66: [0, .69444, .08293, 0, .66667], 67: [0, .69444, .11983, 0, .63889], 68: [0, .69444, .07555, 0, .72223], 69: [0, .69444, .11983, 0, .59722], 70: [0, .69444, .13372, 0, .56945], 71: [0, .69444, .11983, 0, .66667], 72: [0, .69444, .08094, 0, .70834], 73: [0, .69444, .13372, 0, .27778], 74: [0, .69444, .08094, 0, .47222], 75: [0, .69444, .11983, 0, .69445], 76: [0, .69444, 0, 0, .54167], 77: [0, .69444, .08094, 0, .875], 78: [0, .69444, .08094, 0, .70834], 79: [0, .69444, .07555, 0, .73611], 80: [0, .69444, .08293, 0, .63889], 81: [.125, .69444, .07555, 0, .73611], 82: [0, .69444, .08293, 0, .64584], 83: [0, .69444, .09205, 0, .55556], 84: [0, .69444, .13372, 0, .68056], 85: [0, .69444, .08094, 0, .6875], 86: [0, .69444, .1615, 0, .66667], 87: [0, .69444, .1615, 0, .94445], 88: [0, .69444, .13372, 0, .66667], 89: [0, .69444, .17261, 0, .66667], 90: [0, .69444, .11983, 0, .61111], 91: [.25, .75, .15942, 0, .28889], 93: [.25, .75, .08719, 0, .28889], 94: [0, .69444, .0799, 0, .5], 95: [.35, .09444, .08616, 0, .5], 97: [0, .44444, .00981, 0, .48056], 98: [0, .69444, .03057, 0, .51667], 99: [0, .44444, .08336, 0, .44445], 100: [0, .69444, .09483, 0, .51667], 101: [0, .44444, .06778, 0, .44445], 102: [0, .69444, .21705, 0, .30556], 103: [.19444, .44444, .10836, 0, .5], 104: [0, .69444, .01778, 0, .51667], 105: [0, .67937, .09718, 0, .23889], 106: [.19444, .67937, .09162, 0, .26667], 107: [0, .69444, .08336, 0, .48889], 108: [0, .69444, .09483, 0, .23889], 109: [0, .44444, .01778, 0, .79445], 110: [0, .44444, .01778, 0, .51667], 111: [0, .44444, .06613, 0, .5], 112: [.19444, .44444, .0389, 0, .51667], 113: [.19444, .44444, .04169, 0, .51667], 114: [0, .44444, .10836, 0, .34167], 115: [0, .44444, .0778, 0, .38333], 116: [0, .57143, .07225, 0, .36111], 117: [0, .44444, .04169, 0, .51667], 118: [0, .44444, .10836, 0, .46111], 119: [0, .44444, .10836, 0, .68334], 120: [0, .44444, .09169, 0, .46111], 121: [.19444, .44444, .10836, 0, .46111], 122: [0, .44444, .08752, 0, .43472], 126: [.35, .32659, .08826, 0, .5], 160: [0, 0, 0, 0, .25], 168: [0, .67937, .06385, 0, .5], 176: [0, .69444, 0, 0, .73752], 184: [.17014, 0, 0, 0, .44445], 305: [0, .44444, .04169, 0, .23889], 567: [.19444, .44444, .04169, 0, .26667], 710: [0, .69444, .0799, 0, .5], 711: [0, .63194, .08432, 0, .5], 713: [0, .60889, .08776, 0, .5], 714: [0, .69444, .09205, 0, .5], 715: [0, .69444, 0, 0, .5], 728: [0, .69444, .09483, 0, .5], 729: [0, .67937, .07774, 0, .27778], 730: [0, .69444, 0, 0, .73752], 732: [0, .67659, .08826, 0, .5], 733: [0, .69444, .09205, 0, .5], 915: [0, .69444, .13372, 0, .54167], 916: [0, .69444, 0, 0, .83334], 920: [0, .69444, .07555, 0, .77778], 923: [0, .69444, 0, 0, .61111], 926: [0, .69444, .12816, 0, .66667], 928: [0, .69444, .08094, 0, .70834], 931: [0, .69444, .11983, 0, .72222], 933: [0, .69444, .09031, 0, .77778], 934: [0, .69444, .04603, 0, .72222], 936: [0, .69444, .09031, 0, .77778], 937: [0, .69444, .08293, 0, .72222], 8211: [0, .44444, .08616, 0, .5], 8212: [0, .44444, .08616, 0, 1], 8216: [0, .69444, .07816, 0, .27778], 8217: [0, .69444, .07816, 0, .27778], 8220: [0, .69444, .14205, 0, .5], 8221: [0, .69444, .00316, 0, .5] }, "SansSerif-Regular": { 32: [0, 0, 0, 0, .25], 33: [0, .69444, 0, 0, .31945], 34: [0, .69444, 0, 0, .5], 35: [.19444, .69444, 0, 0, .83334], 36: [.05556, .75, 0, 0, .5], 37: [.05556, .75, 0, 0, .83334], 38: [0, .69444, 0, 0, .75834], 39: [0, .69444, 0, 0, .27778], 40: [.25, .75, 0, 0, .38889], 41: [.25, .75, 0, 0, .38889], 42: [0, .75, 0, 0, .5], 43: [.08333, .58333, 0, 0, .77778], 44: [.125, .08333, 0, 0, .27778], 45: [0, .44444, 0, 0, .33333], 46: [0, .08333, 0, 0, .27778], 47: [.25, .75, 0, 0, .5], 48: [0, .65556, 0, 0, .5], 49: [0, .65556, 0, 0, .5], 50: [0, .65556, 0, 0, .5], 51: [0, .65556, 0, 0, .5], 52: [0, .65556, 0, 0, .5], 53: [0, .65556, 0, 0, .5], 54: [0, .65556, 0, 0, .5], 55: [0, .65556, 0, 0, .5], 56: [0, .65556, 0, 0, .5], 57: [0, .65556, 0, 0, .5], 58: [0, .44444, 0, 0, .27778], 59: [.125, .44444, 0, 0, .27778], 61: [-.13, .37, 0, 0, .77778], 63: [0, .69444, 0, 0, .47222], 64: [0, .69444, 0, 0, .66667], 65: [0, .69444, 0, 0, .66667], 66: [0, .69444, 0, 0, .66667], 67: [0, .69444, 0, 0, .63889], 68: [0, .69444, 0, 0, .72223], 69: [0, .69444, 0, 0, .59722], 70: [0, .69444, 0, 0, .56945], 71: [0, .69444, 0, 0, .66667], 72: [0, .69444, 0, 0, .70834], 73: [0, .69444, 0, 0, .27778], 74: [0, .69444, 0, 0, .47222], 75: [0, .69444, 0, 0, .69445], 76: [0, .69444, 0, 0, .54167], 77: [0, .69444, 0, 0, .875], 78: [0, .69444, 0, 0, .70834], 79: [0, .69444, 0, 0, .73611], 80: [0, .69444, 0, 0, .63889], 81: [.125, .69444, 0, 0, .73611], 82: [0, .69444, 0, 0, .64584], 83: [0, .69444, 0, 0, .55556], 84: [0, .69444, 0, 0, .68056], 85: [0, .69444, 0, 0, .6875], 86: [0, .69444, .01389, 0, .66667], 87: [0, .69444, .01389, 0, .94445], 88: [0, .69444, 0, 0, .66667], 89: [0, .69444, .025, 0, .66667], 90: [0, .69444, 0, 0, .61111], 91: [.25, .75, 0, 0, .28889], 93: [.25, .75, 0, 0, .28889], 94: [0, .69444, 0, 0, .5], 95: [.35, .09444, .02778, 0, .5], 97: [0, .44444, 0, 0, .48056], 98: [0, .69444, 0, 0, .51667], 99: [0, .44444, 0, 0, .44445], 100: [0, .69444, 0, 0, .51667], 101: [0, .44444, 0, 0, .44445], 102: [0, .69444, .06944, 0, .30556], 103: [.19444, .44444, .01389, 0, .5], 104: [0, .69444, 0, 0, .51667], 105: [0, .67937, 0, 0, .23889], 106: [.19444, .67937, 0, 0, .26667], 107: [0, .69444, 0, 0, .48889], 108: [0, .69444, 0, 0, .23889], 109: [0, .44444, 0, 0, .79445], 110: [0, .44444, 0, 0, .51667], 111: [0, .44444, 0, 0, .5], 112: [.19444, .44444, 0, 0, .51667], 113: [.19444, .44444, 0, 0, .51667], 114: [0, .44444, .01389, 0, .34167], 115: [0, .44444, 0, 0, .38333], 116: [0, .57143, 0, 0, .36111], 117: [0, .44444, 0, 0, .51667], 118: [0, .44444, .01389, 0, .46111], 119: [0, .44444, .01389, 0, .68334], 120: [0, .44444, 0, 0, .46111], 121: [.19444, .44444, .01389, 0, .46111], 122: [0, .44444, 0, 0, .43472], 126: [.35, .32659, 0, 0, .5], 160: [0, 0, 0, 0, .25], 168: [0, .67937, 0, 0, .5], 176: [0, .69444, 0, 0, .66667], 184: [.17014, 0, 0, 0, .44445], 305: [0, .44444, 0, 0, .23889], 567: [.19444, .44444, 0, 0, .26667], 710: [0, .69444, 0, 0, .5], 711: [0, .63194, 0, 0, .5], 713: [0, .60889, 0, 0, .5], 714: [0, .69444, 0, 0, .5], 715: [0, .69444, 0, 0, .5], 728: [0, .69444, 0, 0, .5], 729: [0, .67937, 0, 0, .27778], 730: [0, .69444, 0, 0, .66667], 732: [0, .67659, 0, 0, .5], 733: [0, .69444, 0, 0, .5], 915: [0, .69444, 0, 0, .54167], 916: [0, .69444, 0, 0, .83334], 920: [0, .69444, 0, 0, .77778], 923: [0, .69444, 0, 0, .61111], 926: [0, .69444, 0, 0, .66667], 928: [0, .69444, 0, 0, .70834], 931: [0, .69444, 0, 0, .72222], 933: [0, .69444, 0, 0, .77778], 934: [0, .69444, 0, 0, .72222], 936: [0, .69444, 0, 0, .77778], 937: [0, .69444, 0, 0, .72222], 8211: [0, .44444, .02778, 0, .5], 8212: [0, .44444, .02778, 0, 1], 8216: [0, .69444, 0, 0, .27778], 8217: [0, .69444, 0, 0, .27778], 8220: [0, .69444, 0, 0, .5], 8221: [0, .69444, 0, 0, .5] }, "Script-Regular": { 32: [0, 0, 0, 0, .25], 65: [0, .7, .22925, 0, .80253], 66: [0, .7, .04087, 0, .90757], 67: [0, .7, .1689, 0, .66619], 68: [0, .7, .09371, 0, .77443], 69: [0, .7, .18583, 0, .56162], 70: [0, .7, .13634, 0, .89544], 71: [0, .7, .17322, 0, .60961], 72: [0, .7, .29694, 0, .96919], 73: [0, .7, .19189, 0, .80907], 74: [.27778, .7, .19189, 0, 1.05159], 75: [0, .7, .31259, 0, .91364], 76: [0, .7, .19189, 0, .87373], 77: [0, .7, .15981, 0, 1.08031], 78: [0, .7, .3525, 0, .9015], 79: [0, .7, .08078, 0, .73787], 80: [0, .7, .08078, 0, 1.01262], 81: [0, .7, .03305, 0, .88282], 82: [0, .7, .06259, 0, .85], 83: [0, .7, .19189, 0, .86767], 84: [0, .7, .29087, 0, .74697], 85: [0, .7, .25815, 0, .79996], 86: [0, .7, .27523, 0, .62204], 87: [0, .7, .27523, 0, .80532], 88: [0, .7, .26006, 0, .94445], 89: [0, .7, .2939, 0, .70961], 90: [0, .7, .24037, 0, .8212], 160: [0, 0, 0, 0, .25] }, "Size1-Regular": { 32: [0, 0, 0, 0, .25], 40: [.35001, .85, 0, 0, .45834], 41: [.35001, .85, 0, 0, .45834], 47: [.35001, .85, 0, 0, .57778], 91: [.35001, .85, 0, 0, .41667], 92: [.35001, .85, 0, 0, .57778], 93: [.35001, .85, 0, 0, .41667], 123: [.35001, .85, 0, 0, .58334], 125: [.35001, .85, 0, 0, .58334], 160: [0, 0, 0, 0, .25], 710: [0, .72222, 0, 0, .55556], 732: [0, .72222, 0, 0, .55556], 770: [0, .72222, 0, 0, .55556], 771: [0, .72222, 0, 0, .55556], 8214: [-99e-5, .601, 0, 0, .77778], 8593: [1e-5, .6, 0, 0, .66667], 8595: [1e-5, .6, 0, 0, .66667], 8657: [1e-5, .6, 0, 0, .77778], 8659: [1e-5, .6, 0, 0, .77778], 8719: [.25001, .75, 0, 0, .94445], 8720: [.25001, .75, 0, 0, .94445], 8721: [.25001, .75, 0, 0, 1.05556], 8730: [.35001, .85, 0, 0, 1], 8739: [-.00599, .606, 0, 0, .33333], 8741: [-.00599, .606, 0, 0, .55556], 8747: [.30612, .805, .19445, 0, .47222], 8748: [.306, .805, .19445, 0, .47222], 8749: [.306, .805, .19445, 0, .47222], 8750: [.30612, .805, .19445, 0, .47222], 8896: [.25001, .75, 0, 0, .83334], 8897: [.25001, .75, 0, 0, .83334], 8898: [.25001, .75, 0, 0, .83334], 8899: [.25001, .75, 0, 0, .83334], 8968: [.35001, .85, 0, 0, .47222], 8969: [.35001, .85, 0, 0, .47222], 8970: [.35001, .85, 0, 0, .47222], 8971: [.35001, .85, 0, 0, .47222], 9168: [-99e-5, .601, 0, 0, .66667], 10216: [.35001, .85, 0, 0, .47222], 10217: [.35001, .85, 0, 0, .47222], 10752: [.25001, .75, 0, 0, 1.11111], 10753: [.25001, .75, 0, 0, 1.11111], 10754: [.25001, .75, 0, 0, 1.11111], 10756: [.25001, .75, 0, 0, .83334], 10758: [.25001, .75, 0, 0, .83334] }, "Size2-Regular": { 32: [0, 0, 0, 0, .25], 40: [.65002, 1.15, 0, 0, .59722], 41: [.65002, 1.15, 0, 0, .59722], 47: [.65002, 1.15, 0, 0, .81111], 91: [.65002, 1.15, 0, 0, .47222], 92: [.65002, 1.15, 0, 0, .81111], 93: [.65002, 1.15, 0, 0, .47222], 123: [.65002, 1.15, 0, 0, .66667], 125: [.65002, 1.15, 0, 0, .66667], 160: [0, 0, 0, 0, .25], 710: [0, .75, 0, 0, 1], 732: [0, .75, 0, 0, 1], 770: [0, .75, 0, 0, 1], 771: [0, .75, 0, 0, 1], 8719: [.55001, 1.05, 0, 0, 1.27778], 8720: [.55001, 1.05, 0, 0, 1.27778], 8721: [.55001, 1.05, 0, 0, 1.44445], 8730: [.65002, 1.15, 0, 0, 1], 8747: [.86225, 1.36, .44445, 0, .55556], 8748: [.862, 1.36, .44445, 0, .55556], 8749: [.862, 1.36, .44445, 0, .55556], 8750: [.86225, 1.36, .44445, 0, .55556], 8896: [.55001, 1.05, 0, 0, 1.11111], 8897: [.55001, 1.05, 0, 0, 1.11111], 8898: [.55001, 1.05, 0, 0, 1.11111], 8899: [.55001, 1.05, 0, 0, 1.11111], 8968: [.65002, 1.15, 0, 0, .52778], 8969: [.65002, 1.15, 0, 0, .52778], 8970: [.65002, 1.15, 0, 0, .52778], 8971: [.65002, 1.15, 0, 0, .52778], 10216: [.65002, 1.15, 0, 0, .61111], 10217: [.65002, 1.15, 0, 0, .61111], 10752: [.55001, 1.05, 0, 0, 1.51112], 10753: [.55001, 1.05, 0, 0, 1.51112], 10754: [.55001, 1.05, 0, 0, 1.51112], 10756: [.55001, 1.05, 0, 0, 1.11111], 10758: [.55001, 1.05, 0, 0, 1.11111] }, "Size3-Regular": { 32: [0, 0, 0, 0, .25], 40: [.95003, 1.45, 0, 0, .73611], 41: [.95003, 1.45, 0, 0, .73611], 47: [.95003, 1.45, 0, 0, 1.04445], 91: [.95003, 1.45, 0, 0, .52778], 92: [.95003, 1.45, 0, 0, 1.04445], 93: [.95003, 1.45, 0, 0, .52778], 123: [.95003, 1.45, 0, 0, .75], 125: [.95003, 1.45, 0, 0, .75], 160: [0, 0, 0, 0, .25], 710: [0, .75, 0, 0, 1.44445], 732: [0, .75, 0, 0, 1.44445], 770: [0, .75, 0, 0, 1.44445], 771: [0, .75, 0, 0, 1.44445], 8730: [.95003, 1.45, 0, 0, 1], 8968: [.95003, 1.45, 0, 0, .58334], 8969: [.95003, 1.45, 0, 0, .58334], 8970: [.95003, 1.45, 0, 0, .58334], 8971: [.95003, 1.45, 0, 0, .58334], 10216: [.95003, 1.45, 0, 0, .75], 10217: [.95003, 1.45, 0, 0, .75] }, "Size4-Regular": { 32: [0, 0, 0, 0, .25], 40: [1.25003, 1.75, 0, 0, .79167], 41: [1.25003, 1.75, 0, 0, .79167], 47: [1.25003, 1.75, 0, 0, 1.27778], 91: [1.25003, 1.75, 0, 0, .58334], 92: [1.25003, 1.75, 0, 0, 1.27778], 93: [1.25003, 1.75, 0, 0, .58334], 123: [1.25003, 1.75, 0, 0, .80556], 125: [1.25003, 1.75, 0, 0, .80556], 160: [0, 0, 0, 0, .25], 710: [0, .825, 0, 0, 1.8889], 732: [0, .825, 0, 0, 1.8889], 770: [0, .825, 0, 0, 1.8889], 771: [0, .825, 0, 0, 1.8889], 8730: [1.25003, 1.75, 0, 0, 1], 8968: [1.25003, 1.75, 0, 0, .63889], 8969: [1.25003, 1.75, 0, 0, .63889], 8970: [1.25003, 1.75, 0, 0, .63889], 8971: [1.25003, 1.75, 0, 0, .63889], 9115: [.64502, 1.155, 0, 0, .875], 9116: [1e-5, .6, 0, 0, .875], 9117: [.64502, 1.155, 0, 0, .875], 9118: [.64502, 1.155, 0, 0, .875], 9119: [1e-5, .6, 0, 0, .875], 9120: [.64502, 1.155, 0, 0, .875], 9121: [.64502, 1.155, 0, 0, .66667], 9122: [-99e-5, .601, 0, 0, .66667], 9123: [.64502, 1.155, 0, 0, .66667], 9124: [.64502, 1.155, 0, 0, .66667], 9125: [-99e-5, .601, 0, 0, .66667], 9126: [.64502, 1.155, 0, 0, .66667], 9127: [1e-5, .9, 0, 0, .88889], 9128: [.65002, 1.15, 0, 0, .88889], 9129: [.90001, 0, 0, 0, .88889], 9130: [0, .3, 0, 0, .88889], 9131: [1e-5, .9, 0, 0, .88889], 9132: [.65002, 1.15, 0, 0, .88889], 9133: [.90001, 0, 0, 0, .88889], 9143: [.88502, .915, 0, 0, 1.05556], 10216: [1.25003, 1.75, 0, 0, .80556], 10217: [1.25003, 1.75, 0, 0, .80556], 57344: [-.00499, .605, 0, 0, 1.05556], 57345: [-.00499, .605, 0, 0, 1.05556], 57680: [0, .12, 0, 0, .45], 57681: [0, .12, 0, 0, .45], 57682: [0, .12, 0, 0, .45], 57683: [0, .12, 0, 0, .45] }, "Typewriter-Regular": { 32: [0, 0, 0, 0, .525], 33: [0, .61111, 0, 0, .525], 34: [0, .61111, 0, 0, .525], 35: [0, .61111, 0, 0, .525], 36: [.08333, .69444, 0, 0, .525], 37: [.08333, .69444, 0, 0, .525], 38: [0, .61111, 0, 0, .525], 39: [0, .61111, 0, 0, .525], 40: [.08333, .69444, 0, 0, .525], 41: [.08333, .69444, 0, 0, .525], 42: [0, .52083, 0, 0, .525], 43: [-.08056, .53055, 0, 0, .525], 44: [.13889, .125, 0, 0, .525], 45: [-.08056, .53055, 0, 0, .525], 46: [0, .125, 0, 0, .525], 47: [.08333, .69444, 0, 0, .525], 48: [0, .61111, 0, 0, .525], 49: [0, .61111, 0, 0, .525], 50: [0, .61111, 0, 0, .525], 51: [0, .61111, 0, 0, .525], 52: [0, .61111, 0, 0, .525], 53: [0, .61111, 0, 0, .525], 54: [0, .61111, 0, 0, .525], 55: [0, .61111, 0, 0, .525], 56: [0, .61111, 0, 0, .525], 57: [0, .61111, 0, 0, .525], 58: [0, .43056, 0, 0, .525], 59: [.13889, .43056, 0, 0, .525], 60: [-.05556, .55556, 0, 0, .525], 61: [-.19549, .41562, 0, 0, .525], 62: [-.05556, .55556, 0, 0, .525], 63: [0, .61111, 0, 0, .525], 64: [0, .61111, 0, 0, .525], 65: [0, .61111, 0, 0, .525], 66: [0, .61111, 0, 0, .525], 67: [0, .61111, 0, 0, .525], 68: [0, .61111, 0, 0, .525], 69: [0, .61111, 0, 0, .525], 70: [0, .61111, 0, 0, .525], 71: [0, .61111, 0, 0, .525], 72: [0, .61111, 0, 0, .525], 73: [0, .61111, 0, 0, .525], 74: [0, .61111, 0, 0, .525], 75: [0, .61111, 0, 0, .525], 76: [0, .61111, 0, 0, .525], 77: [0, .61111, 0, 0, .525], 78: [0, .61111, 0, 0, .525], 79: [0, .61111, 0, 0, .525], 80: [0, .61111, 0, 0, .525], 81: [.13889, .61111, 0, 0, .525], 82: [0, .61111, 0, 0, .525], 83: [0, .61111, 0, 0, .525], 84: [0, .61111, 0, 0, .525], 85: [0, .61111, 0, 0, .525], 86: [0, .61111, 0, 0, .525], 87: [0, .61111, 0, 0, .525], 88: [0, .61111, 0, 0, .525], 89: [0, .61111, 0, 0, .525], 90: [0, .61111, 0, 0, .525], 91: [.08333, .69444, 0, 0, .525], 92: [.08333, .69444, 0, 0, .525], 93: [.08333, .69444, 0, 0, .525], 94: [0, .61111, 0, 0, .525], 95: [.09514, 0, 0, 0, .525], 96: [0, .61111, 0, 0, .525], 97: [0, .43056, 0, 0, .525], 98: [0, .61111, 0, 0, .525], 99: [0, .43056, 0, 0, .525], 100: [0, .61111, 0, 0, .525], 101: [0, .43056, 0, 0, .525], 102: [0, .61111, 0, 0, .525], 103: [.22222, .43056, 0, 0, .525], 104: [0, .61111, 0, 0, .525], 105: [0, .61111, 0, 0, .525], 106: [.22222, .61111, 0, 0, .525], 107: [0, .61111, 0, 0, .525], 108: [0, .61111, 0, 0, .525], 109: [0, .43056, 0, 0, .525], 110: [0, .43056, 0, 0, .525], 111: [0, .43056, 0, 0, .525], 112: [.22222, .43056, 0, 0, .525], 113: [.22222, .43056, 0, 0, .525], 114: [0, .43056, 0, 0, .525], 115: [0, .43056, 0, 0, .525], 116: [0, .55358, 0, 0, .525], 117: [0, .43056, 0, 0, .525], 118: [0, .43056, 0, 0, .525], 119: [0, .43056, 0, 0, .525], 120: [0, .43056, 0, 0, .525], 121: [.22222, .43056, 0, 0, .525], 122: [0, .43056, 0, 0, .525], 123: [.08333, .69444, 0, 0, .525], 124: [.08333, .69444, 0, 0, .525], 125: [.08333, .69444, 0, 0, .525], 126: [0, .61111, 0, 0, .525], 127: [0, .61111, 0, 0, .525], 160: [0, 0, 0, 0, .525], 176: [0, .61111, 0, 0, .525], 184: [.19445, 0, 0, 0, .525], 305: [0, .43056, 0, 0, .525], 567: [.22222, .43056, 0, 0, .525], 711: [0, .56597, 0, 0, .525], 713: [0, .56555, 0, 0, .525], 714: [0, .61111, 0, 0, .525], 715: [0, .61111, 0, 0, .525], 728: [0, .61111, 0, 0, .525], 730: [0, .61111, 0, 0, .525], 770: [0, .61111, 0, 0, .525], 771: [0, .61111, 0, 0, .525], 776: [0, .61111, 0, 0, .525], 915: [0, .61111, 0, 0, .525], 916: [0, .61111, 0, 0, .525], 920: [0, .61111, 0, 0, .525], 923: [0, .61111, 0, 0, .525], 926: [0, .61111, 0, 0, .525], 928: [0, .61111, 0, 0, .525], 931: [0, .61111, 0, 0, .525], 933: [0, .61111, 0, 0, .525], 934: [0, .61111, 0, 0, .525], 936: [0, .61111, 0, 0, .525], 937: [0, .61111, 0, 0, .525], 8216: [0, .61111, 0, 0, .525], 8217: [0, .61111, 0, 0, .525], 8242: [0, .61111, 0, 0, .525], 9251: [.11111, .21944, 0, 0, .525] } }; const B = { slant: [.25, .25, .25], space: [0, 0, 0], stretch: [0, 0, 0], shrink: [0, 0, 0], xHeight: [.431, .431, .431], quad: [1, 1.171, 1.472], extraSpace: [0, 0, 0], num1: [.677, .732, .925], num2: [.394, .384, .387], num3: [.444, .471, .504], denom1: [.686, .752, 1.025], denom2: [.345, .344, .532], sup1: [.413, .503, .504], sup2: [.363, .431, .404], sup3: [.289, .286, .294], sub1: [.15, .143, .2], sub2: [.247, .286, .4], supDrop: [.386, .353, .494], subDrop: [.05, .071, .1], delim1: [2.39, 1.7, 1.98], delim2: [1.01, 1.157, 1.42], axisHeight: [.25, .25, .25], defaultRuleThickness: [.04, .049, .049], bigOpSpacing1: [.111, .111, .111], bigOpSpacing2: [.166, .166, .166], bigOpSpacing3: [.2, .2, .2], bigOpSpacing4: [.6, .611, .611], bigOpSpacing5: [.1, .143, .143], sqrtRuleThickness: [.04, .04, .04], ptPerEm: [10, 10, 10], doubleRuleSep: [.2, .2, .2], arrayRuleWidth: [.04, .04, .04], fboxsep: [.3, .3, .3], fboxrule: [.04, .04, .04] }, C = { "\xc5": "A", "\xd0": "D", "\xde": "o", "\xe5": "a", "\xf0": "d", "\xfe": "o", "\u0410": "A", "\u0411": "B", "\u0412": "B", "\u0413": "F", "\u0414": "A", "\u0415": "E", "\u0416": "K", "\u0417": "3", "\u0418": "N", "\u0419": "N", "\u041a": "K", "\u041b": "N", "\u041c": "M", "\u041d": "H", "\u041e": "O", "\u041f": "N", "\u0420": "P", "\u0421": "C", "\u0422": "T", "\u0423": "y", "\u0424": "O", "\u0425": "X", "\u0426": "U", "\u0427": "h", "\u0428": "W", "\u0429": "W", "\u042a": "B", "\u042b": "X", "\u042c": "B", "\u042d": "3", "\u042e": "X", "\u042f": "R", "\u0430": "a", "\u0431": "b", "\u0432": "a", "\u0433": "r", "\u0434": "y", "\u0435": "e", "\u0436": "m", "\u0437": "e", "\u0438": "n", "\u0439": "n", "\u043a": "n", "\u043b": "n", "\u043c": "m", "\u043d": "n", "\u043e": "o", "\u043f": "n", "\u0440": "p", "\u0441": "c", "\u0442": "o", "\u0443": "y", "\u0444": "b", "\u0445": "x", "\u0446": "n", "\u0447": "n", "\u0448": "w", "\u0449": "w", "\u044a": "a", "\u044b": "m", "\u044c": "a", "\u044d": "e", "\u044e": "m", "\u044f": "r" }; function N(e, t, r) { if (!T[t]) throw new Error("Font metrics not found for font: " + t + "."); let n = e.charCodeAt(0), o = T[t][n]; if (!o && e[0] in C && (n = C[e[0]].charCodeAt(0), o = T[t][n]), o || "text" !== r || S(n) && (o = T[t][77]), o) return { depth: o[0], height: o[1], italic: o[2], skew: o[3], width: o[4] } } const q = {}; const I = [[1, 1, 1], [2, 1, 1], [3, 1, 1], [4, 2, 1], [5, 2, 1], [6, 3, 1], [7, 4, 2], [8, 6, 3], [9, 7, 6], [10, 8, 7], [11, 10, 9]], R = [.5, .6, .7, .8, .9, 1, 1.2, 1.44, 1.728, 2.074, 2.488], H = function (e, t) { return t.size < 2 ? e : I[e - 1][t.size - 1] }; class O { constructor(e) { this.style = void 0, this.color = void 0, this.size = void 0, this.textSize = void 0, this.phantom = void 0, this.font = void 0, this.fontFamily = void 0, this.fontWeight = void 0, this.fontShape = void 0, this.sizeMultiplier = void 0, this.maxSize = void 0, this.minRuleThickness = void 0, this._fontMetrics = void 0, this.style = e.style, this.color = e.color, this.size = e.size || O.BASESIZE, this.textSize = e.textSize || this.size, this.phantom = !!e.phantom, this.font = e.font || "", this.fontFamily = e.fontFamily || "", this.fontWeight = e.fontWeight || "", this.fontShape = e.fontShape || "", this.sizeMultiplier = R[this.size - 1], this.maxSize = e.maxSize, this.minRuleThickness = e.minRuleThickness, this._fontMetrics = void 0 } extend(e) { const t = { style: this.style, size: this.size, textSize: this.textSize, color: this.color, phantom: this.phantom, font: this.font, fontFamily: this.fontFamily, fontWeight: this.fontWeight, fontShape: this.fontShape, maxSize: this.maxSize, minRuleThickness: this.minRuleThickness }; for (const r in e) e.hasOwnProperty(r) && (t[r] = e[r]); return new O(t) } havingStyle(e) { return this.style === e ? this : this.extend({ style: e, size: H(this.textSize, e) }) } havingCrampedStyle() { return this.havingStyle(this.style.cramp()) } havingSize(e) { return this.size === e && this.textSize === e ? this : this.extend({ style: this.style.text(), size: e, textSize: e, sizeMultiplier: R[e - 1] }) } havingBaseStyle(e) { e = e || this.style.text(); const t = H(O.BASESIZE, e); return this.size === t && this.textSize === O.BASESIZE && this.style === e ? this : this.extend({ style: e, size: t }) } havingBaseSizing() { let e; switch (this.style.id) { case 4: case 5: e = 3; break; case 6: case 7: e = 1; break; default: e = 6 }return this.extend({ style: this.style.text(), size: e }) } withColor(e) { return this.extend({ color: e }) } withPhantom() { return this.extend({ phantom: !0 }) } withFont(e) { return this.extend({ font: e }) } withTextFontFamily(e) { return this.extend({ fontFamily: e, font: "" }) } withTextFontWeight(e) { return this.extend({ fontWeight: e, font: "" }) } withTextFontShape(e) { return this.extend({ fontShape: e, font: "" }) } sizingClasses(e) { return e.size !== this.size ? ["sizing", "reset-size" + e.size, "size" + this.size] : [] } baseSizingClasses() { return this.size !== O.BASESIZE ? ["sizing", "reset-size" + this.size, "size" + O.BASESIZE] : [] } fontMetrics() { return this._fontMetrics || (this._fontMetrics = function (e) { let t; if (t = e >= 5 ? 0 : e >= 3 ? 1 : 2, !q[t]) { const e = q[t] = { cssEmPerMu: B.quad[t] / 18 }; for (const r in B) B.hasOwnProperty(r) && (e[r] = B[r][t]) } return q[t] }(this.size)), this._fontMetrics } getColor() { return this.phantom ? "transparent" : this.color } } O.BASESIZE = 6; var E = O; const L = { pt: 1, mm: 7227 / 2540, cm: 7227 / 254, in: 72.27, bp: 1.00375, pc: 12, dd: 1238 / 1157, cc: 14856 / 1157, nd: 685 / 642, nc: 1370 / 107, sp: 1 / 65536, px: 1.00375 }, D = { ex: !0, em: !0, mu: !0 }, V = function (e) { return "string" != typeof e && (e = e.unit), e in L || e in D || "ex" === e }, P = function (e, t) { let r; if (e.unit in L) r = L[e.unit] / t.fontMetrics().ptPerEm / t.sizeMultiplier; else if ("mu" === e.unit) r = t.fontMetrics().cssEmPerMu; else { let o; if (o = t.style.isTight() ? t.havingStyle(t.style.text()) : t, "ex" === e.unit) r = o.fontMetrics().xHeight; else { if ("em" !== e.unit) throw new n("Invalid unit: '" + e.unit + "'"); r = o.fontMetrics().quad } o !== t && (r *= o.sizeMultiplier / t.sizeMultiplier) } return Math.min(e.number * r, t.maxSize) }, F = function (e) { return +e.toFixed(4) + "em" }, G = function (e) { return e.filter((e => e)).join(" ") }, U = function (e, t, r) { if (this.classes = e || [], this.attributes = {}, this.height = 0, this.depth = 0, this.maxFontSize = 0, this.style = r || {}, t) { t.style.isTight() && this.classes.push("mtight"); const e = t.getColor(); e && (this.style.color = e) } }, Y = function (e) { const t = document.createElement(e); t.className = G(this.classes); for (const e in this.style) this.style.hasOwnProperty(e) && (t.style[e] = this.style[e]); for (const e in this.attributes) this.attributes.hasOwnProperty(e) && t.setAttribute(e, this.attributes[e]); for (let e = 0; e < this.children.length; e++)t.appendChild(this.children[e].toNode()); return t }, X = function (e) { let t = "<" + e; this.classes.length && (t += ' class="' + l.escape(G(this.classes)) + '"'); let r = ""; for (const e in this.style) this.style.hasOwnProperty(e) && (r += l.hyphenate(e) + ":" + this.style[e] + ";"); r && (t += ' style="' + l.escape(r) + '"'); for (const e in this.attributes) this.attributes.hasOwnProperty(e) && (t += " " + e + '="' + l.escape(this.attributes[e]) + '"'); t += ">"; for (let e = 0; e < this.children.length; e++)t += this.children[e].toMarkup(); return t += "", t }; class W { constructor(e, t, r, n) { this.children = void 0, this.attributes = void 0, this.classes = void 0, this.height = void 0, this.depth = void 0, this.width = void 0, this.maxFontSize = void 0, this.style = void 0, U.call(this, e, r, n), this.children = t || [] } setAttribute(e, t) { this.attributes[e] = t } hasClass(e) { return l.contains(this.classes, e) } toNode() { return Y.call(this, "span") } toMarkup() { return X.call(this, "span") } } class _ { constructor(e, t, r, n) { this.children = void 0, this.attributes = void 0, this.classes = void 0, this.height = void 0, this.depth = void 0, this.maxFontSize = void 0, this.style = void 0, U.call(this, t, n), this.children = r || [], this.setAttribute("href", e) } setAttribute(e, t) { this.attributes[e] = t } hasClass(e) { return l.contains(this.classes, e) } toNode() { return Y.call(this, "a") } toMarkup() { return X.call(this, "a") } } class j { constructor(e, t, r) { this.src = void 0, this.alt = void 0, this.classes = void 0, this.height = void 0, this.depth = void 0, this.maxFontSize = void 0, this.style = void 0, this.alt = t, this.src = e, this.classes = ["mord"], this.style = r } hasClass(e) { return l.contains(this.classes, e) } toNode() { const e = document.createElement("Crop_img"); e.src = this.src, e.alt = this.alt, e.className = "mord"; for (const t in this.style) this.style.hasOwnProperty(t) && (e.style[t] = this.style[t]); return e } toMarkup() { let e = '= n[0] && e <= n[1]) return r.name } } return null }(this.text.charCodeAt(0)); l && this.classes.push(l + "_fallback"), /[\xee\xef\xed\xec]/.test(this.text) && (this.text = $[this.text]) } hasClass(e) { return l.contains(this.classes, e) } toNode() { const e = document.createTextNode(this.text); let t = null; this.italic > 0 && (t = document.createElement("span"), t.style.marginRight = F(this.italic)), this.classes.length > 0 && (t = t || document.createElement("span"), t.className = G(this.classes)); for (const e in this.style) this.style.hasOwnProperty(e) && (t = t || document.createElement("span"), t.style[e] = this.style[e]); return t ? (t.appendChild(e), t) : e } toMarkup() { let e = !1, t = " 0 && (r += "margin-right:" + this.italic + "em;"); for (const e in this.style) this.style.hasOwnProperty(e) && (r += l.hyphenate(e) + ":" + this.style[e] + ";"); r && (e = !0, t += ' style="' + l.escape(r) + '"'); const n = l.escape(this.text); return e ? (t += ">", t += n, t += "", t) : n } } class K { constructor(e, t) { this.children = void 0, this.attributes = void 0, this.children = e || [], this.attributes = t || {} } toNode() { const e = document.createElementNS("http://www.w3.org/2000/svg", "svg"); for (const t in this.attributes) Object.prototype.hasOwnProperty.call(this.attributes, t) && e.setAttribute(t, this.attributes[t]); for (let t = 0; t < this.children.length; t++)e.appendChild(this.children[t].toNode()); return e } toMarkup() { let e = '' : '' } } class Q { constructor(e) { this.attributes = void 0, this.attributes = e || {} } toNode() { const e = document.createElementNS("http://www.w3.org/2000/svg", "line"); for (const t in this.attributes) Object.prototype.hasOwnProperty.call(this.attributes, t) && e.setAttribute(t, this.attributes[t]); return e } toMarkup() { let e = "", "\\gt", !0), se(ie, le, ye, "\u2208", "\\in", !0), se(ie, le, ye, "\ue020", "\\@not"), se(ie, le, ye, "\u2282", "\\subset", !0), se(ie, le, ye, "\u2283", "\\supset", !0), se(ie, le, ye, "\u2286", "\\subseteq", !0), se(ie, le, ye, "\u2287", "\\supseteq", !0), se(ie, he, ye, "\u2288", "\\nsubseteq", !0), se(ie, he, ye, "\u2289", "\\nsupseteq", !0), se(ie, le, ye, "\u22a8", "\\models"), se(ie, le, ye, "\u2190", "\\leftarrow", !0), se(ie, le, ye, "\u2264", "\\le"), se(ie, le, ye, "\u2264", "\\leq", !0), se(ie, le, ye, "<", "\\lt", !0), se(ie, le, ye, "\u2192", "\\rightarrow", !0), se(ie, le, ye, "\u2192", "\\to"), se(ie, he, ye, "\u2271", "\\ngeq", !0), se(ie, he, ye, "\u2270", "\\nleq", !0), se(ie, le, xe, "\xa0", "\\ "), se(ie, le, xe, "\xa0", "\\space"), se(ie, le, xe, "\xa0", "\\nobreakspace"), se(ae, le, xe, "\xa0", "\\ "), se(ae, le, xe, "\xa0", " "), se(ae, le, xe, "\xa0", "\\space"), se(ae, le, xe, "\xa0", "\\nobreakspace"), se(ie, le, xe, null, "\\nobreak"), se(ie, le, xe, null, "\\allowbreak"), se(ie, le, be, ",", ","), se(ie, le, be, ";", ";"), se(ie, he, me, "\u22bc", "\\barwedge", !0), se(ie, he, me, "\u22bb", "\\veebar", !0), se(ie, le, me, "\u2299", "\\odot", !0), se(ie, le, me, "\u2295", "\\oplus", !0), se(ie, le, me, "\u2297", "\\otimes", !0), se(ie, le, we, "\u2202", "\\partial", !0), se(ie, le, me, "\u2298", "\\oslash", !0), se(ie, he, me, "\u229a", "\\circledcirc", !0), se(ie, he, me, "\u22a1", "\\boxdot", !0), se(ie, le, me, "\u25b3", "\\bigtriangleup"), se(ie, le, me, "\u25bd", "\\bigtriangledown"), se(ie, le, me, "\u2020", "\\dagger"), se(ie, le, me, "\u22c4", "\\diamond"), se(ie, le, me, "\u22c6", "\\star"), se(ie, le, me, "\u25c3", "\\triangleleft"), se(ie, le, me, "\u25b9", "\\triangleright"), se(ie, le, fe, "{", "\\{"), se(ae, le, we, "{", "\\{"), se(ae, le, we, "{", "\\textbraceleft"), se(ie, le, pe, "}", "\\}"), se(ae, le, we, "}", "\\}"), se(ae, le, we, "}", "\\textbraceright"), se(ie, le, fe, "{", "\\lbrace"), se(ie, le, pe, "}", "\\rbrace"), se(ie, le, fe, "[", "\\lbrack", !0), se(ae, le, we, "[", "\\lbrack", !0), se(ie, le, pe, "]", "\\rbrack", !0), se(ae, le, we, "]", "\\rbrack", !0), se(ie, le, fe, "(", "\\lparen", !0), se(ie, le, pe, ")", "\\rparen", !0), se(ae, le, we, "<", "\\textless", !0), se(ae, le, we, ">", "\\textgreater", !0), se(ie, le, fe, "\u230a", "\\lfloor", !0), se(ie, le, pe, "\u230b", "\\rfloor", !0), se(ie, le, fe, "\u2308", "\\lceil", !0), se(ie, le, pe, "\u2309", "\\rceil", !0), se(ie, le, we, "\\", "\\backslash"), se(ie, le, we, "\u2223", "|"), se(ie, le, we, "\u2223", "\\vert"), se(ae, le, we, "|", "\\textbar", !0), se(ie, le, we, "\u2225", "\\|"), se(ie, le, we, "\u2225", "\\Vert"), se(ae, le, we, "\u2225", "\\textbardbl"), se(ae, le, we, "~", "\\textasciitilde"), se(ae, le, we, "\\", "\\textbackslash"), se(ae, le, we, "^", "\\textasciicircum"), se(ie, le, ye, "\u2191", "\\uparrow", !0), se(ie, le, ye, "\u21d1", "\\Uparrow", !0), se(ie, le, ye, "\u2193", "\\downarrow", !0), se(ie, le, ye, "\u21d3", "\\Downarrow", !0), se(ie, le, ye, "\u2195", "\\updownarrow", !0), se(ie, le, ye, "\u21d5", "\\Updownarrow", !0), se(ie, le, ge, "\u2210", "\\coprod"), se(ie, le, ge, "\u22c1", "\\bigvee"), se(ie, le, ge, "\u22c0", "\\bigwedge"), se(ie, le, ge, "\u2a04", "\\biguplus"), se(ie, le, ge, "\u22c2", "\\bigcap"), se(ie, le, ge, "\u22c3", "\\bigcup"), se(ie, le, ge, "\u222b", "\\int"), se(ie, le, ge, "\u222b", "\\intop"), se(ie, le, ge, "\u222c", "\\iint"), se(ie, le, ge, "\u222d", "\\iiint"), se(ie, le, ge, "\u220f", "\\prod"), se(ie, le, ge, "\u2211", "\\sum"), se(ie, le, ge, "\u2a02", "\\bigotimes"), se(ie, le, ge, "\u2a01", "\\bigoplus"), se(ie, le, ge, "\u2a00", "\\bigodot"), se(ie, le, ge, "\u222e", "\\oint"), se(ie, le, ge, "\u222f", "\\oiint"), se(ie, le, ge, "\u2230", "\\oiiint"), se(ie, le, ge, "\u2a06", "\\bigsqcup"), se(ie, le, ge, "\u222b", "\\smallint"), se(ae, le, ue, "\u2026", "\\textellipsis"), se(ie, le, ue, "\u2026", "\\mathellipsis"), se(ae, le, ue, "\u2026", "\\ldots", !0), se(ie, le, ue, "\u2026", "\\ldots", !0), se(ie, le, ue, "\u22ef", "\\@cdots", !0), se(ie, le, ue, "\u22f1", "\\ddots", !0), se(ie, le, we, "\u22ee", "\\varvdots"), se(ie, le, ce, "\u02ca", "\\acute"), se(ie, le, ce, "\u02cb", "\\grave"), se(ie, le, ce, "\xa8", "\\ddot"), se(ie, le, ce, "~", "\\tilde"), se(ie, le, ce, "\u02c9", "\\bar"), se(ie, le, ce, "\u02d8", "\\breve"), se(ie, le, ce, "\u02c7", "\\check"), se(ie, le, ce, "^", "\\hat"), se(ie, le, ce, "\u20d7", "\\vec"), se(ie, le, ce, "\u02d9", "\\dot"), se(ie, le, ce, "\u02da", "\\mathring"), se(ie, le, de, "\ue131", "\\@imath"), se(ie, le, de, "\ue237", "\\@jmath"), se(ie, le, we, "\u0131", "\u0131"), se(ie, le, we, "\u0237", "\u0237"), se(ae, le, we, "\u0131", "\\i", !0), se(ae, le, we, "\u0237", "\\j", !0), se(ae, le, we, "\xdf", "\\ss", !0), se(ae, le, we, "\xe6", "\\ae", !0), se(ae, le, we, "\u0153", "\\oe", !0), se(ae, le, we, "\xf8", "\\o", !0), se(ae, le, we, "\xc6", "\\AE", !0), se(ae, le, we, "\u0152", "\\OE", !0), se(ae, le, we, "\xd8", "\\O", !0), se(ae, le, ce, "\u02ca", "\\'"), se(ae, le, ce, "\u02cb", "\\`"), se(ae, le, ce, "\u02c6", "\\^"), se(ae, le, ce, "\u02dc", "\\~"), se(ae, le, ce, "\u02c9", "\\="), se(ae, le, ce, "\u02d8", "\\u"), se(ae, le, ce, "\u02d9", "\\."), se(ae, le, ce, "\xb8", "\\c"), se(ae, le, ce, "\u02da", "\\r"), se(ae, le, ce, "\u02c7", "\\v"), se(ae, le, ce, "\xa8", '\\"'), se(ae, le, ce, "\u02dd", "\\H"), se(ae, le, ce, "\u25ef", "\\textcircled"); const ve = { "--": !0, "---": !0, "``": !0, "''": !0 }; se(ae, le, we, "\u2013", "--", !0), se(ae, le, we, "\u2013", "\\textendash"), se(ae, le, we, "\u2014", "---", !0), se(ae, le, we, "\u2014", "\\textemdash"), se(ae, le, we, "\u2018", "`", !0), se(ae, le, we, "\u2018", "\\textquoteleft"), se(ae, le, we, "\u2019", "'", !0), se(ae, le, we, "\u2019", "\\textquoteright"), se(ae, le, we, "\u201c", "``", !0), se(ae, le, we, "\u201c", "\\textquotedblleft"), se(ae, le, we, "\u201d", "''", !0), se(ae, le, we, "\u201d", "\\textquotedblright"), se(ie, le, we, "\xb0", "\\degree", !0), se(ae, le, we, "\xb0", "\\degree"), se(ae, le, we, "\xb0", "\\textdegree", !0), se(ie, le, we, "\xa3", "\\pounds"), se(ie, le, we, "\xa3", "\\mathsterling", !0), se(ae, le, we, "\xa3", "\\pounds"), se(ae, le, we, "\xa3", "\\textsterling", !0), se(ie, he, we, "\u2720", "\\maltese"), se(ae, he, we, "\u2720", "\\maltese"); const ke = '0123456789/@."'; for (let e = 0; e < ke.length; e++) { const t = ke.charAt(e); se(ie, le, we, t, t) } const Se = '0123456789!@*()-=+";:?/.,'; for (let e = 0; e < Se.length; e++) { const t = Se.charAt(e); se(ae, le, we, t, t) } const Me = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; for (let e = 0; e < Me.length; e++) { const t = Me.charAt(e); se(ie, le, de, t, t), se(ae, le, we, t, t) } se(ie, he, we, "C", "\u2102"), se(ae, he, we, "C", "\u2102"), se(ie, he, we, "H", "\u210d"), se(ae, he, we, "H", "\u210d"), se(ie, he, we, "N", "\u2115"), se(ae, he, we, "N", "\u2115"), se(ie, he, we, "P", "\u2119"), se(ae, he, we, "P", "\u2119"), se(ie, he, we, "Q", "\u211a"), se(ae, he, we, "Q", "\u211a"), se(ie, he, we, "R", "\u211d"), se(ae, he, we, "R", "\u211d"), se(ie, he, we, "Z", "\u2124"), se(ae, he, we, "Z", "\u2124"), se(ie, le, de, "h", "\u210e"), se(ae, le, de, "h", "\u210e"); let ze = ""; for (let e = 0; e < Me.length; e++) { const t = Me.charAt(e); ze = String.fromCharCode(55349, 56320 + e), se(ie, le, de, t, ze), se(ae, le, we, t, ze), ze = String.fromCharCode(55349, 56372 + e), se(ie, le, de, t, ze), se(ae, le, we, t, ze), ze = String.fromCharCode(55349, 56424 + e), se(ie, le, de, t, ze), se(ae, le, we, t, ze), ze = String.fromCharCode(55349, 56580 + e), se(ie, le, de, t, ze), se(ae, le, we, t, ze), ze = String.fromCharCode(55349, 56684 + e), se(ie, le, de, t, ze), se(ae, le, we, t, ze), ze = String.fromCharCode(55349, 56736 + e), se(ie, le, de, t, ze), se(ae, le, we, t, ze), ze = String.fromCharCode(55349, 56788 + e), se(ie, le, de, t, ze), se(ae, le, we, t, ze), ze = String.fromCharCode(55349, 56840 + e), se(ie, le, de, t, ze), se(ae, le, we, t, ze), ze = String.fromCharCode(55349, 56944 + e), se(ie, le, de, t, ze), se(ae, le, we, t, ze), e < 26 && (ze = String.fromCharCode(55349, 56632 + e), se(ie, le, de, t, ze), se(ae, le, we, t, ze), ze = String.fromCharCode(55349, 56476 + e), se(ie, le, de, t, ze), se(ae, le, we, t, ze)) } ze = String.fromCharCode(55349, 56668), se(ie, le, de, "k", ze), se(ae, le, we, "k", ze); for (let e = 0; e < 10; e++) { const t = e.toString(); ze = String.fromCharCode(55349, 57294 + e), se(ie, le, de, t, ze), se(ae, le, we, t, ze), ze = String.fromCharCode(55349, 57314 + e), se(ie, le, de, t, ze), se(ae, le, we, t, ze), ze = String.fromCharCode(55349, 57324 + e), se(ie, le, de, t, ze), se(ae, le, we, t, ze), ze = String.fromCharCode(55349, 57334 + e), se(ie, le, de, t, ze), se(ae, le, we, t, ze) } const Ae = "\xd0\xde\xfe"; for (let e = 0; e < Ae.length; e++) { const t = Ae.charAt(e); se(ie, le, de, t, t), se(ae, le, we, t, t) } const Te = [["mathbf", "textbf", "Main-Bold"], ["mathbf", "textbf", "Main-Bold"], ["mathnormal", "textit", "Math-Italic"], ["mathnormal", "textit", "Math-Italic"], ["boldsymbol", "boldsymbol", "Main-BoldItalic"], ["boldsymbol", "boldsymbol", "Main-BoldItalic"], ["mathscr", "textscr", "Script-Regular"], ["", "", ""], ["", "", ""], ["", "", ""], ["mathfrak", "textfrak", "Fraktur-Regular"], ["mathfrak", "textfrak", "Fraktur-Regular"], ["mathbb", "textbb", "AMS-Regular"], ["mathbb", "textbb", "AMS-Regular"], ["mathboldfrak", "textboldfrak", "Fraktur-Regular"], ["mathboldfrak", "textboldfrak", "Fraktur-Regular"], ["mathsf", "textsf", "SansSerif-Regular"], ["mathsf", "textsf", "SansSerif-Regular"], ["mathboldsf", "textboldsf", "SansSerif-Bold"], ["mathboldsf", "textboldsf", "SansSerif-Bold"], ["mathitsf", "textitsf", "SansSerif-Italic"], ["mathitsf", "textitsf", "SansSerif-Italic"], ["", "", ""], ["", "", ""], ["mathtt", "texttt", "Typewriter-Regular"], ["mathtt", "texttt", "Typewriter-Regular"]], Be = [["mathbf", "textbf", "Main-Bold"], ["", "", ""], ["mathsf", "textsf", "SansSerif-Regular"], ["mathboldsf", "textboldsf", "SansSerif-Bold"], ["mathtt", "texttt", "Typewriter-Regular"]], Ce = function (e, t, r) { return oe[r][e] && oe[r][e].replace && (e = oe[r][e].replace), { value: e, metrics: N(e, t, r) } }, Ne = function (e, t, r, n, o) { const s = Ce(e, t, r), i = s.metrics; let a; if (e = s.value, i) { let t = i.italic; ("text" === r || n && "mathit" === n.font) && (t = 0), a = new Z(e, i.height, i.depth, t, i.skew, i.width, o) } else "undefined" != typeof console && console.warn("No character metrics for '" + e + "' in style '" + t + "' and mode '" + r + "'"), a = new Z(e, 0, 0, 0, 0, 0, o); if (n) { a.maxFontSize = n.sizeMultiplier, n.style.isTight() && a.classes.push("mtight"); const e = n.getColor(); e && (a.style.color = e) } return a }, qe = (e, t) => { if (G(e.classes) !== G(t.classes) || e.skew !== t.skew || e.maxFontSize !== t.maxFontSize) return !1; if (1 === e.classes.length) { const t = e.classes[0]; if ("mbin" === t || "mord" === t) return !1 } for (const r in e.style) if (e.style.hasOwnProperty(r) && e.style[r] !== t.style[r]) return !1; for (const r in t.style) if (t.style.hasOwnProperty(r) && e.style[r] !== t.style[r]) return !1; return !0 }, Ie = function (e) { let t = 0, r = 0, n = 0; for (let o = 0; o < e.children.length; o++) { const s = e.children[o]; s.height > t && (t = s.height), s.depth > r && (r = s.depth), s.maxFontSize > n && (n = s.maxFontSize) } e.height = t, e.depth = r, e.maxFontSize = n }, Re = function (e, t, r, n) { const o = new W(e, t, r, n); return Ie(o), o }, He = (e, t, r, n) => new W(e, t, r, n), Oe = function (e) { const t = new A(e); return Ie(t), t }, Ee = function (e, t, r) { let n, o = ""; switch (e) { case "amsrm": o = "AMS"; break; case "textrm": o = "Main"; break; case "textsf": o = "SansSerif"; break; case "texttt": o = "Typewriter"; break; default: o = e }return n = "textbf" === t && "textit" === r ? "BoldItalic" : "textbf" === t ? "Bold" : "textit" === t ? "Italic" : "Regular", o + "-" + n }, Le = { mathbf: { variant: "bold", fontName: "Main-Bold" }, mathrm: { variant: "normal", fontName: "Main-Regular" }, textit: { variant: "italic", fontName: "Main-Italic" }, mathit: { variant: "italic", fontName: "Main-Italic" }, mathnormal: { variant: "italic", fontName: "Math-Italic" }, mathbb: { variant: "double-struck", fontName: "AMS-Regular" }, mathcal: { variant: "script", fontName: "Caligraphic-Regular" }, mathfrak: { variant: "fraktur", fontName: "Fraktur-Regular" }, mathscr: { variant: "script", fontName: "Script-Regular" }, mathsf: { variant: "sans-serif", fontName: "SansSerif-Regular" }, mathtt: { variant: "monospace", fontName: "Typewriter-Regular" } }, De = { vec: ["vec", .471, .714], oiintSize1: ["oiintSize1", .957, .499], oiintSize2: ["oiintSize2", 1.472, .659], oiiintSize1: ["oiiintSize1", 1.304, .499], oiiintSize2: ["oiiintSize2", 1.98, .659] }; var Ve = { fontMap: Le, makeSymbol: Ne, mathsym: function (e, t, r, n) { return void 0 === n && (n = []), "boldsymbol" === r.font && Ce(e, "Main-Bold", t).metrics ? Ne(e, "Main-Bold", t, r, n.concat(["mathbf"])) : "\\" === e || "main" === oe[t][e].font ? Ne(e, "Main-Regular", t, r, n) : Ne(e, "AMS-Regular", t, r, n.concat(["amsrm"])) }, makeSpan: Re, makeSvgSpan: He, makeLineSpan: function (e, t, r) { const n = Re([e], [], t); return n.height = Math.max(r || t.fontMetrics().defaultRuleThickness, t.minRuleThickness), n.style.borderBottomWidth = F(n.height), n.maxFontSize = 1, n }, makeAnchor: function (e, t, r, n) { const o = new _(e, t, r, n); return Ie(o), o }, makeFragment: Oe, wrapFragment: function (e, t) { return e instanceof A ? Re([], [e], t) : e }, makeVList: function (e, t) { const { children: r, depth: n } = function (e) { if ("individualShift" === e.positionType) { const t = e.children, r = [t[0]], n = -t[0].shift - t[0].elem.depth; let o = n; for (let e = 1; e < t.length; e++) { const n = -t[e].shift - o - t[e].elem.depth, s = n - (t[e - 1].elem.height + t[e - 1].elem.depth); o += n, r.push({ type: "kern", size: s }), r.push(t[e]) } return { children: r, depth: n } } let t; if ("top" === e.positionType) { let r = e.positionData; for (let t = 0; t < e.children.length; t++) { const n = e.children[t]; r -= "kern" === n.type ? n.size : n.elem.height + n.elem.depth } t = r } else if ("bottom" === e.positionType) t = -e.positionData; else { const r = e.children[0]; if ("elem" !== r.type) throw new Error('First child must have type "elem".'); if ("shift" === e.positionType) t = -r.elem.depth - e.positionData; else { if ("firstBaseline" !== e.positionType) throw new Error("Invalid positionType " + e.positionType + "."); t = -r.elem.depth } } return { children: e.children, depth: t } }(e); let o = 0; for (let e = 0; e < r.length; e++) { const t = r[e]; if ("elem" === t.type) { const e = t.elem; o = Math.max(o, e.maxFontSize, e.height) } } o += 2; const s = Re(["pstrut"], []); s.style.height = F(o); const i = []; let a = n, l = n, h = n; for (let e = 0; e < r.length; e++) { const t = r[e]; if ("kern" === t.type) h += t.size; else { const e = t.elem, r = t.wrapperClasses || [], n = t.wrapperStyle || {}, a = Re(r, [s, e], void 0, n); a.style.top = F(-o - h - e.depth), t.marginLeft && (a.style.marginLeft = t.marginLeft), t.marginRight && (a.style.marginRight = t.marginRight), i.push(a), h += e.height + e.depth } a = Math.min(a, h), l = Math.max(l, h) } const c = Re(["vlist"], i); let m; if (c.style.height = F(l), a < 0) { const e = Re([], []), t = Re(["vlist"], [e]); t.style.height = F(-a); const r = Re(["vlist-s"], [new Z("\u200b")]); m = [Re(["vlist-r"], [c, r]), Re(["vlist-r"], [t])] } else m = [Re(["vlist-r"], [c])]; const p = Re(["vlist-t"], m); return 2 === m.length && p.classes.push("vlist-t2"), p.height = l, p.depth = -a, p }, makeOrd: function (e, t, r) { const o = e.mode, s = e.text, i = ["mord"], a = "math" === o || "text" === o && t.font, l = a ? t.font : t.fontFamily; let h = "", c = ""; if (55349 === s.charCodeAt(0) && ([h, c] = function (e, t) { const r = 1024 * (e.charCodeAt(0) - 55296) + (e.charCodeAt(1) - 56320) + 65536, o = "math" === t ? 0 : 1; if (119808 <= r && r < 120484) { const e = Math.floor((r - 119808) / 26); return [Te[e][2], Te[e][o]] } if (120782 <= r && r <= 120831) { const e = Math.floor((r - 120782) / 10); return [Be[e][2], Be[e][o]] } if (120485 === r || 120486 === r) return [Te[0][2], Te[0][o]]; if (120486 < r && r < 120782) return ["", ""]; throw new n("Unsupported character: " + e) }(s, o)), h.length > 0) return Ne(s, h, o, t, i.concat(c)); if (l) { let e, n; if ("boldsymbol" === l) { const t = function (e, t, r, n, o) { return "textord" !== o && Ce(e, "Math-BoldItalic", t).metrics ? { fontName: "Math-BoldItalic", fontClass: "boldsymbol" } : { fontName: "Main-Bold", fontClass: "mathbf" } }(s, o, 0, 0, r); e = t.fontName, n = [t.fontClass] } else a ? (e = Le[l].fontName, n = [l]) : (e = Ee(l, t.fontWeight, t.fontShape), n = [l, t.fontWeight, t.fontShape]); if (Ce(s, e, o).metrics) return Ne(s, e, o, t, i.concat(n)); if (ve.hasOwnProperty(s) && "Typewriter" === e.slice(0, 10)) { const r = []; for (let a = 0; a < s.length; a++)r.push(Ne(s[a], e, o, t, i.concat(n))); return Oe(r) } } if ("mathord" === r) return Ne(s, "Math-Italic", o, t, i.concat(["mathnormal"])); if ("textord" === r) { const e = oe[o][s] && oe[o][s].font; if ("ams" === e) { const e = Ee("amsrm", t.fontWeight, t.fontShape); return Ne(s, e, o, t, i.concat("amsrm", t.fontWeight, t.fontShape)) } if ("main" !== e && e) { const r = Ee(e, t.fontWeight, t.fontShape); return Ne(s, r, o, t, i.concat(r, t.fontWeight, t.fontShape)) } { const e = Ee("textrm", t.fontWeight, t.fontShape); return Ne(s, e, o, t, i.concat(t.fontWeight, t.fontShape)) } } throw new Error("unexpected type: " + r + " in makeOrd") }, makeGlue: (e, t) => { const r = Re(["mspace"], [], t), n = P(e, t); return r.style.marginRight = F(n), r }, staticSvg: function (e, t) { const [r, n, o] = De[e], s = new J(r), i = new K([s], { width: F(n), height: F(o), style: "width:" + F(n), viewBox: "0 0 " + 1e3 * n + " " + 1e3 * o, preserveAspectRatio: "xMinYMin" }), a = He(["overlay"], [i], t); return a.height = o, a.style.height = F(o), a.style.width = F(n), a }, svgData: De, tryCombineChars: e => { for (let t = 0; t < e.length - 1; t++) { const r = e[t], n = e[t + 1]; r instanceof Z && n instanceof Z && qe(r, n) && (r.text += n.text, r.height = Math.max(r.height, n.height), r.depth = Math.max(r.depth, n.depth), r.italic = n.italic, e.splice(t + 1, 1), t--) } return e } }; const Pe = { number: 3, unit: "mu" }, Fe = { number: 4, unit: "mu" }, Ge = { number: 5, unit: "mu" }, Ue = { mord: { mop: Pe, mbin: Fe, mrel: Ge, minner: Pe }, mop: { mord: Pe, mop: Pe, mrel: Ge, minner: Pe }, mbin: { mord: Fe, mop: Fe, mopen: Fe, minner: Fe }, mrel: { mord: Ge, mop: Ge, mopen: Ge, minner: Ge }, mopen: {}, mclose: { mop: Pe, mbin: Fe, mrel: Ge, minner: Pe }, mpunct: { mord: Pe, mop: Pe, mrel: Ge, mopen: Pe, mclose: Pe, mpunct: Pe, minner: Pe }, minner: { mord: Pe, mop: Pe, mbin: Fe, mrel: Ge, mopen: Pe, mpunct: Pe, minner: Pe } }, Ye = { mord: { mop: Pe }, mop: { mord: Pe, mop: Pe }, mbin: {}, mrel: {}, mopen: {}, mclose: { mop: Pe }, mpunct: {}, minner: { mop: Pe } }, Xe = {}, We = {}, _e = {}; function je(e) { let { type: t, names: r, props: n, handler: o, htmlBuilder: s, mathmlBuilder: i } = e; const a = { type: t, numArgs: n.numArgs, argTypes: n.argTypes, allowedInArgument: !!n.allowedInArgument, allowedInText: !!n.allowedInText, allowedInMath: void 0 === n.allowedInMath || n.allowedInMath, numOptionalArgs: n.numOptionalArgs || 0, infix: !!n.infix, primitive: !!n.primitive, handler: o }; for (let e = 0; e < r.length; ++e)Xe[r[e]] = a; t && (s && (We[t] = s), i && (_e[t] = i)) } function $e(e) { let { type: t, htmlBuilder: r, mathmlBuilder: n } = e; je({ type: t, names: [], props: { numArgs: 0 }, handler() { throw new Error("Should never be called.") }, htmlBuilder: r, mathmlBuilder: n }) } const Ze = function (e) { return "ordgroup" === e.type && 1 === e.body.length ? e.body[0] : e }, Ke = function (e) { return "ordgroup" === e.type ? e.body : [e] }, Je = Ve.makeSpan, Qe = ["leftmost", "mbin", "mopen", "mrel", "mop", "mpunct"], et = ["rightmost", "mrel", "mclose", "mpunct"], tt = { display: w.DISPLAY, text: w.TEXT, script: w.SCRIPT, scriptscript: w.SCRIPTSCRIPT }, rt = { mord: "mord", mop: "mop", mbin: "mbin", mrel: "mrel", mopen: "mopen", mclose: "mclose", mpunct: "mpunct", minner: "minner" }, nt = function (e, t, r, n) { void 0 === n && (n = [null, null]); const o = []; for (let r = 0; r < e.length; r++) { const n = ht(e[r], t); if (n instanceof A) { const e = n.children; o.push(...e) } else o.push(n) } if (Ve.tryCombineChars(o), !r) return o; let s = t; if (1 === e.length) { const r = e[0]; "sizing" === r.type ? s = t.havingSize(r.size) : "styling" === r.type && (s = t.havingStyle(tt[r.style])) } const i = Je([n[0] || "leftmost"], [], t), a = Je([n[1] || "rightmost"], [], t), h = "root" === r; return ot(o, ((e, t) => { const r = t.classes[0], n = e.classes[0]; "mbin" === r && l.contains(et, n) ? t.classes[0] = "mord" : "mbin" === n && l.contains(Qe, r) && (e.classes[0] = "mord") }), { node: i }, a, h), ot(o, ((e, t) => { const r = at(t), n = at(e), o = r && n ? e.hasClass("mtight") ? Ye[r][n] : Ue[r][n] : null; if (o) return Ve.makeGlue(o, s) }), { node: i }, a, h), o }, ot = function (e, t, r, n, o) { n && e.push(n); let s = 0; for (; s < e.length; s++) { const n = e[s], i = st(n); if (i) { ot(i.children, t, r, null, o); continue } const a = !n.hasClass("mspace"); if (a) { const o = t(n, r.node); o && (r.insertAfter ? r.insertAfter(o) : (e.unshift(o), s++)) } a ? r.node = n : o && n.hasClass("newline") && (r.node = Je(["leftmost"])), r.insertAfter = (t => r => { e.splice(t + 1, 0, r), s++ })(s) } n && e.pop() }, st = function (e) { return e instanceof A || e instanceof _ || e instanceof W && e.hasClass("enclosing") ? e : null }, it = function (e, t) { const r = st(e); if (r) { const e = r.children; if (e.length) { if ("right" === t) return it(e[e.length - 1], "right"); if ("left" === t) return it(e[0], "left") } } return e }, at = function (e, t) { return e ? (t && (e = it(e, t)), rt[e.classes[0]] || null) : null }, lt = function (e, t) { const r = ["nulldelimiter"].concat(e.baseSizingClasses()); return Je(t.concat(r)) }, ht = function (e, t, r) { if (!e) return Je(); if (We[e.type]) { let n = We[e.type](e, t); if (r && t.size !== r.size) { n = Je(t.sizingClasses(r), [n], t); const e = t.sizeMultiplier / r.sizeMultiplier; n.height *= e, n.depth *= e } return n } throw new n("Got group of unknown type: '" + e.type + "'") }; function ct(e, t) { const r = Je(["base"], e, t), n = Je(["strut"]); return n.style.height = F(r.height + r.depth), r.depth && (n.style.verticalAlign = F(-r.depth)), r.children.unshift(n), r } function mt(e, t) { let r = null; 1 === e.length && "tag" === e[0].type && (r = e[0].tag, e = e[0].body); const n = nt(e, t, "root"); let o; 2 === n.length && n[1].hasClass("tag") && (o = n.pop()); const s = []; let i, a = []; for (let e = 0; e < n.length; e++)if (a.push(n[e]), n[e].hasClass("mbin") || n[e].hasClass("mrel") || n[e].hasClass("allowbreak")) { let r = !1; for (; e < n.length - 1 && n[e + 1].hasClass("mspace") && !n[e + 1].hasClass("newline");)e++, a.push(n[e]), n[e].hasClass("nobreak") && (r = !0); r || (s.push(ct(a, t)), a = []) } else n[e].hasClass("newline") && (a.pop(), a.length > 0 && (s.push(ct(a, t)), a = []), s.push(n[e])); a.length > 0 && s.push(ct(a, t)), r ? (i = ct(nt(r, t, !0)), i.classes = ["tag"], s.push(i)) : o && s.push(o); const l = Je(["katex-html"], s); if (l.setAttribute("aria-hidden", "true"), i) { const e = i.children[0]; e.style.height = F(l.height + l.depth), l.depth && (e.style.verticalAlign = F(-l.depth)) } return l } function pt(e) { return new A(e) } class ut { constructor(e, t, r) { this.type = void 0, this.attributes = void 0, this.children = void 0, this.classes = void 0, this.type = e, this.attributes = {}, this.children = t || [], this.classes = r || [] } setAttribute(e, t) { this.attributes[e] = t } getAttribute(e) { return this.attributes[e] } toNode() { const e = document.createElementNS("http://www.w3.org/1998/Math/MathML", this.type); for (const t in this.attributes) Object.prototype.hasOwnProperty.call(this.attributes, t) && e.setAttribute(t, this.attributes[t]); this.classes.length > 0 && (e.className = G(this.classes)); for (let t = 0; t < this.children.length; t++)e.appendChild(this.children[t].toNode()); return e } toMarkup() { let e = "<" + this.type; for (const t in this.attributes) Object.prototype.hasOwnProperty.call(this.attributes, t) && (e += " " + t + '="', e += l.escape(this.attributes[t]), e += '"'); this.classes.length > 0 && (e += ' class ="' + l.escape(G(this.classes)) + '"'), e += ">"; for (let t = 0; t < this.children.length; t++)e += this.children[t].toMarkup(); return e += "", e } toText() { return this.children.map((e => e.toText())).join("") } } class dt { constructor(e) { this.text = void 0, this.text = e } toNode() { return document.createTextNode(this.text) } toMarkup() { return l.escape(this.toText()) } toText() { return this.text } } var gt = { MathNode: ut, TextNode: dt, SpaceNode: class { constructor(e) { this.width = void 0, this.character = void 0, this.width = e, this.character = e >= .05555 && e <= .05556 ? "\u200a" : e >= .1666 && e <= .1667 ? "\u2009" : e >= .2222 && e <= .2223 ? "\u2005" : e >= .2777 && e <= .2778 ? "\u2005\u200a" : e >= -.05556 && e <= -.05555 ? "\u200a\u2063" : e >= -.1667 && e <= -.1666 ? "\u2009\u2063" : e >= -.2223 && e <= -.2222 ? "\u205f\u2063" : e >= -.2778 && e <= -.2777 ? "\u2005\u2063" : null } toNode() { if (this.character) return document.createTextNode(this.character); { const e = document.createElementNS("http://www.w3.org/1998/Math/MathML", "mspace"); return e.setAttribute("width", F(this.width)), e } } toMarkup() { return this.character ? "" + this.character + "" : '' } toText() { return this.character ? this.character : " " } }, newDocumentFragment: pt }; const ft = function (e, t, r) { return !oe[t][e] || !oe[t][e].replace || 55349 === e.charCodeAt(0) || ve.hasOwnProperty(e) && r && (r.fontFamily && "tt" === r.fontFamily.slice(4, 6) || r.font && "tt" === r.font.slice(4, 6)) || (e = oe[t][e].replace), new gt.TextNode(e) }, bt = function (e) { return 1 === e.length ? e[0] : new gt.MathNode("mrow", e) }, yt = function (e, t) { if ("texttt" === t.fontFamily) return "monospace"; if ("textsf" === t.fontFamily) return "textit" === t.fontShape && "textbf" === t.fontWeight ? "sans-serif-bold-italic" : "textit" === t.fontShape ? "sans-serif-italic" : "textbf" === t.fontWeight ? "bold-sans-serif" : "sans-serif"; if ("textit" === t.fontShape && "textbf" === t.fontWeight) return "bold-italic"; if ("textit" === t.fontShape) return "italic"; if ("textbf" === t.fontWeight) return "bold"; const r = t.font; if (!r || "mathnormal" === r) return null; const n = e.mode; if ("mathit" === r) return "italic"; if ("boldsymbol" === r) return "textord" === e.type ? "bold" : "bold-italic"; if ("mathbf" === r) return "bold"; if ("mathbb" === r) return "double-struck"; if ("mathfrak" === r) return "fraktur"; if ("mathscr" === r || "mathcal" === r) return "script"; if ("mathsf" === r) return "sans-serif"; if ("mathtt" === r) return "monospace"; let o = e.text; if (l.contains(["\\imath", "\\jmath"], o)) return null; oe[n][o] && oe[n][o].replace && (o = oe[n][o].replace); return N(o, Ve.fontMap[r].fontName, n) ? Ve.fontMap[r].variant : null }, xt = function (e, t, r) { if (1 === e.length) { const n = vt(e[0], t); return r && n instanceof ut && "mo" === n.type && (n.setAttribute("lspace", "0em"), n.setAttribute("rspace", "0em")), [n] } const n = []; let o; for (let r = 0; r < e.length; r++) { const s = vt(e[r], t); if (s instanceof ut && o instanceof ut) { if ("mtext" === s.type && "mtext" === o.type && s.getAttribute("mathvariant") === o.getAttribute("mathvariant")) { o.children.push(...s.children); continue } if ("mn" === s.type && "mn" === o.type) { o.children.push(...s.children); continue } if ("mi" === s.type && 1 === s.children.length && "mn" === o.type) { const e = s.children[0]; if (e instanceof dt && "." === e.text) { o.children.push(...s.children); continue } } else if ("mi" === o.type && 1 === o.children.length) { const e = o.children[0]; if (e instanceof dt && "\u0338" === e.text && ("mo" === s.type || "mi" === s.type || "mn" === s.type)) { const e = s.children[0]; e instanceof dt && e.text.length > 0 && (e.text = e.text.slice(0, 1) + "\u0338" + e.text.slice(1), n.pop()) } } } n.push(s), o = s } return n }, wt = function (e, t, r) { return bt(xt(e, t, r)) }, vt = function (e, t) { if (!e) return new gt.MathNode("mrow"); if (_e[e.type]) { return _e[e.type](e, t) } throw new n("Got group of unknown type: '" + e.type + "'") }; function kt(e, t, r, n, o) { const s = xt(e, r); let i; i = 1 === s.length && s[0] instanceof ut && l.contains(["mrow", "mtable"], s[0].type) ? s[0] : new gt.MathNode("mrow", s); const a = new gt.MathNode("annotation", [new gt.TextNode(t)]); a.setAttribute("encoding", "application/x-tex"); const h = new gt.MathNode("semantics", [i, a]), c = new gt.MathNode("math", [h]); c.setAttribute("xmlns", "http://www.w3.org/1998/Math/MathML"), n && c.setAttribute("display", "block"); const m = o ? "katex" : "katex-mathml"; return Ve.makeSpan([m], [c]) } const St = function (e) { return new E({ style: e.displayMode ? w.DISPLAY : w.TEXT, maxSize: e.maxSize, minRuleThickness: e.minRuleThickness }) }, Mt = function (e, t) { if (t.displayMode) { const r = ["katex-display"]; t.leqno && r.push("leqno"), t.fleqn && r.push("fleqn"), e = Ve.makeSpan(r, [e]) } return e }, zt = function (e, t, r) { const n = St(r); let o; if ("mathml" === r.output) return kt(e, t, n, r.displayMode, !0); if ("html" === r.output) { const t = mt(e, n); o = Ve.makeSpan(["katex"], [t]) } else { const s = kt(e, t, n, r.displayMode, !1), i = mt(e, n); o = Ve.makeSpan(["katex"], [s, i]) } return Mt(o, r) }; const At = { widehat: "^", widecheck: "\u02c7", widetilde: "~", utilde: "~", overleftarrow: "\u2190", underleftarrow: "\u2190", xleftarrow: "\u2190", overrightarrow: "\u2192", underrightarrow: "\u2192", xrightarrow: "\u2192", underbrace: "\u23df", overbrace: "\u23de", overgroup: "\u23e0", undergroup: "\u23e1", overleftrightarrow: "\u2194", underleftrightarrow: "\u2194", xleftrightarrow: "\u2194", Overrightarrow: "\u21d2", xRightarrow: "\u21d2", overleftharpoon: "\u21bc", xleftharpoonup: "\u21bc", overrightharpoon: "\u21c0", xrightharpoonup: "\u21c0", xLeftarrow: "\u21d0", xLeftrightarrow: "\u21d4", xhookleftarrow: "\u21a9", xhookrightarrow: "\u21aa", xmapsto: "\u21a6", xrightharpoondown: "\u21c1", xleftharpoondown: "\u21bd", xrightleftharpoons: "\u21cc", xleftrightharpoons: "\u21cb", xtwoheadleftarrow: "\u219e", xtwoheadrightarrow: "\u21a0", xlongequal: "=", xtofrom: "\u21c4", xrightleftarrows: "\u21c4", xrightequilibrium: "\u21cc", xleftequilibrium: "\u21cb", "\\cdrightarrow": "\u2192", "\\cdleftarrow": "\u2190", "\\cdlongequal": "=" }, Tt = { overrightarrow: [["rightarrow"], .888, 522, "xMaxYMin"], overleftarrow: [["leftarrow"], .888, 522, "xMinYMin"], underrightarrow: [["rightarrow"], .888, 522, "xMaxYMin"], underleftarrow: [["leftarrow"], .888, 522, "xMinYMin"], xrightarrow: [["rightarrow"], 1.469, 522, "xMaxYMin"], "\\cdrightarrow": [["rightarrow"], 3, 522, "xMaxYMin"], xleftarrow: [["leftarrow"], 1.469, 522, "xMinYMin"], "\\cdleftarrow": [["leftarrow"], 3, 522, "xMinYMin"], Overrightarrow: [["doublerightarrow"], .888, 560, "xMaxYMin"], xRightarrow: [["doublerightarrow"], 1.526, 560, "xMaxYMin"], xLeftarrow: [["doubleleftarrow"], 1.526, 560, "xMinYMin"], overleftharpoon: [["leftharpoon"], .888, 522, "xMinYMin"], xleftharpoonup: [["leftharpoon"], .888, 522, "xMinYMin"], xleftharpoondown: [["leftharpoondown"], .888, 522, "xMinYMin"], overrightharpoon: [["rightharpoon"], .888, 522, "xMaxYMin"], xrightharpoonup: [["rightharpoon"], .888, 522, "xMaxYMin"], xrightharpoondown: [["rightharpoondown"], .888, 522, "xMaxYMin"], xlongequal: [["longequal"], .888, 334, "xMinYMin"], "\\cdlongequal": [["longequal"], 3, 334, "xMinYMin"], xtwoheadleftarrow: [["twoheadleftarrow"], .888, 334, "xMinYMin"], xtwoheadrightarrow: [["twoheadrightarrow"], .888, 334, "xMaxYMin"], overleftrightarrow: [["leftarrow", "rightarrow"], .888, 522], overbrace: [["leftbrace", "midbrace", "rightbrace"], 1.6, 548], underbrace: [["leftbraceunder", "midbraceunder", "rightbraceunder"], 1.6, 548], underleftrightarrow: [["leftarrow", "rightarrow"], .888, 522], xleftrightarrow: [["leftarrow", "rightarrow"], 1.75, 522], xLeftrightarrow: [["doubleleftarrow", "doublerightarrow"], 1.75, 560], xrightleftharpoons: [["leftharpoondownplus", "rightharpoonplus"], 1.75, 716], xleftrightharpoons: [["leftharpoonplus", "rightharpoondownplus"], 1.75, 716], xhookleftarrow: [["leftarrow", "righthook"], 1.08, 522], xhookrightarrow: [["lefthook", "rightarrow"], 1.08, 522], overlinesegment: [["leftlinesegment", "rightlinesegment"], .888, 522], underlinesegment: [["leftlinesegment", "rightlinesegment"], .888, 522], overgroup: [["leftgroup", "rightgroup"], .888, 342], undergroup: [["leftgroupunder", "rightgroupunder"], .888, 342], xmapsto: [["leftmapsto", "rightarrow"], 1.5, 522], xtofrom: [["leftToFrom", "rightToFrom"], 1.75, 528], xrightleftarrows: [["baraboveleftarrow", "rightarrowabovebar"], 1.75, 901], xrightequilibrium: [["baraboveshortleftharpoon", "rightharpoonaboveshortbar"], 1.75, 716], xleftequilibrium: [["shortbaraboveleftharpoon", "shortrightharpoonabovebar"], 1.75, 716] }; var Bt = function (e, t, r, n, o) { let s; const i = e.height + e.depth + r + n; if (/fbox|color|angl/.test(t)) { if (s = Ve.makeSpan(["stretchy", t], [], o), "fbox" === t) { const e = o.color && o.getColor(); e && (s.style.borderColor = e) } } else { const e = []; /^[bx]cancel$/.test(t) && e.push(new Q({ x1: "0", y1: "0", x2: "100%", y2: "100%", "stroke-width": "0.046em" })), /^x?cancel$/.test(t) && e.push(new Q({ x1: "0", y1: "100%", x2: "100%", y2: "0", "stroke-width": "0.046em" })); const r = new K(e, { width: "100%", height: F(i) }); s = Ve.makeSvgSpan([], [r], o) } return s.height = i, s.style.height = F(i), s }, Ct = function (e) { const t = new gt.MathNode("mo", [new gt.TextNode(At[e.replace(/^\\/, "")])]); return t.setAttribute("stretchy", "true"), t }, Nt = function (e, t) { const { span: r, minWidth: n, height: o } = function () { let r = 4e5; const n = e.label.slice(1); if (l.contains(["widehat", "widecheck", "widetilde", "utilde"], n)) { const s = "ordgroup" === (o = e.base).type ? o.body.length : 1; let i, a, l; if (s > 5) "widehat" === n || "widecheck" === n ? (i = 420, r = 2364, l = .42, a = n + "4") : (i = 312, r = 2340, l = .34, a = "tilde4"); else { const e = [1, 1, 2, 2, 3, 3][s]; "widehat" === n || "widecheck" === n ? (r = [0, 1062, 2364, 2364, 2364][e], i = [0, 239, 300, 360, 420][e], l = [0, .24, .3, .3, .36, .42][e], a = n + e) : (r = [0, 600, 1033, 2339, 2340][e], i = [0, 260, 286, 306, 312][e], l = [0, .26, .286, .3, .306, .34][e], a = "tilde" + e) } const h = new J(a), c = new K([h], { width: "100%", height: F(l), viewBox: "0 0 " + r + " " + i, preserveAspectRatio: "none" }); return { span: Ve.makeSvgSpan([], [c], t), minWidth: 0, height: l } } { const e = [], o = Tt[n], [s, i, a] = o, l = a / 1e3, h = s.length; let c, m; if (1 === h) { c = ["hide-tail"], m = [o[3]] } else if (2 === h) c = ["halfarrow-left", "halfarrow-right"], m = ["xMinYMin", "xMaxYMin"]; else { if (3 !== h) throw new Error("Correct katexImagesData or update code here to support\n " + h + " children."); c = ["brace-left", "brace-center", "brace-right"], m = ["xMinYMin", "xMidYMin", "xMaxYMin"] } for (let n = 0; n < h; n++) { const o = new J(s[n]), p = new K([o], { width: "400em", height: F(l), viewBox: "0 0 " + r + " " + a, preserveAspectRatio: m[n] + " slice" }), u = Ve.makeSvgSpan([c[n]], [p], t); if (1 === h) return { span: u, minWidth: i, height: l }; u.style.height = F(l), e.push(u) } return { span: Ve.makeSpan(["stretchy"], e, t), minWidth: i, height: l } } var o }(); return r.height = o, r.style.height = F(o), n > 0 && (r.style.minWidth = F(n)), r }; function qt(e, t) { if (!e || e.type !== t) throw new Error("Expected node of type " + t + ", but got " + (e ? "node of type " + e.type : String(e))); return e } function It(e) { const t = Rt(e); if (!t) throw new Error("Expected node of symbol group type, but got " + (e ? "node of type " + e.type : String(e))); return t } function Rt(e) { return e && ("atom" === e.type || re.hasOwnProperty(e.type)) ? e : null } const Ht = (e, t) => { let r, n, o; e && "supsub" === e.type ? (n = qt(e.base, "accent"), r = n.base, e.base = r, o = function (e) { if (e instanceof W) return e; throw new Error("Expected span but got " + String(e) + ".") }(ht(e, t)), e.base = n) : (n = qt(e, "accent"), r = n.base); const s = ht(r, t.havingCrampedStyle()); let i = 0; if (n.isShifty && l.isCharacterBox(r)) { const e = l.getBaseElem(r); i = ee(ht(e, t.havingCrampedStyle())).skew } const a = "\\c" === n.label; let h, c = a ? s.height + s.depth : Math.min(s.height, t.fontMetrics().xHeight); if (n.isStretchy) h = Nt(n, t), h = Ve.makeVList({ positionType: "firstBaseline", children: [{ type: "elem", elem: s }, { type: "elem", elem: h, wrapperClasses: ["svg-align"], wrapperStyle: i > 0 ? { width: "calc(100% - " + F(2 * i) + ")", marginLeft: F(2 * i) } : void 0 }] }, t); else { let e, r; "\\vec" === n.label ? (e = Ve.staticSvg("vec", t), r = Ve.svgData.vec[1]) : (e = Ve.makeOrd({ mode: n.mode, text: n.label }, t, "textord"), e = ee(e), e.italic = 0, r = e.width, a && (c += e.depth)), h = Ve.makeSpan(["accent-body"], [e]); const o = "\\textcircled" === n.label; o && (h.classes.push("accent-full"), c = s.height); let l = i; o || (l -= r / 2), h.style.left = F(l), "\\textcircled" === n.label && (h.style.top = ".2em"), h = Ve.makeVList({ positionType: "firstBaseline", children: [{ type: "elem", elem: s }, { type: "kern", size: -c }, { type: "elem", elem: h }] }, t) } const m = Ve.makeSpan(["mord", "accent"], [h], t); return o ? (o.children[0] = m, o.height = Math.max(m.height, o.height), o.classes[0] = "mord", o) : m }, Ot = (e, t) => { const r = e.isStretchy ? Ct(e.label) : new gt.MathNode("mo", [ft(e.label, e.mode)]), n = new gt.MathNode("mover", [vt(e.base, t), r]); return n.setAttribute("accent", "true"), n }, Et = new RegExp(["\\acute", "\\grave", "\\ddot", "\\tilde", "\\bar", "\\breve", "\\check", "\\hat", "\\vec", "\\dot", "\\mathring"].map((e => "\\" + e)).join("|")); je({ type: "accent", names: ["\\acute", "\\grave", "\\ddot", "\\tilde", "\\bar", "\\breve", "\\check", "\\hat", "\\vec", "\\dot", "\\mathring", "\\widecheck", "\\widehat", "\\widetilde", "\\overrightarrow", "\\overleftarrow", "\\Overrightarrow", "\\overleftrightarrow", "\\overgroup", "\\overlinesegment", "\\overleftharpoon", "\\overrightharpoon"], props: { numArgs: 1 }, handler: (e, t) => { const r = Ze(t[0]), n = !Et.test(e.funcName), o = !n || "\\widehat" === e.funcName || "\\widetilde" === e.funcName || "\\widecheck" === e.funcName; return { type: "accent", mode: e.parser.mode, label: e.funcName, isStretchy: n, isShifty: o, base: r } }, htmlBuilder: Ht, mathmlBuilder: Ot }), je({ type: "accent", names: ["\\'", "\\`", "\\^", "\\~", "\\=", "\\u", "\\.", '\\"', "\\c", "\\r", "\\H", "\\v", "\\textcircled"], props: { numArgs: 1, allowedInText: !0, allowedInMath: !0, argTypes: ["primitive"] }, handler: (e, t) => { const r = t[0]; let n = e.parser.mode; return "math" === n && (e.parser.settings.reportNonstrict("mathVsTextAccents", "LaTeX's accent " + e.funcName + " works only in text mode"), n = "text"), { type: "accent", mode: n, label: e.funcName, isStretchy: !1, isShifty: !0, base: r } }, htmlBuilder: Ht, mathmlBuilder: Ot }), je({ type: "accentUnder", names: ["\\underleftarrow", "\\underrightarrow", "\\underleftrightarrow", "\\undergroup", "\\underlinesegment", "\\utilde"], props: { numArgs: 1 }, handler: (e, t) => { let { parser: r, funcName: n } = e; const o = t[0]; return { type: "accentUnder", mode: r.mode, label: n, base: o } }, htmlBuilder: (e, t) => { const r = ht(e.base, t), n = Nt(e, t), o = "\\utilde" === e.label ? .12 : 0, s = Ve.makeVList({ positionType: "top", positionData: r.height, children: [{ type: "elem", elem: n, wrapperClasses: ["svg-align"] }, { type: "kern", size: o }, { type: "elem", elem: r }] }, t); return Ve.makeSpan(["mord", "accentunder"], [s], t) }, mathmlBuilder: (e, t) => { const r = Ct(e.label), n = new gt.MathNode("munder", [vt(e.base, t), r]); return n.setAttribute("accentunder", "true"), n } }); const Lt = e => { const t = new gt.MathNode("mpadded", e ? [e] : []); return t.setAttribute("width", "+0.6em"), t.setAttribute("lspace", "0.3em"), t }; je({ type: "xArrow", names: ["\\xleftarrow", "\\xrightarrow", "\\xLeftarrow", "\\xRightarrow", "\\xleftrightarrow", "\\xLeftrightarrow", "\\xhookleftarrow", "\\xhookrightarrow", "\\xmapsto", "\\xrightharpoondown", "\\xrightharpoonup", "\\xleftharpoondown", "\\xleftharpoonup", "\\xrightleftharpoons", "\\xleftrightharpoons", "\\xlongequal", "\\xtwoheadrightarrow", "\\xtwoheadleftarrow", "\\xtofrom", "\\xrightleftarrows", "\\xrightequilibrium", "\\xleftequilibrium", "\\\\cdrightarrow", "\\\\cdleftarrow", "\\\\cdlongequal"], props: { numArgs: 1, numOptionalArgs: 1 }, handler(e, t, r) { let { parser: n, funcName: o } = e; return { type: "xArrow", mode: n.mode, label: o, body: t[0], below: r[0] } }, htmlBuilder(e, t) { const r = t.style; let n = t.havingStyle(r.sup()); const o = Ve.wrapFragment(ht(e.body, n, t), t), s = "\\x" === e.label.slice(0, 2) ? "x" : "cd"; let i; o.classes.push(s + "-arrow-pad"), e.below && (n = t.havingStyle(r.sub()), i = Ve.wrapFragment(ht(e.below, n, t), t), i.classes.push(s + "-arrow-pad")); const a = Nt(e, t), l = -t.fontMetrics().axisHeight + .5 * a.height; let h, c = -t.fontMetrics().axisHeight - .5 * a.height - .111; if ((o.depth > .25 || "\\xleftequilibrium" === e.label) && (c -= o.depth), i) { const e = -t.fontMetrics().axisHeight + i.height + .5 * a.height + .111; h = Ve.makeVList({ positionType: "individualShift", children: [{ type: "elem", elem: o, shift: c }, { type: "elem", elem: a, shift: l }, { type: "elem", elem: i, shift: e }] }, t) } else h = Ve.makeVList({ positionType: "individualShift", children: [{ type: "elem", elem: o, shift: c }, { type: "elem", elem: a, shift: l }] }, t); return h.children[0].children[0].children[1].classes.push("svg-align"), Ve.makeSpan(["mrel", "x-arrow"], [h], t) }, mathmlBuilder(e, t) { const r = Ct(e.label); let n; if (r.setAttribute("minsize", "x" === e.label.charAt(0) ? "1.75em" : "3.0em"), e.body) { const o = Lt(vt(e.body, t)); if (e.below) { const s = Lt(vt(e.below, t)); n = new gt.MathNode("munderover", [r, s, o]) } else n = new gt.MathNode("mover", [r, o]) } else if (e.below) { const o = Lt(vt(e.below, t)); n = new gt.MathNode("munder", [r, o]) } else n = Lt(), n = new gt.MathNode("mover", [r, n]); return n } }); const Dt = Ve.makeSpan; function Vt(e, t) { const r = nt(e.body, t, !0); return Dt([e.mclass], r, t) } function Pt(e, t) { let r; const n = xt(e.body, t); return "minner" === e.mclass ? r = new gt.MathNode("mpadded", n) : "mord" === e.mclass ? e.isCharacterBox ? (r = n[0], r.type = "mi") : r = new gt.MathNode("mi", n) : (e.isCharacterBox ? (r = n[0], r.type = "mo") : r = new gt.MathNode("mo", n), "mbin" === e.mclass ? (r.attributes.lspace = "0.22em", r.attributes.rspace = "0.22em") : "mpunct" === e.mclass ? (r.attributes.lspace = "0em", r.attributes.rspace = "0.17em") : "mopen" === e.mclass || "mclose" === e.mclass ? (r.attributes.lspace = "0em", r.attributes.rspace = "0em") : "minner" === e.mclass && (r.attributes.lspace = "0.0556em", r.attributes.width = "+0.1111em")), r } je({ type: "mclass", names: ["\\mathord", "\\mathbin", "\\mathrel", "\\mathopen", "\\mathclose", "\\mathpunct", "\\mathinner"], props: { numArgs: 1, primitive: !0 }, handler(e, t) { let { parser: r, funcName: n } = e; const o = t[0]; return { type: "mclass", mode: r.mode, mclass: "m" + n.slice(5), body: Ke(o), isCharacterBox: l.isCharacterBox(o) } }, htmlBuilder: Vt, mathmlBuilder: Pt }); const Ft = e => { const t = "ordgroup" === e.type && e.body.length ? e.body[0] : e; return "atom" !== t.type || "bin" !== t.family && "rel" !== t.family ? "mord" : "m" + t.family }; je({ type: "mclass", names: ["\\@binrel"], props: { numArgs: 2 }, handler(e, t) { let { parser: r } = e; return { type: "mclass", mode: r.mode, mclass: Ft(t[0]), body: Ke(t[1]), isCharacterBox: l.isCharacterBox(t[1]) } } }), je({ type: "mclass", names: ["\\stackrel", "\\overset", "\\underset"], props: { numArgs: 2 }, handler(e, t) { let { parser: r, funcName: n } = e; const o = t[1], s = t[0]; let i; i = "\\stackrel" !== n ? Ft(o) : "mrel"; const a = { type: "op", mode: o.mode, limits: !0, alwaysHandleSupSub: !0, parentIsSupSub: !1, symbol: !1, suppressBaseShift: "\\stackrel" !== n, body: Ke(o) }, h = { type: "supsub", mode: s.mode, base: a, sup: "\\underset" === n ? null : s, sub: "\\underset" === n ? s : null }; return { type: "mclass", mode: r.mode, mclass: i, body: [h], isCharacterBox: l.isCharacterBox(h) } }, htmlBuilder: Vt, mathmlBuilder: Pt }), je({ type: "pmb", names: ["\\pmb"], props: { numArgs: 1, allowedInText: !0 }, handler(e, t) { let { parser: r } = e; return { type: "pmb", mode: r.mode, mclass: Ft(t[0]), body: Ke(t[0]) } }, htmlBuilder(e, t) { const r = nt(e.body, t, !0), n = Ve.makeSpan([e.mclass], r, t); return n.style.textShadow = "0.02em 0.01em 0.04px", n }, mathmlBuilder(e, t) { const r = xt(e.body, t), n = new gt.MathNode("mstyle", r); return n.setAttribute("style", "text-shadow: 0.02em 0.01em 0.04px"), n } }); const Gt = { ">": "\\\\cdrightarrow", "<": "\\\\cdleftarrow", "=": "\\\\cdlongequal", A: "\\uparrow", V: "\\downarrow", "|": "\\Vert", ".": "no arrow" }, Ut = e => "textord" === e.type && "@" === e.text; function Yt(e, t, r) { const n = Gt[e]; switch (n) { case "\\\\cdrightarrow": case "\\\\cdleftarrow": return r.callFunction(n, [t[0]], [t[1]]); case "\\uparrow": case "\\downarrow": { const e = { type: "atom", text: n, mode: "math", family: "rel" }, o = { type: "ordgroup", mode: "math", body: [r.callFunction("\\\\cdleft", [t[0]], []), r.callFunction("\\Big", [e], []), r.callFunction("\\\\cdright", [t[1]], [])] }; return r.callFunction("\\\\cdparent", [o], []) } case "\\\\cdlongequal": return r.callFunction("\\\\cdlongequal", [], []); case "\\Vert": { const e = { type: "textord", text: "\\Vert", mode: "math" }; return r.callFunction("\\Big", [e], []) } default: return { type: "textord", text: " ", mode: "math" } } } je({ type: "cdlabel", names: ["\\\\cdleft", "\\\\cdright"], props: { numArgs: 1 }, handler(e, t) { let { parser: r, funcName: n } = e; return { type: "cdlabel", mode: r.mode, side: n.slice(4), label: t[0] } }, htmlBuilder(e, t) { const r = t.havingStyle(t.style.sup()), n = Ve.wrapFragment(ht(e.label, r, t), t); return n.classes.push("cd-label-" + e.side), n.style.bottom = F(.8 - n.depth), n.height = 0, n.depth = 0, n }, mathmlBuilder(e, t) { let r = new gt.MathNode("mrow", [vt(e.label, t)]); return r = new gt.MathNode("mpadded", [r]), r.setAttribute("width", "0"), "left" === e.side && r.setAttribute("lspace", "-1width"), r.setAttribute("voffset", "0.7em"), r = new gt.MathNode("mstyle", [r]), r.setAttribute("displaystyle", "false"), r.setAttribute("scriptlevel", "1"), r } }), je({ type: "cdlabelparent", names: ["\\\\cdparent"], props: { numArgs: 1 }, handler(e, t) { let { parser: r } = e; return { type: "cdlabelparent", mode: r.mode, fragment: t[0] } }, htmlBuilder(e, t) { const r = Ve.wrapFragment(ht(e.fragment, t), t); return r.classes.push("cd-vert-arrow"), r }, mathmlBuilder(e, t) { return new gt.MathNode("mrow", [vt(e.fragment, t)]) } }), je({ type: "textord", names: ["\\@char"], props: { numArgs: 1, allowedInText: !0 }, handler(e, t) { let { parser: r } = e; const o = qt(t[0], "ordgroup").body; let s = ""; for (let e = 0; e < o.length; e++) { s += qt(o[e], "textord").text } let i, a = parseInt(s); if (isNaN(a)) throw new n("\\@char has non-numeric argument " + s); if (a < 0 || a >= 1114111) throw new n("\\@char with invalid code point " + s); return a <= 65535 ? i = String.fromCharCode(a) : (a -= 65536, i = String.fromCharCode(55296 + (a >> 10), 56320 + (1023 & a))), { type: "textord", mode: r.mode, text: i } } }); const Xt = (e, t) => { const r = nt(e.body, t.withColor(e.color), !1); return Ve.makeFragment(r) }, Wt = (e, t) => { const r = xt(e.body, t.withColor(e.color)), n = new gt.MathNode("mstyle", r); return n.setAttribute("mathcolor", e.color), n }; je({ type: "color", names: ["\\textcolor"], props: { numArgs: 2, allowedInText: !0, argTypes: ["color", "original"] }, handler(e, t) { let { parser: r } = e; const n = qt(t[0], "color-token").color, o = t[1]; return { type: "color", mode: r.mode, color: n, body: Ke(o) } }, htmlBuilder: Xt, mathmlBuilder: Wt }), je({ type: "color", names: ["\\color"], props: { numArgs: 1, allowedInText: !0, argTypes: ["color"] }, handler(e, t) { let { parser: r, breakOnTokenText: n } = e; const o = qt(t[0], "color-token").color; r.gullet.macros.set("\\current@color", o); const s = r.parseExpression(!0, n); return { type: "color", mode: r.mode, color: o, body: s } }, htmlBuilder: Xt, mathmlBuilder: Wt }), je({ type: "cr", names: ["\\\\"], props: { numArgs: 0, numOptionalArgs: 0, allowedInText: !0 }, handler(e, t, r) { let { parser: n } = e; const o = "[" === n.gullet.future().text ? n.parseSizeGroup(!0) : null, s = !n.settings.displayMode || !n.settings.useStrictBehavior("newLineInDisplayMode", "In LaTeX, \\\\ or \\newline does nothing in display mode"); return { type: "cr", mode: n.mode, newLine: s, size: o && qt(o, "size").value } }, htmlBuilder(e, t) { const r = Ve.makeSpan(["mspace"], [], t); return e.newLine && (r.classes.push("newline"), e.size && (r.style.marginTop = F(P(e.size, t)))), r }, mathmlBuilder(e, t) { const r = new gt.MathNode("mspace"); return e.newLine && (r.setAttribute("linebreak", "newline"), e.size && r.setAttribute("height", F(P(e.size, t)))), r } }); const _t = { "\\global": "\\global", "\\long": "\\\\globallong", "\\\\globallong": "\\\\globallong", "\\def": "\\gdef", "\\gdef": "\\gdef", "\\edef": "\\xdef", "\\xdef": "\\xdef", "\\let": "\\\\globallet", "\\futurelet": "\\\\globalfuture" }, jt = e => { const t = e.text; if (/^(?:[\\{}$&#^_]|EOF)$/.test(t)) throw new n("Expected a control sequence", e); return t }, $t = (e, t, r, n) => { let o = e.gullet.macros.get(r.text); null == o && (r.noexpand = !0, o = { tokens: [r], numArgs: 0, unexpandable: !e.gullet.isExpandable(r.text) }), e.gullet.macros.set(t, o, n) }; je({ type: "internal", names: ["\\global", "\\long", "\\\\globallong"], props: { numArgs: 0, allowedInText: !0 }, handler(e) { let { parser: t, funcName: r } = e; t.consumeSpaces(); const o = t.fetch(); if (_t[o.text]) return "\\global" !== r && "\\\\globallong" !== r || (o.text = _t[o.text]), qt(t.parseFunction(), "internal"); throw new n("Invalid token after macro prefix", o) } }), je({ type: "internal", names: ["\\def", "\\gdef", "\\edef", "\\xdef"], props: { numArgs: 0, allowedInText: !0, primitive: !0 }, handler(e) { let { parser: t, funcName: r } = e, o = t.gullet.popToken(); const s = o.text; if (/^(?:[\\{}$&#^_]|EOF)$/.test(s)) throw new n("Expected a control sequence", o); let i, a = 0; const l = [[]]; for (; "{" !== t.gullet.future().text;)if (o = t.gullet.popToken(), "#" === o.text) { if ("{" === t.gullet.future().text) { i = t.gullet.future(), l[a].push("{"); break } if (o = t.gullet.popToken(), !/^[1-9]$/.test(o.text)) throw new n('Invalid argument number "' + o.text + '"'); if (parseInt(o.text) !== a + 1) throw new n('Argument number "' + o.text + '" out of order'); a++, l.push([]) } else { if ("EOF" === o.text) throw new n("Expected a macro definition"); l[a].push(o.text) } let { tokens: h } = t.gullet.consumeArg(); return i && h.unshift(i), "\\edef" !== r && "\\xdef" !== r || (h = t.gullet.expandTokens(h), h.reverse()), t.gullet.macros.set(s, { tokens: h, numArgs: a, delimiters: l }, r === _t[r]), { type: "internal", mode: t.mode } } }), je({ type: "internal", names: ["\\let", "\\\\globallet"], props: { numArgs: 0, allowedInText: !0, primitive: !0 }, handler(e) { let { parser: t, funcName: r } = e; const n = jt(t.gullet.popToken()); t.gullet.consumeSpaces(); const o = (e => { let t = e.gullet.popToken(); return "=" === t.text && (t = e.gullet.popToken(), " " === t.text && (t = e.gullet.popToken())), t })(t); return $t(t, n, o, "\\\\globallet" === r), { type: "internal", mode: t.mode } } }), je({ type: "internal", names: ["\\futurelet", "\\\\globalfuture"], props: { numArgs: 0, allowedInText: !0, primitive: !0 }, handler(e) { let { parser: t, funcName: r } = e; const n = jt(t.gullet.popToken()), o = t.gullet.popToken(), s = t.gullet.popToken(); return $t(t, n, s, "\\\\globalfuture" === r), t.gullet.pushToken(s), t.gullet.pushToken(o), { type: "internal", mode: t.mode } } }); const Zt = function (e, t, r) { const n = N(oe.math[e] && oe.math[e].replace || e, t, r); if (!n) throw new Error("Unsupported symbol " + e + " and font size " + t + "."); return n }, Kt = function (e, t, r, n) { const o = r.havingBaseStyle(t), s = Ve.makeSpan(n.concat(o.sizingClasses(r)), [e], r), i = o.sizeMultiplier / r.sizeMultiplier; return s.height *= i, s.depth *= i, s.maxFontSize = o.sizeMultiplier, s }, Jt = function (e, t, r) { const n = t.havingBaseStyle(r), o = (1 - t.sizeMultiplier / n.sizeMultiplier) * t.fontMetrics().axisHeight; e.classes.push("delimcenter"), e.style.top = F(o), e.height -= o, e.depth += o }, Qt = function (e, t, r, n, o, s) { const i = function (e, t, r, n) { return Ve.makeSymbol(e, "Size" + t + "-Regular", r, n) }(e, t, o, n), a = Kt(Ve.makeSpan(["delimsizing", "size" + t], [i], n), w.TEXT, n, s); return r && Jt(a, n, w.TEXT), a }, er = function (e, t, r) { let n; n = "Size1-Regular" === t ? "delim-size1" : "delim-size4"; return { type: "elem", elem: Ve.makeSpan(["delimsizinginner", n], [Ve.makeSpan([], [Ve.makeSymbol(e, t, r)])]) } }, tr = function (e, t, r) { const n = T["Size4-Regular"][e.charCodeAt(0)] ? T["Size4-Regular"][e.charCodeAt(0)][4] : T["Size1-Regular"][e.charCodeAt(0)][4], o = new J("inner", function (e, t) { switch (e) { case "\u239c": return "M291 0 H417 V" + t + " H291z M291 0 H417 V" + t + " H291z"; case "\u2223": return "M145 0 H188 V" + t + " H145z M145 0 H188 V" + t + " H145z"; case "\u2225": return "M145 0 H188 V" + t + " H145z M145 0 H188 V" + t + " H145zM367 0 H410 V" + t + " H367z M367 0 H410 V" + t + " H367z"; case "\u239f": return "M457 0 H583 V" + t + " H457z M457 0 H583 V" + t + " H457z"; case "\u23a2": return "M319 0 H403 V" + t + " H319z M319 0 H403 V" + t + " H319z"; case "\u23a5": return "M263 0 H347 V" + t + " H263z M263 0 H347 V" + t + " H263z"; case "\u23aa": return "M384 0 H504 V" + t + " H384z M384 0 H504 V" + t + " H384z"; case "\u23d0": return "M312 0 H355 V" + t + " H312z M312 0 H355 V" + t + " H312z"; case "\u2016": return "M257 0 H300 V" + t + " H257z M257 0 H300 V" + t + " H257zM478 0 H521 V" + t + " H478z M478 0 H521 V" + t + " H478z"; default: return "" } }(e, Math.round(1e3 * t))), s = new K([o], { width: F(n), height: F(t), style: "width:" + F(n), viewBox: "0 0 " + 1e3 * n + " " + Math.round(1e3 * t), preserveAspectRatio: "xMinYMin" }), i = Ve.makeSvgSpan([], [s], r); return i.height = t, i.style.height = F(t), i.style.width = F(n), { type: "elem", elem: i } }, rr = { type: "kern", size: -.008 }, nr = ["|", "\\lvert", "\\rvert", "\\vert"], or = ["\\|", "\\lVert", "\\rVert", "\\Vert"], sr = function (e, t, r, n, o, s) { let i, a, h, c, m = "", p = 0; i = h = c = e, a = null; let u = "Size1-Regular"; "\\uparrow" === e ? h = c = "\u23d0" : "\\Uparrow" === e ? h = c = "\u2016" : "\\downarrow" === e ? i = h = "\u23d0" : "\\Downarrow" === e ? i = h = "\u2016" : "\\updownarrow" === e ? (i = "\\uparrow", h = "\u23d0", c = "\\downarrow") : "\\Updownarrow" === e ? (i = "\\Uparrow", h = "\u2016", c = "\\Downarrow") : l.contains(nr, e) ? (h = "\u2223", m = "vert", p = 333) : l.contains(or, e) ? (h = "\u2225", m = "doublevert", p = 556) : "[" === e || "\\lbrack" === e ? (i = "\u23a1", h = "\u23a2", c = "\u23a3", u = "Size4-Regular", m = "lbrack", p = 667) : "]" === e || "\\rbrack" === e ? (i = "\u23a4", h = "\u23a5", c = "\u23a6", u = "Size4-Regular", m = "rbrack", p = 667) : "\\lfloor" === e || "\u230a" === e ? (h = i = "\u23a2", c = "\u23a3", u = "Size4-Regular", m = "lfloor", p = 667) : "\\lceil" === e || "\u2308" === e ? (i = "\u23a1", h = c = "\u23a2", u = "Size4-Regular", m = "lceil", p = 667) : "\\rfloor" === e || "\u230b" === e ? (h = i = "\u23a5", c = "\u23a6", u = "Size4-Regular", m = "rfloor", p = 667) : "\\rceil" === e || "\u2309" === e ? (i = "\u23a4", h = c = "\u23a5", u = "Size4-Regular", m = "rceil", p = 667) : "(" === e || "\\lparen" === e ? (i = "\u239b", h = "\u239c", c = "\u239d", u = "Size4-Regular", m = "lparen", p = 875) : ")" === e || "\\rparen" === e ? (i = "\u239e", h = "\u239f", c = "\u23a0", u = "Size4-Regular", m = "rparen", p = 875) : "\\{" === e || "\\lbrace" === e ? (i = "\u23a7", a = "\u23a8", c = "\u23a9", h = "\u23aa", u = "Size4-Regular") : "\\}" === e || "\\rbrace" === e ? (i = "\u23ab", a = "\u23ac", c = "\u23ad", h = "\u23aa", u = "Size4-Regular") : "\\lgroup" === e || "\u27ee" === e ? (i = "\u23a7", c = "\u23a9", h = "\u23aa", u = "Size4-Regular") : "\\rgroup" === e || "\u27ef" === e ? (i = "\u23ab", c = "\u23ad", h = "\u23aa", u = "Size4-Regular") : "\\lmoustache" === e || "\u23b0" === e ? (i = "\u23a7", c = "\u23ad", h = "\u23aa", u = "Size4-Regular") : "\\rmoustache" !== e && "\u23b1" !== e || (i = "\u23ab", c = "\u23a9", h = "\u23aa", u = "Size4-Regular"); const d = Zt(i, u, o), g = d.height + d.depth, f = Zt(h, u, o), b = f.height + f.depth, y = Zt(c, u, o), x = y.height + y.depth; let v = 0, k = 1; if (null !== a) { const e = Zt(a, u, o); v = e.height + e.depth, k = 2 } const S = g + x + v, M = S + Math.max(0, Math.ceil((t - S) / (k * b))) * k * b; let z = n.fontMetrics().axisHeight; r && (z *= n.sizeMultiplier); const A = M / 2 - z, T = []; if (m.length > 0) { const e = M - g - x, t = Math.round(1e3 * M), r = function (e, t) { switch (e) { case "lbrack": return "M403 1759 V84 H666 V0 H319 V1759 v" + t + " v1759 h347 v-84\nH403z M403 1759 V0 H319 V1759 v" + t + " v1759 h84z"; case "rbrack": return "M347 1759 V0 H0 V84 H263 V1759 v" + t + " v1759 H0 v84 H347z\nM347 1759 V0 H263 V1759 v" + t + " v1759 h84z"; case "vert": return "M145 15 v585 v" + t + " v585 c2.667,10,9.667,15,21,15\nc10,0,16.667,-5,20,-15 v-585 v" + -t + " v-585 c-2.667,-10,-9.667,-15,-21,-15\nc-10,0,-16.667,5,-20,15z M188 15 H145 v585 v" + t + " v585 h43z"; case "doublevert": return "M145 15 v585 v" + t + " v585 c2.667,10,9.667,15,21,15\nc10,0,16.667,-5,20,-15 v-585 v" + -t + " v-585 c-2.667,-10,-9.667,-15,-21,-15\nc-10,0,-16.667,5,-20,15z M188 15 H145 v585 v" + t + " v585 h43z\nM367 15 v585 v" + t + " v585 c2.667,10,9.667,15,21,15\nc10,0,16.667,-5,20,-15 v-585 v" + -t + " v-585 c-2.667,-10,-9.667,-15,-21,-15\nc-10,0,-16.667,5,-20,15z M410 15 H367 v585 v" + t + " v585 h43z"; case "lfloor": return "M319 602 V0 H403 V602 v" + t + " v1715 h263 v84 H319z\nMM319 602 V0 H403 V602 v" + t + " v1715 H319z"; case "rfloor": return "M319 602 V0 H403 V602 v" + t + " v1799 H0 v-84 H319z\nMM319 602 V0 H403 V602 v" + t + " v1715 H319z"; case "lceil": return "M403 1759 V84 H666 V0 H319 V1759 v" + t + " v602 h84z\nM403 1759 V0 H319 V1759 v" + t + " v602 h84z"; case "rceil": return "M347 1759 V0 H0 V84 H263 V1759 v" + t + " v602 h84z\nM347 1759 V0 h-84 V1759 v" + t + " v602 h84z"; case "lparen": return "M863,9c0,-2,-2,-5,-6,-9c0,0,-17,0,-17,0c-12.7,0,-19.3,0.3,-20,1\nc-5.3,5.3,-10.3,11,-15,17c-242.7,294.7,-395.3,682,-458,1162c-21.3,163.3,-33.3,349,\n-36,557 l0," + (t + 84) + "c0.2,6,0,26,0,60c2,159.3,10,310.7,24,454c53.3,528,210,\n949.7,470,1265c4.7,6,9.7,11.7,15,17c0.7,0.7,7,1,19,1c0,0,18,0,18,0c4,-4,6,-7,6,-9\nc0,-2.7,-3.3,-8.7,-10,-18c-135.3,-192.7,-235.5,-414.3,-300.5,-665c-65,-250.7,-102.5,\n-544.7,-112.5,-882c-2,-104,-3,-167,-3,-189\nl0,-" + (t + 92) + "c0,-162.7,5.7,-314,17,-454c20.7,-272,63.7,-513,129,-723c65.3,\n-210,155.3,-396.3,270,-559c6.7,-9.3,10,-15.3,10,-18z"; case "rparen": return "M76,0c-16.7,0,-25,3,-25,9c0,2,2,6.3,6,13c21.3,28.7,42.3,60.3,\n63,95c96.7,156.7,172.8,332.5,228.5,527.5c55.7,195,92.8,416.5,111.5,664.5\nc11.3,139.3,17,290.7,17,454c0,28,1.7,43,3.3,45l0," + (t + 9) + "\nc-3,4,-3.3,16.7,-3.3,38c0,162,-5.7,313.7,-17,455c-18.7,248,-55.8,469.3,-111.5,664\nc-55.7,194.7,-131.8,370.3,-228.5,527c-20.7,34.7,-41.7,66.3,-63,95c-2,3.3,-4,7,-6,11\nc0,7.3,5.7,11,17,11c0,0,11,0,11,0c9.3,0,14.3,-0.3,15,-1c5.3,-5.3,10.3,-11,15,-17\nc242.7,-294.7,395.3,-681.7,458,-1161c21.3,-164.7,33.3,-350.7,36,-558\nl0,-" + (t + 144) + "c-2,-159.3,-10,-310.7,-24,-454c-53.3,-528,-210,-949.7,\n-470,-1265c-4.7,-6,-9.7,-11.7,-15,-17c-0.7,-0.7,-6.7,-1,-18,-1z"; default: throw new Error("Unknown stretchy delimiter.") } }(m, Math.round(1e3 * e)), o = new J(m, r), s = (p / 1e3).toFixed(3) + "em", i = (t / 1e3).toFixed(3) + "em", a = new K([o], { width: s, height: i, viewBox: "0 0 " + p + " " + t }), l = Ve.makeSvgSpan([], [a], n); l.height = t / 1e3, l.style.width = s, l.style.height = i, T.push({ type: "elem", elem: l }) } else { if (T.push(er(c, u, o)), T.push(rr), null === a) { const e = M - g - x + .016; T.push(tr(h, e, n)) } else { const e = (M - g - x - v) / 2 + .016; T.push(tr(h, e, n)), T.push(rr), T.push(er(a, u, o)), T.push(rr), T.push(tr(h, e, n)) } T.push(rr), T.push(er(i, u, o)) } const B = n.havingBaseStyle(w.TEXT), C = Ve.makeVList({ positionType: "bottom", positionData: A, children: T }, B); return Kt(Ve.makeSpan(["delimsizing", "mult"], [C], B), w.TEXT, n, s) }, ir = .08, ar = function (e, t, r, n, o) { const s = function (e, t, r) { t *= 1e3; let n = ""; switch (e) { case "sqrtMain": n = function (e, t) { return "M95," + (622 + e + t) + "\nc-2.7,0,-7.17,-2.7,-13.5,-8c-5.8,-5.3,-9.5,-10,-9.5,-14\nc0,-2,0.3,-3.3,1,-4c1.3,-2.7,23.83,-20.7,67.5,-54\nc44.2,-33.3,65.8,-50.3,66.5,-51c1.3,-1.3,3,-2,5,-2c4.7,0,8.7,3.3,12,10\ns173,378,173,378c0.7,0,35.3,-71,104,-213c68.7,-142,137.5,-285,206.5,-429\nc69,-144,104.5,-217.7,106.5,-221\nl" + e / 2.075 + " -" + e + "\nc5.3,-9.3,12,-14,20,-14\nH400000v" + (40 + e) + "H845.2724\ns-225.272,467,-225.272,467s-235,486,-235,486c-2.7,4.7,-9,7,-19,7\nc-6,0,-10,-1,-12,-3s-194,-422,-194,-422s-65,47,-65,47z\nM" + (834 + e) + " " + t + "h400000v" + (40 + e) + "h-400000z" }(t, M); break; case "sqrtSize1": n = function (e, t) { return "M263," + (601 + e + t) + "c0.7,0,18,39.7,52,119\nc34,79.3,68.167,158.7,102.5,238c34.3,79.3,51.8,119.3,52.5,120\nc340,-704.7,510.7,-1060.3,512,-1067\nl" + e / 2.084 + " -" + e + "\nc4.7,-7.3,11,-11,19,-11\nH40000v" + (40 + e) + "H1012.3\ns-271.3,567,-271.3,567c-38.7,80.7,-84,175,-136,283c-52,108,-89.167,185.3,-111.5,232\nc-22.3,46.7,-33.8,70.3,-34.5,71c-4.7,4.7,-12.3,7,-23,7s-12,-1,-12,-1\ns-109,-253,-109,-253c-72.7,-168,-109.3,-252,-110,-252c-10.7,8,-22,16.7,-34,26\nc-22,17.3,-33.3,26,-34,26s-26,-26,-26,-26s76,-59,76,-59s76,-60,76,-60z\nM" + (1001 + e) + " " + t + "h400000v" + (40 + e) + "h-400000z" }(t, M); break; case "sqrtSize2": n = function (e, t) { return "M983 " + (10 + e + t) + "\nl" + e / 3.13 + " -" + e + "\nc4,-6.7,10,-10,18,-10 H400000v" + (40 + e) + "\nH1013.1s-83.4,268,-264.1,840c-180.7,572,-277,876.3,-289,913c-4.7,4.7,-12.7,7,-24,7\ns-12,0,-12,0c-1.3,-3.3,-3.7,-11.7,-7,-25c-35.3,-125.3,-106.7,-373.3,-214,-744\nc-10,12,-21,25,-33,39s-32,39,-32,39c-6,-5.3,-15,-14,-27,-26s25,-30,25,-30\nc26.7,-32.7,52,-63,76,-91s52,-60,52,-60s208,722,208,722\nc56,-175.3,126.3,-397.3,211,-666c84.7,-268.7,153.8,-488.2,207.5,-658.5\nc53.7,-170.3,84.5,-266.8,92.5,-289.5z\nM" + (1001 + e) + " " + t + "h400000v" + (40 + e) + "h-400000z" }(t, M); break; case "sqrtSize3": n = function (e, t) { return "M424," + (2398 + e + t) + "\nc-1.3,-0.7,-38.5,-172,-111.5,-514c-73,-342,-109.8,-513.3,-110.5,-514\nc0,-2,-10.7,14.3,-32,49c-4.7,7.3,-9.8,15.7,-15.5,25c-5.7,9.3,-9.8,16,-12.5,20\ns-5,7,-5,7c-4,-3.3,-8.3,-7.7,-13,-13s-13,-13,-13,-13s76,-122,76,-122s77,-121,77,-121\ns209,968,209,968c0,-2,84.7,-361.7,254,-1079c169.3,-717.3,254.7,-1077.7,256,-1081\nl" + e / 4.223 + " -" + e + "c4,-6.7,10,-10,18,-10 H400000\nv" + (40 + e) + "H1014.6\ns-87.3,378.7,-272.6,1166c-185.3,787.3,-279.3,1182.3,-282,1185\nc-2,6,-10,9,-24,9\nc-8,0,-12,-0.7,-12,-2z M" + (1001 + e) + " " + t + "\nh400000v" + (40 + e) + "h-400000z" }(t, M); break; case "sqrtSize4": n = function (e, t) { return "M473," + (2713 + e + t) + "\nc339.3,-1799.3,509.3,-2700,510,-2702 l" + e / 5.298 + " -" + e + "\nc3.3,-7.3,9.3,-11,18,-11 H400000v" + (40 + e) + "H1017.7\ns-90.5,478,-276.2,1466c-185.7,988,-279.5,1483,-281.5,1485c-2,6,-10,9,-24,9\nc-8,0,-12,-0.7,-12,-2c0,-1.3,-5.3,-32,-16,-92c-50.7,-293.3,-119.7,-693.3,-207,-1200\nc0,-1.3,-5.3,8.7,-16,30c-10.7,21.3,-21.3,42.7,-32,64s-16,33,-16,33s-26,-26,-26,-26\ns76,-153,76,-153s77,-151,77,-151c0.7,0.7,35.7,202,105,604c67.3,400.7,102,602.7,104,\n606zM" + (1001 + e) + " " + t + "h400000v" + (40 + e) + "H1017.7z" }(t, M); break; case "sqrtTall": n = function (e, t, r) { return "M702 " + (e + t) + "H400000" + (40 + e) + "\nH742v" + (r - 54 - t - e) + "l-4 4-4 4c-.667.7 -2 1.5-4 2.5s-4.167 1.833-6.5 2.5-5.5 1-9.5 1\nh-12l-28-84c-16.667-52-96.667 -294.333-240-727l-212 -643 -85 170\nc-4-3.333-8.333-7.667-13 -13l-13-13l77-155 77-156c66 199.333 139 419.667\n219 661 l218 661zM702 " + t + "H400000v" + (40 + e) + "H742z" }(t, M, r) }return n }(e, n, r), i = new J(e, s), a = new K([i], { width: "400em", height: F(t), viewBox: "0 0 400000 " + r, preserveAspectRatio: "xMinYMin slice" }); return Ve.makeSvgSpan(["hide-tail"], [a], o) }, lr = ["(", "\\lparen", ")", "\\rparen", "[", "\\lbrack", "]", "\\rbrack", "\\{", "\\lbrace", "\\}", "\\rbrace", "\\lfloor", "\\rfloor", "\u230a", "\u230b", "\\lceil", "\\rceil", "\u2308", "\u2309", "\\surd"], hr = ["\\uparrow", "\\downarrow", "\\updownarrow", "\\Uparrow", "\\Downarrow", "\\Updownarrow", "|", "\\|", "\\vert", "\\Vert", "\\lvert", "\\rvert", "\\lVert", "\\rVert", "\\lgroup", "\\rgroup", "\u27ee", "\u27ef", "\\lmoustache", "\\rmoustache", "\u23b0", "\u23b1"], cr = ["<", ">", "\\langle", "\\rangle", "/", "\\backslash", "\\lt", "\\gt"], mr = [0, 1.2, 1.8, 2.4, 3], pr = [{ type: "small", style: w.SCRIPTSCRIPT }, { type: "small", style: w.SCRIPT }, { type: "small", style: w.TEXT }, { type: "large", size: 1 }, { type: "large", size: 2 }, { type: "large", size: 3 }, { type: "large", size: 4 }], ur = [{ type: "small", style: w.SCRIPTSCRIPT }, { type: "small", style: w.SCRIPT }, { type: "small", style: w.TEXT }, { type: "stack" }], dr = [{ type: "small", style: w.SCRIPTSCRIPT }, { type: "small", style: w.SCRIPT }, { type: "small", style: w.TEXT }, { type: "large", size: 1 }, { type: "large", size: 2 }, { type: "large", size: 3 }, { type: "large", size: 4 }, { type: "stack" }], gr = function (e) { if ("small" === e.type) return "Main-Regular"; if ("large" === e.type) return "Size" + e.size + "-Regular"; if ("stack" === e.type) return "Size4-Regular"; throw new Error("Add support for delim type '" + e.type + "' here.") }, fr = function (e, t, r, n) { for (let o = Math.min(2, 3 - n.style.size); o < r.length && "stack" !== r[o].type; o++) { const s = Zt(e, gr(r[o]), "math"); let i = s.height + s.depth; if ("small" === r[o].type) { i *= n.havingBaseStyle(r[o].style).sizeMultiplier } if (i > t) return r[o] } return r[r.length - 1] }, br = function (e, t, r, n, o, s) { let i; "<" === e || "\\lt" === e || "\u27e8" === e ? e = "\\langle" : ">" !== e && "\\gt" !== e && "\u27e9" !== e || (e = "\\rangle"), i = l.contains(cr, e) ? pr : l.contains(lr, e) ? dr : ur; const a = fr(e, t, i, n); return "small" === a.type ? function (e, t, r, n, o, s) { const i = Ve.makeSymbol(e, "Main-Regular", o, n), a = Kt(i, t, n, s); return r && Jt(a, n, t), a }(e, a.style, r, n, o, s) : "large" === a.type ? Qt(e, a.size, r, n, o, s) : sr(e, t, r, n, o, s) }; var yr = { sqrtImage: function (e, t) { const r = t.havingBaseSizing(), n = fr("\\surd", e * r.sizeMultiplier, dr, r); let o = r.sizeMultiplier; const s = Math.max(0, t.minRuleThickness - t.fontMetrics().sqrtRuleThickness); let i, a, l = 0, h = 0, c = 0; return "small" === n.type ? (c = 1e3 + 1e3 * s + 80, e < 1 ? o = 1 : e < 1.4 && (o = .7), l = (1 + s + ir) / o, h = (1 + s) / o, i = ar("sqrtMain", l, c, s, t), i.style.minWidth = "0.853em", a = .833 / o) : "large" === n.type ? (c = 1080 * mr[n.size], h = (mr[n.size] + s) / o, l = (mr[n.size] + s + ir) / o, i = ar("sqrtSize" + n.size, l, c, s, t), i.style.minWidth = "1.02em", a = 1 / o) : (l = e + s + ir, h = e + s, c = Math.floor(1e3 * e + s) + 80, i = ar("sqrtTall", l, c, s, t), i.style.minWidth = "0.742em", a = 1.056), i.height = h, i.style.height = F(l), { span: i, advanceWidth: a, ruleWidth: (t.fontMetrics().sqrtRuleThickness + s) * o } }, sizedDelim: function (e, t, r, o, s) { if ("<" === e || "\\lt" === e || "\u27e8" === e ? e = "\\langle" : ">" !== e && "\\gt" !== e && "\u27e9" !== e || (e = "\\rangle"), l.contains(lr, e) || l.contains(cr, e)) return Qt(e, t, !1, r, o, s); if (l.contains(hr, e)) return sr(e, mr[t], !1, r, o, s); throw new n("Illegal delimiter: '" + e + "'") }, sizeToMaxHeight: mr, customSizedDelim: br, leftRightDelim: function (e, t, r, n, o, s) { const i = n.fontMetrics().axisHeight * n.sizeMultiplier, a = 5 / n.fontMetrics().ptPerEm, l = Math.max(t - i, r + i), h = Math.max(l / 500 * 901, 2 * l - a); return br(e, h, !0, n, o, s) } }; const xr = { "\\bigl": { mclass: "mopen", size: 1 }, "\\Bigl": { mclass: "mopen", size: 2 }, "\\biggl": { mclass: "mopen", size: 3 }, "\\Biggl": { mclass: "mopen", size: 4 }, "\\bigr": { mclass: "mclose", size: 1 }, "\\Bigr": { mclass: "mclose", size: 2 }, "\\biggr": { mclass: "mclose", size: 3 }, "\\Biggr": { mclass: "mclose", size: 4 }, "\\bigm": { mclass: "mrel", size: 1 }, "\\Bigm": { mclass: "mrel", size: 2 }, "\\biggm": { mclass: "mrel", size: 3 }, "\\Biggm": { mclass: "mrel", size: 4 }, "\\big": { mclass: "mord", size: 1 }, "\\Big": { mclass: "mord", size: 2 }, "\\bigg": { mclass: "mord", size: 3 }, "\\Bigg": { mclass: "mord", size: 4 } }, wr = ["(", "\\lparen", ")", "\\rparen", "[", "\\lbrack", "]", "\\rbrack", "\\{", "\\lbrace", "\\}", "\\rbrace", "\\lfloor", "\\rfloor", "\u230a", "\u230b", "\\lceil", "\\rceil", "\u2308", "\u2309", "<", ">", "\\langle", "\u27e8", "\\rangle", "\u27e9", "\\lt", "\\gt", "\\lvert", "\\rvert", "\\lVert", "\\rVert", "\\lgroup", "\\rgroup", "\u27ee", "\u27ef", "\\lmoustache", "\\rmoustache", "\u23b0", "\u23b1", "/", "\\backslash", "|", "\\vert", "\\|", "\\Vert", "\\uparrow", "\\Uparrow", "\\downarrow", "\\Downarrow", "\\updownarrow", "\\Updownarrow", "."]; function vr(e, t) { const r = Rt(e); if (r && l.contains(wr, r.text)) return r; throw new n(r ? "Invalid delimiter '" + r.text + "' after '" + t.funcName + "'" : "Invalid delimiter type '" + e.type + "'", e) } function kr(e) { if (!e.body) throw new Error("Bug: The leftright ParseNode wasn't fully parsed.") } je({ type: "delimsizing", names: ["\\bigl", "\\Bigl", "\\biggl", "\\Biggl", "\\bigr", "\\Bigr", "\\biggr", "\\Biggr", "\\bigm", "\\Bigm", "\\biggm", "\\Biggm", "\\big", "\\Big", "\\bigg", "\\Bigg"], props: { numArgs: 1, argTypes: ["primitive"] }, handler: (e, t) => { const r = vr(t[0], e); return { type: "delimsizing", mode: e.parser.mode, size: xr[e.funcName].size, mclass: xr[e.funcName].mclass, delim: r.text } }, htmlBuilder: (e, t) => "." === e.delim ? Ve.makeSpan([e.mclass]) : yr.sizedDelim(e.delim, e.size, t, e.mode, [e.mclass]), mathmlBuilder: e => { const t = []; "." !== e.delim && t.push(ft(e.delim, e.mode)); const r = new gt.MathNode("mo", t); "mopen" === e.mclass || "mclose" === e.mclass ? r.setAttribute("fence", "true") : r.setAttribute("fence", "false"), r.setAttribute("stretchy", "true"); const n = F(yr.sizeToMaxHeight[e.size]); return r.setAttribute("minsize", n), r.setAttribute("maxsize", n), r } }), je({ type: "leftright-right", names: ["\\right"], props: { numArgs: 1, primitive: !0 }, handler: (e, t) => { const r = e.parser.gullet.macros.get("\\current@color"); if (r && "string" != typeof r) throw new n("\\current@color set to non-string in \\right"); return { type: "leftright-right", mode: e.parser.mode, delim: vr(t[0], e).text, color: r } } }), je({ type: "leftright", names: ["\\left"], props: { numArgs: 1, primitive: !0 }, handler: (e, t) => { const r = vr(t[0], e), n = e.parser; ++n.leftrightDepth; const o = n.parseExpression(!1); --n.leftrightDepth, n.expect("\\right", !1); const s = qt(n.parseFunction(), "leftright-right"); return { type: "leftright", mode: n.mode, body: o, left: r.text, right: s.delim, rightColor: s.color } }, htmlBuilder: (e, t) => { kr(e); const r = nt(e.body, t, !0, ["mopen", "mclose"]); let n, o, s = 0, i = 0, a = !1; for (let e = 0; e < r.length; e++)r[e].isMiddle ? a = !0 : (s = Math.max(r[e].height, s), i = Math.max(r[e].depth, i)); if (s *= t.sizeMultiplier, i *= t.sizeMultiplier, n = "." === e.left ? lt(t, ["mopen"]) : yr.leftRightDelim(e.left, s, i, t, e.mode, ["mopen"]), r.unshift(n), a) for (let t = 1; t < r.length; t++) { const n = r[t].isMiddle; n && (r[t] = yr.leftRightDelim(n.delim, s, i, n.options, e.mode, [])) } if ("." === e.right) o = lt(t, ["mclose"]); else { const r = e.rightColor ? t.withColor(e.rightColor) : t; o = yr.leftRightDelim(e.right, s, i, r, e.mode, ["mclose"]) } return r.push(o), Ve.makeSpan(["minner"], r, t) }, mathmlBuilder: (e, t) => { kr(e); const r = xt(e.body, t); if ("." !== e.left) { const t = new gt.MathNode("mo", [ft(e.left, e.mode)]); t.setAttribute("fence", "true"), r.unshift(t) } if ("." !== e.right) { const t = new gt.MathNode("mo", [ft(e.right, e.mode)]); t.setAttribute("fence", "true"), e.rightColor && t.setAttribute("mathcolor", e.rightColor), r.push(t) } return bt(r) } }), je({ type: "middle", names: ["\\middle"], props: { numArgs: 1, primitive: !0 }, handler: (e, t) => { const r = vr(t[0], e); if (!e.parser.leftrightDepth) throw new n("\\middle without preceding \\left", r); return { type: "middle", mode: e.parser.mode, delim: r.text } }, htmlBuilder: (e, t) => { let r; if ("." === e.delim) r = lt(t, []); else { r = yr.sizedDelim(e.delim, 1, t, e.mode, []); const n = { delim: e.delim, options: t }; r.isMiddle = n } return r }, mathmlBuilder: (e, t) => { const r = "\\vert" === e.delim || "|" === e.delim ? ft("|", "text") : ft(e.delim, e.mode), n = new gt.MathNode("mo", [r]); return n.setAttribute("fence", "true"), n.setAttribute("lspace", "0.05em"), n.setAttribute("rspace", "0.05em"), n } }); const Sr = (e, t) => { const r = Ve.wrapFragment(ht(e.body, t), t), n = e.label.slice(1); let o, s = t.sizeMultiplier, i = 0; const a = l.isCharacterBox(e.body); if ("sout" === n) o = Ve.makeSpan(["stretchy", "sout"]), o.height = t.fontMetrics().defaultRuleThickness / s, i = -.5 * t.fontMetrics().xHeight; else if ("phase" === n) { const e = P({ number: .6, unit: "pt" }, t), n = P({ number: .35, unit: "ex" }, t); s /= t.havingBaseSizing().sizeMultiplier; const a = r.height + r.depth + e + n; r.style.paddingLeft = F(a / 2 + e); const l = Math.floor(1e3 * a * s), c = "M400000 " + (h = l) + " H0 L" + h / 2 + " 0 l65 45 L145 " + (h - 80) + " H400000z", m = new K([new J("phase", c)], { width: "400em", height: F(l / 1e3), viewBox: "0 0 400000 " + l, preserveAspectRatio: "xMinYMin slice" }); o = Ve.makeSvgSpan(["hide-tail"], [m], t), o.style.height = F(a), i = r.depth + e + n } else { /cancel/.test(n) ? a || r.classes.push("cancel-pad") : "angl" === n ? r.classes.push("anglpad") : r.classes.push("boxpad"); let s = 0, l = 0, h = 0; /box/.test(n) ? (h = Math.max(t.fontMetrics().fboxrule, t.minRuleThickness), s = t.fontMetrics().fboxsep + ("colorbox" === n ? 0 : h), l = s) : "angl" === n ? (h = Math.max(t.fontMetrics().defaultRuleThickness, t.minRuleThickness), s = 4 * h, l = Math.max(0, .25 - r.depth)) : (s = a ? .2 : 0, l = s), o = Bt(r, n, s, l, t), /fbox|boxed|fcolorbox/.test(n) ? (o.style.borderStyle = "solid", o.style.borderWidth = F(h)) : "angl" === n && .049 !== h && (o.style.borderTopWidth = F(h), o.style.borderRightWidth = F(h)), i = r.depth + l, e.backgroundColor && (o.style.backgroundColor = e.backgroundColor, e.borderColor && (o.style.borderColor = e.borderColor)) } var h; let c; if (e.backgroundColor) c = Ve.makeVList({ positionType: "individualShift", children: [{ type: "elem", elem: o, shift: i }, { type: "elem", elem: r, shift: 0 }] }, t); else { const e = /cancel|phase/.test(n) ? ["svg-align"] : []; c = Ve.makeVList({ positionType: "individualShift", children: [{ type: "elem", elem: r, shift: 0 }, { type: "elem", elem: o, shift: i, wrapperClasses: e }] }, t) } return /cancel/.test(n) && (c.height = r.height, c.depth = r.depth), /cancel/.test(n) && !a ? Ve.makeSpan(["mord", "cancel-lap"], [c], t) : Ve.makeSpan(["mord"], [c], t) }, Mr = (e, t) => { let r = 0; const n = new gt.MathNode(e.label.indexOf("colorbox") > -1 ? "mpadded" : "menclose", [vt(e.body, t)]); switch (e.label) { case "\\cancel": n.setAttribute("notation", "updiagonalstrike"); break; case "\\bcancel": n.setAttribute("notation", "downdiagonalstrike"); break; case "\\phase": n.setAttribute("notation", "phasorangle"); break; case "\\sout": n.setAttribute("notation", "horizontalstrike"); break; case "\\fbox": n.setAttribute("notation", "box"); break; case "\\angl": n.setAttribute("notation", "actuarial"); break; case "\\fcolorbox": case "\\colorbox": if (r = t.fontMetrics().fboxsep * t.fontMetrics().ptPerEm, n.setAttribute("width", "+" + 2 * r + "pt"), n.setAttribute("height", "+" + 2 * r + "pt"), n.setAttribute("lspace", r + "pt"), n.setAttribute("voffset", r + "pt"), "\\fcolorbox" === e.label) { const r = Math.max(t.fontMetrics().fboxrule, t.minRuleThickness); n.setAttribute("style", "border: " + r + "em solid " + String(e.borderColor)) } break; case "\\xcancel": n.setAttribute("notation", "updiagonalstrike downdiagonalstrike") }return e.backgroundColor && n.setAttribute("mathbackground", e.backgroundColor), n }; je({ type: "enclose", names: ["\\colorbox"], props: { numArgs: 2, allowedInText: !0, argTypes: ["color", "text"] }, handler(e, t, r) { let { parser: n, funcName: o } = e; const s = qt(t[0], "color-token").color, i = t[1]; return { type: "enclose", mode: n.mode, label: o, backgroundColor: s, body: i } }, htmlBuilder: Sr, mathmlBuilder: Mr }), je({ type: "enclose", names: ["\\fcolorbox"], props: { numArgs: 3, allowedInText: !0, argTypes: ["color", "color", "text"] }, handler(e, t, r) { let { parser: n, funcName: o } = e; const s = qt(t[0], "color-token").color, i = qt(t[1], "color-token").color, a = t[2]; return { type: "enclose", mode: n.mode, label: o, backgroundColor: i, borderColor: s, body: a } }, htmlBuilder: Sr, mathmlBuilder: Mr }), je({ type: "enclose", names: ["\\fbox"], props: { numArgs: 1, argTypes: ["hbox"], allowedInText: !0 }, handler(e, t) { let { parser: r } = e; return { type: "enclose", mode: r.mode, label: "\\fbox", body: t[0] } } }), je({ type: "enclose", names: ["\\cancel", "\\bcancel", "\\xcancel", "\\sout", "\\phase"], props: { numArgs: 1 }, handler(e, t) { let { parser: r, funcName: n } = e; const o = t[0]; return { type: "enclose", mode: r.mode, label: n, body: o } }, htmlBuilder: Sr, mathmlBuilder: Mr }), je({ type: "enclose", names: ["\\angl"], props: { numArgs: 1, argTypes: ["hbox"], allowedInText: !1 }, handler(e, t) { let { parser: r } = e; return { type: "enclose", mode: r.mode, label: "\\angl", body: t[0] } } }); const zr = {}; function Ar(e) { let { type: t, names: r, props: n, handler: o, htmlBuilder: s, mathmlBuilder: i } = e; const a = { type: t, numArgs: n.numArgs || 0, allowedInText: !1, numOptionalArgs: 0, handler: o }; for (let e = 0; e < r.length; ++e)zr[r[e]] = a; s && (We[t] = s), i && (_e[t] = i) } const Tr = {}; function Br(e, t) { Tr[e] = t } class Cr { constructor(e, t, r) { this.lexer = void 0, this.start = void 0, this.end = void 0, this.lexer = e, this.start = t, this.end = r } static range(e, t) { return t ? e && e.loc && t.loc && e.loc.lexer === t.loc.lexer ? new Cr(e.loc.lexer, e.loc.start, t.loc.end) : null : e && e.loc } } class Nr { constructor(e, t) { this.text = void 0, this.loc = void 0, this.noexpand = void 0, this.treatAsRelax = void 0, this.text = e, this.loc = t } range(e, t) { return new Nr(t, Cr.range(this, e)) } } function qr(e) { const t = []; e.consumeSpaces(); let r = e.fetch().text; for ("\\relax" === r && (e.consume(), e.consumeSpaces(), r = e.fetch().text); "\\hline" === r || "\\hdashline" === r;)e.consume(), t.push("\\hdashline" === r), e.consumeSpaces(), r = e.fetch().text; return t } const Ir = e => { if (!e.parser.settings.displayMode) throw new n("{" + e.envName + "} can be used only in display mode.") }; function Rr(e) { if (-1 === e.indexOf("ed")) return -1 === e.indexOf("*") } function Hr(e, t, r) { let { hskipBeforeAndAfter: o, addJot: s, cols: i, arraystretch: a, colSeparationType: l, autoTag: h, singleRow: c, emptySingleRow: m, maxNumCols: p, leqno: u } = t; if (e.gullet.beginGroup(), c || e.gullet.macros.set("\\cr", "\\\\\\relax"), !a) { const t = e.gullet.expandMacroAsText("\\arraystretch"); if (null == t) a = 1; else if (a = parseFloat(t), !a || a < 0) throw new n("Invalid \\arraystretch: " + t) } e.gullet.beginGroup(); let d = []; const g = [d], f = [], b = [], y = null != h ? [] : void 0; function x() { h && e.gullet.macros.set("\\@eqnsw", "1", !0) } function w() { y && (e.gullet.macros.get("\\df@tag") ? (y.push(e.subparse([new Nr("\\df@tag")])), e.gullet.macros.set("\\df@tag", void 0, !0)) : y.push(Boolean(h) && "1" === e.gullet.macros.get("\\@eqnsw"))) } for (x(), b.push(qr(e)); ;) { let t = e.parseExpression(!1, c ? "\\end" : "\\\\"); e.gullet.endGroup(), e.gullet.beginGroup(), t = { type: "ordgroup", mode: e.mode, body: t }, r && (t = { type: "styling", mode: e.mode, style: r, body: [t] }), d.push(t); const o = e.fetch().text; if ("&" === o) { if (p && d.length === p) { if (c || l) throw new n("Too many tab characters: &", e.nextToken); e.settings.reportNonstrict("textEnv", "Too few columns specified in the {array} column argument.") } e.consume() } else { if ("\\end" === o) { w(), 1 === d.length && "styling" === t.type && 0 === t.body[0].body.length && (g.length > 1 || !m) && g.pop(), b.length < g.length + 1 && b.push([]); break } if ("\\\\" !== o) throw new n("Expected & or \\\\ or \\cr or \\end", e.nextToken); { let t; e.consume(), " " !== e.gullet.future().text && (t = e.parseSizeGroup(!0)), f.push(t ? t.value : null), w(), b.push(qr(e)), d = [], g.push(d), x() } } } return e.gullet.endGroup(), e.gullet.endGroup(), { type: "array", mode: e.mode, addJot: s, arraystretch: a, body: g, cols: i, rowGaps: f, hskipBeforeAndAfter: o, hLinesBeforeRow: b, colSeparationType: l, tags: y, leqno: u } } function Or(e) { return "d" === e.slice(0, 1) ? "display" : "text" } const Er = function (e, t) { let r, o; const s = e.body.length, i = e.hLinesBeforeRow; let a = 0, h = new Array(s); const c = [], m = Math.max(t.fontMetrics().arrayRuleWidth, t.minRuleThickness), p = 1 / t.fontMetrics().ptPerEm; let u = 5 * p; if (e.colSeparationType && "small" === e.colSeparationType) { u = t.havingStyle(w.SCRIPT).sizeMultiplier / t.sizeMultiplier * .2778 } const d = "CD" === e.colSeparationType ? P({ number: 3, unit: "ex" }, t) : 12 * p, g = 3 * p, f = e.arraystretch * d, b = .7 * f, y = .3 * f; let x = 0; function v(e) { for (let t = 0; t < e.length; ++t)t > 0 && (x += .25), c.push({ pos: x, isDashed: e[t] }) } for (v(i[0]), r = 0; r < e.body.length; ++r) { const n = e.body[r]; let s = b, l = y; a < n.length && (a = n.length); const c = new Array(n.length); for (o = 0; o < n.length; ++o) { const e = ht(n[o], t); l < e.depth && (l = e.depth), s < e.height && (s = e.height), c[o] = e } const m = e.rowGaps[r]; let p = 0; m && (p = P(m, t), p > 0 && (p += y, l < p && (l = p), p = 0)), e.addJot && (l += g), c.height = s, c.depth = l, x += s, c.pos = x, x += l + p, h[r] = c, v(i[r + 1]) } const k = x / 2 + t.fontMetrics().axisHeight, S = e.cols || [], M = []; let z, A; const T = []; if (e.tags && e.tags.some((e => e))) for (r = 0; r < s; ++r) { const n = h[r], o = n.pos - k, s = e.tags[r]; let i; i = !0 === s ? Ve.makeSpan(["eqn-num"], [], t) : !1 === s ? Ve.makeSpan([], [], t) : Ve.makeSpan([], nt(s, t, !0), t), i.depth = n.depth, i.height = n.height, T.push({ type: "elem", elem: i, shift: o }) } for (o = 0, A = 0; o < a || A < S.length; ++o, ++A) { let i, c = S[A] || {}, p = !0; for (; "separator" === c.type;) { if (p || (z = Ve.makeSpan(["arraycolsep"], []), z.style.width = F(t.fontMetrics().doubleRuleSep), M.push(z)), "|" !== c.separator && ":" !== c.separator) throw new n("Invalid separator type: " + c.separator); { const e = "|" === c.separator ? "solid" : "dashed", r = Ve.makeSpan(["vertical-separator"], [], t); r.style.height = F(x), r.style.borderRightWidth = F(m), r.style.borderRightStyle = e, r.style.margin = "0 " + F(-m / 2); const n = x - k; n && (r.style.verticalAlign = F(-n)), M.push(r) } A++, c = S[A] || {}, p = !1 } if (o >= a) continue; (o > 0 || e.hskipBeforeAndAfter) && (i = l.deflt(c.pregap, u), 0 !== i && (z = Ve.makeSpan(["arraycolsep"], []), z.style.width = F(i), M.push(z))); let d = []; for (r = 0; r < s; ++r) { const e = h[r], t = e[o]; if (!t) continue; const n = e.pos - k; t.depth = e.depth, t.height = e.height, d.push({ type: "elem", elem: t, shift: n }) } d = Ve.makeVList({ positionType: "individualShift", children: d }, t), d = Ve.makeSpan(["col-align-" + (c.align || "c")], [d]), M.push(d), (o < a - 1 || e.hskipBeforeAndAfter) && (i = l.deflt(c.postgap, u), 0 !== i && (z = Ve.makeSpan(["arraycolsep"], []), z.style.width = F(i), M.push(z))) } if (h = Ve.makeSpan(["mtable"], M), c.length > 0) { const e = Ve.makeLineSpan("hline", t, m), r = Ve.makeLineSpan("hdashline", t, m), n = [{ type: "elem", elem: h, shift: 0 }]; for (; c.length > 0;) { const t = c.pop(), o = t.pos - k; t.isDashed ? n.push({ type: "elem", elem: r, shift: o }) : n.push({ type: "elem", elem: e, shift: o }) } h = Ve.makeVList({ positionType: "individualShift", children: n }, t) } if (0 === T.length) return Ve.makeSpan(["mord"], [h], t); { let e = Ve.makeVList({ positionType: "individualShift", children: T }, t); return e = Ve.makeSpan(["tag"], [e], t), Ve.makeFragment([h, e]) } }, Lr = { c: "center ", l: "left ", r: "right " }, Dr = function (e, t) { const r = [], n = new gt.MathNode("mtd", [], ["mtr-glue"]), o = new gt.MathNode("mtd", [], ["mml-eqn-num"]); for (let s = 0; s < e.body.length; s++) { const i = e.body[s], a = []; for (let e = 0; e < i.length; e++)a.push(new gt.MathNode("mtd", [vt(i[e], t)])); e.tags && e.tags[s] && (a.unshift(n), a.push(n), e.leqno ? a.unshift(o) : a.push(o)), r.push(new gt.MathNode("mtr", a)) } let s = new gt.MathNode("mtable", r); const i = .5 === e.arraystretch ? .1 : .16 + e.arraystretch - 1 + (e.addJot ? .09 : 0); s.setAttribute("rowspacing", F(i)); let a = "", l = ""; if (e.cols && e.cols.length > 0) { const t = e.cols; let r = "", n = !1, o = 0, i = t.length; "separator" === t[0].type && (a += "top ", o = 1), "separator" === t[t.length - 1].type && (a += "bottom ", i -= 1); for (let e = o; e < i; e++)"align" === t[e].type ? (l += Lr[t[e].align], n && (r += "none "), n = !0) : "separator" === t[e].type && n && (r += "|" === t[e].separator ? "solid " : "dashed ", n = !1); s.setAttribute("columnalign", l.trim()), /[sd]/.test(r) && s.setAttribute("columnlines", r.trim()) } if ("align" === e.colSeparationType) { const t = e.cols || []; let r = ""; for (let e = 1; e < t.length; e++)r += e % 2 ? "0em " : "1em "; s.setAttribute("columnspacing", r.trim()) } else "alignat" === e.colSeparationType || "gather" === e.colSeparationType ? s.setAttribute("columnspacing", "0em") : "small" === e.colSeparationType ? s.setAttribute("columnspacing", "0.2778em") : "CD" === e.colSeparationType ? s.setAttribute("columnspacing", "0.5em") : s.setAttribute("columnspacing", "1em"); let h = ""; const c = e.hLinesBeforeRow; a += c[0].length > 0 ? "left " : "", a += c[c.length - 1].length > 0 ? "right " : ""; for (let e = 1; e < c.length - 1; e++)h += 0 === c[e].length ? "none " : c[e][0] ? "dashed " : "solid "; return /[sd]/.test(h) && s.setAttribute("rowlines", h.trim()), "" !== a && (s = new gt.MathNode("menclose", [s]), s.setAttribute("notation", a.trim())), e.arraystretch && e.arraystretch < 1 && (s = new gt.MathNode("mstyle", [s]), s.setAttribute("scriptlevel", "1")), s }, Vr = function (e, t) { -1 === e.envName.indexOf("ed") && Ir(e); const r = [], o = e.envName.indexOf("at") > -1 ? "alignat" : "align", s = "split" === e.envName, i = Hr(e.parser, { cols: r, addJot: !0, autoTag: s ? void 0 : Rr(e.envName), emptySingleRow: !0, colSeparationType: o, maxNumCols: s ? 2 : void 0, leqno: e.parser.settings.leqno }, "display"); let a, l = 0; const h = { type: "ordgroup", mode: e.mode, body: [] }; if (t[0] && "ordgroup" === t[0].type) { let e = ""; for (let r = 0; r < t[0].body.length; r++) { e += qt(t[0].body[r], "textord").text } a = Number(e), l = 2 * a } const c = !l; i.body.forEach((function (e) { for (let t = 1; t < e.length; t += 2) { const r = qt(e[t], "styling"); qt(r.body[0], "ordgroup").body.unshift(h) } if (c) l < e.length && (l = e.length); else { const t = e.length / 2; if (a < t) throw new n("Too many math in a row: expected " + a + ", but got " + t, e[0]) } })); for (let e = 0; e < l; ++e) { let t = "r", n = 0; e % 2 == 1 ? t = "l" : e > 0 && c && (n = 1), r[e] = { type: "align", align: t, pregap: n, postgap: 0 } } return i.colSeparationType = c ? "align" : "alignat", i }; Ar({ type: "array", names: ["array", "darray"], props: { numArgs: 1 }, handler(e, t) { const r = (Rt(t[0]) ? [t[0]] : qt(t[0], "ordgroup").body).map((function (e) { const t = It(e).text; if (-1 !== "lcr".indexOf(t)) return { type: "align", align: t }; if ("|" === t) return { type: "separator", separator: "|" }; if (":" === t) return { type: "separator", separator: ":" }; throw new n("Unknown column alignment: " + t, e) })), o = { cols: r, hskipBeforeAndAfter: !0, maxNumCols: r.length }; return Hr(e.parser, o, Or(e.envName)) }, htmlBuilder: Er, mathmlBuilder: Dr }), Ar({ type: "array", names: ["matrix", "pmatrix", "bmatrix", "Bmatrix", "vmatrix", "Vmatrix", "matrix*", "pmatrix*", "bmatrix*", "Bmatrix*", "vmatrix*", "Vmatrix*"], props: { numArgs: 0 }, handler(e) { const t = { matrix: null, pmatrix: ["(", ")"], bmatrix: ["[", "]"], Bmatrix: ["\\{", "\\}"], vmatrix: ["|", "|"], Vmatrix: ["\\Vert", "\\Vert"] }[e.envName.replace("*", "")]; let r = "c"; const o = { hskipBeforeAndAfter: !1, cols: [{ type: "align", align: r }] }; if ("*" === e.envName.charAt(e.envName.length - 1)) { const t = e.parser; if (t.consumeSpaces(), "[" === t.fetch().text) { if (t.consume(), t.consumeSpaces(), r = t.fetch().text, -1 === "lcr".indexOf(r)) throw new n("Expected l or c or r", t.nextToken); t.consume(), t.consumeSpaces(), t.expect("]"), t.consume(), o.cols = [{ type: "align", align: r }] } } const s = Hr(e.parser, o, Or(e.envName)), i = Math.max(0, ...s.body.map((e => e.length))); return s.cols = new Array(i).fill({ type: "align", align: r }), t ? { type: "leftright", mode: e.mode, body: [s], left: t[0], right: t[1], rightColor: void 0 } : s }, htmlBuilder: Er, mathmlBuilder: Dr }), Ar({ type: "array", names: ["smallmatrix"], props: { numArgs: 0 }, handler(e) { const t = Hr(e.parser, { arraystretch: .5 }, "script"); return t.colSeparationType = "small", t }, htmlBuilder: Er, mathmlBuilder: Dr }), Ar({ type: "array", names: ["subarray"], props: { numArgs: 1 }, handler(e, t) { const r = (Rt(t[0]) ? [t[0]] : qt(t[0], "ordgroup").body).map((function (e) { const t = It(e).text; if (-1 !== "lc".indexOf(t)) return { type: "align", align: t }; throw new n("Unknown column alignment: " + t, e) })); if (r.length > 1) throw new n("{subarray} can contain only one column"); let o = { cols: r, hskipBeforeAndAfter: !1, arraystretch: .5 }; if (o = Hr(e.parser, o, "script"), o.body.length > 0 && o.body[0].length > 1) throw new n("{subarray} can contain only one column"); return o }, htmlBuilder: Er, mathmlBuilder: Dr }), Ar({ type: "array", names: ["cases", "dcases", "rcases", "drcases"], props: { numArgs: 0 }, handler(e) { const t = Hr(e.parser, { arraystretch: 1.2, cols: [{ type: "align", align: "l", pregap: 0, postgap: 1 }, { type: "align", align: "l", pregap: 0, postgap: 0 }] }, Or(e.envName)); return { type: "leftright", mode: e.mode, body: [t], left: e.envName.indexOf("r") > -1 ? "." : "\\{", right: e.envName.indexOf("r") > -1 ? "\\}" : ".", rightColor: void 0 } }, htmlBuilder: Er, mathmlBuilder: Dr }), Ar({ type: "array", names: ["align", "align*", "aligned", "split"], props: { numArgs: 0 }, handler: Vr, htmlBuilder: Er, mathmlBuilder: Dr }), Ar({ type: "array", names: ["gathered", "gather", "gather*"], props: { numArgs: 0 }, handler(e) { l.contains(["gather", "gather*"], e.envName) && Ir(e); const t = { cols: [{ type: "align", align: "c" }], addJot: !0, colSeparationType: "gather", autoTag: Rr(e.envName), emptySingleRow: !0, leqno: e.parser.settings.leqno }; return Hr(e.parser, t, "display") }, htmlBuilder: Er, mathmlBuilder: Dr }), Ar({ type: "array", names: ["alignat", "alignat*", "alignedat"], props: { numArgs: 1 }, handler: Vr, htmlBuilder: Er, mathmlBuilder: Dr }), Ar({ type: "array", names: ["equation", "equation*"], props: { numArgs: 0 }, handler(e) { Ir(e); const t = { autoTag: Rr(e.envName), emptySingleRow: !0, singleRow: !0, maxNumCols: 1, leqno: e.parser.settings.leqno }; return Hr(e.parser, t, "display") }, htmlBuilder: Er, mathmlBuilder: Dr }), Ar({ type: "array", names: ["CD"], props: { numArgs: 0 }, handler(e) { return Ir(e), function (e) { const t = []; for (e.gullet.beginGroup(), e.gullet.macros.set("\\cr", "\\\\\\relax"), e.gullet.beginGroup(); ;) { t.push(e.parseExpression(!1, "\\\\")), e.gullet.endGroup(), e.gullet.beginGroup(); const r = e.fetch().text; if ("&" !== r && "\\\\" !== r) { if ("\\end" === r) { 0 === t[t.length - 1].length && t.pop(); break } throw new n("Expected \\\\ or \\cr or \\end", e.nextToken) } e.consume() } let r = []; const o = [r]; for (let a = 0; a < t.length; a++) { const l = t[a]; let h = { type: "styling", body: [], mode: "math", style: "display" }; for (let t = 0; t < l.length; t++)if (Ut(l[t])) { r.push(h), t += 1; const o = It(l[t]).text, a = new Array(2); if (a[0] = { type: "ordgroup", mode: "math", body: [] }, a[1] = { type: "ordgroup", mode: "math", body: [] }, "=|.".indexOf(o) > -1); else { if (!("<>AV".indexOf(o) > -1)) throw new n('Expected one of "<>AV=|." after @', l[t]); for (let e = 0; e < 2; e++) { let r = !0; for (let h = t + 1; h < l.length; h++) { if (i = o, ("mathord" === (s = l[h]).type || "atom" === s.type) && s.text === i) { r = !1, t = h; break } if (Ut(l[h])) throw new n("Missing a " + o + " character to complete a CD arrow.", l[h]); a[e].body.push(l[h]) } if (r) throw new n("Missing a " + o + " character to complete a CD arrow.", l[t]) } } const c = { type: "styling", body: [Yt(o, a, e)], mode: "math", style: "display" }; r.push(c), h = { type: "styling", body: [], mode: "math", style: "display" } } else h.body.push(l[t]); a % 2 == 0 ? r.push(h) : r.shift(), r = [], o.push(r) } var s, i; return e.gullet.endGroup(), e.gullet.endGroup(), { type: "array", mode: "math", body: o, arraystretch: 1, addJot: !0, rowGaps: [null], cols: new Array(o[0].length).fill({ type: "align", align: "c", pregap: .25, postgap: .25 }), colSeparationType: "CD", hLinesBeforeRow: new Array(o.length + 1).fill([]) } }(e.parser) }, htmlBuilder: Er, mathmlBuilder: Dr }), Br("\\nonumber", "\\gdef\\@eqnsw{0}"), Br("\\notag", "\\nonumber"), je({ type: "text", names: ["\\hline", "\\hdashline"], props: { numArgs: 0, allowedInText: !0, allowedInMath: !0 }, handler(e, t) { throw new n(e.funcName + " valid only within array environment") } }); var Pr = zr; je({ type: "environment", names: ["\\begin", "\\end"], props: { numArgs: 1, argTypes: ["text"] }, handler(e, t) { let { parser: r, funcName: o } = e; const s = t[0]; if ("ordgroup" !== s.type) throw new n("Invalid environment name", s); let i = ""; for (let e = 0; e < s.body.length; ++e)i += qt(s.body[e], "textord").text; if ("\\begin" === o) { if (!Pr.hasOwnProperty(i)) throw new n("No such environment: " + i, s); const e = Pr[i], { args: t, optArgs: o } = r.parseArguments("\\begin{" + i + "}", e), a = { mode: r.mode, envName: i, parser: r }, l = e.handler(a, t, o); r.expect("\\end", !1); const h = r.nextToken, c = qt(r.parseFunction(), "environment"); if (c.name !== i) throw new n("Mismatch: \\begin{" + i + "} matched by \\end{" + c.name + "}", h); return l } return { type: "environment", mode: r.mode, name: i, nameGroup: s } } }); const Fr = (e, t) => { const r = e.font, n = t.withFont(r); return ht(e.body, n) }, Gr = (e, t) => { const r = e.font, n = t.withFont(r); return vt(e.body, n) }, Ur = { "\\Bbb": "\\mathbb", "\\bold": "\\mathbf", "\\frak": "\\mathfrak", "\\bm": "\\boldsymbol" }; je({ type: "font", names: ["\\mathrm", "\\mathit", "\\mathbf", "\\mathnormal", "\\mathbb", "\\mathcal", "\\mathfrak", "\\mathscr", "\\mathsf", "\\mathtt", "\\Bbb", "\\bold", "\\frak"], props: { numArgs: 1, allowedInArgument: !0 }, handler: (e, t) => { let { parser: r, funcName: n } = e; const o = Ze(t[0]); let s = n; return s in Ur && (s = Ur[s]), { type: "font", mode: r.mode, font: s.slice(1), body: o } }, htmlBuilder: Fr, mathmlBuilder: Gr }), je({ type: "mclass", names: ["\\boldsymbol", "\\bm"], props: { numArgs: 1 }, handler: (e, t) => { let { parser: r } = e; const n = t[0], o = l.isCharacterBox(n); return { type: "mclass", mode: r.mode, mclass: Ft(n), body: [{ type: "font", mode: r.mode, font: "boldsymbol", body: n }], isCharacterBox: o } } }), je({ type: "font", names: ["\\rm", "\\sf", "\\tt", "\\bf", "\\it", "\\cal"], props: { numArgs: 0, allowedInText: !0 }, handler: (e, t) => { let { parser: r, funcName: n, breakOnTokenText: o } = e; const { mode: s } = r, i = r.parseExpression(!0, o); return { type: "font", mode: s, font: "math" + n.slice(1), body: { type: "ordgroup", mode: r.mode, body: i } } }, htmlBuilder: Fr, mathmlBuilder: Gr }); const Yr = (e, t) => { let r = t; return "display" === e ? r = r.id >= w.SCRIPT.id ? r.text() : w.DISPLAY : "text" === e && r.size === w.DISPLAY.size ? r = w.TEXT : "script" === e ? r = w.SCRIPT : "scriptscript" === e && (r = w.SCRIPTSCRIPT), r }, Xr = (e, t) => { const r = Yr(e.size, t.style), n = r.fracNum(), o = r.fracDen(); let s; s = t.havingStyle(n); const i = ht(e.numer, s, t); if (e.continued) { const e = 8.5 / t.fontMetrics().ptPerEm, r = 3.5 / t.fontMetrics().ptPerEm; i.height = i.height < e ? e : i.height, i.depth = i.depth < r ? r : i.depth } s = t.havingStyle(o); const a = ht(e.denom, s, t); let l, h, c, m, p, u, d, g, f, b; if (e.hasBarLine ? (e.barSize ? (h = P(e.barSize, t), l = Ve.makeLineSpan("frac-line", t, h)) : l = Ve.makeLineSpan("frac-line", t), h = l.height, c = l.height) : (l = null, h = 0, c = t.fontMetrics().defaultRuleThickness), r.size === w.DISPLAY.size || "display" === e.size ? (m = t.fontMetrics().num1, p = h > 0 ? 3 * c : 7 * c, u = t.fontMetrics().denom1) : (h > 0 ? (m = t.fontMetrics().num2, p = c) : (m = t.fontMetrics().num3, p = 3 * c), u = t.fontMetrics().denom2), l) { const e = t.fontMetrics().axisHeight; m - i.depth - (e + .5 * h) < p && (m += p - (m - i.depth - (e + .5 * h))), e - .5 * h - (a.height - u) < p && (u += p - (e - .5 * h - (a.height - u))); const r = -(e - .5 * h); d = Ve.makeVList({ positionType: "individualShift", children: [{ type: "elem", elem: a, shift: u }, { type: "elem", elem: l, shift: r }, { type: "elem", elem: i, shift: -m }] }, t) } else { const e = m - i.depth - (a.height - u); e < p && (m += .5 * (p - e), u += .5 * (p - e)), d = Ve.makeVList({ positionType: "individualShift", children: [{ type: "elem", elem: a, shift: u }, { type: "elem", elem: i, shift: -m }] }, t) } return s = t.havingStyle(r), d.height *= s.sizeMultiplier / t.sizeMultiplier, d.depth *= s.sizeMultiplier / t.sizeMultiplier, g = r.size === w.DISPLAY.size ? t.fontMetrics().delim1 : r.size === w.SCRIPTSCRIPT.size ? t.havingStyle(w.SCRIPT).fontMetrics().delim2 : t.fontMetrics().delim2, f = null == e.leftDelim ? lt(t, ["mopen"]) : yr.customSizedDelim(e.leftDelim, g, !0, t.havingStyle(r), e.mode, ["mopen"]), b = e.continued ? Ve.makeSpan([]) : null == e.rightDelim ? lt(t, ["mclose"]) : yr.customSizedDelim(e.rightDelim, g, !0, t.havingStyle(r), e.mode, ["mclose"]), Ve.makeSpan(["mord"].concat(s.sizingClasses(t)), [f, Ve.makeSpan(["mfrac"], [d]), b], t) }, Wr = (e, t) => { let r = new gt.MathNode("mfrac", [vt(e.numer, t), vt(e.denom, t)]); if (e.hasBarLine) { if (e.barSize) { const n = P(e.barSize, t); r.setAttribute("linethickness", F(n)) } } else r.setAttribute("linethickness", "0px"); const n = Yr(e.size, t.style); if (n.size !== t.style.size) { r = new gt.MathNode("mstyle", [r]); const e = n.size === w.DISPLAY.size ? "true" : "false"; r.setAttribute("displaystyle", e), r.setAttribute("scriptlevel", "0") } if (null != e.leftDelim || null != e.rightDelim) { const t = []; if (null != e.leftDelim) { const r = new gt.MathNode("mo", [new gt.TextNode(e.leftDelim.replace("\\", ""))]); r.setAttribute("fence", "true"), t.push(r) } if (t.push(r), null != e.rightDelim) { const r = new gt.MathNode("mo", [new gt.TextNode(e.rightDelim.replace("\\", ""))]); r.setAttribute("fence", "true"), t.push(r) } return bt(t) } return r }; je({ type: "genfrac", names: ["\\dfrac", "\\frac", "\\tfrac", "\\dbinom", "\\binom", "\\tbinom", "\\\\atopfrac", "\\\\bracefrac", "\\\\brackfrac"], props: { numArgs: 2, allowedInArgument: !0 }, handler: (e, t) => { let { parser: r, funcName: n } = e; const o = t[0], s = t[1]; let i, a = null, l = null, h = "auto"; switch (n) { case "\\dfrac": case "\\frac": case "\\tfrac": i = !0; break; case "\\\\atopfrac": i = !1; break; case "\\dbinom": case "\\binom": case "\\tbinom": i = !1, a = "(", l = ")"; break; case "\\\\bracefrac": i = !1, a = "\\{", l = "\\}"; break; case "\\\\brackfrac": i = !1, a = "[", l = "]"; break; default: throw new Error("Unrecognized genfrac command") }switch (n) { case "\\dfrac": case "\\dbinom": h = "display"; break; case "\\tfrac": case "\\tbinom": h = "text" }return { type: "genfrac", mode: r.mode, continued: !1, numer: o, denom: s, hasBarLine: i, leftDelim: a, rightDelim: l, size: h, barSize: null } }, htmlBuilder: Xr, mathmlBuilder: Wr }), je({ type: "genfrac", names: ["\\cfrac"], props: { numArgs: 2 }, handler: (e, t) => { let { parser: r, funcName: n } = e; const o = t[0], s = t[1]; return { type: "genfrac", mode: r.mode, continued: !0, numer: o, denom: s, hasBarLine: !0, leftDelim: null, rightDelim: null, size: "display", barSize: null } } }), je({ type: "infix", names: ["\\over", "\\choose", "\\atop", "\\brace", "\\brack"], props: { numArgs: 0, infix: !0 }, handler(e) { let t, { parser: r, funcName: n, token: o } = e; switch (n) { case "\\over": t = "\\frac"; break; case "\\choose": t = "\\binom"; break; case "\\atop": t = "\\\\atopfrac"; break; case "\\brace": t = "\\\\bracefrac"; break; case "\\brack": t = "\\\\brackfrac"; break; default: throw new Error("Unrecognized infix genfrac command") }return { type: "infix", mode: r.mode, replaceWith: t, token: o } } }); const _r = ["display", "text", "script", "scriptscript"], jr = function (e) { let t = null; return e.length > 0 && (t = e, t = "." === t ? null : t), t }; je({ type: "genfrac", names: ["\\genfrac"], props: { numArgs: 6, allowedInArgument: !0, argTypes: ["math", "math", "size", "text", "math", "math"] }, handler(e, t) { let { parser: r } = e; const n = t[4], o = t[5], s = Ze(t[0]), i = "atom" === s.type && "open" === s.family ? jr(s.text) : null, a = Ze(t[1]), l = "atom" === a.type && "close" === a.family ? jr(a.text) : null, h = qt(t[2], "size"); let c, m = null; h.isBlank ? c = !0 : (m = h.value, c = m.number > 0); let p = "auto", u = t[3]; if ("ordgroup" === u.type) { if (u.body.length > 0) { const e = qt(u.body[0], "textord"); p = _r[Number(e.text)] } } else u = qt(u, "textord"), p = _r[Number(u.text)]; return { type: "genfrac", mode: r.mode, numer: n, denom: o, continued: !1, hasBarLine: c, barSize: m, leftDelim: i, rightDelim: l, size: p } }, htmlBuilder: Xr, mathmlBuilder: Wr }), je({ type: "infix", names: ["\\above"], props: { numArgs: 1, argTypes: ["size"], infix: !0 }, handler(e, t) { let { parser: r, funcName: n, token: o } = e; return { type: "infix", mode: r.mode, replaceWith: "\\\\abovefrac", size: qt(t[0], "size").value, token: o } } }), je({ type: "genfrac", names: ["\\\\abovefrac"], props: { numArgs: 3, argTypes: ["math", "size", "math"] }, handler: (e, t) => { let { parser: r, funcName: n } = e; const o = t[0], s = function (e) { if (!e) throw new Error("Expected non-null, but got " + String(e)); return e }(qt(t[1], "infix").size), i = t[2], a = s.number > 0; return { type: "genfrac", mode: r.mode, numer: o, denom: i, continued: !1, hasBarLine: a, barSize: s, leftDelim: null, rightDelim: null, size: "auto" } }, htmlBuilder: Xr, mathmlBuilder: Wr }); const $r = (e, t) => { const r = t.style; let n, o; "supsub" === e.type ? (n = e.sup ? ht(e.sup, t.havingStyle(r.sup()), t) : ht(e.sub, t.havingStyle(r.sub()), t), o = qt(e.base, "horizBrace")) : o = qt(e, "horizBrace"); const s = ht(o.base, t.havingBaseStyle(w.DISPLAY)), i = Nt(o, t); let a; if (o.isOver ? (a = Ve.makeVList({ positionType: "firstBaseline", children: [{ type: "elem", elem: s }, { type: "kern", size: .1 }, { type: "elem", elem: i }] }, t), a.children[0].children[0].children[1].classes.push("svg-align")) : (a = Ve.makeVList({ positionType: "bottom", positionData: s.depth + .1 + i.height, children: [{ type: "elem", elem: i }, { type: "kern", size: .1 }, { type: "elem", elem: s }] }, t), a.children[0].children[0].children[0].classes.push("svg-align")), n) { const e = Ve.makeSpan(["mord", o.isOver ? "mover" : "munder"], [a], t); a = o.isOver ? Ve.makeVList({ positionType: "firstBaseline", children: [{ type: "elem", elem: e }, { type: "kern", size: .2 }, { type: "elem", elem: n }] }, t) : Ve.makeVList({ positionType: "bottom", positionData: e.depth + .2 + n.height + n.depth, children: [{ type: "elem", elem: n }, { type: "kern", size: .2 }, { type: "elem", elem: e }] }, t) } return Ve.makeSpan(["mord", o.isOver ? "mover" : "munder"], [a], t) }; je({ type: "horizBrace", names: ["\\overbrace", "\\underbrace"], props: { numArgs: 1 }, handler(e, t) { let { parser: r, funcName: n } = e; return { type: "horizBrace", mode: r.mode, label: n, isOver: /^\\over/.test(n), base: t[0] } }, htmlBuilder: $r, mathmlBuilder: (e, t) => { const r = Ct(e.label); return new gt.MathNode(e.isOver ? "mover" : "munder", [vt(e.base, t), r]) } }), je({ type: "href", names: ["\\href"], props: { numArgs: 2, argTypes: ["url", "original"], allowedInText: !0 }, handler: (e, t) => { let { parser: r } = e; const n = t[1], o = qt(t[0], "url").url; return r.settings.isTrusted({ command: "\\href", url: o }) ? { type: "href", mode: r.mode, href: o, body: Ke(n) } : r.formatUnsupportedCmd("\\href") }, htmlBuilder: (e, t) => { const r = nt(e.body, t, !1); return Ve.makeAnchor(e.href, [], r, t) }, mathmlBuilder: (e, t) => { let r = wt(e.body, t); return r instanceof ut || (r = new ut("mrow", [r])), r.setAttribute("href", e.href), r } }), je({ type: "href", names: ["\\url"], props: { numArgs: 1, argTypes: ["url"], allowedInText: !0 }, handler: (e, t) => { let { parser: r } = e; const n = qt(t[0], "url").url; if (!r.settings.isTrusted({ command: "\\url", url: n })) return r.formatUnsupportedCmd("\\url"); const o = []; for (let e = 0; e < n.length; e++) { let t = n[e]; "~" === t && (t = "\\textasciitilde"), o.push({ type: "textord", mode: "text", text: t }) } const s = { type: "text", mode: r.mode, font: "\\texttt", body: o }; return { type: "href", mode: r.mode, href: n, body: Ke(s) } } }), je({ type: "hbox", names: ["\\hbox"], props: { numArgs: 1, argTypes: ["text"], allowedInText: !0, primitive: !0 }, handler(e, t) { let { parser: r } = e; return { type: "hbox", mode: r.mode, body: Ke(t[0]) } }, htmlBuilder(e, t) { const r = nt(e.body, t, !1); return Ve.makeFragment(r) }, mathmlBuilder(e, t) { return new gt.MathNode("mrow", xt(e.body, t)) } }), je({ type: "html", names: ["\\htmlClass", "\\htmlId", "\\htmlStyle", "\\htmlData"], props: { numArgs: 2, argTypes: ["raw", "original"], allowedInText: !0 }, handler: (e, t) => { let { parser: r, funcName: o, token: s } = e; const i = qt(t[0], "raw").string, a = t[1]; let l; r.settings.strict && r.settings.reportNonstrict("htmlExtension", "HTML extension is disabled on strict mode"); const h = {}; switch (o) { case "\\htmlClass": h.class = i, l = { command: "\\htmlClass", class: i }; break; case "\\htmlId": h.id = i, l = { command: "\\htmlId", id: i }; break; case "\\htmlStyle": h.style = i, l = { command: "\\htmlStyle", style: i }; break; case "\\htmlData": { const e = i.split(","); for (let t = 0; t < e.length; t++) { const r = e[t].split("="); if (2 !== r.length) throw new n("Error parsing key-value for \\htmlData"); h["data-" + r[0].trim()] = r[1].trim() } l = { command: "\\htmlData", attributes: h }; break } default: throw new Error("Unrecognized html command") }return r.settings.isTrusted(l) ? { type: "html", mode: r.mode, attributes: h, body: Ke(a) } : r.formatUnsupportedCmd(o) }, htmlBuilder: (e, t) => { const r = nt(e.body, t, !1), n = ["enclosing"]; e.attributes.class && n.push(...e.attributes.class.trim().split(/\s+/)); const o = Ve.makeSpan(n, r, t); for (const t in e.attributes) "class" !== t && e.attributes.hasOwnProperty(t) && o.setAttribute(t, e.attributes[t]); return o }, mathmlBuilder: (e, t) => wt(e.body, t) }), je({ type: "htmlmathml", names: ["\\html@mathml"], props: { numArgs: 2, allowedInText: !0 }, handler: (e, t) => { let { parser: r } = e; return { type: "htmlmathml", mode: r.mode, html: Ke(t[0]), mathml: Ke(t[1]) } }, htmlBuilder: (e, t) => { const r = nt(e.html, t, !1); return Ve.makeFragment(r) }, mathmlBuilder: (e, t) => wt(e.mathml, t) }); const Zr = function (e) { if (/^[-+]? *(\d+(\.\d*)?|\.\d+)$/.test(e)) return { number: +e, unit: "bp" }; { const t = /([-+]?) *(\d+(?:\.\d*)?|\.\d+) *([a-z]{2})/.exec(e); if (!t) throw new n("Invalid size: '" + e + "' in \\includegraphics"); const r = { number: +(t[1] + t[2]), unit: t[3] }; if (!V(r)) throw new n("Invalid unit: '" + r.unit + "' in \\includegraphics."); return r } }; je({ type: "includegraphics", names: ["\\includegraphics"], props: { numArgs: 1, numOptionalArgs: 1, argTypes: ["raw", "url"], allowedInText: !1 }, handler: (e, t, r) => { let { parser: o } = e, s = { number: 0, unit: "em" }, i = { number: .9, unit: "em" }, a = { number: 0, unit: "em" }, l = ""; if (r[0]) { const e = qt(r[0], "raw").string.split(","); for (let t = 0; t < e.length; t++) { const r = e[t].split("="); if (2 === r.length) { const e = r[1].trim(); switch (r[0].trim()) { case "alt": l = e; break; case "width": s = Zr(e); break; case "height": i = Zr(e); break; case "totalheight": a = Zr(e); break; default: throw new n("Invalid key: '" + r[0] + "' in \\includegraphics.") } } } } const h = qt(t[0], "url").url; return "" === l && (l = h, l = l.replace(/^.*[\\/]/, ""), l = l.substring(0, l.lastIndexOf("."))), o.settings.isTrusted({ command: "\\includegraphics", url: h }) ? { type: "includegraphics", mode: o.mode, alt: l, width: s, height: i, totalheight: a, src: h } : o.formatUnsupportedCmd("\\includegraphics") }, htmlBuilder: (e, t) => { const r = P(e.height, t); let n = 0; e.totalheight.number > 0 && (n = P(e.totalheight, t) - r); let o = 0; e.width.number > 0 && (o = P(e.width, t)); const s = { height: F(r + n) }; o > 0 && (s.width = F(o)), n > 0 && (s.verticalAlign = F(-n)); const i = new j(e.src, e.alt, s); return i.height = r, i.depth = n, i }, mathmlBuilder: (e, t) => { const r = new gt.MathNode("mglyph", []); r.setAttribute("alt", e.alt); const n = P(e.height, t); let o = 0; if (e.totalheight.number > 0 && (o = P(e.totalheight, t) - n, r.setAttribute("valign", F(-o))), r.setAttribute("height", F(n + o)), e.width.number > 0) { const n = P(e.width, t); r.setAttribute("width", F(n)) } return r.setAttribute("src", e.src), r } }), je({ type: "kern", names: ["\\kern", "\\mkern", "\\hskip", "\\mskip"], props: { numArgs: 1, argTypes: ["size"], primitive: !0, allowedInText: !0 }, handler(e, t) { let { parser: r, funcName: n } = e; const o = qt(t[0], "size"); if (r.settings.strict) { const e = "m" === n[1], t = "mu" === o.value.unit; e ? (t || r.settings.reportNonstrict("mathVsTextUnits", "LaTeX's " + n + " supports only mu units, not " + o.value.unit + " units"), "math" !== r.mode && r.settings.reportNonstrict("mathVsTextUnits", "LaTeX's " + n + " works only in math mode")) : t && r.settings.reportNonstrict("mathVsTextUnits", "LaTeX's " + n + " doesn't support mu units") } return { type: "kern", mode: r.mode, dimension: o.value } }, htmlBuilder(e, t) { return Ve.makeGlue(e.dimension, t) }, mathmlBuilder(e, t) { const r = P(e.dimension, t); return new gt.SpaceNode(r) } }), je({ type: "lap", names: ["\\mathllap", "\\mathrlap", "\\mathclap"], props: { numArgs: 1, allowedInText: !0 }, handler: (e, t) => { let { parser: r, funcName: n } = e; const o = t[0]; return { type: "lap", mode: r.mode, alignment: n.slice(5), body: o } }, htmlBuilder: (e, t) => { let r; "clap" === e.alignment ? (r = Ve.makeSpan([], [ht(e.body, t)]), r = Ve.makeSpan(["inner"], [r], t)) : r = Ve.makeSpan(["inner"], [ht(e.body, t)]); const n = Ve.makeSpan(["fix"], []); let o = Ve.makeSpan([e.alignment], [r, n], t); const s = Ve.makeSpan(["strut"]); return s.style.height = F(o.height + o.depth), o.depth && (s.style.verticalAlign = F(-o.depth)), o.children.unshift(s), o = Ve.makeSpan(["thinbox"], [o], t), Ve.makeSpan(["mord", "vbox"], [o], t) }, mathmlBuilder: (e, t) => { const r = new gt.MathNode("mpadded", [vt(e.body, t)]); if ("rlap" !== e.alignment) { const t = "llap" === e.alignment ? "-1" : "-0.5"; r.setAttribute("lspace", t + "width") } return r.setAttribute("width", "0px"), r } }), je({ type: "styling", names: ["\\(", "$"], props: { numArgs: 0, allowedInText: !0, allowedInMath: !1 }, handler(e, t) { let { funcName: r, parser: n } = e; const o = n.mode; n.switchMode("math"); const s = "\\(" === r ? "\\)" : "$", i = n.parseExpression(!1, s); return n.expect(s), n.switchMode(o), { type: "styling", mode: n.mode, style: "text", body: i } } }), je({ type: "text", names: ["\\)", "\\]"], props: { numArgs: 0, allowedInText: !0, allowedInMath: !1 }, handler(e, t) { throw new n("Mismatched " + e.funcName) } }); const Kr = (e, t) => { switch (t.style.size) { case w.DISPLAY.size: return e.display; case w.TEXT.size: return e.text; case w.SCRIPT.size: return e.script; case w.SCRIPTSCRIPT.size: return e.scriptscript; default: return e.text } }; je({ type: "mathchoice", names: ["\\mathchoice"], props: { numArgs: 4, primitive: !0 }, handler: (e, t) => { let { parser: r } = e; return { type: "mathchoice", mode: r.mode, display: Ke(t[0]), text: Ke(t[1]), script: Ke(t[2]), scriptscript: Ke(t[3]) } }, htmlBuilder: (e, t) => { const r = Kr(e, t), n = nt(r, t, !1); return Ve.makeFragment(n) }, mathmlBuilder: (e, t) => { const r = Kr(e, t); return wt(r, t) } }); const Jr = (e, t, r, n, o, s, i) => { e = Ve.makeSpan([], [e]); const a = r && l.isCharacterBox(r); let h, c, m; if (t) { const e = ht(t, n.havingStyle(o.sup()), n); c = { elem: e, kern: Math.max(n.fontMetrics().bigOpSpacing1, n.fontMetrics().bigOpSpacing3 - e.depth) } } if (r) { const e = ht(r, n.havingStyle(o.sub()), n); h = { elem: e, kern: Math.max(n.fontMetrics().bigOpSpacing2, n.fontMetrics().bigOpSpacing4 - e.height) } } if (c && h) { const t = n.fontMetrics().bigOpSpacing5 + h.elem.height + h.elem.depth + h.kern + e.depth + i; m = Ve.makeVList({ positionType: "bottom", positionData: t, children: [{ type: "kern", size: n.fontMetrics().bigOpSpacing5 }, { type: "elem", elem: h.elem, marginLeft: F(-s) }, { type: "kern", size: h.kern }, { type: "elem", elem: e }, { type: "kern", size: c.kern }, { type: "elem", elem: c.elem, marginLeft: F(s) }, { type: "kern", size: n.fontMetrics().bigOpSpacing5 }] }, n) } else if (h) { const t = e.height - i; m = Ve.makeVList({ positionType: "top", positionData: t, children: [{ type: "kern", size: n.fontMetrics().bigOpSpacing5 }, { type: "elem", elem: h.elem, marginLeft: F(-s) }, { type: "kern", size: h.kern }, { type: "elem", elem: e }] }, n) } else { if (!c) return e; { const t = e.depth + i; m = Ve.makeVList({ positionType: "bottom", positionData: t, children: [{ type: "elem", elem: e }, { type: "kern", size: c.kern }, { type: "elem", elem: c.elem, marginLeft: F(s) }, { type: "kern", size: n.fontMetrics().bigOpSpacing5 }] }, n) } } const p = [m]; if (h && 0 !== s && !a) { const e = Ve.makeSpan(["mspace"], [], n); e.style.marginRight = F(s), p.unshift(e) } return Ve.makeSpan(["mop", "op-limits"], p, n) }, Qr = ["\\smallint"], en = (e, t) => { let r, n, o, s = !1; "supsub" === e.type ? (r = e.sup, n = e.sub, o = qt(e.base, "op"), s = !0) : o = qt(e, "op"); const i = t.style; let a, h = !1; if (i.size === w.DISPLAY.size && o.symbol && !l.contains(Qr, o.name) && (h = !0), o.symbol) { const e = h ? "Size2-Regular" : "Size1-Regular"; let r = ""; if ("\\oiint" !== o.name && "\\oiiint" !== o.name || (r = o.name.slice(1), o.name = "oiint" === r ? "\\iint" : "\\iiint"), a = Ve.makeSymbol(o.name, e, "math", t, ["mop", "op-symbol", h ? "large-op" : "small-op"]), r.length > 0) { const e = a.italic, n = Ve.staticSvg(r + "Size" + (h ? "2" : "1"), t); a = Ve.makeVList({ positionType: "individualShift", children: [{ type: "elem", elem: a, shift: 0 }, { type: "elem", elem: n, shift: h ? .08 : 0 }] }, t), o.name = "\\" + r, a.classes.unshift("mop"), a.italic = e } } else if (o.body) { const e = nt(o.body, t, !0); 1 === e.length && e[0] instanceof Z ? (a = e[0], a.classes[0] = "mop") : a = Ve.makeSpan(["mop"], e, t) } else { const e = []; for (let r = 1; r < o.name.length; r++)e.push(Ve.mathsym(o.name[r], o.mode, t)); a = Ve.makeSpan(["mop"], e, t) } let c = 0, m = 0; return (a instanceof Z || "\\oiint" === o.name || "\\oiiint" === o.name) && !o.suppressBaseShift && (c = (a.height - a.depth) / 2 - t.fontMetrics().axisHeight, m = a.italic), s ? Jr(a, r, n, t, i, m, c) : (c && (a.style.position = "relative", a.style.top = F(c)), a) }, tn = (e, t) => { let r; if (e.symbol) r = new ut("mo", [ft(e.name, e.mode)]), l.contains(Qr, e.name) && r.setAttribute("largeop", "false"); else if (e.body) r = new ut("mo", xt(e.body, t)); else { r = new ut("mi", [new dt(e.name.slice(1))]); const t = new ut("mo", [ft("\u2061", "text")]); r = e.parentIsSupSub ? new ut("mrow", [r, t]) : pt([r, t]) } return r }, rn = { "\u220f": "\\prod", "\u2210": "\\coprod", "\u2211": "\\sum", "\u22c0": "\\bigwedge", "\u22c1": "\\bigvee", "\u22c2": "\\bigcap", "\u22c3": "\\bigcup", "\u2a00": "\\bigodot", "\u2a01": "\\bigoplus", "\u2a02": "\\bigotimes", "\u2a04": "\\biguplus", "\u2a06": "\\bigsqcup" }; je({ type: "op", names: ["\\coprod", "\\bigvee", "\\bigwedge", "\\biguplus", "\\bigcap", "\\bigcup", "\\intop", "\\prod", "\\sum", "\\bigotimes", "\\bigoplus", "\\bigodot", "\\bigsqcup", "\\smallint", "\u220f", "\u2210", "\u2211", "\u22c0", "\u22c1", "\u22c2", "\u22c3", "\u2a00", "\u2a01", "\u2a02", "\u2a04", "\u2a06"], props: { numArgs: 0 }, handler: (e, t) => { let { parser: r, funcName: n } = e, o = n; return 1 === o.length && (o = rn[o]), { type: "op", mode: r.mode, limits: !0, parentIsSupSub: !1, symbol: !0, name: o } }, htmlBuilder: en, mathmlBuilder: tn }), je({ type: "op", names: ["\\mathop"], props: { numArgs: 1, primitive: !0 }, handler: (e, t) => { let { parser: r } = e; const n = t[0]; return { type: "op", mode: r.mode, limits: !1, parentIsSupSub: !1, symbol: !1, body: Ke(n) } }, htmlBuilder: en, mathmlBuilder: tn }); const nn = { "\u222b": "\\int", "\u222c": "\\iint", "\u222d": "\\iiint", "\u222e": "\\oint", "\u222f": "\\oiint", "\u2230": "\\oiiint" }; je({ type: "op", names: ["\\arcsin", "\\arccos", "\\arctan", "\\arctg", "\\arcctg", "\\arg", "\\ch", "\\cos", "\\cosec", "\\cosh", "\\cot", "\\cotg", "\\coth", "\\csc", "\\ctg", "\\cth", "\\deg", "\\dim", "\\exp", "\\hom", "\\ker", "\\lg", "\\ln", "\\log", "\\sec", "\\sin", "\\sinh", "\\sh", "\\tan", "\\tanh", "\\tg", "\\th"], props: { numArgs: 0 }, handler(e) { let { parser: t, funcName: r } = e; return { type: "op", mode: t.mode, limits: !1, parentIsSupSub: !1, symbol: !1, name: r } }, htmlBuilder: en, mathmlBuilder: tn }), je({ type: "op", names: ["\\det", "\\gcd", "\\inf", "\\lim", "\\max", "\\min", "\\Pr", "\\sup"], props: { numArgs: 0 }, handler(e) { let { parser: t, funcName: r } = e; return { type: "op", mode: t.mode, limits: !0, parentIsSupSub: !1, symbol: !1, name: r } }, htmlBuilder: en, mathmlBuilder: tn }), je({ type: "op", names: ["\\int", "\\iint", "\\iiint", "\\oint", "\\oiint", "\\oiiint", "\u222b", "\u222c", "\u222d", "\u222e", "\u222f", "\u2230"], props: { numArgs: 0 }, handler(e) { let { parser: t, funcName: r } = e, n = r; return 1 === n.length && (n = nn[n]), { type: "op", mode: t.mode, limits: !1, parentIsSupSub: !1, symbol: !0, name: n } }, htmlBuilder: en, mathmlBuilder: tn }); const on = (e, t) => { let r, n, o, s, i = !1; if ("supsub" === e.type ? (r = e.sup, n = e.sub, o = qt(e.base, "operatorname"), i = !0) : o = qt(e, "operatorname"), o.body.length > 0) { const e = o.body.map((e => { const t = e.text; return "string" == typeof t ? { type: "textord", mode: e.mode, text: t } : e })), r = nt(e, t.withFont("mathrm"), !0); for (let e = 0; e < r.length; e++) { const t = r[e]; t instanceof Z && (t.text = t.text.replace(/\u2212/, "-").replace(/\u2217/, "*")) } s = Ve.makeSpan(["mop"], r, t) } else s = Ve.makeSpan(["mop"], [], t); return i ? Jr(s, r, n, t, t.style, 0, 0) : s }; function sn(e, t, r) { const n = nt(e, t, !1), o = t.sizeMultiplier / r.sizeMultiplier; for (let e = 0; e < n.length; e++) { const s = n[e].classes.indexOf("sizing"); s < 0 ? Array.prototype.push.apply(n[e].classes, t.sizingClasses(r)) : n[e].classes[s + 1] === "reset-size" + t.size && (n[e].classes[s + 1] = "reset-size" + r.size), n[e].height *= o, n[e].depth *= o } return Ve.makeFragment(n) } je({ type: "operatorname", names: ["\\operatorname@", "\\operatornamewithlimits"], props: { numArgs: 1 }, handler: (e, t) => { let { parser: r, funcName: n } = e; const o = t[0]; return { type: "operatorname", mode: r.mode, body: Ke(o), alwaysHandleSupSub: "\\operatornamewithlimits" === n, limits: !1, parentIsSupSub: !1 } }, htmlBuilder: on, mathmlBuilder: (e, t) => { let r = xt(e.body, t.withFont("mathrm")), n = !0; for (let e = 0; e < r.length; e++) { const t = r[e]; if (t instanceof gt.SpaceNode); else if (t instanceof gt.MathNode) switch (t.type) { case "mi": case "mn": case "ms": case "mspace": case "mtext": break; case "mo": { const e = t.children[0]; 1 === t.children.length && e instanceof gt.TextNode ? e.text = e.text.replace(/\u2212/, "-").replace(/\u2217/, "*") : n = !1; break } default: n = !1 } else n = !1 } if (n) { const e = r.map((e => e.toText())).join(""); r = [new gt.TextNode(e)] } const o = new gt.MathNode("mi", r); o.setAttribute("mathvariant", "normal"); const s = new gt.MathNode("mo", [ft("\u2061", "text")]); return e.parentIsSupSub ? new gt.MathNode("mrow", [o, s]) : gt.newDocumentFragment([o, s]) } }), Br("\\operatorname", "\\@ifstar\\operatornamewithlimits\\operatorname@"), $e({ type: "ordgroup", htmlBuilder(e, t) { return e.semisimple ? Ve.makeFragment(nt(e.body, t, !1)) : Ve.makeSpan(["mord"], nt(e.body, t, !0), t) }, mathmlBuilder(e, t) { return wt(e.body, t, !0) } }), je({ type: "overline", names: ["\\overline"], props: { numArgs: 1 }, handler(e, t) { let { parser: r } = e; const n = t[0]; return { type: "overline", mode: r.mode, body: n } }, htmlBuilder(e, t) { const r = ht(e.body, t.havingCrampedStyle()), n = Ve.makeLineSpan("overline-line", t), o = t.fontMetrics().defaultRuleThickness, s = Ve.makeVList({ positionType: "firstBaseline", children: [{ type: "elem", elem: r }, { type: "kern", size: 3 * o }, { type: "elem", elem: n }, { type: "kern", size: o }] }, t); return Ve.makeSpan(["mord", "overline"], [s], t) }, mathmlBuilder(e, t) { const r = new gt.MathNode("mo", [new gt.TextNode("\u203e")]); r.setAttribute("stretchy", "true"); const n = new gt.MathNode("mover", [vt(e.body, t), r]); return n.setAttribute("accent", "true"), n } }), je({ type: "phantom", names: ["\\phantom"], props: { numArgs: 1, allowedInText: !0 }, handler: (e, t) => { let { parser: r } = e; const n = t[0]; return { type: "phantom", mode: r.mode, body: Ke(n) } }, htmlBuilder: (e, t) => { const r = nt(e.body, t.withPhantom(), !1); return Ve.makeFragment(r) }, mathmlBuilder: (e, t) => { const r = xt(e.body, t); return new gt.MathNode("mphantom", r) } }), je({ type: "hphantom", names: ["\\hphantom"], props: { numArgs: 1, allowedInText: !0 }, handler: (e, t) => { let { parser: r } = e; const n = t[0]; return { type: "hphantom", mode: r.mode, body: n } }, htmlBuilder: (e, t) => { let r = Ve.makeSpan([], [ht(e.body, t.withPhantom())]); if (r.height = 0, r.depth = 0, r.children) for (let e = 0; e < r.children.length; e++)r.children[e].height = 0, r.children[e].depth = 0; return r = Ve.makeVList({ positionType: "firstBaseline", children: [{ type: "elem", elem: r }] }, t), Ve.makeSpan(["mord"], [r], t) }, mathmlBuilder: (e, t) => { const r = xt(Ke(e.body), t), n = new gt.MathNode("mphantom", r), o = new gt.MathNode("mpadded", [n]); return o.setAttribute("height", "0px"), o.setAttribute("depth", "0px"), o } }), je({ type: "vphantom", names: ["\\vphantom"], props: { numArgs: 1, allowedInText: !0 }, handler: (e, t) => { let { parser: r } = e; const n = t[0]; return { type: "vphantom", mode: r.mode, body: n } }, htmlBuilder: (e, t) => { const r = Ve.makeSpan(["inner"], [ht(e.body, t.withPhantom())]), n = Ve.makeSpan(["fix"], []); return Ve.makeSpan(["mord", "rlap"], [r, n], t) }, mathmlBuilder: (e, t) => { const r = xt(Ke(e.body), t), n = new gt.MathNode("mphantom", r), o = new gt.MathNode("mpadded", [n]); return o.setAttribute("width", "0px"), o } }), je({ type: "raisebox", names: ["\\raisebox"], props: { numArgs: 2, argTypes: ["size", "hbox"], allowedInText: !0 }, handler(e, t) { let { parser: r } = e; const n = qt(t[0], "size").value, o = t[1]; return { type: "raisebox", mode: r.mode, dy: n, body: o } }, htmlBuilder(e, t) { const r = ht(e.body, t), n = P(e.dy, t); return Ve.makeVList({ positionType: "shift", positionData: -n, children: [{ type: "elem", elem: r }] }, t) }, mathmlBuilder(e, t) { const r = new gt.MathNode("mpadded", [vt(e.body, t)]), n = e.dy.number + e.dy.unit; return r.setAttribute("voffset", n), r } }), je({ type: "internal", names: ["\\relax"], props: { numArgs: 0, allowedInText: !0 }, handler(e) { let { parser: t } = e; return { type: "internal", mode: t.mode } } }), je({ type: "rule", names: ["\\rule"], props: { numArgs: 2, numOptionalArgs: 1, argTypes: ["size", "size", "size"] }, handler(e, t, r) { let { parser: n } = e; const o = r[0], s = qt(t[0], "size"), i = qt(t[1], "size"); return { type: "rule", mode: n.mode, shift: o && qt(o, "size").value, width: s.value, height: i.value } }, htmlBuilder(e, t) { const r = Ve.makeSpan(["mord", "rule"], [], t), n = P(e.width, t), o = P(e.height, t), s = e.shift ? P(e.shift, t) : 0; return r.style.borderRightWidth = F(n), r.style.borderTopWidth = F(o), r.style.bottom = F(s), r.width = n, r.height = o + s, r.depth = -s, r.maxFontSize = 1.125 * o * t.sizeMultiplier, r }, mathmlBuilder(e, t) { const r = P(e.width, t), n = P(e.height, t), o = e.shift ? P(e.shift, t) : 0, s = t.color && t.getColor() || "black", i = new gt.MathNode("mspace"); i.setAttribute("mathbackground", s), i.setAttribute("width", F(r)), i.setAttribute("height", F(n)); const a = new gt.MathNode("mpadded", [i]); return o >= 0 ? a.setAttribute("height", F(o)) : (a.setAttribute("height", F(o)), a.setAttribute("depth", F(-o))), a.setAttribute("voffset", F(o)), a } }); const an = ["\\tiny", "\\sixptsize", "\\scriptsize", "\\footnotesize", "\\small", "\\normalsize", "\\large", "\\Large", "\\LARGE", "\\huge", "\\Huge"]; je({ type: "sizing", names: an, props: { numArgs: 0, allowedInText: !0 }, handler: (e, t) => { let { breakOnTokenText: r, funcName: n, parser: o } = e; const s = o.parseExpression(!1, r); return { type: "sizing", mode: o.mode, size: an.indexOf(n) + 1, body: s } }, htmlBuilder: (e, t) => { const r = t.havingSize(e.size); return sn(e.body, r, t) }, mathmlBuilder: (e, t) => { const r = t.havingSize(e.size), n = xt(e.body, r), o = new gt.MathNode("mstyle", n); return o.setAttribute("mathsize", F(r.sizeMultiplier)), o } }), je({ type: "smash", names: ["\\smash"], props: { numArgs: 1, numOptionalArgs: 1, allowedInText: !0 }, handler: (e, t, r) => { let { parser: n } = e, o = !1, s = !1; const i = r[0] && qt(r[0], "ordgroup"); if (i) { let e = ""; for (let t = 0; t < i.body.length; ++t) { if (e = i.body[t].text, "t" === e) o = !0; else { if ("b" !== e) { o = !1, s = !1; break } s = !0 } } } else o = !0, s = !0; const a = t[0]; return { type: "smash", mode: n.mode, body: a, smashHeight: o, smashDepth: s } }, htmlBuilder: (e, t) => { const r = Ve.makeSpan([], [ht(e.body, t)]); if (!e.smashHeight && !e.smashDepth) return r; if (e.smashHeight && (r.height = 0, r.children)) for (let e = 0; e < r.children.length; e++)r.children[e].height = 0; if (e.smashDepth && (r.depth = 0, r.children)) for (let e = 0; e < r.children.length; e++)r.children[e].depth = 0; const n = Ve.makeVList({ positionType: "firstBaseline", children: [{ type: "elem", elem: r }] }, t); return Ve.makeSpan(["mord"], [n], t) }, mathmlBuilder: (e, t) => { const r = new gt.MathNode("mpadded", [vt(e.body, t)]); return e.smashHeight && r.setAttribute("height", "0px"), e.smashDepth && r.setAttribute("depth", "0px"), r } }), je({ type: "sqrt", names: ["\\sqrt"], props: { numArgs: 1, numOptionalArgs: 1 }, handler(e, t, r) { let { parser: n } = e; const o = r[0], s = t[0]; return { type: "sqrt", mode: n.mode, body: s, index: o } }, htmlBuilder(e, t) { let r = ht(e.body, t.havingCrampedStyle()); 0 === r.height && (r.height = t.fontMetrics().xHeight), r = Ve.wrapFragment(r, t); const n = t.fontMetrics().defaultRuleThickness; let o = n; t.style.id < w.TEXT.id && (o = t.fontMetrics().xHeight); let s = n + o / 4; const i = r.height + r.depth + s + n, { span: a, ruleWidth: l, advanceWidth: h } = yr.sqrtImage(i, t), c = a.height - l; c > r.height + r.depth + s && (s = (s + c - r.height - r.depth) / 2); const m = a.height - r.height - s - l; r.style.paddingLeft = F(h); const p = Ve.makeVList({ positionType: "firstBaseline", children: [{ type: "elem", elem: r, wrapperClasses: ["svg-align"] }, { type: "kern", size: -(r.height + m) }, { type: "elem", elem: a }, { type: "kern", size: l }] }, t); if (e.index) { const r = t.havingStyle(w.SCRIPTSCRIPT), n = ht(e.index, r, t), o = .6 * (p.height - p.depth), s = Ve.makeVList({ positionType: "shift", positionData: -o, children: [{ type: "elem", elem: n }] }, t), i = Ve.makeSpan(["root"], [s]); return Ve.makeSpan(["mord", "sqrt"], [i, p], t) } return Ve.makeSpan(["mord", "sqrt"], [p], t) }, mathmlBuilder(e, t) { const { body: r, index: n } = e; return n ? new gt.MathNode("mroot", [vt(r, t), vt(n, t)]) : new gt.MathNode("msqrt", [vt(r, t)]) } }); const ln = { display: w.DISPLAY, text: w.TEXT, script: w.SCRIPT, scriptscript: w.SCRIPTSCRIPT }; je({ type: "styling", names: ["\\displaystyle", "\\textstyle", "\\scriptstyle", "\\scriptscriptstyle"], props: { numArgs: 0, allowedInText: !0, primitive: !0 }, handler(e, t) { let { breakOnTokenText: r, funcName: n, parser: o } = e; const s = o.parseExpression(!0, r), i = n.slice(1, n.length - 5); return { type: "styling", mode: o.mode, style: i, body: s } }, htmlBuilder(e, t) { const r = ln[e.style], n = t.havingStyle(r).withFont(""); return sn(e.body, n, t) }, mathmlBuilder(e, t) { const r = ln[e.style], n = t.havingStyle(r), o = xt(e.body, n), s = new gt.MathNode("mstyle", o), i = { display: ["0", "true"], text: ["0", "false"], script: ["1", "false"], scriptscript: ["2", "false"] }[e.style]; return s.setAttribute("scriptlevel", i[0]), s.setAttribute("displaystyle", i[1]), s } }); $e({ type: "supsub", htmlBuilder(e, t) { const r = function (e, t) { const r = e.base; if (r) return "op" === r.type ? r.limits && (t.style.size === w.DISPLAY.size || r.alwaysHandleSupSub) ? en : null : "operatorname" === r.type ? r.alwaysHandleSupSub && (t.style.size === w.DISPLAY.size || r.limits) ? on : null : "accent" === r.type ? l.isCharacterBox(r.base) ? Ht : null : "horizBrace" === r.type && !e.sub === r.isOver ? $r : null; return null }(e, t); if (r) return r(e, t); const { base: n, sup: o, sub: s } = e, i = ht(n, t); let a, h; const c = t.fontMetrics(); let m = 0, p = 0; const u = n && l.isCharacterBox(n); if (o) { const e = t.havingStyle(t.style.sup()); a = ht(o, e, t), u || (m = i.height - e.fontMetrics().supDrop * e.sizeMultiplier / t.sizeMultiplier) } if (s) { const e = t.havingStyle(t.style.sub()); h = ht(s, e, t), u || (p = i.depth + e.fontMetrics().subDrop * e.sizeMultiplier / t.sizeMultiplier) } let d; d = t.style === w.DISPLAY ? c.sup1 : t.style.cramped ? c.sup3 : c.sup2; const g = t.sizeMultiplier, f = F(.5 / c.ptPerEm / g); let b, y = null; if (h) { const t = e.base && "op" === e.base.type && e.base.name && ("\\oiint" === e.base.name || "\\oiiint" === e.base.name); (i instanceof Z || t) && (y = F(-i.italic)) } if (a && h) { m = Math.max(m, d, a.depth + .25 * c.xHeight), p = Math.max(p, c.sub2); const e = 4 * c.defaultRuleThickness; if (m - a.depth - (h.height - p) < e) { p = e - (m - a.depth) + h.height; const t = .8 * c.xHeight - (m - a.depth); t > 0 && (m += t, p -= t) } const r = [{ type: "elem", elem: h, shift: p, marginRight: f, marginLeft: y }, { type: "elem", elem: a, shift: -m, marginRight: f }]; b = Ve.makeVList({ positionType: "individualShift", children: r }, t) } else if (h) { p = Math.max(p, c.sub1, h.height - .8 * c.xHeight); const e = [{ type: "elem", elem: h, marginLeft: y, marginRight: f }]; b = Ve.makeVList({ positionType: "shift", positionData: p, children: e }, t) } else { if (!a) throw new Error("supsub must have either sup or sub."); m = Math.max(m, d, a.depth + .25 * c.xHeight), b = Ve.makeVList({ positionType: "shift", positionData: -m, children: [{ type: "elem", elem: a, marginRight: f }] }, t) } const x = at(i, "right") || "mord"; return Ve.makeSpan([x], [i, Ve.makeSpan(["msupsub"], [b])], t) }, mathmlBuilder(e, t) { let r, n, o = !1; e.base && "horizBrace" === e.base.type && (n = !!e.sup, n === e.base.isOver && (o = !0, r = e.base.isOver)), !e.base || "op" !== e.base.type && "operatorname" !== e.base.type || (e.base.parentIsSupSub = !0); const s = [vt(e.base, t)]; let i; if (e.sub && s.push(vt(e.sub, t)), e.sup && s.push(vt(e.sup, t)), o) i = r ? "mover" : "munder"; else if (e.sub) if (e.sup) { const r = e.base; i = r && "op" === r.type && r.limits && t.style === w.DISPLAY || r && "operatorname" === r.type && r.alwaysHandleSupSub && (t.style === w.DISPLAY || r.limits) ? "munderover" : "msubsup" } else { const r = e.base; i = r && "op" === r.type && r.limits && (t.style === w.DISPLAY || r.alwaysHandleSupSub) || r && "operatorname" === r.type && r.alwaysHandleSupSub && (r.limits || t.style === w.DISPLAY) ? "munder" : "msub" } else { const r = e.base; i = r && "op" === r.type && r.limits && (t.style === w.DISPLAY || r.alwaysHandleSupSub) || r && "operatorname" === r.type && r.alwaysHandleSupSub && (r.limits || t.style === w.DISPLAY) ? "mover" : "msup" } return new gt.MathNode(i, s) } }), $e({ type: "atom", htmlBuilder(e, t) { return Ve.mathsym(e.text, e.mode, t, ["m" + e.family]) }, mathmlBuilder(e, t) { const r = new gt.MathNode("mo", [ft(e.text, e.mode)]); if ("bin" === e.family) { const n = yt(e, t); "bold-italic" === n && r.setAttribute("mathvariant", n) } else "punct" === e.family ? r.setAttribute("separator", "true") : "open" !== e.family && "close" !== e.family || r.setAttribute("stretchy", "false"); return r } }); const hn = { mi: "italic", mn: "normal", mtext: "normal" }; $e({ type: "mathord", htmlBuilder(e, t) { return Ve.makeOrd(e, t, "mathord") }, mathmlBuilder(e, t) { const r = new gt.MathNode("mi", [ft(e.text, e.mode, t)]), n = yt(e, t) || "italic"; return n !== hn[r.type] && r.setAttribute("mathvariant", n), r } }), $e({ type: "textord", htmlBuilder(e, t) { return Ve.makeOrd(e, t, "textord") }, mathmlBuilder(e, t) { const r = ft(e.text, e.mode, t), n = yt(e, t) || "normal"; let o; return o = "text" === e.mode ? new gt.MathNode("mtext", [r]) : /[0-9]/.test(e.text) ? new gt.MathNode("mn", [r]) : "\\prime" === e.text ? new gt.MathNode("mo", [r]) : new gt.MathNode("mi", [r]), n !== hn[o.type] && o.setAttribute("mathvariant", n), o } }); const cn = { "\\nobreak": "nobreak", "\\allowbreak": "allowbreak" }, mn = { " ": {}, "\\ ": {}, "~": { className: "nobreak" }, "\\space": {}, "\\nobreakspace": { className: "nobreak" } }; $e({ type: "spacing", htmlBuilder(e, t) { if (mn.hasOwnProperty(e.text)) { const r = mn[e.text].className || ""; if ("text" === e.mode) { const n = Ve.makeOrd(e, t, "textord"); return n.classes.push(r), n } return Ve.makeSpan(["mspace", r], [Ve.mathsym(e.text, e.mode, t)], t) } if (cn.hasOwnProperty(e.text)) return Ve.makeSpan(["mspace", cn[e.text]], [], t); throw new n('Unknown type of space "' + e.text + '"') }, mathmlBuilder(e, t) { let r; if (!mn.hasOwnProperty(e.text)) { if (cn.hasOwnProperty(e.text)) return new gt.MathNode("mspace"); throw new n('Unknown type of space "' + e.text + '"') } return r = new gt.MathNode("mtext", [new gt.TextNode("\xa0")]), r } }); const pn = () => { const e = new gt.MathNode("mtd", []); return e.setAttribute("width", "50%"), e }; $e({ type: "tag", mathmlBuilder(e, t) { const r = new gt.MathNode("mtable", [new gt.MathNode("mtr", [pn(), new gt.MathNode("mtd", [wt(e.body, t)]), pn(), new gt.MathNode("mtd", [wt(e.tag, t)])])]); return r.setAttribute("width", "100%"), r } }); const un = { "\\text": void 0, "\\textrm": "textrm", "\\textsf": "textsf", "\\texttt": "texttt", "\\textnormal": "textrm" }, dn = { "\\textbf": "textbf", "\\textmd": "textmd" }, gn = { "\\textit": "textit", "\\textup": "textup" }, fn = (e, t) => { const r = e.font; return r ? un[r] ? t.withTextFontFamily(un[r]) : dn[r] ? t.withTextFontWeight(dn[r]) : "\\emph" === r ? "textit" === t.fontShape ? t.withTextFontShape("textup") : t.withTextFontShape("textit") : t.withTextFontShape(gn[r]) : t }; je({ type: "text", names: ["\\text", "\\textrm", "\\textsf", "\\texttt", "\\textnormal", "\\textbf", "\\textmd", "\\textit", "\\textup", "\\emph"], props: { numArgs: 1, argTypes: ["text"], allowedInArgument: !0, allowedInText: !0 }, handler(e, t) { let { parser: r, funcName: n } = e; const o = t[0]; return { type: "text", mode: r.mode, body: Ke(o), font: n } }, htmlBuilder(e, t) { const r = fn(e, t), n = nt(e.body, r, !0); return Ve.makeSpan(["mord", "text"], n, r) }, mathmlBuilder(e, t) { const r = fn(e, t); return wt(e.body, r) } }), je({ type: "underline", names: ["\\underline"], props: { numArgs: 1, allowedInText: !0 }, handler(e, t) { let { parser: r } = e; return { type: "underline", mode: r.mode, body: t[0] } }, htmlBuilder(e, t) { const r = ht(e.body, t), n = Ve.makeLineSpan("underline-line", t), o = t.fontMetrics().defaultRuleThickness, s = Ve.makeVList({ positionType: "top", positionData: r.height, children: [{ type: "kern", size: o }, { type: "elem", elem: n }, { type: "kern", size: 3 * o }, { type: "elem", elem: r }] }, t); return Ve.makeSpan(["mord", "underline"], [s], t) }, mathmlBuilder(e, t) { const r = new gt.MathNode("mo", [new gt.TextNode("\u203e")]); r.setAttribute("stretchy", "true"); const n = new gt.MathNode("munder", [vt(e.body, t), r]); return n.setAttribute("accentunder", "true"), n } }), je({ type: "vcenter", names: ["\\vcenter"], props: { numArgs: 1, argTypes: ["original"], allowedInText: !1 }, handler(e, t) { let { parser: r } = e; return { type: "vcenter", mode: r.mode, body: t[0] } }, htmlBuilder(e, t) { const r = ht(e.body, t), n = t.fontMetrics().axisHeight, o = .5 * (r.height - n - (r.depth + n)); return Ve.makeVList({ positionType: "shift", positionData: o, children: [{ type: "elem", elem: r }] }, t) }, mathmlBuilder(e, t) { return new gt.MathNode("mpadded", [vt(e.body, t)], ["vcenter"]) } }), je({ type: "verb", names: ["\\verb"], props: { numArgs: 0, allowedInText: !0 }, handler(e, t, r) { throw new n("\\verb ended by end of line instead of matching delimiter") }, htmlBuilder(e, t) { const r = bn(e), n = [], o = t.havingStyle(t.style.text()); for (let t = 0; t < r.length; t++) { let s = r[t]; "~" === s && (s = "\\textasciitilde"), n.push(Ve.makeSymbol(s, "Typewriter-Regular", e.mode, o, ["mord", "texttt"])) } return Ve.makeSpan(["mord", "text"].concat(o.sizingClasses(t)), Ve.tryCombineChars(n), o) }, mathmlBuilder(e, t) { const r = new gt.TextNode(bn(e)), n = new gt.MathNode("mtext", [r]); return n.setAttribute("mathvariant", "monospace"), n } }); const bn = e => e.body.replace(/ /g, e.star ? "\u2423" : "\xa0"); var yn = Xe; const xn = "[ \r\n\t]", wn = "(\\\\[a-zA-Z@]+)" + xn + "*", vn = "[\u0300-\u036f]", kn = new RegExp(vn + "+$"), Sn = "(" + xn + "+)|\\\\(\n|[ \r\t]+\n?)[ \r\t]*|([!-\\[\\]-\u2027\u202a-\ud7ff\uf900-\uffff]" + vn + "*|[\ud800-\udbff][\udc00-\udfff]" + vn + "*|\\\\verb\\*([^]).*?\\4|\\\\verb([^*a-zA-Z]).*?\\5|" + wn + "|\\\\[^\ud800-\udfff])"; class Mn { constructor(e, t) { this.input = void 0, this.settings = void 0, this.tokenRegex = void 0, this.catcodes = void 0, this.input = e, this.settings = t, this.tokenRegex = new RegExp(Sn, "g"), this.catcodes = { "%": 14, "~": 13 } } setCatcode(e, t) { this.catcodes[e] = t } lex() { const e = this.input, t = this.tokenRegex.lastIndex; if (t === e.length) return new Nr("EOF", new Cr(this, t, t)); const r = this.tokenRegex.exec(e); if (null === r || r.index !== t) throw new n("Unexpected character: '" + e[t] + "'", new Nr(e[t], new Cr(this, t, t + 1))); const o = r[6] || r[3] || (r[2] ? "\\ " : " "); if (14 === this.catcodes[o]) { const t = e.indexOf("\n", this.tokenRegex.lastIndex); return -1 === t ? (this.tokenRegex.lastIndex = e.length, this.settings.reportNonstrict("commentAtEnd", "% comment has no terminating newline; LaTeX would fail because of commenting the end of math mode (e.g. $)")) : this.tokenRegex.lastIndex = t + 1, this.lex() } return new Nr(o, new Cr(this, t, this.tokenRegex.lastIndex)) } } class zn { constructor(e, t) { void 0 === e && (e = {}), void 0 === t && (t = {}), this.current = void 0, this.builtins = void 0, this.undefStack = void 0, this.current = t, this.builtins = e, this.undefStack = [] } beginGroup() { this.undefStack.push({}) } endGroup() { if (0 === this.undefStack.length) throw new n("Unbalanced namespace destruction: attempt to pop global namespace; please report this as a bug"); const e = this.undefStack.pop(); for (const t in e) e.hasOwnProperty(t) && (null == e[t] ? delete this.current[t] : this.current[t] = e[t]) } endGroups() { for (; this.undefStack.length > 0;)this.endGroup() } has(e) { return this.current.hasOwnProperty(e) || this.builtins.hasOwnProperty(e) } get(e) { return this.current.hasOwnProperty(e) ? this.current[e] : this.builtins[e] } set(e, t, r) { if (void 0 === r && (r = !1), r) { for (let t = 0; t < this.undefStack.length; t++)delete this.undefStack[t][e]; this.undefStack.length > 0 && (this.undefStack[this.undefStack.length - 1][e] = t) } else { const t = this.undefStack[this.undefStack.length - 1]; t && !t.hasOwnProperty(e) && (t[e] = this.current[e]) } null == t ? delete this.current[e] : this.current[e] = t } } var An = Tr; Br("\\noexpand", (function (e) { const t = e.popToken(); return e.isExpandable(t.text) && (t.noexpand = !0, t.treatAsRelax = !0), { tokens: [t], numArgs: 0 } })), Br("\\expandafter", (function (e) { const t = e.popToken(); return e.expandOnce(!0), { tokens: [t], numArgs: 0 } })), Br("\\@firstoftwo", (function (e) { return { tokens: e.consumeArgs(2)[0], numArgs: 0 } })), Br("\\@secondoftwo", (function (e) { return { tokens: e.consumeArgs(2)[1], numArgs: 0 } })), Br("\\@ifnextchar", (function (e) { const t = e.consumeArgs(3); e.consumeSpaces(); const r = e.future(); return 1 === t[0].length && t[0][0].text === r.text ? { tokens: t[1], numArgs: 0 } : { tokens: t[2], numArgs: 0 } })), Br("\\@ifstar", "\\@ifnextchar *{\\@firstoftwo{#1}}"), Br("\\TextOrMath", (function (e) { const t = e.consumeArgs(2); return "text" === e.mode ? { tokens: t[0], numArgs: 0 } : { tokens: t[1], numArgs: 0 } })); const Tn = { 0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, a: 10, A: 10, b: 11, B: 11, c: 12, C: 12, d: 13, D: 13, e: 14, E: 14, f: 15, F: 15 }; Br("\\char", (function (e) { let t, r = e.popToken(), o = ""; if ("'" === r.text) t = 8, r = e.popToken(); else if ('"' === r.text) t = 16, r = e.popToken(); else if ("`" === r.text) if (r = e.popToken(), "\\" === r.text[0]) o = r.text.charCodeAt(1); else { if ("EOF" === r.text) throw new n("\\char` missing argument"); o = r.text.charCodeAt(0) } else t = 10; if (t) { if (o = Tn[r.text], null == o || o >= t) throw new n("Invalid base-" + t + " digit " + r.text); let s; for (; null != (s = Tn[e.future().text]) && s < t;)o *= t, o += s, e.popToken() } return "\\@char{" + o + "}" })); const Bn = (e, t, r) => { let o = e.consumeArg().tokens; if (1 !== o.length) throw new n("\\newcommand's first argument must be a macro name"); const s = o[0].text, i = e.isDefined(s); if (i && !t) throw new n("\\newcommand{" + s + "} attempting to redefine " + s + "; use \\renewcommand"); if (!i && !r) throw new n("\\renewcommand{" + s + "} when command " + s + " does not yet exist; use \\newcommand"); let a = 0; if (o = e.consumeArg().tokens, 1 === o.length && "[" === o[0].text) { let t = "", r = e.expandNextToken(); for (; "]" !== r.text && "EOF" !== r.text;)t += r.text, r = e.expandNextToken(); if (!t.match(/^\s*[0-9]+\s*$/)) throw new n("Invalid number of arguments: " + t); a = parseInt(t), o = e.consumeArg().tokens } return e.macros.set(s, { tokens: o, numArgs: a }), "" }; Br("\\newcommand", (e => Bn(e, !1, !0))), Br("\\renewcommand", (e => Bn(e, !0, !1))), Br("\\providecommand", (e => Bn(e, !0, !0))), Br("\\message", (e => { const t = e.consumeArgs(1)[0]; return console.log(t.reverse().map((e => e.text)).join("")), "" })), Br("\\errmessage", (e => { const t = e.consumeArgs(1)[0]; return console.error(t.reverse().map((e => e.text)).join("")), "" })), Br("\\show", (e => { const t = e.popToken(), r = t.text; return console.log(t, e.macros.get(r), yn[r], oe.math[r], oe.text[r]), "" })), Br("\\bgroup", "{"), Br("\\egroup", "}"), Br("~", "\\nobreakspace"), Br("\\lq", "`"), Br("\\rq", "'"), Br("\\aa", "\\r a"), Br("\\AA", "\\r A"), Br("\\textcopyright", "\\html@mathml{\\textcircled{c}}{\\char`\xa9}"), Br("\\copyright", "\\TextOrMath{\\textcopyright}{\\text{\\textcopyright}}"), Br("\\textregistered", "\\html@mathml{\\textcircled{\\scriptsize R}}{\\char`\xae}"), Br("\u212c", "\\mathscr{B}"), Br("\u2130", "\\mathscr{E}"), Br("\u2131", "\\mathscr{F}"), Br("\u210b", "\\mathscr{H}"), Br("\u2110", "\\mathscr{I}"), Br("\u2112", "\\mathscr{L}"), Br("\u2133", "\\mathscr{M}"), Br("\u211b", "\\mathscr{R}"), Br("\u212d", "\\mathfrak{C}"), Br("\u210c", "\\mathfrak{H}"), Br("\u2128", "\\mathfrak{Z}"), Br("\\Bbbk", "\\Bbb{k}"), Br("\xb7", "\\cdotp"), Br("\\llap", "\\mathllap{\\textrm{#1}}"), Br("\\rlap", "\\mathrlap{\\textrm{#1}}"), Br("\\clap", "\\mathclap{\\textrm{#1}}"), Br("\\mathstrut", "\\vphantom{(}"), Br("\\underbar", "\\underline{\\text{#1}}"), Br("\\not", '\\html@mathml{\\mathrel{\\mathrlap\\@not}}{\\char"338}'), Br("\\neq", "\\html@mathml{\\mathrel{\\not=}}{\\mathrel{\\char`\u2260}}"), Br("\\ne", "\\neq"), Br("\u2260", "\\neq"), Br("\\notin", "\\html@mathml{\\mathrel{{\\in}\\mathllap{/\\mskip1mu}}}{\\mathrel{\\char`\u2209}}"), Br("\u2209", "\\notin"), Br("\u2258", "\\html@mathml{\\mathrel{=\\kern{-1em}\\raisebox{0.4em}{$\\scriptsize\\frown$}}}{\\mathrel{\\char`\u2258}}"), Br("\u2259", "\\html@mathml{\\stackrel{\\tiny\\wedge}{=}}{\\mathrel{\\char`\u2258}}"), Br("\u225a", "\\html@mathml{\\stackrel{\\tiny\\vee}{=}}{\\mathrel{\\char`\u225a}}"), Br("\u225b", "\\html@mathml{\\stackrel{\\scriptsize\\star}{=}}{\\mathrel{\\char`\u225b}}"), Br("\u225d", "\\html@mathml{\\stackrel{\\tiny\\mathrm{def}}{=}}{\\mathrel{\\char`\u225d}}"), Br("\u225e", "\\html@mathml{\\stackrel{\\tiny\\mathrm{m}}{=}}{\\mathrel{\\char`\u225e}}"), Br("\u225f", "\\html@mathml{\\stackrel{\\tiny?}{=}}{\\mathrel{\\char`\u225f}}"), Br("\u27c2", "\\perp"), Br("\u203c", "\\mathclose{!\\mkern-0.8mu!}"), Br("\u220c", "\\notni"), Br("\u231c", "\\ulcorner"), Br("\u231d", "\\urcorner"), Br("\u231e", "\\llcorner"), Br("\u231f", "\\lrcorner"), Br("\xa9", "\\copyright"), Br("\xae", "\\textregistered"), Br("\ufe0f", "\\textregistered"), Br("\\ulcorner", '\\html@mathml{\\@ulcorner}{\\mathop{\\char"231c}}'), Br("\\urcorner", '\\html@mathml{\\@urcorner}{\\mathop{\\char"231d}}'), Br("\\llcorner", '\\html@mathml{\\@llcorner}{\\mathop{\\char"231e}}'), Br("\\lrcorner", '\\html@mathml{\\@lrcorner}{\\mathop{\\char"231f}}'), Br("\\vdots", "\\mathord{\\varvdots\\rule{0pt}{15pt}}"), Br("\u22ee", "\\vdots"), Br("\\varGamma", "\\mathit{\\Gamma}"), Br("\\varDelta", "\\mathit{\\Delta}"), Br("\\varTheta", "\\mathit{\\Theta}"), Br("\\varLambda", "\\mathit{\\Lambda}"), Br("\\varXi", "\\mathit{\\Xi}"), Br("\\varPi", "\\mathit{\\Pi}"), Br("\\varSigma", "\\mathit{\\Sigma}"), Br("\\varUpsilon", "\\mathit{\\Upsilon}"), Br("\\varPhi", "\\mathit{\\Phi}"), Br("\\varPsi", "\\mathit{\\Psi}"), Br("\\varOmega", "\\mathit{\\Omega}"), Br("\\substack", "\\begin{subarray}{c}#1\\end{subarray}"), Br("\\colon", "\\nobreak\\mskip2mu\\mathpunct{}\\mathchoice{\\mkern-3mu}{\\mkern-3mu}{}{}{:}\\mskip6mu\\relax"), Br("\\boxed", "\\fbox{$\\displaystyle{#1}$}"), Br("\\iff", "\\DOTSB\\;\\Longleftrightarrow\\;"), Br("\\implies", "\\DOTSB\\;\\Longrightarrow\\;"), Br("\\impliedby", "\\DOTSB\\;\\Longleftarrow\\;"); const Cn = { ",": "\\dotsc", "\\not": "\\dotsb", "+": "\\dotsb", "=": "\\dotsb", "<": "\\dotsb", ">": "\\dotsb", "-": "\\dotsb", "*": "\\dotsb", ":": "\\dotsb", "\\DOTSB": "\\dotsb", "\\coprod": "\\dotsb", "\\bigvee": "\\dotsb", "\\bigwedge": "\\dotsb", "\\biguplus": "\\dotsb", "\\bigcap": "\\dotsb", "\\bigcup": "\\dotsb", "\\prod": "\\dotsb", "\\sum": "\\dotsb", "\\bigotimes": "\\dotsb", "\\bigoplus": "\\dotsb", "\\bigodot": "\\dotsb", "\\bigsqcup": "\\dotsb", "\\And": "\\dotsb", "\\longrightarrow": "\\dotsb", "\\Longrightarrow": "\\dotsb", "\\longleftarrow": "\\dotsb", "\\Longleftarrow": "\\dotsb", "\\longleftrightarrow": "\\dotsb", "\\Longleftrightarrow": "\\dotsb", "\\mapsto": "\\dotsb", "\\longmapsto": "\\dotsb", "\\hookrightarrow": "\\dotsb", "\\doteq": "\\dotsb", "\\mathbin": "\\dotsb", "\\mathrel": "\\dotsb", "\\relbar": "\\dotsb", "\\Relbar": "\\dotsb", "\\xrightarrow": "\\dotsb", "\\xleftarrow": "\\dotsb", "\\DOTSI": "\\dotsi", "\\int": "\\dotsi", "\\oint": "\\dotsi", "\\iint": "\\dotsi", "\\iiint": "\\dotsi", "\\iiiint": "\\dotsi", "\\idotsint": "\\dotsi", "\\DOTSX": "\\dotsx" }; Br("\\dots", (function (e) { let t = "\\dotso"; const r = e.expandAfterFuture().text; return r in Cn ? t = Cn[r] : ("\\not" === r.slice(0, 4) || r in oe.math && l.contains(["bin", "rel"], oe.math[r].group)) && (t = "\\dotsb"), t })); const Nn = { ")": !0, "]": !0, "\\rbrack": !0, "\\}": !0, "\\rbrace": !0, "\\rangle": !0, "\\rceil": !0, "\\rfloor": !0, "\\rgroup": !0, "\\rmoustache": !0, "\\right": !0, "\\bigr": !0, "\\biggr": !0, "\\Bigr": !0, "\\Biggr": !0, $: !0, ";": !0, ".": !0, ",": !0 }; Br("\\dotso", (function (e) { return e.future().text in Nn ? "\\ldots\\," : "\\ldots" })), Br("\\dotsc", (function (e) { const t = e.future().text; return t in Nn && "," !== t ? "\\ldots\\," : "\\ldots" })), Br("\\cdots", (function (e) { return e.future().text in Nn ? "\\@cdots\\," : "\\@cdots" })), Br("\\dotsb", "\\cdots"), Br("\\dotsm", "\\cdots"), Br("\\dotsi", "\\!\\cdots"), Br("\\dotsx", "\\ldots\\,"), Br("\\DOTSI", "\\relax"), Br("\\DOTSB", "\\relax"), Br("\\DOTSX", "\\relax"), Br("\\tmspace", "\\TextOrMath{\\kern#1#3}{\\mskip#1#2}\\relax"), Br("\\,", "\\tmspace+{3mu}{.1667em}"), Br("\\thinspace", "\\,"), Br("\\>", "\\mskip{4mu}"), Br("\\:", "\\tmspace+{4mu}{.2222em}"), Br("\\medspace", "\\:"), Br("\\;", "\\tmspace+{5mu}{.2777em}"), Br("\\thickspace", "\\;"), Br("\\!", "\\tmspace-{3mu}{.1667em}"), Br("\\negthinspace", "\\!"), Br("\\negmedspace", "\\tmspace-{4mu}{.2222em}"), Br("\\negthickspace", "\\tmspace-{5mu}{.277em}"), Br("\\enspace", "\\kern.5em "), Br("\\enskip", "\\hskip.5em\\relax"), Br("\\quad", "\\hskip1em\\relax"), Br("\\qquad", "\\hskip2em\\relax"), Br("\\tag", "\\@ifstar\\tag@literal\\tag@paren"), Br("\\tag@paren", "\\tag@literal{({#1})}"), Br("\\tag@literal", (e => { if (e.macros.get("\\df@tag")) throw new n("Multiple \\tag"); return "\\gdef\\df@tag{\\text{#1}}" })), Br("\\bmod", "\\mathchoice{\\mskip1mu}{\\mskip1mu}{\\mskip5mu}{\\mskip5mu}\\mathbin{\\rm mod}\\mathchoice{\\mskip1mu}{\\mskip1mu}{\\mskip5mu}{\\mskip5mu}"), Br("\\pod", "\\allowbreak\\mathchoice{\\mkern18mu}{\\mkern8mu}{\\mkern8mu}{\\mkern8mu}(#1)"), Br("\\pmod", "\\pod{{\\rm mod}\\mkern6mu#1}"), Br("\\mod", "\\allowbreak\\mathchoice{\\mkern18mu}{\\mkern12mu}{\\mkern12mu}{\\mkern12mu}{\\rm mod}\\,\\,#1"), Br("\\newline", "\\\\\\relax"), Br("\\TeX", "\\textrm{\\html@mathml{T\\kern-.1667em\\raisebox{-.5ex}{E}\\kern-.125emX}{TeX}}"); const qn = F(T["Main-Regular"]["T".charCodeAt(0)][1] - .7 * T["Main-Regular"]["A".charCodeAt(0)][1]); Br("\\LaTeX", "\\textrm{\\html@mathml{L\\kern-.36em\\raisebox{" + qn + "}{\\scriptstyle A}\\kern-.15em\\TeX}{LaTeX}}"), Br("\\KaTeX", "\\textrm{\\html@mathml{K\\kern-.17em\\raisebox{" + qn + "}{\\scriptstyle A}\\kern-.15em\\TeX}{KaTeX}}"), Br("\\hspace", "\\@ifstar\\@hspacer\\@hspace"), Br("\\@hspace", "\\hskip #1\\relax"), Br("\\@hspacer", "\\rule{0pt}{0pt}\\hskip #1\\relax"), Br("\\ordinarycolon", ":"), Br("\\vcentcolon", "\\mathrel{\\mathop\\ordinarycolon}"), Br("\\dblcolon", '\\html@mathml{\\mathrel{\\vcentcolon\\mathrel{\\mkern-.9mu}\\vcentcolon}}{\\mathop{\\char"2237}}'), Br("\\coloneqq", '\\html@mathml{\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}=}}{\\mathop{\\char"2254}}'), Br("\\Coloneqq", '\\html@mathml{\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}=}}{\\mathop{\\char"2237\\char"3d}}'), Br("\\coloneq", '\\html@mathml{\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}\\mathrel{-}}}{\\mathop{\\char"3a\\char"2212}}'), Br("\\Coloneq", '\\html@mathml{\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}\\mathrel{-}}}{\\mathop{\\char"2237\\char"2212}}'), Br("\\eqqcolon", '\\html@mathml{\\mathrel{=\\mathrel{\\mkern-1.2mu}\\vcentcolon}}{\\mathop{\\char"2255}}'), Br("\\Eqqcolon", '\\html@mathml{\\mathrel{=\\mathrel{\\mkern-1.2mu}\\dblcolon}}{\\mathop{\\char"3d\\char"2237}}'), Br("\\eqcolon", '\\html@mathml{\\mathrel{\\mathrel{-}\\mathrel{\\mkern-1.2mu}\\vcentcolon}}{\\mathop{\\char"2239}}'), Br("\\Eqcolon", '\\html@mathml{\\mathrel{\\mathrel{-}\\mathrel{\\mkern-1.2mu}\\dblcolon}}{\\mathop{\\char"2212\\char"2237}}'), Br("\\colonapprox", '\\html@mathml{\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}\\approx}}{\\mathop{\\char"3a\\char"2248}}'), Br("\\Colonapprox", '\\html@mathml{\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}\\approx}}{\\mathop{\\char"2237\\char"2248}}'), Br("\\colonsim", '\\html@mathml{\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}\\sim}}{\\mathop{\\char"3a\\char"223c}}'), Br("\\Colonsim", '\\html@mathml{\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}\\sim}}{\\mathop{\\char"2237\\char"223c}}'), Br("\u2237", "\\dblcolon"), Br("\u2239", "\\eqcolon"), Br("\u2254", "\\coloneqq"), Br("\u2255", "\\eqqcolon"), Br("\u2a74", "\\Coloneqq"), Br("\\ratio", "\\vcentcolon"), Br("\\coloncolon", "\\dblcolon"), Br("\\colonequals", "\\coloneqq"), Br("\\coloncolonequals", "\\Coloneqq"), Br("\\equalscolon", "\\eqqcolon"), Br("\\equalscoloncolon", "\\Eqqcolon"), Br("\\colonminus", "\\coloneq"), Br("\\coloncolonminus", "\\Coloneq"), Br("\\minuscolon", "\\eqcolon"), Br("\\minuscoloncolon", "\\Eqcolon"), Br("\\coloncolonapprox", "\\Colonapprox"), Br("\\coloncolonsim", "\\Colonsim"), Br("\\simcolon", "\\mathrel{\\sim\\mathrel{\\mkern-1.2mu}\\vcentcolon}"), Br("\\simcoloncolon", "\\mathrel{\\sim\\mathrel{\\mkern-1.2mu}\\dblcolon}"), Br("\\approxcolon", "\\mathrel{\\approx\\mathrel{\\mkern-1.2mu}\\vcentcolon}"), Br("\\approxcoloncolon", "\\mathrel{\\approx\\mathrel{\\mkern-1.2mu}\\dblcolon}"), Br("\\notni", "\\html@mathml{\\not\\ni}{\\mathrel{\\char`\u220c}}"), Br("\\limsup", "\\DOTSB\\operatorname*{lim\\,sup}"), Br("\\liminf", "\\DOTSB\\operatorname*{lim\\,inf}"), Br("\\injlim", "\\DOTSB\\operatorname*{inj\\,lim}"), Br("\\projlim", "\\DOTSB\\operatorname*{proj\\,lim}"), Br("\\varlimsup", "\\DOTSB\\operatorname*{\\overline{lim}}"), Br("\\varliminf", "\\DOTSB\\operatorname*{\\underline{lim}}"), Br("\\varinjlim", "\\DOTSB\\operatorname*{\\underrightarrow{lim}}"), Br("\\varprojlim", "\\DOTSB\\operatorname*{\\underleftarrow{lim}}"), Br("\\gvertneqq", "\\html@mathml{\\@gvertneqq}{\u2269}"), Br("\\lvertneqq", "\\html@mathml{\\@lvertneqq}{\u2268}"), Br("\\ngeqq", "\\html@mathml{\\@ngeqq}{\u2271}"), Br("\\ngeqslant", "\\html@mathml{\\@ngeqslant}{\u2271}"), Br("\\nleqq", "\\html@mathml{\\@nleqq}{\u2270}"), Br("\\nleqslant", "\\html@mathml{\\@nleqslant}{\u2270}"), Br("\\nshortmid", "\\html@mathml{\\@nshortmid}{\u2224}"), Br("\\nshortparallel", "\\html@mathml{\\@nshortparallel}{\u2226}"), Br("\\nsubseteqq", "\\html@mathml{\\@nsubseteqq}{\u2288}"), Br("\\nsupseteqq", "\\html@mathml{\\@nsupseteqq}{\u2289}"), Br("\\varsubsetneq", "\\html@mathml{\\@varsubsetneq}{\u228a}"), Br("\\varsubsetneqq", "\\html@mathml{\\@varsubsetneqq}{\u2acb}"), Br("\\varsupsetneq", "\\html@mathml{\\@varsupsetneq}{\u228b}"), Br("\\varsupsetneqq", "\\html@mathml{\\@varsupsetneqq}{\u2acc}"), Br("\\imath", "\\html@mathml{\\@imath}{\u0131}"), Br("\\jmath", "\\html@mathml{\\@jmath}{\u0237}"), Br("\\llbracket", "\\html@mathml{\\mathopen{[\\mkern-3.2mu[}}{\\mathopen{\\char`\u27e6}}"), Br("\\rrbracket", "\\html@mathml{\\mathclose{]\\mkern-3.2mu]}}{\\mathclose{\\char`\u27e7}}"), Br("\u27e6", "\\llbracket"), Br("\u27e7", "\\rrbracket"), Br("\\lBrace", "\\html@mathml{\\mathopen{\\{\\mkern-3.2mu[}}{\\mathopen{\\char`\u2983}}"), Br("\\rBrace", "\\html@mathml{\\mathclose{]\\mkern-3.2mu\\}}}{\\mathclose{\\char`\u2984}}"), Br("\u2983", "\\lBrace"), Br("\u2984", "\\rBrace"), Br("\\minuso", "\\mathbin{\\html@mathml{{\\mathrlap{\\mathchoice{\\kern{0.145em}}{\\kern{0.145em}}{\\kern{0.1015em}}{\\kern{0.0725em}}\\circ}{-}}}{\\char`\u29b5}}"), Br("\u29b5", "\\minuso"), Br("\\darr", "\\downarrow"), Br("\\dArr", "\\Downarrow"), Br("\\Darr", "\\Downarrow"), Br("\\lang", "\\langle"), Br("\\rang", "\\rangle"), Br("\\uarr", "\\uparrow"), Br("\\uArr", "\\Uparrow"), Br("\\Uarr", "\\Uparrow"), Br("\\N", "\\mathbb{N}"), Br("\\R", "\\mathbb{R}"), Br("\\Z", "\\mathbb{Z}"), Br("\\alef", "\\aleph"), Br("\\alefsym", "\\aleph"), Br("\\Alpha", "\\mathrm{A}"), Br("\\Beta", "\\mathrm{B}"), Br("\\bull", "\\bullet"), Br("\\Chi", "\\mathrm{X}"), Br("\\clubs", "\\clubsuit"), Br("\\cnums", "\\mathbb{C}"), Br("\\Complex", "\\mathbb{C}"), Br("\\Dagger", "\\ddagger"), Br("\\diamonds", "\\diamondsuit"), Br("\\empty", "\\emptyset"), Br("\\Epsilon", "\\mathrm{E}"), Br("\\Eta", "\\mathrm{H}"), Br("\\exist", "\\exists"), Br("\\harr", "\\leftrightarrow"), Br("\\hArr", "\\Leftrightarrow"), Br("\\Harr", "\\Leftrightarrow"), Br("\\hearts", "\\heartsuit"), Br("\\image", "\\Im"), Br("\\infin", "\\infty"), Br("\\Iota", "\\mathrm{I}"), Br("\\isin", "\\in"), Br("\\Kappa", "\\mathrm{K}"), Br("\\larr", "\\leftarrow"), Br("\\lArr", "\\Leftarrow"), Br("\\Larr", "\\Leftarrow"), Br("\\lrarr", "\\leftrightarrow"), Br("\\lrArr", "\\Leftrightarrow"), Br("\\Lrarr", "\\Leftrightarrow"), Br("\\Mu", "\\mathrm{M}"), Br("\\natnums", "\\mathbb{N}"), Br("\\Nu", "\\mathrm{N}"), Br("\\Omicron", "\\mathrm{O}"), Br("\\plusmn", "\\pm"), Br("\\rarr", "\\rightarrow"), Br("\\rArr", "\\Rightarrow"), Br("\\Rarr", "\\Rightarrow"), Br("\\real", "\\Re"), Br("\\reals", "\\mathbb{R}"), Br("\\Reals", "\\mathbb{R}"), Br("\\Rho", "\\mathrm{P}"), Br("\\sdot", "\\cdot"), Br("\\sect", "\\S"), Br("\\spades", "\\spadesuit"), Br("\\sub", "\\subset"), Br("\\sube", "\\subseteq"), Br("\\supe", "\\supseteq"), Br("\\Tau", "\\mathrm{T}"), Br("\\thetasym", "\\vartheta"), Br("\\weierp", "\\wp"), Br("\\Zeta", "\\mathrm{Z}"), Br("\\argmin", "\\DOTSB\\operatorname*{arg\\,min}"), Br("\\argmax", "\\DOTSB\\operatorname*{arg\\,max}"), Br("\\plim", "\\DOTSB\\mathop{\\operatorname{plim}}\\limits"), Br("\\bra", "\\mathinner{\\langle{#1}|}"), Br("\\ket", "\\mathinner{|{#1}\\rangle}"), Br("\\braket", "\\mathinner{\\langle{#1}\\rangle}"), Br("\\Bra", "\\left\\langle#1\\right|"), Br("\\Ket", "\\left|#1\\right\\rangle"); const In = e => t => { const r = t.consumeArg().tokens, n = t.consumeArg().tokens, o = t.consumeArg().tokens, s = t.consumeArg().tokens, i = t.macros.get("|"), a = t.macros.get("\\|"); t.macros.beginGroup(); const l = t => r => { e && (r.macros.set("|", i), o.length && r.macros.set("\\|", a)); let s = t; if (!t && o.length) { "|" === r.future().text && (r.popToken(), s = !0) } return { tokens: s ? o : n, numArgs: 0 } }; t.macros.set("|", l(!1)), o.length && t.macros.set("\\|", l(!0)); const h = t.consumeArg().tokens, c = t.expandTokens([...s, ...h, ...r]); return t.macros.endGroup(), { tokens: c.reverse(), numArgs: 0 } }; Br("\\bra@ket", In(!1)), Br("\\bra@set", In(!0)), Br("\\Braket", "\\bra@ket{\\left\\langle}{\\,\\middle\\vert\\,}{\\,\\middle\\vert\\,}{\\right\\rangle}"), Br("\\Set", "\\bra@set{\\left\\{\\:}{\\;\\middle\\vert\\;}{\\;\\middle\\Vert\\;}{\\:\\right\\}}"), Br("\\set", "\\bra@set{\\{\\,}{\\mid}{}{\\,\\}}"), Br("\\angln", "{\\angl n}"), Br("\\blue", "\\textcolor{##6495ed}{#1}"), Br("\\orange", "\\textcolor{##ffa500}{#1}"), Br("\\pink", "\\textcolor{##ff00af}{#1}"), Br("\\red", "\\textcolor{##df0030}{#1}"), Br("\\green", "\\textcolor{##28ae7b}{#1}"), Br("\\gray", "\\textcolor{gray}{#1}"), Br("\\purple", "\\textcolor{##9d38bd}{#1}"), Br("\\blueA", "\\textcolor{##ccfaff}{#1}"), Br("\\blueB", "\\textcolor{##80f6ff}{#1}"), Br("\\blueC", "\\textcolor{##63d9ea}{#1}"), Br("\\blueD", "\\textcolor{##11accd}{#1}"), Br("\\blueE", "\\textcolor{##0c7f99}{#1}"), Br("\\tealA", "\\textcolor{##94fff5}{#1}"), Br("\\tealB", "\\textcolor{##26edd5}{#1}"), Br("\\tealC", "\\textcolor{##01d1c1}{#1}"), Br("\\tealD", "\\textcolor{##01a995}{#1}"), Br("\\tealE", "\\textcolor{##208170}{#1}"), Br("\\greenA", "\\textcolor{##b6ffb0}{#1}"), Br("\\greenB", "\\textcolor{##8af281}{#1}"), Br("\\greenC", "\\textcolor{##74cf70}{#1}"), Br("\\greenD", "\\textcolor{##1fab54}{#1}"), Br("\\greenE", "\\textcolor{##0d923f}{#1}"), Br("\\goldA", "\\textcolor{##ffd0a9}{#1}"), Br("\\goldB", "\\textcolor{##ffbb71}{#1}"), Br("\\goldC", "\\textcolor{##ff9c39}{#1}"), Br("\\goldD", "\\textcolor{##e07d10}{#1}"), Br("\\goldE", "\\textcolor{##a75a05}{#1}"), Br("\\redA", "\\textcolor{##fca9a9}{#1}"), Br("\\redB", "\\textcolor{##ff8482}{#1}"), Br("\\redC", "\\textcolor{##f9685d}{#1}"), Br("\\redD", "\\textcolor{##e84d39}{#1}"), Br("\\redE", "\\textcolor{##bc2612}{#1}"), Br("\\maroonA", "\\textcolor{##ffbde0}{#1}"), Br("\\maroonB", "\\textcolor{##ff92c6}{#1}"), Br("\\maroonC", "\\textcolor{##ed5fa6}{#1}"), Br("\\maroonD", "\\textcolor{##ca337c}{#1}"), Br("\\maroonE", "\\textcolor{##9e034e}{#1}"), Br("\\purpleA", "\\textcolor{##ddd7ff}{#1}"), Br("\\purpleB", "\\textcolor{##c6b9fc}{#1}"), Br("\\purpleC", "\\textcolor{##aa87ff}{#1}"), Br("\\purpleD", "\\textcolor{##7854ab}{#1}"), Br("\\purpleE", "\\textcolor{##543b78}{#1}"), Br("\\mintA", "\\textcolor{##f5f9e8}{#1}"), Br("\\mintB", "\\textcolor{##edf2df}{#1}"), Br("\\mintC", "\\textcolor{##e0e5cc}{#1}"), Br("\\grayA", "\\textcolor{##f6f7f7}{#1}"), Br("\\grayB", "\\textcolor{##f0f1f2}{#1}"), Br("\\grayC", "\\textcolor{##e3e5e6}{#1}"), Br("\\grayD", "\\textcolor{##d6d8da}{#1}"), Br("\\grayE", "\\textcolor{##babec2}{#1}"), Br("\\grayF", "\\textcolor{##888d93}{#1}"), Br("\\grayG", "\\textcolor{##626569}{#1}"), Br("\\grayH", "\\textcolor{##3b3e40}{#1}"), Br("\\grayI", "\\textcolor{##21242c}{#1}"), Br("\\kaBlue", "\\textcolor{##314453}{#1}"), Br("\\kaGreen", "\\textcolor{##71B307}{#1}"); const Rn = { "^": !0, _: !0, "\\limits": !0, "\\nolimits": !0 }; class Hn { constructor(e, t, r) { this.settings = void 0, this.expansionCount = void 0, this.lexer = void 0, this.macros = void 0, this.stack = void 0, this.mode = void 0, this.settings = t, this.expansionCount = 0, this.feed(e), this.macros = new zn(An, t.macros), this.mode = r, this.stack = [] } feed(e) { this.lexer = new Mn(e, this.settings) } switchMode(e) { this.mode = e } beginGroup() { this.macros.beginGroup() } endGroup() { this.macros.endGroup() } endGroups() { this.macros.endGroups() } future() { return 0 === this.stack.length && this.pushToken(this.lexer.lex()), this.stack[this.stack.length - 1] } popToken() { return this.future(), this.stack.pop() } pushToken(e) { this.stack.push(e) } pushTokens(e) { this.stack.push(...e) } scanArgument(e) { let t, r, n; if (e) { if (this.consumeSpaces(), "[" !== this.future().text) return null; t = this.popToken(), ({ tokens: n, end: r } = this.consumeArg(["]"])) } else ({ tokens: n, start: t, end: r } = this.consumeArg()); return this.pushToken(new Nr("EOF", r.loc)), this.pushTokens(n), t.range(r, "") } consumeSpaces() { for (; ;) { if (" " !== this.future().text) break; this.stack.pop() } } consumeArg(e) { const t = [], r = e && e.length > 0; r || this.consumeSpaces(); const o = this.future(); let s, i = 0, a = 0; do { if (s = this.popToken(), t.push(s), "{" === s.text) ++i; else if ("}" === s.text) { if (--i, -1 === i) throw new n("Extra }", s) } else if ("EOF" === s.text) throw new n("Unexpected end of input in a macro argument, expected '" + (e && r ? e[a] : "}") + "'", s); if (e && r) if ((0 === i || 1 === i && "{" === e[a]) && s.text === e[a]) { if (++a, a === e.length) { t.splice(-a, a); break } } else a = 0 } while (0 !== i || r); return "{" === o.text && "}" === t[t.length - 1].text && (t.pop(), t.shift()), t.reverse(), { tokens: t, start: o, end: s } } consumeArgs(e, t) { if (t) { if (t.length !== e + 1) throw new n("The length of delimiters doesn't match the number of args!"); const r = t[0]; for (let e = 0; e < r.length; e++) { const t = this.popToken(); if (r[e] !== t.text) throw new n("Use of the macro doesn't match its definition", t) } } const r = []; for (let n = 0; n < e; n++)r.push(this.consumeArg(t && t[n + 1]).tokens); return r } countExpansion(e) { if (this.expansionCount += e, this.expansionCount > this.settings.maxExpand) throw new n("Too many expansions: infinite loop or need to increase maxExpand setting") } expandOnce(e) { const t = this.popToken(), r = t.text, o = t.noexpand ? null : this._getExpansion(r); if (null == o || e && o.unexpandable) { if (e && null == o && "\\" === r[0] && !this.isDefined(r)) throw new n("Undefined control sequence: " + r); return this.pushToken(t), !1 } this.countExpansion(1); let s = o.tokens; const i = this.consumeArgs(o.numArgs, o.delimiters); if (o.numArgs) { s = s.slice(); for (let e = s.length - 1; e >= 0; --e) { let t = s[e]; if ("#" === t.text) { if (0 === e) throw new n("Incomplete placeholder at end of macro body", t); if (t = s[--e], "#" === t.text) s.splice(e + 1, 1); else { if (!/^[1-9]$/.test(t.text)) throw new n("Not a valid argument number", t); s.splice(e, 2, ...i[+t.text - 1]) } } } } return this.pushTokens(s), s.length } expandAfterFuture() { return this.expandOnce(), this.future() } expandNextToken() { for (; ;)if (!1 === this.expandOnce()) { const e = this.stack.pop(); return e.treatAsRelax && (e.text = "\\relax"), e } throw new Error } expandMacro(e) { return this.macros.has(e) ? this.expandTokens([new Nr(e)]) : void 0 } expandTokens(e) { const t = [], r = this.stack.length; for (this.pushTokens(e); this.stack.length > r;)if (!1 === this.expandOnce(!0)) { const e = this.stack.pop(); e.treatAsRelax && (e.noexpand = !1, e.treatAsRelax = !1), t.push(e) } return this.countExpansion(t.length), t } expandMacroAsText(e) { const t = this.expandMacro(e); return t ? t.map((e => e.text)).join("") : t } _getExpansion(e) { const t = this.macros.get(e); if (null == t) return t; if (1 === e.length) { const t = this.lexer.catcodes[e]; if (null != t && 13 !== t) return } const r = "function" == typeof t ? t(this) : t; if ("string" == typeof r) { let e = 0; if (-1 !== r.indexOf("#")) { const t = r.replace(/##/g, ""); for (; -1 !== t.indexOf("#" + (e + 1));)++e } const t = new Mn(r, this.settings), n = []; let o = t.lex(); for (; "EOF" !== o.text;)n.push(o), o = t.lex(); n.reverse(); return { tokens: n, numArgs: e } } return r } isDefined(e) { return this.macros.has(e) || yn.hasOwnProperty(e) || oe.math.hasOwnProperty(e) || oe.text.hasOwnProperty(e) || Rn.hasOwnProperty(e) } isExpandable(e) { const t = this.macros.get(e); return null != t ? "string" == typeof t || "function" == typeof t || !t.unexpandable : yn.hasOwnProperty(e) && !yn[e].primitive } } const On = /^[\u208a\u208b\u208c\u208d\u208e\u2080\u2081\u2082\u2083\u2084\u2085\u2086\u2087\u2088\u2089\u2090\u2091\u2095\u1d62\u2c7c\u2096\u2097\u2098\u2099\u2092\u209a\u1d63\u209b\u209c\u1d64\u1d65\u2093\u1d66\u1d67\u1d68\u1d69\u1d6a]/, En = Object.freeze({ "\u208a": "+", "\u208b": "-", "\u208c": "=", "\u208d": "(", "\u208e": ")", "\u2080": "0", "\u2081": "1", "\u2082": "2", "\u2083": "3", "\u2084": "4", "\u2085": "5", "\u2086": "6", "\u2087": "7", "\u2088": "8", "\u2089": "9", "\u2090": "a", "\u2091": "e", "\u2095": "h", "\u1d62": "i", "\u2c7c": "j", "\u2096": "k", "\u2097": "l", "\u2098": "m", "\u2099": "n", "\u2092": "o", "\u209a": "p", "\u1d63": "r", "\u209b": "s", "\u209c": "t", "\u1d64": "u", "\u1d65": "v", "\u2093": "x", "\u1d66": "\u03b2", "\u1d67": "\u03b3", "\u1d68": "\u03c1", "\u1d69": "\u03d5", "\u1d6a": "\u03c7", "\u207a": "+", "\u207b": "-", "\u207c": "=", "\u207d": "(", "\u207e": ")", "\u2070": "0", "\xb9": "1", "\xb2": "2", "\xb3": "3", "\u2074": "4", "\u2075": "5", "\u2076": "6", "\u2077": "7", "\u2078": "8", "\u2079": "9", "\u1d2c": "A", "\u1d2e": "B", "\u1d30": "D", "\u1d31": "E", "\u1d33": "G", "\u1d34": "H", "\u1d35": "I", "\u1d36": "J", "\u1d37": "K", "\u1d38": "L", "\u1d39": "M", "\u1d3a": "N", "\u1d3c": "O", "\u1d3e": "P", "\u1d3f": "R", "\u1d40": "T", "\u1d41": "U", "\u2c7d": "V", "\u1d42": "W", "\u1d43": "a", "\u1d47": "b", "\u1d9c": "c", "\u1d48": "d", "\u1d49": "e", "\u1da0": "f", "\u1d4d": "g", "\u02b0": "h", "\u2071": "i", "\u02b2": "j", "\u1d4f": "k", "\u02e1": "l", "\u1d50": "m", "\u207f": "n", "\u1d52": "o", "\u1d56": "p", "\u02b3": "r", "\u02e2": "s", "\u1d57": "t", "\u1d58": "u", "\u1d5b": "v", "\u02b7": "w", "\u02e3": "x", "\u02b8": "y", "\u1dbb": "z", "\u1d5d": "\u03b2", "\u1d5e": "\u03b3", "\u1d5f": "\u03b4", "\u1d60": "\u03d5", "\u1d61": "\u03c7", "\u1dbf": "\u03b8" }), Ln = { "\u0301": { text: "\\'", math: "\\acute" }, "\u0300": { text: "\\`", math: "\\grave" }, "\u0308": { text: '\\"', math: "\\ddot" }, "\u0303": { text: "\\~", math: "\\tilde" }, "\u0304": { text: "\\=", math: "\\bar" }, "\u0306": { text: "\\u", math: "\\breve" }, "\u030c": { text: "\\v", math: "\\check" }, "\u0302": { text: "\\^", math: "\\hat" }, "\u0307": { text: "\\.", math: "\\dot" }, "\u030a": { text: "\\r", math: "\\mathring" }, "\u030b": { text: "\\H" }, "\u0327": { text: "\\c" } }, Dn = { "\xe1": "a\u0301", "\xe0": "a\u0300", "\xe4": "a\u0308", "\u01df": "a\u0308\u0304", "\xe3": "a\u0303", "\u0101": "a\u0304", "\u0103": "a\u0306", "\u1eaf": "a\u0306\u0301", "\u1eb1": "a\u0306\u0300", "\u1eb5": "a\u0306\u0303", "\u01ce": "a\u030c", "\xe2": "a\u0302", "\u1ea5": "a\u0302\u0301", "\u1ea7": "a\u0302\u0300", "\u1eab": "a\u0302\u0303", "\u0227": "a\u0307", "\u01e1": "a\u0307\u0304", "\xe5": "a\u030a", "\u01fb": "a\u030a\u0301", "\u1e03": "b\u0307", "\u0107": "c\u0301", "\u1e09": "c\u0327\u0301", "\u010d": "c\u030c", "\u0109": "c\u0302", "\u010b": "c\u0307", "\xe7": "c\u0327", "\u010f": "d\u030c", "\u1e0b": "d\u0307", "\u1e11": "d\u0327", "\xe9": "e\u0301", "\xe8": "e\u0300", "\xeb": "e\u0308", "\u1ebd": "e\u0303", "\u0113": "e\u0304", "\u1e17": "e\u0304\u0301", "\u1e15": "e\u0304\u0300", "\u0115": "e\u0306", "\u1e1d": "e\u0327\u0306", "\u011b": "e\u030c", "\xea": "e\u0302", "\u1ebf": "e\u0302\u0301", "\u1ec1": "e\u0302\u0300", "\u1ec5": "e\u0302\u0303", "\u0117": "e\u0307", "\u0229": "e\u0327", "\u1e1f": "f\u0307", "\u01f5": "g\u0301", "\u1e21": "g\u0304", "\u011f": "g\u0306", "\u01e7": "g\u030c", "\u011d": "g\u0302", "\u0121": "g\u0307", "\u0123": "g\u0327", "\u1e27": "h\u0308", "\u021f": "h\u030c", "\u0125": "h\u0302", "\u1e23": "h\u0307", "\u1e29": "h\u0327", "\xed": "i\u0301", "\xec": "i\u0300", "\xef": "i\u0308", "\u1e2f": "i\u0308\u0301", "\u0129": "i\u0303", "\u012b": "i\u0304", "\u012d": "i\u0306", "\u01d0": "i\u030c", "\xee": "i\u0302", "\u01f0": "j\u030c", "\u0135": "j\u0302", "\u1e31": "k\u0301", "\u01e9": "k\u030c", "\u0137": "k\u0327", "\u013a": "l\u0301", "\u013e": "l\u030c", "\u013c": "l\u0327", "\u1e3f": "m\u0301", "\u1e41": "m\u0307", "\u0144": "n\u0301", "\u01f9": "n\u0300", "\xf1": "n\u0303", "\u0148": "n\u030c", "\u1e45": "n\u0307", "\u0146": "n\u0327", "\xf3": "o\u0301", "\xf2": "o\u0300", "\xf6": "o\u0308", "\u022b": "o\u0308\u0304", "\xf5": "o\u0303", "\u1e4d": "o\u0303\u0301", "\u1e4f": "o\u0303\u0308", "\u022d": "o\u0303\u0304", "\u014d": "o\u0304", "\u1e53": "o\u0304\u0301", "\u1e51": "o\u0304\u0300", "\u014f": "o\u0306", "\u01d2": "o\u030c", "\xf4": "o\u0302", "\u1ed1": "o\u0302\u0301", "\u1ed3": "o\u0302\u0300", "\u1ed7": "o\u0302\u0303", "\u022f": "o\u0307", "\u0231": "o\u0307\u0304", "\u0151": "o\u030b", "\u1e55": "p\u0301", "\u1e57": "p\u0307", "\u0155": "r\u0301", "\u0159": "r\u030c", "\u1e59": "r\u0307", "\u0157": "r\u0327", "\u015b": "s\u0301", "\u1e65": "s\u0301\u0307", "\u0161": "s\u030c", "\u1e67": "s\u030c\u0307", "\u015d": "s\u0302", "\u1e61": "s\u0307", "\u015f": "s\u0327", "\u1e97": "t\u0308", "\u0165": "t\u030c", "\u1e6b": "t\u0307", "\u0163": "t\u0327", "\xfa": "u\u0301", "\xf9": "u\u0300", "\xfc": "u\u0308", "\u01d8": "u\u0308\u0301", "\u01dc": "u\u0308\u0300", "\u01d6": "u\u0308\u0304", "\u01da": "u\u0308\u030c", "\u0169": "u\u0303", "\u1e79": "u\u0303\u0301", "\u016b": "u\u0304", "\u1e7b": "u\u0304\u0308", "\u016d": "u\u0306", "\u01d4": "u\u030c", "\xfb": "u\u0302", "\u016f": "u\u030a", "\u0171": "u\u030b", "\u1e7d": "v\u0303", "\u1e83": "w\u0301", "\u1e81": "w\u0300", "\u1e85": "w\u0308", "\u0175": "w\u0302", "\u1e87": "w\u0307", "\u1e98": "w\u030a", "\u1e8d": "x\u0308", "\u1e8b": "x\u0307", "\xfd": "y\u0301", "\u1ef3": "y\u0300", "\xff": "y\u0308", "\u1ef9": "y\u0303", "\u0233": "y\u0304", "\u0177": "y\u0302", "\u1e8f": "y\u0307", "\u1e99": "y\u030a", "\u017a": "z\u0301", "\u017e": "z\u030c", "\u1e91": "z\u0302", "\u017c": "z\u0307", "\xc1": "A\u0301", "\xc0": "A\u0300", "\xc4": "A\u0308", "\u01de": "A\u0308\u0304", "\xc3": "A\u0303", "\u0100": "A\u0304", "\u0102": "A\u0306", "\u1eae": "A\u0306\u0301", "\u1eb0": "A\u0306\u0300", "\u1eb4": "A\u0306\u0303", "\u01cd": "A\u030c", "\xc2": "A\u0302", "\u1ea4": "A\u0302\u0301", "\u1ea6": "A\u0302\u0300", "\u1eaa": "A\u0302\u0303", "\u0226": "A\u0307", "\u01e0": "A\u0307\u0304", "\xc5": "A\u030a", "\u01fa": "A\u030a\u0301", "\u1e02": "B\u0307", "\u0106": "C\u0301", "\u1e08": "C\u0327\u0301", "\u010c": "C\u030c", "\u0108": "C\u0302", "\u010a": "C\u0307", "\xc7": "C\u0327", "\u010e": "D\u030c", "\u1e0a": "D\u0307", "\u1e10": "D\u0327", "\xc9": "E\u0301", "\xc8": "E\u0300", "\xcb": "E\u0308", "\u1ebc": "E\u0303", "\u0112": "E\u0304", "\u1e16": "E\u0304\u0301", "\u1e14": "E\u0304\u0300", "\u0114": "E\u0306", "\u1e1c": "E\u0327\u0306", "\u011a": "E\u030c", "\xca": "E\u0302", "\u1ebe": "E\u0302\u0301", "\u1ec0": "E\u0302\u0300", "\u1ec4": "E\u0302\u0303", "\u0116": "E\u0307", "\u0228": "E\u0327", "\u1e1e": "F\u0307", "\u01f4": "G\u0301", "\u1e20": "G\u0304", "\u011e": "G\u0306", "\u01e6": "G\u030c", "\u011c": "G\u0302", "\u0120": "G\u0307", "\u0122": "G\u0327", "\u1e26": "H\u0308", "\u021e": "H\u030c", "\u0124": "H\u0302", "\u1e22": "H\u0307", "\u1e28": "H\u0327", "\xcd": "I\u0301", "\xcc": "I\u0300", "\xcf": "I\u0308", "\u1e2e": "I\u0308\u0301", "\u0128": "I\u0303", "\u012a": "I\u0304", "\u012c": "I\u0306", "\u01cf": "I\u030c", "\xce": "I\u0302", "\u0130": "I\u0307", "\u0134": "J\u0302", "\u1e30": "K\u0301", "\u01e8": "K\u030c", "\u0136": "K\u0327", "\u0139": "L\u0301", "\u013d": "L\u030c", "\u013b": "L\u0327", "\u1e3e": "M\u0301", "\u1e40": "M\u0307", "\u0143": "N\u0301", "\u01f8": "N\u0300", "\xd1": "N\u0303", "\u0147": "N\u030c", "\u1e44": "N\u0307", "\u0145": "N\u0327", "\xd3": "O\u0301", "\xd2": "O\u0300", "\xd6": "O\u0308", "\u022a": "O\u0308\u0304", "\xd5": "O\u0303", "\u1e4c": "O\u0303\u0301", "\u1e4e": "O\u0303\u0308", "\u022c": "O\u0303\u0304", "\u014c": "O\u0304", "\u1e52": "O\u0304\u0301", "\u1e50": "O\u0304\u0300", "\u014e": "O\u0306", "\u01d1": "O\u030c", "\xd4": "O\u0302", "\u1ed0": "O\u0302\u0301", "\u1ed2": "O\u0302\u0300", "\u1ed6": "O\u0302\u0303", "\u022e": "O\u0307", "\u0230": "O\u0307\u0304", "\u0150": "O\u030b", "\u1e54": "P\u0301", "\u1e56": "P\u0307", "\u0154": "R\u0301", "\u0158": "R\u030c", "\u1e58": "R\u0307", "\u0156": "R\u0327", "\u015a": "S\u0301", "\u1e64": "S\u0301\u0307", "\u0160": "S\u030c", "\u1e66": "S\u030c\u0307", "\u015c": "S\u0302", "\u1e60": "S\u0307", "\u015e": "S\u0327", "\u0164": "T\u030c", "\u1e6a": "T\u0307", "\u0162": "T\u0327", "\xda": "U\u0301", "\xd9": "U\u0300", "\xdc": "U\u0308", "\u01d7": "U\u0308\u0301", "\u01db": "U\u0308\u0300", "\u01d5": "U\u0308\u0304", "\u01d9": "U\u0308\u030c", "\u0168": "U\u0303", "\u1e78": "U\u0303\u0301", "\u016a": "U\u0304", "\u1e7a": "U\u0304\u0308", "\u016c": "U\u0306", "\u01d3": "U\u030c", "\xdb": "U\u0302", "\u016e": "U\u030a", "\u0170": "U\u030b", "\u1e7c": "V\u0303", "\u1e82": "W\u0301", "\u1e80": "W\u0300", "\u1e84": "W\u0308", "\u0174": "W\u0302", "\u1e86": "W\u0307", "\u1e8c": "X\u0308", "\u1e8a": "X\u0307", "\xdd": "Y\u0301", "\u1ef2": "Y\u0300", "\u0178": "Y\u0308", "\u1ef8": "Y\u0303", "\u0232": "Y\u0304", "\u0176": "Y\u0302", "\u1e8e": "Y\u0307", "\u0179": "Z\u0301", "\u017d": "Z\u030c", "\u1e90": "Z\u0302", "\u017b": "Z\u0307", "\u03ac": "\u03b1\u0301", "\u1f70": "\u03b1\u0300", "\u1fb1": "\u03b1\u0304", "\u1fb0": "\u03b1\u0306", "\u03ad": "\u03b5\u0301", "\u1f72": "\u03b5\u0300", "\u03ae": "\u03b7\u0301", "\u1f74": "\u03b7\u0300", "\u03af": "\u03b9\u0301", "\u1f76": "\u03b9\u0300", "\u03ca": "\u03b9\u0308", "\u0390": "\u03b9\u0308\u0301", "\u1fd2": "\u03b9\u0308\u0300", "\u1fd1": "\u03b9\u0304", "\u1fd0": "\u03b9\u0306", "\u03cc": "\u03bf\u0301", "\u1f78": "\u03bf\u0300", "\u03cd": "\u03c5\u0301", "\u1f7a": "\u03c5\u0300", "\u03cb": "\u03c5\u0308", "\u03b0": "\u03c5\u0308\u0301", "\u1fe2": "\u03c5\u0308\u0300", "\u1fe1": "\u03c5\u0304", "\u1fe0": "\u03c5\u0306", "\u03ce": "\u03c9\u0301", "\u1f7c": "\u03c9\u0300", "\u038e": "\u03a5\u0301", "\u1fea": "\u03a5\u0300", "\u03ab": "\u03a5\u0308", "\u1fe9": "\u03a5\u0304", "\u1fe8": "\u03a5\u0306", "\u038f": "\u03a9\u0301", "\u1ffa": "\u03a9\u0300" }; class Vn { constructor(e, t) { this.mode = void 0, this.gullet = void 0, this.settings = void 0, this.leftrightDepth = void 0, this.nextToken = void 0, this.mode = "math", this.gullet = new Hn(e, t, this.mode), this.settings = t, this.leftrightDepth = 0 } expect(e, t) { if (void 0 === t && (t = !0), this.fetch().text !== e) throw new n("Expected '" + e + "', got '" + this.fetch().text + "'", this.fetch()); t && this.consume() } consume() { this.nextToken = null } fetch() { return null == this.nextToken && (this.nextToken = this.gullet.expandNextToken()), this.nextToken } switchMode(e) { this.mode = e, this.gullet.switchMode(e) } parse() { this.settings.globalGroup || this.gullet.beginGroup(), this.settings.colorIsTextColor && this.gullet.macros.set("\\color", "\\textcolor"); try { const e = this.parseExpression(!1); return this.expect("EOF"), this.settings.globalGroup || this.gullet.endGroup(), e } finally { this.gullet.endGroups() } } subparse(e) { const t = this.nextToken; this.consume(), this.gullet.pushToken(new Nr("}")), this.gullet.pushTokens(e); const r = this.parseExpression(!1); return this.expect("}"), this.nextToken = t, r } parseExpression(e, t) { const r = []; for (; ;) { "math" === this.mode && this.consumeSpaces(); const n = this.fetch(); if (-1 !== Vn.endOfExpression.indexOf(n.text)) break; if (t && n.text === t) break; if (e && yn[n.text] && yn[n.text].infix) break; const o = this.parseAtom(t); if (!o) break; "internal" !== o.type && r.push(o) } return "text" === this.mode && this.formLigatures(r), this.handleInfixNodes(r) } handleInfixNodes(e) { let t, r = -1; for (let o = 0; o < e.length; o++)if ("infix" === e[o].type) { if (-1 !== r) throw new n("only one infix operator per group", e[o].token); r = o, t = e[o].replaceWith } if (-1 !== r && t) { let n, o; const s = e.slice(0, r), i = e.slice(r + 1); let a; return n = 1 === s.length && "ordgroup" === s[0].type ? s[0] : { type: "ordgroup", mode: this.mode, body: s }, o = 1 === i.length && "ordgroup" === i[0].type ? i[0] : { type: "ordgroup", mode: this.mode, body: i }, a = "\\\\abovefrac" === t ? this.callFunction(t, [n, e[r], o], []) : this.callFunction(t, [n, o], []), [a] } return e } handleSupSubscript(e) { const t = this.fetch(), r = t.text; this.consume(), this.consumeSpaces(); const o = this.parseGroup(e); if (!o) throw new n("Expected group after '" + r + "'", t); return o } formatUnsupportedCmd(e) { const t = []; for (let r = 0; r < e.length; r++)t.push({ type: "textord", mode: "text", text: e[r] }); const r = { type: "text", mode: this.mode, body: t }; return { type: "color", mode: this.mode, color: this.settings.errorColor, body: [r] } } parseAtom(e) { const t = this.parseGroup("atom", e); if ("text" === this.mode) return t; let r, o; for (; ;) { this.consumeSpaces(); const e = this.fetch(); if ("\\limits" === e.text || "\\nolimits" === e.text) { if (t && "op" === t.type) { const r = "\\limits" === e.text; t.limits = r, t.alwaysHandleSupSub = !0 } else { if (!t || "operatorname" !== t.type) throw new n("Limit controls must follow a math operator", e); t.alwaysHandleSupSub && (t.limits = "\\limits" === e.text) } this.consume() } else if ("^" === e.text) { if (r) throw new n("Double superscript", e); r = this.handleSupSubscript("superscript") } else if ("_" === e.text) { if (o) throw new n("Double subscript", e); o = this.handleSupSubscript("subscript") } else if ("'" === e.text) { if (r) throw new n("Double superscript", e); const t = { type: "textord", mode: this.mode, text: "\\prime" }, o = [t]; for (this.consume(); "'" === this.fetch().text;)o.push(t), this.consume(); "^" === this.fetch().text && o.push(this.handleSupSubscript("superscript")), r = { type: "ordgroup", mode: this.mode, body: o } } else { if (!En[e.text]) break; { const t = On.test(e.text), n = []; for (n.push(new Nr(En[e.text])), this.consume(); ;) { const e = this.fetch().text; if (!En[e]) break; if (On.test(e) !== t) break; n.unshift(new Nr(En[e])), this.consume() } const s = this.subparse(n); t ? o = { type: "ordgroup", mode: "math", body: s } : r = { type: "ordgroup", mode: "math", body: s } } } } return r || o ? { type: "supsub", mode: this.mode, base: t, sup: r, sub: o } : t } parseFunction(e, t) { const r = this.fetch(), o = r.text, s = yn[o]; if (!s) return null; if (this.consume(), t && "atom" !== t && !s.allowedInArgument) throw new n("Got function '" + o + "' with no arguments" + (t ? " as " + t : ""), r); if ("text" === this.mode && !s.allowedInText) throw new n("Can't use function '" + o + "' in text mode", r); if ("math" === this.mode && !1 === s.allowedInMath) throw new n("Can't use function '" + o + "' in math mode", r); const { args: i, optArgs: a } = this.parseArguments(o, s); return this.callFunction(o, i, a, r, e) } callFunction(e, t, r, o, s) { const i = { funcName: e, parser: this, token: o, breakOnTokenText: s }, a = yn[e]; if (a && a.handler) return a.handler(i, t, r); throw new n("No function handler for " + e) } parseArguments(e, t) { const r = t.numArgs + t.numOptionalArgs; if (0 === r) return { args: [], optArgs: [] }; const o = [], s = []; for (let i = 0; i < r; i++) { let r = t.argTypes && t.argTypes[i]; const a = i < t.numOptionalArgs; (t.primitive && null == r || "sqrt" === t.type && 1 === i && null == s[0]) && (r = "primitive"); const l = this.parseGroupOfType("argument to '" + e + "'", r, a); if (a) s.push(l); else { if (null == l) throw new n("Null argument, please report this as a bug"); o.push(l) } } return { args: o, optArgs: s } } parseGroupOfType(e, t, r) { switch (t) { case "color": return this.parseColorGroup(r); case "size": return this.parseSizeGroup(r); case "url": return this.parseUrlGroup(r); case "math": case "text": return this.parseArgumentGroup(r, t); case "hbox": { const e = this.parseArgumentGroup(r, "text"); return null != e ? { type: "styling", mode: e.mode, body: [e], style: "text" } : null } case "raw": { const e = this.parseStringGroup("raw", r); return null != e ? { type: "raw", mode: "text", string: e.text } : null } case "primitive": { if (r) throw new n("A primitive argument cannot be optional"); const t = this.parseGroup(e); if (null == t) throw new n("Expected group as " + e, this.fetch()); return t } case "original": case null: case void 0: return this.parseArgumentGroup(r); default: throw new n("Unknown group type as " + e, this.fetch()) } } consumeSpaces() { for (; " " === this.fetch().text;)this.consume() } parseStringGroup(e, t) { const r = this.gullet.scanArgument(t); if (null == r) return null; let n, o = ""; for (; "EOF" !== (n = this.fetch()).text;)o += n.text, this.consume(); return this.consume(), r.text = o, r } parseRegexGroup(e, t) { const r = this.fetch(); let o, s = r, i = ""; for (; "EOF" !== (o = this.fetch()).text && e.test(i + o.text);)s = o, i += s.text, this.consume(); if ("" === i) throw new n("Invalid " + t + ": '" + r.text + "'", r); return r.range(s, i) } parseColorGroup(e) { const t = this.parseStringGroup("color", e); if (null == t) return null; const r = /^(#[a-f0-9]{3}|#?[a-f0-9]{6}|[a-z]+)$/i.exec(t.text); if (!r) throw new n("Invalid color: '" + t.text + "'", t); let o = r[0]; return /^[0-9a-f]{6}$/i.test(o) && (o = "#" + o), { type: "color-token", mode: this.mode, color: o } } parseSizeGroup(e) { let t, r = !1; if (this.gullet.consumeSpaces(), t = e || "{" === this.gullet.future().text ? this.parseStringGroup("size", e) : this.parseRegexGroup(/^[-+]? *(?:$|\d+|\d+\.\d*|\.\d*) *[a-z]{0,2} *$/, "size"), !t) return null; e || 0 !== t.text.length || (t.text = "0pt", r = !0); const o = /([-+]?) *(\d+(?:\.\d*)?|\.\d+) *([a-z]{2})/.exec(t.text); if (!o) throw new n("Invalid size: '" + t.text + "'", t); const s = { number: +(o[1] + o[2]), unit: o[3] }; if (!V(s)) throw new n("Invalid unit: '" + s.unit + "'", t); return { type: "size", mode: this.mode, value: s, isBlank: r } } parseUrlGroup(e) { this.gullet.lexer.setCatcode("%", 13), this.gullet.lexer.setCatcode("~", 12); const t = this.parseStringGroup("url", e); if (this.gullet.lexer.setCatcode("%", 14), this.gullet.lexer.setCatcode("~", 13), null == t) return null; const r = t.text.replace(/\\([#$%&~_^{}])/g, "$1"); return { type: "url", mode: this.mode, url: r } } parseArgumentGroup(e, t) { const r = this.gullet.scanArgument(e); if (null == r) return null; const n = this.mode; t && this.switchMode(t), this.gullet.beginGroup(); const o = this.parseExpression(!1, "EOF"); this.expect("EOF"), this.gullet.endGroup(); const s = { type: "ordgroup", mode: this.mode, loc: r.loc, body: o }; return t && this.switchMode(n), s } parseGroup(e, t) { const r = this.fetch(), o = r.text; let s; if ("{" === o || "\\begingroup" === o) { this.consume(); const e = "{" === o ? "}" : "\\endgroup"; this.gullet.beginGroup(); const t = this.parseExpression(!1, e), n = this.fetch(); this.expect(e), this.gullet.endGroup(), s = { type: "ordgroup", mode: this.mode, loc: Cr.range(r, n), body: t, semisimple: "\\begingroup" === o || void 0 } } else if (s = this.parseFunction(t, e) || this.parseSymbol(), null == s && "\\" === o[0] && !Rn.hasOwnProperty(o)) { if (this.settings.throwOnError) throw new n("Undefined control sequence: " + o, r); s = this.formatUnsupportedCmd(o), this.consume() } return s } formLigatures(e) { let t = e.length - 1; for (let r = 0; r < t; ++r) { const n = e[r], o = n.text; "-" === o && "-" === e[r + 1].text && (r + 1 < t && "-" === e[r + 2].text ? (e.splice(r, 3, { type: "textord", mode: "text", loc: Cr.range(n, e[r + 2]), text: "---" }), t -= 2) : (e.splice(r, 2, { type: "textord", mode: "text", loc: Cr.range(n, e[r + 1]), text: "--" }), t -= 1)), "'" !== o && "`" !== o || e[r + 1].text !== o || (e.splice(r, 2, { type: "textord", mode: "text", loc: Cr.range(n, e[r + 1]), text: o + o }), t -= 1) } } parseSymbol() { const e = this.fetch(); let t = e.text; if (/^\\verb[^a-zA-Z]/.test(t)) { this.consume(); let e = t.slice(5); const r = "*" === e.charAt(0); if (r && (e = e.slice(1)), e.length < 2 || e.charAt(0) !== e.slice(-1)) throw new n("\\verb assertion failed --\n please report what input caused this bug"); return e = e.slice(1, -1), { type: "verb", mode: "text", body: e, star: r } } Dn.hasOwnProperty(t[0]) && !oe[this.mode][t[0]] && (this.settings.strict && "math" === this.mode && this.settings.reportNonstrict("unicodeTextInMathMode", 'Accented Unicode text character "' + t[0] + '" used in math mode', e), t = Dn[t[0]] + t.slice(1)); const r = kn.exec(t); let o; if (r && (t = t.substring(0, r.index), "i" === t ? t = "\u0131" : "j" === t && (t = "\u0237")), oe[this.mode][t]) { this.settings.strict && "math" === this.mode && Ae.indexOf(t) >= 0 && this.settings.reportNonstrict("unicodeTextInMathMode", 'Latin-1/Unicode text character "' + t[0] + '" used in math mode', e); const r = oe[this.mode][t].group, n = Cr.range(e); let s; if (te.hasOwnProperty(r)) { const e = r; s = { type: "atom", mode: this.mode, family: e, loc: n, text: t } } else s = { type: r, mode: this.mode, loc: n, text: t }; o = s } else { if (!(t.charCodeAt(0) >= 128)) return null; this.settings.strict && (S(t.charCodeAt(0)) ? "math" === this.mode && this.settings.reportNonstrict("unicodeTextInMathMode", 'Unicode text character "' + t[0] + '" used in math mode', e) : this.settings.reportNonstrict("unknownSymbol", 'Unrecognized Unicode character "' + t[0] + '" (' + t.charCodeAt(0) + ")", e)), o = { type: "textord", mode: "text", loc: Cr.range(e), text: t } } if (this.consume(), r) for (let t = 0; t < r[0].length; t++) { const s = r[0][t]; if (!Ln[s]) throw new n("Unknown accent ' " + s + "'", e); const i = Ln[s][this.mode] || Ln[s].text; if (!i) throw new n("Accent " + s + " unsupported in " + this.mode + " mode", e); o = { type: "accent", mode: this.mode, loc: Cr.range(e), label: i, isStretchy: !1, isShifty: !0, base: o } } return o } } Vn.endOfExpression = ["}", "\\endgroup", "\\end", "\\right", "&"]; var Pn = function (e, t) { if (!("string" == typeof e || e instanceof String)) throw new TypeError("KaTeX can only parse string typed expression"); const r = new Vn(e, t); delete r.gullet.macros.current["\\df@tag"]; let o = r.parse(); if (delete r.gullet.macros.current["\\current@color"], delete r.gullet.macros.current["\\color"], r.gullet.macros.get("\\df@tag")) { if (!t.displayMode) throw new n("\\tag works only in display equations"); o = [{ type: "tag", mode: "text", body: o, tag: r.subparse([new Nr("\\df@tag")]) }] } return o }; let Fn = function (e, t, r) { t.textContent = ""; const n = Un(e, r).toNode(); t.appendChild(n) }; "undefined" != typeof document && "CSS1Compat" !== document.compatMode && ("undefined" != typeof console && console.warn("Warning: KaTeX doesn't work in quirks mode. Make sure your website has a suitable doctype."), Fn = function () { throw new n("KaTeX doesn't work in quirks mode.") }); const Gn = function (e, t, r) { if (r.throwOnError || !(e instanceof n)) throw e; const o = Ve.makeSpan(["katex-error"], [new Z(t)]); return o.setAttribute("title", e.toString()), o.setAttribute("style", "color:" + r.errorColor), o }, Un = function (e, t) { const r = new m(t); try { const t = Pn(e, r); return zt(t, e, r) } catch (t) { return Gn(t, e, r) } }; var Yn = { version: "0.16.11", render: Fn, renderToString: function (e, t) { return Un(e, t).toMarkup() }, ParseError: n, SETTINGS_SCHEMA: h, __parse: function (e, t) { const r = new m(t); return Pn(e, r) }, __renderToDomTree: Un, __renderToHTMLTree: function (e, t) { const r = new m(t); try { return function (e, t, r) { const n = mt(e, St(r)), o = Ve.makeSpan(["katex"], [n]); return Mt(o, r) }(Pn(e, r), 0, r) } catch (t) { return Gn(t, e, r) } }, __setFontMetrics: function (e, t) { T[e] = t }, __defineSymbol: se, __defineFunction: je, __defineMacro: Br, __domTree: { Span: W, Anchor: _, SymbolNode: Z, SvgNode: K, PathNode: J, LineNode: Q } }; return t = t.default }() })); diff --git a/docs/ppocr/infer_deploy/cpp_infer.en.md b/docs/ppocr/infer_deploy/cpp_infer.en.md index fa63d38..691523c 100644 --- a/docs/ppocr/infer_deploy/cpp_infer.en.md +++ b/docs/ppocr/infer_deploy/cpp_infer.en.md @@ -378,7 +378,7 @@ predict Crop_img: ../../doc/imgs/12.jpg 1 det boxes: [[23,507],[513,488],[515,529],[24,548]] rec text: 绿洲仕格维花园公寓 rec score: 0.993728 2 det boxes: [[187,456],[399,448],[400,480],[188,488]] rec text: 打浦路15号 rec score: 0.964994 3 det boxes: [[42,413],[483,391],[484,428],[43,450]] rec text: 上海斯格威铂尔大酒店 rec score: 0.980086 -The detection visualized image saved in ./output//12.jpg +The detection visualized image saved in ./json//12.jpg ``` - layout+table @@ -417,9 +417,9 @@ predict Crop_img: ../../ppstructure/docs/table/1.png 0 det boxes: [[6,2],[113,2],[113,14],[6,14]] rec text: 5.Conclusion rec score: 0.856903 ********** end print ocr result ********** 6 type: table, region: [14,360,402,711], score: 0.963643, res:
MethodsExtRPFFPS
TextSnake [18]Syn85.367.975.6
CSE [17]MiLT76.178.777.40.38
LOMO[40]Syn76.585.780.84.4
ATRR[35]Sy-80.280.180.1-
SegLink++ [28]Syn79.882.881.3-
TextField [37]Syn79.883.081.46.0
MSR[38]Syn79.084.181.54.3
PSENet-1s [33]MLT79.784.882.23.9
DB [12]Syn80.286.983.422.0
CRAFT [2]Syn81.186.083.5-
TextDragon [5]MLT+82.884.583.6
PAN [34]Syn81.286.483.739.8
ContourNet [36]84.183.783.94.5
DRRG [41]MLT83.0285.9384.45-
TextPerception[23]Syn81.987.584.6
Ours Syn80.5787.6683.9712.08
Ours81.4587.8184.5112.15
OursMLT83.6086.4585.0012.21
-The table visualized image saved in ./output//6_1.png +The table visualized image saved in ./json//6_1.png 7 type: table, region: [462,359,820,657], score: 0.953917, res:
MethodsRPFFPS
SegLink [26]70.086.077.08.9
PixelLink [4]73.283.077.8-
TextSnake [18]73.983.278.31.1
TextField [37]75.987.481.35.2
MSR[38]76.787.481.7-
FTSN[3]77.187.682.0:
LSE[30]81.784.282.9
CRAFT [2]78.288.282.98.6
MCN [16]798883-
ATRR[35]82.185.283.6-
PAN [34]83.884.484.130.2
DB[12]79.291.584.932.0
DRRG [41]82.3088.0585.08-
Ours (SynText)80.6885.4082.9712.68
Ours (MLT-17)84.5486.6285.5712.31
-The table visualized image saved in ./output//7_1.png +The table visualized image saved in ./json//7_1.png 8 type: figure, region: [14,3,836,310], score: 0.969443, res: count of ocr result is : 26 ********** print ocr result ********** 0 det boxes: [[506,14],[539,15],[539,22],[506,21]] rec text: E rec score: 0.318073 diff --git a/docs/ppocr/infer_deploy/cpp_infer.md b/docs/ppocr/infer_deploy/cpp_infer.md index f025e2d..f673cdd 100644 --- a/docs/ppocr/infer_deploy/cpp_infer.md +++ b/docs/ppocr/infer_deploy/cpp_infer.md @@ -388,7 +388,7 @@ predict Crop_img: ../../doc/imgs/12.jpg 1 det boxes: [[23,507],[513,488],[515,529],[24,548]] rec text: 绿洲仕格维花园公寓 rec score: 0.993728 2 det boxes: [[187,456],[399,448],[400,480],[188,488]] rec text: 打浦路15号 rec score: 0.964994 3 det boxes: [[42,413],[483,391],[484,428],[43,450]] rec text: 上海斯格威铂尔大酒店 rec score: 0.980086 -The detection visualized image saved in ./output//12.jpg +The detection visualized image saved in ./json//12.jpg ``` - layout+table @@ -427,9 +427,9 @@ predict Crop_img: ../../ppstructure/docs/table/1.png 0 det boxes: [[6,2],[113,2],[113,14],[6,14]] rec text: 5.Conclusion rec score: 0.856903 ********** end print ocr result ********** 6 type: table, region: [14,360,402,711], score: 0.963643, res:
MethodsExtRPFFPS
TextSnake [18]Syn85.367.975.6
CSE [17]MiLT76.178.777.40.38
LOMO[40]Syn76.585.780.84.4
ATRR[35]Sy-80.280.180.1-
SegLink++ [28]Syn79.882.881.3-
TextField [37]Syn79.883.081.46.0
MSR[38]Syn79.084.181.54.3
PSENet-1s [33]MLT79.784.882.23.9
DB [12]Syn80.286.983.422.0
CRAFT [2]Syn81.186.083.5-
TextDragon [5]MLT+82.884.583.6
PAN [34]Syn81.286.483.739.8
ContourNet [36]84.183.783.94.5
DRRG [41]MLT83.0285.9384.45-
TextPerception[23]Syn81.987.584.6
Ours Syn80.5787.6683.9712.08
Ours81.4587.8184.5112.15
OursMLT83.6086.4585.0012.21
-The table visualized image saved in ./output//6_1.png +The table visualized image saved in ./json//6_1.png 7 type: table, region: [462,359,820,657], score: 0.953917, res:
MethodsRPFFPS
SegLink [26]70.086.077.08.9
PixelLink [4]73.283.077.8-
TextSnake [18]73.983.278.31.1
TextField [37]75.987.481.35.2
MSR[38]76.787.481.7-
FTSN[3]77.187.682.0:
LSE[30]81.784.282.9
CRAFT [2]78.288.282.98.6
MCN [16]798883-
ATRR[35]82.185.283.6-
PAN [34]83.884.484.130.2
DB[12]79.291.584.932.0
DRRG [41]82.3088.0585.08-
Ours (SynText)80.6885.4082.9712.68
Ours (MLT-17)84.5486.6285.5712.31
-The table visualized image saved in ./output//7_1.png +The table visualized image saved in ./json//7_1.png 8 type: figure, region: [14,3,836,310], score: 0.969443, res: count of ocr result is : 26 ********** print ocr result ********** 0 det boxes: [[506,14],[539,15],[539,22],[506,21]] rec text: E rec score: 0.318073 diff --git a/docs/ppocr/infer_deploy/paddle_cloud.md b/docs/ppocr/infer_deploy/paddle_cloud.md index dada8bb..a60b13a 100644 --- a/docs/ppocr/infer_deploy/paddle_cloud.md +++ b/docs/ppocr/infer_deploy/paddle_cloud.md @@ -151,14 +151,14 @@ $ tar xf /home/PaddleOCR/pre_train/ch_PP-OCRv3_det_distill_train.tar -C /home/Pa ```bash linenums="1" # 这里以 GPU 训练为例,使用 CPU 进行训练的话,需要指定参数 Global.use_gpu=false -python3 tools/train.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml -o Global.save_model_dir=./output/ Global.pretrained_model=./pre_train/ch_PP-OCRv3_det_distill_train/best_accuracy +python3 tools/train.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml -o Global.save_model_dir=./json/ Global.pretrained_model=./pre_train/ch_PP-OCRv3_det_distill_train/best_accuracy ``` 如果要使用多GPU分布式训练,请使用如下命令: ```bash linenums="1" # 启动训练,训练模型默认保存在output目录下,--gpus '0,1,2,3'表示使用0,1,2,3号GPU训练 -python3 -m paddle.distributed.launch --log_dir=./debug/ --gpus '0,1,2,3' tools/train.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml -o Global.save_model_dir=./output/ Global.pretrained_model=./pre_train/ch_PP-OCRv3_det_distill_train/best_accuracy +python3 -m paddle.distributed.launch --log_dir=./debug/ --gpus '0,1,2,3' tools/train.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml -o Global.save_model_dir=./json/ Global.pretrained_model=./pre_train/ch_PP-OCRv3_det_distill_train/best_accuracy ``` ### 1.6 模型评估 @@ -180,7 +180,7 @@ latest.pdopt # 默认保存的最新模型的优化器相关参数 # 进行模型评估 cd /home/PaddleOCR/ -python3 tools/eval.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml -o Global.checkpoints=./output/best_accuracy +python3 tools/eval.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml -o Global.checkpoints=./json/best_accuracy ``` ## 2. PP-OCRv3云端部署 diff --git a/docs/ppocr/model_compress/knowledge_distillation.en.md b/docs/ppocr/model_compress/knowledge_distillation.en.md index 8b54e6f..36205f5 100644 --- a/docs/ppocr/model_compress/knowledge_distillation.en.md +++ b/docs/ppocr/model_compress/knowledge_distillation.en.md @@ -63,7 +63,7 @@ Architecture: Teacher: # The name of the subnet, it must include at least the `pretrained` and `freeze_params` parameters, and the other parameters are the construction parameters of the subnet pretrained: # Does this sub-network need to load pre-training weights freeze_params: false # Do you need fixed parameters - return_all_feats: true # Do you need to return all features, if it is False, only the final output is returned + return_all_feats: true # Do you need to return all features, if it is False, only the final json is returned model_type: *model_type # Model category algorithm: SVTR # The algorithm name of the sub-network. The remaining parameters of the sub-network are consistent with the general model training configuration Transform: @@ -241,8 +241,8 @@ Loss: loss_config_list: # List of loss function configuration files, mandatory functions for CombinedLoss - DistillationCTCLoss: # CTC loss function based on distillation, inherited from standard CTC loss weight: 1.0 # The weight of the loss function. In loss_config_list, each loss function must include this field - model_name_list: ["Student", "Teacher"] # For the prediction results of the distillation model, extract the output of these two sub-networks and calculate the CTC loss with gt - key: head_out # In the sub-network output dict, take the corresponding tensor + model_name_list: ["Student", "Teacher"] # For the prediction results of the distillation model, extract the json of these two sub-networks and calculate the CTC loss with gt + key: head_out # In the sub-network json dict, take the corresponding tensor - DistillationDMLLoss: # DML loss function, inherited from the standard DMLLoss weight: 1.0 act: "softmax" # Activation function, use it to process the input, can be softmax, sigmoid or None, the default is None @@ -269,8 +269,8 @@ Loss: key: backbone_out - DistillationSARLoss: # SAR loss function based on distillation, inherited from standard SAR loss weight: 1.0 # The weight of the loss function. In loss_config_list, each loss function must include this field - model_name_list: ["Student", "Teacher"] # For the prediction results of the distillation model, extract the output of these two sub-networks and calculate the SAR loss with gt - key: head_out # In the sub-network output dict, take the corresponding tensor + model_name_list: ["Student", "Teacher"] # For the prediction results of the distillation model, extract the json of these two sub-networks and calculate the SAR loss with gt + key: head_out # In the sub-network json dict, take the corresponding tensor multi_head: True # whether it is multi-head or not, if true, SAR branch is used to calculate the loss ``` @@ -297,7 +297,7 @@ In the knowledge distillation task, the post-processing configuration is as foll PostProcess: name: DistillationCTCLabelDecode # CTC decoding post-processing of distillation tasks, inherited from the standard CTCLabelDecode class model_name: ["Student", "Teacher"] # For the prediction results of the distillation model, extract the outputs of these two sub-networks and decode them - key: head_out # Take the corresponding tensor in the subnet output dict + key: head_out # Take the corresponding tensor in the subnet json dict multi_head: True # whether it is multi-head or not, if true, CTC branch is used to calculate the loss ``` @@ -313,7 +313,7 @@ In the knowledge distillation task, the metric calculation configuration is as f ```yaml linenums="1" Metric: name: DistillationMetric # CTC decoding post-processing of distillation tasks, inherited from the standard CTCLabelDecode class - base_metric_name: RecMetric # The base class of indicator calculation. For the output of the model, the indicator will be calculated based on this class + base_metric_name: RecMetric # The base class of indicator calculation. For the json of the model, the indicator will be calculated based on this class main_indicator: acc # The name of the indicator key: "Student" # Select the main_indicator of this subnet as the criterion for saving the best model ignore_space: False # whether to ignore space during evaulation @@ -375,7 +375,7 @@ Architecture: Student: # The name of the subnet, it must include at least the `pretrained` and `freeze_params` parameters, and the other parameters are the construction parameters of the subnet pretrained: ./pretrain_models/MobileNetV3_large_x0_5_pretrained # Does this sub-network need to load pre-training weights freeze_params: false # Do you need fixed parameters - return_all_feats: false # Do you need to return all features, if it is False, only the final output is returned + return_all_feats: false # Do you need to return all features, if it is False, only the final json is returned model_type: det algorithm: DB Backbone: @@ -547,7 +547,7 @@ In the task of detecting knowledge distillation, the post-processing configurati ```yaml linenums="1" PostProcess: name: DistillationDBPostProcess # The post-processing of the DB detection distillation task, inherited from the standard DBPostProcess class - model_name: ["Student", "Student2", "Teacher"] # Extract the output of multiple sub-networks and decode them. The network that does not require post-processing is not set in model_name + model_name: ["Student", "Student2", "Teacher"] # Extract the json of multiple sub-networks and decode them. The network that does not require post-processing is not set in model_name thresh: 0.3 box_thresh: 0.6 max_candidates: 1000 diff --git a/docs/ppocr/model_compress/prune.en.md b/docs/ppocr/model_compress/prune.en.md index 7579f34..b8f4672 100644 --- a/docs/ppocr/model_compress/prune.en.md +++ b/docs/ppocr/model_compress/prune.en.md @@ -58,7 +58,7 @@ The function would return a dict after loading the sensitivity file. The keys of Enter the PaddleOCR root directory,perform sensitivity analysis on the model with the following command: ```bash linenums="1" -python3.7 deploy/slim/prune/sensitivity_anal.py -c configs/det/ch_ppocr_v2.0/ch_det_mv3_db_v2.0.yml -o Global.pretrained_model="your trained model" Global.save_model_dir=./output/prune_model/ +python3.7 deploy/slim/prune/sensitivity_anal.py -c configs/det/ch_ppocr_v2.0/ch_det_mv3_db_v2.0.yml -o Global.pretrained_model="your trained model" Global.save_model_dir=./json/prune_model/ ``` ### 5. Export inference model and deploy it @@ -66,7 +66,7 @@ python3.7 deploy/slim/prune/sensitivity_anal.py -c configs/det/ch_ppocr_v2.0/ch_ We can export the pruned model as inference_model for deployment: ```bash linenums="1" -python deploy/slim/prune/export_prune_model.py -c configs/det/ch_ppocr_v2.0/ch_det_mv3_db_v2.0.yml -o Global.pretrained_model=./output/det_db/best_accuracy Global.save_inference_dir=./prune/prune_inference_model +python deploy/slim/prune/export_prune_model.py -c configs/det/ch_ppocr_v2.0/ch_det_mv3_db_v2.0.yml -o Global.pretrained_model=./json/det_db/best_accuracy Global.save_inference_dir=./prune/prune_inference_model ``` Reference for prediction and deployment of inference model: diff --git a/docs/ppocr/model_compress/prune.md b/docs/ppocr/model_compress/prune.md index ea3103b..3f270d3 100644 --- a/docs/ppocr/model_compress/prune.md +++ b/docs/ppocr/model_compress/prune.md @@ -54,7 +54,7 @@ sen.pickle(Dict){ 进入PaddleOCR根目录,通过以下命令对模型进行敏感度分析训练: ```bash linenums="1" -python3.7 deploy/slim/prune/sensitivity_anal.py -c configs/det/ch_ppocr_v2.0/ch_det_mv3_db_v2.0.yml -o Global.pretrained_model="your trained model" Global.save_model_dir=./output/prune_model/ +python3.7 deploy/slim/prune/sensitivity_anal.py -c configs/det/ch_ppocr_v2.0/ch_det_mv3_db_v2.0.yml -o Global.pretrained_model="your trained model" Global.save_model_dir=./json/prune_model/ ``` ### 4.导出模型、预测部署 @@ -62,7 +62,7 @@ python3.7 deploy/slim/prune/sensitivity_anal.py -c configs/det/ch_ppocr_v2.0/ch_ 在得到裁剪训练保存的模型后,我们可以将其导出为inference_model: ```bash linenums="1" -pytho3.7 deploy/slim/prune/export_prune_model.py -c configs/det/ch_ppocr_v2.0/ch_det_mv3_db_v2.0.yml -o Global.pretrained_model=./output/det_db/best_accuracy Global.save_inference_dir=./prune/prune_inference_model +pytho3.7 deploy/slim/prune/export_prune_model.py -c configs/det/ch_ppocr_v2.0/ch_det_mv3_db_v2.0.yml -o Global.pretrained_model=./json/det_db/best_accuracy Global.save_inference_dir=./prune/prune_inference_model ``` inference model的预测和部署参考: diff --git a/docs/ppocr/model_compress/quantization.en.md b/docs/ppocr/model_compress/quantization.en.md index 78163ce..249ebb0 100644 --- a/docs/ppocr/model_compress/quantization.en.md +++ b/docs/ppocr/model_compress/quantization.en.md @@ -50,7 +50,7 @@ The code for quantization training is located in `slim/quantization/quant.py`. F wget https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_distill_train.tar tar xf ch_PP-OCRv3_det_distill_train.tar -python deploy/slim/quantization/quant.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml -o Global.pretrained_model='./ch_PP-OCRv3_det_distill_train/best_accuracy' Global.save_model_dir=./output/quant_model_distill/ +python deploy/slim/quantization/quant.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml -o Global.pretrained_model='./ch_PP-OCRv3_det_distill_train/best_accuracy' Global.save_model_dir=./json/quant_model_distill/ ``` If you want to quantify the text recognition model, you can modify the configuration file and loaded model parameters. @@ -60,7 +60,7 @@ If you want to quantify the text recognition model, you can modify the configura Once we got the model after pruning and fine-tuning, we can export it as an inference model for the deployment of predictive tasks: ```bash linenums="1" -python deploy/slim/quantization/export_model.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml -o Global.checkpoints=output/quant_model/best_accuracy Global.save_inference_dir=./output/quant_inference_model +python deploy/slim/quantization/export_model.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml -o Global.checkpoints=json/quant_model/best_accuracy Global.save_inference_dir=./json/quant_inference_model ``` ### 5. Deploy diff --git a/docs/ppocr/model_compress/quantization.md b/docs/ppocr/model_compress/quantization.md index eb72cfb..9a32145 100644 --- a/docs/ppocr/model_compress/quantization.md +++ b/docs/ppocr/model_compress/quantization.md @@ -45,7 +45,7 @@ PaddleOCR提供了一系列训练好的[模型](../model_list.md),如果待量 wget https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_distill_train.tar tar xf ch_PP-OCRv3_det_distill_train.tar -python deploy/slim/quantization/quant.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml -o Global.pretrained_model='./ch_PP-OCRv3_det_distill_train/best_accuracy' Global.save_model_dir=./output/quant_model_distill/ +python deploy/slim/quantization/quant.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml -o Global.pretrained_model='./ch_PP-OCRv3_det_distill_train/best_accuracy' Global.save_model_dir=./json/quant_model_distill/ ``` 如果要训练识别模型的量化,修改配置文件和加载的模型参数即可。 @@ -55,7 +55,7 @@ python deploy/slim/quantization/quant.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_ 在得到量化训练保存的模型后,我们可以将其导出为inference_model,用于预测部署: ```bash linenums="1" -python deploy/slim/quantization/export_model.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml -o Global.checkpoints=output/quant_model/best_accuracy Global.save_inference_dir=./output/quant_inference_model +python deploy/slim/quantization/export_model.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml -o Global.checkpoints=json/quant_model/best_accuracy Global.save_inference_dir=./json/quant_inference_model ``` ### 5. 量化模型部署 diff --git a/docs/ppocr/model_train/PPOCRv3_det_train.en.md b/docs/ppocr/model_train/PPOCRv3_det_train.en.md index 836a612..74604d2 100644 --- a/docs/ppocr/model_train/PPOCRv3_det_train.en.md +++ b/docs/ppocr/model_train/PPOCRv3_det_train.en.md @@ -42,12 +42,12 @@ wget -P ./pretrain_models/ https://paddleocr.bj.bcebos.com/pretrained/ResNet50_v python3 tools/train.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_dml.yml \ -o Architecture.Models.Student.pretrained=./pretrain_models/ResNet50_vd_ssld_pretrained \ Architecture.Models.Student2.pretrained=./pretrain_models/ResNet50_vd_ssld_pretrained \ -Global.save_model_dir=./output/ +Global.save_model_dir=./json/ # If you want to use multi-GPU distributed training, please use the following command: python3 -m paddle.distributed.launch --gpus '0,1,2,3' tools/train.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_dml.yml \ -o Architecture.Models.Student.pretrained=./pretrain_models/ResNet50_vd_ssld_pretrained \ Architecture.Models.Student2.pretrained=./pretrain_models/ResNet50_vd_ssld_pretrained \ -Global.save_model_dir=./output/ +Global.save_model_dir=./json/ ``` The model saved during training is in the output directory, which contains the following files: @@ -66,7 +66,7 @@ Among them, best_accuracy is the model parameter with the highest accuracy saved The model evaluation command is as follows: ```bash linenums="1" -python3 tools/eval.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_dml.yml -o Global.checkpoints=./output/best_accuracy +python3 tools/eval.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_dml.yml -o Global.checkpoints=./json/best_accuracy ``` The trained teacher model has a larger structure and higher accuracy, which is used to improve the accuracy of the student model. @@ -110,20 +110,20 @@ python3 tools/train.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml \ -o Architecture.Models.Student.pretrained=./pretrain_models/MobileNetV3_large_x0_5_pretrained \ Architecture.Models.Student2.pretrained=./pretrain_models/MobileNetV3_large_x0_5_pretrained \ Architecture.Models.Teacher.pretrained=./pretrain_models/dml_teacher \ -Global.save_model_dir=./output/ +Global.save_model_dir=./json/ # If you want to use multi-GPU distributed training, please use the following command: python3 -m paddle.distributed.launch --gpus '0,1,2,3' tools/train.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml \ -o Architecture.Models.Student.pretrained=./pretrain_models/MobileNetV3_large_x0_5_pretrained \ Architecture.Models.Student2.pretrained=./pretrain_models/MobileNetV3_large_x0_5_pretrained \ Architecture.Models.Teacher.pretrained=./pretrain_models/dml_teacher \ -Global.save_model_dir=./output/ +Global.save_model_dir=./json/ ``` The model saved during the training process is in the output directory. The model evaluation command is as follows: ```bash linenums="1" -python3 tools/eval.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml -o Global.checkpoints=./output/best_accuracy +python3 tools/eval.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml -o Global.checkpoints=./json/best_accuracy ``` best_accuracy contains the parameters of three models, corresponding to Student, Student2, and Teacher in the configuration file. The method to extract Student parameters is as follows: @@ -173,11 +173,11 @@ Start training: # Single card training python3 tools/train.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml \ -o Global.pretrained_model=./ch_PP-OCRv3_det_distill_train/best_accuracy \ -Global.save_model_dir=./output/ +Global.save_model_dir=./json/ # If you want to use multi-GPU distributed training, please use the following command: python3 -m paddle.distributed.launch --gpus '0,1,2,3' tools/train.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml \ -o Global.pretrained_model=./ch_PP-OCRv3_det_distill_train/best_accuracy \ -Global.save_model_dir=./output/ +Global.save_model_dir=./json/ ``` **Finetune training based on PP-OCRv3 lightweight detection model** @@ -213,11 +213,11 @@ Train using the configuration file [ch_PP-OCRv3_det_student.yml](https://github. # Single card training python3 tools/train.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml \ -o Global.pretrained_model=./student \ -Global.save_model_dir=./output/ +Global.save_model_dir=./json/ # If you want to use multi-GPU distributed training, please use the following command: python3 -m paddle.distributed.launch --gpus '0,1,2,3' tools/train.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml \ -o Global.pretrained_model=./student \ -Global.save_model_dir=./output/ +Global.save_model_dir=./json/ ``` **Finetune training based on DML distillation method** @@ -245,10 +245,10 @@ paddle.save(s_params, "./teacher.pdparams") python3 tools/train.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_dml.yml \ -o Architecture.Models.Student.pretrained=./teacher \ Architecture.Models.Student2.pretrained=./teacher \ -Global.save_model_dir=./output/ +Global.save_model_dir=./json/ # If you want to use multi-GPU distributed training, please use the following command: python3 -m paddle.distributed.launch --gpus '0,1,2,3' tools/train.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_dml.yml \ -o Architecture.Models.Student.pretrained=./teacher \ Architecture.Models.Student2.pretrained=./teacher \ -Global.save_model_dir=./output/ +Global.save_model_dir=./json/ ``` diff --git a/docs/ppocr/model_train/PPOCRv3_det_train.md b/docs/ppocr/model_train/PPOCRv3_det_train.md index abdff65..85aad05 100644 --- a/docs/ppocr/model_train/PPOCRv3_det_train.md +++ b/docs/ppocr/model_train/PPOCRv3_det_train.md @@ -41,12 +41,12 @@ wget -P ./pretrain_models/ https://paddleocr.bj.bcebos.com/pretrained/ResNet50_v python3 tools/train.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_dml.yml \ -o Architecture.Models.Student.pretrained=./pretrain_models/ResNet50_vd_ssld_pretrained \ Architecture.Models.Student2.pretrained=./pretrain_models/ResNet50_vd_ssld_pretrained \ - Global.save_model_dir=./output/ + Global.save_model_dir=./json/ # 如果要使用多GPU分布式训练,请使用如下命令: python3 -m paddle.distributed.launch --gpus '0,1,2,3' tools/train.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_dml.yml \ -o Architecture.Models.Student.pretrained=./pretrain_models/ResNet50_vd_ssld_pretrained \ Architecture.Models.Student2.pretrained=./pretrain_models/ResNet50_vd_ssld_pretrained \ - Global.save_model_dir=./output/ + Global.save_model_dir=./json/ ``` 训练过程中保存的模型在output目录下,包含以下文件: @@ -65,7 +65,7 @@ latest.pdopt # 默认保存的最新模型的优化器相关参数 模型评估命令如下: ```bash linenums="1" -python3 tools/eval.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_dml.yml -o Global.checkpoints=./output/best_accuracy +python3 tools/eval.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_dml.yml -o Global.checkpoints=./json/best_accuracy ``` 训练的教师模型结构更大,精度更高,用于提升学生模型的精度。 @@ -109,20 +109,20 @@ python3 tools/train.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml \ -o Architecture.Models.Student.pretrained=./pretrain_models/MobileNetV3_large_x0_5_pretrained \ Architecture.Models.Student2.pretrained=./pretrain_models/MobileNetV3_large_x0_5_pretrained \ Architecture.Models.Teacher.pretrained=./pretrain_models/dml_teacher \ - Global.save_model_dir=./output/ + Global.save_model_dir=./json/ # 如果要使用多GPU分布式训练,请使用如下命令: python3 -m paddle.distributed.launch --gpus '0,1,2,3' tools/train.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml \ -o Architecture.Models.Student.pretrained=./pretrain_models/MobileNetV3_large_x0_5_pretrained \ Architecture.Models.Student2.pretrained=./pretrain_models/MobileNetV3_large_x0_5_pretrained \ Architecture.Models.Teacher.pretrained=./pretrain_models/dml_teacher \ - Global.save_model_dir=./output/ + Global.save_model_dir=./json/ ``` 训练过程中保存的模型在output目录下, 模型评估命令如下: ```bash linenums="1" -python3 tools/eval.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml -o Global.checkpoints=./output/best_accuracy +python3 tools/eval.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml -o Global.checkpoints=./json/best_accuracy ``` best_accuracy包含三个模型的参数,分别对应配置文件中的Student,Student2,Teacher。提取Student参数的方法如下: @@ -170,11 +170,11 @@ ch_PP-OCRv3_det_distill_train/best_accuracy.pdparams包含CML配置文件中Stud # 单卡训练 python3 tools/train.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml \ -o Global.pretrained_model=./ch_PP-OCRv3_det_distill_train/best_accuracy \ - Global.save_model_dir=./output/ + Global.save_model_dir=./json/ # 如果要使用多GPU分布式训练,请使用如下命令: python3 -m paddle.distributed.launch --gpus '0,1,2,3' tools/train.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml \ -o Global.pretrained_model=./ch_PP-OCRv3_det_distill_train/best_accuracy \ - Global.save_model_dir=./output/ + Global.save_model_dir=./json/ ``` **基于PP-OCRv3轻量检测模型的finetune训练** @@ -210,11 +210,11 @@ paddle.save(s_params, "./student.pdparams") # 单卡训练 python3 tools/train.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml \ -o Global.pretrained_model=./student \ - Global.save_model_dir=./output/ + Global.save_model_dir=./json/ # 如果要使用多GPU分布式训练,请使用如下命令: python3 -m paddle.distributed.launch --gpus '0,1,2,3' tools/train.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml \ -o Global.pretrained_model=./student \ - Global.save_model_dir=./output/ + Global.save_model_dir=./json/ ``` **基于DML蒸馏方法的finetune训练** @@ -242,10 +242,10 @@ paddle.save(s_params, "./teacher.pdparams") python3 tools/train.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_dml.yml \ -o Architecture.Models.Student.pretrained=./teacher \ Architecture.Models.Student2.pretrained=./teacher \ - Global.save_model_dir=./output/ + Global.save_model_dir=./json/ # 如果要使用多GPU分布式训练,请使用如下命令: python3 -m paddle.distributed.launch --gpus '0,1,2,3' tools/train.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_dml.yml \ -o Architecture.Models.Student.pretrained=./teacher \ Architecture.Models.Student2.pretrained=./teacher \ - Global.save_model_dir=./output/ + Global.save_model_dir=./json/ ``` diff --git a/docs/ppocr/model_train/detection.md b/docs/ppocr/model_train/detection.md index aae8496..57e1c6e 100644 --- a/docs/ppocr/model_train/detection.md +++ b/docs/ppocr/model_train/detection.md @@ -204,7 +204,7 @@ inference 模型(`paddle.jit.save`保存的模型) 检测模型转inference 模型方式: ```bash linenums="1" -# 加载配置文件`det_mv3_db.yml`,从`output/det_db`目录下加载`best_accuracy`模型,inference模型保存在`./output/det_db_inference`目录下 +# 加载配置文件`det_mv3_db.yml`,从`json/det_db`目录下加载`best_accuracy`模型,inference模型保存在`./json/det_db_inference`目录下 python3 tools/export_model.py -c configs/det/det_mv3_db.yml -o Global.pretrained_model="./output/det_db/best_accuracy" Global.save_inference_dir="./output/det_db_inference/" ``` diff --git a/docs/ppocr/model_train/kie.en.md b/docs/ppocr/model_train/kie.en.md index 8b3be83..076e61b 100644 --- a/docs/ppocr/model_train/kie.en.md +++ b/docs/ppocr/model_train/kie.en.md @@ -156,9 +156,9 @@ Take the SER model training as an example. After the training is started, you wi [2022/08/08 16:28:28] ppocr INFO: epoch: [1/200], global_step: 10, lr: 0.000006, loss: 1.871535, avg_reader_cost: 0.28200 s, avg_batch_cost: 0.82318 s, avg_samples: 8.0, ips: 9.71838 samples/s, eta: 0:51:59 [2022/08/08 16:28:33] ppocr INFO: epoch: [1/200], global_step: 19, lr: 0.000018, loss: 1.461939, avg_reader_cost: 0.00042 s, avg_batch_cost: 0.32037 s, avg_samples: 6.9, ips: 21.53773 samples/s, eta: 0:37:55 [2022/08/08 16:28:39] ppocr INFO: cur metric, precision: 0.11526348939743859, recall: 0.19776657060518732, hmean: 0.14564265817747712, fps: 34.008392345050055 -[2022/08/08 16:28:45] ppocr INFO: save best model is to ./output/ser_vi_layoutxlm_xfund_zh/best_accuracy +[2022/08/08 16:28:45] ppocr INFO: save best model is to ./json/ser_vi_layoutxlm_xfund_zh/best_accuracy [2022/08/08 16:28:45] ppocr INFO: best metric, hmean: 0.14564265817747712, precision: 0.11526348939743859, recall: 0.19776657060518732, fps: 34.008392345050055, best_epoch: 1 -[2022/08/08 16:28:51] ppocr INFO: save model in ./output/ser_vi_layoutxlm_xfund_zh/latest +[2022/08/08 16:28:51] ppocr INFO: save model in ./json/ser_vi_layoutxlm_xfund_zh/latest ``` The following information will be automatically printed. @@ -234,7 +234,7 @@ Eval: If the training process is interrupted and you want to load the saved model to resume training, you can specify the path of the model to be loaded by specifying `Architecture.Backbone.checkpoints`. ```bash linenums="1" -python3 tools/train.py -c configs/kie/vi_layoutxlm/ser_vi_layoutxlm_xfund_zh.yml -o Architecture.Backbone.checkpoints=./output/ser_vi_layoutxlm_xfund_zh/best_accuracy +python3 tools/train.py -c configs/kie/vi_layoutxlm/ser_vi_layoutxlm_xfund_zh.yml -o Architecture.Backbone.checkpoints=./json/ser_vi_layoutxlm_xfund_zh/best_accuracy ``` **Note:** @@ -284,7 +284,7 @@ The trained model will be saved in `Global.save_model_dir`. When evaluation, you ```bash linenums="1" # GPU evaluation, Global.checkpoints is the weight to be tested -python3 tools/eval.py -c configs/kie/vi_layoutxlm/ser_vi_layoutxlm_xfund_zh.yml -o Architecture.Backbone.checkpoints=./output/ser_vi_layoutxlm_xfund_zh/best_accuracy +python3 tools/eval.py -c configs/kie/vi_layoutxlm/ser_vi_layoutxlm_xfund_zh.yml -o Architecture.Backbone.checkpoints=./json/ser_vi_layoutxlm_xfund_zh/best_accuracy ``` The following information will be printed such as precision, recall, hmean and so on. @@ -326,7 +326,7 @@ Among them, best_accuracy.*is the best model on the evaluation set; latest.* is The configuration file for prediction must be consistent with the training file. If you finish the training process using `python3 tools/train.py -c configs/kie/vi_layoutxlm/ser_vi_layoutxlm_xfund_zh.yml`. You can use the following command for prediction. ```bash linenums="1" -python3 tools/infer_kie_token_ser.py -c configs/kie/vi_layoutxlm/ser_vi_layoutxlm_xfund_zh.yml -o Architecture.Backbone.checkpoints=./output/ser_vi_layoutxlm_xfund_zh/best_accuracy Global.infer_img=./ppstructure/docs/kie/input/zh_val_42.jpg +python3 tools/infer_kie_token_ser.py -c configs/kie/vi_layoutxlm/ser_vi_layoutxlm_xfund_zh.yml -o Architecture.Backbone.checkpoints=./json/ser_vi_layoutxlm_xfund_zh/best_accuracy Global.infer_img=./ppstructure/docs/kie/input/zh_val_42.jpg ``` The output image is as follows, which is also saved in `Global.save_res_path`. @@ -336,7 +336,7 @@ The output image is as follows, which is also saved in `Global.save_res_path`. During the prediction process, the detection and recognition model of PP-OCRv3 will be loaded by default for information extraction of OCR. If you want to load the OCR results obtained in advance, you can use the following method to predict, and specify `Global.infer_img` as the annotation file, which contains the image path and OCR information, and specifies `Global.infer_mode` as False, indicating that the OCR inference engine is not used at this time. ```bash linenums="1" -python3 tools/infer_kie_token_ser.py -c configs/kie/vi_layoutxlm/ser_vi_layoutxlm_xfund_zh.yml -o Architecture.Backbone.checkpoints=./output/ser_vi_layoutxlm_xfund_zh/best_accuracy Global.infer_img=./train_data/XFUND/zh_val/val.json Global.infer_mode=False +python3 tools/infer_kie_token_ser.py -c configs/kie/vi_layoutxlm/ser_vi_layoutxlm_xfund_zh.yml -o Architecture.Backbone.checkpoints=./json/ser_vi_layoutxlm_xfund_zh/best_accuracy Global.infer_img=./train_data/XFUND/zh_val/val.json Global.infer_mode=False ``` For the above image, if information extraction is performed using the labeled OCR results, the prediction results are as follows. @@ -398,7 +398,7 @@ The SER model can be converted to the inference model using the following comman # -o Set optional parameters. # Architecture.Backbone.checkpoints Set the training model address. # Global.save_inference_dir Set the address where the converted model will be saved. -python3 tools/export_model.py -c configs/kie/vi_layoutxlm/ser_vi_layoutxlm_xfund_zh.yml -o Architecture.Backbone.checkpoints=./output/ser_vi_layoutxlm_xfund_zh/best_accuracy Global.save_inference_dir=./inference/ser_vi_layoutxlm +python3 tools/export_model.py -c configs/kie/vi_layoutxlm/ser_vi_layoutxlm_xfund_zh.yml -o Architecture.Backbone.checkpoints=./json/ser_vi_layoutxlm_xfund_zh/best_accuracy Global.save_inference_dir=./inference/ser_vi_layoutxlm ``` After the conversion is successful, there are three files in the model save directory: @@ -417,7 +417,7 @@ The RE model can be converted to the inference model using the following command # -o Set optional parameters. # Architecture.Backbone.checkpoints Set the training model address. # Global.save_inference_dir Set the address where the converted model will be saved. -python3 tools/export_model.py -c configs/kie/vi_layoutxlm/re_vi_layoutxlm_xfund_zh.yml -o Architecture.Backbone.checkpoints=./output/re_vi_layoutxlm_xfund_zh/best_accuracy Global.save_inference_dir=./inference/re_vi_layoutxlm +python3 tools/export_model.py -c configs/kie/vi_layoutxlm/re_vi_layoutxlm_xfund_zh.yml -o Architecture.Backbone.checkpoints=./json/re_vi_layoutxlm_xfund_zh/best_accuracy Global.save_inference_dir=./inference/re_vi_layoutxlm ``` After the conversion is successful, there are three files in the model save directory: diff --git a/docs/ppocr/model_train/kie.md b/docs/ppocr/model_train/kie.md index 14e3f9a..104584c 100644 --- a/docs/ppocr/model_train/kie.md +++ b/docs/ppocr/model_train/kie.md @@ -154,9 +154,9 @@ python3 tools/train.py -c configs/kie/vi_layoutxlm/re_vi_layoutxlm_xfund_zh.yml [2022/08/08 16:28:28] ppocr INFO: epoch: [1/200], global_step: 10, lr: 0.000006, loss: 1.871535, avg_reader_cost: 0.28200 s, avg_batch_cost: 0.82318 s, avg_samples: 8.0, ips: 9.71838 samples/s, eta: 0:51:59 [2022/08/08 16:28:33] ppocr INFO: epoch: [1/200], global_step: 19, lr: 0.000018, loss: 1.461939, avg_reader_cost: 0.00042 s, avg_batch_cost: 0.32037 s, avg_samples: 6.9, ips: 21.53773 samples/s, eta: 0:37:55 [2022/08/08 16:28:39] ppocr INFO: cur metric, precision: 0.11526348939743859, recall: 0.19776657060518732, hmean: 0.14564265817747712, fps: 34.008392345050055 -[2022/08/08 16:28:45] ppocr INFO: save best model is to ./output/ser_vi_layoutxlm_xfund_zh/best_accuracy +[2022/08/08 16:28:45] ppocr INFO: save best model is to ./json/ser_vi_layoutxlm_xfund_zh/best_accuracy [2022/08/08 16:28:45] ppocr INFO: best metric, hmean: 0.14564265817747712, precision: 0.11526348939743859, recall: 0.19776657060518732, fps: 34.008392345050055, best_epoch: 1 -[2022/08/08 16:28:51] ppocr INFO: save model in ./output/ser_vi_layoutxlm_xfund_zh/latest +[2022/08/08 16:28:51] ppocr INFO: save model in ./json/ser_vi_layoutxlm_xfund_zh/latest ``` log 中自动打印如下信息: @@ -233,7 +233,7 @@ Eval: 如果训练程序中断,如果希望加载训练中断的模型从而恢复训练,可以通过指定`Architecture.Backbone.checkpoints`指定要加载的模型路径: ```bash linenums="1" -python3 tools/train.py -c configs/kie/vi_layoutxlm/ser_vi_layoutxlm_xfund_zh.yml -o Architecture.Backbone.checkpoints=./output/ser_vi_layoutxlm_xfund_zh/best_accuracy +python3 tools/train.py -c configs/kie/vi_layoutxlm/ser_vi_layoutxlm_xfund_zh.yml -o Architecture.Backbone.checkpoints=./json/ser_vi_layoutxlm_xfund_zh/best_accuracy ``` **注意**: @@ -282,7 +282,7 @@ DCU设备上运行需要设置环境变量 `export HIP_VISIBLE_DEVICES=0,1,2,3` ```bash linenums="1" # GPU 评估, Global.checkpoints 为待测权重 -python3 tools/eval.py -c configs/kie/vi_layoutxlm/ser_vi_layoutxlm_xfund_zh.yml -o Architecture.Backbone.checkpoints=./output/ser_vi_layoutxlm_xfund_zh/best_accuracy +python3 tools/eval.py -c configs/kie/vi_layoutxlm/ser_vi_layoutxlm_xfund_zh.yml -o Architecture.Backbone.checkpoints=./json/ser_vi_layoutxlm_xfund_zh/best_accuracy ``` 会输出以下信息,打印出precision、recall、hmean等信息。 @@ -326,7 +326,7 @@ output/ser_vi_layoutxlm_xfund_zh/ 您可以使用如下命令进行中文模型预测。 ```bash linenums="1" -python3 tools/infer_kie_token_ser.py -c configs/kie/vi_layoutxlm/ser_vi_layoutxlm_xfund_zh.yml -o Architecture.Backbone.checkpoints=./output/ser_vi_layoutxlm_xfund_zh/best_accuracy Global.infer_img=./ppstructure/docs/kie/input/zh_val_42.jpg +python3 tools/infer_kie_token_ser.py -c configs/kie/vi_layoutxlm/ser_vi_layoutxlm_xfund_zh.yml -o Architecture.Backbone.checkpoints=./json/ser_vi_layoutxlm_xfund_zh/best_accuracy Global.infer_img=./ppstructure/docs/kie/input/zh_val_42.jpg ``` 预测图片如下所示,图片会存储在`Global.save_res_path`路径中。 @@ -336,7 +336,7 @@ python3 tools/infer_kie_token_ser.py -c configs/kie/vi_layoutxlm/ser_vi_layoutxl 预测过程中,默认会加载PP-OCRv3的检测识别模型,用于OCR的信息抽取,如果希望加载预先获取的OCR结果,可以使用下面的方式进行预测,指定`Global.infer_img`为标注文件,其中包含图片路径以及OCR信息,同时指定`Global.infer_mode`为False,表示此时不使用OCR预测引擎。 ```bash linenums="1" -python3 tools/infer_kie_token_ser.py -c configs/kie/vi_layoutxlm/ser_vi_layoutxlm_xfund_zh.yml -o Architecture.Backbone.checkpoints=./output/ser_vi_layoutxlm_xfund_zh/best_accuracy Global.infer_img=./train_data/XFUND/zh_val/val.json Global.infer_mode=False +python3 tools/infer_kie_token_ser.py -c configs/kie/vi_layoutxlm/ser_vi_layoutxlm_xfund_zh.yml -o Architecture.Backbone.checkpoints=./json/ser_vi_layoutxlm_xfund_zh/best_accuracy Global.infer_img=./train_data/XFUND/zh_val/val.json Global.infer_mode=False ``` 对于上述图片,如果使用标注的OCR结果进行信息抽取,预测结果如下。 @@ -392,7 +392,7 @@ inference 模型(`paddle.jit.save`保存的模型) # Architecture.Backbone.checkpoints 参数设置待转换的训练模型地址 # Global.save_inference_dir 参数设置转换的模型将保存的地址 -python3 tools/export_model.py -c configs/kie/vi_layoutxlm/ser_vi_layoutxlm_xfund_zh.yml -o Architecture.Backbone.checkpoints=./output/ser_vi_layoutxlm_xfund_zh/best_accuracy Global.save_inference_dir=./inference/ser_vi_layoutxlm +python3 tools/export_model.py -c configs/kie/vi_layoutxlm/ser_vi_layoutxlm_xfund_zh.yml -o Architecture.Backbone.checkpoints=./json/ser_vi_layoutxlm_xfund_zh/best_accuracy Global.save_inference_dir=./inference/ser_vi_layoutxlm ``` 转换成功后,在目录下有三个文件: @@ -412,7 +412,7 @@ inference/ser_vi_layoutxlm/ # Architecture.Backbone.checkpoints 参数设置待转换的训练模型地址 # Global.save_inference_dir 参数设置转换的模型将保存的地址 -python3 tools/export_model.py -c configs/kie/vi_layoutxlm/re_vi_layoutxlm_xfund_zh.yml -o Architecture.Backbone.checkpoints=./output/re_vi_layoutxlm_xfund_zh/best_accuracy Global.save_inference_dir=./inference/re_vi_layoutxlm +python3 tools/export_model.py -c configs/kie/vi_layoutxlm/re_vi_layoutxlm_xfund_zh.yml -o Architecture.Backbone.checkpoints=./json/re_vi_layoutxlm_xfund_zh/best_accuracy Global.save_inference_dir=./inference/re_vi_layoutxlm ``` 转换成功后,在目录下有三个文件: diff --git a/docs/ppstructure/blog/return_word_pos.en.md b/docs/ppstructure/blog/return_word_pos.en.md index 7b26541..24a2968 100644 --- a/docs/ppstructure/blog/return_word_pos.en.md +++ b/docs/ppstructure/blog/return_word_pos.en.md @@ -43,7 +43,7 @@ python predict_system.py \ --layout_dict_path=../ppocr/utils/dict/layout_dict/layout_publaynet_dict.txt \ --vis_font_path=../doc/fonts/simfang.ttf \ --recovery=True \ ---output=../output/ \ +--json=../json/ \ --return_word_box=True ``` @@ -91,7 +91,7 @@ python predict_system.py \ --layout_dict_path=../ppocr/utils/dict/layout_dict/layout_cdla_dict.txt \ --vis_font_path=../doc/fonts/chinese_cht.ttf \ --recovery=True \ ---output=../output/ \ +--json=../json/ \ --return_word_box=True ``` diff --git a/docs/ppstructure/blog/return_word_pos.md b/docs/ppstructure/blog/return_word_pos.md index 30c962a..8b8fb79 100644 --- a/docs/ppstructure/blog/return_word_pos.md +++ b/docs/ppstructure/blog/return_word_pos.md @@ -43,7 +43,7 @@ python predict_system.py \ --layout_dict_path=../ppocr/utils/dict/layout_dict/layout_publaynet_dict.txt \ --vis_font_path=../doc/fonts/simfang.ttf \ --recovery=True \ - --output=../output/ \ + --json=../json/ \ --return_word_box=True ``` @@ -91,7 +91,7 @@ python predict_system.py \ --layout_dict_path=../ppocr/utils/dict/layout_dict/layout_cdla_dict.txt \ --vis_font_path=../doc/fonts/chinese_cht.ttf \ --recovery=True \ - --output=../output/ \ + --json=../json/ \ --return_word_box=True ``` diff --git a/docs/ppstructure/infer_deploy/cpp_infer.en.md b/docs/ppstructure/infer_deploy/cpp_infer.en.md index 41e3f2a..30a0a8a 100644 --- a/docs/ppstructure/infer_deploy/cpp_infer.en.md +++ b/docs/ppstructure/infer_deploy/cpp_infer.en.md @@ -378,7 +378,7 @@ predict Crop_img: ../../doc/imgs/12.jpg 1 det boxes: [[23,507],[513,488],[515,529],[24,548]] rec text: 绿洲仕格维花园公寓 rec score: 0.993728 2 det boxes: [[187,456],[399,448],[400,480],[188,488]] rec text: 打浦路15号 rec score: 0.964994 3 det boxes: [[42,413],[483,391],[484,428],[43,450]] rec text: 上海斯格威铂尔大酒店 rec score: 0.980086 -The detection visualized image saved in ./output//12.jpg +The detection visualized image saved in ./json//12.jpg ``` - layout+table @@ -417,9 +417,9 @@ predict Crop_img: ../../ppstructure/docs/table/1.png 0 det boxes: [[6,2],[113,2],[113,14],[6,14]] rec text: 5.Conclusion rec score: 0.856903 ********** end print ocr result ********** 6 type: table, region: [14,360,402,711], score: 0.963643, res:
MethodsExtRPFFPS
TextSnake [18]Syn85.367.975.6
CSE [17]MiLT76.178.777.40.38
LOMO[40]Syn76.585.780.84.4
ATRR[35]Sy-80.280.180.1-
SegLink++ [28]Syn79.882.881.3-
TextField [37]Syn79.883.081.46.0
MSR[38]Syn79.084.181.54.3
PSENet-1s [33]MLT79.784.882.23.9
DB [12]Syn80.286.983.422.0
CRAFT [2]Syn81.186.083.5-
TextDragon [5]MLT+82.884.583.6
PAN [34]Syn81.286.483.739.8
ContourNet [36]84.183.783.94.5
DRRG [41]MLT83.0285.9384.45-
TextPerception[23]Syn81.987.584.6
Ours Syn80.5787.6683.9712.08
Ours81.4587.8184.5112.15
OursMLT83.6086.4585.0012.21
-The table visualized image saved in ./output//6_1.png +The table visualized image saved in ./json//6_1.png 7 type: table, region: [462,359,820,657], score: 0.953917, res:
MethodsRPFFPS
SegLink [26]70.086.077.08.9
PixelLink [4]73.283.077.8-
TextSnake [18]73.983.278.31.1
TextField [37]75.987.481.35.2
MSR[38]76.787.481.7-
FTSN[3]77.187.682.0:
LSE[30]81.784.282.9
CRAFT [2]78.288.282.98.6
MCN [16]798883-
ATRR[35]82.185.283.6-
PAN [34]83.884.484.130.2
DB[12]79.291.584.932.0
DRRG [41]82.3088.0585.08-
Ours (SynText)80.6885.4082.9712.68
Ours (MLT-17)84.5486.6285.5712.31
-The table visualized image saved in ./output//7_1.png +The table visualized image saved in ./json//7_1.png 8 type: figure, region: [14,3,836,310], score: 0.969443, res: count of ocr result is : 26 ********** print ocr result ********** 0 det boxes: [[506,14],[539,15],[539,22],[506,21]] rec text: E rec score: 0.318073 diff --git a/docs/ppstructure/infer_deploy/cpp_infer.md b/docs/ppstructure/infer_deploy/cpp_infer.md index c6867eb..0497cb8 100644 --- a/docs/ppstructure/infer_deploy/cpp_infer.md +++ b/docs/ppstructure/infer_deploy/cpp_infer.md @@ -388,7 +388,7 @@ predict Crop_img: ../../doc/imgs/12.jpg 1 det boxes: [[23,507],[513,488],[515,529],[24,548]] rec text: 绿洲仕格维花园公寓 rec score: 0.993728 2 det boxes: [[187,456],[399,448],[400,480],[188,488]] rec text: 打浦路15号 rec score: 0.964994 3 det boxes: [[42,413],[483,391],[484,428],[43,450]] rec text: 上海斯格威铂尔大酒店 rec score: 0.980086 -The detection visualized image saved in ./output//12.jpg +The detection visualized image saved in ./json//12.jpg ``` - layout+table @@ -427,9 +427,9 @@ predict Crop_img: ../../ppstructure/docs/table/1.png 0 det boxes: [[6,2],[113,2],[113,14],[6,14]] rec text: 5.Conclusion rec score: 0.856903 ********** end print ocr result ********** 6 type: table, region: [14,360,402,711], score: 0.963643, res:
MethodsExtRPFFPS
TextSnake [18]Syn85.367.975.6
CSE [17]MiLT76.178.777.40.38
LOMO[40]Syn76.585.780.84.4
ATRR[35]Sy-80.280.180.1-
SegLink++ [28]Syn79.882.881.3-
TextField [37]Syn79.883.081.46.0
MSR[38]Syn79.084.181.54.3
PSENet-1s [33]MLT79.784.882.23.9
DB [12]Syn80.286.983.422.0
CRAFT [2]Syn81.186.083.5-
TextDragon [5]MLT+82.884.583.6
PAN [34]Syn81.286.483.739.8
ContourNet [36]84.183.783.94.5
DRRG [41]MLT83.0285.9384.45-
TextPerception[23]Syn81.987.584.6
Ours Syn80.5787.6683.9712.08
Ours81.4587.8184.5112.15
OursMLT83.6086.4585.0012.21
-The table visualized image saved in ./output//6_1.png +The table visualized image saved in ./json//6_1.png 7 type: table, region: [462,359,820,657], score: 0.953917, res:
MethodsRPFFPS
SegLink [26]70.086.077.08.9
PixelLink [4]73.283.077.8-
TextSnake [18]73.983.278.31.1
TextField [37]75.987.481.35.2
MSR[38]76.787.481.7-
FTSN[3]77.187.682.0:
LSE[30]81.784.282.9
CRAFT [2]78.288.282.98.6
MCN [16]798883-
ATRR[35]82.185.283.6-
PAN [34]83.884.484.130.2
DB[12]79.291.584.932.0
DRRG [41]82.3088.0585.08-
Ours (SynText)80.6885.4082.9712.68
Ours (MLT-17)84.5486.6285.5712.31
-The table visualized image saved in ./output//7_1.png +The table visualized image saved in ./json//7_1.png 8 type: figure, region: [14,3,836,310], score: 0.969443, res: count of ocr result is : 26 ********** print ocr result ********** 0 det boxes: [[506,14],[539,15],[539,22],[506,21]] rec text: E rec score: 0.318073 diff --git a/docs/ppstructure/infer_deploy/python_infer.en.md b/docs/ppstructure/infer_deploy/python_infer.en.md index d405038..c2a080e 100644 --- a/docs/ppstructure/infer_deploy/python_infer.en.md +++ b/docs/ppstructure/infer_deploy/python_infer.en.md @@ -34,7 +34,7 @@ python3 predict_system.py --det_model_dir=inference/ch_PP-OCRv3_det_infer \ --image_dir=./docs/table/1.png \ --rec_char_dict_path=../ppocr/utils/ppocr_keys_v1.txt \ --table_char_dict_path=../ppocr/utils/dict/table_structure_dict_ch.txt \ - --output=../output \ + --json=../json \ --vis_font_path=../doc/fonts/simfang.ttf ``` @@ -45,7 +45,7 @@ After the operation is completed, each image will have a directory with the same ```bash linenums="1" python3 predict_system.py --layout_model_dir=inference/picodet_lcnet_x1_0_layout_infer \ --image_dir=./docs/table/1.png \ - --output=../output \ + --json=../json \ --table=false \ --ocr=false ``` @@ -61,7 +61,7 @@ python3 predict_system.py --det_model_dir=inference/ch_PP-OCRv3_det_infer \ --image_dir=./docs/table/table.jpg \ --rec_char_dict_path=../ppocr/utils/ppocr_keys_v1.txt \ --table_char_dict_path=../ppocr/utils/dict/table_structure_dict_ch.txt \ - --output=../output \ + --json=../json \ --vis_font_path=../doc/fonts/simfang.ttf \ --layout=false ``` diff --git a/docs/ppstructure/infer_deploy/python_infer.md b/docs/ppstructure/infer_deploy/python_infer.md index 0db9803..b413eb8 100644 --- a/docs/ppstructure/infer_deploy/python_infer.md +++ b/docs/ppstructure/infer_deploy/python_infer.md @@ -37,7 +37,7 @@ python3 predict_system.py --det_model_dir=inference/ch_PP-OCRv3_det_infer \ --image_dir=./docs/table/1.png \ --rec_char_dict_path=../ppocr/utils/ppocr_keys_v1.txt \ --table_char_dict_path=../ppocr/utils/dict/table_structure_dict_ch.txt \ - --output=../output \ + --json=../json \ --vis_font_path=../doc/fonts/simfang.ttf ``` @@ -48,7 +48,7 @@ python3 predict_system.py --det_model_dir=inference/ch_PP-OCRv3_det_infer \ ```bash linenums="1" python3 predict_system.py --layout_model_dir=inference/picodet_lcnet_x1_0_layout_infer \ --image_dir=./docs/table/1.png \ - --output=../output \ + --json=../json \ --table=false \ --ocr=false ``` @@ -64,7 +64,7 @@ python3 predict_system.py --det_model_dir=inference/ch_PP-OCRv3_det_infer \ --image_dir=./docs/table/table.jpg \ --rec_char_dict_path=../ppocr/utils/ppocr_keys_v1.txt \ --table_char_dict_path=../ppocr/utils/dict/table_structure_dict_ch.txt \ - --output=../output \ + --json=../json \ --vis_font_path=../doc/fonts/simfang.ttf \ --layout=false ``` diff --git a/docs/ppstructure/model_train/recovery_to_doc.en.md b/docs/ppstructure/model_train/recovery_to_doc.en.md index 722ee5b..17f22c6 100644 --- a/docs/ppstructure/model_train/recovery_to_doc.en.md +++ b/docs/ppstructure/model_train/recovery_to_doc.en.md @@ -96,7 +96,7 @@ python3 predict_system.py \ --image_dir=ppstructure/docs/recovery/UnrealText.pdf \ --recovery=True \ --use_pdf2docx_api=True \ - --output=../output/ + --json=../json/ ``` ## 4. Quick Start using image format PDF parse @@ -155,7 +155,7 @@ python3 predict_system.py \ --layout_dict_path=../ppocr/utils/dict/layout_dict/layout_publaynet_dict.txt \ --vis_font_path=../doc/fonts/simfang.ttf \ --recovery=True \ - --output=../output/ + --json=../json/ ``` After running, the docx of each picture will be saved in the directory specified by the output field diff --git a/docs/ppstructure/model_train/recovery_to_doc.md b/docs/ppstructure/model_train/recovery_to_doc.md index 09c1643..454fcc1 100644 --- a/docs/ppstructure/model_train/recovery_to_doc.md +++ b/docs/ppstructure/model_train/recovery_to_doc.md @@ -94,7 +94,7 @@ python3 predict_system.py \ --image_dir=ppstructure/docs/recovery/UnrealText.pdf \ --recovery=True \ --use_pdf2docx_api=True \ - --output=../output/ + --json=../json/ ``` ## 4.使用图片格式PDF解析进行版面恢复 @@ -162,7 +162,7 @@ python3 predict_system.py \ --layout_dict_path=../ppocr/utils/dict/layout_dict/layout_publaynet_dict.txt \ --vis_font_path=../doc/fonts/simfang.ttf \ --recovery=True \ - --output=../output/ + --json=../json/ ``` 运行完成后,恢复版面的docx文档会保存到`output`字段指定的目录下 diff --git a/docs/ppstructure/model_train/train_layout.en.md b/docs/ppstructure/model_train/train_layout.en.md index 0af0a5b..1f8460f 100644 --- a/docs/ppstructure/model_train/train_layout.en.md +++ b/docs/ppstructure/model_train/train_layout.en.md @@ -258,7 +258,7 @@ python3 tools/train.py \ # GPU evaluation, weights as weights to be measured python3 tools/eval.py \ -c configs/picodet/legacy_model/application/layout_analysis/picodet_lcnet_x1_0_layout.yml \ - -o weights=./output/picodet_lcnet_x1_0_layout/best_model + -o weights=./json/picodet_lcnet_x1_0_layout/best_model ``` The following information will be printed out, such as mAP, AP0.5, etc. @@ -286,7 +286,7 @@ If you use the provided pre-training model for evaluation or the FGD distillatio python3 tools/eval.py \ -c configs/picodet/legacy_model/application/layout_analysis/picodet_lcnet_x1_0_layout.yml \ --slim_config configs/picodet/legacy_model/application/layout_analysis/picodet_lcnet_x2_5_layout.yml \ - -o weights=output/picodet_lcnet_x2_5_layout/best_model + -o weights=json/picodet_lcnet_x2_5_layout/best_model ``` - `-c`: Specify the model configuration file. @@ -302,7 +302,7 @@ With trained PaddleDetection model, you can use the following commands to make ```bash linenums="1" python3 tools/infer.py \ -c configs/picodet/legacy_model/application/layout_analysis/picodet_lcnet_x1_0_layout.yml \ - -o weights='output/picodet_lcnet_x1_0_layout/best_model.pdparams' \ + -o weights='json/picodet_lcnet_x1_0_layout/best_model.pdparams' \ --infer_img='docs/images/layout.jpg' \ --output_dir=output_dir/ \ --draw_threshold=0.5 @@ -318,7 +318,7 @@ If you use the provided pre-training model for prediction or the FGD distillatio python3 tools/infer.py \ -c configs/picodet/legacy_model/application/layout_analysis/picodet_lcnet_x1_0_layout.yml \ --slim_config configs/picodet/legacy_model/application/layout_analysis/picodet_lcnet_x2_5_layout.yml \ - -o weights='output/picodet_lcnet_x2_5_layout/best_model.pdparams' \ + -o weights='json/picodet_lcnet_x2_5_layout/best_model.pdparams' \ --infer_img='docs/images/layout.jpg' \ --output_dir=output_dir/ \ --draw_threshold=0.5 @@ -339,7 +339,7 @@ Layout analysis model to inference model steps are as follows: ```bash linenums="1" python3 tools/export_model.py \ -c configs/picodet/legacy_model/application/layout_analysis/picodet_lcnet_x1_0_layout.yml \ - -o weights=output/picodet_lcnet_x1_0_layout/best_model \ + -o weights=json/picodet_lcnet_x1_0_layout/best_model \ --output_dir=output_inference/ ``` @@ -361,7 +361,7 @@ If you change the `weights` model path using the provided pre-training model to python3 tools/export_model.py \ -c configs/picodet/legacy_model/application/layout_analysis/picodet_lcnet_x1_0_layout.yml \ --slim_config configs/picodet/legacy_model/application/layout_analysis/picodet_lcnet_x2_5_layout.yml \ - -o weights=./output/picodet_lcnet_x2_5_layout/best_model \ + -o weights=./json/picodet_lcnet_x2_5_layout/best_model \ --output_dir=output_inference/ ``` diff --git a/docs/ppstructure/model_train/train_layout.md b/docs/ppstructure/model_train/train_layout.md index 15207db..779de6c 100644 --- a/docs/ppstructure/model_train/train_layout.md +++ b/docs/ppstructure/model_train/train_layout.md @@ -259,7 +259,7 @@ python3 tools/train.py \ # GPU 评估, weights 为待测权重 python3 tools/eval.py \ -c configs/picodet/legacy_model/application/layout_analysis/picodet_lcnet_x1_0_layout.yml \ - -o weights=./output/picodet_lcnet_x1_0_layout/best_model + -o weights=./json/picodet_lcnet_x1_0_layout/best_model ``` 会输出以下信息,打印出mAP、AP0.5等信息。 @@ -287,7 +287,7 @@ python3 tools/eval.py \ python3 tools/eval.py \ -c configs/picodet/legacy_model/application/layout_analysis/picodet_lcnet_x1_0_layout.yml \ --slim_config configs/picodet/legacy_model/application/layout_analysis/picodet_lcnet_x2_5_layout.yml \ - -o weights=output/picodet_lcnet_x2_5_layout/best_model + -o weights=json/picodet_lcnet_x2_5_layout/best_model ``` - `-c`: 指定模型配置文件。 @@ -303,7 +303,7 @@ python3 tools/eval.py \ ```bash linenums="1" python3 tools/infer.py \ -c configs/picodet/legacy_model/application/layout_analysis/picodet_lcnet_x1_0_layout.yml \ - -o weights='output/picodet_lcnet_x1_0_layout/best_model.pdparams' \ + -o weights='json/picodet_lcnet_x1_0_layout/best_model.pdparams' \ --infer_img='docs/images/layout.jpg' \ --output_dir=output_dir/ \ --draw_threshold=0.5 @@ -319,7 +319,7 @@ python3 tools/infer.py \ python3 tools/infer.py \ -c configs/picodet/legacy_model/application/layout_analysis/picodet_lcnet_x1_0_layout.yml \ --slim_config configs/picodet/legacy_model/application/layout_analysis/picodet_lcnet_x2_5_layout.yml \ - -o weights='output/picodet_lcnet_x2_5_layout/best_model.pdparams' \ + -o weights='json/picodet_lcnet_x2_5_layout/best_model.pdparams' \ --infer_img='docs/images/layout.jpg' \ --output_dir=output_dir/ \ --draw_threshold=0.5 @@ -336,7 +336,7 @@ inference 模型(`paddle.jit.save`保存的模型) 一般是模型训练, ```bash linenums="1" python3 tools/export_model.py \ -c configs/picodet/legacy_model/application/layout_analysis/picodet_lcnet_x1_0_layout.yml \ - -o weights=output/picodet_lcnet_x1_0_layout/best_model \ + -o weights=json/picodet_lcnet_x1_0_layout/best_model \ --output_dir=output_inference/ ``` @@ -358,7 +358,7 @@ output_inference/picodet_lcnet_x1_0_layout/ python3 tools/export_model.py \ -c configs/picodet/legacy_model/application/layout_analysis/picodet_lcnet_x1_0_layout.yml \ --slim_config configs/picodet/legacy_model/application/layout_analysis/picodet_lcnet_x2_5_layout.yml \ - -o weights=./output/picodet_lcnet_x2_5_layout/best_model \ + -o weights=./json/picodet_lcnet_x2_5_layout/best_model \ --output_dir=output_inference/ ``` diff --git a/docs/ppstructure/model_train/train_table.en.md b/docs/ppstructure/model_train/train_table.en.md index 5a75ba2..94508ad 100644 --- a/docs/ppstructure/model_train/train_table.en.md +++ b/docs/ppstructure/model_train/train_table.en.md @@ -75,7 +75,7 @@ python3.7 table/predict_table.py \ --rec_char_dict_path=../ppocr/utils/ppocr_keys_v1.txt \ --table_char_dict_path=../ppocr/utils/dict/table_structure_dict_ch.txt \ --image_dir=docs/table/table.jpg \ - --output=../output/table + --json=../json/table ``` diff --git a/docs/ppstructure/model_train/train_table.md b/docs/ppstructure/model_train/train_table.md index 165e5bb..465190f 100644 --- a/docs/ppstructure/model_train/train_table.md +++ b/docs/ppstructure/model_train/train_table.md @@ -78,7 +78,7 @@ python table/predict_table.py \ --rec_char_dict_path=../ppocr/utils/ppocr_keys_v1.txt \ --table_char_dict_path=../ppocr/utils/dict/table_structure_dict_ch.txt \ --image_dir=docs/table/table.jpg \ - --output=../output/table + --json=../json/table ``` 运行完成后,每张图片的excel表格会保存到output字段指定的目录下,同时在该目录下回生产一个html文件,用于可视化查看单元格坐标和识别的表格。 diff --git a/docs/ppstructure/quick_start.en.md b/docs/ppstructure/quick_start.en.md index cc236c9..ddf342a 100644 --- a/docs/ppstructure/quick_start.en.md +++ b/docs/ppstructure/quick_start.en.md @@ -96,7 +96,7 @@ from paddleocr import PPStructure,draw_structure_result,save_structure_res table_engine = PPStructure(show_log=True, image_orientation=True) -save_folder = './output' +save_folder = './json' img_path = 'ppstructure/docs/table/1.png' img = cv2.imread(img_path) result = table_engine(img) @@ -124,7 +124,7 @@ from paddleocr import PPStructure,draw_structure_result,save_structure_res table_engine = PPStructure(show_log=True) -save_folder = './output' +save_folder = './json' img_path = 'ppstructure/docs/table/1.png' img = cv2.imread(img_path) result = table_engine(img) @@ -152,7 +152,7 @@ from paddleocr import PPStructure,save_structure_res table_engine = PPStructure(table=False, ocr=False, show_log=True) -save_folder = './output' +save_folder = './json' img_path = 'ppstructure/docs/table/1.png' img = cv2.imread(img_path) result = table_engine(img) @@ -170,7 +170,7 @@ from paddleocr import PPStructure,save_structure_res ocr_engine = PPStructure(table=False, ocr=True, show_log=True) -save_folder = './output' +save_folder = './json' img_path = 'ppstructure/docs/recovery/UnrealText.pdf' result = ocr_engine(img_path) for index, res in enumerate(result): @@ -192,7 +192,7 @@ from PIL import Image ocr_engine = PPStructure(table=False, ocr=True, show_log=True) -save_folder = './output' +save_folder = './json' img_path = 'ppstructure/docs/recovery/UnrealText.pdf' fitz = try_import("fitz") @@ -228,7 +228,7 @@ from paddleocr import PPStructure,save_structure_res table_engine = PPStructure(layout=False, show_log=True) -save_folder = './output' +save_folder = './json' img_path = 'ppstructure/docs/table/table.jpg' img = cv2.imread(img_path) result = table_engine(img) @@ -256,7 +256,7 @@ table_engine = PPStructure(recovery=True) # English image # table_engine = PPStructure(recovery=True, lang='en') -save_folder = './output' +save_folder = './json' img_path = 'ppstructure/docs/table/1.png' img = cv2.imread(img_path) result = table_engine(img) diff --git a/docs/ppstructure/quick_start.md b/docs/ppstructure/quick_start.md index 365d87e..dfabc86 100644 --- a/docs/ppstructure/quick_start.md +++ b/docs/ppstructure/quick_start.md @@ -114,7 +114,7 @@ from paddleocr import PPStructure,draw_structure_result,save_structure_res table_engine = PPStructure(show_log=True, image_orientation=True) -save_folder = './output' +save_folder = './json' img_path = 'ppstructure/docs/table/1.png' img = cv2.imread(img_path) result = table_engine(img) @@ -142,7 +142,7 @@ from paddleocr import PPStructure,draw_structure_result,save_structure_res table_engine = PPStructure(show_log=True) -save_folder = './output' +save_folder = './json' img_path = 'ppstructure/docs/table/1.png' img = cv2.imread(img_path) result = table_engine(img) @@ -170,7 +170,7 @@ from paddleocr import PPStructure,save_structure_res table_engine = PPStructure(table=False, ocr=False, show_log=True) -save_folder = './output' +save_folder = './json' img_path = 'ppstructure/docs/table/1.png' img = cv2.imread(img_path) result = table_engine(img) @@ -188,7 +188,7 @@ from paddleocr import PPStructure,save_structure_res ocr_engine = PPStructure(table=False, ocr=True, show_log=True) -save_folder = './output' +save_folder = './json' img_path = 'ppstructure/docs/recovery/UnrealText.pdf' result = ocr_engine(img_path) for index, res in enumerate(result): @@ -210,7 +210,7 @@ from PIL import Image ocr_engine = PPStructure(table=False, ocr=True, show_log=True) -save_folder = './output' +save_folder = './json' img_path = 'ppstructure/docs/recovery/UnrealText.pdf' fitz = try_import("fitz") @@ -246,7 +246,7 @@ from paddleocr import PPStructure,save_structure_res table_engine = PPStructure(layout=False, show_log=True) -save_folder = './output' +save_folder = './json' img_path = 'ppstructure/docs/table/table.jpg' img = cv2.imread(img_path) result = table_engine(img) @@ -274,7 +274,7 @@ table_engine = PPStructure(recovery=True) # 英文测试图 # table_engine = PPStructure(recovery=True, lang='en') -save_folder = './output' +save_folder = './json' img_path = 'ppstructure/docs/table/1.png' img = cv2.imread(img_path) result = table_engine(img) diff --git a/ocr_api.py b/ocr_api.py index 2b8a06e..138dc6b 100644 --- a/ocr_api.py +++ b/ocr_api.py @@ -1,12 +1,18 @@ -from fastapi import FastAPI +# -*- coding: utf-8 -*- + +from fastapi import FastAPI, HTTPException from pydantic import BaseModel -import base64 +from typing import List +import asyncio import subprocess import re -import uuid import os import logging -from typing import List +import boto3 +from botocore.client import Config +from snowflake import SnowflakeGenerator +import requests +import time # 导入 time 模块 app = FastAPI() @@ -15,65 +21,210 @@ logger = logging.getLogger(__name__) ansi_escape = re.compile(r'\x1b[^m]*m') +minio_config = { + "endpoint_url": "http://192.168.10.137:9002", # MinIO endpoint + "aws_access_key_id": "admin", # MinIO accessKey + "aws_secret_access_key": "12345678", # MinIO secretKey +} +bucket_name = "nxfuhsi" # MinIO bucket name + +s3_client = boto3.client("s3", **minio_config) + +gen = SnowflakeGenerator(42) + +# API URL of the large model +model_api_url = "http://112.81.86.50:11434/api/chat" + class PictureRequest(BaseModel): - pic_id: int - pic: str + file_ids: List[str] + suffix: str class PictureResponse(BaseModel): - pic_id: int - pic_txt: str - code: int + file_id: str + draw_img_id: str + ocr_text: str + status: int + error_msg: str = None + + +class TitleRequest(BaseModel): + text: str + + +class TitleResponse(BaseModel): + title: str + status: int + error_msg: str = None + + +def send_request_to_model(text: str) -> TitleResponse: + prompt = """ + 提取下面文本中前40个字中明显的标题: + + ### 注意事项: + 1. 将结果以JSON格式返回。不需要进行解释。 + 2. 如果某字段提取不到,则返回""。 + 3. 文本原文可能为空,返回""。 + 4. 标题只会出现在前40个字中 + 5. 非常明确是标题的文本,才能返回结果。 + 6. 有可能很大概率是没有标题的。 + + 文本原文: + {text} + 输出json格式:{{"title":"*****"}},如果没有明显标题:{{"title":""}}。 + + 回溯你输出的结果,确保你的输出结果符合json格式。 + """ + prompt_t = prompt.format(text=text) + + payload = { + "model": "qwen2:72b", + "messages": [ + {"role": "user", "content": f"{prompt_t}"} + ], + "type": "json_object", + "stream": False + } + + headers = {"Content-Type": "application/json"} + + try: + response = requests.post(model_api_url, json=payload, headers=headers) + response.raise_for_status() + result = response.json() + + json_pattern = re.compile(r'\{"title":\s*"([^"]*)"\}') + content = result.get('message', {}).get('content', '') + if not isinstance(content, str): + raise ValueError("Invalid response content") + + matches = json_pattern.findall(content) + + if len(matches) == 1: + title_value = matches[0] + return TitleResponse(title=title_value, status=0, error_msg="") + else: + return TitleResponse(title="", status=0, error_msg="") + + except requests.exceptions.RequestException as e: + logger.error(f"Failed to request model API: {e}") + return TitleResponse(title="", status=2, error_msg=f"Request failed: {e}") + except ValueError as e: + logger.error(f"Invalid result returned by model API: {e}") + return TitleResponse(title="", status=2, error_msg=f"Invalid result: {e}") + + +async def process_image(file_id: str, suffix: str) -> PictureResponse: + start_time = time.time() # 记录总处理开始时间 + temp_image_file = None + processed_file_name = None + error_msg = "" + try: + logger.info(f"图片后缀: “{suffix}”") + if not suffix: + suffix = "jpg" # 默认后缀为 jpg + logger.info(f"无后缀,更改图片后缀为: {suffix}") + else: + suffix = suffix + + # Step 1: 从 MinIO 获取图片 + step_start_time = time.time() + pic_name = f"{file_id}" + response = s3_client.get_object(Bucket=bucket_name, Key=pic_name) + image_data = response['Body'].read() + logger.info(f"从 MinIO 获取图片时间: {time.time() - step_start_time:.2f} 秒") + + # Step 2: 将图片写入临时文件 + step_start_time = time.time() + temp_image_file = f"{next(gen)}.{suffix}" + with open(temp_image_file, "wb") as f: + f.write(image_data) + logger.info(f"写入临时文件时间: {time.time() - step_start_time:.2f} 秒") + + # Step 3: 调用 OCR 脚本进行识别 + step_start_time = time.time() + command = [ + 'python', 'tools/infer/predict_system_1.py', + '--use_gpu=False', + '--cls_model_dir=./models/cls', + '--rec_model_dir=./models/rec', + '--det_model_dir=./models/det', + f'--image_dir={temp_image_file}' + ] + + logger.info(f"正在处理file_id: {file_id}的图像 ") + process = await asyncio.create_subprocess_exec( + *command, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE + ) + + stdout, stderr = await process.communicate() + + if process.returncode == 0: + ocr_str = ansi_escape.sub('', stdout.decode()).strip() + status = 0 + logger.info(f"对file_id:{file_id}的OCR成功") + logger.info(f"OCR 脚本识别时间: {time.time() - step_start_time:.2f} 秒") + + # Step 4: 将识别结果上传到 MinIO + step_start_time = time.time() + processed_file_id = str(next(gen)) + processed_file_name = processed_file_id # Remove the suffix + result_file_path = f"inference_results/{temp_image_file}" + + with open(result_file_path, "rb") as data: + s3_client.upload_fileobj(data, bucket_name, processed_file_name) + logger.info(f"文件: {processed_file_name} 存储在MinIO中。") + logger.info(f"上传至 MinIO 时间: {time.time() - step_start_time:.2f} 秒") + else: + ocr_str = "" + status = 2 + error_msg = stderr.decode().strip() + logger.error(f"对file_id:{file_id}的OCR失败, return code: {process.returncode}") + + except Exception as e: + ocr_str = "" + status = 2 + error_msg = str(e) + processed_file_id = file_id + logger.exception(f"处理file_id: {file_id}时发生异常") + + finally: + # Step 5: 删除临时文件 + if temp_image_file and os.path.exists(temp_image_file): + os.remove(temp_image_file) + if processed_file_name: + result_file_path = f"inference_results/{temp_image_file}" + if os.path.exists(result_file_path): + os.remove(result_file_path) + logger.info(f"临时文件: {result_file_path} 已被删除") + logger.info(f"删除临时文件时间: {time.time() - step_start_time:.2f} 秒") + + logger.info(f"总处理时间: {time.time() - start_time:.2f} 秒") + return PictureResponse( + file_id=file_id, + draw_img_id=processed_file_id if status == 0 else "", + ocr_text=ocr_str, + status=status, + error_msg=error_msg + ) @app.post("/ocr", response_model=List[PictureResponse]) -async def ocr_endpoint(pictures: List[PictureRequest]): - results = [] - - for picture in pictures: - image_data = base64.b64decode(picture.pic) - temp_image_file = f"{uuid.uuid4()}.jpg" # 使用uuid生成唯一的临时文件名 - - try: - with open(temp_image_file, "wb") as f: - f.write(image_data) - - command = [ - 'python', 'tools/infer/predict_system_1.py', - '--use_gpu=False', - '--cls_model_dir=./models/cls', - '--rec_model_dir=./models/rec', - '--det_model_dir=./models/det', - f'--image_dir={temp_image_file}' - ] - - logger.info(f"Processing image with pic_id: {picture.pic_id}") - result = subprocess.run(command, capture_output=True, text=True, encoding='utf-8', errors='ignore') - - if result.returncode == 0: - ocr_str = ansi_escape.sub('', result.stdout).strip() - code = 200 - logger.info(f"OCR successful for pic_id: {picture.pic_id}") - else: - ocr_str = "" - code = 500 - logger.error(f"OCR failed for pic_id: {picture.pic_id}, return code: {result.returncode}") - - except Exception as e: - ocr_str = str(e) - code = 500 - logger.exception(f"Exception occurred while processing pic_id: {picture.pic_id}") - - finally: - if os.path.exists(temp_image_file): - os.remove(temp_image_file) # 确保临时文件在处理完成后被删除 - - results.append({"pic_id": picture.pic_id, "pic_txt": ocr_str, "code": code}) - +async def ocr_endpoint(picture: PictureRequest): + tasks = [process_image(file_id, picture.suffix) for file_id in picture.file_ids] + results = await asyncio.gather(*tasks) return results +@app.post("/retrieve", response_model=TitleResponse) +def get_title(request: TitleRequest): + return send_request_to_model(request.text) + + if __name__ == "__main__": import uvicorn diff --git a/ppocr/data/imaug/drrg_targets.py b/ppocr/data/imaug/drrg_targets.py index 8eeef26..f99a5f2 100644 --- a/ppocr/data/imaug/drrg_targets.py +++ b/ppocr/data/imaug/drrg_targets.py @@ -712,7 +712,7 @@ class DRRGTargets(object): data (dict): The input result dictionary. Returns: - data (dict): The output result dictionary. + data (dict): The json result dictionary. """ assert isinstance(data, dict) diff --git a/ppocr/data/imaug/fce_targets.py b/ppocr/data/imaug/fce_targets.py index 9955980..b4bbbef 100644 --- a/ppocr/data/imaug/fce_targets.py +++ b/ppocr/data/imaug/fce_targets.py @@ -661,7 +661,7 @@ class FCENetTargets: results (dict): The input result dictionary. Returns: - results (dict): The output result dictionary. + results (dict): The json result dictionary. """ assert isinstance(results, dict) diff --git a/ppocr/data/imaug/label_ops.py b/ppocr/data/imaug/label_ops.py index 7d4afec..0ae37b8 100644 --- a/ppocr/data/imaug/label_ops.py +++ b/ppocr/data/imaug/label_ops.py @@ -143,7 +143,7 @@ class BaseRecLabelEncode(object): input: text: text labels of each image. [batch_size] - output: + json: text: concatenated text index for CTCLoss. [sum(text_lengths)] = [text_index_0 + text_index_1 + ... + text_index_(n - 1)] length: length of each text. [batch_size] diff --git a/ppocr/modeling/backbones/rec_efficientb3_pren.py b/ppocr/modeling/backbones/rec_efficientb3_pren.py index dab4a2a..3e9c43b 100644 --- a/ppocr/modeling/backbones/rec_efficientb3_pren.py +++ b/ppocr/modeling/backbones/rec_efficientb3_pren.py @@ -196,7 +196,7 @@ class MbConvBlock(nn.Layer): self._se_reduce = nn.Conv2D(oup, num_squeezed_channels, 1) self._se_expand = nn.Conv2D(num_squeezed_channels, oup, 1) - # output phase and some util class + # json phase and some util class self.final_oup = self._block_args.output_filters self._project_conv = nn.Conv2D(oup, self.final_oup, 1, bias_attr=False) self._bn2 = nn.BatchNorm(self.final_oup) diff --git a/ppocr/modeling/backbones/rec_resnet_31.py b/ppocr/modeling/backbones/rec_resnet_31.py index c4aa4fc..004a94b 100644 --- a/ppocr/modeling/backbones/rec_resnet_31.py +++ b/ppocr/modeling/backbones/rec_resnet_31.py @@ -104,7 +104,7 @@ class ResNet31(nn.Layer): in_channels (int): Number of channels of input image tensor. layers (list[int]): List of BasicBlock number for each stage. channels (list[int]): List of out_channels of Conv2d layer. - out_indices (None | Sequence[int]): Indices of output stages. + out_indices (None | Sequence[int]): Indices of json stages. last_stage_pool (bool): If True, add `MaxPool2d` layer to last stage. init_type (None | str): the config to control the initialization. """ diff --git a/ppocr/modeling/backbones/rec_resnet_32.py b/ppocr/modeling/backbones/rec_resnet_32.py index 63d78d3..42c20cb 100644 --- a/ppocr/modeling/backbones/rec_resnet_32.py +++ b/ppocr/modeling/backbones/rec_resnet_32.py @@ -39,7 +39,7 @@ class ResNet32(nn.Layer): Args: in_channels (int): input channel - output_channel (int): output channel + output_channel (int): json channel """ super(ResNet32, self).__init__() self.out_channels = out_channels @@ -51,7 +51,7 @@ class ResNet32(nn.Layer): inputs: input feature Returns: - output feature + json feature """ return self.ConvNet(inputs) @@ -131,7 +131,7 @@ class ResNet(nn.Layer): Args: input_channel (int): input channel - output_channel (int): output channel + output_channel (int): json channel block (BasicBlock): convolution block layers (list): layers of the block """ diff --git a/ppocr/modeling/backbones/rec_resnet_fpn.py b/ppocr/modeling/backbones/rec_resnet_fpn.py index d259f1d..cb87e86 100644 --- a/ppocr/modeling/backbones/rec_resnet_fpn.py +++ b/ppocr/modeling/backbones/rec_resnet_fpn.py @@ -196,7 +196,7 @@ class ConvBNLayer(nn.Layer): stride=stride, padding=(kernel_size - 1) // 2, groups=groups, - weight_attr=ParamAttr(name=name + ".conv2d.output.1.w_0"), + weight_attr=ParamAttr(name=name + ".conv2d.json.1.w_0"), bias_attr=False, ) @@ -207,8 +207,8 @@ class ConvBNLayer(nn.Layer): self.bn = nn.BatchNorm( num_channels=out_channels, act=act, - param_attr=ParamAttr(name=name + ".output.1.w_0"), - bias_attr=ParamAttr(name=name + ".output.1.b_0"), + param_attr=ParamAttr(name=name + ".json.1.w_0"), + bias_attr=ParamAttr(name=name + ".json.1.b_0"), moving_mean_name=bn_name + "_mean", moving_variance_name=bn_name + "_variance", ) diff --git a/ppocr/modeling/backbones/rec_resnet_rfl.py b/ppocr/modeling/backbones/rec_resnet_rfl.py index 4742ef8..e3f9cc6 100644 --- a/ppocr/modeling/backbones/rec_resnet_rfl.py +++ b/ppocr/modeling/backbones/rec_resnet_rfl.py @@ -90,7 +90,7 @@ class ResNetRFL(nn.Layer): Args: in_channels (int): input channel - out_channels (int): output channel + out_channels (int): json channel """ super(ResNetRFL, self).__init__() assert use_cnt or use_seq diff --git a/ppocr/modeling/heads/local_graph.py b/ppocr/modeling/heads/local_graph.py index f65c9aa..3166ed8 100644 --- a/ppocr/modeling/heads/local_graph.py +++ b/ppocr/modeling/heads/local_graph.py @@ -74,7 +74,7 @@ def feature_embedding(input_feats, out_feat_len): Args: input_feats (ndarray): The input features of shape (N, d), where N is the number of nodes in graph, d is the input feature vector length. - out_feat_len (int): The length of output feature vector. + out_feat_len (int): The length of json feature vector. Returns: embedded_feats (ndarray): The embedded features. diff --git a/ppocr/modeling/heads/rec_aster_head.py b/ppocr/modeling/heads/rec_aster_head.py index ca4809f..39ea0ba 100644 --- a/ppocr/modeling/heads/rec_aster_head.py +++ b/ppocr/modeling/heads/rec_aster_head.py @@ -81,7 +81,7 @@ class Embedding(nn.Layer): self.mid_dim = mid_dim self.eEmbed = nn.Linear( in_timestep * in_planes, self.embed_dim - ) # Embed encoder output to a word-embedding like + ) # Embed encoder json to a word-embedding like def forward(self, x): x = paddle.reshape(x, [x.shape[0], -1]) @@ -92,13 +92,13 @@ class Embedding(nn.Layer): class AttentionRecognitionHead(nn.Layer): """ input: [b x 16 x 64 x in_planes] - output: probability sequence: [b x T x num_classes] + json: probability sequence: [b x T x num_classes] """ def __init__(self, in_channels, out_channels, sDim, attDim, max_len_labels): super(AttentionRecognitionHead, self).__init__() self.num_classes = ( - out_channels # this is the output classes. So it includes the . + out_channels # this is the json classes. So it includes the . ) self.in_planes = in_channels self.sDim = sDim @@ -241,7 +241,7 @@ class AttentionRecognitionHead(nn.Layer): [self.max_len_labels] * beam_width for _ in range(batch_size) ] # Placeholder for lengths of top-k sequences - # the last step output of the beams are not sorted + # the last step json of the beams are not sorted # thus they are sorted here sorted_score, sorted_idx = paddle.topk( paddle.reshape(stored_scores[-1], shape=[batch_size, beam_width]), diff --git a/ppocr/modeling/heads/rec_nrtr_head.py b/ppocr/modeling/heads/rec_nrtr_head.py index ad01438..4acc8d5 100644 --- a/ppocr/modeling/heads/rec_nrtr_head.py +++ b/ppocr/modeling/heads/rec_nrtr_head.py @@ -146,7 +146,7 @@ class Transformer(nn.Layer): - src: :math:`(B, sN, C)`. - tgt: :math:`(B, tN, C)`. Examples: - >>> output = transformer_model(src, tgt) + >>> json = transformer_model(src, tgt) """ if self.training: @@ -524,9 +524,9 @@ class PositionalEncoding(nn.Layer): x: the sequence fed to the positional encoder model (required). Shape: x: [sequence length, batch size, embed dim] - output: [sequence length, batch size, embed dim] + json: [sequence length, batch size, embed dim] Examples: - >>> output = pos_encoder(x) + >>> json = pos_encoder(x) """ x = x.transpose([1, 0, 2]) x = x + self.pe[: x.shape[0], :] @@ -577,9 +577,9 @@ class PositionalEncoding_2d(nn.Layer): x: the sequence fed to the positional encoder model (required). Shape: x: [sequence length, batch size, embed dim] - output: [sequence length, batch size, embed dim] + json: [sequence length, batch size, embed dim] Examples: - >>> output = pos_encoder(x) + >>> json = pos_encoder(x) """ w_pe = self.pe[: x.shape[-1], :] w1 = self.linear1(self.avg_pool_1(x).squeeze()).unsqueeze(0) diff --git a/ppocr/modeling/heads/rec_robustscanner_head.py b/ppocr/modeling/heads/rec_robustscanner_head.py index d11a78c..7c07048 100644 --- a/ppocr/modeling/heads/rec_robustscanner_head.py +++ b/ppocr/modeling/heads/rec_robustscanner_head.py @@ -62,7 +62,7 @@ class ChannelReductionEncoder(nn.Layer): Args: in_channels (int): Number of input channels. - out_channels (int): Number of output channels. + out_channels (int): Number of json channels. """ def __init__(self, in_channels, out_channels, **kwargs): @@ -130,25 +130,25 @@ class SequenceAttentionDecoder(BaseDecoder): Robust Text Recognition `_ Args: - num_classes (int): Number of output classes :math:`C`. + num_classes (int): Number of json classes :math:`C`. rnn_layers (int): Number of RNN layers. dim_input (int): Dimension :math:`D_i` of input vector ``feat``. dim_model (int): Dimension :math:`D_m` of the model. Should also be the - same as encoder output vector ``out_enc``. - max_seq_len (int): Maximum output sequence length :math:`T`. + same as encoder json vector ``out_enc``. + max_seq_len (int): Maximum json sequence length :math:`T`. start_idx (int): The index of ``. mask (bool): Whether to mask input features according to ``img_meta['valid_ratio']``. padding_idx (int): The index of ``. dropout (float): Dropout rate. return_feature (bool): Return feature or logits as the result. - encode_value (bool): Whether to use the output of encoder ``out_enc`` + encode_value (bool): Whether to use the json of encoder ``out_enc`` as `value` of attention layer. If False, the original feature ``feat`` will be used. Warning: This decoder will not predict the final class which is assumed to be - ``. Therefore, its output size is always :math:`C - 1`. `` + ``. Therefore, its json size is always :math:`C - 1`. `` is also ignored by loss as specified in :obj:`mmocr.models.textrecog.recognizer.EncodeDecodeRecognizer`. """ @@ -203,7 +203,7 @@ class SequenceAttentionDecoder(BaseDecoder): """ Args: feat (Tensor): Tensor of shape :math:`(N, D_i, H, W)`. - out_enc (Tensor): Encoder output of shape + out_enc (Tensor): Encoder json of shape :math:`(N, D_m, H, W)`. targets (Tensor): a tensor of shape :math:`(N, T)`. Each element is the index of a character. @@ -247,12 +247,12 @@ class SequenceAttentionDecoder(BaseDecoder): """ Args: feat (Tensor): Tensor of shape :math:`(N, D_i, H, W)`. - out_enc (Tensor): Encoder output of shape + out_enc (Tensor): Encoder json of shape :math:`(N, D_m, H, W)`. valid_ratios (Tensor): valid length ratio of Crop_img. Returns: - Tensor: The output logit sequence tensor of shape + Tensor: The json logit sequence tensor of shape :math:`(N, T, C-1)`. """ seq_len = self.max_seq_len @@ -282,7 +282,7 @@ class SequenceAttentionDecoder(BaseDecoder): """ Args: feat (Tensor): Tensor of shape :math:`(N, D_i, H, W)`. - out_enc (Tensor): Encoder output of shape + out_enc (Tensor): Encoder json of shape :math:`(N, D_m, H, W)`. decode_sequence (Tensor): Shape :math:`(N, T)`. The tensor that stores history decoding result. @@ -361,22 +361,22 @@ class PositionAttentionDecoder(BaseDecoder): Robust Text Recognition `_ Args: - num_classes (int): Number of output classes :math:`C`. + num_classes (int): Number of json classes :math:`C`. rnn_layers (int): Number of RNN layers. dim_input (int): Dimension :math:`D_i` of input vector ``feat``. dim_model (int): Dimension :math:`D_m` of the model. Should also be the - same as encoder output vector ``out_enc``. - max_seq_len (int): Maximum output sequence length :math:`T`. + same as encoder json vector ``out_enc``. + max_seq_len (int): Maximum json sequence length :math:`T`. mask (bool): Whether to mask input features according to ``img_meta['valid_ratio']``. return_feature (bool): Return feature or logits as the result. - encode_value (bool): Whether to use the output of encoder ``out_enc`` + encode_value (bool): Whether to use the json of encoder ``out_enc`` as `value` of attention layer. If False, the original feature ``feat`` will be used. Warning: This decoder will not predict the final class which is assumed to be - ``. Therefore, its output size is always :math:`C - 1`. `` + ``. Therefore, its json size is always :math:`C - 1`. `` is also ignored by loss """ @@ -427,7 +427,7 @@ class PositionAttentionDecoder(BaseDecoder): """ Args: feat (Tensor): Tensor of shape :math:`(N, D_i, H, W)`. - out_enc (Tensor): Encoder output of shape + out_enc (Tensor): Encoder json of shape :math:`(N, D_m, H, W)`. targets (dict): A dict with the key ``padded_targets``, a tensor of shape :math:`(N, T)`. Each element is the index of a @@ -470,7 +470,7 @@ class PositionAttentionDecoder(BaseDecoder): """ Args: feat (Tensor): Tensor of shape :math:`(N, D_i, H, W)`. - out_enc (Tensor): Encoder output of shape + out_enc (Tensor): Encoder json of shape :math:`(N, D_m, H, W)`. valid_ratios (Tensor): valid length ratio of Crop_img position_index (Tensor): The position of each word. @@ -528,22 +528,22 @@ class RobustScannerDecoder(BaseDecoder): Robust Text Recognition `_ Args: - num_classes (int): Number of output classes :math:`C`. + num_classes (int): Number of json classes :math:`C`. dim_input (int): Dimension :math:`D_i` of input vector ``feat``. dim_model (int): Dimension :math:`D_m` of the model. Should also be the - same as encoder output vector ``out_enc``. - max_seq_len (int): Maximum output sequence length :math:`T`. + same as encoder json vector ``out_enc``. + max_seq_len (int): Maximum json sequence length :math:`T`. start_idx (int): The index of ``. mask (bool): Whether to mask input features according to ``img_meta['valid_ratio']``. padding_idx (int): The index of ``. - encode_value (bool): Whether to use the output of encoder ``out_enc`` + encode_value (bool): Whether to use the json of encoder ``out_enc`` as `value` of attention layer. If False, the original feature ``feat`` will be used. Warning: This decoder will not predict the final class which is assumed to be - ``. Therefore, its output size is always :math:`C - 1`. `` + ``. Therefore, its json size is always :math:`C - 1`. `` is also ignored by loss as specified in :obj:`mmocr.models.textrecog.recognizer.EncodeDecodeRecognizer`. """ @@ -612,7 +612,7 @@ class RobustScannerDecoder(BaseDecoder): """ Args: feat (Tensor): Tensor of shape :math:`(N, D_i, H, W)`. - out_enc (Tensor): Encoder output of shape + out_enc (Tensor): Encoder json of shape :math:`(N, D_m, H, W)`. target (dict): A dict with the key ``padded_targets``, a tensor of shape :math:`(N, T)`. Each element is the index of a @@ -640,12 +640,12 @@ class RobustScannerDecoder(BaseDecoder): """ Args: feat (Tensor): Tensor of shape :math:`(N, D_i, H, W)`. - out_enc (Tensor): Encoder output of shape + out_enc (Tensor): Encoder json of shape :math:`(N, D_m, H, W)`. valid_ratios (Tensor): word_positions (Tensor): The position of each word. Returns: - Tensor: The output logit sequence tensor of shape + Tensor: The json logit sequence tensor of shape :math:`(N, T, C-1)`. """ seq_len = self.max_seq_len diff --git a/ppocr/modeling/heads/rec_visionlan_head.py b/ppocr/modeling/heads/rec_visionlan_head.py index 755856f..524fb2d 100644 --- a/ppocr/modeling/heads/rec_visionlan_head.py +++ b/ppocr/modeling/heads/rec_visionlan_head.py @@ -265,8 +265,8 @@ class Prediction(nn.Layer): self.pp_share = PP_layer( n_dim=n_dim, N_max_character=N_max_character, n_position=n_position ) - self.w_vrm = nn.Linear(n_dim, n_class) # output layer - self.w_share = nn.Linear(n_dim, n_class) # output layer + self.w_vrm = nn.Linear(n_dim, n_class) # json layer + self.w_share = nn.Linear(n_dim, n_class) # json layer self.nclass = n_class def forward(self, cnn_feature, f_res, f_sub, train_mode=False, use_mlm=True): @@ -348,7 +348,7 @@ class MLM_VRM(nn.Layer): x: input image label_pos: character index training_step: LF or LA process - output + json text_pre: prediction of VRM test_rem: prediction of remaining string in MLM text_mas: prediction of occluded character in MLM diff --git a/ppocr/modeling/heads/self_attention.py b/ppocr/modeling/heads/self_attention.py index 4f3ad32..b8c0010 100644 --- a/ppocr/modeling/heads/self_attention.py +++ b/ppocr/modeling/heads/self_attention.py @@ -306,7 +306,7 @@ class MultiHeadAttention(nn.Layer): out = paddle.transpose(out, perm=[0, 2, 1, 3]) out = paddle.reshape(x=out, shape=[0, 0, out.shape[2] * out.shape[3]]) - # project to output + # project to json out = self.proj_fc(out) return out diff --git a/ppocr/modeling/heads/table_att_head.py b/ppocr/modeling/heads/table_att_head.py index 127b7ce..a8aa539 100644 --- a/ppocr/modeling/heads/table_att_head.py +++ b/ppocr/modeling/heads/table_att_head.py @@ -397,7 +397,7 @@ class SLAHead(nn.Layer): @return: """ emb_feature = self.emb(pre_chars) - # output shape is b * self.hidden_size + # json shape is b * self.hidden_size (output, hidden), alpha = self.structure_attention_cell( hidden, features, emb_feature ) diff --git a/ppocr/modeling/necks/csp_pan.py b/ppocr/modeling/necks/csp_pan.py index 5e8464d..065203e 100644 --- a/ppocr/modeling/necks/csp_pan.py +++ b/ppocr/modeling/necks/csp_pan.py @@ -63,7 +63,7 @@ class DPModule(nn.Layer): Depth-wise and point-wise module. Args: in_channel (int): The input channels of this Module. - out_channel (int): The output channels of this Module. + out_channel (int): The json channels of this Module. kernel_size (int): The conv2d kernel size of this Module. stride (int): The conv2d's stride of this Module. act (str): The activation function of this Module, @@ -114,12 +114,12 @@ class DPModule(nn.Layer): class DarknetBottleneck(nn.Layer): """The basic bottleneck block used in Darknet. Each Block consists of two ConvModules and the input is added to the - final output. Each ConvModule is composed of Conv, BN, and act. + final json. Each ConvModule is composed of Conv, BN, and act. The first convLayer has filter size of 1x1 and the second one has the filter size of 3x3. Args: in_channels (int): The input channels of this Module. - out_channels (int): The output channels of this Module. + out_channels (int): The json channels of this Module. expansion (int): The kernel size of the convolution. Default: 0.5 add_identity (bool): Whether to add identity to the out. Default: True @@ -167,7 +167,7 @@ class CSPLayer(nn.Layer): """Cross Stage Partial Layer. Args: in_channels (int): The input channels of the CSP layer. - out_channels (int): The output channels of the CSP layer. + out_channels (int): The json channels of the CSP layer. expand_ratio (float): Ratio to adjust the number of channels of the hidden layer. Default: 0.5 num_blocks (int): Number of blocks. Default: 1 @@ -235,7 +235,7 @@ class CSPPAN(nn.Layer): """Path Aggregation Network with CSP module. Args: in_channels (List[int]): Number of input channels per scale. - out_channels (int): Number of output channels (used at each scale) + out_channels (int): Number of json channels (used at each scale) kernel_size (int): The conv2d kernel size of this Module. num_csp_blocks (int): Number of bottlenecks in CSPLayer. Default: 1 use_depthwise (bool): Whether to depthwise separable convolution in diff --git a/ppocr/modeling/necks/fce_fpn.py b/ppocr/modeling/necks/fce_fpn.py index a456fd1..99405b1 100644 --- a/ppocr/modeling/necks/fce_fpn.py +++ b/ppocr/modeling/necks/fce_fpn.py @@ -93,10 +93,10 @@ class FCEFPN(nn.Layer): Feature Pyramid Network, see https://arxiv.org/abs/1612.03144 Args: in_channels (list[int]): input channels of each level which can be - derived from the output shape of backbone by from_config - out_channels (list[int]): output channel of each level + derived from the json shape of backbone by from_config + out_channels (list[int]): json channel of each level spatial_scales (list[float]): the spatial scales between input feature - maps and original input image which can be derived from the output + maps and original input image which can be derived from the json shape of backbone by from_config has_extra_convs (bool): whether to add extra conv to the last level. default False diff --git a/ppocr/modeling/necks/rf_adaptor.py b/ppocr/modeling/necks/rf_adaptor.py index e27e894..67b9a54 100644 --- a/ppocr/modeling/necks/rf_adaptor.py +++ b/ppocr/modeling/necks/rf_adaptor.py @@ -78,7 +78,7 @@ class V2SAdaptor(nn.Layer): self.in_channels = in_channels self.return_mask = return_mask - # output transformation + # json transformation self.channel_inter = nn.Linear( self.in_channels, self.in_channels, bias_attr=False ) diff --git a/ppocr/modeling/necks/rnn.py b/ppocr/modeling/necks/rnn.py index fa7b8a1..f3c7bcc 100644 --- a/ppocr/modeling/necks/rnn.py +++ b/ppocr/modeling/necks/rnn.py @@ -190,7 +190,7 @@ class EncoderWithSVTR(nn.Layer): ) self.norm = nn.LayerNorm(hidden_dims, epsilon=1e-6) self.conv3 = ConvBNLayer(hidden_dims, in_channels, kernel_size=1, act=nn.Swish) - # last conv-nxn, the input is concat of input tensor and conv3 output tensor + # last conv-nxn, the input is concat of input tensor and conv3 json tensor self.conv4 = ConvBNLayer( 2 * in_channels, in_channels // 8, diff --git a/ppocr/postprocess/fce_postprocess.py b/ppocr/postprocess/fce_postprocess.py index bff9316..a39b308 100644 --- a/ppocr/postprocess/fce_postprocess.py +++ b/ppocr/postprocess/fce_postprocess.py @@ -175,7 +175,7 @@ class FCEPostProcess(object): """Decoding predictions of FCENet to instances. Args: - preds (list(Tensor)): The head output tensors. + preds (list(Tensor)): The head json tensors. fourier_degree (int): The maximum Fourier transform degree k. num_reconstr_points (int): The points number of the polygon reconstructed from predicted Fourier coefficients. diff --git a/ppocr/postprocess/picodet_postprocess.py b/ppocr/postprocess/picodet_postprocess.py index 9189c8e..78c817f 100644 --- a/ppocr/postprocess/picodet_postprocess.py +++ b/ppocr/postprocess/picodet_postprocess.py @@ -239,7 +239,7 @@ class PicoDetPostProcess(object): else: picked_box_probs = np.concatenate(picked_box_probs) - # resize output boxes + # resize json boxes picked_box_probs[:, :4] = self.warp_boxes( picked_box_probs[:, :4], ori_shape[batch_id] ) diff --git a/ppocr/utils/profiler.py b/ppocr/utils/profiler.py index e4e3e05..ba591ba 100644 --- a/ppocr/utils/profiler.py +++ b/ppocr/utils/profiler.py @@ -105,7 +105,7 @@ def add_profiler_step(options_str=None): # profile : https://www.paddlepaddle.org.cn/documentation/docs/zh/guides/performance_improving/profiling_model.html#chakanxingnengshujudetongjibiaodan # timer_only = True only the model's throughput and time overhead are displayed # timer_only = False calling summary can print a statistical form that presents performance data from different perspectives. - # timer_only = False the output Timeline information can be found in the profiler_log directory + # timer_only = False the json Timeline information can be found in the profiler_log directory if _prof is None: _timer_only = str(_profiler_options["timer_only"]) == str(True) _prof = profiler.Profiler( diff --git a/ppstructure/docs/inference.md b/ppstructure/docs/inference.md index a7efd5e..d997229 100644 --- a/ppstructure/docs/inference.md +++ b/ppstructure/docs/inference.md @@ -38,7 +38,7 @@ python3 predict_system.py --det_model_dir=inference/ch_PP-OCRv3_det_infer \ --image_dir=./docs/table/1.png \ --rec_char_dict_path=../ppocr/utils/ppocr_keys_v1.txt \ --table_char_dict_path=../ppocr/utils/dict/table_structure_dict_ch.txt \ - --output=../output \ + --json=../json \ --vis_font_path=../doc/fonts/simfang.ttf ``` 运行完成后,每张图片会在`output`字段指定的目录下的`structure`目录下有一个同名目录,图片里的每个表格会存储为一个excel,图片区域会被裁剪之后保存下来,excel文件和图片名为表格在图片里的坐标。详细的结果会存储在`res.txt`文件中。 @@ -48,7 +48,7 @@ python3 predict_system.py --det_model_dir=inference/ch_PP-OCRv3_det_infer \ ```bash python3 predict_system.py --layout_model_dir=inference/picodet_lcnet_x1_0_layout_infer \ --image_dir=./docs/table/1.png \ - --output=../output \ + --json=../json \ --table=false \ --ocr=false ``` @@ -63,7 +63,7 @@ python3 predict_system.py --det_model_dir=inference/ch_PP-OCRv3_det_infer \ --image_dir=./docs/table/table.jpg \ --rec_char_dict_path=../ppocr/utils/ppocr_keys_v1.txt \ --table_char_dict_path=../ppocr/utils/dict/table_structure_dict_ch.txt \ - --output=../output \ + --json=../json \ --vis_font_path=../doc/fonts/simfang.ttf \ --layout=false ``` diff --git a/ppstructure/docs/inference_en.md b/ppstructure/docs/inference_en.md index 69ca0b2..6f9c56b 100644 --- a/ppstructure/docs/inference_en.md +++ b/ppstructure/docs/inference_en.md @@ -40,7 +40,7 @@ python3 predict_system.py --det_model_dir=inference/ch_PP-OCRv3_det_infer \ --image_dir=./docs/table/1.png \ --rec_char_dict_path=../ppocr/utils/ppocr_keys_v1.txt \ --table_char_dict_path=../ppocr/utils/dict/table_structure_dict_ch.txt \ - --output=../output \ + --json=../json \ --vis_font_path=../doc/fonts/simfang.ttf ``` After the operation is completed, each image will have a directory with the same name in the `structure` directory under the directory specified by the `output` field. Each table in the image will be stored as an excel, and the picture area will be cropped and saved. The filename of excel and picture is their coordinates in the image. Detailed results are stored in the `res.txt` file. @@ -50,7 +50,7 @@ After the operation is completed, each image will have a directory with the same ```bash python3 predict_system.py --layout_model_dir=inference/picodet_lcnet_x1_0_layout_infer \ --image_dir=./docs/table/1.png \ - --output=../output \ + --json=../json \ --table=false \ --ocr=false ``` @@ -65,7 +65,7 @@ python3 predict_system.py --det_model_dir=inference/ch_PP-OCRv3_det_infer \ --image_dir=./docs/table/table.jpg \ --rec_char_dict_path=../ppocr/utils/ppocr_keys_v1.txt \ --table_char_dict_path=../ppocr/utils/dict/table_structure_dict_ch.txt \ - --output=../output \ + --json=../json \ --vis_font_path=../doc/fonts/simfang.ttf \ --layout=false ``` diff --git a/ppstructure/docs/quickstart.md b/ppstructure/docs/quickstart.md index 2a44b2b..b2a91e8 100644 --- a/ppstructure/docs/quickstart.md +++ b/ppstructure/docs/quickstart.md @@ -140,7 +140,7 @@ from paddleocr import PPStructure,draw_structure_result,save_structure_res table_engine = PPStructure(show_log=True, image_orientation=True) -save_folder = './output' +save_folder = './json' img_path = 'ppstructure/docs/table/1.png' img = cv2.imread(img_path) result = table_engine(img) @@ -169,7 +169,7 @@ from paddleocr import PPStructure,draw_structure_result,save_structure_res table_engine = PPStructure(show_log=True) -save_folder = './output' +save_folder = './json' img_path = 'ppstructure/docs/table/1.png' img = cv2.imread(img_path) result = table_engine(img) @@ -198,7 +198,7 @@ from paddleocr import PPStructure,save_structure_res table_engine = PPStructure(table=False, ocr=False, show_log=True) -save_folder = './output' +save_folder = './json' img_path = 'ppstructure/docs/table/1.png' img = cv2.imread(img_path) result = table_engine(img) @@ -216,7 +216,7 @@ from paddleocr import PPStructure,save_structure_res ocr_engine = PPStructure(table=False, ocr=True, show_log=True) -save_folder = './output' +save_folder = './json' img_path = 'ppstructure/docs/recovery/UnrealText.pdf' result = ocr_engine(img_path) for index, res in enumerate(result): @@ -238,7 +238,7 @@ from PIL import Image ocr_engine = PPStructure(table=False, ocr=True, show_log=True) -save_folder = './output' +save_folder = './json' img_path = 'ppstructure/docs/recovery/UnrealText.pdf' fitz = try_import("fitz") @@ -276,7 +276,7 @@ from paddleocr import PPStructure,save_structure_res table_engine = PPStructure(layout=False, show_log=True) -save_folder = './output' +save_folder = './json' img_path = 'ppstructure/docs/table/table.jpg' img = cv2.imread(img_path) result = table_engine(img) @@ -307,7 +307,7 @@ table_engine = PPStructure(recovery=True) # 英文测试图 # table_engine = PPStructure(recovery=True, lang='en') -save_folder = './output' +save_folder = './json' img_path = 'ppstructure/docs/table/1.png' img = cv2.imread(img_path) result = table_engine(img) diff --git a/ppstructure/docs/quickstart_en.md b/ppstructure/docs/quickstart_en.md index a0342f6..70ded32 100644 --- a/ppstructure/docs/quickstart_en.md +++ b/ppstructure/docs/quickstart_en.md @@ -123,7 +123,7 @@ from paddleocr import PPStructure,draw_structure_result,save_structure_res table_engine = PPStructure(show_log=True, image_orientation=True) -save_folder = './output' +save_folder = './json' img_path = 'ppstructure/docs/table/1.png' img = cv2.imread(img_path) result = table_engine(img) @@ -152,7 +152,7 @@ from paddleocr import PPStructure,draw_structure_result,save_structure_res table_engine = PPStructure(show_log=True) -save_folder = './output' +save_folder = './json' img_path = 'ppstructure/docs/table/1.png' img = cv2.imread(img_path) result = table_engine(img) @@ -181,7 +181,7 @@ from paddleocr import PPStructure,save_structure_res table_engine = PPStructure(table=False, ocr=False, show_log=True) -save_folder = './output' +save_folder = './json' img_path = 'ppstructure/docs/table/1.png' img = cv2.imread(img_path) result = table_engine(img) @@ -199,7 +199,7 @@ from paddleocr import PPStructure,save_structure_res ocr_engine = PPStructure(table=False, ocr=True, show_log=True) -save_folder = './output' +save_folder = './json' img_path = 'ppstructure/docs/recovery/UnrealText.pdf' result = ocr_engine(img_path) for index, res in enumerate(result): @@ -221,7 +221,7 @@ from PIL import Image ocr_engine = PPStructure(table=False, ocr=True, show_log=True) -save_folder = './output' +save_folder = './json' img_path = 'ppstructure/docs/recovery/UnrealText.pdf' fitz = try_import("fitz") @@ -258,7 +258,7 @@ from paddleocr import PPStructure,save_structure_res table_engine = PPStructure(layout=False, show_log=True) -save_folder = './output' +save_folder = './json' img_path = 'ppstructure/docs/table/table.jpg' img = cv2.imread(img_path) result = table_engine(img) @@ -288,7 +288,7 @@ table_engine = PPStructure(recovery=True) # English image # table_engine = PPStructure(recovery=True, lang='en') -save_folder = './output' +save_folder = './json' img_path = 'ppstructure/docs/table/1.png' img = cv2.imread(img_path) result = table_engine(img) diff --git a/ppstructure/kie/tools/eval_with_label_end2end.py b/ppstructure/kie/tools/eval_with_label_end2end.py index 749d5f8..0fa62bc 100644 --- a/ppstructure/kie/tools/eval_with_label_end2end.py +++ b/ppstructure/kie/tools/eval_with_label_end2end.py @@ -99,7 +99,7 @@ def ed(args, str1, str2): def convert_bbox_to_polygon(bbox): """ bbox : [x1, y1, x2, y2] - output: [[x1, y1], [x2, y2], [x3, y3], [x4, y4]] + json: [[x1, y1], [x2, y2], [x3, y3], [x4, y4]] """ xmin, ymin, xmax, ymax = bbox poly = [[xmin, ymin], [xmax, ymin], [xmax, ymax], [xmin, ymax]] diff --git a/ppstructure/layout/README.md b/ppstructure/layout/README.md index 6830f8e..596147f 100644 --- a/ppstructure/layout/README.md +++ b/ppstructure/layout/README.md @@ -277,7 +277,7 @@ python3 tools/train.py \ # GPU evaluation, weights as weights to be measured python3 tools/eval.py \ -c configs/picodet/legacy_model/application/layout_analysis/picodet_lcnet_x1_0_layout.yml \ - -o weights=./output/picodet_lcnet_x1_0_layout/best_model + -o weights=./json/picodet_lcnet_x1_0_layout/best_model ``` The following information will be printed out, such as mAP, AP0.5, etc. @@ -322,7 +322,7 @@ With trained PaddleDetection model, you can use the following commands to make ```bash python3 tools/infer.py \ -c configs/picodet/legacy_model/application/layout_analysis/picodet_lcnet_x1_0_layout.yml \ - -o weights='output/picodet_lcnet_x1_0_layout/best_model.pdparams' \ + -o weights='json/picodet_lcnet_x1_0_layout/best_model.pdparams' \ --infer_img='docs/images/layout.jpg' \ --output_dir=output_dir/ \ --draw_threshold=0.5 @@ -361,7 +361,7 @@ Layout analysis model to inference model steps are as follows: ```bash python3 tools/export_model.py \ -c configs/picodet/legacy_model/application/layout_analysis/picodet_lcnet_x1_0_layout.yml \ - -o weights=output/picodet_lcnet_x1_0_layout/best_model \ + -o weights=json/picodet_lcnet_x1_0_layout/best_model \ --output_dir=output_inference/ ``` @@ -383,7 +383,7 @@ If you change the `weights` model path using the provided pre-training model to python3 tools/export_model.py \ -c configs/picodet/legacy_model/application/layout_analysis/picodet_lcnet_x1_0_layout.yml \ --slim_config configs/picodet/legacy_model/application/layout_analysis/picodet_lcnet_x2_5_layout.yml \ - -o weights=./output/picodet_lcnet_x2_5_layout/best_model \ + -o weights=./json/picodet_lcnet_x2_5_layout/best_model \ --output_dir=output_inference/ ``` diff --git a/ppstructure/layout/README_ch.md b/ppstructure/layout/README_ch.md index adef46d..d9e46f9 100644 --- a/ppstructure/layout/README_ch.md +++ b/ppstructure/layout/README_ch.md @@ -278,7 +278,7 @@ python3 tools/train.py \ # GPU 评估, weights 为待测权重 python3 tools/eval.py \ -c configs/picodet/legacy_model/application/layout_analysis/picodet_lcnet_x1_0_layout.yml \ - -o weights=./output/picodet_lcnet_x1_0_layout/best_model + -o weights=./json/picodet_lcnet_x1_0_layout/best_model ``` 会输出以下信息,打印出mAP、AP0.5等信息。 @@ -323,7 +323,7 @@ python3 tools/eval.py \ ```bash python3 tools/infer.py \ -c configs/picodet/legacy_model/application/layout_analysis/picodet_lcnet_x1_0_layout.yml \ - -o weights='output/picodet_lcnet_x1_0_layout/best_model.pdparams' \ + -o weights='json/picodet_lcnet_x1_0_layout/best_model.pdparams' \ --infer_img='docs/images/layout.jpg' \ --output_dir=output_dir/ \ --draw_threshold=0.5 @@ -358,7 +358,7 @@ inference 模型(`paddle.jit.save`保存的模型) 一般是模型训练, ```bash python3 tools/export_model.py \ -c configs/picodet/legacy_model/application/layout_analysis/picodet_lcnet_x1_0_layout.yml \ - -o weights=output/picodet_lcnet_x1_0_layout/best_model \ + -o weights=json/picodet_lcnet_x1_0_layout/best_model \ --output_dir=output_inference/ ``` @@ -380,7 +380,7 @@ output_inference/picodet_lcnet_x1_0_layout/ python3 tools/export_model.py \ -c configs/picodet/legacy_model/application/layout_analysis/picodet_lcnet_x1_0_layout.yml \ --slim_config configs/picodet/legacy_model/application/layout_analysis/picodet_lcnet_x2_5_layout.yml \ - -o weights=./output/picodet_lcnet_x2_5_layout/best_model \ + -o weights=./json/picodet_lcnet_x2_5_layout/best_model \ --output_dir=output_inference/ ``` diff --git a/ppstructure/pdf2word/pdf2word.py b/ppstructure/pdf2word/pdf2word.py index d19c58d..5c66dc7 100644 --- a/ppstructure/pdf2word/pdf2word.py +++ b/ppstructure/pdf2word/pdf2word.py @@ -172,7 +172,7 @@ class Worker(QThread): for index, img in enumerate(imgs): res, time_dict = self.predictors[self.lang](img) - # save output + # save json save_structure_res(res, self.outputDir, img_name) # draw_img = draw_structure_result(Crop_img, res, self.vis_font_path) # img_save_path = os.path.join(self.outputDir, img_name, 'show_{}.jpg'.format(index)) @@ -397,7 +397,7 @@ class APP_Image2Doc(QWidget): args.table_model_dir = os.path.join( root, "inference", "en_ppstructure_mobile_v2.0_SLANet_infer" ) - args.output = os.path.join(root, "output") # 结果保存路径 + args.output = os.path.join(root, "json") # 结果保存路径 args.layout_model_dir = os.path.join( root, "inference", "picodet_lcnet_x1_0_fgd_layout_infer" ) @@ -412,7 +412,7 @@ class APP_Image2Doc(QWidget): args.table_model_dir = os.path.join( root, "inference", "cn_ppstructure_mobile_v2.0_SLANet_infer" ) - args.output = os.path.join(root, "output") # 结果保存路径 + args.output = os.path.join(root, "json") # 结果保存路径 args.layout_model_dir = os.path.join( root, "inference", "picodet_lcnet_x1_0_fgd_layout_cdla_infer" ) @@ -463,7 +463,7 @@ class APP_Image2Doc(QWidget): elif len(self.imagePaths) > 0: # for image file selection # Must set image path list and language before start self.output_dir = os.path.join( - os.path.dirname(self.imagePaths[0]), "output" + os.path.dirname(self.imagePaths[0]), "json" ) # output_dir shold be same as imagepath self._thread.setOutputDir(self.output_dir) self._thread.setImagePath(self.imagePaths) diff --git a/ppstructure/recovery/README.md b/ppstructure/recovery/README.md index 6fa6e6c..a096fc6 100644 --- a/ppstructure/recovery/README.md +++ b/ppstructure/recovery/README.md @@ -120,7 +120,7 @@ python3 predict_system.py \ --image_dir=ppstructure/docs/recovery/UnrealText.pdf \ --recovery=True \ --use_pdf2docx_api=True \ - --output=../output/ + --json=../json/ ``` @@ -182,7 +182,7 @@ python3 predict_system.py \ --layout_dict_path=../ppocr/utils/dict/layout_dict/layout_publaynet_dict.txt \ --vis_font_path=../doc/fonts/simfang.ttf \ --recovery=True \ - --output=../output/ + --json=../json/ ``` After running, the docx of each picture will be saved in the directory specified by the output field diff --git a/ppstructure/recovery/README_ch.md b/ppstructure/recovery/README_ch.md index 63a686d..28d644d 100644 --- a/ppstructure/recovery/README_ch.md +++ b/ppstructure/recovery/README_ch.md @@ -116,7 +116,7 @@ python3 predict_system.py \ --image_dir=ppstructure/docs/recovery/UnrealText.pdf \ --recovery=True \ --use_pdf2docx_api=True \ - --output=../output/ + --json=../json/ ``` @@ -191,7 +191,7 @@ python3 predict_system.py \ --layout_dict_path=../ppocr/utils/dict/layout_dict/layout_publaynet_dict.txt \ --vis_font_path=../doc/fonts/simfang.ttf \ --recovery=True \ - --output=../output/ + --json=../json/ ``` 运行完成后,恢复版面的docx文档会保存到`output`字段指定的目录下 diff --git a/ppstructure/return_word_pos.md b/ppstructure/return_word_pos.md index 5a42d1c..90c8bb3 100644 --- a/ppstructure/return_word_pos.md +++ b/ppstructure/return_word_pos.md @@ -34,7 +34,7 @@ python predict_system.py \ --layout_dict_path=../ppocr/utils/dict/layout_dict/layout_publaynet_dict.txt \ --vis_font_path=../doc/fonts/simfang.ttf \ --recovery=True \ - --output=../output/ \ + --json=../json/ \ --return_word_box=True ``` @@ -77,7 +77,7 @@ python predict_system.py \ --layout_dict_path=../ppocr/utils/dict/layout_dict/layout_cdla_dict.txt \ --vis_font_path=../doc/fonts/chinese_cht.ttf \ --recovery=True \ - --output=../output/ \ + --json=../json/ \ --return_word_box=True ``` diff --git a/ppstructure/table/table_master_match.py b/ppstructure/table/table_master_match.py index 54b4506..1e75c82 100644 --- a/ppstructure/table/table_master_match.py +++ b/ppstructure/table/table_master_match.py @@ -883,7 +883,7 @@ class Matcher: "sorted_bboxes_groups": sorted_bboxes_groups, } - # format output + # format json match_result_dict = self._format(match_result_dict, file_name) match_results[file_name] = match_result_dict @@ -935,7 +935,7 @@ class Matcher: master_token_list.extend(virtual_master_token_list) master_token_list.append("